public Participant PickWinner(Participant[] participants) { var odds = participants.Select(el => el.Odd).ToArray(); var totalMargin = MarginCalculator.Calculate(odds); var participantTicketsRangeLength = participants.Select(el => (int)Math.Round(el.Odd.ToPercentageOdds() / totalMargin * 10000D)).ToArray(); var participantTicketsBounds = new List <(int lowerBound, int upperBound)>(); var lowerBound = 0; for (var i = 0; i < participants.Length; i++) { var upperBound = lowerBound + participantTicketsRangeLength[i]; participantTicketsBounds.Add((lowerBound, upperBound)); lowerBound = upperBound + 1; } var winnerTicket = randomizer.Next(participantTicketsBounds[participants.Length - 1].upperBound); var winnerIndex = participantTicketsBounds.FindIndex(el => el.lowerBound <= winnerTicket && el.upperBound >= winnerTicket); return(participants[winnerIndex]); }
public Participant DoRace() { var odds = _participants.Values.Select(el => el.Odd).ToArray(); var totalMargin = MarginCalculator.Calculate(odds); if (totalMargin < 110.00D) { throw new TotalMarginDeficitException(); } return(_winnerCalculator.PickWinner(_participants.Values.ToArray())); }
public void AddParticipant(Participant participant) { if (_participants.ContainsKey(participant.Name)) { throw new ParticipantAlreadyAddedException(); } var odds = _participants.Values.Select(el => el.Odd).Append(participant.Odd).ToArray(); var totalMargin = MarginCalculator.Calculate(odds); if (totalMargin > 140.00D) { throw new TotalMarginOverloadException(); } _participants[participant.Name] = participant; }