diff --git a/server/mess-quer.mjs b/server/mess-quer.mjs index 3c0e8749..be2f7c98 100644 --- a/server/mess-quer.mjs +++ b/server/mess-quer.mjs @@ -310,6 +310,7 @@ const GERAETE = [ ["Handy", 412, 915], ["iPhone", 390, 844], ["kleines Handy", 360, 640], + ["kleinstes Handy", 320, 568], ]; let befunde = 0; @@ -374,6 +375,16 @@ for (const [gname, breite, hoehe] of GERAETE) { const register = await host.seite.evaluate(() => [...document.querySelectorAll(".reiter__knopf")].map((b) => b.dataset.tafel)); console.log(` Register: ${register.join(" · ")}`); + { + const z = await host.seite.evaluate(() => { + const saal = document.getElementById("saal"); + const teile = [...saal.children].filter((e) => e.getBoundingClientRect().height > 0) + .map((e) => { const q = e.getBoundingClientRect(); + return `${e.id || e.className.split(" ")[0]} ${Math.round(q.top)}..${Math.round(q.bottom)}`; }); + return `Zeilen ${getComputedStyle(saal).gridTemplateRows} | ${teile.join(" / ")}`; + }); + console.log(` ${z}`); + } /* Erst die Seite als Ganzes. */ const seitlich = await host.seite.evaluate(() => diff --git a/server/mess-reaktion.mjs b/server/mess-reaktion.mjs index 765c5918..4bfb3400 100644 --- a/server/mess-reaktion.mjs +++ b/server/mess-reaktion.mjs @@ -2456,15 +2456,55 @@ await zuschauer.kontext.close(); const alle = [...document.getElementById("saal").children] .filter((e) => e.getBoundingClientRect().height > 0) .map((e) => `${e.id || e.className.split(" ")[0]}=${Math.round(e.getBoundingClientRect().height)}`); + /* WIEVIEL VOM BILD IST WIRKLICH ZU SEHEN? + Die Hoehe der Kinozeile sagt das nicht: Seit die Regie am + Handy eine Schublade darueber ist, kann die Zeile 431 Pixel + hoch sein und trotzdem vollstaendig verdeckt. Ein gruener + Haken ueber eine Zeilenhoehe waere genau die Sorte, die das + Falsche misst. Gefragt ist der Streifen, der oberhalb der + Schublade uebrig bleibt. */ + const kino = document.getElementById("teil-live").getBoundingClientRect(); + const regie = document.getElementById("pult").getBoundingClientRect(); + const frei = Math.max(0, Math.round(Math.min(kino.bottom, regie.top) - kino.top)); return { saal: g("saal"), leiste: g("regieleiste"), kino: g("teil-live"), pult: g("pult"), - alle: alle.join(" + ") }; + frei, alle: alle.join(" + ") }; }); console.log(` Handy offen: Saal ${platzHandy.saal} = Leiste ${platzHandy.leiste} ` + `+ Kino ${platzHandy.kino} + Regie ${platzHandy.pult}`); console.log(` Handy Zeilen: ${platzHandy.alle}`); - if (platzHandy.kino < 190) { + const spur = await chef.seite.evaluate(() => { + const saal = document.getElementById("saal"); + const r = saal.getBoundingClientRect(); + const teile = [...saal.children].filter((e) => e.getBoundingClientRect().height > 0) + .map((e) => { + const q = e.getBoundingClientRect(); + return `${e.id || e.className.split(" ")[0]} ${Math.round(q.top)}..${Math.round(q.bottom)}`; + }); + const tr = document.querySelector(".transport"); + const teileT = [...(tr ? tr.children : [])].map((e) => { + const q = e.getBoundingClientRect(); + return `${e.className.split(" ")[0]}=${Math.round(q.height)}`; + }); + return `Saal ${Math.round(r.top)}..${Math.round(r.bottom)} (Fenster ${window.innerHeight})` + + ` | Zeilen ${getComputedStyle(saal).gridTemplateRows}` + + ` | ${teile.join(" / ")}` + + ` | Transport: ${teileT.join(" + ")}` + + ` | Regie-Kopf: ${(() => { + const l = document.querySelector(".pult__leiste"); + if (!l) return "-"; + const kinder = [...l.children].map((e) => { + const q = e.getBoundingClientRect(); + return `${e.className.split(" ")[0] || e.tagName.toLowerCase()}` + + ` ${Math.round(q.top)}..${Math.round(q.bottom)}`; + }); + return `${Math.round(l.getBoundingClientRect().height)} px = ${kinder.join(" / ")}`; + })()}`; + }); + console.log(` SPUR: ${spur}`); + console.log(` Vom Bild sichtbar (nicht von der Regie verdeckt): ${platzHandy.frei} px`); + if (platzHandy.frei < 120) { offenePunkte.push(`Am Handy bleibt bei offener Regie vom Bild fast nichts ` - + `(${platzHandy.kino} px, noetig 190). Bekannt seit 28.09.2026. ` + + `(${platzHandy.frei} px sichtbar, noetig 120). Bekannt seit 28.09.2026. ` + `Wurzel: die umgebrochene Transportleiste braucht auf 320 px ` + `Breite 220 Pixel. Der Weg steht in reaktion.css beim Handy-Block.`); } diff --git a/server/pruef-reaktion.mjs b/server/pruef-reaktion.mjs index 3d214f0b..f978f45d 100644 --- a/server/pruef-reaktion.mjs +++ b/server/pruef-reaktion.mjs @@ -989,12 +989,39 @@ melde("=== 12. Die Regie ==="); Grundregeln, die beide sagen, WIE das Bauteil gebaut ist -- `grid` gegen `flex`, wie bei `.stufen`. */ const positiv = (wert) => wert && wert !== "none" && !/^none/.test(wert); + + /* ZWEI EINSCHRAENKUNGEN MEHR, BEIDE AM 29.09.2026 NOETIG GEWORDEN. + + (3) Der Selektor muss GENAU die Klasse sein. `.saal .pult { + display: flex }` ist keine zweite Grundregel zu `.pult { + display: grid }`, sondern dieselbe Klasse in einem anderen + Zusammenhang -- und genau dafuer sind Selektoren da. Die + erste Fassung nahm jede Klasse, der ein Trennzeichen + vorausging, und meldete deshalb `pult (grid vs. flex)`. + + (4) Regeln INNERHALB einer Medienabfrage zaehlen nicht. Sie + sind per Definition eine Variante fuer eine andere + Umgebung -- `messwerte__paar` steht am Fingergeraet als + `flex` und sonst als `grid`, und das ist die Absicht. + + Was uebrig bleibt, ist der Fall, um den es ging: `.stufen` + stand zweimal als blanke Grundregel, ohne Medienabfrage und + ohne Zusammenhang -- zwei verschiedene Bauteile, ein Name. */ + const ohneMedien = (text) => text.replace( + /@media[^{]*\{(?:[^{}]|\{[^{}]*\})*\}/g, + (m) => m.replace(new RegExp("[^" + String.fromCharCode(10) + "]", "g"), " ")); + const lies = (text) => { const raus = {}; - for (const m of text.matchAll(/(^|[\s};])(\.(-?[a-zA-Z_][a-zA-Z0-9_-]*))\s*\{([^{}]*)\}/g)) { - const wert = (m[4].match(/(?:^|[\s;])display\s*:\s*([^;]+)/) || [, ""])[1].trim(); + /* LOOKBEHIND STATT VERBRAUCHEN. Mit `(^|[};])` frisst der erste + Treffer die schliessende Klammer, die der naechste als Anfang + braeuchte -- `.stufen { … } .stufen { … }` lieferte dann nur + EINEN Treffer, und die Gegenprobe zum echten Fall vom 28.09. + schlug fehl. */ + for (const m of ohneMedien(text).matchAll(/(?:^|(?<=[};]))\s*(\.(-?[a-zA-Z_][a-zA-Z0-9_-]*))\s*\{([^{}]*)\}/g)) { + const wert = (m[3].match(/(?:^|[\s;])display\s*:\s*([^;]+)/) || [, ""])[1].trim(); if (!positiv(wert)) continue; - (raus[m[3]] ||= []).push(wert); + (raus[m[2]] ||= []).push(wert); } return raus; }; @@ -1010,20 +1037,33 @@ melde("=== 12. Die Regie ==="); : `${Object.keys(grundregeln).length} Klassen sagen, WIE sie gebaut sind ` + "-- keine davon zweimal verschieden"); - /* GEGENPROBE: Findet die Regel einen eingeschobenen Streit? Ohne - diese Zeile waere oben nur bewiesen, dass sie „in Ordnung" - sagen kann. Eingeschoben wird genau der Fall vom 28.09.: eine - zweite Grundregel mit einem anderen positiven display. */ - ok(streitIn(roh("reaktion.css") + " .pult-tafel { display: flex; } ") - .some((z) => z.startsWith("pult-tafel (")), - "Gegenprobe: eine zweite Grundregel mit anderem display faellt auf"); - - /* UND IN DIE ANDERE RICHTUNG: Ein Bauteil, das erst versteckt und - dann gezeigt wird, darf NICHT anschlagen -- sonst haette man - die Regel nur so lange geschaerft, bis sie alles meldet. */ - ok(streitIn(" .probe { display: none; } .probe { display: grid; } ").length === 0 - && streitIn(" .probe { display: grid; } .probe { display: flex; } ").length === 1, - "Gegenprobe: verstecken-und-zeigen ist kein Streit, grid-gegen-flex schon"); + /* GEGENPROBEN AN EIGENSTAENDIGEN TEXTEN, nicht an die echte + Datei angehaengt. Die erste Fassung tat das -- und scheiterte, + sobald der Sucher Medienabfragen ausklammert: Was hinter dem + letzten `@media` angehaengt wird, kann darin verschwinden. + Eine Gegenprobe, die vom Inhalt der geprueften Datei abhaengt, + prueft nicht die Regel, sondern die Datei. */ + { + const faelle = [ + ["der Fall vom 28.09. (zwei Grundregeln, anderes display)", + ".stufen { display: grid; } .stufen { display: flex; }", true], + ["verstecken und zeigen", + ".probe { display: none; } .probe { display: grid; }", false], + ["dieselbe Klasse in einem Zusammenhang", + ".pult { display: grid; } .saal .pult { display: flex; }", false], + ["eine Variante in einer Medienabfrage", + ".paar { display: grid; } @media (pointer: coarse) { .paar { display: flex; } }", false], + ["zweimal dasselbe display", + ".gleich { display: grid; } .gleich { display: grid; }", false], + ]; + const daneben = faelle + .filter(([, text, soll]) => (streitIn(text).length > 0) !== soll) + .map(([name]) => name); + ok(daneben.length === 0, + daneben.length ? `Gegenprobe daneben bei: ${daneben.join(", ")}` + : `Gegenprobe: alle ${faelle.length} Faelle richtig eingeordnet ` + + "(Streit, Zustand, Zusammenhang, Medienabfrage, Wiederholung)"); + } /* ---- Nichts rollt absichtlich waagerecht ---------------------- diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html index 7a2c171b..487a394a 100644 --- a/workspace/anruf-probe.html +++ b/workspace/anruf-probe.html @@ -16,8 +16,8 @@ verdeckt. Gefunden hat es pruef-struktur. Richtig sind `gate.css` (die Farbwerte des Hauses) und `haus.css`. --> - - + + - +