mtg_python_deckbuilder/README.md

303 lines
No EOL
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 🃏 MTG Python Deckbuilder
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
[![Docker](https://img.shields.io/badge/docker-supported-blue.svg)](https://www.docker.com/)
A web-first Commander/EDH deckbuilder with a shared core for CLI, headless, and Docker workflows. It builds curated decks, enforces bracket policies, understands owned cards, and ships a modern FastAPI + HTMX UI.
- **Web UI priority**: All homepage actions map to the sections below.
- **Shared logic**: Web, CLI, and headless runs use the same builder engine and exports.
- **Deterministic outputs**: Random modes respect seeds, include/exclude lists, and bracket rules.
- **Data-aware UX**: Owned library, themes, commanders, diagnostics, and logs live side-by-side.
---
## Table of contents
- [Quick start](#quick-start)
- [Homepage guide](#homepage-guide)
- [Build a Deck](#build-a-deck)
- [Run a JSON Config](#run-a-json-config)
- [Initial Setup](#initial-setup)
- [Owned Library](#owned-library)
- [Browse Commanders](#browse-commanders)
- [Browse Themes](#browse-themes)
- [Finished Decks](#finished-decks)
- [Random Build](#random-build)
- [Diagnostics](#diagnostics)
- [View Logs](#view-logs)
- [CLI & headless flows](#cli--headless-flows)
- [Data, exports, and volumes](#data-exports-and-volumes)
- [Environment variables](#environment-variables)
- [Project layout](#project-layout)
- [Development setup](#development-setup)
- [Troubleshooting](#troubleshooting)
- [Contributing](#contributing)
- [License & attribution](#license--attribution)
- [Further reading](#further-reading)
---
## Quick start
Pick the path that fits your setup. All commands target Windows PowerShell.
### Option 1 — Docker Compose (recommended web experience)
```powershell
docker compose up --build --no-deps -d web
```
The Web UI starts on http://localhost:8080. First boot seeds data, refreshes decks, and tags cards automatically (see env defaults in `docker-compose.yml`). Use `docker compose stop web` / `docker compose start web` to pause or resume.
### Option 2 — Docker Hub image
```powershell
docker run --rm -p 8080:8080 `
-v "${PWD}/deck_files:/app/deck_files" `
-v "${PWD}/logs:/app/logs" `
-v "${PWD}/csv_files:/app/csv_files" `
-v "${PWD}/config:/app/config" `
-v "${PWD}/owned_cards:/app/owned_cards" `
mwisnowski/mtg-python-deckbuilder:latest
```
Brings up the same web UI using the prebuilt image. All volumes persist on the host.
### Option 3 — Run from source
```powershell
python -m venv .venv
.\venv\Scripts\Activate.ps1
pip install -r requirements.txt
uvicorn code.web.app:app --host 127.0.0.1 --port 8080
```
CLI entry point: `python code/main.py`. Headless convenience runner: `python code/headless_runner.py --config config/deck.json`.
For deeper Docker notes (including headless runs, impersonating CLI via compose, and maintenance scripts) see [`DOCKER.md`](DOCKER.md).
---
## Homepage guide
Every tile on the homepage connects to a workflow. Use these sections as your tour.
### Build a Deck
Start here for interactive deck creation.
- Pick commander, themes (primary/secondary/tertiary), bracket, and optional deck name in the unified modal.
- Locks, Replace, Compare, and Permalinks live in Step 5.
- Exports (CSV, TXT, compliance JSON, summary JSON) land in `deck_files/` and reuse your chosen deck name when set.
- `ALLOW_MUST_HAVES=1` (default) enables include/exclude enforcement.
- `WEB_AUTO_ENFORCE=1` re-runs bracket enforcement automatically after each build.
### Run a JSON Config
Execute saved configs without manual input.
- Place JSON configs under `config/` (see `config/deck.json` for a template).
- Launch via homepage button or by running the container with `APP_MODE=cli` and `DECK_MODE=headless`.
- Respect include/exclude, owned, and theme overrides defined in the config file or env vars.
### Initial Setup
Refresh data and caches when formats shift.
- Runs card downloads, CSV regeneration, tagging, and commander catalog rebuilds.
- Controlled by `SHOW_SETUP=1` (on by default in compose).
- Force a rebuild manually:
```powershell
docker compose run --rm --entrypoint bash web -lc "python -m code.file_setup.setup"
```
- Rebuild only the commander catalog:
```powershell
docker compose run --rm --entrypoint bash web -lc "python -m code.scripts.refresh_commander_catalog"
```
### Owned Library
Keep track of cards you own.
- Upload `.txt` or `.csv` lists; the app enriches and deduplicates entries.
- Owned-only and Prefer-owned build modes live in the New Deck modal.
- `owned_cards/` is persisted via volume mounting (`OWNED_CARDS_DIR=/app/owned_cards`).
- Enable virtualization for large libraries with `WEB_VIRTUALIZE=1`.
### Browse Commanders
Explore the curated commander catalog.
- Powered by `csv_files/commander_cards.csv`.
- Toggle the tile with `SHOW_COMMANDERS=1`.
- Refresh via Initial Setup or the commander catalog script above.
- MDFC merges and compatibility snapshots are handled automatically; use `--compat-snapshot` on the refresh script to emit an unmerged snapshot.
### Browse Themes
Investigate theme synergies and diagnostics.
- `ENABLE_THEMES=1` keeps the tile visible (default).
- Extra tooling (`/themes/metrics`, uncapped synergies, editorial quality) is gated by `WEB_THEME_PICKER_DIAGNOSTICS=1`.
- Rebuild the merged catalog as needed:
```powershell
docker compose run --rm --entrypoint bash web -lc "python -m code.scripts.build_theme_catalog"
```
- Advanced editorial knobs (`EDITORIAL_*`, `SPLASH_ADAPTIVE`, etc.) live in `.env.example` and are summarized in the env table below.
### Finished Decks
Review, compare, and export previous builds.
- Reads from the `deck_files/` volume.
- Compare view can diff two builds, copy summaries, and download text lists.
- Locks, replace history, and compliance metadata persist per deck.
### Random Build
Spin up surprise decks with deterministic fallbacks.
- Enable backend endpoints with `RANDOM_MODES=1` and the UI tile with `RANDOM_UI=1`.
- Fine-tune with `RANDOM_MAX_ATTEMPTS`, `RANDOM_TIMEOUT_MS`, `RANDOM_PRIMARY_THEME`, `RANDOM_SEED`, and `RANDOM_AUTO_FILL`.
- Random flows honor include/exclude lists, owned filters, and bracket enforcement.
### Diagnostics
Peek at health & performance.
- Enabled via `SHOW_DIAGNOSTICS=1`.
- `/diagnostics` summarizes system status, feature flags, and theme metrics.
- `/healthz` offers a lightweight probe (`{status, version, uptime_seconds}`).
- Press `v` inside virtualized lists (when `WEB_VIRTUALIZE=1`) to view grid diagnostics.
### View Logs
Tail and download logs without leaving the browser.
- Enabled via `SHOW_LOGS=1`.
- `/logs` shows recent entries, filtering, and copy-to-clipboard.
- Raw files live under the mounted `logs/` directory.
- `/status/logs?tail=N` returns JSON payloads for automation.
---
## CLI & headless flows
The CLI and headless runners share the builder core.
- Launch menu-driven CLI: `python code/main.py`.
- Run headless (non-interactive) builds: `python code/headless_runner.py --config config/deck.json`.
- In Docker, set `APP_MODE=cli` (and optionally `DECK_MODE=headless`) to switch the container entrypoint to the CLI.
- Config precedence is CLI prompts > environment variables > JSON config > defaults.
---
## Data, exports, and volumes
| Host path | Container path | Purpose |
| --- | --- | --- |
| `deck_files/` | `/app/deck_files` | CSV/TXT exports, compliance JSON, summary JSON |
| `logs/` | `/app/logs` | Application logs, taxonomy snapshots |
| `csv_files/` | `/app/csv_files` | Card datasets, commander catalog, tagging metadata |
| `config/` | `/app/config` | JSON configs, bracket policies, themes, card lists |
| `owned_cards/` | `/app/owned_cards` | Uploaded owned-card libraries |
Exports follow a stable naming scheme and include a `.summary.json` sidecar containing deck metadata, resolved themes, and lock history.
---
## Environment variables
Most defaults are defined in `docker-compose.yml` and documented in `.env.example`. Highlights:
### Core modes & networking
| Variable | Default | Purpose |
| --- | --- | --- |
| `APP_MODE` | `web` | Switch between Web UI (`web`) and CLI (`cli`). |
| `DECK_MODE` | _(unset)_ | `headless` auto-runs the builder in CLI mode. |
| `DECK_CONFIG` | `/app/config/deck.json` | Points the headless runner at a config file or folder. |
| `HOST` / `PORT` / `WORKERS` | `0.0.0.0` / `8080` / `1` | Uvicorn settings for the web server. |
### Homepage visibility & UX
| Variable | Default | Purpose |
| --- | --- | --- |
| `SHOW_SETUP` | `1` | Show the Initial Setup tile. |
| `SHOW_LOGS` | `1` | Enable the logs viewer tile and endpoints. |
| `SHOW_DIAGNOSTICS` | `1` | Unlock diagnostics views and overlays. |
| `SHOW_COMMANDERS` | `1` | Enable the commander browser. |
| `ENABLE_THEMES` | `1` | Keep the theme browser and selector active. |
| `WEB_VIRTUALIZE` | `1` | Opt into virtualized lists for large datasets. |
| `ALLOW_MUST_HAVES` | `1` | Enforce include/exclude (must-have) lists. |
| `THEME` | `dark` | Default UI theme (`system`, `light`, or `dark`). |
### Random build tuning
| Variable | Default | Purpose |
| --- | --- | --- |
| `RANDOM_MODES` | _(unset)_ | Expose random build endpoints. |
| `RANDOM_UI` | _(unset)_ | Show the Random Build homepage tile. |
| `RANDOM_MAX_ATTEMPTS` | `5` | Retry budget when constraints are tight. |
| `RANDOM_TIMEOUT_MS` | `5000` | Per-attempt timeout in milliseconds. |
| `RANDOM_PRIMARY_THEME` / `RANDOM_SECONDARY_THEME` / `RANDOM_TERTIARY_THEME` | _(blank)_ | Override selected themes. |
| `RANDOM_SEED` | _(blank)_ | Deterministic seed for reproducible builds. |
| `RANDOM_AUTO_FILL` | `1` | Allow auto-fill of missing theme slots. |
### Automation & performance
| Variable | Default | Purpose |
| --- | --- | --- |
| `WEB_AUTO_SETUP` | `1` | Auto-run setup when artifacts are missing or stale. |
| `WEB_AUTO_REFRESH_DAYS` | `7` | Refresh `cards.csv` if older than N days. |
| `WEB_TAG_PARALLEL` | `1` | Enable parallel tagging workers. |
| `WEB_TAG_WORKERS` | `4` | Worker count for tagging (compose default). |
| `WEB_AUTO_ENFORCE` | `0` | Auto-apply bracket enforcement after builds. |
| `WEB_THEME_PICKER_DIAGNOSTICS` | `1` | Enable theme diagnostics endpoints. |
### Paths & overrides
| Variable | Default | Purpose |
| --- | --- | --- |
| `CSV_FILES_DIR` | `/app/csv_files` | Alternate dataset location (useful for tests). |
| `DECK_EXPORTS` | `/app/deck_files` | Override where exports land. |
| `OWNED_CARDS_DIR` / `CARD_LIBRARY_DIR` | `/app/owned_cards` | Override owned library path. |
| `CARD_INDEX_EXTRA_CSV` | _(blank)_ | Inject extra CSV data into the card index. |
Refer to `.env.example` for advanced editorial, taxonomy, and experimentation knobs (`EDITORIAL_*`, `SPLASH_ADAPTIVE`, `WEB_THEME_FILTER_PREWARM`, etc.). Document any newly introduced variables in the README, DOCKER guide, compose files, and `.env.example`.
---
## Project layout
```
code/ FastAPI app, deckbuilding engine, CLI, scripts, and tests
├─ web/ Web UI (FastAPI + Jinja2 + HTMX)
├─ deck_builder/ Core builder logic and services
├─ tagging/ Tag pipelines and utilities
├─ locks/ Card locking utilities
├─ scripts/ Maintenance and editorial tools
├─ tests/ Pytest suite (web, CLI, random, tagging)
config/ JSON configs, bracket policies, themes, card lists
csv_files/ Card datasets, commander catalog, theme outputs
owned_cards/ User-supplied owned lists
logs/ Application logs and taxonomy snapshots
deck_files/ Generated deck exports (CSV/TXT/JSON)
```
---
## Development setup
1. Create and activate the virtual environment:
```powershell
python -m venv .venv
.\venv\Scripts\Activate.ps1
```
2. Install dependencies:
```powershell
pip install -r requirements.txt -r requirements-dev.txt
```
3. Run the web app locally:
```powershell
uvicorn code.web.app:app --host 127.0.0.1 --port 8080
```
4. Run tests (prefer targeted files—no wildcards):
```powershell
C:/Users/Matt/mtg_python/mtg_python_deckbuilder/.venv/Scripts/python.exe -m pytest -q code/tests/test_random_determinism.py code/tests/test_permalinks_and_locks.py
```
Use `tasks.json` entries such as `pytest-fast-random` or `pytest-fast-locks` for quick feedback.
5. Linting and type checks follow `pyproject.toml` / `mypy.ini` defaults. Keep changes minimal and well-typed.
When adding features, favor the web UI first, keep public builder APIs stable, and update documentation (CHANGELOG → RELEASE_NOTES_TEMPLATE → DOCKER → README) in that order.
---
## Troubleshooting
- **Blank page after start**: Visit `/healthz`, check `/logs`, ensure `SHOW_LOGS=1`, and inspect host `logs/` for stack traces.
- **Stale data**: Run Initial Setup or delete `csv_files/.tagging_complete.json` to force reseeding.
- **Owned-only build fails**: Confirm owned files were uploaded correctly and that `owned_cards/` is mounted.
- **Random build stalls**: Lower `RANDOM_MAX_ATTEMPTS`, increase `RANDOM_TIMEOUT_MS`, and verify selected themes exist via `/themes/`.
- **Commander list outdated**: Rerun the commander refresh script or Initial Setup.
---
## Contributing
Pull requests are welcome—follow the conventional commit style, keep diffs focused, add or update tests when behavior changes, and document new env vars or workflows. Review `CONTRIBUTING_EDITORIAL.md` for editorial tooling guidance.
---
## License & attribution
Licensed under the [MIT License](LICENSE). Card data and imagery are provided by [Scryfall](https://scryfall.com); please respect their [API terms](https://scryfall.com/docs/api).
---
## Further reading
- [Web UI deep dive](docs/web_ui_deep_dive.md) advanced Stage 5 tooling, multi-copy packages, virtualization tips, and diagnostics overlays.
- [Theme catalog advanced guide](docs/theme_catalog_advanced.md) API endpoints, governance policies, editorial tooling, and validation scripts.
- [Headless & CLI guide](docs/headless_cli_guide.md) automation entry points, environment overrides, and argument walkthroughs.
- [Commander catalog handbook](docs/commander_catalog.md) required columns, refresh workflow, and staging toggles.
- [Random theme exclusions reference](docs/random_theme_exclusions.md) curation guidance for curated pools.
- [Theme taxonomy rationale](docs/theme_taxonomy_rationale.md) roadmap and philosophy behind theme governance.