/// <summary> /// Wrapper for handling replace task, but without adding to merge records. /// </summary> /// <param name="vote">The vote being modified.</param> /// <param name="task">The new task to apply to the vote.</param> /// <returns>Returns true if the task replacement was successfully completed.</returns> private bool ReplaceTaskImplWrapper(VoteLineBlock vote, string task) { if (!VoteStorage.TryGetValue(vote, out var supporters)) { return(false); } // Incoming parameter may be an entry in storage, or a copy of a vote. // Adjust so that we're always pointing at an actual vote. // If the vote isn't found in VoteStorage, just use the one provided. vote = VoteStorage.GetVoteMatching(vote) ?? vote; // Remove the version of the vote we're starting with. VoteStorage.Remove(vote); string originalTask = vote.Task; vote.Task = task; // If there's a conflict with the newly-tasked vote, we need to merge with the existing vote. if (VoteStorage.ContainsKey(vote)) { if (VoteStorage.TryGetValue(vote, out var toSupport)) { foreach (var(supporterName, supporterVote) in supporters) { if (!toSupport.ContainsKey(supporterName)) { supporterVote.Task = task; toSupport.Add(supporterName, supporterVote); } } } else { // Undo the attempt if we couldn't get the conflicting vote data vote.Task = originalTask; VoteStorage.Add(vote, supporters); return(false); } } // If there's no conflict, update the tasks in the supporter votes and add the revised vote. else { foreach (var(_, supporterVote) in supporters) { supporterVote.Task = task; } VoteStorage.Add(vote, supporters); } return(true); }
CountVotesForTask(VoteStorage taskVotes) { int[,] pairwisePreferences = GetPairwisePreferences(taskVotes); int[,] strongestPaths = GetStrongestPaths(pairwisePreferences, taskVotes.Count); int[,] winningPaths = GetWinningPaths(strongestPaths, taskVotes.Count); List <((int rank, double rankScore) ranking, VoteStorageEntry vote)> winningChoices = GetResultsInOrder(winningPaths, taskVotes); return(winningChoices); }
/// <summary> /// Reset all tracking variables. /// </summary> public void Reset() { VoteStorage.Clear(); ReferenceOrigins.Clear(); ReferencePlans.Clear(); FutureReferences.Clear(); UndoBuffer.Clear(); VoteDefinedTasks.Clear(); OrderedVoteTaskList.Clear(); TaskList.Clear(); OnPropertyChanged("VoteCounter"); OnPropertyChanged("Tasks"); }
private bool SplitImplWrapper(VoteLineBlock fromVote, List <VoteLineBlock> toVotes) { if (!VoteStorage.TryGetValue(fromVote, out var fromSupport)) { return(false); } foreach (var toVote in toVotes) { if (!VoteStorage.TryGetValue(toVote, out var toSupport)) { return(false); } MergeImpl(fromVote, toVote, fromSupport, toSupport); } // But we still want to remove the from vote. return(VoteStorage.Remove(fromVote)); }
/// <summary> /// Add a collection of votes to the vote counter. /// </summary> /// <param name="votePartitions">A string list of all the parts of the vote to be added.</param> /// <param name="voter">The voter for this vote.</param> /// <param name="postID">The post ID for this vote.</param> /// <param name="voteType">The type of vote being added.</param> public void AddVotes(IEnumerable <VoteLineBlock> votePartitions, Origin voter) { if (!votePartitions.Any()) { return; } // Remove the voter from any existing votes VoteStorage.RemoveVoterFromVotes(voter); // Add/update all segments of the provided vote foreach (var partition in votePartitions) { VoteStorage.AddSupporterToVote(partition, voter); AddPotentialVoteTask(partition.Task); } // Cleanup any votes that no longer have any support VoteStorage.RemoveUnsupportedVotes(); }
CountVotesForTask(VoteStorage taskVotes) { var results = from vote in taskVotes let wilsonScore = RankingCalculations.LowerWilsonRankingScore(vote) select new { vote, score = wilsonScore }; var orderedResults = results.OrderByDescending(a => a.score.score) .ThenByDescending(a => a.score.count); int r = 1; List <((int rank, double rankScore) ranking, VoteStorageEntry vote)> resultList = new List <((int rank, double rankScore) ranking, VoteStorageEntry vote)>(); foreach (var res in orderedResults) { resultList.Add(((r++, res.score.score), res.vote)); } return(resultList); }
/// <summary> /// Delete an entire vote and all associated supporters. /// </summary> /// <param name="vote">The vote to delete.</param> /// <returns>Returns true if successfully completed.</returns> public bool Delete(VoteLineBlock vote) { bool removed = false; if (VoteStorage.ContainsKey(vote)) { UndoBuffer.Push(new UndoAction(UndoActionType.Delete, VoteStorage)); removed = VoteStorage.Remove(vote); } if (removed) { OnPropertyChanged("Votes"); OnPropertyChanged("Voters"); OnPropertyChanged(nameof(HasUndoActions)); } else { UndoBuffer.Pop(); } return(removed); }
/// <summary> /// The wrapper handles the process of extracting the vote support from /// the storage before passing the pieces on to the implementation. /// </summary> /// <param name="fromVote">The vote being merged.</param> /// <param name="toVote">The vote being merged into.</param> /// <returns>Returns true if there was a successful merge.</returns> private bool MergeImplWrapper(VoteLineBlock fromVote, VoteLineBlock toVote) { if (fromVote == toVote) { return(false); } if (!VoteStorage.TryGetValue(fromVote, out var fromSupport)) { return(false); } if (!VoteStorage.TryGetValue(toVote, out var toSupport)) { return(false); } // Theoretically, all the supporters in the from vote could already // be in the to vote, in which case no merging would happen. MergeImpl(fromVote, toVote, fromSupport, toSupport); // But we still want to remove the from vote. return(VoteStorage.Remove(fromVote)); }
public bool Join(List <Origin> voters, Origin voterToJoin) { bool joined = false; UndoBuffer.Push(new UndoAction(UndoActionType.Join, VoteStorage)); foreach (var voter in voters) { joined = JoinImpl(voter, voterToJoin) || joined; } if (joined) { OnPropertyChanged("Votes"); OnPropertyChanged("Voters"); OnPropertyChanged(nameof(HasUndoActions)); } else { UndoBuffer.Pop(); } return(joined); /// <summary> /// Implement joining logic per voter. /// </summary> /// <param name="joiningVoter">The voter being moved to a new voting support set.</param> /// <param name="voterToJoin">The voter being joined.</param> /// <returns>Returns true if the join was completed.</returns> bool JoinImpl(Origin joiningVoter, Origin voterToJoin) { var source = GetVotesBy(joiningVoter); var dest = GetVotesBy(voterToJoin); if (!source.Any() || !dest.Any()) { return(false); } bool joined = false; // Remove support from any votes where the target voter isn't also present. foreach (var vote in source) { if (!VoteStorage.DoesVoterSupportVote(voterToJoin, vote)) { VoteStorage.RemoveSupporterFromVote(vote, joiningVoter); } } VoteStorage.RemoveUnsupportedVotes(); foreach (var vote in dest) { if (!VoteStorage.DoesVoterSupportVote(joiningVoter, vote)) { VoteStorage.AddSupporterToVote(vote, joiningVoter); joined = true; } } return(joined); } }
/// <summary> /// Gets all voters that are supporting the specified vote. /// </summary> /// <param name="vote">The vote to check on.</param> /// <returns>Returns an IEnumerable of the voter names that are supporting the given vote.</returns> public IEnumerable <Origin> GetVotersFor(VoteLineBlock vote) => VoteStorage.GetVotersFor(vote);
/// <summary> /// Get a list of all known voters. /// </summary> /// <returns>Returns an IEnumerable of the registered reference voters.</returns> public IEnumerable <Origin> GetAllVoters() => VoteStorage.GetAllVoters();
/// <summary> /// Get a collection of all the votes that currently have supporters. /// </summary> /// <returns>Returns an IEnumerable of the currently stored vote blocks.</returns> public IEnumerable <VoteLineBlock> GetAllVotes() => VoteStorage.GetAllVotes();
/// <summary> /// Get a list of all vote blocks supported by a specified voter (which may be a plan name). /// </summary> /// <param name="voterName">The name of the voter or plan being requested.</param> /// <returns>Returns a list of all vote blocks supported by the specified voter or plan.</returns> public List <VoteLineBlock> GetVotesBy(Origin voter) => VoteStorage.GetVotesBy(voter);