@testgorilla/tgo-typing-test 0.0.1 → 1.0.0

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.
Files changed (134) hide show
  1. package/esm2022/index.mjs +3 -0
  2. package/esm2022/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.mjs +45 -0
  3. package/esm2022/lib/components/tgo-typing-test/tgo-typing-test.component.mjs +299 -0
  4. package/esm2022/lib/helpers/config.mjs +24 -0
  5. package/esm2022/lib/helpers/constants/default-config.mjs +103 -0
  6. package/esm2022/lib/helpers/controllers/input-controller.mjs +586 -0
  7. package/esm2022/lib/helpers/controllers/quotes-controller.mjs +118 -0
  8. package/esm2022/lib/helpers/observables/config-event.mjs +16 -0
  9. package/esm2022/lib/helpers/observables/timer-event.mjs +16 -0
  10. package/esm2022/lib/helpers/states/active-page.mjs +8 -0
  11. package/esm2022/lib/helpers/states/composition.mjs +20 -0
  12. package/esm2022/lib/helpers/states/page-transition.mjs +8 -0
  13. package/esm2022/lib/helpers/states/slow-timer.mjs +15 -0
  14. package/esm2022/lib/helpers/states/test-active.mjs +8 -0
  15. package/esm2022/lib/helpers/states/time.mjs +11 -0
  16. package/esm2022/lib/helpers/test/caps-warning.mjs +50 -0
  17. package/esm2022/lib/helpers/test/caret.mjs +80 -0
  18. package/esm2022/lib/helpers/test/custom-text.mjs +59 -0
  19. package/esm2022/lib/helpers/test/english-punctuation.mjs +29 -0
  20. package/esm2022/lib/helpers/test/focus.mjs +35 -0
  21. package/esm2022/lib/helpers/test/manual-restart-tracker.mjs +11 -0
  22. package/esm2022/lib/helpers/test/out-of-focus.mjs +14 -0
  23. package/esm2022/lib/helpers/test/replay.mjs +217 -0
  24. package/esm2022/lib/helpers/test/test-input.mjs +264 -0
  25. package/esm2022/lib/helpers/test/test-logic.mjs +927 -0
  26. package/esm2022/lib/helpers/test/test-state.mjs +13 -0
  27. package/esm2022/lib/helpers/test/test-stats.mjs +342 -0
  28. package/esm2022/lib/helpers/test/test-timer.mjs +207 -0
  29. package/esm2022/lib/helpers/test/test-ui.mjs +341 -0
  30. package/esm2022/lib/helpers/test/test-words.mjs +69 -0
  31. package/esm2022/lib/helpers/test/timer-progress.mjs +15 -0
  32. package/esm2022/lib/helpers/test/weak-spot.mjs +65 -0
  33. package/esm2022/lib/helpers/test/wordset.mjs +100 -0
  34. package/esm2022/lib/utils/misc.mjs +673 -0
  35. package/esm2022/testgorilla-tgo-typing-test.mjs +5 -0
  36. package/fesm2022/testgorilla-tgo-typing-test.mjs +4707 -0
  37. package/fesm2022/testgorilla-tgo-typing-test.mjs.map +1 -0
  38. package/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.d.ts +14 -0
  39. package/lib/components/tgo-typing-test/tgo-typing-test.component.d.ts +54 -0
  40. package/lib/helpers/config.d.ts +98 -0
  41. package/lib/helpers/constants/default-config.d.ts +3 -0
  42. package/lib/helpers/controllers/input-controller.d.ts +16 -0
  43. package/lib/helpers/controllers/quotes-controller.d.ts +20 -0
  44. package/lib/helpers/observables/config-event.d.ts +5 -0
  45. package/lib/helpers/observables/timer-event.d.ts +4 -0
  46. package/lib/helpers/states/active-page.d.ts +2 -0
  47. package/lib/helpers/states/composition.d.ts +10 -0
  48. package/lib/helpers/states/page-transition.d.ts +2 -0
  49. package/lib/helpers/states/slow-timer.d.ts +3 -0
  50. package/lib/helpers/states/test-active.d.ts +2 -0
  51. package/lib/helpers/states/time.d.ts +3 -0
  52. package/lib/helpers/test/caps-warning.d.ts +5 -0
  53. package/lib/helpers/test/caret.d.ts +11 -0
  54. package/lib/helpers/test/custom-text.d.ts +16 -0
  55. package/lib/helpers/test/english-punctuation.d.ts +3 -0
  56. package/lib/helpers/test/focus.d.ts +7 -0
  57. package/lib/helpers/test/manual-restart-tracker.d.ts +3 -0
  58. package/lib/helpers/test/out-of-focus.d.ts +4 -0
  59. package/lib/helpers/test/replay.d.ts +20 -0
  60. package/lib/helpers/test/test-input.d.ts +86 -0
  61. package/lib/helpers/test/test-logic.d.ts +25 -0
  62. package/lib/helpers/test/test-state.d.ts +7 -0
  63. package/lib/helpers/test/test-stats.d.ts +92 -0
  64. package/lib/helpers/test/test-timer.d.ts +6 -0
  65. package/lib/helpers/test/test-ui.d.ts +27 -0
  66. package/lib/helpers/test/test-words.d.ts +23 -0
  67. package/lib/helpers/test/timer-progress.d.ts +3 -0
  68. package/lib/helpers/test/weak-spot.d.ts +3 -0
  69. package/lib/helpers/test/wordset.d.ts +7 -0
  70. package/lib/utils/misc.d.ts +81 -0
  71. package/package.json +18 -7
  72. package/.eslintrc.json +0 -45
  73. package/jest.config.ts +0 -21
  74. package/ng-package.json +0 -15
  75. package/project.json +0 -36
  76. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.html +0 -30
  77. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.spec.ts +0 -250
  78. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.ts +0 -48
  79. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.html +0 -72
  80. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.spec.ts +0 -699
  81. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.ts +0 -294
  82. package/src/lib/helpers/config.ts +0 -28
  83. package/src/lib/helpers/constants/default-config.ts +0 -103
  84. package/src/lib/helpers/controllers/input-controller.ts +0 -710
  85. package/src/lib/helpers/controllers/quotes-controller.ts +0 -183
  86. package/src/lib/helpers/observables/banner-event.ts +0 -18
  87. package/src/lib/helpers/observables/config-event.ts +0 -31
  88. package/src/lib/helpers/observables/timer-event.ts +0 -18
  89. package/src/lib/helpers/states/active-page.ts +0 -9
  90. package/src/lib/helpers/states/composition.ts +0 -29
  91. package/src/lib/helpers/states/page-transition.ts +0 -9
  92. package/src/lib/helpers/states/slow-timer.ts +0 -16
  93. package/src/lib/helpers/states/test-active.ts +0 -9
  94. package/src/lib/helpers/states/time.ts +0 -13
  95. package/src/lib/helpers/test/caps-warning.ts +0 -50
  96. package/src/lib/helpers/test/caret.ts +0 -92
  97. package/src/lib/helpers/test/custom-text.ts +0 -73
  98. package/src/lib/helpers/test/english-punctuation.ts +0 -38
  99. package/src/lib/helpers/test/focus.ts +0 -39
  100. package/src/lib/helpers/test/manual-restart-tracker.ts +0 -13
  101. package/src/lib/helpers/test/out-of-focus.ts +0 -19
  102. package/src/lib/helpers/test/replay.ts +0 -265
  103. package/src/lib/helpers/test/test-input.ts +0 -320
  104. package/src/lib/helpers/test/test-logic.ts +0 -1039
  105. package/src/lib/helpers/test/test-state.ts +0 -17
  106. package/src/lib/helpers/test/test-stats.ts +0 -442
  107. package/src/lib/helpers/test/test-timer.ts +0 -209
  108. package/src/lib/helpers/test/test-ui.ts +0 -370
  109. package/src/lib/helpers/test/test-words.ts +0 -72
  110. package/src/lib/helpers/test/timer-progress.ts +0 -16
  111. package/src/lib/helpers/test/tts.ts +0 -42
  112. package/src/lib/helpers/test/weak-spot.ts +0 -74
  113. package/src/lib/helpers/test/wordset.ts +0 -109
  114. package/src/lib/styles/animations.scss +0 -101
  115. package/src/lib/styles/caret.scss +0 -108
  116. package/src/lib/styles/core.scss +0 -498
  117. package/src/lib/styles/index.scss +0 -19
  118. package/src/lib/styles/inputs.scss +0 -290
  119. package/src/lib/styles/popups.scss +0 -1311
  120. package/src/lib/styles/test.scss +0 -1008
  121. package/src/lib/styles/z_media-queries.scss +0 -848
  122. package/src/lib/types/types.d.ts +0 -731
  123. package/src/lib/utils/misc.ts +0 -776
  124. package/src/test-setup.ts +0 -1
  125. package/tsconfig.json +0 -16
  126. package/tsconfig.lib.json +0 -14
  127. package/tsconfig.lib.prod.json +0 -9
  128. package/tsconfig.spec.json +0 -11
  129. /package/{src/assets → assets}/typing-test-languages/english.json +0 -0
  130. /package/{src/assets → assets}/typing-test-languages/english_punctuation.json +0 -0
  131. /package/{src/assets → assets}/typing-test-languages/quotes/english_version_1.json +0 -0
  132. /package/{src/assets → assets}/typing-test-languages/quotes/english_version_2.json +0 -0
  133. /package/{src/assets → assets}/typing-test-languages/quotes/filtered_sources.json +0 -0
  134. /package/{src/index.ts → index.d.ts} +0 -0
@@ -0,0 +1,217 @@
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
@@ -0,0 +1,264 @@
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==