From cff9dab650b8bc0e453be6b312a96b778fdcbc93 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Tue, 14 Dec 2021 03:11:04 +0000
Subject: [PATCH 0001/2493] Remove combo scaling and change miss penalty
---
.../Difficulty/OsuPerformanceCalculator.cs | 17 +++--------------
1 file changed, 3 insertions(+), 14 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
index 8d45c7a8cc..6de6572b93 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
@@ -101,13 +101,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
aimValue *= lengthBonus;
- // Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0)
- aimValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), effectiveMissCount);
-
- // Combo scaling.
- if (Attributes.MaxCombo > 0)
- aimValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(Attributes.MaxCombo, 0.8), 1.0);
+ aimValue *= Math.Pow(0.97, effectiveMissCount);
double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
@@ -151,13 +146,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
speedValue *= lengthBonus;
- // Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0)
- speedValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), Math.Pow(effectiveMissCount, .875));
-
- // Combo scaling.
- if (Attributes.MaxCombo > 0)
- speedValue *= Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(Attributes.MaxCombo, 0.8), 1.0);
+ speedValue *= Math.Pow(0.97, effectiveMissCount);
double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
@@ -238,9 +228,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
if (mods.Any(h => h is OsuModHidden))
flashlightValue *= 1.3;
- // Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0)
- flashlightValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), Math.Pow(effectiveMissCount, .875));
+ flashlightValue *= Math.Pow(0.97, effectiveMissCount);
// Combo scaling.
if (Attributes.MaxCombo > 0)
From 86ad42a7440ec0a1478e2030209c2675985e3220 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Tue, 14 Dec 2021 17:47:41 +0000
Subject: [PATCH 0002/2493] Nerf length bonus
---
osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
index 6de6572b93..6ade8c1732 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
@@ -96,7 +96,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double aimValue = Math.Pow(5.0 * Math.Max(1.0, rawAim / 0.0675) - 4.0, 3.0) / 100000.0;
// Longer maps are worth more.
- double lengthBonus = 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) +
+ double lengthBonus = 0.95 + 0.25 * Math.Min(1.0, totalHits / 2000.0) +
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
aimValue *= lengthBonus;
@@ -142,7 +142,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double speedValue = Math.Pow(5.0 * Math.Max(1.0, Attributes.SpeedStrain / 0.0675) - 4.0, 3.0) / 100000.0;
// Longer maps are worth more.
- double lengthBonus = 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) +
+ double lengthBonus = 0.95 + 0.25 * Math.Min(1.0, totalHits / 2000.0) +
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
speedValue *= lengthBonus;
From 489aa43b1bab6efeb0ed05e97ec66181dfe3b4f4 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Tue, 14 Dec 2021 19:57:36 +0000
Subject: [PATCH 0003/2493] Make miss penalty harsher
---
.../Difficulty/OsuPerformanceCalculator.cs | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
index 6ade8c1732..0459c64c0e 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
@@ -96,13 +96,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double aimValue = Math.Pow(5.0 * Math.Max(1.0, rawAim / 0.0675) - 4.0, 3.0) / 100000.0;
// Longer maps are worth more.
- double lengthBonus = 0.95 + 0.25 * Math.Min(1.0, totalHits / 2000.0) +
+ double lengthBonus = 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) +
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
aimValue *= lengthBonus;
if (effectiveMissCount > 0)
- aimValue *= Math.Pow(0.97, effectiveMissCount);
+ aimValue *= Math.Pow(0.96, effectiveMissCount);
double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
@@ -142,12 +142,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double speedValue = Math.Pow(5.0 * Math.Max(1.0, Attributes.SpeedStrain / 0.0675) - 4.0, 3.0) / 100000.0;
// Longer maps are worth more.
- double lengthBonus = 0.95 + 0.25 * Math.Min(1.0, totalHits / 2000.0) +
+ double lengthBonus = 0.95 + 0.4 * Math.Min(1.0, totalHits / 2000.0) +
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
speedValue *= lengthBonus;
if (effectiveMissCount > 0)
- speedValue *= Math.Pow(0.97, effectiveMissCount);
+ speedValue *= Math.Pow(0.96, effectiveMissCount);
double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
@@ -229,7 +229,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
flashlightValue *= 1.3;
if (effectiveMissCount > 0)
- flashlightValue *= Math.Pow(0.97, effectiveMissCount);
+ flashlightValue *= Math.Pow(0.96, effectiveMissCount);
// Combo scaling.
if (Attributes.MaxCombo > 0)
From bac4cfed50be4e3d1e0264ce0cd9099c3132d4b5 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Thu, 16 Dec 2021 18:37:57 +0000
Subject: [PATCH 0004/2493] Use frost's miss count penalty
---
.../Difficulty/OsuPerformanceCalculator.cs | 21 ++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
index 0459c64c0e..bba53c92fc 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
@@ -102,7 +102,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
aimValue *= lengthBonus;
if (effectiveMissCount > 0)
- aimValue *= Math.Pow(0.96, effectiveMissCount);
+ aimValue *= calculateMissPenalty(effectiveMissCount);
double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
@@ -147,7 +147,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
speedValue *= lengthBonus;
if (effectiveMissCount > 0)
- speedValue *= Math.Pow(0.96, effectiveMissCount);
+ speedValue *= calculateMissPenalty(effectiveMissCount);
double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
@@ -229,7 +229,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
flashlightValue *= 1.3;
if (effectiveMissCount > 0)
- flashlightValue *= Math.Pow(0.96, effectiveMissCount);
+ flashlightValue *= calculateMissPenalty(effectiveMissCount);
// Combo scaling.
if (Attributes.MaxCombo > 0)
@@ -265,6 +265,21 @@ namespace osu.Game.Rulesets.Osu.Difficulty
return Math.Max(countMiss, (int)Math.Floor(comboBasedMissCount));
}
+ private double calculateMissPenalty(double missCount)
+ {
+ double leniency = 2.0;
+
+ if (missCount > totalHits - leniency)
+ return 0;
+
+ double missApprox = erfInvApprox((totalHits - leniency - missCount) / totalHits);
+ double fcApprox = erfInvApprox((totalHits - leniency) / totalHits);
+
+ return Math.Pow(missApprox / fcApprox, 1.5);
+ }
+
+ private double logit(double x) => Math.Log(x / (1 - x));
+ private double erfInvApprox(double x) => (Math.Sqrt(Math.PI) / 4) * logit((x + 1) / 2);
private int totalHits => countGreat + countOk + countMeh + countMiss;
private int totalSuccessfulHits => countGreat + countOk + countMeh;
}
From 60e2a8ed4b2f0f38dafe0cc9bc6ab8c55128b189 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Tue, 21 Dec 2021 17:54:26 +0000
Subject: [PATCH 0005/2493] Use MathNet for miss penalty calculation, and use
old penalty formula for Flashlight
---
.../Difficulty/OsuPerformanceCalculator.cs | 14 +++++++-------
osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 4 ++++
2 files changed, 11 insertions(+), 7 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
index bba53c92fc..90caa64512 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
@@ -9,6 +9,7 @@ using osu.Game.Rulesets.Mods;
using osu.Game.Rulesets.Osu.Mods;
using osu.Game.Rulesets.Scoring;
using osu.Game.Scoring;
+using MathNet.Numerics;
namespace osu.Game.Rulesets.Osu.Difficulty
{
@@ -228,8 +229,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty
if (mods.Any(h => h is OsuModHidden))
flashlightValue *= 1.3;
+ // Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0)
- flashlightValue *= calculateMissPenalty(effectiveMissCount);
+ flashlightValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), Math.Pow(effectiveMissCount, .875));
// Combo scaling.
if (Attributes.MaxCombo > 0)
@@ -267,19 +269,17 @@ namespace osu.Game.Rulesets.Osu.Difficulty
private double calculateMissPenalty(double missCount)
{
- double leniency = 2.0;
+ double leniency = 4.3;
if (missCount > totalHits - leniency)
return 0;
- double missApprox = erfInvApprox((totalHits - leniency - missCount) / totalHits);
- double fcApprox = erfInvApprox((totalHits - leniency) / totalHits);
+ double missApprox = SpecialFunctions.ErfInv((totalHits - leniency - missCount) / totalHits);
+ double fcApprox = SpecialFunctions.ErfInv((totalHits - leniency) / totalHits);
- return Math.Pow(missApprox / fcApprox, 1.5);
+ return Math.Pow(missApprox / fcApprox, 3.5);
}
- private double logit(double x) => Math.Log(x / (1 - x));
- private double erfInvApprox(double x) => (Math.Sqrt(Math.PI) / 4) * logit((x + 1) / 2);
private int totalHits => countGreat + countOk + countMeh + countMiss;
private int totalSuccessfulHits => countGreat + countOk + countMeh;
}
diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
index 98f1e69bd1..018bdb93df 100644
--- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
+++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
@@ -15,4 +15,8 @@
+
+
+
+
\ No newline at end of file
From 5640918c8c7c8af2e29feec4c7ad6d501619dafc Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Sun, 26 Dec 2021 23:51:49 +0000
Subject: [PATCH 0006/2493] New miss penalty formula, using relevant difficult
notes in each skill (targets diffspikes)
---
.../Difficulty/OsuDifficultyAttributes.cs | 6 ++++++
.../Difficulty/OsuDifficultyCalculator.cs | 9 +++++++++
.../Difficulty/OsuPerformanceCalculator.cs | 16 ++++------------
.../Difficulty/Skills/OsuStrainSkill.cs | 7 +++++++
4 files changed, 26 insertions(+), 12 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
index 4b2e54da17..6102f4a8b2 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
@@ -24,6 +24,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty
[JsonProperty("slider_factor")]
public double SliderFactor { get; set; }
+ [JsonProperty("aim_difficult_strain_count")]
+ public int AimDifficultStrainCount { get; set; }
+
+ [JsonProperty("speed_difficult_strain_count")]
+ public int SpeedDifficultStrainCount { get; set; }
+
[JsonProperty("approach_rate")]
public double ApproachRate { get; set; }
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
index ed42f333c0..ac228b0a32 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
@@ -40,6 +40,13 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1;
+ int aimDifficultyStrainCount = ((OsuStrainSkill)skills[0]).RelevantDifficultStrains();
+ int speedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).RelevantDifficultStrains();
+
+ // Total number of strains in a map can vary by clockrate, and this needs to be corrected for.
+ aimDifficultyStrainCount = (int)(aimDifficultyStrainCount * clockRate);
+ speedDifficultyStrainCount = (int)(aimDifficultyStrainCount * clockRate);
+
if (mods.Any(h => h is OsuModRelax))
speedRating = 0.0;
@@ -78,6 +85,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
SpeedStrain = speedRating,
FlashlightRating = flashlightRating,
SliderFactor = sliderFactor,
+ AimDifficultStrainCount = aimDifficultyStrainCount,
+ SpeedDifficultStrainCount = speedDifficultyStrainCount,
ApproachRate = preempt > 1200 ? (1800 - preempt) / 120 : (1200 - preempt) / 150 + 5,
OverallDifficulty = (80 - hitWindowGreat) / 6,
DrainRate = drainRate,
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
index 90caa64512..3efb8951b3 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
@@ -103,7 +103,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
aimValue *= lengthBonus;
if (effectiveMissCount > 0)
- aimValue *= calculateMissPenalty(effectiveMissCount);
+ aimValue *= calculateMissPenalty(effectiveMissCount, Attributes.AimDifficultStrainCount);
double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
@@ -148,7 +148,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
speedValue *= lengthBonus;
if (effectiveMissCount > 0)
- speedValue *= calculateMissPenalty(effectiveMissCount);
+ speedValue *= calculateMissPenalty(effectiveMissCount, Attributes.SpeedDifficultStrainCount);
double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
@@ -267,17 +267,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty
return Math.Max(countMiss, (int)Math.Floor(comboBasedMissCount));
}
- private double calculateMissPenalty(double missCount)
+ private double calculateMissPenalty(double missCount, double strainCount)
{
- double leniency = 4.3;
-
- if (missCount > totalHits - leniency)
- return 0;
-
- double missApprox = SpecialFunctions.ErfInv((totalHits - leniency - missCount) / totalHits);
- double fcApprox = SpecialFunctions.ErfInv((totalHits - leniency) / totalHits);
-
- return Math.Pow(missApprox / fcApprox, 3.5);
+ return 0.95 / ((missCount / (3 * Math.Sqrt(strainCount))) + 1);
}
private int totalHits => countGreat + countOk + countMeh + countMiss;
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
index e47edc37cc..43e39482a7 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
@@ -57,5 +57,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
return difficulty * DifficultyMultiplier;
}
+
+ public int RelevantDifficultStrains()
+ {
+ List strains = GetCurrentStrainPeaks().OrderByDescending(d => d).ToList();
+
+ return strains.Count(s => s > strains[0] * 0.66);
+ }
}
}
From e9589e57a662bc47297fec2429d7bfce1256db68 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Mon, 27 Dec 2021 02:23:03 +0000
Subject: [PATCH 0007/2493] Fix logical error
---
osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
index ac228b0a32..87ab12248f 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
@@ -45,7 +45,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
// Total number of strains in a map can vary by clockrate, and this needs to be corrected for.
aimDifficultyStrainCount = (int)(aimDifficultyStrainCount * clockRate);
- speedDifficultyStrainCount = (int)(aimDifficultyStrainCount * clockRate);
+ speedDifficultyStrainCount = (int)(speedDifficultyStrainCount * clockRate);
if (mods.Any(h => h is OsuModRelax))
speedRating = 0.0;
From 8ce6e3c573104d55956c9a3c4cd3c8beffd41b09 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 29 Dec 2021 18:49:13 +0000
Subject: [PATCH 0008/2493] Remove mathnet
---
osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs | 4 ----
osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj | 4 ----
2 files changed, 8 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
index d7d294df47..f6e5481feb 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
@@ -99,8 +99,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty
if (effectiveMissCount > 0)
aimValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), effectiveMissCount);
- aimValue *= getComboScalingFactor();
-
double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
approachRateFactor = 0.3 * (Attributes.ApproachRate - 10.33);
@@ -146,8 +144,6 @@ namespace osu.Game.Rulesets.Osu.Difficulty
if (effectiveMissCount > 0)
speedValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), Math.Pow(effectiveMissCount, .875));
- speedValue *= getComboScalingFactor();
-
double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
approachRateFactor = 0.3 * (Attributes.ApproachRate - 10.33);
diff --git a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
index 018bdb93df..98f1e69bd1 100644
--- a/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
+++ b/osu.Game.Rulesets.Osu/osu.Game.Rulesets.Osu.csproj
@@ -15,8 +15,4 @@
-
-
-
-
\ No newline at end of file
From 4f257d6987b1144912f561d5a3360593598be834 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 29 Dec 2021 18:59:17 +0000
Subject: [PATCH 0009/2493] Clean up unsuccessful merge
---
.../Difficulty/OsuPerformanceCalculator.cs | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
index f6e5481feb..793f9e790f 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
@@ -95,9 +95,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
aimValue *= lengthBonus;
- // Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0)
- aimValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), effectiveMissCount);
+ aimValue *= calculateMissPenalty(effectiveMissCount, Attributes.AimDifficultStrainCount);
double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
@@ -140,9 +139,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
(totalHits > 2000 ? Math.Log10(totalHits / 2000.0) * 0.5 : 0.0);
speedValue *= lengthBonus;
- // Penalize misses by assessing # of misses relative to the total # of objects. Default a 3% reduction for any # of misses.
if (effectiveMissCount > 0)
- speedValue *= 0.97 * Math.Pow(1 - Math.Pow((double)effectiveMissCount / totalHits, 0.775), Math.Pow(effectiveMissCount, .875));
+ speedValue *= calculateMissPenalty(effectiveMissCount, Attributes.SpeedDifficultStrainCount);
double approachRateFactor = 0.0;
if (Attributes.ApproachRate > 10.33)
@@ -259,6 +257,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty
}
private double getComboScalingFactor() => Attributes.MaxCombo <= 0 ? 1.0 : Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(Attributes.MaxCombo, 0.8), 1.0);
+
+ private double calculateMissPenalty(double missCount, double strainCount)
+ {
+ return 0.95 / ((missCount / (3 * Math.Sqrt(strainCount))) + 1);
+ }
+
private int totalHits => countGreat + countOk + countMeh + countMiss;
private int totalSuccessfulHits => countGreat + countOk + countMeh;
}
From fd1028f3bb5c0f19ac2154974fafa528ea6e52e9 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 29 Dec 2021 23:49:07 +0000
Subject: [PATCH 0010/2493] Use clockrate in the difficult strain count method
---
.../Difficulty/OsuDifficultyCalculator.cs | 8 ++------
.../Difficulty/Skills/OsuStrainSkill.cs | 9 +++++++--
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
index 44ba6c6a58..27d97e9d75 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
@@ -40,12 +40,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1;
- int aimDifficultyStrainCount = ((OsuStrainSkill)skills[0]).RelevantDifficultStrains();
- int speedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).RelevantDifficultStrains();
-
- // Total number of strains in a map can vary by clockrate, and this needs to be corrected for.
- aimDifficultyStrainCount = (int)(aimDifficultyStrainCount * clockRate);
- speedDifficultyStrainCount = (int)(speedDifficultyStrainCount * clockRate);
+ int aimDifficultyStrainCount = ((OsuStrainSkill)skills[0]).CountDifficultStrains(clockRate);
+ int speedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).CountDifficultStrains(clockRate);
if (mods.Any(h => h is OsuModRelax))
speedRating = 0.0;
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
index 43e39482a7..fd751727a9 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
@@ -58,11 +58,16 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
return difficulty * DifficultyMultiplier;
}
- public int RelevantDifficultStrains()
+ ///
+ /// Returns the number of difficult strains.
+ /// A strain is considered difficult if it's higher than 66% of the highest strain.
+ ///
+ public int CountDifficultStrains(double clockRate)
{
List strains = GetCurrentStrainPeaks().OrderByDescending(d => d).ToList();
- return strains.Count(s => s > strains[0] * 0.66);
+ // Total number of strains in a map can vary by clockrate, and this needs to be corrected for.
+ return (int)(strains.Count(s => s > strains[0] * 0.66) * clockRate);
}
}
}
From d2b815b745b1cfaef241488c436b26fede000571 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Sun, 2 Jan 2022 19:20:20 +0000
Subject: [PATCH 0011/2493] Add miss penalty comment
---
.../Difficulty/OsuPerformanceCalculator.cs | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
index 793f9e790f..d8fe85d645 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
@@ -256,13 +256,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty
return Math.Max(countMiss, (int)Math.Floor(comboBasedMissCount));
}
+ // Miss penalty assumes that a player will miss on the relatively hard parts of a map, not the easy parts, hence the strain count.
+ private double calculateMissPenalty(double missCount, double strainCount) => 0.95 / ((missCount / (3 * Math.Sqrt(strainCount))) + 1);
+
private double getComboScalingFactor() => Attributes.MaxCombo <= 0 ? 1.0 : Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(Attributes.MaxCombo, 0.8), 1.0);
-
- private double calculateMissPenalty(double missCount, double strainCount)
- {
- return 0.95 / ((missCount / (3 * Math.Sqrt(strainCount))) + 1);
- }
-
private int totalHits => countGreat + countOk + countMeh + countMiss;
private int totalSuccessfulHits => countGreat + countOk + countMeh;
}
From 75be4e83d6a44adc7016c150b5cbd1c74d1caf34 Mon Sep 17 00:00:00 2001
From: Luminiscental
Date: Mon, 3 Jan 2022 22:22:32 +0000
Subject: [PATCH 0012/2493] Remove abusable 0.66 threshold by averaging
---
.../Difficulty/Skills/OsuStrainSkill.cs | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
index fd751727a9..1513befad5 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
@@ -59,15 +59,15 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
}
///
- /// Returns the number of difficult strains.
- /// A strain is considered difficult if it's higher than 66% of the highest strain.
+ /// Returns the number of strains above a threshold averaged as the threshold varies.
+ /// The result is scaled by clock rate as it affects the total number of strains.
///
public int CountDifficultStrains(double clockRate)
{
- List strains = GetCurrentStrainPeaks().OrderByDescending(d => d).ToList();
-
- // Total number of strains in a map can vary by clockrate, and this needs to be corrected for.
- return (int)(strains.Count(s => s > strains[0] * 0.66) * clockRate);
+ List strains = GetCurrentStrainPeaks().ToList();
+ // This is the average value of strains.Count(s => s > p * strains.Max()) for p between 0 and 1.
+ double realtimeCount = strains.Sum() / strains.Max();
+ return (int)(clockRate * realtimeCount);
}
}
}
From 132079004ca5e6df33a2bc646a52f3036edff85e Mon Sep 17 00:00:00 2001
From: Luminiscental
Date: Tue, 4 Jan 2022 12:30:05 +0000
Subject: [PATCH 0013/2493] Remove unnecessary truncation
---
osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs | 4 ++--
osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs | 4 ++--
osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs | 4 ++--
3 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
index 51842f65d5..7ab4232a19 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
@@ -25,10 +25,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty
public double SliderFactor { get; set; }
[JsonProperty("aim_difficult_strain_count")]
- public int AimDifficultStrainCount { get; set; }
+ public double AimDifficultStrainCount { get; set; }
[JsonProperty("speed_difficult_strain_count")]
- public int SpeedDifficultStrainCount { get; set; }
+ public double SpeedDifficultStrainCount { get; set; }
[JsonProperty("approach_rate")]
public double ApproachRate { get; set; }
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
index 27d97e9d75..3c039c9b7e 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
@@ -40,8 +40,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1;
- int aimDifficultyStrainCount = ((OsuStrainSkill)skills[0]).CountDifficultStrains(clockRate);
- int speedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).CountDifficultStrains(clockRate);
+ double aimDifficultyStrainCount = ((OsuStrainSkill)skills[0]).CountDifficultStrains(clockRate);
+ double speedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).CountDifficultStrains(clockRate);
if (mods.Any(h => h is OsuModRelax))
speedRating = 0.0;
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
index 1513befad5..46dc9c683b 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
@@ -62,12 +62,12 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
/// Returns the number of strains above a threshold averaged as the threshold varies.
/// The result is scaled by clock rate as it affects the total number of strains.
///
- public int CountDifficultStrains(double clockRate)
+ public double CountDifficultStrains(double clockRate)
{
List strains = GetCurrentStrainPeaks().ToList();
// This is the average value of strains.Count(s => s > p * strains.Max()) for p between 0 and 1.
double realtimeCount = strains.Sum() / strains.Max();
- return (int)(clockRate * realtimeCount);
+ return clockRate * realtimeCount;
}
}
}
From 443640a48c8bed53510947240e8337c9350d8d6d Mon Sep 17 00:00:00 2001
From: apollo <83023433+apollo-dw@users.noreply.github.com>
Date: Tue, 4 Jan 2022 16:39:30 +0000
Subject: [PATCH 0014/2493] Revert "Remove abusable 0.66 threshold by
averaging"
---
.../Difficulty/OsuDifficultyAttributes.cs | 4 ++--
.../Difficulty/OsuDifficultyCalculator.cs | 4 ++--
.../Difficulty/Skills/OsuStrainSkill.cs | 14 +++++++-------
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
index 7ab4232a19..51842f65d5 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
@@ -25,10 +25,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty
public double SliderFactor { get; set; }
[JsonProperty("aim_difficult_strain_count")]
- public double AimDifficultStrainCount { get; set; }
+ public int AimDifficultStrainCount { get; set; }
[JsonProperty("speed_difficult_strain_count")]
- public double SpeedDifficultStrainCount { get; set; }
+ public int SpeedDifficultStrainCount { get; set; }
[JsonProperty("approach_rate")]
public double ApproachRate { get; set; }
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
index 3c039c9b7e..27d97e9d75 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
@@ -40,8 +40,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1;
- double aimDifficultyStrainCount = ((OsuStrainSkill)skills[0]).CountDifficultStrains(clockRate);
- double speedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).CountDifficultStrains(clockRate);
+ int aimDifficultyStrainCount = ((OsuStrainSkill)skills[0]).CountDifficultStrains(clockRate);
+ int speedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).CountDifficultStrains(clockRate);
if (mods.Any(h => h is OsuModRelax))
speedRating = 0.0;
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
index 46dc9c683b..fd751727a9 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
@@ -59,15 +59,15 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
}
///
- /// Returns the number of strains above a threshold averaged as the threshold varies.
- /// The result is scaled by clock rate as it affects the total number of strains.
+ /// Returns the number of difficult strains.
+ /// A strain is considered difficult if it's higher than 66% of the highest strain.
///
- public double CountDifficultStrains(double clockRate)
+ public int CountDifficultStrains(double clockRate)
{
- List strains = GetCurrentStrainPeaks().ToList();
- // This is the average value of strains.Count(s => s > p * strains.Max()) for p between 0 and 1.
- double realtimeCount = strains.Sum() / strains.Max();
- return clockRate * realtimeCount;
+ List strains = GetCurrentStrainPeaks().OrderByDescending(d => d).ToList();
+
+ // Total number of strains in a map can vary by clockrate, and this needs to be corrected for.
+ return (int)(strains.Count(s => s > strains[0] * 0.66) * clockRate);
}
}
}
From dcb969316dd5a7e2bd1b06ebd1450a0ab56ef831 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Tue, 4 Jan 2022 17:33:23 +0000
Subject: [PATCH 0015/2493] Weight difficult strain count against the top
strain
---
osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
index 46dc9c683b..3e0fccb6c4 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
@@ -59,14 +59,15 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
}
///
- /// Returns the number of strains above a threshold averaged as the threshold varies.
+ /// Returns the number of strains weighted against the top strain.
/// The result is scaled by clock rate as it affects the total number of strains.
///
public double CountDifficultStrains(double clockRate)
{
List strains = GetCurrentStrainPeaks().ToList();
- // This is the average value of strains.Count(s => s > p * strains.Max()) for p between 0 and 1.
- double realtimeCount = strains.Sum() / strains.Max();
+ double topStrain = strains.Max();
+
+ double realtimeCount = strains.Sum(s => Math.Pow(s / topStrain, 4));
return clockRate * realtimeCount;
}
}
From 400abc147b1f3742061125d91e80a62f5e1333f7 Mon Sep 17 00:00:00 2001
From: Dan Balasescu
Date: Thu, 6 Jan 2022 16:28:04 +0900
Subject: [PATCH 0016/2493] Add attribute ids to mapping functions
---
osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs | 4 ++++
osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs | 2 ++
2 files changed, 6 insertions(+)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
index 7ab4232a19..7041acc16c 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyAttributes.cs
@@ -60,6 +60,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
yield return (ATTRIB_ID_FLASHLIGHT, FlashlightDifficulty);
yield return (ATTRIB_ID_SLIDER_FACTOR, SliderFactor);
+ yield return (ATTRIB_ID_AIM_DIFFICULT_STRAIN_COUNT, AimDifficultStrainCount);
+ yield return (ATTRIB_ID_SPEED_DIFFICULT_STRAIN_COUNT, SpeedDifficultStrainCount);
}
public override void FromDatabaseAttributes(IReadOnlyDictionary values)
@@ -74,6 +76,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
StarRating = values[ATTRIB_ID_DIFFICULTY];
FlashlightDifficulty = values.GetValueOrDefault(ATTRIB_ID_FLASHLIGHT);
SliderFactor = values[ATTRIB_ID_SLIDER_FACTOR];
+ AimDifficultStrainCount = values[ATTRIB_ID_AIM_DIFFICULT_STRAIN_COUNT];
+ SpeedDifficultStrainCount = values[ATTRIB_ID_SPEED_DIFFICULT_STRAIN_COUNT];
}
#region Newtonsoft.Json implicit ShouldSerialize() methods
diff --git a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs
index 991b567f57..803a5bdac7 100644
--- a/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs
+++ b/osu.Game/Rulesets/Difficulty/DifficultyAttributes.cs
@@ -24,6 +24,8 @@ namespace osu.Game.Rulesets.Difficulty
protected const int ATTRIB_ID_SCORE_MULTIPLIER = 15;
protected const int ATTRIB_ID_FLASHLIGHT = 17;
protected const int ATTRIB_ID_SLIDER_FACTOR = 19;
+ protected const int ATTRIB_ID_AIM_DIFFICULT_STRAIN_COUNT = 21;
+ protected const int ATTRIB_ID_SPEED_DIFFICULT_STRAIN_COUNT = 23;
///
/// The mods which were applied to the beatmap.
From 598946737f07c0f2a3ac7523666a868722906db1 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Wed, 12 Jan 2022 14:38:53 +0000
Subject: [PATCH 0017/2493] Reword comment and rename argument
---
.../Difficulty/OsuPerformanceCalculator.cs | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
index d8fe85d645..52658dfe38 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
@@ -256,9 +256,10 @@ namespace osu.Game.Rulesets.Osu.Difficulty
return Math.Max(countMiss, (int)Math.Floor(comboBasedMissCount));
}
- // Miss penalty assumes that a player will miss on the relatively hard parts of a map, not the easy parts, hence the strain count.
- private double calculateMissPenalty(double missCount, double strainCount) => 0.95 / ((missCount / (3 * Math.Sqrt(strainCount))) + 1);
-
+ // Miss penalty assumes that a player will miss on the hardest parts of a map,
+ // so we use the amount of relatively difficult sections to adjust miss penalty
+ // to make it more punishing on maps with lower amount of hard sections.
+ private double calculateMissPenalty(double missCount, double difficultStrainCount) => 0.95 / ((missCount / (3 * Math.Sqrt(difficultStrainCount))) + 1);
private double getComboScalingFactor() => Attributes.MaxCombo <= 0 ? 1.0 : Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(Attributes.MaxCombo, 0.8), 1.0);
private int totalHits => countGreat + countOk + countMeh + countMiss;
private int totalSuccessfulHits => countGreat + countOk + countMeh;
From da31ca17e7c12a2922ab83657df4d8d9b6826bbd Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Mon, 14 Feb 2022 01:53:03 +0000
Subject: [PATCH 0018/2493] Use note strains instead of sectional strains
---
osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs | 2 ++
osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs | 7 ++++---
osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs | 6 +++++-
3 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
index a6301aed6d..3486db04af 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Aim.cs
@@ -159,6 +159,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
currentStrain *= strainDecay(current.DeltaTime);
currentStrain += strainValueOf(current) * skillMultiplier;
+ objectStrains.Add(currentStrain);
+
return currentStrain;
}
}
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
index 3e0fccb6c4..94e2c9d774 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
@@ -28,6 +28,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
///
protected virtual double DifficultyMultiplier => 1.06;
+ protected List objectStrains = new List();
+
protected OsuStrainSkill(Mod[] mods)
: base(mods)
{
@@ -64,10 +66,9 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
///
public double CountDifficultStrains(double clockRate)
{
- List strains = GetCurrentStrainPeaks().ToList();
- double topStrain = strains.Max();
+ double topStrain = objectStrains.Max();
- double realtimeCount = strains.Sum(s => Math.Pow(s / topStrain, 4));
+ double realtimeCount = objectStrains.Sum(s => Math.Pow(s / topStrain, 4));
return clockRate * realtimeCount;
}
}
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
index 06d1ef7346..108edc6f2d 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/Speed.cs
@@ -173,7 +173,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
currentRhythm = calculateRhythmBonus(current);
- return currentStrain * currentRhythm;
+ double totalStrain = currentStrain * currentRhythm;
+
+ objectStrains.Add(totalStrain);
+
+ return totalStrain;
}
}
}
From 94a46ab640b36c3ca58f03eaf2644ab51c3abd51 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Mon, 14 Feb 2022 02:02:46 +0000
Subject: [PATCH 0019/2493] Rescale miss penalty for note strains
---
osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
index cf2116cc5d..cf1af18d39 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
@@ -259,7 +259,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
// Miss penalty assumes that a player will miss on the hardest parts of a map,
// so we use the amount of relatively difficult sections to adjust miss penalty
// to make it more punishing on maps with lower amount of hard sections.
- private double calculateMissPenalty(double missCount, double difficultStrainCount) => 0.95 / ((missCount / (3 * Math.Sqrt(difficultStrainCount))) + 1);
+ private double calculateMissPenalty(double missCount, double difficultStrainCount) => 0.94 / ((missCount / (2 * Math.Sqrt(difficultStrainCount))) + 1);
private double getComboScalingFactor() => Attributes.MaxCombo <= 0 ? 1.0 : Math.Min(Math.Pow(scoreMaxCombo, 0.8) / Math.Pow(Attributes.MaxCombo, 0.8), 1.0);
private int totalHits => countGreat + countOk + countMeh + countMiss;
private int totalSuccessfulHits => countGreat + countOk + countMeh;
From c18df86720244a7d5bba22bc502afd4f959c9082 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Sat, 19 Feb 2022 15:33:28 +0000
Subject: [PATCH 0020/2493] Remove clockrate factor
---
osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs | 4 ++--
osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs | 5 ++---
2 files changed, 4 insertions(+), 5 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
index 3c039c9b7e..788b515d7f 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuDifficultyCalculator.cs
@@ -40,8 +40,8 @@ namespace osu.Game.Rulesets.Osu.Difficulty
double sliderFactor = aimRating > 0 ? aimRatingNoSliders / aimRating : 1;
- double aimDifficultyStrainCount = ((OsuStrainSkill)skills[0]).CountDifficultStrains(clockRate);
- double speedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).CountDifficultStrains(clockRate);
+ double aimDifficultyStrainCount = ((OsuStrainSkill)skills[0]).CountDifficultStrains();
+ double speedDifficultyStrainCount = ((OsuStrainSkill)skills[2]).CountDifficultStrains();
if (mods.Any(h => h is OsuModRelax))
speedRating = 0.0;
diff --git a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
index 94e2c9d774..1124c4466f 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/Skills/OsuStrainSkill.cs
@@ -64,12 +64,11 @@ namespace osu.Game.Rulesets.Osu.Difficulty.Skills
/// Returns the number of strains weighted against the top strain.
/// The result is scaled by clock rate as it affects the total number of strains.
///
- public double CountDifficultStrains(double clockRate)
+ public double CountDifficultStrains()
{
double topStrain = objectStrains.Max();
- double realtimeCount = objectStrains.Sum(s => Math.Pow(s / topStrain, 4));
- return clockRate * realtimeCount;
+ return objectStrains.Sum(s => Math.Pow(s / topStrain, 4));
}
}
}
From 2f335a76dca77b0304f5ff21ed7ca2c8e1130757 Mon Sep 17 00:00:00 2001
From: apollo-dw <83023433+apollo-dw@users.noreply.github.com>
Date: Thu, 17 Mar 2022 22:08:56 +0000
Subject: [PATCH 0021/2493] Switch to using osuAttributes
---
osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
index 48b4f53a3e..964bd73e81 100644
--- a/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
+++ b/osu.Game.Rulesets.Osu/Difficulty/OsuPerformanceCalculator.cs
@@ -92,7 +92,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
aimValue *= lengthBonus;
if (effectiveMissCount > 0)
- aimValue *= calculateMissPenalty(effectiveMissCount, Attributes.AimDifficultStrainCount);
+ aimValue *= calculateMissPenalty(effectiveMissCount, attributes.AimDifficultStrainCount);
double approachRateFactor = 0.0;
if (attributes.ApproachRate > 10.33)
@@ -136,7 +136,7 @@ namespace osu.Game.Rulesets.Osu.Difficulty
speedValue *= lengthBonus;
if (effectiveMissCount > 0)
- speedValue *= calculateMissPenalty(effectiveMissCount, Attributes.SpeedDifficultStrainCount);
+ speedValue *= calculateMissPenalty(effectiveMissCount, attributes.SpeedDifficultStrainCount);
double approachRateFactor = 0.0;
if (attributes.ApproachRate > 10.33)
From c907751a5cf4e53c7910212e9ff0643a3f9c36f5 Mon Sep 17 00:00:00 2001
From: mk56-spn
Date: Mon, 16 Jan 2023 16:57:18 +0100
Subject: [PATCH 0022/2493] Set up test scene and basic LeaderBoardScoreV2.cs
shape
---
.../SongSelect/TestSceneLeaderboardScoreV2.cs | 26 +++++++++++
.../Online/Leaderboards/LeaderBoardScoreV2.cs | 43 +++++++++++++++++++
2 files changed, 69 insertions(+)
create mode 100644 osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs
create mode 100644 osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs
diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs
new file mode 100644
index 0000000000..2c631e943d
--- /dev/null
+++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs
@@ -0,0 +1,26 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Game.Online.Leaderboards;
+
+namespace osu.Game.Tests.Visual.SongSelect
+{
+ public partial class TestSceneLeaderboardScoreV2 : OsuTestScene
+ {
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ Child = new Container
+ {
+ Width = 900,
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ AutoSizeAxes = Axes.Y,
+ Child = new LeaderBoardScoreV2()
+ };
+ }
+ }
+}
diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs
new file mode 100644
index 0000000000..07184b8474
--- /dev/null
+++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs
@@ -0,0 +1,43 @@
+// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
+// See the LICENCE file in the repository root for full licence text.
+
+using osu.Framework.Allocation;
+using osu.Framework.Graphics;
+using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Shapes;
+using osu.Game.Graphics.Containers;
+using osuTK;
+
+namespace osu.Game.Online.Leaderboards
+{
+ public partial class LeaderBoardScoreV2 : OsuClickableContainer
+ {
+ private const int HEIGHT = 60;
+ private const int corner_radius = 10;
+
+ private static readonly Vector2 shear = new Vector2(0.15f, 0);
+
+ private Container content = null!;
+
+ [BackgroundDependencyLoader]
+ private void load()
+ {
+ Shear = shear;
+ RelativeSizeAxes = Axes.X;
+ Height = HEIGHT;
+ Child = content = new Container
+ {
+ Masking = true,
+ CornerRadius = corner_radius,
+ RelativeSizeAxes = Axes.Both,
+ Children = new Drawable[]
+ {
+ new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ }
+ }
+ };
+ }
+ }
+}
From b7584b4a02471c5d8894f30189da61075b8e46ec Mon Sep 17 00:00:00 2001
From: mk56-spn
Date: Mon, 16 Jan 2023 17:15:37 +0100
Subject: [PATCH 0023/2493] Add grid container with sections, add background
colours and hover logic
---
.../SongSelect/TestSceneLeaderboardScoreV2.cs | 10 ++-
.../Online/Leaderboards/LeaderBoardScoreV2.cs | 78 ++++++++++++++++++-
2 files changed, 85 insertions(+), 3 deletions(-)
diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs
index 2c631e943d..377bc79605 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs
@@ -5,6 +5,7 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Game.Online.Leaderboards;
+using osuTK;
namespace osu.Game.Tests.Visual.SongSelect
{
@@ -13,13 +14,18 @@ namespace osu.Game.Tests.Visual.SongSelect
[BackgroundDependencyLoader]
private void load()
{
- Child = new Container
+ Child = new FillFlowContainer
{
Width = 900,
Anchor = Anchor.Centre,
Origin = Anchor.Centre,
+ Spacing = new Vector2(0, 10),
AutoSizeAxes = Axes.Y,
- Child = new LeaderBoardScoreV2()
+ Children = new Drawable[]
+ {
+ new LeaderBoardScoreV2(),
+ new LeaderBoardScoreV2(true)
+ }
};
}
}
diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs
index 07184b8474..7a56657365 100644
--- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs
+++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs
@@ -5,23 +5,43 @@ using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Shapes;
+using osu.Framework.Input.Events;
using osu.Game.Graphics.Containers;
+using osu.Game.Overlays;
using osuTK;
namespace osu.Game.Online.Leaderboards
{
public partial class LeaderBoardScoreV2 : OsuClickableContainer
{
+ private readonly bool isPersonalBest;
private const int HEIGHT = 60;
private const int corner_radius = 10;
+ private const int transition_duration = 200;
+
+ private Colour4 foregroundColour;
+ private Colour4 backgroundColour;
private static readonly Vector2 shear = new Vector2(0.15f, 0);
+ [Cached]
+ private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine);
+
private Container content = null!;
+ private Box background = null!;
+ private Box foreground = null!;
+
+ public LeaderBoardScoreV2(bool isPersonalBest = false)
+ {
+ this.isPersonalBest = isPersonalBest;
+ }
[BackgroundDependencyLoader]
private void load()
{
+ foregroundColour = isPersonalBest ? colourProvider.Background1 : colourProvider.Background5;
+ backgroundColour = isPersonalBest ? colourProvider.Background2 : colourProvider.Background4;
+
Shear = shear;
RelativeSizeAxes = Axes.X;
Height = HEIGHT;
@@ -32,12 +52,68 @@ namespace osu.Game.Online.Leaderboards
RelativeSizeAxes = Axes.Both,
Children = new Drawable[]
{
- new Box
+ background = new Box
{
RelativeSizeAxes = Axes.Both,
+ Colour = backgroundColour
+ },
+ new GridContainer
+ {
+ RelativeSizeAxes = Axes.Both,
+ ColumnDimensions = new[]
+ {
+ new Dimension(GridSizeMode.Absolute, 65),
+ new Dimension(),
+ new Dimension(GridSizeMode.Absolute, 176)
+ },
+ Content = new[]
+ {
+ new[]
+ {
+ Empty(),
+ createCentreContent(),
+ Empty(),
+ }
+ }
}
}
};
}
+
+ private Container createCentreContent() =>
+ new Container
+ {
+ Anchor = Anchor.CentreLeft,
+ Origin = Anchor.CentreLeft,
+ Masking = true,
+ CornerRadius = corner_radius,
+ RelativeSizeAxes = Axes.Both,
+ Children = new Drawable[]
+ {
+ foreground = new Box
+ {
+ RelativeSizeAxes = Axes.Both,
+ Colour = foregroundColour
+ }
+ }
+ };
+
+ protected override bool OnHover(HoverEvent e)
+ {
+ updateState();
+ return base.OnHover(e);
+ }
+
+ protected override void OnHoverLost(HoverLostEvent e)
+ {
+ updateState();
+ base.OnHoverLost(e);
+ }
+
+ private void updateState()
+ {
+ foreground.FadeColour(IsHovered ? foregroundColour.Lighten(0.2f) : foregroundColour, transition_duration, Easing.OutQuint);
+ background.FadeColour(IsHovered ? backgroundColour.Lighten(0.2f) : backgroundColour, transition_duration, Easing.OutQuint);
+ }
}
}
From 9ea151539670ad5bb8175026c8fcaeba6059e695 Mon Sep 17 00:00:00 2001
From: mk56-spn
Date: Mon, 16 Jan 2023 17:35:27 +0100
Subject: [PATCH 0024/2493] setup up rank and score logic flow
---
.../SongSelect/TestSceneLeaderboardScoreV2.cs | 60 ++++++++++++++++++-
.../Online/Leaderboards/LeaderBoardScoreV2.cs | 45 +++++++++++++-
2 files changed, 100 insertions(+), 5 deletions(-)
diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs
index 377bc79605..13eaf5417d 100644
--- a/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs
+++ b/osu.Game.Tests/Visual/SongSelect/TestSceneLeaderboardScoreV2.cs
@@ -4,7 +4,13 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
+using osu.Game.Online.API.Requests.Responses;
using osu.Game.Online.Leaderboards;
+using osu.Game.Rulesets.Mods;
+using osu.Game.Rulesets.Osu;
+using osu.Game.Rulesets.Osu.Mods;
+using osu.Game.Scoring;
+using osu.Game.Users;
using osuTK;
namespace osu.Game.Tests.Visual.SongSelect
@@ -14,6 +20,56 @@ namespace osu.Game.Tests.Visual.SongSelect
[BackgroundDependencyLoader]
private void load()
{
+ var scores = new[]
+ {
+ new ScoreInfo
+ {
+ Position = 999,
+ Rank = ScoreRank.XH,
+ Accuracy = 1,
+ MaxCombo = 244,
+ TotalScore = 1707827,
+ Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), },
+ Ruleset = new OsuRuleset().RulesetInfo,
+ User = new APIUser
+ {
+ Id = 6602580,
+ Username = @"waaiiru",
+ CountryCode = CountryCode.ES,
+ },
+ },
+ new ScoreInfo
+ {
+ Position = 110000,
+ Rank = ScoreRank.X,
+ Accuracy = 1,
+ MaxCombo = 244,
+ TotalScore = 1707827,
+ Ruleset = new OsuRuleset().RulesetInfo,
+ User = new APIUser
+ {
+ Id = 4608074,
+ Username = @"Skycries",
+ CountryCode = CountryCode.BR,
+ },
+ },
+ new ScoreInfo
+ {
+ Position = 22333,
+ Rank = ScoreRank.S,
+ Accuracy = 1,
+ MaxCombo = 244,
+ TotalScore = 1707827,
+ Ruleset = new OsuRuleset().RulesetInfo,
+ User = new APIUser
+ {
+ Id = 1541390,
+ Username = @"Toukai",
+ CountryCode = CountryCode.CA,
+ },
+ }
+ };
+
Child = new FillFlowContainer
{
Width = 900,
@@ -23,8 +79,8 @@ namespace osu.Game.Tests.Visual.SongSelect
AutoSizeAxes = Axes.Y,
Children = new Drawable[]
{
- new LeaderBoardScoreV2(),
- new LeaderBoardScoreV2(true)
+ new LeaderBoardScoreV2(scores[0], 1),
+ new LeaderBoardScoreV2(scores[2], 3, true)
}
};
}
diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs
index 7a56657365..d526172861 100644
--- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs
+++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs
@@ -4,21 +4,32 @@
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
+using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
using osu.Framework.Input.Events;
+using osu.Framework.Localisation;
+using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
+using osu.Game.Graphics.Sprites;
using osu.Game.Overlays;
+using osu.Game.Scoring;
+using osu.Game.Utils;
using osuTK;
namespace osu.Game.Online.Leaderboards
{
public partial class LeaderBoardScoreV2 : OsuClickableContainer
{
- private readonly bool isPersonalBest;
+ private readonly ScoreInfo score;
+
private const int HEIGHT = 60;
private const int corner_radius = 10;
private const int transition_duration = 200;
+ private readonly int? rank;
+
+ private readonly bool isPersonalBest;
+
private Colour4 foregroundColour;
private Colour4 backgroundColour;
@@ -31,8 +42,10 @@ namespace osu.Game.Online.Leaderboards
private Box background = null!;
private Box foreground = null!;
- public LeaderBoardScoreV2(bool isPersonalBest = false)
+ public LeaderBoardScoreV2(ScoreInfo score, int? rank, bool isPersonalBest = false)
{
+ this.score = score;
+ this.rank = rank;
this.isPersonalBest = isPersonalBest;
}
@@ -70,7 +83,14 @@ namespace osu.Game.Online.Leaderboards
{
new[]
{
- Empty(),
+ new RankLabel(rank)
+ {
+ Shear = -shear,
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ RelativeSizeAxes = Axes.Y,
+ Width = 35
+ },
createCentreContent(),
Empty(),
}
@@ -115,5 +135,24 @@ namespace osu.Game.Online.Leaderboards
foreground.FadeColour(IsHovered ? foregroundColour.Lighten(0.2f) : foregroundColour, transition_duration, Easing.OutQuint);
background.FadeColour(IsHovered ? backgroundColour.Lighten(0.2f) : backgroundColour, transition_duration, Easing.OutQuint);
}
+
+ private partial class RankLabel : Container, IHasTooltip
+ {
+ public RankLabel(int? rank)
+ {
+ if (rank >= 1000)
+ TooltipText = $"#{rank:N0}";
+
+ Child = new OsuSpriteText
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Font = OsuFont.GetFont(size: 20, weight: FontWeight.SemiBold, italics: true),
+ Text = rank == null ? "-" : rank.Value.FormatRank().Insert(0, "#")
+ };
+ }
+
+ public LocalisableString TooltipText { get; }
+ }
}
}
From 9178e3fd7dba9d8a2fde74ecbd8c691b9f646f47 Mon Sep 17 00:00:00 2001
From: mk56-spn
Date: Mon, 16 Jan 2023 18:03:38 +0100
Subject: [PATCH 0025/2493] Add right side content
---
.../Online/Leaderboards/LeaderBoardScoreV2.cs | 128 +++++++++++++++++-
osu.Game/Rulesets/UI/ModSwitchTiny.cs | 16 +--
2 files changed, 132 insertions(+), 12 deletions(-)
diff --git a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs
index d526172861..ed8536a2bf 100644
--- a/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs
+++ b/osu.Game/Online/Leaderboards/LeaderBoardScoreV2.cs
@@ -1,24 +1,34 @@
// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence.
// See the LICENCE file in the repository root for full licence text.
+using System.Collections.Generic;
+using System.Linq;
using osu.Framework.Allocation;
using osu.Framework.Graphics;
using osu.Framework.Graphics.Containers;
using osu.Framework.Graphics.Cursor;
using osu.Framework.Graphics.Shapes;
+using osu.Framework.Graphics.UserInterface;
using osu.Framework.Input.Events;
using osu.Framework.Localisation;
+using osu.Framework.Platform;
+using osu.Game.Database;
using osu.Game.Graphics;
using osu.Game.Graphics.Containers;
using osu.Game.Graphics.Sprites;
+using osu.Game.Graphics.UserInterface;
using osu.Game.Overlays;
+using osu.Game.Resources.Localisation.Web;
+using osu.Game.Rulesets.Mods;
+using osu.Game.Rulesets.UI;
using osu.Game.Scoring;
+using osu.Game.Screens.Select;
using osu.Game.Utils;
using osuTK;
namespace osu.Game.Online.Leaderboards
{
- public partial class LeaderBoardScoreV2 : OsuClickableContainer
+ public partial class LeaderBoardScoreV2 : OsuClickableContainer, IHasContextMenu
{
private readonly ScoreInfo score;
@@ -38,10 +48,25 @@ namespace osu.Game.Online.Leaderboards
[Cached]
private OverlayColourProvider colourProvider { get; set; } = new OverlayColourProvider(OverlayColourScheme.Aquamarine);
+ [Resolved]
+ private SongSelect? songSelect { get; set; }
+
+ [Resolved]
+ private IDialogOverlay? dialogOverlay { get; set; }
+
+ [Resolved]
+ private Storage storage { get; set; } = null!;
+
private Container content = null!;
private Box background = null!;
private Box foreground = null!;
+ protected Container RankContainer { get; private set; } = null!;
+ private FillFlowContainer modsContainer = null!;
+
+ private OsuSpriteText scoreText = null!;
+ private Drawable scoreRank = null!;
+
public LeaderBoardScoreV2(ScoreInfo score, int? rank, bool isPersonalBest = false)
{
this.score = score;
@@ -50,7 +75,7 @@ namespace osu.Game.Online.Leaderboards
}
[BackgroundDependencyLoader]
- private void load()
+ private void load(ScoreManager scoreManager)
{
foregroundColour = isPersonalBest ? colourProvider.Background1 : colourProvider.Background5;
backgroundColour = isPersonalBest ? colourProvider.Background2 : colourProvider.Background4;
@@ -81,7 +106,7 @@ namespace osu.Game.Online.Leaderboards
},
Content = new[]
{
- new[]
+ new Drawable[]
{
new RankLabel(rank)
{
@@ -92,12 +117,15 @@ namespace osu.Game.Online.Leaderboards
Width = 35
},
createCentreContent(),
- Empty(),
+ createRightSideContent(scoreManager)
}
}
}
}
};
+
+ modsContainer.Spacing = new Vector2(modsContainer.Children.Count > 5 ? -20 : 2, 0);
+ modsContainer.Padding = new MarginPadding { Top = modsContainer.Children.Count > 0 ? 4 : 0 };
}
private Container createCentreContent() =>
@@ -118,6 +146,63 @@ namespace osu.Game.Online.Leaderboards
}
};
+ private FillFlowContainer createRightSideContent(ScoreManager scoreManager) =>
+ new FillFlowContainer
+ {
+ Padding = new MarginPadding { Left = 11, Right = 15 },
+ Y = -5,
+ AutoSizeAxes = Axes.Y,
+ RelativeSizeAxes = Axes.X,
+ Anchor = Anchor.CentreLeft,
+ Origin = Anchor.CentreLeft,
+ Direction = FillDirection.Vertical,
+ Spacing = new Vector2(13, 0f),
+ Children = new Drawable[]
+ {
+ new Container
+ {
+ AutoSizeAxes = Axes.Y,
+ RelativeSizeAxes = Axes.X,
+ Children = new Drawable[]
+ {
+ scoreText = new OsuSpriteText
+ {
+ Shear = -shear,
+ Current = scoreManager.GetBindableTotalScoreString(score),
+
+ //Does not match figma, adjusted to allow 8 digits to fit comfortably
+ Font = OsuFont.GetFont(size: 28, weight: FontWeight.SemiBold, fixedWidth: false),
+ },
+ RankContainer = new Container
+ {
+ BypassAutoSizeAxes = Axes.Both,
+ Y = 2,
+ Shear = -shear,
+ Anchor = Anchor.CentreRight,
+ Origin = Anchor.CentreRight,
+ AutoSizeAxes = Axes.Both,
+ Children = new[]
+ {
+ scoreRank = new UpdateableRank(score.Rank)
+ {
+ Anchor = Anchor.Centre,
+ Origin = Anchor.Centre,
+ Size = new Vector2(32)
+ }
+ }
+ }
+ }
+ },
+ modsContainer = new FillFlowContainer
+ {
+ Shear = -shear,
+ AutoSizeAxes = Axes.Both,
+ Direction = FillDirection.Horizontal,
+ ChildrenEnumerable = score.Mods.Select(mod => new ColouredModSwitchTiny(mod) { Scale = new Vector2(0.375f) })
+ }
+ }
+ };
+
protected override bool OnHover(HoverEvent e)
{
updateState();
@@ -154,5 +239,40 @@ namespace osu.Game.Online.Leaderboards
public LocalisableString TooltipText { get; }
}
+
+ private partial class ColouredModSwitchTiny : ModSwitchTiny
+ {
+ [Resolved]
+ private OsuColour colours { get; set; } = null!;
+
+ public ColouredModSwitchTiny(IMod mod)
+ : base(mod)
+ {
+ }
+
+ protected override void UpdateState()
+ {
+ AcronymText.Colour = Colour4.FromHex("#555555");
+ Background.Colour = colours.Yellow;
+ }
+ }
+
+ public MenuItem[] ContextMenuItems
+ {
+ get
+ {
+ List