1

Affiche le part_num sur les frises de têtes

This commit is contained in:
Richard Dern 2025-12-02 22:26:52 +01:00
parent 43062b7ed4
commit 9158b7440c
5 changed files with 23 additions and 12 deletions

View File

@ -352,5 +352,5 @@ Le script lit `data/intermediate/minifigs_by_set.csv`, `data/intermediate/sets_e
- `data/intermediate/minifig_character_sets.csv` : apparitions des personnages avec set, identifiant de set, année, possession et fig_num.
- `figures/step32/minifig_characters/{personnage}.png` : frise horizontale par personnage, composée des visuels de minifigs dans lordre chronologique, annotés avec lannée, le numéro de set (avec `*` si possédé) et lidentifiant de minifig. Les minifigs dont limage nest pas disponible sont remplacées par un rectangle neutre pour matérialiser le manque.
- `figures/step32/minifig_heads/{personnage}.png` : même principe mais en utilisant les visuels de têtes (`head.jpg`) pour chaque apparition.
- `figures/step32/minifig_heads/{personnage}.png` : même principe mais en utilisant les visuels de têtes (`head.jpg`) pour chaque apparition, annotés avec lannée, le set (avec `*` si possédé) et le `part_num` de la tête.
- Les étiquettes affichent aussi lidentifiant de la minifig (`fig-*`) et un astérisque à côté du set (`set_num*`) lorsquil est présent dans la collection.

View File

@ -58,6 +58,7 @@ def build_character_collage(
font: ImageFont.ImageFont,
missing_paths: Set[str] | None = None,
image_filename: str = "minifig.jpg",
label_field: str = "fig_num",
image_height: int = 260,
label_height: int = 44,
spacing: int = 28,
@ -69,7 +70,8 @@ def build_character_collage(
for row in entries:
image_path = resources_dir / row["set_id"] / sanitized / image_filename
owned = "*" if row.get("in_collection", "").lower() == "true" else ""
label = f"{row['year']} - {row['set_num']}{owned} ({row['fig_num']})"
label_value = row[label_field]
label = f"{row['year']} - {row['set_num']}{owned} ({label_value})"
if str(image_path) in missing:
image = build_placeholder(image_height)
else:
@ -94,6 +96,7 @@ def build_character_collages(
destination_dir: Path,
missing_paths: Set[str] | None = None,
image_filename: str = "minifig.jpg",
label_field: str = "fig_num",
image_height: int = 260,
label_height: int = 44,
spacing: int = 28,
@ -111,6 +114,7 @@ def build_character_collages(
font,
missing_paths=missing_paths,
image_filename=image_filename,
label_field=label_field,
image_height=image_height,
label_height=label_height,
spacing=spacing,

View File

@ -28,17 +28,18 @@ def build_character_sets(
) -> 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()
seen: set[tuple[str, str, str, str]] = set()
character_sets: List[dict] = []
for row in minifigs_rows:
character = row["known_character"].strip()
fig_num = row["fig_num"].strip()
part_num = row["part_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)
key = (character, row["set_num"], fig_num, part_num)
if key in seen:
continue
character_sets.append(
@ -49,11 +50,12 @@ def build_character_sets(
"year": set_row["year"],
"fig_num": fig_num,
"in_collection": set_row["in_collection"],
"part_num": part_num,
}
)
seen.add(key)
character_sets.sort(
key=lambda row: (row["known_character"], int(row["year"]), row["set_num"], row["fig_num"])
key=lambda row: (row["known_character"], int(row["year"]), row["set_num"], row["fig_num"], row["part_num"])
)
return character_sets
@ -61,7 +63,7 @@ def build_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", "in_collection"]
fieldnames = ["known_character", "set_num", "set_id", "year", "fig_num", "in_collection", "part_num"]
with destination_path.open("w", newline="") as csv_file:
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
writer.writeheader()

View File

@ -36,6 +36,7 @@ def main() -> None:
DESTINATION_DIR,
missing_paths=missing_heads,
image_filename="head.jpg",
label_field="part_num",
)

View File

@ -18,12 +18,12 @@ def create_image(path: Path, color: tuple[int, int, int], size: tuple[int, int])
def test_build_character_sets_and_collages(tmp_path: Path) -> None:
"""Construit les apparitions par personnage puis les frises associées."""
minifigs_rows = [
{"set_num": "1000-1", "known_character": "Alice", "fig_num": "fig-1"},
{"set_num": "1000-1", "known_character": "Alice", "fig_num": "fig-1"},
{"set_num": "1001-1", "known_character": "Bob", "fig_num": "fig-2"},
{"set_num": "1002-1", "known_character": "Bob", "fig_num": "fig-3"},
{"set_num": "1004-1", "known_character": "Claire Dearing", "fig_num": "fig-5"},
{"set_num": "1003-1", "known_character": "Figurant", "fig_num": "fig-4"},
{"set_num": "1000-1", "known_character": "Alice", "fig_num": "fig-1", "part_num": "p1"},
{"set_num": "1000-1", "known_character": "Alice", "fig_num": "fig-1", "part_num": "p1"},
{"set_num": "1001-1", "known_character": "Bob", "fig_num": "fig-2", "part_num": "p2"},
{"set_num": "1002-1", "known_character": "Bob", "fig_num": "fig-3", "part_num": "p3"},
{"set_num": "1004-1", "known_character": "Claire Dearing", "fig_num": "fig-5", "part_num": "p5"},
{"set_num": "1003-1", "known_character": "Figurant", "fig_num": "fig-4", "part_num": "p4"},
]
sets_lookup = {
"1000-1": {"set_id": "1000", "year": "2020", "in_collection": "true"},
@ -42,6 +42,7 @@ def test_build_character_sets_and_collages(tmp_path: Path) -> None:
"year": "2020",
"fig_num": "fig-1",
"in_collection": "true",
"part_num": "p1",
},
{
"known_character": "Bob",
@ -50,6 +51,7 @@ def test_build_character_sets_and_collages(tmp_path: Path) -> None:
"year": "2021",
"fig_num": "fig-2",
"in_collection": "false",
"part_num": "p2",
},
{
"known_character": "Bob",
@ -58,6 +60,7 @@ def test_build_character_sets_and_collages(tmp_path: Path) -> None:
"year": "2022",
"fig_num": "fig-3",
"in_collection": "false",
"part_num": "p3",
},
{
"known_character": "Claire Dearing",
@ -66,6 +69,7 @@ def test_build_character_sets_and_collages(tmp_path: Path) -> None:
"year": "2024",
"fig_num": "fig-5",
"in_collection": "true",
"part_num": "p5",
},
]