Skip to content

Commit

Permalink
don't go to final-round with 1 candidate
Browse files Browse the repository at this point in the history
  • Loading branch information
artoonie committed Jun 5, 2023
1 parent eb5a352 commit 6c41305
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 27 deletions.
19 changes: 15 additions & 4 deletions src/main/java/network/brightspots/rcv/Tabulator.java
Original file line number Diff line number Diff line change
Expand Up @@ -493,19 +493,30 @@ private List<String> identifyWinners(
} else {
// We should only look for more winners if we haven't already filled all the seats.
if (winnerToRound.size() < config.getNumberOfWinners()) {
// If the number of continuing candidates equals the number of seats to fill, everyone wins.
if (currentRoundCandidateToTally.size()
== config.getNumberOfWinners() - winnerToRound.size()) {
// If the number of continuing candidates equals the number of seats to fill, everyone wins.
selectedWinners.addAll(currentRoundCandidateToTally.keySet());
} else if (config.isFirstRoundDeterminesThresholdEnabled() &&
currentRoundCandidateToTally.size() - 1 == config.getNumberOfWinners()) {
// Edge case: if nobody meets the threshold, but we're on the penultimate round when
// isFirstRoundDeterminesThresholdEnabled is true, select the max vote getters as the winners.
BigDecimal maxVotes = currentRoundTallyToCandidates.lastKey();
selectedWinners = currentRoundTallyToCandidates.get(maxVotes);
} else if (!config.isMultiSeatBottomsUpUntilNWinnersEnabled()) {
// Otherwise, select all winners above the threshold
selectWinners(currentRoundTallyToCandidates, selectedWinners);
}
}

// Edge case: if we've identified multiple winners in this round, but we're only supposed to
// elect one winner per round, pick the top vote-getter and defer the others to subsequent
// rounds.
if (config.isMultiSeatAllowOnlyOneWinnerPerRoundEnabled() && selectedWinners.size() > 1) {
// elect one winner per round, pick the top vote-getter. If this is a multi-winner election,
// defer the others to subsequent rounds. If this is a single-winner election where its possible
// for no candidate to reach the threshold (isFirstRoundDeterminesThresholdEnabled=true), the tiebreaker
// will choose the only winner.
boolean useTiebreakerIfNeeded = config.isMultiSeatAllowOnlyOneWinnerPerRoundEnabled()
|| config.isFirstRoundDeterminesThresholdEnabled();
if (useTiebreakerIfNeeded && selectedWinners.size() > 1) {
// currentRoundTallyToCandidates is sorted from low to high, so just look at the last key
BigDecimal maxVotes = currentRoundTallyToCandidates.lastKey();
selectedWinners = currentRoundTallyToCandidates.get(maxVotes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,17 +25,6 @@
"Carmona, Ralph C." : "5",
"Vail, Christopher L." : "6"
},
"tallyResults" : [ {
"eliminated" : "Carmona, Ralph C.",
"transfers" : {
"exhausted" : "5"
}
} ]
}, {
"round" : 3,
"tally" : {
"Vail, Christopher L." : "6"
},
"tallyResults" : [ {
"elected" : "Vail, Christopher L.",
"transfers" : { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,7 @@
"Vail, Christopher L." : "6"
},
"tallyResults" : [ {
"eliminated" : "Vail, Christopher L.",
"transfers" : {
"exhausted" : "6"
}
} ]
}, {
"round" : 3,
"tally" : {
"Carmona, Ralph C." : "6"
},
"tallyResults" : [ {
"elected" : "Carmona, Ralph C.",
"elected" : "Vail, Christopher L.",
"transfers" : { }
} ]
} ]
Expand Down

0 comments on commit 6c41305

Please sign in to comment.