ts-fsrs 5.0.1 → 5.2.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.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +63 -242
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +1 -1
- package/dist/index.umd.js.map +1 -1
- package/package.json +7 -7
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var h=(s=>(s[s.New=0]="New",s[s.Learning=1]="Learning",s[s.Review=2]="Review",s[s.Relearning=3]="Relearning",s))(h||{}),l=(s=>(s[s.Manual=0]="Manual",s[s.Again=1]="Again",s[s.Hard=2]="Hard",s[s.Good=3]="Good",s[s.Easy=4]="Easy",s))(l||{});class o{static card(t){return{...t,state:o.state(t.state),due:o.time(t.due),last_review:t.last_review?o.time(t.last_review):void 0}}static rating(t){if(typeof t=="string"){const e=t.charAt(0).toUpperCase(),i=t.slice(1).toLowerCase(),r=l[`${e}${i}`];if(r===void 0)throw new Error(`Invalid rating:[${t}]`);return r}else if(typeof t=="number")return t;throw new Error(`Invalid rating:[${t}]`)}static state(t){if(typeof t=="string"){const e=t.charAt(0).toUpperCase(),i=t.slice(1).toLowerCase(),r=h[`${e}${i}`];if(r===void 0)throw new Error(`Invalid state:[${t}]`);return r}else if(typeof t=="number")return t;throw new Error(`Invalid state:[${t}]`)}static time(t){if(typeof t=="object"&&t instanceof Date)return t;if(typeof t=="string"){const e=Date.parse(t);if(isNaN(e))throw new Error(`Invalid date:[${t}]`);return new Date(e)}else if(typeof t=="number")return new Date(t);throw new Error(`Invalid date:[${t}]`)}static review_log(t){return{...t,due:o.time(t.due),rating:o.rating(t.rating),state:o.state(t.state),review:o.time(t.review)}}}Date.prototype.scheduler=function(s,t){return H(this,s,t)},Date.prototype.diff=function(s,t){return C(this,s,t)},Date.prototype.format=function(){return G(this)},Date.prototype.dueFormat=function(s,t,e){return T(this,s,t,e)};function H(s,t,e){return new Date(e?o.time(s).getTime()+t*24*60*60*1e3:o.time(s).getTime()+t*60*1e3)}function C(s,t,e){if(!s||!t)throw new Error("Invalid date");const i=o.time(s).getTime()-o.time(t).getTime();let r=0;switch(e){case"days":r=Math.floor(i/(24*60*60*1e3));break;case"minutes":r=Math.floor(i/(60*1e3));break}return r}function G(s){const t=o.time(s),e=t.getFullYear(),i=t.getMonth()+1,r=t.getDate(),a=t.getHours(),n=t.getMinutes(),d=t.getSeconds();return`${e}-${v(i)}-${v(r)} ${v(a)}:${v(n)}:${v(d)}`}function v(s){return s<10?`0${s}`:`${s}`}const A=[60,60,24,31,12],F=["second","min","hour","day","month","year"];function T(s,t,e,i=F){s=o.time(s),t=o.time(t),i.length!==F.length&&(i=F);let r=s.getTime()-t.getTime(),a;for(r/=1e3,a=0;a<A.length&&!(r<A[a]);a++)r/=A[a];return`${Math.floor(r)}${e?i[a]:""}`}function rt(s){return o.time(s)}function at(s){return o.state(s)}function st(s){return o.rating(s)}const z=Object.freeze([l.Again,l.Hard,l.Good,l.Easy]),nt=[{start:2.5,end:7,factor:.15},{start:7,end:20,factor:.1},{start:20,end:1/0,factor:.05}];function U(s,t,e){let i=1;for(const n of nt)i+=n.factor*Math.max(Math.min(s,n.end)-n.start,0);s=Math.min(s,e);let r=Math.max(2,Math.round(s-i));const a=Math.min(Math.round(s+i),e);return s>t&&(r=Math.max(r,t+1)),r=Math.min(r,a),{min_ivl:r,max_ivl:a}}function y(s,t,e){return Math.min(Math.max(s,t),e)}function P(s,t){const e=Date.UTC(s.getUTCFullYear(),s.getUTCMonth(),s.getUTCDate()),i=Date.UTC(t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate());return Math.floor((i-e)/864e5)}const lt="5.0.1",k=.9,q=36500,Y=!1,j=!0,O=Object.freeze(["1m","10m"]),W=Object.freeze(["10m"]),dt=`v${lt} using FSRS-6.0`,m=.001,ot=36500,x=100,D=.5,X=.2,L=Object.freeze([.2172,1.1771,3.2602,16.1507,7.0114,.57,2.0966,.0069,1.5261,.112,1.0178,1.849,.1133,.3127,2.2934,.2191,3.0004,.7536,.3332,.1437,X]),B=2,V=s=>[[m,x],[m,x],[m,x],[m,x],[1,10],[.001,4],[.001,4],[.001,.75],[0,4.5],[0,.8],[.001,3.5],[.001,5],[.001,.25],[.001,.9],[0,4],[0,1],[1,6],[0,s],[0,s],[0,.8],[.1,.8]],S=(s,t)=>{let e=B;if(Math.max(0,t)>1){const i=-(Math.log(s[11])+Math.log(Math.pow(2,s[13])-1)+s[14]*.3)/t;e=y(+i.toFixed(8),.01,2)}return V(e).map(([i,r],a)=>y(s[a],i,r))},ut=s=>{if(s.find(t=>!isFinite(t)&&!isNaN(t))!==void 0)throw Error(`Non-finite or NaN value in parameters ${s}`);if(![17,19,21].includes(s.length))throw Error(`Invalid parameter length: ${s.length}. Must be 17, 19 or 21 for FSRSv4, 5 and 6 respectively.`);return s},M=s=>{if(s===void 0)return[...L];switch(s.length){case 21:return[...s];case 19:return console.debug("[FSRS-6]auto fill w from 19 to 21 length"),[...s,0,D];case 17:{const t=[...s];return t[4]=+(t[5]*2+t[4]).toFixed(8),t[5]=+(Math.log(t[5]*3+1)/3).toFixed(8),t[6]=+(t[6]+.5).toFixed(8),console.debug("[FSRS-6]auto fill w from 17 to 21 length"),t.concat([0,0,0,D])}default:return console.warn("[FSRS]Invalid parameters length, using default parameters"),[...L]}},N=s=>{const t=Array.isArray(s?.learning_steps)?s.learning_steps:O,e=Array.isArray(s?.relearning_steps)?s.relearning_steps:W,i=S(M(s?.w),e.length);return{request_retention:s?.request_retention||k,maximum_interval:s?.maximum_interval||q,w:i,enable_fuzz:s?.enable_fuzz??Y,enable_short_term:s?.enable_short_term??j,learning_steps:t,relearning_steps:e}};function E(s,t){const e={due:s?o.time(s):new Date,stability:0,difficulty:0,elapsed_days:0,scheduled_days:0,reps:0,lapses:0,learning_steps:0,state:h.New,last_review:void 0};return t&&typeof t=="function"?t(e):e}class ht{c;s0;s1;s2;constructor(t){const e=ct();this.c=1,this.s0=e(" "),this.s1=e(" "),this.s2=e(" "),t==null&&(t=+new Date),this.s0-=e(t),this.s0<0&&(this.s0+=1),this.s1-=e(t),this.s1<0&&(this.s1+=1),this.s2-=e(t),this.s2<0&&(this.s2+=1)}next(){const t=2091639*this.s0+this.c*23283064365386963e-26;return this.s0=this.s1,this.s1=this.s2,this.s2=t-(this.c=t|0),this.s2}set state(t){this.c=t.c,this.s0=t.s0,this.s1=t.s1,this.s2=t.s2}get state(){return{c:this.c,s0:this.s0,s1:this.s1,s2:this.s2}}}function ct(){let s=4022871197;return function(t){t=String(t);for(let e=0;e<t.length;e++){s+=t.charCodeAt(e);let i=.02519603282416938*s;s=i>>>0,i-=s,i*=s,s=i>>>0,i-=s,s+=i*4294967296}return(s>>>0)*23283064365386963e-26}}function _t(s){const t=new ht(s),e=()=>t.next();return e.int32=()=>t.next()*4294967296|0,e.double=()=>e()+(e()*2097152|0)*11102230246251565e-32,e.state=()=>t.state,e.importState=i=>(t.state=i,e),e}const I=s=>{const t=typeof s=="number"?-s:-s[20],e=Math.exp(Math.pow(t,-1)*Math.log(.9))-1;return{decay:t,factor:+e.toFixed(8)}};function R(s,t,e){const{decay:i,factor:r}=I(s);return+Math.pow(1+r*t/e,i).toFixed(8)}class J{param;intervalModifier;_seed;constructor(t){this.param=new Proxy(N(t),this.params_handler_proxy()),this.intervalModifier=this.calculate_interval_modifier(this.param.request_retention),this.forgetting_curve=R.bind(this,this.param.w)}get interval_modifier(){return this.intervalModifier}set seed(t){this._seed=t}calculate_interval_modifier(t){if(t<=0||t>1)throw new Error("Requested retention rate should be in the range (0,1]");const{decay:e,factor:i}=I(this.param.w);return+((Math.pow(t,1/e)-1)/i).toFixed(8)}get parameters(){return this.param}set parameters(t){this.update_parameters(t)}params_handler_proxy(){const t=this;return{set:function(e,i,r){return i==="request_retention"&&Number.isFinite(r)?t.intervalModifier=t.calculate_interval_modifier(Number(r)):i==="w"&&(r=S(M(r),e.relearning_steps.length),t.forgetting_curve=R.bind(this,r),t.intervalModifier=t.calculate_interval_modifier(Number(e.request_retention))),Reflect.set(e,i,r),!0}}}update_parameters(t){const e=N(t);for(const i in e)if(i in this.param){const r=i;this.param[r]=e[r]}}init_stability(t){return Math.max(this.param.w[t-1],.1)}init_difficulty(t){const e=this.param.w[4]-Math.exp((t-1)*this.param.w[5])+1;return y(+e.toFixed(8),1,10)}apply_fuzz(t,e){if(!this.param.enable_fuzz||t<2.5)return Math.round(t);const i=_t(this._seed)(),{min_ivl:r,max_ivl:a}=U(t,e,this.param.maximum_interval);return Math.floor(i*(a-r+1)+r)}next_interval(t,e){const i=Math.min(Math.max(1,Math.round(t*this.intervalModifier)),this.param.maximum_interval);return this.apply_fuzz(i,e)}linear_damping(t,e){return+(t*(10-e)/9).toFixed(8)}next_difficulty(t,e){const i=-this.param.w[6]*(e-3),r=t+this.linear_damping(i,t);return y(this.mean_reversion(this.init_difficulty(l.Easy),r),1,10)}mean_reversion(t,e){return+(this.param.w[7]*t+(1-this.param.w[7])*e).toFixed(8)}next_recall_stability(t,e,i,r){const a=l.Hard===r?this.param.w[15]:1,n=l.Easy===r?this.param.w[16]:1;return+y(e*(1+Math.exp(this.param.w[8])*(11-t)*Math.pow(e,-this.param.w[9])*(Math.exp((1-i)*this.param.w[10])-1)*a*n),m,36500).toFixed(8)}next_forget_stability(t,e,i){return+y(this.param.w[11]*Math.pow(t,-this.param.w[12])*(Math.pow(e+1,this.param.w[13])-1)*Math.exp((1-i)*this.param.w[14]),m,36500).toFixed(8)}next_short_term_stability(t,e){const i=Math.pow(t,-this.param.w[19])*Math.exp(this.param.w[17]*(e-3+this.param.w[18])),r=e>=3?Math.max(i,1):i;return+y(t*r,m,36500).toFixed(8)}forgetting_curve;next_state(t,e,i){const{difficulty:r,stability:a}=t??{difficulty:0,stability:0};if(e<0)throw new Error(`Invalid delta_t "${e}"`);if(i<0||i>4)throw new Error(`Invalid grade "${i}"`);if(r===0&&a===0)return{difficulty:this.init_difficulty(i),stability:this.init_stability(i)};if(i===0)return{difficulty:r,stability:a};if(r<1||a<m)throw new Error(`Invalid memory state { difficulty: ${r}, stability: ${a} }`);const n=this.forgetting_curve(e,a),d=this.next_recall_stability(r,a,n,i),u=this.next_forget_stability(r,a,n),c=this.next_short_term_stability(a,i);let _=d;if(i===1){let[g,p]=[0,0];this.param.enable_short_term&&(g=this.param.w[17],p=this.param.w[18]);const f=a/Math.exp(g*p);_=y(+f.toFixed(8),m,u)}return e===0&&this.param.enable_short_term&&(_=c),{difficulty:this.next_difficulty(r,i),stability:_}}}function K(){const s=this.review_time.getTime(),t=this.current.reps,e=this.current.difficulty*this.current.stability;return`${s}_${t}_${e}`}function ft(s){return function(){const t=Reflect.get(this.current,s)??0,e=this.current.reps;return String(t+e||0)}}const Q=s=>{const t=s.slice(-1),e=parseInt(s.slice(0,-1),10);if(isNaN(e)||!Number.isFinite(e)||e<0)throw new Error(`Invalid step value: ${s}`);switch(t){case"m":return e;case"h":return e*60;case"d":return e*1440;default:throw new Error(`Invalid step unit: ${s}, expected m/h/d`)}},Z=(s,t,e)=>{const i=t===h.Relearning||t===h.Review?s.relearning_steps:s.learning_steps,r=i.length;if(r===0||e>=r)return{};const a=i[0],n=Q,d=()=>n(a),u=()=>{if(r===1)return Math.round(n(a)*1.5);const f=i[1];return Math.round((n(a)+n(f))/2)},c=f=>f<0||f>=r?null:i[f],_=f=>n(f),g={},p=c(Math.max(0,e));if(t===h.Review)return g[l.Again]={scheduled_minutes:n(p),next_step:0},g;{g[l.Again]={scheduled_minutes:d(),next_step:0},g[l.Hard]={scheduled_minutes:u(),next_step:e};const f=c(e+1);if(f){const w=_(f);w&&(g[l.Good]={scheduled_minutes:Math.round(w),next_step:e+1})}}return g};var b=(s=>(s.SCHEDULER="Scheduler",s.LEARNING_STEPS="LearningSteps",s.SEED="Seed",s))(b||{});class ${last;current;review_time;next=new Map;algorithm;strategies;constructor(t,e,i,r){this.algorithm=i,this.last=o.card(t),this.current=o.card(t),this.review_time=o.time(e),this.strategies=r,this.init()}checkGrade(t){if(!Number.isFinite(t)||t<0||t>4)throw new Error(`Invalid grade "${t}",expected 1-4`)}init(){const{state:t,last_review:e}=this.current;let i=0;t!==h.New&&e&&(i=P(e,this.review_time)),this.current.last_review=this.review_time,this.current.elapsed_days=i,this.current.reps+=1;let r=K;if(this.strategies){const a=this.strategies.get(b.SEED);a&&(r=a)}this.algorithm.seed=r.call(this)}preview(){return{[l.Again]:this.review(l.Again),[l.Hard]:this.review(l.Hard),[l.Good]:this.review(l.Good),[l.Easy]:this.review(l.Easy),[Symbol.iterator]:this.previewIterator.bind(this)}}*previewIterator(){for(const t of z)yield this.review(t)}review(t){const{state:e}=this.last;let i;switch(this.checkGrade(t),e){case h.New:i=this.newState(t);break;case h.Learning:case h.Relearning:i=this.learningState(t);break;case h.Review:i=this.reviewState(t);break}return i}buildLog(t){const{last_review:e,due:i,elapsed_days:r}=this.last;return{rating:t,state:this.current.state,due:e||i,stability:this.current.stability,difficulty:this.current.difficulty,elapsed_days:this.current.elapsed_days,last_elapsed_days:r,scheduled_days:this.current.scheduled_days,learning_steps:this.current.learning_steps,review:this.review_time}}}class tt extends ${learningStepsStrategy;constructor(t,e,i,r){super(t,e,i,r);let a=Z;if(this.strategies){const n=this.strategies.get(b.LEARNING_STEPS);n&&(a=n)}this.learningStepsStrategy=a}getLearningInfo(t,e){const i=this.algorithm.parameters;t.learning_steps=t.learning_steps||0;const r=this.learningStepsStrategy(i,t.state,this.current.state===h.Learning?t.learning_steps+1:t.learning_steps),a=Math.max(0,r[e]?.scheduled_minutes??0),n=Math.max(0,r[e]?.next_step??0);return{scheduled_minutes:a,next_steps:n}}applyLearningSteps(t,e,i){const{scheduled_minutes:r,next_steps:a}=this.getLearningInfo(this.current,e);if(r>0&&r<1440)t.learning_steps=a,t.scheduled_days=0,t.state=i,t.due=this.review_time.scheduler(Math.round(r),!1);else if(t.state=h.Review,r>=1440)t.learning_steps=a,t.due=this.review_time.scheduler(Math.round(r),!1),t.scheduled_days=Math.floor(r/1440);else{t.learning_steps=0;const n=this.algorithm.next_interval(t.stability,this.current.elapsed_days);t.scheduled_days=n,t.due=this.review_time.scheduler(n,!0)}}newState(t){const e=this.next.get(t);if(e)return e;const i=o.card(this.current);i.difficulty=this.algorithm.init_difficulty(t),i.stability=this.algorithm.init_stability(t),this.applyLearningSteps(i,t,h.Learning);const r={card:i,log:this.buildLog(t)};return this.next.set(t,r),r}learningState(t){const e=this.next.get(t);if(e)return e;const{state:i,difficulty:r,stability:a}=this.last,n=o.card(this.current);n.difficulty=this.algorithm.next_difficulty(r,t),n.stability=this.algorithm.next_short_term_stability(a,t),this.applyLearningSteps(n,t,i);const d={card:n,log:this.buildLog(t)};return this.next.set(t,d),d}reviewState(t){const e=this.next.get(t);if(e)return e;const i=this.current.elapsed_days,{difficulty:r,stability:a}=this.last,n=this.algorithm.forgetting_curve(i,a),d=o.card(this.current),u=o.card(this.current),c=o.card(this.current),_=o.card(this.current);this.next_ds(d,u,c,_,r,a,n),this.next_interval(u,c,_,i),this.next_state(u,c,_),this.applyLearningSteps(d,l.Again,h.Relearning),d.lapses+=1;const g={card:d,log:this.buildLog(l.Again)},p={card:u,log:super.buildLog(l.Hard)},f={card:c,log:super.buildLog(l.Good)},w={card:_,log:super.buildLog(l.Easy)};return this.next.set(l.Again,g),this.next.set(l.Hard,p),this.next.set(l.Good,f),this.next.set(l.Easy,w),this.next.get(t)}next_ds(t,e,i,r,a,n,d){t.difficulty=this.algorithm.next_difficulty(a,l.Again);const u=n/Math.exp(this.algorithm.parameters.w[17]*this.algorithm.parameters.w[18]),c=this.algorithm.next_forget_stability(a,n,d);t.stability=y(+u.toFixed(8),m,c),e.difficulty=this.algorithm.next_difficulty(a,l.Hard),e.stability=this.algorithm.next_recall_stability(a,n,d,l.Hard),i.difficulty=this.algorithm.next_difficulty(a,l.Good),i.stability=this.algorithm.next_recall_stability(a,n,d,l.Good),r.difficulty=this.algorithm.next_difficulty(a,l.Easy),r.stability=this.algorithm.next_recall_stability(a,n,d,l.Easy)}next_interval(t,e,i,r){let a,n;a=this.algorithm.next_interval(t.stability,r),n=this.algorithm.next_interval(e.stability,r),a=Math.min(a,n),n=Math.max(n,a+1);const d=Math.max(this.algorithm.next_interval(i.stability,r),n+1);t.scheduled_days=a,t.due=this.review_time.scheduler(a,!0),e.scheduled_days=n,e.due=this.review_time.scheduler(n,!0),i.scheduled_days=d,i.due=this.review_time.scheduler(d,!0)}next_state(t,e,i){t.state=h.Review,t.learning_steps=0,e.state=h.Review,e.learning_steps=0,i.state=h.Review,i.learning_steps=0}}class et extends ${newState(t){const e=this.next.get(t);if(e)return e;this.current.scheduled_days=0,this.current.elapsed_days=0;const i=o.card(this.current),r=o.card(this.current),a=o.card(this.current),n=o.card(this.current);return this.init_ds(i,r,a,n),this.next_interval(i,r,a,n,0),this.next_state(i,r,a,n),this.update_next(i,r,a,n),this.next.get(t)}init_ds(t,e,i,r){t.difficulty=this.algorithm.init_difficulty(l.Again),t.stability=this.algorithm.init_stability(l.Again),e.difficulty=this.algorithm.init_difficulty(l.Hard),e.stability=this.algorithm.init_stability(l.Hard),i.difficulty=this.algorithm.init_difficulty(l.Good),i.stability=this.algorithm.init_stability(l.Good),r.difficulty=this.algorithm.init_difficulty(l.Easy),r.stability=this.algorithm.init_stability(l.Easy)}learningState(t){return this.reviewState(t)}reviewState(t){const e=this.next.get(t);if(e)return e;const i=this.current.elapsed_days,{difficulty:r,stability:a}=this.last,n=this.algorithm.forgetting_curve(i,a),d=o.card(this.current),u=o.card(this.current),c=o.card(this.current),_=o.card(this.current);return this.next_ds(d,u,c,_,r,a,n),this.next_interval(d,u,c,_,i),this.next_state(d,u,c,_),d.lapses+=1,this.update_next(d,u,c,_),this.next.get(t)}next_ds(t,e,i,r,a,n,d){t.difficulty=this.algorithm.next_difficulty(a,l.Again);const u=this.algorithm.next_forget_stability(a,n,d);t.stability=y(n,m,u),e.difficulty=this.algorithm.next_difficulty(a,l.Hard),e.stability=this.algorithm.next_recall_stability(a,n,d,l.Hard),i.difficulty=this.algorithm.next_difficulty(a,l.Good),i.stability=this.algorithm.next_recall_stability(a,n,d,l.Good),r.difficulty=this.algorithm.next_difficulty(a,l.Easy),r.stability=this.algorithm.next_recall_stability(a,n,d,l.Easy)}next_interval(t,e,i,r,a){let n,d,u,c;n=this.algorithm.next_interval(t.stability,a),d=this.algorithm.next_interval(e.stability,a),u=this.algorithm.next_interval(i.stability,a),c=this.algorithm.next_interval(r.stability,a),n=Math.min(n,d),d=Math.max(d,n+1),u=Math.max(u,d+1),c=Math.max(c,u+1),t.scheduled_days=n,t.due=this.review_time.scheduler(n,!0),e.scheduled_days=d,e.due=this.review_time.scheduler(d,!0),i.scheduled_days=u,i.due=this.review_time.scheduler(u,!0),r.scheduled_days=c,r.due=this.review_time.scheduler(c,!0)}next_state(t,e,i,r){t.state=h.Review,t.learning_steps=0,e.state=h.Review,e.learning_steps=0,i.state=h.Review,i.learning_steps=0,r.state=h.Review,r.learning_steps=0}update_next(t,e,i,r){const a={card:t,log:this.buildLog(l.Again)},n={card:e,log:super.buildLog(l.Hard)},d={card:i,log:super.buildLog(l.Good)},u={card:r,log:super.buildLog(l.Easy)};this.next.set(l.Again,a),this.next.set(l.Hard,n),this.next.set(l.Good,d),this.next.set(l.Easy,u)}}class gt{fsrs;constructor(t){this.fsrs=t}replay(t,e,i){return this.fsrs.next(t,e,i)}handleManualRating(t,e,i,r,a,n,d){if(typeof e>"u")throw new Error("reschedule: state is required for manual rating");let u,c;if(e===h.New)u={rating:l.Manual,state:e,due:d??i,stability:t.stability,difficulty:t.difficulty,elapsed_days:r,last_elapsed_days:t.elapsed_days,scheduled_days:t.scheduled_days,learning_steps:t.learning_steps,review:i},c=E(i),c.last_review=i;else{if(typeof d>"u")throw new Error("reschedule: due is required for manual rating");const _=d.diff(i,"days");u={rating:l.Manual,state:t.state,due:t.last_review||t.due,stability:t.stability,difficulty:t.difficulty,elapsed_days:r,last_elapsed_days:t.elapsed_days,scheduled_days:t.scheduled_days,learning_steps:t.learning_steps,review:i},c={...t,state:e,due:d,last_review:i,stability:a||t.stability,difficulty:n||t.difficulty,elapsed_days:r,scheduled_days:_,reps:t.reps+1}}return{card:c,log:u}}reschedule(t,e){const i=[];let r=E(t.due);for(const a of e){let n;if(a.review=o.time(a.review),a.rating===l.Manual){let d=0;r.state!==h.New&&r.last_review&&(d=a.review.diff(r.last_review,"days")),n=this.handleManualRating(r,a.state,a.review,d,a.stability,a.difficulty,a.due?o.time(a.due):void 0)}else n=this.replay(r,a.review,a.rating);i.push(n),r=n.card}return i}calculateManualRecord(t,e,i,r){if(!i)return null;const{card:a,log:n}=i,d=o.card(t);return d.due.getTime()===a.due.getTime()?null:(d.scheduled_days=a.due.diff(d.due,"days"),this.handleManualRating(d,a.state,o.time(e),n.elapsed_days,r?a.stability:void 0,r?a.difficulty:void 0,a.due))}}class it extends J{strategyHandler=new Map;Scheduler;constructor(t){super(t);const{enable_short_term:e}=this.parameters;this.Scheduler=e?tt:et}params_handler_proxy(){const t=this;return{set:function(e,i,r){return i==="request_retention"&&Number.isFinite(r)?t.intervalModifier=t.calculate_interval_modifier(Number(r)):i==="enable_short_term"?t.Scheduler=r===!0?tt:et:i==="w"&&(r=S(M(r),e.relearning_steps.length),t.forgetting_curve=R.bind(this,r),t.intervalModifier=t.calculate_interval_modifier(Number(e.request_retention))),Reflect.set(e,i,r),!0}}}useStrategy(t,e){return this.strategyHandler.set(t,e),this}clearStrategy(t){return t?this.strategyHandler.delete(t):this.strategyHandler.clear(),this}getScheduler(t,e){const i=this.strategyHandler.get(b.SCHEDULER)||this.Scheduler;return new i(t,e,this,this.strategyHandler)}repeat(t,e,i){const r=this.getScheduler(t,e).preview();return i&&typeof i=="function"?i(r):r}next(t,e,i,r){const a=this.getScheduler(t,e),n=o.rating(i);if(n===l.Manual)throw new Error("Cannot review a manual rating");const d=a.review(n);return r&&typeof r=="function"?r(d):d}get_retrievability(t,e,i=!0){const r=o.card(t);e=e?o.time(e):new Date;const a=r.state!==h.New?Math.max(e.diff(r.last_review,"days"),0):0,n=r.state!==h.New?this.forgetting_curve(a,+r.stability.toFixed(8)):0;return i?`${(n*100).toFixed(2)}%`:n}rollback(t,e,i){const r=o.card(t),a=o.review_log(e);if(a.rating===l.Manual)throw new Error("Cannot rollback a manual rating");let n,d,u;switch(a.state){case h.New:n=a.due,d=void 0,u=0;break;case h.Learning:case h.Relearning:case h.Review:n=a.review,d=a.due,u=r.lapses-(a.rating===l.Again&&a.state===h.Review?1:0);break}const c={...r,due:n,stability:a.stability,difficulty:a.difficulty,elapsed_days:a.last_elapsed_days,scheduled_days:a.scheduled_days,reps:Math.max(0,r.reps-1),lapses:Math.max(0,u),learning_steps:a.learning_steps,state:a.state,last_review:d};return i&&typeof i=="function"?i(c):c}forget(t,e,i=!1,r){const a=o.card(t);e=o.time(e);const n=a.state===h.New?0:e.diff(a.last_review,"days"),d={rating:l.Manual,state:a.state,due:a.due,stability:a.stability,difficulty:a.difficulty,elapsed_days:0,last_elapsed_days:a.elapsed_days,scheduled_days:n,learning_steps:a.learning_steps,review:e},u={card:{...a,due:e,stability:0,difficulty:0,elapsed_days:0,scheduled_days:0,reps:i?0:a.reps,lapses:i?0:a.lapses,learning_steps:0,state:h.New,last_review:a.last_review},log:d};return r&&typeof r=="function"?r(u):u}reschedule(t,e=[],i={}){const{recordLogHandler:r,reviewsOrderBy:a,skipManual:n=!0,now:d=new Date,update_memory_state:u=!1}=i;a&&typeof a=="function"&&e.sort(a),n&&(e=e.filter(w=>w.rating!==l.Manual));const c=new gt(this),_=c.reschedule(i.first_card||E(),e),g=_.length,p=o.card(t),f=c.calculateManualRecord(p,d,g?_[g-1]:void 0,u);return r&&typeof r=="function"?{collections:_.map(r),reschedule_item:f?r(f):null}:{collections:_,reschedule_item:f}}}const mt=s=>new it(s||{});exports.AbstractScheduler=$,exports.BasicLearningStepsStrategy=Z,exports.CLAMP_PARAMETERS=V,exports.ConvertStepUnitToMinutes=Q,exports.DefaultInitSeedStrategy=K,exports.FSRS=it,exports.FSRS5_DEFAULT_DECAY=D,exports.FSRS6_DEFAULT_DECAY=X,exports.FSRSAlgorithm=J,exports.FSRSVersion=dt,exports.GenSeedStrategyWithCardId=ft,exports.Grades=z,exports.INIT_S_MAX=x,exports.Rating=l,exports.S_MAX=ot,exports.S_MIN=m,exports.State=h,exports.StrategyMode=b,exports.TypeConvert=o,exports.W17_W18_Ceiling=B,exports.checkParameters=ut,exports.clamp=y,exports.clipParameters=S,exports.computeDecayFactor=I,exports.createEmptyCard=E,exports.dateDiffInDays=P,exports.date_diff=C,exports.date_scheduler=H,exports.default_enable_fuzz=Y,exports.default_enable_short_term=j,exports.default_learning_steps=O,exports.default_maximum_interval=q,exports.default_relearning_steps=W,exports.default_request_retention=k,exports.default_w=L,exports.fixDate=rt,exports.fixRating=st,exports.fixState=at,exports.forgetting_curve=R,exports.formatDate=G,exports.fsrs=mt,exports.generatorParameters=N,exports.get_fuzz_range=U,exports.migrateParameters=M,exports.show_diff_message=T,module.exports=Object.assign(exports.default||{},exports);
|
|
1
|
+
"use strict";var h=(a=>(a[a.New=0]="New",a[a.Learning=1]="Learning",a[a.Review=2]="Review",a[a.Relearning=3]="Relearning",a))(h||{}),l=(a=>(a[a.Manual=0]="Manual",a[a.Again=1]="Again",a[a.Hard=2]="Hard",a[a.Good=3]="Good",a[a.Easy=4]="Easy",a))(l||{});class o{static card(t){return{...t,state:o.state(t.state),due:o.time(t.due),last_review:t.last_review?o.time(t.last_review):void 0}}static rating(t){if(typeof t=="string"){const e=t.charAt(0).toUpperCase(),i=t.slice(1).toLowerCase(),r=l[`${e}${i}`];if(r===void 0)throw new Error(`Invalid rating:[${t}]`);return r}else if(typeof t=="number")return t;throw new Error(`Invalid rating:[${t}]`)}static state(t){if(typeof t=="string"){const e=t.charAt(0).toUpperCase(),i=t.slice(1).toLowerCase(),r=h[`${e}${i}`];if(r===void 0)throw new Error(`Invalid state:[${t}]`);return r}else if(typeof t=="number")return t;throw new Error(`Invalid state:[${t}]`)}static time(t){if(typeof t=="object"&&t instanceof Date)return t;if(typeof t=="string"){const e=Date.parse(t);if(isNaN(e))throw new Error(`Invalid date:[${t}]`);return new Date(e)}else if(typeof t=="number")return new Date(t);throw new Error(`Invalid date:[${t}]`)}static review_log(t){return{...t,due:o.time(t.due),rating:o.rating(t.rating),state:o.state(t.state),review:o.time(t.review)}}}Date.prototype.scheduler=function(a,t){return y(this,a,t)},Date.prototype.diff=function(a,t){return v(this,a,t)},Date.prototype.format=function(){return G(this)},Date.prototype.dueFormat=function(a,t,e){return T(this,a,t,e)};function y(a,t,e){return new Date(e?o.time(a).getTime()+t*24*60*60*1e3:o.time(a).getTime()+t*60*1e3)}function v(a,t,e){if(!a||!t)throw new Error("Invalid date");const i=o.time(a).getTime()-o.time(t).getTime();let r=0;switch(e){case"days":r=Math.floor(i/(24*60*60*1e3));break;case"minutes":r=Math.floor(i/(60*1e3));break}return r}function G(a){const t=o.time(a),e=t.getFullYear(),i=t.getMonth()+1,r=t.getDate(),s=t.getHours(),n=t.getMinutes(),d=t.getSeconds();return`${e}-${b(i)}-${b(r)} ${b(s)}:${b(n)}:${b(d)}`}function b(a){return a<10?`0${a}`:`${a}`}const D=[60,60,24,31,12],L=["second","min","hour","day","month","year"];function T(a,t,e,i=L){a=o.time(a),t=o.time(t),i.length!==L.length&&(i=L);let r=a.getTime()-t.getTime(),s;for(r/=1e3,s=0;s<D.length&&!(r<D[s]);s++)r/=D[s];return`${Math.floor(r)}${e?i[s]:""}`}function rt(a){return o.time(a)}function st(a){return o.state(a)}function at(a){return o.rating(a)}const z=Object.freeze([l.Again,l.Hard,l.Good,l.Easy]),nt=[{start:2.5,end:7,factor:.15},{start:7,end:20,factor:.1},{start:20,end:1/0,factor:.05}];function U(a,t,e){let i=1;for(const n of nt)i+=n.factor*Math.max(Math.min(a,n.end)-n.start,0);a=Math.min(a,e);let r=Math.max(2,Math.round(a-i));const s=Math.min(Math.round(a+i),e);return a>t&&(r=Math.max(r,t+1)),r=Math.min(r,s),{min_ivl:r,max_ivl:s}}function g(a,t,e){return Math.min(Math.max(a,t),e)}function P(a,t){const e=Date.UTC(a.getUTCFullYear(),a.getUTCMonth(),a.getUTCDate()),i=Date.UTC(t.getUTCFullYear(),t.getUTCMonth(),t.getUTCDate());return Math.floor((i-e)/864e5)}const lt="5.2.0",k=.9,q=36500,Y=!1,j=!0,O=Object.freeze(["1m","10m"]),W=Object.freeze(["10m"]),dt=`v${lt} using FSRS-6.0`,p=.001,ot=36500,M=100,N=.5,X=.1542,I=Object.freeze([.212,1.2931,2.3065,8.2956,6.4133,.8334,3.0194,.001,1.8722,.1666,.796,1.4835,.0614,.2629,1.6483,.6014,1.8729,.5425,.0912,.0658,X]),B=2,V=a=>[[p,M],[p,M],[p,M],[p,M],[1,10],[.001,4],[.001,4],[.001,.75],[0,4.5],[0,.8],[.001,3.5],[.001,5],[.001,.25],[.001,.9],[0,4],[0,1],[1,6],[0,a],[0,a],[0,.8],[.1,.8]],E=(a,t)=>{let e=B;if(Math.max(0,t)>1){const i=-(Math.log(a[11])+Math.log(Math.pow(2,a[13])-1)+a[14]*.3)/t;e=g(+i.toFixed(8),.01,2)}return V(e).map(([i,r],s)=>g(a[s],i,r))},ut=a=>{if(a.find(t=>!isFinite(t)&&!isNaN(t))!==void 0)throw Error(`Non-finite or NaN value in parameters ${a}`);if(![17,19,21].includes(a.length))throw Error(`Invalid parameter length: ${a.length}. Must be 17, 19 or 21 for FSRSv4, 5 and 6 respectively.`);return a},R=a=>{if(a===void 0)return[...I];switch(a.length){case 21:return[...a];case 19:return console.debug("[FSRS-6]auto fill w from 19 to 21 length"),[...a,0,N];case 17:{const t=[...a];return t[4]=+(t[5]*2+t[4]).toFixed(8),t[5]=+(Math.log(t[5]*3+1)/3).toFixed(8),t[6]=+(t[6]+.5).toFixed(8),console.debug("[FSRS-6]auto fill w from 17 to 21 length"),t.concat([0,0,0,N])}default:return console.warn("[FSRS]Invalid parameters length, using default parameters"),[...I]}},$=a=>{const t=Array.isArray(a?.learning_steps)?a.learning_steps:O,e=Array.isArray(a?.relearning_steps)?a.relearning_steps:W,i=E(R(a?.w),e.length);return{request_retention:a?.request_retention||k,maximum_interval:a?.maximum_interval||q,w:i,enable_fuzz:a?.enable_fuzz??Y,enable_short_term:a?.enable_short_term??j,learning_steps:t,relearning_steps:e}};function A(a,t){const e={due:a?o.time(a):new Date,stability:0,difficulty:0,elapsed_days:0,scheduled_days:0,reps:0,lapses:0,learning_steps:0,state:h.New,last_review:void 0};return t&&typeof t=="function"?t(e):e}class ht{c;s0;s1;s2;constructor(t){const e=ct();this.c=1,this.s0=e(" "),this.s1=e(" "),this.s2=e(" "),t==null&&(t=+new Date),this.s0-=e(t),this.s0<0&&(this.s0+=1),this.s1-=e(t),this.s1<0&&(this.s1+=1),this.s2-=e(t),this.s2<0&&(this.s2+=1)}next(){const t=2091639*this.s0+this.c*23283064365386963e-26;return this.s0=this.s1,this.s1=this.s2,this.s2=t-(this.c=t|0),this.s2}set state(t){this.c=t.c,this.s0=t.s0,this.s1=t.s1,this.s2=t.s2}get state(){return{c:this.c,s0:this.s0,s1:this.s1,s2:this.s2}}}function ct(){let a=4022871197;return function(t){t=String(t);for(let e=0;e<t.length;e++){a+=t.charCodeAt(e);let i=.02519603282416938*a;a=i>>>0,i-=a,i*=a,a=i>>>0,i-=a,a+=i*4294967296}return(a>>>0)*23283064365386963e-26}}function _t(a){const t=new ht(a),e=()=>t.next();return e.int32=()=>t.next()*4294967296|0,e.double=()=>e()+(e()*2097152|0)*11102230246251565e-32,e.state=()=>t.state,e.importState=i=>(t.state=i,e),e}const C=a=>{const t=typeof a=="number"?-a:-a[20],e=Math.exp(Math.pow(t,-1)*Math.log(.9))-1;return{decay:t,factor:+e.toFixed(8)}};function F(a,t,e){const{decay:i,factor:r}=C(a);return+Math.pow(1+r*t/e,i).toFixed(8)}class J{param;intervalModifier;_seed;constructor(t){this.param=new Proxy($(t),this.params_handler_proxy()),this.intervalModifier=this.calculate_interval_modifier(this.param.request_retention),this.forgetting_curve=F.bind(this,this.param.w)}get interval_modifier(){return this.intervalModifier}set seed(t){this._seed=t}calculate_interval_modifier(t){if(t<=0||t>1)throw new Error("Requested retention rate should be in the range (0,1]");const{decay:e,factor:i}=C(this.param.w);return+((Math.pow(t,1/e)-1)/i).toFixed(8)}get parameters(){return this.param}set parameters(t){this.update_parameters(t)}params_handler_proxy(){const t=this;return{set:function(e,i,r){return i==="request_retention"&&Number.isFinite(r)?t.intervalModifier=t.calculate_interval_modifier(Number(r)):i==="w"&&(r=E(R(r),e.relearning_steps.length),t.forgetting_curve=F.bind(this,r),t.intervalModifier=t.calculate_interval_modifier(Number(e.request_retention))),Reflect.set(e,i,r),!0}}}update_parameters(t){const e=$(t);for(const i in e)if(i in this.param){const r=i;this.param[r]=e[r]}}init_stability(t){return Math.max(this.param.w[t-1],.1)}init_difficulty(t){return+(this.param.w[4]-Math.exp((t-1)*this.param.w[5])+1).toFixed(8)}apply_fuzz(t,e){if(!this.param.enable_fuzz||t<2.5)return Math.round(t);const i=_t(this._seed)(),{min_ivl:r,max_ivl:s}=U(t,e,this.param.maximum_interval);return Math.floor(i*(s-r+1)+r)}next_interval(t,e){const i=Math.min(Math.max(1,Math.round(t*this.intervalModifier)),this.param.maximum_interval);return this.apply_fuzz(i,e)}linear_damping(t,e){return+(t*(10-e)/9).toFixed(8)}next_difficulty(t,e){const i=-this.param.w[6]*(e-3),r=t+this.linear_damping(i,t);return g(this.mean_reversion(this.init_difficulty(l.Easy),r),1,10)}mean_reversion(t,e){return+(this.param.w[7]*t+(1-this.param.w[7])*e).toFixed(8)}next_recall_stability(t,e,i,r){const s=l.Hard===r?this.param.w[15]:1,n=l.Easy===r?this.param.w[16]:1;return+g(e*(1+Math.exp(this.param.w[8])*(11-t)*Math.pow(e,-this.param.w[9])*(Math.exp((1-i)*this.param.w[10])-1)*s*n),p,36500).toFixed(8)}next_forget_stability(t,e,i){return+g(this.param.w[11]*Math.pow(t,-this.param.w[12])*(Math.pow(e+1,this.param.w[13])-1)*Math.exp((1-i)*this.param.w[14]),p,36500).toFixed(8)}next_short_term_stability(t,e){const i=Math.pow(t,-this.param.w[19])*Math.exp(this.param.w[17]*(e-3+this.param.w[18])),r=e>=3?Math.max(i,1):i;return+g(t*r,p,36500).toFixed(8)}forgetting_curve;next_state(t,e,i){const{difficulty:r,stability:s}=t??{difficulty:0,stability:0};if(e<0)throw new Error(`Invalid delta_t "${e}"`);if(i<0||i>4)throw new Error(`Invalid grade "${i}"`);if(r===0&&s===0)return{difficulty:g(this.init_difficulty(i),1,10),stability:this.init_stability(i)};if(i===0)return{difficulty:r,stability:s};if(r<1||s<p)throw new Error(`Invalid memory state { difficulty: ${r}, stability: ${s} }`);const n=this.forgetting_curve(e,s),d=this.next_recall_stability(r,s,n,i),u=this.next_forget_stability(r,s,n),c=this.next_short_term_stability(s,i);let _=d;if(i===1){let[m,w]=[0,0];this.param.enable_short_term&&(m=this.param.w[17],w=this.param.w[18]);const f=s/Math.exp(m*w);_=g(+f.toFixed(8),p,u)}return e===0&&this.param.enable_short_term&&(_=c),{difficulty:this.next_difficulty(r,i),stability:_}}}function K(){const a=this.review_time.getTime(),t=this.current.reps,e=this.current.difficulty*this.current.stability;return`${a}_${t}_${e}`}function ft(a){return function(){const t=Reflect.get(this.current,a)??0,e=this.current.reps;return String(t+e||0)}}const Q=a=>{const t=a.slice(-1),e=parseInt(a.slice(0,-1),10);if(isNaN(e)||!Number.isFinite(e)||e<0)throw new Error(`Invalid step value: ${a}`);switch(t){case"m":return e;case"h":return e*60;case"d":return e*1440;default:throw new Error(`Invalid step unit: ${a}, expected m/h/d`)}},Z=(a,t,e)=>{const i=t===h.Relearning||t===h.Review?a.relearning_steps:a.learning_steps,r=i.length;if(r===0||e>=r)return{};const s=i[0],n=Q,d=()=>n(s),u=()=>{if(r===1)return Math.round(n(s)*1.5);const f=i[1];return Math.round((n(s)+n(f))/2)},c=f=>f<0||f>=r?null:i[f],_=f=>n(f),m={},w=c(Math.max(0,e));if(t===h.Review)return m[l.Again]={scheduled_minutes:n(w),next_step:0},m;{m[l.Again]={scheduled_minutes:d(),next_step:0},m[l.Hard]={scheduled_minutes:u(),next_step:e};const f=c(e+1);if(f){const x=_(f);x&&(m[l.Good]={scheduled_minutes:Math.round(x),next_step:e+1})}}return m};var S=(a=>(a.SCHEDULER="Scheduler",a.LEARNING_STEPS="LearningSteps",a.SEED="Seed",a))(S||{});class H{last;current;review_time;next=new Map;algorithm;strategies;elapsed_days=0;constructor(t,e,i,r){this.algorithm=i,this.last=o.card(t),this.current=o.card(t),this.review_time=o.time(e),this.strategies=r,this.init()}checkGrade(t){if(!Number.isFinite(t)||t<0||t>4)throw new Error(`Invalid grade "${t}",expected 1-4`)}init(){const{state:t,last_review:e}=this.current;let i=0;t!==h.New&&e&&(i=P(e,this.review_time)),this.current.last_review=this.review_time,this.elapsed_days=i,this.current.elapsed_days=i,this.current.reps+=1;let r=K;if(this.strategies){const s=this.strategies.get(S.SEED);s&&(r=s)}this.algorithm.seed=r.call(this)}preview(){return{[l.Again]:this.review(l.Again),[l.Hard]:this.review(l.Hard),[l.Good]:this.review(l.Good),[l.Easy]:this.review(l.Easy),[Symbol.iterator]:this.previewIterator.bind(this)}}*previewIterator(){for(const t of z)yield this.review(t)}review(t){const{state:e}=this.last;let i;switch(this.checkGrade(t),e){case h.New:i=this.newState(t);break;case h.Learning:case h.Relearning:i=this.learningState(t);break;case h.Review:i=this.reviewState(t);break}return i}buildLog(t){const{last_review:e,due:i,elapsed_days:r}=this.last;return{rating:t,state:this.current.state,due:e||i,stability:this.current.stability,difficulty:this.current.difficulty,elapsed_days:this.elapsed_days,last_elapsed_days:r,scheduled_days:this.current.scheduled_days,learning_steps:this.current.learning_steps,review:this.review_time}}}class tt extends H{learningStepsStrategy;constructor(t,e,i,r){super(t,e,i,r);let s=Z;if(this.strategies){const n=this.strategies.get(S.LEARNING_STEPS);n&&(s=n)}this.learningStepsStrategy=s}getLearningInfo(t,e){const i=this.algorithm.parameters;t.learning_steps=t.learning_steps||0;const r=this.learningStepsStrategy(i,t.state,this.current.state===h.Learning?t.learning_steps+1:t.learning_steps),s=Math.max(0,r[e]?.scheduled_minutes??0),n=Math.max(0,r[e]?.next_step??0);return{scheduled_minutes:s,next_steps:n}}applyLearningSteps(t,e,i){const{scheduled_minutes:r,next_steps:s}=this.getLearningInfo(this.current,e);if(r>0&&r<1440)t.learning_steps=s,t.scheduled_days=0,t.state=i,t.due=y(this.review_time,Math.round(r),!1);else if(t.state=h.Review,r>=1440)t.learning_steps=s,t.due=y(this.review_time,Math.round(r),!1),t.scheduled_days=Math.floor(r/1440);else{t.learning_steps=0;const n=this.algorithm.next_interval(t.stability,this.elapsed_days);t.scheduled_days=n,t.due=y(this.review_time,n,!0)}}newState(t){const e=this.next.get(t);if(e)return e;const i=o.card(this.current);i.difficulty=g(this.algorithm.init_difficulty(t),1,10),i.stability=this.algorithm.init_stability(t),this.applyLearningSteps(i,t,h.Learning);const r={card:i,log:this.buildLog(t)};return this.next.set(t,r),r}learningState(t){const e=this.next.get(t);if(e)return e;const{state:i,difficulty:r,stability:s}=this.last,n=o.card(this.current);n.difficulty=this.algorithm.next_difficulty(r,t),n.stability=this.algorithm.next_short_term_stability(s,t),this.applyLearningSteps(n,t,i);const d={card:n,log:this.buildLog(t)};return this.next.set(t,d),d}reviewState(t){const e=this.next.get(t);if(e)return e;const i=this.elapsed_days,{difficulty:r,stability:s}=this.last,n=this.algorithm.forgetting_curve(i,s),d=o.card(this.current),u=o.card(this.current),c=o.card(this.current),_=o.card(this.current);this.next_ds(d,u,c,_,r,s,n),this.next_interval(u,c,_,i),this.next_state(u,c,_),this.applyLearningSteps(d,l.Again,h.Relearning),d.lapses+=1;const m={card:d,log:this.buildLog(l.Again)},w={card:u,log:super.buildLog(l.Hard)},f={card:c,log:super.buildLog(l.Good)},x={card:_,log:super.buildLog(l.Easy)};return this.next.set(l.Again,m),this.next.set(l.Hard,w),this.next.set(l.Good,f),this.next.set(l.Easy,x),this.next.get(t)}next_ds(t,e,i,r,s,n,d){t.difficulty=this.algorithm.next_difficulty(s,l.Again);const u=n/Math.exp(this.algorithm.parameters.w[17]*this.algorithm.parameters.w[18]),c=this.algorithm.next_forget_stability(s,n,d);t.stability=g(+u.toFixed(8),p,c),e.difficulty=this.algorithm.next_difficulty(s,l.Hard),e.stability=this.algorithm.next_recall_stability(s,n,d,l.Hard),i.difficulty=this.algorithm.next_difficulty(s,l.Good),i.stability=this.algorithm.next_recall_stability(s,n,d,l.Good),r.difficulty=this.algorithm.next_difficulty(s,l.Easy),r.stability=this.algorithm.next_recall_stability(s,n,d,l.Easy)}next_interval(t,e,i,r){let s,n;s=this.algorithm.next_interval(t.stability,r),n=this.algorithm.next_interval(e.stability,r),s=Math.min(s,n),n=Math.max(n,s+1);const d=Math.max(this.algorithm.next_interval(i.stability,r),n+1);t.scheduled_days=s,t.due=y(this.review_time,s,!0),e.scheduled_days=n,e.due=y(this.review_time,n,!0),i.scheduled_days=d,i.due=y(this.review_time,d,!0)}next_state(t,e,i){t.state=h.Review,t.learning_steps=0,e.state=h.Review,e.learning_steps=0,i.state=h.Review,i.learning_steps=0}}class et extends H{newState(t){const e=this.next.get(t);if(e)return e;this.current.scheduled_days=0,this.current.elapsed_days=0;const i=o.card(this.current),r=o.card(this.current),s=o.card(this.current),n=o.card(this.current);return this.init_ds(i,r,s,n),this.next_interval(i,r,s,n,0),this.next_state(i,r,s,n),this.update_next(i,r,s,n),this.next.get(t)}init_ds(t,e,i,r){t.difficulty=g(this.algorithm.init_difficulty(l.Again),1,10),t.stability=this.algorithm.init_stability(l.Again),e.difficulty=g(this.algorithm.init_difficulty(l.Hard),1,10),e.stability=this.algorithm.init_stability(l.Hard),i.difficulty=g(this.algorithm.init_difficulty(l.Good),1,10),i.stability=this.algorithm.init_stability(l.Good),r.difficulty=g(this.algorithm.init_difficulty(l.Easy),1,10),r.stability=this.algorithm.init_stability(l.Easy)}learningState(t){return this.reviewState(t)}reviewState(t){const e=this.next.get(t);if(e)return e;const i=this.elapsed_days,{difficulty:r,stability:s}=this.last,n=this.algorithm.forgetting_curve(i,s),d=o.card(this.current),u=o.card(this.current),c=o.card(this.current),_=o.card(this.current);return this.next_ds(d,u,c,_,r,s,n),this.next_interval(d,u,c,_,i),this.next_state(d,u,c,_),d.lapses+=1,this.update_next(d,u,c,_),this.next.get(t)}next_ds(t,e,i,r,s,n,d){t.difficulty=this.algorithm.next_difficulty(s,l.Again);const u=this.algorithm.next_forget_stability(s,n,d);t.stability=g(n,p,u),e.difficulty=this.algorithm.next_difficulty(s,l.Hard),e.stability=this.algorithm.next_recall_stability(s,n,d,l.Hard),i.difficulty=this.algorithm.next_difficulty(s,l.Good),i.stability=this.algorithm.next_recall_stability(s,n,d,l.Good),r.difficulty=this.algorithm.next_difficulty(s,l.Easy),r.stability=this.algorithm.next_recall_stability(s,n,d,l.Easy)}next_interval(t,e,i,r,s){let n,d,u,c;n=this.algorithm.next_interval(t.stability,s),d=this.algorithm.next_interval(e.stability,s),u=this.algorithm.next_interval(i.stability,s),c=this.algorithm.next_interval(r.stability,s),n=Math.min(n,d),d=Math.max(d,n+1),u=Math.max(u,d+1),c=Math.max(c,u+1),t.scheduled_days=n,t.due=y(this.review_time,n,!0),e.scheduled_days=d,e.due=y(this.review_time,d,!0),i.scheduled_days=u,i.due=y(this.review_time,u,!0),r.scheduled_days=c,r.due=y(this.review_time,c,!0)}next_state(t,e,i,r){t.state=h.Review,t.learning_steps=0,e.state=h.Review,e.learning_steps=0,i.state=h.Review,i.learning_steps=0,r.state=h.Review,r.learning_steps=0}update_next(t,e,i,r){const s={card:t,log:this.buildLog(l.Again)},n={card:e,log:super.buildLog(l.Hard)},d={card:i,log:super.buildLog(l.Good)},u={card:r,log:super.buildLog(l.Easy)};this.next.set(l.Again,s),this.next.set(l.Hard,n),this.next.set(l.Good,d),this.next.set(l.Easy,u)}}class gt{fsrs;constructor(t){this.fsrs=t}replay(t,e,i){return this.fsrs.next(t,e,i)}handleManualRating(t,e,i,r,s,n,d){if(typeof e>"u")throw new Error("reschedule: state is required for manual rating");let u,c;if(e===h.New)u={rating:l.Manual,state:e,due:d??i,stability:t.stability,difficulty:t.difficulty,elapsed_days:r,last_elapsed_days:t.elapsed_days,scheduled_days:t.scheduled_days,learning_steps:t.learning_steps,review:i},c=A(i),c.last_review=i;else{if(typeof d>"u")throw new Error("reschedule: due is required for manual rating");const _=v(d,i,"days");u={rating:l.Manual,state:t.state,due:t.last_review||t.due,stability:t.stability,difficulty:t.difficulty,elapsed_days:r,last_elapsed_days:t.elapsed_days,scheduled_days:t.scheduled_days,learning_steps:t.learning_steps,review:i},c={...t,state:e,due:d,last_review:i,stability:s||t.stability,difficulty:n||t.difficulty,elapsed_days:r,scheduled_days:_,reps:t.reps+1}}return{card:c,log:u}}reschedule(t,e){const i=[];let r=A(t.due);for(const s of e){let n;if(s.review=o.time(s.review),s.rating===l.Manual){let d=0;r.state!==h.New&&r.last_review&&(d=v(s.review,r.last_review,"days")),n=this.handleManualRating(r,s.state,s.review,d,s.stability,s.difficulty,s.due?o.time(s.due):void 0)}else n=this.replay(r,s.review,s.rating);i.push(n),r=n.card}return i}calculateManualRecord(t,e,i,r){if(!i)return null;const{card:s,log:n}=i,d=o.card(t);return d.due.getTime()===s.due.getTime()?null:(d.scheduled_days=v(s.due,d.due,"days"),this.handleManualRating(d,s.state,o.time(e),n.elapsed_days,r?s.stability:void 0,r?s.difficulty:void 0,s.due))}}class it extends J{strategyHandler=new Map;Scheduler;constructor(t){super(t);const{enable_short_term:e}=this.parameters;this.Scheduler=e?tt:et}params_handler_proxy(){const t=this;return{set:function(e,i,r){return i==="request_retention"&&Number.isFinite(r)?t.intervalModifier=t.calculate_interval_modifier(Number(r)):i==="enable_short_term"?t.Scheduler=r===!0?tt:et:i==="w"&&(r=E(R(r),e.relearning_steps.length),t.forgetting_curve=F.bind(this,r),t.intervalModifier=t.calculate_interval_modifier(Number(e.request_retention))),Reflect.set(e,i,r),!0}}}useStrategy(t,e){return this.strategyHandler.set(t,e),this}clearStrategy(t){return t?this.strategyHandler.delete(t):this.strategyHandler.clear(),this}getScheduler(t,e){const i=this.strategyHandler.get(S.SCHEDULER)||this.Scheduler;return new i(t,e,this,this.strategyHandler)}repeat(t,e,i){const r=this.getScheduler(t,e).preview();return i&&typeof i=="function"?i(r):r}next(t,e,i,r){const s=this.getScheduler(t,e),n=o.rating(i);if(n===l.Manual)throw new Error("Cannot review a manual rating");const d=s.review(n);return r&&typeof r=="function"?r(d):d}get_retrievability(t,e,i=!0){const r=o.card(t);e=e?o.time(e):new Date;const s=r.state!==h.New?Math.max(v(e,r.last_review,"days"),0):0,n=r.state!==h.New?this.forgetting_curve(s,+r.stability.toFixed(8)):0;return i?`${(n*100).toFixed(2)}%`:n}rollback(t,e,i){const r=o.card(t),s=o.review_log(e);if(s.rating===l.Manual)throw new Error("Cannot rollback a manual rating");let n,d,u;switch(s.state){case h.New:n=s.due,d=void 0,u=0;break;case h.Learning:case h.Relearning:case h.Review:n=s.review,d=s.due,u=r.lapses-(s.rating===l.Again&&s.state===h.Review?1:0);break}const c={...r,due:n,stability:s.stability,difficulty:s.difficulty,elapsed_days:s.last_elapsed_days,scheduled_days:s.scheduled_days,reps:Math.max(0,r.reps-1),lapses:Math.max(0,u),learning_steps:s.learning_steps,state:s.state,last_review:d};return i&&typeof i=="function"?i(c):c}forget(t,e,i=!1,r){const s=o.card(t);e=o.time(e);const n=s.state===h.New?0:v(e,s.due,"days"),d={rating:l.Manual,state:s.state,due:s.due,stability:s.stability,difficulty:s.difficulty,elapsed_days:0,last_elapsed_days:s.elapsed_days,scheduled_days:n,learning_steps:s.learning_steps,review:e},u={card:{...s,due:e,stability:0,difficulty:0,elapsed_days:0,scheduled_days:0,reps:i?0:s.reps,lapses:i?0:s.lapses,learning_steps:0,state:h.New,last_review:s.last_review},log:d};return r&&typeof r=="function"?r(u):u}reschedule(t,e=[],i={}){const{recordLogHandler:r,reviewsOrderBy:s,skipManual:n=!0,now:d=new Date,update_memory_state:u=!1}=i;s&&typeof s=="function"&&e.sort(s),n&&(e=e.filter(x=>x.rating!==l.Manual));const c=new gt(this),_=c.reschedule(i.first_card||A(),e),m=_.length,w=o.card(t),f=c.calculateManualRecord(w,d,m?_[m-1]:void 0,u);return r&&typeof r=="function"?{collections:_.map(r),reschedule_item:f?r(f):null}:{collections:_,reschedule_item:f}}}const mt=a=>new it(a||{});exports.AbstractScheduler=H,exports.BasicLearningStepsStrategy=Z,exports.CLAMP_PARAMETERS=V,exports.ConvertStepUnitToMinutes=Q,exports.DefaultInitSeedStrategy=K,exports.FSRS=it,exports.FSRS5_DEFAULT_DECAY=N,exports.FSRS6_DEFAULT_DECAY=X,exports.FSRSAlgorithm=J,exports.FSRSVersion=dt,exports.GenSeedStrategyWithCardId=ft,exports.Grades=z,exports.INIT_S_MAX=M,exports.Rating=l,exports.S_MAX=ot,exports.S_MIN=p,exports.State=h,exports.StrategyMode=S,exports.TypeConvert=o,exports.W17_W18_Ceiling=B,exports.checkParameters=ut,exports.clamp=g,exports.clipParameters=E,exports.computeDecayFactor=C,exports.createEmptyCard=A,exports.dateDiffInDays=P,exports.date_diff=v,exports.date_scheduler=y,exports.default_enable_fuzz=Y,exports.default_enable_short_term=j,exports.default_learning_steps=O,exports.default_maximum_interval=q,exports.default_relearning_steps=W,exports.default_request_retention=k,exports.default_w=I,exports.fixDate=rt,exports.fixRating=at,exports.fixState=st,exports.forgetting_curve=F,exports.formatDate=G,exports.fsrs=mt,exports.generatorParameters=$,exports.get_fuzz_range=U,exports.migrateParameters=R,exports.show_diff_message=T,module.exports=Object.assign(exports.default||{},exports);
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|