More work on unit/integration tests
This commit is contained in:
parent
f12db205b9
commit
a641b97d1f
@ -9,10 +9,11 @@ export CARGO_TARGET_DIR=target/coverage
|
||||
cargo test
|
||||
|
||||
llvm-profdata merge -sparse target/coverage/prof/*.profraw -o target/coverage/opentally.profdata
|
||||
for file in $(cargo test --no-run --message-format=json 2>/dev/null | jq -r "select(.profile.test == true) | .filenames[]"); do echo -n --object '"'$file'" '; done > target/coverage/objects
|
||||
|
||||
# Need "eval" to correctly parse arguments
|
||||
eval llvm-cov show target/coverage/debug/opentally -instr-profile=target/coverage/opentally.profdata -Xdemangler="$HOME/.cargo/bin/rustfilt" \
|
||||
$(for file in $(cargo test --no-run --message-format=json 2>/dev/null | jq -r "select(.profile.test == true) | .filenames[]"); do echo -n --object '"'$file'" '; done) \
|
||||
$(cat target/coverage/objects) \
|
||||
-ignore-filename-regex="$HOME/." \
|
||||
-ignore-filename-regex=rustc \
|
||||
-ignore-filename-regex=numbers/rational_num.rs \
|
||||
|
@ -35,7 +35,6 @@ use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
|
||||
/// An election to be counted
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), derive(Archive, Deserialize, Serialize))]
|
||||
pub struct Election<N> {
|
||||
/// Name of the election
|
||||
@ -93,7 +92,7 @@ impl<N: Number> Election<N> {
|
||||
}
|
||||
|
||||
/// A candidate in an [Election]
|
||||
#[derive(Clone, Eq, Hash, PartialEq)]
|
||||
#[derive(Eq, Hash, PartialEq)]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), derive(Archive, Deserialize, Serialize))]
|
||||
pub struct Candidate {
|
||||
/// Name of the candidate
|
||||
@ -465,7 +464,6 @@ impl<'a, N> Vote<'a, N> {
|
||||
}
|
||||
|
||||
/// A record of a voter's preferences
|
||||
#[derive(Clone)]
|
||||
#[cfg_attr(not(target_arch = "wasm32"), derive(Archive, Deserialize, Serialize))]
|
||||
pub struct Ballot<N> {
|
||||
/// Original value/weight of the ballot
|
||||
|
@ -16,7 +16,6 @@
|
||||
*/
|
||||
|
||||
/// Smart logger used in election counts
|
||||
#[derive(Clone)]
|
||||
pub struct Logger<'a> {
|
||||
/// [Vec] of log entries for the current stage
|
||||
pub entries: Vec<LogEntry<'a>>,
|
||||
@ -72,7 +71,6 @@ impl<'a> Logger<'a> {
|
||||
}
|
||||
|
||||
/// Represents either a literal or smart log entry
|
||||
#[derive(Clone)]
|
||||
pub enum LogEntry<'a> {
|
||||
/// Smart log entry - see [SmartLogEntry]
|
||||
Smart(SmartLogEntry<'a>),
|
||||
@ -81,7 +79,6 @@ pub enum LogEntry<'a> {
|
||||
}
|
||||
|
||||
/// Smart log entry
|
||||
#[derive(Clone)]
|
||||
pub struct SmartLogEntry<'a> {
|
||||
template1: &'a str,
|
||||
template2: &'a str,
|
||||
|
@ -176,6 +176,16 @@ impl Assign<&Self> for Fixed {
|
||||
fn assign(&mut self, src: &Self) { self.0 = src.0.clone() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assign() {
|
||||
Fixed::set_dps(2);
|
||||
let a = Fixed::parse("123.45");
|
||||
let b = Fixed::parse("678.90");
|
||||
|
||||
let mut x = a.clone(); x.assign(b.clone()); assert_eq!(x, b);
|
||||
let mut x = a.clone(); x.assign(&b); assert_eq!(x, b);
|
||||
}
|
||||
|
||||
impl From<usize> for Fixed {
|
||||
fn from(n: usize) -> Self { Self(IBig::from(n) * get_factor()) }
|
||||
}
|
||||
@ -219,6 +229,13 @@ impl fmt::Display for Fixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_debug() {
|
||||
Fixed::set_dps(2);
|
||||
let x = Fixed::parse("123.4"); assert_eq!(format!("{}", x), "123.40");
|
||||
let x = Fixed::parse("123.4"); assert_eq!(format!("{:?}", x), "Fixed(12340)");
|
||||
}
|
||||
|
||||
impl One for Fixed {
|
||||
fn one() -> Self { Self(get_factor().clone()) }
|
||||
}
|
||||
@ -255,9 +272,7 @@ impl ops::Div for Fixed {
|
||||
|
||||
impl ops::Rem for Fixed {
|
||||
type Output = Self;
|
||||
fn rem(self, _rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
fn rem(self, rhs: Self) -> Self::Output { Self(self.0 % rhs.0) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -270,6 +285,7 @@ fn arith_owned_owned() {
|
||||
assert_eq!(a.clone() - b.clone(), Fixed::parse("-555.45"));
|
||||
assert_eq!(a.clone() * b.clone(), Fixed::parse("83810.20")); // = 83810.205 rounds to 83810.20
|
||||
assert_eq!(a.clone() / b.clone(), Fixed::parse("0.18"));
|
||||
assert_eq!(b.clone() % a.clone(), Fixed::parse("61.65"));
|
||||
}
|
||||
|
||||
impl ops::Add<&Self> for Fixed {
|
||||
@ -294,9 +310,7 @@ impl ops::Div<&Self> for Fixed {
|
||||
|
||||
impl ops::Rem<&Self> for Fixed {
|
||||
type Output = Self;
|
||||
fn rem(self, _rhs: &Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
fn rem(self, rhs: &Self) -> Self::Output { Self(self.0 % &rhs.0) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -309,6 +323,7 @@ fn arith_owned_ref() {
|
||||
assert_eq!(a.clone() - &b, Fixed::parse("-555.45"));
|
||||
assert_eq!(a.clone() * &b, Fixed::parse("83810.20"));
|
||||
assert_eq!(a.clone() / &b, Fixed::parse("0.18"));
|
||||
assert_eq!(b.clone() % &a, Fixed::parse("61.65"));
|
||||
}
|
||||
|
||||
impl ops::AddAssign for Fixed {
|
||||
@ -334,9 +349,7 @@ impl ops::DivAssign for Fixed {
|
||||
}
|
||||
|
||||
impl ops::RemAssign for Fixed {
|
||||
fn rem_assign(&mut self, _rhs: Self) {
|
||||
todo!()
|
||||
}
|
||||
fn rem_assign(&mut self, rhs: Self) { self.0 %= rhs.0; }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -349,6 +362,7 @@ fn arithassign_owned() {
|
||||
let mut x = a.clone(); x -= b.clone(); assert_eq!(x, Fixed::parse("-555.45"));
|
||||
let mut x = a.clone(); x *= b.clone(); assert_eq!(x, Fixed::parse("83810.20"));
|
||||
let mut x = a.clone(); x /= b.clone(); assert_eq!(x, Fixed::parse("0.18"));
|
||||
let mut x = b.clone(); x %= a.clone(); assert_eq!(x, Fixed::parse("61.65"));
|
||||
}
|
||||
|
||||
impl ops::AddAssign<&Self> for Fixed {
|
||||
@ -374,9 +388,7 @@ impl ops::DivAssign<&Self> for Fixed {
|
||||
}
|
||||
|
||||
impl ops::RemAssign<&Self> for Fixed {
|
||||
fn rem_assign(&mut self, _rhs: &Self) {
|
||||
todo!()
|
||||
}
|
||||
fn rem_assign(&mut self, rhs: &Self) { self.0 %= &rhs.0; }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -389,6 +401,7 @@ fn arithassign_ref() {
|
||||
let mut x = a.clone(); x -= &b; assert_eq!(x, Fixed::parse("-555.45"));
|
||||
let mut x = a.clone(); x *= &b; assert_eq!(x, Fixed::parse("83810.20"));
|
||||
let mut x = a.clone(); x /= &b; assert_eq!(x, Fixed::parse("0.18"));
|
||||
let mut x = b.clone(); x %= &a; assert_eq!(x, Fixed::parse("61.65"));
|
||||
}
|
||||
|
||||
impl ops::Neg for &Fixed {
|
||||
@ -418,9 +431,7 @@ impl ops::Div<Self> for &Fixed {
|
||||
|
||||
impl ops::Rem<Self> for &Fixed {
|
||||
type Output = Fixed;
|
||||
fn rem(self, _rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
fn rem(self, rhs: Self) -> Self::Output { Fixed(&self.0 % &rhs.0) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -433,6 +444,7 @@ fn arith_ref_ref() {
|
||||
assert_eq!(&a - &b, Fixed::parse("-555.45"));
|
||||
assert_eq!(&a * &b, Fixed::parse("83810.20"));
|
||||
assert_eq!(&a / &b, Fixed::parse("0.18"));
|
||||
assert_eq!(&b % &a, Fixed::parse("61.65"));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -220,6 +220,16 @@ impl Assign<&Self> for GuardedFixed {
|
||||
fn assign(&mut self, src: &Self) { self.0 = src.0.clone() }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assign() {
|
||||
GuardedFixed::set_dps(2);
|
||||
let a = GuardedFixed::parse("123.45");
|
||||
let b = GuardedFixed::parse("678.90");
|
||||
|
||||
let mut x = a.clone(); x.assign(b.clone()); assert_eq!(x, b);
|
||||
let mut x = a.clone(); x.assign(&b); assert_eq!(x, b);
|
||||
}
|
||||
|
||||
impl From<usize> for GuardedFixed {
|
||||
fn from(n: usize) -> Self { Self(IBig::from(n) * get_factor()) }
|
||||
}
|
||||
@ -262,6 +272,13 @@ impl fmt::Display for GuardedFixed {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_debug() {
|
||||
GuardedFixed::set_dps(2);
|
||||
let x = GuardedFixed::parse("123.4"); assert_eq!(format!("{}", x), "123.40");
|
||||
let x = GuardedFixed::parse("123.4"); assert_eq!(format!("{:?}", x), "GuardedFixed(1234000)");
|
||||
}
|
||||
|
||||
impl One for GuardedFixed {
|
||||
fn one() -> Self { Self(get_factor().clone()) }
|
||||
}
|
||||
@ -298,9 +315,7 @@ impl ops::Div for GuardedFixed {
|
||||
|
||||
impl ops::Rem for GuardedFixed {
|
||||
type Output = Self;
|
||||
fn rem(self, _rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
fn rem(self, rhs: Self) -> Self::Output { Self(self.0 % rhs.0) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -313,6 +328,7 @@ fn arith_owned_owned() {
|
||||
assert_eq!(a.clone() - b.clone(), GuardedFixed::parse("-555.45"));
|
||||
assert_eq!(a.clone() * b.clone(), GuardedFixed::parse("83810.205")); // Must compare to 3 d.p.s as doesn't meet FACTOR_CMP
|
||||
assert_eq!(a.clone() / b.clone(), GuardedFixed::parse("0.18")); // Meets FACTOR_CMP so compare only 2 d.p.s
|
||||
assert_eq!(b.clone() % a.clone(), GuardedFixed::parse("61.65"));
|
||||
}
|
||||
|
||||
impl ops::Add<&Self> for GuardedFixed {
|
||||
@ -337,9 +353,7 @@ impl ops::Div<&Self> for GuardedFixed {
|
||||
|
||||
impl ops::Rem<&Self> for GuardedFixed {
|
||||
type Output = Self;
|
||||
fn rem(self, _rhs: &Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
fn rem(self, rhs: &Self) -> Self::Output { Self(self.0 % &rhs.0) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -352,6 +366,7 @@ fn arith_owned_ref() {
|
||||
assert_eq!(a.clone() - &b, GuardedFixed::parse("-555.45"));
|
||||
assert_eq!(a.clone() * &b, GuardedFixed::parse("83810.205"));
|
||||
assert_eq!(a.clone() / &b, GuardedFixed::parse("0.18"));
|
||||
assert_eq!(b.clone() % &a, GuardedFixed::parse("61.65"));
|
||||
}
|
||||
|
||||
impl ops::AddAssign for GuardedFixed {
|
||||
@ -377,9 +392,7 @@ impl ops::DivAssign for GuardedFixed {
|
||||
}
|
||||
|
||||
impl ops::RemAssign for GuardedFixed {
|
||||
fn rem_assign(&mut self, _rhs: Self) {
|
||||
todo!()
|
||||
}
|
||||
fn rem_assign(&mut self, rhs: Self) { self.0 %= rhs.0; }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -392,6 +405,7 @@ fn arithassign_owned() {
|
||||
let mut x = a.clone(); x -= b.clone(); assert_eq!(x, GuardedFixed::parse("-555.45"));
|
||||
let mut x = a.clone(); x *= b.clone(); assert_eq!(x, GuardedFixed::parse("83810.205"));
|
||||
let mut x = a.clone(); x /= b.clone(); assert_eq!(x, GuardedFixed::parse("0.18"));
|
||||
let mut x = b.clone(); x %= a.clone(); assert_eq!(x, GuardedFixed::parse("61.65"));
|
||||
}
|
||||
|
||||
impl ops::AddAssign<&Self> for GuardedFixed {
|
||||
@ -417,9 +431,7 @@ impl ops::DivAssign<&Self> for GuardedFixed {
|
||||
}
|
||||
|
||||
impl ops::RemAssign<&Self> for GuardedFixed {
|
||||
fn rem_assign(&mut self, _rhs: &Self) {
|
||||
todo!()
|
||||
}
|
||||
fn rem_assign(&mut self, rhs: &Self) { self.0 %= &rhs.0; }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -432,6 +444,7 @@ fn arithassign_ref() {
|
||||
let mut x = a.clone(); x -= &b; assert_eq!(x, GuardedFixed::parse("-555.45"));
|
||||
let mut x = a.clone(); x *= &b; assert_eq!(x, GuardedFixed::parse("83810.205"));
|
||||
let mut x = a.clone(); x /= &b; assert_eq!(x, GuardedFixed::parse("0.18"));
|
||||
let mut x = b.clone(); x %= &a; assert_eq!(x, GuardedFixed::parse("61.65"));
|
||||
}
|
||||
|
||||
impl ops::Neg for &GuardedFixed {
|
||||
@ -461,9 +474,7 @@ impl ops::Div<Self> for &GuardedFixed {
|
||||
|
||||
impl ops::Rem<Self> for &GuardedFixed {
|
||||
type Output = GuardedFixed;
|
||||
fn rem(self, _rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
fn rem(self, rhs: Self) -> Self::Output { GuardedFixed(&self.0 % &rhs.0) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -476,6 +487,7 @@ fn arith_ref_ref() {
|
||||
assert_eq!(&a - &b, GuardedFixed::parse("-555.45"));
|
||||
assert_eq!(&a * &b, GuardedFixed::parse("83810.205"));
|
||||
assert_eq!(&a / &b, GuardedFixed::parse("0.18"));
|
||||
assert_eq!(&b % &a, GuardedFixed::parse("61.65"));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -54,6 +54,12 @@ impl Number for NativeFloat64 {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_debug() {
|
||||
let x = NativeFloat64::parse("123.4"); assert_eq!(format!("{}", x), format!("{}", 123.40_f64));
|
||||
let x = NativeFloat64::parse("123.4"); assert_eq!(format!("{:?}", x), format!("NativeFloat64({})", 123.40_f64));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rounding() {
|
||||
let mut x = NativeFloat64::parse("55.550"); x.floor_mut(2); assert_eq!(x, NativeFloat64::parse("55.55"));
|
||||
@ -90,6 +96,15 @@ impl Assign<&NativeFloat64> for NativeFloat64 {
|
||||
fn assign(&mut self, src: &NativeFloat64) { self.0 = src.0; }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assign() {
|
||||
let a = NativeFloat64::parse("123.45");
|
||||
let b = NativeFloat64::parse("678.90");
|
||||
|
||||
let mut x = a.clone(); x.assign(b.clone()); assert_eq!(x, b);
|
||||
let mut x = a.clone(); x.assign(&b); assert_eq!(x, b);
|
||||
}
|
||||
|
||||
impl From<usize> for NativeFloat64 {
|
||||
fn from(n: usize) -> Self { Self(n as ImplType) }
|
||||
}
|
||||
@ -139,9 +154,7 @@ impl ops::Div for NativeFloat64 {
|
||||
|
||||
impl ops::Rem for NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn rem(self, _rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
fn rem(self, rhs: Self) -> Self::Output { Self(self.0 % rhs.0) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -153,33 +166,32 @@ fn arith_owned_owned() {
|
||||
assert_eq!(a.clone() - b.clone(), NativeFloat64::from(123.45_f64 - 678.90_f64));
|
||||
assert_eq!(a.clone() * b.clone(), NativeFloat64::from(123.45_f64 * 678.90_f64));
|
||||
assert_eq!(a.clone() / b.clone(), NativeFloat64::from(123.45_f64 / 678.90_f64));
|
||||
assert_eq!(b.clone() % a.clone(), NativeFloat64::from(678.90_f64 % 123.45_f64));
|
||||
}
|
||||
|
||||
impl ops::Add<&NativeFloat64> for NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn add(self, rhs: &NativeFloat64) -> Self::Output { Self(self.0 + &rhs.0) }
|
||||
fn add(self, rhs: &NativeFloat64) -> Self::Output { Self(self.0 + rhs.0) }
|
||||
}
|
||||
|
||||
impl ops::Sub<&NativeFloat64> for NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn sub(self, rhs: &NativeFloat64) -> Self::Output { Self(self.0 - &rhs.0) }
|
||||
fn sub(self, rhs: &NativeFloat64) -> Self::Output { Self(self.0 - rhs.0) }
|
||||
}
|
||||
|
||||
impl ops::Mul<&NativeFloat64> for NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn mul(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 * &rhs.0) }
|
||||
fn mul(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 * rhs.0) }
|
||||
}
|
||||
|
||||
impl ops::Div<&NativeFloat64> for NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn div(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 / &rhs.0) }
|
||||
fn div(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 / rhs.0) }
|
||||
}
|
||||
|
||||
impl ops::Rem<&NativeFloat64> for NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn rem(self, _rhs: &NativeFloat64) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
fn rem(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 % rhs.0) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -191,6 +203,7 @@ fn arith_owned_ref() {
|
||||
assert_eq!(a.clone() - &b, NativeFloat64::from(123.45_f64 - 678.90_f64));
|
||||
assert_eq!(a.clone() * &b, NativeFloat64::from(123.45_f64 * 678.90_f64));
|
||||
assert_eq!(a.clone() / &b, NativeFloat64::from(123.45_f64 / 678.90_f64));
|
||||
assert_eq!(b.clone() % &a, NativeFloat64::from(678.90_f64 % 123.45_f64));
|
||||
}
|
||||
|
||||
impl ops::AddAssign for NativeFloat64 {
|
||||
@ -206,13 +219,11 @@ impl ops::MulAssign for NativeFloat64 {
|
||||
}
|
||||
|
||||
impl ops::DivAssign for NativeFloat64 {
|
||||
fn div_assign(&mut self, rhs: Self) { self.0 /= &rhs.0; }
|
||||
fn div_assign(&mut self, rhs: Self) { self.0 /= rhs.0; }
|
||||
}
|
||||
|
||||
impl ops::RemAssign for NativeFloat64 {
|
||||
fn rem_assign(&mut self, _rhs: Self) {
|
||||
todo!()
|
||||
}
|
||||
fn rem_assign(&mut self, rhs: Self) { self.0 %= rhs.0; }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -224,28 +235,27 @@ fn arithassign_owned() {
|
||||
let mut x = a.clone(); x -= b.clone(); assert_eq!(x, NativeFloat64::from(123.45_f64 - 678.90_f64));
|
||||
let mut x = a.clone(); x *= b.clone(); assert_eq!(x, NativeFloat64::from(123.45_f64 * 678.90_f64));
|
||||
let mut x = a.clone(); x /= b.clone(); assert_eq!(x, NativeFloat64::from(123.45_f64 / 678.90_f64));
|
||||
let mut x = b.clone(); x %= a.clone(); assert_eq!(x, NativeFloat64::from(678.90_f64 % 123.45_f64));
|
||||
}
|
||||
|
||||
impl ops::AddAssign<&NativeFloat64> for NativeFloat64 {
|
||||
fn add_assign(&mut self, rhs: &NativeFloat64) { self.0 += &rhs.0; }
|
||||
fn add_assign(&mut self, rhs: &NativeFloat64) { self.0 += rhs.0; }
|
||||
}
|
||||
|
||||
impl ops::SubAssign<&NativeFloat64> for NativeFloat64 {
|
||||
fn sub_assign(&mut self, rhs: &NativeFloat64) { self.0 -= &rhs.0; }
|
||||
fn sub_assign(&mut self, rhs: &NativeFloat64) { self.0 -= rhs.0; }
|
||||
}
|
||||
|
||||
impl ops::MulAssign<&NativeFloat64> for NativeFloat64 {
|
||||
fn mul_assign(&mut self, rhs: &NativeFloat64) { self.0 *= &rhs.0; }
|
||||
fn mul_assign(&mut self, rhs: &NativeFloat64) { self.0 *= rhs.0; }
|
||||
}
|
||||
|
||||
impl ops::DivAssign<&NativeFloat64> for NativeFloat64 {
|
||||
fn div_assign(&mut self, rhs: &NativeFloat64) { self.0 /= &rhs.0; }
|
||||
fn div_assign(&mut self, rhs: &NativeFloat64) { self.0 /= rhs.0; }
|
||||
}
|
||||
|
||||
impl ops::RemAssign<&NativeFloat64> for NativeFloat64 {
|
||||
fn rem_assign(&mut self, _rhs: &NativeFloat64) {
|
||||
todo!()
|
||||
}
|
||||
fn rem_assign(&mut self, rhs: &NativeFloat64) { self.0 %= rhs.0; }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -257,38 +267,37 @@ fn arithassign_ref() {
|
||||
let mut x = a.clone(); x -= &b; assert_eq!(x, NativeFloat64::from(123.45_f64 - 678.90_f64));
|
||||
let mut x = a.clone(); x *= &b; assert_eq!(x, NativeFloat64::from(123.45_f64 * 678.90_f64));
|
||||
let mut x = a.clone(); x /= &b; assert_eq!(x, NativeFloat64::from(123.45_f64 / 678.90_f64));
|
||||
let mut x = b.clone(); x %= &a; assert_eq!(x, NativeFloat64::from(678.90_f64 % 123.45_f64));
|
||||
}
|
||||
|
||||
impl ops::Neg for &NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn neg(self) -> Self::Output { NativeFloat64(-&self.0) }
|
||||
fn neg(self) -> Self::Output { NativeFloat64(-self.0) }
|
||||
}
|
||||
|
||||
impl ops::Add<Self> for &NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn add(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(&self.0 + &rhs.0) }
|
||||
fn add(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 + rhs.0) }
|
||||
}
|
||||
|
||||
impl ops::Sub<Self> for &NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn sub(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(&self.0 - &rhs.0) }
|
||||
fn sub(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 - rhs.0) }
|
||||
}
|
||||
|
||||
impl ops::Mul<Self> for &NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn mul(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(&self.0 * &rhs.0) }
|
||||
fn mul(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 * rhs.0) }
|
||||
}
|
||||
|
||||
impl ops::Div<Self> for &NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn div(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(&self.0 / &rhs.0) }
|
||||
fn div(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 / rhs.0) }
|
||||
}
|
||||
|
||||
impl ops::Rem<Self> for &NativeFloat64 {
|
||||
type Output = NativeFloat64;
|
||||
fn rem(self, _rhs: &NativeFloat64) -> Self::Output {
|
||||
todo!()
|
||||
}
|
||||
fn rem(self, rhs: &NativeFloat64) -> Self::Output { NativeFloat64(self.0 % rhs.0) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -300,6 +309,7 @@ fn arith_ref_ref() {
|
||||
assert_eq!(&a - &b, NativeFloat64::from(123.45_f64 - 678.90_f64));
|
||||
assert_eq!(&a * &b, NativeFloat64::from(123.45_f64 * 678.90_f64));
|
||||
assert_eq!(&a / &b, NativeFloat64::from(123.45_f64 / 678.90_f64));
|
||||
assert_eq!(&b % &a, NativeFloat64::from(678.90_f64 % 123.45_f64));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -104,6 +104,12 @@ impl Number for Rational {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn describe() {
|
||||
// Never executed - just for the sake of code coverage
|
||||
assert_eq!(Rational::describe(), "--numbers rational");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rounding() {
|
||||
let mut x = Rational::parse("55.550"); x.floor_mut(2); assert_eq!(x, Rational::parse("55.55"));
|
||||
@ -140,6 +146,15 @@ impl Assign<&Self> for Rational {
|
||||
fn assign(&mut self, src: &Self) { self.0.assign(&src.0) }
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn assign() {
|
||||
let a = Rational::parse("123.45");
|
||||
let b = Rational::parse("678.90");
|
||||
|
||||
let mut x = a.clone(); x.assign(b.clone()); assert_eq!(x, b);
|
||||
let mut x = a.clone(); x.assign(&b); assert_eq!(x, b);
|
||||
}
|
||||
|
||||
impl From<usize> for Rational {
|
||||
fn from(n: usize) -> Self { Self(rug::Rational::from(n)) }
|
||||
}
|
||||
@ -175,6 +190,13 @@ impl fmt::Display for Rational {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn display_debug() {
|
||||
let x = Rational::parse("123.4"); assert_eq!(format!("{}", x), "617/5");
|
||||
let x = Rational::parse("123.4"); assert_eq!(format!("{:.2}", x), "123.40");
|
||||
let x = Rational::parse("123.4"); assert_eq!(format!("{:?}", x), "Rational(617/5)");
|
||||
}
|
||||
|
||||
impl One for Rational {
|
||||
fn one() -> Self { Self(rug::Rational::from(1)) }
|
||||
}
|
||||
@ -216,8 +238,12 @@ impl ops::Div for Rational {
|
||||
|
||||
impl ops::Rem for Rational {
|
||||
type Output = Self;
|
||||
fn rem(self, _rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
fn rem(self, rhs: Self) -> Self::Output {
|
||||
// TODO: Is there a cleaner way of implementing this?
|
||||
let mut quotient = self.0 / &rhs.0;
|
||||
quotient.rem_trunc_mut();
|
||||
quotient *= rhs.0;
|
||||
return Self(quotient);
|
||||
}
|
||||
}
|
||||
|
||||
@ -229,7 +255,8 @@ fn arith_owned_owned() {
|
||||
assert_eq!(a.clone() + b.clone(), Rational::parse("802.35"));
|
||||
assert_eq!(a.clone() - b.clone(), Rational::parse("-555.45"));
|
||||
assert_eq!(a.clone() * b.clone(), Rational::parse("83810.205"));
|
||||
assert_eq!((a.clone() / b.clone()) * b, a);
|
||||
assert_eq!((a.clone() / b.clone()) * b.clone(), a);
|
||||
assert_eq!(b.clone() % a.clone(), Rational::parse("61.65"));
|
||||
}
|
||||
|
||||
impl ops::Add<&Self> for Rational {
|
||||
@ -254,8 +281,11 @@ impl ops::Div<&Self> for Rational {
|
||||
|
||||
impl ops::Rem<&Self> for Rational {
|
||||
type Output = Self;
|
||||
fn rem(self, _rhs: &Self) -> Self::Output {
|
||||
todo!()
|
||||
fn rem(self, rhs: &Self) -> Self::Output {
|
||||
let mut quotient = self.0 / &rhs.0;
|
||||
quotient.rem_trunc_mut();
|
||||
quotient *= &rhs.0;
|
||||
return Self(quotient);
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,7 +297,8 @@ fn arith_owned_ref() {
|
||||
assert_eq!(a.clone() + &b, Rational::parse("802.35"));
|
||||
assert_eq!(a.clone() - &b, Rational::parse("-555.45"));
|
||||
assert_eq!(a.clone() * &b, Rational::parse("83810.205"));
|
||||
assert_eq!((a.clone() / &b) * b, a);
|
||||
assert_eq!((a.clone() / &b) * &b, a);
|
||||
assert_eq!(b.clone() % &a, Rational::parse("61.65"));
|
||||
}
|
||||
|
||||
impl ops::AddAssign for Rational {
|
||||
@ -287,8 +318,10 @@ impl ops::DivAssign for Rational {
|
||||
}
|
||||
|
||||
impl ops::RemAssign for Rational {
|
||||
fn rem_assign(&mut self, _rhs: Self) {
|
||||
todo!()
|
||||
fn rem_assign(&mut self, rhs: Self) {
|
||||
self.0 /= &rhs.0;
|
||||
self.0.rem_trunc_mut();
|
||||
self.0 *= rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,7 +333,8 @@ fn arithassign_owned() {
|
||||
let mut x = a.clone(); x += b.clone(); assert_eq!(x, Rational::parse("802.35"));
|
||||
let mut x = a.clone(); x -= b.clone(); assert_eq!(x, Rational::parse("-555.45"));
|
||||
let mut x = a.clone(); x *= b.clone(); assert_eq!(x, Rational::parse("83810.205"));
|
||||
let mut x = a.clone(); x /= b.clone(); x *= b; assert_eq!(x, a);
|
||||
let mut x = a.clone(); x /= b.clone(); x *= &b; assert_eq!(x, a);
|
||||
let mut x = b.clone(); x %= a.clone(); assert_eq!(x, Rational::parse("61.65"));
|
||||
}
|
||||
|
||||
impl ops::AddAssign<&Self> for Rational {
|
||||
@ -320,8 +354,10 @@ impl ops::DivAssign<&Self> for Rational {
|
||||
}
|
||||
|
||||
impl ops::RemAssign<&Self> for Rational {
|
||||
fn rem_assign(&mut self, _rhs: &Self) {
|
||||
todo!()
|
||||
fn rem_assign(&mut self, rhs: &Self) {
|
||||
self.0 /= &rhs.0;
|
||||
self.0.rem_trunc_mut();
|
||||
self.0 *= &rhs.0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -333,7 +369,8 @@ fn arithassign_ref() {
|
||||
let mut x = a.clone(); x += &b; assert_eq!(x, Rational::parse("802.35"));
|
||||
let mut x = a.clone(); x -= &b; assert_eq!(x, Rational::parse("-555.45"));
|
||||
let mut x = a.clone(); x *= &b; assert_eq!(x, Rational::parse("83810.205"));
|
||||
let mut x = a.clone(); x /= &b; x *= b; assert_eq!(x, a);
|
||||
let mut x = a.clone(); x /= &b; x *= &b; assert_eq!(x, a);
|
||||
let mut x = b.clone(); x %= &a; assert_eq!(x, Rational::parse("61.65"));
|
||||
}
|
||||
|
||||
impl ops::Neg for &Rational {
|
||||
@ -363,8 +400,11 @@ impl ops::Div<Self> for &Rational {
|
||||
|
||||
impl ops::Rem<Self> for &Rational {
|
||||
type Output = Rational;
|
||||
fn rem(self, _rhs: Self) -> Self::Output {
|
||||
todo!()
|
||||
fn rem(self, rhs: Self) -> Self::Output {
|
||||
let mut quotient = rug::Rational::from(&self.0 / &rhs.0);
|
||||
quotient.rem_trunc_mut();
|
||||
quotient *= &rhs.0;
|
||||
return Rational(quotient);
|
||||
}
|
||||
}
|
||||
|
||||
@ -376,7 +416,8 @@ fn arith_ref_ref() {
|
||||
assert_eq!(&a + &b, Rational::parse("802.35"));
|
||||
assert_eq!(&a - &b, Rational::parse("-555.45"));
|
||||
assert_eq!(&a * &b, Rational::parse("83810.205"));
|
||||
assert_eq!((&a / &b) * b, a);
|
||||
assert_eq!((&a / &b) * &b, a);
|
||||
assert_eq!(&b % &a, Rational::parse("61.65"));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -19,7 +19,6 @@ use ibig::UBig;
|
||||
use sha2::{Digest, Sha256};
|
||||
|
||||
/// Deterministic random number generator using SHA256
|
||||
#[derive(Clone)]
|
||||
pub struct SHARandom<'r> {
|
||||
seed: &'r str,
|
||||
counter: usize,
|
||||
|
@ -460,15 +460,15 @@ impl<'e, N: Number> TransferTable<'e, N> {
|
||||
}
|
||||
|
||||
/// Render table as plain text
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
//#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn render_text(&self, opts: &STVOptions) -> String {
|
||||
return self.render(opts).to_string();
|
||||
}
|
||||
|
||||
/// Render table as HTML
|
||||
pub fn render_html(&self, opts: &STVOptions) -> String {
|
||||
return self.render(opts).to_string();
|
||||
}
|
||||
// Render table as HTML
|
||||
//pub fn render_html(&self, opts: &STVOptions) -> String {
|
||||
// return self.render(opts).to_string();
|
||||
//}
|
||||
}
|
||||
|
||||
/// Column in a [TransferTable]
|
||||
|
@ -68,7 +68,7 @@ pub struct STVOptions {
|
||||
pub sum_surplus_transfers: SumSurplusTransfersMode,
|
||||
|
||||
/// (Meek STV) Limit for stopping iteration of surplus distribution
|
||||
#[builder(default)]
|
||||
#[builder(default=r#"String::from("0.001%")"#)]
|
||||
pub meek_surplus_tolerance: String,
|
||||
|
||||
/// Convert ballots with value >1 to multiple ballots of value 1 (used only for [STVOptions::describe])
|
||||
@ -88,7 +88,7 @@ pub struct STVOptions {
|
||||
pub quota_mode: QuotaMode,
|
||||
|
||||
/// Tie-breaking method
|
||||
#[builder(default)]
|
||||
#[builder(default="vec![TieStrategy::Prompt]")]
|
||||
pub ties: Vec<TieStrategy>,
|
||||
|
||||
/// Method of surplus distributions
|
||||
@ -180,12 +180,12 @@ impl STVOptions {
|
||||
if self.normalise_ballots { flags.push("--normalise-ballots".to_string()); }
|
||||
if self.quota != QuotaType::Droop { flags.push(self.quota.describe()); }
|
||||
if self.quota_criterion != QuotaCriterion::Greater { flags.push(self.quota_criterion.describe()); }
|
||||
if self.surplus != SurplusMethod::Meek && self.quota_mode != QuotaMode::Static { flags.push(self.quota_mode.describe()); }
|
||||
if self.quota_mode != QuotaMode::Static { flags.push(self.quota_mode.describe()); }
|
||||
let ties_str = self.ties.iter().map(|t| t.describe()).join(" ");
|
||||
if ties_str != "prompt" { flags.push(format!("--ties {}", ties_str)); }
|
||||
for t in self.ties.iter() { if let TieStrategy::Random(seed) = t { flags.push(format!("--random-seed {}", seed)); } }
|
||||
if self.surplus != SurplusMethod::WIG { flags.push(self.surplus.describe()); }
|
||||
if self.surplus == SurplusMethod::WIG || self.surplus == SurplusMethod::UIG || self.surplus == SurplusMethod::EG {
|
||||
if self.surplus != SurplusMethod::Meek {
|
||||
if self.surplus_order != SurplusOrder::BySize { flags.push(self.surplus_order.describe()); }
|
||||
if self.transferable_only { flags.push("--transferable-only".to_string()); }
|
||||
if self.exclusion != ExclusionMethod::SingleStage { flags.push(self.exclusion.describe()); }
|
||||
|
@ -177,7 +177,7 @@ macro_rules! impl_type {
|
||||
/// Call [render_html](crate::stv::transfers::TransferTable::render_html) on [CountState::transfer_table]
|
||||
pub fn transfer_table_render_html(&self, opts: &STVOptions) -> Option<String> {
|
||||
return match &self.0.transfer_table {
|
||||
Some(tt) => Some(tt.render_html(&opts.0)), // TODO
|
||||
Some(tt) => Some(tt.render_text(&opts.0)), // TODO
|
||||
None => None,
|
||||
};
|
||||
}
|
||||
|
@ -33,5 +33,7 @@ fn act_kurrajong20_rational() {
|
||||
.early_bulk_elect(false)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--round-votes 6 --round-quota 0 --quota-criterion geq --surplus eg --surplus-order by_order --transferable-only --exclusion by_value --no-early-bulk-elect");
|
||||
|
||||
utils::read_validate_election::<Rational>("tests/data/ACT2020Kurrajong.csv", "tests/data/ACT2020Kurrajong.blt", stv_opts, Some(6), &["exhausted", "lbf"]);
|
||||
}
|
||||
|
@ -70,5 +70,7 @@ fn aec_tas19_rational() {
|
||||
.bulk_exclude(true)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--round-votes 0 --round-quota 0 --quota-criterion geq --surplus uig --surplus-order by_order --exclusion by_value --bulk-exclude");
|
||||
|
||||
utils::validate_election::<Rational>(stages, records, election, stv_opts, None, &["exhausted", "lbf"]);
|
||||
}
|
||||
|
@ -34,5 +34,7 @@ fn cambridge_cc03_rational() {
|
||||
.min_threshold("49".to_string())
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--round-quota 0 --normalise-ballots --quota-criterion geq --surplus cincinnati --transferable-only --sample nth_ballot --sample-per-ballot --no-early-bulk-elect --min-threshold 49");
|
||||
|
||||
utils::read_validate_election::<Rational>("tests/data/CambCC2003.csv", "tests/data/CambCC2003.blt", stv_opts, None, &["exhausted"]);
|
||||
}
|
||||
|
@ -19,14 +19,14 @@ use assert_cmd::Command;
|
||||
use predicates::prelude::*;
|
||||
|
||||
#[test]
|
||||
fn cli_ers97old() {
|
||||
fn cli_ers97old_fixed5() {
|
||||
Command::cargo_bin("opentally").expect("Cargo Error")
|
||||
.args(&["stv", "tests/data/ers97old.blt", "--numbers", "fixed", "--decimals", "5", "--round-tvs", "2", "--round-weights", "2", "--round-votes", "2", "--round-quota", "2", "--quota", "droop_exact", "--quota-mode", "ers97", "--surplus", "eg", "--transferable-only", "--exclusion", "by_value"])
|
||||
.assert().success();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cli_ers97_transfers_detail() {
|
||||
fn cli_ers97_fixed5_transfers_detail() {
|
||||
Command::cargo_bin("opentally").expect("Cargo Error")
|
||||
.args(&["stv", "tests/data/ers97.blt", "--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", "--transfers-detail"])
|
||||
.assert().success();
|
||||
|
@ -35,5 +35,7 @@ fn ers97_coe_rational() {
|
||||
.defer_surpluses(true)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--round-surplus-fractions 2 --round-values 2 --round-votes 2 --round-quota 2 --sum-surplus-transfers per_ballot --quota-criterion geq --surplus eg --transferable-only --exclusion by_value --defer-surpluses");
|
||||
|
||||
utils::read_validate_election::<Rational>("tests/data/ers97_coe.csv", "tests/data/ers97.blt", stv_opts, None, &["nt"]);
|
||||
}
|
||||
|
@ -30,5 +30,7 @@ fn csm15_float64() {
|
||||
.bulk_exclude(true)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<NativeFloat64>(), "--numbers float64 --round-quota 0 --quota-criterion geq --exclusion wright --no-early-bulk-elect --bulk-exclude");
|
||||
|
||||
utils::read_validate_election::<NativeFloat64>("tests/data/CSM15.csv", "tests/data/CSM15.blt", stv_opts, Some(6), &["quota"]);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
|
||||
use crate::utils;
|
||||
|
||||
use opentally::numbers::Rational;
|
||||
use opentally::numbers::{Fixed, GuardedFixed, NativeFloat64, Rational};
|
||||
use opentally::stv;
|
||||
|
||||
use assert_cmd::Command;
|
||||
@ -42,6 +42,8 @@ fn ers97old_rational() {
|
||||
.defer_surpluses(true)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--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 --no-early-bulk-elect --bulk-exclude --defer-surpluses");
|
||||
|
||||
utils::read_validate_election::<Rational>("tests/data/ers97old.csv", "tests/data/ers97old.blt", stv_opts, None, &["nt", "vre"]);
|
||||
}
|
||||
|
||||
@ -63,9 +65,84 @@ fn ers97_rational() {
|
||||
.defer_surpluses(true)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--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 --no-early-bulk-elect --bulk-exclude --defer-surpluses");
|
||||
|
||||
utils::read_validate_election::<Rational>("tests/data/ers97.csv", "tests/data/ers97.blt", stv_opts, None, &["nt", "vre"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ers97_fixed9() {
|
||||
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)
|
||||
.early_bulk_elect(false)
|
||||
.bulk_exclude(true)
|
||||
.defer_surpluses(true)
|
||||
.build().unwrap();
|
||||
|
||||
Fixed::set_dps(9);
|
||||
|
||||
assert_eq!(stv_opts.describe::<Fixed>(), "--numbers fixed --decimals 9 --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 --no-early-bulk-elect --bulk-exclude --defer-surpluses");
|
||||
|
||||
utils::read_validate_election::<Fixed>("tests/data/ers97.csv", "tests/data/ers97.blt", stv_opts, None, &["nt", "vre"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ers97_gfixed5() {
|
||||
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)
|
||||
.early_bulk_elect(false)
|
||||
.bulk_exclude(true)
|
||||
.defer_surpluses(true)
|
||||
.build().unwrap();
|
||||
|
||||
GuardedFixed::set_dps(5);
|
||||
|
||||
assert_eq!(stv_opts.describe::<GuardedFixed>(), "--numbers gfixed --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 --no-early-bulk-elect --bulk-exclude --defer-surpluses");
|
||||
|
||||
utils::read_validate_election::<GuardedFixed>("tests/data/ers97.csv", "tests/data/ers97.blt", stv_opts, None, &["nt", "vre"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ers97_float64() {
|
||||
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)
|
||||
.early_bulk_elect(false)
|
||||
.bulk_exclude(true)
|
||||
.defer_surpluses(true)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<NativeFloat64>(), "--numbers float64 --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 --no-early-bulk-elect --bulk-exclude --defer-surpluses");
|
||||
|
||||
utils::read_validate_election::<NativeFloat64>("tests/data/ers97.csv", "tests/data/ers97.blt", stv_opts, Some(2), &["nt", "vre"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn ers97_rational_csv() {
|
||||
let cmd = Command::cargo_bin("opentally").expect("Cargo Error")
|
||||
@ -98,5 +175,7 @@ fn ers76_rational() {
|
||||
.defer_surpluses(true)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--round-surplus-fractions 2 --round-values 2 --round-votes 2 --round-quota 0 --quota droop_exact --quota-criterion geq --quota-mode ers76 --surplus eg --transferable-only --exclusion by_value --no-early-bulk-elect --bulk-exclude --defer-surpluses");
|
||||
|
||||
utils::read_validate_election::<Rational>("tests/data/ers76.csv", "tests/data/ers76.blt", stv_opts, None, &["nt", "vre"]);
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ use opentally::stv;
|
||||
#[test]
|
||||
fn meek87_ers97old_float64() {
|
||||
let stv_opts = stv::STVOptionsBuilder::default()
|
||||
.meek_surplus_tolerance("0.001%".to_string())
|
||||
//.meek_surplus_tolerance("0.001%".to_string())
|
||||
.quota(stv::QuotaType::DroopExact)
|
||||
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||
.quota_mode(stv::QuotaMode::DynamicByTotal)
|
||||
@ -34,6 +34,8 @@ fn meek87_ers97old_float64() {
|
||||
.immediate_elect(false)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<NativeFloat64>(), "--numbers float64 --quota droop_exact --quota-criterion geq --quota-mode dynamic_by_total --surplus meek --no-immediate-elect");
|
||||
|
||||
utils::read_validate_election::<NativeFloat64>("tests/data/ers97old_meek.csv", "tests/data/ers97old.blt", stv_opts, Some(2), &["exhausted", "quota"]);
|
||||
}
|
||||
|
||||
@ -54,6 +56,8 @@ fn meek06_ers97old_fixed12() {
|
||||
|
||||
Fixed::set_dps(12);
|
||||
|
||||
assert_eq!(stv_opts.describe::<Fixed>(), "--numbers fixed --decimals 12 --round-surplus-fractions 9 --round-values 9 --round-votes 9 --round-quota 9 --meek-surplus-tolerance 0.0001 --quota-criterion geq --quota-mode dynamic_by_total --surplus meek --defer-surpluses");
|
||||
|
||||
// Read BLT
|
||||
let election: Election<Fixed> = blt::parse_path("tests/data/ers97old.blt").expect("Syntax Error");
|
||||
|
||||
@ -114,6 +118,8 @@ fn meeknz_ers97old_fixed12() {
|
||||
|
||||
Fixed::set_dps(12);
|
||||
|
||||
assert_eq!(stv_opts.describe::<Fixed>(), "--numbers fixed --decimals 12 --round-surplus-fractions 9 --round-values 9 --round-votes 9 --round-quota 9 --meek-surplus-tolerance 0.0001 --quota-criterion geq --quota-mode dynamic_by_total --surplus meek --meek-nz-exclusion --defer-surpluses");
|
||||
|
||||
// Read BLT
|
||||
let election: Election<Fixed> = blt::parse_path("tests/data/ers97old.blt").expect("Syntax Error");
|
||||
|
||||
|
@ -26,12 +26,14 @@ fn minneapolis_boe09_rational() {
|
||||
.round_surplus_fractions(Some(4))
|
||||
.round_quota(Some(0))
|
||||
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||
.early_bulk_elect(true)
|
||||
//.early_bulk_elect(true)
|
||||
.bulk_exclude(true)
|
||||
.defer_surpluses(true)
|
||||
.immediate_elect(false)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--round-surplus-fractions 4 --round-quota 0 --quota-criterion geq --bulk-exclude --defer-surpluses --no-immediate-elect");
|
||||
|
||||
utils::read_validate_election::<Rational>("tests/data/Mppls-2009-BOE-full.csv", "tests/data/Mppls-2009-BOE-full.blt", stv_opts, Some(4), &[]);
|
||||
}
|
||||
|
||||
@ -41,11 +43,13 @@ fn minneapolis_pal13_rational() {
|
||||
.round_surplus_fractions(Some(4))
|
||||
.round_quota(Some(0))
|
||||
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||
.early_bulk_elect(true)
|
||||
//.early_bulk_elect(true)
|
||||
.bulk_exclude(true)
|
||||
.defer_surpluses(true)
|
||||
.immediate_elect(false)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--round-surplus-fractions 4 --round-quota 0 --quota-criterion geq --bulk-exclude --defer-surpluses --no-immediate-elect");
|
||||
|
||||
utils::read_validate_election::<Rational>("tests/data/2013-Park-At-Large-CVR.csv", "tests/data/2013-Park-At-Large-CVR.blt", stv_opts, Some(4), &[]);
|
||||
}
|
||||
|
@ -35,5 +35,7 @@ fn prsa1_rational() {
|
||||
.early_bulk_elect(false)
|
||||
.build().unwrap();
|
||||
|
||||
assert_eq!(stv_opts.describe::<Rational>(), "--round-surplus-fractions 3 --round-values 3 --round-votes 3 --round-quota 3 --quota-criterion geq --surplus eg --surplus-order by_order --transferable-only --exclusion parcels_by_order --no-early-bulk-elect");
|
||||
|
||||
utils::read_validate_election::<Rational>("tests/data/prsa1.csv", "tests/data/prsa1.blt", stv_opts, None, &["exhausted", "lbf"]);
|
||||
}
|
||||
|
@ -33,13 +33,15 @@ fn scotland_linn07_fixed5() {
|
||||
//.round_votes(Some(5))
|
||||
.round_quota(Some(0))
|
||||
.sum_surplus_transfers(stv::SumSurplusTransfersMode::PerBallot)
|
||||
//.normalise_ballots(true)
|
||||
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||
.early_bulk_elect(false)
|
||||
.pp_decimals(5)
|
||||
.build().unwrap();
|
||||
|
||||
Fixed::set_dps(5);
|
||||
|
||||
assert_eq!(stv_opts.describe::<Fixed>(), "--numbers fixed --decimals 5 --round-surplus-fractions 5 --round-quota 0 --sum-surplus-transfers per_ballot --quota-criterion geq --no-early-bulk-elect --pp-decimals 5");
|
||||
|
||||
scotland_linn07::<Fixed>(stv_opts);
|
||||
}
|
||||
|
||||
@ -51,13 +53,15 @@ fn scotland_linn07_gfixed5() {
|
||||
.round_votes(Some(5))
|
||||
.round_quota(Some(0))
|
||||
.sum_surplus_transfers(stv::SumSurplusTransfersMode::PerBallot)
|
||||
//.normalise_ballots(true)
|
||||
.quota_criterion(stv::QuotaCriterion::GreaterOrEqual)
|
||||
.early_bulk_elect(false)
|
||||
.pp_decimals(5)
|
||||
.build().unwrap();
|
||||
|
||||
GuardedFixed::set_dps(5);
|
||||
|
||||
assert_eq!(stv_opts.describe::<GuardedFixed>(), "--numbers gfixed --decimals 5 --round-surplus-fractions 5 --round-values 5 --round-votes 5 --round-quota 0 --sum-surplus-transfers per_ballot --quota-criterion geq --no-early-bulk-elect --pp-decimals 5");
|
||||
|
||||
scotland_linn07::<GuardedFixed>(stv_opts);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user