private int[,] GetPairwisePreferences(VoteStorage taskVotes) { int[,] pairwisePreferences = new int[taskVotes.Count, taskVotes.Count]; var choiceIndexes = GetChoicesIndexes(taskVotes.Keys); // Invert the votes so that we can look at preferences per user. var voterPreferences = taskVotes.SelectMany(v => v.Value).GroupBy(u => u.Key).ToDictionary(t => t.Key, s => s.Select(q => q.Value).ToHashSet()); foreach (var voter in voterPreferences) { // We want a list of everything each voter didn't vote for. var unrankedChoices1 = taskVotes.Keys.Except(voter.Value); foreach (var choice in voter.Value) { // Each choice matching or beating the ranks of other ranked choices is marked. foreach (var otherChoice in voter.Value) { if ((choice != otherChoice) && (choice.MarkerValue <= otherChoice.MarkerValue)) { pairwisePreferences[choiceIndexes[choice], choiceIndexes[otherChoice]]++; } } // Each choice is ranked higher than all unranked choices foreach (var nonChoice in unrankedChoices1) { pairwisePreferences[choiceIndexes[choice], choiceIndexes[nonChoice]]++; } } } return(pairwisePreferences); }
/// <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); }
CountVotesForTask(VoteStorage taskVotes) { var listOfChoices = taskVotes.Select(v => v.Key).ToList(); // Invert the votes so that we can look at preferences per user. var voterPreferences = taskVotes .SelectMany(v => v.Value) .GroupBy(u => u.Key) .ToDictionary(t => t.Key, s => s.Select(q => q.Value).OrderBy(r => r.MarkerValue).ToList()); int[,] pairwisePreferences = GetPairwisePreferences(voterPreferences, listOfChoices); int[,] pairwiseWinners = GetPairwiseWinners(pairwisePreferences, listOfChoices.Count); List <((int rank, double rankScore) ranking, VoteStorageEntry vote)> winningChoices = GetResultsInOrder(pairwiseWinners, listOfChoices, taskVotes); return(winningChoices); }