Ajoute le pipeline PageSpec (validation, rendu, publication /p/{slug}),
les démos TipTap /demo, et le simulateur Carnot (modes frigo/PAC/moteur,
énergie kJ vs puissance W, unités K/°C/°F) avec correctifs d’équations KaTeX.
Co-authored-by: Cursor <cursoragent@cursor.com>
60 lines
3.5 KiB
Markdown
60 lines
3.5 KiB
Markdown
# Simulateurs interactifs (plugins)
|
||
|
||
Bibliothèque de simulateurs pédagogiques pour les **pages interactives** (`/p/{slug}`).
|
||
L'IA ne code jamais une simulation : elle **choisit** un simulateur de cette liste et le
|
||
**configure** (`preset` = valeurs de la note), ou utilise `generic-formula` si aucun ne
|
||
correspond au sujet.
|
||
|
||
## Liste des simulateurs disponibles
|
||
|
||
| `simId` | Famille | Sujet | Interaction |
|
||
|---|---|---|---|
|
||
| `carnot-cycle` | `sim` | Machine frigorifique / PAC / moteur de Carnot (2ᵉ principe) | Curseurs T_c, T_h, Q_c → COP, η, W min, Q_h en direct |
|
||
| `carnot-cycle-anim` | `anim` | Cycle de Carnot animé (piston + diagramme P–V live, 5 étapes) | Play / Pause / Step / Reset / vitesse + narration |
|
||
| `generic-formula` | `sim` | (générique) toute relation chiffrée y = f(paramètres) | Curseurs définis par l'IA, expressions sûres (aucun `eval`) |
|
||
|
||
Deux familles de plugins : `sim` (manipulation de paramètres, calcul en direct) et
|
||
`anim` (scène animée codée en dur, pilotée par le player Play/Step — narration par
|
||
battements). Les deux sont choisis par l'IA via le même bloc `{ "type": "sim" }`.
|
||
|
||
## Comment l'IA les utilise
|
||
|
||
1. Le prompt de génération de section injecte `catalogForPrompt(lang)` (registry.ts) —
|
||
id + résumé + mots-clés + bornes de chaque simulateur.
|
||
2. Si le contenu de la note correspond (`keywords`), l'IA émet
|
||
`{ "type": "sim", "sim": { "simId": "carnot-cycle", "preset": { "t_hot": 300 } } }`.
|
||
3. `validateInteractivePage` vérifie : `simId` connu, preset dans les bornes,
|
||
`compute(preset)` fini — sinon rejet (renvoyé au LLM ou fallback).
|
||
|
||
## Ajouter un plugin (5 étapes)
|
||
|
||
Pour un **`sim`** (curseurs) :
|
||
1. **`lib/simulators/<id>.ts`** — implémenter `SimulatorPlugin` (`family: 'sim'`) :
|
||
`id`, `title`/`summary` fr+en (le summary sert au matching IA), `keywords`,
|
||
`params` (curseurs : bornes, pas, défaut, unité, intent), `outputs` (symbole KaTeX,
|
||
unité), et `compute(env)` **pur et déterministe**.
|
||
2. **`lib/simulators/index.ts`** — ajouter au `REGISTRY`.
|
||
3. **`components/simulators/<id>-view.tsx`** — composant sur mesure
|
||
(props : `preset`, `title`, `disclaimer`, `lang`). Réutiliser
|
||
`SimSlider` / `SimOutputCard` / `SimHeading` / `SimKaTeX` de `sim-controls.tsx`.
|
||
4. **`components/simulators/index.ts`** — enregistrer dans `SIMULATOR_VIEWS`.
|
||
5. Vérifier : `compute` fini aux valeurs par défaut, `npx tsc --noEmit`, tester sur
|
||
`/dev/interactive-page`.
|
||
|
||
Pour une **`anim`** (scène animée Play/Step) :
|
||
1. **`lib/simulators/<id>.ts`** — implémenter `AnimPlugin` (`family: 'anim'`) :
|
||
`id`, `title`/`summary` fr+en, `keywords`, `disclaimer?`, `beats` (narration
|
||
fr+en par étape — KaTeX inline `$…$` dans `speak`).
|
||
2. **`lib/simulators/index.ts`** — ajouter au `REGISTRY`.
|
||
3. **`components/simulators/<id>-anim-view.tsx`** — scène SVG/React pilotée par
|
||
`step` (props : `step`, `lang`). Transitions CSS sur `transform`/`opacity`
|
||
uniquement. Le chrome (Play/Pause/Step/Reset/vitesse + panneau de narration +
|
||
clavier Espace/←/→/R) est fourni par `AnimPlayerShell` — ne pas le réécrire.
|
||
4. **`components/simulators/index.ts`** — enregistrer dans `ANIM_VIEWS`.
|
||
5. Vérifier : chaque `step` rend un état cohérent (y compris état final sans JS),
|
||
`npx tsc --noEmit`, tester sur `/dev/interactive-page`.
|
||
|
||
Règles : pas de couleurs en dur (intents / tokens `--pp-*`), labels fr+en dans le
|
||
plugin, tout calcul côté `compute` ou scène codée (jamais de logique LLM), SSR =
|
||
état lisible sans JS.
|