public async Task <BeforeMatchResponse> BeforeMatch(BeforeMatchRequest request) { var realSteamIds = request.Players.Select(ulong.Parse).ToList(); var responses = await _context.Players.Where(p => realSteamIds.Contains(p.SteamId)) .Select(p => new { SteamId = p.SteamId.ToString(), Patreon = new BeforeMatchResponse.Patreon() { Level = p.PatreonLevel, EmblemEnabled = p.PatreonEmblemEnabled.GetValueOrDefault(true), EmblemColor = p.PatreonEmblemColor ?? "White", BootsEnabled = p.PatreonBootsEnabled.GetValueOrDefault(true), }, MatchesOnMap = p.Matches .Where(m => m.Match.MapName == request.MapName) .OrderByDescending(m => m.MatchId) .Select(m => new { IsWinner = m.Team == m.Match.Winner, m.Kills, m.Deaths, m.Assists }) .ToList(), SmartRandomHeroesMap = p.Matches .Where(m => m.Match.MapName == request.MapName) .Where(m => m.PickReason == "pick") .OrderByDescending(m => m.MatchId) .Take(100) .GroupBy(m => m.Hero) .Where(g => g.Count() >= (int)Math.Ceiling(p.Matches.Count() / 20.0)) .Select(g => g.Key) .ToList(), SmartRandomHeroesGlobal = p.Matches .Where(m => m.PickReason == "pick") .OrderByDescending(m => m.MatchId) .Take(100) .GroupBy(m => m.Hero) .Where(g => g.Count() >= (int)Math.Ceiling(p.Matches.Count() / 20.0)) .Select(g => g.Key) .ToList(), LastSmartRandomUse = p.Matches .Where(m => m.PickReason == "smart-random") .OrderByDescending(m => m.Match.EndedAt) .Take(1) .Select(m => m.Match.EndedAt) .FirstOrDefault() }) .ToListAsync(); return(new BeforeMatchResponse() { Players = request.Players .Select(id => { var response = responses.FirstOrDefault(p => p.SteamId == id); if (response == null) { return new BeforeMatchResponse.Player() { SteamId = id.ToString(), Patreon = new BeforeMatchResponse.Patreon() { Level = 0, EmblemEnabled = true, EmblemColor = "White", BootsEnabled = true, }, SmartRandomHeroesError = "no_stats", }; } var player = new BeforeMatchResponse.Player { SteamId = id.ToString(), // TODO: Remove it PatreonLevel = response.Patreon.Level, Patreon = response.Patreon, Streak = response.MatchesOnMap.TakeWhile(w => w.IsWinner).Count(), BestStreak = response.MatchesOnMap.LongestStreak(w => w.IsWinner), AverageKills = response.MatchesOnMap.Select(x => (double)x.Kills) .DefaultIfEmpty() .Average(), AverageDeaths = response.MatchesOnMap.Select(x => (double)x.Deaths) .DefaultIfEmpty() .Average(), AverageAssists = response.MatchesOnMap.Select(x => (double)x.Assists).DefaultIfEmpty().Average(), Wins = response.MatchesOnMap.Count(w => w.IsWinner), Loses = response.MatchesOnMap.Count(w => !w.IsWinner), }; var canUseSmartRandom = response.Patreon.Level >= 1 || (DateTime.UtcNow - response.LastSmartRandomUse).TotalDays >= 1; if (canUseSmartRandom) { var heroes = response.SmartRandomHeroesMap.Count >= 5 ? response.SmartRandomHeroesMap : response.SmartRandomHeroesGlobal; if (heroes.Count >= 3) { player.SmartRandomHeroes = heroes; } else { player.SmartRandomHeroesError = "no_stats"; } } else { player.SmartRandomHeroesError = "cooldown"; } return player; }) .ToList() }); }
public async Task <BeforeMatchResponse> Before(BeforeMatchRequest request) { var customGame = request.CustomGame.Value; var mapName = request.MapName; var realSteamIds = request.Players.Select(ulong.Parse).ToList(); var responses = await _context.Players .Where(p => realSteamIds.Contains(p.SteamId)) .Select(p => new { SteamId = p.SteamId.ToString(), Patreon = new BeforeMatchResponse.Patreon() { EndDate = p.PatreonEndDate, Level = p.PatreonLevel, EmblemEnabled = p.PatreonEmblemEnabled ?? true, EmblemColor = p.PatreonEmblemColor ?? "White", BootsEnabled = p.PatreonBootsEnabled ?? true, ChatWheelFavorites = p.PatreonChatWheelFavorites ?? new List <int>(), Cosmetics = p.PatreonCosmetics, }, Matches = p.Matches .Where(m => m.Match.CustomGame == customGame) .OrderByDescending(m => m.MatchId) .Select(mp => new { mp.Kills, mp.Deaths, mp.Assists, mp.Match.MapName, mp.PickReason, mp.Hero, IsWinner = mp.Team == mp.Match.Winner, }) .ToList(), }) .ToListAsync(); return(new BeforeMatchResponse() { Players = request.Players .Select(id => { var response = responses.FirstOrDefault(p => p.SteamId == id); if (response == null) { return new BeforeMatchResponse.Player() { SteamId = id.ToString(), Patreon = new BeforeMatchResponse.Patreon() { Level = 0, EmblemEnabled = true, EmblemColor = "White", BootsEnabled = true, ChatWheelFavorites = new List <int>(), }, SmartRandomHeroesError = "no_stats", }; } if (response.Patreon.EndDate < DateTime.UtcNow) { response.Patreon.Level = 0; } var matchesOnMap = response.Matches.Where(m => m.MapName == mapName).ToList(); var player = new BeforeMatchResponse.Player { SteamId = id.ToString(), Patreon = response.Patreon, Streak = matchesOnMap.TakeWhile(w => w.IsWinner).Count(), BestStreak = matchesOnMap.LongestStreak(w => w.IsWinner), AverageKills = matchesOnMap .Select(x => (double)x.Kills) .DefaultIfEmpty() .Average(), AverageDeaths = matchesOnMap .Select(x => (double)x.Deaths) .DefaultIfEmpty() .Average(), AverageAssists = matchesOnMap .Select(x => (double)x.Assists) .DefaultIfEmpty() .Average(), Wins = matchesOnMap.Count(w => w.IsWinner), Loses = matchesOnMap.Count(w => !w.IsWinner), }; List <string> GetSmartRandomHeroes(bool onMap) { var matches = (onMap ? matchesOnMap : response.Matches).Where(m => m.PickReason == "pick"); return matches .Take(100) .GroupBy(m => m.Hero) .Where(g => g.Count() >= (int)Math.Ceiling(Math.Min(matches.Count(), 100) / 20.0)) .Select(g => g.Key) .ToList(); }; var smartRandomHeroesMap = GetSmartRandomHeroes(true); var smartRandomHeroesGlobal = GetSmartRandomHeroes(false); var heroes = smartRandomHeroesMap.Count >= 5 ? smartRandomHeroesMap : smartRandomHeroesGlobal; if (heroes.Count >= 3) { player.SmartRandomHeroes = heroes; } else { player.SmartRandomHeroesError = "no_stats"; } return player; }) .ToList() });