2019-01-24 16:43:03 +08:00
|
|
|
|
// 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.
|
2018-06-06 15:20:17 +08:00
|
|
|
|
|
2022-06-17 15:37:17 +08:00
|
|
|
|
#nullable disable
|
|
|
|
|
|
2018-06-06 15:20:17 +08:00
|
|
|
|
using System;
|
2019-02-21 12:12:37 +08:00
|
|
|
|
using System.Collections.Generic;
|
2021-11-30 10:11:42 +08:00
|
|
|
|
using System.Linq;
|
2018-06-06 15:20:17 +08:00
|
|
|
|
using NUnit.Framework;
|
2018-06-14 15:04:48 +08:00
|
|
|
|
using osu.Game.Beatmaps;
|
2018-06-06 15:20:17 +08:00
|
|
|
|
using osu.Game.Rulesets.Difficulty;
|
2019-02-21 12:12:37 +08:00
|
|
|
|
using osu.Game.Rulesets.Difficulty.Preprocessing;
|
|
|
|
|
using osu.Game.Rulesets.Difficulty.Skills;
|
2018-06-06 15:20:17 +08:00
|
|
|
|
using osu.Game.Rulesets.Mods;
|
2021-11-30 10:11:42 +08:00
|
|
|
|
using osu.Game.Utils;
|
2018-06-06 15:20:17 +08:00
|
|
|
|
|
|
|
|
|
namespace osu.Game.Tests.NonVisual
|
|
|
|
|
{
|
|
|
|
|
[TestFixture]
|
|
|
|
|
public class DifficultyAdjustmentModCombinationsTest
|
|
|
|
|
{
|
|
|
|
|
[Test]
|
|
|
|
|
public void TestNoMods()
|
|
|
|
|
{
|
2019-02-12 15:01:25 +08:00
|
|
|
|
var combinations = new TestLegacyDifficultyCalculator().CreateDifficultyAdjustmentModCombinations();
|
2018-06-06 15:20:17 +08:00
|
|
|
|
|
2021-11-30 10:11:42 +08:00
|
|
|
|
assertCombinations(new[]
|
|
|
|
|
{
|
|
|
|
|
new[] { typeof(ModNoMod) }
|
|
|
|
|
}, combinations);
|
2018-06-06 15:20:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void TestSingleMod()
|
|
|
|
|
{
|
2019-02-12 15:01:25 +08:00
|
|
|
|
var combinations = new TestLegacyDifficultyCalculator(new ModA()).CreateDifficultyAdjustmentModCombinations();
|
2018-06-06 15:20:17 +08:00
|
|
|
|
|
2021-11-30 10:11:42 +08:00
|
|
|
|
assertCombinations(new[]
|
|
|
|
|
{
|
|
|
|
|
new[] { typeof(ModNoMod) },
|
|
|
|
|
new[] { typeof(ModA) }
|
|
|
|
|
}, combinations);
|
2018-06-06 15:20:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void TestDoubleMod()
|
|
|
|
|
{
|
2019-02-12 15:01:25 +08:00
|
|
|
|
var combinations = new TestLegacyDifficultyCalculator(new ModA(), new ModB()).CreateDifficultyAdjustmentModCombinations();
|
2018-06-06 15:20:17 +08:00
|
|
|
|
|
2021-11-30 10:11:42 +08:00
|
|
|
|
assertCombinations(new[]
|
|
|
|
|
{
|
|
|
|
|
new[] { typeof(ModNoMod) },
|
|
|
|
|
new[] { typeof(ModA) },
|
|
|
|
|
new[] { typeof(ModA), typeof(ModB) },
|
|
|
|
|
new[] { typeof(ModB) }
|
|
|
|
|
}, combinations);
|
2018-06-06 15:20:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void TestIncompatibleMods()
|
|
|
|
|
{
|
2019-02-12 15:01:25 +08:00
|
|
|
|
var combinations = new TestLegacyDifficultyCalculator(new ModA(), new ModIncompatibleWithA()).CreateDifficultyAdjustmentModCombinations();
|
2018-06-06 15:20:17 +08:00
|
|
|
|
|
2021-11-30 10:11:42 +08:00
|
|
|
|
assertCombinations(new[]
|
|
|
|
|
{
|
|
|
|
|
new[] { typeof(ModNoMod) },
|
|
|
|
|
new[] { typeof(ModA) },
|
|
|
|
|
new[] { typeof(ModIncompatibleWithA) }
|
|
|
|
|
}, combinations);
|
2018-06-06 15:20:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void TestDoubleIncompatibleMods()
|
|
|
|
|
{
|
2019-02-12 15:01:25 +08:00
|
|
|
|
var combinations = new TestLegacyDifficultyCalculator(new ModA(), new ModB(), new ModIncompatibleWithA(), new ModIncompatibleWithAAndB()).CreateDifficultyAdjustmentModCombinations();
|
2018-06-06 15:20:17 +08:00
|
|
|
|
|
2021-11-30 10:11:42 +08:00
|
|
|
|
assertCombinations(new[]
|
|
|
|
|
{
|
|
|
|
|
new[] { typeof(ModNoMod) },
|
|
|
|
|
new[] { typeof(ModA) },
|
|
|
|
|
new[] { typeof(ModA), typeof(ModB) },
|
|
|
|
|
new[] { typeof(ModB) },
|
|
|
|
|
new[] { typeof(ModB), typeof(ModIncompatibleWithA) },
|
|
|
|
|
new[] { typeof(ModIncompatibleWithA) },
|
|
|
|
|
new[] { typeof(ModIncompatibleWithA), typeof(ModIncompatibleWithAAndB) },
|
|
|
|
|
new[] { typeof(ModIncompatibleWithAAndB) },
|
|
|
|
|
}, combinations);
|
2018-06-06 15:20:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
|
|
|
|
public void TestIncompatibleThroughBaseType()
|
|
|
|
|
{
|
2019-02-12 15:01:25 +08:00
|
|
|
|
var combinations = new TestLegacyDifficultyCalculator(new ModAofA(), new ModIncompatibleWithAofA()).CreateDifficultyAdjustmentModCombinations();
|
2018-06-06 15:20:17 +08:00
|
|
|
|
|
2021-11-30 10:11:42 +08:00
|
|
|
|
assertCombinations(new[]
|
|
|
|
|
{
|
|
|
|
|
new[] { typeof(ModNoMod) },
|
|
|
|
|
new[] { typeof(ModAofA) },
|
|
|
|
|
new[] { typeof(ModIncompatibleWithAofA) }
|
|
|
|
|
}, combinations);
|
2018-06-06 15:20:17 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-14 18:03:11 +08:00
|
|
|
|
[Test]
|
2020-10-14 18:18:04 +08:00
|
|
|
|
public void TestMultiModFlattening()
|
2020-10-14 18:03:11 +08:00
|
|
|
|
{
|
|
|
|
|
var combinations = new TestLegacyDifficultyCalculator(new ModA(), new MultiMod(new ModB(), new ModC())).CreateDifficultyAdjustmentModCombinations();
|
|
|
|
|
|
2021-11-30 10:11:42 +08:00
|
|
|
|
assertCombinations(new[]
|
|
|
|
|
{
|
|
|
|
|
new[] { typeof(ModNoMod) },
|
|
|
|
|
new[] { typeof(ModA) },
|
|
|
|
|
new[] { typeof(ModA), typeof(ModB), typeof(ModC) },
|
|
|
|
|
new[] { typeof(ModB), typeof(ModC) }
|
|
|
|
|
}, combinations);
|
2020-10-14 18:03:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[Test]
|
2020-10-14 18:18:04 +08:00
|
|
|
|
public void TestIncompatibleThroughMultiMod()
|
2020-10-14 18:03:11 +08:00
|
|
|
|
{
|
|
|
|
|
var combinations = new TestLegacyDifficultyCalculator(new ModA(), new MultiMod(new ModB(), new ModIncompatibleWithA())).CreateDifficultyAdjustmentModCombinations();
|
|
|
|
|
|
2021-11-30 10:11:42 +08:00
|
|
|
|
assertCombinations(new[]
|
|
|
|
|
{
|
|
|
|
|
new[] { typeof(ModNoMod) },
|
|
|
|
|
new[] { typeof(ModA) },
|
|
|
|
|
new[] { typeof(ModB), typeof(ModIncompatibleWithA) }
|
|
|
|
|
}, combinations);
|
2020-10-14 18:03:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
2020-10-14 18:53:37 +08:00
|
|
|
|
[Test]
|
|
|
|
|
public void TestIncompatibleWithSameInstanceViaMultiMod()
|
|
|
|
|
{
|
|
|
|
|
var combinations = new TestLegacyDifficultyCalculator(new ModA(), new MultiMod(new ModA(), new ModB())).CreateDifficultyAdjustmentModCombinations();
|
|
|
|
|
|
2021-11-30 10:11:42 +08:00
|
|
|
|
assertCombinations(new[]
|
|
|
|
|
{
|
|
|
|
|
new[] { typeof(ModNoMod) },
|
|
|
|
|
new[] { typeof(ModA) },
|
|
|
|
|
new[] { typeof(ModA), typeof(ModB) }
|
|
|
|
|
}, combinations);
|
|
|
|
|
}
|
2020-10-14 18:53:37 +08:00
|
|
|
|
|
2021-11-30 10:11:42 +08:00
|
|
|
|
private void assertCombinations(Type[][] expectedCombinations, Mod[] actualCombinations)
|
|
|
|
|
{
|
|
|
|
|
Assert.AreEqual(expectedCombinations.Length, actualCombinations.Length);
|
|
|
|
|
|
2021-12-01 10:29:02 +08:00
|
|
|
|
Assert.Multiple(() =>
|
2021-11-30 10:11:42 +08:00
|
|
|
|
{
|
2021-12-01 10:29:02 +08:00
|
|
|
|
for (int i = 0; i < expectedCombinations.Length; ++i)
|
2021-11-30 10:11:42 +08:00
|
|
|
|
{
|
2021-12-01 10:29:02 +08:00
|
|
|
|
Type[] expectedTypes = expectedCombinations[i];
|
|
|
|
|
Type[] actualTypes = ModUtils.FlattenMod(actualCombinations[i]).Select(m => m.GetType()).ToArray();
|
|
|
|
|
|
|
|
|
|
Assert.That(expectedTypes, Is.EquivalentTo(actualTypes));
|
|
|
|
|
}
|
|
|
|
|
});
|
2020-10-14 18:53:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
2018-06-06 15:20:17 +08:00
|
|
|
|
private class ModA : Mod
|
|
|
|
|
{
|
|
|
|
|
public override string Name => nameof(ModA);
|
2018-11-30 16:16:00 +08:00
|
|
|
|
public override string Acronym => nameof(ModA);
|
2021-04-15 13:32:01 +08:00
|
|
|
|
public override string Description => string.Empty;
|
2018-06-06 15:20:17 +08:00
|
|
|
|
public override double ScoreMultiplier => 1;
|
|
|
|
|
|
|
|
|
|
public override Type[] IncompatibleMods => new[] { typeof(ModIncompatibleWithA), typeof(ModIncompatibleWithAAndB) };
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private class ModB : Mod
|
|
|
|
|
{
|
|
|
|
|
public override string Name => nameof(ModB);
|
2021-04-15 13:32:01 +08:00
|
|
|
|
public override string Description => string.Empty;
|
2018-11-30 16:16:00 +08:00
|
|
|
|
public override string Acronym => nameof(ModB);
|
2018-06-06 15:20:17 +08:00
|
|
|
|
public override double ScoreMultiplier => 1;
|
|
|
|
|
|
|
|
|
|
public override Type[] IncompatibleMods => new[] { typeof(ModIncompatibleWithAAndB) };
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-14 18:03:11 +08:00
|
|
|
|
private class ModC : Mod
|
|
|
|
|
{
|
|
|
|
|
public override string Name => nameof(ModC);
|
|
|
|
|
public override string Acronym => nameof(ModC);
|
2021-04-15 13:32:01 +08:00
|
|
|
|
public override string Description => string.Empty;
|
2020-10-14 18:03:11 +08:00
|
|
|
|
public override double ScoreMultiplier => 1;
|
|
|
|
|
}
|
|
|
|
|
|
2018-06-06 15:20:17 +08:00
|
|
|
|
private class ModIncompatibleWithA : Mod
|
|
|
|
|
{
|
|
|
|
|
public override string Name => $"Incompatible With {nameof(ModA)}";
|
2018-11-30 16:16:00 +08:00
|
|
|
|
public override string Acronym => $"Incompatible With {nameof(ModA)}";
|
2021-04-15 13:32:01 +08:00
|
|
|
|
public override string Description => string.Empty;
|
2018-06-06 15:20:17 +08:00
|
|
|
|
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)}";
|
2018-11-30 16:16:00 +08:00
|
|
|
|
public override string Acronym => $"Incompatible With {nameof(ModA)} and {nameof(ModB)}";
|
2021-04-15 13:32:01 +08:00
|
|
|
|
public override string Description => string.Empty;
|
2018-06-06 15:20:17 +08:00
|
|
|
|
public override double ScoreMultiplier => 1;
|
|
|
|
|
|
|
|
|
|
public override Type[] IncompatibleMods => new[] { typeof(ModA), typeof(ModB) };
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-21 12:12:37 +08:00
|
|
|
|
private class TestLegacyDifficultyCalculator : DifficultyCalculator
|
2018-06-06 15:20:17 +08:00
|
|
|
|
{
|
2019-02-12 15:01:25 +08:00
|
|
|
|
public TestLegacyDifficultyCalculator(params Mod[] mods)
|
2018-06-14 15:04:48 +08:00
|
|
|
|
: base(null, null)
|
2018-06-06 15:20:17 +08:00
|
|
|
|
{
|
|
|
|
|
DifficultyAdjustmentMods = mods;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override Mod[] DifficultyAdjustmentMods { get; }
|
2018-06-14 15:04:48 +08:00
|
|
|
|
|
2019-02-21 12:12:37 +08:00
|
|
|
|
protected override DifficultyAttributes CreateDifficultyAttributes(IBeatmap beatmap, Mod[] mods, Skill[] skills, double clockRate)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected override IEnumerable<DifficultyHitObject> CreateDifficultyHitObjects(IBeatmap beatmap, double clockRate)
|
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
|
|
|
|
|
2021-06-03 14:09:37 +08:00
|
|
|
|
protected override Skill[] CreateSkills(IBeatmap beatmap, Mod[] mods, double clockRate)
|
2019-02-21 12:12:37 +08:00
|
|
|
|
{
|
|
|
|
|
throw new NotImplementedException();
|
|
|
|
|
}
|
2018-06-06 15:20:17 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|