Report when and how ties are broken
This commit is contained in:
parent
daeb706b44
commit
266d8e2495
@ -81,8 +81,11 @@ impl<'a> SmartLogEntry<'a> {
|
|||||||
} else if self.data.len() == 1 {
|
} else if self.data.len() == 1 {
|
||||||
return String::from(self.template1).replace("{}", self.data.first().unwrap());
|
return String::from(self.template1).replace("{}", self.data.first().unwrap());
|
||||||
} else {
|
} else {
|
||||||
let rendered_list = format!("{} and {}", self.data[0..self.data.len()-1].join(", "), self.data.last().unwrap());
|
return String::from(self.template2).replace("{}", &smart_join(&self.data));
|
||||||
return String::from(self.template2).replace("{}", &rendered_list);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn smart_join(data: &Vec<&str>) -> String {
|
||||||
|
return format!("{} and {}", data[0..data.len()-1].join(", "), data.last().unwrap());
|
||||||
|
}
|
||||||
|
@ -1243,7 +1243,7 @@ fn finished_before_stage<N: Number>(state: &CountState<N>) -> bool {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn choose_highest<'c, N: Number>(state: &CountState<N>, opts: &STVOptions, candidates: Vec<&'c Candidate>) -> Result<&'c Candidate, STVError> {
|
fn choose_highest<'c, N: Number>(state: &mut CountState<N>, opts: &STVOptions, candidates: Vec<&'c Candidate>) -> Result<&'c Candidate, STVError> {
|
||||||
for strategy in opts.ties.iter() {
|
for strategy in opts.ties.iter() {
|
||||||
match strategy.choose_highest(state, &candidates) {
|
match strategy.choose_highest(state, &candidates) {
|
||||||
Ok(c) => {
|
Ok(c) => {
|
||||||
@ -1261,7 +1261,7 @@ fn choose_highest<'c, N: Number>(state: &CountState<N>, opts: &STVOptions, candi
|
|||||||
panic!("Unable to resolve tie");
|
panic!("Unable to resolve tie");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn choose_lowest<'c, N: Number>(state: &CountState<N>, opts: &STVOptions, candidates: Vec<&'c Candidate>) -> Result<&'c Candidate, STVError> {
|
fn choose_lowest<'c, N: Number>(state: &mut CountState<N>, opts: &STVOptions, candidates: Vec<&'c Candidate>) -> Result<&'c Candidate, STVError> {
|
||||||
for strategy in opts.ties.iter() {
|
for strategy in opts.ties.iter() {
|
||||||
match strategy.choose_lowest(state, &candidates) {
|
match strategy.choose_lowest(state, &candidates) {
|
||||||
Ok(c) => {
|
Ok(c) => {
|
||||||
|
17
src/ties.rs
17
src/ties.rs
@ -16,6 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
use crate::election::{Candidate, CountState};
|
use crate::election::{Candidate, CountState};
|
||||||
|
use crate::logger::smart_join;
|
||||||
use crate::numbers::Number;
|
use crate::numbers::Number;
|
||||||
use crate::stv::STVError;
|
use crate::stv::STVError;
|
||||||
|
|
||||||
@ -43,7 +44,7 @@ impl<'s> TieStrategy<'s> {
|
|||||||
}.to_string()
|
}.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn choose_highest<'c, N: Number>(&self, state: &CountState<N>, candidates: &Vec<&'c Candidate>) -> Result<&'c Candidate, STVError> {
|
pub fn choose_highest<'c, N: Number>(&self, state: &mut CountState<N>, candidates: &Vec<&'c Candidate>) -> Result<&'c Candidate, STVError> {
|
||||||
match self {
|
match self {
|
||||||
Self::Forwards => {
|
Self::Forwards => {
|
||||||
let mut candidates = candidates.clone();
|
let mut candidates = candidates.clone();
|
||||||
@ -55,6 +56,7 @@ impl<'s> TieStrategy<'s> {
|
|||||||
if state.forwards_tiebreak.as_ref().unwrap().get(candidates[0]).unwrap() == state.forwards_tiebreak.as_ref().unwrap().get(candidates[1]).unwrap() {
|
if state.forwards_tiebreak.as_ref().unwrap().get(candidates[0]).unwrap() == state.forwards_tiebreak.as_ref().unwrap().get(candidates[1]).unwrap() {
|
||||||
return Err(STVError::UnresolvedTie);
|
return Err(STVError::UnresolvedTie);
|
||||||
} else {
|
} else {
|
||||||
|
state.logger.log_literal(format!("Tie between {} broken forwards.", smart_join(&candidates.iter().map(|c| c.name.as_str()).collect())));
|
||||||
return Ok(candidates[0]);
|
return Ok(candidates[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -67,17 +69,24 @@ impl<'s> TieStrategy<'s> {
|
|||||||
if state.backwards_tiebreak.as_ref().unwrap().get(candidates[0]).unwrap() == state.backwards_tiebreak.as_ref().unwrap().get(candidates[1]).unwrap() {
|
if state.backwards_tiebreak.as_ref().unwrap().get(candidates[0]).unwrap() == state.backwards_tiebreak.as_ref().unwrap().get(candidates[1]).unwrap() {
|
||||||
return Err(STVError::UnresolvedTie);
|
return Err(STVError::UnresolvedTie);
|
||||||
} else {
|
} else {
|
||||||
|
state.logger.log_literal(format!("Tie between {} broken backwards.", smart_join(&candidates.iter().map(|c| c.name.as_str()).collect())));
|
||||||
return Ok(candidates[0]);
|
return Ok(candidates[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Self::Random(_seed) => { todo!() }
|
Self::Random(_seed) => { todo!() }
|
||||||
Self::Prompt => {
|
Self::Prompt => {
|
||||||
return prompt(candidates);
|
match prompt(candidates) {
|
||||||
|
Ok(c) => {
|
||||||
|
state.logger.log_literal(format!("Tie between {} broken by manual intervention.", smart_join(&candidates.iter().map(|c| c.name.as_str()).collect())));
|
||||||
|
return Ok(c);
|
||||||
|
}
|
||||||
|
Err(e) => { return Err(e); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn choose_lowest<'c, N: Number>(&self, state: &CountState<N>, candidates: &Vec<&'c Candidate>) -> Result<&'c Candidate, STVError> {
|
pub fn choose_lowest<'c, N: Number>(&self, state: &mut CountState<N>, candidates: &Vec<&'c Candidate>) -> Result<&'c Candidate, STVError> {
|
||||||
match self {
|
match self {
|
||||||
Self::Forwards => {
|
Self::Forwards => {
|
||||||
let mut candidates = candidates.clone();
|
let mut candidates = candidates.clone();
|
||||||
@ -88,6 +97,7 @@ impl<'s> TieStrategy<'s> {
|
|||||||
if state.forwards_tiebreak.as_ref().unwrap().get(candidates[0]).unwrap() == state.forwards_tiebreak.as_ref().unwrap().get(candidates[1]).unwrap() {
|
if state.forwards_tiebreak.as_ref().unwrap().get(candidates[0]).unwrap() == state.forwards_tiebreak.as_ref().unwrap().get(candidates[1]).unwrap() {
|
||||||
return Err(STVError::UnresolvedTie);
|
return Err(STVError::UnresolvedTie);
|
||||||
} else {
|
} else {
|
||||||
|
state.logger.log_literal(format!("Tie between {} broken forwards.", smart_join(&candidates.iter().map(|c| c.name.as_str()).collect())));
|
||||||
return Ok(candidates[0]);
|
return Ok(candidates[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -100,6 +110,7 @@ impl<'s> TieStrategy<'s> {
|
|||||||
if state.backwards_tiebreak.as_ref().unwrap().get(candidates[0]).unwrap() == state.backwards_tiebreak.as_ref().unwrap().get(candidates[1]).unwrap() {
|
if state.backwards_tiebreak.as_ref().unwrap().get(candidates[0]).unwrap() == state.backwards_tiebreak.as_ref().unwrap().get(candidates[1]).unwrap() {
|
||||||
return Err(STVError::UnresolvedTie);
|
return Err(STVError::UnresolvedTie);
|
||||||
} else {
|
} else {
|
||||||
|
state.logger.log_literal(format!("Tie between {} broken backwards.", smart_join(&candidates.iter().map(|c| c.name.as_str()).collect())));
|
||||||
return Ok(candidates[0]);
|
return Ok(candidates[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user