From 3839e0406ea816625bd3869b3f6099032099d619 Mon Sep 17 00:00:00 2001 From: Miodec Date: Sat, 13 Jun 2026 11:25:51 +0200 Subject: [PATCH 1/2] fix: unintended auto restart when on result screen --- frontend/src/ts/test/test-logic.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/src/ts/test/test-logic.ts b/frontend/src/ts/test/test-logic.ts index 4a3a1337d793..6189421e4208 100644 --- a/frontend/src/ts/test/test-logic.ts +++ b/frontend/src/ts/test/test-logic.ts @@ -2028,6 +2028,7 @@ qs(".pageTest")?.onChild("click", "#restartTestButtonWithSameWordset", () => { window.addEventListener("focus", () => { if ( !TestState.isActive && + !TestState.resultVisible && (Config.mode === "time" || Config.mode === "words") ) { restart({ @@ -2041,6 +2042,7 @@ document.addEventListener("visibilitychange", () => { if (document.visibilityState !== "visible") return; if ( !TestState.isActive && + !TestState.resultVisible && (Config.mode === "time" || Config.mode === "words") ) { restart({ From b751e7dbb1e10cfd2c930d366604bc3eeac4945c Mon Sep 17 00:00:00 2001 From: Miodec Date: Sat, 13 Jun 2026 12:30:47 +0200 Subject: [PATCH 2/2] fix: final word char count in timed tests also bump mismatch check version --- frontend/src/ts/test/test-logic.ts | 2 +- frontend/src/ts/test/test-stats.ts | 22 ++++++++-------------- packages/contracts/src/results.ts | 2 +- 3 files changed, 10 insertions(+), 16 deletions(-) diff --git a/frontend/src/ts/test/test-logic.ts b/frontend/src/ts/test/test-logic.ts index 6189421e4208..ac2da630d78b 100644 --- a/frontend/src/ts/test/test-logic.ts +++ b/frontend/src/ts/test/test-logic.ts @@ -1317,7 +1317,7 @@ function compareCompletedEvents( difficulty: ce.difficulty, duration: ce.testDuration, funboxes: getActiveFunboxNames().join(","), - version: 18, + version: 19, data: { words: TestWords.words.list.join(" "), events: getAllTestEvents(), diff --git a/frontend/src/ts/test/test-stats.ts b/frontend/src/ts/test/test-stats.ts index 545afdb1ca30..0d2885905bc3 100644 --- a/frontend/src/ts/test/test-stats.ts +++ b/frontend/src/ts/test/test-stats.ts @@ -206,7 +206,7 @@ export function removeAfkData(): void { TestInput.rawHistory.splice(testSeconds); } -function getInputWords(): string[] { +function getInputWords(isTimedTest: boolean): string[] { const containsKorean = TestState.koreanStatus; let inputWords = [...TestInput.input.getHistory()]; @@ -219,7 +219,7 @@ function getInputWords(): string[] { inputWords = inputWords.map((w) => Hangul.disassemble(w).join("")); } - for (let i = 0; i < inputWords.length - 1; i++) { + for (let i = 0; i < inputWords.length - (isTimedTest ? 0 : 1); i++) { if ( getLastChar(inputWords[i] as string) !== "\n" && !isFunboxActiveWithProperty("nospace") @@ -231,7 +231,7 @@ function getInputWords(): string[] { return inputWords; } -function getTargetWords(): string[] { +function getTargetWords(isTimedTest: boolean): string[] { const containsKorean = TestState.koreanStatus; let targetWords = [ @@ -252,7 +252,7 @@ function getTargetWords(): string[] { targetWords = targetWords.map((w) => Hangul.disassemble(w).join("")); } - for (let i = 0; i < targetWords.length - 1; i++) { + for (let i = 0; i < targetWords.length - (isTimedTest ? 0 : 1); i++) { if ( getLastChar(targetWords[i] as string) !== "\n" && !isFunboxActiveWithProperty("nospace") @@ -271,25 +271,19 @@ function countChars(final = false): CharCount { let extraChars = 0; let missedChars = 0; - const inputWords = getInputWords(); - const targetWords = getTargetWords(); - const isTimedTest = Config.mode === "time" || + (Config.mode === "words" && Config.words === 0) || (Config.mode === "custom" && CustomText.getLimit().mode === "time"); + const inputWords = getInputWords(isTimedTest); + const targetWords = getTargetWords(isTimedTest); + for (let i = 0; i < inputWords.length; i++) { const inputWord = inputWords[i] as string; let targetWord = targetWords[i] as string; const isLastInputWord = i === inputWords.length - 1; - // getTargetWords appends a delimiter to every word except the last in the - // generated list; for the last input word (active in timed/mid-test, or - // the actual last word) drop that delimiter so overshoot counts as extra - if (isLastInputWord && targetWord.endsWith(" ")) { - targetWord = targetWord.slice(0, -1); - } - const { correctWord, allCorrect, incorrect, missed, extra } = countCharsUtils( inputWord, diff --git a/packages/contracts/src/results.ts b/packages/contracts/src/results.ts index fd60efc116e9..b80b4b13fba1 100644 --- a/packages/contracts/src/results.ts +++ b/packages/contracts/src/results.ts @@ -75,7 +75,7 @@ export const ReportCompletedEventMismatchRequestSchema = z.object({ difficulty: DifficultySchema.optional(), duration: z.number().max(200).optional(), funboxes: z.string().max(100).optional(), - version: z.literal(18), + version: z.literal(19), data: z.object({ words: z.string().max(10000), events: z.array(z.record(z.unknown())),