mtg_python_deckbuilder/README.md

220 lines
19 KiB
Markdown
Raw Normal View History

2025-08-21 10:50:22 -07:00
<EFBFBD><EFBFBD># <<EFBFBD><EFBFBD><EFBFBD> MTG Python Deckbuilder
2025-08-21 10:50:22 -07:00
[![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 fast, menu-driven deckbuilder for MTG Commander/EDH with both CLI and Web UI. Supports interactive and headless runs, CSV/TXT exports, owned-card libraries, and Docker.
## =<3D>9<EFBFBD> Features
- Web UI and CLI, powered by the same builder
- Commander search with smart theme tagging (primary/secondary/tertiary)
- Power bracket selection and ideal count prompts
- CSV and TXT exports with stable filenames
- Headless mode (non-interactive) and a headless submenu in the main menu
- Config precedence: CLI > env > JSON > defaults
## (' Highlights
- Smart tagging and suggestions for commander + themes, with AND/OR combine modes
- Exports CSV and TXT decklists to `deck_files/`
- Owned-cards mode: point to one or more `.txt`/`.csv` files in `owned_cards/` and choose "Use only owned cards?"
- If you opt out, final CSV marks owned cards with an `Owned` column
- Interactive menu with a headless submenu
- Works locally or in Docker (Windows PowerShell friendly)
- Card images and data via Scryfall (attribution shown in the Web UI)
## <> Quick start
### Docker Hub (PowerShell)
```powershell
docker run -it --rm `
-v "${PWD}/deck_files:/app/deck_files" `
-v "${PWD}/logs:/app/logs" `
-v "${PWD}/csv_files:/app/csv_files" `
-v "${PWD}/owned_cards:/app/owned_cards" `
-v "${PWD}/config:/app/config" `
mwisnowski/mtg-python-deckbuilder:latest
2025-08-21 10:57:33 -07:00
```
### From source
```powershell
2025-08-21 10:50:22 -07:00
pip install -r requirements.txt
python code/main.py
```
### From this repo with Docker Compose (PowerShell)
```powershell
docker compose build
docker compose run --rm mtg-deckbuilder
```
## <<EFBFBD><10> Web UI
Run the browser-based UI backed by the same deckbuilding engine.
### From source
```powershell
pip install -r requirements.txt
uvicorn code.web.app:app --host 127.0.0.1 --port 8080
```
Open http://127.0.0.1:8080
### Docker Compose (PowerShell)
```powershell
docker compose build web
docker compose up --no-deps web
```
Then open http://localhost:8080
Notes:
- Exports/logs/configs use the same folders and will appear under your mounted volumes (see compose file).
- The footer includes Scryfall attribution per their guidelines.
## ><3E><16> Headless mode (no prompts)
- Auto-headless: set `DECK_MODE=headless`
- Example (PowerShell):
```powershell
docker compose run --rm -e DECK_MODE=headless mtg-deckbuilder
```
- Use a JSON config: mount `./config` to `/app/config` and set `DECK_CONFIG=/app/config/deck.json`
- Example (PowerShell):
```powershell
docker compose run --rm `
-e DECK_MODE=headless `
-e DECK_CONFIG=/app/config/deck.json `
mtg-deckbuilder
```
- Override via env vars (subset): `DECK_COMMANDER`, `DECK_PRIMARY_CHOICE`, `DECK_SECONDARY_CHOICE`, `DECK_TERTIARY_CHOICE`, `DECK_ADD_LANDS`, `DECK_FETCH_COUNT`, `DECK_BRACKET_LEVEL`
- Precedence: CLI > env > JSON > defaults
Headless submenu notes:
- If one JSON exists in `config/`, it auto-runs it
- If multiple exist, they re listed as "Commander - Theme1, Theme2, Theme3"; `deck.json` shows as "Default"
- CSV/TXT are exported as usual; JSON run-config is exported only in interactive runs
### Run locally (no Docker)
```powershell
# Show resolved settings (no run)
python code/headless_runner.py --config config/deck.json --dry-run
# Run with a specific config file
python code/headless_runner.py --config config/deck.json
# Point to a folder; if exactly one config exists, it's auto-used
python code/headless_runner.py --config config
# Override via CLI
python code/headless_runner.py --commander "Pantlaza, Sun-Favored" --primary-choice 2 --secondary-choice 0 --add-lands true --fetch-count 3
```
### CLI flags
- --config <path> Path to JSON config file or a folder to discover configs (uses DECK_CONFIG by default)
- --commander <name> Commander name to search and select
- --primary-choice <n> Primary theme index
- --secondary-choice <n|none> Secondary theme index or omit with "none"
- --tertiary-choice <n|none> Tertiary theme index or omit with "none"
- --add-lands <bool> Include land building steps (true/false)
- --fetch-count <n> Requested number of fetch lands
- --dual-count <n> Requested number of dual lands (optional; not exported)
- --triple-count <n> Requested number of triple lands (optional; not exported)
- --utility-count <n> Requested number of utility lands (optional; not exported)
- --add-creatures <bool> Add creatures
- --add-non-creature-spells <bool> Add non-creature spells orchestrator
- --add-ramp <bool> Add ramp (when not using orchestrator)
- --add-removal <bool> Add removal (when not using orchestrator)
- --add-wipes <bool> Add board wipes (when not using orchestrator)
- --add-card-advantage <bool> Add card draw (when not using orchestrator)
- --add-protection <bool> Add protection (when not using orchestrator)
- --bracket-level <1-5> Power bracket selection (or use DECK_BRACKET_LEVEL)
- --dry-run Print resolved config and exit
Booleans accept: 1/0, true/false, yes/no, on/off.
### JSON export in headless
- By default, headless runs do not export a JSON run-config to avoid duplicates.
- Opt-in with:
```powershell
$env:HEADLESS_EXPORT_JSON = "1"
python code/headless_runner.py --config config/deck.json
```
- Tip: when opting in, prefer using `--config` instead of a `DECK_CONFIG` file path to avoid creating both a stem-based JSON and a second explicit-path JSON.
Example JSON (`config/deck.json`):
```json
{
"commander": "Pantlaza",
"bracket_level": 3,
"primary_choice": 2,
"secondary_choice": 2,
"tertiary_choice": 2,
"tag_mode": "OR", // OR or AND; Web UI default is OR
"add_lands": true,
"fetch_count": 3,
"ideal_counts": { "ramp": 10, "lands": 36, "basic_lands": 16, "creatures": 28, "removal": 8, "wipes": 3, "card_advantage": 8, "protection": 3 }
}
2025-08-21 10:50:22 -07:00
```
Notes: headless honors `ideal_counts` (leave prompts blank to accept). Only `fetch_count` is tracked/exported for lands.
## ><3E><><EFBFBD> Theme combine mode (AND/OR)
- OR (default): Recommend cards that match any selected themes, prioritizing overlap.
- AND: Prioritize multi-theme intersections. For creatures, an AND pre-pass first picks "all selected themes" creatures up to a cap, then fills by weighted overlap.
UI tips:
- Step 2 includes AND/OR radios with a tooltip explaining trade-offs.
- In staged build view, "Creatures: All-Theme" shows which selected themes each card hits.
## =<3D>y<EFBFBD><0F> Usage (interactive)
1) Start the app (Docker or from source)
2) Pick Build a New Deck
3) Search/confirm commander
4) Pick primary/secondary/tertiary themes (or stop at primary); choose AND/OR combine mode
5) Choose power bracket and review ideal counts
6) Deck builds; CSV/TXT export to `deck_files/`
## <00>&<0F> Environment variables (common)
- DECK_MODE=headless
- DECK_CONFIG=/app/config/deck.json
- DECK_COMMANDER, DECK_PRIMARY_CHOICE, DECK_SECONDARY_CHOICE, DECK_TERTIARY_CHOICE
- DECK_ADD_LANDS, DECK_FETCH_COUNT
- DECK_ADD_CREATURES, DECK_ADD_NON_CREATURE_SPELLS, DECK_ADD_RAMP, DECK_ADD_REMOVAL, DECK_ADD_WIPES, DECK_ADD_CARD_ADVANTAGE, DECK_ADD_PROTECTION
- DECK_BRACKET_LEVEL
Optional name-based tag overrides (mapped to indices for the chosen commander):
- DECK_PRIMARY_TAG, DECK_SECONDARY_TAG, DECK_TERTIARY_TAG
Combine mode in headless:
- JSON: set `"tag_mode": "AND" | "OR"`
- Env var: `DECK_TAG_MODE=AND|OR` (if configured in your environment)
## =<3D><><EFBFBD> Folders
- `deck_files/`  CSV/TXT exports
- `csv_files/`  card data
- `logs/`  logs
- `config/`  JSON configs (optional)
- `owned_cards/`  your owned cards lists (`.txt`/`.csv`); used for owned-only builds and Owned flagging
## ><3E><><EFBFBD> Troubleshooting
- Use `docker compose run --rm` (not `up`) for interactive sessions
- Ensure volumes are mounted so files persist (`deck_files`, `logs`, `csv_files`)
- For headless with config, mount `./config:/app/config` and set `DECK_CONFIG`
- Card data refresh: if `csv_files/cards.csv` is missing or older than 7 days, the app refreshes data and re-tags automatically. A `.tagging_complete.json` file in `csv_files/` indicates tagging completion.
## =<3D><><EFBFBD> Releases
- Release notes are maintained in `RELEASE_NOTES_TEMPLATE.md`. Automated workflows read from this file to populate Docker Hub and GitHub releases.
## ><3E><><EFBFBD> Owned cards library
- Place `.txt` or `.csv` lists in `owned_cards/` (one card name per line for `.txt`; any `.csv` with a `name` column works).
- After commander selection, you ll be prompted: "Use only owned cards?"
- Yes: deck builds from owned cards only; if fewer than 100 cards, it stays incomplete and prints a note.
- No: the build uses the full pool, but the final CSV marks owned cards with an `Owned` column.
- If an owned-only build is incomplete, a recommendations file is exported: `deck_files/[stem]_recommendations.csv` and `.txt`. The app prints: "Recommended but unowned cards in deck_files/[stem]_recommendations.csv".
## =<3D><><EFBFBD> License & help
- License: MIT (see `LICENSE`)
- Issues/Requests: GitHub Issues/Discussions
- Docker details: see `DOCKER.md`