示例#1
0
 public void Register()
 {
     _metaService.AddRuntimeMeta <ClientPaginationRequest, InformationResponse>(MetaType.Information, GetProfileMeta);
     _metaService.AddRuntimeMeta <ClientPaginationRequest, ReceivedPenaltyResponse>(MetaType.ReceivedPenalty, GetReceivedPenaltiesMeta);
     _metaService.AddRuntimeMeta <ClientPaginationRequest, AdministeredPenaltyResponse>(MetaType.Penalized, GetAdministeredPenaltiesMeta);
     _metaService.AddRuntimeMeta <ClientPaginationRequest, UpdatedAliasResponse>(MetaType.AliasUpdate, GetUpdatedAliasMeta);
 }
示例#2
0
        public async Task OnLoadAsync(IManager manager)
        {
            // load custom configuration
            if (Config.Configuration() == null)
            {
                Config.Set((StatsConfiguration) new StatsConfiguration().Generate());
            }
            Config.Configuration().ApplyMigration();
            await Config.Save();

            // register the topstats page
            // todo:generate the URL/Location instead of hardcoding
            manager.GetPageList()
            .Pages.Add(
                Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_TOP_TEXT"],
                "/Stats/TopPlayersAsync");

            // meta data info
            async Task <IEnumerable <InformationResponse> > getStats(ClientPaginationRequest request)
            {
                IList <EFClientStatistics> clientStats;
                int messageCount = 0;

                await using var ctx = _databaseContextFactory.CreateContext(enableTracking: false);
                clientStats         = await ctx.Set <EFClientStatistics>().Where(c => c.ClientId == request.ClientId).ToListAsync();

                messageCount = await ctx.Set <EFClientMessage>().CountAsync(_message => _message.ClientId == request.ClientId);

                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);

                return(new List <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)),
                        Column = 0,
                        Order = 0,
                        Type = MetaType.Information
                    },
                    new InformationResponse()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KILLS"],
                        Value = kills.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 1,
                        Type = MetaType.Information
                    },
                    new InformationResponse()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_DEATHS"],
                        Value = deaths.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 2,
                        Type = MetaType.Information
                    },
                    new InformationResponse()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KDR"],
                        Value = kdr.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 3,
                        Type = MetaType.Information
                    },
                    new InformationResponse()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_PERFORMANCE"],
                        Value = performance.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 4,
                        Type = MetaType.Information
                    },
                    new InformationResponse()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_META_SPM"],
                        Value = spm.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 5,
                        Type = MetaType.Information
                    },
                    new InformationResponse()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_MESSAGES"],
                        Value = messageCount.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 1,
                        Order = 4,
                        Type = MetaType.Information
                    }
                });
            }

            async Task <IEnumerable <InformationResponse> > getAnticheatInfo(ClientPaginationRequest request)
            {
                IList <EFClientStatistics> clientStats;

                await using var ctx = _databaseContextFactory.CreateContext(enableTracking: false);
                clientStats         = await ctx.Set <EFClientStatistics>()
                                      .Include(c => c.HitLocations)
                                      .Where(c => c.ClientId == request.ClientId)
                                      .ToListAsync();

                double headRatio         = 0;
                double chestRatio        = 0;
                double abdomenRatio      = 0;
                double chestAbdomenRatio = 0;
                double hitOffsetAverage  = 0;
                double averageSnapValue  = 0;
                double maxStrain         = clientStats.Count(c => c.MaxStrain > 0) == 0 ? 0 : clientStats.Max(cs => cs.MaxStrain);

                if (clientStats.Where(cs => cs.HitLocations.Count > 0).FirstOrDefault() != null)
                {
                    chestRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(c =>
                                                                                                  c.HitLocations.First(hl => hl.Location == (int)IW4Info.HitLocation.torso_upper).HitCount) /
                                             (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);

                    abdomenRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(c =>
                                                                                                    c.HitLocations.First(hl => hl.Location == (int)IW4Info.HitLocation.torso_lower).HitCount) /
                                               (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);

                    chestAbdomenRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == (int)IW4Info.HitLocation.torso_upper).HitCount) /
                                                    (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == (int)IW4Info.HitLocation.torso_lower).HitCount)) * 100.0, 0);

                    headRatio = Math.Round((clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == (int)IW4Info.HitLocation.head).HitCount) /
                                            (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);
                    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 <InformationResponse>()
                {
                    new InformationResponse()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 1",
                        Value = chestRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%',
                        Type = MetaType.Information,
                        Column = 2,
                        Order = 0,
                        ToolTipText = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM1"],
                        IsSensitive = true
                    },
                    new InformationResponse()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 2",
                        Value = abdomenRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%',
                        Type = MetaType.Information,
                        Column = 2,
                        Order = 1,
                        ToolTipText = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM2"],
                        IsSensitive = true
                    },
                    new InformationResponse()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 3",
                        Value = chestAbdomenRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%',
                        Type = MetaType.Information,
                        Column = 2,
                        Order = 2,
                        ToolTipText = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM3"],
                        IsSensitive = true
                    },
                    new InformationResponse()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 4",
                        Value = headRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%',
                        Type = MetaType.Information,
                        Column = 2,
                        Order = 3,
                        ToolTipText = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM4"],
                        IsSensitive = true
                    },
                    new InformationResponse()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 5",
                        // todo: make sure this is wrapped somewhere else
                        Value = $"{Math.Round(((float)hitOffsetAverage), 4).ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName))}°",
                        Type = MetaType.Information,
                        Column = 2,
                        Order = 4,
                        ToolTipText = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM5"],
                        IsSensitive = true
                    },
                    new InformationResponse()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 6",
                        Value = Math.Round(maxStrain, 3).ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Type = MetaType.Information,
                        Column = 2,
                        Order = 5,
                        ToolTipText = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM6"],
                        IsSensitive = true
                    },
                    new InformationResponse()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 7",
                        Value = Math.Round(averageSnapValue, 3).ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Type = MetaType.Information,
                        Column = 2,
                        Order = 6,
                        ToolTipText = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM7"],
                        IsSensitive = true
                    }
                });
            }

            async Task <IEnumerable <MessageResponse> > getMessages(ClientPaginationRequest request)
            {
                var query = new ChatSearchQuery()
                {
                    ClientId      = request.ClientId,
                    Before        = request.Before,
                    SentBefore    = request.Before ?? DateTime.UtcNow,
                    Count         = request.Count,
                    IsProfileMeta = true
                };

                return((await _chatQueryHelper.QueryResource(query)).Results);
            }

            if (Config.Configuration().AnticheatConfiguration.Enable)
            {
                _metaService.AddRuntimeMeta <ClientPaginationRequest, InformationResponse>(MetaType.Information, getAnticheatInfo);
            }

            _metaService.AddRuntimeMeta <ClientPaginationRequest, InformationResponse>(MetaType.Information, getStats);
            _metaService.AddRuntimeMeta <ClientPaginationRequest, MessageResponse>(MetaType.ChatMessage, getMessages);

            async Task <string> totalKills(Server server)
            {
                await using var context = _databaseContextFactory.CreateContext(false);
                long kills = await context.Set <EFServerStatistics>().Where(s => s.Active).SumAsync(s => s.TotalKills);

                return(kills.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)));
            }

            async Task <string> totalPlayTime(Server server)
            {
                await using var context = _databaseContextFactory.CreateContext(false);
                long playTime = await context.Set <EFServerStatistics>().Where(s => s.Active).SumAsync(s => s.TotalPlayTime);

                return((playTime / 3600.0).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)));
            }

            async Task <string> 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 <string> 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 <string> 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));

            if (Config.Configuration().EnableAdvancedMetrics)
            {
                foreach (var calculator in _statCalculators)
                {
                    await calculator.GatherDependencies();
                }
            }

            ServerManager = manager;
            Manager       = new StatManager(_managerLogger, manager, _databaseContextFactory, Config, _serverDistributionCalculator);
            await _serverDistributionCalculator.Initialize();
        }