Skip to content

Commit

Permalink
Fix/elapsed days (#45)
Browse files Browse the repository at this point in the history
* Fix/ incorrect calculation of elapsed_days in the revlog caused by rollback

* 3.1.0-beta3
  • Loading branch information
ishiko732 authored Nov 11, 2023
1 parent 8154795 commit c9d994d
Show file tree
Hide file tree
Showing 7 changed files with 100 additions and 12 deletions.
5 changes: 4 additions & 1 deletion __tests__/FSRSV4.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import {
createEmptyCard,
State,
Grade,
Grades
Grades,
} from "../src/fsrs";

describe("initial FSRS V4", () => {
Expand Down Expand Up @@ -77,6 +77,9 @@ describe("FSRS V4 AC by py-fsrs", () => {
scheduling_cards[check].log,
);
expect(rollbackCard).toEqual(card);
expect(scheduling_cards[check].log.elapsed_days).toEqual(
card.last_review ? now.diff(card.last_review as Date, "days") : 0,
);
}
card = scheduling_cards[rating].card;
const ivl = card.scheduled_days;
Expand Down
74 changes: 74 additions & 0 deletions __tests__/elapsed_days.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
// Ref:https://github.com/ishiko732/ts-fsrs/issues/44

import { fsrs, FSRS, createEmptyCard, Rating, Grade } from "../src/fsrs";

describe("elapsed_days", () => {
const f: FSRS = fsrs();

const createDue = new Date(Date.UTC(2023, 9, 18, 14, 32, 3, 370));
const grades: Grade[] = [
Rating.Good,
Rating.Again,
Rating.Again,
Rating.Good,
];
let currentLog = null;
let index = 0;
let card = createEmptyCard(createDue);
test("first repeat[Rating.Good]", () => {
const firstDue = new Date(Date.UTC(2023, 10, 5, 8, 27, 2, 605));
const sc = f.repeat(card, firstDue);
currentLog = sc[grades[index]].log;

expect(currentLog.elapsed_days).toEqual(0);
// console.log(sc[grades[index]].log)
card = sc[grades[index]].card;
// console.log(card)
index += 1;
});

test("second repeat[Rating.Again]", () => {
// 2023-11-08 15:02:09.791,4.93,2023-11-05 08:27:02.605
const secondDue = new Date(Date.UTC(2023, 10, 8, 15, 2, 9, 791));
expect(card).not.toBeNull()
const sc = f.repeat(card, secondDue);

currentLog = sc[grades[index]].log;
expect(currentLog.elapsed_days).toEqual(secondDue.diff(card.last_review as Date,'days')); // 3
expect(currentLog.elapsed_days).toEqual(3); // 0
card = sc[grades[index]].card;
// console.log(card)
// console.log(currentLog)
index += 1;
});

test("third repeat[Rating.Again]", () => {
// 2023-11-08 15:02:30.799,4.93,2023-11-08 15:02:09.791
const secondDue = new Date(Date.UTC(2023, 10, 8, 15, 2, 30, 799));
expect(card).not.toBeNull()
const sc = f.repeat(card, secondDue);

currentLog = sc[grades[index]].log;
expect(currentLog.elapsed_days).toEqual(secondDue.diff(card.last_review as Date,'days')); // 0
expect(currentLog.elapsed_days).toEqual(0); // 0
// console.log(currentLog);
card = sc[grades[index]].card;
// console.log(card);
index += 1;
});

test("fourth repeat[Rating.Good]", () => {
// 2023-11-08 15:04:08.739,4.93,2023-11-08 15:02:30.799
const secondDue = new Date(Date.UTC(2023, 10, 8, 15, 4, 8, 739));
expect(card).not.toBeNull()
const sc = f.repeat(card, secondDue);

currentLog = sc[grades[index]].log;
expect(currentLog.elapsed_days).toEqual(secondDue.diff(card.last_review as Date,'days')); // 0
expect(currentLog.elapsed_days).toEqual(0); // 0
// console.log(currentLog);
card = sc[grades[index]].card;
// console.log(card);
index += 1;
})
});
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ts-fsrs",
"version": "3.1.0-beta2",
"version": "3.1.0-beta3",
"description": "ts-fsrs is a TypeScript package used to implement the Free Spaced Repetition Scheduler (FSRS) algorithm. It helps developers apply FSRS to their flashcard applications, thereby improving the user learning experience.",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
2 changes: 1 addition & 1 deletion src/fsrs/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ export const default_w = envParams.FSRS_W || [
];
export const default_enable_fuzz = envParams.FSRS_ENABLE_FUZZ || false;

export const FSRSVersion: string = "3.1.0-beta2";
export const FSRSVersion: string = "3.1.0-beta3";

export const generatorParameters = (props?: Partial<FSRSParameters>): FSRSParameters => {
return {
Expand Down
12 changes: 9 additions & 3 deletions src/fsrs/fsrs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,13 @@ export class FSRS extends FSRSAlgorithm {
if (log.rating === Rating.Manual) {
throw new Error("Cannot rollback a manual rating");
}
let last_due, last_review, last_lapses;
let last_due, last_review, last_lapses, last_elapsed_days;
switch (log.state) {
case State.New:
last_due = log.due;
last_review = undefined;
last_lapses = 0;
last_elapsed_days = 0;
break;
case State.Learning:
case State.Relearning:
Expand All @@ -122,6 +123,10 @@ export class FSRS extends FSRSAlgorithm {
last_lapses =
card.lapses -
(log.rating === Rating.Again && log.state === State.Review ? 1 : 0);
last_elapsed_days =
log.elapsed_days == 0
? 0
: card.scheduled_days;
break;
}

Expand All @@ -130,7 +135,7 @@ export class FSRS extends FSRSAlgorithm {
due: last_due,
stability: log.stability,
difficulty: log.difficulty,
elapsed_days: log.elapsed_days,
elapsed_days: log.last_elapsed_days,
scheduled_days: log.scheduled_days,
reps: Math.max(0, card.reps - 1),
lapses: Math.max(0, last_lapses),
Expand All @@ -152,7 +157,8 @@ export class FSRS extends FSRSAlgorithm {
due: card.due,
stability: card.stability,
difficulty: card.difficulty,
elapsed_days: card.elapsed_days,
elapsed_days: 0,
last_elapsed_days: card.elapsed_days,
scheduled_days: card.scheduled_days,
review: now,
};
Expand Down
1 change: 1 addition & 0 deletions src/fsrs/models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export interface ReviewLog {
stability: number;
difficulty: number;
elapsed_days: number;
last_elapsed_days: number;
scheduled_days: number;
review: Date;
}
Expand Down
16 changes: 10 additions & 6 deletions src/fsrs/scheduler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export class SchedulingCard {
good: Card;
easy: Card;
last_review: Date;
elapsed_days: number;
last_elapsed_days: number;

private copy(card: Card): Card {
return {
Expand All @@ -17,7 +17,7 @@ export class SchedulingCard {

constructor(card: Card, now: Date) {
this.last_review = card.last_review || card.due;
this.elapsed_days = card.elapsed_days;
this.last_elapsed_days = card.elapsed_days;
card.elapsed_days =
card.state === State.New ? 0 : now.diff(card.last_review as Date, "days"); //相距时间
card.last_review = now; // 上次复习时间
Expand Down Expand Up @@ -80,7 +80,8 @@ export class SchedulingCard {
due: this.last_review,
stability: card.stability,
difficulty: card.difficulty,
elapsed_days: this.elapsed_days,
elapsed_days: card.elapsed_days,
last_elapsed_days: this.last_elapsed_days,
scheduled_days: card.scheduled_days,
review: now,
},
Expand All @@ -93,7 +94,8 @@ export class SchedulingCard {
due: this.last_review,
stability: card.stability,
difficulty: card.difficulty,
elapsed_days: this.elapsed_days,
elapsed_days: card.elapsed_days,
last_elapsed_days: this.last_elapsed_days,
scheduled_days: card.scheduled_days,
review: now,
},
Expand All @@ -106,7 +108,8 @@ export class SchedulingCard {
due: this.last_review,
stability: card.stability,
difficulty: card.difficulty,
elapsed_days: this.elapsed_days,
elapsed_days: card.elapsed_days,
last_elapsed_days: this.last_elapsed_days,
scheduled_days: card.scheduled_days,
review: now,
},
Expand All @@ -119,7 +122,8 @@ export class SchedulingCard {
due: this.last_review,
stability: card.stability,
difficulty: card.difficulty,
elapsed_days: this.elapsed_days,
elapsed_days: card.elapsed_days,
last_elapsed_days: this.last_elapsed_days,
scheduled_days: card.scheduled_days,
review: now,
},
Expand Down

0 comments on commit c9d994d

Please sign in to comment.