mirror of
https://github.com/ppy/osu.git
synced 2024-12-17 04:32:53 +08:00
Merge branch 'master' into adjust-profile-scores
This commit is contained in:
commit
2a463e2893
175
osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs
Normal file
175
osu.Game.Tests/Visual/SongSelect/TestSceneAdvancedStats.cs
Normal file
@ -0,0 +1,175 @@
|
|||||||
|
// 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;
|
||||||
|
using System.Linq;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using osu.Framework.Allocation;
|
||||||
|
using osu.Framework.Graphics.Sprites;
|
||||||
|
using osu.Framework.Testing;
|
||||||
|
using osu.Game.Beatmaps;
|
||||||
|
using osu.Game.Graphics;
|
||||||
|
using osu.Game.Rulesets;
|
||||||
|
using osu.Game.Rulesets.Mods;
|
||||||
|
using osu.Game.Screens.Select.Details;
|
||||||
|
using osuTK.Graphics;
|
||||||
|
|
||||||
|
namespace osu.Game.Tests.Visual.SongSelect
|
||||||
|
{
|
||||||
|
[System.ComponentModel.Description("Advanced beatmap statistics display")]
|
||||||
|
public class TestSceneAdvancedStats : OsuTestScene
|
||||||
|
{
|
||||||
|
private TestAdvancedStats advancedStats;
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private RulesetStore rulesets { get; set; }
|
||||||
|
|
||||||
|
[Resolved]
|
||||||
|
private OsuColour colours { get; set; }
|
||||||
|
|
||||||
|
[SetUp]
|
||||||
|
public void Setup() => Schedule(() => Child = advancedStats = new TestAdvancedStats
|
||||||
|
{
|
||||||
|
Width = 500
|
||||||
|
});
|
||||||
|
|
||||||
|
private BeatmapInfo exampleBeatmapInfo => new BeatmapInfo
|
||||||
|
{
|
||||||
|
RulesetID = 0,
|
||||||
|
Ruleset = rulesets.AvailableRulesets.First(),
|
||||||
|
BaseDifficulty = new BeatmapDifficulty
|
||||||
|
{
|
||||||
|
CircleSize = 7.2f,
|
||||||
|
DrainRate = 3,
|
||||||
|
OverallDifficulty = 5.7f,
|
||||||
|
ApproachRate = 3.5f
|
||||||
|
},
|
||||||
|
StarDifficulty = 4.5f
|
||||||
|
};
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestNoMod()
|
||||||
|
{
|
||||||
|
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
|
||||||
|
|
||||||
|
AddStep("no mods selected", () => SelectedMods.Value = Array.Empty<Mod>());
|
||||||
|
|
||||||
|
AddAssert("first bar text is Circle Size", () => advancedStats.ChildrenOfType<SpriteText>().First().Text == "Circle Size");
|
||||||
|
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.FirstValue));
|
||||||
|
AddAssert("HP drain bar is white", () => barIsWhite(advancedStats.HpDrain));
|
||||||
|
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.Accuracy));
|
||||||
|
AddAssert("approach rate bar is white", () => barIsWhite(advancedStats.ApproachRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestManiaFirstBarText()
|
||||||
|
{
|
||||||
|
AddStep("set beatmap", () => advancedStats.Beatmap = new BeatmapInfo
|
||||||
|
{
|
||||||
|
Ruleset = rulesets.GetRuleset(3),
|
||||||
|
BaseDifficulty = new BeatmapDifficulty
|
||||||
|
{
|
||||||
|
CircleSize = 5,
|
||||||
|
DrainRate = 4.3f,
|
||||||
|
OverallDifficulty = 4.5f,
|
||||||
|
ApproachRate = 3.1f
|
||||||
|
},
|
||||||
|
StarDifficulty = 8
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("first bar text is Key Count", () => advancedStats.ChildrenOfType<SpriteText>().First().Text == "Key Count");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestEasyMod()
|
||||||
|
{
|
||||||
|
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
|
||||||
|
|
||||||
|
AddStep("select EZ mod", () =>
|
||||||
|
{
|
||||||
|
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
|
||||||
|
SelectedMods.Value = new[] { ruleset.GetAllMods().OfType<ModEasy>().Single() };
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("circle size bar is blue", () => barIsBlue(advancedStats.FirstValue));
|
||||||
|
AddAssert("HP drain bar is blue", () => barIsBlue(advancedStats.HpDrain));
|
||||||
|
AddAssert("accuracy bar is blue", () => barIsBlue(advancedStats.Accuracy));
|
||||||
|
AddAssert("approach rate bar is blue", () => barIsBlue(advancedStats.ApproachRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestHardRockMod()
|
||||||
|
{
|
||||||
|
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
|
||||||
|
|
||||||
|
AddStep("select HR mod", () =>
|
||||||
|
{
|
||||||
|
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
|
||||||
|
SelectedMods.Value = new[] { ruleset.GetAllMods().OfType<ModHardRock>().Single() };
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("circle size bar is red", () => barIsRed(advancedStats.FirstValue));
|
||||||
|
AddAssert("HP drain bar is red", () => barIsRed(advancedStats.HpDrain));
|
||||||
|
AddAssert("accuracy bar is red", () => barIsRed(advancedStats.Accuracy));
|
||||||
|
AddAssert("approach rate bar is red", () => barIsRed(advancedStats.ApproachRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestUnchangedDifficultyAdjustMod()
|
||||||
|
{
|
||||||
|
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
|
||||||
|
|
||||||
|
AddStep("select unchanged Difficulty Adjust mod", () =>
|
||||||
|
{
|
||||||
|
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
|
||||||
|
var difficultyAdjustMod = ruleset.GetAllMods().OfType<ModDifficultyAdjust>().Single();
|
||||||
|
difficultyAdjustMod.ReadFromDifficulty(advancedStats.Beatmap.BaseDifficulty);
|
||||||
|
SelectedMods.Value = new[] { difficultyAdjustMod };
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.FirstValue));
|
||||||
|
AddAssert("HP drain bar is white", () => barIsWhite(advancedStats.HpDrain));
|
||||||
|
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.Accuracy));
|
||||||
|
AddAssert("approach rate bar is white", () => barIsWhite(advancedStats.ApproachRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestChangedDifficultyAdjustMod()
|
||||||
|
{
|
||||||
|
AddStep("set beatmap", () => advancedStats.Beatmap = exampleBeatmapInfo);
|
||||||
|
|
||||||
|
AddStep("select changed Difficulty Adjust mod", () =>
|
||||||
|
{
|
||||||
|
var ruleset = advancedStats.Beatmap.Ruleset.CreateInstance();
|
||||||
|
var difficultyAdjustMod = ruleset.GetAllMods().OfType<ModDifficultyAdjust>().Single();
|
||||||
|
var originalDifficulty = advancedStats.Beatmap.BaseDifficulty;
|
||||||
|
var adjustedDifficulty = new BeatmapDifficulty
|
||||||
|
{
|
||||||
|
CircleSize = originalDifficulty.CircleSize,
|
||||||
|
DrainRate = originalDifficulty.DrainRate - 0.5f,
|
||||||
|
OverallDifficulty = originalDifficulty.OverallDifficulty,
|
||||||
|
ApproachRate = originalDifficulty.ApproachRate + 2.2f,
|
||||||
|
};
|
||||||
|
difficultyAdjustMod.ReadFromDifficulty(adjustedDifficulty);
|
||||||
|
SelectedMods.Value = new[] { difficultyAdjustMod };
|
||||||
|
});
|
||||||
|
|
||||||
|
AddAssert("circle size bar is white", () => barIsWhite(advancedStats.FirstValue));
|
||||||
|
AddAssert("drain rate bar is blue", () => barIsBlue(advancedStats.HpDrain));
|
||||||
|
AddAssert("accuracy bar is white", () => barIsWhite(advancedStats.Accuracy));
|
||||||
|
AddAssert("approach rate bar is red", () => barIsRed(advancedStats.ApproachRate));
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool barIsWhite(AdvancedStats.StatisticRow row) => row.ModBar.AccentColour == Color4.White;
|
||||||
|
private bool barIsBlue(AdvancedStats.StatisticRow row) => row.ModBar.AccentColour == colours.BlueDark;
|
||||||
|
private bool barIsRed(AdvancedStats.StatisticRow row) => row.ModBar.AccentColour == colours.Red;
|
||||||
|
|
||||||
|
private class TestAdvancedStats : AdvancedStats
|
||||||
|
{
|
||||||
|
public new StatisticRow FirstValue => base.FirstValue;
|
||||||
|
public new StatisticRow HpDrain => base.HpDrain;
|
||||||
|
public new StatisticRow Accuracy => base.Accuracy;
|
||||||
|
public new StatisticRow ApproachRate => base.ApproachRate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,14 +3,8 @@
|
|||||||
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using osu.Framework.Allocation;
|
|
||||||
using osu.Framework.Graphics;
|
using osu.Framework.Graphics;
|
||||||
using osu.Framework.Testing;
|
|
||||||
using osu.Game.Beatmaps;
|
using osu.Game.Beatmaps;
|
||||||
using osu.Game.Graphics;
|
|
||||||
using osu.Game.Graphics.UserInterface;
|
|
||||||
using osu.Game.Rulesets;
|
|
||||||
using osu.Game.Rulesets.Mods;
|
|
||||||
using osu.Game.Screens.Select;
|
using osu.Game.Screens.Select;
|
||||||
|
|
||||||
namespace osu.Game.Tests.Visual.SongSelect
|
namespace osu.Game.Tests.Visual.SongSelect
|
||||||
@ -180,27 +174,5 @@ namespace osu.Game.Tests.Visual.SongSelect
|
|||||||
OnlineBeatmapID = 162,
|
OnlineBeatmapID = 162,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private RulesetStore rulesets { get; set; }
|
|
||||||
|
|
||||||
[Resolved]
|
|
||||||
private OsuColour colours { get; set; }
|
|
||||||
|
|
||||||
[Test]
|
|
||||||
public void TestModAdjustments()
|
|
||||||
{
|
|
||||||
TestAllMetrics();
|
|
||||||
|
|
||||||
Ruleset ruleset = rulesets.AvailableRulesets.First().CreateInstance();
|
|
||||||
|
|
||||||
AddStep("with EZ mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModEasy) });
|
|
||||||
|
|
||||||
AddAssert("first bar coloured blue", () => details.ChildrenOfType<Bar>().Skip(1).First().AccentColour == colours.BlueDark);
|
|
||||||
|
|
||||||
AddStep("with HR mod", () => SelectedMods.Value = new[] { ruleset.GetAllMods().First(m => m is ModHardRock) });
|
|
||||||
|
|
||||||
AddAssert("first bar coloured red", () => details.ChildrenOfType<Bar>().Skip(1).First().AccentColour == colours.Red);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,7 @@ using System.Collections.Generic;
|
|||||||
using osu.Game.Rulesets.Mods;
|
using osu.Game.Rulesets.Mods;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using osu.Framework.Threading;
|
using osu.Framework.Threading;
|
||||||
|
using osu.Framework.Utils;
|
||||||
using osu.Game.Configuration;
|
using osu.Game.Configuration;
|
||||||
using osu.Game.Overlays.Settings;
|
using osu.Game.Overlays.Settings;
|
||||||
|
|
||||||
@ -26,7 +27,8 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
[Resolved]
|
[Resolved]
|
||||||
private IBindable<IReadOnlyList<Mod>> mods { get; set; }
|
private IBindable<IReadOnlyList<Mod>> mods { get; set; }
|
||||||
|
|
||||||
private readonly StatisticRow firstValue, hpDrain, accuracy, approachRate, starDifficulty;
|
protected readonly StatisticRow FirstValue, HpDrain, Accuracy, ApproachRate;
|
||||||
|
private readonly StatisticRow starDifficulty;
|
||||||
|
|
||||||
private BeatmapInfo beatmap;
|
private BeatmapInfo beatmap;
|
||||||
|
|
||||||
@ -52,10 +54,10 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
Spacing = new Vector2(4f),
|
Spacing = new Vector2(4f),
|
||||||
Children = new[]
|
Children = new[]
|
||||||
{
|
{
|
||||||
firstValue = new StatisticRow(), //circle size/key amount
|
FirstValue = new StatisticRow(), //circle size/key amount
|
||||||
hpDrain = new StatisticRow { Title = "HP Drain" },
|
HpDrain = new StatisticRow { Title = "HP Drain" },
|
||||||
accuracy = new StatisticRow { Title = "Accuracy" },
|
Accuracy = new StatisticRow { Title = "Accuracy" },
|
||||||
approachRate = new StatisticRow { Title = "Approach Rate" },
|
ApproachRate = new StatisticRow { Title = "Approach Rate" },
|
||||||
starDifficulty = new StatisticRow(10, true) { Title = "Star Difficulty" },
|
starDifficulty = new StatisticRow(10, true) { Title = "Star Difficulty" },
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@ -122,24 +124,24 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
case 3:
|
case 3:
|
||||||
// Account for mania differences locally for now
|
// Account for mania differences locally for now
|
||||||
// Eventually this should be handled in a more modular way, allowing rulesets to return arbitrary difficulty attributes
|
// Eventually this should be handled in a more modular way, allowing rulesets to return arbitrary difficulty attributes
|
||||||
firstValue.Title = "Key Count";
|
FirstValue.Title = "Key Count";
|
||||||
firstValue.Value = (baseDifficulty?.CircleSize ?? 0, null);
|
FirstValue.Value = (baseDifficulty?.CircleSize ?? 0, null);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
firstValue.Title = "Circle Size";
|
FirstValue.Title = "Circle Size";
|
||||||
firstValue.Value = (baseDifficulty?.CircleSize ?? 0, adjustedDifficulty?.CircleSize);
|
FirstValue.Value = (baseDifficulty?.CircleSize ?? 0, adjustedDifficulty?.CircleSize);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
starDifficulty.Value = ((float)(Beatmap?.StarDifficulty ?? 0), null);
|
starDifficulty.Value = ((float)(Beatmap?.StarDifficulty ?? 0), null);
|
||||||
|
|
||||||
hpDrain.Value = (baseDifficulty?.DrainRate ?? 0, adjustedDifficulty?.DrainRate);
|
HpDrain.Value = (baseDifficulty?.DrainRate ?? 0, adjustedDifficulty?.DrainRate);
|
||||||
accuracy.Value = (baseDifficulty?.OverallDifficulty ?? 0, adjustedDifficulty?.OverallDifficulty);
|
Accuracy.Value = (baseDifficulty?.OverallDifficulty ?? 0, adjustedDifficulty?.OverallDifficulty);
|
||||||
approachRate.Value = (baseDifficulty?.ApproachRate ?? 0, adjustedDifficulty?.ApproachRate);
|
ApproachRate.Value = (baseDifficulty?.ApproachRate ?? 0, adjustedDifficulty?.ApproachRate);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class StatisticRow : Container, IHasAccentColour
|
public class StatisticRow : Container, IHasAccentColour
|
||||||
{
|
{
|
||||||
private const float value_width = 25;
|
private const float value_width = 25;
|
||||||
private const float name_width = 70;
|
private const float name_width = 70;
|
||||||
@ -147,7 +149,8 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
private readonly float maxValue;
|
private readonly float maxValue;
|
||||||
private readonly bool forceDecimalPlaces;
|
private readonly bool forceDecimalPlaces;
|
||||||
private readonly OsuSpriteText name, valueText;
|
private readonly OsuSpriteText name, valueText;
|
||||||
private readonly Bar bar, modBar;
|
private readonly Bar bar;
|
||||||
|
public readonly Bar ModBar;
|
||||||
|
|
||||||
[Resolved]
|
[Resolved]
|
||||||
private OsuColour colours { get; set; }
|
private OsuColour colours { get; set; }
|
||||||
@ -173,14 +176,14 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
bar.Length = value.baseValue / maxValue;
|
bar.Length = value.baseValue / maxValue;
|
||||||
|
|
||||||
valueText.Text = (value.adjustedValue ?? value.baseValue).ToString(forceDecimalPlaces ? "0.00" : "0.##");
|
valueText.Text = (value.adjustedValue ?? value.baseValue).ToString(forceDecimalPlaces ? "0.00" : "0.##");
|
||||||
modBar.Length = (value.adjustedValue ?? 0) / maxValue;
|
ModBar.Length = (value.adjustedValue ?? 0) / maxValue;
|
||||||
|
|
||||||
if (value.adjustedValue > value.baseValue)
|
if (Precision.AlmostEquals(value.baseValue, value.adjustedValue ?? value.baseValue, 0.05f))
|
||||||
modBar.AccentColour = valueText.Colour = colours.Red;
|
ModBar.AccentColour = valueText.Colour = Color4.White;
|
||||||
|
else if (value.adjustedValue > value.baseValue)
|
||||||
|
ModBar.AccentColour = valueText.Colour = colours.Red;
|
||||||
else if (value.adjustedValue < value.baseValue)
|
else if (value.adjustedValue < value.baseValue)
|
||||||
modBar.AccentColour = valueText.Colour = colours.BlueDark;
|
ModBar.AccentColour = valueText.Colour = colours.BlueDark;
|
||||||
else
|
|
||||||
modBar.AccentColour = valueText.Colour = Color4.White;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +220,7 @@ namespace osu.Game.Screens.Select.Details
|
|||||||
BackgroundColour = Color4.White.Opacity(0.5f),
|
BackgroundColour = Color4.White.Opacity(0.5f),
|
||||||
Padding = new MarginPadding { Left = name_width + 10, Right = value_width + 10 },
|
Padding = new MarginPadding { Left = name_width + 10, Right = value_width + 10 },
|
||||||
},
|
},
|
||||||
modBar = new Bar
|
ModBar = new Bar
|
||||||
{
|
{
|
||||||
Origin = Anchor.CentreLeft,
|
Origin = Anchor.CentreLeft,
|
||||||
Anchor = Anchor.CentreLeft,
|
Anchor = Anchor.CentreLeft,
|
||||||
|
Loading…
Reference in New Issue
Block a user