Skip to content

Commit e30f1af

Browse files
authored
docs: simplify Mermaid diagrams in README (#41)
* docs: simplify Mermaid diagrams in README Replace detailed architecture and protocol diagrams with concise versions showing only the essential TV/phone relationship and core protocol exchange. * docs: clarify communication flow in architecture diagram Remove internal Game State node. Show HTTP and WebSocket connections as separate labeled edges to each player with clear direction arrows. * docs: trim to two players, drop wifi label
1 parent f4b218c commit e30f1af

1 file changed

Lines changed: 24 additions & 120 deletions

File tree

README.md

Lines changed: 24 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -25,138 +25,42 @@ Turn an Android TV / Fire TV into a local party-game console and use phones as w
2525

2626
## How It Works
2727

28-
TV runs a static file server (default `:8080`) and a WebSocket game server (default `:8082`).
29-
Phones open the controller page, connect via WebSocket, send actions, and receive state updates.
30-
31-
### System Architecture
32-
3328
```mermaid
34-
graph TB
35-
subgraph TV["Android TV (Host)"]
36-
direction TB
37-
HOST["@couch-kit/host<br/><i>React Native / Expo</i>"]
38-
PROVIDER["GameHostProvider"]
39-
REDUCER_H["createGameReducer<br/><i>Canonical game state</i>"]
40-
HTTP["Static File Server<br/><i>:8080</i>"]
41-
WS["WebSocket Server<br/><i>:8082</i>"]
42-
HOST --> PROVIDER
43-
PROVIDER --> REDUCER_H
44-
PROVIDER --> HTTP
45-
PROVIDER --> WS
46-
end
47-
48-
subgraph CORE["@couch-kit/core"]
49-
TYPES["IGameState · IPlayer · IAction"]
50-
PROTOCOL["Protocol Messages<br/><i>JOIN · WELCOME · STATE_UPDATE<br/>ACTION · PING · PONG · ERROR</i>"]
51-
FN["createGameReducer<br/>derivePlayerId · middleware"]
52-
end
53-
54-
subgraph LAN["Local Network (LAN)"]
55-
direction LR
56-
HTTP_CONN["HTTP — serves controller page"]
57-
WS_CONN["WebSocket — real-time game sync"]
29+
graph LR
30+
subgraph TV["📺 Android TV"]
31+
HTTP["HTTP :8080"]
32+
WS["WebSocket :8082"]
5833
end
5934
60-
subgraph PHONE1["Phone Browser (Client 1)"]
61-
direction TB
62-
CLIENT1["@couch-kit/client<br/><i>React / Vite</i>"]
63-
HOOK1["useGameClient"]
64-
REDUCER_C1["createGameReducer<br/><i>Optimistic local state</i>"]
65-
SYNC1["useServerTime<br/><i>NTP-style clock sync</i>"]
66-
CLIENT1 --> HOOK1
67-
HOOK1 --> REDUCER_C1
68-
HOOK1 --> SYNC1
35+
subgraph PHONES["📱 Phones"]
36+
P1["Player 1"]
37+
P2["Player 2"]
6938
end
7039
71-
subgraph PHONE2["Phone Browser (Client 2)"]
72-
direction TB
73-
CLIENT2["@couch-kit/client"]
74-
HOOK2["useGameClient"]
75-
CLIENT2 --> HOOK2
76-
end
77-
78-
TV -- "HTTP :8080" --> LAN
79-
TV -- "WS :8082" --> LAN
80-
LAN -- "GET /index.html" --> PHONE1
81-
LAN -- "ws:// bidirectional" --> PHONE1
82-
LAN -- "GET /index.html" --> PHONE2
83-
LAN -- "ws:// bidirectional" --> PHONE2
84-
85-
CORE -. "shared types &<br/>reducer wrapper" .-> TV
86-
CORE -. "shared types &<br/>reducer wrapper" .-> PHONE1
87-
CORE -. "shared types &<br/>reducer wrapper" .-> PHONE2
88-
89-
style TV fill:#1a1a2e,stroke:#e94560,color:#fff
90-
style CORE fill:#0f3460,stroke:#16213e,color:#fff
91-
style LAN fill:#16213e,stroke:#533483,color:#fff
92-
style PHONE1 fill:#1a1a2e,stroke:#00b4d8,color:#fff
93-
style PHONE2 fill:#1a1a2e,stroke:#00b4d8,color:#fff
40+
HTTP -- "serves controller page" --> P1 & P2
41+
P1 & P2 -- "actions ➡" --> WS
42+
WS -- "⬅ state updates" --> P1 & P2
9443
```
9544

96-
### Protocol Sequence
97-
9845
```mermaid
9946
sequenceDiagram
100-
participant Phone as Phone Browser
101-
participant HTTP as HTTP Server :8080
102-
participant WS as WebSocket Server :8082
103-
participant Host as Host (GameHostProvider)
104-
participant Reducer as createGameReducer
105-
106-
Note over Phone,HTTP: 1. Load Controller Page
107-
Phone->>HTTP: GET /index.html
108-
HTTP-->>Phone: Static web controller (React/Vite app)
109-
110-
Note over Phone,WS: 2. Establish Connection
111-
Phone->>WS: WebSocket connect to ws://host:8082/ws
112-
WS-->>Host: connection event (socketId)
113-
114-
Note over Phone,Reducer: 3. Join Handshake
115-
Phone->>WS: JOIN { name, avatar, secret }
116-
WS->>Host: message event
117-
Host->>Host: Validate secret (isValidSecret)
118-
Host->>Host: derivePlayerId(secret) via SHA-256
119-
120-
Host->>Reducer: dispatch __PLAYER_JOINED__ { id, name, avatar }
121-
Reducer-->>Host: New state with player added
122-
123-
Host-->>Phone: WELCOME { playerId, state, serverTime }
124-
125-
Note over Phone,Reducer: 4. Game Loop (throttled to ~30fps)
126-
loop State Sync
127-
Phone->>WS: ACTION { type, payload }
128-
WS->>Host: message event
129-
Host->>Host: Rate limit check (60 actions/sec)
130-
Host->>Reducer: dispatch action { ...payload, playerId }
131-
Reducer-->>Host: New state
132-
Host-->>Phone: STATE_UPDATE { state }
133-
end
47+
participant P as 📱 Phone
48+
participant TV as 📺 TV
49+
50+
P->>TV: GET controller page (HTTP)
51+
TV-->>P: Web app
52+
53+
P->>TV: JOIN { name, secret }
54+
TV-->>P: WELCOME { playerId, state }
13455
135-
Note over Phone,Host: 5. Time Synchronization
136-
loop Clock Sync (every 5s)
137-
Host-->>Phone: PING { serverTime }
138-
Phone->>WS: PONG { clientTime, serverTime }
56+
loop Game Loop
57+
P->>TV: ACTION { type, payload }
58+
TV-->>P: STATE_UPDATE { state }
13959
end
14060
141-
Note over Phone,Reducer: 6. Disconnection & Session Recovery
142-
Phone--xWS: Connection lost
143-
WS->>Host: disconnect event
144-
Host->>Reducer: dispatch __PLAYER_LEFT__ { playerId }
145-
Reducer-->>Host: Player marked connected: false
146-
147-
Note over Host: 5-min disconnect timeout starts
148-
149-
alt Player reconnects within 5 minutes
150-
Phone->>WS: WebSocket reconnect
151-
Phone->>WS: JOIN { name, avatar, secret } (same secret)
152-
Host->>Host: derivePlayerId returns same playerId
153-
Host->>Host: Cancel cleanup timer
154-
Host->>Reducer: dispatch __PLAYER_RECONNECTED__ { playerId }
155-
Reducer-->>Host: Player marked connected: true
156-
Host-->>Phone: WELCOME { playerId, state, serverTime }
157-
else Timeout expires (5 min)
158-
Host->>Reducer: dispatch __PLAYER_REMOVED__ { playerId }
159-
Reducer-->>Host: Player permanently removed from state
61+
loop Heartbeat
62+
TV-->>P: PING
63+
P->>TV: PONG
16064
end
16165
```
16266

0 commit comments

Comments
 (0)