/// <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> private (VoteStorageEntry vote, double score) GetWinningVote(VoteStorage votes) { var workingVotes = new VoteStorage(votes); int voterCount = workingVotes.SelectMany(a => a.Value).Distinct().Count(); int winCount = voterCount / 2 + 1; while (workingVotes.Count > 1) { // Invert the votes so that we can look at preferences per user. var voterPreferences = workingVotes .SelectMany(v => v.Value) .GroupBy(u => u.Key) .ToDictionary(t => t.Key, s => s.Select(q => q.Value).OrderBy(r => r.MarkerValue).ToList()); // Check to see if we have a winner. var(vote, count) = GetMostPreferredVote(voterPreferences); if (count >= winCount) { var fullVote = workingVotes.First(a => a.Key == vote); return(fullVote, count); } VoteLineBlock leastPreferredChoice; // If not, eliminate the least preferred option and try again. if (leastPreferredChecksFullVotes) { leastPreferredChoice = GetLeastPreferredChoice(workingVotes); } else { leastPreferredChoice = GetLeastPreferredChoice(voterPreferences); } workingVotes.Remove(leastPreferredChoice); } // If we get to here, the only option left has to win. return(workingVotes.First(), 1); }