@ethlete/cdk 4.45.0 → 4.46.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 (22) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/esm2022/lib/components/bracket/components/new-bracket/bracket-new.mjs +782 -0
  3. package/esm2022/lib/components/bracket/components/new-bracket/draw-man.mjs +66 -0
  4. package/esm2022/lib/components/bracket/components/new-bracket/grid-definitions.mjs +47 -0
  5. package/esm2022/lib/components/bracket/components/new-bracket/grid-placements.mjs +97 -0
  6. package/esm2022/lib/components/bracket/components/new-bracket/index.mjs +8 -0
  7. package/esm2022/lib/components/bracket/components/new-bracket/new-bracket-default-match.component.mjs +17 -0
  8. package/esm2022/lib/components/bracket/components/new-bracket/new-bracket-default-round-header.component.mjs +16 -0
  9. package/esm2022/lib/components/bracket/components/new-bracket/new-bracket.component.mjs +54 -0
  10. package/esm2022/lib/components/bracket/public-api/index.mjs +5 -1
  11. package/fesm2022/ethlete-cdk.mjs +1096 -3
  12. package/fesm2022/ethlete-cdk.mjs.map +1 -1
  13. package/lib/components/bracket/components/new-bracket/bracket-new.d.ts +238 -0
  14. package/lib/components/bracket/components/new-bracket/draw-man.d.ts +12 -0
  15. package/lib/components/bracket/components/new-bracket/grid-definitions.d.ts +9 -0
  16. package/lib/components/bracket/components/new-bracket/grid-placements.d.ts +56 -0
  17. package/lib/components/bracket/components/new-bracket/index.d.ts +7 -0
  18. package/lib/components/bracket/components/new-bracket/new-bracket-default-match.component.d.ts +8 -0
  19. package/lib/components/bracket/components/new-bracket/new-bracket-default-round-header.component.d.ts +7 -0
  20. package/lib/components/bracket/components/new-bracket/new-bracket.component.d.ts +26 -0
  21. package/lib/components/bracket/public-api/index.d.ts +4 -0
  22. package/package.json +1 -1
@@ -0,0 +1,782 @@
1
+ export const FALLBACK_MATCH_POSITION = -1;
2
+ export const TOURNAMENT_MODE = {
3
+ SINGLE_ELIMINATION: 'single-elimination',
4
+ DOUBLE_ELIMINATION: 'double-elimination',
5
+ GROUP: 'group',
6
+ SWISS: 'swiss',
7
+ SWISS_WITH_ELIMINATION: 'swiss-with-elimination',
8
+ };
9
+ export const COMMON_BRACKET_ROUND_TYPE = {
10
+ THIRD_PLACE: 'third-place',
11
+ FINAL: 'final',
12
+ };
13
+ export const SINGLE_ELIMINATION_BRACKET_ROUND_TYPE = {
14
+ SINGLE_ELIMINATION_BRACKET: 'single-elimination-bracket',
15
+ };
16
+ export const DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE = {
17
+ UPPER_BRACKET: 'upper-bracket',
18
+ LOWER_BRACKET: 'lower-bracket',
19
+ REVERSE_FINAL: 'reverse-final',
20
+ };
21
+ export const SWISS_BRACKET_ROUND_TYPE = {
22
+ SWISS: 'swiss',
23
+ };
24
+ export const GROUP_BRACKET_ROUND_TYPE = {
25
+ GROUP: 'group',
26
+ };
27
+ export const generateRoundTypeFromEthleteRoundType = (type, tournamentMode) => {
28
+ switch (type) {
29
+ case 'normal':
30
+ switch (tournamentMode) {
31
+ case 'single-elimination':
32
+ return SINGLE_ELIMINATION_BRACKET_ROUND_TYPE.SINGLE_ELIMINATION_BRACKET;
33
+ case 'group':
34
+ return GROUP_BRACKET_ROUND_TYPE.GROUP;
35
+ case 'swiss':
36
+ return SWISS_BRACKET_ROUND_TYPE.SWISS;
37
+ default:
38
+ throw new Error(`Unsupported tournament mode for a normal type round: ${tournamentMode}`);
39
+ }
40
+ case 'third_place':
41
+ return COMMON_BRACKET_ROUND_TYPE.THIRD_PLACE;
42
+ case 'final':
43
+ return COMMON_BRACKET_ROUND_TYPE.FINAL;
44
+ case 'reverse_final':
45
+ return DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE.REVERSE_FINAL;
46
+ case 'winner_bracket':
47
+ return DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE.UPPER_BRACKET;
48
+ case 'loser_bracket':
49
+ return DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE.LOWER_BRACKET;
50
+ }
51
+ };
52
+ export const generateTournamentModeFormEthleteRounds = (source) => {
53
+ const firstRound = source[0];
54
+ const firstMatch = firstRound?.matches[0];
55
+ if (!firstRound)
56
+ throw new Error('No rounds found');
57
+ if (!firstMatch)
58
+ throw new Error('No matches found');
59
+ switch (firstMatch.matchType) {
60
+ case 'groups':
61
+ return TOURNAMENT_MODE.GROUP;
62
+ case 'fifa_swiss': {
63
+ const lastRound = source[source.length - 1];
64
+ if (!lastRound)
65
+ throw new Error('No last round found');
66
+ if (lastRound.matches.length !== firstRound.matches.length) {
67
+ return TOURNAMENT_MODE.SWISS_WITH_ELIMINATION;
68
+ }
69
+ else {
70
+ return TOURNAMENT_MODE.SWISS;
71
+ }
72
+ }
73
+ case 'double_elimination':
74
+ return TOURNAMENT_MODE.DOUBLE_ELIMINATION;
75
+ case 'single_elimination':
76
+ return TOURNAMENT_MODE.SINGLE_ELIMINATION;
77
+ default:
78
+ throw new Error(`Unsupported tournament mode: ${firstMatch.matchType}`);
79
+ }
80
+ };
81
+ export const generateBracketDataForEthlete = (source) => {
82
+ const tournamentMode = generateTournamentModeFormEthleteRounds(source);
83
+ const bracketData = {
84
+ rounds: new Map(),
85
+ matches: new Map(),
86
+ participants: new Map(),
87
+ mode: tournamentMode,
88
+ };
89
+ let currentUpperBracketIndex = 0;
90
+ let currentLowerBracketIndex = 0;
91
+ for (const currentItem of source) {
92
+ if (bracketData.rounds.has(currentItem.round.id)) {
93
+ throw new Error(`Round with id ${currentItem.round.id} already exists in the bracket data.`);
94
+ }
95
+ const roundType = generateRoundTypeFromEthleteRoundType(currentItem.round.type, tournamentMode);
96
+ const isLowerBracket = roundType === DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE.LOWER_BRACKET;
97
+ const bracketRound = {
98
+ type: roundType,
99
+ id: currentItem.round.id,
100
+ index: isLowerBracket ? currentLowerBracketIndex : currentUpperBracketIndex,
101
+ data: currentItem.round,
102
+ position: currentItem.round.number,
103
+ name: currentItem.round.name || currentItem.round.type,
104
+ matchCount: currentItem.matches.length,
105
+ matches: new Map(),
106
+ };
107
+ bracketData.rounds.set(currentItem.round.id, bracketRound);
108
+ for (const [matchIndex, match] of currentItem.matches.entries()) {
109
+ if (bracketData.matches.has(match.id)) {
110
+ throw new Error(`Match with id ${match.id} already exists in the bracket data.`);
111
+ }
112
+ const bracketMatch = {
113
+ id: match.id,
114
+ indexInRound: matchIndex,
115
+ position: (matchIndex + 1),
116
+ data: match,
117
+ round: bracketRound,
118
+ home: match.home?.id || null,
119
+ away: match.away?.id || null,
120
+ winner: match.winningSide,
121
+ status: match.status === 'published' ? 'completed' : 'pending',
122
+ };
123
+ bracketData.matches.set(match.id, bracketMatch);
124
+ bracketRound.matches.set(match.id, bracketMatch);
125
+ const participants = [match.home, match.away];
126
+ for (const participant of participants) {
127
+ if (!participant)
128
+ continue;
129
+ const participantId = participant.id;
130
+ if (!bracketData.participants.has(participantId)) {
131
+ bracketData.participants.set(participantId, {
132
+ id: participantId,
133
+ name: participant.name || 'Unknown',
134
+ matches: new Map(),
135
+ });
136
+ }
137
+ const participantData = bracketData.participants.get(participantId);
138
+ if (!participantData.matches.has(match.id)) {
139
+ participantData.matches.set(match.id, {
140
+ side: match.home?.id === participantId ? 'home' : 'away',
141
+ bracketMatch,
142
+ });
143
+ }
144
+ }
145
+ }
146
+ if (isLowerBracket) {
147
+ currentLowerBracketIndex++;
148
+ }
149
+ else {
150
+ currentUpperBracketIndex++;
151
+ }
152
+ }
153
+ return bracketData;
154
+ };
155
+ export const generateMatchPositionMaps = (bracketData) => {
156
+ const matchPositionMaps = new Map();
157
+ for (const round of bracketData.rounds.values()) {
158
+ const matchMap = new Map([...round.matches.values()].map((m) => [m.position, m]));
159
+ matchPositionMaps.set(round.id, matchMap);
160
+ }
161
+ return matchPositionMaps;
162
+ };
163
+ export const generateBracketRoundTypeMap = (bracketData) => {
164
+ const roundAmountMap = new Map();
165
+ for (const round of bracketData.rounds.values()) {
166
+ if (!roundAmountMap.has(round.type)) {
167
+ roundAmountMap.set(round.type, new Map([[round.id, round]]));
168
+ }
169
+ else {
170
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
171
+ roundAmountMap.set(round.type, roundAmountMap.get(round.type).set(round.id, round));
172
+ }
173
+ }
174
+ return roundAmountMap;
175
+ };
176
+ const UPPER_LOOP_ORDER = [
177
+ SINGLE_ELIMINATION_BRACKET_ROUND_TYPE.SINGLE_ELIMINATION_BRACKET,
178
+ DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE.UPPER_BRACKET,
179
+ SWISS_BRACKET_ROUND_TYPE.SWISS,
180
+ GROUP_BRACKET_ROUND_TYPE.GROUP,
181
+ COMMON_BRACKET_ROUND_TYPE.FINAL,
182
+ DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE.REVERSE_FINAL,
183
+ COMMON_BRACKET_ROUND_TYPE.THIRD_PLACE,
184
+ ];
185
+ const LOWER_LOOP_ORDER = [DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE.LOWER_BRACKET];
186
+ export const generateRoundRelations = (bracketData) => {
187
+ const roundRelations = new Map();
188
+ const sortedRoundsByType = new Map();
189
+ for (const round of bracketData.rounds.values()) {
190
+ if (!sortedRoundsByType.has(round.type)) {
191
+ sortedRoundsByType.set(round.type, [round]);
192
+ }
193
+ else {
194
+ sortedRoundsByType.get(round.type)?.push(round);
195
+ }
196
+ }
197
+ for (const rounds of sortedRoundsByType.values()) {
198
+ if (rounds.length === 1)
199
+ continue;
200
+ rounds.sort((a, b) => a.position - b.position);
201
+ }
202
+ const sortedUpperRounds = UPPER_LOOP_ORDER.map((t) => sortedRoundsByType.get(t))
203
+ .filter((r) => !!r)
204
+ .flat();
205
+ const sortedLowerRounds = LOWER_LOOP_ORDER.map((t) => sortedRoundsByType.get(t))
206
+ .filter((r) => !!r)
207
+ .flat();
208
+ const firstUpperRound = sortedUpperRounds[0] || null;
209
+ const firstLowerRound = sortedLowerRounds[0] || null;
210
+ if (!firstUpperRound)
211
+ throw new Error('firstUpperRound is null');
212
+ const hasLowerRounds = sortedLowerRounds.length > 0;
213
+ const lastLowerRound = sortedLowerRounds[sortedLowerRounds.length - 1] || null;
214
+ for (const [currentUpperRoundIndex, currentUpperRound] of sortedUpperRounds.entries()) {
215
+ const previousUpperRound = sortedUpperRounds[currentUpperRoundIndex - 1] || null;
216
+ const nextUpperRound = sortedUpperRounds[currentUpperRoundIndex + 1] || null;
217
+ const currentLowerRound = sortedLowerRounds[currentUpperRoundIndex] || null;
218
+ const previousLowerRound = sortedLowerRounds[currentUpperRoundIndex - 1] || null;
219
+ const nextLowerRound = sortedLowerRounds[currentUpperRoundIndex + 1] || null;
220
+ const isFirstRound = currentUpperRoundIndex === 0;
221
+ const isLastUpperRound = currentUpperRoundIndex === sortedUpperRounds.length - 1;
222
+ const isFinal = currentUpperRound.type === COMMON_BRACKET_ROUND_TYPE.FINAL;
223
+ if (isFinal && hasLowerRounds) {
224
+ // two to one relation
225
+ if (!lastLowerRound || !currentLowerRound || !previousUpperRound)
226
+ throw new Error('lastLowerRound or currentLowerRound or previousUpperRound is null');
227
+ // in a sync double elimination bracket, the final round has the same index as the last lower round
228
+ // in an async one, there is always one more round in the lower bracket since we only display a section of the whole tournament
229
+ const isAsyncBracket = currentLowerRound.id !== lastLowerRound.id;
230
+ const finalLowerRound = isAsyncBracket ? nextLowerRound : currentLowerRound;
231
+ if (!finalLowerRound)
232
+ throw new Error('finalLowerRound is null');
233
+ if (!firstLowerRound)
234
+ throw new Error('firstLowerRound is null');
235
+ if (finalLowerRound.id !== lastLowerRound.id)
236
+ throw new Error('finalLowerRound is not the last lower round');
237
+ // if we have a reverse final
238
+ if (nextUpperRound) {
239
+ // for the final
240
+ roundRelations.set(currentUpperRound.id, {
241
+ type: 'two-to-one',
242
+ previousUpperRound: previousUpperRound,
243
+ previousLowerRound: finalLowerRound,
244
+ nextRound: nextUpperRound,
245
+ currentRound: currentUpperRound,
246
+ nextRoundMatchFactor: nextUpperRound.matchCount / currentUpperRound.matchCount,
247
+ previousUpperRoundMatchFactor: previousUpperRound.matchCount / currentUpperRound.matchCount,
248
+ previousLowerRoundMatchFactor: finalLowerRound.matchCount / currentUpperRound.matchCount,
249
+ upperRootRoundMatchFactor: firstUpperRound.matchCount / currentUpperRound.matchCount,
250
+ lowerRootRoundMatchFactor: firstLowerRound.matchCount / currentUpperRound.matchCount,
251
+ });
252
+ }
253
+ else {
254
+ // no reverse final means the final is the last round
255
+ // for the final
256
+ roundRelations.set(currentUpperRound.id, {
257
+ type: 'two-to-nothing',
258
+ previousUpperRound: previousUpperRound,
259
+ previousLowerRound: finalLowerRound,
260
+ currentRound: currentUpperRound,
261
+ previousLowerRoundMatchFactor: finalLowerRound.matchCount / currentUpperRound.matchCount,
262
+ previousUpperRoundMatchFactor: previousUpperRound.matchCount / currentUpperRound.matchCount,
263
+ lowerRootRoundMatchFactor: firstLowerRound.matchCount / currentUpperRound.matchCount,
264
+ upperRootRoundMatchFactor: firstUpperRound.matchCount / currentUpperRound.matchCount,
265
+ });
266
+ }
267
+ if (isAsyncBracket) {
268
+ // if this is an async bracket, we need to set the relations for the 2 last lower rounds since they will be skipped by the default one to one logic
269
+ const preFinalLowerRound = sortedLowerRounds[sortedLowerRounds.length - 2] || null;
270
+ const prePreFinalLowerRound = sortedLowerRounds[sortedLowerRounds.length - 3] || null;
271
+ if (!preFinalLowerRound)
272
+ throw new Error('preFinalLowerRound is null');
273
+ if (!firstLowerRound)
274
+ throw new Error('firstLowerRound is null');
275
+ // for the last lower round
276
+ roundRelations.set(finalLowerRound.id, {
277
+ type: 'one-to-one',
278
+ previousRound: preFinalLowerRound,
279
+ nextRound: currentUpperRound,
280
+ currentRound: finalLowerRound,
281
+ nextRoundMatchFactor: currentUpperRound.matchCount / finalLowerRound.matchCount,
282
+ previousRoundMatchFactor: preFinalLowerRound.matchCount / finalLowerRound.matchCount,
283
+ rootRoundMatchFactor: firstLowerRound.matchCount / finalLowerRound.matchCount,
284
+ });
285
+ if (prePreFinalLowerRound) {
286
+ // for the pre final lower round
287
+ roundRelations.set(preFinalLowerRound.id, {
288
+ type: 'one-to-one',
289
+ previousRound: prePreFinalLowerRound,
290
+ nextRound: finalLowerRound,
291
+ currentRound: preFinalLowerRound,
292
+ nextRoundMatchFactor: finalLowerRound.matchCount / preFinalLowerRound.matchCount,
293
+ previousRoundMatchFactor: prePreFinalLowerRound.matchCount / preFinalLowerRound.matchCount,
294
+ rootRoundMatchFactor: firstLowerRound.matchCount / preFinalLowerRound.matchCount,
295
+ });
296
+ }
297
+ else {
298
+ // for the first lower round
299
+ roundRelations.set(preFinalLowerRound.id, {
300
+ type: 'nothing-to-one',
301
+ nextRound: finalLowerRound,
302
+ currentRound: preFinalLowerRound,
303
+ nextRoundMatchFactor: finalLowerRound.matchCount / preFinalLowerRound.matchCount,
304
+ });
305
+ }
306
+ }
307
+ else {
308
+ // this is a sync bracket, we only need to set the relation for the last lower round
309
+ if (!previousLowerRound)
310
+ throw new Error('previousLowerRound is null');
311
+ if (!firstLowerRound)
312
+ throw new Error('firstLowerRound is null');
313
+ // for the last lower round
314
+ roundRelations.set(finalLowerRound.id, {
315
+ type: 'one-to-one',
316
+ previousRound: previousLowerRound,
317
+ nextRound: currentUpperRound,
318
+ currentRound: finalLowerRound,
319
+ nextRoundMatchFactor: currentUpperRound.matchCount / finalLowerRound.matchCount,
320
+ previousRoundMatchFactor: previousLowerRound.matchCount / finalLowerRound.matchCount,
321
+ rootRoundMatchFactor: firstLowerRound.matchCount / finalLowerRound.matchCount,
322
+ });
323
+ }
324
+ }
325
+ else if (isLastUpperRound) {
326
+ // one to nothing relation
327
+ if (!previousUpperRound)
328
+ throw new Error('previousUpperRound is null');
329
+ roundRelations.set(currentUpperRound.id, {
330
+ type: 'one-to-nothing',
331
+ previousRound: previousUpperRound,
332
+ currentRound: currentUpperRound,
333
+ previousRoundMatchFactor: previousUpperRound.matchCount / currentUpperRound.matchCount,
334
+ rootRoundMatchFactor: firstUpperRound.matchCount / currentUpperRound.matchCount,
335
+ });
336
+ }
337
+ else if (isFirstRound) {
338
+ // nothing to one relation
339
+ if (!nextUpperRound)
340
+ throw new Error('nextUpperRound is null');
341
+ roundRelations.set(currentUpperRound.id, {
342
+ type: 'nothing-to-one',
343
+ nextRound: nextUpperRound,
344
+ currentRound: currentUpperRound,
345
+ nextRoundMatchFactor: nextUpperRound.matchCount / currentUpperRound.matchCount,
346
+ });
347
+ if (currentLowerRound) {
348
+ if (!nextLowerRound)
349
+ throw new Error('nextLowerRound is null');
350
+ roundRelations.set(currentLowerRound.id, {
351
+ type: 'nothing-to-one',
352
+ nextRound: nextLowerRound,
353
+ currentRound: currentLowerRound,
354
+ nextRoundMatchFactor: nextLowerRound.matchCount / currentLowerRound.matchCount,
355
+ });
356
+ }
357
+ }
358
+ else {
359
+ // one to one relation
360
+ if (!previousUpperRound)
361
+ throw new Error('previousUpperRound is null');
362
+ if (!nextUpperRound)
363
+ throw new Error('nextUpperRound is null');
364
+ roundRelations.set(currentUpperRound.id, {
365
+ type: 'one-to-one',
366
+ previousRound: previousUpperRound,
367
+ nextRound: nextUpperRound,
368
+ currentRound: currentUpperRound,
369
+ nextRoundMatchFactor: nextUpperRound.matchCount / currentUpperRound.matchCount,
370
+ previousRoundMatchFactor: previousUpperRound.matchCount / currentUpperRound.matchCount,
371
+ rootRoundMatchFactor: firstUpperRound.matchCount / currentUpperRound.matchCount,
372
+ });
373
+ // we only want to set lower rounds here until the special merging point of the final.
374
+ // lower bracket rounds after and including the final will be set in the final round block
375
+ if (currentLowerRound && currentUpperRound.type === DOUBLE_ELIMINATION_BRACKET_ROUND_TYPE.UPPER_BRACKET) {
376
+ if (!previousLowerRound)
377
+ throw new Error('previousLowerRound is null');
378
+ if (!nextLowerRound)
379
+ throw new Error('nextLowerRound is null');
380
+ if (!firstLowerRound)
381
+ throw new Error('firstLowerRound is null');
382
+ roundRelations.set(currentLowerRound.id, {
383
+ type: 'one-to-one',
384
+ previousRound: previousLowerRound,
385
+ nextRound: nextLowerRound,
386
+ currentRound: currentLowerRound,
387
+ nextRoundMatchFactor: nextLowerRound.matchCount / currentLowerRound.matchCount,
388
+ previousRoundMatchFactor: previousLowerRound.matchCount / currentLowerRound.matchCount,
389
+ rootRoundMatchFactor: firstLowerRound.matchCount / currentLowerRound.matchCount,
390
+ });
391
+ }
392
+ }
393
+ }
394
+ return roundRelations;
395
+ };
396
+ export const generateMatchRelations = (bracketData, roundRelations, matchPositionMaps) => {
397
+ const matchRelations = new Map();
398
+ for (const match of bracketData.matches.values()) {
399
+ const currentRelation = roundRelations.get(match.round.id);
400
+ if (!currentRelation)
401
+ throw new Error('Match round not found');
402
+ const { nextRoundMatchPosition, previousLowerRoundMatchPosition, previousUpperRoundMatchPosition } = generateMatchRelationPositions(currentRelation, match);
403
+ switch (currentRelation.type) {
404
+ case 'nothing-to-one': {
405
+ const nextMatch = matchPositionMaps.get(currentRelation.nextRound.id)?.get(nextRoundMatchPosition);
406
+ if (!nextMatch)
407
+ throw new Error('Next round match not found');
408
+ // means left is nothing. right is one
409
+ matchRelations.set(match.id, {
410
+ type: 'nothing-to-one',
411
+ currentMatch: match,
412
+ currentRound: currentRelation.currentRound,
413
+ nextRound: currentRelation.nextRound,
414
+ nextMatch,
415
+ });
416
+ break;
417
+ }
418
+ case 'one-to-nothing': {
419
+ const previousUpperMatch = matchPositionMaps
420
+ .get(currentRelation.previousRound.id)
421
+ ?.get(previousUpperRoundMatchPosition);
422
+ const previousLowerMatch = matchPositionMaps
423
+ .get(currentRelation.previousRound.id)
424
+ ?.get(previousLowerRoundMatchPosition);
425
+ if (!previousUpperMatch)
426
+ throw new Error('Previous round match not found');
427
+ if (previousUpperRoundMatchPosition !== previousLowerRoundMatchPosition) {
428
+ // means left is two. right is one
429
+ if (!previousLowerMatch)
430
+ throw new Error('Previous lower round match not found');
431
+ matchRelations.set(match.id, {
432
+ type: 'two-to-nothing',
433
+ currentMatch: match,
434
+ currentRound: currentRelation.currentRound,
435
+ previousUpperMatch,
436
+ previousUpperRound: currentRelation.previousRound,
437
+ previousLowerMatch,
438
+ previousLowerRound: currentRelation.previousRound,
439
+ });
440
+ }
441
+ else {
442
+ // means left is one. right is nothing
443
+ matchRelations.set(match.id, {
444
+ type: 'one-to-nothing',
445
+ currentMatch: match,
446
+ currentRound: currentRelation.currentRound,
447
+ previousMatch: previousUpperMatch,
448
+ previousRound: currentRelation.previousRound,
449
+ });
450
+ }
451
+ break;
452
+ }
453
+ case 'one-to-one': {
454
+ const nextMatch = matchPositionMaps.get(currentRelation.nextRound.id)?.get(nextRoundMatchPosition);
455
+ const previousUpperMatch = matchPositionMaps
456
+ .get(currentRelation.previousRound.id)
457
+ ?.get(previousUpperRoundMatchPosition);
458
+ const previousLowerMatch = matchPositionMaps
459
+ .get(currentRelation.previousRound.id)
460
+ ?.get(previousLowerRoundMatchPosition);
461
+ if (!nextMatch)
462
+ throw new Error('Next round match not found');
463
+ if (!previousUpperMatch)
464
+ throw new Error(`Previous upper round match not found`);
465
+ if (!previousLowerMatch)
466
+ throw new Error('Previous lower round match not found');
467
+ // can be either one to one or two to one
468
+ const isLeftOne = previousUpperRoundMatchPosition === previousLowerRoundMatchPosition;
469
+ if (isLeftOne) {
470
+ // one-to-one
471
+ matchRelations.set(match.id, {
472
+ type: 'one-to-one',
473
+ currentMatch: match,
474
+ currentRound: currentRelation.currentRound,
475
+ previousMatch: previousUpperMatch,
476
+ previousRound: currentRelation.previousRound,
477
+ nextMatch,
478
+ nextRound: currentRelation.nextRound,
479
+ });
480
+ }
481
+ else {
482
+ // two-to-one
483
+ matchRelations.set(match.id, {
484
+ type: 'two-to-one',
485
+ currentMatch: match,
486
+ currentRound: currentRelation.currentRound,
487
+ previousUpperMatch,
488
+ previousUpperRound: currentRelation.previousRound,
489
+ previousLowerMatch,
490
+ previousLowerRound: currentRelation.previousRound,
491
+ nextMatch,
492
+ nextRound: currentRelation.nextRound,
493
+ });
494
+ }
495
+ break;
496
+ }
497
+ case 'two-to-one': {
498
+ const nextMatch = matchPositionMaps.get(currentRelation.nextRound.id)?.get(nextRoundMatchPosition);
499
+ const previousUpperMatch = matchPositionMaps
500
+ .get(currentRelation.previousUpperRound.id)
501
+ ?.get(previousUpperRoundMatchPosition);
502
+ const previousLowerMatch = matchPositionMaps
503
+ .get(currentRelation.previousLowerRound.id)
504
+ ?.get(previousLowerRoundMatchPosition);
505
+ if (!nextMatch)
506
+ throw new Error('Next round match not found');
507
+ if (!previousUpperMatch)
508
+ throw new Error(`Previous upper round match not found`);
509
+ if (!previousLowerMatch)
510
+ throw new Error('Previous lower round match not found');
511
+ matchRelations.set(match.id, {
512
+ type: 'two-to-one',
513
+ currentMatch: match,
514
+ currentRound: currentRelation.currentRound,
515
+ previousUpperMatch,
516
+ previousUpperRound: currentRelation.previousUpperRound,
517
+ previousLowerMatch,
518
+ previousLowerRound: currentRelation.previousLowerRound,
519
+ nextMatch,
520
+ nextRound: currentRelation.nextRound,
521
+ });
522
+ break;
523
+ }
524
+ case 'two-to-nothing': {
525
+ const previousUpperMatch = matchPositionMaps
526
+ .get(currentRelation.previousUpperRound.id)
527
+ ?.get(previousUpperRoundMatchPosition);
528
+ const previousLowerMatch = matchPositionMaps
529
+ .get(currentRelation.previousUpperRound.id)
530
+ ?.get(previousLowerRoundMatchPosition);
531
+ if (!previousUpperMatch)
532
+ throw new Error(`Previous upper round match not found`);
533
+ if (!previousLowerMatch)
534
+ throw new Error('Previous lower round match not found');
535
+ matchRelations.set(match.id, {
536
+ type: 'two-to-nothing',
537
+ currentMatch: match,
538
+ currentRound: currentRelation.currentRound,
539
+ previousUpperMatch,
540
+ previousUpperRound: currentRelation.previousUpperRound,
541
+ previousLowerMatch,
542
+ previousLowerRound: currentRelation.previousUpperRound,
543
+ });
544
+ break;
545
+ }
546
+ }
547
+ }
548
+ return matchRelations;
549
+ };
550
+ export const generateMatchRelationPositions = (currentRelation, match) => {
551
+ switch (currentRelation.type) {
552
+ case 'nothing-to-one': {
553
+ return {
554
+ nextRoundMatchPosition: generateMatchPosition(match, currentRelation.nextRoundMatchFactor),
555
+ previousUpperRoundMatchPosition: FALLBACK_MATCH_POSITION,
556
+ previousLowerRoundMatchPosition: FALLBACK_MATCH_POSITION,
557
+ };
558
+ }
559
+ case 'one-to-nothing': {
560
+ const previousRoundHasDoubleTheMatchCount = currentRelation.previousRoundMatchFactor === 2;
561
+ const doubleUpperMatchCountShift = previousRoundHasDoubleTheMatchCount ? 1 : 0;
562
+ return {
563
+ nextRoundMatchPosition: FALLBACK_MATCH_POSITION,
564
+ previousUpperRoundMatchPosition: (generateMatchPosition(match, currentRelation.previousRoundMatchFactor) -
565
+ doubleUpperMatchCountShift),
566
+ previousLowerRoundMatchPosition: generateMatchPosition(match, currentRelation.previousRoundMatchFactor),
567
+ };
568
+ }
569
+ case 'one-to-one': {
570
+ const previousRoundHasDoubleTheMatchCount = currentRelation.previousRoundMatchFactor === 2;
571
+ const doubleUpperMatchCountShift = previousRoundHasDoubleTheMatchCount ? 1 : 0;
572
+ return {
573
+ nextRoundMatchPosition: generateMatchPosition(match, currentRelation.nextRoundMatchFactor),
574
+ previousUpperRoundMatchPosition: (generateMatchPosition(match, currentRelation.previousRoundMatchFactor) -
575
+ doubleUpperMatchCountShift),
576
+ previousLowerRoundMatchPosition: generateMatchPosition(match, currentRelation.previousRoundMatchFactor),
577
+ };
578
+ }
579
+ case 'two-to-one': {
580
+ return {
581
+ nextRoundMatchPosition: generateMatchPosition(match, currentRelation.nextRoundMatchFactor),
582
+ previousUpperRoundMatchPosition: generateMatchPosition(match, currentRelation.previousUpperRoundMatchFactor),
583
+ previousLowerRoundMatchPosition: generateMatchPosition(match, currentRelation.previousLowerRoundMatchFactor),
584
+ };
585
+ }
586
+ case 'two-to-nothing': {
587
+ return {
588
+ nextRoundMatchPosition: FALLBACK_MATCH_POSITION,
589
+ previousUpperRoundMatchPosition: generateMatchPosition(match, currentRelation.previousUpperRoundMatchFactor),
590
+ previousLowerRoundMatchPosition: generateMatchPosition(match, currentRelation.previousLowerRoundMatchFactor),
591
+ };
592
+ }
593
+ }
594
+ };
595
+ export const generateMatchPosition = (match, factor) => {
596
+ return Math.ceil(match.position * factor);
597
+ };
598
+ export const logRoundRelations = (roundRelations, bracketData) => {
599
+ for (const [roundId, relation] of roundRelations.entries()) {
600
+ const round = bracketData.rounds.get(roundId);
601
+ if (!round) {
602
+ console.error(`Round with id ${roundId} not found in bracket data. The bracket will be malformed.`);
603
+ continue;
604
+ }
605
+ switch (relation.type) {
606
+ case 'nothing-to-one':
607
+ console.log(`START: ${round.name} -> ${relation.nextRound.name} (F: ${relation.nextRoundMatchFactor})`);
608
+ break;
609
+ case 'one-to-nothing':
610
+ console.log(`${relation.previousRound.name} (F: ${relation.previousRoundMatchFactor}) <- ENDING: ${round.name}`);
611
+ break;
612
+ case 'one-to-one':
613
+ console.log(`${relation.previousRound.name} (F: ${relation.previousRoundMatchFactor}) <- ${round.name} -> ${relation.nextRound.name} (F: ${relation.nextRoundMatchFactor})`);
614
+ break;
615
+ case 'two-to-one':
616
+ console.log(`MERGER: ${relation.previousUpperRound.name} (F: ${relation.previousUpperRoundMatchFactor}) AND ${relation.previousLowerRound.name} (F: ${relation.previousLowerRoundMatchFactor}) <- ${round.name} -> ${relation.nextRound.name} (F: ${relation.nextRoundMatchFactor})`);
617
+ break;
618
+ case 'two-to-nothing':
619
+ console.log(`MERGER: ${relation.previousUpperRound.name} (F: ${relation.previousUpperRoundMatchFactor}) AND ${relation.previousLowerRound.name} (F: ${relation.previousLowerRoundMatchFactor}) <- ENDING: ${round.name}`);
620
+ break;
621
+ }
622
+ }
623
+ };
624
+ export const generateMatchParticipantMap = (bracketData) => {
625
+ const matchParticipantMap = new Map();
626
+ const hasElimination = bracketData.mode === TOURNAMENT_MODE.SINGLE_ELIMINATION ||
627
+ bracketData.mode === TOURNAMENT_MODE.DOUBLE_ELIMINATION ||
628
+ bracketData.mode === TOURNAMENT_MODE.SWISS_WITH_ELIMINATION;
629
+ for (const participant of bracketData.participants.values()) {
630
+ let winsTilNow = 0;
631
+ let lossesTilNow = 0;
632
+ let tiesTilNow = 0;
633
+ for (const matchParticipantMatch of participant.matches.values()) {
634
+ const isWinner = matchParticipantMatch.bracketMatch.winner === matchParticipantMatch.side;
635
+ const isLooser = matchParticipantMatch.bracketMatch.winner &&
636
+ matchParticipantMatch.bracketMatch.winner !== matchParticipantMatch.side;
637
+ const isTie = matchParticipantMatch.bracketMatch.status === 'completed' && !matchParticipantMatch.bracketMatch.winner;
638
+ if (isWinner) {
639
+ winsTilNow++;
640
+ }
641
+ else if (isLooser) {
642
+ lossesTilNow++;
643
+ }
644
+ else if (isTie) {
645
+ tiesTilNow++;
646
+ }
647
+ let isEliminated = false;
648
+ let isEliminationMatch = false;
649
+ if (hasElimination) {
650
+ // TODO: Implement elimination logic
651
+ // Means the current match is loss and it's the last match of the participant
652
+ isEliminated = false;
653
+ // Always true for single elimination, never for e.g. groups, depends on the round for double elimination, depends on the loss count for swiss with elimination
654
+ isEliminationMatch = false;
655
+ }
656
+ // TODO: Implement round logic
657
+ // true if its the first round of the bracket
658
+ const isFirstRound = false;
659
+ // true if its the last round of the bracket (eg. final for single elimination)
660
+ const isLastRound = false;
661
+ const participantMatchData = {
662
+ bracketMatch: matchParticipantMatch.bracketMatch,
663
+ result: isWinner ? 'win' : isLooser ? 'loss' : isTie ? 'tie' : null,
664
+ isEliminated,
665
+ isEliminationMatch,
666
+ isFirstRound,
667
+ isLastRound,
668
+ tieCount: tiesTilNow,
669
+ winCount: winsTilNow,
670
+ lossCount: lossesTilNow,
671
+ };
672
+ if (!matchParticipantMap.has(participant.id)) {
673
+ matchParticipantMap.set(participant.id, {
674
+ id: participant.id,
675
+ name: participant.name,
676
+ matches: new Map(),
677
+ });
678
+ }
679
+ const participantData = matchParticipantMap.get(participant.id);
680
+ participantData.matches.set(matchParticipantMatch.bracketMatch.id, participantMatchData);
681
+ }
682
+ }
683
+ return matchParticipantMap;
684
+ };
685
+ const factorialCache = new Map();
686
+ export const getAvailableSwissGroupsForRound = (roundNumber, totalMatchesInRound) => {
687
+ const ADVANCE_WINS = 3;
688
+ const ELIMINATE_LOSSES = 3;
689
+ // Cache factorial calculations
690
+ const getFactorial = (n) => {
691
+ if (n <= 1)
692
+ return 1;
693
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
694
+ if (factorialCache.has(n))
695
+ return factorialCache.get(n);
696
+ const result = n * getFactorial(n - 1);
697
+ factorialCache.set(n, result);
698
+ return result;
699
+ };
700
+ // Pre-calculate roundFactorial
701
+ const roundFact = getFactorial(roundNumber);
702
+ let totalCombinations = 0;
703
+ const validGroups = [];
704
+ // Single loop to gather valid groups and total combinations
705
+ for (let wins = roundNumber; wins >= 0; wins--) {
706
+ const losses = roundNumber - wins;
707
+ const remainingGames = ADVANCE_WINS + ELIMINATE_LOSSES - (wins + losses) - 1;
708
+ const notYetEliminated = losses < ELIMINATE_LOSSES;
709
+ const canStillAdvance = wins < ADVANCE_WINS && remainingGames >= 0;
710
+ if (!canStillAdvance || !notYetEliminated)
711
+ continue;
712
+ const combinations = roundFact / (getFactorial(wins) * getFactorial(losses));
713
+ totalCombinations += combinations;
714
+ validGroups.push({ wins, losses, combinations });
715
+ }
716
+ // Create final groups with calculated proportions
717
+ return validGroups.map(({ wins, losses, combinations }) => ({
718
+ id: `${wins}-${losses}`,
719
+ name: `${wins}-${losses}`,
720
+ matchesInGroup: Math.round((combinations / totalCombinations) * totalMatchesInRound),
721
+ }));
722
+ };
723
+ export const generateBracketRoundSwissGroupMaps = (bracketData, matchParticipantMap) => {
724
+ if (bracketData.mode !== TOURNAMENT_MODE.SWISS_WITH_ELIMINATION) {
725
+ return null;
726
+ }
727
+ const roundsWithSwissGroups = new Map();
728
+ let roundNumber = 0;
729
+ for (const bracketRound of bracketData.rounds.values()) {
730
+ const availableGroups = getAvailableSwissGroupsForRound(roundNumber, bracketRound.matchCount);
731
+ const roundSwissData = {
732
+ groups: new Map(),
733
+ };
734
+ for (const group of availableGroups) {
735
+ const subGroup = {
736
+ id: group.id,
737
+ name: group.name,
738
+ matches: new Map(),
739
+ allowedMatchCount: group.matchesInGroup,
740
+ };
741
+ roundSwissData.groups.set(group.id, subGroup);
742
+ }
743
+ const emptyMatchIds = [];
744
+ for (const match of bracketRound.matches.values()) {
745
+ const participantHome = match.home ? (matchParticipantMap.get(match.home) ?? null) : null;
746
+ const participantAway = match.away ? (matchParticipantMap.get(match.away) ?? null) : null;
747
+ const anyParticipant = participantHome || participantAway;
748
+ if (!anyParticipant) {
749
+ emptyMatchIds.push(match.id);
750
+ continue;
751
+ }
752
+ const matchParticipantMatch = anyParticipant.matches.get(match.id);
753
+ if (!matchParticipantMatch)
754
+ throw new Error('Match participant match not found');
755
+ const wins = matchParticipantMatch.winCount;
756
+ const losses = matchParticipantMatch.lossCount;
757
+ const group = roundSwissData.groups.get(`${wins}-${losses}`);
758
+ if (!group)
759
+ throw new Error('Group not found for match: ' + match.id);
760
+ group.matches.set(match.id, match);
761
+ }
762
+ for (const emptyMatchId of emptyMatchIds) {
763
+ const match = bracketRound.matches.get(emptyMatchId);
764
+ if (!match)
765
+ throw new Error('Empty match not found');
766
+ let groupFound = false;
767
+ for (const group of roundSwissData.groups.values()) {
768
+ if (group.matches.size < group.allowedMatchCount) {
769
+ group.matches.set(match.id, match);
770
+ groupFound = true;
771
+ break;
772
+ }
773
+ }
774
+ if (!groupFound) {
775
+ throw new Error('No group found for empty match');
776
+ }
777
+ }
778
+ roundNumber++;
779
+ }
780
+ return roundsWithSwissGroups;
781
+ };
782
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYnJhY2tldC1uZXcuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9saWJzL2Nkay9zcmMvbGliL2NvbXBvbmVudHMvYnJhY2tldC9jb21wb25lbnRzL25ldy1icmFja2V0L2JyYWNrZXQtbmV3LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQWtCQSxNQUFNLENBQUMsTUFBTSx1QkFBdUIsR0FBRyxDQUFDLENBQXlCLENBQUM7QUFFbEUsTUFBTSxDQUFDLE1BQU0sZUFBZSxHQUFHO0lBQzdCLGtCQUFrQixFQUFFLG9CQUFvQjtJQUN4QyxrQkFBa0IsRUFBRSxvQkFBb0I7SUFDeEMsS0FBSyxFQUFFLE9BQU87SUFDZCxLQUFLLEVBQUUsT0FBTztJQUNkLHNCQUFzQixFQUFFLHdCQUF3QjtDQUN4QyxDQUFDO0FBSVgsTUFBTSxDQUFDLE1BQU0seUJBQXlCLEdBQUc7SUFDdkMsV0FBVyxFQUFFLGFBQWE7SUFDMUIsS0FBSyxFQUFFLE9BQU87Q0FDTixDQUFDO0FBRVgsTUFBTSxDQUFDLE1BQU0scUNBQXFDLEdBQUc7SUFDbkQsMEJBQTBCLEVBQUUsNEJBQTRCO0NBQ2hELENBQUM7QUFFWCxNQUFNLENBQUMsTUFBTSxxQ0FBcUMsR0FBRztJQUNuRCxhQUFhLEVBQUUsZUFBZTtJQUM5QixhQUFhLEVBQUUsZUFBZTtJQUM5QixhQUFhLEVBQUUsZUFBZTtDQUN0QixDQUFDO0FBRVgsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUc7SUFDdEMsS0FBSyxFQUFFLE9BQU87Q0FDTixDQUFDO0FBRVgsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUc7SUFDdEMsS0FBSyxFQUFFLE9BQU87Q0FDTixDQUFDO0FBcVFYLE1BQU0sQ0FBQyxNQUFNLHFDQUFxQyxHQUFHLENBQ25ELElBQWUsRUFDZixjQUE4QixFQUNaLEVBQUU7SUFDcEIsUUFBUSxJQUFJLEVBQUUsQ0FBQztRQUNiLEtBQUssUUFBUTtZQUNYLFFBQVEsY0FB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QUNuRCxJQUFJLEtBQUssQ0FBQyxPQUFPLENBQUMsSUFBSSxHQUFHLEtBQUssQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO29CQUNqRCxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsRUFBRSxFQUFFLEtBQUssQ0FBQyxDQUFDO29CQUNuQyxVQUFVLEdBQUcsSUFBSSxDQUFDO29CQUNsQixNQUFNO2dCQUNSLENBQUM7WUFDSCxDQUFDO1lBRUQsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO2dCQUNoQixNQUFNLElBQUksS0FBSyxDQUFDLGdDQUFnQyxDQUFDLENBQUM7WUFDcEQsQ0FBQztRQUNILENBQUM7UUFFRCxXQUFXLEVBQUUsQ0FBQztJQUNoQixDQUFDO0lBRUQsT0FBTyxxQkFBcUIsQ0FBQztBQUMvQixDQUFDLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBNYXRjaExpc3RWaWV3VW5pb24sXG4gIE9wcG9uZW50U2lkZSxcbiAgUm91bmRTdGFnZVN0cnVjdHVyZVZpZXcsXG4gIFJvdW5kU3RhZ2VTdHJ1Y3R1cmVXaXRoTWF0Y2hlc1ZpZXcsXG4gIFJvdW5kVHlwZSxcbn0gZnJvbSAnQGV0aGxldGUvdHlwZXMnO1xuXG5leHBvcnQgdHlwZSBCcmFja2V0Um91bmRJZCA9IHN0cmluZyAmIHsgX19icmFuZDogJ0JyYWNrZXRSb3VuZElkJyB9O1xuZXhwb3J0IHR5cGUgQnJhY2tldE1hdGNoSWQgPSBzdHJpbmcgJiB7IF9fYnJhbmQ6ICdCcmFja2V0TWF0Y2hJZCcgfTtcbmV4cG9ydCB0eXBlIEJyYWNrZXRSb3VuZFBvc2l0aW9uID0gbnVtYmVyICYgeyBfX2JyYW5kOiAnQnJhY2tldFJvdW5kUG9zaXRpb24nIH07XG5leHBvcnQgdHlwZSBCcmFja2V0TWF0Y2hQb3NpdGlvbiA9IG51bWJlciAmIHsgX19icmFuZDogJ0JyYWNrZXRNYXRjaFBvc2l0aW9uJyB9O1xuZXhwb3J0IHR5cGUgTWF0Y2hQYXJ0aWNpcGFudElkID0gc3RyaW5nICYgeyBfX2JyYW5kOiAnTWF0Y2hQYXJ0aWNpcGFudElkJyB9O1xuZXhwb3J0IHR5cGUgQnJhY2tldFJvdW5kU3dpc3NHcm91cElkID0gc3RyaW5nICYgeyBfX2JyYW5kOiAnQnJhY2tldFJvdW5kU3dpc3NHcm91cElkJyB9O1xuXG4vLyBXaWxsIHVzdWFsbHkgYmUgMC41LCAxIG9yIDIuIEluIFN3aXNzIHRoaXMgdmFsdWUgd2lsbCBiZSBnaWJiZXJpc2hcbmV4cG9ydCB0eXBlIE1hdGNoRmFjdG9yID0gbnVtYmVyO1xuXG5leHBvcnQgY29uc3QgRkFMTEJBQ0tfTUFUQ0hfUE9TSVRJT04gPSAtMSBhcyBCcmFja2V0TWF0Y2hQb3NpdGlvbjtcblxuZXhwb3J0IGNvbnN0IFRPVVJOQU1FTlRfTU9ERSA9IHtcbiAgU0lOR0xFX0VMSU1JTkFUSU9OOiAnc2luZ2xlLWVsaW1pbmF0aW9uJyxcbiAgRE9VQkxFX0VMSU1JTkFUSU9OOiAnZG91YmxlLWVsaW1pbmF0aW9uJyxcbiAgR1JPVVA6ICdncm91cCcsXG4gIFNXSVNTOiAnc3dpc3MnLFxuICBTV0lTU19XSVRIX0VMSU1JTkFUSU9OOiAnc3dpc3Mtd2l0aC1lbGltaW5hdGlvbicsXG59IGFzIGNvbnN0O1xuXG5leHBvcnQgdHlwZSBUb3VybmFtZW50TW9kZSA9ICh0eXBlb2YgVE9VUk5BTUVOVF9NT0RFKVtrZXlvZiB0eXBlb2YgVE9VUk5BTUVOVF9NT0RFXTtcblxuZXhwb3J0IGNvbnN0IENPTU1PTl9CUkFDS0VUX1JPVU5EX1RZUEUgPSB7XG4gIFRISVJEX1BMQUNFOiAndGhpcmQtcGxhY2UnLFxuICBGSU5BTDogJ2ZpbmFsJyxcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCBjb25zdCBTSU5HTEVfRUxJTUlOQVRJT05fQlJBQ0tFVF9ST1VORF9UWVBFID0ge1xuICBTSU5HTEVfRUxJTUlOQVRJT05fQlJBQ0tFVDogJ3NpbmdsZS1lbGltaW5hdGlvbi1icmFja2V0Jyxcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCBjb25zdCBET1VCTEVfRUxJTUlOQVRJT05fQlJBQ0tFVF9ST1VORF9UWVBFID0ge1xuICBVUFBFUl9CUkFDS0VUOiAndXBwZXItYnJhY2tldCcsXG4gIExPV0VSX0JSQUNLRVQ6ICdsb3dlci1icmFja2V0JyxcbiAgUkVWRVJTRV9GSU5BTDogJ3JldmVyc2UtZmluYWwnLFxufSBhcyBjb25zdDtcblxuZXhwb3J0IGNvbnN0IFNXSVNTX0JSQUNLRVRfUk9VTkRfVFlQRSA9IHtcbiAgU1dJU1M6ICdzd2lzcycsXG59IGFzIGNvbnN0O1xuXG5leHBvcnQgY29uc3QgR1JPVVBfQlJBQ0tFVF9ST1VORF9UWVBFID0ge1xuICBHUk9VUDogJ2dyb3VwJyxcbn0gYXMgY29uc3Q7XG5cbmV4cG9ydCB0eXBlIENvbW1vbkJyYWNrZXRSb3VuZFR5cGUgPSAodHlwZW9mIENPTU1PTl9CUkFDS0VUX1JPVU5EX1RZUEUpW2tleW9mIHR5cGVvZiBDT01NT05fQlJBQ0tFVF9ST1VORF9UWVBFXTtcbmV4cG9ydCB0eXBlIFNpbmdsZUVsaW1pbmF0aW9uQnJhY2tldFJvdW5kVHlwZSA9XG4gIHwgQ29tbW9uQnJhY2tldFJvdW5kVHlwZVxuICB8ICh0eXBlb2YgU0lOR0xFX0VMSU1JTkFUSU9OX0JSQUNLRVRfUk9VTkRfVFlQRSlba2V5b2YgdHlwZW9mIFNJTkdMRV9FTElNSU5BVElPTl9CUkFDS0VUX1JPVU5EX1RZUEVdO1xuZXhwb3J0IHR5cGUgRG91YmxlRWxpbWluYXRpb25CcmFja2V0Um91bmRUeXBlID1cbiAgfCBDb21tb25CcmFja2V0Um91bmRUeXBlXG4gIHwgKHR5cGVvZiBET1VCTEVfRUxJTUlOQVRJT05fQlJBQ0tFVF9ST1VORF9UWVBFKVtrZXlvZiB0eXBlb2YgRE9VQkxFX0VMSU1JTkFUSU9OX0JSQUNLRVRfUk9VTkRfVFlQRV07XG5leHBvcnQgdHlwZSBTd2lzc0JyYWNrZXRSb3VuZFR5cGUgPSAodHlwZW9mIFNXSVNTX0JSQUNLRVRfUk9VTkRfVFlQRSlba2V5b2YgdHlwZW9mIFNXSVNTX0JSQUNLRVRfUk9VTkRfVFlQRV07XG5leHBvcnQgdHlwZSBHcm91cEJyYWNrZXRSb3VuZFR5cGUgPSAodHlwZW9mIEdST1VQX0JSQUNLRVRfUk9VTkRfVFlQRSlba2V5b2YgdHlwZW9mIEdST1VQX0JSQUNLRVRfUk9VTkRfVFlQRV07XG5cbmV4cG9ydCB0eXBlIEJyYWNrZXRSb3VuZFR5cGUgPVxuICB8IFNpbmdsZUVsaW1pbmF0aW9uQnJhY2tldFJvdW5kVHlwZVxuICB8IERvdWJsZUVsaW1pbmF0aW9uQnJhY2tldFJvdW5kVHlwZVxuICB8IFN3aXNzQnJhY2tldFJvdW5kVHlwZVxuICB8IEdyb3VwQnJhY2tldFJvdW5kVHlwZTtcblxuZXhwb3J0IHR5cGUgQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICAvLyBOT1RFOiBUaGlzIGlzIHRoZSBsb2dpY2FsIGluZGV4IGluc2lkZSB0aGUgYnJhY2tldC5cbiAgLy8gSW4gYSBkb3VibGUgZWxpbWluYXRpb24gYnJhY2tldCwgdGhlIGZpcnN0IHJvdW5kIG9mIHRoZSBsb3dlciBicmFja2V0IHdpbGwgaGF2ZSB0aGUgc2FtZSBpbmRleCBhcyB0aGUgZmluYWwgcm91bmQgb2YgdGhlIHVwcGVyIGJyYWNrZXRcbiAgaW5kZXg6IG51bWJlcjtcbiAgdHlwZTogQnJhY2tldFJvdW5kVHlwZTtcbiAgaWQ6IEJyYWNrZXRSb3VuZElkO1xuICBkYXRhOiBUUm91bmREYXRhO1xuICBwb3NpdGlvbjogQnJhY2tldFJvdW5kUG9zaXRpb247XG4gIG5hbWU6IHN0cmluZztcbiAgbWF0Y2hDb3VudDogbnVtYmVyO1xuICBtYXRjaGVzOiBCcmFja2V0TWF0Y2hNYXA8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG59O1xuXG5leHBvcnQgdHlwZSBCcmFja2V0TWF0Y2hTdGF0dXMgPSAnY29tcGxldGVkJyB8ICdwZW5kaW5nJztcblxuZXhwb3J0IHR5cGUgQnJhY2tldE1hdGNoPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICBkYXRhOiBUTWF0Y2hEYXRhO1xuICBpbmRleEluUm91bmQ6IG51bWJlcjtcbiAgaWQ6IEJyYWNrZXRNYXRjaElkO1xuICByb3VuZDogQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBwb3NpdGlvbjogQnJhY2tldE1hdGNoUG9zaXRpb247XG4gIGhvbWU6IE1hdGNoUGFydGljaXBhbnRJZCB8IG51bGw7XG4gIGF3YXk6IE1hdGNoUGFydGljaXBhbnRJZCB8IG51bGw7XG4gIHdpbm5lcjogT3Bwb25lbnRTaWRlIHwgbnVsbDtcbiAgc3RhdHVzOiBCcmFja2V0TWF0Y2hTdGF0dXM7XG59O1xuXG5leHBvcnQgdHlwZSBCcmFja2V0Um91bmRNYXA8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPSBNYXA8QnJhY2tldFJvdW5kSWQsIEJyYWNrZXRSb3VuZDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPj47XG5leHBvcnQgdHlwZSBCcmFja2V0TWF0Y2hNYXA8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPSBNYXA8QnJhY2tldE1hdGNoSWQsIEJyYWNrZXRNYXRjaDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPj47XG5cbmV4cG9ydCB0eXBlIEJyYWNrZXREYXRhPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICByb3VuZHM6IEJyYWNrZXRSb3VuZE1hcDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgbWF0Y2hlczogQnJhY2tldE1hdGNoTWFwPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBwYXJ0aWNpcGFudHM6IEJyYWNrZXRQYXJ0aWNpcGFudE1hcDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgbW9kZTogVG91cm5hbWVudE1vZGU7XG59O1xuXG5leHBvcnQgdHlwZSBBbnlCcmFja2V0RGF0YSA9IEJyYWNrZXREYXRhPHVua25vd24sIHVua25vd24+O1xuXG4vLyBPbmUgbWF0Y2ggaGFzIG9uZSBwcmV2aW91cyBtYXRjaCBhbmQgb25lIG5leHQgbWF0Y2ggKHRoaXMgd291bGQgYmUgdGhlIGNhc2UsIGlmIGEgZ3JvdXAgdG91cm5hbWVudCBpcyBiZWluZyBkaXNwbGF5ZWQgdmlhIGEgYnJhY2tldClcbmV4cG9ydCB0eXBlIEJyYWNrZXRNYXRjaFJlbGF0aW9uT25lVG9PbmU8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPSB7XG4gIHR5cGU6ICdvbmUtdG8tb25lJztcbiAgY3VycmVudE1hdGNoOiBCcmFja2V0TWF0Y2g8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG4gIGN1cnJlbnRSb3VuZDogQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBwcmV2aW91c01hdGNoOiBCcmFja2V0TWF0Y2g8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG4gIHByZXZpb3VzUm91bmQ6IEJyYWNrZXRSb3VuZDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgbmV4dE1hdGNoOiBCcmFja2V0TWF0Y2g8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG4gIG5leHRSb3VuZDogQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xufTtcblxuLy8gVGhlIG1hdGNoIGhhcyBubyBwcmV2aW91cyBtYXRjaCBidXQgYSBzaW5nbGUgbmV4dCBtYXRjaCAoZWcuIHRoZSBzdGFydCBvZiB0aGUgYnJhY2tldClcbmV4cG9ydCB0eXBlIEJyYWNrZXRNYXRjaFJlbGF0aW9uTm90aGluZ1RvT25lPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICB0eXBlOiAnbm90aGluZy10by1vbmUnO1xuICBjdXJyZW50TWF0Y2g6IEJyYWNrZXRNYXRjaDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgY3VycmVudFJvdW5kOiBCcmFja2V0Um91bmQ8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG4gIG5leHRNYXRjaDogQnJhY2tldE1hdGNoPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBuZXh0Um91bmQ6IEJyYWNrZXRSb3VuZDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbn07XG5cbi8vIFRoZSBtYXRjaCBoYXMgbm8gbmV4dCBtYXRjaCBidXQgYSBzaW5nbGUgcHJldmlvdXMgbWF0Y2ggKGVnLiByZXZlcnNlIGZpbmFscylcbmV4cG9ydCB0eXBlIEJyYWNrZXRNYXRjaFJlbGF0aW9uT25lVG9Ob3RoaW5nPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICB0eXBlOiAnb25lLXRvLW5vdGhpbmcnO1xuICBjdXJyZW50TWF0Y2g6IEJyYWNrZXRNYXRjaDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgY3VycmVudFJvdW5kOiBCcmFja2V0Um91bmQ8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG4gIHByZXZpb3VzTWF0Y2g6IEJyYWNrZXRNYXRjaDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgcHJldmlvdXNSb3VuZDogQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xufTtcblxuLy8gVGhlIG1hdGNoIGhhcyB0d28gcHJldmlvdXMgbWF0Y2hlcyBhbmQgb25lIG5leHQgbWF0Y2ggKGVnLiBhIG5vcm1hbCBtYXRjaCBpbiB0aGUgYnJhY2tldCB0aGF0IGlzIG5laXRoZXIgdGhlIHN0YXJ0IG5vciB0aGUgZW5kKVxuZXhwb3J0IHR5cGUgQnJhY2tldE1hdGNoUmVsYXRpb25Ud29Ub09uZTxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPiA9IHtcbiAgdHlwZTogJ3R3by10by1vbmUnO1xuICBjdXJyZW50TWF0Y2g6IEJyYWNrZXRNYXRjaDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgY3VycmVudFJvdW5kOiBCcmFja2V0Um91bmQ8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG4gIHByZXZpb3VzVXBwZXJNYXRjaDogQnJhY2tldE1hdGNoPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBwcmV2aW91c1VwcGVyUm91bmQ6IEJyYWNrZXRSb3VuZDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgcHJldmlvdXNMb3dlck1hdGNoOiBCcmFja2V0TWF0Y2g8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG4gIHByZXZpb3VzTG93ZXJSb3VuZDogQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBuZXh0TWF0Y2g6IEJyYWNrZXRNYXRjaDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgbmV4dFJvdW5kOiBCcmFja2V0Um91bmQ8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG59O1xuXG4vLyBUaGUgbWF0Y2ggaGFzIHR3byBwcmV2aW91cyBtYXRjaGVzIGFuZCBubyBuZXh0IG1hdGNoIChlZy4gdGhlIGZpbmFscyBpbiBhIHNpbmdsZSBlbGltaW5hdGlvbiBicmFja2V0KVxuZXhwb3J0IHR5cGUgQnJhY2tldE1hdGNoUmVsYXRpb25Ud29Ub05vdGhpbmc8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPSB7XG4gIHR5cGU6ICd0d28tdG8tbm90aGluZyc7XG4gIGN1cnJlbnRNYXRjaDogQnJhY2tldE1hdGNoPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBjdXJyZW50Um91bmQ6IEJyYWNrZXRSb3VuZDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgcHJldmlvdXNVcHBlck1hdGNoOiBCcmFja2V0TWF0Y2g8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG4gIHByZXZpb3VzVXBwZXJSb3VuZDogQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBwcmV2aW91c0xvd2VyTWF0Y2g6IEJyYWNrZXRNYXRjaDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgcHJldmlvdXNMb3dlclJvdW5kOiBCcmFja2V0Um91bmQ8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG59O1xuXG5leHBvcnQgdHlwZSBCcmFja2V0TWF0Y2hSZWxhdGlvbjxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPiA9XG4gIHwgQnJhY2tldE1hdGNoUmVsYXRpb25PbmVUb09uZTxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPlxuICB8IEJyYWNrZXRNYXRjaFJlbGF0aW9uVHdvVG9PbmU8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT5cbiAgfCBCcmFja2V0TWF0Y2hSZWxhdGlvbk5vdGhpbmdUb09uZTxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPlxuICB8IEJyYWNrZXRNYXRjaFJlbGF0aW9uT25lVG9Ob3RoaW5nPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+XG4gIHwgQnJhY2tldE1hdGNoUmVsYXRpb25Ud29Ub05vdGhpbmc8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG5cbmV4cG9ydCB0eXBlIEJyYWNrZXRNYXRjaFJlbGF0aW9uc01hcDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPiA9IE1hcDxcbiAgQnJhY2tldE1hdGNoSWQsXG4gIEJyYWNrZXRNYXRjaFJlbGF0aW9uPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+XG4+O1xuXG4vLyBPbmUgcm91bmQgaGFzIG9uZSBuZXh0IHJvdW5kICh0aGUgZmlyc3Qgcm91bmQgb2YgdGhlIGJyYWNrZXQpXG5leHBvcnQgdHlwZSBCcmFja2V0Um91bmRSZWxhdGlvbk5vdGhpbmdUb09uZTxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPiA9IHtcbiAgdHlwZTogJ25vdGhpbmctdG8tb25lJztcbiAgY3VycmVudFJvdW5kOiBCcmFja2V0Um91bmQ8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG4gIG5leHRSb3VuZDogQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBuZXh0Um91bmRNYXRjaEZhY3RvcjogbnVtYmVyO1xufTtcblxuLy8gT25lIHJvdW5kIGhhcyBvbmUgcHJldmlvdXMgcm91bmQgKGVnLiB0aGUgZmluYWxzIHJvdW5kIG9mIHRoZSBicmFja2V0IGluIGNhc2Ugb2YgYSBzaW5nbGUgZWxpbWluYXRpb24gYnJhY2tldClcbmV4cG9ydCB0eXBlIEJyYWNrZXRSb3VuZFJlbGF0aW9uT25lVG9Ob3RoaW5nPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICB0eXBlOiAnb25lLXRvLW5vdGhpbmcnO1xuICBjdXJyZW50Um91bmQ6IEJyYWNrZXRSb3VuZDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgcHJldmlvdXNSb3VuZDogQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBwcmV2aW91c1JvdW5kTWF0Y2hGYWN0b3I6IG51bWJlcjtcbiAgcm9vdFJvdW5kTWF0Y2hGYWN0b3I6IG51bWJlcjtcbn07XG5cbi8vIE9uZSByb3VuZCBoYXMgb25lIHByZXZpb3VzIHJvdW5kIGFuZCBvbmUgbmV4dCByb3VuZCAoZWcuIGEgbm9ybWFsIHJvdW5kIGluIHRoZSBicmFja2V0IHRoYXQgaXMgbmVpdGhlciB0aGUgc3RhcnQgbm9yIHRoZSBlbmQpXG5leHBvcnQgdHlwZSBCcmFja2V0Um91bmRSZWxhdGlvbk9uZVRvT25lPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICB0eXBlOiAnb25lLXRvLW9uZSc7XG4gIGN1cnJlbnRSb3VuZDogQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBwcmV2aW91c1JvdW5kOiBCcmFja2V0Um91bmQ8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG4gIG5leHRSb3VuZDogQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBuZXh0Um91bmRNYXRjaEZhY3RvcjogbnVtYmVyO1xuICBwcmV2aW91c1JvdW5kTWF0Y2hGYWN0b3I6IG51bWJlcjtcbiAgcm9vdFJvdW5kTWF0Y2hGYWN0b3I6IG51bWJlcjtcbn07XG5cbi8vIE9uZSByb3VuZCBoYXMgdHdvIHByZXZpb3VzIHJvdW5kcyBhbmQgb25lIG5leHQgcm91bmQgKGVnLiB0aGUgZmluYWxzIHJvdW5kIGluIGEgZG91YmxlIGVsaW1pbmF0aW9uIGJyYWNrZXQgd2hlbiB0aGUgcmV2ZXJzZSBmaW5hbHMgaXMgYWxzbyBiZWluZyBwbGF5ZWQpXG5leHBvcnQgdHlwZSBCcmFja2V0Um91bmRSZWxhdGlvblR3b1RvT25lPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICB0eXBlOiAndHdvLXRvLW9uZSc7XG4gIGN1cnJlbnRSb3VuZDogQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBwcmV2aW91c1VwcGVyUm91bmQ6IEJyYWNrZXRSb3VuZDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgcHJldmlvdXNMb3dlclJvdW5kOiBCcmFja2V0Um91bmQ8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG4gIG5leHRSb3VuZDogQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBuZXh0Um91bmRNYXRjaEZhY3RvcjogbnVtYmVyO1xuICBwcmV2aW91c1VwcGVyUm91bmRNYXRjaEZhY3RvcjogbnVtYmVyO1xuICBwcmV2aW91c0xvd2VyUm91bmRNYXRjaEZhY3RvcjogbnVtYmVyO1xuICB1cHBlclJvb3RSb3VuZE1hdGNoRmFjdG9yOiBudW1iZXI7XG4gIGxvd2VyUm9vdFJvdW5kTWF0Y2hGYWN0b3I6IG51bWJlcjtcbn07XG5cbi8vIE9uZSByb3VuZCBoYXMgdHdvIHByZXZpb3VzIHJvdW5kcyBhbmQgbm8gbmV4dCByb3VuZCAoZWcuIHRoZSBmaW5hbHMgcm91bmQgaW4gYSBkb3VibGUgZWxpbWluYXRpb24gYnJhY2tldCB3aGVuIHRoZSByZXZlcnNlIGZpbmFscyBpcyBub3QgYmVpbmcgcGxheWVkKVxuZXhwb3J0IHR5cGUgQnJhY2tldFJvdW5kUmVsYXRpb25Ud29Ub05vdGhpbmc8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPSB7XG4gIHR5cGU6ICd0d28tdG8tbm90aGluZyc7XG4gIGN1cnJlbnRSb3VuZDogQnJhY2tldFJvdW5kPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICBwcmV2aW91c1VwcGVyUm91bmQ6IEJyYWNrZXRSb3VuZDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgcHJldmlvdXNMb3dlclJvdW5kOiBCcmFja2V0Um91bmQ8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG4gIHByZXZpb3VzVXBwZXJSb3VuZE1hdGNoRmFjdG9yOiBudW1iZXI7XG4gIHByZXZpb3VzTG93ZXJSb3VuZE1hdGNoRmFjdG9yOiBudW1iZXI7XG4gIHVwcGVyUm9vdFJvdW5kTWF0Y2hGYWN0b3I6IG51bWJlcjtcbiAgbG93ZXJSb290Um91bmRNYXRjaEZhY3RvcjogbnVtYmVyO1xufTtcblxuZXhwb3J0IHR5cGUgQnJhY2tldFJvdW5kUmVsYXRpb248VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPVxuICB8IEJyYWNrZXRSb3VuZFJlbGF0aW9uTm90aGluZ1RvT25lPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+XG4gIHwgQnJhY2tldFJvdW5kUmVsYXRpb25PbmVUb05vdGhpbmc8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT5cbiAgfCBCcmFja2V0Um91bmRSZWxhdGlvbk9uZVRvT25lPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+XG4gIHwgQnJhY2tldFJvdW5kUmVsYXRpb25Ud29Ub09uZTxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPlxuICB8IEJyYWNrZXRSb3VuZFJlbGF0aW9uVHdvVG9Ob3RoaW5nPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuXG5leHBvcnQgdHlwZSBCcmFja2V0Um91bmRSZWxhdGlvbnM8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPSBNYXA8XG4gIEJyYWNrZXRSb3VuZElkLFxuICBCcmFja2V0Um91bmRSZWxhdGlvbjxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPlxuPjtcblxuZXhwb3J0IHR5cGUgTWF0Y2hQb3NpdGlvbk1hcHM8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPSBNYXA8XG4gIEJyYWNrZXRSb3VuZElkLFxuICBNYXA8QnJhY2tldE1hdGNoUG9zaXRpb24sIEJyYWNrZXRNYXRjaDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPj5cbj47XG5cbmV4cG9ydCB0eXBlIFBhcnRpY2lwYW50TWF0Y2hSZXN1bHQgPSAnd2luJyB8ICdsb3NzJyB8ICd0aWUnO1xuZXhwb3J0IHR5cGUgUGFydGljaXBhbnRNYXRjaFR5cGUgPSBCcmFja2V0Um91bmRUeXBlO1xuXG5leHBvcnQgdHlwZSBNYXRjaFBhcnRpY2lwYW50TWF0Y2g8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPSB7XG4gIGJyYWNrZXRNYXRjaDogQnJhY2tldE1hdGNoPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xuICByZXN1bHQ6IFBhcnRpY2lwYW50TWF0Y2hSZXN1bHQgfCBudWxsO1xuICBpc0VsaW1pbmF0ZWQ6IGJvb2xlYW47XG4gIGlzRWxpbWluYXRpb25NYXRjaDogYm9vbGVhbjtcbiAgaXNGaXJzdFJvdW5kOiBib29sZWFuO1xuICBpc0xhc3RSb3VuZDogYm9vbGVhbjtcbiAgdGllQ291bnQ6IG51bWJlcjtcbiAgd2luQ291bnQ6IG51bWJlcjtcbiAgbG9zc0NvdW50OiBudW1iZXI7XG59O1xuXG5leHBvcnQgdHlwZSBNYXRjaFBhcnRpY2lwYW50PFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICBpZDogTWF0Y2hQYXJ0aWNpcGFudElkO1xuICBuYW1lOiBzdHJpbmc7XG4gIG1hdGNoZXM6IE1hcDxCcmFja2V0TWF0Y2hJZCwgTWF0Y2hQYXJ0aWNpcGFudE1hdGNoPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+Pjtcbn07XG5cbmV4cG9ydCB0eXBlIEJyYWNrZXRQYXJ0aWNpcGFudE1hdGNoPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICBzaWRlOiBPcHBvbmVudFNpZGU7XG4gIGJyYWNrZXRNYXRjaDogQnJhY2tldE1hdGNoPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+O1xufTtcblxuZXhwb3J0IHR5cGUgQnJhY2tldFBhcnRpY2lwYW50PFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICBpZDogTWF0Y2hQYXJ0aWNpcGFudElkO1xuICBuYW1lOiBzdHJpbmc7XG4gIG1hdGNoZXM6IE1hcDxCcmFja2V0TWF0Y2hJZCwgQnJhY2tldFBhcnRpY2lwYW50TWF0Y2g8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4+O1xufTtcblxuZXhwb3J0IHR5cGUgQnJhY2tldFBhcnRpY2lwYW50TWFwPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0gTWFwPFxuICBNYXRjaFBhcnRpY2lwYW50SWQsXG4gIEJyYWNrZXRQYXJ0aWNpcGFudDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPlxuPjtcblxuZXhwb3J0IHR5cGUgTWF0Y2hQYXJ0aWNpcGFudE1hcDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPiA9IE1hcDxcbiAgTWF0Y2hQYXJ0aWNpcGFudElkLFxuICBNYXRjaFBhcnRpY2lwYW50PFRSb3VuZERhdGEsIFRNYXRjaERhdGE+XG4+O1xuXG5leHBvcnQgdHlwZSBCcmFja2V0Um91bmRTd2lzc0dyb3VwPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICBpZDogQnJhY2tldFJvdW5kU3dpc3NHcm91cElkO1xuICBuYW1lOiBzdHJpbmc7XG4gIG1hdGNoZXM6IEJyYWNrZXRNYXRjaE1hcDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgYWxsb3dlZE1hdGNoQ291bnQ6IG51bWJlcjtcbn07XG5cbmV4cG9ydCB0eXBlIEJyYWNrZXRSb3VuZFN3aXNzR3JvdXBNYXA8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPSBNYXA8XG4gIEJyYWNrZXRSb3VuZFN3aXNzR3JvdXBJZCxcbiAgQnJhY2tldFJvdW5kU3dpc3NHcm91cDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPlxuPjtcblxuZXhwb3J0IHR5cGUgQnJhY2tldFJvdW5kU3dpc3NEYXRhPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICBncm91cHM6IEJyYWNrZXRSb3VuZFN3aXNzR3JvdXBNYXA8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT47XG59O1xuXG5leHBvcnQgdHlwZSBCcmFja2V0Um91bmRNYXBXaXRoU3dpc3NEYXRhPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0gTWFwPFxuICBCcmFja2V0Um91bmRJZCxcbiAgQnJhY2tldFJvdW5kU3dpc3NEYXRhPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+XG4+O1xuXG5leHBvcnQgdHlwZSBCcmFja2V0Um91bmRUeXBlTWFwPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0gTWFwPFxuICBCcmFja2V0Um91bmRUeXBlLFxuICBCcmFja2V0Um91bmRNYXA8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT5cbj47XG5cbmV4cG9ydCBjb25zdCBnZW5lcmF0ZVJvdW5kVHlwZUZyb21FdGhsZXRlUm91bmRUeXBlID0gKFxuICB0eXBlOiBSb3VuZFR5cGUsXG4gIHRvdXJuYW1lbnRNb2RlOiBUb3VybmFtZW50TW9kZSxcbik6IEJyYWNrZXRSb3VuZFR5cGUgPT4ge1xuICBzd2l0Y2ggKHR5cGUpIHtcbiAgICBjYXNlICdub3JtYWwnOlxuICAgICAgc3dpdGNoICh0b3VybmFtZW50TW9kZSkge1xuICAgICAgICBjYXNlICdzaW5nbGUtZWxpbWluYXRpb24nOlxuICAgICAgICAgIHJldHVybiBTSU5HTEVfRUxJTUlOQVRJT05fQlJBQ0tFVF9ST1VORF9UWVBFLlNJTkdMRV9FTElNSU5BVElPTl9CUkFDS0VUO1xuICAgICAgICBjYXNlICdncm91cCc6XG4gICAgICAgICAgcmV0dXJuIEdST1VQX0JSQUNLRVRfUk9VTkRfVFlQRS5HUk9VUDtcbiAgICAgICAgY2FzZSAnc3dpc3MnOlxuICAgICAgICAgIHJldHVybiBTV0lTU19CUkFDS0VUX1JPVU5EX1RZUEUuU1dJU1M7XG4gICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBVbnN1cHBvcnRlZCB0b3VybmFtZW50IG1vZGUgZm9yIGEgbm9ybWFsIHR5cGUgcm91bmQ6ICR7dG91cm5hbWVudE1vZGV9YCk7XG4gICAgICB9XG4gICAgY2FzZSAndGhpcmRfcGxhY2UnOlxuICAgICAgcmV0dXJuIENPTU1PTl9CUkFDS0VUX1JPVU5EX1RZUEUuVEhJUkRfUExBQ0U7XG4gICAgY2FzZSAnZmluYWwnOlxuICAgICAgcmV0dXJuIENPTU1PTl9CUkFDS0VUX1JPVU5EX1RZUEUuRklOQUw7XG4gICAgY2FzZSAncmV2ZXJzZV9maW5hbCc6XG4gICAgICByZXR1cm4gRE9VQkxFX0VMSU1JTkFUSU9OX0JSQUNLRVRfUk9VTkRfVFlQRS5SRVZFUlNFX0ZJTkFMO1xuICAgIGNhc2UgJ3dpbm5lcl9icmFja2V0JzpcbiAgICAgIHJldHVybiBET1VCTEVfRUxJTUlOQVRJT05fQlJBQ0tFVF9ST1VORF9UWVBFLlVQUEVSX0JSQUNLRVQ7XG4gICAgY2FzZSAnbG9zZXJfYnJhY2tldCc6XG4gICAgICByZXR1cm4gRE9VQkxFX0VMSU1JTkFUSU9OX0JSQUNLRVRfUk9VTkRfVFlQRS5MT1dFUl9CUkFDS0VUO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgZ2VuZXJhdGVUb3VybmFtZW50TW9kZUZvcm1FdGhsZXRlUm91bmRzID0gKFxuICBzb3VyY2U6IFJvdW5kU3RhZ2VTdHJ1Y3R1cmVXaXRoTWF0Y2hlc1ZpZXdbXSxcbik6IFRvdXJuYW1lbnRNb2RlID0+IHtcbiAgY29uc3QgZmlyc3RSb3VuZCA9IHNvdXJjZVswXTtcbiAgY29uc3QgZmlyc3RNYXRjaCA9IGZpcnN0Um91bmQ/Lm1hdGNoZXNbMF07XG5cbiAgaWYgKCFmaXJzdFJvdW5kKSB0aHJvdyBuZXcgRXJyb3IoJ05vIHJvdW5kcyBmb3VuZCcpO1xuICBpZiAoIWZpcnN0TWF0Y2gpIHRocm93IG5ldyBFcnJvcignTm8gbWF0Y2hlcyBmb3VuZCcpO1xuXG4gIHN3aXRjaCAoZmlyc3RNYXRjaC5tYXRjaFR5cGUpIHtcbiAgICBjYXNlICdncm91cHMnOlxuICAgICAgcmV0dXJuIFRPVVJOQU1FTlRfTU9ERS5HUk9VUDtcbiAgICBjYXNlICdmaWZhX3N3aXNzJzoge1xuICAgICAgY29uc3QgbGFzdFJvdW5kID0gc291cmNlW3NvdXJjZS5sZW5ndGggLSAxXTtcblxuICAgICAgaWYgKCFsYXN0Um91bmQpIHRocm93IG5ldyBFcnJvcignTm8gbGFzdCByb3VuZCBmb3VuZCcpO1xuXG4gICAgICBpZiAobGFzdFJvdW5kLm1hdGNoZXMubGVuZ3RoICE9PSBmaXJzdFJvdW5kLm1hdGNoZXMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBUT1VSTkFNRU5UX01PREUuU1dJU1NfV0lUSF9FTElNSU5BVElPTjtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBUT1VSTkFNRU5UX01PREUuU1dJU1M7XG4gICAgICB9XG4gICAgfVxuICAgIGNhc2UgJ2RvdWJsZV9lbGltaW5hdGlvbic6XG4gICAgICByZXR1cm4gVE9VUk5BTUVOVF9NT0RFLkRPVUJMRV9FTElNSU5BVElPTjtcbiAgICBjYXNlICdzaW5nbGVfZWxpbWluYXRpb24nOlxuICAgICAgcmV0dXJuIFRPVVJOQU1FTlRfTU9ERS5TSU5HTEVfRUxJTUlOQVRJT047XG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IG5ldyBFcnJvcihgVW5zdXBwb3J0ZWQgdG91cm5hbWVudCBtb2RlOiAke2ZpcnN0TWF0Y2gubWF0Y2hUeXBlfWApO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgZ2VuZXJhdGVCcmFja2V0RGF0YUZvckV0aGxldGUgPSAoc291cmNlOiBSb3VuZFN0YWdlU3RydWN0dXJlV2l0aE1hdGNoZXNWaWV3W10pID0+IHtcbiAgY29uc3QgdG91cm5hbWVudE1vZGUgPSBnZW5lcmF0ZVRvdXJuYW1lbnRNb2RlRm9ybUV0aGxldGVSb3VuZHMoc291cmNlKTtcblxuICBjb25zdCBicmFja2V0RGF0YTogQnJhY2tldERhdGE8Um91bmRTdGFnZVN0cnVjdHVyZVZpZXcsIE1hdGNoTGlzdFZpZXdVbmlvbj4gPSB7XG4gICAgcm91bmRzOiBuZXcgTWFwKCksXG4gICAgbWF0Y2hlczogbmV3IE1hcCgpLFxuICAgIHBhcnRpY2lwYW50czogbmV3IE1hcCgpLFxuICAgIG1vZGU6IHRvdXJuYW1lbnRNb2RlLFxuICB9O1xuXG4gIGxldCBjdXJyZW50VXBwZXJCcmFja2V0SW5kZXggPSAwO1xuICBsZXQgY3VycmVudExvd2VyQnJhY2tldEluZGV4ID0gMDtcblxuICBmb3IgKGNvbnN0IGN1cnJlbnRJdGVtIG9mIHNvdXJjZSkge1xuICAgIGlmIChicmFja2V0RGF0YS5yb3VuZHMuaGFzKGN1cnJlbnRJdGVtLnJvdW5kLmlkIGFzIEJyYWNrZXRSb3VuZElkKSkge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKGBSb3VuZCB3aXRoIGlkICR7Y3VycmVudEl0ZW0ucm91bmQuaWR9IGFscmVhZHkgZXhpc3RzIGluIHRoZSBicmFja2V0IGRhdGEuYCk7XG4gICAgfVxuXG4gICAgY29uc3Qgcm91bmRUeXBlID0gZ2VuZXJhdGVSb3VuZFR5cGVGcm9tRXRobGV0ZVJvdW5kVHlwZShjdXJyZW50SXRlbS5yb3VuZC50eXBlLCB0b3VybmFtZW50TW9kZSk7XG4gICAgY29uc3QgaXNMb3dlckJyYWNrZXQgPSByb3VuZFR5cGUgPT09IERPVUJMRV9FTElNSU5BVElPTl9CUkFDS0VUX1JPVU5EX1RZUEUuTE9XRVJfQlJBQ0tFVDtcblxuICAgIGNvbnN0IGJyYWNrZXRSb3VuZDogQnJhY2tldFJvdW5kPFJvdW5kU3RhZ2VTdHJ1Y3R1cmVWaWV3LCBNYXRjaExpc3RWaWV3VW5pb24+ID0ge1xuICAgICAgdHlwZTogcm91bmRUeXBlLFxuICAgICAgaWQ6IGN1cnJlbnRJdGVtLnJvdW5kLmlkIGFzIEJyYWNrZXRSb3VuZElkLFxuICAgICAgaW5kZXg6IGlzTG93ZXJCcmFja2V0ID8gY3VycmVudExvd2VyQnJhY2tldEluZGV4IDogY3VycmVudFVwcGVyQnJhY2tldEluZGV4LFxuICAgICAgZGF0YTogY3VycmVudEl0ZW0ucm91bmQsXG4gICAgICBwb3NpdGlvbjogY3VycmVudEl0ZW0ucm91bmQubnVtYmVyIGFzIEJyYWNrZXRSb3VuZFBvc2l0aW9uLFxuICAgICAgbmFtZTogY3VycmVudEl0ZW0ucm91bmQubmFtZSB8fCBjdXJyZW50SXRlbS5yb3VuZC50eXBlLFxuICAgICAgbWF0Y2hDb3VudDogY3VycmVudEl0ZW0ubWF0Y2hlcy5sZW5ndGgsXG4gICAgICBtYXRjaGVzOiBuZXcgTWFwKCksXG4gICAgfTtcblxuICAgIGJyYWNrZXREYXRhLnJvdW5kcy5zZXQoY3VycmVudEl0ZW0ucm91bmQuaWQgYXMgQnJhY2tldFJvdW5kSWQsIGJyYWNrZXRSb3VuZCk7XG5cbiAgICBmb3IgKGNvbnN0IFttYXRjaEluZGV4LCBtYXRjaF0gb2YgY3VycmVudEl0ZW0ubWF0Y2hlcy5lbnRyaWVzKCkpIHtcbiAgICAgIGlmIChicmFja2V0RGF0YS5tYXRjaGVzLmhhcyhtYXRjaC5pZCBhcyBCcmFja2V0TWF0Y2hJZCkpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBNYXRjaCB3aXRoIGlkICR7bWF0Y2guaWR9IGFscmVhZHkgZXhpc3RzIGluIHRoZSBicmFja2V0IGRhdGEuYCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGJyYWNrZXRNYXRjaDogQnJhY2tldE1hdGNoPFJvdW5kU3RhZ2VTdHJ1Y3R1cmVWaWV3LCBNYXRjaExpc3RWaWV3VW5pb24+ID0ge1xuICAgICAgICBpZDogbWF0Y2guaWQgYXMgQnJhY2tldE1hdGNoSWQsXG4gICAgICAgIGluZGV4SW5Sb3VuZDogbWF0Y2hJbmRleCxcbiAgICAgICAgcG9zaXRpb246IChtYXRjaEluZGV4ICsgMSkgYXMgQnJhY2tldE1hdGNoUG9zaXRpb24sXG4gICAgICAgIGRhdGE6IG1hdGNoLFxuICAgICAgICByb3VuZDogYnJhY2tldFJvdW5kLFxuICAgICAgICBob21lOiAobWF0Y2guaG9tZT8uaWQgYXMgTWF0Y2hQYXJ0aWNpcGFudElkKSB8fCBudWxsLFxuICAgICAgICBhd2F5OiAobWF0Y2guYXdheT8uaWQgYXMgTWF0Y2hQYXJ0aWNpcGFudElkKSB8fCBudWxsLFxuICAgICAgICB3aW5uZXI6IG1hdGNoLndpbm5pbmdTaWRlLFxuICAgICAgICBzdGF0dXM6IG1hdGNoLnN0YXR1cyA9PT0gJ3B1Ymxpc2hlZCcgPyAnY29tcGxldGVkJyA6ICdwZW5kaW5nJyxcbiAgICAgIH07XG5cbiAgICAgIGJyYWNrZXREYXRhLm1hdGNoZXMuc2V0KG1hdGNoLmlkIGFzIEJyYWNrZXRNYXRjaElkLCBicmFja2V0TWF0Y2gpO1xuICAgICAgYnJhY2tldFJvdW5kLm1hdGNoZXMuc2V0KG1hdGNoLmlkIGFzIEJyYWNrZXRNYXRjaElkLCBicmFja2V0TWF0Y2gpO1xuXG4gICAgICBjb25zdCBwYXJ0aWNpcGFudHMgPSBbbWF0Y2guaG9tZSwgbWF0Y2guYXdheV07XG5cbiAgICAgIGZvciAoY29uc3QgcGFydGljaXBhbnQgb2YgcGFydGljaXBhbnRzKSB7XG4gICAgICAgIGlmICghcGFydGljaXBhbnQpIGNvbnRpbnVlO1xuXG4gICAgICAgIGNvbnN0IHBhcnRpY2lwYW50SWQgPSBwYXJ0aWNpcGFudC5pZCBhcyBNYXRjaFBhcnRpY2lwYW50SWQ7XG5cbiAgICAgICAgaWYgKCFicmFja2V0RGF0YS5wYXJ0aWNpcGFudHMuaGFzKHBhcnRpY2lwYW50SWQpKSB7XG4gICAgICAgICAgYnJhY2tldERhdGEucGFydGljaXBhbnRzLnNldChwYXJ0aWNpcGFudElkLCB7XG4gICAgICAgICAgICBpZDogcGFydGljaXBhbnRJZCxcbiAgICAgICAgICAgIG5hbWU6IHBhcnRpY2lwYW50Lm5hbWUgfHwgJ1Vua25vd24nLFxuICAgICAgICAgICAgbWF0Y2hlczogbmV3IE1hcCgpLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcGFydGljaXBhbnREYXRhID0gYnJhY2tldERhdGEucGFydGljaXBhbnRzLmdldChwYXJ0aWNpcGFudElkKSBhcyBCcmFja2V0UGFydGljaXBhbnQ8XG4gICAgICAgICAgUm91bmRTdGFnZVN0cnVjdHVyZVZpZXcsXG4gICAgICAgICAgTWF0Y2hMaXN0Vmlld1VuaW9uXG4gICAgICAgID47XG5cbiAgICAgICAgaWYgKCFwYXJ0aWNpcGFudERhdGEubWF0Y2hlcy5oYXMobWF0Y2guaWQgYXMgQnJhY2tldE1hdGNoSWQpKSB7XG4gICAgICAgICAgcGFydGljaXBhbnREYXRhLm1hdGNoZXMuc2V0KG1hdGNoLmlkIGFzIEJyYWNrZXRNYXRjaElkLCB7XG4gICAgICAgICAgICBzaWRlOiBtYXRjaC5ob21lPy5pZCA9PT0gcGFydGljaXBhbnRJZCA/ICdob21lJyA6ICdhd2F5JyxcbiAgICAgICAgICAgIGJyYWNrZXRNYXRjaCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmIChpc0xvd2VyQnJhY2tldCkge1xuICAgICAgY3VycmVudExvd2VyQnJhY2tldEluZGV4Kys7XG4gICAgfSBlbHNlIHtcbiAgICAgIGN1cnJlbnRVcHBlckJyYWNrZXRJbmRleCsrO1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBicmFja2V0RGF0YTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZW5lcmF0ZU1hdGNoUG9zaXRpb25NYXBzID0gPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+KGJyYWNrZXREYXRhOiBCcmFja2V0RGF0YTxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPikgPT4ge1xuICBjb25zdCBtYXRjaFBvc2l0aW9uTWFwczogTWF0Y2hQb3NpdGlvbk1hcHM8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPSBuZXcgTWFwKCk7XG5cbiAgZm9yIChjb25zdCByb3VuZCBvZiBicmFja2V0RGF0YS5yb3VuZHMudmFsdWVzKCkpIHtcbiAgICBjb25zdCBtYXRjaE1hcCA9IG5ldyBNYXAoWy4uLnJvdW5kLm1hdGNoZXMudmFsdWVzKCldLm1hcCgobSkgPT4gW20ucG9zaXRpb24sIG1dKSk7XG5cbiAgICBtYXRjaFBvc2l0aW9uTWFwcy5zZXQocm91bmQuaWQsIG1hdGNoTWFwKTtcbiAgfVxuXG4gIHJldHVybiBtYXRjaFBvc2l0aW9uTWFwcztcbn07XG5cbmV4cG9ydCBjb25zdCBnZW5lcmF0ZUJyYWNrZXRSb3VuZFR5cGVNYXAgPSA8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4oXG4gIGJyYWNrZXREYXRhOiBCcmFja2V0RGF0YTxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPixcbikgPT4ge1xuICBjb25zdCByb3VuZEFtb3VudE1hcDogQnJhY2tldFJvdW5kVHlwZU1hcDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPiA9IG5ldyBNYXAoKTtcblxuICBmb3IgKGNvbnN0IHJvdW5kIG9mIGJyYWNrZXREYXRhLnJvdW5kcy52YWx1ZXMoKSkge1xuICAgIGlmICghcm91bmRBbW91bnRNYXAuaGFzKHJvdW5kLnR5cGUpKSB7XG4gICAgICByb3VuZEFtb3VudE1hcC5zZXQocm91bmQudHlwZSwgbmV3IE1hcChbW3JvdW5kLmlkLCByb3VuZF1dKSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgICByb3VuZEFtb3VudE1hcC5zZXQocm91bmQudHlwZSwgcm91bmRBbW91bnRNYXAuZ2V0KHJvdW5kLnR5cGUpIS5zZXQocm91bmQuaWQsIHJvdW5kKSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHJvdW5kQW1vdW50TWFwO1xufTtcblxuY29uc3QgVVBQRVJfTE9PUF9PUkRFUjogQnJhY2tldFJvdW5kVHlwZVtdID0gW1xuICBTSU5HTEVfRUxJTUlOQVRJT05fQlJBQ0tFVF9ST1VORF9UWVBFLlNJTkdMRV9FTElNSU5BVElPTl9CUkFDS0VULFxuICBET1VCTEVfRUxJTUlOQVRJT05fQlJBQ0tFVF9ST1VORF9UWVBFLlVQUEVSX0JSQUNLRVQsXG4gIFNXSVNTX0JSQUNLRVRfUk9VTkRfVFlQRS5TV0lTUyxcbiAgR1JPVVBfQlJBQ0tFVF9ST1VORF9UWVBFLkdST1VQLFxuICBDT01NT05fQlJBQ0tFVF9ST1VORF9UWVBFLkZJTkFMLFxuICBET1VCTEVfRUxJTUlOQVRJT05fQlJBQ0tFVF9ST1VORF9UWVBFLlJFVkVSU0VfRklOQUwsXG4gIENPTU1PTl9CUkFDS0VUX1JPVU5EX1RZUEUuVEhJUkRfUExBQ0UsXG5dO1xuXG5jb25zdCBMT1dFUl9MT09QX09SREVSOiBCcmFja2V0Um91bmRUeXBlW10gPSBbRE9VQkxFX0VMSU1JTkFUSU9OX0JSQUNLRVRfUk9VTkRfVFlQRS5MT1dFUl9CUkFDS0VUXTtcblxuZXhwb3J0IGNvbnN0IGdlbmVyYXRlUm91bmRSZWxhdGlvbnMgPSA8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4oYnJhY2tldERhdGE6IEJyYWNrZXREYXRhPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+KSA9PiB7XG4gIGNvbnN0IHJvdW5kUmVsYXRpb25zOiBCcmFja2V0Um91bmRSZWxhdGlvbnM8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPSBuZXcgTWFwKCk7XG5cbiAgY29uc3Qgc29ydGVkUm91bmRzQnlUeXBlID0gbmV3IE1hcDxCcmFja2V0Um91bmRUeXBlLCBCcmFja2V0Um91bmQ8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT5bXT4oKTtcblxuICBmb3IgKGNvbnN0IHJvdW5kIG9mIGJyYWNrZXREYXRhLnJvdW5kcy52YWx1ZXMoKSkge1xuICAgIGlmICghc29ydGVkUm91bmRzQnlUeXBlLmhhcyhyb3VuZC50eXBlKSkge1xuICAgICAgc29ydGVkUm91bmRzQnlUeXBlLnNldChyb3VuZC50eXBlLCBbcm91bmRdKTtcbiAgICB9IGVsc2Uge1xuICAgICAgc29ydGVkUm91bmRzQnlUeXBlLmdldChyb3VuZC50eXBlKT8ucHVzaChyb3VuZCk7XG4gICAgfVxuICB9XG5cbiAgZm9yIChjb25zdCByb3VuZHMgb2Ygc29ydGVkUm91bmRzQnlUeXBlLnZhbHVlcygpKSB7XG4gICAgaWYgKHJvdW5kcy5sZW5ndGggPT09IDEpIGNvbnRpbnVlO1xuXG4gICAgcm91bmRzLnNvcnQoKGEsIGIpID0+IGEucG9zaXRpb24gLSBiLnBvc2l0aW9uKTtcbiAgfVxuXG4gIGNvbnN0IHNvcnRlZFVwcGVyUm91bmRzID0gVVBQRVJfTE9PUF9PUkRFUi5tYXAoKHQpID0+IHNvcnRlZFJvdW5kc0J5VHlwZS5nZXQodCkpXG4gICAgLmZpbHRlcigocikgPT4gISFyKVxuICAgIC5mbGF0KCk7XG4gIGNvbnN0IHNvcnRlZExvd2VyUm91bmRzID0gTE9XRVJfTE9PUF9PUkRFUi5tYXAoKHQpID0+IHNvcnRlZFJvdW5kc0J5VHlwZS5nZXQodCkpXG4gICAgLmZpbHRlcigocikgPT4gISFyKVxuICAgIC5mbGF0KCk7XG5cbiAgY29uc3QgZmlyc3RVcHBlclJvdW5kID0gc29ydGVkVXBwZXJSb3VuZHNbMF0gfHwgbnVsbDtcbiAgY29uc3QgZmlyc3RMb3dlclJvdW5kID0gc29ydGVkTG93ZXJSb3VuZHNbMF0gfHwgbnVsbDtcblxuICBpZiAoIWZpcnN0VXBwZXJSb3VuZCkgdGhyb3cgbmV3IEVycm9yKCdmaXJzdFVwcGVyUm91bmQgaXMgbnVsbCcpO1xuXG4gIGNvbnN0IGhhc0xvd2VyUm91bmRzID0gc29ydGVkTG93ZXJSb3VuZHMubGVuZ3RoID4gMDtcbiAgY29uc3QgbGFzdExvd2VyUm91bmQgPSBzb3J0ZWRMb3dlclJvdW5kc1tzb3J0ZWRMb3dlclJvdW5kcy5sZW5ndGggLSAxXSB8fCBudWxsO1xuXG4gIGZvciAoY29uc3QgW2N1cnJlbnRVcHBlclJvdW5kSW5kZXgsIGN1cnJlbnRVcHBlclJvdW5kXSBvZiBzb3J0ZWRVcHBlclJvdW5kcy5lbnRyaWVzKCkpIHtcbiAgICBjb25zdCBwcmV2aW91c1VwcGVyUm91bmQgPSBzb3J0ZWRVcHBlclJvdW5kc1tjdXJyZW50VXBwZXJSb3VuZEluZGV4IC0gMV0gfHwgbnVsbDtcbiAgICBjb25zdCBuZXh0VXBwZXJSb3VuZCA9IHNvcnRlZFVwcGVyUm91bmRzW2N1cnJlbnRVcHBlclJvdW5kSW5kZXggKyAxXSB8fCBudWxsO1xuXG4gICAgY29uc3QgY3VycmVudExvd2VyUm91bmQgPSBzb3J0ZWRMb3dlclJvdW5kc1tjdXJyZW50VXBwZXJSb3VuZEluZGV4XSB8fCBudWxsO1xuICAgIGNvbnN0IHByZXZpb3VzTG93ZXJSb3VuZCA9IHNvcnRlZExvd2VyUm91bmRzW2N1cnJlbnRVcHBlclJvdW5kSW5kZXggLSAxXSB8fCBudWxsO1xuICAgIGNvbnN0IG5leHRMb3dlclJvdW5kID0gc29ydGVkTG93ZXJSb3VuZHNbY3VycmVudFVwcGVyUm91bmRJbmRleCArIDFdIHx8IG51bGw7XG5cbiAgICBjb25zdCBpc0ZpcnN0Um91bmQgPSBjdXJyZW50VXBwZXJSb3VuZEluZGV4ID09PSAwO1xuICAgIGNvbnN0IGlzTGFzdFVwcGVyUm91bmQgPSBjdXJyZW50VXBwZXJSb3VuZEluZGV4ID09PSBzb3J0ZWRVcHBlclJvdW5kcy5sZW5ndGggLSAxO1xuXG4gICAgY29uc3QgaXNGaW5hbCA9IGN1cnJlbnRVcHBlclJvdW5kLnR5cGUgPT09IENPTU1PTl9CUkFDS0VUX1JPVU5EX1RZUEUuRklOQUw7XG5cbiAgICBpZiAoaXNGaW5hbCAmJiBoYXNMb3dlclJvdW5kcykge1xuICAgICAgLy8gdHdvIHRvIG9uZSByZWxhdGlvblxuXG4gICAgICBpZiAoIWxhc3RMb3dlclJvdW5kIHx8ICFjdXJyZW50TG93ZXJSb3VuZCB8fCAhcHJldmlvdXNVcHBlclJvdW5kKVxuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ2xhc3RMb3dlclJvdW5kIG9yIGN1cnJlbnRMb3dlclJvdW5kIG9yIHByZXZpb3VzVXBwZXJSb3VuZCBpcyBudWxsJyk7XG5cbiAgICAgIC8vIGluIGEgc3luYyBkb3VibGUgZWxpbWluYXRpb24gYnJhY2tldCwgdGhlIGZpbmFsIHJvdW5kIGhhcyB0aGUgc2FtZSBpbmRleCBhcyB0aGUgbGFzdCBsb3dlciByb3VuZFxuICAgICAgLy8gaW4gYW4gYXN5bmMgb25lLCB0aGVyZSBpcyBhbHdheXMgb25lIG1vcmUgcm91bmQgaW4gdGhlIGxvd2VyIGJyYWNrZXQgc2luY2Ugd2Ugb25seSBkaXNwbGF5IGEgc2VjdGlvbiBvZiB0aGUgd2hvbGUgdG91cm5hbWVudFxuICAgICAgY29uc3QgaXNBc3luY0JyYWNrZXQgPSBjdXJyZW50TG93ZXJSb3VuZC5pZCAhPT0gbGFzdExvd2VyUm91bmQuaWQ7XG4gICAgICBjb25zdCBmaW5hbExvd2VyUm91bmQgPSBpc0FzeW5jQnJhY2tldCA/IG5leHRMb3dlclJvdW5kIDogY3VycmVudExvd2VyUm91bmQ7XG5cbiAgICAgIGlmICghZmluYWxMb3dlclJvdW5kKSB0aHJvdyBuZXcgRXJyb3IoJ2ZpbmFsTG93ZXJSb3VuZCBpcyBudWxsJyk7XG4gICAgICBpZiAoIWZpcnN0TG93ZXJSb3VuZCkgdGhyb3cgbmV3IEVycm9yKCdmaXJzdExvd2VyUm91bmQgaXMgbnVsbCcpO1xuXG4gICAgICBpZiAoZmluYWxMb3dlclJvdW5kLmlkICE9PSBsYXN0TG93ZXJSb3VuZC5pZCkgdGhyb3cgbmV3IEVycm9yKCdmaW5hbExvd2VyUm91bmQgaXMgbm90IHRoZSBsYXN0IGxvd2VyIHJvdW5kJyk7XG5cbiAgICAgIC8vIGlmIHdlIGhhdmUgYSByZXZlcnNlIGZpbmFsXG4gICAgICBpZiAobmV4dFVwcGVyUm91bmQpIHtcbiAgICAgICAgLy8gZm9yIHRoZSBmaW5hbFxuICAgICAgICByb3VuZFJlbGF0aW9ucy5zZXQoY3VycmVudFVwcGVyUm91bmQuaWQsIHtcbiAgICAgICAgICB0eXBlOiAndHdvLXRvLW9uZScsXG4gICAgICAgICAgcHJldmlvdXNVcHBlclJvdW5kOiBwcmV2aW91c1VwcGVyUm91bmQsXG4gICAgICAgICAgcHJldmlvdXNMb3dlclJvdW5kOiBmaW5hbExvd2VyUm91bmQsXG4gICAgICAgICAgbmV4dFJvdW5kOiBuZXh0VXBwZXJSb3VuZCxcbiAgICAgICAgICBjdXJyZW50Um91bmQ6IGN1cnJlbnRVcHBlclJvdW5kLFxuICAgICAgICAgIG5leHRSb3VuZE1hdGNoRmFjdG9yOiBuZXh0VXBwZXJSb3VuZC5tYXRjaENvdW50IC8gY3VycmVudFVwcGVyUm91bmQubWF0Y2hDb3VudCxcbiAgICAgICAgICBwcmV2aW91c1VwcGVyUm91bmRNYXRjaEZhY3RvcjogcHJldmlvdXNVcHBlclJvdW5kLm1hdGNoQ291bnQgLyBjdXJyZW50VXBwZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgICAgIHByZXZpb3VzTG93ZXJSb3VuZE1hdGNoRmFjdG9yOiBmaW5hbExvd2VyUm91bmQubWF0Y2hDb3VudCAvIGN1cnJlbnRVcHBlclJvdW5kLm1hdGNoQ291bnQsXG4gICAgICAgICAgdXBwZXJSb290Um91bmRNYXRjaEZhY3RvcjogZmlyc3RVcHBlclJvdW5kLm1hdGNoQ291bnQgLyBjdXJyZW50VXBwZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgICAgIGxvd2VyUm9vdFJvdW5kTWF0Y2hGYWN0b3I6IGZpcnN0TG93ZXJSb3VuZC5tYXRjaENvdW50IC8gY3VycmVudFVwcGVyUm91bmQubWF0Y2hDb3VudCxcbiAgICAgICAgfSk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBubyByZXZlcnNlIGZpbmFsIG1lYW5zIHRoZSBmaW5hbCBpcyB0aGUgbGFzdCByb3VuZFxuXG4gICAgICAgIC8vIGZvciB0aGUgZmluYWxcbiAgICAgICAgcm91bmRSZWxhdGlvbnMuc2V0KGN1cnJlbnRVcHBlclJvdW5kLmlkLCB7XG4gICAgICAgICAgdHlwZTogJ3R3by10by1ub3RoaW5nJyxcbiAgICAgICAgICBwcmV2aW91c1VwcGVyUm91bmQ6IHByZXZpb3VzVXBwZXJSb3VuZCxcbiAgICAgICAgICBwcmV2aW91c0xvd2VyUm91bmQ6IGZpbmFsTG93ZXJSb3VuZCxcbiAgICAgICAgICBjdXJyZW50Um91bmQ6IGN1cnJlbnRVcHBlclJvdW5kLFxuICAgICAgICAgIHByZXZpb3VzTG93ZXJSb3VuZE1hdGNoRmFjdG9yOiBmaW5hbExvd2VyUm91bmQubWF0Y2hDb3VudCAvIGN1cnJlbnRVcHBlclJvdW5kLm1hdGNoQ291bnQsXG4gICAgICAgICAgcHJldmlvdXNVcHBlclJvdW5kTWF0Y2hGYWN0b3I6IHByZXZpb3VzVXBwZXJSb3VuZC5tYXRjaENvdW50IC8gY3VycmVudFVwcGVyUm91bmQubWF0Y2hDb3VudCxcbiAgICAgICAgICBsb3dlclJvb3RSb3VuZE1hdGNoRmFjdG9yOiBmaXJzdExvd2VyUm91bmQubWF0Y2hDb3VudCAvIGN1cnJlbnRVcHBlclJvdW5kLm1hdGNoQ291bnQsXG4gICAgICAgICAgdXBwZXJSb290Um91bmRNYXRjaEZhY3RvcjogZmlyc3RVcHBlclJvdW5kLm1hdGNoQ291bnQgLyBjdXJyZW50VXBwZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgICB9KTtcbiAgICAgIH1cblxuICAgICAgaWYgKGlzQXN5bmNCcmFja2V0KSB7XG4gICAgICAgIC8vIGlmIHRoaXMgaXMgYW4gYXN5bmMgYnJhY2tldCwgd2UgbmVlZCB0byBzZXQgdGhlIHJlbGF0aW9ucyBmb3IgdGhlIDIgbGFzdCBsb3dlciByb3VuZHMgc2luY2UgdGhleSB3aWxsIGJlIHNraXBwZWQgYnkgdGhlIGRlZmF1bHQgb25lIHRvIG9uZSBsb2dpY1xuICAgICAgICBjb25zdCBwcmVGaW5hbExvd2VyUm91bmQgPSBzb3J0ZWRMb3dlclJvdW5kc1tzb3J0ZWRMb3dlclJvdW5kcy5sZW5ndGggLSAyXSB8fCBudWxsO1xuICAgICAgICBjb25zdCBwcmVQcmVGaW5hbExvd2VyUm91bmQgPSBzb3J0ZWRMb3dlclJvdW5kc1tzb3J0ZWRMb3dlclJvdW5kcy5sZW5ndGggLSAzXSB8fCBudWxsO1xuXG4gICAgICAgIGlmICghcHJlRmluYWxMb3dlclJvdW5kKSB0aHJvdyBuZXcgRXJyb3IoJ3ByZUZpbmFsTG93ZXJSb3VuZCBpcyBudWxsJyk7XG5cbiAgICAgICAgaWYgKCFmaXJzdExvd2VyUm91bmQpIHRocm93IG5ldyBFcnJvcignZmlyc3RMb3dlclJvdW5kIGlzIG51bGwnKTtcblxuICAgICAgICAvLyBmb3IgdGhlIGxhc3QgbG93ZXIgcm91bmRcbiAgICAgICAgcm91bmRSZWxhdGlvbnMuc2V0KGZpbmFsTG93ZXJSb3VuZC5pZCwge1xuICAgICAgICAgIHR5cGU6ICdvbmUtdG8tb25lJyxcbiAgICAgICAgICBwcmV2aW91c1JvdW5kOiBwcmVGaW5hbExvd2VyUm91bmQsXG4gICAgICAgICAgbmV4dFJvdW5kOiBjdXJyZW50VXBwZXJSb3VuZCxcbiAgICAgICAgICBjdXJyZW50Um91bmQ6IGZpbmFsTG93ZXJSb3VuZCxcbiAgICAgICAgICBuZXh0Um91bmRNYXRjaEZhY3RvcjogY3VycmVudFVwcGVyUm91bmQubWF0Y2hDb3VudCAvIGZpbmFsTG93ZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgICAgIHByZXZpb3VzUm91bmRNYXRjaEZhY3RvcjogcHJlRmluYWxMb3dlclJvdW5kLm1hdGNoQ291bnQgLyBmaW5hbExvd2VyUm91bmQubWF0Y2hDb3VudCxcbiAgICAgICAgICByb290Um91bmRNYXRjaEZhY3RvcjogZmlyc3RMb3dlclJvdW5kLm1hdGNoQ291bnQgLyBmaW5hbExvd2VyUm91bmQubWF0Y2hDb3VudCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHByZVByZUZpbmFsTG93ZXJSb3VuZCkge1xuICAgICAgICAgIC8vIGZvciB0aGUgcHJlIGZpbmFsIGxvd2VyIHJvdW5kXG4gICAgICAgICAgcm91bmRSZWxhdGlvbnMuc2V0KHByZUZpbmFsTG93ZXJSb3VuZC5pZCwge1xuICAgICAgICAgICAgdHlwZTogJ29uZS10by1vbmUnLFxuICAgICAgICAgICAgcHJldmlvdXNSb3VuZDogcHJlUHJlRmluYWxMb3dlclJvdW5kLFxuICAgICAgICAgICAgbmV4dFJvdW5kOiBmaW5hbExvd2VyUm91bmQsXG4gICAgICAgICAgICBjdXJyZW50Um91bmQ6IHByZUZpbmFsTG93ZXJSb3VuZCxcbiAgICAgICAgICAgIG5leHRSb3VuZE1hdGNoRmFjdG9yOiBmaW5hbExvd2VyUm91bmQubWF0Y2hDb3VudCAvIHByZUZpbmFsTG93ZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgICAgICAgcHJldmlvdXNSb3VuZE1hdGNoRmFjdG9yOiBwcmVQcmVGaW5hbExvd2VyUm91bmQubWF0Y2hDb3VudCAvIHByZUZpbmFsTG93ZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgICAgICAgcm9vdFJvdW5kTWF0Y2hGYWN0b3I6IGZpcnN0TG93ZXJSb3VuZC5tYXRjaENvdW50IC8gcHJlRmluYWxMb3dlclJvdW5kLm1hdGNoQ291bnQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gZm9yIHRoZSBmaXJzdCBsb3dlciByb3VuZFxuICAgICAgICAgIHJvdW5kUmVsYXRpb25zLnNldChwcmVGaW5hbExvd2VyUm91bmQuaWQsIHtcbiAgICAgICAgICAgIHR5cGU6ICdub3RoaW5nLXRvLW9uZScsXG4gICAgICAgICAgICBuZXh0Um91bmQ6IGZpbmFsTG93ZXJSb3VuZCxcbiAgICAgICAgICAgIGN1cnJlbnRSb3VuZDogcHJlRmluYWxMb3dlclJvdW5kLFxuICAgICAgICAgICAgbmV4dFJvdW5kTWF0Y2hGYWN0b3I6IGZpbmFsTG93ZXJSb3VuZC5tYXRjaENvdW50IC8gcHJlRmluYWxMb3dlclJvdW5kLm1hdGNoQ291bnQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIHRoaXMgaXMgYSBzeW5jIGJyYWNrZXQsIHdlIG9ubHkgbmVlZCB0byBzZXQgdGhlIHJlbGF0aW9uIGZvciB0aGUgbGFzdCBsb3dlciByb3VuZFxuICAgICAgICBpZiAoIXByZXZpb3VzTG93ZXJSb3VuZCkgdGhyb3cgbmV3IEVycm9yKCdwcmV2aW91c0xvd2VyUm91bmQgaXMgbnVsbCcpO1xuICAgICAgICBpZiAoIWZpcnN0TG93ZXJSb3VuZCkgdGhyb3cgbmV3IEVycm9yKCdmaXJzdExvd2VyUm91bmQgaXMgbnVsbCcpO1xuXG4gICAgICAgIC8vIGZvciB0aGUgbGFzdCBsb3dlciByb3VuZFxuICAgICAgICByb3VuZFJlbGF0aW9ucy5zZXQoZmluYWxMb3dlclJvdW5kLmlkLCB7XG4gICAgICAgICAgdHlwZTogJ29uZS10by1vbmUnLFxuICAgICAgICAgIHByZXZpb3VzUm91bmQ6IHByZXZpb3VzTG93ZXJSb3VuZCxcbiAgICAgICAgICBuZXh0Um91bmQ6IGN1cnJlbnRVcHBlclJvdW5kLFxuICAgICAgICAgIGN1cnJlbnRSb3VuZDogZmluYWxMb3dlclJvdW5kLFxuICAgICAgICAgIG5leHRSb3VuZE1hdGNoRmFjdG9yOiBjdXJyZW50VXBwZXJSb3VuZC5tYXRjaENvdW50IC8gZmluYWxMb3dlclJvdW5kLm1hdGNoQ291bnQsXG4gICAgICAgICAgcHJldmlvdXNSb3VuZE1hdGNoRmFjdG9yOiBwcmV2aW91c0xvd2VyUm91bmQubWF0Y2hDb3VudCAvIGZpbmFsTG93ZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgICAgIHJvb3RSb3VuZE1hdGNoRmFjdG9yOiBmaXJzdExvd2VyUm91bmQubWF0Y2hDb3VudCAvIGZpbmFsTG93ZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKGlzTGFzdFVwcGVyUm91bmQpIHtcbiAgICAgIC8vIG9uZSB0byBub3RoaW5nIHJlbGF0aW9uXG5cbiAgICAgIGlmICghcHJldmlvdXNVcHBlclJvdW5kKSB0aHJvdyBuZXcgRXJyb3IoJ3ByZXZpb3VzVXBwZXJSb3VuZCBpcyBudWxsJyk7XG5cbiAgICAgIHJvdW5kUmVsYXRpb25zLnNldChjdXJyZW50VXBwZXJSb3VuZC5pZCwge1xuICAgICAgICB0eXBlOiAnb25lLXRvLW5vdGhpbmcnLFxuICAgICAgICBwcmV2aW91c1JvdW5kOiBwcmV2aW91c1VwcGVyUm91bmQsXG4gICAgICAgIGN1cnJlbnRSb3VuZDogY3VycmVudFVwcGVyUm91bmQsXG4gICAgICAgIHByZXZpb3VzUm91bmRNYXRjaEZhY3RvcjogcHJldmlvdXNVcHBlclJvdW5kLm1hdGNoQ291bnQgLyBjdXJyZW50VXBwZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgICByb290Um91bmRNYXRjaEZhY3RvcjogZmlyc3RVcHBlclJvdW5kLm1hdGNoQ291bnQgLyBjdXJyZW50VXBwZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgfSk7XG4gICAgfSBlbHNlIGlmIChpc0ZpcnN0Um91bmQpIHtcbiAgICAgIC8vIG5vdGhpbmcgdG8gb25lIHJlbGF0aW9uXG5cbiAgICAgIGlmICghbmV4dFVwcGVyUm91bmQpIHRocm93IG5ldyBFcnJvcignbmV4dFVwcGVyUm91bmQgaXMgbnVsbCcpO1xuXG4gICAgICByb3VuZFJlbGF0aW9ucy5zZXQoY3VycmVudFVwcGVyUm91bmQuaWQsIHtcbiAgICAgICAgdHlwZTogJ25vdGhpbmctdG8tb25lJyxcbiAgICAgICAgbmV4dFJvdW5kOiBuZXh0VXBwZXJSb3VuZCxcbiAgICAgICAgY3VycmVudFJvdW5kOiBjdXJyZW50VXBwZXJSb3VuZCxcbiAgICAgICAgbmV4dFJvdW5kTWF0Y2hGYWN0b3I6IG5leHRVcHBlclJvdW5kLm1hdGNoQ291bnQgLyBjdXJyZW50VXBwZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgfSk7XG5cbiAgICAgIGlmIChjdXJyZW50TG93ZXJSb3VuZCkge1xuICAgICAgICBpZiAoIW5leHRMb3dlclJvdW5kKSB0aHJvdyBuZXcgRXJyb3IoJ25leHRMb3dlclJvdW5kIGlzIG51bGwnKTtcblxuICAgICAgICByb3VuZFJlbGF0aW9ucy5zZXQoY3VycmVudExvd2VyUm91bmQuaWQsIHtcbiAgICAgICAgICB0eXBlOiAnbm90aGluZy10by1vbmUnLFxuICAgICAgICAgIG5leHRSb3VuZDogbmV4dExvd2VyUm91bmQsXG4gICAgICAgICAgY3VycmVudFJvdW5kOiBjdXJyZW50TG93ZXJSb3VuZCxcbiAgICAgICAgICBuZXh0Um91bmRNYXRjaEZhY3RvcjogbmV4dExvd2VyUm91bmQubWF0Y2hDb3VudCAvIGN1cnJlbnRMb3dlclJvdW5kLm1hdGNoQ291bnQsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBvbmUgdG8gb25lIHJlbGF0aW9uXG5cbiAgICAgIGlmICghcHJldmlvdXNVcHBlclJvdW5kKSB0aHJvdyBuZXcgRXJyb3IoJ3ByZXZpb3VzVXBwZXJSb3VuZCBpcyBudWxsJyk7XG4gICAgICBpZiAoIW5leHRVcHBlclJvdW5kKSB0aHJvdyBuZXcgRXJyb3IoJ25leHRVcHBlclJvdW5kIGlzIG51bGwnKTtcblxuICAgICAgcm91bmRSZWxhdGlvbnMuc2V0KGN1cnJlbnRVcHBlclJvdW5kLmlkLCB7XG4gICAgICAgIHR5cGU6ICdvbmUtdG8tb25lJyxcbiAgICAgICAgcHJldmlvdXNSb3VuZDogcHJldmlvdXNVcHBlclJvdW5kLFxuICAgICAgICBuZXh0Um91bmQ6IG5leHRVcHBlclJvdW5kLFxuICAgICAgICBjdXJyZW50Um91bmQ6IGN1cnJlbnRVcHBlclJvdW5kLFxuICAgICAgICBuZXh0Um91bmRNYXRjaEZhY3RvcjogbmV4dFVwcGVyUm91bmQubWF0Y2hDb3VudCAvIGN1cnJlbnRVcHBlclJvdW5kLm1hdGNoQ291bnQsXG4gICAgICAgIHByZXZpb3VzUm91bmRNYXRjaEZhY3RvcjogcHJldmlvdXNVcHBlclJvdW5kLm1hdGNoQ291bnQgLyBjdXJyZW50VXBwZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgICByb290Um91bmRNYXRjaEZhY3RvcjogZmlyc3RVcHBlclJvdW5kLm1hdGNoQ291bnQgLyBjdXJyZW50VXBwZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgfSk7XG5cbiAgICAgIC8vIHdlIG9ubHkgd2FudCB0byBzZXQgbG93ZXIgcm91bmRzIGhlcmUgdW50aWwgdGhlIHNwZWNpYWwgbWVyZ2luZyBwb2ludCBvZiB0aGUgZmluYWwuXG4gICAgICAvLyBsb3dlciBicmFja2V0IHJvdW5kcyBhZnRlciBhbmQgaW5jbHVkaW5nIHRoZSBmaW5hbCB3aWxsIGJlIHNldCBpbiB0aGUgZmluYWwgcm91bmQgYmxvY2tcbiAgICAgIGlmIChjdXJyZW50TG93ZXJSb3VuZCAmJiBjdXJyZW50VXBwZXJSb3VuZC50eXBlID09PSBET1VCTEVfRUxJTUlOQVRJT05fQlJBQ0tFVF9ST1VORF9UWVBFLlVQUEVSX0JSQUNLRVQpIHtcbiAgICAgICAgaWYgKCFwcmV2aW91c0xvd2VyUm91bmQpIHRocm93IG5ldyBFcnJvcigncHJldmlvdXNMb3dlclJvdW5kIGlzIG51bGwnKTtcbiAgICAgICAgaWYgKCFuZXh0TG93ZXJSb3VuZCkgdGhyb3cgbmV3IEVycm9yKCduZXh0TG93ZXJSb3VuZCBpcyBudWxsJyk7XG4gICAgICAgIGlmICghZmlyc3RMb3dlclJvdW5kKSB0aHJvdyBuZXcgRXJyb3IoJ2ZpcnN0TG93ZXJSb3VuZCBpcyBudWxsJyk7XG5cbiAgICAgICAgcm91bmRSZWxhdGlvbnMuc2V0KGN1cnJlbnRMb3dlclJvdW5kLmlkLCB7XG4gICAgICAgICAgdHlwZTogJ29uZS10by1vbmUnLFxuICAgICAgICAgIHByZXZpb3VzUm91bmQ6IHByZXZpb3VzTG93ZXJSb3VuZCxcbiAgICAgICAgICBuZXh0Um91bmQ6IG5leHRMb3dlclJvdW5kLFxuICAgICAgICAgIGN1cnJlbnRSb3VuZDogY3VycmVudExvd2VyUm91bmQsXG4gICAgICAgICAgbmV4dFJvdW5kTWF0Y2hGYWN0b3I6IG5leHRMb3dlclJvdW5kLm1hdGNoQ291bnQgLyBjdXJyZW50TG93ZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgICAgIHByZXZpb3VzUm91bmRNYXRjaEZhY3RvcjogcHJldmlvdXNMb3dlclJvdW5kLm1hdGNoQ291bnQgLyBjdXJyZW50TG93ZXJSb3VuZC5tYXRjaENvdW50LFxuICAgICAgICAgIHJvb3RSb3VuZE1hdGNoRmFjdG9yOiBmaXJzdExvd2VyUm91bmQubWF0Y2hDb3VudCAvIGN1cnJlbnRMb3dlclJvdW5kLm1hdGNoQ291bnQsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiByb3VuZFJlbGF0aW9ucztcbn07XG5cbmV4cG9ydCBjb25zdCBnZW5lcmF0ZU1hdGNoUmVsYXRpb25zID0gPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+KFxuICBicmFja2V0RGF0YTogQnJhY2tldERhdGE8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4sXG4gIHJvdW5kUmVsYXRpb25zOiBCcmFja2V0Um91bmRSZWxhdGlvbnM8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4sXG4gIG1hdGNoUG9zaXRpb25NYXBzOiBNYXRjaFBvc2l0aW9uTWFwczxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPixcbikgPT4ge1xuICBjb25zdCBtYXRjaFJlbGF0aW9uczogQnJhY2tldE1hdGNoUmVsYXRpb25zTWFwPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0gbmV3IE1hcCgpO1xuXG4gIGZvciAoY29uc3QgbWF0Y2ggb2YgYnJhY2tldERhdGEubWF0Y2hlcy52YWx1ZXMoKSkge1xuICAgIGNvbnN0IGN1cnJlbnRSZWxhdGlvbiA9IHJvdW5kUmVsYXRpb25zLmdldChtYXRjaC5yb3VuZC5pZCk7XG5cbiAgICBpZiAoIWN1cnJlbnRSZWxhdGlvbikgdGhyb3cgbmV3IEVycm9yKCdNYXRjaCByb3VuZCBub3QgZm91bmQnKTtcblxuICAgIGNvbnN0IHsgbmV4dFJvdW5kTWF0Y2hQb3NpdGlvbiwgcHJldmlvdXNMb3dlclJvdW5kTWF0Y2hQb3NpdGlvbiwgcHJldmlvdXNVcHBlclJvdW5kTWF0Y2hQb3NpdGlvbiB9ID1cbiAgICAgIGdlbmVyYXRlTWF0Y2hSZWxhdGlvblBvc2l0aW9ucyhjdXJyZW50UmVsYXRpb24sIG1hdGNoKTtcblxuICAgIHN3aXRjaCAoY3VycmVudFJlbGF0aW9uLnR5cGUpIHtcbiAgICAgIGNhc2UgJ25vdGhpbmctdG8tb25lJzoge1xuICAgICAgICBjb25zdCBuZXh0TWF0Y2ggPSBtYXRjaFBvc2l0aW9uTWFwcy5nZXQoY3VycmVudFJlbGF0aW9uLm5leHRSb3VuZC5pZCk/LmdldChuZXh0Um91bmRNYXRjaFBvc2l0aW9uKTtcblxuICAgICAgICBpZiAoIW5leHRNYXRjaCkgdGhyb3cgbmV3IEVycm9yKCdOZXh0IHJvdW5kIG1hdGNoIG5vdCBmb3VuZCcpO1xuXG4gICAgICAgIC8vIG1lYW5zIGxlZnQgaXMgbm90aGluZy4gcmlnaHQgaXMgb25lXG4gICAgICAgIG1hdGNoUmVsYXRpb25zLnNldChtYXRjaC5pZCwge1xuICAgICAgICAgIHR5cGU6ICdub3RoaW5nLXRvLW9uZScsXG4gICAgICAgICAgY3VycmVudE1hdGNoOiBtYXRjaCxcbiAgICAgICAgICBjdXJyZW50Um91bmQ6IGN1cnJlbnRSZWxhdGlvbi5jdXJyZW50Um91bmQsXG4gICAgICAgICAgbmV4dFJvdW5kOiBjdXJyZW50UmVsYXRpb24ubmV4dFJvdW5kLFxuICAgICAgICAgIG5leHRNYXRjaCxcbiAgICAgICAgfSk7XG5cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICBjYXNlICdvbmUtdG8tbm90aGluZyc6IHtcbiAgICAgICAgY29uc3QgcHJldmlvdXNVcHBlck1hdGNoID0gbWF0Y2hQb3NpdGlvbk1hcHNcbiAgICAgICAgICAuZ2V0KGN1cnJlbnRSZWxhdGlvbi5wcmV2aW91c1JvdW5kLmlkKVxuICAgICAgICAgID8uZ2V0KHByZXZpb3VzVXBwZXJSb3VuZE1hdGNoUG9zaXRpb24pO1xuICAgICAgICBjb25zdCBwcmV2aW91c0xvd2VyTWF0Y2ggPSBtYXRjaFBvc2l0aW9uTWFwc1xuICAgICAgICAgIC5nZXQoY3VycmVudFJlbGF0aW9uLnByZXZpb3VzUm91bmQuaWQpXG4gICAgICAgICAgPy5nZXQocHJldmlvdXNMb3dlclJvdW5kTWF0Y2hQb3NpdGlvbik7XG5cbiAgICAgICAgaWYgKCFwcmV2aW91c1VwcGVyTWF0Y2gpIHRocm93IG5ldyBFcnJvcignUHJldmlvdXMgcm91bmQgbWF0Y2ggbm90IGZvdW5kJyk7XG5cbiAgICAgICAgaWYgKHByZXZpb3VzVXBwZXJSb3VuZE1hdGNoUG9zaXRpb24gIT09IHByZXZpb3VzTG93ZXJSb3VuZE1hdGNoUG9zaXRpb24pIHtcbiAgICAgICAgICAvLyBtZWFucyBsZWZ0IGlzIHR3by4gcmlnaHQgaXMgb25lXG5cbiAgICAgICAgICBpZiAoIXByZXZpb3VzTG93ZXJNYXRjaCkgdGhyb3cgbmV3IEVycm9yKCdQcmV2aW91cyBsb3dlciByb3VuZCBtYXRjaCBub3QgZm91bmQnKTtcblxuICAgICAgICAgIG1hdGNoUmVsYXRpb25zLnNldChtYXRjaC5pZCwge1xuICAgICAgICAgICAgdHlwZTogJ3R3by10by1ub3RoaW5nJyxcbiAgICAgICAgICAgIGN1cnJlbnRNYXRjaDogbWF0Y2gsXG4gICAgICAgICAgICBjdXJyZW50Um91bmQ6IGN1cnJlbnRSZWxhdGlvbi5jdXJyZW50Um91bmQsXG4gICAgICAgICAgICBwcmV2aW91c1VwcGVyTWF0Y2gsXG4gICAgICAgICAgICBwcmV2aW91c1VwcGVyUm91bmQ6IGN1cnJlbnRSZWxhdGlvbi5wcmV2aW91c1JvdW5kLFxuICAgICAgICAgICAgcHJldmlvdXNMb3dlck1hdGNoLFxuICAgICAgICAgICAgcHJldmlvdXNMb3dlclJvdW5kOiBjdXJyZW50UmVsYXRpb24ucHJldmlvdXNSb3VuZCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyBtZWFucyBsZWZ0IGlzIG9uZS4gcmlnaHQgaXMgbm90aGluZ1xuICAgICAgICAgIG1hdGNoUmVsYXRpb25zLnNldChtYXRjaC5pZCwge1xuICAgICAgICAgICAgdHlwZTogJ29uZS10by1ub3RoaW5nJyxcbiAgICAgICAgICAgIGN1cnJlbnRNYXRjaDogbWF0Y2gsXG4gICAgICAgICAgICBjdXJyZW50Um91bmQ6IGN1cnJlbnRSZWxhdGlvbi5jdXJyZW50Um91bmQsXG4gICAgICAgICAgICBwcmV2aW91c01hdGNoOiBwcmV2aW91c1VwcGVyTWF0Y2gsXG4gICAgICAgICAgICBwcmV2aW91c1JvdW5kOiBjdXJyZW50UmVsYXRpb24ucHJldmlvdXNSb3VuZCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuXG4gICAgICBjYXNlICdvbmUtdG8tb25lJzoge1xuICAgICAgICBjb25zdCBuZXh0TWF0Y2ggPSBtYXRjaFBvc2l0aW9uTWFwcy5nZXQoY3VycmVudFJlbGF0aW9uLm5leHRSb3VuZC5pZCk/LmdldChuZXh0Um91bmRNYXRjaFBvc2l0aW9uKTtcbiAgICAgICAgY29uc3QgcHJldmlvdXNVcHBlck1hdGNoID0gbWF0Y2hQb3NpdGlvbk1hcHNcbiAgICAgICAgICAuZ2V0KGN1cnJlbnRSZWxhdGlvbi5wcmV2aW91c1JvdW5kLmlkKVxuICAgICAgICAgID8uZ2V0KHByZXZpb3VzVXBwZXJSb3VuZE1hdGNoUG9zaXRpb24pO1xuICAgICAgICBjb25zdCBwcmV2aW91c0xvd2VyTWF0Y2ggPSBtYXRjaFBvc2l0aW9uTWFwc1xuICAgICAgICAgIC5nZXQoY3VycmVudFJlbGF0aW9uLnByZXZpb3VzUm91bmQuaWQpXG4gICAgICAgICAgPy5nZXQocHJldmlvdXNMb3dlclJvdW5kTWF0Y2hQb3NpdGlvbik7XG5cbiAgICAgICAgaWYgKCFuZXh0TWF0Y2gpIHRocm93IG5ldyBFcnJvcignTmV4dCByb3VuZCBtYXRjaCBub3QgZm91bmQnKTtcbiAgICAgICAgaWYgKCFwcmV2aW91c1VwcGVyTWF0Y2gpIHRocm93IG5ldyBFcnJvcihgUHJldmlvdXMgdXBwZXIgcm91bmQgbWF0Y2ggbm90IGZvdW5kYCk7XG4gICAgICAgIGlmICghcHJldmlvdXNMb3dlck1hdGNoKSB0aHJvdyBuZXcgRXJyb3IoJ1ByZXZpb3VzIGxvd2VyIHJvdW5kIG1hdGNoIG5vdCBmb3VuZCcpO1xuXG4gICAgICAgIC8vIGNhbiBiZSBlaXRoZXIgb25lIHRvIG9uZSBvciB0d28gdG8gb25lXG4gICAgICAgIGNvbnN0IGlzTGVmdE9uZSA9IHByZXZpb3VzVXBwZXJSb3VuZE1hdGNoUG9zaXRpb24gPT09IHByZXZpb3VzTG93ZXJSb3VuZE1hdGNoUG9zaXRpb247XG5cbiAgICAgICAgaWYgKGlzTGVmdE9uZSkge1xuICAgICAgICAgIC8vIG9uZS10by1vbmVcbiAgICAgICAgICBtYXRjaFJlbGF0aW9ucy5zZXQobWF0Y2guaWQsIHtcbiAgICAgICAgICAgIHR5cGU6ICdvbmUtdG8tb25lJyxcbiAgICAgICAgICAgIGN1cnJlbnRNYXRjaDogbWF0Y2gsXG4gICAgICAgICAgICBjdXJyZW50Um91bmQ6IGN1cnJlbnRSZWxhdGlvbi5jdXJyZW50Um91bmQsXG4gICAgICAgICAgICBwcmV2aW91c01hdGNoOiBwcmV2aW91c1VwcGVyTWF0Y2gsXG4gICAgICAgICAgICBwcmV2aW91c1JvdW5kOiBjdXJyZW50UmVsYXRpb24ucHJldmlvdXNSb3VuZCxcbiAgICAgICAgICAgIG5leHRNYXRjaCxcbiAgICAgICAgICAgIG5leHRSb3VuZDogY3VycmVudFJlbGF0aW9uLm5leHRSb3VuZCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAvLyB0d28tdG8tb25lXG4gICAgICAgICAgbWF0Y2hSZWxhdGlvbnMuc2V0KG1hdGNoLmlkLCB7XG4gICAgICAgICAgICB0eXBlOiAndHdvLXRvLW9uZScsXG4gICAgICAgICAgICBjdXJyZW50TWF0Y2g6IG1hdGNoLFxuICAgICAgICAgICAgY3VycmVudFJvdW5kOiBjdXJyZW50UmVsYXRpb24uY3VycmVudFJvdW5kLFxuICAgICAgICAgICAgcHJldmlvdXNVcHBlck1hdGNoLFxuICAgICAgICAgICAgcHJldmlvdXNVcHBlclJvdW5kOiBjdXJyZW50UmVsYXRpb24ucHJldmlvdXNSb3VuZCxcbiAgICAgICAgICAgIHByZXZpb3VzTG93ZXJNYXRjaCxcbiAgICAgICAgICAgIHByZXZpb3VzTG93ZXJSb3VuZDogY3VycmVudFJlbGF0aW9uLnByZXZpb3VzUm91bmQsXG4gICAgICAgICAgICBuZXh0TWF0Y2gsXG4gICAgICAgICAgICBuZXh0Um91bmQ6IGN1cnJlbnRSZWxhdGlvbi5uZXh0Um91bmQsXG4gICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ3R3by10by1vbmUnOiB7XG4gICAgICAgIGNvbnN0IG5leHRNYXRjaCA9IG1hdGNoUG9zaXRpb25NYXBzLmdldChjdXJyZW50UmVsYXRpb24ubmV4dFJvdW5kLmlkKT8uZ2V0KG5leHRSb3VuZE1hdGNoUG9zaXRpb24pO1xuXG4gICAgICAgIGNvbnN0IHByZXZpb3VzVXBwZXJNYXRjaCA9IG1hdGNoUG9zaXRpb25NYXBzXG4gICAgICAgICAgLmdldChjdXJyZW50UmVsYXRpb24ucHJldmlvdXNVcHBlclJvdW5kLmlkKVxuICAgICAgICAgID8uZ2V0KHByZXZpb3VzVXBwZXJSb3VuZE1hdGNoUG9zaXRpb24pO1xuICAgICAgICBjb25zdCBwcmV2aW91c0xvd2VyTWF0Y2ggPSBtYXRjaFBvc2l0aW9uTWFwc1xuICAgICAgICAgIC5nZXQoY3VycmVudFJlbGF0aW9uLnByZXZpb3VzTG93ZXJSb3VuZC5pZClcbiAgICAgICAgICA/LmdldChwcmV2aW91c0xvd2VyUm91bmRNYXRjaFBvc2l0aW9uKTtcblxuICAgICAgICBpZiAoIW5leHRNYXRjaCkgdGhyb3cgbmV3IEVycm9yKCdOZXh0IHJvdW5kIG1hdGNoIG5vdCBmb3VuZCcpO1xuICAgICAgICBpZiAoIXByZXZpb3VzVXBwZXJNYXRjaCkgdGhyb3cgbmV3IEVycm9yKGBQcmV2aW91cyB1cHBlciByb3VuZCBtYXRjaCBub3QgZm91bmRgKTtcbiAgICAgICAgaWYgKCFwcmV2aW91c0xvd2VyTWF0Y2gpIHRocm93IG5ldyBFcnJvcignUHJldmlvdXMgbG93ZXIgcm91bmQgbWF0Y2ggbm90IGZvdW5kJyk7XG5cbiAgICAgICAgbWF0Y2hSZWxhdGlvbnMuc2V0KG1hdGNoLmlkLCB7XG4gICAgICAgICAgdHlwZTogJ3R3by10by1vbmUnLFxuICAgICAgICAgIGN1cnJlbnRNYXRjaDogbWF0Y2gsXG4gICAgICAgICAgY3VycmVudFJvdW5kOiBjdXJyZW50UmVsYXRpb24uY3VycmVudFJvdW5kLFxuICAgICAgICAgIHByZXZpb3VzVXBwZXJNYXRjaCxcbiAgICAgICAgICBwcmV2aW91c1VwcGVyUm91bmQ6IGN1cnJlbnRSZWxhdGlvbi5wcmV2aW91c1VwcGVyUm91bmQsXG4gICAgICAgICAgcHJldmlvdXNMb3dlck1hdGNoLFxuICAgICAgICAgIHByZXZpb3VzTG93ZXJSb3VuZDogY3VycmVudFJlbGF0aW9uLnByZXZpb3VzTG93ZXJSb3VuZCxcbiAgICAgICAgICBuZXh0TWF0Y2gsXG4gICAgICAgICAgbmV4dFJvdW5kOiBjdXJyZW50UmVsYXRpb24ubmV4dFJvdW5kLFxuICAgICAgICB9KTtcblxuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ3R3by10by1ub3RoaW5nJzoge1xuICAgICAgICBjb25zdCBwcmV2aW91c1VwcGVyTWF0Y2ggPSBtYXRjaFBvc2l0aW9uTWFwc1xuICAgICAgICAgIC5nZXQoY3VycmVudFJlbGF0aW9uLnByZXZpb3VzVXBwZXJSb3VuZC5pZClcbiAgICAgICAgICA/LmdldChwcmV2aW91c1VwcGVyUm91bmRNYXRjaFBvc2l0aW9uKTtcbiAgICAgICAgY29uc3QgcHJldmlvdXNMb3dlck1hdGNoID0gbWF0Y2hQb3NpdGlvbk1hcHNcbiAgICAgICAgICAuZ2V0KGN1cnJlbnRSZWxhdGlvbi5wcmV2aW91c1VwcGVyUm91bmQuaWQpXG4gICAgICAgICAgPy5nZXQocHJldmlvdXNMb3dlclJvdW5kTWF0Y2hQb3NpdGlvbik7XG5cbiAgICAgICAgaWYgKCFwcmV2aW91c1VwcGVyTWF0Y2gpIHRocm93IG5ldyBFcnJvcihgUHJldmlvdXMgdXBwZXIgcm91bmQgbWF0Y2ggbm90IGZvdW5kYCk7XG4gICAgICAgIGlmICghcHJldmlvdXNMb3dlck1hdGNoKSB0aHJvdyBuZXcgRXJyb3IoJ1ByZXZpb3VzIGxvd2VyIHJvdW5kIG1hdGNoIG5vdCBmb3VuZCcpO1xuXG4gICAgICAgIG1hdGNoUmVsYXRpb25zLnNldChtYXRjaC5pZCwge1xuICAgICAgICAgIHR5cGU6ICd0d28tdG8tbm90aGluZycsXG4gICAgICAgICAgY3VycmVudE1hdGNoOiBtYXRjaCxcbiAgICAgICAgICBjdXJyZW50Um91bmQ6IGN1cnJlbnRSZWxhdGlvbi5jdXJyZW50Um91bmQsXG4gICAgICAgICAgcHJldmlvdXNVcHBlck1hdGNoLFxuICAgICAgICAgIHByZXZpb3VzVXBwZXJSb3VuZDogY3VycmVudFJlbGF0aW9uLnByZXZpb3VzVXBwZXJSb3VuZCxcbiAgICAgICAgICBwcmV2aW91c0xvd2VyTWF0Y2gsXG4gICAgICAgICAgcHJldmlvdXNMb3dlclJvdW5kOiBjdXJyZW50UmVsYXRpb24ucHJldmlvdXNVcHBlclJvdW5kLFxuICAgICAgICB9KTtcblxuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICByZXR1cm4gbWF0Y2hSZWxhdGlvbnM7XG59O1xuXG5leHBvcnQgY29uc3QgZ2VuZXJhdGVNYXRjaFJlbGF0aW9uUG9zaXRpb25zID0gPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+KFxuICBjdXJyZW50UmVsYXRpb246IEJyYWNrZXRSb3VuZFJlbGF0aW9uPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+LFxuICBtYXRjaDogQnJhY2tldE1hdGNoPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+LFxuKSA9PiB7XG4gIHN3aXRjaCAoY3VycmVudFJlbGF0aW9uLnR5cGUpIHtcbiAgICBjYXNlICdub3RoaW5nLXRvLW9uZSc6IHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5leHRSb3VuZE1hdGNoUG9zaXRpb246IGdlbmVyYXRlTWF0Y2hQb3NpdGlvbihtYXRjaCwgY3VycmVudFJlbGF0aW9uLm5leHRSb3VuZE1hdGNoRmFjdG9yKSxcbiAgICAgICAgcHJldmlvdXNVcHBlclJvdW5kTWF0Y2hQb3NpdGlvbjogRkFMTEJBQ0tfTUFUQ0hfUE9TSVRJT04sXG4gICAgICAgIHByZXZpb3VzTG93ZXJSb3VuZE1hdGNoUG9zaXRpb246IEZBTExCQUNLX01BVENIX1BPU0lUSU9OLFxuICAgICAgfTtcbiAgICB9XG4gICAgY2FzZSAnb25lLXRvLW5vdGhpbmcnOiB7XG4gICAgICBjb25zdCBwcmV2aW91c1JvdW5kSGFzRG91YmxlVGhlTWF0Y2hDb3VudCA9IGN1cnJlbnRSZWxhdGlvbi5wcmV2aW91c1JvdW5kTWF0Y2hGYWN0b3IgPT09IDI7XG4gICAgICBjb25zdCBkb3VibGVVcHBlck1hdGNoQ291bnRTaGlmdCA9IHByZXZpb3VzUm91bmRIYXNEb3VibGVUaGVNYXRjaENvdW50ID8gMSA6IDA7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5leHRSb3VuZE1hdGNoUG9zaXRpb246IEZBTExCQUNLX01BVENIX1BPU0lUSU9OLFxuICAgICAgICBwcmV2aW91c1VwcGVyUm91bmRNYXRjaFBvc2l0aW9uOiAoZ2VuZXJhdGVNYXRjaFBvc2l0aW9uKG1hdGNoLCBjdXJyZW50UmVsYXRpb24ucHJldmlvdXNSb3VuZE1hdGNoRmFjdG9yKSAtXG4gICAgICAgICAgZG91YmxlVXBwZXJNYXRjaENvdW50U2hpZnQpIGFzIEJyYWNrZXRNYXRjaFBvc2l0aW9uLFxuICAgICAgICBwcmV2aW91c0xvd2VyUm91bmRNYXRjaFBvc2l0aW9uOiBnZW5lcmF0ZU1hdGNoUG9zaXRpb24obWF0Y2gsIGN1cnJlbnRSZWxhdGlvbi5wcmV2aW91c1JvdW5kTWF0Y2hGYWN0b3IpLFxuICAgICAgfTtcbiAgICB9XG4gICAgY2FzZSAnb25lLXRvLW9uZSc6IHtcbiAgICAgIGNvbnN0IHByZXZpb3VzUm91bmRIYXNEb3VibGVUaGVNYXRjaENvdW50ID0gY3VycmVudFJlbGF0aW9uLnByZXZpb3VzUm91bmRNYXRjaEZhY3RvciA9PT0gMjtcbiAgICAgIGNvbnN0IGRvdWJsZVVwcGVyTWF0Y2hDb3VudFNoaWZ0ID0gcHJldmlvdXNSb3VuZEhhc0RvdWJsZVRoZU1hdGNoQ291bnQgPyAxIDogMDtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbmV4dFJvdW5kTWF0Y2hQb3NpdGlvbjogZ2VuZXJhdGVNYXRjaFBvc2l0aW9uKG1hdGNoLCBjdXJyZW50UmVsYXRpb24ubmV4dFJvdW5kTWF0Y2hGYWN0b3IpLFxuICAgICAgICBwcmV2aW91c1VwcGVyUm91bmRNYXRjaFBvc2l0aW9uOiAoZ2VuZXJhdGVNYXRjaFBvc2l0aW9uKG1hdGNoLCBjdXJyZW50UmVsYXRpb24ucHJldmlvdXNSb3VuZE1hdGNoRmFjdG9yKSAtXG4gICAgICAgICAgZG91YmxlVXBwZXJNYXRjaENvdW50U2hpZnQpIGFzIEJyYWNrZXRNYXRjaFBvc2l0aW9uLFxuICAgICAgICBwcmV2aW91c0xvd2VyUm91bmRNYXRjaFBvc2l0aW9uOiBnZW5lcmF0ZU1hdGNoUG9zaXRpb24obWF0Y2gsIGN1cnJlbnRSZWxhdGlvbi5wcmV2aW91c1JvdW5kTWF0Y2hGYWN0b3IpLFxuICAgICAgfTtcbiAgICB9XG4gICAgY2FzZSAndHdvLXRvLW9uZSc6IHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5leHRSb3VuZE1hdGNoUG9zaXRpb246IGdlbmVyYXRlTWF0Y2hQb3NpdGlvbihtYXRjaCwgY3VycmVudFJlbGF0aW9uLm5leHRSb3VuZE1hdGNoRmFjdG9yKSxcbiAgICAgICAgcHJldmlvdXNVcHBlclJvdW5kTWF0Y2hQb3NpdGlvbjogZ2VuZXJhdGVNYXRjaFBvc2l0aW9uKG1hdGNoLCBjdXJyZW50UmVsYXRpb24ucHJldmlvdXNVcHBlclJvdW5kTWF0Y2hGYWN0b3IpLFxuICAgICAgICBwcmV2aW91c0xvd2VyUm91bmRNYXRjaFBvc2l0aW9uOiBnZW5lcmF0ZU1hdGNoUG9zaXRpb24obWF0Y2gsIGN1cnJlbnRSZWxhdGlvbi5wcmV2aW91c0xvd2VyUm91bmRNYXRjaEZhY3RvciksXG4gICAgICB9O1xuICAgIH1cbiAgICBjYXNlICd0d28tdG8tbm90aGluZyc6IHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5leHRSb3VuZE1hdGNoUG9zaXRpb246IEZBTExCQUNLX01BVENIX1BPU0lUSU9OLFxuICAgICAgICBwcmV2aW91c1VwcGVyUm91bmRNYXRjaFBvc2l0aW9uOiBnZW5lcmF0ZU1hdGNoUG9zaXRpb24obWF0Y2gsIGN1cnJlbnRSZWxhdGlvbi5wcmV2aW91c1VwcGVyUm91bmRNYXRjaEZhY3RvciksXG4gICAgICAgIHByZXZpb3VzTG93ZXJSb3VuZE1hdGNoUG9zaXRpb246IGdlbmVyYXRlTWF0Y2hQb3NpdGlvbihtYXRjaCwgY3VycmVudFJlbGF0aW9uLnByZXZpb3VzTG93ZXJSb3VuZE1hdGNoRmFjdG9yKSxcbiAgICAgIH07XG4gICAgfVxuICB9XG59O1xuXG5leHBvcnQgY29uc3QgZ2VuZXJhdGVNYXRjaFBvc2l0aW9uID0gKG1hdGNoOiBCcmFja2V0TWF0Y2g8dW5rbm93biwgdW5rbm93bj4sIGZhY3RvcjogTWF0Y2hGYWN0b3IpID0+IHtcbiAgcmV0dXJuIE1hdGguY2VpbChtYXRjaC5wb3NpdGlvbiAqIGZhY3RvcikgYXMgQnJhY2tldE1hdGNoUG9zaXRpb247XG59O1xuXG5leHBvcnQgY29uc3QgbG9nUm91bmRSZWxhdGlvbnMgPSAoXG4gIHJvdW5kUmVsYXRpb25zOiBCcmFja2V0Um91bmRSZWxhdGlvbnM8dW5rbm93biwgdW5rbm93bj4sXG4gIGJyYWNrZXREYXRhOiBCcmFja2V0RGF0YTx1bmtub3duLCB1bmtub3duPixcbikgPT4ge1xuICBmb3IgKGNvbnN0IFtyb3VuZElkLCByZWxhdGlvbl0gb2Ygcm91bmRSZWxhdGlvbnMuZW50cmllcygpKSB7XG4gICAgY29uc3Qgcm91bmQgPSBicmFja2V0RGF0YS5yb3VuZHMuZ2V0KHJvdW5kSWQpO1xuXG4gICAgaWYgKCFyb3VuZCkge1xuICAgICAgY29uc29sZS5lcnJvcihgUm91bmQgd2l0aCBpZCAke3JvdW5kSWR9IG5vdCBmb3VuZCBpbiBicmFja2V0IGRhdGEuIFRoZSBicmFja2V0IHdpbGwgYmUgbWFsZm9ybWVkLmApO1xuICAgICAgY29udGludWU7XG4gICAgfVxuXG4gICAgc3dpdGNoIChyZWxhdGlvbi50eXBlKSB7XG4gICAgICBjYXNlICdub3RoaW5nLXRvLW9uZSc6XG4gICAgICAgIGNvbnNvbGUubG9nKGBTVEFSVDogJHtyb3VuZC5uYW1lfSAtPiAke3JlbGF0aW9uLm5leHRSb3VuZC5uYW1lfSAoRjogJHtyZWxhdGlvbi5uZXh0Um91bmRNYXRjaEZhY3Rvcn0pYCk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnb25lLXRvLW5vdGhpbmcnOlxuICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICBgJHtyZWxhdGlvbi5wcmV2aW91c1JvdW5kLm5hbWV9IChGOiAke3JlbGF0aW9uLnByZXZpb3VzUm91bmRNYXRjaEZhY3Rvcn0pIDwtIEVORElORzogJHtyb3VuZC5uYW1lfWAsXG4gICAgICAgICk7XG4gICAgICAgIGJyZWFrO1xuICAgICAgY2FzZSAnb25lLXRvLW9uZSc6XG4gICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgIGAke3JlbGF0aW9uLnByZXZpb3VzUm91bmQubmFtZX0gKEY6ICR7cmVsYXRpb24ucHJldmlvdXNSb3VuZE1hdGNoRmFjdG9yfSkgPC0gJHtyb3VuZC5uYW1lfSAtPiAke3JlbGF0aW9uLm5leHRSb3VuZC5uYW1lfSAoRjogJHtyZWxhdGlvbi5uZXh0Um91bmRNYXRjaEZhY3Rvcn0pYCxcbiAgICAgICAgKTtcbiAgICAgICAgYnJlYWs7XG4gICAgICBjYXNlICd0d28tdG8tb25lJzpcbiAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgYE1FUkdFUjogJHtyZWxhdGlvbi5wcmV2aW91c1VwcGVyUm91bmQubmFtZX0gKEY6ICR7cmVsYXRpb24ucHJldmlvdXNVcHBlclJvdW5kTWF0Y2hGYWN0b3J9KSBBTkQgJHtyZWxhdGlvbi5wcmV2aW91c0xvd2VyUm91bmQubmFtZX0gKEY6ICR7cmVsYXRpb24ucHJldmlvdXNMb3dlclJvdW5kTWF0Y2hGYWN0b3J9KSA8LSAke3JvdW5kLm5hbWV9IC0+ICR7cmVsYXRpb24ubmV4dFJvdW5kLm5hbWV9IChGOiAke3JlbGF0aW9uLm5leHRSb3VuZE1hdGNoRmFjdG9yfSlgLFxuICAgICAgICApO1xuICAgICAgICBicmVhaztcbiAgICAgIGNhc2UgJ3R3by10by1ub3RoaW5nJzpcbiAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgYE1FUkdFUjogJHtyZWxhdGlvbi5wcmV2aW91c1VwcGVyUm91bmQubmFtZX0gKEY6ICR7cmVsYXRpb24ucHJldmlvdXNVcHBlclJvdW5kTWF0Y2hGYWN0b3J9KSBBTkQgJHtyZWxhdGlvbi5wcmV2aW91c0xvd2VyUm91bmQubmFtZX0gKEY6ICR7cmVsYXRpb24ucHJldmlvdXNMb3dlclJvdW5kTWF0Y2hGYWN0b3J9KSA8LSBFTkRJTkc6ICR7cm91bmQubmFtZX1gLFxuICAgICAgICApO1xuICAgICAgICBicmVhaztcbiAgICB9XG4gIH1cbn07XG5cbmV4cG9ydCBjb25zdCBnZW5lcmF0ZU1hdGNoUGFydGljaXBhbnRNYXAgPSA8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4oXG4gIGJyYWNrZXREYXRhOiBCcmFja2V0RGF0YTxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPixcbikgPT4ge1xuICBjb25zdCBtYXRjaFBhcnRpY2lwYW50TWFwOiBNYXRjaFBhcnRpY2lwYW50TWFwPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0gbmV3IE1hcCgpO1xuXG4gIGNvbnN0IGhhc0VsaW1pbmF0aW9uID1cbiAgICBicmFja2V0RGF0YS5tb2RlID09PSBUT1VSTkFNRU5UX01PREUuU0lOR0xFX0VMSU1JTkFUSU9OIHx8XG4gICAgYnJhY2tldERhdGEubW9kZSA9PT0gVE9VUk5BTUVOVF9NT0RFLkRPVUJMRV9FTElNSU5BVElPTiB8fFxuICAgIGJyYWNrZXREYXRhLm1vZGUgPT09IFRPVVJOQU1FTlRfTU9ERS5TV0lTU19XSVRIX0VMSU1JTkFUSU9OO1xuXG4gIGZvciAoY29uc3QgcGFydGljaXBhbnQgb2YgYnJhY2tldERhdGEucGFydGljaXBhbnRzLnZhbHVlcygpKSB7XG4gICAgbGV0IHdpbnNUaWxOb3cgPSAwO1xuICAgIGxldCBsb3NzZXNUaWxOb3cgPSAwO1xuICAgIGxldCB0aWVzVGlsTm93ID0gMDtcblxuICAgIGZvciAoY29uc3QgbWF0Y2hQYXJ0aWNpcGFudE1hdGNoIG9mIHBhcnRpY2lwYW50Lm1hdGNoZXMudmFsdWVzKCkpIHtcbiAgICAgIGNvbnN0IGlzV2lubmVyID0gbWF0Y2hQYXJ0aWNpcGFudE1hdGNoLmJyYWNrZXRNYXRjaC53aW5uZXIgPT09IG1hdGNoUGFydGljaXBhbnRNYXRjaC5zaWRlO1xuICAgICAgY29uc3QgaXNMb29zZXIgPVxuICAgICAgICBtYXRjaFBhcnRpY2lwYW50TWF0Y2guYnJhY2tldE1hdGNoLndpbm5lciAmJlxuICAgICAgICBtYXRjaFBhcnRpY2lwYW50TWF0Y2guYnJhY2tldE1hdGNoLndpbm5lciAhPT0gbWF0Y2hQYXJ0aWNpcGFudE1hdGNoLnNpZGU7XG4gICAgICBjb25zdCBpc1RpZSA9XG4gICAgICAgIG1hdGNoUGFydGljaXBhbnRNYXRjaC5icmFja2V0TWF0Y2guc3RhdHVzID09PSAnY29tcGxldGVkJyAmJiAhbWF0Y2hQYXJ0aWNpcGFudE1hdGNoLmJyYWNrZXRNYXRjaC53aW5uZXI7XG5cbiAgICAgIGlmIChpc1dpbm5lcikge1xuICAgICAgICB3aW5zVGlsTm93Kys7XG4gICAgICB9IGVsc2UgaWYgKGlzTG9vc2VyKSB7XG4gICAgICAgIGxvc3Nlc1RpbE5vdysrO1xuICAgICAgfSBlbHNlIGlmIChpc1RpZSkge1xuICAgICAgICB0aWVzVGlsTm93Kys7XG4gICAgICB9XG5cbiAgICAgIGxldCBpc0VsaW1pbmF0ZWQgPSBmYWxzZTtcbiAgICAgIGxldCBpc0VsaW1pbmF0aW9uTWF0Y2ggPSBmYWxzZTtcblxuICAgICAgaWYgKGhhc0VsaW1pbmF0aW9uKSB7XG4gICAgICAgIC8vIFRPRE86IEltcGxlbWVudCBlbGltaW5hdGlvbiBsb2dpY1xuXG4gICAgICAgIC8vIE1lYW5zIHRoZSBjdXJyZW50IG1hdGNoIGlzIGxvc3MgYW5kIGl0J3MgdGhlIGxhc3QgbWF0Y2ggb2YgdGhlIHBhcnRpY2lwYW50XG4gICAgICAgIGlzRWxpbWluYXRlZCA9IGZhbHNlO1xuXG4gICAgICAgIC8vIEFsd2F5cyB0cnVlIGZvciBzaW5nbGUgZWxpbWluYXRpb24sIG5ldmVyIGZvciBlLmcuIGdyb3VwcywgZGVwZW5kcyBvbiB0aGUgcm91bmQgZm9yIGRvdWJsZSBlbGltaW5hdGlvbiwgZGVwZW5kcyBvbiB0aGUgbG9zcyBjb3VudCBmb3Igc3dpc3Mgd2l0aCBlbGltaW5hdGlvblxuICAgICAgICBpc0VsaW1pbmF0aW9uTWF0Y2ggPSBmYWxzZTtcbiAgICAgIH1cblxuICAgICAgLy8gVE9ETzogSW1wbGVtZW50IHJvdW5kIGxvZ2ljXG4gICAgICAvLyB0cnVlIGlmIGl0cyB0aGUgZmlyc3Qgcm91bmQgb2YgdGhlIGJyYWNrZXRcbiAgICAgIGNvbnN0IGlzRmlyc3RSb3VuZCA9IGZhbHNlO1xuXG4gICAgICAvLyB0cnVlIGlmIGl0cyB0aGUgbGFzdCByb3VuZCBvZiB0aGUgYnJhY2tldCAoZWcuIGZpbmFsIGZvciBzaW5nbGUgZWxpbWluYXRpb24pXG4gICAgICBjb25zdCBpc0xhc3RSb3VuZCA9IGZhbHNlO1xuXG4gICAgICBjb25zdCBwYXJ0aWNpcGFudE1hdGNoRGF0YTogTWF0Y2hQYXJ0aWNpcGFudE1hdGNoPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+ID0ge1xuICAgICAgICBicmFja2V0TWF0Y2g6IG1hdGNoUGFydGljaXBhbnRNYXRjaC5icmFja2V0TWF0Y2gsXG4gICAgICAgIHJlc3VsdDogaXNXaW5uZXIgPyAnd2luJyA6IGlzTG9vc2VyID8gJ2xvc3MnIDogaXNUaWUgPyAndGllJyA6IG51bGwsXG4gICAgICAgIGlzRWxpbWluYXRlZCxcbiAgICAgICAgaXNFbGltaW5hdGlvbk1hdGNoLFxuICAgICAgICBpc0ZpcnN0Um91bmQsXG4gICAgICAgIGlzTGFzdFJvdW5kLFxuICAgICAgICB0aWVDb3VudDogdGllc1RpbE5vdyxcbiAgICAgICAgd2luQ291bnQ6IHdpbnNUaWxOb3csXG4gICAgICAgIGxvc3NDb3VudDogbG9zc2VzVGlsTm93LFxuICAgICAgfTtcblxuICAgICAgaWYgKCFtYXRjaFBhcnRpY2lwYW50TWFwLmhhcyhwYXJ0aWNpcGFudC5pZCkpIHtcbiAgICAgICAgbWF0Y2hQYXJ0aWNpcGFudE1hcC5zZXQocGFydGljaXBhbnQuaWQsIHtcbiAgICAgICAgICBpZDogcGFydGljaXBhbnQuaWQsXG4gICAgICAgICAgbmFtZTogcGFydGljaXBhbnQubmFtZSxcbiAgICAgICAgICBtYXRjaGVzOiBuZXcgTWFwKCksXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBwYXJ0aWNpcGFudERhdGEgPSBtYXRjaFBhcnRpY2lwYW50TWFwLmdldChwYXJ0aWNpcGFudC5pZCkgYXMgTWF0Y2hQYXJ0aWNpcGFudDxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPjtcbiAgICAgIHBhcnRpY2lwYW50RGF0YS5tYXRjaGVzLnNldChtYXRjaFBhcnRpY2lwYW50TWF0Y2guYnJhY2tldE1hdGNoLmlkLCBwYXJ0aWNpcGFudE1hdGNoRGF0YSk7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIG1hdGNoUGFydGljaXBhbnRNYXA7XG59O1xuXG5jb25zdCBmYWN0b3JpYWxDYWNoZSA9IG5ldyBNYXA8bnVtYmVyLCBudW1iZXI+KCk7XG5cbmV4cG9ydCBjb25zdCBnZXRBdmFpbGFibGVTd2lzc0dyb3Vwc0ZvclJvdW5kID0gKHJvdW5kTnVtYmVyOiBudW1iZXIsIHRvdGFsTWF0Y2hlc0luUm91bmQ6IG51bWJlcikgPT4ge1xuICBjb25zdCBBRFZBTkNFX1dJTlMgPSAzO1xuICBjb25zdCBFTElNSU5BVEVfTE9TU0VTID0gMztcblxuICAvLyBDYWNoZSBmYWN0b3JpYWwgY2FsY3VsYXRpb25zXG4gIGNvbnN0IGdldEZhY3RvcmlhbCA9IChuOiBudW1iZXIpOiBudW1iZXIgPT4ge1xuICAgIGlmIChuIDw9IDEpIHJldHVybiAxO1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tbm9uLW51bGwtYXNzZXJ0aW9uXG4gICAgaWYgKGZhY3RvcmlhbENhY2hlLmhhcyhuKSkgcmV0dXJuIGZhY3RvcmlhbENhY2hlLmdldChuKSE7XG5cbiAgICBjb25zdCByZXN1bHQgPSBuICogZ2V0RmFjdG9yaWFsKG4gLSAxKTtcbiAgICBmYWN0b3JpYWxDYWNoZS5zZXQobiwgcmVzdWx0KTtcbiAgICByZXR1cm4gcmVzdWx0O1xuICB9O1xuXG4gIC8vIFByZS1jYWxjdWxhdGUgcm91bmRGYWN0b3JpYWxcbiAgY29uc3Qgcm91bmRGYWN0ID0gZ2V0RmFjdG9yaWFsKHJvdW5kTnVtYmVyKTtcblxuICBsZXQgdG90YWxDb21iaW5hdGlvbnMgPSAwO1xuICBjb25zdCB2YWxpZEdyb3VwczogeyB3aW5zOiBudW1iZXI7IGxvc3NlczogbnVtYmVyOyBjb21iaW5hdGlvbnM6IG51bWJlciB9W10gPSBbXTtcblxuICAvLyBTaW5nbGUgbG9vcCB0byBnYXRoZXIgdmFsaWQgZ3JvdXBzIGFuZCB0b3RhbCBjb21iaW5hdGlvbnNcbiAgZm9yIChsZXQgd2lucyA9IHJvdW5kTnVtYmVyOyB3aW5zID49IDA7IHdpbnMtLSkge1xuICAgIGNvbnN0IGxvc3NlcyA9IHJvdW5kTnVtYmVyIC0gd2lucztcbiAgICBjb25zdCByZW1haW5pbmdHYW1lcyA9IEFEVkFOQ0VfV0lOUyArIEVMSU1JTkFURV9MT1NTRVMgLSAod2lucyArIGxvc3NlcykgLSAxO1xuICAgIGNvbnN0IG5vdFlldEVsaW1pbmF0ZWQgPSBsb3NzZXMgPCBFTElNSU5BVEVfTE9TU0VTO1xuICAgIGNvbnN0IGNhblN0aWxsQWR2YW5jZSA9IHdpbnMgPCBBRFZBTkNFX1dJTlMgJiYgcmVtYWluaW5nR2FtZXMgPj0gMDtcblxuICAgIGlmICghY2FuU3RpbGxBZHZhbmNlIHx8ICFub3RZZXRFbGltaW5hdGVkKSBjb250aW51ZTtcblxuICAgIGNvbnN0IGNvbWJpbmF0aW9ucyA9IHJvdW5kRmFjdCAvIChnZXRGYWN0b3JpYWwod2lucykgKiBnZXRGYWN0b3JpYWwobG9zc2VzKSk7XG4gICAgdG90YWxDb21iaW5hdGlvbnMgKz0gY29tYmluYXRpb25zO1xuICAgIHZhbGlkR3JvdXBzLnB1c2goeyB3aW5zLCBsb3NzZXMsIGNvbWJpbmF0aW9ucyB9KTtcbiAgfVxuXG4gIC8vIENyZWF0ZSBmaW5hbCBncm91cHMgd2l0aCBjYWxjdWxhdGVkIHByb3BvcnRpb25zXG4gIHJldHVybiB2YWxpZEdyb3Vwcy5tYXAoKHsgd2lucywgbG9zc2VzLCBjb21iaW5hdGlvbnMgfSkgPT4gKHtcbiAgICBpZDogYCR7d2luc30tJHtsb3NzZXN9YCBhcyBCcmFja2V0Um91bmRTd2lzc0dyb3VwSWQsXG4gICAgbmFtZTogYCR7d2luc30tJHtsb3NzZXN9YCxcbiAgICBtYXRjaGVzSW5Hcm91cDogTWF0aC5yb3VuZCgoY29tYmluYXRpb25zIC8gdG90YWxDb21iaW5hdGlvbnMpICogdG90YWxNYXRjaGVzSW5Sb3VuZCksXG4gIH0pKTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZW5lcmF0ZUJyYWNrZXRSb3VuZFN3aXNzR3JvdXBNYXBzID0gPFRSb3VuZERhdGEsIFRNYXRjaERhdGE+KFxuICBicmFja2V0RGF0YTogQnJhY2tldERhdGE8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4sXG4gIG1hdGNoUGFydGljaXBhbnRNYXA6IE1hdGNoUGFydGljaXBhbnRNYXA8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4sXG4pID0+IHtcbiAgaWYgKGJyYWNrZXREYXRhLm1vZGUgIT09IFRPVVJOQU1FTlRfTU9ERS5TV0lTU19XSVRIX0VMSU1JTkFUSU9OKSB7XG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBjb25zdCByb3VuZHNXaXRoU3dpc3NHcm91cHM6IEJyYWNrZXRSb3VuZE1hcFdpdGhTd2lzc0RhdGE8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPSBuZXcgTWFwKCk7XG5cbiAgbGV0IHJvdW5kTnVtYmVyID0gMDtcbiAgZm9yIChjb25zdCBicmFja2V0Um91bmQgb2YgYnJhY2tldERhdGEucm91bmRzLnZhbHVlcygpKSB7XG4gICAgY29uc3QgYXZhaWxhYmxlR3JvdXBzID0gZ2V0QXZhaWxhYmxlU3dpc3NHcm91cHNGb3JSb3VuZChyb3VuZE51bWJlciwgYnJhY2tldFJvdW5kLm1hdGNoQ291bnQpO1xuXG4gICAgY29uc3Qgcm91bmRTd2lzc0RhdGE6IEJyYWNrZXRSb3VuZFN3aXNzRGF0YTxUUm91bmREYXRhLCBUTWF0Y2hEYXRhPiA9IHtcbiAgICAgIGdyb3VwczogbmV3IE1hcCgpLFxuICAgIH07XG5cbiAgICBmb3IgKGNvbnN0IGdyb3VwIG9mIGF2YWlsYWJsZUdyb3Vwcykge1xuICAgICAgY29uc3Qgc3ViR3JvdXA6IEJyYWNrZXRSb3VuZFN3aXNzR3JvdXA8VFJvdW5kRGF0YSwgVE1hdGNoRGF0YT4gPSB7XG4gICAgICAgIGlkOiBncm91cC5pZCxcbiAgICAgICAgbmFtZTogZ3JvdXAubmFtZSxcbiAgICAgICAgbWF0Y2hlczogbmV3IE1hcCgpLFxuICAgICAgICBhbGxvd2VkTWF0Y2hDb3VudDogZ3JvdXAubWF0Y2hlc0luR3JvdXAsXG4gICAgICB9O1xuXG4gICAgICByb3VuZFN3aXNzRGF0YS5ncm91cHMuc2V0KGdyb3VwLmlkLCBzdWJHcm91cCk7XG4gICAgfVxuXG4gICAgY29uc3QgZW1wdHlNYXRjaElkczogQnJhY2tldE1hdGNoSWRbXSA9IFtdO1xuXG4gICAgZm9yIChjb25zdCBtYXRjaCBvZiBicmFja2V0Um91bmQubWF0Y2hlcy52YWx1ZXMoKSkge1xuICAgICAgY29uc3QgcGFydGljaXBhbnRIb21lID0gbWF0Y2guaG9tZSA/IChtYXRjaFBhcnRpY2lwYW50TWFwLmdldChtYXRjaC5ob21lKSA/PyBudWxsKSA6IG51bGw7XG4gICAgICBjb25zdCBwYXJ0aWNpcGFudEF3YXkgPSBtYXRjaC5hd2F5ID8gKG1hdGNoUGFydGljaXBhbnRNYXAuZ2V0KG1hdGNoLmF3YXkpID8/IG51bGwpIDogbnVsbDtcblxuICAgICAgY29uc3QgYW55UGFydGljaXBhbnQgPSBwYXJ0aWNpcGFudEhvbWUgfHwgcGFydGljaXBhbnRBd2F5O1xuXG4gICAgICBpZiAoIWFueVBhcnRpY2lwYW50KSB7XG4gICAgICAgIGVtcHR5TWF0Y2hJZHMucHVzaChtYXRjaC5pZCk7XG4gICAgICAgIGNvbnRpbnVlO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBtYXRjaFBhcnRpY2lwYW50TWF0Y2ggPSBhbnlQYXJ0aWNpcGFudC5tYXRjaGVzLmdldChtYXRjaC5pZCk7XG5cbiAgICAgIGlmICghbWF0Y2hQYXJ0aWNpcGFudE1hdGNoKSB0aHJvdyBuZXcgRXJyb3IoJ01hdGNoIHBhcnRpY2lwYW50IG1hdGNoIG5vdCBmb3VuZCcpO1xuXG4gICAgICBjb25zdCB3aW5zID0gbWF0Y2hQYXJ0aWNpcGFudE1hdGNoLndpbkNvdW50O1xuICAgICAgY29uc3QgbG9zc2VzID0gbWF0Y2hQYXJ0aWNpcGFudE1hdGNoLmxvc3NDb3VudDtcblxuICAgICAgY29uc3QgZ3JvdXAgPSByb3VuZFN3aXNzRGF0YS5ncm91cHMuZ2V0KGAke3dpbnN9LSR7bG9zc2VzfWAgYXMgQnJhY2tldFJvdW5kU3dpc3NHcm91cElkKTtcblxuICAgICAgaWYgKCFncm91cCkgdGhyb3cgbmV3IEVycm9yKCdHcm91cCBub3QgZm91bmQgZm9yIG1hdGNoOiAnICsgbWF0Y2guaWQpO1xuXG4gICAgICBncm91cC5tYXRjaGVzLnNldChtYXRjaC5pZCwgbWF0Y2gpO1xuICAgIH1cblxuICAgIGZvciAoY29uc3QgZW1wdHlNYXRjaElkIG9mIGVtcHR5TWF0Y2hJZHMpIHtcbiAgICAgIGNvbnN0IG1hdGNoID0gYnJhY2tldFJvdW5kLm1hdGNoZXMuZ2V0KGVtcHR5TWF0Y2hJZCk7XG5cbiAgICAgIGlmICghbWF0Y2gpIHRocm93IG5ldyBFcnJvcignRW1wdHkgbWF0Y2ggbm90IGZvdW5kJyk7XG5cbiAgICAgIGxldCBncm91cEZvdW5kID0gZmFsc2U7XG4gICAgICBmb3IgKGNvbnN0IGdyb3VwIG9mIHJvdW5kU3dpc3NEYXRhLmdyb3Vwcy52YWx1ZXMoKSkge1xuICAgICAgICBpZiAoZ3JvdXAubWF0Y2hlcy5zaXplIDwgZ3JvdXAuYWxsb3dlZE1hdGNoQ291bnQpIHtcbiAgICAgICAgICBncm91cC5tYXRjaGVzLnNldChtYXRjaC5pZCwgbWF0Y2gpO1xuICAgICAgICAgIGdyb3VwRm91bmQgPSB0cnVlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmICghZ3JvdXBGb3VuZCkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGdyb3VwIGZvdW5kIGZvciBlbXB0eSBtYXRjaCcpO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJvdW5kTnVtYmVyKys7XG4gIH1cblxuICByZXR1cm4gcm91bmRzV2l0aFN3aXNzR3JvdXBzO1xufTtcbiJdfQ==