public void EloExpected_EqualEloShouldHaveSameValue() { var expectedScore1 = new EloRating(1300).ExpectedScoreAgainst(1300); var expectedScore2 = new EloRating(1300).ExpectedScoreAgainst(1300); Assert.AreEqual(expectedScore1, expectedScore2); }
public void EloExpected_HigherEloShouldBeExpectedToWin() { var expectedScore1 = new EloRating(1400).ExpectedScoreAgainst(1300); var expectedScore2 = new EloRating(1300).ExpectedScoreAgainst(1400); Assert.Greater(expectedScore1, expectedScore2); }
public void BasicRankIt() { //for (int i = 0; i < 500; i++) { var eloRatingConfig = new EloRatingConfig(); eloRatingConfig.FlatScore = 400; eloRatingConfig.Factor = 120; var eloRatingInput = new EloRatingInput(EloRatingVictoryEnum.FirstPlayerWins); eloRatingInput.Player1Points = 1700; eloRatingInput.Player2Points = 1300; var eloRating = new EloRating(eloRatingConfig); var eloRatingOutput = eloRating.RankIt(eloRatingInput); Assert.IsTrue(eloRatingConfig.FlatScore > 0 && eloRatingConfig.Factor > 0); Assert.IsTrue(eloRatingInput.Victory == EloRatingVictoryEnum.FirstPlayerWins); Assert.IsTrue(eloRating.Config == eloRatingConfig); Assert.IsTrue(eloRatingOutput.SourceInput.Player1Points == eloRatingInput.Player1Points); Assert.IsTrue(eloRatingOutput.SourceInput.Player2Points == eloRatingInput.Player2Points); Assert.IsTrue(eloRatingOutput.Player1NewPoints > eloRatingInput.Player1Points); Assert.IsTrue(eloRatingOutput.Player2NewPoints < eloRatingInput.Player2Points); int i = 0; Console.WriteLine($"interatction {i} Player 1 Input {eloRatingInput.Player1Points} --- Player1 Output {eloRatingOutput.Player1NewPoints}"); Console.WriteLine($"interatction {i} Player 2 Input {eloRatingInput.Player2Points} --- Player2 Output {eloRatingOutput.Player2NewPoints}"); Console.WriteLine("------"); } }
public void ComputeRatingNbMatchAbove30() { var catA = new Cat { CatId = "a", Looses = 15, Wins = 16, Rating = 1220 }; var catB = new Cat { CatId = "b", Looses = 0, Wins = 0, Rating = 1200 }; var expectedRatingA = 1230; var expectedRatingB = 1180; var elo = new EloRating(catA.Rating, catB.Rating, true, false, catA.TotalMatches, catB.TotalMatches); var(newRatingA, newRatingB) = elo.GetNewResults(); Assert.AreEqual(expectedRatingA, newRatingA); Assert.AreEqual(expectedRatingB, newRatingB); }
protected void nextCats_Click(object sender, EventArgs e) { var allCats = SessionHelper.Get <List <Cat> >("Cats"); var leftCat = allCats.Find(c => c.id == leftCatId.Value); var rightCat = allCats.Find(c => c.id == rightCatId.Value); EloRating.UpdateScores(leftCat, rightCat, 0.5, 400, 10); DisplayTwoCats(); }
public void Handle(GamePlayed @event) { var redTeam = GetTeam(@event.RedOffensive, @event.RedDefensive); var blueTeam = GetTeam(@event.BlueOffensive, @event.BlueDefensive); var rating = new EloRating(redTeam.Score, blueTeam.Score, @event.ScoreRed, @event.ScoreBlue, 0); redTeam.UpdateScore(rating.Point1); blueTeam.UpdateScore(rating.Point2); }
public void ScoreCat(WhichCat whichCat) { var allCats = SessionHelper.Get <List <Cat> >("Cats"); var leftCat = allCats.Find(c => c.id == leftCatId.Value); var rightCat = allCats.Find(c => c.id == rightCatId.Value); var resultat = whichCat == WhichCat.Left ? 1 : 0; EloRating.UpdateScores(leftCat, rightCat, resultat, 400, 10); }
public void PlayerWithSameIdentifierAndRating_AssertEquality() { var identifier = new EloPlayerIdentifier(Guid.NewGuid()); var rating = new EloRating(1200); var player1 = new EloPlayer(identifier, rating); var player2 = new EloPlayer(identifier, rating); Assert.AreEqual(player1, player2); Assert.IsTrue(player1 == player2); Assert.IsTrue(player1.Equals(player2)); }
public void TwoTeamsWithSamePlayers_AssertEquality() { var playerIdentifier = new EloPlayerIdentifier(); var rating = new EloRating(1200); var player1 = new EloPlayer(playerIdentifier, rating); var player2 = new EloPlayer(playerIdentifier, rating); var teamIdentifier = new EloTeamIdentifier(); var team1 = new EloTeam(teamIdentifier, player1, true); var team2 = new EloTeam(teamIdentifier, player2, false); Assert.AreEqual(team1, team2); Assert.IsTrue(team1 == team2); Assert.IsTrue(team1.Equals(team2)); }
private void DisplayTwoCats() { nbVotes = getNbCats(); if ((SessionHelper.Get <List <Cat> >("Cats")) != null) { var catsForVote = SessionHelper.Get <List <Cat> >("Cats"); if (catsForVote != null) { var twoCats = CatsHelper.Random <Cat>(catsForVote); btnLeftCat.ImageUrl = twoCats.First().url; leftCatId.Value = twoCats.First().id; probaWinLeft.Text = Math.Round(EloRating.GetProbaWinCat(twoCats.First(), twoCats.Last()) * 100, 2) + " %"; var rightCat = CatsHelper.Random <Cat>(catsForVote); btnRightCat.ImageUrl = twoCats.Last().url; rightCatId.Value = twoCats.Last().id; probaWinRight.Text = Math.Round(EloRating.GetProbaWinCat(twoCats.Last(), twoCats.First()) * 100, 2) + " %"; } } }
public bool Finish(string matchId, int challengerPoints, int opponentPoints) { Claim objectId = ClaimsPrincipal.Current.Identities.First().Claims.FirstOrDefault(c => c.Type == "http://schemas.microsoft.com/identity/claims/objectidentifier"); var userId = objectId.Value; var match = Matches.GetMatchById(Guid.Parse(matchId)); if (match.ChallengerId == userId || match.OpponentId == userId) { if (match.Status != 1) { return(false); } match.Status = 2; match.ChallengerPoints = challengerPoints; match.OpponentPoints = opponentPoints; Matches.Update(match); var challenger = Users.GetByUserId(match.ChallengerId); var opponent = Users.GetByUserId(match.OpponentId); // update users EloRating elo = new EloRating(challenger.EloRating, opponent.EloRating, challengerPoints, opponentPoints); challenger.EloRating = elo.FinalResult1; opponent.EloRating = elo.FinalResult2; Users.Update(challenger); Users.Update(opponent); return(true); } else { return(false); } // if match status is not equal to 0, accept is not possible. }
public void TestElo() { int elop1 = 2400; int elop2 = 2000; int elop1new; int elop2new; EloRating.Calculate(elop1, elop2, 1, out elop1new, out elop2new); Assert.AreEqual(2403, elop1new); Assert.AreEqual(1997, elop2new); EloRating.Calculate(elop1, elop2, 2, out elop1new, out elop2new); Assert.AreEqual(2371, elop1new); Assert.AreEqual(2029, elop2new); EloRating.Calculate(elop1, elop2, 0, out elop1new, out elop2new); Assert.AreEqual(2387, elop1new); Assert.AreEqual(2013, elop2new); }
private unsafe void OnDataReceived(IAsyncResult async) { SocketState state = (SocketState)async.AsyncState; if (state == null || state.Socket == null || !state.Socket.Connected) { return; } try { // receive data from the socket int received = state.Socket.EndReceive(async); if (received == 0) { return; } var buffer = state.Buffer; var input = Encoding.UTF8.GetString(XorBytes(buffer, 0, received - 7, XorKEY), 0, received); Log(Category, input); if (input.StartsWith(@"\auth\\gamename\")) { var sesskey = Interlocked.Increment(ref _sessionCounter).ToString("0000000000"); SendToClient(state, $@"\lc\2\sesskey\{sesskey}\proof\0\id\1\final\"); goto CONTINUE; } if (input.StartsWith(@"\authp\\pid\")) { //var clientData = LoginDatabase.Instance.GetData(state.Name); // \authp\\pid\87654321\resp\67512e365ba89497d60963caa4ce23d4\lid\1\final\ // \authp\\pid\87654321\resp\7e2270c581e8daf5a5321ff218953035\lid\1\final\ var pid = input.Substring(12, 9); state.ProfileId = long.Parse(pid); SendToClient(state, $@"\pauthr\{pid}\lid\1\final\"); //SendToClient(state, @"\pauthr\-3\lid\1\errmsg\helloworld\final\"); //SendToClient(state, @"\pauthr\100000004\lid\1\final\"); goto CONTINUE; } if (input.StartsWith(@"\getpd\")) { // \\getpd\\\\pid\\87654321\\ptype\\3\\dindex\\0\\keys\\\u0001points\u0001points2\u0001points3\u0001stars\u0001games\u0001wins\u0001disconn\u0001a_durat\u0001m_streak\u0001f_race\u0001SM_wins\u0001Chaos_wins\u0001Ork_wins\u0001Tau_wins\u0001SoB_wins\u0001DE_wins\u0001Eldar_wins\u0001IG_wins\u0001Necron_wins\u0001lsw\u0001rnkd_vics\u0001con_rnkd_vics\u0001team_vics\u0001mdls1\u0001mdls2\u0001rg\u0001pw\\lid\\1\\final\\ // \getpd\\pid\87654321\ptype\3\dindex\0\keys\pointspoints2points3starsgameswinsdisconna_duratm_streakf_raceSM_winsChaos_winsOrk_winsTau_winsSoB_winsDE_winsEldar_winsIG_winsNecron_winslswrnkd_vicscon_rnkd_vicsteam_vicsmdls1mdls2rgpw\lid\1\final\ var pid = input.Substring(12, 9); var keysIndex = input.IndexOf("keys") + 5; var keys = input.Substring(keysIndex); var keysList = keys.Split(new string[] { "\u0001", "\\lid\\1\\final\\", "final", "\\", "lid" }, StringSplitOptions.RemoveEmptyEntries); var keysResult = new StringBuilder(); var stats = UsersDatabase.Instance.GetStatsDataByProfileId(long.Parse(pid)); var gamesCount = stats.GamesCount; var stars = Math.Min(5, gamesCount); for (int i = 0; i < keysList.Length; i++) { var key = keysList[i]; keysResult.Append("\\" + key + "\\"); switch (key) { case "points": keysResult.Append(stats.Score1v1); break; case "points2": keysResult.Append(stats.Score2v2); break; case "points3": keysResult.Append(stats.Score3v3); break; case "stars": keysResult.Append(stars); break; case "games": keysResult.Append(gamesCount); break; case "wins": keysResult.Append(stats.WinsCount); break; case "disconn": keysResult.Append(stats.Disconnects); break; case "a_durat": keysResult.Append(stats.AverageDuractionTicks); break; case "m_streak": keysResult.Append(stats.Best1v1Winstreak); break; case "f_race": keysResult.Append(stats.FavouriteRace); break; case "SM_wins": keysResult.Append(stats.Smwincount); break; case "Chaos_wins": keysResult.Append(stats.Csmwincount); break; case "Ork_wins": keysResult.Append(stats.Orkwincount); break; case "Tau_wins": keysResult.Append(stats.Tauwincount); break; case "SoB_wins": keysResult.Append(stats.Sobwincount); break; case "DE_wins": keysResult.Append(stats.Dewincount); break; case "Eldar_wins": keysResult.Append(stats.Eldarwincount); break; case "IG_wins": keysResult.Append(stats.Igwincount); break; case "Necron_wins": keysResult.Append(stats.Necrwincount); break; /*case "lsw": keysResult.Append("123"); break; * case "rnkd_vics": keysResult.Append("50"); break; * case "con_rnkd_vics": keysResult.Append("200"); break; * case "team_vics": keysResult.Append("250"); break; * case "mdls1": keysResult.Append("260"); break; * case "mdls2": keysResult.Append("270"); break; * case "rg": keysResult.Append("280"); break; * case "pw": keysResult.Append("290"); break;*/ default: keysResult.Append("0"); break; } } SendToClient(state, $@"\getpdr\1\lid\1\pid\{pid}\mod\{stats.Modified}\length\{keys.Length}\data\{keysResult}\final\"); goto CONTINUE; } if (input.StartsWith(@"\setpd\")) { var pid = input.Substring(12, 9); var lidIndex = input.IndexOf("\\lid\\", StringComparison.OrdinalIgnoreCase); var lid = input.Substring(lidIndex + 5, 1); var timeInSeconds = (ulong)((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds); SendToClient(state, $@"\setpdr\1\lid\{lid}\pid\{pid}\mod\{timeInSeconds}\final\"); goto CONTINUE; } if (input.StartsWith(@"\updgame\")) { var gamedataIndex = input.IndexOf("gamedata"); var finalIndex = input.IndexOf("final"); var gameDataString = input.Substring(gamedataIndex + 9, finalIndex - gamedataIndex - 10); var valuesList = gameDataString.Split(new string[] { "\u0001", "\\lid\\1\\final\\", "final", "\\", "lid" }, StringSplitOptions.RemoveEmptyEntries); var dictionary = new Dictionary <string, string>(); for (int i = 0; i < valuesList.Length; i += 2) { dictionary[valuesList[i]] = valuesList[i + 1]; } var playersCount = int.Parse(dictionary["Players"]); for (int i = 0; i < playersCount; i++) { // Dont process games with AI if (dictionary["PHuman_" + i] != "1") { goto CONTINUE; } } var gameInternalSession = dictionary["SessionID"]; var teamsCount = int.Parse(dictionary["Teams"]); var version = dictionary["Version"]; var mod = dictionary["Mod"]; var modVersion = dictionary["ModVer"]; var uniqueGameSessionBuilder = new StringBuilder(gameInternalSession); for (int i = 0; i < playersCount; i++) { uniqueGameSessionBuilder.Append('<'); uniqueGameSessionBuilder.Append(dictionary["PID_" + i]); uniqueGameSessionBuilder.Append('>'); } var uniqueSession = uniqueGameSessionBuilder.ToString(); if (!HandledGamesCache.Add(uniqueSession, uniqueSession, new CacheItemPolicy() { SlidingExpiration = TimeSpan.FromDays(1) })) { goto CONTINUE; } var usersGameInfos = new GameUserInfo[playersCount]; GameUserInfo currentUserInfo = null; for (int i = 0; i < playersCount; i++) { //var nick = dictionary["player_"+i]; var pid = long.Parse(dictionary["PID_" + i]); var info = new GameUserInfo() { Stats = UsersDatabase.Instance.GetStatsDataByProfileId(pid), Race = (Race)Enum.Parse(typeof(Race), dictionary["PRace_" + i], true), Team = int.Parse(dictionary["PTeam_" + i]), FinalState = (PlayerFinalState)Enum.Parse(typeof(PlayerFinalState), dictionary["PFnlState_" + i]), }; usersGameInfos[i] = info; if (pid == state.ProfileId) { currentUserInfo = info; } } var teams = usersGameInfos.GroupBy(x => x.Team).ToDictionary(x => x.Key, x => x.ToArray()); var gameDuration = long.Parse(dictionary["Duration"]); foreach (var team in teams) { for (int i = 0; i < team.Value.Length; i++) { var info = team.Value[i]; info.Stats.AllInGameTicks += gameDuration; switch (info.Race) { case Race.space_marine_race: info.Stats.Smgamescount++; break; case Race.chaos_marine_race: info.Stats.Csmgamescount++; break; case Race.ork_race: info.Stats.Orkgamescount++; break; case Race.eldar_race: info.Stats.Eldargamescount++; break; case Race.guard_race: info.Stats.Iggamescount++; break; case Race.necron_race: info.Stats.Necrgamescount++; break; case Race.tau_race: info.Stats.Taugamescount++; break; case Race.dark_eldar_race: info.Stats.Degamescount++; break; case Race.sisters_race: info.Stats.Sobgamescount++; break; default: break; } if (info.FinalState == PlayerFinalState.Winner) { switch (info.Race) { case Race.space_marine_race: info.Stats.Smwincount++; break; case Race.chaos_marine_race: info.Stats.Csmwincount++; break; case Race.ork_race: info.Stats.Orkwincount++; break; case Race.eldar_race: info.Stats.Eldarwincount++; break; case Race.guard_race: info.Stats.Igwincount++; break; case Race.necron_race: info.Stats.Necrwincount++; break; case Race.tau_race: info.Stats.Tauwincount++; break; case Race.dark_eldar_race: info.Stats.Dewincount++; break; case Race.sisters_race: info.Stats.Sobwincount++; break; default: break; } } } } var chatUserInfo = ChatServer.IrcDaemon.Users[state.ProfileId]; var game = chatUserInfo.Game; // For rated games if (game != null && game.Clean()) { chatUserInfo.Game = null; var usersInGame = game.UsersInGame; if (usersGameInfos.Select(x => x.Stats.ProfileId).OrderBy(x => x).SequenceEqual(usersInGame.OrderBy(x => x))) { // Update winstreaks for 1v1 only if (usersInGame.Length == 2) { UpdateStreak(usersGameInfos[0]); UpdateStreak(usersGameInfos[1]); } var groupedTeams = usersGameInfos.GroupBy(x => x.Team).Select(x => x.ToArray()).ToArray(); var players1Team = groupedTeams[0]; var players2Team = groupedTeams[1]; Func <StatsData, long> scoreSelector = null; Action <StatsData, long> scoreUpdater = null; switch (usersInGame.Length) { case 2: scoreSelector = StatsDelegates.Score1v1Selector; scoreUpdater = StatsDelegates.Score1v1Updated; break; case 4: scoreSelector = StatsDelegates.Score2v2Selector; scoreUpdater = StatsDelegates.Score2v2Updated; break; case 6: case 8: scoreSelector = StatsDelegates.Score3v3Selector; scoreUpdater = StatsDelegates.Score3v3Updated; break; default: goto UPDATE; } var team0score = (long)players1Team.Average(x => scoreSelector(x.Stats)); var team1score = (long)players2Team.Average(x => scoreSelector(x.Stats)); var isFirstTeamResult = players1Team.Any(x => x.FinalState == PlayerFinalState.Winner); var delta = EloRating.CalculateELOdelta(team0score, team1score, isFirstTeamResult? EloRating.GameOutcome.Win : EloRating.GameOutcome.Loss); //if (isFirstTeamResult) //{ for (int i = 0; i < players1Team.Length; i++) { scoreUpdater(players1Team[i].Stats, Math.Max(1000L, scoreSelector(players1Team[i].Stats) + delta)); } for (int i = 0; i < players2Team.Length; i++) { scoreUpdater(players2Team[i].Stats, Math.Max(1000L, scoreSelector(players1Team[i].Stats) - delta)); } /*} * else * { * for (int i = 0; i < players1Team.Length; i++) * scoreUpdater(players1Team[i].Stats, scoreSelector(players1Team[i].Stats) + delta); * * for (int i = 0; i < players2Team.Length; i++) * scoreUpdater(players1Team[i].Stats, scoreSelector(players1Team[i].Stats) - delta); * }*/ } } UPDATE: for (int i = 0; i < usersGameInfos.Length; i++) { UsersDatabase.Instance.UpdateUserStats(usersGameInfos[i].Stats); } } } catch (ObjectDisposedException) { if (state != null) { state.Dispose(); } state = null; return; } catch (SocketException e) { switch (e.SocketErrorCode) { case SocketError.ConnectionReset: if (state != null) { state.Dispose(); } state = null; return; case SocketError.Disconnecting: if (state != null) { state.Dispose(); } state = null; return; default: LogError(Category, "Error receiving data"); LogError(Category, String.Format("{0} {1}", e.SocketErrorCode, e)); if (state != null) { state.Dispose(); } state = null; return; } } catch (Exception e) { LogError(Category, "Error receiving data"); LogError(Category, e.ToString()); } // and we wait for more data... CONTINUE : WaitForData(state); }
public void GetExpectedScoreScenario() { var expectedScore = new EloRating(1460).ExpectedScoreAgainst(1130); Assert.Greater(expectedScore, 0.5); }
public async Task <IActionResult> Result([FromRoute] int matchId, [FromBody] ResultModel model) { try { var match = _context.Matches .Include(x => x.CatA) .Include(x => x.CatB) .FirstOrDefault(x => x.MatchId == matchId); if (match != null) { var catA = match.CatA; var catB = match.CatB; var rating = new EloRating(catA.Rating, catB.Rating, model.Result == MatchResult.PLAYER_A_WIN, model.Result == MatchResult.PLAYER_B_WIN, catA.TotalMatches, catB.TotalMatches); var(newRatingA, newRatingB) = rating.GetNewResults(); var now = DateTime.UtcNow; catA.Rating = newRatingA; catA.Wins = model.Result == MatchResult.PLAYER_A_WIN ? catA.Wins + 1 : catA.Wins; catA.Looses = model.Result == MatchResult.PLAYER_B_WIN ? catA.Looses + 1 : catA.Looses; catA.Histories.Add(new History { Date = now, Rating = newRatingA, MatchId = matchId }); catB.Rating = newRatingB; catB.Wins = model.Result == MatchResult.PLAYER_B_WIN ? catB.Wins + 1 : catB.Wins; catB.Looses = model.Result == MatchResult.PLAYER_A_WIN ? catB.Looses + 1 : catB.Looses; catB.Histories.Add(new History { Date = now, Rating = newRatingB, MatchId = matchId }); match.Result = (int)model.Result; await _context.SaveChangesAsync(); var winnerId = model.Result == MatchResult.PLAYER_A_WIN ? catA.CatId : catB.CatId; return(Ok(winnerId)); } return(BadRequest()); } catch (Exception) { return(StatusCode(500)); } }
public virtual async Task<IEnumerable<EloRating>> GetRatings(DateTime time, IEnumerable<Team> teams) { time = time.Date; if (!_eloCache.ContainsKey(time)) { await UpdateCacheForDate(time); } var teamsList = teams.ToList(); var result = new List<EloRating>(); var ratings = _eloCache[time]; foreach (var ratingsRow in ratings) { var team = teamsList.FirstOrDefault(x => x.MatchName(ratingsRow.Club)); if (team != null) { var rating = new EloRating { TeamName = team.Name, Rating = ratingsRow.Elo, Time = time, }; result.Add(rating); } } return result; }
private unsafe void OnDataReceived(IAsyncResult async) { SocketState state = (SocketState)async.AsyncState; if (state == null || state.Socket == null || !state.Socket.Connected) return; try { // receive data from the socket int received = state.Socket.EndReceive(async); if (received == 0) return; var buffer = state.Buffer; var input = Encoding.UTF8.GetString(XorBytes(buffer, 0, received - 7, XorKEY), 0, received); Logger.Info($"Receive data from the socket: {input}"); if (input.StartsWith(@"\auth\\gamename\")) { var sesskey = Interlocked.Increment(ref _sessionCounter).ToString("0000000000"); SendToClient(state, $@"\lc\2\sesskey\{sesskey}\proof\0\id\1\final\"); goto CONTINUE; } if (input.StartsWith(@"\authp\\pid\")) { try { var pid = GetPidFromInput(input, 12); var profileId = long.Parse(pid); state.ProfileId = profileId; state.Nick = Database.UsersDBInstance.GetProfileById(profileId).Name; SendToClient(state, $@"\pauthr\{pid}\lid\1\final\"); } catch (Exception) { state.Dispose(); return; } goto CONTINUE; } if (input.StartsWith(@"\getpd\")) { // \\getpd\\\\pid\\87654321\\ptype\\3\\dindex\\0\\keys\\\u0001points\u0001points2\u0001points3\u0001stars\u0001games\u0001wins\u0001disconn\u0001a_durat\u0001m_streak\u0001f_race\u0001SM_wins\u0001Chaos_wins\u0001Ork_wins\u0001Tau_wins\u0001SoB_wins\u0001DE_wins\u0001Eldar_wins\u0001IG_wins\u0001Necron_wins\u0001lsw\u0001rnkd_vics\u0001con_rnkd_vics\u0001team_vics\u0001mdls1\u0001mdls2\u0001rg\u0001pw\\lid\\1\\final\\ // \getpd\\pid\87654321\ptype\3\dindex\0\keys\pointspoints2points3starsgameswinsdisconna_duratm_streakf_raceSM_winsChaos_winsOrk_winsTau_winsSoB_winsDE_winsEldar_winsIG_winsNecron_winslswrnkd_vicscon_rnkd_vicsteam_vicsmdls1mdls2rgpw\lid\1\final\ var pid = GetPidFromInput(input, 12); var keysIndex = input.IndexOf("keys") + 5; var keys = input.Substring(keysIndex); var keysList = keys.Split(new string[] { "\u0001", "\\lid\\1\\final\\", "final", "\\", "lid" }, StringSplitOptions.RemoveEmptyEntries ); var keysResult = new StringBuilder(); var stats = ProfilesCache.GetProfileByPid(pid); for (int i = 0; i < keysList.Length; i++) { var key = keysList[i]; keysResult.Append("\\"+key+"\\"); switch (key) { case "points": keysResult.Append(stats.Score1v1); break; case "points2": keysResult.Append(stats.Score2v2); break; case "points3": keysResult.Append(stats.Score3v3); break; case "stars": keysResult.Append(stats.StarsCount); break; case "games": keysResult.Append(stats.GamesCount); break; case "wins": keysResult.Append(stats.WinsCount); break; case "disconn": keysResult.Append(stats.Disconnects); break; case "a_durat": keysResult.Append(stats.AverageDuractionTicks); break; case "m_streak": keysResult.Append(stats.Best1v1Winstreak); break; case "f_race": keysResult.Append(stats.FavouriteRace); break; case "SM_wins": keysResult.Append(stats.Smwincount); break; case "Chaos_wins": keysResult.Append(stats.Csmwincount); break; case "Ork_wins": keysResult.Append(stats.Orkwincount); break; case "Tau_wins": keysResult.Append(stats.Tauwincount); break; case "SoB_wins": keysResult.Append(stats.Sobwincount); break; case "DE_wins": keysResult.Append(stats.Dewincount); break; case "Eldar_wins": keysResult.Append(stats.Eldarwincount); break; case "IG_wins": keysResult.Append(stats.Igwincount); break; case "Necron_wins": keysResult.Append(stats.Necrwincount); break; /*case "lsw": keysResult.Append("123"); break; case "rnkd_vics": keysResult.Append("50"); break; case "con_rnkd_vics": keysResult.Append("200"); break; case "team_vics": keysResult.Append("250"); break; case "mdls1": keysResult.Append("260"); break; case "mdls2": keysResult.Append("270"); break; case "rg": keysResult.Append("280"); break; case "pw": keysResult.Append("290"); break;*/ default: keysResult.Append("0"); break; } } SendToClient(state, $@"\getpdr\1\lid\1\pid\{pid}\mod\{stats.Modified}\length\{keys.Length}\data\{keysResult}\final\"); goto CONTINUE; } if (input.StartsWith(@"\setpd\")) { var pid = GetPidFromInput(input, 12); var lidIndex = input.IndexOf("\\lid\\", StringComparison.OrdinalIgnoreCase); var lid = input.Substring(lidIndex+5, 1); var timeInSeconds = (ulong)((DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds); SendToClient(state, $@"\setpdr\1\lid\{lid}\pid\{pid}\mod\{timeInSeconds}\final\"); goto CONTINUE; } if (input.StartsWith(@"\updgame\")) { Task.Factory.StartNew(() => { var gamedataIndex = input.IndexOf("gamedata"); var finalIndex = input.IndexOf("final"); var gameDataString = input.Substring(gamedataIndex + 9, finalIndex - gamedataIndex - 10); var valuesList = gameDataString.Split(new string[] { "\u0001", "\\lid\\1\\final\\", "final", "\\", "lid" }, StringSplitOptions.RemoveEmptyEntries); var dictionary = new Dictionary<string, string>(); for (int i = 0; i < valuesList.Length; i += 2) dictionary[valuesList[i]] = valuesList[i + 1]; var playersCount = int.Parse(dictionary["Players"]); for (int i = 0; i < playersCount; i++) { // Dont process games with AI if (dictionary["PHuman_" + i] != "1") return; } var gameInternalSession = dictionary["SessionID"]; var teamsCount = int.Parse(dictionary["Teams"]); var version = dictionary["Version"]; var mod = dictionary["Mod"]; var modVersion = dictionary["ModVer"]; var uniqueGameSessionBuilder = new StringBuilder(gameInternalSession); for (int i = 0; i < playersCount; i++) { uniqueGameSessionBuilder.Append('<'); uniqueGameSessionBuilder.Append(dictionary["player_" + i]); uniqueGameSessionBuilder.Append('>'); } var uniqueSession = uniqueGameSessionBuilder.ToString(); if (!HandledGamesCache.Add(uniqueSession, uniqueSession, new CacheItemPolicy() { SlidingExpiration = TimeSpan.FromDays(1) })) { return; } var usersGameInfos = new GameUserInfo[playersCount]; GameUserInfo currentUserInfo = null; for (int i = 0; i < playersCount; i++) { var nick = dictionary["player_"+i]; var info = new GameUserInfo { Profile = ProfilesCache.GetProfileByName(nick), Race = Enum.Parse<Race>(dictionary["PRace_" + i], true), Team = int.Parse(dictionary["PTeam_" + i]), FinalState = Enum.Parse<PlayerFinalState>(dictionary["PFnlState_" + i]), }; usersGameInfos[i] = info; if (nick.Equals(state.Nick, StringComparison.Ordinal)) currentUserInfo = info; } var teams = usersGameInfos.GroupBy(x => x.Team).ToDictionary(x => x.Key, x => x.ToArray()); var gameDuration = long.Parse(dictionary["Duration"]); foreach (var team in teams) { for (int i = 0; i < team.Value.Length; i++) { var info = team.Value[i]; info.Profile.AllInGameTicks += gameDuration; switch (info.Race) { case Race.space_marine_race: info.Profile.Smgamescount++; break; case Race.chaos_marine_race: info.Profile.Csmgamescount++; break; case Race.ork_race: info.Profile.Orkgamescount++; break; case Race.eldar_race: info.Profile.Eldargamescount++; break; case Race.guard_race: info.Profile.Iggamescount++; break; case Race.necron_race: info.Profile.Necrgamescount++; break; case Race.tau_race: info.Profile.Taugamescount++; break; case Race.dark_eldar_race: info.Profile.Degamescount++; break; case Race.sisters_race: info.Profile.Sobgamescount++; break; default: break; } if (info.FinalState == PlayerFinalState.Winner) { switch (info.Race) { case Race.space_marine_race: info.Profile.Smwincount++; break; case Race.chaos_marine_race: info.Profile.Csmwincount++; break; case Race.ork_race: info.Profile.Orkwincount++; break; case Race.eldar_race: info.Profile.Eldarwincount++; break; case Race.guard_race: info.Profile.Igwincount++; break; case Race.necron_race: info.Profile.Necrwincount++; break; case Race.tau_race: info.Profile.Tauwincount++; break; case Race.dark_eldar_race: info.Profile.Dewincount++; break; case Race.sisters_race: info.Profile.Sobwincount++; break; default: break; } } } } bool isRateGame = false; if (ChatServer.IrcDaemon.Users.TryGetValue(state.ProfileId, out UserInfo chatUserInfo)) { var game = chatUserInfo.Game; isRateGame = game != null && game.Clean(); // For rated games if (isRateGame) { Console.WriteLine("UPDATE RATING GAME " + uniqueSession); chatUserInfo.Game = null; var usersInGame = game.UsersInGame; if (usersGameInfos.Select(x => x.Profile.Id).OrderBy(x => x).SequenceEqual(usersInGame.OrderBy(x => x))) { // Update winstreaks for 1v1 only if (usersInGame.Length == 2) { UpdateStreak(usersGameInfos[0]); UpdateStreak(usersGameInfos[1]); } var groupedTeams = usersGameInfos.GroupBy(x => x.Team).Select(x => x.ToArray()).ToArray(); var players1Team = groupedTeams[0]; var players2Team = groupedTeams[1]; Func<ProfileData, long> scoreSelector = null; Action<ProfileData, long> scoreUpdater = null; ReatingGameType type = ReatingGameType.Unknown; switch (usersInGame.Length) { case 2: scoreSelector = StatsDelegates.Score1v1Selector; scoreUpdater = StatsDelegates.Score1v1Updated; type = ReatingGameType.Rating1v1; break; case 4: scoreSelector = StatsDelegates.Score2v2Selector; scoreUpdater = StatsDelegates.Score2v2Updated; type = ReatingGameType.Rating2v2; break; case 6: case 8: type = ReatingGameType.Rating3v3_4v4; scoreSelector = StatsDelegates.Score3v3Selector; scoreUpdater = StatsDelegates.Score3v3Updated; break; default: goto UPDATE; } var team0score = (long)players1Team.Average(x => scoreSelector(x.Profile)); var team1score = (long)players2Team.Average(x => scoreSelector(x.Profile)); var isFirstTeamResult = players1Team.Any(x => x.FinalState == PlayerFinalState.Winner); var delta = EloRating.CalculateELOdelta(team0score, team1score, isFirstTeamResult ? EloRating.GameOutcome.Win : EloRating.GameOutcome.Loss); for (int i = 0; i < players1Team.Length; i++) { players1Team[i].Delta = delta; players1Team[i].RatingGameType = type; scoreUpdater(players1Team[i].Profile, Math.Max(1000L, scoreSelector(players1Team[i].Profile) + delta)); } for (int i = 0; i < players2Team.Length; i++) { players2Team[i].Delta = -delta; players2Team[i].RatingGameType = type; scoreUpdater(players2Team[i].Profile, Math.Max(1000L, scoreSelector(players2Team[i].Profile) - delta)); } } } } UPDATE: for (int i = 0; i < usersGameInfos.Length; i++) { var info = usersGameInfos[i]; var profile = info.Profile; ProfilesCache.UpdateProfilesCache(profile); Database.UsersDBInstance.UpdateProfileData(profile); if (info.Delta != 0) { Task.Delay(5000).ContinueWith(task => { switch (info.RatingGameType) { case ReatingGameType.Unknown: break; case ReatingGameType.Rating1v1: ChatServer.IrcDaemon.SendToUser(profile.Id, $@"Ваш рейтинг 1v1 изменился на {GetDeltaString(info.Delta)} и сейчас равен {info.Profile.Score1v1}."); break; case ReatingGameType.Rating2v2: ChatServer.IrcDaemon.SendToUser(profile.Id, $@"Ваш рейтинг 2v2 изменился на {GetDeltaString(info.Delta)} и сейчас равен {info.Profile.Score2v2}."); break; case ReatingGameType.Rating3v3_4v4: ChatServer.IrcDaemon.SendToUser(profile.Id, $@"Ваш рейтинг 3v3/4v4 изменился на {GetDeltaString(info.Delta)} и сейчас равен {info.Profile.Score3v3}."); break; default: break; } }); } } Dowstats.UploadGame(dictionary, usersGameInfos, isRateGame); }, CancellationToken.None, TaskCreationOptions.LongRunning | TaskCreationOptions.PreferFairness, _exclusiveScheduler); goto CONTINUE; } } catch (ObjectDisposedException) { if (state != null) state.Dispose(); state = null; return; } catch (SocketException e) { switch (e.SocketErrorCode) { case SocketError.ConnectionReset: if (state != null) state.Dispose(); state = null; return; case SocketError.Disconnecting: if (state != null) state.Dispose(); state = null; return; default: Logger.Error(e, $"Error receiving data. SocketErrorCode: {e.SocketErrorCode}"); if (state != null) state.Dispose(); state = null; return; } } catch (Exception e) { Logger.Error(e, "Error receiving data"); } // and we wait for more data... CONTINUE: WaitForData(state); }