Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions frontend/__tests__/utils/strings.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -993,6 +993,54 @@ describe("string utils", () => {
missed: 0,
},
},
{
description: "correctly count incorrect newlines",
input: {
inputWord: "hello ",
targetWord: "hello\n",
lastWord: false,
shouldLastPartialWordCount: false,
},
expected: {
allCorrect: 5,
correctWord: 0,
incorrect: 1,
extra: 0,
missed: 0,
},
},
{
description: "partial correct, with space",
input: {
inputWord: "helxx ",
targetWord: "hello ",
lastWord: false,
shouldLastPartialWordCount: false,
},
expected: {
allCorrect: 3,
correctWord: 0,
incorrect: 3,
extra: 0,
missed: 0,
},
},
{
description: "newlines",
input: {
inputWord: "hello\n",
targetWord: "hello\n",
lastWord: false,
shouldLastPartialWordCount: false,
},
expected: {
allCorrect: 6,
correctWord: 6,
incorrect: 0,
extra: 0,
missed: 0,
},
},
];

it.each(testCases)("$description", ({ input, expected }) => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/ts/test/test-logic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -865,7 +865,7 @@ function buildCompletedEvent(
wpm: stats.wpm,
rawWpm: stats.wpmRaw,
charStats: [
stats.correctChars + stats.correctSpaces,
stats.correctChars,
stats.incorrectChars,
stats.extraChars,
stats.missedChars,
Expand Down
132 changes: 42 additions & 90 deletions frontend/src/ts/test/test-stats.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import Hangul from "hangul-js";
import { Config } from "../config/store";
import * as Strings from "../utils/strings";
import * as TestInput from "./test-input";
import * as TestWords from "./test-words";
import * as TestState from "./test-state";
import * as Numbers from "@monkeytype/util/numbers";
import { isFunboxActiveWithProperty } from "./funbox/list";
import * as CustomText from "./custom-text";
import { getLastResult } from "../states/test";
import { countChars as countCharsUtils, getLastChar } from "../utils/strings";
import { isFunboxActiveWithProperty } from "./funbox/list";

type CharCount = {
spaces: number;
correctWordChars: number;
allCorrectChars: number;
incorrectChars: number;
extraChars: number;
missedChars: number;
correctSpaces: number;
};

export type Stats = {
Expand All @@ -29,8 +27,6 @@ export type Stats = {
extraChars: number;
allChars: number;
time: number;
spaces: number;
correctSpaces: number;
};

export let start: number, end: number;
Expand Down Expand Up @@ -130,13 +126,10 @@ export function calculateWpmAndRaw(

const chars = countChars(final);
const wpm = Numbers.roundTo2(
((chars.correctWordChars + chars.correctSpaces) * (60 / testSeconds)) / 5,
(chars.correctWordChars * (60 / testSeconds)) / 5,
);
const raw = Numbers.roundTo2(
((chars.allCorrectChars +
chars.spaces +
chars.incorrectChars +
chars.extraChars) *
((chars.allCorrectChars + chars.incorrectChars + chars.extraChars) *
(60 / testSeconds)) /
5,
);
Expand Down Expand Up @@ -225,6 +218,15 @@ function getInputWords(): string[] {
inputWords = inputWords.map((w) => Hangul.disassemble(w).join(""));
}

for (let i = 0; i < inputWords.length - 1; i++) {
if (
getLastChar(inputWords[i] as string) !== "\n" &&
!isFunboxActiveWithProperty("nospace")
) {
inputWords[i] += " ";
}
}

return inputWords;
}

Expand All @@ -249,6 +251,15 @@ function getTargetWords(): string[] {
targetWords = targetWords.map((w) => Hangul.disassemble(w).join(""));
}

for (let i = 0; i < targetWords.length - 1; i++) {
if (
getLastChar(targetWords[i] as string) !== "\n" &&
!isFunboxActiveWithProperty("nospace")
) {
targetWords[i] += " ";
}
}

return targetWords;
}

Expand All @@ -258,93 +269,40 @@ function countChars(final = false): CharCount {
let incorrectChars = 0;
let extraChars = 0;
let missedChars = 0;
let spaces = 0;
let correctspaces = 0;

const inputWords = getInputWords();
const targetWords = getTargetWords();

const isTimedTest =
Config.mode === "time" ||
(Config.mode === "custom" && CustomText.getLimit().mode === "time");

for (let i = 0; i < inputWords.length; i++) {
const inputWord = inputWords[i] as string;
const targetWord = targetWords[i] as string;

if (inputWord === targetWord) {
//the word is correct
correctWordChars += targetWord.length;
correctChars += targetWord.length;
if (
i < inputWords.length - 1 &&
Strings.getLastChar(inputWord) !== "\n"
) {
correctspaces++;
}
} else if (inputWord.length >= targetWord.length) {
//too many chars
for (let c = 0; c < inputWord.length; c++) {
if (c < targetWord.length) {
//on char that still has a word list pair
if (inputWord[c] === targetWord[c]) {
correctChars++;
} else {
incorrectChars++;
}
} else {
//on char that is extra
extraChars++;
}
}
} else {
//not enough chars
const toAdd = {
correct: 0,
incorrect: 0,
missed: 0,
};
for (let c = 0; c < targetWord.length; c++) {
if (c < inputWord.length) {
//on char that still has a word list pair
if (inputWord[c] === targetWord[c]) {
toAdd.correct++;
} else {
toAdd.incorrect++;
}
} else {
//on char that is extra
toAdd.missed++;
}
}
correctChars += toAdd.correct;
incorrectChars += toAdd.incorrect;

const isTimedTest =
Config.mode === "time" ||
(Config.mode === "custom" && CustomText.getLimit().mode === "time");
const shouldCountPartialLastWord = !final || (final && isTimedTest);

if (i === inputWords.length - 1 && shouldCountPartialLastWord) {
//last word - check if it was all correct - add to correct word chars
if (toAdd.incorrect === 0) correctWordChars += toAdd.correct;
} else {
missedChars += toAdd.missed;
}
}
if (i < inputWords.length - 1) {
spaces++;
}
}
if (isFunboxActiveWithProperty("nospace")) {
spaces = 0;
correctspaces = 0;
const { correctWord, allCorrect, incorrect, missed, extra } =
countCharsUtils(
inputWord,
targetWord,
!final || (i === inputWords.length - 1 && final),
isTimedTest,
);

correctWordChars += correctWord;
correctChars += allCorrect;
incorrectChars += incorrect;
extraChars += extra;
missedChars += missed;
}

return {
spaces: spaces,
correctWordChars: correctWordChars,
allCorrectChars: correctChars,
incorrectChars:
Config.mode === "zen" ? TestInput.accuracy.incorrect : incorrectChars,
extraChars: extraChars,
missedChars: missedChars,
correctSpaces: correctspaces,
};
}

Expand Down Expand Up @@ -386,17 +344,11 @@ export function calculateFinalStats(): Stats {
wpmRaw: isNaN(raw) ? 0 : raw,
acc: acc,
correctChars: chars.correctWordChars,
incorrectChars: chars.incorrectChars + chars.spaces - chars.correctSpaces,
incorrectChars: chars.incorrectChars,
missedChars: chars.missedChars,
extraChars: chars.extraChars,
allChars:
chars.allCorrectChars +
chars.spaces +
chars.incorrectChars +
chars.extraChars,
allChars: chars.allCorrectChars + chars.incorrectChars + chars.extraChars,
time: Numbers.roundTo2(testSeconds),
spaces: chars.spaces,
correctSpaces: chars.correctSpaces,
};
console.debug("Result stats", ret);
return ret;
Expand Down
Loading