@testgorilla/tgo-typing-test 1.0.0 → 2.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/.eslintrc.json +46 -0
  2. package/jest.config.ts +21 -0
  3. package/ng-package.json +15 -0
  4. package/package.json +7 -22
  5. package/project.json +36 -0
  6. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.html +30 -0
  7. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.spec.ts +250 -0
  8. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.ts +47 -0
  9. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.html +72 -0
  10. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.spec.ts +699 -0
  11. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.ts +287 -0
  12. package/src/lib/helpers/config.ts +28 -0
  13. package/src/lib/helpers/constants/default-config.ts +103 -0
  14. package/src/lib/helpers/controllers/input-controller.ts +710 -0
  15. package/src/lib/helpers/controllers/quotes-controller.ts +183 -0
  16. package/src/lib/helpers/observables/banner-event.ts +18 -0
  17. package/src/lib/helpers/observables/config-event.ts +31 -0
  18. package/src/lib/helpers/observables/timer-event.ts +18 -0
  19. package/src/lib/helpers/states/active-page.ts +9 -0
  20. package/src/lib/helpers/states/composition.ts +29 -0
  21. package/src/lib/helpers/states/page-transition.ts +9 -0
  22. package/src/lib/helpers/states/slow-timer.ts +16 -0
  23. package/src/lib/helpers/states/test-active.ts +9 -0
  24. package/src/lib/helpers/states/time.ts +13 -0
  25. package/src/lib/helpers/test/caps-warning.ts +50 -0
  26. package/src/lib/helpers/test/caret.ts +92 -0
  27. package/src/lib/helpers/test/custom-text.ts +73 -0
  28. package/src/lib/helpers/test/english-punctuation.ts +38 -0
  29. package/src/lib/helpers/test/focus.ts +39 -0
  30. package/src/lib/helpers/test/manual-restart-tracker.ts +13 -0
  31. package/src/lib/helpers/test/out-of-focus.ts +19 -0
  32. package/src/lib/helpers/test/replay.ts +265 -0
  33. package/src/lib/helpers/test/test-input.ts +320 -0
  34. package/src/lib/helpers/test/test-logic.ts +1039 -0
  35. package/src/lib/helpers/test/test-state.ts +17 -0
  36. package/src/lib/helpers/test/test-stats.ts +442 -0
  37. package/src/lib/helpers/test/test-timer.ts +209 -0
  38. package/src/lib/helpers/test/test-ui.ts +370 -0
  39. package/src/lib/helpers/test/test-words.ts +72 -0
  40. package/src/lib/helpers/test/timer-progress.ts +16 -0
  41. package/src/lib/helpers/test/tts.ts +42 -0
  42. package/src/lib/helpers/test/weak-spot.ts +74 -0
  43. package/src/lib/helpers/test/wordset.ts +109 -0
  44. package/src/lib/styles/animations.scss +101 -0
  45. package/src/lib/styles/caret.scss +108 -0
  46. package/src/lib/styles/core.scss +498 -0
  47. package/src/lib/styles/index.scss +19 -0
  48. package/src/lib/styles/inputs.scss +290 -0
  49. package/src/lib/styles/popups.scss +1311 -0
  50. package/src/lib/styles/test.scss +1008 -0
  51. package/src/lib/styles/z_media-queries.scss +848 -0
  52. package/src/lib/types/types.d.ts +731 -0
  53. package/src/lib/utils/misc.ts +776 -0
  54. package/src/test-setup.ts +20 -0
  55. package/tsconfig.json +16 -0
  56. package/tsconfig.lib.json +14 -0
  57. package/tsconfig.lib.prod.json +9 -0
  58. package/tsconfig.spec.json +11 -0
  59. package/esm2022/index.mjs +0 -3
  60. package/esm2022/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.mjs +0 -45
  61. package/esm2022/lib/components/tgo-typing-test/tgo-typing-test.component.mjs +0 -299
  62. package/esm2022/lib/helpers/config.mjs +0 -24
  63. package/esm2022/lib/helpers/constants/default-config.mjs +0 -103
  64. package/esm2022/lib/helpers/controllers/input-controller.mjs +0 -586
  65. package/esm2022/lib/helpers/controllers/quotes-controller.mjs +0 -118
  66. package/esm2022/lib/helpers/observables/config-event.mjs +0 -16
  67. package/esm2022/lib/helpers/observables/timer-event.mjs +0 -16
  68. package/esm2022/lib/helpers/states/active-page.mjs +0 -8
  69. package/esm2022/lib/helpers/states/composition.mjs +0 -20
  70. package/esm2022/lib/helpers/states/page-transition.mjs +0 -8
  71. package/esm2022/lib/helpers/states/slow-timer.mjs +0 -15
  72. package/esm2022/lib/helpers/states/test-active.mjs +0 -8
  73. package/esm2022/lib/helpers/states/time.mjs +0 -11
  74. package/esm2022/lib/helpers/test/caps-warning.mjs +0 -50
  75. package/esm2022/lib/helpers/test/caret.mjs +0 -80
  76. package/esm2022/lib/helpers/test/custom-text.mjs +0 -59
  77. package/esm2022/lib/helpers/test/english-punctuation.mjs +0 -29
  78. package/esm2022/lib/helpers/test/focus.mjs +0 -35
  79. package/esm2022/lib/helpers/test/manual-restart-tracker.mjs +0 -11
  80. package/esm2022/lib/helpers/test/out-of-focus.mjs +0 -14
  81. package/esm2022/lib/helpers/test/replay.mjs +0 -217
  82. package/esm2022/lib/helpers/test/test-input.mjs +0 -264
  83. package/esm2022/lib/helpers/test/test-logic.mjs +0 -927
  84. package/esm2022/lib/helpers/test/test-state.mjs +0 -13
  85. package/esm2022/lib/helpers/test/test-stats.mjs +0 -342
  86. package/esm2022/lib/helpers/test/test-timer.mjs +0 -207
  87. package/esm2022/lib/helpers/test/test-ui.mjs +0 -341
  88. package/esm2022/lib/helpers/test/test-words.mjs +0 -69
  89. package/esm2022/lib/helpers/test/timer-progress.mjs +0 -15
  90. package/esm2022/lib/helpers/test/weak-spot.mjs +0 -65
  91. package/esm2022/lib/helpers/test/wordset.mjs +0 -100
  92. package/esm2022/lib/utils/misc.mjs +0 -673
  93. package/esm2022/testgorilla-tgo-typing-test.mjs +0 -5
  94. package/fesm2022/testgorilla-tgo-typing-test.mjs +0 -4707
  95. package/fesm2022/testgorilla-tgo-typing-test.mjs.map +0 -1
  96. package/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.d.ts +0 -14
  97. package/lib/components/tgo-typing-test/tgo-typing-test.component.d.ts +0 -54
  98. package/lib/helpers/config.d.ts +0 -98
  99. package/lib/helpers/constants/default-config.d.ts +0 -3
  100. package/lib/helpers/controllers/input-controller.d.ts +0 -16
  101. package/lib/helpers/controllers/quotes-controller.d.ts +0 -20
  102. package/lib/helpers/observables/config-event.d.ts +0 -5
  103. package/lib/helpers/observables/timer-event.d.ts +0 -4
  104. package/lib/helpers/states/active-page.d.ts +0 -2
  105. package/lib/helpers/states/composition.d.ts +0 -10
  106. package/lib/helpers/states/page-transition.d.ts +0 -2
  107. package/lib/helpers/states/slow-timer.d.ts +0 -3
  108. package/lib/helpers/states/test-active.d.ts +0 -2
  109. package/lib/helpers/states/time.d.ts +0 -3
  110. package/lib/helpers/test/caps-warning.d.ts +0 -5
  111. package/lib/helpers/test/caret.d.ts +0 -11
  112. package/lib/helpers/test/custom-text.d.ts +0 -16
  113. package/lib/helpers/test/english-punctuation.d.ts +0 -3
  114. package/lib/helpers/test/focus.d.ts +0 -7
  115. package/lib/helpers/test/manual-restart-tracker.d.ts +0 -3
  116. package/lib/helpers/test/out-of-focus.d.ts +0 -4
  117. package/lib/helpers/test/replay.d.ts +0 -20
  118. package/lib/helpers/test/test-input.d.ts +0 -86
  119. package/lib/helpers/test/test-logic.d.ts +0 -25
  120. package/lib/helpers/test/test-state.d.ts +0 -7
  121. package/lib/helpers/test/test-stats.d.ts +0 -92
  122. package/lib/helpers/test/test-timer.d.ts +0 -6
  123. package/lib/helpers/test/test-ui.d.ts +0 -27
  124. package/lib/helpers/test/test-words.d.ts +0 -23
  125. package/lib/helpers/test/timer-progress.d.ts +0 -3
  126. package/lib/helpers/test/weak-spot.d.ts +0 -3
  127. package/lib/helpers/test/wordset.d.ts +0 -7
  128. package/lib/utils/misc.d.ts +0 -81
  129. /package/{assets → src/assets}/typing-test-languages/english.json +0 -0
  130. /package/{assets → src/assets}/typing-test-languages/english_punctuation.json +0 -0
  131. /package/{assets → src/assets}/typing-test-languages/quotes/english_version_1.json +0 -0
  132. /package/{assets → src/assets}/typing-test-languages/quotes/english_version_2.json +0 -0
  133. /package/{assets → src/assets}/typing-test-languages/quotes/filtered_sources.json +0 -0
  134. /package/{index.d.ts → src/index.ts} +0 -0
@@ -1,13 +0,0 @@
1
- export let isRepeated = false;
2
- export let isPaceRepeat = false;
3
- export let activeChallenge = null;
4
- export function setRepeated(tf) {
5
- isRepeated = tf;
6
- }
7
- export function setPaceRepeat(tf) {
8
- isPaceRepeat = tf;
9
- }
10
- export function setActiveChallenge(val) {
11
- activeChallenge = val;
12
- }
13
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC1zdGF0ZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3Rnby10eXBpbmctdGVzdC9zcmMvbGliL2hlbHBlcnMvdGVzdC90ZXN0LXN0YXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUVBLE1BQU0sQ0FBQyxJQUFJLFVBQVUsR0FBRyxLQUFLLENBQUM7QUFDOUIsTUFBTSxDQUFDLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQztBQUNoQyxNQUFNLENBQUMsSUFBSSxlQUFlLEdBQWlDLElBQUksQ0FBQztBQUVoRSxNQUFNLFVBQVUsV0FBVyxDQUFDLEVBQVc7SUFDckMsVUFBVSxHQUFHLEVBQUUsQ0FBQztBQUNsQixDQUFDO0FBRUQsTUFBTSxVQUFVLGFBQWEsQ0FBQyxFQUFXO0lBQ3ZDLFlBQVksR0FBRyxFQUFFLENBQUM7QUFDcEIsQ0FBQztBQUVELE1BQU0sVUFBVSxrQkFBa0IsQ0FBQyxHQUFpQztJQUNsRSxlQUFlLEdBQUcsR0FBRyxDQUFDO0FBQ3hCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBNb25rZXlUeXBlcyB9IGZyb20gJy4uLy4uL3R5cGVzL3R5cGVzJztcblxuZXhwb3J0IGxldCBpc1JlcGVhdGVkID0gZmFsc2U7XG5leHBvcnQgbGV0IGlzUGFjZVJlcGVhdCA9IGZhbHNlO1xuZXhwb3J0IGxldCBhY3RpdmVDaGFsbGVuZ2U6IG51bGwgfCBNb25rZXlUeXBlcy5DaGFsbGVuZ2UgPSBudWxsO1xuXG5leHBvcnQgZnVuY3Rpb24gc2V0UmVwZWF0ZWQodGY6IGJvb2xlYW4pOiB2b2lkIHtcbiAgaXNSZXBlYXRlZCA9IHRmO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0UGFjZVJlcGVhdCh0ZjogYm9vbGVhbik6IHZvaWQge1xuICBpc1BhY2VSZXBlYXQgPSB0Zjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldEFjdGl2ZUNoYWxsZW5nZSh2YWw6IG51bGwgfCBNb25rZXlUeXBlcy5DaGFsbGVuZ2UpOiB2b2lkIHtcbiAgYWN0aXZlQ2hhbGxlbmdlID0gdmFsO1xufVxuIl19
@@ -1,342 +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
- export let invalid = false;
6
- export let start, end;
7
- export let start2, end2;
8
- export let lastSecondNotRound = false;
9
- export let lastTestWpm = 0;
10
- export function setLastTestWpm(wpm) {
11
- lastTestWpm = wpm;
12
- }
13
- export let lastResult;
14
- export function setLastResult(result) {
15
- lastResult = result;
16
- }
17
- let wpmCalcDebug = false;
18
- export function wpmCalculationDebug() {
19
- console.log('wpm calculation debug enabled');
20
- wpmCalcDebug = true;
21
- }
22
- export function getStats() {
23
- const ret = {
24
- lastResult,
25
- start,
26
- end,
27
- wpmHistory: TestInput.wpmHistory,
28
- rawHistory: TestInput.wpmHistory,
29
- burstHistory: TestInput.burstHistory,
30
- keypressPerSecond: TestInput.keypressPerSecond,
31
- currentKeypress: TestInput.currentKeypress,
32
- lastKeypress: TestInput.lastKeypress,
33
- currentBurstStart: TestInput.currentBurstStart,
34
- lastSecondNotRound,
35
- missedWords: TestInput.missedWords,
36
- accuracy: TestInput.accuracy,
37
- keypressTimings: TestInput.keypressTimings,
38
- };
39
- try {
40
- ret.keySpacingStats = {
41
- average: TestInput.keypressTimings.spacing.array.reduce((previous, current) => (current += previous)) / TestInput.keypressTimings.spacing.array.length,
42
- sd: Misc.stdDev(TestInput.keypressTimings.spacing.array),
43
- };
44
- }
45
- catch (e) {
46
- //
47
- }
48
- try {
49
- ret.keyDurationStats = {
50
- average: TestInput.keypressTimings.duration.array.reduce((previous, current) => (current += previous)) / TestInput.keypressTimings.duration.array.length,
51
- sd: Misc.stdDev(TestInput.keypressTimings.duration.array),
52
- };
53
- }
54
- catch (e) {
55
- //
56
- }
57
- return ret;
58
- }
59
- export function restart() {
60
- start = 0;
61
- end = 0;
62
- invalid = false;
63
- lastSecondNotRound = false;
64
- }
65
- export let restartCount = 0;
66
- export let incompleteSeconds = 0;
67
- export function incrementRestartCount() {
68
- restartCount++;
69
- }
70
- export function incrementIncompleteSeconds(val) {
71
- incompleteSeconds += val;
72
- }
73
- export function resetIncomplete() {
74
- restartCount = 0;
75
- incompleteSeconds = 0;
76
- }
77
- export function setInvalid() {
78
- invalid = true;
79
- }
80
- export function calculateTestSeconds(now) {
81
- if (now === undefined) {
82
- const endAfkSeconds = (end - TestInput.lastKeypress) / 1000;
83
- if ((Config.mode == 'zen' || TestInput.bailout) && endAfkSeconds < 7) {
84
- return (TestInput.lastKeypress - start) / 1000;
85
- }
86
- else {
87
- return (end - start) / 1000;
88
- }
89
- }
90
- else {
91
- return (now - start) / 1000;
92
- }
93
- }
94
- export function calculateWpmAndRaw() {
95
- let chars = 0;
96
- let correctWordChars = 0;
97
- let spaces = 0;
98
- //check input history
99
- for (let i = 0; i < TestInput.input.history.length; i++) {
100
- const word = Config.mode == 'zen' ? TestInput.input.getHistory(i) : TestWords.words.get(i);
101
- if (TestInput.input.getHistory(i) == word) {
102
- //the word is correct
103
- //+1 for space
104
- correctWordChars += word.length;
105
- if (i < TestInput.input.history.length - 1 &&
106
- Misc.getLastChar(TestInput.input.getHistory(i)) !== '\n') {
107
- spaces++;
108
- }
109
- }
110
- chars += TestInput.input.getHistory(i).length;
111
- }
112
- if (TestInput.input.current !== '') {
113
- const word = Config.mode == 'zen' ? TestInput.input.current : TestWords.words.getCurrent();
114
- //check whats currently typed
115
- const toAdd = {
116
- correct: 0,
117
- incorrect: 0,
118
- missed: 0,
119
- };
120
- for (let c = 0; c < word.length; c++) {
121
- if (c < TestInput.input.current.length) {
122
- //on char that still has a word list pair
123
- if (TestInput.input.current[c] == word[c]) {
124
- toAdd.correct++;
125
- }
126
- else {
127
- toAdd.incorrect++;
128
- }
129
- }
130
- else {
131
- //on char that is extra
132
- toAdd.missed++;
133
- }
134
- }
135
- chars += toAdd.correct;
136
- chars += toAdd.incorrect;
137
- chars += toAdd.missed;
138
- if (toAdd.incorrect == 0) {
139
- //word is correct so far, add chars
140
- correctWordChars += toAdd.correct;
141
- }
142
- }
143
- if (Config.funbox === 'nospace' || Config.funbox === 'arrows') {
144
- spaces = 0;
145
- }
146
- chars += TestInput.input.current.length;
147
- const testSeconds = calculateTestSeconds(performance.now());
148
- const wpm = Math.round(((correctWordChars + spaces) * (60 / testSeconds)) / 5);
149
- const raw = Math.round(((chars + spaces) * (60 / testSeconds)) / 5);
150
- return {
151
- wpm: wpm,
152
- raw: raw,
153
- };
154
- }
155
- export function setEnd(e) {
156
- end = e;
157
- end2 = Date.now();
158
- }
159
- export function setStart(s) {
160
- start = s;
161
- start2 = Date.now();
162
- }
163
- export function calculateAfkSeconds(testSeconds) {
164
- let extraAfk = 0;
165
- if (testSeconds !== undefined) {
166
- if (Config.mode === 'time') {
167
- extraAfk = Math.round(testSeconds) - TestInput.keypressPerSecond.length;
168
- }
169
- else {
170
- extraAfk = Math.ceil(testSeconds) - TestInput.keypressPerSecond.length;
171
- }
172
- if (extraAfk < 0)
173
- extraAfk = 0;
174
- // console.log("-- extra afk debug");
175
- // console.log("should be " + Math.ceil(testSeconds));
176
- // console.log(keypressPerSecond.length);
177
- // console.log(
178
- // `gonna add extra ${extraAfk} seconds of afk because of no keypress data`
179
- // );
180
- }
181
- const ret = TestInput.keypressPerSecond.filter(x => x.afk).length;
182
- return ret + extraAfk;
183
- }
184
- export function setLastSecondNotRound() {
185
- lastSecondNotRound = true;
186
- }
187
- export function calculateBurst() {
188
- const timeToWrite = (performance.now() - TestInput.currentBurstStart) / 1000;
189
- let wordLength;
190
- wordLength = TestInput.input.current.length;
191
- if (wordLength == 0) {
192
- wordLength = TestInput.input.getHistoryLast()?.length ?? 0;
193
- }
194
- if (wordLength == 0)
195
- return 0;
196
- const speed = Misc.roundTo2((wordLength * (60 / timeToWrite)) / 5);
197
- return Math.round(speed);
198
- }
199
- export function calculateAccuracy() {
200
- const acc = (TestInput.accuracy.correct / (TestInput.accuracy.correct + TestInput.accuracy.incorrect)) *
201
- 100;
202
- return isNaN(acc) ? 0 : acc;
203
- }
204
- export function removeAfkData() {
205
- const testSeconds = calculateTestSeconds();
206
- TestInput.keypressPerSecond.splice(testSeconds);
207
- TestInput.wpmHistory.splice(testSeconds);
208
- TestInput.burstHistory.splice(testSeconds);
209
- TestInput.rawHistory.splice(testSeconds);
210
- }
211
- function countChars() {
212
- let correctWordChars = 0;
213
- let correctChars = 0;
214
- let incorrectChars = 0;
215
- let extraChars = 0;
216
- let missedChars = 0;
217
- let spaces = 0;
218
- let correctspaces = 0;
219
- for (let i = 0; i < TestInput.input.history.length; i++) {
220
- const word = Config.mode == 'zen' ? TestInput.input.getHistory(i) : TestWords.words.get(i);
221
- if (TestInput.input.getHistory(i) === '') {
222
- //last word that was not started
223
- continue;
224
- }
225
- if (TestInput.input.getHistory(i) == word) {
226
- //the word is correct
227
- correctWordChars += word.length;
228
- correctChars += word.length;
229
- if (i < TestInput.input.history.length - 1 &&
230
- Misc.getLastChar(TestInput.input.getHistory(i)) !== '\n') {
231
- correctspaces++;
232
- }
233
- }
234
- else if (TestInput.input.getHistory(i).length >= word.length) {
235
- //too many chars
236
- for (let c = 0; c < TestInput.input.getHistory(i).length; c++) {
237
- if (c < word.length) {
238
- //on char that still has a word list pair
239
- if (TestInput.input.getHistory(i)[c] == word[c]) {
240
- correctChars++;
241
- }
242
- else {
243
- incorrectChars++;
244
- }
245
- }
246
- else {
247
- //on char that is extra
248
- extraChars++;
249
- }
250
- }
251
- }
252
- else {
253
- //not enough chars
254
- const toAdd = {
255
- correct: 0,
256
- incorrect: 0,
257
- missed: 0,
258
- };
259
- for (let c = 0; c < word.length; c++) {
260
- if (c < TestInput.input.getHistory(i).length) {
261
- //on char that still has a word list pair
262
- if (TestInput.input.getHistory(i)[c] == word[c]) {
263
- toAdd.correct++;
264
- }
265
- else {
266
- toAdd.incorrect++;
267
- }
268
- }
269
- else {
270
- //on char that is extra
271
- toAdd.missed++;
272
- }
273
- }
274
- correctChars += toAdd.correct;
275
- incorrectChars += toAdd.incorrect;
276
- if (i === TestInput.input.history.length - 1 && Config.mode == 'time') {
277
- //last word - check if it was all correct - add to correct word chars
278
- if (toAdd.incorrect === 0)
279
- correctWordChars += toAdd.correct;
280
- }
281
- else {
282
- missedChars += toAdd.missed;
283
- }
284
- }
285
- if (i < TestInput.input.history.length - 1) {
286
- spaces++;
287
- }
288
- }
289
- if (Config.funbox === 'nospace' || Config.funbox === 'arrows') {
290
- spaces = 0;
291
- correctspaces = 0;
292
- }
293
- return {
294
- spaces: spaces,
295
- correctWordChars: correctWordChars,
296
- allCorrectChars: correctChars,
297
- incorrectChars: Config.mode == 'zen' ? TestInput.accuracy.incorrect : incorrectChars,
298
- extraChars: extraChars,
299
- missedChars: missedChars,
300
- correctSpaces: correctspaces,
301
- };
302
- }
303
- export function calculateStats() {
304
- let testSeconds = calculateTestSeconds();
305
- if (wpmCalcDebug) {
306
- console.log('date based time', (end2 - start2) / 1000);
307
- console.log('performance.now based time', testSeconds);
308
- }
309
- if (Config.mode != 'custom') {
310
- testSeconds = Misc.roundTo2(testSeconds);
311
- if (wpmCalcDebug) {
312
- console.log('mode is not custom - wounding');
313
- console.log('new time', testSeconds);
314
- }
315
- }
316
- const chars = countChars();
317
- const wpm = Misc.roundTo2(((chars.correctWordChars + chars.correctSpaces) * (60 / testSeconds)) / 5);
318
- const wpmraw = Misc.roundTo2(((chars.allCorrectChars + chars.spaces + chars.incorrectChars + chars.extraChars) *
319
- (60 / testSeconds)) /
320
- 5);
321
- if (wpmCalcDebug) {
322
- console.log('chars', chars);
323
- console.log('wpm', ((chars.correctWordChars + chars.correctSpaces) * (60 / testSeconds)) / 5);
324
- console.log('wpm rounded to 2', wpm);
325
- console.log('wpmraw', wpmraw);
326
- }
327
- const acc = Misc.roundTo2(calculateAccuracy());
328
- return {
329
- wpm: isNaN(wpm) ? 0 : wpm,
330
- wpmRaw: isNaN(wpmraw) ? 0 : wpmraw,
331
- acc: acc,
332
- correctChars: chars.correctWordChars,
333
- incorrectChars: chars.incorrectChars,
334
- missedChars: chars.missedChars,
335
- extraChars: chars.extraChars,
336
- allChars: chars.allCorrectChars + chars.spaces + chars.incorrectChars + chars.extraChars,
337
- time: Misc.roundTo2(testSeconds),
338
- spaces: chars.spaces,
339
- correctSpaces: chars.correctSpaces,
340
- };
341
- }
342
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC1zdGF0cy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3Rnby10eXBpbmctdGVzdC9zcmMvbGliL2hlbHBlcnMvdGVzdC90ZXN0LXN0YXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sTUFBTSxNQUFNLHNCQUFzQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxJQUFJLE1BQU0sa0JBQWtCLENBQUM7QUFDekMsT0FBTyxLQUFLLFNBQVMsTUFBTSxjQUFjLENBQUM7QUFDMUMsT0FBTyxLQUFLLFNBQVMsTUFBTSxjQUFjLENBQUM7QUErRTFDLE1BQU0sQ0FBQyxJQUFJLE9BQU8sR0FBRyxLQUFLLENBQUM7QUFDM0IsTUFBTSxDQUFDLElBQUksS0FBYSxFQUFFLEdBQVcsQ0FBQztBQUN0QyxNQUFNLENBQUMsSUFBSSxNQUFjLEVBQUUsSUFBWSxDQUFDO0FBQ3hDLE1BQU0sQ0FBQyxJQUFJLGtCQUFrQixHQUFHLEtBQUssQ0FBQztBQUV0QyxNQUFNLENBQUMsSUFBSSxXQUFXLEdBQUcsQ0FBQyxDQUFDO0FBRTNCLE1BQU0sVUFBVSxjQUFjLENBQUMsR0FBVztJQUN4QyxXQUFXLEdBQUcsR0FBRyxDQUFDO0FBQ3BCLENBQUM7QUFFRCxNQUFNLENBQUMsSUFBSSxVQUFnRCxDQUFDO0FBRTVELE1BQU0sVUFBVSxhQUFhLENBQUMsTUFBNEM7SUFDeEUsVUFBVSxHQUFHLE1BQU0sQ0FBQztBQUN0QixDQUFDO0FBRUQsSUFBSSxZQUFZLEdBQUcsS0FBSyxDQUFDO0FBQ3pCLE1BQU0sVUFBVSxtQkFBbUI7SUFDakMsT0FBTyxDQUFDLEdBQUcsQ0FBQywrQkFBK0IsQ0FBQyxDQUFDO0lBQzdDLFlBQVksR0FBRyxJQUFJLENBQUM7QUFDdEIsQ0FBQztBQUVELE1BQU0sVUFBVSxRQUFRO0lBQ3RCLE1BQU0sR0FBRyxHQUFlO1FBQ3RCLFVBQVU7UUFDVixLQUFLO1FBQ0wsR0FBRztRQUNILFVB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LEtBQUssQ0FBQyxVQUFVO1FBQzVCLFFBQVEsRUFBRSxLQUFLLENBQUMsZUFBZSxHQUFHLEtBQUssQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUMsVUFBVTtRQUN4RixJQUFJLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUM7UUFDaEMsTUFBTSxFQUFFLEtBQUssQ0FBQyxNQUFNO1FBQ3BCLGFBQWEsRUFBRSxLQUFLLENBQUMsYUFBYTtLQUNuQyxDQUFDO0FBQ0osQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCBDb25maWcgZnJvbSAnLi4vLi4vaGVscGVycy9jb25maWcnO1xuaW1wb3J0ICogYXMgTWlzYyBmcm9tICcuLi8uLi91dGlscy9taXNjJztcbmltcG9ydCAqIGFzIFRlc3RJbnB1dCBmcm9tICcuL3Rlc3QtaW5wdXQnO1xuaW1wb3J0ICogYXMgVGVzdFdvcmRzIGZyb20gJy4vdGVzdC13b3Jkcyc7XG5pbXBvcnQgeyBNb25rZXlUeXBlcyB9IGZyb20gJy4uLy4uL3R5cGVzL3R5cGVzJztcbmludGVyZmFjZSBDaGFyQ291bnQge1xuICBzcGFjZXM6IG51bWJlcjtcbiAgY29ycmVjdFdvcmRDaGFyczogbnVtYmVyO1xuICBhbGxDb3JyZWN0Q2hhcnM6IG51bWJlcjtcbiAgaW5jb3JyZWN0Q2hhcnM6IG51bWJlcjtcbiAgZXh0cmFDaGFyczogbnVtYmVyO1xuICBtaXNzZWRDaGFyczogbnVtYmVyO1xuICBjb3JyZWN0U3BhY2VzOiBudW1iZXI7XG59XG5cbmludGVyZmFjZSBLZXlwcmVzcyB7XG4gIGNvdW50OiBudW1iZXI7XG4gIGVycm9yczogbnVtYmVyO1xuICB3b3JkczogbnVtYmVyW107XG4gIGFmazogYm9vbGVhbjtcbn1cblxuaW50ZXJmYWNlIEtleXByZXNzVGltaW5ncyB7XG4gIHNwYWNpbmc6IHtcbiAgICBjdXJyZW50OiBudW1iZXI7XG4gICAgYXJyYXk6IG51bWJlcltdIHwgJ3Rvb2xvbmcnO1xuICB9O1xuICBkdXJhdGlvbjoge1xuICAgIGN1cnJlbnQ6IG51bWJlcjtcbiAgICBhcnJheTogbnVtYmVyW10gfCAndG9vbG9uZyc7XG4gIH07XG59XG5cbmludGVyZmFjZSBEZWJ1Z1N0YXRzIHtcbiAgbGFzdFJlc3VsdD86IE1vbmtleVR5cGVzLlJlc3VsdDxNb25rZXlUeXBlcy5Nb2RlPjtcbiAgc3RhcnQ6IG51bWJlcjtcbiAgZW5kOiBudW1iZXI7XG4gIHdwbUhpc3Rvcnk6IG51bWJlcltdO1xuICByYXdIaXN0b3J5OiBudW1iZXJbXTtcbiAgYnVyc3RIaXN0b3J5OiBudW1iZXJbXTtcbiAga2V5cHJlc3NQZXJTZWNvbmQ6IEtleXByZXNzW107XG4gIGN1cnJlbnRLZXlwcmVzczoge1xuICAgIGNvdW50OiBudW1iZXI7XG4gICAgZXJyb3JzOiBudW1iZXI7XG4gICAgd29yZHM6IG51bWJlcltdO1xuICAgIGFmazogYm9vbGVhbjtcbiAgfTtcbiAgbGFzdEtleXByZXNzOiBudW1iZXI7XG4gIGN1cnJlbnRCdXJzdFN0YXJ0OiBudW1iZXI7XG4gIGxhc3RTZWNvbmROb3RSb3VuZDogYm9vbGVhbjtcbiAgbWlzc2VkV29yZHM6IHtcbiAgICBbd29yZDogc3RyaW5nXTogbnVtYmVyO1xuICB9O1xuICBhY2N1cmFjeToge1xuICAgIGNvcnJlY3Q6IG51bWJlcjtcbiAgICBpbmNvcnJlY3Q6IG51bWJlcjtcbiAgfTtcbiAga2V5cHJlc3NUaW1pbmdzOiBLZXlwcmVzc1RpbWluZ3M7XG4gIGtleVNwYWNpbmdTdGF0cz86IHtcbiAgICBhdmVyYWdlOiBudW1iZXI7XG4gICAgc2Q6IG51bWJlcjtcbiAgfTtcbiAga2V5RHVyYXRpb25TdGF0cz86IHtcbiAgICBhdmVyYWdlOiBudW1iZXI7XG4gICAgc2Q6IG51bWJlcjtcbiAgfTtcbn1cblxuaW50ZXJmYWNlIFN0YXRzIHtcbiAgd3BtOiBudW1iZXI7XG4gIHdwbVJhdzogbnVtYmVyO1xuICBhY2M6IG51bWJlcjtcbiAgY29ycmVjdENoYXJzOiBudW1iZXI7XG4gIGluY29ycmVjdENoYXJzOiBudW1iZXI7XG4gIG1pc3NlZENoYXJzOiBudW1iZXI7XG4gIGV4dHJhQ2hhcnM6IG51bWJlcjtcbiAgYWxsQ2hhcnM6IG51bWJlcjtcbiAgdGltZTogbnVtYmVyO1xuICBzcGFjZXM6IG51bWJlcjtcbiAgY29ycmVjdFNwYWNlczogbnVtYmVyO1xufVxuXG5leHBvcnQgbGV0IGludmFsaWQgPSBmYWxzZTtcbmV4cG9ydCBsZXQgc3RhcnQ6IG51bWJlciwgZW5kOiBudW1iZXI7XG5leHBvcnQgbGV0IHN0YXJ0MjogbnVtYmVyLCBlbmQyOiBudW1iZXI7XG5leHBvcnQgbGV0IGxhc3RTZWNvbmROb3RSb3VuZCA9IGZhbHNlO1xuXG5leHBvcnQgbGV0IGxhc3RUZXN0V3BtID0gMDtcblxuZXhwb3J0IGZ1bmN0aW9uIHNldExhc3RUZXN0V3BtKHdwbTogbnVtYmVyKTogdm9pZCB7XG4gIGxhc3RUZXN0V3BtID0gd3BtO1xufVxuXG5leHBvcnQgbGV0IGxhc3RSZXN1bHQ6IE1vbmtleVR5cGVzLlJlc3VsdDxNb25rZXlUeXBlcy5Nb2RlPjtcblxuZXhwb3J0IGZ1bmN0aW9uIHNldExhc3RSZXN1bHQocmVzdWx0OiBNb25rZXlUeXBlcy5SZXN1bHQ8TW9ua2V5VHlwZXMuTW9kZT4pOiB2b2lkIHtcbiAgbGFzdFJlc3VsdCA9IHJlc3VsdDtcbn1cblxubGV0IHdwbUNhbGNEZWJ1ZyA9IGZhbHNlO1xuZXhwb3J0IGZ1bmN0aW9uIHdwbUNhbGN1bGF0aW9uRGVidWcoKTogdm9pZCB7XG4gIGNvbnNvbGUubG9nKCd3cG0gY2FsY3VsYXRpb24gZGVidWcgZW5hYmxlZCcpO1xuICB3cG1DYWxjRGVidWcgPSB0cnVlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0U3RhdHMoKTogRGVidWdTdGF0cyB7XG4gIGNvbnN0IHJldDogRGVidWdTdGF0cyA9IHtcbiAgICBsYXN0UmVzdWx0LFxuICAgIHN0YXJ0LFxuICAgIGVuZCxcbiAgICB3cG1IaXN0b3J5OiBUZXN0SW5wdXQud3BtSGlzdG9yeSxcbiAgICByYXdIaXN0b3J5OiBUZXN0SW5wdXQud3BtSGlzdG9yeSxcbiAgICBidXJzdEhpc3Rvcnk6IFRlc3RJbnB1dC5idXJzdEhpc3RvcnksXG4gICAga2V5cHJlc3NQZXJTZWNvbmQ6IFRlc3RJbnB1dC5rZXlwcmVzc1BlclNlY29uZCxcbiAgICBjdXJyZW50S2V5cHJlc3M6IFRlc3RJbnB1dC5jdXJyZW50S2V5cHJlc3MsXG4gICAgbGFzdEtleXByZXNzOiBUZXN0SW5wdXQubGFzdEtleXByZXNzLFxuICAgIGN1cnJlbnRCdXJzdFN0YXJ0OiBUZXN0SW5wdXQuY3VycmVudEJ1cnN0U3RhcnQsXG4gICAgbGFzdFNlY29uZE5vdFJvdW5kLFxuICAgIG1pc3NlZFdvcmRzOiBUZXN0SW5wdXQubWlzc2VkV29yZHMsXG4gICAgYWNjdXJhY3k6IFRlc3RJbnB1dC5hY2N1cmFjeSxcbiAgICBrZXlwcmVzc1RpbWluZ3M6IFRlc3RJbnB1dC5rZXlwcmVzc1RpbWluZ3MsXG4gIH07XG5cbiAgdHJ5IHtcbiAgICByZXQua2V5U3BhY2luZ1N0YXRzID0ge1xuICAgICAgYXZlcmFnZTpcbiAgICAgICAgKFRlc3RJbnB1dC5rZXlwcmVzc1RpbWluZ3Muc3BhY2luZy5hcnJheSBhcyBudW1iZXJbXSkucmVkdWNlKFxuICAgICAgICAgIChwcmV2aW91cywgY3VycmVudCkgPT4gKGN1cnJlbnQgKz0gcHJldmlvdXMpXG4gICAgICAgICkgLyBUZXN0SW5wdXQua2V5cHJlc3NUaW1pbmdzLnNwYWNpbmcuYXJyYXkubGVuZ3RoLFxuICAgICAgc2Q6IE1pc2Muc3RkRGV2KFRlc3RJbnB1dC5rZXlwcmVzc1RpbWluZ3Muc3BhY2luZy5hcnJheSBhcyBudW1iZXJbXSksXG4gICAgfTtcbiAgfSBjYXRjaCAoZSkge1xuICAgIC8vXG4gIH1cbiAgdHJ5IHtcbiAgICByZXQua2V5RHVyYXRpb25TdGF0cyA9IHtcbiAgICAgIGF2ZXJhZ2U6XG4gICAgICAgIChUZXN0SW5wdXQua2V5cHJlc3NUaW1pbmdzLmR1cmF0aW9uLmFycmF5IGFzIG51bWJlcltdKS5yZWR1Y2UoXG4gICAgICAgICAgKHByZXZpb3VzLCBjdXJyZW50KSA9PiAoY3VycmVudCArPSBwcmV2aW91cylcbiAgICAgICAgKSAvIFRlc3RJbnB1dC5rZXlwcmVzc1RpbWluZ3MuZHVyYXRpb24uYXJyYXkubGVuZ3RoLFxuICAgICAgc2Q6IE1pc2Muc3RkRGV2KFRlc3RJbnB1dC5rZXlwcmVzc1RpbWluZ3MuZHVyYXRpb24uYXJyYXkgYXMgbnVtYmVyW10pLFxuICAgIH07XG4gIH0gY2F0Y2ggKGUpIHtcbiAgICAvL1xuICB9XG5cbiAgcmV0dXJuIHJldDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlc3RhcnQoKTogdm9pZCB7XG4gIHN0YXJ0ID0gMDtcbiAgZW5kID0gMDtcbiAgaW52YWxpZCA9IGZhbHNlO1xuICBsYXN0U2Vjb25kTm90Um91bmQgPSBmYWxzZTtcbn1cblxuZXhwb3J0IGxldCByZXN0YXJ0Q291bnQgPSAwO1xuZXhwb3J0IGxldCBpbmNvbXBsZXRlU2Vjb25kcyA9IDA7XG5cbmV4cG9ydCBmdW5jdGlvbiBpbmNyZW1lbnRSZXN0YXJ0Q291bnQoKTogdm9pZCB7XG4gIHJlc3RhcnRDb3VudCsrO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gaW5jcmVtZW50SW5jb21wbGV0ZVNlY29uZHModmFsOiBudW1iZXIpOiB2b2lkIHtcbiAgaW5jb21wbGV0ZVNlY29uZHMgKz0gdmFsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVzZXRJbmNvbXBsZXRlKCk6IHZvaWQge1xuICByZXN0YXJ0Q291bnQgPSAwO1xuICBpbmNvbXBsZXRlU2Vjb25kcyA9IDA7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRJbnZhbGlkKCk6IHZvaWQge1xuICBpbnZhbGlkID0gdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZVRlc3RTZWNvbmRzKG5vdz86IG51bWJlcik6IG51bWJlciB7XG4gIGlmIChub3cgPT09IHVuZGVmaW5lZCkge1xuICAgIGNvbnN0IGVuZEFma1NlY29uZHMgPSAoZW5kIC0gVGVzdElucHV0Lmxhc3RLZXlwcmVzcykgLyAxMDAwO1xuICAgIGlmICgoQ29uZmlnLm1vZGUgPT0gJ3plbicgfHwgVGVzdElucHV0LmJhaWxvdXQpICYmIGVuZEFma1NlY29uZHMgPCA3KSB7XG4gICAgICByZXR1cm4gKFRlc3RJbnB1dC5sYXN0S2V5cHJlc3MgLSBzdGFydCkgLyAxMDAwO1xuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gKGVuZCAtIHN0YXJ0KSAvIDEwMDA7XG4gICAgfVxuICB9IGVsc2Uge1xuICAgIHJldHVybiAobm93IC0gc3RhcnQpIC8gMTAwMDtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlV3BtQW5kUmF3KCk6IE1vbmtleVR5cGVzLldvcmRzUGVyTWludXRlQW5kUmF3IHtcbiAgbGV0IGNoYXJzID0gMDtcbiAgbGV0IGNvcnJlY3RXb3JkQ2hhcnMgPSAwO1xuICBsZXQgc3BhY2VzID0gMDtcbiAgLy9jaGVjayBpbnB1dCBoaXN0b3J5XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgVGVzdElucHV0LmlucHV0Lmhpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCB3b3JkID0gQ29uZmlnLm1vZGUgPT0gJ3plbicgPyBUZXN0SW5wdXQuaW5wdXQuZ2V0SGlzdG9yeShpKSA6IFRlc3RXb3Jkcy53b3Jkcy5nZXQoaSk7XG4gICAgaWYgKFRlc3RJbnB1dC5pbnB1dC5nZXRIaXN0b3J5KGkpID09IHdvcmQpIHtcbiAgICAgIC8vdGhlIHdvcmQgaXMgY29ycmVjdFxuICAgICAgLy8rMSBmb3Igc3BhY2VcbiAgICAgIGNvcnJlY3RXb3JkQ2hhcnMgKz0gd29yZC5sZW5ndGg7XG4gICAgICBpZiAoXG4gICAgICAgIGkgPCBUZXN0SW5wdXQuaW5wdXQuaGlzdG9yeS5sZW5ndGggLSAxICYmXG4gICAgICAgIE1pc2MuZ2V0TGFzdENoYXIoVGVzdElucHV0LmlucHV0LmdldEhpc3RvcnkoaSkgYXMgc3RyaW5nKSAhPT0gJ1xcbidcbiAgICAgICkge1xuICAgICAgICBzcGFjZXMrKztcbiAgICAgIH1cbiAgICB9XG4gICAgY2hhcnMgKz0gVGVzdElucHV0LmlucHV0LmdldEhpc3RvcnkoaSkubGVuZ3RoO1xuICB9XG4gIGlmIChUZXN0SW5wdXQuaW5wdXQuY3VycmVudCAhPT0gJycpIHtcbiAgICBjb25zdCB3b3JkID0gQ29uZmlnLm1vZGUgPT0gJ3plbicgPyBUZXN0SW5wdXQuaW5wdXQuY3VycmVudCA6IFRlc3RXb3Jkcy53b3Jkcy5nZXRDdXJyZW50KCk7XG4gICAgLy9jaGVjayB3aGF0cyBjdXJyZW50bHkgdHlwZWRcbiAgICBjb25zdCB0b0FkZCA9IHtcbiAgICAgIGNvcnJlY3Q6IDAsXG4gICAgICBpbmNvcnJlY3Q6IDAsXG4gICAgICBtaXNzZWQ6IDAsXG4gICAgfTtcbiAgICBmb3IgKGxldCBjID0gMDsgYyA8IHdvcmQubGVuZ3RoOyBjKyspIHtcbiAgICAgIGlmIChjIDwgVGVzdElucHV0LmlucHV0LmN1cnJlbnQubGVuZ3RoKSB7XG4gICAgICAgIC8vb24gY2hhciB0aGF0IHN0aWxsIGhhcyBhIHdvcmQgbGlzdCBwYWlyXG4gICAgICAgIGlmIChUZXN0SW5wdXQuaW5wdXQuY3VycmVudFtjXSA9PSB3b3JkW2NdKSB7XG4gICAgICAgICAgdG9BZGQuY29ycmVjdCsrO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIHRvQWRkLmluY29ycmVjdCsrO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvL29uIGNoYXIgdGhhdCBpcyBleHRyYVxuICAgICAgICB0b0FkZC5taXNzZWQrKztcbiAgICAgIH1cbiAgICB9XG4gICAgY2hhcnMgKz0gdG9BZGQuY29ycmVjdDtcbiAgICBjaGFycyArPSB0b0FkZC5pbmNvcnJlY3Q7XG4gICAgY2hhcnMgKz0gdG9BZGQubWlzc2VkO1xuICAgIGlmICh0b0FkZC5pbmNvcnJlY3QgPT0gMCkge1xuICAgICAgLy93b3JkIGlzIGNvcnJlY3Qgc28gZmFyLCBhZGQgY2hhcnNcbiAgICAgIGNvcnJlY3RXb3JkQ2hhcnMgKz0gdG9BZGQuY29ycmVjdDtcbiAgICB9XG4gIH1cbiAgaWYgKENvbmZpZy5mdW5ib3ggPT09ICdub3NwYWNlJyB8fCBDb25maWcuZnVuYm94ID09PSAnYXJyb3dzJykge1xuICAgIHNwYWNlcyA9IDA7XG4gIH1cbiAgY2hhcnMgKz0gVGVzdElucHV0LmlucHV0LmN1cnJlbnQubGVuZ3RoO1xuICBjb25zdCB0ZXN0U2Vjb25kcyA9IGNhbGN1bGF0ZVRlc3RTZWNvbmRzKHBlcmZvcm1hbmNlLm5vdygpKTtcbiAgY29uc3Qgd3BtID0gTWF0aC5yb3VuZCgoKGNvcnJlY3RXb3JkQ2hhcnMgKyBzcGFjZXMpICogKDYwIC8gdGVzdFNlY29uZHMpKSAvIDUpO1xuICBjb25zdCByYXcgPSBNYXRoLnJvdW5kKCgoY2hhcnMgKyBzcGFjZXMpICogKDYwIC8gdGVzdFNlY29uZHMpKSAvIDUpO1xuICByZXR1cm4ge1xuICAgIHdwbTogd3BtLFxuICAgIHJhdzogcmF3LFxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0RW5kKGU6IG51bWJlcik6IHZvaWQge1xuICBlbmQgPSBlO1xuICBlbmQyID0gRGF0ZS5ub3coKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldFN0YXJ0KHM6IG51bWJlcik6IHZvaWQge1xuICBzdGFydCA9IHM7XG4gIHN0YXJ0MiA9IERhdGUubm93KCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjYWxjdWxhdGVBZmtTZWNvbmRzKHRlc3RTZWNvbmRzOiBudW1iZXIpOiBudW1iZXIge1xuICBsZXQgZXh0cmFBZmsgPSAwO1xuICBpZiAodGVzdFNlY29uZHMgIT09IHVuZGVmaW5lZCkge1xuICAgIGlmIChDb25maWcubW9kZSA9PT0gJ3RpbWUnKSB7XG4gICAgICBleHRyYUFmayA9IE1hdGgucm91bmQodGVzdFNlY29uZHMpIC0gVGVzdElucHV0LmtleXByZXNzUGVyU2Vjb25kLmxlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgZXh0cmFBZmsgPSBNYXRoLmNlaWwodGVzdFNlY29uZHMpIC0gVGVzdElucHV0LmtleXByZXNzUGVyU2Vjb25kLmxlbmd0aDtcbiAgICB9XG4gICAgaWYgKGV4dHJhQWZrIDwgMCkgZXh0cmFBZmsgPSAwO1xuICAgIC8vIGNvbnNvbGUubG9nKFwiLS0gZXh0cmEgYWZrIGRlYnVnXCIpO1xuICAgIC8vIGNvbnNvbGUubG9nKFwic2hvdWxkIGJlIFwiICsgTWF0aC5jZWlsKHRlc3RTZWNvbmRzKSk7XG4gICAgLy8gY29uc29sZS5sb2coa2V5cHJlc3NQZXJTZWNvbmQubGVuZ3RoKTtcbiAgICAvLyBjb25zb2xlLmxvZyhcbiAgICAvLyAgIGBnb25uYSBhZGQgZXh0cmEgJHtleHRyYUFma30gc2Vjb25kcyBvZiBhZmsgYmVjYXVzZSBvZiBubyBrZXlwcmVzcyBkYXRhYFxuICAgIC8vICk7XG4gIH1cbiAgY29uc3QgcmV0ID0gVGVzdElucHV0LmtleXByZXNzUGVyU2Vjb25kLmZpbHRlcih4ID0+IHguYWZrKS5sZW5ndGg7XG4gIHJldHVybiByZXQgKyBleHRyYUFmaztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldExhc3RTZWNvbmROb3RSb3VuZCgpOiB2b2lkIHtcbiAgbGFzdFNlY29uZE5vdFJvdW5kID0gdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZUJ1cnN0KCk6IG51bWJlciB7XG4gIGNvbnN0IHRpbWVUb1dyaXRlID0gKHBlcmZvcm1hbmNlLm5vdygpIC0gVGVzdElucHV0LmN1cnJlbnRCdXJzdFN0YXJ0KSAvIDEwMDA7XG4gIGxldCB3b3JkTGVuZ3RoOiBudW1iZXI7XG4gIHdvcmRMZW5ndGggPSBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5sZW5ndGg7XG4gIGlmICh3b3JkTGVuZ3RoID09IDApIHtcbiAgICB3b3JkTGVuZ3RoID0gVGVzdElucHV0LmlucHV0LmdldEhpc3RvcnlMYXN0KCk/Lmxlbmd0aCA/PyAwO1xuICB9XG4gIGlmICh3b3JkTGVuZ3RoID09IDApIHJldHVybiAwO1xuICBjb25zdCBzcGVlZCA9IE1pc2Mucm91bmRUbzIoKHdvcmRMZW5ndGggKiAoNjAgLyB0aW1lVG9Xcml0ZSkpIC8gNSk7XG4gIHJldHVybiBNYXRoLnJvdW5kKHNwZWVkKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNhbGN1bGF0ZUFjY3VyYWN5KCk6IG51bWJlciB7XG4gIGNvbnN0IGFjYyA9XG4gICAgKFRlc3RJbnB1dC5hY2N1cmFjeS5jb3JyZWN0IC8gKFRlc3RJbnB1dC5hY2N1cmFjeS5jb3JyZWN0ICsgVGVzdElucHV0LmFjY3VyYWN5LmluY29ycmVjdCkpICpcbiAgICAxMDA7XG4gIHJldHVybiBpc05hTihhY2MpID8gMCA6IGFjYztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZUFma0RhdGEoKTogdm9pZCB7XG4gIGNvbnN0IHRlc3RTZWNvbmRzID0gY2FsY3VsYXRlVGVzdFNlY29uZHMoKTtcbiAgVGVzdElucHV0LmtleXByZXNzUGVyU2Vjb25kLnNwbGljZSh0ZXN0U2Vjb25kcyk7XG4gIFRlc3RJbnB1dC53cG1IaXN0b3J5LnNwbGljZSh0ZXN0U2Vjb25kcyk7XG4gIFRlc3RJbnB1dC5idXJzdEhpc3Rvcnkuc3BsaWNlKHRlc3RTZWNvbmRzKTtcbiAgVGVzdElucHV0LnJhd0hpc3Rvcnkuc3BsaWNlKHRlc3RTZWNvbmRzKTtcbn1cblxuZnVuY3Rpb24gY291bnRDaGFycygpOiBDaGFyQ291bnQge1xuICBsZXQgY29ycmVjdFdvcmRDaGFycyA9IDA7XG4gIGxldCBjb3JyZWN0Q2hhcnMgPSAwO1xuICBsZXQgaW5jb3JyZWN0Q2hhcnMgPSAwO1xuICBsZXQgZXh0cmFDaGFycyA9IDA7XG4gIGxldCBtaXNzZWRDaGFycyA9IDA7XG4gIGxldCBzcGFjZXMgPSAwO1xuICBsZXQgY29ycmVjdHNwYWNlcyA9IDA7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgVGVzdElucHV0LmlucHV0Lmhpc3RvcnkubGVuZ3RoOyBpKyspIHtcbiAgICBjb25zdCB3b3JkID0gQ29uZmlnLm1vZGUgPT0gJ3plbicgPyBUZXN0SW5wdXQuaW5wdXQuZ2V0SGlzdG9yeShpKSA6IFRlc3RXb3Jkcy53b3Jkcy5nZXQoaSk7XG4gICAgaWYgKFRlc3RJbnB1dC5pbnB1dC5nZXRIaXN0b3J5KGkpID09PSAnJykge1xuICAgICAgLy9sYXN0IHdvcmQgdGhhdCB3YXMgbm90IHN0YXJ0ZWRcbiAgICAgIGNvbnRpbnVlO1xuICAgIH1cbiAgICBpZiAoVGVzdElucHV0LmlucHV0LmdldEhpc3RvcnkoaSkgPT0gd29yZCkge1xuICAgICAgLy90aGUgd29yZCBpcyBjb3JyZWN0XG4gICAgICBjb3JyZWN0V29yZENoYXJzICs9IHdvcmQubGVuZ3RoO1xuICAgICAgY29ycmVjdENoYXJzICs9IHdvcmQubGVuZ3RoO1xuICAgICAgaWYgKFxuICAgICAgICBpIDwgVGVzdElucHV0LmlucHV0Lmhpc3RvcnkubGVuZ3RoIC0gMSAmJlxuICAgICAgICBNaXNjLmdldExhc3RDaGFyKFRlc3RJbnB1dC5pbnB1dC5nZXRIaXN0b3J5KGkpIGFzIHN0cmluZykgIT09ICdcXG4nXG4gICAgICApIHtcbiAgICAgICAgY29ycmVjdHNwYWNlcysrO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoVGVzdElucHV0LmlucHV0LmdldEhpc3RvcnkoaSkubGVuZ3RoID49IHdvcmQubGVuZ3RoKSB7XG4gICAgICAvL3RvbyBtYW55IGNoYXJzXG4gICAgICBmb3IgKGxldCBjID0gMDsgYyA8IFRlc3RJbnB1dC5pbnB1dC5nZXRIaXN0b3J5KGkpLmxlbmd0aDsgYysrKSB7XG4gICAgICAgIGlmIChjIDwgd29yZC5sZW5ndGgpIHtcbiAgICAgICAgICAvL29uIGNoYXIgdGhhdCBzdGlsbCBoYXMgYSB3b3JkIGxpc3QgcGFpclxuICAgICAgICAgIGlmIChUZXN0SW5wdXQuaW5wdXQuZ2V0SGlzdG9yeShpKVtjXSA9PSB3b3JkW2NdKSB7XG4gICAgICAgICAgICBjb3JyZWN0Q2hhcnMrKztcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaW5jb3JyZWN0Q2hhcnMrKztcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy9vbiBjaGFyIHRoYXQgaXMgZXh0cmFcbiAgICAgICAgICBleHRyYUNoYXJzKys7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy9ub3QgZW5vdWdoIGNoYXJzXG4gICAgICBjb25zdCB0b0FkZCA9IHtcbiAgICAgICAgY29ycmVjdDogMCxcbiAgICAgICAgaW5jb3JyZWN0OiAwLFxuICAgICAgICBtaXNzZWQ6IDAsXG4gICAgICB9O1xuICAgICAgZm9yIChsZXQgYyA9IDA7IGMgPCB3b3JkLmxlbmd0aDsgYysrKSB7XG4gICAgICAgIGlmIChjIDwgVGVzdElucHV0LmlucHV0LmdldEhpc3RvcnkoaSkubGVuZ3RoKSB7XG4gICAgICAgICAgLy9vbiBjaGFyIHRoYXQgc3RpbGwgaGFzIGEgd29yZCBsaXN0IHBhaXJcbiAgICAgICAgICBpZiAoVGVzdElucHV0LmlucHV0LmdldEhpc3RvcnkoaSlbY10gPT0gd29yZFtjXSkge1xuICAgICAgICAgICAgdG9BZGQuY29ycmVjdCsrO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0b0FkZC5pbmNvcnJlY3QrKztcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy9vbiBjaGFyIHRoYXQgaXMgZXh0cmFcbiAgICAgICAgICB0b0FkZC5taXNzZWQrKztcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgY29ycmVjdENoYXJzICs9IHRvQWRkLmNvcnJlY3Q7XG4gICAgICBpbmNvcnJlY3RDaGFycyArPSB0b0FkZC5pbmNvcnJlY3Q7XG4gICAgICBpZiAoaSA9PT0gVGVzdElucHV0LmlucHV0Lmhpc3RvcnkubGVuZ3RoIC0gMSAmJiBDb25maWcubW9kZSA9PSAndGltZScpIHtcbiAgICAgICAgLy9sYXN0IHdvcmQgLSBjaGVjayBpZiBpdCB3YXMgYWxsIGNvcnJlY3QgLSBhZGQgdG8gY29ycmVjdCB3b3JkIGNoYXJzXG4gICAgICAgIGlmICh0b0FkZC5pbmNvcnJlY3QgPT09IDApIGNvcnJlY3RXb3JkQ2hhcnMgKz0gdG9BZGQuY29ycmVjdDtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIG1pc3NlZENoYXJzICs9IHRvQWRkLm1pc3NlZDtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGkgPCBUZXN0SW5wdXQuaW5wdXQuaGlzdG9yeS5sZW5ndGggLSAxKSB7XG4gICAgICBzcGFjZXMrKztcbiAgICB9XG4gIH1cbiAgaWYgKENvbmZpZy5mdW5ib3ggPT09ICdub3NwYWNlJyB8fCBDb25maWcuZnVuYm94ID09PSAnYXJyb3dzJykge1xuICAgIHNwYWNlcyA9IDA7XG4gICAgY29ycmVjdHNwYWNlcyA9IDA7XG4gIH1cbiAgcmV0dXJuIHtcbiAgICBzcGFjZXM6IHNwYWNlcyxcbiAgICBjb3JyZWN0V29yZENoYXJzOiBjb3JyZWN0V29yZENoYXJzLFxuICAgIGFsbENvcnJlY3RDaGFyczogY29ycmVjdENoYXJzLFxuICAgIGluY29ycmVjdENoYXJzOiBDb25maWcubW9kZSA9PSAnemVuJyA/IFRlc3RJbnB1dC5hY2N1cmFjeS5pbmNvcnJlY3QgOiBpbmNvcnJlY3RDaGFycyxcbiAgICBleHRyYUNoYXJzOiBleHRyYUNoYXJzLFxuICAgIG1pc3NlZENoYXJzOiBtaXNzZWRDaGFycyxcbiAgICBjb3JyZWN0U3BhY2VzOiBjb3JyZWN0c3BhY2VzLFxuICB9O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gY2FsY3VsYXRlU3RhdHMoKTogU3RhdHMge1xuICBsZXQgdGVzdFNlY29uZHMgPSBjYWxjdWxhdGVUZXN0U2Vjb25kcygpO1xuICBpZiAod3BtQ2FsY0RlYnVnKSB7XG4gICAgY29uc29sZS5sb2coJ2RhdGUgYmFzZWQgdGltZScsIChlbmQyIC0gc3RhcnQyKSAvIDEwMDApO1xuICAgIGNvbnNvbGUubG9nKCdwZXJmb3JtYW5jZS5ub3cgYmFzZWQgdGltZScsIHRlc3RTZWNvbmRzKTtcbiAgfVxuICBpZiAoQ29uZmlnLm1vZGUgIT0gJ2N1c3RvbScpIHtcbiAgICB0ZXN0U2Vjb25kcyA9IE1pc2Mucm91bmRUbzIodGVzdFNlY29uZHMpO1xuICAgIGlmICh3cG1DYWxjRGVidWcpIHtcbiAgICAgIGNvbnNvbGUubG9nKCdtb2RlIGlzIG5vdCBjdXN0b20gLSB3b3VuZGluZycpO1xuICAgICAgY29uc29sZS5sb2coJ25ldyB0aW1lJywgdGVzdFNlY29uZHMpO1xuICAgIH1cbiAgfVxuICBjb25zdCBjaGFycyA9IGNvdW50Q2hhcnMoKTtcbiAgY29uc3Qgd3BtID0gTWlzYy5yb3VuZFRvMihcbiAgICAoKGNoYXJzLmNvcnJlY3RXb3JkQ2hhcnMgKyBjaGFycy5jb3JyZWN0U3BhY2VzKSAqICg2MCAvIHRlc3RTZWNvbmRzKSkgLyA1XG4gICk7XG4gIGNvbnN0IHdwbXJhdyA9IE1pc2Mucm91bmRUbzIoXG4gICAgKChjaGFycy5hbGxDb3JyZWN0Q2hhcnMgKyBjaGFycy5zcGFjZXMgKyBjaGFycy5pbmNvcnJlY3RDaGFycyArIGNoYXJzLmV4dHJhQ2hhcnMpICpcbiAgICAgICg2MCAvIHRlc3RTZWNvbmRzKSkgL1xuICAgICAgNVxuICApO1xuICBpZiAod3BtQ2FsY0RlYnVnKSB7XG4gICAgY29uc29sZS5sb2coJ2NoYXJzJywgY2hhcnMpO1xuICAgIGNvbnNvbGUubG9nKCd3cG0nLCAoKGNoYXJzLmNvcnJlY3RXb3JkQ2hhcnMgKyBjaGFycy5jb3JyZWN0U3BhY2VzKSAqICg2MCAvIHRlc3RTZWNvbmRzKSkgLyA1KTtcbiAgICBjb25zb2xlLmxvZygnd3BtIHJvdW5kZWQgdG8gMicsIHdwbSk7XG4gICAgY29uc29sZS5sb2coJ3dwbXJhdycsIHdwbXJhdyk7XG4gIH1cbiAgY29uc3QgYWNjID0gTWlzYy5yb3VuZFRvMihjYWxjdWxhdGVBY2N1cmFjeSgpKTtcbiAgcmV0dXJuIHtcbiAgICB3cG06IGlzTmFOKHdwbSkgPyAwIDogd3BtLFxuICAgIHdwbVJhdzogaXNOYU4od3BtcmF3KSA/IDAgOiB3cG1yYXcsXG4gICAgYWNjOiBhY2MsXG4gICAgY29ycmVjdENoYXJzOiBjaGFycy5jb3JyZWN0V29yZENoYXJzLFxuICAgIGluY29ycmVjdENoYXJzOiBjaGFycy5pbmNvcnJlY3RDaGFycyxcbiAgICBtaXNzZWRDaGFyczogY2hhcnMubWlzc2VkQ2hhcnMsXG4gICAgZXh0cmFDaGFyczogY2hhcnMuZXh0cmFDaGFycyxcbiAgICBhbGxDaGFyczogY2hhcnMuYWxsQ29ycmVjdENoYXJzICsgY2hhcnMuc3BhY2VzICsgY2hhcnMuaW5jb3JyZWN0Q2hhcnMgKyBjaGFycy5leHRyYUNoYXJzLFxuICAgIHRpbWU6IE1pc2Mucm91bmRUbzIodGVzdFNlY29uZHMpLFxuICAgIHNwYWNlczogY2hhcnMuc3BhY2VzLFxuICAgIGNvcnJlY3RTcGFjZXM6IGNoYXJzLmNvcnJlY3RTcGFjZXMsXG4gIH07XG59XG4iXX0=
@@ -1,207 +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
- import Config from '../../helpers/config';
4
- import * as Misc from '../../utils/misc';
5
- import * as TimerEvent from '../observables/timer-event';
6
- import * as SlowTimer from '../states/slow-timer';
7
- import * as TestActive from '../states/test-active';
8
- import * as Time from '../states/time';
9
- import * as Caret from './caret';
10
- import * as CustomText from './custom-text';
11
- import * as TestInput from './test-input';
12
- import * as TestStats from './test-stats';
13
- import * as TestWords from './test-words';
14
- import * as TimerProgress from './timer-progress';
15
- let slowTimerCount = 0;
16
- let timer = null;
17
- const interval = 1000;
18
- let expected = 0;
19
- let timerDebug = false;
20
- export function enableTimerDebug() {
21
- timerDebug = true;
22
- }
23
- let checkIfTimeIsUpDisabled = false;
24
- export function disableCheckIfTimeIsUp() {
25
- checkIfTimeIsUpDisabled = true;
26
- }
27
- export function clear() {
28
- Time.set(0);
29
- if (timer !== null)
30
- clearTimeout(timer);
31
- }
32
- function premid() {
33
- if (timerDebug)
34
- console.time('premid');
35
- const premidSecondsLeft = document.querySelector('#premidSecondsLeft');
36
- if (premidSecondsLeft !== null) {
37
- premidSecondsLeft.innerHTML = (Config.time - Time.get()).toString();
38
- }
39
- if (timerDebug)
40
- console.timeEnd('premid');
41
- }
42
- function updateTimer() {
43
- if (timerDebug)
44
- console.time('timer progress update');
45
- if (Config.mode === 'time' || (Config.mode === 'custom' && CustomText.isTimeRandom)) {
46
- TimerProgress.update();
47
- }
48
- if (timerDebug)
49
- console.timeEnd('timer progress update');
50
- }
51
- function calculateWpmRaw() {
52
- if (timerDebug)
53
- console.time('calculate wpm and raw');
54
- const wpmAndRaw = TestStats.calculateWpmAndRaw();
55
- if (timerDebug)
56
- console.timeEnd('calculate wpm and raw');
57
- if (timerDebug)
58
- console.time('push to history');
59
- TestInput.pushToWpmHistory(wpmAndRaw.wpm);
60
- TestInput.pushToRawHistory(wpmAndRaw.raw);
61
- if (timerDebug)
62
- console.timeEnd('push to history');
63
- return wpmAndRaw;
64
- }
65
- function monkey(wpmAndRaw) {
66
- if (timerDebug)
67
- console.time('update monkey');
68
- const num = Config.blindMode ? wpmAndRaw.raw : wpmAndRaw.wpm;
69
- if (timerDebug)
70
- console.timeEnd('update monkey');
71
- }
72
- function calculateAcc() {
73
- if (timerDebug)
74
- console.time('calculate acc');
75
- const acc = Misc.roundTo2(TestStats.calculateAccuracy());
76
- if (timerDebug)
77
- console.timeEnd('calculate acc');
78
- return acc;
79
- }
80
- function layoutfluid() {
81
- if (timerDebug)
82
- console.time('layoutfluid');
83
- if (Config.funbox === 'layoutfluid' && Config.mode === 'time') {
84
- const layouts = Config.customLayoutfluid
85
- ? Config.customLayoutfluid.split('#')
86
- : ['qwerty', 'dvorak', 'colemak'];
87
- const switchTime = Config.time / layouts.length;
88
- const time = Time.get();
89
- const index = Math.floor(time / switchTime);
90
- const layout = layouts[index];
91
- const flooredSwitchTimes = [];
92
- for (let i = 1; i < layouts.length; i++) {
93
- flooredSwitchTimes.push(Math.floor(switchTime * i));
94
- }
95
- }
96
- if (timerDebug)
97
- console.timeEnd('layoutfluid');
98
- }
99
- function checkIfFailed(wpmAndRaw, acc) {
100
- if (timerDebug)
101
- console.time('fail conditions');
102
- TestInput.pushKeypressesToHistory();
103
- if (Config.minWpm === 'custom' &&
104
- wpmAndRaw.wpm < Config.minWpmCustomSpeed &&
105
- TestWords.words.currentIndex > 3) {
106
- if (timer !== null)
107
- clearTimeout(timer);
108
- SlowTimer.clear();
109
- slowTimerCount = 0;
110
- TimerEvent.dispatch('fail', 'min wpm');
111
- return;
112
- }
113
- if (Config.minAcc === 'custom' && acc < Config.minAccCustom) {
114
- if (timer !== null)
115
- clearTimeout(timer);
116
- SlowTimer.clear();
117
- slowTimerCount = 0;
118
- TimerEvent.dispatch('fail', 'min accuracy');
119
- return;
120
- }
121
- if (timerDebug)
122
- console.timeEnd('fail conditions');
123
- }
124
- function checkIfTimeIsUp() {
125
- if (timerDebug)
126
- console.time('times up check');
127
- if (Config.mode == 'time' || (Config.mode === 'custom' && CustomText.isTimeRandom)) {
128
- if ((Time.get() >= Config.time && Config.time !== 0 && Config.mode === 'time') ||
129
- (Time.get() >= CustomText.time && CustomText.time !== 0 && Config.mode === 'custom')) {
130
- //times up
131
- if (timer !== null)
132
- clearTimeout(timer);
133
- Caret.hide();
134
- TestInput.input.pushHistory();
135
- TestInput.corrected.pushHistory();
136
- SlowTimer.clear();
137
- slowTimerCount = 0;
138
- TimerEvent.dispatch('finish');
139
- return;
140
- }
141
- }
142
- if (timerDebug)
143
- console.timeEnd('times up check');
144
- }
145
- // ---------------------------------------
146
- let timerStats = [];
147
- export function getTimerStats() {
148
- return timerStats;
149
- }
150
- async function timerStep() {
151
- if (timerDebug)
152
- 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)
165
- console.timeEnd('timer step -----------------------------');
166
- }
167
- export async function start() {
168
- SlowTimer.clear();
169
- slowTimerCount = 0;
170
- timerStats = [];
171
- expected = TestStats.start + interval;
172
- (function loop() {
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 ((Config.mode === 'time' && Config.time < 130 && Config.time > 0) ||
181
- (Config.mode === 'words' && Config.words < 250 && Config.words > 0)) {
182
- if (delay < interval / 2) {
183
- //slow timer
184
- SlowTimer.set();
185
- }
186
- if (delay < interval / 10) {
187
- slowTimerCount++;
188
- if (slowTimerCount > 5) {
189
- TimerEvent.dispatch('fail', 'slow timer');
190
- }
191
- }
192
- }
193
- timer = setTimeout(function () {
194
- if (!TestActive.get()) {
195
- if (timer !== null)
196
- clearTimeout(timer);
197
- SlowTimer.clear();
198
- slowTimerCount = 0;
199
- return;
200
- }
201
- timerStep();
202
- expected += interval;
203
- loop();
204
- }, delay);
205
- })();
206
- }
207
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC10aW1lci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3Rnby10eXBpbmctdGVzdC9zcmMvbGliL2hlbHBlcnMvdGVzdC90ZXN0LXRpbWVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGdDQUFnQztBQUNoQyw2RkFBNkY7QUFFN0YsT0FBTyxNQUFNLE1BQU0sc0JBQXNCLENBQUM7QUFFMUMsT0FBTyxLQUFLLElBQUksTUFBTSxrQkFBa0IsQ0FBQztBQUN6QyxPQUFPLEtBQUssVUFBVSxNQUFNLDRCQUE0QixDQUFDO0FBQ3pELE9BQU8sS0FBSyxTQUFTLE1BQU0sc0JBQXNCLENBQUM7QUFDbEQsT0FBTyxLQUFLLFVBQVUsTUFBTSx1QkFBdUIsQ0FBQztBQUNwRCxPQUFPLEtBQUssSUFBSSxNQUFNLGdCQUFnQixDQUFDO0FBQ3ZDLE9BQU8sS0FBSyxLQUFLLE1BQU0sU0FBUyxDQUFDO0FBQ2pDLE9BQU8sS0FBSyxVQUFVLE1BQU0sZUFBZSxDQUFDO0FBQzVDLE9BQU8sS0FBSyxTQUFTLE1BQU0sY0FBYyxDQUFDO0FBQzFDLE9BQU8sS0FBSyxTQUFTLE1BQU0sY0FBYyxDQUFDO0FBQzFDLE9BQU8sS0FBSyxTQUFTLE1BQU0sY0FBYyxDQUFDO0FBQzFDLE9BQU8sS0FBSyxhQUFhLE1BQU0sa0JBQWtCLENBQUM7QUFDbEQsSUFBSSxjQUFjLEdBQUcsQ0FBQyxDQUFDO0FBQ3ZCLElBQUksS0FBSyxHQUEwQixJQUFJLENBQUM7QUFDeEMsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDO0FBQ3RCLElBQUksUUFBUSxHQUFHLENBQUMsQ0FBQztBQUVqQixJQUFJLFVBQVUsR0FBRyxLQUFLLENBQUM7QUFDdkIsTUFBTSxVQUFVLGdCQUFnQjtJQUM5QixVQUFVLEdBQUcsSUFBSSxDQUFDO0FBQ3BCLENBQUM7QUFFRCxJQUFJLHVCQUF1QixHQUFHLEtBQUssQ0FBQztBQUNwQyxNQUFNLFVBQVUs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QUFFLENBQUM7Z0JBQ2pCLElBQUksY0FBYyxHQUFHLENBQUMsRUFBRSxDQUFDO29CQUN2QixVQUFVLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxZQUFZLENBQUMsQ0FBQztnQkFDNUMsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO1FBQ0QsS0FBSyxHQUFHLFVBQVUsQ0FBQztZQUNqQixJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUM7Z0JBQ3RCLElBQUksS0FBSyxLQUFLLElBQUk7b0JBQUUsWUFBWSxDQUFDLEtBQUssQ0FBQyxDQUFDO2dCQUN4QyxTQUFTLENBQUMsS0FBSyxFQUFFLENBQUM7Z0JBQ2xCLGNBQWMsR0FBRyxDQUFDLENBQUM7Z0JBQ25CLE9BQU87WUFDVCxDQUFDO1lBRUQsU0FBUyxFQUFFLENBQUM7WUFFWixRQUFRLElBQUksUUFBUSxDQUFDO1lBQ3JCLElBQUksRUFBRSxDQUFDO1FBQ1QsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDO0lBQ1osQ0FBQyxDQUFDLEVBQUUsQ0FBQztBQUNQLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBNb3N0IG9mIHRoZSBjb2RlIGlzIHRoYW5rcyB0b1xuLy8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9xdWVzdGlvbnMvMjk5NzE4OTgvaG93LXRvLWNyZWF0ZS1hbi1hY2N1cmF0ZS10aW1lci1pbi1qYXZhc2NyaXB0XG5cbmltcG9ydCBDb25maWcgZnJvbSAnLi4vLi4vaGVscGVycy9jb25maWcnO1xuaW1wb3J0IHsgTW9ua2V5VHlwZXMgfSBmcm9tICcuLi8uLi90eXBlcy90eXBlcyc7XG5pbXBvcnQgKiBhcyBNaXNjIGZyb20gJy4uLy4uL3V0aWxzL21pc2MnO1xuaW1wb3J0ICogYXMgVGltZXJFdmVudCBmcm9tICcuLi9vYnNlcnZhYmxlcy90aW1lci1ldmVudCc7XG5pbXBvcnQgKiBhcyBTbG93VGltZXIgZnJvbSAnLi4vc3RhdGVzL3Nsb3ctdGltZXInO1xuaW1wb3J0ICogYXMgVGVzdEFjdGl2ZSBmcm9tICcuLi9zdGF0ZXMvdGVzdC1hY3RpdmUnO1xuaW1wb3J0ICogYXMgVGltZSBmcm9tICcuLi9zdGF0ZXMvdGltZSc7XG5pbXBvcnQgKiBhcyBDYXJldCBmcm9tICcuL2NhcmV0JztcbmltcG9ydCAqIGFzIEN1c3RvbVRleHQgZnJvbSAnLi9jdXN0b20tdGV4dCc7XG5pbXBvcnQgKiBhcyBUZXN0SW5wdXQgZnJvbSAnLi90ZXN0LWlucHV0JztcbmltcG9ydCAqIGFzIFRlc3RTdGF0cyBmcm9tICcuL3Rlc3Qtc3RhdHMnO1xuaW1wb3J0ICogYXMgVGVzdFdvcmRzIGZyb20gJy4vdGVzdC13b3Jkcyc7XG5pbXBvcnQgKiBhcyBUaW1lclByb2dyZXNzIGZyb20gJy4vdGltZXItcHJvZ3Jlc3MnO1xubGV0IHNsb3dUaW1lckNvdW50ID0gMDtcbmxldCB0aW1lcjogTm9kZUpTLlRpbWVvdXQgfCBudWxsID0gbnVsbDtcbmNvbnN0IGludGVydmFsID0gMTAwMDtcbmxldCBleHBlY3RlZCA9IDA7XG5cbmxldCB0aW1lckRlYnVnID0gZmFsc2U7XG5leHBvcnQgZnVuY3Rpb24gZW5hYmxlVGltZXJEZWJ1ZygpOiB2b2lkIHtcbiAgdGltZXJEZWJ1ZyA9IHRydWU7XG59XG5cbmxldCBjaGVja0lmVGltZUlzVXBEaXNhYmxlZCA9IGZhbHNlO1xuZXhwb3J0IGZ1bmN0aW9uIGRpc2FibGVDaGVja0lmVGltZUlzVXAoKTogdm9pZCB7XG4gIGNoZWNrSWZUaW1lSXNVcERpc2FibGVkID0gdHJ1ZTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGNsZWFyKCk6IHZvaWQge1xuICBUaW1lLnNldCgwKTtcbiAgaWYgKHRpbWVyICE9PSBudWxsKSBjbGVhclRpbWVvdXQodGltZXIpO1xufVxuXG5mdW5jdGlvbiBwcmVtaWQoKTogdm9pZCB7XG4gIGlmICh0aW1lckRlYnVnKSBjb25zb2xlLnRpbWUoJ3ByZW1pZCcpO1xuICBjb25zdCBwcmVtaWRTZWNvbmRzTGVmdCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyNwcmVtaWRTZWNvbmRzTGVmdCcpO1xuXG4gIGlmIChwcmVtaWRTZWNvbmRzTGVmdCAhPT0gbnVsbCkge1xuICAgIHByZW1pZFNlY29uZHNMZWZ0LmlubmVySFRNTCA9IChDb25maWcudGltZSAtIFRpbWUuZ2V0KCkpLnRvU3RyaW5nKCk7XG4gIH1cbiAgaWYgKHRpbWVyRGVidWcpIGNvbnNvbGUudGltZUVuZCgncHJlbWlkJyk7XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVRpbWVyKCk6IHZvaWQge1xuICBpZiAodGltZXJEZWJ1ZykgY29uc29sZS50aW1lKCd0aW1lciBwcm9ncmVzcyB1cGRhdGUnKTtcbiAgaWYgKENvbmZpZy5tb2RlID09PSAndGltZScgfHwgKENvbmZpZy5tb2RlID09PSAnY3VzdG9tJyAmJiBDdXN0b21UZXh0LmlzVGltZVJhbmRvbSkpIHtcbiAgICBUaW1lclByb2dyZXNzLnVwZGF0ZSgpO1xuICB9XG4gIGlmICh0aW1lckRlYnVnKSBjb25zb2xlLnRpbWVFbmQoJ3RpbWVyIHByb2dyZXNzIHVwZGF0ZScpO1xufVxuXG5mdW5jdGlvbiBjYWxjdWxhdGVXcG1SYXcoKTogTW9ua2V5VHlwZXMuV29yZHNQZXJNaW51dGVBbmRSYXcge1xuICBpZiAodGltZXJEZWJ1ZykgY29uc29sZS50aW1lKCdjYWxjdWxhdGUgd3BtIGFuZCByYXcnKTtcbiAgY29uc3Qgd3BtQW5kUmF3ID0gVGVzdFN0YXRzLmNhbGN1bGF0ZVdwbUFuZFJhdygpO1xuICBpZiAodGltZXJEZWJ1ZykgY29uc29sZS50aW1lRW5kKCdjYWxjdWxhdGUgd3BtIGFuZCByYXcnKTtcbiAgaWYgKHRpbWVyRGVidWcpIGNvbnNvbGUudGltZSgncHVzaCB0byBoaXN0b3J5Jyk7XG4gIFRlc3RJbnB1dC5wdXNoVG9XcG1IaXN0b3J5KHdwbUFuZFJhdy53cG0pO1xuICBUZXN0SW5wdXQucHVzaFRvUmF3SGlzdG9yeSh3cG1BbmRSYXcucmF3KTtcbiAgaWYgKHRpbWVyRGVidWcpIGNvbnNvbGUudGltZUVuZCgncHVzaCB0byBoaXN0b3J5Jyk7XG4gIHJldHVybiB3cG1BbmRSYXc7XG59XG5cbmZ1bmN0aW9uIG1vbmtleSh3cG1BbmRSYXc6IE1vbmtleVR5cGVzLldvcmRzUGVyTWludXRlQW5kUmF3KTogdm9pZCB7XG4gIGlmICh0aW1lckRlYnVnKSBjb25zb2xlLnRpbWUoJ3VwZGF0ZSBtb25rZXknKTtcbiAgY29uc3QgbnVtID0gQ29uZmlnLmJsaW5kTW9kZSA/IHdwbUFuZFJhdy5yYXcgOiB3cG1BbmRSYXcud3BtO1xuICBpZiAodGltZXJEZWJ1ZykgY29uc29sZS50aW1lRW5kKCd1cGRhdGUgbW9ua2V5Jyk7XG59XG5cbmZ1bmN0aW9uIGNhbGN1bGF0ZUFjYygpOiBudW1iZXIge1xuICBpZiAodGltZXJEZWJ1ZykgY29uc29sZS50aW1lKCdjYWxjdWxhdGUgYWNjJyk7XG4gIGNvbnN0IGFjYyA9IE1pc2Mucm91bmRUbzIoVGVzdFN0YXRzLmNhbGN1bGF0ZUFjY3VyYWN5KCkpO1xuICBpZiAodGltZXJEZWJ1ZykgY29uc29sZS50aW1lRW5kKCdjYWxjdWxhdGUgYWNjJyk7XG4gIHJldHVybiBhY2M7XG59XG5cbmZ1bmN0aW9uIGxheW91dGZsdWlkKCk6IHZvaWQge1xuICBpZiAodGltZXJEZWJ1ZykgY29uc29sZS50aW1lKCdsYXlvdXRmbHVpZCcpO1xuICBpZiAoQ29uZmlnLmZ1bmJveCA9PT0gJ2xheW91dGZsdWlkJyAmJiBDb25maWcubW9kZSA9PT0gJ3RpbWUnKSB7XG4gICAgY29uc3QgbGF5b3V0cyA9IENvbmZpZy5jdXN0b21MYXlvdXRmbHVpZFxuICAgICAgPyBDb25maWcuY3VzdG9tTGF5b3V0Zmx1aWQuc3BsaXQoJyMnKVxuICAgICAgOiBbJ3F3ZXJ0eScsICdkdm9yYWsnLCAnY29sZW1hayddO1xuICAgIGNvbnN0IHN3aXRjaFRpbWUgPSBDb25maWcudGltZSAvIGxheW91dHMubGVuZ3RoO1xuICAgIGNvbnN0IHRpbWUgPSBUaW1lLmdldCgpO1xuICAgIGNvbnN0IGluZGV4ID0gTWF0aC5mbG9vcih0aW1lIC8gc3dpdGNoVGltZSk7XG4gICAgY29uc3QgbGF5b3V0ID0gbGF5b3V0c1tpbmRleF07XG4gICAgY29uc3QgZmxvb3JlZFN3aXRjaFRpbWVzID0gW107XG5cbiAgICBmb3IgKGxldCBpID0gMTsgaSA8IGxheW91dHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGZsb29yZWRTd2l0Y2hUaW1lcy5wdXNoKE1hdGguZmxvb3Ioc3dpdGNoVGltZSAqIGkpKTtcbiAgICB9XG4gIH1cbiAgaWYgKHRpbWVyRGVidWcpIGNvbnNvbGUudGltZUVuZCgnbGF5b3V0Zmx1aWQnKTtcbn1cblxuZnVuY3Rpb24gY2hlY2tJZkZhaWxlZCh3cG1BbmRSYXc6IE1vbmtleVR5cGVzLldvcmRzUGVyTWludXRlQW5kUmF3LCBhY2M6IG51bWJlcik6IHZvaWQge1xuICBpZiAodGltZXJEZWJ1ZykgY29uc29sZS50aW1lKCdmYWlsIGNvbmRpdGlvbnMnKTtcbiAgVGVzdElucHV0LnB1c2hLZXlwcmVzc2VzVG9IaXN0b3J5KCk7XG4gIGlmIChcbiAgICBDb25maWcubWluV3BtID09PSAnY3VzdG9tJyAmJlxuICAgIHdwbUFuZFJhdy53cG0gPCBDb25maWcubWluV3BtQ3VzdG9tU3BlZWQgJiZcbiAgICBUZXN0V29yZHMud29yZHMuY3VycmVudEluZGV4ID4gM1xuICApIHtcbiAgICBpZiAodGltZXIgIT09IG51bGwpIGNsZWFyVGltZW91dCh0aW1lcik7XG4gICAgU2xvd1RpbWVyLmNsZWFyKCk7XG4gICAgc2xvd1RpbWVyQ291bnQgPSAwO1xuICAgIFRpbWVyRXZlbnQuZGlzcGF0Y2goJ2ZhaWwnLCAnbWluIHdwbScpO1xuICAgIHJldHVybjtcbiAgfVxuICBpZiAoQ29uZmlnLm1pbkFjYyA9PT0gJ2N1c3RvbScgJiYgYWNjIDwgQ29uZmlnLm1pbkFjY0N1c3RvbSkge1xuICAgIGlmICh0aW1lciAhPT0gbnVsbCkgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICBTbG93VGltZXIuY2xlYXIoKTtcbiAgICBzbG93VGltZXJDb3VudCA9IDA7XG4gICAgVGltZXJFdmVudC5kaXNwYXRjaCgnZmFpbCcsICdtaW4gYWNjdXJhY3knKTtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKHRpbWVyRGVidWcpIGNvbnNvbGUudGltZUVuZCgnZmFpbCBjb25kaXRpb25zJyk7XG59XG5cbmZ1bmN0aW9uIGNoZWNrSWZUaW1lSXNVcCgpOiB2b2lkIHtcbiAgaWYgKHRpbWVyRGVidWcpIGNvbnNvbGUudGltZSgndGltZXMgdXAgY2hlY2snKTtcbiAgaWYgKENvbmZpZy5tb2RlID09ICd0aW1lJyB8fCAoQ29uZmlnLm1vZGUgPT09ICdjdXN0b20nICYmIEN1c3RvbVRleHQuaXNUaW1lUmFuZG9tKSkge1xuICAgIGlmIChcbiAgICAgIChUaW1lLmdldCgpID49IENvbmZpZy50aW1lICYmIENvbmZpZy50aW1lICE9PSAwICYmIENvbmZpZy5tb2RlID09PSAndGltZScpIHx8XG4gICAgICAoVGltZS5nZXQoKSA+PSBDdXN0b21UZXh0LnRpbWUgJiYgQ3VzdG9tVGV4dC50aW1lICE9PSAwICYmIENvbmZpZy5tb2RlID09PSAnY3VzdG9tJylcbiAgICApIHtcbiAgICAgIC8vdGltZXMgdXBcbiAgICAgIGlmICh0aW1lciAhPT0gbnVsbCkgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgIENhcmV0LmhpZGUoKTtcbiAgICAgIFRlc3RJbnB1dC5pbnB1dC5wdXNoSGlzdG9yeSgpO1xuICAgICAgVGVzdElucHV0LmNvcnJlY3RlZC5wdXNoSGlzdG9yeSgpO1xuICAgICAgU2xvd1RpbWVyLmNsZWFyKCk7XG4gICAgICBzbG93VGltZXJDb3VudCA9IDA7XG4gICAgICBUaW1lckV2ZW50LmRpc3BhdGNoKCdmaW5pc2gnKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cbiAgaWYgKHRpbWVyRGVidWcpIGNvbnNvbGUudGltZUVuZCgndGltZXMgdXAgY2hlY2snKTtcbn1cblxuLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbmxldCB0aW1lclN0YXRzOiBNb25rZXlUeXBlcy5UaW1lclN0YXRzW10gPSBbXTtcblxuZXhwb3J0IGZ1bmN0aW9uIGdldFRpbWVyU3RhdHMoKTogTW9ua2V5VHlwZXMuVGltZXJTdGF0c1tdIHtcbiAgcmV0dXJuIHRpbWVyU3RhdHM7XG59XG5cbmFzeW5jIGZ1bmN0aW9uIHRpbWVyU3RlcCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKHRpbWVyRGVidWcpIGNvbnNvbGUudGltZSgndGltZXIgc3RlcCAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLScpO1xuICBUaW1lLmluY3JlbWVudCgpO1xuICBwcmVtaWQoKTtcbiAgdXBkYXRlVGltZXIoKTtcbiAgY29uc3Qgd3BtQW5kUmF3ID0gY2FsY3VsYXRlV3BtUmF3KCk7XG4gIGNvbnN0IGFjYyA9IGNhbGN1bGF0ZUFjYygpO1xuICBtb25rZXkod3BtQW5kUmF3KTtcbiAgbGF5b3V0Zmx1aWQoKTtcbiAgY2hlY2tJZkZhaWxlZCh3cG1BbmRSYXcsIGFjYyk7XG4gIGlmICghY2hlY2tJZlRpbWVJc1VwRGlzYWJsZWQpIHtcbiAgICBjaGVja0lmVGltZUlzVXAoKTtcbiAgfVxuICBpZiAodGltZXJEZWJ1ZykgY29uc29sZS50aW1lRW5kKCd0aW1lciBzdGVwIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tJyk7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzdGFydCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgU2xvd1RpbWVyLmNsZWFyKCk7XG4gIHNsb3dUaW1lckNvdW50ID0gMDtcbiAgdGltZXJTdGF0cyA9IFtdO1xuICBleHBlY3RlZCA9IFRlc3RTdGF0cy5zdGFydCArIGludGVydmFsO1xuICAoZnVuY3Rpb24gbG9vcCgpOiB2b2lkIHtcbiAgICBjb25zdCBkZWxheSA9IGV4cGVjdGVkIC0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgdGltZXJTdGF0cy5wdXNoKHtcbiAgICAgIGRhdGVOb3c6IERhdGUubm93KCksXG4gICAgICBub3c6IHBlcmZvcm1hbmNlLm5vdygpLFxuICAgICAgZXhwZWN0ZWQ6IGV4cGVjdGVkLFxuICAgICAgbmV4dERlbGF5OiBkZWxheSxcbiAgICB9KTtcbiAgICBpZiAoXG4gICAgICAoQ29uZmlnLm1vZGUgPT09ICd0aW1lJyAmJiBDb25maWcudGltZSA8IDEzMCAmJiBDb25maWcudGltZSA+IDApIHx8XG4gICAgICAoQ29uZmlnLm1vZGUgPT09ICd3b3JkcycgJiYgQ29uZmlnLndvcmRzIDwgMjUwICYmIENvbmZpZy53b3JkcyA+IDApXG4gICAgKSB7XG4gICAgICBpZiAoZGVsYXkgPCBpbnRlcnZhbCAvIDIpIHtcbiAgICAgICAgLy9zbG93IHRpbWVyXG4gICAgICAgIFNsb3dUaW1lci5zZXQoKTtcbiAgICAgIH1cbiAgICAgIGlmIChkZWxheSA8IGludGVydmFsIC8gMTApIHtcbiAgICAgICAgc2xvd1RpbWVyQ291bnQrKztcbiAgICAgICAgaWYgKHNsb3dUaW1lckNvdW50ID4gNSkge1xuICAgICAgICAgIFRpbWVyRXZlbnQuZGlzcGF0Y2goJ2ZhaWwnLCAnc2xvdyB0aW1lcicpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIHRpbWVyID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAoIVRlc3RBY3RpdmUuZ2V0KCkpIHtcbiAgICAgICAgaWYgKHRpbWVyICE9PSBudWxsKSBjbGVhclRpbWVvdXQodGltZXIpO1xuICAgICAgICBTbG93VGltZXIuY2xlYXIoKTtcbiAgICAgICAgc2xvd1RpbWVyQ291bnQgPSAwO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRpbWVyU3RlcCgpO1xuXG4gICAgICBleHBlY3RlZCArPSBpbnRlcnZhbDtcbiAgICAgIGxvb3AoKTtcbiAgICB9LCBkZWxheSk7XG4gIH0pKCk7XG59XG4iXX0=