From 6ace6bfee17fbf0ffcb4d8f3c88a23d22acf2332 Mon Sep 17 00:00:00 2001
From: Walavouchey <36758269+Walavouchey@users.noreply.github.com>
Date: Tue, 7 Feb 2023 11:16:36 +0100
Subject: [PATCH 01/10] ensure `AccuracyCircle` doesn't land in gaps created by
`RankNotch`es
---
.../Visual/Ranking/TestSceneAccuracyCircle.cs | 9 +++++
.../Expanded/Accuracy/AccuracyCircle.cs | 34 ++++++++++++++++++-
.../Ranking/Expanded/Accuracy/RankNotch.cs | 2 +-
3 files changed, 43 insertions(+), 2 deletions(-)
diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
index 0145a1dfef..314e275ca3 100644
--- a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
+++ b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
@@ -24,11 +24,20 @@ namespace osu.Game.Tests.Visual.Ranking
{
public partial class TestSceneAccuracyCircle : OsuTestScene
{
+ [TestCase(0, ScoreRank.D)]
[TestCase(0.2, ScoreRank.D)]
[TestCase(0.5, ScoreRank.D)]
+ [TestCase(0.699, ScoreRank.D)]
+ [TestCase(0.7, ScoreRank.C)]
[TestCase(0.75, ScoreRank.C)]
+ [TestCase(0.799, ScoreRank.C)]
+ [TestCase(0.80, ScoreRank.B)]
[TestCase(0.85, ScoreRank.B)]
+ [TestCase(0.899, ScoreRank.B)]
+ [TestCase(0.9, ScoreRank.A)]
[TestCase(0.925, ScoreRank.A)]
+ [TestCase(0.949, ScoreRank.A)]
+ [TestCase(0.95, ScoreRank.S)]
[TestCase(0.975, ScoreRank.S)]
[TestCase(0.9999, ScoreRank.S)]
[TestCase(1, ScoreRank.X)]
diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
index 8e04bb68fb..3cb09734c5 100644
--- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
+++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
@@ -73,6 +73,11 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
///
private const double virtual_ss_percentage = 0.01;
+ ///
+ /// The width of a in terms of accuracy.
+ ///
+ public const double NOTCH_WIDTH_PERCENTAGE = 0.002;
+
///
/// The easing for the circle filling transforms.
///
@@ -263,7 +268,34 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
using (BeginDelayedSequence(ACCURACY_TRANSFORM_DELAY))
{
- double targetAccuracy = score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH ? 1 : Math.Min(1 - virtual_ss_percentage, score.Accuracy);
+ double targetAccuracy = score.Accuracy;
+
+ // Ensure the gauge overshoots or undershoots a bit so it doesn't land in the gaps of the inner graded circle (caused by `RankNotch`es),
+ // to prevent ambiguity on what grade it's pointing at.
+ double[] notchPercentages = { 0.7, 0.8, 0.9, 0.95 };
+
+ foreach (double p in notchPercentages)
+ {
+ if (targetAccuracy > p - NOTCH_WIDTH_PERCENTAGE / 2 && targetAccuracy < p + NOTCH_WIDTH_PERCENTAGE / 2)
+ {
+ int tippingDirection = targetAccuracy - p >= 0 ? 1 : -1; // We "round up" here to match rank criteria
+ targetAccuracy = p + tippingDirection * (NOTCH_WIDTH_PERCENTAGE / 2);
+ break;
+ }
+ }
+
+ // The final gap between 99.999...% (S) and 100% (SS) is exaggerated by `virtual_ss_percentage`. We don't want to land there either.
+ if (score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH)
+ targetAccuracy = 1;
+ else
+ targetAccuracy = Math.Min(1 - virtual_ss_percentage - NOTCH_WIDTH_PERCENTAGE / 2, targetAccuracy);
+
+ // The accuracy circle gauge visually fills up a bit too much.
+ // This wouldn't normally matter but we want it to align properly with the inner graded circle in the above cases.
+ const double visual_alignment_offset = 0.001;
+
+ if (targetAccuracy < 1 && targetAccuracy >= visual_alignment_offset)
+ targetAccuracy -= visual_alignment_offset;
accuracyCircle.FillTo(targetAccuracy, ACCURACY_TRANSFORM_DURATION, ACCURACY_TRANSFORM_EASING);
diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs
index 7e73767318..32f2eb2fa5 100644
--- a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs
+++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankNotch.cs
@@ -41,7 +41,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
Origin = Anchor.TopCentre,
RelativeSizeAxes = Axes.Y,
Height = AccuracyCircle.RANK_CIRCLE_RADIUS,
- Width = 1f,
+ Width = (float)AccuracyCircle.NOTCH_WIDTH_PERCENTAGE * 360f,
Colour = OsuColour.Gray(0.3f),
EdgeSmoothness = new Vector2(1f)
}
From 0531c010ebeb17037059d34b21aa948849ca67d2 Mon Sep 17 00:00:00 2001
From: Walavouchey <36758269+Walavouchey@users.noreply.github.com>
Date: Tue, 7 Feb 2023 12:08:37 +0100
Subject: [PATCH 02/10] display `RankBadge`s on on their sector centres
the D `RankBadge` does this anyway. the A and S badges are slightly off
centre to prevent overlap with the SS badge
---
.../Ranking/Expanded/Accuracy/AccuracyCircle.cs | 12 ++++++------
.../Screens/Ranking/Expanded/Accuracy/RankBadge.cs | 11 +++++++++--
2 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
index 3cb09734c5..9ee63b40dd 100644
--- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
+++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
@@ -220,12 +220,12 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
Padding = new MarginPadding { Vertical = -15, Horizontal = -20 },
Children = new[]
{
- new RankBadge(1, getRank(ScoreRank.X)),
- new RankBadge(0.95, getRank(ScoreRank.S)),
- new RankBadge(0.9, getRank(ScoreRank.A)),
- new RankBadge(0.8, getRank(ScoreRank.B)),
- new RankBadge(0.7, getRank(ScoreRank.C)),
- new RankBadge(0.35, getRank(ScoreRank.D)),
+ new RankBadge(1, 1, getRank(ScoreRank.X)),
+ new RankBadge(0.95, 0.95 + (0.025 - virtual_ss_percentage) / 2, getRank(ScoreRank.S)),
+ new RankBadge(0.9, 0.9125, getRank(ScoreRank.A)),
+ new RankBadge(0.8, 0.85, getRank(ScoreRank.B)),
+ new RankBadge(0.7, 0.75, getRank(ScoreRank.C)),
+ new RankBadge(0, 0.35, getRank(ScoreRank.D)),
}
},
rankText = new RankText(score.Rank)
diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs
index 5432b4cbeb..7af327828e 100644
--- a/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs
+++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/RankBadge.cs
@@ -27,6 +27,11 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
///
public readonly double Accuracy;
+ ///
+ /// The position around the to display this badge.
+ ///
+ private readonly double displayPosition;
+
private readonly ScoreRank rank;
private Drawable rankContainer;
@@ -36,10 +41,12 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
/// Creates a new .
///
/// The accuracy value corresponding to .
+ /// The position around the to display this badge.
/// The to be displayed in this .
- public RankBadge(double accuracy, ScoreRank rank)
+ public RankBadge(double accuracy, double position, ScoreRank rank)
{
Accuracy = accuracy;
+ displayPosition = position;
this.rank = rank;
RelativeSizeAxes = Axes.Both;
@@ -92,7 +99,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
base.Update();
// Starts at -90deg (top) and moves counter-clockwise by the accuracy
- rankContainer.Position = circlePosition(-MathF.PI / 2 - (1 - (float)Accuracy) * MathF.PI * 2);
+ rankContainer.Position = circlePosition(-MathF.PI / 2 - (1 - (float)displayPosition) * MathF.PI * 2);
}
private Vector2 circlePosition(float t)
From ee40444fd3c96b37b32d3defb8b7509267244b45 Mon Sep 17 00:00:00 2001
From: Walavouchey <36758269+Walavouchey@users.noreply.github.com>
Date: Wed, 8 Feb 2023 23:59:19 +0100
Subject: [PATCH 03/10] use `Precision.AlmostEquals` for bounds check
---
osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
index 9ee63b40dd..24daea21f3 100644
--- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
+++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
@@ -276,7 +276,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
foreach (double p in notchPercentages)
{
- if (targetAccuracy > p - NOTCH_WIDTH_PERCENTAGE / 2 && targetAccuracy < p + NOTCH_WIDTH_PERCENTAGE / 2)
+ if (Precision.AlmostEquals(p, targetAccuracy, NOTCH_WIDTH_PERCENTAGE / 2))
{
int tippingDirection = targetAccuracy - p >= 0 ? 1 : -1; // We "round up" here to match rank criteria
targetAccuracy = p + tippingDirection * (NOTCH_WIDTH_PERCENTAGE / 2);
From 9544a1d26d6cf819aa192c689fea10e78bb4ac11 Mon Sep 17 00:00:00 2001
From: Walavouchey <36758269+Walavouchey@users.noreply.github.com>
Date: Thu, 9 Feb 2023 00:02:32 +0100
Subject: [PATCH 04/10] use values closer to the extremities for test cases
---
.../Visual/Ranking/TestSceneAccuracyCircle.cs | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
index 314e275ca3..f94cf9eb58 100644
--- a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
+++ b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
@@ -27,16 +27,16 @@ namespace osu.Game.Tests.Visual.Ranking
[TestCase(0, ScoreRank.D)]
[TestCase(0.2, ScoreRank.D)]
[TestCase(0.5, ScoreRank.D)]
- [TestCase(0.699, ScoreRank.D)]
+ [TestCase(0.6999, ScoreRank.D)]
[TestCase(0.7, ScoreRank.C)]
[TestCase(0.75, ScoreRank.C)]
- [TestCase(0.799, ScoreRank.C)]
- [TestCase(0.80, ScoreRank.B)]
+ [TestCase(0.7999, ScoreRank.C)]
+ [TestCase(0.8, ScoreRank.B)]
[TestCase(0.85, ScoreRank.B)]
- [TestCase(0.899, ScoreRank.B)]
+ [TestCase(0.8999, ScoreRank.B)]
[TestCase(0.9, ScoreRank.A)]
[TestCase(0.925, ScoreRank.A)]
- [TestCase(0.949, ScoreRank.A)]
+ [TestCase(0.9499, ScoreRank.A)]
[TestCase(0.95, ScoreRank.S)]
[TestCase(0.975, ScoreRank.S)]
[TestCase(0.9999, ScoreRank.S)]
From fd93bd3f501de37fa7ca43e7e0a52efe2566cb5f Mon Sep 17 00:00:00 2001
From: Walavouchey <36758269+Walavouchey@users.noreply.github.com>
Date: Thu, 9 Feb 2023 00:34:28 +0100
Subject: [PATCH 05/10] move rank accuracy requirements to class-local
constants
---
.../Expanded/Accuracy/AccuracyCircle.cs | 62 ++++++++++++-------
1 file changed, 40 insertions(+), 22 deletions(-)
diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
index 24daea21f3..9606c2bf22 100644
--- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
+++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
@@ -28,6 +28,18 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
///
public partial class AccuracyCircle : CompositeDrawable
{
+ private const double accuracy_x = 1;
+
+ private const double accuracy_s = 0.95;
+
+ private const double accuracy_a = 0.9;
+
+ private const double accuracy_b = 0.8;
+
+ private const double accuracy_c = 0.7;
+
+ private const double accuracy_d = 0;
+
///
/// Duration for the transforms causing this component to appear.
///
@@ -150,49 +162,49 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.ForRank(ScoreRank.X),
InnerRadius = RANK_CIRCLE_RADIUS,
- Current = { Value = 1 }
+ Current = { Value = accuracy_x }
},
new CircularProgress
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.ForRank(ScoreRank.S),
InnerRadius = RANK_CIRCLE_RADIUS,
- Current = { Value = 1 - virtual_ss_percentage }
+ Current = { Value = accuracy_x - virtual_ss_percentage }
},
new CircularProgress
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.ForRank(ScoreRank.A),
InnerRadius = RANK_CIRCLE_RADIUS,
- Current = { Value = 0.95f }
+ Current = { Value = accuracy_s }
},
new CircularProgress
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.ForRank(ScoreRank.B),
InnerRadius = RANK_CIRCLE_RADIUS,
- Current = { Value = 0.9f }
+ Current = { Value = accuracy_a }
},
new CircularProgress
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.ForRank(ScoreRank.C),
InnerRadius = RANK_CIRCLE_RADIUS,
- Current = { Value = 0.8f }
+ Current = { Value = accuracy_b }
},
new CircularProgress
{
RelativeSizeAxes = Axes.Both,
Colour = OsuColour.ForRank(ScoreRank.D),
InnerRadius = RANK_CIRCLE_RADIUS,
- Current = { Value = 0.7f }
+ Current = { Value = accuracy_c }
},
- new RankNotch(0),
- new RankNotch((float)(1 - virtual_ss_percentage)),
- new RankNotch(0.95f),
- new RankNotch(0.9f),
- new RankNotch(0.8f),
- new RankNotch(0.7f),
+ new RankNotch((float)accuracy_x),
+ new RankNotch((float)(accuracy_x - virtual_ss_percentage)),
+ new RankNotch((float)accuracy_s),
+ new RankNotch((float)accuracy_a),
+ new RankNotch((float)accuracy_b),
+ new RankNotch((float)accuracy_c),
new BufferedContainer
{
Name = "Graded circle mask",
@@ -220,12 +232,13 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
Padding = new MarginPadding { Vertical = -15, Horizontal = -20 },
Children = new[]
{
- new RankBadge(1, 1, getRank(ScoreRank.X)),
- new RankBadge(0.95, 0.95 + (0.025 - virtual_ss_percentage) / 2, getRank(ScoreRank.S)),
- new RankBadge(0.9, 0.9125, getRank(ScoreRank.A)),
- new RankBadge(0.8, 0.85, getRank(ScoreRank.B)),
- new RankBadge(0.7, 0.75, getRank(ScoreRank.C)),
- new RankBadge(0, 0.35, getRank(ScoreRank.D)),
+ // The S and A badges are moved down slightly to prevent collision with the SS badge.
+ new RankBadge(accuracy_x, accuracy_x, getRank(ScoreRank.X)),
+ new RankBadge(accuracy_s, Interpolation.Lerp(accuracy_s, (accuracy_x - virtual_ss_percentage), 0.25), getRank(ScoreRank.S)),
+ new RankBadge(accuracy_a, Interpolation.Lerp(accuracy_a, accuracy_s, 0.25), getRank(ScoreRank.A)),
+ new RankBadge(accuracy_b, Interpolation.Lerp(accuracy_b, accuracy_a, 0.5), getRank(ScoreRank.B)),
+ new RankBadge(accuracy_c, Interpolation.Lerp(accuracy_c, accuracy_b, 0.5), getRank(ScoreRank.C)),
+ new RankBadge(accuracy_d, Interpolation.Lerp(accuracy_d, accuracy_c, 0.5), getRank(ScoreRank.D)),
}
},
rankText = new RankText(score.Rank)
@@ -269,11 +282,16 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
using (BeginDelayedSequence(ACCURACY_TRANSFORM_DELAY))
{
double targetAccuracy = score.Accuracy;
+ double[] notchPercentages =
+ {
+ accuracy_s,
+ accuracy_a,
+ accuracy_b,
+ accuracy_c,
+ };
// Ensure the gauge overshoots or undershoots a bit so it doesn't land in the gaps of the inner graded circle (caused by `RankNotch`es),
// to prevent ambiguity on what grade it's pointing at.
- double[] notchPercentages = { 0.7, 0.8, 0.9, 0.95 };
-
foreach (double p in notchPercentages)
{
if (Precision.AlmostEquals(p, targetAccuracy, NOTCH_WIDTH_PERCENTAGE / 2))
@@ -288,7 +306,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
if (score.Rank == ScoreRank.X || score.Rank == ScoreRank.XH)
targetAccuracy = 1;
else
- targetAccuracy = Math.Min(1 - virtual_ss_percentage - NOTCH_WIDTH_PERCENTAGE / 2, targetAccuracy);
+ targetAccuracy = Math.Min(accuracy_x - virtual_ss_percentage - NOTCH_WIDTH_PERCENTAGE / 2, targetAccuracy);
// The accuracy circle gauge visually fills up a bit too much.
// This wouldn't normally matter but we want it to align properly with the inner graded circle in the above cases.
@@ -325,7 +343,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
if (badge.Accuracy > score.Accuracy)
continue;
- using (BeginDelayedSequence(inverseEasing(ACCURACY_TRANSFORM_EASING, Math.Min(1 - virtual_ss_percentage, badge.Accuracy) / targetAccuracy) * ACCURACY_TRANSFORM_DURATION))
+ using (BeginDelayedSequence(inverseEasing(ACCURACY_TRANSFORM_EASING, Math.Min(accuracy_x - virtual_ss_percentage, badge.Accuracy) / targetAccuracy) * ACCURACY_TRANSFORM_DURATION))
{
badge.Appear();
From 57312279f02049028fbc97f41f94be8192f323c0 Mon Sep 17 00:00:00 2001
From: Walavouchey <36758269+Walavouchey@users.noreply.github.com>
Date: Thu, 9 Feb 2023 02:20:05 +0100
Subject: [PATCH 06/10] adjust `RankNotch` gap size to match original value
---
osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
index 9606c2bf22..31ce3ddf95 100644
--- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
+++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
@@ -88,7 +88,7 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
///
/// The width of a in terms of accuracy.
///
- public const double NOTCH_WIDTH_PERCENTAGE = 0.002;
+ public const double NOTCH_WIDTH_PERCENTAGE = 1.0 / 360;
///
/// The easing for the circle filling transforms.
From cf009432cc5af59b8a35e809468ece6472eb2561 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Thu, 9 Feb 2023 15:41:45 +0900
Subject: [PATCH 07/10] Centralise accuracy cutoff constants and add lookup
helper methods
---
osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 93 +++++++++++++++----
.../Expanded/Accuracy/AccuracyCircle.cs | 18 ++--
2 files changed, 81 insertions(+), 30 deletions(-)
diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
index b5f42ec2cc..1e03a3ff80 100644
--- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
+++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
@@ -7,21 +7,28 @@ using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Linq;
using osu.Framework.Bindables;
+using osu.Framework.Localisation;
using osu.Framework.Utils;
using osu.Game.Beatmaps;
using osu.Game.Extensions;
+using osu.Game.Localisation;
using osu.Game.Rulesets.Judgements;
using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Objects;
using osu.Game.Rulesets.Replays;
using osu.Game.Scoring;
-using osu.Framework.Localisation;
-using osu.Game.Localisation;
namespace osu.Game.Rulesets.Scoring
{
public partial class ScoreProcessor : JudgementProcessor
{
+ private const double accuracy_cutoff_x = 1;
+ private const double accuracy_cutoff_s = 0.95;
+ private const double accuracy_cutoff_a = 0.9;
+ private const double accuracy_cutoff_b = 0.8;
+ private const double accuracy_cutoff_c = 0.7;
+ private const double accuracy_cutoff_d = 0;
+
private const double max_score = 1000000;
///
@@ -160,7 +167,7 @@ namespace osu.Game.Rulesets.Scoring
Combo.ValueChanged += combo => HighestCombo.Value = Math.Max(HighestCombo.Value, combo.NewValue);
Accuracy.ValueChanged += accuracy =>
{
- Rank.Value = rankFrom(accuracy.NewValue);
+ Rank.Value = RankFromAccuracy(accuracy.NewValue);
foreach (var mod in Mods.Value.OfType())
Rank.Value = mod.AdjustRank(Rank.Value, accuracy.NewValue);
};
@@ -369,22 +376,6 @@ namespace osu.Game.Rulesets.Scoring
}
}
- private ScoreRank rankFrom(double acc)
- {
- if (acc == 1)
- return ScoreRank.X;
- if (acc >= 0.95)
- return ScoreRank.S;
- if (acc >= 0.9)
- return ScoreRank.A;
- if (acc >= 0.8)
- return ScoreRank.B;
- if (acc >= 0.7)
- return ScoreRank.C;
-
- return ScoreRank.D;
- }
-
///
/// Resets this ScoreProcessor to a default state.
///
@@ -583,6 +574,70 @@ namespace osu.Game.Rulesets.Scoring
hitEvents.Clear();
}
+ #region Static helper methods
+
+ ///
+ /// Given an accuracy (0..1), return the correct .
+ ///
+ public static ScoreRank RankFromAccuracy(double accuracy)
+ {
+ switch (accuracy)
+ {
+ case accuracy_cutoff_x:
+ return ScoreRank.X;
+
+ case >= accuracy_cutoff_s:
+ return ScoreRank.S;
+
+ case >= accuracy_cutoff_a:
+ return ScoreRank.A;
+
+ case >= accuracy_cutoff_b:
+ return ScoreRank.B;
+
+ case >= accuracy_cutoff_c:
+ return ScoreRank.C;
+
+ default:
+ return ScoreRank.D;
+ }
+ }
+
+ ///
+ /// Given a , return the cutoff accuracy (0..1).
+ /// Accuracy must be great or equal to the cutoff to qualify for the provided rank.
+ ///
+ public static double AccuracyCutoffFromRank(ScoreRank rank)
+ {
+ switch (rank)
+ {
+ case ScoreRank.X:
+ case ScoreRank.XH:
+ return accuracy_cutoff_x;
+
+ case ScoreRank.S:
+ case ScoreRank.SH:
+ return accuracy_cutoff_s;
+
+ case ScoreRank.A:
+ return accuracy_cutoff_a;
+
+ case ScoreRank.B:
+ return accuracy_cutoff_b;
+
+ case ScoreRank.C:
+ return accuracy_cutoff_c;
+
+ case ScoreRank.D:
+ return accuracy_cutoff_d;
+
+ default:
+ throw new ArgumentOutOfRangeException(nameof(rank), rank, null);
+ }
+ }
+
+ #endregion
+
///
/// Stores the required scoring data that fulfils the minimum requirements for a to calculate score.
///
diff --git a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
index 31ce3ddf95..2ec4270c3c 100644
--- a/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
+++ b/osu.Game/Screens/Ranking/Expanded/Accuracy/AccuracyCircle.cs
@@ -17,6 +17,7 @@ using osu.Framework.Utils;
using osu.Game.Audio;
using osu.Game.Graphics;
using osu.Game.Rulesets.Mods;
+using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
using osu.Game.Skinning;
using osuTK;
@@ -28,17 +29,12 @@ namespace osu.Game.Screens.Ranking.Expanded.Accuracy
///
public partial class AccuracyCircle : CompositeDrawable
{
- private const double accuracy_x = 1;
-
- private const double accuracy_s = 0.95;
-
- private const double accuracy_a = 0.9;
-
- private const double accuracy_b = 0.8;
-
- private const double accuracy_c = 0.7;
-
- private const double accuracy_d = 0;
+ private static readonly double accuracy_x = ScoreProcessor.AccuracyCutoffFromRank(ScoreRank.X);
+ private static readonly double accuracy_s = ScoreProcessor.AccuracyCutoffFromRank(ScoreRank.S);
+ private static readonly double accuracy_a = ScoreProcessor.AccuracyCutoffFromRank(ScoreRank.A);
+ private static readonly double accuracy_b = ScoreProcessor.AccuracyCutoffFromRank(ScoreRank.B);
+ private static readonly double accuracy_c = ScoreProcessor.AccuracyCutoffFromRank(ScoreRank.C);
+ private static readonly double accuracy_d = ScoreProcessor.AccuracyCutoffFromRank(ScoreRank.D);
///
/// Duration for the transforms causing this component to appear.
From 92eb6b6717852dfeb7f3babcadc5a707af4423bd Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Thu, 9 Feb 2023 15:41:55 +0900
Subject: [PATCH 08/10] Simplify `TestSceneAccuracyCircle` test specifications
---
.../Visual/Ranking/TestSceneAccuracyCircle.cs | 38 +++++++++----------
1 file changed, 19 insertions(+), 19 deletions(-)
diff --git a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
index f94cf9eb58..bf18bd3e51 100644
--- a/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
+++ b/osu.Game.Tests/Visual/Ranking/TestSceneAccuracyCircle.cs
@@ -24,26 +24,26 @@ namespace osu.Game.Tests.Visual.Ranking
{
public partial class TestSceneAccuracyCircle : OsuTestScene
{
- [TestCase(0, ScoreRank.D)]
- [TestCase(0.2, ScoreRank.D)]
- [TestCase(0.5, ScoreRank.D)]
- [TestCase(0.6999, ScoreRank.D)]
- [TestCase(0.7, ScoreRank.C)]
- [TestCase(0.75, ScoreRank.C)]
- [TestCase(0.7999, ScoreRank.C)]
- [TestCase(0.8, ScoreRank.B)]
- [TestCase(0.85, ScoreRank.B)]
- [TestCase(0.8999, ScoreRank.B)]
- [TestCase(0.9, ScoreRank.A)]
- [TestCase(0.925, ScoreRank.A)]
- [TestCase(0.9499, ScoreRank.A)]
- [TestCase(0.95, ScoreRank.S)]
- [TestCase(0.975, ScoreRank.S)]
- [TestCase(0.9999, ScoreRank.S)]
- [TestCase(1, ScoreRank.X)]
- public void TestRank(double accuracy, ScoreRank rank)
+ [TestCase(0)]
+ [TestCase(0.2)]
+ [TestCase(0.5)]
+ [TestCase(0.6999)]
+ [TestCase(0.7)]
+ [TestCase(0.75)]
+ [TestCase(0.7999)]
+ [TestCase(0.8)]
+ [TestCase(0.85)]
+ [TestCase(0.8999)]
+ [TestCase(0.9)]
+ [TestCase(0.925)]
+ [TestCase(0.9499)]
+ [TestCase(0.95)]
+ [TestCase(0.975)]
+ [TestCase(0.9999)]
+ [TestCase(1)]
+ public void TestRank(double accuracy)
{
- var score = createScore(accuracy, rank);
+ var score = createScore(accuracy, ScoreProcessor.RankFromAccuracy(accuracy));
addCircleStep(score);
}
From 96c1832af407a9f8cf3d014ea6f4f17e609b02eb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bart=C5=82omiej=20Dach?=
Date: Fri, 10 Feb 2023 00:07:24 +0100
Subject: [PATCH 09/10] Fix grammar in xmldoc
Co-authored-by: Walavouchey <36758269+Walavouchey@users.noreply.github.com>
---
osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
index 1e03a3ff80..7fc8980cf5 100644
--- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
+++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
@@ -605,7 +605,7 @@ namespace osu.Game.Rulesets.Scoring
///
/// Given a , return the cutoff accuracy (0..1).
- /// Accuracy must be great or equal to the cutoff to qualify for the provided rank.
+ /// Accuracy must be greater than or equal to the cutoff to qualify for the provided rank.
///
public static double AccuracyCutoffFromRank(ScoreRank rank)
{
From 1df6fc631104e0338eeced59f6b7fa91836ac9a9 Mon Sep 17 00:00:00 2001
From: Dean Herbert
Date: Fri, 10 Feb 2023 17:03:27 +0900
Subject: [PATCH 10/10] Use `if` statements rather than conditional `case`
---
osu.Game/Rulesets/Scoring/ScoreProcessor.cs | 30 ++++++++-------------
1 file changed, 11 insertions(+), 19 deletions(-)
diff --git a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
index 7fc8980cf5..96f6922224 100644
--- a/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
+++ b/osu.Game/Rulesets/Scoring/ScoreProcessor.cs
@@ -581,26 +581,18 @@ namespace osu.Game.Rulesets.Scoring
///
public static ScoreRank RankFromAccuracy(double accuracy)
{
- switch (accuracy)
- {
- case accuracy_cutoff_x:
- return ScoreRank.X;
+ if (accuracy == accuracy_cutoff_x)
+ return ScoreRank.X;
+ if (accuracy >= accuracy_cutoff_s)
+ return ScoreRank.S;
+ if (accuracy >= accuracy_cutoff_a)
+ return ScoreRank.A;
+ if (accuracy >= accuracy_cutoff_b)
+ return ScoreRank.B;
+ if (accuracy >= accuracy_cutoff_c)
+ return ScoreRank.C;
- case >= accuracy_cutoff_s:
- return ScoreRank.S;
-
- case >= accuracy_cutoff_a:
- return ScoreRank.A;
-
- case >= accuracy_cutoff_b:
- return ScoreRank.B;
-
- case >= accuracy_cutoff_c:
- return ScoreRank.C;
-
- default:
- return ScoreRank.D;
- }
+ return ScoreRank.D;
}
///