@quesmed/types 2.4.4 → 2.4.6

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.
@@ -2,6 +2,7 @@ export * from './commonFunctions';
2
2
  export * from './lightgallery';
3
3
  export * from './offlineLink';
4
4
  export * from './random';
5
+ export * from './supermemo';
5
6
  export * from './webSocketLink';
6
7
  export * from './wordsToNumber';
7
8
  import uuid from './uuid4';
@@ -18,6 +18,7 @@ __exportStar(require("./commonFunctions"), exports);
18
18
  __exportStar(require("./lightgallery"), exports);
19
19
  __exportStar(require("./offlineLink"), exports);
20
20
  __exportStar(require("./random"), exports);
21
+ __exportStar(require("./supermemo"), exports);
21
22
  __exportStar(require("./webSocketLink"), exports);
22
23
  __exportStar(require("./wordsToNumber"), exports);
23
24
  const uuid4_1 = __importDefault(require("./uuid4"));
@@ -0,0 +1,25 @@
1
+ import Decimal from 'decimal.js';
2
+ import { Id, IUserCompletedCard } from '../models';
3
+ export declare const ALGO_FRACTION: Decimal;
4
+ export interface IScoreQuesCardInput {
5
+ cardId: number;
6
+ score: number;
7
+ timeTaken: number;
8
+ }
9
+ export interface IScoreQuesCardVar {
10
+ input: IScoreQuesCardInput;
11
+ completedCard: IUserCompletedCard;
12
+ userId: Id;
13
+ }
14
+ export interface IScoreQuesCardData {
15
+ cardId: Id;
16
+ userId: Id;
17
+ lastSeen: Date;
18
+ reviewDate: Date;
19
+ score: number;
20
+ iteration: number;
21
+ optimalFactor: number;
22
+ }
23
+ export declare function scoreQuesCard({ input, completedCard, userId, }: IScoreQuesCardVar): IScoreQuesCardData;
24
+ export declare function supermemo(EF: number, quality: number): number;
25
+ export declare function calcOptimalFactor(iteration: number, quality: number, prevOF: number): number;
@@ -0,0 +1,112 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.calcOptimalFactor = exports.supermemo = exports.scoreQuesCard = exports.ALGO_FRACTION = void 0;
7
+ const decimal_js_1 = __importDefault(require("decimal.js"));
8
+ const luxon_1 = require("luxon");
9
+ exports.ALGO_FRACTION = new decimal_js_1.default(0.5);
10
+ function scoreQuesCard({ input, completedCard, userId, }) {
11
+ const lastSeen = luxon_1.DateTime.now();
12
+ let prevScore = 2.5;
13
+ let iteration = 1;
14
+ let optimalFactor = 2;
15
+ if (completedCard) {
16
+ prevScore = completedCard.score;
17
+ if (input.score >= 3) {
18
+ iteration = completedCard.iteration + 1;
19
+ }
20
+ else {
21
+ iteration = 1;
22
+ }
23
+ optimalFactor = calcOptimalFactor(iteration, input.score, completedCard.optimalFactor);
24
+ }
25
+ const EF = supermemo(prevScore, input.score);
26
+ let reviewDate = lastSeen.plus({ days: 1 });
27
+ if (optimalFactor !== 2) {
28
+ let daysToReview = 1;
29
+ if (iteration > 1) {
30
+ daysToReview = optimalFactor * (iteration - 1) * EF;
31
+ }
32
+ reviewDate = lastSeen.plus({ days: daysToReview });
33
+ }
34
+ return {
35
+ score: EF,
36
+ iteration,
37
+ lastSeen: lastSeen.toJSDate(),
38
+ cardId: input.cardId,
39
+ userId,
40
+ optimalFactor,
41
+ reviewDate: reviewDate.toJSDate(),
42
+ };
43
+ }
44
+ exports.scoreQuesCard = scoreQuesCard;
45
+ function supermemo(EF, quality) {
46
+ // EF':=EF-0.8+0.28*q-0.02*q*q
47
+ // EF':=EF+(0.1-(5-q)*(0.08+(5-q)*0.02))
48
+ const qFactor = new decimal_js_1.default(5 - quality);
49
+ let newEF = new decimal_js_1.default(EF).plus(new decimal_js_1.default(0.1)
50
+ .minus(qFactor)
51
+ .mul(new decimal_js_1.default(0.08).plus(qFactor).mul(new decimal_js_1.default(0.02))));
52
+ if (newEF.lessThan(1.3)) {
53
+ newEF = new decimal_js_1.default(1.3);
54
+ }
55
+ else if (newEF.greaterThan(2.5)) {
56
+ newEF = new decimal_js_1.default(2.5);
57
+ }
58
+ return newEF.toNearest(0.01).toNumber();
59
+ }
60
+ exports.supermemo = supermemo;
61
+ function calcOptimalFactor(iteration, quality, prevOF) {
62
+ const iter = new decimal_js_1.default(iteration);
63
+ const q = new decimal_js_1.default(quality);
64
+ const pOF = new decimal_js_1.default(prevOF);
65
+ const one = new decimal_js_1.default(1);
66
+ let modifier = new decimal_js_1.default(0);
67
+ let mod5 = iter.plus(one).div(iter);
68
+ const one_05 = new decimal_js_1.default(1.05);
69
+ if (mod5.lessThan(one_05)) {
70
+ mod5 = one_05;
71
+ }
72
+ let mod2 = iter.minus(one).div(iter);
73
+ const zero_75 = new decimal_js_1.default(0.75);
74
+ if (mod2.greaterThan(zero_75)) {
75
+ mod2 = zero_75;
76
+ }
77
+ const four = new decimal_js_1.default(4);
78
+ if (q.greaterThan(four)) {
79
+ modifier = one.plus(mod5.minus(one).mul(q.minus(four)));
80
+ }
81
+ else {
82
+ modifier = one.minus(one.minus(mod2).div(new decimal_js_1.default(2)).mul(four.minus(q)));
83
+ }
84
+ if (modifier.lessThan(0.05)) {
85
+ modifier = new decimal_js_1.default(0.05);
86
+ }
87
+ let usedOF = four;
88
+ if (!iter.eq(1)) {
89
+ const tmp = pOF.mul(new decimal_js_1.default(0.72).plus(q).mul(new decimal_js_1.default(0.07)));
90
+ usedOF = pOF
91
+ .mul(new decimal_js_1.default(1).minus(exports.ALGO_FRACTION))
92
+ .plus(exports.ALGO_FRACTION.mul(tmp));
93
+ }
94
+ let newOF = usedOF.mul(modifier);
95
+ if (q.greaterThan(four)) {
96
+ if (newOF.lessThan(pOF)) {
97
+ newOF = pOF;
98
+ }
99
+ }
100
+ else if (q.lessThan(four)) {
101
+ if (newOF.greaterThan(pOF)) {
102
+ newOF = pOF;
103
+ }
104
+ }
105
+ newOF = newOF.mul(exports.ALGO_FRACTION).plus(pOF.mul(one.minus(exports.ALGO_FRACTION)));
106
+ const one_2 = new decimal_js_1.default(1.2);
107
+ if (newOF.lessThan(one_2)) {
108
+ newOF = one_2;
109
+ }
110
+ return newOF.toNearest(0.01).toNumber();
111
+ }
112
+ exports.calcOptimalFactor = calcOptimalFactor;
@@ -2,6 +2,7 @@ export * from './commonFunctions';
2
2
  export * from './lightgallery';
3
3
  export * from './offlineLink';
4
4
  export * from './random';
5
+ export * from './supermemo';
5
6
  export * from './webSocketLink';
6
7
  export * from './wordsToNumber';
7
8
  import uuid from './uuid4';
@@ -2,6 +2,7 @@ export * from './commonFunctions';
2
2
  export * from './lightgallery';
3
3
  export * from './offlineLink';
4
4
  export * from './random';
5
+ export * from './supermemo';
5
6
  export * from './webSocketLink';
6
7
  export * from './wordsToNumber';
7
8
  import uuid from './uuid4';
@@ -0,0 +1,25 @@
1
+ import Decimal from 'decimal.js';
2
+ import { Id, IUserCompletedCard } from '../models';
3
+ export declare const ALGO_FRACTION: Decimal;
4
+ export interface IScoreQuesCardInput {
5
+ cardId: number;
6
+ score: number;
7
+ timeTaken: number;
8
+ }
9
+ export interface IScoreQuesCardVar {
10
+ input: IScoreQuesCardInput;
11
+ completedCard: IUserCompletedCard;
12
+ userId: Id;
13
+ }
14
+ export interface IScoreQuesCardData {
15
+ cardId: Id;
16
+ userId: Id;
17
+ lastSeen: Date;
18
+ reviewDate: Date;
19
+ score: number;
20
+ iteration: number;
21
+ optimalFactor: number;
22
+ }
23
+ export declare function scoreQuesCard({ input, completedCard, userId, }: IScoreQuesCardVar): IScoreQuesCardData;
24
+ export declare function supermemo(EF: number, quality: number): number;
25
+ export declare function calcOptimalFactor(iteration: number, quality: number, prevOF: number): number;
@@ -0,0 +1,103 @@
1
+ import Decimal from 'decimal.js';
2
+ import { DateTime } from 'luxon';
3
+ export const ALGO_FRACTION = new Decimal(0.5);
4
+ export function scoreQuesCard({ input, completedCard, userId, }) {
5
+ const lastSeen = DateTime.now();
6
+ let prevScore = 2.5;
7
+ let iteration = 1;
8
+ let optimalFactor = 2;
9
+ if (completedCard) {
10
+ prevScore = completedCard.score;
11
+ if (input.score >= 3) {
12
+ iteration = completedCard.iteration + 1;
13
+ }
14
+ else {
15
+ iteration = 1;
16
+ }
17
+ optimalFactor = calcOptimalFactor(iteration, input.score, completedCard.optimalFactor);
18
+ }
19
+ const EF = supermemo(prevScore, input.score);
20
+ let reviewDate = lastSeen.plus({ days: 1 });
21
+ if (optimalFactor !== 2) {
22
+ let daysToReview = 1;
23
+ if (iteration > 1) {
24
+ daysToReview = optimalFactor * (iteration - 1) * EF;
25
+ }
26
+ reviewDate = lastSeen.plus({ days: daysToReview });
27
+ }
28
+ return {
29
+ score: EF,
30
+ iteration,
31
+ lastSeen: lastSeen.toJSDate(),
32
+ cardId: input.cardId,
33
+ userId,
34
+ optimalFactor,
35
+ reviewDate: reviewDate.toJSDate(),
36
+ };
37
+ }
38
+ export function supermemo(EF, quality) {
39
+ // EF':=EF-0.8+0.28*q-0.02*q*q
40
+ // EF':=EF+(0.1-(5-q)*(0.08+(5-q)*0.02))
41
+ const qFactor = new Decimal(5 - quality);
42
+ let newEF = new Decimal(EF).plus(new Decimal(0.1)
43
+ .minus(qFactor)
44
+ .mul(new Decimal(0.08).plus(qFactor).mul(new Decimal(0.02))));
45
+ if (newEF.lessThan(1.3)) {
46
+ newEF = new Decimal(1.3);
47
+ }
48
+ else if (newEF.greaterThan(2.5)) {
49
+ newEF = new Decimal(2.5);
50
+ }
51
+ return newEF.toNearest(0.01).toNumber();
52
+ }
53
+ export function calcOptimalFactor(iteration, quality, prevOF) {
54
+ const iter = new Decimal(iteration);
55
+ const q = new Decimal(quality);
56
+ const pOF = new Decimal(prevOF);
57
+ const one = new Decimal(1);
58
+ let modifier = new Decimal(0);
59
+ let mod5 = iter.plus(one).div(iter);
60
+ const one_05 = new Decimal(1.05);
61
+ if (mod5.lessThan(one_05)) {
62
+ mod5 = one_05;
63
+ }
64
+ let mod2 = iter.minus(one).div(iter);
65
+ const zero_75 = new Decimal(0.75);
66
+ if (mod2.greaterThan(zero_75)) {
67
+ mod2 = zero_75;
68
+ }
69
+ const four = new Decimal(4);
70
+ if (q.greaterThan(four)) {
71
+ modifier = one.plus(mod5.minus(one).mul(q.minus(four)));
72
+ }
73
+ else {
74
+ modifier = one.minus(one.minus(mod2).div(new Decimal(2)).mul(four.minus(q)));
75
+ }
76
+ if (modifier.lessThan(0.05)) {
77
+ modifier = new Decimal(0.05);
78
+ }
79
+ let usedOF = four;
80
+ if (!iter.eq(1)) {
81
+ const tmp = pOF.mul(new Decimal(0.72).plus(q).mul(new Decimal(0.07)));
82
+ usedOF = pOF
83
+ .mul(new Decimal(1).minus(ALGO_FRACTION))
84
+ .plus(ALGO_FRACTION.mul(tmp));
85
+ }
86
+ let newOF = usedOF.mul(modifier);
87
+ if (q.greaterThan(four)) {
88
+ if (newOF.lessThan(pOF)) {
89
+ newOF = pOF;
90
+ }
91
+ }
92
+ else if (q.lessThan(four)) {
93
+ if (newOF.greaterThan(pOF)) {
94
+ newOF = pOF;
95
+ }
96
+ }
97
+ newOF = newOF.mul(ALGO_FRACTION).plus(pOF.mul(one.minus(ALGO_FRACTION)));
98
+ const one_2 = new Decimal(1.2);
99
+ if (newOF.lessThan(one_2)) {
100
+ newOF = one_2;
101
+ }
102
+ return newOF.toNearest(0.01).toNumber();
103
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quesmed/types",
3
- "version": "2.4.4",
3
+ "version": "2.4.6",
4
4
  "description": "Typescript types for Quesmed",
5
5
  "keywords": [
6
6
  "quesmed",
@@ -97,7 +97,9 @@
97
97
  "@apollo/client": "^3.5.7",
98
98
  "@react-native-async-storage/async-storage": "^1.15.16",
99
99
  "@types/react-native": "^0.64",
100
+ "decimal.js": "^10.4.3",
100
101
  "localforage": "^1.10.0",
102
+ "luxon": "^3.2.1",
101
103
  "react-native": "0.64.0",
102
104
  "react-native-expo-image-cache": "^4.1.0"
103
105
  },
@@ -108,6 +110,7 @@
108
110
  "@graphql-tools/load-files": "^6.5.3",
109
111
  "@graphql-tools/merge": "^8.2.2",
110
112
  "@types/jest": "^27.4.1",
113
+ "@types/luxon": "^3.2.0",
111
114
  "@types/node": "^17.0.10",
112
115
  "@yarnpkg/pnpify": "^3.1.1-rc.11",
113
116
  "babel-jest": "^27.4.6",