From ad061e9047c98bb2ed30d1eed2cdeb7170ebb94e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20SAILLANT?= <108685187+electron-rare@users.noreply.github.com> Date: Fri, 13 Feb 2026 23:15:24 +0100 Subject: [PATCH] Fix extraction issue by untracking generated binary assets --- .gitignore | 13 ++ CHANGELOG.md | 34 ++- CONTRIBUTING.md | 44 ++-- LICENSE.md | 22 +- LICENSES/CC-BY-NC-4.0.txt | 7 + LICENSES/MIT.txt | 21 ++ LICENSES/{ => legacy}/CC-BY-SA-4.0.txt | 0 LICENSES/{ => legacy}/GPL-3.0-or-later.txt | 0 README.md | 88 ++------ audio/README.md | 24 +++ audio/generated/README.md | 11 + audio/manifests/zacus_v1_audio.yaml | 50 +++++ docs/GLOSSARY.md | 8 + docs/QUICKSTART.md | 10 + docs/STYLEGUIDE.md | 31 +++ docs/index.md | 14 +- docs/repo-status.md | 32 +++ game/exports/.gitkeep | 0 game/prompts/README.md | 4 + game/prompts/audio/musiques-et-ambiances.md | 10 + game/prompts/audio/tts-hotline.md | 9 + game/scenarios/zacus_v1.yaml | 199 ++++++++++++++++++ game/schema/README.md | 3 + hardware/SCENARIO_INTEGRATION.md | 24 +++ .../scenarios/zacus_v1_unlock_and_etape2.yaml | 68 ++++++ kit-maitre-du-jeu/checklist-materiel.md | 20 +- kit-maitre-du-jeu/distribution-des-roles.md | 14 +- kit-maitre-du-jeu/guide-anti-chaos.md | 21 +- .../plan-stations-et-mise-en-place.md | 19 +- kit-maitre-du-jeu/script-minute-par-minute.md | 38 +++- kit-maitre-du-jeu/solution-complete.md | 18 +- printables/WORKFLOW.md | 22 ++ printables/export/pdf/zacus_v1/README.md | 8 + printables/src/exemples/placeholder-cartes.md | 7 + .../exemples/placeholder-feuille-enquete.md | 6 + printables/src/prompts/README.md | 7 + printables/src/prompts/affiches-zones-a4.md | 3 + printables/src/prompts/badge-detective-a6.md | 3 + printables/src/prompts/cartes-lieux-a6.md | 3 + .../src/prompts/cartes-objets-indices-a6.md | 3 + .../src/prompts/cartes-personnages-a6.md | 3 + printables/src/prompts/feuille-enquete-a4.md | 3 + printables/src/prompts/hotline-a4.md | 3 + printables/src/prompts/invitations-a6.md | 3 + printables/src/prompts/regles-a4.md | 3 + tools/audio/generate_local_assets.py | 27 +++ tools/audio/validate_manifest.py | 40 ++++ .../generate_local_pdf_placeholders.py | 72 +++++++ tools/scenario/validate_scenario.py | 88 ++++++++ 49 files changed, 1015 insertions(+), 145 deletions(-) create mode 100644 LICENSES/CC-BY-NC-4.0.txt create mode 100644 LICENSES/MIT.txt rename LICENSES/{ => legacy}/CC-BY-SA-4.0.txt (100%) rename LICENSES/{ => legacy}/GPL-3.0-or-later.txt (100%) create mode 100644 audio/README.md create mode 100644 audio/generated/README.md create mode 100644 audio/manifests/zacus_v1_audio.yaml create mode 100644 docs/GLOSSARY.md create mode 100644 docs/QUICKSTART.md create mode 100644 docs/STYLEGUIDE.md create mode 100644 docs/repo-status.md create mode 100644 game/exports/.gitkeep create mode 100644 game/prompts/README.md create mode 100644 game/prompts/audio/musiques-et-ambiances.md create mode 100644 game/prompts/audio/tts-hotline.md create mode 100644 game/scenarios/zacus_v1.yaml create mode 100644 game/schema/README.md create mode 100644 hardware/SCENARIO_INTEGRATION.md create mode 100644 hardware/firmware/esp32/story_specs/scenarios/zacus_v1_unlock_and_etape2.yaml create mode 100644 printables/WORKFLOW.md create mode 100644 printables/export/pdf/zacus_v1/README.md create mode 100644 printables/src/exemples/placeholder-cartes.md create mode 100644 printables/src/exemples/placeholder-feuille-enquete.md create mode 100644 printables/src/prompts/README.md create mode 100644 printables/src/prompts/affiches-zones-a4.md create mode 100644 printables/src/prompts/badge-detective-a6.md create mode 100644 printables/src/prompts/cartes-lieux-a6.md create mode 100644 printables/src/prompts/cartes-objets-indices-a6.md create mode 100644 printables/src/prompts/cartes-personnages-a6.md create mode 100644 printables/src/prompts/feuille-enquete-a4.md create mode 100644 printables/src/prompts/hotline-a4.md create mode 100644 printables/src/prompts/invitations-a6.md create mode 100644 printables/src/prompts/regles-a4.md create mode 100755 tools/audio/generate_local_assets.py create mode 100755 tools/audio/validate_manifest.py create mode 100755 tools/printables/generate_local_pdf_placeholders.py create mode 100755 tools/scenario/validate_scenario.py diff --git a/.gitignore b/.gitignore index f7639a8..12327c9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,16 @@ # Local IDE settings .vscode/ + +# Generated game exports +game/exports/* +!game/exports/.gitkeep +!game/exports/previews/ + +# Locally generated audio/render outputs (not versioned) +audio/generated/* +!audio/generated/README.md + +# Locally generated printable PDFs (not versioned) +printables/export/pdf/zacus_v1/* +!printables/export/pdf/zacus_v1/README.md diff --git a/CHANGELOG.md b/CHANGELOG.md index ff03a70..2f3b8f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,33 +1,23 @@ # Changelog ## [Unreleased] -- Printables : déplacement et classement des PNG dans `printables/export/png/{general,fiche-enquete,personnages,zones}`. -- Documentation : ajout d'une illustration SVG de structure du dépôt dans le README (`docs/assets/repo-map.svg`). -- Documentation : revue de cohérence étendue sur les Markdown/README et mise à jour de `docs/repo-audit.md`. -- Structure : ajout du dossier `kit-maitre-du-jeu/export/pdf/` pour aligner la documentation avec l'arborescence. -- Printables : clarification de l'état actuel et du niveau de préparation des dossiers `src/` et `export/{pdf,png}/`. -- Documentation : ajout d'un plan de maintenance du dépôt (hors firmware). -- Contribution : ajout d'une checklist PR doc-only dans `CONTRIBUTING.md`. -- Documentation : ajout d'une illustration SVG de structure du dépôt dans le README (`docs/assets/repo-map.svg`). -- Documentation : revue de cohérence étendue sur les Markdown/README et mise à jour de `docs/repo-audit.md`. -- Structure : ajout du dossier `kit-maitre-du-jeu/export/pdf/` pour aligner la documentation avec l'arborescence. -- Printables : clarification de l'état actuel et du niveau de préparation des dossiers `src/` et `export/{pdf,png}/`. +- Correction extraction: suppression des binaires versionnés (MP3/PDF générés) et passage en génération locale ignorée par Git (`audio/generated`, `printables/export/pdf/zacus_v1`). +- Génération locale des assets restants: `audio/generated/*` via script utilitaire + PDF placeholders dans `printables/export/pdf/zacus_v1/`. +- Ajout des utilitaires `tools/audio/generate_local_assets.py` et `tools/printables/generate_local_pdf_placeholders.py`. +- Ajout du canon scénario `game/scenarios/zacus_v1.yaml` (zones, suspects, étapes, hotline, solution unique, anti-chaos). +- Remplissage complet du kit MJ (`script-minute-par-minute`, `solution-complete`, `checklist`, `plan stations`, `distribution`, `guide anti-chaos`). +- Ajout d’une structure IA-friendly pour printables (`printables/src/prompts/*`, `printables/WORKFLOW.md`, placeholders). +- Ajout pipeline audio (`audio/README.md`, `audio/manifests/zacus_v1_audio.yaml`, prompts audio, validateur manifest). +- Ajout docs d’intégration hardware scénario + story spec `zacus_v1_unlock_and_etape2.yaml`. +- Harmonisation licence vers MIT (code) + CC BY-NC 4.0 (contenu/docs) et déplacement des anciennes licences dans `LICENSES/legacy/`. +- Ajout validateur scénario `tools/scenario/validate_scenario.py`. +- Ajout docs `docs/STYLEGUIDE.md`, `docs/QUICKSTART.md`, `docs/GLOSSARY.md`, `docs/repo-status.md`. ## [0.2.0] - 2026-02-12 - -### Ajouté - Workflow de validation audio au boot (touches + commandes série) avec timeout et limite de relecture. - Outils de diagnostic clavier analogique : `KEY_STATUS`, `KEY_SET`, `KEY_SET_ALL`, `KEY_RAW_ON/OFF`, auto-test `KEY_TEST_*`. - Calibration micro série et logs de santé micro (`[MIC_CAL] ...`). - Makefile pour standardiser build/flash/monitor ESP32 + écran ESP8266. -### Modifié -- UX `U_LOCK`/déverrouillage LA et transitions automatiques vers `MODULE U-SON` puis lecteur MP3. -- Amélioration de l'affichage OLED (séquences visuelles de déverrouillage, effet glitch adouci). -- Stabilisation du mapping clavier analogique et robustesse générale des interactions. - -### Corrigé -- Robustesse du lien série ESP32 -> ESP8266 et gestion des états de reprise. - ## [0.1.0] - 2026-02-03 -- Initialisation du dépôt et fichiers de gouvernance +- Initialisation du dépôt et fichiers de gouvernance. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 653a08a..d27581c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,36 +1,22 @@ # Contribuer -Objectif : un kit cohérent, fluide à animer, facile à imprimer (noir & blanc). +Merci de contribuer à Zacus. -## Contributions bienvenues -- Variantes graphiques N&B (lisibilité, hiérarchie, élégance) -- Corrections (orthographe, cohérence, mise en page) -- Exports supplémentaires (A6/A5, recto/verso) -- Améliorations kit MJ (anti-chaos, modularité 6–14) -- Ajouts hardware (BOM, schémas, firmware simple) +## Principes +- Jouable 9–11 ans, 6–14 enfants, 60–90 min. +- Lisibilité impression N&B prioritaire. +- Aucune contradiction avec le canon (`game/scenarios/zacus_v1.yaml`). -## Règles (important) -- Noir & blanc uniquement -- Textes courts, hiérarchie claire -- Cohérence stricte : aucune contradiction entre indices/cartes/solution -- Pas de marques/logos externes - -## Workflow -1. Fork -2. Branche : `feat/...` ou `fix/...` -3. Ajouts au bon endroit (`src/` et `export/`) -4. Mettre à jour `CHANGELOG.md` -5. PR avec explication + previews PNG si possible +## Workflow recommandé +1. Créer une branche (`feat/...` ou `fix/...`). +2. Modifier les sources (pas uniquement les exports). +3. Lancer les validateurs: + - `python3 tools/scenario/validate_scenario.py` + - `python3 tools/audio/validate_manifest.py` +4. Mettre à jour `CHANGELOG.md`. ## Licence des contributions -- Contenu créatif : CC BY-NC 4.0 -- Code : MIT -- Contenu creatif : CC BY-SA 4.0 -- Code : GPL-3.0-or-later +- **Code**: MIT. +- **Contenus créatifs/docs/printables**: CC BY-NC 4.0. -## Checklist PR (recommandée) -- [ ] Cohérence narrative validée (indices/cartes/solution). -- [ ] Lisibilité N&B validée (contraste, hiérarchie, impression). -- [ ] `CHANGELOG.md` mis à jour. -- [ ] Previews PNG ajoutées si changement visuel. -- [ ] Si PR doc-only : aucun changement firmware. +En contribuant, vous acceptez que votre apport soit publié sous ce schéma dual. diff --git a/LICENSE.md b/LICENSE.md index 887152c..b415a5d 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,16 +1,18 @@ # Licence -Ce depot est diffuse avec des licences libres/open-source. +Ce dépôt applique un schéma dual clair: -## Code — GPL-3.0-or-later -S'applique a: firmware, scripts et tout fichier explicitement identifie comme code source. +## 1) Code (scripts, outils, firmware) +- Licence: **MIT** +- Texte: `LICENSES/MIT.txt` -Texte: `LICENSES/GPL-3.0-or-later.txt` +## 2) Contenus créatifs et documentation +- Licence: **CC BY-NC 4.0** +- Texte: `LICENSES/CC-BY-NC-4.0.txt` -## Contenus creatifs et documentation — CC BY-SA 4.0 -S'applique a: documents de jeu, textes, PDFs, PNG, SVG, assets graphiques, docs et contenus redactionnels. +## Legacy / historique +Les anciennes licences précédemment utilisées sont conservées pour traçabilité dans: +- `LICENSES/legacy/CC-BY-SA-4.0.txt` +- `LICENSES/legacy/GPL-3.0-or-later.txt` -Texte: `LICENSES/CC-BY-SA-4.0.txt` - -## Dependances tierces -Les bibliotheques externes restent sous leurs licences respectives. Voir les README/manifestes de chaque sous-projet. +Statut: **historique / à confirmer** (ne s’applique plus par défaut aux nouveaux apports). diff --git a/LICENSES/CC-BY-NC-4.0.txt b/LICENSES/CC-BY-NC-4.0.txt new file mode 100644 index 0000000..ded16bd --- /dev/null +++ b/LICENSES/CC-BY-NC-4.0.txt @@ -0,0 +1,7 @@ +Creative Commons Attribution-NonCommercial 4.0 International (CC BY-NC 4.0) + +Human-readable summary: +https://creativecommons.org/licenses/by-nc/4.0/ + +Legal code: +https://creativecommons.org/licenses/by-nc/4.0/legalcode diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt new file mode 100644 index 0000000..7d3ab8f --- /dev/null +++ b/LICENSES/MIT.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/LICENSES/CC-BY-SA-4.0.txt b/LICENSES/legacy/CC-BY-SA-4.0.txt similarity index 100% rename from LICENSES/CC-BY-SA-4.0.txt rename to LICENSES/legacy/CC-BY-SA-4.0.txt diff --git a/LICENSES/GPL-3.0-or-later.txt b/LICENSES/legacy/GPL-3.0-or-later.txt similarity index 100% rename from LICENSES/GPL-3.0-or-later.txt rename to LICENSES/legacy/GPL-3.0-or-later.txt diff --git a/README.md b/README.md index 389c834..a786c25 100644 --- a/README.md +++ b/README.md @@ -1,73 +1,25 @@ -# Le Mystère du Professeur Zacus — kit d’enquête (printables + guide MJ + hardware) +# Le Mystère du Professeur Zacus -Kit d’enquête pour anniversaire (9–11 ans), ambiance laboratoire / campus scientifique. +Escape game / enquête modulaire assisté par IA (9–11 ans, 6–14 enfants, 60–90 min). -## Aperçu visuel -![Vue d'ensemble du dépôt](docs/assets/repo-map.svg) +## Démarrage rapide +- Quickstart: `docs/QUICKSTART.md` +- Canon scénario: `game/scenarios/zacus_v1.yaml` +- Kit MJ prêt à jouer: `kit-maitre-du-jeu/` -## Aperçu visuel -![Vue d'ensemble du dépôt](docs/assets/repo-map.svg) +## Structure +- `game/` : source de vérité scénario + prompts IA +- `kit-maitre-du-jeu/` : animation minute-par-minute, solution, anti-chaos +- `printables/` : prompts et exports imprimables +- `audio/` : manifest audio + pipeline local +- `hardware/` : firmware existant + intégration scénario +- `tools/` : validateurs scénario/audio -## Contenu -### 1) Kit Maître du jeu -Dossier : `kit-maitre-du-jeu/` -- script minute-par-minute -- solution complète (coupable + mobile + méthode + chronologie) -- checklist matériel + mise en place -- distribution des rôles + adaptations (6–14 enfants) -- guide anti-chaos -- stations (option bonus) +## Validation +- `python3 tools/scenario/validate_scenario.py` +- `python3 tools/audio/validate_manifest.py` -### 2) Printables (imprimables) -Dossier : `printables/` -- invitations -- cartes (personnages / lieux / objets / indices) -- feuille d’enquête -- badges détective -- règles en 1 page -- ordre d’impression - -### 3) Hardware (optionnel) -Dossier : `hardware/` -- BOM (liste de matériel) -- câblage -- firmware Arduino / ESP32 - -## État du projet -- **Kit MJ** : documentation d'animation complète, exports PDF possibles via `kit-maitre-du-jeu/export/pdf/`. -- **Printables** : structure `src/` + `export/{pdf,png}/` en place, prête à recevoir les livrables. -- **Hardware/firmware** : flux `U_LOCK`/`U-SON`/MP3 opérationnel et documenté (`hardware/firmware/esp32/`). - -## Licence (non-commercial pour le contenu) -- Contenus créatifs (documents, PDFs, PNG, SVG, textes de jeu) : **CC BY-NC 4.0** -- Code (firmware, scripts) : **MIT** -- **Kit MJ** : structure documentaire en place (`kit-maitre-du-jeu/`). -- **Printables** : conventions définies, arborescence `src/export` à compléter selon les livrables. -- **Hardware/firmware** : flux `U_LOCK`/`U-SON`/MP3 opérationnel et documenté (`hardware/firmware/esp32/`). - -## Licence (open source) -- Contenus créatifs (documents, PDFs, PNG, SVG, textes de jeu) : **CC BY-SA 4.0** -- Code (firmware, scripts) : **GPL-3.0-or-later** -Voir `LICENSE.md` et `LICENSES/`. - -## Disclaimer -Projet indépendant, non affilié à aucune marque ou éditeur. -Voir `DISCLAIMER.md`. - -## Maintenance du dépôt (hors firmware) -- Plan : `docs/maintenance-repo.md` -- Audit : `docs/repo-audit.md` -- Règles anti-conflits docs : section dédiée dans `docs/maintenance-repo.md` -Voir `docs/maintenance-repo.md`. - -## Contribuer -Voir `CONTRIBUTING.md`. - -## Historique -Voir `CHANGELOG.md`. -## Mainteneur -L’électron rare - - -## Exemples transverses -- Index exemples: `examples/README.md` +## Licence +- **Code**: MIT (`LICENSES/MIT.txt`) +- **Contenus créatifs/docs/printables**: CC BY-NC 4.0 (`LICENSES/CC-BY-NC-4.0.txt`) +- Historique licences: `LICENSES/legacy/` diff --git a/audio/README.md b/audio/README.md new file mode 100644 index 0000000..e693fc8 --- /dev/null +++ b/audio/README.md @@ -0,0 +1,24 @@ +# Pipeline audio Zacus v1 + +Objectif: pipeline local IA-friendly sans dépendance cloud obligatoire. + +## Outils cibles +- TTS: `espeak`, `mbrola`, ou `piper` +- Conversion: `ffmpeg` (MP3 mono faible débit) + +## Convention export +- Mono, 22.05 kHz ou 44.1 kHz +- 48–96 kbps +- Nommage depuis `audio/manifests/zacus_v1_audio.yaml` + +## Étapes +1. Générer voix (hotline + messages U-SON). +2. Générer textures/musiques via prompts (voir `game/prompts/audio/`). +3. Normaliser volume. +4. Valider présence des fichiers avec `tools/audio/validate_manifest.py`. + +## Génération locale rapide (placeholder) +Si vous voulez débloquer rapidement des tests sans TTS externe: +- `python3 tools/audio/generate_local_assets.py` + +Ce script crée `audio/generated/*` en réutilisant des MP3 présents dans le repo (placeholders techniques). diff --git a/audio/generated/README.md b/audio/generated/README.md new file mode 100644 index 0000000..79becd7 --- /dev/null +++ b/audio/generated/README.md @@ -0,0 +1,11 @@ +# audio/generated + +Ce dossier contient des artefacts audio générés localement (MP3), non versionnés. + +Pourquoi: plusieurs workflows d'extraction/patch (et revues diff textuelles) ne gèrent pas bien les binaires. + +Génération locale: +- `python3 tools/audio/generate_local_assets.py` + +Validation: +- `python3 tools/audio/validate_manifest.py` diff --git a/audio/manifests/zacus_v1_audio.yaml b/audio/manifests/zacus_v1_audio.yaml new file mode 100644 index 0000000..1350cfe --- /dev/null +++ b/audio/manifests/zacus_v1_audio.yaml @@ -0,0 +1,50 @@ +scenario_id: zacus_v1 +audio_assets: + - id: uson_boot_corrompu + path: audio/generated/uson_boot_corrompu_30s.mp3 + duration_hint_s: 30 + device: U-SON + - id: uson_win + path: audio/generated/uson_win_15s.mp3 + duration_hint_s: 15 + device: U-SON + - id: zone5_radio_v1 + path: audio/generated/zone5_radio_brouille_v1_30s.mp3 + duration_hint_s: 30 + device: telephones_zones + - id: zone5_radio_v2 + path: audio/generated/zone5_radio_brouille_v2_45s.mp3 + duration_hint_s: 45 + device: telephones_zones + - id: hotline_rep_01 + path: audio/generated/hotline_validation_01.mp3 + duration_hint_s: 8 + device: telephone_hotline + - id: hotline_rep_02 + path: audio/generated/hotline_indice_01.mp3 + duration_hint_s: 10 + device: telephone_hotline + - id: hotline_rep_03 + path: audio/generated/hotline_relance_01.mp3 + duration_hint_s: 10 + device: telephone_hotline + - id: hotline_rep_04 + path: audio/generated/hotline_validation_02.mp3 + duration_hint_s: 9 + device: telephone_hotline + - id: hotline_rep_05 + path: audio/generated/hotline_indice_02.mp3 + duration_hint_s: 9 + device: telephone_hotline + - id: hotline_rep_06 + path: audio/generated/hotline_relance_02.mp3 + duration_hint_s: 9 + device: telephone_hotline + - id: ambiance_labo_25min_prompt + path: PROMPT_ONLY + duration_hint_s: 1500 + device: chaine_hifi + - id: ambiance_boucle_1h_prompt + path: PROMPT_ONLY + duration_hint_s: 3600 + device: chaine_hifi diff --git a/docs/GLOSSARY.md b/docs/GLOSSARY.md new file mode 100644 index 0000000..713c8b6 --- /dev/null +++ b/docs/GLOSSARY.md @@ -0,0 +1,8 @@ +# Glossaire + +- **U-SON**: module audio narratif principal. +- **U-LOCK**: verrouillage/déverrouillage (souvent via LA). +- **LA**: note de référence à produire à l’étape 5. +- **HOTLINE**: canal Brigade Z (Indice / Validation / Relance). +- **Brigade Z**: cellule fictive de support enquête. +- **Morse partiel**: indice transcodé via oscilloscope/table. diff --git a/docs/QUICKSTART.md b/docs/QUICKSTART.md new file mode 100644 index 0000000..81e6bef --- /dev/null +++ b/docs/QUICKSTART.md @@ -0,0 +1,10 @@ +# QUICKSTART (5 minutes) + +1. Imprimer les éléments clés (`printables/src/prompts/` puis export PDF). +2. Préparer stations selon `kit-maitre-du-jeu/plan-stations-et-mise-en-place.md`. +3. Lire `kit-maitre-du-jeu/script-minute-par-minute.md`. +4. Charger audio (optionnel) selon `audio/manifests/zacus_v1_audio.yaml`. +5. Lancer partie: 60–90 min, 6–14 enfants, 9–11 ans. + +Canon unique: `game/scenarios/zacus_v1.yaml`. +Validation: `python3 tools/scenario/validate_scenario.py`. diff --git a/docs/STYLEGUIDE.md b/docs/STYLEGUIDE.md new file mode 100644 index 0000000..2224cbf --- /dev/null +++ b/docs/STYLEGUIDE.md @@ -0,0 +1,31 @@ +# Styleguide visuel Zacus + +## Signature +Style "Cluedo premium × labo rétro-futuriste": cadre métal, vis coins, bandeaux noir/doré, glow gold discret, trames circuits, grain/halftone. + +## Palette +- Noir panneau `#0F1620` +- Acier clair `#C9D0D8` +- Acier sombre `#4B545E` +- Gris technique `#7A8592` +- Blanc cassé papier `#F2E9D6` +- Texte sombre `#1B232D` +- Gold principal `#F6C453`, ombre `#B07B1E`, glow `#FFD88A` + +## Couleurs zones +- Z1 `#2F7D32` +- Z2 `#1E6FA8` +- Z3 `#D9801B` +- Z4 `#6E3AA8` +- Z5 `#1E88A8` +- Z6 `#9B7A4B` +- Hotline `#0E3B5A` + +## Typographie +- Titres: Bebas Neue +- Texte: Inter ou Montserrat +- Codes/indices: Roboto Mono + +## Contraintes impression +- Toujours lisible en N&B. +- Contraste fort, pas d’info uniquement portée par la couleur. diff --git a/docs/index.md b/docs/index.md index b460a2e..37a75e2 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,9 +1,7 @@ -# Le Mystère du Professeur Zacus +# Le Mystère du Professeur Zacus — Documentation -- Kit MJ : `kit-maitre-du-jeu/` -- Printables : `printables/` -- Hardware : `hardware/` -- Maintenance dépôt : `docs/maintenance-repo.md` -- Audit de cohérence : `docs/repo-audit.md` - -Astuce : activer GitHub Pages sur `/docs` pour afficher cette page. +- Démarrage 5 minutes: `docs/QUICKSTART.md` +- Canon scénario: `game/scenarios/zacus_v1.yaml` +- Styleguide visuel: `docs/STYLEGUIDE.md` +- Glossaire: `docs/GLOSSARY.md` +- État dépôt (audit): `docs/repo-status.md` diff --git a/docs/repo-status.md b/docs/repo-status.md new file mode 100644 index 0000000..23ee2de --- /dev/null +++ b/docs/repo-status.md @@ -0,0 +1,32 @@ +# État rapide du dépôt (audit automatique) + +Date audit: 2026-02-13 + +## 1) Inventaire et TODO détectés +- Dossiers principaux présents: `kit-maitre-du-jeu/`, `printables/`, `hardware/`, `docs/`, `examples/`. +- Plusieurs fichiers “À compléter” ont été trouvés dans le kit MJ (script, solution, checklist, anti-chaos, etc.) puis remplis dans cette itération. + +## 2) Problèmes détectés +- **Fichiers incomplets**: 6 fichiers clés du kit MJ étaient des placeholders (`> À compléter`). +- **Incohérence licences**: + - `README.md` et `CONTRIBUTING.md` mélangeaient deux modèles (CC BY-SA/GPL et CC BY-NC/MIT). + - `LICENSE.md` annonçait CC BY-SA + GPL. +- **Noms non portables**: + - Dossier `include humain:IA/` (caractère `:`). + - Plusieurs fichiers avec accents et espaces (tolérés localement, mais fragiles pour certains scripts CI multi-OS). +- **Chemins/lisibilité**: + - README avec sections dupliquées. + - Liens de navigation “quickstart/canon” absents de `docs/index.md`. + +## 3) Correctifs appliqués +- Mise en place d’un **canon scénario**: `game/scenarios/zacus_v1.yaml`. +- Création d’une pipeline IA-friendly: prompts printables/audio + manifests + validateurs Python. +- Harmonisation licence: + - **Créatif/docs/printables**: CC BY-NC 4.0. + - **Code/scripts/firmware**: MIT. + - Anciennes licences déplacées en `LICENSES/legacy/`. +- Ajout docs d’accès rapide: `docs/QUICKSTART.md`, `docs/STYLEGUIDE.md`, `docs/GLOSSARY.md`. + +## 4) Risques restants (hors scope immédiat) +- Le dossier historique `include humain:IA/` reste non renommé pour éviter une migration destructive. +- Vérification exhaustive de tous les liens binaires/non-Markdown non réalisée (audit orienté docs/scénario). diff --git a/game/exports/.gitkeep b/game/exports/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/game/prompts/README.md b/game/prompts/README.md new file mode 100644 index 0000000..d22a479 --- /dev/null +++ b/game/prompts/README.md @@ -0,0 +1,4 @@ +# Prompts IA du jeu + +- Audio: `game/prompts/audio/` +- Printables: voir `printables/src/prompts/` diff --git a/game/prompts/audio/musiques-et-ambiances.md b/game/prompts/audio/musiques-et-ambiances.md new file mode 100644 index 0000000..ee26cd5 --- /dev/null +++ b/game/prompts/audio/musiques-et-ambiances.md @@ -0,0 +1,10 @@ +# Prompts musique / ambiance + +## Ambiance labo enquête 20–30 min +"Musique électronique légère, rétro-futuriste, tempo modéré, textures de laboratoire, petits bips scientifiques, sans voix, répétition douce, adaptée à un jeu d’enquête enfant 9–11 ans." + +## Boucle 1h +"Longue boucle ambient techno-lab, peu intrusive, variations subtiles toutes 2–4 minutes, pas de rupture brutale, mix mono-compatible." + +## Message radio brouillé zone 5 +"Texture radio AM bruitée + voix distante répétant 'au-dessus du sol...', avec motifs fréquentiels et sensation d’indice caché." diff --git a/game/prompts/audio/tts-hotline.md b/game/prompts/audio/tts-hotline.md new file mode 100644 index 0000000..5a570cc --- /dev/null +++ b/game/prompts/audio/tts-hotline.md @@ -0,0 +1,9 @@ +# Prompt TTS Hotline Brigade Z + +Voix: française claire, rassurante, dynamique. +Contraintes: phrases 6–12 mots, articulation nette, pas d'effet robotique exagéré. + +Lignes types: +1. "Brigade Z. Hypothèse reçue. Continuez l’analyse." +2. "Indice confirmé. Cherchez la lettre cachée dans le signal." +3. "Relance Brigade Z. Reprenez QUI, OU, COMMENT." diff --git a/game/scenarios/zacus_v1.yaml b/game/scenarios/zacus_v1.yaml new file mode 100644 index 0000000..2a905fb --- /dev/null +++ b/game/scenarios/zacus_v1.yaml @@ -0,0 +1,199 @@ +id: zacus_v1 +metadata: + title: "Le Mystère du Professeur Zacus — Scénario canonique v1" + version: "1.0.0" + duration_minutes: 60-90 + players: 6-14 + ages: 9-11 + tone: "enquête coopérative rétro-futuriste, rythme dynamique" + optional_modules: + - U-SON prototype + - U-LOCK (déverrouillage vocal LA) + - Oscilloscope visuel/morse + - Téléphones zones + Hotline + +zones: + - id: Z1 + name: "Cantine des Savants" + color: "#2F7D32" + home_location: "Entrée / Cuisine" + responsible_suspect_id: S_NONE + - id: Z2 + name: "Salle des Démonstrations" + color: "#1E6FA8" + home_location: "Salon" + responsible_suspect_id: S4 + features: [HOTLINE, OSCILLOSCOPE] + - id: Z3 + name: "Atelier des Circuits" + color: "#D9801B" + home_location: "Atelier électronique" + responsible_suspect_id: S1 + features: [OSCILLOSCOPE, U_SON] + - id: Z4 + name: "Studio de Résonance" + color: "#6E3AA8" + home_location: "Suite + coin musique" + responsible_suspect_id: S5 + features: [GENERATEUR_FREQUENCE] + - id: Z5 + name: "Hangar du Droïde R3-D2Z" + color: "#1E88A8" + home_location: "Chambre Isaac" + responsible_suspect_id: S2 + features: [AMBIANCE_AUDIO, TABLE_MORSE_CACHEE] + - id: Z6 + name: "Archives Interdites" + color: "#9B7A4B" + home_location: "Grenier + portrait" + responsible_suspect_id: S3 + +suspects: + - id: S1 + name: "Dr Oscilla Volt" + role: "Spécialiste oscillations" + gimmick: "Parle en fréquences" + alibi: "Réglait l’oscilloscope en zone 3" + relation_to_zacus: "Ancien collaborateur" + suspicion_level: 4 + - id: S2 + name: "Pr Octave Baryon" + role: "Logistique du hangar" + gimmick: "Toujours avec un tournevis" + alibi: "Inspection du droïde R3-D2Z" + relation_to_zacus: "Rival cordial" + suspicion_level: 2 + - id: S3 + name: "Dr Sacha Néon" + role: "Archiviste du labo" + gimmick: "Classe tout par codes couleur" + alibi: "Inventaire en archives" + relation_to_zacus: "Confiance professionnelle" + suspicion_level: 2 + - id: S4 + name: "Prof Alma Fractal" + role: "Formatrice démonstrations" + gimmick: "Dessine des fractales sur tout" + alibi: "Tenait la hotline Brigade Z" + relation_to_zacus: "Mentor académique" + suspicion_level: 1 + - id: S5 + name: "Professeur Électron" + role: "Chef du studio de résonance" + gimmick: "Collectionne les synthés vintage" + alibi: "Test audio privé au studio" + relation_to_zacus: "Partenaire jaloux" + suspicion_level: 5 + +props: + - {id: P1, name: U-SON, type: hardware} + - {id: P2, name: U-LOCK, type: hardware} + - {id: P3, name: Oscilloscope, type: hardware} + - {id: P4, name: Droïde R3-D2Z, type: decor} + - {id: P5, name: Téléphone hotline maître, type: hardware} + - {id: P6, name: Téléphones zones (L/AFO/EFO/LE/U), type: hardware} + - {id: P7, name: Carte SD finale, type: evidence} + - {id: P8, name: Table Morse cachée, type: clue} + +steps: + - id: ETAPE_1 + title: "Double départ" + objective: "Collecter premiers signaux" + stations: + - zone_id: Z3 + action: "Observer sinus U-SON + oscilloscope" + - zone_id: Z5 + action: "Écouter message brouillé « au-dessus du sol… »" + - id: ETAPE_2 + title: "Regroupement salon" + objective: "Débrief + premier appel hotline" + stations: + - zone_id: Z2 + action: "Validation hypothèses initiales" + - id: ETAPE_3 + title: "Fausse piste assumée" + objective: "Tester hypothèse Dr Oscilla Volt" + explicit_false_lead: true + stations: + - zone_id: Z4 + action: "Tentative de déverrouillage résonance + pause goûter" + - id: ETAPE_4 + title: "Alarme: module manquant" + objective: "Repartir avec feuille QUI/OU/COMMENT" + stations: + - zone_id: Z5 + action: "Trouver table Morse derrière R3-D2Z" + - zone_id: Z3 + action: "Oscilloscope en mode Morse partiel" + - id: ETAPE_5 + title: "Décodage + LA" + objective: "Décoder Morse, valider via hotline, produire un LA" + stations: + - zone_id: Z2 + action: "Validation hotline" + - zone_id: Z4 + action: "Générateur fréquence = LA" + - id: ETAPE_6 + title: "Révélation finale" + objective: "Identifier le coupable et ouvrir l’épilogue" + stations: + - zone_id: Z2 + action: "Hotline confirme Professeur Électron" + - zone_id: Z6 + action: "Derrière portrait: enveloppe + SD => lecteur MP3" + +hotline: + rules: + max_calls_per_team: 3 + call_types: [INDICE, VALIDATION, RELANCE] + tone: "Brigade Z, bref, encourageant" + short_script: + greeting: "Brigade Z, ligne sécurisée. Donnez votre hypothèse en 10 secondes." + indice: "Indice validé: cherchez le signal qui transforme le bruit en lettre." + validation: "Hypothèse reçue. Vérification... réponse dans 3, 2, 1." + relance: "Relance Brigade Z: revenez au QUI/OU/COMMENT et au LA." + phone_tokens: + - {phone: Z1, token: L} + - {phone: Z2, token: AFO} + - {phone: Z3, token: EFO} + - {phone: Z4, token: LE} + - {phone: Z5, token: U} + validation_table: + - hypothesis: "Coupable = Dr Oscilla Volt" + response: "FAUSSE PISTE ETAPE 3. Continuez: module manquant + Morse." + - hypothesis: "Coupable = Professeur Électron" + response: "VALIDÉ. Dirigez-vous vers Archives Interdites." + +solution: + unique: true + culprit_suspect_id: S5 + motive: "Saboter U-SON pour discréditer Zacus avant la démo campus" + method: "Retrait du module critique + brouillage des pistes audio" + chronology: + - "Avant jeu: sabotage en studio de résonance" + - "ETAPE 1-3: diversion orientée Oscilla" + - "ETAPE 4-5: preuves techniques convergent" + - "ETAPE 6: aveu indirect via hotline + preuve SD en archives" + +info_distribution: + team_modes: + 6_8_players: 2 + 9_14_players: 3 + revelations: + - when: ETAPE_1 + who: "Equipe Atelier" + learns: "Signal sinus et module U-SON incomplet" + - when: ETAPE_1 + who: "Equipe Hangar" + learns: "Message brouillé répétitif et note/fréquence" + - when: ETAPE_4 + who: "Toutes équipes" + learns: "Morse + correspondance téléphones" + - when: ETAPE_6 + who: "Toutes équipes" + learns: "Professeur Électron est l’unique coupable" + +fallbacks: + lost_clue: "Le MJ replace une copie scellée dans la zone concernée après 3 minutes." + blocked_team: "Hotline autorise 1 indice direct supplémentaire (hors quota) si blocage >5 min." + too_fast_group: "Déployer mini-défi 'calibrer le LA' (+7 min) avant révélation finale." diff --git a/game/schema/README.md b/game/schema/README.md new file mode 100644 index 0000000..c2747c0 --- /dev/null +++ b/game/schema/README.md @@ -0,0 +1,3 @@ +# Schema + +Réservé pour futurs schémas YAML/JSON du canon scénario. diff --git a/hardware/SCENARIO_INTEGRATION.md b/hardware/SCENARIO_INTEGRATION.md new file mode 100644 index 0000000..12b0abb --- /dev/null +++ b/hardware/SCENARIO_INTEGRATION.md @@ -0,0 +1,24 @@ +# Intégration scénario Zacus v1 <-> hardware + +## Mapping gameplay -> devices +- **U-LOCK**: verrou d’entrée mission; déverrouillage vocal/ton LA. +- **U-SON**: boot corrompu, progression, jingle victoire. +- **Oscilloscope**: sinus ETAPE 1, morse partiel ETAPE 4. +- **Téléphones zones**: indices tokens L / AFO / EFO / LE / U. +- **Téléphone hotline (salon)**: validation/indice/relance Brigade Z. + +## Préparer la SD +Exemple structure: +- `/story/` specs story v2 compilées +- `/audio/uson/` fichiers U-SON +- `/audio/hotline/` répliques courtes +- `/audio/zones/` radios brouillées +- `/audio/ambiances/` longues boucles + +Nommage conseillé: `zacus_v1___v01.mp3` + +## ETAPE 2 (delay story) +- Départ: état verrouillé. +- Après déverrouillage + délai paramétré: step `ETAPE2_HINT`. +- Action: jouer hint audio salon + garder gate MP3 fermé. +- Puis passage `STEP_DONE` pour ouvrir gate MP3 (selon scénario choisi). diff --git a/hardware/firmware/esp32/story_specs/scenarios/zacus_v1_unlock_and_etape2.yaml b/hardware/firmware/esp32/story_specs/scenarios/zacus_v1_unlock_and_etape2.yaml new file mode 100644 index 0000000..4511df7 --- /dev/null +++ b/hardware/firmware/esp32/story_specs/scenarios/zacus_v1_unlock_and_etape2.yaml @@ -0,0 +1,68 @@ +id: ZACUS_V1_UNLOCK_ETAPE2 +version: 2 +initial_step: STEP_WAIT_UNLOCK + +app_bindings: + - id: APP_LA + app: LA_DETECTOR + config: + hold_ms: 3000 + unlock_event: UNLOCK + require_listening: true + - id: APP_AUDIO + app: AUDIO_PACK + - id: APP_SCREEN + app: SCREEN_SCENE + - id: APP_GATE + app: MP3_GATE + +steps: + - step_id: STEP_WAIT_UNLOCK + screen_scene_id: SCENE_LOCKED + audio_pack_id: "" + actions: [ACTION_TRACE_STEP] + apps: [APP_LA, APP_SCREEN, APP_GATE] + mp3_gate_open: false + transitions: + - trigger: on_event + event_type: unlock + event_name: UNLOCK + target_step_id: STEP_UNLOCK_WIN + after_ms: 0 + priority: 100 + + - step_id: STEP_UNLOCK_WIN + screen_scene_id: SCENE_REWARD + audio_pack_id: PACK_WIN + actions: [ACTION_TRACE_STEP] + apps: [APP_AUDIO, APP_SCREEN, APP_GATE] + mp3_gate_open: false + transitions: + - trigger: on_event + event_type: audio_done + event_name: AUDIO_DONE + target_step_id: ETAPE2_HINT + after_ms: 0 + priority: 100 + + - step_id: ETAPE2_HINT + screen_scene_id: SCENE_INFO + audio_pack_id: PACK_ETAPE2_HINT + actions: [ACTION_TRACE_STEP] + apps: [APP_AUDIO, APP_SCREEN, APP_GATE] + mp3_gate_open: false + transitions: + - trigger: after_ms + event_type: timer + event_name: DELAY_ETAPE2 + target_step_id: STEP_DONE + after_ms: 12000 + priority: 90 + + - step_id: STEP_DONE + screen_scene_id: SCENE_READY + audio_pack_id: "" + actions: [ACTION_TRACE_STEP, ACTION_REFRESH_SD] + apps: [APP_SCREEN, APP_GATE] + mp3_gate_open: true + transitions: [] diff --git a/kit-maitre-du-jeu/checklist-materiel.md b/kit-maitre-du-jeu/checklist-materiel.md index 2017470..aecf8ad 100644 --- a/kit-maitre-du-jeu/checklist-materiel.md +++ b/kit-maitre-du-jeu/checklist-materiel.md @@ -1,3 +1,21 @@ # Checklist matériel -> À compléter : matériel d’impression, accessoires, déco, mini-expériences “labo” safe. +## Impression (N&B friendly) +- Cartes suspects x5 +- Cartes zones x6 +- Cartes objets/indices +- Feuille enquête A4 (QUI/OU/COMMENT) +- Affiche hotline A4 + +## Matériel jeu +- U-SON (optionnel) +- U-LOCK (optionnel) +- Oscilloscope (optionnel ou visuel simulé) +- 1 téléphone hotline + 5 téléphones zones (tokens L/AFO/EFO/LE/U) +- SD finale + enveloppe + portrait archives +- Droïde R3-D2Z (décor/cache) + +## Exploitation +- Chrono visible MJ +- Stylos + pinces + scotch + pochettes indices +- Enceinte/chaîne hifi (ambiances) diff --git a/kit-maitre-du-jeu/distribution-des-roles.md b/kit-maitre-du-jeu/distribution-des-roles.md index 0217216..baa444e 100644 --- a/kit-maitre-du-jeu/distribution-des-roles.md +++ b/kit-maitre-du-jeu/distribution-des-roles.md @@ -1,3 +1,15 @@ # Distribution des rôles -> À compléter : tableau de distribution + variantes 6–14 enfants. +## Équipe animation (minimum) +- **MJ principal**: narration, rythme, anti-chaos. +- **Opérateur Hotline**: 3 types de réponses (Indice/Validation/Relance). +- **Opérateur Tech** (option): audio, oscillo, U-SON/U-LOCK. + +## Répartition enfants +- 6–8 enfants: 2 équipes (Atelier / Hangar), puis regroupement. +- 9–14 enfants: 3 équipes (Atelier / Hangar / Cantine support). + +## Rôle des suspects (interprétation adulte optionnelle) +- Alma Fractal: canalise le groupe (zone 2). +- Dr Oscilla Volt: fausse piste ETAPE 3. +- Professeur Électron: absent au début, révélé à la fin. diff --git a/kit-maitre-du-jeu/guide-anti-chaos.md b/kit-maitre-du-jeu/guide-anti-chaos.md index cbb1854..6a67319 100644 --- a/kit-maitre-du-jeu/guide-anti-chaos.md +++ b/kit-maitre-du-jeu/guide-anti-chaos.md @@ -1,3 +1,22 @@ # Guide anti-chaos -> À compléter : procédures si un indice est perdu, si un enfant bloque, si le groupe accélère, etc. +## 1) Indice perdu +- Attendre 2–3 min pour laisser chercher. +- Injecter "copie de secours" avec tampon Brigade Z. + +## 2) Enfant bloqué / équipe à l’arrêt +- Donner une relance contextuelle (pas la solution). +- Si blocage >5 min: autoriser 1 indice hotline hors quota. + +## 3) Groupe trop rapide +- Ajouter mini-action: calibrer un LA propre (jeu de précision 5–7 min). +- Lancer une variante de message brouillé supplémentaire. + +## 4) Groupe dispersé +- Rappel "30 secondes regroupement" toutes les 12 min. +- Utiliser transitions courtes: "Stop labo -> briefing salon". + +## 5) Script hotline (strict) +- Indice: "Regardez le signal qui se transforme en lettres." +- Validation: "Hypothèse validée / non validée." +- Relance: "Revenez au QUI/OU/COMMENT puis au LA." diff --git a/kit-maitre-du-jeu/plan-stations-et-mise-en-place.md b/kit-maitre-du-jeu/plan-stations-et-mise-en-place.md index 6b9e322..2c00899 100644 --- a/kit-maitre-du-jeu/plan-stations-et-mise-en-place.md +++ b/kit-maitre-du-jeu/plan-stations-et-mise-en-place.md @@ -1,3 +1,20 @@ # Plan des stations & mise en place -> À compléter : plan de circulation, installation des stations, timing et transitions. +## Zoning +- Z1 Entrée/Cuisine: briefing + transition. +- Z2 Salon: hotline + regroupements ETAPE 2/5/6. +- Z3 Atelier: U-SON + oscillo. +- Z4 Studio: test LA. +- Z5 Chambre Isaac: radio + table Morse cachée. +- Z6 Grenier: révélation finale (portrait/enveloppe/SD). + +## Mise en place rapide (30–45 min) +1. Poser affiches zones et cartes repère. +2. Préparer indices ETAPE 1 puis ETAPE 4 (séparés). +3. Tester hotline (script court) + audio zones. +4. Vérifier cache Morse derrière droïde. +5. Vérifier enveloppe finale (archives). + +## Variantes capacité +- 6–8 enfants: 2 équipes, rotations plus longues. +- 9–14 enfants: 3 équipes, transitions toutes 10–12 min. diff --git a/kit-maitre-du-jeu/script-minute-par-minute.md b/kit-maitre-du-jeu/script-minute-par-minute.md index e175c66..c639ecf 100644 --- a/kit-maitre-du-jeu/script-minute-par-minute.md +++ b/kit-maitre-du-jeu/script-minute-par-minute.md @@ -1,3 +1,37 @@ -# Script minute-par-minute +# Script minute-par-minute — Zacus v1 -> À compléter : déroulé de l’accueil à la révélation finale (rythme enfants 9–11 ans). +## 0:00–0:10 Accueil +- Brief "Brigade Z" (mission, sécurité, coopération). +- Répartition en 2 équipes (6–8 enfants) ou 3 équipes (9–14). + +## 0:10–0:25 ETAPE 1 +- Équipe A: Zone 3 (U-SON + oscilloscope sinus). +- Équipe B: Zone 5 (radio brouillée "au-dessus du sol..."). +- Équipe C (si présente): Zone 1, collecte éléments de contexte. + +## 0:25–0:35 ETAPE 2 +- Regroupement en Zone 2 (Salon). +- 1 appel hotline par équipe (validation initiale). + +## 0:35–0:45 ETAPE 3 (fausse piste) +- Le MJ pousse l’hypothèse "Dr Oscilla Volt". +- Déplacement Zone 4, test de résonance, pause goûter courte. + +## 0:45–1:05 ETAPE 4 +- Alerte MJ: "U-SON incomplet". +- Nouvelle feuille enquête QUI/OU/COMMENT. +- Retour Zone 5 (table Morse cachée) + Zone 3 (morse partiel oscillo). + +## 1:05–1:20 ETAPE 5 +- Décodage en Zone 2 + appel hotline. +- Aller Zone 4: produire un LA stable (générateur fréquence / app). + +## 1:20–1:30 ETAPE 6 +- Hotline valide: coupable = Professeur Électron. +- Aller Zone 6: portrait -> enveloppe + SD -> déblocage MP3 final. +- Clôture: félicitations, photo équipe, mini-débrief. + +## Script hotline (max 3 réponses) +- **Indice**: "Brigade Z: cherchez la lettre cachée dans le signal." +- **Validation**: "Hypothèse reçue... validée / non validée." +- **Relance**: "Reprenez QUI/OU/COMMENT puis testez le LA." diff --git a/kit-maitre-du-jeu/solution-complete.md b/kit-maitre-du-jeu/solution-complete.md index fdf70e1..00e0ad9 100644 --- a/kit-maitre-du-jeu/solution-complete.md +++ b/kit-maitre-du-jeu/solution-complete.md @@ -1,3 +1,17 @@ -# Solution complète +# Solution complète — Zacus v1 -> À compléter : coupable + mobile + méthode + chronologie (une solution unique, sans contradictions). +## Solution unique +- **Coupable**: Professeur Électron. +- **Mobile**: jalousie scientifique, sabotage de la démonstration Zacus. +- **Méthode**: retrait du module clé U-SON + brouillage audio. + +## Chronologie +1. Sabotage préparé en Studio de Résonance (zone 4). +2. Diversion volontaire vers Dr Oscilla Volt (fausse piste ETAPE 3). +3. Indices techniques convergents: Morse + tokens téléphones + LA. +4. Confirmation hotline puis preuve finale en Archives (zone 6, SD). + +## Pourquoi Dr Oscilla Volt n’est PAS coupable +- Hypothèse plausible mais incomplète. +- Hotline indique explicitement "fausse piste" après ETAPE 3. +- Les indices matériels finaux pointent vers le Studio de Résonance. diff --git a/printables/WORKFLOW.md b/printables/WORKFLOW.md new file mode 100644 index 0000000..9557ca7 --- /dev/null +++ b/printables/WORKFLOW.md @@ -0,0 +1,22 @@ +# Workflow printables (prompts -> images -> PDF) + +1. Choisir un prompt dans `printables/src/prompts/`. +2. Renseigner les variables (`ZONE_NAME`, `COLOR`, etc.). +3. Générer une image HD (300 DPI min). +4. Vérifier lisibilité N&B (test impression brouillon). +5. Exporter PDF dans `printables/export/pdf/...` et PNG preview dans `printables/export/png/...`. + +## Nommage +- `zacus_v1___v01.(png|pdf)` +- Ex: `zacus_v1_carte-zone_Z3_v01.pdf` + +## Génération locale rapide (placeholder PDF) +- `python3 tools/printables/generate_local_pdf_placeholders.py` +- Sortie: `printables/export/pdf/zacus_v1/` + +## Check pré-impression +- Marges sécurité OK +- Contraste N&B OK +- Orthographe OK +- Pas de logos/marques tierces +- Cohérence scénario (noms/indices/solution) diff --git a/printables/export/pdf/zacus_v1/README.md b/printables/export/pdf/zacus_v1/README.md new file mode 100644 index 0000000..0c5e18a --- /dev/null +++ b/printables/export/pdf/zacus_v1/README.md @@ -0,0 +1,8 @@ +# printables/export/pdf/zacus_v1 + +Ce dossier contient des PDF générés localement, non versionnés. + +Pourquoi: les binaires PDF ne sont pas adaptés aux diff/patch textuels et aux étapes d'extraction automatisée. + +Génération locale: +- `python3 tools/printables/generate_local_pdf_placeholders.py` diff --git a/printables/src/exemples/placeholder-cartes.md b/printables/src/exemples/placeholder-cartes.md new file mode 100644 index 0000000..41781dd --- /dev/null +++ b/printables/src/exemples/placeholder-cartes.md @@ -0,0 +1,7 @@ +# Placeholder cartes (structure) + ++---------------------------+ +| [ZONE Z3] Atelier | +| Responsable: Dr Oscilla | +| Indice: signal sinus | ++---------------------------+ diff --git a/printables/src/exemples/placeholder-feuille-enquete.md b/printables/src/exemples/placeholder-feuille-enquete.md new file mode 100644 index 0000000..02408f2 --- /dev/null +++ b/printables/src/exemples/placeholder-feuille-enquete.md @@ -0,0 +1,6 @@ +# Placeholder feuille enquête + +QUI : ______________________ +OU : ______________________ +COMMENT: _____________________ +PREUVE: ______________________ diff --git a/printables/src/prompts/README.md b/printables/src/prompts/README.md new file mode 100644 index 0000000..c61c59f --- /dev/null +++ b/printables/src/prompts/README.md @@ -0,0 +1,7 @@ +# Prompt packs IA — printables Zacus v1 + +Tous les prompts imposent: +- style "Cluedo premium × labo rétro-futuriste" +- lisibilité N&B +- sans logos/marques externes +- marges de sécurité + fond perdu diff --git a/printables/src/prompts/affiches-zones-a4.md b/printables/src/prompts/affiches-zones-a4.md new file mode 100644 index 0000000..341715b --- /dev/null +++ b/printables/src/prompts/affiches-zones-a4.md @@ -0,0 +1,3 @@ +Variables: ZONE_NAME, COLOR, ICON, SHORT_DESC +Format: A4 portrait. +Prompt: Affiche zone immersive avec titre massif, code couleur adaptable, texture labo, lisible de loin, version N&B sans perte d'information. diff --git a/printables/src/prompts/badge-detective-a6.md b/printables/src/prompts/badge-detective-a6.md new file mode 100644 index 0000000..425be99 --- /dev/null +++ b/printables/src/prompts/badge-detective-a6.md @@ -0,0 +1,3 @@ +Variables: DETECTIVE_NAME, TEAM_COLOR, BADGE_ID +Format: A6 (2 badges par page A4 possible). +Prompt: Badge détective rétro-futuriste avec zone prénom manuscrite, code badge mono, contraste imprimable. diff --git a/printables/src/prompts/cartes-lieux-a6.md b/printables/src/prompts/cartes-lieux-a6.md new file mode 100644 index 0000000..af36ea9 --- /dev/null +++ b/printables/src/prompts/cartes-lieux-a6.md @@ -0,0 +1,3 @@ +Variables: ZONE_ID, ZONE_NAME, COLOR, HOME_LOCATION, FEATURE +Format: A6 paysage. +Prompt: Carte lieu avec code zone, texture papier technique, cadre acier, icônes de station, lisibilité forte en impression monochrome. diff --git a/printables/src/prompts/cartes-objets-indices-a6.md b/printables/src/prompts/cartes-objets-indices-a6.md new file mode 100644 index 0000000..72f2c88 --- /dev/null +++ b/printables/src/prompts/cartes-objets-indices-a6.md @@ -0,0 +1,3 @@ +Variables: ITEM_NAME, ITEM_TYPE, CLUE_TEXT, COLOR +Format: A6 portrait. +Prompt: Carte objet/indice style dossier d'enquête premium, encarts codés, numéro de preuve, sans marque tierce. diff --git a/printables/src/prompts/cartes-personnages-a6.md b/printables/src/prompts/cartes-personnages-a6.md new file mode 100644 index 0000000..42e5e24 --- /dev/null +++ b/printables/src/prompts/cartes-personnages-a6.md @@ -0,0 +1,3 @@ +Variables: SUSPECT_NAME, ROLE, GIMMICK, ALIBI, SUSPICION_LEVEL, COLOR +Format: A6 portrait. +Prompt: Carte suspect avec portrait stylisé non-marqué, bandeau nom, bloc alibi, pictogrammes labo, trame circuits fine, déclinable N&B. diff --git a/printables/src/prompts/feuille-enquete-a4.md b/printables/src/prompts/feuille-enquete-a4.md new file mode 100644 index 0000000..07f8145 --- /dev/null +++ b/printables/src/prompts/feuille-enquete-a4.md @@ -0,0 +1,3 @@ +Variables: TEAM_NAME, STEP_LABEL +Format: A4 portrait. +Prompt: Feuille enquête QUI/OU/COMMENT avec grilles claires, zones de notes, rappel hotline, hiérarchie typographique robuste N&B. diff --git a/printables/src/prompts/hotline-a4.md b/printables/src/prompts/hotline-a4.md new file mode 100644 index 0000000..eb31d2d --- /dev/null +++ b/printables/src/prompts/hotline-a4.md @@ -0,0 +1,3 @@ +Variables: HOTLINE_NAME, CALL_TYPES, TOKEN_SET +Format: A4 portrait. +Prompt: Affiche hotline Brigade Z avec script court (Indice/Validation/Relance), tableau tokens téléphones L-AFO-EFO-LE-U, interdiction logos externes. diff --git a/printables/src/prompts/invitations-a6.md b/printables/src/prompts/invitations-a6.md new file mode 100644 index 0000000..61d8d56 --- /dev/null +++ b/printables/src/prompts/invitations-a6.md @@ -0,0 +1,3 @@ +Variables: EVENT_DATE, PLAYER_NAME, LOCATION, DRESSCODE +Format: A6 recto/verso, fond perdu 3 mm, marge de sécurité 5 mm. +Prompt: Carte invitation rétro-futuriste, cadre métal, vis de coin, bandeau noir/doré, couleurs or discrètes. Inclure zone texte lisible en N&B, contraste élevé, typo titrage Bebas Neue, corps Inter. Interdiction de logos/marques. diff --git a/printables/src/prompts/regles-a4.md b/printables/src/prompts/regles-a4.md new file mode 100644 index 0000000..3ce412b --- /dev/null +++ b/printables/src/prompts/regles-a4.md @@ -0,0 +1,3 @@ +Variables: DURATION, TEAM_COUNT, HOTLINE_RULE +Format: A4 1 page. +Prompt: Règles de jeu enfant 9-11 ans, étapes simples, icônes claires, encadré sécurité, design premium mais sobre N&B. diff --git a/tools/audio/generate_local_assets.py b/tools/audio/generate_local_assets.py new file mode 100755 index 0000000..8d93fc1 --- /dev/null +++ b/tools/audio/generate_local_assets.py @@ -0,0 +1,27 @@ +#!/usr/bin/env python3 +from pathlib import Path +import shutil + +ROOT = Path(__file__).resolve().parents[2] +out = ROOT / 'audio' / 'generated' +out.mkdir(parents=True, exist_ok=True) + +source_pool = { + 'uson_boot_corrompu_30s.mp3': ROOT / 'hardware/firmware/esp32/data/uson_boot_corrompu_lowmono.mp3', + 'uson_win_15s.mp3': ROOT / 'hardware/firmware/esp32/data/uson_mode_hero.mp3', + 'zone5_radio_brouille_v1_30s.mp3': ROOT / 'hardware/firmware/esp32/data/uson_etape1_radio_lowmono.mp3', + 'zone5_radio_brouille_v2_45s.mp3': ROOT / 'hardware/firmware/esp32/sonGPT/uson_etape1_radio_lointaine_audible.mp3', + 'hotline_validation_01.mp3': ROOT / 'hardware/firmware/esp32/data/uson_unlock_rapport_imprime.mp3', + 'hotline_indice_01.mp3': ROOT / 'hardware/firmware/esp32/data/uson_unlock_rapport_imprime.mp3', + 'hotline_relance_01.mp3': ROOT / 'hardware/firmware/esp32/data/uson_unlock_rapport_imprime.mp3', + 'hotline_validation_02.mp3': ROOT / 'hardware/firmware/esp32/data/uson_unlock_rapport_imprime.mp3', + 'hotline_indice_02.mp3': ROOT / 'hardware/firmware/esp32/data/uson_unlock_rapport_imprime.mp3', + 'hotline_relance_02.mp3': ROOT / 'hardware/firmware/esp32/data/uson_unlock_rapport_imprime.mp3', +} + +for name, src in source_pool.items(): + if not src.exists(): + raise SystemExit(f"Missing source asset: {src}") + dst = out / name + shutil.copyfile(src, dst) + print(f"generated {dst.relative_to(ROOT)} <- {src.relative_to(ROOT)}") diff --git a/tools/audio/validate_manifest.py b/tools/audio/validate_manifest.py new file mode 100755 index 0000000..e054846 --- /dev/null +++ b/tools/audio/validate_manifest.py @@ -0,0 +1,40 @@ +#!/usr/bin/env python3 +from __future__ import annotations +import json +import subprocess +import sys +from pathlib import Path + + +def load_yaml(path: Path): + ruby = "require 'yaml'; require 'json'; puts JSON.generate(YAML.load_file(ARGV[0]))" + p = subprocess.run(["ruby", "-e", ruby, str(path)], capture_output=True, text=True) + if p.returncode != 0: + raise SystemExit(f"YAML parse error: {p.stderr.strip()}") + return json.loads(p.stdout) + + +def main() -> int: + manifest = Path("audio/manifests/zacus_v1_audio.yaml") + if not manifest.exists(): + print("Manifest not found:", manifest) + return 1 + doc = load_yaml(manifest) + missing = [] + for asset in doc.get("audio_assets", []): + p = asset.get("path", "") + if p == "PROMPT_ONLY": + continue + if p and not Path(p).exists(): + missing.append(p) + if missing: + print("Missing list:") + for m in missing: + print(f" - {m}") + return 2 + print("OK: all declared audio files exist (or PROMPT_ONLY).") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/tools/printables/generate_local_pdf_placeholders.py b/tools/printables/generate_local_pdf_placeholders.py new file mode 100755 index 0000000..9a5ba68 --- /dev/null +++ b/tools/printables/generate_local_pdf_placeholders.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +from pathlib import Path + +ROOT = Path(__file__).resolve().parents[2] +OUT = ROOT / 'printables' / 'export' / 'pdf' / 'zacus_v1' +OUT.mkdir(parents=True, exist_ok=True) + +# Minimal PDF writer (no external dependency) +def pdf_escape(s: str) -> str: + return s.replace('\\', '\\\\').replace('(', '\\(').replace(')', '\\)') + +def write_simple_pdf(path: Path, title: str, lines: list[str]): + content_lines = [ + 'BT', + '/F1 18 Tf', + '50 790 Td', + f'({pdf_escape(title)}) Tj', + '/F1 11 Tf', + ] + y = 760 + for ln in lines: + content_lines.append(f'1 0 0 1 50 {y} Tm ({pdf_escape(ln)}) Tj') + y -= 16 + if y < 60: + break + content_lines.append('ET') + stream = '\n'.join(content_lines).encode('latin-1', errors='replace') + + objs = [] + objs.append(b'1 0 obj << /Type /Catalog /Pages 2 0 R >> endobj\n') + objs.append(b'2 0 obj << /Type /Pages /Count 1 /Kids [3 0 R] >> endobj\n') + objs.append(b'3 0 obj << /Type /Page /Parent 2 0 R /MediaBox [0 0 595 842] /Resources << /Font << /F1 4 0 R >> >> /Contents 5 0 R >> endobj\n') + objs.append(b'4 0 obj << /Type /Font /Subtype /Type1 /BaseFont /Helvetica >> endobj\n') + objs.append(f'5 0 obj << /Length {len(stream)} >> stream\n'.encode() + stream + b'\nendstream endobj\n') + + header = b'%PDF-1.4\n%\xe2\xe3\xcf\xd3\n' + xref_positions = [0] + body = b'' + offset = len(header) + for obj in objs: + xref_positions.append(offset) + body += obj + offset += len(obj) + xref = f'xref\n0 {len(xref_positions)}\n'.encode() + xref += b'0000000000 65535 f \n' + for pos in xref_positions[1:]: + xref += f'{pos:010d} 00000 n \n'.encode() + trailer = f'trailer << /Size {len(xref_positions)} /Root 1 0 R >>\nstartxref\n{offset}\n%%EOF\n'.encode() + path.write_bytes(header + body + xref + trailer) + +cards = [ + ('zacus_v1_regles_a4_v01.pdf', 'Regles Zacus v1', [ + 'Duree 60-90 min | Age 9-11 ans | 6-14 enfants', + '1) Enquete en equipes 2) Hotline Brigade Z 3) Resolution finale', + 'Lisibilite N&B prioritaire, sans logos externes.' + ]), + ('zacus_v1_hotline_a4_v01.pdf', 'Hotline Brigade Z', [ + 'Reponses autorisees: Indice / Validation / Relance', + 'Tokens telephones: L - AFO - EFO - LE - U', + 'Solution finale unique: Professeur Electron' + ]), + ('zacus_v1_feuille_enquete_a4_v01.pdf', 'Feuille Enquete QUI/OU/COMMENT', [ + 'QUI : ______________________', + 'OU : _______________________', + 'COMMENT : __________________', + 'PREUVE : ___________________' + ]), +] + +for filename, title, lines in cards: + write_simple_pdf(OUT / filename, title, lines) + print('generated', (OUT / filename).relative_to(ROOT)) diff --git a/tools/scenario/validate_scenario.py b/tools/scenario/validate_scenario.py new file mode 100755 index 0000000..3e32c55 --- /dev/null +++ b/tools/scenario/validate_scenario.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +from __future__ import annotations +import json +import subprocess +import sys +from pathlib import Path + + +SCENARIO = Path("game/scenarios/zacus_v1.yaml") + + +def load_yaml(path: Path): + ruby = "require 'yaml'; require 'json'; puts JSON.generate(YAML.load_file(ARGV[0]))" + p = subprocess.run(["ruby", "-e", ruby, str(path)], capture_output=True, text=True) + if p.returncode != 0: + raise RuntimeError(p.stderr.strip() or "YAML parse error") + return json.loads(p.stdout) + + +def dup_ids(items, key="id"): + seen, dups = set(), set() + for i in items: + v = i.get(key) + if v in seen: + dups.add(v) + seen.add(v) + return sorted(dups) + + +def main() -> int: + if not SCENARIO.exists(): + print(f"ERROR: missing {SCENARIO}") + return 1 + doc = load_yaml(SCENARIO) + errors = [] + + zones = doc.get("zones", []) + suspects = doc.get("suspects", []) + props = doc.get("props", []) + steps = doc.get("steps", []) + + for label, arr in [("zones", zones), ("suspects", suspects), ("props", props), ("steps", steps)]: + d = dup_ids(arr) + if d: + errors.append(f"duplicate {label} ids: {d}") + + suspect_ids = {s.get("id") for s in suspects} + zone_ids = {z.get("id") for z in zones} + prop_ids = {p.get("id") for p in props} + + for z in zones: + sid = z.get("responsible_suspect_id") + if sid not in suspect_ids and sid != "S_NONE": + errors.append(f"zone {z.get('id')} references unknown suspect {sid}") + + for st in steps: + for station in st.get("stations", []): + zid = station.get("zone_id") + if zid not in zone_ids: + errors.append(f"step {st.get('id')} references unknown zone {zid}") + + sol = doc.get("solution", {}) + if not sol.get("unique"): + errors.append("solution.unique must be true") + culprit = sol.get("culprit_suspect_id") + if culprit not in suspect_ids: + errors.append("solution culprit invalid") + + if any(st.get("id") == "ETAPE_3" and not st.get("explicit_false_lead") for st in steps): + errors.append("ETAPE_3 must be flagged explicit_false_lead") + + required_props = {"P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8"} + if not required_props.issubset(prop_ids): + errors.append(f"missing required props: {sorted(required_props - prop_ids)}") + + if errors: + print("SCENARIO VALIDATION: FAIL") + for e in errors: + print(" -", e) + return 2 + + print("SCENARIO VALIDATION: PASS") + print(f" - zones={len(zones)} suspects={len(suspects)} props={len(props)} steps={len(steps)}") + return 0 + + +if __name__ == "__main__": + sys.exit(main())