-m 'Statistik überarbeitet'

This commit is contained in:
jamulix 2025-10-23 19:12:11 +02:00 committed by jamulix (aider)
commit cbe8d4a670
3 changed files with 90 additions and 45 deletions

View file

@ -104,6 +104,19 @@ Das Training umfasst 20 Lektionen:
4. Ihre Statistiken (WPM und Genauigkeit) werden in Echtzeit aktualisiert
5. Wechseln Sie zur nächsten Lektion oder beenden Sie die Sitzung
## Zeitmessung und Statistik
Die Zeitmessung beginnt mit dem ersten Tastendruck und läuft kontinuierlich bis zum Abschluss der Lektion. Folgende Metriken werden berechnet:
- **Tastaturanschläge**: Jeder Tastendruck wird gezählt (inklusive Backspace)
- **Korrekte Zeichen**: Zeichen, die exakt mit der Vorlage übereinstimmen
- **Falsche Zeichen**: Differenz zwischen Gesamtanschlägen und korrekten Zeichen
- **Zeichen pro Sekunde**: Korrekte Zeichen / verstrichene Zeit in Sekunden
- **Fehlerrate**: (Falsche Zeichen * 100) / Korrekte Zeichen
- **Wörter pro Minute (WPM)**: (Korrekte Zeichen / 5) / (verstrichene Zeit in Minuten)
Die Berechnung erfolgt über die gesamte Lektion hinweg und berücksichtigt alle Zeilen.
## Entwickler-Funktionen
- `/debug` - Debug-Informationen

View file

@ -44,11 +44,15 @@ document.addEventListener('DOMContentLoaded', function() {
const totalElement = document.getElementById('total');
const wpmElement = document.getElementById('wpm');
// Aktuelle Textdaten (verwende nur lines, entferne currentText)
// Aktuelle Textdaten
let lines = window.lines;
let currentLineIndex = window.currentLineIndex;
let startTime = null;
let timerInterval = null;
let completedLines = []; // Abgeschlossene Zeilen
let currentLineInput = ''; // Aktuelle Eingabe in der aktuellen Zeile
let fullText = lines.join('\n'); // Gesamter Text der Lektion
let keyStrokeCount = 0; // Zähler für alle Tastaturanschläge (inkl. Backspace)
// Zeige die erste Zeile an
updateLineDisplay();
@ -56,33 +60,43 @@ document.addEventListener('DOMContentLoaded', function() {
// Fokus auf das Eingabefeld setzen
userInput.focus();
// Starte die Zeitmessung beim ersten Tastendruck
// Starte die Zeitmessung beim ersten Tastendruck und zähle Tastaturanschläge
userInput.addEventListener('keydown', function(event) {
if (!startTime && event.key.length === 1) { // Nur Buchstaben, Zahlen, etc.
startTime = new Date();
// Zähle Tastaturanschläge für alle Tasten, die keine Steuertasten sind (inkl. Backspace)
// Beachte: event.key für Backspace ist 'Backspace'
if (event.key.length === 1 || event.key === 'Backspace') {
if (!startTime) {
startTime = new Date();
}
keyStrokeCount++;
// Aktualisiere die Statistik sofort, um die Änderung anzuzeigen
updateStatistics();
}
});
// Aktualisiere die Statistik bei jedem Tastendruck
// Aktualisiere die Statistik bei jedem Tastendruck (keyup)
userInput.addEventListener('keyup', function() {
const userValue = this.value;
currentLineInput = this.value;
const currentLine = lines[currentLineIndex];
updateStatistics(userValue, currentLine);
// Wenn die Zeile vollständig korrekt getippt wurde, zur nächsten Zeile
if (userValue === currentLine) {
if (currentLineInput === currentLine) {
if (currentLineIndex < lines.length - 1) {
completedLines.push(currentLineInput);
currentLineInput = '';
this.value = '';
currentLineIndex++;
userInput.value = '';
updateLineDisplay();
updateStatistics('', lines[currentLineIndex]);
} else {
// Lektion beendet - Statistik speichern
// Letzte Zeile abgeschlossen
completedLines.push(currentLineInput);
currentLineInput = '';
this.value = '';
alert('Lektion beendet!');
// Setze zurück für nächste Lektion?
// Oder automatisch zur nächsten Lektion?
}
}
updateStatistics();
});
// Funktion zum Aktualisieren der Lektionsmarkierung
@ -124,14 +138,18 @@ document.addEventListener('DOMContentLoaded', function() {
if (data.error) {
alert('Fehler: ' + data.error);
} else {
// Verwende nur lines, entferne currentText
lines = data.text.split('\n');
currentLineIndex = 0;
completedLines = [];
currentLineInput = '';
fullText = lines.join('\n');
startTime = null;
keyStrokeCount = 0; // Zurücksetzen des Tastaturanschlagszählers
updateLineDisplay();
document.getElementById('lesson-title').textContent = data.title;
userInput.value = '';
userInput.focus();
updateStatistics('', lines[currentLineIndex]);
updateStatistics();
// Aktualisiere die Markierung der aktuellen Lektion
updateLessonHighlight(lessonIndex);
}
@ -157,15 +175,19 @@ document.addEventListener('DOMContentLoaded', function() {
})
.then(response => response.json())
.then(data => {
// Verwende nur lines, entferne currentText
lines = data.text.split('\n');
currentLineIndex = 0;
completedLines = [];
currentLineInput = '';
fullText = lines.join('\n');
startTime = null;
keyStrokeCount = 0; // Zurücksetzen des Tastaturanschlagszählers
updateLineDisplay();
// Aktualisiere den Lektionstitel
document.getElementById('lesson-title').textContent = data.title;
userInput.value = '';
userInput.focus(); // Fokus zurück auf Eingabefeld
updateStatistics('', lines[currentLineIndex]);
updateStatistics();
// Aktualisiere die Markierung der aktuellen Lektion
updateLessonHighlight(data.index);
})
@ -190,7 +212,7 @@ document.addEventListener('DOMContentLoaded', function() {
});
// Statistik aktualisieren
function updateStatistics(userInput, currentText) {
function updateStatistics() {
// Berechne verstrichene Zeit nur wenn der Benutzer tippt
let elapsedTime = 0;
if (startTime) {
@ -198,32 +220,42 @@ document.addEventListener('DOMContentLoaded', function() {
elapsedTime = (now - startTime) / 1000; // in Sekunden
}
// Sende Daten an den Server nur wenn der Benutzer tippt oder klickt
fetch('/update_progress', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
user_input: userInput,
current_text: currentText,
elapsed_time: elapsedTime
})
})
.then(response => response.json())
.then(data => {
// Aktualisiere die Anzeige
speedElement.textContent = data.typing_speed;
errorRateElement.textContent = data.error_rate.toFixed(1);
correctElement.textContent = data.correct_chars;
incorrectElement.textContent = data.incorrect_chars;
totalElement.textContent = data.total_chars;
wpmElement.textContent = Math.round(data.words_per_minute);
// Aktualisiere die Textfarben
updateTextHighlighting(userInput, currentText);
})
.catch(error => console.error('Fehler:', error));
// Berechne die gesamte Benutzereingabe
let fullUserInput = completedLines.join('\n');
if (completedLines.length > 0) {
fullUserInput += '\n' + currentLineInput;
} else {
fullUserInput = currentLineInput;
}
// Berechne Statistiken
let totalKeyStrokes = keyStrokeCount; // Verwende jetzt die Anzahl aller Tastaturanschläge (inkl. Backspace)
let correctKeyStrokes = 0;
// Zähle korrekte Zeichen
for (let i = 0; i < fullUserInput.length; i++) {
if (i < fullText.length && fullUserInput[i] === fullText[i]) {
correctKeyStrokes++;
} else {
break;
}
}
let incorrectKeyStrokes = totalKeyStrokes - correctKeyStrokes;
let charsPerSecond = elapsedTime > 0 ? correctKeyStrokes / elapsedTime : 0;
let errorRate = correctKeyStrokes > 0 ? (incorrectKeyStrokes * 100.0) / correctKeyStrokes : 0;
let wpm = elapsedTime > 0 ? (correctKeyStrokes / 5) / (elapsedTime / 60) : 0;
// Aktualisiere die Anzeige
speedElement.textContent = charsPerSecond.toFixed(1);
errorRateElement.textContent = errorRate.toFixed(1);
correctElement.textContent = correctKeyStrokes;
incorrectElement.textContent = incorrectKeyStrokes;
totalElement.textContent = totalKeyStrokes;
wpmElement.textContent = Math.round(wpm);
// Aktualisiere die Textfarben
updateTextHighlighting(currentLineInput, lines[currentLineIndex]);
}
// Text hervorheben

View file

@ -101,7 +101,7 @@
<span id="incorrect" class="badge bg-danger rounded-pill">0</span>
</li>
<li class="list-group-item d-flex justify-content-between align-items-center">
Gesamtzeichen
Tastaturanschläge
<span id="total" class="badge bg-secondary rounded-pill">0</span>
</li>
</ul>