Affiche le part_num sur les frises de têtes
This commit is contained in:
parent
43062b7ed4
commit
9158b7440c
@ -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.
|
- `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 l’ordre chronologique, annotés avec l’année, le numéro de set (avec `*` si possédé) et l’identifiant de minifig. Les minifigs dont l’image n’est pas disponible sont remplacées par un rectangle neutre pour matérialiser le manque.
|
- `figures/step32/minifig_characters/{personnage}.png` : frise horizontale par personnage, composée des visuels de minifigs dans l’ordre chronologique, annotés avec l’année, le numéro de set (avec `*` si possédé) et l’identifiant de minifig. Les minifigs dont l’image n’est 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 l’année, le set (avec `*` si possédé) et le `part_num` de la tête.
|
||||||
- Les étiquettes affichent aussi l’identifiant de la minifig (`fig-*`) et un astérisque à côté du set (`set_num*`) lorsqu’il est présent dans la collection.
|
- Les étiquettes affichent aussi l’identifiant de la minifig (`fig-*`) et un astérisque à côté du set (`set_num*`) lorsqu’il est présent dans la collection.
|
||||||
|
|||||||
@ -58,6 +58,7 @@ def build_character_collage(
|
|||||||
font: ImageFont.ImageFont,
|
font: ImageFont.ImageFont,
|
||||||
missing_paths: Set[str] | None = None,
|
missing_paths: Set[str] | None = None,
|
||||||
image_filename: str = "minifig.jpg",
|
image_filename: str = "minifig.jpg",
|
||||||
|
label_field: str = "fig_num",
|
||||||
image_height: int = 260,
|
image_height: int = 260,
|
||||||
label_height: int = 44,
|
label_height: int = 44,
|
||||||
spacing: int = 28,
|
spacing: int = 28,
|
||||||
@ -69,7 +70,8 @@ def build_character_collage(
|
|||||||
for row in entries:
|
for row in entries:
|
||||||
image_path = resources_dir / row["set_id"] / sanitized / image_filename
|
image_path = resources_dir / row["set_id"] / sanitized / image_filename
|
||||||
owned = "*" if row.get("in_collection", "").lower() == "true" else ""
|
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:
|
if str(image_path) in missing:
|
||||||
image = build_placeholder(image_height)
|
image = build_placeholder(image_height)
|
||||||
else:
|
else:
|
||||||
@ -94,6 +96,7 @@ def build_character_collages(
|
|||||||
destination_dir: Path,
|
destination_dir: Path,
|
||||||
missing_paths: Set[str] | None = None,
|
missing_paths: Set[str] | None = None,
|
||||||
image_filename: str = "minifig.jpg",
|
image_filename: str = "minifig.jpg",
|
||||||
|
label_field: str = "fig_num",
|
||||||
image_height: int = 260,
|
image_height: int = 260,
|
||||||
label_height: int = 44,
|
label_height: int = 44,
|
||||||
spacing: int = 28,
|
spacing: int = 28,
|
||||||
@ -111,6 +114,7 @@ def build_character_collages(
|
|||||||
font,
|
font,
|
||||||
missing_paths=missing_paths,
|
missing_paths=missing_paths,
|
||||||
image_filename=image_filename,
|
image_filename=image_filename,
|
||||||
|
label_field=label_field,
|
||||||
image_height=image_height,
|
image_height=image_height,
|
||||||
label_height=label_height,
|
label_height=label_height,
|
||||||
spacing=spacing,
|
spacing=spacing,
|
||||||
|
|||||||
@ -28,17 +28,18 @@ def build_character_sets(
|
|||||||
) -> List[dict]:
|
) -> List[dict]:
|
||||||
"""Associe chaque personnage connu aux sets où il apparaît (hors figurants)."""
|
"""Associe chaque personnage connu aux sets où il apparaît (hors figurants)."""
|
||||||
excluded = set(excluded_characters or [])
|
excluded = set(excluded_characters or [])
|
||||||
seen: set[tuple[str, str, str]] = set()
|
seen: set[tuple[str, str, str, str]] = set()
|
||||||
character_sets: List[dict] = []
|
character_sets: List[dict] = []
|
||||||
for row in minifigs_rows:
|
for row in minifigs_rows:
|
||||||
character = row["known_character"].strip()
|
character = row["known_character"].strip()
|
||||||
fig_num = row["fig_num"].strip()
|
fig_num = row["fig_num"].strip()
|
||||||
|
part_num = row["part_num"].strip()
|
||||||
if character == "" or fig_num == "":
|
if character == "" or fig_num == "":
|
||||||
continue
|
continue
|
||||||
if character in excluded:
|
if character in excluded:
|
||||||
continue
|
continue
|
||||||
set_row = sets_lookup[row["set_num"]]
|
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:
|
if key in seen:
|
||||||
continue
|
continue
|
||||||
character_sets.append(
|
character_sets.append(
|
||||||
@ -49,11 +50,12 @@ def build_character_sets(
|
|||||||
"year": set_row["year"],
|
"year": set_row["year"],
|
||||||
"fig_num": fig_num,
|
"fig_num": fig_num,
|
||||||
"in_collection": set_row["in_collection"],
|
"in_collection": set_row["in_collection"],
|
||||||
|
"part_num": part_num,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
seen.add(key)
|
seen.add(key)
|
||||||
character_sets.sort(
|
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
|
return character_sets
|
||||||
|
|
||||||
@ -61,7 +63,7 @@ def build_character_sets(
|
|||||||
def write_character_sets(destination_path: Path, rows: Sequence[dict]) -> None:
|
def write_character_sets(destination_path: Path, rows: Sequence[dict]) -> None:
|
||||||
"""Écrit le CSV listant les sets par personnage."""
|
"""Écrit le CSV listant les sets par personnage."""
|
||||||
ensure_parent_dir(destination_path)
|
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:
|
with destination_path.open("w", newline="") as csv_file:
|
||||||
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
|
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
|
||||||
writer.writeheader()
|
writer.writeheader()
|
||||||
|
|||||||
@ -36,6 +36,7 @@ def main() -> None:
|
|||||||
DESTINATION_DIR,
|
DESTINATION_DIR,
|
||||||
missing_paths=missing_heads,
|
missing_paths=missing_heads,
|
||||||
image_filename="head.jpg",
|
image_filename="head.jpg",
|
||||||
|
label_field="part_num",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -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:
|
def test_build_character_sets_and_collages(tmp_path: Path) -> None:
|
||||||
"""Construit les apparitions par personnage puis les frises associées."""
|
"""Construit les apparitions par personnage puis les frises associées."""
|
||||||
minifigs_rows = [
|
minifigs_rows = [
|
||||||
{"set_num": "1000-1", "known_character": "Alice", "fig_num": "fig-1"},
|
{"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"},
|
{"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"},
|
{"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"},
|
{"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"},
|
{"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"},
|
{"set_num": "1003-1", "known_character": "Figurant", "fig_num": "fig-4", "part_num": "p4"},
|
||||||
]
|
]
|
||||||
sets_lookup = {
|
sets_lookup = {
|
||||||
"1000-1": {"set_id": "1000", "year": "2020", "in_collection": "true"},
|
"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",
|
"year": "2020",
|
||||||
"fig_num": "fig-1",
|
"fig_num": "fig-1",
|
||||||
"in_collection": "true",
|
"in_collection": "true",
|
||||||
|
"part_num": "p1",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"known_character": "Bob",
|
"known_character": "Bob",
|
||||||
@ -50,6 +51,7 @@ def test_build_character_sets_and_collages(tmp_path: Path) -> None:
|
|||||||
"year": "2021",
|
"year": "2021",
|
||||||
"fig_num": "fig-2",
|
"fig_num": "fig-2",
|
||||||
"in_collection": "false",
|
"in_collection": "false",
|
||||||
|
"part_num": "p2",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"known_character": "Bob",
|
"known_character": "Bob",
|
||||||
@ -58,6 +60,7 @@ def test_build_character_sets_and_collages(tmp_path: Path) -> None:
|
|||||||
"year": "2022",
|
"year": "2022",
|
||||||
"fig_num": "fig-3",
|
"fig_num": "fig-3",
|
||||||
"in_collection": "false",
|
"in_collection": "false",
|
||||||
|
"part_num": "p3",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"known_character": "Claire Dearing",
|
"known_character": "Claire Dearing",
|
||||||
@ -66,6 +69,7 @@ def test_build_character_sets_and_collages(tmp_path: Path) -> None:
|
|||||||
"year": "2024",
|
"year": "2024",
|
||||||
"fig_num": "fig-5",
|
"fig_num": "fig-5",
|
||||||
"in_collection": "true",
|
"in_collection": "true",
|
||||||
|
"part_num": "p5",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user