docs: describe rematches and series

The rematch spec is implemented; AGENTS.md lists it with notes on the
offers, the keyed game route and stale dev builds, TODO.md takes the
items left out.
This commit is contained in:
Halit Aksoy 2026-10-17 02:21:01 +03:00
parent 79f68416ee
commit a3fe708746
5 changed files with 24 additions and 5 deletions

View File

@ -24,7 +24,8 @@ Online Mancala (the Turkish *Mangala* rules) with a web app, an Android/iOS app
Specs that exist: `keycloak-auth` (login, guests, tokens), `game-history` (saved games, live games, replay),
`game-clock` (5 minutes per player, ending games on time), `web-redesign` (the web app's look: themes, board,
pages), `quarkus-backend` (the backend's move from Node to Java and Quarkus), `game-bot` (playing against a bot
at four levels) and `tutorial` (rules page, lessons, hints in bot games).
at four levels), `tutorial` (rules page, lessons, hints in bot games) and `rematch` (rematches, alternating first
moves, the series strip).
## Running locally
@ -73,6 +74,8 @@ which helps to check what the server holds.
`dist`. After changing a package, run `yarn build` in it (or `yarn dev` to rebuild on change), or the apps use stale
code.
Running dev servers do not notice a rebuilt package: restart Parcel after deleting `apps/frontend/.parcel-cache`.
`yarn build` in `apps/frontend` writes to the `dist` that `yarn dev` serves; running it while the dev server runs
can leave stale CSS or JS being served, so restart the dev server afterwards.
The backend does not use the packages.
- Backend and frontend Docker images are built from the repo root: `docker build -f apps/backend/Dockerfile .`.
- The mobile app uses `RTMTWS` from core (its own `src/rtmt` copy is unused), so changing the core WebSocket client
@ -98,6 +101,10 @@ which helps to check what the server holds.
- The bot plays as `bot:<level>` (`BotLevel.isBotId`) in many games at once: `GameStore` does not map it to a game,
nothing is sent to it, it is always online and `PublicIds` keeps its id. The bot's search must never run on the
game loop; `BotPlayer` runs it on its own pool and plays the move back on the loop.
- Rematch offers (`RematchOffers`) hook into `GameManager` like `BotPlayer` (`onGameEnded`, `onPlayerSearching`) and
live in memory only. A game's series travels with the live game (`BackendGame.series`, snapshots); the seat that
moved first is derived from the history (`firstSeat()`), not stored.
- `-Dtest=GameManagerTest` skips its `@Nested` classes; use `-Dtest='GameManagerTest*'`.
- `-Dgroups=...` runs only the tests with that tag; run the untagged tests separately too.
- Unit tests build the logic with fakes (`FakeRtmt`, in-memory stores, `ManualScheduler` instead of timers and
direct executors); only storage, HTTP and WebSocket tests are `@QuarkusTest`s. `FakeTokenVerifier` replaces
@ -119,6 +126,8 @@ which helps to check what the server holds.
- The rules, lessons and move explanations live in `packages/core/src/tutorial`; their boards after a move come from
the engine (`getMoveOutcome`). After a rule change, run core's tests: they fail if a lesson no longer works, and
the rule texts in `en.ts`/`tr.ts` may need updating.
- The game route renders `GamePage` with `key={gameId}`, so following a rematch to the new game's id remounts it.
- Short class names collide across the global CSS files (e.g. `.st` is a stone on the board); check before adding one.
- When a script drives the app in Chrome, wait for the header (`.hdr`) and a few seconds after the first load before
navigating; navigating during the guest login leaves an invalid token. Open the lobby with the "New Game" button,
not by URL, or the matchmaking message goes out before the WebSocket is open.

12
TODO.md
View File

@ -80,7 +80,17 @@ See `docs/specs/tutorial`.
See `docs/specs/web-redesign`.
- [ ] Bring the new design to the mobile app (themes, board, game screen)
- [ ] A rematch button on the game-over card (the design has one; there is no rematch yet)
## Rematch
See `docs/specs/rematch`.
- [ ] Rematch and the series strip in the mobile app, with its new design; until then a web player's request to a
mobile player ends after a minute
- [ ] Series of a fixed length ("best of 3") and a series winner
- [ ] Group series in the game history and on the home page (`games.series_id`)
- [ ] Take spectators along to the next game of a series
- [ ] Leaving the game page does not answer a request; the opponent waits for the minute to pass
## Deployment

View File

@ -1,6 +1,6 @@
# Rematch and series: requirements
Status: in progress, on branch `feature/rematch` (based on `develop`).
Status: implemented on branch `feature/rematch` (based on `develop`); checked in Chrome against the local stack.
Scope: backend, `packages/core`, web app. The mobile app comes later (see R6).
## Goals

View File

@ -13,6 +13,6 @@ Work through the tasks in order; each ends with its tests passing and a commit.
- [x] 6. **Web app, rematch**: the game page following `on_game_start` (`key={gameId}`), the game over card's rematch
states, "Play again" as a rematch, the score in two columns.
- [x] 7. **Web app, series strip**: `SeriesStrip`, the series score on the game over card, spectators.
- [ ] 8. **End to end and docs**: the Chrome tests from `design.md`; `AGENTS.md` (the specs list, rematch notes),
- [x] 8. **End to end and docs**: the Chrome tests from `design.md`; `AGENTS.md` (the specs list, rematch notes),
`TODO.md` (the out of scope items; remove "A rematch button" from Web redesign), the web redesign design's note
on the rematch button.

View File

@ -38,5 +38,5 @@ at once. Without the parameter the endpoint behaves as before, which the mobile
## Not done
- The design's "Rematch" button: there is no rematch; the game-over card offers "New Game".
- The design's "Rematch" button: added later with rematches and series (`docs/specs/rematch`).
- The mobile app.