Extract score statistics directly into ScoringValues

This commit is contained in:
Dan Balasescu 2022-05-31 17:50:18 +09:00
parent af0f934e1a
commit d0e3e50ca7

View File

@ -288,16 +288,12 @@ namespace osu.Game.Rulesets.Scoring
if (!ruleset.RulesetInfo.Equals(scoreInfo.Ruleset)) if (!ruleset.RulesetInfo.Equals(scoreInfo.Ruleset))
throw new ArgumentException($"Unexpected score ruleset. Expected \"{ruleset.RulesetInfo.ShortName}\" but was \"{scoreInfo.Ruleset.ShortName}\"."); throw new ArgumentException($"Unexpected score ruleset. Expected \"{ruleset.RulesetInfo.ShortName}\" but was \"{scoreInfo.Ruleset.ShortName}\".");
extractFromStatistics(scoreInfo.Statistics, extractFromStatistics(scoreInfo.Statistics, out var current, out var max);
out double extractedBaseScore,
out double extractedMaxBaseScore,
out int extractedMaxCombo,
out int extractedBasicHitObjects);
double accuracyRatio = extractedMaxBaseScore > 0 ? extractedBaseScore / extractedMaxBaseScore : 1; double accuracyRatio = max.BaseScore > 0 ? current.BaseScore / max.BaseScore : 1;
double comboRatio = extractedMaxCombo > 0 ? (double)scoreInfo.MaxCombo / extractedMaxCombo : 1; double comboRatio = max.MaxCombo > 0 ? (double)scoreInfo.MaxCombo / max.MaxCombo : 1;
return ComputeScore(mode, accuracyRatio, comboRatio, getBonusScore(scoreInfo.Statistics), extractedBasicHitObjects); return ComputeScore(mode, accuracyRatio, comboRatio, getBonusScore(scoreInfo.Statistics), max.HitObjects);
} }
/// <summary> /// <summary>
@ -317,13 +313,9 @@ namespace osu.Game.Rulesets.Scoring
if (!beatmapApplied) if (!beatmapApplied)
throw new InvalidOperationException($"Cannot compute partial score without calling {nameof(ApplyBeatmap)}."); throw new InvalidOperationException($"Cannot compute partial score without calling {nameof(ApplyBeatmap)}.");
extractFromStatistics(scoreInfo.Statistics, extractFromStatistics(scoreInfo.Statistics, out var current, out _);
out double extractedBaseScore,
out _,
out _,
out _);
double accuracyRatio = maximumScoringValues.BaseScore > 0 ? extractedBaseScore / maximumScoringValues.BaseScore : 1; double accuracyRatio = maximumScoringValues.BaseScore > 0 ? current.BaseScore / maximumScoringValues.BaseScore : 1;
double comboRatio = maximumScoringValues.MaxCombo > 0 ? (double)scoreInfo.MaxCombo / maximumScoringValues.MaxCombo : 1; double comboRatio = maximumScoringValues.MaxCombo > 0 ? (double)scoreInfo.MaxCombo / maximumScoringValues.MaxCombo : 1;
return ComputeScore(mode, accuracyRatio, comboRatio, getBonusScore(scoreInfo.Statistics), maximumScoringValues.HitObjects); return ComputeScore(mode, accuracyRatio, comboRatio, getBonusScore(scoreInfo.Statistics), maximumScoringValues.HitObjects);
@ -353,14 +345,9 @@ namespace osu.Game.Rulesets.Scoring
// Note: This cannot be applied universally to all legacy scores, as some rulesets (e.g. catch) group multiple judgements together. // Note: This cannot be applied universally to all legacy scores, as some rulesets (e.g. catch) group multiple judgements together.
if (scoreInfo.IsLegacyScore && scoreInfo.Ruleset.OnlineID == 3) if (scoreInfo.IsLegacyScore && scoreInfo.Ruleset.OnlineID == 3)
{ {
extractFromStatistics(scoreInfo.Statistics, extractFromStatistics(scoreInfo.Statistics, out var current, out var maximum);
out double computedBaseScore, if (maximum.BaseScore > 0)
out double computedMaxBaseScore, accuracyRatio = current.BaseScore / current.MaxCombo;
out _,
out _);
if (computedMaxBaseScore > 0)
accuracyRatio = computedBaseScore / computedMaxBaseScore;
} }
int computedBasicHitObjects = scoreInfo.Statistics.Where(kvp => kvp.Key.IsBasic()).Select(kvp => kvp.Value).Sum(); int computedBasicHitObjects = scoreInfo.Statistics.Where(kvp => kvp.Key.IsBasic()).Select(kvp => kvp.Value).Sum();
@ -472,10 +459,7 @@ namespace osu.Game.Rulesets.Scoring
if (frame.Header == null) if (frame.Header == null)
return; return;
extractFromStatistics(frame.Header.Statistics, out double baseScore, out double rollingMaxBaseScore, out _, out _); extractFromStatistics(frame.Header.Statistics, out currentScoringValues, out rollingMaximumScoringValues);
currentScoringValues.BaseScore = baseScore;
rollingMaximumScoringValues.BaseScore = rollingMaxBaseScore;
HighestCombo.Value = frame.Header.MaxCombo; HighestCombo.Value = frame.Header.MaxCombo;
scoreResultCounts.Clear(); scoreResultCounts.Clear();
@ -486,49 +470,59 @@ namespace osu.Game.Rulesets.Scoring
OnResetFromReplayFrame?.Invoke(); OnResetFromReplayFrame?.Invoke();
} }
private void extractFromStatistics(IReadOnlyDictionary<HitResult, int> statistics, out double baseScore, out double maxBaseScore, out int maxCombo, private void extractFromStatistics(IReadOnlyDictionary<HitResult, int> statistics, out ScoringValues current, out ScoringValues maximum)
out int basicHitObjects)
{ {
baseScore = 0; current = default;
maxBaseScore = 0; maximum = default;
maxCombo = 0;
basicHitObjects = 0;
foreach ((HitResult result, int count) in statistics) foreach ((HitResult result, int count) in statistics)
{ {
// Bonus scores are counted separately directly from the statistics dictionary later on. if (!result.IsScorable())
if (!result.IsScorable() || result.IsBonus())
continue; continue;
// The maximum result of this judgement if it wasn't a miss. if (result.IsBonus())
// E.g. For a GOOD judgement, the max result is either GREAT/PERFECT depending on which one the ruleset uses (osu!: GREAT, osu!mania: PERFECT).
HitResult maxResult;
switch (result)
{ {
case HitResult.LargeTickHit: current.BonusScore += count * Judgement.ToNumericResult(result);
case HitResult.LargeTickMiss: maximum.BonusScore += count * Judgement.ToNumericResult(result);
maxResult = HitResult.LargeTickHit; }
break; else
{
// The maximum result of this judgement if it wasn't a miss.
// E.g. For a GOOD judgement, the max result is either GREAT/PERFECT depending on which one the ruleset uses (osu!: GREAT, osu!mania: PERFECT).
HitResult maxResult;
case HitResult.SmallTickHit: switch (result)
case HitResult.SmallTickMiss: {
maxResult = HitResult.SmallTickHit; case HitResult.LargeTickHit:
break; case HitResult.LargeTickMiss:
maxResult = HitResult.LargeTickHit;
break;
default: case HitResult.SmallTickHit:
maxResult = maxBasicResult ??= ruleset.GetHitResults().OrderByDescending(kvp => Judgement.ToNumericResult(kvp.result)).First().result; case HitResult.SmallTickMiss:
break; maxResult = HitResult.SmallTickHit;
break;
default:
maxResult = maxBasicResult ??= ruleset.GetHitResults().OrderByDescending(kvp => Judgement.ToNumericResult(kvp.result)).First().result;
break;
}
current.BaseScore += count * Judgement.ToNumericResult(result);
maximum.BaseScore += count * Judgement.ToNumericResult(maxResult);
} }
baseScore += count * Judgement.ToNumericResult(result);
maxBaseScore += count * Judgement.ToNumericResult(maxResult);
if (result.AffectsCombo()) if (result.AffectsCombo())
maxCombo += count; {
current.MaxCombo += count;
maximum.MaxCombo += count;
}
if (result.IsBasic()) if (result.IsBasic())
basicHitObjects += count; {
current.HitObjects += count;
maximum.HitObjects += count;
}
} }
} }