mirror of
https://github.com/LBPUnion/ProjectLighthouse.git
synced 2025-07-19 11:41:30 +00:00
Fix level ordering in busiest slots
This commit is contained in:
parent
15a3cbea42
commit
91e792aea0
3 changed files with 163 additions and 22 deletions
|
@ -351,31 +351,30 @@ public class SlotsController : ControllerBase
|
|||
|
||||
PaginationData pageData = this.Request.GetPaginationData();
|
||||
|
||||
Dictionary<int, int> playersBySlotId = new();
|
||||
List<int> busiestSlots = RoomHelper.Rooms.Where(r => r.Slot.SlotType == SlotType.User)
|
||||
.GroupBy(r => r.Slot.SlotId)
|
||||
.OrderByDescending(kvp => kvp.Count())
|
||||
.Select(kvp => kvp.Key)
|
||||
.AsQueryable()
|
||||
.ApplyPagination(pageData)
|
||||
.ToList();
|
||||
|
||||
foreach (Room room in RoomHelper.Rooms)
|
||||
pageData.TotalElements = busiestSlots.Count;
|
||||
|
||||
List<SlotBase> slots = new();
|
||||
|
||||
Expression<Func<SlotEntity, bool>> filterQuery = this.FilterFromRequest(token).Build();
|
||||
|
||||
foreach (int slotId in busiestSlots)
|
||||
{
|
||||
// TODO: support developer slotTypes?
|
||||
if (room.Slot.SlotType != SlotType.User) continue;
|
||||
|
||||
if (!playersBySlotId.TryGetValue(room.Slot.SlotId, out int playerCount))
|
||||
playersBySlotId.Add(room.Slot.SlotId, 0);
|
||||
|
||||
playerCount += room.PlayerIds.Count;
|
||||
|
||||
playersBySlotId.Remove(room.Slot.SlotId);
|
||||
playersBySlotId.Add(room.Slot.SlotId, playerCount);
|
||||
SlotBase? slot = await this.database.Slots.Where(s => s.SlotId == slotId)
|
||||
.Where(filterQuery)
|
||||
.Select(s => SlotBase.CreateFromEntity(s, token))
|
||||
.FirstOrDefaultAsync();
|
||||
if (slot == null) continue;
|
||||
slots.Add(slot);
|
||||
}
|
||||
|
||||
pageData.TotalElements = playersBySlotId.Count;
|
||||
|
||||
List<int> orderedPlayersBySlotId = playersBySlotId.OrderByDescending(kvp => kvp.Value).Select(kvp => kvp.Key).ToList();
|
||||
|
||||
SlotQueryBuilder queryBuilder = this.FilterFromRequest(token);
|
||||
queryBuilder.AddFilter(0, new SlotIdFilter(orderedPlayersBySlotId));
|
||||
|
||||
List<SlotBase> slots = await this.database.GetSlots(token, queryBuilder, pageData, new SlotSortBuilder<SlotEntity>());
|
||||
|
||||
return this.Ok(new GenericSlotResponse(slots, pageData));
|
||||
}
|
||||
}
|
|
@ -1,13 +1,16 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Servers.GameServer.Controllers.Slots;
|
||||
using LBPUnion.ProjectLighthouse.Tests.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Level;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
|
||||
using LBPUnion.ProjectLighthouse.Types.Levels;
|
||||
using LBPUnion.ProjectLighthouse.Types.Matchmaking.Rooms;
|
||||
using LBPUnion.ProjectLighthouse.Types.Serialization;
|
||||
using LBPUnion.ProjectLighthouse.Types.Users;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
@ -377,4 +380,139 @@ public class SlotControllerTests
|
|||
}
|
||||
#endregion
|
||||
|
||||
#region BusiestLevels
|
||||
|
||||
// Rather than trying to mock a singleton
|
||||
// we just make the unit tests take turns
|
||||
private static readonly Mutex roomMutex = new(false);
|
||||
|
||||
private static async Task AddRoom(int slotId, SlotType type, params int[] playerIds)
|
||||
{
|
||||
await RoomHelper.Rooms.AddAsync(new Room
|
||||
{
|
||||
PlayerIds = new List<int>(playerIds),
|
||||
Slot = new RoomSlot
|
||||
{
|
||||
SlotId = slotId,
|
||||
SlotType = type,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BusiestLevels_ShouldReturnSlots_OrderedByRoomCount()
|
||||
{
|
||||
roomMutex.WaitOne();
|
||||
try
|
||||
{
|
||||
DatabaseContext db = await MockHelper.GetTestDatabase(new[]
|
||||
{
|
||||
new List<SlotEntity>
|
||||
{
|
||||
new()
|
||||
{
|
||||
SlotId = 1,
|
||||
Type = SlotType.User,
|
||||
},
|
||||
new()
|
||||
{
|
||||
SlotId = 2,
|
||||
Type = SlotType.User,
|
||||
},
|
||||
new()
|
||||
{
|
||||
SlotId = 3,
|
||||
Type = SlotType.User,
|
||||
},
|
||||
new()
|
||||
{
|
||||
SlotId = 4,
|
||||
Type = SlotType.Developer,
|
||||
InternalSlotId = 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
SlotsController controller = new(db);
|
||||
controller.SetupTestController();
|
||||
|
||||
await AddRoom(1, SlotType.User, 1);
|
||||
await AddRoom(2, SlotType.User, 2);
|
||||
await AddRoom(2, SlotType.User, 3);
|
||||
await AddRoom(3, SlotType.User, 4);
|
||||
await AddRoom(3, SlotType.User, 5);
|
||||
await AddRoom(3, SlotType.User, 6);
|
||||
|
||||
await AddRoom(10, SlotType.Developer, 7);
|
||||
|
||||
IActionResult result = await controller.BusiestLevels();
|
||||
GenericSlotResponse slotResponse = result.CastTo<OkObjectResult, GenericSlotResponse>();
|
||||
Assert.Equal(3, slotResponse.Slots.Count);
|
||||
Assert.IsType<GameUserSlot>(slotResponse.Slots[0]);
|
||||
Assert.Equal(3, ((GameUserSlot)slotResponse.Slots[0]).SlotId);
|
||||
Assert.IsType<GameUserSlot>(slotResponse.Slots[1]);
|
||||
Assert.Equal(2, ((GameUserSlot)slotResponse.Slots[1]).SlotId);
|
||||
Assert.IsType<GameUserSlot>(slotResponse.Slots[2]);
|
||||
Assert.Equal(1, ((GameUserSlot)slotResponse.Slots[2]).SlotId);
|
||||
}
|
||||
finally
|
||||
{
|
||||
roomMutex.ReleaseMutex();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BusiestLevels_ShouldNotIncludeDeveloperSlots()
|
||||
{
|
||||
roomMutex.WaitOne();
|
||||
try
|
||||
{
|
||||
DatabaseContext db = await MockHelper.GetTestDatabase(new[]
|
||||
{
|
||||
new List<SlotEntity>
|
||||
{
|
||||
new()
|
||||
{
|
||||
SlotId = 4,
|
||||
Type = SlotType.Developer,
|
||||
InternalSlotId = 10,
|
||||
},
|
||||
},
|
||||
});
|
||||
SlotsController controller = new(db);
|
||||
controller.SetupTestController();
|
||||
|
||||
await AddRoom(10, SlotType.Developer, 1);
|
||||
|
||||
IActionResult result = await controller.BusiestLevels();
|
||||
GenericSlotResponse slotResponse = result.CastTo<OkObjectResult, GenericSlotResponse>();
|
||||
Assert.Empty(slotResponse.Slots);
|
||||
}
|
||||
finally
|
||||
{
|
||||
roomMutex.ReleaseMutex();
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BusiestLevels_ShouldNotIncludeInvalidSlots()
|
||||
{
|
||||
roomMutex.WaitOne();
|
||||
try
|
||||
{
|
||||
DatabaseContext db = await MockHelper.GetTestDatabase();
|
||||
SlotsController controller = new(db);
|
||||
controller.SetupTestController();
|
||||
|
||||
await AddRoom(1, SlotType.User, 1);
|
||||
|
||||
IActionResult result = await controller.BusiestLevels();
|
||||
GenericSlotResponse slotResponse = result.CastTo<OkObjectResult, GenericSlotResponse>();
|
||||
Assert.Empty(slotResponse.Slots);
|
||||
}
|
||||
finally
|
||||
{
|
||||
roomMutex.ReleaseMutex();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
|
@ -7,6 +7,7 @@ using System.Runtime.CompilerServices;
|
|||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using LBPUnion.ProjectLighthouse.Database;
|
||||
using LBPUnion.ProjectLighthouse.Helpers;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Profile;
|
||||
using LBPUnion.ProjectLighthouse.Types.Entities.Token;
|
||||
using LBPUnion.ProjectLighthouse.Types.Users;
|
||||
|
@ -53,6 +54,8 @@ public static class MockHelper
|
|||
|
||||
public static async Task<DatabaseContext> GetTestDatabase(IEnumerable<IList> sets, [CallerMemberName] string caller = "", [CallerLineNumber] int lineNum = 0)
|
||||
{
|
||||
await RoomHelper.Rooms.RemoveAllAsync();
|
||||
|
||||
Dictionary<Type, IList> setDict = new();
|
||||
foreach (IList list in sets)
|
||||
{
|
||||
|
@ -77,7 +80,6 @@ public static class MockHelper
|
|||
};
|
||||
}
|
||||
|
||||
|
||||
DbContextOptions<DatabaseContext> options = new DbContextOptionsBuilder<DatabaseContext>()
|
||||
.UseInMemoryDatabase($"{caller}_{lineNum}")
|
||||
.Options;
|
||||
|
@ -101,6 +103,8 @@ public static class MockHelper
|
|||
[CallerMemberName] string caller = "", [CallerLineNumber] int lineNum = 0
|
||||
)
|
||||
{
|
||||
await RoomHelper.Rooms.RemoveAllAsync();
|
||||
|
||||
users ??= new List<UserEntity>
|
||||
{
|
||||
GetUnitTestUser(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue