CharGraph Editor V0.2 - Dokumentation
Regelbasierte Minutenlogik mit intelligenter Modifikator-Validierung
Version: 0.2 Datum: 02. Januar 2026 Autor: Rainer Wieland
Inhaltsverzeichnis
- Übersicht
- Hauptänderungen von V0.1 zu V0.2
- Regelbasierte Architektur
- Modifikator-System
- Positionsbasierte Validierung
- LED-Logik im Detail
- Praxisbeispiele
- URL-Parameter
- Migration von V0.1 zu V0.2
- Technische Details
Übersicht
CharGraph Editor V0.2 ist eine vollständig überarbeitete Version des CharGraph-Pattern-Editors mit regelbasierter Minutenlogik und intelligenter Validierung von Zeitmodifikatoren.
Kernfeatures:
- Regelbasierte Minutenlogik - Deklarative Regeln statt if-else-Kaskaden
- Positionsbasierte Validierung - Prüft, ob Modifikatoren an der richtigen Stelle im Grid sind
- Intelligente Fallback-Strategie - Progressive Auswahl der besten verfügbaren Option
- Korrekte LED-Logik - Links = addieren, rechts = subtrahieren
- URL-Parameter Support - Pattern und Zeit direkt über URL laden
Hauptänderungen
Von V0.1 zu V0.2
| Aspekt | V0.1 | V0.2 |
|---|---|---|
| Minutenlogik | 285 Zeilen if-else | 60 deklarative Regeln |
| Code-Größe | ~2900 Zeilen | ~3200 Zeilen |
| Validierung | Nur Existenz | Position + Existenz |
| Fallback | Oft fehlerhaft | Progressiv & intelligent |
| LED-Richtung | Immer links | Links/rechts je nach Kontext |
| Wartbarkeit | Schwierig | Sehr gut |
Konkrete Verbesserungen:
-
Reduzierung der if-else-Komplexität
- Vorher: 285 Zeilen verschachtelter if-else-Statements
- Nachher: 60 Regel-Objekte mit Handler-Funktionen
-
Intelligente Modifikator-Auswahl
- Vorher: Modifikator existiert → wird verwendet
- Nachher: Modifikator existiert + an richtiger Position → wird verwendet
-
Menschlich-logische Zeitangaben
- Vorher: "ES IST NACH EINS (+4)" bei 01:04
- Nachher: "ES IST BALD FÜNF NACH EINS (+1)" bei 01:04
Regelbasierte Architektur
Konzept
Jede Minute (0-59) wird durch ein Regel-Objekt repräsentiert:
{
range: [min, max], // Minuten-Bereich
handler: (ctx) => [...] // Funktion, die Wörter zurückgibt
}
Beispiel: Die :04-Regel
// :04 - BALD/FAST FÜNF NACH (1 Min vor :05, FAST > BALD mit Validierung)
{
range: [4, 4],
handler: (ctx) => {
// Versuche FAST mit Validierung
if(ctx.hasFast) {
const testWords = [...ctx.words, "FAST", "FÜNF", "NACH", ctx.hours[ctx.h12]];
if(validateWordSequence(testWords, ctx.gridStr).valid) {
return ["FAST", "FÜNF", "NACH", ctx.hours[ctx.h12]];
}
}
// Fallback: BALD
if(ctx.hasBald) {
return ["BALD", "FÜNF", "NACH", ctx.hours[ctx.h12]];
}
// Letzter Fallback
return ["NACH", ctx.hours[ctx.h12]];
}
}
Kontext-Objekt
Jeder Handler erhält ein Kontext-Objekt mit allen relevanten Informationen:
const context = {
mm, // Aktuelle Minute (0-59)
h12, // Stunde im 12h-Format (0-11)
hours, // Array mit Stunden-Wörtern
hourWord, // Aktuelles Stunden-Wort (z.B. "SIEBEN")
hasUhrAtEnd, // "UHR" am Ende verfügbar?
hasKurz, // "KURZ" im Grid?
hasBald, // "BALD" im Grid?
hasFast, // "FAST" im Grid?
hasZwanzig, // "ZWANZIG" im Grid?
hasDreiviertel, // "DREIVIERTEL" im Grid?
gridStr, // Grid als String (für Validierung)
words // Bereits gesammelte Wörter
};
Modifikator-System
Die 5 Modifikatoren
| Modifikator | Bedeutung | Verwendung | Position |
|---|---|---|---|
| FAST | 1 Min vor Marke | "FAST HALB" = :29 | VOR HALB |
| BALD | 2 Min vor Marke | "BALD FÜNF NACH" = :03 | VOR HALB |
| KURZ | Kurz davor/danach | "KURZ VOR HALB" = :28 | Flexibel |
| ZWANZIG | Alternative zu "ZEHN VOR HALB" | "ZWANZIG NACH" = :20 | Flexibel |
| DREIVIERTEL | Alternative zu "VIERTEL VOR" | "DREIVIERTEL" = :45 | Flexibel |
Prioritäten bei 1-Minute-vor-Marken
Bei Uhrzeiten wie :04, :09, :14, :19, :29, :34, :39, :49, :54, :59:
FAST (validiert) > BALD > Basis-Zeit
Warum Validierung?
FAST kann im Grid existieren, aber an der falschen Position stehen:
- Korrekt: FAST steht VOR HALB
- Falsch: FAST steht NACH HALB
Modifikator-Kombinationen
Fall 1: Alle Modifikatoren vorhanden, alle an richtiger Position
Pattern: ES_IST_KURZBALDFASTFÜNFZEHNVORNACHHALB_...
06:29:
- hasFast = true, Position: VOR HALB
- Validierung erfolgreich
- Anzeige: "ES IST FAST HALB SIEBEN" + 1 LED rechts
Fall 2: FAST vorhanden, aber an falscher Position
Pattern: ES_IST_BALDFÜNFZEHNVORNACH_HALB_FAST...
06:29:
- hasFast = true, aber Position: NACH HALB
- Validierung fehlgeschlagen
- Fallback zu KURZ (falls vorhanden) oder BALD
- Anzeige: "ES IST BALD HALB SIEBEN" + 2 LEDs rechts
Fall 3: BALD vorhanden, FAST nicht
Pattern: ES_IST_BALDFÜNFZEHNVORNACHHALB_...
01:04:
- hasFast = false
- hasBald = true
- Anzeige: "ES IST BALD FÜNF NACH EINS" + 1 LED rechts
Fall 4: Weder FAST noch BALD
Pattern: ES_IST_FÜNFZEHNVORNACHHALB_...
01:04:
- hasFast = false
- hasBald = false
- Anzeige: "ES IST NACH EINS" + 4 LEDs links
Positionsbasierte Validierung
Problem
Modifikatoren können im Grid existieren, aber an der falschen Position:
Beispiel-Pattern:
ES_IST_BALDFÜNFZWANZIGDREIVIERTELZEHNKURZEITFASTNACHVOR_HALB_VIER_...
^ ^ ^
BALD (Position 7-10) FAST HALB
(Position 41) (Position 51)
- HALB ist an Position ~51
- FAST ist an Position ~41
- FAST kommt VOR HALB → Validierung erfolgreich
Validierungslogik
Die Funktion validateWordSequence() prüft:
- Sequenz-Reihenfolge: Kommen die Wörter in der richtigen Reihenfolge im Grid vor?
- Positionsbeschränkungen:
- Minutenwörter (FÜNF, ZEHN, etc.) müssen VOR HALB stehen
- Stundenwörter müssen NACH HALB stehen
- FAST/BALD/KURZ müssen VOR HALB stehen (bei "HALB"-Zeiten)
Validierungs-Beispiel
06:29 mit Pattern:
ES_IST_BALDFÜNF...KURZEITFASTNACHVOR_HALB_VIER_ZWEINSIEBENELF...
Handler-Logik:
// Schritt 1: Prüfe FAST mit Validierung
if(ctx.hasFast) {
const testWords = ["ES", "IST", "FAST", "HALB", "SIEBEN"];
// Validierung:
// - FAST an Position ~41
// - HALB an Position ~51
// - SIEBEN an Position ~60 (nach HALB)
// - Sequenz korrekt
if(validateWordSequence(testWords, gridStr).valid) {
return ["FAST", "HALB", "SIEBEN"]; // Erfolgreich
}
}
// Schritt 2: Falls FAST fehlschlägt → KURZ
if(ctx.hasKurz) {
return ["KURZ", "VOR", "HALB", "SIEBEN"];
}
// Schritt 3: Falls KURZ fehlt → BALD
if(ctx.hasBald) {
return ["BALD", "HALB", "SIEBEN"];
}
// Schritt 4: Letzter Fallback
return ["FÜNF", "VOR", "HALB", "SIEBEN"];
Ergebnis: "ES IST FAST HALB SIEBEN"
LED-Logik im Detail
Grundprinzip
LEDs zeigen die Differenz zwischen der angezeigten 5-Minuten-Marke und der tatsächlichen Minute.
Zwei Modi:
- LEDs von LINKS (addieren) - Bei NACH-Zeiten
- LEDs von RECHTS (subtrahieren) - Bei VOR-Zeiten, FAST, BALD
LED-Richtungs-Regeln
const isInvertedDisplay = hasBald || hasFast || hasVor;
// Bei invertierten Zeiten: LEDs von rechts
// Bei normalen Zeiten: LEDs von links
for(let i = 0; i < remainder; i++) {
const dotIndex = isInvertedDisplay ? (3 - i) : i;
if(dots[dotIndex]) dots[dotIndex].classList.add('lit');
}
Remainder-Berechnung
Zwei verschiedene Berechnungen:
if(hasBald || hasFast || (hasKurz && hasVor)) {
// Fehlende Minuten bis zur nächsten Marke
remainder = mm % 5 === 0 ? 0 : (5 - mm % 5);
} else {
// Vergangene Minuten seit der letzten Marke
remainder = mm % 5;
}
LED-Tabelle
| Modifikator | Berechnung | Richtung | Bedeutung |
|---|---|---|---|
| FAST | 5 - mm%5 | Rechts | Fehlende Minuten |
| BALD | 5 - mm%5 | Rechts | Fehlende Minuten |
| KURZ VOR | 5 - mm%5 | Rechts | Fehlende Minuten |
| VOR (ohne KURZ) | mm%5 | Rechts | Von Minutenzahl abziehen |
| NACH | mm%5 | Links | Zur Zeit addieren |
| KURZ NACH | mm%5 | Links | Zur Zeit addieren |
Detaillierte Beispiele
Beispiel 1: FAST HALB (06:29)
Zeit: 06:29
Anzeige: "ES IST FAST HALB SIEBEN"
HALB SIEBEN = 06:30
Berechnung:
- mm = 29
- hasFast = true (in wordsToLight)
- remainder = 5 - 29%5 = 5 - 4 = 1
- isInvertedDisplay = true (weil hasFast)
- LEDs: 1 von RECHTS
Bedeutung: Noch 1 Minute bis HALB SIEBEN
Beispiel 2: BALD FÜNF NACH (01:03)
Zeit: 01:03
Anzeige: "ES IST BALD FÜNF NACH EINS"
FÜNF NACH EINS = 01:05
Berechnung:
- mm = 3
- hasBald = true (in wordsToLight)
- remainder = 5 - 3%5 = 5 - 3 = 2
- isInvertedDisplay = true (weil hasBald)
- LEDs: 2 von RECHTS
Bedeutung: Noch 2 Minuten bis FÜNF NACH
Beispiel 3: FÜNF VOR HALB (06:27)
Zeit: 06:27
Anzeige: "ES IST FÜNF VOR HALB SIEBEN"
FÜNF VOR HALB = 06:25
HALB SIEBEN = 06:30
Berechnung:
- mm = 27
- hasVor = true
- hasBald = false (nicht in wordsToLight!)
- hasFast = false
- remainder = mm%5 = 27%5 = 2
- isInvertedDisplay = true (weil hasVor)
- LEDs: 2 von RECHTS
Bedeutung: FÜNF VOR minus 2 = DREI VOR HALB
Tatsächlich: 06:27 = 3 Minuten vor 06:30
Beispiel 4: FÜNF NACH (01:06)
Zeit: 01:06
Anzeige: "ES IST FÜNF NACH EINS"
FÜNF NACH EINS = 01:05
Berechnung:
- mm = 6
- hasVor = false
- hasBald = false
- hasFast = false
- remainder = mm%5 = 6%5 = 1
- isInvertedDisplay = false (normale NACH-Zeit)
- LEDs: 1 von LINKS
Bedeutung: FÜNF NACH plus 1 = SECHS NACH
Tatsächlich: 01:06
Beispiel 5: KURZ VOR HALB (06:28)
Zeit: 06:28
Anzeige: "ES IST KURZ VOR HALB SIEBEN"
HALB SIEBEN = 06:30
Berechnung:
- mm = 28
- hasKurz = true (in wordsToLight)
- hasVor = true (in wordsToLight)
- remainder = 5 - 28%5 = 5 - 3 = 2
- isInvertedDisplay = true (weil hasVor)
- LEDs: 2 von RECHTS
Bedeutung: Noch 2 Minuten bis HALB SIEBEN
Tatsächlich: 06:28 = 2 Minuten vor 06:30
Warum zwei verschiedene Berechnungen?
BALD/FAST/KURZ VOR: "Fast an der Marke"
- Zeigen an, wie viele Minuten bis zur Marke fehlen
- Berechnung:
5 - mm%5 - Beispiel: 06:29 → "FAST HALB" → 1 Minute fehlt bis :30
VOR (ohne KURZ): "X Minuten vor Marke"
- Zeigen an, wie viele Minuten seit der letzten Marke vergangen sind
- Diese werden von der Minutenzahl abgezogen
- Berechnung:
mm%5 - Beispiel: 06:27 → "FÜNF VOR" + 2 LEDs → "DREI VOR"
NACH: "X Minuten nach Marke"
- Zeigen an, wie viele Minuten seit der Marke vergangen sind
- Diese werden zur Zeit addiert
- Berechnung:
mm%5 - Beispiel: 01:06 → "FÜNF NACH" + 1 LED → "SECHS NACH"
Praxisbeispiele
Szenario 1: Vollständiges Pattern mit allen Modifikatoren
Pattern:
ES_IST_BALDFÜNFZWANZIGDREIVIERTELZEHNKURZEITFASTNACHVOR_HALB_VIER_ZWEINSIEBENELFZWÖLFÜNFZEHNEUNACHT_SECHS_DREI
Verfügbare Modifikatoren:
- BALD (Position 7-10)
- FÜNFZWANZIG → enthält FÜNF, ZWANZIG (nicht als einzelne Wörter)
- DREIVIERTEL (Position 12-22)
- ZEHN (Position 23-26)
- KURZ (Position 27-30, aber in "KURZZEIT")
- FAST (Position 36-39)
- NACH (Position 40-43)
- VOR (Position 44-46)
- HALB (Position 48-51)
Zeitbeispiele:
| Zeit | Anzeige | LEDs | Erklärung |
|---|---|---|---|
| 06:29 | ES IST FAST HALB SIEBEN | 1 rechts | FAST validiert ✓, 1 Min bis :30 |
| 06:28 | ES IST KURZ VOR HALB SIEBEN | 2 rechts | KURZ VOR, 2 Min bis :30 |
| 06:27 | ES IST BALD HALB SIEBEN | 3 rechts | BALD (kein FAST+KURZ gleichzeitig) |
| 01:04 | ES IST FAST FÜNF NACH EINS | 1 rechts | FAST validiert, 1 Min bis :05 |
| 01:03 | ES IST BALD FÜNF NACH EINS | 2 rechts | BALD, 2 Min bis :05 |
Szenario 2: Pattern ohne FAST
Pattern:
ES_IST_BALDFÜNFZEHNVORNACHHALB_ZWEI_EINSDREIVIERFÜNFSECHSSIEBEN...
Verfügbare Modifikatoren:
- BALD
- FAST (nicht vorhanden)
Zeitbeispiele:
| Zeit | Anzeige | LEDs | Erklärung |
|---|---|---|---|
| 06:29 | ES IST BALD HALB SIEBEN | 2 rechts | Kein FAST → BALD |
| 01:04 | ES IST BALD FÜNF NACH EINS | 1 rechts | Kein FAST → BALD |
Szenario 3: Pattern ohne BALD und FAST
Pattern:
ES_IST_FÜNFZEHNVORNACHHALB_ZWEI_EINSDREIVIERFÜNFSECHSSIEBEN...
Verfügbare Modifikatoren:
- BALD (nicht vorhanden)
- FAST (nicht vorhanden)
Zeitbeispiele:
| Zeit | Anzeige | LEDs | Erklärung |
|---|---|---|---|
| 06:29 | ES IST FÜNF VOR HALB SIEBEN | 4 links | Kein Modifikator, normales VOR |
| 01:04 | ES IST NACH EINS | 4 links | Kein Modifikator, nur NACH |
| 01:06 | ES IST FÜNF NACH EINS | 1 links | Normale NACH-Zeit |
Szenario 4: FAST an falscher Position
Pattern:
ES_IST_BALDFÜNFZEHNVORNACH_HALB_FAST_ZWEI_EINSDREIVIER...
^ ^
HALB FAST (falsche Reihenfolge!)
Verfügbare Modifikatoren:
- BALD
- FAST (aber NACH HALB!)
06:29:
Handler für :29:
1. Prüfe FAST:
- hasFast = true
- Teste: ["ES", "IST", "FAST", "HALB", "SIEBEN"]
- Validierung: FAST steht NACH HALB
- Validierung fehlgeschlagen
2. Prüfe KURZ:
- hasKurz = false
3. Prüfe BALD:
- hasBald = true
- Ergebnis: ["BALD", "HALB", "SIEBEN"]
Anzeige: "ES IST BALD HALB SIEBEN" + 2 LEDs rechts
URL-Parameter
Verwendung
Die Seite unterstützt URL-Parameter zum direkten Laden von Pattern und Zeit:
https://www.chargraph.de/charMatrixV02.html?pattern=ES_IST_BALD...&time=06:29
Parameter
| Parameter | Format | Beispiel | Beschreibung |
|---|---|---|---|
pattern | String | ES_IST_BALD... | Lädt das Pattern ins Grid |
time | HH:MM oder H:MM | 06:29 oder 6:29 | Setzt Simulation auf Zeit |
Beispiele
Nur Pattern:
?pattern=ES_IST_BALDFÜNFZWANZIGDREIVIERTELZEHNKURZEITFASTNACHVOR_HALB_VIER_ZWEINSIEBENELFZWÖLFÜNFZEHNEUNACHT_SECHS_DREI
Pattern + Zeit:
?pattern=ES_IST_BALD...&time=06:29
Nur Zeit:
?time=06:29
Implementierung
Die Funktion loadFromURLParams() wird beim Laden der Seite automatisch aufgerufen:
function loadFromURLParams() {
const params = new URLSearchParams(window.location.search);
// Pattern laden
const pattern = params.get('pattern');
if(pattern) {
const patternUpper = pattern.toUpperCase().replace(/\s+/g, '');
// ... Grid füllen
}
// Zeit setzen
const time = params.get('time');
if(time && /^\d{1,2}:\d{2}$/.test(time)) {
const [h, m] = time.split(':');
const formattedTime = `${h.padStart(2, '0')}:${m}`;
simSelector.value = formattedTime;
handleSimChange();
}
}
Migration von V0.1 zu V0.2
Kompatibilität
V0.2 ist vollständig rückwärtskompatibel mit V0.1:
- Alle Pattern, die in V0.1 funktionieren, funktionieren auch in V0.2
- Die Ausgabe ist identisch oder besser (menschlich-logischer)
Was sich ändert
-
Bessere Zeitangaben bei 1-Minute-vor-Marken
- V0.1: "ES IST NACH EINS (+4)" bei 01:04
- V0.2: "ES IST BALD FÜNF NACH EINS (+1)" bei 01:04
-
Korrekte LED-Richtung
- V0.1: Immer von links
- V0.2: Links bei NACH, rechts bei VOR/FAST/BALD
-
Validierung
- V0.1: Keine Positionsprüfung
- V0.2: Prüft Position von Modifikatoren
Empfohlene Anpassungen
Wenn du ein bestehendes Pattern hast:
- Teste mit V0.2: Öffne das Pattern in V0.2
- Prüfe kritische Zeiten: :04, :09, :14, :19, :29, :34, :39, :49, :54, :59
- Achte auf LED-Richtung: Bei VOR-Zeiten sollten LEDs von rechts sein
Wenn FAST an der falschen Position steht:
- Option 1: Verschiebe FAST im Pattern vor HALB
- Option 2: Entferne FAST (V0.2 nutzt dann BALD als Fallback)
Technische Details
MINUTE_RULES Array
Zentrale Datenstruktur mit 60 Regel-Objekten (eine pro Minute):
const MINUTE_RULES = [
{ range: [0, 0], handler: (ctx) => {...} }, // :00
{ range: [1, 2], handler: (ctx) => {...} }, // :01-:02
// ... 58 weitere Regeln
{ range: [59, 59], handler: (ctx) => {...} } // :59
];
Handler-Funktion Struktur
Jeder Handler folgt diesem Pattern:
handler: (ctx) => {
// 1. Prüfe primäre Option mit Validierung
if(ctx.hasModifier) {
const testWords = [...ctx.words, "MODIFIER", "TIME", ctx.hourWord];
if(validateWordSequence(testWords, ctx.gridStr).valid) {
return ["MODIFIER", "TIME", ctx.hourWord];
}
}
// 2. Fallback zu sekundärer Option
if(ctx.hasSecondary) {
return ["SECONDARY", "TIME", ctx.hourWord];
}
// 3. Letzter Fallback
return ["BASE", "TIME", ctx.hourWord];
}
Validierungs-Algorithmus
function validateWordSequence(words, gridStr) {
let lastPos = -1;
const halbIndex = gridStr.indexOf("HALB");
for(const word of words) {
const pos = gridStr.indexOf(word, lastPos + 1);
if(pos === -1 || pos <= lastPos) {
return { valid: false, reason: "Sequence error" };
}
// Positionsbeschränkungen
if(isMinuteWord(word) && halbIndex !== -1 && pos > halbIndex) {
return { valid: false, reason: "Minute word after HALB" };
}
if(isHourWord(word) && halbIndex !== -1 && pos < halbIndex) {
return { valid: false, reason: "Hour word before HALB" };
}
lastPos = pos;
}
return { valid: true };
}
Performance
- Regel-Lookup: O(1) amortisiert (Binary Search über ranges)
- Validierung: O(n) wobei n = Anzahl Wörter (typisch 4-6)
- Gesamt: < 1ms pro Zeitberechnung
Zusammenfassung
CharGraph Editor V0.2 bietet:
- Regelbasierte Architektur - Wartbar, erweiterbar, verständlich
- Intelligente Validierung - Prüft Position von Modifikatoren
- Menschlich-logische Ausgaben - "BALD" statt "+4"
- Korrekte LED-Logik - Links/rechts je nach Kontext
- Vollständige Rückwärtskompatibilität - Alle V0.1 Pattern funktionieren
Kernlogik
Modifikator vorhanden?
└─> Ja → An richtiger Position?
└─> Ja → Verwenden ✓
└─> Nein → Nächster Fallback
└─> Nein → Nächster Fallback
LED-Richtung:
NACH-Zeiten → Links (addieren)
VOR/FAST/BALD → Rechts (subtrahieren)
LED-Anzahl:
FAST/BALD/KURZ VOR → Fehlende Minuten (5 - mm%5)
VOR/NACH → Vergangene Minuten (mm%5)
Support
Bei Fragen oder Problemen:
- GitHub Issues: https://github.com/anthropics/claude-code/issues
- Dokumentation: Siehe diese Datei
Version: 0.2 Stand: 02. Januar 2026 Lizenz: Siehe Hauptprojekt