// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using System.Collections.Generic; using System.Linq; using JetBrains.Annotations; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; using osu.Game.Scoring; using osu.Game.Screens.Play; namespace osu.Game.Tests.Visual { public abstract class ModTestScene : PlayerTestScene { protected sealed override bool HasCustomSteps => true; public override IReadOnlyList RequiredTypes => new[] { typeof(ModTestScene) }; protected ModTestScene(Ruleset ruleset) : base(ruleset) { } private ModTestCaseData currentTest; protected void CreateModTest(ModTestCaseData testCaseData) => CreateTest(() => { AddStep("set test data", () => currentTest = testCaseData); }); public override void TearDownSteps() { AddUntilStep("test passed", () => { if (currentTest == null) return true; return currentTest.PassCondition?.Invoke() ?? false; }); base.TearDownSteps(); } protected sealed override IBeatmap CreateBeatmap(RulesetInfo ruleset) => currentTest?.Beatmap ?? base.CreateBeatmap(ruleset); protected sealed override Player CreatePlayer(Ruleset ruleset) { SelectedMods.Value = SelectedMods.Value.Append(currentTest.Mod).ToArray(); var score = currentTest.Autoplay ? ruleset.GetAutoplayMod().CreateReplayScore(Beatmap.Value.GetPlayableBeatmap(ruleset.RulesetInfo, SelectedMods.Value)) : null; return CreateReplayPlayer(score, AllowFail); } /// /// Creates the for a test case. /// /// The . /// Whether the player can fail. protected virtual TestPlayer CreateReplayPlayer(Score score, bool allowFail) => new TestPlayer(score, allowFail); protected class TestPlayer : TestReplayPlayer { protected override bool AllowFail { get; } public TestPlayer(Score score, bool allowFail) : base(score, false, false) { AllowFail = allowFail; } } protected class ModTestCaseData { /// /// Whether to use a replay to simulate an auto-play. True by default. /// public bool Autoplay = true; /// /// The beatmap for this test case. /// [CanBeNull] public IBeatmap Beatmap; /// /// The conditions that cause this test case to pass. /// [CanBeNull] public Func PassCondition; /// /// The this test case tests. /// public readonly Mod Mod; public ModTestCaseData(Mod mod) { Mod = mod; } } } }