Plateau jouable en PWA : interface, Web Worker, stockage, service worker

L'application est à la racine du site : plateau en SVG, saisie au toucher
(pion puis case d'arrivée, proposées à partir du moteur), boutons du jet,
du videau et de nouvelle partie, coup de l'ordinateur affiché avec son
temps, fin de partie, reprise depuis localStorage, aide lue dans les
copies de docs/. Le moteur tourne dans le Web Worker existant ; main.ts
est le seul assembleur (nouvelles règles dependency-cruiser). Le service
worker met tout le site en cache, avec une empreinte du contenu comme
version. Les pages de test du moteur passent sous /moteur/. Politique de
sécurité du contenu dans le Caddyfile ; make test-browser joue une partie
dans Chromium et Firefox sans écran (Playwright, hors de make test).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Pierre MARTIN
2026-11-02 21:47:12 +01:00
co-authored by Claude Opus 5.5
parent 613ff38254
commit a8636b3f83
37 changed files with 2548 additions and 106 deletions
+32 -37
View File
@@ -3,46 +3,41 @@
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Ustagammon : test du moteur</title>
<link rel="stylesheet" href="style.css">
<script type="module" src="page.mjs"></script>
<meta name="color-scheme" content="light dark">
<meta name="theme-color" content="#6b4426">
<title>Ustagammon</title>
<link rel="manifest" href="manifest.webmanifest">
<link rel="icon" href="icons/icon.svg" type="image/svg+xml">
<link rel="stylesheet" href="app.css">
<script type="module" src="app/main.js"></script>
</head>
<body>
<main>
<h1>Test du moteur</h1>
<p>Le moteur GNU Backgammon, compilé en WebAssembly, calcule dans le navigateur.</p>
<p id="status" class="status">Chargement du moteur…</p>
<!-- Les textes des boutons et des messages viennent de app/src/ui/texts.ts. -->
<header class="topbar">
<h1>Ustagammon</h1>
<button id="help-button" type="button" class="secondary"></button>
<button id="new-game" type="button" class="secondary"></button>
</header>
<form id="form">
<label>Exemple
<select id="example"><option value="">(choisir une position de référence)</option></select>
</label>
<label>Position ID
<input id="position-id" required autocomplete="off" spellcheck="false" value="4HPwATDgc/ABMA">
</label>
<label>Match ID
<input id="match-id" required autocomplete="off" spellcheck="false" value="cIkFAAAAAAAA">
</label>
<div class="row">
<label>Dé 1 <input id="die1" type="number" min="1" max="6" required value="3"></label>
<label>Dé 2 <input id="die2" type="number" min="1" max="6" required value="1"></label>
<label>Niveau
<select id="ply">
<option value="0">rapide (0 pli)</option>
<option value="2">fort (2 plis)</option>
</select>
</label>
</div>
<button id="best-move" type="submit" disabled>Meilleur coup</button>
</form>
<section id="result" class="result" hidden>
<p>Meilleur coup : <strong id="move"></strong></p>
<p id="details"></p>
<p>Temps de calcul : <strong id="time"></strong></p>
</section>
<p><a href="bench.html">Page de mesure</a></p>
<main id="game">
<svg id="board" class="board" role="img" xmlns="http://www.w3.org/2000/svg"></svg>
<p id="pips" class="pips"></p>
<p id="info" class="info" aria-live="polite"></p>
<p id="prompt" class="prompt" aria-live="polite"></p>
<div class="actions">
<button id="roll" type="button" hidden></button>
<button id="double" type="button" class="secondary" hidden></button>
<button id="take" type="button" hidden></button>
<button id="drop" type="button" class="secondary" hidden></button>
<button id="cancel" type="button" class="secondary" hidden></button>
<button id="again" type="button" hidden></button>
</div>
<noscript><p>Ustagammon a besoin de JavaScript.</p></noscript>
</main>
<section id="help" class="help" hidden>
<button id="help-back" type="button" class="secondary"></button>
<div id="help-content"></div>
</section>
</body>
</html>