ts-fsrs 2.0.2 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,189 +1,203 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- const seedrandom_1 = __importDefault(require("seedrandom"));
7
- const index_1 = require("./index");
8
- class FSRS {
9
- constructor(param) {
10
- this.repeat = (card, now) => {
11
- card = Object.assign({}, card);
12
- now = new Date(now.getTime());
13
- card.elapsed_days = card.state === index_1.State.New ? 0 : now.diff(card.last_review, "days"); //相距时间
14
- card.last_review = now; // 上次复习时间
15
- card.reps += 1;
16
- const s = new index_1.SchedulingCard(card);
17
- s.update_state(card.state);
18
- this.seed = String(card.last_review.getTime()) + String(card.elapsed_days);
19
- let easy_interval, good_interval, hard_interval;
20
- switch (card.state) {
21
- case index_1.State.New:
22
- this.init_ds(s);
23
- s.again.due = now.scheduler(1);
24
- s.hard.due = now.scheduler(5);
25
- s.good.due = now.scheduler(10);
26
- easy_interval = this.next_interval(s.easy.stability * this.param.easy_bonus);
27
- s.easy.scheduled_days = easy_interval;
28
- s.easy.due = now.scheduler(easy_interval, true);
29
- break;
30
- case index_1.State.Learning:
31
- case index_1.State.Relearning:
32
- hard_interval = 0;
33
- good_interval = this.next_interval(s.good.stability);
34
- easy_interval = Math.max(this.next_interval(s.easy.stability * this.param.easy_bonus), good_interval + 1);
35
- s.schedule(now, hard_interval, good_interval, easy_interval);
36
- break;
37
- case index_1.State.Review:
38
- const interval = card.elapsed_days;
39
- const last_d = card.difficulty;
40
- const last_s = card.stability;
41
- const retrievability = this.current_retrievability(interval, last_s);
42
- this.next_ds(s, last_d, last_s, retrievability);
43
- hard_interval = this.next_interval(last_s * this.param.hard_factor);
44
- good_interval = this.next_interval(s.good.stability);
45
- hard_interval = Math.min(hard_interval, good_interval);
46
- good_interval = Math.max(good_interval, hard_interval + 1);
47
- easy_interval = Math.max(this.next_interval(s.easy.stability * this.param.easy_bonus), good_interval + 1);
48
- s.schedule(now, hard_interval, good_interval, easy_interval);
49
- break;
50
- }
51
- return s.record_log(card, now);
52
- };
53
- this.get_retrievability = (card, now) => {
54
- if (card.state !== index_1.State.Review) {
55
- return undefined;
56
- }
57
- const t = Math.max(now.diff(card.last_review, "days"), 0);
58
- return (this.current_retrievability(t, card.stability) * 100).toFixed(2) + '%';
59
- };
60
- this.param = param || (0, index_1.generatorParameters)();
61
- this.intervalModifier = Math.log(this.param.request_retention) / Math.log(0.9);
62
- }
63
- init_ds(s) {
64
- s.again.difficulty = this.init_difficulty(index_1.Rating.Again);
65
- s.again.stability = this.init_stability(index_1.Rating.Again);
66
- s.hard.difficulty = this.init_difficulty(index_1.Rating.Hard);
67
- s.hard.stability = this.init_stability(index_1.Rating.Hard);
68
- s.good.difficulty = this.init_difficulty(index_1.Rating.Good);
69
- s.good.stability = this.init_stability(index_1.Rating.Good);
70
- s.easy.difficulty = this.init_difficulty(index_1.Rating.Easy);
71
- s.easy.stability = this.init_stability(index_1.Rating.Easy);
72
- }
73
- /**
74
- *
75
- * @param s scheduling Card
76
- * @param last_d Difficulty
77
- * @param last_s Stability
78
- * @param retrievability Retrievability
79
- */
80
- next_ds(s, last_d, last_s, retrievability) {
81
- s.again.difficulty = this.next_difficulty(last_d, index_1.Rating.Again);
82
- s.again.stability = this.next_forget_stability(s.again.difficulty, last_s, retrievability);
83
- s.hard.difficulty = this.next_difficulty(last_d, index_1.Rating.Hard);
84
- s.hard.stability = this.next_recall_stability(s.hard.difficulty, last_s, retrievability);
85
- s.good.difficulty = this.next_difficulty(last_d, index_1.Rating.Good);
86
- s.good.stability = this.next_recall_stability(s.good.difficulty, last_s, retrievability);
87
- s.easy.difficulty = this.next_difficulty(last_d, index_1.Rating.Easy);
88
- s.easy.stability = this.next_recall_stability(s.easy.difficulty, last_s, retrievability);
89
- }
90
- /**
91
- * The formula used is :
92
- * $$S_0(G) = w_0 + G \cdot w_1$$
93
- * $$\max \{S_0,0.1\}$$
94
- * @param g Grade (rating at Anki) [0.again,1.hard,2.good,3.easy]
95
- * @return Stability (interval when R=90%)
96
- */
97
- init_stability(g) {
98
- return Math.max(this.param.w[0] + this.param.w[1] * g, 0.1);
99
- }
100
- /**
101
- * The formula used is :
102
- * $$D_0(G) = w_2 + (G-2) \cdot w_3$$
103
- * $$\min \{\max \{D_0(G),1\},10\}$$
104
- * @param g Grade (rating at Anki) [0.again,1.hard,2.good,3.easy]
105
- * @return Difficulty D \in [1,10]
106
- */
107
- init_difficulty(g) {
108
- return Math.min(Math.max(this.param.w[2] + this.param.w[3] * (g - 2), 1), 10);
109
- }
110
- apply_fuzz(ivl) {
111
- if (!this.param.enable_fuzz || ivl < 2.5)
112
- return ivl;
113
- const generator = (0, seedrandom_1.default)(this.seed);
114
- const fuzz_factor = generator();
115
- ivl = Math.round(ivl);
116
- const min_ivl = Math.max(2, Math.round(ivl * 0.95 - 1));
117
- const max_ivl = Math.round(ivl * 1.05 + 1);
118
- return Math.floor(fuzz_factor * (max_ivl - min_ivl + 1) + min_ivl);
119
- }
120
- next_interval(s) {
121
- const newInterval = this.apply_fuzz(s * this.intervalModifier);
122
- return Math.min(Math.max(Math.round(newInterval), 1), this.param.maximum_interval);
123
- }
124
- /**
125
- * The formula used is :
126
- * $$next_d = D + w_4 \cdot (R - 2)$$
127
- * $$D^\prime(D,R) = w_5 \cdot D_0(2) +(1 - w_5) \cdot next_d$$
128
- * @param d
129
- * @param g Grade (Rating[0.again,1.hard,2.good,3.easy])
130
- * @return next_D
131
- */
132
- next_difficulty(d, g) {
133
- const next_d = d + this.param.w[4] * (g - 2);
134
- return this.constrain_difficulty(this.mean_reversion(this.param.w[2], next_d));
135
- }
136
- /**
137
- * The formula used is :
138
- * $$\min \{\max \{D_0,1\},10\}$$
139
- */
140
- constrain_difficulty(difficulty) {
141
- return Math.min(Math.max(Number(difficulty.toFixed(2)), 1), 10);
142
- }
143
- /**
144
- * The formula used is :
145
- * $$w_5 \cdot init +(1 - w_5) \cdot current$$
146
- * @param init $$w_2 : D_0(2) = w_2 + (R-2) \cdot w_3= w_2$$
147
- * @param current $$D + w_4 \cdot (R - 2)$$
148
- * @return difficulty
149
- */
150
- mean_reversion(init, current) {
151
- return this.param.w[5] * init + (1 - this.param.w[5]) * current;
152
- }
153
- /**
154
- * The formula used is :
155
- * $$S^\prime_r(D,S,R) = S\cdot(e^{w_6}\cdot (11-D)\cdot S^{w_7}\cdot(e^{w_8\cdot(1-R)}-1)+1)$$
156
- * @param d Difficulty D \in [1,10]
157
- * @param s Stability (interval when R=90%)
158
- * @param r Retrievability (probability of recall)
159
- * @return S^\prime_r new stability after recall
160
- */
161
- next_recall_stability(d, s, r) {
162
- return s * (1 + Math.exp(this.param.w[6]) *
163
- (11 - d) *
164
- Math.pow(s, this.param.w[7]) *
165
- (Math.exp((1 - r) * this.param.w[8]) - 1));
166
- }
167
- /**
168
- * The formula used is :
169
- * $$S^\prime_f(D,S,R) = w_9\cdot D^{w_{10}}\cdot S^{w_{11}}\cdot e^{w_{12}\cdot(1-R)}.$$
170
- * @param d Difficulty D \in [1,10]
171
- * @param s Stability (interval when R=90%)
172
- * @param r Retrievability (probability of recall)
173
- * @return S^\prime_f new stability after forgetting
174
- */
175
- next_forget_stability(d, s, r) {
176
- return this.param.w[9] * Math.pow(d, this.param.w[10]) * Math.pow(s, this.param.w[11]) * Math.exp((1 - r) * this.param.w[12]);
177
- }
178
- /**
179
- * The formula used is :
180
- * $$R(t,S) = 0.9^{\frac{t}{S}}$$
181
- * @param t t days since the last review
182
- * @param s Stability (interval when R=90%)
183
- * @return r Retrievability (probability of recall)
184
- */
185
- current_retrievability(t, s) {
186
- return Math.exp(Math.log(0.9) * t / s);
187
- }
188
- }
189
- exports.default = FSRS;
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const seedrandom_1 = __importDefault(require("seedrandom"));
7
+ const index_1 = require("./index");
8
+ const help_1 = require("./help");
9
+ class FSRS {
10
+ param;
11
+ intervalModifier;
12
+ seed;
13
+ constructor(param) {
14
+ this.param = param || (0, index_1.generatorParameters)();
15
+ this.intervalModifier =
16
+ Math.log(this.param.request_retention) / Math.log(0.9);
17
+ }
18
+ repeat = (card, now) => {
19
+ card = {
20
+ ...card,
21
+ };
22
+ now = new Date((0, help_1.fixDate)(now));
23
+ card.elapsed_days =
24
+ card.state === index_1.State.New ? 0 : now.diff(card.last_review, "days"); //相距时间
25
+ card.last_review = now; // 上次复习时间
26
+ card.reps += 1;
27
+ const s = new index_1.SchedulingCard(card);
28
+ s.update_state(card.state);
29
+ this.seed = String(card.last_review.getTime()) + String(card.elapsed_days);
30
+ let easy_interval, good_interval, hard_interval;
31
+ switch (card.state) {
32
+ case index_1.State.New:
33
+ this.init_ds(s);
34
+ s.again.due = now.scheduler(1);
35
+ s.hard.due = now.scheduler(5);
36
+ s.good.due = now.scheduler(10);
37
+ easy_interval = this.next_interval(s.easy.stability * this.param.easy_bonus);
38
+ s.easy.scheduled_days = easy_interval;
39
+ s.easy.due = now.scheduler(easy_interval, true);
40
+ break;
41
+ case index_1.State.Learning:
42
+ case index_1.State.Relearning:
43
+ hard_interval = 0;
44
+ good_interval = this.next_interval(s.good.stability);
45
+ easy_interval = Math.max(this.next_interval(s.easy.stability * this.param.easy_bonus), good_interval + 1);
46
+ s.schedule(now, hard_interval, good_interval, easy_interval);
47
+ break;
48
+ case index_1.State.Review: {
49
+ const interval = card.elapsed_days;
50
+ const last_d = card.difficulty;
51
+ const last_s = card.stability;
52
+ const retrievability = this.current_retrievability(interval, last_s);
53
+ this.next_ds(s, last_d, last_s, retrievability);
54
+ hard_interval = this.next_interval(last_s * this.param.hard_factor);
55
+ good_interval = this.next_interval(s.good.stability);
56
+ hard_interval = Math.min(hard_interval, good_interval);
57
+ good_interval = Math.max(good_interval, hard_interval + 1);
58
+ easy_interval = Math.max(this.next_interval(s.easy.stability * this.param.easy_bonus), good_interval + 1);
59
+ s.schedule(now, hard_interval, good_interval, easy_interval);
60
+ break;
61
+ }
62
+ }
63
+ return s.record_log(card, now);
64
+ };
65
+ get_retrievability = (card, now) => {
66
+ if (card.state !== index_1.State.Review) {
67
+ return undefined;
68
+ }
69
+ const t = Math.max(now.diff(card.last_review, "days"), 0);
70
+ return ((this.current_retrievability(t, card.stability) * 100).toFixed(2) + "%");
71
+ };
72
+ init_ds(s) {
73
+ s.again.difficulty = this.init_difficulty(index_1.Rating.Again);
74
+ s.again.stability = this.init_stability(index_1.Rating.Again);
75
+ s.hard.difficulty = this.init_difficulty(index_1.Rating.Hard);
76
+ s.hard.stability = this.init_stability(index_1.Rating.Hard);
77
+ s.good.difficulty = this.init_difficulty(index_1.Rating.Good);
78
+ s.good.stability = this.init_stability(index_1.Rating.Good);
79
+ s.easy.difficulty = this.init_difficulty(index_1.Rating.Easy);
80
+ s.easy.stability = this.init_stability(index_1.Rating.Easy);
81
+ }
82
+ /**
83
+ *
84
+ * @param s scheduling Card
85
+ * @param last_d Difficulty
86
+ * @param last_s Stability
87
+ * @param retrievability Retrievability
88
+ */
89
+ next_ds(s, last_d, last_s, retrievability) {
90
+ s.again.difficulty = this.next_difficulty(last_d, index_1.Rating.Again);
91
+ s.again.stability = this.next_forget_stability(s.again.difficulty, last_s, retrievability);
92
+ s.hard.difficulty = this.next_difficulty(last_d, index_1.Rating.Hard);
93
+ s.hard.stability = this.next_recall_stability(s.hard.difficulty, last_s, retrievability);
94
+ s.good.difficulty = this.next_difficulty(last_d, index_1.Rating.Good);
95
+ s.good.stability = this.next_recall_stability(s.good.difficulty, last_s, retrievability);
96
+ s.easy.difficulty = this.next_difficulty(last_d, index_1.Rating.Easy);
97
+ s.easy.stability = this.next_recall_stability(s.easy.difficulty, last_s, retrievability);
98
+ }
99
+ /**
100
+ * The formula used is :
101
+ * $$S_0(G) = w_0 + G \cdot w_1$$
102
+ * $$\max \{S_0,0.1\}$$
103
+ * @param g Grade (rating at Anki) [0.again,1.hard,2.good,3.easy]
104
+ * @return Stability (interval when R=90%)
105
+ */
106
+ init_stability(g) {
107
+ return Math.max(this.param.w[0] + this.param.w[1] * g, 0.1);
108
+ }
109
+ /**
110
+ * The formula used is :
111
+ * $$D_0(G) = w_2 + (G-2) \cdot w_3$$
112
+ * $$\min \{\max \{D_0(G),1\},10\}$$
113
+ * @param g Grade (rating at Anki) [0.again,1.hard,2.good,3.easy]
114
+ * @return Difficulty D \in [1,10]
115
+ */
116
+ init_difficulty(g) {
117
+ return Math.min(Math.max(this.param.w[2] + this.param.w[3] * (g - 2), 1), 10);
118
+ }
119
+ apply_fuzz(ivl) {
120
+ if (!this.param.enable_fuzz || ivl < 2.5)
121
+ return ivl;
122
+ const generator = (0, seedrandom_1.default)(this.seed);
123
+ const fuzz_factor = generator();
124
+ ivl = Math.round(ivl);
125
+ const min_ivl = Math.max(2, Math.round(ivl * 0.95 - 1));
126
+ const max_ivl = Math.round(ivl * 1.05 + 1);
127
+ return Math.floor(fuzz_factor * (max_ivl - min_ivl + 1) + min_ivl);
128
+ }
129
+ next_interval(s) {
130
+ const newInterval = this.apply_fuzz(s * this.intervalModifier);
131
+ return Math.min(Math.max(Math.round(newInterval), 1), this.param.maximum_interval);
132
+ }
133
+ /**
134
+ * The formula used is :
135
+ * $$next_d = D + w_4 \cdot (R - 2)$$
136
+ * $$D^\prime(D,R) = w_5 \cdot D_0(2) +(1 - w_5) \cdot next_d$$
137
+ * @param d
138
+ * @param g Grade (Rating[0.again,1.hard,2.good,3.easy])
139
+ * @return next_D
140
+ */
141
+ next_difficulty(d, g) {
142
+ const next_d = d + this.param.w[4] * (g - 2);
143
+ return this.constrain_difficulty(this.mean_reversion(this.param.w[2], next_d));
144
+ }
145
+ /**
146
+ * The formula used is :
147
+ * $$\min \{\max \{D_0,1\},10\}$$
148
+ */
149
+ constrain_difficulty(difficulty) {
150
+ return Math.min(Math.max(Number(difficulty.toFixed(2)), 1), 10);
151
+ }
152
+ /**
153
+ * The formula used is :
154
+ * $$w_5 \cdot init +(1 - w_5) \cdot current$$
155
+ * @param init $$w_2 : D_0(2) = w_2 + (R-2) \cdot w_3= w_2$$
156
+ * @param current $$D + w_4 \cdot (R - 2)$$
157
+ * @return difficulty
158
+ */
159
+ mean_reversion(init, current) {
160
+ return this.param.w[5] * init + (1 - this.param.w[5]) * current;
161
+ }
162
+ /**
163
+ * The formula used is :
164
+ * $$S^\prime_r(D,S,R) = S\cdot(e^{w_6}\cdot (11-D)\cdot S^{w_7}\cdot(e^{w_8\cdot(1-R)}-1)+1)$$
165
+ * @param d Difficulty D \in [1,10]
166
+ * @param s Stability (interval when R=90%)
167
+ * @param r Retrievability (probability of recall)
168
+ * @return S^\prime_r new stability after recall
169
+ */
170
+ next_recall_stability(d, s, r) {
171
+ return (s *
172
+ (1 +
173
+ Math.exp(this.param.w[6]) *
174
+ (11 - d) *
175
+ Math.pow(s, this.param.w[7]) *
176
+ (Math.exp((1 - r) * this.param.w[8]) - 1)));
177
+ }
178
+ /**
179
+ * The formula used is :
180
+ * $$S^\prime_f(D,S,R) = w_9\cdot D^{w_{10}}\cdot S^{w_{11}}\cdot e^{w_{12}\cdot(1-R)}.$$
181
+ * @param d Difficulty D \in [1,10]
182
+ * @param s Stability (interval when R=90%)
183
+ * @param r Retrievability (probability of recall)
184
+ * @return S^\prime_f new stability after forgetting
185
+ */
186
+ next_forget_stability(d, s, r) {
187
+ return (this.param.w[9] *
188
+ Math.pow(d, this.param.w[10]) *
189
+ Math.pow(s, this.param.w[11]) *
190
+ Math.exp((1 - r) * this.param.w[12]));
191
+ }
192
+ /**
193
+ * The formula used is :
194
+ * $$R(t,S) = 0.9^{\frac{t}{S}}$$
195
+ * @param t t days since the last review
196
+ * @param s Stability (interval when R=90%)
197
+ * @return r Retrievability (probability of recall)
198
+ */
199
+ current_retrievability(t, s) {
200
+ return Math.exp((Math.log(0.9) * t) / s);
201
+ }
202
+ }
203
+ exports.default = FSRS;
@@ -0,0 +1,2 @@
1
+ declare const FSRSVersion: string;
2
+ export default FSRSVersion;
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
4
+ // @ts-ignore
5
+ const package_json_1 = require("../../package.json");
6
+ const FSRSVersion = package_json_1.version;
7
+ exports.default = FSRSVersion;
@@ -1,19 +1,20 @@
1
- export type unit = 'days' | 'minutes';
2
- export type int = number & {
3
- __int__: void;
4
- };
5
- export type double = number & {
6
- __double__: void;
7
- };
8
- declare global {
9
- export interface Date {
10
- scheduler(t: int, isDay?: boolean): Date;
11
- diff(pre: Date, unit: unit): int;
12
- format(): string;
13
- dueFormat(last_review: Date, unit?: boolean): string;
14
- }
15
- }
16
- export declare function date_scheduler(now: Date, t: number, isDay?: boolean): Date;
17
- export declare function date_diff(now: Date, pre: Date, unit: unit): number;
18
- export declare function formatDate(date: Date): string;
19
- export declare function show_diff_message(due: Date, last_review: Date, unit?: boolean): string;
1
+ export type unit = "days" | "minutes";
2
+ export type int = number & {
3
+ __int__: void;
4
+ };
5
+ export type double = number & {
6
+ __double__: void;
7
+ };
8
+ declare global {
9
+ export interface Date {
10
+ scheduler(t: int, isDay?: boolean): Date;
11
+ diff(pre: Date, unit: unit): int;
12
+ format(): string;
13
+ dueFormat(last_review: Date, unit?: boolean): string;
14
+ }
15
+ }
16
+ export declare function date_scheduler(now: Date, t: number, isDay?: boolean): Date;
17
+ export declare function date_diff(now: Date, pre: Date, unit: unit): number;
18
+ export declare function formatDate(date: Date): string;
19
+ export declare function show_diff_message(due: Date, last_review: Date, unit?: boolean, timeUnit?: string[]): string;
20
+ export declare function fixDate(value: unknown): Date;
package/dist/help.js ADDED
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.fixDate = exports.show_diff_message = exports.formatDate = exports.date_diff = exports.date_scheduler = void 0;
4
+ Date.prototype.scheduler = function (t, isDay) {
5
+ return date_scheduler(this, t, isDay);
6
+ };
7
+ /**
8
+ * 当前时间与之前的时间差值
9
+ * @param pre 比当前时间还要之前
10
+ * @param unit 单位: days | minutes
11
+ */
12
+ Date.prototype.diff = function (pre, unit) {
13
+ return date_diff(this, pre, unit);
14
+ };
15
+ Date.prototype.format = function () {
16
+ return formatDate(this);
17
+ };
18
+ Date.prototype.dueFormat = function (last_review, unit) {
19
+ return show_diff_message(this, last_review, unit);
20
+ };
21
+ function date_scheduler(now, t, isDay) {
22
+ return new Date(isDay
23
+ ? now.getTime() + t * 24 * 60 * 60 * 1000
24
+ : now.getTime() + t * 60 * 1000);
25
+ }
26
+ exports.date_scheduler = date_scheduler;
27
+ function date_diff(now, pre, unit) {
28
+ const diff = now.getTime() - pre.getTime();
29
+ let r = 0;
30
+ switch (unit) {
31
+ case "days":
32
+ r = Math.floor(diff / (24 * 60 * 60 * 1000));
33
+ break;
34
+ case "minutes":
35
+ r = Math.floor(diff / (60 * 1000));
36
+ break;
37
+ }
38
+ return r;
39
+ }
40
+ exports.date_diff = date_diff;
41
+ function formatDate(date) {
42
+ const year = date.getFullYear();
43
+ const month = date.getMonth() + 1;
44
+ const day = date.getDate();
45
+ const hours = date.getHours();
46
+ const minutes = date.getMinutes();
47
+ const seconds = date.getSeconds();
48
+ return `${year}-${padZero(month)}-${padZero(day)} ${padZero(hours)}:${padZero(minutes)}:${padZero(seconds)}`;
49
+ }
50
+ exports.formatDate = formatDate;
51
+ function padZero(num) {
52
+ return num < 10 ? `0${num}` : `${num}`;
53
+ }
54
+ const TIMEUNIT = [60, 60, 24, 31, 12];
55
+ const TIMEUNITFORMAT = ["second", "min", "hour", "day", "month", "year"];
56
+ function show_diff_message(due, last_review, unit, timeUnit = TIMEUNITFORMAT) {
57
+ due = fixDate(due);
58
+ last_review = fixDate(last_review);
59
+ if (timeUnit.length !== TIMEUNITFORMAT.length) {
60
+ timeUnit = TIMEUNITFORMAT;
61
+ }
62
+ let diff = due.getTime() - last_review.getTime();
63
+ let i;
64
+ diff /= 1000;
65
+ for (i = 0; i < TIMEUNIT.length; i++) {
66
+ if (diff < TIMEUNIT[i]) {
67
+ break;
68
+ }
69
+ else {
70
+ diff /= TIMEUNIT[i];
71
+ }
72
+ }
73
+ return `${Math.floor(diff)}${unit ? timeUnit[i] : ""}`;
74
+ }
75
+ exports.show_diff_message = show_diff_message;
76
+ function fixDate(value) {
77
+ if (typeof value === "object" && value instanceof Date) {
78
+ return value;
79
+ }
80
+ else if (typeof value === "string") {
81
+ const timestamp = Date.parse(value);
82
+ if (!isNaN(timestamp)) {
83
+ return new Date(timestamp);
84
+ }
85
+ else {
86
+ throw new Error(`Invalid date:[${value}]`);
87
+ }
88
+ }
89
+ else if (typeof value === "number") {
90
+ return new Date(value);
91
+ }
92
+ throw new Error(`Invalid date:[${value}]`);
93
+ }
94
+ exports.fixDate = fixDate;
@@ -1,25 +1,26 @@
1
- import FSRS from "./fsrs";
2
- import { Card, default_easy_bonus, default_enable_fuzz, default_hard_factor, default_maximum_interval, default_request_retention, default_w, FSRSParameters, Rating, RatingType, ReviewLog, SchedulingLog, State, StateType } from "./models";
3
- import { SchedulingCard } from "./scheduler";
4
- declare const fsrs: (param?: FSRSParameters) => FSRS;
5
- declare const createEmptyCard: (now?: Date) => Card;
6
- declare const generatorParameters: (props?: {
7
- request_retention?: number;
8
- maximum_interval?: number;
9
- easy_bonus?: number;
10
- hard_factor?: number;
11
- w?: number[];
12
- enable_fuzz?: boolean;
13
- }) => {
14
- request_retention: number;
15
- maximum_interval: number;
16
- easy_bonus: number;
17
- hard_factor: number;
18
- w: number[];
19
- enable_fuzz: boolean;
20
- };
21
- declare const FSRS_Version = "2.0.2";
22
- export { fsrs, FSRS_Version, State, Rating, SchedulingCard, createEmptyCard, generatorParameters };
23
- export type { StateType, RatingType, ReviewLog, Card, SchedulingLog, FSRSParameters };
24
- export { default_request_retention, default_maximum_interval, default_easy_bonus, default_hard_factor, default_w, default_enable_fuzz };
25
- export { date_scheduler, date_diff, formatDate, show_diff_message } from './help';
1
+ import FSRS from "./fsrs";
2
+ import { Card, default_easy_bonus, default_enable_fuzz, default_hard_factor, default_maximum_interval, default_request_retention, default_w, FSRSParameters, Rating, RatingType, ReviewLog, SchedulingLog, State, StateType } from "./models";
3
+ import { SchedulingCard } from "./scheduler";
4
+ import FSRSVersion from "./fsrs_version";
5
+ declare const fsrs: (param?: FSRSParameters) => FSRS;
6
+ declare const createEmptyCard: (now?: Date) => Card;
7
+ declare const generatorParameters: (props?: {
8
+ request_retention?: number;
9
+ maximum_interval?: number;
10
+ easy_bonus?: number;
11
+ hard_factor?: number;
12
+ w?: number[];
13
+ enable_fuzz?: boolean;
14
+ }) => {
15
+ request_retention: number;
16
+ maximum_interval: number;
17
+ easy_bonus: number;
18
+ hard_factor: number;
19
+ w: number[];
20
+ enable_fuzz: boolean;
21
+ };
22
+ export { fsrs, FSRSVersion, State, Rating, SchedulingCard, createEmptyCard, generatorParameters, };
23
+ export type { StateType, RatingType, ReviewLog, Card, SchedulingLog, FSRSParameters, };
24
+ export { default_request_retention, default_maximum_interval, default_easy_bonus, default_hard_factor, default_w, default_enable_fuzz, };
25
+ export { date_scheduler, date_diff, formatDate, show_diff_message, } from "./help";
26
+ export type { int, double } from "./help";