diff --git a/src/DevilDaggersInfo.Web.ApiSpec.Main/CustomLeaderboards/GetCustomLeaderboardAllowedCategory.cs b/src/DevilDaggersInfo.Web.ApiSpec.Main/CustomLeaderboards/GetCustomLeaderboardAllowedCategory.cs
index 05a2e3684..63fe6515d 100644
--- a/src/DevilDaggersInfo.Web.ApiSpec.Main/CustomLeaderboards/GetCustomLeaderboardAllowedCategory.cs
+++ b/src/DevilDaggersInfo.Web.ApiSpec.Main/CustomLeaderboards/GetCustomLeaderboardAllowedCategory.cs
@@ -7,4 +7,6 @@ public record GetCustomLeaderboardAllowedCategory
public required GameMode GameMode { get; init; }
public required CustomLeaderboardRankSorting RankSorting { get; init; }
+
+ public required int LeaderboardCount { get; init; }
}
diff --git a/src/DevilDaggersInfo.Web.ApiSpec.Tools/CustomLeaderboards/GetCustomLeaderboardAllowedCategory.cs b/src/DevilDaggersInfo.Web.ApiSpec.Tools/CustomLeaderboards/GetCustomLeaderboardAllowedCategory.cs
index bca7ce63b..5f6a8b9a7 100644
--- a/src/DevilDaggersInfo.Web.ApiSpec.Tools/CustomLeaderboards/GetCustomLeaderboardAllowedCategory.cs
+++ b/src/DevilDaggersInfo.Web.ApiSpec.Tools/CustomLeaderboards/GetCustomLeaderboardAllowedCategory.cs
@@ -5,4 +5,6 @@ public record GetCustomLeaderboardAllowedCategory
public required SpawnsetGameMode GameMode { get; init; }
public required CustomLeaderboardRankSorting RankSorting { get; init; }
+
+ public required int LeaderboardCount { get; init; }
}
diff --git a/src/DevilDaggersInfo.Web.Client/Pages/Custom/Leaderboards/Index.cs b/src/DevilDaggersInfo.Web.Client/Pages/Custom/Leaderboards/Index.cs
index 3de966690..06cbe05d0 100644
--- a/src/DevilDaggersInfo.Web.Client/Pages/Custom/Leaderboards/Index.cs
+++ b/src/DevilDaggersInfo.Web.Client/Pages/Custom/Leaderboards/Index.cs
@@ -61,7 +61,7 @@ protected override async Task OnInitializedAsync()
GetTotalCustomLeaderboardData = await Http.GetTotalCustomLeaderboardData();
List allowedCategories = await Http.GetCustomLeaderboardAllowedCategories();
- _categories = allowedCategories.ConvertAll(a => new CategoryDropdown(a.GameMode, a.RankSorting));
+ _categories = allowedCategories.ConvertAll(a => new CategoryDropdown(a.GameMode, a.RankSorting, a.LeaderboardCount));
}
protected override async Task OnParametersSetAsync()
@@ -135,10 +135,13 @@ private async Task Fetch()
private sealed class CategoryDropdown
{
- public CategoryDropdown(GameMode gameMode, CustomLeaderboardRankSorting rankSorting)
+ private readonly int _leaderboardCount;
+
+ public CategoryDropdown(GameMode gameMode, CustomLeaderboardRankSorting rankSorting, int leaderboardCount)
{
GameMode = gameMode;
RankSorting = rankSorting;
+ _leaderboardCount = leaderboardCount;
}
public GameMode GameMode { get; }
@@ -146,7 +149,9 @@ public CategoryDropdown(GameMode gameMode, CustomLeaderboardRankSorting rankSort
public override string ToString()
{
- return $"{GameMode.ToCore().ToDisplayString()}: {RankSorting.ToDisplayString()}";
+ string gameMode = GameMode.ToCore().ToDisplayString();
+ string rankSorting = RankSorting.ToDisplayString();
+ return $"{gameMode}: {rankSorting} ({_leaderboardCount})";
}
}
}
diff --git a/src/DevilDaggersInfo.Web.Client/Pages/Custom/Leaderboards/Index.razor b/src/DevilDaggersInfo.Web.Client/Pages/Custom/Leaderboards/Index.razor
index 96a17a857..0f4510da6 100644
--- a/src/DevilDaggersInfo.Web.Client/Pages/Custom/Leaderboards/Index.razor
+++ b/src/DevilDaggersInfo.Web.Client/Pages/Custom/Leaderboards/Index.razor
@@ -22,23 +22,22 @@
Check out the global custom leaderboards here.
-@if (GetCustomLeaderboards == null)
+@if (GetCustomLeaderboards == null || _categories == null)
{
Spawnset name
-
+
Author name
-
- @if (_categories != null)
- {
- Category
-
- }
+
+ Category
+
@@ -71,7 +70,7 @@ else
CustomLeaderboardRankSorting.TimeAsc or CustomLeaderboardRankSorting.TimeDesc => StringFormats.TimeFormat,
_ => "0",
};
-
+
@customLeaderboard.SpawnsetAuthorName.ToNoBreakString()
diff --git a/src/DevilDaggersInfo.Web.Server.Domain.Admin/Services/CustomLeaderboardService.cs b/src/DevilDaggersInfo.Web.Server.Domain.Admin/Services/CustomLeaderboardService.cs
index 4987ef9f9..c613f2673 100644
--- a/src/DevilDaggersInfo.Web.Server.Domain.Admin/Services/CustomLeaderboardService.cs
+++ b/src/DevilDaggersInfo.Web.Server.Domain.Admin/Services/CustomLeaderboardService.cs
@@ -5,6 +5,7 @@
using DevilDaggersInfo.Web.ApiSpec.Admin.CustomEntries;
using DevilDaggersInfo.Web.Server.Domain.Admin.Converters.ApiToDomain;
using DevilDaggersInfo.Web.Server.Domain.Admin.Exceptions;
+using DevilDaggersInfo.Web.Server.Domain.Converters.CoreToDomain;
using DevilDaggersInfo.Web.Server.Domain.Entities;
using DevilDaggersInfo.Web.Server.Domain.Entities.Enums;
using DevilDaggersInfo.Web.Server.Domain.Entities.Values;
@@ -466,7 +467,7 @@ private async Task ValidateCustomLeaderboardAsync(
if (spawnsetBinary.GameMode == GameMode.TimeAttack && !spawnsetBinary.HasSpawns())
throw new CustomLeaderboardValidationException("Time Attack spawnset must have spawns.");
- if (!CustomLeaderboardUtils.IsGameModeAndRankSortingCombinationAllowed(spawnsetBinary.GameMode, rankSorting))
+ if (!CustomLeaderboardUtils.IsGameModeAndRankSortingCombinationAllowed(spawnsetBinary.GameMode.ToDomain(), rankSorting))
throw new CustomLeaderboardValidationException($"Combining game mode '{spawnsetBinary.GameMode}' and rank sorting '{rankSorting}' is not allowed.");
CustomLeaderboardCriteriaOperator deathTypeOperator = deathTypeCriteria.Operator.ToDomain();
diff --git a/src/DevilDaggersInfo.Web.Server.Domain/Models/CustomLeaderboards/CustomLeaderboardAllowedCategory.cs b/src/DevilDaggersInfo.Web.Server.Domain/Models/CustomLeaderboards/CustomLeaderboardAllowedCategory.cs
new file mode 100644
index 000000000..6be0c9262
--- /dev/null
+++ b/src/DevilDaggersInfo.Web.Server.Domain/Models/CustomLeaderboards/CustomLeaderboardAllowedCategory.cs
@@ -0,0 +1,12 @@
+using DevilDaggersInfo.Web.Server.Domain.Entities.Enums;
+
+namespace DevilDaggersInfo.Web.Server.Domain.Models.CustomLeaderboards;
+
+public record CustomLeaderboardAllowedCategory
+{
+ public required SpawnsetGameMode GameMode { get; init; }
+
+ public required CustomLeaderboardRankSorting RankSorting { get; init; }
+
+ public required int LeaderboardCount { get; init; }
+}
diff --git a/src/DevilDaggersInfo.Web.Server.Domain/Repositories/CustomLeaderboardRepository.cs b/src/DevilDaggersInfo.Web.Server.Domain/Repositories/CustomLeaderboardRepository.cs
index c7b1e01f9..c91dbbeca 100644
--- a/src/DevilDaggersInfo.Web.Server.Domain/Repositories/CustomLeaderboardRepository.cs
+++ b/src/DevilDaggersInfo.Web.Server.Domain/Repositories/CustomLeaderboardRepository.cs
@@ -344,6 +344,23 @@ public async Task
GetCustomLeaderboardIdBySpawnsetHashAsync(byte[] hash)
return customLeaderboard.Id;
}
+ public async Task> GetCustomLeaderboardAllowedCategories()
+ {
+ List<(SpawnsetGameMode GameMode, CustomLeaderboardRankSorting RankSorting)> allowedCategories = CustomLeaderboardUtils.GetAllowedGameModeAndRankSortingCombinations();
+
+ // ! Navigation property.
+ var customLeaderboards = await _dbContext.CustomLeaderboards
+ .Select(cl => new { cl.Spawnset!.GameMode, cl.RankSorting })
+ .ToListAsync();
+
+ return allowedCategories.ConvertAll(ac => new CustomLeaderboardAllowedCategory
+ {
+ GameMode = ac.GameMode,
+ RankSorting = ac.RankSorting,
+ LeaderboardCount = customLeaderboards.Count(cl => cl.GameMode == ac.GameMode && cl.RankSorting == ac.RankSorting),
+ });
+ }
+
private static CustomLeaderboardOverview ToOverview(CustomLeaderboardData cl)
{
if (cl.CustomLeaderboard.Spawnset == null)
diff --git a/src/DevilDaggersInfo.Web.Server.Domain/Utils/CustomLeaderboardUtils.cs b/src/DevilDaggersInfo.Web.Server.Domain/Utils/CustomLeaderboardUtils.cs
index a312ef2ab..cf9a2c48e 100644
--- a/src/DevilDaggersInfo.Web.Server.Domain/Utils/CustomLeaderboardUtils.cs
+++ b/src/DevilDaggersInfo.Web.Server.Domain/Utils/CustomLeaderboardUtils.cs
@@ -1,4 +1,3 @@
-using DevilDaggersInfo.Core.Spawnset;
using DevilDaggersInfo.Web.Server.Domain.Entities.Enums;
using DevilDaggersInfo.Web.Server.Domain.Extensions;
using DevilDaggersInfo.Web.Server.Domain.Models.CustomLeaderboards;
@@ -53,24 +52,24 @@ public static CustomLeaderboardDagger GetDaggerFromStat(CustomLeaderboardRankSor
return CustomLeaderboardDagger.Default;
}
- public static bool IsGameModeAndRankSortingCombinationAllowed(GameMode gameMode, CustomLeaderboardRankSorting rankSorting)
+ public static bool IsGameModeAndRankSortingCombinationAllowed(SpawnsetGameMode gameMode, CustomLeaderboardRankSorting rankSorting)
{
// Allow all rank sortings for Survival.
- if (gameMode == GameMode.Survival)
+ if (gameMode == SpawnsetGameMode.Survival)
return true;
// Allow both time rank sortings for Race.
- if (gameMode == GameMode.Race)
+ if (gameMode == SpawnsetGameMode.Race)
return rankSorting is CustomLeaderboardRankSorting.TimeAsc or CustomLeaderboardRankSorting.TimeDesc;
// Only allow ascending time sort for TimeAttack for now.
return rankSorting == CustomLeaderboardRankSorting.TimeAsc;
}
- public static List<(GameMode GameMode, CustomLeaderboardRankSorting RankSorting)> GetAllowedGameModeAndRankSortingCombinations()
+ public static List<(SpawnsetGameMode GameMode, CustomLeaderboardRankSorting RankSorting)> GetAllowedGameModeAndRankSortingCombinations()
{
- List<(GameMode GameMode, CustomLeaderboardRankSorting RankSorting)> allowedCombinations = [];
- foreach (GameMode gameMode in Enum.GetValues())
+ List<(SpawnsetGameMode GameMode, CustomLeaderboardRankSorting RankSorting)> allowedCombinations = [];
+ foreach (SpawnsetGameMode gameMode in Enum.GetValues())
{
foreach (CustomLeaderboardRankSorting rankSorting in Enum.GetValues().Where(rs => IsGameModeAndRankSortingCombinationAllowed(gameMode, rs)))
allowedCombinations.Add((gameMode, rankSorting));
diff --git a/src/DevilDaggersInfo.Web.Server/Controllers/Main/CustomLeaderboardsController.cs b/src/DevilDaggersInfo.Web.Server/Controllers/Main/CustomLeaderboardsController.cs
index 4d172f73e..675178b3f 100644
--- a/src/DevilDaggersInfo.Web.Server/Controllers/Main/CustomLeaderboardsController.cs
+++ b/src/DevilDaggersInfo.Web.Server/Controllers/Main/CustomLeaderboardsController.cs
@@ -4,13 +4,12 @@
using DevilDaggersInfo.Web.Client;
using DevilDaggersInfo.Web.Server.Converters.ApiToDomain.Main;
using DevilDaggersInfo.Web.Server.Converters.DomainToApi.Main;
-using DevilDaggersInfo.Web.Server.Domain.Converters.CoreToDomain;
using DevilDaggersInfo.Web.Server.Domain.Main.Converters.DomainToApi;
using DevilDaggersInfo.Web.Server.Domain.Repositories;
using DevilDaggersInfo.Web.Server.Domain.Utils;
using Microsoft.AspNetCore.Mvc;
using System.ComponentModel.DataAnnotations;
-using Model = DevilDaggersInfo.Web.Server.Domain.Models.CustomLeaderboards;
+using MainApi = DevilDaggersInfo.Web.Server.Domain.Models.CustomLeaderboards;
namespace DevilDaggersInfo.Web.Server.Controllers.Main;
@@ -38,7 +37,7 @@ public async Task>> GetCustomLea
CustomLeaderboardSorting? sortBy = null,
bool ascending = false)
{
- Domain.Models.Page cls = await _customLeaderboardRepository.GetCustomLeaderboardOverviewsAsync(
+ Domain.Models.Page cls = await _customLeaderboardRepository.GetCustomLeaderboardOverviewsAsync(
rankSorting: rankSorting.ToDomain(),
gameMode: gameMode.ToDomain(),
spawnsetFilter: spawnsetFilter,
@@ -61,7 +60,7 @@ public async Task>> GetCustomLea
[ProducesResponseType(StatusCodes.Status400BadRequest)]
public async Task> GetGlobalCustomLeaderboardForCategory([Required] GameMode gameMode, [Required] CustomLeaderboardRankSorting rankSorting)
{
- Model.GlobalCustomLeaderboard globalCustomLeaderboard = await _customLeaderboardRepository.GetGlobalCustomLeaderboardAsync(gameMode.ToDomain(), rankSorting.ToDomain());
+ MainApi.GlobalCustomLeaderboard globalCustomLeaderboard = await _customLeaderboardRepository.GetGlobalCustomLeaderboardAsync(gameMode.ToDomain(), rankSorting.ToDomain());
return new GetGlobalCustomLeaderboard
{
Entries = globalCustomLeaderboard.Entries
@@ -97,7 +96,7 @@ public async Task> GetGlobalCustomLeade
[ProducesResponseType(StatusCodes.Status200OK)]
public async Task> GetTotalCustomLeaderboardData()
{
- Model.CustomLeaderboardsTotalData totalData = await _customLeaderboardRepository.GetCustomLeaderboardsTotalDataAsync();
+ MainApi.CustomLeaderboardsTotalData totalData = await _customLeaderboardRepository.GetCustomLeaderboardsTotalDataAsync();
return new GetTotalCustomLeaderboardData
{
LeaderboardsPerGameMode = totalData.LeaderboardsPerGameMode.ToDictionary(kvp => kvp.Key.ToMainApi(), kvp => kvp.Value),
@@ -113,19 +112,15 @@ public async Task> GetTotalCustomLea
[ProducesResponseType(StatusCodes.Status404NotFound)]
public async Task> GetCustomLeaderboardById(int id)
{
- Model.SortedCustomLeaderboard cl = await _customLeaderboardRepository.GetSortedCustomLeaderboardByIdAsync(id);
+ MainApi.SortedCustomLeaderboard cl = await _customLeaderboardRepository.GetSortedCustomLeaderboardByIdAsync(id);
return cl.ToMainApi();
}
[HttpGet("allowed-categories")]
[ProducesResponseType(StatusCodes.Status200OK)]
- public ActionResult> GetCustomLeaderboardAllowedCategories()
+ public async Task>> GetCustomLeaderboardAllowedCategories()
{
- List<(DevilDaggersInfo.Core.Spawnset.GameMode GameMode, Domain.Entities.Enums.CustomLeaderboardRankSorting RankSorting)> allowedCategories = CustomLeaderboardUtils.GetAllowedGameModeAndRankSortingCombinations();
- return allowedCategories.ConvertAll(ac => new GetCustomLeaderboardAllowedCategory
- {
- GameMode = ac.GameMode.ToDomain().ToMainApi(),
- RankSorting = ac.RankSorting.ToMainApi(),
- });
+ List allowedCategories = await _customLeaderboardRepository.GetCustomLeaderboardAllowedCategories();
+ return allowedCategories.ConvertAll(ac => ac.ToMainApi());
}
}
diff --git a/src/DevilDaggersInfo.Web.Server/Controllers/Tools/CustomLeaderboardsController.cs b/src/DevilDaggersInfo.Web.Server/Controllers/Tools/CustomLeaderboardsController.cs
index ce1a28104..693ec19e5 100644
--- a/src/DevilDaggersInfo.Web.Server/Controllers/Tools/CustomLeaderboardsController.cs
+++ b/src/DevilDaggersInfo.Web.Server/Controllers/Tools/CustomLeaderboardsController.cs
@@ -67,13 +67,9 @@ public async Task CustomLeaderboardExistsBySpawnsetHash([FromQuery
[HttpGet("allowed-categories")]
[ProducesResponseType(StatusCodes.Status200OK)]
- public ActionResult> GetCustomLeaderboardAllowedCategories()
+ public async Task>> GetCustomLeaderboardAllowedCategories()
{
- List<(DevilDaggersInfo.Core.Spawnset.GameMode GameMode, Domain.Entities.Enums.CustomLeaderboardRankSorting RankSorting)> allowedCategories = CustomLeaderboardUtils.GetAllowedGameModeAndRankSortingCombinations();
- return allowedCategories.ConvertAll(ac => new GetCustomLeaderboardAllowedCategory
- {
- GameMode = ac.GameMode.ToDomain().ToToolsApi(),
- RankSorting = ac.RankSorting.ToToolsApi(),
- });
+ List customLeaderboardAllowedCategories = await _customLeaderboardRepository.GetCustomLeaderboardAllowedCategories();
+ return customLeaderboardAllowedCategories.ConvertAll(ac => ac.ToToolsApi());
}
}
diff --git a/src/DevilDaggersInfo.Web.Server/Converters/DomainToApi/Main/CustomLeaderboardConverters.cs b/src/DevilDaggersInfo.Web.Server/Converters/DomainToApi/Main/CustomLeaderboardConverters.cs
index 36b5a3c27..4095d8e2b 100644
--- a/src/DevilDaggersInfo.Web.Server/Converters/DomainToApi/Main/CustomLeaderboardConverters.cs
+++ b/src/DevilDaggersInfo.Web.Server/Converters/DomainToApi/Main/CustomLeaderboardConverters.cs
@@ -88,6 +88,16 @@ private static MainApi.GetCustomEntry ToMainApi(this CustomEntry customEntry, Sp
};
}
+ public static MainApi.GetCustomLeaderboardAllowedCategory ToMainApi(this CustomLeaderboardAllowedCategory allowedCategory)
+ {
+ return new MainApi.GetCustomLeaderboardAllowedCategory
+ {
+ GameMode = allowedCategory.GameMode.ToMainApi(),
+ RankSorting = allowedCategory.RankSorting.ToMainApi(),
+ LeaderboardCount = allowedCategory.LeaderboardCount,
+ };
+ }
+
private static MainApi.GetCustomLeaderboardDaggers ToMainApi(this CustomLeaderboardDaggers customLeaderboardDaggers, bool isTime)
{
return new MainApi.GetCustomLeaderboardDaggers
diff --git a/src/DevilDaggersInfo.Web.Server/Converters/DomainToApi/Tools/CustomLeaderboardConverters.cs b/src/DevilDaggersInfo.Web.Server/Converters/DomainToApi/Tools/CustomLeaderboardConverters.cs
index df0fc7be8..2d9b7212d 100644
--- a/src/DevilDaggersInfo.Web.Server/Converters/DomainToApi/Tools/CustomLeaderboardConverters.cs
+++ b/src/DevilDaggersInfo.Web.Server/Converters/DomainToApi/Tools/CustomLeaderboardConverters.cs
@@ -161,6 +161,16 @@ public static ToolsApi.GetCustomLeaderboardForOverview ToToolsApi(this CustomLea
};
}
+ public static ToolsApi.GetCustomLeaderboardAllowedCategory ToToolsApi(this CustomLeaderboardAllowedCategory customLeaderboardAllowedCategory)
+ {
+ return new ToolsApi.GetCustomLeaderboardAllowedCategory
+ {
+ GameMode = customLeaderboardAllowedCategory.GameMode.ToToolsApi(),
+ RankSorting = customLeaderboardAllowedCategory.RankSorting.ToToolsApi(),
+ LeaderboardCount = customLeaderboardAllowedCategory.LeaderboardCount,
+ };
+ }
+
private static ToolsApi.GetCustomLeaderboardCriteria ToToolsApi(this CustomLeaderboardCriteria customLeaderboardCriteria)
{
return new ToolsApi.GetCustomLeaderboardCriteria