@testgorilla/tgo-typing-test 1.0.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (134) hide show
  1. package/.eslintrc.json +46 -0
  2. package/jest.config.ts +21 -0
  3. package/ng-package.json +15 -0
  4. package/package.json +7 -22
  5. package/project.json +36 -0
  6. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.html +30 -0
  7. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.spec.ts +250 -0
  8. package/src/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.ts +47 -0
  9. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.html +72 -0
  10. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.spec.ts +699 -0
  11. package/src/lib/components/tgo-typing-test/tgo-typing-test.component.ts +287 -0
  12. package/src/lib/helpers/config.ts +28 -0
  13. package/src/lib/helpers/constants/default-config.ts +103 -0
  14. package/src/lib/helpers/controllers/input-controller.ts +710 -0
  15. package/src/lib/helpers/controllers/quotes-controller.ts +183 -0
  16. package/src/lib/helpers/observables/banner-event.ts +18 -0
  17. package/src/lib/helpers/observables/config-event.ts +31 -0
  18. package/src/lib/helpers/observables/timer-event.ts +18 -0
  19. package/src/lib/helpers/states/active-page.ts +9 -0
  20. package/src/lib/helpers/states/composition.ts +29 -0
  21. package/src/lib/helpers/states/page-transition.ts +9 -0
  22. package/src/lib/helpers/states/slow-timer.ts +16 -0
  23. package/src/lib/helpers/states/test-active.ts +9 -0
  24. package/src/lib/helpers/states/time.ts +13 -0
  25. package/src/lib/helpers/test/caps-warning.ts +50 -0
  26. package/src/lib/helpers/test/caret.ts +92 -0
  27. package/src/lib/helpers/test/custom-text.ts +73 -0
  28. package/src/lib/helpers/test/english-punctuation.ts +38 -0
  29. package/src/lib/helpers/test/focus.ts +39 -0
  30. package/src/lib/helpers/test/manual-restart-tracker.ts +13 -0
  31. package/src/lib/helpers/test/out-of-focus.ts +19 -0
  32. package/src/lib/helpers/test/replay.ts +265 -0
  33. package/src/lib/helpers/test/test-input.ts +320 -0
  34. package/src/lib/helpers/test/test-logic.ts +1039 -0
  35. package/src/lib/helpers/test/test-state.ts +17 -0
  36. package/src/lib/helpers/test/test-stats.ts +442 -0
  37. package/src/lib/helpers/test/test-timer.ts +209 -0
  38. package/src/lib/helpers/test/test-ui.ts +370 -0
  39. package/src/lib/helpers/test/test-words.ts +72 -0
  40. package/src/lib/helpers/test/timer-progress.ts +16 -0
  41. package/src/lib/helpers/test/tts.ts +42 -0
  42. package/src/lib/helpers/test/weak-spot.ts +74 -0
  43. package/src/lib/helpers/test/wordset.ts +109 -0
  44. package/src/lib/styles/animations.scss +101 -0
  45. package/src/lib/styles/caret.scss +108 -0
  46. package/src/lib/styles/core.scss +498 -0
  47. package/src/lib/styles/index.scss +19 -0
  48. package/src/lib/styles/inputs.scss +290 -0
  49. package/src/lib/styles/popups.scss +1311 -0
  50. package/src/lib/styles/test.scss +1008 -0
  51. package/src/lib/styles/z_media-queries.scss +848 -0
  52. package/src/lib/types/types.d.ts +731 -0
  53. package/src/lib/utils/misc.ts +776 -0
  54. package/src/test-setup.ts +20 -0
  55. package/tsconfig.json +16 -0
  56. package/tsconfig.lib.json +14 -0
  57. package/tsconfig.lib.prod.json +9 -0
  58. package/tsconfig.spec.json +11 -0
  59. package/esm2022/index.mjs +0 -3
  60. package/esm2022/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.mjs +0 -45
  61. package/esm2022/lib/components/tgo-typing-test/tgo-typing-test.component.mjs +0 -299
  62. package/esm2022/lib/helpers/config.mjs +0 -24
  63. package/esm2022/lib/helpers/constants/default-config.mjs +0 -103
  64. package/esm2022/lib/helpers/controllers/input-controller.mjs +0 -586
  65. package/esm2022/lib/helpers/controllers/quotes-controller.mjs +0 -118
  66. package/esm2022/lib/helpers/observables/config-event.mjs +0 -16
  67. package/esm2022/lib/helpers/observables/timer-event.mjs +0 -16
  68. package/esm2022/lib/helpers/states/active-page.mjs +0 -8
  69. package/esm2022/lib/helpers/states/composition.mjs +0 -20
  70. package/esm2022/lib/helpers/states/page-transition.mjs +0 -8
  71. package/esm2022/lib/helpers/states/slow-timer.mjs +0 -15
  72. package/esm2022/lib/helpers/states/test-active.mjs +0 -8
  73. package/esm2022/lib/helpers/states/time.mjs +0 -11
  74. package/esm2022/lib/helpers/test/caps-warning.mjs +0 -50
  75. package/esm2022/lib/helpers/test/caret.mjs +0 -80
  76. package/esm2022/lib/helpers/test/custom-text.mjs +0 -59
  77. package/esm2022/lib/helpers/test/english-punctuation.mjs +0 -29
  78. package/esm2022/lib/helpers/test/focus.mjs +0 -35
  79. package/esm2022/lib/helpers/test/manual-restart-tracker.mjs +0 -11
  80. package/esm2022/lib/helpers/test/out-of-focus.mjs +0 -14
  81. package/esm2022/lib/helpers/test/replay.mjs +0 -217
  82. package/esm2022/lib/helpers/test/test-input.mjs +0 -264
  83. package/esm2022/lib/helpers/test/test-logic.mjs +0 -927
  84. package/esm2022/lib/helpers/test/test-state.mjs +0 -13
  85. package/esm2022/lib/helpers/test/test-stats.mjs +0 -342
  86. package/esm2022/lib/helpers/test/test-timer.mjs +0 -207
  87. package/esm2022/lib/helpers/test/test-ui.mjs +0 -341
  88. package/esm2022/lib/helpers/test/test-words.mjs +0 -69
  89. package/esm2022/lib/helpers/test/timer-progress.mjs +0 -15
  90. package/esm2022/lib/helpers/test/weak-spot.mjs +0 -65
  91. package/esm2022/lib/helpers/test/wordset.mjs +0 -100
  92. package/esm2022/lib/utils/misc.mjs +0 -673
  93. package/esm2022/testgorilla-tgo-typing-test.mjs +0 -5
  94. package/fesm2022/testgorilla-tgo-typing-test.mjs +0 -4707
  95. package/fesm2022/testgorilla-tgo-typing-test.mjs.map +0 -1
  96. package/lib/components/tgo-typing-replay-input/tgo-typing-replay-input.component.d.ts +0 -14
  97. package/lib/components/tgo-typing-test/tgo-typing-test.component.d.ts +0 -54
  98. package/lib/helpers/config.d.ts +0 -98
  99. package/lib/helpers/constants/default-config.d.ts +0 -3
  100. package/lib/helpers/controllers/input-controller.d.ts +0 -16
  101. package/lib/helpers/controllers/quotes-controller.d.ts +0 -20
  102. package/lib/helpers/observables/config-event.d.ts +0 -5
  103. package/lib/helpers/observables/timer-event.d.ts +0 -4
  104. package/lib/helpers/states/active-page.d.ts +0 -2
  105. package/lib/helpers/states/composition.d.ts +0 -10
  106. package/lib/helpers/states/page-transition.d.ts +0 -2
  107. package/lib/helpers/states/slow-timer.d.ts +0 -3
  108. package/lib/helpers/states/test-active.d.ts +0 -2
  109. package/lib/helpers/states/time.d.ts +0 -3
  110. package/lib/helpers/test/caps-warning.d.ts +0 -5
  111. package/lib/helpers/test/caret.d.ts +0 -11
  112. package/lib/helpers/test/custom-text.d.ts +0 -16
  113. package/lib/helpers/test/english-punctuation.d.ts +0 -3
  114. package/lib/helpers/test/focus.d.ts +0 -7
  115. package/lib/helpers/test/manual-restart-tracker.d.ts +0 -3
  116. package/lib/helpers/test/out-of-focus.d.ts +0 -4
  117. package/lib/helpers/test/replay.d.ts +0 -20
  118. package/lib/helpers/test/test-input.d.ts +0 -86
  119. package/lib/helpers/test/test-logic.d.ts +0 -25
  120. package/lib/helpers/test/test-state.d.ts +0 -7
  121. package/lib/helpers/test/test-stats.d.ts +0 -92
  122. package/lib/helpers/test/test-timer.d.ts +0 -6
  123. package/lib/helpers/test/test-ui.d.ts +0 -27
  124. package/lib/helpers/test/test-words.d.ts +0 -23
  125. package/lib/helpers/test/timer-progress.d.ts +0 -3
  126. package/lib/helpers/test/weak-spot.d.ts +0 -3
  127. package/lib/helpers/test/wordset.d.ts +0 -7
  128. package/lib/utils/misc.d.ts +0 -81
  129. /package/{assets → src/assets}/typing-test-languages/english.json +0 -0
  130. /package/{assets → src/assets}/typing-test-languages/english_punctuation.json +0 -0
  131. /package/{assets → src/assets}/typing-test-languages/quotes/english_version_1.json +0 -0
  132. /package/{assets → src/assets}/typing-test-languages/quotes/english_version_2.json +0 -0
  133. /package/{assets → src/assets}/typing-test-languages/quotes/filtered_sources.json +0 -0
  134. /package/{index.d.ts → src/index.ts} +0 -0
@@ -1,341 +0,0 @@
1
- import Config from '../../helpers/config';
2
- import * as TestWords from './test-words';
3
- import * as TestInput from './test-input';
4
- import * as Caret from './caret';
5
- import * as OutOfFocus from './out-of-focus';
6
- import * as Misc from '../../utils/misc';
7
- import * as CompositionState from '../states/composition';
8
- let wordsWrapper;
9
- let wordsInput;
10
- let words;
11
- export let currentWordElementIndex = 0;
12
- export let resultVisible = false;
13
- export let activeWordTop = 0;
14
- export let testRestarting = false;
15
- export let testRestartingPromise;
16
- export const lineTransition = false;
17
- export let currentTestLine = 0;
18
- export let resultCalculating = false;
19
- export function setWordsWrapperElement(wordsWrapperElem) {
20
- wordsWrapper = wordsWrapperElem;
21
- }
22
- export function setWordsInputElementTestUI(wordsElement) {
23
- wordsInput = wordsElement;
24
- }
25
- export function setWordsElement(wordsElem) {
26
- words = wordsElem;
27
- }
28
- export function setResultVisible(val) {
29
- resultVisible = val;
30
- }
31
- export function setCurrentWordElementIndex(val) {
32
- currentWordElementIndex = val;
33
- }
34
- export function setActiveWordTop(val) {
35
- activeWordTop = val;
36
- }
37
- let restartingResolve;
38
- export function setTestRestarting(val) {
39
- testRestarting = val;
40
- if (val === true) {
41
- testRestartingPromise = new Promise(resolve => {
42
- restartingResolve = resolve;
43
- });
44
- }
45
- else {
46
- if (restartingResolve)
47
- restartingResolve();
48
- restartingResolve = null;
49
- }
50
- }
51
- export function setResultCalculating(val) {
52
- resultCalculating = val;
53
- }
54
- export function reset() {
55
- currentTestLine = 0;
56
- currentWordElementIndex = 0;
57
- }
58
- export function focusWords() {
59
- if (!wordsWrapper.classList.contains('hidden')) {
60
- wordsInput.focus();
61
- }
62
- }
63
- export function updateActiveElement(backspace) {
64
- const active = document.querySelector('#words .active');
65
- if (Config.mode == 'zen' && backspace) {
66
- active?.remove();
67
- }
68
- else if (active !== null) {
69
- if (Config.highlightMode == 'word') {
70
- active.querySelectorAll('letter').forEach(e => {
71
- e.classList.remove('correct');
72
- });
73
- }
74
- active.classList.remove('active');
75
- }
76
- try {
77
- const activeWord = document.querySelectorAll('#words .word')[currentWordElementIndex];
78
- activeWord.classList.add('active');
79
- activeWord.classList.remove('error');
80
- activeWordTop = document.querySelector('#words .active').offsetTop;
81
- if (Config.highlightMode == 'word') {
82
- activeWord.querySelectorAll('letter').forEach(e => {
83
- e.classList.add('correct');
84
- });
85
- }
86
- }
87
- catch (e) {
88
- console.error(e);
89
- }
90
- }
91
- function getWordHTML(word) {
92
- let newlineafter = false;
93
- let retval = `<div class='word'>`;
94
- for (let c = 0; c < word.length; c++) {
95
- if (Config.funbox === 'tenKeyMode') {
96
- newlineafter = true;
97
- }
98
- if (Config.funbox === 'arrows') {
99
- if (word.charAt(c) === '↑') {
100
- retval += `<letter><i class="fas fa-arrow-up"></i></letter>`;
101
- }
102
- if (word.charAt(c) === '↓') {
103
- retval += `<letter><i class="fas fa-arrow-down"></i></letter>`;
104
- }
105
- if (word.charAt(c) === '←') {
106
- retval += `<letter><i class="fas fa-arrow-left"></i></letter>`;
107
- }
108
- if (word.charAt(c) === '→') {
109
- retval += `<letter><i class="fas fa-arrow-right"></i></letter>`;
110
- }
111
- }
112
- else if (word.charAt(c) === '\t') {
113
- retval += `<letter class='tabChar'><i class="fas fa-long-arrow-alt-right"></i></letter>`;
114
- }
115
- else if (word.charAt(c) === '\n') {
116
- newlineafter = true;
117
- retval += `<letter class='nlChar'><i class="fas fa-angle-down"></i></letter>`;
118
- }
119
- else {
120
- retval += '<letter>' + word.charAt(c) + '</letter>';
121
- }
122
- }
123
- retval += '</div>';
124
- if (newlineafter)
125
- retval += "<div class='newline'></div>";
126
- return retval;
127
- }
128
- export function showWords() {
129
- if (Config.indicateTypos === 'below') {
130
- words.classList.add('indicateTyposBelow');
131
- wordsWrapper.classList.add('indicateTyposBelow');
132
- }
133
- else {
134
- words.classList.remove('indicateTyposBelow');
135
- wordsWrapper.classList.remove('indicateTyposBelow');
136
- }
137
- let wordsHTML = '';
138
- for (let i = 0; i < TestWords.words.length; i++) {
139
- wordsHTML += getWordHTML(TestWords.words.get(i));
140
- }
141
- words.innerHTML = wordsHTML;
142
- wordsWrapper.classList.remove('hidden');
143
- const currentWord = document.querySelector('.word');
144
- const currentWordStyle = window.getComputedStyle(currentWord);
145
- const wordHeight = parseFloat(currentWordStyle.marginTop) +
146
- parseFloat(currentWordStyle.marginBottom) +
147
- currentWord.getBoundingClientRect().height;
148
- words.style.height = wordHeight * (Config.funbox === 'tenKeyMode' ? 5 : 4) + 'px';
149
- words.style.overflow = 'hidden';
150
- words.style.width = '100%';
151
- words.style.marginLeft = 'unset';
152
- wordsWrapper.style.height = wordHeight * (Config.funbox === 'tenKeyMode' ? 5 : 3) + 'px';
153
- wordsWrapper.style.overflow = 'hidden';
154
- updateActiveElement();
155
- Caret.updatePosition();
156
- }
157
- export function addWord(word) {
158
- words.insertAdjacentHTML('beforeend', getWordHTML(word));
159
- }
160
- export function updateWordElement(showError = !Config.blindMode) {
161
- const input = TestInput.input.current;
162
- const wordAtIndex = document.querySelector('#words .word.active');
163
- const currentWord = TestWords.words.getCurrent();
164
- if (!currentWord && Config.mode !== 'zen')
165
- return;
166
- let ret = '';
167
- let newlineafter = false;
168
- if (Config.mode === 'zen') {
169
- for (let i = 0; i < TestInput.input.current.length; i++) {
170
- if (TestInput.input.current[i] === '\t') {
171
- ret += `<letter class='tabChar correct' style="opacity: 0"><i class="fas fa-long-arrow-alt-right"></i></letter>`;
172
- }
173
- else if (TestInput.input.current[i] === '\n') {
174
- newlineafter = true;
175
- ret += `<letter class='nlChar correct' style="opacity: 0"><i class="fas fa-angle-down"></i></letter>`;
176
- }
177
- else {
178
- ret += `<letter class="correct">${TestInput.input.current[i]}</letter>`;
179
- }
180
- }
181
- }
182
- else {
183
- let correctSoFar = false;
184
- // slice earlier if input has trailing compose characters
185
- const inputWithoutComposeLength = Misc.trailingComposeChars.test(input)
186
- ? input.search(Misc.trailingComposeChars)
187
- : input.length;
188
- if (input.search(Misc.trailingComposeChars) < currentWord.length &&
189
- currentWord.slice(0, inputWithoutComposeLength) === input.slice(0, inputWithoutComposeLength)) {
190
- correctSoFar = true;
191
- }
192
- let wordHighlightClassString = correctSoFar ? 'correct' : 'incorrect';
193
- if (Config.blindMode) {
194
- wordHighlightClassString = 'correct';
195
- }
196
- for (let i = 0; i < input.length; i++) {
197
- const charCorrect = currentWord[i] == input[i];
198
- let correctClass = 'correct';
199
- if (Config.highlightMode == 'off') {
200
- correctClass = '';
201
- }
202
- let currentLetter = currentWord[i];
203
- let tabChar = '';
204
- let nlChar = '';
205
- if (Config.funbox === 'arrows') {
206
- if (currentLetter === '↑') {
207
- currentLetter = `<i class="fas fa-arrow-up"></i>`;
208
- }
209
- if (currentLetter === '↓') {
210
- currentLetter = `<i class="fas fa-arrow-down"></i>`;
211
- }
212
- if (currentLetter === '←') {
213
- currentLetter = `<i class="fas fa-arrow-left"></i>`;
214
- }
215
- if (currentLetter === '→') {
216
- currentLetter = `<i class="fas fa-arrow-right"></i>`;
217
- }
218
- }
219
- else if (currentLetter === '\t') {
220
- tabChar = 'tabChar';
221
- currentLetter = `<i class="fas fa-long-arrow-alt-right"></i>`;
222
- }
223
- else if (currentLetter === '\n') {
224
- nlChar = 'nlChar';
225
- currentLetter = `<i class="fas fa-angle-down"></i>`;
226
- }
227
- if (charCorrect) {
228
- ret += `<letter class="${Config.highlightMode == 'word' ? wordHighlightClassString : correctClass} ${tabChar}${nlChar}">${currentLetter}</letter>`;
229
- }
230
- else if (currentLetter !== undefined &&
231
- CompositionState.getComposing() &&
232
- i >= CompositionState.getStartPos()) {
233
- ret += `<letter class="${Config.highlightMode == 'word' ? wordHighlightClassString : ''} dead">${currentLetter}</letter>`;
234
- }
235
- else if (!showError) {
236
- if (currentLetter !== undefined) {
237
- ret += `<letter class="${Config.highlightMode == 'word' ? wordHighlightClassString : correctClass} ${tabChar}${nlChar}">${currentLetter}</letter>`;
238
- }
239
- }
240
- else if (currentLetter === undefined) {
241
- if (!Config.hideExtraLetters) {
242
- let letter = input[i];
243
- if (letter == ' ' || letter == '\t' || letter == '\n') {
244
- letter = '_';
245
- }
246
- ret += `<letter class="${Config.highlightMode == 'word' ? wordHighlightClassString : 'incorrect'} extra ${tabChar}${nlChar}">${letter}</letter>`;
247
- }
248
- }
249
- else {
250
- ret +=
251
- `<letter class="${Config.highlightMode == 'word' ? wordHighlightClassString : 'incorrect'} ${tabChar}${nlChar}">` +
252
- (Config.indicateTypos === 'replace'
253
- ? input[i] == ' '
254
- ? '_'
255
- : input[i]
256
- : currentLetter) +
257
- (Config.indicateTypos === 'below' ? `<hint>${input[i]}</hint>` : '') +
258
- '</letter>';
259
- }
260
- }
261
- for (let i = input.length; i < currentWord.length; i++) {
262
- if (Config.funbox === 'arrows') {
263
- if (currentWord[i] === '↑') {
264
- ret += `<letter><i class="fas fa-arrow-up"></i></letter>`;
265
- }
266
- if (currentWord[i] === '↓') {
267
- ret += `<letter><i class="fas fa-arrow-down"></i></letter>`;
268
- }
269
- if (currentWord[i] === '←') {
270
- ret += `<letter><i class="fas fa-arrow-left"></i></letter>`;
271
- }
272
- if (currentWord[i] === '→') {
273
- ret += `<letter><i class="fas fa-arrow-right"></i></letter>`;
274
- }
275
- }
276
- else if (currentWord[i] === '\t') {
277
- ret += `<letter class='tabChar'><i class="fas fa-long-arrow-alt-right"></i></letter>`;
278
- }
279
- else if (currentWord[i] === '\n') {
280
- ret += `<letter class='nlChar'><i class="fas fa-angle-down"></i></letter>`;
281
- }
282
- else {
283
- ret +=
284
- `<letter class="${Config.highlightMode == 'word' ? wordHighlightClassString : ''}">` +
285
- currentWord[i] +
286
- '</letter>';
287
- }
288
- }
289
- if (Config.highlightMode === 'letter' && Config.hideExtraLetters) {
290
- if (input.length > currentWord.length && !Config.blindMode) {
291
- wordAtIndex.classList.add('error');
292
- }
293
- else if (input.length == currentWord.length) {
294
- wordAtIndex.classList.remove('error');
295
- }
296
- }
297
- }
298
- wordAtIndex.innerHTML = ret;
299
- if (newlineafter)
300
- words.insertAdjacentHTML('beforeend', "<div class='newline'></div>");
301
- }
302
- export function lineJump(currentTop) {
303
- if ((Config.tapeMode === 'off' && currentTestLine > 0) ||
304
- (Config.tapeMode !== 'off' && currentTestLine >= 0)) {
305
- const hideBound = currentTop;
306
- const toHide = [];
307
- const wordElements = document.querySelectorAll('#words .word');
308
- for (let i = 0; i < currentWordElementIndex; i++) {
309
- if (wordElements[i].classList.contains('hidden'))
310
- continue;
311
- const forWordTop = Math.floor(wordElements[i].offsetTop);
312
- if (forWordTop < (Config.tapeMode === 'off' ? hideBound - 10 : hideBound + 10)) {
313
- toHide.push(document.querySelectorAll('#words .word')[i]);
314
- }
315
- }
316
- toHide.forEach(el => el.remove());
317
- currentWordElementIndex -= toHide.length;
318
- }
319
- currentTestLine++;
320
- }
321
- export function highlightBadWord(index, showError) {
322
- if (!showError)
323
- return;
324
- document.querySelectorAll('#words .word')[index].classList.add('error');
325
- }
326
- export function wordsInputFocusTestUI() {
327
- if (!resultVisible && Config.showOutOfFocusWarning) {
328
- OutOfFocus.hide();
329
- }
330
- Caret.show();
331
- }
332
- export function wordsInputFocusOut() {
333
- if (!resultVisible && Config.showOutOfFocusWarning) {
334
- OutOfFocus.show();
335
- }
336
- Caret.hide();
337
- }
338
- export function wordsWrapperClick() {
339
- focusWords();
340
- }
341
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC11aS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3Rnby10eXBpbmctdGVzdC9zcmMvbGliL2hlbHBlcnMvdGVzdC90ZXN0LXVpLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sTUFBTSxNQUFNLHNCQUFzQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxTQUFTLE1BQU0sY0FBYyxDQUFDO0FBQzFDLE9BQU8sS0FBSyxTQUFTLE1BQU0sY0FBYyxDQUFDO0FBQzFDLE9BQU8sS0FBSyxLQUFLLE1BQU0sU0FBUyxDQUFDO0FBQ2pDLE9BQU8sS0FBSyxVQUFVLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxLQUFLLElBQUksTUFBTSxrQkFBa0IsQ0FBQztBQUN6QyxPQUFPLEtBQUssZ0JBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFFMUQsSUFBSSxZQUF5QixDQUFDO0FBQzlCLElBQUksVUFBNEIsQ0FBQztBQUNqQyxJQUFJLEtBQWtCLENBQUM7QUFFdkIsTUFBTSxDQUFDLElBQUksdUJBQXVCLEdBQUcsQ0FBQyxDQUFDO0FBQ3ZDLE1BQU0sQ0FBQyxJQUFJLGFBQWEsR0FBRyxLQUFLLENBQUM7QUFDakMsTUFBTSxDQUFDLElBQUksYUFBYSxHQUFHLENBQUMsQ0FBQztBQUM3QixNQUFNLENBQUMsSUFBSSxjQUFjLEdBQUcsS0FBSyxDQUFDO0FBQ2xDLE1BQU0sQ0FBQyxJQUFJLHFCQUF1QyxDQUFDO0FBQ25ELE1BQU0sQ0FBQyxNQUFNLGNBQWMsR0FBRyxLQUFLLENBQUM7QUFDcEMsTUFBTSxDQUFDLElBQUksZUFBZSxHQUFHLENBQUMsQ0FBQztBQUMvQixNQUFNLENBQUMsSUFBSSxpQkFBaUIsR0FBRyxLQUFLLENBQUM7QUFFckMsTUFBTSxVQUFVLHNCQUFzQixDQUFDLGdCQUE2QjtJQUNsRSxZQUFZLEdBQUcsZ0JBQWdCLENBQUM7QUFDbEMsQ0FBQztBQUVELE1BQU0sVUFBVSwwQkFBMEIsQ0FBQyxZQUE4QjtJQUN2RSxVQUFVLEdBQUcsWUFBWSxDQUFDO0FBQzVCLENBQUM7QUFFRCxNQUFNLFVBQVUsZUFBZSxDQUFDLFNBQXNCO0lBQ3BELEtBQUssR0FBRyxTQUFTLENBQUM7QUFDcEIsQ0FBQztBQUVELE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxHQUFZO0lBQzNDLGFBQWEsR0FBRyxHQUFHLENBQUM7QUFDdEIsQ0FBQztBQUVELE1BQU0sVUFBVSwwQkFBMEIsQ0FBQyxHQUFXO0lBQ3BELHVCQUF1QixHQUFHLEdBQUcsQ0FBQztBQUNoQyxDQUFDO0FBRUQsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEdBQVc7SUFDMUMsYUFBYSxHQUFHLEdBQUcsQ0FBQztBQUN0QixDQUFDO0FBRUQsSUFBSSxpQkFBcUQsQ0FBQztBQUMxRCxNQUFNLFVBQVUsaUJBQWlCLENBQUMsR0FBWTtJQUM1QyxjQUFjLEdBQUcsR0FBRyxDQUFDO0lBQ3JCLElBQUksR0FBRyxLQUFLLElBQUksRUFBRSxDQUFDO1FBQ2pCLHFCQUFxQixHQUFHLElBQUksT0FBTyxDQUFDLE9BQU8sQ0FBQyxFQUFFO1lBQzVDLGlCQUFpQixHQUFHLE9BQU8sQ0FBQztRQUM5QixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7U0FBTSxDQUFDO1FBQ04sSUFBSSxpQkFBaUI7WUFBRSxpQkFBaUIsRUFBRSxDQUFDO1FBQzNDLGlCQUFpQixHQUFHLElBQUksQ0FBQztJQUMzQixDQUFDO0FBQ0gsQ0FBQztBQUVELE1BQU0sVUFBVSxvQkFBb0IsQ0FBQyxHQUFZO0lBQy9DLGlCQUFpQixHQUFHLEdBQUcsQ0FBQztBQUMxQixDQUFDO0FBRUQsTUFBTSxVQUFVLEtBQUs7SUFDbkIsZUFBZSxHQUFHLENBQUMsQ0FBQztJQUNwQix1QkFBdUIsR0FBRyxDQUFDLENBQUM7QUFDOUIsQ0FBQztBQUVELE1BQU0sVUFBVSxVQUFVO0lBQ3hCLElBQUksQ0FBQyxZQUFZLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDO1FBQy9DLFVBQVUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNyQixDQUFDO0FBQ0gsQ0FBQztBQUVELE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxTQUFtQjtJQUNyRCxNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFDLENBQUM7SUFDeEQsSUFBSSxNQUFNLENBQUMsSUFBSSxJQUFJLEtBQUssSUFBSSxTQUFTLEVBQUUsQ0FBQztRQUN0QyxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUM7SUFDbkIsQ0FBQztTQUFNLElBQUksTUFBTSxLQUFLLElBQUksRUFBRSxDQUFDO1FBQzNCLElBQUksTUFBTSxDQUFDLGFBQWEsSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUNuQyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFO2dCQUM1QyxDQUFDLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUNoQyxDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7UUFDRCxNQUFNLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUNwQyxDQUFDO0lBQ0QsSUFBSSxDQUFDO1FBQ0gsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFDLGdCQUFnQixDQUFDLGNBQWMsQ0FBQyxDQUFDLHVCQUF1QixDQUFDLENBQUM7UUFDdEYsVUFBVSxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDbkMsVUFBVSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUM7UUFDckMsYUFBYSxHQUFpQixRQUFRLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFFLENBQUMsU0FBUyxDQUFDO1FBQ2xGLElBQUksTUFBTSxDQUFDLGFBQWEsSUFBSSxNQUFNLEVBQUUsQ0FBQztZQUNuQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxFQUFFO2dCQUNoRCxDQUFDLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUM3QixDQUFDLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDO0lBQUMsT0FBTyxDQUFDLEVBQUUsQ0FBQztRQUNYLE9BQU8sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDbkIsQ0FBQztBQUNILENBQUM7QUFFRCxTQUFTLFdBQVcsQ0FBQyxJQUFZO0lBQy9CLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQztJQUN6QixJQUFJLE1BQU0sR0FBRyxvQkFBb0IsQ0FBQztJQUNsQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ3JDLElBQUksTUFBTSxDQUFDLE1BQU0sS0FBSyxZQUFZLEVBQUUsQ0FBQztZQUNuQyxZQUFZLEdBQUcsSUFBSSxDQUFDO1FBQ3RCLENBQUM7UUFDRCxJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssUUFBUSxFQUFFLENBQUM7WUFDL0IsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO2dCQUMzQixNQUFNLElBQUksa0RBQWtELENBQUM7WUFDL0QsQ0FBQztZQUNELElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztnQkFDM0IsTUFBTSxJQUFJLG9EQUFvRCxDQUFDO1lBQ2pFLENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7Z0JBQzNCLE1BQU0sSUFBSSxvREFBb0QsQ0FBQztZQUNqRSxDQUFDO1lBQ0QsSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO2dCQUMzQixNQUFNLElBQUkscURBQXFELENBQUM7WUFDbEUsQ0FBQztRQUNILENBQUM7YUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDbkMsTUFBTSxJQUFJLDhFQUE4RSxDQUFDO1FBQzNGLENBQUM7YUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDbkMsWUFBWSxHQUFHLElBQUksQ0FBQztZQUNwQixNQUFNLElBQUksbUVBQW1FLENBQUM7UUFDaEYsQ0FBQzthQUFNLENBQUM7WUFDTixNQUFNLElBQUksVUFBVSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsV0FBVyxDQUFDO1FBQ3RELENBQUM7SUFDSCxDQUFDO0lBQ0QsTUFBTSxJQUFJLFFBQVEsQ0FBQztJQUNuQixJQUFJLFlBQVk7UUFBRSxNQUFNLElBQUksNkJBQTZCLENBQUM7SUFDMUQsT0FBTyxNQUFNLENBQUM7QUFDaEIsQ0FBQztBQUVELE1BQU0sVUFBVSxTQUFTO0lBQ3ZCLElBQUksTUFBTSxDQUFDLGFBQWEsS0FBSyxPQUFPLEVBQUUsQ0FBQztRQUNyQyxLQUFLLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQzFDLFlBQVksQ0FBQyxTQUFTLENBQUMsR0FBRyxDQUFDLG9CQUFvQixDQUFDLENBQUM7SUFDbkQsQ0FBQztTQUFNLENBQUM7UUFDTixLQUFLLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDO1FBQzdDLFlBQVksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLG9CQUFvQixDQUFDLENBQUM7SUFDdEQsQ0FBQztJQUVELElBQUksU0FBUyxHQUFHLEVBQUUsQ0FBQztJQUNuQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNoRCxTQUFTLElBQUksV0FBVyxDQUFTLFNBQVMsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDM0QsQ0FBQztJQUVELEtBQUssQ0FBQyxTQUFTLEdBQUcsU0FBUyxDQUFDO0lBRTVCLFlBQVksQ0FBQyxTQUFTLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3hDLE1BQU0sV0FBVyxHQUFZLFFBQVEsQ0FBQyxhQUFhLENBQUMsT0FBTyxDQUFDLENBQUM7SUFDN0QsTUFBTSxnQkFBZ0IsR0FBRyxNQUFNLENBQUMsZ0JBQWdCLENBQUMsV0FBVyxDQUFDLENBQUM7SUFDOUQsTUFBTSxVQUFVLEdBQ2QsVUFBVSxDQUFDLGdCQUFnQixDQUFDLFNBQVMsQ0FBQztRQUN0QyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsWUFBWSxDQUFDO1FBQ3pDLFdBQVcsQ0FBQyxxQkFBcUIsRUFBRSxDQUFDLE1BQU0sQ0FBQztJQUU3QyxLQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxVQUFVLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxLQUFLLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUM7SUFDbEYsS0FBSyxDQUFDLEtBQUssQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO0lBQ2hDLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBSyxHQUFHLE1BQU0sQ0FBQztJQUMzQixLQUFLLENBQUMsS0FBSyxDQUFDLFVBQVUsR0FBRyxPQUFPLENBQUM7SUFDakMsWUFBWSxDQUFDLEtBQUssQ0FBQyxNQUFNLEdBQUcsVUFBVSxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sS0FBSyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDO0lBQ3pGLFlBQVksQ0FBQyxLQUFLLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQztJQUV2QyxtQkFBbUIsRUFBRSxDQUFDO0lBQ3RCLEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztBQUN6QixDQUFDO0FBRUQsTUFBTSxVQUFVLE9BQU8sQ0FBQyxJQUFZO0lBQ2xDLEtBQUssQ0FBQyxrQkFBa0IsQ0FBQyxXQUFXLEVBQUUsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDM0QsQ0FBQztBQUVELE1BQU0sVUFBVSxpQkFBaUIsQ0FBQyxTQUFTLEdBQUcsQ0FBQyxNQUFNLENBQUMsU0FBUztJQUM3RCxNQUFNLEtBQUssR0FBRyxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQztJQUN0QyxNQUFNLFdBQVcsR0FBWSxRQUFRLENBQUMsYUFBYSxDQUFDLHFCQUFxQixDQUFDLENBQUM7SUFDM0UsTUFBTSxXQUFXLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxVQUFVLEVBQUUsQ0FBQztJQUNqRCxJQUFJLENBQUMsV0FBVyxJQUFJLE1BQU0sQ0FBQyxJQUFJLEtBQUssS0FBSztRQUFFLE9BQU87SUFFbEQsSUFBSSxHQUFHLEdBQUcsRUFBRSxDQUFDO0lBRWIsSUFBSSxZQUFZLEdBQUcsS0FBSyxDQUFDO0lBRXpCLElBQUksTUFBTSxDQUFDLElBQUksS0FBSyxLQUFLLEVBQUUsQ0FBQztRQUMxQixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDeEQsSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDeEMsR0FBRyxJQUFJLHlHQUF5RyxDQUFDO1lBQ25ILENBQUM7aUJBQU0sSUFBSSxTQUFTLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDL0MsWUFBWSxHQUFHLElBQUksQ0FBQztnQkFDcEIsR0FBRyxJQUFJLDhGQUE4RixDQUFDO1lBQ3hHLENBQUM7aUJBQU0sQ0FBQztnQkFDTixHQUFHLElBQUksMkJBQTJCLFNBQVMsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUM7WUFDMUUsQ0FBQztRQUNILENBQUM7SUFDSCxDQUFDO1NBQU0sQ0FBQztRQUNOLElBQUksWUFBWSxHQUFHLEtBQUssQ0FBQztRQUV6Qix5REFBeUQ7UUFDekQsTUFBTSx5QkFBeUIsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQztZQUNyRSxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsb0JBQW9CLENBQUM7WUFDekMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUM7UUFDakIsSUFDRSxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxNQUFNO1lBQzVELFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxFQUFFLHlCQUF5QixDQUFDLEtBQUssS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUseUJBQXlCLENBQUMsRUFDN0YsQ0FBQztZQUNELFlBQVksR0FBRyxJQUFJLENBQUM7UUFDdEIsQ0FBQztRQUVELElBQUksd0JBQXdCLEdBQUcsWUFBWSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQztRQUN0RSxJQUFJLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztZQUNyQix3QkFBd0IsR0FBRyxTQUFTLENBQUM7UUFDdkMsQ0FBQztRQUVELEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDdEMsTUFBTSxXQUFXLEdBQUcsV0FBVyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUUvQyxJQUFJLFlBQVksR0FBRyxTQUFTLENBQUM7WUFDN0IsSUFBSSxNQUFNLENBQUMsYUFBYSxJQUFJLEtBQUssRUFBRSxDQUFDO2dCQUNsQyxZQUFZLEdBQUcsRUFBRSxDQUFDO1lBQ3BCLENBQUM7WUFFRCxJQUFJLGFBQWEsR0FBRyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDbkMsSUFBSSxPQUFPLEdBQUcsRUFBRSxDQUFDO1lBQ2pCLElBQUksTUFBTSxHQUFHLEVBQUUsQ0FBQztZQUNoQixJQUFJLE1BQU0sQ0FBQyxNQUFNLEtBQUssUUFBUSxFQUFFLENBQUM7Z0JBQy9CLElBQUksYUFBYSxLQUFLLEdBQUcsRUFBRSxDQUFDO29CQUMxQixhQUFhLEdBQUcsaUNBQWlDLENBQUM7Z0JBQ3BELENBQUM7Z0JBQ0QsSUFBSSxhQUFhLEtBQUssR0FBRyxFQUFFLENBQUM7b0JBQzFCLGFBQWEsR0FBRyxtQ0FBbUMsQ0FBQztnQkFDdEQsQ0FBQztnQkFDRCxJQUFJLGFBQWEsS0FBSyxHQUFHLEVBQUUsQ0FBQztvQkFDMUIsYUFBYSxHQUFHLG1DQUFtQyxDQUFDO2dCQUN0RCxDQUFDO2dCQUNELElBQUksYUFBYSxLQUFLLEdBQUcsRUFBRSxDQUFDO29CQUMxQixhQUFhLEdBQUcsb0NBQW9DLENBQUM7Z0JBQ3ZELENBQUM7WUFDSCxDQUFDO2lCQUFNLElBQUksYUFBYSxLQUFLLElBQUksRUFBRSxDQUFDO2dCQUNsQyxPQUFPLEdBQUcsU0FBUyxDQUFDO2dCQUNwQixhQUFhLEdBQUcsNkNBQTZDLENBQUM7WUFDaEUsQ0FBQztpQkFBTSxJQUFJLGFBQWEsS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDbEMsTUFBTSxHQUFHLFFBQVEsQ0FBQztnQkFDbEIsYUFBYSxHQUFHLG1DQUFtQyxDQUFDO1lBQ3RELENBQUM7WUFFRCxJQUFJLFdBQVcsRUFBRSxDQUFDO2dCQUNoQixHQUFHLElBQUksa0JBQ0wsTUFBTSxDQUFDLGFBQWEsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLHdCQUF3QixDQUFDLENBQUMsQ0FBQyxZQUM5RCxJQUFJLE9BQU8sR0FBRyxNQUFNLEtBQUssYUFBYSxXQUFXLENBQUM7WUFDcEQsQ0FBQztpQkFBTSxJQUNMLGFBQWEsS0FBSyxTQUFTO2dCQUMzQixnQkFBZ0IsQ0FBQyxZQUFZLEVBQUU7Z0JBQy9CLENBQUMsSUFBSSxnQkFBZ0IsQ0FBQyxXQUFXLEVBQUUsRUFDbkMsQ0FBQztnQkFDRCxHQUFHLElBQUksa0JBQ0wsTUFBTSxDQUFDLGFBQWEsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLHdCQUF3QixDQUFDLENBQUMsQ0FBQyxFQUM5RCxVQUFVLGFBQWEsV0FBVyxDQUFDO1lBQ3JDLENBQUM7aUJBQU0sSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO2dCQUN0QixJQUFJLGFBQWEsS0FBSyxTQUFTLEVBQUUsQ0FBQztvQkFDaEMsR0FBRyxJQUFJLGtCQUNMLE1BQU0sQ0FBQyxhQUFhLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDLENBQUMsWUFDOUQsSUFBSSxPQUFPLEdBQUcsTUFBTSxLQUFLLGFBQWEsV0FBVyxDQUFDO2dCQUNwRCxDQUFDO1lBQ0gsQ0FBQztpQkFBTSxJQUFJLGFBQWEsS0FBSyxTQUFTLEVBQUUsQ0FBQztnQkFDdkMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxnQkFBZ0IsRUFBRSxDQUFDO29CQUM3QixJQUFJLE1BQU0sR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7b0JBQ3RCLElBQUksTUFBTSxJQUFJLEdBQUcsSUFBSSxNQUFNLElBQUksSUFBSSxJQUFJLE1BQU0sSUFBSSxJQUFJLEVBQUUsQ0FBQzt3QkFDdEQsTUFBTSxHQUFHLEdBQUcsQ0FBQztvQkFDZixDQUFDO29CQUNELEdBQUcsSUFBSSxrQkFDTCxNQUFNLENBQUMsYUFBYSxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsd0JBQXdCLENBQUMsQ0FBQyxDQUFDLFdBQzlELFVBQVUsT0FBTyxHQUFHLE1BQU0sS0FBSyxNQUFNLFdBQVcsQ0FBQztnQkFDbkQsQ0FBQztZQUNILENBQUM7aUJBQU0sQ0FBQztnQkFDTixHQUFHO29CQUNELGtCQUNFLE1BQU0sQ0FBQyxhQUFhLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQyx3QkFBd0IsQ0FBQyxDQUFDLENBQUMsV0FDOUQsSUFBSSxPQUFPLEdBQUcsTUFBTSxJQUFJO3dCQUN4QixDQUFDLE1BQU0sQ0FBQyxhQUFhLEtBQUssU0FBUzs0QkFDakMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUFHO2dDQUNmLENBQUMsQ0FBQyxHQUFHO2dDQUNMLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDOzRCQUNaLENBQUMsQ0FBQyxhQUFhLENBQUM7d0JBQ2xCLENBQUMsTUFBTSxDQUFDLGFBQWEsS0FBSyxPQUFPLENBQUMsQ0FBQyxDQUFDLFNBQVMsS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQzt3QkFDcEUsV0FBVyxDQUFDO1lBQ2hCLENBQUM7UUFDSCxDQUFDO1FBRUQsS0FBSyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsR0FBRyxXQUFXLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDdkQsSUFBSSxNQUFNLENBQUMsTUFBTSxLQUFLLFFBQVEsRUFBRSxDQUFDO2dCQUMvQixJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztvQkFDM0IsR0FBRyxJQUFJLGtEQUFrRCxDQUFDO2dCQUM1RCxDQUFDO2dCQUNELElBQUksV0FBVyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsRUFBRSxDQUFDO29CQUMzQixHQUFHLElBQUksb0RBQW9ELENBQUM7Z0JBQzlELENBQUM7Z0JBQ0QsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLEtBQUssR0FBRyxFQUFFLENBQUM7b0JBQzNCLEdBQUcsSUFBSSxvREFBb0QsQ0FBQztnQkFDOUQsQ0FBQztnQkFDRCxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLEVBQUUsQ0FBQztvQkFDM0IsR0FBRyxJQUFJLHFEQUFxRCxDQUFDO2dCQUMvRCxDQUFDO1lBQ0gsQ0FBQztpQkFBTSxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsS0FBSyxJQUFJLEVBQUUsQ0FBQztnQkFDbkMsR0FBRyxJQUFJLDhFQUE4RSxDQUFDO1lBQ3hGLENBQUM7aUJBQU0sSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7Z0JBQ25DLEdBQUcsSUFBSSxtRUFBbUUsQ0FBQztZQUM3RSxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sR0FBRztvQkFDRCxrQkFBa0IsTUFBTSxDQUFDLGFBQWEsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLHdCQUF3QixDQUFDLENBQUMsQ0FBQyxFQUFFLElBQUk7d0JBQ3BGLFdBQVcsQ0FBQyxDQUFDLENBQUM7d0JBQ2QsV0FBVyxDQUFDO1lBQ2hCLENBQUM7UUFDSCxDQUFDO1FBRUQsSUFBSSxNQUFNLENBQUMsYUFBYSxLQUFLLFFBQVEsSUFBSSxNQUFNLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztZQUNqRSxJQUFJLEtBQUssQ0FBQyxNQUFNLEdBQUcsV0FBVyxDQUFDLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUUsQ0FBQztnQkFDM0QsV0FBVyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7WUFDckMsQ0FBQztpQkFBTSxJQUFJLEtBQUssQ0FBQyxNQUFNLElBQUksV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDO2dCQUM5QyxXQUFXLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUN4QyxDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFDRCxXQUFXLENBQUMsU0FBUyxHQUFHLEdBQUcsQ0FBQztJQUM1QixJQUFJLFlBQVk7UUFBRSxLQUFLLENBQUMsa0JBQWtCLENBQUMsV0FBVyxFQUFFLDZCQUE2QixDQUFDLENBQUM7QUFDekYsQ0FBQztBQUVELE1BQU0sVUFBVSxRQUFRLENBQUMsVUFBa0I7SUFDekMsSUFDRSxDQUFDLE1BQU0sQ0FBQyxRQUFRLEtBQUssS0FBSyxJQUFJLGVBQWUsR0FBRyxDQUFDLENBQUM7UUFDbEQsQ0FBQyxNQUFNLENBQUMsUUFBUSxLQUFLLEtBQUssSUFBSSxlQUFlLElBQUksQ0FBQyxDQUFDLEVBQ25ELENBQUM7UUFDRCxNQUFNLFNBQVMsR0FBRyxVQUFVLENBQUM7UUFFN0IsTUFBTSxNQUFNLEdBQVUsRUFBRSxDQUFDO1FBQ3pCLE1BQU0sWUFBWSxHQUFHLFFBQVEsQ0FBQyxnQkFBZ0IsQ0FBQyxjQUFjLENBQTRCLENBQUM7UUFDMUYsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLHVCQUF1QixFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDakQsSUFBSSxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUM7Z0JBQUUsU0FBUztZQUMzRCxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQztZQUN6RCxJQUFJLFVBQVUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxRQUFRLEtBQUssS0FBSyxDQUFDLENBQUMsQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTLEdBQUcsRUFBRSxDQUFDLEVBQUUsQ0FBQztnQkFDL0UsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsZ0JBQWdCLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUM1RCxDQUFDO1FBQ0gsQ0FBQztRQUNELE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQztRQUNsQyx1QkFBdUIsSUFBSSxNQUFNLENBQUMsTUFBTSxDQUFDO0lBQzNDLENBQUM7SUFDRCxlQUFlLEVBQUUsQ0FBQztBQUNwQixDQUFDO0FBRUQsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEtBQWEsRUFBRSxTQUFrQjtJQUNoRSxJQUFJLENBQUMsU0FBUztRQUFFLE9BQU87SUFDdkIsUUFBUSxDQUFDLGdCQUFnQixDQUFDLGNBQWMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLFNBQVMsQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUM7QUFDMUUsQ0FBQztBQUVELE1BQU0sVUFBVSxxQkFBcUI7SUFDbkMsSUFBSSxDQUFDLGFBQWEsSUFBSSxNQUFNLENBQUMscUJBQXFCLEVBQUUsQ0FBQztRQUNuRCxVQUFVLENBQUMsSUFBSSxFQUFFLENBQUM7SUFDcEIsQ0FBQztJQUNELEtBQUssQ0FBQyxJQUFJLEVBQUUsQ0FBQztBQUNmLENBQUM7QUFFRCxNQUFNLFVBQVUsa0JBQWtCO0lBQ2hDLElBQUksQ0FBQyxhQUFhLElBQUksTUFBTSxDQUFDLHFCQUFxQixFQUFFLENBQUM7UUFDbkQsVUFBVSxDQUFDLElBQUksRUFBRSxDQUFDO0lBQ3BCLENBQUM7SUFDRCxLQUFLLENBQUMsSUFBSSxFQUFFLENBQUM7QUFDZixDQUFDO0FBRUQsTUFBTSxVQUFVLGlCQUFpQjtJQUMvQixVQUFVLEVBQUUsQ0FBQztBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgQ29uZmlnIGZyb20gJy4uLy4uL2hlbHBlcnMvY29uZmlnJztcbmltcG9ydCAqIGFzIFRlc3RXb3JkcyBmcm9tICcuL3Rlc3Qtd29yZHMnO1xuaW1wb3J0ICogYXMgVGVzdElucHV0IGZyb20gJy4vdGVzdC1pbnB1dCc7XG5pbXBvcnQgKiBhcyBDYXJldCBmcm9tICcuL2NhcmV0JztcbmltcG9ydCAqIGFzIE91dE9mRm9jdXMgZnJvbSAnLi9vdXQtb2YtZm9jdXMnO1xuaW1wb3J0ICogYXMgTWlzYyBmcm9tICcuLi8uLi91dGlscy9taXNjJztcbmltcG9ydCAqIGFzIENvbXBvc2l0aW9uU3RhdGUgZnJvbSAnLi4vc3RhdGVzL2NvbXBvc2l0aW9uJztcblxubGV0IHdvcmRzV3JhcHBlcjogSFRNTEVsZW1lbnQ7XG5sZXQgd29yZHNJbnB1dDogSFRNTElucHV0RWxlbWVudDtcbmxldCB3b3JkczogSFRNTEVsZW1lbnQ7XG5cbmV4cG9ydCBsZXQgY3VycmVudFdvcmRFbGVtZW50SW5kZXggPSAwO1xuZXhwb3J0IGxldCByZXN1bHRWaXNpYmxlID0gZmFsc2U7XG5leHBvcnQgbGV0IGFjdGl2ZVdvcmRUb3AgPSAwO1xuZXhwb3J0IGxldCB0ZXN0UmVzdGFydGluZyA9IGZhbHNlO1xuZXhwb3J0IGxldCB0ZXN0UmVzdGFydGluZ1Byb21pc2U6IFByb21pc2U8dW5rbm93bj47XG5leHBvcnQgY29uc3QgbGluZVRyYW5zaXRpb24gPSBmYWxzZTtcbmV4cG9ydCBsZXQgY3VycmVudFRlc3RMaW5lID0gMDtcbmV4cG9ydCBsZXQgcmVzdWx0Q2FsY3VsYXRpbmcgPSBmYWxzZTtcblxuZXhwb3J0IGZ1bmN0aW9uIHNldFdvcmRzV3JhcHBlckVsZW1lbnQod29yZHNXcmFwcGVyRWxlbTogSFRNTEVsZW1lbnQpIHtcbiAgd29yZHNXcmFwcGVyID0gd29yZHNXcmFwcGVyRWxlbTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldFdvcmRzSW5wdXRFbGVtZW50VGVzdFVJKHdvcmRzRWxlbWVudDogSFRNTElucHV0RWxlbWVudCkge1xuICB3b3Jkc0lucHV0ID0gd29yZHNFbGVtZW50O1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0V29yZHNFbGVtZW50KHdvcmRzRWxlbTogSFRNTEVsZW1lbnQpIHtcbiAgd29yZHMgPSB3b3Jkc0VsZW07XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRSZXN1bHRWaXNpYmxlKHZhbDogYm9vbGVhbik6IHZvaWQge1xuICByZXN1bHRWaXNpYmxlID0gdmFsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2V0Q3VycmVudFdvcmRFbGVtZW50SW5kZXgodmFsOiBudW1iZXIpOiB2b2lkIHtcbiAgY3VycmVudFdvcmRFbGVtZW50SW5kZXggPSB2YWw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRBY3RpdmVXb3JkVG9wKHZhbDogbnVtYmVyKTogdm9pZCB7XG4gIGFjdGl2ZVdvcmRUb3AgPSB2YWw7XG59XG5cbmxldCByZXN0YXJ0aW5nUmVzb2x2ZTogbnVsbCB8ICgodmFsdWU/OiB1bmtub3duKSA9PiB2b2lkKTtcbmV4cG9ydCBmdW5jdGlvbiBzZXRUZXN0UmVzdGFydGluZyh2YWw6IGJvb2xlYW4pOiB2b2lkIHtcbiAgdGVzdFJlc3RhcnRpbmcgPSB2YWw7XG4gIGlmICh2YWwgPT09IHRydWUpIHtcbiAgICB0ZXN0UmVzdGFydGluZ1Byb21pc2UgPSBuZXcgUHJvbWlzZShyZXNvbHZlID0+IHtcbiAgICAgIHJlc3RhcnRpbmdSZXNvbHZlID0gcmVzb2x2ZTtcbiAgICB9KTtcbiAgfSBlbHNlIHtcbiAgICBpZiAocmVzdGFydGluZ1Jlc29sdmUpIHJlc3RhcnRpbmdSZXNvbHZlKCk7XG4gICAgcmVzdGFydGluZ1Jlc29sdmUgPSBudWxsO1xuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRSZXN1bHRDYWxjdWxhdGluZyh2YWw6IGJvb2xlYW4pOiB2b2lkIHtcbiAgcmVzdWx0Q2FsY3VsYXRpbmcgPSB2YWw7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZXNldCgpOiB2b2lkIHtcbiAgY3VycmVudFRlc3RMaW5lID0gMDtcbiAgY3VycmVudFdvcmRFbGVtZW50SW5kZXggPSAwO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gZm9jdXNXb3JkcygpOiB2b2lkIHtcbiAgaWYgKCF3b3Jkc1dyYXBwZXIuY2xhc3NMaXN0LmNvbnRhaW5zKCdoaWRkZW4nKSkge1xuICAgIHdvcmRzSW5wdXQuZm9jdXMoKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlQWN0aXZlRWxlbWVudChiYWNrc3BhY2U/OiBib29sZWFuKTogdm9pZCB7XG4gIGNvbnN0IGFjdGl2ZSA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyN3b3JkcyAuYWN0aXZlJyk7XG4gIGlmIChDb25maWcubW9kZSA9PSAnemVuJyAmJiBiYWNrc3BhY2UpIHtcbiAgICBhY3RpdmU/LnJlbW92ZSgpO1xuICB9IGVsc2UgaWYgKGFjdGl2ZSAhPT0gbnVsbCkge1xuICAgIGlmIChDb25maWcuaGlnaGxpZ2h0TW9kZSA9PSAnd29yZCcpIHtcbiAgICAgIGFjdGl2ZS5xdWVyeVNlbGVjdG9yQWxsKCdsZXR0ZXInKS5mb3JFYWNoKGUgPT4ge1xuICAgICAgICBlLmNsYXNzTGlzdC5yZW1vdmUoJ2NvcnJlY3QnKTtcbiAgICAgIH0pO1xuICAgIH1cbiAgICBhY3RpdmUuY2xhc3NMaXN0LnJlbW92ZSgnYWN0aXZlJyk7XG4gIH1cbiAgdHJ5IHtcbiAgICBjb25zdCBhY3RpdmVXb3JkID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnI3dvcmRzIC53b3JkJylbY3VycmVudFdvcmRFbGVtZW50SW5kZXhdO1xuICAgIGFjdGl2ZVdvcmQuY2xhc3NMaXN0LmFkZCgnYWN0aXZlJyk7XG4gICAgYWN0aXZlV29yZC5jbGFzc0xpc3QucmVtb3ZlKCdlcnJvcicpO1xuICAgIGFjdGl2ZVdvcmRUb3AgPSAoPEhUTUxFbGVtZW50PmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyN3b3JkcyAuYWN0aXZlJykpLm9mZnNldFRvcDtcbiAgICBpZiAoQ29uZmlnLmhpZ2hsaWdodE1vZGUgPT0gJ3dvcmQnKSB7XG4gICAgICBhY3RpdmVXb3JkLnF1ZXJ5U2VsZWN0b3JBbGwoJ2xldHRlcicpLmZvckVhY2goZSA9PiB7XG4gICAgICAgIGUuY2xhc3NMaXN0LmFkZCgnY29ycmVjdCcpO1xuICAgICAgfSk7XG4gICAgfVxuICB9IGNhdGNoIChlKSB7XG4gICAgY29uc29sZS5lcnJvcihlKTtcbiAgfVxufVxuXG5mdW5jdGlvbiBnZXRXb3JkSFRNTCh3b3JkOiBzdHJpbmcpOiBzdHJpbmcge1xuICBsZXQgbmV3bGluZWFmdGVyID0gZmFsc2U7XG4gIGxldCByZXR2YWwgPSBgPGRpdiBjbGFzcz0nd29yZCc+YDtcbiAgZm9yIChsZXQgYyA9IDA7IGMgPCB3b3JkLmxlbmd0aDsgYysrKSB7XG4gICAgaWYgKENvbmZpZy5mdW5ib3ggPT09ICd0ZW5LZXlNb2RlJykge1xuICAgICAgbmV3bGluZWFmdGVyID0gdHJ1ZTtcbiAgICB9XG4gICAgaWYgKENvbmZpZy5mdW5ib3ggPT09ICdhcnJvd3MnKSB7XG4gICAgICBpZiAod29yZC5jaGFyQXQoYykgPT09ICfihpEnKSB7XG4gICAgICAgIHJldHZhbCArPSBgPGxldHRlcj48aSBjbGFzcz1cImZhcyBmYS1hcnJvdy11cFwiPjwvaT48L2xldHRlcj5gO1xuICAgICAgfVxuICAgICAgaWYgKHdvcmQuY2hhckF0KGMpID09PSAn4oaTJykge1xuICAgICAgICByZXR2YWwgKz0gYDxsZXR0ZXI+PGkgY2xhc3M9XCJmYXMgZmEtYXJyb3ctZG93blwiPjwvaT48L2xldHRlcj5gO1xuICAgICAgfVxuICAgICAgaWYgKHdvcmQuY2hhckF0KGMpID09PSAn4oaQJykge1xuICAgICAgICByZXR2YWwgKz0gYDxsZXR0ZXI+PGkgY2xhc3M9XCJmYXMgZmEtYXJyb3ctbGVmdFwiPjwvaT48L2xldHRlcj5gO1xuICAgICAgfVxuICAgICAgaWYgKHdvcmQuY2hhckF0KGMpID09PSAn4oaSJykge1xuICAgICAgICByZXR2YWwgKz0gYDxsZXR0ZXI+PGkgY2xhc3M9XCJmYXMgZmEtYXJyb3ctcmlnaHRcIj48L2k+PC9sZXR0ZXI+YDtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHdvcmQuY2hhckF0KGMpID09PSAnXFx0Jykge1xuICAgICAgcmV0dmFsICs9IGA8bGV0dGVyIGNsYXNzPSd0YWJDaGFyJz48aSBjbGFzcz1cImZhcyBmYS1sb25nLWFycm93LWFsdC1yaWdodFwiPjwvaT48L2xldHRlcj5gO1xuICAgIH0gZWxzZSBpZiAod29yZC5jaGFyQXQoYykgPT09ICdcXG4nKSB7XG4gICAgICBuZXdsaW5lYWZ0ZXIgPSB0cnVlO1xuICAgICAgcmV0dmFsICs9IGA8bGV0dGVyIGNsYXNzPSdubENoYXInPjxpIGNsYXNzPVwiZmFzIGZhLWFuZ2xlLWRvd25cIj48L2k+PC9sZXR0ZXI+YDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dmFsICs9ICc8bGV0dGVyPicgKyB3b3JkLmNoYXJBdChjKSArICc8L2xldHRlcj4nO1xuICAgIH1cbiAgfVxuICByZXR2YWwgKz0gJzwvZGl2Pic7XG4gIGlmIChuZXdsaW5lYWZ0ZXIpIHJldHZhbCArPSBcIjxkaXYgY2xhc3M9J25ld2xpbmUnPjwvZGl2PlwiO1xuICByZXR1cm4gcmV0dmFsO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gc2hvd1dvcmRzKCk6IHZvaWQge1xuICBpZiAoQ29uZmlnLmluZGljYXRlVHlwb3MgPT09ICdiZWxvdycpIHtcbiAgICB3b3Jkcy5jbGFzc0xpc3QuYWRkKCdpbmRpY2F0ZVR5cG9zQmVsb3cnKTtcbiAgICB3b3Jkc1dyYXBwZXIuY2xhc3NMaXN0LmFkZCgnaW5kaWNhdGVUeXBvc0JlbG93Jyk7XG4gIH0gZWxzZSB7XG4gICAgd29yZHMuY2xhc3NMaXN0LnJlbW92ZSgnaW5kaWNhdGVUeXBvc0JlbG93Jyk7XG4gICAgd29yZHNXcmFwcGVyLmNsYXNzTGlzdC5yZW1vdmUoJ2luZGljYXRlVHlwb3NCZWxvdycpO1xuICB9XG5cbiAgbGV0IHdvcmRzSFRNTCA9ICcnO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IFRlc3RXb3Jkcy53b3Jkcy5sZW5ndGg7IGkrKykge1xuICAgIHdvcmRzSFRNTCArPSBnZXRXb3JkSFRNTCg8c3RyaW5nPlRlc3RXb3Jkcy53b3Jkcy5nZXQoaSkpO1xuICB9XG5cbiAgd29yZHMuaW5uZXJIVE1MID0gd29yZHNIVE1MO1xuXG4gIHdvcmRzV3JhcHBlci5jbGFzc0xpc3QucmVtb3ZlKCdoaWRkZW4nKTtcbiAgY29uc3QgY3VycmVudFdvcmQgPSA8RWxlbWVudD5kb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcud29yZCcpO1xuICBjb25zdCBjdXJyZW50V29yZFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoY3VycmVudFdvcmQpO1xuICBjb25zdCB3b3JkSGVpZ2h0ID1cbiAgICBwYXJzZUZsb2F0KGN1cnJlbnRXb3JkU3R5bGUubWFyZ2luVG9wKSArXG4gICAgcGFyc2VGbG9hdChjdXJyZW50V29yZFN0eWxlLm1hcmdpbkJvdHRvbSkgK1xuICAgIGN1cnJlbnRXb3JkLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodDtcblxuICB3b3Jkcy5zdHlsZS5oZWlnaHQgPSB3b3JkSGVpZ2h0ICogKENvbmZpZy5mdW5ib3ggPT09ICd0ZW5LZXlNb2RlJyA/IDUgOiA0KSArICdweCc7XG4gIHdvcmRzLnN0eWxlLm92ZXJmbG93ID0gJ2hpZGRlbic7XG4gIHdvcmRzLnN0eWxlLndpZHRoID0gJzEwMCUnO1xuICB3b3Jkcy5zdHlsZS5tYXJnaW5MZWZ0ID0gJ3Vuc2V0JztcbiAgd29yZHNXcmFwcGVyLnN0eWxlLmhlaWdodCA9IHdvcmRIZWlnaHQgKiAoQ29uZmlnLmZ1bmJveCA9PT0gJ3RlbktleU1vZGUnID8gNSA6IDMpICsgJ3B4JztcbiAgd29yZHNXcmFwcGVyLnN0eWxlLm92ZXJmbG93ID0gJ2hpZGRlbic7XG5cbiAgdXBkYXRlQWN0aXZlRWxlbWVudCgpO1xuICBDYXJldC51cGRhdGVQb3NpdGlvbigpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gYWRkV29yZCh3b3JkOiBzdHJpbmcpOiB2b2lkIHtcbiAgd29yZHMuaW5zZXJ0QWRqYWNlbnRIVE1MKCdiZWZvcmVlbmQnLCBnZXRXb3JkSFRNTCh3b3JkKSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB1cGRhdGVXb3JkRWxlbWVudChzaG93RXJyb3IgPSAhQ29uZmlnLmJsaW5kTW9kZSk6IHZvaWQge1xuICBjb25zdCBpbnB1dCA9IFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50O1xuICBjb25zdCB3b3JkQXRJbmRleCA9IDxFbGVtZW50PmRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJyN3b3JkcyAud29yZC5hY3RpdmUnKTtcbiAgY29uc3QgY3VycmVudFdvcmQgPSBUZXN0V29yZHMud29yZHMuZ2V0Q3VycmVudCgpO1xuICBpZiAoIWN1cnJlbnRXb3JkICYmIENvbmZpZy5tb2RlICE9PSAnemVuJykgcmV0dXJuO1xuXG4gIGxldCByZXQgPSAnJztcblxuICBsZXQgbmV3bGluZWFmdGVyID0gZmFsc2U7XG5cbiAgaWYgKENvbmZpZy5tb2RlID09PSAnemVuJykge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgVGVzdElucHV0LmlucHV0LmN1cnJlbnQubGVuZ3RoOyBpKyspIHtcbiAgICAgIGlmIChUZXN0SW5wdXQuaW5wdXQuY3VycmVudFtpXSA9PT0gJ1xcdCcpIHtcbiAgICAgICAgcmV0ICs9IGA8bGV0dGVyIGNsYXNzPSd0YWJDaGFyIGNvcnJlY3QnIHN0eWxlPVwib3BhY2l0eTogMFwiPjxpIGNsYXNzPVwiZmFzIGZhLWxvbmctYXJyb3ctYWx0LXJpZ2h0XCI+PC9pPjwvbGV0dGVyPmA7XG4gICAgICB9IGVsc2UgaWYgKFRlc3RJbnB1dC5pbnB1dC5jdXJyZW50W2ldID09PSAnXFxuJykge1xuICAgICAgICBuZXdsaW5lYWZ0ZXIgPSB0cnVlO1xuICAgICAgICByZXQgKz0gYDxsZXR0ZXIgY2xhc3M9J25sQ2hhciBjb3JyZWN0JyBzdHlsZT1cIm9wYWNpdHk6IDBcIj48aSBjbGFzcz1cImZhcyBmYS1hbmdsZS1kb3duXCI+PC9pPjwvbGV0dGVyPmA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXQgKz0gYDxsZXR0ZXIgY2xhc3M9XCJjb3JyZWN0XCI+JHtUZXN0SW5wdXQuaW5wdXQuY3VycmVudFtpXX08L2xldHRlcj5gO1xuICAgICAgfVxuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBsZXQgY29ycmVjdFNvRmFyID0gZmFsc2U7XG5cbiAgICAvLyBzbGljZSBlYXJsaWVyIGlmIGlucHV0IGhhcyB0cmFpbGluZyBjb21wb3NlIGNoYXJhY3RlcnNcbiAgICBjb25zdCBpbnB1dFdpdGhvdXRDb21wb3NlTGVuZ3RoID0gTWlzYy50cmFpbGluZ0NvbXBvc2VDaGFycy50ZXN0KGlucHV0KVxuICAgICAgPyBpbnB1dC5zZWFyY2goTWlzYy50cmFpbGluZ0NvbXBvc2VDaGFycylcbiAgICAgIDogaW5wdXQubGVuZ3RoO1xuICAgIGlmIChcbiAgICAgIGlucHV0LnNlYXJjaChNaXNjLnRyYWlsaW5nQ29tcG9zZUNoYXJzKSA8IGN1cnJlbnRXb3JkLmxlbmd0aCAmJlxuICAgICAgY3VycmVudFdvcmQuc2xpY2UoMCwgaW5wdXRXaXRob3V0Q29tcG9zZUxlbmd0aCkgPT09IGlucHV0LnNsaWNlKDAsIGlucHV0V2l0aG91dENvbXBvc2VMZW5ndGgpXG4gICAgKSB7XG4gICAgICBjb3JyZWN0U29GYXIgPSB0cnVlO1xuICAgIH1cblxuICAgIGxldCB3b3JkSGlnaGxpZ2h0Q2xhc3NTdHJpbmcgPSBjb3JyZWN0U29GYXIgPyAnY29ycmVjdCcgOiAnaW5jb3JyZWN0JztcbiAgICBpZiAoQ29uZmlnLmJsaW5kTW9kZSkge1xuICAgICAgd29yZEhpZ2hsaWdodENsYXNzU3RyaW5nID0gJ2NvcnJlY3QnO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5wdXQubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGNoYXJDb3JyZWN0ID0gY3VycmVudFdvcmRbaV0gPT0gaW5wdXRbaV07XG5cbiAgICAgIGxldCBjb3JyZWN0Q2xhc3MgPSAnY29ycmVjdCc7XG4gICAgICBpZiAoQ29uZmlnLmhpZ2hsaWdodE1vZGUgPT0gJ29mZicpIHtcbiAgICAgICAgY29ycmVjdENsYXNzID0gJyc7XG4gICAgICB9XG5cbiAgICAgIGxldCBjdXJyZW50TGV0dGVyID0gY3VycmVudFdvcmRbaV07XG4gICAgICBsZXQgdGFiQ2hhciA9ICcnO1xuICAgICAgbGV0IG5sQ2hhciA9ICcnO1xuICAgICAgaWYgKENvbmZpZy5mdW5ib3ggPT09ICdhcnJvd3MnKSB7XG4gICAgICAgIGlmIChjdXJyZW50TGV0dGVyID09PSAn4oaRJykge1xuICAgICAgICAgIGN1cnJlbnRMZXR0ZXIgPSBgPGkgY2xhc3M9XCJmYXMgZmEtYXJyb3ctdXBcIj48L2k+YDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY3VycmVudExldHRlciA9PT0gJ+KGkycpIHtcbiAgICAgICAgICBjdXJyZW50TGV0dGVyID0gYDxpIGNsYXNzPVwiZmFzIGZhLWFycm93LWRvd25cIj48L2k+YDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY3VycmVudExldHRlciA9PT0gJ+KGkCcpIHtcbiAgICAgICAgICBjdXJyZW50TGV0dGVyID0gYDxpIGNsYXNzPVwiZmFzIGZhLWFycm93LWxlZnRcIj48L2k+YDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY3VycmVudExldHRlciA9PT0gJ+KGkicpIHtcbiAgICAgICAgICBjdXJyZW50TGV0dGVyID0gYDxpIGNsYXNzPVwiZmFzIGZhLWFycm93LXJpZ2h0XCI+PC9pPmA7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY3VycmVudExldHRlciA9PT0gJ1xcdCcpIHtcbiAgICAgICAgdGFiQ2hhciA9ICd0YWJDaGFyJztcbiAgICAgICAgY3VycmVudExldHRlciA9IGA8aSBjbGFzcz1cImZhcyBmYS1sb25nLWFycm93LWFsdC1yaWdodFwiPjwvaT5gO1xuICAgICAgfSBlbHNlIGlmIChjdXJyZW50TGV0dGVyID09PSAnXFxuJykge1xuICAgICAgICBubENoYXIgPSAnbmxDaGFyJztcbiAgICAgICAgY3VycmVudExldHRlciA9IGA8aSBjbGFzcz1cImZhcyBmYS1hbmdsZS1kb3duXCI+PC9pPmA7XG4gICAgICB9XG5cbiAgICAgIGlmIChjaGFyQ29ycmVjdCkge1xuICAgICAgICByZXQgKz0gYDxsZXR0ZXIgY2xhc3M9XCIke1xuICAgICAgICAgIENvbmZpZy5oaWdobGlnaHRNb2RlID09ICd3b3JkJyA/IHdvcmRIaWdobGlnaHRDbGFzc1N0cmluZyA6IGNvcnJlY3RDbGFzc1xuICAgICAgICB9ICR7dGFiQ2hhcn0ke25sQ2hhcn1cIj4ke2N1cnJlbnRMZXR0ZXJ9PC9sZXR0ZXI+YDtcbiAgICAgIH0gZWxzZSBpZiAoXG4gICAgICAgIGN1cnJlbnRMZXR0ZXIgIT09IHVuZGVmaW5lZCAmJlxuICAgICAgICBDb21wb3NpdGlvblN0YXRlLmdldENvbXBvc2luZygpICYmXG4gICAgICAgIGkgPj0gQ29tcG9zaXRpb25TdGF0ZS5nZXRTdGFydFBvcygpXG4gICAgICApIHtcbiAgICAgICAgcmV0ICs9IGA8bGV0dGVyIGNsYXNzPVwiJHtcbiAgICAgICAgICBDb25maWcuaGlnaGxpZ2h0TW9kZSA9PSAnd29yZCcgPyB3b3JkSGlnaGxpZ2h0Q2xhc3NTdHJpbmcgOiAnJ1xuICAgICAgICB9IGRlYWRcIj4ke2N1cnJlbnRMZXR0ZXJ9PC9sZXR0ZXI+YDtcbiAgICAgIH0gZWxzZSBpZiAoIXNob3dFcnJvcikge1xuICAgICAgICBpZiAoY3VycmVudExldHRlciAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgICAgcmV0ICs9IGA8bGV0dGVyIGNsYXNzPVwiJHtcbiAgICAgICAgICAgIENvbmZpZy5oaWdobGlnaHRNb2RlID09ICd3b3JkJyA/IHdvcmRIaWdobGlnaHRDbGFzc1N0cmluZyA6IGNvcnJlY3RDbGFzc1xuICAgICAgICAgIH0gJHt0YWJDaGFyfSR7bmxDaGFyfVwiPiR7Y3VycmVudExldHRlcn08L2xldHRlcj5gO1xuICAgICAgICB9XG4gICAgICB9IGVsc2UgaWYgKGN1cnJlbnRMZXR0ZXIgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBpZiAoIUNvbmZpZy5oaWRlRXh0cmFMZXR0ZXJzKSB7XG4gICAgICAgICAgbGV0IGxldHRlciA9IGlucHV0W2ldO1xuICAgICAgICAgIGlmIChsZXR0ZXIgPT0gJyAnIHx8IGxldHRlciA9PSAnXFx0JyB8fCBsZXR0ZXIgPT0gJ1xcbicpIHtcbiAgICAgICAgICAgIGxldHRlciA9ICdfJztcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0ICs9IGA8bGV0dGVyIGNsYXNzPVwiJHtcbiAgICAgICAgICAgIENvbmZpZy5oaWdobGlnaHRNb2RlID09ICd3b3JkJyA/IHdvcmRIaWdobGlnaHRDbGFzc1N0cmluZyA6ICdpbmNvcnJlY3QnXG4gICAgICAgICAgfSBleHRyYSAke3RhYkNoYXJ9JHtubENoYXJ9XCI+JHtsZXR0ZXJ9PC9sZXR0ZXI+YDtcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0ICs9XG4gICAgICAgICAgYDxsZXR0ZXIgY2xhc3M9XCIke1xuICAgICAgICAgICAgQ29uZmlnLmhpZ2hsaWdodE1vZGUgPT0gJ3dvcmQnID8gd29yZEhpZ2hsaWdodENsYXNzU3RyaW5nIDogJ2luY29ycmVjdCdcbiAgICAgICAgICB9ICR7dGFiQ2hhcn0ke25sQ2hhcn1cIj5gICtcbiAgICAgICAgICAoQ29uZmlnLmluZGljYXRlVHlwb3MgPT09ICdyZXBsYWNlJ1xuICAgICAgICAgICAgPyBpbnB1dFtpXSA9PSAnICdcbiAgICAgICAgICAgICAgPyAnXydcbiAgICAgICAgICAgICAgOiBpbnB1dFtpXVxuICAgICAgICAgICAgOiBjdXJyZW50TGV0dGVyKSArXG4gICAgICAgICAgKENvbmZpZy5pbmRpY2F0ZVR5cG9zID09PSAnYmVsb3cnID8gYDxoaW50PiR7aW5wdXRbaV19PC9oaW50PmAgOiAnJykgK1xuICAgICAgICAgICc8L2xldHRlcj4nO1xuICAgICAgfVxuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSBpbnB1dC5sZW5ndGg7IGkgPCBjdXJyZW50V29yZC5sZW5ndGg7IGkrKykge1xuICAgICAgaWYgKENvbmZpZy5mdW5ib3ggPT09ICdhcnJvd3MnKSB7XG4gICAgICAgIGlmIChjdXJyZW50V29yZFtpXSA9PT0gJ+KGkScpIHtcbiAgICAgICAgICByZXQgKz0gYDxsZXR0ZXI+PGkgY2xhc3M9XCJmYXMgZmEtYXJyb3ctdXBcIj48L2k+PC9sZXR0ZXI+YDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY3VycmVudFdvcmRbaV0gPT09ICfihpMnKSB7XG4gICAgICAgICAgcmV0ICs9IGA8bGV0dGVyPjxpIGNsYXNzPVwiZmFzIGZhLWFycm93LWRvd25cIj48L2k+PC9sZXR0ZXI+YDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY3VycmVudFdvcmRbaV0gPT09ICfihpAnKSB7XG4gICAgICAgICAgcmV0ICs9IGA8bGV0dGVyPjxpIGNsYXNzPVwiZmFzIGZhLWFycm93LWxlZnRcIj48L2k+PC9sZXR0ZXI+YDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY3VycmVudFdvcmRbaV0gPT09ICfihpInKSB7XG4gICAgICAgICAgcmV0ICs9IGA8bGV0dGVyPjxpIGNsYXNzPVwiZmFzIGZhLWFycm93LXJpZ2h0XCI+PC9pPjwvbGV0dGVyPmA7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFdvcmRbaV0gPT09ICdcXHQnKSB7XG4gICAgICAgIHJldCArPSBgPGxldHRlciBjbGFzcz0ndGFiQ2hhcic+PGkgY2xhc3M9XCJmYXMgZmEtbG9uZy1hcnJvdy1hbHQtcmlnaHRcIj48L2k+PC9sZXR0ZXI+YDtcbiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFdvcmRbaV0gPT09ICdcXG4nKSB7XG4gICAgICAgIHJldCArPSBgPGxldHRlciBjbGFzcz0nbmxDaGFyJz48aSBjbGFzcz1cImZhcyBmYS1hbmdsZS1kb3duXCI+PC9pPjwvbGV0dGVyPmA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXQgKz1cbiAgICAgICAgICBgPGxldHRlciBjbGFzcz1cIiR7Q29uZmlnLmhpZ2hsaWdodE1vZGUgPT0gJ3dvcmQnID8gd29yZEhpZ2hsaWdodENsYXNzU3RyaW5nIDogJyd9XCI+YCArXG4gICAgICAgICAgY3VycmVudFdvcmRbaV0gK1xuICAgICAgICAgICc8L2xldHRlcj4nO1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChDb25maWcuaGlnaGxpZ2h0TW9kZSA9PT0gJ2xldHRlcicgJiYgQ29uZmlnLmhpZGVFeHRyYUxldHRlcnMpIHtcbiAgICAgIGlmIChpbnB1dC5sZW5ndGggPiBjdXJyZW50V29yZC5sZW5ndGggJiYgIUNvbmZpZy5ibGluZE1vZGUpIHtcbiAgICAgICAgd29yZEF0SW5kZXguY2xhc3NMaXN0LmFkZCgnZXJyb3InKTtcbiAgICAgIH0gZWxzZSBpZiAoaW5wdXQubGVuZ3RoID09IGN1cnJlbnRXb3JkLmxlbmd0aCkge1xuICAgICAgICB3b3JkQXRJbmRleC5jbGFzc0xpc3QucmVtb3ZlKCdlcnJvcicpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuICB3b3JkQXRJbmRleC5pbm5lckhUTUwgPSByZXQ7XG4gIGlmIChuZXdsaW5lYWZ0ZXIpIHdvcmRzLmluc2VydEFkamFjZW50SFRNTCgnYmVmb3JlZW5kJywgXCI8ZGl2IGNsYXNzPSduZXdsaW5lJz48L2Rpdj5cIik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBsaW5lSnVtcChjdXJyZW50VG9wOiBudW1iZXIpOiB2b2lkIHtcbiAgaWYgKFxuICAgIChDb25maWcudGFwZU1vZGUgPT09ICdvZmYnICYmIGN1cnJlbnRUZXN0TGluZSA+IDApIHx8XG4gICAgKENvbmZpZy50YXBlTW9kZSAhPT0gJ29mZicgJiYgY3VycmVudFRlc3RMaW5lID49IDApXG4gICkge1xuICAgIGNvbnN0IGhpZGVCb3VuZCA9IGN1cnJlbnRUb3A7XG5cbiAgICBjb25zdCB0b0hpZGU6IGFueVtdID0gW107XG4gICAgY29uc3Qgd29yZEVsZW1lbnRzID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnI3dvcmRzIC53b3JkJykgYXMgTm9kZUxpc3RPZjxIVE1MRWxlbWVudD47XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjdXJyZW50V29yZEVsZW1lbnRJbmRleDsgaSsrKSB7XG4gICAgICBpZiAod29yZEVsZW1lbnRzW2ldLmNsYXNzTGlzdC5jb250YWlucygnaGlkZGVuJykpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgZm9yV29yZFRvcCA9IE1hdGguZmxvb3Iod29yZEVsZW1lbnRzW2ldLm9mZnNldFRvcCk7XG4gICAgICBpZiAoZm9yV29yZFRvcCA8IChDb25maWcudGFwZU1vZGUgPT09ICdvZmYnID8gaGlkZUJvdW5kIC0gMTAgOiBoaWRlQm91bmQgKyAxMCkpIHtcbiAgICAgICAgdG9IaWRlLnB1c2goZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbCgnI3dvcmRzIC53b3JkJylbaV0pO1xuICAgICAgfVxuICAgIH1cbiAgICB0b0hpZGUuZm9yRWFjaChlbCA9PiBlbC5yZW1vdmUoKSk7XG4gICAgY3VycmVudFdvcmRFbGVtZW50SW5kZXggLT0gdG9IaWRlLmxlbmd0aDtcbiAgfVxuICBjdXJyZW50VGVzdExpbmUrKztcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhpZ2hsaWdodEJhZFdvcmQoaW5kZXg6IG51bWJlciwgc2hvd0Vycm9yOiBib29sZWFuKTogdm9pZCB7XG4gIGlmICghc2hvd0Vycm9yKSByZXR1cm47XG4gIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJyN3b3JkcyAud29yZCcpW2luZGV4XS5jbGFzc0xpc3QuYWRkKCdlcnJvcicpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gd29yZHNJbnB1dEZvY3VzVGVzdFVJKCkge1xuICBpZiAoIXJlc3VsdFZpc2libGUgJiYgQ29uZmlnLnNob3dPdXRPZkZvY3VzV2FybmluZykge1xuICAgIE91dE9mRm9jdXMuaGlkZSgpO1xuICB9XG4gIENhcmV0LnNob3coKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHdvcmRzSW5wdXRGb2N1c091dCgpIHtcbiAgaWYgKCFyZXN1bHRWaXNpYmxlICYmIENvbmZpZy5zaG93T3V0T2ZGb2N1c1dhcm5pbmcpIHtcbiAgICBPdXRPZkZvY3VzLnNob3coKTtcbiAgfVxuICBDYXJldC5oaWRlKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiB3b3Jkc1dyYXBwZXJDbGljaygpIHtcbiAgZm9jdXNXb3JkcygpO1xufVxuIl19
@@ -1,69 +0,0 @@
1
- class Words {
2
- list;
3
- length;
4
- currentIndex;
5
- constructor() {
6
- this.list = [];
7
- this.length = 0;
8
- this.currentIndex = 0;
9
- }
10
- get(i, raw = false) {
11
- if (i === undefined) {
12
- return this.list;
13
- }
14
- else {
15
- if (raw) {
16
- return this.list[i]?.replace(/[.?!":\-,]/g, "")?.toLowerCase();
17
- }
18
- else {
19
- return this.list[i];
20
- }
21
- }
22
- }
23
- getCurrent() {
24
- return this.list[this.currentIndex];
25
- }
26
- getLast() {
27
- return this.list[this.list.length - 1];
28
- }
29
- push(word) {
30
- this.list.push(word);
31
- this.length = this.list.length;
32
- }
33
- reset() {
34
- this.list = [];
35
- this.currentIndex = 0;
36
- this.length = this.list.length;
37
- }
38
- resetCurrentIndex() {
39
- this.currentIndex = 0;
40
- }
41
- decreaseCurrentIndex() {
42
- this.currentIndex--;
43
- }
44
- increaseCurrentIndex() {
45
- this.currentIndex++;
46
- }
47
- clean() {
48
- for (const s of this.list) {
49
- if (/ +/.test(s)) {
50
- const id = this.list.indexOf(s);
51
- const tempList = s.split(" ");
52
- this.list.splice(id, 1);
53
- for (let i = 0; i < tempList.length; i++) {
54
- this.list.splice(id + i, 0, tempList[i]);
55
- }
56
- }
57
- }
58
- }
59
- }
60
- export const words = new Words();
61
- export let hasTab = false;
62
- export let randomQuote = null;
63
- export function setRandomQuote(rq) {
64
- randomQuote = rq;
65
- }
66
- export function setHasTab(tf) {
67
- hasTab = tf;
68
- }
69
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdC13b3Jkcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3BhY2thZ2VzL3Rnby10eXBpbmctdGVzdC9zcmMvbGliL2hlbHBlcnMvdGVzdC90ZXN0LXdvcmRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE1BQU0sS0FBSztJQUNGLElBQUksQ0FBVztJQUNmLE1BQU0sQ0FBUztJQUNmLFlBQVksQ0FBUztJQUM1QjtRQUNFLElBQUksQ0FBQyxJQUFJLEdBQUcsRUFBRSxDQUFDO1FBQ2YsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUM7UUFDaEIsSUFBSSxDQUFDLFlBQVksR0FBRyxDQUFDLENBQUM7SUFDeEIsQ0FBQztJQUdELEdBQUcsQ0FBQyxDQUFzQixFQUFFLEdBQUcsR0FBRyxLQUFLO1FBQ3JDLElBQUksQ0FBQyxLQUFLLFNBQVMsRUFBRSxDQUFDO1lBQ3BCLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQztRQUNuQixDQUFDO2FBQU0sQ0FBQztZQUNOLElBQUksR0FBRyxFQUFFLENBQUM7Z0JBQ1IsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLE9BQU8sQ0FBQyxhQUFhLEVBQUUsRUFBRSxDQUFDLEVBQUUsV0FBVyxFQUFFLENBQUM7WUFDakUsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN0QixDQUFDO1FBQ0gsQ0FBQztJQUNILENBQUM7SUFDRCxVQUFVO1FBQ1IsT0FBTyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUN0QyxDQUFDO0lBQ0QsT0FBTztRQUNMLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN6QyxDQUFDO0lBQ0QsSUFBSSxDQUFDLElBQVk7UUFDZixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNyQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ2pDLENBQUM7SUFDRCxLQUFLO1FBQ0gsSUFBSSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUM7UUFDZixJQUFJLENBQUMsWUFBWSxHQUFHLENBQUMsQ0FBQztRQUN0QixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ2pDLENBQUM7SUFDRCxpQkFBaUI7UUFDZixJQUFJLENBQUMsWUFBWSxHQUFHLENBQUMsQ0FBQztJQUN4QixDQUFDO0lBQ0Qsb0JBQW9CO1FBQ2xCLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBQ0Qsb0JBQW9CO1FBQ2xCLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBQ0QsS0FBSztRQUNILEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzFCLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO2dCQUNqQixNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDaEMsTUFBTSxRQUFRLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDO2dCQUN4QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO29CQUN6QyxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDM0MsQ0FBQztZQUNILENBQUM7UUFDSCxDQUFDO0lBQ0gsQ0FBQztDQUNGO0FBRUQsTUFBTSxDQUFDLE1BQU0sS0FBSyxHQUFHLElBQUksS0FBSyxFQUFFLENBQUM7QUFDakMsTUFBTSxDQUFDLElBQUksTUFBTSxHQUFHLEtBQUssQ0FBQztBQUMxQixNQUFNLENBQUMsSUFBSSxXQUFXLEdBQUcsSUFBb0MsQ0FBQztBQUU5RCxNQUFNLFVBQVUsY0FBYyxDQUFDLEVBQXFCO0lBQ2xELFdBQVcsR0FBRyxFQUFFLENBQUM7QUFDbkIsQ0FBQztBQUVELE1BQU0sVUFBVSxTQUFTLENBQUMsRUFBVztJQUNuQyxNQUFNLEdBQUcsRUFBRSxDQUFDO0FBQ2QsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE1vbmtleVR5cGVzIH0gZnJvbSAnLi4vLi4vdHlwZXMvdHlwZXMnO1xuY2xhc3MgV29yZHMge1xuICBwdWJsaWMgbGlzdDogc3RyaW5nW107XG4gIHB1YmxpYyBsZW5ndGg6IG51bWJlcjtcbiAgcHVibGljIGN1cnJlbnRJbmRleDogbnVtYmVyO1xuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLmxpc3QgPSBbXTtcbiAgICB0aGlzLmxlbmd0aCA9IDA7XG4gICAgdGhpcy5jdXJyZW50SW5kZXggPSAwO1xuICB9XG4gIGdldChpPzogdW5kZWZpbmVkLCByYXc/OiBib29sZWFuKTogc3RyaW5nW107XG4gIGdldChpOiBudW1iZXIsIHJhdz86IGJvb2xlYW4pOiBzdHJpbmc7XG4gIGdldChpPzogbnVtYmVyIHwgdW5kZWZpbmVkLCByYXcgPSBmYWxzZSk6IHN0cmluZyB8IHN0cmluZ1tdIHtcbiAgICBpZiAoaSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICByZXR1cm4gdGhpcy5saXN0O1xuICAgIH0gZWxzZSB7XG4gICAgICBpZiAocmF3KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RbaV0/LnJlcGxhY2UoL1suPyFcIjpcXC0sXS9nLCBcIlwiKT8udG9Mb3dlckNhc2UoKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiB0aGlzLmxpc3RbaV07XG4gICAgICB9XG4gICAgfVxuICB9XG4gIGdldEN1cnJlbnQoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gdGhpcy5saXN0W3RoaXMuY3VycmVudEluZGV4XTtcbiAgfVxuICBnZXRMYXN0KCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMubGlzdFt0aGlzLmxpc3QubGVuZ3RoIC0gMV07XG4gIH1cbiAgcHVzaCh3b3JkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICB0aGlzLmxpc3QucHVzaCh3b3JkKTtcbiAgICB0aGlzLmxlbmd0aCA9IHRoaXMubGlzdC5sZW5ndGg7XG4gIH1cbiAgcmVzZXQoKTogdm9pZCB7XG4gICAgdGhpcy5saXN0ID0gW107XG4gICAgdGhpcy5jdXJyZW50SW5kZXggPSAwO1xuICAgIHRoaXMubGVuZ3RoID0gdGhpcy5saXN0Lmxlbmd0aDtcbiAgfVxuICByZXNldEN1cnJlbnRJbmRleCgpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnRJbmRleCA9IDA7XG4gIH1cbiAgZGVjcmVhc2VDdXJyZW50SW5kZXgoKTogdm9pZCB7XG4gICAgdGhpcy5jdXJyZW50SW5kZXgtLTtcbiAgfVxuICBpbmNyZWFzZUN1cnJlbnRJbmRleCgpOiB2b2lkIHtcbiAgICB0aGlzLmN1cnJlbnRJbmRleCsrO1xuICB9XG4gIGNsZWFuKCk6IHZvaWQge1xuICAgIGZvciAoY29uc3QgcyBvZiB0aGlzLmxpc3QpIHtcbiAgICAgIGlmICgvICsvLnRlc3QocykpIHtcbiAgICAgICAgY29uc3QgaWQgPSB0aGlzLmxpc3QuaW5kZXhPZihzKTtcbiAgICAgICAgY29uc3QgdGVtcExpc3QgPSBzLnNwbGl0KFwiIFwiKTtcbiAgICAgICAgdGhpcy5saXN0LnNwbGljZShpZCwgMSk7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGVtcExpc3QubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICB0aGlzLmxpc3Quc3BsaWNlKGlkICsgaSwgMCwgdGVtcExpc3RbaV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBjb25zdCB3b3JkcyA9IG5ldyBXb3JkcygpO1xuZXhwb3J0IGxldCBoYXNUYWIgPSBmYWxzZTtcbmV4cG9ydCBsZXQgcmFuZG9tUXVvdGUgPSBudWxsIGFzIHVua25vd24gYXMgTW9ua2V5VHlwZXMuUXVvdGU7XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXRSYW5kb21RdW90ZShycTogTW9ua2V5VHlwZXMuUXVvdGUpOiB2b2lkIHtcbiAgcmFuZG9tUXVvdGUgPSBycTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNldEhhc1RhYih0ZjogYm9vbGVhbik6IHZvaWQge1xuICBoYXNUYWIgPSB0Zjtcbn1cbiJdfQ==
@@ -1,15 +0,0 @@
1
- import Config from '../../helpers/config';
2
- import * as Misc from '../../utils/misc';
3
- import * as Time from '../states/time';
4
- import { BehaviorSubject } from 'rxjs';
5
- export const timeLeft = new BehaviorSubject('1:00');
6
- export function update() {
7
- const time = Time.get();
8
- const maxtime = Config.time;
9
- let displayTime = Misc.secondsToString(maxtime - time);
10
- if (maxtime === 0) {
11
- displayTime = Misc.secondsToString(time);
12
- }
13
- timeLeft.next(displayTime);
14
- }
15
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGltZXItcHJvZ3Jlc3MuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wYWNrYWdlcy90Z28tdHlwaW5nLXRlc3Qvc3JjL2xpYi9oZWxwZXJzL3Rlc3QvdGltZXItcHJvZ3Jlc3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxNQUFNLE1BQU0sc0JBQXNCLENBQUM7QUFDMUMsT0FBTyxLQUFLLElBQUksTUFBTSxrQkFBa0IsQ0FBQztBQUN6QyxPQUFPLEtBQUssSUFBSSxNQUFNLGdCQUFnQixDQUFDO0FBQ3ZDLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxNQUFNLENBQUM7QUFFdkMsTUFBTSxDQUFDLE1BQU0sUUFBUSxHQUFHLElBQUksZUFBZSxDQUFTLE1BQU0sQ0FBQyxDQUFDO0FBRTVELE1BQU0sVUFBVSxNQUFNO0lBQ3BCLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUN4QixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsSUFBSSxDQUFDO0lBQzVCLElBQUksV0FBVyxHQUFHLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ3ZELElBQUksT0FBTyxLQUFLLENBQUMsRUFBRSxDQUFDO1FBQ2xCLFdBQVcsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQzNDLENBQUM7SUFDRCxRQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDO0FBQzdCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgQ29uZmlnIGZyb20gJy4uLy4uL2hlbHBlcnMvY29uZmlnJztcbmltcG9ydCAqIGFzIE1pc2MgZnJvbSAnLi4vLi4vdXRpbHMvbWlzYyc7XG5pbXBvcnQgKiBhcyBUaW1lIGZyb20gJy4uL3N0YXRlcy90aW1lJztcbmltcG9ydCB7IEJlaGF2aW9yU3ViamVjdCB9IGZyb20gJ3J4anMnO1xuXG5leHBvcnQgY29uc3QgdGltZUxlZnQgPSBuZXcgQmVoYXZpb3JTdWJqZWN0PHN0cmluZz4oJzE6MDAnKTtcblxuZXhwb3J0IGZ1bmN0aW9uIHVwZGF0ZSgpOiB2b2lkIHtcbiAgY29uc3QgdGltZSA9IFRpbWUuZ2V0KCk7XG4gIGNvbnN0IG1heHRpbWUgPSBDb25maWcudGltZTtcbiAgbGV0IGRpc3BsYXlUaW1lID0gTWlzYy5zZWNvbmRzVG9TdHJpbmcobWF4dGltZSAtIHRpbWUpO1xuICBpZiAobWF4dGltZSA9PT0gMCkge1xuICAgIGRpc3BsYXlUaW1lID0gTWlzYy5zZWNvbmRzVG9TdHJpbmcodGltZSk7XG4gIH1cbiAgdGltZUxlZnQubmV4dChkaXNwbGF5VGltZSk7XG59XG4iXX0=
@@ -1,65 +0,0 @@
1
- import * as TestInput from './test-input';
2
- // Changes how quickly it 'learns' scores - very roughly the score for a char
3
- // is based on last perCharCount occurrences. Make it smaller to adjust faster.
4
- const perCharCount = 50;
5
- // Choose the highest scoring word from this many random words. Higher values
6
- // will choose words with more weak letters on average.
7
- const wordSamples = 20;
8
- // Score penatly (in milliseconds) for getting a letter wrong.
9
- const incorrectPenalty = 5000;
10
- const scores = {};
11
- class Score {
12
- average;
13
- count;
14
- constructor() {
15
- this.average = 0.0;
16
- this.count = 0;
17
- }
18
- update(score) {
19
- if (this.count < perCharCount) {
20
- this.count++;
21
- }
22
- const adjustRate = 1.0 / this.count;
23
- // Keep an exponential moving average of the score over time.
24
- this.average = score * adjustRate + this.average * (1 - adjustRate);
25
- }
26
- }
27
- export function updateScore(char, isCorrect) {
28
- const timings = TestInput.keypressTimings.spacing.array;
29
- if (timings.length === 0 || typeof timings === 'string') {
30
- return;
31
- }
32
- let score = timings[timings.length - 1];
33
- if (!isCorrect) {
34
- score += incorrectPenalty;
35
- }
36
- if (!(char in scores)) {
37
- scores[char] = new Score();
38
- }
39
- scores[char].update(score);
40
- }
41
- function score(word) {
42
- let total = 0.0;
43
- let numChars = 0;
44
- for (const c of word) {
45
- if (c in scores) {
46
- total += scores[c].average;
47
- numChars++;
48
- }
49
- }
50
- return numChars == 0 ? 0.0 : total / numChars;
51
- }
52
- export function getWord(wordset) {
53
- let highScore;
54
- let randomWord = '';
55
- for (let i = 0; i < wordSamples; i++) {
56
- const newWord = wordset.randomWord();
57
- const newScore = score(newWord);
58
- if (i == 0 || highScore === undefined || newScore > highScore) {
59
- randomWord = newWord;
60
- highScore = newScore;
61
- }
62
- }
63
- return randomWord;
64
- }
65
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2Vhay1zcG90LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcGFja2FnZXMvdGdvLXR5cGluZy10ZXN0L3NyYy9saWIvaGVscGVycy90ZXN0L3dlYWstc3BvdC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssU0FBUyxNQUFNLGNBQWMsQ0FBQztBQUcxQyw2RUFBNkU7QUFDN0UsK0VBQStFO0FBQy9FLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQztBQUV4Qiw2RUFBNkU7QUFDN0UsdURBQXVEO0FBQ3ZELE1BQU0sV0FBVyxHQUFHLEVBQUUsQ0FBQztBQUV2Qiw4REFBOEQ7QUFDOUQsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUM7QUFFOUIsTUFBTSxNQUFNLEdBQThCLEVBQUUsQ0FBQztBQUU3QyxNQUFNLEtBQUs7SUFDRixPQUFPLENBQVM7SUFDaEIsS0FBSyxDQUFTO0lBQ3JCO1FBQ0UsSUFBSSxDQUFDLE9BQU8sR0FBRyxHQUFHLENBQUM7UUFDbkIsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUM7SUFDakIsQ0FBQztJQUVELE1BQU0sQ0FBQyxLQUFhO1FBQ2xCLElBQUksSUFBSSxDQUFDLEtBQUssR0FBRyxZQUFZLEVBQUUsQ0FBQztZQUM5QixJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDZixDQUFDO1FBQ0QsTUFBTSxVQUFVLEdBQUcsR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUM7UUFDcEMsNkRBQTZEO1FBQzdELElBQUksQ0FBQyxPQUFPLEdBQUcsS0FBSyxHQUFHLFVBQVUsR0FBRyxJQUFJLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxHQUFHLFVBQVUsQ0FBQyxDQUFDO0lBQ3RFLENBQUM7Q0FDRjtBQUVELE1BQU0sVUFBVSxXQUFXLENBQUMsSUFBWSxFQUFFLFNBQWtCO0lBQzFELE1BQU0sT0FBTyxHQUFHLFNBQVMsQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztJQUN4RCxJQUFJLE9BQU8sQ0FBQyxNQUFNLEtBQUssQ0FBQyxJQUFJLE9BQU8sT0FBTyxLQUFLLFFBQVEsRUFBRSxDQUFDO1FBQ3hELE9BQU87SUFDVCxDQUFDO0lBQ0QsSUFBSSxLQUFLLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDeEMsSUFBSSxDQUFDLFNBQVMsRUFBRSxDQUFDO1FBQ2YsS0FBSyxJQUFJLGdCQUFnQixDQUFDO0lBQzVCLENBQUM7SUFDRCxJQUFJLENBQUMsQ0FBQyxJQUFJLElBQUksTUFBTSxDQUFDLEVBQUUsQ0FBQztRQUN0QixNQUFNLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxLQUFLLEVBQUUsQ0FBQztJQUM3QixDQUFDO0lBQ0QsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUM3QixDQUFDO0FBRUQsU0FBUyxLQUFLLENBQUMsSUFBWTtJQUN6QixJQUFJLEtBQUssR0FBRyxHQUFHLENBQUM7SUFDaEIsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDO0lBQ2pCLEtBQUssTUFBTSxDQUFDLElBQUksSUFBSSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLElBQUksTUFBTSxFQUFFLENBQUM7WUFDaEIsS0FBSyxJQUFJLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUM7WUFDM0IsUUFBUSxFQUFFLENBQUM7UUFDYixDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sUUFBUSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxLQUFLLEdBQUcsUUFBUSxDQUFDO0FBQ2hELENBQUM7QUFFRCxNQUFNLFVBQVUsT0FBTyxDQUFDLE9BQWdCO0lBQ3RDLElBQUksU0FBUyxDQUFDO0lBQ2QsSUFBSSxVQUFVLEdBQUcsRUFBRSxDQUFDO0lBQ3BCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxXQUFXLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNyQyxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUM7UUFDckMsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ2hDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxTQUFTLEtBQUssU0FBUyxJQUFJLFFBQVEsR0FBRyxTQUFTLEVBQUUsQ0FBQztZQUM5RCxVQUFVLEdBQUcsT0FBTyxDQUFDO1lBQ3JCLFNBQVMsR0FBRyxRQUFRLENBQUM7UUFDdkIsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLFVBQVUsQ0FBQztBQUNwQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0ICogYXMgVGVzdElucHV0IGZyb20gJy4vdGVzdC1pbnB1dCc7XG5pbXBvcnQgeyBXb3Jkc2V0IH0gZnJvbSAnLi93b3Jkc2V0JztcblxuLy8gQ2hhbmdlcyBob3cgcXVpY2tseSBpdCAnbGVhcm5zJyBzY29yZXMgLSB2ZXJ5IHJvdWdobHkgdGhlIHNjb3JlIGZvciBhIGNoYXJcbi8vIGlzIGJhc2VkIG9uIGxhc3QgcGVyQ2hhckNvdW50IG9jY3VycmVuY2VzLiBNYWtlIGl0IHNtYWxsZXIgdG8gYWRqdXN0IGZhc3Rlci5cbmNvbnN0IHBlckNoYXJDb3VudCA9IDUwO1xuXG4vLyBDaG9vc2UgdGhlIGhpZ2hlc3Qgc2NvcmluZyB3b3JkIGZyb20gdGhpcyBtYW55IHJhbmRvbSB3b3Jkcy4gSGlnaGVyIHZhbHVlc1xuLy8gd2lsbCBjaG9vc2Ugd29yZHMgd2l0aCBtb3JlIHdlYWsgbGV0dGVycyBvbiBhdmVyYWdlLlxuY29uc3Qgd29yZFNhbXBsZXMgPSAyMDtcblxuLy8gU2NvcmUgcGVuYXRseSAoaW4gbWlsbGlzZWNvbmRzKSBmb3IgZ2V0dGluZyBhIGxldHRlciB3cm9uZy5cbmNvbnN0IGluY29ycmVjdFBlbmFsdHkgPSA1MDAwO1xuXG5jb25zdCBzY29yZXM6IHsgW2NoYXI6IHN0cmluZ106IFNjb3JlIH0gPSB7fTtcblxuY2xhc3MgU2NvcmUge1xuICBwdWJsaWMgYXZlcmFnZTogbnVtYmVyO1xuICBwdWJsaWMgY291bnQ6IG51bWJlcjtcbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5hdmVyYWdlID0gMC4wO1xuICAgIHRoaXMuY291bnQgPSAwO1xuICB9XG5cbiAgdXBkYXRlKHNjb3JlOiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jb3VudCA8IHBlckNoYXJDb3VudCkge1xuICAgICAgdGhpcy5jb3VudCsrO1xuICAgIH1cbiAgICBjb25zdCBhZGp1c3RSYXRlID0gMS4wIC8gdGhpcy5jb3VudDtcbiAgICAvLyBLZWVwIGFuIGV4cG9uZW50aWFsIG1vdmluZyBhdmVyYWdlIG9mIHRoZSBzY29yZSBvdmVyIHRpbWUuXG4gICAgdGhpcy5hdmVyYWdlID0gc2NvcmUgKiBhZGp1c3RSYXRlICsgdGhpcy5hdmVyYWdlICogKDEgLSBhZGp1c3RSYXRlKTtcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdXBkYXRlU2NvcmUoY2hhcjogc3RyaW5nLCBpc0NvcnJlY3Q6IGJvb2xlYW4pOiB2b2lkIHtcbiAgY29uc3QgdGltaW5ncyA9IFRlc3RJbnB1dC5rZXlwcmVzc1RpbWluZ3Muc3BhY2luZy5hcnJheTtcbiAgaWYgKHRpbWluZ3MubGVuZ3RoID09PSAwIHx8IHR5cGVvZiB0aW1pbmdzID09PSAnc3RyaW5nJykge1xuICAgIHJldHVybjtcbiAgfVxuICBsZXQgc2NvcmUgPSB0aW1pbmdzW3RpbWluZ3MubGVuZ3RoIC0gMV07XG4gIGlmICghaXNDb3JyZWN0KSB7XG4gICAgc2NvcmUgKz0gaW5jb3JyZWN0UGVuYWx0eTtcbiAgfVxuICBpZiAoIShjaGFyIGluIHNjb3JlcykpIHtcbiAgICBzY29yZXNbY2hhcl0gPSBuZXcgU2NvcmUoKTtcbiAgfVxuICBzY29yZXNbY2hhcl0udXBkYXRlKHNjb3JlKTtcbn1cblxuZnVuY3Rpb24gc2NvcmUod29yZDogc3RyaW5nKTogbnVtYmVyIHtcbiAgbGV0IHRvdGFsID0gMC4wO1xuICBsZXQgbnVtQ2hhcnMgPSAwO1xuICBmb3IgKGNvbnN0IGMgb2Ygd29yZCkge1xuICAgIGlmIChjIGluIHNjb3Jlcykge1xuICAgICAgdG90YWwgKz0gc2NvcmVzW2NdLmF2ZXJhZ2U7XG4gICAgICBudW1DaGFycysrO1xuICAgIH1cbiAgfVxuICByZXR1cm4gbnVtQ2hhcnMgPT0gMCA/IDAuMCA6IHRvdGFsIC8gbnVtQ2hhcnM7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRXb3JkKHdvcmRzZXQ6IFdvcmRzZXQpOiBzdHJpbmcge1xuICBsZXQgaGlnaFNjb3JlO1xuICBsZXQgcmFuZG9tV29yZCA9ICcnO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHdvcmRTYW1wbGVzOyBpKyspIHtcbiAgICBjb25zdCBuZXdXb3JkID0gd29yZHNldC5yYW5kb21Xb3JkKCk7XG4gICAgY29uc3QgbmV3U2NvcmUgPSBzY29yZShuZXdXb3JkKTtcbiAgICBpZiAoaSA9PSAwIHx8IGhpZ2hTY29yZSA9PT0gdW5kZWZpbmVkIHx8IG5ld1Njb3JlID4gaGlnaFNjb3JlKSB7XG4gICAgICByYW5kb21Xb3JkID0gbmV3V29yZDtcbiAgICAgIGhpZ2hTY29yZSA9IG5ld1Njb3JlO1xuICAgIH1cbiAgfVxuICByZXR1cm4gcmFuZG9tV29yZDtcbn1cbiJdfQ==