Files
stream-overlay/README.md
T

208 lines
6.3 KiB
Markdown
Raw 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
# Clona / entra nel progetto
cd tennis-roots
# Avvia tutto con uno script
chmod +x start.sh
./start.sh
```
Oppure manualmente:
```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)
Il progetto include `Dockerfile` e `docker-compose.yml` pronti per il deploy
su un'infrastruttura con **Traefik** come reverse proxy.
### Prerequisiti
- Docker e Docker Compose installati
- Rete `traefik-public` già esistente (`docker network create traefik-public`)
- Dominio configurato (es. `tennis.ricordatiilatte.it`)
### Procedura
```bash
# Clona il progetto sulla VPS
git clone <url> tennis-roots
cd tennis-roots
# Avvia
docker compose up -d
# Log
docker compose logs -f
```
### Accessi
| Risorsa | URL |
|---------|-----|
| Controller | `https://tennis.ricordatiilatte.it/controller/` |
| Scoreboard | `https://tennis.ricordatiilatte.it/overlay/scoreboard.html` |
| Match Info | `https://tennis.ricordatiilatte.it/overlay/match-info.html` |
| Clock | `https://tennis.ricordatiilatte.it/overlay/clock.html` |
| Server Ind. | `https://tennis.ricordatiilatte.it/overlay/server-indicator.html` |
| API stato | `https://tennis.ricordatiilatte.it/api/state` |
| WebSocket | `wss://tennis.ricordatiilatte.it/ws` |
### Note
- Il server è stateless (stato in memoria). Un restart azzera il match.
- Il WebSocket funziona nativamente con Traefik (upgrade HTTP → WS automatico).
- Se vuoi un dominio diverso, cambia il valore di `Host(...)` in `docker-compose.yml`.
## 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
```
tennis-roots/
├── server/
│ ├── package.json
│ ├── index.js # Server Express + WebSocket
│ └── node_modules/
├── overlay/
│ ├── common.js # Client WebSocket condiviso
│ ├── scoreboard.html
│ ├── match-info.html
│ ├── clock.html
│ └── server-indicator.html
├── controller/
│ └── index.html # Pannello di controllo
├── server/
│ ├── Dockerfile # Immagine container
│ └── ...
├── docker-compose.yml # Deploy con Traefik
└── README.md
```