From 99724e550451a7747efa12fe5cf679c1dbfea042 Mon Sep 17 00:00:00 2001 From: Jay Robson Date: Sat, 3 May 2025 21:40:08 +1000 Subject: [PATCH] improve ballot parse function --- src/ballot.rs | 71 +++++++++++++++++++++++--------------------------- src/counter.rs | 7 ++++- src/main.rs | 3 +-- 3 files changed, 39 insertions(+), 42 deletions(-) diff --git a/src/ballot.rs b/src/ballot.rs index 3910835..04f5d76 100644 --- a/src/ballot.rs +++ b/src/ballot.rs @@ -22,54 +22,47 @@ pub struct Ballot { } impl Ballot { - pub fn parse_rows(csv: quick_csv::Csv, header: &Header) -> Result, Box> { - let mut ballots = Vec::::new(); + pub fn parse(row: quick_csv::Row, header: &Header) -> Result> { + let mut cols = row.columns()?; + + let (state, division, collection_point, collection_point_id, batch_id, paper_id) = cols.next_tuple().ok_or("Missing columns")?; + let cols = cols.collect_vec(); + let mut votes: Vec>; + let ty: BallotType; let col_filter = |(index, place): (usize, &str)| match place.parse::() { Ok(v) => Some((index, v - 1)), Err(_) => None, }; - for result in csv { - let row = result?; - let mut cols = row.columns()?; - - let (state, division, collection_point, collection_point_id, batch_id, paper_id) = cols.next_tuple().ok_or("Missing columns")?; - let cols = cols.collect_vec(); - let mut votes: Vec>; - let ty: BallotType; - - // below the line votes - if cols.len() > header.parties.len() { - ty = BallotType::Candidate; - votes = vec![None; header.candidates.len()]; - for (col_id, place) in cols.iter().copied().skip(header.parties.len()).take(header.candidates.len()).enumerate().filter_map(col_filter) { - votes[place] = Some(col_id); - } + // below the line votes + if cols.len() > header.parties.len() { + ty = BallotType::Candidate; + votes = vec![None; header.candidates.len()]; + for (col_id, place) in cols.iter().copied().skip(header.parties.len()).take(header.candidates.len()).enumerate().filter_map(col_filter) { + votes[place] = Some(col_id); } - - // above the line votes - else { - ty = BallotType::Party; - votes = vec![None; header.parties.len()]; - for (col_id, place) in cols.iter().copied().take(header.parties.len()).enumerate().filter_map(col_filter) { - votes[place] = Some(col_id); - } - } - - ballots.push(Ballot { - state: state.to_owned(), - division: division.to_owned(), - collection_point: collection_point.to_owned(), - collection_point_id: collection_point_id.parse()?, - batch_id: batch_id.parse()?, - paper_id: paper_id.parse()?, - votes: votes.iter().copied().filter_map(|v| v).collect(), - ty, - }); } - Ok(ballots) + // above the line votes + else { + ty = BallotType::Party; + votes = vec![None; header.parties.len()]; + for (col_id, place) in cols.iter().copied().take(header.parties.len()).enumerate().filter_map(col_filter) { + votes[place] = Some(col_id); + } + } + + Ok(Ballot { + state: state.to_owned(), + division: division.to_owned(), + collection_point: collection_point.to_owned(), + collection_point_id: collection_point_id.parse()?, + batch_id: batch_id.parse()?, + paper_id: paper_id.parse()?, + votes: votes.iter().copied().filter_map(|v| v).collect(), + ty, + }) } } diff --git a/src/counter.rs b/src/counter.rs index a7c95e2..4fa1118 100644 --- a/src/counter.rs +++ b/src/counter.rs @@ -10,7 +10,11 @@ pub struct Counter { impl Counter { pub fn new(mut csv: quick_csv::Csv) -> Result> { let header = Header::parse(csv.next().ok_or("csv header missing")??)?; - let ballots = Ballot::parse_rows(csv, &header)?; + let mut ballots = Vec::new(); + + for row in csv { + ballots.push(Ballot::parse(row?, &header)?); + } Ok(Counter { header, @@ -18,5 +22,6 @@ impl Counter { }) } + } diff --git a/src/main.rs b/src/main.rs index 8615295..c2a06fe 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,8 +1,7 @@ use std::env; -use ballot::{Ballot, BallotType}; +use ballot::BallotType; use counter::Counter; -use header::Header; pub mod candidate; pub mod ballot;