diff --git a/LDJAM_API/Voting.py b/LDJAM_API/Voting.py index 674bab6..bf536b1 100644 --- a/LDJAM_API/Voting.py +++ b/LDJAM_API/Voting.py @@ -1,6 +1,8 @@ from enum import Enum from time import sleep +from typing import Set + from LDJAM_API.LDJAM_API import vote_theme from util.ConsoleFunctions import clear_console, print_file @@ -11,6 +13,29 @@ class VotingExitReason(Enum): NO_MORE_THEMES = 2 +def get_tokens_to_process(vote_string: Set[str]) -> Set[int]: + tokens_to_process: Set[int] = set() + # Enumerate each token in the votes string + for i, token in enumerate(vote_string): + # If the token is numeric... + if token.isnumeric(): + # Convert the token to an int + token_numeric = int(token) + # Make sure the token is in range. + # If it's not then check the next token, if it is then add it to the list + if token_numeric > 10 or token_numeric < 1: + print(f"{0} is not a valid value", token_numeric) + continue + + tokens_to_process.add(token_numeric) + # If the token isn't numeric then we're done here + else: + break + + # Return the list of tokens + return tokens_to_process + + def start_general_voting(themes: dict, voted_themes: dict): # array for themes we voted on while in the function local_voted_themes = [] @@ -64,108 +89,77 @@ def start_general_voting(themes: dict, voted_themes: dict): # get user input user_input = input('What do you want to do? [Y/N/F/C] > ') + vote_string = user_input.upper().split(' ') - # make sure input is valid - if (user_input.upper().startswith('Y') or user_input.upper().startswith('N') or user_input.upper().startswith( - 'C') or user_input.upper().startswith('F')) is False: - continue - - # cancel if user typed c - if user_input.upper() == 'C': - return VotingExitReason.USER_ABORTED - - # we are voting yes - elif user_input.upper().startswith('Y'): - - input_split = user_input.upper().split(' ') - - theme_index = 0 - - for theme in display_themes: - - theme_index += 1 - - # if no numbers provided, yes vote all themes. otherwise, vote yes if index is in input list. - if (len(input_split) > 1 and str(theme_index) in input_split[1:]) or len(input_split) == 1: - print(f'Voting YES on theme "{themes.get(theme)}"') - vote_result = vote_theme(theme, 'yes') - - if vote_result != 0: - # there was an error posting vote - return VotingExitReason.GENERAL_ERROR - - # add theme to local voted array so it gets removed on successive searches - local_voted_themes.append(theme) - - # update unvoted counter - unvoted_themes -= 1 - - # sleep for 1 second to give the API some breathing room - sleep(1) - - if unvoted_themes == 0: - return VotingExitReason.NO_MORE_THEMES - - # same as yes but actually no - elif user_input.upper().startswith('N'): - input_split = user_input.upper().split(' ') - - theme_index = 0 - - for theme in display_themes: - - theme_index += 1 - - if (len(input_split) > 1 and str(theme_index) in input_split[1:]) or len(input_split) == 1: - print(f'Voting NO on theme "{themes.get(theme)}"') - vote_result = vote_theme(theme, 'no') + # Keep track of all the tokens we've processed so far + tokens_processed_so_far: Set[int] = set() - if vote_result != 0: - # there was an error posting vote - return VotingExitReason.GENERAL_ERROR + while len(vote_string) > 0: + # If the token is a Y, N or an F, get the appropriate tokens + if vote_string[0] in ['Y', 'N', 'F']: + # Set the vote action accordingly + vote_action = {'Y': 'yes', 'N': 'no', 'F': 'flag'}.get(vote_string[0]) - local_voted_themes.append(theme) + # Start a list of all the themes that we want to process + tokens_to_process: Set[int] = set() - # update unvoted counter - unvoted_themes -= 1 + # If this token is the last one in the string, vote for all of them + if len(vote_string) == 1: + tokens_to_process = [i for i in set(range(1, 11)) if i not in tokens_processed_so_far] + else: + tokens_to_process = get_tokens_to_process(vote_string[1:]) - sleep(1) + # Make sure that flagging isn't being abused + if vote_action == 'flag' and len(tokens_to_process) > 1 or len(tokens_to_process) == 0: + print("Flagging themes requires exactly one theme to be listed") + # See if the user has entered anything that's otherwise valid + vote_string = vote_string[len(tokens_to_process) + 1:] - if unvoted_themes == 0: - return VotingExitReason.NO_MORE_THEMES + else: + # Vote for each token + for token in tokens_to_process: + # Convert the token into the actual theme ID + theme_id = display_themes[token - 1] - elif user_input.upper().startswith('F'): - # flag a theme. this only works if an index was given. - input_split = user_input.upper().split(' ') + # Skip voting again if we've already voted for this item + if token in tokens_processed_so_far: + print(f"{themes.get(theme_id)} has already been voted for. Skipping") + continue - # to be precise, if EXACTLY ONE index was given. - if len(input_split) != 2: - continue + # Vote for the theme + print(f'Voting {vote_action.upper()} on theme "{themes.get(theme_id)}"') + vote_result = vote_theme(theme_id, vote_action) - theme_index = 0 + # Check that the vote was successful + if vote_result != 0: + return VotingExitReason.GENERAL_ERROR - for theme in display_themes: - # find the theme to flag - theme_index += 1 + # add theme to local voted array so it gets removed on successive searches + local_voted_themes.append(theme_id) - if str(theme_index) in input_split[1:]: + # Add the token to the list of tokens we've already processed + tokens_processed_so_far.add(token) - print(f'FLAGGING theme "{themes.get(theme)}"') - vote_result = vote_theme(theme, 'flag') + # update unvoted counter + unvoted_themes -= 1 - if vote_result != 0: - # there was an error posting vote - return VotingExitReason.GENERAL_ERROR + # sleep for 1 second to give the API some breathing room + sleep(1) - local_voted_themes.append(theme) + # Remove the tokens we've just processed from the voting string + vote_string = vote_string[len(tokens_to_process) + 1:] - # update unvoted counter - unvoted_themes -= 1 + if unvoted_themes == 0: + return VotingExitReason.NO_MORE_THEMES - sleep(1) + # The user is opting to go back to the main menu + elif vote_string[0] == 'C': + return VotingExitReason.USER_ABORTED + pass - if unvoted_themes == 0: - return VotingExitReason.NO_MORE_THEMES + # The user has entered an invalid value + else: + print(f"Action {vote_string[0].upper()} is not recognised") def start_bulk_voting(themes: dict, voted_themes: dict): diff --git a/files/bulk_voting_explanation.txt b/files/bulk_voting_explanation.txt index 21f82bf..0356b4b 100644 --- a/files/bulk_voting_explanation.txt +++ b/files/bulk_voting_explanation.txt @@ -2,5 +2,6 @@ Starting keyword theme voting. Enter a keyword. The program will then look for themes containing that keyword. You then have the ability to vote YES/NO for all of them at once. If you only want to vote for certain themes, include their index in the command. For example, 'Y 2 3 12' will vote YES for themes 2, 3 and 12. +You can also use multiple commands in one line. For example, 'N 1 2 Y' will vote NO for themes 1 and 2, but yes for the rest. To prevent abuse, you can only flag one theme at a time. Make sure to include its index. \ No newline at end of file