From f2913e2b303f3799d851cd35ecf8d701088b36a8 Mon Sep 17 00:00:00 2001 From: AlexGarrity Date: Mon, 21 Mar 2022 18:07:56 +0000 Subject: [PATCH 1/4] Updated voting so that multiple commands can be included in one string It is now possible to input the following commands: - `Y 1 2 5 N 4 8` for voting yes for 1, 2, and 5 but no to 4 and 8 - `Y 1 2 N` to vote yes for 1 and 2, but no for the rest - `Y 4 N 7 F 2 C` to vote yes for 4, no for 7, flag 2, then return to the menu --- LDJAM_API/Voting.py | 162 +++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 85 deletions(-) diff --git a/LDJAM_API/Voting.py b/LDJAM_API/Voting.py index 674bab6..930cb54 100644 --- a/LDJAM_API/Voting.py +++ b/LDJAM_API/Voting.py @@ -11,6 +11,29 @@ class VotingExitReason(Enum): NO_MORE_THEMES = 2 +def get_tokens_to_process(vote_string: set[str]): + tokens_to_process = set[int]() + # 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 +87,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'): + # Keep track of all the tokens we've processed so far + tokens_processed_so_far = set[int]() - input_split = user_input.upper().split(' ') + 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]) - theme_index = 0 + # Start a list of all the themes that we want to process + tokens_to_process = set[int]() - for theme in display_themes: - - theme_index += 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:]) - # 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') + # 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 vote_result != 0: - # there was an error posting vote - return VotingExitReason.GENERAL_ERROR + 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] - # add theme to local voted array so it gets removed on successive searches - local_voted_themes.append(theme) + # 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 - # update unvoted counter - unvoted_themes -= 1 + # Vote for the theme + print(f'Voting {vote_action.upper()} on theme "{themes.get(theme_id)}"') + vote_result = vote_theme(theme_id, vote_action) - # sleep for 1 second to give the API some breathing room - sleep(1) + # Check that the vote was successful + if vote_result != 0: + return VotingExitReason.GENERAL_ERROR - if unvoted_themes == 0: - return VotingExitReason.NO_MORE_THEMES + # add theme to local voted array so it gets removed on successive searches + local_voted_themes.append(theme_id) - # same as yes but actually no - elif user_input.upper().startswith('N'): - input_split = user_input.upper().split(' ') + # Add the token to the list of tokens we've already processed + tokens_processed_so_far.add(token) - theme_index = 0 + # update unvoted counter + unvoted_themes -= 1 - for theme in display_themes: + # sleep for 1 second to give the API some breathing room + sleep(1) - theme_index += 1 + # Remove the tokens we've just processed from the voting string + vote_string = vote_string[len(tokens_to_process) + 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') + if unvoted_themes == 0: + return VotingExitReason.NO_MORE_THEMES - if vote_result != 0: - # there was an error posting vote - return VotingExitReason.GENERAL_ERROR - - local_voted_themes.append(theme) - - # update unvoted counter - unvoted_themes -= 1 - - sleep(1) - - if unvoted_themes == 0: - return VotingExitReason.NO_MORE_THEMES - - elif user_input.upper().startswith('F'): - # flag a theme. this only works if an index was given. - input_split = user_input.upper().split(' ') - - # to be precise, if EXACTLY ONE index was given. - if len(input_split) != 2: - continue - - theme_index = 0 - - for theme in display_themes: - # find the theme to flag - theme_index += 1 - - if str(theme_index) in input_split[1:]: - - print(f'FLAGGING theme "{themes.get(theme)}"') - vote_result = vote_theme(theme, 'flag') - - if vote_result != 0: - # there was an error posting vote - return VotingExitReason.GENERAL_ERROR - - local_voted_themes.append(theme) - - # update unvoted counter - unvoted_themes -= 1 - - 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): From d94d97c3b3b359de95ecce20cd10dc2f48702220 Mon Sep 17 00:00:00 2001 From: AlexGarrity Date: Mon, 21 Mar 2022 19:03:45 +0000 Subject: [PATCH 2/4] Updated voting explanation to include section about multiple-command inputs --- files/bulk_voting_explanation.txt | 1 + 1 file changed, 1 insertion(+) 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 From 56162066ba3034cde71ca6e31b0d6299573990c7 Mon Sep 17 00:00:00 2001 From: AlexGarrity Date: Mon, 21 Mar 2022 19:58:48 +0000 Subject: [PATCH 3/4] Fixed type hints. Should work on Python 3.5+ (Apparently there's a difference between `set[int]` and `Set[int]`) --- LDJAM_API/Voting.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/LDJAM_API/Voting.py b/LDJAM_API/Voting.py index 930cb54..300e26a 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,8 +13,8 @@ class VotingExitReason(Enum): NO_MORE_THEMES = 2 -def get_tokens_to_process(vote_string: set[str]): - tokens_to_process = set[int]() +def get_tokens_to_process(vote_string: Set[str]): + tokens_to_process = Set[int]() # Enumerate each token in the votes string for i, token in enumerate(vote_string): # If the token is numeric... @@ -90,7 +92,7 @@ def start_general_voting(themes: dict, voted_themes: dict): vote_string = user_input.upper().split(' ') # Keep track of all the tokens we've processed so far - tokens_processed_so_far = set[int]() + tokens_processed_so_far = Set[int]() while len(vote_string) > 0: # If the token is a Y, N or an F, get the appropriate tokens @@ -99,7 +101,7 @@ def start_general_voting(themes: dict, voted_themes: dict): vote_action = {'Y': 'yes', 'N': 'no', 'F': 'flag'}.get(vote_string[0]) # Start a list of all the themes that we want to process - tokens_to_process = set[int]() + tokens_to_process = Set[int]() # If this token is the last one in the string, vote for all of them if len(vote_string) == 1: From e077571c81bd52430ea48bdf6bc68c425f6f61d3 Mon Sep 17 00:00:00 2001 From: AlexGarrity Date: Mon, 21 Mar 2022 20:08:42 +0000 Subject: [PATCH 4/4] Fixed type hints (again) --- LDJAM_API/Voting.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/LDJAM_API/Voting.py b/LDJAM_API/Voting.py index 300e26a..bf536b1 100644 --- a/LDJAM_API/Voting.py +++ b/LDJAM_API/Voting.py @@ -13,8 +13,8 @@ class VotingExitReason(Enum): NO_MORE_THEMES = 2 -def get_tokens_to_process(vote_string: Set[str]): - tokens_to_process = Set[int]() +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... @@ -92,7 +92,7 @@ def start_general_voting(themes: dict, voted_themes: dict): vote_string = user_input.upper().split(' ') # Keep track of all the tokens we've processed so far - tokens_processed_so_far = Set[int]() + tokens_processed_so_far: Set[int] = set() while len(vote_string) > 0: # If the token is a Y, N or an F, get the appropriate tokens @@ -101,7 +101,7 @@ def start_general_voting(themes: dict, voted_themes: dict): vote_action = {'Y': 'yes', 'N': 'no', 'F': 'flag'}.get(vote_string[0]) # Start a list of all the themes that we want to process - tokens_to_process = Set[int]() + tokens_to_process: Set[int] = set() # If this token is the last one in the string, vote for all of them if len(vote_string) == 1: