DOCS/section-event-map-setup.md
Thomas Fransolet c69cb15ba2 D1 corrigé : le bug offline nº1 était 283 lignes de code mort
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 16:57:23 +02:00

16 KiB
Raw Permalink Blame History

Guide : SectionEvent, SectionMap & SectionGame — Configuration et affichage

Cas d'usage typiques : carnaval, parc à thème, festival, musée en plein air, escape game


Vue d'ensemble

La plateforme permet de proposer à un visiteur une vue carte ou une vue liste pour naviguer dans un événement géolocalisé, ou de lancer un escape game (géolocalisé ou non). Les types de section principaux :

Type Usage Contient
SectionMap Carte interactive ou liste de POI GeoPoints, catégories, parcours guidés
SectionEvent Événement avec dates + programme Dates, carte de base, programme horaire, annotations carte, parcours guidés
SectionGame Jeu interactif Puzzle, puzzle glissant, escape game (géolocalisé ou non)

Modèles de données (manager-service)

Section (base commune)

ManagerService/Data/Section.cs

Tous les types héritent de cette classe :

  • Id, Label, Title, Description, Order, Type
  • ConfigurationId, InstanceId, IsActive
  • IsSubSection, ParentId — pour sections imbriquées
  • Latitude, Longitude, BeaconId, MeterZoneGPS — déclenchement géoloc

SectionMap

ManagerService/Data/SubSection/SectionMap.cs

SectionMap
├── MapMapProvider        → Google ou MapBox
├── MapMapType            → Normal / Satellite / Terrain / Hybrid (Google)
├── MapTypeMapbox         → Standard / Streets / Outdoors / Light / Dark / Satellite
├── MapZoom               → Niveau de zoom par défaut (défaut: 18)
├── MapCenterLatitude/Longitude
├── IsListViewEnabled     → ⭐ toggle carte / liste dans la visitapp
├── MapCategories[]       → Catégories de filtrage des points
└── MapPoints[]           → GeoPoints (POI sur la carte)

GeoPoint (POI) :

  • Title, Description, Contents[]
  • Geometry (Point / Polyline / Circle / Polygon)
  • CategorieId — pour le filtrage
  • SectionMapId ou SectionEventId (multi-parent)
  • Schedules, Prices, Phone, Email, Site

SectionEvent

ManagerService/Data/SubSection/SectionEvent.cs

SectionEvent
├── StartDate / EndDate
├── BaseSectionMapId      → ⭐ lien vers une SectionMap (carte de fond)
├── BaseMap               → navigation property vers la SectionMap
├── GlobalMapAnnotations[]→ annotations au niveau de l'événement entier
├── Programme[]           → blocs horaires
└── ParcoursIds[]         → ⚠️ INUTILISÉ (voir GuidedPath.SectionEventId)

ProgrammeBlock (bloc horaire) :

  • StartTime, EndTime
  • Title, Description (traduits)
  • MapAnnotations[] — annotations spécifiques à ce créneau

MapAnnotation :

  • GeometryType : Point / Polyline / Circle / Polygon
  • Geometry (PostGIS)
  • Type (traduit) : "first_aid", "parking", "scène", etc.
  • PolyColor, Icon, IconResourceId
  • SectionEventId (null = annotation de bloc)

SectionGame

ManagerService/Data/SubSection/SectionGame.cs

SectionGame
├── GameType              → Puzzle | SlidingPuzzle | Escape ⭐
├── GameMessageDebut[]    → message d'intro (traduit + media)
├── GameMessageFin[]      → message de fin (traduit + media)
├── GamePuzzleImageId     → image source du puzzle
├── GamePuzzleRows        → nombre de lignes (défaut: 3)
└── GamePuzzleCols        → nombre de colonnes (défaut: 3)

Pour le mode Escape, les parcours guidés sont portés par GuidedPath.SectionGameId (pas de champ direct sur SectionGame).

GuidedPath (Parcours guidé)

ManagerService/Data/SubSection/GuidedPath.cs

Un parcours peut être attaché à une carte ou un événement ou un jeu :

GuidedPath
├── SectionMapId      → lié à une SectionMap (nullable)
├── SectionEventId    → lié à un SectionEvent (nullable)
├── SectionGameId     → lié à un SectionGame (nullable) ⭐ escape game
├── IsLinear          → ordre obligatoire
├── RequireSuccessToAdvance → résoudre une énigme pour avancer
├── HideNextStepsUntilComplete
├── Order
└── Steps[]           → GuidedStep

GuidedStep (étape du parcours) :

  • Geometry, ZoneRadiusMeters — zone de déclenchement géoloc
  • TriggerGeoPointId — peut référencer un GeoPoint
  • IsHiddenInitially, IsStepLocked
  • IsStepTimer, TimerSeconds, TimerExpiredMessage
  • QuizQuestions[] — énigmes/questions à résoudre pour valider l'étape

Endpoints API (manager-service)

SectionEvent → /api/sectionevent/{id}/...

Méthode Route Description
GET /{id}/programmes Tous les blocs horaires
POST /{id}/programmes Créer un bloc
PUT /programmes Modifier un bloc
DELETE /programmes/{blockId} Supprimer un bloc
GET /{id}/global-map-annotations Annotations globales
POST /{id}/global-map-annotations Ajouter annotation globale
DELETE /map-annotations/{annotationId} Supprimer annotation

SectionMap → /api/sectionmap/{id}/...

Méthode Route Description
GET /{id}/points Tous les GeoPoints
POST /{id}/points Créer un GeoPoint
PUT /points Modifier un GeoPoint
DELETE /points/{pointId} Supprimer un GeoPoint
GET /{id}/guided-path Tous les parcours
POST /{id}/guided-path Créer un parcours
PUT /guided-path Modifier un parcours
DELETE /guided-path/{pathId} Supprimer un parcours
GET /guided-path/{pathId}/guided-step Étapes d'un parcours
POST /guided-path/{pathId}/guided-step Créer une étape

Configuration dans le manager-app

EventConfig

manager-app/lib/Screens/Configurations/Section/SubSection/Event/event_config.dart

Interface de configuration d'un SectionEvent :

  1. Dates (début / fin avec date+heure picker)
  2. Carte de base — dropdown des SectionMap disponibles dans la configuration → sette baseSectionMapId
  3. Annotations globales — marqueurs/zones visibles sur toute la durée de l'événement
  4. Programme — blocs horaires avec titre, description, heures
  5. Parcours guidés — via ParcoursConfig(isEvent: true, parentId: eventDTO.id!)

MapConfig

manager-app/lib/Screens/Configurations/Section/SubSection/Map/map_config.dart

Deux onglets :

  • "Points d'intérêt" — CRUD sur les GeoPoints avec filtrage par catégorie
  • "Parcours" — via ParcoursConfig(isEvent: false, parentId: mapId)

Paramètre clé : isListViewEnabled → détermine si la visitapp affiche la carte ou une liste.

GameConfig

manager-app/lib/Screens/Configurations/Section/SubSection/Game/game_config.dart

Interface à 3 onglets selon le GameType :

  1. Puzzle — configuration lignes/colonnes + image source
  2. Puzzle Glissant — idem
  3. Escape Game — intègre ParcoursConfig(isEscapeMode: true, parentId: gameId)

ParcoursConfig

manager-app/lib/Screens/Configurations/Section/SubSection/Parcours/parcours_config.dart

Composant réutilisé pour maps, events et escape games via 3 flags :

Appel Contexte FK créée sur GuidedPath
isEscapeMode: true SectionGame sectionGameId
isEvent: true SectionEvent sectionEventId
les deux à false SectionMap sectionMapId
  • Liste réordrable (drag & drop) des parcours
  • Création/édition via showGuidedPathEditor (Parcours/guided_path_editor.dart, refonte DB4 du 2026-08-11 — remplace les trois popups empilées showNewOrUpdate…)
  • Suppression avec confirmation

showGuidedPathEditor ouvre une fenêtre unique avec un rail d'étapes à gauche et le panneau de détail à droite. On y configure :

  • Titre / description (multilingue)
  • Options : linéaire, réussite requise, cacher les étapes suivantes
  • Les étapes, avec géolocalisation et quiz optionnel — la question se déplie dans le panneau de l'étape

Tout est enregistré à la saisie (débounce ~700 ms) : pas de bouton « Sauvegarder ». Le parcours est créé en base à la première modification, et les questions partent avec leur étape (elles n'ont pas d'endpoint propre).


Affichage dans la visitapp

Routing des sections

mymuseum-visitapp/lib/Screens/section_page.dart

switch(sectionDTO.type) {
  case SectionType.Map:     MapPage(mapDTO)
  case SectionType.Agenda:  AgendaPage(agendaDTO)
  case SectionType.Game:    GamePage(gameDTO)
  // SectionType.Event n'est pas encore géré nativement
}

⚠️ Limitation actuelle : SectionType.Event n'a pas de page dédiée dans la visitapp. Les événements passent actuellement par SectionType.Agenda.

MapPage

mymuseum-visitapp/lib/Screens/Sections/Map/map_page.dart

  • mapDTO.isListViewEnabled → bascule carte / liste
  • Provider : Google (GoogleMapView) ou MapBox (MapBoxView / FlutterMapView)
  • Filtrage par catégorie via GeoPointFilter
  • Tap sur point → détail du GeoPoint

AgendaPage (événements)

mymuseum-visitapp/lib/Screens/Sections/Agenda/agenda_page.dart

  • Grille 2 colonnes d'EventAgenda items
  • Filtrage par mois
  • Tap → EventPopup avec détails

GamePage (jeux)

mymuseum-visitapp/lib/Screens/Sections/Game/game_page.dart

  • Reçoit GameDTO avec gameType
  • Affiche le message d'intro (GameMessageDebut) au lancement
  • Modes Puzzle / SlidingPuzzle : découpe l'image en pièces, gameplay drag & drop, message de fin à la complétion
  • Mode Escape : ⚠️ pas encore implémenté nativement dans la visitapp — gameType n'est pas encore dispatché vers une UI dédiée

Exemple concret : Carnaval / Parc à thème

Setup manager-app

Étape 1 — Créer la SectionMap "Plan du site"

  • Provider : MapBox (Outdoors pour un parc)
  • isListViewEnabled: false (vue carte par défaut)
  • Ajouter les GeoPoints :
    • Manèges / attractions → catégorie "Attractions"
    • Restauration → catégorie "Nourriture"
    • Premiers secours → catégorie "Services"
    • Parkings → catégorie "Accès"

Étape 2 — Créer la SectionEvent "Carnaval 2025"

  • Dates : 17 mars 2025
  • Carte de base : sélectionner "Plan du site" (créé à l'étape 1)
  • Annotations globales :
    • Zones de parade (Polyline)
    • Scène principale (Polygon)
    • Points de premiers secours (Point + icône)
  • Programme :
    • "Parade d'ouverture" — 1 mars 14h-16h (annotation : tracé de la parade)
    • "Spectacle de feu" — chaque soir 21h-22h (annotation : scène)
    • "Feux d'artifice" — 7 mars 22h (annotation : point de lancement)
  • Parcours guidés :
    • "Circuit famille" (linéaire) — 5 étapes vers les attractions family-friendly
    • "Tour photo" (non-linéaire) — spots photos librement visitables
    • "Chasse au trésor" (linéaire, réussite requise) — énigmes géolocalisées

Ce que voit le visiteur

Vue carte (baseSectionMapId défini) :

  • Carte du site avec tous les GeoPoints
  • Filtrage par catégorie (attractions, food, services...)
  • Annotations globales superposées (zones, tracés)
  • Selon l'heure : annotations du bloc programme actif surlignées
  • Onglet / bouton "Parcours" pour lancer un itinéraire guidé

Vue liste (isListViewEnabled: true sur la SectionMap) :

  • Liste des attractions avec détails
  • Horaires par catégorie

Escape Game — fonctionnement détaillé

Deux variantes

Escape game non-géolocalisé

  • Le visiteur progresse en résolvant des énigmes/quiz à chaque étape, sans se déplacer physiquement
  • Les GuidedStep n'ont pas de Geometry ni de ZoneRadiusMeters
  • Typiquement utilisé en intérieur (salle d'exposition, tablette fixe, kiosque)
  • Navigation : l'app passe à l'étape suivante dès que la condition est remplie (RequireSuccessToAdvance)

Escape game géolocalisé

  • Le visiteur doit se rendre physiquement à un endroit pour débloquer une étape
  • Les GuidedStep ont une Geometry (Point avec ZoneRadiusMeters, ou Polygon)
  • Le déclenchement peut aussi passer par un TriggerGeoPointId (un POI de la carte)
  • Typiquement utilisé en extérieur (parc, ville, musée multi-salles)
  • L'app détecte l'entrée dans la zone → débloque l'étape

Configuration d'un escape game dans le manager-app

  1. Créer une SectionGame avec GameType: Escape
  2. Dans l'onglet Escape Game → ajouter un ou plusieurs Parcours via ParcoursConfig(isEscapeMode: true)
  3. Pour chaque parcours, configurer :
    • isLinear : oui = ordre imposé, non = étapes libres
    • requireSuccessToAdvance : oui = résoudre l'énigme avant d'aller au suivant
    • hideNextStepsUntilComplete : oui = étapes masquées tant que non débloquées
  4. Pour chaque étape du parcours :
    • Titre + description (multilingue)
    • (Optionnel) Géométrie + rayon → pour version géolocalisée
    • (Optionnel) TriggerGeoPointId → lier à un POI existant
    • IsStepTimer + TimerSeconds → compte à rebours
    • QuizQuestions[] → énigmes/questions à résoudre

Structure de données

SectionGame (GameType: Escape)
└── GuidedPath[] (via SectionGameId)
    ├── IsLinear, RequireSuccessToAdvance, HideNextStepsUntilComplete
    └── GuidedStep[]
        ├── Title, Description
        ├── Geometry + ZoneRadiusMeters   ← géoloc (optionnel)
        ├── TriggerGeoPointId             ← lien POI (optionnel)
        ├── IsStepTimer, TimerSeconds     ← countdown (optionnel)
        └── QuizQuestions[]               ← énigmes à résoudre

Exemple : Escape game géolocalisé dans un parc à thème

Scénario : "La Quête du Trésor" — 5 énigmes réparties dans le parc, à résoudre dans l'ordre.

Config :

  • SectionGameGameType: Escape
  • 1 GuidedPath : isLinear: true, requireSuccessToAdvance: true, hideNextStepsUntilComplete: true
  • 5 GuidedStep :
    1. Zone fontaine centrale (polygon 10m) → quiz "Que représente cette statue ?"
    2. Zone entrée château (point, rayon 15m) → quiz + timer 60s
    3. Zone jardin secret (polygon) → quiz "Comptez les rosiers rouges"
    4. Zone boutique (point, rayon 5m) → quiz avec image indice
    5. Zone scène finale (polygon) → quiz final → débloque le message de fin

Ce que voit le visiteur (à implémenter dans la visitapp) :

  • Carte avec marqueur de la prochaine étape
  • En approchant → notification de déclenchement
  • Énigme s'affiche → réponse validée → étape suivante révélée
  • Toutes étapes complétées → GameMessageFin affiché

Relation ParcoursIds — clarification

SectionEvent.ParcoursIds (liste de strings en JSONB) est inutilisé :

  • La relation réelle est portée par GuidedPath.SectionEventId (FK)
  • L'app charge les parcours via sectionMapGetAllGuidedPathFromSection(eventId)
  • ParcoursIds est une relique de conception initiale, peut être supprimé

Bugs / limitations connus

Problème Détail
SectionType.Event non géré dans visitapp Passe par SectionType.Agenda, pas de page dédiée
Escape game non affiché dans visitapp GamePage ne dispatche pas sur gameType == Escape
GuidedPath.SectionGameId non mis à jour UpdateGuidedPath() dans le controller ne copie pas sectionGameId depuis le DTO
SectionEvent.ParcoursIds inutilisé Relique, remplacé par GuidedPath.SectionEventId

Hiérarchie de types Section

Section (base)
├── SectionEvent    ← événement avec carte + programme
├── SectionMap      ← carte / liste de POI
├── SectionAgenda   ← agenda d'événements externe (JSON)
├── SectionArticle
├── SectionGame     ← puzzle | puzzle glissant | escape game (géoloc ou non)
├── SectionQuiz
├── SectionVideo
├── SectionWeb
├── SectionPdf
├── SectionMenu
├── SectionSlider
└── SectionWeather