mirror of
https://github.com/osukey/osukey.git
synced 2025-05-26 07:57:32 +09:00
Update TestMultiplayerClient with expired item ordering
This commit is contained in:
parent
487a71312e
commit
9d6fe558c2
@ -45,11 +45,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Guaranteed up-to-date playlist.
|
/// Guaranteed up-to-date playlist.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private List<MultiplayerPlaylistItem> serverSidePlaylist = new List<MultiplayerPlaylistItem>();
|
private readonly List<MultiplayerPlaylistItem> serverSidePlaylist = new List<MultiplayerPlaylistItem>();
|
||||||
|
|
||||||
private MultiplayerPlaylistItem? currentItem => Room?.Playlist[currentIndex];
|
private MultiplayerPlaylistItem? currentItem => Room?.Playlist[currentIndex];
|
||||||
private int currentIndex;
|
private int currentIndex;
|
||||||
|
|
||||||
|
private long lastPlaylistItemId;
|
||||||
|
|
||||||
public TestMultiplayerClient(TestMultiplayerRoomManager roomManager)
|
public TestMultiplayerClient(TestMultiplayerRoomManager roomManager)
|
||||||
{
|
{
|
||||||
this.roomManager = roomManager;
|
this.roomManager = roomManager;
|
||||||
@ -169,6 +171,7 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
serverSidePlaylist.Clear();
|
serverSidePlaylist.Clear();
|
||||||
serverSidePlaylist.AddRange(apiRoom.Playlist.Select(item => new MultiplayerPlaylistItem(item)));
|
serverSidePlaylist.AddRange(apiRoom.Playlist.Select(item => new MultiplayerPlaylistItem(item)));
|
||||||
|
lastPlaylistItemId = serverSidePlaylist.Max(item => item.ID);
|
||||||
|
|
||||||
var localUser = new MultiplayerRoomUser(api.LocalUser.Value.Id)
|
var localUser = new MultiplayerRoomUser(api.LocalUser.Value.Id)
|
||||||
{
|
{
|
||||||
@ -397,10 +400,13 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
// Expire the current playlist item.
|
// Expire the current playlist item.
|
||||||
currentItem.Expired = true;
|
currentItem.Expired = true;
|
||||||
|
currentItem.UpdatedAt = DateTimeOffset.Now;
|
||||||
|
|
||||||
await ((IMultiplayerClient)this).PlaylistItemChanged(currentItem).ConfigureAwait(false);
|
await ((IMultiplayerClient)this).PlaylistItemChanged(currentItem).ConfigureAwait(false);
|
||||||
|
await updatePlaylistOrder(Room).ConfigureAwait(false);
|
||||||
|
|
||||||
// In host-only mode, a duplicate playlist item will be used for the next round.
|
// In host-only mode, a duplicate playlist item will be used for the next round.
|
||||||
if (Room.Settings.QueueMode == QueueMode.HostOnly)
|
if (Room.Settings.QueueMode == QueueMode.HostOnly && serverSidePlaylist.All(item => item.Expired))
|
||||||
await duplicateCurrentItem().ConfigureAwait(false);
|
await duplicateCurrentItem().ConfigureAwait(false);
|
||||||
|
|
||||||
await updateCurrentItem(Room).ConfigureAwait(false);
|
await updateCurrentItem(Room).ConfigureAwait(false);
|
||||||
@ -424,11 +430,14 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
{
|
{
|
||||||
Debug.Assert(Room != null);
|
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.
|
// Add the item to the list first in order to compute gameplay order.
|
||||||
serverSidePlaylist.Add(item);
|
serverSidePlaylist.Add(item);
|
||||||
await updatePlaylistOrder(Room).ConfigureAwait(false);
|
await updatePlaylistOrder(Room).ConfigureAwait(false);
|
||||||
|
|
||||||
item.ID = serverSidePlaylist[^2].ID + 1;
|
item.ID = ++lastPlaylistItemId;
|
||||||
await ((IMultiplayerClient)this).PlaylistItemAdded(item).ConfigureAwait(false);
|
await ((IMultiplayerClient)this).PlaylistItemAdded(item).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -447,15 +456,17 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
|
|
||||||
private async Task updatePlaylistOrder(MultiplayerRoom room)
|
private async Task updatePlaylistOrder(MultiplayerRoom room)
|
||||||
{
|
{
|
||||||
List<MultiplayerPlaylistItem> orderedItems;
|
List<MultiplayerPlaylistItem> orderedActiveItems;
|
||||||
|
|
||||||
switch (room.Settings.QueueMode)
|
switch (room.Settings.QueueMode)
|
||||||
{
|
{
|
||||||
default:
|
default:
|
||||||
orderedItems = serverSidePlaylist.OrderBy(item => item.ID == 0 ? int.MaxValue : item.ID).ToList();
|
orderedActiveItems = serverSidePlaylist.Where(item => !item.Expired).OrderBy(item => item.ID == 0 ? int.MaxValue : item.ID).ToList();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case QueueMode.AllPlayersRoundRobin:
|
case QueueMode.AllPlayersRoundRobin:
|
||||||
|
orderedActiveItems = new List<MultiplayerPlaylistItem>();
|
||||||
|
|
||||||
// Todo: This could probably be more efficient, likely at the cost of increased complexity.
|
// Todo: This could probably be more efficient, likely at the cost of increased complexity.
|
||||||
// Number of "expired" or "used" items per player.
|
// Number of "expired" or "used" items per player.
|
||||||
Dictionary<int, int> perUserCounts = serverSidePlaylist
|
Dictionary<int, int> perUserCounts = serverSidePlaylist
|
||||||
@ -463,7 +474,6 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
.ToDictionary(group => group.Key, group => group.Count(item => item.Expired));
|
.ToDictionary(group => group.Key, group => group.Count(item => item.Expired));
|
||||||
|
|
||||||
// We'll run a simulation over all items which are not expired ("unprocessed"). Expired items will not have their ordering updated.
|
// We'll run a simulation over all items which are not expired ("unprocessed"). Expired items will not have their ordering updated.
|
||||||
List<MultiplayerPlaylistItem> processedItems = serverSidePlaylist.Where(item => item.Expired).ToList();
|
|
||||||
List<MultiplayerPlaylistItem> unprocessedItems = serverSidePlaylist.Where(item => !item.Expired).ToList();
|
List<MultiplayerPlaylistItem> unprocessedItems = serverSidePlaylist.Where(item => !item.Expired).ToList();
|
||||||
|
|
||||||
// In every iteration of the simulation, pick the first available item from the user with the lowest number of items in the queue to add to the result set.
|
// In every iteration of the simulation, pick the first available item from the user with the lowest number of items in the queue to add to the result set.
|
||||||
@ -476,31 +486,40 @@ namespace osu.Game.Tests.Visual.Multiplayer
|
|||||||
.First();
|
.First();
|
||||||
|
|
||||||
unprocessedItems.Remove(candidateItem);
|
unprocessedItems.Remove(candidateItem);
|
||||||
processedItems.Add(candidateItem);
|
orderedActiveItems.Add(candidateItem);
|
||||||
|
|
||||||
perUserCounts[candidateItem.OwnerID]++;
|
perUserCounts[candidateItem.OwnerID]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
orderedItems = processedItems;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < orderedItems.Count; i++)
|
// 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.
|
||||||
// Items which are already ordered correct don't need to be updated.
|
List<MultiplayerPlaylistItem> orderedExpiredItems = serverSidePlaylist.Where(item => item.Expired).OrderBy(item => item.UpdatedAt).ToList();
|
||||||
if (orderedItems[i].PlaylistOrder == i)
|
for (int i = 0; i < orderedExpiredItems.Count; i++)
|
||||||
continue;
|
await setOrder(orderedExpiredItems[i], (ushort)i).ConfigureAwait(false);
|
||||||
|
|
||||||
orderedItems[i].PlaylistOrder = (ushort)i;
|
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;
|
||||||
|
|
||||||
|
item.PlaylistOrder = order;
|
||||||
|
|
||||||
// Items which have an ID of 0 are not in the database, so avoid propagating database/hub events for them.
|
// Items which have an ID of 0 are not in the database, so avoid propagating database/hub events for them.
|
||||||
if (orderedItems[i].ID <= 0)
|
if (item.ID <= 0)
|
||||||
continue;
|
return;
|
||||||
|
|
||||||
await ((IMultiplayerClient)this).PlaylistItemChanged(orderedItems[i]).ConfigureAwait(false);
|
await ((IMultiplayerClient)this).PlaylistItemChanged(item).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
serverSidePlaylist = orderedItems;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user