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/dist/index.d.ts
CHANGED
|
@@ -325,9 +325,10 @@ declare class FSRSAlgorithm {
|
|
|
325
325
|
* @param memory_state - The current state of memory, which can be null.
|
|
326
326
|
* @param t - The time elapsed since the last review.
|
|
327
327
|
* @param {Rating} g Grade (Rating[0.Manual,1.Again,2.Hard,3.Good,4.Easy])
|
|
328
|
+
* @param r - Optional retrievability value. If not provided, it will be calculated.
|
|
328
329
|
* @returns The next state of memory with updated difficulty and stability.
|
|
329
330
|
*/
|
|
330
|
-
next_state(memory_state: FSRSState | null, t: number, g: number): FSRSState;
|
|
331
|
+
next_state(memory_state: FSRSState | null, t: number, g: number, r?: number): FSRSState;
|
|
331
332
|
}
|
|
332
333
|
|
|
333
334
|
declare enum StrategyMode {
|
|
@@ -560,6 +561,7 @@ declare function get_fuzz_range(interval: number, elapsed_days: number, maximum_
|
|
|
560
561
|
max_ivl: number;
|
|
561
562
|
};
|
|
562
563
|
declare function clamp(value: number, min: number, max: number): number;
|
|
564
|
+
declare function roundTo(num: number, decimals: number): number;
|
|
563
565
|
declare function dateDiffInDays(last: Date, cur: Date): number;
|
|
564
566
|
|
|
565
567
|
declare const ConvertStepUnitToMinutes: (step: StepUnit) => number;
|
|
@@ -587,5 +589,5 @@ declare function DefaultInitSeedStrategy(this: AbstractScheduler): string;
|
|
|
587
589
|
*/
|
|
588
590
|
declare function GenSeedStrategyWithCardId(card_id_field: string | number): TSeedStrategy;
|
|
589
591
|
|
|
590
|
-
export { AbstractScheduler, BasicLearningStepsStrategy, CLAMP_PARAMETERS, ConvertStepUnitToMinutes, DefaultInitSeedStrategy, FSRS, FSRS5_DEFAULT_DECAY, FSRS6_DEFAULT_DECAY, FSRSAlgorithm, FSRSVersion, GenSeedStrategyWithCardId, Grades, INIT_S_MAX, Rating, S_MAX, S_MIN, State, StrategyMode, TypeConvert, W17_W18_Ceiling, checkParameters, clamp, clipParameters, computeDecayFactor, createEmptyCard, dateDiffInDays, date_diff, date_scheduler, default_enable_fuzz, default_enable_short_term, default_learning_steps, default_maximum_interval, default_relearning_steps, default_request_retention, default_w, fixDate, fixRating, fixState, forgetting_curve, formatDate, fsrs, generatorParameters, get_fuzz_range, migrateParameters, show_diff_message };
|
|
592
|
+
export { AbstractScheduler, BasicLearningStepsStrategy, CLAMP_PARAMETERS, ConvertStepUnitToMinutes, DefaultInitSeedStrategy, FSRS, FSRS5_DEFAULT_DECAY, FSRS6_DEFAULT_DECAY, FSRSAlgorithm, FSRSVersion, GenSeedStrategyWithCardId, Grades, INIT_S_MAX, Rating, S_MAX, S_MIN, State, StrategyMode, TypeConvert, W17_W18_Ceiling, checkParameters, clamp, clipParameters, computeDecayFactor, createEmptyCard, dateDiffInDays, date_diff, date_scheduler, default_enable_fuzz, default_enable_short_term, default_learning_steps, default_maximum_interval, default_relearning_steps, default_request_retention, default_w, fixDate, fixRating, fixState, forgetting_curve, formatDate, fsrs, generatorParameters, get_fuzz_range, migrateParameters, roundTo, show_diff_message };
|
|
591
593
|
export type { Card, CardInput, DateInput, FSRSHistory, FSRSParameters, FSRSReview, FSRSState, Grade, GradeType, IFSRS, IPreview, IReschedule, IScheduler, RatingType, RecordLog, RecordLogItem, RescheduleOptions, ReviewLog, ReviewLogInput, StateType, StepUnit, Steps, TLearningStepsStrategy, TSchedulerStrategy, TSeedStrategy, TStrategyHandler, TimeUnit, double, int, unit };
|
package/dist/index.mjs
CHANGED
|
@@ -52,8 +52,12 @@ class TypeConvert {
|
|
|
52
52
|
throw new Error(`Invalid state:[${value}]`);
|
|
53
53
|
}
|
|
54
54
|
static time(value) {
|
|
55
|
-
if (
|
|
55
|
+
if (value instanceof Date) {
|
|
56
56
|
return value;
|
|
57
|
+
}
|
|
58
|
+
const date = new Date(value);
|
|
59
|
+
if (typeof value === "object" && value !== null && !Number.isNaN(Date.parse(value) || +date)) {
|
|
60
|
+
return date;
|
|
57
61
|
} else if (typeof value === "string") {
|
|
58
62
|
const timestamp = Date.parse(value);
|
|
59
63
|
if (!Number.isNaN(timestamp)) {
|
|
@@ -77,15 +81,19 @@ class TypeConvert {
|
|
|
77
81
|
}
|
|
78
82
|
}
|
|
79
83
|
|
|
84
|
+
/* istanbul ignore next -- @preserve */
|
|
80
85
|
Date.prototype.scheduler = function(t, isDay) {
|
|
81
86
|
return date_scheduler(this, t, isDay);
|
|
82
87
|
};
|
|
88
|
+
/* istanbul ignore next -- @preserve */
|
|
83
89
|
Date.prototype.diff = function(pre, unit) {
|
|
84
90
|
return date_diff(this, pre, unit);
|
|
85
91
|
};
|
|
92
|
+
/* istanbul ignore next -- @preserve */
|
|
86
93
|
Date.prototype.format = function() {
|
|
87
94
|
return formatDate(this);
|
|
88
95
|
};
|
|
96
|
+
/* istanbul ignore next -- @preserve */
|
|
89
97
|
Date.prototype.dueFormat = function(last_review, unit, timeUnit) {
|
|
90
98
|
return show_diff_message(this, last_review, unit, timeUnit);
|
|
91
99
|
};
|
|
@@ -145,12 +153,15 @@ function show_diff_message(due, last_review, unit, timeUnit = TIMEUNITFORMAT) {
|
|
|
145
153
|
}
|
|
146
154
|
return `${Math.floor(diff)}${unit ? timeUnit[i] : ""}`;
|
|
147
155
|
}
|
|
156
|
+
/* istanbul ignore next -- @preserve */
|
|
148
157
|
function fixDate(value) {
|
|
149
158
|
return TypeConvert.time(value);
|
|
150
159
|
}
|
|
160
|
+
/* istanbul ignore next -- @preserve */
|
|
151
161
|
function fixState(value) {
|
|
152
162
|
return TypeConvert.state(value);
|
|
153
163
|
}
|
|
164
|
+
/* istanbul ignore next -- @preserve */
|
|
154
165
|
function fixRating(value) {
|
|
155
166
|
return TypeConvert.rating(value);
|
|
156
167
|
}
|
|
@@ -194,6 +205,10 @@ function get_fuzz_range(interval, elapsed_days, maximum_interval) {
|
|
|
194
205
|
function clamp(value, min, max) {
|
|
195
206
|
return Math.min(Math.max(value, min), max);
|
|
196
207
|
}
|
|
208
|
+
function roundTo(num, decimals) {
|
|
209
|
+
const factor = 10 ** decimals;
|
|
210
|
+
return Math.round(num * factor) / factor;
|
|
211
|
+
}
|
|
197
212
|
function dateDiffInDays(last, cur) {
|
|
198
213
|
const utc1 = Date.UTC(
|
|
199
214
|
last.getUTCFullYear(),
|
|
@@ -466,7 +481,7 @@ function alea(seed) {
|
|
|
466
481
|
return prng;
|
|
467
482
|
}
|
|
468
483
|
|
|
469
|
-
const version="5.
|
|
484
|
+
const version="5.3.0";
|
|
470
485
|
|
|
471
486
|
const default_request_retention = 0.9;
|
|
472
487
|
const default_maximum_interval = 36500;
|
|
@@ -640,11 +655,11 @@ function createEmptyCard(now, afterHandler) {
|
|
|
640
655
|
const computeDecayFactor = (decayOrParams) => {
|
|
641
656
|
const decay = typeof decayOrParams === "number" ? -decayOrParams : -decayOrParams[20];
|
|
642
657
|
const factor = Math.exp(Math.pow(decay, -1) * Math.log(0.9)) - 1;
|
|
643
|
-
return { decay, factor:
|
|
658
|
+
return { decay, factor: roundTo(factor, 8) };
|
|
644
659
|
};
|
|
645
660
|
function forgetting_curve(decayOrParams, elapsed_days, stability) {
|
|
646
661
|
const { decay, factor } = computeDecayFactor(decayOrParams);
|
|
647
|
-
return
|
|
662
|
+
return roundTo(Math.pow(1 + factor * elapsed_days / stability, decay), 8);
|
|
648
663
|
}
|
|
649
664
|
class FSRSAlgorithm {
|
|
650
665
|
param;
|
|
@@ -678,7 +693,7 @@ class FSRSAlgorithm {
|
|
|
678
693
|
throw new Error("Requested retention rate should be in the range (0,1]");
|
|
679
694
|
}
|
|
680
695
|
const { decay, factor } = computeDecayFactor(this.param.w);
|
|
681
|
-
return
|
|
696
|
+
return roundTo((Math.pow(request_retention, 1 / decay) - 1) / factor, 8);
|
|
682
697
|
}
|
|
683
698
|
/**
|
|
684
699
|
* Get the parameters of the algorithm.
|
|
@@ -745,8 +760,9 @@ class FSRSAlgorithm {
|
|
|
745
760
|
* @return {number} Difficulty $$D \in [1,10]$$
|
|
746
761
|
*/
|
|
747
762
|
init_difficulty(g) {
|
|
748
|
-
const
|
|
749
|
-
|
|
763
|
+
const w = this.param.w;
|
|
764
|
+
const d = w[4] - Math.exp((g - 1) * w[5]) + 1;
|
|
765
|
+
return roundTo(d, 8);
|
|
750
766
|
}
|
|
751
767
|
/**
|
|
752
768
|
* If fuzzing is disabled or ivl is less than 2.5, it returns the original interval.
|
|
@@ -781,7 +797,7 @@ class FSRSAlgorithm {
|
|
|
781
797
|
* @see https://github.com/open-spaced-repetition/fsrs4anki/issues/697
|
|
782
798
|
*/
|
|
783
799
|
linear_damping(delta_d, old_d) {
|
|
784
|
-
return
|
|
800
|
+
return roundTo(delta_d * (10 - old_d) / 9, 8);
|
|
785
801
|
}
|
|
786
802
|
/**
|
|
787
803
|
* The formula used is :
|
|
@@ -809,9 +825,8 @@ class FSRSAlgorithm {
|
|
|
809
825
|
* @return {number} difficulty
|
|
810
826
|
*/
|
|
811
827
|
mean_reversion(init, current) {
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
);
|
|
828
|
+
const w = this.param.w;
|
|
829
|
+
return roundTo(w[7] * init + (1 - w[7]) * current, 8);
|
|
815
830
|
}
|
|
816
831
|
/**
|
|
817
832
|
* The formula used is :
|
|
@@ -823,13 +838,17 @@ class FSRSAlgorithm {
|
|
|
823
838
|
* @return {number} S^\prime_r new stability after recall
|
|
824
839
|
*/
|
|
825
840
|
next_recall_stability(d, s, r, g) {
|
|
826
|
-
const
|
|
827
|
-
const
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
841
|
+
const w = this.param.w;
|
|
842
|
+
const hard_penalty = Rating.Hard === g ? w[15] : 1;
|
|
843
|
+
const easy_bound = Rating.Easy === g ? w[16] : 1;
|
|
844
|
+
return roundTo(
|
|
845
|
+
clamp(
|
|
846
|
+
s * (1 + Math.exp(w[8]) * (11 - d) * Math.pow(s, -w[9]) * (Math.exp((1 - r) * w[10]) - 1) * hard_penalty * easy_bound),
|
|
847
|
+
S_MIN,
|
|
848
|
+
36500
|
|
849
|
+
),
|
|
850
|
+
8
|
|
851
|
+
);
|
|
833
852
|
}
|
|
834
853
|
/**
|
|
835
854
|
* The formula used is :
|
|
@@ -842,11 +861,15 @@ class FSRSAlgorithm {
|
|
|
842
861
|
* @return {number} S^\prime_f new stability after forgetting
|
|
843
862
|
*/
|
|
844
863
|
next_forget_stability(d, s, r) {
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
864
|
+
const w = this.param.w;
|
|
865
|
+
return roundTo(
|
|
866
|
+
clamp(
|
|
867
|
+
w[11] * Math.pow(d, -w[12]) * (Math.pow(s + 1, w[13]) - 1) * Math.exp((1 - r) * w[14]),
|
|
868
|
+
S_MIN,
|
|
869
|
+
36500
|
|
870
|
+
),
|
|
871
|
+
8
|
|
872
|
+
);
|
|
850
873
|
}
|
|
851
874
|
/**
|
|
852
875
|
* The formula used is :
|
|
@@ -855,9 +878,10 @@ class FSRSAlgorithm {
|
|
|
855
878
|
* @param {Grade} g Grade (Rating[0.again,1.hard,2.good,3.easy])
|
|
856
879
|
*/
|
|
857
880
|
next_short_term_stability(s, g) {
|
|
858
|
-
const
|
|
859
|
-
const
|
|
860
|
-
|
|
881
|
+
const w = this.param.w;
|
|
882
|
+
const sinc = Math.pow(s, -w[19]) * Math.exp(w[17] * (g - 3 + w[18]));
|
|
883
|
+
const maskedSinc = g >= Rating.Hard ? Math.max(sinc, 1) : sinc;
|
|
884
|
+
return roundTo(clamp(s * maskedSinc, S_MIN, 36500), 8);
|
|
861
885
|
}
|
|
862
886
|
/**
|
|
863
887
|
* The formula used is :
|
|
@@ -873,9 +897,10 @@ class FSRSAlgorithm {
|
|
|
873
897
|
* @param memory_state - The current state of memory, which can be null.
|
|
874
898
|
* @param t - The time elapsed since the last review.
|
|
875
899
|
* @param {Rating} g Grade (Rating[0.Manual,1.Again,2.Hard,3.Good,4.Easy])
|
|
900
|
+
* @param r - Optional retrievability value. If not provided, it will be calculated.
|
|
876
901
|
* @returns The next state of memory with updated difficulty and stability.
|
|
877
902
|
*/
|
|
878
|
-
next_state(memory_state, t, g) {
|
|
903
|
+
next_state(memory_state, t, g, r) {
|
|
879
904
|
const { difficulty: d, stability: s } = memory_state ?? {
|
|
880
905
|
difficulty: 0,
|
|
881
906
|
stability: 0
|
|
@@ -903,22 +928,22 @@ class FSRSAlgorithm {
|
|
|
903
928
|
`Invalid memory state { difficulty: ${d}, stability: ${s} }`
|
|
904
929
|
);
|
|
905
930
|
}
|
|
906
|
-
const
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
if (g === 1) {
|
|
931
|
+
const w = this.param.w;
|
|
932
|
+
r = typeof r === "number" ? r : this.forgetting_curve(t, s);
|
|
933
|
+
let new_s;
|
|
934
|
+
if (t === 0 && this.param.enable_short_term) {
|
|
935
|
+
new_s = this.next_short_term_stability(s, g);
|
|
936
|
+
} else if (g === 1) {
|
|
937
|
+
const s_after_fail = this.next_forget_stability(d, s, r);
|
|
912
938
|
let [w_17, w_18] = [0, 0];
|
|
913
939
|
if (this.param.enable_short_term) {
|
|
914
|
-
w_17 =
|
|
915
|
-
w_18 =
|
|
940
|
+
w_17 = w[17];
|
|
941
|
+
w_18 = w[18];
|
|
916
942
|
}
|
|
917
943
|
const next_s_min = s / Math.exp(w_17 * w_18);
|
|
918
|
-
new_s = clamp(
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
new_s = s_after_short_term;
|
|
944
|
+
new_s = clamp(roundTo(next_s_min, 8), S_MIN, s_after_fail);
|
|
945
|
+
} else {
|
|
946
|
+
new_s = this.next_recall_stability(d, s, r, g);
|
|
922
947
|
}
|
|
923
948
|
const new_d = this.next_difficulty(d, g);
|
|
924
949
|
return { difficulty: new_d, stability: new_s };
|
|
@@ -1003,9 +1028,7 @@ class BasicScheduler extends AbstractScheduler {
|
|
|
1003
1028
|
if (exist) {
|
|
1004
1029
|
return exist;
|
|
1005
1030
|
}
|
|
1006
|
-
const next =
|
|
1007
|
-
next.difficulty = clamp(this.algorithm.init_difficulty(grade), 1, 10);
|
|
1008
|
-
next.stability = this.algorithm.init_stability(grade);
|
|
1031
|
+
const next = this.next_ds(this.elapsed_days, grade);
|
|
1009
1032
|
this.applyLearningSteps(next, grade, State.Learning);
|
|
1010
1033
|
const item = {
|
|
1011
1034
|
card: next,
|
|
@@ -1019,14 +1042,11 @@ class BasicScheduler extends AbstractScheduler {
|
|
|
1019
1042
|
if (exist) {
|
|
1020
1043
|
return exist;
|
|
1021
1044
|
}
|
|
1022
|
-
const
|
|
1023
|
-
const next = TypeConvert.card(this.current);
|
|
1024
|
-
next.difficulty = this.algorithm.next_difficulty(difficulty, grade);
|
|
1025
|
-
next.stability = this.algorithm.next_short_term_stability(stability, grade);
|
|
1045
|
+
const next = this.next_ds(this.elapsed_days, grade);
|
|
1026
1046
|
this.applyLearningSteps(
|
|
1027
1047
|
next,
|
|
1028
1048
|
grade,
|
|
1029
|
-
state
|
|
1049
|
+
this.last.state
|
|
1030
1050
|
/** Learning or Relearning */
|
|
1031
1051
|
);
|
|
1032
1052
|
const item = {
|
|
@@ -1042,21 +1062,14 @@ class BasicScheduler extends AbstractScheduler {
|
|
|
1042
1062
|
return exist;
|
|
1043
1063
|
}
|
|
1044
1064
|
const interval = this.elapsed_days;
|
|
1045
|
-
const
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
const next_hard = TypeConvert.card(this.current);
|
|
1049
|
-
const next_good = TypeConvert.card(this.current);
|
|
1050
|
-
const next_easy = TypeConvert.card(this.current);
|
|
1051
|
-
this.next_ds(
|
|
1052
|
-
next_again,
|
|
1053
|
-
next_hard,
|
|
1054
|
-
next_good,
|
|
1055
|
-
next_easy,
|
|
1056
|
-
difficulty,
|
|
1057
|
-
stability,
|
|
1058
|
-
retrievability
|
|
1065
|
+
const retrievability = this.algorithm.forgetting_curve(
|
|
1066
|
+
interval,
|
|
1067
|
+
this.current.stability
|
|
1059
1068
|
);
|
|
1069
|
+
const next_again = this.next_ds(interval, Rating.Again, retrievability);
|
|
1070
|
+
const next_hard = this.next_ds(interval, Rating.Hard, retrievability);
|
|
1071
|
+
const next_good = this.next_ds(interval, Rating.Good, retrievability);
|
|
1072
|
+
const next_easy = this.next_ds(interval, Rating.Easy, retrievability);
|
|
1060
1073
|
this.next_interval(next_hard, next_good, next_easy, interval);
|
|
1061
1074
|
this.next_state(next_hard, next_good, next_easy);
|
|
1062
1075
|
this.applyLearningSteps(next_again, Rating.Again, State.Relearning);
|
|
@@ -1086,50 +1099,20 @@ class BasicScheduler extends AbstractScheduler {
|
|
|
1086
1099
|
/**
|
|
1087
1100
|
* Review next_ds
|
|
1088
1101
|
*/
|
|
1089
|
-
next_ds(
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
difficulty,
|
|
1099
|
-
stability,
|
|
1100
|
-
retrievability
|
|
1101
|
-
);
|
|
1102
|
-
next_again.stability = clamp(+nextSMin.toFixed(8), S_MIN, s_after_fail);
|
|
1103
|
-
next_hard.difficulty = this.algorithm.next_difficulty(
|
|
1104
|
-
difficulty,
|
|
1105
|
-
Rating.Hard
|
|
1106
|
-
);
|
|
1107
|
-
next_hard.stability = this.algorithm.next_recall_stability(
|
|
1108
|
-
difficulty,
|
|
1109
|
-
stability,
|
|
1110
|
-
retrievability,
|
|
1111
|
-
Rating.Hard
|
|
1112
|
-
);
|
|
1113
|
-
next_good.difficulty = this.algorithm.next_difficulty(
|
|
1114
|
-
difficulty,
|
|
1115
|
-
Rating.Good
|
|
1116
|
-
);
|
|
1117
|
-
next_good.stability = this.algorithm.next_recall_stability(
|
|
1118
|
-
difficulty,
|
|
1119
|
-
stability,
|
|
1120
|
-
retrievability,
|
|
1121
|
-
Rating.Good
|
|
1122
|
-
);
|
|
1123
|
-
next_easy.difficulty = this.algorithm.next_difficulty(
|
|
1124
|
-
difficulty,
|
|
1125
|
-
Rating.Easy
|
|
1126
|
-
);
|
|
1127
|
-
next_easy.stability = this.algorithm.next_recall_stability(
|
|
1128
|
-
difficulty,
|
|
1129
|
-
stability,
|
|
1130
|
-
retrievability,
|
|
1131
|
-
Rating.Easy
|
|
1102
|
+
next_ds(t, g, r) {
|
|
1103
|
+
const next_state = this.algorithm.next_state(
|
|
1104
|
+
{
|
|
1105
|
+
difficulty: this.current.difficulty,
|
|
1106
|
+
stability: this.current.stability
|
|
1107
|
+
},
|
|
1108
|
+
t,
|
|
1109
|
+
g,
|
|
1110
|
+
r
|
|
1132
1111
|
);
|
|
1112
|
+
const card = TypeConvert.card(this.current);
|
|
1113
|
+
card.difficulty = next_state.difficulty;
|
|
1114
|
+
card.stability = next_state.stability;
|
|
1115
|
+
return card;
|
|
1133
1116
|
}
|
|
1134
1117
|
/**
|
|
1135
1118
|
* Review next_interval
|
|
@@ -1172,12 +1155,11 @@ class LongTermScheduler extends AbstractScheduler {
|
|
|
1172
1155
|
}
|
|
1173
1156
|
this.current.scheduled_days = 0;
|
|
1174
1157
|
this.current.elapsed_days = 0;
|
|
1175
|
-
const next_again = TypeConvert.card(this.current);
|
|
1176
|
-
const next_hard = TypeConvert.card(this.current);
|
|
1177
|
-
const next_good = TypeConvert.card(this.current);
|
|
1178
|
-
const next_easy = TypeConvert.card(this.current);
|
|
1179
|
-
this.init_ds(next_again, next_hard, next_good, next_easy);
|
|
1180
1158
|
const first_interval = 0;
|
|
1159
|
+
const next_again = this.next_ds(first_interval, Rating.Again);
|
|
1160
|
+
const next_hard = this.next_ds(first_interval, Rating.Hard);
|
|
1161
|
+
const next_good = this.next_ds(first_interval, Rating.Good);
|
|
1162
|
+
const next_easy = this.next_ds(first_interval, Rating.Easy);
|
|
1181
1163
|
this.next_interval(
|
|
1182
1164
|
next_again,
|
|
1183
1165
|
next_hard,
|
|
@@ -1189,31 +1171,20 @@ class LongTermScheduler extends AbstractScheduler {
|
|
|
1189
1171
|
this.update_next(next_again, next_hard, next_good, next_easy);
|
|
1190
1172
|
return this.next.get(grade);
|
|
1191
1173
|
}
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
1,
|
|
1202
|
-
10
|
|
1203
|
-
);
|
|
1204
|
-
next_hard.stability = this.algorithm.init_stability(Rating.Hard);
|
|
1205
|
-
next_good.difficulty = clamp(
|
|
1206
|
-
this.algorithm.init_difficulty(Rating.Good),
|
|
1207
|
-
1,
|
|
1208
|
-
10
|
|
1209
|
-
);
|
|
1210
|
-
next_good.stability = this.algorithm.init_stability(Rating.Good);
|
|
1211
|
-
next_easy.difficulty = clamp(
|
|
1212
|
-
this.algorithm.init_difficulty(Rating.Easy),
|
|
1213
|
-
1,
|
|
1214
|
-
10
|
|
1174
|
+
next_ds(t, g, r) {
|
|
1175
|
+
const next_state = this.algorithm.next_state(
|
|
1176
|
+
{
|
|
1177
|
+
difficulty: this.current.difficulty,
|
|
1178
|
+
stability: this.current.stability
|
|
1179
|
+
},
|
|
1180
|
+
t,
|
|
1181
|
+
g,
|
|
1182
|
+
r
|
|
1215
1183
|
);
|
|
1216
|
-
|
|
1184
|
+
const card = TypeConvert.card(this.current);
|
|
1185
|
+
card.difficulty = next_state.difficulty;
|
|
1186
|
+
card.stability = next_state.stability;
|
|
1187
|
+
return card;
|
|
1217
1188
|
}
|
|
1218
1189
|
/**
|
|
1219
1190
|
* @see https://github.com/open-spaced-repetition/ts-fsrs/issues/98#issuecomment-2241923194
|
|
@@ -1227,72 +1198,20 @@ class LongTermScheduler extends AbstractScheduler {
|
|
|
1227
1198
|
return exist;
|
|
1228
1199
|
}
|
|
1229
1200
|
const interval = this.elapsed_days;
|
|
1230
|
-
const
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
const next_hard = TypeConvert.card(this.current);
|
|
1234
|
-
const next_good = TypeConvert.card(this.current);
|
|
1235
|
-
const next_easy = TypeConvert.card(this.current);
|
|
1236
|
-
this.next_ds(
|
|
1237
|
-
next_again,
|
|
1238
|
-
next_hard,
|
|
1239
|
-
next_good,
|
|
1240
|
-
next_easy,
|
|
1241
|
-
difficulty,
|
|
1242
|
-
stability,
|
|
1243
|
-
retrievability
|
|
1201
|
+
const retrievability = this.algorithm.forgetting_curve(
|
|
1202
|
+
interval,
|
|
1203
|
+
this.current.stability
|
|
1244
1204
|
);
|
|
1205
|
+
const next_again = this.next_ds(interval, Rating.Again, retrievability);
|
|
1206
|
+
const next_hard = this.next_ds(interval, Rating.Hard, retrievability);
|
|
1207
|
+
const next_good = this.next_ds(interval, Rating.Good, retrievability);
|
|
1208
|
+
const next_easy = this.next_ds(interval, Rating.Easy, retrievability);
|
|
1245
1209
|
this.next_interval(next_again, next_hard, next_good, next_easy, interval);
|
|
1246
1210
|
this.next_state(next_again, next_hard, next_good, next_easy);
|
|
1247
1211
|
next_again.lapses += 1;
|
|
1248
1212
|
this.update_next(next_again, next_hard, next_good, next_easy);
|
|
1249
1213
|
return this.next.get(grade);
|
|
1250
1214
|
}
|
|
1251
|
-
/**
|
|
1252
|
-
* Review next_ds
|
|
1253
|
-
*/
|
|
1254
|
-
next_ds(next_again, next_hard, next_good, next_easy, difficulty, stability, retrievability) {
|
|
1255
|
-
next_again.difficulty = this.algorithm.next_difficulty(
|
|
1256
|
-
difficulty,
|
|
1257
|
-
Rating.Again
|
|
1258
|
-
);
|
|
1259
|
-
const s_after_fail = this.algorithm.next_forget_stability(
|
|
1260
|
-
difficulty,
|
|
1261
|
-
stability,
|
|
1262
|
-
retrievability
|
|
1263
|
-
);
|
|
1264
|
-
next_again.stability = clamp(stability, S_MIN, s_after_fail);
|
|
1265
|
-
next_hard.difficulty = this.algorithm.next_difficulty(
|
|
1266
|
-
difficulty,
|
|
1267
|
-
Rating.Hard
|
|
1268
|
-
);
|
|
1269
|
-
next_hard.stability = this.algorithm.next_recall_stability(
|
|
1270
|
-
difficulty,
|
|
1271
|
-
stability,
|
|
1272
|
-
retrievability,
|
|
1273
|
-
Rating.Hard
|
|
1274
|
-
);
|
|
1275
|
-
next_good.difficulty = this.algorithm.next_difficulty(
|
|
1276
|
-
difficulty,
|
|
1277
|
-
Rating.Good
|
|
1278
|
-
);
|
|
1279
|
-
next_good.stability = this.algorithm.next_recall_stability(
|
|
1280
|
-
difficulty,
|
|
1281
|
-
stability,
|
|
1282
|
-
retrievability,
|
|
1283
|
-
Rating.Good
|
|
1284
|
-
);
|
|
1285
|
-
next_easy.difficulty = this.algorithm.next_difficulty(
|
|
1286
|
-
difficulty,
|
|
1287
|
-
Rating.Easy
|
|
1288
|
-
);
|
|
1289
|
-
next_easy.stability = this.algorithm.next_recall_stability(
|
|
1290
|
-
difficulty,
|
|
1291
|
-
stability,
|
|
1292
|
-
retrievability,
|
|
1293
|
-
Rating.Easy
|
|
1294
|
-
);
|
|
1295
|
-
}
|
|
1296
1215
|
/**
|
|
1297
1216
|
* Review/New next_interval
|
|
1298
1217
|
*/
|
|
@@ -1936,5 +1855,5 @@ const fsrs = (params) => {
|
|
|
1936
1855
|
return new FSRS(params || {});
|
|
1937
1856
|
};
|
|
1938
1857
|
|
|
1939
|
-
export { AbstractScheduler, BasicLearningStepsStrategy, CLAMP_PARAMETERS, ConvertStepUnitToMinutes, DefaultInitSeedStrategy, FSRS, FSRS5_DEFAULT_DECAY, FSRS6_DEFAULT_DECAY, FSRSAlgorithm, FSRSVersion, GenSeedStrategyWithCardId, Grades, INIT_S_MAX, Rating, S_MAX, S_MIN, State, StrategyMode, TypeConvert, W17_W18_Ceiling, checkParameters, clamp, clipParameters, computeDecayFactor, createEmptyCard, dateDiffInDays, date_diff, date_scheduler, default_enable_fuzz, default_enable_short_term, default_learning_steps, default_maximum_interval, default_relearning_steps, default_request_retention, default_w, fixDate, fixRating, fixState, forgetting_curve, formatDate, fsrs, generatorParameters, get_fuzz_range, migrateParameters, show_diff_message };
|
|
1858
|
+
export { AbstractScheduler, BasicLearningStepsStrategy, CLAMP_PARAMETERS, ConvertStepUnitToMinutes, DefaultInitSeedStrategy, FSRS, FSRS5_DEFAULT_DECAY, FSRS6_DEFAULT_DECAY, FSRSAlgorithm, FSRSVersion, GenSeedStrategyWithCardId, Grades, INIT_S_MAX, Rating, S_MAX, S_MIN, State, StrategyMode, TypeConvert, W17_W18_Ceiling, checkParameters, clamp, clipParameters, computeDecayFactor, createEmptyCard, dateDiffInDays, date_diff, date_scheduler, default_enable_fuzz, default_enable_short_term, default_learning_steps, default_maximum_interval, default_relearning_steps, default_request_retention, default_w, fixDate, fixRating, fixState, forgetting_curve, formatDate, fsrs, generatorParameters, get_fuzz_range, migrateParameters, roundTo, show_diff_message };
|
|
1940
1859
|
//# sourceMappingURL=index.mjs.map
|