/// <inheritdoc/> protected override void SetState(Candidate candidate, CandidateState.States state) { if (!candidateStates.ContainsKey(candidate)) { candidateStates[candidate] = new MeekCandidateState(); } base.SetState(candidate, state); // Set KeepFactor to 0 for losers as per B.3 if (new[] { CandidateState.States.defeated, CandidateState.States.withdrawn } .Contains(candidateStates[candidate].State)) { (candidateStates[candidate] as MeekCandidateState).KeepFactor = 0.0m; } }
/// <inheritdoc/> protected override void CountBallot(CountedBallot ballot) { decimal weight = 1.0m; List <Vote> votes = ballot.Votes.ToList(); // Ensure any newly-seen candidates are counted List <Candidate> c = ballot.Votes.Where(x => !candidateStates.Keys.Contains(x.Candidate)) .Select(x => x.Candidate).ToList(); InitializeCandidateStates(c); votes.Sort(); foreach (Vote v in votes) { MeekCandidateState cs = candidateStates[v.Candidate] as MeekCandidateState; if (cs is null) { throw new InvalidOperationException("candidateState contains objects that aren't of type MeekCandidateState"); } // Get value to transfer to this candidate, restricted to // the specified precision decimal value = weight * cs.KeepFactor; weight = RoundUp(weight); // Add this to the candidate's vote and remove from ballot's // weight. CountedBallot shows multiple identical ballots, so // we add that many ballots to the vote and decrease the weight // of all identical ballots by the value kept. cs.VoteCount += value * ballot.Count; weight -= value; // Do this until weight hits zero, or we run out of rankings. // Note: Already-elected candidates have keep factors between // 0 and 1; hopefuls all have 1; defeated will have 0. The // remaining voting power is either all transfered to the first // hopeful candidate or exhausted as the ballot runs out of // non-defeated candidates. // // We only hit 0 if a non-elected hopeful is on the ballot. if (weight <= 0.0m) { break; } } }