mirror of https://github.com/ppy/osu
Unify legacy total score / accuracy / rank recomputation flows
This commit is contained in:
parent
2958631c5d
commit
db4849442e
|
@ -355,8 +355,7 @@ private void convertLegacyTotalScoreToStandardised()
|
|||
realmAccess.Write(r =>
|
||||
{
|
||||
ScoreInfo s = r.Find<ScoreInfo>(id)!;
|
||||
// TODO: ensure that this is also updating rank (as it will set TotalScoreVersion to latest).
|
||||
StandardisedScoreMigrationTools.UpdateFromLegacy(s, beatmapManager);
|
||||
StandardisedScoreMigrationTools.UpdateFromLegacy(s, beatmapManager.GetWorkingBeatmap(s.BeatmapInfo));
|
||||
s.TotalScoreVersion = LegacyScoreEncoder.LATEST_VERSION;
|
||||
});
|
||||
|
||||
|
@ -412,8 +411,7 @@ private void upgradeScoreRanks()
|
|||
realmAccess.Write(r =>
|
||||
{
|
||||
ScoreInfo s = r.Find<ScoreInfo>(id)!;
|
||||
// TODO: uncomment when ready
|
||||
// s.Rank = StandardisedScoreMigrationTools.ComputeRank(s, beatmapManager);
|
||||
s.Rank = StandardisedScoreMigrationTools.ComputeRank(s);
|
||||
});
|
||||
|
||||
++processedCount;
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using osu.Framework.Logging;
|
||||
using osu.Game.Beatmaps;
|
||||
|
@ -235,39 +234,49 @@ static int numericScoreFor(HitResult result)
|
|||
/// Updates a legacy <see cref="ScoreInfo"/> to standardised scoring.
|
||||
/// </summary>
|
||||
/// <param name="score">The score to update.</param>
|
||||
/// <param name="beatmaps">A <see cref="BeatmapManager"/> used for <see cref="WorkingBeatmap"/> lookups.</param>
|
||||
public static void UpdateFromLegacy(ScoreInfo score, BeatmapManager beatmaps)
|
||||
/// <param name="beatmap">The <see cref="WorkingBeatmap"/> applicable for this score.</param>
|
||||
public static void UpdateFromLegacy(ScoreInfo score, WorkingBeatmap beatmap)
|
||||
{
|
||||
score.TotalScore = convertFromLegacyTotalScore(score, beatmaps);
|
||||
score.Accuracy = ComputeAccuracy(score);
|
||||
var ruleset = score.Ruleset.CreateInstance();
|
||||
var scoreProcessor = ruleset.CreateScoreProcessor();
|
||||
|
||||
score.TotalScore = convertFromLegacyTotalScore(score, ruleset, beatmap);
|
||||
score.Accuracy = computeAccuracy(score, scoreProcessor);
|
||||
score.Rank = computeRank(score, scoreProcessor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates a legacy <see cref="ScoreInfo"/> to standardised scoring.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This overload is intended for server-side flows.
|
||||
/// See: https://github.com/ppy/osu-queue-score-statistics/blob/3681e92ac91c6c61922094bdbc7e92e6217dd0fc/osu.Server.Queues.ScoreStatisticsProcessor/Commands/Queue/BatchInserter.cs
|
||||
/// </remarks>
|
||||
/// <param name="score">The score to update.</param>
|
||||
/// <param name="ruleset">The <see cref="Ruleset"/> in which the score was set.</param>
|
||||
/// <param name="difficulty">The beatmap difficulty.</param>
|
||||
/// <param name="attributes">The legacy scoring attributes for the beatmap which the score was set on.</param>
|
||||
public static void UpdateFromLegacy(ScoreInfo score, LegacyBeatmapConversionDifficultyInfo difficulty, LegacyScoreAttributes attributes)
|
||||
public static void UpdateFromLegacy(ScoreInfo score, Ruleset ruleset, LegacyBeatmapConversionDifficultyInfo difficulty, LegacyScoreAttributes attributes)
|
||||
{
|
||||
score.TotalScore = convertFromLegacyTotalScore(score, difficulty, attributes);
|
||||
score.Accuracy = ComputeAccuracy(score);
|
||||
var scoreProcessor = ruleset.CreateScoreProcessor();
|
||||
|
||||
score.TotalScore = convertFromLegacyTotalScore(score, ruleset, difficulty, attributes);
|
||||
score.Accuracy = computeAccuracy(score, scoreProcessor);
|
||||
score.Rank = computeRank(score, scoreProcessor);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts from <see cref="ScoreInfo.LegacyTotalScore"/> to the new standardised scoring of <see cref="ScoreProcessor"/>.
|
||||
/// </summary>
|
||||
/// <param name="score">The score to convert the total score of.</param>
|
||||
/// <param name="beatmaps">A <see cref="BeatmapManager"/> used for <see cref="WorkingBeatmap"/> lookups.</param>
|
||||
/// <param name="ruleset">The <see cref="Ruleset"/> in which the score was set.</param>
|
||||
/// <param name="beatmap">The <see cref="WorkingBeatmap"/> applicable for this score.</param>
|
||||
/// <returns>The standardised total score.</returns>
|
||||
private static long convertFromLegacyTotalScore(ScoreInfo score, BeatmapManager beatmaps)
|
||||
private static long convertFromLegacyTotalScore(ScoreInfo score, Ruleset ruleset, WorkingBeatmap beatmap)
|
||||
{
|
||||
if (!score.IsLegacyScore)
|
||||
return score.TotalScore;
|
||||
|
||||
WorkingBeatmap beatmap = beatmaps.GetWorkingBeatmap(score.BeatmapInfo);
|
||||
Ruleset ruleset = score.Ruleset.CreateInstance();
|
||||
|
||||
if (ruleset is not ILegacyRuleset legacyRuleset)
|
||||
return score.TotalScore;
|
||||
|
||||
|
@ -283,27 +292,28 @@ private static long convertFromLegacyTotalScore(ScoreInfo score, BeatmapManager
|
|||
ILegacyScoreSimulator sv1Simulator = legacyRuleset.CreateLegacyScoreSimulator();
|
||||
LegacyScoreAttributes attributes = sv1Simulator.Simulate(beatmap, playableBeatmap);
|
||||
|
||||
return convertFromLegacyTotalScore(score, LegacyBeatmapConversionDifficultyInfo.FromBeatmap(beatmap.Beatmap), attributes);
|
||||
return convertFromLegacyTotalScore(score, ruleset, LegacyBeatmapConversionDifficultyInfo.FromBeatmap(beatmap.Beatmap), attributes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts from <see cref="ScoreInfo.LegacyTotalScore"/> to the new standardised scoring of <see cref="ScoreProcessor"/>.
|
||||
/// </summary>
|
||||
/// <param name="score">The score to convert the total score of.</param>
|
||||
/// <param name="ruleset">The <see cref="Ruleset"/> in which the score was set.</param>
|
||||
/// <param name="difficulty">The beatmap difficulty.</param>
|
||||
/// <param name="attributes">The legacy scoring attributes for the beatmap which the score was set on.</param>
|
||||
/// <returns>The standardised total score.</returns>
|
||||
private static long convertFromLegacyTotalScore(ScoreInfo score, LegacyBeatmapConversionDifficultyInfo difficulty, LegacyScoreAttributes attributes)
|
||||
private static long convertFromLegacyTotalScore(ScoreInfo score, Ruleset ruleset, LegacyBeatmapConversionDifficultyInfo difficulty, LegacyScoreAttributes attributes)
|
||||
{
|
||||
if (!score.IsLegacyScore)
|
||||
return score.TotalScore;
|
||||
|
||||
Debug.Assert(score.LegacyTotalScore != null);
|
||||
|
||||
Ruleset ruleset = score.Ruleset.CreateInstance();
|
||||
if (ruleset is not ILegacyRuleset legacyRuleset)
|
||||
return score.TotalScore;
|
||||
|
||||
// ensure legacy total score is saved for later.
|
||||
score.LegacyTotalScore = score.TotalScore;
|
||||
|
||||
double legacyModMultiplier = legacyRuleset.CreateLegacyScoreSimulator().GetLegacyScoreMultiplier(score.Mods, difficulty);
|
||||
int maximumLegacyAccuracyScore = attributes.AccuracyScore;
|
||||
long maximumLegacyComboScore = (long)Math.Round(attributes.ComboScore * legacyModMultiplier);
|
||||
|
@ -584,11 +594,10 @@ double estimateDroppedComboScoreAfterMiss(int lengthOfComboAfterMiss)
|
|||
}
|
||||
}
|
||||
|
||||
public static double ComputeAccuracy(ScoreInfo scoreInfo)
|
||||
{
|
||||
Ruleset ruleset = scoreInfo.Ruleset.CreateInstance();
|
||||
ScoreProcessor scoreProcessor = ruleset.CreateScoreProcessor();
|
||||
public static double ComputeAccuracy(ScoreInfo scoreInfo) => computeAccuracy(scoreInfo, scoreInfo.Ruleset.CreateInstance().CreateScoreProcessor());
|
||||
|
||||
private static double computeAccuracy(ScoreInfo scoreInfo, ScoreProcessor scoreProcessor)
|
||||
{
|
||||
int baseScore = scoreInfo.Statistics.Where(kvp => kvp.Key.AffectsAccuracy())
|
||||
.Sum(kvp => kvp.Value * scoreProcessor.GetBaseScoreForResult(kvp.Key));
|
||||
int maxBaseScore = scoreInfo.MaximumStatistics.Where(kvp => kvp.Key.AffectsAccuracy())
|
||||
|
@ -597,10 +606,11 @@ public static double ComputeAccuracy(ScoreInfo scoreInfo)
|
|||
return maxBaseScore == 0 ? 1 : baseScore / (double)maxBaseScore;
|
||||
}
|
||||
|
||||
public static ScoreRank ComputeRank(ScoreInfo scoreInfo)
|
||||
public static ScoreRank ComputeRank(ScoreInfo scoreInfo) => computeRank(scoreInfo, scoreInfo.Ruleset.CreateInstance().CreateScoreProcessor());
|
||||
|
||||
private static ScoreRank computeRank(ScoreInfo scoreInfo, ScoreProcessor scoreProcessor)
|
||||
{
|
||||
Ruleset ruleset = scoreInfo.Ruleset.CreateInstance();
|
||||
var rank = ruleset.CreateScoreProcessor().RankFromScore(scoreInfo.Accuracy, scoreInfo.Statistics);
|
||||
var rank = scoreProcessor.RankFromScore(scoreInfo.Accuracy, scoreInfo.Statistics);
|
||||
|
||||
foreach (var mod in scoreInfo.Mods.OfType<IApplicableToScoreProcessor>())
|
||||
rank = mod.AdjustRank(rank, scoreInfo.Accuracy);
|
||||
|
|
|
@ -134,8 +134,7 @@ public Score Parse(Stream stream)
|
|||
}
|
||||
|
||||
PopulateMaximumStatistics(score.ScoreInfo, workingBeatmap);
|
||||
score.ScoreInfo.Accuracy = StandardisedScoreMigrationTools.ComputeAccuracy(score.ScoreInfo);
|
||||
score.ScoreInfo.Rank = StandardisedScoreMigrationTools.ComputeRank(score.ScoreInfo);
|
||||
StandardisedScoreMigrationTools.UpdateFromLegacy(score.ScoreInfo, workingBeatmap);
|
||||
|
||||
// before returning for database import, we must restore the database-sourced BeatmapInfo.
|
||||
// if not, the clone operation in GetPlayableBeatmap will cause a dereference and subsequent database exception.
|
||||
|
@ -342,18 +341,6 @@ public static void PopulateLegacyAccuracyAndRank(ScoreInfo score)
|
|||
}
|
||||
}
|
||||
|
||||
private void populateLazerAccuracyAndRank(ScoreInfo scoreInfo)
|
||||
{
|
||||
scoreInfo.Accuracy = StandardisedScoreMigrationTools.ComputeAccuracy(scoreInfo);
|
||||
|
||||
var rank = currentRuleset.CreateScoreProcessor().RankFromScore(scoreInfo.Accuracy, scoreInfo.Statistics);
|
||||
|
||||
foreach (var mod in scoreInfo.Mods.OfType<IApplicableToScoreProcessor>())
|
||||
rank = mod.AdjustRank(rank, scoreInfo.Accuracy);
|
||||
|
||||
scoreInfo.Rank = rank;
|
||||
}
|
||||
|
||||
private void readLegacyReplay(Replay replay, StreamReader reader)
|
||||
{
|
||||
float lastTime = beatmapOffset;
|
||||
|
|
|
@ -100,11 +100,6 @@ protected override void Populate(ScoreInfo model, ArchiveReader? archive, Realm
|
|||
// this requires: max combo, statistics, max statistics (where available), and mods to already be populated on the score.
|
||||
if (StandardisedScoreMigrationTools.ShouldMigrateToNewStandardised(model))
|
||||
model.TotalScore = StandardisedScoreMigrationTools.GetNewStandardised(model);
|
||||
else if (model.IsLegacyScore)
|
||||
{
|
||||
model.LegacyTotalScore = model.TotalScore;
|
||||
StandardisedScoreMigrationTools.UpdateFromLegacy(model, beatmaps());
|
||||
}
|
||||
}
|
||||
|
||||
// Very naive local caching to improve performance of large score imports (where the username is usually the same for most or all scores).
|
||||
|
|
Loading…
Reference in New Issue