Fixes to count description

This commit is contained in:
RunasSudo 2021-06-12 16:03:31 +10:00
parent a89c949315
commit e059a6a3d9
No known key found for this signature in database
GPG Key ID: 7234E476BF21C61A
7 changed files with 45 additions and 4 deletions

View File

@ -103,6 +103,7 @@ async function clickCount() {
document.getElementById('chkRoundVotes').checked ? parseInt(document.getElementById('txtRoundVotes').value) : null, document.getElementById('chkRoundVotes').checked ? parseInt(document.getElementById('txtRoundVotes').value) : null,
document.getElementById('chkRoundQuota').checked ? parseInt(document.getElementById('txtRoundQuota').value) : null, document.getElementById('chkRoundQuota').checked ? parseInt(document.getElementById('txtRoundQuota').value) : null,
document.getElementById('selSumTransfers').value, document.getElementById('selSumTransfers').value,
document.getElementById('chkNormaliseBallots').checked,
document.getElementById('selQuota').value, document.getElementById('selQuota').value,
document.getElementById('selQuotaCriterion').value, document.getElementById('selQuotaCriterion').value,
document.getElementById('selQuotaMode').value, document.getElementById('selQuotaMode').value,

View File

@ -181,6 +181,7 @@ where
cmd_opts.round_votes, cmd_opts.round_votes,
cmd_opts.round_quota, cmd_opts.round_quota,
&cmd_opts.sum_surplus_transfers, &cmd_opts.sum_surplus_transfers,
cmd_opts.normalise_ballots,
&cmd_opts.quota, &cmd_opts.quota,
&cmd_opts.quota_criterion, &cmd_opts.quota_criterion,
&cmd_opts.quota_mode, &cmd_opts.quota_mode,
@ -193,6 +194,17 @@ where
cmd_opts.pp_decimals, cmd_opts.pp_decimals,
); );
// Describe count
let total_ballots = election.ballots.iter().fold(N::zero(), |acc, b| { acc + &b.orig_value });
print!("Count computed by OpenTally (revision {}). Read {:.0} ballots from \"{}\" for election \"{}\". There are {} candidates for {} vacancies. ", opentally::VERSION, total_ballots, cmd_opts.filename, election.name, election.candidates.len(), election.seats);
let opts_str = stv_opts.describe::<N>();
if opts_str.len() > 0 {
println!("Counting using options \"{}\".", opts_str);
} else {
println!("Counting using default options.");
}
println!();
// Normalise ballots if requested // Normalise ballots if requested
if cmd_opts.normalise_ballots { if cmd_opts.normalise_ballots {
election.normalise_ballots(); election.normalise_ballots();

View File

@ -47,6 +47,7 @@ where
fn new() -> Self; fn new() -> Self;
fn describe() -> String; fn describe() -> String;
fn describe_opt() -> String { Self::describe() }
fn pow_assign(&mut self, exponent: i32); fn pow_assign(&mut self, exponent: i32);
fn floor_mut(&mut self, dps: usize); fn floor_mut(&mut self, dps: usize);

View File

@ -33,6 +33,7 @@ impl Number for Rational {
fn new() -> Self { Self(RatioType::zero()) } fn new() -> Self { Self(RatioType::zero()) }
fn describe() -> String { "--numbers rational".to_string() } fn describe() -> String { "--numbers rational".to_string() }
fn describe_opt() -> String { String::new() }
fn pow_assign(&mut self, exponent: i32) { fn pow_assign(&mut self, exponent: i32) {
self.0 = self.0.pow(exponent); self.0 = self.0.pow(exponent);

View File

@ -32,6 +32,7 @@ impl Number for Rational {
fn new() -> Self { Self(rug::Rational::new()) } fn new() -> Self { Self(rug::Rational::new()) }
fn describe() -> String { "--numbers rational".to_string() } fn describe() -> String { "--numbers rational".to_string() }
fn describe_opt() -> String { String::new() }
fn pow_assign(&mut self, exponent: i32) { fn pow_assign(&mut self, exponent: i32) {
self.0.pow_assign(exponent); self.0.pow_assign(exponent);

View File

@ -38,6 +38,7 @@ pub struct STVOptions {
pub round_votes: Option<usize>, pub round_votes: Option<usize>,
pub round_quota: Option<usize>, pub round_quota: Option<usize>,
pub sum_surplus_transfers: SumSurplusTransfersMode, pub sum_surplus_transfers: SumSurplusTransfersMode,
pub normalise_ballots: bool,
pub quota: QuotaType, pub quota: QuotaType,
pub quota_criterion: QuotaCriterion, pub quota_criterion: QuotaCriterion,
pub quota_mode: QuotaMode, pub quota_mode: QuotaMode,
@ -57,7 +58,8 @@ impl STVOptions {
round_weights: Option<usize>, round_weights: Option<usize>,
round_votes: Option<usize>, round_votes: Option<usize>,
round_quota: Option<usize>, round_quota: Option<usize>,
sum_transfers: &str, sum_surplus_transfers: &str,
normalise_ballots: bool,
quota: &str, quota: &str,
quota_criterion: &str, quota_criterion: &str,
quota_mode: &str, quota_mode: &str,
@ -74,12 +76,13 @@ impl STVOptions {
round_weights, round_weights,
round_votes, round_votes,
round_quota, round_quota,
sum_surplus_transfers: match sum_transfers { sum_surplus_transfers: match sum_surplus_transfers {
"single_step" => SumSurplusTransfersMode::SingleStep, "single_step" => SumSurplusTransfersMode::SingleStep,
"by_value" => SumSurplusTransfersMode::ByValue, "by_value" => SumSurplusTransfersMode::ByValue,
"per_ballot" => SumSurplusTransfersMode::PerBallot, "per_ballot" => SumSurplusTransfersMode::PerBallot,
_ => panic!("Invalid --sum-transfers"), _ => panic!("Invalid --sum-transfers"),
}, },
normalise_ballots,
quota: match quota { quota: match quota {
"droop" => QuotaType::Droop, "droop" => QuotaType::Droop,
"hare" => QuotaType::Hare, "hare" => QuotaType::Hare,
@ -127,11 +130,13 @@ impl STVOptions {
// Not exported to WebAssembly // Not exported to WebAssembly
pub fn describe<N: Number>(&self) -> String { pub fn describe<N: Number>(&self) -> String {
let mut flags = Vec::new(); let mut flags = Vec::new();
flags.push(N::describe()); let n_str = N::describe_opt(); if n_str.len() > 0 { flags.push(N::describe_opt()) };
if let Some(dps) = self.round_tvs { flags.push(format!("--round-tvs {}", dps)); } if let Some(dps) = self.round_tvs { flags.push(format!("--round-tvs {}", dps)); }
if let Some(dps) = self.round_weights { flags.push(format!("--round-weights {}", dps)); } if let Some(dps) = self.round_weights { flags.push(format!("--round-weights {}", dps)); }
if let Some(dps) = self.round_votes { flags.push(format!("--round-votes {}", dps)); } if let Some(dps) = self.round_votes { flags.push(format!("--round-votes {}", dps)); }
if let Some(dps) = self.round_quota { flags.push(format!("--round-quota {}", dps)); } if let Some(dps) = self.round_quota { flags.push(format!("--round-quota {}", dps)); }
if self.sum_surplus_transfers != SumSurplusTransfersMode::SingleStep { flags.push(self.sum_surplus_transfers.describe()); }
if self.normalise_ballots { flags.push("--normalise-ballots".to_string()); }
if self.quota != QuotaType::DroopExact { flags.push(self.quota.describe()); } if self.quota != QuotaType::DroopExact { flags.push(self.quota.describe()); }
if self.quota_criterion != QuotaCriterion::Greater { flags.push(self.quota_criterion.describe()); } if self.quota_criterion != QuotaCriterion::Greater { flags.push(self.quota_criterion.describe()); }
if self.quota_mode != QuotaMode::Static { flags.push(self.quota_mode.describe()); } if self.quota_mode != QuotaMode::Static { flags.push(self.quota_mode.describe()); }
@ -139,6 +144,8 @@ impl STVOptions {
if self.surplus_order != SurplusOrder::BySize { flags.push(self.surplus_order.describe()); } if self.surplus_order != SurplusOrder::BySize { flags.push(self.surplus_order.describe()); }
if self.transferable_only { flags.push("--transferable-only".to_string()); } if self.transferable_only { flags.push("--transferable-only".to_string()); }
if self.exclusion != ExclusionMethod::SingleStage { flags.push(self.exclusion.describe()); } if self.exclusion != ExclusionMethod::SingleStage { flags.push(self.exclusion.describe()); }
if self.bulk_exclude { flags.push("--bulk-exclude".to_string()); }
if self.defer_surpluses { flags.push("--defer-surpluses".to_string()); }
if self.pp_decimals != 2 { flags.push(format!("--pp-decimals {}", self.pp_decimals)); } if self.pp_decimals != 2 { flags.push(format!("--pp-decimals {}", self.pp_decimals)); }
return flags.join(" "); return flags.join(" ");
} }
@ -153,6 +160,16 @@ pub enum SumSurplusTransfersMode {
PerBallot, PerBallot,
} }
impl SumSurplusTransfersMode {
fn describe(self) -> String {
match self {
SumSurplusTransfersMode::SingleStep => "--sum-surplus-transfers single_step",
SumSurplusTransfersMode::ByValue => "--sum-surplus-transfers by_value",
SumSurplusTransfersMode::PerBallot => "--sum-surplus-transfers per_ballot",
}.to_string()
}
}
#[wasm_bindgen] #[wasm_bindgen]
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[derive(PartialEq)] #[derive(PartialEq)]

View File

@ -157,7 +157,15 @@ fn describe_count<N: Number>(filename: String, election: &Election<N>, opts: &st
let mut result = String::from("<p>Count computed by OpenTally (revision "); let mut result = String::from("<p>Count computed by OpenTally (revision ");
result.push_str(crate::VERSION); result.push_str(crate::VERSION);
let total_ballots = election.ballots.iter().fold(N::zero(), |acc, b| { acc + &b.orig_value }); let total_ballots = election.ballots.iter().fold(N::zero(), |acc, b| { acc + &b.orig_value });
result.push_str(&format!(r#"). Read {:.0} ballots from &lsquo;{}&rsquo; for election &lsquo;{}&rsquo;. There are {} candidates for {} vacancies. Counting using options <span style="font-family: monospace;">{}</span>.</p>"#, total_ballots, filename, election.name, election.candidates.len(), election.seats, opts.describe::<N>())); result.push_str(&format!(r#"). Read {:.0} ballots from &lsquo;{}&rsquo; for election &lsquo;{}&rsquo;. There are {} candidates for {} vacancies. "#, total_ballots, filename, election.name, election.candidates.len(), election.seats));
let opts_str = opts.describe::<N>();
if opts_str.len() > 0 {
result.push_str(&format!(r#"Counting using options <span style="font-family: monospace;">{}</span>.</p>"#, opts_str))
} else {
result.push_str(r#"Counting using default options.</p>"#);
}
return result; return result;
} }