| """ |
| Convierte los 11 documentos oficiales de Riftbound (en ~/Desktop por defecto) |
| a backend/data/processed/*.md, listos para ingest. |
| |
| - Docs ya-Markdown (Core Rules, Tournament, FAQs, Patch Notes): se copian con |
| nombre normalizado y encoding UTF-8. |
| - Erratas (3 docs): se parsean (New/Old + set por H1 interno), se consolidan por |
| carta con precedencia por fecha (la más reciente gana) y se renderiza un |
| errata_<set>.md por expansión. |
| |
| Uso: |
| python scripts/build_corpus.py [carpeta_fuente] |
| """ |
| import os |
| from pathlib import Path |
|
|
| from scripts.parse_errata import parse_errata_doc, render_errata_md |
|
|
| |
| |
| PASSTHROUGH_DOCS = { |
| "# Riftbound Core Rules.txt": "rulebook", |
| "# Riftbound Tournament Rules.txt": "tournament_rules", |
| "# Riftbound Core Rules Patch Notes.txt": "patch_notes_origins", |
| "# Riftbound Core Rules – Spiritforged Patch Notes.txt": "patch_notes_spiritforged", |
| "Riftbound Core Rules Unleashed Patch Notes.txt": "patch_notes_unleashed", |
| "# Riftbound Origins FAQ.txt": "faq_origins", |
| "# Riftbound FAQ – Spiritforged.txt": "faq_spiritforged", |
| "# Unleashed Rules FAQ and Clarifications.txt": "faq_unleashed", |
| } |
|
|
| |
| ERRATA_DOCS = { |
| "Riftbound Origins Card Errata.txt": ("origins", "2025-10-27"), |
| "# Riftbound Spiritforged Errata.txt": ("spiritforged", "2026-01-13"), |
| "Unleashed Errata Updates.txt": ("unleashed", "2026-04-02"), |
| } |
|
|
|
|
| def consolidate_errata(docs: list[dict]) -> dict[str, list[dict]]: |
| """Consolida cartas de varios docs de errata. |
| |
| `docs`: lista de {"date": ISO, "cards": [card dicts]}. |
| Si una carta aparece en varios docs, gana la de fecha MÁS RECIENTE. |
| Returns: dict set -> lista de cartas (ordenada por nombre). |
| """ |
| latest: dict[str, dict] = {} |
| latest_date: dict[str, str] = {} |
|
|
| for doc in docs: |
| date = doc["date"] |
| for card in doc["cards"]: |
| name = card["card"] |
| if name not in latest_date or date > latest_date[name]: |
| latest_date[name] = date |
| latest[name] = card |
|
|
| by_set: dict[str, list[dict]] = {} |
| for card in latest.values(): |
| by_set.setdefault(card["set"], []).append(card) |
| for cards in by_set.values(): |
| cards.sort(key=lambda c: c["card"]) |
| return by_set |
|
|
|
|
| def _normalize_md(text: str) -> str: |
| """Normaliza saltos de línea y asegura newline final.""" |
| text = text.replace("\r\n", "\n").replace("\r", "\n") |
| return text.rstrip() + "\n" |
|
|
|
|
| def build_corpus(source_dir: Path, processed_dir: Path) -> dict: |
| processed_dir.mkdir(parents=True, exist_ok=True) |
| report = {"passthrough": [], "errata": [], "missing": []} |
|
|
| |
| for src_name, stem in PASSTHROUGH_DOCS.items(): |
| src = source_dir / src_name |
| if not src.exists(): |
| report["missing"].append(src_name) |
| continue |
| text = _normalize_md(src.read_text(encoding="utf-8")) |
| (processed_dir / f"{stem}.md").write_text(text, encoding="utf-8") |
| report["passthrough"].append(stem) |
|
|
| |
| parsed_docs = [] |
| for src_name, (default_set, date) in ERRATA_DOCS.items(): |
| src = source_dir / src_name |
| if not src.exists(): |
| report["missing"].append(src_name) |
| continue |
| cards = parse_errata_doc(src.read_text(encoding="utf-8"), default_set=default_set) |
| parsed_docs.append({"date": date, "cards": cards}) |
|
|
| by_set = consolidate_errata(parsed_docs) |
| for set_name, cards in by_set.items(): |
| md = render_errata_md(cards, set_name=set_name) |
| (processed_dir / f"errata_{set_name}.md").write_text(md, encoding="utf-8") |
| report["errata"].append({"set": set_name, "cards": len(cards)}) |
|
|
| return report |
|
|
|
|
| if __name__ == "__main__": |
| import sys |
|
|
| source = Path(sys.argv[1]) if len(sys.argv) > 1 else Path(os.path.expanduser("~")) / "Desktop" |
| processed = Path(__file__).parent.parent / "data" / "processed" |
| rep = build_corpus(source, processed) |
| print("Passthrough:", ", ".join(rep["passthrough"])) |
| print("Erratas:", rep["errata"]) |
| if rep["missing"]: |
| print("FALTANTES:", rep["missing"]) |
|
|