@testgorilla/tgo-typing-test 1.0.0 → 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/fesm2022/testgorilla-tgo-typing-test.mjs +795 -811
  2. package/fesm2022/testgorilla-tgo-typing-test.mjs.map +1 -1
  3. package/lib/helpers/config.d.ts +4 -4
  4. package/lib/utils/misc.d.ts +0 -1
  5. package/package.json +6 -8
  6. package/esm2022/index.mjs +0 -3
  7. package/esm2022/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.mjs +0 -45
  8. package/esm2022/lib/components/tgo-typing-test/tgo-typing-test.component.mjs +0 -299
  9. package/esm2022/lib/helpers/config.mjs +0 -24
  10. package/esm2022/lib/helpers/constants/default-config.mjs +0 -103
  11. package/esm2022/lib/helpers/controllers/input-controller.mjs +0 -586
  12. package/esm2022/lib/helpers/controllers/quotes-controller.mjs +0 -118
  13. package/esm2022/lib/helpers/observables/config-event.mjs +0 -16
  14. package/esm2022/lib/helpers/observables/timer-event.mjs +0 -16
  15. package/esm2022/lib/helpers/states/active-page.mjs +0 -8
  16. package/esm2022/lib/helpers/states/composition.mjs +0 -20
  17. package/esm2022/lib/helpers/states/page-transition.mjs +0 -8
  18. package/esm2022/lib/helpers/states/slow-timer.mjs +0 -15
  19. package/esm2022/lib/helpers/states/test-active.mjs +0 -8
  20. package/esm2022/lib/helpers/states/time.mjs +0 -11
  21. package/esm2022/lib/helpers/test/caps-warning.mjs +0 -50
  22. package/esm2022/lib/helpers/test/caret.mjs +0 -80
  23. package/esm2022/lib/helpers/test/custom-text.mjs +0 -59
  24. package/esm2022/lib/helpers/test/english-punctuation.mjs +0 -29
  25. package/esm2022/lib/helpers/test/focus.mjs +0 -35
  26. package/esm2022/lib/helpers/test/manual-restart-tracker.mjs +0 -11
  27. package/esm2022/lib/helpers/test/out-of-focus.mjs +0 -14
  28. package/esm2022/lib/helpers/test/replay.mjs +0 -217
  29. package/esm2022/lib/helpers/test/test-input.mjs +0 -264
  30. package/esm2022/lib/helpers/test/test-logic.mjs +0 -927
  31. package/esm2022/lib/helpers/test/test-state.mjs +0 -13
  32. package/esm2022/lib/helpers/test/test-stats.mjs +0 -342
  33. package/esm2022/lib/helpers/test/test-timer.mjs +0 -207
  34. package/esm2022/lib/helpers/test/test-ui.mjs +0 -341
  35. package/esm2022/lib/helpers/test/test-words.mjs +0 -69
  36. package/esm2022/lib/helpers/test/timer-progress.mjs +0 -15
  37. package/esm2022/lib/helpers/test/weak-spot.mjs +0 -65
  38. package/esm2022/lib/helpers/test/wordset.mjs +0 -100
  39. package/esm2022/lib/utils/misc.mjs +0 -673
  40. package/esm2022/testgorilla-tgo-typing-test.mjs +0 -5
@@ -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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5wdXQtY29udHJvbGxlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3Rnby10eXBpbmctdGVzdC9zcmMvbGliL2hlbHBlcnMvY29udHJvbGxlcnMvaW5wdXQtY29udHJvbGxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxNQUFNLE1BQU0saUJBQWlCLENBQUM7QUFDMUMsT0FBTyxLQUFLLFNBQVMsTUFBTSxvQkFBb0IsQ0FBQztBQUNoRCxPQUFPLE1BQXlCLE1BQU0sV0FBVyxDQUFDO0FBQ2xELE9BQU8sS0FBSyxJQUFJLE1BQU0sa0JBQWtCLENBQUM7QUFDekMsT0FBTyxLQUFLLEtBQUssTUFBTSxlQUFlLENBQUM7QUFDdkMsT0FBTyxLQUFLLFVBQVUsTUFBTSxxQkFBcUIsQ0FBQztBQUNsRCxPQUFPLEtBQUssYUFBYSxNQUFNLHdCQUF3QixDQUFDO0FBQ3hELE9BQU8sS0FBSyxLQUFLLE1BQU0sZUFBZSxDQUFDO0FBQ3ZDLE9BQU8sS0FBSyxNQUFNLE1BQU0sZ0JBQWdCLENBQUM7QUFDekMsT0FBTyxLQUFLLFFBQVEsTUFBTSxtQkFBbUIsQ0FBQztBQUM5QyxPQUFPLEtBQUssVUFBVSxNQUFNLHVCQUF1QixDQUFDO0FBQ3BELE9BQU8sS0FBSyxnQkFBZ0IsTUFBTSx1QkFBdUIsQ0FBQztBQUMxRCxPQUFPLEtBQUssU0FBUyxNQUFNLG9CQUFvQixDQUFDO0FBQ2hELE9BQU8sS0FBSyxTQUFTLE1BQU0sb0JBQW9CLENBQUM7QUFFaEQsSUFBSSxlQUFlLEdBQUcsS0FBSyxDQUFDO0FBQzVCLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO0FBRTlCLElBQUksVUFBNEIsQ0FBQztBQUVqQyxTQUFTLGFBQWEsQ0FBQyxLQUFhO0lBQ2xDLCtEQUErRDtJQUMvRCxnRUFBZ0U7SUFDaEUsYUFBYTtJQUNiLElBQUksS0FBSyxLQUFLLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztRQUMvQixVQUFVLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQztJQUMzQixDQUFDO0FBQ0gsQ0FBQztBQUVELFNBQVMsUUFBUTtJQUNmLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLGlCQUFpQixFQUFFLENBQUMsQ0FBQztBQUMzRCxDQUFDO0FBRUQsU0FBUyxtQkFBbUI7SUFDMUIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7UUFBRSxPQUFPO0lBRTlCLElBQUksU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsSUFBSSxNQUFNLENBQUMsdUJBQXVCLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDL0UsT0FBTztJQUNULENBQUM7SUFFRCxJQUNFLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxZQUFZLEdBQUcsQ0FBQyxDQUFDO1FBQ3hELFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsWUFBWSxHQUFHLENBQUMsQ0FBQztRQUNyRCxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUM7UUFDdEIsUUFBUTthQUNMLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUN6QixTQUFTLENBQUMsS0FBSyxDQUFDLFlBQVksR0FBRyxDQUFDLENBQUMsRUFBRSxTQUFTLENBQUMsUUFBUSxDQUFDLFFBQVEsQ0FBQyxFQUNsRSxDQUFDO1FBQ0QsT0FBTztJQUNULENBQUM7SUFFRCxJQUFJLE1BQU0sQ0FBQyxjQUFjLEtBQUssSUFBSSxJQUFJLE1BQU0sQ0FBQyxjQUFjLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDdEUsT0FBTztJQUNULENBQUM7SUFFRCxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ3ZELFNBQVMsQ0FBQyxTQUFTLENBQUMsVUFBVSxFQUFFLENBQUM7SUFDakMsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLFNBQVMsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQzlELFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNqRSxDQUFDO0lBQ0QsU0FBUyxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO0lBQ3ZDLE1BQU0sQ0FBQywwQkFBMEIsQ0FBQyxNQUFNLENBQUMsdUJBQXVCLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDdEUsTUFBTSxDQUFDLG1CQUFtQixDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2pDLE1BQU0sQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO0lBRTNCLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUN2QixNQUFNLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxDQUFDO0FBQ3BDLENBQUM7QUFFRCxTQUFTLFdBQVc7SUFDbEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUU7UUFBRSxPQUFPO0lBRTlCLElBQUksU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLEtBQUssRUFBRTtRQUFFLE9BQU87SUFFM0MsTUFBTSxXQUFXLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUNqRCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssYUFBYSxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssTUFBTSxFQUFFLENBQUM7UUFDOUQsdUtBQXVLO1FBQ3ZLLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxpQkFBaUI7WUFDdEMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDO1lBQ3JDLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxRQUFRLEVBQUUsU0FBUyxDQUFDLENBQUM7UUFDcEMsSUFBSSxLQUFLLEdBQUcsQ0FBQyxDQUFDO1FBQ2QsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFDckMsS0FBSyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxLQUFLLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7SUFDdEYsQ0FBQztJQUNELGVBQWUsR0FBRyxJQUFJLENBQUM7SUFFdkIsTUFBTSxLQUFLLEdBQUcsU0FBUyxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ3pDLFNBQVMsQ0FBQyxrQkFBa0IsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUVwQyw2QkFBNkI7SUFDN0IsTUFBTSxhQUFhLEdBQUcsV0FBVyxJQUFJLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxJQUFJLE1BQU0sQ0FBQyxJQUFJLElBQUksS0FBSyxDQUFDO0lBQ3JGLFNBQVMsQ0FBQyxpQkFBaUIsQ0FBQyxhQUFhLENBQUMsQ0FBQztJQUMzQyxJQUFJLGFBQWEsRUFBRSxDQUFDO1FBQ2xCLFNBQVMsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDOUIsU0FBUyxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsRUFBRSxDQUFDO1FBQ3ZDLE1BQU0sQ0FBQywwQkFBMEIsQ0FBQyxNQUFNLENBQUMsdUJBQXVCLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDdEUsTUFBTSxDQUFDLG1CQUFtQixFQUFFLENBQUM7UUFDN0IsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3ZCLFNBQVMsQ0FBQyxzQkFBc0IsRUFBRSxDQUFDO1FBQ25DLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDO1FBQ3pELE1BQU0sQ0FBQyxjQUFjLENBQUMsbUJBQW1CLENBQUMsQ0FBQztJQUM3QyxDQUFDO1NBQU0sQ0FBQztRQUNOLFNBQVMsQ0FBQyxjQUFjLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQ3ZELFNBQVMsQ0FBQyx1QkFBdUIsRUFBRSxDQUFDO1FBQ3BDLE1BQU0sR0FBRyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztRQUMzQyxJQUFJLEdBQUcsSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDLE1BQU0sRUFBRSxDQUFDO1lBQy9DLElBQUksR0FBRyxJQUFJLFNBQVMsQ0FBQyxTQUFTLENBQUMsT0FBTyxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUM5QyxTQUFTLENBQUMsU0FBUyxDQUFDLE9BQU8sSUFBSSxHQUFHLENBQUM7WUFDckMsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLFNBQVMsQ0FBQyxTQUFTLENBQUMsT0FBTztvQkFDekIsU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUM7d0JBQzdDLEdBQUc7d0JBQ0gsU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUNuRCxDQUFDO1FBQ0gsQ0FBQztRQUNELElBQUksTUFBTSxDQUFDLFdBQVcsSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUNoQyxJQUFJLE1BQU0sQ0FBQyxVQUFVLElBQUksUUFBUSxJQUFJLE1BQU0sQ0FBQyxVQUFVLElBQUksUUFBUSxFQUFFLENBQUM7Z0JBQ25FLHdDQUF3QztnQkFDeEMsU0FBUyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztnQkFDN0IsT0FBTztZQUNULENBQUM7WUFDRCxJQUFJLE1BQU0sQ0FBQyxXQUFXLElBQUksTUFBTSxFQUFFLENBQUM7Z0JBQ2pDLGVBQWUsR0FBRyxLQUFLLENBQUM7Z0JBQ3hCLE1BQU0sQ0FBQyxjQUFjLENBQUMsaUJBQWlCLEVBQUUsR0FBRyxDQUFDLENBQUM7Z0JBQzlDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztnQkFDL0IsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1lBQ3pCLENBQUM7WUFDRCxPQUFPO1FBQ1QsQ0FBQztRQUNELFNBQVMsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDOUIsTUFBTSxDQUFDLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyx1QkFBdUIsRUFBRSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUMzRSxTQUFTLENBQUMsS0FBSyxDQUFDLG9CQUFvQixFQUFFLENBQUM7UUFDdkMsTUFBTSxDQUFDLDBCQUEwQixDQUFDLE1BQU0sQ0FBQyx1QkFBdUIsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUN0RSxNQUFNLENBQUMsbUJBQW1CLEVBQUUsQ0FBQztRQUM3QixLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdkIsU0FBUyxDQUFDLHNCQUFzQixFQUFFLENBQUM7UUFDbkMsU0FBUyxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7UUFDekQsU0FBUyxDQUFDLGtCQUFrQixFQUFFLENBQUM7UUFDL0IsSUFBSSxNQUFNLENBQUMsVUFBVSxJQUFJLFFBQVEsSUFBSSxNQUFNLENBQUMsVUFBVSxJQUFJLFFBQVEsRUFBRSxDQUFDO1lBQ25FLFNBQVMsQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLENBQUM7WUFDN0IsT0FBTztRQUNULENBQUM7YUFBTSxJQUFJLFNBQVMsQ0FBQyxLQUFLLENBQUMsWUFBWSxJQUFJLFNBQVMsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDbEUsdUNBQXVDO1lBQ3ZDLFNBQVMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNuQixPQUFPO1FBQ1QsQ0FBQztRQUNELE1BQU0sQ0FBQyxjQUFjLENBQUMsaUJBQWlCLENBQUMsQ0FBQztJQUMzQyxDQUFDO0lBRUQsSUFBSSxVQUFVLENBQUM7SUFDZixJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssS0FBSyxFQUFFLENBQUM7UUFDMUIsVUFBVSxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQztJQUM5QyxDQUFDO1NBQU0sQ0FBQztRQUNOLFVBQVUsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDLE1BQU0sQ0FBQztJQUNuRCxDQUFDO0lBRUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsbUJBQW1CLEVBQUUsVUFBVSxDQUFDLENBQUM7SUFFaEUsU0FBUyxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztJQUVsQyxJQUNFLENBQUMsTUFBTSxDQUFDLFlBQVk7UUFDcEIsTUFBTSxDQUFDLElBQUksSUFBSSxNQUFNO1FBQ3JCLENBQUMsVUFBVSxDQUFDLFlBQVksSUFBSSxVQUFVLENBQUMsSUFBSSxJQUFJLENBQUMsQ0FBQztRQUNqRCxVQUFVLENBQUMsWUFBWSxFQUN2QixDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FDM0IsUUFBUSxDQUFDLGdCQUFnQixDQUFjLGNBQWMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyx1QkFBdUIsR0FBRyxDQUFDLENBQUM7YUFDdkYsU0FBUyxDQUNiLENBQUM7UUFDRixJQUFJLE9BQU8sQ0FBQztRQUNaLElBQUksQ0FBQztZQUNILE9BQU8sR0FBRyxJQUFJLENBQUMsS0FBSyxDQUNsQixRQUFRLENBQUMsZ0JBQWdCLENBQWMsY0FBYyxDQUFDLENBQUMsTUFBTSxDQUFDLHVCQUF1QixDQUFDO2lCQUNuRixTQUFTLENBQ2IsQ0FBQztRQUNKLENBQUM7UUFBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQ1gsT0FBTyxHQUFHLENBQUMsQ0FBQztRQUNkLENBQUM7UUFFRCxJQUFJLE9BQU8sR0FBRyxVQUFVLElBQUksQ0FBQyxNQUFNLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDbkQsTUFBTSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQztRQUM5QixDQUFDO0lBQ0gsQ0FBQyxDQUFDLGtCQUFrQjtJQUVwQixJQUNFLE1BQU0sQ0FBQyxJQUFJLEtBQUssT0FBTztRQUN2QixNQUFNLENBQUMsSUFBSSxLQUFLLFFBQVE7UUFDeEIsTUFBTSxDQUFDLElBQUksS0FBSyxPQUFPO1FBQ3ZCLE1BQU0sQ0FBQyxJQUFJLEtBQUssS0FBSyxFQUNyQixDQUFDO1FBQ0QsYUFBYSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQ3pCLENBQUM7SUFDRCxJQUNFLE1BQU0sQ0FBQyxJQUFJLElBQUksTUFBTTtRQUNyQixNQUFNLENBQUMsSUFBSSxJQUFJLE9BQU87UUFDdEIsTUFBTSxDQUFDLElBQUksSUFBSSxRQUFRO1FBQ3ZCLE1BQU0sQ0FBQyxJQUFJLElBQUksT0FBTyxFQUN0QixDQUFDO1FBQ0QsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDO0lBQ3RCLENBQUM7QUFDSCxDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsSUFBWSxFQUFFLFNBQWlCO0lBQ3BELElBQUksQ0FBQyxnQkFBZ0I7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUVwQyxJQUFJLE1BQU0sQ0FBQyxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7UUFDekIsT0FBTyxJQUFJLENBQUM7SUFDZCxDQUFDO0lBRUQsTUFBTSxZQUFZLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUU3RCxJQUFJLFlBQVksSUFBSSxJQUFJLEVBQUUsQ0FBQztRQUN6QixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxJQUFJLE1BQU0sQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLFNBQVMsRUFBRSxDQUFDO1FBQy9DLElBQUksQ0FBQyxJQUFJLEtBQUssR0FBRyxJQUFJLElBQUksS0FBSyxHQUFHLENBQUMsSUFBSSxZQUFZLElBQUksR0FBRyxFQUFFLENBQUM7WUFDMUQsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBQ0QsSUFBSSxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsWUFBWSxJQUFJLEdBQUcsSUFBSSxZQUFZLEtBQUssR0FBRyxDQUFDLEVBQUUsQ0FBQztZQUNsRSxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7SUFDSCxDQUFDO0lBRUQsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQy9CLElBQUksQ0FBQyxJQUFJLEtBQUssR0FBRyxJQUFJLElBQUksS0FBSyxTQUFTLENBQUMsSUFBSSxZQUFZLElBQUksR0FBRyxFQUFFLENBQUM7WUFDaEUsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBQ0QsSUFBSSxDQUFDLElBQUksS0FBSyxHQUFHLElBQUksSUFBSSxLQUFLLFdBQVcsQ0FBQyxJQUFJLFlBQVksSUFBSSxHQUFHLEVBQUUsQ0FBQztZQUNsRSxPQUFPLElBQUksQ0FBQztRQUNkLENBQUM7UUFDRCxJQUFJLENBQUMsSUFBSSxLQUFLLEdBQUcsSUFBSSxJQUFJLEtBQUssV0FBVyxDQUFDLElBQUksWUFBWSxJQUFJLEdBQUcsRUFBRSxDQUFDO1lBQ2xFLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztRQUNELElBQUksQ0FBQyxJQUFJLEtBQUssR0FBRyxJQUFJLElBQUksS0FBSyxZQUFZLENBQUMsSUFBSSxZQUFZLElBQUksR0FBRyxFQUFFLENBQUM7WUFDbkUsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO0lBQ0gsQ0FBQztJQUVELElBQ0UsQ0FBQyxJQUFJLEtBQUssR0FBRyxJQUFJLElBQUksS0FBSyxHQUFHLElBQUksSUFBSSxLQUFLLEdBQUcsQ0FBQztRQUM5QyxDQUFDLFlBQVksSUFBSSxHQUFHLElBQUksWUFBWSxLQUFLLEdBQUcsSUFBSSxZQUFZLEtBQUssR0FBRyxDQUFDLEVBQ3JFLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxJQUNFLENBQUMsSUFBSSxLQUFLLEdBQUcsSUFBSSxJQUFJLEtBQUssR0FBRyxJQUFJLElBQUksSUFBSSxHQUFHLElBQUksSUFBSSxLQUFLLEdBQUcsQ0FBQztRQUM3RCxDQUFDLFlBQVksSUFBSSxHQUFHLElBQUksWUFBWSxLQUFLLEdBQUcsSUFBSSxZQUFZLEtBQUssR0FBRyxJQUFJLFlBQVksS0FBSyxHQUFHLENBQUMsRUFDN0YsQ0FBQztRQUNELE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVELElBQ0UsQ0FBQyxJQUFJLEtBQUssR0FBRyxJQUFJLElBQUksS0FBSyxHQUFHLElBQUksSUFBSSxJQUFJLEdBQUcsQ0FBQztRQUM3QyxDQUFDLFlBQVksSUFBSSxHQUFHLElBQUksWUFBWSxLQUFLLEdBQUcsSUFBSSxZQUFZLEtBQUssR0FBRyxDQUFDLEVBQ3JFLENBQUM7UUFDRCxPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUM7QUFFRCxTQUFTLFVBQVUsQ0FBQyxJQUFZLEVBQUUsU0FBaUI7SUFDakQsSUFBSSxNQUFNLENBQUMsaUJBQWlCLElBQUksTUFBTSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBQ3JELE9BQU87SUFDVCxDQUFDO0lBRUQsSUFBSSxJQUFJLEtBQUssR0FBRyxFQUFFLENBQUM7UUFDakIsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQzNCLFVBQVUsQ0FBQyxHQUFHLEVBQUUsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ2pDLENBQUM7UUFFRCxPQUFPO0lBQ1QsQ0FBQztJQUVELElBQUksSUFBSSxLQUFLLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLEtBQUssT0FBTyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssWUFBWSxDQUFDLEVBQUUsQ0FBQztRQUNuRixJQUFJLEdBQUcsR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUVELElBQUksSUFBSSxLQUFLLElBQUksSUFBSSxJQUFJLEtBQUssSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUN0RCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssU0FBUyxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssUUFBUTtZQUFFLE9BQU87UUFDdEUsV0FBVyxFQUFFLENBQUM7UUFFZCxxREFBcUQ7UUFDckQsbUNBQW1DO1FBQ25DLDRCQUE0QjtRQUM1QixJQUNFLE1BQU0sQ0FBQyxVQUFVLEtBQUssUUFBUTtZQUM5QixDQUFDLE1BQU0sQ0FBQyxXQUFXLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxLQUFLLENBQUM7WUFDN0MsTUFBTSxDQUFDLFdBQVcsS0FBSyxNQUFNLEVBQzdCLENBQUM7WUFDRCxJQUFJLGVBQWUsRUFBRSxDQUFDO2dCQUNwQixlQUFlLEdBQUcsS0FBSyxDQUFDO2dCQUN4QixPQUFPO1lBQ1QsQ0FBQztRQUNILENBQUM7YUFBTSxDQUFDO1lBQ04sT0FBTztRQUNULENBQUM7SUFDSCxDQUFDO0lBRUQsSUFBSSxNQUFNLENBQUMsSUFBSSxLQUFLLEtBQUssSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxLQUFLLElBQUksSUFBSSxJQUFJLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDL0YsT0FBTztJQUNULENBQUM7SUFFRCxnQkFBZ0I7SUFDaEIsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDO1FBQ2hELE9BQU87SUFDVCxDQUFDO0lBRUQsS0FBSyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoQixLQUFLLENBQUMsYUFBYSxFQUFFLENBQUM7SUFFdEIsTUFBTSxlQUFlLEdBQUcsYUFBYSxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQztJQUV2RCxJQUFJLGVBQWUsSUFBSSxNQUFNLENBQUMsSUFBSSxLQUFLLEtBQUssRUFBRSxDQUFDO1FBQzdDLElBQUksR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLFVBQVUsRUFBRSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUN4RCxDQUFDO0lBRUQsSUFBSSxDQUFDLGVBQWUsSUFBSSxJQUFJLEtBQUssSUFBSSxFQUFFLENBQUM7UUFDdEMsSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sS0FBSyxFQUFFO1lBQUUsT0FBTztRQUMzQyxJQUFJLEdBQUcsR0FBRyxDQUFDO0lBQ2IsQ0FBQztJQUVELElBQUksU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLEtBQUssRUFBRSxFQUFFLENBQUM7UUFDbkMsU0FBUyxDQUFDLGFBQWEsQ0FBQyxXQUFXLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQztJQUM3QyxDQUFDO0lBRUQsTUFBTSxhQUFhLEdBQ2pCLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsU0FBUyxDQUFDO1FBQy9DLElBQUk7UUFDSixTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBRW5ELHdFQUF3RTtJQUN4RSxJQUNFLENBQUMsZUFBZTtRQUNoQixJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQztRQUM3QyxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsRUFDL0IsQ0FBQztRQUNELFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxHQUFHLGFBQWEsQ0FBQztRQUN4QyxNQUFNLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztRQUMzQixLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdkIsT0FBTztJQUNULENBQUM7SUFFRCx5Q0FBeUM7SUFDekMsU0FBUyxDQUFDLGlCQUFpQixDQUFDLGVBQWUsQ0FBQyxDQUFDO0lBRTdDLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUNyQixTQUFTLENBQUMsdUJBQXVCLEVBQUUsQ0FBQztRQUNwQyxTQUFTLENBQUMsY0FBYyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FBQztJQUN6RCxDQUFDO0lBRUQsUUFBUSxDQUFDLFdBQVcsQ0FDbEIsTUFBTSxDQUFDLElBQUksS0FBSyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxTQUFTLENBQUMsRUFDdEUsZUFBZSxDQUNoQixDQUFDO0lBRUYsSUFBSSxDQUFDLGdCQUFnQixJQUFJLE1BQU0sQ0FBQyxVQUFVLElBQUksUUFBUTtRQUFFLE9BQU87SUFFL0QsOEpBQThKO0lBQzlKLElBQUksU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPLEtBQUssRUFBRSxFQUFFLENBQUM7UUFDdkMsU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPLElBQUksYUFBYSxDQUFDO0lBQy9DLENBQUM7U0FBTSxDQUFDO1FBQ04sSUFBSSxTQUFTLElBQUksU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDcEQsU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPLElBQUksSUFBSSxDQUFDO1FBQ3RDLENBQUM7YUFBTSxJQUFJLENBQUMsZUFBZSxFQUFFLENBQUM7WUFDNUIsU0FBUyxDQUFDLFNBQVMsQ0FBQyxPQUFPO2dCQUN6QixTQUFTLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQztvQkFDbkQsSUFBSTtvQkFDSixTQUFTLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsU0FBUyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3pELENBQUM7SUFDSCxDQUFDO0lBRUQsU0FBUyxDQUFDLHNCQUFzQixFQUFFLENBQUM7SUFDbkMsU0FBUyxDQUFDLGtCQUFrQixFQUFFLENBQUM7SUFDL0IsU0FBUyxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLENBQUM7SUFFekQsSUFBSSxNQUFNLENBQUMsVUFBVSxLQUFLLFFBQVEsSUFBSSxNQUFNLENBQUMsV0FBVyxJQUFJLFFBQVEsSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1FBQ3pGLE9BQU87SUFDVCxDQUFDO0lBRUQsTUFBTSxDQUFDLGNBQWMsQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsaUJBQWlCLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFFbkYsMkNBQTJDO0lBQzNDLElBQUksU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLFlBQVksS0FBSyxDQUFDLEVBQUUsQ0FBQztRQUMvRSxNQUFNLENBQUMsZ0JBQWdCLENBQWUsUUFBUSxDQUFDLGFBQWEsQ0FBQyxnQkFBZ0IsQ0FBRSxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQzlGLENBQUM7SUFFRCw4REFBOEQ7SUFDOUQsSUFDRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLEtBQUssS0FBSyxJQUFJLFNBQVMsR0FBRyxFQUFFLENBQUM7UUFDekMsQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLEtBQUssSUFBSSxTQUFTLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxNQUFNLEdBQUcsRUFBRSxDQUFDLEVBQy9FLENBQUM7UUFDRCxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxhQUFhLENBQUM7SUFDMUMsQ0FBQztJQUVELElBQUksQ0FBQyxlQUFlLElBQUksTUFBTSxDQUFDLFVBQVUsSUFBSSxRQUFRLEVBQUUsQ0FBQztRQUN0RCxTQUFTLENBQUMsS0FBSyxDQUFDLFdBQVcsRUFBRSxDQUFDO1FBQzlCLFNBQVMsQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDbEMsU0FBUyxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUM3QixPQUFPO0lBQ1QsQ0FBQztJQUVELElBQUksTUFBTSxDQUFDLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztRQUN6Qiw0QkFBNEI7UUFDNUIsZ0RBQWdEO1FBQ2hELE1BQU0sV0FBVyxHQUFHLFNBQVMsQ0FBQyxLQUFLLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDakQsTUFBTSxTQUFTLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUM7UUFDL0MsSUFDRSxDQUFDLFdBQVcsSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU87WUFDckMsQ0FBQyxNQUFNLENBQUMsUUFBUTtnQkFDZCxXQUFXLENBQUMsTUFBTSxJQUFJLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU07Z0JBQ3BELE1BQU0sQ0FBQyxXQUFXLElBQUksS0FBSyxDQUFDLENBQUM7WUFDakMsU0FBUyxJQUFJLFNBQVMsQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsRUFDdkMsQ0FBQztZQUNELFNBQVMsQ0FBQyxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDOUIsU0FBUyxDQUFDLFNBQVMsQ0FBQyxXQUFXLEVBQUUsQ0FBQztZQUNsQyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDbkIsT0FBTztRQUNULENBQUM7SUFDSCxDQUFDO0lBRUQsTUFBTSx1QkFBdUIsR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFjLHFCQUFxQixDQUFDO1FBQ3hGLEVBQUUsU0FBbUIsQ0FBQztJQUN4QixNQUFNLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUUzQixJQUFJLENBQUMsTUFBTSxDQUFDLGdCQUFnQixFQUFFLENBQUM7UUFDN0IsTUFBTSxZQUFZLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBYyxxQkFBcUIsQ0FBQztZQUM3RSxFQUFFLFNBQW1CLENBQUM7UUFDeEIseUVBQXlFO1FBQ3pFLElBQ0UsdUJBQXVCLEdBQUcsWUFBWTtZQUN0QyxDQUFDLE1BQU0sQ0FBQyxjQUFjO1lBQ3RCLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQ2xDLENBQUM7WUFDRCxJQUFJLE1BQU0sQ0FBQyxJQUFJLElBQUksS0FBSyxFQUFFLENBQUM7Z0JBQ3pCLE1BQU0sVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQzNCLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBYyxjQUFjLENBQUMsQ0FBQyxNQUFNLENBQUMsdUJBQXVCLEdBQUcsQ0FBQyxDQUFDO29CQUN4RixFQUFFLFNBQVMsQ0FDSixDQUFDO2dCQUNaLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWTtvQkFBRSxNQUFNLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQyxDQUFDO1lBQ3hELENBQUM7aUJBQU0sQ0FBQztnQkFDTixTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQy9ELE1BQU0sQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1lBQzdCLENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztJQUVELHdDQUF3QztJQUN4QyxJQUNFLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxLQUFLLFNBQVMsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLFFBQVEsQ0FBQztRQUMxRCxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEtBQUssU0FBUyxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQyxNQUFNLENBQUM7UUFDekUsQ0FBQyxJQUFJLEtBQUssSUFBSSxJQUFJLGVBQWUsQ0FBQyxFQUNsQyxDQUFDO1FBQ0QsV0FBVyxFQUFFLENBQUM7SUFDaEIsQ0FBQztJQUVELElBQUksSUFBSSxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ2xCLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztJQUN6QixDQUFDO0FBQ0gsQ0FBQztBQUVELFNBQVMsU0FBUyxDQUNoQixLQUFvRCxFQUNwRCxZQUFxQjtJQUVyQixJQUFJLE1BQU0sQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBQzdCLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN2QixPQUFPO0lBQ1QsQ0FBQztJQUVELElBQUksd0JBQXdCLEdBQUcsS0FBSyxDQUFDO0lBRXJDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxJQUFJLEtBQUssSUFBSSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLElBQUksQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQztRQUN2Rix3QkFBd0IsR0FBRyxJQUFJLENBQUM7SUFDbEMsQ0FBQztBQUNILENBQUM7QUFFRCxNQUFNLFVBQVUsb0JBQW9CLENBQUMsWUFBOEI7SUFDakUsVUFBVSxHQUFHLFlBQVksQ0FBQztBQUM1QixDQUFDO0FBRUQsTUFBTSxDQUFDLEtBQUssVUFBVSxZQUFZLENBQUMsS0FBVSxFQUFFLFlBQXFCO0lBQ2xFLE1BQU0sV0FBVyxHQUFHLENBQUMsTUFBTSxDQUFDLGFBQWEsSUFBSSxDQUFDLFlBQVksSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLE9BQU8sQ0FBQyxDQUFDO0lBRXJGLHlCQUF5QjtJQUN6QixJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssWUFBWSxJQUFJLEtBQUssQ0FBQyxPQUFPLEtBQUssRUFBRSxFQUFFLENBQUM7UUFDM0QsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO0lBQ3pCLENBQUM7SUFFRCxJQUFJLFdBQVcsSUFBSSxDQUFDLFlBQVksSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLE9BQU8sRUFBRSxDQUFDO1FBQzFELE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQztRQUNwQixJQUFJLE1BQU0sQ0FBQyxxQkFBcUIsRUFBRSxDQUFDO1lBQ2pDLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN6QixDQUFDO0lBQ0gsQ0FBQztJQUVELEtBQUs7SUFDTCxJQUFJLEtBQUssQ0FBQyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7UUFDdkIsU0FBUyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRUQsSUFBSSxDQUFDLFdBQVc7UUFBRSxPQUFPO0lBRXpCLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxJQUFJLE1BQU0sQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUM5QyxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDdkIsT0FBTztJQUNULENBQUM7SUFFRCxJQUFJLFNBQVMsQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUMzQixPQUFPLENBQUMsR0FBRyxDQUNULGVBQWUsRUFDZixVQUFVLEVBQ1YsS0FBSyxDQUFDLEdBQUcsRUFDVCxRQUFRLEVBQ1IsU0FBUyxDQUFDLGVBQWUsQ0FBQyxPQUFPLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FDL0MsQ0FBQztJQUNKLENBQUM7SUFDRCxTQUFTLENBQUMscUJBQXFCLEVBQUUsQ0FBQztJQUNsQyxTQUFTLENBQUMsbUJBQW1CLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7SUFDakQsU0FBUyxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFFOUIsNERBQTREO0lBQzVELElBQUksS0FBSyxDQUFDLEdBQUcsS0FBSyxXQUFXLEVBQUUsQ0FBQztRQUM5QixNQUFNLENBQUMsR0FBRyx3QkFBd0IsQ0FBQztRQUNuQyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBRSxLQUFLLENBQUMsTUFBNkIsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDO1lBQzFELEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN6QixDQUFDO1FBRUQsSUFBSSxNQUFNLENBQUMsY0FBYyxLQUFLLEtBQUssRUFBRSxDQUFDO1lBQ3BDLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztZQUN2QixPQUFPO1FBQ1QsQ0FBQztJQUNILENBQUM7SUFFRCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssUUFBUSxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUM7UUFDM0QsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3ZCLE9BQU87SUFDVCxDQUFDO0lBRUQsSUFBSSxLQUFLLENBQUMsR0FBRyxLQUFLLFdBQVcsSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDdEUsbUJBQW1CLEVBQUUsQ0FBQztRQUN0QixJQUFJLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDNUIsYUFBYSxDQUFDLEdBQUcsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUMsQ0FBQztRQUNyRCxDQUFDO0lBQ0gsQ0FBQztJQUVELElBQUksS0FBSyxDQUFDLEdBQUcsS0FBSyxPQUFPLEVBQUUsQ0FBQztRQUMxQixJQUFJLEtBQUssQ0FBQyxRQUFRLElBQUksTUFBTSxDQUFDLElBQUksSUFBSSxLQUFLLEVBQUUsQ0FBQztZQUMzQyxTQUFTLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDckIsQ0FBQzthQUFNLElBQ0wsS0FBSyxDQUFDLFFBQVE7WUFDZCxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksSUFBSSxNQUFNLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLENBQUM7Z0JBQzNDLENBQUMsTUFBTSxDQUFDLElBQUksSUFBSSxPQUFPLElBQUksTUFBTSxDQUFDLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUNqRCxDQUFDO1lBQ0QsU0FBUyxDQUFDLFVBQVUsQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMzQixTQUFTLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDckIsQ0FBQzthQUFNLENBQUM7WUFDTixVQUFVLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQ2pELGFBQWEsQ0FBQyxHQUFHLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvQyxDQUFDO0lBQ0gsQ0FBQztJQUVELGdCQUFnQjtJQUNoQixJQUFJLEtBQUssQ0FBQyxHQUFHLEtBQUssTUFBTSxJQUFJLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQztRQUM3RCxNQUFNLElBQUksR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFjLHFCQUFxQixDQUFDLENBQUM7UUFDeEUsTUFBTSxHQUFHLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUMsc0VBQXNFO1FBRWxILGtFQUFrRTtRQUNsRSxNQUFNLFVBQVUsR0FBRyxJQUFJLEVBQUUsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDekQsSUFBSSxVQUFVLEVBQUUsQ0FBQztZQUNmLFVBQVUsQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ3RDLENBQUM7SUFDSCxDQUFDO0lBRUQsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQy9CLElBQUksSUFBSSxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUM7UUFDckIsSUFBSSxDQUFDLFdBQVcsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFFLFdBQVcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3ZFLElBQUksSUFBSSxLQUFLLFdBQVc7Z0JBQUUsSUFBSSxHQUFHLEdBQUcsQ0FBQztZQUNyQyxJQUFJLElBQUksS0FBSyxZQUFZO2dCQUFFLElBQUksR0FBRyxHQUFHLENBQUM7WUFDdEMsSUFBSSxJQUFJLEtBQUssV0FBVztnQkFBRSxJQUFJLEdBQUcsR0FBRyxDQUFDO1lBQ3JDLElBQUksSUFBSSxLQUFLLFNBQVM7Z0JBQUUsSUFBSSxHQUFHLEdBQUcsQ0FBQztZQUNuQyxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDdkIsVUFBVSxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNqRCxRQUFRLEVBQUUsQ0FBQztZQUNYLGFBQWEsQ0FBQyxHQUFHLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMvQyxDQUFDO0lBQ0gsQ0FBQztBQUNILENBQUM7QUFFRCxNQUFNLFVBQVUsZUFBZSxDQUFDLEtBQVU7SUFDeEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLElBQUksTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQzlDLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN2QixPQUFPO0lBQ1QsQ0FBQztJQUVELElBQUksTUFBTSxDQUFDLGFBQWE7UUFBRSxPQUFPO0lBQ2pDLE1BQU0sR0FBRyxHQUFHLFdBQVcsQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUM5QixJQUFJLFNBQVMsQ0FBQyxlQUFlLENBQUMsUUFBUSxDQUFDLE9BQU8sS0FBSyxDQUFDLENBQUMsRUFBRSxDQUFDO1FBQ3RELE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsU0FBUyxDQUFDLGVBQWUsQ0FBQyxRQUFRLENBQUMsT0FBTyxHQUFHLEdBQUcsQ0FBQyxDQUFDO1FBQ3hFLFNBQVMsQ0FBQyxvQkFBb0IsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBQ0QsU0FBUyxDQUFDLG1CQUFtQixDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQ3JDLENBQUM7QUFFRCxNQUFNLFVBQVUscUJBQXFCLENBQUMsS0FBVTtJQUM5QyxJQUFJLENBQUMsS0FBSyxDQUFDLFNBQVM7UUFBRSxPQUFPO0lBQzdCLElBQUssS0FBSyxDQUFDLE1BQTJCLENBQUMsS0FBSyxLQUFLLEVBQUUsRUFBRSxDQUFDO1FBQ25ELEtBQUssQ0FBQyxNQUEyQixDQUFDLEtBQUssR0FBRyxHQUFHLENBQUM7SUFDakQsQ0FBQztBQUNILENBQUM7QUFFRCxNQUFNLFVBQVUsZUFBZSxDQUFDLEtBQVU7SUFDeEMsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLElBQUksTUFBTSxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQzdDLEtBQUssQ0FBQyxNQUEyQixDQUFDLEtBQUssR0FBRyxHQUFHLENBQUM7UUFDL0MsT0FBTztJQUNULENBQUM7SUFFRCxTQUFTLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUU5QixNQUFNLGNBQWMsR0FBSSxLQUFLLENBQUMsTUFBMkIsQ0FBQyxLQUFLLENBQUMsU0FBUyxFQUFFLENBQUM7SUFDNUUsTUFBTSxVQUFVLEdBQUcsY0FBYyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUUzQywyREFBMkQ7SUFDM0Qsc0VBQXNFO0lBQ3RFLCtEQUErRDtJQUMvRCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssU0FBUyxJQUFJLFVBQVUsQ0FBQyxNQUFNLElBQUksU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUM7UUFDdkYsYUFBYSxDQUFDLEdBQUcsR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQzdDLE9BQU87SUFDVCxDQUFDO0lBRUQsSUFBSSxjQUFjLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDeEUsd0RBQXdEO1FBQ3hELG1CQUFtQixFQUFFLENBQUM7SUFDeEIsQ0FBQztTQUFNLElBQUksVUFBVSxDQUFDLE1BQU0sR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsQ0FBQztRQUM5RCxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxVQUFVLENBQUM7UUFDckMsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDM0IsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDO1lBQ3JDLE1BQU0sQ0FBQyxjQUFjLENBQUMsZ0JBQWdCLEVBQUUsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDMUUsQ0FBQztJQUNILENBQUM7U0FBTSxJQUFJLFVBQVUsS0FBSyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2xELElBQUksU0FBUyxHQUFHLENBQUMsQ0FBQztRQUNsQixPQUFPLFVBQVUsQ0FBQyxTQUFTLENBQUMsS0FBSyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDO1lBQ3BFLFNBQVMsRUFBRSxDQUFDO1FBQ2QsQ0FBQztRQUVELEtBQUssSUFBSSxDQUFDLEdBQUcsU0FBUyxFQUFFLENBQUMsR0FBRyxVQUFVLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDbkQsVUFBVSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMvQixDQUFDO0lBQ0gsQ0FBQztJQUVELGFBQWEsQ0FBQyxHQUFHLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsQ0FBQztJQUM3QyxRQUFRLEVBQUUsQ0FBQztJQUVYLE1BQU0sV0FBVyxHQUFHLGdCQUFnQixDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ3BELFVBQVUsQ0FBQyxHQUFHLEVBQUU7UUFDZCx5RUFBeUU7UUFDekUsdUVBQXVFO1FBQ3ZFLHlDQUF5QztRQUN6QyxpQ0FBaUM7UUFFakMsTUFBTSxVQUFVLEdBQUcsZ0JBQWdCLENBQUMsWUFBWSxFQUFFLENBQUM7UUFDbkQsSUFBSSxXQUFXLEtBQUssVUFBVSxFQUFFLENBQUM7WUFDL0IsTUFBTSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDN0IsQ0FBQztRQUVELDhCQUE4QjtRQUM5Qix1RUFBdUU7UUFDdkUsdUNBQXVDO1FBQ3ZDLElBQ0csS0FBSyxDQUFDLE1BQTJCLENBQUMsY0FBYztZQUM5QyxLQUFLLENBQUMsTUFBMkIsQ0FBQyxLQUFLLENBQUMsTUFBTTtZQUNqRCxDQUFDLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBRSxLQUFLLENBQUMsTUFBMkIsQ0FBQyxLQUFLLENBQUM7Z0JBQ3hFLENBQUUsS0FBSyxDQUFDLE1BQTJCLENBQUMsY0FBYyxJQUFJLENBQUMsQ0FBQztvQkFDckQsS0FBSyxDQUFDLE1BQTJCLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxFQUMvRSxDQUFDO1lBQ0EsS0FBSyxDQUFDLE1BQTJCLENBQUMsY0FBYyxHQUMvQyxLQUFLLENBQUMsTUFDUCxDQUFDLFlBQVksR0FBSSxLQUFLLENBQUMsTUFBMkIsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQ25FLENBQUM7SUFDSCxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUM7QUFDUixDQUFDO0FBRUQsTUFBTSxVQUFVLGVBQWUsQ0FBQyxLQUFtQztJQUNoRSxLQUFLLENBQUMsTUFBMkIsQ0FBQyxjQUFjLEdBQy9DLEtBQUssQ0FBQyxNQUNQLENBQUMsWUFBWSxHQUFJLEtBQUssQ0FBQyxNQUEyQixDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7QUFDbkUsQ0FBQztBQUVELE1BQU0sVUFBVSxjQUFjLENBQUMsS0FBcUM7SUFDbEUsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO0FBQ3pCLENBQUM7QUFFRCxNQUFNLFVBQVUsZUFBZSxDQUFDLEtBQXFDO0lBQ25FLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUN6QixDQUFDO0FBRUQsbUJBQW1CO0FBQ25CLE1BQU0sVUFBVSwwQkFBMEI7SUFDeEMsZ0JBQWdCLENBQUMsWUFBWSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ3BDLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQztBQUMvRCxDQUFDO0FBRUQsTUFBTSxVQUFVLHdCQUF3QjtJQUN0QyxnQkFBZ0IsQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUM7QUFDdkMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIFRlc3RMb2dpYyBmcm9tICcuLi90ZXN0L3Rlc3QtbG9naWMnO1xuaW1wb3J0ICogYXMgVGVzdFVJIGZyb20gJy4uL3Rlc3QvdGVzdC11aSc7XG5pbXBvcnQgKiBhcyBUZXN0U3RhdHMgZnJvbSAnLi4vdGVzdC90ZXN0LXN0YXRzJztcbmltcG9ydCBDb25maWcsICogYXMgVXBkYXRlQ29uZmlnIGZyb20gJy4uL2NvbmZpZyc7XG5pbXBvcnQgKiBhcyBNaXNjIGZyb20gJy4uLy4uL3V0aWxzL21pc2MnO1xuaW1wb3J0ICogYXMgQ2FyZXQgZnJvbSAnLi4vdGVzdC9jYXJldCc7XG5pbXBvcnQgKiBhcyBDdXN0b21UZXh0IGZyb20gJy4uL3Rlc3QvY3VzdG9tLXRleHQnO1xuaW1wb3J0ICogYXMgVGltZXJQcm9ncmVzcyBmcm9tICcuLi90ZXN0L3RpbWVyLXByb2dyZXNzJztcbmltcG9ydCAqIGFzIEZvY3VzIGZyb20gJy4uL3Rlc3QvZm9jdXMnO1xuaW1wb3J0ICogYXMgUmVwbGF5IGZyb20gJy4uL3Rlc3QvcmVwbGF5JztcbmltcG9ydCAqIGFzIFdlYWtTcG90IGZyb20gJy4uL3Rlc3Qvd2Vhay1zcG90JztcbmltcG9ydCAqIGFzIFRlc3RBY3RpdmUgZnJvbSAnLi4vc3RhdGVzL3Rlc3QtYWN0aXZlJztcbmltcG9ydCAqIGFzIENvbXBvc2l0aW9uU3RhdGUgZnJvbSAnLi4vc3RhdGVzL2NvbXBvc2l0aW9uJztcbmltcG9ydCAqIGFzIFRlc3RJbnB1dCBmcm9tICcuLi90ZXN0L3Rlc3QtaW5wdXQnO1xuaW1wb3J0ICogYXMgVGVzdFdvcmRzIGZyb20gJy4uL3Rlc3QvdGVzdC13b3Jkcyc7XG5cbmxldCBkb250SW5zZXJ0U3BhY2UgPSBmYWxzZTtcbmNvbnN0IGNvcnJlY3RTaGlmdFVzZWQgPSB0cnVlO1xuXG5sZXQgd29yZHNJbnB1dDogSFRNTElucHV0RWxlbWVudDtcblxuZnVuY3Rpb24gc2V0V29yZHNJbnB1dCh2YWx1ZTogc3RyaW5nKTogdm9pZCB7XG4gIC8vIE9ubHkgY2hhbmdlICN3b3Jkc0lucHV0IGlmIGl0J3Mgbm90IGFscmVhZHkgdGhlIHdhbnRlZCB2YWx1ZVxuICAvLyBBdm9pZHMgU2FmYXJpIHRyaWdnZXJpbmcgdW5uZWVkZWQgZXZlbnRzLCBjYXVzaW5nIGlzc3VlcyB3aXRoXG4gIC8vIGRlYWQga2V5cy5cbiAgaWYgKHZhbHVlICE9PSB3b3Jkc0lucHV0LnZhbHVlKSB7XG4gICAgd29yZHNJbnB1dC52YWx1ZSA9IHZhbHVlO1xuICB9XG59XG5cbmZ1bmN0aW9uIHVwZGF0ZVVJKCk6IHZvaWQge1xuICBjb25zdCBhY2MgPSBNaXNjLnJvdW5kVG8yKFRlc3RTdGF0cy5jYWxjdWxhdGVBY2N1cmFjeSgpKTtcbn1cblxuZnVuY3Rpb24gYmFja3NwYWNlVG9QcmV2aW91cygpOiB2b2lkIHtcbiAgaWYgKCFUZXN0QWN0aXZlLmdldCgpKSByZXR1cm47XG5cbiAgaWYgKFRlc3RJbnB1dC5pbnB1dC5oaXN0b3J5Lmxlbmd0aCA9PSAwIHx8IFRlc3RVSS5jdXJyZW50V29yZEVsZW1lbnRJbmRleCA9PSAwKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKFxuICAgIChUZXN0SW5wdXQuaW5wdXQuaGlzdG9yeVtUZXN0V29yZHMud29yZHMuY3VycmVudEluZGV4IC0gMV0gPT1cbiAgICAgIFRlc3RXb3Jkcy53b3Jkcy5nZXQoVGVzdFdvcmRzLndvcmRzLmN1cnJlbnRJbmRleCAtIDEpICYmXG4gICAgICAhQ29uZmlnLmZyZWVkb21Nb2RlKSB8fFxuICAgIGRvY3VtZW50XG4gICAgICAucXVlcnlTZWxlY3RvckFsbCgnLndvcmQnKVxuICAgICAgW1Rlc3RXb3Jkcy53b3Jkcy5jdXJyZW50SW5kZXggLSAxXT8uY2xhc3NMaXN0LmNvbnRhaW5zKCdoaWRkZW4nKVxuICApIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoQ29uZmlnLmNvbmZpZGVuY2VNb2RlID09PSAnb24nIHx8IENvbmZpZy5jb25maWRlbmNlTW9kZSA9PT0gJ21heCcpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudCA9IFRlc3RJbnB1dC5pbnB1dC5wb3BIaXN0b3J5KCk7XG4gIFRlc3RJbnB1dC5jb3JyZWN0ZWQucG9wSGlzdG9yeSgpO1xuICBpZiAoQ29uZmlnLmZ1bmJveCA9PT0gJ25vc3BhY2UnIHx8IENvbmZpZy5mdW5ib3ggPT09ICdhcnJvd3MnKSB7XG4gICAgVGVzdElucHV0LmlucHV0LmN1cnJlbnQgPSBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5zbGljZSgwLCAtMSk7XG4gIH1cbiAgVGVzdFdvcmRzLndvcmRzLmRlY3JlYXNlQ3VycmVudEluZGV4KCk7XG4gIFRlc3RVSS5zZXRDdXJyZW50V29yZEVsZW1lbnRJbmRleChUZXN0VUkuY3VycmVudFdvcmRFbGVtZW50SW5kZXggLSAxKTtcbiAgVGVzdFVJLnVwZGF0ZUFjdGl2ZUVsZW1lbnQodHJ1ZSk7XG4gIFRlc3RVSS51cGRhdGVXb3JkRWxlbWVudCgpO1xuXG4gIENhcmV0LnVwZGF0ZVBvc2l0aW9uKCk7XG4gIFJlcGxheS5hZGRSZXBsYXlFdmVudCgnYmFja1dvcmQnKTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlU3BhY2UoKTogdm9pZCB7XG4gIGlmICghVGVzdEFjdGl2ZS5nZXQoKSkgcmV0dXJuO1xuXG4gIGlmIChUZXN0SW5wdXQuaW5wdXQuY3VycmVudCA9PT0gJycpIHJldHVybjtcblxuICBjb25zdCBjdXJyZW50V29yZCA9IFRlc3RXb3Jkcy53b3Jkcy5nZXRDdXJyZW50KCk7XG4gIGlmIChDb25maWcuZnVuYm94ID09PSAnbGF5b3V0Zmx1aWQnICYmIENvbmZpZy5tb2RlICE9PSAndGltZScpIHtcbiAgICAvLyBoZXJlIEkgbmVlZCB0byBjaGVjayBpZiBDb25maWcuY3VzdG9tTGF5b3V0Rmx1aWQgZXhpc3RzIGJlY2F1c2Ugb2YgbXkgc2N1ZmZlZCBzb2x1dGlvbiBvZiByZXR1cm5pbmcgd2hlbmV2ZXIgdmFsdWUgaXMgdW5kZWZpbmVkIGluIHRoZSBzZXRDdXN0b21MYXlvdXRmbHVpZCBmdW5jdGlvblxuICAgIGNvbnN0IGxheW91dHMgPSBDb25maWcuY3VzdG9tTGF5b3V0Zmx1aWRcbiAgICAgID8gQ29uZmlnLmN1c3RvbUxheW91dGZsdWlkLnNwbGl0KCcjJylcbiAgICAgIDogWydxd2VydHknLCAnZHZvcmFrJywgJ2NvbGVtYWsnXTtcbiAgICBsZXQgaW5kZXggPSAwO1xuICAgIGNvbnN0IG91dG9mID0gVGVzdFdvcmRzLndvcmRzLmxlbmd0aDtcbiAgICBpbmRleCA9IE1hdGguZmxvb3IoKFRlc3RJbnB1dC5pbnB1dC5oaXN0b3J5Lmxlbmd0aCArIDEpIC8gKG91dG9mIC8gbGF5b3V0cy5sZW5ndGgpKTtcbiAgfVxuICBkb250SW5zZXJ0U3BhY2UgPSB0cnVlO1xuXG4gIGNvbnN0IGJ1cnN0ID0gVGVzdFN0YXRzLmNhbGN1bGF0ZUJ1cnN0KCk7XG4gIFRlc3RJbnB1dC5wdXNoQnVyc3RUb0hpc3RvcnkoYnVyc3QpO1xuXG4gIC8vY29ycmVjdCB3b3JkIG9yIGluIHplbiBtb2RlXG4gIGNvbnN0IGlzV29yZENvcnJlY3QgPSBjdXJyZW50V29yZCA9PSBUZXN0SW5wdXQuaW5wdXQuY3VycmVudCB8fCBDb25maWcubW9kZSA9PSAnemVuJztcbiAgVGVzdElucHV0LmluY3JlbWVudEFjY3VyYWN5KGlzV29yZENvcnJlY3QpO1xuICBpZiAoaXNXb3JkQ29ycmVjdCkge1xuICAgIFRlc3RJbnB1dC5pbnB1dC5wdXNoSGlzdG9yeSgpO1xuICAgIFRlc3RXb3Jkcy53b3Jkcy5pbmNyZWFzZUN1cnJlbnRJbmRleCgpO1xuICAgIFRlc3RVSS5zZXRDdXJyZW50V29yZEVsZW1lbnRJbmRleChUZXN0VUkuY3VycmVudFdvcmRFbGVtZW50SW5kZXggKyAxKTtcbiAgICBUZXN0VUkudXBkYXRlQWN0aXZlRWxlbWVudCgpO1xuICAgIENhcmV0LnVwZGF0ZVBvc2l0aW9uKCk7XG4gICAgVGVzdElucHV0LmluY3JlbWVudEtleXByZXNzQ291bnQoKTtcbiAgICBUZXN0SW5wdXQucHVzaEtleXByZXNzV29yZChUZXN0V29yZHMud29yZHMuY3VycmVudEluZGV4KTtcbiAgICBSZXBsYXkuYWRkUmVwbGF5RXZlbnQoJ3N1Ym1pdENvcnJlY3RXb3JkJyk7XG4gIH0gZWxzZSB7XG4gICAgVGVzdElucHV0LnB1c2hNaXNzZWRXb3JkKFRlc3RXb3Jkcy53b3Jkcy5nZXRDdXJyZW50KCkpO1xuICAgIFRlc3RJbnB1dC5pbmNyZW1lbnRLZXlwcmVzc0Vycm9ycygpO1xuICAgIGNvbnN0IGNpbCA9IFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50Lmxlbmd0aDtcbiAgICBpZiAoY2lsIDw9IFRlc3RXb3Jkcy53b3Jkcy5nZXRDdXJyZW50KCkubGVuZ3RoKSB7XG4gICAgICBpZiAoY2lsID49IFRlc3RJbnB1dC5jb3JyZWN0ZWQuY3VycmVudC5sZW5ndGgpIHtcbiAgICAgICAgVGVzdElucHV0LmNvcnJlY3RlZC5jdXJyZW50ICs9ICdfJztcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIFRlc3RJbnB1dC5jb3JyZWN0ZWQuY3VycmVudCA9XG4gICAgICAgICAgVGVzdElucHV0LmNvcnJlY3RlZC5jdXJyZW50LnN1YnN0cmluZygwLCBjaWwpICtcbiAgICAgICAgICAnXycgK1xuICAgICAgICAgIFRlc3RJbnB1dC5jb3JyZWN0ZWQuY3VycmVudC5zdWJzdHJpbmcoY2lsICsgMSk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChDb25maWcuc3RvcE9uRXJyb3IgIT0gJ29mZicpIHtcbiAgICAgIGlmIChDb25maWcuZGlmZmljdWx0eSA9PSAnZXhwZXJ0JyB8fCBDb25maWcuZGlmZmljdWx0eSA9PSAnbWFzdGVyJykge1xuICAgICAgICAvL2ZhaWxlZCBkdWUgdG8gZGlmZiB3aGVuIHByZXNzaW5nIHNwYWNlXG4gICAgICAgIFRlc3RMb2dpYy5mYWlsKCdkaWZmaWN1bHR5Jyk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIGlmIChDb25maWcuc3RvcE9uRXJyb3IgPT0gJ3dvcmQnKSB7XG4gICAgICAgIGRvbnRJbnNlcnRTcGFjZSA9IGZhbHNlO1xuICAgICAgICBSZXBsYXkuYWRkUmVwbGF5RXZlbnQoJ2luY29ycmVjdExldHRlcicsICdfJyk7XG4gICAgICAgIFRlc3RVSS51cGRhdGVXb3JkRWxlbWVudCh0cnVlKTtcbiAgICAgICAgQ2FyZXQudXBkYXRlUG9zaXRpb24oKTtcbiAgICAgIH1cbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgVGVzdElucHV0LmlucHV0LnB1c2hIaXN0b3J5KCk7XG4gICAgVGVzdFVJLmhpZ2hsaWdodEJhZFdvcmQoVGVzdFVJLmN1cnJlbnRXb3JkRWxlbWVudEluZGV4LCAhQ29uZmlnLmJsaW5kTW9kZSk7XG4gICAgVGVzdFdvcmRzLndvcmRzLmluY3JlYXNlQ3VycmVudEluZGV4KCk7XG4gICAgVGVzdFVJLnNldEN1cnJlbnRXb3JkRWxlbWVudEluZGV4KFRlc3RVSS5jdXJyZW50V29yZEVsZW1lbnRJbmRleCArIDEpO1xuICAgIFRlc3RVSS51cGRhdGVBY3RpdmVFbGVtZW50KCk7XG4gICAgQ2FyZXQudXBkYXRlUG9zaXRpb24oKTtcbiAgICBUZXN0SW5wdXQuaW5jcmVtZW50S2V5cHJlc3NDb3VudCgpO1xuICAgIFRlc3RJbnB1dC5wdXNoS2V5cHJlc3NXb3JkKFRlc3RXb3Jkcy53b3Jkcy5jdXJyZW50SW5kZXgpO1xuICAgIFRlc3RJbnB1dC51cGRhdGVMYXN0S2V5cHJlc3MoKTtcbiAgICBpZiAoQ29uZmlnLmRpZmZpY3VsdHkgPT0gJ2V4cGVydCcgfHwgQ29uZmlnLmRpZmZpY3VsdHkgPT0gJ21hc3RlcicpIHtcbiAgICAgIFRlc3RMb2dpYy5mYWlsKCdkaWZmaWN1bHR5Jyk7XG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIGlmIChUZXN0V29yZHMud29yZHMuY3VycmVudEluZGV4ID09IFRlc3RXb3Jkcy53b3Jkcy5sZW5ndGgpIHtcbiAgICAgIC8vc3VibWl0dGVkIGxhc3Qgd29yZCB0aGF0IGlzIGluY29ycmVjdFxuICAgICAgVGVzdExvZ2ljLmZpbmlzaCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBSZXBsYXkuYWRkUmVwbGF5RXZlbnQoJ3N1Ym1pdEVycm9yV29yZCcpO1xuICB9XG5cbiAgbGV0IHdvcmRMZW5ndGg7XG4gIGlmIChDb25maWcubW9kZSA9PT0gJ3plbicpIHtcbiAgICB3b3JkTGVuZ3RoID0gVGVzdElucHV0LmlucHV0LmN1cnJlbnQubGVuZ3RoO1xuICB9IGVsc2Uge1xuICAgIHdvcmRMZW5ndGggPSBUZXN0V29yZHMud29yZHMuZ2V0Q3VycmVudCgpLmxlbmd0aDtcbiAgfVxuXG4gIGNvbnN0IGZsZXggPSBNaXNjLndob3JmKENvbmZpZy5taW5CdXJzdEN1c3RvbVNwZWVkLCB3b3JkTGVuZ3RoKTtcblxuICBUZXN0SW5wdXQuY29ycmVjdGVkLnB1c2hIaXN0b3J5KCk7XG5cbiAgaWYgKFxuICAgICFDb25maWcuc2hvd0FsbExpbmVzIHx8XG4gICAgQ29uZmlnLm1vZGUgPT0gJ3RpbWUnIHx8XG4gICAgKEN1c3RvbVRleHQuaXNXb3JkUmFuZG9tICYmIEN1c3RvbVRleHQud29yZCA9PSAwKSB8fFxuICAgIEN1c3RvbVRleHQuaXNUaW1lUmFuZG9tXG4gICkge1xuICAgIGNvbnN0IGN1cnJlbnRUb3AgPSBNYXRoLmZsb29yKFxuICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbDxIVE1MRWxlbWVudD4oJyN3b3JkcyAud29yZCcpW1Rlc3RVSS5jdXJyZW50V29yZEVsZW1lbnRJbmRleCAtIDFdXG4gICAgICAgIC5vZmZzZXRUb3BcbiAgICApO1xuICAgIGxldCBuZXh0VG9wO1xuICAgIHRyeSB7XG4gICAgICBuZXh0VG9wID0gTWF0aC5mbG9vcihcbiAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbDxIVE1MRWxlbWVudD4oJyN3b3JkcyAud29yZCcpW1Rlc3RVSS5jdXJyZW50V29yZEVsZW1lbnRJbmRleF1cbiAgICAgICAgICAub2Zmc2V0VG9wXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIG5leHRUb3AgPSAwO1xuICAgIH1cblxuICAgIGlmIChuZXh0VG9wID4gY3VycmVudFRvcCAmJiAhVGVzdFVJLmxpbmVUcmFuc2l0aW9uKSB7XG4gICAgICBUZXN0VUkubGluZUp1bXAoY3VycmVudFRvcCk7XG4gICAgfVxuICB9IC8vZW5kIG9mIGxpbmUgd3JhcFxuXG4gIGlmIChcbiAgICBDb25maWcubW9kZSA9PT0gJ3dvcmRzJyB8fFxuICAgIENvbmZpZy5tb2RlID09PSAnY3VzdG9tJyB8fFxuICAgIENvbmZpZy5tb2RlID09PSAncXVvdGUnIHx8XG4gICAgQ29uZmlnLm1vZGUgPT09ICd6ZW4nXG4gICkge1xuICAgIFRpbWVyUHJvZ3Jlc3MudXBkYXRlKCk7XG4gIH1cbiAgaWYgKFxuICAgIENvbmZpZy5tb2RlID09ICd0aW1lJyB8fFxuICAgIENvbmZpZy5tb2RlID09ICd3b3JkcycgfHxcbiAgICBDb25maWcubW9kZSA9PSAnY3VzdG9tJyB8fFxuICAgIENvbmZpZy5tb2RlID09ICdxdW90ZSdcbiAgKSB7XG4gICAgVGVzdExvZ2ljLmFkZFdvcmQoKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBpc0NoYXJDb3JyZWN0KGNoYXI6IHN0cmluZywgY2hhckluZGV4OiBudW1iZXIpOiBib29sZWFuIHtcbiAgaWYgKCFjb3JyZWN0U2hpZnRVc2VkKSByZXR1cm4gZmFsc2U7XG5cbiAgaWYgKENvbmZpZy5tb2RlID09ICd6ZW4nKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBjb25zdCBvcmlnaW5hbENoYXIgPSBUZXN0V29yZHMud29yZHMuZ2V0Q3VycmVudCgpW2NoYXJJbmRleF07XG5cbiAgaWYgKG9yaWdpbmFsQ2hhciA9PSBjaGFyKSB7XG4gICAgcmV0dXJuIHRydWU7XG4gIH1cblxuICBpZiAoQ29uZmlnLmxhbmd1YWdlLnNwbGl0KCdfJylbMF0gPT0gJ3J1c3NpYW4nKSB7XG4gICAgaWYgKChjaGFyID09PSAn0LUnIHx8IGNoYXIgPT09ICdlJykgJiYgb3JpZ2luYWxDaGFyID09ICfRkScpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoY2hhciA9PT0gJ9GRJyAmJiAob3JpZ2luYWxDaGFyID09ICfQtScgfHwgb3JpZ2luYWxDaGFyID09PSAnZScpKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gIH1cblxuICBpZiAoQ29uZmlnLmZ1bmJveCA9PT0gJ2Fycm93cycpIHtcbiAgICBpZiAoKGNoYXIgPT09ICd3JyB8fCBjaGFyID09PSAnQXJyb3dVcCcpICYmIG9yaWdpbmFsQ2hhciA9PSAn4oaRJykge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIGlmICgoY2hhciA9PT0gJ3MnIHx8IGNoYXIgPT09ICdBcnJvd0Rvd24nKSAmJiBvcmlnaW5hbENoYXIgPT0gJ+KGkycpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgICBpZiAoKGNoYXIgPT09ICdhJyB8fCBjaGFyID09PSAnQXJyb3dMZWZ0JykgJiYgb3JpZ2luYWxDaGFyID09ICfihpAnKSB7XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKChjaGFyID09PSAnZCcgfHwgY2hhciA9PT0gJ0Fycm93UmlnaHQnKSAmJiBvcmlnaW5hbENoYXIgPT0gJ+KGkicpIHtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH1cbiAgfVxuXG4gIGlmIChcbiAgICAoY2hhciA9PT0gYOKAmWAgfHwgY2hhciA9PT0gJ+KAmCcgfHwgY2hhciA9PT0gXCInXCIpICYmXG4gICAgKG9yaWdpbmFsQ2hhciA9PSBg4oCZYCB8fCBvcmlnaW5hbENoYXIgPT09ICfigJgnIHx8IG9yaWdpbmFsQ2hhciA9PT0gXCInXCIpXG4gICkge1xuICAgIHJldHVybiB0cnVlO1xuICB9XG5cbiAgaWYgKFxuICAgIChjaGFyID09PSBgXCJgIHx8IGNoYXIgPT09ICfigJ0nIHx8IGNoYXIgPT0gJ+KAnCcgfHwgY2hhciA9PT0gJ+KAnicpICYmXG4gICAgKG9yaWdpbmFsQ2hhciA9PSBgXCJgIHx8IG9yaWdpbmFsQ2hhciA9PT0gJ+KAnScgfHwgb3JpZ2luYWxDaGFyID09PSAn4oCcJyB8fCBvcmlnaW5hbENoYXIgPT09ICfigJ4nKVxuICApIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIGlmIChcbiAgICAoY2hhciA9PT0gJ+KAkycgfHwgY2hhciA9PT0gJ+KAlCcgfHwgY2hhciA9PSAnLScpICYmXG4gICAgKG9yaWdpbmFsQ2hhciA9PSAnLScgfHwgb3JpZ2luYWxDaGFyID09PSAn4oCTJyB8fCBvcmlnaW5hbENoYXIgPT09ICfigJQnKVxuICApIHtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gaGFuZGxlQ2hhcihjaGFyOiBzdHJpbmcsIGNoYXJJbmRleDogbnVtYmVyKTogdm9pZCB7XG4gIGlmIChUZXN0VUkucmVzdWx0Q2FsY3VsYXRpbmcgfHwgVGVzdFVJLnJlc3VsdFZpc2libGUpIHtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoY2hhciA9PT0gJ+KApicpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDM7IGkrKykge1xuICAgICAgaGFuZGxlQ2hhcignLicsIGNoYXJJbmRleCArIGkpO1xuICAgIH1cblxuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChjaGFyID09PSAnXFxuJyAmJiAoQ29uZmlnLmZ1bmJveCA9PT0gJzU4MDA4JyB8fCBDb25maWcuZnVuYm94ID09PSAndGVuS2V5TW9kZScpKSB7XG4gICAgY2hhciA9ICcgJztcbiAgfVxuXG4gIGlmIChjaGFyICE9PSAnXFxuJyAmJiBjaGFyICE9PSAnXFx0JyAmJiAvXFxzLy50ZXN0KGNoYXIpKSB7XG4gICAgaWYgKENvbmZpZy5mdW5ib3ggPT09ICdub3NwYWNlJyB8fCBDb25maWcuZnVuYm94ID09PSAnYXJyb3dzJykgcmV0dXJuO1xuICAgIGhhbmRsZVNwYWNlKCk7XG5cbiAgICAvL2luc2VydCBzcGFjZSBmb3IgZXhwZXJ0IGFuZCBtYXN0ZXIgb3Igc3RyaWN0IHNwYWNlLFxuICAgIC8vb3IgZm9yIHN0b3Agb24gZXJyb3Igc2V0IHRvIHdvcmQsXG4gICAgLy9vdGhlcndpc2UgZG9udCBkbyBhbnl0aGluZ1xuICAgIGlmIChcbiAgICAgIENvbmZpZy5kaWZmaWN1bHR5ICE9PSAnbm9ybWFsJyB8fFxuICAgICAgKENvbmZpZy5zdHJpY3RTcGFjZSAmJiBDb25maWcubW9kZSAhPT0gJ3plbicpIHx8XG4gICAgICBDb25maWcuc3RvcE9uRXJyb3IgPT09ICd3b3JkJ1xuICAgICkge1xuICAgICAgaWYgKGRvbnRJbnNlcnRTcGFjZSkge1xuICAgICAgICBkb250SW5zZXJ0U3BhY2UgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICB9XG5cbiAgaWYgKENvbmZpZy5tb2RlICE9PSAnemVuJyAmJiBUZXN0V29yZHMud29yZHMuZ2V0Q3VycmVudCgpW2NoYXJJbmRleF0gIT09ICdcXG4nICYmIGNoYXIgPT09ICdcXG4nKSB7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy9zdGFydCB0aGUgdGVzdFxuICBpZiAoIVRlc3RBY3RpdmUuZ2V0KCkgJiYgIVRlc3RMb2dpYy5zdGFydFRlc3QoKSkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIEZvY3VzLnNldCh0cnVlKTtcbiAgQ2FyZXQuc3RvcEFuaW1hdGlvbigpO1xuXG4gIGNvbnN0IHRoaXNDaGFyQ29ycmVjdCA9IGlzQ2hhckNvcnJlY3QoY2hhciwgY2hhckluZGV4KTtcblxuICBpZiAodGhpc0NoYXJDb3JyZWN0ICYmIENvbmZpZy5tb2RlICE9PSAnemVuJykge1xuICAgIGNoYXIgPSBUZXN0V29yZHMud29yZHMuZ2V0Q3VycmVudCgpLmNoYXJBdChjaGFySW5kZXgpO1xuICB9XG5cbiAgaWYgKCF0aGlzQ2hhckNvcnJlY3QgJiYgY2hhciA9PT0gJ1xcbicpIHtcbiAgICBpZiAoVGVzdElucHV0LmlucHV0LmN1cnJlbnQgPT09ICcnKSByZXR1cm47XG4gICAgY2hhciA9ICcgJztcbiAgfVxuXG4gIGlmIChUZXN0SW5wdXQuaW5wdXQuY3VycmVudCA9PT0gJycpIHtcbiAgICBUZXN0SW5wdXQuc2V0QnVyc3RTdGFydChwZXJmb3JtYW5jZS5ub3coKSk7XG4gIH1cblxuICBjb25zdCByZXN1bHRpbmdXb3JkID1cbiAgICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5zdWJzdHJpbmcoMCwgY2hhckluZGV4KSArXG4gICAgY2hhciArXG4gICAgVGVzdElucHV0LmlucHV0LmN1cnJlbnQuc3Vic3RyaW5nKGNoYXJJbmRleCArIDEpO1xuXG4gIC8vIElmIGEgdHJhaWxpbmcgY29tcG9zZWQgY2hhciBpcyB1c2VkLCBpZ25vcmUgaXQgd2hlbiBjb3VudGluZyBhY2N1cmFjeVxuICBpZiAoXG4gICAgIXRoaXNDaGFyQ29ycmVjdCAmJlxuICAgIE1pc2MudHJhaWxpbmdDb21wb3NlQ2hhcnMudGVzdChyZXN1bHRpbmdXb3JkKSAmJlxuICAgIENvbXBvc2l0aW9uU3RhdGUuZ2V0Q29tcG9zaW5nKClcbiAgKSB7XG4gICAgVGVzdElucHV0LmlucHV0LmN1cnJlbnQgPSByZXN1bHRpbmdXb3JkO1xuICAgIFRlc3RVSS51cGRhdGVXb3JkRWxlbWVudCgpO1xuICAgIENhcmV0LnVwZGF0ZVBvc2l0aW9uKCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgLy8gTW9ua2V5UG93ZXIuYWRkUG93ZXIodGhpc0NoYXJDb3JyZWN0KTtcbiAgVGVzdElucHV0LmluY3JlbWVudEFjY3VyYWN5KHRoaXNDaGFyQ29ycmVjdCk7XG5cbiAgaWYgKCF0aGlzQ2hhckNvcnJlY3QpIHtcbiAgICBUZXN0SW5wdXQuaW5jcmVtZW50S2V5cHJlc3NFcnJvcnMoKTtcbiAgICBUZXN0SW5wdXQucHVzaE1pc3NlZFdvcmQoVGVzdFdvcmRzLndvcmRzLmdldEN1cnJlbnQoKSk7XG4gIH1cblxuICBXZWFrU3BvdC51cGRhdGVTY29yZShcbiAgICBDb25maWcubW9kZSA9PT0gJ3plbicgPyBjaGFyIDogVGVzdFdvcmRzLndvcmRzLmdldEN1cnJlbnQoKVtjaGFySW5kZXhdLFxuICAgIHRoaXNDaGFyQ29ycmVjdFxuICApO1xuXG4gIGlmICghY29ycmVjdFNoaWZ0VXNlZCAmJiBDb25maWcuZGlmZmljdWx0eSAhPSAnbWFzdGVyJykgcmV0dXJuO1xuXG4gIC8vdXBkYXRlIGN1cnJlbnQgY29ycmVjdGVkIHZlcnNpb24uIGlmIGl0cyBlbXB0eSB0aGVuIGFkZCB0aGUgY3VycmVudCBjaGFyLiBpZiBpdHMgbm90IHRoZW4gcmVwbGFjZSB0aGUgbGFzdCBjaGFyYWN0ZXIgd2l0aCB0aGUgY3VycmVudGx5IHByZXNzZWQgb25lIC8gYWRkIGl0XG4gIGlmIChUZXN0SW5wdXQuY29ycmVjdGVkLmN1cnJlbnQgPT09ICcnKSB7XG4gICAgVGVzdElucHV0LmNvcnJlY3RlZC5jdXJyZW50ICs9IHJlc3VsdGluZ1dvcmQ7XG4gIH0gZWxzZSB7XG4gICAgaWYgKGNoYXJJbmRleCA+PSBUZXN0SW5wdXQuY29ycmVjdGVkLmN1cnJlbnQubGVuZ3RoKSB7XG4gICAgICBUZXN0SW5wdXQuY29ycmVjdGVkLmN1cnJlbnQgKz0gY2hhcjtcbiAgICB9IGVsc2UgaWYgKCF0aGlzQ2hhckNvcnJlY3QpIHtcbiAgICAgIFRlc3RJbnB1dC5jb3JyZWN0ZWQuY3VycmVudCA9XG4gICAgICAgIFRlc3RJbnB1dC5jb3JyZWN0ZWQuY3VycmVudC5zdWJzdHJpbmcoMCwgY2hhckluZGV4KSArXG4gICAgICAgIGNoYXIgK1xuICAgICAgICBUZXN0SW5wdXQuY29ycmVjdGVkLmN1cnJlbnQuc3Vic3RyaW5nKGNoYXJJbmRleCArIDEpO1xuICAgIH1cbiAgfVxuXG4gIFRlc3RJbnB1dC5pbmNyZW1lbnRLZXlwcmVzc0NvdW50KCk7XG4gIFRlc3RJbnB1dC51cGRhdGVMYXN0S2V5cHJlc3MoKTtcbiAgVGVzdElucHV0LnB1c2hLZXlwcmVzc1dvcmQoVGVzdFdvcmRzLndvcmRzLmN1cnJlbnRJbmRleCk7XG5cbiAgaWYgKENvbmZpZy5kaWZmaWN1bHR5ICE9PSAnbWFzdGVyJyAmJiBDb25maWcuc3RvcE9uRXJyb3IgPT0gJ2xldHRlcicgJiYgIXRoaXNDaGFyQ29ycmVjdCkge1xuICAgIHJldHVybjtcbiAgfVxuXG4gIFJlcGxheS5hZGRSZXBsYXlFdmVudCh0aGlzQ2hhckNvcnJlY3QgPyAnY29ycmVjdExldHRlcicgOiAnaW5jb3JyZWN0TGV0dGVyJywgY2hhcik7XG5cbiAgLy91cGRhdGUgdGhlIGFjdGl2ZSB3b3JkIHRvcCwgYnV0IG9ubHkgb25jZVxuICBpZiAoVGVzdElucHV0LmlucHV0LmN1cnJlbnQubGVuZ3RoID09PSAxICYmIFRlc3RXb3Jkcy53b3Jkcy5jdXJyZW50SW5kZXggPT09IDApIHtcbiAgICBUZXN0VUkuc2V0QWN0aXZlV29yZFRvcCgoPEhUTUxFbGVtZW50PmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyN3b3JkcyAuYWN0aXZlJykpPy5vZmZzZXRUb3ApO1xuICB9XG5cbiAgLy9tYXggbGVuZ3RoIG9mIHRoZSBpbnB1dCBpcyAyMCB1bmxlc3MgaW4gemVuIG1vZGUgdGhlbiBpdHMgMzBcbiAgaWYgKFxuICAgIChDb25maWcubW9kZSA9PT0gJ3plbicgJiYgY2hhckluZGV4IDwgMzApIHx8XG4gICAgKENvbmZpZy5tb2RlICE9PSAnemVuJyAmJiBjaGFySW5kZXggPCBUZXN0V29yZHMud29yZHMuZ2V0Q3VycmVudCgpLmxlbmd0aCArIDIwKVxuICApIHtcbiAgICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudCA9IHJlc3VsdGluZ1dvcmQ7XG4gIH1cblxuICBpZiAoIXRoaXNDaGFyQ29ycmVjdCAmJiBDb25maWcuZGlmZmljdWx0eSA9PSAnbWFzdGVyJykge1xuICAgIFRlc3RJbnB1dC5pbnB1dC5wdXNoSGlzdG9yeSgpO1xuICAgIFRlc3RJbnB1dC5jb3JyZWN0ZWQucHVzaEhpc3RvcnkoKTtcbiAgICBUZXN0TG9naWMuZmFpbCgnZGlmZmljdWx0eScpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChDb25maWcubW9kZSAhPSAnemVuJykge1xuICAgIC8vbm90IGFwcGxpY2FibGUgdG8gemVuIG1vZGVcbiAgICAvL2F1dG8gc3RvcCB0aGUgdGVzdCBpZiB0aGUgbGFzdCB3b3JkIGlzIGNvcnJlY3RcbiAgICBjb25zdCBjdXJyZW50V29yZCA9IFRlc3RXb3Jkcy53b3Jkcy5nZXRDdXJyZW50KCk7XG4gICAgY29uc3QgbGFzdGluZGV4ID0gVGVzdFdvcmRzLndvcmRzLmN1cnJlbnRJbmRleDtcbiAgICBpZiAoXG4gICAgICAoY3VycmVudFdvcmQgPT0gVGVzdElucHV0LmlucHV0LmN1cnJlbnQgfHxcbiAgICAgICAgKENvbmZpZy5xdWlja0VuZCAmJlxuICAgICAgICAgIGN1cnJlbnRXb3JkLmxlbmd0aCA9PSBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5sZW5ndGggJiZcbiAgICAgICAgICBDb25maWcuc3RvcE9uRXJyb3IgPT0gJ29mZicpKSAmJlxuICAgICAgbGFzdGluZGV4ID09IFRlc3RXb3Jkcy53b3Jkcy5sZW5ndGggLSAxXG4gICAgKSB7XG4gICAgICBUZXN0SW5wdXQuaW5wdXQucHVzaEhpc3RvcnkoKTtcbiAgICAgIFRlc3RJbnB1dC5jb3JyZWN0ZWQucHVzaEhpc3RvcnkoKTtcbiAgICAgIFRlc3RMb2dpYy5maW5pc2goKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gIH1cblxuICBjb25zdCBhY3RpdmVXb3JkVG9wQmVmb3JlSnVtcCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3I8SFRNTEVsZW1lbnQ+KCcjd29yZHMgLndvcmQuYWN0aXZlJylcbiAgICA/Lm9mZnNldFRvcCBhcyBudW1iZXI7XG4gIFRlc3RVSS51cGRhdGVXb3JkRWxlbWVudCgpO1xuXG4gIGlmICghQ29uZmlnLmhpZGVFeHRyYUxldHRlcnMpIHtcbiAgICBjb25zdCBuZXdBY3RpdmVUb3AgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxFbGVtZW50PignI3dvcmRzIC53b3JkLmFjdGl2ZScpXG4gICAgICA/Lm9mZnNldFRvcCBhcyBudW1iZXI7XG4gICAgLy9zdG9wIHRoZSB3b3JkIGp1bXAgYnkgc2xpY2luZyBvZmYgdGhlIGxhc3QgY2hhcmFjdGVyLCB1cGRhdGUgd29yZCBhZ2FpblxuICAgIGlmIChcbiAgICAgIGFjdGl2ZVdvcmRUb3BCZWZvcmVKdW1wIDwgbmV3QWN0aXZlVG9wICYmXG4gICAgICAhVGVzdFVJLmxpbmVUcmFuc2l0aW9uICYmXG4gICAgICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5sZW5ndGggPiAxXG4gICAgKSB7XG4gICAgICBpZiAoQ29uZmlnLm1vZGUgPT0gJ3plbicpIHtcbiAgICAgICAgY29uc3QgY3VycmVudFRvcCA9IE1hdGguZmxvb3IoXG4gICAgICAgICAgZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbDxIVE1MRWxlbWVudD4oJyN3b3JkcyAud29yZCcpW1Rlc3RVSS5jdXJyZW50V29yZEVsZW1lbnRJbmRleCAtIDFdXG4gICAgICAgICAgICA/Lm9mZnNldFRvcFxuICAgICAgICApIGFzIG51bWJlcjtcbiAgICAgICAgaWYgKCFDb25maWcuc2hvd0FsbExpbmVzKSBUZXN0VUkubGluZUp1bXAoY3VycmVudFRvcCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudCA9IFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50LnNsaWNlKDAsIC0xKTtcbiAgICAgICAgVGVzdFVJLnVwZGF0ZVdvcmRFbGVtZW50KCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLy9zaW11bGF0ZSBzcGFjZSBwcmVzcyBpbiBub3NwYWNlIGZ1bmJveFxuICBpZiAoXG4gICAgKChDb25maWcuZnVuYm94ID09PSAnbm9zcGFjZScgfHwgQ29uZmlnLmZ1bmJveCA9PT0gJ2Fycm93cycpICYmXG4gICAgICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5sZW5ndGggPT09IFRlc3RXb3Jkcy53b3Jkcy5nZXRDdXJyZW50KCkubGVuZ3RoKSB8fFxuICAgIChjaGFyID09PSAnXFxuJyAmJiB0aGlzQ2hhckNvcnJlY3QpXG4gICkge1xuICAgIGhhbmRsZVNwYWNlKCk7XG4gIH1cblxuICBpZiAoY2hhciAhPT0gJ1xcbicpIHtcbiAgICBDYXJldC51cGRhdGVQb3NpdGlvbigpO1xuICB9XG59XG5cbmZ1bmN0aW9uIGhhbmRsZVRhYihcbiAgZXZlbnQ6IHsgcHJldmVudERlZmF1bHQ6ICgpID0+IHZvaWQ7IHNoaWZ0S2V5OiBhbnkgfSxcbiAgcG9wdXBWaXNpYmxlOiBib29sZWFuXG4pOiB2b2lkIHtcbiAgaWYgKFRlc3RVSS5yZXN1bHRDYWxjdWxhdGluZykge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgbGV0IHNob3VsZEluc2VydFRhYkNoYXJhY3RlciA9IGZhbHNlO1xuXG4gIGlmICgoQ29uZmlnLm1vZGUgPT0gJ3plbicgJiYgIWV2ZW50LnNoaWZ0S2V5KSB8fCAoVGVzdFdvcmRzLmhhc1RhYiAmJiAhZXZlbnQuc2hpZnRLZXkpKSB7XG4gICAgc2hvdWxkSW5zZXJ0VGFiQ2hhcmFjdGVyID0gdHJ1ZTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0V29yZHNJbnB1dEVsZW1lbnQod29yZHNFbGVtZW50OiBIVE1MSW5wdXRFbGVtZW50KSB7XG4gIHdvcmRzSW5wdXQgPSB3b3Jkc0VsZW1lbnQ7XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBpbnB1dEtleWRvd24oZXZlbnQ6IGFueSwgd29yZHNGb2N1c2VkOiBib29sZWFuKSB7XG4gIGNvbnN0IGFsbG93VHlwaW5nID0gIVRlc3RVSS5yZXN1bHRWaXNpYmxlICYmICh3b3Jkc0ZvY3VzZWQgfHwgZXZlbnQua2V5ICE9PSAnRW50ZXInKTtcblxuICAvL25vIHNwYWNlIGZvciB0ZW5LZXlNb2RlXG4gIGlmIChDb25maWcuZnVuYm94ID09PSAndGVuS2V5TW9kZScgJiYgZXZlbnQua2V5Q29kZSA9PT0gMzIpIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICB9XG5cbiAgaWYgKGFsbG93VHlwaW5nICYmICF3b3Jkc0ZvY3VzZWQgJiYgZXZlbnQua2V5ICE9PSAnRW50ZXInKSB7XG4gICAgVGVzdFVJLmZvY3VzV29yZHMoKTtcbiAgICBpZiAoQ29uZmlnLnNob3dPdXRPZkZvY3VzV2FybmluZykge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG4gIH1cblxuICAvL3RhYlxuICBpZiAoZXZlbnQua2V5ID09ICdUYWInKSB7XG4gICAgaGFuZGxlVGFiKGV2ZW50LCBmYWxzZSk7XG4gIH1cblxuICBpZiAoIWFsbG93VHlwaW5nKSByZXR1cm47XG5cbiAgaWYgKCFldmVudC5pc1RydXN0ZWQgfHwgVGVzdFVJLnRlc3RSZXN0YXJ0aW5nKSB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICByZXR1cm47XG4gIH1cblxuICBpZiAoVGVzdElucHV0LnNwYWNpbmdEZWJ1Zykge1xuICAgIGNvbnNvbGUubG9nKFxuICAgICAgJ3NwYWNpbmcgZGVidWcnLFxuICAgICAgJ2tleXByZXNzJyxcbiAgICAgIGV2ZW50LmtleSxcbiAgICAgICdsZW5ndGgnLFxuICAgICAgVGVzdElucHV0LmtleXByZXNzVGltaW5ncy5zcGFjaW5nLmFycmF5Lmxlbmd0aFxuICAgICk7XG4gIH1cbiAgVGVzdElucHV0LnJlY29yZEtleXByZXNzU3BhY2luZygpO1xuICBUZXN0SW5wdXQuc2V0S2V5cHJlc3NEdXJhdGlvbihwZXJmb3JtYW5jZS5ub3coKSk7XG4gIFRlc3RJbnB1dC5zZXRLZXlwcmVzc05vdEFmaygpO1xuXG4gIC8vYmxvY2tpbmcgZmlyZWZveCBmcm9tIGdvaW5nIGJhY2sgaW4gaGlzdG9yeSB3aXRoIGJhY2tzcGFjZVxuICBpZiAoZXZlbnQua2V5ID09PSAnQmFja3NwYWNlJykge1xuICAgIGNvbnN0IHQgPSAvSU5QVVR8U0VMRUNUfFRFWFRBUkVBL2k7XG4gICAgaWYgKCF0LnRlc3QoKGV2ZW50LnRhcmdldCBhcyB1bmtub3duIGFzIEVsZW1lbnQpLnRhZ05hbWUpKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIGlmIChDb25maWcuY29uZmlkZW5jZU1vZGUgPT09ICdtYXgnKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgfVxuXG4gIGlmIChDb25maWcuZnVuYm94ICE9PSAnYXJyb3dzJyAmJiAvQXJyb3cvaS50ZXN0KGV2ZW50LmtleSkpIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChldmVudC5rZXkgPT09ICdCYWNrc3BhY2UnICYmIFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50Lmxlbmd0aCA9PT0gMCkge1xuICAgIGJhY2tzcGFjZVRvUHJldmlvdXMoKTtcbiAgICBpZiAoVGVzdElucHV0LmlucHV0LmN1cnJlbnQpIHtcbiAgICAgIHNldFdvcmRzSW5wdXQoJyAnICsgVGVzdElucHV0LmlucHV0LmN1cnJlbnQgKyAnICcpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChldmVudC5rZXkgPT09ICdFbnRlcicpIHtcbiAgICBpZiAoZXZlbnQuc2hpZnRLZXkgJiYgQ29uZmlnLm1vZGUgPT0gJ3plbicpIHtcbiAgICAgIFRlc3RMb2dpYy5maW5pc2goKTtcbiAgICB9IGVsc2UgaWYgKFxuICAgICAgZXZlbnQuc2hpZnRLZXkgJiZcbiAgICAgICgoQ29uZmlnLm1vZGUgPT0gJ3RpbWUnICYmIENvbmZpZy50aW1lID09PSAwKSB8fFxuICAgICAgICAoQ29uZmlnLm1vZGUgPT0gJ3dvcmRzJyAmJiBDb25maWcud29yZHMgPT09IDApKVxuICAgICkge1xuICAgICAgVGVzdElucHV0LnNldEJhaWxvdXQodHJ1ZSk7XG4gICAgICBUZXN0TG9naWMuZmluaXNoKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIGhhbmRsZUNoYXIoJ1xcbicsIFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50Lmxlbmd0aCk7XG4gICAgICBzZXRXb3Jkc0lucHV0KCcgJyArIFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50KTtcbiAgICB9XG4gIH1cblxuICAvL3Nob3cgZGVhZCBrZXlzXG4gIGlmIChldmVudC5rZXkgPT09ICdEZWFkJyAmJiAhQ29tcG9zaXRpb25TdGF0ZS5nZXRDb21wb3NpbmcoKSkge1xuICAgIGNvbnN0IHdvcmQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yPEhUTUxFbGVtZW50PignI3dvcmRzIC53b3JkLmFjdGl2ZScpO1xuICAgIGNvbnN0IGxlbiA9IFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50Lmxlbmd0aDsgLy8gaGF2ZSB0byBkbyB0aGlzIGJlY2F1c2UgcHJldHRpZXIgd3JhcHMgdGhlIGxpbmUgYW5kIGNhdXNlcyBhbiBlcnJvclxuXG4gICAgLy8gQ2hlY2sgdG8gc2VlIGlmIHRoZSBsZXR0ZXIgYWN0dWFsbHkgZXhpc3RzIHRvIHRvZ2dsZSBpdCBhcyBkZWFkXG4gICAgY29uc3QgZGVhZExldHRlciA9IHdvcmQ/LnF1ZXJ5U2VsZWN0b3JBbGwoJ2xldHRlcicpW2xlbl07XG4gICAgaWYgKGRlYWRMZXR0ZXIpIHtcbiAgICAgIGRlYWRMZXR0ZXIuY2xhc3NMaXN0LnRvZ2dsZSgnZGVhZCcpO1xuICAgIH1cbiAgfVxuXG4gIGlmIChDb25maWcuZnVuYm94ID09PSAnYXJyb3dzJykge1xuICAgIGxldCBjaGFyID0gZXZlbnQua2V5O1xuICAgIGlmIChbJ0Fycm93TGVmdCcsICdBcnJvd1VwJywgJ0Fycm93UmlnaHQnLCAnQXJyb3dEb3duJ10uaW5jbHVkZXMoY2hhcikpIHtcbiAgICAgIGlmIChjaGFyID09PSAnQXJyb3dMZWZ0JykgY2hhciA9ICdhJztcbiAgICAgIGlmIChjaGFyID09PSAnQXJyb3dSaWdodCcpIGNoYXIgPSAnZCc7XG4gICAgICBpZiAoY2hhciA9PT0gJ0Fycm93RG93bicpIGNoYXIgPSAncyc7XG4gICAgICBpZiAoY2hhciA9PT0gJ0Fycm93VXAnKSBjaGFyID0gJ3cnO1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgIGhhbmRsZUNoYXIoY2hhciwgVGVzdElucHV0LmlucHV0LmN1cnJlbnQubGVuZ3RoKTtcbiAgICAgIHVwZGF0ZVVJKCk7XG4gICAgICBzZXRXb3Jkc0lucHV0KCcgJyArIFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50KTtcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdvcmRzSW5wdXRLZXl1cChldmVudDogYW55KSB7XG4gIGlmICghZXZlbnQuaXNUcnVzdGVkIHx8IFRlc3RVSS50ZXN0UmVzdGFydGluZykge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgcmV0dXJuO1xuICB9XG5cbiAgaWYgKFRlc3RVSS5yZXN1bHRWaXNpYmxlKSByZXR1cm47XG4gIGNvbnN0IG5vdyA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICBpZiAoVGVzdElucHV0LmtleXByZXNzVGltaW5ncy5kdXJhdGlvbi5jdXJyZW50ICE9PSAtMSkge1xuICAgIGNvbnN0IGRpZmYgPSBNYXRoLmFicyhUZXN0SW5wdXQua2V5cHJlc3NUaW1pbmdzLmR1cmF0aW9uLmN1cnJlbnQgLSBub3cpO1xuICAgIFRlc3RJbnB1dC5wdXNoS2V5cHJlc3NEdXJhdGlvbihkaWZmKTtcbiAgfVxuICBUZXN0SW5wdXQuc2V0S2V5cHJlc3NEdXJhdGlvbihub3cpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd29yZHNJbnB1dEJlZm9yZWlucHV0KGV2ZW50OiBhbnkpIHtcbiAgaWYgKCFldmVudC5pc1RydXN0ZWQpIHJldHVybjtcbiAgaWYgKChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWUgPT09ICcnKSB7XG4gICAgKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZSA9ICcgJztcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gd29yZHNJbnB1dElucHV0KGV2ZW50OiBhbnkpIHtcbiAgaWYgKCFldmVudC5pc1RydXN0ZWQgfHwgVGVzdFVJLnRlc3RSZXN0YXJ0aW5nKSB7XG4gICAgKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZSA9ICcgJztcbiAgICByZXR1cm47XG4gIH1cblxuICBUZXN0SW5wdXQuc2V0S2V5cHJlc3NOb3RBZmsoKTtcblxuICBjb25zdCByZWFsSW5wdXRWYWx1ZSA9IChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWUubm9ybWFsaXplKCk7XG4gIGNvbnN0IGlucHV0VmFsdWUgPSByZWFsSW5wdXRWYWx1ZS5zbGljZSgxKTtcblxuICAvLyBpbnB1dCB3aWxsIGJlIG1vZGlmaWVkIGV2ZW4gd2l0aCB0aGUgcHJldmVudERlZmF1bHQoKSBpblxuICAvLyBiZWZvcmVpbnB1dC9rZXlkb3duIGlmIGl0J3MgcGFydCBvZiBhIGNvbXBvc2Ugc2VxdWVuY2UuIHRoaXMgdW5kb2VzXG4gIC8vIHRoZSBlZmZlY3RzIG9mIHRoYXQgYW5kIHRha2VzIHRoZSBpbnB1dCBvdXQgb2YgY29tcG9zZSBtb2RlLlxuICBpZiAoQ29uZmlnLmxheW91dCAhPT0gJ2RlZmF1bHQnICYmIGlucHV0VmFsdWUubGVuZ3RoID49IFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50Lmxlbmd0aCkge1xuICAgIHNldFdvcmRzSW5wdXQoJyAnICsgVGVzdElucHV0LmlucHV0LmN1cnJlbnQpO1xuICAgIHJldHVybjtcbiAgfVxuXG4gIGlmIChyZWFsSW5wdXRWYWx1ZS5sZW5ndGggPT09IDAgJiYgVGVzdElucHV0LmlucHV0LmN1cnJlbnQubGVuZ3RoID09PSAwKSB7XG4gICAgLy8gZmFsbGJhY2sgZm9yIHdoZW4gbm8gQmFja3NwYWNlIGtleWRvd24gZXZlbnQgKG1vYmlsZSlcbiAgICBiYWNrc3BhY2VUb1ByZXZpb3VzKCk7XG4gIH0gZWxzZSBpZiAoaW5wdXRWYWx1ZS5sZW5ndGggPCBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5sZW5ndGgpIHtcbiAgICBUZXN0SW5wdXQuaW5wdXQuY3VycmVudCA9IGlucHV0VmFsdWU7XG4gICAgVGVzdFVJLnVwZGF0ZVdvcmRFbGVtZW50KCk7XG4gICAgQ2FyZXQudXBkYXRlUG9zaXRpb24oKTtcbiAgICBpZiAoIUNvbXBvc2l0aW9uU3RhdGUuZ2V0Q29tcG9zaW5nKCkpIHtcbiAgICAgIFJlcGxheS5hZGRSZXBsYXlFdmVudCgnc2V0TGV0dGVySW5kZXgnLCBUZXN0SW5wdXQuaW5wdXQuY3VycmVudC5sZW5ndGgpO1xuICAgIH1cbiAgfSBlbHNlIGlmIChpbnB1dFZhbHVlICE9PSBUZXN0SW5wdXQuaW5wdXQuY3VycmVudCkge1xuICAgIGxldCBkaWZmU3RhcnQgPSAwO1xuICAgIHdoaWxlIChpbnB1dFZhbHVlW2RpZmZTdGFydF0gPT09IFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50W2RpZmZTdGFydF0pIHtcbiAgICAgIGRpZmZTdGFydCsrO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSBkaWZmU3RhcnQ7IGkgPCBpbnB1dFZhbHVlLmxlbmd0aDsgaSsrKSB7XG4gICAgICBoYW5kbGVDaGFyKGlucHV0VmFsdWVbaV0sIGkpO1xuICAgIH1cbiAgfVxuXG4gIHNldFdvcmRzSW5wdXQoJyAnICsgVGVzdElucHV0LmlucHV0LmN1cnJlbnQpO1xuICB1cGRhdGVVSSgpO1xuXG4gIGNvbnN0IHN0YXRlYmVmb3JlID0gQ29tcG9zaXRpb25TdGF0ZS5nZXRDb21wb3NpbmcoKTtcbiAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgLy8gY2hlY2tpbmcgY29tcG9zaXRpb24gc3RhdGUgZHVyaW5nIHRoZSBpbnB1dCBldmVudCBhbmQgb24gdGhlIG5leHQgbG9vcFxuICAgIC8vIHRoaXMgaXMgZG9uZSBiZWNhdXNlIHNvbWUgYnJvd3NlcnMgKGUuZy4gQ2hyb21lKSB3aWxsIGZpcmUgdGhlIGlucHV0XG4gICAgLy8gZXZlbnQgYmVmb3JlIHRoZSBjb21wb3NpdGlvbmVuZCBldmVudC5cbiAgICAvLyB0aGlzIGVuc3VyZXMgdGhlIFVJIGlzIGNvcnJlY3RcblxuICAgIGNvbnN0IHN0YXRlYWZ0ZXIgPSBDb21wb3NpdGlvblN0YXRlLmdldENvbXBvc2luZygpO1xuICAgIGlmIChzdGF0ZWJlZm9yZSAhPT0gc3RhdGVhZnRlcikge1xuICAgICAgVGVzdFVJLnVwZGF0ZVdvcmRFbGVtZW50KCk7XG4gICAgfVxuXG4gICAgLy8gZm9yY2UgY2FyZXQgYXQgZW5kIG9mIGlucHV0XG4gICAgLy8gZG9pbmcgaXQgb24gbmV4dCBjeWNsZSBiZWNhdXNlIENocm9taXVtIG9uIEFuZHJvaWQgd29uJ3QgbGV0IG1lIGVkaXRcbiAgICAvLyB0aGUgc2VsZWN0aW9uIGluc2lkZSB0aGUgaW5wdXQgZXZlbnRcbiAgICBpZiAoXG4gICAgICAoZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQpLnNlbGVjdGlvblN0YXJ0ICE9PVxuICAgICAgICAoZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQpLnZhbHVlLmxlbmd0aCAmJlxuICAgICAgKCFNaXNjLnRyYWlsaW5nQ29tcG9zZUNoYXJzLnRlc3QoKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZSkgfHxcbiAgICAgICAgKChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkuc2VsZWN0aW9uU3RhcnQgPz8gMCkgPFxuICAgICAgICAgIChldmVudC50YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWUuc2VhcmNoKE1pc2MudHJhaWxpbmdDb21wb3NlQ2hhcnMpKVxuICAgICkge1xuICAgICAgKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS5zZWxlY3Rpb25TdGFydCA9IChcbiAgICAgICAgZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnRcbiAgICAgICkuc2VsZWN0aW9uRW5kID0gKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZS5sZW5ndGg7XG4gICAgfVxuICB9LCAwKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdvcmRzSW5wdXRGb2N1cyhldmVudDogeyB0YXJnZXQ6IEhUTUxJbnB1dEVsZW1lbnQgfSkge1xuICAoZXZlbnQudGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQpLnNlbGVjdGlvblN0YXJ0ID0gKFxuICAgIGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50XG4gICkuc2VsZWN0aW9uRW5kID0gKGV2ZW50LnRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZS5sZW5ndGg7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3b3Jkc0lucHV0Q29weShldmVudDogeyBwcmV2ZW50RGVmYXVsdDogKCkgPT4gdm9pZCB9KSB7XG4gIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3b3Jkc0lucHV0UGFzdGUoZXZlbnQ6IHsgcHJldmVudERlZmF1bHQ6ICgpID0+IHZvaWQgfSkge1xuICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xufVxuXG4vLyBDb21wb3NpbmcgZXZlbnRzXG5leHBvcnQgZnVuY3Rpb24gd29yZHNJbnB1dENvbXBvc2l0aW9uc3RhcnQoKSB7XG4gIENvbXBvc2l0aW9uU3RhdGUuc2V0Q29tcG9zaW5nKHRydWUpO1xuICBDb21wb3NpdGlvblN0YXRlLnNldFN0YXJ0UG9zKFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50Lmxlbmd0aCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3b3Jkc0lucHV0Q29tcG9zaXRpb25lbmQoKSB7XG4gIENvbXBvc2l0aW9uU3RhdGUuc2V0Q29tcG9zaW5nKGZhbHNlKTtcbn1cbiJdfQ==