import * as TestLogic from "./test-logic"; import * as TestUI from "./test-ui"; import * as TestStats from "./test-stats"; import * as Monkey from "./monkey"; import Config, * as UpdateConfig from "./config"; import * as Keymap from "./keymap"; import * as Misc from "./misc"; import * as LiveAcc from "./live-acc"; import * as LiveBurst from "./live-burst"; import * as Funbox from "./funbox"; import * as Sound from "./sound"; import * as Caret from "./caret"; import * as ManualRestart from "./manual-restart-tracker"; import * as Notifications from "./notifications"; import * as CustomText from "./custom-text"; import * as UI from "./ui"; import * as Settings from "./settings"; import * as LayoutEmulator from "./layout-emulator"; import * as PaceCaret from "./pace-caret"; import * as TimerProgress from "./timer-progress"; import * as TestTimer from "./test-timer"; import * as Focus from "./focus"; import * as ShiftTracker from "./shift-tracker"; import * as Replay from "./replay.js"; import * as MonkeyPower from "./monkey-power"; import * as WeakSpot from "./weak-spot"; $("#wordsInput").keypress((event) => { event.preventDefault(); }); let dontInsertSpace = false; function handleTab(event) { if (TestUI.resultCalculating) { event.preventDefault(); } if ( !$("#presetWrapper").hasClass("hidden") || !$("#tagsWrapper").hasClass("hidden") ) { event.preventDefault(); return; } if ($("#customTextPopup .textarea").is(":focus")) { event.preventDefault(); let area = $("#customTextPopup .textarea")[0]; var start = area.selectionStart; var end = area.selectionEnd; // set textarea value to: text before caret + tab + text after caret area.value = area.value.substring(0, start) + "\t" + area.value.substring(end); // put caret at right position again area.selectionStart = area.selectionEnd = start + 1; // event.preventDefault(); // $("#customTextPopup .textarea").val( // $("#customTextPopup .textarea").val() + "\t" // ); return; } else if ( !TestUI.resultCalculating && $("#commandLineWrapper").hasClass("hidden") && $("#simplePopupWrapper").hasClass("hidden") && !$(".page.pageLogin").hasClass("active") ) { if ($(".pageTest").hasClass("active")) { if (Config.quickTab) { if ( (Config.mode == "zen" && !event.shiftKey) || (TestLogic.hasTab && !event.shiftKey) ) { //ignore } else { if (event.shiftKey) { ManualRestart.set(); } else { ManualRestart.reset(); } event.preventDefault(); if ( TestLogic.active && Config.repeatQuotes === "typing" && Config.mode === "quote" ) { TestLogic.restart(true, false, event); } else { TestLogic.restart(false, false, event); } } } else { if ( !TestUI.resultVisible && ((TestLogic.hasTab && event.shiftKey) || (!TestLogic.hasTab && Config.mode !== "zen") || (Config.mode === "zen" && event.shiftKey)) ) { event.preventDefault(); $("#restartTestButton").focus(); } } } else if (Config.quickTab) { UI.changePage("test"); } } } function handleBackspace(event) { event.preventDefault(); if (!TestLogic.active) return; if ( TestLogic.input.current == "" && TestLogic.input.history.length > 0 && TestUI.currentWordElementIndex > 0 ) { //if nothing is inputted and its not the first word if ( (TestLogic.input.getHistory(TestLogic.words.currentIndex - 1) == TestLogic.words.get(TestLogic.words.currentIndex - 1) && !Config.freedomMode) || $($(".word")[TestLogic.words.currentIndex - 1]).hasClass("hidden") ) { return; } else { if (Config.confidenceMode === "on" || Config.confidenceMode === "max") return; if (event["ctrlKey"] || event["altKey"]) { TestLogic.input.resetCurrent(); TestLogic.input.popHistory(); TestLogic.corrected.popHistory(); } else { TestLogic.input.setCurrent(TestLogic.input.popHistory()); TestLogic.corrected.setCurrent(TestLogic.corrected.popHistory()); if (Config.funbox === "nospace") { TestLogic.input.setCurrent( TestLogic.input.current.substring( 0, TestLogic.input.current.length - 1 ) ); } } TestLogic.words.decreaseCurrentIndex(); Replay.addReplayEvent("backWord"); TestUI.setCurrentWordElementIndex(TestUI.currentWordElementIndex - 1); TestUI.updateActiveElement(true); Funbox.toggleScript(TestLogic.words.getCurrent()); TestUI.updateWordElement(!Config.blindMode); } } else if (TestLogic.input.current !== "") { if (Config.confidenceMode === "max") return; if (event["ctrlKey"] || event["altKey"] || event.metaKey) { Replay.addReplayEvent("clearWord"); // let limiter = " "; // if ( // TestLogic.input.current.lastIndexOf("-") > // TestLogic.input.current.lastIndexOf(" ") // ) // limiter = "-"; // let split = TestLogic.input.current.replace(/ +/g, " ").split(limiter); // if (split[split.length - 1] == "") { // split.pop(); // } // let addlimiter = false; // if (split.length > 1) { // addlimiter = true; // } // split.pop(); // TestLogic.input.setCurrent(split.join(limiter)); // if (addlimiter) { // TestLogic.input.appendCurrent(limiter); // } if ( /^[ £§`~!@#$%^&*()_+\\\-=[\]{};':"|,./<>?]*$/g.test( TestLogic.input.getCurrent() ) ) { //pop current and previous TestLogic.input.resetCurrent(); TestLogic.input.popHistory(); TestLogic.corrected.popHistory(); TestUI.updateWordElement(!Config.blindMode); TestLogic.words.decreaseCurrentIndex(); Replay.addReplayEvent("backWord"); TestUI.setCurrentWordElementIndex(TestUI.currentWordElementIndex - 1); TestUI.updateActiveElement(true); Funbox.toggleScript(TestLogic.words.getCurrent()); TestUI.updateWordElement(!Config.blindMode); TestLogic.input.resetCurrent(); } else { const regex = new RegExp( /[ £§`~!@#$%^&*()_+\\\-=[\]{};':"|,./<>?]/, "g" ); let input = TestLogic.input.getCurrent(); regex.test(input); // let puncIndex = regex.lastIndex; let puncIndex = input.lastIndexOfRegex( /[ £§`~!@#$%^&*()_+\\\-=[\]{};':"|,./<>?]/g ); while ( /[ £§`~!@#$%^&*()_+\\\-=[\]{};':"|,./<>?]/g.test(input.slice(-1)) ) { input = input.substring(0, input.length - 1); } puncIndex = input.lastIndexOfRegex( /[ £§`~!@#$%^&*()_+\\\-=[\]{};':"|,./<>?]/g ); TestLogic.input.setCurrent( input.substring(0, puncIndex == 0 ? 0 : puncIndex + 1) ); } } else { TestLogic.input.setCurrent( TestLogic.input.current.substring(0, TestLogic.input.current.length - 1) ); Replay.addReplayEvent("deleteLetter"); } TestUI.updateWordElement(!Config.blindMode); } Sound.playClick(Config.playSoundOnClick); if (Config.keymapMode === "react") { Keymap.flashKey(event.code, true); } else if (Config.keymapMode === "next" && Config.mode !== "zen") { Keymap.highlightKey( TestLogic.words .getCurrent() .substring( TestLogic.input.current.length, TestLogic.input.current.length + 1 ) .toString() .toUpperCase() ); } Caret.updatePosition(); } function handleSpace(event, isEnter) { if (!TestLogic.active) return; if (TestLogic.input.current === "") return; // let nextWord = wordsList[TestLogic.words.currentIndex + 1]; // if ((isEnter && nextWord !== "\n") && (isEnter && Config.funbox !== "58008")) return; // if (!isEnter && nextWord === "\n") return; event.preventDefault(); if (Config.mode == "zen") { $("#words .word.active").removeClass("active"); $("#words").append("
"); } let currentWord = TestLogic.words.getCurrent(); if (Config.funbox === "layoutfluid" && Config.mode !== "time") { // here I need to check if Config.customLayoutFluid exists because of my scuffed solution of returning whenever value is undefined in the setCustomLayoutfluid function const layouts = Config.customLayoutfluid ? Config.customLayoutfluid.split("#") : ["qwerty", "dvorak", "colemak"]; let index = 0; let outof = TestLogic.words.length; index = Math.floor( (TestLogic.input.history.length + 1) / (outof / layouts.length) ); if (Config.layout !== layouts[index] && layouts[index] !== undefined) { Notifications.add(`--- !!! ${layouts[index]} !!! ---`, 0); } UpdateConfig.setLayout(layouts[index]); UpdateConfig.setKeymapLayout(layouts[index]); Keymap.highlightKey( TestLogic.words .getCurrent() .substring( TestLogic.input.current.length, TestLogic.input.current.length + 1 ) .toString() .toUpperCase() ); Settings.groups.layout.updateButton(); } dontInsertSpace = true; let burst = TestStats.calculateBurst(); LiveBurst.update(Math.round(burst)); TestStats.pushBurstToHistory(burst); if (currentWord == TestLogic.input.current || Config.mode == "zen") { //correct word or in zen mode MonkeyPower.addPower(true, true); PaceCaret.handleSpace(true, currentWord); TestStats.incrementAccuracy(true); TestLogic.input.pushHistory(); TestLogic.words.increaseCurrentIndex(); TestUI.setCurrentWordElementIndex(TestUI.currentWordElementIndex + 1); TestUI.updateActiveElement(); Funbox.toggleScript(TestLogic.words.getCurrent()); Caret.updatePosition(); TestStats.incrementKeypressCount(); TestStats.pushKeypressWord(TestLogic.words.currentIndex); // currentKeypress.count++; // currentKeypress.words.push(TestLogic.words.currentIndex); if (Config.funbox !== "nospace") { Sound.playClick(Config.playSoundOnClick); } Replay.addReplayEvent("submitCorrectWord"); } else { //incorrect word MonkeyPower.addPower(false, true); if (Config.funbox !== "nospace") { if (!Config.playSoundOnError || Config.blindMode) { Sound.playClick(Config.playSoundOnClick); } else { Sound.playError(Config.playSoundOnError); } } TestStats.pushMissedWord(TestLogic.words.getCurrent()); TestStats.incrementAccuracy(false); TestStats.incrementKeypressErrors(); let cil = TestLogic.input.current.length; if (cil <= TestLogic.words.getCurrent().length) { if (cil >= TestLogic.corrected.current.length) { TestLogic.corrected.appendCurrent("_"); } else { TestLogic.corrected.setCurrent( TestLogic.corrected.current.substring(0, cil) + "_" + TestLogic.corrected.current.substring(cil + 1) ); } } if (Config.stopOnError != "off") { if (Config.difficulty == "expert" || Config.difficulty == "master") { //failed due to diff when pressing space TestLogic.fail("difficulty"); return; } if (Config.stopOnError == "word") { TestLogic.input.appendCurrent(" "); Replay.addReplayEvent("incorrectLetter", "_"); TestUI.updateWordElement(true); Caret.updatePosition(); } return; } PaceCaret.handleSpace(false, currentWord); if (Config.blindMode) $("#words .word.active letter").addClass("correct"); TestLogic.input.pushHistory(); TestUI.highlightBadWord(TestUI.currentWordElementIndex, !Config.blindMode); TestLogic.words.increaseCurrentIndex(); TestUI.setCurrentWordElementIndex(TestUI.currentWordElementIndex + 1); TestUI.updateActiveElement(); Funbox.toggleScript(TestLogic.words.getCurrent()); Caret.updatePosition(); // currentKeypress.count++; // currentKeypress.words.push(TestLogic.words.currentIndex); TestStats.incrementKeypressCount(); TestStats.pushKeypressWord(TestLogic.words.currentIndex); TestStats.updateLastKeypress(); if (Config.difficulty == "expert" || Config.difficulty == "master") { TestLogic.fail("difficulty"); return; } else if (TestLogic.words.currentIndex == TestLogic.words.length) { //submitted last word that is incorrect TestLogic.finish(); return; } Replay.addReplayEvent("submitErrorWord"); } let wordLength; if (Config.mode === "zen") { wordLength = TestLogic.input.getCurrent().length; } else { wordLength = TestLogic.words.getCurrent().length; } let flex = Misc.whorf(Config.minBurstCustomSpeed, wordLength); if ( (Config.minBurst === "fixed" && burst < Config.minBurstCustomSpeed) || (Config.minBurst === "flex" && burst < flex) ) { TestLogic.fail("min burst"); return; } TestLogic.corrected.pushHistory(); if ( !Config.showAllLines || Config.mode == "time" || (CustomText.isWordRandom && CustomText.word == 0) || CustomText.isTimeRandom ) { let currentTop = Math.floor( document.querySelectorAll("#words .word")[ TestUI.currentWordElementIndex - 1 ].offsetTop ); let nextTop; try { nextTop = Math.floor( document.querySelectorAll("#words .word")[ TestUI.currentWordElementIndex ].offsetTop ); } catch (e) { nextTop = 0; } if (nextTop > currentTop && !TestUI.lineTransition) { TestUI.lineJump(currentTop); } } //end of line wrap // Caret.updatePosition(); if (Config.keymapMode === "react") { Keymap.flashKey(event.code, true); } else if (Config.keymapMode === "next" && Config.mode !== "zen") { Keymap.highlightKey( TestLogic.words .getCurrent() .substring( TestLogic.input.current.length, TestLogic.input.current.length + 1 ) .toString() .toUpperCase() ); } if ( Config.mode === "words" || Config.mode === "custom" || Config.mode === "quote" || Config.mode === "zen" ) { TimerProgress.update(TestTimer.time); } if ( Config.mode == "time" || Config.mode == "words" || Config.mode == "custom" ) { TestLogic.addWord(); } } function handleAlpha(event) { if ( [ "ContextMenu", "Escape", "Shift", "Control", "Meta", "Alt", "AltGraph", "CapsLock", "Backspace", "PageUp", "PageDown", "Home", "ArrowUp", "ArrowLeft", "ArrowRight", "ArrowDown", "OS", "Insert", "Home", "Undefined", "Control", "Fn", "FnLock", "Hyper", "NumLock", "ScrollLock", "Symbol", "SymbolLock", "Super", "Unidentified", "Process", "Delete", "KanjiMode", "Pause", "PrintScreen", "Clear", "End", "GroupPrevious", "GroupNext", "WakeUp", undefined, ].includes(event.key) ) { TestStats.incrementKeypressMod(); // currentKeypress.mod++; return; } //insert space for expert and master or strict space, //otherwise dont do anything if (event.key === " ") { if (Config.difficulty !== "normal" || Config.strictSpace) { if (dontInsertSpace) { dontInsertSpace = false; return; } } else { return; } } if (event.key === "Tab") { if ( Config.mode !== "zen" && (!TestLogic.hasTab || (TestLogic.hasTab && event.shiftKey)) ) { return; } event.key = "\t"; event.preventDefault(); } if (event.key === "Enter") { if (event.shiftKey && Config.mode == "zen") { TestLogic.finish(); } if ( event.shiftKey && ((Config.mode == "time" && Config.time === 0) || (Config.mode == "words" && Config.words === 0)) ) { TestLogic.setBailout(true); TestLogic.finish(); } event.key = "\n"; } // if (event.key.length > 1) return; if (/F\d+/.test(event.key)) return; if (/Numpad/.test(event.key)) return; if (/Volume/.test(event.key)) return; if (/Media/.test(event.key)) return; if ( event.ctrlKey != event.altKey && (event.ctrlKey || /Linux/.test(window.navigator.platform)) ) return; if (event.metaKey) return; let originalEvent = { code: event.code, }; event = LayoutEmulator.updateEvent(event); //start the test if ( TestLogic.input.current == "" && TestLogic.input.history.length == 0 && !TestLogic.active ) { if (!TestLogic.startTest()) return; MonkeyPower.addPower(); } else { if (!TestLogic.active) return; } if (TestLogic.input.current == "") { TestStats.setBurstStart(performance.now()); } Focus.set(true); Caret.stopAnimation(); //show dead keys if (event.key === "Dead") { Sound.playClick(Config.playSoundOnClick); $( document.querySelector("#words .word.active").querySelectorAll("letter")[ TestLogic.input.current.length ] ).toggleClass("dead"); return; } //check if the char typed was correct let thisCharCorrect; let nextCharInWord; if (Config.mode != "zen") { nextCharInWord = TestLogic.words .getCurrent() .substring( TestLogic.input.current.length, TestLogic.input.current.length + 1 ); } if (nextCharInWord == event["key"]) { thisCharCorrect = true; } else { thisCharCorrect = false; } if (Config.language.split("_")[0] == "russian") { if ((event.key === "е" || event.key === "e") && nextCharInWord == "ё") { event.key = nextCharInWord; thisCharCorrect = true; } if ( event.key === "ё" && (nextCharInWord == "е" || nextCharInWord === "e") ) { event.key = nextCharInWord; thisCharCorrect = true; } } if (Config.mode == "zen") { thisCharCorrect = true; } if ( (event.key === `’` || event.key === `‘` || event.key === "'") && (nextCharInWord == `’` || nextCharInWord === `‘` || nextCharInWord === "'") ) { event.key = nextCharInWord; thisCharCorrect = true; } if ( (event.key === `"` || event.key === "”" || event.key == "“" || event.key === "„") && (nextCharInWord == `"` || nextCharInWord === "”" || nextCharInWord === "“" || nextCharInWord === "„") ) { event.key = nextCharInWord; thisCharCorrect = true; } if ( (event.key === "–" || event.key === "—" || event.key == "-") && (nextCharInWord == "-" || nextCharInWord === "–" || nextCharInWord === "—") ) { event.key = nextCharInWord; thisCharCorrect = true; } if ( Config.oppositeShiftMode === "on" && ShiftTracker.isUsingOppositeShift(originalEvent) === false ) { thisCharCorrect = false; } MonkeyPower.addPower(thisCharCorrect); if (!thisCharCorrect) { TestStats.incrementAccuracy(false); TestStats.incrementKeypressErrors(); // currentError.count++; // currentError.words.push(TestLogic.words.currentIndex); thisCharCorrect = false; TestStats.pushMissedWord(TestLogic.words.getCurrent()); } else { TestStats.incrementAccuracy(true); thisCharCorrect = true; if (Config.mode == "zen") { //making the input visible to the user $("#words .active").append( `${event.key}` ); } } WeakSpot.updateScore(nextCharInWord, thisCharCorrect); if (thisCharCorrect) { Sound.playClick(Config.playSoundOnClick); } else { if (!Config.playSoundOnError || Config.blindMode) { Sound.playClick(Config.playSoundOnClick); } else { Sound.playError(Config.playSoundOnError); } } if ( Config.oppositeShiftMode === "on" && ShiftTracker.isUsingOppositeShift(originalEvent) === false ) return; //update current corrected verison. if its empty then add the current key. if its not then replace the last character with the currently pressed one / add it if (TestLogic.corrected.current === "") { TestLogic.corrected.setCurrent(TestLogic.input.current + event["key"]); } else { let cil = TestLogic.input.current.length; if (cil >= TestLogic.corrected.current.length) { TestLogic.corrected.appendCurrent(event["key"]); } else if (!thisCharCorrect) { TestLogic.corrected.setCurrent( TestLogic.corrected.current.substring(0, cil) + event["key"] + TestLogic.corrected.current.substring(cil + 1) ); } } TestStats.incrementKeypressCount(); TestStats.updateLastKeypress(); TestStats.pushKeypressWord(TestLogic.words.currentIndex); // currentKeypress.count++; // currentKeypress.words.push(TestLogic.words.currentIndex); if (Config.stopOnError == "letter" && !thisCharCorrect) { return; } Replay.addReplayEvent( thisCharCorrect ? "correctLetter" : "incorrectLetter", event.key ); //update the active word top, but only once if ( TestLogic.input.current.length === 1 && TestLogic.words.currentIndex === 0 ) { TestUI.setActiveWordTop(document.querySelector("#words .active").offsetTop); } //max length of the input is 20 unless in zen mode then its 30 if ( (Config.mode == "zen" && TestLogic.input.current.length < 30) || (Config.mode !== "zen" && TestLogic.input.current.length < TestLogic.words.getCurrent().length + 20) ) { TestLogic.input.appendCurrent(event["key"]); } if (!thisCharCorrect && Config.difficulty == "master") { TestLogic.input.pushHistory(); TestLogic.corrected.pushHistory(); TestLogic.fail("difficulty"); return; } //keymap if (Config.keymapMode === "react") { Keymap.flashKey(event.key, thisCharCorrect); } else if (Config.keymapMode === "next" && Config.mode !== "zen") { Keymap.highlightKey( TestLogic.words .getCurrent() .substring( TestLogic.input.current.length, TestLogic.input.current.length + 1 ) .toString() .toUpperCase() ); } let activeWordTopBeforeJump = TestUI.activeWordTop; TestUI.updateWordElement(!Config.blindMode); if (Config.mode != "zen") { //not applicable to zen mode //auto stop the test if the last word is correct let currentWord = TestLogic.words.getCurrent(); let lastindex = TestLogic.words.currentIndex; if ( (currentWord == TestLogic.input.current || (Config.quickEnd && currentWord.length == TestLogic.input.current.length && Config.stopOnError == "off")) && lastindex == TestLogic.words.length - 1 ) { TestLogic.input.pushHistory(); TestLogic.corrected.pushHistory(); TestLogic.finish(); } } //simulate space press in nospace funbox if ( (Config.funbox === "nospace" && TestLogic.input.current.length === TestLogic.words.getCurrent().length) || (event.key === "\n" && thisCharCorrect) ) { $.event.trigger({ type: "keydown", which: " ".charCodeAt(0), key: " ", }); } let newActiveTop = document.querySelector("#words .word.active").offsetTop; //stop the word jump by slicing off the last character, update word again if ( activeWordTopBeforeJump < newActiveTop && !TestUI.lineTransition && TestLogic.input.current.length > 1 ) { if (Config.mode == "zen") { let currentTop = Math.floor( document.querySelectorAll("#words .word")[ TestUI.currentWordElementIndex - 1 ].offsetTop ); if (!Config.showAllLines) TestUI.lineJump(currentTop); } else { TestLogic.input.setCurrent(TestLogic.input.current.slice(0, -1)); TestUI.updateWordElement(!Config.blindMode); } } if (originalEvent.code !== "Enter") Caret.updatePosition(); } $(document).keyup((event) => { if (!event.originalEvent.isTrusted) return; if (TestUI.resultVisible) return; let now = performance.now(); let diff = Math.abs(TestStats.keypressTimings.duration.current - now); if (TestStats.keypressTimings.duration.current !== -1) { TestStats.pushKeypressDuration(diff); // keypressStats.duration.array.push(diff); } TestStats.setKeypressDuration(now); // keypressStats.duration.current = now; Monkey.stop(); }); $(document).keydown(function (event) { if (!(event.key == " ") && !event.originalEvent.isTrusted) return; if (!TestUI.resultVisible) { TestStats.recordKeypressSpacing(); } Monkey.type(); //autofocus let pageTestActive = !$(".pageTest").hasClass("hidden"); let commandLineVisible = !$("#commandLineWrapper").hasClass("hidden"); let leaderboardsVisible = !$("#leaderboardsWrapper").hasClass("hidden"); let wordsFocused = $("#wordsInput").is(":focus"); let modePopupVisible = !$("#customTextPopupWrapper").hasClass("hidden") || !$("#customWordAmountPopupWrapper").hasClass("hidden") || !$("#customTestDurationPopupWrapper").hasClass("hidden") || !$("#quoteSearchPopupWrapper").hasClass("hidden") || !$("#wordFilterPopupWrapper").hasClass("hidden"); if ( pageTestActive && !commandLineVisible && !leaderboardsVisible && !modePopupVisible && !TestUI.resultVisible && !wordsFocused && event.key !== "Enter" ) { TestUI.focusWords(); wordsFocused = true; if (Config.showOutOfFocusWarning) return; } //tab if ( (event.key == "Tab" && !Config.swapEscAndTab) || (event.key == "Escape" && Config.swapEscAndTab) ) { handleTab(event); // event.preventDefault(); } //blocking firefox from going back in history with backspace if (event.key === "Backspace" && wordsFocused) { let t = /INPUT|SELECT|TEXTAREA/i; if ( !t.test(event.target.tagName) || event.target.disabled || event.target.readOnly ) { event.preventDefault(); } } // keypressStats.duration.current = performance.now(); TestStats.setKeypressDuration(performance.now()); if (TestUI.testRestarting) { return; } //backspace const isBackspace = event.key === "Backspace" || (Config.capsLockBackspace && event.key === "CapsLock"); if (isBackspace && wordsFocused) { handleBackspace(event); } if (event.key === "Enter" && Config.funbox === "58008" && wordsFocused) { event.key = " "; } //space or enter if (event.key === " " && wordsFocused) { handleSpace(event, false); } if (wordsFocused && !commandLineVisible && !leaderboardsVisible) { handleAlpha(event); } let acc = Misc.roundTo2(TestStats.calculateAccuracy()); LiveAcc.update(acc); });