Esempio n. 1
0
        private eventResult GenerateEvent(int queueId, List <string> versions, string title, string filename)
        {
            Console.WriteLine($"Generating stats at {DateTime.Now}...");
            var result = new eventResult();

            result.Versions = versions;

            var matches = DataStore.ReadMatchesByRegVerQue(f => f.queueId == queueId && versions.Contains(f.version))
                          .Select(m => matchFromJson(m.json, m.region))
                          .Where(m => m != null);

            int matchCount = 0;
            var champWins  = new AutoDictionary <int, int>();
            var champSeens = new AutoDictionary <int, int>();
            var bans       = new AutoDictionary <int, winrateStat>(ch => new winrateStat());

            foreach (var match in matches)
            {
                matchCount++;
                // Champ winrates
                foreach (var champ in match.WinChamps)
                {
                    if (!match.LoseChamps.Contains(champ))
                    {
                        champSeens.IncSafe(champ);
                        champWins.IncSafe(champ);
                    }
                }
                foreach (var champ in match.LoseChamps)
                {
                    if (!match.WinChamps.Contains(champ))
                    {
                        champSeens.IncSafe(champ);
                    }
                }

                // Bans: winrate for games where champ wasn't banned, and our team didn't pick it
                foreach (var champ in LeagueStaticData.Champions.Keys)
                {
                    if (!match.BannedChamps.Contains(champ))
                    {
                        if (!match.WinChamps.Contains(champ))
                        {
                            bans[champ].Total++;
                            bans[champ].Wins++;
                        }
                        if (!match.LoseChamps.Contains(champ))
                        {
                            bans[champ].Total++;
                        }
                    }
                }
            }
            var html = new List <object>();

            html.Add(new H1(title));
            html.Add(new H2("Champion Winrates"));
            html.Add(new P($"Last updated: {DateTime.UtcNow:d' 'MMM' 'yyyy' at 'HH:mm' UTC'}"));
            html.Add(new P($"Based on {matchCount:#,0} total matches. Game version(s) {versions.JoinString(", ")} in queue {queueId}."));
            html.Add(new P(new RawTag("&nbsp;")));
            html.Add(new P("Note: win rate is an unreliable measure when the number of matches is low. To correctly account for this, sort by the p95 columns."));
            html.Add(new P("One column is optimal for finding the best champions, the other is optimal for finding the worst ones."));
            html.Add(new P(new RawTag("&nbsp;")));
            var bestworst = new List <(int champ, double p95best, double p95worst, double winrate)>();

            html.Add(makeSortableTable(
                         new TR(colAsc("Champion"), colDesc("Matches"), colDesc("Winrate"), colDesc("Best (p95 lower)", true), colAsc("Worst (p95 upper)")),
                         LeagueStaticData.Champions.Values.Where(c => champSeens[c.Id] > 0).Select(c =>
            {
                var winrate = champWins[c.Id] / (double)champSeens[c.Id];
                var p95     = Utils.WilsonConfidenceInterval(winrate, champSeens[c.Id], 1.96);
                bestworst.Add((c.Id, p95.lower, p95.upper, winrate));
                return(new TR(cellStr(c.Name), cellInt(champSeens[c.Id]), cellPrc(winrate, 1), cellPrc(p95.lower, 1), cellPrc(p95.upper, 1)));
            })));
            result.LinkWinrates = $"{filename}-winrates.html";
            GenerateHtmlToFile(Path.Combine(_settings.OutputPath, result.LinkWinrates), html, true);
            if (bestworst.Count > 0)
            {
                var bestchamp  = bestworst.MaxElement(x => x.p95best);
                var worstchamp = bestworst.MinElement(x => x.p95worst);
                result.BestChamp         = bestchamp.champ;
                result.BestChampWinrate  = bestchamp.winrate;
                result.WorstChamp        = worstchamp.champ;
                result.WorstChampWinrate = worstchamp.winrate;
            }

            html = new List <object>();
            html.Add(new H1(title));
            html.Add(new H2("Best Bans"));
            html.Add(new P($"Last updated: {DateTime.UtcNow:d' 'MMM' 'yyyy' at 'HH:mm' UTC'}"));
            html.Add(new P($"Based on {matchCount:#,0} total matches. Game version(s) {versions.JoinString(", ")} in queue {queueId}."));
            html.Add(new P(new RawTag("&nbsp;")));
            html.Add(makeSortableTable(
                         new TR(colAsc("Champion"), colDesc("Matchups evaluated"), colDesc("Δwinrate if banned"), colDesc("Best bans (p95 Δwr lower)", true), colAsc("Worst bans (p95 Δwr upper)")),
                         LeagueStaticData.Champions.Values.Select(c =>
            {
                var p95 = Utils.WilsonConfidenceInterval(bans[c.Id].Winrate, bans[c.Id].Total, 1.96);
                return(new TR(cellStr(c.Name), cellInt(bans[c.Id].Total), cellPrcDelta(0.5 - bans[c.Id].Winrate, 2), cellPrcDelta(0.5 - p95.upper, 2), cellPrcDelta(0.5 - p95.lower, 2)));
            })));
            result.LinkBans = $"{filename}-bans.html";
            GenerateHtmlToFile(Path.Combine(_settings.OutputPath, result.LinkBans), html, true);

            result.MatchCount = matchCount;
            return(result);
        }