From 1944c255a78575a0e075642f66e1ca3655fd2d80 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Thu, 28 Oct 2021 18:23:52 +0900 Subject: [PATCH] Implement score interfaces --- .../Gameplay/TestSceneReplayDownloadButton.cs | 2 +- .../Online/API/Requests/GetScoresRequest.cs | 10 +- .../API/Requests/Responses/APIScoreInfo.cs | 113 ++++++++++-------- .../Responses/APIScoreWithPosition.cs | 1 + osu.Game/Scoring/IScoreInfo.cs | 31 +++-- osu.Game/Scoring/ScoreInfo.cs | 7 +- osu.Game/Screens/Ranking/SoloResultsScreen.cs | 2 +- 7 files changed, 95 insertions(+), 71 deletions(-) diff --git a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs index 20dec46101..b84ac6c2f1 100644 --- a/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs +++ b/osu.Game.Tests/Visual/Gameplay/TestSceneReplayDownloadButton.cs @@ -134,7 +134,7 @@ namespace osu.Game.Tests.Visual.Gameplay { return new APIScoreInfo { - OnlineScoreID = 2553163309, + OnlineID = 2553163309, OnlineRulesetID = 0, Replay = replayAvailable, User = new User diff --git a/osu.Game/Online/API/Requests/GetScoresRequest.cs b/osu.Game/Online/API/Requests/GetScoresRequest.cs index 11b0cdddd8..9037869c77 100644 --- a/osu.Game/Online/API/Requests/GetScoresRequest.cs +++ b/osu.Game/Online/API/Requests/GetScoresRequest.cs @@ -38,20 +38,20 @@ namespace osu.Game.Online.API.Requests private void onSuccess(APIScoresCollection r) { - Debug.Assert(ruleset.ID != null, "ruleset.ID != null"); + Debug.Assert(ruleset.OnlineID >= 0); foreach (APIScoreInfo score in r.Scores) { - score.BeatmapInfo = beatmapInfo; - score.OnlineRulesetID = ruleset.ID.Value; + score.Beatmap = beatmapInfo; + score.OnlineRulesetID = ruleset.OnlineID; } var userScore = r.UserScore; if (userScore != null) { - userScore.Score.BeatmapInfo = beatmapInfo; - userScore.Score.OnlineRulesetID = ruleset.ID.Value; + userScore.Score.Beatmap = beatmapInfo; + userScore.Score.OnlineRulesetID = ruleset.OnlineID; } } diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs index c977d27a68..568c6bea7f 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreInfo.cs @@ -9,14 +9,71 @@ using Newtonsoft.Json.Converters; using osu.Game.Beatmaps; using osu.Game.Rulesets; using osu.Game.Rulesets.Mods; +using osu.Game.Rulesets.Scoring; using osu.Game.Scoring; using osu.Game.Scoring.Legacy; using osu.Game.Users; namespace osu.Game.Online.API.Requests.Responses { - public class APIScoreInfo + public class APIScoreInfo : IScoreInfo { + [JsonProperty(@"score")] + public long TotalScore { get; set; } + + [JsonProperty(@"max_combo")] + public int MaxCombo { get; set; } + + [JsonProperty(@"user")] + public User User { get; set; } + + public bool HasReplay { get; set; } + + [JsonProperty(@"id")] + public long OnlineID { get; set; } + + [JsonProperty(@"replay")] + public bool Replay { get; set; } + + [JsonProperty(@"created_at")] + public DateTimeOffset Date { get; set; } + + [JsonProperty(@"beatmap")] + public IBeatmapInfo Beatmap { get; set; } + + [JsonProperty("accuracy")] + public double Accuracy { get; set; } + + [JsonProperty(@"pp")] + public double? PP { get; set; } + + [JsonProperty(@"beatmapset")] + public APIBeatmapSet BeatmapSet + { + set + { + // in the deserialisation case we need to ferry this data across. + if (Beatmap is APIBeatmap apiBeatmap) + apiBeatmap.BeatmapSet = value; + } + } + + [JsonProperty("statistics")] + public Dictionary Statistics { get; set; } + + [JsonProperty(@"mode_int")] + public int OnlineRulesetID { get; set; } + + [JsonProperty(@"mods")] + public string[] Mods { get; set; } + + [JsonProperty("rank")] + [JsonConverter(typeof(StringEnumConverter))] + public ScoreRank Rank { get; set; } + + IBeatmapInfo IScoreInfo.Beatmap => Beatmap; + + // TODO: nuke public ScoreInfo CreateScoreInfo(RulesetStore rulesets) { var ruleset = rulesets.GetRuleset(OnlineRulesetID); @@ -34,10 +91,10 @@ namespace osu.Game.Online.API.Requests.Responses MaxCombo = MaxCombo, User = User, Accuracy = Accuracy, - OnlineScoreID = OnlineScoreID, + OnlineScoreID = OnlineID, Date = Date, PP = PP, - BeatmapInfo = BeatmapInfo, + BeatmapInfo = Beatmap.ToBeatmapInfo(rulesets), RulesetID = OnlineRulesetID, Hash = Replay ? "online" : string.Empty, // todo: temporary? Rank = Rank, @@ -81,57 +138,19 @@ namespace osu.Game.Online.API.Requests.Responses return scoreInfo; } - [JsonProperty(@"score")] - public int TotalScore { get; set; } - - [JsonProperty(@"max_combo")] - public int MaxCombo { get; set; } - - [JsonProperty(@"user")] - public User User { get; set; } - - [JsonProperty(@"id")] - public long OnlineScoreID { get; set; } - - [JsonProperty(@"replay")] - public bool Replay { get; set; } - - [JsonProperty(@"created_at")] - public DateTimeOffset Date { get; set; } - - [JsonProperty(@"beatmap")] - public BeatmapInfo BeatmapInfo { get; set; } - - [JsonProperty("accuracy")] - public double Accuracy { get; set; } - - [JsonProperty(@"pp")] - public double? PP { get; set; } - [JsonProperty(@"beatmapset")] - public BeatmapMetadata Metadata + public APIBeatmapSet Metadata { set { - // extract the set ID to its correct place. - BeatmapInfo.BeatmapSet = new BeatmapSetInfo { OnlineBeatmapSetID = value.ID }; - value.ID = 0; - - BeatmapInfo.Metadata = value; + // in the deserialisation case we need to ferry this data across. + if (Beatmap is APIBeatmap apiBeatmap) + apiBeatmap.BeatmapSet = value; } } - [JsonProperty(@"statistics")] - public Dictionary Statistics { get; set; } + public IRulesetInfo Ruleset => new RulesetInfo { ID = OnlineRulesetID }; - [JsonProperty(@"mode_int")] - public int OnlineRulesetID { get; set; } - - [JsonProperty(@"mods")] - public string[] Mods { get; set; } - - [JsonProperty("rank")] - [JsonConverter(typeof(StringEnumConverter))] - public ScoreRank Rank { get; set; } + Dictionary IScoreInfo.Statistics => new Dictionary(); // TODO: implement... maybe. hitresults have weird mappings per ruleset it would seem. } } diff --git a/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs b/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs index 9c97ad4f05..89bb416393 100644 --- a/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs +++ b/osu.Game/Online/API/Requests/Responses/APIScoreWithPosition.cs @@ -16,6 +16,7 @@ namespace osu.Game.Online.API.Requests.Responses public APIScoreInfo Score; public ScoreInfo CreateScoreInfo(RulesetStore rulesets) + { var score = Score.CreateScoreInfo(rulesets); score.Position = Position; diff --git a/osu.Game/Scoring/IScoreInfo.cs b/osu.Game/Scoring/IScoreInfo.cs index c783a77203..b230babf3c 100644 --- a/osu.Game/Scoring/IScoreInfo.cs +++ b/osu.Game/Scoring/IScoreInfo.cs @@ -5,38 +5,37 @@ using System; using System.Collections.Generic; using osu.Game.Beatmaps; using osu.Game.Database; +using osu.Game.Rulesets; +using osu.Game.Rulesets.Scoring; using osu.Game.Users; namespace osu.Game.Scoring { public interface IScoreInfo : IHasOnlineID { - int TotalScore { get; set; } + User User { get; } - int MaxCombo { get; set; } + long TotalScore { get; } - User User { get; set; } + int MaxCombo { get; } - long OnlineScoreID { get; set; } + double Accuracy { get; } - bool Replay { get; set; } + bool HasReplay { get; } - DateTimeOffset Date { get; set; } + DateTimeOffset Date { get; } - BeatmapInfo BeatmapInfo { get; set; } + double? PP { get; } - double Accuracy { get; set; } + IBeatmapInfo Beatmap { get; } - double? PP { get; set; } + Dictionary Statistics { get; } - BeatmapMetadata Metadata { get; set; } + IRulesetInfo Ruleset { get; } - Dictionary Statistics { get; set; } + public ScoreRank Rank { get; } - int OnlineRulesetID { get; set; } - - string[] Mods { get; set; } - - public ScoreRank Rank { get; set; } + // Mods is currently missing from this interface as the `IMod` class has properties which can't be fulfilled by `APIMod`, + // but also doesn't expose `Settings`. We can consider how to implement this in the future if required. } } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 0afec89450..3b09669926 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -57,6 +57,7 @@ namespace osu.Game.Scoring public RulesetInfo Ruleset { get; set; } private APIMod[] localAPIMods; + private Mod[] mods; [JsonIgnore] @@ -160,7 +161,7 @@ namespace osu.Game.Scoring public DateTimeOffset Date { get; set; } [JsonProperty("statistics")] - public Dictionary Statistics = new Dictionary(); + public Dictionary Statistics { get; set; } = new Dictionary(); [JsonIgnore] [Column("Statistics")] @@ -273,5 +274,9 @@ namespace osu.Game.Scoring } public long OnlineID => OnlineScoreID ?? -1; + + IBeatmapInfo IScoreInfo.Beatmap => BeatmapInfo; + IRulesetInfo IScoreInfo.Ruleset => Ruleset; + bool IScoreInfo.HasReplay => Files.Any(); } } diff --git a/osu.Game/Screens/Ranking/SoloResultsScreen.cs b/osu.Game/Screens/Ranking/SoloResultsScreen.cs index 5e582a8dcb..684c7574cb 100644 --- a/osu.Game/Screens/Ranking/SoloResultsScreen.cs +++ b/osu.Game/Screens/Ranking/SoloResultsScreen.cs @@ -31,7 +31,7 @@ namespace osu.Game.Screens.Ranking return null; getScoreRequest = new GetScoresRequest(Score.BeatmapInfo, Score.Ruleset); - getScoreRequest.Success += r => scoresCallback?.Invoke(r.Scores.Where(s => s.OnlineScoreID != Score.OnlineScoreID).Select(s => s.CreateScoreInfo(rulesets))); + getScoreRequest.Success += r => scoresCallback?.Invoke(r.Scores.Where(s => s.OnlineID != Score.OnlineScoreID).Select(s => s.CreateScoreInfo(rulesets))); return getScoreRequest; }