From 5189a7401071629af5b011cc8d4b5c61322125e7 Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Sun, 30 May 2021 18:27:28 +1000 Subject: [PATCH] Fix bug when excluding candidate with 0 votes --- src/stv/mod.rs | 88 ++++++++++++++++++++++++++------------------------ 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/src/stv/mod.rs b/src/stv/mod.rs index 901aabd..3cd5134 100644 --- a/src/stv/mod.rs +++ b/src/stv/mod.rs @@ -445,53 +445,57 @@ where panic!("Invalid --exclusion"); } - let value = &votes[0].value / &votes[0].ballot.orig_value; - - // Count next preferences - let result = next_preferences(state, votes); - - if opts.exclusion == "one_round" { - state.logger.log_literal(format!("Transferring {:.0} ballot papers, totalling {:.2} votes.", result.total_ballots, result.total_votes)); - } else if opts.exclusion == "by_value" { - state.logger.log_literal(format!("Transferring {:.0} ballot papers, totalling {:.2} votes, received at value {:.2}.", result.total_ballots, result.total_votes, value)); - } - - // Transfer candidate votes let mut checksum = N::new(); - for (candidate, entry) in result.candidates.into_iter() { - let parcel = entry.votes as Parcel; - let count_card = state.candidates.get_mut(candidate).unwrap(); - count_card.parcels.push(parcel); + if votes.len() > 0 { + let value = &votes[0].value / &votes[0].ballot.orig_value; - // Round transfers - let mut candidate_transfers = entry.num_votes; - if let Some(dps) = opts.round_votes { - candidate_transfers.floor_mut(dps); + // Count next preferences + let result = next_preferences(state, votes); + + if opts.exclusion == "one_round" { + state.logger.log_literal(format!("Transferring {:.0} ballot papers, totalling {:.2} votes.", result.total_ballots, result.total_votes)); + } else if opts.exclusion == "by_value" { + state.logger.log_literal(format!("Transferring {:.0} ballot papers, totalling {:.2} votes, received at value {:.2}.", result.total_ballots, result.total_votes, value)); } - count_card.transfer(&candidate_transfers); - checksum += candidate_transfers; - } - - // Transfer exhausted votes - let parcel = result.exhausted.votes as Parcel; - state.exhausted.parcels.push(parcel); - - let mut exhausted_transfers = result.exhausted.num_votes; - if let Some(dps) = opts.round_votes { - exhausted_transfers.floor_mut(dps); - } - state.exhausted.transfer(&exhausted_transfers); - checksum += exhausted_transfers; - - if votes_remaining > 0 { - // Subtract from candidate tally - let count_card = state.candidates.get_mut(excluded_candidate).unwrap(); - checksum -= &result.total_votes; - count_card.transfer(&-result.total_votes); - // By definition, there is no loss by fraction - } else { + // Transfer candidate votes + for (candidate, entry) in result.candidates.into_iter() { + let parcel = entry.votes as Parcel; + let count_card = state.candidates.get_mut(candidate).unwrap(); + count_card.parcels.push(parcel); + + // Round transfers + let mut candidate_transfers = entry.num_votes; + if let Some(dps) = opts.round_votes { + candidate_transfers.floor_mut(dps); + } + count_card.transfer(&candidate_transfers); + checksum += candidate_transfers; + } + + // Transfer exhausted votes + let parcel = result.exhausted.votes as Parcel; + state.exhausted.parcels.push(parcel); + + let mut exhausted_transfers = result.exhausted.num_votes; + if let Some(dps) = opts.round_votes { + exhausted_transfers.floor_mut(dps); + } + state.exhausted.transfer(&exhausted_transfers); + checksum += exhausted_transfers; + + if votes_remaining > 0 { + // Subtract from candidate tally + let count_card = state.candidates.get_mut(excluded_candidate).unwrap(); + checksum -= &result.total_votes; + count_card.transfer(&-result.total_votes); + + // By definition, there is no loss by fraction + } + } + + if votes_remaining == 0 { // Finalise candidate votes let count_card = state.candidates.get_mut(excluded_candidate).unwrap(); checksum -= &count_card.votes;