Skip to content

Commit df06b62

Browse files
committed
refactor: rework keypress tracking
removes the need for a setTimeout which causes issues during lag
1 parent 52b7d96 commit df06b62

File tree

2 files changed

+70
-28
lines changed

2 files changed

+70
-28
lines changed

frontend/src/ts/controllers/input-controller.ts

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,11 +1182,9 @@ $("#wordsInput").on("keydown", (event) => {
11821182
}
11831183

11841184
const now = performance.now();
1185-
setTimeout(() => {
1186-
const eventCode =
1187-
event.code === "" || event.key === "Unidentified" ? "NoCode" : event.code;
1188-
TestInput.recordKeydownTime(now, eventCode);
1189-
}, 0);
1185+
const eventCode =
1186+
event.code === "" || event.key === "Unidentified" ? "NoCode" : event.code;
1187+
TestInput.recordKeydownTime(now, eventCode);
11901188
});
11911189

11921190
$("#wordsInput").on("keyup", (event) => {
@@ -1213,11 +1211,9 @@ $("#wordsInput").on("keyup", (event) => {
12131211
}
12141212

12151213
const now = performance.now();
1216-
setTimeout(() => {
1217-
const eventCode =
1218-
event.code === "" || event.key === "Unidentified" ? "NoCode" : event.code;
1219-
TestInput.recordKeyupTime(now, eventCode);
1220-
}, 0);
1214+
const eventCode =
1215+
event.code === "" || event.key === "Unidentified" ? "NoCode" : event.code;
1216+
TestInput.recordKeyupTime(now, eventCode);
12211217
});
12221218

12231219
$("#wordsInput").on("keyup", (event) => {

frontend/src/ts/test/test-input.ts

Lines changed: 64 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -262,16 +262,37 @@ export function forceKeyup(now: number): void {
262262
//using mean here because for words mode, the last keypress ends the test.
263263
//if we then force keyup on that last keypress, it will record a duration of 0
264264
//skewing the average and standard deviation
265-
const avg = roundTo2(mean(keypressTimings.duration.array));
266-
const keysOrder = Object.entries(keyDownData);
267-
keysOrder.sort((a, b) => a[1].timestamp - b[1].timestamp);
268-
for (const keyOrder of keysOrder) {
269-
recordKeyupTime(now, keyOrder[0]);
265+
266+
const indexesToRemove = new Set(
267+
Object.values(keyDownData).map((data) => data.index)
268+
);
269+
270+
const keypressDurations = keypressTimings.duration.array.filter(
271+
(_, index) => !indexesToRemove.has(index)
272+
);
273+
if (keypressDurations.length === 0) {
274+
// this means the test ended while all keys were still held - probably safe to ignore
275+
// since this will result in a "too short" test anyway
276+
return;
270277
}
271-
const last = lastElementFromArray(keysOrder)?.[0] as string;
272-
const index = keyDownData[last]?.index;
273-
if (last !== undefined && index !== undefined) {
278+
279+
const avg = roundTo2(mean(keypressDurations));
280+
281+
const orderedKeys = Object.entries(keyDownData).sort(
282+
(a, b) => a[1].timestamp - b[1].timestamp
283+
);
284+
285+
for (const [key, { index }] of orderedKeys) {
274286
keypressTimings.duration.array[index] = avg;
287+
288+
if (key === "NoCode") {
289+
noCodeIndex--;
290+
}
291+
292+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
293+
delete keyDownData[key];
294+
295+
updateOverlap(now);
275296
}
276297
}
277298

@@ -350,6 +371,21 @@ function updateOverlap(now: number): void {
350371
}
351372

352373
export function resetKeypressTimings(): void {
374+
//because keydown triggers before input, we need to grab the first keypress data here and carry it over
375+
376+
//take the key with the largest index
377+
const lastKey = Object.keys(keyDownData).reduce((a, b) => {
378+
const aIndex = keyDownData[a]?.index;
379+
const bIndex = keyDownData[b]?.index;
380+
if (aIndex === undefined) return b;
381+
if (bIndex === undefined) return a;
382+
return aIndex > bIndex ? a : b;
383+
});
384+
385+
//get the data
386+
const lastKeyData = keyDownData[lastKey];
387+
388+
//reset
353389
keypressTimings = {
354390
spacing: {
355391
first: -1,
@@ -366,6 +402,26 @@ export function resetKeypressTimings(): void {
366402
};
367403
keyDownData = {};
368404
noCodeIndex = 0;
405+
406+
//carry over
407+
if (lastKeyData !== undefined) {
408+
keypressTimings = {
409+
spacing: {
410+
first: lastKeyData.timestamp,
411+
last: lastKeyData.timestamp,
412+
array: [],
413+
},
414+
duration: {
415+
array: [0],
416+
},
417+
};
418+
keyDownData[lastKey] = {
419+
timestamp: lastKeyData.timestamp,
420+
// make sure to set it to the first index
421+
index: 0,
422+
};
423+
}
424+
369425
console.debug("Keypress timings reset");
370426
}
371427

@@ -413,14 +469,4 @@ export function restart(): void {
413469
correct: 0,
414470
incorrect: 0,
415471
};
416-
keypressTimings = {
417-
spacing: {
418-
first: -1,
419-
last: -1,
420-
array: [],
421-
},
422-
duration: {
423-
array: [],
424-
},
425-
};
426472
}

0 commit comments

Comments
 (0)