Refactor project structure and update documentation
- Migrated data files to 'data/collection/' and 'data/decks/'. - Moved 'card_cache.json' to 'cache/'. - Reorganized 'collection_hydrated/' and 'deck_analysis.json' into 'output/'. - Updated 'hydrate.py' and script defaults to match the new paths. - Updated 'README.template.md' and 'AGENTS.template.md' templates. - Regenerated 'README.md' and 'AGENTS.md'.
This commit is contained in:
41
docs/templates/AGENTS.template.md
vendored
41
docs/templates/AGENTS.template.md
vendored
@@ -27,21 +27,24 @@ python scripts/analyze_decks.py --help
|
||||
|
||||
```
|
||||
├── hydrate.py # Main CLI - fetches card data from Scryfall
|
||||
├── card_cache.json # Local cache of Scryfall card data
|
||||
├── deck_analysis.json # Analysis output
|
||||
├── collection/ # Raw decklist text files
|
||||
├── collection_hydrated/ # Enriched card data by type
|
||||
│ ├── deck.json # All cards combined
|
||||
│ ├── commander.json
|
||||
│ ├── creatures.json
|
||||
│ ├── instants.json
|
||||
│ ├── sorceries.json
|
||||
│ ├── artifacts.json
|
||||
│ ├── enchantments.json
|
||||
│ ├── lands.json
|
||||
│ └── planeswalkers.json
|
||||
├── decks/ # Deck definitions (JSON)
|
||||
│ └── <deck_name>.json # name, commander, colors, archetype, cards
|
||||
├── cache/
|
||||
│ └── card_cache.json # Local cache of Scryfall card data
|
||||
├── output/
|
||||
│ ├── deck_analysis.json # Analysis output
|
||||
│ └── hydrated/ # Enriched card data by type
|
||||
│ ├── deck.json # All cards combined
|
||||
│ ├── commander.json
|
||||
│ ├── creatures.json
|
||||
│ ├── instants.json
|
||||
│ ├── sorceries.json
|
||||
│ ├── artifacts.json
|
||||
│ ├── enchantments.json
|
||||
│ ├── lands.json
|
||||
│ └── planeswalkers.json
|
||||
├── data/
|
||||
│ ├── collection/ # Raw decklist text files
|
||||
│ └── decks/ # Deck definitions (JSON)
|
||||
│ └── <deck_name>.json # name, commander, colors, archetype, cards
|
||||
├── scripts/
|
||||
│ ├── analyze_decks.py # Find upgrade options for decks
|
||||
│ ├── find_synergies.py # Search for synergistic cards
|
||||
@@ -53,7 +56,7 @@ python scripts/analyze_decks.py --help
|
||||
|
||||
## Data Formats
|
||||
|
||||
### Deck JSON (`decks/*.json`)
|
||||
### Deck JSON (`data/decks/*.json`)
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -68,7 +71,7 @@ python scripts/analyze_decks.py --help
|
||||
}
|
||||
```
|
||||
|
||||
### Card Data (`collection_hydrated/*.json`)
|
||||
### Card Data (`output/hydrated/*.json`)
|
||||
|
||||
Array of card objects with Scryfall fields:
|
||||
- `name`, `mana_cost`, `cmc`, `colors`, `color_identity`
|
||||
@@ -79,7 +82,7 @@ Array of card objects with Scryfall fields:
|
||||
|
||||
### Adding a New Deck
|
||||
|
||||
1. Create `decks/<name>.json` with required fields
|
||||
1. Create `data/decks/<name>.json` with required fields
|
||||
2. Run `python scripts/update_docs.py` to regenerate documentation
|
||||
|
||||
### Adding a New Script
|
||||
@@ -97,4 +100,4 @@ Array of card objects with Scryfall fields:
|
||||
|
||||
## Current Decks
|
||||
|
||||
{{DECK_TABLE}}
|
||||
{{DECK_TABLE}}
|
||||
98
docs/templates/README.template.md
vendored
98
docs/templates/README.template.md
vendored
@@ -22,7 +22,7 @@ No dependencies required - pure Python 3 standard library.
|
||||
Fetch card data from Scryfall for a decklist:
|
||||
|
||||
```bash
|
||||
python hydrate.py hydrate collection/decklist.txt -o collection_hydrated/ -c card_cache.json
|
||||
python hydrate.py hydrate data/collection/decklist.txt -o output/hydrated/ -c cache/card_cache.json
|
||||
```
|
||||
|
||||
### Create a New Deck
|
||||
@@ -36,7 +36,7 @@ python hydrate.py new my_deck
|
||||
Find upgrade options from your collection:
|
||||
|
||||
```bash
|
||||
python scripts/analyze_decks.py --collection collection_hydrated/deck.json --deck-dir decks/
|
||||
python scripts/analyze_decks.py --collection output/hydrated/deck.json --deck-dir data/decks/
|
||||
```
|
||||
|
||||
### Find Synergies
|
||||
@@ -45,19 +45,19 @@ Search for cards by keywords, colors, and type:
|
||||
|
||||
```bash
|
||||
# Find landfall cards in Simic colors
|
||||
python scripts/find_synergies.py --collection collection_hydrated/deck.json --colors U G --keywords landfall
|
||||
python scripts/find_synergies.py --collection output/hydrated/deck.json --colors U G --keywords landfall
|
||||
|
||||
# Find Bird creatures in Bant colors
|
||||
python scripts/find_synergies.py --collection collection_hydrated/deck.json --colors U G W --creature-type Bird
|
||||
python scripts/find_synergies.py --collection output/hydrated/deck.json --colors U G W --creature-type Bird
|
||||
|
||||
# Find instants with CMC 2 or less
|
||||
python scripts/find_synergies.py --collection collection_hydrated/deck.json --type instant --cmc-max 2
|
||||
python scripts/find_synergies.py --collection output/hydrated/deck.json --type instant --cmc-max 2
|
||||
```
|
||||
|
||||
### Generate Reports
|
||||
|
||||
```bash
|
||||
python scripts/deck_report.py --collection collection_hydrated/deck.json --decks-dir decks/ --output report.md
|
||||
python scripts/deck_report.py --collection output/hydrated/deck.json --decks-dir data/decks/ --output output/report.md
|
||||
```
|
||||
|
||||
## Decks
|
||||
@@ -68,10 +68,10 @@ python scripts/deck_report.py --collection collection_hydrated/deck.json --decks
|
||||
|
||||
### Quick Reference
|
||||
|
||||
1. **Import** - Place text decklists in `collection/`
|
||||
2. **Hydrate** - Run `hydrate.py` to fetch Scryfall data → `collection_hydrated/`
|
||||
1. **Import** - Place text decklists in `data/collection/`
|
||||
2. **Hydrate** - Run `hydrate.py` to fetch Scryfall data → `output/hydrated/`
|
||||
3. **Explore** - Find synergies and commanders in your collection
|
||||
4. **Define** - Create deck JSON files in `decks/`
|
||||
4. **Define** - Create deck JSON files in `data/decks/`
|
||||
5. **Analyze** - Run `analyze_decks.py` to find upgrade options
|
||||
6. **Report** - Use `deck_report.py` for markdown summaries
|
||||
|
||||
@@ -81,7 +81,7 @@ python scripts/deck_report.py --collection collection_hydrated/deck.json --decks
|
||||
|
||||
### Step 1: Import Your Collection
|
||||
|
||||
Create a text file in `collection/` with your cards (one per line):
|
||||
Create a text file in `data/collection/` with your cards (one per line):
|
||||
|
||||
```
|
||||
1 Sol Ring (CMA) 1
|
||||
@@ -98,13 +98,13 @@ The set code and collector number are optional but help with accuracy.
|
||||
Fetch card data from Scryfall:
|
||||
|
||||
```bash
|
||||
python hydrate.py hydrate collection/my_cards.txt -o collection_hydrated/ -c card_cache.json
|
||||
python hydrate.py hydrate data/collection/my_cards.txt -o output/hydrated/ -c cache/card_cache.json
|
||||
```
|
||||
|
||||
This creates:
|
||||
- `collection_hydrated/deck.json` - All cards with full data
|
||||
- `collection_hydrated/creatures.json` - Creatures only
|
||||
- `collection_hydrated/instants.json`, `sorceries.json`, etc.
|
||||
- `output/hydrated/deck.json` - All cards with full data
|
||||
- `output/hydrated/creatures.json` - Creatures only
|
||||
- `output/hydrated/instants.json`, `sorceries.json`, etc.
|
||||
|
||||
### Step 3: Explore Your Collection
|
||||
|
||||
@@ -113,7 +113,7 @@ This creates:
|
||||
python -c "
|
||||
import json
|
||||
from collections import Counter
|
||||
cards = json.load(open('collection_hydrated/deck.json'))
|
||||
cards = json.load(open('output/hydrated/deck.json'))
|
||||
colors = Counter(c for card in cards for c in card.get('color_identity', []))
|
||||
for c, n in colors.most_common(): print(f'{c}: {n}')
|
||||
"
|
||||
@@ -121,29 +121,29 @@ for c, n in colors.most_common(): print(f'{c}: {n}')
|
||||
|
||||
**Find creature types you own:**
|
||||
```bash
|
||||
python scripts/find_synergies.py --collection collection_hydrated/deck.json --creature-type Elf
|
||||
python scripts/find_synergies.py --collection collection_hydrated/deck.json --creature-type Elemental
|
||||
python scripts/find_synergies.py --collection output/hydrated/deck.json --creature-type Elf
|
||||
python scripts/find_synergies.py --collection output/hydrated/deck.json --creature-type Elemental
|
||||
```
|
||||
|
||||
**Find cards by keyword/mechanic:**
|
||||
```bash
|
||||
# Find all landfall cards
|
||||
python scripts/find_synergies.py --collection collection_hydrated/deck.json --keywords landfall
|
||||
python scripts/find_synergies.py --collection output/hydrated/deck.json --keywords landfall
|
||||
|
||||
# Find lifegain synergies
|
||||
python scripts/find_synergies.py --collection collection_hydrated/deck.json --keywords "gain life"
|
||||
python scripts/find_synergies.py --collection output/hydrated/deck.json --keywords "gain life"
|
||||
|
||||
# Find -1/-1 counter cards
|
||||
python scripts/find_synergies.py --collection collection_hydrated/deck.json --keywords "-1/-1 counter"
|
||||
python scripts/find_synergies.py --collection output/hydrated/deck.json --keywords "-1/-1 counter"
|
||||
```
|
||||
|
||||
**Find cards by color identity:**
|
||||
```bash
|
||||
# Simic (UG) cards
|
||||
python scripts/find_synergies.py --collection collection_hydrated/deck.json --colors U G
|
||||
python scripts/find_synergies.py --collection output/hydrated/deck.json --colors U G
|
||||
|
||||
# Esper (WUB) instants
|
||||
python scripts/find_synergies.py --collection collection_hydrated/deck.json --colors W U B --type instant
|
||||
python scripts/find_synergies.py --collection output/hydrated/deck.json --colors W U B --type instant
|
||||
```
|
||||
|
||||
### Step 4: Choose a Commander
|
||||
@@ -155,7 +155,7 @@ Based on your collection strengths, pick a commander that matches:
|
||||
|
||||
### Step 5: Create the Deck File
|
||||
|
||||
Create `decks/<deck_name>.json`:
|
||||
Create `data/decks/<deck_name>.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -176,7 +176,7 @@ Create `decks/<deck_name>.json`:
|
||||
Find cards in your collection that fit your deck:
|
||||
|
||||
```bash
|
||||
python scripts/analyze_decks.py --collection collection_hydrated/deck.json --deck-dir decks/
|
||||
python scripts/analyze_decks.py --collection output/hydrated/deck.json --deck-dir data/decks/
|
||||
```
|
||||
|
||||
This compares your deck against your collection and suggests:
|
||||
@@ -187,7 +187,7 @@ This compares your deck against your collection and suggests:
|
||||
### Step 7: Generate a Report
|
||||
|
||||
```bash
|
||||
python scripts/deck_report.py --collection collection_hydrated/deck.json --decks-dir decks/ --output report.md
|
||||
python scripts/deck_report.py --collection output/hydrated/deck.json --decks-dir data/decks/ --output output/report.md
|
||||
```
|
||||
|
||||
---
|
||||
@@ -196,17 +196,17 @@ python scripts/deck_report.py --collection collection_hydrated/deck.json --decks
|
||||
|
||||
```bash
|
||||
# 1. Add your collection
|
||||
echo "1 Ashling, Rekindled // Ashling, Rimebound (ECL) 124" >> collection/my_cards.txt
|
||||
echo "1 Ashling, Rekindled // Ashling, Rimebound (ECL) 124" >> data/collection/my_cards.txt
|
||||
|
||||
# 2. Hydrate
|
||||
python hydrate.py hydrate collection/my_cards.txt -o collection_hydrated/ -c card_cache.json
|
||||
python hydrate.py hydrate data/collection/my_cards.txt -o output/hydrated/ -c cache/card_cache.json
|
||||
|
||||
# 3. Find red instants/sorceries (spellslinger support)
|
||||
python scripts/find_synergies.py --collection collection_hydrated/deck.json --colors R --type instant
|
||||
python scripts/find_synergies.py --collection collection_hydrated/deck.json --colors R --type sorcery
|
||||
python scripts/find_synergies.py --collection output/hydrated/deck.json --colors R --type instant
|
||||
python scripts/find_synergies.py --collection output/hydrated/deck.json --colors R --type sorcery
|
||||
|
||||
# 4. Create deck file
|
||||
cat > decks/ashling.json << 'EOF'
|
||||
cat > data/decks/ashling.json << 'EOF'
|
||||
{
|
||||
"name": "Ashling Spellslinger",
|
||||
"commander": "Ashling, Rekindled // Ashling, Rimebound",
|
||||
@@ -217,7 +217,7 @@ cat > decks/ashling.json << 'EOF'
|
||||
EOF
|
||||
|
||||
# 5. Analyze and find synergies
|
||||
python scripts/analyze_decks.py --collection collection_hydrated/deck.json --deck-dir decks/
|
||||
python scripts/analyze_decks.py --collection output/hydrated/deck.json --deck-dir data/decks/
|
||||
```
|
||||
|
||||
---
|
||||
@@ -230,24 +230,24 @@ If you opened new packs and want to add cards:
|
||||
|
||||
```bash
|
||||
# 1. Create a new file with the new cards
|
||||
cat > collection/new_cards_2026-02-20.txt << 'EOF'
|
||||
cat > data/collection/new_cards_2026-02-20.txt << 'EOF'
|
||||
1 Bre of Clan Stoutarm (ECL) 8
|
||||
3 Mulldrifter (ECC) 67
|
||||
1 Sol Ring (ECC) 57
|
||||
EOF
|
||||
|
||||
# 2. Hydrate the new file (merges into existing cache)
|
||||
python hydrate.py hydrate collection/new_cards_2026-02-20.txt -o collection_hydrated/ -c card_cache.json
|
||||
python hydrate.py hydrate data/collection/new_cards_2026-02-20.txt -o output/hydrated/ -c cache/card_cache.json
|
||||
```
|
||||
|
||||
### Scenario 2: Add Cards to Existing File
|
||||
|
||||
```bash
|
||||
# Append to existing collection file
|
||||
echo "1 The Reaper, King No More (ECC) 4" >> "collection/Box1 2026-01-30.txt"
|
||||
echo "1 The Reaper, King No More (ECC) 4" >> "data/collection/Box1 2026-01-30.txt"
|
||||
|
||||
# Re-hydrate that file
|
||||
python hydrate.py hydrate "collection/Box1 2026-01-30.txt" -o collection_hydrated/ -c card_cache.json
|
||||
python hydrate.py hydrate "data/collection/Box1 2026-01-30.txt" -o output/hydrated/ -c cache/card_cache.json
|
||||
```
|
||||
|
||||
### Scenario 3: Merge Multiple Collection Files
|
||||
@@ -256,12 +256,12 @@ If you have multiple files to combine:
|
||||
|
||||
```bash
|
||||
# Hydrate each file separately (cache persists)
|
||||
python hydrate.py hydrate collection/Box1.txt -o collection_hydrated/ -c card_cache.json
|
||||
python hydrate.py hydrate collection/Box2.txt -o collection_hydrated/ -c card_cache.json
|
||||
python hydrate.py hydrate data/collection/Box1.txt -o output/hydrated/ -c cache/card_cache.json
|
||||
python hydrate.py hydrate data/collection/Box2.txt -o output/hydrated/ -c cache/card_cache.json
|
||||
|
||||
# Note: Each run overwrites deck.json. To merge, combine files first:
|
||||
cat collection/Box1.txt collection/Box2.txt > collection/combined.txt
|
||||
python hydrate.py hydrate collection/combined.txt -o collection_hydrated/ -c card_cache.json
|
||||
cat data/collection/Box1.txt data/collection/Box2.txt > data/collection/combined.txt
|
||||
python hydrate.py hydrate data/collection/combined.txt -o output/hydrated/ -c cache/card_cache.json
|
||||
```
|
||||
|
||||
### Scenario 4: Re-hydrate Entire Collection
|
||||
@@ -270,11 +270,11 @@ If cache is corrupted or you want fresh data:
|
||||
|
||||
```bash
|
||||
# Option A: Keep cache, just re-run
|
||||
python hydrate.py hydrate collection/combined.txt -o collection_hydrated/ -c card_cache.json
|
||||
python hydrate.py hydrate data/collection/combined.txt -o output/hydrated/ -c cache/card_cache.json
|
||||
|
||||
# Option B: Clear cache and fetch fresh (slow, ~100ms per unique card)
|
||||
rm card_cache.json
|
||||
python hydrate.py hydrate collection/combined.txt -o collection_hydrated/ -c card_cache.json
|
||||
rm cache/card_cache.json
|
||||
python hydrate.py hydrate data/collection/combined.txt -o output/hydrated/ -c cache/card_cache.json
|
||||
```
|
||||
|
||||
### Scenario 5: Update After Set Release
|
||||
@@ -283,16 +283,16 @@ When a new set releases and you want to add those cards:
|
||||
|
||||
```bash
|
||||
# 1. Add new set cards to collection file
|
||||
echo "# Lorwyn Eclipsed - 2026-01-23" >> collection/my_collection.txt
|
||||
cat collection/new_ecl_cards.txt >> collection/my_collection.txt
|
||||
echo "# Lorwyn Eclipsed - 2026-01-23" >> data/collection/my_collection.txt
|
||||
cat data/collection/new_ecl_cards.txt >> data/collection/my_collection.txt
|
||||
|
||||
# 2. Hydrate (cache speeds up existing cards, fetches new ones)
|
||||
python hydrate.py hydrate collection/my_collection.txt -o collection_hydrated/ -c card_cache.json
|
||||
python hydrate.py hydrate data/collection/my_collection.txt -o output/hydrated/ -c cache/card_cache.json
|
||||
|
||||
# 3. Verify new cards are present
|
||||
python -c "
|
||||
import json
|
||||
cards = json.load(open('collection_hydrated/deck.json'))
|
||||
cards = json.load(open('output/hydrated/deck.json'))
|
||||
print(f'Total unique cards: {len(cards)}')
|
||||
"
|
||||
```
|
||||
@@ -326,7 +326,7 @@ If the same card appears multiple times in your file, they're stored separately.
|
||||
python -c "
|
||||
from collections import Counter
|
||||
cards = Counter()
|
||||
with open('collection/my_cards.txt') as f:
|
||||
with open('data/collection/my_cards.txt') as f:
|
||||
for line in f:
|
||||
line = line.strip()
|
||||
if line and not line.startswith('#'):
|
||||
@@ -337,7 +337,7 @@ with open('collection/my_cards.txt') as f:
|
||||
cards[name.split('(')[0].strip()] += count
|
||||
for name, count in sorted(cards.items()):
|
||||
print(f'{count} {name}')
|
||||
" > collection/deduped.txt
|
||||
" > data/collection/deduped.txt
|
||||
```
|
||||
|
||||
**Slow hydration:**
|
||||
@@ -351,4 +351,4 @@ for name, count in sorted(cards.items()):
|
||||
|
||||
---
|
||||
|
||||
*This file is auto-generated. Edit `docs/templates/README.template.md` instead.*
|
||||
*This file is auto-generated. Edit `docs/templates/README.template.md` instead.*
|
||||
Reference in New Issue
Block a user