diff --git a/src/counter.rs b/src/counter.rs index 7fbf7a4..0285da9 100644 --- a/src/counter.rs +++ b/src/counter.rs @@ -4,7 +4,7 @@ use crate::{ballot::Ballot, header::Header, score_item::{ScoreItem, ScoreItems}} #[derive(Debug)] pub enum Event { - Lose(ScoreItem), + Lose(Vec), Win(Vec), } @@ -61,26 +61,42 @@ impl Iterator for Counter { fn next(&mut self) -> Option { let mut winners = Vec::::with_capacity(self.enabled.len()); - let primaries = self.count_primaries().collect_vec(); - let mut lowest = *primaries.first()?; + let mut losers = Vec::::with_capacity(self.enabled.len()); + let mut primaries = self.count_primaries().collect_vec(); + primaries.sort_by(|a, b| a.cmp(b)); + + let &lowest = primaries.first()?; + let &highest = primaries.last()?; + let mut lose_total = 0.0; for &score in primaries.iter() { - lowest = lowest.min(score); if score.value >= self.quota { winners.push(score); } + if lose_total + score.value < highest.value { + lose_total += score.value; + losers.push(score); + } } if primaries.len() == 1 && self.winners_left == 1 { - self.enabled[lowest.index] = false; - return Some(Event::Win(vec![lowest])); + self.enabled[highest.index] = false; + return Some(Event::Win(vec![highest])); + } + + if losers.len() == 0 { + losers.push(lowest); } if winners.len() == 0 { - self.enabled[lowest.index] = false; - return Some(Event::Lose(lowest)); + for score in losers.iter() { + self.enabled[score.index] = false; + } + return Some(Event::Lose(losers)); } + winners.sort_by(|a,b| b.cmp(a)); + for ballot in self.ballots.iter_mut() { let index = match ballot.get_primary_index(|id| self.enabled[id]) { Some(v) => v, diff --git a/src/main.rs b/src/main.rs index db257c9..e9990a3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -36,16 +36,18 @@ fn main() { for (index, event) in (1..).zip(counter) { match event { - counter::Event::Win(mut v) => { + counter::Event::Win(v) => { eprintln!(" {index}: Win:"); - v.sort_by(|a,b| b.cmp(a)); for winner in v.iter() { eprintln!(" - {}, {}, {}", header.get_candidate_name(winner.index), winner.value, Percent(winner.value, total)); } winners.extend_from_slice(&v); } counter::Event::Lose(v) => { - eprintln!(" {index}: Lose: {}, {}, {}", header.get_candidate_name(v.index), v.value, Percent(v.value, total)); + eprintln!(" {index}: Lose:"); + for loser in v.iter() { + eprintln!(" - {}, {}, {}", header.get_candidate_name(loser.index), loser.value, Percent(loser.value, total)); + } } } }