Mes parties : la feuille se ferme à la reprise ; plan 1b : résultat
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
e3aaa0b3a3
commit
d228d70387
@@ -110,7 +110,10 @@ export function createGamesView(options: GamesViewOptions): GamesView {
|
||||
actions.append(
|
||||
button(
|
||||
GAMES_TEXTS.resume,
|
||||
run(() => options.resume(game.id)),
|
||||
run(async () => {
|
||||
await options.resume(game.id);
|
||||
hide();
|
||||
}),
|
||||
"",
|
||||
"resume",
|
||||
),
|
||||
|
||||
@@ -54,4 +54,44 @@ rechargement). Commits fréquents ; pas de push ni de MR.
|
||||
|
||||
## Résultat
|
||||
|
||||
À remplir à la clôture.
|
||||
Réalisé le 2026-11-03 sur la branche `parties-enregistrees`, fusionnée avec
|
||||
main après la révision UX (MR !35).
|
||||
|
||||
- **Stockage** (`app/src/storage/`) : `GameLibrary` (list, load, save,
|
||||
remove, current, setCurrent) sur IndexedDB (base « ustagammon » v1 :
|
||||
magasins games, journals, settings ; résumé et journal dans la même
|
||||
transaction), en repli sur localStorage puis sur la mémoire. Opérations
|
||||
exécutées dans l'ordre des appels. La partie de l'étape 0
|
||||
(`ustagammon.current-game`) est migrée puis effacée. `GameSession` tient
|
||||
la partie à l'écran : nouvelle partie, « Reprendre l'ancienne » (relue
|
||||
par son identifiant, la nouvelle est supprimée), reprise d'une partie ou
|
||||
d'une branche.
|
||||
- **Domaine** : `branches(journal)` et `switchToBranch` (branches.ts),
|
||||
`Game.branches` et `Game.switchBranch`, résumé d'une partie
|
||||
(saved-game.ts), export SGF de GNU Backgammon avec les branches en
|
||||
variantes, la branche courante d'abord (sgf.ts).
|
||||
- **Interface** : « Mes parties », ligne du menu en feuille, ouvre une
|
||||
feuille (games-view.ts) : reprendre une partie ou une branche (changement
|
||||
de partie à l'écran, sans recharger), exporter en SGF, supprimer en deux
|
||||
touchers (jamais la partie affichée).
|
||||
- **Vérification SGF** : `tests/test_web.sh` joue 6 parties sur le vrai
|
||||
moteur (complètes, branches, videau, positions particulières), les
|
||||
exporte (9 fichiers, un par branche) et les fait relire par le gnubg de
|
||||
référence (`tests/sgf/check.py`) : après chaque coup, sa position égale
|
||||
celle du journal, et le résultat concorde. Une altération volontaire d'un
|
||||
coup ou de la position de départ est détectée.
|
||||
- **Scénarios** : `docs/scenarios/mes-parties.feature` (reprendre une partie
|
||||
parmi plusieurs, rejouer d'ici sans perdre l'original, exporter) ; le
|
||||
scénario « Reprendre l'ancienne » de `regler-l-application.feature` passe
|
||||
par la session. Glossaire : partie-enregistree.md, sgf.md, branche.md
|
||||
(code: Branch).
|
||||
- **Tests** : `make lint`, `make test` (10/10, 20 scénarios) et
|
||||
`make test-browser` (Chromium et Firefox : parties listées, SGF
|
||||
téléchargé, première partie reprise sans rechargement, « Reprendre
|
||||
l'ancienne » sans partie en trop) passent.
|
||||
|
||||
Limites connues : gnubg 1.08 ne lit que la première variante d'un SGF ;
|
||||
l'enregistrement n'est pas attendu (une fermeture dans les millisecondes
|
||||
qui suivent une action peut la perdre) ; pas de score de match avant 1c ;
|
||||
le schéma IndexedDB devient un contrat durable (amendement de l'ADR 0007 à
|
||||
envisager). L'adresse `#/parties` viendra avec 0e.4.
|
||||
|
||||
@@ -1188,7 +1188,15 @@ step("mes parties");
|
||||
await shot("4b-mes-parties");
|
||||
const loads = await page.evaluate(() => performance.getEntriesByType("navigation").length);
|
||||
await oldest.locator('[data-action="resume"]').click();
|
||||
await page.waitForSelector("#games-veil", { state: "hidden" });
|
||||
await page.waitForSelector("#games-veil", { state: "hidden", timeout: 20_000 }).catch(async () => {
|
||||
const state = await page.evaluate(() => ({
|
||||
message: document.querySelector("#games .games-message")?.textContent,
|
||||
busy: document.body.classList.contains("busy"),
|
||||
info: document.getElementById("info")?.textContent,
|
||||
panel: !document.getElementById("panel-veil").hidden,
|
||||
}));
|
||||
throw new Error(`reprise bloquée : ${JSON.stringify(state)}`);
|
||||
});
|
||||
await page.waitForSelector("#panel");
|
||||
const resumed = await savedJournal();
|
||||
check(JSON.stringify(resumed) === JSON.stringify(finished), "la première partie n'a pas été reprise");
|
||||
|
||||
Reference in New Issue
Block a user