@testgorilla/tgo-typing-test 1.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 +795 -811
- package/fesm2022/testgorilla-tgo-typing-test.mjs.map +1 -1
- package/lib/helpers/config.d.ts +4 -4
- package/lib/utils/misc.d.ts +0 -1
- package/package.json +6 -8
- package/esm2022/index.mjs +0 -3
- package/esm2022/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.mjs +0 -45
- package/esm2022/lib/components/tgo-typing-test/tgo-typing-test.component.mjs +0 -299
- package/esm2022/lib/helpers/config.mjs +0 -24
- package/esm2022/lib/helpers/constants/default-config.mjs +0 -103
- package/esm2022/lib/helpers/controllers/input-controller.mjs +0 -586
- package/esm2022/lib/helpers/controllers/quotes-controller.mjs +0 -118
- package/esm2022/lib/helpers/observables/config-event.mjs +0 -16
- package/esm2022/lib/helpers/observables/timer-event.mjs +0 -16
- package/esm2022/lib/helpers/states/active-page.mjs +0 -8
- package/esm2022/lib/helpers/states/composition.mjs +0 -20
- package/esm2022/lib/helpers/states/page-transition.mjs +0 -8
- package/esm2022/lib/helpers/states/slow-timer.mjs +0 -15
- package/esm2022/lib/helpers/states/test-active.mjs +0 -8
- package/esm2022/lib/helpers/states/time.mjs +0 -11
- package/esm2022/lib/helpers/test/caps-warning.mjs +0 -50
- package/esm2022/lib/helpers/test/caret.mjs +0 -80
- package/esm2022/lib/helpers/test/custom-text.mjs +0 -59
- package/esm2022/lib/helpers/test/english-punctuation.mjs +0 -29
- package/esm2022/lib/helpers/test/focus.mjs +0 -35
- package/esm2022/lib/helpers/test/manual-restart-tracker.mjs +0 -11
- package/esm2022/lib/helpers/test/out-of-focus.mjs +0 -14
- package/esm2022/lib/helpers/test/replay.mjs +0 -217
- package/esm2022/lib/helpers/test/test-input.mjs +0 -264
- package/esm2022/lib/helpers/test/test-logic.mjs +0 -927
- package/esm2022/lib/helpers/test/test-state.mjs +0 -13
- package/esm2022/lib/helpers/test/test-stats.mjs +0 -342
- package/esm2022/lib/helpers/test/test-timer.mjs +0 -207
- package/esm2022/lib/helpers/test/test-ui.mjs +0 -341
- package/esm2022/lib/helpers/test/test-words.mjs +0 -69
- package/esm2022/lib/helpers/test/timer-progress.mjs +0 -15
- package/esm2022/lib/helpers/test/weak-spot.mjs +0 -65
- package/esm2022/lib/helpers/test/wordset.mjs +0 -100
- package/esm2022/lib/utils/misc.mjs +0 -673
- package/esm2022/testgorilla-tgo-typing-test.mjs +0 -5
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
import config from '../../helpers/config';
|
|
2
|
-
let wordsList = [];
|
|
3
|
-
let replayData = [];
|
|
4
|
-
let replayStartTime = 0;
|
|
5
|
-
let replayRecording = true;
|
|
6
|
-
let wordPos = 0;
|
|
7
|
-
let curPos = 0;
|
|
8
|
-
let targetWordPos = 0;
|
|
9
|
-
let targetCurPos = 0;
|
|
10
|
-
let timeoutList = [];
|
|
11
|
-
let stopwatchList = [];
|
|
12
|
-
let toggleButton;
|
|
13
|
-
let replayStopwatch;
|
|
14
|
-
function setToggleButton(toggleButtonElement) {
|
|
15
|
-
toggleButton = toggleButtonElement?.children[0];
|
|
16
|
-
}
|
|
17
|
-
function setReplayStopwatch(replayStopwatchElement) {
|
|
18
|
-
replayStopwatch = replayStopwatchElement;
|
|
19
|
-
}
|
|
20
|
-
function replayGetWordsList(wordsListFromScript) {
|
|
21
|
-
wordsList = wordsListFromScript;
|
|
22
|
-
}
|
|
23
|
-
function initializeReplayPrompt() {
|
|
24
|
-
const replayWordsElement = document.getElementById('replayWords');
|
|
25
|
-
if (replayWordsElement === null)
|
|
26
|
-
return;
|
|
27
|
-
replayWordsElement.innerHTML = '';
|
|
28
|
-
let wordCount = 0;
|
|
29
|
-
replayData.forEach(item => {
|
|
30
|
-
if (item.action === 'backWord') {
|
|
31
|
-
wordCount--;
|
|
32
|
-
}
|
|
33
|
-
else if (item.action === 'submitCorrectWord' || item.action === 'submitErrorWord') {
|
|
34
|
-
wordCount++;
|
|
35
|
-
}
|
|
36
|
-
});
|
|
37
|
-
wordsList.forEach((item, i) => {
|
|
38
|
-
if (i > wordCount)
|
|
39
|
-
return;
|
|
40
|
-
const x = document.createElement('div');
|
|
41
|
-
x.className = 'word';
|
|
42
|
-
for (i = 0; i < item.length; i++) {
|
|
43
|
-
const letter = document.createElement('letter');
|
|
44
|
-
letter.innerHTML = item[i];
|
|
45
|
-
x.appendChild(letter);
|
|
46
|
-
}
|
|
47
|
-
replayWordsElement.appendChild(x);
|
|
48
|
-
if (config.funbox === 'tenKeyMode') {
|
|
49
|
-
const y = document.createElement('div');
|
|
50
|
-
y.className = 'newline';
|
|
51
|
-
replayWordsElement.appendChild(y);
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
export function pauseReplay() {
|
|
56
|
-
timeoutList.forEach(item => {
|
|
57
|
-
clearTimeout(item);
|
|
58
|
-
});
|
|
59
|
-
timeoutList = [];
|
|
60
|
-
stopwatchList.forEach(item => {
|
|
61
|
-
clearTimeout(item);
|
|
62
|
-
});
|
|
63
|
-
stopwatchList = [];
|
|
64
|
-
targetCurPos = curPos;
|
|
65
|
-
targetWordPos = wordPos;
|
|
66
|
-
if (toggleButton === undefined)
|
|
67
|
-
return;
|
|
68
|
-
toggleButton.className = 'Play';
|
|
69
|
-
toggleButton.parentNode?.setAttribute('aria-label', 'Resume replay');
|
|
70
|
-
}
|
|
71
|
-
function handleDisplayLogic(item, nosound = false) {
|
|
72
|
-
let activeWord = document.getElementById('replayWords')?.children[wordPos];
|
|
73
|
-
if (activeWord === undefined)
|
|
74
|
-
return;
|
|
75
|
-
if (activeWord.className == 'newline') {
|
|
76
|
-
curPos = 0;
|
|
77
|
-
wordPos++;
|
|
78
|
-
activeWord = document.getElementById('replayWords')?.children[wordPos];
|
|
79
|
-
if (activeWord === undefined)
|
|
80
|
-
return;
|
|
81
|
-
}
|
|
82
|
-
if (item.action === 'correctLetter') {
|
|
83
|
-
// if (!nosound) playSound();
|
|
84
|
-
activeWord.children[curPos].classList.add('correct');
|
|
85
|
-
curPos++;
|
|
86
|
-
}
|
|
87
|
-
else if (item.action === 'incorrectLetter') {
|
|
88
|
-
// if (!nosound) playSound(true);
|
|
89
|
-
let myElement;
|
|
90
|
-
if (curPos >= activeWord.children.length) {
|
|
91
|
-
//if letter is an extra
|
|
92
|
-
myElement = document.createElement('letter');
|
|
93
|
-
myElement.classList.add('extra');
|
|
94
|
-
myElement.innerHTML = item.value?.toString() ?? '';
|
|
95
|
-
activeWord.appendChild(myElement);
|
|
96
|
-
}
|
|
97
|
-
myElement = activeWord.children[curPos];
|
|
98
|
-
myElement.classList.add('incorrect');
|
|
99
|
-
curPos++;
|
|
100
|
-
}
|
|
101
|
-
else if (item.action === 'setLetterIndex' && typeof item.value === 'number') {
|
|
102
|
-
curPos = item.value;
|
|
103
|
-
// remove all letters from cursor to end of word
|
|
104
|
-
for (const myElement of Array.from(activeWord.children).slice(curPos)) {
|
|
105
|
-
if (myElement.classList.contains('extra')) {
|
|
106
|
-
myElement.remove();
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
myElement.className = '';
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
else if (item.action === 'submitCorrectWord') {
|
|
114
|
-
wordPos++;
|
|
115
|
-
curPos = 0;
|
|
116
|
-
}
|
|
117
|
-
else if (item.action === 'submitErrorWord') {
|
|
118
|
-
activeWord.classList.add('error');
|
|
119
|
-
wordPos++;
|
|
120
|
-
curPos = 0;
|
|
121
|
-
}
|
|
122
|
-
else if (item.action === 'backWord') {
|
|
123
|
-
wordPos--;
|
|
124
|
-
const replayWords = document.getElementById('replayWords');
|
|
125
|
-
if (replayWords !== null)
|
|
126
|
-
activeWord = replayWords.children[wordPos];
|
|
127
|
-
curPos = activeWord.children.length;
|
|
128
|
-
while (activeWord.children[curPos - 1].className === '')
|
|
129
|
-
curPos--;
|
|
130
|
-
activeWord.classList.remove('error');
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
function loadOldReplay() {
|
|
134
|
-
let startingIndex = 0;
|
|
135
|
-
curPos = 0;
|
|
136
|
-
wordPos = 0;
|
|
137
|
-
replayData.forEach((item, i) => {
|
|
138
|
-
if (wordPos < targetWordPos || (wordPos === targetWordPos && curPos < targetCurPos)) {
|
|
139
|
-
//quickly display everything up to the target
|
|
140
|
-
handleDisplayLogic(item, true);
|
|
141
|
-
startingIndex = i + 1;
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
const time = Math.floor((replayData[startingIndex]?.time || 0) / 1000);
|
|
145
|
-
replayStopwatch.innerText = time + 's';
|
|
146
|
-
return startingIndex;
|
|
147
|
-
}
|
|
148
|
-
function startReplayRecording() {
|
|
149
|
-
replayData = [];
|
|
150
|
-
replayStartTime = performance.now();
|
|
151
|
-
replayRecording = true;
|
|
152
|
-
targetCurPos = 0;
|
|
153
|
-
targetWordPos = 0;
|
|
154
|
-
}
|
|
155
|
-
function stopReplayRecording() {
|
|
156
|
-
replayRecording = false;
|
|
157
|
-
}
|
|
158
|
-
function addReplayEvent(action, value) {
|
|
159
|
-
if (!replayRecording) {
|
|
160
|
-
return;
|
|
161
|
-
}
|
|
162
|
-
const timeDelta = performance.now() - replayStartTime;
|
|
163
|
-
replayData.push({ action: action, value: value, time: timeDelta });
|
|
164
|
-
}
|
|
165
|
-
function playReplay() {
|
|
166
|
-
curPos = 0;
|
|
167
|
-
wordPos = 0;
|
|
168
|
-
if (toggleButton === undefined)
|
|
169
|
-
return;
|
|
170
|
-
toggleButton.className = 'Pause';
|
|
171
|
-
toggleButton.parentNode?.setAttribute('aria-label', 'Pause replay');
|
|
172
|
-
initializeReplayPrompt();
|
|
173
|
-
const startingIndex = loadOldReplay();
|
|
174
|
-
const lastTime = replayData[startingIndex]?.time || 0;
|
|
175
|
-
let swTime = Math.round(lastTime / 1000); //starting time
|
|
176
|
-
const swEndTime = Math.round((replayData[replayData.length - 1]?.time || 0) / 1000);
|
|
177
|
-
while (swTime <= swEndTime) {
|
|
178
|
-
const time = swTime;
|
|
179
|
-
stopwatchList.push(setTimeout(() => {
|
|
180
|
-
replayStopwatch.innerText = time + 's';
|
|
181
|
-
}, time * 1000 - lastTime));
|
|
182
|
-
swTime++;
|
|
183
|
-
}
|
|
184
|
-
replayData.forEach((item, i) => {
|
|
185
|
-
if (i < startingIndex)
|
|
186
|
-
return;
|
|
187
|
-
timeoutList.push(setTimeout(() => {
|
|
188
|
-
handleDisplayLogic(item);
|
|
189
|
-
}, item.time - lastTime));
|
|
190
|
-
});
|
|
191
|
-
timeoutList.push(setTimeout(() => {
|
|
192
|
-
//after the replay has finished, this will run
|
|
193
|
-
targetCurPos = 0;
|
|
194
|
-
targetWordPos = 0;
|
|
195
|
-
toggleButton.className = 'Play';
|
|
196
|
-
toggleButton.parentNode.setAttribute('aria-label', 'Start replay');
|
|
197
|
-
}, (replayData[replayData.length - 1]?.time || 0) - lastTime));
|
|
198
|
-
}
|
|
199
|
-
function getReplayExport() {
|
|
200
|
-
return JSON.stringify({
|
|
201
|
-
replayData: replayData,
|
|
202
|
-
wordsList: wordsList,
|
|
203
|
-
});
|
|
204
|
-
}
|
|
205
|
-
function setReplayData(data) {
|
|
206
|
-
replayData = data;
|
|
207
|
-
}
|
|
208
|
-
function playpauseReplayButtonClick() {
|
|
209
|
-
if (toggleButton?.className === 'Play') {
|
|
210
|
-
playReplay();
|
|
211
|
-
}
|
|
212
|
-
else if (toggleButton?.className === 'Pause') {
|
|
213
|
-
pauseReplay();
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
export { addReplayEvent, getReplayExport, initializeReplayPrompt, loadOldReplay, playReplay, playpauseReplayButtonClick, replayGetWordsList, setReplayData, setReplayStopwatch, setToggleButton, startReplayRecording, stopReplayRecording, };
|
|
217
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVwbGF5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvdGdvLXR5cGluZy10ZXN0L3NyYy9saWIvaGVscGVycy90ZXN0L3JlcGxheS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLE1BQU0sTUFBTSxzQkFBc0IsQ0FBQztBQWdCMUMsSUFBSSxTQUFTLEdBQWEsRUFBRSxDQUFDO0FBQzdCLElBQUksVUFBVSxHQUFhLEVBQUUsQ0FBQztBQUM5QixJQUFJLGVBQWUsR0FBRyxDQUFDLENBQUM7QUFDeEIsSUFBSSxlQUFlLEdBQUcsSUFBSSxDQUFDO0FBQzNCLElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQztBQUNoQixJQUFJLE1BQU0sR0FBRyxDQUFDLENBQUM7QUFDZixJQUFJLGFBQWEsR0FBRyxDQUFDLENBQUM7QUFDdEIsSUFBSSxZQUFZLEdBQUcsQ0FBQyxDQUFDO0FBQ3JCLElBQUksV0FBVyxHQUFxQixFQUFFLENBQUM7QUFDdkMsSUFBSSxhQUFhLEdBQXFCLEVBQUUsQ0FBQztBQUN6QyxJQUFJLFlBQXFCLENBQUM7QUFDMUIsSUFBSSxlQUE0QixDQUFDO0FBRWpDLFNBQVMsZUFBZSxDQUFDLG1CQUFnQztJQUN2RCxZQUFZLEdBQUcsbUJBQW1CLEVBQUUsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDO0FBQ2xELENBQUM7QUFFRCxTQUFTLGtCQUFrQixDQUFDLHNCQUFtQztJQUM3RCxlQUFlLEdBQUcsc0JBQXNCLENBQUM7QUFDM0MsQ0FBQztBQUVELFNBQVMsa0JBQWtCLENBQUMsbUJBQTZCO0lBQ3ZELFNBQVMsR0FBRyxtQkFBbUIsQ0FBQztBQUNsQyxDQUFDO0FBRUQsU0FBUyxzQkFBc0I7SUFDN0IsTUFBTSxrQkFBa0IsR0FBRyxRQUFRLENBQUMsY0FBYyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBRWxFLElBQUksa0JBQWtCLEtBQUssSUFBSTtRQUFFLE9BQU87SUFFeEMsa0JB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Q0FBQztBQUNILENBQUM7QUFFRCxPQUFPLEVBQ0wsY0FBYyxFQUNkLGVBQWUsRUFDZixzQkFBc0IsRUFDdEIsYUFBYSxFQUNiLFVBQVUsRUFDViwwQkFBMEIsRUFDMUIsa0JBQWtCLEVBQ2xCLGFBQWEsRUFDYixrQkFBa0IsRUFDbEIsZUFBZSxFQUNmLG9CQUFvQixFQUNwQixtQkFBbUIsR0FDcEIsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBjb25maWcgZnJvbSAnLi4vLi4vaGVscGVycy9jb25maWcnO1xuXG50eXBlIFJlcGxheUFjdGlvbiA9XG4gIHwgJ2NvcnJlY3RMZXR0ZXInXG4gIHwgJ2luY29ycmVjdExldHRlcidcbiAgfCAnYmFja1dvcmQnXG4gIHwgJ3N1Ym1pdENvcnJlY3RXb3JkJ1xuICB8ICdzdWJtaXRFcnJvcldvcmQnXG4gIHwgJ3NldExldHRlckluZGV4JztcblxuaW50ZXJmYWNlIFJlcGxheSB7XG4gIGFjdGlvbjogUmVwbGF5QWN0aW9uO1xuICB2YWx1ZT86IHN0cmluZyB8IG51bWJlcjtcbiAgdGltZTogbnVtYmVyO1xufVxuXG5sZXQgd29yZHNMaXN0OiBzdHJpbmdbXSA9IFtdO1xubGV0IHJlcGxheURhdGE6IFJlcGxheVtdID0gW107XG5sZXQgcmVwbGF5U3RhcnRUaW1lID0gMDtcbmxldCByZXBsYXlSZWNvcmRpbmcgPSB0cnVlO1xubGV0IHdvcmRQb3MgPSAwO1xubGV0IGN1clBvcyA9IDA7XG5sZXQgdGFyZ2V0V29yZFBvcyA9IDA7XG5sZXQgdGFyZ2V0Q3VyUG9zID0gMDtcbmxldCB0aW1lb3V0TGlzdDogTm9kZUpTLlRpbWVvdXRbXSA9IFtdO1xubGV0IHN0b3B3YXRjaExpc3Q6IE5vZGVKUy5UaW1lb3V0W10gPSBbXTtcbmxldCB0b2dnbGVCdXR0b246IEVsZW1lbnQ7XG5sZXQgcmVwbGF5U3RvcHdhdGNoOiBIVE1MRWxlbWVudDtcblxuZnVuY3Rpb24gc2V0VG9nZ2xlQnV0dG9uKHRvZ2dsZUJ1dHRvbkVsZW1lbnQ6IEhUTUxFbGVtZW50KSB7XG4gIHRvZ2dsZUJ1dHRvbiA9IHRvZ2dsZUJ1dHRvbkVsZW1lbnQ/LmNoaWxkcmVuWzBdO1xufVxuXG5mdW5jdGlvbiBzZXRSZXBsYXlTdG9wd2F0Y2gocmVwbGF5U3RvcHdhdGNoRWxlbWVudDogSFRNTEVsZW1lbnQpIHtcbiAgcmVwbGF5U3RvcHdhdGNoID0gcmVwbGF5U3RvcHdhdGNoRWxlbWVudDtcbn1cblxuZnVuY3Rpb24gcmVwbGF5R2V0V29yZHNMaXN0KHdvcmRzTGlzdEZyb21TY3JpcHQ6IHN0cmluZ1tdKTogdm9pZCB7XG4gIHdvcmRzTGlzdCA9IHdvcmRzTGlzdEZyb21TY3JpcHQ7XG59XG5cbmZ1bmN0aW9uIGluaXRpYWxpemVSZXBsYXlQcm9tcHQoKTogdm9pZCB7XG4gIGNvbnN0IHJlcGxheVdvcmRzRWxlbWVudCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdyZXBsYXlXb3JkcycpO1xuXG4gIGlmIChyZXBsYXlXb3Jkc0VsZW1lbnQgPT09IG51bGwpIHJldHVybjtcblxuICByZXBsYXlXb3Jkc0VsZW1lbnQuaW5uZXJIVE1MID0gJyc7XG4gIGxldCB3b3JkQ291bnQgPSAwO1xuICByZXBsYXlEYXRhLmZvckVhY2goaXRlbSA9PiB7XG4gICAgaWYgKGl0ZW0uYWN0aW9uID09PSAnYmFja1dvcmQnKSB7XG4gICAgICB3b3JkQ291bnQtLTtcbiAgICB9IGVsc2UgaWYgKGl0ZW0uYWN0aW9uID09PSAnc3VibWl0Q29ycmVjdFdvcmQnIHx8IGl0ZW0uYWN0aW9uID09PSAnc3VibWl0RXJyb3JXb3JkJykge1xuICAgICAgd29yZENvdW50Kys7XG4gICAgfVxuICB9KTtcbiAgd29yZHNMaXN0LmZvckVhY2goKGl0ZW0sIGkpID0+IHtcbiAgICBpZiAoaSA+IHdvcmRDb3VudCkgcmV0dXJuO1xuICAgIGNvbnN0IHggPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICB4LmNsYXNzTmFtZSA9ICd3b3JkJztcbiAgICBmb3IgKGkgPSAwOyBpIDwgaXRlbS5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3QgbGV0dGVyID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnbGV0dGVyJyk7XG4gICAgICBsZXR0ZXIuaW5uZXJIVE1MID0gaXRlbVtpXTtcbiAgICAgIHguYXBwZW5kQ2hpbGQobGV0dGVyKTtcbiAgICB9XG4gICAgcmVwbGF5V29yZHNFbGVtZW50LmFwcGVuZENoaWxkKHgpO1xuICAgIGlmIChjb25maWcuZnVuYm94ID09PSAndGVuS2V5TW9kZScpIHtcbiAgICAgIGNvbnN0IHkgPSBkb2N1bWVudC5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgIHkuY2xhc3NOYW1lID0gJ25ld2xpbmUnO1xuICAgICAgcmVwbGF5V29yZHNFbGVtZW50LmFwcGVuZENoaWxkKHkpO1xuICAgIH1cbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwYXVzZVJlcGxheSgpOiB2b2lkIHtcbiAgdGltZW91dExpc3QuZm9yRWFjaChpdGVtID0+IHtcbiAgICBjbGVhclRpbWVvdXQoaXRlbSk7XG4gIH0pO1xuICB0aW1lb3V0TGlzdCA9IFtdO1xuICBzdG9wd2F0Y2hMaXN0LmZvckVhY2goaXRlbSA9PiB7XG4gICAgY2xlYXJUaW1lb3V0KGl0ZW0pO1xuICB9KTtcbiAgc3RvcHdhdGNoTGlzdCA9IFtdO1xuICB0YXJnZXRDdXJQb3MgPSBjdXJQb3M7XG4gIHRhcmdldFdvcmRQb3MgPSB3b3JkUG9zO1xuXG4gIGlmICh0b2dnbGVCdXR0b24gPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuXG4gIHRvZ2dsZUJ1dHRvbi5jbGFzc05hbWUgPSAnUGxheSc7XG4gICh0b2dnbGVCdXR0b24ucGFyZW50Tm9kZSBhcyBFbGVtZW50KT8uc2V0QXR0cmlidXRlKCdhcmlhLWxhYmVsJywgJ1Jlc3VtZSByZXBsYXknKTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlRGlzcGxheUxvZ2ljKGl0ZW06IFJlcGxheSwgbm9zb3VuZCA9IGZhbHNlKTogdm9pZCB7XG4gIGxldCBhY3RpdmVXb3JkID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3JlcGxheVdvcmRzJyk/LmNoaWxkcmVuW3dvcmRQb3NdO1xuXG4gIGlmIChhY3RpdmVXb3JkID09PSB1bmRlZmluZWQpIHJldHVybjtcbiAgaWYgKGFjdGl2ZVdvcmQuY2xhc3NOYW1lID09ICduZXdsaW5lJykge1xuICAgIGN1clBvcyA9IDA7XG4gICAgd29yZFBvcysrO1xuICAgIGFjdGl2ZVdvcmQgPSBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCgncmVwbGF5V29yZHMnKT8uY2hpbGRyZW5bd29yZFBvc107XG4gICAgaWYgKGFjdGl2ZVdvcmQgPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuICB9XG4gIGlmIChpdGVtLmFjdGlvbiA9PT0gJ2NvcnJlY3RMZXR0ZXInKSB7XG4gICAgLy8gaWYgKCFub3NvdW5kKSBwbGF5U291bmQoKTtcbiAgICBhY3RpdmVXb3JkLmNoaWxkcmVuW2N1clBvc10uY2xhc3NMaXN0LmFkZCgnY29ycmVjdCcpO1xuICAgIGN1clBvcysrO1xuICB9IGVsc2UgaWYgKGl0ZW0uYWN0aW9uID09PSAnaW5jb3JyZWN0TGV0dGVyJykge1xuICAgIC8vIGlmICghbm9zb3VuZCkgcGxheVNvdW5kKHRydWUpO1xuICAgIGxldCBteUVsZW1lbnQ7XG4gICAgaWYgKGN1clBvcyA+PSBhY3RpdmVXb3JkLmNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgLy9pZiBsZXR0ZXIgaXMgYW4gZXh0cmFcbiAgICAgIG15RWxlbWVudCA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoJ2xldHRlcicpO1xuICAgICAgbXlFbGVtZW50LmNsYXNzTGlzdC5hZGQoJ2V4dHJhJyk7XG4gICAgICBteUVsZW1lbnQuaW5uZXJIVE1MID0gaXRlbS52YWx1ZT8udG9TdHJpbmcoKSA/PyAnJztcbiAgICAgIGFjdGl2ZVdvcmQuYXBwZW5kQ2hpbGQobXlFbGVtZW50KTtcbiAgICB9XG4gICAgbXlFbGVtZW50ID0gYWN0aXZlV29yZC5jaGlsZHJlbltjdXJQb3NdO1xuICAgIG15RWxlbWVudC5jbGFzc0xpc3QuYWRkKCdpbmNvcnJlY3QnKTtcbiAgICBjdXJQb3MrKztcbiAgfSBlbHNlIGlmIChpdGVtLmFjdGlvbiA9PT0gJ3NldExldHRlckluZGV4JyAmJiB0eXBlb2YgaXRlbS52YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICBjdXJQb3MgPSBpdGVtLnZhbHVlO1xuICAgIC8vIHJlbW92ZSBhbGwgbGV0dGVycyBmcm9tIGN1cnNvciB0byBlbmQgb2Ygd29yZFxuICAgIGZvciAoY29uc3QgbXlFbGVtZW50IG9mIEFycmF5LmZyb20oYWN0aXZlV29yZC5jaGlsZHJlbikuc2xpY2UoY3VyUG9zKSkge1xuICAgICAgaWYgKG15RWxlbWVudC5jbGFzc0xpc3QuY29udGFpbnMoJ2V4dHJhJykpIHtcbiAgICAgICAgbXlFbGVtZW50LnJlbW92ZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbXlFbGVtZW50LmNsYXNzTmFtZSA9ICcnO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIGlmIChpdGVtLmFjdGlvbiA9PT0gJ3N1Ym1pdENvcnJlY3RXb3JkJykge1xuICAgIHdvcmRQb3MrKztcbiAgICBjdXJQb3MgPSAwO1xuICB9IGVsc2UgaWYgKGl0ZW0uYWN0aW9uID09PSAnc3VibWl0RXJyb3JXb3JkJykge1xuICAgIGFjdGl2ZVdvcmQuY2xhc3NMaXN0LmFkZCgnZXJyb3InKTtcbiAgICB3b3JkUG9zKys7XG4gICAgY3VyUG9zID0gMDtcbiAgfSBlbHNlIGlmIChpdGVtLmFjdGlvbiA9PT0gJ2JhY2tXb3JkJykge1xuICAgIHdvcmRQb3MtLTtcblxuICAgIGNvbnN0IHJlcGxheVdvcmRzID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoJ3JlcGxheVdvcmRzJyk7XG5cbiAgICBpZiAocmVwbGF5V29yZHMgIT09IG51bGwpIGFjdGl2ZVdvcmQgPSByZXBsYXlXb3Jkcy5jaGlsZHJlblt3b3JkUG9zXTtcblxuICAgIGN1clBvcyA9IGFjdGl2ZVdvcmQuY2hpbGRyZW4ubGVuZ3RoO1xuICAgIHdoaWxlIChhY3RpdmVXb3JkLmNoaWxkcmVuW2N1clBvcyAtIDFdLmNsYXNzTmFtZSA9PT0gJycpIGN1clBvcy0tO1xuICAgIGFjdGl2ZVdvcmQuY2xhc3NMaXN0LnJlbW92ZSgnZXJyb3InKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBsb2FkT2xkUmVwbGF5KCk6IG51bWJlciB7XG4gIGxldCBzdGFydGluZ0luZGV4ID0gMDtcbiAgY3VyUG9zID0gMDtcbiAgd29yZFBvcyA9IDA7XG4gIHJlcGxheURhdGEuZm9yRWFjaCgoaXRlbSwgaSkgPT4ge1xuICAgIGlmICh3b3JkUG9zIDwgdGFyZ2V0V29yZFBvcyB8fCAod29yZFBvcyA9PT0gdGFyZ2V0V29yZFBvcyAmJiBjdXJQb3MgPCB0YXJnZXRDdXJQb3MpKSB7XG4gICAgICAvL3F1aWNrbHkgZGlzcGxheSBldmVyeXRoaW5nIHVwIHRvIHRoZSB0YXJnZXRcbiAgICAgIGhhbmRsZURpc3BsYXlMb2dpYyhpdGVtLCB0cnVlKTtcbiAgICAgIHN0YXJ0aW5nSW5kZXggPSBpICsgMTtcbiAgICB9XG4gIH0pO1xuICBjb25zdCB0aW1lID0gTWF0aC5mbG9vcigocmVwbGF5RGF0YVtzdGFydGluZ0luZGV4XT8udGltZSB8fCAwKSAvIDEwMDApO1xuICByZXBsYXlTdG9wd2F0Y2guaW5uZXJUZXh0ID0gdGltZSArICdzJztcbiAgcmV0dXJuIHN0YXJ0aW5nSW5kZXg7XG59XG5cbmZ1bmN0aW9uIHN0YXJ0UmVwbGF5UmVjb3JkaW5nKCk6IHZvaWQge1xuICByZXBsYXlEYXRhID0gW107XG4gIHJlcGxheVN0YXJ0VGltZSA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICByZXBsYXlSZWNvcmRpbmcgPSB0cnVlO1xuICB0YXJnZXRDdXJQb3MgPSAwO1xuICB0YXJnZXRXb3JkUG9zID0gMDtcbn1cblxuZnVuY3Rpb24gc3RvcFJlcGxheVJlY29yZGluZygpOiB2b2lkIHtcbiAgcmVwbGF5UmVjb3JkaW5nID0gZmFsc2U7XG59XG5cbmZ1bmN0aW9uIGFkZFJlcGxheUV2ZW50KGFjdGlvbjogUmVwbGF5QWN0aW9uLCB2YWx1ZT86IG51bWJlciB8IHN0cmluZyk6IHZvaWQge1xuICBpZiAoIXJlcGxheVJlY29yZGluZykge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGNvbnN0IHRpbWVEZWx0YSA9IHBlcmZvcm1hbmNlLm5vdygpIC0gcmVwbGF5U3RhcnRUaW1lO1xuICByZXBsYXlEYXRhLnB1c2goeyBhY3Rpb246IGFjdGlvbiwgdmFsdWU6IHZhbHVlLCB0aW1lOiB0aW1lRGVsdGEgfSk7XG59XG5cbmZ1bmN0aW9uIHBsYXlSZXBsYXkoKTogdm9pZCB7XG4gIGN1clBvcyA9IDA7XG4gIHdvcmRQb3MgPSAwO1xuXG4gIGlmICh0b2dnbGVCdXR0b24gPT09IHVuZGVmaW5lZCkgcmV0dXJuO1xuXG4gIHRvZ2dsZUJ1dHRvbi5jbGFzc05hbWUgPSAnUGF1c2UnO1xuICAodG9nZ2xlQnV0dG9uLnBhcmVudE5vZGUgYXMgRWxlbWVudCk/LnNldEF0dHJpYnV0ZSgnYXJpYS1sYWJlbCcsICdQYXVzZSByZXBsYXknKTtcbiAgaW5pdGlhbGl6ZVJlcGxheVByb21wdCgpO1xuICBjb25zdCBzdGFydGluZ0luZGV4ID0gbG9hZE9sZFJlcGxheSgpO1xuICBjb25zdCBsYXN0VGltZSA9IHJlcGxheURhdGFbc3RhcnRpbmdJbmRleF0/LnRpbWUgfHwgMDtcbiAgbGV0IHN3VGltZSA9IE1hdGgucm91bmQobGFzdFRpbWUgLyAxMDAwKTsgLy9zdGFydGluZyB0aW1lXG4gIGNvbnN0IHN3RW5kVGltZSA9IE1hdGgucm91bmQoKHJlcGxheURhdGFbcmVwbGF5RGF0YS5sZW5ndGggLSAxXT8udGltZSB8fCAwKSAvIDEwMDApO1xuICB3aGlsZSAoc3dUaW1lIDw9IHN3RW5kVGltZSkge1xuICAgIGNvbnN0IHRpbWUgPSBzd1RpbWU7XG4gICAgc3RvcHdhdGNoTGlzdC5wdXNoKFxuICAgICAgc2V0VGltZW91dChcbiAgICAgICAgKCkgPT4ge1xuICAgICAgICAgIHJlcGxheVN0b3B3YXRjaC5pbm5lclRleHQgPSB0aW1lICsgJ3MnO1xuICAgICAgICB9LFxuICAgICAgICB0aW1lICogMTAwMCAtIGxhc3RUaW1lXG4gICAgICApXG4gICAgKTtcbiAgICBzd1RpbWUrKztcbiAgfVxuICByZXBsYXlEYXRhLmZvckVhY2goKGl0ZW0sIGkpID0+IHtcbiAgICBpZiAoaSA8IHN0YXJ0aW5nSW5kZXgpIHJldHVybjtcbiAgICB0aW1lb3V0TGlzdC5wdXNoKFxuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIGhhbmRsZURpc3BsYXlMb2dpYyhpdGVtKTtcbiAgICAgIH0sIGl0ZW0udGltZSAtIGxhc3RUaW1lKVxuICAgICk7XG4gIH0pO1xuICB0aW1lb3V0TGlzdC5wdXNoKFxuICAgIHNldFRpbWVvdXQoXG4gICAgICAoKSA9PiB7XG4gICAgICAgIC8vYWZ0ZXIgdGhlIHJlcGxheSBoYXMgZmluaXNoZWQsIHRoaXMgd2lsbCBydW5cbiAgICAgICAgdGFyZ2V0Q3VyUG9zID0gMDtcbiAgICAgICAgdGFyZ2V0V29yZFBvcyA9IDA7XG4gICAgICAgIHRvZ2dsZUJ1dHRvbi5jbGFzc05hbWUgPSAnUGxheSc7XG4gICAgICAgICh0b2dnbGVCdXR0b24ucGFyZW50Tm9kZSBhcyBFbGVtZW50KS5zZXRBdHRyaWJ1dGUoJ2FyaWEtbGFiZWwnLCAnU3RhcnQgcmVwbGF5Jyk7XG4gICAgICB9LFxuICAgICAgKHJlcGxheURhdGFbcmVwbGF5RGF0YS5sZW5ndGggLSAxXT8udGltZSB8fCAwKSAtIGxhc3RUaW1lXG4gICAgKVxuICApO1xufVxuXG5mdW5jdGlvbiBnZXRSZXBsYXlFeHBvcnQoKTogc3RyaW5nIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHtcbiAgICByZXBsYXlEYXRhOiByZXBsYXlEYXRhLFxuICAgIHdvcmRzTGlzdDogd29yZHNMaXN0LFxuICB9KTtcbn1cblxuZnVuY3Rpb24gc2V0UmVwbGF5RGF0YShkYXRhOiBSZXBsYXlbXSkge1xuICByZXBsYXlEYXRhID0gZGF0YTtcbn1cblxuZnVuY3Rpb24gcGxheXBhdXNlUmVwbGF5QnV0dG9uQ2xpY2soKSB7XG4gIGlmICh0b2dnbGVCdXR0b24/LmNsYXNzTmFtZSA9PT0gJ1BsYXknKSB7XG4gICAgcGxheVJlcGxheSgpO1xuICB9IGVsc2UgaWYgKHRvZ2dsZUJ1dHRvbj8uY2xhc3NOYW1lID09PSAnUGF1c2UnKSB7XG4gICAgcGF1c2VSZXBsYXkoKTtcbiAgfVxufVxuXG5leHBvcnQge1xuICBhZGRSZXBsYXlFdmVudCxcbiAgZ2V0UmVwbGF5RXhwb3J0LFxuICBpbml0aWFsaXplUmVwbGF5UHJvbXB0LFxuICBsb2FkT2xkUmVwbGF5LFxuICBwbGF5UmVwbGF5LFxuICBwbGF5cGF1c2VSZXBsYXlCdXR0b25DbGljayxcbiAgcmVwbGF5R2V0V29yZHNMaXN0LFxuICBzZXRSZXBsYXlEYXRhLFxuICBzZXRSZXBsYXlTdG9wd2F0Y2gsXG4gIHNldFRvZ2dsZUJ1dHRvbixcbiAgc3RhcnRSZXBsYXlSZWNvcmRpbmcsXG4gIHN0b3BSZXBsYXlSZWNvcmRpbmcsXG59O1xuIl19
|
|
@@ -1,264 +0,0 @@
|
|
|
1
|
-
import * as TestWords from './test-words';
|
|
2
|
-
import { roundTo2 } from '../../utils/misc';
|
|
3
|
-
class Input {
|
|
4
|
-
current;
|
|
5
|
-
history;
|
|
6
|
-
historyLength;
|
|
7
|
-
length;
|
|
8
|
-
constructor() {
|
|
9
|
-
this.current = '';
|
|
10
|
-
this.history = [];
|
|
11
|
-
this.historyLength = 0;
|
|
12
|
-
this.length = 0;
|
|
13
|
-
}
|
|
14
|
-
reset() {
|
|
15
|
-
this.current = '';
|
|
16
|
-
this.history = [];
|
|
17
|
-
this.length = 0;
|
|
18
|
-
}
|
|
19
|
-
resetHistory() {
|
|
20
|
-
this.history = [];
|
|
21
|
-
this.length = 0;
|
|
22
|
-
}
|
|
23
|
-
setCurrent(val) {
|
|
24
|
-
this.current = val;
|
|
25
|
-
this.length = this.current.length;
|
|
26
|
-
}
|
|
27
|
-
appendCurrent(val) {
|
|
28
|
-
this.current += val;
|
|
29
|
-
this.length = this.current.length;
|
|
30
|
-
}
|
|
31
|
-
resetCurrent() {
|
|
32
|
-
this.current = '';
|
|
33
|
-
}
|
|
34
|
-
getCurrent() {
|
|
35
|
-
return this.current;
|
|
36
|
-
}
|
|
37
|
-
pushHistory() {
|
|
38
|
-
this.history.push(this.current);
|
|
39
|
-
this.historyLength = this.history.length;
|
|
40
|
-
this.resetCurrent();
|
|
41
|
-
}
|
|
42
|
-
popHistory() {
|
|
43
|
-
const ret = this.history.pop() ?? '';
|
|
44
|
-
this.historyLength = this.history.length;
|
|
45
|
-
return ret;
|
|
46
|
-
}
|
|
47
|
-
getHistory(i) {
|
|
48
|
-
if (i === undefined) {
|
|
49
|
-
return this.history;
|
|
50
|
-
}
|
|
51
|
-
else {
|
|
52
|
-
return this.history[i];
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
getHistoryLast() {
|
|
56
|
-
return this.history[this.history.length - 1];
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
class Corrected {
|
|
60
|
-
current;
|
|
61
|
-
history;
|
|
62
|
-
constructor() {
|
|
63
|
-
this.current = '';
|
|
64
|
-
this.history = [];
|
|
65
|
-
}
|
|
66
|
-
setCurrent(val) {
|
|
67
|
-
this.current = val;
|
|
68
|
-
}
|
|
69
|
-
appendCurrent(val) {
|
|
70
|
-
this.current += val;
|
|
71
|
-
}
|
|
72
|
-
resetCurrent() {
|
|
73
|
-
this.current = '';
|
|
74
|
-
}
|
|
75
|
-
resetHistory() {
|
|
76
|
-
this.history = [];
|
|
77
|
-
}
|
|
78
|
-
reset() {
|
|
79
|
-
this.resetCurrent();
|
|
80
|
-
this.resetHistory();
|
|
81
|
-
}
|
|
82
|
-
getHistory(i) {
|
|
83
|
-
return this.history[i];
|
|
84
|
-
}
|
|
85
|
-
popHistory() {
|
|
86
|
-
return this.history.pop() ?? '';
|
|
87
|
-
}
|
|
88
|
-
pushHistory() {
|
|
89
|
-
this.history.push(this.current);
|
|
90
|
-
this.current = '';
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
export const input = new Input();
|
|
94
|
-
export const corrected = new Corrected();
|
|
95
|
-
export let keypressPerSecond = [];
|
|
96
|
-
export let currentKeypress = {
|
|
97
|
-
count: 0,
|
|
98
|
-
errors: 0,
|
|
99
|
-
words: [],
|
|
100
|
-
afk: true,
|
|
101
|
-
};
|
|
102
|
-
export let lastKeypress;
|
|
103
|
-
export let currentBurstStart = 0;
|
|
104
|
-
export let missedWords = {};
|
|
105
|
-
export let accuracy = {
|
|
106
|
-
correct: 0,
|
|
107
|
-
incorrect: 0,
|
|
108
|
-
};
|
|
109
|
-
export let keypressTimings = {
|
|
110
|
-
spacing: {
|
|
111
|
-
current: -1,
|
|
112
|
-
array: [],
|
|
113
|
-
},
|
|
114
|
-
duration: {
|
|
115
|
-
current: -1,
|
|
116
|
-
array: [],
|
|
117
|
-
},
|
|
118
|
-
};
|
|
119
|
-
export let wpmHistory = [];
|
|
120
|
-
export let rawHistory = [];
|
|
121
|
-
export let burstHistory = [];
|
|
122
|
-
export let bailout = false;
|
|
123
|
-
export function setBailout(tf) {
|
|
124
|
-
bailout = tf;
|
|
125
|
-
}
|
|
126
|
-
export let spacingDebug = false;
|
|
127
|
-
export function enableSpacingDebug() {
|
|
128
|
-
spacingDebug = true;
|
|
129
|
-
console.clear();
|
|
130
|
-
}
|
|
131
|
-
export function updateLastKeypress() {
|
|
132
|
-
lastKeypress = performance.now();
|
|
133
|
-
}
|
|
134
|
-
export function incrementKeypressCount() {
|
|
135
|
-
currentKeypress.count++;
|
|
136
|
-
}
|
|
137
|
-
export function setKeypressNotAfk() {
|
|
138
|
-
currentKeypress.afk = false;
|
|
139
|
-
}
|
|
140
|
-
export function incrementKeypressErrors() {
|
|
141
|
-
currentKeypress.errors++;
|
|
142
|
-
}
|
|
143
|
-
export function pushKeypressWord(wordIndex) {
|
|
144
|
-
currentKeypress.words.push(wordIndex);
|
|
145
|
-
}
|
|
146
|
-
export function setBurstStart(time) {
|
|
147
|
-
currentBurstStart = time;
|
|
148
|
-
}
|
|
149
|
-
export function pushKeypressesToHistory() {
|
|
150
|
-
keypressPerSecond.push(currentKeypress);
|
|
151
|
-
currentKeypress = {
|
|
152
|
-
count: 0,
|
|
153
|
-
errors: 0,
|
|
154
|
-
words: [],
|
|
155
|
-
afk: true,
|
|
156
|
-
};
|
|
157
|
-
}
|
|
158
|
-
export function incrementAccuracy(correctincorrect) {
|
|
159
|
-
if (correctincorrect) {
|
|
160
|
-
accuracy.correct++;
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
accuracy.incorrect++;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
export function setKeypressTimingsTooLong() {
|
|
167
|
-
keypressTimings.spacing.array = 'toolong';
|
|
168
|
-
keypressTimings.duration.array = 'toolong';
|
|
169
|
-
}
|
|
170
|
-
export function pushKeypressDuration(val) {
|
|
171
|
-
keypressTimings.duration.array.push(roundTo2(val));
|
|
172
|
-
}
|
|
173
|
-
export function setKeypressDuration(val) {
|
|
174
|
-
keypressTimings.duration.current = roundTo2(val);
|
|
175
|
-
}
|
|
176
|
-
function pushKeypressSpacing(val) {
|
|
177
|
-
keypressTimings.spacing.array.push(roundTo2(val));
|
|
178
|
-
}
|
|
179
|
-
function setKeypressSpacing(val) {
|
|
180
|
-
keypressTimings.spacing.current = roundTo2(val);
|
|
181
|
-
}
|
|
182
|
-
export function recordKeypressSpacing() {
|
|
183
|
-
const now = performance.now();
|
|
184
|
-
const diff = Math.abs(keypressTimings.spacing.current - now);
|
|
185
|
-
if (keypressTimings.spacing.current !== -1) {
|
|
186
|
-
pushKeypressSpacing(diff);
|
|
187
|
-
if (spacingDebug) {
|
|
188
|
-
console.log('spacing debug', 'push', diff, 'length', keypressTimings.spacing.array.length);
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
setKeypressSpacing(now);
|
|
192
|
-
if (spacingDebug) {
|
|
193
|
-
console.log('spacing debug', 'set', now, 'length', keypressTimings.spacing.array.length);
|
|
194
|
-
}
|
|
195
|
-
if (spacingDebug) {
|
|
196
|
-
console.log('spacing debug', 'recorded', 'length', keypressTimings.spacing.array.length);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
export function resetKeypressTimings() {
|
|
200
|
-
keypressTimings = {
|
|
201
|
-
spacing: {
|
|
202
|
-
current: performance.now(),
|
|
203
|
-
array: [],
|
|
204
|
-
},
|
|
205
|
-
duration: {
|
|
206
|
-
current: performance.now(),
|
|
207
|
-
array: [],
|
|
208
|
-
},
|
|
209
|
-
};
|
|
210
|
-
if (spacingDebug)
|
|
211
|
-
console.clear();
|
|
212
|
-
}
|
|
213
|
-
export function pushMissedWord(word) {
|
|
214
|
-
if (!Object.keys(missedWords).includes(word)) {
|
|
215
|
-
missedWords[word] = 1;
|
|
216
|
-
}
|
|
217
|
-
else {
|
|
218
|
-
missedWords[word]++;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
export function pushToWpmHistory(wpm) {
|
|
222
|
-
wpmHistory.push(wpm);
|
|
223
|
-
}
|
|
224
|
-
export function pushToRawHistory(raw) {
|
|
225
|
-
rawHistory.push(raw);
|
|
226
|
-
}
|
|
227
|
-
export function pushBurstToHistory(speed) {
|
|
228
|
-
if (burstHistory[TestWords.words.currentIndex] === undefined) {
|
|
229
|
-
burstHistory.push(speed);
|
|
230
|
-
}
|
|
231
|
-
else {
|
|
232
|
-
//repeated word - override
|
|
233
|
-
burstHistory[TestWords.words.currentIndex] = speed;
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
export function restart() {
|
|
237
|
-
wpmHistory = [];
|
|
238
|
-
rawHistory = [];
|
|
239
|
-
burstHistory = [];
|
|
240
|
-
keypressPerSecond = [];
|
|
241
|
-
currentKeypress = {
|
|
242
|
-
count: 0,
|
|
243
|
-
errors: 0,
|
|
244
|
-
words: [],
|
|
245
|
-
afk: true,
|
|
246
|
-
};
|
|
247
|
-
currentBurstStart = 0;
|
|
248
|
-
missedWords = {};
|
|
249
|
-
accuracy = {
|
|
250
|
-
correct: 0,
|
|
251
|
-
incorrect: 0,
|
|
252
|
-
};
|
|
253
|
-
keypressTimings = {
|
|
254
|
-
spacing: {
|
|
255
|
-
current: -1,
|
|
256
|
-
array: [],
|
|
257
|
-
},
|
|
258
|
-
duration: {
|
|
259
|
-
current: -1,
|
|
260
|
-
array: [],
|
|
261
|
-
},
|
|
262
|
-
};
|
|
263
|
-
}
|
|
264
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC1pbnB1dC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3Rnby10eXBpbmctdGVzdC9zcmMvbGliL2hlbHBlcnMvdGVzdC90ZXN0LWlucHV0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxTQUFTLE1BQU0sY0FBYyxDQUFDO0FBQzFDLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQW9CNUMsTUFBTSxLQUFLO0lBQ1QsT0FBTyxDQUFTO0lBQ2hCLE9BQU8sQ0FBVztJQUNsQixhQUFhLENBQVM7SUFDdEIsTUFBTSxDQUFTO0lBQ2Y7UUFDRSxJQUFJLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNsQixJQUFJLENBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztRQUNsQixJQUFJLENBQUMsYUFBYSxHQUFHLENBQUMsQ0FBQztRQUN2QixJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQztJQUNsQixDQUFDO0lBRUQsS0FBSztRQUNILElBQUksQ0FBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2xCLElBQUksQ0FBQyxPQUFPLEdBQUcsRUFBRSxDQUFDO1FBQ2xCLElBQUksQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDO0lBQ2xCLENBQUM7SUFFRCxZQUFZO1FBQ1YsSUFBSSxDQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7UUFDbEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7SUFDbEIsQ0FBQztJQUVELFVBQVUsQ0FBQyxHQUFXO1FBQ3BCLElBQUksQ0FBQyxPQUFPLEdBQUcsR0FBRyxDQUFDO1FBQ25CLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUM7SUFDcEMsQ0FBQztJQUVELGFBQWEsQ0FBQyxHQUFXO1FBQ3ZCLElBQUksQ0FBQyxPQUFPLElBQUksR0FBRyxDQUFDO1FBQ3BCLElBQUksQ0FB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MEJBQTBCO1FBQzFCLFlBQVksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxHQUFHLEtBQUssQ0FBQztJQUNyRCxDQUFDO0FBQ0gsQ0FBQztBQUVELE1BQU0sVUFBVSxPQUFPO0lBQ3JCLFVBQVUsR0FBRyxFQUFFLENBQUM7SUFDaEIsVUFBVSxHQUFHLEVBQUUsQ0FBQztJQUNoQixZQUFZLEdBQUcsRUFBRSxDQUFDO0lBQ2xCLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztJQUN2QixlQUFlLEdBQUc7UUFDaEIsS0FBSyxFQUFFLENBQUM7UUFDUixNQUFNLEVBQUUsQ0FBQztRQUNULEtBQUssRUFBRSxFQUFFO1FBQ1QsR0FBRyxFQUFFLElBQUk7S0FDVixDQUFDO0lBQ0YsaUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0lBQ3RCLFdBQVcsR0FBRyxFQUFFLENBQUM7SUFDakIsUUFBUSxHQUFHO1FBQ1QsT0FBTyxFQUFFLENBQUM7UUFDVixTQUFTLEVBQUUsQ0FBQztLQUNiLENBQUM7SUFDRixlQUFlLEdBQUc7UUFDaEIsT0FBTyxFQUFFO1lBQ1AsT0FBTyxFQUFFLENBQUMsQ0FBQztZQUNYLEtBQUssRUFBRSxFQUFFO1NBQ1Y7UUFDRCxRQUFRLEVBQUU7WUFDUixPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQ1gsS0FBSyxFQUFFLEVBQUU7U0FDVjtLQUNGLENBQUM7QUFDSixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgVGVzdFdvcmRzIGZyb20gJy4vdGVzdC13b3Jkcyc7XG5pbXBvcnQgeyByb3VuZFRvMiB9IGZyb20gJy4uLy4uL3V0aWxzL21pc2MnO1xuXG5pbnRlcmZhY2UgS2V5cHJlc3Mge1xuICBjb3VudDogbnVtYmVyO1xuICBlcnJvcnM6IG51bWJlcjtcbiAgd29yZHM6IG51bWJlcltdO1xuICBhZms6IGJvb2xlYW47XG59XG5cbmludGVyZmFjZSBLZXlwcmVzc1RpbWluZ3Mge1xuICBzcGFjaW5nOiB7XG4gICAgY3VycmVudDogbnVtYmVyO1xuICAgIGFycmF5OiBudW1iZXJbXSB8ICd0b29sb25nJztcbiAgfTtcbiAgZHVyYXRpb246IHtcbiAgICBjdXJyZW50OiBudW1iZXI7XG4gICAgYXJyYXk6IG51bWJlcltdIHwgJ3Rvb2xvbmcnO1xuICB9O1xufVxuXG5jbGFzcyBJbnB1dCB7XG4gIGN1cnJlbnQ6IHN0cmluZztcbiAgaGlzdG9yeTogc3RyaW5nW107XG4gIGhpc3RvcnlMZW5ndGg6IG51bWJlcjtcbiAgbGVuZ3RoOiBudW1iZXI7XG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuY3VycmVudCA9ICcnO1xuICAgIHRoaXMuaGlzdG9yeSA9IFtdO1xuICAgIHRoaXMuaGlzdG9yeUxlbmd0aCA9IDA7XG4gICAgdGhpcy5sZW5ndGggPSAwO1xuICB9XG5cbiAgcmVzZXQoKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50ID0gJyc7XG4gICAgdGhpcy5oaXN0b3J5ID0gW107XG4gICAgdGhpcy5sZW5ndGggPSAwO1xuICB9XG5cbiAgcmVzZXRIaXN0b3J5KCk6IHZvaWQge1xuICAgIHRoaXMuaGlzdG9yeSA9IFtdO1xuICAgIHRoaXMubGVuZ3RoID0gMDtcbiAgfVxuXG4gIHNldEN1cnJlbnQodmFsOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnQgPSB2YWw7XG4gICAgdGhpcy5sZW5ndGggPSB0aGlzLmN1cnJlbnQubGVuZ3RoO1xuICB9XG5cbiAgYXBwZW5kQ3VycmVudCh2YWw6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudCArPSB2YWw7XG4gICAgdGhpcy5sZW5ndGggPSB0aGlzLmN1cnJlbnQubGVuZ3RoO1xuICB9XG5cbiAgcmVzZXRDdXJyZW50KCk6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudCA9ICcnO1xuICB9XG5cbiAgZ2V0Q3VycmVudCgpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmN1cnJlbnQ7XG4gIH1cblxuICBwdXNoSGlzdG9yeSgpOiB2b2lkIHtcbiAgICB0aGlzLmhpc3RvcnkucHVzaCh0aGlzLmN1cnJlbnQpO1xuICAgIHRoaXMuaGlzdG9yeUxlbmd0aCA9IHRoaXMuaGlzdG9yeS5sZW5ndGg7XG4gICAgdGhpcy5yZXNldEN1cnJlbnQoKTtcbiAgfVxuXG4gIHBvcEhpc3RvcnkoKTogc3RyaW5nIHtcbiAgICBjb25zdCByZXQgPSB0aGlzLmhpc3RvcnkucG9wKCkgPz8gJyc7XG4gICAgdGhpcy5oaXN0b3J5TGVuZ3RoID0gdGhpcy5oaXN0b3J5Lmxlbmd0aDtcbiAgICByZXR1cm4gcmV0O1xuICB9XG5cbiAgZ2V0SGlzdG9yeShpPzogbnVtYmVyKTogc3RyaW5nIHwgc3RyaW5nW10ge1xuICAgIGlmIChpID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiB0aGlzLmhpc3Rvcnk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiB0aGlzLmhpc3RvcnlbaV07XG4gICAgfVxuICB9XG5cbiAgZ2V0SGlzdG9yeUxhc3QoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5oaXN0b3J5W3RoaXMuaGlzdG9yeS5sZW5ndGggLSAxXTtcbiAgfVxufVxuXG5jbGFzcyBDb3JyZWN0ZWQge1xuICBjdXJyZW50OiBzdHJpbmc7XG4gIGhpc3Rvcnk6IHN0cmluZ1tdO1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmN1cnJlbnQgPSAnJztcbiAgICB0aGlzLmhpc3RvcnkgPSBbXTtcbiAgfVxuICBzZXRDdXJyZW50KHZhbDogc3RyaW5nKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50ID0gdmFsO1xuICB9XG5cbiAgYXBwZW5kQ3VycmVudCh2YWw6IHN0cmluZyk6IHZvaWQge1xuICAgIHRoaXMuY3VycmVudCArPSB2YWw7XG4gIH1cblxuICByZXNldEN1cnJlbnQoKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50ID0gJyc7XG4gIH1cblxuICByZXNldEhpc3RvcnkoKTogdm9pZCB7XG4gICAgdGhpcy5oaXN0b3J5ID0gW107XG4gIH1cblxuICByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLnJlc2V0Q3VycmVudCgpO1xuICAgIHRoaXMucmVzZXRIaXN0b3J5KCk7XG4gIH1cblxuICBnZXRIaXN0b3J5KGk6IG51bWJlcik6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuaGlzdG9yeVtpXTtcbiAgfVxuXG4gIHBvcEhpc3RvcnkoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5oaXN0b3J5LnBvcCgpID8/ICcnO1xuICB9XG5cbiAgcHVzaEhpc3RvcnkoKTogdm9pZCB7XG4gICAgdGhpcy5oaXN0b3J5LnB1c2godGhpcy5jdXJyZW50KTtcbiAgICB0aGlzLmN1cnJlbnQgPSAnJztcbiAgfVxufVxuXG5leHBvcnQgY29uc3QgaW5wdXQgPSBuZXcgSW5wdXQoKTtcbmV4cG9ydCBjb25zdCBjb3JyZWN0ZWQgPSBuZXcgQ29ycmVjdGVkKCk7XG5cbmV4cG9ydCBsZXQga2V5cHJlc3NQZXJTZWNvbmQ6IEtleXByZXNzW10gPSBbXTtcbmV4cG9ydCBsZXQgY3VycmVudEtleXByZXNzOiBLZXlwcmVzcyA9IHtcbiAgY291bnQ6IDAsXG4gIGVycm9yczogMCxcbiAgd29yZHM6IFtdLFxuICBhZms6IHRydWUsXG59O1xuZXhwb3J0IGxldCBsYXN0S2V5cHJlc3M6IG51bWJlcjtcbmV4cG9ydCBsZXQgY3VycmVudEJ1cnN0U3RhcnQgPSAwO1xuZXhwb3J0IGxldCBtaXNzZWRXb3Jkczoge1xuICBbd29yZDogc3RyaW5nXTogbnVtYmVyO1xufSA9IHt9O1xuZXhwb3J0IGxldCBhY2N1cmFjeSA9IHtcbiAgY29ycmVjdDogMCxcbiAgaW5jb3JyZWN0OiAwLFxufTtcbmV4cG9ydCBsZXQga2V5cHJlc3NUaW1pbmdzOiBLZXlwcmVzc1RpbWluZ3MgPSB7XG4gIHNwYWNpbmc6IHtcbiAgICBjdXJyZW50OiAtMSxcbiAgICBhcnJheTogW10sXG4gIH0sXG4gIGR1cmF0aW9uOiB7XG4gICAgY3VycmVudDogLTEsXG4gICAgYXJyYXk6IFtdLFxuICB9LFxufTtcbmV4cG9ydCBsZXQgd3BtSGlzdG9yeTogbnVtYmVyW10gPSBbXTtcbmV4cG9ydCBsZXQgcmF3SGlzdG9yeTogbnVtYmVyW10gPSBbXTtcbmV4cG9ydCBsZXQgYnVyc3RIaXN0b3J5OiBudW1iZXJbXSA9IFtdO1xuZXhwb3J0IGxldCBiYWlsb3V0ID0gZmFsc2U7XG5leHBvcnQgZnVuY3Rpb24gc2V0QmFpbG91dCh0ZjogYm9vbGVhbik6IHZvaWQge1xuICBiYWlsb3V0ID0gdGY7XG59XG5cbmV4cG9ydCBsZXQgc3BhY2luZ0RlYnVnID0gZmFsc2U7XG5leHBvcnQgZnVuY3Rpb24gZW5hYmxlU3BhY2luZ0RlYnVnKCk6IHZvaWQge1xuICBzcGFjaW5nRGVidWcgPSB0cnVlO1xuICBjb25zb2xlLmNsZWFyKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVMYXN0S2V5cHJlc3MoKTogdm9pZCB7XG4gIGxhc3RLZXlwcmVzcyA9IHBlcmZvcm1hbmNlLm5vdygpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaW5jcmVtZW50S2V5cHJlc3NDb3VudCgpOiB2b2lkIHtcbiAgY3VycmVudEtleXByZXNzLmNvdW50Kys7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRLZXlwcmVzc05vdEFmaygpOiB2b2lkIHtcbiAgY3VycmVudEtleXByZXNzLmFmayA9IGZhbHNlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaW5jcmVtZW50S2V5cHJlc3NFcnJvcnMoKTogdm9pZCB7XG4gIGN1cnJlbnRLZXlwcmVzcy5lcnJvcnMrKztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHB1c2hLZXlwcmVzc1dvcmQod29yZEluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgY3VycmVudEtleXByZXNzLndvcmRzLnB1c2god29yZEluZGV4KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldEJ1cnN0U3RhcnQodGltZTogbnVtYmVyKTogdm9pZCB7XG4gIGN1cnJlbnRCdXJzdFN0YXJ0ID0gdGltZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHB1c2hLZXlwcmVzc2VzVG9IaXN0b3J5KCk6IHZvaWQge1xuICBrZXlwcmVzc1BlclNlY29uZC5wdXNoKGN1cnJlbnRLZXlwcmVzcyk7XG4gIGN1cnJlbnRLZXlwcmVzcyA9IHtcbiAgICBjb3VudDogMCxcbiAgICBlcnJvcnM6IDAsXG4gICAgd29yZHM6IFtdLFxuICAgIGFmazogdHJ1ZSxcbiAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGluY3JlbWVudEFjY3VyYWN5KGNvcnJlY3RpbmNvcnJlY3Q6IGJvb2xlYW4pOiB2b2lkIHtcbiAgaWYgKGNvcnJlY3RpbmNvcnJlY3QpIHtcbiAgICBhY2N1cmFjeS5jb3JyZWN0Kys7XG4gIH0gZWxzZSB7XG4gICAgYWNjdXJhY3kuaW5jb3JyZWN0Kys7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldEtleXByZXNzVGltaW5nc1Rvb0xvbmcoKTogdm9pZCB7XG4gIGtleXByZXNzVGltaW5ncy5zcGFjaW5nLmFycmF5ID0gJ3Rvb2xvbmcnO1xuICBrZXlwcmVzc1RpbWluZ3MuZHVyYXRpb24uYXJyYXkgPSAndG9vbG9uZyc7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwdXNoS2V5cHJlc3NEdXJhdGlvbih2YWw6IG51bWJlcik6IHZvaWQge1xuICAoa2V5cHJlc3NUaW1pbmdzLmR1cmF0aW9uLmFycmF5IGFzIG51bWJlcltdKS5wdXNoKHJvdW5kVG8yKHZhbCkpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0S2V5cHJlc3NEdXJhdGlvbih2YWw6IG51bWJlcik6IHZvaWQge1xuICBrZXlwcmVzc1RpbWluZ3MuZHVyYXRpb24uY3VycmVudCA9IHJvdW5kVG8yKHZhbCk7XG59XG5cbmZ1bmN0aW9uIHB1c2hLZXlwcmVzc1NwYWNpbmcodmFsOiBudW1iZXIpOiB2b2lkIHtcbiAgKGtleXByZXNzVGltaW5ncy5zcGFjaW5nLmFycmF5IGFzIG51bWJlcltdKS5wdXNoKHJvdW5kVG8yKHZhbCkpO1xufVxuXG5mdW5jdGlvbiBzZXRLZXlwcmVzc1NwYWNpbmcodmFsOiBudW1iZXIpOiB2b2lkIHtcbiAga2V5cHJlc3NUaW1pbmdzLnNwYWNpbmcuY3VycmVudCA9IHJvdW5kVG8yKHZhbCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZWNvcmRLZXlwcmVzc1NwYWNpbmcoKTogdm9pZCB7XG4gIGNvbnN0IG5vdyA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICBjb25zdCBkaWZmID0gTWF0aC5hYnMoa2V5cHJlc3NUaW1pbmdzLnNwYWNpbmcuY3VycmVudCAtIG5vdyk7XG4gIGlmIChrZXlwcmVzc1RpbWluZ3Muc3BhY2luZy5jdXJyZW50ICE9PSAtMSkge1xuICAgIHB1c2hLZXlwcmVzc1NwYWNpbmcoZGlmZik7XG4gICAgaWYgKHNwYWNpbmdEZWJ1Zykge1xuICAgICAgY29uc29sZS5sb2coJ3NwYWNpbmcgZGVidWcnLCAncHVzaCcsIGRpZmYsICdsZW5ndGgnLCBrZXlwcmVzc1RpbWluZ3Muc3BhY2luZy5hcnJheS5sZW5ndGgpO1xuICAgIH1cbiAgfVxuICBzZXRLZXlwcmVzc1NwYWNpbmcobm93KTtcbiAgaWYgKHNwYWNpbmdEZWJ1Zykge1xuICAgIGNvbnNvbGUubG9nKCdzcGFjaW5nIGRlYnVnJywgJ3NldCcsIG5vdywgJ2xlbmd0aCcsIGtleXByZXNzVGltaW5ncy5zcGFjaW5nLmFycmF5Lmxlbmd0aCk7XG4gIH1cbiAgaWYgKHNwYWNpbmdEZWJ1Zykge1xuICAgIGNvbnNvbGUubG9nKCdzcGFjaW5nIGRlYnVnJywgJ3JlY29yZGVkJywgJ2xlbmd0aCcsIGtleXByZXNzVGltaW5ncy5zcGFjaW5nLmFycmF5Lmxlbmd0aCk7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlc2V0S2V5cHJlc3NUaW1pbmdzKCk6IHZvaWQge1xuICBrZXlwcmVzc1RpbWluZ3MgPSB7XG4gICAgc3BhY2luZzoge1xuICAgICAgY3VycmVudDogcGVyZm9ybWFuY2Uubm93KCksXG4gICAgICBhcnJheTogW10sXG4gICAgfSxcbiAgICBkdXJhdGlvbjoge1xuICAgICAgY3VycmVudDogcGVyZm9ybWFuY2Uubm93KCksXG4gICAgICBhcnJheTogW10sXG4gICAgfSxcbiAgfTtcbiAgaWYgKHNwYWNpbmdEZWJ1ZykgY29uc29sZS5jbGVhcigpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHVzaE1pc3NlZFdvcmQod29yZDogc3RyaW5nKTogdm9pZCB7XG4gIGlmICghT2JqZWN0LmtleXMobWlzc2VkV29yZHMpLmluY2x1ZGVzKHdvcmQpKSB7XG4gICAgbWlzc2VkV29yZHNbd29yZF0gPSAxO1xuICB9IGVsc2Uge1xuICAgIG1pc3NlZFdvcmRzW3dvcmRdKys7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHB1c2hUb1dwbUhpc3Rvcnkod3BtOiBudW1iZXIpOiB2b2lkIHtcbiAgd3BtSGlzdG9yeS5wdXNoKHdwbSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBwdXNoVG9SYXdIaXN0b3J5KHJhdzogbnVtYmVyKTogdm9pZCB7XG4gIHJhd0hpc3RvcnkucHVzaChyYXcpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcHVzaEJ1cnN0VG9IaXN0b3J5KHNwZWVkOiBudW1iZXIpOiB2b2lkIHtcbiAgaWYgKGJ1cnN0SGlzdG9yeVtUZXN0V29yZHMud29yZHMuY3VycmVudEluZGV4XSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgYnVyc3RIaXN0b3J5LnB1c2goc3BlZWQpO1xuICB9IGVsc2Uge1xuICAgIC8vcmVwZWF0ZWQgd29yZCAtIG92ZXJyaWRlXG4gICAgYnVyc3RIaXN0b3J5W1Rlc3RXb3Jkcy53b3Jkcy5jdXJyZW50SW5kZXhdID0gc3BlZWQ7XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlc3RhcnQoKTogdm9pZCB7XG4gIHdwbUhpc3RvcnkgPSBbXTtcbiAgcmF3SGlzdG9yeSA9IFtdO1xuICBidXJzdEhpc3RvcnkgPSBbXTtcbiAga2V5cHJlc3NQZXJTZWNvbmQgPSBbXTtcbiAgY3VycmVudEtleXByZXNzID0ge1xuICAgIGNvdW50OiAwLFxuICAgIGVycm9yczogMCxcbiAgICB3b3JkczogW10sXG4gICAgYWZrOiB0cnVlLFxuICB9O1xuICBjdXJyZW50QnVyc3RTdGFydCA9IDA7XG4gIG1pc3NlZFdvcmRzID0ge307XG4gIGFjY3VyYWN5ID0ge1xuICAgIGNvcnJlY3Q6IDAsXG4gICAgaW5jb3JyZWN0OiAwLFxuICB9O1xuICBrZXlwcmVzc1RpbWluZ3MgPSB7XG4gICAgc3BhY2luZzoge1xuICAgICAgY3VycmVudDogLTEsXG4gICAgICBhcnJheTogW10sXG4gICAgfSxcbiAgICBkdXJhdGlvbjoge1xuICAgICAgY3VycmVudDogLTEsXG4gICAgICBhcnJheTogW10sXG4gICAgfSxcbiAgfTtcbn1cbiJdfQ==
|