barsa-user-workspace 0.0.0-watch

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 (56) hide show
  1. package/README.md +24 -0
  2. package/esm2022/barsa-user-workspace.mjs +5 -0
  3. package/esm2022/lib/barsa-user-workspace.module.mjs +82 -0
  4. package/esm2022/lib/coercion/boolean-property.mjs +5 -0
  5. package/esm2022/lib/coercion/number-property.mjs +14 -0
  6. package/esm2022/lib/directives/drag-handle.mjs +29 -0
  7. package/esm2022/lib/directives/placeholder.mjs +31 -0
  8. package/esm2022/lib/directives/resize-handle.mjs +29 -0
  9. package/esm2022/lib/grid/grid.component.mjs +609 -0
  10. package/esm2022/lib/grid-item/grid-item.component.mjs +196 -0
  11. package/esm2022/lib/grid.definitions.mjs +3 -0
  12. package/esm2022/lib/grid.service.mjs +49 -0
  13. package/esm2022/lib/layout-container/layout-container.component.mjs +213 -0
  14. package/esm2022/lib/layout-grid-mapper.pipe.mjs +29 -0
  15. package/esm2022/lib/nav-container/nav-container.component.mjs +27 -0
  16. package/esm2022/lib/report-grid-layout/report-grid-layout.component.mjs +15 -0
  17. package/esm2022/lib/utils/client-rect.mjs +57 -0
  18. package/esm2022/lib/utils/grid.utils.mjs +225 -0
  19. package/esm2022/lib/utils/operators.mjs +17 -0
  20. package/esm2022/lib/utils/passive-listeners.mjs +29 -0
  21. package/esm2022/lib/utils/pointer.utils.mjs +110 -0
  22. package/esm2022/lib/utils/react-grid-layout.utils.mjs +493 -0
  23. package/esm2022/lib/utils/scroll.mjs +233 -0
  24. package/esm2022/lib/utils/transition-duration.mjs +34 -0
  25. package/esm2022/lib/utils.mjs +14 -0
  26. package/esm2022/public-api.mjs +15 -0
  27. package/esm2022/types.mjs +2 -0
  28. package/fesm2022/barsa-user-workspace.mjs +2469 -0
  29. package/fesm2022/barsa-user-workspace.mjs.map +1 -0
  30. package/index.d.ts +5 -0
  31. package/lib/barsa-user-workspace.module.d.ts +34 -0
  32. package/lib/coercion/boolean-property.d.ts +7 -0
  33. package/lib/coercion/number-property.d.ts +9 -0
  34. package/lib/directives/drag-handle.d.ts +15 -0
  35. package/lib/directives/placeholder.d.ts +17 -0
  36. package/lib/directives/resize-handle.d.ts +15 -0
  37. package/lib/grid/grid.component.d.ts +147 -0
  38. package/lib/grid-item/grid-item.component.d.ts +83 -0
  39. package/lib/grid.definitions.d.ts +61 -0
  40. package/lib/grid.service.d.ts +15 -0
  41. package/lib/layout-container/layout-container.component.d.ts +79 -0
  42. package/lib/layout-grid-mapper.pipe.d.ts +9 -0
  43. package/lib/nav-container/nav-container.component.d.ts +10 -0
  44. package/lib/report-grid-layout/report-grid-layout.component.d.ts +7 -0
  45. package/lib/utils/client-rect.d.ts +36 -0
  46. package/lib/utils/grid.utils.d.ts +45 -0
  47. package/lib/utils/operators.d.ts +6 -0
  48. package/lib/utils/passive-listeners.d.ts +12 -0
  49. package/lib/utils/pointer.utils.d.ts +29 -0
  50. package/lib/utils/react-grid-layout.utils.d.ts +177 -0
  51. package/lib/utils/scroll.d.ts +28 -0
  52. package/lib/utils/transition-duration.d.ts +6 -0
  53. package/lib/utils.d.ts +6 -0
  54. package/package.json +25 -0
  55. package/public-api.d.ts +12 -0
  56. package/types.d.ts +3 -0
@@ -0,0 +1,609 @@
1
+ import { ChangeDetectionStrategy, Component, ContentChildren, EventEmitter, Input, Output, ViewEncapsulation } from '@angular/core';
2
+ import { coerceNumberProperty } from '../coercion/number-property';
3
+ import { KtdGridItemComponent } from '../grid-item/grid-item.component';
4
+ import { combineLatest, merge, NEVER, Observable, of } from 'rxjs';
5
+ import { exhaustMap, map, startWith, switchMap, takeUntil } from 'rxjs/operators';
6
+ import { ktdGetGridItemRowHeight, ktdGridItemDragging, ktdGridItemLayoutItemAreEqual, ktdGridItemResizing } from '../utils/grid.utils';
7
+ import { compact } from '../utils/react-grid-layout.utils';
8
+ import { GRID_ITEM_GET_RENDER_DATA_TOKEN } from '../grid.definitions';
9
+ import { ktdPointerUp, ktdPointerClientX, ktdPointerClientY } from '../utils/pointer.utils';
10
+ import { getMutableClientRect } from '../utils/client-rect';
11
+ import { ktdGetScrollTotalRelativeDifference$, ktdScrollIfNearElementClientRect$ } from '../utils/scroll';
12
+ import { coerceBooleanProperty } from '../coercion/boolean-property';
13
+ import { getTransformTransitionDurationInMs } from '../utils/transition-duration';
14
+ import * as i0 from "@angular/core";
15
+ import * as i1 from "../grid.service";
16
+ function getDragResizeEventData(gridItem, layout) {
17
+ return {
18
+ layout,
19
+ layoutItem: layout.find((item) => item.id === gridItem.id),
20
+ gridItemRef: gridItem
21
+ };
22
+ }
23
+ function getColumnWidth(config, width) {
24
+ const { cols, gap } = config;
25
+ const widthExcludingGap = width - Math.max(gap * (cols - 1), 0);
26
+ return widthExcludingGap / cols;
27
+ }
28
+ function getRowHeightInPixels(config, height) {
29
+ const { rowHeight, layout, gap } = config;
30
+ return rowHeight === 'fit' ? ktdGetGridItemRowHeight(layout, height, gap) : rowHeight;
31
+ }
32
+ function layoutToRenderItems(config, width, height) {
33
+ const { layout, gap } = config;
34
+ const rowHeightInPixels = getRowHeightInPixels(config, height);
35
+ const itemWidthPerColumn = getColumnWidth(config, width);
36
+ const renderItems = {};
37
+ for (const item of layout) {
38
+ renderItems[item.id] = {
39
+ id: item.id,
40
+ top: item.y * rowHeightInPixels + gap * item.y,
41
+ left: item.x * itemWidthPerColumn + gap * item.x,
42
+ width: item.w * itemWidthPerColumn + gap * Math.max(item.w - 1, 0),
43
+ height: item.h * rowHeightInPixels + gap * Math.max(item.h - 1, 0)
44
+ };
45
+ }
46
+ return renderItems;
47
+ }
48
+ function getGridHeight(layout, rowHeight, gap) {
49
+ return layout.reduce((acc, cur) => Math.max(acc, (cur.y + cur.h) * rowHeight + Math.max(cur.y + cur.h - 1, 0) * gap), 0);
50
+ }
51
+ // eslint-disable-next-line
52
+ export function parseRenderItemToPixels(renderItem) {
53
+ return {
54
+ id: renderItem.id,
55
+ top: `${renderItem.top}px`,
56
+ left: `${renderItem.left}px`,
57
+ width: `${renderItem.width}px`,
58
+ height: `${renderItem.height}px`
59
+ };
60
+ }
61
+ // eslint-disable-next-line
62
+ export function __gridItemGetRenderDataFactoryFunc(gridCmp) {
63
+ return function (id) {
64
+ return parseRenderItemToPixels(gridCmp.getItemRenderData(id));
65
+ };
66
+ }
67
+ export function ktdGridItemGetRenderDataFactoryFunc(gridCmp) {
68
+ // Workaround explained: https://github.com/ng-packagr/ng-packagr/issues/696#issuecomment-387114613
69
+ const resultFunc = __gridItemGetRenderDataFactoryFunc(gridCmp);
70
+ return resultFunc;
71
+ }
72
+ const defaultBackgroundConfig = {
73
+ borderColor: '#ffa72678',
74
+ gapColor: 'transparent',
75
+ rowColor: 'transparent',
76
+ columnColor: 'transparent',
77
+ borderWidth: 1
78
+ };
79
+ export class KtdGridComponent {
80
+ /** Whether or not to update the internal layout when some dependent property change. */
81
+ get compactOnPropsChange() {
82
+ return this._compactOnPropsChange;
83
+ }
84
+ set compactOnPropsChange(value) {
85
+ this._compactOnPropsChange = coerceBooleanProperty(value);
86
+ }
87
+ /** If true, grid items won't change position when being dragged over. Handy when using no compaction */
88
+ get preventCollision() {
89
+ return this._preventCollision;
90
+ }
91
+ set preventCollision(value) {
92
+ this._preventCollision = coerceBooleanProperty(value);
93
+ }
94
+ /** Number of CSS pixels that would be scrolled on each 'tick' when auto scroll is performed. */
95
+ get scrollSpeed() {
96
+ return this._scrollSpeed;
97
+ }
98
+ set scrollSpeed(value) {
99
+ this._scrollSpeed = coerceNumberProperty(value, 2);
100
+ }
101
+ /** Type of compaction that will be applied to the layout (vertical, horizontal or free). Defaults to 'vertical' */
102
+ get compactType() {
103
+ return this._compactType;
104
+ }
105
+ set compactType(val) {
106
+ this._compactType = val;
107
+ }
108
+ /**
109
+ * Row height as number or as 'fit'.
110
+ * If rowHeight is a number value, it means that each row would have those css pixels in height.
111
+ * if rowHeight is 'fit', it means that rows will fit in the height available. If 'fit' value is set, a 'height' should be also provided.
112
+ */
113
+ get rowHeight() {
114
+ return this._rowHeight;
115
+ }
116
+ set rowHeight(val) {
117
+ this._rowHeight = val === 'fit' ? val : Math.max(1, Math.round(coerceNumberProperty(val)));
118
+ }
119
+ /** Number of columns */
120
+ get cols() {
121
+ return this._cols;
122
+ }
123
+ set cols(val) {
124
+ this._cols = Math.max(1, Math.round(coerceNumberProperty(val)));
125
+ }
126
+ /** Layout of the grid. Array of all the grid items with its 'id' and position on the grid. */
127
+ get layout() {
128
+ return this._layout;
129
+ }
130
+ set layout(layout) {
131
+ /**
132
+ * Enhancement:
133
+ * Only set layout if it's reference has changed and use a boolean to track whenever recalculate the layout on ngOnChanges.
134
+ *
135
+ * Why:
136
+ * The normal use of this lib is having the variable layout in the outer component or in a store, assigning it whenever it changes and
137
+ * binded in the component with it's input [layout]. In this scenario, we would always calculate one unnecessary change on the layout when
138
+ * it is re-binded on the input.
139
+ */
140
+ this._layout = layout;
141
+ }
142
+ /** Grid gap in css pixels */
143
+ get gap() {
144
+ return this._gap;
145
+ }
146
+ set gap(val) {
147
+ this._gap = Math.max(coerceNumberProperty(val), 0);
148
+ }
149
+ /**
150
+ * If height is a number, fixes the height of the grid to it, recommended when rowHeight = 'fit' is used.
151
+ * If height is null, height will be automatically set according to its inner grid items.
152
+ * Defaults to null.
153
+ * */
154
+ get height() {
155
+ return this._height;
156
+ }
157
+ set height(val) {
158
+ this._height = typeof val === 'number' ? Math.max(val, 0) : null;
159
+ }
160
+ get backgroundConfig() {
161
+ return this._backgroundConfig;
162
+ }
163
+ set backgroundConfig(val) {
164
+ this._backgroundConfig = val;
165
+ // If there is background configuration, add main grid background class. Grid background class comes with opacity 0.
166
+ // It is done this way for adding opacity animation and to don't add any styles when grid background is null.
167
+ const classList = this.elementRef.nativeElement.classList;
168
+ this._backgroundConfig !== null
169
+ ? classList.add('buw-grid-background')
170
+ : classList.remove('buw-grid-background');
171
+ // Set background visibility
172
+ this.setGridBackgroundVisible(this._backgroundConfig?.show === 'always');
173
+ }
174
+ get config() {
175
+ return {
176
+ cols: this.cols,
177
+ rowHeight: this.rowHeight,
178
+ height: this.height,
179
+ layout: this.layout,
180
+ preventCollision: this.preventCollision,
181
+ gap: this.gap
182
+ };
183
+ }
184
+ constructor(gridService, elementRef, viewContainerRef, renderer, ngZone) {
185
+ this.gridService = gridService;
186
+ this.elementRef = elementRef;
187
+ this.viewContainerRef = viewContainerRef;
188
+ this.renderer = renderer;
189
+ this.ngZone = ngZone;
190
+ /** Emits when layout change */
191
+ this.layoutUpdated = new EventEmitter();
192
+ /** Emits when drag starts */
193
+ this.dragStarted = new EventEmitter();
194
+ /** Emits when resize starts */
195
+ this.resizeStarted = new EventEmitter();
196
+ /** Emits when drag ends */
197
+ this.dragEnded = new EventEmitter();
198
+ /** Emits when resize ends */
199
+ this.resizeEnded = new EventEmitter();
200
+ /** Emits when a grid item is being resized and its bounds have changed */
201
+ this.gridItemResize = new EventEmitter();
202
+ /**
203
+ * Parent element that contains the scroll. If an string is provided it would search that element by id on the dom.
204
+ * If no data provided or null autoscroll is not performed.
205
+ */
206
+ this.scrollableParent = null;
207
+ this._compactOnPropsChange = true;
208
+ this._preventCollision = false;
209
+ this._scrollSpeed = 2;
210
+ this._compactType = 'vertical';
211
+ this._rowHeight = 100;
212
+ this._cols = 6;
213
+ this._gap = 0;
214
+ this._height = null;
215
+ this._backgroundConfig = null;
216
+ this.subscriptions = [];
217
+ }
218
+ ngOnChanges(changes) {
219
+ if (this.rowHeight === 'fit' && this.height == null) {
220
+ console.warn(`KtdGridComponent: The @Input() height should not be null when using rowHeight 'fit'`);
221
+ }
222
+ let needsCompactLayout = false;
223
+ let needsRecalculateRenderData = false;
224
+ // TODO: Does fist change need to be compacted by default?
225
+ // Compact layout whenever some dependent prop changes.
226
+ if (changes.compactType || changes.cols || changes.layout) {
227
+ needsCompactLayout = true;
228
+ }
229
+ // Check if wee need to recalculate rendering data.
230
+ if (needsCompactLayout || changes.rowHeight || changes.height || changes.gap || changes.backgroundConfig) {
231
+ needsRecalculateRenderData = true;
232
+ }
233
+ // Only compact layout if lib user has provided it. Lib users that want to save/store always the same layout as it is represented (compacted)
234
+ // can use KtdCompactGrid utility and pre-compact the layout. This is the recommended behaviour for always having a the same layout on this component
235
+ // and the ones that uses it.
236
+ if (needsCompactLayout && this.compactOnPropsChange) {
237
+ this.compactLayout();
238
+ }
239
+ if (needsRecalculateRenderData) {
240
+ this.calculateRenderData();
241
+ }
242
+ }
243
+ ngAfterContentInit() {
244
+ this.initSubscriptions();
245
+ }
246
+ ngAfterContentChecked() {
247
+ this.render();
248
+ }
249
+ resize() {
250
+ this.calculateRenderData();
251
+ this.render();
252
+ }
253
+ ngOnDestroy() {
254
+ this.subscriptions.forEach((sub) => sub.unsubscribe());
255
+ }
256
+ compactLayout() {
257
+ this.layout = compact(this.layout, this.compactType, this.cols);
258
+ }
259
+ getItemsRenderData() {
260
+ return { ...this._gridItemsRenderData };
261
+ }
262
+ getItemRenderData(itemId) {
263
+ return this._gridItemsRenderData[itemId];
264
+ }
265
+ calculateRenderData() {
266
+ const clientRect = this.elementRef.nativeElement.getBoundingClientRect();
267
+ this.gridCurrentHeight =
268
+ this.height ??
269
+ (this.rowHeight === 'fit' ? clientRect.height : getGridHeight(this.layout, this.rowHeight, this.gap));
270
+ this._gridItemsRenderData = layoutToRenderItems(this.config, clientRect.width, this.gridCurrentHeight);
271
+ // Set Background CSS variables
272
+ this.setBackgroundCssVariables(getRowHeightInPixels(this.config, this.gridCurrentHeight));
273
+ }
274
+ render() {
275
+ this.renderer.setStyle(this.elementRef.nativeElement, 'height', `${this.gridCurrentHeight}px`);
276
+ this.updateGridItemsStyles();
277
+ }
278
+ setBackgroundCssVariables(rowHeight) {
279
+ const style = this.elementRef.nativeElement.style;
280
+ if (this._backgroundConfig) {
281
+ // structure
282
+ style.setProperty('--gap', this.gap + 'px');
283
+ style.setProperty('--row-height', rowHeight + 'px');
284
+ style.setProperty('--columns', `${this.cols}`);
285
+ style.setProperty('--border-width', (this._backgroundConfig.borderWidth ?? defaultBackgroundConfig.borderWidth) + 'px');
286
+ // colors
287
+ style.setProperty('--border-color', this._backgroundConfig.borderColor ?? defaultBackgroundConfig.borderColor);
288
+ style.setProperty('--gap-color', this._backgroundConfig.gapColor ?? defaultBackgroundConfig.gapColor);
289
+ style.setProperty('--row-color', this._backgroundConfig.rowColor ?? defaultBackgroundConfig.rowColor);
290
+ style.setProperty('--column-color', this._backgroundConfig.columnColor ?? defaultBackgroundConfig.columnColor);
291
+ }
292
+ else {
293
+ style.removeProperty('--gap');
294
+ style.removeProperty('--row-height');
295
+ style.removeProperty('--columns');
296
+ style.removeProperty('--border-width');
297
+ style.removeProperty('--border-color');
298
+ style.removeProperty('--gap-color');
299
+ style.removeProperty('--row-color');
300
+ style.removeProperty('--column-color');
301
+ }
302
+ }
303
+ updateGridItemsStyles() {
304
+ this._gridItems.forEach((item) => {
305
+ const gridItemRenderData = this._gridItemsRenderData[item.id];
306
+ if (gridItemRenderData == null) {
307
+ console.error(`Couldn't find the specified grid item for the id: ${item.id}`);
308
+ }
309
+ else {
310
+ item.setStyles(parseRenderItemToPixels(gridItemRenderData));
311
+ }
312
+ });
313
+ }
314
+ setGridBackgroundVisible(visible) {
315
+ const classList = this.elementRef.nativeElement.classList;
316
+ visible ? classList.add('buw-grid-background-visible') : classList.remove('buw-grid-background-visible');
317
+ }
318
+ initSubscriptions() {
319
+ this.subscriptions = [
320
+ this._gridItems.changes
321
+ .pipe(startWith(this._gridItems), switchMap((gridItems) => merge(...gridItems.map((gridItem) => gridItem.dragStart$.pipe(map((event) => ({ event, gridItem, type: 'drag' })))), ...gridItems.map((gridItem) => gridItem.resizeStart$.pipe(map((event) => ({
322
+ event,
323
+ gridItem,
324
+ type: 'resize'
325
+ }))))).pipe(exhaustMap(({ event, gridItem, type }) => {
326
+ // Emit drag or resize start events. Ensure that is start event is inside the zone.
327
+ this.ngZone.run(() => (type === 'drag' ? this.dragStarted : this.resizeStarted).emit(getDragResizeEventData(gridItem, this.layout)));
328
+ this.setGridBackgroundVisible(this._backgroundConfig?.show === 'whenDragging' ||
329
+ this._backgroundConfig?.show === 'always');
330
+ // Perform drag sequence
331
+ return this.performDragSequence$(gridItem, event, type).pipe(map((layout) => ({ layout, gridItem, type })));
332
+ }))))
333
+ .subscribe(({ layout, gridItem, type }) => {
334
+ this.layout = layout;
335
+ // Calculate new rendering data given the new layout.
336
+ this.calculateRenderData();
337
+ // Emit drag or resize end events.
338
+ (type === 'drag' ? this.dragEnded : this.resizeEnded).emit(getDragResizeEventData(gridItem, layout));
339
+ // Notify that the layout has been updated.
340
+ this.layoutUpdated.emit(layout);
341
+ this.setGridBackgroundVisible(this._backgroundConfig?.show === 'always');
342
+ })
343
+ ];
344
+ }
345
+ /**
346
+ * Perform a general grid drag action, from start to end. A general grid drag action basically includes creating the placeholder element and adding
347
+ * some class animations. calcNewStateFunc needs to be provided in order to calculate the new state of the layout.
348
+ * @param gridItem that is been dragged
349
+ * @param pointerDownEvent event (mousedown or touchdown) where the user initiated the drag
350
+ * @param calcNewStateFunc function that return the new layout state and the drag element position
351
+ */
352
+ performDragSequence$(gridItem, pointerDownEvent, type) {
353
+ return new Observable((observer) => {
354
+ // Retrieve grid (parent) and gridItem (draggedElem) client rects.
355
+ const gridElemClientRect = getMutableClientRect(this.elementRef.nativeElement);
356
+ const dragElemClientRect = getMutableClientRect(gridItem.elementRef.nativeElement);
357
+ const scrollableParent = typeof this.scrollableParent === 'string'
358
+ ? document.getElementById(this.scrollableParent)
359
+ : this.scrollableParent;
360
+ this.renderer.addClass(gridItem.elementRef.nativeElement, 'no-transitions');
361
+ this.renderer.addClass(gridItem.elementRef.nativeElement, 'buw-grid-item-dragging');
362
+ const placeholderClientRect = {
363
+ ...dragElemClientRect,
364
+ left: dragElemClientRect.left - gridElemClientRect.left,
365
+ top: dragElemClientRect.top - gridElemClientRect.top
366
+ };
367
+ this.createPlaceholderElement(placeholderClientRect, gridItem.placeholder);
368
+ let newLayout;
369
+ // TODO (enhancement): consider move this 'side effect' observable inside the main drag loop.
370
+ // - Pros are that we would not repeat subscriptions and takeUntil would shut down observables at the same time.
371
+ // - Cons are that moving this functionality as a side effect inside the main drag loop would be confusing.
372
+ const scrollSubscription = this.ngZone.runOutsideAngular(() => (!scrollableParent
373
+ ? NEVER
374
+ : this.gridService.mouseOrTouchMove$(document).pipe(map((event) => ({
375
+ pointerX: ktdPointerClientX(event),
376
+ pointerY: ktdPointerClientY(event)
377
+ })), ktdScrollIfNearElementClientRect$(scrollableParent, { scrollStep: this.scrollSpeed })))
378
+ .pipe(takeUntil(ktdPointerUp(document)))
379
+ .subscribe());
380
+ /**
381
+ * Main subscription, it listens for 'pointer move' and 'scroll' events and recalculates the layout on each emission
382
+ */
383
+ const subscription = this.ngZone.runOutsideAngular(() => merge(combineLatest([
384
+ this.gridService.mouseOrTouchMove$(document),
385
+ ...(!scrollableParent
386
+ ? [of({ top: 0, left: 0 })]
387
+ : [
388
+ ktdGetScrollTotalRelativeDifference$(scrollableParent).pipe(startWith({ top: 0, left: 0 }) // Force first emission to allow CombineLatest to emit even no scroll event has occurred
389
+ )
390
+ ])
391
+ ]))
392
+ .pipe(takeUntil(ktdPointerUp(document)))
393
+ .subscribe(([pointerDragEvent, scrollDifference]) => {
394
+ pointerDragEvent.preventDefault();
395
+ /**
396
+ * Set the new layout to be the layout in which the calcNewStateFunc would be executed.
397
+ * NOTE: using the mutated layout is the way to go by 'react-grid-layout' utils. If we don't use the previous layout,
398
+ * some utilities from 'react-grid-layout' would not work as expected.
399
+ */
400
+ const currentLayout = newLayout || this.layout;
401
+ // Get the correct newStateFunc depending on if we are dragging or resizing
402
+ const calcNewStateFunc = type === 'drag' ? ktdGridItemDragging : ktdGridItemResizing;
403
+ const { layout, draggedItemPos } = calcNewStateFunc(gridItem, {
404
+ layout: currentLayout,
405
+ rowHeight: this.rowHeight,
406
+ height: this.height,
407
+ cols: this.cols,
408
+ preventCollision: this.preventCollision,
409
+ gap: this.gap
410
+ }, this.compactType, {
411
+ pointerDownEvent,
412
+ pointerDragEvent,
413
+ gridElemClientRect,
414
+ dragElemClientRect,
415
+ scrollDifference
416
+ });
417
+ newLayout = layout;
418
+ this.gridCurrentHeight =
419
+ this.height ??
420
+ (this.rowHeight === 'fit'
421
+ ? gridElemClientRect.height
422
+ : getGridHeight(newLayout, this.rowHeight, this.gap));
423
+ this._gridItemsRenderData = layoutToRenderItems({
424
+ cols: this.cols,
425
+ rowHeight: this.rowHeight,
426
+ height: this.height,
427
+ layout: newLayout,
428
+ preventCollision: this.preventCollision,
429
+ gap: this.gap
430
+ }, gridElemClientRect.width, gridElemClientRect.height);
431
+ const newGridItemRenderData = { ...this._gridItemsRenderData[gridItem.id] };
432
+ const placeholderStyles = parseRenderItemToPixels(newGridItemRenderData);
433
+ // Put the real final position to the placeholder element
434
+ this.placeholder.style.width = placeholderStyles.width;
435
+ this.placeholder.style.height = placeholderStyles.height;
436
+ this.placeholder.style.transform = `translateX(${placeholderStyles.left}) translateY(${placeholderStyles.top})`;
437
+ // modify the position of the dragged item to be the once we want (for example the mouse position or whatever)
438
+ this._gridItemsRenderData[gridItem.id] = {
439
+ ...draggedItemPos,
440
+ id: this._gridItemsRenderData[gridItem.id].id
441
+ };
442
+ this.setBackgroundCssVariables(this.rowHeight === 'fit'
443
+ ? ktdGetGridItemRowHeight(newLayout, gridElemClientRect.height, this.gap)
444
+ : this.rowHeight);
445
+ this.render();
446
+ // If we are performing a resize, and bounds have changed, emit event.
447
+ // NOTE: Only emit on resize for now. Use case for normal drag is not justified for now. Emitting on resize is,
448
+ // since we may want to re-render the grid item or the placeholder in order to fit the new bounds.
449
+ if (type === 'resize') {
450
+ const prevGridItem = currentLayout.find((item) => item.id === gridItem.id);
451
+ const newGridItem = newLayout.find((item) => item.id === gridItem.id);
452
+ // Check if item resized has changed, if so, emit resize change event
453
+ if (!ktdGridItemLayoutItemAreEqual(prevGridItem, newGridItem)) {
454
+ this.gridItemResize.emit({
455
+ width: newGridItemRenderData.width,
456
+ height: newGridItemRenderData.height,
457
+ gridItemRef: getDragResizeEventData(gridItem, newLayout).gridItemRef
458
+ });
459
+ }
460
+ }
461
+ }, (error) => observer.error(error), () => {
462
+ this.ngZone.run(() => {
463
+ // Remove drag classes
464
+ this.renderer.removeClass(gridItem.elementRef.nativeElement, 'no-transitions');
465
+ this.renderer.removeClass(gridItem.elementRef.nativeElement, 'buw-grid-item-dragging');
466
+ this.addGridItemAnimatingClass(gridItem).subscribe();
467
+ // Consider destroying the placeholder after the animation has finished.
468
+ this.destroyPlaceholder();
469
+ if (newLayout) {
470
+ // TODO: newLayout should already be pruned. If not, it should have type Layout, not KtdGridLayout as it is now.
471
+ // Prune react-grid-layout compact extra properties.
472
+ observer.next(newLayout.map((item) => ({
473
+ id: item.id,
474
+ x: item.x,
475
+ y: item.y,
476
+ w: item.w,
477
+ h: item.h,
478
+ minW: item.minW,
479
+ minH: item.minH,
480
+ maxW: item.maxW,
481
+ maxH: item.maxH
482
+ })));
483
+ }
484
+ else {
485
+ // TODO: Need we really to emit if there is no layout change but drag started and ended?
486
+ observer.next(this.layout);
487
+ }
488
+ observer.complete();
489
+ });
490
+ }));
491
+ return () => {
492
+ scrollSubscription.unsubscribe();
493
+ subscription.unsubscribe();
494
+ };
495
+ });
496
+ }
497
+ /**
498
+ * It adds the `buw-grid-item-animating` class and removes it when the animated transition is complete.
499
+ * This function is meant to be executed when the drag has ended.
500
+ * @param gridItem that has been dragged
501
+ */
502
+ addGridItemAnimatingClass(gridItem) {
503
+ return new Observable((observer) => {
504
+ const duration = getTransformTransitionDurationInMs(gridItem.elementRef.nativeElement);
505
+ if (duration === 0) {
506
+ observer.next();
507
+ observer.complete();
508
+ return;
509
+ }
510
+ this.renderer.addClass(gridItem.elementRef.nativeElement, 'buw-grid-item-animating');
511
+ const handler = ((event) => {
512
+ if (!event ||
513
+ (event.target === gridItem.elementRef.nativeElement && event.propertyName === 'transform')) {
514
+ this.renderer.removeClass(gridItem.elementRef.nativeElement, 'buw-grid-item-animating');
515
+ removeEventListener();
516
+ clearTimeout(timeout);
517
+ observer.next();
518
+ observer.complete();
519
+ }
520
+ });
521
+ // If a transition is short enough, the browser might not fire the `transitionend` event.
522
+ // Since we know how long it's supposed to take, add a timeout with a 50% buffer that'll
523
+ // fire if the transition hasn't completed when it was supposed to.
524
+ const timeout = setTimeout(handler, duration * 1.5);
525
+ const removeEventListener = this.renderer.listen(gridItem.elementRef.nativeElement, 'transitionend', handler);
526
+ });
527
+ }
528
+ /** Creates placeholder element */
529
+ createPlaceholderElement(clientRect, gridItemPlaceholder) {
530
+ this.placeholder = this.renderer.createElement('div');
531
+ this.placeholder.style.width = `${clientRect.width}px`;
532
+ this.placeholder.style.height = `${clientRect.height}px`;
533
+ this.placeholder.style.transform = `translateX(${clientRect.left}px) translateY(${clientRect.top}px)`;
534
+ this.placeholder.classList.add('buw-grid-item-placeholder');
535
+ this.renderer.appendChild(this.elementRef.nativeElement, this.placeholder);
536
+ // Create and append custom placeholder if provided.
537
+ // Important: Append it after creating & appending the container placeholder. This way we ensure parent bounds are set when creating the embeddedView.
538
+ if (gridItemPlaceholder) {
539
+ this.placeholderRef = this.viewContainerRef.createEmbeddedView(gridItemPlaceholder.templateRef, gridItemPlaceholder.data);
540
+ this.placeholderRef.rootNodes.forEach((node) => this.placeholder.appendChild(node));
541
+ this.placeholderRef.detectChanges();
542
+ }
543
+ else {
544
+ this.placeholder.classList.add('buw-grid-item-placeholder-default');
545
+ }
546
+ }
547
+ /** Destroys the placeholder element and its ViewRef. */
548
+ destroyPlaceholder() {
549
+ this.placeholder?.remove();
550
+ this.placeholderRef?.destroy();
551
+ this.placeholder = this.placeholderRef = null;
552
+ }
553
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: KtdGridComponent, deps: [{ token: i1.KtdGridService }, { token: i0.ElementRef }, { token: i0.ViewContainerRef }, { token: i0.Renderer2 }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
554
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: KtdGridComponent, selector: "buw-grid", inputs: { scrollableParent: "scrollableParent", compactOnPropsChange: "compactOnPropsChange", preventCollision: "preventCollision", scrollSpeed: "scrollSpeed", compactType: "compactType", rowHeight: "rowHeight", cols: "cols", layout: "layout", gap: "gap", height: "height", backgroundConfig: "backgroundConfig" }, outputs: { layoutUpdated: "layoutUpdated", dragStarted: "dragStarted", resizeStarted: "resizeStarted", dragEnded: "dragEnded", resizeEnded: "resizeEnded", gridItemResize: "gridItemResize" }, providers: [
555
+ {
556
+ provide: GRID_ITEM_GET_RENDER_DATA_TOKEN,
557
+ useFactory: ktdGridItemGetRenderDataFactoryFunc,
558
+ deps: [KtdGridComponent]
559
+ }
560
+ ], queries: [{ propertyName: "_gridItems", predicate: KtdGridItemComponent, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<ng-content></ng-content>", styles: ["buw-grid{display:block;position:relative;width:100%}buw-grid.buw-grid-background:before{content:\"\";border:none;position:absolute;inset:0;z-index:0;transition:opacity .2s;opacity:0;background-image:repeating-linear-gradient(var(--border-color) 0 var(--border-width),var(--row-color) var(--border-width) calc(var(--row-height) - var(--border-width)),var(--border-color) calc(var(--row-height) - var(--border-width)) calc(var(--row-height)),var(--gap-color) calc(var(--row-height)) calc(var(--row-height) + var(--gap))),repeating-linear-gradient(90deg,var(--border-color) 0 var(--border-width),var(--column-color) var(--border-width) calc(100% - (var(--border-width) + var(--gap))),var(--border-color) calc(100% - (var(--border-width) + var(--gap))) calc(100% - var(--gap)),var(--gap-color) calc(100% - var(--gap)) 100%);background-size:calc((100% + var(--gap)) / var(--columns)) calc(var(--row-height) + var(--gap));background-position:0 0}buw-grid.buw-grid-background.buw-grid-background-visible:before{opacity:1}buw-grid buw-grid-item.buw-grid-item-dragging,buw-grid buw-grid-item.buw-grid-item-animating{z-index:1000}buw-grid buw-grid-item.no-transitions{transition:none!important}buw-grid .buw-grid-item-placeholder{position:absolute;z-index:0;transition-property:transform;transition:all .15s ease}buw-grid .buw-grid-item-placeholder-default{background-color:#8b0000;opacity:.6}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
561
+ }
562
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: KtdGridComponent, decorators: [{
563
+ type: Component,
564
+ args: [{ selector: 'buw-grid', encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
565
+ {
566
+ provide: GRID_ITEM_GET_RENDER_DATA_TOKEN,
567
+ useFactory: ktdGridItemGetRenderDataFactoryFunc,
568
+ deps: [KtdGridComponent]
569
+ }
570
+ ], template: "<ng-content></ng-content>", styles: ["buw-grid{display:block;position:relative;width:100%}buw-grid.buw-grid-background:before{content:\"\";border:none;position:absolute;inset:0;z-index:0;transition:opacity .2s;opacity:0;background-image:repeating-linear-gradient(var(--border-color) 0 var(--border-width),var(--row-color) var(--border-width) calc(var(--row-height) - var(--border-width)),var(--border-color) calc(var(--row-height) - var(--border-width)) calc(var(--row-height)),var(--gap-color) calc(var(--row-height)) calc(var(--row-height) + var(--gap))),repeating-linear-gradient(90deg,var(--border-color) 0 var(--border-width),var(--column-color) var(--border-width) calc(100% - (var(--border-width) + var(--gap))),var(--border-color) calc(100% - (var(--border-width) + var(--gap))) calc(100% - var(--gap)),var(--gap-color) calc(100% - var(--gap)) 100%);background-size:calc((100% + var(--gap)) / var(--columns)) calc(var(--row-height) + var(--gap));background-position:0 0}buw-grid.buw-grid-background.buw-grid-background-visible:before{opacity:1}buw-grid buw-grid-item.buw-grid-item-dragging,buw-grid buw-grid-item.buw-grid-item-animating{z-index:1000}buw-grid buw-grid-item.no-transitions{transition:none!important}buw-grid .buw-grid-item-placeholder{position:absolute;z-index:0;transition-property:transform;transition:all .15s ease}buw-grid .buw-grid-item-placeholder-default{background-color:#8b0000;opacity:.6}\n"] }]
571
+ }], ctorParameters: () => [{ type: i1.KtdGridService }, { type: i0.ElementRef }, { type: i0.ViewContainerRef }, { type: i0.Renderer2 }, { type: i0.NgZone }], propDecorators: { _gridItems: [{
572
+ type: ContentChildren,
573
+ args: [KtdGridItemComponent, { descendants: true }]
574
+ }], layoutUpdated: [{
575
+ type: Output
576
+ }], dragStarted: [{
577
+ type: Output
578
+ }], resizeStarted: [{
579
+ type: Output
580
+ }], dragEnded: [{
581
+ type: Output
582
+ }], resizeEnded: [{
583
+ type: Output
584
+ }], gridItemResize: [{
585
+ type: Output
586
+ }], scrollableParent: [{
587
+ type: Input
588
+ }], compactOnPropsChange: [{
589
+ type: Input
590
+ }], preventCollision: [{
591
+ type: Input
592
+ }], scrollSpeed: [{
593
+ type: Input
594
+ }], compactType: [{
595
+ type: Input
596
+ }], rowHeight: [{
597
+ type: Input
598
+ }], cols: [{
599
+ type: Input
600
+ }], layout: [{
601
+ type: Input
602
+ }], gap: [{
603
+ type: Input
604
+ }], height: [{
605
+ type: Input
606
+ }], backgroundConfig: [{
607
+ type: Input
608
+ }] } });
609
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ3JpZC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9iYXJzYS11c2VyLXdvcmtzcGFjZS9zcmMvbGliL2dyaWQvZ3JpZC5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9iYXJzYS11c2VyLXdvcmtzcGFjZS9zcmMvbGliL2dyaWQvZ3JpZC5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBR0gsdUJBQXVCLEVBQ3ZCLFNBQVMsRUFDVCxlQUFlLEVBR2YsWUFBWSxFQUNaLEtBQUssRUFJTCxNQUFNLEVBS04saUJBQWlCLEVBQ3BCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxvQkFBb0IsRUFBZSxNQUFNLDZCQUE2QixDQUFDO0FBQ2hGLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBQ3hFLE9BQU8sRUFBRSxhQUFhLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQVksRUFBRSxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUMzRixPQUFPLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxNQUFNLGdCQUFnQixDQUFDO0FBQ2xGLE9BQU8sRUFDSCx1QkFBdUIsRUFDdkIsbUJBQW1CLEVBQ25CLDZCQUE2QixFQUM3QixtQkFBbUIsRUFDdEIsTUFBTSxxQkFBcUIsQ0FBQztBQUM3QixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDM0QsT0FBTyxFQUNILCtCQUErQixFQU9sQyxNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sRUFBRSxZQUFZLEVBQUUsaUJBQWlCLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUc1RixPQUFPLEVBQUUsb0JBQW9CLEVBQWlCLE1BQU0sc0JBQXNCLENBQUM7QUFD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Z0I7c0JBRG5CLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICAgIEFmdGVyQ29udGVudENoZWNrZWQsXG4gICAgQWZ0ZXJDb250ZW50SW5pdCxcbiAgICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgICBDb21wb25lbnQsXG4gICAgQ29udGVudENoaWxkcmVuLFxuICAgIEVsZW1lbnRSZWYsXG4gICAgRW1iZWRkZWRWaWV3UmVmLFxuICAgIEV2ZW50RW1pdHRlcixcbiAgICBJbnB1dCxcbiAgICBOZ1pvbmUsXG4gICAgT25DaGFuZ2VzLFxuICAgIE9uRGVzdHJveSxcbiAgICBPdXRwdXQsXG4gICAgUXVlcnlMaXN0LFxuICAgIFJlbmRlcmVyMixcbiAgICBTaW1wbGVDaGFuZ2VzLFxuICAgIFZpZXdDb250YWluZXJSZWYsXG4gICAgVmlld0VuY2Fwc3VsYXRpb25cbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBjb2VyY2VOdW1iZXJQcm9wZXJ0eSwgTnVtYmVySW5wdXQgfSBmcm9tICcuLi9jb2VyY2lvbi9udW1iZXItcHJvcGVydHknO1xuaW1wb3J0IHsgS3RkR3JpZEl0ZW1Db21wb25lbnQgfSBmcm9tICcuLi9ncmlkLWl0ZW0vZ3JpZC1pdGVtLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBjb21iaW5lTGF0ZXN0LCBtZXJnZSwgTkVWRVIsIE9ic2VydmFibGUsIE9ic2VydmVyLCBvZiwgU3Vic2NyaXB0aW9uIH0gZnJvbSAncnhqcyc7XG5pbXBvcnQgeyBleGhhdXN0TWFwLCBtYXAsIHN0YXJ0V2l0aCwgc3dpdGNoTWFwLCB0YWtlVW50aWwgfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge1xuICAgIGt0ZEdldEdyaWRJdGVtUm93SGVpZ2h0LFxuICAgIGt0ZEdyaWRJdGVtRHJhZ2dpbmcsXG4gICAga3RkR3JpZEl0ZW1MYXlvdXRJdGVtQXJlRXF1YWwsXG4gICAga3RkR3JpZEl0ZW1SZXNpemluZ1xufSBmcm9tICcuLi91dGlscy9ncmlkLnV0aWxzJztcbmltcG9ydCB7IGNvbXBhY3QgfSBmcm9tICcuLi91dGlscy9yZWFjdC1ncmlkLWxheW91dC51dGlscyc7XG5pbXBvcnQge1xuICAgIEdSSURfSVRFTV9HRVRfUkVOREVSX0RBVEFfVE9LRU4sXG4gICAgS3RkR3JpZEJhY2tncm91bmRDZmcsXG4gICAgS3RkR3JpZENmZyxcbiAgICBLdGRHcmlkQ29tcGFjdFR5cGUsXG4gICAgS3RkR3JpZEl0ZW1SZW5kZXJEYXRhLFxuICAgIEt0ZEdyaWRMYXlvdXQsXG4gICAgS3RkR3JpZExheW91dEl0ZW1cbn0gZnJvbSAnLi4vZ3JpZC5kZWZpbml0aW9ucyc7XG5pbXBvcnQgeyBrdGRQb2ludGVyVXAsIGt0ZFBvaW50ZXJDbGllbnRYLCBrdGRQb2ludGVyQ2xpZW50WSB9IGZyb20gJy4uL3V0aWxzL3BvaW50ZXIudXRpbHMnO1xuaW1wb3J0IHsgS3RkRGljdGlvbmFyeSB9IGZyb20gJy4uLy4uL3R5cGVzJztcbmltcG9ydCB7IEt0ZEdyaWRTZXJ2aWNlIH0gZnJvbSAnLi4vZ3JpZC5zZXJ2aWNlJztcbmltcG9ydCB7IGdldE11dGFibGVDbGllbnRSZWN0LCBLdGRDbGllbnRSZWN0IH0gZnJvbSAnLi4vdXRpbHMvY2xpZW50LXJlY3QnO1xuaW1wb3J0IHsga3RkR2V0U2Nyb2xsVG90YWxSZWxhdGl2ZURpZmZlcmVuY2UkLCBrdGRTY3JvbGxJZk5lYXJFbGVtZW50Q2xpZW50UmVjdCQgfSBmcm9tICcuLi91dGlscy9zY3JvbGwnO1xuaW1wb3J0IHsgQm9vbGVhbklucHV0LCBjb2VyY2VCb29sZWFuUHJvcGVydHkgfSBmcm9tICcuLi9jb2VyY2lvbi9ib29sZWFuLXByb3BlcnR5JztcbmltcG9ydCB7IEt0ZEdyaWRJdGVtUGxhY2Vob2xkZXIgfSBmcm9tICcuLi9kaXJlY3RpdmVzL3BsYWNlaG9sZGVyJztcbmltcG9ydCB7IGdldFRyYW5zZm9ybVRyYW5zaXRpb25EdXJhdGlvbkluTXMgfSBmcm9tICcuLi91dGlscy90cmFuc2l0aW9uLWR1cmF0aW9uJztcblxuaW50ZXJmYWNlIEt0ZERyYWdSZXNpemVFdmVudCB7XG4gICAgbGF5b3V0OiBLdGRHcmlkTGF5b3V0O1xuICAgIGxheW91dEl0ZW06IEt0ZEdyaWRMYXlvdXRJdGVtO1xuICAgIGdyaWRJdGVtUmVmOiBLdGRHcmlkSXRlbUNvbXBvbmVudDtcbn1cblxuZXhwb3J0IHR5cGUgS3RkRHJhZ1N0YXJ0ID0gS3RkRHJhZ1Jlc2l6ZUV2ZW50O1xuZXhwb3J0IHR5cGUgS3RkUmVzaXplU3RhcnQgPSBLdGREcmFnUmVzaXplRXZlbnQ7XG5leHBvcnQgdHlwZSBLdGREcmFnRW5kID0gS3RkRHJhZ1Jlc2l6ZUV2ZW50O1xuZXhwb3J0IHR5cGUgS3RkUmVzaXplRW5kID0gS3RkRHJhZ1Jlc2l6ZUV2ZW50O1xuXG5leHBvcnQgaW50ZXJmYWNlIEt0ZEdyaWRJdGVtUmVzaXplRXZlbnQge1xuICAgIHdpZHRoOiBudW1iZXI7XG4gICAgaGVpZ2h0OiBudW1iZXI7XG4gICAgZ3JpZEl0ZW1SZWY6IEt0ZEdyaWRJdGVtQ29tcG9uZW50O1xufVxuXG50eXBlIERyYWdBY3Rpb25UeXBlID0gJ2RyYWcnIHwgJ3Jlc2l6ZSc7XG5cbmZ1bmN0aW9uIGdldERyYWdSZXNpemVFdmVudERhdGEoZ3JpZEl0ZW06IEt0ZEdyaWRJdGVtQ29tcG9uZW50LCBsYXlvdXQ6IEt0ZEdyaWRMYXlvdXQpOiBLdGREcmFnUmVzaXplRXZlbnQge1xuICAgIHJldHVybiB7XG4gICAgICAgIGxheW91dCxcbiAgICAgICAgbGF5b3V0SXRlbTogbGF5b3V0LmZpbmQoKGl0ZW0pID0+IGl0ZW0uaWQgPT09IGdyaWRJdGVtLmlkKSEsXG4gICAgICAgIGdyaWRJdGVtUmVmOiBncmlkSXRlbVxuICAgIH07XG59XG5cbmZ1bmN0aW9uIGdldENvbHVtbldpZHRoKGNvbmZpZzogS3RkR3JpZENmZywgd2lkdGg6IG51bWJlcik6IG51bWJlciB7XG4gICAgY29uc3QgeyBjb2xzLCBnYXAgfSA9IGNvbmZpZztcbiAgICBjb25zdCB3aWR0aEV4Y2x1ZGluZ0dhcCA9IHdpZHRoIC0gTWF0aC5tYXgoZ2FwICogKGNvbHMgLSAxKSwgMCk7XG4gICAgcmV0dXJuIHdpZHRoRXhjbHVkaW5nR2FwIC8gY29scztcbn1cblxuZnVuY3Rpb24gZ2V0Um93SGVpZ2h0SW5QaXhlbHMoY29uZmlnOiBLdGRHcmlkQ2ZnLCBoZWlnaHQ6IG51bWJlcik6IG51bWJlciB7XG4gICAgY29uc3QgeyByb3dIZWlnaHQsIGxheW91dCwgZ2FwIH0gPSBjb25maWc7XG4gICAgcmV0dXJuIHJvd0hlaWdodCA9PT0gJ2ZpdCcgPyBrdGRHZXRHcmlkSXRlbVJvd0hlaWdodChsYXlvdXQsIGhlaWdodCwgZ2FwKSA6IHJvd0hlaWdodDtcbn1cblxuZnVuY3Rpb24gbGF5b3V0VG9SZW5kZXJJdGVtcyhcbiAgICBjb25maWc6IEt0ZEdyaWRDZmcsXG4gICAgd2lkdGg6IG51bWJlcixcbiAgICBoZWlnaHQ6IG51bWJlclxuKTogS3RkRGljdGlvbmFyeTxLdGRHcmlkSXRlbVJlbmRlckRhdGE8bnVtYmVyPj4ge1xuICAgIGNvbnN0IHsgbGF5b3V0LCBnYXAgfSA9IGNvbmZpZztcbiAgICBjb25zdCByb3dIZWlnaHRJblBpeGVscyA9IGdldFJvd0hlaWdodEluUGl4ZWxzKGNvbmZpZywgaGVpZ2h0KTtcbiAgICBjb25zdCBpdGVtV2lkdGhQZXJDb2x1bW4gPSBnZXRDb2x1bW5XaWR0aChjb25maWcsIHdpZHRoKTtcbiAgICBjb25zdCByZW5kZXJJdGVtczogS3RkRGljdGlvbmFyeTxLdGRHcmlkSXRlbVJlbmRlckRhdGE8bnVtYmVyPj4gPSB7fTtcbiAgICBmb3IgKGNvbnN0IGl0ZW0gb2YgbGF5b3V0KSB7XG4gICAgICAgIHJlbmRlckl0ZW1zW2l0ZW0uaWRdID0ge1xuICAgICAgICAgICAgaWQ6IGl0ZW0uaWQsXG4gICAgICAgICAgICB0b3A6IGl0ZW0ueSAqIHJvd0hlaWdodEluUGl4ZWxzICsgZ2FwICogaXRlbS55LFxuICAgICAgICAgICAgbGVmdDogaXRlbS54ICogaXRlbVdpZHRoUGVyQ29sdW1uICsgZ2FwICogaXRlbS54LFxuICAgICAgICAgICAgd2lkdGg6IGl0ZW0udyAqIGl0ZW1XaWR0aFBlckNvbHVtbiArIGdhcCAqIE1hdGgubWF4KGl0ZW0udyAtIDEsIDApLFxuICAgICAgICAgICAgaGVpZ2h0OiBpdGVtLmggKiByb3dIZWlnaHRJblBpeGVscyArIGdhcCAqIE1hdGgubWF4KGl0ZW0uaCAtIDEsIDApXG4gICAgICAgIH07XG4gICAgfVxuICAgIHJldHVybiByZW5kZXJJdGVtcztcbn1cblxuZnVuY3Rpb24gZ2V0R3JpZEhlaWdodChsYXlvdXQ6IEt0ZEdyaWRMYXlvdXQsIHJvd0hlaWdodDogbnVtYmVyLCBnYXA6IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIGxheW91dC5yZWR1Y2UoXG4gICAgICAgIChhY2MsIGN1cikgPT4gTWF0aC5tYXgoYWNjLCAoY3VyLnkgKyBjdXIuaCkgKiByb3dIZWlnaHQgKyBNYXRoLm1heChjdXIueSArIGN1ci5oIC0gMSwgMCkgKiBnYXApLFxuICAgICAgICAwXG4gICAgKTtcbn1cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5leHBvcnQgZnVuY3Rpb24gcGFyc2VSZW5kZXJJdGVtVG9QaXhlbHMocmVuZGVySXRlbTogS3RkR3JpZEl0ZW1SZW5kZXJEYXRhPG51bWJlcj4pOiBLdGRHcmlkSXRlbVJlbmRlckRhdGE8c3RyaW5nPiB7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgaWQ6IHJlbmRlckl0ZW0uaWQsXG4gICAgICAgIHRvcDogYCR7cmVuZGVySXRlbS50b3B9cHhgLFxuICAgICAgICBsZWZ0OiBgJHtyZW5kZXJJdGVtLmxlZnR9cHhgLFxuICAgICAgICB3aWR0aDogYCR7cmVuZGVySXRlbS53aWR0aH1weGAsXG4gICAgICAgIGhlaWdodDogYCR7cmVuZGVySXRlbS5oZWlnaHR9cHhgXG4gICAgfTtcbn1cblxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG5leHBvcnQgZnVuY3Rpb24gX19ncmlkSXRlbUdldFJlbmRlckRhdGFGYWN0b3J5RnVuYyhncmlkQ21wOiBLdGRHcmlkQ29tcG9uZW50KSB7XG4gICAgcmV0dXJuIGZ1bmN0aW9uIChpZDogc3RyaW5nKSB7XG4gICAgICAgIHJldHVybiBwYXJzZVJlbmRlckl0ZW1Ub1BpeGVscyhncmlkQ21wLmdldEl0ZW1SZW5kZXJEYXRhKGlkKSk7XG4gICAgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGt0ZEdyaWRJdGVtR2V0UmVuZGVyRGF0YUZhY3RvcnlGdW5jKGdyaWRDbXA6IEt0ZEdyaWRDb21wb25lbnQpOiBhbnkge1xuICAgIC8vIFdvcmthcm91bmQgZXhwbGFpbmVkOiBodHRwczovL2dpdGh1Yi5jb20vbmctcGFja2Fnci9uZy1wYWNrYWdyL2lzc3Vlcy82OTYjaXNzdWVjb21tZW50LTM4NzExNDYxM1xuICAgIGNvbnN0IHJlc3VsdEZ1bmMgPSBfX2dyaWRJdGVtR2V0UmVuZGVyRGF0YUZhY3RvcnlGdW5jKGdyaWRDbXApO1xuICAgIHJldHVybiByZXN1bHRGdW5jO1xufVxuXG5jb25zdCBkZWZhdWx0QmFja2dyb3VuZENvbmZpZzogUmVxdWlyZWQ8T21pdDxLdGRHcmlkQmFja2dyb3VuZENmZywgJ3Nob3cnPj4gPSB7XG4gICAgYm9yZGVyQ29sb3I6ICcjZmZhNzI2NzgnLFxuICAgIGdhcENvbG9yOiAndHJhbnNwYXJlbnQnLFxuICAgIHJvd0NvbG9yOiAndHJhbnNwYXJlbnQnLFxuICAgIGNvbHVtbkNvbG9yOiAndHJhbnNwYXJlbnQnLFxuICAgIGJvcmRlcldpZHRoOiAxXG59O1xuXG5AQ29tcG9uZW50KHtcbiAgICBzZWxlY3RvcjogJ2J1dy1ncmlkJyxcbiAgICB0ZW1wbGF0ZVVybDogJy4vZ3JpZC5jb21wb25lbnQuaHRtbCcsXG4gICAgc3R5bGVVcmxzOiBbJy4vZ3JpZC5jb21wb25lbnQuc2NzcyddLFxuICAgIGVuY2Fwc3VsYXRpb246IFZpZXdFbmNhcHN1bGF0aW9uLk5vbmUsXG4gICAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICAgIHByb3ZpZGU6IEdSSURfSVRFTV9HRVRfUkVOREVSX0RBVEFfVE9LRU4sXG4gICAgICAgICAgICB1c2VGYWN0b3J5OiBrdGRHcmlkSXRlbUdldFJlbmRlckRhdGFGYWN0b3J5RnVuYyxcbiAgICAgICAgICAgIGRlcHM6IFtLdGRHcmlkQ29tcG9uZW50XVxuICAgICAgICB9XG4gICAgXVxufSlcbmV4cG9ydCBjbGFzcyBLdGRHcmlkQ29tcG9uZW50IGltcGxlbWVudHMgT25DaGFuZ2VzLCBBZnRlckNvbnRlbnRJbml0LCBBZnRlckNvbnRlbnRDaGVja2VkLCBPbkRlc3Ryb3kge1xuICAgIC8qKiBRdWVyeSBsaXN0IG9mIGdyaWQgaXRlbXMgdGhhdCBhcmUgYmVpbmcgcmVuZGVyZWQuICovXG4gICAgQENvbnRlbnRDaGlsZHJlbihLdGRHcmlkSXRlbUNvbXBvbmVudCwgeyBkZXNjZW5kYW50czogdHJ1ZSB9KSBfZ3JpZEl0ZW1zOiBRdWVyeUxpc3Q8S3RkR3JpZEl0ZW1Db21wb25lbnQ+O1xuXG4gICAgLyoqIEVtaXRzIHdoZW4gbGF5b3V0IGNoYW5nZSAqL1xuICAgIEBPdXRwdXQoKSBsYXlvdXRVcGRhdGVkOiBFdmVudEVtaXR0ZXI8S3RkR3JpZExheW91dD4gPSBuZXcgRXZlbnRFbWl0dGVyPEt0ZEdyaWRMYXlvdXQ+KCk7XG5cbiAgICAvKiogRW1pdHMgd2hlbiBkcmFnIHN0YXJ0cyAqL1xuICAgIEBPdXRwdXQoKSBkcmFnU3RhcnRlZDogRXZlbnRFbWl0dGVyPEt0ZERyYWdTdGFydD4gPSBuZXcgRXZlbnRFbWl0dGVyPEt0ZERyYWdTdGFydD4oKTtcblxuICAgIC8qKiBFbWl0cyB3aGVuIHJlc2l6ZSBzdGFydHMgKi9cbiAgICBAT3V0cHV0KCkgcmVzaXplU3RhcnRlZDogRXZlbnRFbWl0dGVyPEt0ZFJlc2l6ZVN0YXJ0PiA9IG5ldyBFdmVudEVtaXR0ZXI8S3RkUmVzaXplU3RhcnQ+KCk7XG5cbiAgICAvKiogRW1pdHMgd2hlbiBkcmFnIGVuZHMgKi9cbiAgICBAT3V0cHV0KCkgZHJhZ0VuZGVkOiBFdmVudEVtaXR0ZXI8S3RkRHJhZ0VuZD4gPSBuZXcgRXZlbnRFbWl0dGVyPEt0ZERyYWdFbmQ+KCk7XG5cbiAgICAvKiogRW1pdHMgd2hlbiByZXNpemUgZW5kcyAqL1xuICAgIEBPdXRwdXQoKSByZXNpemVFbmRlZDogRXZlbnRFbWl0dGVyPEt0ZFJlc2l6ZUVuZD4gPSBuZXcgRXZlbnRFbWl0dGVyPEt0ZFJlc2l6ZUVuZD4oKTtcblxuICAgIC8qKiBFbWl0cyB3aGVuIGEgZ3JpZCBpdGVtIGlzIGJlaW5nIHJlc2l6ZWQgYW5kIGl0cyBib3VuZHMgaGF2ZSBjaGFuZ2VkICovXG4gICAgQE91dHB1dCgpIGdyaWRJdGVtUmVzaXplOiBFdmVudEVtaXR0ZXI8S3RkR3JpZEl0ZW1SZXNpemVFdmVudD4gPSBuZXcgRXZlbnRFbWl0dGVyPEt0ZEdyaWRJdGVtUmVzaXplRXZlbnQ+KCk7XG5cbiAgICAvKipcbiAgICAgKiBQYXJlbnQgZWxlbWVudCB0aGF0IGNvbnRhaW5zIHRoZSBzY3JvbGwuIElmIGFuIHN0cmluZyBpcyBwcm92aWRlZCBpdCB3b3VsZCBzZWFyY2ggdGhhdCBlbGVtZW50IGJ5IGlkIG9uIHRoZSBkb20uXG4gICAgICogSWYgbm8gZGF0YSBwcm92aWRlZCBvciBudWxsIGF1dG9zY3JvbGwgaXMgbm90IHBlcmZvcm1lZC5cbiAgICAgKi9cbiAgICBASW5wdXQoKSBzY3JvbGxhYmxlUGFyZW50OiBIVE1MRWxlbWVudCB8IERvY3VtZW50IHwgc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgICAvKiogV2hldGhlciBvciBub3QgdG8gdXBkYXRlIHRoZSBpbnRlcm5hbCBsYXlvdXQgd2hlbiBzb21lIGRlcGVuZGVudCBwcm9wZXJ0eSBjaGFuZ2UuICovXG4gICAgQElucHV0KClcbiAgICBnZXQgY29tcGFjdE9uUHJvcHNDaGFuZ2UoKTogYm9vbGVhbiB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb21wYWN0T25Qcm9wc0NoYW5nZTtcbiAgICB9XG5cbiAgICBzZXQgY29tcGFjdE9uUHJvcHNDaGFuZ2UodmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5fY29tcGFjdE9uUHJvcHNDaGFuZ2UgPSBjb2VyY2VCb29sZWFuUHJvcGVydHkodmFsdWUpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2NvbXBhY3RPblByb3BzQ2hhbmdlID0gdHJ1ZTtcblxuICAgIC8qKiBJZiB0cnVlLCBncmlkIGl0ZW1zIHdvbid0IGNoYW5nZSBwb3NpdGlvbiB3aGVuIGJlaW5nIGRyYWdnZWQgb3Zlci4gSGFuZHkgd2hlbiB1c2luZyBubyBjb21wYWN0aW9uICovXG4gICAgQElucHV0KClcbiAgICBnZXQgcHJldmVudENvbGxpc2lvbigpOiBib29sZWFuIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3ByZXZlbnRDb2xsaXNpb247XG4gICAgfVxuXG4gICAgc2V0IHByZXZlbnRDb2xsaXNpb24odmFsdWU6IGJvb2xlYW4pIHtcbiAgICAgICAgdGhpcy5fcHJldmVudENvbGxpc2lvbiA9IGNvZXJjZUJvb2xlYW5Qcm9wZXJ0eSh2YWx1ZSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfcHJldmVudENvbGxpc2lvbiA9IGZhbHNlO1xuXG4gICAgLyoqIE51bWJlciBvZiBDU1MgcGl4ZWxzIHRoYXQgd291bGQgYmUgc2Nyb2xsZWQgb24gZWFjaCAndGljaycgd2hlbiBhdXRvIHNjcm9sbCBpcyBwZXJmb3JtZWQuICovXG4gICAgQElucHV0KClcbiAgICBnZXQgc2Nyb2xsU3BlZWQoKTogbnVtYmVyIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3Njcm9sbFNwZWVkO1xuICAgIH1cblxuICAgIHNldCBzY3JvbGxTcGVlZCh2YWx1ZTogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuX3Njcm9sbFNwZWVkID0gY29lcmNlTnVtYmVyUHJvcGVydHkodmFsdWUsIDIpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX3Njcm9sbFNwZWVkID0gMjtcblxuICAgIC8qKiBUeXBlIG9mIGNvbXBhY3Rpb24gdGhhdCB3aWxsIGJlIGFwcGxpZWQgdG8gdGhlIGxheW91dCAodmVydGljYWwsIGhvcml6b250YWwgb3IgZnJlZSkuIERlZmF1bHRzIHRvICd2ZXJ0aWNhbCcgKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCBjb21wYWN0VHlwZSgpOiBLdGRHcmlkQ29tcGFjdFR5cGUge1xuICAgICAgICByZXR1cm4gdGhpcy5fY29tcGFjdFR5cGU7XG4gICAgfVxuXG4gICAgc2V0IGNvbXBhY3RUeXBlKHZhbDogS3RkR3JpZENvbXBhY3RUeXBlKSB7XG4gICAgICAgIHRoaXMuX2NvbXBhY3RUeXBlID0gdmFsO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2NvbXBhY3RUeXBlOiBLdGRHcmlkQ29tcGFjdFR5cGUgPSAndmVydGljYWwnO1xuXG4gICAgLyoqXG4gICAgICogUm93IGhlaWdodCBhcyBudW1iZXIgb3IgYXMgJ2ZpdCcuXG4gICAgICogSWYgcm93SGVpZ2h0IGlzIGEgbnVtYmVyIHZhbHVlLCBpdCBtZWFucyB0aGF0IGVhY2ggcm93IHdvdWxkIGhhdmUgdGhvc2UgY3NzIHBpeGVscyBpbiBoZWlnaHQuXG4gICAgICogaWYgcm93SGVpZ2h0IGlzICdmaXQnLCBpdCBtZWFucyB0aGF0IHJvd3Mgd2lsbCBmaXQgaW4gdGhlIGhlaWdodCBhdmFpbGFibGUuIElmICdmaXQnIHZhbHVlIGlzIHNldCwgYSAnaGVpZ2h0JyBzaG91bGQgYmUgYWxzbyBwcm92aWRlZC5cbiAgICAgKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCByb3dIZWlnaHQoKTogbnVtYmVyIHwgJ2ZpdCcge1xuICAgICAgICByZXR1cm4gdGhpcy5fcm93SGVpZ2h0O1xuICAgIH1cblxuICAgIHNldCByb3dIZWlnaHQodmFsOiBudW1iZXIgfCAnZml0Jykge1xuICAgICAgICB0aGlzLl9yb3dIZWlnaHQgPSB2YWwgPT09ICdmaXQnID8gdmFsIDogTWF0aC5tYXgoMSwgTWF0aC5yb3VuZChjb2VyY2VOdW1iZXJQcm9wZXJ0eSh2YWwpKSk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfcm93SGVpZ2h0OiBudW1iZXIgfCAnZml0JyA9IDEwMDtcblxuICAgIC8qKiBOdW1iZXIgb2YgY29sdW1ucyAgKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCBjb2xzKCk6IG51bWJlciB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jb2xzO1xuICAgIH1cblxuICAgIHNldCBjb2xzKHZhbDogbnVtYmVyKSB7XG4gICAgICAgIHRoaXMuX2NvbHMgPSBNYXRoLm1heCgxLCBNYXRoLnJvdW5kKGNvZXJjZU51bWJlclByb3BlcnR5KHZhbCkpKTtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9jb2xzID0gNjtcblxuICAgIC8qKiBMYXlvdXQgb2YgdGhlIGdyaWQuIEFycmF5IG9mIGFsbCB0aGUgZ3JpZCBpdGVtcyB3aXRoIGl0cyAnaWQnIGFuZCBwb3NpdGlvbiBvbiB0aGUgZ3JpZC4gKi9cbiAgICBASW5wdXQoKVxuICAgIGdldCBsYXlvdXQoKTogS3RkR3JpZExheW91dCB7XG4gICAgICAgIHJldHVybiB0aGlzLl9sYXlvdXQ7XG4gICAgfVxuXG4gICAgc2V0IGxheW91dChsYXlvdXQ6IEt0ZEdyaWRMYXlvdXQpIHtcbiAgICAgICAgLyoqXG4gICAgICAgICAqIEVuaGFuY2VtZW50OlxuICAgICAgICAgKiBPbmx5IHNldCBsYXlvdXQgaWYgaXQncyByZWZlcmVuY2UgaGFzIGNoYW5nZWQgYW5kIHVzZSBhIGJvb2xlYW4gdG8gdHJhY2sgd2hlbmV2ZXIgcmVjYWxjdWxhdGUgdGhlIGxheW91dCBvbiBuZ09uQ2hhbmdlcy5cbiAgICAgICAgICpcbiAgICAgICAgICogV2h5OlxuICAgICAgICAgKiBUaGUgbm9ybWFsIHVzZSBvZiB0aGlzIGxpYiBpcyBoYXZpbmcgdGhlIHZhcmlhYmxlIGxheW91dCBpbiB0aGUgb3V0ZXIgY29tcG9uZW50IG9yIGluIGEgc3RvcmUsIGFzc2lnbmluZyBpdCB3aGVuZXZlciBpdCBjaGFuZ2VzIGFuZFxuICAgICAgICAgKiBiaW5kZWQgaW4gdGhlIGNvbXBvbmVudCB3aXRoIGl0J3MgaW5wdXQgW2xheW91dF0uIEluIHRoaXMgc2NlbmFyaW8sIHdlIHdvdWxkIGFsd2F5cyBjYWxjdWxhdGUgb25lIHVubmVjZXNzYXJ5IGNoYW5nZSBvbiB0aGUgbGF5b3V0IHdoZW5cbiAgICAgICAgICogaXQgaXMgcmUtYmluZGVkIG9uIHRoZSBpbnB1dC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuX2xheW91dCA9IGxheW91dDtcbiAgICB9XG5cbiAgICBwcml2YXRlIF9sYXlvdXQ6IEt0ZEdyaWRMYXlvdXQ7XG5cbiAgICAvKiogR3JpZCBnYXAgaW4gY3NzIHBpeGVscyAqL1xuICAgIEBJbnB1dCgpXG4gICAgZ2V0IGdhcCgpOiBudW1iZXIge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ2FwO1xuICAgIH1cblxuICAgIHNldCBnYXAodmFsOiBudW1iZXIpIHtcbiAgICAgICAgdGhpcy5fZ2FwID0gTWF0aC5tYXgoY29lcmNlTnVtYmVyUHJvcGVydHkodmFsKSwgMCk7XG4gICAgfVxuXG4gICAgcHJpdmF0ZSBfZ2FwID0gMDtcblxuICAgIC8qKlxuICAgICAqIElmIGhlaWdodCBpcyBhIG51bWJlciwgZml4ZXMgdGhlIGhlaWdodCBvZiB0aGUgZ3JpZCB0byBpdCwgcmVjb21tZW5kZWQgd2hlbiByb3dIZWlnaHQgPSAnZml0JyBpcyB1c2VkLlxuICAgICAqIElmIGhlaWdodCBpcyBudWxsLCBoZWlnaHQgd2lsbCBiZSBhdXRvbWF0aWNhbGx5IHNldCBhY2NvcmRpbmcgdG8gaXRzIGlubmVyIGdyaWQgaXRlbXMuXG4gICAgICogRGVmYXVsdHMgdG8gbnVsbC5cbiAgICAgKiAqL1xuICAgIEBJbnB1dCgpXG4gICAgZ2V0IGhlaWdodCgpOiBudW1iZXIgfCBudWxsIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2hlaWdodDtcbiAgICB9XG5cbiAgICBzZXQgaGVpZ2h0KHZhbDogbnVtYmVyIHwgbnVsbCkge1xuICAgICAgICB0aGlzLl9oZWlnaHQgPSB0eXBlb2YgdmFsID09PSAnbnVtYmVyJyA/IE1hdGgubWF4KHZhbCwgMCkgOiBudWxsO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2hlaWdodDogbnVtYmVyIHwgbnVsbCA9IG51bGw7XG5cbiAgICBASW5wdXQoKVxuICAgIGdldCBiYWNrZ3JvdW5kQ29uZmlnKCk6IEt0ZEdyaWRCYWNrZ3JvdW5kQ2ZnIHwgbnVsbCB7XG4gICAgICAgIHJldHVybiB0aGlzLl9iYWNrZ3JvdW5kQ29uZmlnO1xuICAgIH1cblxuICAgIHNldCBiYWNrZ3JvdW5kQ29uZmlnKHZhbDogS3RkR3JpZEJhY2tncm91bmRDZmcgfCBudWxsKSB7XG4gICAgICAgIHRoaXMuX2JhY2tncm91bmRDb25maWcgPSB2YWw7XG5cbiAgICAgICAgLy8gSWYgdGhlcmUgaXMgYmFja2dyb3VuZCBjb25maWd1cmF0aW9uLCBhZGQgbWFpbiBncmlkIGJhY2tncm91bmQgY2xhc3MuIEdyaWQgYmFja2dyb3VuZCBjbGFzcyBjb21lcyB3aXRoIG9wYWNpdHkgMC5cbiAgICAgICAgLy8gSXQgaXMgZG9uZSB0aGlzIHdheSBmb3IgYWRkaW5nIG9wYWNpdHkgYW5pbWF0aW9uIGFuZCB0byBkb24ndCBhZGQgYW55IHN0eWxlcyB3aGVuIGdyaWQgYmFja2dyb3VuZCBpcyBudWxsLlxuICAgICAgICBjb25zdCBjbGFzc0xpc3QgPSAodGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTERpdkVsZW1lbnQpLmNsYXNzTGlzdDtcbiAgICAgICAgdGhpcy5fYmFja2dyb3VuZENvbmZpZyAhPT0gbnVsbFxuICAgICAgICAgICAgPyBjbGFzc0xpc3QuYWRkKCdidXctZ3JpZC1iYWNrZ3JvdW5kJylcbiAgICAgICAgICAgIDogY2xhc3NMaXN0LnJlbW92ZSgnYnV3LWdyaWQtYmFja2dyb3VuZCcpO1xuXG4gICAgICAgIC8vIFNldCBiYWNrZ3JvdW5kIHZpc2liaWxpdHlcbiAgICAgICAgdGhpcy5zZXRHcmlkQmFja2dyb3VuZFZpc2libGUodGhpcy5fYmFja2dyb3VuZENvbmZpZz8uc2hvdyA9PT0gJ2Fsd2F5cycpO1xuICAgIH1cblxuICAgIHByaXZhdGUgX2JhY2tncm91bmRDb25maWc6IEt0ZEdyaWRCYWNrZ3JvdW5kQ2ZnIHwgbnVsbCA9IG51bGw7XG5cbiAgICBwcml2YXRlIGdyaWRDdXJyZW50SGVpZ2h0OiBudW1iZXI7XG5cbiAgICBnZXQgY29uZmlnKCk6IEt0ZEdyaWRDZmcge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgY29sczogdGhpcy5jb2xzLFxuICAgICAgICAgICAgcm93SGVpZ2h0OiB0aGlzLnJvd0hlaWdodCxcbiAgICAgICAgICAgIGhlaWdodDogdGhpcy5oZWlnaHQsXG4gICAgICAgICAgICBsYXlvdXQ6IHRoaXMubGF5b3V0LFxuICAgICAgICAgICAgcHJldmVudENvbGxpc2lvbjogdGhpcy5wcmV2ZW50Q29sbGlzaW9uLFxuICAgICAgICAgICAgZ2FwOiB0aGlzLmdhcFxuICAgICAgICB9O1xuICAgIH1cblxuICAgIC8qKiBSZWZlcmVuY2UgdG8gdGhlIHZpZXcgb2YgdGhlIHBsYWNlaG9sZGVyIGVsZW1lbnQuICovXG4gICAgcHJpdmF0ZSBwbGFjZWhvbGRlclJlZjogRW1iZWRkZWRWaWV3UmVmPGFueT4gfCBudWxsO1xuXG4gICAgLyoqIEVsZW1lbnQgdGhhdCBpcyByZW5kZXJlZCBhcyBwbGFjZWhvbGRlciB3aGVuIGEgZ3JpZCBpdGVtIGlzIGJlaW5nIGRyYWdnZWQgKi9cbiAgICBwcml2YXRlIHBsYWNlaG9sZGVyOiBIVE1MRWxlbWVudCB8IG51bGw7XG5cbiAgICBwcml2YXRlIF9ncmlkSXRlbXNSZW5kZXJEYXRhOiBLdGREaWN0aW9uYXJ5PEt0ZEdyaWRJdGVtUmVuZGVyRGF0YTxudW1iZXI+PjtcbiAgICBwcml2YXRlIHN1YnNjcmlwdGlvbnM6IFN1YnNjcmlwdGlvbltdID0gW107XG5cbiAgICBjb25zdHJ1Y3RvcihcbiAgICAgICAgcHJpdmF0ZSBncmlkU2VydmljZTogS3RkR3JpZFNlcnZpY2UsXG4gICAgICAgIHByaXZhdGUgZWxlbWVudFJlZjogRWxlbWVudFJlZixcbiAgICAgICAgcHJpdmF0ZSB2aWV3Q29udGFpbmVyUmVmOiBWaWV3Q29udGFpbmVyUmVmLFxuICAgICAgICBwcml2YXRlIHJlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICAgICAgIHByaXZhdGUgbmdab25lOiBOZ1pvbmVcbiAgICApIHt9XG5cbiAgICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XG4gICAgICAgIGlmICh0aGlzLnJvd0hlaWdodCA9PT0gJ2ZpdCcgJiYgdGhpcy5oZWlnaHQgPT0gbnVsbCkge1xuICAgICAgICAgICAgY29uc29sZS53YXJuKGBLdGRHcmlkQ29tcG9uZW50OiBUaGUgQElucHV0KCkgaGVpZ2h0IHNob3VsZCBub3QgYmUgbnVsbCB3aGVuIHVzaW5nIHJvd0hlaWdodCAnZml0J2ApO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5lZWRzQ29tcGFjdExheW91dCA9IGZhbHNlO1xuICAgICAgICBsZXQgbmVlZHNSZWNhbGN1bGF0ZVJlbmRlckRhdGEgPSBmYWxzZTtcblxuICAgICAgICAvLyBUT0RPOiBEb2VzIGZpc3QgY2hhbmdlIG5lZWQgdG8gYmUgY29tcGFjdGVkIGJ5IGRlZmF1bHQ/XG4gICAgICAgIC8vIENvbXBhY3QgbGF5b3V0IHdoZW5ldmVyIHNvbWUgZGVwZW5kZW50IHByb3AgY2hhbmdlcy5cbiAgICAgICAgaWYgKGNoYW5nZXMuY29tcGFjdFR5cGUgfHwgY2hhbmdlcy5jb2xzIHx8IGNoYW5nZXMubGF5b3V0KSB7XG4gICAgICAgICAgICBuZWVkc0NvbXBhY3RMYXlvdXQgPSB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgd2VlIG5lZWQgdG8gcmVjYWxjdWxhdGUgcmVuZGVyaW5nIGRhdGEuXG4gICAgICAgIGlmIChuZWVkc0NvbXBhY3RMYXlvdXQgfHwgY2hhbmdlcy5yb3dIZWlnaHQgfHwgY2hhbmdlcy5oZWlnaHQgfHwgY2hhbmdlcy5nYXAgfHwgY2hhbmdlcy5iYWNrZ3JvdW5kQ29uZmlnKSB7XG4gICAgICAgICAgICBuZWVkc1JlY2FsY3VsYXRlUmVuZGVyRGF0YSA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBPbmx5IGNvbXBhY3QgbGF5b3V0IGlmIGxpYiB1c2VyIGhhcyBwcm92aWRlZCBpdC4gTGliIHVzZXJzIHRoYXQgd2FudCB0byBzYXZlL3N0b3JlIGFsd2F5cyB0aGUgc2FtZSBsYXlvdXQgIGFzIGl0IGlzIHJlcHJlc2VudGVkIChjb21wYWN0ZWQpXG4gICAgICAgIC8vIGNhbiB1c2UgS3RkQ29tcGFjdEdyaWQgdXRpbGl0eSBhbmQgcHJlLWNvbXBhY3QgdGhlIGxheW91dC4gVGhpcyBpcyB0aGUgcmVjb21tZW5kZWQgYmVoYXZpb3VyIGZvciBhbHdheXMgaGF2aW5nIGEgdGhlIHNhbWUgbGF5b3V0IG9uIHRoaXMgY29tcG9uZW50XG4gICAgICAgIC8vIGFuZCB0aGUgb25lcyB0aGF0IHVzZXMgaXQuXG4gICAgICAgIGlmIChuZWVkc0NvbXBhY3RMYXlvdXQgJiYgdGhpcy5jb21wYWN0T25Qcm9wc0NoYW5nZSkge1xuICAgICAgICAgICAgdGhpcy5jb21wYWN0TGF5b3V0KCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAobmVlZHNSZWNhbGN1bGF0ZVJlbmRlckRhdGEpIHtcbiAgICAgICAgICAgIHRoaXMuY2FsY3VsYXRlUmVuZGVyRGF0YSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmluaXRTdWJzY3JpcHRpb25zKCk7XG4gICAgfVxuXG4gICAgbmdBZnRlckNvbnRlbnRDaGVja2VkKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnJlbmRlcigpO1xuICAgIH1cblxuICAgIHJlc2l6ZSgpOiB2b2lkIHtcbiAgICAgICAgdGhpcy5jYWxjdWxhdGVSZW5kZXJEYXRhKCk7XG4gICAgICAgIHRoaXMucmVuZGVyKCk7XG4gICAgfVxuXG4gICAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgICAgIHRoaXMuc3Vic2NyaXB0aW9ucy5mb3JFYWNoKChzdWIpID0+IHN1Yi51bnN1YnNjcmliZSgpKTtcbiAgICB9XG5cbiAgICBjb21wYWN0TGF5b3V0KCk6IHZvaWQge1xuICAgICAgICB0aGlzLmxheW91dCA9IGNvbXBhY3QodGhpcy5sYXlvdXQsIHRoaXMuY29tcGFjdFR5cGUsIHRoaXMuY29scyk7XG4gICAgfVxuXG4gICAgZ2V0SXRlbXNSZW5kZXJEYXRhKCk6IEt0ZERpY3Rpb25hcnk8S3RkR3JpZEl0ZW1SZW5kZXJEYXRhPG51bWJlcj4+IHtcbiAgICAgICAgcmV0dXJuIHsgLi4udGhpcy5fZ3JpZEl0ZW1zUmVuZGVyRGF0YSB9O1xuICAgIH1cblxuICAgIGdldEl0ZW1SZW5kZXJEYXRhKGl0ZW1JZDogc3RyaW5nKTogS3RkR3JpZEl0ZW1SZW5kZXJEYXRhPG51bWJlcj4ge1xuICAgICAgICByZXR1cm4gdGhpcy5fZ3JpZEl0ZW1zUmVuZGVyRGF0YVtpdGVtSWRdO1xuICAgIH1cblxuICAgIGNhbGN1bGF0ZVJlbmRlckRhdGEoKTogdm9pZCB7XG4gICAgICAgIGNvbnN0IGNsaWVudFJlY3QgPSAodGhpcy5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQgYXMgSFRNTEVsZW1lbnQpLmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgICB0aGlzLmdyaWRDdXJyZW50SGVpZ2h0ID1cbiAgICAgICAgICAgIHRoaXMuaGVpZ2h0ID8/XG4gICAgICAgICAgICAodGhpcy5yb3dIZWlnaHQgPT09ICdmaXQnID8gY2xpZW50UmVjdC5oZWlnaHQgOiBnZXRHcmlkSGVpZ2h0KHRoaXMubGF5b3V0LCB0aGlzLnJvd0hlaWdodCwgdGhpcy5nYXApKTtcbiAgICAgICAgdGhpcy5fZ3JpZEl0ZW1zUmVuZGVyRGF0YSA9IGxheW91dFRvUmVuZGVySXRlbXModGhpcy5jb25maWcsIGNsaWVudFJlY3Qud2lkdGgsIHRoaXMuZ3JpZEN1cnJlbnRIZWlnaHQpO1xuXG4gICAgICAgIC8vIFNldCBCYWNrZ3JvdW5kIENTUyB2YXJpYWJsZXNcbiAgICAgICAgdGhpcy5zZXRCYWNrZ3JvdW5kQ3NzVmFyaWFibGVzKGdldFJvd0hlaWdodEluUGl4ZWxzKHRoaXMuY29uZmlnLCB0aGlzLmdyaWRDdXJyZW50SGVpZ2h0KSk7XG4gICAgfVxuXG4gICAgcmVuZGVyKCk6IHZvaWQge1xuICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAnaGVpZ2h0JywgYCR7dGhpcy5ncmlkQ3VycmVudEhlaWdodH1weGApO1xuICAgICAgICB0aGlzLnVwZGF0ZUdyaWRJdGVtc1N0eWxlcygpO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2V0QmFja2dyb3VuZENzc1ZhcmlhYmxlcyhyb3dIZWlnaHQ6IG51bWJlcik6IHZvaWQge1xuICAgICAgICBjb25zdCBzdHlsZSA9ICh0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRGl2RWxlbWVudCkuc3R5bGU7XG5cbiAgICAgICAgaWYgKHRoaXMuX2JhY2tncm91bmRDb25maWcpIHtcbiAgICAgICAgICAgIC8vIHN0cnVjdHVyZVxuICAgICAgICAgICAgc3R5bGUuc2V0UHJvcGVydHkoJy0tZ2FwJywgdGhpcy5nYXAgKyAncHgnKTtcbiAgICAgICAgICAgIHN0eWxlLnNldFByb3BlcnR5KCctLXJvdy1oZWlnaHQnLCByb3dIZWlnaHQgKyAncHgnKTtcbiAgICAgICAgICAgIHN0eWxlLnNldFByb3BlcnR5KCctLWNvbHVtbnMnLCBgJHt0aGlzLmNvbHN9YCk7XG4gICAgICAgICAgICBzdHlsZS5zZXRQcm9wZXJ0eShcbiAgICAgICAgICAgICAgICAnLS1ib3JkZXItd2lkdGgnLFxuICAgICAgICAgICAgICAgICh0aGlzLl9iYWNrZ3JvdW5kQ29uZmlnLmJvcmRlcldpZHRoID8/IGRlZmF1bHRCYWNrZ3JvdW5kQ29uZmlnLmJvcmRlcldpZHRoKSArICdweCdcbiAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgIC8vIGNvbG9yc1xuICAgICAgICAgICAgc3R5bGUuc2V0UHJvcGVydHkoXG4gICAgICAgICAgICAgICAgJy0tYm9yZGVyLWNvbG9yJyxcbiAgICAgICAgICAgICAgICB0aGlzLl9iYWNrZ3JvdW5kQ29uZmlnLmJvcmRlckNvbG9yID8/IGRlZmF1bHRCYWNrZ3JvdW5kQ29uZmlnLmJvcmRlckNvbG9yXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgc3R5bGUuc2V0UHJvcGVydHkoJy0tZ2FwLWNvbG9yJywgdGhpcy5fYmFja2dyb3VuZENvbmZpZy5nYXBDb2xvciA/PyBkZWZhdWx0QmFja2dyb3VuZENvbmZpZy5nYXBDb2xvcik7XG4gICAgICAgICAgICBzdHlsZS5zZXRQcm9wZXJ0eSgnLS1yb3ctY29sb3InLCB0aGlzLl9iYWNrZ3JvdW5kQ29uZmlnLnJvd0NvbG9yID8/IGRlZmF1bHRCYWNrZ3JvdW5kQ29uZmlnLnJvd0NvbG9yKTtcbiAgICAgICAgICAgIHN0eWxlLnNldFByb3BlcnR5KFxuICAgICAgICAgICAgICAgICctLWNvbHVtbi1jb2xvcicsXG4gICAgICAgICAgICAgICAgdGhpcy5fYmFja2dyb3VuZENvbmZpZy5jb2x1bW5Db2xvciA/PyBkZWZhdWx0QmFja2dyb3VuZENvbmZpZy5jb2x1bW5Db2xvclxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0eWxlLnJlbW92ZVByb3BlcnR5KCctLWdhcCcpO1xuICAgICAgICAgICAgc3R5bGUucmVtb3ZlUHJvcGVydHkoJy0tcm93LWhlaWdodCcpO1xuICAgICAgICAgICAgc3R5bGUucmVtb3ZlUHJvcGVydHkoJy0tY29sdW1ucycpO1xuICAgICAgICAgICAgc3R5bGUucmVtb3ZlUHJvcGVydHkoJy0tYm9yZGVyLXdpZHRoJyk7XG4gICAgICAgICAgICBzdHlsZS5yZW1vdmVQcm9wZXJ0eSgnLS1ib3JkZXItY29sb3InKTtcbiAgICAgICAgICAgIHN0eWxlLnJlbW92ZVByb3BlcnR5KCctLWdhcC1jb2xvcicpO1xuICAgICAgICAgICAgc3R5bGUucmVtb3ZlUHJvcGVydHkoJy0tcm93LWNvbG9yJyk7XG4gICAgICAgICAgICBzdHlsZS5yZW1vdmVQcm9wZXJ0eSgnLS1jb2x1bW4tY29sb3InKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIHByaXZhdGUgdXBkYXRlR3JpZEl0ZW1zU3R5bGVzKCk6IHZvaWQge1xuICAgICAgICB0aGlzLl9ncmlkSXRlbXMuZm9yRWFjaCgoaXRlbSkgPT4ge1xuICAgICAgICAgICAgY29uc3QgZ3JpZEl0ZW1SZW5kZXJEYXRhOiBLdGRHcmlkSXRlbVJlbmRlckRhdGE8bnVtYmVyPiB8IHVuZGVmaW5lZCA9IHRoaXMuX2dyaWRJdGVtc1JlbmRlckRhdGFbaXRlbS5pZF07XG4gICAgICAgICAgICBpZiAoZ3JpZEl0ZW1SZW5kZXJEYXRhID09IG51bGwpIHtcbiAgICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKGBDb3VsZG4ndCBmaW5kIHRoZSBzcGVjaWZpZWQgZ3JpZCBpdGVtIGZvciB0aGUgaWQ6ICR7aXRlbS5pZH1gKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaXRlbS5zZXRTdHlsZXMocGFyc2VSZW5kZXJJdGVtVG9QaXhlbHMoZ3JpZEl0ZW1SZW5kZXJEYXRhKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIHByaXZhdGUgc2V0R3JpZEJhY2tncm91bmRWaXNpYmxlKHZpc2libGU6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAgICAgY29uc3QgY2xhc3NMaXN0ID0gKHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50IGFzIEhUTUxEaXZFbGVtZW50KS5jbGFzc0xpc3Q7XG4gICAgICAgIHZpc2libGUgPyBjbGFzc0xpc3QuYWRkKCdidXctZ3JpZC1iYWNrZ3JvdW5kLXZpc2libGUnKSA6IGNsYXNzTGlzdC5yZW1vdmUoJ2J1dy1ncmlkLWJhY2tncm91bmQtdmlzaWJsZScpO1xuICAgIH1cblxuICAgIHByaXZhdGUgaW5pdFN1YnNjcmlwdGlvbnMoKTogYW55IHtcbiAgICAgICAgdGhpcy5zdWJzY3JpcHRpb25zID0gW1xuICAgICAgICAgICAgdGhpcy5fZ3JpZEl0ZW1zLmNoYW5nZXNcbiAgICAgICAgICAgICAgICAucGlwZShcbiAgICAgICAgICAgICAgICAgICAgc3RhcnRXaXRoKHRoaXMuX2dyaWRJdGVtcyksXG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaE1hcCgoZ3JpZEl0ZW1zOiBRdWVyeUxpc3Q8S3RkR3JpZEl0ZW1Db21wb25lbnQ+KSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgbWVyZ2UoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uZ3JpZEl0ZW1zLm1hcCgoZ3JpZEl0ZW0pID0+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyaWRJdGVtLmRyYWdTdGFydCQucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcCgoZXZlbnQpID0+ICh7IGV2ZW50LCBncmlkSXRlbSwgdHlwZTogJ2RyYWcnIGFzIERyYWdBY3Rpb25UeXBlIH0pKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5ncmlkSXRlbXMubWFwKChncmlkSXRlbSkgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JpZEl0ZW0ucmVzaXplU3RhcnQkLnBpcGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXAoKGV2ZW50KSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV2ZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyaWRJdGVtLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU6ICdyZXNpemUnIGFzIERyYWdBY3Rpb25UeXBlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgICAgICkucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGhhdXN0TWFwKCh7IGV2ZW50LCBncmlkSXRlbSwgdHlwZSB9KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVtaXQgZHJhZyBvciByZXNpemUgc3RhcnQgZXZlbnRzLiBFbnN1cmUgdGhhdCBpcyBzdGFydCBldmVudCBpcyBpbnNpZGUgdGhlIHpvbmUuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMubmdab25lLnJ1bigoKSA9PlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHR5cGUgPT09ICdkcmFnJyA/IHRoaXMuZHJhZ1N0YXJ0ZWQgOiB0aGlzLnJlc2l6ZVN0YXJ0ZWQpLmVtaXQoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2V0RHJhZ1Jlc2l6ZUV2ZW50RGF0YShncmlkSXRlbSwgdGhpcy5sYXlvdXQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRHcmlkQmFja2dyb3VuZFZpc2libGUoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9iYWNrZ3JvdW5kQ29uZmlnPy5zaG93ID09PSAnd2hlbkRyYWdnaW5nJyB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2JhY2tncm91bmRDb25maWc/LnNob3cgPT09ICdhbHdheXMnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUGVyZm9ybSBkcmFnIHNlcXVlbmNlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLnBlcmZvcm1EcmFnU2VxdWVuY2UkKGdyaWRJdGVtLCBldmVudCwgdHlwZSkucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcCgobGF5b3V0KSA9PiAoeyBsYXlvdXQsIGdyaWRJdGVtLCB0eXBlIH0pKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgLnN1YnNjcmliZSgoeyBsYXlvdXQsIGdyaWRJdGVtLCB0eXBlIH0pID0+IHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sYXlvdXQgPSBsYXlvdXQ7XG4gICAgICAgICAgICAgICAgICAgIC8vIENhbGN1bGF0ZSBuZXcgcmVuZGVyaW5nIGRhdGEgZ2l2ZW4gdGhlIG5ldyBsYXlvdXQuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2FsY3VsYXRlUmVuZGVyRGF0YSgpO1xuICAgICAgICAgICAgICAgICAgICAvLyBFbWl0IGRyYWcgb3IgcmVzaXplIGVuZCBldmVudHMuXG4gICAgICAgICAgICAgICAgICAgICh0eXBlID09PSAnZHJhZycgPyB0aGlzLmRyYWdFbmRlZCA6IHRoaXMucmVzaXplRW5kZWQpLmVtaXQoXG4gICAgICAgICAgICAgICAgICAgICAgICBnZXREcmFnUmVzaXplRXZlbnREYXRhKGdyaWRJdGVtLCBsYXlvdXQpXG4gICAgICAgICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdGlmeSB0aGF0IHRoZSBsYXlvdXQgaGFzIGJlZW4gdXBkYXRlZC5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sYXlvdXRVcGRhdGVkLmVtaXQobGF5b3V0KTtcblxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldEdyaWRCYWNrZ3JvdW5kVmlzaWJsZSh0aGlzLl9iYWNrZ3JvdW5kQ29uZmlnPy5zaG93ID09PSAnYWx3YXlzJyk7XG4gICAgICAgICAgICAgICAgfSlcbiAgICAgICAgXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQZXJmb3JtIGEgZ2VuZXJhbCBncmlkIGRyYWcgYWN0aW9uLCBmcm9tIHN0YXJ0IHRvIGVuZC4gQSBnZW5lcmFsIGdyaWQgZHJhZyBhY3Rpb24gYmFzaWNhbGx5IGluY2x1ZGVzIGNyZWF0aW5nIHRoZSBwbGFjZWhvbGRlciBlbGVtZW50IGFuZCBhZGRpbmdcbiAgICAgKiBzb21lIGNsYXNzIGFuaW1hdGlvbnMuIGNhbGNOZXdTdGF0ZUZ1bmMgbmVlZHMgdG8gYmUgcHJvdmlkZWQgaW4gb3JkZXIgdG8gY2FsY3VsYXRlIHRoZSBuZXcgc3RhdGUgb2YgdGhlIGxheW91dC5cbiAgICAgKiBAcGFyYW0gZ3JpZEl0ZW0gdGhhdCBpcyBiZWVuIGRyYWdnZWRcbiAgICAgKiBAcGFyYW0gcG9pbnRlckRvd25FdmVudCBldmVudCAobW91c2Vkb3duIG9yIHRvdWNoZG93bikgd2hlcmUgdGhlIHVzZXIgaW5pdGlhdGVkIHRoZSBkcmFnXG4gICAgICogQHBhcmFtIGNhbGNOZXdTdGF0ZUZ1bmMgZnVuY3Rpb24gdGhhdCByZXR1cm4gdGhlIG5ldyBsYXlvdXQgc3RhdGUgYW5kIHRoZSBkcmFnIGVsZW1lbnQgcG9zaXRpb25cbiAgICAgKi9cbiAgICBwcml2YXRlIHBlcmZvcm1EcmFnU2VxdWVuY2UkKFxuICAgICAgICBncmlkSXRlbTogS3RkR3JpZEl0ZW1Db21wb25lbnQsXG4gICAgICAgIHBvaW50ZXJEb3duRXZlbnQ6IE1vdXNlRXZlbnQgfCBUb3VjaEV2ZW50LFxuICAgICAgICB0eXBlOiBEcmFnQWN0aW9uVHlwZVxuICAgICk6IE9ic2VydmFibGU8S3RkR3JpZExheW91dD4ge1xuICAgICAgICByZXR1cm4gbmV3IE9ic2VydmFibGU8S3RkR3JpZExheW91dD4oKG9ic2VydmVyOiBPYnNlcnZlcjxLdGRHcmlkTGF5b3V0PikgPT4ge1xuICAgICAgICAgICAgLy8gUmV0cmlldmUgZ3JpZCAocGFyZW50KSBhbmQgZ3JpZEl0ZW0gKGRyYWdnZWRFbGVtKSBjbGllbnQgcmVjdHMuXG4gICAgICAgICAgICBjb25zdCBncmlkRWxlbUNsaWVudFJlY3Q6IEt0ZENsaWVudFJlY3QgPSBnZXRNdXRhYmxlQ2xpZW50UmVjdChcbiAgICAgICAgICAgICAgICB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGNvbnN0IGRyYWdFbGVtQ2xpZW50UmVjdDogS3RkQ2xpZW50UmVjdCA9IGdldE11dGFibGVDbGllbnRSZWN0KFxuICAgICAgICAgICAgICAgIGdyaWRJdGVtLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCBhcyBIVE1MRWxlbWVudFxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgY29uc3Qgc2Nyb2xsYWJsZVBhcmVudCA9XG4gICAgICAgICAgICAgICAgdHlwZW9mIHRoaXMuc2Nyb2xsYWJsZVBhcmVudCA9PT0gJ3N0cmluZydcbiAgICAgICAgICAgICAgICAgICAgPyBkb2N1bWVudC5nZXRFbGVtZW50QnlJZCh0aGlzLnNjcm9sbGFibGVQYXJlbnQpXG4gICAgICAgICAgICAgICAgICAgIDogdGhpcy5zY3JvbGxhYmxlUGFyZW50O1xuXG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKGdyaWRJdGVtLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ25vLXRyYW5zaXRpb25zJyk7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLmFkZENsYXNzKGdyaWRJdGVtLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ2J1dy1ncmlkLWl0ZW0tZHJhZ2dpbmcnKTtcblxuICAgICAgICAgICAgY29uc3QgcGxhY2Vob2xkZXJDbGllbnRSZWN0OiBLdGRDbGllbnRSZWN0ID0ge1xuICAgICAgICAgICAgICAgIC4uLmRyYWdFbGVtQ2xpZW50UmVjdCxcbiAgICAgICAgICAgICAgICBsZWZ0OiBkcmFnRWxlbUNsaWVudFJlY3QubGVmdCAtIGdyaWRFbGVtQ2xpZW50UmVjdC5sZWZ0LFxuICAgICAgICAgICAgICAgIHRvcDogZHJhZ0VsZW1DbGllbnRSZWN0LnRvcCAtIGdyaWRFbGVtQ2xpZW50UmVjdC50b3BcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLmNyZWF0ZVBsYWNlaG9sZGVyRWxlbWVudChwbGFjZWhvbGRlckNsaWVudFJlY3QsIGdyaWRJdGVtLnBsYWNlaG9sZGVyKTtcblxuICAgICAgICAgICAgbGV0IG5ld0xheW91dDogS3RkR3JpZExheW91dEl0ZW1bXTtcblxuICAgICAgICAgICAgLy8gVE9ETyAoZW5oYW5jZW1lbnQpOiBjb25zaWRlciBtb3ZlIHRoaXMgJ3NpZGUgZWZmZWN0JyBvYnNlcnZhYmxlIGluc2lkZSB0aGUgbWFpbiBkcmFnIGxvb3AuXG4gICAgICAgICAgICAvLyAgLSBQcm9zIGFyZSB0aGF0IHdlIHdvdWxkIG5vdCByZXBlYXQgc3Vic2NyaXB0aW9ucyBhbmQgdGFrZVVudGlsIHdvdWxkIHNodXQgZG93biBvYnNlcnZhYmxlcyBhdCB0aGUgc2FtZSB0aW1lLlxuICAgICAgICAgICAgLy8gIC0gQ29ucyBhcmUgdGhhdCBtb3ZpbmcgdGhpcyBmdW5jdGlvbmFsaXR5IGFzIGEgc2lkZSBlZmZlY3QgaW5zaWRlIHRoZSBtYWluIGRyYWcgbG9vcCB3b3VsZCBiZSBjb25mdXNpbmcuXG4gICAgICAgICAgICBjb25zdCBzY3JvbGxTdWJzY3JpcHRpb24gPSB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PlxuICAgICAgICAgICAgICAgICghc2Nyb2xsYWJsZVBhcmVudFxuICAgICAgICAgICAgICAgICAgICA/IE5FVkVSXG4gICAgICAgICAgICAgICAgICAgIDogdGhpcy5ncmlkU2VydmljZS5tb3VzZU9yVG91Y2hNb3ZlJChkb2N1bWVudCkucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgbWFwKChldmVudCkgPT4gKHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvaW50ZXJYOiBrdGRQb2ludGVyQ2xpZW50WChldmVudCksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludGVyWToga3RkUG9pbnRlckNsaWVudFkoZXZlbnQpXG4gICAgICAgICAgICAgICAgICAgICAgICAgIH0pKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAga3RkU2Nyb2xsSWZOZWFyRWxlbWVudENsaWVudFJlY3QkKHNjcm9sbGFibGVQYXJlbnQsIHsgc2Nyb2xsU3RlcDogdGhpcy5zY3JvbGxTcGVlZCB9KVxuICAgICAgICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgIC5waXBlKHRha2VVbnRpbChrdGRQb2ludGVyVXAoZG9jdW1lbnQpKSlcbiAgICAgICAgICAgICAgICAgICAgLnN1YnNjcmliZSgpXG4gICAgICAgICAgICApO1xuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIE1haW4gc3Vic2NyaXB0aW9uLCBpdCBsaXN0ZW5zIGZvciAncG9pbnRlciBtb3ZlJyBhbmQgJ3Njcm9sbCcgZXZlbnRzIGFuZCByZWNhbGN1bGF0ZXMgdGhlIGxheW91dCBvbiBlYWNoIGVtaXNzaW9uXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGNvbnN0IHN1YnNjcmlwdGlvbiA9IHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+XG4gICAgICAgICAgICAgICAgbWVyZ2UoXG4gICAgICAgICAgICAgICAgICAgIGNvbWJpbmVMYXRlc3QoW1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5ncmlkU2VydmljZS5tb3VzZU9yVG91Y2hNb3ZlJChkb2N1bWVudCksXG4gICAgICAgICAgICAgICAgICAgICAgICAuLi4oIXNjcm9sbGFibGVQYXJlbnRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IFtvZih7IHRvcDogMCwgbGVmdDogMCB9KV1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBrdGRHZXRTY3JvbGxUb3RhbFJlbGF0aXZlRGlmZmVyZW5jZSQoc2Nyb2xsYWJsZVBhcmVudCkucGlwZShcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RhcnRXaXRoKHsgdG9wOiAwLCBsZWZ0OiAwIH0pIC8vIEZvcmNlIGZpcnN0IGVtaXNzaW9uIHRvIGFsbG93IENvbWJpbmVMYXRlc3QgdG8gZW1pdCBldmVuIG5vIHNjcm9sbCBldmVudCBoYXMgb2NjdXJyZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBdKVxuICAgICAgICAgICAgICAgICAgICBdKVxuICAgICAgICAgICAgICAgIClcbiAgICAgICAgICAgICAgICAgICAgLnBpcGUodGFrZVVudGlsKGt0ZFBvaW50ZXJVcChkb2N1bWVudCkpKVxuICAgICAgICAgICAgICAgICAgICAuc3Vic2NyaWJlKFxuICAgICAgICAgICAgICAgICAgICAgICAgKFtwb2ludGVyRHJhZ0V2ZW50LCBzY3JvbGxEaWZmZXJlbmNlXSkgPT5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAgICA6IFtNb3VzZUV2ZW50IHwgVG91Y2hFdmVudCB8IFBvaW50ZXJFdmVudHsgdG9wOiBudW1iZXI7IGxlZnQ6IG51bWJlciB9XVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRlckRyYWdFdmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKiBTZXQgdGhlIG5ldyBsYXlvdXQgdG8gYmUgdGhlIGxheW91dCBpbiB3aGljaCB0aGUgY2FsY05ld1N0YXRlRnVuYyB3b3VsZCBiZSBleGVjdXRlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogTk9URTogdXNpbmcgdGhlIG11dGF0ZWQgbGF5b3V0IGlzIHRoZSB3YXkgdG8gZ28gYnkgJ3JlYWN0LWdyaWQtbGF5b3V0JyB1dGlscy4gSWYgd2UgZG9uJ3QgdXNlIHRoZSBwcmV2aW91cyBsYXlvdXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIHNvbWUgdXRpbGl0aWVzIGZyb20gJ3JlYWN0LWdyaWQtbGF5b3V0JyB3b3VsZCBub3Qgd29yayBhcyBleHBlY3RlZC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRMYXlvdXQ6IEt0ZEdyaWRMYXlvdXQgPSBuZXdMYXlvdXQgfHwgdGhpcy5sYXlvdXQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gR2V0IHRoZSBjb3JyZWN0IG5ld1N0YXRlRnVuYyBkZXBlbmRpbmcgb24gaWYgd2UgYXJlIGRyYWdnaW5nIG9yIHJlc2l6aW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNhbGNOZXdTdGF0ZUZ1bmMgPSB0eXBlID09PSAnZHJhZycgPyBrdGRHcmlkSXRlbURyYWdnaW5nIDoga3RkR3JpZEl0ZW1SZXNpemluZztcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB7IGxheW91dCwgZHJhZ2dlZEl0ZW1Qb3MgfSA9IGNhbGNOZXdTdGF0ZUZ1bmMoXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmlkSXRlbSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsYXlvdXQ6IGN1cnJlbnRMYXlvdXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93SGVpZ2h0OiB0aGlzLnJvd0hlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBoZWlnaHQ6IHRoaXMuaGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbHM6IHRoaXMuY29scyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwcmV2ZW50Q29sbGlzaW9uOiB0aGlzLnByZXZlbnRDb2xsaXNpb24sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ2FwOiB0aGlzLmdhcFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY29tcGFjdFR5cGUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9pbnRlckRvd25FdmVudCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludGVyRHJhZ0V2ZW50LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdyaWRFbGVtQ2xpZW50UmVjdCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkcmFnRWxlbUNsaWVudFJlY3QsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Nyb2xsRGlmZmVyZW5jZVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdMYXlvdXQgPSBsYXlvdXQ7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5ncmlkQ3VycmVudEhlaWdodCA9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhlaWdodCA/P1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKHRoaXMucm93SGVpZ2h0ID09PSAnZml0J1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gZ3JpZEVsZW1DbGllbnRSZWN0LmhlaWdodFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogZ2V0R3JpZEhlaWdodChuZXdMYXlvdXQsIHRoaXMucm93SGVpZ2h0LCB0aGlzLmdhcCkpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2dyaWRJdGVtc1JlbmRlckRhdGEgPSBsYXlvdXRUb1JlbmRlckl0ZW1zKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbHM6IHRoaXMuY29scyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3dIZWlnaHQ6IHRoaXMucm93SGVpZ2h0LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogdGhpcy5oZWlnaHQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGF5b3V0OiBuZXdMYXlvdXQsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJldmVudENvbGxpc2lvbjogdGhpcy5wcmV2ZW50Q29sbGlzaW9uLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdhcDogdGhpcy5nYXBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmlkRWxlbUNsaWVudFJlY3Qud2lkdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBncmlkRWxlbUNsaWVudFJlY3QuaGVpZ2h0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV3R3JpZEl0ZW1SZW5kZXJEYXRhID0geyAuLi50aGlzLl9ncmlkSXRlbXNSZW5kZXJEYXRhW2dyaWRJdGVtLmlkXSB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwbGFjZWhvbGRlclN0eWxlcyA9IHBhcnNlUmVuZGVySXRlbVRvUGl4ZWxzKG5ld0dyaWRJdGVtUmVuZGVyRGF0YSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUHV0IHRoZSByZWFsIGZpbmFsIHBvc2l0aW9uIHRvIHRoZSBwbGFjZWhvbGRlciBlbGVtZW50XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGxhY2Vob2xkZXIhLnN0eWxlLndpZHRoID0gcGxhY2Vob2xkZXJTdHlsZXMud2lkdGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucGxhY2Vob2xkZXIhLnN0eWxlLmhlaWdodCA9IHBsYWNlaG9sZGVyU3R5bGVzLmhlaWdodDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5wbGFjZWhvbGRlciEuc3R5bGUudHJhbnNmb3JtID0gYHRyYW5zbGF0ZVgoJHtwbGFjZWhvbGRlclN0eWxlcy5sZWZ0fSkgdHJhbnNsYXRlWSgke3BsYWNlaG9sZGVyU3R5bGVzLnRvcH0pYDtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBtb2RpZnkgdGhlIHBvc2l0aW9uIG9mIHRoZSBkcmFnZ2VkIGl0ZW0gdG8gYmUgdGhlIG9uY2Ugd2Ugd2FudCAoZm9yIGV4YW1wbGUgdGhlIG1vdXNlIHBvc2l0aW9uIG9yIHdoYXRldmVyKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9ncmlkSXRlbXNSZW5kZXJEYXRhW2dyaWRJdGVtLmlkXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLmRyYWdnZWRJdGVtUG9zLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ6IHRoaXMuX2dyaWRJdGVtc1JlbmRlckRhdGFbZ3JpZEl0ZW0uaWRdLmlkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXRCYWNrZ3JvdW5kQ3NzVmFyaWFibGVzKFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yb3dIZWlnaHQgPT09ICdmaXQnXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBrdGRHZXRHcmlkSXRlbVJvd0hlaWdodChuZXdMYXlvdXQsIGdyaWRFbGVtQ2xpZW50UmVjdC5oZWlnaHQsIHRoaXMuZ2FwKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogdGhpcy5yb3dIZWlnaHRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcigpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIHdlIGFyZSBwZXJmb3JtaW5nIGEgcmVzaXplLCBhbmQgYm91bmRzIGhhdmUgY2hhbmdlZCwgZW1pdCBldmVudC5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTk9URTogT25seSBlbWl0IG9uIHJlc2l6ZSBmb3Igbm93LiBVc2UgY2FzZSBmb3Igbm9ybWFsIGRyYWcgaXMgbm90IGp1c3RpZmllZCBmb3Igbm93LiBFbWl0dGluZyBvbiByZXNpemUgaXMsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHNpbmNlIHdlIG1heSB3YW50IHRvIHJlLXJlbmRlciB0aGUgZ3JpZCBpdGVtIG9yIHRoZSBwbGFjZWhvbGRlciBpbiBvcmRlciB0byBmaXQgdGhlIG5ldyBib3VuZHMuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0eXBlID09PSAncmVzaXplJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcHJldkdyaWRJdGVtID0gY3VycmVudExheW91dC5maW5kKChpdGVtKSA9PiBpdGVtLmlkID09PSBncmlkSXRlbS5pZCkhO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbmV3R3JpZEl0ZW0gPSBuZXdMYXlvdXQuZmluZCgoaXRlbSkgPT4gaXRlbS5pZCA9PT0gZ3JpZEl0ZW0uaWQpITtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIGl0ZW0gcmVzaXplZCBoYXMgY2hhbmdlZCwgaWYgc28sIGVtaXQgcmVzaXplIGNoYW5nZSBldmVudFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFrdGRHcmlkSXRlbUxheW91dEl0ZW1BcmVFcXVhbChwcmV2R3JpZEl0ZW0sIG5ld0dyaWRJdGVtKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZ3JpZEl0ZW1SZXNpemUuZW1pdCh7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHdpZHRoOiBuZXdHcmlkSXRlbVJlbmRlckRhdGEud2lkdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodDogbmV3R3JpZEl0ZW1SZW5kZXJEYXRhLmhlaWdodCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZ3JpZEl0ZW1SZWY6IGdldERyYWdSZXNpemVFdmVudERhdGEoZ3JpZEl0ZW0sIG5ld0xheW91dCkuZ3JpZEl0ZW1SZWZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAoZXJyb3IpID0+IG9ic2VydmVyLmVycm9yKGVycm9yKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgZHJhZyBjbGFzc2VzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMucmVuZGVyZXIucmVtb3ZlQ2xhc3MoZ3JpZEl0ZW0uZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LCAnbm8tdHJhbnNpdGlvbnMnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5yZW1vdmVDbGFzcyhncmlkSXRlbS5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICdidXctZ3JpZC1pdGVtLWRyYWdnaW5nJyk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5hZGRHcmlkSXRlbUFuaW1hdGluZ0NsYXNzKGdyaWRJdGVtKS5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ29uc2lkZXIgZGVzdHJveWluZyB0aGUgcGxhY2Vob2xkZXIgYWZ0ZXIgdGhlIGFuaW1hdGlvbiBoYXMgZmluaXNoZWQuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZGVzdHJveVBsYWNlaG9sZGVyKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG5ld0xheW91dCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogbmV3TGF5b3V0IHNob3VsZCBhbHJlYWR5IGJlIHBydW5lZC4gSWYgbm90LCBpdCBzaG91bGQgaGF2ZSB0eXBlIExheW91dCwgbm90IEt0ZEdyaWRMYXlvdXQgYXMgaXQgaXMgbm93LlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUHJ1bmUgcmVhY3QtZ3JpZC1sYXlvdXQgY29tcGFjdCBleHRyYSBwcm9wZXJ0aWVzLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dChcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdMYXlvdXQubWFwKChpdGVtKSA9PiAoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZDogaXRlbS5pZCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeDogaXRlbS54LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB5OiBpdGVtLnksXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHc6IGl0ZW0udyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaDogaXRlbS5oLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtaW5XOiBpdGVtLm1pblcsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbkg6IGl0ZW0ubWluSCxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF4VzogaXRlbS5tYXhXLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXhIOiBpdGVtLm1heEhcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KSkgYXMgS3RkR3JpZExheW91dFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IE5lZWQgd2UgcmVhbGx5IHRvIGVtaXQgaWYgdGhlcmUgaXMgbm8gbGF5b3V0IGNoYW5nZSBidXQgZHJhZyBzdGFydGVkIGFuZCBlbmRlZD9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQodGhpcy5sYXlvdXQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb2JzZXJ2ZXIuY29tcGxldGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgKTtcblxuICAgICAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICAgICAgICBzY3JvbGxTdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgICAgICBzdWJzY3JpcHRpb24udW5zdWJzY3JpYmUoKTtcbiAgICAgICAgICAgIH07XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEl0IGFkZHMgdGhlIGBidXctZ3JpZC1pdGVtLWFuaW1hdGluZ2AgY2xhc3MgYW5kIHJlbW92ZXMgaXQgd2hlbiB0aGUgYW5pbWF0ZWQgdHJhbnNpdGlvbiBpcyBjb21wbGV0ZS5cbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGlzIG1lYW50IHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIGRyYWcgaGFzIGVuZGVkLlxuICAgICAqIEBwYXJhbSBncmlkSXRlbSB0aGF0IGhhcyBiZWVuIGRyYWdnZWRcbiAgICAgKi9cbiAgICBwcml2YXRlIGFkZEdyaWRJdGVtQW5pbWF0aW5nQ2xhc3MoZ3JpZEl0ZW06IEt0ZEdyaWRJdGVtQ29tcG9uZW50KTogT2JzZXJ2YWJsZTx1bmRlZmluZWQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBPYnNlcnZhYmxlKChvYnNlcnZlcikgPT4ge1xuICAgICAgICAgICAgY29uc3QgZHVyYXRpb24gPSBnZXRUcmFuc2Zvcm1UcmFuc2l0aW9uRHVyYXRpb25Jbk1zKGdyaWRJdGVtLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCk7XG5cbiAgICAgICAgICAgIGlmIChkdXJhdGlvbiA9PT0gMCkge1xuICAgICAgICAgICAgICAgIG9ic2VydmVyLm5leHQoKTtcbiAgICAgICAgICAgICAgICBvYnNlcnZlci5jb21wbGV0ZSgpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5yZW5kZXJlci5hZGRDbGFzcyhncmlkSXRlbS5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsICdidXctZ3JpZC1pdGVtLWFuaW1hdGluZycpO1xuICAgICAgICAgICAgY29uc3QgaGFuZGxlciA9ICgoZXZlbnQ6IFRyYW5zaXRpb25FdmVudCkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICAgICAgIWV2ZW50IHx8XG4gICAgICAgICAgICAgICAgICAgIChldmVudC50YXJnZXQgPT09IGdyaWRJdGVtLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCAmJiBldmVudC5wcm9wZXJ0eU5hbWUgPT09ICd0cmFuc2Zvcm0nKVxuICAgICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnJlbW92ZUNsYXNzKGdyaWRJdGVtLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgJ2J1dy1ncmlkLWl0ZW0tYW5pbWF0aW5nJyk7XG4gICAgICAgICAgICAgICAgICAgIHJlbW92ZUV2ZW50TGlzdGVuZXIoKTtcbiAgICAgICAgICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVvdXQpO1xuICAgICAgICAgICAgICAgICAgICBvYnNlcnZlci5uZXh0KCk7XG4gICAgICAgICAgICAgICAgICAgIG9ic2VydmVyLmNvbXBsZXRlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkgYXMgRXZlbnRMaXN0ZW5lcjtcblxuICAgICAgICAgICAgLy8gSWYgYSB0cmFuc2l0aW9uIGlzIHNob3J0IGVub3VnaCwgdGhlIGJyb3dzZXIgbWlnaHQgbm90IGZpcmUgdGhlIGB0cmFuc2l0aW9uZW5kYCBldmVudC5cbiAgICAgICAgICAgIC8vIFNpbmNlIHdlIGtub3cgaG93IGxvbmcgaXQncyBzdXBwb3NlZCB0byB0YWtlLCBhZGQgYSB0aW1lb3V0IHdpdGggYSA1MCUgYnVmZmVyIHRoYXQnbGxcbiAgICAgICAgICAgIC8vIGZpcmUgaWYgdGhlIHRyYW5zaXRpb24gaGFzbid0IGNvbXBsZXRlZCB3aGVuIGl0IHdhcyBzdXBwb3NlZCB0by5cbiAgICAgICAgICAgIGNvbnN0IHRpbWVvdXQgPSBzZXRUaW1lb3V0KGhhbmRsZXIsIGR1cmF0aW9uICogMS41KTtcbiAgICAgICAgICAgIGNvbnN0IHJlbW92ZUV2ZW50TGlzdGVuZXIgPSB0aGlzLnJlbmRlcmVyLmxpc3RlbihcbiAgICAgICAgICAgICAgICBncmlkSXRlbS5lbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgICAgICAgICAgJ3RyYW5zaXRpb25lbmQnLFxuICAgICAgICAgICAgICAgIGhhbmRsZXJcbiAgICAgICAgICAgICk7XG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKiBDcmVhdGVzIHBsYWNlaG9sZGVyIGVsZW1lbnQgKi9cbiAgICBwcml2YXRlIGNyZWF0ZVBsYWNlaG9sZGVyRWxlbWVudChjbGllbnRSZWN0OiBLdGRDbGllbnRSZWN0LCBncmlkSXRlbVBsYWNlaG9sZGVyPzogS3RkR3JpZEl0ZW1QbGFjZWhvbGRlcik6IHZvaWQge1xuICAgICAgICB0aGlzLnBsYWNlaG9sZGVyID0gdGhpcy5yZW5kZXJlci5jcmVhdGVFbGVtZW50KCdkaXYnKTtcbiAgICAgICAgdGhpcy5wbGFjZWhvbGRlciEuc3R5bGUud2lkdGggPSBgJHtjbGllbnRSZWN0LndpZHRofXB4YDtcbiAgICAgICAgdGhpcy5wbGFjZWhvbGRlciEuc3R5bGUuaGVpZ2h0ID0gYCR7Y2xpZW50UmVjdC5oZWlnaHR9cHhgO1xuICAgICAgICB0aGlzLnBsYWNlaG9sZGVyIS5zdHlsZS50cmFuc2Zvcm0gPSBgdHJhbnNsYXRlWCgke2NsaWVudFJlY3QubGVmdH1weCkgdHJhbnNsYXRlWSgke2NsaWVudFJlY3QudG9wfXB4KWA7XG4gICAgICAgIHRoaXMucGxhY2Vob2xkZXIhLmNsYXNzTGlzdC5hZGQoJ2J1dy1ncmlkLWl0ZW0tcGxhY2Vob2xkZXInKTtcbiAgICAgICAgdGhpcy5yZW5kZXJlci5hcHBlbmRDaGlsZCh0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCwgdGhpcy5wbGFjZWhvbGRlcik7XG5cbiAgICAgICAgLy8gQ3JlYXRlIGFuZCBhcHBlbmQgY3VzdG9tIHBsYWNlaG9sZGVyIGlmIHByb3ZpZGVkLlxuICAgICAgICAvLyBJbXBvcnRhbnQ6IEFwcGVuZCBpdCBhZnRlciBjcmVhdGluZyAmIGFwcGVuZGluZyB0aGUgY29udGFpbmVyIHBsYWNlaG9sZGVyLiBUaGlzIHdheSB3ZSBlbnN1cmUgcGFyZW50IGJvdW5kcyBhcmUgc2V0IHdoZW4gY3JlYXRpbmcgdGhlIGVtYmVkZGVkVmlldy5cbiAgICAgICAgaWYgKGdyaWRJdGVtUGxhY2Vob2xkZXIpIHtcbiAgICAgICAgICAgIHRoaXMucGxhY2Vob2xkZXJSZWYgPSB0aGlzLnZpZXdDb250YWluZXJSZWYuY3JlYXRlRW1iZWRkZWRWaWV3KFxuICAgICAgICAgICAgICAgIGdyaWRJdGVtUGxhY2Vob2xkZXIudGVtcGxhdGVSZWYsXG4gICAgICAgICAgICAgICAgZ3JpZEl0ZW1QbGFjZWhvbGRlci5kYXRhXG4gICAgICAgICAgICApO1xuICAgICAgICAgICAgdGhpcy5wbGFjZWhvbGRlclJlZi5yb290Tm9kZXMuZm9yRWFjaCgobm9kZSkgPT4gdGhpcy5wbGFjZWhvbGRlciEuYXBwZW5kQ2hpbGQobm9kZSkpO1xuICAgICAgICAgICAgdGhpcy5wbGFjZWhvbGRlclJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnBsYWNlaG9sZGVyIS5jbGFzc0xpc3QuYWRkKCdidXctZ3JpZC1pdGVtLXBsYWNlaG9sZGVyLWRlZmF1bHQnKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKiBEZXN0cm95cyB0aGUgcGxhY2Vob2xkZXIgZWxlbWVudCBhbmQgaXRzIFZpZXdSZWYuICovXG4gICAgcHJpdmF0ZSBkZXN0cm95UGxhY2Vob2xkZXIoKTogdm9pZCB7XG4gICAgICAgIHRoaXMucGxhY2Vob2xkZXI/LnJlbW92ZSgpO1xuICAgICAgICB0aGlzLnBsYWNlaG9sZGVyUmVmPy5kZXN0cm95KCk7XG4gICAgICAgIHRoaXMucGxhY2Vob2xkZXIgPSB0aGlzLnBsYWNlaG9sZGVyUmVmID0gbnVsbCE7XG4gICAgfVxuXG4gICAgc3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX2NvbHM6IE51bWJlcklucHV0O1xuICAgIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9yb3dIZWlnaHQ6IE51bWJlcklucHV0O1xuICAgIHN0YXRpYyBuZ0FjY2VwdElucHV0VHlwZV9zY3JvbGxTcGVlZDogTnVtYmVySW5wdXQ7XG4gICAgc3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX2NvbXBhY3RPblByb3BzQ2hhbmdlOiBCb29sZWFuSW5wdXQ7XG4gICAgc3RhdGljIG5nQWNjZXB0SW5wdXRUeXBlX3ByZXZlbnRDb2xsaXNpb246IEJvb2xlYW5JbnB1dDtcbn1cblxuIiwiPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PiJdfQ==