Files
COC_API/app/utils/catalogs/race_catalog.py
2025-11-02 01:14:41 -05:00

73 lines
2.8 KiB
Python

# race_catalog.py
from __future__ import annotations
from dataclasses import dataclass
from pathlib import Path
from typing import Dict, List, Any
import yaml
from app.models.enums import Race
from app.models.primitives import Attributes, Resources
from app.models.races import RaceSheet, RacialTrait
from app.utils.hero_catalog import SkillDef, SpellDef
class RaceDataRegistry:
"""
In-memory catalog of YAML-defined race sheets.
"""
def __init__(self) -> None:
self._by_race: Dict[Race, RaceSheet] = {}
# promoted global catalogs for cross-use at runtime (optional)
self._skills: Dict[str, SkillDef] = {}
self._spells: Dict[str, SpellDef] = {}
def load_dir(self, directory: str | Path) -> None:
directory = Path(directory)
for path in sorted(directory.glob("*.y*ml")):
with path.open("r", encoding="utf-8") as f:
raw = yaml.safe_load(f) or {}
key_raw = raw.get("key")
if not key_raw:
raise ValueError(f"{path.name}: missing required 'key'")
race = Race(key_raw) # validates enum
base_attributes = Attributes(**(raw.get("base_attributes") or {}))
starting_resources = Resources(**(raw.get("starting_resources") or {}))
sheet = RaceSheet(
key=race,
display_name=raw.get("display_name", race.value.title()),
base_attributes=base_attributes,
starting_resources=starting_resources,
starting_skills=list(raw.get("starting_skills") or []),
starting_spells=list(raw.get("starting_spells") or []),
)
# Local skill/spell catalogs (optional)
for sid, sdef in (raw.get("skills") or {}).items():
s = SkillDef.from_yaml(sid, sdef)
sheet.skills[sid] = s
self._skills[sid] = s
for spid, spdef in (raw.get("spells") or {}).items():
sp = SpellDef.from_yaml(spid, spdef)
sheet.spells[spid] = sp
self._spells[spid] = sp
# Traits
traits_raw = raw.get("traits") or []
for t in traits_raw:
sheet.traits.append(RacialTrait(id=t.get("id"), data=dict(t.get("data") or {})))
self._by_race[race] = sheet
def for_race(self, race: Race) -> RaceSheet:
if race not in self._by_race:
raise KeyError(f"No race sheet loaded for {race.value}")
return self._by_race[race]
# Optional global lookups (if you want to fetch a skill from race-only files)
def get_skill(self, skill_id: str) -> SkillDef: return self._skills[skill_id]
def get_spell(self, spell_id: str) -> SpellDef: return self._spells[spell_id]