#!/usr/bin/env python3 """ Analyze decks against a hydrated collection to find upgrade options. Usage: 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 import json import os import sys from pathlib import Path def load_collection(path: str) -> dict: """Load hydrated collection JSON.""" with open(path, 'r') as f: cards = json.load(f) return {c['name']: c for c in cards} def load_deck(path: str) -> dict: """Load deck JSON (from parse_deck.py output or deck.json format).""" with open(path, 'r') as f: data = json.load(f) if 'cards' in data: return data['cards'] return data def get_color_identity(card: dict) -> set: """Get color identity as a set.""" return set(card.get('color_identity', [])) def matches_colors(card_identity: set, deck_colors: set) -> bool: """Check if card identity fits within deck colors.""" return card_identity <= deck_colors or not card_identity def find_upgrades(collection: dict[str, dict], deck_cards: dict, all_deck_cards: set, deck_colors: set, archetype: str | None = None) -> dict: """Find potential upgrade cards for a deck.""" available = set(collection.keys()) - all_deck_cards upgrades = { 'creatures': [], 'instants': [], 'sorceries': [], 'artifacts': [], 'enchantments': [], 'lands': [], 'other': [] } for name in available: card = collection.get(name, {}) if not card: continue ci = get_color_identity(card) if not matches_colors(ci, deck_colors): continue type_line = card.get('type_line', '').lower() if card.get('type_line') else '' entry = { 'name': name, 'mana_cost': card.get('mana_cost', ''), 'cmc': card.get('cmc', 0), 'type_line': card.get('type_line', ''), 'oracle_text': card.get('oracle_text', ''), 'count': card.get('count', 1) } if 'creature' in type_line: upgrades['creatures'].append(entry) elif 'instant' in type_line: upgrades['instants'].append(entry) elif 'sorcery' in type_line: upgrades['sorceries'].append(entry) elif 'artifact' in type_line: upgrades['artifacts'].append(entry) elif 'enchantment' in type_line: upgrades['enchantments'].append(entry) elif 'land' in type_line: upgrades['lands'].append(entry) else: upgrades['other'].append(entry) return upgrades def find_synergies(collection: dict, available: set, deck_colors: set, keywords: list) -> list: """Find cards with specific keyword synergies.""" synergies = [] for name in available: card = collection.get(name, {}) if not card: continue ci = get_color_identity(card) if not matches_colors(ci, deck_colors): continue oracle = card.get('oracle_text', '').lower() if card.get('oracle_text') else '' if any(kw.lower() in oracle for kw in keywords): synergies.append({ 'name': name, 'type_line': card.get('type_line', ''), 'mana_cost': card.get('mana_cost', ''), 'oracle_snippet': oracle[:100] }) return synergies def main(): parser = argparse.ArgumentParser(description='Analyze decks for upgrade options') parser.add_argument('--collection', '-c', required=True, help='Hydrated collection JSON') parser.add_argument('--decks', '-d', nargs='+', help='Deck JSON files') parser.add_argument('--deck-dir', help='Directory containing deck JSON files') parser.add_argument('--output', '-o', help='Output JSON file') parser.add_argument('--keywords', '-k', nargs='+', help='Keywords to search for synergies') args = parser.parse_args() collection = load_collection(args.collection) decks = {} if args.decks: for path in args.decks: name = Path(path).stem decks[name] = load_deck(path) elif args.deck_dir: for path in Path(args.deck_dir).glob('*.json'): decks[path.stem] = load_deck(str(path)) else: print("Error: Provide --decks or --deck-dir", file=sys.stderr) sys.exit(1) all_deck_cards = set() for deck_cards in decks.values(): all_deck_cards.update(deck_cards.keys()) results = {} for deck_name, deck_cards in decks.items(): deck_colors = set() for name in deck_cards: card = collection.get(name, {}) deck_colors |= get_color_identity(card) upgrades = find_upgrades(collection, deck_cards, all_deck_cards, deck_colors) available = set(collection.keys()) - all_deck_cards synergies = {} if args.keywords: synergies = find_synergies(collection, available, deck_colors, args.keywords) results[deck_name] = { 'total_cards': sum(deck_cards.values()), 'unique_cards': len(deck_cards), 'color_identity': list(deck_colors), 'available_upgrades': {k: len(v) for k, v in upgrades.items()}, 'upgrades': upgrades, 'synergies': synergies } output = json.dumps(results, indent=2) if args.output: with open(args.output, 'w') as f: f.write(output) else: print(output) if __name__ == '__main__': main()