From d5803e541bdfcc1b0f6ed703bdb0773b766b5624 Mon Sep 17 00:00:00 2001 From: Dan Balasescu Date: Fri, 3 Dec 2021 20:05:25 +0900 Subject: [PATCH] Give playlist items a PlayedAt date --- .../TestSceneMultiplayerPlaylist.cs | 4 ++- .../Online/Multiplayer/MultiplayerClient.cs | 3 +- .../Online/Rooms/MultiplayerPlaylistItem.cs | 8 ++--- osu.Game/Online/Rooms/PlaylistItem.cs | 3 ++ .../Match/Playlist/MultiplayerHistoryList.cs | 2 +- .../Multiplayer/TestMultiplayerClient.cs | 36 +++++++------------ 6 files changed, 26 insertions(+), 30 deletions(-) diff --git a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs index ae885685f7..674ee0f186 100644 --- a/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs +++ b/osu.Game.Tests/Visual/Multiplayer/TestSceneMultiplayerPlaylist.cs @@ -1,6 +1,7 @@ // Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. +using System; using System.Linq; using NUnit.Framework; using osu.Framework.Allocation; @@ -168,7 +169,8 @@ namespace osu.Game.Tests.Visual.Multiplayer { Beatmap = { Value = importedBeatmap }, BeatmapID = importedBeatmap.OnlineID ?? -1, - Expired = expired + Expired = expired, + PlayedAt = DateTimeOffset.Now }))); /// diff --git a/osu.Game/Online/Multiplayer/MultiplayerClient.cs b/osu.Game/Online/Multiplayer/MultiplayerClient.cs index ae53ef2e52..555558eb6d 100644 --- a/osu.Game/Online/Multiplayer/MultiplayerClient.cs +++ b/osu.Game/Online/Multiplayer/MultiplayerClient.cs @@ -742,7 +742,8 @@ namespace osu.Game.Online.Multiplayer Beatmap = { Value = apiBeatmap }, Ruleset = { Value = ruleset }, Expired = item.Expired, - PlaylistOrder = item.PlaylistOrder + PlaylistOrder = item.PlaylistOrder, + PlayedAt = item.PlayedAt }; playlistItem.RequiredMods.AddRange(item.RequiredMods.Select(m => m.ToMod(rulesetInstance))); diff --git a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs index c84b5b9039..1c33b79531 100644 --- a/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs +++ b/osu.Game/Online/Rooms/MultiplayerPlaylistItem.cs @@ -46,11 +46,10 @@ namespace osu.Game.Online.Rooms public ushort PlaylistOrder { get; set; } /// - /// The date when this was last updated. - /// Not serialised to/from the client. + /// The date when this was played. /// - [IgnoreMember] - public DateTimeOffset UpdatedAt { get; set; } + [Key(9)] + public DateTimeOffset? PlayedAt { get; set; } public MultiplayerPlaylistItem() { @@ -66,6 +65,7 @@ namespace osu.Game.Online.Rooms AllowedMods = item.AllowedMods.Select(m => new APIMod(m)).ToArray(); Expired = item.Expired; PlaylistOrder = item.PlaylistOrder ?? 0; + PlayedAt = item.PlayedAt; } } } diff --git a/osu.Game/Online/Rooms/PlaylistItem.cs b/osu.Game/Online/Rooms/PlaylistItem.cs index beefb17d54..4d67864048 100644 --- a/osu.Game/Online/Rooms/PlaylistItem.cs +++ b/osu.Game/Online/Rooms/PlaylistItem.cs @@ -36,6 +36,9 @@ namespace osu.Game.Online.Rooms [JsonProperty("playlist_order")] public ushort? PlaylistOrder { get; set; } + [JsonProperty("played_at")] + public DateTimeOffset? PlayedAt { get; set; } + [JsonIgnore] public IBindable Valid => valid; diff --git a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs index ed41a6fc78..d708b39898 100644 --- a/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs +++ b/osu.Game/Screens/OnlinePlay/Multiplayer/Match/Playlist/MultiplayerHistoryList.cs @@ -27,7 +27,7 @@ namespace osu.Game.Screens.OnlinePlay.Multiplayer.Match.Playlist private class HistoryFillFlowContainer : FillFlowContainer> { - public override IEnumerable FlowingChildren => base.FlowingChildren.OfType>().OrderByDescending(item => item.Model.PlaylistOrder); + public override IEnumerable FlowingChildren => base.FlowingChildren.OfType>().OrderByDescending(item => item.Model.PlayedAt); } } } diff --git a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs index f2d5323386..024b091bfb 100644 --- a/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs +++ b/osu.Game/Tests/Visual/Multiplayer/TestMultiplayerClient.cs @@ -400,7 +400,7 @@ namespace osu.Game.Tests.Visual.Multiplayer // Expire the current playlist item. currentItem.Expired = true; - currentItem.UpdatedAt = DateTimeOffset.Now; + currentItem.PlayedAt = DateTimeOffset.Now; await ((IMultiplayerClient)this).PlaylistItemChanged(currentItem).ConfigureAwait(false); await updatePlaylistOrder(Room).ConfigureAwait(false); @@ -430,9 +430,6 @@ namespace osu.Game.Tests.Visual.Multiplayer { Debug.Assert(Room != null); - // Some tests can add items in already-expired states. - item.UpdatedAt = DateTimeOffset.Now; - // Add the item to the list first in order to compute gameplay order. serverSidePlaylist.Add(item); await updatePlaylistOrder(Room).ConfigureAwait(false); @@ -443,8 +440,12 @@ namespace osu.Game.Tests.Visual.Multiplayer private async Task updateCurrentItem(MultiplayerRoom room, bool notify = true) { - // The playlist is already in correct gameplay order, so pick the next non-expired item or default to the last item. - MultiplayerPlaylistItem nextItem = serverSidePlaylist.FirstOrDefault(i => !i.Expired) ?? room.Playlist.Last(); + MultiplayerPlaylistItem nextItem = serverSidePlaylist + .Where(i => !i.Expired) + .OrderBy(i => i.PlaylistOrder) + .FirstOrDefault() + ?? room.Playlist.Last(); + currentIndex = serverSidePlaylist.IndexOf(nextItem); long lastItem = room.Settings.PlaylistItemId; @@ -494,29 +495,18 @@ namespace osu.Game.Tests.Visual.Multiplayer break; } - // For expired items, it's important that they're ordered in ascending order such that the last updated item is the last in the list. - // This is so that the updated_at database column doesn't get refreshed as a result of change in ordering. - List orderedExpiredItems = serverSidePlaylist.Where(item => item.Expired).OrderBy(item => item.UpdatedAt).ToList(); - for (int i = 0; i < orderedExpiredItems.Count; i++) - await setOrder(orderedExpiredItems[i], (ushort)i).ConfigureAwait(false); - for (int i = 0; i < orderedActiveItems.Count; i++) - await setOrder(orderedActiveItems[i], (ushort)i).ConfigureAwait(false); - - serverSidePlaylist.Clear(); - serverSidePlaylist.AddRange(orderedExpiredItems); - serverSidePlaylist.AddRange(orderedActiveItems); - - async Task setOrder(MultiplayerPlaylistItem item, ushort order) { - if (item.PlaylistOrder == order) - return; + var item = orderedActiveItems[i]; - item.PlaylistOrder = order; + if (item.PlaylistOrder == i) + continue; + + item.PlaylistOrder = (ushort)i; // Items which have an ID of 0 are not in the database, so avoid propagating database/hub events for them. if (item.ID <= 0) - return; + continue; await ((IMultiplayerClient)this).PlaylistItemChanged(item).ConfigureAwait(false); }