public void StandardElo() { var standardElo = new StandardElo(); // Standard match var result = standardElo.Calculate(1600, 1500, 1500); Assert.That(result.WinnerDelta, Is.EqualTo(16)); Assert.That(result.LoserDelta, Is.EqualTo(-16)); // K32 vs K24 result = standardElo.Calculate(1600, 1500, 2300); Assert.That(result.WinnerDelta, Is.EqualTo(32)); Assert.That(result.LoserDelta, Is.EqualTo(-24)); // K32 vs K16 result = standardElo.Calculate(1600, 1600, 2402); Assert.That(result.WinnerDelta, Is.EqualTo(32)); Assert.That(result.LoserDelta, Is.EqualTo(-16)); // K24 vs K16 result = standardElo.Calculate(1600, 2100, 2400); Assert.That(result.WinnerDelta, Is.EqualTo(20)); Assert.That(result.LoserDelta, Is.EqualTo(-14)); // K32 Tie result = standardElo.Calculate(1600, 1600, 1800, true); Assert.That(result.WinnerDelta, Is.EqualTo(8)); Assert.That(result.LoserDelta, Is.EqualTo(-8)); }
public void RejectMatch(int boardId, int matchId, string userName) { // Used to match against match Loser profile for verification of rejection authority. var userProfile = _repository.UserProfiles.FindProfile(userName); var board = _repository.GetBoardById(boardId); bool adminRejection = false; if (userProfile == null) throw new InvalidOperationException("Can not find your profile."); // All unresolved matches for this challenge board. var unresolvedMatches = _repository.GetUnresolvedMatchesByBoardId(boardId).OrderBy(x => x.VerificationDeadline).ToList(); var rejectedMatch = unresolvedMatches.SingleOrDefault(x => x.MatchId == matchId); if (rejectedMatch == null) throw new ServiceException("Can not find match."); if(board.Owner.ProfileUserId == userProfile.UserId) // Board owner can reject anything adminRejection = true; else if (rejectedMatch.Loser.ProfileUserId != userProfile.UserId) // Loser can reject match throw new ServiceException("You are not able to reject this match."); if(rejectedMatch.IsResolved) throw new ServiceException("This match has already been resolved."); if (DateTime.Now > rejectedMatch.VerificationDeadline) throw new ServiceException("The deadline for rejecting this match has passed."); rejectedMatch.Rejected = true; rejectedMatch.Resolved = DateTime.Now; rejectedMatch.Winner.RejectionsReceived++; rejectedMatch.Loser.RejectionsGiven++; // Anonymous list of unresolve matches taking place after the rejected match. // * These are the matches we need to recalculate var matchList = unresolvedMatches.Select( x => new {x.MatchId, x.Created}) .Where(x => x.Created >= rejectedMatch.Created && x.MatchId != rejectedMatch.MatchId); IScoringSystem system = new StandardElo(); foreach (var match in matchList) { // Get unresolved matches prior to this one var filteredUnresolved = unresolvedMatches.Where(x => x.Created <= match.Created && x.MatchId != match.MatchId).ToList(); // Pick out the match to recalc and save var matchToRecalc = unresolvedMatches.First(x => x.MatchId == match.MatchId); // Figure unverified ratings. Parses and sums unverified matches var unverifiedWinnerRank = matchToRecalc.Winner.CalculateUnverifiedRank(filteredUnresolved); var unverifiedLoserRank = matchToRecalc.Loser.CalculateUnverifiedRank(filteredUnresolved); // Run the recalc var eloRecalc = system.Calculate(board.StartingRating, unverifiedWinnerRank, unverifiedLoserRank, matchToRecalc.Tied); // Update the ratings matchToRecalc.WinnerRatingDelta = eloRecalc.WinnerDelta.RoundToWhole(); matchToRecalc.LoserRatingDelta = eloRecalc.LoserDelta.RoundToWhole(); matchToRecalc.WinnerEstimatedRating = unverifiedWinnerRank + matchToRecalc.WinnerRatingDelta; matchToRecalc.LoserEstimatedRating = unverifiedLoserRank + matchToRecalc.LoserRatingDelta; } _repository.CommitChanges(); _mailService.SendEmail(rejectedMatch.Winner.Profile.EmailAddress, rejectedMatch.Winner.Profile.UserName, "Match Rejected", EmailType.MatchRejectionNotice, new MatchRejectionNotice { RejectorName = adminRejection ? "the board administrator" : rejectedMatch.Loser.Name, RejectedName = rejectedMatch.Winner.Name, BoardName = board.Name, BoardOwnerName = board.Owner.Name }); }
public Match GenerateMatch(int boardId, string winnerName, string loserName, bool tie = false) { var board = _repository.GetBoardByIdWithCompetitors(boardId); if(board == null) throw (new ServiceException("Can not find challenge board.")); if (DateTime.Now >= board.End) throw (new ServiceException("This challenge board has ended.")); var winner = board.Competitors.Active().FindCompetitorByName(winnerName); var loser = board.Competitors.Active().FindCompetitorByName(loserName); if(winner == null) throw (new ServiceException("You are not part of this challenge board.")); if (loser == null) throw (new ServiceException("Can not find opponent.")); if (loser.Name == winner.Name) throw (new ServiceException("You can't play yourself.")); var match = new Match { Board = board, Tied = tie, Winner = winner, Loser = loser, Created = DateTime.Now, VerificationDeadline = DateTime.Now.AddHours(board.AutoVerification) }; var unresolvedMatches = _repository.GetUnresolvedMatchesByBoardId(boardId, false).ToList(); // Figure unverified ratings. Parses and sums unverified matches var unverifiedWinnerRank = winner.CalculateUnverifiedRank(unresolvedMatches); var unverifiedLoserRank = loser.CalculateUnverifiedRank(unresolvedMatches); // Run scoring calculation IScoringSystem system = new StandardElo(); var eloResult = system.Calculate(board.StartingRating, unverifiedWinnerRank, unverifiedLoserRank, tie); match.WinnerRatingDelta = eloResult.WinnerDelta.RoundToWhole(); match.LoserRatingDelta = eloResult.LoserDelta.RoundToWhole(); match.WinnerEstimatedRating = unverifiedWinnerRank + match.WinnerRatingDelta; match.LoserEstimatedRating = unverifiedLoserRank + match.LoserRatingDelta; return (match); }