made it so multiple candidates can lose in 1 round

This commit is contained in:
Jay Robson 2025-05-06 21:08:26 +10:00
parent 101db55d04
commit 96f1775004
2 changed files with 29 additions and 11 deletions

View File

@ -4,7 +4,7 @@ use crate::{ballot::Ballot, header::Header, score_item::{ScoreItem, ScoreItems}}
#[derive(Debug)]
pub enum Event {
Lose(ScoreItem),
Lose(Vec<ScoreItem>),
Win(Vec<ScoreItem>),
}
@ -61,26 +61,42 @@ impl Iterator for Counter {
fn next(&mut self) -> Option<Self::Item> {
let mut winners = Vec::<ScoreItem>::with_capacity(self.enabled.len());
let primaries = self.count_primaries().collect_vec();
let mut lowest = *primaries.first()?;
let mut losers = Vec::<ScoreItem>::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,

View File

@ -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));
}
}
}
}