feat: verbessere initialTotalDue und begrenze tägliche Übungsanzahl auf MAX_DAILY_DUE
All checks were successful
Deploy to production / deploy (push) Successful in 1m59s
All checks were successful
Deploy to production / deploy (push) Successful in 1m59s
This commit is contained in:
@@ -193,14 +193,16 @@ export default class VocabService {
|
||||
}
|
||||
|
||||
// Determine safe default nextDueAt for newly created items:
|
||||
// - default: next calendar day at 08:00
|
||||
// - ensure at least 24 hours after creation
|
||||
// - prefer a calendar time (08:00) at least one day after creation
|
||||
// - ensure at least 48 hours after creation so freshly practiced items
|
||||
// don't immediately appear as due the next day
|
||||
const createdAt = new Date(now);
|
||||
const nextCalendar08 = new Date(createdAt);
|
||||
nextCalendar08.setHours(8, 0, 0, 0);
|
||||
nextCalendar08.setDate(nextCalendar08.getDate() + 1);
|
||||
const min24h = new Date(createdAt.getTime() + 24 * 60 * 60 * 1000);
|
||||
const safeNextDue = nextCalendar08.getTime() < min24h.getTime() ? min24h : nextCalendar08;
|
||||
// consider the day after tomorrow as earliest calendar slot
|
||||
nextCalendar08.setDate(nextCalendar08.getDate() + 2);
|
||||
const min48h = new Date(createdAt.getTime() + 48 * 60 * 60 * 1000);
|
||||
const safeNextDue = nextCalendar08.getTime() < min48h.getTime() ? min48h : nextCalendar08;
|
||||
|
||||
const created = await VocabSrsItem.create({
|
||||
userId,
|
||||
|
||||
@@ -161,6 +161,7 @@ const PRACTICE_MIN_EXPOSURES = 3;
|
||||
const SRS_SESSION_STORAGE_VERSION = 2;
|
||||
const HARD_REQUIRED_CONSECUTIVE_CORRECT = 5;
|
||||
const SRS_AGAIN_REINSERT_OFFSET = 3;
|
||||
const MAX_DAILY_DUE = 50;
|
||||
|
||||
export default {
|
||||
name: 'VocabPracticeDialog',
|
||||
@@ -514,13 +515,14 @@ export default {
|
||||
}
|
||||
|
||||
if (!this.srsSession) {
|
||||
const initialTotal = Math.min(MAX_DAILY_DUE, Number.isFinite(Number(this.srsServerTotalDue)) ? Number(this.srsServerTotalDue) : dueIds.length);
|
||||
this.srsSession = {
|
||||
version: SRS_SESSION_STORAGE_VERSION,
|
||||
dateKey: this.getLocalDateKey(),
|
||||
courseId: this.openParams.courseId,
|
||||
// Prefer server-reported total due count when available (shows full-course due count)
|
||||
initialTotalDue: Number.isFinite(Number(this.srsServerTotalDue)) ? Number(this.srsServerTotalDue) : dueIds.length,
|
||||
initialDueIds: dueIds,
|
||||
// For the user's session we cap the number practiced per day to MAX_DAILY_DUE
|
||||
initialTotalDue: initialTotal,
|
||||
initialDueIds: dueIds.slice(0, initialTotal),
|
||||
doneIds: [],
|
||||
correctCount: 0,
|
||||
wrongCount: 0,
|
||||
@@ -536,26 +538,22 @@ export default {
|
||||
// If the stored session has an invalid initialTotalDue (e.g. 0), repair it from server/pool data.
|
||||
if (this.srsSession && (!Number.isFinite(Number(this.srsSession.initialTotalDue)) || Number(this.srsSession.initialTotalDue) <= 0)) {
|
||||
const repairedTotal = Number.isFinite(Number(this.srsServerTotalDue)) && Number(this.srsServerTotalDue) > 0 ? Number(this.srsServerTotalDue) : dueIds.length;
|
||||
try { console.debug('[VocabPracticeDialog] repair srsSession.initialTotalDue', { before: this.srsSession.initialTotalDue, repairedTotal }); } catch (_) {}
|
||||
this.srsSession.initialTotalDue = repairedTotal;
|
||||
this.srsSession.initialDueIds = Array.isArray(this.srsSession.initialDueIds) && this.srsSession.initialDueIds.length ? this.srsSession.initialDueIds : dueIds;
|
||||
const capped = Math.min(MAX_DAILY_DUE, repairedTotal);
|
||||
this.srsSession.initialTotalDue = capped;
|
||||
this.srsSession.initialDueIds = Array.isArray(this.srsSession.initialDueIds) && this.srsSession.initialDueIds.length ? this.srsSession.initialDueIds.slice(0, capped) : dueIds.slice(0, capped);
|
||||
try { this.saveSrsSession(); } catch (_) {}
|
||||
}
|
||||
|
||||
const doneSet = new Set(Array.isArray(this.srsSession.doneIds) ? this.srsSession.doneIds : []);
|
||||
this.srsQueueIds = dueIds.filter((id) => !doneSet.has(id));
|
||||
try {
|
||||
console.debug('[VocabPracticeDialog] initSrsSessionFromPool', { courseId: this.openParams?.courseId, dueIdsLen: dueIds.length, srsQueueLen: this.srsQueueIds.length, stored: !!this.srsSession });
|
||||
} catch (_) {}
|
||||
|
||||
// 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);
|
||||
if (fallbackIds.length > 0) {
|
||||
try { console.debug('[VocabPracticeDialog] initSrsSessionFromPool: srsQueueIds empty, falling back to pool ids', { fallbackLen: fallbackIds.length }); } catch (_) {}
|
||||
this.srsQueueIds = fallbackIds;
|
||||
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: fallbackIds.length, initialDueIds: fallbackIds, 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: [], correctCount: 0, wrongCount: 0 };
|
||||
}
|
||||
}
|
||||
this.saveSrsSession();
|
||||
@@ -595,10 +593,6 @@ export default {
|
||||
document.addEventListener('keydown', this.handleKeyDown);
|
||||
});
|
||||
this.loadHardVocabMap();
|
||||
// Expose instance for temporary debugging in browser console
|
||||
try {
|
||||
window.__vocabPracticeDialog = this;
|
||||
} catch (_) {}
|
||||
this.reloadPool();
|
||||
},
|
||||
close() {
|
||||
@@ -747,7 +741,6 @@ export default {
|
||||
});
|
||||
|
||||
const result = mapped.filter(Boolean);
|
||||
try { console.debug('[VocabPracticeDialog] normalizePool', { inputLen, outLen: result.length, sample: result.slice(0,5) }); } catch (_) {}
|
||||
return result;
|
||||
} catch (e) {
|
||||
console.warn('[VocabPracticeDialog] normalizePool failed', e);
|
||||
|
||||
Reference in New Issue
Block a user