/// <summary> /// Implementation to generate the ranking list for the provided set /// of votes for a specific task. /// </summary> /// <param name="task">The task that the votes are grouped under.</param> /// <returns>Returns a ranking list of winning votes.</returns> protected override RankResults RankTask(GroupedVotesByTask task) { RankResults winningChoices = new RankResults(); // The groupVotes are used for getting the Wilson score var rankedVotes = GroupRankVotes.GroupByVoteAndRank(task); // The voterRankings are used for the runoff var voterRankings = GroupRankVotes.GroupByVoterAndRank(task); // The full choices list is just to keep track of how many we have left. var allChoices = GroupRankVotes.GetAllChoices(voterRankings); for (int i = 1; i <= 9; i++) { RankResult winner = GetWinningVote(voterRankings, rankedVotes); if (winner == null) { break; } winningChoices.Add(winner); allChoices.Remove(winner.Option); if (!allChoices.Any()) { break; } voterRankings = RemoveChoiceFromVotes(voterRankings, winner.Option); rankedVotes = RemoveChoiceFromRanks(rankedVotes, winner.Option); } return(winningChoices); }
/// <summary> /// Gets the least preferred choice. /// This is normally determined by selecting the option with the lowest Borda count. /// This is inverted because we don't want to convert ranks to Borda values (it gains us nothing). /// It then needs to be averaged across the number of instances of each vote, to /// account for unranked options. This allows apples-to-apples comparisons against options /// that are ranked in all votes. /// We then need to scale it relative to the number of instances of that option appearing, to deal /// with truncated rankings (where there are more options than rankings allowed). /// An option ranked infrequently can be scaled up relative to its rate of occurance for /// a high likelihood of elimination. /// </summary> /// <param name="localRankings">The vote rankings.</param> /// <returns>Returns the vote string for the least preferred vote.</returns> private static string GetLeastPreferredChoice(List <VoterRankings> localRankings) { var groupVotes = GroupRankVotes.GroupByVoteAndRank(localRankings); var rankedVotes = from vote in groupVotes select new { Vote = vote.VoteContent, Rank = RankScoring.LowerWilsonScore(vote.Ranks) }; var worstVote = rankedVotes.MinObject(a => a.Rank); Debug.Write($"({worstVote.Rank:f5}) {worstVote.Vote}"); return(worstVote.Vote); }
/// <summary> /// Implementation to generate the ranking list for the provided set /// of votes for a specific task. /// </summary> /// <param name="task">The task that the votes are grouped under.</param> /// <returns>Returns a ranking list of winning votes.</returns> protected override RankResults RankTask(GroupedVotesByTask task) { var groupVotes = GroupRankVotes.GroupByVoteAndRank(task); var rankedVotes = from vote in groupVotes select new { Vote = vote.VoteContent, Rank = RankVote(vote.Ranks) }; var orderedVotes = rankedVotes.OrderByDescending(a => a.Rank); RankResults results = new RankResults(); results.AddRange(orderedVotes.Select(a => new RankResult(a.Vote, $"BordaRank: [{a.Rank}]"))); return(results); }
/// <summary> /// Implementation to generate the ranking list for the provided set /// of votes for a specific task. /// </summary> /// <param name="task">The task that the votes are grouped under.</param> /// <returns>Returns a ranking list of winning votes.</returns> protected override RankResults RankTask(GroupedVotesByTask task) { // Can calculating the score easily by having all the rankings for // each vote grouped together. var groupVotes = GroupRankVotes.GroupByVoteAndRank(task); var rankedVotes = from vote in groupVotes select new { Vote = vote.VoteContent, Rank = RankScoring.LowerWilsonScore(vote.Ranks) }; var orderedVotes = rankedVotes.OrderByDescending(a => a.Rank); RankResults results = new RankResults(); results.AddRange(orderedVotes.Select(a => new RankResult(a.Vote, $"Wilson: [{a.Rank:f5}]"))); return(results); }
/// <summary> /// Implementation to generate the ranking list for the provided set /// of votes for a specific task. /// </summary> /// <param name="task">The task that the votes are grouped under.</param> /// <returns>Returns a ranking list of winning votes.</returns> protected override RankResults RankTask(GroupedVotesByTask task) { Debug.WriteLine(">>Normalized Borda Counting<<"); //var voterCount = task.SelectMany(t => t.Value).Distinct().Count(); var groupVotes = GroupRankVotes.GroupByVoteAndRank(task); var rankedVotes = from vote in groupVotes select new { Vote = vote.VoteContent, Rank = RankVote(vote.Ranks) }; var orderedVotes = rankedVotes.OrderBy(a => a.Rank); RankResults results = new RankResults(); results.AddRange(orderedVotes.Select(a => new RankResult(a.Vote, $"BordaNorm: [{a.Rank:f5}]"))); return(results); }