1. SIEBEN VON ELF HATTEN KEIN GERAET ANGEMELDET.
Gemessen am echten Server, nicht geschaetzt (die Notiz von heute Nacht
sagte acht -- Tamy hat inzwischen eins). Bei ihnen kommt nichts an,
solange die Seite zu ist: keine Aufgabe, kein Termin, kein Anruf.
Die Glocke sagt das seit jeher korrekt und kennt sogar den
iPhone-Sonderfall ("erst zum Home-Bildschirm"). Nur tippt sie niemand
an -- sie ist ein stiller Schalter in einer Leiste.
Jetzt steht es dort, wo man hinsieht: als Hinweis in "Was ist dran?",
mit Weg auf anruf-probe.html. Als OFFENER PUNKT, nicht als Warnung --
eine Warnung, die bei sieben von elf Leuten dauerhaft oben steht, ist
nach einer Woche unsichtbar, und mit ihr die echten daneben. Er
verschwindet von selbst, sobald ein Geraet da ist (Gegenprobe in
pruef-glocke).
Und ohne die "1" davor: Er zaehlt nichts, er beschreibt einen Zustand.
FUENF DER SIEBEN DURFTEN DIE SEITE GAR NICHT OEFFNEN. anruf-probe.html
stand nur Leitung und Modis offen. Das war die falsche Einschraenkung:
Die Seite prueft die ganze Kette bis zur Geraete-Kennung, und die
traegt auch jede Aufgaben- und Terminerinnerung. Jetzt alle Team-Rollen,
ohne "gast" (die Community bekommt keine Erinnerungen).
2. 49 PRUEFUNGEN KONNTEN "BELEGT" NICHT VON "KAPUTT" UNTERSCHEIDEN.
Aufgefallen beim Nachsehen, warum ein Lauf rot war: Es war mein eigener,
haengengebliebener Lauf, der den Port hielt. Kein Befund.
Dabei gemessen: Von 130 Pruefungen hatten 49 keinen Portwaechter, und
SIEBEN Portnummern sind doppelt vergeben (4186, 4188, 4189, 4193, 4198,
4321, 4345). Bei belegtem Port startet der eigene Server STILL nicht --
und alles Weitere misst gegen einen fremden Stand. Das hat in diesem
Haus schon zweimal Stunden gekostet (27.08. und 05.09.).
Der Waechter existierte seit dem 05.09., er war nur nie ausgerollt.
Jetzt haben ihn alle 130. Gegenprobe gemacht: Port belegt ->
Rueckgabewert 3 mit Begruendung statt stillem Messen.
pruef-content bekommt BEIDE Ports -- sie startet zwei Server, und der
zweite gehoert zur Gegenprobe. Nur den ersten zu schuetzen hiesse,
ausgerechnet den Teil ungeschuetzt zu lassen, dem man glaubt.
Die sieben doppelten Nummern bleiben vorerst. Mit dem Waechter ist eine
Kollision jetzt laut statt still; Umnummerieren ist ein eigener Schritt.
3. pruef-rollen IST ABGESTUERZT, SEIT WANN WEISS NIEMAND.
"Target crashed" bei der fuenften Rolle, nach 234 gruenen Pruefungen.
Kein Fehlschlag -- ein toter Browser.
NACHGEMESSEN GEGEN DEN STAND VOR HEUTE (0b73fbb): dort genauso, an
derselben Stelle. Es lag also nicht an den Aenderungen dieses Tages.
Aufgefallen ist es nie, weil ein abgestuerzter Browser von aussen wie
ein Programmfehler aussieht und die 234 gruenen Zeilen davor sich wie
ein fast bestandener Lauf lesen.
Ursache ist die Menge: fuenf Rollen mal sechzehn Seiten in EINEM
Browserprozess. Die Kontexte wurden je Rolle geschlossen, der Prozess
darunter lief durch. Jetzt bekommt jede Rolle ihren eigenen Browser,
und ein Absturz meldet sich selbst statt als Zeitueberschreitung
irgendwo weiter unten aufzuschlagen.
Ergebnis: 321 Pruefungen, alles in Ordnung -- statt Absturz bei 234.
4. DAS SYMBOL FUER TIKTOK.
assets/img/app-symbole/workspace-1024.png, frisch gerendert statt
hochskaliert (das Huskygesicht lebt von harten Kanten) und als VOLLES
Quadrat ohne Rundung: Die Aufnahme hat keinen Alphakanal, die Ecken
waeren sonst weiss. App-Portale wollen ohnehin das volle Quadrat, die
Rundung macht das Betriebssystem.
Die sechs vorhandenen Groessen sind dabei bitgleich geblieben --
gepruefte Nebenwirkung, nicht gehofft.
GEMESSEN: pruef-glocke 31/0 (neu: 5 zum Hinweis), pruef-rollen 321/0
(vorher Absturz), pruef-rechtetafel 19/0, pruef-struktur 0 Fehler,
pruef-betreuung und pruef-werdegang gruen.
Co-Authored-By: Claude Opus 5 <[email protected]>
339 lines
17 KiB
JavaScript
339 lines
17 KiB
JavaScript
/* ===================================================================
|
|
Das App-Symbol des Workspace: Husky UND Chili in einem Zeichen.
|
|
|
|
Filipe (08.09.2026): "ich will dass du da eine geile mischung machst
|
|
von diesen zwei logo ... mach was ultra krass geiles draus bitte."
|
|
|
|
DIE AUFGABE IST NICHT "zwei Bilder nebeneinander". Ein App-Symbol
|
|
steht bei 32 px im Browserreiter und bei 192 px auf dem
|
|
Startbildschirm. Zwei vollstaendige Logos nebeneinander ergeben dort
|
|
zwei unlesbare Haelften. Gebraucht wird EINE Form, in der beide
|
|
vorkommen.
|
|
|
|
DIE LOESUNG: Der Husky ist das Zeichen, die Chili seine Farbe. Er
|
|
steht gross und mittig, sie liegt klein darunter -- ein Hauptmotiv
|
|
und ein Beiklang, nicht zwei gleich laute Stimmen.
|
|
|
|
ÜBERARBEITET AM 09.09.2026 (Filipe: "kannst du bitte das logo wenn
|
|
man es installiert auf pc oder handy ... noch perfektionnieren. ich
|
|
finde es könnte noch besser aussehen"). Was falsch war und warum:
|
|
|
|
1. DER HUSKY WAR EIN FLECK. Er lag als Maske auf einer Silberflaeche.
|
|
Von einer Maske zaehlt nur der Alphakanal, und die Vorlage ist
|
|
rundum freigestellt -- also war das Ergebnis eine geschlossene
|
|
Flaeche in Hundeform: kein Auge, keine Schnauze, kein Ohrinneres.
|
|
Jetzt liegt die Originalzeichnung im Mischmodus "screen" ueber
|
|
einer stahlblauen Silhouette. Das Fell bleibt dunkel, das Gesicht
|
|
kommt heraus. Aus dem Fleck wird wieder ein Hund.
|
|
2. DIE CHILI LIEF UEBER DEN FANG. Als Bogen unten herum gedreht kreuzte
|
|
ihr Stiel die Schnauze. Jetzt ist sie gespiegelt (Stiel nach rechts,
|
|
weg vom Kopf), deutlich kleiner und liegt hinter dem Hals.
|
|
3. DER HALS ENDETE IN EINER GERADEN KANTE. Die Vorlage ist unten
|
|
angeschnitten; als Symbol sah das nach Fehler aus. Eine zweite
|
|
Maske blendet ihn nach unten aus, statt ihn abzuschneiden.
|
|
4. DER GRUND WAR MATSCHIG. Rot und Blau trafen sich diagonal genau in
|
|
der Mitte -- dort, wo der Kopf steht. Jetzt liegt das kalte Licht
|
|
oben (beim Kopf), das warme unten (bei der Chili), und dazwischen
|
|
ist ruhiges Nachtblau.
|
|
|
|
MASKABLE: Android schneidet bis zu 20 % ringsum weg. Dafuer wird genau
|
|
EINE Zahl kleiner -- die Groesse der Gruppe, in der Kopf und Chili in
|
|
Prozent sitzen. Nicht sechs einzelne Werte, die auseinanderlaufen.
|
|
|
|
Aufrufen mit: node tools/workspace-symbol.mjs
|
|
=================================================================== */
|
|
|
|
import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs";
|
|
import { join, dirname } from "node:path";
|
|
import { fileURLToPath } from "node:url";
|
|
|
|
const WURZEL = join(dirname(fileURLToPath(import.meta.url)), "..");
|
|
const HUSKY = join(WURZEL, "workspace", "assets", "img", "marke-husky.webp");
|
|
const CHILI = join(WURZEL, "workspace", "assets", "img", "marke-spicy.webp");
|
|
/* Das Ziel ist umlenkbar (SYMBOL_ZIEL=/tmp/probe). Ein Symbol beurteilt
|
|
man nicht aus dem Quelltext, sondern indem man es ansieht -- und dafuer
|
|
darf man die sechs echten Dateien nicht bei jedem Versuch ueberschreiben.
|
|
Ohne die Variable bleibt alles wie bisher. */
|
|
const ZIEL = process.env.SYMBOL_ZIEL || join(WURZEL, "assets", "img", "app-symbole");
|
|
|
|
for (const q of [HUSKY, CHILI]) {
|
|
if (!existsSync(q)) { console.error(`Fehlt: ${q}`); process.exit(1); }
|
|
}
|
|
const alsDaten = (p) => "data:image/webp;base64," + readFileSync(p).toString("base64");
|
|
|
|
/* Die Groessen, die Manifest und HTML tatsaechlich anfordern.
|
|
|
|
1024 KOMMT AM 19.09.2026 DAZU, und zwar nicht fuer das Haus: TikTok
|
|
verlangt fuer die Anmeldung der Display-API ein Symbol in
|
|
1024 x 1024. Vorhanden war 512.
|
|
|
|
HIER EINGETRAGEN UND NICHT VON HAND HOCHSKALIERT: Ein hochgerechnetes
|
|
512er-Bild ist an den Kanten weich, und ausgerechnet das Gesicht des
|
|
Huskys lebt von harten Kanten. Diese Datei rendert die Groesse
|
|
frisch -- und die drei Gegenproben unten (Streuung, Gesicht, Chili)
|
|
gelten fuer sie damit genauso wie fuer alle anderen. */
|
|
const GROESSEN = [
|
|
{ n: 1024, endung: "1024", voll: true },
|
|
{ n: 512, endung: "512" },
|
|
{ n: 192, endung: "192" },
|
|
{ n: 512, endung: "512-maskable", maskable: true },
|
|
{ n: 192, endung: "192-maskable", maskable: true },
|
|
{ n: 180, endung: "180" },
|
|
{ n: 32, endung: "32" },
|
|
];
|
|
|
|
/* `weglassen` ist NUR fuer die Gegenprobe da: "zeichnung" oder "chili"
|
|
blendet genau einen Bestandteil aus. Verglichen wird danach das
|
|
erzeugte Bild mit und ohne -- sind beide gleich, war der Bestandteil
|
|
nie zu sehen. Eine Pruefung, die nur "es steht etwas drauf" sagt,
|
|
haette den Fleck von gestern anstandslos durchgewunken. */
|
|
function html(n, maskable, husky, chili, weglassen = "", voll = false) {
|
|
/* KLEIN = alles unter 64 px. Dort faellt die GESICHTSZEICHNUNG weg,
|
|
nicht die Chili. Achtfach vergroessert nebeneinandergelegt: Mit
|
|
Zeichnung ist der Kopf bei 32 px ein dunkler Fleck, als reine
|
|
Silhouette ist er eindeutig ein Hund. Die Chili dagegen ist gerade
|
|
klein am nuetzlichsten -- im Reiterband erkennt man ein Zeichen
|
|
zuerst an der Farbe, und Rot hat sonst nichts hier. */
|
|
const klein = n < 64;
|
|
const rand = Math.round(n * 0.22);
|
|
/* ALLES STECKT IN EINER GRUPPE. Kopf und Chili sitzen darin in
|
|
Prozent. Fuer die maskable-Fassung wird deshalb genau EINE Zahl
|
|
kleiner -- nicht sechs einzelne, die auseinanderlaufen koennen.
|
|
0,72 ist nachgemessen (mit eingezeichnetem Kreis angesehen): Damit
|
|
liegt alles Wesentliche im Sicherheitskreis mit 80 % Durchmesser,
|
|
den Android als einziges garantiert. */
|
|
const g = Math.round(n * (maskable ? 0.72 : 0.94));
|
|
/* `voll` heisst: KEINE abgerundeten Ecken (19.09.2026).
|
|
|
|
Fuer die 1024er-Fassung, die an ein Portal geht. Die Aufnahme hat
|
|
keinen Alphakanal -- was ausserhalb der Rundung liegt, wird also
|
|
nicht durchsichtig, sondern WEISS. Auf TikToks hellem Hintergrund
|
|
faellt das nicht auf, auf einem dunklen sieht es aus wie vier
|
|
abgeschnittene Ecken.
|
|
|
|
App-Portale wollen ohnehin das volle Quadrat: Die Rundung macht
|
|
das Betriebssystem selbst, und eine zweite darunter ergibt einen
|
|
hellen Saum. */
|
|
const ecke = (maskable || voll) ? "" : `border-radius:${rand}px;`;
|
|
|
|
/* ALLE REGELN TRAGEN DENSELBEN VORSATZ `.gruppe > i`.
|
|
|
|
Nicht aus Ordnungsliebe: Waehrend des Bauens stand hier `.chili`
|
|
ohne Vorsatz -- und `.gruppe > i` (Klasse + Typ) ist spezifischer
|
|
als `.chili` (nur Klasse). Die Drehung der Chili wurde dadurch
|
|
stillschweigend von der allgemeinen Regel ueberschrieben. Zwei
|
|
Regeln fuer dieselbe Eigenschaft, die spaetere verliert trotzdem:
|
|
genau der Fehler, der im Haus schon mehrfach Zeit gekostet hat.
|
|
Gleicher Vorsatz ueberall heisst: die Reihenfolge entscheidet, und
|
|
die ist sichtbar. */
|
|
return `<!doctype html><html><head><meta charset="utf-8"><style>
|
|
html,body{margin:0;width:${n}px;height:${n}px;overflow:hidden}
|
|
.feld{position:relative;width:${n}px;height:${n}px;${ecke}
|
|
/* DER GRUND. Ruhiges Nachtblau von oben nach unten, darueber zwei
|
|
Lichter: kaltes Dogi-Blau oben (da steht der Kopf), warmes
|
|
Spicy-Rot unten (da liegt die Chili). Der alte diagonale
|
|
Blau-nach-Rot-Verlauf traf sich in der Mitte -- genau dort, wo
|
|
der Kopf steht, und machte ihn matschig. */
|
|
background:
|
|
radial-gradient(76% 56% at 50% 26%, rgba(95,189,255,.20) 0%, transparent 68%),
|
|
radial-gradient(88% 54% at 50% 104%, rgba(176,40,32,.40) 0%, transparent 68%),
|
|
linear-gradient(180deg,#1a2f47 0%,#0d1a29 50%,#060c14 100%);
|
|
box-shadow:inset 0 ${Math.max(1, Math.round(n * .004))}px 0 rgba(255,255,255,.24),
|
|
inset 0 0 ${Math.round(n * .06)}px rgba(0,0,0,.38);
|
|
display:grid;place-items:center}
|
|
.gruppe{position:relative;width:${g}px;height:${g}px}
|
|
.gruppe > i{position:absolute;left:50%;transform:translate(-50%,-50%)}
|
|
|
|
/* DIE CHILI liegt HINTER dem Kopf (der hat z-index 2, sie keinen).
|
|
Sie ist gespiegelt: Der Stiel zeigt damit nach rechts, weg von der
|
|
Schnauze. In der Fassung davor lief er quer ueber den Fang -- das
|
|
war der Grund, warum das Zeichen unruhig wirkte. */
|
|
.gruppe > i.chili{width:${klein ? 40 : 46}%;height:${klein ? 40 : 46}%;top:${klein ? 80 : 84}%;
|
|
transform:translate(-50%,-50%) rotate(8deg) scaleX(-1);
|
|
background:url("${chili}") center/contain no-repeat;
|
|
/* KLEIN OHNE SCHLAGSCHATTEN. Bei 32 px ist der Schatten so breit
|
|
wie die Chili selbst -- nachgesehen: aus dem roten Zeichen wurde
|
|
ein dunkler Schmier. Klein wird sie stattdessen eine Spur heller
|
|
gestellt, weil davon nur noch die Farbe uebrig bleibt. */
|
|
filter:${klein
|
|
? "saturate(1.06) brightness(1.08)"
|
|
: `saturate(.92)
|
|
drop-shadow(0 ${Math.max(1, Math.round(n * .004))}px ${Math.round(n * .01)}px rgba(0,0,0,.7))
|
|
drop-shadow(0 0 ${Math.round(n * .02)}px rgba(255,86,64,.34))`}}
|
|
|
|
/* DER KOPF -- hier steckt die eigentliche Verbesserung.
|
|
|
|
Vorher war er eine MASKE. Von einer Maske zaehlt nur der
|
|
Alphakanal, und die Vorlage ist rundum freigestellt: Uebrig blieb
|
|
eine geschlossene Flaeche -- ein heller Fleck in Hundeform, ohne
|
|
Auge, ohne Schnauze, ohne Ohrinneres. Bei 22 px in der Kopfleiste
|
|
war genau das der Grund, warum man nichts erkannt hat.
|
|
|
|
Jetzt zwei Lagen: unten die Silhouette in Stahlblau, darueber die
|
|
ORIGINALZEICHNUNG im Mischmodus "screen". Screen laesst Schwarz
|
|
stehen (das Fell bleibt stahlblau) und hebt Weiss heraus (Gesicht,
|
|
Ohrinneres, Auge). Aus der Silhouette wird wieder ein Gesicht --
|
|
ohne eine einzige neu gezeichnete Linie.
|
|
|
|
Warum nicht "mask-mode: luminance"? Chromium kann das (geprueft:
|
|
CSS.supports meldet true). Aber der Weg ueber zwei Masken ist
|
|
empfindlich: Eine Kurzschreibweise "-webkit-mask" in einer
|
|
spezifischeren Regel setzt "mask-mode" stillschweigend auf "alpha"
|
|
zurueck, und man sieht wieder den Fleck -- genau das ist beim
|
|
Bauen passiert, mit richtig aussehendem Quelltext. Der Mischmodus
|
|
hat diese Falle nicht.
|
|
|
|
ZWEITE MASKE, DER AUSLAUF: Die Vorlage ist am unteren Rand
|
|
abgeschnitten, der Hals endet gerade. Als Symbol sah das aus wie
|
|
ein Fehler beim Freistellen. Der Verlauf blendet den Hals nach
|
|
unten aus, statt ihn abzuschneiden. */
|
|
.gruppe > i.kopf{width:${klein ? 76 : 88}%;height:${klein ? 76 : 88}%;
|
|
top:${klein ? 44 : 43}%;
|
|
z-index:2;isolation:isolate;
|
|
background:linear-gradient(162deg,#5486b2 0%,#25507a 44%,#0e2b45 100%);
|
|
${klein
|
|
/* KLEIN OHNE AUSLAUF. Bei 32 px frisst der Verlauf gerade die
|
|
Schnauze weg -- nachgesehen und 8-fach vergroessert
|
|
verglichen: mit Auslauf ist es ein Berg, ohne Auslauf ein
|
|
Hundekopf. Die gerade Kante am Hals ist dort drei Bildpunkte
|
|
hoch und faellt nicht auf. */
|
|
? `-webkit-mask:url("${husky}") center/contain no-repeat;
|
|
mask:url("${husky}") center/contain no-repeat;`
|
|
: `-webkit-mask:url("${husky}") center/contain no-repeat,
|
|
linear-gradient(180deg,#000 58%, transparent 86%);
|
|
-webkit-mask-composite:source-in;
|
|
mask:url("${husky}") center/contain no-repeat,
|
|
linear-gradient(180deg,#000 58%, transparent 86%);
|
|
mask-composite:intersect;`}
|
|
filter:drop-shadow(0 ${Math.round(n * .006)}px ${Math.round(n * .016)}px rgba(0,0,0,.7))
|
|
drop-shadow(0 0 ${Math.round(n * .022)}px rgba(140,200,245,.34))}
|
|
.gruppe > i.kopf .zeichnung{position:absolute;inset:0;display:block;
|
|
background:url("${husky}") center/contain no-repeat;
|
|
mix-blend-mode:screen;
|
|
/* Ohne den Daempfer wird das Weiss der Vorlage zu reinem Weiss --
|
|
auf dunklem Grund blendet das. Augenschonend heisst hier: hell
|
|
genug zum Erkennen, nicht heller. */
|
|
filter:brightness(.88)}
|
|
.gruppe > i.kopf.flach{background:linear-gradient(168deg,#ffffff 4%,#e4eef8 38%,#adc0d4 100%)}
|
|
.gruppe > i.kopf.flach .zeichnung{display:none}
|
|
${weglassen === "zeichnung" ? ".gruppe > i.kopf .zeichnung{display:none}" : ""}
|
|
${weglassen === "chili" ? ".gruppe > i.chili{display:none}" : ""}
|
|
</style></head><body><div class="feld"><div class="gruppe">
|
|
<i class="kopf${klein ? " flach" : ""}"><b class="zeichnung"></b></i>
|
|
<i class="chili"></i>
|
|
</div></div></body></html>`;
|
|
}
|
|
|
|
const { chromium } = await import(
|
|
"file:///C:/Users/qciga/Documents/Obelix/Analyse/node_modules/playwright/index.mjs");
|
|
const browser = await chromium.launch();
|
|
const seite = await (await browser.newContext({ deviceScaleFactor: 1 })).newPage();
|
|
if (!existsSync(ZIEL)) mkdirSync(ZIEL, { recursive: true });
|
|
|
|
const husky = alsDaten(HUSKY), chili = alsDaten(CHILI);
|
|
let gebaut = 0;
|
|
const maengel = [];
|
|
|
|
/* Eine Fassung aufnehmen. `weglassen` steuert die Gegenprobe. */
|
|
async function aufnehmen(n, maskable, weglassen = "", voll = false) {
|
|
await seite.setViewportSize({ width: n, height: n });
|
|
await seite.setContent(html(n, maskable, husky, chili, weglassen, voll),
|
|
{ waitUntil: "networkidle" });
|
|
return await seite.screenshot({ omitBackground: false });
|
|
}
|
|
|
|
/* Streuung der Helligkeit: Ein leeres Feld hat keine. Das beweist, dass
|
|
ueberhaupt etwas draufsteht -- mehr nicht. Die Bytezahl beweist auch
|
|
das nicht, ein einfarbiges PNG ist genauso gross wie ein volles. */
|
|
async function streuungVon(bild) {
|
|
return await seite.evaluate(async (b64) => {
|
|
const b = new Image(); b.src = "data:image/png;base64," + b64; await b.decode();
|
|
const c = document.createElement("canvas");
|
|
c.width = b.width; c.height = b.height;
|
|
const g2 = c.getContext("2d"); g2.drawImage(b, 0, 0);
|
|
const d = g2.getImageData(0, 0, c.width, c.height).data;
|
|
let s = 0, s2 = 0, m = 0;
|
|
for (let i = 0; i < d.length; i += 4) {
|
|
const h = 0.2126 * d[i] + 0.7152 * d[i + 1] + 0.0722 * d[i + 2];
|
|
s += h; s2 += h * h; m++;
|
|
}
|
|
return Math.sqrt(s2 / m - (s / m) ** 2);
|
|
}, bild.toString("base64"));
|
|
}
|
|
|
|
/* Anteil der Bildpunkte, die sich zwischen zwei Aufnahmen sichtbar
|
|
unterscheiden. Acht Stufen Abstand, damit Kantenglaettung allein den
|
|
Wert nicht hochtreibt. */
|
|
async function unterschied(a, b) {
|
|
return await seite.evaluate(async ([x, y]) => {
|
|
const laden = async (b64) => {
|
|
const b = new Image(); b.src = "data:image/png;base64," + b64; await b.decode();
|
|
const c = document.createElement("canvas");
|
|
c.width = b.width; c.height = b.height;
|
|
c.getContext("2d").drawImage(b, 0, 0);
|
|
return c.getContext("2d").getImageData(0, 0, c.width, c.height).data;
|
|
};
|
|
const [p, q] = [await laden(x), await laden(y)];
|
|
let anders = 0, m = 0;
|
|
for (let i = 0; i < p.length; i += 4) {
|
|
const w = Math.max(Math.abs(p[i] - q[i]), Math.abs(p[i + 1] - q[i + 1]),
|
|
Math.abs(p[i + 2] - q[i + 2]), Math.abs(p[i + 3] - q[i + 3]));
|
|
if (w > 8) anders++;
|
|
m++;
|
|
}
|
|
return anders / m;
|
|
}, [a.toString("base64"), b.toString("base64")]);
|
|
}
|
|
|
|
for (const g of GROESSEN) {
|
|
const bild = await aufnehmen(g.n, !!g.maskable, "", !!g.voll);
|
|
writeFileSync(join(ZIEL, `workspace-${g.endung}.png`), bild);
|
|
gebaut++;
|
|
|
|
const streuung = await streuungVon(bild);
|
|
if (streuung < 12) maengel.push(`${g.endung}: kaum Zeichnung (Streuung ${streuung.toFixed(1)})`);
|
|
|
|
/* DIE ZWEI GEGENPROBEN. Beide messen nicht "sieht gut aus", sondern
|
|
"ist ueberhaupt da": Wenn das Bild ohne die Zeichnung genauso
|
|
aussieht wie mit ihr, dann war die Zeichnung nie zu sehen -- und
|
|
genau das war der Fehler der alten Fassung, die trotzdem gruen war. */
|
|
const klein = g.n < 64;
|
|
const ohneZeichnung = await unterschied(bild,
|
|
await aufnehmen(g.n, !!g.maskable, "zeichnung", !!g.voll));
|
|
const ohneChili = await unterschied(bild,
|
|
await aufnehmen(g.n, !!g.maskable, "chili", !!g.voll));
|
|
|
|
if (klein) {
|
|
/* Unter 64 px ist die schlichte Silhouette Absicht. Geprueft wird,
|
|
dass sie es auch bleibt -- sonst waere die Regel bloss ein
|
|
Kommentar, der beim naechsten Umbau stillschweigend kippt. */
|
|
if (ohneZeichnung > 0.001) maengel.push(
|
|
`${g.endung}: klein soll ohne Gesichtszeichnung sein`);
|
|
} else {
|
|
/* Das Gesicht bedeckt gemessen rund ein Siebtel der Flaeche; 4 %
|
|
ist der Boden, unter den es nur durch einen Fehler faellt. */
|
|
if (ohneZeichnung < 0.04) maengel.push(
|
|
`${g.endung}: das Gesicht kommt nicht durch (${(ohneZeichnung * 100).toFixed(1)} %)`);
|
|
}
|
|
/* Die Chili gehoert in JEDE Fassung, gerade in die kleine. Sie nimmt
|
|
gemessen 4 bis 7 % ein; 1 % ist der Boden. */
|
|
if (ohneChili < 0.01) maengel.push(
|
|
`${g.endung}: die Chili fehlt (${(ohneChili * 100).toFixed(1)} %)`);
|
|
|
|
console.log(` workspace-${g.endung}.png`.padEnd(32)
|
|
+ `${(bild.length / 1024).toFixed(1)} KB · Streuung ${streuung.toFixed(1)}`
|
|
+ ` · Gesicht ${(ohneZeichnung * 100).toFixed(1)} %`
|
|
+ ` · Chili ${(ohneChili * 100).toFixed(1)} %`);
|
|
}
|
|
await browser.close();
|
|
|
|
/* Die Zahlen gehoeren in die Bedingung, nicht nur in den Bericht. */
|
|
if (gebaut !== GROESSEN.length) {
|
|
console.error(`\nFEHLER: ${gebaut} von ${GROESSEN.length} erzeugt.`); process.exit(1);
|
|
}
|
|
if (maengel.length) {
|
|
console.error("\nFEHLER:\n " + maengel.join("\n ")); process.exit(1);
|
|
}
|
|
console.log(`\n${gebaut} Symbole erzeugt. Husky-Gesicht und Chili sind in jeder`
|
|
+ ` grossen Fassung nachweisbar sichtbar, die kleine bleibt bewusst schlicht.`);
|