From a714ba6a90f44f1feba0e3ee4224908e761b5733 Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Wed, 9 Jun 2021 19:43:11 +1000 Subject: [PATCH] Correctly apportion votes in bulk exclusions --- src/stv/mod.rs | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/stv/mod.rs b/src/stv/mod.rs index e54358f..8cf09d5 100644 --- a/src/stv/mod.rs +++ b/src/stv/mod.rs @@ -964,6 +964,7 @@ where // Determine votes to transfer in this stage let mut votes = Vec::new(); let mut votes_remain; + let mut checksum = N::new(); match opts.exclusion { ExclusionMethod::SingleStage => { @@ -972,6 +973,11 @@ where let count_card = state.candidates.get_mut(excluded_candidate).unwrap(); votes.append(&mut count_card.parcels.concat()); //count_card.parcels.clear(); + + // Update votes + let votes_transferred = votes.iter().fold(N::new(), |acc, v| acc + &v.value); + checksum -= &votes_transferred; + count_card.transfer(&-votes_transferred); } votes_remain = false; } @@ -993,8 +999,10 @@ where let cand_votes = count_card.parcels.concat(); + let mut votes_transferred = N::new(); for vote in cand_votes.into_iter() { if &vote.value / &vote.ballot.orig_value == max_value { + votes_transferred += &vote.value; votes.push(vote); } else { remaining_votes.push(vote); @@ -1007,6 +1015,10 @@ where // Leave remaining votes with candidate (as one parcel) count_card.parcels = vec![remaining_votes]; + + // Update votes + checksum -= &votes_transferred; + count_card.transfer(&-votes_transferred); } } ExclusionMethod::ParcelsByOrder => { @@ -1018,11 +1030,14 @@ where let count_card = state.candidates.get_mut(excluded_candidates.first().unwrap()).unwrap(); votes = count_card.parcels.remove(0); votes_remain = count_card.parcels.len() > 0; + + // Update votes + let votes_transferred = votes.iter().fold(N::new(), |acc, v| acc + &v.value); + checksum -= &votes_transferred; + count_card.transfer(&-votes_transferred); } } - let mut checksum = N::new(); - if votes.len() > 0 { let value = &votes[0].value / &votes[0].ballot.orig_value; @@ -1060,16 +1075,6 @@ where } state.exhausted.transfer(&exhausted_transfers); checksum += exhausted_transfers; - - if votes_remain { - if excluded_candidates.len() == 1 { - // TODO: Handle >1 excluded candidate - // Subtract from candidate tally - let count_card = state.candidates.get_mut(excluded_candidates.first().unwrap()).unwrap(); - checksum -= &result.total_votes; - count_card.transfer(&-result.total_votes); - } - } } if !votes_remain { @@ -1077,7 +1082,7 @@ where for excluded_candidate in excluded_candidates.into_iter() { let count_card = state.candidates.get_mut(excluded_candidate).unwrap(); checksum -= &count_card.votes; - count_card.transfers = -count_card.votes.clone(); + count_card.transfers -= &count_card.votes; count_card.votes = N::new(); }