diff --git a/backend/services/vocabService.js b/backend/services/vocabService.js index 7cddebd..2227d4f 100644 --- a/backend/services/vocabService.js +++ b/backend/services/vocabService.js @@ -2900,12 +2900,45 @@ export default class VocabService { }); const isWeeklyReview = plainLesson.lessonType === 'weekly_review'; + const isCheckpoint = (String(plainLesson.didacticMode || '').toLowerCase() === 'checkpoint') + || (/checkpoint/i.test(String(plainLesson.title || '')) && plainLesson.weekNumber != null); // Lade Vokabeln aus vorherigen Lektionen (für Wiederholung UND für gemischten Vokabeltrainer) - if (plainLesson.lessonNumber > 1 && !isWeeklyReview) { + if (plainLesson.lessonNumber > 1 && !isWeeklyReview && !isCheckpoint) { plainLesson.previousLessonExercises = await this._getReviewVocabExercises(plainLesson.courseId, plainLesson.lessonNumber); } - if (isWeeklyReview) { + + // Checkpoint-Lektionen: kleine Stichprobe aus den Wochen-Übungen (ca. 10-30%) + if (isCheckpoint) { + const weeklyLessons = await this._getReviewLessons( + plainLesson.courseId, + plainLesson.lessonNumber, + plainLesson.weekNumber + ); + const weeklyExercises = await this._getReviewVocabExercises( + plainLesson.courseId, + plainLesson.lessonNumber, + plainLesson.weekNumber + ); + plainLesson.reviewLessons = weeklyLessons; + plainLesson.previousLessonExercises = []; + plainLesson.weeklyReviewTrainingExercises = weeklyExercises; + plainLesson.reviewVocabExercises = this._selectCheckpointExamExercises(weeklyExercises, plainLesson.id); + plainLesson.weeklyReviewExamCount = plainLesson.reviewVocabExercises.length; + plainLesson.weeklyReviewTrainingCount = weeklyExercises.length; + plainLesson.corePatterns = weeklyLessons.flatMap((entry) => { + if (Array.isArray(entry.corePatterns)) return entry.corePatterns; + if (typeof entry.corePatterns === 'string') { + try { + const parsed = JSON.parse(entry.corePatterns); + return Array.isArray(parsed) ? parsed : []; + } catch (error) { + return []; + } + } + return []; + }); + } else if (isWeeklyReview) { const weeklyLessons = await this._getReviewLessons( plainLesson.courseId, plainLesson.lessonNumber, @@ -3210,6 +3243,17 @@ export default class VocabService { return this._seededShuffle(list.slice(), seed).slice(0, targetCount); } + _selectCheckpointExamExercises(exercises = [], lessonId) { + const list = Array.isArray(exercises) ? exercises : []; + if (list.length === 0) return []; + + const seed = (Number(lessonId) * 100003) >>> 0; + // Checkpoints: smaller sample ~10-30% + const percentage = 10 + (seed % 21); + const targetCount = Math.max(1, Math.ceil((list.length * percentage) / 100)); + return this._seededShuffle(list.slice(), seed).slice(0, targetCount); + } + /** * Sammelt Grammatik‑Übungen aus vorherigen Lektionen derselben Woche */ diff --git a/frontend/src/views/social/VocabLessonView.vue b/frontend/src/views/social/VocabLessonView.vue index 64e290a..6be743e 100644 --- a/frontend/src/views/social/VocabLessonView.vue +++ b/frontend/src/views/social/VocabLessonView.vue @@ -1390,11 +1390,12 @@ export default { } return core; }, - /** Für Wiederholungslektionen: Übungen aus vorherigen Lektionen (Kapitelprüfung). Sonst: eigene Grammatik-Übungen. */ + /** Für Wiederholungslektionen und Checkpoints: Übungen aus vorherigen Lektionen (Kapitelprüfung). Sonst: eigene Grammatik-Übungen. */ effectiveExercises() { if (!this.lesson) return []; - const isReview = ['review', 'vocab_review', 'weekly_review'].includes(this.lesson.lessonType); - if (isReview && this.lesson.reviewVocabExercises && Array.isArray(this.lesson.reviewVocabExercises) && this.lesson.reviewVocabExercises.length > 0) { + // Wenn die API bereits reviewVocabExercises liefert (z.B. für Wochenwiederholungen oder Checkpoints), + // nutze diese explizit – sie enthalten die Kapitel-/Checkpoint-Übungen. + if (this.lesson.reviewVocabExercises && Array.isArray(this.lesson.reviewVocabExercises) && this.lesson.reviewVocabExercises.length > 0) { return this.lesson.reviewVocabExercises; } if (this.lesson.grammarExercises && Array.isArray(this.lesson.grammarExercises)) {