From eea3a6a659abbc45ff298f506d5f7dc6186136ec Mon Sep 17 00:00:00 2001 From: Tuan-Dat Tran Date: Thu, 26 Feb 2026 14:51:48 +0100 Subject: [PATCH] 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'. --- AGENTS.md | 41 +- README.md | 98 +- card_cache.json => cache/card_cache.json | 0 collection.txt | 866 ------------------ collection/LWC Display 2026-09-19.txt | 74 -- .../collection}/Box1 2026-01-30.txt | 50 +- data/collection/LWC Display 2026-09-19.txt | 158 ++++ {decks => data/decks}/choco.json | 0 {decks => data/decks}/hazel.json | 0 {decks => data/decks}/palamecia.json | 0 {decks => data/decks}/yshtola.json | 0 docs/templates/AGENTS.template.md | 41 +- docs/templates/README.template.md | 98 +- hydrate.py | 6 +- .../deck_analysis.json | 0 .../hydrated}/artifacts.json | 0 .../hydrated}/commander.json | 0 .../hydrated}/creatures.json | 0 .../hydrated}/deck.json | 0 .../hydrated}/enchantments.json | 0 .../hydrated}/instants.json | 0 .../hydrated}/lands.json | 0 .../hydrated}/planeswalkers.json | 0 .../hydrated}/sorceries.json | 0 scripts/analyze_decks.py | 4 +- scripts/deck_report.py | 8 +- scripts/find_synergies.py | 6 +- scripts/update_docs.py | 4 +- 28 files changed, 328 insertions(+), 1126 deletions(-) rename card_cache.json => cache/card_cache.json (100%) delete mode 100644 collection.txt delete mode 100644 collection/LWC Display 2026-09-19.txt rename {collection => data/collection}/Box1 2026-01-30.txt (96%) create mode 100644 data/collection/LWC Display 2026-09-19.txt rename {decks => data/decks}/choco.json (100%) rename {decks => data/decks}/hazel.json (100%) rename {decks => data/decks}/palamecia.json (100%) rename {decks => data/decks}/yshtola.json (100%) rename deck_analysis.json => output/deck_analysis.json (100%) rename {collection_hydrated => output/hydrated}/artifacts.json (100%) rename {collection_hydrated => output/hydrated}/commander.json (100%) rename {collection_hydrated => output/hydrated}/creatures.json (100%) rename {collection_hydrated => output/hydrated}/deck.json (100%) rename {collection_hydrated => output/hydrated}/enchantments.json (100%) rename {collection_hydrated => output/hydrated}/instants.json (100%) rename {collection_hydrated => output/hydrated}/lands.json (100%) rename {collection_hydrated => output/hydrated}/planeswalkers.json (100%) rename {collection_hydrated => output/hydrated}/sorceries.json (100%) diff --git a/AGENTS.md b/AGENTS.md index afcc48c..f218dcf 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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) -│ └── .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) +│ └── .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/.json` with required fields +1. Create `data/decks/.json` with required fields 2. Run `python scripts/update_docs.py` to regenerate documentation ### Adding a New Script @@ -102,4 +105,4 @@ Array of card objects with Scryfall fields: | Choco | UGW | Choco, Seeker of Paradise | Bird Tribal Landfall | | Hazel | BG | Hazel of the Rootbloom | Golgari Aristocrats | | Palamecia | UR | The Emperor of Palamecia // The Lord Master of Hell | Izzet Self-Mill Storm | -| Yshtola | UBW | Y'shtola, Night's Blessed | Esper Stax Drain | +| Yshtola | UBW | Y'shtola, Night's Blessed | Esper Stax Drain | \ No newline at end of file diff --git a/README.md b/README.md index dd70740..71e8858 100644 --- a/README.md +++ b/README.md @@ -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 @@ -73,10 +73,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 @@ -86,7 +86,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 @@ -103,13 +103,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 @@ -118,7 +118,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}') " @@ -126,29 +126,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 @@ -160,7 +160,7 @@ Based on your collection strengths, pick a commander that matches: ### Step 5: Create the Deck File -Create `decks/.json`: +Create `data/decks/.json`: ```json { @@ -181,7 +181,7 @@ Create `decks/.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: @@ -192,7 +192,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 ``` --- @@ -201,17 +201,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", @@ -222,7 +222,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/ ``` --- @@ -235,24 +235,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 @@ -261,12 +261,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 @@ -275,11 +275,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 @@ -288,16 +288,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)}') " ``` @@ -331,7 +331,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('#'): @@ -342,7 +342,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:** @@ -365,4 +365,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.* \ No newline at end of file diff --git a/card_cache.json b/cache/card_cache.json similarity index 100% rename from card_cache.json rename to cache/card_cache.json diff --git a/collection.txt b/collection.txt deleted file mode 100644 index 2af1b0c..0000000 --- a/collection.txt +++ /dev/null @@ -1,866 +0,0 @@ -1x Giant Koi -1x Grappling Kraken -1x Stratosoarer -1x Doc Ock, Sinister Scientist -1x Hraesvelgr of the First Brood -1x Summon: Shiva -1x Pestered Wellguard -1x Wanderwine Distracter -1x Alphinaud Leveilleur -1x Kukemssa Serpent -1x Surveillance Monitor -1x Enduring Curiosity -1x Kulrath Mystic -1x Glamermite -1x Nebelgast Herald -1x Quistis Trepe -1x Erudite Wizard -1x The Mechanist, Aerial Artisan -1x Jill, Shiva's Dominant // Shiva, Warden of Ice -1x Gogo, Master of Mimicry -1x Fear of Isolation -1x Il Mheg Pixie -1x Agent of Kotis -1x Hypnotic Sprite // Mesmeric Glare -1x Tiger-Seal -1x Kithkeeper -1x Salt Road Packbeast -1x Beatrix, Loyal General -1x Sun-Dappled Celebrant -1x Summon: Good King Mog XII -1x Master Piandao -1x Kalonian Twingrove -1x Thancred Waters -1x Minwu, White Mage -1x Friendly Ghost -1x Daily Bugle Reporters -1x Unsettling Twins -1x Kyoshi Warriors -1x Summon: Primal Garuda -1x Rosa, Resolute White Mage -1x Dragonback Lancer -4x Weapons Vendor -1x Gallant Fowlknight -1x Shore Lurker -1x Anafenza, Unyielding Lineage -1x Tempest Hawk -1x Summon: Choco/Mog -1x Arachne, Psionic Weaver -1x Dazzling Angel -1x Flight-Deck Coordinator -1x Earth Kingdom Jailer -1x Aerith Gainsborough -1x Alisaie Leveilleur -1x Glider Kids -3x Gaelicat -2x Reluctant Dounguard -1x Meanders Guide -1x Tributary Vaulter -1x Sunpearl Kirin -1x Bearer of Glory -1x Flash Thompson, Spider-Fan -1x Tataru Taru -1x Jeong Jeong's Deserters -1x Hildibrand Manderville // Gentleman's Rise -2x Ambrosia Whiteheart -4x Coeurl -1x Timid Shieldbearer -1x Encumbered Reejerey -1x Veteran Survivor -1x Mardu Devotee -1x Momo, Friendly Flier -1x Curious Farm Animals -2x Valkyrie Aerial Unit -2x Ice Flan -3x Rook Turret -2x Venser, Shaper Savant -2x Qiqirn Merchant -8x Dragoon's Wyvern -3x Sahagin -3x Scorpion Sentinel -2x G'raha Tia -4x Cloudbound Moogle -2x Delivery Moogle -2x Compassionate Healer -3x Adelbert Steiner -6x Dwarven Castle Guard -2x Magitek Infantry -1x Zodiark, Umbral God -1x Feral Deathgorger // Dusk Sight -1x Basilica Stalker -1x Spectral Snatcher -1x Canyon Crawler -1x Perigee Beckoner -1x Venom, Evil Unleashed -1x Stinging Scorpion -1x Blighted Blackthorn -1x Syr Konrad, the Grim -1x Zenos yae Galvus // Shinryu, Transcendent Rival -1x Jecht, Reluctant Guardian // Braska's Final Aeon -1x Dashing Bloodsucker -1x Crypt Feaster -1x Gravblade Heavy -1x Buzzard-Wasp Colony -1x Soul-Shackled Zombie -1x Dawnhand Eulogist -1x Dream Seizer -1x Nightmare Sower -1x Vincent Valentine // Galian Beast -1x Shambling Cie'th -1x Plaguecrafter -1x Archghoul of Thraben -1x Fang, Fearless l'Cie -1x Hog-Monkey -1x Pirate Peddlers -1x Moonglove Extractor -1x Heirloom Auntie -1x Gnarlbark Elm -1x Retched Wretch -1x June, Bounty Hunter -1x Merchant of Many Hats -1x Mai, Scornful Striker -1x Corrupt Court Official -1x Burglar Rat -1x Reno and Rude -1x Demon Wall -1x Unburied Earthcarver -1x Scarblade Scout -1x Boggart Prankster -1x Bile-Vial Boggart -2x Summon: Primal Odin -2x Malboro -2x Beetle-Headed Merchants -4x Namazu Trader -2x Gaius van Baelsar -2x Qutrub Forayer -3x Ahriman -3x Shinra Reinforcements -2x Fire Nation Engineer -2x Wolfbat -3x Al Bhed Salvagers -3x Undercity Dire Rat -5x Hecteyes -1x Kulrath Zealot -1x Gilgamesh, Master-at-Arms -1x Mongoose Lizard -1x Boilerbilges Ripper -1x Razorkin Hordecaller -1x Sandworm -1x Combustion Man -1x Meticulous Artisan -1x Sower of Chaos -1x Wartime Protestors -1x Gogo, Mysterious Mime -1x Flamekin Gildweaver -1x Tersa Lightshatter -1x Vicious Clown -1x Frontline War-Rager -1x Spider-Gwen, Free Spirit -1x Lightning, Security Sergeant -1x Summon: G.F. Cerberus -1x Boar-q-pine -1x Brambleback Brute -1x Brazen Scourge -1x Deserter's Disciple -1x Yuyan Archers -1x Blood Petal Celebrant -1x Axgard Cavalry -1x Shock Brigade -1x Taxi Driver -1x Firebrand Archer -1x Explosive Prodigy -1x Flame-Chain Mauler -2x Hill Gigas -2x Boldwyr Aggressor -2x Barret Wallace -2x Spider-Islanders -2x Fire Nation Raider -2x Mysidian Elder -2x Superior Foes of Spider-Man -2x Queen Brahne -4x Summon: G.F. Ifrit -2x Enraged Flamecaster -2x Sabotender -2x Tiger-Dillo -7x Item Shopkeep -2x Gristle Glutton -3x Blazing Bomb -2x Freya Crescent -1x Wildwood Scourge -1x Diamond Weapon -1x Coliseum Behemoth -1x Slavering Branchsnapper -1x Spider-Rex, Daring Dino -1x Apothecary Stomper -1x Badgermole -1x Safewright Cavalry -1x The Boulder, Ready to Rumble -1x Cackling Prowler -1x Damage Control Crew -1x Festerhide Boar -1x Rainveil Rejuvenator -1x Trystan, Callous Cultivator // Trystan, Penitent Culler -1x Vinebred Brawler -1x Ostrich-Horse -1x Supportive Parents -1x Cryptid Inspector -1x Tireless Tracker -1x Lys Alana Informant -1x Lys Alana Dignitary -1x Town Greeter -1x Sultai Devotee -1x Rebellious Captives -1x Hinterland Logger // Timber Shredder -1x House Cartographer -1x Tunnel Tipster -1x Virulent Emissary -1x Spider-Ham, Peter Porker -1x Cactuar -1x Llanowar Elves -3x Balamb T-Rexaur -2x Summon: Fat Chocobo -2x Vanille, Cheerful l'Cie -6x Gigantoad -2x Crossroads Watcher -2x Walltop Sentries -3x Loporrit Scout -3x Summon: Fenrir -2x Great Forest Druid -2x Goobbue Gardener -2x Kraven's Cats -2x Turtle-Duck -2x Gran Pulse Ochu -1x Reputable Merchant -1x Monastery Messenger -1x G'raha Tia, Scion Reborn -1x Rhino, Barreling Brute -1x Vibrance -1x Huntmaster of the Fells // Ravager of the Fells -1x Uncle Iroh -1x Rydia, Summoner of Mist -1x Stoic Grove-Guide -1x Dai Li Agents -1x Jenova, Ancient Calamity -1x Stalwart Successor -1x Lluwen, Imperfect Naturalist -1x Shadow Urchin -1x Chaos Spewer -1x Black Waltz No. 3 -1x Vial Smasher the Fierce -1x Zuko, Conflicted -1x Omega, Heartless Evolution -1x Guru Pathik -1x Clement, the Worrywort -1x Hermitic Herbalist -1x Platypus-Bear -1x Twinflame Travelers -1x Twinflame Travelers -1x Sanar, Innovative First-Year -2x Shantotto, Tactician Magician -1x Flaring Cinder -1x Ashling, Rekindled // Ashling, Rimebound -2x The Emperor of Palamecia // The Lord Master of Hell -1x Balmor, Battlemage Captain -1x Azula, Cunning Usurper -1x Ultimecia, Time Sorceress // Ultimecia, Omnipotent -1x Messenger Hawk -1x Emet-Selch, Unsundered // Hades, Sorcerer of Eld -1x Locke Cole -1x Suki, Kyoshi Warrior -1x Good-Fortune Unicorn -1x Serah Farron // Crystallized Serah -1x Wary Farmer -1x Garnet, Princess of Alexandria -1x Catharsis -1x Cloud, Planet's Champion -1x Sami, Ship's Engineer -1x Feisty Spikeling -1x Eirdu, Carrier of Dawn // Isilu, Carrier of Twilight -1x Estinien Varlineau -1x Prideful Feastling -1x Ardbert, Warrior of Darkness -1x Merrow Skyswimmer -1x Wraith, Vicious Vigilante -1x Lyse Hext -1x Tidus, Blitzball Star -1x Deepchannel Duelist -1x Urianger Augurelt -2x Gladiolus Amicitia -2x Balthier and Fran -3x Cloud of Darkness -2x Exdeath, Void Warlock // Neo Exdeath, Dimension's End -2x Boggart Cursecrafter -2x Garland, Knight of Cornelia // Chaos, the Endless -2x Ignis Scientia -2x Mischievous Sneakling -2x Voracious Tome-Skimmer -2x Rinoa Heartilly -2x Giott, King of the Dwarves -2x Private Eye -1x Red Herring -1x Abundant Maw -1x Relentless X-ATM092 -1x Rooftop Percher -1x Palladium Myr -1x Changeling Wayfinder -1x Spider-Bot -1x Campus Guide -2x Iron Giant -7x Magic Pot -2x Mechanical Mobster -2x Embermouth Sentinel -2x Chocobo Racetrack -1x The Fire Crystal -1x Chaos Shrine's Black Crystal -1x Cryogen Relic -1x Phoenix Down -1x Coveted Jewel -1x Firdoch Core -1x Puca's Eye -1x Talisman of Dominance -1x Ravenous Amulet -1x Tome of Legends -3x Sol Ring -2x Everflowing Chalice -9x White Auracite -3x Blitzball -4x Instant Ramen -3x World Map -3x Lunatic Pandora -1x Genji Glove -2x Black Mage's Rod -1x Barbed Bloodletter -2x Blue Mage's Cane -1x Dragoon's Lance -1x Ultima Weapon -1x Leyline Axe -1x Butcher's Cleaver -2x Whispersilk Cloak -1x Monk's Fist -1x Cobbled Wings -1x Kyoshi Battle Fan -2x Swiftfoot Boots -1x Spider-Suit -1x Thinking Cap -1x Excalibur II -1x Phantom Train -1x Invasion Submersible -1x Cargo Ship -1x Smuggler's Copter -1x Subway Train -3x Bard's Bow -5x Warrior's Sword -5x Samurai's Katana -4x Red Mage's Rapier -3x Coral Sword -4x Dark Knight's Greatsword -4x Sage's Nouliths -3x Astrologian's Planisphere -3x Paladin's Arms -4x White Mage's Staff -2x Crystal Fragments // Summon: Alexander -2x The Masamune -2x Stalactite Dagger -2x The Prima Vista -3x Magitek Armor -1x Disturbing Mirth -1x Eusocial Engineering -1x Wall Crawl -1x Gilt-Leaf's Embrace -1x Campsite Cuisine -1x Triple Triad -1x Breaching Dragonstorm -1x Connecting the Dots -1x Meathook Massacre II -1x Boggart Mischief -1x Cracked Skull -1x Bastion of Remembrance -1x Eye of Nidhogg -1x Mornsong Aria -1x Corroding Dragonstorm -1x Northern Air Temple -1x Sidequest: Card Collection // Magicked Card -1x Meat Locker // Drowned Diner -1x Spider-Man No More -1x Security Bypass -1x Roiling Dragonstorm -1x Blossombind -1x Noggle the Mind -1x Aquitect's Defenses -1x Watery Grasp -1x Sleep Magic -1x Witness Protection -1x Ringing Strike Mastery -1x Kinbinding -1x Southern Air Temple -1x Clachan Festival -1x Spiral into Solitude -1x Evershrike's Gift -2x Kraven's Last Hunt -2x Prismatic Undercurrents -3x Ride the Shoopuf -2x Sidequest: Play Blitzball // World Champion, Celestial Weapon -2x Liminal Hold -2x Sidequest: Catch a Fish // Cooking Campsite -2x Due Diligence -1x Dragonclaw Strike -1x Trystan's Command -1x Grub's Command -1x Pumpkin Bombardment -1x Lie in Wait -1x Brigid's Command -1x Rydia's Return -1x Bite Down on Crime -1x Earthbending Lesson -2x Reach the Horizon -1x Tend the Sprigs -1x Shattered Wings -1x Scout the City -2x Chocobo Kick -1x Clash of the Eikons -1x Clash of the Eikons -1x Choco-Comet -1x Terminal Velocity -1x Unexpected Request -1x Light Up the Stage -1x Boulder Dash -1x Jet's Brainwashing -1x Killing Wave -1x Bloodline Bidding -1x Evil Reawakened -1x Crux of Fate -2x Circle of Power -1x The Final Days -2x Risky Research -1x Temporal Intervention -1x Extract a Confession -1x Bogslither's Embrace -1x Reanimate -1x Wanderwine Farewell -1x Waterbending Lesson -1x Lingering Souls -1x Cut a Deal -4x Gysahl Greens -4x Commune with Beavers -2x Random Encounter -2x Call the Mountain Chocobo -3x Suplex -2x Impolite Entrance -2x Cinder Strike -3x Venom's Hunger -2x Darkness Descends -2x Poison the Waters -2x Dai Li Indoctrination -4x Resentful Revelation -2x Retrieve the Esper -2x Temporal Cleansing -3x Relm's Sketching -3x Combat Tutorial -2x Boomerang Basics -2x The Crystal's Chosen -3x Aerith Rescue Mission -2x From Father to Son -2x Aang's Journey -1x Auroral Procession -1x Perennation -1x Abandon Attachments -2x Prishe's Wanderings -1x Cycle of Renewal -1x Unforgiving Aim -1x Origin of Metalbending -1x Rocky Rebuke -1x Heritage Reclamation -1x Close Encounter -1x Midnight Tilling -1x Giant Growth -1x Caught Red-Handed -1x Impossible Inferno -1x Judgment Bolt -1x Seize Opportunity -1x Tweeze -1x Laughing Mad -1x Lightning Strike -1x Firebending Lesson -2x Fire Magic -1x Murder -1x Alesha's Legacy -1x Fatal Fissure -2x Vincent's Limit Break -1x Fatal Push -1x Scarblade's Malice -1x Into the Story -2x Sublime Epiphany -1x Unexpected Assistance -1x Uncharted Voyage -1x Glimmerburst -1x Scour for Scrap -1x Swat Away -1x Faebloom Trick -1x Don't Make a Sound -1x It'll Quench Ya! -1x Dreams of Laguna -1x Backslide -1x Accumulate Wisdom -1x Whoosh! -1x Run Away Together -1x Wild Unraveling -1x Get Out -1x Long River's Pull -1x Stolen Uniform -1x Claws Out -1x Moogles' Valor -1x Rally the Monastery -1x Protective Response -1x Razor Rings -1x Keep Out -1x Riverguard's Reflexes -1x Yip Yip! -1x Enter the Avatar State -1x Unwanted Remake -1x Strength of Arms -1x Zuko's Exile -3x Airship Crash -2x Allies at Last -2x Sarkhan's Resolve -3x Blitzball Shot -2x Light of Judgment -2x Haste Magic -2x Cunning Maneuver -4x Thunder Magic -2x Sephiroth's Intervention -3x Fight On! -3x Vayne's Treachery -3x Syncopate -2x Lost Days -2x Eject -3x Ice Magic -2x Octopus Form -3x Magic Damper -6x Fate of the Sun-Cryst -2x Auron's Inspiration -2x Battle Menu -6x Slash of Light -3x You're Not Alone -1x Emeria Angel -1x Summon: Choco/Mog -1x Arcane Denial -1x Emeria Shepherd -1x Abandoned Air Temple -2x Prairie Stream -1x Tangled Islet -3x Reliquary Tower -1x Farseek -1x Gilded Goose -1x Restoration Magic -1x Radiant Grove -1x Tranquil Landscape -1x Suburban Sanctuary -1x Hinterland Harbor -1x Jackdaw Savior -1x Negate -1x Sazh's Chocobo -1x Balamb Garden, SeeD Academy // Balamb Garden, Airborne -2x Birds of Paradise -2x Beastmaster Ascension -1x River Hoopoe -2x Swords to Plowshares -1x Austere Command -1x Bartz and Boko -1x The Goose Mother -1x Beast Within -1x Flurry of Wings -1x Glacial Fortress -1x An Offer You Can't Refuse -1x Cultivate -1x Patchwork Banner -1x Kastral, the Windcrested -1x Restless Anchorage -2x Plains -1x Watcher of the Spheres -1x Murmuration -1x Talisman of Progress -1x Windurst, Federation Center -1x Meditation Pools -1x Demolition Field -1x Adarkar Wastes -1x Empyrean Eagle -1x Forest -1x Seaside Citadel -1x Warden of Evos Isle -2x Exotic Orchard -1x Felidar Retreat -1x Ascend from Avernus -1x Path to Exile -1x Curiosity Crafter -1x Sazh Katzroy -1x Traveling Chocobo -2x Counterspell -1x Jumbo Cactuar -1x Lifecreed Duo -2x Evolving Wilds -2x Path of Ancestry -1x Airborne Aid -1x Sharlayan, Nation of Scholars -1x Brushland -1x Plumecreed Escort -1x Summon: Fat Chocobo -1x Rampant Growth -1x Winged Portent -1x Hermes, Overseer of Elpis -1x Wingmate Roc -1x Sunpetal Grove -1x Herald's Horn -1x Kangee's Lieutenant -1x Dusk // Dawn -1x Nature's Lore -1x Terramorphic Expanse -1x Plains -1x Yavimaya Coast -1x Seaside Haven -1x Forest -1x Gwaihir the Windlord -1x City Pigeon -1x Command Tower -1x Sevinne's Reclamation -1x Kangee, Sky Warden -3x Plains -1x Sidequest: Raise a Chocobo // Black Chocobo -1x Generous Gift -4x Island -1x Canopy Vista -2x Forest -1x Choco, Seeker of Paradise -3x Plains -2x Mountain -1x Mana Geyser -1x Big Score -1x Ovika, Enigma Goliath -1x Summons of Saruman -1x Izzet Signet -1x Seize the Storm -1x Fact or Fiction -2x Ring of the Lucii -1x Elixir of Immortality -1x Drown in Dreams -1x Vivi Ornitier -1x Ultros, Obnoxious Octopus -1x Island -1x Decaying Time Loop -1x Tellah, Great Sage -1x Traumatize -1x Experimental Overload -1x Sulfur Falls -1x Abundant Growth -1x Curator's Ward -2x Curiosity -1x Snort -1x Aetherize -1x Talrand, Sky Summoner -1x Epic Experiment -2x Ur-Golem's Eye -1x Careful Consideration -1x Isengard Unleashed -1x The Rollercrusher Ride -1x Press the Enemy -1x Thousand-Year Storm -1x Fateful Showdown -1x Increasing Confusion -1x Snapcaster Mage -1x Tezzeret's Gambit -1x Command Tower -1x Shivan Reef -1x Zephid's Embrace -1x Arcane Signet -1x Drake Umbra -1x Channeled Force -1x Bond of Insight -1x Consider -1x Baron, Airship Kingdom -1x Mystic Confluence -1x Frostboil Snarl -1x Ether -1x Spellheart Chimera -1x Protective Bubble -1x Path of the Pyromancer -1x Blasphemous Act -2x Firemind Vessel -1x Pirate's Pillage -1x Rise from the Tides -1x Full Throttle -2x Rewind -1x Gandalf's Sanction -2x Hedron Archive -1x Peter Parker's Camera -1x Pinnacle Monk // Mystic Peak -1x Cut Your Losses -2x Mountain -6x Island -4x Mountain -6x Island -4x Mountain -5x Island -1x Garruk, Cursed Huntsman -1x Moldervine Reclamation -1x Chitterspitter -1x Viridescent Bog -1x Gourmand's Talent -1x Moonstone Eulogist -1x Wolfwillow Haven -1x Beledros Witherbloom -1x Ravenous Squirrel -1x Llanowar Wastes -1x Arasta of the Endless Web -1x Command Tower -1x Worthy Cost -1x Swarmyard Massacre -1x Rootcast Apprenticeship -1x Sword of the Squeak -1x Necroblossom Snarl -1x Chatterfang, Squirrel General -1x Chatterstorm -1x Gilded Goose -1x Temple of Malady -1x Golgari Rot Farm -1x Casualties of War -1x Woe Strider -1x Bojuka Bog -1x Haunted Mire -1x Hazel's Brewmaster -1x Deadly Dispute -1x Ogre Slumlord -1x Nested Shambler -1x Oran-Rief, the Vastwood -1x Terramorphic Expanse -1x Prosperous Innkeeper -1x Maelstrom Pulse -1x Jungle Hollow -1x Skullclamp -1x Plumb the Forbidden -1x Saw in Half -1x End-Raze Forerunners -1x Putrefy -1x Squirrel Sovereign -1x Toski, Bearer of Secrets -1x Insatiable Frugivore -1x Poison-Tip Archer -1x Windgrace's Judgment -1x Honored Dreyleader -1x Cache Grab -1x Tear Asunder -1x Tranquil Thicket -1x Skyfisher Spider -1x Shamanic Revelation -1x Zulaport Cutthroat -1x Nadier's Nightblade -1x Chittering Witch -1x Haywire Mite -1x Deep Forest Hermit -1x Idol of Oblivion -1x Tainted Wood -1x Barren Moor -1x Talisman of Resilience -1x Binding the Old Gods -1x Tireless Provisioner -1x Midgar, City of Mako // Reactor Raid -1x Golgari Signet -1x Morbid Opportunist -1x Swarmyard -1x Twilight Mire -1x Arcane Signet -1x Squirrel Nest -1x Maskwood Nexus -1x The Odd Acorn Gang -1x Woodland Cemetery -1x Second Harvest -1x Academy Manufactor -1x Sol Ring -1x Scurry of Squirrels -1x Decree of Pain -1x Bastion of Remembrance -1x Grim Backwoods -1x Hazel of the Rootbloom -5x Forest -4x Swamp -4x Forest -3x Swamp -1x Exotic Orchard -1x Ultima -1x Darkwater Catacombs -1x Void Rend -1x Avatar's Wrath -1x Arcane Sanctum -1x Vindicate -1x Overkill -1x Drowned Catacomb -1x Authority of the Consuls -1x School Daze -1x Cleansing Nova -1x Multiversal Passage -1x Choked Estuary -1x Exsanguinate -1x Cornered by Black Mages -1x Frantic Search -1x Evolving Wilds -1x Lethal Scheme -1x Withering Torment -1x Rite of Replication -1x Underground River -1x Archaeomancer's Map -2x Swamp -1x Vanish from Sight -1x Scavenger Grounds -1x Fetid Heath -1x Reaper's Scythe -1x Brainstorm -1x Urza's Saga -1x Krile Baldesion -1x Swamp -1x Amazing Acrobatics -1x Ash Barrens -1x Riverwalk Technique -1x Dig Through Time -1x Vote Out -1x Syphon Mind -1x Banishing Light -1x Command Beacon -1x Murderous Rider // Swift End -1x Emet-Selch of the Third Seat -1x Sunlit Marsh -1x Dancer's Chakrams -1x Skycloud Expanse -1x Sol Ring -1x Stuck in Summoner's Sanctum -1x Static Snare -1x Fandaniel, Telophoroi Ascian -1x Talisman of Hierarchy -1x Archmage Emeritus -1x Shineshadow Snarl -1x Sunken Hollow -1x Idyllic Beachfront -1x Glacial Fortress -1x Thought Vessel -1x Papalymo Totolymo -1x Path of Ancestry -1x Final Judgment -1x Torrential Gearhulk -1x Propaganda -1x Transpose -1x Snuff Out -1x Dovin's Veto -1x Archmage of Runes -1x Temple of the False God -1x Sunken Ruins -1x Observed Stasis -1x Relic of Legends -1x Contaminated Aquifer -1x Port Town -1x Demolition Field -1x Champions from Beyond -1x Baleful Strix -1x Desolate Mire -1x Isolated Chapel -1x Y'shtola, Night's Blessed -1x Barret, Avalanche Leader -1x Cloud, Midgar Mercenary -1x Wakka, Devoted Guardian -1x Elspeth, Storm Slayer diff --git a/collection/LWC Display 2026-09-19.txt b/collection/LWC Display 2026-09-19.txt deleted file mode 100644 index 29770cf..0000000 --- a/collection/LWC Display 2026-09-19.txt +++ /dev/null @@ -1,74 +0,0 @@ -1 Nameless Inversion (ECL) 113 -1 Lavaleaper (ECL) 318 -1 Burdened Stoneback (ECL) 8 -1 Gathering Stone (ECL) 257 -1 Deepchannel Duelist (ECL) 213 -1 Gangly Stompling (ECL) 226 -1 Merrow Skyswimmer (ECL) 234 -1 Appeal to Eirdu (ECL) 5 -1 Elder Auntie (ECL) 133 -1 Sygg's Command (ECL) 244 -1 Pitiless Fists (ECL) 187 -1 Encumbered Reejerey (ECL) 14 -1 Sear (ECL) 154 -1 Feisty Spikeling (ECL) 223 -1 Enraged Flamecaster (ECL) 135 -1 Bile-Vial Boggart (ECL) 87 -1 Blossombind (ECL) 45 -1 Trystan, Callous Cultivator // Trystan, Penitent Culler (ECL) 199 -1 Gutsplitter Gang (ECL) 106 -1 Glamer Gifter (ECL) 49 -1 Keep Out (ECL) 19 -1 Barbed Bloodletter (ECL) 86 -1 Sun-Dappled Celebrant (ECL) 37 -1 Wanderwine Distracter (ECL) 82 -1 Lluwen, Imperfect Naturalist (ECL) 232 -1 Deceit (ECL) 212 -1 Iron-Shield Elf (ECL) 108 -1 Illusion Spinners (ECL) 55 -1 Kindle the Inner Flame (ECL) 147 -1 Mischievous Sneakling (ECL) 235 -1 Stratosoarer (ECL) 72 -1 Run Away Together (ECL) 67 -1 Shore Lurker (ECL) 34 -2 Reckless Ransacking (ECL) 152 -1 Dawnhand Eulogist (ECL) 99 -1 Evershrike's Gift (ECL) 15 -1 Dawnhand Dissident (ECL) 311 -1 Bark of Doran (ECL) 6 -1 Gnarlbark Elm (ECL) 103 -1 Luminollusk (ECL) 179 -1 Flaring Cinder (ECL) 225 -1 Dose of Dawnglow (ECL) 100 -1 Ashling, Rekindled // Ashling, Rimebound (ECL) 124 -1 Morcant's Eyes (ECL) 185 -1 Wanderwine Farewell (ECL) 83 -1 Pyrrhic Strike (ECL) 30 -1 Chaos Spewer (ECL) 210 -1 Blighted Blackthorn (ECL) 90 -1 Great Forest Druid (ECL) 178 -2 Thoughtweft Charge (ECL) 198 -2 Unexpected Assistance (ECL) 80 -2 Safewright Cavalry (ECL) 191 -3 Bogslither's Embrace (ECL) 94 -3 Riverguard's Reflexes (ECL) 33 -2 Unbury (ECL) 123 -3 Midnight Tilling (ECL) 182 -2 Flamekin Gildweaver (ECL) 140 -2 Stalactite Dagger (ECL) 261 -2 Cinder Strike (ECL) 131 -2 Lys Alana Informant (ECL) 181 -2 Reluctant Dounguard (ECL) 31 -2 Temporal Cleansing (ECL) 78 -1 Loch Mare (ECL) 57 -1 Sygg, Wanderwine Wisdom // Sygg, Wanderbrine Shield (ECL) 76 -1 Moonglove Extractor (ECL) 109 -1 Wildvine Pummeler (ECL) 203 -1 Aquitect's Defenses (ECL) 44 -1 Gallant Fowlknight (ECL) 17 -1 Wary Farmer (ECL) 251 -1 Chitinous Graspling (ECL) 211 -1 Reaping Willow (ECL) 240 -1 Moon-Vigil Adherents (ECL) 184 -1 Dawn-Blessed Pennant (ECL) 254 -1 Unwelcome Sprite (ECL) 81 diff --git a/collection/Box1 2026-01-30.txt b/data/collection/Box1 2026-01-30.txt similarity index 96% rename from collection/Box1 2026-01-30.txt rename to data/collection/Box1 2026-01-30.txt index 3f224d3..6f72ba4 100644 --- a/collection/Box1 2026-01-30.txt +++ b/data/collection/Box1 2026-01-30.txt @@ -23,7 +23,7 @@ 1 Agent of Kotis (TDM) 36 1 Hypnotic Sprite // Mesmeric Glare (FIC) 264 1 Tiger-Seal (TLA) 75 -1 Kithkeeper (ECL) 23 +2 Kithkeeper (ECL) 23 1 Salt Road Packbeast (TDM) 23 1 Beatrix, Loyal General (FIN) 554 2 Sun-Dappled Celebrant (ECL) 37 @@ -102,7 +102,7 @@ 1 Gravblade Heavy (EOE) 102 1 Buzzard-Wasp Colony (TLA) 88 1 Soul-Shackled Zombie (FDN) 70 -3 Dawnhand Eulogist (ECL) 99 +4 Dawnhand Eulogist (ECL) 99 4 Dream Seizer (ECL) 101 1 Nightmare Sower (ECL) 114 1 Vincent Valentine // Galian Beast (FIN) 125 @@ -238,7 +238,7 @@ 1 Huntmaster of the Fells // Ravager of the Fells (INR) 241 1 Uncle Iroh (TLA) 248 1 Rydia, Summoner of Mist (FIN) 239 -2 Stoic Grove-Guide (ECL) 243 +3 Stoic Grove-Guide (ECL) 243 1 Dai Li Agents (TLA) 214 1 Jenova, Ancient Calamity (FIN) 228 1 Stalwart Successor (TDM) 227 @@ -254,7 +254,7 @@ 1 Hermitic Herbalist (TLA) 226 1 Platypus-Bear (TLA) 236 1 Twinflame Travelers (ECL) 345 -1 Twinflame Travelers (ECL) 248 +2 Twinflame Travelers (ECL) 248 1 Sanar, Innovative First-Year (ECL) 241 2 Shantotto, Tactician Magician (FIN) 241 2 Flaring Cinder (ECL) 225 @@ -292,7 +292,7 @@ 2 Boggart Cursecrafter (ECL) 331 2 Garland, Knight of Cornelia // Chaos, the Endless (FIN) 221 2 Ignis Scientia (FIN) 227 -2 Mischievous Sneakling (ECL) 235 +3 Mischievous Sneakling (ECL) 235 2 Voracious Tome-Skimmer (ECL) 250 2 Rinoa Heartilly (FIN) 237 2 Giott, King of the Dwarves (FIN) 223 @@ -366,7 +366,7 @@ 1 Disturbing Mirth (DSK) 212 1 Eusocial Engineering (EOE) 181 1 Wall Crawl (SPM) 121 -5 Gilt-Leaf's Embrace (ECL) 177 +6 Gilt-Leaf's Embrace (ECL) 177 1 Campsite Cuisine (FIC) 464 1 Triple Triad (FIN) 340 1 Breaching Dragonstorm (TDM) 101 @@ -394,7 +394,7 @@ 1 Kinbinding (ECL) 407 *F* 1 Southern Air Temple (TLA) 36 2 Clachan Festival (ECL) 10 -4 Spiral into Solitude (ECL) 36 +5 Spiral into Solitude (ECL) 36 1 Evershrike's Gift (ECL) 15 2 Kraven's Last Hunt (SPM) 105 2 Prismatic Undercurrents (ECL) 189 @@ -503,7 +503,7 @@ 1 Accumulate Wisdom (TLA) 44 1 Whoosh! (SPM) 48 3 Run Away Together (ECL) 67 -4 Wild Unraveling (ECL) 84 +5 Wild Unraveling (ECL) 84 1 Get Out (DSK) 60 1 Long River's Pull (BLB) 58 1 Stolen Uniform (FIN) 75 @@ -870,11 +870,11 @@ 1 Thoughtweft Lieutenant (ECL) 343 1 Rime Chill (ECL) 64 1 Flock Impostor (ECL) 16 -1 Reckless Ransacking (ECL) 152 +2 Reckless Ransacking (ECL) 152 1 Requiting Hex (ECL) 116 1 Bristlebane Battler (ECL) 168 -1 Sting-Slinger (ECL) 161 -1 Surly Farrier (ECL) 196 +2 Sting-Slinger (ECL) 161 +2 Surly Farrier (ECL) 196 1 Gravelgill Scoundrel (ECL) 53 2 Omni-Changeling (ECL) 62 1 Ashling's Command (ECL) 205 @@ -883,7 +883,7 @@ 1 Chomping Changeling (ECL) 172 1 Rhys, the Evermore (ECL) 32 1 Pitiless Fists (ECL) 187 -1 Bark of Doran (ECL) 6 +2 Bark of Doran (ECL) 6 1 Lofty Dreams (ECL) 58 1 Taster of Wares (ECL) 121 1 Tanufel Rimespeaker (ECL) 77 @@ -892,10 +892,10 @@ 2 Dawn-Blessed Pennant (ECL) 254 1 Deepway Navigator (ECL) 214 1 Iron-Shield Elf (ECL) 108 -2 Evolving Wilds (ECL) 264 +3 Evolving Wilds (ECL) 264 2 Giantfall (ECL) 141 2 Rimekin Recluse (ECL) 66 -2 Foraging Wickermaw (ECL) 256 +3 Foraging Wickermaw (ECL) 256 2 Lasting Tarfire (ECL) 149 2 Elder Auntie (ECL) 133 1 Blight Rot (ECL) 89 @@ -908,25 +908,3 @@ 1 Abigale, Eloquent First-Year (ECL) 204 1 Swamp (ECL) 271 1 Pallimud (TMP) 195 -1 Steam Vents (ECL) 267 -1 Champions of the Shoal (ECL) 46 -1 End-Blaze Epiphany (ECL) 134 -1 Dundoolin Weaver (ECL) 175 -1 Boggart Cursecrafter (ECL) 206 -1 Mirrormind Crown (ECL) 258 -1 Celestial Reunion (ECL) 170 -1 Morcant's Loyalist (ECL) 236 -2 Assert Perfection (ECL) 164 -1 Gutsplitter Gang (ECL) 106 -1 Dream Harvest (ECL) 216 -1 Eclipsed Kithkin (ECL) 220 -1 Sizzling Changeling (ECL) 155 -1 Chitinous Graspling (ECL) 211 -1 Wanderbrine Preacher (ECL) 41 -1 Summit Sentinel (ECL) 73 -1 Mistmeadow Council (ECL) 183 -1 Burning Curiosity (ECL) 129 -1 Goliath Daydreamer (ECL) 143 -1 Morcant's Loyalist (ECL) 341 -1 Puca's Eye (ECL) 259 -1 Clachan Festival (ECL) 10 diff --git a/data/collection/LWC Display 2026-09-19.txt b/data/collection/LWC Display 2026-09-19.txt new file mode 100644 index 0000000..560dcdd --- /dev/null +++ b/data/collection/LWC Display 2026-09-19.txt @@ -0,0 +1,158 @@ +1 Steam Vents (ECL) 267 +2 Champions of the Shoal (ECL) 46 +1 End-Blaze Epiphany (ECL) 134 +1 Dundoolin Weaver (ECL) 175 +1 Boggart Cursecrafter (ECL) 206 +1 Mirrormind Crown (ECL) 258 +1 Celestial Reunion (ECL) 170 +1 Morcant's Loyalist (ECL) 236 +3 Assert Perfection (ECL) 164 +1 Dream Harvest (ECL) 216 +1 Eclipsed Kithkin (ECL) 220 +2 Sizzling Changeling (ECL) 155 +3 Wanderbrine Preacher (ECL) 41 +3 Summit Sentinel (ECL) 73 +3 Mistmeadow Council (ECL) 183 +2 Burning Curiosity (ECL) 129 +1 Goliath Daydreamer (ECL) 143 +1 Nameless Inversion (ECL) 113 +1 Lavaleaper (ECL) 318 +1 Burdened Stoneback (ECL) 8 +2 Gathering Stone (ECL) 257 +1 Deepchannel Duelist (ECL) 213 +3 Gangly Stompling (ECL) 226 +2 Merrow Skyswimmer (ECL) 234 +1 Appeal to Eirdu (ECL) 5 +3 Elder Auntie (ECL) 133 +1 Sygg's Command (ECL) 244 +1 Pitiless Fists (ECL) 187 +2 Encumbered Reejerey (ECL) 14 +1 Feisty Spikeling (ECL) 223 +2 Enraged Flamecaster (ECL) 135 +1 Bile-Vial Boggart (ECL) 87 +2 Blossombind (ECL) 45 +1 Trystan, Callous Cultivator // Trystan, Penitent Culler (ECL) 199 +1 Glamer Gifter (ECL) 49 +2 Keep Out (ECL) 19 +1 Barbed Bloodletter (ECL) 86 +1 Sun-Dappled Celebrant (ECL) 37 +2 Wanderwine Distracter (ECL) 82 +1 Lluwen, Imperfect Naturalist (ECL) 232 +1 Deceit (ECL) 212 +1 Iron-Shield Elf (ECL) 108 +1 Illusion Spinners (ECL) 55 +1 Kindle the Inner Flame (ECL) 147 +2 Mischievous Sneakling (ECL) 235 +1 Stratosoarer (ECL) 72 +2 Run Away Together (ECL) 67 +2 Shore Lurker (ECL) 34 +2 Reckless Ransacking (ECL) 152 +2 Dawnhand Eulogist (ECL) 99 +1 Evershrike's Gift (ECL) 15 +1 Dawnhand Dissident (ECL) 311 +1 Bark of Doran (ECL) 6 +1 Gnarlbark Elm (ECL) 103 +1 Luminollusk (ECL) 179 +1 Flaring Cinder (ECL) 225 +1 Dose of Dawnglow (ECL) 100 +1 Ashling, Rekindled // Ashling, Rimebound (ECL) 124 +1 Morcant's Eyes (ECL) 185 +1 Wanderwine Farewell (ECL) 83 +1 Pyrrhic Strike (ECL) 30 +1 Chaos Spewer (ECL) 210 +2 Blighted Blackthorn (ECL) 90 +2 Great Forest Druid (ECL) 178 +2 Thoughtweft Charge (ECL) 198 +2 Unexpected Assistance (ECL) 80 +2 Safewright Cavalry (ECL) 191 +4 Bogslither's Embrace (ECL) 94 +3 Riverguard's Reflexes (ECL) 33 +2 Unbury (ECL) 123 +3 Midnight Tilling (ECL) 182 +2 Flamekin Gildweaver (ECL) 140 +2 Stalactite Dagger (ECL) 261 +2 Cinder Strike (ECL) 131 +3 Lys Alana Informant (ECL) 181 +2 Reluctant Dounguard (ECL) 31 +2 Temporal Cleansing (ECL) 78 +1 Morcant's Loyalist (ECL) 341 +2 Puca's Eye (ECL) 259 +1 Loch Mare (ECL) 57 +1 Sygg, Wanderwine Wisdom // Sygg, Wanderbrine Shield (ECL) 76 +2 Moonglove Extractor (ECL) 109 +2 Wildvine Pummeler (ECL) 203 +1 Aquitect's Defenses (ECL) 44 +1 Gallant Fowlknight (ECL) 17 +2 Wary Farmer (ECL) 251 +2 Reaping Willow (ECL) 240 +1 Moon-Vigil Adherents (ECL) 184 +1 Dawn-Blessed Pennant (ECL) 254 +1 Unwelcome Sprite (ECL) 81 +1 Glen Elendra Guardian (ECL) 51 +1 Thoughtweft Lieutenant (ECL) 246 +1 Meek Attack (ECL) 151 +1 Hallowed Fountain (ECL) 265 +1 Vinebred Brawler (ECL) 201 +2 Personify (ECL) 28 +2 Rooftop Percher (ECL) 2 +1 Blight Rot (ECL) 89 +2 Liminal Hold (ECL) 24 +1 Kulrath Mystic (ECL) 56 +1 Crossroads Watcher (ECL) 173 +1 Flame-Chain Mauler (ECL) 138 +2 Scarblade's Malice (ECL) 119 +1 Bitterblossom (SPG) 133 +1 Rimefire Torque (ECL) 65 +1 Shimmerwilds Growth (ECL) 194 +2 Evolving Wilds (ECL) 264 +1 Kirol, Attentive First-Year (ECL) 231 +1 Shimmercreep (ECL) 120 +1 Flamebraider (ECL) 139 +1 Tanufel Rimespeaker (ECL) 77 +2 Glamermite (ECL) 50 +2 Heirloom Auntie (ECL) 107 +2 Gutsplitter Gang (ECL) 106 +4 Chitinous Graspling (ECL) 211 +2 Sear (ECL) 154 +2 Clachan Festival (ECL) 10 +1 Oko, Lorwyn Liege // Oko, Shadowmoor Scion (ECL) 61 +1 Selfless Safewright (ECL) 193 +2 Creakwood Safewright (ECL) 96 +1 Noggle Robber (ECL) 237 +2 Brambleback Brute (ECL) 128 +1 Dawn's Light Archer (ECL) 174 +2 Feed the Flames (ECL) 137 +1 Auntie's Sentence (ECL) 85 +1 Kinscaer Sentry (ECL) 22 +1 Spell Snare (ECL) 71 +2 Virulent Emissary (ECL) 202 +1 Explosive Prodigy (ECL) 136 +1 Foraging Wickermaw (ECL) 256 +1 Silvergill Peddler (ECL) 70 +2 Goldmeadow Nomad (ECL) 18 +1 Harmonized Crescendo (ECL) 54 +1 Shinestriker (ECL) 68 +1 Chomping Changeling (ECL) 172 +1 Retched Wretch (ECL) 117 +1 Soulbright Seeker (ECL) 157 +1 Stoic Grove-Guide (ECL) 243 +2 Surly Farrier (ECL) 196 +1 Scarblade Scout (ECL) 118 +1 Timid Shieldbearer (ECL) 39 +1 Unforgiving Aim (ECL) 200 +1 Kulrath Zealot (ECL) 148 +1 Shadow Urchin (ECL) 242 +1 Rimekin Recluse (ECL) 66 +1 Sting-Slinger (ECL) 161 +1 Requiting Hex (ECL) 116 +1 Trystan's Command (ECL) 247 +1 Sourbread Auntie (ECL) 158 +1 Champion of the Clachan (ECL) 9 +1 Blossoming Defense (ECL) 167 +1 Hovel Hurler (ECL) 230 +1 Tweeze (ECL) 162 +1 Spiral into Solitude (ECL) 36 +2 Gravelgill Scoundrel (ECL) 53 +1 Twilight Diviner (ECL) 122 +1 Warren Torchmaster (ECL) 163 +1 Noggle the Mind (ECL) 60 diff --git a/decks/choco.json b/data/decks/choco.json similarity index 100% rename from decks/choco.json rename to data/decks/choco.json diff --git a/decks/hazel.json b/data/decks/hazel.json similarity index 100% rename from decks/hazel.json rename to data/decks/hazel.json diff --git a/decks/palamecia.json b/data/decks/palamecia.json similarity index 100% rename from decks/palamecia.json rename to data/decks/palamecia.json diff --git a/decks/yshtola.json b/data/decks/yshtola.json similarity index 100% rename from decks/yshtola.json rename to data/decks/yshtola.json diff --git a/docs/templates/AGENTS.template.md b/docs/templates/AGENTS.template.md index 085c1ef..0504f5c 100644 --- a/docs/templates/AGENTS.template.md +++ b/docs/templates/AGENTS.template.md @@ -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) -│ └── .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) +│ └── .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/.json` with required fields +1. Create `data/decks/.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}} \ No newline at end of file diff --git a/docs/templates/README.template.md b/docs/templates/README.template.md index ee8bb51..50822eb 100644 --- a/docs/templates/README.template.md +++ b/docs/templates/README.template.md @@ -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/.json`: +Create `data/decks/.json`: ```json { @@ -176,7 +176,7 @@ Create `decks/.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.* \ No newline at end of file diff --git a/hydrate.py b/hydrate.py index c0e143d..ac23050 100644 --- a/hydrate.py +++ b/hydrate.py @@ -206,12 +206,12 @@ def main(): hydrate_parser = subparsers.add_parser("hydrate", help="Hydrate a decklist with Scryfall data") hydrate_parser.add_argument("input", help="Input decklist file") - hydrate_parser.add_argument("-o", "--output", default="output", help="Output directory") - hydrate_parser.add_argument("-c", "--cache", default="card_cache.json", help="Cache file for card data") + hydrate_parser.add_argument("-o", "--output", default="output/hydrated", help="Output directory") + hydrate_parser.add_argument("-c", "--cache", default="cache/card_cache.json", help="Cache file for card data") new_parser = subparsers.add_parser("new", help="Create a new deck folder") new_parser.add_argument("name", help="Deck name") - new_parser.add_argument("-d", "--dir", default="decks", help="Base directory for decks") + new_parser.add_argument("-d", "--dir", default="data/decks", help="Base directory for decks") args = parser.parse_args() diff --git a/deck_analysis.json b/output/deck_analysis.json similarity index 100% rename from deck_analysis.json rename to output/deck_analysis.json diff --git a/collection_hydrated/artifacts.json b/output/hydrated/artifacts.json similarity index 100% rename from collection_hydrated/artifacts.json rename to output/hydrated/artifacts.json diff --git a/collection_hydrated/commander.json b/output/hydrated/commander.json similarity index 100% rename from collection_hydrated/commander.json rename to output/hydrated/commander.json diff --git a/collection_hydrated/creatures.json b/output/hydrated/creatures.json similarity index 100% rename from collection_hydrated/creatures.json rename to output/hydrated/creatures.json diff --git a/collection_hydrated/deck.json b/output/hydrated/deck.json similarity index 100% rename from collection_hydrated/deck.json rename to output/hydrated/deck.json diff --git a/collection_hydrated/enchantments.json b/output/hydrated/enchantments.json similarity index 100% rename from collection_hydrated/enchantments.json rename to output/hydrated/enchantments.json diff --git a/collection_hydrated/instants.json b/output/hydrated/instants.json similarity index 100% rename from collection_hydrated/instants.json rename to output/hydrated/instants.json diff --git a/collection_hydrated/lands.json b/output/hydrated/lands.json similarity index 100% rename from collection_hydrated/lands.json rename to output/hydrated/lands.json diff --git a/collection_hydrated/planeswalkers.json b/output/hydrated/planeswalkers.json similarity index 100% rename from collection_hydrated/planeswalkers.json rename to output/hydrated/planeswalkers.json diff --git a/collection_hydrated/sorceries.json b/output/hydrated/sorceries.json similarity index 100% rename from collection_hydrated/sorceries.json rename to output/hydrated/sorceries.json diff --git a/scripts/analyze_decks.py b/scripts/analyze_decks.py index e08c20a..83ac756 100644 --- a/scripts/analyze_decks.py +++ b/scripts/analyze_decks.py @@ -2,8 +2,8 @@ """ Analyze decks against a hydrated collection to find upgrade options. Usage: - python analyze_decks.py --collection collection_hydrated/deck.json --decks deck1.json deck2.json ... - python analyze_decks.py --collection collection_hydrated/deck.json --deck-dir decks/ + python analyze_decks.py --collection output/hydrated/deck.json --decks deck1.json deck2.json ... + python analyze_decks.py --collection output/hydrated/deck.json --deck-dir data/decks/ """ import argparse diff --git a/scripts/deck_report.py b/scripts/deck_report.py index d6ea8f4..9be71db 100644 --- a/scripts/deck_report.py +++ b/scripts/deck_report.py @@ -2,7 +2,7 @@ """ Generate a deck upgrade report comparing collection to existing decks. Usage: - python deck_report.py --collection collection_hydrated/deck.json --decks-dir decks/ --output report.md + python deck_report.py --collection output/hydrated/deck.json --decks-dir data/decks/ --output output/report.md """ import argparse @@ -26,9 +26,9 @@ def load_deck(path: str) -> dict: def main(): parser = argparse.ArgumentParser(description='Generate deck upgrade report') - parser.add_argument('--collection', '-c', required=True) - parser.add_argument('--decks-dir', '-d', required=True) - parser.add_argument('--output', '-o', required=True) + parser.add_argument('--collection', '-c', default='output/hydrated/deck.json') + parser.add_argument('--decks-dir', '-d', default='data/decks') + parser.add_argument('--output', '-o', default='output/deck_report.md') args = parser.parse_args() collection = load_collection(args.collection) diff --git a/scripts/find_synergies.py b/scripts/find_synergies.py index c446cfb..53f2868 100644 --- a/scripts/find_synergies.py +++ b/scripts/find_synergies.py @@ -2,9 +2,9 @@ """ Find cards with specific synergies from a hydrated collection. Usage: - python find_synergies.py --collection collection_hydrated/deck.json --colors U R --keywords "landfall" "enter the battlefield" - python find_synergies.py --collection collection_hydrated/deck.json --colors U R --creature-type Bird - python find_synergies.py --collection collection_hydrated/deck.json --colors U R --cmc-min 4 --type instant + python find_synergies.py --collection output/hydrated/deck.json --colors U R --keywords "landfall" "enter the battlefield" + python find_synergies.py --collection output/hydrated/deck.json --colors U R --creature-type Bird + python find_synergies.py --collection output/hydrated/deck.json --colors U R --cmc-min 4 --type instant """ import argparse diff --git a/scripts/update_docs.py b/scripts/update_docs.py index 99a6d8c..31136fb 100644 --- a/scripts/update_docs.py +++ b/scripts/update_docs.py @@ -12,8 +12,8 @@ from pathlib import Path SCRIPT_DIR = Path(__file__).parent PROJECT_ROOT = SCRIPT_DIR.parent TEMPLATES_DIR = PROJECT_ROOT / "docs" / "templates" -DECKS_DIR = PROJECT_ROOT / "decks" -COLLECTION_DIR = PROJECT_ROOT / "collection_hydrated" +DECKS_DIR = PROJECT_ROOT / "data" / "decks" +COLLECTION_DIR = PROJECT_ROOT / "output" / "hydrated" def load_decks() -> list[dict]: