public void Update(MatchInfoEntry infoEntry, DatabaseContext databaseContext) { const int maxServersCount = 50; foreach (var entry in databaseContext.ChangeTracker.Entries <MatchInfoEntry>()) { entry.State = EntityState.Unchanged; } var recentMatches = databaseContext.RecentMatches.OrderByDescending(x => x.Timestamp).ToList(); if (recentMatches.Count < maxServersCount) { databaseContext.RecentMatches.Add( new RecentMatchEntry { Key = infoEntry.Key, Server = infoEntry.Endpoint, Timestamp = infoEntry.Timestamp, }); } else if (recentMatches[recentMatches.Count - 1].Timestamp < infoEntry.Timestamp) { databaseContext.RecentMatches.Remove(recentMatches[recentMatches.Count - 1]); databaseContext.RecentMatches.Add( new RecentMatchEntry { Key = infoEntry.Key, Server = infoEntry.Endpoint, Timestamp = infoEntry.Timestamp, }); } }
public async Task PutMatchInfo(string endpoint, DateTime timestamp, MatchInfoEntry infoEntry) { await Task.Run(() => { var serverEntry = databaseContext.Servers.Find(endpoint); if (serverEntry == null) { throw new BadRequestException("Bad Request"); } var key = endpoint + timestamp.ToString(CultureInfo.InvariantCulture); if (databaseContext.Matches.Find(key) != null) { throw new BadRequestException("Bad Request"); } infoEntry.Key = key; infoEntry.Endpoint = endpoint; infoEntry.Timestamp = timestamp; lock (databaseContext) { databaseContext.Matches.Add(infoEntry); databaseContext.SaveChanges(); statisticsUpdater.Update(infoEntry, databaseContext); databaseContext.SaveChanges(); } }); }
public async Task PutMatchInfo_DoesNot_ResavesInfo() { var endpoint = "PutServerInfo_SavesInfo"; var timeStamp = DateTime.UtcNow.Date - TimeSpan.FromDays(3); var matchData = new MatchInfoEntry { Map = "NewMap", GameMode = "TDM", FragLimit = 200, TimeLimit = 200, TimeElapsed = 152.9, Scoreboard = new List <ScoreEntry> { new ScoreEntry { Name = "Player2", Frags = 20, Kills = 21, Deaths = 3 }, new ScoreEntry { Name = "Player1", Frags = 2, Kills = 2, Deaths = 21 } } }; try { await statistics.PutMatchInfo(endpoint, timeStamp, matchData); } catch (Exception e) { Assert.IsTrue(e is BadRequestException); } }
public void Update(MatchInfoEntry infoEntry, DatabaseContext databaseContext) { foreach (var statisticsUpdater in updaters) { statisticsUpdater.Update(infoEntry, databaseContext); } }
public MatchInfo(MatchInfoEntry entry) { Map = entry.Map; GameMode = entry.GameMode; FragLimit = entry.FragLimit; TimeLimit = entry.TimeLimit; TimeElapsed = entry.TimeElapsed; Scoreboard = entry.Scoreboard.Select(x => new Score(x)).ToList(); }
public void Update(MatchInfoEntry infoEntry, DatabaseContext databaseContext) { var previous = databaseContext.ServerStatistics.Find(infoEntry.Endpoint); if (previous == null) { SetFirstEntry(infoEntry, databaseContext); } else { UpdateEntry(previous, infoEntry); } }
private void SetFirstEntry(MatchInfoEntry infoEntry, DatabaseContext databaseContext) { databaseContext.ServerStatistics.Add(new ServerStatisticsEntry { Endpoint = infoEntry.Endpoint, TotalMatchesPlayed = 1, MaximumMatchesPerDay = 1, AverageMatchesPerDay = 1, MaximumPopulation = infoEntry.Scoreboard.Count, AveragePopulation = infoEntry.Scoreboard.Count, Top5GameModes = new List <StringEntry> { new StringEntry { String = infoEntry.GameMode } }, Top5Maps = new List <StringEntry> { new StringEntry { String = infoEntry.Map } }, MatchesPerDay = new List <DayCountEntry> { new DayCountEntry { Day = infoEntry.Timestamp.Date, Count = 1 } }, PopulationPerMatch = new List <MatchCountEntry> { new MatchCountEntry { Key = infoEntry.Endpoint + infoEntry.Timestamp, Endpoint = infoEntry.Endpoint, TimeStamp = infoEntry.Timestamp, Count = infoEntry.Scoreboard.Count } }, GameModePopularity = new List <NameCountEntry> { new NameCountEntry { Name = infoEntry.GameMode, Count = 1 } }, MapPopularity = new List <NameCountEntry> { new NameCountEntry { Name = infoEntry.Map, Count = 1 } } }); }
public async Task GetBestPlayers_DoesNotCountPlayersWithoutDeaths() { var time = DateTime.Now; var data = new ServerInfoEntry { Endpoint = "GetBestPlayers_DoesNotCountPlayersWithoutDeaths", Name = "Test", GameModes = new List <StringEntry> { new StringEntry { String = "DM" }, new StringEntry { String = "TDM" } } }; var match = new MatchInfoEntry { Map = "1", GameMode = "2", FragLimit = 20, TimeLimit = 300, TimeElapsed = 25, Scoreboard = new List <ScoreEntry> { new ScoreEntry { Name = "GetBestPlayers_DoesNotCountPlayersWithoutDeaths1", Deaths = 0, Frags = 2, Kills = 20 }, new ScoreEntry { Name = "GetBestPlayers_DoesNotCountPlayersWithoutDeaths2", Deaths = 0, Frags = 20, Kills = 2 } } }; await statistics.PutServerInfo(data.Endpoint, new ServerInfoEntry { Name = data.Name, GameModes = data.GameModes }); await statistics.PutMatchInfo(data.Endpoint, time, match); new GameStatistics().GetBestPlayers(50).Result.Should().BeEmpty(); }
public void Update(MatchInfoEntry infoEntry, DatabaseContext databaseContext) { foreach (var player in infoEntry.Scoreboard) { var previous = databaseContext.PlayersStatistics.FirstOrDefault(x => x.Name.Equals(player.Name, StringComparison.InvariantCultureIgnoreCase)); if (previous == null) { SetFirstEntry(infoEntry, player.Name, databaseContext); } else { UpdateEntry(previous, infoEntry); } } }
private void UpdateEntry(ServerStatisticsEntry previous, MatchInfoEntry infoEntry) { previous.MatchesPerDay.AddOrUpdate(x => x.Day == infoEntry.Timestamp.Date, () => new DayCountEntry { Day = infoEntry.Timestamp.Date, Count = 1 }, x => x.Count++); previous.PopulationPerMatch.AddOrUpdate(x => x.Key == infoEntry.Endpoint + infoEntry.Timestamp, () => new MatchCountEntry { Key = infoEntry.Endpoint + infoEntry.Timestamp, Endpoint = infoEntry.Endpoint, TimeStamp = infoEntry.Timestamp, Count = infoEntry.Scoreboard.Count }, x => x.Count++); previous.GameModePopularity.AddOrUpdate(x => x.Name == infoEntry.GameMode, () => new NameCountEntry { Name = infoEntry.GameMode, Count = 1 }, x => x.Count++); previous.MapPopularity.AddOrUpdate(x => x.Name == infoEntry.Map, () => new NameCountEntry { Name = infoEntry.Map, Count = 1 }, x => x.Count++); var totalDays = (previous.MatchesPerDay.Max(x => x.Day) - previous.MatchesPerDay.Min(x => x.Day)).TotalDays; previous.TotalMatchesPlayed = previous.TotalMatchesPlayed + 1; previous.MaximumMatchesPerDay = previous.MatchesPerDay.Select(x => x.Count).Max(); previous.AverageMatchesPerDay = Math.Abs(totalDays) < 0.00001 ? previous.MatchesPerDay.Select(x => x.Count).Sum() : previous.MatchesPerDay.Select(x => x.Count).Sum() / totalDays; previous.MaximumPopulation = previous.PopulationPerMatch.Select(x => x.Count).Max(); previous.AveragePopulation = (double)previous.PopulationPerMatch.Select(x => x.Count).Sum() / previous.PopulationPerMatch.Count; previous.Top5GameModes = previous.GameModePopularity .OrderByDescending(x => x.Count) .Take(5) .Select(x => new StringEntry { String = x.Name }) .ToList(); previous.Top5Maps = previous.MapPopularity .OrderByDescending(x => x.Count) .Take(5) .Select(x => new StringEntry { String = x.Name }) .ToList(); }
private void UpdateEntry(PlayerStatisticsEntry previous, MatchInfoEntry infoEntry) { var position = infoEntry.Scoreboard.FindIndex(x => x.Name == previous.Name); var scoreboardPercent = 100.0; if (infoEntry.Scoreboard.Count > 1) { scoreboardPercent = (double)(infoEntry.Scoreboard.Count - position - 1) / (infoEntry.Scoreboard.Count - 1) * 100; } var totalMatchesWon = position == 0 ? previous.TotalMatchesWon + 1 : previous.TotalMatchesWon; previous.ServersPopularity.AddOrUpdate(x => x.Name == infoEntry.Endpoint, () => new NameCountEntry { Name = infoEntry.GameMode, Count = 1 }, x => x.Count++); previous.GameModePopularity.AddOrUpdate(x => x.Name == infoEntry.GameMode, () => new NameCountEntry { Name = infoEntry.GameMode, Count = 1 }, x => x.Count++); previous.MatchesPerDay.AddOrUpdate(x => x.Day == infoEntry.Timestamp.Date, () => new DayCountEntry { Day = infoEntry.Timestamp.Date, Count = 1 }, x => x.Count++); previous.TotalKills += infoEntry.Scoreboard[position].Kills; previous.TotalDeaths += infoEntry.Scoreboard[position].Deaths; var totalDays = (previous.MatchesPerDay.Max(x => x.Day) - previous.MatchesPerDay.Min(x => x.Day)).TotalDays; var averageScoreboardPercent = (previous.AverageScoreboardPercent * previous.TotalMatchesPlayed + scoreboardPercent) / (previous.TotalMatchesPlayed + 1); var lastMatchPlayed = infoEntry.Timestamp > previous.LastMatchPlayed ? infoEntry.Timestamp : previous.LastMatchPlayed; var noDeaths = previous.TotalDeaths == 0; previous.TotalMatchesPlayed = previous.TotalMatchesPlayed + 1; previous.TotalMatchesWon = totalMatchesWon; previous.FavoriteServer = previous.ServersPopularity.OrderByDescending(x => x.Count).First().Name; previous.UniqueServers = previous.ServersPopularity.Count; previous.FavoriteGameMode = previous.GameModePopularity.OrderByDescending(x => x.Count).First().Name; previous.AverageScoreboardPercent = averageScoreboardPercent; previous.MaximumMatchesPerDay = previous.MatchesPerDay.Select(x => x.Count).Max(); previous.AverageMatchesPerDay = Math.Abs(totalDays) < 0.01 ? previous.MatchesPerDay.Select(x => x.Count).Sum() : previous.MatchesPerDay.Select(x => x.Count).Sum() / totalDays; previous.LastMatchPlayed = lastMatchPlayed; previous.KillToDeathRatio = noDeaths ? previous.TotalKills : (double)previous.TotalKills / previous.TotalDeaths; }
public void Update(MatchInfoEntry infoEntry, DatabaseContext databaseContext) { const int maxPlayersCount = 50; const int requiredMatchesCount = 10; var bestPlayers = databaseContext.BestPlayers.OrderByDescending(x => x.KillToDeathRatio).ToList(); foreach (var player in infoEntry.Scoreboard) { var playerInfo = databaseContext.PlayersStatistics.FirstOrDefault(x => x.Name.Equals(player.Name, StringComparison.InvariantCultureIgnoreCase)); if (playerInfo == null || playerInfo.TotalDeaths == 0 || playerInfo.TotalMatchesPlayed < requiredMatchesCount) { continue; } var previous = bestPlayers.Find(x => x.Name == player.Name); if (previous != null) { previous.KillToDeathRatio = playerInfo.KillToDeathRatio; continue; } if (bestPlayers.Count < maxPlayersCount) { databaseContext.BestPlayers.Add(new BestPlayerEntry { Name = playerInfo.Name, KillToDeathRatio = playerInfo.KillToDeathRatio }); } else if (bestPlayers[bestPlayers.Count - 1].KillToDeathRatio < playerInfo.KillToDeathRatio) { databaseContext.BestPlayers.Remove(bestPlayers[bestPlayers.Count - 1]); databaseContext.BestPlayers.Add(new BestPlayerEntry { Name = playerInfo.Name, KillToDeathRatio = playerInfo.KillToDeathRatio }); } } }
private void SetFirstEntry(MatchInfoEntry infoEntry, string name, DatabaseContext databaseContext) { var position = infoEntry.Scoreboard.FindIndex(x => x.Name == name); var scoreboardPercent = 100.0; if (infoEntry.Scoreboard.Count > 1) { scoreboardPercent = (double)(infoEntry.Scoreboard.Count - position - 1) / (infoEntry.Scoreboard.Count - 1) * 100; } databaseContext.PlayersStatistics.Add(new PlayerStatisticsEntry { Name = name, TotalMatchesPlayed = 1, TotalMatchesWon = position == 0 ? 1 : 0, FavoriteServer = infoEntry.Endpoint, UniqueServers = 1, FavoriteGameMode = infoEntry.GameMode, AverageScoreboardPercent = scoreboardPercent, MaximumMatchesPerDay = 1, AverageMatchesPerDay = 1, LastMatchPlayed = infoEntry.Timestamp, KillToDeathRatio = 0, ServersPopularity = new List <NameCountEntry> { new NameCountEntry { Name = infoEntry.Endpoint, Count = 1 } }, GameModePopularity = new List <NameCountEntry> { new NameCountEntry { Name = infoEntry.GameMode, Count = 1 } }, MatchesPerDay = new List <DayCountEntry> { new DayCountEntry { Day = infoEntry.Timestamp.Date, Count = 1 } }, TotalKills = infoEntry.Scoreboard[position].Kills, TotalDeaths = infoEntry.Scoreboard[position].Deaths }); }
public void Update(MatchInfoEntry infoEntry, DatabaseContext databaseContext) { const int maxServersCount = 50; var popularServers = databaseContext.PopularServers.OrderByDescending(x => x.AverageMatchesPerDay).ToList(); var serverStatistics = databaseContext.ServerStatistics.Find(infoEntry.Endpoint); var serverInfo = databaseContext.Servers.Find(infoEntry.Endpoint); if (serverStatistics == null || serverInfo == null) { return; } var serverName = serverInfo.Name; var previous = popularServers.Find(x => x.Endpoint == serverInfo.Endpoint); if (previous != null) { previous.AverageMatchesPerDay = serverStatistics.AverageMatchesPerDay; } else if (popularServers.Count < maxServersCount) { databaseContext.PopularServers.Add(new PopularServerEntry { Endpoint = infoEntry.Endpoint, Name = serverName, AverageMatchesPerDay = serverStatistics.AverageMatchesPerDay }); } else if (popularServers[popularServers.Count - 1].AverageMatchesPerDay < serverStatistics.AverageMatchesPerDay) { databaseContext.PopularServers.Remove(popularServers[popularServers.Count - 1]); databaseContext.PopularServers.Add(new PopularServerEntry { Endpoint = infoEntry.Endpoint, Name = serverName, AverageMatchesPerDay = serverStatistics.AverageMatchesPerDay }); } }
public async Task PutMatchInfo_SavesInfo() { var endpoint = "PutServerInfo_SavesInfo"; var timeStamp = DateTime.UtcNow.Date - TimeSpan.FromDays(3); var matchData = new MatchInfoEntry { Map = "DM-HelloWorld", GameMode = "TM", FragLimit = 20, TimeLimit = 20, TimeElapsed = 12.345678, Scoreboard = new List <ScoreEntry> { new ScoreEntry { Name = "Player1", Frags = 20, Kills = 21, Deaths = 3 }, new ScoreEntry { Name = "Player2", Frags = 2, Kills = 2, Deaths = 21 } } }; await statistics.PutMatchInfo(endpoint, timeStamp, matchData); using (var databaseContext = new DatabaseContext()) { var result = databaseContext.Matches.Find(matchData.Endpoint + timeStamp.ToString(CultureInfo.InvariantCulture)); result.ShouldBeEquivalentTo(matchData, o => { o.Excluding(x => x.Key); o.Excluding(x => x.Timestamp); o.Excluding(x => x.RecentMatchEntry); return(o); }); } }
public async Task PutMatchInfo(MatchInfoEntry serverInfoEntry, string endpoint, DateTime timestamp) { await statistics.PutMatchInfo(endpoint, timestamp, serverInfoEntry); }