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