def process_ballot(self, ballot): """Prints out each ballot item and allows user to select and verify a choice for each""" for item in ballot.items: # skip BallotItems that cannot be filled out any more if item.max_choices_selected(): continue choice_num = 1 print(item.description) for choice in item.choices: choice_str_list = [str(choice_num), ':', choice.description] if choice.chosen: choice_str_list.append('SELECTED') print(" ".join(choice_str_list)) choice_num = choice_num + 1 candidate_selection = utils.get_input_of_type( "Please enter the number of the candidate to bubble in your optical scan ballot: ", int, list(range(1, len(item.choices) + 1))) candidate_index = candidate_selection - 1 confirmed = utils.get_input_of_type( "Enter 'y' to confirm selection or 'n' to reject. " + item.choices[candidate_index].description + ": ", str, ['y', 'n']) if confirmed == 'y': item.choices[candidate_index].select() else: # prompt user to re-select # item.clear() # clear the BallotItem so it can be filled all at once (for simplicity) pass
def fill_out(self, selections=None, **kwargs): """ selections pre-determined selections (used by simulation/adversaries) ex: {'President': [0], 'Vice President': [1]} Returns whether or not ballot was filled out. This determines whether or not a transaction will be created. Future enhancement: Implement retry mechanism, allowing ballots to be invalidated. To do this, we would have to support invalidating claim tickets and allowing the voter to claim another ticket in its stead. """ if selections: for position in selections: self.select(position, selections[position]) return True print("Ballot for {}".format(self.election)) for position in self.items: metadata = self.items[position] print("{}: {}".format(position, metadata['description'])) for num, choice in enumerate(metadata['choices']): print("{}. {}".format(num + 1, choice)) max_choices = metadata['max_choices'] if max_choices > 1: msg = "Please enter your choice numbers, separated by commas (no more than {} selections): ".format( max_choices) else: msg = "Please enter your choice number: " user_input = input(msg) user_input = user_input.split( ",")[:max_choices] # cap at max_choices selection_indexes = [] for selection in user_input: try: candidate = metadata['choices'][int(selection) - 1] selection_indexes.append(int(selection) - 1) except (IndexError, ValueError): retry = True # no valid selections were made if not selection_indexes: retry = True selections = [metadata['choices'][i] for i in selection_indexes] print("Your valid selections: {}".format(selections)) confirmation = utils.get_input_of_type( "Enter 'y' to confirm choices or 'n' to invalidate ballot ", str, allowed_inputs=['y', 'n', 'Y', 'N']).lower() print() if confirmation == 'n': retry = True return False else: self.select(position, selection_indexes) return True
def lookup_voter_id(self): name = utils.get_input_of_type("Type in your full name: ", str).lower() matches = self.get_voter_by_name(name) if not matches: print("No matches found") else: print("Matching ID(s) found: {}".format( [voter.id for voter in matches]))
def begin_voting_process(self): for voter in self.voter_roll: print(voter.id, voter.name) # Allow user to self-authenticate voter_id = utils.get_input_of_type("Please enter your voter ID: ", str) voter = self.get_voter_by_id(voter_id) if not voter: print("Incorrect ID entered.") return # check that voter has not voted before voter_computer = random.choice(self.voter_computers) voted = voter_computer.has_voter_voted(voter) if voted: print('You have already voted!') return # voter has not voted; retrieve a ballot from the ballot generator ballot = self.ballot_generator.retrieve_ballot( ) # this will create a transaction for the ballot as well print('your ballot id: ' + str(ballot.id)) # create transaction on voter computer indicating that voter has retrieved ballot (we say that they voted) print('Creating transaction on voter blockchain') voter_computer.create_transaction(voter) # voter visits random voting computer voting_computer = random.choice(self.voting_computers) print('Now at voting booth') # voter fills out ballot and confirms choice self.process_ballot(ballot) ballot_filled = ballot.is_filled() # ensures that ballot is filled while not ballot_filled: self.process_ballot(ballot) ballot_filled = ballot.is_filled() input("Press enter to submit your ballot") # submit ballot to paper trail self.paper_trail.append(ballot) # simulation does not offer the chance for voter to omit ballot not change it; maybe request a new one? # TODO: handle state of select/chosen for multi-choice options # self.paper_trail.append(ballot) # create a transaction with the ballot voting_computer.create_transaction(ballot) print("Created a transaction with the ballot and the ballot state.")
def begin_election(self): """Main entry point to begin the election program""" exit = False print('Start of election!') ballots_available = True while not exit and ballots_available: self.clear_screen() self.print_menu() menu_choice = utils.get_input_of_type("Please enter choice:", int) exit = self.handle_input(menu_choice) ballots_available = False if not self.ballot_generator.are_ballots_available( ) else True print('Election Over!')
def _authenticate_voter(self, voter_auth_booth, **kwargs): """Authenticates voter and returns voter object (None if voter cannot vote).""" voter_name = utils.get_input_of_type( "Please authenticate yourself by typing in your full name.\n", str).lower() voter_id = None voter = None voters = self.get_voter_by_name(voter_name) if len(voters) > 1: voter_id = utils.get_input_of_type( "Multiple matches found for {}. Please enter in your voter id.\n" .format(voter_name), str) for v in voters: if v.id == voter_id: voter = v break if not voter: print("Please look up your ID and try again.") return None elif len(voters) == 1: voter = voters[0] voter_id = voters[0].id return voter
def get_menu_choice(self): return utils.get_input_of_type('Enter in an option: ', int)