From f09a0c34567a2a9bf1215380fcac03c80a3fd4aa Mon Sep 17 00:00:00 2001 From: Dogfather Date: Tue, 6 Oct 2026 16:52:51 +0200 Subject: [PATCH] Rundgang: drei Schritte fuer die Community, fuenf fuers Team Bauplan Kapitel 10 verlangt "Community drei Schritte, Team-Rollen fuenf Schritte (zusaetzlich 'Deine Aufgaben' und die Gruppen ...)". Gemessen hatte die Community bisher FUENF -- sie bekam auch die beiden Arbeitslisten gezeigt, "Was ist dran" und "Deine Aufgaben". Auf ihrer Zentrale stehen beide Kaesten zwar, aber leer; eine Station, die vor einem leeren Kasten erklaert, was dort sonst steht, ist schlechter als keine. WO DIE ENTSCHEIDUNG LIEGT, UND WARUM NICHT IN rundgang.js: Der Server schickt mit der Einweisung jetzt `team: true/false` (abgeleitet aus AUSSEN_ROLLEN, nicht aus einer zweiten Liste von Rollennamen). `rundgang.js` siebt damit und kennt weiterhin keinen einzigen Rollennamen. Haette ich die Rollen dort hineingeschrieben, waere jede spaeter dazukommende Rolle stillschweigend eine Teamrolle -- und niemand kaeme auf die Idee, in einer Datei ueber Begruessungen nach Rechten zu suchen. ZWEI SIEBE, UND BEIDE SIND NOETIG: `nurTeam` nimmt der Community die Arbeitslisten, `querySelector` nimmt jedem das, was auf SEINER Zentrale gar nicht steht. Ohne das zweite bliebe der Rundgang vor einem Kasten stehen, den es nicht gibt. Dazu zwei Kleinigkeiten, beide beim Nachmessen aufgefallen: * Die Begruessung sagte "In fuenf Minuten"; im Bauplan steht "In zwei Minuten". Fuenf Minuten sind eine Ankuendigung, die abschreckt -- und bei drei Schritten auch nicht wahr. * Ohne Namen stand dort "Willkommen im Creator Workspace". Dieselbe Datei laeuft auf beiden Adressen; bei Team Dogi war das das falsche Haus. Jetzt nur "Willkommen!" -- kein Haus zu nennen ist besser als das falsche. GEPRUEFT (pruef-anleitung 137 -> 148): Die Zaehlung wird nicht nachgebildet, sondern AUSGEFUEHRT: Die Stationsliste und der Siebausdruck werden aus der echten Datei geholt und laufen zweimal, mit team=false und team=true. Ein Muster ("steht da istTeam?") waere gruen, sobald das Wort in einem Kommentar steht -- genau der Fall, der am 04.10. bei pruef-anruf-klingelt aufgefallen ist. Gegenprobe gefahren: Sieb entfernt -> drei FEHL, Anzahl bleibt 148 (kein stilles Ueberspringen). Dazu eine Zeile, die festhaelt, dass in rundgang.js kein Rollenname steht, auf dem Code ohne Kommentare. Im Browser nachgemessen (mess-anleitung-crew, echte Anmeldung, 390 px, HTTPS-Vorbau wegen HSTS): Community 3 Stationen, Rechte Hand 5, beide mit der neuen Begruessung. Co-Authored-By: Claude Opus 5 --- server/mess-anleitung-crew.mjs | 41 +++++++++++++++++ server/pruef-anleitung.mjs | 79 +++++++++++++++++++++++++++++++++ server/workspace-anleitung.js | 12 ++++- workspace/anleitung.html | 28 ++++++------ workspace/anruf-probe.html | 10 ++--- workspace/app.webmanifest | 8 ++-- workspace/assets/js/rundgang.js | 44 ++++++++++++++---- workspace/aufgaben.html | 38 ++++++++-------- workspace/automation.html | 32 ++++++------- workspace/befinden.html | 34 +++++++------- workspace/bereich.html | 44 +++++++++--------- workspace/bewerben.html | 38 ++++++++-------- workspace/bewerbungen.html | 36 +++++++-------- workspace/buehne.html | 6 +-- workspace/calls.html | 34 +++++++------- workspace/chat.html | 40 ++++++++--------- workspace/content.html | 34 +++++++------- workspace/crew-index.html | 12 ++--- workspace/crew.webmanifest | 8 ++-- workspace/dateien.html | 34 +++++++------- workspace/entwicklung.html | 36 +++++++-------- workspace/hilfe.html | 30 ++++++------- workspace/index.html | 10 ++--- workspace/kalender.html | 34 +++++++------- workspace/leistung.html | 32 ++++++------- workspace/manager-ziele.html | 28 ++++++------ workspace/material.html | 32 ++++++------- workspace/notizen.html | 28 ++++++------ workspace/personen.html | 32 ++++++------- workspace/profil.html | 36 +++++++-------- workspace/reaktion.html | 38 ++++++++-------- workspace/rechte.html | 34 +++++++------- workspace/report.html | 36 +++++++-------- workspace/scouting.html | 32 ++++++------- workspace/start.html | 36 +++++++-------- workspace/startcheck.html | 34 +++++++------- workspace/steckbrief.html | 36 +++++++-------- workspace/support.html | 28 ++++++------ workspace/tafel.html | 6 +-- workspace/talente.html | 36 +++++++-------- workspace/team.html | 32 ++++++------- workspace/teamlage.html | 34 +++++++------- workspace/teilen.html | 30 ++++++------- workspace/treff-moderation.html | 32 ++++++------- workspace/treff-regeln.html | 32 ++++++------- workspace/uebersicht.html | 32 ++++++------- workspace/unsere-seiten.html | 30 ++++++------- workspace/unterstuetzen.html | 32 ++++++------- workspace/werdegang.html | 32 ++++++------- workspace/wissen.html | 34 +++++++------- 50 files changed, 852 insertions(+), 694 deletions(-) diff --git a/server/mess-anleitung-crew.mjs b/server/mess-anleitung-crew.mjs index d1fc0552..b7cec7da 100644 --- a/server/mess-anleitung-crew.mjs +++ b/server/mess-anleitung-crew.mjs @@ -239,6 +239,47 @@ for (const [rolle, wie] of ROLLEN) { console.log(` Browsermeldungen : ${klagen.length ? klagen.join(" | ") : "keine"}`); console.log(` Fehlgeschlagen : ${schlecht.length ? schlecht.slice(0, 6).join(" | ") : "nichts"}`); + /* ==== DER RUNDGANG BEIM ERSTEN ANMELDEN (Bauplan Kapitel 10) ==== + + Er ist selbstanpassend gebaut ("Wird ein Ziel nicht gefunden, + faellt der Schritt weg") -- daraus sollen sich die drei Schritte + der Community und die fuenf der Teamrollen von selbst ergeben. + Geglaubt wird das nicht, es wird gezaehlt. */ + const start = await kontext.newPage(); + await start.goto(`https://${CREW}:${HP}/workspace/start.html`, + { waitUntil: "networkidle" }); + await start.waitForTimeout(1800); + const gruss = await start.evaluate(() => { + const g = document.querySelector(".rg-gruss"); + return { da: !!g, text: (g?.textContent || "").replace(/\s+/g, " ").trim().slice(0, 70) }; + }); + let stationen = 0; + if (gruss.da) { + await start.evaluate(() => { + const k = [...document.querySelectorAll(".rg-gruss button")] + .find((b) => /Los/i.test(b.textContent || "")); + k?.click(); + }); + await start.waitForTimeout(700); + /* Durchklicken und zaehlen, wie viele Stationen es wirklich gibt. */ + for (let i = 0; i < 9; i++) { + const da = await start.evaluate(() => !!document.querySelector(".rg__kasten")); + if (!da) break; + stationen++; + const weiter = await start.evaluate(() => { + const b = [...document.querySelectorAll(".rg__knoepfe button")] + .find((x) => /Weiter|Fertig|Los/i.test(x.textContent || "")); + if (!b) return false; + b.click(); return true; + }); + if (!weiter) break; + await start.waitForTimeout(400); + } + } + console.log(` Begruessung : ${gruss.da} "${gruss.text}"`); + console.log(` Stationen gezaehlt : ${stationen}`); + await start.close(); + await seite.screenshot({ path: new URL("./" + datei, import.meta.url).pathname .replace(/^\/([A-Za-z]:)/, "$1"), fullPage: true }); await kontext.close(); diff --git a/server/pruef-anleitung.mjs b/server/pruef-anleitung.mjs index 465149db..521348b7 100644 --- a/server/pruef-anleitung.mjs +++ b/server/pruef-anleitung.mjs @@ -890,6 +890,85 @@ ok(eDogi.code === 200 && eDogi.j?.zeigen === false, d5.close(); } +/* ===================================================================== + DREI SCHRITTE FUER DIE COMMUNITY, FUENF FUERS TEAM + --------------------------------------------------------------------- + Bauplan Kapitel 10: "Community drei Schritte ... Team-Rollen fuenf + Schritte (zusaetzlich 'Deine Aufgaben' und die Gruppen ...)". + + Gemessen wird das in ZWEI Haelften, weil die Entscheidung an zwei + Stellen liegt: + + 1. Der Server sagt Ja/Nein ("team"). Das ist die Stelle, an der + die Rolle vorkommt -- `rundgang.js` kennt absichtlich keinen + einzigen Rollennamen, sonst muesste jede neue Rolle dort + nachgetragen werden und waere sonst stillschweigend Team. + 2. Der Browser siebt damit die Stationen. + + Die zweite Haelfte wird hier NICHT nachgebildet, sondern + AUSGEFUEHRT: Stationsliste und Siebausdruck werden aus der echten + Datei geholt und laufen zweimal -- einmal mit team=true, einmal mit + team=false. Ein Muster ("steht da istTeam?") waere gruen, sobald das + Wort irgendwo in einem Kommentar steht; der Ausdruck selbst kann + nicht luegen. Und der zweite Lauf ist gleich die Gegenprobe: Faellt + das Sieb weg, kommen beide Male fuenf heraus, und beide Zeilen + schlagen an. */ +melde("\n=== Rundgang: drei Schritte / fuenf Schritte ==="); +{ + const erwartet = { gast: false, modi: true, linke: true, hand: true }; + for (const [rolle, soll] of Object.entries(erwartet)) { + const e = await einweisung(rolle, CREW_HOST); + ok(e.j?.team === soll, + `${rolle}: Server meldet team=${soll} (bekommen ${e.j?.team})`); + } + /* Das Agenturhaus arbeitet -- dort ist jede Rolle eine Teamrolle. + Diese Zeile ist die Gegenrichtung zum Gast: Sie beweist, dass das + Feld nicht einfach immer dasselbe antwortet. */ + const eCre = await einweisung("creator"); + ok(eCre.j?.team === true, `creator: Server meldet team=true (${eCre.j?.team})`); + + const quelle = readFileSync( + new URL("../workspace/assets/js/rundgang.js", import.meta.url), "utf8"); + + /* Die Stationsliste aus der echten Datei, als Ausdruck ausgefuehrt. */ + const anfang = quelle.indexOf("const STATIONEN = ["); + const ende = quelle.indexOf("\n ];", anfang); + const liste = anfang >= 0 && ende > anfang + ? vm.runInNewContext(quelle.slice(anfang + "const STATIONEN = ".length, ende + 4)) + : null; + ok(Array.isArray(liste) && liste.length === 5, + `fuenf Stationen in rundgang.js (${liste?.length})`); + ok(Array.isArray(liste) && liste.filter((s) => s.nurTeam).length === 2, + `davon zwei nur fuers Team (${liste?.filter((s) => s.nurTeam).length})`); + + /* Der Siebausdruck, ebenfalls aus der echten Datei. Faellt er weg, + ist das KEIN Ueberspringen, sondern ein Fehlschlag: Die Aussage + "die Community bekommt drei" waere dann unbewiesen, und genau das + ist der Zustand, den diese Pruefung verhindern soll. */ + const m = quelle.match(/\.filter\(\(s\) => \((s\.nurTeam[^\n]*?)\)\)/); + ok(!!m, `der Siebausdruck steht in rundgang.js${m ? "" : " — NICHT gefunden"}`); + if (m && Array.isArray(liste)) { + const sieb = (istTeam) => + liste.filter(vm.runInNewContext(`(s) => (${m[1]})`, { istTeam })).length; + ok(sieb(false) === 3, `Community: drei Stationen (${sieb(false)})`); + ok(sieb(true) === 5, `Teamrolle: fuenf Stationen (${sieb(true)})`); + } else { + ok(false, "Community/Team-Zaehlung nicht durchfuehrbar — Siebausdruck fehlt"); + ok(false, "Community/Team-Zaehlung nicht durchfuehrbar — Siebausdruck fehlt"); + } + + /* KEIN ROLLENNAME IN rundgang.js. Der Grund steht im Kopf der + Datei; diese Zeile haelt ihn fest, damit die naechste Rolle nicht + per Hand nachgetragen werden muss. */ + const nurCode = quelle + .replace(/\/\*[\s\S]*?\*\//g, " ") + .replace(/(^|[^:])\/\/[^\n]*/g, "$1 "); + const gefunden = ["'gast'", '"gast"', "'hand'", "'modi'", "'linke'", "'creator'"] + .filter((w) => nurCode.includes(w)); + ok(gefunden.length === 0, + `kein Rollenname im Code von rundgang.js${gefunden.length ? " — " + gefunden.join(", ") : ""}`); +} + /* ---------- Abschluss ------------------------------------------------ */ try { rmSync(ordner, { recursive: true, force: true }); } catch { /* egal */ } console.log(`\n${fehler ? "FEHLER: " + fehler : "Alles in Ordnung"} — ${geprueft} Prüfungen`); diff --git a/server/workspace-anleitung.js b/server/workspace-anleitung.js index 544a78a4..5743e9d3 100644 --- a/server/workspace-anleitung.js +++ b/server/workspace-anleitung.js @@ -33,7 +33,7 @@ ===================================================================== */ import express from "express"; -import { db, sitzungLesen } from "./workspace.js"; +import { db, sitzungLesen, AUSSEN_ROLLEN } from "./workspace.js"; import { STUFEN, PFLEGE_ROLLEN, fassungenFuer, } from "./anleitung-tabellen.js"; @@ -611,6 +611,16 @@ anleitungRouter.get("/workspace/api/anleitung/einweisung", (req, res) => { rolle, name: person.name || "", muss, + /* IST DAS EINE TEAMROLLE? (06.10.2026, Bauplan Kapitel 10) + "Community drei Schritte, Team-Rollen fuenf." + + Als Ja/Nein und nicht als Rollenname: rundgang.js laeuft im + Browser, und in dieser Datei steht bewusst kein einziger + Rollenname -- sie waere sonst am Tag nach der naechsten + Aenderung falsch, und zwar bei jedem, der sie schon geladen + hat. Gefragt wird dieselbe Menge, die auch sonst entscheidet, + wer von aussen kommt. */ + team: !AUSSEN_ROLLEN.has(rolle), }); } catch (fehler) { console.error("[workspace] Einweisung:", fehler?.message); diff --git a/workspace/anleitung.html b/workspace/anleitung.html index c8ba9a0a..fbab67e2 100644 --- a/workspace/anleitung.html +++ b/workspace/anleitung.html @@ -7,17 +7,17 @@ - - - - - + + + + + - - + + @@ -289,16 +289,16 @@ Und anleitung.js braucht es doppelt: Symbol, Farbe, Name und Adresse jeder Karte kommen von dort, nicht vom Server. --> - + - - - - - - + + + + + + diff --git a/workspace/anruf-probe.html b/workspace/anruf-probe.html index 88b66e18..86179a00 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`. --> - - + + - +