diff --git a/src/stv/gregory/transfers.rs b/src/stv/gregory/transfers.rs
index 6eb5d52..ac1e986 100644
--- a/src/stv/gregory/transfers.rs
+++ b/src/stv/gregory/transfers.rs
@@ -202,7 +202,8 @@ impl<'e, N: Number> TransferTable<'e, N> {
if self.surplus.is_none() || opts.sum_surplus_transfers == SumSurplusTransfersMode::ByValue {
for (_candidate, cell) in self.total.cells.iter_mut() {
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();
} else {
votes_out = cell.ballots.clone();
@@ -221,7 +222,7 @@ impl<'e, N: Number> TransferTable<'e, N> {
if self.surplus.is_none() || !opts.transferable_only {
let mut votes_out;
- if is_weighted {
+ if is_weighted || self.surpfrac.is_none() {
votes_out = self.total.exhausted.votes_in.clone();
} else {
votes_out = self.total.exhausted.ballots.clone();
diff --git a/tests/data/surplus_values_received.blt b/tests/data/surplus_values_received.blt
new file mode 100644
index 0000000..a2c3ea6
--- /dev/null
+++ b/tests/data/surplus_values_received.blt
@@ -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"
diff --git a/tests/data/surplus_values_received.csv b/tests/data/surplus_values_received.csv
new file mode 100644
index 0000000..f1842c0
--- /dev/null
+++ b/tests/data/surplus_values_received.csv
@@ -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,
diff --git a/tests/data/surplus_values_received.ods b/tests/data/surplus_values_received.ods
new file mode 100644
index 0000000..266209d
Binary files /dev/null and b/tests/data/surplus_values_received.ods differ
diff --git a/tests/tests_impl/special_cases.rs b/tests/tests_impl/special_cases.rs
index 172f9b2..dadc9a1 100644
--- a/tests/tests_impl/special_cases.rs
+++ b/tests/tests_impl/special_cases.rs
@@ -15,8 +15,10 @@
* along with this program. If not, see .
*/
+use crate::utils;
+
use opentally::election::{CandidateState, CountState, Election};
-use opentally::numbers::Rational;
+use opentally::numbers::{Fixed, Rational};
use opentally::parser::blt;
use opentally::stv;
use opentally::ties::TieStrategy;
@@ -146,3 +148,28 @@ fn tideman_a34_prsa1977_rational() {
// 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::(), "--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::("tests/data/surplus_values_received.csv", "tests/data/surplus_values_received.blt", stv_opts, None, &["exhausted"]);
+}