1
0
mirror of https://github.com/ppy/osu.git synced 2024-12-13 05:22:54 +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 hitTinyDroplets;
private int maximumBasicJudgements;
private int currentBasicJudgements;
public CatchScoreProcessor()
: 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;
const int tiny_droplets_portion = 400000;
return (
((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * comboRatio +
tiny_droplets_portion * tinyDropletScale * fruitHitsRatio +
BonusPortion
) * ScoreMultiplier;
return ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * comboRatio
+ tiny_droplets_portion * tinyDropletScale * fruitHitsRatio
+ bonusPortion;
}
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);
ComboPortion += change.combo;
BonusPortion += change.bonus;
hitTinyDroplets += change.tinyDropletHits;
base.ApplyScoreChange(result);
if (result.HitObject is TinyDroplet)
hitTinyDroplets++;
if (result.Type.IsBasic())
currentBasicJudgements++;
}
protected override void RemoveScoreChange(JudgementResult result)
{
var change = computeScoreChange(result);
ComboPortion -= change.combo;
BonusPortion -= change.bonus;
hitTinyDroplets -= change.tinyDropletHits;
}
base.RemoveScoreChange(result);
private (double combo, double bonus, int tinyDropletHits) computeScoreChange(JudgementResult result)
{
if (result.HitObject is TinyDroplet)
return (0, 0, 1);
hitTinyDroplets--;
if (result.Type.IsBonus())
return (0, Judgement.ToNumericResult(result.Type), 0);
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);
if (result.Type.IsBasic())
currentBasicJudgements--;
}
protected override void Reset(bool storeResults)
@ -71,14 +68,16 @@ namespace osu.Game.Rulesets.Catch.Scoring
if (storeResults)
{
maximumTinyDroplets = hitTinyDroplets;
maximumBasicJudgements = currentBasicJudgements;
if (maximumTinyDroplets + MaxBasicJudgements == 0)
if (maximumTinyDroplets + maximumBasicJudgements == 0)
tinyDropletScale = 0;
else
tinyDropletScale = (double)maximumTinyDroplets / (maximumTinyDroplets + MaxBasicJudgements);
tinyDropletScale = (double)maximumTinyDroplets / (maximumTinyDroplets + maximumBasicJudgements);
}
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;
double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1;
return (
200000 * comboRatio +
800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyRatio +
BonusPortion
) * ScoreMultiplier;
return 200000 * comboRatio
+ 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * accuracyRatio
+ bonusPortion;
}
protected override void AddScoreChange(JudgementResult result)
{
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);
}
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));
}
}

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;
double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1;
return (
700000 * comboRatio +
300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio +
BonusPortion
) * ScoreMultiplier;
return 700000 * comboRatio
+ 300000 * Math.Pow(Accuracy.Value, 10) * accuracyRatio
+ bonusPortion;
}
}
}

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;
double accuracyRatio = MaxBasicJudgements > 0 ? (double)CurrentBasicJudgements / MaxBasicJudgements : 1;
return (
250000 * comboRatio +
750000 * Math.Pow(Accuracy.Value, 3.6) * accuracyRatio +
BonusPortion
) * ScoreMultiplier;
return 250000 * comboRatio
+ 750000 * Math.Pow(Accuracy.Value, 3.6) * accuracyRatio
+ bonusPortion;
}
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);
ComboPortion += change.combo;
BonusPortion += change.bonus;
return Judgement.ToNumericResult(result.Type)
* Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base))
* 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)
{
double strongBonus = strong.Parent is DrumRollTick ? 3 : 7;
hitValue *= strongBonus;
}
return strong.Parent is DrumRollTick ? 3 : 7;
if (result.Type.IsBonus())
return (0, hitValue);
return (hitValue * Math.Min(Math.Max(0.5, Math.Log(result.ComboAfterJudgement, combo_base)), Math.Log(400, combo_base)), 0);
return 1;
}
}
}

View File

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

View File

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