Reimplement classic scoring mode

This commit is contained in:
Dan Balasescu 2023-05-09 20:00:14 +09:00
parent 3c3c812ed6
commit a7b623f52a
6 changed files with 37 additions and 35 deletions

View File

@ -31,13 +31,11 @@ protected override double ComputeTotalScore()
const int tiny_droplets_portion = 400000; const int tiny_droplets_portion = 400000;
return return (
(int)Math.Round
((
((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * ComboPortion / MaxComboPortion + ((1000000 - tiny_droplets_portion) + tiny_droplets_portion * (1 - tinyDropletScale)) * ComboPortion / MaxComboPortion +
tiny_droplets_portion * tinyDropletScale * fruitHitsRatio + tiny_droplets_portion * tinyDropletScale * fruitHitsRatio +
BonusPortion BonusPortion
) * ScoreMultiplier); ) * ScoreMultiplier;
} }
protected override void AddScoreChange(JudgementResult result) protected override void AddScoreChange(JudgementResult result)

View File

@ -20,13 +20,11 @@ public ManiaScoreProcessor(Ruleset ruleset)
protected override double ComputeTotalScore() protected override double ComputeTotalScore()
{ {
return return (
(int)Math.Round
((
200000 * ComboPortion / MaxComboPortion + 200000 * ComboPortion / MaxComboPortion +
800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + 800000 * Math.Pow(Accuracy.Value, 2 + 2 * Accuracy.Value) * ((double)CurrentBasicJudgements / MaxBasicJudgements) +
BonusPortion BonusPortion
) * ScoreMultiplier); ) * ScoreMultiplier;
} }
protected override void AddScoreChange(JudgementResult result) protected override void AddScoreChange(JudgementResult result)

View File

@ -17,13 +17,11 @@ public OsuScoreProcessor(Ruleset ruleset)
protected override double ComputeTotalScore() protected override double ComputeTotalScore()
{ {
return return (
(int)Math.Round
((
700000 * ComboPortion / MaxComboPortion + 700000 * ComboPortion / MaxComboPortion +
300000 * Math.Pow(Accuracy.Value, 10) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + 300000 * Math.Pow(Accuracy.Value, 10) * ((double)CurrentBasicJudgements / MaxBasicJudgements) +
BonusPortion BonusPortion
) * ScoreMultiplier); ) * ScoreMultiplier;
} }
} }
} }

View File

@ -21,13 +21,11 @@ public TaikoScoreProcessor(Ruleset ruleset)
protected override double ComputeTotalScore() protected override double ComputeTotalScore()
{ {
return return (
(int)Math.Round
((
250000 * ComboPortion / MaxComboPortion + 250000 * ComboPortion / MaxComboPortion +
750000 * Math.Pow(Accuracy.Value, 3.6) * ((double)CurrentBasicJudgements / MaxBasicJudgements) + 750000 * Math.Pow(Accuracy.Value, 3.6) * ((double)CurrentBasicJudgements / MaxBasicJudgements) +
BonusPortion BonusPortion
) * ScoreMultiplier); ) * ScoreMultiplier;
} }
protected override void AddScoreChange(JudgementResult result) protected override void AddScoreChange(JudgementResult result)

View File

@ -274,8 +274,20 @@ private void updateScore()
{ {
Accuracy.Value = currentMaxBasicScore > 0 ? currentBasicScore / currentMaxBasicScore : 1; Accuracy.Value = currentMaxBasicScore > 0 ? currentBasicScore / currentMaxBasicScore : 1;
// Todo: Classic/Standardised double standardisedScore = ComputeTotalScore();
TotalScore.Value = (long)Math.Round(ComputeTotalScore());
if (Mode.Value == ScoringMode.Standardised)
TotalScore.Value = (long)Math.Round(standardisedScore);
else
TotalScore.Value = ConvertToClassic(standardisedScore);
}
public long ConvertToClassic(double standardised)
{
// This gives a similar feeling to osu!stable scoring (ScoreV1) while keeping classic scoring as only a constant multiple of standardised scoring.
// The invariant is important to ensure that scores don't get re-ordered on leaderboards between the two scoring modes.
double scaledRawScore = standardised / MAX_SCORE;
return (long)Math.Round(Math.Pow(scaledRawScore * Math.Max(1, MaxBasicJudgements), 2) * ClassicScoreMultiplier);
} }
protected abstract double ComputeTotalScore(); protected abstract double ComputeTotalScore();

View File

@ -107,17 +107,15 @@ public IEnumerable<ScoreInfo> OrderByTotalScore(IEnumerable<ScoreInfo> scores)
/// <returns>The total score.</returns> /// <returns>The total score.</returns>
public long GetTotalScore([NotNull] ScoreInfo score, ScoringMode mode = ScoringMode.Standardised) public long GetTotalScore([NotNull] ScoreInfo score, ScoringMode mode = ScoringMode.Standardised)
{ {
// TODO: This is required for playlist aggregate scores. They should likely not be getting here in the first place. if (mode == ScoringMode.Standardised)
if (string.IsNullOrEmpty(score.BeatmapInfo.MD5Hash))
return score.TotalScore; return score.TotalScore;
var ruleset = score.Ruleset.CreateInstance(); var ruleset = score.Ruleset.CreateInstance();
var scoreProcessor = ruleset.CreateScoreProcessor(); var scoreProcessor = ruleset.CreateScoreProcessor();
scoreProcessor.Mods.Value = score.Mods; scoreProcessor.Mods.Value = score.Mods;
// Todo: // Todo: This loses precision because we're dealing with pre-rounded total scores.
return 0; return scoreProcessor.ConvertToClassic(score.TotalScore);
// return scoreProcessor.ComputeScore(mode, score);
} }
/// <summary> /// <summary>