docs(claude): riscrivi CLAUDE.md in italiano con istruzioni operative
Traduzione completa in italiano, aggiunta sezione Deploy con riferimento al registry Gitea self-hosted, sezione Istruzioni operative con linee guida per nuove funzionalità e convenzioni di naming. Inclusa anche la configurazione plugin Claude Code (.claude/settings.json).
This commit is contained in:
@@ -2,26 +2,28 @@
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Purpose
|
||||
## Scopo del progetto
|
||||
|
||||
**Segnapunti Anto** is a real-time volleyball scoreboard PWA. An Express/WebSocket server hosts the game state; two separate web interfaces — a **display** (public scoreboard) and a **controller** (operator panel) — stay in sync via WebSocket.
|
||||
**Segnapunti Anto** è una PWA per il segnapunti pallavolo in tempo reale. Un server Express/WebSocket gestisce lo stato di gioco; due interfacce Vue separate — **display** (tabellone pubblico) e **controller** (pannello operatore) — si sincronizzano via WebSocket.
|
||||
|
||||
## Commands
|
||||
## Comandi
|
||||
|
||||
```bash
|
||||
npm run dev # Vite dev server — display: :5173/display, controller: :5173/controller
|
||||
npm run serve # Build + run production — display: :3000/display, controller: :3000/controller
|
||||
npm run serve # Build + avvio produzione — display: :3000/display, controller: :3000/controller
|
||||
|
||||
npm run test # Vitest watch mode
|
||||
npm run test:all # All Vitest suites once (unit, integration, component, stress)
|
||||
npm run test:unit # Unit + integration only
|
||||
npm run test:component # Vue component tests
|
||||
npm run test:stress # Load tests (50+ concurrent clients)
|
||||
npm run test:e2e # Playwright E2E (requires servers to be running via npm run serve)
|
||||
npm run test:e2e:ui # Playwright with interactive UI
|
||||
npm run test # Vitest in modalità watch
|
||||
npm run test:all # Tutte le suite Vitest in una sola esecuzione
|
||||
npm run test:unit # Solo unit + integration
|
||||
npm run test:component # Test componenti Vue (happy-dom)
|
||||
npm run test:stress # Load test (50+ client concorrenti)
|
||||
npm run test:e2e # Playwright E2E (richiede npm run serve attivo)
|
||||
npm run test:e2e:ui # Playwright con UI interattiva
|
||||
```
|
||||
|
||||
## Architecture
|
||||
Per eseguire un singolo file di test: `npx vitest run tests/unit/gameState.test.js`
|
||||
|
||||
## Architettura
|
||||
|
||||
```
|
||||
Controller (Vue) ──WebSocket──┐
|
||||
@@ -30,33 +32,51 @@ Display (Vue) ──WebSocket──┤── websocket-handler.js ── gam
|
||||
│ └── persist.js ── .segnapunti/state.json
|
||||
```
|
||||
|
||||
All game logic lives in `src/gameState.js` as three pure functions:
|
||||
- `createInitialState()` — returns the initial state
|
||||
- `applyAction(state, action)` — immutable reducer (deep-clones via `structuredClone`)
|
||||
- `checkVittoria(state)` — volleyball win conditions (25-point sets with 2-point margin, 15-point final set)
|
||||
**Tutta la logica di gioco** è in `src/gameState.js` come tre funzioni pure esportate:
|
||||
- `createInitialState()` — restituisce lo stato iniziale
|
||||
- `applyAction(state, action)` — reducer immutabile (deep-clone via `structuredClone`)
|
||||
- `checkVittoria(state)` — condizioni di vittoria set (25 punti, vantaggio di 2; 15 punti nel set decisivo)
|
||||
|
||||
`src/websocket-handler.js` receives actions, validates that the sender is a registered controller (not just a display), calls `applyAction`, broadcasts the new state to all clients, then calls `onStateChange` to persist state to disk.
|
||||
`src/websocket-handler.js` riceve i messaggi WebSocket, valida che il mittente sia un `controller` (non un `display`), chiama `applyAction`, fa il broadcast del nuovo stato a tutti i client, poi invoca `onStateChange` per persistere su disco.
|
||||
|
||||
`server.js` (Express) serves both interfaces on port 3000: `/display` → `dist/index.html`, `/controller` → `dist/controller.html`. Single WebSocket endpoint at `/ws`.
|
||||
`server.js` (Express) serve entrambe le interfacce sulla porta 3000: `/display` → `dist/index.html`, `/controller` → `dist/controller.html`. Singolo endpoint WebSocket su `/ws`.
|
||||
|
||||
In development, `vite-plugin-websocket.js` embeds the WebSocket server inside the Vite dev server with URL rewrite middleware for `/display` and `/controller`.
|
||||
In sviluppo, `vite-plugin-websocket.js` incorpora il server WebSocket dentro il dev server Vite con middleware di URL rewrite per `/display` e `/controller`.
|
||||
|
||||
## Key Design Constraints
|
||||
## Vincoli di design
|
||||
|
||||
- **All game rules on the server** — clients are pure UI; the server is the source of truth.
|
||||
- **Role-based WebSocket** — clients register as `display` or `controller`; only controllers may send actions.
|
||||
- **Immutable state** — `applyAction` never mutates; always returns a new state object.
|
||||
- **Single-controller intent** — the design targets one active controller and one display; no conflict resolution exists for simultaneous controllers.
|
||||
- **Persistent state** — `src/persist.js` saves state to `.segnapunti/state.json` after every action and loads it on server startup.
|
||||
- **Tutta la logica sul server** — i client sono pura UI; il server è l'unica source of truth.
|
||||
- **WebSocket role-based** — i client si registrano come `display` o `controller`; solo i controller possono inviare azioni.
|
||||
- **Stato immutabile** — `applyAction` non muta mai lo stato, restituisce sempre un nuovo oggetto.
|
||||
- **Un solo controller** — il design prevede un controller e un display attivi; non esiste conflict resolution per controller simultanei.
|
||||
- **Stato persistente** — `src/persist.js` salva lo stato in `.segnapunti/state.json` dopo ogni azione e lo carica all'avvio del server.
|
||||
|
||||
## Test Layout
|
||||
## Layout dei test
|
||||
|
||||
| Suite | Path | Runner |
|
||||
|-------|------|--------|
|
||||
| Suite | Percorso | Runner |
|
||||
|-------|----------|--------|
|
||||
| Unit | `tests/unit/` | Vitest + Node |
|
||||
| Integration | `tests/integration/` | Vitest + Node |
|
||||
| Component | `tests/component/` | Vitest + Happy-DOM |
|
||||
| Stress | `tests/stress/` | Vitest + Node |
|
||||
| E2E | `tests/e2e/` | Playwright (Chromium, Firefox, Mobile Chrome) |
|
||||
|
||||
E2E tests run serially (`workers: 1`) to avoid WebSocket state races. Run `npm run serve` before `npm run test:e2e`.
|
||||
I test E2E girano in serie (`workers: 1`) per evitare race condition sullo stato WebSocket. Eseguire `npm run serve` prima di `npm run test:e2e`.
|
||||
|
||||
## Deploy
|
||||
|
||||
Il progetto si distribuisce tramite Docker. L'immagine è pubblicata sul registry Gitea self-hosted (`santantonio.sytes.net`):
|
||||
|
||||
```bash
|
||||
docker compose up -d # Avvia con immagine dal registry privato (porta 3000)
|
||||
```
|
||||
|
||||
Il volume `./.segnapunti` persiste lo stato tra i riavvii del container.
|
||||
|
||||
## Istruzioni operative
|
||||
|
||||
- Per ogni nuova funzionalità: analizza come si inserisce nel flusso `action → applyAction → broadcast`, poi decidi se aggiungere un nuovo tipo di action o estendere uno esistente.
|
||||
- Qualsiasi modifica alle regole di gioco va fatta esclusivamente in `src/gameState.js`.
|
||||
- Qualsiasi modifica al protocollo WebSocket va fatta in `src/websocket-handler.js`.
|
||||
- Aggiungere test unit in `tests/unit/gameState.test.js` per ogni nuovo action type o regola di gioco.
|
||||
- Il codice deve essere scritto in italiano per commenti e nomi di variabili di dominio (es. `servHome`, `striscia`, `nomi`), ma in inglese per nomi tecnici standard (`state`, `action`, `handler`).
|
||||
|
||||
Reference in New Issue
Block a user