Skip to content

Commit

Permalink
Doc/add return type in algorithm.ts&update example in README.md (#41)
Browse files Browse the repository at this point in the history
* Doc/add return type in algorithm.ts

* Doc/update example in README.md

* 3.0.5
  • Loading branch information
ishiko732 authored Nov 3, 2023
1 parent c613571 commit 13dbecb
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 51 deletions.
44 changes: 23 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,26 +30,28 @@ const now = new Date('2022-2-2 10:00:00');// new Date();
const scheduling_cards = f.repeat(card, now);

// console.log(scheduling_cards);
Object.keys(Rating).filter(key => typeof Rating[key as any] === 'number').forEach(key => {
// @ts-ignore
const { log, card } = scheduling_cards[Rating[key]];
console.group(`${key}`);
console.table({
[`card_${key}`]: {
...card,
due: formatDate(card.due),
last_review: formatDate(card.last_review),
},
});
console.table({
[`log_${key}`]: {
...log,
review: formatDate(log.review),
},
});
console.groupEnd();
console.log('----------------------------------------------------------------');
});
Object.keys(Rating)
.filter(key => !isNaN(Number(key)))
.map(key => Number(key) as Rating) // [Rating.Again, Rating.Hard, Rating.Good, Rating.Easy]
.forEach(grade => {
const { log, card } = scheduling_cards[grade];
console.group(`${Rating[grade]}`);
console.table({
[`card_${Rating[grade]}`]: {
...card,
due: formatDate(card.due),
last_review: formatDate(card.last_review as Date),
},
});
console.table({
[`log_${Rating[grade]}`]: {
...log,
review: formatDate(log.review),
},
});
console.groupEnd();
console.log('----------------------------------------------------------------');
});
```

> More examples refer to the [Example](https://github.com/ishiko732/ts-fsrs/blob/master/example/index.ts)
Expand Down Expand Up @@ -88,7 +90,7 @@ import {
} from "ts-fsrs";

let card: Card = createEmptyCard();
const f: FSRS = new FSRS();
const f: FSRS = new FSRS(); // or const f: FSRS = fsrs(params);
let scheduling_cards: RecordLog = f.repeat(card, new Date());
```

Expand Down
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.0.4",
"version": "3.0.5",
"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
59 changes: 31 additions & 28 deletions src/fsrs/algorithm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import type { int } from "./type";
// Ref: https://github.com/open-spaced-repetition/fsrs4anki/wiki/The-Algorithm#fsrs-v4
export class FSRSAlgorithm {
protected param: FSRSParameters;
private readonly intervalModifier;
private readonly intervalModifier: number;
protected seed?: string;

constructor(param: Partial<FSRSParameters>) {
Expand All @@ -28,11 +28,11 @@ export class FSRSAlgorithm {
}

/**
* Updates the difficulty and stability values of the scheduling card based on the last difficulty,
* Updates the difficulty and stability values of the scheduling card based on the last difficulty,
* last stability, and the current retrievability.
* @param s scheduling Card
* @param last_d Difficulty
* @param last_s Stability
* @param {SchedulingCard} s scheduling Card
* @param {number} last_d Difficulty
* @param {number} last_s Stability
* @param retrievability Retrievability
*/
next_ds(
Expand Down Expand Up @@ -86,21 +86,22 @@ export class FSRSAlgorithm {
* $$D_0(G) = w_4 - (G-3) \cdot w_5$$
* $$\min \{\max \{D_0(G),1\},10\}$$
* where the D_0(3)=w_4 when the first rating is good.
* @param g Grade (rating at Anki) [1.again,2.hard,3.good,4.easy]
* @return Difficulty D \in [1,10]
* @param {number} g Grade (rating at Anki) [1.again,2.hard,3.good,4.easy]
* @return {number} Difficulty D \in [1,10]
*/
init_difficulty(g: number): number {
return Math.min(
Math.max(this.param.w[4] - (g - 3) * this.param.w[5], 1),
10,
);
}

/**
* If fuzzing is disabled or ivl is less than 2.5, it returns the original interval.
* @param {number} ivl - The interval to be fuzzed.
* @returns {number} - The fuzzed interval.
* @return {number} - The fuzzed interval.
**/
apply_fuzz(ivl: number) {
apply_fuzz(ivl: number): number {
if (!this.param.enable_fuzz || ivl < 2.5) return ivl;
const generator = pseudorandom(this.seed);
const fuzz_factor = generator();
Expand All @@ -114,6 +115,7 @@ export class FSRSAlgorithm {
* Ref:
* constructor(param: Partial<FSRSParameters>)
* this.intervalModifier = 9 * (1 / this.param.request_retention - 1);
* @param {number} s - Stability (interval when R=90%)
*/
next_interval(s: number): int {
const newInterval = this.apply_fuzz(s * this.intervalModifier);
Expand All @@ -127,9 +129,9 @@ export class FSRSAlgorithm {
* The formula used is :
* $$next_d = D - w_6 \cdot (R - 2)$$
* $$D^\prime(D,R) = w_5 \cdot D_0(2) +(1 - w_5) \cdot next_d$$
* @param d
* @param g Grade (rating at Anki) [1.again,2.hard,3.good,4.easy]
* @return next_D
* @param {number} d Difficulty D \in [1,10]
* @param {Rating} g Grade (rating at Anki) [1.again,2.hard,3.good,4.easy]
* @return {number} next_D
*/
next_difficulty(d: number, g: number): number {
const next_d = d - this.param.w[6] * (g - 3);
Expand All @@ -141,17 +143,18 @@ export class FSRSAlgorithm {
/**
* The formula used is :
* $$\min \{\max \{D_0,1\},10\}$$
* @param {number} difficulty D \in [1,10]
*/
constrain_difficulty(difficulty: number) {
constrain_difficulty(difficulty: number): number {
return Math.min(Math.max(Number(difficulty.toFixed(2)), 1), 10);
}

/**
* The formula used is :
* $$w_7 \cdot init +(1 - w_7) \cdot current$$
* @param init $$w_2 : D_0(3) = w_2 + (R-2) \cdot w_3= w_2$$
* @param current $$D - w_6 \cdot (R - 2)$$
* @return difficulty
* @param {number} init $$w_2 : D_0(3) = w_2 + (R-2) \cdot w_3= w_2$$
* @param {number} current $$D - w_6 \cdot (R - 2)$$
* @return {number} difficulty
*/
mean_reversion(init: number, current: number): number {
return this.param.w[7] * init + (1 - this.param.w[7]) * current;
Expand All @@ -160,11 +163,11 @@ export class FSRSAlgorithm {
/**
* The formula used is :
* $$S^\prime_r(D,S,R,G) = S\cdot(e^{w_8}\cdot (11-D)\cdot S^{-w_9}\cdot(e^{w_10\cdot(1-R)}-1)\cdot w_15(if G=2) \cdot w_16(if G=4)+1)$$
* @param d Difficulty D \in [1,10]
* @param s Stability (interval when R=90%)
* @param r Retrievability (probability of recall)
* @param g Grade (Rating[0.again,1.hard,2.good,3.easy])
* @return S^\prime_r new stability after recall
* @param {number} d Difficulty D \in [1,10]
* @param {number} s Stability (interval when R=90%)
* @param {number} r Retrievability (probability of recall)
* @param {Rating} g Grade (Rating[0.again,1.hard,2.good,3.easy])
* @return {number} S^\prime_r new stability after recall
*/
next_recall_stability(d: number, s: number, r: number, g: Rating): number {
const hard_penalty = Rating.Hard === g ? this.param.w[15] : 1;
Expand All @@ -184,10 +187,10 @@ export class FSRSAlgorithm {
/**
* The formula used is :
* $$S^\prime_f(D,S,R) = w_11\cdot D^{-w_{12}}\cdot ((S+1)^{w_{13}}-1) \cdot e^{w_{14}\cdot(1-R)}.$$
* @param d Difficulty D \in [1,10]
* @param s Stability (interval when R=90%)
* @param r Retrievability (probability of recall)
* @return S^\prime_f new stability after forgetting
* @param {number} d Difficulty D \in [1,10]
* @param {number} s Stability (interval when R=90%)
* @param {number} r Retrievability (probability of recall)
* @return {number} S^\prime_f new stability after forgetting
*/
next_forget_stability(d: number, s: number, r: number): number {
return (
Expand All @@ -201,9 +204,9 @@ export class FSRSAlgorithm {
/**
* The formula used is :
* $$R(t,S) = (1 + \frac{t}{9 \cdot S})^{-1},$$
* @param t t days since the last review
* @param s Stability (interval when R=90%)
* @return r Retrievability (probability of recall)
* @param {number} t t days since the last review
* @param {number} s Stability (interval when R=90%)
* @return {number} r Retrievability (probability of recall)
*/
current_retrievability(t: number, s: number): number {
return Math.pow(1 + t / (9 * s), -1);
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.0.4";
export const FSRSVersion: string = "3.0.5";

export const generatorParameters = (props?: Partial<FSRSParameters>): FSRSParameters => {
return {
Expand Down

0 comments on commit 13dbecb

Please sign in to comment.