3
3
using System . Net . WebSockets ;
4
4
using System . Text ;
5
5
using System . Text . Json ;
6
+ using System . Text . RegularExpressions ;
6
7
using Microsoft . AspNetCore . Cors ;
7
8
using Microsoft . AspNetCore . Mvc ;
8
9
using Microsoft . EntityFrameworkCore ;
@@ -20,6 +21,8 @@ namespace Server.Api;
20
21
[ Route ( "api/[controller]" ) ]
21
22
public class DataController : ControllerBase
22
23
{
24
+ public static readonly Regex HuntedRegex = new Regex ( @"(?<=Kill(?:\sor\smaroon)\s)([^,]+)" ) ;
25
+
23
26
private readonly ReplayDbContext _context ;
24
27
private readonly IMemoryCache _cache ;
25
28
@@ -75,7 +78,8 @@ public async Task<LeaderboardData> GetLeaderboard(
75
78
var leaderboardResult = new LeaderboardData ( )
76
79
{
77
80
MostSeenPlayers = new Dictionary < string , PlayerCount > ( ) ,
78
- MostAntagPlayers = new Dictionary < string , PlayerCount > ( )
81
+ MostAntagPlayers = new Dictionary < string , PlayerCount > ( ) ,
82
+ MostHuntedPlayer = new Dictionary < string , PlayerCount > ( ) ,
79
83
} ;
80
84
81
85
// To calculate the most seen player, we just count how many times we see a player in each RoundEndPlayer list.
@@ -133,7 +137,36 @@ public async Task<LeaderboardData> GetLeaderboard(
133
137
134
138
#endregion
135
139
136
- // TODO: Implement most hunted player
140
+ // The most hunted player is a bit more complex. We need to check the round end text for the following string
141
+ // "Kill or maroon <name>, <job> | "
142
+ // We need to extract the name and then look for that player in the player list for that replay.
143
+ // If we find the player, we increment the count.
144
+ if ( dataReplay . RoundEndText == null || dataReplay . RoundEndPlayers == null )
145
+ continue ;
146
+
147
+ var matches = HuntedRegex . Matches ( dataReplay . RoundEndText ) ;
148
+ foreach ( Match match in matches )
149
+ {
150
+ var playerName = match . Value . Trim ( ) ;
151
+ var player = dataReplay . RoundEndPlayers . FirstOrDefault ( p => p . PlayerIcName == playerName ) ;
152
+ if ( player == null )
153
+ continue ;
154
+
155
+ var playerKey = new PlayerData ( )
156
+ {
157
+ PlayerGuid = player . PlayerGuid ,
158
+ Username = ""
159
+ } ;
160
+ var didAdd = leaderboardResult . MostHuntedPlayer . TryAdd ( playerKey . PlayerGuid . ToString ( ) , new PlayerCount ( )
161
+ {
162
+ Count = 1 ,
163
+ Player = playerKey ,
164
+ } ) ;
165
+ if ( ! didAdd )
166
+ {
167
+ leaderboardResult . MostHuntedPlayer [ playerKey . PlayerGuid . ToString ( ) ] . Count ++ ;
168
+ }
169
+ }
137
170
}
138
171
139
172
// Need to only return the top 10 players
@@ -147,6 +180,11 @@ public async Task<LeaderboardData> GetLeaderboard(
147
180
. Take ( 10 )
148
181
. ToDictionary ( p => p . Key , p => p . Value ) ;
149
182
183
+ leaderboardResult . MostHuntedPlayer = leaderboardResult . MostHuntedPlayer
184
+ . OrderByDescending ( p => p . Value . Count )
185
+ . Take ( 10 )
186
+ . ToDictionary ( p => p . Key , p => p . Value ) ;
187
+
150
188
// Now we need to fetch the usernames for the players
151
189
foreach ( var player in leaderboardResult . MostSeenPlayers )
152
190
{
@@ -162,6 +200,13 @@ public async Task<LeaderboardData> GetLeaderboard(
162
200
await Task . Delay ( 50 ) ; // Rate limit the API
163
201
}
164
202
203
+ foreach ( var player in leaderboardResult . MostHuntedPlayer )
204
+ {
205
+ var playerData = await FetchPlayerDataFromGuid ( player . Value . Player . PlayerGuid ) ;
206
+ player . Value . Player . Username = playerData . Username ;
207
+ await Task . Delay ( 50 ) ; // Rate limit the API
208
+ }
209
+
165
210
// Save leaderboard to cache (its expensive as fuck to calculate)
166
211
var cacheEntryOptions = new MemoryCacheEntryOptions ( )
167
212
. SetAbsoluteExpiration ( TimeSpan . FromHours ( 3 ) ) ;
0 commit comments