61 lines
1.4 KiB
Rust
61 lines
1.4 KiB
Rust
|
mod ballot_box;
|
||
|
mod reporting;
|
||
|
mod candidates;
|
||
|
mod ballot;
|
||
|
|
||
|
use ballot_box::BallotBox;
|
||
|
use ballot_box::CountStatus::*;
|
||
|
|
||
|
use std::path;
|
||
|
use std::process;
|
||
|
|
||
|
use clap::Parser;
|
||
|
|
||
|
#[derive(Parser, Debug)]
|
||
|
#[clap(author, version)]
|
||
|
struct Args {
|
||
|
/// Path to the CSV containing the ballots.
|
||
|
#[clap()]
|
||
|
path : path::PathBuf,
|
||
|
|
||
|
/// Threshold to win.
|
||
|
#[clap(long, short, default_value = "0.5")]
|
||
|
threshold : f64,
|
||
|
|
||
|
/// Generate report of counting.
|
||
|
#[clap(long, takes_value = false)]
|
||
|
report : bool,
|
||
|
}
|
||
|
|
||
|
/// Primary entry point to vote counting algorithms.
|
||
|
fn count(args : Args) -> Result<(), csv::Error> {
|
||
|
|
||
|
let mut ballot_box = BallotBox::from_file(&args.path, args.report)?;
|
||
|
|
||
|
let winner = loop {
|
||
|
match ballot_box.status(args.threshold, args.report) {
|
||
|
Winner(winner) => break Some(winner),
|
||
|
Tie => break None,
|
||
|
Runoff(to_eliminated) => ballot_box.runoff(to_eliminated),
|
||
|
Promotion(to_promote) => ballot_box.promote(to_promote),
|
||
|
}
|
||
|
};
|
||
|
|
||
|
reporting::winner(winner, &ballot_box.candidates);
|
||
|
|
||
|
Ok(())
|
||
|
}
|
||
|
|
||
|
fn main() {
|
||
|
let args = Args::parse();
|
||
|
match count(args) {
|
||
|
Ok(_) => {
|
||
|
process::exit(exitcode::OK);
|
||
|
},
|
||
|
Err(error) => {
|
||
|
println!("An error occured reading the CSV data: {}", error);
|
||
|
process::exit(exitcode::DATAERR);
|
||
|
}
|
||
|
}
|
||
|
}
|