fix(card): improve SM-2 algorithm An An SM-2 algorithm for LEARNING/RElearning cards now uses correct steps ( RELEARNING_STEPS for relearning cards)
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -126,7 +126,7 @@ function scheduleNewCard(ease: ReviewEase, currentFactor: number): {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function scheduleLearningCard(ease: ReviewEase, currentFactor: number, left: number): {
|
function scheduleLearningCard(ease: ReviewEase, currentFactor: number, left: number, isRelearning: boolean): {
|
||||||
type: CardType;
|
type: CardType;
|
||||||
queue: CardQueue;
|
queue: CardQueue;
|
||||||
ivl: number;
|
ivl: number;
|
||||||
@@ -134,12 +134,13 @@ function scheduleLearningCard(ease: ReviewEase, currentFactor: number, left: num
|
|||||||
newFactor: number;
|
newFactor: number;
|
||||||
newLeft: number;
|
newLeft: number;
|
||||||
} {
|
} {
|
||||||
const steps = SM2_CONFIG.LEARNING_STEPS;
|
const steps = isRelearning ? SM2_CONFIG.RELEARNING_STEPS : SM2_CONFIG.LEARNING_STEPS;
|
||||||
const totalSteps = steps.length;
|
const totalSteps = steps.length;
|
||||||
|
const cardType = isRelearning ? CardType.RELEARNING : CardType.LEARNING;
|
||||||
|
|
||||||
if (ease === 1) {
|
if (ease === 1) {
|
||||||
return {
|
return {
|
||||||
type: CardType.LEARNING,
|
type: cardType,
|
||||||
queue: CardQueue.LEARNING,
|
queue: CardQueue.LEARNING,
|
||||||
ivl: 0,
|
ivl: 0,
|
||||||
due: Math.floor(Date.now() / 1000) + steps[0] * 60,
|
due: Math.floor(Date.now() / 1000) + steps[0] * 60,
|
||||||
@@ -152,9 +153,11 @@ function scheduleLearningCard(ease: ReviewEase, currentFactor: number, left: num
|
|||||||
|
|
||||||
if (ease === 2) {
|
if (ease === 2) {
|
||||||
if (stepIndex === 0 && steps.length >= 2) {
|
if (stepIndex === 0 && steps.length >= 2) {
|
||||||
const avgStep = (steps[0] + steps[1]) / 2;
|
const step0 = steps[0] ?? 1;
|
||||||
|
const step1 = steps[1] ?? step0;
|
||||||
|
const avgStep = (step0 + step1) / 2;
|
||||||
return {
|
return {
|
||||||
type: CardType.LEARNING,
|
type: cardType,
|
||||||
queue: CardQueue.LEARNING,
|
queue: CardQueue.LEARNING,
|
||||||
ivl: 0,
|
ivl: 0,
|
||||||
due: Math.floor(Date.now() / 1000) + avgStep * 60,
|
due: Math.floor(Date.now() / 1000) + avgStep * 60,
|
||||||
@@ -162,35 +165,26 @@ function scheduleLearningCard(ease: ReviewEase, currentFactor: number, left: num
|
|||||||
newLeft: left,
|
newLeft: left,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
if (stepIndex < steps.length - 1) {
|
const currentStepDelay = steps[stepIndex] ?? steps[0] ?? 1;
|
||||||
return {
|
return {
|
||||||
type: CardType.LEARNING,
|
type: cardType,
|
||||||
queue: CardQueue.LEARNING,
|
queue: CardQueue.LEARNING,
|
||||||
ivl: 0,
|
ivl: 0,
|
||||||
due: Math.floor(Date.now() / 1000) + steps[stepIndex] * 60,
|
due: Math.floor(Date.now() / 1000) + currentStepDelay * 60,
|
||||||
newFactor: currentFactor,
|
newFactor: currentFactor,
|
||||||
newLeft: left,
|
newLeft: left,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
const ivl = SM2_CONFIG.GRADUATING_INTERVAL_GOOD;
|
|
||||||
return {
|
|
||||||
type: CardType.REVIEW,
|
|
||||||
queue: CardQueue.REVIEW,
|
|
||||||
ivl,
|
|
||||||
due: calculateDueDate(ivl),
|
|
||||||
newFactor: SM2_CONFIG.DEFAULT_FACTOR,
|
|
||||||
newLeft: 0,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ease === 3) {
|
if (ease === 3) {
|
||||||
if (stepIndex < steps.length - 1) {
|
if (stepIndex < steps.length - 1) {
|
||||||
const nextStep = stepIndex + 1;
|
const nextStep = stepIndex + 1;
|
||||||
|
const nextStepDelay = steps[nextStep] ?? steps[0];
|
||||||
return {
|
return {
|
||||||
type: CardType.LEARNING,
|
type: cardType,
|
||||||
queue: CardQueue.LEARNING,
|
queue: CardQueue.LEARNING,
|
||||||
ivl: 0,
|
ivl: 0,
|
||||||
due: Math.floor(Date.now() / 1000) + steps[nextStep] * 60,
|
due: Math.floor(Date.now() / 1000) + nextStepDelay * 60,
|
||||||
newFactor: currentFactor,
|
newFactor: currentFactor,
|
||||||
newLeft: nextStep * 1000 + (totalSteps - nextStep),
|
newLeft: nextStep * 1000 + (totalSteps - nextStep),
|
||||||
};
|
};
|
||||||
@@ -361,7 +355,7 @@ export async function serviceAnswerCard(
|
|||||||
nextReviewDate: calculateNextReviewTime(result.ivl),
|
nextReviewDate: calculateNextReviewTime(result.ivl),
|
||||||
};
|
};
|
||||||
} else if (card.type === CardType.LEARNING || card.type === CardType.RELEARNING) {
|
} else if (card.type === CardType.LEARNING || card.type === CardType.RELEARNING) {
|
||||||
const result = scheduleLearningCard(ease, card.factor, card.left);
|
const result = scheduleLearningCard(ease, card.factor, card.left, card.type === CardType.RELEARNING);
|
||||||
updateData = {
|
updateData = {
|
||||||
type: result.type,
|
type: result.type,
|
||||||
queue: result.queue,
|
queue: result.queue,
|
||||||
|
|||||||
Reference in New Issue
Block a user