1
0
mirror of https://github.com/ppy/osu.git synced 2024-11-11 09:27:29 +08:00

Add catch scoring algorithms to test scene

This commit is contained in:
Bartłomiej Dach 2023-09-13 15:27:35 +02:00
parent 5eccc771c2
commit aa8aa14a57
No known key found for this signature in database

View File

@ -3,6 +3,7 @@
using System; using System;
using NUnit.Framework; using NUnit.Framework;
using osu.Framework.Bindables;
using osu.Game.Beatmaps; using osu.Game.Beatmaps;
using osu.Game.Rulesets.Catch.Beatmaps; using osu.Game.Rulesets.Catch.Beatmaps;
using osu.Game.Rulesets.Catch.Judgements; using osu.Game.Rulesets.Catch.Judgements;
@ -22,6 +23,12 @@ namespace osu.Game.Rulesets.Catch.Tests
{ {
} }
private Bindable<double> scoreMultiplier { get; } = new BindableDouble
{
Default = 4,
Value = 4
};
protected override IBeatmap CreateBeatmap(int maxCombo) protected override IBeatmap CreateBeatmap(int maxCombo)
{ {
var beatmap = new CatchBeatmap(); var beatmap = new CatchBeatmap();
@ -30,51 +37,105 @@ namespace osu.Game.Rulesets.Catch.Tests
return beatmap; return beatmap;
} }
protected override IScoringAlgorithm CreateScoreV1() => new ScoreV1(); protected override IScoringAlgorithm CreateScoreV1() => new ScoreV1 { ScoreMultiplier = { BindTarget = scoreMultiplier } };
protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo); protected override IScoringAlgorithm CreateScoreV2(int maxCombo) => new ScoreV2(maxCombo);
protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode) => new CatchProcessorBasedScoringAlgorithm(beatmap, mode); protected override ProcessorBasedScoringAlgorithm CreateScoreAlgorithm(IBeatmap beatmap, ScoringMode mode) => new CatchProcessorBasedScoringAlgorithm(beatmap, mode);
[Test]
public void TestBasicScenarios()
{
AddStep("set up score multiplier", () =>
{
scoreMultiplier.BindValueChanged(_ => Rerun());
});
AddStep("set max combo to 100", () => MaxCombo.Value = 100);
AddStep("set perfect score", () =>
{
NonPerfectLocations.Clear();
MissLocations.Clear();
});
AddStep("set score with misses", () =>
{
NonPerfectLocations.Clear();
MissLocations.Clear();
MissLocations.AddRange(new[] { 24d, 49 });
});
AddSliderStep("adjust score multiplier", 0, 10, (int)scoreMultiplier.Default, multiplier => scoreMultiplier.Value = multiplier);
}
private const int base_great = 300;
private class ScoreV1 : IScoringAlgorithm private class ScoreV1 : IScoringAlgorithm
{ {
public void ApplyHit() private int currentCombo;
public BindableDouble ScoreMultiplier { get; } = new BindableDouble();
public void ApplyHit() => applyHitV1(base_great);
public void ApplyNonPerfect() => throw new NotSupportedException("catch does not have \"non-perfect\" judgements.");
public void ApplyMiss() => applyHitV1(0);
private void applyHitV1(int baseScore)
{ {
if (baseScore == 0)
{
currentCombo = 0;
return;
}
TotalScore += baseScore;
// combo multiplier
// ReSharper disable once PossibleLossOfFraction
TotalScore += (int)(Math.Max(0, currentCombo - 1) * (baseScore / 25 * ScoreMultiplier.Value));
currentCombo++;
} }
public void ApplyNonPerfect() public long TotalScore { get; private set; }
{
}
public void ApplyMiss()
{
}
public long TotalScore => 0;
} }
private class ScoreV2 : IScoringAlgorithm private class ScoreV2 : IScoringAlgorithm
{ {
private readonly int maxCombo; private int currentCombo;
private double comboPortion;
private readonly double comboPortionMax;
private const double combo_base = 4;
private const int combo_cap = 200;
public ScoreV2(int maxCombo) public ScoreV2(int maxCombo)
{ {
this.maxCombo = maxCombo; for (int i = 0; i < maxCombo; i++)
ApplyHit();
comboPortionMax = comboPortion;
currentCombo = 0;
comboPortion = 0;
} }
public void ApplyHit() public void ApplyHit() => applyHitV2(base_great);
{
}
public void ApplyNonPerfect() public void ApplyNonPerfect() => throw new NotSupportedException("catch does not have \"non-perfect\" judgements.");
private void applyHitV2(int baseScore)
{ {
comboPortion += baseScore * Math.Min(Math.Max(0.5, Math.Log(++currentCombo, combo_base)), Math.Log(combo_cap, combo_base));
} }
public void ApplyMiss() public void ApplyMiss()
{ {
currentCombo = 0;
} }
public long TotalScore => 0; public long TotalScore
=> (int)Math.Round(1000000 * comboPortion / comboPortionMax); // vast simplification, as we're not doing ticks here.
} }
private class CatchProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm private class CatchProcessorBasedScoringAlgorithm : ProcessorBasedScoringAlgorithm