From fd29f2d1adbc6ee10db6943e27a974a660ea78d8 Mon Sep 17 00:00:00 2001 From: RaidMax Date: Wed, 23 Mar 2022 13:54:42 -0500 Subject: [PATCH] update stats to use new meta service --- Application/ApplicationManager.cs | 4 +- Plugins/Stats/Plugin.cs | 166 +++++++++++++++--------------- 2 files changed, 83 insertions(+), 87 deletions(-) diff --git a/Application/ApplicationManager.cs b/Application/ApplicationManager.cs index 0fbfe301..bec2f708 100644 --- a/Application/ApplicationManager.cs +++ b/Application/ApplicationManager.cs @@ -59,7 +59,6 @@ namespace IW4MAdmin.Application readonly PenaltyService PenaltySvc; public IConfigurationHandler ConfigHandler; readonly IPageList PageList; - private readonly IMetaService _metaService; private readonly TimeSpan _throttleTimeout = new TimeSpan(0, 1, 0); private readonly CancellationTokenSource _tokenSource; private readonly Dictionary> _operationLookup = new Dictionary>(); @@ -81,7 +80,7 @@ namespace IW4MAdmin.Application ITranslationLookup translationLookup, IConfigurationHandler commandConfiguration, IConfigurationHandler appConfigHandler, IGameServerInstanceFactory serverInstanceFactory, IEnumerable plugins, IParserRegexFactory parserRegexFactory, IEnumerable customParserEvents, - IEventHandler eventHandler, IScriptCommandFactory scriptCommandFactory, IDatabaseContextFactory contextFactory, IMetaService metaService, + IEventHandler eventHandler, IScriptCommandFactory scriptCommandFactory, IDatabaseContextFactory contextFactory, IMetaRegistration metaRegistration, IScriptPluginServiceResolver scriptPluginServiceResolver, ClientService clientService, IServiceProvider serviceProvider, ChangeHistoryService changeHistoryService, ApplicationConfiguration appConfig, PenaltyService penaltyService) { @@ -97,7 +96,6 @@ namespace IW4MAdmin.Application AdditionalRConParsers = new List() { new BaseRConParser(serviceProvider.GetRequiredService>(), parserRegexFactory) }; TokenAuthenticator = new TokenAuthentication(); _logger = logger; - _metaService = metaService; _tokenSource = new CancellationTokenSource(); _commands = commands.ToList(); _translationLookup = translationLookup; diff --git a/Plugins/Stats/Plugin.cs b/Plugins/Stats/Plugin.cs index e645883f..947dbc2a 100644 --- a/Plugins/Stats/Plugin.cs +++ b/Plugins/Stats/Plugin.cs @@ -9,6 +9,7 @@ using Stats.Dtos; using System; using System.Collections.Generic; using System.Linq; +using System.Threading; using System.Threading.Tasks; using Data.Abstractions; using Data.Models.Client.Stats; @@ -35,7 +36,7 @@ namespace IW4MAdmin.Plugins.Stats private readonly IDatabaseContextFactory _databaseContextFactory; private readonly ITranslationLookup _translationLookup; - private readonly IMetaService _metaService; + private readonly IMetaServiceV2 _metaService; private readonly IResourceQueryHelper _chatQueryHelper; private readonly ILogger _managerLogger; private readonly ILogger _logger; @@ -43,7 +44,7 @@ namespace IW4MAdmin.Plugins.Stats private readonly IServerDistributionCalculator _serverDistributionCalculator; public Plugin(ILogger logger, IConfigurationHandlerFactory configurationHandlerFactory, IDatabaseContextFactory databaseContextFactory, - ITranslationLookup translationLookup, IMetaService metaService, IResourceQueryHelper chatQueryHelper, ILogger managerLogger, + ITranslationLookup translationLookup, IMetaServiceV2 metaService, IResourceQueryHelper chatQueryHelper, ILogger managerLogger, IEnumerable statCalculators, IServerDistributionCalculator serverDistributionCalculator) { Config = configurationHandlerFactory.GetConfigurationHandler("StatsPluginSettings"); @@ -57,52 +58,52 @@ namespace IW4MAdmin.Plugins.Stats _serverDistributionCalculator = serverDistributionCalculator; } - public async Task OnEventAsync(GameEvent E, Server S) + public async Task OnEventAsync(GameEvent gameEvent, Server server) { - switch (E.Type) + switch (gameEvent.Type) { case GameEvent.EventType.Start: - Manager.AddServer(S); + Manager.AddServer(server); break; case GameEvent.EventType.Disconnect: - await Manager.RemovePlayer(E.Origin); + await Manager.RemovePlayer(gameEvent.Origin); break; case GameEvent.EventType.Say: - if (!string.IsNullOrEmpty(E.Data) && - E.Origin.ClientId > 1) + if (!string.IsNullOrEmpty(gameEvent.Data) && + gameEvent.Origin.ClientId > 1) { - await Manager.AddMessageAsync(E.Origin.ClientId, StatManager.GetIdForServer(S), true, E.Data); + await Manager.AddMessageAsync(gameEvent.Origin.ClientId, StatManager.GetIdForServer(server), true, gameEvent.Data); } break; case GameEvent.EventType.MapChange: - Manager.SetTeamBased(StatManager.GetIdForServer(S), S.Gametype != "dm"); - Manager.ResetKillstreaks(S); - await Manager.Sync(S); + Manager.SetTeamBased(StatManager.GetIdForServer(server), server.Gametype != "dm"); + Manager.ResetKillstreaks(server); + await Manager.Sync(server); break; case GameEvent.EventType.MapEnd: - Manager.ResetKillstreaks(S); - await Manager.Sync(S); + Manager.ResetKillstreaks(server); + await Manager.Sync(server); break; case GameEvent.EventType.Command: - var shouldPersist = !string.IsNullOrEmpty(E.Data) && - E.Extra?.GetType().Name == "SayCommand"; + var shouldPersist = !string.IsNullOrEmpty(gameEvent.Data) && + gameEvent.Extra?.GetType().Name == "SayCommand"; if (shouldPersist) { - await Manager.AddMessageAsync(E.Origin.ClientId, StatManager.GetIdForServer(S), false, E.Data); + await Manager.AddMessageAsync(gameEvent.Origin.ClientId, StatManager.GetIdForServer(server), false, gameEvent.Data); } break; case GameEvent.EventType.ScriptKill: - string[] killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0]; - if ((S.CustomCallback || ShouldOverrideAnticheatSetting(S)) && killInfo.Length >= 18 && !ShouldIgnoreEvent(E.Origin, E.Target)) + var killInfo = (gameEvent.Data != null) ? gameEvent.Data.Split(';') : Array.Empty(); + if ((server.CustomCallback || ShouldOverrideAnticheatSetting(server)) && killInfo.Length >= 18 && !ShouldIgnoreEvent(gameEvent.Origin, gameEvent.Target)) { // this treats "world" damage as self damage - if (IsWorldDamage(E.Origin)) + if (IsWorldDamage(gameEvent.Origin)) { - E.Origin = E.Target; + gameEvent.Origin = gameEvent.Target; } - await EnsureClientsAdded(E.Origin, E.Target); - await Manager.AddScriptHit(false, E.Time, E.Origin, E.Target, StatManager.GetIdForServer(S), S.CurrentMap.Name, killInfo[7], killInfo[8], + await EnsureClientsAdded(gameEvent.Origin, gameEvent.Target); + await Manager.AddScriptHit(false, gameEvent.Time, gameEvent.Origin, gameEvent.Target, StatManager.GetIdForServer(server), server.CurrentMap.Name, killInfo[7], killInfo[8], killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15], killInfo[16], killInfo[17]); } @@ -112,42 +113,42 @@ namespace IW4MAdmin.Plugins.Stats } break; case GameEvent.EventType.Kill: - if (!ShouldIgnoreEvent(E.Origin, E.Target)) + if (!ShouldIgnoreEvent(gameEvent.Origin, gameEvent.Target)) { // this treats "world" damage as self damage - if (IsWorldDamage(E.Origin)) + if (IsWorldDamage(gameEvent.Origin)) { - E.Origin = E.Target; + gameEvent.Origin = gameEvent.Target; } - await EnsureClientsAdded(E.Origin, E.Target); - await Manager.AddStandardKill(E.Origin, E.Target); + await EnsureClientsAdded(gameEvent.Origin, gameEvent.Target); + await Manager.AddStandardKill(gameEvent.Origin, gameEvent.Target); } break; case GameEvent.EventType.Damage: - if (!ShouldIgnoreEvent(E.Origin, E.Target)) + if (!ShouldIgnoreEvent(gameEvent.Origin, gameEvent.Target)) { // this treats "world" damage as self damage - if (IsWorldDamage(E.Origin)) + if (IsWorldDamage(gameEvent.Origin)) { - E.Origin = E.Target; + gameEvent.Origin = gameEvent.Target; } - Manager.AddDamageEvent(E.Data, E.Origin.ClientId, E.Target.ClientId, StatManager.GetIdForServer(S)); + Manager.AddDamageEvent(gameEvent.Data, gameEvent.Origin.ClientId, gameEvent.Target.ClientId, StatManager.GetIdForServer(server)); } break; case GameEvent.EventType.ScriptDamage: - killInfo = (E.Data != null) ? E.Data.Split(';') : new string[0]; - if ((S.CustomCallback || ShouldOverrideAnticheatSetting(S)) && killInfo.Length >= 18 && !ShouldIgnoreEvent(E.Origin, E.Target)) + killInfo = (gameEvent.Data != null) ? gameEvent.Data.Split(';') : new string[0]; + if ((server.CustomCallback || ShouldOverrideAnticheatSetting(server)) && killInfo.Length >= 18 && !ShouldIgnoreEvent(gameEvent.Origin, gameEvent.Target)) { // this treats "world" damage as self damage - if (IsWorldDamage(E.Origin)) + if (IsWorldDamage(gameEvent.Origin)) { - E.Origin = E.Target; + gameEvent.Origin = gameEvent.Target; } - await EnsureClientsAdded(E.Origin, E.Target); - await Manager.AddScriptHit(true, E.Time, E.Origin, E.Target, StatManager.GetIdForServer(S), S.CurrentMap.Name, killInfo[7], killInfo[8], + await EnsureClientsAdded(gameEvent.Origin, gameEvent.Target); + await Manager.AddScriptHit(true, gameEvent.Time, gameEvent.Origin, gameEvent.Target, StatManager.GetIdForServer(server), server.CurrentMap.Name, killInfo[7], killInfo[8], killInfo[5], killInfo[6], killInfo[3], killInfo[4], killInfo[9], killInfo[10], killInfo[11], killInfo[12], killInfo[13], killInfo[14], killInfo[15], killInfo[16], killInfo[17]); } @@ -165,7 +166,7 @@ namespace IW4MAdmin.Plugins.Stats foreach (var calculator in _statCalculators) { - await calculator.CalculateForEvent(E); + await calculator.CalculateForEvent(gameEvent); } } @@ -188,23 +189,22 @@ namespace IW4MAdmin.Plugins.Stats "/Stats/TopPlayersAsync"); // meta data info - async Task> getStats(ClientPaginationRequest request) + async Task> GetStats(ClientPaginationRequest request, CancellationToken token = default) { - IList clientStats; await using var ctx = _databaseContextFactory.CreateContext(enableTracking: false); - clientStats = await ctx.Set().Where(c => c.ClientId == request.ClientId).ToListAsync(); + IList clientStats = await ctx.Set().Where(c => c.ClientId == request.ClientId).ToListAsync(token); - int kills = clientStats.Sum(c => c.Kills); - int deaths = clientStats.Sum(c => c.Deaths); - double kdr = Math.Round(kills / (double)deaths, 2); - var validPerformanceValues = clientStats.Where(c => c.Performance > 0); - int performancePlayTime = validPerformanceValues.Sum(s => s.TimePlayed); - double performance = Math.Round(validPerformanceValues.Sum(c => c.Performance * c.TimePlayed / performancePlayTime), 2); - double spm = Math.Round(clientStats.Sum(c => c.SPM) / clientStats.Where(c => c.SPM > 0).Count(), 1); + var kills = clientStats.Sum(c => c.Kills); + var deaths = clientStats.Sum(c => c.Deaths); + var kdr = Math.Round(kills / (double)deaths, 2); + var validPerformanceValues = clientStats.Where(c => c.Performance > 0).ToList(); + var performancePlayTime = validPerformanceValues.Sum(s => s.TimePlayed); + var performance = Math.Round(validPerformanceValues.Sum(c => c.Performance * c.TimePlayed / performancePlayTime), 2); + var spm = Math.Round(clientStats.Sum(c => c.SPM) / clientStats.Count(c => c.SPM > 0), 1); - return new List() + return new List { - new InformationResponse() + new InformationResponse { Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_RANKING"], Value = "#" + (await Manager.GetClientOverallRanking(request.ClientId)).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), @@ -212,7 +212,7 @@ namespace IW4MAdmin.Plugins.Stats Order = 0, Type = MetaType.Information }, - new InformationResponse() + new InformationResponse { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KILLS"], Value = kills.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), @@ -220,7 +220,7 @@ namespace IW4MAdmin.Plugins.Stats Order = 1, Type = MetaType.Information }, - new InformationResponse() + new InformationResponse { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_DEATHS"], Value = deaths.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), @@ -228,7 +228,7 @@ namespace IW4MAdmin.Plugins.Stats Order = 2, Type = MetaType.Information }, - new InformationResponse() + new InformationResponse { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KDR"], Value = kdr.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), @@ -236,7 +236,7 @@ namespace IW4MAdmin.Plugins.Stats Order = 3, Type = MetaType.Information }, - new InformationResponse() + new InformationResponse { Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_PERFORMANCE"], Value = performance.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), @@ -244,7 +244,7 @@ namespace IW4MAdmin.Plugins.Stats Order = 4, Type = MetaType.Information }, - new InformationResponse() + new InformationResponse { Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_META_SPM"], Value = spm.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)), @@ -255,15 +255,13 @@ namespace IW4MAdmin.Plugins.Stats }; } - async Task> getAnticheatInfo(ClientPaginationRequest request) + async Task> GetAnticheatInfo(ClientPaginationRequest request, CancellationToken token = default) { - IList clientStats; - - await using var ctx = _databaseContextFactory.CreateContext(enableTracking: false); - clientStats = await ctx.Set() + await using var context = _databaseContextFactory.CreateContext(enableTracking: false); + IList clientStats = await context.Set() .Include(c => c.HitLocations) .Where(c => c.ClientId == request.ClientId) - .ToListAsync(); + .ToListAsync(token); double headRatio = 0; double chestRatio = 0; @@ -271,9 +269,9 @@ namespace IW4MAdmin.Plugins.Stats double chestAbdomenRatio = 0; double hitOffsetAverage = 0; double averageSnapValue = 0; - double maxStrain = clientStats.Count(c => c.MaxStrain > 0) == 0 ? 0 : clientStats.Max(cs => cs.MaxStrain); + var maxStrain = clientStats.Any(c => c.MaxStrain > 0) ? 0 : clientStats.Max(cs => cs.MaxStrain); - if (clientStats.Where(cs => cs.HitLocations.Count > 0).FirstOrDefault() != null) + if (clientStats.Any(cs => cs.HitLocations.Count > 0)) { chestRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => c.HitLocations.First(hl => hl.Location == (int)IW4Info.HitLocation.torso_upper).HitCount) / @@ -291,12 +289,12 @@ namespace IW4MAdmin.Plugins.Stats (double)clientStats.Where(c => c.HitLocations.Count > 0) .Sum(c => c.HitLocations.Where(hl => hl.Location != (int)IW4Info.HitLocation.none).Sum(f => f.HitCount))) * 100.0, 0); - var validOffsets = clientStats.Where(c => c.HitLocations.Count(hl => hl.HitCount > 0) > 0).SelectMany(hl => hl.HitLocations); + var validOffsets = clientStats.Where(c => c.HitLocations.Count(hl => hl.HitCount > 0) > 0).SelectMany(hl => hl.HitLocations).ToList(); hitOffsetAverage = validOffsets.Sum(o => o.HitCount * o.HitOffsetAverage) / (double)validOffsets.Sum(o => o.HitCount); averageSnapValue = clientStats.Any(_stats => _stats.AverageSnapValue > 0) ? clientStats.Where(_stats => _stats.AverageSnapValue > 0).Average(_stat => _stat.AverageSnapValue) : 0; } - return new List() + return new List { new InformationResponse() { @@ -372,9 +370,9 @@ namespace IW4MAdmin.Plugins.Stats }; } - async Task> getMessages(ClientPaginationRequest request) + async Task> GetMessages(ClientPaginationRequest request, CancellationToken token = default) { - var query = new ChatSearchQuery() + var query = new ChatSearchQuery { ClientId = request.ClientId, Before = request.Before, @@ -388,49 +386,49 @@ namespace IW4MAdmin.Plugins.Stats if (Config.Configuration().AnticheatConfiguration.Enable) { - _metaService.AddRuntimeMeta(MetaType.Information, getAnticheatInfo); + _metaService.AddRuntimeMeta(MetaType.Information, GetAnticheatInfo); } - _metaService.AddRuntimeMeta(MetaType.Information, getStats); - _metaService.AddRuntimeMeta(MetaType.ChatMessage, getMessages); + _metaService.AddRuntimeMeta(MetaType.Information, GetStats); + _metaService.AddRuntimeMeta(MetaType.ChatMessage, GetMessages); - async Task totalKills(Server server) + async Task TotalKills(Server server) { await using var context = _databaseContextFactory.CreateContext(false); - long kills = await context.Set().Where(s => s.Active).SumAsync(s => s.TotalKills); + var kills = await context.Set().Where(s => s.Active).SumAsync(s => s.TotalKills); return kills.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)); } - async Task totalPlayTime(Server server) + async Task TotalPlayTime(Server server) { await using var context = _databaseContextFactory.CreateContext(false); - long playTime = await context.Set().Where(s => s.Active).SumAsync(s => s.TotalPlayTime); + var playTime = await context.Set().Where(s => s.Active).SumAsync(s => s.TotalPlayTime); return (playTime / 3600.0).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)); } - async Task topStats(Server s) + async Task TopStats(Server s) { // todo: this needs to needs to be updated when we DI the lookup return string.Join(Environment.NewLine, await Commands.TopStats.GetTopStats(s, Utilities.CurrentLocalization.LocalizationIndex)); } - async Task mostPlayed(Server s) + async Task MostPlayed(Server s) { // todo: this needs to needs to be updated when we DI the lookup return string.Join(Environment.NewLine, await Commands.MostPlayedCommand.GetMostPlayed(s, Utilities.CurrentLocalization.LocalizationIndex, _databaseContextFactory)); } - async Task mostKills(Server gameServer) + async Task MostKills(Server gameServer) { return string.Join(Environment.NewLine, await Commands.MostKillsCommand.GetMostKills(StatManager.GetIdForServer(gameServer), Config.Configuration(), _databaseContextFactory, _translationLookup)); } - manager.GetMessageTokens().Add(new MessageToken("TOTALKILLS", totalKills)); - manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYTIME", totalPlayTime)); - manager.GetMessageTokens().Add(new MessageToken("TOPSTATS", topStats)); - manager.GetMessageTokens().Add(new MessageToken("MOSTPLAYED", mostPlayed)); - manager.GetMessageTokens().Add(new MessageToken("MOSTKILLS", mostKills)); + manager.GetMessageTokens().Add(new MessageToken("TOTALKILLS", TotalKills)); + manager.GetMessageTokens().Add(new MessageToken("TOTALPLAYTIME", TotalPlayTime)); + manager.GetMessageTokens().Add(new MessageToken("TOPSTATS", TopStats)); + manager.GetMessageTokens().Add(new MessageToken("MOSTPLAYED", MostPlayed)); + manager.GetMessageTokens().Add(new MessageToken("MOSTKILLS", MostKills)); if (Config.Configuration().EnableAdvancedMetrics) { @@ -445,7 +443,7 @@ namespace IW4MAdmin.Plugins.Stats await _serverDistributionCalculator.Initialize(); } - public Task OnTickAsync(Server S) + public Task OnTickAsync(Server server) { return Task.CompletedTask; }