Fusion de main (révision UX) ; Mes parties dans le menu, reprise sans rechargement

« Reprendre l'ancienne » relit l'ancienne partie dans le stockage par son
identifiant et supprime la nouvelle (GameSession).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Pierre MARTIN
2026-11-03 20:17:53 +01:00
co-authored by Claude Opus 5.5
35 changed files with 4578 additions and 893 deletions
+38
View File
@@ -47,3 +47,41 @@ moteur sait les lire et les écrire (`engine.h`).
- Les liens restent valables tant que GNU Backgammon garde ces formats, stables
depuis des années.
- Les liens contiennent la position, rien d'autre : pas de donnée personnelle.
## Amendements
### 2026-11-03 — Une adresse pour chaque écran, des liens plutôt que des états
Demandé par Pierre : « il faudra vraiment que chaque page (l'aide, etc.) ait
une URL. Utilise des liens accessibles, pas des états. » Aucun lien de
position n'a encore circulé : le format ci-dessus est remplacé par un schéma
unique pour tous les écrans, avant sa première mise en œuvre.
- Chaque écran a son adresse, dans le fragment (pour les mêmes raisons
qu'au-dessus : hors ligne, service worker, aucune configuration serveur) :
| Écran | Adresse |
| --- | --- |
| Partie en cours | `#/` |
| Accueil | `#/accueil` |
| Aide (onglet Jouer) | `#/aide`, une question : `#/aide/<identifiant>` |
| Les mots du jeu | `#/glossaire`, un terme : `#/glossaire/<fichier sans .md>` |
| À propos | `#/a-propos` |
| Tutoriel | `#/tutoriel`, une étape : `#/tutoriel/<n>` |
| Mes parties | `#/parties`, une partie : `#/parties/<id>` |
| Réglages / menu | `#/menu` |
| Une position | `#/position/<Position ID>/<Match ID>` (Match ID facultatif) |
Les identifiants de gnubg sont encodés avec `encodeURIComponent`. Les
écrans à venir (analyse, leçons, progression) suivront le même schéma.
- On change d'écran par de vrais liens (`<a href="#/aide">`), pas par des
boutons qui modifient un état caché : le lien se partage, s'ouvre dans un
nouvel onglet, se lit aux lecteurs d'écran comme un lien, et le bouton
« retour » du téléphone ramène à l'écran précédent. Les actions de jeu
(lancer, jouer, doubler) restent des boutons : elles ne sont pas des écrans.
- Les feuilles (menu, explication) et panneaux qui sont des écrans à part
entière ont aussi leur adresse ; une confirmation ou un bandeau éphémère
n'en a pas.
- Une adresse inconnue mène à la partie en cours avec un message clair.
- L'adresse de l'écran courant est la source de vérité de la navigation :
l'application l'écoute (`hashchange`) et dessine l'écran correspondant.
+1 -2
View File
@@ -23,8 +23,7 @@ Demandes de Pierre du 2026-11-03, traitées avant d'ouvrir l'étape 1.
| Sous-étape | Contenu | État | Plan |
| --- | --- | --- | --- |
| 0e.3 | Révision UX arbitrée (session « identité », sur délégation de Pierre) : portrait stable, bandeaux de compte de points, menu en feuille et nouvelle partie annulable, vibrations, écran allumé, paysage « plateau = écran » dès la rotation (ADR 0012 amendé) | ⏳ | `plans/2026-11-03-revision-ux.md` |
| 0e.4 | Position dans l'adresse : chaque position du plateau a un lien direct (ADR 0013) | ⏳ | `plans/2026-11-03-position-dans-l-adresse.md` |
| 0e.4 | Une adresse par écran (aide, glossaire, menu, mes parties…) et par position, par de vrais liens (ADR 0013 amendé) | ⏳ | `plans/2026-11-03-position-dans-l-adresse.md` |
| 0e.5 | Page d'accueil, installation en un toucher (« Ajouter à l'écran d'accueil », proposée par l'app), tutoriel des règles très didactique avec plateaux illustrés, aide réécrite sur un ton plus humain ; textes à valider par Pierre | ⏳ | `plans/2026-11-03-accueil-tutoriel-aide.md` |
## Étapes suivantes
@@ -47,6 +47,8 @@ Traiter les points 2 et 3 du message de Pierre du 2026-11-03 et sa demande d'ins
- `beforeinstallprompt` simulé dans Chromium ;
- captures dans `build/browser-shots/accueil-tutoriel/` pour la recette design.
Chaque écran (accueil, étapes du tutoriel, onglets et questions de l'aide) a son adresse et s'ouvre par un vrai lien, selon l'amendement de l'ADR 0013 ; le routeur vient de 0e.4.
`make lint`, `make test` et `make test-browser` doivent passer. Aucune nouvelle dépendance.
## Critères de réussite
@@ -0,0 +1,60 @@
# Conseil du maître (1d)
- **Date** : 2026-11-03
- **Étape** : 1d (`docs/etape-1.md`)
- **Statut** : prévu (après 1c)
- **Exécutant** : sous-agent general-purpose, dans un worktree
## Objectif
Le coach bienveillant, « mis en avant mais discret » (Pierre, 2026-11-03) :
après chaque coup et chaque décision de videau du joueur, jamais avant
(ADR 0011), une appréciation et une phrase du maître fondées sur les chiffres
du moteur.
## Références
- ADR 0011 ; maquette « conseil du maître après le coup » du canevas
https://claude.ai/artifact/CQw6vbDpi6XQqVWQa4sANe ; règles de la charte
(`docs/identite/charte/`, dont interaction.md) ; la ligne réservée de 44 px
de la révision UX.
- Moteur : `analyseMove`, `analyseCube`, `luck`, seuils `SKILL_THRESHOLDS`
(gnubg : 0,03 / 0,06 / 0,12).
## Consignes
1. **Analyse en arrière-plan** : après la validation d'un coup (ou une
décision de videau), l'analyse à 2 plis part dans le Worker sans retarder le
tour de l'ordinateur ; son résultat est rattaché au coup dans le journal
(événement d'analyse rétrocompatible, ou cache séparé justifié) pour servir
au bilan (1e) sans recalcul.
2. **Ligne du maître** : icône d'appréciation, mot en couleur (« Bon coup. »,
« Imprécision. », « Erreur. », « Gaffe. » : correspondance avec les seuils
de gnubg documentée), phrase courte en italique, chevron. Toucher ouvre la
feuille d'explication : coup joué et meilleur coup montrés sur le plateau
(pions animés, ADR 0011 « comparaison visuelle »), écart d'équité seulement
sur demande, lien vers la fiche du glossaire du concept en jeu si le moteur
permet de le déterminer, sinon rien.
3. **Phrases du maître** : gabarits versionnés en français dans une source
unique sous `docs/` (CC BY-SA 4.0), ton encourageant, jamais culpabilisant ;
elles ne citent que des faits du moteur (coup recommandé, rang, pions
frappés, écart) : aucune explication inventée. Première version à faire
valider par Pierre (ton).
4. **Discret** : rien n'apparaît pendant que le joueur réfléchit ; la ligne
s'efface à l'action suivante ; désactivable (réglage de 1c et menu).
5. **Videau** : même traitement pour doubler, ne pas doubler, prendre, passer.
6. Scénarios Gherkin (bon coup, erreur avec meilleur coup montré, conseil
désactivé, décision de videau commentée) avec positions et dés imposés ;
tests unitaires des gabarits (chaque gabarit rendu sur des analyses réelles
du moteur). `make lint`, `make test`, `make test-browser`, captures pour la
recette design.
## Critères de réussite
Après une erreur volontaire dans une position connue, la ligne du maître dit
« Erreur. », nomme le coup recommandé par le moteur et le montre sur demande ;
le tour de l'ordinateur n'est pas retardé ; les trois commandes passent.
## Résultat
À remplir à la clôture.
@@ -0,0 +1,47 @@
# Match, niveaux et réglages (1c)
- **Date** : 2026-11-03
- **Étape** : 1c (`docs/etape-1.md`)
- **Statut** : prévu (après la révision UX et 1b)
- **Exécutant** : sous-agent general-purpose, dans un worktree
## Objectif
Choisir sa partie : partie libre ou match en N points, avec les règles de
Crawford et de Jacoby, contre l'ordinateur au niveau voulu.
## Consignes
ADR 0007, 0008. Le moteur expose depuis 1a les niveaux de gnubg
(`levelMove`, `levelCubeDecision`) et accepte les matchs dans son API C.
1. **Domaine** : longueur de match, score, règle de Crawford (partie Crawford
et suivantes, calculées par le moteur via le Match ID), règle de Jacoby en
partie libre ; enchaînement des manches d'un match jusqu'à sa fin ; le
journal d'événements reste rétrocompatible (les parties existantes se
rechargent).
2. **Adaptateur** : `EngineCube` étendu au match (score, longueur, Crawford)
ou remplacé par le Match ID, sans casser les appels existants.
3. **Niveau de l'ordinateur** : ses coups et ses décisions de videau au niveau
choisi. Reprendre de `ComputerTurn` (gnubg, `play.c`) les règles de
déroulement non reprises en 1a : pré-filtre « fenêtre de marché » et double
facultatif à 0 pli, avec citation des sources.
4. **Écran de nouvelle partie** (maquettes de la session « identité » si
disponibles, sinon sobre et conforme à la charte) : type de partie, niveau
(noms montrés au joueur à proposer simplement : Débutant, Amateur,
Intermédiaire, Avancé, Expert, Champion — correspondance avec les niveaux
de gnubg documentée), conseil du maître activé ou non. Par défaut : partie
libre, Intermédiaire, conseil activé. Le réglage est mémorisé.
5. Affichage du score de match et de la partie Crawford sur le plateau.
6. Scénarios Gherkin (match en 3 points jusqu'au bout avec dés imposés,
Crawford, Jacoby) et fiches du glossaire (match, Crawford, Jacoby si
absentes). `make lint`, `make test`, `make test-browser` (un match court).
## Critères de réussite
Un match en 3 points se joue jusqu'au bout, au niveau choisi, avec Crawford
appliqué ; les trois commandes passent.
## Résultat
À remplir à la clôture.
@@ -1,20 +1,29 @@
# Position dans l'adresse (0e.4)
# Une adresse pour chaque écran, et pour chaque position (0e.4)
- **Date** : 2026-11-03
- **Étape** : 0e.4 (feuille de route)
- **Statut** : prévu (après la fusion de la révision UX, qui touche les mêmes fichiers)
- **Statut** : prévu (après la fusion de la révision UX et de 1b)
- **Exécutant** : sous-agent general-purpose, dans un worktree
## Objectif
Appliquer l'ADR 0013 : chaque position du plateau a un lien direct.
Appliquer l'ADR 0013 et son amendement du 2026-11-03 : chaque écran (aide,
glossaire, menu, mes parties…) a son adresse et s'ouvre par un vrai lien ;
chaque position du plateau a un lien direct.
## Consignes
ADR 0007, 0008 et 0013. Aucune nouvelle dépendance.
1. Lecture du fragment `#position=…&match=…` au chargement et sur
`hashchange` ; validation par le moteur ; message clair si illisible.
0. **Routeur** : un petit module pur (sans dépendance) qui traduit le
fragment en écran et inversement, testé unitairement ; l'app dessine
l'écran demandé par l'adresse, sur `hashchange`. Tous les écrans existants
(aide et ses questions, glossaire et ses termes, à propos, menu, mes
parties de 1b) passent par lui, avec de vrais liens `<a href>` ; le bouton
retour du navigateur ramène à l'écran précédent. Les actions de jeu restent
des boutons.
1. Lecture de `#/position/<Position ID>/<Match ID>` ; validation par le
moteur ; message clair si illisible.
2. Vue de la position, non jouable, avec « Jouer à partir d'ici » (nouvelle
partie depuis la position, la partie en cours restant reprenable) et
« Retour à ma partie ».
@@ -26,8 +35,10 @@ ADR 0007, 0008 et 0013. Aucune nouvelle dépendance.
position (test aller-retour).
5. Scénarios Gherkin (« Ouvrir un lien vers une position », « Partager la
position »), fiches du glossaire (Position ID, Match ID si absentes).
6. `make lint`, `make test`, `make test-browser` (ouvrir un lien, jouer à
partir d'ici, revenir, lien invalide).
6. `make lint`, `make test`, `make test-browser` : chaque adresse du tableau
de l'ADR ouverte directement dans un nouvel onglet montre le bon écran ;
« retour » du navigateur ; liens reconnus comme liens (rôle `link`) ;
position : ouvrir un lien, jouer à partir d'ici, revenir, lien invalide.
## Critères de réussite
-63
View File
@@ -1,63 +0,0 @@
# Révision UX : portrait stable, compte de points, menu, paysage « plateau = écran »
- **Date** : 2026-11-03
- **Étape** : 0e.3 (feuille de route)
- **Statut** : prévu
- **Exécutant** : sous-agent general-purpose, dans un worktree
## Objectif
Appliquer la revue UX (0e.2) telle qu'arbitrée par la session « identité » sur
délégation de Pierre le 2026-11-03, et l'amendement de l'ADR 0012.
## Références
- Maquettes : https://claude.ai/artifact/CQw6vbDpi6XQqVWQa4sANe, rangées
« Révision UX » en bas du canevas.
- Règles : section « Interaction » du design system, copiée dans
`docs/identite/charte/interaction.md` (durées, courbes, motifs de vibration,
touches) et composant Icons (10 pictogrammes).
- Rapport du designer UI : conservé dans la description de la MR qui clôt ce
plan.
## Décisions à appliquer
1. **Portrait stable** (maquette « Portrait révisé ») :
- une barre haute avec le symbole et trois pictogrammes, libellés de 13 px dessous : Aide, Plein écran, Menu ;
- le bandeau de l'ordinateur, puis le plateau, puis le bandeau du joueur ;
- une ligne réservée de 44 px : le dernier coup de l'ordinateur avec ↻, ou la ligne du maître ;
- la consigne ;
- une barre d'actions collée en bas, l'action secondaire à gauche et la principale à droite (« Jouer ce coup »). Toucher les dés valide aussi ;
- la durée de calcul affichée disparaît.
2. **Compte de points** :
- en portrait, des bandeaux. Les chiffres sont en 20 px gras, alignés. Le bandeau de celui qui a la main est en accent-soft (« Vous · à vous de jouer »). L'écart s'écrit « mène de 8 », en muted, du côté de celui qui mène. Toucher le chiffre ouvre une bulle avec le texte de la fiche du glossaire (source unique, ADR 0008) ;
- en paysage, des pastilles aux bouts de la barre.
3. **Menu en feuille** qui monte du bas :
- il contient Nouvelle partie, Plein écran, Aide et glossaire, Thème, et les interrupteurs Vibrations et « Écran allumé pendant la partie » ;
- « Nouvelle partie » agit sans confirmation. Un bandeau « Nouvelle partie commencée. Reprendre l'ancienne » reste 10 s avec une barre de temps, et l'ancienne partie se restaure depuis son journal ;
- plus de `window.confirm`.
4. **Pas de passage automatique du tour** quand aucun coup n'est possible : les dés sont barrés avec le message, et le joueur passe en touchant les dés (ou Espace). Ajouter `overscroll-behavior: none` et `user-select: none`. L'écran reste allumé pendant une partie (Wake Lock), activé par défaut, avec un interrupteur.
5. **Paysage, « le plateau est l'écran »** (ADR 0012 amendé) :
- la vue s'applique dès la rotation, sur `100dvh` ;
- la géométrie suit l'écran, par une fonction pure testée unitairement, d'après les formules du composant Board des maquettes ;
- une colonne de commandes à gauche dans le cadre : menu en haut, videau au milieu, ↶ en bas, remplacé par ↻ quand le coup de l'ordinateur est montré ;
- les sorties restent libres ;
- numéros des flèches à 12 px au moins ;
- la fin de partie s'affiche dans un panneau centré sur un voile ;
- le plein écran s'ouvre sur un geste (pictogramme ou menu), avec `requestFullscreen` puis `screen.orientation.lock` et un repli par rotation CSS. Ce n'est pas le réglage par défaut de l'app installée.
6. **Vibrations** (`navigator.vibrate`, si disponible) aux quatre moments, avec les motifs d'`interaction.md` : pion posé, pion frappé, double proposé par l'ordinateur, fin de partie. Elles sont activées par défaut, rien au lancer des dés, et elles doublent toujours un signal visible.
7. **Pictogrammes** du composant Icons, en SVG dans le site (CSP : pas de style en ligne).
8. **Consigne** : forme longue pendant les trois premières parties, puis forme courte.
9. **Mouvement** :
- durées de 90, 160 et 240 ms, avec la courbe cubic-bezier(0.2, 0, 0, 1) ;
- l'ordinateur joue pion par pion : 160 ms par pion, 120 ms de pause ;
- `prefers-reduced-motion` est respecté.
10. **Clavier** (priorité basse) : prévoir dans l'architecture une table d'actions commune au toucher et au clavier. Les touches d'`interaction.md` peuvent venir dans une MR ultérieure.
## Consignes
ADR 0007 : ni le domaine ni le moteur ne changent pour la mise en page. ADR 0008 : scénarios Gherkin pour les comportements visibles nouveaux (nouvelle partie annulable, menu). Aucune nouvelle dépendance. `tests/browser/play.mjs` étendu aux deux orientations, avec des captures Playwright en 412×915, 915×412 et 844×320, en thème clair et sombre, rangées dans un dossier indiqué par la session principale pour la revue design. `make lint`, `make test` et `make test-browser` passent.
## Résultat
À remplir à la clôture.
+1
View File
@@ -48,3 +48,4 @@ Règles d'écriture :
| --- | --- | --- |
| [jouer-une-partie.feature](jouer-une-partie.feature) | Jouer une partie contre l'ordinateur | Étape 0d |
| [mes-parties.feature](mes-parties.feature) | Retrouver mes parties, leurs branches, les exporter en SGF | Étape 1b |
| [regler-l-application.feature](regler-l-application.feature) | Régler l'application (menu) | Étape 0e |
+18 -5
View File
@@ -14,7 +14,7 @@ Fonctionnalité: Jouer une partie contre l'ordinateur
Touchez un pion, puis sa case d'arrivée ; s'il n'en a qu'une, il y va dès
que vous le touchez. Chaque dé joué s'estompe. Une fois tous vos dés
joués, votre coup attend que vous le validiez : touchez vos dés, d'un côté
ou de l'autre du plateau, ou « Valider ».
ou de l'autre du plateau, ou « Jouer ce coup ».
Étant donné que c'est à vous de jouer avec le jet 3-1
Quand vous jouez 8/5 6/5
@@ -61,21 +61,22 @@ Fonctionnalité: Jouer une partie contre l'ordinateur
Scénario: Aucun coup possible avec votre jet
Il arrive que les dés ne permettent de bouger aucun pion. Votre jet reste
affiché avec un message, et le tour ne passe à l'ordinateur qu'une fois
que vous avez touché « Continuer ».
affiché, barré, avec un message. L'application ne joue jamais à votre
place : le tour ne passe à l'ordinateur que quand vous touchez vos dés
(ou « Continuer »).
Étant donné que votre pion sur la barre ne peut pas rentrer
Quand vous lancez les dés
Alors aucun coup n'est possible avec votre jet
Et c'est toujours à vous
Quand vous continuez
Quand vous laissez passer votre tour
Alors c'est ensuite au tour de l'ordinateur
Scénario: Voir le coup de l'ordinateur
Après chaque coup de l'ordinateur, ses pions glissent un par un sur le
plateau. Restent ensuite, jusqu'à votre prochaine action, une flèche par
pion déplacé, ses pions arrivés entourés et un pion fantôme là où ils
étaient. Le bouton « Revoir » rejoue son coup.
étaient. « Revoir » (la flèche circulaire) rejoue son coup.
Étant donné qu'un de vos pions est seul à portée de l'ordinateur
Quand l'ordinateur a joué
@@ -83,6 +84,18 @@ Fonctionnalité: Jouer une partie contre l'ordinateur
Et votre pion frappé part sur la barre
Et vous pouvez revoir son coup
Scénario: Voir le compte de points
Au-dessus et au-dessous du plateau, le bandeau de chaque camp donne son
compte de points, et « mène de 7 » s'affiche du côté de celui qui mène la
course. Touchez un compte pour lire ce qu'il veut dire. En paysage, les
comptes sont aux deux bouts de la barre.
Quand vous commencez une nouvelle partie
Alors chaque camp a un compte de points de 167
Et personne ne mène la course
Quand vous jouez 13/8 13/11
Alors vous menez la course de 7
Scénario: Doubler, après confirmation
Avant de lancer les dés, vous pouvez doubler en touchant le videau ou
« Doubler ». L'application vous demande de confirmer : une fois proposé,
@@ -0,0 +1,48 @@
# language: fr
Fonctionnalité: Régler l'application
Le menu, qui monte du bas de l'écran, regroupe ce qui ne sert pas à chaque
coup : commencer une nouvelle partie, passer en plein écran, ouvrir l'aide
et le glossaire, choisir le thème, couper les vibrations, et laisser ou non
l'écran allumé pendant la partie. Rien de ce qu'il contient ne vous pose de
question : ce qui se fait se rattrape.
Scénario: Commencer une nouvelle partie, puis reprendre l'ancienne
Une nouvelle partie commence tout de suite, sans question. Pendant 10
secondes, le bandeau « Reprendre l'ancienne » vous rend la partie que
vous venez de quitter, exactement là où vous l'aviez laissée.
Étant donné qu'une partie est en cours depuis quelques coups
Quand vous commencez une nouvelle partie depuis le menu
Alors une nouvelle partie commence aussitôt
Et l'ancienne partie peut être reprise pendant 10 secondes
Quand vous reprenez l'ancienne partie
Alors vous retrouvez exactement la partie quittée
Scénario: Couper les vibrations
Le téléphone vibre brièvement quand votre pion se pose, quand un pion est
frappé, quand l'ordinateur vous propose de doubler et à la fin de la
partie. Ces vibrations accompagnent toujours ce que montre l'écran ; rien
ne vibre quand vous lancez les dés. Elles se coupent dans le menu.
Étant donné que vous ouvrez l'application pour la première fois
Quand un pion est frappé
Alors le téléphone vibre deux fois, brièvement
Quand vous coupez les vibrations dans le menu
Et qu'un pion est frappé
Alors le téléphone ne vibre pas
Scénario: Garder l'écran allumé pendant la partie
Pour que le téléphone ne se mette pas en veille pendant que vous
réfléchissez, l'écran reste allumé tant qu'une partie est en cours.
Étant donné que vous ouvrez l'application pour la première fois
Alors l'écran reste allumé pendant une partie
Quand vous coupez « Écran allumé pendant la partie » dans le menu
Alors l'écran peut se mettre en veille comme d'habitude
Scénario: Choisir le thème
Étant donné que vous ouvrez l'application pour la première fois
Alors le thème suit celui du téléphone
Quand vous changez de thème dans le menu
Alors il passe à clair, puis à sombre, puis revient à automatique