feat: add player Names Throughout the Game UI

This commit is contained in:
2026-08-30 01:02:34 +03:00
parent 4d9d0db02d
commit dfc6b023f7
12 changed files with 307 additions and 34 deletions
+6 -6
View File
@@ -47,7 +47,7 @@ Failure (maximum 160 encoded bytes):
| Route | Maximum request | Response / maximum |
| -------------------------- | --------------: | --------------------------------------------- |
| `GET /api/info` | 128 B target | public device/slot state, 192 B |
| `GET /api/info` | 128 B target | public device/slot state and names, 384 B |
| `GET /api/health` | 128 B target | diagnostics without secrets, 320 B; includes reset reason |
| `POST /api/session/join` | 192 B body | `{name,requestedRole}`; token and role, 192 B |
| `POST /api/session/resume` | 96 B body | `{token}`; role and state metadata, 192 B |
@@ -56,7 +56,7 @@ Failure (maximum 160 encoded bytes):
| `POST /api/game/shot` | 96 B body | `{token,gameId,x,y}`; common envelope |
| `POST /api/game/rematch` | 80 B body | `{token,gameId}`; common envelope |
| `POST /api/game/abort` | 80 B body | `{token,gameId}`; common envelope |
| `GET /api/state?version=N` | 128 B target | one role-safe state, 512 B |
| `GET /api/state?version=N` | 128 B target | one role-safe state, 768 B |
| `GET /api/statistics` | 128 B target | role and bounded match/cumulative counters |
The session token is in each POST body. For `GET /api/state`, it is supplied
@@ -65,17 +65,17 @@ parameter.
## Role-safe state event
The HTTP state response and WebSocket `state` event use this single 512-byte
The HTTP state response and WebSocket `state` event use this single 768-byte
maximum schema:
```json
{"type":"state","version":17,"gameId":4,"phase":"in_progress","mode":"human","viewer":"player1","turn":"player2","boards":["000...100 cells...","000...100 cells..."],"wins":[0,0],"winner":null,"statistics":[[3,2,1,1],[4,1,3,0]]}
{"type":"state","version":17,"gameId":4,"phase":"in_progress","mode":"human","viewer":"player1","turn":"player2","players":["Алиса","Борис"],"boards":["000...100 cells...","000...100 cells..."],"wins":[0,0],"winner":null,"statistics":[[3,2,1,1],[4,1,3,0]]}
```
`boards[0]` belongs to player 1 and `boards[1]` to player 2. The presenter
replaces every unauthorized unhit ship with `0`. In `finished`, both boards may
contain `1`. `winner` is `null` until `finished`, then player index `0` or `1`.
Each compact statistics tuple is `[shots,hits,misses,shipsSunk]`. No other event
`players` contains validated display names for occupied slots (an empty string for a free slot). Each compact statistics tuple is `[shots,hits,misses,shipsSunk]`. No other event
contains a board.
## Statistics response
@@ -100,7 +100,7 @@ first frame must arrive within 5 seconds:
It receives a `state` snapshot. Supported inbound frames are `hello` (96 B),
`ping` (16 B), `config` (96 B), `start` (80 B), `shot` (96 B), `rematch`
(80 B), and `abort` (80 B). Their fields exactly match the corresponding HTTP
commands. Outbound `state` is at most 512 B; `error` uses the common 160-byte
commands. Outbound `state` is at most 768 B; `error` uses the common 160-byte
failure envelope; `pong` is 16 B. Commands are idempotent when the same
`gameId`, `version`, and command payload are retried: the server returns the
current state rather than applying the action twice.
+2 -2
View File
@@ -15,7 +15,7 @@ time. The application partition is 2,097,152 B and LittleFS is 2,031,616 B.
| Firmware image | 1,500,000 B | M004 fixed threshold, leaving 597,152 B app-partition reserve |
| LittleFS image | 250,000 B | M004 fixed threshold, leaving 1,781,616 B filesystem reserve |
| Minimum free heap | 96,000 B | M004 fixed threshold; observed minimum was 249,616 B |
| Largest role-safe state JSON | 512 B | Tested fixed serialization cap; production schema is compact strings |
| Largest role-safe state JSON | 768 B | Two bounded 80-byte display names plus role-safe game state |
| HTTP JSON request body | 192 B | Largest defined command (`join`) fits within this bound |
| WebSocket incoming frame | 192 B | `hello` is the largest defined incoming frame |
| HTTP request target/query | 128 B | `/api/state?version=4294967295` is below this bound |
@@ -26,7 +26,7 @@ time. The application partition is 2,097,152 B and LittleFS is 2,031,616 B.
| Open HTTP sockets | 12 | Ten clients plus two polling/transport headroom; LWIP is configured for 16 |
No handler may allocate a per-client complete JSON state. It serializes one
bounded snapshot at a time into the 512-byte transport buffer.
bounded snapshot at a time into the 768-byte transport buffer.
## Per-milestone budget gates
+9 -2
View File
@@ -271,7 +271,7 @@ components:
properties: { role: { $ref: '#/components/schemas/Role' } }
Info:
type: object
required: [ok, phase, gameId, version, player1Available, player2Available, spectatorsAvailable]
required: [ok, phase, gameId, version, player1Available, player2Available, player1Name, player2Name, spectatorsAvailable]
properties:
ok: { type: boolean, enum: [true] }
phase: { $ref: '#/components/schemas/Phase' }
@@ -279,6 +279,8 @@ components:
version: { $ref: '#/components/schemas/GameId' }
player1Available: { type: boolean }
player2Available: { type: boolean }
player1Name: { type: string, maxLength: 20 }
player2Name: { type: string, maxLength: 20 }
spectatorsAvailable: { type: integer, minimum: 0, maximum: 8 }
Health:
type: object
@@ -311,7 +313,7 @@ components:
description: '[games, wins, losses, shipsSunk, shots, hits, misses]'
State:
type: object
required: [type, version, gameId, phase, mode, viewer, turn, boards, wins, winner, statistics]
required: [type, version, gameId, phase, mode, viewer, turn, players, boards, wins, winner, statistics]
properties:
type: { type: string, enum: [state] }
version: { $ref: '#/components/schemas/GameId' }
@@ -320,6 +322,11 @@ components:
mode: { $ref: '#/components/schemas/Mode' }
viewer: { $ref: '#/components/schemas/Role' }
turn: { type: string, enum: [player1, player2] }
players:
type: array
minItems: 2
maxItems: 2
items: { type: string, maxLength: 20 }
boards:
type: array
minItems: 2