def validate(ranks, vote): errors = [] # Only one rank per choice for i, rank_list in enumerate(ranks): if len(rank_list) > 1: errors.append(f'Choice {i+1} has multiple ranks assigned.') actual_ranks = [rank_list[0] for rank_list in ranks if rank_list] counter = collections.Counter(actual_ranks) # Can't skip ranks for i in range(max(actual_ranks)): if counter[i + 1] == 0: errors.append(f'Rank {i+1} has been skipped.') break # Can't assign same rank to two choices for i in range(len(ranks)): if counter[i + 1] > 1: errors.append(f'Rank {i+1} has been assigned more than once.') choices = [None] * max(actual_ranks) for i, rank in enumerate(ranks): if rank: choices[rank[0] - 1] = vote.choices[i] ballot = pyrankvote.Ballot(ranked_candidates=choices) return ballot, errors
def test_create_object(self): """Test that voting with two equal candidates raises DuplicateCandidateError""" candidate1 = pyrankvote.Candidate("Per") candidate2 = pyrankvote.Candidate("Maria") candidate3 = pyrankvote.Candidate("Aase") ranked_candidates = (candidate1, candidate2, candidate3) ballot = pyrankvote.Ballot(ranked_candidates) self.assertTupleEqual(ranked_candidates, ballot.ranked_candidates)
def test_new_candidate_objects(self): """Test that if one of the candidate that are voted for are not a cadidate, that a TypeError is raised""" class NewCandidate: def __init__(self, name): self.name = "New " + name def __hash__(self): return hash(self.name) candidate1 = NewCandidate("Per") candidate2 = NewCandidate("Aase") # This should NOT raise an error pyrankvote.Ballot(ranked_candidates=[candidate1, candidate2])
def test_raise_error_if_not_all_obj_are_candidate_objects(self): """Test that if one of the candidate that are voted for are not a cadidate, that a TypeError is raised""" candidate1 = pyrankvote.Candidate("Per") candidate2 = "Aase" def tester(_): pyrankvote.Ballot(ranked_candidates=[candidate1, candidate2]) msg = "Candidate 2 is a string, not a Candidate, and should raise a TypeError" self.assertRaises(TypeError, tester, msg) # TEST THE OPPOSITE candidate1 = pyrankvote.Candidate("Per") candidate2 = pyrankvote.Candidate("Aase") # This should NOT raise an error pyrankvote.Ballot(ranked_candidates=[candidate1, candidate2])
def test_raise_duplicate_candidate_error(self): """Test that voting with two equal candidates raises DuplicateCandidateError""" candidate1 = pyrankvote.Candidate("Per") candidate2 = pyrankvote.Candidate("Per") candidate3 = pyrankvote.Candidate("Aase") def tester(_): pyrankvote.Ballot( ranked_candidates=[candidate1, candidate2, candidate3]) msg = "Candidate 1 and 2 is equal and should raise duplicate candidate error" self.assertRaises(pyrankvote.models.DuplicateCandidatesError, tester, msg) # TEST THE OPPOSITE candidate1 = pyrankvote.Candidate("Per") candidate2 = pyrankvote.Candidate("Maria") candidate3 = pyrankvote.Candidate("Aase") # This should NOT raise an error pyrankvote.Ballot( ranked_candidates=[candidate1, candidate2, candidate3])
def main(): gc = gspread.authorize(get_creds()) wb = gc.open_by_key(os.environ['gsheet_id']) worksheet = wb.get_worksheet(0) candidates = {} for candidate in [CANDIDATE_REGEX.search(c).group(1) for c in worksheet.row_values(1) if CANDIDATE_REGEX.search(c)]: candidates[candidate] = pyrankvote.Candidate(candidate) raw_ballots = worksheet.get_all_records() ballots = [] for raw_ballot in raw_ballots: ballot = sorted({candidates[CANDIDATE_REGEX.search(c).group(1)]: r for (c, r) in raw_ballot.items() if CANDIDATE_REGEX.search(c)}.items(), key=lambda x: x[1]) ballots.append(pyrankvote.Ballot(ranked_candidates=[c for c, r in ballot])) # print(ballot) election_result = pyrankvote.single_transferable_vote(candidates=candidates.values(), ballots=ballots, number_of_seats=SEATS) winners = election_result.get_winners() with open('output/results.txt', 'w+') as f: f.write(str(election_result)) print(election_result)
def tester(_): pyrankvote.Ballot(ranked_candidates=[candidate1, candidate2])
names.append(word) else: continue return names votes = get_votes(path) for vote in votes: names = get_names(vote) ballot = [] for name in names: name = name[0].upper() + name[1:] if name not in candidates: candidates[name] = prv.Candidate(name) ballot.append(candidates[name]) ballots.append(prv.Ballot(ranked_candidates=ballot)) Candidates = [candidates[i] for i in candidates] election = prv.single_transferable_vote(Candidates, ballots, spots) if "show_all" in sys.argv: print(election) elif "show_last" in sys.argv: print(f"Final result, last of {len(election.rounds) + 1} rounds") print(election.rounds[-1]) else: winners = election.get_winners() for winner in winners: print(winner)