85 lines
3.2 KiB
Markdown
85 lines
3.2 KiB
Markdown
|
|
# Manual Poll Start — Upstream Integration Guide
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
The vote-app now supports a `poll.start` WebSocket message that explicitly triggers poll generation. This replaces the previous behavior where polls were always auto-generated on `game.ended`.
|
||
|
|
|
||
|
|
## Poll Modes
|
||
|
|
|
||
|
|
The vote-app has two poll modes:
|
||
|
|
|
||
|
|
| Mode | `game.ended` behavior | `poll.start` behavior |
|
||
|
|
|------|----------------------|----------------------|
|
||
|
|
| **manual** (default) | Logged but no poll generated | Generates a new poll |
|
||
|
|
| **auto** | Generates a new poll (legacy behavior) | Generates a new poll |
|
||
|
|
|
||
|
|
The mode is persisted in the vote-app database and survives restarts. It can be toggled from the debug panel (Game Control section).
|
||
|
|
|
||
|
|
## Message Format
|
||
|
|
|
||
|
|
Send this JSON message over the existing upstream WebSocket connection:
|
||
|
|
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"type": "poll.start",
|
||
|
|
"sessionId": 3
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Fields
|
||
|
|
|
||
|
|
| Field | Type | Required | Description |
|
||
|
|
|-------|------|----------|-------------|
|
||
|
|
| `type` | string | yes | Must be `"poll.start"` |
|
||
|
|
| `sessionId` | number | no | Included for consistency; the vote-app uses its internally tracked session ID |
|
||
|
|
|
||
|
|
The `sessionId` field is optional in practice — the vote-app tracks the active session from `session.started` / subscription events and uses that to determine which games to exclude from the poll. Including it is recommended for protocol consistency.
|
||
|
|
|
||
|
|
## When to Send
|
||
|
|
|
||
|
|
- **After `game.ended`** — if the vote-app is in `manual` mode, `game.ended` alone will not create a poll. Send `poll.start` when you're ready for viewers to vote on the next game.
|
||
|
|
- **At any time** — you can send `poll.start` to force a new poll regardless of mode. Any existing active poll is deactivated and replaced.
|
||
|
|
|
||
|
|
## What Happens on Receipt
|
||
|
|
|
||
|
|
1. The vote-app fetches enabled games from the upstream API (`GET /api/games?enabled=true`)
|
||
|
|
2. It fetches the current session's games (`GET /api/sessions/{id}/games`) to exclude recently played titles
|
||
|
|
3. It picks 3 random games (weighted by favor bias) plus an "Other" option
|
||
|
|
4. The previous active poll (if any) is deactivated
|
||
|
|
5. The new poll is created and broadcast to all connected browser clients via WebSocket
|
||
|
|
|
||
|
|
## Example (Node.js)
|
||
|
|
|
||
|
|
```javascript
|
||
|
|
// Assuming `ws` is your existing WebSocket connection to the vote-app upstream
|
||
|
|
// and you've already authenticated and subscribed to the session
|
||
|
|
|
||
|
|
function startPoll(sessionId) {
|
||
|
|
ws.send(JSON.stringify({
|
||
|
|
type: 'poll.start',
|
||
|
|
sessionId: sessionId
|
||
|
|
}));
|
||
|
|
}
|
||
|
|
|
||
|
|
// Typical flow: game ends, wait for the right moment, then start the poll
|
||
|
|
ws.on('message', (raw) => {
|
||
|
|
const msg = JSON.parse(raw);
|
||
|
|
|
||
|
|
if (msg.type === 'game.ended') {
|
||
|
|
// Game just ended — start poll when ready
|
||
|
|
// (in manual mode, vote-app won't auto-generate one)
|
||
|
|
startPoll(msg.data.sessionId);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
```
|
||
|
|
|
||
|
|
## Existing Messages (Unchanged)
|
||
|
|
|
||
|
|
These upstream messages continue to work as before:
|
||
|
|
|
||
|
|
- `game.ended` — in `auto` mode, still triggers poll generation; in `manual` mode, logged but no poll created
|
||
|
|
- `voting.ended` — deactivates the active poll and broadcasts the winner
|
||
|
|
- `game.started` — deactivates the active poll and hides the overlay
|
||
|
|
- `room.connected` — deactivates the active poll and broadcasts room info
|
||
|
|
- `poll.leading` — still sent by the vote-app to upstream when the leading vote changes
|