Skip to content

Commit

Permalink
Process input in batch and prevent postfix overrun
Browse files Browse the repository at this point in the history
  • Loading branch information
na2hiro committed Apr 26, 2024
1 parent 124bca6 commit 81fea7e
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 41 deletions.
114 changes: 74 additions & 40 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,43 @@
import React, { Component } from 'react';
import React, { Component } from "react";
import "react-tippy/dist/tippy.css";
import PARAMS from './utils/params.js';
import { isLessonTextValid } from './utils/utils';
import { getLessonIndexData } from './utils/lessonIndexData';
import { getRecommendedNextLesson } from './utils/recommendations';
import { getFlashcardsNextLesson } from './utils/flashcardsRecommendations';
import PARAMS from "./utils/params.js";
import { isLessonTextValid } from "./utils/utils";
import { getLessonIndexData } from "./utils/lessonIndexData";
import { getRecommendedNextLesson } from "./utils/recommendations";
import { getFlashcardsNextLesson } from "./utils/flashcardsRecommendations";
import {
createWordListFromMetWords,
parseCustomMaterial,
parseWordList,
setupLessonProgress,
getTargetStrokeCount,
loadPersonalPreferences,
matchSplitText,
parseCustomMaterial,
parseLesson,
parseWordList,
repetitionsRemaining,
setupLessonProgress,
shouldShowStroke,
strokeAccuracy,
getTargetStrokeCount,
updateCapitalisationStrokesInNextItem,
writePersonalPreferences
} from './utils/typey-type';
import { fetchDictionaryIndex, getLesson } from './utils/getData';
} from "./utils/typey-type";
import { fetchDictionaryIndex, getLesson } from "./utils/getData";
import describePunctuation, { punctuationDescriptions } from "./utils/describePunctuation";
import {
generateListOfWordsAndStrokes
} from './utils/transformingDictionaries/transformingDictionaries';
import queryString from 'query-string';
import { generateListOfWordsAndStrokes } from "./utils/transformingDictionaries/transformingDictionaries";
import queryString from "query-string";
import GoogleAnalytics from "react-ga4";
import fallbackLesson from './constant/fallbackLesson';
import fetchAndSetupGlobalDict from './utils/app/fetchAndSetupGlobalDict';
import calculateMemorisedWordCount from './utils/calculateMemorisedWordCount';
import calculateSeenWordCount from './utils/calculateSeenWordCount';
import increaseMetWords from './utils/increaseMetWords';
import filterByFamiliarity from './utils/lessons/filterByFamiliarity';
import replaceSmartTypographyInPresentedMaterial from './utils/lessons/replaceSmartTypographyInPresentedMaterial';
import sortLesson from './utils/lessons/sortLesson';
import Zipper from './utils/zipper';
import generateCustomLesson from './pages/lessons/custom/generator/utilities/generateCustomLesson';
import customiseLesson from './pages/lessons/utilities/customiseLesson';
import setCustomLessonContent from './pages/lessons/utilities/setCustomLessonContent';
import updateMultipleMetWords from './pages/games/KPOES/updateMultipleMetWords';
import fallbackLesson from "./constant/fallbackLesson";
import fetchAndSetupGlobalDict from "./utils/app/fetchAndSetupGlobalDict";
import calculateMemorisedWordCount from "./utils/calculateMemorisedWordCount";
import calculateSeenWordCount from "./utils/calculateSeenWordCount";
import increaseMetWords from "./utils/increaseMetWords";
import filterByFamiliarity from "./utils/lessons/filterByFamiliarity";
import replaceSmartTypographyInPresentedMaterial from "./utils/lessons/replaceSmartTypographyInPresentedMaterial";
import sortLesson from "./utils/lessons/sortLesson";
import Zipper from "./utils/zipper";
import generateCustomLesson from "./pages/lessons/custom/generator/utilities/generateCustomLesson";
import customiseLesson from "./pages/lessons/utilities/customiseLesson";
import setCustomLessonContent from "./pages/lessons/utilities/setCustomLessonContent";
import updateMultipleMetWords from "./pages/games/KPOES/updateMultipleMetWords";
import {
changeShowScoresWhileTyping,
changeShowStrokesAs,
Expand All @@ -59,23 +57,23 @@ import {
handleUpcomingWordsLayout,
toggleHideOtherSettings,
updatePreset
} from './pages/lessons/components/UserSettings/updateUserSetting';
} from "./pages/lessons/components/UserSettings/updateUserSetting";
import {
changeShowStrokesInLesson,
updateRevisionMaterial,
} from './pages/lessons/components/UserSettings/updateLessonSetting';
updateRevisionMaterial
} from "./pages/lessons/components/UserSettings/updateLessonSetting";
import {
changeWriterInput,
dismissBackupBanner,
toggleExperiment
} from './pages/lessons/components/UserSettings/updateGlobalUserSetting';
} from "./pages/lessons/components/UserSettings/updateGlobalUserSetting";
import {
changeFlashcardCourseLevel,
changeFullscreen,
} from './pages/lessons/components/UserSettings/updateFlashcardSetting';
import AppRoutes from './AppRoutes';
import applyQueryParamsToUserSettings from './pages/lessons/components/UserSettings/applyQueryParamsToUserSettings';
import removeIgnoredCharsFromSplitText from './utils/app/removeIgnoredCharsFromSplitText';
changeFullscreen
} from "./pages/lessons/components/UserSettings/updateFlashcardSetting";
import AppRoutes from "./AppRoutes";
import applyQueryParamsToUserSettings from "./pages/lessons/components/UserSettings/applyQueryParamsToUserSettings";
import removeIgnoredCharsFromSplitText from "./utils/app/removeIgnoredCharsFromSplitText";

/** @type {SpeechSynthesis | null} */
let synth = null;
Expand Down Expand Up @@ -1135,9 +1133,33 @@ class App extends Component {
});
}

markupBuffer = [];
updateBufferTimer = null;

updateMarkup(event) {
let actualText = event.target.value;
// TODO: remove cookie thing before merging
const batchUpdate = document.cookie.indexOf("batchUpdate=1")>=0;
if(!batchUpdate) {
this.updateBufferSingle(actualText, false);
return;
}
// Immediately update the text in the input field
this.setState({ actualText });
this.markupBuffer.push(actualText);

if (this.updateBufferTimer) {
clearTimeout(this.updateBufferTimer);
}
this.updateBufferTimer = setTimeout(() => {
// TODO: do we need char-level processing for stats? If not, only store latest
const latest = this.markupBuffer[this.markupBuffer.length - 1];
this.markupBuffer = [];
this.updateBufferSingle(latest, true);
}, 16); // 60fps
}

updateBufferSingle(actualText, batchUpdate) {
// Start timer on first key stroke
if (this.state.startTime === null) {
this.setState({
Expand Down Expand Up @@ -1193,7 +1215,17 @@ class App extends Component {
this.setState({showStrokesInLesson: true});
}

if (numberOfUnmatchedChars === 0) {
let proceedToNextWord;
if (batchUpdate) {
// e.g. unmatchedActual is "es" if "Frenches" is typed for "French"
// In case of spaceAfterOutput, unmatchedChars is not empty and don't care here.
// In case of spaceExact, proceed without checking next actual chars.
const excessLookFine = this.state.userSettings.spacePlacement === "spaceAfterOutput" || this.state.userSettings.spacePlacement === "spaceExact" || unmatchedActual.length === 0 || unmatchedActual[0] === " ";
proceedToNextWord = numberOfUnmatchedChars === 0 && excessLookFine;
} else {
proceedToNextWord = numberOfUnmatchedChars === 0;
}
if (proceedToNextWord) {
newState.currentPhraseAttempts = []; // reset for next word
newState.currentLessonStrokes = this.state.currentLessonStrokes; // [{word: "cat", attempts: ["cut"], stroke: "KAT"}, {word: "sciences", attempts ["sign", "ss"], stroke: "SAOEUPB/EPBC/-S"]

Expand Down Expand Up @@ -1251,7 +1283,7 @@ class App extends Component {
newState.repetitionsRemaining = repetitionsRemaining(this.state.userSettings, this.state.lesson.presentedMaterial, this.state.currentPhraseID + 1);
newState.totalNumberOfMatchedChars = this.state.totalNumberOfMatchedChars + numberOfMatchedChars;
newState.previousCompletedPhraseAsTyped = actualText;
newState.actualText = '';
newState.actualText = batchUpdate ? unmatchedActual : '';
newState.showStrokesInLesson = false;
newState.currentPhraseID = nextPhraseID;

Expand All @@ -1262,6 +1294,8 @@ class App extends Component {
this.setState(newState, () => {
if (this.isFinished()) {
this.stopLesson();
} else if(batchUpdate && proceedToNextWord && unmatchedActual.length>0) {
this.updateBufferSingle(unmatchedActual);
}
});
}
Expand Down
4 changes: 3 additions & 1 deletion src/App.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ describe(App, () => {
).toMatchInlineSnapshot(
`"You can lead a horse to water but you can't make it drink. You can't have it both ways. You can't have your cake and eat it too. You can't make an omelette without breaking eggs. You can't make a silk purse out of a You can lead a horse to water but you can't make it drink. You can't have it both ways. You can't have your cake and eat it too. You can't make an omelette without breaking eggs. You can't make a silk purse out of a You can lead a horse to water but you can't make it drink. You can't have it both ways. You can't have your cake and eat it too. You can't make an omelette without breaking eggs. You can't make a silk purse out of a"`
);
document.cookie = "batchUpdate=1";
});

function getStatsState() {
Expand Down Expand Up @@ -157,6 +158,7 @@ describe(App, () => {
});
// Current behavior
it("accepts excess chars", async () => {
document.cookie = "batchUpdate=0";
// This user with spaceOff setting actually puts space after
const spBefore = spacePlacement === "spaceBeforeOutput" ? " " : "";
const spAfter = spacePlacement === "spaceAfterOutput" || spacePlacement === "spaceOff" ? " " : "";
Expand Down Expand Up @@ -210,7 +212,7 @@ describe(App, () => {
);
});
// Future behavior
it.skip("doesn't accept excess chars", async () => {
it("doesn't accept excess chars", async () => {
// This user with spaceOff setting actually puts space before
const spBefore = spacePlacement === "spaceBeforeOutput" || spacePlacement === "spaceOff" ? " " : "";
const spAfter = spacePlacement === "spaceAfterOutput" ? " " : "";
Expand Down

0 comments on commit 81fea7e

Please sign in to comment.