From 0cb5ca68b6acdeb5c3ac2ff38fc03dd2f9046576 Mon Sep 17 00:00:00 2001 From: jamulix Date: Mon, 27 Oct 2025 14:37:13 +0100 Subject: [PATCH] alembic verbessert, Javascript modularisiert --- CLAUDE.md | 38 +- JAVASCRIPT_MODULES.md | 371 +++++++++++++++++++ app.py | 65 +++- setup_database.py | 97 +++++ static/js/keyboard.js | 128 +++++++ static/js/main.js | 484 +++++++++++++++++++++++++ static/js/metronome.js | 210 +++++++++++ static/js/{script.js => script.js.old} | 0 static/js/session.js | 255 +++++++++++++ static/js/statistics.js | 115 ++++++ static/js/textDisplay.js | 219 +++++++++++ static/js/theme.js | 67 ++++ static/js/ui.js | 253 +++++++++++++ templates/index.html | 6 +- 14 files changed, 2296 insertions(+), 12 deletions(-) create mode 100644 JAVASCRIPT_MODULES.md create mode 100644 setup_database.py create mode 100644 static/js/keyboard.js create mode 100644 static/js/main.js create mode 100644 static/js/metronome.js rename static/js/{script.js => script.js.old} (100%) create mode 100644 static/js/session.js create mode 100644 static/js/statistics.js create mode 100644 static/js/textDisplay.js create mode 100644 static/js/theme.js create mode 100644 static/js/ui.js diff --git a/CLAUDE.md b/CLAUDE.md index 002514b..4c5565d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -29,7 +29,27 @@ The application runs on `http://localhost:5000` by default. ### Database Setup -The database is automatically initialized when the application starts for the first time. Tables are created via SQLAlchemy in `app.py` using `db.create_all()`. +**WICHTIG**: Die Anwendung verwendet Alembic für Datenbank-Migrationen. + +**Erste Installation**: +```bash +# Setup-Script ausführen (empfohlen) +python setup_database.py + +# ODER manuell: +alembic upgrade head +``` + +**Bei Schema-Änderungen**: +```bash +# Neue Migration erstellen +alembic revision --autogenerate -m "Beschreibung der Änderung" + +# Migration anwenden +alembic upgrade head +``` + +Siehe `MIGRATIONS.md` für detaillierte Informationen. ### Dependencies @@ -98,13 +118,27 @@ curl http://localhost:5000/debug ### Frontend Architecture +**Modular JavaScript (ES6 Modules)**: Das Frontend ist in separate Module aufgeteilt für bessere Wartbarkeit: + +- **`theme.js`**: Theme Management (Light/Dark Mode) +- **`metronome.js`**: Adaptive Metronome-Klasse und Audio-Player +- **`statistics.js`**: Statistik-Berechnungen und Anzeige +- **`textDisplay.js`**: Text-Rendering und Highlighting +- **`keyboard.js`**: Keyboard-Event-Handling +- **`session.js`**: Session Management und Fortschritt-Speicherung +- **`ui.js`**: UI-Interaktionen (Buttons, Modals, Toggles) +- **`main.js`**: Hauptorchestration und Initialisierung + **Theme System**: Light/Dark mode toggle using Bootstrap's `data-bs-theme` attribute, stored in localStorage. -**Adaptive Metronome** (`script.js`): +**Adaptive Metronome**: - Adjusts typing speed guidance based on user accuracy - Target accuracy: 96% (configurable) - Tracks last 50 keystrokes to calculate rolling accuracy - Speed increases when accuracy is high, decreases when low +- Implementiert in `metronome.js` mit zwei Klassen: + - `AdaptiveMetronome`: Geschwindigkeitsanpassungslogik + - `MetronomePlayer`: Audio-Wiedergabe und Timing **Visual Feedback**: - Green highlighting for correct characters diff --git a/JAVASCRIPT_MODULES.md b/JAVASCRIPT_MODULES.md new file mode 100644 index 0000000..0def2b3 --- /dev/null +++ b/JAVASCRIPT_MODULES.md @@ -0,0 +1,371 @@ +# JavaScript-Modulstruktur + +Dieses Dokument beschreibt die modularisierte JavaScript-Architektur des Typewriter Tutors. + +## Überblick + +Das Frontend wurde in separate ES6-Module aufgeteilt, um die Wartbarkeit, Testbarkeit und Lesbarkeit zu verbessern. Statt einer monolithischen `script.js` (1.122 Zeilen) gibt es nun 8 fokussierte Module. + +## Module + +### 1. `theme.js` - Theme Management + +**Verantwortlichkeit**: Verwaltung des Light/Dark-Modus + +**Klasse**: `ThemeManager` + +**Funktionen**: +- `initialize()` - Initialisiert Theme aus localStorage +- `toggle()` - Wechselt zwischen Light und Dark Mode +- `setTheme(theme)` - Setzt ein spezifisches Theme +- `setupEventListeners()` - Bindet Theme-Toggle-Button + +**Verwendung**: +```javascript +const themeManager = new ThemeManager(); +themeManager.initialize(); +themeManager.setupEventListeners(); +``` + +--- + +### 2. `metronome.js` - Adaptive Metronom-Logik + +**Verantwortlichkeit**: Intelligente Geschwindigkeitsanpassung und Audio-Wiedergabe + +**Klassen**: + +#### `AdaptiveMetronome` +Implementiert die 5-Regel-Geschwindigkeitsanpassung basierend auf Tipp-Genauigkeit. + +**Eigenschaften**: +- `speed` - Aktuelle Geschwindigkeit in BPM +- `accuracy_history` - Letzte 50 Tasteneingaben (1=korrekt, 0=falsch) +- `consecutive_correct` - Aufeinanderfolgende korrekte Zeichen +- `target_accuracy` - Zielgenauigkeit (Standard: 96%) + +**Methoden**: +- `process_keystroke(is_correct, difficulty)` - Verarbeitet Tastendruck und passt Geschwindigkeit an +- `_adjust_speed(difficulty)` - Interne Geschwindigkeitsanpassung + +**Anpassungsregeln**: +1. Streak-Bonus bei ≥15 korrekten Zeichen: +3% +2. Zu einfach (>95% Genauigkeit): +2% +3. Zu schwer (<85% Genauigkeit): -8% +4. Leicht unter Ziel (85-91%): -3% +5. Im Zielbereich (91-95%): +1% + +#### `MetronomePlayer` +Verwaltet die Audio-Wiedergabe und das Timing. + +**Methoden**: +- `start()` - Startet das Metronom +- `stop()` - Stoppt das Metronom +- `setBPM(bpm)` - Setzt BPM und startet neu +- `toggle()` - Schaltet Audio ein/aus +- `play()` - Spielt einen Beat + +**Verwendung**: +```javascript +const adaptive = new AdaptiveMetronome(); +const player = new MetronomePlayer(); + +// Bei jedem Tastendruck: +const newBPM = adaptive.process_keystroke(isCorrect); +player.setBPM(newBPM); +``` + +--- + +### 3. `statistics.js` - Statistik-Berechnungen + +**Verantwortlichkeit**: Berechnung und Anzeige von Tipp-Statistiken + +**Klasse**: `StatisticsManager` + +**Methoden**: +- `calculateStatistics(userInput, fullText, elapsedTime, totalKeyStrokes)` - Berechnet alle Metriken +- `updateDisplay(stats)` - Aktualisiert UI-Elemente +- `setSpeedDisplay(display)` - Setzt Anzeige-Modus ('zpm' oder 'wpm') +- `saveLessonStatistics(...)` - Speichert Statistiken auf Server + +**Berechnete Metriken**: +- `charsPerMinute` - Zeichen pro Minute +- `wpm` - Wörter pro Minute (Zeichen/5) +- `errorRate` - Fehlerrate in Prozent +- `correctKeyStrokes` - Anzahl korrekter Zeichen +- `incorrectKeyStrokes` - Anzahl falscher Zeichen + +--- + +### 4. `textDisplay.js` - Text-Rendering + +**Verantwortlichkeit**: Text-Darstellung, Highlighting und Scrollen + +**Klasse**: `TextDisplayManager` + +**Methoden**: +- `updateDisplay(userInput, currentCharIndex)` - Aktualisiert Textanzeige mit Highlighting +- `updateText(newText)` - Lädt neuen Text (z.B. neue Lektion) +- `highlightChar(char, type, isCursor, incorrectChar)` - Rendert einzelnes Zeichen +- `getCurrentLineIndex(charIndex)` - Berechnet Zeilennummer +- `resetScroll()` - Setzt Scroll-Position zurück +- `isLineComplete(lineIndex, userInput)` - Prüft ob Zeile komplett korrekt + +**Highlight-Typen**: +- `correct` - Grün für korrekte Zeichen +- `incorrect` - Rot für falsche Zeichen (mit orangefarbenem Overlay) +- `neutral` - Standard für noch nicht getippte Zeichen + +**Features**: +- Automatisches Scrollen zur aktuellen Zeile +- Sichtbarmachung von Leerzeichen (·), Tabs (→), Newlines (↵) +- Manuelles Scrollen wird erkannt und respektiert + +--- + +### 5. `keyboard.js` - Tastatur-Verwaltung + +**Verantwortlichkeit**: Tastatur-Events und ErrorLock-Funktionalität + +**Klasse**: `KeyboardHandler` + +**Methoden**: +- `handleKeyDown(event, state)` - Verarbeitet alle Tastatureingaben +- `setErrorLock(enabled)` - Aktiviert/deaktiviert ErrorLock +- `getCorrectPrefixLength(userInput, fullText)` - Berechnet korrekte Präfix-Länge +- `setupEventListeners()` - Richtet Fokus-Management ein + +**Unterstützte Tasten**: +- Zeichen-Eingabe +- `Backspace` - Löschen +- `ArrowLeft`/`ArrowRight` - Cursor-Bewegung +- `Enter` - Zeilenumbruch +- `Ctrl`/`Cmd` - Blockiert (Anti-Cheat) + +**ErrorLock**: +Wenn aktiviert, können nur Fehler an der Cursor-Position korrigiert werden. + +--- + +### 6. `session.js` - Session Management + +**Verantwortlichkeit**: Fortschritt-Tracking und Server-Kommunikation + +**Klasse**: `SessionManager` + +**Eigenschaften**: +- `lastStartTime` - Zeitpunkt des letzten Starts +- `totalElapsedTime` - Gesamte verstrichene Zeit +- `keyStrokeCount` - Anzahl aller Tasteneingaben +- `isPaused` - Pause-Status +- `currentLessonIndex` - Aktuelle Lektion + +**Methoden**: +- `initialize(initialState)` - Initialisiert aus Server-Daten +- `start()` / `pause()` / `resume()` - Zeit-Tracking +- `togglePause()` - Pause ein/aus +- `incrementKeystrokes()` - Erhöht Tastenzähler +- `reset()` - Zurücksetzen für neue Lektion +- `saveProgress(...)` - Speichert Fortschritt auf Server +- `nextLesson()` - Lädt nächste Lektion +- `setLesson(index)` - Lädt spezifische Lektion +- `endSession()` - Beendet Session +- `setupBeforeUnload(getSaveData)` - Speichert beim Schließen + +**Server-Endpunkte**: +- `POST /update_progress` - Fortschritt speichern +- `POST /next_text` - Nächste Lektion +- `POST /set_lesson` - Lektion wechseln +- `POST /end_session` - Session beenden + +--- + +### 7. `ui.js` - UI-Management + +**Verantwortlichkeit**: UI-Elemente, Buttons, Modals, Toggles + +**Klasse**: `UIManager` + +**Methoden**: +- `initialize()` - Initialisiert alle UI-Elemente +- Icon-Verwaltung: + - `toggleVolume(enabled)` - Volume-Icon + - `toggleLock(locked)` - Lock-Icon + - `togglePlayPause(isPaused)` - Play/Pause-Icon +- Anzeige-Updates: + - `updateLessonTitle(title)` - Aktualisiert Lektionstitel + - `updateLessonHighlight(index)` - Markiert aktuelle Lektion +- Dialoge: + - `alert(message)` - Alert-Dialog + - `confirm(message)` - Confirm-Dialog +- Modals und Links: + - `setupHelpModal()` - Help-Modal + - `setupSettingsLink()` - Settings-Navigation + - `setupStatisticsLink(callback)` - Statistics-Navigation +- Performance-Anzeige: + - `setupPerformanceToggle()` - Toggle für Statistik-Anzeige + - `setProgressStatsVisibility(visible)` - Zeigt/verbirgt Stats + +--- + +### 8. `main.js` - Hauptorchestration + +**Verantwortlichkeit**: Initialisierung und Koordination aller Module + +**Klasse**: `TypewriterApp` + +**Ablauf**: +1. Initialisierung aller Module +2. Laden von Konfiguration aus `window.*` Variablen +3. Setup von Event-Listenern +4. Start der Anwendung + +**Zentrale Methoden**: +- `initialize()` - Haupt-Initialisierung +- `initializeModules()` - Erstellt alle Module +- `setupEventListeners()` - Bindet alle Events +- `processKeystroke(key, isCorrect)` - Koordiniert Tastendruck-Verarbeitung +- `updateDisplay()` / `updateStatistics()` - Aktualisiert UI +- `completeLesson()` - Behandelt Lektions-Abschluss +- `nextLesson()` / `loadLesson(index)` - Lektions-Navigation + +**Event-Handling**: +```javascript +// Tastatur +document.addEventListener('keydown', (event) => { + keyboardHandler.handleKeyDown(event, state); +}); + +// Metronom-Toggle +volumeToggle.addEventListener('click', () => { + metronomePlayer.toggle(); + saveMetronomeSettings(); +}); + +// Play/Pause +playPauseToggle.addEventListener('click', () => { + sessionManager.togglePause(); + uiManager.togglePlayPause(isPaused); +}); +``` + +--- + +## Initialisierung + +**Template** (`index.html`): +```html + + + + + +``` + +**Ablauf**: +1. DOM lädt +2. `DOMContentLoaded` Event feuert +3. `TypewriterApp` wird instanziiert +4. `app.initialize()` wird aufgerufen +5. Alle Module werden initialisiert +6. Event-Listener werden gebunden +7. Anwendung ist bereit + +--- + +## Kommunikation zwischen Modulen + +Die Module kommunizieren über die zentrale `TypewriterApp`-Instanz: + +``` +User Input + ↓ +KeyboardHandler → TypewriterApp + ↓ ↓ + ├→ AdaptiveMetronome (Geschwindigkeit) + ├→ TextDisplayManager (Anzeige) + ├→ StatisticsManager (Metriken) + ├→ SessionManager (Speichern) + └→ UIManager (UI-Updates) +``` + +**Vorteile**: +- Klare Verantwortlichkeiten +- Lose Kopplung +- Einfaches Testing +- Wiederverwendbarkeit +- Bessere Wartbarkeit + +--- + +## Testing + +Jedes Modul kann isoliert getestet werden: + +**Backend-Tests**: `python -m unittest test_app -v` + +**Metronom-Tests**: `python -m unittest test_metronome_velocity -v` + +Die JavaScript-Module sind so strukturiert, dass sie leicht mit Jest oder ähnlichen Frameworks getestet werden können. + +--- + +## Migration von Alt zu Neu + +Die alte monolithische `script.js` wurde als `script.js.old` gesichert. + +**Hauptänderungen**: +1. **ES6-Module**: Alle Exports/Imports verwenden ES6-Syntax +2. **Klassen-basiert**: Alle Funktionalität in Klassen gekapselt +3. **Zentrale Orchestration**: `main.js` koordiniert alle Module +4. **Template-Änderung**: ` - + +