"""Liste les sets contenant chaque personnage connu.""" import csv from pathlib import Path from typing import Dict, Iterable, List, Sequence from lib.filesystem import ensure_parent_dir from lib.rebrickable.stats import read_rows def load_minifigs_by_set(path: Path) -> List[dict]: """Charge le CSV minifigs_by_set.""" return read_rows(path) def load_sets(path: Path) -> Dict[str, dict]: """Indexe les sets enrichis par set_num.""" lookup: Dict[str, dict] = {} for row in read_rows(path): lookup[row["set_num"]] = row return lookup def build_character_sets( minifigs_rows: Iterable[dict], sets_lookup: Dict[str, dict], excluded_characters: Sequence[str] | None = None, ) -> List[dict]: """Associe chaque personnage connu aux sets où il apparaît (hors figurants).""" excluded = set(excluded_characters or []) seen: set[tuple[str, str, str]] = set() character_sets: List[dict] = [] for row in minifigs_rows: character = row["known_character"].strip() fig_num = row["fig_num"].strip() if character == "" or fig_num == "": continue if character in excluded: continue set_row = sets_lookup[row["set_num"]] key = (character, row["set_num"], fig_num) if key in seen: continue character_sets.append( { "known_character": character, "set_num": row["set_num"], "set_id": set_row["set_id"], "year": set_row["year"], "fig_num": fig_num, } ) seen.add(key) character_sets.sort(key=lambda row: (row["known_character"], int(row["year"]), row["set_num"], row["fig_num"])) return character_sets def write_character_sets(destination_path: Path, rows: Sequence[dict]) -> None: """Écrit le CSV listant les sets par personnage.""" ensure_parent_dir(destination_path) fieldnames = ["known_character", "set_num", "set_id", "year", "fig_num"] with destination_path.open("w", newline="") as csv_file: writer = csv.DictWriter(csv_file, fieldnames=fieldnames) writer.writeheader() for row in rows: writer.writerow(row) def group_by_character(rows: Iterable[dict]) -> Dict[str, List[dict]]: """Regroupe les lignes par personnage pour la génération des frises.""" grouped: Dict[str, List[dict]] = {} for row in rows: character = row["known_character"] entries = grouped.get(character) if entries is None: entries = [] grouped[character] = entries entries.append(row) for character, entries in grouped.items(): entries.sort(key=lambda row: (int(row["year"]), row["set_num"], row["fig_num"])) return grouped def load_missing_minifigs(path: Path) -> set[str]: """Charge les ressources minifigs introuvables consignées dans le log de téléchargement.""" missing: set[str] = set() with path.open() as csv_file: reader = csv.DictReader(csv_file) for row in reader: if row["status"] != "missing": continue if not row["path"].endswith("minifig.jpg"): continue missing.add(row["path"]) return missing