pub use crate::config::*;
pub struct Builder {
pub(crate) _rules: VoteRules,
pub(crate) _candidates: Option<Vec<Candidate>>,
pub(crate) _votes: Vec<Ballot>,
}
impl Builder {
pub fn new(rules: &VoteRules) -> Result<Builder, VotingErrors> {
Ok(Builder {
_rules: rules.clone(),
_candidates: None,
_votes: Vec::new(),
})
}
pub fn candidates(self, cands: &[String]) -> Result<Builder, VotingErrors> {
Ok(Builder {
_rules: self._rules,
_candidates: Some(
cands
.to_vec()
.iter()
.map(|name| Candidate {
name: name.clone(),
code: None,
excluded: false,
})
.collect(),
),
_votes: Vec::new(),
})
}
pub fn add_vote_simple(&mut self, candidates: &[String]) -> Result<(), VotingErrors> {
self.add_vote(&[candidates.to_vec()], 1)
}
pub fn add_vote(&mut self, candidates: &[Vec<String>], count: u32) -> Result<(), VotingErrors> {
let mut choices: Vec<BallotChoice> = Vec::new();
for c in candidates {
let cand = match c.as_slice() {
[] => BallotChoice::Undervote,
[s] if s.is_empty() => BallotChoice::Blank,
[s] => {
if let Some(valid_candidates) = self._candidates.as_deref() {
if valid_candidates.iter().any(|cd| cd.name == *s) {
BallotChoice::Candidate(s.clone())
} else {
BallotChoice::UndeclaredWriteIn
}
} else {
BallotChoice::Candidate(s.clone())
}
}
_ => BallotChoice::Overvote,
};
choices.push(cand);
}
self.add_vote_2(&Ballot {
count: count as u64,
candidates: choices,
})
}
pub fn add_vote_2(&mut self, vote: &Ballot) -> Result<(), VotingErrors> {
self._votes.push(vote.clone());
Ok(())
}
}