Fix incorrect crediting of votes when surplus votes transferred at values received
Many thanks to J Groves for pointing this out
This commit is contained in:
parent
f5114bccda
commit
6968df5c9b
@ -202,7 +202,8 @@ impl<'e, N: Number> TransferTable<'e, N> {
|
|||||||
if self.surplus.is_none() || opts.sum_surplus_transfers == SumSurplusTransfersMode::ByValue {
|
if self.surplus.is_none() || opts.sum_surplus_transfers == SumSurplusTransfersMode::ByValue {
|
||||||
for (_candidate, cell) in self.total.cells.iter_mut() {
|
for (_candidate, cell) in self.total.cells.iter_mut() {
|
||||||
let mut votes_out;
|
let mut votes_out;
|
||||||
if is_weighted {
|
if is_weighted || self.surpfrac.is_none() {
|
||||||
|
// NB: If surplus.is_none, then votes transferred at values received
|
||||||
votes_out = cell.votes_in.clone();
|
votes_out = cell.votes_in.clone();
|
||||||
} else {
|
} else {
|
||||||
votes_out = cell.ballots.clone();
|
votes_out = cell.ballots.clone();
|
||||||
@ -221,7 +222,7 @@ impl<'e, N: Number> TransferTable<'e, N> {
|
|||||||
|
|
||||||
if self.surplus.is_none() || !opts.transferable_only {
|
if self.surplus.is_none() || !opts.transferable_only {
|
||||||
let mut votes_out;
|
let mut votes_out;
|
||||||
if is_weighted {
|
if is_weighted || self.surpfrac.is_none() {
|
||||||
votes_out = self.total.exhausted.votes_in.clone();
|
votes_out = self.total.exhausted.votes_in.clone();
|
||||||
} else {
|
} else {
|
||||||
votes_out = self.total.exhausted.ballots.clone();
|
votes_out = self.total.exhausted.ballots.clone();
|
||||||
|
13
tests/data/surplus_values_received.blt
Normal file
13
tests/data/surplus_values_received.blt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
# Comment: Constructed example - surplus votes need to be transferred at values received
|
||||||
|
4 3
|
||||||
|
12 1 2 0
|
||||||
|
3 1 2 3 0 # These votes need to be transferred to C at values received by B
|
||||||
|
9 2 0
|
||||||
|
8 3 0
|
||||||
|
7 4 0
|
||||||
|
0
|
||||||
|
"A"
|
||||||
|
"B"
|
||||||
|
"C"
|
||||||
|
"D"
|
||||||
|
"Surplus transferred at values received"
|
7
tests/data/surplus_values_received.csv
Normal file
7
tests/data/surplus_values_received.csv
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
Stage:,1,,2,,3,
|
||||||
|
Comment:,First preferences,,Surplus of A,,Surplus of B,
|
||||||
|
A,15,EL,9.75,EL,9.75,EL
|
||||||
|
B,9,H,14.25,EL,9.75,EL
|
||||||
|
C,8,H,8,H,9.05,EL
|
||||||
|
D,7,H,7,H,7,H
|
||||||
|
Exhausted,0,,0,,3.45,
|
|
BIN
tests/data/surplus_values_received.ods
Normal file
BIN
tests/data/surplus_values_received.ods
Normal file
Binary file not shown.
@ -15,8 +15,10 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
use crate::utils;
|
||||||
|
|
||||||
use opentally::election::{CandidateState, CountState, Election};
|
use opentally::election::{CandidateState, CountState, Election};
|
||||||
use opentally::numbers::Rational;
|
use opentally::numbers::{Fixed, Rational};
|
||||||
use opentally::parser::blt;
|
use opentally::parser::blt;
|
||||||
use opentally::stv;
|
use opentally::stv;
|
||||||
use opentally::ties::TieStrategy;
|
use opentally::ties::TieStrategy;
|
||||||
@ -146,3 +148,28 @@ fn tideman_a34_prsa1977_rational() {
|
|||||||
|
|
||||||
// Assert count completes
|
// Assert count completes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Surplus votes need to be transferred at values received
|
||||||
|
#[test]
|
||||||
|
fn surplus_values_received() {
|
||||||
|
let stv_opts = stv::STVOptionsBuilder::default()
|
||||||
|
.round_surplus_fractions(Some(2))
|
||||||
|
.round_values(Some(2))
|
||||||
|
.round_votes(Some(2))
|
||||||
|
.round_quota(Some(2))
|
||||||
|
.quota(stv::QuotaType::DroopExact)
|
||||||
|
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||||
|
.quota_mode(stv::QuotaMode::ERS97)
|
||||||
|
.surplus(stv::SurplusMethod::EG)
|
||||||
|
.transferable_only(true)
|
||||||
|
.exclusion(stv::ExclusionMethod::ByValue)
|
||||||
|
.bulk_exclude(true)
|
||||||
|
.defer_surpluses(true)
|
||||||
|
.build().unwrap();
|
||||||
|
|
||||||
|
Fixed::set_dps(5);
|
||||||
|
|
||||||
|
assert_eq!(stv_opts.describe::<Fixed>(), "--numbers fixed --decimals 5 --round-surplus-fractions 2 --round-values 2 --round-votes 2 --round-quota 2 --quota droop_exact --quota-criterion geq --quota-mode ers97 --surplus eg --transferable-only --exclusion by_value --bulk-exclude --defer-surpluses");
|
||||||
|
|
||||||
|
utils::read_validate_election::<Fixed>("tests/data/surplus_values_received.csv", "tests/data/surplus_values_received.blt", stv_opts, None, &["exhausted"]);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user