From 29cfe8d9325e3f2b5ce941698d4f1c3b9717d6a2 Mon Sep 17 00:00:00 2001 From: Dilyorbek <62857168+drdilyor@users.noreply.github.com> Date: Tue, 4 Apr 2023 03:56:39 +0500 Subject: [PATCH] Fix duration ordering and new algorithm for key overlap (#4141) drdilyor * test2 * mod2 * mod3 * fix incomplete keystrokes now have duration * make loop go forward for readability * check if keysorder is empty * prettier * clean up * rename variables for readability * remove the algorithm and debug info * type casting * merged objects into one moved code around * removed "toolong" clientside type * fixed assignment --------- Co-authored-by: Miodec --- frontend/src/ts/test/test-input.ts | 162 +++++++++++++++-------------- frontend/src/ts/test/test-logic.ts | 6 +- 2 files changed, 86 insertions(+), 82 deletions(-) diff --git a/frontend/src/ts/test/test-input.ts b/frontend/src/ts/test/test-input.ts index 5f784ee44..f298b1a46 100644 --- a/frontend/src/ts/test/test-input.ts +++ b/frontend/src/ts/test/test-input.ts @@ -1,6 +1,57 @@ import * as TestWords from "./test-words"; import { mean, roundTo2 } from "../utils/misc"; +const keysToTrack = [ + "Backquote", + "Digit1", + "Digit2", + "Digit3", + "Digit4", + "Digit5", + "Digit6", + "Digit7", + "Digit8", + "Digit9", + "Digit0", + "Minus", + "Equal", + "KeyQ", + "KeyW", + "KeyE", + "KeyR", + "KeyT", + "KeyY", + "KeyU", + "KeyI", + "KeyO", + "KeyP", + "BracketLeft", + "BracketRight", + "Backslash", + "KeyA", + "KeyS", + "KeyD", + "KeyF", + "KeyG", + "KeyH", + "KeyJ", + "KeyK", + "KeyL", + "Semicolon", + "Quote", + "KeyZ", + "KeyX", + "KeyC", + "KeyV", + "KeyB", + "KeyN", + "KeyM", + "Comma", + "Period", + "Slash", + "Space", +]; + interface Keypress { count: number; errors: number; @@ -11,13 +62,18 @@ interface Keypress { interface KeypressTimings { spacing: { last: number; - array: number[] | "toolong"; + array: number[]; }; duration: { - array: number[] | "toolong"; + array: number[]; }; } +interface Keydata { + timestamp: number; + index: number; +} + class Input { current: string; history: string[]; @@ -136,6 +192,8 @@ class Corrected { } } +let keyDownData: Record = {}; + export const input = new Input(); export const corrected = new Corrected(); @@ -224,98 +282,49 @@ export function incrementAccuracy(correctincorrect: boolean): void { } } -export function setKeypressTimingsTooLong(): void { - keypressTimings.spacing.array = "toolong"; - keypressTimings.duration.array = "toolong"; -} - -let keysObj: Record = {}; - -const keysToTrack = [ - "Backquote", - "Digit1", - "Digit2", - "Digit3", - "Digit4", - "Digit5", - "Digit6", - "Digit7", - "Digit8", - "Digit9", - "Digit0", - "Minus", - "Equal", - "KeyQ", - "KeyW", - "KeyE", - "KeyR", - "KeyT", - "KeyY", - "KeyU", - "KeyI", - "KeyO", - "KeyP", - "BracketLeft", - "BracketRight", - "Backslash", - "KeyA", - "KeyS", - "KeyD", - "KeyF", - "KeyG", - "KeyH", - "KeyJ", - "KeyK", - "KeyL", - "Semicolon", - "Quote", - "KeyZ", - "KeyX", - "KeyC", - "KeyV", - "KeyB", - "KeyN", - "KeyM", - "Comma", - "Period", - "Slash", - "Space", -]; - export function forceKeyup(): void { //using mean here because for words mode, the last keypress ends the test. //if we then force keyup on that last keypress, it will record a duration of 0 //skewing the average and standard deviation - const avg = roundTo2(mean(keypressTimings.duration.array as number[])); - for (const key of Object.keys(keysObj)) { - (keypressTimings.duration.array as number[]).push(avg); - delete keysObj[key]; + const avg = roundTo2(mean(keypressTimings.duration.array)); + const keysOrder = Object.entries(keyDownData); + keysOrder.sort((a, b) => a[1].timestamp - b[1].timestamp); + for (let i = 0; i < keysOrder.length - 1; i++) { + recordKeyupTime(keysOrder[i][0]); + } + const last = keysOrder[keysOrder.length - 1]; + if (last !== undefined) { + keypressTimings.duration.array[keyDownData[last[0]].index] = avg; } } export function recordKeyupTime(key: string): void { - if (keysObj[key] === undefined || !keysToTrack.includes(key)) { + if (keyDownData[key] === undefined || !keysToTrack.includes(key)) { return; } const now = performance.now(); - const diff = Math.abs(keysObj[key] - now); - (keypressTimings.duration.array as number[]).push(roundTo2(diff)); - delete keysObj[key]; + const diff = Math.abs(keyDownData[key].timestamp - now); + keypressTimings.duration.array[keyDownData[key].index] = diff; + delete keyDownData[key]; - updateOverlap(); + updateOverlap(now); } export function recordKeydownTime(key: string): void { - if (keysObj[key] !== undefined || !keysToTrack.includes(key)) { + if (keyDownData[key] !== undefined || !keysToTrack.includes(key)) { return; } - keysObj[key] = performance.now(); + keyDownData[key] = { + timestamp: performance.now(), + index: keypressTimings.duration.array.length, + }; + keypressTimings.duration.array.push(0); - updateOverlap(); + updateOverlap(keyDownData[key].timestamp); if (keypressTimings.spacing.last !== -1) { const diff = Math.abs(performance.now() - keypressTimings.spacing.last); - (keypressTimings.spacing.array as number[]).push(roundTo2(diff)); + keypressTimings.spacing.array.push(roundTo2(diff)); if (spacingDebug) { console.log( "spacing debug", @@ -331,9 +340,8 @@ export function recordKeydownTime(key: string): void { keypressTimings.spacing.last = performance.now(); } -function updateOverlap(): void { - const now = performance.now(); - const keys = Object.keys(keysObj); +function updateOverlap(now: number): void { + const keys = Object.keys(keyDownData); if (keys.length > 1) { if (keyOverlap.lastStartTime === -1) { keyOverlap.lastStartTime = now; @@ -360,7 +368,7 @@ export function resetKeypressTimings(): void { total: 0, lastStartTime: -1, }; - keysObj = {}; + keyDownData = {}; if (spacingDebug) console.clear(); } diff --git a/frontend/src/ts/test/test-logic.ts b/frontend/src/ts/test/test-logic.ts index 12cc45dd9..76042782d 100644 --- a/frontend/src/ts/test/test-logic.ts +++ b/frontend/src/ts/test/test-logic.ts @@ -1443,10 +1443,7 @@ function buildCompletedEvent(difficultyFailed: boolean): CompletedEvent { const stddev = Misc.stdDev(rawPerSecond); const avg = Misc.mean(rawPerSecond); let consistency = Misc.roundTo2(Misc.kogasa(stddev / avg)); - let keyConsistencyArray = - TestInput.keypressTimings.spacing.array === "toolong" - ? [] - : TestInput.keypressTimings.spacing.array.slice(); + let keyConsistencyArray = TestInput.keypressTimings.spacing.array.slice(); if (keyConsistencyArray.length > 0) { keyConsistencyArray = keyConsistencyArray.slice( 0, @@ -1757,7 +1754,6 @@ export async function finish(difficultyFailed = false): Promise { completedEvent.chartData = "toolong"; completedEvent.keySpacing = "toolong"; completedEvent.keyDuration = "toolong"; - TestInput.setKeypressTimingsTooLong(); } if (dontSave) {