Die Rechtetafel siebt die Karten jetzt wirklich -- und „ab Dabei" steht dran
ZWEI SACHEN, EINE DAVON EIN ECHTER BEFUND. 1) DIE KARTEN KAMEN AN DER RECHTETAFEL VORBEI Der Bauplan sagt in Kapitel 04 und noch einmal in der Abnahme: "Leite die sichtbaren Karten aus derselben Rechte-Tafel ab, die rechte.html verwendet. Eine Rolle sieht nur Karten zu Seiten, die sie oeffnen darf; pruefe das SERVERSEITIG." Ich habe dafuer eine Pruefung geschrieben, die die Seite ueber die ECHTE Schnittstelle sperrt (nicht mit einem UPDATE in der Datenbank -- nur so laeuft tafelLaden() mit). Sie wurde sofort rot: Nach dem Sperren von bereich.html fuer einen Modi lieferte der Server weiterhin ALLE ELF Bereichs-Karten. Im Browser fiel das nicht auf, und das ist der heikle Teil: Die Seite verbindet jede Karte mit einer Kachel, und die Kachelliste ist gefiltert -- die Karten verschwanden also auf dem Bildschirm. Die TEXTE gingen trotzdem hinaus. Eine Oberflaeche, die etwas nicht anzeigt, ist keine Schranke; genau deshalb steht im Bauplan "serverseitig". Jetzt siebt `darfKarte()` an der Quelle. Der Pfad wird aus dem Schluessel GERECHNET (`bereich:highlight` -> /workspace/bereich.html), nicht aus einer Zuordnungsliste -- das ist die Umkehrung von `schluesselVonZiel`, und eine gepflegte Tabelle daneben waere die, die beim naechsten neuen Brett fehlt. Entschieden wird mit `darfSeite` selbst; hier wird nichts davon nachgebaut. Gegenprobe in derselben Pruefung: zuruecksperren -> die Karten sind wieder da (29 von 29). Und eine Zeile dazwischen, die zaehlt, dass NUR sie verschwunden sind -- waere mit der Sperre die halbe Anleitung weggefallen, waere die erste Zeile auch gruen gewesen. 2) „AB DABEI" UND „AB STAMM" AN DER KARTE (Kapitel 04) "Kann ein Community-Mitglied etwas wegen seiner Stufe noch nicht, steht das an der Karte." Auch das abgeleitet: aus TREFF_SCHREIBEN, derselben Tafel, die das Schreiben ENTSCHEIDET. `null` darin heisst "von aussen schreibt hier niemand" -- das ist keine Stufe, die man erreicht, und bekommt deshalb keine Marke. "ab Stamm" an einem Anschlagbrett waere ein Versprechen, das nie eingeloest wird. Als Wort, nicht als Schloss-Symbol: Ein Schloss sagt "du darfst nicht" und laesst offen, ob jemals. "ab Dabei" sagt, dass es kommt -- und wann, steht mit Datum in der Karte "Deine Stufe" darueber. Ruhig gestaltet, nicht rot: Es ist keine Sperre, sondern eine Auskunft ueber die Zeit. GEPRUEFT (pruef-anleitung 166 -> 173) Die wichtigste der neuen Zeilen ist die, dass die Marke nach dem Aufstieg VERSCHWINDET. Eine Marke, die bleibt, ist schlimmer als keine: Sie sagt jemandem, er duerfe etwas nicht, das er laengst darf, und er probiert es gar nicht erst. Gemessen an drei Karten mit drei verschiedenen Antworten (Chat: Dabei, Highlights: Stamm, Anschlagbrett: gar nichts) -- waere die Rechnung grob falsch, traefe sie alle drei gleich. Dazu die Gegenprobe, dass eine Teamrolle keine einzige solche Marke bekommt. Mitgelaufen: pruef-rechtetafel 19, pruef-rechte-umstellen 56, pruef-css-klassen, pruef-tippziele 13 -- alle gruen. Die Abnahmezahlen aus Kapitel 13 (14/29/29/34 mit ihrer Aufteilung) sind nach dem neuen Sieb unveraendert; das ist der Beleg, dass es im Normalfall nichts wegnimmt. Im Browser nachgemessen (390 px, echte Anmeldung): Community sieht vier Marken (Rudel-Chat, Wunschliste, Mitmachen „ab Dabei", Highlights „ab Stamm"), die rechte Hand keine einzige. Co-Authored-By: Claude Opus 5 <[email protected]>
This commit is contained in:
@@ -1186,6 +1186,110 @@ melde("\n=== Die Abnahme-Checkliste (Bauplan Kapitel 13) ===");
|
||||
}
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
„AB DABEI" UND „AB STAMM" AN DER KARTE (Bauplan Kapitel 04)
|
||||
---------------------------------------------------------------------
|
||||
„Kann ein Community-Mitglied etwas wegen seiner Stufe noch nicht,
|
||||
steht das an der Karte."
|
||||
|
||||
DIE WICHTIGE ZEILE IST DIE DRITTE: Nach dem Aufstieg muss die Marke
|
||||
VERSCHWINDEN. Eine Marke, die bleibt, ist schlimmer als keine --
|
||||
sie sagt jemandem, er duerfe etwas nicht, das er laengst darf, und
|
||||
er probiert es gar nicht erst.
|
||||
|
||||
GEMESSEN WIRD AN DREI KARTEN MIT DREI VERSCHIEDENEN ANTWORTEN, und
|
||||
das ist Absicht: Der Rudel-Chat braucht „Dabei", die Highlights
|
||||
brauchen „Stamm", und das Anschlagbrett braucht gar nichts (dort
|
||||
schreibt von aussen NIEMAND, auf keiner Stufe). Waere die Rechnung
|
||||
grob falsch, traefe sie alle drei gleich. */
|
||||
melde("\n=== „ab Dabei“ und „ab Stamm“ an der Karte ===");
|
||||
{
|
||||
const markeVon = (j, kachel) =>
|
||||
(j?.karten || []).find((k) => k.kachel === kachel)?.erst_ab ?? null;
|
||||
const gastId = (() => {
|
||||
const d = new DatabaseSync(process.env.WORKSPACE_DB);
|
||||
const z = d.prepare("SELECT id FROM personen WHERE rolle = 'gast'").get();
|
||||
d.close(); return z?.id || 0;
|
||||
})();
|
||||
const beitritt = (tageHer) => {
|
||||
const d = new DatabaseSync(process.env.WORKSPACE_DB);
|
||||
d.prepare("UPDATE personen SET erstellt = ? WHERE id = ?")
|
||||
.run(new Date(Date.now() - tageHer * 86400_000).toISOString(), gastId);
|
||||
d.close();
|
||||
};
|
||||
|
||||
beitritt(0);
|
||||
const neuJ = (await holen("gast", CREW_HOST)).j;
|
||||
ok(markeVon(neuJ, "chat:treff") === "Dabei"
|
||||
&& markeVon(neuJ, "bereich:highlight") === "Stamm"
|
||||
&& markeVon(neuJ, "bereich:anschlag") === null,
|
||||
`Stufe Neu: Chat „ab ${markeVon(neuJ, "chat:treff")}“, Highlights `
|
||||
+ `„ab ${markeVon(neuJ, "bereich:highlight")}“, Anschlagbrett `
|
||||
+ `${markeVon(neuJ, "bereich:anschlag") || "ohne Marke"}`);
|
||||
|
||||
beitritt(10);
|
||||
const dabeiJ = (await holen("gast", CREW_HOST)).j;
|
||||
ok(markeVon(dabeiJ, "chat:treff") === null
|
||||
&& markeVon(dabeiJ, "bereich:highlight") === "Stamm",
|
||||
`Stufe Dabei: die Chat-Marke ist weg (${markeVon(dabeiJ, "chat:treff") || "weg"}), `
|
||||
+ `die der Highlights bleibt (${markeVon(dabeiJ, "bereich:highlight")})`);
|
||||
|
||||
/* Eine Teamrolle hat keine Mitglieder-Stufe -- an ihren Karten darf
|
||||
nie eine solche Marke stehen. Ohne diese Zeile waere die Rechnung
|
||||
auch dann gruen, wenn sie die Stufe gar nicht beachtete. */
|
||||
const handJ = (await holen("hand", CREW_HOST)).j;
|
||||
const beimTeam = (handJ?.karten || []).filter((k) => k.erst_ab).length;
|
||||
ok(beimTeam === 0,
|
||||
`eine Teamrolle bekommt keine einzige Stufen-Marke (${beimTeam})`);
|
||||
beitritt(0);
|
||||
}
|
||||
|
||||
/* =====================================================================
|
||||
EINE SEITE SPERREN — UND DIE KARTE IST WEG (Bauplan Kapitel 13)
|
||||
---------------------------------------------------------------------
|
||||
„In ‚Wer sieht was' eine Seite sperren: Die Karte verschwindet bei
|
||||
dieser Rolle."
|
||||
|
||||
DAS IST DER PUNKT, AN DEM DIE ANLEITUNG GEFAEHRLICH WERDEN KANN.
|
||||
Eine Karte ist eine Einladung mit einem Knopf „Hingehen". Bleibt sie
|
||||
stehen, nachdem die Seite gesperrt wurde, schickt die Einweisung
|
||||
jemanden gegen eine Tuer — und erzaehlt ihm vorher noch, was dahinter
|
||||
zu tun waere. Der Bauplan verlangt deshalb ausdruecklich, dass die
|
||||
Karten aus DERSELBEN Tafel kommen wie die Tuer.
|
||||
|
||||
GESPERRT WIRD UEBER DIE ECHTE SCHNITTSTELLE, nicht mit einem
|
||||
UPDATE in der Datenbank: Nur so laeuft auch `tafelLaden()` mit, und
|
||||
genau dort koennte die Kette reissen. Danach wird die Sperre wieder
|
||||
aufgehoben und nachgemessen, dass die Karte zurueckkommt — sonst
|
||||
wuesste man nicht, ob sie verschwunden ist oder nur nie da war. */
|
||||
melde("\n=== Seite sperren, Karte weg (Abnahme Kapitel 13) ===");
|
||||
{
|
||||
const PFAD = "/workspace/bereich.html";
|
||||
const stellen = (erlaubt) => roh("/workspace/api/rechte/feld", CREW_HOST,
|
||||
{ pfad: PFAD, rolle: "modi", erlaubt }, kekse.admin, "PUT");
|
||||
|
||||
const vorher = (await holen("modi", CREW_HOST)).j?.karten || [];
|
||||
const bereicheVorher = vorher.filter((k) => k.kachel.startsWith("bereich:")).length;
|
||||
ok(bereicheVorher > 0,
|
||||
`vorher erklaert die Anleitung dem Modi ${bereicheVorher} Bereichs-Karten`);
|
||||
|
||||
const zu = await stellen(false);
|
||||
const gesperrt = (await holen("modi", CREW_HOST)).j?.karten || [];
|
||||
const bereicheGesperrt = gesperrt.filter((k) => k.kachel.startsWith("bereich:")).length;
|
||||
ok(zu.code === 200 && bereicheGesperrt === 0,
|
||||
`nach dem Sperren sind sie weg (HTTP ${zu.code}, noch ${bereicheGesperrt})`);
|
||||
/* UND NUR SIE. Waere mit der Sperre die halbe Anleitung
|
||||
verschwunden, waere die Zeile darueber auch gruen. */
|
||||
ok(gesperrt.length === vorher.length - bereicheVorher,
|
||||
`und nur sie (${vorher.length} - ${bereicheVorher} = ${gesperrt.length})`);
|
||||
|
||||
const auf = await stellen(true);
|
||||
const zurueck = (await holen("modi", CREW_HOST)).j?.karten || [];
|
||||
ok(auf.code === 200 && zurueck.length === vorher.length,
|
||||
`Gegenprobe: zurueckgestellt sind sie wieder da (${zurueck.length} von `
|
||||
+ `${vorher.length})`);
|
||||
}
|
||||
|
||||
/* ---------- Abschluss ------------------------------------------------ */
|
||||
try { rmSync(ordner, { recursive: true, force: true }); } catch { /* egal */ }
|
||||
console.log(`\n${fehler ? "FEHLER: " + fehler : "Alles in Ordnung"} — ${geprueft} Prüfungen`);
|
||||
|
||||
Reference in New Issue
Block a user