diff --git a/osu.Game.Rulesets.Taiko/Difficulty/Evaluators/RhythmEvaluator.cs b/osu.Game.Rulesets.Taiko/Difficulty/Evaluators/RhythmEvaluator.cs
index e7d82453eb..22321a8f6e 100644
--- a/osu.Game.Rulesets.Taiko/Difficulty/Evaluators/RhythmEvaluator.cs
+++ b/osu.Game.Rulesets.Taiko/Difficulty/Evaluators/RhythmEvaluator.cs
@@ -14,48 +14,64 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Evaluators
public class RhythmEvaluator
{
///
- /// Multiplier for a given denominator term.
+ /// Evaluate the difficulty of a hitobject considering its interval change.
///
- private static double termPenalty(double ratio, int denominator, double power, double multiplier)
+ public static double EvaluateDifficultyOf(DifficultyHitObject hitObject, double hitWindow)
{
- return -multiplier * Math.Pow(Math.Cos(denominator * Math.PI * ratio), power);
- }
+ TaikoDifficultyHitObjectRhythm rhythm = ((TaikoDifficultyHitObject)hitObject).Rhythm;
+ double difficulty = 0.0d;
- ///
- /// Validates the ratio by ensuring it is a normal number in cases where maps breach regular mapping conditions.
- ///
- private static double validateRatio(double ratio)
- {
- return double.IsNormal(ratio) ? ratio : 0;
- }
+ double sameRhythm = 0;
+ double samePattern = 0;
+ double intervalPenalty = 0;
- ///
- /// Calculates the difficulty of a given ratio using a combination of periodic penalties and bonuses.
- ///
- private static double ratioDifficulty(double ratio, int terms = 8)
- {
- double difficulty = 0;
- ratio = validateRatio(ratio);
-
- for (int i = 1; i <= terms; ++i)
+ if (rhythm.SameRhythmHitObjects?.FirstHitObject == hitObject) // Difficulty for SameRhythmHitObjects
{
- difficulty += termPenalty(ratio, i, 4, 1);
+ sameRhythm += 10.0 * evaluateDifficultyOf(rhythm.SameRhythmHitObjects, hitWindow);
+ intervalPenalty = repeatedIntervalPenalty(rhythm.SameRhythmHitObjects, hitWindow);
}
- difficulty += terms / (1 + ratio);
+ if (rhythm.SamePatterns?.FirstHitObject == hitObject) // Difficulty for SamePatterns
+ samePattern += 1.15 * ratioDifficulty(rhythm.SamePatterns.IntervalRatio);
- // Give bonus to near-1 ratios
- difficulty += DifficultyCalculationUtils.BellCurve(ratio, 1, 0.5);
-
- // Penalize ratios that are VERY near 1
- difficulty -= DifficultyCalculationUtils.BellCurve(ratio, 1, 0.3);
-
- difficulty = Math.Max(difficulty, 0);
- difficulty /= Math.Sqrt(8);
+ difficulty += Math.Max(sameRhythm, samePattern) * intervalPenalty;
return difficulty;
}
+ private static double evaluateDifficultyOf(SameRhythmHitObjects sameRhythmHitObjects, double hitWindow)
+ {
+ double intervalDifficulty = ratioDifficulty(sameRhythmHitObjects.HitObjectIntervalRatio);
+ double? previousInterval = sameRhythmHitObjects.Previous?.HitObjectInterval;
+
+ intervalDifficulty *= repeatedIntervalPenalty(sameRhythmHitObjects, hitWindow);
+
+ // If a previous interval exists and there are multiple hit objects in the sequence:
+ if (previousInterval != null && sameRhythmHitObjects.Children.Count > 1)
+ {
+ double expectedDurationFromPrevious = (double)previousInterval * sameRhythmHitObjects.Children.Count;
+ double durationDifference = sameRhythmHitObjects.Duration - expectedDurationFromPrevious;
+
+ if (durationDifference > 0)
+ {
+ intervalDifficulty *= DifficultyCalculationUtils.Logistic(
+ durationDifference / hitWindow,
+ midpointOffset: 0.7,
+ multiplier: 1.0,
+ maxValue: 1);
+ }
+ }
+
+ // Penalise patterns that can be hit within a single hit window.
+ intervalDifficulty *= DifficultyCalculationUtils.Logistic(
+ sameRhythmHitObjects.Duration / hitWindow,
+ midpointOffset: 0.6,
+ multiplier: 1,
+ maxValue: 1);
+
+ return Math.Pow(intervalDifficulty, 0.75);
+ }
+
///
/// Determines if the changes in hit object intervals is consistent based on a given threshold.
///
@@ -102,68 +118,39 @@ namespace osu.Game.Rulesets.Taiko.Difficulty.Evaluators
}
}
- private static double evaluateDifficultyOf(SameRhythmHitObjects sameRhythmHitObjects, double hitWindow)
- {
- double intervalDifficulty = ratioDifficulty(sameRhythmHitObjects.HitObjectIntervalRatio);
- double? previousInterval = sameRhythmHitObjects.Previous?.HitObjectInterval;
-
- intervalDifficulty *= repeatedIntervalPenalty(sameRhythmHitObjects, hitWindow);
-
- // If a previous interval exists and there are multiple hit objects in the sequence:
- if (previousInterval != null && sameRhythmHitObjects.Children.Count > 1)
- {
- double expectedDurationFromPrevious = (double)previousInterval * sameRhythmHitObjects.Children.Count;
- double durationDifference = sameRhythmHitObjects.Duration - expectedDurationFromPrevious;
-
- if (durationDifference > 0)
- {
- intervalDifficulty *= DifficultyCalculationUtils.Logistic(
- durationDifference / hitWindow,
- midpointOffset: 0.7,
- multiplier: 1.0,
- maxValue: 1);
- }
- }
-
- // Penalise patterns that can be hit within a single hit window.
- intervalDifficulty *= DifficultyCalculationUtils.Logistic(
- sameRhythmHitObjects.Duration / hitWindow,
- midpointOffset: 0.6,
- multiplier: 1,
- maxValue: 1);
-
- return Math.Pow(intervalDifficulty, 0.75);
- }
-
- private static double evaluateDifficultyOf(SamePatterns samePatterns)
- {
- return ratioDifficulty(samePatterns.IntervalRatio);
- }
-
///
- /// Evaluate the difficulty of a hitobject considering its interval change.
+ /// Calculates the difficulty of a given ratio using a combination of periodic penalties and bonuses.
///
- public static double EvaluateDifficultyOf(DifficultyHitObject hitObject, double hitWindow)
+ private static double ratioDifficulty(double ratio, int terms = 8)
{
- TaikoDifficultyHitObjectRhythm rhythm = ((TaikoDifficultyHitObject)hitObject).Rhythm;
- double difficulty = 0.0d;
+ double difficulty = 0;
- double sameRhythm = 0;
- double samePattern = 0;
- double intervalPenalty = 0;
+ // Validate the ratio by ensuring it is a normal number in cases where maps breach regular mapping conditions.
+ ratio = double.IsNormal(ratio) ? ratio : 0;
- if (rhythm.SameRhythmHitObjects?.FirstHitObject == hitObject) // Difficulty for SameRhythmHitObjects
+ for (int i = 1; i <= terms; ++i)
{
- sameRhythm += 10.0 * evaluateDifficultyOf(rhythm.SameRhythmHitObjects, hitWindow);
- intervalPenalty = repeatedIntervalPenalty(rhythm.SameRhythmHitObjects, hitWindow);
+ difficulty += termPenalty(ratio, i, 4, 1);
}
- if (rhythm.SamePatterns?.FirstHitObject == hitObject) // Difficulty for SamePatterns
- samePattern += 1.15 * evaluateDifficultyOf(rhythm.SamePatterns);
+ difficulty += terms / (1 + ratio);
- difficulty += Math.Max(sameRhythm, samePattern) * intervalPenalty;
+ // Give bonus to near-1 ratios
+ difficulty += DifficultyCalculationUtils.BellCurve(ratio, 1, 0.5);
+
+ // Penalize ratios that are VERY near 1
+ difficulty -= DifficultyCalculationUtils.BellCurve(ratio, 1, 0.3);
+
+ difficulty = Math.Max(difficulty, 0);
+ difficulty /= Math.Sqrt(8);
return difficulty;
}
+
+ ///
+ /// Multiplier for a given denominator term.
+ ///
+ private static double termPenalty(double ratio, int denominator, double power, double multiplier) =>
+ -multiplier * Math.Pow(Math.Cos(denominator * Math.PI * ratio), power);
}
}