1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-14 02:22:59 +08:00

Refactor for safety

This commit is contained in:
Dan Balasescu 2023-05-19 14:37:26 +09:00
parent 2ae34530f7
commit d74bf2a096
6 changed files with 111 additions and 152 deletions

View File

@ -17,51 +17,48 @@ namespace osu.Game.Rulesets.Catch.Scoring
private int maximumTinyDroplets; private int maximumTinyDroplets;
private int hitTinyDroplets; private int hitTinyDroplets;
private int maximumBasicJudgements;
private int currentBasicJudgements;
public CatchScoreProcessor() public CatchScoreProcessor()
: base(new CatchRuleset()) : base(new CatchRuleset())
{ {
} }
protected override double ComputeTotalScore() protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion)
{ {
double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1;
double fruitHitsRatio = maximumTinyDroplets == 0 ? 0 : (double)hitTinyDroplets / maximumTinyDroplets; double fruitHitsRatio = maximumTinyDroplets == 0 ? 0 : (double)hitTinyDroplets / maximumTinyDroplets;
const int tiny_droplets_portion = 400000; const int tiny_droplets_portion = 400000;
return ( return ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * comboRatio
((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * comboRatio + + tiny_droplets_portion * tinyDropletScale * fruitHitsRatio
tiny_droplets_portion * tinyDropletScale * fruitHitsRatio + + bonusPortion;
BonusPortion
) * ScoreMultiplier;
} }
protected override void AddScoreChange(JudgementResult result) protected override double GetComboScoreChange(JudgementResult result)
=> Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(combo_cap, combo_base));
protected override void ApplyScoreChange(JudgementResult result)
{ {
var change = computeScoreChange(result); base.ApplyScoreChange(result);
ComboPortion += change.combo;
BonusPortion += change.bonus; if (result.HitObject is TinyDroplet)
hitTinyDroplets += change.tinyDropletHits; hitTinyDroplets++;
if (result.Type.IsBasic())
currentBasicJudgements++;
} }
protected override void RemoveScoreChange(JudgementResult result) protected override void RemoveScoreChange(JudgementResult result)
{ {
var change = computeScoreChange(result); base.RemoveScoreChange(result);
ComboPortion -= change.combo;
BonusPortion -= change.bonus;
hitTinyDroplets -= change.tinyDropletHits;
}
private (double combo, double bonus, int tinyDropletHits) computeScoreChange(JudgementResult result)
{
if (result.HitObject is TinyDroplet) if (result.HitObject is TinyDroplet)
return (0, 0, 1); hitTinyDroplets--;
if (result.Type.IsBonus()) if (result.Type.IsBasic())
return (0, Judgement.ToNumericResult(result.Type), 0); currentBasicJudgements--;
return (Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(combo_cap, combo_base)), 0, 0);
} }
protected override void Reset(bool storeResults) protected override void Reset(bool storeResults)
@ -71,14 +68,16 @@ namespace osu.Game.Rulesets.Catch.Scoring
if (storeResults) if (storeResults)
{ {
maximumTinyDroplets = hitTinyDroplets; maximumTinyDroplets = hitTinyDroplets;
maximumBasicJudgements = currentBasicJudgements;
if (maximumTinyDroplets + MaxBasicJudgements == 0) if (maximumTinyDroplets + maximumBasicJudgements == 0)
tinyDropletScale = 0; tinyDropletScale = 0;
else else
tinyDropletScale = (double)maximumTinyDroplets / (maximumTinyDroplets + MaxBasicJudgements); tinyDropletScale = (double)maximumTinyDroplets / (maximumTinyDroplets + maximumBasicJudgements);
} }
hitTinyDroplets = 0; hitTinyDroplets = 0;
currentBasicJudgements = 0;
} }
} }
} }

View File

@ -16,38 +16,14 @@ namespace osu.Game.Rulesets.Mania.Scoring
{ {
} }
protected override double ComputeTotalScore() protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion)
{ {
double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1; return 200000 * comboRatio
double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1; + 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyRatio
+ bonusPortion;
return (
200000 * comboRatio +
800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyRatio +
BonusPortion
) * ScoreMultiplier;
} }
protected override void AddScoreChange(JudgementResult result) protected override double GetComboScoreChange(JudgementResult result)
{ => Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base));
var change = computeScoreChange(result);
ComboPortion += change.combo;
BonusPortion += change.bonus;
}
protected override void RemoveScoreChange(JudgementResult result)
{
var change = computeScoreChange(result);
ComboPortion -= change.combo;
BonusPortion -= change.bonus;
}
private (double combo, double bonus) computeScoreChange(JudgementResult result)
{
if (result.Type.IsBonus())
return (0, Judgement.ToNumericResult(result.Type));
return (Judgement.ToNumericResult(result.Type) * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base)), 0);
}
} }
} }

View File

@ -13,16 +13,11 @@ namespace osu.Game.Rulesets.Osu.Scoring
{ {
} }
protected override double ComputeTotalScore() protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion)
{ {
double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1; return 700000 * comboRatio
double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1; + 300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio
+ bonusPortion;
return (
700000 * comboRatio +
300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio +
BonusPortion
) * ScoreMultiplier;
} }
} }
} }

View File

@ -17,46 +17,28 @@ namespace osu.Game.Rulesets.Taiko.Scoring
{ {
} }
protected override double ComputeTotalScore() protected override double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion)
{ {
double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1; return 250000 * comboRatio
double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1; + 750000 * Math.Pow(Accuracy.Value, 3.6) * accuracyRatio
+ bonusPortion;
return (
250000 * comboRatio +
750000 * Math.Pow(Accuracy.Value, 3.6) * accuracyRatio +
BonusPortion
) * ScoreMultiplier;
} }
protected override void AddScoreChange(JudgementResult result) protected override double GetBonusScoreChange(JudgementResult result) => base.GetBonusScoreChange(result) * strongScaleValue(result);
protected override double GetComboScoreChange(JudgementResult result)
{ {
var change = computeScoreChange(result); return Judgement.ToNumericResult(result.Type)
ComboPortion += change.combo; * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base))
BonusPortion += change.bonus; * strongScaleValue(result);
} }
protected override void RemoveScoreChange(JudgementResult result) private double strongScaleValue(JudgementResult result)
{ {
var change = computeScoreChange(result);
ComboPortion -= change.combo;
BonusPortion -= change.bonus;
}
private (double combo, double bonus) computeScoreChange(JudgementResult result)
{
double hitValue = Judgement.ToNumericResult(result.Type);
if (result.HitObject is StrongNestedHitObject strong) if (result.HitObject is StrongNestedHitObject strong)
{ return strong.Parent is DrumRollTick ? 3 : 7;
double strongBonus = strong.Parent is DrumRollTick ? 3 : 7;
hitValue *= strongBonus;
}
if (result.Type.IsBonus()) return 1;
return (0, hitValue);
return (hitValue * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base)), 0);
} }
} }
} }

View File

@ -68,7 +68,7 @@ namespace osu.Game.Rulesets.Difficulty
ScoreProcessor scoreProcessor = ruleset.CreateScoreProcessor(); ScoreProcessor scoreProcessor = ruleset.CreateScoreProcessor();
scoreProcessor.Mods.Value = perfectPlay.Mods; scoreProcessor.Mods.Value = perfectPlay.Mods;
scoreProcessor.ApplyBeatmap(playableBeatmap); scoreProcessor.ApplyBeatmap(playableBeatmap);
perfectPlay.TotalScore = scoreProcessor.MaxTotalScore; perfectPlay.TotalScore = scoreProcessor.MaximumTotalScore;
// compute rank achieved // compute rank achieved
// default to SS, then adjust the rank with mods // default to SS, then adjust the rank with mods

View File

@ -90,10 +90,18 @@ namespace osu.Game.Rulesets.Scoring
/// <summary> /// <summary>
/// The maximum achievable total score. /// The maximum achievable total score.
/// </summary> /// </summary>
public long MaxTotalScore { get; private set; } public long MaximumTotalScore { get; private set; }
/// <summary> /// <summary>
/// The sum of all accuracy-affecting judgements at the current time. /// The maximum sum of accuracy-affecting judgements at the current point in time.
/// </summary>
/// <remarks>
/// Used to compute accuracy.
/// </remarks>
private double currentMaximumBaseScore;
/// <summary>
/// The sum of all accuracy-affecting judgements at the current point in time.
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// Used to compute accuracy. /// Used to compute accuracy.
@ -101,42 +109,34 @@ namespace osu.Game.Rulesets.Scoring
private double currentBaseScore; private double currentBaseScore;
/// <summary> /// <summary>
/// The maximum sum of accuracy-affecting judgements at the current time. /// The count of all basic judgements in the beatmap.
/// </summary> /// </summary>
/// <remarks> private int maximumCountBasicJudgements;
/// Used to compute accuracy.
/// </remarks>
private double currentMaxBaseScore;
/// <summary> /// <summary>
/// The total count of basic judgements in the beatmap. /// The count of basic judgements at the current point in time.
/// </summary> /// </summary>
protected int MaxBasicJudgements { get; private set; } private int currentCountBasicJudgements;
/// <summary> /// <summary>
/// The current count of basic judgements by the player. /// The maximum combo score in the beatmap.
/// </summary> /// </summary>
protected int CurrentBasicJudgements { get; private set; } private double maximumComboPortion;
/// <summary> /// <summary>
/// The current combo score. /// The combo score at the current point in time.
/// </summary> /// </summary>
protected double ComboPortion { get; set; } private double currentComboPortion;
/// <summary> /// <summary>
/// The maximum achievable combo score. /// The bonus score at the current point in time.
/// </summary> /// </summary>
protected double MaxComboPortion { get; private set; } private double currentBonusPortion;
/// <summary>
/// The current bonus score.
/// </summary>
protected double BonusPortion { get; set; }
/// <summary> /// <summary>
/// The total score multiplier. /// The total score multiplier.
/// </summary> /// </summary>
protected double ScoreMultiplier { get; private set; } = 1; private double scoreMultiplier = 1;
public Dictionary<HitResult, int> MaximumStatistics public Dictionary<HitResult, int> MaximumStatistics
{ {
@ -171,10 +171,10 @@ namespace osu.Game.Rulesets.Scoring
Mods.ValueChanged += mods => Mods.ValueChanged += mods =>
{ {
ScoreMultiplier = 1; scoreMultiplier = 1;
foreach (var m in mods.NewValue) foreach (var m in mods.NewValue)
ScoreMultiplier *= m.ScoreMultiplier; scoreMultiplier *= m.ScoreMultiplier;
updateScore(); updateScore();
}; };
@ -207,15 +207,21 @@ namespace osu.Game.Rulesets.Scoring
result.ComboAfterJudgement = Combo.Value; result.ComboAfterJudgement = Combo.Value;
if (result.Type.IsBasic()) if (result.Type.IsBasic())
CurrentBasicJudgements++; currentCountBasicJudgements++;
if (result.Type.AffectsAccuracy()) if (result.Type.AffectsAccuracy())
{ {
currentMaxBaseScore += Judgement.ToNumericResult(result.Judgement.MaxResult); currentMaximumBaseScore += Judgement.ToNumericResult(result.Judgement.MaxResult);
currentBaseScore += Judgement.ToNumericResult(result.Type); currentBaseScore += Judgement.ToNumericResult(result.Type);
} }
AddScoreChange(result); if (result.Type.IsBonus())
currentBonusPortion += GetBonusScoreChange(result);
if (result.Type.AffectsCombo())
currentComboPortion += GetComboScoreChange(result);
ApplyScoreChange(result);
hitEvents.Add(CreateHitEvent(result)); hitEvents.Add(CreateHitEvent(result));
lastHitObject = result.HitObject; lastHitObject = result.HitObject;
@ -245,14 +251,20 @@ namespace osu.Game.Rulesets.Scoring
return; return;
if (result.Type.IsBasic()) if (result.Type.IsBasic())
CurrentBasicJudgements--; currentCountBasicJudgements--;
if (result.Type.AffectsAccuracy()) if (result.Type.AffectsAccuracy())
{ {
currentMaxBaseScore -= Judgement.ToNumericResult(result.Judgement.MaxResult); currentMaximumBaseScore -= Judgement.ToNumericResult(result.Judgement.MaxResult);
currentBaseScore -= Judgement.ToNumericResult(result.Type); currentBaseScore -= Judgement.ToNumericResult(result.Type);
} }
if (result.Type.IsBonus())
currentBonusPortion -= GetBonusScoreChange(result);
if (result.Type.AffectsCombo())
currentComboPortion -= GetComboScoreChange(result);
RemoveScoreChange(result); RemoveScoreChange(result);
Debug.Assert(hitEvents.Count > 0); Debug.Assert(hitEvents.Count > 0);
@ -262,42 +274,37 @@ namespace osu.Game.Rulesets.Scoring
updateScore(); updateScore();
} }
protected virtual void AddScoreChange(JudgementResult result) protected virtual double GetBonusScoreChange(JudgementResult result) => Judgement.ToNumericResult(result.Type);
{
if (result.Type.IsBonus())
BonusPortion += Judgement.ToNumericResult(result.Type);
if (result.Type.AffectsCombo()) protected virtual double GetComboScoreChange(JudgementResult result) => Judgement.ToNumericResult(result.Type) * (1 + result.ComboAfterJudgement / 10d);
ComboPortion += Judgement.ToNumericResult(result.Type) * (1 + result.ComboAfterJudgement / 10d);
protected virtual void ApplyScoreChange(JudgementResult result)
{
} }
protected virtual void RemoveScoreChange(JudgementResult result) protected virtual void RemoveScoreChange(JudgementResult result)
{ {
if (result.Type.IsBonus())
BonusPortion -= Judgement.ToNumericResult(result.Type);
if (result.Type.AffectsCombo())
ComboPortion -= Judgement.ToNumericResult(result.Type) * (1 + result.ComboAfterJudgement / 10d);
} }
private void updateScore() private void updateScore()
{ {
Accuracy.Value = currentMaxBaseScore > 0 ? currentBaseScore / currentMaxBaseScore : 1; Accuracy.Value = currentMaximumBaseScore > 0 ? currentBaseScore / currentMaximumBaseScore : 1;
TotalScore.Value = (long)Math.Round(ComputeTotalScore());
double comboRatio = maximumComboPortion > 0 ? currentComboPortion / maximumComboPortion : 1;
double accuracyRatio = maximumCountBasicJudgements > 0 ? (double)currentCountBasicJudgements / maximumCountBasicJudgements : 1;
TotalScore.Value = (long)Math.Round(ComputeTotalScore(comboRatio, accuracyRatio, currentBonusPortion) * scoreMultiplier);
} }
protected virtual double ComputeTotalScore() protected virtual double ComputeTotalScore(double comboRatio, double accuracyRatio, double bonusPortion)
{ {
double comboRatio = MaxComboPortion > 0 ? ComboPortion / MaxComboPortion : 1;
double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1;
return return
(int)Math.Round (int)Math.Round
(( ((
700000 * comboRatio + 700000 * comboRatio +
300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio + 300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio +
BonusPortion bonusPortion
) * ScoreMultiplier); ) * scoreMultiplier);
} }
/// <summary> /// <summary>
@ -313,22 +320,22 @@ namespace osu.Game.Rulesets.Scoring
if (storeResults) if (storeResults)
{ {
MaxComboPortion = ComboPortion; maximumComboPortion = currentComboPortion;
MaxBasicJudgements = CurrentBasicJudgements; maximumCountBasicJudgements = currentCountBasicJudgements;
maximumResultCounts.Clear(); maximumResultCounts.Clear();
maximumResultCounts.AddRange(scoreResultCounts); maximumResultCounts.AddRange(scoreResultCounts);
MaxTotalScore = TotalScore.Value; MaximumTotalScore = TotalScore.Value;
} }
scoreResultCounts.Clear(); scoreResultCounts.Clear();
currentBaseScore = 0; currentBaseScore = 0;
currentMaxBaseScore = 0; currentMaximumBaseScore = 0;
CurrentBasicJudgements = 0; currentCountBasicJudgements = 0;
ComboPortion = 0; currentComboPortion = 0;
BonusPortion = 0; currentBonusPortion = 0;
TotalScore.Value = 0; TotalScore.Value = 0;
Accuracy.Value = 1; Accuracy.Value = 1;
@ -338,7 +345,7 @@ namespace osu.Game.Rulesets.Scoring
HighestCombo.Value = 0; HighestCombo.Value = 0;
currentBaseScore = 0; currentBaseScore = 0;
currentMaxBaseScore = 0; currentMaximumBaseScore = 0;
} }
/// <summary> /// <summary>