CharGraph Editor V0.2 - Dokumentation

Regelbasierte Minutenlogik mit intelligenter Modifikator-Validierung

Version: 0.2 Datum: 02. Januar 2026 Autor: Rainer Wieland


Inhaltsverzeichnis

  1. Übersicht
  2. Hauptänderungen von V0.1 zu V0.2
  3. Regelbasierte Architektur
  4. Modifikator-System
  5. Positionsbasierte Validierung
  6. LED-Logik im Detail
  7. Praxisbeispiele
  8. URL-Parameter
  9. Migration von V0.1 zu V0.2
  10. 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

AspektV0.1V0.2
Minutenlogik285 Zeilen if-else60 deklarative Regeln
Code-Größe~2900 Zeilen~3200 Zeilen
ValidierungNur ExistenzPosition + Existenz
FallbackOft fehlerhaftProgressiv & intelligent
LED-RichtungImmer linksLinks/rechts je nach Kontext
WartbarkeitSchwierigSehr gut

Konkrete Verbesserungen:

  1. Reduzierung der if-else-Komplexität

    • Vorher: 285 Zeilen verschachtelter if-else-Statements
    • Nachher: 60 Regel-Objekte mit Handler-Funktionen
  2. Intelligente Modifikator-Auswahl

    • Vorher: Modifikator existiert → wird verwendet
    • Nachher: Modifikator existiert + an richtiger Position → wird verwendet
  3. 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

ModifikatorBedeutungVerwendungPosition
FAST1 Min vor Marke"FAST HALB" = :29VOR HALB
BALD2 Min vor Marke"BALD FÜNF NACH" = :03VOR HALB
KURZKurz davor/danach"KURZ VOR HALB" = :28Flexibel
ZWANZIGAlternative zu "ZEHN VOR HALB""ZWANZIG NACH" = :20Flexibel
DREIVIERTELAlternative zu "VIERTEL VOR""DREIVIERTEL" = :45Flexibel

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:

  1. Sequenz-Reihenfolge: Kommen die Wörter in der richtigen Reihenfolge im Grid vor?
  2. 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:

  1. LEDs von LINKS (addieren) - Bei NACH-Zeiten
  2. 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

ModifikatorBerechnungRichtungBedeutung
FAST5 - mm%5RechtsFehlende Minuten
BALD5 - mm%5RechtsFehlende Minuten
KURZ VOR5 - mm%5RechtsFehlende Minuten
VOR (ohne KURZ)mm%5RechtsVon Minutenzahl abziehen
NACHmm%5LinksZur Zeit addieren
KURZ NACHmm%5LinksZur 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:

ZeitAnzeigeLEDsErklärung
06:29ES IST FAST HALB SIEBEN1 rechtsFAST validiert ✓, 1 Min bis :30
06:28ES IST KURZ VOR HALB SIEBEN2 rechtsKURZ VOR, 2 Min bis :30
06:27ES IST BALD HALB SIEBEN3 rechtsBALD (kein FAST+KURZ gleichzeitig)
01:04ES IST FAST FÜNF NACH EINS1 rechtsFAST validiert, 1 Min bis :05
01:03ES IST BALD FÜNF NACH EINS2 rechtsBALD, 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:

ZeitAnzeigeLEDsErklärung
06:29ES IST BALD HALB SIEBEN2 rechtsKein FAST → BALD
01:04ES IST BALD FÜNF NACH EINS1 rechtsKein 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:

ZeitAnzeigeLEDsErklärung
06:29ES IST FÜNF VOR HALB SIEBEN4 linksKein Modifikator, normales VOR
01:04ES IST NACH EINS4 linksKein Modifikator, nur NACH
01:06ES IST FÜNF NACH EINS1 linksNormale 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

ParameterFormatBeispielBeschreibung
patternStringES_IST_BALD...Lädt das Pattern ins Grid
timeHH:MM oder H:MM06:29 oder 6:29Setzt 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

  1. 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
  2. Korrekte LED-Richtung

    • V0.1: Immer von links
    • V0.2: Links bei NACH, rechts bei VOR/FAST/BALD
  3. Validierung

    • V0.1: Keine Positionsprüfung
    • V0.2: Prüft Position von Modifikatoren

Empfohlene Anpassungen

Wenn du ein bestehendes Pattern hast:

  1. Teste mit V0.2: Öffne das Pattern in V0.2
  2. Prüfe kritische Zeiten: :04, :09, :14, :19, :29, :34, :39, :49, :54, :59
  3. 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:

  1. Regelbasierte Architektur - Wartbar, erweiterbar, verständlich
  2. Intelligente Validierung - Prüft Position von Modifikatoren
  3. Menschlich-logische Ausgaben - "BALD" statt "+4"
  4. Korrekte LED-Logik - Links/rechts je nach Kontext
  5. 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:


Version: 0.2 Stand: 02. Januar 2026 Lizenz: Siehe Hauptprojekt