class Game: def quit(self): self._user_interface.print("Bye!") exit() def __init__(self): self._world = World() directions = resources.load_directions() resources.load_rooms(self._world, directions) self._player = Player(self._world.starting_room, directions) commands = resources.load_commands(self) self._user_interface = UserInterface(commands) aliases = resources.load_aliases() errors = resources.load_errors() parser = Parser(directions, commands, aliases, errors) while True: self._user_interface.describe_room(self._player.room) (cmd, *args) = parser.get_input() result = cmd(*args) if result: result.show() @property def world(self): return self._world @property def user_interface(self): return self._user_interface @property def player(self): return self._player
def __init__(self, game_map, move): self.user_interface = UserInterface() self.backpack = Backpack() self.move = move self.game_map = game_map
class Merchant: """ This class handles all merchant related actions including buying and selling as well as depositing gold """ MERCHANTS = Enum('Merchants', 'WEAPONS, BLACKSMITH, POTIONS, ITEMS, BANKER') def __init__(self, game_map, move): self.user_interface = UserInterface() self.backpack = Backpack() self.move = move self.game_map = game_map def move_to_merchant(self, merchant_type): """ Move to a merchant """ # Move to the appropriate merchant merchant_tile = None # Weapons shopkeeper if merchant_type == self.MERCHANTS.WEAPONS: merchant_tile = self.game_map.TILES.WEAPON_SHOPKEEPER.value self.move.move_to(self.move.WEAPON_SHOPKEEPER) # Blacksmith elif merchant_type == self.MERCHANTS.BLACKSMITH: merchant_tile = self.game_map.TILES.BLACKSMITH.value self.move.move_to(self.move.FURNACE) # Potions shopkeeper elif merchant_type == self.MERCHANTS.POTIONS: merchant_tile = self.game_map.TILES.POTIONS_SHOPKEEPER.value self.move.move_to(self.move.POTIONS_SHOPKEEPER) # Items shopkeeper elif merchant_type == self.MERCHANTS.ITEMS: merchant_tile = self.game_map.TILES.ITEM_SHOPKEEPER.value self.move.move_to(self.move.ITEMS) # Banker elif merchant_type == self.MERCHANTS.BANKER: merchant_tile = self.game_map.TILES.BANKER.value self.move.move_to(self.move.BANKER) else: utils.log("SEVERE", "Invalid merchant_type supplied to move_to_merchant") utils.quit_game() # Update map so merchant's position will be current self.game_map.update_map() # Get the 5x5 matrix of tiles surrounding the player clickable_tiles = self.game_map.game_map[( self.game_map.player_position[0] - 2):(self.game_map.player_position[0] + 3), (self.game_map.player_position[1] - 2):(self.game_map.player_position[1] + 3)] # Find the index where merchant is located merchant_indices = np.argwhere(clickable_tiles == merchant_tile) if merchant_indices.size == 0: return False # Get the merchant index merchant_index = merchant_indices[0] # Calculate where to click (2 because player is in center of 5x5 matrix that is 0 indexed) x_coord = merchant_index[0] - 2 y_coord = merchant_index[1] - 2 return (176 + (x_coord * 16), 176 + (y_coord * 16)) def click_on_merchant(self, merchant_type): """ Move to the specified merchant type and double click them """ # Move to the merchant attempts = 0 while attempts < 10: # Find where to click on the merchant click_at = self.move_to_merchant(merchant_type) if not click_at: continue # Click on the merchant pyautogui.moveTo(click_at[0], click_at[1], 0.15) pyautogui.doubleClick() # Check that the buy or sell window was opened buy_or_sell = self.user_interface.wait_for_ui_element( 'buyOrSell', exit_on_fail=False) # Buy and sell window is open if buy_or_sell: return True # Still not open sleep(1) attempts += 1 # Never opened return False def open_merchant_window(self, merchant_type): """ Open the "Buy or Sell" window or return False is unable to """ attempts = 0 while attempts < 10: # Try and click on the merchant window_is_open = self.click_on_merchant(merchant_type) if window_is_open: return window_is_open sleep(1) attempts += 1 return False def buy_item(self, item, merchant_type): """ Move to a merchant and buy an item """ # Open the "Buy or Sell" window buy_or_sell = self.open_merchant_window(merchant_type) if not buy_or_sell: utils.log( "SEVERE", F"Failed to click on {merchant_type} and open 'Buy or Sell' after 10 attempts" ) utils.quit_game() # Click the buy button buy_button = self.user_interface.wait_for_ui_element('buy') pyautogui.moveTo(buy_button[0] + 10, buy_button[1] + 10, 0.15) pyautogui.click() # Wait for the buy menu to open self.user_interface.wait_for_ui_element('buyMenu') # Find the item to buy item_loc = self.user_interface.wait_for_ui_element(item) pyautogui.moveTo(item_loc[0] + 6, item_loc[1] + 6, 0.15) pyautogui.doubleClick() # Confirm the sale check_mark = self.user_interface.wait_for_ui_element('checkMark') pyautogui.moveTo(check_mark[0] + 5, check_mark[1] + 5, 0.15) pyautogui.click() # Click cancel to leave the window cancel = self.user_interface.wait_for_ui_element('cancel') pyautogui.moveTo(cancel[0] + 5, cancel[1] + 5, 0.15) pyautogui.click() pyautogui.moveTo(400, 400) utils.log("INFO", F"Bought a {item}") def sell_item(self, item, merchant_type): """ Move to a merchant and sell an item """ # Open the "Buy or Sell" window buy_or_sell = self.open_merchant_window(merchant_type) if not buy_or_sell: utils.log( "SEVERE", F"Failed to click on {merchant_type} and open 'Buy or Sell' after 10 attempts" ) utils.quit_game() # Click the sell button sell_button = self.user_interface.wait_for_ui_element('sell') pyautogui.moveTo(sell_button[0] + 10, sell_button[1] + 10, 0.15) pyautogui.click() # Wait for the sell menu to open self.user_interface.wait_for_ui_element('sellMenu') # Offer up to 12 items items_sold = 0 for _ in range(12): # Move the cursor away so it will register an "hover" event when move back pyautogui.moveTo(330, 206) # Find a item to sell item_loc = self.user_interface.get_ui_element(item, exit_on_fail=False) # No item_locs left to sell if not item_loc: utils.log("INFO", F"No {item} left to offer shopkeeper") break items_sold += 1 pyautogui.moveTo(item_loc[0] + 6, item_loc[1] + 12, 0.15) pyautogui.doubleClick() sleep(0.5) # Confirm the sale check_mark = self.user_interface.wait_for_ui_element('checkMark') pyautogui.moveTo(check_mark[0] + 5, check_mark[1] + 5, 0.15) pyautogui.click() # Click cancel to leave the window cancel = self.user_interface.wait_for_ui_element('cancel') pyautogui.moveTo(cancel[0] + 5, cancel[1] + 5, 0.15) pyautogui.click() utils.log("INFO", F"Sold {items_sold} {item}(s)") return items_sold
class Player(): """ This class handles everything relating to the player """ LOW_HEALTH = 150 TASKS = Enum('Task', 'MINE, SMELT, FORGE') def __init__(self, game_map, task=TASKS.MINE): self.user_interface = UserInterface() self.backpack = Backpack() self.mine = Mine(self, game_map) self.smelt = Smelt(self, game_map) self.forge = Forge(self, game_map) # Set the default initial task self.task = task self.action_count = 0 def perform_task(self): """ Checks health, organizes backpack and then performs one of the following tasks: mine, smelt, or forge """ # Do pre-task checks self.action_count += 1 # Only check health every 25 turns (it is a slow process) if self.action_count % 25 == 0: self.action_count = 0 self.check_health() # Perform task if self.task == self.TASKS.MINE: self.task = self.mine.mine() delay = 0 elif self.task == self.TASKS.SMELT: self.task = self.smelt.smelt() delay = 1.4 elif self.task == self.TASKS.FORGE: self.task = self.forge.forge() delay = 2.1 # Give the task time to complete sleep(delay) # Organize backpack now that items have been potentially added self.organize_backpack() def check_health(self): """ Checks player's HP and uses a potion if it is low. If no potions are found, game will quit """ # Check if HP is low if self.user_interface.get_health() < self.LOW_HEALTH: # Attempt to use a potion utils.log("INFO", F"Health dropped below {self.LOW_HEALTH}") used_potion = self.backpack.use_item('potion', offset=(4, 9)) # No potions were found if not used_potion: # Potions may be obscurred by items, try selling self.forge.sell_items() # Try using a potion again used_potion = self.backpack.use_item('potion', offset=(4, 9)) # Still can't use potions, likely do not have any if not used_potion: utils.log("SEVERE", "No potions found") utils.quit_game() # Sleep so that there is no issue using the next item utils.log("INFO", F"Used a potion") sleep(6) def is_weight_below_threshold(self, threshold): # Calculate how much more weight the player can carry current_weight, max_weight = self.user_interface.get_weight() difference = max_weight - current_weight # Check if the weight the player can carry is below the threshold if difference < threshold: utils.log("INFO", F"Weight is {difference} from max, threshold was set to {threshold}") return True return False def organize_backpack(self): """ Move all items to the correct areas of the backpack """ self.backpack.move_item('ore', self.backpack.ORE_LOC, (8, 6)) self.backpack.move_item('gem', self.backpack.GEM_LOC, (4, 2)) self.backpack.move_item('jewel', self.backpack.GEM_LOC, (4, 2)) self.backpack.move_item('galantine', self.backpack.GEM_LOC, (5, 4)) self.backpack.move_item('pickaxe', self.backpack.PICKAXE_LOC, (9, 4)) self.backpack.move_item('dagger', self.backpack.DAGGER_LOC, (4, 6)) self.backpack.move_item('hammer', self.backpack.HAMMER_LOC, (7, 3)) self.backpack.move_item('gold', self.backpack.GEM_LOC, (6, 5)) self.backpack.move_item('ingot', self.backpack.INGOT_LOC)
import sys sys.path.append("../src/") from user_interface import UserInterface from camera import Camera camera = Camera() camera.start() ui = UserInterface() ui.setup_screen("con", "not con") ui.wait_for_input() ui.opening_screen() ui.wait_for_input() ui.x_of_y_screen(1, 3) ui.wait_for_input() ui.countdown_screen(camera) ui.image_screen("../images/photobooth_opening.png") ui.wait_for_input() ui.print_screen("../images/photobooth_opening.png") ui.wait_for_input()
from user_interface import UserInterface UserInterface().main()
class Feeder: def __init__(self, task): self.running = False self.ui = UserInterface() self.task = task self.first_start = time.time() self.start = time.time() self.recorded_time = 0 self.paused = False def run(self): self.running = True self.ui.win.addstr(11, 1, f"Task: ") self.ui.win.addstr(11, 7, f"{self.task}", curses.color_pair(2)) self.feed() def quit(self): self.running = False self.ui.quit_ui() if self.paused: self.start = time.time() + 1 task = f" in {self.task}" if self.task != "None" else "" exit( f"Time{task}: {timer.get_time_string(self.start, self.recorded_time)}" ) def feed(self): try: while self.running: while sys.stdin in select([sys.stdin], [], [], 0)[0]: line = sys.stdin.read(1) if line.strip().lower() == "q": if config.autosave_q: save = Save(self.first_start, self.paused, self.recorded_time, self.start, self.task) save.save_to_csv() self.quit() break elif line.strip().lower() == "p": if self.paused: self.start = time.time() self.ui.win.addstr(14, 29, " ") self.paused = False else: self.recorded_time = timer.compute_time( self.start, self.recorded_time) self.ui.win.addstr(14, 29, "**PAUSED**", curses.color_pair(1)) self.paused = True elif line.strip().lower() == "s": save = Save(self.first_start, self.paused, self.recorded_time, self.start, self.task) save.save_to_csv() if not self.paused: self.ui.win.addstr( 9, 33, timer.get_time_string(self.start, self.recorded_time), curses.A_BOLD) if not config.autosave_delay == 0: if int(time.time()) != int(self.start): if (int(time.time()) - int(self.start)) % config.autosave_delay == 0: save = Save(self.first_start, self.paused, self.recorded_time, self.start, self.task) save.save_to_csv() self.ui.refresh() time.sleep(0.1) except KeyboardInterrupt: if config.autosave_c: save = Save(self.first_start, self.paused, self.recorded_time, self.start, self.task) save.save_to_csv() self.quit()
class TimesheetManager: def __init__(self, name=None, path=os.getcwd()): self.__version__ = VERSION self.path = pathjoin(path, "timesheets") os.makedirs(self.path, exist_ok=True) os.makedirs(CONFIG_PATH, exist_ok=True) if "config.data" not in os.listdir(CONFIG_PATH): self.create_config() default, tz = self.load_config() self.tz = tz if name is None: if default != "": name = default else: clear() print( "[SETUP] There is no default Timesheet set. A temporary Timesheet will be created." ) print( "\nIf you have not yet created a timesheet, or need to set your default timesheet," ) print("please do so in the 'Timesheet Management' menu.") _ = input("\nPress ENTER to continue...") name = "TEMPORARY" self.name = name self.today = pendulum.today(tz=self.tz) new = False loaded = self.load_timesheet(self.name) if not loaded: clear() print( "[SETUP] The current default Timesheet does not exist.\nA temporary Timesheet will be created." ) print( "\nPlease change your default timesheet in the 'Timesheet Management' menu." ) _ = input("\nPress ENTER to continue...") name = "TEMPORARY" new = True self.tasks = None self.data = pd.DataFrame(index=self.tasks) self.init_configs() self.working_start = None self.work_day_allocated = 0 self.UI = UserInterface(name, new, self.today, VERSION) if ".state-{}".format(name) in os.listdir(STATE_PATH): task, start = self.load_state() self.start_task_from_state(task, start) if ".state-{}-workday".format(name) in os.listdir(STATE_PATH): self.working_start, self.work_day_allocated = self.load_workday_state( ) self.UI.working = True while True: code, string = self.UI.ask_generic_input() if code == '1': self.start_task(string) elif code == '2': if string == 'start': self.start_workday() else: self.add_workday() elif code == '31': self.time_per_task(string) elif code == '32': self.time_per_day(string) elif code == '33': self.time_per_taskday(*string) elif code == '34': self.total_time() elif code == "35": self.weekly_report() elif code == '41': self.list_tasks() elif code == '43': self.delete_task(string) elif code == '42': self.add_task(string) elif code == '43': self.delete_task(string) elif code == '51': self.list_timesheets() elif code == '52': self.create_new_timesheet(string) elif code == '53': loaded = self.load_timesheet(string) if not loaded: print("Timesheet '{}' does not exist.".format(name)) self.UI.user_return() elif code == '54': self.delete_timesheet(string) elif code == '55': self.backup_timesheet(string) elif code == '56': self.save_config_default(string) elif code == '59': self.export() elif code == '57': self.set_baseline(string) elif code == '58': self.set_workweek(string) elif code == '7': if self.working_start is not None: self.UI.banner() print( "[WARNING] The workday is still running! Please stop it before exiting." ) self.UI.user_return() else: sys.exit() elif code == 'debug': self.debug() self.UI.banner() # places banner at top of each new page ################ File Management Functions ################ def save_timesheet(self, path, name, data): """ Saves current active timesheet at specified path. :param path: path to save :param name: name of Timesheet :param data: data of timesheet """ path = pathjoin(path, "{}.pkl".format(name)) pickle.dump(data, open(path, "wb")) def load_timesheet(self, name, only_data=False): """ Loads a timesheet and sets all the parameters of this class to deal with the new timesheet :param name: name of Timesheet :return: False if file not found error, True if loaded, or data if asking for data """ if name != "": path = pathjoin(self.path, "{}.pkl".format(name)) if not only_data: try: self.data = pickle.load(open(path, "rb")) self.name = name self.working_start = None self.work_day_allocated = 0 self.UI = UserInterface(name, False, self.today, VERSION) self.init_configs() print("{} Timesheet loaded.".format(name)) if ".state-{}".format(name) in os.listdir(STATE_PATH): task, start = self.load_state() self.start_task_from_state(task, start) if ".state-{}-workday".format(name) in os.listdir( STATE_PATH): self.working_start, self.work_day_allocated = self.load_workday_state( ) except FileNotFoundError: return False else: try: return pickle.load(open(path, "rb")) except FileNotFoundError: return False return True def delete_timesheet(self, name): """ Deletes a timesheet. Has a confirmation to make sure a file isn't deleted when not wanted to Will not delete backups! This is a safety feature. :param name: name of timesheet to delete """ self.UI.banner() if name != "": decision = None while decision not in ["y", "n"]: decision = input( "[WARNING] Confirm DELETION of Timesheet '{}' [y/n]: ". format(name)).lower() if decision == "y": if "{}.pkl".format(name) in os.listdir(self.path): if name == self.name: os.remove(pathjoin(self.path, name + ".pkl")) print( "[WARNING] Deleting current Timesheet, new current Timesheet will be the default." ) _ = input("\nPress ENTER to continue...") loaded = self.load_timesheet(self.load_config()[0]) if not loaded: self.UI.banner() print( "[WARNING] No default Timesheet set, creating a temporary..." ) _ = input("\nPress ENTER to acknowledge...") self.create_new_timesheet("TEMPORARY") self.UI.banner() print("'{}' deleted.".format(name)) self.UI.user_return() else: print( "There exists no Timesheet with the name '{}'.".format( name)) self.UI.user_return() else: print("'{}' not deleted.".format(name)) self.UI.user_return() def list_timesheets(self): """ Lists Timesheets saved """ self.UI.banner() print("List of Timesheets:\n") i = 1 # need this because it will also pick up non .pkls if using enumerate for timesheet in os.listdir(self.path): if timesheet[-4:] == '.pkl': print("\t({}) {}".format( i, timesheet.split( '.')[0])) # remove the .pkl extension in printing i += 1 self.UI.user_return() def backup_timesheet(self, name): """ Backups a timesheet by saving it in another folder. First loads it, then saves it in the backup folder :param name: name of timesheet to backup """ path = pathjoin(self.path, ".backup") os.makedirs(path, exist_ok=True) data = self.load_timesheet(name, only_data=True) if type(data) == bool: print("Timesheet '{}' does not exist.".format(name)) else: self.save_timesheet(path, name, data) if "{}-config.data".format(self.name) in os.listdir(CONFIG_PATH): os.makedirs(pathjoin(path, ".config"), exist_ok=True) copyfile( pathjoin(CONFIG_PATH, "{}-config.data".format(self.name)), pathjoin(path, ".config", "{}-config.data".format(self.name))) print("'{}' successfully backed up.".format(name)) self.UI.user_return() def create_new_timesheet(self, name): """ Creates a new timesheet with specified name :param name: Name of new timesheet """ self.UI.banner() if "{}.pkl".format(name) in os.listdir(self.path): print("Timesheet '{}' already exists.".format(name)) self.UI.user_return() else: if name != "": self.name = name new = True self.tasks = None self.data = pd.DataFrame(index=self.tasks) self.UI = UserInterface(name, new, self.today, VERSION) self.working_start = None self.init_configs() print("New Timesheet with the name '{}' loaded.".format(name)) self.UI.user_return() def export(self): """ Exports data to csv after confirmation dialog """ self.UI.banner() export = input( "[WARNING] Exporting times from the current Timesheet will allow \n" "anyone to view the data without the need for unpickling.\n\n" "Do you wish to continue? [y/n]...") if export.lower() == 'y': self.UI.banner() print("Exporting Timesheet '{}' to '{}.csv'".format( self.name, self.name)) self.data.to_csv("{}.csv".format(self.name)) print("\nExport successful.") self.UI.user_return() elif export.lower() == 'n': self.UI.banner() print("Exporting canceled.") self.UI.user_return() else: self.UI.banner() print("[WARNING] Invalid input...not exporting.") self.UI.user_return() ################ State Functions ################ def create_state(self, task, start): """ Creates a hidden state file with the current task and time being recording so it can be started again in case of failure. No need to check for existence since it will always be deleted on startup. :param task: task being recorded :param start: starting time of task """ with open(pathjoin(STATE_PATH, ".state-{}".format(self.name)), "w") as state: state.write("{}={}".format(task, start)) def create_workday_state(self): """ Creates a hidden state file with the time the workday was started and also allocated time so the workday can be started again in case of failure. No need to check for existence since it will always be deleted on startup. """ with open(pathjoin(STATE_PATH, ".state-{}-workday".format(self.name)), "w") as state: state.write("{}={}".format(self.working_start, self.work_day_allocated)) def load_workday_state(self): """ Loads the workday information in the saved state file :return: workday time and allocated time """ with open(pathjoin(STATE_PATH, ".state-{}-workday".format(self.name)), "r") as state: old = state.read().split("=") workday = float(old[0]) allocated = float(old[1]) return workday, allocated def load_state(self): """ Loads the information in the saved state file :return: the task and start time of the info in the file """ with open(pathjoin(STATE_PATH, ".state-{}".format(self.name)), "r") as state: old = state.read().split("=") task = old[0] start = float(old[1]) return task, start def delete_state(self): """ Deletes the state file """ os.remove(pathjoin(STATE_PATH, ".state-{}".format(self.name))) def delete_workday_state(self): """ Deletes the workday state file """ os.remove(pathjoin(STATE_PATH, ".state-{}-workday".format(self.name))) ################ Configuration Functions ################ def create_config(self): """ Creates a config with all parameters empty """ with open(pathjoin(CONFIG_PATH, "config.data"), "w") as config: config.write("default_timesheet=") config.write("\ntz=local") def save_config_default(self, default): """ Saves default timesheet in a text file for later usage. :param default: name of timesheet to set as default """ self.UI.banner() with open(pathjoin(CONFIG_PATH, "config.data"), "r") as config: lines = config.readlines() with open(pathjoin(CONFIG_PATH, "config.data"), 'w') as config: config.seek(0) # rewind config.write( "default_timesheet={}\n".format(default)) # write the new line for line in lines[1:]: # paste all future lines config.write(line) print("'{}' set as default Timesheet.".format(default)) self.UI.user_return() def save_config_timesheet(self, workweek_hours, baseline): """ Saves timesheet specific configurations Format: [NAME] workweek=40 baseline=23h17m [NAME] workweek= baseline= :param workweek_hours: what the workweek hours are; defaults to what is loaded at start :param baseline: imported already worked times; defaults to what is loaded at start """ if "{}-config.data".format(self.name) not in os.listdir( CONFIG_PATH): # create it if it doesn't exist with open( pathjoin(CONFIG_PATH, "{}-config.data".format(self.name)), "w") as config: config.write("[{}]".format(self.name)) with open(pathjoin(CONFIG_PATH, "{}-config.data".format(self.name)), "w") as config: if workweek_hours == None: workweek_hours = "" if baseline == None: baseline = "" config.write("[{}]".format(self.name)) config.write("\nworkweek={}".format(workweek_hours)) config.write("\nbaseline={}".format(baseline)) def load_config_timesheet(self): """ Loads in timesheet specific config information """ with open(pathjoin(CONFIG_PATH, "{}-config.data".format(self.name)), "r") as config: for line in config.readlines(): if line[:8] == "workweek": workweek_line = line elif line[:8] == "baseline": baseline_line = line workweek = workweek_line.split("=")[1] baseline = baseline_line.split("=")[1] return workweek[:-1], baseline # to -2 to avoid \n def load_config(self): """ Loads config file """ with open(pathjoin(CONFIG_PATH, "config.data"), "r") as config: for line in config.readlines(): if line[:7] == "default": default_line = line elif line[:2] == "tz": tz_line = line default = default_line.split("=")[1] tz = tz_line.split("=")[1] return default[:-1], tz # to -2 to avoid \n def set_baseline(self, baseline): """ Sets baseline by rewriting file and keeping everything the same except baseline :param baseline: the baseline to write """ self.UI.banner() self.save_config_timesheet(self.workweek, baseline) print("Baseline saved for Timesheet '{}'.".format(self.name)) self.baseline = baseline self.UI.user_return() def set_workweek(self, workweek): """ Sets workweek by rewriting file and keeping everything the same except workweek :param workweek: the workweek to write """ self.UI.banner() if workweek != "": self.workweek = int(workweek) else: self.workweek = "" self.save_config_timesheet(workweek, self.baseline) print("Workweek saved for Timesheet '{}'.".format(self.name)) self.UI.user_return() def init_configs(self): """ Just a function to help keep the code clean since this will appear multiple times. """ try: workweek, baseline = self.load_config_timesheet() if workweek != "": self.workweek = int(workweek) else: self.workweek = "" self.baseline = baseline except FileNotFoundError: self.workweek = "" self.baseline = "" ################ Logging Functions ################ def start_task(self, task_name): """ Starts the recording process. Quietly calls _end_task when done, to record the time into the data. Creates a new task if provided task is not already existing. :param task_name: task to record """ go_on = True if task_name != "": if task_name not in self.data.index: self.UI.banner() add = input( "[WARNING] '{}' is not in the list of Tasks...would you like to add it? [y/n]..." .format(task_name)) if add.lower() == 'y': self.add_task(task_name, suppress=True) go_on = True elif add.lower() == 'n': go_on = False else: print( "[WARNING] Invalid input...not creating new Task and returning to the main menu..." ) go_on = False self.UI.user_return() if go_on: if self.today.to_date_string() not in self.data.columns: self.data[self.today.to_date_string()] = 0 start_time = time.time() # Save the state in case of crashes: self.create_state(task_name, start_time) # Start the UI logging time, once stopped through the UI, record the time self.UI.timelogger(task_name) self._end_task(task_name, start_time) def start_task_from_state(self, task_name, start): """ Starts recording time on the given task and then adds on previously recorded time. ASSUMES TASK WAS CONTINUED CONTINUOUSLY FROM INITIAL START # TODO: Allow resuming task on a different day :param task_name: task to resume :param start: old starting time """ if self.today.to_date_string() not in self.data.columns: self.data[self.today.to_date_string()] = 0 self.UI.timelogger(task_name, start) self._end_task(task_name, start) def _end_task(self, name, start_time): """ Quietly called from start_task. Ends the task and records the time by adding it to the time already recorded for that task :param name: task to record """ self.UI.banner() time_worked = int(time.time() - start_time) # do not care about ms self.data.at[name, self.today.to_date_string()] += time_worked print("Logging of Task '{}' stopped...".format(name)) self.save_timesheet(self.path, self.name, self.data) print("Time successfully recorded!") self.delete_state() if self.working_start: if name != "General": self.work_day_allocated += time_worked self.create_workday_state() self.UI.user_return() self.UI.banner() def start_workday(self): """ Starts recording all time until deactivated. """ self.working_start = time.time() self.create_workday_state() def add_workday(self): """ Adds to task "general" all the time during the workday that was not already assigned to a task. """ work_time = time.time() - self.working_start self.UI.banner() if self.today.to_date_string() not in self.data.columns: self.data[self.today.to_date_string()] = 0 if "General" not in self.data.index: print( "No Task exists to log general work time...creating Task 'General'" ) self.add_task("General") workday = work_time - self.work_day_allocated self.work_day_allocated = 0 self.working_start = None self.delete_workday_state() if workday < 0: print( "[ERROR] Workday length was negative time. Did you start your workday properly?" ) print("[DEBUG] workday={}, worktime={}".format(workday, work_time)) self.UI.user_return() else: self.UI.banner() self.data.at["General", self.today.to_date_string()] += int( workday) # do not care about ms work_time_mins = Converter.sec2min(work_time) work_time_hours, work_time_mins = Converter.min2hour( work_time_mins) work_hour_min_string = Converter.convert2string( int(work_time_hours), int(work_time_mins)) mins = Converter.sec2min(workday) hours, mins = Converter.min2hour(mins) hour_min_string = Converter.convert2string(int(hours), int(mins)) print( "Total hours accumulated during the this work day: {}".format( work_hour_min_string)) print("Total hours set as general tasks during this period: {}". format(hour_min_string)) print("\nWork day ended!") self.save_timesheet(self.path, self.name, self.data) self.UI.user_return() ################ Task Functions ################ def list_tasks(self): """ Lists the index of the data, which are the task names """ self.UI.banner() print("List of Tasks in Timesheet {}:\n".format(self.name)) for i, task in enumerate(self.data.index): print("\t({}) {}".format(i + 1, task)) self.UI.user_return() def add_task(self, task_name, suppress=False): """ Adds task to the dataframe by adding it to the index. If the task already exists, it exits. Can take string or [str]. :param task_name: name of task to add :param suppress: suppresses user blocking input """ self.UI.banner() if task_name in self.data.index: print("Task '{}' already in Timesheet '{}'.".format( task_name, self.name)) self.UI.user_return() else: if task_name != "": if type(task_name) == str: task_name = [task_name] new_task = pd.DataFrame(index=task_name) self.data = self.data.append(new_task, verify_integrity=True, sort=False) print("Task '{}' created.".format(task_name[0])) self.data.fillna(0, inplace=True) self.save_timesheet(self.path, self.name, self.data) if not suppress: self.UI.user_return() def delete_task(self, task_name): """ Deletes task from the data. If it doesn't exist, it does nothing. :param task_name: task to delete """ self.UI.banner() if task_name not in self.data.index: if task_name != "": print("'{}' task not in database.".format(task_name)) self.UI.user_return() else: self.data.drop(task_name, inplace=True) self.save_timesheet(self.path, self.name, self.data) print("Task '{}' successfully deleted.".format(task_name)) self.UI.user_return() ################ Time Functions ################ #TODO: Printing when only seconds are there def time_per_day(self, day): """ Reports total time worked on given day :param day: day to report """ self.UI.banner() if day == "today": day = self.today.to_date_string() elif day == "yesterday": day = pendulum.yesterday(tz=self.tz).to_date_string() if day not in self.data.columns: print("There is no data for the selected date ({}).".format(day)) else: times = self.data[day].sum() if times == 0: print("No Tasks were logged on {}.".format(day)) else: mins = Converter.sec2min(times) hours, mins = Converter.min2hour(mins) hour_min_string = Converter.convert2string( int(hours), int(mins)) string = "Summary for {}:".format(day) print(string) self.UI.summary_divider(string) if hours == 0: print(hour_min_string.split(", ")[1]) else: print(hour_min_string) if type(self.workweek) == int: per_day_minutes = (self.workweek / 5) * 60 per_day_hours, per_day_minutes = Converter.min2hour( per_day_minutes) diff_hours, diff_mins = TimeCalculator.subtract( per_day_hours, per_day_minutes, hours, mins) print("\nWith a workweek of {} hours, " "the average daily hours equates to: {}.".format( self.workweek, Converter.convert2string( int(per_day_hours), int(per_day_minutes)))) # ugly lol if diff_hours is not None: print("{} is left remaining.".format( Converter.convert2string(int(diff_hours), int(diff_mins)))) else: print( "Sufficient hours have been worked today to meet that amount." ) self.UI.user_return() def time_per_task(self, task): """ Reports total time worked for given task :param task: task to report """ self.UI.banner() if task not in self.data.index: print("There is no Task named '{}'.".format(task)) else: times = self.data.loc[task].sum() if times == 0: print("No time was logged for Task '{}'.".format(task)) else: mins = Converter.sec2min(times) hours, mins = Converter.min2hour(mins) hour_min_string = Converter.convert2string( int(hours), int(mins)) days, hours_day = Converter.hour2day(hours) day_hour_min_string = Converter.convert2string_days( int(days), int(hours_day), int(mins)) string = "Summary for '{}':".format(task) print(string) self.UI.summary_divider(string) if hours == 0: print(hour_min_string.split(", ")[1]) else: print(hour_min_string) if days != 0: print(day_hour_min_string) self.UI.user_return() def time_per_taskday(self, task, day): """ Reports total time for a given task on a given day :param task: task to report :param day: day to report on """ self.UI.banner() skip = False if day == "today": day = self.today.to_date_string() elif day == "yesterday": day = pendulum.yesterday(tz=self.tz).to_date_string() if task not in self.data.index: print("There is no Task named '{}'.".format(task)) skip = True if day not in self.data.columns: print("There is no data for the selected date ({}).".format(day)) skip = True if not skip: times = self.data[day].loc[task] if times == 0: print("No time was logged for Task '{}' on {}.".format( task, day)) else: mins = Converter.sec2min(times) hours, mins = Converter.min2hour(mins) hour_min_string = Converter.convert2string( int(hours), int(mins)) string = "Summary for '{}' on {}:".format(task, day) print(string) self.UI.summary_divider(string) if hours == 0: print(hour_min_string.split(", ")[1]) else: print(hour_min_string) self.UI.user_return() def total_time(self): """ Report on total time worked """ self.UI.banner() times = self.data.values.sum() if times == 0: print("No time has been logged in this Timesheet yet.") else: mins = Converter.sec2min(times) hours, mins = Converter.min2hour(mins) hour_min_string = Converter.convert2string(int(hours), int(mins)) days, hours_day = Converter.hour2day(hours) day_hour_min_string = Converter.convert2string_days( int(days), int(hours_day), int(mins)) string = "Summary of all time worked stored in Timesheet '{}':".format( self.name) print(string) self.UI.summary_divider(string) if hours == 0: try: print(hour_min_string.split(", ")[1]) except: print("Less than a minute.") else: print(hour_min_string) print(day_hour_min_string) if self.baseline != "": string = "Summary of all time worked including baseline:" print("\n" + string) self.UI.summary_divider(string) back_days, back_hours, back_mins = Converter.parse_DHM( self.baseline) total_days = back_days + days total_hours = back_hours + hours_day total_mins = back_mins + mins total_worked_hours = (back_days * 24) + back_hours + hours print( Converter.convert2string(int(total_worked_hours), int(mins))) print( Converter.convert2string_days(int(total_days), int(total_hours), int(total_mins))) print( "\nSince the creation of this Timesheet, {} individual days have been worked." .format(len(self.data.columns.values))) self.UI.user_return() def weekly_report(self): self.UI.banner() workdays = get_current_week_days(self.today) summable_days = workdays tasks = self.data.index report_data = generate_day_dict(workdays, tasks) # Fill up dictionary with data deletable = [] for day in workdays: for task in tasks: try: report_data[day][task] = self.data[day].loc[task] except KeyError: report_data[day][task] = 0 deletable.append(day) for delete in set(deletable): # to remove duplicates summable_days.remove(delete) # Get max length of tasks so that spacing works out max_len = 0 for task in tasks: if len(task) > max_len: max_len = len(task) # Start report string = "Current Week Report" print(string) self.UI.summary_divider(string) for day in reversed(workdays): day_string = day day = pendulum.parse(day) print("{}, {}".format(Converter.convert_int2day(day.day_of_week), day_string[5:])) print("-" * 16) # length of Wednesday string values = [] for task in tasks: value = report_data[day_string][task] values.append(value) if value != 0: mins = Converter.sec2min(value) hours, mins = Converter.min2hour(mins) hour_min_string = Converter.convert2string( int(hours), int(mins)) if len(task) < max_len: string = "{}:".format(task) + (" " * (max_len - len(task))) else: string = "{}:".format(task) if hours == 0 and mins != 0: hour_min_string = hour_min_string.split(", ")[1] print("\t" + string + "\t{}".format(hour_min_string)) elif hours == 0 and mins == 0: continue else: print("\t" + string + "\t{}".format(hour_min_string)) value = sum(values) # Daily sums mins = Converter.sec2min(value) hours, mins = Converter.min2hour(mins) hour_min_string = Converter.convert2string(int(hours), int(mins)) if hours == 0 and mins != 0: hour_min_string = hour_min_string.split(", ")[1] print("\n\tDaily Total:\t\t{}\n".format(hour_min_string)) elif hours == 0 and mins == 0: continue else: print("\n\tDaily Total:\t\t{}\n".format(hour_min_string)) print("\n------------") print("Weekly Total") print("------------") total = int(self.data[summable_days].sum().sum()) mins = Converter.sec2min(total) hours, mins = Converter.min2hour(mins) hour_min_string = Converter.convert2string(int(hours), int(mins)) days, hours_day = Converter.hour2day(hours) day_hour_min_string = Converter.convert2string_days( int(days), int(hours_day), int(mins)) if days == 0: if hours == 0: print(hour_min_string.split(", ")[1]) else: print(hour_min_string) else: print(hour_min_string) print(day_hour_min_string) if type(self.workweek) == int: if hours > self.workweek: print( "Sufficient hours have been worked this week to meet the workweek requirements." ) else: diff = self.workweek - hours print( "{} hours still need to be worked this week in order to meet workweek requirements." .format(diff)) self.UI.user_return() ################ Debug Functions ################ def debug(self): self.UI.banner() print("[DEBUG] Printing head(20) of underlying dataframe...\n") print(self.data.head(20)) self.UI.user_return()
class TestUserInterface(unittest.TestCase): class SampleReport: def __init__(self): self.clone_groups = { 0: [ '/home/alexey/Downloads/masteringdjangocore-sample.pdf', '/home/alexey/Downloads/paris.ps', '/home/alexey/Downloads/IMG_1665.JPG' ], 1: [ '/home/alexey/Downloads/Fluent_Python.pdf', '/home/alexey/Downloads/Photos1/IMG_1670.JPG', '/home/alexey/Downloads/IMG_1664.JPG' ] } self.unavailable_files = { 'can not read anything!!!', 'what to do?' } self.scanned_files_num = 43 self.scanned_folders_num = 12 self.duplications_num = 33 self.name_scanned_folder = '/dd/qwd/qwdw' sample_report = SampleReport() ui = UserInterface(sample_report) def test_general_information(self): self.ui.general_information() def test_exceptions(self): self.ui.exceptions_information() def test_show_search_report(self): self.ui.show_search_report() def test_show_cleaning_input(self): # we suppose that a user entered 1 self.assertEqual(self.ui.show_cleaning_input(0), ([ '/home/alexey/Downloads/masteringdjangocore-sample.pdf', '/home/alexey/Downloads/paris.ps', '/home/alexey/Downloads/IMG_1665.JPG' ], 1)) # we suppose that a user entered 2 self.assertEqual(self.ui.show_cleaning_input(1), ([ '/home/alexey/Downloads/Fluent_Python.pdf', '/home/alexey/Downloads/Photos1/IMG_1670.JPG', '/home/alexey/Downloads/IMG_1664.JPG' ], 2)) # we suppose that a user entered Enter self.assertEqual(self.ui.show_cleaning_input(1), (0, 0)) # we suppose that a user entered 2 self.assertEqual(self.ui.show_cleaning_input(1), ([ '/home/alexey/Downloads/Fluent_Python.pdf', '/home/alexey/Downloads/Photos1/IMG_1670.JPG', '/home/alexey/Downloads/IMG_1664.JPG' ], 2)) def test_report(self): cl_report1 = (['mistake1', 'mistake2'], 1, 2, 3) cl_report2 = (['mistake4', 'mistake5'], 6, 8, 9) self.ui.report(cl_report1) self.ui.report(cl_report2) def test_overall(self): self.ui.overall()
# encoding: utf-8 import os import i18n from models import Student from user_interface import UserInterface from logger import LoggerInterface tanslation_path = os.getcwd() + '/locales' i18n.load_path.append(tanslation_path) userInterface = UserInterface() loggerInterface = LoggerInterface.getInstance() name = userInterface.greet_user() student = Student(name) loggerInterface.initialize_logging(student) show_question = 'Y' while show_question == 'Y': question, answer, time_taken = userInterface.display_question() is_correct = userInterface.is_answer_correct(question, answer) userInterface.show_feedback(is_correct) userInterface.update_confidence(is_correct) userInterface.update_difficulty_level(is_correct) loggerInterface.log( "{operand1} * {operand2},{answer},{correct},{time_taken}".format( operand1=question.operand1, operand2=question.operand2, answer=answer, correct='Yes' if is_correct else 'No', time_taken=time_taken))
from user_interface import UserInterface from hand import Hand UI = UserInterface() class Game: def __init__(self, deck, dealer = None, players = None): """Set up game object. Define min/max bets, whether the game is over or not, the deck, players, and dealer, and the maximum number of players.""" self.min_bet = 10 self.max_bet = 100 self.turn_limit = 1000 self.over = False self.deck = deck self.max_players = 2 self.dealer = dealer if players == None: self.players = [] else: self.players = players def end_game(self): """Simply set the game state to be over.""" self.over = True def start_turn(self): """Deal new hands, and take initial user bets (minimum). Perform any other start-of-turn actions. Boot players if they do not have enough chips for a minimum bet. End the game if there are no more players."""
def main(): c = Controller(View(), UserInterface(), GameSession(), Menu(), HumanPlayer(), Player()) c.play_game()
from game import Game from user_interface import UserInterface # It is import that an imported player imported as 'Player' if you're using # only the one player. from ai_players import SplitDoublePlayer, HitPlayer, RandomPlayer from card_counting_ai import SimpleBeatTheDealerPlayer as CardCounterPlayer """This file exists to start the game and help the Game class to direct the flow. It initializes the game object and runs the primary game loop. The primary game loop, in short, does the following: 1. receive input actions from each player. 2. Let the dealer have an action. 3. If everybody is done, the dealer does actions until he/she is finished. 4. End the turn and start a new one.""" UI = UserInterface() UI.game_instructions() # generate initial players, dealer, and deck deck = Deck() deck.shuffle() # The discard pile is a deck of size 0 # For now, create a single player. Should allow for more. # @TODO Ask for number of players and their names. # UNCOMMENT THE FOLLOWING LINE LINE TO EXPERIMENT WITH PRE-BUILT AI SCRIPTS #players = [SplitDoublePlayer("Human 1"), HitPlayer("Human 2"), RandomPlayer("Human 3")] #players = [Player('Team Twitter')] players = [CardCounterPlayer("BeatTheDealer01")]
CONNECTION_IP = '10.0.0.138' DEFAULT_CAM = 0 #incomingVideoStream = VideoListener(CONNECTION_IP) incomingAudioStream = None # not implemented outgoingVideoStream = VideoStream(src=DEFAULT_CAM).start() #outgoingAudioStream = AudioStream() #get = GetSingleVideoFrame #get.GetFrame(get,outgoingVideoStream) #videoServer = VideoServer(CONNECTION_IP, outgoingVideoStream) #audioSender = None # not implemented # start the app #userInterface = UserInterface(incomingVideoStream, incomingAudioStream) userInterface = UserInterface(outgoingVideoStream, incomingAudioStream) # troubleshooting #userInterface.StartGui(); #this might be better #https://stackoverflow.com/questions/14140495/how-to-capture-a-video-and-audio-in-python-from-a-camera-or-webcam """ SOURCE ELEMENTS: Audio Source Microphone block captures real-world audio samples at a sampling rate Fs Amplitude Control: Use this to reduce the dynamic range of the audio signal. Uniform Encoder: Uniformly quantize and encode the input into specified number of bits (nbits). The input is saturated at positive and negative Peak value. Output datatype is either 8, 16, or 32-bit signed or unsigned integer, based on the least number of bits needed. Apply Fixed delay: Models the propagation delay in the network Apply Random Delay: Models the effect of jittering in the network. UDP send: Transmit audio packets over the IP network with user data gram protocol (UDP) DESTINATION ELEMENTS: 7. Receive UDP packets from the the other PC and fill up the Buffer.
def main(): game = Game() ui = UserInterface(game) ui.run_game()
from user_interface import UserInterface if __name__ == '__main__': interface = UserInterface() interface.run()
class Menu: ui: UserInterface gs: GameSession view: View game_files: str users_data: dict def __init__(self): self.ui = UserInterface() self.gs = GameSession() self.view = View() self.game_file = '' self.users_data = {} # initialize users data self.get_users_data() # actualise users data # main menu components: self.main_menu_lst = [ ('L', 'Login', self.login), ('R', 'Register', self.register), ('Q', 'Quit Game', self.quit)] self.main_menu_dict = self.ui.make_menu(self.main_menu_lst) def get_users_data(self): self.users_data = cu.get_users_data() def print_and_chose_main_menu(self): self.view.prt_menu_all('Main Menu:', self.main_menu_dict) self.ui.chose_menu(self.main_menu_dict.keys(), self.main_menu_dict) return def login(self): # verify if username - in database while True: username = cu.ask_for_username_password(password=False) if username in ['q', 'Q']: self.print_and_chose_main_menu() return elif username in self.users_data.keys(): break # continue to next while else: # if username - not in database => unknown user message self.view.unknown_user_message() # verify password: while True: password = cu.ask_for_username_password() print('password ', password, type(password)) print('passwords: ', self.users_data[username], type(self.users_data[username])) if password in ['q', 'Q']: # back to main menu: self.print_and_chose_main_menu() return # password does not correspond to user elif password != self.users_data[username]: self.view.invalid_password_message() else: break # continue to print welcome back message self.view.print_old_user_message(username) return def register(self): pass @staticmethod def quit(): exit()
def start_ui(name, child_conn): ui = UserInterface(name) ui.run(child_conn)
from drone import Drone from map import Map from repository import Repository from controller import Controller from user_interface import UserInterface if __name__ == '__main__': drone = Drone() n = 20 map = Map(n, n) repository = Repository(drone, map) controller = Controller(repository) ui = UserInterface(controller) ui.run()