FIX: poll ranked choice result algo majority check (#28191)

This commit is contained in:
Robert 2024-08-02 07:51:26 +01:00 committed by GitHub
parent 26c4d1398a
commit 183ef2024c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 45 additions and 4 deletions

View File

@ -44,7 +44,7 @@ class DiscoursePoll::RankedChoice
potential_winners = find_potential_winners(tally, max_votes)
# Check for a majority and return if found
if majority_check(tally, potential_winners, max_votes)
if majority_check(tally, max_votes)
majority_candidate = enrich(potential_winners.keys.first, options)
round_activity << { round: round, majority: majority_candidate, eliminated: nil }
@ -112,10 +112,10 @@ class DiscoursePoll::RankedChoice
tally.select { |k, v| v == max_votes }
end
def self.majority_check(tally, potential_winners, max_votes)
def self.majority_check(tally, max_votes)
total_votes = tally.values.sum
max_votes > total_votes / 2 || potential_winners.count == 1
max_votes && max_votes > total_votes / 2
end
def self.identify_losers(tally)

View File

@ -14,6 +14,19 @@ RSpec.describe DiscoursePoll::RankedChoice do
]
end
let(:options_4) do
[
{ id: "Belle-lettres", html: "Belle-lettres" },
{ id: "Comedy", html: "Comedy" },
{ id: "Fantasy", html: "Fantasy" },
{ id: "Historical", html: "Historical" },
{ id: "Mystery", html: "Mystery" },
{ id: "Non-fiction", html: "Non-fiction" },
{ id: "Sci-fi", html: "Sci-fi" },
{ id: "Thriller", html: "Thriller" },
]
end
it "correctly finds the winner with a simple majority" do
votes = [%w[Alice Bob], %w[Bob Alice], %w[Alice Bob], %w[Bob Alice], %w[Alice Bob]]
expect(described_class.run(votes, options_1)[:winning_candidate]).to eq(
@ -60,10 +73,38 @@ RSpec.describe DiscoursePoll::RankedChoice do
expect(described_class.run(votes, options_3)[:round_activity].length).to eq(2)
end
it "handles the winner with a simple majority" do
it "handles a tie after an elimination" do
votes = [%w[Dave Alice], %w[Bob Dave]]
expect(described_class.run(votes, options_3)[:tied_candidates]).to eq(
[{ digest: "Dave", html: "Dave" }, { digest: "Bob", html: "Bob" }],
)
end
it "handles a complex multi-round tie" do
votes = [
%w[Belle-lettres Thriller Non-fiction Sci-fi Mystery Comedy Historical Fantasy],
%w[Mystery Fantasy Belle-lettres Sci-fi Non-fiction Historical Thriller Comedy],
%w[Mystery Thriller Belle-lettres Sci-fi Comedy Non-fiction Fantasy Historical],
%w[Mystery Sci-fi Fantasy Thriller Non-fiction Belle-lettres Historical Comedy],
%w[Mystery Thriller Non-fiction Sci-fi Comedy Historical Belle-lettres Fantasy],
%w[Fantasy Non-fiction Mystery Sci-fi Thriller Historical Belle-lettres Comedy],
%w[Fantasy Mystery Historical Thriller Sci-fi Non-fiction Comedy Belle-lettres],
%w[Thriller Mystery Fantasy Non-fiction Sci-fi Historical Comedy Belle-lettres],
%w[Mystery Fantasy Historical Thriller Non-fiction Comedy Sci-fi Belle-lettres],
%w[Fantasy Sci-fi Thriller Mystery Non-fiction Comedy Historical Belle-lettres],
%w[Fantasy Sci-fi Historical Non-fiction Comedy],
%w[Fantasy Sci-fi Mystery Comedy Thriller Non-fiction Historical],
%w[Fantasy Mystery Historical Non-fiction Sci-fi Comedy],
%w[Fantasy Sci-fi Mystery Comedy Thriller Historical Non-fiction],
%w[Comedy Historical Fantasy Sci-fi Mystery],
%w[Sci-fi Thriller Mystery Non-fiction Comedy Fantasy],
]
outcome = described_class.run(votes, options_4)
expect(outcome[:tied_candidates]).to eq(
[{ digest: "Mystery", html: "Mystery" }, { digest: "Fantasy", html: "Fantasy" }],
)
expect(outcome[:round_activity].length).to eq(3)
end
end