From a1cea9c37d8f914dbcdf1b80101bb200469ac194 Mon Sep 17 00:00:00 2001 From: Julian Appel Date: Wed, 19 Aug 2026 20:39:27 +0200 Subject: [PATCH] README auf den gemergten Stand gebracht Ergaenzt: Splashscreen als dritte Monitoransicht und Standard beim Start, Team-Datenbank, Debugfenster, Spiegelung des Adminpanels, Steuerung des Kiosk-Browsers, die zugehoerigen etc-, db- und score-Endpunkte sowie der Hinweis zur PORT-Variable. Korrigiert: Portangabe, Projektstruktur, Antwortformate und die Abhaengigkeitsliste. Co-Authored-By: Claude Opus 5 --- README.md | 149 +++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 124 insertions(+), 25 deletions(-) diff --git a/README.md b/README.md index 3fa35a4..d9193b5 100644 --- a/README.md +++ b/README.md @@ -10,16 +10,24 @@ Das System besteht aus zwei Teilen: | Teil | URL | Beschreibung | |---|---|---| -| **Monitor** | `http://:3000/` | Vollbildanzeige für den Beamer/Monitor (Timer + Score) | -| **Admin-Panel** | `http://:3000/admin` | Steuerung von Timer und Scoreboard | +| **Monitor** | `http://:3000/` | Vollbildanzeige für den Beamer/Monitor | +| **Admin-Panel** | `http://:3000/admin` | Steuerung von Timer, Scoreboard und Anzeige | Alle Änderungen vom Admin-Panel werden über **WebSockets (Socket.IO)** in Echtzeit auf dem Monitor angezeigt — ohne Seiten-Reload. +Der Monitor rendert je nach Serverzustand eine von drei Ansichten: + +| Ansicht | Template | Wann | +|---|---|---| +| Splashscreen | `splashscreen.hbs` | Solange der Splashscreen aktiv ist (Standard beim Start) | +| Timer + Score | `indexScore.hbs` | Splashscreen aus, Scoreboard aktiv (Standard) | +| Nur Timer | `index.hbs` | Splashscreen aus, Scoreboard deaktiviert | + --- ## Voraussetzungen -- Node.js (v18 oder neuer empfohlen) +- Node.js (v18 oder neuer) - npm --- @@ -32,9 +40,21 @@ npm install npm start ``` -Der Server startet mit `nodemon` und ist anschließend unter Port **3000** erreichbar. +Der Server startet mit `nodemon` und ist anschließend unter Port **3000** erreichbar. Der Socket.IO-Server läuft separat auf Port **3001**. +### Port ändern + +Der HTTP-Port lässt sich über die Umgebungsvariable `PORT` setzen: + +```bash +PORT=80 npm start +``` + +Auf dem Anzeige-Rechner (Raspberry Pi) wird Port **80** verwendet, damit der +Kiosk-Browser die Seite ohne Portangabe unter `http://localhost` öffnen kann. +Port 80 erfordert erhöhte Rechte. + --- ## Projektstruktur @@ -43,27 +63,34 @@ Der Socket.IO-Server läuft separat auf Port **3001**. scoreboard/ ├── app.js # Express-App, Middleware, Routen ├── bin/www # HTTP-Server, startet die App +├── db.json # Persistente Liste bekannter Teamnamen ├── controllers/ │ ├── socketio.js # Socket.IO-Server (Port 3001) │ ├── timer.js # Timer-Logik (Start, Pause, Reset, IncDec) │ ├── score.js # Score-Logik (Punkte, Teams, Seitenwechsel) -│ └── cli.js # CLI-Controller (aktuell Testcode) +│ ├── db.js # Lesen/Schreiben der Teamnamen in db.json +│ ├── etc.js # Splashscreen-Status +│ └── cli.js # Start/Stop des Kiosk-Browsers auf dem Anzeigerechner ├── routes/ │ ├── admin.js # REST-Endpunkte für das Admin-Panel │ └── index.js # Monitor-Ansicht + WebSocket-Verbindungshandler ├── views/ │ ├── admin.hbs # Admin-Panel (Handlebars-Template) -│ ├── index.hbs # Monitor ohne Scoreboard (nur Timer) -│ └── indexScore.hbs # Monitor mit Scoreboard (Timer + Score + Teamnamen) +│ ├── splashscreen.hbs # Monitor: Vereinslogo +│ ├── index.hbs # Monitor: nur Timer +│ └── indexScore.hbs # Monitor: Timer + Score + Teamnamen └── public/ + ├── img/ # Logos für den Splashscreen ├── javascripts/ │ ├── admin.js # Frontend-Logik Admin-Panel │ ├── index.js # Frontend-Logik Monitor (ohne Score) - │ └── indexScore.js # Frontend-Logik Monitor (mit Score) + │ ├── indexScore.js # Frontend-Logik Monitor (mit Score) + │ └── splashscreen.js # Frontend-Logik Splashscreen (nur Refresh-Handler) └── stylesheets/ ├── admin.css ├── index.css ├── indexScore.css + ├── splashscreen.css └── seven-segment.css # Seven-Segment-Display-Schrift für den Timer ``` @@ -81,11 +108,10 @@ scoreboard/ ### Scoreboard -- Punktestand für **Team A** und **Team B** -- Punkte einzeln erhöhen (+1) oder verringern (-1) +- Punktestand für **Team A** und **Team B**, direkt im Admin-Panel über +1/-1 steuerbar - Score direkt auf einen bestimmten Wert setzen - Score zurücksetzen (beide Teams auf 0) -- **Scoreboard ein-/ausblenden:** Der Monitor wechselt zwischen Timer-only-Ansicht (`index.hbs`) und Timer+Score-Ansicht (`indexScore.hbs`) +- **Scoreboard ein-/ausblenden:** Der Monitor wechselt zwischen Timer-only-Ansicht und Timer+Score-Ansicht ### Teams konfigurieren @@ -97,13 +123,47 @@ Jedes Team hat folgende Felder: | `name2` | Zweiter Name (nur bei Spielgemeinschaft) | | `isSpielgemeinschaft` | Wenn aktiv, werden beide Namen untereinander angezeigt | +Die Namen können frei eingetippt oder per Dropdown aus der **Team-Datenbank** gewählt werden. + +### Team-Datenbank + +Häufig verwendete Teamnamen werden in `db.json` gespeichert und stehen im +Konfigurationsdialog als Auswahl zur Verfügung. Teams lassen sich im +Debugfenster hinzufügen und löschen. + ### Seitenwechsel (Halbzeit) -Über "Seitenwechsel" werden Team A und Team B auf dem Monitor die Seiten tauschen — der Spielstand bleibt unverändert, nur die Anzeigepositionen (links/rechts) wechseln. +Über "Seitenwechsel" tauschen Team A und Team B auf dem Monitor die Seiten — der Spielstand bleibt unverändert, nur die Anzeigepositionen (links/rechts) wechseln. + +### Spiegelung des Admin-Panels + +Sitzt die Bedienung **hinter** dem Monitor, stimmt die Links/Rechts-Zuordnung im +Admin-Panel nicht mehr mit der Sicht auf die Anzeigetafel überein. Der Schalter +"Teamanzeige im Adminpanel spiegeln" im Debugfenster dreht die Darstellung im +Admin-Panel um — inklusive der +1/-1-Buttons, die dann dem jeweils richtigen Team +zugeordnet werden. Die Monitoranzeige bleibt davon unberührt. + +### Splashscreen + +Standardmäßig zeigt der Monitor beim Start das Vereinslogo. Über den Schalter im +Debugfenster wird zwischen Splashscreen und Spielanzeige umgeschaltet. + +### Debugfenster + +Sammelt die selten benötigten Schalter: Spiegelung, Scoreboard ein/aus, +Splashscreen ein/aus, Monitor neu laden, Kiosk-Browser starten/stoppen sowie die +Verwaltung der Team-Datenbank. + +### Kiosk-Browser steuern + +Auf dem Anzeige-Rechner (Raspberry Pi) kann der Chromium-Browser aus dem +Admin-Panel heraus im Kiosk-Modus gestartet und wieder beendet werden. Die +Funktion ist Linux-spezifisch und setzt einen Benutzer `pi` mit Zugriff auf +Display `:0` voraus. ### Monitor neu laden -Der Button "Monitor neu laden" im Admin-Panel sendet ein `refresh`-Event an alle verbundenen Clients und löst einen Seiten-Reload des Monitors aus. Nützlich z.B. nach dem Ein-/Ausblenden des Scoreboards. +Der Button "Monitor neu laden" sendet ein `refresh`-Event an alle verbundenen Clients und löst einen Seiten-Reload des Monitors aus. Nötig, wenn zwischen zwei Ansichten gewechselt wurde. --- @@ -118,19 +178,25 @@ Admin-Panel (Browser) routes/admin.js │ ├── controllers/timer.js ──┐ - └── controllers/score.js ──┤ - │ io.sockets.emit(event, data) - ▼ - Socket.IO-Server :3001 + ├── controllers/score.js ──┤ + ├── controllers/etc.js ──┤ + ├── controllers/db.js ──┐ │ + └── controllers/cli.js │ │ io.sockets.emit(event, data) + │ ▼ + db.json Socket.IO-Server :3001 │ WebSocket-Verbindung │ - ┌───────────────┴───────────────┐ - ▼ ▼ - Monitor (index.hbs) Monitor (indexScore.hbs) - index.js indexScore.js + ┌──────────────────────┼──────────────────────┐ + ▼ ▼ ▼ + Monitor (splashscreen) Monitor (index) Monitor (indexScore) + splashscreen.js index.js indexScore.js ``` +Der gesamte Spielzustand (Timer, Score, Teams, Schalter) liegt **im +Arbeitsspeicher** der Controller. Ein Serverneustart setzt ihn zurück; einzig die +Teamnamen in `db.json` bleiben erhalten. + ### WebSocket-Events | Event | Richtung | Beschreibung | @@ -152,6 +218,20 @@ Alle Endpunkte sind unter `/admin` erreichbar. | Methode | Endpunkt | Beschreibung | |---|---|---| | GET | `/admin/refreshMonitor` | Sendet `refresh` an alle Monitors | +| GET | `/admin/openBrowser` | Startet den Kiosk-Browser auf dem Anzeigerechner | +| GET | `/admin/killBrowser` | Beendet den Kiosk-Browser | + +### Anzeige (etc) + +| Methode | Endpunkt | Beschreibung | +|---|---|---| +| GET | `/admin/etcGetValues` | Aktuellen Splashscreen-Status abrufen | +| GET | `/admin/etcToggleSplashscreen` | Splashscreen ein-/ausblenden | + +Antwortformat: +```json +{ "splashscreenEnabled": true } +``` ### Timer @@ -163,12 +243,15 @@ Alle Endpunkte sind unter `/admin` erreichbar. | POST | `/admin/timerIncDec` | `{ value: }` | Timer erhöhen (positiv) / verringern (negativ) | | GET | `/admin/timerGetValues` | — | Aktuelle Timer-Werte abrufen | +`timerStart` und `timerPause` antworten mit **406**, wenn die Aktion nicht möglich +ist (Timer läuft bereits, ist bereits pausiert oder abgelaufen). + Antwortformat `timerGetValues`: ```json { "isPaused": true, - "duration": "", - "durationLeft": "", + "duration": "PT7M", + "durationLeft": "PT7M", "print": "07:00" } ``` @@ -181,6 +264,7 @@ Antwortformat `timerGetValues`: | GET | `/admin/scoreGetValues` | — | Aktuelle Score-Werte abrufen | | GET | `/admin/scoreClearScore` | — | Spielstand beider Teams auf 0 | | GET | `/admin/scoreToggleSideswitch` | — | Seiten der Teams tauschen | +| GET | `/admin/scoreToggleReferenceMirrored` | — | Admin-Panel-Darstellung spiegeln | | POST | `/admin/scoreSetScore` | `{ team, score }` | Score direkt setzen | | POST | `/admin/scoreAlterScore` | `{ team, dir }` | Score um 1 ändern (`dir`: `"inc"` / `"dec"`) | | POST | `/admin/scoreConfigTeams` | `{ teamA: { name, name2, isSpielgemeinschaft }, teamB: { ... } }` | Teams konfigurieren | @@ -190,14 +274,29 @@ Antwortformat `timerGetValues`: Antwortformat `scoreGetValues`: ```json { - "enabled": false, + "enabled": true, "teamA": { "name": "Team A", "name2": "", "score": 0, "isSpielgemeinschaft": 0 }, "teamB": { "name": "Team B", "name2": "", "score": 0, "isSpielgemeinschaft": 0 }, "sideswitch": false, - "print": "0:0" + "referenceMirrored": false, + "print": "0:0", + "teams": ["Arheilgen", "Prechtal"] } ``` +### Team-Datenbank + +| Methode | Endpunkt | Body | Beschreibung | +|---|---|---|---| +| GET | `/admin/dbGetValues` | — | Alle gespeicherten Teamnamen abrufen | +| POST | `/admin/dbAddTeam` | `{ teamName }` | Teamnamen hinzufügen (Duplikate und Leerstrings werden ignoriert) | +| POST | `/admin/dbDeleteTeam` | `{ teamName }` | Teamnamen löschen | + +Antwortformat: +```json +{ "teams": ["Arheilgen", "Prechtal"] } +``` + --- ## Abhängigkeiten