refactor: Move the SM2 implementation to the backend
This commit is contained in:
parent
6e80ed79d2
commit
7de3cedb15
@ -8,7 +8,9 @@ import { authRoute } from "../security/token";
|
|||||||
import { userFromSession } from "../utils/user";
|
import { userFromSession } from "../utils/user";
|
||||||
|
|
||||||
import { IUser, IUserDBModel } from "../models/user";
|
import { IUser, IUserDBModel } from "../models/user";
|
||||||
import { ISM2Metadata } from "../models/review";
|
import {
|
||||||
|
ISchedulingData, AnswerType, updateSchedulingData
|
||||||
|
} from "../algorithms/sm2";
|
||||||
import { LRequest } from "../types/express";
|
import { LRequest } from "../types/express";
|
||||||
|
|
||||||
const userRouter = express.Router();
|
const userRouter = express.Router();
|
||||||
@ -190,34 +192,31 @@ userRouter.post("/lastReview", async (req: LRequest, res) => {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: Oh oh
|
||||||
|
// Update the user's score based on what they sent us
|
||||||
user.score += parseInt(req.body.delta);
|
user.score += parseInt(req.body.delta);
|
||||||
|
|
||||||
|
// Itterate over all of the vocabulary that needs to have its
|
||||||
|
// metadata updated.
|
||||||
|
// Use our SM2 implementation to update the vocabulary and modify our
|
||||||
|
// copy of the user object, so that we can write the copied (and modified)
|
||||||
|
// user object back into the database.
|
||||||
Object.keys(req.body.sm2).forEach((id: string) => {
|
Object.keys(req.body.sm2).forEach((id: string) => {
|
||||||
const vocabId = parseInt(id);
|
const vocabId = parseInt(id);
|
||||||
const correct: boolean = req.body.sm2[id];
|
const correct: boolean = req.body.sm2[id];
|
||||||
let vocab_sm2: ISM2Metadata = Object.assign({},
|
let vocab_sm2: ISchedulingData = Object.assign({},
|
||||||
user.vocabMetadata[vocabId]);
|
user.vocabMetadata[vocabId]);
|
||||||
|
|
||||||
// TODO: Tuning?
|
const answer = correct ? AnswerType.CORRECT : AnswerType.WRONG;
|
||||||
// TODO: Move into another module
|
user.vocabMetadata[vocabId] = updateSchedulingData(vocab_sm2, answer);
|
||||||
const perf = correct ? 3 : 1;
|
|
||||||
vocab_sm2.easiness += -0.8 + 0.28 * perf + 0.02 * Math.pow(perf, 2);
|
|
||||||
// Update the consecutive correct answers and the due date
|
|
||||||
if (correct) {
|
|
||||||
vocab_sm2.consecutiveCorrectAnswers += 1;
|
|
||||||
vocab_sm2.nextDueDate = dateInNDays(6 * Math.pow(vocab_sm2.easiness, vocab_sm2.consecutiveCorrectAnswers - 1));
|
|
||||||
} else {
|
|
||||||
vocab_sm2.consecutiveCorrectAnswers = 0;
|
|
||||||
vocab_sm2.nextDueDate = dateInNDays(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
user.vocabMetadata[vocabId] = vocab_sm2;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Update the last review
|
// Update the last review
|
||||||
user.lastReview = req.body.meta;
|
user.lastReview = req.body.meta;
|
||||||
|
|
||||||
// TODO: Error handling
|
// NOTE: Error handling could be implemented here, but we can ensure that
|
||||||
|
// the user exists, as we just got his username (and entire data)
|
||||||
|
// from `userFromSession`.
|
||||||
await db.collection("users").updateOne({
|
await db.collection("users").updateOne({
|
||||||
username: user.username,
|
username: user.username,
|
||||||
}, {
|
}, {
|
||||||
|
Reference in New Issue
Block a user