From 1bef2d7b3946d6856da6574aa1cbaed244547755 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Tue, 12 Jul 2022 04:04:21 +0900 Subject: [PATCH] Add and consume `SoloScoreInfo` --- osu.Game/Online/API/APIAccess.cs | 2 +- .../Responses/APIScoreWithPosition.cs | 4 +- .../Requests/Responses/APIScoresCollection.cs | 2 +- .../API/Requests/Responses/SoloScoreInfo.cs | 124 ++++++++++++++++++ .../BeatmapSet/Scores/ScoresContainer.cs | 2 +- 5 files changed, 129 insertions(+), 5 deletions(-) create mode 100644 osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs diff --git a/osu.Game/Online/API/APIAccess.cs b/osu.Game/Online/API/APIAccess.cs index 088dc56701..43cea7fb97 100644 --- a/osu.Game/Online/API/APIAccess.cs +++ b/osu.Game/Online/API/APIAccess.cs @@ -38,7 +38,7 @@ namespace osu.Game.Online.API public string WebsiteRootUrl { get; } - public int APIVersion => 20220217; // We may want to pull this from the game version eventually. + public int APIVersion => 20220705; // We may want to pull this from the game version eventually. public Exception LastLoginError { get; private set; } diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs b/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs index 8bd54f889d..494826f534 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs @@ -16,11 +16,11 @@ namespace osu.Game.Online.API.Requests.Responses public int? Position; [JsonProperty(@"score")] - public APIScore Score; + public SoloScoreInfo Score; public ScoreInfo CreateScoreInfo(RulesetStore rulesets, BeatmapInfo beatmap = null) { - var score = Score.CreateScoreInfo(rulesets, beatmap); + var score = Score.ToScoreInfo(rulesets, beatmap); score.Position = Position; return score; } diff --git a/osu.Game/Online/API/Requests/Responses/APIScoresCollection.cs b/osu.Game/Online/API/Requests/Responses/APIScoresCollection.cs index 9c8a38c63a..38c67d92f4 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoresCollection.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoresCollection.cs @@ -11,7 +11,7 @@ namespace osu.Game.Online.API.Requests.Responses public class APIScoresCollection { [JsonProperty(@"scores")] - public List Scores; + public List Scores; [JsonProperty(@"userScore")] public APIScoreWithPosition UserScore; diff --git a/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs new file mode 100644 index 0000000000..71479d2867 --- /dev/null +++ b/osu.Game/Online/API/Requests/Responses/SoloScoreInfo.cs @@ -0,0 +1,124 @@ +// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. +// See the LICENCE file in the repository root for full licence text. + +#nullable disable +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using System.Linq; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; +using osu.Game.Beatmaps; +using osu.Game.Database; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; +using osu.Game.Scoring; + +namespace osu.Game.Online.API.Requests.Responses +{ + [SuppressMessage("ReSharper", "InconsistentNaming")] + [Serializable] + public class SoloScoreInfo : IHasOnlineID + { + [JsonIgnore] + public long id { get; set; } + + public int user_id { get; set; } + + public int beatmap_id { get; set; } + + public int ruleset_id { get; set; } + + public int? build_id { get; set; } + + public bool passed { get; set; } + + public int total_score { get; set; } + + public double accuracy { get; set; } + + public APIUser user { get; set; } + + // TODO: probably want to update this column to match user stats (short)? + public int max_combo { get; set; } + + [JsonConverter(typeof(StringEnumConverter))] + public ScoreRank rank { get; set; } + + public DateTimeOffset? started_at { get; set; } + + public DateTimeOffset? ended_at { get; set; } + + public List mods { get; set; } = new List(); + + [JsonProperty("statistics")] + public Dictionary Statistics { get; set; } = new Dictionary(); + + public override string ToString() => $"score_id: {id} user_id: {user_id}"; + + [JsonIgnore] + public DateTimeOffset created_at { get; set; } + + [JsonIgnore] + public DateTimeOffset updated_at { get; set; } + + [JsonIgnore] + public DateTimeOffset? deleted_at { get; set; } + + /// + /// Create a from an API score instance. + /// + /// A ruleset store, used to populate a ruleset instance in the returned score. + /// An optional beatmap, copied into the returned score (for cases where the API does not populate the beatmap). + /// + public ScoreInfo CreateScoreInfo(RulesetStore rulesets, BeatmapInfo beatmap = null) + { + var ruleset = rulesets.GetRuleset(ruleset_id) ?? throw new InvalidOperationException($"Ruleset with ID of {ruleset_id} not found locally"); + + var rulesetInstance = ruleset.CreateInstance(); + + var modInstances = mods.Select(apiMod => rulesetInstance.CreateModFromAcronym(apiMod.Acronym)).Where(m => m != null).ToArray(); + + // all API scores provided by this class are considered to be legacy. + modInstances = modInstances.Append(rulesetInstance.CreateMod()).ToArray(); + + var scoreInfo = new ScoreInfo + { + User = user ?? new APIUser { Id = user_id }, + BeatmapInfo = beatmap ?? new BeatmapInfo { OnlineID = beatmap_id }, + Passed = passed, + TotalScore = total_score, + Accuracy = accuracy, + MaxCombo = max_combo, + Rank = rank, + Statistics = Statistics, + OnlineID = OnlineID, + Date = ended_at ?? DateTimeOffset.Now, + // PP = + Hash = "online", // TODO: temporary? + Ruleset = ruleset, + Mods = modInstances, + }; + + return scoreInfo; + } + + public ScoreInfo CreateScoreInfo(Mod[] mods) => new ScoreInfo + { + OnlineID = id, + User = new APIUser { Id = user_id }, + BeatmapInfo = new BeatmapInfo { OnlineID = beatmap_id }, + Ruleset = new RulesetInfo { OnlineID = ruleset_id }, + Passed = passed, + TotalScore = total_score, + Accuracy = accuracy, + MaxCombo = max_combo, + Rank = rank, + Mods = mods, + Statistics = Statistics + }; + + public long OnlineID => id; + } +} diff --git a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs index c2e54d0d7b..98202ba7c0 100644 --- a/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs +++ b/osu.Game/Overlays/BeatmapSet/Scores/ScoresContainer.cs @@ -101,7 +101,7 @@ namespace osu.Game.Overlays.BeatmapSet.Scores scoreTable.Show(); var userScore = value.UserScore; - var userScoreInfo = userScore?.Score.CreateScoreInfo(rulesets, beatmapInfo); + var userScoreInfo = userScore?.Score.ToScoreInfo(rulesets, beatmapInfo); topScoresContainer.Add(new DrawableTopScore(topScore));