示例#1
0
        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));
        }
示例#2
0
        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.Started)
            {
                throw (new ServiceException("This challenge board start on " + board.Started.ToShortDateString() + "."));
            }
            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
            var 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);
        }
示例#3
0
        public void RejectMatch(int boardId, int matchId, string userName)
        {
            // Used to match against match Loser profile for verification of rejection authority.
            var competior = _repository.GetCompetitorByUserName(boardId, userName);
            var board     = _repository.GetBoardById(boardId);

            bool adminRejection = false;

            if (competior == 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.IsOwner(competior)) // Board owner can reject anything
            {
                adminRejection = true;
            }
            else if (rejectedMatch.DoesNotInvolve(competior)) // Participants have a say
            {
                throw new ServiceException("You are not able to modify 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.Invalidate(competior);

            // 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);

            var 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();

            if (rejectedMatch.Withdrawn)
            {
                _mailService.SendEmail(rejectedMatch.Loser.Profile.EmailAddress, rejectedMatch.Loser.Profile.UserName,
                                       "Match Withdrawn", EmailType.MatchWithdrawlNotice,
                                       new MatchWithdrawlNotice
                {
                    Withdrawer = rejectedMatch.Winner.Name,
                    Withdrawee = rejectedMatch.Loser.Name,
                    BoardName  = board.Name,
                });
            }
            else
            {
                _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
                });
            }
        }