Files
DogFatherGitandClaude Opus 5 d0ac8ee8d1 Das Logo: aus dem Fleck wird wieder ein Hund
Filipe: "kannst du bitte das logo wenn man es installiert auf pc oder
handy und oben rechts in der leiste noch perfektionnieren."

Beide Stellen hatten denselben Fehler, und er war derselbe wie an
mehreren Stellen davor: Der Husky lag als MASKE auf einer Farbflaeche.
Von einer Maske zaehlt nur der Alphakanal, und die Vorlage ist rundum
freigestellt -- uebrig blieb eine geschlossene Flaeche in Hundeform.
Kein Auge, keine Schnauze, kein Ohrinneres. Ein Fleck.

Jetzt liegt an beiden Stellen dieselbe Zeichnung im Mischmodus "screen"
ueber einer stahlblauen Silhouette: Schwarz laesst das Fell dunkel,
Weiss hebt Gesicht, Ohren und Auge heraus. Gleiche Farben, gleicher
Daempfer (.88) -- ein Zeichen, zwei Orte.

App-Symbol ausserdem:
- Die Chili lief mit ihrem Stiel quer ueber den Fang. Sie ist jetzt
  gespiegelt, kleiner und liegt hinter dem Hals.
- Der Hals endete in einer geraden Kante (die Vorlage ist unten
  angeschnitten). Eine zweite Maske blendet ihn aus, statt ihn
  abzuschneiden.
- Der Grund war matschig: Rot und Blau trafen sich diagonal genau dort,
  wo der Kopf steht. Jetzt kaltes Licht oben, warmes unten.
- Unter 64 px faellt die Gesichtszeichnung weg, die Chili aber NICHT --
  klein erkennt man ein Zeichen zuerst an der Farbe.
- Alle Masse haengen an einer Zahl (Groesse der Gruppe), nicht an sechs.

Kopfleiste ausserdem:
- Die Chili links hatte einen BLAUEN Schein -- aus der Zeit, als dort
  der Husky stand. Der Schein ist nie mitgewandert. Jetzt warm.
- `filter` ersetzt, es ergaenzt nicht: Beim Ueberfahren wurde der Schein
  geloescht und das Zeichen dabei flacher statt heller. Behoben.

Damit die Aenderung auch ankommt:
- Der Stempel gilt jetzt auch fuer die App-Symbole und fuer das
  Manifest. Bilder werden einen Tag zwischengespeichert, das Symbol der
  INSTALLIERTEN App gar nicht neu geholt -- ohne Stempel haette niemand
  das neue Zeichen gesehen.
- pruef-zwischenspeicher prueft das (18 -> 21 Pruefungen).

Werkzeuge:
- tools/ausschnitt.mjs (neu): schneidet aus einem Bildschirmfoto ein
  Stueck heraus und vergroessert die PNG-Datei. Noetig, weil eine
  Vergroesserung per CSS-transform den Browser NEU rechnen laesst --
  ich habe damit 264 px beurteilt und geglaubt, es seien 22, und daraus
  den falschen Schluss gezogen, ein Gesicht trage bei 22 px nicht.
- tools/ansicht.mjs: AUSSCHNITT=<selektor> nimmt nur ein Element auf.
- workspace-symbol.mjs: SYMBOL_ZIEL lenkt die Ausgabe um (Entwuerfe
  ansehen, ohne die sechs echten Dateien zu ueberschreiben), und zwei
  Gegenproben pruefen jetzt, dass Gesicht und Chili wirklich zu sehen
  sind -- die alte Pruefung sagte nur "es steht etwas drauf" und haette
  den Fleck anstandslos durchgewunken.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-09 18:24:20 +02:00

93 lines
3.9 KiB
JavaScript

/* ANSEHEN — startet die Anwendung mit frischer Datenbank, meldet sich an
und legt Bildschirmfotos ab. Kein Prueflauf, nur ein Blick.
Aufruf: node tools/ansicht.mjs [seite ...] */
import { mkdtempSync, rmSync } from "node:fs";
import { tmpdir } from "node:os";
import { join, dirname } from "node:path";
import { fileURLToPath } from "node:url";
import { spawn } from "node:child_process";
import { DatabaseSync } from "node:sqlite";
import { scryptSync, randomBytes } from "node:crypto";
const HIER = join(dirname(fileURLToPath(import.meta.url)), "..", "server");
const PORT = 4362;
const BASIS = `http://127.0.0.1:${PORT}`;
const ordner = mkdtempSync(join(tmpdir(), "ws-ans-"));
const DB = join(ordner, "workspace.db");
const SEITEN = process.argv.slice(2).length ? process.argv.slice(2) : ["start"];
let kind = null;
async function start() {
kind = spawn(process.execPath, [join(HIER, "index.js")], {
env: { ...process.env, WORKSPACE_DB: DB, PORT: String(PORT),
SITE_ACCESS_SECRET: "lokaler-test",
SITE_PUBLIC_LAUNCH_AT: "2020-01-01T00:00:00+01:00" },
stdio: ["ignore", "pipe", "pipe"] });
let aus = "";
kind.stdout.on("data", (d) => { aus += d; });
kind.stderr.on("data", (d) => { aus += d; });
for (let i = 0; i < 80; i++) {
await new Promise((r) => setTimeout(r, 250));
if (kind.exitCode !== null) break;
try { const a = await fetch(BASIS + "/workspace/", { redirect: "manual" });
if (a.status < 500) return; } catch { /* noch nicht oben */ }
}
throw new Error("Server startete nicht:\n" + aus.slice(-1500));
}
await start();
kind.kill();
await new Promise((r) => setTimeout(r, 600));
{
const d = new DatabaseSync(DB);
const salz = randomBytes(16).toString("hex");
const hash = scryptSync("CODE-DOGI-0001", salz, 64,
{ N: 32768, r: 8, p: 1, maxmem: 96 * 1024 * 1024 }).toString("hex");
d.prepare("INSERT INTO personen (name, rolle, code_hash, code_salt, code_n, aktiv, erstellt) VALUES (?,?,?,?,?,1,?)")
.run("Filipe", "admin", hash, salz, 32768, new Date().toISOString());
d.close();
}
await start();
const pw = await import("file:///C:/Users/qciga/Documents/Obelix/Analyse/node_modules/playwright/index.mjs");
const browser = await pw.chromium.launch();
/* Breite ueber die Umgebung: node tools/ansicht.mjs start -> Rechner
BREITE=412 node tools/ansicht.mjs start -> Handy */
const BREITE = Number(process.env.BREITE || 1600);
const HOEHE = Number(process.env.HOEHE || (BREITE < 700 ? 915 : 1000));
const ctx = await browser.newContext({
viewport: { width: BREITE, height: HOEHE }, deviceScaleFactor: 1,
isMobile: BREITE < 700, hasTouch: BREITE < 700 });
const seite = await ctx.newPage();
await seite.goto(BASIS + "/workspace/", { waitUntil: "networkidle" });
await seite.click('.rolle[data-rolle="admin"]');
await seite.fill("#code", "CODE-DOGI-0001");
await seite.click("button[type=submit]");
await seite.waitForURL("**/start.html", { timeout: 25000 });
/* AUSSCHNITT=.kopfleiste node tools/ansicht.mjs start aufgaben
nimmt nur dieses eine Element auf. Ein 1600 px breites Bild wird beim
Ansehen heruntergerechnet -- ein 22-px-Zeichen darin ist danach ein
Fleck aus vier Punkten, und man beurteilt die Verkleinerung statt der
Sache. */
const AUSSCHNITT = process.env.AUSSCHNITT || "";
for (const s of SEITEN) {
await seite.goto(`${BASIS}/workspace/${s}.html`, { waitUntil: "networkidle" });
await seite.waitForTimeout(1600);
const pfad = `/tmp/a-${s}${BREITE < 700 ? "-handy" : ""}.png`;
if (AUSSCHNITT) {
const teil = seite.locator(AUSSCHNITT).first();
if (await teil.count() === 0) throw new Error(`Auf ${s}.html gibt es kein ${AUSSCHNITT}`);
await teil.screenshot({ path: pfad });
} else {
await seite.screenshot({ path: pfad, fullPage: false });
}
console.log(pfad);
}
await browser.close();
kind.kill();
await new Promise((r) => setTimeout(r, 400));
try { rmSync(ordner, { recursive: true, force: true }); } catch { /* Zugabe */ }