feat: Points for doing reviews

This commit is contained in:
Alexander Polynomdivision 2018-10-01 19:21:57 +02:00
parent d08e591e27
commit 977f5df9dd
7 changed files with 35 additions and 17 deletions

View File

@ -130,7 +130,7 @@ function dateInNDays(n: number): number {
userRouter.post("/lastReview", async (req: LRequest, res) => { userRouter.post("/lastReview", async (req: LRequest, res) => {
// Check if we get the needed data // Check if we get the needed data
if (!req.body || !("meta" in req.body) || !("sm2" in req.body)) { if (!req.body || !("meta" in req.body) || !("sm2" in req.body) || !("delta" in req.body)) {
res.send({ res.send({
error: "400", error: "400",
data: { data: {
@ -152,6 +152,8 @@ userRouter.post("/lastReview", async (req: LRequest, res) => {
return; return;
} }
user.score += parseInt(req.body.delta);
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];
@ -184,6 +186,7 @@ userRouter.post("/lastReview", async (req: LRequest, res) => {
$set: { $set: {
lastReview: user.lastReview, lastReview: user.lastReview,
vocabMetadata: user.vocabMetadata, vocabMetadata: user.vocabMetadata,
score: user.score,
}, },
}); });

View File

@ -5,4 +5,4 @@ rm -rf dist/
chmod 705 dist dist/app chmod 705 dist dist/app
chmod 604 dist/app/* chmod 604 dist/app/*
#sed "s/\/src/\/app\/src/" dist/app/index.html sed -e "s/\/src/\/app\/src/g" --in-place dist/app/index.html

View File

@ -120,6 +120,14 @@ export function setLastReview(metadata: IReviewMetadata) {
}; };
}; };
export const SET_USER_SCORE_DELTA = "SET_USER_SCORE_DELTA";
export function setUserScoreDelta(delta: number) {
return {
type: SET_USER_SCORE_DELTA,
delta,
};
};
export const SET_REVIEW = "SET_REVIEW"; export const SET_REVIEW = "SET_REVIEW";
export function setReview(current: IReviewCard, meta: IReviewMetadata) { export function setReview(current: IReviewCard, meta: IReviewMetadata) {
return { return {

View File

@ -31,7 +31,8 @@ interface IProps {
setAuthenticated: (status: boolean) => void; setAuthenticated: (status: boolean) => void;
setDidLogin: (status: boolean) => void; setDidLogin: (status: boolean) => void;
setUser: (user: IUser) => void; setUser: (user: IUser) => void;
setLastReview: (meta: IReviewMetadata) => void; setLastReview: (meta: IReviewMetadata, delta: number) => void;
setUserScoreDelta: (delta: number) => void;
}; };
// TODO: Replace the sessionStorage with localStorage? // TODO: Replace the sessionStorage with localStorage?
@ -107,9 +108,10 @@ export default class Application extends React.Component<IProps> {
} }
// TODO: Type? // TODO: Type?
setLastReview = (meta: IReviewMetadata, sm2: any) => { setLastReview = (meta: IReviewMetadata, sm2: any, delta: number) => {
// Update the state // Update the state
this.props.setLastReview(meta); this.props.setLastReview(meta);
this.props.setUserScoreDelta(delta);
// Tell the server about the last review // Tell the server about the last review
fetch(`${BACKEND_URL}/api/user/lastReview`, { fetch(`${BACKEND_URL}/api/user/lastReview`, {
@ -121,6 +123,7 @@ export default class Application extends React.Component<IProps> {
body: JSON.stringify({ body: JSON.stringify({
meta, meta,
sm2, sm2,
delta,
}), }),
}).then(resp => resp.json(), err => { }).then(resp => resp.json(), err => {
console.log("Application::setLastReview: POSTing last results failed"); console.log("Application::setLastReview: POSTing last results failed");

View File

@ -4,7 +4,10 @@ import { IUser } from "../models/user";
import Application from "../components/app"; import Application from "../components/app";
import { setAuthenticated, setUser, setDidLogin, setLastReview } from "../actions"; import {
setAuthenticated, setUser, setDidLogin, setLastReview,
setUserScoreDelta
} from "../actions";
import { IReviewMetadata } from "../models/review"; import { IReviewMetadata } from "../models/review";
@ -20,6 +23,7 @@ const mapDispatchToProps = dispatch => {
setDidLogin: (state: boolean) => dispatch(setDidLogin(state)), setDidLogin: (state: boolean) => dispatch(setDidLogin(state)),
setUser: (user: IUser) => dispatch(setUser(user)), setUser: (user: IUser) => dispatch(setUser(user)),
setLastReview: (meta: IReviewMetadata) => dispatch(setLastReview(meta)), setLastReview: (meta: IReviewMetadata) => dispatch(setLastReview(meta)),
setUserScoreDelta: (delta: number) => dispatch(setUserScoreDelta(delta)),
}; };
}; };

View File

@ -33,7 +33,7 @@ interface IProps {
levelId?: number; levelId?: number;
vocabByLevel?: (level: number) => Promise<IVocab[]>; vocabByLevel?: (level: number) => Promise<IVocab[]>;
vocabByQueue?: () => Promise<IVocab[]>; vocabByQueue?: () => Promise<IVocab[]>;
setLastReview: (meta: IReviewMetadata, sm2: any) => void; setLastReview: (meta: IReviewMetadata, sm2: any, delta: number) => void;
reviewType: ReviewType; reviewType: ReviewType;
history: any; history: any;
@ -65,6 +65,7 @@ const ReviewPageWithRouter = withRouter(
private inputRef: HTMLInputElement; private inputRef: HTMLInputElement;
// Mapping: Vocab Id -> Correctly answered // Mapping: Vocab Id -> Correctly answered
private sm2_metadata: any = {}; private sm2_metadata: any = {};
private score_delta = 0;
constructor(props: any) { constructor(props: any) {
super(props); super(props);
@ -189,13 +190,15 @@ const ReviewPageWithRouter = withRouter(
// Check if the user's answer was correct // Check if the user's answer was correct
if (minDist === 0) { if (minDist === 0) {
this.updateGroupSM2(true); this.updateGroupSM2(true);
// TODO: Is this correct?
this.score_delta += 1;
// TODO: Show it's correct? // TODO: Show it's correct?
// Show the next vocab word // Show the next vocab word
if (this.reviewQueue.size() === 0) { if (this.reviewQueue.size() === 0) {
// Update the metadata // Update the metadata
this.props.setReview(this.props.current, this.increaseMeta(1, 0)); this.props.setReview(this.props.current, this.increaseMeta(1, 0));
this.props.setLastReview(this.props.metadata, this.sm2_metadata); this.props.setLastReview(this.props.metadata, this.sm2_metadata, this.score_delta);
this.props.setLoading(true); this.props.setLoading(true);
// Show the drawer button again // Show the drawer button again
@ -213,18 +216,9 @@ const ReviewPageWithRouter = withRouter(
} else if (minDist <= LEVENSHTEIN_MAX_DISTANCE) { } else if (minDist <= LEVENSHTEIN_MAX_DISTANCE) {
this.props.setPopover(true, "Das war fast richtig", "yellow", "black"); this.props.setPopover(true, "Das war fast richtig", "yellow", "black");
} else { } else {
// Find the IVocab item
/* const vocab = this.vocabFromId(this.props.current.id);
* if (vocab) {
* // Re-Add the vocabulary item to the review queue
* // TODO: Only re-add when it when it's not re-queued
* // vocabToReviewCard(vocab).forEach(this.reviewQueue.enqueue);
* } else {
* console.log("[ReviewPage::checkInput] Could not find IVocab item for wrong IReviewCard");
* }
*/
// Update the metadata // Update the metadata
this.updateGroupSM2(false); this.updateGroupSM2(false);
this.score_delta -= 1;
this.props.setReview(this.props.current, this.increaseMeta(0, 1)); this.props.setReview(this.props.current, this.increaseMeta(0, 1));
this.props.setPopover(true, "Das war nicht richtig", "red", "white"); this.props.setPopover(true, "Das war nicht richtig", "red", "white");
} }

View File

@ -202,6 +202,12 @@ export function LateinicusApp(state: IState = initialState, action: any) {
return Object.assign({}, state, { return Object.assign({}, state, {
lastReview: action.metadata, lastReview: action.metadata,
}); });
case Actions.SET_USER_SCORE_DELTA:
return Object.assign({}, state, {
user: Object.assign({}, state.user, {
score: state.user.score + action.delta,
}),
});
case Actions.REVIEW_SET_LOADING: case Actions.REVIEW_SET_LOADING:
return Object.assign({}, state, { return Object.assign({}, state, {
review: Object.assign({}, state.review, { review: Object.assign({}, state.review, {