コード例 #1
0
ファイル: VoteCounter.cs プロジェクト: MizMahem/NetTally
        /// <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);
        }
コード例 #2
0
        public UndoAction(UndoActionType actionType, VoteStorage currentState,
                          VoteLineBlock?storageVote = null)
        {
            ActionType = actionType;

            // Clone the current vote repository.
            storage = new VoteStorage(currentState);

            // Utilize a cloned storage vote if we need to track a changed VoteLineBlock
            // that had internal properties changed.  Otherwise those will be propogated
            // to our storage collection.
            if (storageVote != null)
            {
                var storedVote = storageVote.Clone();
                storage.TryGetValue(storageVote, out var storedVoteSupporters);
                storage.Remove(storageVote);
                storage.Add(storedVote, storedVoteSupporters);
            }
        }
コード例 #3
0
        /// <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);
        }
コード例 #4
0
        CountVotesForTask(VoteStorage taskVotes)
        {
            int r = 1;

            List <((int rank, double rankScore) ranking, VoteStorageEntry vote)> resultList
                = new List <((int rank, double rankScore) ranking, VoteStorageEntry vote)>();

            var workingVotes = new VoteStorage(taskVotes);

            while (workingVotes.Count > 0)
            {
                var(vote, score) = GetWinningVote(workingVotes);

                resultList.Add(((r++, score), vote));

                workingVotes.Remove(vote.Key);
            }

            return(resultList);
        }
コード例 #5
0
ファイル: VoteCounter.cs プロジェクト: MizMahem/NetTally
        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));
        }
コード例 #6
0
ファイル: VoteCounter.cs プロジェクト: MizMahem/NetTally
        /// <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);
        }
コード例 #7
0
ファイル: VoteCounter.cs プロジェクト: MizMahem/NetTally
        /// <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));
        }