feat(VocabLessonView): enhance review lesson logic and vocabulary handling
All checks were successful
Deploy to production / deploy (push) Successful in 4m28s

- Added logic to adjust vocabulary blending and switching conditions based on lesson type and didactic mode, improving the learning experience during review lessons.
- Implemented dynamic thresholds for switching between multiple choice and typing modes based on success rates and lesson context.
- Enhanced vocabulary source selection to incorporate a review share, optimizing the question pool for better engagement during typing sessions.
This commit is contained in:
Torsten Schulz (local)
2026-04-17 14:37:40 +02:00
parent b3346d4cac
commit f93a0f8b35

View File

@@ -1156,10 +1156,52 @@ export default {
if (!this.hasPreviousVocab) {
return 0;
}
const lessonType = String(this.lesson?.lessonType || '').toLowerCase();
const didacticMode = String(this.lessonPedagogy?.didacticMode || '').toLowerCase();
const isReviewLesson = ['review', 'vocab_review'].includes(lessonType)
|| ['review', 'vocab_review', 'intensive_review'].includes(didacticMode);
if (isReviewLesson) {
// In Wiederholungslektionen soll altes Material frueher und staerker einfliesen.
// Start: ~35%, Ramp-up bis max ~75%.
const blendStart = Math.max(2, Math.ceil(this.trainerNewFocusTarget * 0.2));
const rampWindow = Math.max(6, Math.ceil(this.trainerNewFocusTarget * 0.5));
const progressPastBlendStart = Math.max(0, this.vocabTrainerCurrentAttempts - blendStart);
const normalizedRamp = Math.min(1, progressPastBlendStart / rampWindow);
return Math.min(0.75, 0.35 + (normalizedRamp * 0.4));
}
const progressPastBlendStart = Math.max(0, this.vocabTrainerCurrentAttempts - this.trainerReviewBlendStart);
const normalizedRamp = Math.min(1, progressPastBlendStart / this.trainerReviewRampWindow);
return Math.min(0.55, normalizedRamp * 0.55);
},
typingCurrentLessonShare() {
if (!this.hasPreviousVocab) {
return 1;
}
const lessonType = String(this.lesson?.lessonType || '').toLowerCase();
const didacticMode = String(this.lessonPedagogy?.didacticMode || '').toLowerCase();
const isReviewLesson = ['review', 'vocab_review'].includes(lessonType)
|| ['review', 'vocab_review', 'intensive_review'].includes(didacticMode);
if (isReviewLesson) {
return Math.max(0.25, 1 - this.currentReviewShare);
}
// Normale Lektion: Progressives Streuen im Typing-Modus
// Start 100% aktuelle Lektion -> dann 90% -> später 50%.
const startRampAt = Math.max(3, Math.ceil(this.trainerNewFocusTarget * 0.3));
const midRampAt = Math.max(startRampAt + 1, Math.ceil(this.trainerNewFocusTarget * 0.6));
const attempts = Math.max(0, Number(this.vocabTrainerCurrentAttempts) || 0);
if (attempts < startRampAt) {
return 1;
}
if (attempts < midRampAt) {
return 0.9;
}
return 0.5;
},
canAccessExercises() {
if (!this.hasExercises) return false;
if (this.exerciseNeedsReinforcement) return false;
@@ -3349,10 +3391,19 @@ export default {
this.vocabTrainerPhase = this.hasPreviousVocab && this.currentReviewShare > 0 ? 'mixed' : 'current';
if (this.vocabTrainerMode === 'multiple_choice' && this.vocabTrainerTotalAttempts >= this.trainerExerciseUnlockAttempts) {
const lessonType = String(this.lesson?.lessonType || '').toLowerCase();
const didacticMode = String(this.lessonPedagogy?.didacticMode || '').toLowerCase();
const isReviewLesson = ['review', 'vocab_review'].includes(lessonType)
|| ['review', 'vocab_review', 'intensive_review'].includes(didacticMode);
const switchAfterAttempts = isReviewLesson
? Math.max(8, Math.ceil(this.trainerExerciseUnlockAttempts * 0.35))
: this.trainerExerciseUnlockAttempts;
const requiredSuccessRate = isReviewLesson ? 75 : 80;
if (this.vocabTrainerMode === 'multiple_choice' && this.vocabTrainerTotalAttempts >= switchAfterAttempts) {
const successRate = (this.vocabTrainerCorrect / this.vocabTrainerTotalAttempts) * 100;
if (successRate >= 80) {
debugLog('[VocabLessonView] Mixed-Phase abgeschlossen, wechsle zu Typing');
if (successRate >= requiredSuccessRate) {
debugLog('[VocabLessonView] Wechsle zu Typing (Abruf staerken)');
this.vocabTrainerMode = 'typing';
this.vocabTrainerAutoSwitchedToTyping = true;
this.vocabTrainerPool = [...this.trainableLessonVocab, ...this.vocabTrainerMixedPool];
@@ -3508,9 +3559,13 @@ export default {
}
if (!dueRepeatVocab && this.vocabTrainerMode === 'typing') {
sourcePool = this.vocabTrainerPool;
if (this.vocabTrainerMixedPool.length > 0 && Math.random() < 0.35) {
const typingReviewShare = Math.max(0, 1 - this.typingCurrentLessonShare);
if (this.vocabTrainerMixedPool.length > 0 && typingReviewShare > 0 && Math.random() < typingReviewShare) {
sourcePool = this.vocabTrainerMixedPool;
questionSource = 'review';
} else {
sourcePool = this.trainableLessonVocab;
questionSource = 'current';
}
} else if (!dueRepeatVocab && this.vocabTrainerMixedPool.length > 0 && this.currentReviewShare > 0 && Math.random() < this.currentReviewShare) {
sourcePool = this.vocabTrainerMixedPool;