Skip to content

Instantly share code, notes, and snippets.

@jallspaw
Created November 22, 2021 17:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jallspaw/4728dcc8c89b89d262cbb9828e343636 to your computer and use it in GitHub Desktop.
Save jallspaw/4728dcc8c89b89d262cbb9828e343636 to your computer and use it in GitHub Desktop.
# Project 1b - Voting Booth
# Sadie Allspaw -- period 10
#### PEER FEEDBACK
# No major bugs, but it didn’t specify how it counted votes entered that weren’t the candidate
# There are no bugs that I ran into
# I didn’t notice any.
ballot = [] # start the list off as empty
#### making the ballot #######
# display candidaties
def display_candidates():
option_number = 0
for name in ballot:
# linebreaks used to make it look nicer
print("\noption", str(option_number + 1) + ":", ballot[option_number], "\n")
option_number += 1
# add a candidate
def add_candidate(candidate):
ballot.append(candidate)
# ask the user if they want to display the current list of candidates
def ask_to_display():
want_to_display = input("Do you want to see your current candidate list?\ny = yes, n = no\n>")
if ballot == []: # this is the option I would put if they didn't submit a candidate yet
print("Please add a candidate first")
elif want_to_display == "y":
display_candidates() # notice I don't have an 'else' because if they don't want to view the list, I'll just move onto the next thing
# form candidate list
def form_ballot():
not_done = True # keep going until user says they are done
while not_done == True:
if len(ballot) >= 2 and len(ballot) < 10:
print("""
enter 1 to add a candidate
enter 2 to view candidate list
enter 3 to move onto voting
""")
option_chosen = input("> ")
if len(ballot) < 10:
if option_chosen == "1":
# this distinction is only so the wording is more elegant
new_candidate = input("What new candidate would you like to add?\n> ")
ballot.append(new_candidate)
# if len(ballot) == 0:
# new_candidate = input("What do you want your first candidate to be?\n> ")
# else:
# new_candidate = input("What do you want your next candidate to be? \n> ")
elif option_chosen == "2":
display_candidates()
elif option_chosen == "3":
if len(ballot) < 2:
print("You must have at least 2 candidates")
else:
not_done = False
else:
print("please enter 1, 2, or 3")
else:
print("You have exceeded the limit of 10 candidates, sorry :(")
not_done == False
elif len(ballot) < 2:
while len(ballot) < 2:
print("""
enter 1 to add a candidate
enter 2 to view candidate list
""")
option_chosen = input("> ")
if option_chosen == "1":
new_candidate = input("What new candidate would you like to add?\n> ")
ballot.append(new_candidate)
if option_chosen == "2":
display_candidates()
##### lists of votes #######
# get current totals
# current totals -- starts off as amount of people that voted for 1st place, then adding the votes of those whose higher choice candidates were eliminated
def get_ini_current_total(candidate):
current_total = tally[ballot.index(candidate)][1]
return current_total
# these are where the votes will be stored -- this is why there is a limit of 10 candidates
votes_c1 = []
votes_c2 = []
votes_c3 = []
votes_c4 = []
votes_c5 = []
votes_c6 = []
votes_c7 = []
votes_c8 = []
votes_c9 = []
votes_c10 = []
list_of_vote_collections = [votes_c1, votes_c2, votes_c3, votes_c4, votes_c5, votes_c6, votes_c7, votes_c8, votes_c9, votes_c10]
# tally means that if a candidate was ranked first 3 times and 2nd 6 times then their list would look like [3, 6]
tally_c1 = [0, 0]
tally_c2 = [0, 0]
tally_c3 = [0, 0]
tally_c4 = [0, 0]
tally_c5 = [0, 0]
tally_c6 = [0, 0]
tally_c7 = [0, 0]
tally_c8 = [0, 0]
tally_c9 = [0, 0]
tally_c10 = [0, 0]
tally = [tally_c1, tally_c2, tally_c3, tally_c4, tally_c5, tally_c6, tally_c7, tally_c8, tally_c9, tally_c10]
###### voting ######
# this gets the user's ranking for the candidates
def get_rank(rank_number):
for person in ballot:
print("What is your #" + str(rank_number), "choice?")
candidate_voted = input("> ") # "which candidate is your #1 choice?"
return candidate_voted
# this takes the user's rank and puts it into the dictionary for that candidate
def add_vote(candidate, rank):
if candidate in ballot:
list_pos = 0
for person in ballot: # for each candidate in the ballot, by list position (iterate thru)
if candidate == ballot[list_pos]:
candidate_list = list_of_vote_collections[list_pos]
candidate_list.append(rank)
list_pos += 1
else:
list_pos += 1
else:
print("That candidate isn't in your ballot.")
return
# keep track of amount of ballots bc not every ballot needs every candidate
# this puts "get rank" and "add vote" together to fill out the ballot
def fillout_ballot():
current_rank = 1
still_ranking = True # equals false when they want to stop filling it out
while still_ranking == True:
for person in ballot:
candidate = get_rank(current_rank)
add_vote(candidate, current_rank) # this adds the vote to the list fot the candidate
current_rank += 1
# this makes sure you only vote for however many candidates you have
if current_rank > len(ballot):
still_ranking = False
return
def vote():
still_voting = True
num_of_ballots = 0
while still_voting == True:
display_candidates()
fillout_ballot()
num_of_ballots += 1
want_to_keep_voting = input("Would you like to submit another ballot?\n y = yes n = no\n> ")
# this makes it so that the user can submit as many ballots as they want
if want_to_keep_voting == "n" or want_to_keep_voting == "N":
still_voting = False
##### results ####### (smaller functions)
# this tallies up amount of times ranked 1st, then 2nd, and so on by using a list of lists
# the round tells us whether we are counting how many times they were voted first, second, third, or any other place
# remember : the round is the place in the list + 1, index 0 in the list corresponds to ranked first
c_total_c1 = 0
c_total_c2 = 0
c_total_c3 = 0
c_total_c4 = 0
c_total_c5 = 0
c_total_c6 = 0
c_total_c7 = 0
c_total_c8 = 0
c_total_c9 = 0
c_total_c10 = 0
current_totals = [c_total_c1, c_total_c2, c_total_c3, c_total_c4, c_total_c5, c_total_c6, c_total_c7, c_total_c8, c_total_c9, c_total_c10]
eliminated_candidates = []
def tally_up(round_num):
count = 0 # keep track of which candidate we are on
for person in ballot: # iterate thru candidates
# a candidate list includes all the rankes they recieved, while the candidate tally includes all the ranks of what type they recieved
person_index = ballot.index(person)
candidate_list = list_of_vote_collections[person_index]
candidate_tally = tally[person_index]
tally[person_index][0] = person
# if it doesnt have for this round yet add an item thats value is 0
if len(candidate_tally) < round_num + 2:
# add a new slot
candidate_tally.append(0)
for number in candidate_list:
# check if it's equal to the current round #
if number == round_num:
candidate_tally[round_num] += 1
# add 1
count += 1
# this is to see the maximum amount of people someone voted for
def get_longest_ballot():
list_of_ballot_lengths = []
for ballot in list_of_vote_collections:
ballot_len = len(ballot)
list_of_ballot_lengths += ballot_len
return max(list_of_ballot_lengths)
# this gets the total amount of votes for one rank e.g: how many times anyone was ranked 1st, or 2nd, or 3rd, and so on...
def get_all_votes():
all_votes = 0
for total in current_totals:
if total != -1:
all_votes += total
return all_votes
# does anyone have 50% of the vote or more?
def have_majority():
# if false: no majority
is_there_majority = 0
all_votes = get_all_votes()
# does any candidate have the majority?
for total in current_totals:
if total > all_votes / 2:
person_with_majority = total
is_there_majority = 1
if is_there_majority == False:
person_with_majority = 0
return person_with_majority, is_there_majority
# find the candidate w the least current total
def find_loser():
# this gets all of the current totals together in a list
comparing_list = []
for candidate in ballot:
candidate_num = ballot.index(candidate)
current_total = current_totals[candidate_num]
# only add to candidates being considered if they are still in the running
if candidate not in eliminated_candidates and current_total >= 0:
candidate_num = ballot.index(candidate)
can_current_total = current_totals[candidate_num]
comparing_list.append(can_current_total)
if have_majority()[0] != 0:
# this finds the smallest of all the current totals
votes_loser_got = min(comparing_list)
candidate_num = current_totals.index(votes_loser_got)
loser = ballot[candidate_num]
else:
loser = 0
return loser
# find the winner
def find_winner():
# this gets all of the current totals together in a list
comparing_list = []
for candidate in ballot:
can_current_total = current_totals[ballot.index(candidate)]
comparing_list.append(can_current_total)
# this finds the biggest of all the current totals
votes_winner_got = max(comparing_list)
candidate_num = comparing_list.index(votes_winner_got)
winner = ballot[candidate_num]
return winner
# take the person who was eliminated and redistribute their vote
def redistribute(round_num):
# round 1 = we are redistributing the votes from 1st place, round 2 is 2nd place, and so on...
eliminated = find_loser()
# candidate being eliminated
loser_num = ballot.index(eliminated)
list_of_votes = list_of_vote_collections[loser_num]
ballots_to_distribute = []
# add eliminated candidate to list
# ballot.remove(eliminated)
eliminated_candidates.append(eliminated)
current_totals[loser_num] = -1
for vote in list_of_votes:
if vote == round_num:
to_save = list_of_votes.index(vote)
ballots_to_distribute.append(to_save)
for index in ballots_to_distribute:
for vote_list in list_of_vote_collections:
current_candidate_num = list_of_vote_collections.index(vote_list)
if vote == round_num + 1:
current_totals[current_candidate_num] += 1
# checking every vote in the list of votes for that candidate to see where exactly they were voted for that specific round
ballot_num = list_of_votes[round_num] # EX: if we are in round 1, the computer is looking through the list of rankings for that candidate and seeing where they were ranked first
####### vote calculation ####### (bigger functions)
def final_results():
# keep track of rounds and whether we're still going
still_counting = True
rounds_completed = 0
round_num = 0
# tally up each candidate
for person in ballot:
person_num = ballot.index(person) + 1
tally_up(person_num)
# add tally for 1st place to current total
place = 0
for person in ballot:
person_num = ballot.index(person) + 1
current_totals[place] += tally[place][1]
place += 1
winner = ""
loser = find_loser()
while still_counting == True:
round_num += 1
if rounds_completed == len(ballot) or loser == 0:
print("Oh no!! A winner couldn't be determined!")
still_counting = False
# if someone has the majority
else:
if have_majority()[1] != 0:
votes_winner_got = have_majority()[0]
winner = find_winner()
still_counting = False
print("round", round_num -1, "didn't yield a majority\nmoving onto round #", round_num)
else:
print("no one has the majority")
redistribute(round_num)
print(have_majority()[0])
rounds_completed += 1
return winner
# winner = final_results()
# if winner != "":
# print("and the winner is...", winner + "!!!")
######### putting it all together -- the main code ##########
print("""-- MARIO KART CHARACTER VOTING BOOTH --
* with ranked choice voting *
By: Sadie Allspaw
This is a voting booth simulator. You will have the chance to create a candidate list and submit multiple ballots ranking these candidates. At the end, you will get a result of who wins.
NOTE: I named this Mario Kart Character Voting Booth because it was created to find the best Mario Kart character. However, it can be used to vote on any list of candidates.
STEP 1: CREATE YOUR LIST OF CANDIDATES
""")
form_ballot()
print("""
STEP 2: VOTE ON YOUR CANDIDATES""")
vote()
print("""
STEP 3: CALCULATE RESULTS
""")
winner = final_results()
if winner != "":
print("and the winner is...", winner + "!!!")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment