Die Chatkiste steht immer, Beenden raeumt auf -- und eine verspaetete Antwort ueberschreibt nichts Neueres mehr
Filipe, 30.09.2026: „wenn eine sendung beendet wurde soll alles
automatisch verschwinden. also von daten die da stehen von dem video."
Und: „mach dass ich die chat kiste immer sehe bitte und nicht erst
wenn das video läuft."
=====================================================================
1. BEENDET HEISST LEER
=====================================================================
Beim Beenden verschwinden Titel, YouTube-Adresse, Videotitel,
Vorschaubild, Beginn und das zweite Video samt seiner Stelle. Vorher
blieb alles stehen; beim naechsten Aufmachen stand dort der Titel der
letzten Sendung und ein Beginn, der in der Vergangenheit liegt.
ERST DER VERLAUF, DANN DAS LEEREN -- weg vom Schreibtisch heisst
nicht weg aus der Welt. Geprueft: Nach dem Beenden steht die Sendung
weiter in `reaktion_verlauf`, samt Video.
EINE FELDLISTE, NICHT ZWEI. Die Aufzaehlung stand in der
Zuruecksetzen-Route; jetzt brauchen sie zwei Wege. `SENDUNGS_FELDER`
und `PULT_EINSTELLUNGEN` stehen einmal oben. Zwei Abschriften waeren
die, die beim naechsten Spaltenzuwachs auseinanderlaufen -- genau so
sind am 11.09. drei Spalten mit Inhalt verlorengegangen.
Einstellungen (Bildaufteilung, Kameragroesse, Chatmodus) und die
Warteschlange bleiben -- die raeumt weiter nur „Alles zuruecksetzen"
ab. Wer nur vorbereitet und dann zumacht, behaelt seine Eingaben; das
ist eine Entscheidung und steht als Pruefung fest.
DAS FELD „BEGINN" WURDE NIE GELEERT, nur gefuellt:
`if (lage.beginnt_am && document.activeElement !== …)` -- zwei Fragen
in einer Bedingung, und die zweite beantwortete die erste
stillschweigend mit nein. Das betraf auch den vorhandenen
Zuruecksetzen-Knopf.
=====================================================================
2. DIE CHATKISTE STEHT IMMER
=====================================================================
Sie lag in `#teil-live` und ging mit ihm weg. Im Wartebereich stand
dabei woertlich „Der Chat ist schon offen" -- der Satz stimmte sogar,
der Server laesst dort schreiben (201, geprueft); zu sehen war der
Chat trotzdem nicht.
Die drei Haeute und die Schiene liegen jetzt in einem gemeinsamen
`.raum`: links wechseln die Haeute, rechts steht der Chat. Das Raster
wandert mit nach oben statt sich zu verdoppeln -- zwei
`grid-template-columns` fuer dieselbe Frage waren am 28.09. der
Grund, warum die Regieleiste null Pixel bekam.
Wer nicht schreiben darf, liest den Grund im Feld („Der Saal ist zu").
DER UMBAU HAT DREI DINGE VERSCHOBEN, und die Messung hat sie sofort
gefunden: Kino 0 px hoch, Spendenkarte bei x=1458 ausserhalb des
Bildes, „Kamera aus"-Schild kam nicht an. Eine Ursache: Zwei Regeln
(`grid-row: 2` und `grid-area: kino`) zielten auf die drei Haeute,
weil die frueher unmittelbar im Saal lagen. Gefunden hat das nicht
das Nachdenken, sondern eine Messung der ganzen Kette --
`teil-live 0x0 @1440,742` lag NEBEN dem Raum.
=====================================================================
3. „DER SAAL IST ZU" ERREICHTE NIEMANDEN, DER DARIN SASS
=====================================================================
`stand: "zu"` loescht `reaktion_dabei`, und `melden()` suchte seine
Empfaenger erst danach -- in genau dieser geleerten Liste. Die Seiten
der Zuschauer blieben auf „live" stehen.
`melden(art, daten, wer)` nimmt jetzt eine Empfaengerliste; die
Stand-Route bestimmt sie VOR jeder Aenderung.
UND EINE ZUGESPERRTE SEITE VERSTUMMTE FUER IMMER. War der Saal zu,
hielt `anschliessen()` jeden Takt an -- und Rundrufe bekam sie auch
keine, weil sie in keiner Liste mehr stand. Machte der Host wieder
auf, passierte bei allen mit offenem Reiter NICHTS. Nicht in dreissig
Sekunden: nie, bis jemand von Hand neu lud. Gemessen: Server sagt
„vorbereitung", die Seite zeigt „zu", auch nach 40 Sekunden.
Jetzt fragt eine geschlossene Seite alle 15 Sekunden nach -- der
ruhigste Zustand des Hauses, dort kostet das nichts.
=====================================================================
4. WER ZULETZT ANTWORTET, HAT NICHT RECHT
=====================================================================
Eine Abfrage ist Sekundenbruchteile unterwegs. Kommt in dieser Zeit
ein Rundruf an, ist SEIN Stand der neuere -- und trotzdem hat die
verspaetete Antwort ihn ueberschrieben.
Gemessen: Die Regie schaltet die Werbung auf Wechsel, der Rundruf
zeichnet ihn, und einen Augenblick spaeter steht wieder Laufband.
Eine feste Wartezeit in der Messung hatte das zugedeckt; es fiel
erst auf, als ich sie durch eine echte Bedingung ersetzte.
Drei Runden Raten lagen daneben. Gefunden hat es eine Mitschrift der
Aufrufkette:
wechsel:2 @ EventSource
laufband:2 @ zeichnen < standHolen < signalEmpfangen
Eine Folgenummer zaehlt jeden angekommenen Rundruf. Jede Abfrage, die
die Seite VON SICH AUS macht -- nach dem Verbindungsaufbau, im
geschlossenen Saal, bei jedem Verbindungssignal, nach einer
abgelehnten Anwesenheitsmeldung, und der Anwesenheitstakt selbst --
verwirft ihr Ergebnis, wenn inzwischen etwas Neueres da war.
Abfragen nach einer EIGENEN Handlung bleiben hart: Sie bringen Dinge
mit, die kein Rundruf traegt (die Verwaltungslisten der Regie). Die
Unterscheidung steht am Aufruf, nicht in einer Bedingung im Inneren.
=====================================================================
5. UND DIE MESSUNGEN WARTEN NICHT MEHR AUF DIE UHR
=====================================================================
Feste Wartezeiten sind dieselbe Falle wie feste Schwellen: Sie
stimmen, bis daneben etwas langsamer wird, und melden dann einen
Fehler, den es nicht gibt. Zweimal ist mir das in einer Stunde
passiert -- einmal beim Band, einmal bei den Ecken. Der Werbeblock
wartet jetzt fuenfmal auf das Ergebnis, der Gleichlauf viermal; laeuft
eine Frist ab, ist es ein echter Befund.
Die erste Fassung der Gleichlauf-Gegenprobe war selbst falsch -- sie
hielt das Selbstheilen des Systems fuer einen Fehler.
Neu in mess-reaktion: „Die Chatkiste in jedem Zustand" (alle drei,
mit Breite und Sperrgrund) und „Beendet heisst leer (im Pult)" -- dort
gemessen, wo Filipe hinsieht, nicht in der Datenbank.
Neu in pruef-reaktion (+14): das Leeren, die Gegenprobe „vorher war
etwas drin", der Verlauf bleibt, und die Entscheidung „wer nur
vorbereitet hat, behaelt seine Eingaben".
Gemessen: mess-reaktion dreimal hintereinander 0/0, pruef-reaktion
407/0, pruef-css-klassen 37/0, pruef-struktur 44/0, pruef-tippziele
13/0, pruef-haus-seiten 38/0, pruef-haus-trennung 100/0, pruef-buehne
38/0, pruef-push-ziel 38/0, mess-buehne 0.
Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -125,7 +125,12 @@ body.reaktion-seite > .kopfleiste { flex: none; }
|
||||
max-width: none;
|
||||
}
|
||||
.regieleiste { grid-row: 1; }
|
||||
#teil-zu, #teil-warte, #teil-live { grid-row: 2; }
|
||||
/* DER RAUM steht in der zweiten Zeile -- nicht mehr die drei Häute.
|
||||
Sie liegen seit dem 30.09.2026 in ihm und werden dort platziert
|
||||
(siehe „DER RAUM" weiter unten). Stünde die Angabe weiter an
|
||||
ihnen, legte sie sie in eine stillschweigende zweite Zeile DES
|
||||
RAUMS; gemessen war das Kino danach 0 px hoch. */
|
||||
.raum { grid-row: 2; }
|
||||
.pult { grid-row: 3; }
|
||||
.transport { grid-row: 4; }
|
||||
.transport[hidden] { display: none; }
|
||||
@@ -168,9 +173,12 @@ body.reaktion-seite > .kopfleiste { flex: none; }
|
||||
grid-template-rows: auto minmax(0, 1fr) auto auto;
|
||||
}
|
||||
.saal:has(.pult[data-auf="ja"]) .regieleiste { grid-area: leiste; }
|
||||
.saal:has(.pult[data-auf="ja"]) #teil-zu,
|
||||
.saal:has(.pult[data-auf="ja"]) #teil-warte,
|
||||
.saal:has(.pult[data-auf="ja"]) #teil-live { grid-area: kino; }
|
||||
/* Das Feld „kino" nimmt der RAUM ein -- darin stehen dann Bild und
|
||||
Chat nebeneinander, wie der Satz oben es beschreibt. Vor dem
|
||||
30.09.2026 standen hier die drei Häute; seit sie im Raum liegen,
|
||||
zeigte die Angabe auf ein Feld, das es in ihrem Raster nicht
|
||||
gibt, und das Kino landete mit 0 px neben dem Bild. */
|
||||
.saal:has(.pult[data-auf="ja"]) .raum { grid-area: kino; }
|
||||
.saal:has(.pult[data-auf="ja"]) .transport { grid-area: transport; }
|
||||
|
||||
.saal:has(.pult[data-auf="ja"]) .pult {
|
||||
@@ -319,6 +327,41 @@ body.reaktion-seite > .kopfleiste { flex: none; }
|
||||
/* ---------------------------------------------------------------------
|
||||
HÄUTE EIN- UND AUSBLENDEN
|
||||
--------------------------------------------------------------------- */
|
||||
/* ==== DER RAUM: zwei Spalten, und die rechte bleibt ===============
|
||||
|
||||
Filipe, 30.09.2026: „mach dass ich die chat kiste immer sehe bitte
|
||||
und nicht erst wenn das video läuft."
|
||||
|
||||
Die Schiene lag bis dahin IM Kino und ging mit ihm weg — sichtbar
|
||||
war sie damit nur im Live. Jetzt hält der Raum die Spalten: Links
|
||||
wechseln sich die drei Häute ab, rechts steht der Chat.
|
||||
|
||||
DIE SPALTEN STEHEN NUR HIER. `.kino` hatte sie vorher selbst;
|
||||
blieben sie dort, wären es zwei Antworten auf dieselbe Frage — und
|
||||
genau daran ist am 28.09. die Regieleiste auf null Pixel gelaufen,
|
||||
weil zwei `grid-template-rows` in dieser Datei standen und die
|
||||
spätere gewann. */
|
||||
.raum {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr minmax(19rem, 23rem);
|
||||
/* DIE ZEILE MUSS FEST SEIN. Ohne Angabe hat ein Raster eine
|
||||
stillschweigende Zeile, die sich am Inhalt bemisst — und darin
|
||||
steht `.kino` mit `height: 100%`, also „so hoch wie die Zeile".
|
||||
Zwei Angaben, die aufeinander zeigen; der Browser löst das mit
|
||||
NULL auf. Gemessen: Kino 613 px → 0 px, und mit der Leinwand
|
||||
rutschten Spendenkarte und Kamera-Schild aus dem Bild.
|
||||
|
||||
Vorher lag `.kino` unmittelbar in der Zeile `minmax(0, 1fr)` des
|
||||
Saals — die Festigkeit wandert hier mit. */
|
||||
grid-template-rows: minmax(0, 1fr);
|
||||
height: 100%;
|
||||
min-height: 0; /* sonst wächst das Raster über das Fenster */
|
||||
}
|
||||
/* ALLE DREI HÄUTE IN DIESELBE ZELLE. Nicht nebeneinander: Sichtbar
|
||||
ist immer genau eine, und die soll die ganze Spalte haben. */
|
||||
#teil-zu, #teil-warte, #teil-live { grid-area: 1 / 1; }
|
||||
.raum > .schiene { grid-area: 1 / 2; }
|
||||
|
||||
#teil-zu, #teil-warte, #teil-live { display: none; }
|
||||
.saal[data-stand="zu"] #teil-zu { display: grid; }
|
||||
.saal[data-stand="vorbereitung"] #teil-warte { display: grid; }
|
||||
@@ -445,7 +488,9 @@ body.reaktion-seite > .kopfleiste { flex: none; }
|
||||
LIVE — der Kinosaal
|
||||
===================================================================== */
|
||||
.kino {
|
||||
grid-template-columns: 1fr minmax(19rem, 23rem);
|
||||
/* KEINE SPALTEN MEHR — die hält seit dem 30.09.2026 `.raum`, weil
|
||||
die Chatschiene nicht mehr hier drinliegt. Hier stünde sonst die
|
||||
zweite Antwort auf dieselbe Frage. */
|
||||
gap: 0;
|
||||
height: 100%;
|
||||
min-height: 0; /* sonst wächst das Raster über das Fenster */
|
||||
@@ -2664,8 +2709,16 @@ body.reaktion-seite > .kopfleiste { flex: none; }
|
||||
}
|
||||
.transport__teil--rechts { justify-content: center; }
|
||||
|
||||
.kino {
|
||||
/* AM SCHMALEN GERÄT UNTEREINANDER: erst das Bild, dann der Chat.
|
||||
Die Angabe gehört an denselben Ort wie die breite — an den Raum,
|
||||
nicht ans Kino. */
|
||||
.raum {
|
||||
grid-template-columns: 1fr;
|
||||
grid-template-rows: auto minmax(0, 1fr);
|
||||
}
|
||||
#teil-zu, #teil-warte, #teil-live { grid-area: 1 / 1; }
|
||||
.raum > .schiene { grid-area: 2 / 1; }
|
||||
.kino {
|
||||
grid-template-rows: auto 1fr;
|
||||
}
|
||||
.leinwand {
|
||||
@@ -3064,7 +3117,10 @@ body[data-nur="buehne"] .spendentafel {
|
||||
body[data-nur="buehne"] .saal {
|
||||
height: 100dvh;
|
||||
}
|
||||
body[data-nur="buehne"] .kino { grid-template-columns: 1fr; }
|
||||
/* In der Bühnenquelle gibt es keinen Chat — dann soll die rechte
|
||||
Spalte auch keinen Platz belegen. */
|
||||
body[data-nur="buehne"] .raum,
|
||||
.obs-buehne .raum { grid-template-columns: 1fr; }
|
||||
body[data-nur="buehne"] { background: #000; }
|
||||
|
||||
/* ==== KEINE TASTENKUERZEL AM FINGERGERAET =========================
|
||||
|
||||
+188
-15
@@ -1264,7 +1264,16 @@
|
||||
den Wachhund zu warten; den behalten wir als Netz, aber
|
||||
er soll nicht der Normalfall sein. */
|
||||
if (!binSender && lage && lage.stand === 'live') {
|
||||
await standHolen().catch(() => { /* dann eben mit dem alten Stand */ });
|
||||
/* SANFT (30.09.2026): Diese Abfrage macht die Seite von
|
||||
sich aus, bei jedem Verbindungssignal. Kommt während
|
||||
ihrer Laufzeit ein Rundruf, ist der neuer.
|
||||
|
||||
Gemessen hat sie den frisch gesetzten Wechsel der
|
||||
Werbung wieder auf Laufband zurückgedreht — gefunden hat
|
||||
das nicht das Nachdenken, sondern eine Mitschrift der
|
||||
Aufrufkette: `zeichnen < standHolen < signalEmpfangen`.
|
||||
Drei Runden Raten davor lagen daneben. */
|
||||
await standHolen(true).catch(() => { /* dann eben mit dem alten Stand */ });
|
||||
}
|
||||
if (binSender && !meinStrom) await kameraHolen();
|
||||
const d = draht(von);
|
||||
@@ -2650,12 +2659,27 @@
|
||||
if (document.activeElement !== $('p-titel')) $('p-titel').value = lage.titel || '';
|
||||
if (document.activeElement !== $('p-video')) $('p-video').value = lage.video || '';
|
||||
if (document.activeElement !== $('p-vorschau')) $('p-vorschau').value = lage.vorschau || '';
|
||||
if (lage.beginnt_am && document.activeElement !== $('p-beginn')) {
|
||||
const d = new Date(lage.beginnt_am);
|
||||
if (!Number.isNaN(d.getTime())) {
|
||||
/* ZWEI FRAGEN, ZWEI BEDINGUNGEN (30.09.2026).
|
||||
|
||||
Hier stand `if (lage.beginnt_am && document.activeElement !== …)`.
|
||||
„Tippt gerade jemand darin?" ist die eine Frage, „gibt es einen
|
||||
Wert?" die andere — zusammengezogen beantwortet die zweite die
|
||||
erste stillschweigend mit nein: Fiel der Termin weg, wurde der
|
||||
ganze Block übersprungen, und im Kasten stand das alte Datum
|
||||
weiter, bis jemand die Seite neu lud.
|
||||
|
||||
Das betraf auch den Knopf „Alles zurücksetzen": Die Spalte war
|
||||
leer, das Pult zeigte den Termin trotzdem. Titel und Video
|
||||
haben es immer richtig gemacht (`|| ''`), dieses eine Feld
|
||||
nicht. */
|
||||
if (document.activeElement !== $('p-beginn')) {
|
||||
const d = lage.beginnt_am ? new Date(lage.beginnt_am) : null;
|
||||
if (d && !Number.isNaN(d.getTime())) {
|
||||
const p = (n) => String(n).padStart(2, '0');
|
||||
$('p-beginn').value = `${d.getFullYear()}-${p(d.getMonth() + 1)}-${p(d.getDate())}`
|
||||
+ `T${p(d.getHours())}:${p(d.getMinutes())}`;
|
||||
} else {
|
||||
$('p-beginn').value = '';
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3244,9 +3268,38 @@
|
||||
function stromAuf() {
|
||||
if (strom) return;
|
||||
strom = new EventSource('/workspace/api/chat/strom');
|
||||
strom.addEventListener('open', () => { stromOffen = true; });
|
||||
/* WER GERADE ZUHOEREN KANN, FRAGT NACH, WAS ER VERPASST HAT
|
||||
(30.09.2026).
|
||||
|
||||
Zwischen dem Laden der Seite und dem Offensein des Stroms
|
||||
liegt ein Fenster. Was die Regie darin umschaltet, kam bei
|
||||
dieser Seite NIE an: Der Rundruf ging hinaus, als noch niemand
|
||||
zuhoerte, und danach fragte niemand mehr nach.
|
||||
|
||||
Dasselbe nach jedem Abriss — der Browser baut den Strom von
|
||||
selbst wieder auf, aber alles aus der Unterbrechung ist weg.
|
||||
Die Seite zeigte dann einen Stand von vor dem Abriss, und zwar
|
||||
unbegrenzt: Ein Zuschauer lädt eine Stunde lang nicht neu.
|
||||
|
||||
Eine kleine Abfrage je Verbindung macht die Seite
|
||||
selbstheilend. Die Alternative wäre, jedem Rundruf zu
|
||||
glauben, dass er angekommen ist — und genau das war der
|
||||
Fehler. */
|
||||
strom.addEventListener('open', () => {
|
||||
stromOffen = true;
|
||||
/* SANFT: Diese Abfrage macht die Seite von sich aus. Kommt
|
||||
währenddessen ein Rundruf, ist der neuer — dann gilt er. */
|
||||
standHolen(true);
|
||||
});
|
||||
strom.addEventListener('reaktion', (e) => {
|
||||
try {
|
||||
/* JEDER RUNDRUF ZAEHLT — an EINER Stelle, ganz oben. In
|
||||
jeden Zweig einzeln geschrieben wäre es die Zeile, die
|
||||
beim nächsten Zweig vergessen wird. Dass dabei auch
|
||||
Rundrufe mitzählen, die `lage` gar nicht anfassen, ist
|
||||
die sichere Richtung: Im Zweifel behält die Seite, was
|
||||
sie über den Strom weiß. */
|
||||
standFolge++;
|
||||
const d = JSON.parse(e.data);
|
||||
if (d.was === 'video') {
|
||||
/* WER STEUERT, FOLGT SEINEM EIGENEN ECHO NICHT (29.09.2026).
|
||||
@@ -3265,10 +3318,23 @@
|
||||
danebensteht, muss weiter folgen, sonst sieht er etwas
|
||||
anderes als alle übrigen.
|
||||
|
||||
DAS TEMPO ZIEHT TROTZDEM MIT — es steht darunter und
|
||||
kommt nicht von seinem eigenen Spieler, sondern aus dem
|
||||
Regiepult. */
|
||||
if (!(lage?.host?.id && lage.host.id === meineId)) folgen(d);
|
||||
DAS TEMPO GILT AUCH FÜR IHN, und zwar ausdrücklich.
|
||||
Hier stand erst „das zieht trotzdem mit — es steht
|
||||
darunter". Das war falsch: Darunter wird `lage.tempo`
|
||||
gesetzt und das Schild neu gezeichnet; den SPIELER
|
||||
stellt allein `tempoNachziehen()`, und die steht in
|
||||
`folgen()`. Gemessen lief 2× bei ihm danach mit 0,50
|
||||
statt 2,00 Sekunden je Sekunde — er war der Einzige, bei
|
||||
dem die Geschwindigkeit nichts tat.
|
||||
|
||||
Das Tempo kommt nicht aus seinem Spieler zurück, sondern
|
||||
aus dem Pult. Es ist kein Echo seiner selbst, sondern
|
||||
eine Ansage. */
|
||||
if (lage?.host?.id && lage.host.id === meineId) {
|
||||
if (d.tempo) tempoNachziehen(d.tempo);
|
||||
} else {
|
||||
folgen(d);
|
||||
}
|
||||
/* DAS SCHILD MUSS MIT. `folgen()` stellt den Spieler, aber
|
||||
der Rundruf geht hier mit `return` heraus -- ohne diese
|
||||
zwei Zeilen stuende beim Zuschauer weiter „1x", waehrend
|
||||
@@ -3308,8 +3374,23 @@
|
||||
|
||||
`banner_alle` ist NICHT dabei -- die Verwaltungsliste
|
||||
samt abgeschalteten Entwuerfen gehoert nur der Regie.
|
||||
Wer sie braucht, holt den Stand. */
|
||||
if (lage) {
|
||||
Wer sie braucht, holt den Stand.
|
||||
|
||||
KOMMT ER VOR DEM STAND AN, wird der ganze Stand geholt
|
||||
statt den Rundruf wegzuwerfen (30.09.2026). Der
|
||||
Ereignisstrom haengt beim Aufbau der Seite; `lage` ist
|
||||
erst da, wenn `standHolen()` einmal durch ist. In dem
|
||||
Fenster dazwischen ging jeder Rundruf still verloren --
|
||||
wer die Seite gerade aufmachte, waehrend die Regie
|
||||
umschaltete, sah die Werbung nicht, und niemand merkte
|
||||
es.
|
||||
|
||||
Die Messung hat das als scheinbare Flatterhaftigkeit
|
||||
gezeigt: einmal fehlte das Laufband, beim naechsten Lauf
|
||||
der Wechsel. Ein Ergebnis, das zwischen zwei Laeufen
|
||||
springt, ist zuerst als Wettlauf verdaechtig. */
|
||||
if (!lage) { standHolen(); return; }
|
||||
{
|
||||
lage = { ...lage, werbung: {
|
||||
art: d.art, tempo: d.tempo, ecke_dogi: d.ecke_dogi,
|
||||
ecke_hase: d.ecke_hase, ecke_gross: d.ecke_gross, band: d.band,
|
||||
@@ -3443,17 +3524,53 @@
|
||||
if (!lage || lage.stand === 'zu') {
|
||||
clearInterval(draehteUhr);
|
||||
draehteWeg();
|
||||
|
||||
/* ABER NICHT VERSTUMMEN (30.09.2026).
|
||||
|
||||
Hier stand ein blankes `return` — und damit fragte die Seite
|
||||
nie wieder nach. Rundrufe bekommt sie in diesem Zustand auch
|
||||
keine: Wer nicht in `reaktion_dabei` steht, steht nicht in
|
||||
`empfaenger()`, und beim Schließen wird genau diese Liste
|
||||
geleert.
|
||||
|
||||
Folge: Macht der Host wieder auf, passiert bei allen, die den
|
||||
Reiter noch offen haben, NICHTS. Nicht später, nicht in
|
||||
dreißig Sekunden — nie, bis jemand von Hand neu lädt.
|
||||
Gemessen: Server sagt „vorbereitung", die Seite zeigt „zu",
|
||||
auch nach 40 Sekunden.
|
||||
|
||||
Ein geschlossener Saal ist der ruhigste Fall des ganzen
|
||||
Hauses: kein Video, keine Kameras, kein Chat. Eine kleine
|
||||
Abfrage alle fünfzehn Sekunden kostet dort nichts — und ist
|
||||
der Unterschied zwischen „es geht los" und „lad mal neu".
|
||||
|
||||
`anschliessen()` ruft sich danach selbst: Ist wieder
|
||||
aufgemacht, räumt dieser Aufruf den langsamen Takt weg und
|
||||
startet den richtigen. `standHolen()` allein täte das nicht
|
||||
— es zeichnet nur. */
|
||||
dabeiUhr = setInterval(async () => {
|
||||
await standHolen(true);
|
||||
anschliessen();
|
||||
}, 15_000);
|
||||
return;
|
||||
}
|
||||
await stromAbwarten();
|
||||
|
||||
const melden = async () => {
|
||||
try {
|
||||
/* DIE FOLGENUMMER GILT AUCH HIER (30.09.2026). Dieser Takt
|
||||
laeuft auf jeder Zuschauerseite alle 30 Sekunden und
|
||||
ersetzt den GANZEN Stand. Ist er unterwegs, waehrend ein
|
||||
Rundruf ankommt, gewinnt er -- obwohl der Rundruf das
|
||||
Neuere wusste. Gemessen: Der Wechsel der Werbung wurde
|
||||
gezeichnet und war einen Augenblick spaeter wieder leer. */
|
||||
const beim = standFolge;
|
||||
const a = await hole('/workspace/api/reaktion/dabei', { method: 'POST' });
|
||||
if (a.ok) {
|
||||
const neu = await a.json();
|
||||
lage = neu;
|
||||
zeichnen();
|
||||
if (beim === standFolge) { lage = neu; zeichnen(); }
|
||||
/* Die Verbindungen werden in jedem Fall nachgezogen -- das
|
||||
ist kein Stand, sondern der Draht dorthin. */
|
||||
draehteNachziehen();
|
||||
return;
|
||||
}
|
||||
@@ -3466,7 +3583,29 @@
|
||||
if (a.status === 403) {
|
||||
const wort = (await a.json().catch(() => null))?.fehler;
|
||||
if (wort === 'aus_der_sendung' || wort === 'treff_massnahme') rausgenommen(wort);
|
||||
return;
|
||||
}
|
||||
|
||||
/* JEDE ANDERE ABSAGE IST AUCH EINE AUSKUNFT (30.09.2026).
|
||||
|
||||
Der wichtigste Fall ist 409 „saal_zu". Ist der Saal zu,
|
||||
steht diese Person in keiner Dabei-Liste mehr — sie bekommt
|
||||
also auch keinen Rundruf, wenn wieder aufgemacht wird. Ihr
|
||||
Takt lief weiter, wurde jedes Mal abgewiesen, und die Seite
|
||||
blieb stehen. Nicht dreißig Sekunden: für immer, bis
|
||||
jemand neu lädt.
|
||||
|
||||
Gemessen: Nach dem Schließen und Wiederaufmachen stand die
|
||||
Seite der Zuschauerin auch nach 40 Sekunden noch auf „zu".
|
||||
|
||||
Wer nicht sagen kann, ob er dabei ist, holt den Stand.
|
||||
Eine kleine Abfrage je halber Minute — und der Unterschied
|
||||
zwischen einer Seite, die sich fängt, und einer, die man
|
||||
neu laden muss.
|
||||
|
||||
SANFT, wie jede Abfrage, die die Seite von sich aus
|
||||
macht. */
|
||||
standHolen(true);
|
||||
} catch { /* der nächste Takt versucht es wieder */ }
|
||||
};
|
||||
melden();
|
||||
@@ -4034,10 +4173,44 @@
|
||||
document.body.append(kasten);
|
||||
}
|
||||
|
||||
async function standHolen() {
|
||||
/* ==== WER ZULETZT ANTWORTET, HAT NICHT RECHT (30.09.2026) =======
|
||||
|
||||
Eine Abfrage ist Sekundenbruchteile unterwegs. Kommt in dieser
|
||||
Zeit ein Rundruf an, ist SEIN Stand der neuere — und trotzdem
|
||||
hat die verspätete Antwort ihn überschrieben, weil sie später
|
||||
ankam.
|
||||
|
||||
Gemessen: Die Regie schaltet die zwei Eckenbilder ein, der
|
||||
Rundruf zeichnet sie, und eine Sekunde später waren sie wieder
|
||||
weg — eine beim Seitenaufbau gestartete Abfrage war
|
||||
zurückgekommen und hatte den Stand von vorher gesetzt. Eine
|
||||
feste Wartezeit in der Messung hatte das monatelang zugedeckt;
|
||||
sie fiel erst auf, als ich sie durch eine echte Bedingung
|
||||
ersetzte.
|
||||
|
||||
Die Folgenummer zählt jeden angekommenen Rundruf. Eine SANFTE
|
||||
Abfrage merkt sie sich, bevor sie losgeht, und wirft ihr
|
||||
Ergebnis weg, wenn inzwischen etwas Neueres da war. */
|
||||
let standFolge = 0;
|
||||
|
||||
/** Den ganzen Stand holen.
|
||||
*
|
||||
* @param sanft `true`: verwirft das Ergebnis, wenn währenddessen
|
||||
* ein Rundruf angekommen ist. Für Abfragen, die die
|
||||
* Seite von sich aus macht (nach dem Verbindungs-
|
||||
* aufbau, im geschlossenen Saal).
|
||||
*
|
||||
* Ohne Angabe gewinnt die Abfrage — sie bringt
|
||||
* Dinge mit, die kein Rundruf trägt (etwa die
|
||||
* Verwaltungsliste der Regie). Dort wäre der
|
||||
* Vorrang des Rundrufs ein Verlust. */
|
||||
async function standHolen(sanft) {
|
||||
const beim = standFolge;
|
||||
const a = await hole('/workspace/api/reaktion');
|
||||
if (!a.ok) { sagFehler('Die Reaction ist gerade nicht erreichbar.'); return; }
|
||||
lage = await a.json();
|
||||
const neu = await a.json();
|
||||
if (sanft && beim !== standFolge) return;
|
||||
lage = neu;
|
||||
zeichnen();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user