/// <summary> /// Gets the winning vote. /// Excludes any already chosen votes from the process. /// </summary> /// <param name="voterRankings">The voter rankings.</param> /// <param name="chosenChoices">The already chosen choices.</param> /// <returns>Returns the winning vote.</returns> /// <exception cref="System.ArgumentNullException"> /// </exception> private RankResult GetWinningVote(IEnumerable <VoterRankings> voterRankings, RankResults chosenChoices) { if (voterRankings == null) { throw new ArgumentNullException(nameof(voterRankings)); } if (chosenChoices == null) { throw new ArgumentNullException(nameof(chosenChoices)); } // Initial conversion from enumerable to list List <VoterRankings> localRankings = RemoveChoicesFromVotes(voterRankings, chosenChoices.Select(c => c.Option)); int voterCount = localRankings.Count(); int winCount = voterCount / 2 + 1; string eliminated = ""; bool eliminateOne = false; while (true) { var preferredVotes = GetPreferredCounts(localRankings); if (!preferredVotes.Any()) { break; } ChoiceCount best = preferredVotes.MaxObject(a => a.Count); if (best.Count >= winCount) { return(new RankResult(best.Choice, $"Baldwin Eliminations: [{eliminated}]")); } // If no more choice removals will bump up lower prefs to higher prefs, return the best of what's left. if (!localRankings.Any(r => r.RankedVotes.Count() > 1)) { return(new RankResult(best.Choice, $"Baldwin Eliminations: [{eliminated}]")); } string leastPreferredChoice = GetLeastPreferredChoice(localRankings); eliminated += Comma(eliminateOne) + leastPreferredChoice; RemoveChoiceFromVotes(localRankings, leastPreferredChoice); eliminateOne = true; } return(null); }
/// <summary> /// Gets the winning vote, instant runoff style. /// </summary> /// <param name="voterRankings">The voters' rankings.</param> /// <param name="chosenChoices">The already chosen choices that we should exclude.</param> /// <returns>Returns the winning vote, if any. Otherwise, null.</returns> /// <exception cref="System.ArgumentNullException"> /// </exception> private RankResult GetWinningVote(IEnumerable <VoterRankings> voterRankings, RankResults chosenChoices) { if (voterRankings == null) { throw new ArgumentNullException(nameof(voterRankings)); } if (chosenChoices == null) { throw new ArgumentNullException(nameof(chosenChoices)); } List <VoterRankings> localRankings = RemoveChoicesFromVotes(voterRankings, chosenChoices.Select(c => c.Option)); int voterCount = localRankings.Count(v => v.RankedVotes.Any()); int winCount = voterCount / 2 + 1; string eliminated = ""; bool eliminateOne = false; while (true) { var preferredVotes = GetPreferredCounts(localRankings); if (!preferredVotes.Any()) { break; } var best = preferredVotes.MaxObject(a => a.Count); if (best.Count >= winCount) { return(new RankResult(best.Choice, $"IRV Eliminations: [{eliminated}]")); } var worst = preferredVotes.MinObject(a => a.Count); eliminated += Comma(eliminateOne) + worst.Choice; RemoveChoiceFromVotes(localRankings, worst.Choice); eliminateOne = true; } return(null); }