feat: Automatische Fokusvergabe, automatischer Textwechsel und WPM-Anzeige implementiert
Co-authored-by: aider (ollama_chat/qwen3-coder:30b) <aider@aider.chat>
This commit is contained in:
parent
9f44991857
commit
fd134d3fb4
3 changed files with 42 additions and 1 deletions
12
app.py
12
app.py
|
|
@ -99,13 +99,23 @@ def calculate_statistics(user_input, current_text):
|
|||
# Dauer pro Zeichen (in Sekunden)
|
||||
duration_per_char = 1.0 / (typing_speed / 60) if typing_speed > 0 else 0
|
||||
|
||||
# Berechne Wörter pro Minute (WPM)
|
||||
# Annahme: 1 Wort = 5 Zeichen (durchschnittlich)
|
||||
words_per_minute = 0
|
||||
if total_chars > 0 and duration_per_char > 0:
|
||||
# Zeit in Minuten berechnen
|
||||
time_in_minutes = (total_chars * duration_per_char) / 60
|
||||
if time_in_minutes > 0:
|
||||
words_per_minute = total_chars / 5 / time_in_minutes
|
||||
|
||||
return {
|
||||
'correct_chars': correct_chars,
|
||||
'incorrect_chars': incorrect_chars,
|
||||
'total_chars': total_chars,
|
||||
'error_rate': round(error_rate, 2),
|
||||
'typing_speed': typing_speed,
|
||||
'duration_per_char': round(duration_per_char, 3)
|
||||
'duration_per_char': round(duration_per_char, 3),
|
||||
'words_per_minute': round(words_per_minute, 2)
|
||||
}
|
||||
|
||||
@app.route('/next_text', methods=['POST'])
|
||||
|
|
|
|||
|
|
@ -11,14 +11,39 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
const correctElement = document.getElementById('correct');
|
||||
const incorrectElement = document.getElementById('incorrect');
|
||||
const totalElement = document.getElementById('total');
|
||||
const wpmElement = document.getElementById('wpm');
|
||||
|
||||
// Aktuelle Textdaten
|
||||
let currentText = document.querySelector('#target-text').textContent;
|
||||
|
||||
// Fokus auf das Eingabefeld setzen
|
||||
userInput.focus();
|
||||
|
||||
// Aktualisiere die Statistik bei Eingabe
|
||||
userInput.addEventListener('input', function() {
|
||||
const userValue = this.value;
|
||||
updateStatistics(userValue, currentText);
|
||||
|
||||
// Wenn der Text vollständig getippt wurde, automatisch zur nächsten Zeile
|
||||
if (userValue === currentText) {
|
||||
setTimeout(function() {
|
||||
fetch('/next_text', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
}
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
currentText = data.text;
|
||||
document.getElementById('target-text').textContent = currentText;
|
||||
userInput.value = '';
|
||||
userInput.focus(); // Fokus zurück auf Eingabefeld
|
||||
updateStatistics('', currentText);
|
||||
})
|
||||
.catch(error => console.error('Fehler:', error));
|
||||
}, 100); // Kurze Verzögerung für bessere Benutzererfahrung
|
||||
}
|
||||
});
|
||||
|
||||
// Nächste Zeile Button
|
||||
|
|
@ -34,6 +59,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
currentText = data.text;
|
||||
document.getElementById('target-text').textContent = currentText;
|
||||
userInput.value = '';
|
||||
userInput.focus(); // Fokus zurück auf Eingabefeld
|
||||
updateStatistics('', currentText);
|
||||
})
|
||||
.catch(error => console.error('Fehler:', error));
|
||||
|
|
@ -77,6 +103,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
correctElement.textContent = data.correct_chars;
|
||||
incorrectElement.textContent = data.incorrect_chars;
|
||||
totalElement.textContent = data.total_chars;
|
||||
wpmElement.textContent = data.words_per_minute;
|
||||
|
||||
// Aktualisiere die Textfarben
|
||||
updateTextHighlighting(userInput, currentText);
|
||||
|
|
|
|||
|
|
@ -55,6 +55,10 @@
|
|||
Fehlerquote
|
||||
<span id="error-rate" class="badge bg-danger rounded-pill">0%</span>
|
||||
</li>
|
||||
<li class="list-group-item d-flex justify-content-between align-items-center">
|
||||
Wörter pro Minute
|
||||
<span id="wpm" class="badge bg-info rounded-pill">0</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue