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>
This commit is contained in:
@@ -0,0 +1,98 @@
|
||||
# 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é.
|
||||
Reference in New Issue
Block a user