Skip to content

Commit e5b63b7

Browse files
committed
feat: compute speed in the typing test progress
1 parent 3548dd5 commit e5b63b7

File tree

4 files changed

+54
-7
lines changed

4 files changed

+54
-7
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { test } from "node:test";
2+
import { type Step } from "@keybr/textinput";
3+
import { expect, use } from "chai";
4+
import chaiLike from "chai-like";
5+
import { computeProgress, duration_100_chars } from "./duration.ts";
6+
7+
use(chaiLike);
8+
9+
const steps: readonly Step[] = [
10+
{ timeStamp: 1001, codePoint: /* "a" */ 0x0061, timeToType: 100, typo: false },
11+
{ timeStamp: 1201, codePoint: /* "b" */ 0x0062, timeToType: 100, typo: false },
12+
{ timeStamp: 1401, codePoint: /* "c" */ 0x0063, timeToType: 100, typo: false },
13+
];
14+
15+
test("progress", () => {
16+
expect(computeProgress(duration_100_chars, [])).to.be.like({
17+
progress: { time: 0, length: 0, progress: 0, speed: 0 },
18+
completed: false,
19+
});
20+
21+
expect(computeProgress(duration_100_chars, steps.slice(0, 1))).to.be.like({
22+
progress: { time: 0, length: 1, progress: 0.01, speed: 0 },
23+
completed: false,
24+
});
25+
26+
expect(computeProgress(duration_100_chars, steps.slice(0, 2))).to.be.like({
27+
progress: { time: 200, length: 2, progress: 0.02, speed: 600 },
28+
completed: false,
29+
});
30+
31+
expect(computeProgress(duration_100_chars, steps.slice(0, 3))).to.be.like({
32+
progress: { time: 400, length: 3, progress: 0.03, speed: 450 },
33+
completed: false,
34+
});
35+
});

packages/page-typing-test/lib/session/duration.ts

+16-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { type Step } from "@keybr/textinput";
1+
import { computeSpeed, type Step } from "@keybr/textinput";
22
import { type Duration, DurationType, type Progress } from "./types.ts";
33

44
export function timeDuration(time: number): Duration {
@@ -31,17 +31,19 @@ export const durations: readonly NamedDuration[] = [
3131
];
3232

3333
export function computeProgress(
34-
steps: readonly Step[],
3534
duration: Duration,
35+
steps: readonly Step[],
3636
): { progress: Progress; completed: boolean } {
3737
const { length } = steps;
3838
let time = 0;
3939
let progress = 0;
40+
let speed = 0;
4041
let completed = false;
4142
if (length > 0) {
42-
const first = steps[0];
43-
const last = steps[length - 1];
44-
time = last.timeStamp - first.timeStamp;
43+
const head = steps[0];
44+
const curr = steps[length - 1];
45+
time = curr.timeStamp - head.timeStamp;
46+
speed = computeSpeed(length, time);
4547
switch (duration.type) {
4648
case DurationType.Time: {
4749
progress = time / duration.value;
@@ -55,5 +57,13 @@ export function computeProgress(
5557
}
5658
}
5759
}
58-
return { progress: { time, length, progress }, completed };
60+
return {
61+
progress: {
62+
time,
63+
length,
64+
progress,
65+
speed,
66+
},
67+
completed,
68+
};
5969
}

packages/page-typing-test/lib/session/session.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,8 @@ export class Session {
7676
this.#addEvent(event);
7777
const feedback = this.#textInput.onInput(event);
7878
const { progress, completed } = computeProgress(
79-
this.#steps,
8079
this.settings.duration,
80+
this.#steps,
8181
);
8282
this.#updateActiveLine(progress);
8383
if (this.#textInput.completed) {

packages/page-typing-test/lib/session/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export type Progress = {
2525
readonly length: number;
2626
/** Progress made, [0, 1]. */
2727
readonly progress: number;
28+
/** Typing speed so far. */
29+
readonly speed: number;
2830
};
2931

3032
export type SessionSettings = {

0 commit comments

Comments
 (0)