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:
- Bei :03 (2 Min vor :05): BALD dominiert, außer wenn nur FAST vorhanden ist
- Bei :09 (1 Min vor :10): FAST > BALD (kFB, KFB zeigen FAST)
- 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
Progressive Punkte (von links, addieren)
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";
Beispiele Addieren (positive Offsets, LEDs von 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 ✓
Von links (addieren) - Positive Offsets
"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:
- Datenstrukturen
-
Arrays und Strings
-
2D-Matrizen
-
Hash-Maps für Wort-Lookup
- Algorithmen
-
Modulo-Arithmetik
-
Range-Mapping
-
Prioritäts-Queues
-
Constraint-Satisfaction
- Software-Design
-
Separation of Concerns
-
Model-View-Controller Pattern
-
State Management
- User Interface Design
-
Drag-and-Drop Interaktion
-
Echtzeit-Feedback
-
Visuelle Validierung
- 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)
Navigationsknöpfe (← / →)
-
Keyboard-Shortcuts: Pfeiltasten ← und →
-
Automatische Deaktivierung am Anfang/Ende der Liste
-
Deaktiviert bei REALTIME und CUSTOM-Modus
Textausgabe als Footer
-
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)