Ejemplo n.º 1
0
        public override async Task ExecuteAsync(GameEvent E)
        {
            var loc = Utilities.CurrentLocalization.LocalizationIndex;

            String             statLine;
            EFClientStatistics pStats;

            if (E.Data.Length > 0 && E.Target == null)
            {
                E.Target = E.Owner.GetClientByName(E.Data).FirstOrDefault();

                if (E.Target == null)
                {
                    E.Origin.Tell(loc["PLUGINS_STATS_COMMANDS_VIEW_FAIL"]);
                }
            }

            long serverId = await StatManager.GetIdForServer(E.Owner);

            using (var ctx = new DatabaseContext(disableTracking: true))
            {
                if (E.Target != null)
                {
                    int performanceRanking = await StatManager.GetClientOverallRanking(E.Target.ClientId);

                    string performanceRankingString = performanceRanking == 0 ? loc["WEBFRONT_STATS_INDEX_UNRANKED"] : $"{loc["WEBFRONT_STATS_INDEX_RANKED"]} #{performanceRanking}";

                    pStats   = (await ctx.Set <EFClientStatistics>().FirstAsync(c => c.ServerId == serverId && c.ClientId == E.Target.ClientId));
                    statLine = $"^5{pStats.Kills} ^7{loc["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{loc["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Performance} ^7{loc["PLUGINS_STATS_COMMANDS_PERFORMANCE"].ToUpper()} | {performanceRankingString}";
                }

                else
                {
                    int performanceRanking = await StatManager.GetClientOverallRanking(E.Origin.ClientId);

                    string performanceRankingString = performanceRanking == 0 ? loc["WEBFRONT_STATS_INDEX_UNRANKED"] : $"{loc["WEBFRONT_STATS_INDEX_RANKED"]} #{performanceRanking}";

                    pStats   = (await ctx.Set <EFClientStatistics>().FirstAsync((c => c.ServerId == serverId && c.ClientId == E.Origin.ClientId)));
                    statLine = $"^5{pStats.Kills} ^7{loc["PLUGINS_STATS_TEXT_KILLS"]} | ^5{pStats.Deaths} ^7{loc["PLUGINS_STATS_TEXT_DEATHS"]} | ^5{pStats.KDR} ^7KDR | ^5{pStats.Performance} ^7{loc["PLUGINS_STATS_COMMANDS_PERFORMANCE"].ToUpper()} | {performanceRankingString}";
                }
            }

            if (E.Message.IsBroadcastCommand())
            {
                string name = E.Target == null ? E.Origin.Name : E.Target.Name;
                E.Owner.Broadcast(loc["PLUGINS_STATS_COMMANDS_VIEW_SUCCESS"].FormatExt(name));
                E.Owner.Broadcast(statLine);
            }

            else
            {
                if (E.Target != null)
                {
                    E.Origin.Tell(loc["PLUGINS_STATS_COMMANDS_VIEW_SUCCESS"].FormatExt(E.Target.Name));
                }

                E.Origin.Tell(statLine);
            }
        }
Ejemplo n.º 2
0
        public async Task OnLoadAsync(IManager manager)
        {
            // load custom configuration
            Config = new BaseConfigurationHandler <StatsConfiguration>("StatsPluginSettings");
            if (Config.Configuration() == null)
            {
                Config.Set((StatsConfiguration) new StatsConfiguration().Generate());
                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 <List <ProfileMeta> > getStats(int clientId, int offset, int count, DateTime?startAt)
            {
                if (count > 1)
                {
                    return(new List <ProfileMeta>());
                }

                IList <EFClientStatistics> clientStats;

                using (var ctx = new DatabaseContext(disableTracking: true))
                {
                    clientStats = await ctx.Set <EFClientStatistics>().Where(c => c.ClientId == clientId).ToListAsync();
                }

                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 <ProfileMeta>()
                {
                    new ProfileMeta()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_RANKING"],
                        Value = "#" + (await StatManager.GetClientOverallRanking(clientId)).ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 0,
                        Type = ProfileMeta.MetaType.Information
                    },
                    new ProfileMeta()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KILLS"],
                        Value = kills.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 1,
                        Type = ProfileMeta.MetaType.Information
                    },
                    new ProfileMeta()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_DEATHS"],
                        Value = deaths.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 2,
                        Type = ProfileMeta.MetaType.Information
                    },
                    new ProfileMeta()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_TEXT_KDR"],
                        Value = kdr.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 3,
                        Type = ProfileMeta.MetaType.Information
                    },
                    new ProfileMeta()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_COMMANDS_PERFORMANCE"],
                        Value = performance.ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 4,
                        Type = ProfileMeta.MetaType.Information
                    },
                    new ProfileMeta()
                    {
                        Key = Utilities.CurrentLocalization.LocalizationIndex["PLUGINS_STATS_META_SPM"],
                        Value = spm.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Column = 0,
                        Order = 5,
                        Type = ProfileMeta.MetaType.Information
                    }
                });
            }

            async Task <List <ProfileMeta> > getAnticheatInfo(int clientId, int offset, int count, DateTime?startAt)
            {
                if (count > 1)
                {
                    return(new List <ProfileMeta>());
                }

                IList <EFClientStatistics> clientStats;

                using (var ctx = new DatabaseContext(disableTracking: true))
                {
                    clientStats = await ctx.Set <EFClientStatistics>()
                                  .Include(c => c.HitLocations)
                                  .Where(c => c.ClientId == clientId)
                                  .ToListAsync();
                }

                double headRatio         = 0;
                double chestRatio        = 0;
                double abdomenRatio      = 0;
                double chestAbdomenRatio = 0;
                double hitOffsetAverage  = 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 == IW4Info.HitLocation.torso_upper).HitCount) /
                                             (double)clientStats.Where(c => c.HitLocations.Count > 0)
                                             .Sum(c => c.HitLocations.Where(hl => hl.Location != 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 == IW4Info.HitLocation.torso_lower).HitCount) /
                                               (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(c => c.HitLocations.Where(hl => hl.Location != 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 == IW4Info.HitLocation.torso_upper).HitCount) /
                                                    (double)clientStats.Where(c => c.HitLocations.Count > 0).Sum(cs => cs.HitLocations.First(hl => hl.Location == 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 == IW4Info.HitLocation.head).HitCount) /
                                            (double)clientStats.Where(c => c.HitLocations.Count > 0)
                                            .Sum(c => c.HitLocations.Where(hl => hl.Location != 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);
                }

                return(new List <ProfileMeta>()
                {
                    new ProfileMeta()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 1",
                        Value = chestRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%',
                        Type = ProfileMeta.MetaType.Information,
                        Column = 2,
                        Order = 0,
                        Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM1"],
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 2",
                        Value = abdomenRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%',
                        Type = ProfileMeta.MetaType.Information,
                        Column = 2,
                        Order = 1,
                        Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM2"],
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 3",
                        Value = chestAbdomenRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%',
                        Type = ProfileMeta.MetaType.Information,
                        Column = 2,
                        Order = 2,
                        Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM3"],
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 4",
                        Value = headRatio.ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)) + '%',
                        Type = ProfileMeta.MetaType.Information,
                        Column = 2,
                        Order = 3,
                        Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM4"],
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        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 = ProfileMeta.MetaType.Information,
                        Column = 2,
                        Order = 4,
                        Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM5"],
                        Sensitive = true
                    },
                    new ProfileMeta()
                    {
                        Key = $"{Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_META_AC_METRIC"]} 6",
                        Value = Math.Round(maxStrain, 3).ToString(new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                        Type = ProfileMeta.MetaType.Information,
                        Column = 2,
                        Order = 5,
                        Extra = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_CLIENT_TITLE_ACM6"],
                        Sensitive = true
                    },
                });
            }

            async Task <List <ProfileMeta> > getMessages(int clientId, int offset, int count, DateTime?startAt)
            {
                if (count <= 1)
                {
                    using (var ctx = new DatabaseContext(true))
                    {
                        return(new List <ProfileMeta>
                        {
                            new ProfileMeta()
                            {
                                Key = Utilities.CurrentLocalization.LocalizationIndex["WEBFRONT_PROFILE_MESSAGES"],
                                Value = (await ctx.Set <EFClientMessage>()
                                         .CountAsync(_message => _message.ClientId == clientId))
                                        .ToString("#,##0", new System.Globalization.CultureInfo(Utilities.CurrentLocalization.LocalizationName)),
                                Column = 1,
                                Order = 4,
                                Type = ProfileMeta.MetaType.Information
                            }
                        });
                    }
                }

                List <ProfileMeta> messageMeta;

                using (var ctx = new DatabaseContext(disableTracking: true))
                {
                    var messages = ctx.Set <EFClientMessage>()
                                   .Where(m => m.ClientId == clientId)
                                   .Where(_message => _message.TimeSent < startAt)
                                   .OrderByDescending(_message => _message.TimeSent)
                                   .Skip(offset)
                                   .Take(count);

                    messageMeta = await messages.Select(m => new ProfileMeta()
                    {
                        Key   = null,
                        Value = new { m.Message, m.Server.GameName },
                        When  = m.TimeSent,
                        Extra = m.ServerId.ToString(),
                        Type  = ProfileMeta.MetaType.ChatMessage
                    }).ToListAsync();

                    foreach (var message in messageMeta)
                    {
                        if ((message.Value.Message as string).IsQuickMessage())
                        {
                            try
                            {
                                var quickMessages = ServerManager.GetApplicationSettings().Configuration()
                                                    .QuickMessages
                                                    .First(_qm => _qm.Game == message.Value.GameName);
                                message.Value = quickMessages.Messages[(message.Value.Message as string).Substring(1)];
                                message.Type  = ProfileMeta.MetaType.QuickMessage;
                            }
                            catch
                            {
                                message.Value = message.Value.Message;
                            }
                        }

                        else
                        {
                            message.Value = message.Value.Message;
                        }
                    }
                }

                return(messageMeta);
            }

            if (Config.Configuration().EnableAntiCheat)
            {
                MetaService.AddRuntimeMeta(getAnticheatInfo);
            }

            MetaService.AddRuntimeMeta(getStats);
            MetaService.AddRuntimeMeta(getMessages);

            async Task <string> totalKills(Server server)
            {
                using (var ctx = new DatabaseContext(disableTracking: true))
                {
                    long kills = await ctx.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)
            {
                using (var ctx = new DatabaseContext(disableTracking: true))
                {
                    long playTime = await ctx.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)
            {
                return(string.Join(Environment.NewLine, await Commands.TopStats.GetTopStats(s)));
            }

            async Task <string> mostPlayed(Server s)
            {
                return(string.Join(Environment.NewLine, await Commands.MostPlayed.GetMostPlayed(s)));
            }

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

            ServerManager = manager;
            Manager       = new StatManager(manager);
        }