CharGraph V0.2

Technische Dokumentation und Implementierungsdetails der neuen Version 0.2.

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. Bedienungsanleitung
  3. Regelbasierte Architektur
  4. Modifikator-System
  5. Positionsbasierte Validierung
  6. LED-Logik im Detail
  7. Praxisbeispiele
  8. URL-Parameter
  9. 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

Bedienungsanleitung

Der CharGraph Editor besteht aus mehreren Bereichen, die zusammen ein vollständiges Design- und Test-System bilden.

1. Das Buchstaben-Grid (11×10 Matrix)

Das zentrale Element des Editors ist die 11 Spalten × 10 Zeilen große Matrix mit insgesamt 110 Zeichen. Hier definieren Sie das Layout aller Buchstaben:

Verwendung:

  • Klicken Sie auf eine Zelle, um einen Buchstaben einzutippen
  • Tippen Sie Buchstaben ein: ES, IST, FÜNF, etc.
  • Ein Unterstrich _ oder Leerzeichen bedeutet "leere Zelle"
  • Das Gitter speichert automatisch Ihre Eingabe

Beispiel-Layout (11 Zeichen breit, 10 Zeilen hoch):

ESISTKFÜNFZ
EHNVIERTELN
ACHZNACHRWD
HALBUSECHSV
IERCELFZWÖ
LFÜNFZEHNE
UNACHTDREIN
SIEBENFZWE
IVSUHRM___
___________

Vordefinierte Wörter zum Einfügen:

Hauptkategorien:

  • Einleitung: ES, IST
  • Minutenwörter: FÜNF, ZEHN, VIERTEL, ZWANZIG, HALB
  • Präpositionen: VOR, NACH
  • Modifikatoren: KURZ, BALD, FAST
  • Stundenwörter: EINS bis ZWÖLF
  • Abschluss: UHR

Verwendung:

  • Klicken Sie auf ein Wort in der Palette
  • Das Wort wird in die nächste verfügbare Zelle eingefügt (von links oben nach rechts unten)
  • Alternativ: Tippen Sie den Buchstaben direkt ins Gitter

3. Zeit-Simulator (oben rechts)

Wählen Sie eine Uhrzeit aus, um zu sehen, welche Wörter der Editor auswählt:

Funktionen:

  • Dropdown-Auswahl: Vordefinierte Uhrzeiten mit Beispielen (z.B. "03:15 - VIERTEL NACH DREI")
  • Navigation: Pfeiltasten < und > für vorherige/nächste Zeit
  • Manuelle Eingabe: Geben Sie eine Zeit im Format HH:MM ein (z.B. 14:30)
  • Live-Modus: Zeigt aktuelle Uhrzeit an (optional)

Was passiert:

  • Der Simulator sucht die Wörter für die eingegebene Zeit
  • Gefundene Wörter werden im Gitter hervorgehoben
  • Ungültige Kombinationen zeigen eine Fehlermeldung

4. Validierung und Feedback

Status-Anzeige:

  • 🟢 Grün: Alle Wörter für diese Zeit sind vorhanden und korrekt positioniert
  • 🔴 Rot: Wörter sind vorhanden, aber die Wort-Sequenz ist ungültig
  • ⚠️ Warnung: Einige Worte fehlen oder sind nicht an der richtigen Position

Validierungs-Checks:

  • Prüft, ob jedes Wort innerhalb eines 11-Zeichen Blocks liegt (kein Wrap-around zwischen Zeilen)
  • Prüft die logische Reihenfolge: Einleitung → Minuten → Stunden → Abschluss
  • Prüft Duplikate und Zeichenkonflikte

5. Kontrol-Panel (unten)

Buttons und Funktionen:

ButtonFunktionTastatur
↶ RückgängigLetzte Änderung zurücksetzenStrg+Z
↷ WiederherstellenÄnderung wiederherstellenStrg+Y
?Hilfe & Anleitung anzeigen-
🗑️ LöschenGesamtes Gitter leeren-
💡 VorschlagMuster-Layout laden-
🎲 FüllenLeere Zellen zufällig füllen-
🔍 PrüfenDoppelte Zeichen prüfen-
🌐 UhrzeitLayout extern anzeigen-
⚙️ SoftwareFirmware-Code generieren-
⚙️ STL3D-Modell für 3D-Druck generieren-

Dateiname-Eingabe:

  • Geben Sie einen Namen für Ihr Projekt ein (max. 8 Zeichen)
  • Wird verwendet für Download-Dateiname und Identifikation

6. Output-String

Das unterste Textfeld zeigt den 110-Zeichen langen Pattern-String:

  • Automatisch aktualisiert beim Ändern des Gitters
  • Kopierbar mit 📋 Button
  • Kann direkt bearbeitet werden (wird ins Gitter synchronisiert)

7. Shortcuts & Tastaturkürzel

TastaturFunktion
Strg+ZUndo
Strg+YRedo
PfeiltastenIn Zeit-Navigation gehen (wenn aktiviert)
EnterIm Zeit-Input: Zeit testen
TabNächste Eingabezelle

8. Export-Optionen

Software (⚙️ Software):

  • Generiert Arduino-Code für ESP8266
  • Lädt Firmware mit Ihrem Pattern herunter
  • Erfordnis: Gültiges Layout

STL (⚙️ STL):

  • Erzeugt 3D-Modell für 3D-Druck
  • Format: .stl (laden Sie direkt in Ihren Slicer)
  • Parameter: Dicke (Extrusion), Höhe (Rahmen)

URL-Sharing (🔗):

  • Klicken Sie auf das Adressfeld und kopieren Sie die URL
  • Teilen Sie die komplette URL mit ?pattern=...&time=HH:MM
  • Beim Öffnen werden Pattern und Zeit automatisch geladen

Praktische Workflow-Beispiele

Szenario 1: Neues Pattern von Grund auf

  1. Klicken Sie auf "Löschen" um frisch zu starten
  2. Füllen Sie manuell oder über die Palette die Grundwörter (ES, IST, UHR) ein
  3. Ergänzen Sie Minutenwörter, Stundenwörter, Modifikatoren
  4. Testen Sie mit dem Zeitwähler verschiedene Uhrzeiten
  5. Speichern Sie via "Software" oder "STL"

Szenario 2: Vorschlag anpassen

  1. Klicken Sie "Vorschlag", um ein Muster-Layout zu laden
  2. Bearbeiten Sie einzelne Buchstaben
  3. Testen Sie wieder mit verschiedenen Zeiten
  4. Export nur wenn alle Tests grün zeigen

Szenario 3: Layout mit anderen teilen

  1. Finalisieren Sie Ihr Layout
  2. Wählen Sie eine Test-Zeit im Simulator
  3. Klicken Sie die URL in der Adressleiste (Sie sehen ?pattern=...&time=...)
  4. Kopieren und teilen Sie die URL - andere können es sofort sehen und testen

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