Import campagne : detection des PNJ et creatures notables (bout en bout)

Brain : la phase MAP recense les PNJ NOMMES et creatures uniques (pas les
monstres generiques) avec une courte fiche fidele au livre ; dedoublonnage
inter-morceaux (description la plus complete gardee) ; payload done + npc_count.

Core : CampaignImportProposal.npcs + NpcProposal ; a l apply, creation comme
Npc de la campagne (description -> values[Description], meme convention que
les cartes d action des ateliers) avec anti-doublon par nom.

Web : section de revue PNJ a cases a cocher (coches par defaut, grises si
deja presents), compteurs de progression et recapitulatif mis a jour.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-10 15:36:17 +02:00
parent 5061457f76
commit 092898e379
11 changed files with 272 additions and 40 deletions

View File

@@ -424,6 +424,18 @@ class ArcProposal:
chapters: list[ChapterProposal] = field(default_factory=list)
@dataclass(frozen=True)
class NpcImportProposal:
"""PNJ/créature notable détecté à l'import d'un PDF de campagne.
PNJ NOMMÉS et créatures uniques (boss) — pas les monstres génériques.
`description` = courte fiche (rôle, apparence, motivations, où on le croise).
"""
name: str
description: str = ""
@dataclass(frozen=True)
class CampaignImportResult:
"""Proposition d'arborescence narrative extraite d'un PDF de campagne.
@@ -435,6 +447,9 @@ class CampaignImportResult:
arcs: list[ArcProposal]
page_count: int
ocr_page_count: int
# PNJ/créatures notables détectés au fil des morceaux (proposition, à cocher
# dans l'écran de revue avant création).
npcs: list[NpcImportProposal] = field(default_factory=list)
def counts(self) -> tuple[int, int, int]:
"""(nb arcs, nb chapitres, nb scènes) — pour le diagnostic / la progression."""