ballot-counter/src/header.rs

56 lines
1.4 KiB
Rust

use std::{collections::HashMap, rc::Rc};
use itertools::Itertools;
use crate::{candidate::{Candidate, CandidateName}, party::Party};
#[derive(Debug)]
pub struct Header {
pub parties: Vec<Party>,
pub candidates: Vec<Candidate>,
pub winners: usize,
}
impl Header {
pub fn parse(row: quick_csv::Row, winners: usize) -> Result<Rc<Header>, Box<dyn std::error::Error>> {
let mut header = Header {
parties: Vec::new(),
candidates: Vec::new(),
winners,
};
let mut parties_lookup = HashMap::<&str, usize>::new();
for col in row.columns()?.skip(6) {
let [party, name] = col.split(':').next_array().ok_or("Missing ':'")?;
if party == "UG" { // independents
header.candidates.push(Candidate {
name: name.to_owned(),
party_id: None,
});
}
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 {
name: name.to_owned(),
party_id: Some(party_id),
});
}
else {
parties_lookup.insert(party, header.parties.len());
header.parties.push(Party::new(name.to_owned()));
}
}
Ok(header.into())
}
pub fn get_candidate_name(&self, index: usize) -> CandidateName {
self.candidates[index].get_name(self)
}
pub fn iter_candidate_name(&self) -> impl Iterator<Item = CandidateName> {
self.candidates.iter().map(|v| v.get_name(self))
}
}