コード例 #1
0
        public async Task <IActionResult> GetMessageAsync(string serverId, long when)
        {
            var whenTime  = DateTime.FromFileTimeUtc(when);
            var whenUpper = whenTime.AddMinutes(5);
            var whenLower = whenTime.AddMinutes(-5);

            var messages = await _chatResourceQueryHelper.QueryResource(new ChatSearchQuery()
            {
                ServerId   = serverId,
                SentBefore = whenUpper,
                SentAfter  = whenLower
            });

            return(View("~/Views/Client/_MessageContext.cshtml", messages.Results.ToList()));
        }
コード例 #2
0
ファイル: ClientController.cs プロジェクト: weeder/IW4M-Admin
        public async Task <IActionResult> FindAsync([FromQuery] FindClientRequest request)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(new ErrorResponse()
                {
                    Messages = ModelState.Values.SelectMany(_value => _value.Errors.Select(_error => _error.ErrorMessage)).ToArray()
                }));
            }

            try
            {
                var results = await _clientQueryHelper.QueryResource(request);

                return(Ok(new FindClientResponse
                {
                    TotalFoundClients = results.TotalResultCount,
                    Clients = results.Results
                }));
            }

            catch (Exception e)
            {
                _logger.WriteWarning($"Failed to retrieve clients with query - {request.ToDebugString()}");
                _logger.WriteDebug(e.GetExceptionInfo());

                return(StatusCode(StatusCodes.Status500InternalServerError, new ErrorResponse()
                {
                    Messages = new[] { e.Message }
                }));
            }
        }
コード例 #3
0
        public async Task Test_StatsController_ClientStats_Happy()
        {
            var client = ClientGenerators.CreateBasicClient(null);

            var query = new StatsInfoRequest
            {
                ClientId = client.ClientId
            };

            var queryResult = new ResourceQueryHelperResult <StatsInfoResult>()
            {
                Results = new[]
                {
                    new StatsInfoResult
                    {
                        Deaths             = 1,
                        Kills              = 1,
                        LastPlayed         = DateTime.Now,
                        Performance        = 100,
                        Ranking            = 10,
                        ScorePerMinute     = 500,
                        ServerGame         = "IW4",
                        ServerId           = 123,
                        ServerName         = "IW4Host",
                        TotalSecondsPlayed = 100
                    }
                },
                TotalResultCount     = 1,
                RetrievedResultCount = 1
            };

            A.CallTo(() => fakeStatsQueryHelper.QueryResource(A <StatsInfoRequest> .Ignored))
            .Returns(Task.FromResult(queryResult));

            var result = await statsController.ClientStats(query.ClientId.Value);

            Assert.IsInstanceOf <OkObjectResult>(result);

            var viewResult = (result as OkObjectResult).Value as IEnumerable <StatsInfoResult>;

            Assert.NotNull(viewResult);
            Assert.AreEqual(queryResult.Results, viewResult);
        }
コード例 #4
0
        public async Task <IActionResult> Advanced(int id, [FromQuery] string serverId)
        {
            ViewBag.Config = _defaultConfig.GameStrings;
            var hitInfo = await _queryHelper.QueryResource(new StatsInfoRequest
            {
                ClientId       = id,
                ServerEndpoint = serverId
            });

            return(View("~/Views/Client/Statistics/Advanced.cshtml", hitInfo.Results.First()));
        }
コード例 #5
0
ファイル: StatsController.cs プロジェクト: weeder/IW4M-Admin
        public async Task <IActionResult> ClientStats(int clientId)
        {
            if (clientId < 1 || !ModelState.IsValid)
            {
                return(BadRequest(new ErrorResponse
                {
                    Messages = new[] { $"Client Id must be between 1 and {int.MaxValue}" }
                }));
            }

            var request = new StatsInfoRequest()
            {
                ClientId = clientId
            };

            try
            {
                var result = await _statsQueryHelper.QueryResource(request);

                if (result.RetrievedResultCount == 0)
                {
                    return(NotFound());
                }

                return(Ok(result.Results));
            }

            catch (Exception e)
            {
                _logger.WriteWarning($"Could not get client stats for client id {clientId}");
                _logger.WriteDebug(e.GetExceptionInfo());

                return(StatusCode(StatusCodes.Status500InternalServerError, new ErrorResponse
                {
                    Messages = new[] { e.Message }
                }));
            }
        }
コード例 #6
0
        private async Task <IEnumerable <ConnectionHistoryResponse> > GetConnectionHistoryMeta(ClientPaginationRequest request)
        {
            var connections = await _connectionHistoryHelper.QueryResource(request);

            return(connections.Results);
        }
コード例 #7
0
        private async Task <IEnumerable <UpdatedAliasResponse> > GetUpdatedAliasMeta(ClientPaginationRequest request)
        {
            var aliases = await _updatedAliasHelper.QueryResource(request);

            return(aliases.Results);
        }
コード例 #8
0
        private async Task <IEnumerable <AdministeredPenaltyResponse> > GetAdministeredPenaltiesMeta(ClientPaginationRequest request)
        {
            var penalties = await _administeredPenaltyHelper.QueryResource(request);

            return(penalties.Results);
        }
コード例 #9
0
ファイル: Plugin.cs プロジェクト: xerxes-at/IW4M-Admin
        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();
        }