From 45981125860b331d5f5dbaa59966e6d354f2fd4c Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 5 Feb 2023 21:46:38 +0300 Subject: [PATCH 01/22] Add OriginalBeatmapHash to ScoreInfo. Update db schema_version, migration --- osu.Game/Beatmaps/BeatmapManager.cs | 8 ++++++++ osu.Game/Database/RealmAccess.cs | 15 +++++++++++++++ osu.Game/Scoring/ScoreInfo.cs | 2 ++ 3 files changed, 25 insertions(+) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index ad56bbbc3a..e972f067ca 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -13,6 +13,7 @@ using System.Threading.Tasks; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Extensions; +using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Framework.Testing; @@ -25,6 +26,7 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; +using osu.Game.Scoring; using osu.Game.Skinning; using osu.Game.Utils; @@ -454,6 +456,12 @@ namespace osu.Game.Beatmaps if (transferCollections) beatmapInfo.TransferCollectionReferences(r, oldMd5Hash); + //Unlinking all scores from this beatmap + r.All().Where(s => s.BeatmapInfoID == beatmapInfo.ID).ForEach(s => s.BeatmapInfo = new BeatmapInfo()); + + //Linking all the previos scores + r.All().Where(s => s.OriginalBeatmapHash == beatmapInfo.Hash).ForEach(s => s.BeatmapInfo = beatmapInfo); + ProcessBeatmap?.Invoke((liveBeatmapSet, false)); }); } diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 177c671bca..422ceb8af3 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -70,6 +70,7 @@ namespace osu.Game.Database /// 23 2022-08-01 Added LastLocalUpdate to BeatmapInfo. /// 24 2022-08-22 Added MaximumStatistics to ScoreInfo. /// 25 2022-09-18 Remove skins to add with new naming. + /// 26 2023-02-05 Added OriginalBeatmapHash to ScoreInfo. /// private const int schema_version = 25; @@ -865,6 +866,20 @@ namespace osu.Game.Database case 25: // Remove the default skins so they can be added back by SkinManager with updated naming. migration.NewRealm.RemoveRange(migration.NewRealm.All().Where(s => s.Protected)); + break; + case 26: + // Adding origin beatmap hash property to ensure the score corresponds to the version of beatmap it should + // See: https://github.com/ppy/osu/issues/22062 + string ScoreInfoName = getMappedOrOriginalName(typeof(ScoreInfo)); + + var oldScoreInfos = migration.OldRealm.DynamicApi.All(ScoreInfoName); + var newScoreInfos = migration.NewRealm.All(); + + for (int i = 0; i < newScoreInfos.Count(); i++) + { + newScoreInfos.ElementAt(i).OriginalBeatmapHash = oldScoreInfos.ElementAt(i).BeatmapInfo.Hash; + } + break; } } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 1009474d89..2c029bbe68 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -66,6 +66,8 @@ namespace osu.Game.Scoring [MapTo("MaximumStatistics")] public string MaximumStatisticsJson { get; set; } = string.Empty; + public string OriginalBeatmapHash { get; set; } = string.Empty; + public ScoreInfo(BeatmapInfo? beatmap = null, RulesetInfo? ruleset = null, RealmUser? realmUser = null) { Ruleset = ruleset ?? new RulesetInfo(); From d23e787bc1f341ae41c3fa5a21467d0c9f320973 Mon Sep 17 00:00:00 2001 From: Cootz Date: Sun, 5 Feb 2023 21:55:50 +0300 Subject: [PATCH 02/22] Update `schema_version` --- osu.Game/Database/RealmAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 422ceb8af3..6f85b3f1be 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -72,7 +72,7 @@ namespace osu.Game.Database /// 25 2022-09-18 Remove skins to add with new naming. /// 26 2023-02-05 Added OriginalBeatmapHash to ScoreInfo. /// - private const int schema_version = 25; + private const int schema_version = 26; /// /// Lock object which is held during sections, blocking realm retrieval during blocking periods. From b00848e742d48ef08849d5115690909109c88de9 Mon Sep 17 00:00:00 2001 From: Cootz Date: Mon, 6 Feb 2023 13:58:41 +0300 Subject: [PATCH 03/22] Fix realm error. Apply `OriginalBeatmapHash` on import --- osu.Game/Beatmaps/BeatmapManager.cs | 6 ------ osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs | 1 + 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index e972f067ca..b46859cc59 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -456,12 +456,6 @@ namespace osu.Game.Beatmaps if (transferCollections) beatmapInfo.TransferCollectionReferences(r, oldMd5Hash); - //Unlinking all scores from this beatmap - r.All().Where(s => s.BeatmapInfoID == beatmapInfo.ID).ForEach(s => s.BeatmapInfo = new BeatmapInfo()); - - //Linking all the previos scores - r.All().Where(s => s.OriginalBeatmapHash == beatmapInfo.Hash).ForEach(s => s.BeatmapInfo = beatmapInfo); - ProcessBeatmap?.Invoke((liveBeatmapSet, false)); }); } diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs index 6f0b0c62f8..4bd068ca0f 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs @@ -123,6 +123,7 @@ namespace osu.Game.Scoring.Legacy // 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. score.ScoreInfo.BeatmapInfo = workingBeatmap.BeatmapInfo; + score.ScoreInfo.OriginalBeatmapHash = workingBeatmap.BeatmapInfo.Hash; return score; } From 2c7386db39d894cfa8ef335e7c58659399ed2e19 Mon Sep 17 00:00:00 2001 From: Cootz Date: Mon, 6 Feb 2023 15:14:14 +0300 Subject: [PATCH 04/22] FIx score appearing on `BeatmapLeaderboard` and `TopLocalRank` --- osu.Game/Screens/Play/Player.cs | 1 + osu.Game/Screens/Select/Carousel/TopLocalRank.cs | 1 + osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs | 1 + 3 files changed, 3 insertions(+) diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 0d208e6d9b..7bd020db93 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -248,6 +248,7 @@ namespace osu.Game.Screens.Play // ensure the score is in a consistent state with the current player. Score.ScoreInfo.BeatmapInfo = Beatmap.Value.BeatmapInfo; + Score.ScoreInfo.OriginalBeatmapHash = Beatmap.Value.BeatmapInfo.Hash; Score.ScoreInfo.Ruleset = ruleset.RulesetInfo; Score.ScoreInfo.Mods = gameplayMods; diff --git a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs index f1b773c831..3df72f7d3b 100644 --- a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs +++ b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs @@ -65,6 +65,7 @@ namespace osu.Game.Screens.Select.Carousel r.All() .Filter($"{nameof(ScoreInfo.User)}.{nameof(RealmUser.OnlineID)} == $0" + $" && {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.ID)} == $1" + + $" && {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.Hash)} == {nameof(ScoreInfo.OriginalBeatmapHash)}" + $" && {nameof(ScoreInfo.Ruleset)}.{nameof(RulesetInfo.ShortName)} == $2" + $" && {nameof(ScoreInfo.DeletePending)} == false", api.LocalUser.Value.Id, beatmapInfo.ID, ruleset.Value.ShortName), localScoresChanged); diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 5c720c8491..3e90d2465b 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -191,6 +191,7 @@ namespace osu.Game.Screens.Select.Leaderboards scoreSubscription = realm.RegisterForNotifications(r => r.All().Filter($"{nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.ID)} == $0" + + $" AND {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.Hash)} == {nameof(ScoreInfo.OriginalBeatmapHash)}" + $" AND {nameof(ScoreInfo.Ruleset)}.{nameof(RulesetInfo.ShortName)} == $1" + $" AND {nameof(ScoreInfo.DeletePending)} == false" , beatmapInfo.ID, ruleset.Value.ShortName), localScoresChanged); From cb26601cb4be90a62d898d230a14ac9cb667ecc3 Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 7 Feb 2023 02:29:28 +0300 Subject: [PATCH 05/22] Fix test's score generation --- osu.Game.Tests/Resources/TestResources.cs | 1 + .../Visual/SongSelect/TestSceneBeatmapLeaderboard.cs | 10 ++++++++++ .../Visual/UserInterface/TestSceneDeleteLocalScore.cs | 1 + 3 files changed, 12 insertions(+) diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index adf28afc8e..f65d427649 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -176,6 +176,7 @@ namespace osu.Game.Tests.Resources CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", }, BeatmapInfo = beatmap, + OriginalBeatmapHash = beatmap.Hash, Ruleset = beatmap.Ruleset, Mods = new Mod[] { new TestModHardRock(), new TestModDoubleTime() }, TotalScore = 2845370, diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index ef0ad6c25c..7a578230d9 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -210,6 +210,7 @@ namespace osu.Game.Tests.Visual.SongSelect }, Ruleset = new OsuRuleset().RulesetInfo, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, User = new APIUser { Id = 6602580, @@ -226,6 +227,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddSeconds(-30), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser { @@ -243,6 +245,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddSeconds(-70), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -261,6 +264,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddMinutes(-40), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -279,6 +283,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-2), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -297,6 +302,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-25), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -315,6 +321,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-50), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -333,6 +340,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-72), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -351,6 +359,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddMonths(-3), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -369,6 +378,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddYears(-2), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index 7635c61867..14193b1ac8 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -94,6 +94,7 @@ namespace osu.Game.Tests.Visual.UserInterface { OnlineID = i, BeatmapInfo = beatmapInfo, + OriginalBeatmapHash = beatmapInfo.Hash, Accuracy = RNG.NextDouble(), TotalScore = RNG.Next(1, 1000000), MaxCombo = RNG.Next(1, 1000), From 723f13af259da2e022a5c25b61d84b67c8ad75a9 Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 7 Feb 2023 02:43:27 +0300 Subject: [PATCH 06/22] Add summary for `OriginalBeatmapHash` --- osu.Game/Scoring/ScoreInfo.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 2c029bbe68..7ad2d9203a 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -66,6 +66,9 @@ namespace osu.Game.Scoring [MapTo("MaximumStatistics")] public string MaximumStatisticsJson { get; set; } = string.Empty; + /// + /// Hash of the beatmap where it scored + /// public string OriginalBeatmapHash { get; set; } = string.Empty; public ScoreInfo(BeatmapInfo? beatmap = null, RulesetInfo? ruleset = null, RealmUser? realmUser = null) From 1470ea0a311bec07ba3ba6525025939e51322a68 Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 7 Feb 2023 03:07:53 +0300 Subject: [PATCH 07/22] Remove unnecessary using directives --- osu.Game/Beatmaps/BeatmapManager.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/osu.Game/Beatmaps/BeatmapManager.cs b/osu.Game/Beatmaps/BeatmapManager.cs index b46859cc59..ad56bbbc3a 100644 --- a/osu.Game/Beatmaps/BeatmapManager.cs +++ b/osu.Game/Beatmaps/BeatmapManager.cs @@ -13,7 +13,6 @@ using System.Threading.Tasks; using osu.Framework.Audio; using osu.Framework.Audio.Track; using osu.Framework.Extensions; -using osu.Framework.Extensions.IEnumerableExtensions; using osu.Framework.IO.Stores; using osu.Framework.Platform; using osu.Framework.Testing; @@ -26,7 +25,6 @@ using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Overlays.Notifications; using osu.Game.Rulesets; -using osu.Game.Scoring; using osu.Game.Skinning; using osu.Game.Utils; From a1ee3df453f46a271d7ba7450f791340119cc539 Mon Sep 17 00:00:00 2001 From: Cootz Date: Tue, 7 Feb 2023 03:16:25 +0300 Subject: [PATCH 08/22] Improve local variable naming --- osu.Game/Database/RealmAccess.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 6f85b3f1be..1ef904fbc3 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -867,12 +867,13 @@ namespace osu.Game.Database // Remove the default skins so they can be added back by SkinManager with updated naming. migration.NewRealm.RemoveRange(migration.NewRealm.All().Where(s => s.Protected)); break; + case 26: // Adding origin beatmap hash property to ensure the score corresponds to the version of beatmap it should // See: https://github.com/ppy/osu/issues/22062 - string ScoreInfoName = getMappedOrOriginalName(typeof(ScoreInfo)); + string scoreInfoName = getMappedOrOriginalName(typeof(ScoreInfo)); - var oldScoreInfos = migration.OldRealm.DynamicApi.All(ScoreInfoName); + var oldScoreInfos = migration.OldRealm.DynamicApi.All(scoreInfoName); var newScoreInfos = migration.NewRealm.All(); for (int i = 0; i < newScoreInfos.Count(); i++) From 957c9e7e276037c9c0db101f5e77cbaf3ceda5da Mon Sep 17 00:00:00 2001 From: Cootz <50776304+Cootz@users.noreply.github.com> Date: Tue, 7 Feb 2023 11:23:39 +0300 Subject: [PATCH 09/22] Update osu.Game/Scoring/ScoreInfo.cs Co-authored-by: Dean Herbert --- osu.Game/Scoring/ScoreInfo.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 7ad2d9203a..2ea40df44d 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -67,9 +67,9 @@ namespace osu.Game.Scoring public string MaximumStatisticsJson { get; set; } = string.Empty; /// - /// Hash of the beatmap where it scored + /// The beatmap's at the point in time when the score was set. /// - public string OriginalBeatmapHash { get; set; } = string.Empty; + public string BeatmapHash { get; set; } = string.Empty; public ScoreInfo(BeatmapInfo? beatmap = null, RulesetInfo? ruleset = null, RealmUser? realmUser = null) { From 7e127dafe21a89f5059f59de5cff7904f34e9783 Mon Sep 17 00:00:00 2001 From: PC Date: Tue, 7 Feb 2023 11:52:47 +0300 Subject: [PATCH 10/22] Update reference --- osu.Game.Tests/Resources/TestResources.cs | 2 +- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 20 +++++++++---------- .../TestSceneDeleteLocalScore.cs | 2 +- osu.Game/Database/RealmAccess.cs | 4 ++-- osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs | 2 +- osu.Game/Scoring/ScoreInfo.cs | 2 +- osu.Game/Screens/Play/Player.cs | 2 +- .../Screens/Select/Carousel/TopLocalRank.cs | 2 +- .../Select/Leaderboards/BeatmapLeaderboard.cs | 2 +- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/osu.Game.Tests/Resources/TestResources.cs b/osu.Game.Tests/Resources/TestResources.cs index f65d427649..a2d81c0a75 100644 --- a/osu.Game.Tests/Resources/TestResources.cs +++ b/osu.Game.Tests/Resources/TestResources.cs @@ -176,7 +176,7 @@ namespace osu.Game.Tests.Resources CoverUrl = "https://osu.ppy.sh/images/headers/profile-covers/c3.jpg", }, BeatmapInfo = beatmap, - OriginalBeatmapHash = beatmap.Hash, + BeatmapHash = beatmap.Hash, Ruleset = beatmap.Ruleset, Mods = new Mod[] { new TestModHardRock(), new TestModDoubleTime() }, TotalScore = 2845370, diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 7a578230d9..c4bca79480 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -210,7 +210,7 @@ namespace osu.Game.Tests.Visual.SongSelect }, Ruleset = new OsuRuleset().RulesetInfo, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, User = new APIUser { Id = 6602580, @@ -227,7 +227,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddSeconds(-30), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser { @@ -245,7 +245,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddSeconds(-70), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -264,7 +264,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddMinutes(-40), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -283,7 +283,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-2), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -302,7 +302,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-25), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -321,7 +321,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-50), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -340,7 +340,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddHours(-72), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -359,7 +359,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddMonths(-3), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser @@ -378,7 +378,7 @@ namespace osu.Game.Tests.Visual.SongSelect Date = DateTime.Now.AddYears(-2), Mods = new Mod[] { new OsuModHidden(), new OsuModHardRock(), }, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Ruleset = new OsuRuleset().RulesetInfo, User = new APIUser diff --git a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs index 14193b1ac8..529874b71e 100644 --- a/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs +++ b/osu.Game.Tests/Visual/UserInterface/TestSceneDeleteLocalScore.cs @@ -94,7 +94,7 @@ namespace osu.Game.Tests.Visual.UserInterface { OnlineID = i, BeatmapInfo = beatmapInfo, - OriginalBeatmapHash = beatmapInfo.Hash, + BeatmapHash = beatmapInfo.Hash, Accuracy = RNG.NextDouble(), TotalScore = RNG.Next(1, 1000000), MaxCombo = RNG.Next(1, 1000), diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 1ef904fbc3..b151fc6474 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -70,7 +70,7 @@ namespace osu.Game.Database /// 23 2022-08-01 Added LastLocalUpdate to BeatmapInfo. /// 24 2022-08-22 Added MaximumStatistics to ScoreInfo. /// 25 2022-09-18 Remove skins to add with new naming. - /// 26 2023-02-05 Added OriginalBeatmapHash to ScoreInfo. + /// 26 2023-02-05 Added BeatmapHash to ScoreInfo. /// private const int schema_version = 26; @@ -878,7 +878,7 @@ namespace osu.Game.Database for (int i = 0; i < newScoreInfos.Count(); i++) { - newScoreInfos.ElementAt(i).OriginalBeatmapHash = oldScoreInfos.ElementAt(i).BeatmapInfo.Hash; + newScoreInfos.ElementAt(i).BeatmapHash = oldScoreInfos.ElementAt(i).BeatmapInfo.Hash; } break; diff --git a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs index 4bd068ca0f..9b145ad56e 100644 --- a/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs +++ b/osu.Game/Scoring/Legacy/LegacyScoreDecoder.cs @@ -123,7 +123,7 @@ namespace osu.Game.Scoring.Legacy // 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. score.ScoreInfo.BeatmapInfo = workingBeatmap.BeatmapInfo; - score.ScoreInfo.OriginalBeatmapHash = workingBeatmap.BeatmapInfo.Hash; + score.ScoreInfo.BeatmapHash = workingBeatmap.BeatmapInfo.Hash; return score; } diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 2ea40df44d..62adcb9f94 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -67,7 +67,7 @@ namespace osu.Game.Scoring public string MaximumStatisticsJson { get; set; } = string.Empty; /// - /// The beatmap's at the point in time when the score was set. + /// The at the point in time when the score was set. /// public string BeatmapHash { get; set; } = string.Empty; diff --git a/osu.Game/Screens/Play/Player.cs b/osu.Game/Screens/Play/Player.cs index 7bd020db93..a3d8d3237c 100644 --- a/osu.Game/Screens/Play/Player.cs +++ b/osu.Game/Screens/Play/Player.cs @@ -248,7 +248,7 @@ namespace osu.Game.Screens.Play // ensure the score is in a consistent state with the current player. Score.ScoreInfo.BeatmapInfo = Beatmap.Value.BeatmapInfo; - Score.ScoreInfo.OriginalBeatmapHash = Beatmap.Value.BeatmapInfo.Hash; + Score.ScoreInfo.BeatmapHash = Beatmap.Value.BeatmapInfo.Hash; Score.ScoreInfo.Ruleset = ruleset.RulesetInfo; Score.ScoreInfo.Mods = gameplayMods; diff --git a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs index 3df72f7d3b..a57a8b0f27 100644 --- a/osu.Game/Screens/Select/Carousel/TopLocalRank.cs +++ b/osu.Game/Screens/Select/Carousel/TopLocalRank.cs @@ -65,7 +65,7 @@ namespace osu.Game.Screens.Select.Carousel r.All() .Filter($"{nameof(ScoreInfo.User)}.{nameof(RealmUser.OnlineID)} == $0" + $" && {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.ID)} == $1" - + $" && {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.Hash)} == {nameof(ScoreInfo.OriginalBeatmapHash)}" + + $" && {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.Hash)} == {nameof(ScoreInfo.BeatmapHash)}" + $" && {nameof(ScoreInfo.Ruleset)}.{nameof(RulesetInfo.ShortName)} == $2" + $" && {nameof(ScoreInfo.DeletePending)} == false", api.LocalUser.Value.Id, beatmapInfo.ID, ruleset.Value.ShortName), localScoresChanged); diff --git a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs index 3e90d2465b..2b40b9faf8 100644 --- a/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs +++ b/osu.Game/Screens/Select/Leaderboards/BeatmapLeaderboard.cs @@ -191,7 +191,7 @@ namespace osu.Game.Screens.Select.Leaderboards scoreSubscription = realm.RegisterForNotifications(r => r.All().Filter($"{nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.ID)} == $0" - + $" AND {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.Hash)} == {nameof(ScoreInfo.OriginalBeatmapHash)}" + + $" AND {nameof(ScoreInfo.BeatmapInfo)}.{nameof(BeatmapInfo.Hash)} == {nameof(ScoreInfo.BeatmapHash)}" + $" AND {nameof(ScoreInfo.Ruleset)}.{nameof(RulesetInfo.ShortName)} == $1" + $" AND {nameof(ScoreInfo.DeletePending)} == false" , beatmapInfo.ID, ruleset.Value.ShortName), localScoresChanged); From 338d96534a2ad7b27d82eeeafb2c778fb67d0b67 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 8 Feb 2023 05:01:54 +0300 Subject: [PATCH 11/22] Add leaderboard test on beatmap update --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index c4bca79480..13a24cd490 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -96,6 +96,37 @@ namespace osu.Game.Tests.Visual.SongSelect checkCount(0); } + [Test] + public void TestLocalScoresDisplayOnBeatmapEdit() + { + BeatmapInfo beatmapInfo = null!; + + AddStep(@"Set scope", () => leaderboard.Scope = BeatmapLeaderboardScope.Local); + + AddStep(@"Set beatmap", () => + { + beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely(); + beatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First(); + + leaderboard.BeatmapInfo = beatmapInfo; + }); + + clearScores(); + checkCount(0); + + loadMoreScores(() => beatmapInfo); + checkCount(10); + + beatmapEdit(() => beatmapInfo); + checkCount(0); + + loadMoreScores(() => beatmapInfo); + checkCount(10); + + clearScores(); + checkCount(0); + } + [Test] public void TestGlobalScoresDisplay() { @@ -123,6 +154,21 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"None selected", () => leaderboard.SetErrorState(LeaderboardState.NoneSelected)); } + private void beatmapEdit(Func beatmapInfo) + { + AddStep(@"Update beatmap via BeatmapManager", () => + { + BeatmapInfo info = beatmapInfo(); + IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(info).Beatmap; + + beatmap.Difficulty.ApproachRate = 11; + beatmap.Difficulty.DrainRate = 11; + beatmap.Difficulty.OverallDifficulty = 11; + + beatmapManager.Save(info, beatmap); + }); + } + private void showPersonalBestWithNullPosition() { leaderboard.SetScores(leaderboard.Scores, new ScoreInfo From 391af2791b875a9928bba1d92dbcbae2128c0dd0 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 8 Feb 2023 05:23:42 +0300 Subject: [PATCH 12/22] Fix CSharpWarnings::CS1574,CS1584,CS1581,CS1580 --- osu.Game/Scoring/ScoreInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 62adcb9f94..8c912ef32a 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -67,7 +67,7 @@ namespace osu.Game.Scoring public string MaximumStatisticsJson { get; set; } = string.Empty; /// - /// The at the point in time when the score was set. + /// The .Hash at the point in time when the score was set. /// public string BeatmapHash { get; set; } = string.Empty; From 6bf56aff73e07b7cd92241b251ae0ea0d9787b99 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 8 Feb 2023 05:40:20 +0300 Subject: [PATCH 13/22] Add warning for `ScoreInfo` --- osu.Game/Scoring/ScoreInfo.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 8c912ef32a..c57e06bee5 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -22,6 +22,13 @@ using Realms; namespace osu.Game.Scoring { + + /// + /// Store information about the score + /// + /// + /// If you work on inporting/adding score please ensure you provide both BeatmapInfo and BeatmapHash + /// [ExcludeFromDynamicCompile] [MapTo("Score")] public class ScoreInfo : RealmObject, IHasGuidPrimaryKey, IHasRealmFiles, ISoftDelete, IEquatable, IScoreInfo From ab7c9a200bdcc7804927ca68b9c59da58d22d49f Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 8 Feb 2023 05:42:06 +0300 Subject: [PATCH 14/22] Fix a typo --- osu.Game/Scoring/ScoreInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index c57e06bee5..85452ede17 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -27,7 +27,7 @@ namespace osu.Game.Scoring /// Store information about the score /// /// - /// If you work on inporting/adding score please ensure you provide both BeatmapInfo and BeatmapHash + /// Warning: If you work on importing/adding score please ensure you provide both BeatmapInfo and BeatmapHash /// [ExcludeFromDynamicCompile] [MapTo("Score")] From 4ba915268c5e0a34824d2a03cb501a12574707a4 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 8 Feb 2023 05:46:47 +0300 Subject: [PATCH 15/22] Change a comment into `RealmAccess` --- osu.Game/Database/RealmAccess.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index b151fc6474..861a74e163 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -869,7 +869,7 @@ namespace osu.Game.Database break; case 26: - // Adding origin beatmap hash property to ensure the score corresponds to the version of beatmap it should + // Add ScoreInfo.BeatmapHash property to ensure the score corresponds to the version of beatmap it should // See: https://github.com/ppy/osu/issues/22062 string scoreInfoName = getMappedOrOriginalName(typeof(ScoreInfo)); From 086b3eb542348048da062fde8234239e8d7d3ef6 Mon Sep 17 00:00:00 2001 From: Cootz Date: Wed, 8 Feb 2023 05:50:52 +0300 Subject: [PATCH 16/22] Fix minor formating issues --- osu.Game/Scoring/ScoreInfo.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 85452ede17..d2ec4ebd5f 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -22,10 +22,9 @@ using Realms; namespace osu.Game.Scoring { - /// /// Store information about the score - /// + /// /// /// Warning: If you work on importing/adding score please ensure you provide both BeatmapInfo and BeatmapHash /// From 5c113ddb030445c5099fdd2334d6b2608f5851ef Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 14:20:58 +0900 Subject: [PATCH 17/22] Reword xmldoc to read better --- osu.Game/Scoring/ScoreInfo.cs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index d2ec4ebd5f..6213c65c75 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -23,11 +23,8 @@ using Realms; namespace osu.Game.Scoring { /// - /// Store information about the score + /// A realm model containing metadata for a single score. /// - /// - /// Warning: If you work on importing/adding score please ensure you provide both BeatmapInfo and BeatmapHash - /// [ExcludeFromDynamicCompile] [MapTo("Score")] public class ScoreInfo : RealmObject, IHasGuidPrimaryKey, IHasRealmFiles, ISoftDelete, IEquatable, IScoreInfo @@ -35,8 +32,19 @@ namespace osu.Game.Scoring [PrimaryKey] public Guid ID { get; set; } + /// + /// The this score was made against. + /// + /// + /// When setting this, make sure to also set to allow relational consistency when a beatmap is potentially changed. + /// public BeatmapInfo BeatmapInfo { get; set; } = null!; + /// + /// The at the point in time when the score was set. + /// + public string BeatmapHash { get; set; } = string.Empty; + public RulesetInfo Ruleset { get; set; } = null!; public IList Files { get; } = null!; @@ -72,11 +80,6 @@ namespace osu.Game.Scoring [MapTo("MaximumStatistics")] public string MaximumStatisticsJson { get; set; } = string.Empty; - /// - /// The .Hash at the point in time when the score was set. - /// - public string BeatmapHash { get; set; } = string.Empty; - public ScoreInfo(BeatmapInfo? beatmap = null, RulesetInfo? ruleset = null, RealmUser? realmUser = null) { Ruleset = ruleset ?? new RulesetInfo(); From c50ea89bc99f3dc142e85ecec3bf2504d3fd5f32 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 14:24:06 +0900 Subject: [PATCH 18/22] Simplify migration to not rely on old/dynamic schema --- osu.Game/Database/RealmAccess.cs | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/osu.Game/Database/RealmAccess.cs b/osu.Game/Database/RealmAccess.cs index 861a74e163..831e328439 100644 --- a/osu.Game/Database/RealmAccess.cs +++ b/osu.Game/Database/RealmAccess.cs @@ -869,17 +869,11 @@ namespace osu.Game.Database break; case 26: - // Add ScoreInfo.BeatmapHash property to ensure the score corresponds to the version of beatmap it should - // See: https://github.com/ppy/osu/issues/22062 - string scoreInfoName = getMappedOrOriginalName(typeof(ScoreInfo)); + // Add ScoreInfo.BeatmapHash property to ensure scores correspond to the correct version of beatmap. + var scores = migration.NewRealm.All(); - var oldScoreInfos = migration.OldRealm.DynamicApi.All(scoreInfoName); - var newScoreInfos = migration.NewRealm.All(); - - for (int i = 0; i < newScoreInfos.Count(); i++) - { - newScoreInfos.ElementAt(i).BeatmapHash = oldScoreInfos.ElementAt(i).BeatmapInfo.Hash; - } + foreach (var score in scores) + score.BeatmapHash = score.BeatmapInfo.Hash; break; } From c7eec371f52dd403a0bfaeea6f645d4a56dd3857 Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 15:22:17 +0900 Subject: [PATCH 19/22] Clean up tests somewhat --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 41 ++++++++----------- 1 file changed, 18 insertions(+), 23 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 13a24cd490..83bb58804d 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -86,10 +86,10 @@ namespace osu.Game.Tests.Visual.SongSelect clearScores(); checkCount(0); - loadMoreScores(() => beatmapInfo); + importMoreScores(() => beatmapInfo); checkCount(10); - loadMoreScores(() => beatmapInfo); + importMoreScores(() => beatmapInfo); checkCount(20); clearScores(); @@ -114,13 +114,23 @@ namespace osu.Game.Tests.Visual.SongSelect clearScores(); checkCount(0); - loadMoreScores(() => beatmapInfo); + importMoreScores(() => beatmapInfo); checkCount(10); - beatmapEdit(() => beatmapInfo); + AddStep(@"Save beatmap with changes", () => + { + IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(beatmapInfo).Beatmap; + + beatmap.Difficulty.ApproachRate = 11; + beatmap.Difficulty.DrainRate = 11; + beatmap.Difficulty.OverallDifficulty = 11; + + beatmapManager.Save(beatmapInfo, beatmap); + }); + checkCount(0); - loadMoreScores(() => beatmapInfo); + importMoreScores(() => beatmapInfo); checkCount(10); clearScores(); @@ -154,21 +164,6 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep(@"None selected", () => leaderboard.SetErrorState(LeaderboardState.NoneSelected)); } - private void beatmapEdit(Func beatmapInfo) - { - AddStep(@"Update beatmap via BeatmapManager", () => - { - BeatmapInfo info = beatmapInfo(); - IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(info).Beatmap; - - beatmap.Difficulty.ApproachRate = 11; - beatmap.Difficulty.DrainRate = 11; - beatmap.Difficulty.OverallDifficulty = 11; - - beatmapManager.Save(info, beatmap); - }); - } - private void showPersonalBestWithNullPosition() { leaderboard.SetScores(leaderboard.Scores, new ScoreInfo @@ -208,9 +203,9 @@ namespace osu.Game.Tests.Visual.SongSelect }); } - private void loadMoreScores(Func beatmapInfo) + private void importMoreScores(Func beatmapInfo) { - AddStep(@"Load new scores via manager", () => + AddStep(@"Import new scores", () => { foreach (var score in generateSampleScores(beatmapInfo())) scoreManager.Import(score); @@ -223,7 +218,7 @@ namespace osu.Game.Tests.Visual.SongSelect } private void checkCount(int expected) => - AddUntilStep("Correct count displayed", () => leaderboard.ChildrenOfType().Count() == expected); + AddUntilStep($"{expected} scores displayed", () => leaderboard.ChildrenOfType().Count(), () => Is.EqualTo(expected)); private static ScoreInfo[] generateSampleScores(BeatmapInfo beatmapInfo) { From d4d985ba0f0378d3c93a71b17e5cfcb793a7b41b Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 15:34:46 +0900 Subject: [PATCH 20/22] Improve test to also check that reverting hash restores old scores --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 31 ++++++++++++++----- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 83bb58804d..01397563fd 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -100,10 +100,11 @@ namespace osu.Game.Tests.Visual.SongSelect public void TestLocalScoresDisplayOnBeatmapEdit() { BeatmapInfo beatmapInfo = null!; + string originalHash = string.Empty; AddStep(@"Set scope", () => leaderboard.Scope = BeatmapLeaderboardScope.Local); - AddStep(@"Set beatmap", () => + AddStep(@"Import beatmap", () => { beatmapManager.Import(TestResources.GetQuickTestBeatmapForImport()).WaitSafely(); beatmapInfo = beatmapManager.GetAllUsableBeatmapSets().First().Beatmaps.First(); @@ -114,23 +115,39 @@ namespace osu.Game.Tests.Visual.SongSelect clearScores(); checkCount(0); + AddStep(@"Perform initial save to guarantee stable hash", () => + { + IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(beatmapInfo).Beatmap; + beatmapManager.Save(beatmapInfo, beatmap); + + originalHash = beatmapInfo.Hash; + }); + importMoreScores(() => beatmapInfo); checkCount(10); - AddStep(@"Save beatmap with changes", () => + AddStep(@"Save with changes", () => { IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(beatmapInfo).Beatmap; - - beatmap.Difficulty.ApproachRate = 11; - beatmap.Difficulty.DrainRate = 11; - beatmap.Difficulty.OverallDifficulty = 11; - + beatmap.Difficulty.ApproachRate = 12; beatmapManager.Save(beatmapInfo, beatmap); }); + AddAssert("Hash changed", () => beatmapInfo.Hash, () => Is.Not.EqualTo(originalHash)); checkCount(0); importMoreScores(() => beatmapInfo); + importMoreScores(() => beatmapInfo); + checkCount(20); + + AddStep(@"Revert changes", () => + { + IBeatmap beatmap = beatmapManager.GetWorkingBeatmap(beatmapInfo).Beatmap; + beatmap.Difficulty.ApproachRate = 8; + beatmapManager.Save(beatmapInfo, beatmap); + }); + + AddAssert("Hash restored", () => beatmapInfo.Hash, () => Is.EqualTo(originalHash)); checkCount(10); clearScores(); From 38031fdf2327cb50705cd14fa55c4cb1cb058a9d Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 15:38:07 +0900 Subject: [PATCH 21/22] Add test coverage of stores stored in database as well --- .../SongSelect/TestSceneBeatmapLeaderboard.cs | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs index 01397563fd..c234cc8a9c 100644 --- a/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs +++ b/osu.Game.Tests/Visual/SongSelect/TestSceneBeatmapLeaderboard.cs @@ -84,16 +84,16 @@ namespace osu.Game.Tests.Visual.SongSelect }); clearScores(); - checkCount(0); + checkDisplayedCount(0); importMoreScores(() => beatmapInfo); - checkCount(10); + checkDisplayedCount(10); importMoreScores(() => beatmapInfo); - checkCount(20); + checkDisplayedCount(20); clearScores(); - checkCount(0); + checkDisplayedCount(0); } [Test] @@ -113,7 +113,7 @@ namespace osu.Game.Tests.Visual.SongSelect }); clearScores(); - checkCount(0); + checkDisplayedCount(0); AddStep(@"Perform initial save to guarantee stable hash", () => { @@ -124,7 +124,9 @@ namespace osu.Game.Tests.Visual.SongSelect }); importMoreScores(() => beatmapInfo); - checkCount(10); + + checkDisplayedCount(10); + checkStoredCount(10); AddStep(@"Save with changes", () => { @@ -134,11 +136,13 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddAssert("Hash changed", () => beatmapInfo.Hash, () => Is.Not.EqualTo(originalHash)); - checkCount(0); + checkDisplayedCount(0); + checkStoredCount(10); importMoreScores(() => beatmapInfo); importMoreScores(() => beatmapInfo); - checkCount(20); + checkDisplayedCount(20); + checkStoredCount(30); AddStep(@"Revert changes", () => { @@ -148,10 +152,12 @@ namespace osu.Game.Tests.Visual.SongSelect }); AddAssert("Hash restored", () => beatmapInfo.Hash, () => Is.EqualTo(originalHash)); - checkCount(10); + checkDisplayedCount(10); + checkStoredCount(30); clearScores(); - checkCount(0); + checkDisplayedCount(0); + checkStoredCount(0); } [Test] @@ -234,9 +240,12 @@ namespace osu.Game.Tests.Visual.SongSelect AddStep("Clear all scores", () => scoreManager.Delete()); } - private void checkCount(int expected) => + private void checkDisplayedCount(int expected) => AddUntilStep($"{expected} scores displayed", () => leaderboard.ChildrenOfType().Count(), () => Is.EqualTo(expected)); + private void checkStoredCount(int expected) => + AddUntilStep($"Total scores stored is {expected}", () => Realm.Run(r => r.All().Count(s => !s.DeletePending)), () => Is.EqualTo(expected)); + private static ScoreInfo[] generateSampleScores(BeatmapInfo beatmapInfo) { return new[] From 4fdba880b1efc2dcb49a2f3c64585f2e896a64ba Mon Sep 17 00:00:00 2001 From: Dean Herbert Date: Wed, 8 Feb 2023 15:39:18 +0900 Subject: [PATCH 22/22] Fix xmldoc reference fail at CI --- osu.Game/Scoring/ScoreInfo.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/osu.Game/Scoring/ScoreInfo.cs b/osu.Game/Scoring/ScoreInfo.cs index 6213c65c75..02c7acf350 100644 --- a/osu.Game/Scoring/ScoreInfo.cs +++ b/osu.Game/Scoring/ScoreInfo.cs @@ -41,7 +41,7 @@ namespace osu.Game.Scoring public BeatmapInfo BeatmapInfo { get; set; } = null!; /// - /// The at the point in time when the score was set. + /// The at the point in time when the score was set. /// public string BeatmapHash { get; set; } = string.Empty;