Change tiebreaking prompt according to nature of tie
This commit is contained in:
parent
32e89312fa
commit
116ff39fa5
|
@ -98,7 +98,7 @@ where
|
|||
}
|
||||
};
|
||||
let elected_candidate = if max_cands.len() > 1 {
|
||||
super::choose_highest(state, opts, max_cands)?
|
||||
super::choose_highest(state, opts, max_cands, "Which candidate's surplus to distribute?")?
|
||||
} else {
|
||||
max_cands[0]
|
||||
};
|
||||
|
|
|
@ -835,7 +835,7 @@ fn elect_sure_winners<'a, N: Number>(state: &mut CountState<'a, N>, opts: &STVOp
|
|||
while state.num_elected < state.election.seats {
|
||||
let max_cands = ties::multiple_max_by(&hopefuls, |c| &state.candidates[c].votes);
|
||||
let candidate = if max_cands.len() > 1 {
|
||||
choose_highest(state, opts, max_cands)?
|
||||
choose_highest(state, opts, max_cands, "Which candidate to elect?")?
|
||||
} else {
|
||||
max_cands[0]
|
||||
};
|
||||
|
@ -879,7 +879,7 @@ fn elect_hopefuls<'a, N: Number>(state: &mut CountState<'a, N>, opts: &STVOption
|
|||
// Declare elected in descending order of votes
|
||||
let max_cands = ties::multiple_max_by(&cands_meeting_quota, |c| &state.candidates[c].votes);
|
||||
let candidate = if max_cands.len() > 1 {
|
||||
choose_highest(state, opts, max_cands)?
|
||||
choose_highest(state, opts, max_cands, "Which candidate to elect?")?
|
||||
} else {
|
||||
max_cands[0]
|
||||
};
|
||||
|
@ -1016,7 +1016,7 @@ fn do_bulk_elect<N: Number>(state: &mut CountState<N>, opts: &STVOptions, templa
|
|||
while !hopefuls.is_empty() {
|
||||
let max_cands = ties::multiple_max_by(&hopefuls, |c| &state.candidates[c].votes);
|
||||
let candidate = if max_cands.len() > 1 {
|
||||
choose_highest(state, opts, max_cands)?
|
||||
choose_highest(state, opts, max_cands, "Which candidate to elect?")?
|
||||
} else {
|
||||
max_cands[0]
|
||||
};
|
||||
|
@ -1077,7 +1077,7 @@ where
|
|||
// Exclude only the lowest-ranked doomed candidate
|
||||
let min_cands = ties::multiple_min_by(&doomed, |c| &state.candidates[c].votes);
|
||||
excluded_candidates = if min_cands.len() > 1 {
|
||||
vec![choose_lowest(state, opts, min_cands)?]
|
||||
vec![choose_lowest(state, opts, min_cands, "Which candidate to exclude?")?]
|
||||
} else {
|
||||
vec![min_cands[0]]
|
||||
};
|
||||
|
@ -1179,7 +1179,7 @@ where
|
|||
|
||||
let min_cands = ties::multiple_min_by(&hopefuls, |c| &state.candidates[c].votes);
|
||||
excluded_candidates = if min_cands.len() > 1 {
|
||||
vec![choose_lowest(state, opts, min_cands)?]
|
||||
vec![choose_lowest(state, opts, min_cands, "Which candidate to exclude?")?]
|
||||
} else {
|
||||
vec![min_cands[0]]
|
||||
};
|
||||
|
@ -1291,9 +1291,9 @@ fn finished_before_stage<N: Number>(state: &CountState<N>) -> bool {
|
|||
/// Break a tie between the given candidates according to [STVOptions::ties], selecting the highest candidate
|
||||
///
|
||||
/// The given candidates are assumed to be tied in this round
|
||||
fn choose_highest<'c, N: Number>(state: &mut 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>, prompt_text: &str) -> Result<&'c Candidate, STVError> {
|
||||
for strategy in opts.ties.iter() {
|
||||
match strategy.choose_highest(state, opts, &candidates) {
|
||||
match strategy.choose_highest(state, opts, &candidates, prompt_text) {
|
||||
Ok(c) => {
|
||||
return Ok(c);
|
||||
}
|
||||
|
@ -1312,9 +1312,9 @@ fn choose_highest<'c, N: Number>(state: &mut CountState<N>, opts: &STVOptions, c
|
|||
/// Break a tie between the given candidates according to [STVOptions::ties], selecting the lowest candidate
|
||||
///
|
||||
/// The given candidates are assumed to be tied in this round
|
||||
fn choose_lowest<'c, N: Number>(state: &mut 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>, prompt_text: &str) -> Result<&'c Candidate, STVError> {
|
||||
for strategy in opts.ties.iter() {
|
||||
match strategy.choose_lowest(state, opts, &candidates) {
|
||||
match strategy.choose_lowest(state, opts, &candidates, prompt_text) {
|
||||
Ok(c) => {
|
||||
return Ok(c);
|
||||
}
|
||||
|
|
18
src/ties.rs
18
src/ties.rs
|
@ -53,7 +53,7 @@ impl TieStrategy {
|
|||
/// Break a tie between the given candidates, selecting the highest candidate
|
||||
///
|
||||
/// The given candidates are assumed to be tied in this round
|
||||
pub fn choose_highest<'c, N: Number>(&self, state: &mut CountState<N>, opts: &STVOptions, candidates: &Vec<&'c Candidate>) -> Result<&'c Candidate, STVError> {
|
||||
pub fn choose_highest<'c, N: Number>(&self, state: &mut CountState<N>, opts: &STVOptions, candidates: &Vec<&'c Candidate>, prompt_text: &str) -> Result<&'c Candidate, STVError> {
|
||||
match self {
|
||||
Self::Forwards => {
|
||||
let mut candidates = candidates.clone();
|
||||
|
@ -87,7 +87,7 @@ impl TieStrategy {
|
|||
return Ok(candidates[state.random.as_mut().unwrap().next(candidates.len())]);
|
||||
}
|
||||
Self::Prompt => {
|
||||
match prompt(state, opts, candidates) {
|
||||
match prompt(state, opts, candidates, prompt_text) {
|
||||
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);
|
||||
|
@ -101,7 +101,7 @@ impl TieStrategy {
|
|||
/// Break a tie between the given candidates, selecting the lowest candidate
|
||||
///
|
||||
/// The given candidates are assumed to be tied in this round
|
||||
pub fn choose_lowest<'c, N: Number>(&self, state: &mut CountState<N>, opts: &STVOptions, candidates: &Vec<&'c Candidate>) -> Result<&'c Candidate, STVError> {
|
||||
pub fn choose_lowest<'c, N: Number>(&self, state: &mut CountState<N>, opts: &STVOptions, candidates: &Vec<&'c Candidate>, prompt_text: &str) -> Result<&'c Candidate, STVError> {
|
||||
match self {
|
||||
Self::Forwards => {
|
||||
let mut candidates = candidates.clone();
|
||||
|
@ -130,10 +130,10 @@ impl TieStrategy {
|
|||
}
|
||||
}
|
||||
Self::Random(_seed) => {
|
||||
return self.choose_highest(state, opts, candidates);
|
||||
return self.choose_highest(state, opts, candidates, prompt_text);
|
||||
}
|
||||
Self::Prompt => {
|
||||
return self.choose_highest(state, opts, candidates);
|
||||
return self.choose_highest(state, opts, candidates, prompt_text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ where
|
|||
|
||||
/// Prompt the candidate for input, depending on CLI or WebAssembly target
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
fn prompt<'c, N: Number>(state: &CountState<N>, opts: &STVOptions, candidates: &Vec<&'c Candidate>) -> Result<&'c Candidate, STVError> {
|
||||
fn prompt<'c, N: Number>(state: &CountState<N>, opts: &STVOptions, candidates: &Vec<&'c Candidate>, prompt_text: &str) -> Result<&'c Candidate, STVError> {
|
||||
// Show intrastage progress if required
|
||||
if !state.logger.entries.is_empty() {
|
||||
// Print stage details
|
||||
|
@ -224,7 +224,7 @@ fn prompt<'c, N: Number>(state: &CountState<N>, opts: &STVOptions, candidates: &
|
|||
}
|
||||
let mut buffer = String::new();
|
||||
loop {
|
||||
print!("Which candidate to select? [1-{}] ", candidates.len());
|
||||
print!("{} [1-{}] ", prompt_text, candidates.len());
|
||||
stdout().flush().expect("IO Error");
|
||||
stdin().read_line(&mut buffer).expect("IO Error");
|
||||
match buffer.trim().parse::<usize>() {
|
||||
|
@ -252,7 +252,7 @@ extern "C" {
|
|||
}
|
||||
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
fn prompt<'c, N: Number>(state: &CountState<N>, opts: &STVOptions, candidates: &Vec<&'c Candidate>) -> Result<&'c Candidate, STVError> {
|
||||
fn prompt<'c, N: Number>(state: &CountState<N>, opts: &STVOptions, candidates: &Vec<&'c Candidate>, prompt_text: &str) -> Result<&'c Candidate, STVError> {
|
||||
let mut message = String::new();
|
||||
|
||||
// Show intrastage progress if required
|
||||
|
@ -278,7 +278,7 @@ fn prompt<'c, N: Number>(state: &CountState<N>, opts: &STVOptions, candidates: &
|
|||
for (i, candidate) in candidates.iter().enumerate() {
|
||||
message.push_str(&format!("{}. {}\n", i + 1, candidate.name));
|
||||
}
|
||||
message.push_str(&format!("Which candidate to select? [1-{}] ", candidates.len()));
|
||||
message.push_str(&format!("{} [1-{}] ", prompt_text, candidates.len()));
|
||||
|
||||
loop {
|
||||
let response = get_user_input(&message);
|
||||
|
|
Loading…
Reference in New Issue