mirror of
https://github.com/ppy/osu.git
synced 2026-05-22 06:29:54 +08:00
f676206331
Previously, random selection would always be done at a *set* level. The final operation of a random action would be "select the user's recommended difficulty from this randomly selected set". This makes no sense when sets are not grouped together at song select. In fact, it is completely broken with the previous commit which adds group-isolated random support – if we're grouping by difficulty and the user's recommendation is not in the current group it would throw the user into another group unexpectedly. This fixes the issue by splitting out the random implementation into two separate pathways depending on the carousel display mode.
293 lines
9.4 KiB
C#
293 lines
9.4 KiB
C#
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
// See the LICENCE file in the repository root for full licence text.
|
|
|
|
using System.Linq;
|
|
using NUnit.Framework;
|
|
using osu.Framework.Testing;
|
|
using osu.Game.Beatmaps;
|
|
using osu.Game.Screens.Select.Filter;
|
|
using osu.Game.Screens.SelectV2;
|
|
|
|
namespace osu.Game.Tests.Visual.SongSelectV2
|
|
{
|
|
[TestFixture]
|
|
public partial class TestSceneBeatmapCarouselRandom : BeatmapCarouselTestScene
|
|
{
|
|
[SetUpSteps]
|
|
public void SetUpSteps()
|
|
{
|
|
RemoveAllBeatmaps();
|
|
CreateCarousel();
|
|
}
|
|
|
|
[Test]
|
|
public void TestRandomObeysFiltering()
|
|
{
|
|
AddBeatmaps(2, 10, true);
|
|
|
|
ApplyToFilterAndWaitForFilter("filter", c => c.SearchText = BeatmapSets[0].Beatmaps.Last().DifficultyName);
|
|
|
|
CheckDisplayedBeatmapSetsCount(1);
|
|
CheckDisplayedBeatmapsCount(1);
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
{
|
|
nextRandom();
|
|
WaitForSetSelection(0, 9);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Test random non-repeating algorithm
|
|
/// </summary>
|
|
[Test]
|
|
public void TestRandomArtistGrouping()
|
|
{
|
|
SortAndGroupBy(SortMode.Artist, GroupMode.Artist);
|
|
|
|
AddBeatmaps(10, 3, true);
|
|
WaitForDrawablePanels();
|
|
|
|
GroupDefinition? expanded = null;
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
nextRandom();
|
|
expanded ??= storeExpandedGroup();
|
|
|
|
ensureSetRandomDidNotRepeat();
|
|
checkExpandedGroupUnchanged();
|
|
}
|
|
|
|
nextRandom();
|
|
ensureSetRandomDidRepeat();
|
|
checkExpandedGroupUnchanged();
|
|
|
|
prevRandomSet();
|
|
checkRewindCorrectSet();
|
|
checkExpandedGroupUnchanged();
|
|
prevRandomSet();
|
|
checkRewindCorrectSet();
|
|
checkExpandedGroupUnchanged();
|
|
|
|
nextRandom();
|
|
ensureSetRandomDidNotRepeat();
|
|
checkExpandedGroupUnchanged();
|
|
nextRandom();
|
|
ensureSetRandomDidRepeat();
|
|
checkExpandedGroupUnchanged();
|
|
|
|
GroupDefinition? storeExpandedGroup()
|
|
{
|
|
AddStep("store open group", () => expanded = Carousel.ExpandedGroup);
|
|
return null;
|
|
}
|
|
|
|
void checkExpandedGroupUnchanged() => AddAssert("expanded did not change", () => Carousel.ExpandedGroup, () => Is.EqualTo(expanded));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Test random non-repeating algorithm
|
|
/// </summary>
|
|
[Test]
|
|
public void TestRandomDifficultyGroupingRewindsCorrectly()
|
|
{
|
|
SortAndGroupBy(SortMode.Difficulty, GroupMode.Difficulty);
|
|
|
|
AddBeatmaps(3, 3, true);
|
|
WaitForDrawablePanels();
|
|
|
|
GroupDefinition? expanded = null;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
nextRandom();
|
|
expanded ??= storeExpandedGroup();
|
|
|
|
ensureRandomDidNotRepeat();
|
|
checkExpandedGroupUnchanged();
|
|
}
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
prevRandom();
|
|
checkRewindCorrect();
|
|
checkExpandedGroupUnchanged();
|
|
}
|
|
|
|
for (int i = 0; i < 2; i++)
|
|
{
|
|
nextRandom();
|
|
ensureRandomDidNotRepeat();
|
|
checkExpandedGroupUnchanged();
|
|
}
|
|
|
|
nextRandom();
|
|
ensureRandomDidRepeat();
|
|
checkExpandedGroupUnchanged();
|
|
|
|
GroupDefinition? storeExpandedGroup()
|
|
{
|
|
AddStep("store open group", () => expanded = Carousel.ExpandedGroup);
|
|
return null;
|
|
}
|
|
|
|
void checkExpandedGroupUnchanged() => AddAssert("expanded did not change", () => Carousel.ExpandedGroup, () => Is.EqualTo(expanded));
|
|
}
|
|
|
|
/// <summary>
|
|
/// Test random non-repeating algorithm
|
|
/// </summary>
|
|
[Test]
|
|
public void TestRandomDifficultyGroupingRepeatsWhenExhausted()
|
|
{
|
|
SortAndGroupBy(SortMode.Difficulty, GroupMode.Difficulty);
|
|
|
|
AddBeatmaps(3, 3, true);
|
|
WaitForDrawablePanels();
|
|
|
|
GroupDefinition? expanded = null;
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
nextRandom();
|
|
expanded ??= storeExpandedGroup();
|
|
|
|
ensureRandomDidNotRepeat();
|
|
checkExpandedGroupUnchanged();
|
|
}
|
|
|
|
for (int i = 0; i < 3; i++)
|
|
{
|
|
nextRandom();
|
|
ensureRandomDidRepeat();
|
|
}
|
|
|
|
for (int i = 0; i < 5; i++)
|
|
{
|
|
prevRandom();
|
|
checkRewindCorrect();
|
|
checkExpandedGroupUnchanged();
|
|
}
|
|
|
|
nextRandom();
|
|
checkExpandedGroupUnchanged();
|
|
// can't assert repeat or otherwise as we went through multiple permutations.
|
|
|
|
GroupDefinition? storeExpandedGroup()
|
|
{
|
|
AddStep("store open group", () => expanded = Carousel.ExpandedGroup);
|
|
return null;
|
|
}
|
|
|
|
void checkExpandedGroupUnchanged() => AddAssert("expanded did not change", () => Carousel.ExpandedGroup, () => Is.EqualTo(expanded));
|
|
}
|
|
|
|
[Test]
|
|
public void TestRewindOverMultipleIterations()
|
|
{
|
|
const int local_set_count = 3;
|
|
const int random_select_count = local_set_count * 3;
|
|
|
|
AddBeatmaps(local_set_count, 3, true);
|
|
WaitForDrawablePanels();
|
|
|
|
SelectNextSet();
|
|
|
|
for (int i = 0; i < random_select_count; i++)
|
|
nextRandom();
|
|
|
|
for (int i = 0; i < random_select_count; i++)
|
|
{
|
|
prevRandomSet();
|
|
checkRewindCorrectSet();
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestRandomThenRewindSameFrame()
|
|
{
|
|
AddBeatmaps(10, 3, true);
|
|
WaitForDrawablePanels();
|
|
|
|
BeatmapInfo? originalSelected = null;
|
|
|
|
nextRandom();
|
|
|
|
CheckHasSelection();
|
|
AddStep("store selection", () => originalSelected = (BeatmapInfo)Carousel.CurrentSelection!);
|
|
|
|
AddStep("random then rewind", () =>
|
|
{
|
|
Carousel.NextRandom();
|
|
Carousel.PreviousRandom();
|
|
});
|
|
|
|
AddAssert("selection not changed", () => Carousel.CurrentSelection, () => Is.EqualTo(originalSelected));
|
|
}
|
|
|
|
[Test]
|
|
public void TestRewindToDeletedBeatmap()
|
|
{
|
|
AddBeatmaps(10, 3, true);
|
|
WaitForDrawablePanels();
|
|
|
|
BeatmapInfo? originalSelected = null;
|
|
BeatmapInfo? postRandomSelection = null;
|
|
|
|
nextRandom();
|
|
|
|
CheckHasSelection();
|
|
AddStep("store selection", () => originalSelected = (BeatmapInfo)Carousel.CurrentSelection!);
|
|
|
|
nextRandom();
|
|
AddStep("store selection", () => postRandomSelection = (BeatmapInfo)Carousel.CurrentSelection!);
|
|
|
|
AddAssert("selection changed", () => originalSelected, () => Is.Not.SameAs(postRandomSelection));
|
|
|
|
AddStep("delete previous selection beatmaps", () => BeatmapSets.Remove(originalSelected!.BeatmapSet!));
|
|
WaitForFiltering();
|
|
|
|
AddAssert("selection not changed", () => Carousel.CurrentSelection, () => Is.EqualTo(postRandomSelection));
|
|
|
|
prevRandomSet();
|
|
AddAssert("selection not changed", () => Carousel.CurrentSelection, () => Is.EqualTo(postRandomSelection));
|
|
}
|
|
|
|
private void nextRandom() =>
|
|
AddStep("select random next", () => Carousel.NextRandom());
|
|
|
|
private void ensureRandomDidRepeat() =>
|
|
AddAssert("did repeat", () => BeatmapRequestedSelections.Distinct().Count(), () => Is.LessThan(BeatmapRequestedSelections.Count));
|
|
|
|
private void ensureRandomDidNotRepeat() =>
|
|
AddAssert("no repeats", () => BeatmapRequestedSelections.Distinct().Count(), () => Is.EqualTo(BeatmapRequestedSelections.Count));
|
|
|
|
private void ensureSetRandomDidRepeat() =>
|
|
AddAssert("did repeat", () => BeatmapSetRequestedSelections.Distinct().Count(), () => Is.LessThan(BeatmapSetRequestedSelections.Count));
|
|
|
|
private void ensureSetRandomDidNotRepeat() =>
|
|
AddAssert("no repeats", () => BeatmapSetRequestedSelections.Distinct().Count(), () => Is.EqualTo(BeatmapSetRequestedSelections.Count));
|
|
|
|
private void checkRewindCorrect() =>
|
|
AddAssert("rewind matched expected beatmap", () => BeatmapRequestedSelections.Peek(), () => Is.EqualTo(Carousel.SelectedBeatmapInfo));
|
|
|
|
private void checkRewindCorrectSet() =>
|
|
AddAssert("rewind matched expected set", () => BeatmapSetRequestedSelections.Peek(), () => Is.EqualTo(Carousel.SelectedBeatmapSet));
|
|
|
|
private void prevRandom() => AddStep("select last random", () =>
|
|
{
|
|
Carousel.PreviousRandom();
|
|
BeatmapRequestedSelections.Pop();
|
|
// Pop twice because the PreviousRandom call also requests selection.
|
|
BeatmapRequestedSelections.Pop();
|
|
});
|
|
|
|
private void prevRandomSet() => AddStep("select last random set", () =>
|
|
{
|
|
Carousel.PreviousRandom();
|
|
BeatmapSetRequestedSelections.Pop();
|
|
});
|
|
}
|
|
}
|