Intégration du graphe et du multi-branche pour la partie campagne
This commit is contained in:
64
docs/plan.md
64
docs/plan.md
@@ -513,6 +513,66 @@ L'IA ne reçoit **pas** les binaires — juste un signal de présence (`illustra
|
||||
- URL publique d'une image : `/api/images/{id}/content` (proxy Java — évite d'exposer MinIO directement).
|
||||
- Validation MIME côté `ImageService` : `jpeg/png/webp/gif` uniquement, max 10 Mo.
|
||||
|
||||
## Feature "Branches narratives" ✅ (21 avril 2026, session 7)
|
||||
|
||||
> ✅ **Graphe narratif intra-chapitre livré en 6 étapes.** Une scène peut maintenant pointer vers plusieurs autres scènes du même chapitre selon l'action des joueurs (logique "livre dont vous êtes le héros"). Vue graphique SVG custom (organigramme) accessible depuis `chapter-view`.
|
||||
|
||||
### Cadrage produit
|
||||
- **Scope** : branches intra-chapitre uniquement (cross-chapitre = scène "finale" qui mène au chapitre suivant, logique existante).
|
||||
- **Champ `order` conservé (option A)** : la scène `order=1` devient le point d'entrée du graphe. Possibilité future de migrer vers Option B (`isEntryPoint: boolean`) sans effort majeur.
|
||||
- **Formulaire avant graphe** : édition structurée des branches dans `scene-edit`, visualisation ensuite.
|
||||
|
||||
### Étape 1 — Domain (DDD) ✅
|
||||
- **Nouveau** : `SceneBranch` (Value Object, `@Value @Builder @Jacksonized`) — 3 champs : `label`, `targetSceneId`, `condition`.
|
||||
- **Scene.java** : nouveau champ `List<SceneBranch> branches` + méthodes métier `addBranch()` (garde anti-auto-référence) / `removeBranchTo()`.
|
||||
|
||||
### Étape 2 — Persistance ✅
|
||||
- **Nouveau** : `SceneBranchListJsonConverter` (pattern homogène avec `StringListJsonConverter`, TEXT + JSON via Jackson).
|
||||
- **SceneJpaEntity** : colonne `branches TEXT` avec `@Convert`. Colonne auto-créée par Hibernate `ddl-auto=update`.
|
||||
- **PostgresSceneRepository** : mapping `branches` dans les deux sens avec copies défensives.
|
||||
|
||||
### Étape 3 — API ✅
|
||||
- **Nouveau** : `SceneBranchDTO` (mutable, pour wire Jackson).
|
||||
- **SceneDTO** : champ `branches: List<SceneBranchDTO>`.
|
||||
- **SceneMapper** : helpers `toBranchDTOs()` / `toBranchDomain()` branchés sur `toDTO()` / `toDomain()`.
|
||||
- **Controller inchangé** : `PUT /api/scenes/{id}` accepte déjà les branches via `SceneDTO`.
|
||||
|
||||
### Étape 4 — Service (validation métier) ✅
|
||||
- **SceneService.updateScene()** propage `branches` + appelle `validateBranches()`.
|
||||
- Invariants vérifiés : targetSceneId non vide, pas d'auto-référence, appartenance au même chapitre. Chargement une seule fois des IDs du chapitre (évite N+1).
|
||||
|
||||
### Étape 5 — Frontend (édition) ✅
|
||||
- **campaign.model.ts** : interface `SceneBranch` + champs `branches?` sur `Scene` / `SceneCreate`.
|
||||
- **scene-edit** : nouvelle section expandable "🌿 Branches narratives". Chaque branche = carte avec libellé + `<select>` cibles + condition optionnelle + bouton Retirer. Bouton "+ Ajouter une branche".
|
||||
- Dropdown filtré : la scène courante n'apparaît pas comme cible (impossible de créer une auto-référence depuis l'UI).
|
||||
- Mutation immutable (spread) pour préserver change detection Angular.
|
||||
|
||||
### Étape 6 — Vue graphique (organigramme SVG custom) ✅
|
||||
- **Nouveau composant** `chapter-graph` (route `/campaigns/.../chapters/:id/graph`).
|
||||
- **Layout BFS par niveaux** depuis la scène `order=1` (point d'entrée). Scènes non atteignables regroupées dans un niveau "orphelin" en bas.
|
||||
- **Rendu SVG pur** : pas de dépendance lourde (évite ngx-graph ~200 KB + d3). Nœuds cliquables → ouverture de la scène. Flèches via `marker-end`, labels de branche échelonnés le long de l'arête (fraction `t ∈ [0.25, 0.55]` selon index parmi les sorties du nœud source) pour éviter les chevauchements au milieu.
|
||||
- **Bouton "Carte du chapitre"** dans le header de `chapter-view`.
|
||||
|
||||
### Étape 7 — Visibilité IA des branches ✅ (21 avril 2026, session 7 suite)
|
||||
L'IA voyait les scènes comme une liste plate ; elle peut désormais raisonner sur le graphe narratif.
|
||||
- **Domain Java** : `CampaignStructuralContext.SceneSummary` gagne `branches: List<BranchHint>`. Nouveau VO `BranchHint(label, targetSceneName, condition)` — le nom cible est **résolu côté builder** (l'IA ne voit jamais d'UUID).
|
||||
- **Builder** : `CampaignStructuralContextBuilder.toChapterSummary()` construit une map `id→nom` en une seule passe (évite N+1) puis la passe à `toSceneSummary()` pour la résolution des `targetSceneId`. Fallback `"(scène inconnue)"` si ID orphelin.
|
||||
- **Bridge JSON** : `BrainAiChatClient.sceneSummaryToMap()` sérialise `branches` **uniquement si non vide** (payload léger sur scènes linéaires). `condition` omise si blank.
|
||||
- **Brain Python** : nouveau dataclass `SceneBranchHint` + `SceneSummary.branches` avec `field(default_factory=list)` pour rétrocompat. DTO Pydantic `SceneBranchHintDTO` ajouté ; mapping dans `_to_campaign_context`.
|
||||
- **Prompt (`chat.py`)** : rendu `→ "label" vers TargetSceneName (si : condition)` indenté sous chaque scène. Ligne d'explication ajoutée sous le header campagne pour que l'IA interprète les flèches comme des transitions effectives, pas une décoration.
|
||||
- Validation : `mvn clean compile` OK + `python -m py_compile` OK.
|
||||
|
||||
### Bugfixes post-livraison
|
||||
- **`scene-edit` — dropdown cible vide à l'ouverture** : `<select [value]="branch.targetSceneId">` n'était pas appliqué car les `<option>` en `*ngFor` sont rendues après l'évaluation du binding. Fix : `[selected]` sur chaque option (chaque option contrôle son propre état, indépendant de l'ordre de rendu).
|
||||
- **`expandable-section` — dropdown du `LoreLinkPicker` tronqué** : `overflow: hidden` sur le conteneur clippait les popups en position absolute. Retiré — pas d'animation sur cette section, donc l'overflow était superflu ; les coins arrondis restent intacts (le content n'a pas de background propre).
|
||||
- **`chapter-graph` — labels d'arêtes superposés au milieu** : tous les labels étaient centrés à `(x1+x2)/2`, d'où collision quand plusieurs arêtes traversent la même bande horizontale. Fix : position `t` échelonnée selon l'index parmi les sorties du nœud source.
|
||||
|
||||
### Notes & dette
|
||||
- Layout V1 : lignes droites uniquement (pas de courbes Bézier). Risque de chevauchement si un chapitre a beaucoup de branches croisées — acceptable tant qu'on reste à ≤15 scènes par chapitre. Si besoin, on passera à `ngx-graph` (layout Dagre intégré) ou à un routage d'arêtes style `elkjs`.
|
||||
- Pas encore d'édition des branches directement depuis le graphe (drag des nœuds, ajout visuel d'arête). `scene-edit` reste le point d'entrée d'édition.
|
||||
- `choicesConsequences` (TEXT libre) **conservé** : reste utile pour noter les conséquences narratives non-structurelles qui ne justifient pas une nouvelle scène.
|
||||
- Marquage des scènes orphelines (non atteignables) dans le prompt IA : non fait pour cette itération — à ajouter si les MJ créent fréquemment des îlots narratifs que l'IA devrait signaler.
|
||||
|
||||
## Structure des dossiers
|
||||
|
||||
```
|
||||
@@ -579,6 +639,10 @@ Ces points sont à garder en tête pour de futures refactorisations. Pas bloquan
|
||||
- **Gestion des migrations DB** — actuellement `spring.jpa.hibernate.ddl-auto=update` (auto-alter). Acceptable en dev, **inutilisable en prod** (perte de données possible). À remplacer par Flyway ou Liquibase avant la mise en prod (chaque changement de schéma devra être versionné en fichier SQL).
|
||||
|
||||
## Dernière mise à jour
|
||||
21 avril 2026 (session 7, 3h) — **Branches narratives — étape 7 : visibilité IA + bugfixes** : les branches remontent désormais au system prompt du Brain (domain Java → bridge JSON → Pydantic → `chat.py` avec rendu `→ "label" vers TargetScene`). Résolution `targetSceneId → nom` côté builder pour que l'IA ne voie jamais d'UUID. 3 bugfixes : dropdown cible (`[selected]` sur option), clipping dropdown Lore (`overflow` retiré sur expandable-section), labels graphe échelonnés le long de l'arête.
|
||||
|
||||
21 avril 2026 (session 7) — **Feature "Branches narratives" complète (6 étapes)** : Value Object `SceneBranch` (DDD) + persistance TEXT JSON + validation métier intra-chapitre + formulaire d'édition dans `scene-edit` + vue organigramme SVG custom accessible depuis `chapter-view` (`/graph`). Option A retenue pour l'`order` (point d'entrée = `order=1`). Voir section dédiée "Feature Branches narratives".
|
||||
|
||||
21 avril 2026 (session 6) — **Feature "Illustrations & images" complète (6 étapes)** : MinIO + galeries Arc/Chapter/Scene + refactor `Template.fields` avec types TEXT/IMAGE + champs IMAGE sur Pages + synchro Brain Python (`illustration_count`). Voir section dédiée au-dessus de "Structure des dossiers".
|
||||
|
||||
20 avril 2026 (soir, session 4) — **Split View ↔ Edit : mode consultation livré sur Page / Arc / Chapter / Scene**.
|
||||
|
||||
Reference in New Issue
Block a user