def multi_season_prompt(db_session, prompt=None, heading=None): if not prompt: prompt = "Select one or multiple seasons from the list below:" all_seasons = db.Season.get_all_regular_seasons(db_session) choices = {f"{season.year}": season.year for season in all_seasons} instructions = "(use SPACE BAR to select each file type, ENTER to confirm your selections)" seasons_prompt = Check( prompt=instructions, choices=list(choices.keys()), check=EMOJIS.get("CHECK", ""), shift=1, indent=0, margin=2, check_color=colors.foreground["default"], check_on_switch=colors.foreground["default"], word_color=colors.foreground["default"], word_on_switch=colors.bright(colors.foreground["cyan"]), background_color=colors.background["default"], background_on_switch=colors.background["default"], ) selected_years = [] while not selected_years: subprocess.run(["clear"]) if heading: print_heading(heading, fg="bright_yellow") print_message(prompt, wrap=True) result = seasons_prompt.launch() if not result: print_error("\nYou must select at least one season!") pause(message="Press any key to continue...") continue selected_years = [choices[sel] for sel in result] return selected_years
def file_types_prompt(prompt, valid_file_types=VigFile.ALL): if not prompt: prompt = "Select one or multiple file types from the list below:" choices = {f"{f}": f for f in VigFile if int(f) & valid_file_types == f} instructions = "(use SPACE BAR to select each file type, ENTER to confirm your selections)" file_types_prompt = Check( prompt=instructions, choices=list(choices.keys()), check=EMOJIS.get("CHECK", ""), shift=1, indent=0, margin=2, check_color=colors.foreground["default"], check_on_switch=colors.foreground["default"], word_color=colors.foreground["default"], word_on_switch=colors.bright(colors.foreground["cyan"]), background_color=colors.background["default"], background_on_switch=colors.background["default"], ) file_types = [] while not file_types: subprocess.run(["clear"]) print_message(prompt, fg="bright_yellow", bold=True, underline=True) result = file_types_prompt.launch() if not result: print_error("\nYou must select at least one file type!") pause(message="Press any key to continue...") continue file_types = [choices[sel] for sel in result] return file_types
def print_matchup_and_linescore(self): subprocess.run(["clear"]) matchup = self.game_data.get_matchup_details() linescore = self.game_data.get_tui_linescore() print_heading(f"Scraped Data Viewer for Game ID: {self.bbref_game_id}", fg="bright_yellow") print_message(matchup, fg="bright_cyan", bold=True, wrap=False) print_message(linescore, fg="bright_cyan", wrap=False)
def create_and_populate_database_tables(self): self.update_menu_heading("In Progress") result = self.app.initialize_database() if result.success: self.update_menu_heading("Complete!", heading_color="bright_green") print_message(DB_INITIALIZED, fg="bright_green", bold=True) pause(message="Press any key to continue...") return result
def import_scraped_data_prompt(self): example_folder = self.app.get_current_setting("JSON_LOCAL_FOLDER_PATH", DataSet.BBREF_BOXSCORES, year=2019) root_folder = Path(example_folder).parent.parent current_setting = f"JSON_LOCAL_FOLDER_PATH: {root_folder}" self.update_menu_heading("Import Local JSON Folder?") print_message(IMPORT_SCRAPED_DATA_MESSAGE) print_message(current_setting, wrap=False) return yes_no_prompt(IMPORT_SCRAPED_DATA_PROMPT, wrap=False)
def launch_no_prompts(self, year): self.subscribe_to_events() result = self.add_to_db.execute(year) self.spinner.stop() self.unsubscribe_from_events() if result.failure: return result subprocess.run(["clear"]) print_message( f"Added PitchFX data for {len(self.game_ids)} games to database!") return Result.Ok()
def print_page_nav(self): if self.page_count <= 1: return page_number = f"({self.page_index + 1}/{self.page_count})" (pad_left, pad_right) = self.get_pad_lengths(len(page_number)) nav_prev = NAV_PREV if not self.first_page_displayed( ) else f'{" " * NAV_PREV_LEN}' nav_next = NAV_NEXT if not self.last_page_displayed( ) else f'{" " * NAV_NEXT_LEN}' page_nav = f'\n{nav_prev}{" " * pad_left}{page_number}{" " * pad_right}{nav_next}' print_message(page_nav, fg=self.text_color)
def prompt_user_run_task(self): if self.db_initialized: message = WARNING message_color = "bright_red" prompt = RESET_MESSAGE else: message = SETUP_HEADING message_color = None prompt = SETUP_MESSAGE self.update_menu_heading("Run Task?") print_message(message, fg=message_color) return yes_no_prompt(prompt, wrap=False)
def import_scraped_data(self, restart_required): if not self.import_scraped_data_prompt(): return self.setup_complete(restart_required) subprocess.run(["clear"]) self.subscribe_to_events() result = self.import_data_task.execute(overwrite_existing=True) if result.error: print_message(result.error, fg="bright_red") pause(message="Press any key to continue...") else: time.sleep(2) self.unsubscribe_from_events() return self.setup_complete(restart_required)
def data_sets_prompt( heading: str = None, prompt: str = None, valid_data_sets: Optional[List[DataSet]] = None, checked_data_sets: Optional[List[DataSet]] = None, ): if not prompt: prompt = "Select one or multiple data sets from the list below:" if not valid_data_sets: valid_data_sets = [DataSet.ALL] instructions = "(use SPACE BAR to select each data set, ENTER to confirm your selections)" valid_data_sets_int = sum(int(ds) for ds in valid_data_sets) choices = { f"{DATA_SET_TO_NAME_MAP[ds]}": ds for ds in DataSet if valid_data_sets_int & ds == ds } if checked_data_sets: checked_int = sum(int(ds) for ds in checked_data_sets) checked_data_sets = [ f"{DATA_SET_TO_NAME_MAP[ds]}" for ds in DataSet if checked_int & ds == ds ] ds_prompt = DataSetCheck( prompt=instructions, choices=list(choices.keys()), checked_data_sets=checked_data_sets, check=EMOJIS.get("CHECK", ""), shift=1, indent=0, margin=2, check_color=colors.foreground["default"], check_on_switch=colors.foreground["default"], background_color=colors.foreground["default"], background_on_switch=colors.foreground["default"], word_color=colors.foreground["default"], word_on_switch=colors.bright(colors.foreground["cyan"]), ) data_sets = [] while not data_sets: subprocess.run(["clear"]) if heading: print_heading(heading, fg="bright_yellow") print_message(prompt, wrap=True) result = ds_prompt.launch() if not result: print_error("\nYou must select at least one data set!") pause(message="Press any key to continue...") continue data_sets = [DATA_SET_FROM_NAME_MAP[sel] for sel in result] return data_sets
def prompt_user_run_task(self): task_description = [ "This task identifies all games that fulfill the two requirements below:\n", "1. All data sets have been scraped", "2. Data was successfully combined (does not need to be error free)\n", "For all games that meet these requirements, the data listed below will be added to ", "the database:\n", "1. Individual player batting stats", "2. Individual player pitching stats", "3. PitchFX data for all pitches thrown", ] subprocess.run(["clear"]) for line in task_description: print_message(line, fg="bright_yellow") return yes_no_prompt("\nWould you like to run this task?", wrap=False)
def launch(self): while True: subprocess.run(["clear"]) if self.heading: print_heading(self.heading, fg=self.heading_color) result = super().launch() if not result: continue try: return date_parser.parse(result) except ValueError: error = f'\nError: "{result}" could not be parsed as a valid date.' print_heading(error, fg="bright_red") print_message(ERROR_HELP_MESSAGE, fg="bright_red") print_message(EXAMPLES, fg="bright_red") pause(message="Press any key to continue...")
def launch(self): while True: subprocess.run(["clear"]) if self.heading: print_heading(self.heading, fg=self.heading_color) if self.message: print_message(f"{self.message}\n") result = super().launch() if result == DEFAULT_JOB_NAME: return None if JOB_NAME_REGEX.match(result): return result error = ( f"\n'{result}' contains one or more invalid characters. Job name must contain " "only letters, numbers, hyphen and underscore characters.\n") print_error(error, fg="bright_red") pause(message="Press any key to continue...")
def launch_interactive(self, year): if not self.prompt_user_run_task(): return Result.Ok(True) if not year: result = self.select_season_prompt() if result.failure: return Result.Ok() year = result.value self.subscribe_to_events() result = self.add_to_db.execute(year) self.spinner.stop() self.unsubscribe_from_events() if result.failure: return result subprocess.run(["clear"]) print_message( f"Added PitchFX data for {len(self.game_ids)} games to database!") pause(message="\nPress any key to continue...") return Result.Ok(True)
def import_scraped_data_complete(self): self.update_menu_heading("Complete!", heading_color="bright_green") success = "Successfully imported all scraped data from local files" print_message(success, fg="bright_yellow", bold=True) pause(message="\nPress any key to continue...")
def display(self, heading_color=None, text_color=None): if self.heading: print_heading(self.heading, fg=heading_color) for s in self.text: print_message(s, fg=text_color, wrap=self.wrap)
def display_pitch_metrics(self, metrics): heading = f"Avg. Time Between Pitches for {len(self.game_ids)} MLB Games" table = self.construct_stats_table(metrics) print_heading(heading, fg="bright_yellow") print_message(table, wrap=False, fg="bright_cyan")
def print_prompt(self): prompt = f'\n{" " * self.indent}{self.prompt}\n' print_message(prompt, bold=self.confirm_only)