def choose_auto_vis(): """Presents a menu for the user to select if they wish to automatically visualize their automata upon import/creation. Returns ------- bool Whether the setting was turned on, off, or neither (None) """ display_menu(menu_msg) while True: inpt = input() # Check if the user wishes to quit inpt = inpt.lower() if inpt in ["y", "yes"]: global_settings.update(menu_option, True) show_notification("Auto-visualization turned on") return True elif inpt in ["n", "no"]: global_settings.update(menu_option, False) show_notification("Auto-visualization turned off") return False elif inpt in ["e", "exit"]: return None else: show_error("Command not recognized")
def choose_gv_file_type(): """Presents a menu for the user to select their desired graphviz file output type (pdf, png, jpeg...) Returns ------- int The selected index, or None if quit """ display_menu(menu_msg + get_file_type_options() + menu_msg_2) while True: inpt = input() try: # If we get a good number, select it! if int(inpt) in range(len(file_types)): selected = file_types[int(inpt)] show_notification("Selected:\n" + selected) global_settings.update(menu_option, selected) return int(inpt) else: show_error("Not a valid observer index") except ValueError: # Check if the user wishes to quit inpt = inpt.lower() if inpt in ["e", "exit"]: return None else: show_error("Command not recognized")
def select_heuristic(): """Opens a menu to select a heuristic for composing systems in a modular architecture to speed up operations. Parameters ---------- None Returns ------- None """ display_menu(menu_msg) inpt = input() while (True): if inpt in ["0"]: show_notification("Selected no heuristic") return no_heuristic elif inpt in ["1"]: show_notification("Selected most shared events") return most_shared_heuristic elif inpt in ["2"]: show_notification("Selected least new events") return least_new_heuristic else: show_error("Command not recognized") inpt = input()
def initialize(): """Initializes the program's settings Returns ------- None """ global settings settings = defaults try: try: with open(settings_file, 'r') as f: # Load in the settings settings = json.load(f) except FileNotFoundError: with open(settings_file, 'w') as f: # Write new settings settings = defaults json.dump(settings, f) except Exception: show_error("Error reading/writing settings file.\n" + "Reverting to defaults...") for k, v in defaults.items(): if k not in settings: settings[k] = v
def name_automaton_menu(automata, automaton): """Gives the user the opportunity to name an automaton, if the automaton is currently unnamed (or has a name that conflicts with another automaton already loaded). Parameters ---------- automata : list The automata that are currently open (excluding the current automaton) automaton : dict The automaton to name (not in the list parameter) Returns ------- None """ bad_names = set([a["name"] for a in automata]) bad_names.add("") # Checks if automaton already has a valid name; if so, done if "name" in automaton: if automaton["name"] not in bad_names: show_notification("Imported automaton " + automaton["name"]) return # Otherwise, shows a menu to request a name display_menu(menu_msg) name = input() while name in bad_names: show_error("Name already taken! Try again") name = input() # Name the automaton and notify the user automaton["name"] = name show_notification("Imported automaton " + automaton["name"])
def save(automaton): """Saves an automaton to a user-defined location in JSON form, dot form, and the GraphViz PDF form. Parameters ---------- automaton : dict The automaton to save Returns ------- None """ show_notification("Select a location to save " + automaton["name"]) location = filedialog.asksaveasfilename(title="Automaton Export Filename", defaultextension="json") # If selected a location, save it if len(location) == 0: show_error("No location given") return False else: with open(location, 'w') as f: # writing JSON object dump(automaton, f, sort_keys=True, indent=4) # Remove the .json extension location = location[:-5] visualize(automaton, location, view=False) show_notification("Saved to " + location) return True
def select_automata_menu(automata, min_selection=1, menu_name=None): """Menu for selecting multiple automata. Parameters ---------- automata : list All automata that are available for selection min_selection : int The minimum number of automata needed menu_name : str The name for the menu Returns ------- lst The automata that have been selected (or None if none selected) """ if menu_name is None: menu_name = "Select Multiple Automata Menu" else: menu_name = "Select Automata for " + menu_name # Show the menu display_menu(menu_name + multiple_menu_msg) num_options = len(automata) selected = [False] * num_options # Keep selecting until type "e" or "exit" while True: print_selected(automata, selected) inpt = input() try: # Get the integer input from the user and select it if int(inpt) in range(num_options): inpt = int(inpt) selected[inpt] = not selected[inpt] except ValueError: # Check if we are done inpt = inpt.lower() if inpt in ["e", "exit"]: return None elif inpt in ["s", "save"]: result = [ automata[i] for i in range(num_options) if selected[i] ] if len(result) >= min_selection: sel = [item["name"] for item in result] show_notification("Selected:\n" + str(sel)) return result else: # Prevent exit because selection was inadequate show_error("At least " + str(min_selection) + " automata must be selected") else: show_error("Command not recognized")
def select_automaton_menu(automata, menu_name=None): """Menu for selecting a single automaton. Parameters ---------- automata : list All automata that are available for selection menu_name : str The name for the menu Returns ------- dict The automaton selected (or None if none selected) """ if menu_name is None: menu_name = "Select Single Automaton Menu" else: menu_name = "Select Automaton for " + menu_name # Display the menu display_menu(menu_name + single_menu_msg) num_options = len(automata) selected = [False] * num_options # Keep selecting until type "e" or "exit" while True: print_selected(automata, selected) inpt = input() try: # If successfully selected, return the selection if int(inpt) in range(num_options): show_notification("Selected:\n" + str(automata[int(inpt)]["name"])) return automata[int(inpt)] else: show_error("Index not valid, max index is " + str(num_options - 1)) except ValueError: # See if the user wanted to exit inpt = inpt.lower() if inpt in ["e", "exit"]: return None else: show_error("Command not recognized")
def main_menu(next_screens, automata, temp_dir): """Main menu for the application with all of the actions that are possible in the application at a high level. Parameters ---------- next_screens : list The next screens that will be shown (a stack). This is not used much with the current version of the application, but it might be used in the future automata : list List of all automata loaded into the program temp_dir : str The string representing the temporary directory for files Returns ------- None """ display_menu(menu_msg) # Based on input, choose which type of operation to perform inpt = input().lower() if inpt in ["o", "open"]: open_file_menu(automata, temp_dir) elif inpt in ["l", "list"]: print_selected(automata) sleep(0.2) elif inpt in ["b", "begin"]: ops_menu(automata, temp_dir) elif inpt in ["s", "save"]: select_and_save(automata) elif inpt in ["c", "close"]: close_automata_menu(automata) elif inpt in ["v", "visualize"]: select_and_save_temp(automata, temp_dir) elif inpt in ["d", "settings"]: settings_menu() elif inpt in ["e", "exit"]: print("Exiting...") next_screens.pop() # Remove main menu from the stack else: show_error("Command not recognized")
def select_observer_menu(automaton): """Allows the user to select which observer to use for an operation (each observer has an observable alphabet, a controllable alphabet, and a set of secret states). Parameters ---------- automaton : dict Returns ------- int The index of the observer which has been selected """ num_obs = len(automaton["events"]["observable"]) max_input = str(num_obs - 1) # Create the menu message msg = menu_msg + max_input + menu_msg_2 if num_obs > 1: msg += "1 through " + max_input + " are agents" msg += menu_msg_3 # Display the message display_menu(msg) while True: inpt = input() try: # If we get a good number, select it! if int(inpt) in range(num_obs): show_notification("Selected:\n" + inpt) return int(inpt) else: show_error("Not a valid observer index") except ValueError: # Check if the user wishes to quit inpt = inpt.lower() if inpt in ["e", "exit"]: return None else: show_error("Command not recognized")
def settings_menu(): """Opens a menu with options for different settings which can be edited. It changes the default for all future sessions as well. Returns ------- None """ display_menu(menu_msg) inpt = input().lower() # Choose which operation to perform if inpt in ["f", "file"]: choose_gv_file_type() elif inpt in ["a"]: choose_auto_vis() elif inpt in ["e", "exit"]: pass else: show_error("Command not recognized")
def update(setting, value): """Updates the setting with a new value Parameters ---------- setting : str The setting to change value : any The new value for the setting Returns ------- None """ settings[setting] = value try: with open(settings_file, 'w') as f: # Write new settings json.dump(settings, f) except FileNotFoundError: show_error("Error writing settings file.\n" + "Changes are only saved for this session.")
def close_automata_menu(automata): """Menu for closing automaton. It has three major tasks: 1) selecting the automata, then 2) closing without saving or 3) closing with saving. When an automaton has been "closed", it is no longer in the automata list. If it has also been saved, the json and pdf are saved to disk. Parameters ---------- automata : list List of all automata which are available to choose Returns ------- None """ display_menu(menu_msg) num_options = len(automata) selected = [False] * num_options # Keep on selecting automata to close until choose to stop while True: # Print what we've selected so far print_selected(automata, selected) inpt = input() try: # If input is fine, toggle the selection if int(inpt) in range(num_options): inpt = int(inpt) selected[inpt] = not selected[inpt] except ValueError: # Else, see if we want to exit, close, or save inpt = inpt.lower() if inpt in ["e", "exit"]: return None # Exit without closing elif inpt in ["c", "close"]: # Close all automata selected result = [automata[i] for i in range(num_options) if selected[i]] for item in result: automata.remove(item) sel = [item["name"] for item in result] show_notification("The following were closed:\n" + str(sel)) return elif inpt in ["s", "save"]: # Save all automata selected and close all those not failed result = [automata[i] for i in range(num_options) if selected[i]] # Keep track of those that fail to save, and don't close them failed = [] for item in result: saved = save(item) if saved: automata.remove(item) else: show_error("Could not save, so automaton not closed") failed.append(item) # Show which ones were actually closed sel = [item["name"] for item in result if item not in failed] show_notification("The following were saved and closed:\n" + str(sel)) else: show_error("Command not recognized")
def ops_menu(automata, temp_dir): """Opens a menu with options for different operations that can be performed. Parameters ---------- automata : list The list of automata currently open in the program temp_dir : str The temporary directory for the session Returns ------- None """ display_menu(menu_msg) inpt = input().lower() # Choose which operation to perform if inpt in ["d", "determinization"]: selected = select_automaton_menu(automata, "Determinization") if selected is not None: observer = select_observer_menu(selected) if observer is not None: result = determinize(selected, observer) __save(automata, result, temp_dir) elif inpt in ["o", "opacity"]: selected = select_automaton_menu(automata, "Checking Opacity") if selected is not None: observer = select_observer_menu(selected) if observer is not None: result = check_opacity(selected, observer) print("With respect to the observer " + str(observer) + ", the system is opaque") print("for the following secrets:") print([i for i, x in enumerate(result) if x is True]) print("The system is not opaque for the following secrets:") print([i for i, x in enumerate(result) if x is False]) elif inpt in ["u", "union", "parallel composition"]: selected = select_automata_menu(automata, 2, "Parallel Composition") if selected is not None: result = union(selected) __save(automata, result, temp_dir) elif inpt in ["p", "product", "intersection"]: selected = select_automata_menu(automata, 2, "Intersection") if selected is not None: result = product(selected) __save(automata, result, temp_dir) elif inpt in ["a", "accessible"]: selected = select_automaton_menu(automata, "Accessibility Operation") if selected is not None: result = get_accessible(selected) __save(automata, result, temp_dir) elif inpt in ["c", "controllable"]: selected = select_automaton_menu(automata, "Controllability Operation") if selected is not None: result = get_controllable(selected) __save(automata, result, temp_dir) elif inpt in ["ca", "coaccessible"]: selected = select_automaton_menu(automata, "Coaccessibility Operation") if selected is not None: result = get_coaccessible(selected) __save(automata, result, temp_dir) elif inpt in ["l", "leakage"]: selected = select_automaton_menu(automata, "Get Leakage Automaton") if selected is not None: observer = select_observer_menu(selected) if observer is not None: secret = select_secret_menu(selected) if secret is not None: result = create_leakage_automaton(selected, observer, secret) __save(automata, result, temp_dir) elif inpt in ["ba"]: selected = select_automaton_menu(automata, "Constructing Arena") if selected is not None: result = construct_arena(selected) __save(automata, result, temp_dir) show_notification("Bad states:\n" + str(result["states"]["bad"])) elif inpt in ["bt"]: selected = select_automaton_menu(automata, "Constructing Attractor") if selected is not None: result = construct_attractor(selected) __save(automata, result, temp_dir) show_notification("Bad states:\n" + str(result["states"]["bad"])) elif inpt in ["bp"]: selected = select_automaton_menu(automata, "Pruning Arena") if selected is not None: result = get_controllable(construct_attractor(selected)) __save(automata, result, temp_dir) elif inpt in ["om"]: show_notification( "With this operation, we assume the\nattacker can see all items in the\nshared alphabet,as per Enforcing\nOpacity in Modular Systems (2020)" ) selected = select_automata_menu( automata, 1, "Checking Opacity for Modular Systems") if selected is not None: heuristic = select_heuristic() result = check_modular_opacity(selected, heuristic=heuristic) show_notification("The modular system is " + ("opaque" if result else "not opaque")) elif inpt in ["bca"]: selected = select_automaton_menu(automata, "Constructing Communication Arena") if selected is not None: result = construct_communication_arena(selected) __save(automata, result, temp_dir) elif inpt in ["e", "exit"]: pass else: show_error("Command not recognized")