Add collection update runbook with multiple scenarios
This commit is contained in:
125
README.md
125
README.md
@@ -225,6 +225,131 @@ EOF
|
|||||||
python scripts/analyze_decks.py --collection collection_hydrated/deck.json --deck-dir decks/
|
python scripts/analyze_decks.py --collection collection_hydrated/deck.json --deck-dir decks/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Runbook: Update Your Collection
|
||||||
|
|
||||||
|
### Scenario 1: Add New Cards (Single File)
|
||||||
|
|
||||||
|
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'
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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"
|
||||||
|
|
||||||
|
# Re-hydrate that file
|
||||||
|
python hydrate.py hydrate "collection/Box1 2026-01-30.txt" -o collection_hydrated/ -c card_cache.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scenario 3: Merge Multiple Collection Files
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scenario 4: Re-hydrate Entire Collection
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scenario 5: Update After Set Release
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 3. Verify new cards are present
|
||||||
|
python -c "
|
||||||
|
import json
|
||||||
|
cards = json.load(open('collection_hydrated/deck.json'))
|
||||||
|
print(f'Total unique cards: {len(cards)}')
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Collection File Format
|
||||||
|
|
||||||
|
```
|
||||||
|
# Comments start with #
|
||||||
|
# Format: <count> <Card Name> (<Set Code>) <Collector Number>
|
||||||
|
|
||||||
|
1 Sol Ring (CMA) 1
|
||||||
|
3 Birds of Paradise
|
||||||
|
1 Eternal Witness (EMA) 183
|
||||||
|
|
||||||
|
# Set code and collector number are optional but recommended
|
||||||
|
# They help Scryfall find the exact printing
|
||||||
|
```
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
**Card not found:**
|
||||||
|
```
|
||||||
|
Error fetching 'Some Card Name': HTTP 404
|
||||||
|
```
|
||||||
|
→ Check spelling, or try without set code. Use the exact name from Scryfall.
|
||||||
|
|
||||||
|
**Duplicate cards:**
|
||||||
|
If the same card appears multiple times in your file, they're stored separately. Dedupe first:
|
||||||
|
```bash
|
||||||
|
# Combine duplicates
|
||||||
|
python -c "
|
||||||
|
from collections import Counter
|
||||||
|
cards = Counter()
|
||||||
|
with open('collection/my_cards.txt') as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if line and not line.startswith('#'):
|
||||||
|
parts = line.split(None, 1)
|
||||||
|
if parts:
|
||||||
|
count = int(parts[0]) if parts[0].isdigit() else 1
|
||||||
|
name = parts[1] if len(parts) > 1 else parts[0]
|
||||||
|
cards[name.split('(')[0].strip()] += count
|
||||||
|
for name, count in sorted(cards.items()):
|
||||||
|
print(f'{count} {name}')
|
||||||
|
" > collection/deduped.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
**Slow hydration:**
|
||||||
|
- First run fetches all cards (~100ms each)
|
||||||
|
- Subsequent runs use cache (instant)
|
||||||
|
- 866 unique cards ≈ 87 seconds first run
|
||||||
|
|
||||||
## Collection Stats
|
## Collection Stats
|
||||||
|
|
||||||
- **Total cards:** 1209
|
- **Total cards:** 1209
|
||||||
|
|||||||
125
docs/templates/README.template.md
vendored
125
docs/templates/README.template.md
vendored
@@ -220,6 +220,131 @@ EOF
|
|||||||
python scripts/analyze_decks.py --collection collection_hydrated/deck.json --deck-dir decks/
|
python scripts/analyze_decks.py --collection collection_hydrated/deck.json --deck-dir decks/
|
||||||
```
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Runbook: Update Your Collection
|
||||||
|
|
||||||
|
### Scenario 1: Add New Cards (Single File)
|
||||||
|
|
||||||
|
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'
|
||||||
|
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
|
||||||
|
```
|
||||||
|
|
||||||
|
### 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"
|
||||||
|
|
||||||
|
# Re-hydrate that file
|
||||||
|
python hydrate.py hydrate "collection/Box1 2026-01-30.txt" -o collection_hydrated/ -c card_cache.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scenario 3: Merge Multiple Collection Files
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scenario 4: Re-hydrate Entire Collection
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scenario 5: Update After Set Release
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
# 3. Verify new cards are present
|
||||||
|
python -c "
|
||||||
|
import json
|
||||||
|
cards = json.load(open('collection_hydrated/deck.json'))
|
||||||
|
print(f'Total unique cards: {len(cards)}')
|
||||||
|
"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Collection File Format
|
||||||
|
|
||||||
|
```
|
||||||
|
# Comments start with #
|
||||||
|
# Format: <count> <Card Name> (<Set Code>) <Collector Number>
|
||||||
|
|
||||||
|
1 Sol Ring (CMA) 1
|
||||||
|
3 Birds of Paradise
|
||||||
|
1 Eternal Witness (EMA) 183
|
||||||
|
|
||||||
|
# Set code and collector number are optional but recommended
|
||||||
|
# They help Scryfall find the exact printing
|
||||||
|
```
|
||||||
|
|
||||||
|
### Troubleshooting
|
||||||
|
|
||||||
|
**Card not found:**
|
||||||
|
```
|
||||||
|
Error fetching 'Some Card Name': HTTP 404
|
||||||
|
```
|
||||||
|
→ Check spelling, or try without set code. Use the exact name from Scryfall.
|
||||||
|
|
||||||
|
**Duplicate cards:**
|
||||||
|
If the same card appears multiple times in your file, they're stored separately. Dedupe first:
|
||||||
|
```bash
|
||||||
|
# Combine duplicates
|
||||||
|
python -c "
|
||||||
|
from collections import Counter
|
||||||
|
cards = Counter()
|
||||||
|
with open('collection/my_cards.txt') as f:
|
||||||
|
for line in f:
|
||||||
|
line = line.strip()
|
||||||
|
if line and not line.startswith('#'):
|
||||||
|
parts = line.split(None, 1)
|
||||||
|
if parts:
|
||||||
|
count = int(parts[0]) if parts[0].isdigit() else 1
|
||||||
|
name = parts[1] if len(parts) > 1 else parts[0]
|
||||||
|
cards[name.split('(')[0].strip()] += count
|
||||||
|
for name, count in sorted(cards.items()):
|
||||||
|
print(f'{count} {name}')
|
||||||
|
" > collection/deduped.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
**Slow hydration:**
|
||||||
|
- First run fetches all cards (~100ms each)
|
||||||
|
- Subsequent runs use cache (instant)
|
||||||
|
- 866 unique cards ≈ 87 seconds first run
|
||||||
|
|
||||||
## Collection Stats
|
## Collection Stats
|
||||||
|
|
||||||
{{COLLECTION_STATS}}
|
{{COLLECTION_STATS}}
|
||||||
|
|||||||
Reference in New Issue
Block a user