mirror of
https://github.com/mwisnowski/mtg_python_deckbuilder.git
synced 2025-12-17 08:00:13 +01:00
feat!: auto-setup/tagging; direct builder + rerun prompt; fix(type-summary, .txt dup); refactor(export filenames); ci(DockerHub+GH releases); docs(minimal Windows guide, release notes template)
This commit is contained in:
parent
07605990a1
commit
cb710d37ed
12 changed files with 307 additions and 386 deletions
118
code/main.py
118
code/main.py
|
|
@ -1,25 +1,22 @@
|
|||
"""Command-line interface for the MTG Python Deckbuilder application.
|
||||
"""Command-line entrypoint for the MTG Python Deckbuilder.
|
||||
|
||||
This module provides the main menu and user interaction functionality for the
|
||||
MTG Python Deckbuilder. It handles menu display, user input processing, and
|
||||
routing to different application features like setup, deck building, card info
|
||||
lookup and CSV file tagging.
|
||||
Launches directly into the interactive deck builder. On first run (or if the
|
||||
card database is missing), it automatically performs initial setup and tagging.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
# Standard library imports
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import NoReturn, Optional
|
||||
|
||||
# Third-party imports
|
||||
import inquirer.prompt
|
||||
from typing import NoReturn
|
||||
|
||||
# Local imports
|
||||
from deck_builder import DeckBuilder
|
||||
from file_setup import setup
|
||||
from file_setup.setup import initial_setup
|
||||
from tagging import tagger
|
||||
import logging_util
|
||||
import os
|
||||
from settings import CSV_DIRECTORY
|
||||
|
||||
# Create logger for this module
|
||||
logger = logging_util.logging.getLogger(__name__)
|
||||
|
|
@ -27,94 +24,45 @@ logger.setLevel(logging_util.LOG_LEVEL)
|
|||
logger.addHandler(logging_util.file_handler)
|
||||
logger.addHandler(logging_util.stream_handler)
|
||||
|
||||
# Menu constants
|
||||
MENU_SETUP = 'Setup'
|
||||
MAIN_TAG = 'Tag CSV Files'
|
||||
MENU_BUILD_DECK = 'Build a Deck'
|
||||
MENU_QUIT = 'Quit'
|
||||
|
||||
MENU_CHOICES = [MENU_SETUP, MAIN_TAG, MENU_BUILD_DECK, MENU_QUIT]
|
||||
|
||||
builder = DeckBuilder()
|
||||
def get_menu_choice() -> Optional[str]:
|
||||
"""Display the main menu and get user choice.
|
||||
|
||||
Presents a menu of options to the user using inquirer and returns their selection.
|
||||
Handles potential errors from inquirer gracefully.
|
||||
|
||||
Returns:
|
||||
Optional[str]: The selected menu option or None if cancelled/error occurs
|
||||
|
||||
Example:
|
||||
>>> choice = get_menu_choice()
|
||||
>>> if choice == MENU_SETUP:
|
||||
... setup.setup()
|
||||
"""
|
||||
question = [
|
||||
inquirer.List('menu',
|
||||
choices=MENU_CHOICES,
|
||||
carousel=True)
|
||||
]
|
||||
try:
|
||||
answer = inquirer.prompt(question)
|
||||
return answer['menu'] if answer else None
|
||||
except (KeyError, TypeError) as e:
|
||||
logger.error(f"Error getting menu choice: {e}")
|
||||
return None
|
||||
|
||||
def run_menu() -> NoReturn:
|
||||
"""Main menu loop with improved error handling and logger.
|
||||
"""Launch directly into the deck builder after ensuring data files exist.
|
||||
|
||||
Provides the main application loop that displays the menu and handles user selections.
|
||||
Creates required directories, processes menu choices, and handles errors gracefully.
|
||||
Never returns normally - exits via sys.exit().
|
||||
|
||||
Returns:
|
||||
NoReturn: Function never returns normally
|
||||
|
||||
Raises:
|
||||
SystemExit: When user selects Quit option
|
||||
|
||||
Example:
|
||||
>>> run_menu()
|
||||
What would you like to do?
|
||||
1. Setup
|
||||
2. Build a Deck
|
||||
3. Get Card Info
|
||||
4. Tag CSV Files
|
||||
5. Quit
|
||||
Creates required directories, ensures card CSVs are present (running setup
|
||||
and tagging if needed), then starts the full deck build flow. Exits when done.
|
||||
"""
|
||||
logger.info("Starting MTG Python Deckbuilder")
|
||||
Path('csv_files').mkdir(parents=True, exist_ok=True)
|
||||
Path('deck_files').mkdir(parents=True, exist_ok=True)
|
||||
Path('logs').mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Ensure required CSVs exist and are tagged before proceeding
|
||||
try:
|
||||
cards_path = os.path.join(CSV_DIRECTORY, 'cards.csv')
|
||||
if not os.path.exists(cards_path):
|
||||
logger.info("cards.csv not found. Running initial setup and tagging...")
|
||||
initial_setup()
|
||||
tagger.run_tagging()
|
||||
logger.info("Initial setup and tagging completed.")
|
||||
except Exception as e:
|
||||
logger.error(f"Failed ensuring CSVs are ready: {e}")
|
||||
while True:
|
||||
try:
|
||||
print('What would you like to do?')
|
||||
choice = get_menu_choice()
|
||||
|
||||
if choice is None:
|
||||
logger.info("Menu operation cancelled")
|
||||
continue
|
||||
|
||||
logger.info(f"User selected: {choice}")
|
||||
|
||||
match choice:
|
||||
case 'Setup':
|
||||
setup()
|
||||
case 'Tag CSV Files':
|
||||
tagger.run_tagging()
|
||||
case 'Build a Deck':
|
||||
builder.build_deck_full()
|
||||
case 'Quit':
|
||||
logger.info("Exiting application")
|
||||
sys.exit(0)
|
||||
case _:
|
||||
logger.warning(f"Invalid menu choice: {choice}")
|
||||
|
||||
# Fresh builder instance for each deck to avoid state carryover
|
||||
DeckBuilder().build_deck_full()
|
||||
except Exception as e:
|
||||
logger.error(f"Unexpected error in main menu: {e}")
|
||||
logger.error(f"Unexpected error in deck builder: {e}")
|
||||
|
||||
# Prompt to build another deck or quit
|
||||
try:
|
||||
resp = input("\nBuild another deck? (y/n): ").strip().lower()
|
||||
except KeyboardInterrupt:
|
||||
resp = 'n'
|
||||
print("")
|
||||
if resp not in ('y', 'yes'):
|
||||
logger.info("Exiting application")
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
run_menu()
|
||||
Loading…
Add table
Add a link
Reference in a new issue