mirror of
https://github.com/mwisnowski/mtg_python_deckbuilder.git
synced 2025-12-17 08:00:13 +01:00
feat(editorial): Phase D synergy commander enrichment, augmentation, lint & docs\n\nAdds Phase D editorial tooling: synergy-based commander selection with 3/2/1 pattern, duplicate filtering, annotated synergy_commanders, promotion to minimum examples, and augmentation heuristics (e.g. Counters Matter/Proliferate injection). Includes new scripts (generate_theme_editorial_suggestions, lint, validate, catalog build/apply), updates orchestrator & web routes, expands CI workflow, and documents usage & non-determinism policies. Updates lint rules, type definitions, and docker configs.
This commit is contained in:
parent
16261bbf09
commit
f2a76d2ffc
35 changed files with 2818 additions and 509 deletions
79
code/scripts/apply_next_theme_editorial.py
Normal file
79
code/scripts/apply_next_theme_editorial.py
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
"""Apply example_cards / example_commanders to the next theme missing them.
|
||||
|
||||
Usage:
|
||||
python code/scripts/apply_next_theme_editorial.py
|
||||
|
||||
Repeating invocation will fill themes one at a time (skips deprecated alias placeholders).
|
||||
Options:
|
||||
--force overwrite existing lists for that theme
|
||||
--top / --top-commanders size knobs forwarded to suggestion generator
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
import yaml # type: ignore
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
CATALOG_DIR = ROOT / 'config' / 'themes' / 'catalog'
|
||||
|
||||
|
||||
def find_next_missing():
|
||||
for path in sorted(CATALOG_DIR.glob('*.yml')):
|
||||
try:
|
||||
data = yaml.safe_load(path.read_text(encoding='utf-8'))
|
||||
except Exception:
|
||||
continue
|
||||
if not isinstance(data, dict):
|
||||
continue
|
||||
notes = data.get('notes', '')
|
||||
if isinstance(notes, str) and 'Deprecated alias file' in notes:
|
||||
continue
|
||||
# Completion rule: a theme is considered "missing" only if a key itself is absent.
|
||||
# We intentionally allow empty lists (e.g., obscure themes with no clear commanders)
|
||||
# so we don't get stuck repeatedly selecting the same file.
|
||||
if ('example_cards' not in data) or ('example_commanders' not in data):
|
||||
return data.get('display_name'), path.name
|
||||
return None, None
|
||||
|
||||
|
||||
def main(): # pragma: no cover
|
||||
ap = argparse.ArgumentParser(description='Apply editorial examples to next missing theme')
|
||||
ap.add_argument('--force', action='store_true')
|
||||
ap.add_argument('--top', type=int, default=8)
|
||||
ap.add_argument('--top-commanders', type=int, default=5)
|
||||
args = ap.parse_args()
|
||||
theme, fname = find_next_missing()
|
||||
if not theme:
|
||||
print('All themes already have example_cards & example_commanders (or no YAML).')
|
||||
return
|
||||
print(f"Next missing theme: {theme} ({fname})")
|
||||
cmd = [
|
||||
sys.executable,
|
||||
str(ROOT / 'code' / 'scripts' / 'generate_theme_editorial_suggestions.py'),
|
||||
'--themes', theme,
|
||||
'--apply', '--limit-yaml', '1',
|
||||
'--top', str(args.top), '--top-commanders', str(args.top_commanders)
|
||||
]
|
||||
if args.force:
|
||||
cmd.append('--force')
|
||||
print('Running:', ' '.join(cmd))
|
||||
subprocess.run(cmd, check=False)
|
||||
# Post-pass: if we managed to add example_cards but no commanders were inferred, stamp an empty list
|
||||
# so subsequent runs proceed to the next theme instead of re-processing this one forever.
|
||||
if fname:
|
||||
target = CATALOG_DIR / fname
|
||||
try:
|
||||
data = yaml.safe_load(target.read_text(encoding='utf-8'))
|
||||
if isinstance(data, dict) and 'example_cards' in data and 'example_commanders' not in data:
|
||||
data['example_commanders'] = []
|
||||
target.write_text(yaml.safe_dump(data, sort_keys=False, allow_unicode=True), encoding='utf-8')
|
||||
print(f"[post] added empty example_commanders list to {fname} (no suggestions available)")
|
||||
except Exception as e: # pragma: no cover
|
||||
print(f"[post-warn] failed to add placeholder commanders for {fname}: {e}")
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue