diff --git a/osu.Game.Tests/ImportTest.cs b/osu.Game.Tests/ImportTest.cs index 3f0f8a4f14..27b8d3f21e 100644 --- a/osu.Game.Tests/ImportTest.cs +++ b/osu.Game.Tests/ImportTest.cs @@ -9,6 +9,7 @@ using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Platform; using osu.Game.Database; +using osu.Game.Online.API; using osu.Game.Tests.Resources; namespace osu.Game.Tests @@ -46,12 +47,15 @@ namespace osu.Game.Tests public partial class TestOsuGameBase : OsuGameBase { public RealmAccess Realm => Dependencies.Get(); + public new IAPIProvider API => base.API; private readonly bool withBeatmap; public TestOsuGameBase(bool withBeatmap) { this.withBeatmap = withBeatmap; + + base.API = new DummyAPIAccess(); } [BackgroundDependencyLoader] diff --git a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs index 892ceea185..dd724d268e 100644 --- a/osu.Game.Tests/Scores/IO/ImportScoreTest.cs +++ b/osu.Game.Tests/Scores/IO/ImportScoreTest.cs @@ -11,7 +11,10 @@ using NUnit.Framework; using osu.Framework.Allocation; using osu.Framework.Extensions; using osu.Framework.Platform; +using osu.Game.Beatmaps; +using osu.Game.Database; using osu.Game.IO.Archives; +using osu.Game.Online.API; using osu.Game.Online.API.Requests.Responses; using osu.Game.Rulesets.Mods; using osu.Game.Rulesets.Osu; @@ -67,6 +70,116 @@ namespace osu.Game.Tests.Scores.IO } } + [TestCase(false)] + [TestCase(true)] + public void TestLastPlayedUpdate(bool isLocalUser) + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost()) + { + try + { + var osu = LoadOsuIntoHost(host, true); + + if (!isLocalUser) + osu.API.Logout(); + + var beatmap = BeatmapImportHelper.LoadOszIntoOsu(osu, TestResources.GetQuickTestBeatmapForImport()).GetResultSafely(); + var beatmapInfo = beatmap.Beatmaps.First(); + + DateTimeOffset replayDate = DateTimeOffset.Now; + + var toImport = new ScoreInfo + { + Rank = ScoreRank.B, + TotalScore = 987654, + Accuracy = 0.8, + MaxCombo = 500, + Combo = 250, + User = new APIUser + { + Username = "Test user", + Id = DummyAPIAccess.DUMMY_USER_ID, + }, + Date = replayDate, + OnlineID = 12345, + Ruleset = new OsuRuleset().RulesetInfo, + BeatmapInfo = beatmapInfo + }; + + var imported = LoadScoreIntoOsu(osu, toImport); + + Assert.AreEqual(toImport.Rank, imported.Rank); + Assert.AreEqual(toImport.TotalScore, imported.TotalScore); + Assert.AreEqual(toImport.Accuracy, imported.Accuracy); + Assert.AreEqual(toImport.MaxCombo, imported.MaxCombo); + Assert.AreEqual(toImport.User.Username, imported.User.Username); + Assert.AreEqual(toImport.Date, imported.Date); + Assert.AreEqual(toImport.OnlineID, imported.OnlineID); + + if (isLocalUser) + Assert.That(imported.BeatmapInfo!.LastPlayed, Is.EqualTo(replayDate)); + else + Assert.That(imported.BeatmapInfo!.LastPlayed, Is.Null); + } + finally + { + host.Exit(); + } + } + } + + [Test] + public void TestLastPlayedNotUpdatedDueToNewerPlays() + { + using (HeadlessGameHost host = new CleanRunHeadlessGameHost()) + { + try + { + var osu = LoadOsuIntoHost(host, true); + + var beatmap = BeatmapImportHelper.LoadOszIntoOsu(osu, TestResources.GetQuickTestBeatmapForImport()).GetResultSafely(); + var beatmapInfo = beatmap.Beatmaps.First(); + + var realmAccess = osu.Dependencies.Get(); + realmAccess.Write(r => r.Find(beatmapInfo.ID)!.LastPlayed = new DateTimeOffset(2023, 10, 30, 0, 0, 0, TimeSpan.Zero)); + + var toImport = new ScoreInfo + { + Rank = ScoreRank.B, + TotalScore = 987654, + Accuracy = 0.8, + MaxCombo = 500, + Combo = 250, + User = new APIUser + { + Username = "Test user", + Id = DummyAPIAccess.DUMMY_USER_ID, + }, + Date = new DateTimeOffset(2023, 10, 27, 0, 0, 0, TimeSpan.Zero), + OnlineID = 12345, + Ruleset = new OsuRuleset().RulesetInfo, + BeatmapInfo = beatmapInfo + }; + + var imported = LoadScoreIntoOsu(osu, toImport); + + Assert.AreEqual(toImport.Rank, imported.Rank); + Assert.AreEqual(toImport.TotalScore, imported.TotalScore); + Assert.AreEqual(toImport.Accuracy, imported.Accuracy); + Assert.AreEqual(toImport.MaxCombo, imported.MaxCombo); + Assert.AreEqual(toImport.User.Username, imported.User.Username); + Assert.AreEqual(toImport.Date, imported.Date); + Assert.AreEqual(toImport.OnlineID, imported.OnlineID); + + Assert.That(imported.BeatmapInfo!.LastPlayed, Is.EqualTo(new DateTimeOffset(2023, 10, 30, 0, 0, 0, TimeSpan.Zero))); + } + finally + { + host.Exit(); + } + } + } + [Test] public void TestImportMods() { diff --git a/osu.Game/Online/API/DummyAPIAccess.cs b/osu.Game/Online/API/DummyAPIAccess.cs index 2764247f5c..d585124db6 100644 --- a/osu.Game/Online/API/DummyAPIAccess.cs +++ b/osu.Game/Online/API/DummyAPIAccess.cs @@ -112,7 +112,7 @@ namespace osu.Game.Online.API LocalUser.Value = new APIUser { Username = username, - Id = 1001, + Id = DUMMY_USER_ID, }; state.Value = APIState.Online; diff --git a/osu.Game/Scoring/ScoreImporter.cs b/osu.Game/Scoring/ScoreImporter.cs index 7473d887c3..b216c0897e 100644 --- a/osu.Game/Scoring/ScoreImporter.cs +++ b/osu.Game/Scoring/ScoreImporter.cs @@ -182,6 +182,12 @@ namespace osu.Game.Scoring base.PostImport(model, realm, parameters); populateUserDetails(model); + + Debug.Assert(model.BeatmapInfo != null); + + // This needs to be run after user detail population to ensure we have a valid user id. + if (api.IsLoggedIn && api.LocalUser.Value.OnlineID == model.UserID && (model.BeatmapInfo.LastPlayed == null || model.Date > model.BeatmapInfo.LastPlayed)) + model.BeatmapInfo.LastPlayed = model.Date; } ///