Skip to content

Commit b218fa9

Browse files
feat: Enhance server analytics to track denied chat commands
1 parent 4aee316 commit b218fa9

3 files changed

Lines changed: 34 additions & 11 deletions

File tree

src/XtremeIdiots.Portal.Repository.Abstractions.V1/Models/V1/Analytics/Servers/ServerChatCommandCountDto.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ public record ServerChatCommandCountDto : IDto
1010
[JsonProperty]
1111
public int Count { get; internal set; }
1212

13+
[JsonProperty]
14+
public int DeniedCount { get; internal set; }
15+
1316
[JsonIgnore]
1417
public Dictionary<string, string> TelemetryProperties => [];
1518
}

src/XtremeIdiots.Portal.Repository.Abstractions.V1/Models/V1/Analytics/Servers/ServerChatCommandsSummaryDto.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ public record ServerChatCommandsSummaryDto : IDto
1010
[JsonProperty]
1111
public int TotalExecutions { get; internal set; }
1212

13+
[JsonProperty]
14+
public int TotalDenied { get; internal set; }
15+
1316
[JsonProperty]
1417
public List<ServerChatCommandCountDto> Commands { get; internal set; } = [];
1518

src/XtremeIdiots.Portal.Repository.Api.V1/Controllers/V1/ServerAnalyticsController.cs

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ namespace XtremeIdiots.Portal.RepositoryWebApi.Controllers.V1;
2828
public class ServerAnalyticsController : ControllerBase, IServerAnalyticsApi
2929
{
3030
private const string ChatCommandExecutionEventType = "ChatCommandExecution";
31+
private const string ChatCommandDeniedEventType = "ChatCommandDenied";
3132

3233
private readonly PortalDbContext context;
3334
private readonly ILiveStatusStore liveStatusStore;
@@ -471,39 +472,55 @@ async Task<ApiResult<ServerChatCommandsSummaryDto>> IServerAnalyticsApi.GetChatC
471472
}
472473

473474
// The executed command name is stored only inside the event's JSON payload, so we materialise
474-
// the payloads for ChatCommandExecution events in the window and aggregate by command in memory.
475+
// the payloads for chat-command events in the window and aggregate by command in memory.
476+
// ChatCommandExecution = the command ran; ChatCommandDenied = the caller was blocked (both
477+
// carry the same commandPrefix payload).
475478
var payloads = await context.GameServerEvents
476479
.AsNoTracking()
477480
.Where(e => e.GameServerId == gameServerId
478-
&& e.EventType == ChatCommandExecutionEventType
481+
&& (e.EventType == ChatCommandExecutionEventType || e.EventType == ChatCommandDeniedEventType)
479482
&& e.Timestamp >= fromUtc && e.Timestamp < toUtc
480483
&& e.EventData != null)
481-
.Select(e => e.EventData!)
484+
.Select(e => new { e.EventType, EventData = e.EventData! })
482485
.ToListAsync(cancellationToken).ConfigureAwait(false);
483486

484-
var counts = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
487+
var executed = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
488+
var denied = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
485489
foreach (var payload in payloads)
486490
{
487-
var command = ExtractCommandPrefix(payload);
491+
var command = ExtractCommandPrefix(payload.EventData);
488492
if (string.IsNullOrWhiteSpace(command))
489493
{
490494
continue;
491495
}
492496

493-
counts[command] = counts.TryGetValue(command, out var existing) ? existing + 1 : 1;
497+
var target = payload.EventType == ChatCommandDeniedEventType ? denied : executed;
498+
target[command] = target.TryGetValue(command, out var existing) ? existing + 1 : 1;
494499
}
495500

496-
var commands = counts
497-
.OrderByDescending(kvp => kvp.Value)
498-
.ThenBy(kvp => kvp.Key, StringComparer.OrdinalIgnoreCase)
501+
var commands = executed.Keys
502+
.Union(denied.Keys, StringComparer.OrdinalIgnoreCase)
503+
.Select(command =>
504+
{
505+
executed.TryGetValue(command, out var executedCount);
506+
denied.TryGetValue(command, out var deniedCount);
507+
return new ServerChatCommandCountDto
508+
{
509+
Command = command,
510+
Count = executedCount,
511+
DeniedCount = deniedCount
512+
};
513+
})
514+
.OrderByDescending(c => c.Count + c.DeniedCount)
515+
.ThenBy(c => c.Command, StringComparer.OrdinalIgnoreCase)
499516
.Take(top)
500-
.Select(kvp => new ServerChatCommandCountDto { Command = kvp.Key, Count = kvp.Value })
501517
.ToList();
502518

503519
var dto = new ServerChatCommandsSummaryDto
504520
{
505521
Window = CreateWindow(fromUtc, toUtc),
506-
TotalExecutions = counts.Values.Sum(),
522+
TotalExecutions = executed.Values.Sum(),
523+
TotalDenied = denied.Values.Sum(),
507524
Commands = commands
508525
};
509526

0 commit comments

Comments
 (0)