Files

187 lines
5.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 🎾 Tennis Roots
Overlay per streaming tennis (OBS) con controller remoto via WebSocket.
## Architettura
```
┌─────────────────────┐ WebSocket ┌──────────────────────┐
│ Controller (admin) │────────────────────→│ │
│ /controller/ │←── STATE_UPDATE ───│ Express + WebSocket │
└─────────────────────┘ │ Server (hub) │
│ Port 3000 │
┌─────────────────────┐ WebSocket │ │
│ Scoreboard (OBS) │←── STATE_UPDATE ───│ │
│ Match Info (OBS) │←── STATE_UPDATE ───│ │
│ Clock (OBS) │←── STATE_UPDATE ───│ │
│ Server Ind. (OBS) │←── STATE_UPDATE ───│ │
└─────────────────────┘ └──────────────────────┘
```
## Quick Start
```bash
cd server
npm install
npm start
```
Apri nel browser:
- **Controller**: http://localhost:3000/
- **Scoreboard**: http://localhost:3000/overlay/scoreboard.html
- **Match info**: http://localhost:3000/overlay/match-info.html
- **Clock**: http://localhost:3000/overlay/clock.html
- **Server indicator**: http://localhost:3000/overlay/server-indicator.html
## Widget Overlay (per OBS)
Ogni widget è un file HTML indipendente, dimensionabile e posizionabile
liberamente in OBS come **Browser Source**.
| Widget | URL | Dimensioni suggerite |
|--------|-----|---------------------|
| **Scoreboard** | `/overlay/scoreboard.html` | 820×130 px |
| **Match Info** | `/overlay/match-info.html` | 600×50 px |
| **Clock** | `/overlay/clock.html` | 150×50 px |
| **Server Indicator** | `/overlay/server-indicator.html` | 250×50 px |
### Setup in OBS
1. Aggiungi **Browser Source**
2. Inserisci URL del widget (es. `http://localhost:3000/overlay/scoreboard.html`)
3. Imposta larghezza/altezza come da tabella
4. **Importante**: spunta "Controlla audio/visibilità del browser nella sorgente"
5. Usa filtri di ritaglio/posizionamento per sistemare l'overlay
## Controller
Il pannello di controllo admin è accessibile a `/controller/`.
### Sezioni
- **Stato corrente**: live view del match
- **Punteggio**: pulsanti punto P1/P2, Deuce, Reset Game/Match
- **Servizio**: cambio battuta manuale
- **Giocatori**: modifica nomi e bandiere
- **Info Match**: torneo e round
### Scorciatoie da tastiera
| Tasto | Azione |
|-------|--------|
| `1` | Punto P1 |
| `2` | Punto P2 |
| `D` | Deuce |
| `R` | Reset Game |
| `M` | Reset Match |
## API HTTP
```bash
# Stato corrente
curl http://localhost:3000/api/state
# Aggiornamento parziale
curl -X POST http://localhost:3000/api/state \
-H 'Content-Type: application/json' \
-d '{"player1":"N. Djokovic","tournament":"US Open"}'
# Comando
curl -X POST http://localhost:3000/api/command \
-H 'Content-Type: application/json' \
-d '{"command":"ADD_POINT","player":1}'
```
## WebSocket
I widget si connettono automaticamente a `ws://localhost:3000/ws`.
Il server propaga gli aggiornamenti a tutti i client connessi.
### Formato messaggi
**Da controller a server:**
```json
{ "type": "COMMAND", "command": "ADD_POINT", "player": 1 }
{ "type": "COMMAND", "command": "SET_DEUCE" }
{ "type": "COMMAND", "command": "RESET_GAME" }
{ "type": "COMMAND", "command": "RESET_MATCH" }
{ "type": "COMMAND", "command": "SET_SERVER", "player": 2 }
{ "type": "STATE_UPDATE", "state": { "player1": "...", ... } }
```
**Da server a tutti:**
```json
{ "type": "STATE_UPDATE", "state": { ... } }
```
## Sviluppo
```bash
cd server
npm run dev # node --watch
```
## Deploy su VPS (Docker + Traefik)
### Prerequisiti
- Docker e Docker Compose
- Rete `traefik-public` già esistente (`docker network create traefik-public`)
### Procedura
```bash
git clone <url> stream-overlay
cd stream-overlay
cp .env.example .env
# imposta DOMAIN con il tuo dominio
docker compose up -d
```
### Accessi
| Risorsa | URL |
|---------|-----|
| Controller | `https://<tuo-dominio>/controller/` |
| Scoreboard | `https://<tuo-dominio>/overlay/scoreboard.html` |
| Match Info | `https://<tuo-dominio>/overlay/match-info.html` |
| Clock | `https://<tuo-dominio>/overlay/clock.html` |
| Server Ind. | `https://<tuo-dominio>/overlay/server-indicator.html` |
| API stato | `https://<tuo-dominio>/api/state` |
| WebSocket | `wss://<tuo-dominio>/ws` |
### Note
- Il server è stateless (stato in memoria). Un restart azzera il match.
- Il WebSocket funziona nativamente con Traefik (upgrade HTTP → WS automatico).
## Regole punteggio implementate
- Punti game: 0, 15, 30, 40, Deuce, Vantaggio
- Set: primo a 6 game con 2 di scarto
- **Tiebreak**: a 6-6, primi a 7 punti con 2 di scarto
- Servizio nel tiebreak: punto 1 → P1, punto 2 → P2, poi cambio ogni 2 punti
- Match: al meglio dei 3 set
## Struttura file
```
stream-overlay/
├── server/
│ ├── package.json
│ ├── Dockerfile
│ └── index.js
├── overlay/
│ ├── common.js
│ ├── scoreboard.html
│ ├── match-info.html
│ ├── clock.html
│ └── server-indicator.html
├── controller/
│ └── index.html
├── docker-compose.yml
├── .env.example
├── .gitignore
└── README.md
```