mirror of
https://github.com/ppy/osu.git
synced 2024-11-15 20:37:26 +08:00
Pass OK hit window as a separate difficulty attribute, fix erfc approximation
This commit is contained in:
parent
adf16187b1
commit
858afcd0b3
@ -43,6 +43,15 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
[JsonProperty("great_hit_window")]
|
[JsonProperty("great_hit_window")]
|
||||||
public double GreatHitWindow { get; set; }
|
public double GreatHitWindow { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The perceived hit window for an OK hit inclusive of rate-adjusting mods (DT/HT/etc).
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Rate-adjusting mods don't directly affect the hit window, but have a perceived effect as a result of adjusting audio timing.
|
||||||
|
/// </remarks>
|
||||||
|
[JsonProperty("ok_hit_window")]
|
||||||
|
public double OkHitWindow { get; set; }
|
||||||
|
|
||||||
public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes()
|
public override IEnumerable<(int attributeId, object value)> ToDatabaseAttributes()
|
||||||
{
|
{
|
||||||
foreach (var v in base.ToDatabaseAttributes())
|
foreach (var v in base.ToDatabaseAttributes())
|
||||||
|
@ -95,6 +95,7 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
ColourDifficulty = colourRating,
|
ColourDifficulty = colourRating,
|
||||||
PeakDifficulty = combinedRating,
|
PeakDifficulty = combinedRating,
|
||||||
GreatHitWindow = hitWindows.WindowFor(HitResult.Great) / clockRate,
|
GreatHitWindow = hitWindows.WindowFor(HitResult.Great) / clockRate,
|
||||||
|
OkHitWindow = hitWindows.WindowFor(HitResult.Ok) / clockRate,
|
||||||
MaxCombo = beatmap.HitObjects.Count(h => h is Hit),
|
MaxCombo = beatmap.HitObjects.Count(h => h is Hit),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -12,8 +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 osu.Framework.Audio.Track;
|
|
||||||
using osu.Framework.Extensions.IEnumerableExtensions;
|
|
||||||
|
|
||||||
namespace osu.Game.Rulesets.Taiko.Difficulty
|
namespace osu.Game.Rulesets.Taiko.Difficulty
|
||||||
{
|
{
|
||||||
@ -125,17 +123,11 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private double? computeEstimatedUr(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;
|
||||||
|
|
||||||
// Create a new track to properly calculate the hit window of 100s.
|
|
||||||
var track = new TrackVirtual(10000);
|
|
||||||
score.Mods.OfType<IApplicableToTrack>().ForEach(m => m.ApplyToTrack(track));
|
|
||||||
double clockRate = track.Rate;
|
|
||||||
|
|
||||||
double overallDifficulty = (50 - attributes.GreatHitWindow * clockRate) / 3;
|
|
||||||
double h300 = attributes.GreatHitWindow;
|
double h300 = attributes.GreatHitWindow;
|
||||||
double h100 = overallDifficulty <= 5 ? (120 - 8 * overallDifficulty) / clockRate : (80 - 6 * (overallDifficulty - 5)) / clockRate;
|
double h100 = attributes.OkHitWindow;
|
||||||
|
|
||||||
// Returns the likelihood of a deviation resulting in the score's hit judgements. The peak of the curve is the most likely deviation.
|
// 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)
|
double likelihoodGradient(double d)
|
||||||
@ -167,8 +159,10 @@ namespace osu.Game.Rulesets.Taiko.Difficulty
|
|||||||
|
|
||||||
private double logPcHit(double x, double deviation) => logErfcApprox(x / (deviation * Math.Sqrt(2)));
|
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).
|
// There's a numerical approximation to increase how far you can calculate ln(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));
|
private double logErfcApprox(double x) => x <= 5
|
||||||
|
? Math.Log(SpecialFunctions.Erfc(x))
|
||||||
|
: -Math.Pow(x, 2) - Math.Log(x * Math.Sqrt(Math.PI)); // https://www.desmos.com/calculator/kdbxwxgf01
|
||||||
|
|
||||||
// Log rules make subtraction of the non-log value non-trivial, this method simply subtracts the base value of 2 logs.
|
// 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)
|
private double logDiff(double firstLog, double secondLog)
|
||||||
|
Loading…
Reference in New Issue
Block a user