Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add capability to verify maximum statistics of scores #306

Merged
merged 1 commit into from
Dec 6, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -101,6 +103,7 @@ public async Task<int> 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) "
Expand Down Expand Up @@ -244,6 +247,12 @@ public async Task<int> 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};");
Copy link
Collaborator Author

@bdach bdach Nov 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quoting of the maximum statistics is a bit dodgy here but not super sure how to make it any better... It sorta relies on the json serialisation never outputting a quote which is a bit scary.

}
}
finally
{
Expand Down Expand Up @@ -318,6 +327,27 @@ private bool check<T>(ulong scoreId, string name, T imported, T original)
return true;
}

private bool checkDictionary<TKey, TValue>(ulong scoreId, string name, IDictionary<TKey, TValue>? imported, IDictionary<TKey, TValue>? 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<TValue>.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
{
Expand All @@ -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<SoloScoreData>(value);
if (soloScoreData != null)
ScoreData = soloScoreData;
}
}

public HighScore? HighScore { get; set; }
public ScoreInfo? ReferenceScore { get; set; }
}
Expand Down
Loading