Files
ki-fwi/docs/sessions/02-moteur-pedagogique.md
OKIandClaude Opus 5 dadcbdbcbb feat(session-2): moteur pédagogique en Svelte pur — Kaché, Sézon, Rekonèt, Lakou
Trois modes, l'album et la progression locale. Aucun Phaser.

Kaché est pleinement jouable : indices dévoilés un à un (feuille →
écorce → port → coupe → fruit), score dégressif de 100 à 20. Il ne
dépend d'aucune photographie, ce qui le rend jouable aujourd'hui alors
qu'aucune image n'est validée. Les distracteurs sont tirés par proximité
botanique — un corossol face à une pomme-cannelle enseigne la vraie
confusion, deux Annona qu'on confond réellement.

Sézon est jouable et affiche en permanence que sa saisonnalité n'est
sourcée nulle part (a-arbitrer §3). Signalé, pas caché.

Rekonèt est complet mais bloqué : 0 photo validée sur 8 espèces. Il
affiche un état designé qui dit pourquoi, et pose la règle n°1 là où un
enfant la lira — il ne se rabattra jamais sur une image générée.

Répétition espacée Leitner à 5 boîtes dans localStorage, tirage pondéré
8 contre 1 vers les boîtes basses. Vérifié en jouant : bonne réponse →
boîte 2 et fiche débloquée, erreur → retour boîte 1. Export/import JSON,
aucun compte, aucune donnée qui quitte l'appareil.

use:compte pour le moment de révélation : rAF → DOM direct, span animé
aria-hidden, valeur finale en .sr-only dans une région aria-live.

Mesures
- 65,6 Ko de JS gzip (budget 170) · 68 pages prérendues
- npm run check : 259 fichiers, 0 erreur, 0 warning
- elementFromPoint à 375 px : 0 recouvrement, 0 cible sous 44 px
- ordre de tabulation naturel, aucun tabindex positif

Défaut trouvé en testant : le fil d'Ariane faisait 16 px de haut sur
mobile. Corrigé — un lien seul sur sa ligne est une commande, pas un
lien de texte.

La porte « le jeu est-il amusant sans Phaser » reste ouverte : elle
demande de jouer, et elle appartient au porteur.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-07-27 11:53:22 -04:00

99 lines
4.7 KiB
Markdown

# Session 2 — Moteur pédagogique, en Svelte pur
**Date :** 2026-07-27 · **Livrable :** trois modes de jeu, l'album, la progression locale.
## La porte de sortie, honnêtement
| Critère | Cible | Mesuré |
|---|---|---|
| **Le jeu est amusant sans Phaser** | jugement humain | **à trancher par le porteur** — voir plus bas |
| Navigation clavier | complète | contrôles `<button>` natifs, ordre DOM naturel, **aucun `tabindex` positif**, règle `:focus-visible` présente ✅ |
| Cibles tactiles | ≥ 44 px en 375 px | **0 élément sous 44 px** après correction ✅ |
| Zéro superposition | `elementFromPoint` | **0 recouvrement** sur 11 contrôles ✅ |
| Scroll horizontal mobile | aucun | aucun ✅ |
| Progression conservée au rechargement | oui | vérifié dans `localStorage` ✅ |
| JS initial gzip | ≤ 170 Ko | **65,6 Ko** ✅ |
| `npm run check` | 0/0 | **259 fichiers, 0/0** ✅ |
| Erreurs console en partie | 0 | 0 ✅ |
**Le « le jeu est-il amusant » n'est pas une mesure que je peux prendre.** Elle demande de
jouer, et elle appartient au porteur. C'est la porte la plus importante du plan et elle
reste ouverte.
## Ce qui est jouable
### Kaché — pleinement jouable
Cinq questions, indices dévoilés un à un dans l'ordre feuille → écorce → port → coupe →
fruit, score dégressif de 100 à 20 points. Quatre propositions.
**Ce mode ne dépend d'aucune photographie** : il repose sur les indices textuels du dataset.
C'est ce qui le rend jouable aujourd'hui, alors qu'aucune image n'est validée.
Les distracteurs sont choisis par proximité — même famille botanique d'abord, puis mêmes
îles. Un corossol opposé à trois plantes sans rapport n'apprend rien ; opposé à une
pomme-cannelle, il enseigne la vraie confusion, celle qui existe sur le terrain entre deux
*Annona*.
### Sézon — jouable, avec un avertissement affiché
« Quel fruit trouve-t-on en octobre ? » Six questions, quatre propositions.
Le mode **affiche en permanence** que sa saisonnalité n'est vérifiée contre aucune source
et n'est pas ventilée par île (`docs/a-arbitrer.md` §3). Le plan interdit de le publier en
l'état ; il est livré jouable et signalé, pas caché.
### Rekonèt — livré, et bloqué
Le code est complet et fonctionnera dès la première photo validée. Aujourd'hui il affiche
un **état designé** plutôt qu'une page d'erreur : combien d'espèces disposent d'une
photographie validée (0 sur 8), pourquoi il en faut au moins quatre, et surtout —
> « Ce mode fonctionne uniquement sur des photographies réelles, validées par un humain.
> Il ne se rabattra jamais sur une image générée : ce serait apprendre à reconnaître ce
> qu'un modèle invente. »
C'est la règle n°1 du projet, écrite là où un enfant et son enseignant la liront.
### Lakou — l'album
Fiches débloquées, boîtes de Leitner visualisées, export et import de la progression en
JSON, effacement. Les fiches non débloquées apparaissent en cases voilées : on voit ce
qu'il reste à découvrir sans voir la réponse.
## Répétition espacée
Leitner à 5 boîtes, persisté dans `localStorage`. Bonne réponse → la carte monte d'une
boîte ; erreur → retour en boîte 1. Le tirage pondère les boîtes basses 8 contre 1.
Vérifié en jouant : `fwiyapen` répondu juste passe en boîte 2 et se débloque, `pom-kannel`
répondu faux reste en boîte 1 et ne se débloque pas.
Aucun compte, aucun serveur, aucune donnée qui quitte l'appareil. L'export JSON est le seul
moyen de déplacer une progression — et il est utile à un enseignant.
## Le moment de révélation
`use:compte` anime le score final : rAF avec écriture DOM directe, **jamais d'état réactif
par frame**. Le span animé est `aria-hidden`, la valeur finale vit en `.sr-only` dans une
région `aria-live="polite"` — un lecteur d'écran annonce le résultat une fois, pas les
quarante valeurs intermédiaires. En `prefers-reduced-motion`, la valeur finale est posée
immédiatement.
Il manque une pièce au moment de révélation : **le nom kréyòl prononcé**. Aucun
enregistrement n'est embarqué, le jeu se replie en silence et le dit.
## Un défaut trouvé en testant, pas en relisant
Le fil d'Ariane « Retour à l'encyclopédie » mesurait **16 px de haut** sur mobile — moins
de la moitié de la cible tactile minimale. Trouvé par `elementFromPoint` à 375 px, pas à la
relecture du code. Corrigé par une règle partagée : un lien seul sur sa ligne est une
commande, pas un lien de texte.
## Reste ouvert
- **Jouer et juger.** C'est la porte de la session.
- Les prononciations : 10 à enregistrer, 3 déjà disponibles sur Lingua Libre.
- Rekonèt attend des photographies validées.
- Sézon attend une source pour sa saisonnalité.