--- screen1: Glocke nach rechts, Ring so gross wie die Uhr ---
"dieser button links vom kreis soll rechts davon sein und der kreis
soll die gleiche groesse wie die uhr haben."
Die KAESTEN waren schon exakt gleich gross (248 x 248, seit gestern aus
einer Variablen). Der gezeichnete Ring aber nicht: Sein aeusserer Bogen
lag bei Radius 128 von 150, plus halbe Strichbreite also bei 132,5 --
88 Prozent des Kastens, gerendert 219 statt 248 px. Die Uhr daneben
fuellt ihren Kasten ganz aus, ihr Leuchtkranz ragt sogar 7 px darueber
hinaus. Zwei gleich grosse Kaesten mit ungleich grossem Inhalt sehen
ungleich gross aus.
Jetzt 145 statt 128 (aussen) und 120 statt 106 (die Segmente) --
dasselbe Verhaeltnis zueinander, nur bis an den Rand. 145 + 4,5 =
149,5 von 150: ein halber Pixel Luft, damit die runde Kappe nicht
abgeschnitten wird.
Die Glocke steht jetzt rechts vom Ring. Damit liegen beide Knoepfe
INNEN, zwischen den Instrumenten und dem Text -- vorher sassen sie an
den beiden Aussenkanten, so weit voneinander entfernt wie moeglich,
obwohl sie dasselbe tun: einstellen, was einen erreicht.
--- screen2: die Stunden ---
"die stunden muss noch perfektionnieren."
DIE LICHTKANTE WAR EIN KRATZER. Sie stand auf 50 Prozent Weiss bei 0,9
Breite. Auf den schmalen Sekunden- und Minutenbahnen ist das eine
Kante; auf dem 5,8 px breiten Stundenbalken war es ein zweiter,
weisser Balken auf dem roten. Der Grund ist Verhaeltnis UND Farbe:
0,9 von 3,2 sind 28 Prozent, 0,9 von 5,8 nur 16 -- aber die Stunde ist
die einzige deckende, kraeftig gefaerbte Bahn, und auf Rot faellt
dasselbe Weiss doppelt so stark auf wie auf Silber. Jetzt 22 Prozent
bei 0,6 Breite.
DER KOPF BLEIBT ROT. Er stand auf #ffd9dd, also fast weiss -- das
aktuelle Glied war zwar das hellste, hatte aber die Farbe seiner Bahn
verloren und sah aus wie ein Fremdkoerper zwischen den roten Balken.
Jetzt ein helles, deutliches Rot: Es hebt sich durch Helligkeit ab,
nicht durch eine andere Farbe.
--- screen3: die Report-Karten stehen gerade ---
"ich will dass alles passt, nicht bedeckt ist, schief steht oder zu
tief oder zu hoch."
NACHGEMESSEN, ALLE 17 KARTEN -- der Befund deckt sich genau mit dem,
was er beschreibt: Name und Zahl lagen 12 bis 28 px auf VERSCHIEDENEN
Hoehen, sie ueberlappten sich waagerecht (gemessener Abstand -183 bis
-524 px), und Karten in derselben Reihe waren verschieden hoch.
DIE URSACHE IST EINE ZEILE: `.kachel__zahl` steht `position: absolute`
bei top 13 / right 13. Auf der Startseite ist das richtig -- gleich
grosse Kacheln, einzeiliger Name. Hier bricht der Name um ("Community:
neue Eintraege"), die Karte waechst nach unten, die Zahl bleibt oben
kleben. Sie war ausserdem fuer die Hoehenrechnung unsichtbar, weshalb
es vorher schon eine `min-height` als Pflaster brauchte.
Jetzt ein echtes Raster: Name links (Zeile 1), Trend darunter, Zahl
rechts ueber beide Zeilen und mittig. `display: contents` auf dem
Wrapper -- so werden seine Kinder selbst zu Rasterfeldern, ohne dass am
HTML etwas geaendert werden muss und ohne dass die Startseite, die
dieselben Klassen benutzt, etwas davon mitbekommt.
Nachgemessen danach: 17 von 17 sauber -- nichts ragt heraus, nichts
ueberlappt, nichts abgeschnitten, kein Versatz ueber 5 px, und keine
Reihe mit ungleichen Hoehen.
--- screen4: Schutz & Regeln wird Magenta ---
"ich will dass die kategorie eine farbe bekommt die extrem krass
auffaellt. diese kategorie ist naemlich seeeehr wichtig."
MAGENTA, WEIL ES DAS EINZIGE IST, DAS ES SONST NICHT GIBT. Rot ist fuer
"ueberfaellig" und Spicy Media vergeben, Babyblau fuer DogFather, Lila
fuer Manager, Gruen fuer Scout, Bronze fuer Creator, Bernstein fuer
"dringend". #ff2fd0 stoesst mit keinem davon zusammen -- es faellt
nicht auf, weil es HELLER ist, sondern weil es einzigartig ist. Das
ist verlaesslicher: Helligkeit konkurriert mit den Nachbarn,
Einzigartigkeit nicht.
Gerechnet wie bei Ton 21: Abstand zum naechsten Nachbarn 0,1305 (die
Grenze im Satz liegt bei 0,0973), Buntheit 0,276 -- die hoechste im
ganzen Satz, das alte Gold lag bei 0,170 --, Kontrast 6,00:1. Von
sieben Kandidaten sind drei an der Abstandsgrenze gescheitert. Das
Saeuregelb #e0ff00 waere lauter gewesen (16,86:1), haette sich aber
mit dem Bernstein von "dringend" und dem Gold der Nachbarkacheln um
dieselbe Wirkung gestritten. Die Kachel bleibt gebaut wie alle
anderen; was sie heraushebt, ist die Farbe, keine Sonderform.
--- Eine Rueckwirkung, die pruef-buehne gefunden hat ---
Die Typenschilder von gestern nutzen `background-clip: text` -- dafuer
MUSS `color: transparent` sein. pruef-buehne las genau dieses `color`,
machte daraus Schwarz und meldete 1,07:1 fuer Text, der hell und gut
lesbar ist. Fuenf Fehlalarme auf drei Seiten.
Eine Warnung, die bei richtiger Arbeit anschlaegt, wird abgeschaltet.
Sie ist deshalb nicht weichgemacht, sondern GENAUER geworden: Bei
Verlaufsschrift zaehlt jetzt der DUNKELSTE Farbstopp der ersten
Hintergrundebene -- der schlechteste Punkt, den es auf dieser Schrift
wirklich gibt. Damit meldet start.html 4,74:1 (noetig 4,5), die
Pruefung findet also weiter die engste Stelle.
UND DIE GEGENPROBE HAT SOFORT EINEN FEHLER IN MEINEM EIGENEN CODE
GEFUNDEN: Ich suchte das Ende der ersten Ebene mit `"),"` -- diese
Zeichenfolge steht aber schon am Ende des ERSTEN `rgb(...)`. Die
Messung las damit immer nur den ersten Stopp und haette einen dunklen
Verlauf fuer hell gehalten. Jetzt wird ueber Klammern gezaehlt. Der
Helfer steht einmal und wird als Quelltext in beide Seiten-Aufrufe
gereicht -- zwei Kopien waeren zwei Gelegenheiten auseinanderzulaufen.
Geprueft: pruef-buehne (mit neuer Gegenprobe), pruef-start-ansicht,
pruef-css-klassen, pruef-handy, pruef-workspace-seiten -- alle in
Ordnung.
Co-Authored-By: Claude Opus 5 <[email protected]>
277 lines
12 KiB
JavaScript
277 lines
12 KiB
JavaScript
/* ===================================================================
|
|
Die 21 Kachelfarben -- gerechnet, nicht gewaehlt.
|
|
|
|
ANLASS (08.09.2026). Filipe: "viele kacheln haben noch fast die
|
|
gleiche farben, ähneln sich sehr und ich will dass du komplett
|
|
eskalierst ... alle seine eigenen farben und so dass sie sich nicht
|
|
ähneln. sehr wichtig nicht ähneln!!!!"
|
|
|
|
Er hat recht, und es liess sich messen. Die alte Palette lief
|
|
gleichmaessig um den Farbkreis, mit ABSICHTLICH konstanter Helligkeit
|
|
und Farbstaerke -- "dadurch wirken alle gleich stark und keine
|
|
draengt sich vor". Der Gedanke war gut und hat genau den Fehler
|
|
erzeugt, den Filipe sieht:
|
|
|
|
Kleinster Abstand zweier Toene: 0,033 (Dateien gegen Creator)
|
|
Paare unter 0,05 (kaum trennbar): 21 von 210
|
|
Spanne der Helligkeit: 0,002
|
|
|
|
Bei 21 Farben auf EINEM Ring mit gleicher Helligkeit bleibt als
|
|
einziger Unterschied der Farbton. Nachbarn liegen dann zwangslaeufig
|
|
dicht beieinander -- 360 Grad geteilt durch 21 sind 17 Grad, und
|
|
17 Grad Farbton sieht man schlicht nicht.
|
|
|
|
WAS SICH AENDERT: Helligkeit und Farbstaerke variieren jetzt mit.
|
|
Zwei Farben mit aehnlichem Farbton stehen dadurch trotzdem weit
|
|
auseinander, weil die eine hell und satt und die andere dunkel und
|
|
ruhig ist. Der Abstand bekommt eine zweite und dritte Dimension.
|
|
|
|
GERECHNET WIRD IN OKLAB. Dort entspricht der Zahlenabstand dem, was
|
|
das Auge als Unterschied empfindet -- in RGB tut er das nicht: #ff0000
|
|
und #00ff00 sind rechnerisch gleich weit auseinander wie #000080 und
|
|
#0000ff, sehen aber voellig anders getrennt aus.
|
|
|
|
DREI BEDINGUNGEN, die jede Farbe halten muss:
|
|
|
|
1. LESBAR. Mindestens 4,5:1 gegen den dunklen Grund (#0a121e).
|
|
Eine Kachelfarbe traegt auch Text und Zahlen.
|
|
2. AUGENSCHONEND (Hausregel). Farbstaerke gedeckelt -- satt ja,
|
|
Neon nein. Deshalb liegt die Obergrenze der Buntheit bei 0,17
|
|
und nicht am Rand des Darstellbaren.
|
|
3. TRENNBAR. Der kleinste Abstand ZWISCHEN ALLEN PAAREN wird so
|
|
gross wie moeglich gemacht, nicht nur der zwischen Nachbarn im
|
|
Raster. Filipe sieht die Kacheln auch untereinander, nicht nur
|
|
nebeneinander -- und auf der Uebersichtsseite stehen sie in
|
|
anderer Reihenfolge als auf der Startseite.
|
|
|
|
Aufrufen mit: node tools/kachel-farben.mjs
|
|
Die Ausgabe wird nach start.css uebertragen (Abschnitt "Kacheln").
|
|
|
|
ACHTUNG -- ZWEI TOENE SIND VON HAND GESETZT (Stand 09.09.2026).
|
|
|
|
TON 5 (Schutz & Regeln) steht auf #ff2fd0. Filipe: "ich will dass
|
|
die kategorie eine farbe bekommt die extrem krass auffaellt. diese
|
|
kategorie ist naemlich seeeehr wichtig." Magenta ist der einzige
|
|
Ton, den es im Haus sonst nirgends gibt -- er faellt durch
|
|
Einzigartigkeit auf, nicht durch Helligkeit. Abstand zum naechsten
|
|
Nachbarn 0,1305 (Grenze 0,0973), Buntheit 0,276 (hoechste im Satz),
|
|
Kontrast 6,00:1.
|
|
|
|
ACHTUNG -- TON 21 IST SEIT DEM 09.09.2026 VON HAND GESETZT.
|
|
Filipe wollte die Scout-Pipeline ausdruecklich in Knallrot
|
|
("die farbe von dieser kategorie soll knall rot sein"). In start.css
|
|
steht dort #ff1f2e; dieses Werkzeug wuerde beim naechsten Lauf
|
|
wieder Rosa vorschlagen.
|
|
|
|
NICHT EINFACH UEBERNEHMEN, sondern die Ausgabe fuer Ton 21
|
|
verwerfen. Der Wunsch ist geprueft und nicht willkuerlich: #ff1f2e
|
|
liegt in OKLab 0,1228 von seinem naechsten Nachbarn entfernt --
|
|
weiter als das engste vorhandene Paar im Satz (0,0973) -- und hat
|
|
5,01:1 Kontrast. Wer den Satz neu rechnet, muss diese Farbe als
|
|
FESTEN Punkt vorgeben und die uebrigen zwanzig darum herum
|
|
verteilen; sonst ist der naechste Lauf eine stille Ruecknahme einer
|
|
ausdruecklichen Entscheidung.
|
|
=================================================================== */
|
|
|
|
/* ---------- Farbenlehre ------------------------------------------- */
|
|
|
|
const zuLinear = (c) => (c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4));
|
|
const zuSrgb = (c) => (c <= 0.0031308 ? 12.92 * c : 1.055 * Math.pow(c, 1 / 2.4) - 0.055);
|
|
|
|
function oklabAusRgb(r, g, b) {
|
|
const l = Math.cbrt(0.4122214708 * r + 0.5363325363 * g + 0.0514459929 * b);
|
|
const m = Math.cbrt(0.2119034982 * r + 0.6806995451 * g + 0.1073969566 * b);
|
|
const s = Math.cbrt(0.0883024619 * r + 0.2817188376 * g + 0.6299787005 * b);
|
|
return [
|
|
0.2104542553 * l + 0.7936177850 * m - 0.0040720468 * s,
|
|
1.9779984951 * l - 2.4285922050 * m + 0.4505937099 * s,
|
|
0.0259040371 * l + 0.7827717662 * m - 0.8086757660 * s,
|
|
];
|
|
}
|
|
|
|
/** OKLCH -> sRGB. Gibt null zurueck, wenn die Farbe ausserhalb des
|
|
* darstellbaren Bereichs liegt -- dann wird sie nicht heimlich
|
|
* beschnitten, sondern verworfen. Ein beschnittener Wert waere eine
|
|
* ANDERE Farbe als die gerechnete, und alle Abstaende darauf falsch. */
|
|
function ausOklch(L, C, Hgrad) {
|
|
const h = (Hgrad * Math.PI) / 180;
|
|
const a = C * Math.cos(h), bb = C * Math.sin(h);
|
|
const l_ = L + 0.3963377774 * a + 0.2158037573 * bb;
|
|
const m_ = L - 0.1055613458 * a - 0.0638541728 * bb;
|
|
const s_ = L - 0.0894841775 * a - 1.2914855480 * bb;
|
|
const l = l_ ** 3, m = m_ ** 3, s = s_ ** 3;
|
|
const r = +4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s;
|
|
const g = -1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s;
|
|
const b = -0.0041960863 * l - 0.7034186147 * m + 1.7076147010 * s;
|
|
const kanaele = [r, g, b].map(zuSrgb);
|
|
if (kanaele.some((c) => c < -0.002 || c > 1.002)) return null;
|
|
const bytes = kanaele.map((c) => Math.round(Math.min(1, Math.max(0, c)) * 255));
|
|
return {
|
|
hex: "#" + bytes.map((n) => n.toString(16).padStart(2, "0")).join(""),
|
|
oklab: oklabAusRgb(...bytes.map((n) => zuLinear(n / 255))),
|
|
leucht: 0.2126 * zuLinear(bytes[0] / 255) + 0.7152 * zuLinear(bytes[1] / 255)
|
|
+ 0.0722 * zuLinear(bytes[2] / 255),
|
|
};
|
|
}
|
|
|
|
const abstand = (x, y) => Math.hypot(
|
|
x.oklab[0] - y.oklab[0], x.oklab[1] - y.oklab[1], x.oklab[2] - y.oklab[2]);
|
|
|
|
/* Der Grund, auf dem die Kacheln liegen. */
|
|
const GRUND_LEUCHT = 0.2126 * zuLinear(0x0a / 255)
|
|
+ 0.7152 * zuLinear(0x12 / 255)
|
|
+ 0.0722 * zuLinear(0x1e / 255);
|
|
const kontrast = (f) => (f.leucht + 0.05) / (GRUND_LEUCHT + 0.05);
|
|
|
|
/* ---------- Die Kacheln, in fester Reihenfolge --------------------- */
|
|
|
|
const KACHELN = [
|
|
"Dashboard", "Zahlen", "LIVE", "Chat", "Schutz", "Community", "Reports",
|
|
"Kalender", "Bibliothek", "Steckbrief", "Personen", "Content", "Aufgaben",
|
|
"Technik", "Calls", "Start-Check", "Agentur", "Automationen", "Dateien",
|
|
"Creator-Profile", "Scout",
|
|
];
|
|
|
|
/* Wo eine Kachel inhaltlich hingehoert. Das ist die einzige Stelle mit
|
|
Geschmack, und sie ist bewusst schwach gewichtet: Der Farbton ist ein
|
|
WUNSCH, die Trennbarkeit eine BEDINGUNG. Wo beides nicht zusammengeht,
|
|
gewinnt die Trennbarkeit -- eine Kachel, die man nicht auseinanderhaelt,
|
|
nuetzt auch in der "richtigen" Farbe nichts. */
|
|
const WUNSCHTON = {
|
|
"LIVE": 25, // rot -- "on air"
|
|
"Technik": 95, // gelb wie ein Warnschild
|
|
"Reports": 150, // gruen wie ein Ergebnis
|
|
"Personen": 70, // golden wie ein Schluessel
|
|
"Kalender": 320, // pink, hebt den Tagesplan heraus
|
|
"Dashboard": 250, // blau, der Ausgangspunkt
|
|
};
|
|
|
|
/* ---------- Kandidaten ---------------------------------------------- */
|
|
|
|
const KANDIDATEN = [];
|
|
for (let H = 0; H < 360; H += 3) {
|
|
for (const L of [0.60, 0.66, 0.72, 0.78, 0.84]) {
|
|
/* Die groesste Farbstaerke suchen, die bei diesem Ton und dieser
|
|
Helligkeit noch darstellbar ist -- gedeckelt bei 0,17
|
|
(augenschonend, siehe Kopf). Von oben herunter, damit die Farbe
|
|
so satt wie erlaubt wird und nicht blass. */
|
|
for (let C = 0.17; C >= 0.05; C -= 0.005) {
|
|
const f = ausOklch(L, C, H);
|
|
if (!f) continue;
|
|
if (kontrast(f) < 4.5) break; // zu dunkel fuer Text
|
|
KANDIDATEN.push({ ...f, L, C, H });
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ---------- Auswahl: den kleinsten Abstand so gross wie moeglich ----
|
|
|
|
Erst gierig (nimm immer die Farbe, die am weitesten von allen schon
|
|
gewaehlten weg ist), dann verbessern: Jede gewaehlte Farbe wird
|
|
probeweise gegen jede andere getauscht; wird der kleinste Abstand
|
|
dadurch groesser, bleibt der Tausch. Das laeuft, bis keine
|
|
Verbesserung mehr kommt.
|
|
|
|
Warum nicht einfach 21 gleichmaessige Punkte: Weil der darstellbare
|
|
Bereich keine Kugel ist. Gelb vertraegt viel Helligkeit und wenig
|
|
Buntheit, Blau umgekehrt. Ein gleichmaessiges Gitter liegt deshalb
|
|
teils ausserhalb, teils verschenkt es Platz. */
|
|
|
|
const anzahl = KACHELN.length;
|
|
let gewaehlt = [KANDIDATEN.reduce((a, b) => (a.L * 100 + a.H < b.L * 100 + b.H ? a : b))];
|
|
while (gewaehlt.length < anzahl) {
|
|
let beste = null, besterWert = -1;
|
|
for (const k of KANDIDATEN) {
|
|
if (gewaehlt.includes(k)) continue;
|
|
const naechster = Math.min(...gewaehlt.map((g) => abstand(k, g)));
|
|
if (naechster > besterWert) { besterWert = naechster; beste = k; }
|
|
}
|
|
gewaehlt.push(beste);
|
|
}
|
|
|
|
const kleinster = (menge) => {
|
|
let m = Infinity;
|
|
for (let i = 0; i < menge.length; i++)
|
|
for (let j = i + 1; j < menge.length; j++) m = Math.min(m, abstand(menge[i], menge[j]));
|
|
return m;
|
|
};
|
|
|
|
let verbessert = true, runden = 0;
|
|
while (verbessert && runden < 60) {
|
|
verbessert = false; runden++;
|
|
for (let i = 0; i < gewaehlt.length; i++) {
|
|
const jetzt = kleinster(gewaehlt);
|
|
for (const k of KANDIDATEN) {
|
|
if (gewaehlt.includes(k)) continue;
|
|
const probe = gewaehlt.slice(); probe[i] = k;
|
|
if (kleinster(probe) > jetzt + 1e-9) { gewaehlt = probe; verbessert = true; break; }
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ---------- Zuordnung: Wunschton, wo er ohne Verlust geht ---------- */
|
|
|
|
const frei = gewaehlt.slice();
|
|
const zuteilung = new Map();
|
|
/* Erst die Kacheln mit Wunsch -- jede bekommt die freie Farbe, deren
|
|
Ton ihrem Wunsch am naechsten liegt. */
|
|
for (const [name, wunsch] of Object.entries(WUNSCHTON)) {
|
|
if (!KACHELN.includes(name)) continue;
|
|
let beste = 0, bestAbw = Infinity;
|
|
frei.forEach((f, i) => {
|
|
const abw = Math.min(Math.abs(f.H - wunsch), 360 - Math.abs(f.H - wunsch));
|
|
if (abw < bestAbw) { bestAbw = abw; beste = i; }
|
|
});
|
|
zuteilung.set(name, frei.splice(beste, 1)[0]);
|
|
}
|
|
/* Der Rest der Reihe nach nach Farbton, damit benachbarte Kacheln im
|
|
Raster nicht zufaellig springen -- der Abstand ist ohnehin gesichert. */
|
|
frei.sort((a, b) => a.H - b.H);
|
|
for (const name of KACHELN) if (!zuteilung.has(name)) zuteilung.set(name, frei.shift());
|
|
|
|
/* ---------- Nachweis ------------------------------------------------ */
|
|
|
|
const ergebnis = KACHELN.map((n) => ({ name: n, ...zuteilung.get(n) }));
|
|
const min = kleinster(ergebnis);
|
|
const Ls = ergebnis.map((f) => f.oklab[0]);
|
|
let unter5 = 0, paare = 0;
|
|
for (let i = 0; i < ergebnis.length; i++)
|
|
for (let j = i + 1; j < ergebnis.length; j++) {
|
|
paare++; if (abstand(ergebnis[i], ergebnis[j]) < 0.05) unter5++;
|
|
}
|
|
|
|
console.log("ALT (gemessen): kleinster Abstand 0,0328 · 21 von 210 Paaren unter 0,05"
|
|
+ " · Helligkeitsspanne 0,002\n");
|
|
console.log(`NEU: kleinster Abstand ${min.toFixed(4)} · ${unter5} von ${paare}`
|
|
+ ` Paaren unter 0,05 · Helligkeitsspanne ${(Math.max(...Ls) - Math.min(...Ls)).toFixed(3)}\n`);
|
|
|
|
const schlechtester = Math.min(...ergebnis.map(kontrast));
|
|
console.log(`Schlechtester Kontrast gegen den Grund: ${schlechtester.toFixed(2)}:1`
|
|
+ ` (Grenze 4,5) -> ${schlechtester >= 4.5 ? "haelt" : "HAELT NICHT"}\n`);
|
|
|
|
console.log("/* Die Nummern bleiben an ihren Kacheln -- eine Farbe gehoert zu");
|
|
console.log(" einem Bereich, nicht zu einem Platz im Raster. */");
|
|
ergebnis.forEach((f, i) => {
|
|
const n = `[data-ton="${i + 1}"]`.padEnd(16);
|
|
console.log(`${n}{ --ton: ${f.hex}; } /* ${f.name} */`);
|
|
});
|
|
|
|
/* DIE ZAHLEN GEHOEREN IN DIE BEDINGUNG, nicht nur in den Bericht:
|
|
Ein Lauf, der eine schlechtere Palette ausgibt als die alte, waere
|
|
sonst nicht von einem guten zu unterscheiden. */
|
|
if (min <= 0.0328) {
|
|
console.error(`\nFEHLER: Der kleinste Abstand (${min.toFixed(4)}) ist nicht besser als`
|
|
+ ` der alte (0,0328). Nichts uebernehmen.`);
|
|
process.exit(1);
|
|
}
|
|
if (schlechtester < 4.5) {
|
|
console.error(`\nFEHLER: Eine Farbe liegt unter 4,5:1 gegen den Grund.`);
|
|
process.exit(1);
|
|
}
|
|
if (ergebnis.length !== 21) {
|
|
console.error(`\nFEHLER: ${ergebnis.length} Farben statt 21.`);
|
|
process.exit(1);
|
|
}
|
|
console.log(`\n${ergebnis.length} Farben, alle Bedingungen erfuellt.`);
|