@testgorilla/tgo-typing-test 2.0.0 → 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/fesm2022/testgorilla-tgo-typing-test.mjs +4691 -0
- package/fesm2022/testgorilla-tgo-typing-test.mjs.map +1 -0
- package/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.d.ts +14 -0
- package/lib/components/tgo-typing-test/tgo-typing-test.component.d.ts +54 -0
- package/lib/helpers/config.d.ts +98 -0
- package/lib/helpers/constants/default-config.d.ts +3 -0
- package/lib/helpers/controllers/input-controller.d.ts +16 -0
- package/lib/helpers/controllers/quotes-controller.d.ts +20 -0
- package/lib/helpers/observables/config-event.d.ts +5 -0
- package/lib/helpers/observables/timer-event.d.ts +4 -0
- package/lib/helpers/states/active-page.d.ts +2 -0
- package/lib/helpers/states/composition.d.ts +10 -0
- package/lib/helpers/states/page-transition.d.ts +2 -0
- package/lib/helpers/states/slow-timer.d.ts +3 -0
- package/lib/helpers/states/test-active.d.ts +2 -0
- package/lib/helpers/states/time.d.ts +3 -0
- package/lib/helpers/test/caps-warning.d.ts +5 -0
- package/lib/helpers/test/caret.d.ts +11 -0
- package/lib/helpers/test/custom-text.d.ts +16 -0
- package/lib/helpers/test/english-punctuation.d.ts +3 -0
- package/lib/helpers/test/focus.d.ts +7 -0
- package/lib/helpers/test/manual-restart-tracker.d.ts +3 -0
- package/lib/helpers/test/out-of-focus.d.ts +4 -0
- package/lib/helpers/test/replay.d.ts +20 -0
- package/lib/helpers/test/test-input.d.ts +86 -0
- package/lib/helpers/test/test-logic.d.ts +25 -0
- package/lib/helpers/test/test-state.d.ts +7 -0
- package/lib/helpers/test/test-stats.d.ts +92 -0
- package/lib/helpers/test/test-timer.d.ts +6 -0
- package/lib/helpers/test/test-ui.d.ts +27 -0
- package/lib/helpers/test/test-words.d.ts +23 -0
- package/lib/helpers/test/timer-progress.d.ts +3 -0
- package/lib/helpers/test/weak-spot.d.ts +3 -0
- package/lib/helpers/test/wordset.d.ts +7 -0
- package/lib/utils/misc.d.ts +80 -0
- package/package.json +17 -4
- package/.eslintrc.json +0 -46
- package/jest.config.ts +0 -21
- package/ng-package.json +0 -15
- package/project.json +0 -36
- package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.html +0 -30
- package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.spec.ts +0 -250
- package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.ts +0 -47
- package/src/lib/components/tgo-typing-test/tgo-typing-test.component.html +0 -72
- package/src/lib/components/tgo-typing-test/tgo-typing-test.component.spec.ts +0 -699
- package/src/lib/components/tgo-typing-test/tgo-typing-test.component.ts +0 -287
- package/src/lib/helpers/config.ts +0 -28
- package/src/lib/helpers/constants/default-config.ts +0 -103
- package/src/lib/helpers/controllers/input-controller.ts +0 -710
- package/src/lib/helpers/controllers/quotes-controller.ts +0 -183
- package/src/lib/helpers/observables/banner-event.ts +0 -18
- package/src/lib/helpers/observables/config-event.ts +0 -31
- package/src/lib/helpers/observables/timer-event.ts +0 -18
- package/src/lib/helpers/states/active-page.ts +0 -9
- package/src/lib/helpers/states/composition.ts +0 -29
- package/src/lib/helpers/states/page-transition.ts +0 -9
- package/src/lib/helpers/states/slow-timer.ts +0 -16
- package/src/lib/helpers/states/test-active.ts +0 -9
- package/src/lib/helpers/states/time.ts +0 -13
- package/src/lib/helpers/test/caps-warning.ts +0 -50
- package/src/lib/helpers/test/caret.ts +0 -92
- package/src/lib/helpers/test/custom-text.ts +0 -73
- package/src/lib/helpers/test/english-punctuation.ts +0 -38
- package/src/lib/helpers/test/focus.ts +0 -39
- package/src/lib/helpers/test/manual-restart-tracker.ts +0 -13
- package/src/lib/helpers/test/out-of-focus.ts +0 -19
- package/src/lib/helpers/test/replay.ts +0 -265
- package/src/lib/helpers/test/test-input.ts +0 -320
- package/src/lib/helpers/test/test-logic.ts +0 -1039
- package/src/lib/helpers/test/test-state.ts +0 -17
- package/src/lib/helpers/test/test-stats.ts +0 -442
- package/src/lib/helpers/test/test-timer.ts +0 -209
- package/src/lib/helpers/test/test-ui.ts +0 -370
- package/src/lib/helpers/test/test-words.ts +0 -72
- package/src/lib/helpers/test/timer-progress.ts +0 -16
- package/src/lib/helpers/test/tts.ts +0 -42
- package/src/lib/helpers/test/weak-spot.ts +0 -74
- package/src/lib/helpers/test/wordset.ts +0 -109
- package/src/lib/styles/animations.scss +0 -101
- package/src/lib/styles/caret.scss +0 -108
- package/src/lib/styles/core.scss +0 -498
- package/src/lib/styles/index.scss +0 -19
- package/src/lib/styles/inputs.scss +0 -290
- package/src/lib/styles/popups.scss +0 -1311
- package/src/lib/styles/test.scss +0 -1008
- package/src/lib/styles/z_media-queries.scss +0 -848
- package/src/lib/types/types.d.ts +0 -731
- package/src/lib/utils/misc.ts +0 -776
- package/src/test-setup.ts +0 -20
- package/tsconfig.json +0 -16
- package/tsconfig.lib.json +0 -14
- package/tsconfig.lib.prod.json +0 -9
- package/tsconfig.spec.json +0 -11
- /package/{src/assets → assets}/typing-test-languages/english.json +0 -0
- /package/{src/assets → assets}/typing-test-languages/english_punctuation.json +0 -0
- /package/{src/assets → assets}/typing-test-languages/quotes/english_version_1.json +0 -0
- /package/{src/assets → assets}/typing-test-languages/quotes/english_version_2.json +0 -0
- /package/{src/assets → assets}/typing-test-languages/quotes/filtered_sources.json +0 -0
- /package/{src/index.ts → index.d.ts} +0 -0
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { MonkeyTypes } from '../../types/types';
|
|
2
|
-
|
|
3
|
-
export let isRepeated = false;
|
|
4
|
-
export let isPaceRepeat = false;
|
|
5
|
-
export let activeChallenge: null | MonkeyTypes.Challenge = null;
|
|
6
|
-
|
|
7
|
-
export function setRepeated(tf: boolean): void {
|
|
8
|
-
isRepeated = tf;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export function setPaceRepeat(tf: boolean): void {
|
|
12
|
-
isPaceRepeat = tf;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function setActiveChallenge(val: null | MonkeyTypes.Challenge): void {
|
|
16
|
-
activeChallenge = val;
|
|
17
|
-
}
|
|
@@ -1,442 +0,0 @@
|
|
|
1
|
-
import Config from '../../helpers/config';
|
|
2
|
-
import * as Misc from '../../utils/misc';
|
|
3
|
-
import * as TestInput from './test-input';
|
|
4
|
-
import * as TestWords from './test-words';
|
|
5
|
-
import { MonkeyTypes } from '../../types/types';
|
|
6
|
-
interface CharCount {
|
|
7
|
-
spaces: number;
|
|
8
|
-
correctWordChars: number;
|
|
9
|
-
allCorrectChars: number;
|
|
10
|
-
incorrectChars: number;
|
|
11
|
-
extraChars: number;
|
|
12
|
-
missedChars: number;
|
|
13
|
-
correctSpaces: number;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
interface Keypress {
|
|
17
|
-
count: number;
|
|
18
|
-
errors: number;
|
|
19
|
-
words: number[];
|
|
20
|
-
afk: boolean;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
interface KeypressTimings {
|
|
24
|
-
spacing: {
|
|
25
|
-
current: number;
|
|
26
|
-
array: number[] | 'toolong';
|
|
27
|
-
};
|
|
28
|
-
duration: {
|
|
29
|
-
current: number;
|
|
30
|
-
array: number[] | 'toolong';
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
interface DebugStats {
|
|
35
|
-
lastResult?: MonkeyTypes.Result<MonkeyTypes.Mode>;
|
|
36
|
-
start: number;
|
|
37
|
-
end: number;
|
|
38
|
-
wpmHistory: number[];
|
|
39
|
-
rawHistory: number[];
|
|
40
|
-
burstHistory: number[];
|
|
41
|
-
keypressPerSecond: Keypress[];
|
|
42
|
-
currentKeypress: {
|
|
43
|
-
count: number;
|
|
44
|
-
errors: number;
|
|
45
|
-
words: number[];
|
|
46
|
-
afk: boolean;
|
|
47
|
-
};
|
|
48
|
-
lastKeypress: number;
|
|
49
|
-
currentBurstStart: number;
|
|
50
|
-
lastSecondNotRound: boolean;
|
|
51
|
-
missedWords: {
|
|
52
|
-
[word: string]: number;
|
|
53
|
-
};
|
|
54
|
-
accuracy: {
|
|
55
|
-
correct: number;
|
|
56
|
-
incorrect: number;
|
|
57
|
-
};
|
|
58
|
-
keypressTimings: KeypressTimings;
|
|
59
|
-
keySpacingStats?: {
|
|
60
|
-
average: number;
|
|
61
|
-
sd: number;
|
|
62
|
-
};
|
|
63
|
-
keyDurationStats?: {
|
|
64
|
-
average: number;
|
|
65
|
-
sd: number;
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
interface Stats {
|
|
70
|
-
wpm: number;
|
|
71
|
-
wpmRaw: number;
|
|
72
|
-
acc: number;
|
|
73
|
-
correctChars: number;
|
|
74
|
-
incorrectChars: number;
|
|
75
|
-
missedChars: number;
|
|
76
|
-
extraChars: number;
|
|
77
|
-
allChars: number;
|
|
78
|
-
time: number;
|
|
79
|
-
spaces: number;
|
|
80
|
-
correctSpaces: number;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export let invalid = false;
|
|
84
|
-
export let start: number, end: number;
|
|
85
|
-
export let start2: number, end2: number;
|
|
86
|
-
export let lastSecondNotRound = false;
|
|
87
|
-
|
|
88
|
-
export let lastTestWpm = 0;
|
|
89
|
-
|
|
90
|
-
export function setLastTestWpm(wpm: number): void {
|
|
91
|
-
lastTestWpm = wpm;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
export let lastResult: MonkeyTypes.Result<MonkeyTypes.Mode>;
|
|
95
|
-
|
|
96
|
-
export function setLastResult(result: MonkeyTypes.Result<MonkeyTypes.Mode>): void {
|
|
97
|
-
lastResult = result;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
let wpmCalcDebug = false;
|
|
101
|
-
export function wpmCalculationDebug(): void {
|
|
102
|
-
console.log('wpm calculation debug enabled');
|
|
103
|
-
wpmCalcDebug = true;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
export function getStats(): DebugStats {
|
|
107
|
-
const ret: DebugStats = {
|
|
108
|
-
lastResult,
|
|
109
|
-
start,
|
|
110
|
-
end,
|
|
111
|
-
wpmHistory: TestInput.wpmHistory,
|
|
112
|
-
rawHistory: TestInput.wpmHistory,
|
|
113
|
-
burstHistory: TestInput.burstHistory,
|
|
114
|
-
keypressPerSecond: TestInput.keypressPerSecond,
|
|
115
|
-
currentKeypress: TestInput.currentKeypress,
|
|
116
|
-
lastKeypress: TestInput.lastKeypress,
|
|
117
|
-
currentBurstStart: TestInput.currentBurstStart,
|
|
118
|
-
lastSecondNotRound,
|
|
119
|
-
missedWords: TestInput.missedWords,
|
|
120
|
-
accuracy: TestInput.accuracy,
|
|
121
|
-
keypressTimings: TestInput.keypressTimings,
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
ret.keySpacingStats = {
|
|
126
|
-
average:
|
|
127
|
-
(TestInput.keypressTimings.spacing.array as number[]).reduce(
|
|
128
|
-
(previous, current) => (current += previous)
|
|
129
|
-
) / TestInput.keypressTimings.spacing.array.length,
|
|
130
|
-
sd: Misc.stdDev(TestInput.keypressTimings.spacing.array as number[]),
|
|
131
|
-
};
|
|
132
|
-
} catch (e) {
|
|
133
|
-
//
|
|
134
|
-
}
|
|
135
|
-
try {
|
|
136
|
-
ret.keyDurationStats = {
|
|
137
|
-
average:
|
|
138
|
-
(TestInput.keypressTimings.duration.array as number[]).reduce(
|
|
139
|
-
(previous, current) => (current += previous)
|
|
140
|
-
) / TestInput.keypressTimings.duration.array.length,
|
|
141
|
-
sd: Misc.stdDev(TestInput.keypressTimings.duration.array as number[]),
|
|
142
|
-
};
|
|
143
|
-
} catch (e) {
|
|
144
|
-
//
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
return ret;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
export function restart(): void {
|
|
151
|
-
start = 0;
|
|
152
|
-
end = 0;
|
|
153
|
-
invalid = false;
|
|
154
|
-
lastSecondNotRound = false;
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
export let restartCount = 0;
|
|
158
|
-
export let incompleteSeconds = 0;
|
|
159
|
-
|
|
160
|
-
export function incrementRestartCount(): void {
|
|
161
|
-
restartCount++;
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
export function incrementIncompleteSeconds(val: number): void {
|
|
165
|
-
incompleteSeconds += val;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export function resetIncomplete(): void {
|
|
169
|
-
restartCount = 0;
|
|
170
|
-
incompleteSeconds = 0;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
export function setInvalid(): void {
|
|
174
|
-
invalid = true;
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
export function calculateTestSeconds(now?: number): number {
|
|
178
|
-
if (now === undefined) {
|
|
179
|
-
const endAfkSeconds = (end - TestInput.lastKeypress) / 1000;
|
|
180
|
-
if ((Config.mode == 'zen' || TestInput.bailout) && endAfkSeconds < 7) {
|
|
181
|
-
return (TestInput.lastKeypress - start) / 1000;
|
|
182
|
-
} else {
|
|
183
|
-
return (end - start) / 1000;
|
|
184
|
-
}
|
|
185
|
-
} else {
|
|
186
|
-
return (now - start) / 1000;
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
export function calculateWpmAndRaw(): MonkeyTypes.WordsPerMinuteAndRaw {
|
|
191
|
-
let chars = 0;
|
|
192
|
-
let correctWordChars = 0;
|
|
193
|
-
let spaces = 0;
|
|
194
|
-
//check input history
|
|
195
|
-
for (let i = 0; i < TestInput.input.history.length; i++) {
|
|
196
|
-
const word = Config.mode == 'zen' ? TestInput.input.getHistory(i) : TestWords.words.get(i);
|
|
197
|
-
if (TestInput.input.getHistory(i) == word) {
|
|
198
|
-
//the word is correct
|
|
199
|
-
//+1 for space
|
|
200
|
-
correctWordChars += word.length;
|
|
201
|
-
if (
|
|
202
|
-
i < TestInput.input.history.length - 1 &&
|
|
203
|
-
Misc.getLastChar(TestInput.input.getHistory(i) as string) !== '\n'
|
|
204
|
-
) {
|
|
205
|
-
spaces++;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
chars += TestInput.input.getHistory(i).length;
|
|
209
|
-
}
|
|
210
|
-
if (TestInput.input.current !== '') {
|
|
211
|
-
const word = Config.mode == 'zen' ? TestInput.input.current : TestWords.words.getCurrent();
|
|
212
|
-
//check whats currently typed
|
|
213
|
-
const toAdd = {
|
|
214
|
-
correct: 0,
|
|
215
|
-
incorrect: 0,
|
|
216
|
-
missed: 0,
|
|
217
|
-
};
|
|
218
|
-
for (let c = 0; c < word.length; c++) {
|
|
219
|
-
if (c < TestInput.input.current.length) {
|
|
220
|
-
//on char that still has a word list pair
|
|
221
|
-
if (TestInput.input.current[c] == word[c]) {
|
|
222
|
-
toAdd.correct++;
|
|
223
|
-
} else {
|
|
224
|
-
toAdd.incorrect++;
|
|
225
|
-
}
|
|
226
|
-
} else {
|
|
227
|
-
//on char that is extra
|
|
228
|
-
toAdd.missed++;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
chars += toAdd.correct;
|
|
232
|
-
chars += toAdd.incorrect;
|
|
233
|
-
chars += toAdd.missed;
|
|
234
|
-
if (toAdd.incorrect == 0) {
|
|
235
|
-
//word is correct so far, add chars
|
|
236
|
-
correctWordChars += toAdd.correct;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
if (Config.funbox === 'nospace' || Config.funbox === 'arrows') {
|
|
240
|
-
spaces = 0;
|
|
241
|
-
}
|
|
242
|
-
chars += TestInput.input.current.length;
|
|
243
|
-
const testSeconds = calculateTestSeconds(performance.now());
|
|
244
|
-
const wpm = Math.round(((correctWordChars + spaces) * (60 / testSeconds)) / 5);
|
|
245
|
-
const raw = Math.round(((chars + spaces) * (60 / testSeconds)) / 5);
|
|
246
|
-
return {
|
|
247
|
-
wpm: wpm,
|
|
248
|
-
raw: raw,
|
|
249
|
-
};
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
export function setEnd(e: number): void {
|
|
253
|
-
end = e;
|
|
254
|
-
end2 = Date.now();
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
export function setStart(s: number): void {
|
|
258
|
-
start = s;
|
|
259
|
-
start2 = Date.now();
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
export function calculateAfkSeconds(testSeconds: number): number {
|
|
263
|
-
let extraAfk = 0;
|
|
264
|
-
if (testSeconds !== undefined) {
|
|
265
|
-
if (Config.mode === 'time') {
|
|
266
|
-
extraAfk = Math.round(testSeconds) - TestInput.keypressPerSecond.length;
|
|
267
|
-
} else {
|
|
268
|
-
extraAfk = Math.ceil(testSeconds) - TestInput.keypressPerSecond.length;
|
|
269
|
-
}
|
|
270
|
-
if (extraAfk < 0) extraAfk = 0;
|
|
271
|
-
// console.log("-- extra afk debug");
|
|
272
|
-
// console.log("should be " + Math.ceil(testSeconds));
|
|
273
|
-
// console.log(keypressPerSecond.length);
|
|
274
|
-
// console.log(
|
|
275
|
-
// `gonna add extra ${extraAfk} seconds of afk because of no keypress data`
|
|
276
|
-
// );
|
|
277
|
-
}
|
|
278
|
-
const ret = TestInput.keypressPerSecond.filter(x => x.afk).length;
|
|
279
|
-
return ret + extraAfk;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
export function setLastSecondNotRound(): void {
|
|
283
|
-
lastSecondNotRound = true;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
export function calculateBurst(): number {
|
|
287
|
-
const timeToWrite = (performance.now() - TestInput.currentBurstStart) / 1000;
|
|
288
|
-
let wordLength: number;
|
|
289
|
-
wordLength = TestInput.input.current.length;
|
|
290
|
-
if (wordLength == 0) {
|
|
291
|
-
wordLength = TestInput.input.getHistoryLast()?.length ?? 0;
|
|
292
|
-
}
|
|
293
|
-
if (wordLength == 0) return 0;
|
|
294
|
-
const speed = Misc.roundTo2((wordLength * (60 / timeToWrite)) / 5);
|
|
295
|
-
return Math.round(speed);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
export function calculateAccuracy(): number {
|
|
299
|
-
const acc =
|
|
300
|
-
(TestInput.accuracy.correct / (TestInput.accuracy.correct + TestInput.accuracy.incorrect)) *
|
|
301
|
-
100;
|
|
302
|
-
return isNaN(acc) ? 0 : acc;
|
|
303
|
-
}
|
|
304
|
-
|
|
305
|
-
export function removeAfkData(): void {
|
|
306
|
-
const testSeconds = calculateTestSeconds();
|
|
307
|
-
TestInput.keypressPerSecond.splice(testSeconds);
|
|
308
|
-
TestInput.wpmHistory.splice(testSeconds);
|
|
309
|
-
TestInput.burstHistory.splice(testSeconds);
|
|
310
|
-
TestInput.rawHistory.splice(testSeconds);
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
function countChars(): CharCount {
|
|
314
|
-
let correctWordChars = 0;
|
|
315
|
-
let correctChars = 0;
|
|
316
|
-
let incorrectChars = 0;
|
|
317
|
-
let extraChars = 0;
|
|
318
|
-
let missedChars = 0;
|
|
319
|
-
let spaces = 0;
|
|
320
|
-
let correctspaces = 0;
|
|
321
|
-
for (let i = 0; i < TestInput.input.history.length; i++) {
|
|
322
|
-
const word = Config.mode == 'zen' ? TestInput.input.getHistory(i) : TestWords.words.get(i);
|
|
323
|
-
if (TestInput.input.getHistory(i) === '') {
|
|
324
|
-
//last word that was not started
|
|
325
|
-
continue;
|
|
326
|
-
}
|
|
327
|
-
if (TestInput.input.getHistory(i) == word) {
|
|
328
|
-
//the word is correct
|
|
329
|
-
correctWordChars += word.length;
|
|
330
|
-
correctChars += word.length;
|
|
331
|
-
if (
|
|
332
|
-
i < TestInput.input.history.length - 1 &&
|
|
333
|
-
Misc.getLastChar(TestInput.input.getHistory(i) as string) !== '\n'
|
|
334
|
-
) {
|
|
335
|
-
correctspaces++;
|
|
336
|
-
}
|
|
337
|
-
} else if (TestInput.input.getHistory(i).length >= word.length) {
|
|
338
|
-
//too many chars
|
|
339
|
-
for (let c = 0; c < TestInput.input.getHistory(i).length; c++) {
|
|
340
|
-
if (c < word.length) {
|
|
341
|
-
//on char that still has a word list pair
|
|
342
|
-
if (TestInput.input.getHistory(i)[c] == word[c]) {
|
|
343
|
-
correctChars++;
|
|
344
|
-
} else {
|
|
345
|
-
incorrectChars++;
|
|
346
|
-
}
|
|
347
|
-
} else {
|
|
348
|
-
//on char that is extra
|
|
349
|
-
extraChars++;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
} else {
|
|
353
|
-
//not enough chars
|
|
354
|
-
const toAdd = {
|
|
355
|
-
correct: 0,
|
|
356
|
-
incorrect: 0,
|
|
357
|
-
missed: 0,
|
|
358
|
-
};
|
|
359
|
-
for (let c = 0; c < word.length; c++) {
|
|
360
|
-
if (c < TestInput.input.getHistory(i).length) {
|
|
361
|
-
//on char that still has a word list pair
|
|
362
|
-
if (TestInput.input.getHistory(i)[c] == word[c]) {
|
|
363
|
-
toAdd.correct++;
|
|
364
|
-
} else {
|
|
365
|
-
toAdd.incorrect++;
|
|
366
|
-
}
|
|
367
|
-
} else {
|
|
368
|
-
//on char that is extra
|
|
369
|
-
toAdd.missed++;
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
correctChars += toAdd.correct;
|
|
373
|
-
incorrectChars += toAdd.incorrect;
|
|
374
|
-
if (i === TestInput.input.history.length - 1 && Config.mode == 'time') {
|
|
375
|
-
//last word - check if it was all correct - add to correct word chars
|
|
376
|
-
if (toAdd.incorrect === 0) correctWordChars += toAdd.correct;
|
|
377
|
-
} else {
|
|
378
|
-
missedChars += toAdd.missed;
|
|
379
|
-
}
|
|
380
|
-
}
|
|
381
|
-
if (i < TestInput.input.history.length - 1) {
|
|
382
|
-
spaces++;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
if (Config.funbox === 'nospace' || Config.funbox === 'arrows') {
|
|
386
|
-
spaces = 0;
|
|
387
|
-
correctspaces = 0;
|
|
388
|
-
}
|
|
389
|
-
return {
|
|
390
|
-
spaces: spaces,
|
|
391
|
-
correctWordChars: correctWordChars,
|
|
392
|
-
allCorrectChars: correctChars,
|
|
393
|
-
incorrectChars: Config.mode == 'zen' ? TestInput.accuracy.incorrect : incorrectChars,
|
|
394
|
-
extraChars: extraChars,
|
|
395
|
-
missedChars: missedChars,
|
|
396
|
-
correctSpaces: correctspaces,
|
|
397
|
-
};
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
export function calculateStats(): Stats {
|
|
401
|
-
let testSeconds = calculateTestSeconds();
|
|
402
|
-
if (wpmCalcDebug) {
|
|
403
|
-
console.log('date based time', (end2 - start2) / 1000);
|
|
404
|
-
console.log('performance.now based time', testSeconds);
|
|
405
|
-
}
|
|
406
|
-
if (Config.mode != 'custom') {
|
|
407
|
-
testSeconds = Misc.roundTo2(testSeconds);
|
|
408
|
-
if (wpmCalcDebug) {
|
|
409
|
-
console.log('mode is not custom - wounding');
|
|
410
|
-
console.log('new time', testSeconds);
|
|
411
|
-
}
|
|
412
|
-
}
|
|
413
|
-
const chars = countChars();
|
|
414
|
-
const wpm = Misc.roundTo2(
|
|
415
|
-
((chars.correctWordChars + chars.correctSpaces) * (60 / testSeconds)) / 5
|
|
416
|
-
);
|
|
417
|
-
const wpmraw = Misc.roundTo2(
|
|
418
|
-
((chars.allCorrectChars + chars.spaces + chars.incorrectChars + chars.extraChars) *
|
|
419
|
-
(60 / testSeconds)) /
|
|
420
|
-
5
|
|
421
|
-
);
|
|
422
|
-
if (wpmCalcDebug) {
|
|
423
|
-
console.log('chars', chars);
|
|
424
|
-
console.log('wpm', ((chars.correctWordChars + chars.correctSpaces) * (60 / testSeconds)) / 5);
|
|
425
|
-
console.log('wpm rounded to 2', wpm);
|
|
426
|
-
console.log('wpmraw', wpmraw);
|
|
427
|
-
}
|
|
428
|
-
const acc = Misc.roundTo2(calculateAccuracy());
|
|
429
|
-
return {
|
|
430
|
-
wpm: isNaN(wpm) ? 0 : wpm,
|
|
431
|
-
wpmRaw: isNaN(wpmraw) ? 0 : wpmraw,
|
|
432
|
-
acc: acc,
|
|
433
|
-
correctChars: chars.correctWordChars,
|
|
434
|
-
incorrectChars: chars.incorrectChars,
|
|
435
|
-
missedChars: chars.missedChars,
|
|
436
|
-
extraChars: chars.extraChars,
|
|
437
|
-
allChars: chars.allCorrectChars + chars.spaces + chars.incorrectChars + chars.extraChars,
|
|
438
|
-
time: Misc.roundTo2(testSeconds),
|
|
439
|
-
spaces: chars.spaces,
|
|
440
|
-
correctSpaces: chars.correctSpaces,
|
|
441
|
-
};
|
|
442
|
-
}
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
// Most of the code is thanks to
|
|
2
|
-
// https://stackoverflow.com/questions/29971898/how-to-create-an-accurate-timer-in-javascript
|
|
3
|
-
|
|
4
|
-
import Config from '../../helpers/config';
|
|
5
|
-
import { MonkeyTypes } from '../../types/types';
|
|
6
|
-
import * as Misc from '../../utils/misc';
|
|
7
|
-
import * as TimerEvent from '../observables/timer-event';
|
|
8
|
-
import * as SlowTimer from '../states/slow-timer';
|
|
9
|
-
import * as TestActive from '../states/test-active';
|
|
10
|
-
import * as Time from '../states/time';
|
|
11
|
-
import * as Caret from './caret';
|
|
12
|
-
import * as CustomText from './custom-text';
|
|
13
|
-
import * as TestInput from './test-input';
|
|
14
|
-
import * as TestStats from './test-stats';
|
|
15
|
-
import * as TestWords from './test-words';
|
|
16
|
-
import * as TimerProgress from './timer-progress';
|
|
17
|
-
let slowTimerCount = 0;
|
|
18
|
-
let timer: NodeJS.Timeout | null = null;
|
|
19
|
-
const interval = 1000;
|
|
20
|
-
let expected = 0;
|
|
21
|
-
|
|
22
|
-
let timerDebug = false;
|
|
23
|
-
export function enableTimerDebug(): void {
|
|
24
|
-
timerDebug = true;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
let checkIfTimeIsUpDisabled = false;
|
|
28
|
-
export function disableCheckIfTimeIsUp(): void {
|
|
29
|
-
checkIfTimeIsUpDisabled = true;
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function clear(): void {
|
|
33
|
-
Time.set(0);
|
|
34
|
-
if (timer !== null) clearTimeout(timer);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function premid(): void {
|
|
38
|
-
if (timerDebug) console.time('premid');
|
|
39
|
-
const premidSecondsLeft = document.querySelector('#premidSecondsLeft');
|
|
40
|
-
|
|
41
|
-
if (premidSecondsLeft !== null) {
|
|
42
|
-
premidSecondsLeft.innerHTML = (Config.time - Time.get()).toString();
|
|
43
|
-
}
|
|
44
|
-
if (timerDebug) console.timeEnd('premid');
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function updateTimer(): void {
|
|
48
|
-
if (timerDebug) console.time('timer progress update');
|
|
49
|
-
if (Config.mode === 'time' || (Config.mode === 'custom' && CustomText.isTimeRandom)) {
|
|
50
|
-
TimerProgress.update();
|
|
51
|
-
}
|
|
52
|
-
if (timerDebug) console.timeEnd('timer progress update');
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
function calculateWpmRaw(): MonkeyTypes.WordsPerMinuteAndRaw {
|
|
56
|
-
if (timerDebug) console.time('calculate wpm and raw');
|
|
57
|
-
const wpmAndRaw = TestStats.calculateWpmAndRaw();
|
|
58
|
-
if (timerDebug) console.timeEnd('calculate wpm and raw');
|
|
59
|
-
if (timerDebug) console.time('push to history');
|
|
60
|
-
TestInput.pushToWpmHistory(wpmAndRaw.wpm);
|
|
61
|
-
TestInput.pushToRawHistory(wpmAndRaw.raw);
|
|
62
|
-
if (timerDebug) console.timeEnd('push to history');
|
|
63
|
-
return wpmAndRaw;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
function monkey(wpmAndRaw: MonkeyTypes.WordsPerMinuteAndRaw): void {
|
|
67
|
-
if (timerDebug) console.time('update monkey');
|
|
68
|
-
const num = Config.blindMode ? wpmAndRaw.raw : wpmAndRaw.wpm;
|
|
69
|
-
if (timerDebug) console.timeEnd('update monkey');
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function calculateAcc(): number {
|
|
73
|
-
if (timerDebug) console.time('calculate acc');
|
|
74
|
-
const acc = Misc.roundTo2(TestStats.calculateAccuracy());
|
|
75
|
-
if (timerDebug) console.timeEnd('calculate acc');
|
|
76
|
-
return acc;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function layoutfluid(): void {
|
|
80
|
-
if (timerDebug) console.time('layoutfluid');
|
|
81
|
-
if (Config.funbox === 'layoutfluid' && Config.mode === 'time') {
|
|
82
|
-
const layouts = Config.customLayoutfluid
|
|
83
|
-
? Config.customLayoutfluid.split('#')
|
|
84
|
-
: ['qwerty', 'dvorak', 'colemak'];
|
|
85
|
-
const switchTime = Config.time / layouts.length;
|
|
86
|
-
const time = Time.get();
|
|
87
|
-
const index = Math.floor(time / switchTime);
|
|
88
|
-
const layout = layouts[index];
|
|
89
|
-
const flooredSwitchTimes = [];
|
|
90
|
-
|
|
91
|
-
for (let i = 1; i < layouts.length; i++) {
|
|
92
|
-
flooredSwitchTimes.push(Math.floor(switchTime * i));
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
if (timerDebug) console.timeEnd('layoutfluid');
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
function checkIfFailed(wpmAndRaw: MonkeyTypes.WordsPerMinuteAndRaw, acc: number): void {
|
|
99
|
-
if (timerDebug) console.time('fail conditions');
|
|
100
|
-
TestInput.pushKeypressesToHistory();
|
|
101
|
-
if (
|
|
102
|
-
Config.minWpm === 'custom' &&
|
|
103
|
-
wpmAndRaw.wpm < Config.minWpmCustomSpeed &&
|
|
104
|
-
TestWords.words.currentIndex > 3
|
|
105
|
-
) {
|
|
106
|
-
if (timer !== null) clearTimeout(timer);
|
|
107
|
-
SlowTimer.clear();
|
|
108
|
-
slowTimerCount = 0;
|
|
109
|
-
TimerEvent.dispatch('fail', 'min wpm');
|
|
110
|
-
return;
|
|
111
|
-
}
|
|
112
|
-
if (Config.minAcc === 'custom' && acc < Config.minAccCustom) {
|
|
113
|
-
if (timer !== null) clearTimeout(timer);
|
|
114
|
-
SlowTimer.clear();
|
|
115
|
-
slowTimerCount = 0;
|
|
116
|
-
TimerEvent.dispatch('fail', 'min accuracy');
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
if (timerDebug) console.timeEnd('fail conditions');
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function checkIfTimeIsUp(): void {
|
|
123
|
-
if (timerDebug) console.time('times up check');
|
|
124
|
-
if (Config.mode == 'time' || (Config.mode === 'custom' && CustomText.isTimeRandom)) {
|
|
125
|
-
if (
|
|
126
|
-
(Time.get() >= Config.time && Config.time !== 0 && Config.mode === 'time') ||
|
|
127
|
-
(Time.get() >= CustomText.time && CustomText.time !== 0 && Config.mode === 'custom')
|
|
128
|
-
) {
|
|
129
|
-
//times up
|
|
130
|
-
if (timer !== null) clearTimeout(timer);
|
|
131
|
-
Caret.hide();
|
|
132
|
-
TestInput.input.pushHistory();
|
|
133
|
-
TestInput.corrected.pushHistory();
|
|
134
|
-
SlowTimer.clear();
|
|
135
|
-
slowTimerCount = 0;
|
|
136
|
-
TimerEvent.dispatch('finish');
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
if (timerDebug) console.timeEnd('times up check');
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
// ---------------------------------------
|
|
144
|
-
|
|
145
|
-
let timerStats: MonkeyTypes.TimerStats[] = [];
|
|
146
|
-
|
|
147
|
-
export function getTimerStats(): MonkeyTypes.TimerStats[] {
|
|
148
|
-
return timerStats;
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
async function timerStep(): Promise<void> {
|
|
152
|
-
if (timerDebug) console.time('timer step -----------------------------');
|
|
153
|
-
Time.increment();
|
|
154
|
-
premid();
|
|
155
|
-
updateTimer();
|
|
156
|
-
const wpmAndRaw = calculateWpmRaw();
|
|
157
|
-
const acc = calculateAcc();
|
|
158
|
-
monkey(wpmAndRaw);
|
|
159
|
-
layoutfluid();
|
|
160
|
-
checkIfFailed(wpmAndRaw, acc);
|
|
161
|
-
if (!checkIfTimeIsUpDisabled) {
|
|
162
|
-
checkIfTimeIsUp();
|
|
163
|
-
}
|
|
164
|
-
if (timerDebug) console.timeEnd('timer step -----------------------------');
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
export async function start(): Promise<void> {
|
|
168
|
-
SlowTimer.clear();
|
|
169
|
-
slowTimerCount = 0;
|
|
170
|
-
timerStats = [];
|
|
171
|
-
expected = TestStats.start + interval;
|
|
172
|
-
(function loop(): void {
|
|
173
|
-
const delay = expected - performance.now();
|
|
174
|
-
timerStats.push({
|
|
175
|
-
dateNow: Date.now(),
|
|
176
|
-
now: performance.now(),
|
|
177
|
-
expected: expected,
|
|
178
|
-
nextDelay: delay,
|
|
179
|
-
});
|
|
180
|
-
if (
|
|
181
|
-
(Config.mode === 'time' && Config.time < 130 && Config.time > 0) ||
|
|
182
|
-
(Config.mode === 'words' && Config.words < 250 && Config.words > 0)
|
|
183
|
-
) {
|
|
184
|
-
if (delay < interval / 2) {
|
|
185
|
-
//slow timer
|
|
186
|
-
SlowTimer.set();
|
|
187
|
-
}
|
|
188
|
-
if (delay < interval / 10) {
|
|
189
|
-
slowTimerCount++;
|
|
190
|
-
if (slowTimerCount > 5) {
|
|
191
|
-
TimerEvent.dispatch('fail', 'slow timer');
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
}
|
|
195
|
-
timer = setTimeout(function () {
|
|
196
|
-
if (!TestActive.get()) {
|
|
197
|
-
if (timer !== null) clearTimeout(timer);
|
|
198
|
-
SlowTimer.clear();
|
|
199
|
-
slowTimerCount = 0;
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
timerStep();
|
|
204
|
-
|
|
205
|
-
expected += interval;
|
|
206
|
-
loop();
|
|
207
|
-
}, delay);
|
|
208
|
-
})();
|
|
209
|
-
}
|