diff --git a/docs/validation.md b/docs/validation.md index c4ec83f..99e63b4 100644 --- a/docs/validation.md +++ b/docs/validation.md @@ -12,8 +12,10 @@ STV-counting software is frequently validated empirically by comparing the resul | Australian Senate STV | [2019 NSW Senate election](https://results.aec.gov.au/24310/Website/SenateDownloadsMenu-24310-Csv.htm) | EasyCount (official) | | | Australian Capital Territory STV | [2020 Kurrajong Legislative Assembly election](https://www.elections.act.gov.au/elections_and_voting/2020_legislative_assembly_election/ballot-paper-preference-data-2020-election) | [eVACS 2020](https://www.elections.act.gov.au/elections_and_voting/electronic_voting_and_counting) (official) | ✓ | | NSW Local Government STV | [2021 City of Albury Council election](https://pastvtr.elections.nsw.gov.au/LG2101/albury/councillor) | PRCC Vote Count (official) | ✓ | -| Minneapolis STV | [2009 Minneapolis Board of Estimate and Taxation election](https://vote.minneapolismn.gov/results-data/election-results/2009/bet/) | Results sheet (official) | ✓ | +| Minneapolis STV | [2009 Minneapolis Board of Estimate & Taxation election](https://vote.minneapolismn.gov/results-data/election-results/2009/bet/) | Results sheet (official) | ✓ | | Minneapolis STV | [2013 Minneapolis Parks & Recreation Commissioner At Large election](https://vote.minneapolismn.gov/results-data/election-results/2013/park-board-at-large/) | Results sheet (official) | ✓ | +| Minneapolis STV | [2021 Minneapolis Board of Estimate & Taxation election](https://vote.minneapolismn.gov/results-data/election-results/2021/bet/) | Results sheet (official) | ✓ | +| Minneapolis STV | [2021 Minneapolis Parks & Recreation Commissioner At Large election](https://vote.minneapolismn.gov/results-data/election-results/2021/park-board-at-large/) | Results sheet (official) | ✓ | | Cambridge STV | [2003 Cambridge City Council election](https://web.archive.org/web/20070204083508/http://stv.sourceforge.net/) | OpenSTV 1.7, [ChoicePlus Pro 2.1](https://www.votingsolutions.com/cpdetail.htm) (official) | ✓ | | Dáil Éireann STV | [2002 Dublin North election](https://electionsireland.org/counts.cfm?election=2002&cons=96) | Results sheet (official) | ✓ | | van der Craats (‘Wright’) STV | [EVE Online CSM 15 election](https://www.eveonline.com/news/view/meet-the-new-council) | [ccp-wright-stv](https://github.com/ccpgames/ccp-wright-stv) (official) | ✓ | diff --git a/tests/data/2021-BET-Cast-Vote-Record.blt b/tests/data/2021-BET-Cast-Vote-Record.blt new file mode 100644 index 0000000..8ed49af --- /dev/null +++ b/tests/data/2021-BET-Cast-Vote-Record.blt @@ -0,0 +1,93 @@ +# Comment: 2021 Minneapolis Board of Estimate & Taxation election - all votes - Minneapolis STV +# Source: https://vote.minneapolismn.gov/results-data/election-results/2021/bet/ +# Contributor: RunasSudo +5 2 +49712 0 +2262 1 0 +125 1 2 0 +311 1 2 3 0 +279 1 2 4 0 +5 1 2 5 0 +223 1 3 0 +517 1 3 2 0 +428 1 3 4 0 +6 1 3 5 0 +470 1 4 0 +530 1 4 2 0 +607 1 4 3 0 +24 1 4 5 0 +27 1 5 0 +1 1 5 2 0 +4860 2 0 +131 2 1 0 +368 2 1 3 0 +231 2 1 4 0 +7 2 1 5 0 +3336 2 3 0 +1042 2 3 1 0 +5358 2 3 4 0 +77 2 3 5 0 +2518 2 4 0 +643 2 4 1 0 +2140 2 4 3 0 +34 2 4 5 0 +37 2 5 0 +1 2 5 3 0 +3 2 5 4 0 +9309 3 0 +301 3 1 0 +847 3 1 2 0 +881 3 1 4 0 +6 3 1 5 0 +3179 3 2 0 +2361 3 2 1 0 +3318 3 2 4 0 +84 3 2 5 0 +1731 3 4 0 +1441 3 4 1 0 +2013 3 4 2 0 +36 3 4 5 0 +81 3 5 0 +3 3 5 1 0 +5 3 5 2 0 +1 3 5 4 0 +23165 4 0 +1445 4 1 0 +1306 4 1 2 0 +2250 4 1 3 0 +76 4 1 5 0 +4254 4 2 0 +914 4 2 1 0 +2229 4 2 3 0 +65 4 2 5 0 +2609 4 3 0 +1716 4 3 1 0 +2389 4 3 2 0 +35 4 3 5 0 +206 4 5 0 +4 4 5 1 0 +3 4 5 2 0 +6 4 5 3 0 +679 5 0 +5 5 1 0 +1 5 1 2 0 +1 5 1 3 0 +2 5 1 4 0 +3 5 2 0 +1 5 2 1 0 +5 5 2 3 0 +4 5 2 4 0 +5 5 3 0 +2 5 3 1 0 +12 5 3 2 0 +12 5 4 0 +10 5 4 1 0 +7 5 4 2 0 +6 5 4 3 0 +0 +"Kevin Nikiforakis" +"Pine Salica" +"Samantha \"Sam\" Pree-Stinson" +"Steve Brandt" +"UWI" +"2021-BET-Cast-Vote-Record" diff --git a/tests/data/2021-BET-Cast-Vote-Record.csv b/tests/data/2021-BET-Cast-Vote-Record.csv new file mode 100644 index 0000000..81f9c11 --- /dev/null +++ b/tests/data/2021-BET-Cast-Vote-Record.csv @@ -0,0 +1,9 @@ +Stage:,1,,2,,3,,4, +Comment:,First preferences,,"Exclusion of Kevin Nikiforakis, UWI",,Surplus of Steve Brandt,,Exclusion of Pine Salica, +Kevin Nikiforakis,5815,H,0,EX,0,EX,0,EX +Pine Salica,20786,H,21521,H,24137.4788,H,24137.4788,EX +"Samantha ""Sam"" Pree-Stinson",25597,H,26791,H,29494.6198,H,29494.6198,EL +Steve Brandt,42672,H,44340,H,31876,EL,31876,EL +UWI,755,H,0,EX,0,EX,0,EX +Exhausted,49712,,52685,,59828.8754,,59828.8754, +Loss by fraction,0,,0,,0.026,,0.026, diff --git a/tests/data/2021-BET-Cast-Vote-Record.ods b/tests/data/2021-BET-Cast-Vote-Record.ods new file mode 100644 index 0000000..dcc80e0 Binary files /dev/null and b/tests/data/2021-BET-Cast-Vote-Record.ods differ diff --git a/tests/data/2021-Park-AL-Cast-Vote-Record.blt b/tests/data/2021-Park-AL-Cast-Vote-Record.blt new file mode 100644 index 0000000..d87a721 --- /dev/null +++ b/tests/data/2021-Park-AL-Cast-Vote-Record.blt @@ -0,0 +1,370 @@ +# Source: Converted by RunasSudo from a file named 2021-Park-AL-Cast-Vote-Record.csv at https://vote.minneapolismn.gov/results-data/election-results/2021/park-board-at-large/, using minneapolis_to_blt.py +8 3 +38687 0 +3326 1 0 +216 1 2 0 +132 1 2 3 0 +156 1 2 4 0 +199 1 2 5 0 +211 1 2 6 0 +180 1 2 7 0 +3 1 2 8 0 +271 1 3 0 +213 1 3 2 0 +116 1 3 4 0 +547 1 3 5 0 +608 1 3 6 0 +178 1 3 7 0 +2 1 3 8 0 +207 1 4 0 +151 1 4 2 0 +131 1 4 3 0 +107 1 4 5 0 +228 1 4 6 0 +192 1 4 7 0 +4 1 4 8 0 +222 1 5 0 +141 1 5 2 0 +313 1 5 3 0 +104 1 5 4 0 +586 1 5 6 0 +182 1 5 7 0 +3 1 5 8 0 +518 1 6 0 +168 1 6 2 0 +560 1 6 3 0 +195 1 6 4 0 +754 1 6 5 0 +331 1 6 7 0 +8 1 6 8 0 +279 1 7 0 +157 1 7 2 0 +149 1 7 3 0 +154 1 7 4 0 +235 1 7 5 0 +333 1 7 6 0 +7 1 7 8 0 +19 1 8 0 +1 1 8 5 0 +2 1 8 6 0 +3172 2 0 +285 2 1 0 +135 2 1 3 0 +160 2 1 4 0 +219 2 1 5 0 +269 2 1 6 0 +140 2 1 7 0 +6 2 1 8 0 +95 2 3 0 +125 2 3 1 0 +52 2 3 4 0 +101 2 3 5 0 +75 2 3 6 0 +76 2 3 7 0 +7 2 3 8 0 +145 2 4 0 +179 2 4 1 0 +73 2 4 3 0 +77 2 4 5 0 +108 2 4 6 0 +79 2 4 7 0 +5 2 4 8 0 +407 2 5 0 +268 2 5 1 0 +187 2 5 3 0 +51 2 5 4 0 +519 2 5 6 0 +90 2 5 7 0 +10 2 5 8 0 +438 2 6 0 +241 2 6 1 0 +96 2 6 3 0 +95 2 6 4 0 +488 2 6 5 0 +130 2 6 7 0 +3 2 6 8 0 +214 2 7 0 +137 2 7 1 0 +119 2 7 3 0 +296 2 7 4 0 +146 2 7 5 0 +162 2 7 6 0 +5 2 7 8 0 +20 2 8 0 +1 2 8 3 0 +2 2 8 5 0 +1 2 8 6 0 +2 2 8 7 0 +2392 3 0 +171 3 1 0 +62 3 1 2 0 +58 3 1 4 0 +306 3 1 5 0 +476 3 1 6 0 +109 3 1 7 0 +1 3 1 8 0 +83 3 2 0 +89 3 2 1 0 +55 3 2 4 0 +80 3 2 5 0 +65 3 2 6 0 +166 3 2 7 0 +4 3 2 8 0 +44 3 4 0 +64 3 4 1 0 +24 3 4 2 0 +42 3 4 5 0 +68 3 4 6 0 +31 3 4 7 0 +124 3 5 0 +271 3 5 1 0 +104 3 5 2 0 +53 3 5 4 0 +455 3 5 6 0 +109 3 5 7 0 +158 3 6 0 +356 3 6 1 0 +67 3 6 2 0 +81 3 6 4 0 +296 3 6 5 0 +99 3 6 7 0 +3 3 6 8 0 +111 3 7 0 +153 3 7 1 0 +108 3 7 2 0 +44 3 7 4 0 +150 3 7 5 0 +126 3 7 6 0 +3 3 7 8 0 +7 3 8 0 +2 3 8 7 0 +3387 4 0 +365 4 1 0 +209 4 1 2 0 +167 4 1 3 0 +128 4 1 5 0 +300 4 1 6 0 +329 4 1 7 0 +12 4 1 8 0 +216 4 2 0 +217 4 2 1 0 +79 4 2 3 0 +70 4 2 5 0 +91 4 2 6 0 +103 4 2 7 0 +7 4 2 8 0 +51 4 3 0 +89 4 3 1 0 +41 4 3 2 0 +48 4 3 5 0 +86 4 3 6 0 +46 4 3 7 0 +1 4 3 8 0 +91 4 5 0 +104 4 5 1 0 +45 4 5 2 0 +45 4 5 3 0 +190 4 5 6 0 +70 4 5 7 0 +472 4 6 0 +326 4 6 1 0 +103 4 6 2 0 +146 4 6 3 0 +166 4 6 5 0 +200 4 6 7 0 +6 4 6 8 0 +1557 4 7 0 +1583 4 7 1 0 +127 4 7 2 0 +71 4 7 3 0 +203 4 7 5 0 +295 4 7 6 0 +21 4 7 8 0 +38 4 8 0 +2 4 8 1 0 +2 4 8 3 0 +1 4 8 7 0 +2960 5 0 +247 5 1 0 +162 5 1 2 0 +310 5 1 3 0 +63 5 1 4 0 +509 5 1 6 0 +194 5 1 7 0 +2 5 1 8 0 +426 5 2 0 +260 5 2 1 0 +112 5 2 3 0 +40 5 2 4 0 +538 5 2 6 0 +124 5 2 7 0 +6 5 2 8 0 +159 5 3 0 +216 5 3 1 0 +96 5 3 2 0 +29 5 3 4 0 +281 5 3 6 0 +108 5 3 7 0 +2 5 3 8 0 +84 5 4 0 +60 5 4 1 0 +40 5 4 2 0 +38 5 4 3 0 +90 5 4 6 0 +56 5 4 7 0 +923 5 6 0 +1297 5 6 1 0 +782 5 6 2 0 +470 5 6 3 0 +128 5 6 4 0 +326 5 6 7 0 +5 5 6 8 0 +191 5 7 0 +184 5 7 1 0 +112 5 7 2 0 +98 5 7 3 0 +77 5 7 4 0 +249 5 7 6 0 +5 5 7 8 0 +13 5 8 0 +1 5 8 1 0 +1 5 8 7 0 +10018 6 0 +893 6 1 0 +415 6 1 2 0 +1191 6 1 3 0 +282 6 1 4 0 +1223 6 1 5 0 +516 6 1 7 0 +7 6 1 8 0 +554 6 2 0 +385 6 2 1 0 +160 6 2 3 0 +134 6 2 4 0 +1125 6 2 5 0 +231 6 2 7 0 +6 6 2 8 0 +335 6 3 0 +525 6 3 1 0 +146 6 3 2 0 +109 6 3 4 0 +531 6 3 5 0 +278 6 3 7 0 +4 6 3 8 0 +455 6 4 0 +263 6 4 1 0 +117 6 4 2 0 +136 6 4 3 0 +208 6 4 5 0 +204 6 4 7 0 +2 6 4 8 0 +1157 6 5 0 +2700 6 5 1 0 +3366 6 5 2 0 +630 6 5 3 0 +208 6 5 4 0 +594 6 5 7 0 +13 6 5 8 0 +630 6 7 0 +589 6 7 1 0 +295 6 7 2 0 +257 6 7 3 0 +206 6 7 4 0 +459 6 7 5 0 +5 6 7 8 0 +46 6 8 0 +1 6 8 2 0 +2 6 8 3 0 +1 6 8 4 0 +4967 7 0 +476 7 1 0 +210 7 1 2 0 +225 7 1 3 0 +351 7 1 4 0 +357 7 1 5 0 +474 7 1 6 0 +5 7 1 8 0 +284 7 2 0 +194 7 2 1 0 +268 7 2 3 0 +317 7 2 4 0 +200 7 2 5 0 +219 7 2 6 0 +15 7 2 8 0 +150 7 3 0 +163 7 3 1 0 +143 7 3 2 0 +84 7 3 4 0 +165 7 3 5 0 +182 7 3 6 0 +2 7 3 8 0 +1488 7 4 0 +3900 7 4 1 0 +139 7 4 2 0 +96 7 4 3 0 +608 7 4 5 0 +468 7 4 6 0 +26 7 4 8 0 +276 7 5 0 +546 7 5 1 0 +162 7 5 2 0 +168 7 5 3 0 +238 7 5 4 0 +557 7 5 6 0 +4 7 5 8 0 +660 7 6 0 +642 7 6 1 0 +194 7 6 2 0 +237 7 6 3 0 +292 7 6 4 0 +509 7 6 5 0 +6 7 6 8 0 +30 7 8 0 +1 7 8 1 0 +1 7 8 2 0 +1 7 8 3 0 +1 7 8 4 0 +1 7 8 5 0 +518 8 0 +3 8 1 0 +1 8 1 4 0 +1 8 1 6 0 +2 8 1 7 0 +2 8 2 0 +1 8 2 1 0 +1 8 2 3 0 +2 8 2 5 0 +2 8 2 6 0 +1 8 2 7 0 +1 8 3 2 0 +1 8 3 7 0 +7 8 4 0 +1 8 4 1 0 +1 8 4 6 0 +1 8 4 7 0 +3 8 5 0 +1 8 5 1 0 +1 8 5 7 0 +4 8 6 0 +1 8 6 1 0 +3 8 6 2 0 +1 8 6 4 0 +4 8 6 5 0 +4 8 6 7 0 +1 8 7 0 +1 8 7 1 0 +2 8 7 2 0 +1 8 7 3 0 +1 8 7 4 0 +1 8 7 5 0 +1 8 7 6 0 +0 +"Alicia D. Smith" +"Charles Rucker" +"Katherine Kelly" +"Londel French" +"Mary McKelvey" +"Meg Forney" +"Tom Olsen" +"UWI" +"2021-Park-AL-Cast-Vote-Record" diff --git a/tests/data/2021-Park-AL-Cast-Vote-Record.csv b/tests/data/2021-Park-AL-Cast-Vote-Record.csv new file mode 100644 index 0000000..f2193c2 --- /dev/null +++ b/tests/data/2021-Park-AL-Cast-Vote-Record.csv @@ -0,0 +1,12 @@ +Stage:,1,,2,,3,,4,,5,,6,,7, +Comment:,First preferences,,Exclusion of UWI,,Surplus of Meg Forney,,Exclusion of Katherine Kelly,,Exclusion of Charles Rucker,,Exclusion of Londel French,,Surplus of Tom Olsen, +Alicia D. Smith,12799,H,12806,H,13516.896,H,15138.321,H,16868.766,H,19298.057,H,19656.5888,H +Charles Rucker,9711,H,9720,H,10128.043,H,10760.965,H,0,EX,0,EX,0,EX +Katherine Kelly,7270,H,7272,H,7575.01,H,0,EX,0,EX,0,EX,0,EX +Londel French,11906,H,11916,H,12133.759,H,12504.872,H,13393.91,H,0,EX,0,EX +Mary McKelvey,12074,H,12079,H,13440.504,H,14935.871,H,17317.496,H,18298.152,H,18458.3578,H +Meg Forney,31612,H,31629,H,26663,EL,26663,EL,26663,EL,26663,EL,26663,EL +Tom Olsen,20702,H,20710,H,21093.865,H,21934.511,H,23424.778,H,27774.806,H,26663,EL +UWI,576,H,0,EX,0,EX,0,EX,0,EX,0,EX,0,EX +Exhausted,38687,,39205,,40785.676,,43399.213,,47668.803,,53302.738,,53894.74, +Loss by fraction,0,,0,,0.247,,0.247,,0.247,,0.247,,1.3134, diff --git a/tests/data/2021-Park-AL-Cast-Vote-Record.ods b/tests/data/2021-Park-AL-Cast-Vote-Record.ods new file mode 100644 index 0000000..c4c1d82 Binary files /dev/null and b/tests/data/2021-Park-AL-Cast-Vote-Record.ods differ diff --git a/tests/tests_impl/minneapolis.rs b/tests/tests_impl/minneapolis.rs index fce02d3..5d52a45 100644 --- a/tests/tests_impl/minneapolis.rs +++ b/tests/tests_impl/minneapolis.rs @@ -57,3 +57,41 @@ fn minneapolis_pal13_rational() { utils::read_validate_election::("tests/data/2013-Park-At-Large-CVR.csv", "tests/data/2013-Park-At-Large-CVR.blt", stv_opts, Some(4), &[]); } + +#[test] +fn minneapolis_boe21_rational() { + let stv_opts = stv::STVOptionsBuilder::default() + .round_surplus_fractions(Some(4)) + .round_values(Some(4)) + .round_quota(Some(0)) + .round_subtransfers(stv::RoundSubtransfersMode::PerBallot) + .quota_criterion(stv::QuotaCriterion::GreaterOrEqual) + //.early_bulk_elect(true) + .bulk_exclude(true) + .defer_surpluses(true) + .immediate_elect(false) + .build().unwrap(); + + assert_eq!(stv_opts.describe::(), "--round-surplus-fractions 4 --round-values 4 --round-quota 0 --round-subtransfers per_ballot --quota-criterion geq --bulk-exclude --defer-surpluses --no-immediate-elect"); + + utils::read_validate_election::("tests/data/2021-BET-Cast-Vote-Record.csv", "tests/data/2021-BET-Cast-Vote-Record.blt", stv_opts, Some(2), &["exhausted", "lbf"]); +} + +#[test] +fn minneapolis_pal21_rational() { + let stv_opts = stv::STVOptionsBuilder::default() + .round_surplus_fractions(Some(4)) + .round_values(Some(4)) + .round_quota(Some(0)) + .round_subtransfers(stv::RoundSubtransfersMode::PerBallot) + .quota_criterion(stv::QuotaCriterion::GreaterOrEqual) + //.early_bulk_elect(true) + .bulk_exclude(true) + .defer_surpluses(true) + .immediate_elect(false) + .build().unwrap(); + + assert_eq!(stv_opts.describe::(), "--round-surplus-fractions 4 --round-values 4 --round-quota 0 --round-subtransfers per_ballot --quota-criterion geq --bulk-exclude --defer-surpluses --no-immediate-elect"); + + utils::read_validate_election::("tests/data/2021-Park-AL-Cast-Vote-Record.csv", "tests/data/2021-Park-AL-Cast-Vote-Record.blt", stv_opts, Some(3), &["exhausted", "lbf"]); +}