1

Liste les nouveaux personnages par année

This commit is contained in:
2025-12-03 22:41:06 +01:00
parent 46cef55a75
commit d5ff3cd076
4 changed files with 235 additions and 5 deletions

View File

@@ -110,6 +110,69 @@ def aggregate_new_characters_by_year(
return results
def aggregate_new_character_sets(
minifigs_rows: Iterable[dict],
sets_lookup: Dict[str, dict],
excluded_characters: Sequence[str] | None = None,
start_year: int | None = None,
end_year: int | None = None,
) -> List[dict]:
"""Liste les personnages introduits par année avec les sets correspondants."""
excluded = set(excluded_characters or [])
first_year: Dict[str, int] = {}
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.get(row["set_num"])
if set_row is None:
continue
year_int = int(set_row["year"])
current = first_year.get(character)
if current is None or year_int < current:
first_year[character] = year_int
rows: List[dict] = []
seen: set[tuple[str, str]] = set()
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.get(row["set_num"])
if set_row is None:
continue
intro_year = first_year.get(character)
if intro_year is None:
continue
if start_year is not None and intro_year < start_year:
continue
if end_year is not None and intro_year > end_year:
continue
if int(set_row["year"]) != intro_year:
continue
key = (character, set_row["set_num"])
if key in seen:
continue
rows.append(
{
"year": str(int(set_row["year"])),
"known_character": character,
"set_num": set_row["set_num"],
"set_id": set_row.get("set_id", ""),
"set_name": set_row.get("name", ""),
"rebrickable_url": set_row.get("rebrickable_url", ""),
}
)
seen.add(key)
rows.sort(key=lambda r: (int(r["year"]), r["known_character"], r["set_id"]))
return rows
def aggregate_by_gender(rows: Iterable[dict]) -> List[dict]:
"""Compte les minifigs distinctes par genre (fig_num unique)."""
genders_by_fig: Dict[str, str] = {}
@@ -154,6 +217,38 @@ def write_new_characters_by_year(path: Path, rows: Sequence[dict]) -> None:
writer.writerow(row)
def write_new_character_sets_csv(path: Path, rows: Sequence[dict]) -> None:
"""Écrit le CSV listant les personnages introduits et leurs sets."""
ensure_parent_dir(path)
fieldnames = ["year", "known_character", "set_num", "set_id", "set_name", "rebrickable_url"]
with path.open("w", newline="") as csv_file:
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
writer.writeheader()
for row in rows:
writer.writerow(row)
def write_new_character_sets_markdown(path: Path, rows: Sequence[dict]) -> None:
"""Écrit un Markdown listant les personnages introduits par année et leurs sets."""
ensure_parent_dir(path)
grouped: Dict[str, Dict[str, List[dict]]] = {}
for row in rows:
year_group = grouped.setdefault(row["year"], {})
characters = year_group.setdefault(row["known_character"], [])
characters.append(row)
with path.open("w") as md_file:
for year in sorted(grouped.keys(), key=int):
md_file.write(f"##### {year}\n\n")
for character in sorted(grouped[year].keys()):
md_file.write(f"- {character}\n")
for entry in sorted(grouped[year][character], key=lambda r: r["set_id"]):
link = entry["rebrickable_url"] or ""
set_id = entry["set_id"]
name = entry["set_name"]
md_file.write(f" - [{set_id}]({link}) - {name}\n")
md_file.write("\n")
def write_gender_counts(path: Path, rows: Sequence[dict]) -> None:
"""Écrit le CSV des comptes par genre."""
ensure_parent_dir(path)