示例#1
0
        public async Task <IActionResult> FindMessage([FromQuery] string query)
        {
            ViewBag.Localization     = _translationLookup;
            ViewBag.EnableColorCodes = _manager.GetApplicationSettings().Configuration().EnableColorCodes;
            ViewBag.Query            = query;
            ViewBag.QueryLimit       = 100;
            ViewBag.Title            = _translationLookup["WEBFRONT_STATS_MESSAGES_TITLE"];
            ViewBag.Error            = null;
            ViewBag.IsFluid          = true;
            ChatSearchQuery searchRequest = null;

            try
            {
                searchRequest = query.ParseSearchInfo(int.MaxValue, 0);
            }

            catch (ArgumentException e)
            {
                _logger.LogWarning(e, "Could not parse chat message search query {query}", query);
                ViewBag.Error = e;
            }

            catch (FormatException e)
            {
                _logger.LogWarning(e, "Could not parse chat message search query filter format {query}", query);
                ViewBag.Error = e;
            }

            var result = searchRequest != null ? await _chatResourceQueryHelper.QueryResource(searchRequest) : null;

            return(View("~/Views/Client/Message/Find.cshtml", result));
        }
示例#2
0
        /// <summary>
        ///  todo: lets abstract this out to a generic buildable query
        ///  this is just a dirty PoC
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        public static ChatSearchQuery ParseSearchInfo(this string query, int count, int offset)
        {
            string[] filters       = query.Split('|');
            var      searchRequest = new ChatSearchQuery
            {
                Filter = query,
                Count  = count,
                Offset = offset
            };

            // sanity checks
            searchRequest.Count  = Math.Min(searchRequest.Count, MaxMessages);
            searchRequest.Count  = Math.Max(searchRequest.Count, 0);
            searchRequest.Offset = Math.Max(searchRequest.Offset, 0);

            if (filters.Length > 1)
            {
                if (filters[0].ToLower() != "chat")
                {
                    throw new ArgumentException("Query is not compatible with chat");
                }

                foreach (string filter in filters.Skip(1))
                {
                    string[] args = filter.Split(' ');

                    if (args.Length > 1)
                    {
                        string recombinedArgs = string.Join(' ', args.Skip(1));
                        switch (args[0].ToLower())
                        {
                        case "before":
                            searchRequest.SentBefore = DateTime.Parse(recombinedArgs);
                            break;

                        case "after":
                            searchRequest.SentAfter = DateTime.Parse(recombinedArgs);
                            break;

                        case "server":
                            searchRequest.ServerId = args[1];
                            break;

                        case "client":
                            searchRequest.ClientId = int.Parse(args[1]);
                            break;

                        case "contains":
                            searchRequest.MessageContains = string.Join(' ', args.Skip(1));
                            break;

                        case "sort":
                            searchRequest.Direction = Enum.Parse <SortDirection>(args[1], ignoreCase: true);
                            break;
                        }
                    }
                }

                return(searchRequest);
            }

            throw new ArgumentException("No filters specified for chat search");
        }
示例#3
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();
        }