From a2e4ab557c4cdbbf8d10a1e77e6e25c8ab6a3da5 Mon Sep 17 00:00:00 2001 From: RunasSudo Date: Sat, 19 Jun 2021 01:57:04 +1000 Subject: [PATCH] Implement test case for 2006 Meek STV --- tests/meek.rs | 83 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 80 insertions(+), 3 deletions(-) diff --git a/tests/meek.rs b/tests/meek.rs index 48ac876..8abd2a2 100644 --- a/tests/meek.rs +++ b/tests/meek.rs @@ -17,18 +17,23 @@ mod utils; -use opentally::numbers::NativeFloat64; +use opentally::election::{CandidateState, CountState, Election}; +use opentally::numbers::{Fixed, NativeFloat64, Number}; use opentally::stv; +use std::io::{self, BufRead}; +use std::fs::File; + +// Compare ers97.blt count with result produced by 1987 Hill–Wichmann–Woodall reference implementation #[test] -fn meek_ers97_float64() { +fn meek87_ers97_float64() { let stv_opts = stv::STVOptions { round_tvs: None, round_weights: None, round_votes: None, round_quota: None, sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep, - meek_surplus_tolerance: String::from("1.001%"), + meek_surplus_tolerance: String::from("0.001%"), normalise_ballots: false, quota: stv::QuotaType::DroopExact, quota_criterion: stv::QuotaCriterion::GreaterOrEqual, @@ -45,3 +50,75 @@ fn meek_ers97_float64() { }; utils::read_validate_election::("tests/data/ers97_meek.csv", "tests/data/ers97.blt", stv_opts, Some(2), &["exhausted", "quota"]); } + +// Compare ers97.blt count with result produced by OpenSTV "Meek STV" +#[test] +fn meek06_ers97_fixed12() { + let stv_opts = stv::STVOptions { + round_tvs: Some(9), + round_weights: Some(9), + round_votes: Some(9), + round_quota: Some(9), + sum_surplus_transfers: stv::SumSurplusTransfersMode::SingleStep, + meek_surplus_tolerance: String::from("0.0001"), + normalise_ballots: false, + quota: stv::QuotaType::Droop, + quota_criterion: stv::QuotaCriterion::GreaterOrEqual, + quota_mode: stv::QuotaMode::Static, + ties: vec![], + surplus: stv::SurplusMethod::Meek, + surplus_order: stv::SurplusOrder::BySize, + transferable_only: false, + exclusion: stv::ExclusionMethod::SingleStage, + bulk_exclude: false, + defer_surpluses: true, + meek_immediate_elect: true, + pp_decimals: 2, + }; + Fixed::set_dps(12); + + // Read BLT + let file = File::open("tests/data/ers97.blt").expect("IO Error"); + let file_reader = io::BufReader::new(file); + let lines = file_reader.lines(); + + let election: Election = Election::from_blt(lines.map(|r| r.expect("IO Error").to_string()).into_iter()); + + // Initialise count state + let mut state = CountState::new(&election); + + // Count to completion + stv::count_init(&mut state, &stv_opts); + while !stv::count_one_stage(&mut state, &stv_opts).unwrap() {} + + // Check states and keep values + for (candidate, count_card) in state.candidates.iter() { + match candidate.name.as_str() { + "Smith" => { + assert!(count_card.state == CandidateState::Elected); + assert_eq!(count_card.keep_value, Some(Fixed::parse("0.452239778"))); + } + "Carpenter" => { + assert!(count_card.state == CandidateState::Elected); + assert_eq!(count_card.keep_value, Some(Fixed::parse("0.614726576"))); + } + "Duke" => { + assert!(count_card.state == CandidateState::Elected); + assert_eq!(count_card.keep_value, Some(Fixed::parse("0.610901635"))); + } + "Prince" => { + assert!(count_card.state == CandidateState::Elected); + assert_eq!(count_card.keep_value, Some(Fixed::parse("0.741971929"))); + } + "Freeman" => { + assert!(count_card.state == CandidateState::Elected); + assert_eq!(count_card.keep_value, Some(Fixed::parse("0.715546058"))); + } + "Vicar" => { + assert!(count_card.state == CandidateState::Elected); + assert_eq!(count_card.keep_value, Some(Fixed::parse("1.0"))); + } + _ => {} + } + } +}