Skip to content

Commit

Permalink
Finish ToDo for leaderboard most hunted
Browse files Browse the repository at this point in the history
  • Loading branch information
Simyon264 committed Apr 28, 2024
1 parent ed42dde commit ae0471b
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 3 deletions.
18 changes: 18 additions & 0 deletions Client/Components/Pages/Leaderboard.razor
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,24 @@ else
}
</tbody>
</table>

<table class="table">
<thead>
<tr>
<th>Player name</th>
<th>Times hunted by antags</th>
</tr>
</thead>
<tbody>
@foreach (var player in LeaderboardData.MostHuntedPlayer)
{
<tr>
<td>@player.Value.Player.Username</td>
<td>@player.Value.Count</td>
</tr>
}
</tbody>
</table>
}

<script>
Expand Down
49 changes: 47 additions & 2 deletions Server/Api/DataController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Net.WebSockets;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
Expand All @@ -20,6 +21,8 @@ namespace Server.Api;
[Route("api/[controller]")]
public class DataController : ControllerBase
{
public static readonly Regex HuntedRegex = new Regex(@"(?<=Kill(?:\sor\smaroon)\s)([^,]+)");

private readonly ReplayDbContext _context;
private readonly IMemoryCache _cache;

Expand Down Expand Up @@ -75,7 +78,8 @@ public async Task<LeaderboardData> GetLeaderboard(
var leaderboardResult = new LeaderboardData()
{
MostSeenPlayers = new Dictionary<string, PlayerCount>(),
MostAntagPlayers = new Dictionary<string, PlayerCount>()
MostAntagPlayers = new Dictionary<string, PlayerCount>(),
MostHuntedPlayer = new Dictionary<string, PlayerCount>(),
};

// To calculate the most seen player, we just count how many times we see a player in each RoundEndPlayer list.
Expand Down Expand Up @@ -133,7 +137,36 @@ public async Task<LeaderboardData> GetLeaderboard(

#endregion

// TODO: Implement most hunted player
// The most hunted player is a bit more complex. We need to check the round end text for the following string
// "Kill or maroon <name>, <job> | "
// We need to extract the name and then look for that player in the player list for that replay.
// If we find the player, we increment the count.
if (dataReplay.RoundEndText == null || dataReplay.RoundEndPlayers == null)
continue;

var matches = HuntedRegex.Matches(dataReplay.RoundEndText);
foreach (Match match in matches)
{
var playerName = match.Value.Trim();
var player = dataReplay.RoundEndPlayers.FirstOrDefault(p => p.PlayerIcName == playerName);
if (player == null)
continue;

var playerKey = new PlayerData()
{
PlayerGuid = player.PlayerGuid,
Username = ""
};
var didAdd = leaderboardResult.MostHuntedPlayer.TryAdd(playerKey.PlayerGuid.ToString(), new PlayerCount()
{
Count = 1,
Player = playerKey,
});
if (!didAdd)
{
leaderboardResult.MostHuntedPlayer[playerKey.PlayerGuid.ToString()].Count++;
}
}
}

// Need to only return the top 10 players
Expand All @@ -147,6 +180,11 @@ public async Task<LeaderboardData> GetLeaderboard(
.Take(10)
.ToDictionary(p => p.Key, p => p.Value);

leaderboardResult.MostHuntedPlayer = leaderboardResult.MostHuntedPlayer
.OrderByDescending(p => p.Value.Count)
.Take(10)
.ToDictionary(p => p.Key, p => p.Value);

// Now we need to fetch the usernames for the players
foreach (var player in leaderboardResult.MostSeenPlayers)
{
Expand All @@ -162,6 +200,13 @@ public async Task<LeaderboardData> GetLeaderboard(
await Task.Delay(50); // Rate limit the API
}

foreach (var player in leaderboardResult.MostHuntedPlayer)
{
var playerData = await FetchPlayerDataFromGuid(player.Value.Player.PlayerGuid);
player.Value.Player.Username = playerData.Username;
await Task.Delay(50); // Rate limit the API
}

// Save leaderboard to cache (its expensive as fuck to calculate)
var cacheEntryOptions = new MemoryCacheEntryOptions()
.SetAbsoluteExpiration(TimeSpan.FromHours(3));
Expand Down
2 changes: 1 addition & 1 deletion Shared/LeaderboardData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class LeaderboardData
/// <summary>
/// Most times as a kill or maroon target.
/// </summary>
public Dictionary<string, PlayerData> MostHuntedPlayer { get; set; }
public Dictionary<string, PlayerCount> MostHuntedPlayer { get; set; }

Check warning on line 13 in Shared/LeaderboardData.cs

View workflow job for this annotation

GitHub Actions / deploy

Non-nullable property 'MostHuntedPlayer' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.
}

public class PlayerCount
Expand Down

0 comments on commit ae0471b

Please sign in to comment.