more info for election counting

This commit is contained in:
Jay Robson 2025-05-03 23:16:06 +10:00
parent b78fbde121
commit 05834a9691
3 changed files with 44 additions and 13 deletions

View File

@ -2,12 +2,12 @@ use std::collections::HashMap;
use itertools::Itertools; use itertools::Itertools;
use crate::candidate::Candidate; use crate::{candidate::Candidate, party::Party};
#[derive(Debug)] #[derive(Debug)]
pub struct Header { pub struct Header {
pub parties: Vec<String>, pub parties: Vec<Party>,
pub candidates: Vec<Candidate>, pub candidates: Vec<Candidate>,
} }
@ -29,6 +29,7 @@ impl Header {
}); });
} }
else if let Some(party_id) = parties_lookup.get(party).copied() { else if let Some(party_id) = parties_lookup.get(party).copied() {
header.parties[party_id].member_ids.push(header.candidates.len());
header.candidates.push(Candidate { header.candidates.push(Candidate {
name: name.to_owned(), name: name.to_owned(),
party_id: Some(party_id), party_id: Some(party_id),
@ -36,7 +37,7 @@ impl Header {
} }
else { else {
parties_lookup.insert(party, header.parties.len()); parties_lookup.insert(party, header.parties.len());
header.parties.push(name.to_owned()); header.parties.push(Party::new(name.to_owned()));
} }
} }

View File

@ -7,6 +7,7 @@ use itertools::Itertools;
pub mod candidate; pub mod candidate;
pub mod ballot; pub mod ballot;
pub mod header; pub mod header;
pub mod party;
mod counter; mod counter;
fn main() { fn main() {
@ -42,11 +43,11 @@ fn main() {
let ty = BallotType::Candidate; let ty = BallotType::Candidate;
let winner_count = 6; let winner_count = 6;
let names = match ty { let names = match ty {
BallotType::Party => counter.header.parties.clone(), BallotType::Party => counter.header.parties.iter().map(|v| v.name.clone()).collect_vec(),
BallotType::Candidate => counter.header.candidates.iter().map(|v| format!("{}: {}", BallotType::Candidate => counter.header.candidates.iter().map(|v| format!("{}: {}",
v.name, v.name,
v.party_id.map_or("IND", |id| &counter.header.parties[id]), v.party_id.map_or("IND", |id| &counter.header.parties[id].name),
)).collect(), )).collect_vec(),
}; };
let mut running = vec![true; names.len()]; let mut running = vec![true; names.len()];
let mut first = true; let mut first = true;
@ -61,11 +62,18 @@ fn main() {
print!("{name:?}"); print!("{name:?}");
} }
println!(); println!();
eprintln!("Running election rounds:");
for _ in 0..(running.len() - winner_count) { let mut scores: Vec<u32> = Vec::new();
let scores = counter.count_primaries(ty, &running);
let lowest = match scores.iter().copied().enumerate().filter(|&(i,_)| running[i]).min_by(|a, b| u32::cmp(&a.1, &b.1)) { for index in 0..(running.len() - winner_count) {
Some((index, _)) => index, scores = counter.count_primaries(ty, &running);
let (id_worst, score_worst) = match scores.iter().copied().enumerate().filter(|&(i,_)| running[i]).min_by(|a, b| u32::cmp(&a.1, &b.1)) {
Some(v) => v,
None => break
};
let (id_best, score_best) = match scores.iter().copied().enumerate().filter(|&(i,_)| running[i]).min_by(|a, b| u32::cmp(&b.1, &a.1)) {
Some(v) => v,
None => break, None => break,
}; };
let mut first = true; let mut first = true;
@ -80,14 +88,20 @@ fn main() {
print!("{score}"); print!("{score}");
} }
} }
running[lowest] = false; running[id_worst] = false;
println!(); println!();
eprintln!(" {index}:");
eprintln!(" Best: {} ({score_best})", names[id_best]);
eprintln!(" Worst: {} ({score_worst})", names[id_worst]);
} }
let winners = names.iter().enumerate().filter_map(|(index, name)| match running[index] { let winners = names.iter().enumerate().filter_map(|(index, name)| match running[index] {
true => Some(name.as_str()), true => Some((name.as_str(), scores[index])),
false => None, false => None,
}).collect_vec(); }).collect_vec();
eprintln!("Winners: {winners:?}"); eprintln!("Winners: {winners:#?}");
} }

View File

@ -0,0 +1,16 @@
#[derive(Debug)]
pub struct Party {
pub name: String,
pub member_ids: Vec<usize>,
}
impl Party {
pub fn new(name: String) -> Self {
Self {
name,
member_ids: Vec::new(),
}
}
}