diff --git a/.gitignore b/.gitignore index ea8c4bf..4755657 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /target +/results.csv diff --git a/src/counter.rs b/src/counter.rs index 4fa1118..f815bb0 100644 --- a/src/counter.rs +++ b/src/counter.rs @@ -1,4 +1,4 @@ -use crate::{ballot::Ballot, header::Header}; +use crate::{ballot::{Ballot, BallotType}, header::Header}; #[derive(Debug)] @@ -22,6 +22,24 @@ impl Counter { }) } + pub fn count_primaries(&self, ty: BallotType, running: &[bool]) -> Vec { + let mut scores = vec![0; running.len()]; + + for ballot in self.ballots.iter() { + if ballot.ty != ty { + continue; + } + for &id in ballot.votes.iter() { + if !running[id] { + continue; + } + scores[id] += 1; + break; + } + } + + scores + } } diff --git a/src/main.rs b/src/main.rs index c2a06fe..433bbc4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -2,6 +2,7 @@ use std::env; use ballot::BallotType; use counter::Counter; +use itertools::Itertools; pub mod candidate; pub mod ballot; @@ -20,8 +21,8 @@ fn main() { let csv = quick_csv::Csv::from_file(csv_path).unwrap().flexible(true); let counter = Counter::new(csv).unwrap(); - println!("Parties: {}", counter.header.parties.len()); - println!("Candidates: {}", counter.header.candidates.len()); + eprintln!("Parties: {}", counter.header.parties.len()); + eprintln!("Candidates: {}", counter.header.candidates.len()); let total = counter.ballots.len() as u32; let mut total_atl = 0u32; @@ -34,8 +35,59 @@ fn main() { } += 1; } - println!("Above the line: {total_atl} {}%", f64::from(total_atl) / f64::from(total) * 100.0); - println!("Below the line: {total_btl} {}%", f64::from(total_btl) / f64::from(total) * 100.0); - println!("Total: {total}"); + eprintln!("Above the line: {total_atl} {}%", f64::from(total_atl) / f64::from(total) * 100.0); + eprintln!("Below the line: {total_btl} {}%", f64::from(total_btl) / f64::from(total) * 100.0); + eprintln!("Total: {total}"); + + let ty = BallotType::Candidate; + let winner_count = 6; + let names = match ty { + BallotType::Party => counter.header.parties.clone(), + BallotType::Candidate => counter.header.candidates.iter().map(|v| format!("{}: {}", + v.name, + v.party_id.map_or("IND", |id| &counter.header.parties[id]), + )).collect(), + }; + let mut running = vec![true; names.len()]; + let mut first = true; + + for name in names.iter() { + if first { + first = false; + } + else { + print!(","); + } + print!("{name:?}"); + } + println!(); + + for _ in 0..(running.len() - winner_count) { + 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)) { + Some((index, _)) => index, + None => break, + }; + let mut first = true; + for (&score, &running) in scores.iter().zip(running.iter()) { + if first { + first = false; + } + else { + print!(","); + } + if running { + print!("{score}"); + } + } + running[lowest] = false; + println!(); + } + + let winners = names.iter().enumerate().filter_map(|(index, name)| match running[index] { + true => Some(name.as_str()), + false => None, + }).collect_vec(); + eprintln!("Winners: {winners:?}"); } diff --git a/src/party.rs b/src/party.rs new file mode 100644 index 0000000..e69de29