ts-fsrs 5.2.2 → 5.3.0
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.
- package/CHANGELOG.md +11 -0
- package/dist/index.cjs +112 -192
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.mjs +112 -193
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +112 -192
- package/dist/index.umd.js.map +1 -1
- package/package.json +25 -36
- package/README.md +0 -174
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# ts-fsrs
|
|
2
|
+
|
|
3
|
+
## 5.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#266](https://github.com/open-spaced-repetition/ts-fsrs/pull/266) [`17fb34d`](https://github.com/open-spaced-repetition/ts-fsrs/commit/17fb34d849c66f2035c5a239e2dfd64ed40055c9) Thanks [@ishiko732](https://github.com/ishiko732)! - Non-decreasing SInc(Hard) in same-day reviews — sync with fsrs-rs#376 changes
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- [#314](https://github.com/open-spaced-repetition/ts-fsrs/pull/314) [`87f94f2`](https://github.com/open-spaced-repetition/ts-fsrs/commit/87f94f277f7030a449490cef943e1aebe1585b64) Thanks [@user1823](https://github.com/user1823)! - Performance improvements
|
package/dist/index.cjs
CHANGED
|
@@ -54,8 +54,12 @@ class TypeConvert {
|
|
|
54
54
|
throw new Error(`Invalid state:[${value}]`);
|
|
55
55
|
}
|
|
56
56
|
static time(value) {
|
|
57
|
-
if (
|
|
57
|
+
if (value instanceof Date) {
|
|
58
58
|
return value;
|
|
59
|
+
}
|
|
60
|
+
const date = new Date(value);
|
|
61
|
+
if (typeof value === "object" && value !== null && !Number.isNaN(Date.parse(value) || +date)) {
|
|
62
|
+
return date;
|
|
59
63
|
} else if (typeof value === "string") {
|
|
60
64
|
const timestamp = Date.parse(value);
|
|
61
65
|
if (!Number.isNaN(timestamp)) {
|
|
@@ -79,15 +83,19 @@ class TypeConvert {
|
|
|
79
83
|
}
|
|
80
84
|
}
|
|
81
85
|
|
|
86
|
+
/* istanbul ignore next -- @preserve */
|
|
82
87
|
Date.prototype.scheduler = function(t, isDay) {
|
|
83
88
|
return date_scheduler(this, t, isDay);
|
|
84
89
|
};
|
|
90
|
+
/* istanbul ignore next -- @preserve */
|
|
85
91
|
Date.prototype.diff = function(pre, unit) {
|
|
86
92
|
return date_diff(this, pre, unit);
|
|
87
93
|
};
|
|
94
|
+
/* istanbul ignore next -- @preserve */
|
|
88
95
|
Date.prototype.format = function() {
|
|
89
96
|
return formatDate(this);
|
|
90
97
|
};
|
|
98
|
+
/* istanbul ignore next -- @preserve */
|
|
91
99
|
Date.prototype.dueFormat = function(last_review, unit, timeUnit) {
|
|
92
100
|
return show_diff_message(this, last_review, unit, timeUnit);
|
|
93
101
|
};
|
|
@@ -147,12 +155,15 @@ function show_diff_message(due, last_review, unit, timeUnit = TIMEUNITFORMAT) {
|
|
|
147
155
|
}
|
|
148
156
|
return `${Math.floor(diff)}${unit ? timeUnit[i] : ""}`;
|
|
149
157
|
}
|
|
158
|
+
/* istanbul ignore next -- @preserve */
|
|
150
159
|
function fixDate(value) {
|
|
151
160
|
return TypeConvert.time(value);
|
|
152
161
|
}
|
|
162
|
+
/* istanbul ignore next -- @preserve */
|
|
153
163
|
function fixState(value) {
|
|
154
164
|
return TypeConvert.state(value);
|
|
155
165
|
}
|
|
166
|
+
/* istanbul ignore next -- @preserve */
|
|
156
167
|
function fixRating(value) {
|
|
157
168
|
return TypeConvert.rating(value);
|
|
158
169
|
}
|
|
@@ -196,6 +207,10 @@ function get_fuzz_range(interval, elapsed_days, maximum_interval) {
|
|
|
196
207
|
function clamp(value, min, max) {
|
|
197
208
|
return Math.min(Math.max(value, min), max);
|
|
198
209
|
}
|
|
210
|
+
function roundTo(num, decimals) {
|
|
211
|
+
const factor = 10 ** decimals;
|
|
212
|
+
return Math.round(num * factor) / factor;
|
|
213
|
+
}
|
|
199
214
|
function dateDiffInDays(last, cur) {
|
|
200
215
|
const utc1 = Date.UTC(
|
|
201
216
|
last.getUTCFullYear(),
|
|
@@ -468,7 +483,7 @@ function alea(seed) {
|
|
|
468
483
|
return prng;
|
|
469
484
|
}
|
|
470
485
|
|
|
471
|
-
const version="5.
|
|
486
|
+
const version="5.3.0";
|
|
472
487
|
|
|
473
488
|
const default_request_retention = 0.9;
|
|
474
489
|
const default_maximum_interval = 36500;
|
|
@@ -642,11 +657,11 @@ function createEmptyCard(now, afterHandler) {
|
|
|
642
657
|
const computeDecayFactor = (decayOrParams) => {
|
|
643
658
|
const decay = typeof decayOrParams === "number" ? -decayOrParams : -decayOrParams[20];
|
|
644
659
|
const factor = Math.exp(Math.pow(decay, -1) * Math.log(0.9)) - 1;
|
|
645
|
-
return { decay, factor:
|
|
660
|
+
return { decay, factor: roundTo(factor, 8) };
|
|
646
661
|
};
|
|
647
662
|
function forgetting_curve(decayOrParams, elapsed_days, stability) {
|
|
648
663
|
const { decay, factor } = computeDecayFactor(decayOrParams);
|
|
649
|
-
return
|
|
664
|
+
return roundTo(Math.pow(1 + factor * elapsed_days / stability, decay), 8);
|
|
650
665
|
}
|
|
651
666
|
class FSRSAlgorithm {
|
|
652
667
|
param;
|
|
@@ -680,7 +695,7 @@ class FSRSAlgorithm {
|
|
|
680
695
|
throw new Error("Requested retention rate should be in the range (0,1]");
|
|
681
696
|
}
|
|
682
697
|
const { decay, factor } = computeDecayFactor(this.param.w);
|
|
683
|
-
return
|
|
698
|
+
return roundTo((Math.pow(request_retention, 1 / decay) - 1) / factor, 8);
|
|
684
699
|
}
|
|
685
700
|
/**
|
|
686
701
|
* Get the parameters of the algorithm.
|
|
@@ -747,8 +762,9 @@ class FSRSAlgorithm {
|
|
|
747
762
|
* @return {number} Difficulty $$D \in [1,10]$$
|
|
748
763
|
*/
|
|
749
764
|
init_difficulty(g) {
|
|
750
|
-
const
|
|
751
|
-
|
|
765
|
+
const w = this.param.w;
|
|
766
|
+
const d = w[4] - Math.exp((g - 1) * w[5]) + 1;
|
|
767
|
+
return roundTo(d, 8);
|
|
752
768
|
}
|
|
753
769
|
/**
|
|
754
770
|
* If fuzzing is disabled or ivl is less than 2.5, it returns the original interval.
|
|
@@ -783,7 +799,7 @@ class FSRSAlgorithm {
|
|
|
783
799
|
* @see https://github.com/open-spaced-repetition/fsrs4anki/issues/697
|
|
784
800
|
*/
|
|
785
801
|
linear_damping(delta_d, old_d) {
|
|
786
|
-
return
|
|
802
|
+
return roundTo(delta_d * (10 - old_d) / 9, 8);
|
|
787
803
|
}
|
|
788
804
|
/**
|
|
789
805
|
* The formula used is :
|
|
@@ -811,9 +827,8 @@ class FSRSAlgorithm {
|
|
|
811
827
|
* @return {number} difficulty
|
|
812
828
|
*/
|
|
813
829
|
mean_reversion(init, current) {
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
);
|
|
830
|
+
const w = this.param.w;
|
|
831
|
+
return roundTo(w[7] * init + (1 - w[7]) * current, 8);
|
|
817
832
|
}
|
|
818
833
|
/**
|
|
819
834
|
* The formula used is :
|
|
@@ -825,13 +840,17 @@ class FSRSAlgorithm {
|
|
|
825
840
|
* @return {number} S^\prime_r new stability after recall
|
|
826
841
|
*/
|
|
827
842
|
next_recall_stability(d, s, r, g) {
|
|
828
|
-
const
|
|
829
|
-
const
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
843
|
+
const w = this.param.w;
|
|
844
|
+
const hard_penalty = Rating.Hard === g ? w[15] : 1;
|
|
845
|
+
const easy_bound = Rating.Easy === g ? w[16] : 1;
|
|
846
|
+
return roundTo(
|
|
847
|
+
clamp(
|
|
848
|
+
s * (1 + Math.exp(w[8]) * (11 - d) * Math.pow(s, -w[9]) * (Math.exp((1 - r) * w[10]) - 1) * hard_penalty * easy_bound),
|
|
849
|
+
S_MIN,
|
|
850
|
+
36500
|
|
851
|
+
),
|
|
852
|
+
8
|
|
853
|
+
);
|
|
835
854
|
}
|
|
836
855
|
/**
|
|
837
856
|
* The formula used is :
|
|
@@ -844,11 +863,15 @@ class FSRSAlgorithm {
|
|
|
844
863
|
* @return {number} S^\prime_f new stability after forgetting
|
|
845
864
|
*/
|
|
846
865
|
next_forget_stability(d, s, r) {
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
866
|
+
const w = this.param.w;
|
|
867
|
+
return roundTo(
|
|
868
|
+
clamp(
|
|
869
|
+
w[11] * Math.pow(d, -w[12]) * (Math.pow(s + 1, w[13]) - 1) * Math.exp((1 - r) * w[14]),
|
|
870
|
+
S_MIN,
|
|
871
|
+
36500
|
|
872
|
+
),
|
|
873
|
+
8
|
|
874
|
+
);
|
|
852
875
|
}
|
|
853
876
|
/**
|
|
854
877
|
* The formula used is :
|
|
@@ -857,9 +880,10 @@ class FSRSAlgorithm {
|
|
|
857
880
|
* @param {Grade} g Grade (Rating[0.again,1.hard,2.good,3.easy])
|
|
858
881
|
*/
|
|
859
882
|
next_short_term_stability(s, g) {
|
|
860
|
-
const
|
|
861
|
-
const
|
|
862
|
-
|
|
883
|
+
const w = this.param.w;
|
|
884
|
+
const sinc = Math.pow(s, -w[19]) * Math.exp(w[17] * (g - 3 + w[18]));
|
|
885
|
+
const maskedSinc = g >= Rating.Hard ? Math.max(sinc, 1) : sinc;
|
|
886
|
+
return roundTo(clamp(s * maskedSinc, S_MIN, 36500), 8);
|
|
863
887
|
}
|
|
864
888
|
/**
|
|
865
889
|
* The formula used is :
|
|
@@ -875,9 +899,10 @@ class FSRSAlgorithm {
|
|
|
875
899
|
* @param memory_state - The current state of memory, which can be null.
|
|
876
900
|
* @param t - The time elapsed since the last review.
|
|
877
901
|
* @param {Rating} g Grade (Rating[0.Manual,1.Again,2.Hard,3.Good,4.Easy])
|
|
902
|
+
* @param r - Optional retrievability value. If not provided, it will be calculated.
|
|
878
903
|
* @returns The next state of memory with updated difficulty and stability.
|
|
879
904
|
*/
|
|
880
|
-
next_state(memory_state, t, g) {
|
|
905
|
+
next_state(memory_state, t, g, r) {
|
|
881
906
|
const { difficulty: d, stability: s } = memory_state ?? {
|
|
882
907
|
difficulty: 0,
|
|
883
908
|
stability: 0
|
|
@@ -905,22 +930,22 @@ class FSRSAlgorithm {
|
|
|
905
930
|
`Invalid memory state { difficulty: ${d}, stability: ${s} }`
|
|
906
931
|
);
|
|
907
932
|
}
|
|
908
|
-
const
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
if (g === 1) {
|
|
933
|
+
const w = this.param.w;
|
|
934
|
+
r = typeof r === "number" ? r : this.forgetting_curve(t, s);
|
|
935
|
+
let new_s;
|
|
936
|
+
if (t === 0 && this.param.enable_short_term) {
|
|
937
|
+
new_s = this.next_short_term_stability(s, g);
|
|
938
|
+
} else if (g === 1) {
|
|
939
|
+
const s_after_fail = this.next_forget_stability(d, s, r);
|
|
914
940
|
let [w_17, w_18] = [0, 0];
|
|
915
941
|
if (this.param.enable_short_term) {
|
|
916
|
-
w_17 =
|
|
917
|
-
w_18 =
|
|
942
|
+
w_17 = w[17];
|
|
943
|
+
w_18 = w[18];
|
|
918
944
|
}
|
|
919
945
|
const next_s_min = s / Math.exp(w_17 * w_18);
|
|
920
|
-
new_s = clamp(
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
new_s = s_after_short_term;
|
|
946
|
+
new_s = clamp(roundTo(next_s_min, 8), S_MIN, s_after_fail);
|
|
947
|
+
} else {
|
|
948
|
+
new_s = this.next_recall_stability(d, s, r, g);
|
|
924
949
|
}
|
|
925
950
|
const new_d = this.next_difficulty(d, g);
|
|
926
951
|
return { difficulty: new_d, stability: new_s };
|
|
@@ -1005,9 +1030,7 @@ class BasicScheduler extends AbstractScheduler {
|
|
|
1005
1030
|
if (exist) {
|
|
1006
1031
|
return exist;
|
|
1007
1032
|
}
|
|
1008
|
-
const next =
|
|
1009
|
-
next.difficulty = clamp(this.algorithm.init_difficulty(grade), 1, 10);
|
|
1010
|
-
next.stability = this.algorithm.init_stability(grade);
|
|
1033
|
+
const next = this.next_ds(this.elapsed_days, grade);
|
|
1011
1034
|
this.applyLearningSteps(next, grade, State.Learning);
|
|
1012
1035
|
const item = {
|
|
1013
1036
|
card: next,
|
|
@@ -1021,14 +1044,11 @@ class BasicScheduler extends AbstractScheduler {
|
|
|
1021
1044
|
if (exist) {
|
|
1022
1045
|
return exist;
|
|
1023
1046
|
}
|
|
1024
|
-
const
|
|
1025
|
-
const next = TypeConvert.card(this.current);
|
|
1026
|
-
next.difficulty = this.algorithm.next_difficulty(difficulty, grade);
|
|
1027
|
-
next.stability = this.algorithm.next_short_term_stability(stability, grade);
|
|
1047
|
+
const next = this.next_ds(this.elapsed_days, grade);
|
|
1028
1048
|
this.applyLearningSteps(
|
|
1029
1049
|
next,
|
|
1030
1050
|
grade,
|
|
1031
|
-
state
|
|
1051
|
+
this.last.state
|
|
1032
1052
|
/** Learning or Relearning */
|
|
1033
1053
|
);
|
|
1034
1054
|
const item = {
|
|
@@ -1044,21 +1064,14 @@ class BasicScheduler extends AbstractScheduler {
|
|
|
1044
1064
|
return exist;
|
|
1045
1065
|
}
|
|
1046
1066
|
const interval = this.elapsed_days;
|
|
1047
|
-
const
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
const next_hard = TypeConvert.card(this.current);
|
|
1051
|
-
const next_good = TypeConvert.card(this.current);
|
|
1052
|
-
const next_easy = TypeConvert.card(this.current);
|
|
1053
|
-
this.next_ds(
|
|
1054
|
-
next_again,
|
|
1055
|
-
next_hard,
|
|
1056
|
-
next_good,
|
|
1057
|
-
next_easy,
|
|
1058
|
-
difficulty,
|
|
1059
|
-
stability,
|
|
1060
|
-
retrievability
|
|
1067
|
+
const retrievability = this.algorithm.forgetting_curve(
|
|
1068
|
+
interval,
|
|
1069
|
+
this.current.stability
|
|
1061
1070
|
);
|
|
1071
|
+
const next_again = this.next_ds(interval, Rating.Again, retrievability);
|
|
1072
|
+
const next_hard = this.next_ds(interval, Rating.Hard, retrievability);
|
|
1073
|
+
const next_good = this.next_ds(interval, Rating.Good, retrievability);
|
|
1074
|
+
const next_easy = this.next_ds(interval, Rating.Easy, retrievability);
|
|
1062
1075
|
this.next_interval(next_hard, next_good, next_easy, interval);
|
|
1063
1076
|
this.next_state(next_hard, next_good, next_easy);
|
|
1064
1077
|
this.applyLearningSteps(next_again, Rating.Again, State.Relearning);
|
|
@@ -1088,50 +1101,20 @@ class BasicScheduler extends AbstractScheduler {
|
|
|
1088
1101
|
/**
|
|
1089
1102
|
* Review next_ds
|
|
1090
1103
|
*/
|
|
1091
|
-
next_ds(
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
difficulty,
|
|
1101
|
-
stability,
|
|
1102
|
-
retrievability
|
|
1103
|
-
);
|
|
1104
|
-
next_again.stability = clamp(+nextSMin.toFixed(8), S_MIN, s_after_fail);
|
|
1105
|
-
next_hard.difficulty = this.algorithm.next_difficulty(
|
|
1106
|
-
difficulty,
|
|
1107
|
-
Rating.Hard
|
|
1108
|
-
);
|
|
1109
|
-
next_hard.stability = this.algorithm.next_recall_stability(
|
|
1110
|
-
difficulty,
|
|
1111
|
-
stability,
|
|
1112
|
-
retrievability,
|
|
1113
|
-
Rating.Hard
|
|
1114
|
-
);
|
|
1115
|
-
next_good.difficulty = this.algorithm.next_difficulty(
|
|
1116
|
-
difficulty,
|
|
1117
|
-
Rating.Good
|
|
1118
|
-
);
|
|
1119
|
-
next_good.stability = this.algorithm.next_recall_stability(
|
|
1120
|
-
difficulty,
|
|
1121
|
-
stability,
|
|
1122
|
-
retrievability,
|
|
1123
|
-
Rating.Good
|
|
1124
|
-
);
|
|
1125
|
-
next_easy.difficulty = this.algorithm.next_difficulty(
|
|
1126
|
-
difficulty,
|
|
1127
|
-
Rating.Easy
|
|
1128
|
-
);
|
|
1129
|
-
next_easy.stability = this.algorithm.next_recall_stability(
|
|
1130
|
-
difficulty,
|
|
1131
|
-
stability,
|
|
1132
|
-
retrievability,
|
|
1133
|
-
Rating.Easy
|
|
1104
|
+
next_ds(t, g, r) {
|
|
1105
|
+
const next_state = this.algorithm.next_state(
|
|
1106
|
+
{
|
|
1107
|
+
difficulty: this.current.difficulty,
|
|
1108
|
+
stability: this.current.stability
|
|
1109
|
+
},
|
|
1110
|
+
t,
|
|
1111
|
+
g,
|
|
1112
|
+
r
|
|
1134
1113
|
);
|
|
1114
|
+
const card = TypeConvert.card(this.current);
|
|
1115
|
+
card.difficulty = next_state.difficulty;
|
|
1116
|
+
card.stability = next_state.stability;
|
|
1117
|
+
return card;
|
|
1135
1118
|
}
|
|
1136
1119
|
/**
|
|
1137
1120
|
* Review next_interval
|
|
@@ -1174,12 +1157,11 @@ class LongTermScheduler extends AbstractScheduler {
|
|
|
1174
1157
|
}
|
|
1175
1158
|
this.current.scheduled_days = 0;
|
|
1176
1159
|
this.current.elapsed_days = 0;
|
|
1177
|
-
const next_again = TypeConvert.card(this.current);
|
|
1178
|
-
const next_hard = TypeConvert.card(this.current);
|
|
1179
|
-
const next_good = TypeConvert.card(this.current);
|
|
1180
|
-
const next_easy = TypeConvert.card(this.current);
|
|
1181
|
-
this.init_ds(next_again, next_hard, next_good, next_easy);
|
|
1182
1160
|
const first_interval = 0;
|
|
1161
|
+
const next_again = this.next_ds(first_interval, Rating.Again);
|
|
1162
|
+
const next_hard = this.next_ds(first_interval, Rating.Hard);
|
|
1163
|
+
const next_good = this.next_ds(first_interval, Rating.Good);
|
|
1164
|
+
const next_easy = this.next_ds(first_interval, Rating.Easy);
|
|
1183
1165
|
this.next_interval(
|
|
1184
1166
|
next_again,
|
|
1185
1167
|
next_hard,
|
|
@@ -1191,31 +1173,20 @@ class LongTermScheduler extends AbstractScheduler {
|
|
|
1191
1173
|
this.update_next(next_again, next_hard, next_good, next_easy);
|
|
1192
1174
|
return this.next.get(grade);
|
|
1193
1175
|
}
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
1,
|
|
1204
|
-
10
|
|
1205
|
-
);
|
|
1206
|
-
next_hard.stability = this.algorithm.init_stability(Rating.Hard);
|
|
1207
|
-
next_good.difficulty = clamp(
|
|
1208
|
-
this.algorithm.init_difficulty(Rating.Good),
|
|
1209
|
-
1,
|
|
1210
|
-
10
|
|
1211
|
-
);
|
|
1212
|
-
next_good.stability = this.algorithm.init_stability(Rating.Good);
|
|
1213
|
-
next_easy.difficulty = clamp(
|
|
1214
|
-
this.algorithm.init_difficulty(Rating.Easy),
|
|
1215
|
-
1,
|
|
1216
|
-
10
|
|
1176
|
+
next_ds(t, g, r) {
|
|
1177
|
+
const next_state = this.algorithm.next_state(
|
|
1178
|
+
{
|
|
1179
|
+
difficulty: this.current.difficulty,
|
|
1180
|
+
stability: this.current.stability
|
|
1181
|
+
},
|
|
1182
|
+
t,
|
|
1183
|
+
g,
|
|
1184
|
+
r
|
|
1217
1185
|
);
|
|
1218
|
-
|
|
1186
|
+
const card = TypeConvert.card(this.current);
|
|
1187
|
+
card.difficulty = next_state.difficulty;
|
|
1188
|
+
card.stability = next_state.stability;
|
|
1189
|
+
return card;
|
|
1219
1190
|
}
|
|
1220
1191
|
/**
|
|
1221
1192
|
* @see https://github.com/open-spaced-repetition/ts-fsrs/issues/98#issuecomment-2241923194
|
|
@@ -1229,72 +1200,20 @@ class LongTermScheduler extends AbstractScheduler {
|
|
|
1229
1200
|
return exist;
|
|
1230
1201
|
}
|
|
1231
1202
|
const interval = this.elapsed_days;
|
|
1232
|
-
const
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
const next_hard = TypeConvert.card(this.current);
|
|
1236
|
-
const next_good = TypeConvert.card(this.current);
|
|
1237
|
-
const next_easy = TypeConvert.card(this.current);
|
|
1238
|
-
this.next_ds(
|
|
1239
|
-
next_again,
|
|
1240
|
-
next_hard,
|
|
1241
|
-
next_good,
|
|
1242
|
-
next_easy,
|
|
1243
|
-
difficulty,
|
|
1244
|
-
stability,
|
|
1245
|
-
retrievability
|
|
1203
|
+
const retrievability = this.algorithm.forgetting_curve(
|
|
1204
|
+
interval,
|
|
1205
|
+
this.current.stability
|
|
1246
1206
|
);
|
|
1207
|
+
const next_again = this.next_ds(interval, Rating.Again, retrievability);
|
|
1208
|
+
const next_hard = this.next_ds(interval, Rating.Hard, retrievability);
|
|
1209
|
+
const next_good = this.next_ds(interval, Rating.Good, retrievability);
|
|
1210
|
+
const next_easy = this.next_ds(interval, Rating.Easy, retrievability);
|
|
1247
1211
|
this.next_interval(next_again, next_hard, next_good, next_easy, interval);
|
|
1248
1212
|
this.next_state(next_again, next_hard, next_good, next_easy);
|
|
1249
1213
|
next_again.lapses += 1;
|
|
1250
1214
|
this.update_next(next_again, next_hard, next_good, next_easy);
|
|
1251
1215
|
return this.next.get(grade);
|
|
1252
1216
|
}
|
|
1253
|
-
/**
|
|
1254
|
-
* Review next_ds
|
|
1255
|
-
*/
|
|
1256
|
-
next_ds(next_again, next_hard, next_good, next_easy, difficulty, stability, retrievability) {
|
|
1257
|
-
next_again.difficulty = this.algorithm.next_difficulty(
|
|
1258
|
-
difficulty,
|
|
1259
|
-
Rating.Again
|
|
1260
|
-
);
|
|
1261
|
-
const s_after_fail = this.algorithm.next_forget_stability(
|
|
1262
|
-
difficulty,
|
|
1263
|
-
stability,
|
|
1264
|
-
retrievability
|
|
1265
|
-
);
|
|
1266
|
-
next_again.stability = clamp(stability, S_MIN, s_after_fail);
|
|
1267
|
-
next_hard.difficulty = this.algorithm.next_difficulty(
|
|
1268
|
-
difficulty,
|
|
1269
|
-
Rating.Hard
|
|
1270
|
-
);
|
|
1271
|
-
next_hard.stability = this.algorithm.next_recall_stability(
|
|
1272
|
-
difficulty,
|
|
1273
|
-
stability,
|
|
1274
|
-
retrievability,
|
|
1275
|
-
Rating.Hard
|
|
1276
|
-
);
|
|
1277
|
-
next_good.difficulty = this.algorithm.next_difficulty(
|
|
1278
|
-
difficulty,
|
|
1279
|
-
Rating.Good
|
|
1280
|
-
);
|
|
1281
|
-
next_good.stability = this.algorithm.next_recall_stability(
|
|
1282
|
-
difficulty,
|
|
1283
|
-
stability,
|
|
1284
|
-
retrievability,
|
|
1285
|
-
Rating.Good
|
|
1286
|
-
);
|
|
1287
|
-
next_easy.difficulty = this.algorithm.next_difficulty(
|
|
1288
|
-
difficulty,
|
|
1289
|
-
Rating.Easy
|
|
1290
|
-
);
|
|
1291
|
-
next_easy.stability = this.algorithm.next_recall_stability(
|
|
1292
|
-
difficulty,
|
|
1293
|
-
stability,
|
|
1294
|
-
retrievability,
|
|
1295
|
-
Rating.Easy
|
|
1296
|
-
);
|
|
1297
|
-
}
|
|
1298
1217
|
/**
|
|
1299
1218
|
* Review/New next_interval
|
|
1300
1219
|
*/
|
|
@@ -1982,6 +1901,7 @@ exports.fsrs = fsrs;
|
|
|
1982
1901
|
exports.generatorParameters = generatorParameters;
|
|
1983
1902
|
exports.get_fuzz_range = get_fuzz_range;
|
|
1984
1903
|
exports.migrateParameters = migrateParameters;
|
|
1904
|
+
exports.roundTo = roundTo;
|
|
1985
1905
|
exports.show_diff_message = show_diff_message;
|
|
1986
1906
|
module.exports = Object.assign(exports.default || {}, exports)
|
|
1987
1907
|
//# sourceMappingURL=index.cjs.map
|