diff --git a/osu.Server.Queues.ScoreStatisticsProcessor/Commands/Maintenance/VerifyImportedScoresCommand.cs b/osu.Server.Queues.ScoreStatisticsProcessor/Commands/Maintenance/VerifyImportedScoresCommand.cs index 43a7c145..ba41047a 100644 --- a/osu.Server.Queues.ScoreStatisticsProcessor/Commands/Maintenance/VerifyImportedScoresCommand.cs +++ b/osu.Server.Queues.ScoreStatisticsProcessor/Commands/Maintenance/VerifyImportedScoresCommand.cs @@ -11,10 +11,12 @@ using Dapper; using McMaster.Extensions.CommandLineUtils; using MySqlConnector; +using Newtonsoft.Json; using osu.Game.Scoring; using osu.Server.QueueProcessor; using osu.Server.Queues.ScoreStatisticsProcessor.Commands.Queue; using osu.Server.Queues.ScoreStatisticsProcessor.Helpers; +using osu.Server.Queues.ScoreStatisticsProcessor.Models; using StringBuilder = System.Text.StringBuilder; namespace osu.Server.Queues.ScoreStatisticsProcessor.Commands.Maintenance @@ -101,6 +103,7 @@ public async Task OnExecuteAsync(CancellationToken cancellationToken) + "s.ranked," + "s.`rank`, " + "s.`pp`, " + + "s.`data`, " + "h.* " + "FROM scores s " + $"LEFT JOIN {rulesetSpecifics.HighScoreTable} h ON (legacy_score_id = score_id) " @@ -244,6 +247,12 @@ public async Task OnExecuteAsync(CancellationToken cancellationToken) requiresIndexing = true; sqlBuffer.Append($"UPDATE scores SET `rank` = '{referenceScore.Rank.ToString()}' WHERE `id` = {importedScore.id};"); } + + if (!checkDictionary(importedScore.id, "maximum_statistics", importedScore.ScoreData.MaximumStatistics, referenceScore.MaximumStatistics)) + { + Interlocked.Increment(ref fail); + sqlBuffer.Append($"UPDATE `scores` SET `data` = JSON_SET(`data`, '$.maximum_statistics', CAST('{JsonConvert.SerializeObject(referenceScore.MaximumStatistics)}' AS JSON)) WHERE `id` = {importedScore.id};"); + } } finally { @@ -318,6 +327,27 @@ private bool check(ulong scoreId, string name, T imported, T original) return true; } + private bool checkDictionary(ulong scoreId, string name, IDictionary? imported, IDictionary? original) + { + if (imported == null && original == null) + return true; + + if (imported == null || original == null) + return false; + + bool equal = imported.Count == original.Count + && imported.All(kv => original.TryGetValue(kv.Key, out var originalValue) && EqualityComparer.Default.Equals(kv.Value, originalValue)); + + if (!equal) + { + if (Verbose) + Console.WriteLine($"{scoreId}: {name} doesn't match ({JsonConvert.SerializeObject(imported)} vs {JsonConvert.SerializeObject(original)})"); + return false; + } + + return true; + } + [SuppressMessage("ReSharper", "InconsistentNaming")] public class ComparableScore { @@ -331,6 +361,19 @@ public class ComparableScore public bool ranked; public float? pp; + public SoloScoreData ScoreData = new SoloScoreData(); + + public string data + { + get => JsonConvert.SerializeObject(ScoreData); + set + { + var soloScoreData = JsonConvert.DeserializeObject(value); + if (soloScoreData != null) + ScoreData = soloScoreData; + } + } + public HighScore? HighScore { get; set; } public ScoreInfo? ReferenceScore { get; set; } }