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

Reformat everything to be simpler

This commit is contained in:
Natelytle 2023-02-22 14:55:48 -05:00
parent 45e8d18b1b
commit 334f60f528

View File

@ -12,7 +12,6 @@ using osu.Game.Rulesets.Scoring;
using osu.Game.Rulesets.Taiko.Objects; using osu.Game.Rulesets.Taiko.Objects;
using osu.Game.Scoring; using osu.Game.Scoring;
using MathNet.Numerics; using MathNet.Numerics;
using MathNet.Numerics.RootFinding;
using osu.Framework.Audio.Track; using osu.Framework.Audio.Track;
using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.Extensions.IEnumerableExtensions;
@ -24,7 +23,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
private int countOk; private int countOk;
private int countMeh; private int countMeh;
private int countMiss; private int countMiss;
private double? estimatedDeviation; private double? estimatedUr;
private double effectiveMissCount; private double effectiveMissCount;
@ -41,7 +40,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
countOk = score.Statistics.GetValueOrDefault(HitResult.Ok); countOk = score.Statistics.GetValueOrDefault(HitResult.Ok);
countMeh = score.Statistics.GetValueOrDefault(HitResult.Meh); countMeh = score.Statistics.GetValueOrDefault(HitResult.Meh);
countMiss = score.Statistics.GetValueOrDefault(HitResult.Miss); countMiss = score.Statistics.GetValueOrDefault(HitResult.Miss);
estimatedDeviation = computeEstimatedDeviation(score, taikoAttributes); estimatedUr = computeEstimatedUr(score, taikoAttributes);
// The effectiveMissCount is calculated by gaining a ratio for totalSuccessfulHits and increasing the miss penalty for shorter object counts lower than 1000. // The effectiveMissCount is calculated by gaining a ratio for totalSuccessfulHits and increasing the miss penalty for shorter object counts lower than 1000.
if (totalSuccessfulHits > 0) if (totalSuccessfulHits > 0)
@ -71,7 +70,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
Difficulty = difficultyValue, Difficulty = difficultyValue,
Accuracy = accuracyValue, Accuracy = accuracyValue,
EffectiveMissCount = effectiveMissCount, EffectiveMissCount = effectiveMissCount,
EstimatedUr = estimatedDeviation * 10, EstimatedUr = estimatedUr,
Total = totalValue Total = totalValue
}; };
} }
@ -97,18 +96,18 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
if (score.Mods.Any(m => m is ModFlashlight<TaikoHitObject>)) if (score.Mods.Any(m => m is ModFlashlight<TaikoHitObject>))
difficultyValue *= 1.050 * lengthBonus; difficultyValue *= 1.050 * lengthBonus;
if (estimatedDeviation == null) if (estimatedUr == null)
return 0; return 0;
return difficultyValue * Math.Pow(SpecialFunctions.Erf(40 / (Math.Sqrt(2) * estimatedDeviation.Value)), 2.0); return difficultyValue * Math.Pow(SpecialFunctions.Erf(400 / (Math.Sqrt(2) * estimatedUr.Value)), 2.0);
} }
private double computeAccuracyValue(ScoreInfo score, TaikoDifficultyAttributes attributes, bool isConvert) private double computeAccuracyValue(ScoreInfo score, TaikoDifficultyAttributes attributes, bool isConvert)
{ {
if (attributes.GreatHitWindow <= 0 || estimatedDeviation == null) if (attributes.GreatHitWindow <= 0 || estimatedUr == null)
return 0; return 0;
double accuracyValue = Math.Pow(7.5 / estimatedDeviation.Value, 1.1) * Math.Pow(attributes.StarRating / 2.7, 0.8) * 100.0; double accuracyValue = Math.Pow(75 / estimatedUr.Value, 1.1) * Math.Pow(attributes.StarRating / 2.7, 0.8) * 100.0;
double lengthBonus = Math.Min(1.15, Math.Pow(totalHits / 1500.0, 0.3)); double lengthBonus = Math.Min(1.15, Math.Pow(totalHits / 1500.0, 0.3));
@ -124,7 +123,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
/// assuming the player's mean hit error is 0. The estimation is consistent in that two SS scores on the same map with the same settings /// assuming the player's mean hit error is 0. The estimation is consistent in that two SS scores on the same map with the same settings
/// will always return the same deviation. See: https://www.desmos.com/calculator/qlr946netu /// will always return the same deviation. See: https://www.desmos.com/calculator/qlr946netu
/// </summary> /// </summary>
private double? computeEstimatedDeviation(ScoreInfo score, TaikoDifficultyAttributes attributes) private double? computeEstimatedUr(ScoreInfo score, TaikoDifficultyAttributes attributes)
{ {
if (totalSuccessfulHits == 0 || attributes.GreatHitWindow == 0) if (totalSuccessfulHits == 0 || attributes.GreatHitWindow == 0)
return null; return null;
@ -135,52 +134,55 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
double clockRate = track.Rate; double clockRate = track.Rate;
double overallDifficulty = (50 - attributes.GreatHitWindow * clockRate) / 3; double overallDifficulty = (50 - attributes.GreatHitWindow * clockRate) / 3;
double goodHitWindow; double h300 = attributes.GreatHitWindow;
if (overallDifficulty <= 5) double h100 = overallDifficulty <= 5 ? (120 - 8 * overallDifficulty) / clockRate : (80 - 6 * (overallDifficulty - 5)) / clockRate;
goodHitWindow = (120 - 8 * overallDifficulty) / clockRate;
else
goodHitWindow = (80 - 6 * (overallDifficulty - 5)) / clockRate;
double root2 = Math.Sqrt(2); // Returns the likelihood of a deviation resulting in the score's hit judgements. The peak of the curve is the most likely deviation.
double likelihoodGradient(double d)
// Log of the most likely deviation resulting in the score's hit judgements, differentiated such that 1 over the most likely deviation returns 0.
double logLikelihoodGradient(double d)
{ {
if (d <= 0) if (d <= 0)
return 1; return 0;
double p300 = SpecialFunctions.Erf(attributes.GreatHitWindow / root2 * d); double p300 = logDiff(0, logPcHit(h300, d));
double lnP300 = lnErfcApprox(attributes.GreatHitWindow / root2 * d); double p100 = logDiff(logPcHit(h300, d), logPcHit(h100, d));
double lnP100 = lnErfcApprox(goodHitWindow / root2 * d); double p0 = logPcHit(h100, d);
double t1 = countGreat * (Math.Exp(Math.Log(attributes.GreatHitWindow) + -Math.Pow(attributes.GreatHitWindow / root2 * d, 2)) / p300); double gradient = Math.Exp(
(countGreat * p300
+ (countOk + 0.5) * p100
+ countMiss * p0) / totalHits
);
double t2A = Math.Exp(Math.Log(goodHitWindow) + -Math.Pow(goodHitWindow / root2 * d, 2) - logDiff(lnP300, lnP100)); return -gradient;
double t2B = Math.Exp(Math.Log(attributes.GreatHitWindow) + -Math.Pow(attributes.GreatHitWindow / root2 * d, 2) - logDiff(lnP300, lnP100));
double t2 = (countOk + 1) * (t2A - t2B);
double t3 = countMiss * Math.Exp(Math.Log(goodHitWindow) + -Math.Pow(goodHitWindow / root2 * d, 2) - lnP100);
return t1 + t2 - t3;
} }
double root = Brent.FindRootExpand(logLikelihoodGradient, 0.02, 0.3); double deviation = FindMinimum.OfScalarFunction(likelihoodGradient, 30);
return 1 / root; return deviation * 10;
} }
private int totalHits => countGreat + countOk + countMeh + countMiss; private int totalHits => countGreat + countOk + countMeh + countMiss;
private int totalSuccessfulHits => countGreat + countOk + countMeh; private int totalSuccessfulHits => countGreat + countOk + countMeh;
private double lnErfcApprox(double x) private double logPcHit(double x, double deviation) => logErfcApprox(x / (deviation * Math.Sqrt(2)));
// There is a numerical approximation to increase how far you can calculate Erfc(x).
private double logErfcApprox(double x) => x <= 5 ? Math.Log(SpecialFunctions.Erfc(x)) : -Math.Pow(x, 2) - Math.Log(x) - Math.Log(Math.Sqrt(Math.PI));
// Log rules make subtraction of the non-log value non-trivial, this method simply subtracts the base value of 2 logs.
private double logDiff(double firstLog, double secondLog)
{ {
if (x <= 5) double maxVal = Math.Max(firstLog, secondLog);
return Math.Log(SpecialFunctions.Erfc(x));
return -Math.Pow(x, 2) - Math.Log(x) - Math.Log(Math.Sqrt(Math.PI)); // Avoid negative infinity - negative infinity (NaN) by checking if the higher value is negative infinity.
// Shouldn't ever happen, but good for redundancy purposes.
if (double.IsNegativeInfinity(maxVal))
{
return maxVal;
}
return firstLog + SpecialFunctions.Log1p(-Math.Exp(-(firstLog - secondLog)));
} }
private double logDiff(double l1, double l2) => l1 + SpecialFunctions.Log1p(-Math.Exp(-(l1 - l2)));
} }
} }