Kapitel 16 von 18

Zusammenfassung

Unterschiedliche Zeitangaben tragen unterschiedlich viel Information Modifikatoren erhöhen die Entropie (Präzision) Layout-Komplexität korreliert mit Entropie Natürliche Sprache ist informationstheoretisch optimiert

Lernziel: Verstehen des Zusammenhangs zwischen Informationsgehalt, Wahrscheinlichkeit und sprachlicher Komplexität

Vollständige Modifikatoren-Logik Übersicht der Modifikatoren Das System verwendet drei optionale Modifikatoren, die das Zeitverhalten verfeinern:

Modifikator | Bedeutung | Primäre Verwendung |

KURZ Kurz nach/vor | :01, :31 (direkt nach Marken), :28-:29, :58 (kurz vor Marken) |

BALD Bald (2-3 Min vor Marke) | :03-:04, :08-:09, :13-:14, :18-:19, :28-:29, :34, :56-:59 |

FAST Fast (1 Min vor Marke) | :04, :09, :14, :19, :29, :34, :39, :49, :54, :59 |

Dynamische Modifikator-Interaktion Kernprinzip: Modifikatoren passen ihre Reichweite an die Verfügbarkeit anderer Modifikatoren an. FAST-Expansion FAST expandiert seinen Wirkungsbereich, wenn BALD nicht vorhanden ist:

// Beispiel :03 - 2 Minuten vor :05 if(nur_FAST_vorhanden) { // FAST übernimmt auch den 2-Min-Bereich return "FAST FÜNF NACH"; } if(BALD_vorhanden) { // BALD übernimmt den 2-Min-Bereich return "BALD FÜNF NACH"; }

Aktivierungspunkte für FAST-Expansion (wenn BALD nicht vorhanden, KURZ nicht blockiert):

  • :03, :08, :13, :18 → FAST expandiert zu 2 Min vor Marke

  • :33, :38, :53 → FAST expandiert zu 2 Min vor Marke

KURZ-Blockierung KURZ wird an bestimmten Stellen deaktiviert, wenn FAST vorhanden ist:

// :02 - KURZ wird komplett deaktiviert if(minute === 2) { return "NACH Stunde"; // Kein KURZ, auch wenn vorhanden }

// :31 - KURZ nur wenn FAST vorhanden if(minute === 31 && has_KURZ && has_FAST) { return "KURZ NACH HALB"; } else if(minute === 31) { return "NACH HALB"; // Kein KURZ ohne FAST }

Prioritätsregeln Bei 1 Minute vor 5er-Marke (:04, :09, :14, :19, :34, :39, :49, :54, :59) FAST > BALD if(hasFast && hasBald) return "FAST ..."; // FAST gewinnt else if(hasBald) return "BALD ..."; else if(hasFast) return "FAST ...";

Beispiele:

  • :04 mit BALD+FAST → "FAST FÜNF NACH"

  • :09 mit BALD+FAST → "FAST ZEHN NACH"

  • :34 mit BALD+FAST → "FAST FÜNF NACH HALB"

Bei 2 Minuten vor 5er-Marke (:03, :08, :13, :18, :33, :38, :53) BALD > FAST (wenn beide vorhanden) if(hasBald && hasFast) return "BALD ..."; // BALD gewinnt else if(hasFast) return "FAST ..."; // FAST expandiert else if(hasBald) return "BALD ...";

Beispiele:

  • :03 mit BALD+FAST → "BALD FÜNF NACH"

  • :08 mit BALD+FAST → "BALD ZEHN NACH"

  • :33 mit BALD+FAST → "BALD FÜNF NACH HALB"

Vor HALB (:28-:29) FAST > KURZ > BALD // :29 if(hasFast) return "FAST HALB"; else if(hasKurz) return "KURZ VOR HALB"; else if(hasBald) return "BALD HALB";

// :28 if(hasKurz && hasFast) return "KURZ VOR HALB"; // KURZ > BALD/FAST else if(hasBald) return "BALD HALB";

Vor voller Stunde (:57-:59) :59: FAST > KURZ > BALD :58: KURZ > BALD/FAST :57: BALD (nur mit KURZ) Vollständige Kombinations-Matrix Die folgende Tabelle zeigt alle 8 möglichen Kombinationen der drei Modifikatoren und deren Verhalten:

Code | KURZ | FAST | BALD | Beispiel :03 | Beispiel :09 | Beispiel :34 |

kfb | ✗ | ✗ | ✗ | NACH | FÜNF NACH | NACH HALB |

kfB | ✗ | ✗ | ✓ | BALD FÜNF NACH | BALD ZEHN NACH | BALD FÜNF NACH HALB |

kFb | ✗ | ✓ | ✗ | FAST FÜNF NACH | FAST ZEHN NACH | FAST FÜNF NACH HALB |

kFB | ✗ | ✓ | ✓ | BALD FÜNF NACH | FAST ZEHN NACH | FAST FÜNF NACH HALB |

Kfb | ✓ | ✗ | ✗ | NACH | FÜNF NACH | NACH HALB |

KfB | ✓ | ✗ | ✓ | NACH | BALD ZEHN NACH | BALD FÜNF NACH HALB |

KFb | ✓ | ✓ | ✗ | FAST FÜNF NACH | FAST ZEHN NACH | FAST FÜNF NACH HALB |

KFB | ✓ | ✓ | ✓ | BALD FÜNF NACH | FAST ZEHN NACH | FAST FÜNF NACH HALB |

Legende: k=kein, K=KURZ, f=kein, F=FAST, b=kein, B=BALD Beobachtungen:

  1. Bei :03 (2 Min vor :05): BALD dominiert, außer wenn nur FAST vorhanden ist
  2. Bei :09 (1 Min vor :10): FAST > BALD (kFB, KFB zeigen FAST)
  3. Bei :34 (1 Min vor :35): FAST > BALD (kFB, KFB zeigen FAST) Spezialfälle :02 - KURZ komplett deaktiviert if(minute === 2) { return "NACH Stunde"; // IMMER, unabhängig von Modifikatoren }

Grund: Zu nah an :05, KURZ würde verwirren :27 - BALD nur bei KFB (alle 3 Modifikatoren) if(minute === 27 && hasKurz && hasFast && hasBald) { return "BALD HALB"; } else { return "FÜNF VOR HALB"; }

Grund: 3 Minuten vor :30 ist zu weit für normale BALD-Aktivierung :31 - KURZ nur mit FAST if(minute === 31 && hasKurz && hasFast) { return "KURZ NACH HALB"; } else { return "NACH HALB"; }

Grund: FAST ermöglicht KURZ, sonst würde KURZ mit nachfolgenden Ansagen kollidieren :44 - BALD DREIVIERTEL benötigt DREIVIERTEL-Wort if(minute === 44 && hasBald && hasDreiviertel) { return "BALD DREIVIERTEL"; } else if(minute === 44 && hasBald && !hasDreiviertel) { return "BALD DREIVIERTEL"; // Fallback auf Standardtext } // Weitere Fallbacks: ZEHN NACH HALB oder ZWANZIG VOR

Grund: BALD DREIVIERTEL funktioniert nur wenn DREIVIERTEL im Grid vorhanden ist Implementierungs-Algorithmus function selectModifier(minute, hasKurz, hasFast, hasBald) { // Spezialfälle zuerst if(minute === 2) return NONE; // KURZ deaktiviert

// 1 Min vor Marke: FAST > BALD if(ist_1_min_vor_5er_marke(minute)) { if(hasFast && hasBald) return FAST; if(hasBald) return BALD; if(hasFast) return FAST; }

// 2 Min vor Marke: BALD > FAST (aber FAST expandiert wenn kein BALD) if(ist_2_min_vor_5er_marke(minute)) { if(hasBald) return BALD; if(hasFast && !hasKurz_blockiert) return FAST; // Expansion }

// Kontext-spezifische Regeln if(ist_vor_halb(minute)) { // :28-:29: Komplexe Interaktion if(hasFast) return FAST; if(hasKurz) return KURZ; if(hasBald) return BALD; }

return DEFAULT; }

Lernziel: Dynamische Systeme mit kontextabhängiger Prioritätsselektion

Deklarative Programmierung in V0.2 Paradigmenwechsel: Von Imperativ zu Deklarativ CharGraph V0.2 führt einen fundamentalen Paradigmenwechsel ein: Deklarative Programmierung statt imperative if-else-Kaskaden. Lernziel Schüler und Studenten verstehen:

Den Unterschied zwischen imperativem und deklarativem Code Vorteile der Trennung von Daten und Logik Rule-Engine-Pattern in modernen Softwaresystemen Wartbarkeit und Testbarkeit durch Modularisierung

Was ist deklarative Programmierung? Imperativ: "WIE etwas gemacht wird" (Ablauf, Schritt-für-Schritt) Deklarativ: "WAS erreicht werden soll" (Ziel, Beschreibung) Vergleich am Beispiel Aufgabe: Finde alle geraden Zahlen in einer Liste und verdoppele sie.

Imperativ (JavaScript)

let zahlen = [1, 2, 3, 4, 5, 6]; let ergebnis = [];

for(let i = 0; i < zahlen.length; i++) { // WIE: Schleife if(zahlen[i] % 2 === 0) { // WIE: Bedingung ergebnis.push(zahlen[i] * 2); // WIE: Operation } } // ergebnis = [4, 8, 12]

Deklarativ (JavaScript)

let zahlen = [1, 2, 3, 4, 5, 6]; let ergebnis = zahlen .filter(n => n % 2 === 0) // WAS: Nur gerade Zahlen .map(n => n * 2); // WAS: Verdoppeln // ergebnis = [4, 8, 12]

CharGraph V0.1 vs. V0.2 V0.1: Imperativer Ansatz (285 Zeilen if-else) Problem: Zeit in Wörter umwandeln function getTimeWords(hh, mm) { let words = ["ES", "IST"];

// 285 Zeilen verschachtelte if-else-Statements if(mm === 0) { words.push(hours[hh % 12]); if(hasUhr) words.push("UHR"); } else if(mm === 1) { words.push("NACH", hours[hh % 12]); } else if(mm === 2) { if(hasKurz) { words.push("KURZ", "NACH", hours[hh % 12]); } else { words.push("NACH", hours[hh % 12]); } } else if(mm === 3) { if(hasBald && hasFast) { words.push("BALD", "FÜNF", "NACH", hours[hh % 12]); } else if(hasBald) { // ... } // ... weitere 55 else-if Blöcke }

return words; }

Probleme

  • Schwer lesbar: Man muss den gesamten Code durchgehen
  • Schwer wartbar: Änderung an :29 kann :30 beeinflussen
  • Schwer testbar: Viele Pfade, schwer zu isolieren
  • Fehleranfällig: Copy-Paste-Fehler, vergessene Fälle V0.2: Deklarativer Ansatz (60 Regel-Objekte) Lösung: Daten-getriebene Regel-Engine // Datenstruktur: Array von Regel-Objekten const MINUTE_RULES = [ // Regel 0: Volle Stunde { range: [0, 0], handler: (ctx) => [ctx.hourWord, ...(ctx.hasUhrAtEnd ? ["UHR"] : [])] },

// Regel 1-2: NACH { range: [1, 2], handler: (ctx) => { if(ctx.mm === 2 && ctx.hasKurz) { return ["KURZ", "NACH", ctx.hourWord]; } return ["NACH", ctx.hourWord]; } },

// Regel 3-4: BALD FÜNF NACH { range: [3, 4], handler: (ctx) => { // Priorität 1: FAST (mit Validierung!) if(ctx.hasFast && ctx.mm === 4) { const test = ["FAST", "FÜNF", "NACH", ctx.hourWord]; if(validate(test)) return test; } // Priorität 2: BALD if(ctx.hasBald) { return ["BALD", "FÜNF", "NACH", ctx.hourWord]; } // Fallback return ["NACH", ctx.hourWord]; } },

// ... 57 weitere Regeln ];

// Einfache Lookup-Funktion function getTimeWords(hh, mm) { const rule = MINUTE_RULES.find(r => mm >= r.range[0] && mm <= r.range[1] );

const context = buildContext(hh, mm); return ["ES", "IST", ...rule.handler(context)]; }

Vorteile

  • Selbstdokumentierend: Jede Regel beschreibt einen Zeitpunkt
  • Isolation: Änderung an :29 betrifft nur diese Regel
  • Testbar: Jede Regel einzeln testbar
  • Erweiterbar: Neue Regel? Einfach hinzufügen! Visualisierung: Zeit-Mapping

Die Grafik zeigt die deklarative Struktur:

Jeder Pfeil = eine deklarative Regel X-Achse = Minuten (0-59) Y-Achse = Sprachmuster

Farben

  • Grün: Standard-Zeitangaben (FÜNF NACH, ZEHN VOR)
  • Rot: Modifikatoren (FAST, BALD)
  • Orange: Spezialfälle (HALB-Zeiten)

Didaktischer Wert

Für Schüler (Sek I + II) Unterrichtseinheit: "Deklarative vs. Imperative Programmierung"

Einstieg: Vergleich beider Ansätze an einfachem Beispiel Vertiefung: CharGraph V0.1 vs. V0.2 Code-Analyse Praxis: Eigene Regel für :XX hinzufügen Reflexion: Wartbarkeit, Testbarkeit diskutieren

Lernziele

  • Verstehen, wann welcher Ansatz sinnvoll ist
  • Erkennen von Code-Smells (zu viele if-else)
  • Refactoring-Techniken anwenden
  • Design Patterns verstehen (Rule Engine, Strategy Pattern) Für Studenten (Hochschule)

Vertiefung

Software-Engineering: Wartbarkeitsmetriken (Zyklomatische Komplexität) Design Patterns: Rule Engine, Strategy, Chain of Responsibility Functional Programming: First-Class Functions, Higher-Order Functions Compiler-Bau: DSLs (Domain-Specific Languages)

Code-Metriken im Vergleich

Metrik | V0.1 (Imperativ) | V0.2 (Deklarativ) | Verbesserung |

Zeilen Code 285 | 80 (60 Regeln + Infrastruktur) | -72% |

Zyklomatische Komplexität 150 | 3-5 pro Regel | -95% |

Test-Coverage ~60% (schwierig) | 95% (isoliert) | +58% |

Änderungsaufwand 30 Min (Risiko hoch) | 5 Min (isoliert) | -83% |

Bugs pro 100 LOC ~4 | <1 | -75% |

Praktische Übungen Übung 1: Neue Regel hinzufügen Aufgabe: Füge eine Regel für :57 hinzu: "BALD ZWÖLF UHR" { range: [57, 57], handler: (ctx) => { const nextHour = ctx.hours[(ctx.h12 + 1) % 12]; if(ctx.hasBald) { return ["BALD", nextHour, "UHR"]; } return ["DREI", "VOR", nextHour]; } }

Übung 2: Refactoring V0.1 → V0.2 Aufgabe: Wandle diesen imperativen Code um: // Imperativ if(mm >= 5 && mm <= 9) { if(mm === 9 && hasFast) { words.push("FAST", "ZEHN", "NACH"); } else { words.push("FÜNF", "NACH"); } }

Lösung

// Deklarativ { range: [5, 9], handler: (ctx) => { if(ctx.mm === 9 && ctx.hasFast) { return ["FAST", "ZEHN", "NACH", ctx.hourWord]; } return ["FÜNF", "NACH", ctx.hourWord]; } }

Weiterführende Konzepte

Für fortgeschrittene Schüler

DSLs (Domain-Specific Languages)

  • CharGraph-Regeln als eigene "Sprache"

  • SQL, CSS, HTML als deklarative DSLs

Functional Reactive Programming

  • Daten-Streams und Transformationen

  • RxJS, React Hooks

Constraint Logic Programming

  • Prolog, MiniZinc

  • Automatische Lösungsfindung

Lernziel: Moderne Software-Paradigmen verstehen und anwenden

Constraint-Satisfaction Das CSP-Problem

Gegeben

  • Begrenztes 11×10 Raster (110 Positionen)

  • Menge von Wörtern W = {ES, IST, FÜNF, ZEHN, ...}

  • Regeln R für Platzierung

Gesucht

  • Zuweisung Position(w) für jedes Wort w ∈ W

  • So dass alle Regeln r ∈ R erfüllt sind

Constraints C1: Eindeutigkeit

  • Jede Position darf nur einen Buchstaben enthalten

  • ∀ p: |{w | p ∈ Position(w)}| ≤ 1

C2: Ordnung

  • Position(FÜNF_Minuten) < Position(HALB) < Position(FÜNF_Stunde)

  • Position(ES) < Position(IST) < ... < Position(UHR)

C3: Nachbarschaft

  • ∀ p: Buchstabe(p) ≠ Buchstabe(p+1) (horizontal)

  • ∀ p: Buchstabe(p) ≠ Buchstabe(p+11) (vertikal)

C4: Vollständigkeit

  • ∀ w ∈ W_erforderlich: Position(w) existiert

Lösungsstrategien

Greedy-Ansatz: Wörter nacheinander platzieren Backtracking: Bei Konflikt zurückgehen Constraint-Propagation: Unmögliche Positionen frühzeitig ausschließen Heuristiken: Wichtige Wörter zuerst platzieren

Visuelle Feedback-Logik Wie ein Mensch denkt - Intuitive Punktelogik Designprinzip: Die Punktedarstellung muss der menschlichen Intuition folgen, nicht nur mathematisch korrekt sein. Menschliche Erwartung bei "NACH": 13:07 → "FÜNF NACH EINS" + ●● Denkweise: "5 NACH + 2 Punkte = 7 Minuten nach" Berechnung: 5 + 2 = 7 Minuten nach 13:00 → 13:07

Der Mensch addiert die Punkte zur Basis-Anzeige. Menschliche Erwartung bei "VOR": 13:53 → "ZEHN VOR ZWEI" + ●●● Denkweise: "10 VOR - 3 Punkte = 7 Minuten vor" Berechnung: 10 - 3 = 7 Minuten vor 14:00 → 13:53

Der Mensch subtrahiert die Punkte von der Basis-Anzeige.

Falsche Implementierung (mathematisch korrekt, aber kontraintuitiv)

13:53 → "ZEHN VOR ZWEI" + ●● (invertiert) Denkweise: "10 VOR - 2 Punkte = 8 Minuten vor" Berechnung: 10 - 2 = 8 Minuten vor 14:00 → 13:52 ≠ 13:53!

Menschliche Erwartung bei "BALD": 13:58 → "BALD ZWEI" + ●● Denkweise: "BALD bedeutet gleich → noch 2 Minuten fehlen" Berechnung: 14:00 - 2 Minuten = 13:58

Der Mensch interpretiert die Punkte als fehlende Zeit bis zum Ereignis. Zwei-Modi-System für Anzeigepunkte Die 4 LED-Punkte zeigen Minuten zwischen 5-Minuten-Schritten an.

Problem: Wie zeigt man Zwischenwerte konsistent mit menschlicher Intuition?

Unterscheidung der beiden Modi

LEDs werden von links nach rechts angezeigt Die Anzahl wird zur angezeigten Zeit addiert Tritt auf bei: positivem Offset (tatsächliche Zeit > angezeigte Zeit)

  • Bedeutung: "Minuten, die zur angezeigten Zeit addiert werden müssen"

Regressive Punkte (von rechts, subtrahieren)

LEDs werden von rechts nach links angezeigt Die Anzahl wird von der angezeigten Zeit subtrahiert Tritt auf bei: negativem Offset (tatsächliche Zeit < angezeigte Zeit)

  • Bedeutung: "Minuten, die von der angezeigten Zeit subtrahiert werden müssen"

Berechnungslogik Grundprinzip: Die LED-Richtung und -Anzahl werden durch den Offset zwischen angezeigter und tatsächlicher Zeit bestimmt.

Berechnung

signedOffset = actualMinute - displayedMinute; remainder = Math.abs(signedOffset); direction = signedOffset < 0 ? "rechts" : "links";

  • 13:07 → "FÜNF NACH EINS" + ●● (von links)

  • Angezeigt: FÜNF NACH = 13:05, Offset: +2

  • Interpretation: 5 NACH + 2 = 7 Minuten nach 13:00

  • 13:31 → "NACH HALB ZWEI" + ● (von links)

  • Angezeigt: HALB = 13:30, Offset: +1

  • Interpretation: HALB + 1 = 13:31

  • 13:33 → "NACH HALB ZWEI" + ●●● (von links)

  • Angezeigt: HALB = 13:30, Offset: +3

  • Interpretation: HALB + 3 = 13:33

Beispiele Subtrahieren (negative Offsets, LEDs von rechts)

  • 10:53 → "FÜNF VOR ELF" + ●● (von rechts)

  • Angezeigt: FÜNF VOR = :55, Offset: -2

  • Interpretation: 55 - 2 = 53

Gemischte Beispiele (VOR kann beide Richtungen haben!)

  • 03:51 → "ZEHN VOR VIER" + ● (von links, positiver Offset!)

  • Angezeigt: ZEHN VOR = :50, Offset: +1

  • Interpretation: 50 + 1 = 51

Beispiele mit BALD/FAST (negative Offsets)

13:58 → "BALD ZWEI" + ●● (von rechts)

  • Angezeigt: BALD ZWEI = :60 (volle Stunde)

  • Offset: :58 - :60 = -2

  • Interpretation: 60 - 2 = 58 (noch 2 Minuten bis 14:00)

06:27 → "BALD HALB SIEBEN" + ●●● (von rechts)

  • Angezeigt: BALD HALB = :30

  • Offset: :27 - :30 = -3

  • Interpretation: 30 - 3 = 27 (noch 3 Minuten bis HALB)

14:04 → "BALD FÜNF NACH ZWEI" + ● (von rechts)

  • Angezeigt: FÜNF NACH = :05

  • Offset: :04 - :05 = -1

  • Interpretation: 5 - 1 = 4 (noch 1 Minute bis FÜNF NACH)

Wichtig: Die Richtung hängt vom Offset ab, nicht von den Schlüsselwörtern!

01:02 → "KURZ NACH EINS" + ●● (von links!)

  • Angezeigt: NACH = :00 (volle Stunde)

  • Offset: :02 - :00 = +2 (positiv!)

  • Interpretation: 0 + 2 = 2 (2 Minuten nach der vollen Stunde)

Logik-Implementierung // 1. Berechne die angezeigte Minute basierend auf den Wörtern const displayedMinute = calculateDisplayedMinute(wordsToLight);

// 2. Berechne Offset mit Vorzeichen const signedOffset = actualMinute - displayedMinute; const remainder = Math.abs(signedOffset);

// 3. LED-Richtung: positiv = links, negativ = rechts const isInvertedDisplay = signedOffset < 0;

// 4. LEDs anzeigen for(let i = 0; i < remainder; i++) { const dotIndex = isInvertedDisplay ? (3 - i) : i; // rechts → links oder links → rechts if(dots[dotIndex]) dots[dotIndex].classList.add('lit'); }

Die Funktion calculateDisplayedMinute() berücksichtigt

  • HALB-basierte Kombinationen: "FÜNF VOR HALB" = :25, "HALB" = :30, "FÜNF NACH HALB" = :35

  • Minutenmarker: "FÜNF NACH" = :05, "ZEHN VOR" = :50, "VIERTEL NACH" = :15

  • BALD/FAST ohne Marker: "BALD [STUNDE]" = :60 (volle Stunde)

  • Reine Präpositionen: "NACH" = :00, "VOR" = :60

Wichtige Regel: Die LED-Richtung hängt vom Offset zwischen angezeigter und tatsächlicher Zeit ab! Die Entscheidung, ob LEDs von links oder rechts angezeigt werden, wird durch den Offset zur angezeigten Zeit bestimmt:

Von rechts (subtrahieren) - Negative Offsets

"BALD HALB SIEBEN" (06:27)

  • Angezeigt: BALD HALB = :30

  • Offset: 27 - 30 = -3 (negativ!)

  • LEDs: ●●● von rechts

  • Operation: 30 - 3 = 27 ✓

"FÜNF VOR ELF" (10:53)

  • Angezeigt: FÜNF VOR = :55

  • Offset: 53 - 55 = -2 (negativ!)

  • LEDs: ●● von rechts

  • Operation: 55 - 2 = 53 ✓

"KURZ NACH EINS" (01:02)

  • Angezeigt: NACH = :00

  • Offset: 02 - 00 = +2 (positiv!)

  • LEDs: ●● von links

  • Operation: 0 + 2 = 2 ✓

"FÜNF NACH ZWEI" (14:07)

  • Angezeigt: FÜNF NACH = :05

  • Offset: 07 - 05 = +2 (positiv!)

  • LEDs: ●● von links

  • Operation: 5 + 2 = 7 ✓

"ZEHN VOR VIER" (03:51)

  • Angezeigt: ZEHN VOR = :50

  • Offset: 51 - 50 = +1 (positiv!)

  • LEDs: ● von links

  • Operation: 50 + 1 = 51 ✓

Spezialfall: Warum kein "KURZ FÜNF VOR"?

5-Minuten-Regel und natürliche Sprache

Problem: Bei 10:53 ohne BALD/FAST - welche Anzeige ist korrekt?

Falsche Ansätze

❌ Variante A: "ZEHN VOR ELF" + 3 LEDs von links

  • Berechnung: 50 + 3 = 53 ✓ (mathematisch korrekt)
  • Problem: Verstößt gegen die 5-Minuten-Regel
  • :53 ist näher an :55 (2 Min) als an :50 (3 Min)
  • LEDs von links bei VOR ist visuell inkonsistent ❌ Variante B: "KURZ FÜNF VOR ELF"
  • Sprachlich unnatürlich im Deutschen
  • Niemand sagt "ES IST KURZ FÜNF VOR ELF"
  • KURZ funktioniert nur mit direkten Zeitmarken: "KURZ VOR HALB", "KURZ NACH EINS" ✓ Korrekte Lösung: "FÜNF VOR ELF" + 2 LEDs von rechts
  • Angezeigt: FÜNF VOR = :55
  • Offset: 53 - 55 = -2 (negativ)
  • Berechnung: 55 - 2 = 53 ✓
  • LEDs von rechts (negativer Offset) ✓
  • Sprachlich natürlich ✓

Weitere Beispiele mit dieser Logik

10:58 → "VOR ELF" + 2 LEDs von rechts (60 - 2 = 58)

  • Nicht "FÜNF VOR ELF" (wäre 55 - 3 = 52 ❌)

  • :58 ist näher an :00 (2 Min) als an :55 (3 Min)

10:58 mit BALD → "BALD ELF" + 2 LEDs von rechts

10:58 mit FAST → "FAST ELF" + 2 LEDs von rechts 10:58 mit KURZ → "KURZ VOR ELF" + 2 LEDs von rechts

Lernziel: Kontext-abhängige Berechnung, User Experience Design, menschenzentrierte Algorithmik, natürliche Sprachlogik

Test-Driven Development Systematische Test-Strategie Kategorien

Äquivalenzklassen-Tests

  • Volle Stunden (X:00)

  • 5-Minuten-Schritte (X:05, X:10, X:15, ...)

  • Zwischenwerte (X:01-X:04, X:06-X:09, ...)

Grenzwert-Tests

  • Mitternacht (00:00)

  • Mittag (12:00)

  • Tagesübergang (23:59 → 00:00)

Spezialfall-Tests

  • Minute 04: "BALD FÜNF NACH"

  • Minute 29: FAST-Priorität

  • Minute 45-49: DREIVIERTEL vs. VIERTEL VOR

  • 01:00: "ES IST EIN UHR" (wenn UHR als letztes Wort) vs. "ES IST EINS" (wenn UHR fehlt/nicht am Ende)

Test-Beispiele (Minute 29 - Lernfall) Testziel: Prioritäts-Logik verstehen

Variante | KURZ | FAST | BALD | Erwartetes Ergebnis | Begründung |

kfb | ✗ | ✗ | ✗ | "VOR HALB" | Keine Modifikatoren |

kfB | ✗ | ✗ | ✓ | "BALD HALB" | BALD vorhanden |

kFb | ✗ | ✓ | ✗ | "FAST HALB" | FAST vorhanden |

kFB | ✗ | ✓ | ✓ | "FAST HALB" | FAST > BALD bei m=29 |

Kfb | ✓ | ✗ | ✗ | "KURZ VOR HALB" | KURZ vorhanden |

KfB | ✓ | ✗ | ✓ | "BALD HALB" | BALD > KURZ |

KFb | ✓ | ✓ | ✗ | "FAST HALB" | FAST > KURZ |

KFB | ✓ | ✓ | ✓ | "FAST HALB" | FAST hat Priorität |

Code-Implementierung

if(minute === 29) { if(hat_FAST) return [..., "FAST", "HALB", ...]; else if(hat_KURZ) return [..., "KURZ", "VOR", "HALB", ...]; else if(hat_BALD) return [..., "BALD", "HALB", ...]; else return [..., "VOR", "HALB", ...]; }

Automatisierte Tests // Unit Test Framework describe('Zeitberechnung', () => { test('13:00 sollte "EIN UHR" ergeben (wenn UHR am Ende)', () => { const patternMitUhr = "ESIST...EIN...UHR___"; // UHR als letztes Wort expect(berechneZeit(13, 0, patternMitUhr)).toEqual(["ES", "IST", "EIN", "UHR"]); });

test('13:00 sollte "EINS" ergeben (wenn UHR fehlt)', () => { const patternOhneUhr = "ESIST...EINS...NACHT"; // Kein UHR am Ende expect(berechneZeit(13, 0, patternOhneUhr)).toEqual(["ES", "IST", "EINS"]); });

test('13:29 mit FAST sollte "FAST HALB ZWEI" ergeben', () => { const pattern = "...FAST...HALB..."; expect(berechneZeit(13, 29, pattern)).toContain("FAST"); }); });

Validierung und Qualitätssicherung Mehrschichtige Validierung Ebene 1: Strukturvalidierung Prüfung: Sind alle erforderlichen Komponenten vorhanden? function validiereStruktur(layout) { const erforderlich = ["ES", "IST", "HALB", "UHR", "VOR", "NACH"]; const fehlt = erforderlich.filter(wort => !layout.includes(wort));

if(fehlt.length > 0) { return {gültig: false, fehler: Fehlende Wörter: ${fehlt}}; } return {gültig: true}; }

Ebene 2: Nachbarschafts-Validierung Prüfung: Gibt es identische benachbarte Buchstaben? function prüfeNachbarn(raster, zeilen=10, spalten=11) { for(let z = 0; z < zeilen; z++) { for(let s = 0; s < spalten; s++) { const index = z * spalten + s; const zeichen = raster[index];

// Horizontal if(s < spalten - 1 && zeichen === raster[index + 1]) { return {fehler: Dopplung bei Position ${index}}; }

// Vertikal if(z < zeilen - 1 && zeichen === raster[index + spalten]) { return {fehler: Dopplung bei Position ${index}}; } } } return {gültig: true}; }

Ebene 3: Schutzrechts-Compliance Prüfung: Ist das Layout identisch mit geschützten Designs? function prüfeSchutzrechte(layout) { const geschützteLayouts = [ "ESKISTAFÜNFZEHNZWANZIG...", // Beispiel geschütztes Design // Weitere geschützte Varianten ];

for(const geschützt of geschützteLayouts) { if(vergleicheLayouts(layout, geschützt)) { return { gültig: false, warnung: "Layout ist identisch mit geschütztem Design!", hinweis: "Bitte eigenes Design entwickeln." }; } } return {gültig: true}; }

Qualitätsmetriken

Lesbarkeit

  • Durchschnittliche Anzahl beleuchteter Buchstaben

  • Minimale/Maximale Wortlänge

  • Gleichmäßige Verteilung

Effizienz

  • Anzahl ungenutzter Felder

  • Wiederverwendung von Buchstaben (z.B. FÜNF als Minute und Stunde)

Wartbarkeit

  • Konsistente Positionierung

  • Logische Gruppierung

  • Dokumentation im Code

Erweiterte Lernziele Informatik-Konzepte, die durch dieses Projekt vermittelt werden:

  1. Datenstrukturen
  • Arrays und Strings

  • 2D-Matrizen

  • Hash-Maps für Wort-Lookup

  1. Algorithmen
  • Modulo-Arithmetik

  • Range-Mapping

  • Prioritäts-Queues

  • Constraint-Satisfaction

  1. Software-Design
  • Separation of Concerns

  • Model-View-Controller Pattern

  • State Management

  1. User Interface Design
  • Drag-and-Drop Interaktion

  • Echtzeit-Feedback

  • Visuelle Validierung

  1. Qualitätssicherung
  • Unit Testing

  • Integration Testing

  • Validierung gegen Constraints

CAD-Tool-Funktionalität Editor-Features

Visuelle Gestaltung

  • Interaktives 11×10 Raster

  • Manuelle Buchstabeneingabe

  • Undo/Redo-Funktionalität

Wort-Palette mit Drag-&-Drop

Einleitung: ES, IST, WIR (Alternative zu ES), HABEN (Alternative zu IST)

  • Beispiel: "ES IST DREI UHR" oder "WIR HABEN DREI UHR"

Zeiteinheiten: FÜNF, ZEHN, VIERTEL, ZWANZIG (optional), HALB, DREIVIERTEL (optional) Präpositionen: VOR, NACH, KURZ (optional), BALD (optional), FAST (optional) Stunden: EINS, EIN, ZWEI, DREI, VIER, FÜNF, SECHS, SIEBEN, ACHT, NEUN, ZEHN, ELF, ZWÖLF Extras: NACHT, PAUSE, ZEIT, ALARM, RWD Eigener Text: Individueller Text bis 11 Zeichen Ende: UHR

Aufklappbare Gruppen

  • Jede Palette-Gruppe kann individuell eingeklappt werden

  • Klick auf Label (mit ▼-Symbol) klappt Gruppe ein/aus

  • Status wird in localStorage gespeichert und bleibt nach Reload erhalten

  • Standard: Alle Gruppen geöffnet

  • Spart Platz bei wenig genutzten Kategorien

Intelligente Durchstreichung verwendeter Wörter

  • Stunden: nur durchgestrichen, wenn HALB existiert UND Wort nach HALB steht

  • Zeiteinheiten/Präpositionen: nur durchgestrichen, wenn Wort vor HALB steht

  • HALB: durchgestrichen, wenn vorhanden

  • Andere Wörter: durchgestrichen, wenn im Grid vorhanden

Hover-Effekt auf durchgestrichenen Wörtern

  • Zeigt das Wort im Grid grün hervorgehoben

  • Gilt nur für bereits verwendete (durchgestrichene) Wörter

Simulation

  • Test-Szenarien (01:00-02:00, 23:00-00:05)

  • Echtzeit-Beleuchtungs-Vorschau

  • Punkt-Anzeige-Simulation

Live-Uhrzeit-Modus (REALTIME)

  • Automatische Aktualisierung jede Sekunde

  • Textausgabe wird ausgeblendet (nur visuelle Anzeige aktiv)

  • Keyboard-Shortcuts: Pfeiltasten ← und →

  • Automatische Deaktivierung am Anfang/Ende der Liste

  • Deaktiviert bei REALTIME und CUSTOM-Modus

  • Zeigt die beleuchteten Wörter in Textform an

  • Feste Breite (berechnet beim Laden basierend auf maximaler Textlänge)

  • Mittige Positionierung innerhalb der Simulator-Box

  • Wird automatisch bei REALTIME-Modus ausgeblendet

Validierung

  • Automatische Struktur-Prüfung

  • Duplikat-Warnung

  • Schutzrechts-Check

  • Export-Freigabe

Vorschläge und Hilfen

  • Vorschlags-Funktion mit vorgefertigten Layouts

  • Zufälliges Füllen leerer Felder (unter Beachtung der Nachbarschaftsregeln)

Automatische Vorschlagsnummer-Anzeige

  • Button-Text ändert sich zu "Vorschlag (11)" wenn aktuelle Darstellung mit einem Vorschlag übereinstimmt

  • Erscheint nur wenn das Grid sinnvollen Inhalt hat (mindestens 10 Zeichen außer Füllzeichen)

  • Erscheint automatisch im Button-Text in Klammern (1, 2, 3, etc.)

  • Ignoriert Füllzeichen ('_') beim Vergleich

  • Button ist für 2-stellige Nummern vorformatiert (min-width: 145px)

Export

  • Pattern-String (110 Zeichen)

  • 3D-STL für Prototyping

  • Dokumentation (Markdown)

Ausblick und Erweiterungsmöglichkeiten Hardware-Erweiterungen Die universelle Platine kann für weitere Projekte genutzt werden:

1. Spiele-Konsole

  • Snake-Implementierung

  • Tetris-Variante

  • Reaktionsspiele

2. Daten-Visualisierung

  • Audio-Spektrum-Analyzer

  • Temperatur-Heatmap

  • Netzwerk-Aktivität

3. IoT-Integration

  • WLAN-Modul für Wetteranzeige

  • MQTT für Smart-Home-Status

  • API-Anbindung für Social-Media

Software-Erweiterungen

1. Multi-Language Support

  • Englische Zeitangaben

  • Französische Varianten

  • Andere Sprachen

2. Animations-Engine

  • Sanfte Übergänge

  • Lauftext-Modus

  • Effekte

3. KI-Integration

  • Automatische Layout-Optimierung

  • Genetische Algorithmen für beste Platzierung

  • Machine Learning für Nutzer-Präferenzen

Zusammenfassung

Kernkompetenzen, die erlernt werden: Algorithmisches Denken

  • Problemzerlegung

  • Abstrahierung

  • Mustererkennung

Software-Engineering

  • Design-Patterns

  • Testing-Strategien

  • Validierung

Mathematik/Logik

  • Modulo-Arithmetik

  • Constraint-Satisfaction

  • Boolean Logic

User Experience

  • Interface-Design

  • Feedback-Mechanismen

  • Visuelles Design

Pädagogischer Wert Dieses Projekt verbindet:

  • Theorie (Algorithmen, Datenstrukturen)
  • Praxis (Implementierung, Testing)
  • Kreativität (Layout-Design, Varianten)
  • Problemlösung (Constraints, Optimierung) Es eignet sich für:
  • Informatik-Unterricht (Sekundarstufe II, Hochschule)
  • Maker-Spaces und Coding-Clubs
  • ‍ Lehrerfortbildung
  • Projektwochen und Hackathons

Schutzrechtliche Situation (Stand 2025)

Fortschritt89%

Kommt als nächstes:

Schutzrechtliche Situation (Stand 2025)