Tageswiederholung verbessert

This commit is contained in:
Torsten Schulz (local)
2026-08-13 11:23:52 +02:00
parent c77ad79f49
commit 3f80cc40ff

View File

@@ -180,7 +180,7 @@ export default {
// SRS session (Langzeitgedächtnis) progress & persistence
// Stored per day and course so the user can close/reopen without starting over.
srsSession: null, // { version, dateKey, courseId, initialTotalDue, initialDueIds, doneIds, correctCount, wrongCount }
srsSession: null, // { version, dateKey, courseId, initialTotalDue, initialDueIds, doneIds, retryPendingIds, finalReviewIds, correctCount, wrongCount }
srsQueueIds: [], // remaining due ids for this session, in due order
srsServerTotalDue: null,
@@ -545,6 +545,8 @@ export default {
initialTotalDue: initialTotal,
initialDueIds: dueIds.slice(0, initialTotal),
doneIds: [],
retryPendingIds: [],
finalReviewIds: [],
correctCount: 0,
wrongCount: 0,
};
@@ -566,7 +568,13 @@ export default {
}
const doneSet = new Set(Array.isArray(this.srsSession.doneIds) ? this.srsSession.doneIds : []);
this.srsQueueIds = dueIds.filter((id) => !doneSet.has(id));
const finalReviewIds = Array.isArray(this.srsSession.finalReviewIds) ? this.srsSession.finalReviewIds : [];
const finalReviewSet = new Set(finalReviewIds);
const availableIds = new Set(dueIds);
this.srsQueueIds = [
...dueIds.filter((id) => !doneSet.has(id) && !finalReviewSet.has(id)),
...finalReviewIds.filter((id) => !doneSet.has(id) && availableIds.has(id))
];
// Fallback: if SRS mode but queue is empty (e.g. mismatch between stored session and current pool), fall back to pool order
if (this.srsMode && Array.isArray(this.srsQueueIds) && this.srsQueueIds.length === 0) {
const fallbackIds = (this.pool || []).map((it) => it.id).filter(Boolean);
@@ -574,7 +582,7 @@ export default {
const limited = fallbackIds.slice(0, MAX_DAILY_DUE);
this.srsQueueIds = limited;
// keep initialTotalDue stable if possible
if (!this.srsSession) this.srsSession = { version: SRS_SESSION_STORAGE_VERSION, dateKey: this.getLocalDateKey(), courseId: this.openParams.courseId, initialTotalDue: limited.length, initialDueIds: limited, doneIds: [], correctCount: 0, wrongCount: 0 };
if (!this.srsSession) this.srsSession = { version: SRS_SESSION_STORAGE_VERSION, dateKey: this.getLocalDateKey(), courseId: this.openParams.courseId, initialTotalDue: limited.length, initialDueIds: limited, doneIds: [], retryPendingIds: [], finalReviewIds: [], correctCount: 0, wrongCount: 0 };
}
}
this.saveSrsSession();
@@ -1259,12 +1267,20 @@ export default {
if (!this.srsMode || !this.answered || this.locked) {
return;
}
this.locked = true;
await this.reportSrsReview(this.lastCorrect, rating);
const id = this.current?.id;
const treatAsAgain = rating === 'again' || !this.lastCorrect;
const moveToHardPractice = treatAsAgain && this.isItemMarkedHard(this.current);
const retryPendingIds = Array.isArray(this.srsSession?.retryPendingIds)
? this.srsSession.retryPendingIds
: [];
const needsFinalRepeat = this.lastCorrect && retryPendingIds.includes(id);
this.locked = true;
// The immediate correction after a wrong answer is a rehearsal, not the
// SRS result. Only the later repetition at the end is recorded as right.
if (!needsFinalRepeat) {
await this.reportSrsReview(this.lastCorrect, rating);
}
if (id && this.srsSession) {
if (treatAsAgain && !moveToHardPractice) {
@@ -1273,6 +1289,24 @@ export default {
if (Array.isArray(this.srsSession.doneIds)) {
this.srsSession.doneIds = this.srsSession.doneIds.filter((x) => x !== id);
}
if (!retryPendingIds.includes(id)) {
this.srsSession.retryPendingIds = [...retryPendingIds, id];
}
} else if (needsFinalRepeat) {
// The correction was right, but the item must be recalled once more
// after the rest of today's cards before it counts as complete.
this.srsSession.retryPendingIds = retryPendingIds.filter((x) => x !== id);
const finalReviewIds = Array.isArray(this.srsSession.finalReviewIds)
? this.srsSession.finalReviewIds
: [];
if (!finalReviewIds.includes(id)) {
this.srsSession.finalReviewIds = [...finalReviewIds, id];
}
const remaining = Array.isArray(this.srsQueueIds)
? this.srsQueueIds.filter((x) => x !== id)
: [];
remaining.push(id);
this.srsQueueIds = remaining;
} else {
// Hard cards leave the daily review after a wrong answer. They are
// practiced separately through the hard-vocab drill.
@@ -1281,6 +1315,10 @@ export default {
done.push(id);
this.srsSession.doneIds = done;
}
this.srsSession.retryPendingIds = retryPendingIds.filter((x) => x !== id);
this.srsSession.finalReviewIds = (Array.isArray(this.srsSession.finalReviewIds)
? this.srsSession.finalReviewIds
: []).filter((x) => x !== id);
if (Array.isArray(this.srsQueueIds) && this.srsQueueIds[0] === id) {
this.srsQueueIds = this.srsQueueIds.slice(1);
} else if (Array.isArray(this.srsQueueIds)) {