feat: Implement SM2

This commit is contained in:
Alexander Polynomdivision
2018-09-30 16:17:54 +02:00
parent 64bcc932d7
commit 048f375724
8 changed files with 151 additions and 21 deletions

View File

@@ -106,7 +106,8 @@ export default class Application extends React.Component<IProps> {
});
}
setLastReview = (meta: IReviewMetadata) => {
// TODO: Type?
setLastReview = (meta: IReviewMetadata, sm2: any) => {
// Update the state
this.props.setLastReview(meta);
@@ -119,6 +120,7 @@ export default class Application extends React.Component<IProps> {
method: "POST",
body: JSON.stringify({
meta,
sm2,
}),
}).then(resp => resp.json(), err => {
console.log("Application::setLastReview: POSTing last results failed");

View File

@@ -33,6 +33,7 @@ interface IProps {
levelId?: number;
vocabByLevel?: (level: number) => Promise<IVocab[]>;
vocabByQueue?: () => Promise<IVocab[]>;
setLastReview: (meta: IReviewMetadata, sm2: any) => void;
reviewType: ReviewType;
history: any;
@@ -51,7 +52,6 @@ interface IProps {
setSummary: (state: boolean) => void;
setPopover: (state: boolean, text: string, color: string, textColor: string) => void;
drawerButtonState: (state: boolean) => void;
setLastReview: (meta: IReviewMetadata) => void;
setReview: (curent: IReviewCard, meta: IReviewMetadata) => void;
setLoading: (state: boolean) => void;
}
@@ -63,6 +63,7 @@ const ReviewPageWithRouter = withRouter(
// Used for positioning the popover
private buttonRef: HTMLButtonElement;
private inputRef: HTMLInputElement;
// Mapping: Vocab Id -> Correctly answered
private sm2_metadata: any = {};
constructor(props: any) {
@@ -133,6 +134,46 @@ const ReviewPageWithRouter = withRouter(
return this.vocab.find((el) => el.id === this.props.current.id);
}
// When a vocabulary item has been answered, we need to update
// the group's SuperMemo2-data.
// We update based on the following State-Machine: (C = Correct; W = Wrong)
// Answer | Group | New group
// | | state
// -------+-------+----------
// C | C | C
// C | W | W
// W | C | W
// W | W | W
// (1)C | - | C
// (2)W | - | W
// @correct: Was the answer given correct?
updateGroupSM2 = (correct: boolean) => {
const { id } = this.props.current;
switch (correct) {
case true:
// Case (1)
if (!(id in this.sm2_metadata)) {
this.sm2_metadata[id] = true;
break;
}
switch (this.sm2_metadata[id]) {
case true:
this.sm2_metadata[id] = true;
break;
case false:
this.sm2_metadata[id] = false;
break;
}
break;
case false:
// We don't need to explicitly catch case (2), as we set
// anything, that was incorrectly answered to false.
this.sm2_metadata[id] = false;
break;
}
}
checkInput = () => {
// Check if the given answer is somewhere in the german words
const input = this.inputRef.value || "";
@@ -146,12 +187,14 @@ const ReviewPageWithRouter = withRouter(
// Check if the user's answer was correct
if (minDist === 0) {
this.updateGroupSM2(true);
// TODO: Show it's correct?
// Show the next vocab word
if (this.reviewQueue.size() === 0) {
// Update the metadata
this.props.setReview(this.props.current, this.increaseMeta(1, 0));
this.props.setLastReview(this.props.metadata);
this.props.setLastReview(this.props.metadata, this.sm2_metadata);
this.props.setLoading(true);
// Show the drawer button again
@@ -163,6 +206,8 @@ const ReviewPageWithRouter = withRouter(
// Increase the vocab
this.props.setReview(this.reviewQueue.dequeue(), this.increaseMeta(1, 0));
this.inputRef.value = "";
// TODO(?): Show a snackbar for showing the updated score
}
} else if (minDist <= LEVENSHTEIN_MAX_DISTANCE) {
this.props.setPopover(true, "Das war fast richtig", "yellow", "black");
@@ -178,11 +223,10 @@ const ReviewPageWithRouter = withRouter(
* }
*/
// Update the metadata
this.updateGroupSM2(false);
this.props.setReview(this.props.current, this.increaseMeta(0, 1));
this.props.setPopover(true, "Das war nicht richtig", "red", "white");
}
// TODO(?): Show a snackbar for showing the updated score
}
render() {