44 lines
1.4 KiB
Python
44 lines
1.4 KiB
Python
from pathlib import Path
|
|
from typing import Dict, Iterable, Optional
|
|
import yaml
|
|
|
|
from app.game.models.professions import Profession
|
|
|
|
class ProfessionRepository:
|
|
def __init__(self):
|
|
|
|
self.root = Path() / "app" / "game" / "templates" / "professions"
|
|
self._by_id: Dict[str, Profession] = {}
|
|
self.load()
|
|
|
|
@staticmethod
|
|
def _iter_yaml_files(root: Path) -> Iterable[Path]:
|
|
# Recursively find *.yaml under the root
|
|
yield from root.rglob("*.yaml")
|
|
|
|
def load(self) -> None:
|
|
for path in self._iter_yaml_files(self.root):
|
|
with path.open("r", encoding="utf-8") as f:
|
|
data = yaml.safe_load(f) or {}
|
|
|
|
profession = Profession.from_yaml(data)
|
|
|
|
if profession.id in self._by_id:
|
|
raise ValueError(f"Duplicate profession id '{profession.id}' in {path}")
|
|
|
|
self._by_id.update({profession.id:profession})
|
|
|
|
|
|
# ----- Queries -----
|
|
|
|
def get(self, profession_id: str) -> Optional[Profession]:
|
|
return self._by_id.get(profession_id)
|
|
|
|
def list_all(self) -> list[Profession]:
|
|
return list(self._by_id.values())
|
|
|
|
def list_by_tag(self, tag: str) -> list[Profession]:
|
|
return [r for r in self._by_id.values() if tag in r.tags]
|
|
|
|
def list_by_any_tags(self, tags: set[str]) -> list[Profession]:
|
|
return [r for r in self._by_id.values() if r.tags & tags] |