@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.
- package/.eslintrc.json +46 -0
- package/jest.config.ts +21 -0
- package/ng-package.json +15 -0
- package/package.json +7 -22
- package/project.json +36 -0
- package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.html +30 -0
- package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.spec.ts +250 -0
- package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.ts +47 -0
- package/src/lib/components/tgo-typing-test/tgo-typing-test.component.html +72 -0
- package/src/lib/components/tgo-typing-test/tgo-typing-test.component.spec.ts +699 -0
- package/src/lib/components/tgo-typing-test/tgo-typing-test.component.ts +287 -0
- package/src/lib/helpers/config.ts +28 -0
- package/src/lib/helpers/constants/default-config.ts +103 -0
- package/src/lib/helpers/controllers/input-controller.ts +710 -0
- package/src/lib/helpers/controllers/quotes-controller.ts +183 -0
- package/src/lib/helpers/observables/banner-event.ts +18 -0
- package/src/lib/helpers/observables/config-event.ts +31 -0
- package/src/lib/helpers/observables/timer-event.ts +18 -0
- package/src/lib/helpers/states/active-page.ts +9 -0
- package/src/lib/helpers/states/composition.ts +29 -0
- package/src/lib/helpers/states/page-transition.ts +9 -0
- package/src/lib/helpers/states/slow-timer.ts +16 -0
- package/src/lib/helpers/states/test-active.ts +9 -0
- package/src/lib/helpers/states/time.ts +13 -0
- package/src/lib/helpers/test/caps-warning.ts +50 -0
- package/src/lib/helpers/test/caret.ts +92 -0
- package/src/lib/helpers/test/custom-text.ts +73 -0
- package/src/lib/helpers/test/english-punctuation.ts +38 -0
- package/src/lib/helpers/test/focus.ts +39 -0
- package/src/lib/helpers/test/manual-restart-tracker.ts +13 -0
- package/src/lib/helpers/test/out-of-focus.ts +19 -0
- package/src/lib/helpers/test/replay.ts +265 -0
- package/src/lib/helpers/test/test-input.ts +320 -0
- package/src/lib/helpers/test/test-logic.ts +1039 -0
- package/src/lib/helpers/test/test-state.ts +17 -0
- package/src/lib/helpers/test/test-stats.ts +442 -0
- package/src/lib/helpers/test/test-timer.ts +209 -0
- package/src/lib/helpers/test/test-ui.ts +370 -0
- package/src/lib/helpers/test/test-words.ts +72 -0
- package/src/lib/helpers/test/timer-progress.ts +16 -0
- package/src/lib/helpers/test/tts.ts +42 -0
- package/src/lib/helpers/test/weak-spot.ts +74 -0
- package/src/lib/helpers/test/wordset.ts +109 -0
- package/src/lib/styles/animations.scss +101 -0
- package/src/lib/styles/caret.scss +108 -0
- package/src/lib/styles/core.scss +498 -0
- package/src/lib/styles/index.scss +19 -0
- package/src/lib/styles/inputs.scss +290 -0
- package/src/lib/styles/popups.scss +1311 -0
- package/src/lib/styles/test.scss +1008 -0
- package/src/lib/styles/z_media-queries.scss +848 -0
- package/src/lib/types/types.d.ts +731 -0
- package/src/lib/utils/misc.ts +776 -0
- package/src/test-setup.ts +20 -0
- package/tsconfig.json +16 -0
- package/tsconfig.lib.json +14 -0
- package/tsconfig.lib.prod.json +9 -0
- package/tsconfig.spec.json +11 -0
- package/esm2022/index.mjs +0 -3
- package/esm2022/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.mjs +0 -45
- package/esm2022/lib/components/tgo-typing-test/tgo-typing-test.component.mjs +0 -299
- package/esm2022/lib/helpers/config.mjs +0 -24
- package/esm2022/lib/helpers/constants/default-config.mjs +0 -103
- package/esm2022/lib/helpers/controllers/input-controller.mjs +0 -586
- package/esm2022/lib/helpers/controllers/quotes-controller.mjs +0 -118
- package/esm2022/lib/helpers/observables/config-event.mjs +0 -16
- package/esm2022/lib/helpers/observables/timer-event.mjs +0 -16
- package/esm2022/lib/helpers/states/active-page.mjs +0 -8
- package/esm2022/lib/helpers/states/composition.mjs +0 -20
- package/esm2022/lib/helpers/states/page-transition.mjs +0 -8
- package/esm2022/lib/helpers/states/slow-timer.mjs +0 -15
- package/esm2022/lib/helpers/states/test-active.mjs +0 -8
- package/esm2022/lib/helpers/states/time.mjs +0 -11
- package/esm2022/lib/helpers/test/caps-warning.mjs +0 -50
- package/esm2022/lib/helpers/test/caret.mjs +0 -80
- package/esm2022/lib/helpers/test/custom-text.mjs +0 -59
- package/esm2022/lib/helpers/test/english-punctuation.mjs +0 -29
- package/esm2022/lib/helpers/test/focus.mjs +0 -35
- package/esm2022/lib/helpers/test/manual-restart-tracker.mjs +0 -11
- package/esm2022/lib/helpers/test/out-of-focus.mjs +0 -14
- package/esm2022/lib/helpers/test/replay.mjs +0 -217
- package/esm2022/lib/helpers/test/test-input.mjs +0 -264
- package/esm2022/lib/helpers/test/test-logic.mjs +0 -927
- package/esm2022/lib/helpers/test/test-state.mjs +0 -13
- package/esm2022/lib/helpers/test/test-stats.mjs +0 -342
- package/esm2022/lib/helpers/test/test-timer.mjs +0 -207
- package/esm2022/lib/helpers/test/test-ui.mjs +0 -341
- package/esm2022/lib/helpers/test/test-words.mjs +0 -69
- package/esm2022/lib/helpers/test/timer-progress.mjs +0 -15
- package/esm2022/lib/helpers/test/weak-spot.mjs +0 -65
- package/esm2022/lib/helpers/test/wordset.mjs +0 -100
- package/esm2022/lib/utils/misc.mjs +0 -673
- package/esm2022/testgorilla-tgo-typing-test.mjs +0 -5
- package/fesm2022/testgorilla-tgo-typing-test.mjs +0 -4707
- package/fesm2022/testgorilla-tgo-typing-test.mjs.map +0 -1
- package/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.d.ts +0 -14
- package/lib/components/tgo-typing-test/tgo-typing-test.component.d.ts +0 -54
- package/lib/helpers/config.d.ts +0 -98
- package/lib/helpers/constants/default-config.d.ts +0 -3
- package/lib/helpers/controllers/input-controller.d.ts +0 -16
- package/lib/helpers/controllers/quotes-controller.d.ts +0 -20
- package/lib/helpers/observables/config-event.d.ts +0 -5
- package/lib/helpers/observables/timer-event.d.ts +0 -4
- package/lib/helpers/states/active-page.d.ts +0 -2
- package/lib/helpers/states/composition.d.ts +0 -10
- package/lib/helpers/states/page-transition.d.ts +0 -2
- package/lib/helpers/states/slow-timer.d.ts +0 -3
- package/lib/helpers/states/test-active.d.ts +0 -2
- package/lib/helpers/states/time.d.ts +0 -3
- package/lib/helpers/test/caps-warning.d.ts +0 -5
- package/lib/helpers/test/caret.d.ts +0 -11
- package/lib/helpers/test/custom-text.d.ts +0 -16
- package/lib/helpers/test/english-punctuation.d.ts +0 -3
- package/lib/helpers/test/focus.d.ts +0 -7
- package/lib/helpers/test/manual-restart-tracker.d.ts +0 -3
- package/lib/helpers/test/out-of-focus.d.ts +0 -4
- package/lib/helpers/test/replay.d.ts +0 -20
- package/lib/helpers/test/test-input.d.ts +0 -86
- package/lib/helpers/test/test-logic.d.ts +0 -25
- package/lib/helpers/test/test-state.d.ts +0 -7
- package/lib/helpers/test/test-stats.d.ts +0 -92
- package/lib/helpers/test/test-timer.d.ts +0 -6
- package/lib/helpers/test/test-ui.d.ts +0 -27
- package/lib/helpers/test/test-words.d.ts +0 -23
- package/lib/helpers/test/timer-progress.d.ts +0 -3
- package/lib/helpers/test/weak-spot.d.ts +0 -3
- package/lib/helpers/test/wordset.d.ts +0 -7
- package/lib/utils/misc.d.ts +0 -81
- /package/{assets → src/assets}/typing-test-languages/english.json +0 -0
- /package/{assets → src/assets}/typing-test-languages/english_punctuation.json +0 -0
- /package/{assets → src/assets}/typing-test-languages/quotes/english_version_1.json +0 -0
- /package/{assets → src/assets}/typing-test-languages/quotes/english_version_2.json +0 -0
- /package/{assets → src/assets}/typing-test-languages/quotes/filtered_sources.json +0 -0
- /package/{index.d.ts → src/index.ts} +0 -0
|
@@ -1,586 +0,0 @@
|
|
|
1
|
-
import * as TestLogic from '../test/test-logic';
|
|
2
|
-
import * as TestUI from '../test/test-ui';
|
|
3
|
-
import * as TestStats from '../test/test-stats';
|
|
4
|
-
import Config from '../config';
|
|
5
|
-
import * as Misc from '../../utils/misc';
|
|
6
|
-
import * as Caret from '../test/caret';
|
|
7
|
-
import * as CustomText from '../test/custom-text';
|
|
8
|
-
import * as TimerProgress from '../test/timer-progress';
|
|
9
|
-
import * as Focus from '../test/focus';
|
|
10
|
-
import * as Replay from '../test/replay';
|
|
11
|
-
import * as WeakSpot from '../test/weak-spot';
|
|
12
|
-
import * as TestActive from '../states/test-active';
|
|
13
|
-
import * as CompositionState from '../states/composition';
|
|
14
|
-
import * as TestInput from '../test/test-input';
|
|
15
|
-
import * as TestWords from '../test/test-words';
|
|
16
|
-
let dontInsertSpace = false;
|
|
17
|
-
const correctShiftUsed = true;
|
|
18
|
-
let wordsInput;
|
|
19
|
-
function setWordsInput(value) {
|
|
20
|
-
// Only change #wordsInput if it's not already the wanted value
|
|
21
|
-
// Avoids Safari triggering unneeded events, causing issues with
|
|
22
|
-
// dead keys.
|
|
23
|
-
if (value !== wordsInput.value) {
|
|
24
|
-
wordsInput.value = value;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
function updateUI() {
|
|
28
|
-
const acc = Misc.roundTo2(TestStats.calculateAccuracy());
|
|
29
|
-
}
|
|
30
|
-
function backspaceToPrevious() {
|
|
31
|
-
if (!TestActive.get())
|
|
32
|
-
return;
|
|
33
|
-
if (TestInput.input.history.length == 0 || TestUI.currentWordElementIndex == 0) {
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
if ((TestInput.input.history[TestWords.words.currentIndex - 1] ==
|
|
37
|
-
TestWords.words.get(TestWords.words.currentIndex - 1) &&
|
|
38
|
-
!Config.freedomMode) ||
|
|
39
|
-
document
|
|
40
|
-
.querySelectorAll('.word')[TestWords.words.currentIndex - 1]?.classList.contains('hidden')) {
|
|
41
|
-
return;
|
|
42
|
-
}
|
|
43
|
-
if (Config.confidenceMode === 'on' || Config.confidenceMode === 'max') {
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
46
|
-
TestInput.input.current = TestInput.input.popHistory();
|
|
47
|
-
TestInput.corrected.popHistory();
|
|
48
|
-
if (Config.funbox === 'nospace' || Config.funbox === 'arrows') {
|
|
49
|
-
TestInput.input.current = TestInput.input.current.slice(0, -1);
|
|
50
|
-
}
|
|
51
|
-
TestWords.words.decreaseCurrentIndex();
|
|
52
|
-
TestUI.setCurrentWordElementIndex(TestUI.currentWordElementIndex - 1);
|
|
53
|
-
TestUI.updateActiveElement(true);
|
|
54
|
-
TestUI.updateWordElement();
|
|
55
|
-
Caret.updatePosition();
|
|
56
|
-
Replay.addReplayEvent('backWord');
|
|
57
|
-
}
|
|
58
|
-
function handleSpace() {
|
|
59
|
-
if (!TestActive.get())
|
|
60
|
-
return;
|
|
61
|
-
if (TestInput.input.current === '')
|
|
62
|
-
return;
|
|
63
|
-
const currentWord = TestWords.words.getCurrent();
|
|
64
|
-
if (Config.funbox === 'layoutfluid' && Config.mode !== 'time') {
|
|
65
|
-
// here I need to check if Config.customLayoutFluid exists because of my scuffed solution of returning whenever value is undefined in the setCustomLayoutfluid function
|
|
66
|
-
const layouts = Config.customLayoutfluid
|
|
67
|
-
? Config.customLayoutfluid.split('#')
|
|
68
|
-
: ['qwerty', 'dvorak', 'colemak'];
|
|
69
|
-
let index = 0;
|
|
70
|
-
const outof = TestWords.words.length;
|
|
71
|
-
index = Math.floor((TestInput.input.history.length + 1) / (outof / layouts.length));
|
|
72
|
-
}
|
|
73
|
-
dontInsertSpace = true;
|
|
74
|
-
const burst = TestStats.calculateBurst();
|
|
75
|
-
TestInput.pushBurstToHistory(burst);
|
|
76
|
-
//correct word or in zen mode
|
|
77
|
-
const isWordCorrect = currentWord == TestInput.input.current || Config.mode == 'zen';
|
|
78
|
-
TestInput.incrementAccuracy(isWordCorrect);
|
|
79
|
-
if (isWordCorrect) {
|
|
80
|
-
TestInput.input.pushHistory();
|
|
81
|
-
TestWords.words.increaseCurrentIndex();
|
|
82
|
-
TestUI.setCurrentWordElementIndex(TestUI.currentWordElementIndex + 1);
|
|
83
|
-
TestUI.updateActiveElement();
|
|
84
|
-
Caret.updatePosition();
|
|
85
|
-
TestInput.incrementKeypressCount();
|
|
86
|
-
TestInput.pushKeypressWord(TestWords.words.currentIndex);
|
|
87
|
-
Replay.addReplayEvent('submitCorrectWord');
|
|
88
|
-
}
|
|
89
|
-
else {
|
|
90
|
-
TestInput.pushMissedWord(TestWords.words.getCurrent());
|
|
91
|
-
TestInput.incrementKeypressErrors();
|
|
92
|
-
const cil = TestInput.input.current.length;
|
|
93
|
-
if (cil <= TestWords.words.getCurrent().length) {
|
|
94
|
-
if (cil >= TestInput.corrected.current.length) {
|
|
95
|
-
TestInput.corrected.current += '_';
|
|
96
|
-
}
|
|
97
|
-
else {
|
|
98
|
-
TestInput.corrected.current =
|
|
99
|
-
TestInput.corrected.current.substring(0, cil) +
|
|
100
|
-
'_' +
|
|
101
|
-
TestInput.corrected.current.substring(cil + 1);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
if (Config.stopOnError != 'off') {
|
|
105
|
-
if (Config.difficulty == 'expert' || Config.difficulty == 'master') {
|
|
106
|
-
//failed due to diff when pressing space
|
|
107
|
-
TestLogic.fail('difficulty');
|
|
108
|
-
return;
|
|
109
|
-
}
|
|
110
|
-
if (Config.stopOnError == 'word') {
|
|
111
|
-
dontInsertSpace = false;
|
|
112
|
-
Replay.addReplayEvent('incorrectLetter', '_');
|
|
113
|
-
TestUI.updateWordElement(true);
|
|
114
|
-
Caret.updatePosition();
|
|
115
|
-
}
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
TestInput.input.pushHistory();
|
|
119
|
-
TestUI.highlightBadWord(TestUI.currentWordElementIndex, !Config.blindMode);
|
|
120
|
-
TestWords.words.increaseCurrentIndex();
|
|
121
|
-
TestUI.setCurrentWordElementIndex(TestUI.currentWordElementIndex + 1);
|
|
122
|
-
TestUI.updateActiveElement();
|
|
123
|
-
Caret.updatePosition();
|
|
124
|
-
TestInput.incrementKeypressCount();
|
|
125
|
-
TestInput.pushKeypressWord(TestWords.words.currentIndex);
|
|
126
|
-
TestInput.updateLastKeypress();
|
|
127
|
-
if (Config.difficulty == 'expert' || Config.difficulty == 'master') {
|
|
128
|
-
TestLogic.fail('difficulty');
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
else if (TestWords.words.currentIndex == TestWords.words.length) {
|
|
132
|
-
//submitted last word that is incorrect
|
|
133
|
-
TestLogic.finish();
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
Replay.addReplayEvent('submitErrorWord');
|
|
137
|
-
}
|
|
138
|
-
let wordLength;
|
|
139
|
-
if (Config.mode === 'zen') {
|
|
140
|
-
wordLength = TestInput.input.current.length;
|
|
141
|
-
}
|
|
142
|
-
else {
|
|
143
|
-
wordLength = TestWords.words.getCurrent().length;
|
|
144
|
-
}
|
|
145
|
-
const flex = Misc.whorf(Config.minBurstCustomSpeed, wordLength);
|
|
146
|
-
TestInput.corrected.pushHistory();
|
|
147
|
-
if (!Config.showAllLines ||
|
|
148
|
-
Config.mode == 'time' ||
|
|
149
|
-
(CustomText.isWordRandom && CustomText.word == 0) ||
|
|
150
|
-
CustomText.isTimeRandom) {
|
|
151
|
-
const currentTop = Math.floor(document.querySelectorAll('#words .word')[TestUI.currentWordElementIndex - 1]
|
|
152
|
-
.offsetTop);
|
|
153
|
-
let nextTop;
|
|
154
|
-
try {
|
|
155
|
-
nextTop = Math.floor(document.querySelectorAll('#words .word')[TestUI.currentWordElementIndex]
|
|
156
|
-
.offsetTop);
|
|
157
|
-
}
|
|
158
|
-
catch (e) {
|
|
159
|
-
nextTop = 0;
|
|
160
|
-
}
|
|
161
|
-
if (nextTop > currentTop && !TestUI.lineTransition) {
|
|
162
|
-
TestUI.lineJump(currentTop);
|
|
163
|
-
}
|
|
164
|
-
} //end of line wrap
|
|
165
|
-
if (Config.mode === 'words' ||
|
|
166
|
-
Config.mode === 'custom' ||
|
|
167
|
-
Config.mode === 'quote' ||
|
|
168
|
-
Config.mode === 'zen') {
|
|
169
|
-
TimerProgress.update();
|
|
170
|
-
}
|
|
171
|
-
if (Config.mode == 'time' ||
|
|
172
|
-
Config.mode == 'words' ||
|
|
173
|
-
Config.mode == 'custom' ||
|
|
174
|
-
Config.mode == 'quote') {
|
|
175
|
-
TestLogic.addWord();
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
function isCharCorrect(char, charIndex) {
|
|
179
|
-
if (!correctShiftUsed)
|
|
180
|
-
return false;
|
|
181
|
-
if (Config.mode == 'zen') {
|
|
182
|
-
return true;
|
|
183
|
-
}
|
|
184
|
-
const originalChar = TestWords.words.getCurrent()[charIndex];
|
|
185
|
-
if (originalChar == char) {
|
|
186
|
-
return true;
|
|
187
|
-
}
|
|
188
|
-
if (Config.language.split('_')[0] == 'russian') {
|
|
189
|
-
if ((char === 'е' || char === 'e') && originalChar == 'ё') {
|
|
190
|
-
return true;
|
|
191
|
-
}
|
|
192
|
-
if (char === 'ё' && (originalChar == 'е' || originalChar === 'e')) {
|
|
193
|
-
return true;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
if (Config.funbox === 'arrows') {
|
|
197
|
-
if ((char === 'w' || char === 'ArrowUp') && originalChar == '↑') {
|
|
198
|
-
return true;
|
|
199
|
-
}
|
|
200
|
-
if ((char === 's' || char === 'ArrowDown') && originalChar == '↓') {
|
|
201
|
-
return true;
|
|
202
|
-
}
|
|
203
|
-
if ((char === 'a' || char === 'ArrowLeft') && originalChar == '←') {
|
|
204
|
-
return true;
|
|
205
|
-
}
|
|
206
|
-
if ((char === 'd' || char === 'ArrowRight') && originalChar == '→') {
|
|
207
|
-
return true;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
if ((char === `’` || char === '‘' || char === "'") &&
|
|
211
|
-
(originalChar == `’` || originalChar === '‘' || originalChar === "'")) {
|
|
212
|
-
return true;
|
|
213
|
-
}
|
|
214
|
-
if ((char === `"` || char === '”' || char == '“' || char === '„') &&
|
|
215
|
-
(originalChar == `"` || originalChar === '”' || originalChar === '“' || originalChar === '„')) {
|
|
216
|
-
return true;
|
|
217
|
-
}
|
|
218
|
-
if ((char === '–' || char === '—' || char == '-') &&
|
|
219
|
-
(originalChar == '-' || originalChar === '–' || originalChar === '—')) {
|
|
220
|
-
return true;
|
|
221
|
-
}
|
|
222
|
-
return false;
|
|
223
|
-
}
|
|
224
|
-
function handleChar(char, charIndex) {
|
|
225
|
-
if (TestUI.resultCalculating || TestUI.resultVisible) {
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
if (char === '…') {
|
|
229
|
-
for (let i = 0; i < 3; i++) {
|
|
230
|
-
handleChar('.', charIndex + i);
|
|
231
|
-
}
|
|
232
|
-
return;
|
|
233
|
-
}
|
|
234
|
-
if (char === '\n' && (Config.funbox === '58008' || Config.funbox === 'tenKeyMode')) {
|
|
235
|
-
char = ' ';
|
|
236
|
-
}
|
|
237
|
-
if (char !== '\n' && char !== '\t' && /\s/.test(char)) {
|
|
238
|
-
if (Config.funbox === 'nospace' || Config.funbox === 'arrows')
|
|
239
|
-
return;
|
|
240
|
-
handleSpace();
|
|
241
|
-
//insert space for expert and master or strict space,
|
|
242
|
-
//or for stop on error set to word,
|
|
243
|
-
//otherwise dont do anything
|
|
244
|
-
if (Config.difficulty !== 'normal' ||
|
|
245
|
-
(Config.strictSpace && Config.mode !== 'zen') ||
|
|
246
|
-
Config.stopOnError === 'word') {
|
|
247
|
-
if (dontInsertSpace) {
|
|
248
|
-
dontInsertSpace = false;
|
|
249
|
-
return;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
else {
|
|
253
|
-
return;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
if (Config.mode !== 'zen' && TestWords.words.getCurrent()[charIndex] !== '\n' && char === '\n') {
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
//start the test
|
|
260
|
-
if (!TestActive.get() && !TestLogic.startTest()) {
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
Focus.set(true);
|
|
264
|
-
Caret.stopAnimation();
|
|
265
|
-
const thisCharCorrect = isCharCorrect(char, charIndex);
|
|
266
|
-
if (thisCharCorrect && Config.mode !== 'zen') {
|
|
267
|
-
char = TestWords.words.getCurrent().charAt(charIndex);
|
|
268
|
-
}
|
|
269
|
-
if (!thisCharCorrect && char === '\n') {
|
|
270
|
-
if (TestInput.input.current === '')
|
|
271
|
-
return;
|
|
272
|
-
char = ' ';
|
|
273
|
-
}
|
|
274
|
-
if (TestInput.input.current === '') {
|
|
275
|
-
TestInput.setBurstStart(performance.now());
|
|
276
|
-
}
|
|
277
|
-
const resultingWord = TestInput.input.current.substring(0, charIndex) +
|
|
278
|
-
char +
|
|
279
|
-
TestInput.input.current.substring(charIndex + 1);
|
|
280
|
-
// If a trailing composed char is used, ignore it when counting accuracy
|
|
281
|
-
if (!thisCharCorrect &&
|
|
282
|
-
Misc.trailingComposeChars.test(resultingWord) &&
|
|
283
|
-
CompositionState.getComposing()) {
|
|
284
|
-
TestInput.input.current = resultingWord;
|
|
285
|
-
TestUI.updateWordElement();
|
|
286
|
-
Caret.updatePosition();
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
// MonkeyPower.addPower(thisCharCorrect);
|
|
290
|
-
TestInput.incrementAccuracy(thisCharCorrect);
|
|
291
|
-
if (!thisCharCorrect) {
|
|
292
|
-
TestInput.incrementKeypressErrors();
|
|
293
|
-
TestInput.pushMissedWord(TestWords.words.getCurrent());
|
|
294
|
-
}
|
|
295
|
-
WeakSpot.updateScore(Config.mode === 'zen' ? char : TestWords.words.getCurrent()[charIndex], thisCharCorrect);
|
|
296
|
-
if (!correctShiftUsed && Config.difficulty != 'master')
|
|
297
|
-
return;
|
|
298
|
-
//update current corrected version. if its empty then add the current char. if its not then replace the last character with the currently pressed one / add it
|
|
299
|
-
if (TestInput.corrected.current === '') {
|
|
300
|
-
TestInput.corrected.current += resultingWord;
|
|
301
|
-
}
|
|
302
|
-
else {
|
|
303
|
-
if (charIndex >= TestInput.corrected.current.length) {
|
|
304
|
-
TestInput.corrected.current += char;
|
|
305
|
-
}
|
|
306
|
-
else if (!thisCharCorrect) {
|
|
307
|
-
TestInput.corrected.current =
|
|
308
|
-
TestInput.corrected.current.substring(0, charIndex) +
|
|
309
|
-
char +
|
|
310
|
-
TestInput.corrected.current.substring(charIndex + 1);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
TestInput.incrementKeypressCount();
|
|
314
|
-
TestInput.updateLastKeypress();
|
|
315
|
-
TestInput.pushKeypressWord(TestWords.words.currentIndex);
|
|
316
|
-
if (Config.difficulty !== 'master' && Config.stopOnError == 'letter' && !thisCharCorrect) {
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
Replay.addReplayEvent(thisCharCorrect ? 'correctLetter' : 'incorrectLetter', char);
|
|
320
|
-
//update the active word top, but only once
|
|
321
|
-
if (TestInput.input.current.length === 1 && TestWords.words.currentIndex === 0) {
|
|
322
|
-
TestUI.setActiveWordTop(document.querySelector('#words .active')?.offsetTop);
|
|
323
|
-
}
|
|
324
|
-
//max length of the input is 20 unless in zen mode then its 30
|
|
325
|
-
if ((Config.mode === 'zen' && charIndex < 30) ||
|
|
326
|
-
(Config.mode !== 'zen' && charIndex < TestWords.words.getCurrent().length + 20)) {
|
|
327
|
-
TestInput.input.current = resultingWord;
|
|
328
|
-
}
|
|
329
|
-
if (!thisCharCorrect && Config.difficulty == 'master') {
|
|
330
|
-
TestInput.input.pushHistory();
|
|
331
|
-
TestInput.corrected.pushHistory();
|
|
332
|
-
TestLogic.fail('difficulty');
|
|
333
|
-
return;
|
|
334
|
-
}
|
|
335
|
-
if (Config.mode != 'zen') {
|
|
336
|
-
//not applicable to zen mode
|
|
337
|
-
//auto stop the test if the last word is correct
|
|
338
|
-
const currentWord = TestWords.words.getCurrent();
|
|
339
|
-
const lastindex = TestWords.words.currentIndex;
|
|
340
|
-
if ((currentWord == TestInput.input.current ||
|
|
341
|
-
(Config.quickEnd &&
|
|
342
|
-
currentWord.length == TestInput.input.current.length &&
|
|
343
|
-
Config.stopOnError == 'off')) &&
|
|
344
|
-
lastindex == TestWords.words.length - 1) {
|
|
345
|
-
TestInput.input.pushHistory();
|
|
346
|
-
TestInput.corrected.pushHistory();
|
|
347
|
-
TestLogic.finish();
|
|
348
|
-
return;
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
const activeWordTopBeforeJump = document.querySelector('#words .word.active')
|
|
352
|
-
?.offsetTop;
|
|
353
|
-
TestUI.updateWordElement();
|
|
354
|
-
if (!Config.hideExtraLetters) {
|
|
355
|
-
const newActiveTop = document.querySelector('#words .word.active')
|
|
356
|
-
?.offsetTop;
|
|
357
|
-
//stop the word jump by slicing off the last character, update word again
|
|
358
|
-
if (activeWordTopBeforeJump < newActiveTop &&
|
|
359
|
-
!TestUI.lineTransition &&
|
|
360
|
-
TestInput.input.current.length > 1) {
|
|
361
|
-
if (Config.mode == 'zen') {
|
|
362
|
-
const currentTop = Math.floor(document.querySelectorAll('#words .word')[TestUI.currentWordElementIndex - 1]
|
|
363
|
-
?.offsetTop);
|
|
364
|
-
if (!Config.showAllLines)
|
|
365
|
-
TestUI.lineJump(currentTop);
|
|
366
|
-
}
|
|
367
|
-
else {
|
|
368
|
-
TestInput.input.current = TestInput.input.current.slice(0, -1);
|
|
369
|
-
TestUI.updateWordElement();
|
|
370
|
-
}
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
//simulate space press in nospace funbox
|
|
374
|
-
if (((Config.funbox === 'nospace' || Config.funbox === 'arrows') &&
|
|
375
|
-
TestInput.input.current.length === TestWords.words.getCurrent().length) ||
|
|
376
|
-
(char === '\n' && thisCharCorrect)) {
|
|
377
|
-
handleSpace();
|
|
378
|
-
}
|
|
379
|
-
if (char !== '\n') {
|
|
380
|
-
Caret.updatePosition();
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
function handleTab(event, popupVisible) {
|
|
384
|
-
if (TestUI.resultCalculating) {
|
|
385
|
-
event.preventDefault();
|
|
386
|
-
return;
|
|
387
|
-
}
|
|
388
|
-
let shouldInsertTabCharacter = false;
|
|
389
|
-
if ((Config.mode == 'zen' && !event.shiftKey) || (TestWords.hasTab && !event.shiftKey)) {
|
|
390
|
-
shouldInsertTabCharacter = true;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
export function setWordsInputElement(wordsElement) {
|
|
394
|
-
wordsInput = wordsElement;
|
|
395
|
-
}
|
|
396
|
-
export async function inputKeydown(event, wordsFocused) {
|
|
397
|
-
const allowTyping = !TestUI.resultVisible && (wordsFocused || event.key !== 'Enter');
|
|
398
|
-
//no space for tenKeyMode
|
|
399
|
-
if (Config.funbox === 'tenKeyMode' && event.keyCode === 32) {
|
|
400
|
-
event.preventDefault();
|
|
401
|
-
}
|
|
402
|
-
if (allowTyping && !wordsFocused && event.key !== 'Enter') {
|
|
403
|
-
TestUI.focusWords();
|
|
404
|
-
if (Config.showOutOfFocusWarning) {
|
|
405
|
-
event.preventDefault();
|
|
406
|
-
}
|
|
407
|
-
}
|
|
408
|
-
//tab
|
|
409
|
-
if (event.key == 'Tab') {
|
|
410
|
-
handleTab(event, false);
|
|
411
|
-
}
|
|
412
|
-
if (!allowTyping)
|
|
413
|
-
return;
|
|
414
|
-
if (!event.isTrusted || TestUI.testRestarting) {
|
|
415
|
-
event.preventDefault();
|
|
416
|
-
return;
|
|
417
|
-
}
|
|
418
|
-
if (TestInput.spacingDebug) {
|
|
419
|
-
console.log('spacing debug', 'keypress', event.key, 'length', TestInput.keypressTimings.spacing.array.length);
|
|
420
|
-
}
|
|
421
|
-
TestInput.recordKeypressSpacing();
|
|
422
|
-
TestInput.setKeypressDuration(performance.now());
|
|
423
|
-
TestInput.setKeypressNotAfk();
|
|
424
|
-
//blocking firefox from going back in history with backspace
|
|
425
|
-
if (event.key === 'Backspace') {
|
|
426
|
-
const t = /INPUT|SELECT|TEXTAREA/i;
|
|
427
|
-
if (!t.test(event.target.tagName)) {
|
|
428
|
-
event.preventDefault();
|
|
429
|
-
}
|
|
430
|
-
if (Config.confidenceMode === 'max') {
|
|
431
|
-
event.preventDefault();
|
|
432
|
-
return;
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
|
-
if (Config.funbox !== 'arrows' && /Arrow/i.test(event.key)) {
|
|
436
|
-
event.preventDefault();
|
|
437
|
-
return;
|
|
438
|
-
}
|
|
439
|
-
if (event.key === 'Backspace' && TestInput.input.current.length === 0) {
|
|
440
|
-
backspaceToPrevious();
|
|
441
|
-
if (TestInput.input.current) {
|
|
442
|
-
setWordsInput(' ' + TestInput.input.current + ' ');
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
if (event.key === 'Enter') {
|
|
446
|
-
if (event.shiftKey && Config.mode == 'zen') {
|
|
447
|
-
TestLogic.finish();
|
|
448
|
-
}
|
|
449
|
-
else if (event.shiftKey &&
|
|
450
|
-
((Config.mode == 'time' && Config.time === 0) ||
|
|
451
|
-
(Config.mode == 'words' && Config.words === 0))) {
|
|
452
|
-
TestInput.setBailout(true);
|
|
453
|
-
TestLogic.finish();
|
|
454
|
-
}
|
|
455
|
-
else {
|
|
456
|
-
handleChar('\n', TestInput.input.current.length);
|
|
457
|
-
setWordsInput(' ' + TestInput.input.current);
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
//show dead keys
|
|
461
|
-
if (event.key === 'Dead' && !CompositionState.getComposing()) {
|
|
462
|
-
const word = document.querySelector('#words .word.active');
|
|
463
|
-
const len = TestInput.input.current.length; // have to do this because prettier wraps the line and causes an error
|
|
464
|
-
// Check to see if the letter actually exists to toggle it as dead
|
|
465
|
-
const deadLetter = word?.querySelectorAll('letter')[len];
|
|
466
|
-
if (deadLetter) {
|
|
467
|
-
deadLetter.classList.toggle('dead');
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
if (Config.funbox === 'arrows') {
|
|
471
|
-
let char = event.key;
|
|
472
|
-
if (['ArrowLeft', 'ArrowUp', 'ArrowRight', 'ArrowDown'].includes(char)) {
|
|
473
|
-
if (char === 'ArrowLeft')
|
|
474
|
-
char = 'a';
|
|
475
|
-
if (char === 'ArrowRight')
|
|
476
|
-
char = 'd';
|
|
477
|
-
if (char === 'ArrowDown')
|
|
478
|
-
char = 's';
|
|
479
|
-
if (char === 'ArrowUp')
|
|
480
|
-
char = 'w';
|
|
481
|
-
event.preventDefault();
|
|
482
|
-
handleChar(char, TestInput.input.current.length);
|
|
483
|
-
updateUI();
|
|
484
|
-
setWordsInput(' ' + TestInput.input.current);
|
|
485
|
-
}
|
|
486
|
-
}
|
|
487
|
-
}
|
|
488
|
-
export function wordsInputKeyup(event) {
|
|
489
|
-
if (!event.isTrusted || TestUI.testRestarting) {
|
|
490
|
-
event.preventDefault();
|
|
491
|
-
return;
|
|
492
|
-
}
|
|
493
|
-
if (TestUI.resultVisible)
|
|
494
|
-
return;
|
|
495
|
-
const now = performance.now();
|
|
496
|
-
if (TestInput.keypressTimings.duration.current !== -1) {
|
|
497
|
-
const diff = Math.abs(TestInput.keypressTimings.duration.current - now);
|
|
498
|
-
TestInput.pushKeypressDuration(diff);
|
|
499
|
-
}
|
|
500
|
-
TestInput.setKeypressDuration(now);
|
|
501
|
-
}
|
|
502
|
-
export function wordsInputBeforeinput(event) {
|
|
503
|
-
if (!event.isTrusted)
|
|
504
|
-
return;
|
|
505
|
-
if (event.target.value === '') {
|
|
506
|
-
event.target.value = ' ';
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
export function wordsInputInput(event) {
|
|
510
|
-
if (!event.isTrusted || TestUI.testRestarting) {
|
|
511
|
-
event.target.value = ' ';
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
TestInput.setKeypressNotAfk();
|
|
515
|
-
const realInputValue = event.target.value.normalize();
|
|
516
|
-
const inputValue = realInputValue.slice(1);
|
|
517
|
-
// input will be modified even with the preventDefault() in
|
|
518
|
-
// beforeinput/keydown if it's part of a compose sequence. this undoes
|
|
519
|
-
// the effects of that and takes the input out of compose mode.
|
|
520
|
-
if (Config.layout !== 'default' && inputValue.length >= TestInput.input.current.length) {
|
|
521
|
-
setWordsInput(' ' + TestInput.input.current);
|
|
522
|
-
return;
|
|
523
|
-
}
|
|
524
|
-
if (realInputValue.length === 0 && TestInput.input.current.length === 0) {
|
|
525
|
-
// fallback for when no Backspace keydown event (mobile)
|
|
526
|
-
backspaceToPrevious();
|
|
527
|
-
}
|
|
528
|
-
else if (inputValue.length < TestInput.input.current.length) {
|
|
529
|
-
TestInput.input.current = inputValue;
|
|
530
|
-
TestUI.updateWordElement();
|
|
531
|
-
Caret.updatePosition();
|
|
532
|
-
if (!CompositionState.getComposing()) {
|
|
533
|
-
Replay.addReplayEvent('setLetterIndex', TestInput.input.current.length);
|
|
534
|
-
}
|
|
535
|
-
}
|
|
536
|
-
else if (inputValue !== TestInput.input.current) {
|
|
537
|
-
let diffStart = 0;
|
|
538
|
-
while (inputValue[diffStart] === TestInput.input.current[diffStart]) {
|
|
539
|
-
diffStart++;
|
|
540
|
-
}
|
|
541
|
-
for (let i = diffStart; i < inputValue.length; i++) {
|
|
542
|
-
handleChar(inputValue[i], i);
|
|
543
|
-
}
|
|
544
|
-
}
|
|
545
|
-
setWordsInput(' ' + TestInput.input.current);
|
|
546
|
-
updateUI();
|
|
547
|
-
const statebefore = CompositionState.getComposing();
|
|
548
|
-
setTimeout(() => {
|
|
549
|
-
// checking composition state during the input event and on the next loop
|
|
550
|
-
// this is done because some browsers (e.g. Chrome) will fire the input
|
|
551
|
-
// event before the compositionend event.
|
|
552
|
-
// this ensures the UI is correct
|
|
553
|
-
const stateafter = CompositionState.getComposing();
|
|
554
|
-
if (statebefore !== stateafter) {
|
|
555
|
-
TestUI.updateWordElement();
|
|
556
|
-
}
|
|
557
|
-
// force caret at end of input
|
|
558
|
-
// doing it on next cycle because Chromium on Android won't let me edit
|
|
559
|
-
// the selection inside the input event
|
|
560
|
-
if (event.target.selectionStart !==
|
|
561
|
-
event.target.value.length &&
|
|
562
|
-
(!Misc.trailingComposeChars.test(event.target.value) ||
|
|
563
|
-
(event.target.selectionStart ?? 0) <
|
|
564
|
-
event.target.value.search(Misc.trailingComposeChars))) {
|
|
565
|
-
event.target.selectionStart = event.target.selectionEnd = event.target.value.length;
|
|
566
|
-
}
|
|
567
|
-
}, 0);
|
|
568
|
-
}
|
|
569
|
-
export function wordsInputFocus(event) {
|
|
570
|
-
event.target.selectionStart = event.target.selectionEnd = event.target.value.length;
|
|
571
|
-
}
|
|
572
|
-
export function wordsInputCopy(event) {
|
|
573
|
-
event.preventDefault();
|
|
574
|
-
}
|
|
575
|
-
export function wordsInputPaste(event) {
|
|
576
|
-
event.preventDefault();
|
|
577
|
-
}
|
|
578
|
-
// Composing events
|
|
579
|
-
export function wordsInputCompositionstart() {
|
|
580
|
-
CompositionState.setComposing(true);
|
|
581
|
-
CompositionState.setStartPos(TestInput.input.current.length);
|
|
582
|
-
}
|
|
583
|
-
export function wordsInputCompositionend() {
|
|
584
|
-
CompositionState.setComposing(false);
|
|
585
|
-
}
|
|
586
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQtY29udHJvbGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3Rnby10eXBpbmctdGVzdC9zcmMvbGliL2hlbHBlcnMvY29udHJvbGxlcnMvaW5wdXQtY29udHJvbGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLFNBQVMsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRCxPQUFPLE1BQXlCLE1BQU0sV0FBVyxDQUFDO0FBQ2xELE9BQU8sS0FBSyxJQUFJLE1BQU0sa0JBQWtCLENBQUM7QUFDekMsT0FBTyxLQUFLLEtBQUssTUFBTSxlQUFlLENBQUM7QUFDdkMsT0FBTyxLQUFLLFVBQVUsTUFBTSxxQkFBcUIsQ0FBQztBQUNsRCxPQUFPLEtBQUssYUFBYSxNQUFNLHdCQUF3QixDQUFDO0FBQ3hELE9BQU8sS0FBSyxLQUFLLE1BQU0sZUFBZSxDQUFDO0FBQ3ZDLE9BQU8sS0FBSyxNQUFNLE1BQU0sZ0JBQWdCLENBQUM7QUFDekMsT0FBTyxLQUFLLFFBQVEsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEtBQUssVUFBVSxNQUFNLHVCQUF1QixDQUFDO0FBQ3BELE9BQU8sS0FBSyxnQkFBZ0IsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFFaEQsSUFBSSxlQUFlLEdBQUcsS0FBSyxDQUFDO0FBQzVCLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO0FBRTlCLElBQUksVUFBNEIsQ0FBQztBQUVqQyxTQUFTLGFBQWEsQ0FBQyxLQUFhO0lBQ2xDLCtEQUErRDtJQUMvRCxnRUFBZ0U7SUFDaEUsYUFBYTtJ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QUMvRSxDQUFDO1lBQ0EsS0FBSyxDQUFDLE1BQTJCLENBQUMsY0FBYyxHQUMvQyxLQUFLLENBQUMsTUFDUCxDQUFDLFlBQVksR0FBSSxLQUFLLENBQUMsTUFBMkIsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQ25FLENBQUM7SUFDSCxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDUixDQUFDO0FBRUQsTUFBTSxVQUFVLGVBQWUsQ0FBQyxLQUFtQztJQUNoRSxLQUFLLENBQUMsTUFBMkIsQ0FBQyxjQUFjLEdBQy9DLEtBQUssQ0FBQyxNQUNQLENBQUMsWUFBWSxHQUFJLEtBQUssQ0FBQyxNQUEyQixDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7QUFDbkUsQ0FBQztBQUVELE1BQU0sVUFBVSxjQUFjLENBQUMsS0FBcUM7SUFDbEUsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO0FBQ3pCLENBQUM7QUFFRCxNQUFNLFVBQVUsZUFBZSxDQUFDLEtBQXFDO0lBQ25FLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUN6QixDQUFDO0FBRUQsbUJBQW1CO0FBQ25CLE1BQU0sVUFBVSwwQkFBMEI7SUFDeEMsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BDLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUMvRCxDQUFDO0FBRUQsTUFBTSxVQUFVLHdCQUF3QjtJQUN0QyxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDdkMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIFRlc3RMb2dpYyBmcm9tICcuLi90ZXN0L3Rlc3QtbG9naWMnO1xuaW1wb3J0ICogYXMgVGVzdFVJIGZyb20gJy4uL3Rlc3QvdGVzdC11aSc7XG5pbXBvcnQgKiBhcyBUZXN0U3RhdHMgZnJvbSAnLi4vdGVzdC90ZXN0LXN0YXRzJztcbmltcG9ydCBDb25maWcsICogYXMgVXBkYXRlQ29uZmlnIGZyb20gJy4uL2NvbmZpZyc7XG5pbXBvcnQgKiBhcyBNaXNjIGZyb20gJy4uLy4uL3V0aWxzL21pc2MnO1xuaW1wb3J0ICogYXMgQ2FyZXQgZnJvbSAnLi4vdGVzdC9jYXJldCc7XG5pbXBvcnQgKiBhcyBDdXN0b21UZXh0IGZyb20gJy4uL3Rlc3QvY3VzdG9tLXRleHQnO1xuaW1wb3J0ICogYXMgVGltZXJQcm9ncmVzcyBmcm9tICcuLi90ZXN0L3RpbWVyLXByb2dyZXNzJztcbmltcG9ydCAqIGFzIEZvY3VzIGZyb20gJy4uL3Rlc3QvZm9jdXMnO1xuaW1wb3J0ICogYXMgUmVwbGF5IGZyb20gJy4uL3Rlc3QvcmVwbGF5JztcbmltcG9ydCAqIGFzIFdlYWtTcG90IGZyb20gJy4uL3Rlc3Qvd2Vhay1zcG90JztcbmltcG9ydCAqIGFzIFRlc3RBY3RpdmUgZnJvbSAnLi4vc3RhdGVzL3Rlc3QtYWN0aXZlJztcbmltcG9ydCAqIGFzIENvbXBvc2l0aW9uU3RhdGUgZnJvbSAnLi4vc3RhdGVzL2NvbXBvc2l0aW9uJztcbmltcG9ydCAqIGFzIFRlc3RJbnB1dCBmcm9tICcuLi90ZXN0L3Rlc3QtaW5wdXQnO1xuaW1wb3J0ICogYXMgVGVzdFdvcmRzIGZyb20gJy4uL3Rlc3QvdGVzdC13b3Jkcyc7XG5cbmxldCBkb250SW5zZXJ0U3BhY2UgPSBmYWxzZTtcbmNvbnN0IGNvcnJlY3RTaGlmdFVzZWQgPSB0cnVlO1xuXG5sZXQgd29yZHNJbnB1dDogSFRNTElucHV0RWxlbWVudDtcblxuZnVuY3Rpb24gc2V0V29yZHNJbnB1dCh2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gIC8vIE9ubHkgY2hhbmdlICN3b3Jkc0lucHV0IGlmIGl0J3Mgbm90IGFscmVhZHkgdGhlIHdhbnRlZCB2YWx1ZVxuICAvLyBBdm9pZHMgU2FmYXJpIHRyaWdnZXJpbmcgdW5uZWVkZWQgZXZlbnRzLCBjYXVzaW5nIGlzc3VlcyB3aXRoXG4gIC8vIGRlYWQga2V5cy5cbiAgaWYgKHZhbHVlICE9PSB3b3Jkc0lucHV0LnZhbHVlKSB7XG4gICAgd29yZHNJbnB1dC52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVVJKCk6IHZvaWQge1xuICBjb25zdCBhY2MgPSBNaXNjLnJvdW5kVG8yKFRlc3RTdGF0cy5jYWxjdWxhdGVBY2N1cmFjeSgpKTtcbn1cblxuZnVuY3Rpb24gYmFja3NwYWNlVG9QcmV2aW91cygpOiB2b2lkIHtcbiAgaWYgKCFUZXN0QWN0aXZlLmdldCgpKSByZXR1cm47XG5cbiAgaWYgKFRlc3RJbnB1dC5pbnB1dC5oaXN0b3J5Lmxlbmd0aCA9PSAwIHx8IFRlc3RVSS5jdXJyZW50V29yZEVsZW1lbnRJbmRleCA9PSAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKFxuICAgIChUZXN0SW5wdXQuaW5wdXQuaGlzdG9yeVtUZXN0V29yZHMud29yZHMuY3VycmVudEluZGV4IC0gMV0gPT1cbiAgICAgIFRlc3RXb3Jkcy53b3Jkcy5nZXQoVGVzdFdvcmRzLndvcmRzLmN1cnJlbnRJbmRleCAtIDEpICYmXG4gICAgICAhQ29uZmlnLmZyZWVkb21Nb2RlKSB8fFxuICAgIGRvY3VtZW50XG4gICAgICAucXVlcnlTZWxlY3RvckFsbCgnLndvcmQnKVxuICAgICAgW1Rlc3RXb3Jkcy53b3Jkcy5jdXJyZW50SW5kZXggLSAxXT8uY2xhc3NMaXN0LmNvbnRhaW5zKCdoaWRkZW4nKVxuICApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoQ29uZmlnLmNvbmZpZGVuY2VNb2RlID09PSAnb24nIHx8IENvbmZpZy5jb25maWRlbmNlTW9kZSA9PT0gJ21heCcpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudCA9IFRlc3RJbnB1dC5pbnB1dC5wb3BIaXN0b3J5KCk7XG4gIFRlc3RJbnB1dC5jb3JyZWN0ZWQucG9wSGlzdG9yeSgpO1xuICBpZiAoQ29uZmlnLmZ1bmJveCA9PT0gJ25vc3BhY2UnIHx8IENvbmZpZy5mdW5ib3ggPT09ICdhcnJvd3MnKSB7XG4gICAgVGVzdElucHV0LmlucHV0LmN1cnJlbnQgPSBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5zbGljZSgwLCAtMSk7XG4gIH1cbiAgVGVzdFdvcmRzLndvcmRzLmRlY3JlYXNlQ3VycmVudEluZGV4KCk7XG4gIFRlc3RVSS5zZXRDdXJyZW50V29yZEVsZW1lbnRJbmRleChUZXN0VUkuY3VycmVudFdvcmRFbGVtZW50SW5kZXggLSAxKTtcbiAgVGVzdFVJLnVwZGF0ZUFjdGl2ZUVsZW1lbnQodHJ1ZSk7XG4gIFRlc3RVSS51cGRhdGVXb3JkRWxlbWVudCgpO1xuXG4gIENhcmV0LnVwZGF0ZVBvc2l0aW9uKCk7XG4gIFJlcGxheS5hZGRSZXBsYXlFdmVudCgnYmFja1dvcmQnKTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlU3BhY2UoKTogdm9pZCB7XG4gIGlmICghVGVzdEFjdGl2ZS5nZXQoKSkgcmV0dXJuO1xuXG4gIGlmIChUZXN0SW5wdXQuaW5wdXQuY3VycmVudCA9PT0gJycpIHJldHVybjtcblxuICBjb25zdCBjdXJyZW50V29yZCA9IFRlc3RXb3Jkcy53b3Jkcy5nZXRDdXJyZW50KCk7XG4gIGlmIChDb25maWcuZnVuYm94ID09PSAnbGF5b3V0Zmx1aWQnICYmIENvbmZpZy5tb2RlICE9PSAndGltZScpIHtcbiAgICAvLyBoZXJlIEkgbmVlZCB0byBjaGVjayBpZiBDb25maWcuY3VzdG9tTGF5b3V0Rmx1aWQgZXhpc3RzIGJlY2F1c2Ugb2YgbXkgc2N1ZmZlZCBzb2x1dGlvbiBvZiByZXR1cm5pbmcgd2hlbmV2ZXIgdmFsdWUgaXMgdW5kZWZpbmVkIGluIHRoZSBzZXRDdXN0b21MYXlvdXRmbHVpZCBmdW5jdGlvblxuICAgIGNvbnN0IGxheW91dHMgPSBDb25maWcuY3VzdG9tTGF5b3V0Zmx1aWRcbiAgICAgID8gQ29uZmlnLmN1c3RvbUxheW91dGZsdWlkLnNwbGl0KCcjJylcbiAgICAgIDogWydxd2VydHknLCAnZHZvcmFrJywgJ2NvbGVtYWsnXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuICAgIGNvbnN0IG91dG9mID0gVGVzdFdvcmRzLndvcmRzLmxlbmd0aDtcbiAgICBpbmRleCA9IE1hdGguZmxvb3IoKFRlc3RJbnB1dC5pbnB1dC5oaXN0b3J5Lmxlbmd0aCArIDEpIC8gKG91dG9mIC8gbGF5b3V0cy5sZW5ndGgpKTtcbiAgfVxuICBkb250SW5zZXJ0U3BhY2UgPSB0cnVlO1xuXG4gIGNvbnN0IGJ1cnN0ID0gVGVzdFN0YXRzLmNhbGN1bGF0ZUJ1cnN0KCk7XG4gIFRlc3RJbnB1dC5wdXNoQnVyc3RUb0hpc3RvcnkoYnVyc3QpO1xuXG4gIC8vY29ycmVjdCB3b3JkIG9yIGluIHplbiBtb2RlXG4gIGNvbnN0IGlzV29yZENvcnJlY3QgPSBjdXJyZW50V29yZCA9PSBUZXN0SW5wdXQuaW5wdXQuY3VycmVudCB8fCBDb25maWcubW9kZSA9PSAnemVuJztcbiAgVGVzdElucHV0LmluY3JlbWVudEFjY3VyYWN5KGlzV29yZENvcnJlY3QpO1xuICBpZiAoaXNXb3JkQ29ycmVjdCkge1xuICAgIFRlc3RJbnB1dC5pbnB1dC5wdXNoSGlzdG9yeSgpO1xuICAgIFRlc3RXb3Jkcy53b3Jkcy5pbmNyZWFzZUN1cnJlbnRJbmRleCgpO1xuICAgIFRlc3RVSS5zZXRDdXJyZW50V29yZEVsZW1lbnRJbmRleChUZXN0VUkuY3VycmVudFdvcmRFbGVtZW50SW5kZXggKyAxKTtcbiAgICBUZXN0VUkudXBkYXRlQWN0aXZlRWxlbWVudCgpO1xuICAgIENhcmV0LnVwZGF0ZVBvc2l0aW9uKCk7XG4gICAgVGVzdElucHV0LmluY3JlbWVudEtleXByZXNzQ291bnQoKTtcbiAgICBUZXN0SW5wdXQucHVzaEtleXByZXNzV29yZChUZXN0V29yZHMud29yZHMuY3VycmVudEluZGV4KTtcbiAgICBSZXBsYXkuYWRkUmVwbGF5RXZlbnQoJ3N1Ym1pdENvcnJlY3RXb3JkJyk7XG4gIH0gZWxzZSB7XG4gICAgVGVzdElucHV0LnB1c2hNaXNzZWRXb3JkKFRlc3RXb3Jkcy53b3Jkcy5nZXRDdXJyZW50KCkpO1xuICAgIFRlc3RJbnB1dC5pbmNyZW1lbnRLZXlwcmVzc0Vycm9ycygpO1xuICAgIGNvbnN0IGNpbCA9IFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50Lmxlbmd0aDtcbiAgICBpZiAoY2lsIDw9IFRlc3RXb3Jkcy53b3Jkcy5nZXRDdXJyZW50KCkubGVuZ3RoKSB7XG4gICAgICBpZiAoY2lsID49IFRlc3RJbnB1dC5jb3JyZWN0ZWQuY3VycmVudC5sZW5ndGgpIHtcbiAgICAgICAgVGVzdElucHV0LmNvcnJlY3RlZC5jdXJyZW50ICs9ICdfJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIFRlc3RJbnB1dC5jb3JyZWN0ZWQuY3VycmVudCA9XG4gICAgICAgICAgVGVzdElucHV0LmNvcnJlY3RlZC5jdXJyZW50LnN1YnN0cmluZygwLCBjaWwpICtcbiAgICAgICAgICAnXycgK1xuICAgICAgICAgIFRlc3RJbnB1dC5jb3JyZWN0ZWQuY3VycmVudC5zdWJzdHJpbmcoY2lsICsgMSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChDb25maWcuc3RvcE9uRXJyb3IgIT0gJ29mZicpIHtcbiAgICAgIGlmIChDb25maWcuZGlmZmljdWx0eSA9PSAnZXhwZXJ0JyB8fCBDb25maWcuZGlmZmljdWx0eSA9PSAnbWFzdGVyJykge1xuICAgICAgICAvL2ZhaWxlZCBkdWUgdG8gZGlmZiB3aGVuIHByZXNzaW5nIHNwYWNlXG4gICAgICAgIFRlc3RMb2dpYy5mYWlsKCdkaWZmaWN1bHR5Jyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChDb25maWcuc3RvcE9uRXJyb3IgPT0gJ3dvcmQnKSB7XG4gICAgICAgIGRvbnRJbnNlcnRTcGFjZSA9IGZhbHNlO1xuICAgICAgICBSZXBsYXkuYWRkUmVwbGF5RXZlbnQoJ2luY29ycmVjdExldHRlcicsICdfJyk7XG4gICAgICAgIFRlc3RVSS51cGRhdGVXb3JkRWxlbWVudCh0cnVlKTtcbiAgICAgICAgQ2FyZXQudXBkYXRlUG9zaXRpb24oKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgVGVzdElucHV0LmlucHV0LnB1c2hIaXN0b3J5KCk7XG4gICAgVGVzdFVJLmhpZ2hsaWdodEJhZFdvcmQoVGVzdFVJLmN1cnJlbnRXb3JkRWxlbWVudEluZGV4LCAhQ29uZmlnLmJsaW5kTW9kZSk7XG4gICAgVGVzdFdvcmRzLndvcmRzLmluY3JlYXNlQ3VycmVudEluZGV4KCk7XG4gICAgVGVzdFVJLnNldEN1cnJlbnRXb3JkRWxlbWVudEluZGV4KFRlc3RVSS5jdXJyZW50V29yZEVsZW1lbnRJbmRleCArIDEpO1xuICAgIFRlc3RVSS51cGRhdGVBY3RpdmVFbGVtZW50KCk7XG4gICAgQ2FyZXQudXBkYXRlUG9zaXRpb24oKTtcbiAgICBUZXN0SW5wdXQuaW5jcmVtZW50S2V5cHJlc3NDb3VudCgpO1xuICAgIFRlc3RJbnB1dC5wdXNoS2V5cHJlc3NXb3JkKFRlc3RXb3Jkcy53b3Jkcy5jdXJyZW50SW5kZXgpO1xuICAgIFRlc3RJbnB1dC51cGRhdGVMYXN0S2V5cHJlc3MoKTtcbiAgICBpZiAoQ29uZmlnLmRpZmZpY3VsdHkgPT0gJ2V4cGVydCcgfHwgQ29uZmlnLmRpZmZpY3VsdHkgPT0gJ21hc3RlcicpIHtcbiAgICAgIFRlc3RMb2dpYy5mYWlsKCdkaWZmaWN1bHR5Jyk7XG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIGlmIChUZXN0V29yZHMud29yZHMuY3VycmVudEluZGV4ID09IFRlc3RXb3Jkcy53b3Jkcy5sZW5ndGgpIHtcbiAgICAgIC8vc3VibWl0dGVkIGxhc3Qgd29yZCB0aGF0IGlzIGluY29ycmVjdFxuICAgICAgVGVzdExvZ2ljLmZpbmlzaCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBSZXBsYXkuYWRkUmVwbGF5RXZlbnQoJ3N1Ym1pdEVycm9yV29yZCcpO1xuICB9XG5cbiAgbGV0IHdvcmRMZW5ndGg7XG4gIGlmIChDb25maWcubW9kZSA9PT0gJ3plbicpIHtcbiAgICB3b3JkTGVuZ3RoID0gVGVzdElucHV0LmlucHV0LmN1cnJlbnQubGVuZ3RoO1xuICB9IGVsc2Uge1xuICAgIHdvcmRMZW5ndGggPSBUZXN0V29yZHMud29yZHMuZ2V0Q3VycmVudCgpLmxlbmd0aDtcbiAgfVxuXG4gIGNvbnN0IGZsZXggPSBNaXNjLndob3JmKENvbmZpZy5taW5CdXJzdEN1c3RvbVNwZWVkLCB3b3JkTGVuZ3RoKTtcblxuICBUZXN0SW5wdXQuY29ycmVjdGVkLnB1c2hIaXN0b3J5KCk7XG5cbiAgaWYgKFxuICAgICFDb25maWcuc2hvd0FsbExpbmVzIHx8XG4gICAgQ29uZmlnLm1vZGUgPT0gJ3RpbWUnIHx8XG4gICAgKEN1c3RvbVRleHQuaXNXb3JkUmFuZG9tICYmIEN1c3RvbVRleHQud29yZCA9PSAwKSB8fFxuICAgIEN1c3RvbVRleHQuaXNUaW1lUmFuZG9tXG4gICkge1xuICAgIGNvbnN0IGN1cnJlbnRUb3AgPSBNYXRoLmZsb29yKFxuICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbDxIVE1MRWxlbWVudD4oJyN3b3JkcyAud29yZCcpW1Rlc3RVSS5jdXJyZW50V29yZEVsZW1lbnRJbmRleCAtIDFdXG4gICAgICAgIC5vZmZzZXRUb3BcbiAgICApO1xuICAgIGxldCBuZXh0VG9wO1xuICAgIHRyeSB7XG4gICAgICBuZXh0VG9wID0gTWF0aC5mbG9vcihcbiAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbDxIVE1MRWxlbWVudD4oJyN3b3JkcyAud29yZCcpW1Rlc3RVSS5jdXJyZW50V29yZEVsZW1lbnRJbmRleF1cbiAgICAgICAgICAub2Zmc2V0VG9wXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIG5leHRUb3AgPSAwO1xuICAgIH1cblxuICAgIGlmIChuZXh0VG9wID4gY3VycmVudFRvcCAmJiAhVGVzdFVJLmxpbmVUcmFuc2l0aW9uKSB7XG4gICAgICBUZXN0VUkubGluZUp1bXAoY3VycmVudFRvcCk7XG4gICAgfVxuICB9IC8vZW5kIG9mIGxpbmUgd3JhcFxuXG4gIGlmIChcbiAgICBDb25maWcubW9kZSA9PT0gJ3dvcmRzJyB8fFxuICAgIENvbmZpZy5tb2RlID09PSAnY3VzdG9tJyB8fFxuICAgIENvbmZpZy5tb2RlID09PSAncXVvdGUnIHx8XG4gICAgQ29uZmlnLm1vZGUgPT09ICd6ZW4nXG4gICkge1xuICAgIFRpbWVyUHJvZ3Jlc3MudXBkYXRlKCk7XG4gIH1cbiAgaWYgKFxuICAgIENvbmZpZy5tb2RlID09ICd0aW1lJyB8fFxuICAgIENvbmZpZy5tb2RlID09ICd3b3JkcycgfHxcbiAgICBDb25maWcubW9kZSA9PSAnY3VzdG9tJyB8fFxuICAgIENvbmZpZy5tb2RlID09ICdxdW90ZSdcbiAgKSB7XG4gICAgVGVzdExvZ2ljLmFkZFdvcmQoKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpc0NoYXJDb3JyZWN0KGNoYXI6IHN0cmluZywgY2hhckluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgaWYgKCFjb3JyZWN0U2hpZnRVc2VkKSByZXR1cm4gZmFsc2U7XG5cbiAgaWYgKENvbmZpZy5tb2RlID09ICd6ZW4nKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBjb25zdCBvcmlnaW5hbENoYXIgPSBUZXN0V29yZHMud29yZHMuZ2V0Q3VycmVudCgpW2NoYXJJbmRleF07XG5cbiAgaWYgKG9yaWdpbmFsQ2hhciA9PSBjaGFyKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBpZiAoQ29uZmlnLmxhbmd1YWdlLnNwbGl0KCdfJylbMF0gPT0gJ3J1c3NpYW4nKSB7XG4gICAgaWYgKChjaGFyID09PSAn0LUnIHx8IGNoYXIgPT09ICdlJykgJiYgb3JpZ2luYWxDaGFyID09ICfRkScpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoY2hhciA9PT0gJ9GRJyAmJiAob3JpZ2luYWxDaGFyID09ICfQtScgfHwgb3JpZ2luYWxDaGFyID09PSAnZScpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoQ29uZmlnLmZ1bmJveCA9PT0gJ2Fycm93cycpIHtcbiAgICBpZiAoKGNoYXIgPT09ICd3JyB8fCBjaGFyID09PSAnQXJyb3dVcCcpICYmIG9yaWdpbmFsQ2hhciA9PSAn4oaRJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmICgoY2hhciA9PT0gJ3MnIHx8IGNoYXIgPT09ICdBcnJvd0Rvd24nKSAmJiBvcmlnaW5hbENoYXIgPT0gJ+KGkycpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoKGNoYXIgPT09ICdhJyB8fCBjaGFyID09PSAnQXJyb3dMZWZ0JykgJiYgb3JpZ2luYWxDaGFyID09ICfihpAnKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKChjaGFyID09PSAnZCcgfHwgY2hhciA9PT0gJ0Fycm93UmlnaHQnKSAmJiBvcmlnaW5hbENoYXIgPT0gJ+KGkicpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGlmIChcbiAgICAoY2hhciA9PT0gYOKAmWAgfHwgY2hhciA9PT0gJ+KAmCcgfHwgY2hhciA9PT0gXCInXCIpICYmXG4gICAgKG9yaWdpbmFsQ2hhciA9PSBg4oCZYCB8fCBvcmlnaW5hbENoYXIgPT09ICfigJgnIHx8IG9yaWdpbmFsQ2hhciA9PT0gXCInXCIpXG4gICkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgaWYgKFxuICAgIChjaGFyID09PSBgXCJgIHx8IGNoYXIgPT09ICfigJ0nIHx8IGNoYXIgPT0gJ+KAnCcgfHwgY2hhciA9PT0gJ+KAnicpICYmXG4gICAgKG9yaWdpbmFsQ2hhciA9PSBgXCJgIHx8IG9yaWdpbmFsQ2hhciA9PT0gJ+KAnScgfHwgb3JpZ2luYWxDaGFyID09PSAn4oCcJyB8fCBvcmlnaW5hbENoYXIgPT09ICfigJ4nKVxuICApIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGlmIChcbiAgICAoY2hhciA9PT0gJ+KAkycgfHwgY2hhciA9PT0gJ+KAlCcgfHwgY2hhciA9PSAnLScpICYmXG4gICAgKG9yaWdpbmFsQ2hhciA9PSAnLScgfHwgb3JpZ2luYWxDaGFyID09PSAn4oCTJyB8fCBvcmlnaW5hbENoYXIgPT09ICfigJQnKVxuICApIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlQ2hhcihjaGFyOiBzdHJpbmcsIGNoYXJJbmRleDogbnVtYmVyKTogdm9pZCB7XG4gIGlmIChUZXN0VUkucmVzdWx0Q2FsY3VsYXRpbmcgfHwgVGVzdFVJLnJlc3VsdFZpc2libGUpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoY2hhciA9PT0gJ+KApicpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgaGFuZGxlQ2hhcignLicsIGNoYXJJbmRleCArIGkpO1xuICAgIH1cblxuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChjaGFyID09PSAnXFxuJyAmJiAoQ29uZmlnLmZ1bmJveCA9PT0gJzU4MDA4JyB8fCBDb25maWcuZnVuYm94ID09PSAndGVuS2V5TW9kZScpKSB7XG4gICAgY2hhciA9ICcgJztcbiAgfVxuXG4gIGlmIChjaGFyICE9PSAnXFxuJyAmJiBjaGFyICE9PSAnXFx0JyAmJiAvXFxzLy50ZXN0KGNoYXIpKSB7XG4gICAgaWYgKENvbmZpZy5mdW5ib3ggPT09ICdub3NwYWNlJyB8fCBDb25maWcuZnVuYm94ID09PSAnYXJyb3dzJykgcmV0dXJuO1xuICAgIGhhbmRsZVNwYWNlKCk7XG5cbiAgICAvL2luc2VydCBzcGFjZSBmb3IgZXhwZXJ0IGFuZCBtYXN0ZXIgb3Igc3RyaWN0IHNwYWNlLFxuICAgIC8vb3IgZm9yIHN0b3Agb24gZXJyb3Igc2V0IHRvIHdvcmQsXG4gICAgLy9vdGhlcndpc2UgZG9udCBkbyBhbnl0aGluZ1xuICAgIGlmIChcbiAgICAgIENvbmZpZy5kaWZmaWN1bHR5ICE9PSAnbm9ybWFsJyB8fFxuICAgICAgKENvbmZpZy5zdHJpY3RTcGFjZSAmJiBDb25maWcubW9kZSAhPT0gJ3plbicpIHx8XG4gICAgICBDb25maWcuc3RvcE9uRXJyb3IgPT09ICd3b3JkJ1xuICAgICkge1xuICAgICAgaWYgKGRvbnRJbnNlcnRTcGFjZSkge1xuICAgICAgICBkb250SW5zZXJ0U3BhY2UgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG5cbiAgaWYgKENvbmZpZy5tb2RlICE9PSAnemVuJyAmJiBUZXN0V29yZHMud29yZHMuZ2V0Q3VycmVudCgpW2NoYXJJbmRleF0gIT09ICdcXG4nICYmIGNoYXIgPT09ICdcXG4nKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy9zdGFydCB0aGUgdGVzdFxuICBpZiAoIVRlc3RBY3RpdmUuZ2V0KCkgJiYgIVRlc3RMb2dpYy5zdGFydFRlc3QoKSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIEZvY3VzLnNldCh0cnVlKTtcbiAgQ2FyZXQuc3RvcEFuaW1hdGlvbigpO1xuXG4gIGNvbnN0IHRoaXNDaGFyQ29ycmVjdCA9IGlzQ2hhckNvcnJlY3QoY2hhciwgY2hhckluZGV4KTtcblxuICBpZiAodGhpc0NoYXJDb3JyZWN0ICYmIENvbmZpZy5tb2RlICE9PSAnemVuJykge1xuICAgIGNoYXIgPSBUZXN0V29yZHMud29yZHMuZ2V0Q3VycmVudCgpLmNoYXJBdChjaGFySW5kZXgpO1xuICB9XG5cbiAgaWYgKCF0aGlzQ2hhckNvcnJlY3QgJiYgY2hhciA9PT0gJ1xcbicpIHtcbiAgICBpZiAoVGVzdElucHV0LmlucHV0LmN1cnJlbnQgPT09ICcnKSByZXR1cm47XG4gICAgY2hhciA9ICcgJztcbiAgfVxuXG4gIGlmIChUZXN0SW5wdXQuaW5wdXQuY3VycmVudCA9PT0gJycpIHtcbiAgICBUZXN0SW5wdXQuc2V0QnVyc3RTdGFydChwZXJmb3JtYW5jZS5ub3coKSk7XG4gIH1cblxuICBjb25zdCByZXN1bHRpbmdXb3JkID1cbiAgICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5zdWJzdHJpbmcoMCwgY2hhckluZGV4KSArXG4gICAgY2hhciArXG4gICAgVGVzdElucHV0LmlucHV0LmN1cnJlbnQuc3Vic3RyaW5nKGNoYXJJbmRleCArIDEpO1xuXG4gIC8vIElmIGEgdHJhaWxpbmcgY29tcG9zZWQgY2hhciBpcyB1c2VkLCBpZ25vcmUgaXQgd2hlbiBjb3VudGluZyBhY2N1cmFjeVxuICBpZiAoXG4gICAgIXRoaXNDaGFyQ29ycmVjdCAmJlxuICAgIE1pc2MudHJhaWxpbmdDb21wb3NlQ2hhcnMudGVzdChyZXN1bHRpbmdXb3JkKSAmJlxuICAgIENvbXBvc2l0aW9uU3RhdGUuZ2V0Q29tcG9zaW5nKClcbiAgKSB7XG4gICAgVGVzdElucHV0LmlucHV0LmN1cnJlbnQgPSByZXN1bHRpbmdXb3JkO1xuICAgIFRlc3RVSS51cGRhdGVXb3JkRWxlbWVudCgpO1xuICAgIENhcmV0LnVwZGF0ZVBvc2l0aW9uKCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gTW9ua2V5UG93ZXIuYWRkUG93ZXIodGhpc0NoYXJDb3JyZWN0KTtcbiAgVGVzdElucHV0LmluY3JlbWVudEFjY3VyYWN5KHRoaXNDaGFyQ29ycmVjdCk7XG5cbiAgaWYgKCF0aGlzQ2hhckNvcnJlY3QpIHtcbiAgICBUZXN0SW5wdXQuaW5jcmVtZW50S2V5cHJlc3NFcnJvcnMoKTtcbiAgICBUZXN0SW5wdXQucHVzaE1pc3NlZFdvcmQoVGVzdFdvcmRzLndvcmRzLmdldEN1cnJlbnQoKSk7XG4gIH1cblxuICBXZWFrU3BvdC51cGRhdGVTY29yZShcbiAgICBDb25maWcubW9kZSA9PT0gJ3plbicgPyBjaGFyIDogVGVzdFdvcmRzLndvcmRzLmdldEN1cnJlbnQoKVtjaGFySW5kZXhdLFxuICAgIHRoaXNDaGFyQ29ycmVjdFxuICApO1xuXG4gIGlmICghY29ycmVjdFNoaWZ0VXNlZCAmJiBDb25maWcuZGlmZmljdWx0eSAhPSAnbWFzdGVyJykgcmV0dXJuO1xuXG4gIC8vdXBkYXRlIGN1cnJlbnQgY29ycmVjdGVkIHZlcnNpb24uIGlmIGl0cyBlbXB0eSB0aGVuIGFkZCB0aGUgY3VycmVudCBjaGFyLiBpZiBpdHMgbm90IHRoZW4gcmVwbGFjZSB0aGUgbGFzdCBjaGFyYWN0ZXIgd2l0aCB0aGUgY3VycmVudGx5IHByZXNzZWQgb25lIC8gYWRkIGl0XG4gIGlmIChUZXN0SW5wdXQuY29ycmVjdGVkLmN1cnJlbnQgPT09ICcnKSB7XG4gICAgVGVzdElucHV0LmNvcnJlY3RlZC5jdXJyZW50ICs9IHJlc3VsdGluZ1dvcmQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKGNoYXJJbmRleCA+PSBUZXN0SW5wdXQuY29ycmVjdGVkLmN1cnJlbnQubGVuZ3RoKSB7XG4gICAgICBUZXN0SW5wdXQuY29ycmVjdGVkLmN1cnJlbnQgKz0gY2hhcjtcbiAgICB9IGVsc2UgaWYgKCF0aGlzQ2hhckNvcnJlY3QpIHtcbiAgICAgIFRlc3RJbnB1dC5jb3JyZWN0ZWQuY3VycmVudCA9XG4gICAgICAgIFRlc3RJbnB1dC5jb3JyZWN0ZWQuY3VycmVudC5zdWJzdHJpbmcoMCwgY2hhckluZGV4KSArXG4gICAgICAgIGNoYXIgK1xuICAgICAgICBUZXN0SW5wdXQuY29ycmVjdGVkLmN1cnJlbnQuc3Vic3RyaW5nKGNoYXJJbmRleCArIDEpO1xuICAgIH1cbiAgfVxuXG4gIFRlc3RJbnB1dC5pbmNyZW1lbnRLZXlwcmVzc0NvdW50KCk7XG4gIFRlc3RJbnB1dC51cGRhdGVMYXN0S2V5cHJlc3MoKTtcbiAgVGVzdElucHV0LnB1c2hLZXlwcmVzc1dvcmQoVGVzdFdvcmRzLndvcmRzLmN1cnJlbnRJbmRleCk7XG5cbiAgaWYgKENvbmZpZy5kaWZmaWN1bHR5ICE9PSAnbWFzdGVyJyAmJiBDb25maWcuc3RvcE9uRXJyb3IgPT0gJ2xldHRlcicgJiYgIXRoaXNDaGFyQ29ycmVjdCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIFJlcGxheS5hZGRSZXBsYXlFdmVudCh0aGlzQ2hhckNvcnJlY3QgPyAnY29ycmVjdExldHRlcicgOiAnaW5jb3JyZWN0TGV0dGVyJywgY2hhcik7XG5cbiAgLy91cGRhdGUgdGhlIGFjdGl2ZSB3b3JkIHRvcCwgYnV0IG9ubHkgb25jZVxuICBpZiAoVGVzdElucHV0LmlucHV0LmN1cnJlbnQubGVuZ3RoID09PSAxICYmIFRlc3RXb3Jkcy53b3Jkcy5jdXJyZW50SW5kZXggPT09IDApIHtcbiAgICBUZXN0VUkuc2V0QWN0aXZlV29yZFRvcCgoPEhUTUxFbGVtZW50PmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyN3b3JkcyAuYWN0aXZlJykpPy5vZmZzZXRUb3ApO1xuICB9XG5cbiAgLy9tYXggbGVuZ3RoIG9mIHRoZSBpbnB1dCBpcyAyMCB1bmxlc3MgaW4gemVuIG1vZGUgdGhlbiBpdHMgMzBcbiAgaWYgKFxuICAgIChDb25maWcubW9kZSA9PT0gJ3plbicgJiYgY2hhckluZGV4IDwgMzApIHx8XG4gICAgKENvbmZpZy5tb2RlICE9PSAnemVuJyAmJiBjaGFySW5kZXggPCBUZXN0V29yZHMud29yZHMuZ2V0Q3VycmVudCgpLmxlbmd0aCArIDIwKVxuICApIHtcbiAgICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudCA9IHJlc3VsdGluZ1dvcmQ7XG4gIH1cblxuICBpZiAoIXRoaXNDaGFyQ29ycmVjdCAmJiBDb25maWcuZGlmZmljdWx0eSA9PSAnbWFzdGVyJykge1xuICAgIFRlc3RJbnB1dC5pbnB1dC5wdXNoSGlzdG9yeSgpO1xuICAgIFRlc3RJbnB1dC5jb3JyZWN0ZWQucHVzaEhpc3RvcnkoKTtcbiAgICBUZXN0TG9naWMuZmFpbCgnZGlmZmljdWx0eScpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChDb25maWcubW9kZSAhPSAnemVuJykge1xuICAgIC8vbm90IGFwcGxpY2FibGUgdG8gemVuIG1vZGVcbiAgICAvL2F1dG8gc3RvcCB0aGUgdGVzdCBpZiB0aGUgbGFzdCB3b3JkIGlzIGNvcnJlY3RcbiAgICBjb25zdCBjdXJyZW50V29yZCA9IFRlc3RXb3Jkcy53b3Jkcy5nZXRDdXJyZW50KCk7XG4gICAgY29uc3QgbGFzdGluZGV4ID0gVGVzdFdvcmRzLndvcmRzLmN1cnJlbnRJbmRleDtcbiAgICBpZiAoXG4gICAgICAoY3VycmVudFdvcmQgPT0gVGVzdElucHV0LmlucHV0LmN1cnJlbnQgfHxcbiAgICAgICAgKENvbmZpZy5xdWlja0VuZCAmJlxuICAgICAgICAgIGN1cnJlbnRXb3JkLmxlbmd0aCA9PSBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5sZW5ndGggJiZcbiAgICAgICAgICBDb25maWcuc3RvcE9uRXJyb3IgPT0gJ29mZicpKSAmJlxuICAgICAgbGFzdGluZGV4ID09IFRlc3RXb3Jkcy53b3Jkcy5sZW5ndGggLSAxXG4gICAgKSB7XG4gICAgICBUZXN0SW5wdXQuaW5wdXQucHVzaEhpc3RvcnkoKTtcbiAgICAgIFRlc3RJbnB1dC5jb3JyZWN0ZWQucHVzaEhpc3RvcnkoKTtcbiAgICAgIFRlc3RMb2dpYy5maW5pc2goKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cblxuICBjb25zdCBhY3RpdmVXb3JkVG9wQmVmb3JlSnVtcCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTEVsZW1lbnQ+KCcjd29yZHMgLndvcmQuYWN0aXZlJylcbiAgICA/Lm9mZnNldFRvcCBhcyBudW1iZXI7XG4gIFRlc3RVSS51cGRhdGVXb3JkRWxlbWVudCgpO1xuXG4gIGlmICghQ29uZmlnLmhpZGVFeHRyYUxldHRlcnMpIHtcbiAgICBjb25zdCBuZXdBY3RpdmVUb3AgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxFbGVtZW50PignI3dvcmRzIC53b3JkLmFjdGl2ZScpXG4gICAgICA/Lm9mZnNldFRvcCBhcyBudW1iZXI7XG4gICAgLy9zdG9wIHRoZSB3b3JkIGp1bXAgYnkgc2xpY2luZyBvZmYgdGhlIGxhc3QgY2hhcmFjdGVyLCB1cGRhdGUgd29yZCBhZ2FpblxuICAgIGlmIChcbiAgICAgIGFjdGl2ZVdvcmRUb3BCZWZvcmVKdW1wIDwgbmV3QWN0aXZlVG9wICYmXG4gICAgICAhVGVzdFVJLmxpbmVUcmFuc2l0aW9uICYmXG4gICAgICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5sZW5ndGggPiAxXG4gICAgKSB7XG4gICAgICBpZiAoQ29uZmlnLm1vZGUgPT0gJ3plbicpIHtcbiAgICAgICAgY29uc3QgY3VycmVudFRvcCA9IE1hdGguZmxvb3IoXG4gICAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbDxIVE1MRWxlbWVudD4oJyN3b3JkcyAud29yZCcpW1Rlc3RVSS5jdXJyZW50V29yZEVsZW1lbnRJbmRleCAtIDFdXG4gICAgICAgICAgICA/Lm9mZnNldFRvcFxuICAgICAgICApIGFzIG51bWJlcjtcbiAgICAgICAgaWYgKCFDb25maWcuc2hvd0FsbExpbmVzKSBUZXN0VUkubGluZUp1bXAoY3VycmVudFRvcCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudCA9IFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50LnNsaWNlKDAsIC0xKTtcbiAgICAgICAgVGVzdFVJLnVwZGF0ZVdvcmRFbGVtZW50KCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy9zaW11bGF0ZSBzcGFjZSBwcmVzcyBpbiBub3NwYWNlIGZ1bmJveFxuICBpZiAoXG4gICAgKChDb25maWcuZnVuYm94ID09PSAnbm9zcGFjZScgfHwgQ29uZmlnLmZ1bmJveCA9PT0gJ2Fycm93cycpICYmXG4gICAgICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5sZW5ndGggPT09IFRlc3RXb3Jkcy53b3Jkcy5nZXRDdXJyZW50KCkubGVuZ3RoKSB8fFxuICAgIChjaGFyID09PSAnXFxuJyAmJiB0aGlzQ2hhckNvcnJlY3QpXG4gICkge1xuICAgIGhhbmRsZVNwYWNlKCk7XG4gIH1cblxuICBpZiAoY2hhciAhPT0gJ1xcbicpIHtcbiAgICBDYXJldC51cGRhdGVQb3NpdGlvbigpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGhhbmRsZVRhYihcbiAgZXZlbnQ6IHsgcHJldmVudERlZmF1bHQ6ICgpID0+IHZvaWQ7IHNoaWZ0S2V5OiBhbnkgfSxcbiAgcG9wdXBWaXNpYmxlOiBib29sZWFuXG4pOiB2b2lkIHtcbiAgaWYgKFRlc3RVSS5yZXN1bHRDYWxjdWxhdGluZykge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgbGV0IHNob3VsZEluc2VydFRhYkNoYXJhY3RlciA9IGZhbHNlO1xuXG4gIGlmICgoQ29uZmlnLm1vZGUgPT0gJ3plbicgJiYgIWV2ZW50LnNoaWZ0S2V5KSB8fCAoVGVzdFdvcmRzLmhhc1RhYiAmJiAhZXZlbnQuc2hpZnRLZXkpKSB7XG4gICAgc2hvdWxkSW5zZXJ0VGFiQ2hhcmFjdGVyID0gdHJ1ZTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0V29yZHNJbnB1dEVsZW1lbnQod29yZHNFbGVtZW50OiBIVE1MSW5wdXRFbGVtZW50KSB7XG4gIHdvcmRzSW5wdXQgPSB3b3Jkc0VsZW1lbnQ7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnB1dEtleWRvd24oZXZlbnQ6IGFueSwgd29yZHNGb2N1c2VkOiBib29sZWFuKSB7XG4gIGNvbnN0IGFsbG93VHlwaW5nID0gIVRlc3RVSS5yZXN1bHRWaXNpYmxlICYmICh3b3Jkc0ZvY3VzZWQgfHwgZXZlbnQua2V5ICE9PSAnRW50ZXInKTtcblxuICAvL25vIHNwYWNlIGZvciB0ZW5LZXlNb2RlXG4gIGlmIChDb25maWcuZnVuYm94ID09PSAndGVuS2V5TW9kZScgJiYgZXZlbnQua2V5Q29kZSA9PT0gMzIpIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICB9XG5cbiAgaWYgKGFsbG93VHlwaW5nICYmICF3b3Jkc0ZvY3VzZWQgJiYgZXZlbnQua2V5ICE9PSAnRW50ZXInKSB7XG4gICAgVGVzdFVJLmZvY3VzV29yZHMoKTtcbiAgICBpZiAoQ29uZmlnLnNob3dPdXRPZkZvY3VzV2FybmluZykge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG4gIH1cblxuICAvL3RhYlxuICBpZiAoZXZlbnQua2V5ID09ICdUYWInKSB7XG4gICAgaGFuZGxlVGFiKGV2ZW50LCBmYWxzZSk7XG4gIH1cblxuICBpZiAoIWFsbG93VHlwaW5nKSByZXR1cm47XG5cbiAgaWYgKCFldmVudC5pc1RydXN0ZWQgfHwgVGVzdFVJLnRlc3RSZXN0YXJ0aW5nKSB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoVGVzdElucHV0LnNwYWNpbmdEZWJ1Zykge1xuICAgIGNvbnNvbGUubG9nKFxuICAgICAgJ3NwYWNpbmcgZGVidWcnLFxuICAgICAgJ2tleXByZXNzJyxcbiAgICAgIGV2ZW50LmtleSxcbiAgICAgICdsZW5ndGgnLFxuICAgICAgVGVzdElucHV0LmtleXByZXNzVGltaW5ncy5zcGFjaW5nLmFycmF5Lmxlbmd0aFxuICAgICk7XG4gIH1cbiAgVGVzdElucHV0LnJlY29yZEtleXByZXNzU3BhY2luZygpO1xuICBUZXN0SW5wdXQuc2V0S2V5cHJlc3NEdXJhdGlvbihwZXJmb3JtYW5jZS5ub3coKSk7XG4gIFRlc3RJbnB1dC5zZXRLZXlwcmVzc05vdEFmaygpO1xuXG4gIC8vYmxvY2tpbmcgZmlyZWZveCBmcm9tIGdvaW5nIGJhY2sgaW4gaGlzdG9yeSB3aXRoIGJhY2tzcGFjZVxuICBpZiAoZXZlbnQua2V5ID09PSAnQmFja3NwYWNlJykge1xuICAgIGNvbnN0IHQgPSAvSU5QVVR8U0VMRUNUfFRFWFRBUkVBL2k7XG4gICAgaWYgKCF0LnRlc3QoKGV2ZW50LnRhcmdldCBhcyB1bmtub3duIGFzIEVsZW1lbnQpLnRhZ05hbWUpKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIGlmIChDb25maWcuY29uZmlkZW5jZU1vZGUgPT09ICdtYXgnKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuXG4gIGlmIChDb25maWcuZnVuYm94ICE9PSAnYXJyb3dzJyAmJiAvQXJyb3cvaS50ZXN0KGV2ZW50LmtleSkpIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChldmVudC5rZXkgPT09ICdCYWNrc3BhY2UnICYmIFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50Lmxlbmd0aCA9PT0gMCkge1xuICAgIGJhY2tzcGFjZVRvUHJldmlvdXMoKTtcbiAgICBpZiAoVGVzdElucHV0LmlucHV0LmN1cnJlbnQpIHtcbiAgICAgIHNldFdvcmRzSW5wdXQoJyAnICsgVGVzdElucHV0LmlucHV0LmN1cnJlbnQgKyAnICcpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChldmVudC5rZXkgPT09ICdFbnRlcicpIHtcbiAgICBpZiAoZXZlbnQuc2hpZnRLZXkgJiYgQ29uZmlnLm1vZGUgPT0gJ3plbicpIHtcbiAgICAgIFRlc3RMb2dpYy5maW5pc2goKTtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgZXZlbnQuc2hpZnRLZXkgJiZcbiAgICAgICgoQ29uZmlnLm1vZGUgPT0gJ3RpbWUnICYmIENvbmZpZy50aW1lID09PSAwKSB8fFxuICAgICAgICAoQ29uZmlnLm1vZGUgPT0gJ3dvcmRzJyAmJiBDb25maWcud29yZHMgPT09IDApKVxuICAgICkge1xuICAgICAgVGVzdElucHV0LnNldEJhaWxvdXQodHJ1ZSk7XG4gICAgICBUZXN0TG9naWMuZmluaXNoKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGhhbmRsZUNoYXIoJ1xcbicsIFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50Lmxlbmd0aCk7XG4gICAgICBzZXRXb3Jkc0lucHV0KCcgJyArIFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50KTtcbiAgICB9XG4gIH1cblxuICAvL3Nob3cgZGVhZCBrZXlzXG4gIGlmIChldmVudC5rZXkgPT09ICdEZWFkJyAmJiAhQ29tcG9zaXRpb25TdGF0ZS5nZXRDb21wb3NpbmcoKSkge1xuICAgIGNvbnN0IHdvcmQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxFbGVtZW50PignI3dvcmRzIC53b3JkLmFjdGl2ZScpO1xuICAgIGNvbnN0IGxlbiA9IFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50Lmxlbmd0aDsgLy8gaGF2ZSB0byBkbyB0aGlzIGJlY2F1c2UgcHJldHRpZXIgd3JhcHMgdGhlIGxpbmUgYW5kIGNhdXNlcyBhbiBlcnJvclxuXG4gICAgLy8gQ2hlY2sgdG8gc2VlIGlmIHRoZSBsZXR0ZXIgYWN0dWFsbHkgZXhpc3RzIHRvIHRvZ2dsZSBpdCBhcyBkZWFkXG4gICAgY29uc3QgZGVhZExldHRlciA9IHdvcmQ/LnF1ZXJ5U2VsZWN0b3JBbGwoJ2xldHRlcicpW2xlbl07XG4gICAgaWYgKGRlYWRMZXR0ZXIpIHtcbiAgICAgIGRlYWRMZXR0ZXIuY2xhc3NMaXN0LnRvZ2dsZSgnZGVhZCcpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChDb25maWcuZnVuYm94ID09PSAnYXJyb3dzJykge1xuICAgIGxldCBjaGFyID0gZXZlbnQua2V5O1xuICAgIGlmIChbJ0Fycm93TGVmdCcsICdBcnJvd1VwJywgJ0Fycm93UmlnaHQnLCAnQXJyb3dEb3duJ10uaW5jbHVkZXMoY2hhcikpIHtcbiAgICAgIGlmIChjaGFyID09PSAnQXJyb3dMZWZ0JykgY2hhciA9ICdhJztcbiAgICAgIGlmIChjaGFyID09PSAnQXJyb3dSaWdodCcpIGNoYXIgPSAnZCc7XG4gICAgICBpZiAoY2hhciA9PT0gJ0Fycm93RG93bicpIGNoYXIgPSAncyc7XG4gICAgICBpZiAoY2hhciA9PT0gJ0Fycm93VXAnKSBjaGFyID0gJ3cnO1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGhhbmRsZUNoYXIoY2hhciwgVGVzdElucHV0LmlucHV0LmN1cnJlbnQubGVuZ3RoKTtcbiAgICAgIHVwZGF0ZVVJKCk7XG4gICAgICBzZXRXb3Jkc0lucHV0KCcgJyArIFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50KTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdvcmRzSW5wdXRLZXl1cChldmVudDogYW55KSB7XG4gIGlmICghZXZlbnQuaXNUcnVzdGVkIHx8IFRlc3RVSS50ZXN0UmVzdGFydGluZykge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKFRlc3RVSS5yZXN1bHRWaXNpYmxlKSByZXR1cm47XG4gIGNvbnN0IG5vdyA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICBpZiAoVGVzdElucHV0LmtleXByZXNzVGltaW5ncy5kdXJhdGlvbi5jdXJyZW50ICE9PSAtMSkge1xuICAgIGNvbnN0IGRpZmYgPSBNYXRoLmFicyhUZXN0SW5wdXQua2V5cHJlc3NUaW1pbmdzLmR1cmF0aW9uLmN1cnJlbnQgLSBub3cpO1xuICAgIFRlc3RJbnB1dC5wdXNoS2V5cHJlc3NEdXJhdGlvbihkaWZmKTtcbiAgfVxuICBUZXN0SW5wdXQuc2V0S2V5cHJlc3NEdXJhdGlvbihub3cpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd29yZHNJbnB1dEJlZm9yZWlucHV0KGV2ZW50OiBhbnkpIHtcbiAgaWYgKCFldmVudC5pc1RydXN0ZWQpIHJldHVybjtcbiAgaWYgKChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWUgPT09ICcnKSB7XG4gICAgKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZSA9ICcgJztcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gd29yZHNJbnB1dElucHV0KGV2ZW50OiBhbnkpIHtcbiAgaWYgKCFldmVudC5pc1RydXN0ZWQgfHwgVGVzdFVJLnRlc3RSZXN0YXJ0aW5nKSB7XG4gICAgKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZSA9ICcgJztcbiAgICByZXR1cm47XG4gIH1cblxuICBUZXN0SW5wdXQuc2V0S2V5cHJlc3NOb3RBZmsoKTtcblxuICBjb25zdCByZWFsSW5wdXRWYWx1ZSA9IChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWUubm9ybWFsaXplKCk7XG4gIGNvbnN0IGlucHV0VmFsdWUgPSByZWFsSW5wdXRWYWx1ZS5zbGljZSgxKTtcblxuICAvLyBpbnB1dCB3aWxsIGJlIG1vZGlmaWVkIGV2ZW4gd2l0aCB0aGUgcHJldmVudERlZmF1bHQoKSBpblxuICAvLyBiZWZvcmVpbnB1dC9rZXlkb3duIGlmIGl0J3MgcGFydCBvZiBhIGNvbXBvc2Ugc2VxdWVuY2UuIHRoaXMgdW5kb2VzXG4gIC8vIHRoZSBlZmZlY3RzIG9mIHRoYXQgYW5kIHRha2VzIHRoZSBpbnB1dCBvdXQgb2YgY29tcG9zZSBtb2RlLlxuICBpZiAoQ29uZmlnLmxheW91dCAhPT0gJ2RlZmF1bHQnICYmIGlucHV0VmFsdWUubGVuZ3RoID49IFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50Lmxlbmd0aCkge1xuICAgIHNldFdvcmRzSW5wdXQoJyAnICsgVGVzdElucHV0LmlucHV0LmN1cnJlbnQpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChyZWFsSW5wdXRWYWx1ZS5sZW5ndGggPT09IDAgJiYgVGVzdElucHV0LmlucHV0LmN1cnJlbnQubGVuZ3RoID09PSAwKSB7XG4gICAgLy8gZmFsbGJhY2sgZm9yIHdoZW4gbm8gQmFja3NwYWNlIGtleWRvd24gZXZlbnQgKG1vYmlsZSlcbiAgICBiYWNrc3BhY2VUb1ByZXZpb3VzKCk7XG4gIH0gZWxzZSBpZiAoaW5wdXRWYWx1ZS5sZW5ndGggPCBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5sZW5ndGgpIHtcbiAgICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudCA9IGlucHV0VmFsdWU7XG4gICAgVGVzdFVJLnVwZGF0ZVdvcmRFbGVtZW50KCk7XG4gICAgQ2FyZXQudXBkYXRlUG9zaXRpb24oKTtcbiAgICBpZiAoIUNvbXBvc2l0aW9uU3RhdGUuZ2V0Q29tcG9zaW5nKCkpIHtcbiAgICAgIFJlcGxheS5hZGRSZXBsYXlFdmVudCgnc2V0TGV0dGVySW5kZXgnLCBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5sZW5ndGgpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChpbnB1dFZhbHVlICE9PSBUZXN0SW5wdXQuaW5wdXQuY3VycmVudCkge1xuICAgIGxldCBkaWZmU3RhcnQgPSAwO1xuICAgIHdoaWxlIChpbnB1dFZhbHVlW2RpZmZTdGFydF0gPT09IFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50W2RpZmZTdGFydF0pIHtcbiAgICAgIGRpZmZTdGFydCsrO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSBkaWZmU3RhcnQ7IGkgPCBpbnB1dFZhbHVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVDaGFyKGlucHV0VmFsdWVbaV0sIGkpO1xuICAgIH1cbiAgfVxuXG4gIHNldFdvcmRzSW5wdXQoJyAnICsgVGVzdElucHV0LmlucHV0LmN1cnJlbnQpO1xuICB1cGRhdGVVSSgpO1xuXG4gIGNvbnN0IHN0YXRlYmVmb3JlID0gQ29tcG9zaXRpb25TdGF0ZS5nZXRDb21wb3NpbmcoKTtcbiAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgLy8gY2hlY2tpbmcgY29tcG9zaXRpb24gc3RhdGUgZHVyaW5nIHRoZSBpbnB1dCBldmVudCBhbmQgb24gdGhlIG5leHQgbG9vcFxuICAgIC8vIHRoaXMgaXMgZG9uZSBiZWNhdXNlIHNvbWUgYnJvd3NlcnMgKGUuZy4gQ2hyb21lKSB3aWxsIGZpcmUgdGhlIGlucHV0XG4gICAgLy8gZXZlbnQgYmVmb3JlIHRoZSBjb21wb3NpdGlvbmVuZCBldmVudC5cbiAgICAvLyB0aGlzIGVuc3VyZXMgdGhlIFVJIGlzIGNvcnJlY3RcblxuICAgIGNvbnN0IHN0YXRlYWZ0ZXIgPSBDb21wb3NpdGlvblN0YXRlLmdldENvbXBvc2luZygpO1xuICAgIGlmIChzdGF0ZWJlZm9yZSAhPT0gc3RhdGVhZnRlcikge1xuICAgICAgVGVzdFVJLnVwZGF0ZVdvcmRFbGVtZW50KCk7XG4gICAgfVxuXG4gICAgLy8gZm9yY2UgY2FyZXQgYXQgZW5kIG9mIGlucHV0XG4gICAgLy8gZG9pbmcgaXQgb24gbmV4dCBjeWNsZSBiZWNhdXNlIENocm9taXVtIG9uIEFuZHJvaWQgd29uJ3QgbGV0IG1lIGVkaXRcbiAgICAvLyB0aGUgc2VsZWN0aW9uIGluc2lkZSB0aGUgaW5wdXQgZXZlbnRcbiAgICBpZiAoXG4gICAgICAoZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQpLnNlbGVjdGlvblN0YXJ0ICE9PVxuICAgICAgICAoZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQpLnZhbHVlLmxlbmd0aCAmJlxuICAgICAgKCFNaXNjLnRyYWlsaW5nQ29tcG9zZUNoYXJzLnRlc3QoKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZSkgfHxcbiAgICAgICAgKChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkuc2VsZWN0aW9uU3RhcnQgPz8gMCkgPFxuICAgICAgICAgIChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWUuc2VhcmNoKE1pc2MudHJhaWxpbmdDb21wb3NlQ2hhcnMpKVxuICAgICkge1xuICAgICAgKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS5zZWxlY3Rpb25TdGFydCA9IChcbiAgICAgICAgZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnRcbiAgICAgICkuc2VsZWN0aW9uRW5kID0gKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZS5sZW5ndGg7XG4gICAgfVxuICB9LCAwKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdvcmRzSW5wdXRGb2N1cyhldmVudDogeyB0YXJnZXQ6IEhUTUxJbnB1dEVsZW1lbnQgfSkge1xuICAoZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQpLnNlbGVjdGlvblN0YXJ0ID0gKFxuICAgIGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50XG4gICkuc2VsZWN0aW9uRW5kID0gKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZS5sZW5ndGg7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3b3Jkc0lucHV0Q29weShldmVudDogeyBwcmV2ZW50RGVmYXVsdDogKCkgPT4gdm9pZCB9KSB7XG4gIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3b3Jkc0lucHV0UGFzdGUoZXZlbnQ6IHsgcHJldmVudERlZmF1bHQ6ICgpID0+IHZvaWQgfSkge1xuICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xufVxuXG4vLyBDb21wb3NpbmcgZXZlbnRzXG5leHBvcnQgZnVuY3Rpb24gd29yZHNJbnB1dENvbXBvc2l0aW9uc3RhcnQoKSB7XG4gIENvbXBvc2l0aW9uU3RhdGUuc2V0Q29tcG9zaW5nKHRydWUpO1xuICBDb21wb3NpdGlvblN0YXRlLnNldFN0YXJ0UG9zKFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50Lmxlbmd0aCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3b3Jkc0lucHV0Q29tcG9zaXRpb25lbmQoKSB7XG4gIENvbXBvc2l0aW9uU3RhdGUuc2V0Q29tcG9zaW5nKGZhbHNlKTtcbn1cbiJdfQ==
|