use std::default::Default;
use std::error::Error;
use std::fmt::Display;
#[derive(Eq, PartialEq, Debug, Clone, Hash)]
pub enum BallotChoice {
Candidate(String),
UndeclaredWriteIn,
Overvote,
Undervote,
Blank,
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct Ballot {
pub candidates: Vec<BallotChoice>,
pub count: u64,
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct EliminationStats {
pub name: String,
pub transfers: Vec<(String, u64)>,
pub exhausted: u64,
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct RoundStats {
pub round: u32,
pub tally: Vec<(String, u64)>,
pub tally_results_elected: Vec<String>,
pub tally_result_eliminated: Vec<EliminationStats>,
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct VotingResult {
pub winners: Option<Vec<String>>,
pub threshold: u64,
pub round_stats: Vec<RoundStats>,
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub enum VotingErrors {
EmptyElection,
NoConvergence,
NoCandidateToEliminate,
}
impl Error for VotingErrors {}
impl Display for VotingErrors {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "VotingError in ranked_choice")
}
}
#[derive(Eq, PartialEq, Debug, Clone, Copy)]
pub enum TieBreakMode {
UseCandidateOrder,
Random(u32),
}
#[derive(Eq, PartialEq, Debug, Clone, Copy)]
pub enum OverVoteRule {
ExhaustImmediately,
AlwaysSkipToNextRank,
}
#[derive(Eq, PartialEq, Debug, Clone, Copy)]
pub enum DuplicateCandidateMode {
Exhaust,
SkipDuplicate,
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub enum WinnerElectionMode {
SingelWinnerMajority, }
#[derive(Eq, PartialEq, Debug, Clone, Copy)]
pub enum EliminationAlgorithm {
Batch,
Single,
}
#[derive(Eq, PartialEq, Debug, Clone, Copy)]
pub enum MaxSkippedRank {
Unlimited,
ExhaustOnFirstOccurence,
MaxAllowed(u32),
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct VoteRules {
pub tiebreak_mode: TieBreakMode,
pub overvote_rule: OverVoteRule,
pub winner_election_mode: WinnerElectionMode,
pub max_skipped_rank_allowed: MaxSkippedRank,
pub max_rankings_allowed: Option<u32>,
pub elimination_algorithm: EliminationAlgorithm,
pub duplicate_candidate_mode: DuplicateCandidateMode,
}
impl Default for VoteRules {
fn default() -> Self {
VoteRules::DEFAULT_RULES.clone()
}
}
impl VoteRules {
const DEFAULT_RULES: VoteRules = VoteRules {
tiebreak_mode: TieBreakMode::UseCandidateOrder,
overvote_rule: OverVoteRule::AlwaysSkipToNextRank,
winner_election_mode: WinnerElectionMode::SingelWinnerMajority,
max_skipped_rank_allowed: MaxSkippedRank::Unlimited,
max_rankings_allowed: None,
elimination_algorithm: EliminationAlgorithm::Single,
duplicate_candidate_mode: DuplicateCandidateMode::SkipDuplicate,
};
}
#[derive(Eq, PartialEq, Debug, Clone)]
pub(crate) struct Candidate {
pub name: String,
pub code: Option<String>,
pub excluded: bool,
}