// 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 NUnit.Framework; using osu.Game.Beatmaps; using osu.Game.Rulesets.Difficulty; using osu.Game.Rulesets.Difficulty.Preprocessing; using osu.Game.Rulesets.Difficulty.Skills; using osu.Game.Rulesets.Mods; namespace osu.Game.Tests.NonVisual { [TestFixture] public class DifficultyAdjustmentModCombinationsTest { [Test] public void TestNoMods() { var combinations = new TestLegacyDifficultyCalculator().CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(1, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); } [Test] public void TestSingleMod() { var combinations = new TestLegacyDifficultyCalculator(new ModA()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(2, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); Assert.IsTrue(combinations[1] is ModA); } [Test] public void TestDoubleMod() { var combinations = new TestLegacyDifficultyCalculator(new ModA(), new ModB()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(4, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); Assert.IsTrue(combinations[1] is ModA); Assert.IsTrue(combinations[2] is MultiMod); Assert.IsTrue(combinations[3] is ModB); Assert.IsTrue(((MultiMod)combinations[2]).Mods[0] is ModA); Assert.IsTrue(((MultiMod)combinations[2]).Mods[1] is ModB); } [Test] public void TestIncompatibleMods() { var combinations = new TestLegacyDifficultyCalculator(new ModA(), new ModIncompatibleWithA()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(3, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); Assert.IsTrue(combinations[1] is ModA); Assert.IsTrue(combinations[2] is ModIncompatibleWithA); } [Test] public void TestDoubleIncompatibleMods() { var combinations = new TestLegacyDifficultyCalculator(new ModA(), new ModB(), new ModIncompatibleWithA(), new ModIncompatibleWithAAndB()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(8, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); Assert.IsTrue(combinations[1] is ModA); Assert.IsTrue(combinations[2] is MultiMod); Assert.IsTrue(combinations[3] is ModB); Assert.IsTrue(combinations[4] is MultiMod); Assert.IsTrue(combinations[5] is ModIncompatibleWithA); Assert.IsTrue(combinations[6] is MultiMod); Assert.IsTrue(combinations[7] is ModIncompatibleWithAAndB); Assert.IsTrue(((MultiMod)combinations[2]).Mods[0] is ModA); Assert.IsTrue(((MultiMod)combinations[2]).Mods[1] is ModB); Assert.IsTrue(((MultiMod)combinations[4]).Mods[0] is ModB); Assert.IsTrue(((MultiMod)combinations[4]).Mods[1] is ModIncompatibleWithA); Assert.IsTrue(((MultiMod)combinations[6]).Mods[0] is ModIncompatibleWithA); Assert.IsTrue(((MultiMod)combinations[6]).Mods[1] is ModIncompatibleWithAAndB); } [Test] public void TestIncompatibleThroughBaseType() { var combinations = new TestLegacyDifficultyCalculator(new ModAofA(), new ModIncompatibleWithAofA()).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(3, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); Assert.IsTrue(combinations[1] is ModAofA); Assert.IsTrue(combinations[2] is ModIncompatibleWithAofA); } [Test] public void TestMultiModFlattening() { var combinations = new TestLegacyDifficultyCalculator(new ModA(), new MultiMod(new ModB(), new ModC())).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(4, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); Assert.IsTrue(combinations[1] is ModA); Assert.IsTrue(combinations[2] is MultiMod); Assert.IsTrue(combinations[3] is MultiMod); Assert.IsTrue(((MultiMod)combinations[2]).Mods[0] is ModA); Assert.IsTrue(((MultiMod)combinations[2]).Mods[1] is ModB); Assert.IsTrue(((MultiMod)combinations[2]).Mods[2] is ModC); Assert.IsTrue(((MultiMod)combinations[3]).Mods[0] is ModB); Assert.IsTrue(((MultiMod)combinations[3]).Mods[1] is ModC); } [Test] public void TestIncompatibleThroughMultiMod() { var combinations = new TestLegacyDifficultyCalculator(new ModA(), new MultiMod(new ModB(), new ModIncompatibleWithA())).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(3, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); Assert.IsTrue(combinations[1] is ModA); Assert.IsTrue(combinations[2] is MultiMod); Assert.IsTrue(((MultiMod)combinations[2]).Mods[0] is ModB); Assert.IsTrue(((MultiMod)combinations[2]).Mods[1] is ModIncompatibleWithA); } [Test] public void TestIncompatibleWithSameInstanceViaMultiMod() { var combinations = new TestLegacyDifficultyCalculator(new ModA(), new MultiMod(new ModA(), new ModB())).CreateDifficultyAdjustmentModCombinations(); Assert.AreEqual(3, combinations.Length); Assert.IsTrue(combinations[0] is ModNoMod); Assert.IsTrue(combinations[1] is ModA); Assert.IsTrue(combinations[2] is MultiMod); Assert.IsTrue(((MultiMod)combinations[2]).Mods[0] is ModA); Assert.IsTrue(((MultiMod)combinations[2]).Mods[1] is ModB); } private class ModA : Mod { public override string Name => nameof(ModA); public override string Acronym => nameof(ModA); public override string Description => string.Empty; public override double ScoreMultiplier => 1; public override Type[] IncompatibleMods => new[] { typeof(ModIncompatibleWithA), typeof(ModIncompatibleWithAAndB) }; } private class ModB : Mod { public override string Name => nameof(ModB); public override string Description => string.Empty; public override string Acronym => nameof(ModB); public override double ScoreMultiplier => 1; public override Type[] IncompatibleMods => new[] { typeof(ModIncompatibleWithAAndB) }; } private class ModC : Mod { public override string Name => nameof(ModC); public override string Acronym => nameof(ModC); public override string Description => string.Empty; public override double ScoreMultiplier => 1; } private class ModIncompatibleWithA : Mod { public override string Name => $"Incompatible With {nameof(ModA)}"; public override string Acronym => $"Incompatible With {nameof(ModA)}"; public override string Description => string.Empty; public override double ScoreMultiplier => 1; public override Type[] IncompatibleMods => new[] { typeof(ModA) }; } private class ModAofA : ModA { } private class ModIncompatibleWithAofA : ModIncompatibleWithA { // Incompatible through base type } private class ModIncompatibleWithAAndB : Mod { public override string Name => $"Incompatible With {nameof(ModA)} and {nameof(ModB)}"; public override string Acronym => $"Incompatible With {nameof(ModA)} and {nameof(ModB)}"; public override string Description => string.Empty; public override double ScoreMultiplier => 1; public override Type[] IncompatibleMods => new[] { typeof(ModA), typeof(ModB) }; } private class TestLegacyDifficultyCalculator : DifficultyCalculator { public TestLegacyDifficultyCalculator(params Mod[] mods) : base(null, null) { DifficultyAdjustmentMods = mods; } protected override Mod[] DifficultyAdjustmentMods { get; } protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate) { throw new NotImplementedException(); } protected override IEnumerable CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate) { throw new NotImplementedException(); } protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate) { throw new NotImplementedException(); } } } }