angular-multiselect3 10.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/LICENSE +20 -0
  2. package/README.md +306 -0
  3. package/esm2022/angular-multiselect.mjs +5 -0
  4. package/esm2022/lib/clickOutside.mjs +58 -0
  5. package/esm2022/lib/list-filter.mjs +59 -0
  6. package/esm2022/lib/menu-item.mjs +352 -0
  7. package/esm2022/lib/multiselect.component.mjs +1038 -0
  8. package/esm2022/lib/multiselect.interface.mjs +2 -0
  9. package/esm2022/lib/multiselect.model.mjs +9 -0
  10. package/esm2022/lib/multiselect.service.mjs +28 -0
  11. package/esm2022/lib/virtual-scroll/defaultoptions.mjs +2 -0
  12. package/esm2022/lib/virtual-scroll/idimension.mjs +2 -0
  13. package/esm2022/lib/virtual-scroll/ipageinfo.mjs +2 -0
  14. package/esm2022/lib/virtual-scroll/iviewport.mjs +2 -0
  15. package/esm2022/lib/virtual-scroll/virtual-scroll.mjs +1162 -0
  16. package/esm2022/lib/virtual-scroll/wrapgroupdimension.mjs +2 -0
  17. package/esm2022/lib/virtual-scroll/wrapgroupdimensions.mjs +2 -0
  18. package/esm2022/public_api.mjs +7 -0
  19. package/fesm2022/angular-multiselect.mjs +2689 -0
  20. package/fesm2022/angular-multiselect.mjs.map +1 -0
  21. package/index.d.ts +5 -0
  22. package/lib/clickOutside.d.ts +17 -0
  23. package/lib/list-filter.d.ts +12 -0
  24. package/lib/menu-item.d.ts +36 -0
  25. package/lib/multiselect.component.d.ts +134 -0
  26. package/lib/multiselect.interface.d.ts +34 -0
  27. package/lib/multiselect.model.d.ts +5 -0
  28. package/lib/multiselect.service.d.ts +11 -0
  29. package/lib/virtual-scroll/defaultoptions.d.ts +11 -0
  30. package/lib/virtual-scroll/idimension.d.ts +12 -0
  31. package/lib/virtual-scroll/ipageinfo.d.ts +9 -0
  32. package/lib/virtual-scroll/iviewport.d.ts +5 -0
  33. package/lib/virtual-scroll/virtual-scroll.d.ts +132 -0
  34. package/lib/virtual-scroll/wrapgroupdimension.d.ts +5 -0
  35. package/lib/virtual-scroll/wrapgroupdimensions.d.ts +7 -0
  36. package/package.json +37 -0
  37. package/public_api.d.ts +6 -0
  38. package/themes/dark.theme.scss +113 -0
  39. package/themes/default.theme.css +107 -0
  40. package/themes/default.theme.scss +155 -0
@@ -0,0 +1,1162 @@
1
+ import { Component, ContentChild, ElementRef, EventEmitter, Inject, Optional, Input, NgModule, Output, ViewChild, } from '@angular/core';
2
+ import { PLATFORM_ID } from '@angular/core';
3
+ import { isPlatformServer } from '@angular/common';
4
+ import { CommonModule } from '@angular/common';
5
+ import * as tween from '@tweenjs/tween.js';
6
+ import * as i0 from "@angular/core";
7
+ export function VIRTUAL_SCROLLER_DEFAULT_OPTIONS_FACTORY() {
8
+ return {
9
+ scrollThrottlingTime: 0,
10
+ scrollDebounceTime: 0,
11
+ scrollAnimationTime: 750,
12
+ checkResizeInterval: 1000,
13
+ resizeBypassRefreshThreshold: 5,
14
+ modifyOverflowStyleOfParentScroll: true,
15
+ stripedTable: false,
16
+ };
17
+ }
18
+ export class VirtualScrollerComponent {
19
+ element;
20
+ renderer;
21
+ zone;
22
+ changeDetectorRef;
23
+ viewPortItems;
24
+ window = window;
25
+ get viewPortInfo() {
26
+ let pageInfo = this.previousViewPort || {};
27
+ return {
28
+ startIndex: pageInfo.startIndex || 0,
29
+ endIndex: pageInfo.endIndex || 0,
30
+ scrollStartPosition: pageInfo.scrollStartPosition || 0,
31
+ scrollEndPosition: pageInfo.scrollEndPosition || 0,
32
+ maxScrollPosition: pageInfo.maxScrollPosition || 0,
33
+ startIndexWithBuffer: pageInfo.startIndexWithBuffer || 0,
34
+ endIndexWithBuffer: pageInfo.endIndexWithBuffer || 0,
35
+ };
36
+ }
37
+ executeRefreshOutsideAngularZone = false;
38
+ _enableUnequalChildrenSizes = false;
39
+ get enableUnequalChildrenSizes() {
40
+ return this._enableUnequalChildrenSizes;
41
+ }
42
+ set enableUnequalChildrenSizes(value) {
43
+ if (this._enableUnequalChildrenSizes === value) {
44
+ return;
45
+ }
46
+ this._enableUnequalChildrenSizes = value;
47
+ this.minMeasuredChildWidth = undefined;
48
+ this.minMeasuredChildHeight = undefined;
49
+ }
50
+ useMarginInsteadOfTranslate = false;
51
+ modifyOverflowStyleOfParentScroll;
52
+ stripedTable;
53
+ scrollbarWidth;
54
+ scrollbarHeight;
55
+ childWidth;
56
+ childHeight;
57
+ ssrChildWidth;
58
+ ssrChildHeight;
59
+ ssrViewportWidth = 1920;
60
+ ssrViewportHeight = 1080;
61
+ _bufferAmount = 0;
62
+ get bufferAmount() {
63
+ if (typeof this._bufferAmount === 'number' && this._bufferAmount >= 0) {
64
+ return this._bufferAmount;
65
+ }
66
+ else {
67
+ return this.enableUnequalChildrenSizes ? 5 : 0;
68
+ }
69
+ }
70
+ set bufferAmount(value) {
71
+ this._bufferAmount = value;
72
+ }
73
+ scrollAnimationTime;
74
+ resizeBypassRefreshThreshold;
75
+ _scrollThrottlingTime;
76
+ get scrollThrottlingTime() {
77
+ return this._scrollThrottlingTime;
78
+ }
79
+ set scrollThrottlingTime(value) {
80
+ this._scrollThrottlingTime = value;
81
+ this.updateOnScrollFunction();
82
+ }
83
+ _scrollDebounceTime;
84
+ get scrollDebounceTime() {
85
+ return this._scrollDebounceTime;
86
+ }
87
+ set scrollDebounceTime(value) {
88
+ this._scrollDebounceTime = value;
89
+ this.updateOnScrollFunction();
90
+ }
91
+ onScroll;
92
+ updateOnScrollFunction() {
93
+ if (this.scrollDebounceTime) {
94
+ this.onScroll = this.debounce(() => {
95
+ this.refresh_internal(false);
96
+ }, this.scrollDebounceTime);
97
+ }
98
+ else if (this.scrollThrottlingTime) {
99
+ this.onScroll = this.throttleTrailing(() => {
100
+ this.refresh_internal(false);
101
+ }, this.scrollThrottlingTime);
102
+ }
103
+ else {
104
+ this.onScroll = () => {
105
+ this.refresh_internal(false);
106
+ };
107
+ }
108
+ }
109
+ checkScrollElementResizedTimer;
110
+ _checkResizeInterval;
111
+ get checkResizeInterval() {
112
+ return this._checkResizeInterval;
113
+ }
114
+ set checkResizeInterval(value) {
115
+ if (this._checkResizeInterval === value) {
116
+ return;
117
+ }
118
+ this._checkResizeInterval = value;
119
+ this.addScrollEventHandlers();
120
+ }
121
+ _items = [];
122
+ get items() {
123
+ return this._items;
124
+ }
125
+ set items(value) {
126
+ if (value === this._items) {
127
+ return;
128
+ }
129
+ this._items = value || [];
130
+ this.refresh_internal(true);
131
+ }
132
+ compareItems = (item1, item2) => item1 === item2;
133
+ _horizontal;
134
+ get horizontal() {
135
+ return this._horizontal;
136
+ }
137
+ set horizontal(value) {
138
+ this._horizontal = value;
139
+ this.updateDirection();
140
+ }
141
+ revertParentOverscroll() {
142
+ const scrollElement = this.getScrollElement();
143
+ if (scrollElement && this.oldParentScrollOverflow) {
144
+ scrollElement.style['overflow-y'] = this.oldParentScrollOverflow.y;
145
+ scrollElement.style['overflow-x'] = this.oldParentScrollOverflow.x;
146
+ }
147
+ this.oldParentScrollOverflow = undefined;
148
+ }
149
+ oldParentScrollOverflow;
150
+ _parentScroll;
151
+ get parentScroll() {
152
+ return this._parentScroll;
153
+ }
154
+ set parentScroll(value) {
155
+ if (this._parentScroll === value) {
156
+ return;
157
+ }
158
+ this.revertParentOverscroll();
159
+ this._parentScroll = value;
160
+ this.addScrollEventHandlers();
161
+ const scrollElement = this.getScrollElement();
162
+ if (this.modifyOverflowStyleOfParentScroll &&
163
+ scrollElement !== this.element.nativeElement) {
164
+ this.oldParentScrollOverflow = {
165
+ x: scrollElement.style['overflow-x'],
166
+ y: scrollElement.style['overflow-y'],
167
+ };
168
+ scrollElement.style['overflow-y'] = this.horizontal ? 'visible' : 'auto';
169
+ scrollElement.style['overflow-x'] = this.horizontal ? 'auto' : 'visible';
170
+ }
171
+ }
172
+ vsUpdate = new EventEmitter();
173
+ vsChange = new EventEmitter();
174
+ vsStart = new EventEmitter();
175
+ vsEnd = new EventEmitter();
176
+ contentElementRef;
177
+ invisiblePaddingElementRef;
178
+ headerElementRef;
179
+ containerElementRef;
180
+ ngOnInit() {
181
+ this.addScrollEventHandlers();
182
+ }
183
+ ngOnDestroy() {
184
+ this.removeScrollEventHandlers();
185
+ this.revertParentOverscroll();
186
+ }
187
+ ngOnChanges(changes) {
188
+ let indexLengthChanged = this.cachedItemsLength !== this.items.length;
189
+ this.cachedItemsLength = this.items.length;
190
+ const firstRun = !changes.items ||
191
+ !changes.items.previousValue ||
192
+ changes.items.previousValue.length === 0;
193
+ this.refresh_internal(indexLengthChanged || firstRun);
194
+ }
195
+ ngDoCheck() {
196
+ if (this.cachedItemsLength !== this.items.length) {
197
+ this.cachedItemsLength = this.items.length;
198
+ this.refresh_internal(true);
199
+ return;
200
+ }
201
+ if (this.previousViewPort &&
202
+ this.viewPortItems &&
203
+ this.viewPortItems.length > 0) {
204
+ let itemsArrayChanged = false;
205
+ for (let i = 0; i < this.viewPortItems.length; ++i) {
206
+ if (!this.compareItems(this.items[this.previousViewPort.startIndexWithBuffer + i], this.viewPortItems[i])) {
207
+ itemsArrayChanged = true;
208
+ break;
209
+ }
210
+ }
211
+ if (itemsArrayChanged) {
212
+ this.refresh_internal(true);
213
+ }
214
+ }
215
+ }
216
+ refresh() {
217
+ this.refresh_internal(true);
218
+ }
219
+ invalidateAllCachedMeasurements() {
220
+ this.wrapGroupDimensions = {
221
+ maxChildSizePerWrapGroup: [],
222
+ numberOfKnownWrapGroupChildSizes: 0,
223
+ sumOfKnownWrapGroupChildWidths: 0,
224
+ sumOfKnownWrapGroupChildHeights: 0,
225
+ };
226
+ this.minMeasuredChildWidth = undefined;
227
+ this.minMeasuredChildHeight = undefined;
228
+ this.refresh_internal(false);
229
+ }
230
+ invalidateCachedMeasurementForItem(item) {
231
+ if (this.enableUnequalChildrenSizes) {
232
+ let index = this.items && this.items.indexOf(item);
233
+ if (index >= 0) {
234
+ this.invalidateCachedMeasurementAtIndex(index);
235
+ }
236
+ }
237
+ else {
238
+ this.minMeasuredChildWidth = undefined;
239
+ this.minMeasuredChildHeight = undefined;
240
+ }
241
+ this.refresh_internal(false);
242
+ }
243
+ invalidateCachedMeasurementAtIndex(index) {
244
+ if (this.enableUnequalChildrenSizes) {
245
+ let cachedMeasurement = this.wrapGroupDimensions.maxChildSizePerWrapGroup[index];
246
+ if (cachedMeasurement) {
247
+ this.wrapGroupDimensions.maxChildSizePerWrapGroup[index] = undefined;
248
+ --this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
249
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths -=
250
+ cachedMeasurement.childWidth || 0;
251
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights -=
252
+ cachedMeasurement.childHeight || 0;
253
+ }
254
+ }
255
+ else {
256
+ this.minMeasuredChildWidth = undefined;
257
+ this.minMeasuredChildHeight = undefined;
258
+ }
259
+ this.refresh_internal(false);
260
+ }
261
+ scrollInto(item, alignToBeginning = true, additionalOffset = 0, animationMilliseconds = undefined, animationCompletedCallback = undefined) {
262
+ let index = this.items.indexOf(item);
263
+ if (index === -1) {
264
+ return;
265
+ }
266
+ this.scrollToIndex(index, alignToBeginning, additionalOffset, animationMilliseconds, animationCompletedCallback);
267
+ }
268
+ scrollToIndex(index, alignToBeginning = true, additionalOffset = 0, animationMilliseconds = undefined, animationCompletedCallback = undefined) {
269
+ let maxRetries = 5;
270
+ let retryIfNeeded = () => {
271
+ --maxRetries;
272
+ if (maxRetries <= 0) {
273
+ if (animationCompletedCallback) {
274
+ animationCompletedCallback();
275
+ }
276
+ return;
277
+ }
278
+ let dimensions = this.calculateDimensions();
279
+ let desiredStartIndex = Math.min(Math.max(index, 0), dimensions.itemCount - 1);
280
+ if (this.previousViewPort.startIndex === desiredStartIndex) {
281
+ if (animationCompletedCallback) {
282
+ animationCompletedCallback();
283
+ }
284
+ return;
285
+ }
286
+ this.scrollToIndex_internal(index, alignToBeginning, additionalOffset, 0, retryIfNeeded);
287
+ };
288
+ this.scrollToIndex_internal(index, alignToBeginning, additionalOffset, animationMilliseconds, retryIfNeeded);
289
+ }
290
+ scrollToIndex_internal(index, alignToBeginning = true, additionalOffset = 0, animationMilliseconds = undefined, animationCompletedCallback = undefined) {
291
+ animationMilliseconds =
292
+ animationMilliseconds === undefined
293
+ ? this.scrollAnimationTime
294
+ : animationMilliseconds;
295
+ let dimensions = this.calculateDimensions();
296
+ let scroll = this.calculatePadding(index, dimensions) + additionalOffset;
297
+ if (!alignToBeginning) {
298
+ scroll -= dimensions.wrapGroupsPerPage * dimensions[this._childScrollDim];
299
+ }
300
+ this.scrollToPosition(scroll, animationMilliseconds, animationCompletedCallback);
301
+ }
302
+ scrollToPosition(scrollPosition, animationMilliseconds = undefined, animationCompletedCallback = undefined) {
303
+ scrollPosition += this.getElementsOffset();
304
+ animationMilliseconds =
305
+ animationMilliseconds === undefined
306
+ ? this.scrollAnimationTime
307
+ : animationMilliseconds;
308
+ let scrollElement = this.getScrollElement();
309
+ let animationRequest;
310
+ if (this.currentTween) {
311
+ this.currentTween.stop();
312
+ this.currentTween = undefined;
313
+ }
314
+ if (!animationMilliseconds) {
315
+ this.renderer.setProperty(scrollElement, this._scrollType, scrollPosition);
316
+ this.refresh_internal(false, animationCompletedCallback);
317
+ return;
318
+ }
319
+ const tweenConfigObj = { scrollPosition: scrollElement[this._scrollType] };
320
+ let newTween = new tween.Tween(tweenConfigObj)
321
+ .to({ scrollPosition }, animationMilliseconds)
322
+ .easing(tween.Easing.Quadratic.Out)
323
+ .onUpdate((data) => {
324
+ if (isNaN(data.scrollPosition)) {
325
+ return;
326
+ }
327
+ this.renderer.setProperty(scrollElement, this._scrollType, data.scrollPosition);
328
+ this.refresh_internal(false);
329
+ })
330
+ .onStop(() => {
331
+ cancelAnimationFrame(animationRequest);
332
+ })
333
+ .start();
334
+ const animate = (time) => {
335
+ if (!newTween['isPlaying']()) {
336
+ return;
337
+ }
338
+ newTween.update(time);
339
+ if (tweenConfigObj.scrollPosition === scrollPosition) {
340
+ this.refresh_internal(false, animationCompletedCallback);
341
+ return;
342
+ }
343
+ this.zone.runOutsideAngular(() => {
344
+ animationRequest = requestAnimationFrame(animate);
345
+ });
346
+ };
347
+ animate();
348
+ this.currentTween = newTween;
349
+ }
350
+ isAngularUniversalSSR;
351
+ constructor(element, renderer, zone, changeDetectorRef, platformId, options) {
352
+ this.element = element;
353
+ this.renderer = renderer;
354
+ this.zone = zone;
355
+ this.changeDetectorRef = changeDetectorRef;
356
+ this.isAngularUniversalSSR = isPlatformServer(platformId);
357
+ this.scrollThrottlingTime = options.scrollThrottlingTime;
358
+ this.scrollDebounceTime = options.scrollDebounceTime;
359
+ this.scrollAnimationTime = options.scrollAnimationTime;
360
+ this.scrollbarWidth = options.scrollbarWidth;
361
+ this.scrollbarHeight = options.scrollbarHeight;
362
+ this.checkResizeInterval = options.checkResizeInterval;
363
+ this.resizeBypassRefreshThreshold = options.resizeBypassRefreshThreshold;
364
+ this.modifyOverflowStyleOfParentScroll =
365
+ options.modifyOverflowStyleOfParentScroll;
366
+ this.stripedTable = options.stripedTable;
367
+ this.horizontal = false;
368
+ this.resetWrapGroupDimensions();
369
+ }
370
+ getElementSize(element) {
371
+ let result = element.getBoundingClientRect();
372
+ let styles = getComputedStyle(element);
373
+ let marginTop = parseInt(styles['margin-top'], 10) || 0;
374
+ let marginBottom = parseInt(styles['margin-bottom'], 10) || 0;
375
+ let marginLeft = parseInt(styles['margin-left'], 10) || 0;
376
+ let marginRight = parseInt(styles['margin-right'], 10) || 0;
377
+ return {
378
+ top: result.top + marginTop,
379
+ bottom: result.bottom + marginBottom,
380
+ left: result.left + marginLeft,
381
+ right: result.right + marginRight,
382
+ width: result.width + marginLeft + marginRight,
383
+ height: result.height + marginTop + marginBottom,
384
+ y: result.top + marginTop,
385
+ x: result.left + marginLeft,
386
+ toJSON() {
387
+ result.toJSON();
388
+ },
389
+ };
390
+ }
391
+ previousScrollBoundingRect;
392
+ checkScrollElementResized() {
393
+ let boundingRect = this.getElementSize(this.getScrollElement());
394
+ let sizeChanged;
395
+ if (!this.previousScrollBoundingRect) {
396
+ sizeChanged = true;
397
+ }
398
+ else {
399
+ let widthChange = Math.abs(boundingRect.width - this.previousScrollBoundingRect.width);
400
+ let heightChange = Math.abs(boundingRect.height - this.previousScrollBoundingRect.height);
401
+ sizeChanged =
402
+ widthChange > this.resizeBypassRefreshThreshold ||
403
+ heightChange > this.resizeBypassRefreshThreshold;
404
+ }
405
+ if (sizeChanged) {
406
+ this.previousScrollBoundingRect = boundingRect;
407
+ if (boundingRect.width > 0 && boundingRect.height > 0) {
408
+ this.refresh_internal(false);
409
+ }
410
+ }
411
+ }
412
+ _invisiblePaddingProperty;
413
+ _offsetType;
414
+ _scrollType;
415
+ _pageOffsetType;
416
+ _childScrollDim;
417
+ _translateDir;
418
+ _marginDir;
419
+ updateDirection() {
420
+ if (this.horizontal) {
421
+ this._invisiblePaddingProperty = 'width';
422
+ this._offsetType = 'offsetLeft';
423
+ this._pageOffsetType = 'pageXOffset';
424
+ this._childScrollDim = 'childWidth';
425
+ this._marginDir = 'margin-left';
426
+ this._translateDir = 'translateX';
427
+ this._scrollType = 'scrollLeft';
428
+ }
429
+ else {
430
+ this._invisiblePaddingProperty = 'height';
431
+ this._offsetType = 'offsetTop';
432
+ this._pageOffsetType = 'pageYOffset';
433
+ this._childScrollDim = 'childHeight';
434
+ this._marginDir = 'margin-top';
435
+ this._translateDir = 'translateY';
436
+ this._scrollType = 'scrollTop';
437
+ }
438
+ }
439
+ debounce(func, wait) {
440
+ const throttled = this.throttleTrailing(func, wait);
441
+ const result = function () {
442
+ throttled['cancel']();
443
+ throttled.apply(this, arguments);
444
+ };
445
+ result['cancel'] = function () {
446
+ throttled['cancel']();
447
+ };
448
+ return result;
449
+ }
450
+ throttleTrailing(func, wait) {
451
+ let timeout = undefined;
452
+ let _arguments = arguments;
453
+ const result = function () {
454
+ const _this = this;
455
+ _arguments = arguments;
456
+ if (timeout) {
457
+ return;
458
+ }
459
+ if (wait <= 0) {
460
+ func.apply(_this, _arguments);
461
+ }
462
+ else {
463
+ timeout = setTimeout(function () {
464
+ timeout = undefined;
465
+ func.apply(_this, _arguments);
466
+ }, wait);
467
+ }
468
+ };
469
+ result['cancel'] = function () {
470
+ if (timeout) {
471
+ clearTimeout(timeout);
472
+ timeout = undefined;
473
+ }
474
+ };
475
+ return result;
476
+ }
477
+ calculatedScrollbarWidth = 0;
478
+ calculatedScrollbarHeight = 0;
479
+ padding = 0;
480
+ previousViewPort = {};
481
+ currentTween;
482
+ cachedItemsLength;
483
+ disposeScrollHandler;
484
+ disposeResizeHandler;
485
+ refresh_internal(itemsArrayModified, refreshCompletedCallback = undefined, maxRunTimes = 2) {
486
+ //note: maxRunTimes is to force it to keep recalculating if the previous iteration caused a re-render (different sliced items in viewport or scrollPosition changed).
487
+ //The default of 2x max will probably be accurate enough without causing too large a performance bottleneck
488
+ //The code would typically quit out on the 2nd iteration anyways. The main time it'd think more than 2 runs would be necessary would be for vastly different sized child items or if this is the 1st time the items array was initialized.
489
+ //Without maxRunTimes, If the user is actively scrolling this code would become an infinite loop until they stopped scrolling. This would be okay, except each scroll event would start an additional infinte loop. We want to short-circuit it to prevent this.
490
+ if (itemsArrayModified &&
491
+ this.previousViewPort &&
492
+ this.previousViewPort.scrollStartPosition > 0) {
493
+ //if items were prepended, scroll forward to keep same items visible
494
+ let oldViewPort = this.previousViewPort;
495
+ let oldViewPortItems = this.viewPortItems;
496
+ let oldRefreshCompletedCallback = refreshCompletedCallback;
497
+ refreshCompletedCallback = () => {
498
+ let scrollLengthDelta = this.previousViewPort.scrollLength - oldViewPort.scrollLength;
499
+ if (scrollLengthDelta > 0 && this.viewPortItems) {
500
+ let oldStartItem = oldViewPortItems[0];
501
+ let oldStartItemIndex = this.items.findIndex((x) => this.compareItems(oldStartItem, x));
502
+ if (oldStartItemIndex > this.previousViewPort.startIndexWithBuffer) {
503
+ let itemOrderChanged = false;
504
+ for (let i = 1; i < this.viewPortItems.length; ++i) {
505
+ if (!this.compareItems(this.items[oldStartItemIndex + i], oldViewPortItems[i])) {
506
+ itemOrderChanged = true;
507
+ break;
508
+ }
509
+ }
510
+ if (!itemOrderChanged) {
511
+ this.scrollToPosition(this.previousViewPort.scrollStartPosition + scrollLengthDelta, 0, oldRefreshCompletedCallback);
512
+ return;
513
+ }
514
+ }
515
+ }
516
+ if (oldRefreshCompletedCallback) {
517
+ oldRefreshCompletedCallback();
518
+ }
519
+ };
520
+ }
521
+ this.zone.runOutsideAngular(() => {
522
+ requestAnimationFrame(() => {
523
+ if (itemsArrayModified) {
524
+ this.resetWrapGroupDimensions();
525
+ }
526
+ let viewport = this.calculateViewport();
527
+ let startChanged = itemsArrayModified ||
528
+ viewport.startIndex !== this.previousViewPort.startIndex;
529
+ let endChanged = itemsArrayModified ||
530
+ viewport.endIndex !== this.previousViewPort.endIndex;
531
+ let scrollLengthChanged = viewport.scrollLength !== this.previousViewPort.scrollLength;
532
+ let paddingChanged = viewport.padding !== this.previousViewPort.padding;
533
+ let scrollPositionChanged = viewport.scrollStartPosition !==
534
+ this.previousViewPort.scrollStartPosition ||
535
+ viewport.scrollEndPosition !==
536
+ this.previousViewPort.scrollEndPosition ||
537
+ viewport.maxScrollPosition !==
538
+ this.previousViewPort.maxScrollPosition;
539
+ this.previousViewPort = viewport;
540
+ if (scrollLengthChanged) {
541
+ this.renderer.setStyle(this.invisiblePaddingElementRef.nativeElement, this._invisiblePaddingProperty, `${viewport.scrollLength}px`);
542
+ }
543
+ if (paddingChanged) {
544
+ if (this.useMarginInsteadOfTranslate) {
545
+ this.renderer.setStyle(this.contentElementRef.nativeElement, this._marginDir, `${viewport.padding}px`);
546
+ }
547
+ else {
548
+ this.renderer.setStyle(this.contentElementRef.nativeElement, 'transform', `${this._translateDir}(${viewport.padding}px)`);
549
+ this.renderer.setStyle(this.contentElementRef.nativeElement, 'webkitTransform', `${this._translateDir}(${viewport.padding}px)`);
550
+ }
551
+ }
552
+ if (this.headerElementRef) {
553
+ let scrollPosition = this.getScrollElement()[this._scrollType];
554
+ let containerOffset = this.getElementsOffset();
555
+ let offset = Math.max(scrollPosition -
556
+ viewport.padding -
557
+ containerOffset +
558
+ this.headerElementRef.nativeElement.clientHeight, 0);
559
+ this.renderer.setStyle(this.headerElementRef.nativeElement, 'transform', `${this._translateDir}(${offset}px)`);
560
+ this.renderer.setStyle(this.headerElementRef.nativeElement, 'webkitTransform', `${this._translateDir}(${offset}px)`);
561
+ }
562
+ const changeEventArg = startChanged || endChanged
563
+ ? {
564
+ startIndex: viewport.startIndex,
565
+ endIndex: viewport.endIndex,
566
+ scrollStartPosition: viewport.scrollStartPosition,
567
+ scrollEndPosition: viewport.scrollEndPosition,
568
+ startIndexWithBuffer: viewport.startIndexWithBuffer,
569
+ endIndexWithBuffer: viewport.endIndexWithBuffer,
570
+ maxScrollPosition: viewport.maxScrollPosition,
571
+ }
572
+ : undefined;
573
+ if (startChanged || endChanged || scrollPositionChanged) {
574
+ const handleChanged = () => {
575
+ // update the scroll list to trigger re-render of components in viewport
576
+ this.viewPortItems =
577
+ viewport.startIndexWithBuffer >= 0 &&
578
+ viewport.endIndexWithBuffer >= 0
579
+ ? this.items.slice(viewport.startIndexWithBuffer, viewport.endIndexWithBuffer + 1)
580
+ : [];
581
+ this.vsUpdate.emit(this.viewPortItems);
582
+ if (startChanged) {
583
+ this.vsStart.emit(changeEventArg);
584
+ }
585
+ if (endChanged) {
586
+ this.vsEnd.emit(changeEventArg);
587
+ }
588
+ if (startChanged || endChanged) {
589
+ this.changeDetectorRef.markForCheck();
590
+ this.vsChange.emit(changeEventArg);
591
+ }
592
+ if (maxRunTimes > 0) {
593
+ this.refresh_internal(false, refreshCompletedCallback, maxRunTimes - 1);
594
+ return;
595
+ }
596
+ if (refreshCompletedCallback) {
597
+ refreshCompletedCallback();
598
+ }
599
+ };
600
+ if (this.executeRefreshOutsideAngularZone) {
601
+ handleChanged();
602
+ }
603
+ else {
604
+ this.zone.run(handleChanged);
605
+ }
606
+ }
607
+ else {
608
+ if (maxRunTimes > 0 && (scrollLengthChanged || paddingChanged)) {
609
+ this.refresh_internal(false, refreshCompletedCallback, maxRunTimes - 1);
610
+ return;
611
+ }
612
+ if (refreshCompletedCallback) {
613
+ refreshCompletedCallback();
614
+ }
615
+ }
616
+ });
617
+ });
618
+ }
619
+ getScrollElement() {
620
+ return this.parentScroll instanceof Window
621
+ ? document.scrollingElement || document.documentElement || document.body
622
+ : this.parentScroll || this.element.nativeElement;
623
+ }
624
+ addScrollEventHandlers() {
625
+ if (this.isAngularUniversalSSR) {
626
+ return;
627
+ }
628
+ let scrollElement = this.getScrollElement();
629
+ this.removeScrollEventHandlers();
630
+ this.zone.runOutsideAngular(() => {
631
+ if (this.parentScroll instanceof Window) {
632
+ this.disposeScrollHandler = this.renderer.listen('window', 'scroll', this.onScroll);
633
+ this.disposeResizeHandler = this.renderer.listen('window', 'resize', this.onScroll);
634
+ }
635
+ else {
636
+ this.disposeScrollHandler = this.renderer.listen(scrollElement, 'scroll', this.onScroll);
637
+ if (this._checkResizeInterval > 0) {
638
+ this.checkScrollElementResizedTimer = setInterval(() => {
639
+ this.checkScrollElementResized();
640
+ }, this._checkResizeInterval);
641
+ }
642
+ }
643
+ });
644
+ }
645
+ removeScrollEventHandlers() {
646
+ if (this.checkScrollElementResizedTimer) {
647
+ clearInterval(this.checkScrollElementResizedTimer);
648
+ }
649
+ if (this.disposeScrollHandler) {
650
+ this.disposeScrollHandler();
651
+ this.disposeScrollHandler = undefined;
652
+ }
653
+ if (this.disposeResizeHandler) {
654
+ this.disposeResizeHandler();
655
+ this.disposeResizeHandler = undefined;
656
+ }
657
+ }
658
+ getElementsOffset() {
659
+ if (this.isAngularUniversalSSR) {
660
+ return 0;
661
+ }
662
+ let offset = 0;
663
+ if (this.containerElementRef && this.containerElementRef.nativeElement) {
664
+ offset += this.containerElementRef.nativeElement[this._offsetType];
665
+ }
666
+ if (this.parentScroll) {
667
+ let scrollElement = this.getScrollElement();
668
+ let elementClientRect = this.getElementSize(this.element.nativeElement);
669
+ let scrollClientRect = this.getElementSize(scrollElement);
670
+ if (this.horizontal) {
671
+ offset += elementClientRect.left - scrollClientRect.left;
672
+ }
673
+ else {
674
+ offset += elementClientRect.top - scrollClientRect.top;
675
+ }
676
+ if (!(this.parentScroll instanceof Window)) {
677
+ offset += scrollElement[this._scrollType];
678
+ }
679
+ }
680
+ return offset;
681
+ }
682
+ countItemsPerWrapGroup() {
683
+ if (this.isAngularUniversalSSR) {
684
+ return Math.round(this.horizontal
685
+ ? this.ssrViewportHeight / this.ssrChildHeight
686
+ : this.ssrViewportWidth / this.ssrChildWidth);
687
+ }
688
+ let propertyName = this.horizontal ? 'offsetLeft' : 'offsetTop';
689
+ let children = ((this.containerElementRef && this.containerElementRef.nativeElement) ||
690
+ this.contentElementRef.nativeElement).children;
691
+ let childrenLength = children ? children.length : 0;
692
+ if (childrenLength === 0) {
693
+ return 1;
694
+ }
695
+ let firstOffset = children[0][propertyName];
696
+ let result = 1;
697
+ while (result < childrenLength &&
698
+ firstOffset === children[result][propertyName]) {
699
+ ++result;
700
+ }
701
+ return result;
702
+ }
703
+ getScrollStartPosition() {
704
+ let windowScrollValue = undefined;
705
+ if (this.parentScroll instanceof Window) {
706
+ windowScrollValue = window[this._pageOffsetType];
707
+ }
708
+ return windowScrollValue || this.getScrollElement()[this._scrollType] || 0;
709
+ }
710
+ minMeasuredChildWidth;
711
+ minMeasuredChildHeight;
712
+ wrapGroupDimensions;
713
+ resetWrapGroupDimensions() {
714
+ const oldWrapGroupDimensions = this.wrapGroupDimensions;
715
+ this.invalidateAllCachedMeasurements();
716
+ if (!this.enableUnequalChildrenSizes ||
717
+ !oldWrapGroupDimensions ||
718
+ oldWrapGroupDimensions.numberOfKnownWrapGroupChildSizes === 0) {
719
+ return;
720
+ }
721
+ const itemsPerWrapGroup = this.countItemsPerWrapGroup();
722
+ for (let wrapGroupIndex = 0; wrapGroupIndex < oldWrapGroupDimensions.maxChildSizePerWrapGroup.length; ++wrapGroupIndex) {
723
+ const oldWrapGroupDimension = oldWrapGroupDimensions.maxChildSizePerWrapGroup[wrapGroupIndex];
724
+ if (!oldWrapGroupDimension ||
725
+ !oldWrapGroupDimension.items ||
726
+ !oldWrapGroupDimension.items.length) {
727
+ continue;
728
+ }
729
+ if (oldWrapGroupDimension.items.length !== itemsPerWrapGroup) {
730
+ return;
731
+ }
732
+ let itemsChanged = false;
733
+ let arrayStartIndex = itemsPerWrapGroup * wrapGroupIndex;
734
+ for (let i = 0; i < itemsPerWrapGroup; ++i) {
735
+ if (!this.compareItems(oldWrapGroupDimension.items[i], this.items[arrayStartIndex + i])) {
736
+ itemsChanged = true;
737
+ break;
738
+ }
739
+ }
740
+ if (!itemsChanged) {
741
+ ++this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
742
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths +=
743
+ oldWrapGroupDimension.childWidth || 0;
744
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights +=
745
+ oldWrapGroupDimension.childHeight || 0;
746
+ this.wrapGroupDimensions.maxChildSizePerWrapGroup[wrapGroupIndex] =
747
+ oldWrapGroupDimension;
748
+ }
749
+ }
750
+ }
751
+ calculateDimensions() {
752
+ let scrollElement = this.getScrollElement();
753
+ const maxCalculatedScrollBarSize = 25; // Note: Formula to auto-calculate doesn't work for ParentScroll, so we default to this if not set by consuming application
754
+ this.calculatedScrollbarHeight = Math.max(Math.min(scrollElement.offsetHeight - scrollElement.clientHeight, maxCalculatedScrollBarSize), this.calculatedScrollbarHeight);
755
+ this.calculatedScrollbarWidth = Math.max(Math.min(scrollElement.offsetWidth - scrollElement.clientWidth, maxCalculatedScrollBarSize), this.calculatedScrollbarWidth);
756
+ let viewportWidth = scrollElement.offsetWidth -
757
+ (this.scrollbarWidth ||
758
+ this.calculatedScrollbarWidth ||
759
+ (this.horizontal ? 0 : maxCalculatedScrollBarSize));
760
+ let viewportHeight = scrollElement.offsetHeight -
761
+ (this.scrollbarHeight ||
762
+ this.calculatedScrollbarHeight ||
763
+ (this.horizontal ? maxCalculatedScrollBarSize : 0));
764
+ let content = (this.containerElementRef && this.containerElementRef.nativeElement) ||
765
+ this.contentElementRef.nativeElement;
766
+ let itemsPerWrapGroup = this.countItemsPerWrapGroup();
767
+ let wrapGroupsPerPage;
768
+ let defaultChildWidth;
769
+ let defaultChildHeight;
770
+ if (this.isAngularUniversalSSR) {
771
+ viewportWidth = this.ssrViewportWidth;
772
+ viewportHeight = this.ssrViewportHeight;
773
+ defaultChildWidth = this.ssrChildWidth;
774
+ defaultChildHeight = this.ssrChildHeight;
775
+ let itemsPerRow = Math.max(Math.ceil(viewportWidth / defaultChildWidth), 1);
776
+ let itemsPerCol = Math.max(Math.ceil(viewportHeight / defaultChildHeight), 1);
777
+ wrapGroupsPerPage = this.horizontal ? itemsPerRow : itemsPerCol;
778
+ }
779
+ else if (!this.enableUnequalChildrenSizes) {
780
+ if (content.children.length > 0) {
781
+ if (!this.childWidth || !this.childHeight) {
782
+ if (!this.minMeasuredChildWidth && viewportWidth > 0) {
783
+ this.minMeasuredChildWidth = viewportWidth;
784
+ }
785
+ if (!this.minMeasuredChildHeight && viewportHeight > 0) {
786
+ this.minMeasuredChildHeight = viewportHeight;
787
+ }
788
+ }
789
+ let child = content.children[0];
790
+ let clientRect = this.getElementSize(child);
791
+ this.minMeasuredChildWidth = Math.min(this.minMeasuredChildWidth, clientRect.width);
792
+ this.minMeasuredChildHeight = Math.min(this.minMeasuredChildHeight, clientRect.height);
793
+ }
794
+ defaultChildWidth =
795
+ this.childWidth || this.minMeasuredChildWidth || viewportWidth;
796
+ defaultChildHeight =
797
+ this.childHeight || this.minMeasuredChildHeight || viewportHeight;
798
+ let itemsPerRow = Math.max(Math.ceil(viewportWidth / defaultChildWidth), 1);
799
+ let itemsPerCol = Math.max(Math.ceil(viewportHeight / defaultChildHeight), 1);
800
+ wrapGroupsPerPage = this.horizontal ? itemsPerRow : itemsPerCol;
801
+ }
802
+ else {
803
+ let scrollOffset = scrollElement[this._scrollType] -
804
+ (this.previousViewPort ? this.previousViewPort.padding : 0);
805
+ let arrayStartIndex = this.previousViewPort.startIndexWithBuffer || 0;
806
+ let wrapGroupIndex = Math.ceil(arrayStartIndex / itemsPerWrapGroup);
807
+ let maxWidthForWrapGroup = 0;
808
+ let maxHeightForWrapGroup = 0;
809
+ let sumOfVisibleMaxWidths = 0;
810
+ let sumOfVisibleMaxHeights = 0;
811
+ wrapGroupsPerPage = 0;
812
+ for (let i = 0; i < content.children.length; ++i) {
813
+ ++arrayStartIndex;
814
+ let child = content.children[i];
815
+ let clientRect = this.getElementSize(child);
816
+ maxWidthForWrapGroup = Math.max(maxWidthForWrapGroup, clientRect.width);
817
+ maxHeightForWrapGroup = Math.max(maxHeightForWrapGroup, clientRect.height);
818
+ if (arrayStartIndex % itemsPerWrapGroup === 0) {
819
+ let oldValue = this.wrapGroupDimensions.maxChildSizePerWrapGroup[wrapGroupIndex];
820
+ if (oldValue) {
821
+ --this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
822
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths -=
823
+ oldValue.childWidth || 0;
824
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights -=
825
+ oldValue.childHeight || 0;
826
+ }
827
+ ++this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
828
+ const items = this.items.slice(arrayStartIndex - itemsPerWrapGroup, arrayStartIndex);
829
+ this.wrapGroupDimensions.maxChildSizePerWrapGroup[wrapGroupIndex] = {
830
+ childWidth: maxWidthForWrapGroup,
831
+ childHeight: maxHeightForWrapGroup,
832
+ items: items,
833
+ };
834
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths +=
835
+ maxWidthForWrapGroup;
836
+ this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights +=
837
+ maxHeightForWrapGroup;
838
+ if (this.horizontal) {
839
+ let maxVisibleWidthForWrapGroup = Math.min(maxWidthForWrapGroup, Math.max(viewportWidth - sumOfVisibleMaxWidths, 0));
840
+ if (scrollOffset > 0) {
841
+ let scrollOffsetToRemove = Math.min(scrollOffset, maxVisibleWidthForWrapGroup);
842
+ maxVisibleWidthForWrapGroup -= scrollOffsetToRemove;
843
+ scrollOffset -= scrollOffsetToRemove;
844
+ }
845
+ sumOfVisibleMaxWidths += maxVisibleWidthForWrapGroup;
846
+ if (maxVisibleWidthForWrapGroup > 0 &&
847
+ viewportWidth >= sumOfVisibleMaxWidths) {
848
+ ++wrapGroupsPerPage;
849
+ }
850
+ }
851
+ else {
852
+ let maxVisibleHeightForWrapGroup = Math.min(maxHeightForWrapGroup, Math.max(viewportHeight - sumOfVisibleMaxHeights, 0));
853
+ if (scrollOffset > 0) {
854
+ let scrollOffsetToRemove = Math.min(scrollOffset, maxVisibleHeightForWrapGroup);
855
+ maxVisibleHeightForWrapGroup -= scrollOffsetToRemove;
856
+ scrollOffset -= scrollOffsetToRemove;
857
+ }
858
+ sumOfVisibleMaxHeights += maxVisibleHeightForWrapGroup;
859
+ if (maxVisibleHeightForWrapGroup > 0 &&
860
+ viewportHeight >= sumOfVisibleMaxHeights) {
861
+ ++wrapGroupsPerPage;
862
+ }
863
+ }
864
+ ++wrapGroupIndex;
865
+ maxWidthForWrapGroup = 0;
866
+ maxHeightForWrapGroup = 0;
867
+ }
868
+ }
869
+ let averageChildWidth = this.wrapGroupDimensions.sumOfKnownWrapGroupChildWidths /
870
+ this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
871
+ let averageChildHeight = this.wrapGroupDimensions.sumOfKnownWrapGroupChildHeights /
872
+ this.wrapGroupDimensions.numberOfKnownWrapGroupChildSizes;
873
+ defaultChildWidth = this.childWidth || averageChildWidth || viewportWidth;
874
+ defaultChildHeight =
875
+ this.childHeight || averageChildHeight || viewportHeight;
876
+ if (this.horizontal) {
877
+ if (viewportWidth > sumOfVisibleMaxWidths) {
878
+ wrapGroupsPerPage += Math.ceil((viewportWidth - sumOfVisibleMaxWidths) / defaultChildWidth);
879
+ }
880
+ }
881
+ else {
882
+ if (viewportHeight > sumOfVisibleMaxHeights) {
883
+ wrapGroupsPerPage += Math.ceil((viewportHeight - sumOfVisibleMaxHeights) / defaultChildHeight);
884
+ }
885
+ }
886
+ }
887
+ let itemCount = this.items.length;
888
+ let itemsPerPage = itemsPerWrapGroup * wrapGroupsPerPage;
889
+ let pageCount_fractional = itemCount / itemsPerPage;
890
+ let numberOfWrapGroups = Math.ceil(itemCount / itemsPerWrapGroup);
891
+ let scrollLength = 0;
892
+ let defaultScrollLengthPerWrapGroup = this.horizontal
893
+ ? defaultChildWidth
894
+ : defaultChildHeight;
895
+ if (this.enableUnequalChildrenSizes) {
896
+ let numUnknownChildSizes = 0;
897
+ for (let i = 0; i < numberOfWrapGroups; ++i) {
898
+ let childSize = this.wrapGroupDimensions.maxChildSizePerWrapGroup[i] &&
899
+ this.wrapGroupDimensions.maxChildSizePerWrapGroup[i][this._childScrollDim];
900
+ if (childSize) {
901
+ scrollLength += childSize;
902
+ }
903
+ else {
904
+ ++numUnknownChildSizes;
905
+ }
906
+ }
907
+ scrollLength += Math.round(numUnknownChildSizes * defaultScrollLengthPerWrapGroup);
908
+ }
909
+ else {
910
+ scrollLength = numberOfWrapGroups * defaultScrollLengthPerWrapGroup;
911
+ }
912
+ if (this.headerElementRef) {
913
+ scrollLength += this.headerElementRef.nativeElement.clientHeight;
914
+ }
915
+ let viewportLength = this.horizontal ? viewportWidth : viewportHeight;
916
+ let maxScrollPosition = Math.max(scrollLength - viewportLength, 0);
917
+ return {
918
+ itemCount: itemCount,
919
+ itemsPerWrapGroup: itemsPerWrapGroup,
920
+ wrapGroupsPerPage: wrapGroupsPerPage,
921
+ itemsPerPage: itemsPerPage,
922
+ pageCount_fractional: pageCount_fractional,
923
+ childWidth: defaultChildWidth,
924
+ childHeight: defaultChildHeight,
925
+ scrollLength: scrollLength,
926
+ viewportLength: viewportLength,
927
+ maxScrollPosition: maxScrollPosition,
928
+ };
929
+ }
930
+ cachedPageSize = 0;
931
+ previousScrollNumberElements = 0;
932
+ calculatePadding(arrayStartIndexWithBuffer, dimensions) {
933
+ if (dimensions.itemCount === 0) {
934
+ return 0;
935
+ }
936
+ let defaultScrollLengthPerWrapGroup = dimensions[this._childScrollDim];
937
+ let startingWrapGroupIndex = Math.floor(arrayStartIndexWithBuffer / dimensions.itemsPerWrapGroup) || 0;
938
+ if (!this.enableUnequalChildrenSizes) {
939
+ return defaultScrollLengthPerWrapGroup * startingWrapGroupIndex;
940
+ }
941
+ let numUnknownChildSizes = 0;
942
+ let result = 0;
943
+ for (let i = 0; i < startingWrapGroupIndex; ++i) {
944
+ let childSize = this.wrapGroupDimensions.maxChildSizePerWrapGroup[i] &&
945
+ this.wrapGroupDimensions.maxChildSizePerWrapGroup[i][this._childScrollDim];
946
+ if (childSize) {
947
+ result += childSize;
948
+ }
949
+ else {
950
+ ++numUnknownChildSizes;
951
+ }
952
+ }
953
+ result += Math.round(numUnknownChildSizes * defaultScrollLengthPerWrapGroup);
954
+ return result;
955
+ }
956
+ calculatePageInfo(scrollPosition, dimensions) {
957
+ let scrollPercentage = 0;
958
+ if (this.enableUnequalChildrenSizes) {
959
+ const numberOfWrapGroups = Math.ceil(dimensions.itemCount / dimensions.itemsPerWrapGroup);
960
+ let totalScrolledLength = 0;
961
+ let defaultScrollLengthPerWrapGroup = dimensions[this._childScrollDim];
962
+ for (let i = 0; i < numberOfWrapGroups; ++i) {
963
+ let childSize = this.wrapGroupDimensions.maxChildSizePerWrapGroup[i] &&
964
+ this.wrapGroupDimensions.maxChildSizePerWrapGroup[i][this._childScrollDim];
965
+ if (childSize) {
966
+ totalScrolledLength += childSize;
967
+ }
968
+ else {
969
+ totalScrolledLength += defaultScrollLengthPerWrapGroup;
970
+ }
971
+ if (scrollPosition < totalScrolledLength) {
972
+ scrollPercentage = i / numberOfWrapGroups;
973
+ break;
974
+ }
975
+ }
976
+ }
977
+ else {
978
+ scrollPercentage = scrollPosition / dimensions.scrollLength;
979
+ }
980
+ let startingArrayIndex_fractional = Math.min(Math.max(scrollPercentage * dimensions.pageCount_fractional, 0), dimensions.pageCount_fractional) * dimensions.itemsPerPage;
981
+ let maxStart = dimensions.itemCount - dimensions.itemsPerPage - 1;
982
+ let arrayStartIndex = Math.min(Math.floor(startingArrayIndex_fractional), maxStart);
983
+ arrayStartIndex -= arrayStartIndex % dimensions.itemsPerWrapGroup; // round down to start of wrapGroup
984
+ if (this.stripedTable) {
985
+ let bufferBoundary = 2 * dimensions.itemsPerWrapGroup;
986
+ if (arrayStartIndex % bufferBoundary !== 0) {
987
+ arrayStartIndex = Math.max(arrayStartIndex - (arrayStartIndex % bufferBoundary), 0);
988
+ }
989
+ }
990
+ let arrayEndIndex = Math.ceil(startingArrayIndex_fractional) + dimensions.itemsPerPage - 1;
991
+ let endIndexWithinWrapGroup = (arrayEndIndex + 1) % dimensions.itemsPerWrapGroup;
992
+ if (endIndexWithinWrapGroup > 0) {
993
+ arrayEndIndex += dimensions.itemsPerWrapGroup - endIndexWithinWrapGroup; // round up to end of wrapGroup
994
+ }
995
+ if (isNaN(arrayStartIndex)) {
996
+ arrayStartIndex = 0;
997
+ }
998
+ if (isNaN(arrayEndIndex)) {
999
+ arrayEndIndex = 0;
1000
+ }
1001
+ arrayStartIndex = Math.min(Math.max(arrayStartIndex, 0), dimensions.itemCount - 1);
1002
+ arrayEndIndex = Math.min(Math.max(arrayEndIndex, 0), dimensions.itemCount - 1);
1003
+ let bufferSize = this.bufferAmount * dimensions.itemsPerWrapGroup;
1004
+ let startIndexWithBuffer = Math.min(Math.max(arrayStartIndex - bufferSize, 0), dimensions.itemCount - 1);
1005
+ let endIndexWithBuffer = Math.min(Math.max(arrayEndIndex + bufferSize, 0), dimensions.itemCount - 1);
1006
+ return {
1007
+ startIndex: arrayStartIndex,
1008
+ endIndex: arrayEndIndex,
1009
+ startIndexWithBuffer: startIndexWithBuffer,
1010
+ endIndexWithBuffer: endIndexWithBuffer,
1011
+ scrollStartPosition: scrollPosition,
1012
+ scrollEndPosition: scrollPosition + dimensions.viewportLength,
1013
+ maxScrollPosition: dimensions.maxScrollPosition,
1014
+ };
1015
+ }
1016
+ calculateViewport() {
1017
+ let dimensions = this.calculateDimensions();
1018
+ let offset = this.getElementsOffset();
1019
+ let scrollStartPosition = this.getScrollStartPosition();
1020
+ if (scrollStartPosition > dimensions.scrollLength + offset &&
1021
+ !(this.parentScroll instanceof Window)) {
1022
+ scrollStartPosition = dimensions.scrollLength;
1023
+ }
1024
+ else {
1025
+ scrollStartPosition -= offset;
1026
+ }
1027
+ scrollStartPosition = Math.max(0, scrollStartPosition);
1028
+ let pageInfo = this.calculatePageInfo(scrollStartPosition, dimensions);
1029
+ let newPadding = this.calculatePadding(pageInfo.startIndexWithBuffer, dimensions);
1030
+ let newScrollLength = dimensions.scrollLength;
1031
+ return {
1032
+ startIndex: pageInfo.startIndex,
1033
+ endIndex: pageInfo.endIndex,
1034
+ startIndexWithBuffer: pageInfo.startIndexWithBuffer,
1035
+ endIndexWithBuffer: pageInfo.endIndexWithBuffer,
1036
+ padding: Math.round(newPadding),
1037
+ scrollLength: Math.round(newScrollLength),
1038
+ scrollStartPosition: pageInfo.scrollStartPosition,
1039
+ scrollEndPosition: pageInfo.scrollEndPosition,
1040
+ maxScrollPosition: pageInfo.maxScrollPosition,
1041
+ };
1042
+ }
1043
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: VirtualScrollerComponent, deps: [{ token: i0.ElementRef }, { token: i0.Renderer2 }, { token: i0.NgZone }, { token: i0.ChangeDetectorRef }, { token: PLATFORM_ID }, { token: 'virtual-scroller-default-options', optional: true }], target: i0.ɵɵFactoryTarget.Component });
1044
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.14", type: VirtualScrollerComponent, selector: "virtual-scroller,[virtualScroller]", inputs: { executeRefreshOutsideAngularZone: "executeRefreshOutsideAngularZone", enableUnequalChildrenSizes: "enableUnequalChildrenSizes", useMarginInsteadOfTranslate: "useMarginInsteadOfTranslate", modifyOverflowStyleOfParentScroll: "modifyOverflowStyleOfParentScroll", stripedTable: "stripedTable", scrollbarWidth: "scrollbarWidth", scrollbarHeight: "scrollbarHeight", childWidth: "childWidth", childHeight: "childHeight", ssrChildWidth: "ssrChildWidth", ssrChildHeight: "ssrChildHeight", ssrViewportWidth: "ssrViewportWidth", ssrViewportHeight: "ssrViewportHeight", bufferAmount: "bufferAmount", scrollAnimationTime: "scrollAnimationTime", resizeBypassRefreshThreshold: "resizeBypassRefreshThreshold", scrollThrottlingTime: "scrollThrottlingTime", scrollDebounceTime: "scrollDebounceTime", checkResizeInterval: "checkResizeInterval", items: "items", compareItems: "compareItems", horizontal: "horizontal", parentScroll: "parentScroll" }, outputs: { vsUpdate: "vsUpdate", vsChange: "vsChange", vsStart: "vsStart", vsEnd: "vsEnd" }, host: { properties: { "class.horizontal": "horizontal", "class.vertical": "!horizontal", "class.selfScroll": "!parentScroll" } }, queries: [{ propertyName: "headerElementRef", first: true, predicate: ["header"], descendants: true, read: ElementRef }, { propertyName: "containerElementRef", first: true, predicate: ["container"], descendants: true, read: ElementRef }], viewQueries: [{ propertyName: "contentElementRef", first: true, predicate: ["content"], descendants: true, read: ElementRef }, { propertyName: "invisiblePaddingElementRef", first: true, predicate: ["invisiblePadding"], descendants: true, read: ElementRef }], exportAs: ["virtualScroller"], usesOnChanges: true, ngImport: i0, template: `
1045
+ <div class="total-padding" #invisiblePadding></div>
1046
+ <div class="scrollable-content" #content>
1047
+ <ng-content></ng-content>
1048
+ </div>
1049
+ `, isInline: true, styles: [":host{position:relative;display:block;-webkit-overflow-scrolling:touch}:host.horizontal.selfScroll{overflow-y:visible;overflow-x:auto}:host.vertical.selfScroll{overflow-y:auto;overflow-x:visible}.scrollable-content{top:0;left:0;width:100%;height:100%;max-width:100vw;max-height:100vh;position:absolute}.scrollable-content ::ng-deep>*{box-sizing:border-box}:host.horizontal{white-space:nowrap}:host.horizontal .scrollable-content{display:flex}:host.horizontal .scrollable-content ::ng-deep>*{flex-shrink:0;flex-grow:0;white-space:initial}.total-padding{width:1px;opacity:0}:host.horizontal .total-padding{height:100%}\n"] });
1050
+ }
1051
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: VirtualScrollerComponent, decorators: [{
1052
+ type: Component,
1053
+ args: [{ selector: 'virtual-scroller,[virtualScroller]', exportAs: 'virtualScroller', template: `
1054
+ <div class="total-padding" #invisiblePadding></div>
1055
+ <div class="scrollable-content" #content>
1056
+ <ng-content></ng-content>
1057
+ </div>
1058
+ `, host: {
1059
+ '[class.horizontal]': 'horizontal',
1060
+ '[class.vertical]': '!horizontal',
1061
+ '[class.selfScroll]': '!parentScroll',
1062
+ }, styles: [":host{position:relative;display:block;-webkit-overflow-scrolling:touch}:host.horizontal.selfScroll{overflow-y:visible;overflow-x:auto}:host.vertical.selfScroll{overflow-y:auto;overflow-x:visible}.scrollable-content{top:0;left:0;width:100%;height:100%;max-width:100vw;max-height:100vh;position:absolute}.scrollable-content ::ng-deep>*{box-sizing:border-box}:host.horizontal{white-space:nowrap}:host.horizontal .scrollable-content{display:flex}:host.horizontal .scrollable-content ::ng-deep>*{flex-shrink:0;flex-grow:0;white-space:initial}.total-padding{width:1px;opacity:0}:host.horizontal .total-padding{height:100%}\n"] }]
1063
+ }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i0.Renderer2 }, { type: i0.NgZone }, { type: i0.ChangeDetectorRef }, { type: Object, decorators: [{
1064
+ type: Inject,
1065
+ args: [PLATFORM_ID]
1066
+ }] }, { type: undefined, decorators: [{
1067
+ type: Optional
1068
+ }, {
1069
+ type: Inject,
1070
+ args: ['virtual-scroller-default-options']
1071
+ }] }], propDecorators: { executeRefreshOutsideAngularZone: [{
1072
+ type: Input
1073
+ }], enableUnequalChildrenSizes: [{
1074
+ type: Input
1075
+ }], useMarginInsteadOfTranslate: [{
1076
+ type: Input
1077
+ }], modifyOverflowStyleOfParentScroll: [{
1078
+ type: Input
1079
+ }], stripedTable: [{
1080
+ type: Input
1081
+ }], scrollbarWidth: [{
1082
+ type: Input
1083
+ }], scrollbarHeight: [{
1084
+ type: Input
1085
+ }], childWidth: [{
1086
+ type: Input
1087
+ }], childHeight: [{
1088
+ type: Input
1089
+ }], ssrChildWidth: [{
1090
+ type: Input
1091
+ }], ssrChildHeight: [{
1092
+ type: Input
1093
+ }], ssrViewportWidth: [{
1094
+ type: Input
1095
+ }], ssrViewportHeight: [{
1096
+ type: Input
1097
+ }], bufferAmount: [{
1098
+ type: Input
1099
+ }], scrollAnimationTime: [{
1100
+ type: Input
1101
+ }], resizeBypassRefreshThreshold: [{
1102
+ type: Input
1103
+ }], scrollThrottlingTime: [{
1104
+ type: Input
1105
+ }], scrollDebounceTime: [{
1106
+ type: Input
1107
+ }], checkResizeInterval: [{
1108
+ type: Input
1109
+ }], items: [{
1110
+ type: Input
1111
+ }], compareItems: [{
1112
+ type: Input
1113
+ }], horizontal: [{
1114
+ type: Input
1115
+ }], parentScroll: [{
1116
+ type: Input
1117
+ }], vsUpdate: [{
1118
+ type: Output
1119
+ }], vsChange: [{
1120
+ type: Output
1121
+ }], vsStart: [{
1122
+ type: Output
1123
+ }], vsEnd: [{
1124
+ type: Output
1125
+ }], contentElementRef: [{
1126
+ type: ViewChild,
1127
+ args: ['content', { read: ElementRef, static: false }]
1128
+ }], invisiblePaddingElementRef: [{
1129
+ type: ViewChild,
1130
+ args: ['invisiblePadding', { read: ElementRef, static: false }]
1131
+ }], headerElementRef: [{
1132
+ type: ContentChild,
1133
+ args: ['header', { read: ElementRef, static: false }]
1134
+ }], containerElementRef: [{
1135
+ type: ContentChild,
1136
+ args: ['container', { read: ElementRef, static: false }]
1137
+ }] } });
1138
+ export class VirtualScrollerModule {
1139
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: VirtualScrollerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
1140
+ static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "18.2.14", ngImport: i0, type: VirtualScrollerModule, declarations: [VirtualScrollerComponent], imports: [CommonModule], exports: [VirtualScrollerComponent] });
1141
+ static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: VirtualScrollerModule, providers: [
1142
+ {
1143
+ provide: 'virtual-scroller-default-options',
1144
+ useFactory: VIRTUAL_SCROLLER_DEFAULT_OPTIONS_FACTORY,
1145
+ },
1146
+ ], imports: [CommonModule] });
1147
+ }
1148
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: VirtualScrollerModule, decorators: [{
1149
+ type: NgModule,
1150
+ args: [{
1151
+ exports: [VirtualScrollerComponent],
1152
+ declarations: [VirtualScrollerComponent],
1153
+ imports: [CommonModule],
1154
+ providers: [
1155
+ {
1156
+ provide: 'virtual-scroller-default-options',
1157
+ useFactory: VIRTUAL_SCROLLER_DEFAULT_OPTIONS_FACTORY,
1158
+ },
1159
+ ],
1160
+ }]
1161
+ }] });
1162
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmlydHVhbC1zY3JvbGwuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9wcm9qZWN0cy9hbmd1bGFyMi1tdWx0aXNlbGVjdC1kcm9wZG93bi1saWIvc3JjL2xpYi92aXJ0dWFsLXNjcm9sbC92aXJ0dWFsLXNjcm9sbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQ0wsU0FBUyxFQUNULFlBQVksRUFDWixVQUFVLEVBQ1YsWUFBWSxFQUNaLE1BQU0sRUFDTixRQUFRLEVBQ1IsS0FBSyxFQUNMLFFBQVEsRUFLUixNQUFNLEVBRU4sU0FBUyxHQUVWLE1BQU0sZUFBZSxDQUFDO0FBRXZCLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxlQUFlLENBQUM7QUFDNUMsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFbkQsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRS9DLE9BQU8sS0FBSyxLQUFLLE1BQU0sbUJBQW1CLENBQUM7O0FBVTNDLE1BQU0sVUFBVSx3Q0FBd0M7SUFDdEQsT0FBTztRQUNMLG9CQUFvQixFQUFFLENBQUM7UUFDdkIsa0JBQWtCLEVBQUUsQ0FBQztRQUNyQixtQkFBbUIsRUFBRSxHQUFHO1FBQ3hCLG1CQUFtQixFQUFFLElBQUk7UUFDekIsNEJBQTRCLEVBQUUsQ0FBQztRQUMvQixpQ0FBaUMsRUFBRSxJQUFJO1FBQ3ZDLFlBQVksRUFBRSxLQUFLO0tBQ3BCLENBQUM7QUFDSixDQUFDO0FBd0VELE1BQU0sT0FBTyx3QkFBd0I7SUF1ZmQ7SUFDQTtJQUNBO0lBQ1Q7SUF6ZkwsYUFBYSxDQUFRO0lBQ3JCLE1BQU0sR0FBRyxNQUFNLENBQUM7SUFFdkIsSUFBVyxZQUFZO1FBQ3JCLElBQUksUUFBUSxHQUFjLElBQUksQ0FBQyxnQkFBZ0IsSUFBUyxFQUFFLENBQUM7UUFDM0QsT0FBTztZQUNMLFVBQVUsRUFBRSxRQUFRLENBQUMsVUFBVSxJQUFJ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QWlCO3NCQUQxQixTQUFTO3VCQUFDLFNBQVMsRUFBRSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFJL0MsMEJBQTBCO3NCQURuQyxTQUFTO3VCQUFDLGtCQUFrQixFQUFFLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQUl4RCxnQkFBZ0I7c0JBRHpCLFlBQVk7dUJBQUMsUUFBUSxFQUFFLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQUlqRCxtQkFBbUI7c0JBRDVCLFlBQVk7dUJBQUMsV0FBVyxFQUFFLEVBQUUsSUFBSSxFQUFFLFVBQVUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFOztBQTJ3Q2hFLE1BQU0sT0FBTyxxQkFBcUI7d0dBQXJCLHFCQUFxQjt5R0FBckIscUJBQXFCLGlCQWgvQ3JCLHdCQUF3QixhQXcrQ3pCLFlBQVksYUF4K0NYLHdCQUF3Qjt5R0FnL0N4QixxQkFBcUIsYUFQckI7WUFDVDtnQkFDRSxPQUFPLEVBQUUsa0NBQWtDO2dCQUMzQyxVQUFVLEVBQUUsd0NBQXdDO2FBQ3JEO1NBQ0YsWUFOUyxZQUFZOzs0RkFRWCxxQkFBcUI7a0JBWGpDLFFBQVE7bUJBQUM7b0JBQ1IsT0FBTyxFQUFFLENBQUMsd0JBQXdCLENBQUM7b0JBQ25DLFlBQVksRUFBRSxDQUFDLHdCQUF3QixDQUFDO29CQUN4QyxPQUFPLEVBQUUsQ0FBQyxZQUFZLENBQUM7b0JBQ3ZCLFNBQVMsRUFBRTt3QkFDVDs0QkFDRSxPQUFPLEVBQUUsa0NBQWtDOzRCQUMzQyxVQUFVLEVBQUUsd0NBQXdDO3lCQUNyRDtxQkFDRjtpQkFDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7XG4gIENvbXBvbmVudCxcbiAgQ29udGVudENoaWxkLFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIEluamVjdCxcbiAgT3B0aW9uYWwsXG4gIElucHV0LFxuICBOZ01vZHVsZSxcbiAgTmdab25lLFxuICBPbkNoYW5nZXMsXG4gIE9uRGVzdHJveSxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFJlbmRlcmVyMixcbiAgVmlld0NoaWxkLFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5cbmltcG9ydCB7IFBMQVRGT1JNX0lEIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBpc1BsYXRmb3JtU2VydmVyIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcblxuaW1wb3J0IHsgQ29tbW9uTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcblxuaW1wb3J0ICogYXMgdHdlZW4gZnJvbSAnQHR3ZWVuanMvdHdlZW4uanMnO1xuaW1wb3J0IHsgVmlydHVhbFNjcm9sbGVyRGVmYXVsdE9wdGlvbnMgfSBmcm9tICcuL2RlZmF1bHRvcHRpb25zJztcbmltcG9ydCB7IElQYWdlSW5mbyB9IGZyb20gJy4vaXBhZ2VpbmZvJztcbmltcG9ydCB7IElWaWV3cG9ydCB9IGZyb20gJy4vaXZpZXdwb3J0JztcblxuaW1wb3J0IHsgV3JhcEdyb3VwRGltZW5zaW9ucyB9IGZyb20gJy4vd3JhcGdyb3VwZGltZW5zaW9ucyc7XG5pbXBvcnQgeyBXcmFwR3JvdXBEaW1lbnNpb24gfSBmcm9tICcuL3dyYXBncm91cGRpbWVuc2lvbic7XG5cbmltcG9ydCB7IElEaW1lbnNpb25zIH0gZnJvbSAnLi9pZGltZW5zaW9uJztcblxuZXhwb3J0IGZ1bmN0aW9uIFZJUlRVQUxfU0NST0xMRVJfREVGQVVMVF9PUFRJT05TX0ZBQ1RPUlkoKTogVmlydHVhbFNjcm9sbGVyRGVmYXVsdE9wdGlvbnMge1xuICByZXR1cm4ge1xuICAgIHNjcm9sbFRocm90dGxpbmdUaW1lOiAwLFxuICAgIHNjcm9sbERlYm91bmNlVGltZTogMCxcbiAgICBzY3JvbGxBbmltYXRpb25UaW1lOiA3NTAsXG4gICAgY2hlY2tSZXNpemVJbnRlcnZhbDogMTAwMCxcbiAgICByZXNpemVCeXBhc3NSZWZyZXNoVGhyZXNob2xkOiA1LFxuICAgIG1vZGlmeU92ZXJmbG93U3R5bGVPZlBhcmVudFNjcm9sbDogdHJ1ZSxcbiAgICBzdHJpcGVkVGFibGU6IGZhbHNlLFxuICB9O1xufVxuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd2aXJ0dWFsLXNjcm9sbGVyLFt2aXJ0dWFsU2Nyb2xsZXJdJyxcbiAgZXhwb3J0QXM6ICd2aXJ0dWFsU2Nyb2xsZXInLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJ0b3RhbC1wYWRkaW5nXCIgI2ludmlzaWJsZVBhZGRpbmc+PC9kaXY+XG4gICAgPGRpdiBjbGFzcz1cInNjcm9sbGFibGUtY29udGVudFwiICNjb250ZW50PlxuICAgICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICAgIDwvZGl2PlxuICBgLFxuICBob3N0OiB7XG4gICAgJ1tjbGFzcy5ob3Jpem9udGFsXSc6ICdob3Jpem9udGFsJyxcbiAgICAnW2NsYXNzLnZlcnRpY2FsXSc6ICchaG9yaXpvbnRhbCcsXG4gICAgJ1tjbGFzcy5zZWxmU2Nyb2xsXSc6ICchcGFyZW50U2Nyb2xsJyxcbiAgfSxcbiAgc3R5bGVzOiBbXG4gICAgYFxuICAgICAgOmhvc3Qge1xuICAgICAgICBwb3NpdGlvbjogcmVsYXRpdmU7XG4gICAgICAgIGRpc3BsYXk6IGJsb2NrO1xuICAgICAgICAtd2Via2l0LW92ZXJmbG93LXNjcm9sbGluZzogdG91Y2g7XG4gICAgICB9XG5cbiAgICAgIDpob3N0Lmhvcml6b250YWwuc2VsZlNjcm9sbCB7XG4gICAgICAgIG92ZXJmbG93LXk6IHZpc2libGU7XG4gICAgICAgIG92ZXJmbG93LXg6IGF1dG87XG4gICAgICB9XG4gICAgICA6aG9zdC52ZXJ0aWNhbC5zZWxmU2Nyb2xsIHtcbiAgICAgICAgb3ZlcmZsb3cteTogYXV0bztcbiAgICAgICAgb3ZlcmZsb3cteDogdmlzaWJsZTtcbiAgICAgIH1cblxuICAgICAgLnNjcm9sbGFibGUtY29udGVudCB7XG4gICAgICAgIHRvcDogMDtcbiAgICAgICAgbGVmdDogMDtcbiAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICAgIGhlaWdodDogMTAwJTtcbiAgICAgICAgbWF4LXdpZHRoOiAxMDB2dztcbiAgICAgICAgbWF4LWhlaWdodDogMTAwdmg7XG4gICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgIH1cblxuICAgICAgLnNjcm9sbGFibGUtY29udGVudCA6Om5nLWRlZXAgPiAqIHtcbiAgICAgICAgYm94LXNpemluZzogYm9yZGVyLWJveDtcbiAgICAgIH1cblxuICAgICAgOmhvc3QuaG9yaXpvbnRhbCB7XG4gICAgICAgIHdoaXRlLXNwYWNlOiBub3dyYXA7XG4gICAgICB9XG5cbiAgICAgIDpob3N0Lmhvcml6b250YWwgLnNjcm9sbGFibGUtY29udGVudCB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICB9XG5cbiAgICAgIDpob3N0Lmhvcml6b250YWwgLnNjcm9sbGFibGUtY29udGVudCA6Om5nLWRlZXAgPiAqIHtcbiAgICAgICAgZmxleC1zaHJpbms6IDA7XG4gICAgICAgIGZsZXgtZ3JvdzogMDtcbiAgICAgICAgd2hpdGUtc3BhY2U6IGluaXRpYWw7XG4gICAgICB9XG5cbiAgICAgIC50b3RhbC1wYWRkaW5nIHtcbiAgICAgICAgd2lkdGg6IDFweDtcbiAgICAgICAgb3BhY2l0eTogMDtcbiAgICAgIH1cblxuICAgICAgOmhvc3QuaG9yaXpvbnRhbCAudG90YWwtcGFkZGluZyB7XG4gICAgICAgIGhlaWdodDogMTAwJTtcbiAgICAgIH1cbiAgICBgLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBWaXJ0dWFsU2Nyb2xsZXJDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uQ2hhbmdlcywgT25EZXN0cm95IHtcbiAgcHVibGljIHZpZXdQb3J0SXRlbXM6IGFueVtdO1xuICBwdWJsaWMgd2luZG93ID0gd2luZG93O1xuXG4gIHB1YmxpYyBnZXQgdmlld1BvcnRJbmZvKCk6IElQYWdlSW5mbyB7XG4gICAgbGV0IHBhZ2VJbmZvOiBJVmlld3BvcnQgPSB0aGlzLnByZXZpb3VzVmlld1BvcnQgfHwgPGFueT57fTtcbiAgICByZXR1cm4ge1xuICAgICAgc3RhcnRJbmRleDogcGFnZUluZm8uc3RhcnRJbmRleCB8fCAwLFxuICAgICAgZW5kSW5kZXg6IHBhZ2VJbmZvLmVuZEluZGV4IHx8IDAsXG4gICAgICBzY3JvbGxTdGFydFBvc2l0aW9uOiBwYWdlSW5mby5zY3JvbGxTdGFydFBvc2l0aW9uIHx8IDAsXG4gICAgICBzY3JvbGxFbmRQb3NpdGlvbjogcGFnZUluZm8uc2Nyb2xsRW5kUG9zaXRpb24gfHwgMCxcbiAgICAgIG1heFNjcm9sbFBvc2l0aW9uOiBwYWdlSW5mby5tYXhTY3JvbGxQb3NpdGlvbiB8fCAwLFxuICAgICAgc3RhcnRJbmRleFdpdGhCdWZmZXI6IHBhZ2VJbmZvLnN0YXJ0SW5kZXhXaXRoQnVmZmVyIHx8IDAsXG4gICAgICBlbmRJbmRleFdpdGhCdWZmZXI6IHBhZ2VJbmZvLmVuZEluZGV4V2l0aEJ1ZmZlciB8fCAwLFxuICAgIH07XG4gIH1cblxuICBASW5wdXQoKVxuICBwdWJsaWMgZXhlY3V0ZVJlZnJlc2hPdXRzaWRlQW5ndWxhclpvbmU6IGJvb2xlYW4gPSBmYWxzZTtcblxuICBwcm90ZWN0ZWQgX2VuYWJsZVVuZXF1YWxDaGlsZHJlblNpemVzOiBib29sZWFuID0gZmFsc2U7XG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBnZXQgZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2VuYWJsZVVuZXF1YWxDaGlsZHJlblNpemVzO1xuICB9XG4gIHB1YmxpYyBzZXQgZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXModmFsdWU6IGJvb2xlYW4pIHtcbiAgICBpZiAodGhpcy5fZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXMgPT09IHZhbHVlKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5fZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXMgPSB2YWx1ZTtcbiAgICB0aGlzLm1pbk1lYXN1cmVkQ2hpbGRXaWR0aCA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLm1pbk1lYXN1cmVkQ2hpbGRIZWlnaHQgPSB1bmRlZmluZWQ7XG4gIH1cblxuICBASW5wdXQoKVxuICBwdWJsaWMgdXNlTWFyZ2luSW5zdGVhZE9mVHJhbnNsYXRlOiBib29sZWFuID0gZmFsc2U7XG5cbiAgQElucHV0KClcbiAgcHVibGljIG1vZGlmeU92ZXJmbG93U3R5bGVPZlBhcmVudFNjcm9sbDogYm9vbGVhbjtcblxuICBASW5wdXQoKVxuICBwdWJsaWMgc3RyaXBlZFRhYmxlOiBib29sZWFuO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBzY3JvbGxiYXJXaWR0aDogbnVtYmVyO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBzY3JvbGxiYXJIZWlnaHQ6IG51bWJlcjtcblxuICBASW5wdXQoKVxuICBwdWJsaWMgY2hpbGRXaWR0aDogbnVtYmVyO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBjaGlsZEhlaWdodDogbnVtYmVyO1xuXG4gIEBJbnB1dCgpXG4gIHB1YmxpYyBzc3JDaGlsZFdpZHRoOiBudW1iZXI7XG5cbiAgQElucHV0KClcbiAgcHVibGljIHNzckNoaWxkSGVpZ2h0OiBudW1iZXI7XG5cbiAgQElucHV0KClcbiAgcHVibGljIHNzclZpZXdwb3J0V2lkdGg6IG51bWJlciA9IDE5MjA7XG5cbiAgQElucHV0KClcbiAgcHVibGljIHNzclZpZXdwb3J0SGVpZ2h0OiBudW1iZXIgPSAxMDgwO1xuXG4gIHByb3RlY3RlZCBfYnVmZmVyQW1vdW50OiBudW1iZXIgPSAwO1xuICBASW5wdXQoKVxuICBwdWJsaWMgZ2V0IGJ1ZmZlckFtb3VudCgpOiBudW1iZXIge1xuICAgIGlmICh0eXBlb2YgdGhpcy5fYnVmZmVyQW1vdW50ID09PSAnbnVtYmVyJyAmJiB0aGlzLl9idWZmZXJBbW91bnQgPj0gMCkge1xuICAgICAgcmV0dXJuIHRoaXMuX2J1ZmZlckFtb3VudDtcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIHRoaXMuZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXMgPyA1IDogMDtcbiAgICB9XG4gIH1cbiAgcHVibGljIHNldCBidWZmZXJBbW91bnQodmFsdWU6IG51bWJlcikge1xuICAgIHRoaXMuX2J1ZmZlckFtb3VudCA9IHZhbHVlO1xuICB9XG5cbiAgQElucHV0KClcbiAgcHVibGljIHNjcm9sbEFuaW1hdGlvblRpbWU6IG51bWJlcjtcblxuICBASW5wdXQoKVxuICBwdWJsaWMgcmVzaXplQnlwYXNzUmVmcmVzaFRocmVzaG9sZDogbnVtYmVyO1xuXG4gIHByb3RlY3RlZCBfc2Nyb2xsVGhyb3R0bGluZ1RpbWU6IG51bWJlcjtcbiAgQElucHV0KClcbiAgcHVibGljIGdldCBzY3JvbGxUaHJvdHRsaW5nVGltZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9zY3JvbGxUaHJvdHRsaW5nVGltZTtcbiAgfVxuICBwdWJsaWMgc2V0IHNjcm9sbFRocm90dGxpbmdUaW1lKHZhbHVlOiBudW1iZXIpIHtcbiAgICB0aGlzLl9zY3JvbGxUaHJvdHRsaW5nVGltZSA9IHZhbHVlO1xuICAgIHRoaXMudXBkYXRlT25TY3JvbGxGdW5jdGlvbigpO1xuICB9XG5cbiAgcHJvdGVjdGVkIF9zY3JvbGxEZWJvdW5jZVRpbWU6IG51bWJlcjtcbiAgQElucHV0KClcbiAgcHVibGljIGdldCBzY3JvbGxEZWJvdW5jZVRpbWUoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fc2Nyb2xsRGVib3VuY2VUaW1lO1xuICB9XG4gIHB1YmxpYyBzZXQgc2Nyb2xsRGVib3VuY2VUaW1lKHZhbHVlOiBudW1iZXIpIHtcbiAgICB0aGlzLl9zY3JvbGxEZWJvdW5jZVRpbWUgPSB2YWx1ZTtcbiAgICB0aGlzLnVwZGF0ZU9uU2Nyb2xsRnVuY3Rpb24oKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvblNjcm9sbDogKCkgPT4gdm9pZDtcbiAgcHJvdGVjdGVkIHVwZGF0ZU9uU2Nyb2xsRnVuY3Rpb24oKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuc2Nyb2xsRGVib3VuY2VUaW1lKSB7XG4gICAgICB0aGlzLm9uU2Nyb2xsID0gPGFueT50aGlzLmRlYm91bmNlKCgpID0+IHtcbiAgICAgICAgdGhpcy5yZWZyZXNoX2ludGVybmFsKGZhbHNlKTtcbiAgICAgIH0sIHRoaXMuc2Nyb2xsRGVib3VuY2VUaW1lKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuc2Nyb2xsVGhyb3R0bGluZ1RpbWUpIHtcbiAgICAgIHRoaXMub25TY3JvbGwgPSA8YW55PnRoaXMudGhyb3R0bGVUcmFpbGluZygoKSA9PiB7XG4gICAgICAgIHRoaXMucmVmcmVzaF9pbnRlcm5hbChmYWxzZSk7XG4gICAgICB9LCB0aGlzLnNjcm9sbFRocm90dGxpbmdUaW1lKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5vblNjcm9sbCA9ICgpID0+IHtcbiAgICAgICAgdGhpcy5yZWZyZXNoX2ludGVybmFsKGZhbHNlKTtcbiAgICAgIH07XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGNoZWNrU2Nyb2xsRWxlbWVudFJlc2l6ZWRUaW1lcjogbnVtYmVyO1xuICBwcm90ZWN0ZWQgX2NoZWNrUmVzaXplSW50ZXJ2YWw6IG51bWJlcjtcbiAgQElucHV0KClcbiAgcHVibGljIGdldCBjaGVja1Jlc2l6ZUludGVydmFsKCk6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMuX2NoZWNrUmVzaXplSW50ZXJ2YWw7XG4gIH1cbiAgcHVibGljIHNldCBjaGVja1Jlc2l6ZUludGVydmFsKHZhbHVlOiBudW1iZXIpIHtcbiAgICBpZiAodGhpcy5fY2hlY2tSZXNpemVJbnRlcnZhbCA9PT0gdmFsdWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLl9jaGVja1Jlc2l6ZUludGVydmFsID0gdmFsdWU7XG4gICAgdGhpcy5hZGRTY3JvbGxFdmVudEhhbmRsZXJzKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgX2l0ZW1zOiBhbnlbXSA9IFtdO1xuICBASW5wdXQoKVxuICBwdWJsaWMgZ2V0IGl0ZW1zKCk6IGFueVtdIHtcbiAgICByZXR1cm4gdGhpcy5faXRlbXM7XG4gIH1cbiAgcHVibGljIHNldCBpdGVtcyh2YWx1ZTogYW55W10pIHtcbiAgICBpZiAodmFsdWUgPT09IHRoaXMuX2l0ZW1zKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5faXRlbXMgPSB2YWx1ZSB8fCBbXTtcbiAgICB0aGlzLnJlZnJlc2hfaW50ZXJuYWwodHJ1ZSk7XG4gIH1cblxuICBASW5wdXQoKVxuICBwdWJsaWMgY29tcGFyZUl0ZW1zOiAoaXRlbTE6IGFueSwgaXRlbTI6IGFueSkgPT4gYm9vbGVhbiA9IChcbiAgICBpdGVtMTogYW55LFxuICAgIGl0ZW0yOiBhbnksXG4gICkgPT4gaXRlbTEgPT09IGl0ZW0yO1xuXG4gIHByb3RlY3RlZCBfaG9yaXpvbnRhbDogYm9vbGVhbjtcbiAgQElucHV0KClcbiAgcHVibGljIGdldCBob3Jpem9udGFsKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLl9ob3Jpem9udGFsO1xuICB9XG4gIHB1YmxpYyBzZXQgaG9yaXpvbnRhbCh2YWx1ZTogYm9vbGVhbikge1xuICAgIHRoaXMuX2hvcml6b250YWwgPSB2YWx1ZTtcbiAgICB0aGlzLnVwZGF0ZURpcmVjdGlvbigpO1xuICB9XG5cbiAgcHJvdGVjdGVkIHJldmVydFBhcmVudE92ZXJzY3JvbGwoKTogdm9pZCB7XG4gICAgY29uc3Qgc2Nyb2xsRWxlbWVudCA9IHRoaXMuZ2V0U2Nyb2xsRWxlbWVudCgpO1xuICAgIGlmIChzY3JvbGxFbGVtZW50ICYmIHRoaXMub2xkUGFyZW50U2Nyb2xsT3ZlcmZsb3cpIHtcbiAgICAgIHNjcm9sbEVsZW1lbnQuc3R5bGVbJ292ZXJmbG93LXknXSA9IHRoaXMub2xkUGFyZW50U2Nyb2xsT3ZlcmZsb3cueTtcbiAgICAgIHNjcm9sbEVsZW1lbnQuc3R5bGVbJ292ZXJmbG93LXgnXSA9IHRoaXMub2xkUGFyZW50U2Nyb2xsT3ZlcmZsb3cueDtcbiAgICB9XG5cbiAgICB0aGlzLm9sZFBhcmVudFNjcm9sbE92ZXJmbG93ID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgcHJvdGVjdGVkIG9sZFBhcmVudFNjcm9sbE92ZXJmbG93OiB7IHg6IHN0cmluZzsgeTogc3RyaW5nIH07XG4gIHByb3RlY3RlZCBfcGFyZW50U2Nyb2xsOiBFbGVtZW50IHwgV2luZG93O1xuICBASW5wdXQoKVxuICBwdWJsaWMgZ2V0IHBhcmVudFNjcm9sbCgpOiBFbGVtZW50IHwgV2luZG93IHtcbiAgICByZXR1cm4gdGhpcy5fcGFyZW50U2Nyb2xsO1xuICB9XG4gIHB1YmxpYyBzZXQgcGFyZW50U2Nyb2xsKHZhbHVlOiBFbGVtZW50IHwgV2luZG93KSB7XG4gICAgaWYgKHRoaXMuX3BhcmVudFNjcm9sbCA9PT0gdmFsdWUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0aGlzLnJldmVydFBhcmVudE92ZXJzY3JvbGwoKTtcbiAgICB0aGlzLl9wYXJlbnRTY3JvbGwgPSB2YWx1ZTtcbiAgICB0aGlzLmFkZFNjcm9sbEV2ZW50SGFuZGxlcnMoKTtcblxuICAgIGNvbnN0IHNjcm9sbEVsZW1lbnQgPSB0aGlzLmdldFNjcm9sbEVsZW1lbnQoKTtcbiAgICBpZiAoXG4gICAgICB0aGlzLm1vZGlmeU92ZXJmbG93U3R5bGVPZlBhcmVudFNjcm9sbCAmJlxuICAgICAgc2Nyb2xsRWxlbWVudCAhPT0gdGhpcy5lbGVtZW50Lm5hdGl2ZUVsZW1lbnRcbiAgICApIHtcbiAgICAgIHRoaXMub2xkUGFyZW50U2Nyb2xsT3ZlcmZsb3cgPSB7XG4gICAgICAgIHg6IHNjcm9sbEVsZW1lbnQuc3R5bGVbJ292ZXJmbG93LXgnXSxcbiAgICAgICAgeTogc2Nyb2xsRWxlbWVudC5zdHlsZVsnb3ZlcmZsb3cteSddLFxuICAgICAgfTtcbiAgICAgIHNjcm9sbEVsZW1lbnQuc3R5bGVbJ292ZXJmbG93LXknXSA9IHRoaXMuaG9yaXpvbnRhbCA/ICd2aXNpYmxlJyA6ICdhdXRvJztcbiAgICAgIHNjcm9sbEVsZW1lbnQuc3R5bGVbJ292ZXJmbG93LXgnXSA9IHRoaXMuaG9yaXpvbnRhbCA/ICdhdXRvJyA6ICd2aXNpYmxlJztcbiAgICB9XG4gIH1cblxuICBAT3V0cHV0KClcbiAgcHVibGljIHZzVXBkYXRlOiBFdmVudEVtaXR0ZXI8YW55W10+ID0gbmV3IEV2ZW50RW1pdHRlcjxhbnlbXT4oKTtcblxuICBAT3V0cHV0KClcbiAgcHVibGljIHZzQ2hhbmdlOiBFdmVudEVtaXR0ZXI8SVBhZ2VJbmZvPiA9IG5ldyBFdmVudEVtaXR0ZXI8SVBhZ2VJbmZvPigpO1xuXG4gIEBPdXRwdXQoKVxuICBwdWJsaWMgdnNTdGFydDogRXZlbnRFbWl0dGVyPElQYWdlSW5mbz4gPSBuZXcgRXZlbnRFbWl0dGVyPElQYWdlSW5mbz4oKTtcblxuICBAT3V0cHV0KClcbiAgcHVibGljIHZzRW5kOiBFdmVudEVtaXR0ZXI8SVBhZ2VJbmZvPiA9IG5ldyBFdmVudEVtaXR0ZXI8SVBhZ2VJbmZvPigpO1xuXG4gIEBWaWV3Q2hpbGQoJ2NvbnRlbnQnLCB7IHJlYWQ6IEVsZW1lbnRSZWYsIHN0YXRpYzogZmFsc2UgfSlcbiAgcHJvdGVjdGVkIGNvbnRlbnRFbGVtZW50UmVmOiBFbGVtZW50UmVmO1xuXG4gIEBWaWV3Q2hpbGQoJ2ludmlzaWJsZVBhZGRpbmcnLCB7IHJlYWQ6IEVsZW1lbnRSZWYsIHN0YXRpYzogZmFsc2UgfSlcbiAgcHJvdGVjdGVkIGludmlzaWJsZVBhZGRpbmdFbGVtZW50UmVmOiBFbGVtZW50UmVmO1xuXG4gIEBDb250ZW50Q2hpbGQoJ2hlYWRlcicsIHsgcmVhZDogRWxlbWVudFJlZiwgc3RhdGljOiBmYWxzZSB9KVxuICBwcm90ZWN0ZWQgaGVhZGVyRWxlbWVudFJlZjogRWxlbWVudFJlZjtcblxuICBAQ29udGVudENoaWxkKCdjb250YWluZXInLCB7IHJlYWQ6IEVsZW1lbnRSZWYsIHN0YXRpYzogZmFsc2UgfSlcbiAgcHJvdGVjdGVkIGNvbnRhaW5lckVsZW1lbnRSZWY6IEVsZW1lbnRSZWY7XG5cbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuYWRkU2Nyb2xsRXZlbnRIYW5kbGVycygpO1xuICB9XG5cbiAgcHVibGljIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMucmVtb3ZlU2Nyb2xsRXZlbnRIYW5kbGVycygpO1xuICAgIHRoaXMucmV2ZXJ0UGFyZW50T3ZlcnNjcm9sbCgpO1xuICB9XG5cbiAgcHVibGljIG5nT25DaGFuZ2VzKGNoYW5nZXM6IGFueSk6IHZvaWQge1xuICAgIGxldCBpbmRleExlbmd0aENoYW5nZWQgPSB0aGlzLmNhY2hlZEl0ZW1zTGVuZ3RoICE9PSB0aGlzLml0ZW1zLmxlbmd0aDtcbiAgICB0aGlzLmNhY2hlZEl0ZW1zTGVuZ3RoID0gdGhpcy5pdGVtcy5sZW5ndGg7XG5cbiAgICBjb25zdCBmaXJzdFJ1bjogYm9vbGVhbiA9XG4gICAgICAhY2hhbmdlcy5pdGVtcyB8fFxuICAgICAgIWNoYW5nZXMuaXRlbXMucHJldmlvdXNWYWx1ZSB8fFxuICAgICAgY2hhbmdlcy5pdGVtcy5wcmV2aW91c1ZhbHVlLmxlbmd0aCA9PT0gMDtcbiAgICB0aGlzLnJlZnJlc2hfaW50ZXJuYWwoaW5kZXhMZW5ndGhDaGFuZ2VkIHx8IGZpcnN0UnVuKTtcbiAgfVxuXG4gIHB1YmxpYyBuZ0RvQ2hlY2soKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuY2FjaGVkSXRlbXNMZW5ndGggIT09IHRoaXMuaXRlbXMubGVuZ3RoKSB7XG4gICAgICB0aGlzLmNhY2hlZEl0ZW1zTGVuZ3RoID0gdGhpcy5pdGVtcy5sZW5ndGg7XG4gICAgICB0aGlzLnJlZnJlc2hfaW50ZXJuYWwodHJ1ZSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKFxuICAgICAgdGhpcy5wcmV2aW91c1ZpZXdQb3J0ICYmXG4gICAgICB0aGlzLnZpZXdQb3J0SXRlbXMgJiZcbiAgICAgIHRoaXMudmlld1BvcnRJdGVtcy5sZW5ndGggPiAwXG4gICAgKSB7XG4gICAgICBsZXQgaXRlbXNBcnJheUNoYW5nZWQgPSBmYWxzZTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy52aWV3UG9ydEl0ZW1zLmxlbmd0aDsgKytpKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAhdGhpcy5jb21wYXJlSXRlbXMoXG4gICAgICAgICAgICB0aGlzLml0ZW1zW3RoaXMucHJldmlvdXNWaWV3UG9ydC5zdGFydEluZGV4V2l0aEJ1ZmZlciArIGldLFxuICAgICAgICAgICAgdGhpcy52aWV3UG9ydEl0ZW1zW2ldLFxuICAgICAgICAgIClcbiAgICAgICAgKSB7XG4gICAgICAgICAgaXRlbXNBcnJheUNoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpZiAoaXRlbXNBcnJheUNoYW5nZWQpIHtcbiAgICAgICAgdGhpcy5yZWZyZXNoX2ludGVybmFsKHRydWUpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHB1YmxpYyByZWZyZXNoKCk6IHZvaWQge1xuICAgIHRoaXMucmVmcmVzaF9pbnRlcm5hbCh0cnVlKTtcbiAgfVxuXG4gIHB1YmxpYyBpbnZhbGlkYXRlQWxsQ2FjaGVkTWVhc3VyZW1lbnRzKCk6IHZvaWQge1xuICAgIHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucyA9IHtcbiAgICAgIG1heENoaWxkU2l6ZVBlcldyYXBHcm91cDogW10sXG4gICAgICBudW1iZXJPZktub3duV3JhcEdyb3VwQ2hpbGRTaXplczogMCxcbiAgICAgIHN1bU9mS25vd25XcmFwR3JvdXBDaGlsZFdpZHRoczogMCxcbiAgICAgIHN1bU9mS25vd25XcmFwR3JvdXBDaGlsZEhlaWdodHM6IDAsXG4gICAgfTtcblxuICAgIHRoaXMubWluTWVhc3VyZWRDaGlsZFdpZHRoID0gdW5kZWZpbmVkO1xuICAgIHRoaXMubWluTWVhc3VyZWRDaGlsZEhlaWdodCA9IHVuZGVmaW5lZDtcblxuICAgIHRoaXMucmVmcmVzaF9pbnRlcm5hbChmYWxzZSk7XG4gIH1cblxuICBwdWJsaWMgaW52YWxpZGF0ZUNhY2hlZE1lYXN1cmVtZW50Rm9ySXRlbShpdGVtOiBhbnkpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5lbmFibGVVbmVxdWFsQ2hpbGRyZW5TaXplcykge1xuICAgICAgbGV0IGluZGV4ID0gdGhpcy5pdGVtcyAmJiB0aGlzLml0ZW1zLmluZGV4T2YoaXRlbSk7XG4gICAgICBpZiAoaW5kZXggPj0gMCkge1xuICAgICAgICB0aGlzLmludmFsaWRhdGVDYWNoZWRNZWFzdXJlbWVudEF0SW5kZXgoaW5kZXgpO1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLm1pbk1lYXN1cmVkQ2hpbGRXaWR0aCA9IHVuZGVmaW5lZDtcbiAgICAgIHRoaXMubWluTWVhc3VyZWRDaGlsZEhlaWdodCA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICB0aGlzLnJlZnJlc2hfaW50ZXJuYWwoZmFsc2UpO1xuICB9XG5cbiAgcHVibGljIGludmFsaWRhdGVDYWNoZWRNZWFzdXJlbWVudEF0SW5kZXgoaW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIGlmICh0aGlzLmVuYWJsZVVuZXF1YWxDaGlsZHJlblNpemVzKSB7XG4gICAgICBsZXQgY2FjaGVkTWVhc3VyZW1lbnQgPVxuICAgICAgICB0aGlzLndyYXBHcm91cERpbWVuc2lvbnMubWF4Q2hpbGRTaXplUGVyV3JhcEdyb3VwW2luZGV4XTtcbiAgICAgIGlmIChjYWNoZWRNZWFzdXJlbWVudCkge1xuICAgICAgICB0aGlzLndyYXBHcm91cERpbWVuc2lvbnMubWF4Q2hpbGRTaXplUGVyV3JhcEdyb3VwW2luZGV4XSA9IHVuZGVmaW5lZDtcbiAgICAgICAgLS10aGlzLndyYXBHcm91cERpbWVuc2lvbnMubnVtYmVyT2ZLbm93bldyYXBHcm91cENoaWxkU2l6ZXM7XG4gICAgICAgIHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5zdW1PZktub3duV3JhcEdyb3VwQ2hpbGRXaWR0aHMgLT1cbiAgICAgICAgICBjYWNoZWRNZWFzdXJlbWVudC5jaGlsZFdpZHRoIHx8IDA7XG4gICAgICAgIHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5zdW1PZktub3duV3JhcEdyb3VwQ2hpbGRIZWlnaHRzIC09XG4gICAgICAgICAgY2FjaGVkTWVhc3VyZW1lbnQuY2hpbGRIZWlnaHQgfHwgMDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5taW5NZWFzdXJlZENoaWxkV2lkdGggPSB1bmRlZmluZWQ7XG4gICAgICB0aGlzLm1pbk1lYXN1cmVkQ2hpbGRIZWlnaHQgPSB1bmRlZmluZWQ7XG4gICAgfVxuXG4gICAgdGhpcy5yZWZyZXNoX2ludGVybmFsKGZhbHNlKTtcbiAgfVxuXG4gIHB1YmxpYyBzY3JvbGxJbnRvKFxuICAgIGl0ZW06IGFueSxcbiAgICBhbGlnblRvQmVnaW5uaW5nOiBib29sZWFuID0gdHJ1ZSxcbiAgICBhZGRpdGlvbmFsT2Zmc2V0OiBudW1iZXIgPSAwLFxuICAgIGFuaW1hdGlvbk1pbGxpc2Vjb25kczogbnVtYmVyID0gdW5kZWZpbmVkLFxuICAgIGFuaW1hdGlvbkNvbXBsZXRlZENhbGxiYWNrOiAoKSA9PiB2b2lkID0gdW5kZWZpbmVkLFxuICApOiB2b2lkIHtcbiAgICBsZXQgaW5kZXg6IG51bWJlciA9IHRoaXMuaXRlbXMuaW5kZXhPZihpdGVtKTtcbiAgICBpZiAoaW5kZXggPT09IC0xKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgdGhpcy5zY3JvbGxUb0luZGV4KFxuICAgICAgaW5kZXgsXG4gICAgICBhbGlnblRvQmVnaW5uaW5nLFxuICAgICAgYWRkaXRpb25hbE9mZnNldCxcbiAgICAgIGFuaW1hdGlvbk1pbGxpc2Vjb25kcyxcbiAgICAgIGFuaW1hdGlvbkNvbXBsZXRlZENhbGxiYWNrLFxuICAgICk7XG4gIH1cblxuICBwdWJsaWMgc2Nyb2xsVG9JbmRleChcbiAgICBpbmRleDogbnVtYmVyLFxuICAgIGFsaWduVG9CZWdpbm5pbmc6IGJvb2xlYW4gPSB0cnVlLFxuICAgIGFkZGl0aW9uYWxPZmZzZXQ6IG51bWJlciA9IDAsXG4gICAgYW5pbWF0aW9uTWlsbGlzZWNvbmRzOiBudW1iZXIgPSB1bmRlZmluZWQsXG4gICAgYW5pbWF0aW9uQ29tcGxldGVkQ2FsbGJhY2s6ICgpID0+IHZvaWQgPSB1bmRlZmluZWQsXG4gICk6IHZvaWQge1xuICAgIGxldCBtYXhSZXRyaWVzOiBudW1iZXIgPSA1O1xuXG4gICAgbGV0IHJldHJ5SWZOZWVkZWQgPSAoKSA9PiB7XG4gICAgICAtLW1heFJldHJpZXM7XG4gICAgICBpZiAobWF4UmV0cmllcyA8PSAwKSB7XG4gICAgICAgIGlmIChhbmltYXRpb25Db21wbGV0ZWRDYWxsYmFjaykge1xuICAgICAgICAgIGFuaW1hdGlvbkNvbXBsZXRlZENhbGxiYWNrKCk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBsZXQgZGltZW5zaW9ucyA9IHRoaXMuY2FsY3VsYXRlRGltZW5zaW9ucygpO1xuICAgICAgbGV0IGRlc2lyZWRTdGFydEluZGV4ID0gTWF0aC5taW4oXG4gICAgICAgIE1hdGgubWF4KGluZGV4LCAwKSxcbiAgICAgICAgZGltZW5zaW9ucy5pdGVtQ291bnQgLSAxLFxuICAgICAgKTtcbiAgICAgIGlmICh0aGlzLnByZXZpb3VzVmlld1BvcnQuc3RhcnRJbmRleCA9PT0gZGVzaXJlZFN0YXJ0SW5kZXgpIHtcbiAgICAgICAgaWYgKGFuaW1hdGlvbkNvbXBsZXRlZENhbGxiYWNrKSB7XG4gICAgICAgICAgYW5pbWF0aW9uQ29tcGxldGVkQ2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHRoaXMuc2Nyb2xsVG9JbmRleF9pbnRlcm5hbChcbiAgICAgICAgaW5kZXgsXG4gICAgICAgIGFsaWduVG9CZWdpbm5pbmcsXG4gICAgICAgIGFkZGl0aW9uYWxPZmZzZXQsXG4gICAgICAgIDAsXG4gICAgICAgIHJldHJ5SWZOZWVkZWQsXG4gICAgICApO1xuICAgIH07XG5cbiAgICB0aGlzLnNjcm9sbFRvSW5kZXhfaW50ZXJuYWwoXG4gICAgICBpbmRleCxcbiAgICAgIGFsaWduVG9CZWdpbm5pbmcsXG4gICAgICBhZGRpdGlvbmFsT2Zmc2V0LFxuICAgICAgYW5pbWF0aW9uTWlsbGlzZWNvbmRzLFxuICAgICAgcmV0cnlJZk5lZWRlZCxcbiAgICApO1xuICB9XG5cbiAgcHJvdGVjdGVkIHNjcm9sbFRvSW5kZXhfaW50ZXJuYWwoXG4gICAgaW5kZXg6IG51bWJlcixcbiAgICBhbGlnblRvQmVnaW5uaW5nOiBib29sZWFuID0gdHJ1ZSxcbiAgICBhZGRpdGlvbmFsT2Zmc2V0OiBudW1iZXIgPSAwLFxuICAgIGFuaW1hdGlvbk1pbGxpc2Vjb25kczogbnVtYmVyID0gdW5kZWZpbmVkLFxuICAgIGFuaW1hdGlvbkNvbXBsZXRlZENhbGxiYWNrOiAoKSA9PiB2b2lkID0gdW5kZWZpbmVkLFxuICApOiB2b2lkIHtcbiAgICBhbmltYXRpb25NaWxsaXNlY29uZHMgPVxuICAgICAgYW5pbWF0aW9uTWlsbGlzZWNvbmRzID09PSB1bmRlZmluZWRcbiAgICAgICAgPyB0aGlzLnNjcm9sbEFuaW1hdGlvblRpbWVcbiAgICAgICAgOiBhbmltYXRpb25NaWxsaXNlY29uZHM7XG5cbiAgICBsZXQgZGltZW5zaW9ucyA9IHRoaXMuY2FsY3VsYXRlRGltZW5zaW9ucygpO1xuICAgIGxldCBzY3JvbGwgPSB0aGlzLmNhbGN1bGF0ZVBhZGRpbmcoaW5kZXgsIGRpbWVuc2lvbnMpICsgYWRkaXRpb25hbE9mZnNldDtcbiAgICBpZiAoIWFsaWduVG9CZWdpbm5pbmcpIHtcbiAgICAgIHNjcm9sbCAtPSBkaW1lbnNpb25zLndyYXBHcm91cHNQZXJQYWdlICogZGltZW5zaW9uc1t0aGlzLl9jaGlsZFNjcm9sbERpbV07XG4gICAgfVxuXG4gICAgdGhpcy5zY3JvbGxUb1Bvc2l0aW9uKFxuICAgICAgc2Nyb2xsLFxuICAgICAgYW5pbWF0aW9uTWlsbGlzZWNvbmRzLFxuICAgICAgYW5pbWF0aW9uQ29tcGxldGVkQ2FsbGJhY2ssXG4gICAgKTtcbiAgfVxuXG4gIHB1YmxpYyBzY3JvbGxUb1Bvc2l0aW9uKFxuICAgIHNjcm9sbFBvc2l0aW9uOiBudW1iZXIsXG4gICAgYW5pbWF0aW9uTWlsbGlzZWNvbmRzOiBudW1iZXIgPSB1bmRlZmluZWQsXG4gICAgYW5pbWF0aW9uQ29tcGxldGVkQ2FsbGJhY2s6ICgpID0+IHZvaWQgPSB1bmRlZmluZWQsXG4gICk6IHZvaWQge1xuICAgIHNjcm9sbFBvc2l0aW9uICs9IHRoaXMuZ2V0RWxlbWVudHNPZmZzZXQoKTtcblxuICAgIGFuaW1hdGlvbk1pbGxpc2Vjb25kcyA9XG4gICAgICBhbmltYXRpb25NaWxsaXNlY29uZHMgPT09IHVuZGVmaW5lZFxuICAgICAgICA/IHRoaXMuc2Nyb2xsQW5pbWF0aW9uVGltZVxuICAgICAgICA6IGFuaW1hdGlvbk1pbGxpc2Vjb25kcztcblxuICAgIGxldCBzY3JvbGxFbGVtZW50ID0gdGhpcy5nZXRTY3JvbGxFbGVtZW50KCk7XG5cbiAgICBsZXQgYW5pbWF0aW9uUmVxdWVzdDogbnVtYmVyO1xuXG4gICAgaWYgKHRoaXMuY3VycmVudFR3ZWVuKSB7XG4gICAgICB0aGlzLmN1cnJlbnRUd2Vlbi5zdG9wKCk7XG4gICAgICB0aGlzLmN1cnJlbnRUd2VlbiA9IHVuZGVmaW5lZDtcbiAgICB9XG5cbiAgICBpZiAoIWFuaW1hdGlvbk1pbGxpc2Vjb25kcykge1xuICAgICAgdGhpcy5yZW5kZXJlci5zZXRQcm9wZXJ0eShcbiAgICAgICAgc2Nyb2xsRWxlbWVudCxcbiAgICAgICAgdGhpcy5fc2Nyb2xsVHlwZSxcbiAgICAgICAgc2Nyb2xsUG9zaXRpb24sXG4gICAgICApO1xuICAgICAgdGhpcy5yZWZyZXNoX2ludGVybmFsKGZhbHNlLCBhbmltYXRpb25Db21wbGV0ZWRDYWxsYmFjayk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgdHdlZW5Db25maWdPYmogPSB7IHNjcm9sbFBvc2l0aW9uOiBzY3JvbGxFbGVtZW50W3RoaXMuX3Njcm9sbFR5cGVdIH07XG5cbiAgICBsZXQgbmV3VHdlZW4gPSBuZXcgdHdlZW4uVHdlZW4odHdlZW5Db25maWdPYmopXG4gICAgICAudG8oeyBzY3JvbGxQb3NpdGlvbiB9LCBhbmltYXRpb25NaWxsaXNlY29uZHMpXG4gICAgICAuZWFzaW5nKHR3ZWVuLkVhc2luZy5RdWFkcmF0aWMuT3V0KVxuICAgICAgLm9uVXBkYXRlKChkYXRhKSA9PiB7XG4gICAgICAgIGlmIChpc05hTihkYXRhLnNjcm9sbFBvc2l0aW9uKSkge1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFByb3BlcnR5KFxuICAgICAgICAgIHNjcm9sbEVsZW1lbnQsXG4gICAgICAgICAgdGhpcy5fc2Nyb2xsVHlwZSxcbiAgICAgICAgICBkYXRhLnNjcm9sbFBvc2l0aW9uLFxuICAgICAgICApO1xuICAgICAgICB0aGlzLnJlZnJlc2hfaW50ZXJuYWwoZmFsc2UpO1xuICAgICAgfSlcbiAgICAgIC5vblN0b3AoKCkgPT4ge1xuICAgICAgICBjYW5jZWxBbmltYXRpb25GcmFtZShhbmltYXRpb25SZXF1ZXN0KTtcbiAgICAgIH0pXG4gICAgICAuc3RhcnQoKTtcblxuICAgIGNvbnN0IGFuaW1hdGUgPSAodGltZT86IG51bWJlcikgPT4ge1xuICAgICAgaWYgKCFuZXdUd2VlblsnaXNQbGF5aW5nJ10oKSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIG5ld1R3ZWVuLnVwZGF0ZSh0aW1lKTtcbiAgICAgIGlmICh0d2VlbkNvbmZpZ09iai5zY3JvbGxQb3NpdGlvbiA9PT0gc2Nyb2xsUG9zaXRpb24pIHtcbiAgICAgICAgdGhpcy5yZWZyZXNoX2ludGVybmFsKGZhbHNlLCBhbmltYXRpb25Db21wbGV0ZWRDYWxsYmFjayk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgdGhpcy56b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcbiAgICAgICAgYW5pbWF0aW9uUmVxdWVzdCA9IHJlcXVlc3RBbmltYXRpb25GcmFtZShhbmltYXRlKTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBhbmltYXRlKCk7XG4gICAgdGhpcy5jdXJyZW50VHdlZW4gPSBuZXdUd2VlbjtcbiAgfVxuXG4gIHByb3RlY3RlZCBpc0FuZ3VsYXJVbml2ZXJzYWxTU1I6IGJvb2xlYW47XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IGVsZW1lbnQ6IEVsZW1lbnRSZWYsXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHJlbmRlcmVyOiBSZW5kZXJlcjIsXG4gICAgcHJvdGVjdGVkIHJlYWRvbmx5IHpvbmU6IE5nWm9uZSxcbiAgICBwcm90ZWN0ZWQgY2hhbmdlRGV0ZWN0b3JSZWY6IENoYW5nZURldGVjdG9yUmVmLFxuICAgIEBJbmplY3QoUExBVEZPUk1fSUQpIHBsYXRmb3JtSWQ6IE9iamVjdCxcbiAgICBAT3B0aW9uYWwoKVxuICAgIEBJbmplY3QoJ3ZpcnR1YWwtc2Nyb2xsZXItZGVmYXVsdC1vcHRpb25zJylcbiAgICBvcHRpb25zOiBWaXJ0dWFsU2Nyb2xsZXJEZWZhdWx0T3B0aW9ucyxcbiAgKSB7XG4gICAgdGhpcy5pc0FuZ3VsYXJVbml2ZXJzYWxTU1IgPSBpc1BsYXRmb3JtU2VydmVyKHBsYXRmb3JtSWQpO1xuXG4gICAgdGhpcy5zY3JvbGxUaHJvdHRsaW5nVGltZSA9IG9wdGlvbnMuc2Nyb2xsVGhyb3R0bGluZ1RpbWU7XG4gICAgdGhpcy5zY3JvbGxEZWJvdW5jZVRpbWUgPSBvcHRpb25zLnNjcm9sbERlYm91bmNlVGltZTtcbiAgICB0aGlzLnNjcm9sbEFuaW1hdGlvblRpbWUgPSBvcHRpb25zLnNjcm9sbEFuaW1hdGlvblRpbWU7XG4gICAgdGhpcy5zY3JvbGxiYXJXaWR0aCA9IG9wdGlvbnMuc2Nyb2xsYmFyV2lkdGg7XG4gICAgdGhpcy5zY3JvbGxiYXJIZWlnaHQgPSBvcHRpb25zLnNjcm9sbGJhckhlaWdodDtcbiAgICB0aGlzLmNoZWNrUmVzaXplSW50ZXJ2YWwgPSBvcHRpb25zLmNoZWNrUmVzaXplSW50ZXJ2YWw7XG4gICAgdGhpcy5yZXNpemVCeXBhc3NSZWZyZXNoVGhyZXNob2xkID0gb3B0aW9ucy5yZXNpemVCeXBhc3NSZWZyZXNoVGhyZXNob2xkO1xuICAgIHRoaXMubW9kaWZ5T3ZlcmZsb3dTdHlsZU9mUGFyZW50U2Nyb2xsID1cbiAgICAgIG9wdGlvbnMubW9kaWZ5T3ZlcmZsb3dTdHlsZU9mUGFyZW50U2Nyb2xsO1xuICAgIHRoaXMuc3RyaXBlZFRhYmxlID0gb3B0aW9ucy5zdHJpcGVkVGFibGU7XG5cbiAgICB0aGlzLmhvcml6b250YWwgPSBmYWxzZTtcbiAgICB0aGlzLnJlc2V0V3JhcEdyb3VwRGltZW5zaW9ucygpO1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldEVsZW1lbnRTaXplKGVsZW1lbnQ6IEhUTUxFbGVtZW50KTogQ2xpZW50UmVjdCB7XG4gICAgbGV0IHJlc3VsdCA9IGVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgbGV0IHN0eWxlcyA9IGdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XG4gICAgbGV0IG1hcmdpblRvcCA9IHBhcnNlSW50KHN0eWxlc1snbWFyZ2luLXRvcCddLCAxMCkgfHwgMDtcbiAgICBsZXQgbWFyZ2luQm90dG9tID0gcGFyc2VJbnQoc3R5bGVzWydtYXJnaW4tYm90dG9tJ10sIDEwKSB8fCAwO1xuICAgIGxldCBtYXJnaW5MZWZ0ID0gcGFyc2VJbnQoc3R5bGVzWydtYXJnaW4tbGVmdCddLCAxMCkgfHwgMDtcbiAgICBsZXQgbWFyZ2luUmlnaHQgPSBwYXJzZUludChzdHlsZXNbJ21hcmdpbi1yaWdodCddLCAxMCkgfHwgMDtcblxuICAgIHJldHVybiB7XG4gICAgICB0b3A6IHJlc3VsdC50b3AgKyBtYXJnaW5Ub3AsXG4gICAgICBib3R0b206IHJlc3VsdC5ib3R0b20gKyBtYXJnaW5Cb3R0b20sXG4gICAgICBsZWZ0OiByZXN1bHQubGVmdCArIG1hcmdpbkxlZnQsXG4gICAgICByaWdodDogcmVzdWx0LnJpZ2h0ICsgbWFyZ2luUmlnaHQsXG4gICAgICB3aWR0aDogcmVzdWx0LndpZHRoICsgbWFyZ2luTGVmdCArIG1hcmdpblJpZ2h0LFxuICAgICAgaGVpZ2h0OiByZXN1bHQuaGVpZ2h0ICsgbWFyZ2luVG9wICsgbWFyZ2luQm90dG9tLFxuICAgICAgeTogcmVzdWx0LnRvcCArIG1hcmdpblRvcCxcbiAgICAgIHg6IHJlc3VsdC5sZWZ0ICsgbWFyZ2luTGVmdCxcbiAgICAgIHRvSlNPTigpOiBhbnkge1xuICAgICAgICByZXN1bHQudG9KU09OKCk7XG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgcHJldmlvdXNTY3JvbGxCb3VuZGluZ1JlY3Q6IENsaWVudFJlY3Q7XG4gIHByb3RlY3RlZCBjaGVja1Njcm9sbEVsZW1lbnRSZXNpemVkKCk6IHZvaWQge1xuICAgIGxldCBib3VuZGluZ1JlY3QgPSB0aGlzLmdldEVsZW1lbnRTaXplKHRoaXMuZ2V0U2Nyb2xsRWxlbWVudCgpKTtcblxuICAgIGxldCBzaXplQ2hhbmdlZDogYm9vbGVhbjtcbiAgICBpZiAoIXRoaXMucHJldmlvdXNTY3JvbGxCb3VuZGluZ1JlY3QpIHtcbiAgICAgIHNpemVDaGFuZ2VkID0gdHJ1ZTtcbiAgICB9IGVsc2Uge1xuICAgICAgbGV0IHdpZHRoQ2hhbmdlID0gTWF0aC5hYnMoXG4gICAgICAgIGJvdW5kaW5nUmVjdC53aWR0aCAtIHRoaXMucHJldmlvdXNTY3JvbGxCb3VuZGluZ1JlY3Qud2lkdGgsXG4gICAgICApO1xuICAgICAgbGV0IGhlaWdodENoYW5nZSA9IE1hdGguYWJzKFxuICAgICAgICBib3VuZGluZ1JlY3QuaGVpZ2h0IC0gdGhpcy5wcmV2aW91c1Njcm9sbEJvdW5kaW5nUmVjdC5oZWlnaHQsXG4gICAgICApO1xuICAgICAgc2l6ZUNoYW5nZWQgPVxuICAgICAgICB3aWR0aENoYW5nZSA+IHRoaXMucmVzaXplQnlwYXNzUmVmcmVzaFRocmVzaG9sZCB8fFxuICAgICAgICBoZWlnaHRDaGFuZ2UgPiB0aGlzLnJlc2l6ZUJ5cGFzc1JlZnJlc2hUaHJlc2hvbGQ7XG4gICAgfVxuXG4gICAgaWYgKHNpemVDaGFuZ2VkKSB7XG4gICAgICB0aGlzLnByZXZpb3VzU2Nyb2xsQm91bmRpbmdSZWN0ID0gYm91bmRpbmdSZWN0O1xuICAgICAgaWYgKGJvdW5kaW5nUmVjdC53aWR0aCA+IDAgJiYgYm91bmRpbmdSZWN0LmhlaWdodCA+IDApIHtcbiAgICAgICAgdGhpcy5yZWZyZXNoX2ludGVybmFsKGZhbHNlKTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcm90ZWN0ZWQgX2ludmlzaWJsZVBhZGRpbmdQcm9wZXJ0eTtcbiAgcHJvdGVjdGVkIF9vZmZzZXRUeXBlO1xuICBwcm90ZWN0ZWQgX3Njcm9sbFR5cGU7XG4gIHByb3RlY3RlZCBfcGFnZU9mZnNldFR5cGU7XG4gIHByb3RlY3RlZCBfY2hpbGRTY3JvbGxEaW07XG4gIHByb3RlY3RlZCBfdHJhbnNsYXRlRGlyO1xuICBwcm90ZWN0ZWQgX21hcmdpbkRpcjtcbiAgcHJvdGVjdGVkIHVwZGF0ZURpcmVjdGlvbigpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5ob3Jpem9udGFsKSB7XG4gICAgICB0aGlzLl9pbnZpc2libGVQYWRkaW5nUHJvcGVydHkgPSAnd2lkdGgnO1xuICAgICAgdGhpcy5fb2Zmc2V0VHlwZSA9ICdvZmZzZXRMZWZ0JztcbiAgICAgIHRoaXMuX3BhZ2VPZmZzZXRUeXBlID0gJ3BhZ2VYT2Zmc2V0JztcbiAgICAgIHRoaXMuX2NoaWxkU2Nyb2xsRGltID0gJ2NoaWxkV2lkdGgnO1xuICAgICAgdGhpcy5fbWFyZ2luRGlyID0gJ21hcmdpbi1sZWZ0JztcbiAgICAgIHRoaXMuX3RyYW5zbGF0ZURpciA9ICd0cmFuc2xhdGVYJztcbiAgICAgIHRoaXMuX3Njcm9sbFR5cGUgPSAnc2Nyb2xsTGVmdCc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuX2ludmlzaWJsZVBhZGRpbmdQcm9wZXJ0eSA9ICdoZWlnaHQnO1xuICAgICAgdGhpcy5fb2Zmc2V0VHlwZSA9ICdvZmZzZXRUb3AnO1xuICAgICAgdGhpcy5fcGFnZU9mZnNldFR5cGUgPSAncGFnZVlPZmZzZXQnO1xuICAgICAgdGhpcy5fY2hpbGRTY3JvbGxEaW0gPSAnY2hpbGRIZWlnaHQnO1xuICAgICAgdGhpcy5fbWFyZ2luRGlyID0gJ21hcmdpbi10b3AnO1xuICAgICAgdGhpcy5fdHJhbnNsYXRlRGlyID0gJ3RyYW5zbGF0ZVknO1xuICAgICAgdGhpcy5fc2Nyb2xsVHlwZSA9ICdzY3JvbGxUb3AnO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBkZWJvdW5jZShmdW5jOiBGdW5jdGlvbiwgd2FpdDogbnVtYmVyKTogRnVuY3Rpb24ge1xuICAgIGNvbnN0IHRocm90dGxlZCA9IHRoaXMudGhyb3R0bGVUcmFpbGluZyhmdW5jLCB3YWl0KTtcbiAgICBjb25zdCByZXN1bHQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICB0aHJvdHRsZWRbJ2NhbmNlbCddKCk7XG4gICAgICB0aHJvdHRsZWQuYXBwbHkodGhpcywgYXJndW1lbnRzKTtcbiAgICB9O1xuICAgIHJlc3VsdFsnY2FuY2VsJ10gPSBmdW5jdGlvbiAoKSB7XG4gICAgICB0aHJvdHRsZWRbJ2NhbmNlbCddKCk7XG4gICAgfTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwcm90ZWN0ZWQgdGhyb3R0bGVUcmFpbGluZyhmdW5jOiBGdW5jdGlvbiwgd2FpdDogbnVtYmVyKTogRnVuY3Rpb24ge1xuICAgIGxldCB0aW1lb3V0ID0gdW5kZWZpbmVkO1xuICAgIGxldCBfYXJndW1lbnRzID0gYXJndW1lbnRzO1xuICAgIGNvbnN0IHJlc3VsdCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIGNvbnN0IF90aGlzID0gdGhpcztcbiAgICAgIF9hcmd1bWVudHMgPSBhcmd1bWVudHM7XG5cbiAgICAgIGlmICh0aW1lb3V0KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKHdhaXQgPD0gMCkge1xuICAgICAgICBmdW5jLmFwcGx5KF90aGlzLCBfYXJndW1lbnRzKTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRpbWVvdXQgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICB0aW1lb3V0ID0gdW5kZWZpbmVkO1xuICAgICAgICAgIGZ1bmMuYXBwbHkoX3RoaXMsIF9hcmd1bWVudHMpO1xuICAgICAgICB9LCB3YWl0KTtcbiAgICAgIH1cbiAgICB9O1xuICAgIHJlc3VsdFsnY2FuY2VsJ10gPSBmdW5jdGlvbiAoKSB7XG4gICAgICBpZiAodGltZW91dCkge1xuICAgICAgICBjbGVhclRpbWVvdXQodGltZW91dCk7XG4gICAgICAgIHRpbWVvdXQgPSB1bmRlZmluZWQ7XG4gICAgICB9XG4gICAgfTtcblxuICAgIHJldHVybiByZXN1bHQ7XG4gIH1cblxuICBwcm90ZWN0ZWQgY2FsY3VsYXRlZFNjcm9sbGJhcldpZHRoOiBudW1iZXIgPSAwO1xuICBwcm90ZWN0ZWQgY2FsY3VsYXRlZFNjcm9sbGJhckhlaWdodDogbnVtYmVyID0gMDtcblxuICBwcm90ZWN0ZWQgcGFkZGluZzogbnVtYmVyID0gMDtcbiAgcHJvdGVjdGVkIHByZXZpb3VzVmlld1BvcnQ6IElWaWV3cG9ydCA9IDxhbnk+e307XG4gIHByb3RlY3RlZCBjdXJyZW50VHdlZW46IGFueTtcbiAgcHJvdGVjdGVkIGNhY2hlZEl0ZW1zTGVuZ3RoOiBudW1iZXI7XG5cbiAgcHJvdGVjdGVkIGRpc3Bvc2VTY3JvbGxIYW5kbGVyOiAoKSA9PiB2b2lkIHwgdW5kZWZpbmVkO1xuICBwcm90ZWN0ZWQgZGlzcG9zZVJlc2l6ZUhhbmRsZXI6ICgpID0+IHZvaWQgfCB1bmRlZmluZWQ7XG5cbiAgcHJvdGVjdGVkIHJlZnJlc2hfaW50ZXJuYWwoXG4gICAgaXRlbXNBcnJheU1vZGlmaWVkOiBib29sZWFuLFxuICAgIHJlZnJlc2hDb21wbGV0ZWRDYWxsYmFjazogKCkgPT4gdm9pZCA9IHVuZGVmaW5lZCxcbiAgICBtYXhSdW5UaW1lczogbnVtYmVyID0gMixcbiAgKTogdm9pZCB7XG4gICAgLy9ub3RlOiBtYXhSdW5UaW1lcyBpcyB0byBmb3JjZSBpdCB0byBrZWVwIHJlY2FsY3VsYXRpbmcgaWYgdGhlIHByZXZpb3VzIGl0ZXJhdGlvbiBjYXVzZWQgYSByZS1yZW5kZXIgKGRpZmZlcmVudCBzbGljZWQgaXRlbXMgaW4gdmlld3BvcnQgb3Igc2Nyb2xsUG9zaXRpb24gY2hhbmdlZCkuXG4gICAgLy9UaGUgZGVmYXVsdCBvZiAyeCBtYXggd2lsbCBwcm9iYWJseSBiZSBhY2N1cmF0ZSBlbm91Z2ggd2l0aG91dCBjYXVzaW5nIHRvbyBsYXJnZSBhIHBlcmZvcm1hbmNlIGJvdHRsZW5lY2tcbiAgICAvL1RoZSBjb2RlIHdvdWxkIHR5cGljYWxseSBxdWl0IG91dCBvbiB0aGUgMm5kIGl0ZXJhdGlvbiBhbnl3YXlzLiBUaGUgbWFpbiB0aW1lIGl0J2QgdGhpbmsgbW9yZSB0aGFuIDIgcnVucyB3b3VsZCBiZSBuZWNlc3Nhcnkgd291bGQgYmUgZm9yIHZhc3RseSBkaWZmZXJlbnQgc2l6ZWQgY2hpbGQgaXRlbXMgb3IgaWYgdGhpcyBpcyB0aGUgMXN0IHRpbWUgdGhlIGl0ZW1zIGFycmF5IHdhcyBpbml0aWFsaXplZC5cbiAgICAvL1dpdGhvdXQgbWF4UnVuVGltZXMsIElmIHRoZSB1c2VyIGlzIGFjdGl2ZWx5IHNjcm9sbGluZyB0aGlzIGNvZGUgd291bGQgYmVjb21lIGFuIGluZmluaXRlIGxvb3AgdW50aWwgdGhleSBzdG9wcGVkIHNjcm9sbGluZy4gVGhpcyB3b3VsZCBiZSBva2F5LCBleGNlcHQgZWFjaCBzY3JvbGwgZXZlbnQgd291bGQgc3RhcnQgYW4gYWRkaXRpb25hbCBpbmZpbnRlIGxvb3AuIFdlIHdhbnQgdG8gc2hvcnQtY2lyY3VpdCBpdCB0byBwcmV2ZW50IHRoaXMuXG5cbiAgICBpZiAoXG4gICAgICBpdGVtc0FycmF5TW9kaWZpZWQgJiZcbiAgICAgIHRoaXMucHJldmlvdXNWaWV3UG9ydCAmJlxuICAgICAgdGhpcy5wcmV2aW91c1ZpZXdQb3J0LnNjcm9sbFN0YXJ0UG9zaXRpb24gPiAwXG4gICAgKSB7XG4gICAgICAvL2lmIGl0ZW1zIHdlcmUgcHJlcGVuZGVkLCBzY3JvbGwgZm9yd2FyZCB0byBrZWVwIHNhbWUgaXRlbXMgdmlzaWJsZVxuICAgICAgbGV0IG9sZFZpZXdQb3J0ID0gdGhpcy5wcmV2aW91c1ZpZXdQb3J0O1xuICAgICAgbGV0IG9sZFZpZXdQb3J0SXRlbXMgPSB0aGlzLnZpZXdQb3J0SXRlbXM7XG5cbiAgICAgIGxldCBvbGRSZWZyZXNoQ29tcGxldGVkQ2FsbGJhY2sgPSByZWZyZXNoQ29tcGxldGVkQ2FsbGJhY2s7XG4gICAgICByZWZyZXNoQ29tcGxldGVkQ2FsbGJhY2sgPSAoKSA9PiB7XG4gICAgICAgIGxldCBzY3JvbGxMZW5ndGhEZWx0YSA9XG4gICAgICAgICAgdGhpcy5wcmV2aW91c1ZpZXdQb3J0LnNjcm9sbExlbmd0aCAtIG9sZFZpZXdQb3J0LnNjcm9sbExlbmd0aDtcbiAgICAgICAgaWYgKHNjcm9sbExlbmd0aERlbHRhID4gMCAmJiB0aGlzLnZpZXdQb3J0SXRlbXMpIHtcbiAgICAgICAgICBsZXQgb2xkU3RhcnRJdGVtID0gb2xkVmlld1BvcnRJdGVtc1swXTtcbiAgICAgICAgICBsZXQgb2xkU3RhcnRJdGVtSW5kZXggPSB0aGlzLml0ZW1zLmZpbmRJbmRleCgoeCkgPT5cbiAgICAgICAgICAgIHRoaXMuY29tcGFyZUl0ZW1zKG9sZFN0YXJ0SXRlbSwgeCksXG4gICAgICAgICAgKTtcbiAgICAgICAgICBpZiAob2xkU3RhcnRJdGVtSW5kZXggPiB0aGlzLnByZXZpb3VzVmlld1BvcnQuc3RhcnRJbmRleFdpdGhCdWZmZXIpIHtcbiAgICAgICAgICAgIGxldCBpdGVtT3JkZXJDaGFuZ2VkID0gZmFsc2U7XG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMTsgaSA8IHRoaXMudmlld1BvcnRJdGVtcy5sZW5ndGg7ICsraSkge1xuICAgICAgICAgICAgICBpZiAoXG4gICAgICAgICAgICAgICAgIXRoaXMuY29tcGFyZUl0ZW1zKFxuICAgICAgICAgICAgICAgICAgdGhpcy5pdGVtc1tvbGRTdGFydEl0ZW1JbmRleCArIGldLFxuICAgICAgICAgICAgICAgICAgb2xkVmlld1BvcnRJdGVtc1tpXSxcbiAgICAgICAgICAgICAgICApXG4gICAgICAgICAgICAgICkge1xuICAgICAgICAgICAgICAgIGl0ZW1PcmRlckNoYW5nZWQgPSB0cnVlO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghaXRlbU9yZGVyQ2hhbmdlZCkge1xuICAgICAgICAgICAgICB0aGlzLnNjcm9sbFRvUG9zaXRpb24oXG4gICAgICAgICAgICAgICAgdGhpcy5wcmV2aW91c1ZpZXdQb3J0LnNjcm9sbFN0YXJ0UG9zaXRpb24gKyBzY3JvbGxMZW5ndGhEZWx0YSxcbiAgICAgICAgICAgICAgICAwLFxuICAgICAgICAgICAgICAgIG9sZFJlZnJlc2hDb21wbGV0ZWRDYWxsYmFjayxcbiAgICAgICAgICAgICAgKTtcbiAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvbGRSZWZyZXNoQ29tcGxldGVkQ2FsbGJhY2spIHtcbiAgICAgICAgICBvbGRSZWZyZXNoQ29tcGxldGVkQ2FsbGJhY2soKTtcbiAgICAgICAgfVxuICAgICAgfTtcbiAgICB9XG5cbiAgICB0aGlzLnpvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT4ge1xuICAgICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcbiAgICAgICAgaWYgKGl0ZW1zQXJyYXlNb2RpZmllZCkge1xuICAgICAgICAgIHRoaXMucmVzZXRXcmFwR3JvdXBEaW1lbnNpb25zKCk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IHZpZXdwb3J0ID0gdGhpcy5jYWxjdWxhdGVWaWV3cG9ydCgpO1xuXG4gICAgICAgIGxldCBzdGFydENoYW5nZWQgPVxuICAgICAgICAgIGl0ZW1zQXJyYXlNb2RpZmllZCB8fFxuICAgICAgICAgIHZpZXdwb3J0LnN0YXJ0SW5kZXggIT09IHRoaXMucHJldmlvdXNWaWV3UG9ydC5zdGFydEluZGV4O1xuICAgICAgICBsZXQgZW5kQ2hhbmdlZCA9XG4gICAgICAgICAgaXRlbXNBcnJheU1vZGlmaWVkIHx8XG4gICAgICAgICAgdmlld3BvcnQuZW5kSW5kZXggIT09IHRoaXMucHJldmlvdXNWaWV3UG9ydC5lbmRJbmRleDtcbiAgICAgICAgbGV0IHNjcm9sbExlbmd0aENoYW5nZWQgPVxuICAgICAgICAgIHZpZXdwb3J0LnNjcm9sbExlbmd0aCAhPT0gdGhpcy5wcmV2aW91c1ZpZXdQb3J0LnNjcm9sbExlbmd0aDtcbiAgICAgICAgbGV0IHBhZGRpbmdDaGFuZ2VkID0gdmlld3BvcnQucGFkZGluZyAhPT0gdGhpcy5wcmV2aW91c1ZpZXdQb3J0LnBhZGRpbmc7XG4gICAgICAgIGxldCBzY3JvbGxQb3NpdGlvbkNoYW5nZWQgPVxuICAgICAgICAgIHZpZXdwb3J0LnNjcm9sbFN0YXJ0UG9zaXRpb24gIT09XG4gICAgICAgICAgICB0aGlzLnByZXZpb3VzVmlld1BvcnQuc2Nyb2xsU3RhcnRQb3NpdGlvbiB8fFxuICAgICAgICAgIHZpZXdwb3J0LnNjcm9sbEVuZFBvc2l0aW9uICE9PVxuICAgICAgICAgICAgdGhpcy5wcmV2aW91c1ZpZXdQb3J0LnNjcm9sbEVuZFBvc2l0aW9uIHx8XG4gICAgICAgICAgdmlld3BvcnQubWF4U2Nyb2xsUG9zaXRpb24gIT09XG4gICAgICAgICAgICB0aGlzLnByZXZpb3VzVmlld1BvcnQubWF4U2Nyb2xsUG9zaXRpb247XG5cbiAgICAgICAgdGhpcy5wcmV2aW91c1ZpZXdQb3J0ID0gdmlld3BvcnQ7XG5cbiAgICAgICAgaWYgKHNjcm9sbExlbmd0aENoYW5nZWQpIHtcbiAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKFxuICAgICAgICAgICAgdGhpcy5pbnZpc2libGVQYWRkaW5nRWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LFxuICAgICAgICAgICAgdGhpcy5faW52aXNpYmxlUGFkZGluZ1Byb3BlcnR5LFxuICAgICAgICAgICAgYCR7dmlld3BvcnQuc2Nyb2xsTGVuZ3RofXB4YCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhZGRpbmdDaGFuZ2VkKSB7XG4gICAgICAgICAgaWYgKHRoaXMudXNlTWFyZ2luSW5zdGVhZE9mVHJhbnNsYXRlKSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKFxuICAgICAgICAgICAgICB0aGlzLmNvbnRlbnRFbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgICAgICAgIHRoaXMuX21hcmdpbkRpcixcbiAgICAgICAgICAgICAgYCR7dmlld3BvcnQucGFkZGluZ31weGAsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKFxuICAgICAgICAgICAgICB0aGlzLmNvbnRlbnRFbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgICAgICAgICd0cmFuc2Zvcm0nLFxuICAgICAgICAgICAgICBgJHt0aGlzLl90cmFuc2xhdGVEaXJ9KCR7dmlld3BvcnQucGFkZGluZ31weClgLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUoXG4gICAgICAgICAgICAgIHRoaXMuY29udGVudEVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCxcbiAgICAgICAgICAgICAgJ3dlYmtpdFRyYW5zZm9ybScsXG4gICAgICAgICAgICAgIGAke3RoaXMuX3RyYW5zbGF0ZURpcn0oJHt2aWV3cG9ydC5wYWRkaW5nfXB4KWAsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmhlYWRlckVsZW1lbnRSZWYpIHtcbiAgICAgICAgICBsZXQgc2Nyb2xsUG9zaXRpb24gPSB0aGlzLmdldFNjcm9sbEVsZW1lbnQoKVt0aGlzLl9zY3JvbGxUeXBlXTtcbiAgICAgICAgICBsZXQgY29udGFpbmVyT2Zmc2V0ID0gdGhpcy5nZXRFbGVtZW50c09mZnNldCgpO1xuICAgICAgICAgIGxldCBvZmZzZXQgPSBNYXRoLm1heChcbiAgICAgICAgICAgIHNjcm9sbFBvc2l0aW9uIC1cbiAgICAgICAgICAgICAgdmlld3BvcnQucGFkZGluZyAtXG4gICAgICAgICAgICAgIGNvbnRhaW5lck9mZnNldCArXG4gICAgICAgICAgICAgIHRoaXMuaGVhZGVyRWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmNsaWVudEhlaWdodCxcbiAgICAgICAgICAgIDAsXG4gICAgICAgICAgKTtcbiAgICAgICAgICB0aGlzLnJlbmRlcmVyLnNldFN0eWxlKFxuICAgICAgICAgICAgdGhpcy5oZWFkZXJFbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnQsXG4gICAgICAgICAgICAndHJhbnNmb3JtJyxcbiAgICAgICAgICAgIGAke3RoaXMuX3RyYW5zbGF0ZURpcn0oJHtvZmZzZXR9cHgpYCxcbiAgICAgICAgICApO1xuICAgICAgICAgIHRoaXMucmVuZGVyZXIuc2V0U3R5bGUoXG4gICAgICAgICAgICB0aGlzLmhlYWRlckVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCxcbiAgICAgICAgICAgICd3ZWJraXRUcmFuc2Zvcm0nLFxuICAgICAgICAgICAgYCR7dGhpcy5fdHJhbnNsYXRlRGlyfSgke29mZnNldH1weClgLFxuICAgICAgICAgICk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjaGFuZ2VFdmVudEFyZzogSVBhZ2VJbmZvID1cbiAgICAgICAgICBzdGFydENoYW5nZWQgfHwgZW5kQ2hhbmdlZFxuICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgc3RhcnRJbmRleDogdmlld3BvcnQuc3RhcnRJbmRleCxcbiAgICAgICAgICAgICAgICBlbmRJbmRleDogdmlld3BvcnQuZW5kSW5kZXgsXG4gICAgICAgICAgICAgICAgc2Nyb2xsU3RhcnRQb3NpdGlvbjogdmlld3BvcnQuc2Nyb2xsU3RhcnRQb3NpdGlvbixcbiAgICAgICAgICAgICAgICBzY3JvbGxFbmRQb3NpdGlvbjogdmlld3BvcnQuc2Nyb2xsRW5kUG9zaXRpb24sXG4gICAgICAgICAgICAgICAgc3RhcnRJbmRleFdpdGhCdWZmZXI6IHZpZXdwb3J0LnN0YXJ0SW5kZXhXaXRoQnVmZmVyLFxuICAgICAgICAgICAgICAgIGVuZEluZGV4V2l0aEJ1ZmZlcjogdmlld3BvcnQuZW5kSW5kZXhXaXRoQnVmZmVyLFxuICAgICAgICAgICAgICAgIG1heFNjcm9sbFBvc2l0aW9uOiB2aWV3cG9ydC5tYXhTY3JvbGxQb3NpdGlvbixcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAgICAgaWYgKHN0YXJ0Q2hhbmdlZCB8fCBlbmRDaGFuZ2VkIHx8IHNjcm9sbFBvc2l0aW9uQ2hhbmdlZCkge1xuICAgICAgICAgIGNvbnN0IGhhbmRsZUNoYW5nZWQgPSAoKSA9PiB7XG4gICAgICAgICAgICAvLyB1cGRhdGUgdGhlIHNjcm9sbCBsaXN0IHRvIHRyaWdnZXIgcmUtcmVuZGVyIG9mIGNvbXBvbmVudHMgaW4gdmlld3BvcnRcbiAgICAgICAgICAgIHRoaXMudmlld1BvcnRJdGVtcyA9XG4gICAgICAgICAgICAgIHZpZXdwb3J0LnN0YXJ0SW5kZXhXaXRoQnVmZmVyID49IDAgJiZcbiAgICAgICAgICAgICAgdmlld3BvcnQuZW5kSW5kZXhXaXRoQnVmZmVyID49IDBcbiAgICAgICAgICAgICAgICA/IHRoaXMuaXRlbXMuc2xpY2UoXG4gICAgICAgICAgICAgICAgICAgIHZpZXdwb3J0LnN0YXJ0SW5kZXhXaXRoQnVmZmVyLFxuICAgICAgICAgICAgICAgICAgICB2aWV3cG9ydC5lbmRJbmRleFdpdGhCdWZmZXIgKyAxLFxuICAgICAgICAgICAgICAgICAgKVxuICAgICAgICAgICAgICAgIDogW107XG4gICAgICAgICAgICB0aGlzLnZzVXBkYXRlLmVtaXQodGhpcy52aWV3UG9ydEl0ZW1zKTtcblxuICAgICAgICAgICAgaWYgKHN0YXJ0Q2hhbmdlZCkge1xuICAgICAgICAgICAgICB0aGlzLnZzU3RhcnQuZW1pdChjaGFuZ2VFdmVudEFyZyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChlbmRDaGFuZ2VkKSB7XG4gICAgICAgICAgICAgIHRoaXMudnNFbmQuZW1pdChjaGFuZ2VFdmVudEFyZyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChzdGFydENoYW5nZWQgfHwgZW5kQ2hhbmdlZCkge1xuICAgICAgICAgICAgICB0aGlzLmNoYW5nZURldGVjdG9yUmVmLm1hcmtGb3JDaGVjaygpO1xuICAgICAgICAgICAgICB0aGlzLnZzQ2hhbmdlLmVtaXQoY2hhbmdlRXZlbnRBcmcpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAobWF4UnVuVGltZXMgPiAwKSB7XG4gICAgICAgICAgICAgIHRoaXMucmVmcmVzaF9pbnRlcm5hbChcbiAgICAgICAgICAgICAgICBmYWxzZSxcbiAgICAgICAgICAgICAgICByZWZyZXNoQ29tcGxldGVkQ2FsbGJhY2ssXG4gICAgICAgICAgICAgICAgbWF4UnVuVGltZXMgLSAxLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChyZWZyZXNoQ29tcGxldGVkQ2FsbGJhY2spIHtcbiAgICAgICAgICAgICAgcmVmcmVzaENvbXBsZXRlZENhbGxiYWNrKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfTtcblxuICAgICAgICAgIGlmICh0aGlzLmV4ZWN1dGVSZWZyZXNoT3V0c2lkZUFuZ3VsYXJab25lKSB7XG4gICAgICAgICAgICBoYW5kbGVDaGFuZ2VkKCk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuem9uZS5ydW4oaGFuZGxlQ2hhbmdlZCk7XG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIGlmIChtYXhSdW5UaW1lcyA+IDAgJiYgKHNjcm9sbExlbmd0aENoYW5nZWQgfHwgcGFkZGluZ0NoYW5nZWQpKSB7XG4gICAgICAgICAgICB0aGlzLnJlZnJlc2hfaW50ZXJuYWwoXG4gICAgICAgICAgICAgIGZhbHNlLFxuICAgICAgICAgICAgICByZWZyZXNoQ29tcGxldGVkQ2FsbGJhY2ssXG4gICAgICAgICAgICAgIG1heFJ1blRpbWVzIC0gMSxcbiAgICAgICAgICAgICk7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKHJlZnJlc2hDb21wbGV0ZWRDYWxsYmFjaykge1xuICAgICAgICAgICAgcmVmcmVzaENvbXBsZXRlZENhbGxiYWNrKCk7XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRTY3JvbGxFbGVtZW50KCk6IEhUTUxFbGVtZW50IHtcbiAgICByZXR1cm4gdGhpcy5wYXJlbnRTY3JvbGwgaW5zdGFuY2VvZiBXaW5kb3dcbiAgICAgID8gZG9jdW1lbnQuc2Nyb2xsaW5nRWxlbWVudCB8fCBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQgfHwgZG9jdW1lbnQuYm9keVxuICAgICAgOiB0aGlzLnBhcmVudFNjcm9sbCB8fCB0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudDtcbiAgfVxuXG4gIHByb3RlY3RlZCBhZGRTY3JvbGxFdmVudEhhbmRsZXJzKCk6IHZvaWQge1xuICAgIGlmICh0aGlzLmlzQW5ndWxhclVuaXZlcnNhbFNTUikge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBzY3JvbGxFbGVtZW50ID0gdGhpcy5nZXRTY3JvbGxFbGVtZW50KCk7XG5cbiAgICB0aGlzLnJlbW92ZVNjcm9sbEV2ZW50SGFuZGxlcnMoKTtcblxuICAgIHRoaXMuem9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PiB7XG4gICAgICBpZiAodGhpcy5wYXJlbnRTY3JvbGwgaW5zdGFuY2VvZiBXaW5kb3cpIHtcbiAgICAgICAgdGhpcy5kaXNwb3NlU2Nyb2xsSGFuZGxlciA9IHRoaXMucmVuZGVyZXIubGlzdGVuKFxuICAgICAgICAgICd3aW5kb3cnLFxuICAgICAgICAgICdzY3JvbGwnLFxuICAgICAgICAgIHRoaXMub25TY3JvbGwsXG4gICAgICAgICk7XG4gICAgICAgIHRoaXMuZGlzcG9zZVJlc2l6ZUhhbmRsZXIgPSB0aGlzLnJlbmRlcmVyLmxpc3RlbihcbiAgICAgICAgICAnd2luZG93JyxcbiAgICAgICAgICAncmVzaXplJyxcbiAgICAgICAgICB0aGlzLm9uU2Nyb2xsLFxuICAgICAgICApO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5kaXNwb3NlU2Nyb2xsSGFuZGxlciA9IHRoaXMucmVuZGVyZXIubGlzdGVuKFxuICAgICAgICAgIHNjcm9sbEVsZW1lbnQsXG4gICAgICAgICAgJ3Njcm9sbCcsXG4gICAgICAgICAgdGhpcy5vblNjcm9sbCxcbiAgICAgICAgKTtcbiAgICAgICAgaWYgKHRoaXMuX2NoZWNrUmVzaXplSW50ZXJ2YWwgPiAwKSB7XG4gICAgICAgICAgdGhpcy5jaGVja1Njcm9sbEVsZW1lbnRSZXNpemVkVGltZXIgPSA8YW55PnNldEludGVydmFsKCgpID0+IHtcbiAgICAgICAgICAgIHRoaXMuY2hlY2tTY3JvbGxFbGVtZW50UmVzaXplZCgpO1xuICAgICAgICAgIH0sIHRoaXMuX2NoZWNrUmVzaXplSW50ZXJ2YWwpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwcm90ZWN0ZWQgcmVtb3ZlU2Nyb2xsRXZlbnRIYW5kbGVycygpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5jaGVja1Njcm9sbEVsZW1lbnRSZXNpemVkVGltZXIpIHtcbiAgICAgIGNsZWFySW50ZXJ2YWwodGhpcy5jaGVja1Njcm9sbEVsZW1lbnRSZXNpemVkVGltZXIpO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmRpc3Bvc2VTY3JvbGxIYW5kbGVyKSB7XG4gICAgICB0aGlzLmRpc3Bvc2VTY3JvbGxIYW5kbGVyKCk7XG4gICAgICB0aGlzLmRpc3Bvc2VTY3JvbGxIYW5kbGVyID0gdW5kZWZpbmVkO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmRpc3Bvc2VSZXNpemVIYW5kbGVyKSB7XG4gICAgICB0aGlzLmRpc3Bvc2VSZXNpemVIYW5kbGVyKCk7XG4gICAgICB0aGlzLmRpc3Bvc2VSZXNpemVIYW5kbGVyID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBnZXRFbGVtZW50c09mZnNldCgpOiBudW1iZXIge1xuICAgIGlmICh0aGlzLmlzQW5ndWxhclVuaXZlcnNhbFNTUikge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgbGV0IG9mZnNldCA9IDA7XG5cbiAgICBpZiAodGhpcy5jb250YWluZXJFbGVtZW50UmVmICYmIHRoaXMuY29udGFpbmVyRWxlbWVudFJlZi5uYXRpdmVFbGVtZW50KSB7XG4gICAgICBvZmZzZXQgKz0gdGhpcy5jb250YWluZXJFbGVtZW50UmVmLm5hdGl2ZUVsZW1lbnRbdGhpcy5fb2Zmc2V0VHlwZV07XG4gICAgfVxuXG4gICAgaWYgKHRoaXMucGFyZW50U2Nyb2xsKSB7XG4gICAgICBsZXQgc2Nyb2xsRWxlbWVudCA9IHRoaXMuZ2V0U2Nyb2xsRWxlbWVudCgpO1xuICAgICAgbGV0IGVsZW1lbnRDbGllbnRSZWN0ID0gdGhpcy5nZXRFbGVtZW50U2l6ZSh0aGlzLmVsZW1lbnQubmF0aXZlRWxlbWVudCk7XG4gICAgICBsZXQgc2Nyb2xsQ2xpZW50UmVjdCA9IHRoaXMuZ2V0RWxlbWVudFNpemUoc2Nyb2xsRWxlbWVudCk7XG4gICAgICBpZiAodGhpcy5ob3Jpem9udGFsKSB7XG4gICAgICAgIG9mZnNldCArPSBlbGVtZW50Q2xpZW50UmVjdC5sZWZ0IC0gc2Nyb2xsQ2xpZW50UmVjdC5sZWZ0O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb2Zmc2V0ICs9IGVsZW1lbnRDbGllbnRSZWN0LnRvcCAtIHNjcm9sbENsaWVudFJlY3QudG9wO1xuICAgICAgfVxuXG4gICAgICBpZiAoISh0aGlzLnBhcmVudFNjcm9sbCBpbnN0YW5jZW9mIFdpbmRvdykpIHtcbiAgICAgICAgb2Zmc2V0ICs9IHNjcm9sbEVsZW1lbnRbdGhpcy5fc2Nyb2xsVHlwZV07XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG9mZnNldDtcbiAgfVxuXG4gIHByb3RlY3RlZCBjb3VudEl0ZW1zUGVyV3JhcEdyb3VwKCk6IG51bWJlciB7XG4gICAgaWYgKHRoaXMuaXNBbmd1bGFyVW5pdmVyc2FsU1NSKSB7XG4gICAgICByZXR1cm4gTWF0aC5yb3VuZChcbiAgICAgICAgdGhpcy5ob3Jpem9udGFsXG4gICAgICAgICAgPyB0aGlzLnNzclZpZXdwb3J0SGVpZ2h0IC8gdGhpcy5zc3JDaGlsZEhlaWdodFxuICAgICAgICAgIDogdGhpcy5zc3JWaWV3cG9ydFdpZHRoIC8gdGhpcy5zc3JDaGlsZFdpZHRoLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICBsZXQgcHJvcGVydHlOYW1lID0gdGhpcy5ob3Jpem9udGFsID8gJ29mZnNldExlZnQnIDogJ29mZnNldFRvcCc7XG4gICAgbGV0IGNoaWxkcmVuID0gKFxuICAgICAgKHRoaXMuY29udGFpbmVyRWxlbWVudFJlZiAmJiB0aGlzLmNvbnRhaW5lckVsZW1lbnRSZWYubmF0aXZlRWxlbWVudCkgfHxcbiAgICAgIHRoaXMuY29udGVudEVsZW1lbnRSZWYubmF0aXZlRWxlbWVudFxuICAgICkuY2hpbGRyZW47XG5cbiAgICBsZXQgY2hpbGRyZW5MZW5ndGggPSBjaGlsZHJlbiA/IGNoaWxkcmVuLmxlbmd0aCA6IDA7XG4gICAgaWYgKGNoaWxkcmVuTGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gMTtcbiAgICB9XG5cbiAgICBsZXQgZmlyc3RPZmZzZXQgPSBjaGlsZHJlblswXVtwcm9wZXJ0eU5hbWVdO1xuICAgIGxldCByZXN1bHQgPSAxO1xuICAgIHdoaWxlIChcbiAgICAgIHJlc3VsdCA8IGNoaWxkcmVuTGVuZ3RoICYmXG4gICAgICBmaXJzdE9mZnNldCA9PT0gY2hpbGRyZW5bcmVzdWx0XVtwcm9wZXJ0eU5hbWVdXG4gICAgKSB7XG4gICAgICArK3Jlc3VsdDtcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG5cbiAgcHJvdGVjdGVkIGdldFNjcm9sbFN0YXJ0UG9zaXRpb24oKTogbnVtYmVyIHtcbiAgICBsZXQgd2luZG93U2Nyb2xsVmFsdWUgPSB1bmRlZmluZWQ7XG4gICAgaWYgKHRoaXMucGFyZW50U2Nyb2xsIGluc3RhbmNlb2YgV2luZG93KSB7XG4gICAgICB3aW5kb3dTY3JvbGxWYWx1ZSA9IHdpbmRvd1t0aGlzLl9wYWdlT2Zmc2V0VHlwZV07XG4gICAgfVxuXG4gICAgcmV0dXJuIHdpbmRvd1Njcm9sbFZhbHVlIHx8IHRoaXMuZ2V0U2Nyb2xsRWxlbWVudCgpW3RoaXMuX3Njcm9sbFR5cGVdIHx8IDA7XG4gIH1cblxuICBwcm90ZWN0ZWQgbWluTWVhc3VyZWRDaGlsZFdpZHRoOiBudW1iZXI7XG4gIHByb3RlY3RlZCBtaW5NZWFzdXJlZENoaWxkSGVpZ2h0OiBudW1iZXI7XG5cbiAgcHJvdGVjdGVkIHdyYXBHcm91cERpbWVuc2lvbnM6IFdyYXBHcm91cERpbWVuc2lvbnM7XG5cbiAgcHJvdGVjdGVkIHJlc2V0V3JhcEdyb3VwRGltZW5zaW9ucygpOiB2b2lkIHtcbiAgICBjb25zdCBvbGRXcmFwR3JvdXBEaW1lbnNpb25zID0gdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zO1xuICAgIHRoaXMuaW52YWxpZGF0ZUFsbENhY2hlZE1lYXN1cmVtZW50cygpO1xuXG4gICAgaWYgKFxuICAgICAgIXRoaXMuZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXMgfHxcbiAgICAgICFvbGRXcmFwR3JvdXBEaW1lbnNpb25zIHx8XG4gICAgICBvbGRXcmFwR3JvdXBEaW1lbnNpb25zLm51bWJlck9mS25vd25XcmFwR3JvdXBDaGlsZFNpemVzID09PSAwXG4gICAgKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgaXRlbXNQZXJXcmFwR3JvdXA6IG51bWJlciA9IHRoaXMuY291bnRJdGVtc1BlcldyYXBHcm91cCgpO1xuICAgIGZvciAoXG4gICAgICBsZXQgd3JhcEdyb3VwSW5kZXggPSAwO1xuICAgICAgd3JhcEdyb3VwSW5kZXggPCBvbGRXcmFwR3JvdXBEaW1lbnNpb25zLm1heENoaWxkU2l6ZVBlcldyYXBHcm91cC5sZW5ndGg7XG4gICAgICArK3dyYXBHcm91cEluZGV4XG4gICAgKSB7XG4gICAgICBjb25zdCBvbGRXcmFwR3JvdXBEaW1lbnNpb246IFdyYXBHcm91cERpbWVuc2lvbiA9XG4gICAgICAgIG9sZFdyYXBHcm91cERpbWVuc2lvbnMubWF4Q2hpbGRTaXplUGVyV3JhcEdyb3VwW3dyYXBHcm91cEluZGV4XTtcbiAgICAgIGlmIChcbiAgICAgICAgIW9sZFdyYXBHcm91cERpbWVuc2lvbiB8fFxuICAgICAgICAhb2xkV3JhcEdyb3VwRGltZW5zaW9uLml0ZW1zIHx8XG4gICAgICAgICFvbGRXcmFwR3JvdXBEaW1lbnNpb24uaXRlbXMubGVuZ3RoXG4gICAgICApIHtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG5cbiAgICAgIGlmIChvbGRXcmFwR3JvdXBEaW1lbnNpb24uaXRlbXMubGVuZ3RoICE9PSBpdGVtc1BlcldyYXBHcm91cCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGxldCBpdGVtc0NoYW5nZWQgPSBmYWxzZTtcbiAgICAgIGxldCBhcnJheVN0YXJ0SW5kZXggPSBpdGVtc1BlcldyYXBHcm91cCAqIHdyYXBHcm91cEluZGV4O1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBpdGVtc1BlcldyYXBHcm91cDsgKytpKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICAhdGhpcy5jb21wYXJlSXRlbXMoXG4gICAgICAgICAgICBvbGRXcmFwR3JvdXBEaW1lbnNpb24uaXRlbXNbaV0sXG4gICAgICAgICAgICB0aGlzLml0ZW1zW2FycmF5U3RhcnRJbmRleCArIGldLFxuICAgICAgICAgIClcbiAgICAgICAgKSB7XG4gICAgICAgICAgaXRlbXNDaGFuZ2VkID0gdHJ1ZTtcbiAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAoIWl0ZW1zQ2hhbmdlZCkge1xuICAgICAgICArK3RoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5udW1iZXJPZktub3duV3JhcEdyb3VwQ2hpbGRTaXplcztcbiAgICAgICAgdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLnN1bU9mS25vd25XcmFwR3JvdXBDaGlsZFdpZHRocyArPVxuICAgICAgICAgIG9sZFdyYXBHcm91cERpbWVuc2lvbi5jaGlsZFdpZHRoIHx8IDA7XG4gICAgICAgIHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5zdW1PZktub3duV3JhcEdyb3VwQ2hpbGRIZWlnaHRzICs9XG4gICAgICAgICAgb2xkV3JhcEdyb3VwRGltZW5zaW9uLmNoaWxkSGVpZ2h0IHx8IDA7XG4gICAgICAgIHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5tYXhDaGlsZFNpemVQZXJXcmFwR3JvdXBbd3JhcEdyb3VwSW5kZXhdID1cbiAgICAgICAgICBvbGRXcmFwR3JvdXBEaW1lbnNpb247XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIGNhbGN1bGF0ZURpbWVuc2lvbnMoKTogSURpbWVuc2lvbnMge1xuICAgIGxldCBzY3JvbGxFbGVtZW50ID0gdGhpcy5nZXRTY3JvbGxFbGVtZW50KCk7XG5cbiAgICBjb25zdCBtYXhDYWxjdWxhdGVkU2Nyb2xsQmFyU2l6ZTogbnVtYmVyID0gMjU7IC8vIE5vdGU6IEZvcm11bGEgdG8gYXV0by1jYWxjdWxhdGUgZG9lc24ndCB3b3JrIGZvciBQYXJlbnRTY3JvbGwsIHNvIHdlIGRlZmF1bHQgdG8gdGhpcyBpZiBub3Qgc2V0IGJ5IGNvbnN1bWluZyBhcHBsaWNhdGlvblxuICAgIHRoaXMuY2FsY3VsYXRlZFNjcm9sbGJhckhlaWdodCA9IE1hdGgubWF4KFxuICAgICAgTWF0aC5taW4oXG4gICAgICAgIHNjcm9sbEVsZW1lbnQub2Zmc2V0SGVpZ2h0IC0gc2Nyb2xsRWxlbWVudC5jbGllbnRIZWlnaHQsXG4gICAgICAgIG1heENhbGN1bGF0ZWRTY3JvbGxCYXJTaXplLFxuICAgICAgKSxcbiAgICAgIHRoaXMuY2FsY3VsYXRlZFNjcm9sbGJhckhlaWdodCxcbiAgICApO1xuICAgIHRoaXMuY2FsY3VsYXRlZFNjcm9sbGJhcldpZHRoID0gTWF0aC5tYXgoXG4gICAgICBNYXRoLm1pbihcbiAgICAgICAgc2Nyb2xsRWxlbWVudC5vZmZzZXRXaWR0aCAtIHNjcm9sbEVsZW1lbnQuY2xpZW50V2lkdGgsXG4gICAgICAgIG1heENhbGN1bGF0ZWRTY3JvbGxCYXJTaXplLFxuICAgICAgKSxcbiAgICAgIHRoaXMuY2FsY3VsYXRlZFNjcm9sbGJhcldpZHRoLFxuICAgICk7XG5cbiAgICBsZXQgdmlld3BvcnRXaWR0aCA9XG4gICAgICBzY3JvbGxFbGVtZW50Lm9mZnNldFdpZHRoIC1cbiAgICAgICh0aGlzLnNjcm9sbGJhcldpZHRoIHx8XG4gICAgICAgIHRoaXMuY2FsY3VsYXRlZFNjcm9sbGJhcldpZHRoIHx8XG4gICAgICAgICh0aGlzLmhvcml6b250YWwgPyAwIDogbWF4Q2FsY3VsYXRlZFNjcm9sbEJhclNpemUpKTtcbiAgICBsZXQgdmlld3BvcnRIZWlnaHQgPVxuICAgICAgc2Nyb2xsRWxlbWVudC5vZmZzZXRIZWlnaHQgLVxuICAgICAgKHRoaXMuc2Nyb2xsYmFySGVpZ2h0IHx8XG4gICAgICAgIHRoaXMuY2FsY3VsYXRlZFNjcm9sbGJhckhlaWdodCB8fFxuICAgICAgICAodGhpcy5ob3Jpem9udGFsID8gbWF4Q2FsY3VsYXRlZFNjcm9sbEJhclNpemUgOiAwKSk7XG5cbiAgICBsZXQgY29udGVudCA9XG4gICAgICAodGhpcy5jb250YWluZXJFbGVtZW50UmVmICYmIHRoaXMuY29udGFpbmVyRWxlbWVudFJlZi5uYXRpdmVFbGVtZW50KSB8fFxuICAgICAgdGhpcy5jb250ZW50RWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xuXG4gICAgbGV0IGl0ZW1zUGVyV3JhcEdyb3VwID0gdGhpcy5jb3VudEl0ZW1zUGVyV3JhcEdyb3VwKCk7XG4gICAgbGV0IHdyYXBHcm91cHNQZXJQYWdlO1xuXG4gICAgbGV0IGRlZmF1bHRDaGlsZFdpZHRoO1xuICAgIGxldCBkZWZhdWx0Q2hpbGRIZWlnaHQ7XG5cbiAgICBpZiAodGhpcy5pc0FuZ3VsYXJVbml2ZXJzYWxTU1IpIHtcbiAgICAgIHZpZXdwb3J0V2lkdGggPSB0aGlzLnNzclZpZXdwb3J0V2lkdGg7XG4gICAgICB2aWV3cG9ydEhlaWdodCA9IHRoaXMuc3NyVmlld3BvcnRIZWlnaHQ7XG4gICAgICBkZWZhdWx0Q2hpbGRXaWR0aCA9IHRoaXMuc3NyQ2hpbGRXaWR0aDtcbiAgICAgIGRlZmF1bHRDaGlsZEhlaWdodCA9IHRoaXMuc3NyQ2hpbGRIZWlnaHQ7XG4gICAgICBsZXQgaXRlbXNQZXJSb3cgPSBNYXRoLm1heChcbiAgICAgICAgTWF0aC5jZWlsKHZpZXdwb3J0V2lkdGggLyBkZWZhdWx0Q2hpbGRXaWR0aCksXG4gICAgICAgIDEsXG4gICAgICApO1xuICAgICAgbGV0IGl0ZW1zUGVyQ29sID0gTWF0aC5tYXgoXG4gICAgICAgIE1hdGguY2VpbCh2aWV3cG9ydEhlaWdodCAvIGRlZmF1bHRDaGlsZEhlaWdodCksXG4gICAgICAgIDEsXG4gICAgICApO1xuICAgICAgd3JhcEdyb3Vwc1BlclBhZ2UgPSB0aGlzLmhvcml6b250YWwgPyBpdGVtc1BlclJvdyA6IGl0ZW1zUGVyQ29sO1xuICAgIH0gZWxzZSBpZiAoIXRoaXMuZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXMpIHtcbiAgICAgIGlmIChjb250ZW50LmNoaWxkcmVuLmxlbmd0aCA+IDApIHtcbiAgICAgICAgaWYgKCF0aGlzLmNoaWxkV2lkdGggfHwgIXRoaXMuY2hpbGRIZWlnaHQpIHtcbiAgICAgICAgICBpZiAoIXRoaXMubWluTWVhc3VyZWRDaGlsZFdpZHRoICYmIHZpZXdwb3J0V2lkdGggPiAwKSB7XG4gICAgICAgICAgICB0aGlzLm1pbk1lYXN1cmVkQ2hpbGRXaWR0aCA9IHZpZXdwb3J0V2lkdGg7XG4gICAgICAgICAgfVxuICAgICAgICAgIGlmICghdGhpcy5taW5NZWFzdXJlZENoaWxkSGVpZ2h0ICYmIHZpZXdwb3J0SGVpZ2h0ID4gMCkge1xuICAgICAgICAgICAgdGhpcy5taW5NZWFzdXJlZENoaWxkSGVpZ2h0ID0gdmlld3BvcnRIZWlnaHQ7XG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IGNoaWxkID0gY29udGVudC5jaGlsZHJlblswXTtcbiAgICAgICAgbGV0IGNsaWVudFJlY3QgPSB0aGlzLmdldEVsZW1lbnRTaXplKGNoaWxkKTtcbiAgICAgICAgdGhpcy5taW5NZWFzdXJlZENoaWxkV2lkdGggPSBNYXRoLm1pbihcbiAgICAgICAgICB0aGlzLm1pbk1lYXN1cmVkQ2hpbGRXaWR0aCxcbiAgICAgICAgICBjbGllbnRSZWN0LndpZHRoLFxuICAgICAgICApO1xuICAgICAgICB0aGlzLm1pbk1lYXN1cmVkQ2hpbGRIZWlnaHQgPSBNYXRoLm1pbihcbiAgICAgICAgICB0aGlzLm1pbk1lYXN1cmVkQ2hpbGRIZWlnaHQsXG4gICAgICAgICAgY2xpZW50UmVjdC5oZWlnaHQsXG4gICAgICAgICk7XG4gICAgICB9XG5cbiAgICAgIGRlZmF1bHRDaGlsZFdpZHRoID1cbiAgICAgICAgdGhpcy5jaGlsZFdpZHRoIHx8IHRoaXMubWluTWVhc3VyZWRDaGlsZFdpZHRoIHx8IHZpZXdwb3J0V2lkdGg7XG4gICAgICBkZWZhdWx0Q2hpbGRIZWlnaHQgPVxuICAgICAgICB0aGlzLmNoaWxkSGVpZ2h0IHx8IHRoaXMubWluTWVhc3VyZWRDaGlsZEhlaWdodCB8fCB2aWV3cG9ydEhlaWdodDtcbiAgICAgIGxldCBpdGVtc1BlclJvdyA9IE1hdGgubWF4KFxuICAgICAgICBNYXRoLmNlaWwodmlld3BvcnRXaWR0aCAvIGRlZmF1bHRDaGlsZFdpZHRoKSxcbiAgICAgICAgMSxcbiAgICAgICk7XG4gICAgICBsZXQgaXRlbXNQZXJDb2wgPSBNYXRoLm1heChcbiAgICAgICAgTWF0aC5jZWlsKHZpZXdwb3J0SGVpZ2h0IC8gZGVmYXVsdENoaWxkSGVpZ2h0KSxcbiAgICAgICAgMSxcbiAgICAgICk7XG4gICAgICB3cmFwR3JvdXBzUGVyUGFnZSA9IHRoaXMuaG9yaXpvbnRhbCA/IGl0ZW1zUGVyUm93IDogaXRlbXNQZXJDb2w7XG4gICAgfSBlbHNlIHtcbiAgICAgIGxldCBzY3JvbGxPZmZzZXQgPVxuICAgICAgICBzY3JvbGxFbGVtZW50W3RoaXMuX3Njcm9sbFR5cGVdIC1cbiAgICAgICAgKHRoaXMucHJldmlvdXNWaWV3UG9ydCA/IHRoaXMucHJldmlvdXNWaWV3UG9ydC5wYWRkaW5nIDogMCk7XG5cbiAgICAgIGxldCBhcnJheVN0YXJ0SW5kZXggPSB0aGlzLnByZXZpb3VzVmlld1BvcnQuc3RhcnRJbmRleFdpdGhCdWZmZXIgfHwgMDtcbiAgICAgIGxldCB3cmFwR3JvdXBJbmRleCA9IE1hdGguY2VpbChhcnJheVN0YXJ0SW5kZXggLyBpdGVtc1BlcldyYXBHcm91cCk7XG5cbiAgICAgIGxldCBtYXhXaWR0aEZvcldyYXBHcm91cCA9IDA7XG4gICAgICBsZXQgbWF4SGVpZ2h0Rm9yV3JhcEdyb3VwID0gMDtcbiAgICAgIGxldCBzdW1PZlZpc2libGVNYXhXaWR0aHMgPSAwO1xuICAgICAgbGV0IHN1bU9mVmlzaWJsZU1heEhlaWdodHMgPSAwO1xuICAgICAgd3JhcEdyb3Vwc1BlclBhZ2UgPSAwO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGNvbnRlbnQuY2hpbGRyZW4ubGVuZ3RoOyArK2kpIHtcbiAgICAgICAgKythcnJheVN0YXJ0SW5kZXg7XG4gICAgICAgIGxldCBjaGlsZCA9IGNvbnRlbnQuY2hpbGRyZW5baV07XG4gICAgICAgIGxldCBjbGllbnRSZWN0ID0gdGhpcy5nZXRFbGVtZW50U2l6ZShjaGlsZCk7XG5cbiAgICAgICAgbWF4V2lkdGhGb3JXcmFwR3JvdXAgPSBNYXRoLm1heChtYXhXaWR0aEZvcldyYXBHcm91cCwgY2xpZW50UmVjdC53aWR0aCk7XG4gICAgICAgIG1heEhlaWdodEZvcldyYXBHcm91cCA9IE1hdGgubWF4KFxuICAgICAgICAgIG1heEhlaWdodEZvcldyYXBHcm91cCxcbiAgICAgICAgICBjbGllbnRSZWN0LmhlaWdodCxcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAoYXJyYXlTdGFydEluZGV4ICUgaXRlbXNQZXJXcmFwR3JvdXAgPT09IDApIHtcbiAgICAgICAgICBsZXQgb2xkVmFsdWUgPVxuICAgICAgICAgICAgdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLm1heENoaWxkU2l6ZVBlcldyYXBHcm91cFt3cmFwR3JvdXBJbmRleF07XG4gICAgICAgICAgaWYgKG9sZFZhbHVlKSB7XG4gICAgICAgICAgICAtLXRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5udW1iZXJPZktub3duV3JhcEdyb3VwQ2hpbGRTaXplcztcbiAgICAgICAgICAgIHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5zdW1PZktub3duV3JhcEdyb3VwQ2hpbGRXaWR0aHMgLT1cbiAgICAgICAgICAgICAgb2xkVmFsdWUuY2hpbGRXaWR0aCB8fCAwO1xuICAgICAgICAgICAgdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLnN1bU9mS25vd25XcmFwR3JvdXBDaGlsZEhlaWdodHMgLT1cbiAgICAgICAgICAgICAgb2xkVmFsdWUuY2hpbGRIZWlnaHQgfHwgMDtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICArK3RoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5udW1iZXJPZktub3duV3JhcEdyb3VwQ2hpbGRTaXplcztcbiAgICAgICAgICBjb25zdCBpdGVtcyA9IHRoaXMuaXRlbXMuc2xpY2UoXG4gICAgICAgICAgICBhcnJheVN0YXJ0SW5kZXggLSBpdGVtc1BlcldyYXBHcm91cCxcbiAgICAgICAgICAgIGFycmF5U3RhcnRJbmRleCxcbiAgICAgICAgICApO1xuICAgICAgICAgIHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5tYXhDaGlsZFNpemVQZXJXcmFwR3JvdXBbd3JhcEdyb3VwSW5kZXhdID0ge1xuICAgICAgICAgICAgY2hpbGRXaWR0aDogbWF4V2lkdGhGb3JXcmFwR3JvdXAsXG4gICAgICAgICAgICBjaGlsZEhlaWdodDogbWF4SGVpZ2h0Rm9yV3JhcEdyb3VwLFxuICAgICAgICAgICAgaXRlbXM6IGl0ZW1zLFxuICAgICAgICAgIH07XG4gICAgICAgICAgdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLnN1bU9mS25vd25XcmFwR3JvdXBDaGlsZFdpZHRocyArPVxuICAgICAgICAgICAgbWF4V2lkdGhGb3JXcmFwR3JvdXA7XG4gICAgICAgICAgdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLnN1bU9mS25vd25XcmFwR3JvdXBDaGlsZEhlaWdodHMgKz1cbiAgICAgICAgICAgIG1heEhlaWdodEZvcldyYXBHcm91cDtcblxuICAgICAgICAgIGlmICh0aGlzLmhvcml6b250YWwpIHtcbiAgICAgICAgICAgIGxldCBtYXhWaXNpYmxlV2lkdGhGb3JXcmFwR3JvdXAgPSBNYXRoLm1pbihcbiAgICAgICAgICAgICAgbWF4V2lkdGhGb3JXcmFwR3JvdXAsXG4gICAgICAgICAgICAgIE1hdGgubWF4KHZpZXdwb3J0V2lkdGggLSBzdW1PZlZpc2libGVNYXhXaWR0aHMsIDApLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChzY3JvbGxPZmZzZXQgPiAwKSB7XG4gICAgICAgICAgICAgIGxldCBzY3JvbGxPZmZzZXRUb1JlbW92ZSA9IE1hdGgubWluKFxuICAgICAgICAgICAgICAgIHNjcm9sbE9mZnNldCxcbiAgICAgICAgICAgICAgICBtYXhWaXNpYmxlV2lkdGhGb3JXcmFwR3JvdXAsXG4gICAgICAgICAgICAgICk7XG4gICAgICAgICAgICAgIG1heFZpc2libGVXaWR0aEZvcldyYXBHcm91cCAtPSBzY3JvbGxPZmZzZXRUb1JlbW92ZTtcbiAgICAgICAgICAgICAgc2Nyb2xsT2Zmc2V0IC09IHNjcm9sbE9mZnNldFRvUmVtb3ZlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBzdW1PZlZpc2libGVNYXhXaWR0aHMgKz0gbWF4VmlzaWJsZVdpZHRoRm9yV3JhcEdyb3VwO1xuICAgICAgICAgICAgaWYgKFxuICAgICAgICAgICAgICBtYXhWaXNpYmxlV2lkdGhGb3JXcmFwR3JvdXAgPiAwICYmXG4gICAgICAgICAgICAgIHZpZXdwb3J0V2lkdGggPj0gc3VtT2ZWaXNpYmxlTWF4V2lkdGhzXG4gICAgICAgICAgICApIHtcbiAgICAgICAgICAgICAgKyt3cmFwR3JvdXBzUGVyUGFnZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGV0IG1heFZpc2libGVIZWlnaHRGb3JXcmFwR3JvdXAgPSBNYXRoLm1pbihcbiAgICAgICAgICAgICAgbWF4SGVpZ2h0Rm9yV3JhcEdyb3VwLFxuICAgICAgICAgICAgICBNYXRoLm1heCh2aWV3cG9ydEhlaWdodCAtIHN1bU9mVmlzaWJsZU1heEhlaWdodHMsIDApLFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICAgIGlmIChzY3JvbGxPZmZzZXQgPiAwKSB7XG4gICAgICAgICAgICAgIGxldCBzY3JvbGxPZmZzZXRUb1JlbW92ZSA9IE1hdGgubWluKFxuICAgICAgICAgICAgICAgIHNjcm9sbE9mZnNldCxcbiAgICAgICAgICAgICAgICBtYXhWaXNpYmxlSGVpZ2h0Rm9yV3JhcEdyb3VwLFxuICAgICAgICAgICAgICApO1xuICAgICAgICAgICAgICBtYXhWaXNpYmxlSGVpZ2h0Rm9yV3JhcEdyb3VwIC09IHNjcm9sbE9mZnNldFRvUmVtb3ZlO1xuICAgICAgICAgICAgICBzY3JvbGxPZmZzZXQgLT0gc2Nyb2xsT2Zmc2V0VG9SZW1vdmU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHN1bU9mVmlzaWJsZU1heEhlaWdodHMgKz0gbWF4VmlzaWJsZUhlaWdodEZvcldyYXBHcm91cDtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgbWF4VmlzaWJsZUhlaWdodEZvcldyYXBHcm91cCA+IDAgJiZcbiAgICAgICAgICAgICAgdmlld3BvcnRIZWlnaHQgPj0gc3VtT2ZWaXNpYmxlTWF4SGVpZ2h0c1xuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICsrd3JhcEdyb3Vwc1BlclBhZ2U7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgKyt3cmFwR3JvdXBJbmRleDtcblxuICAgICAgICAgIG1heFdpZHRoRm9yV3JhcEdyb3VwID0gMDtcbiAgICAgICAgICBtYXhIZWlnaHRGb3JXcmFwR3JvdXAgPSAwO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGxldCBhdmVyYWdlQ2hpbGRXaWR0aCA9XG4gICAgICAgIHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5zdW1PZktub3duV3JhcEdyb3VwQ2hpbGRXaWR0aHMgL1xuICAgICAgICB0aGlzLndyYXBHcm91cERpbWVuc2lvbnMubnVtYmVyT2ZLbm93bldyYXBHcm91cENoaWxkU2l6ZXM7XG4gICAgICBsZXQgYXZlcmFnZUNoaWxkSGVpZ2h0ID1cbiAgICAgICAgdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLnN1bU9mS25vd25XcmFwR3JvdXBDaGlsZEhlaWdodHMgL1xuICAgICAgICB0aGlzLndyYXBHcm91cERpbWVuc2lvbnMubnVtYmVyT2ZLbm93bldyYXBHcm91cENoaWxkU2l6ZXM7XG4gICAgICBkZWZhdWx0Q2hpbGRXaWR0aCA9IHRoaXMuY2hpbGRXaWR0aCB8fCBhdmVyYWdlQ2hpbGRXaWR0aCB8fCB2aWV3cG9ydFdpZHRoO1xuICAgICAgZGVmYXVsdENoaWxkSGVpZ2h0ID1cbiAgICAgICAgdGhpcy5jaGlsZEhlaWdodCB8fCBhdmVyYWdlQ2hpbGRIZWlnaHQgfHwgdmlld3BvcnRIZWlnaHQ7XG5cbiAgICAgIGlmICh0aGlzLmhvcml6b250YWwpIHtcbiAgICAgICAgaWYgKHZpZXdwb3J0V2lkdGggPiBzdW1PZlZpc2libGVNYXhXaWR0aHMpIHtcbiAgICAgICAgICB3cmFwR3JvdXBzUGVyUGFnZSArPSBNYXRoLmNlaWwoXG4gICAgICAgICAgICAodmlld3BvcnRXaWR0aCAtIHN1bU9mVmlzaWJsZU1heFdpZHRocykgLyBkZWZhdWx0Q2hpbGRXaWR0aCxcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAodmlld3BvcnRIZWlnaHQgPiBzdW1PZlZpc2libGVNYXhIZWlnaHRzKSB7XG4gICAgICAgICAgd3JhcEdyb3Vwc1BlclBhZ2UgKz0gTWF0aC5jZWlsKFxuICAgICAgICAgICAgKHZpZXdwb3J0SGVpZ2h0IC0gc3VtT2ZWaXNpYmxlTWF4SGVpZ2h0cykgLyBkZWZhdWx0Q2hpbGRIZWlnaHQsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBpdGVtQ291bnQgPSB0aGlzLml0ZW1zLmxlbmd0aDtcbiAgICBsZXQgaXRlbXNQZXJQYWdlID0gaXRlbXNQZXJXcmFwR3JvdXAgKiB3cmFwR3JvdXBzUGVyUGFnZTtcbiAgICBsZXQgcGFnZUNvdW50X2ZyYWN0aW9uYWwgPSBpdGVtQ291bnQgLyBpdGVtc1BlclBhZ2U7XG4gICAgbGV0IG51bWJlck9mV3JhcEdyb3VwcyA9IE1hdGguY2VpbChpdGVtQ291bnQgLyBpdGVtc1BlcldyYXBHcm91cCk7XG5cbiAgICBsZXQgc2Nyb2xsTGVuZ3RoID0gMDtcblxuICAgIGxldCBkZWZhdWx0U2Nyb2xsTGVuZ3RoUGVyV3JhcEdyb3VwID0gdGhpcy5ob3Jpem9udGFsXG4gICAgICA/IGRlZmF1bHRDaGlsZFdpZHRoXG4gICAgICA6IGRlZmF1bHRDaGlsZEhlaWdodDtcbiAgICBpZiAodGhpcy5lbmFibGVVbmVxdWFsQ2hpbGRyZW5TaXplcykge1xuICAgICAgbGV0IG51bVVua25vd25DaGlsZFNpemVzID0gMDtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZXcmFwR3JvdXBzOyArK2kpIHtcbiAgICAgICAgbGV0IGNoaWxkU2l6ZSA9XG4gICAgICAgICAgdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLm1heENoaWxkU2l6ZVBlcldyYXBHcm91cFtpXSAmJlxuICAgICAgICAgIHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5tYXhDaGlsZFNpemVQZXJXcmFwR3JvdXBbaV1bXG4gICAgICAgICAgICB0aGlzLl9jaGlsZFNjcm9sbERpbVxuICAgICAgICAgIF07XG4gICAgICAgIGlmIChjaGlsZFNpemUpIHtcbiAgICAgICAgICBzY3JvbGxMZW5ndGggKz0gY2hpbGRTaXplO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICsrbnVtVW5rbm93bkNoaWxkU2l6ZXM7XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgc2Nyb2xsTGVuZ3RoICs9IE1hdGgucm91bmQoXG4gICAgICAgIG51bVVua25vd25DaGlsZFNpemVzICogZGVmYXVsdFNjcm9sbExlbmd0aFBlcldyYXBHcm91cCxcbiAgICAgICk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHNjcm9sbExlbmd0aCA9IG51bWJlck9mV3JhcEdyb3VwcyAqIGRlZmF1bHRTY3JvbGxMZW5ndGhQZXJXcmFwR3JvdXA7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuaGVhZGVyRWxlbWVudFJlZikge1xuICAgICAgc2Nyb2xsTGVuZ3RoICs9IHRoaXMuaGVhZGVyRWxlbWVudFJlZi5uYXRpdmVFbGVtZW50LmNsaWVudEhlaWdodDtcbiAgICB9XG5cbiAgICBsZXQgdmlld3BvcnRMZW5ndGggPSB0aGlzLmhvcml6b250YWwgPyB2aWV3cG9ydFdpZHRoIDogdmlld3BvcnRIZWlnaHQ7XG4gICAgbGV0IG1heFNjcm9sbFBvc2l0aW9uID0gTWF0aC5tYXgoc2Nyb2xsTGVuZ3RoIC0gdmlld3BvcnRMZW5ndGgsIDApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIGl0ZW1Db3VudDogaXRlbUNvdW50LFxuICAgICAgaXRlbXNQZXJXcmFwR3JvdXA6IGl0ZW1zUGVyV3JhcEdyb3VwLFxuICAgICAgd3JhcEdyb3Vwc1BlclBhZ2U6IHdyYXBHcm91cHNQZXJQYWdlLFxuICAgICAgaXRlbXNQZXJQYWdlOiBpdGVtc1BlclBhZ2UsXG4gICAgICBwYWdlQ291bnRfZnJhY3Rpb25hbDogcGFnZUNvdW50X2ZyYWN0aW9uYWwsXG4gICAgICBjaGlsZFdpZHRoOiBkZWZhdWx0Q2hpbGRXaWR0aCxcbiAgICAgIGNoaWxkSGVpZ2h0OiBkZWZhdWx0Q2hpbGRIZWlnaHQsXG4gICAgICBzY3JvbGxMZW5ndGg6IHNjcm9sbExlbmd0aCxcbiAgICAgIHZpZXdwb3J0TGVuZ3RoOiB2aWV3cG9ydExlbmd0aCxcbiAgICAgIG1heFNjcm9sbFBvc2l0aW9uOiBtYXhTY3JvbGxQb3NpdGlvbixcbiAgICB9O1xuICB9XG5cbiAgcHJvdGVjdGVkIGNhY2hlZFBhZ2VTaXplOiBudW1iZXIgPSAwO1xuICBwcm90ZWN0ZWQgcHJldmlvdXNTY3JvbGxOdW1iZXJFbGVtZW50czogbnVtYmVyID0gMDtcblxuICBwcm90ZWN0ZWQgY2FsY3VsYXRlUGFkZGluZyhcbiAgICBhcnJheVN0YXJ0SW5kZXhXaXRoQnVmZmVyOiBudW1iZXIsXG4gICAgZGltZW5zaW9uczogSURpbWVuc2lvbnMsXG4gICk6IG51bWJlciB7XG4gICAgaWYgKGRpbWVuc2lvbnMuaXRlbUNvdW50ID09PSAwKSB7XG4gICAgICByZXR1cm4gMDtcbiAgICB9XG5cbiAgICBsZXQgZGVmYXVsdFNjcm9sbExlbmd0aFBlcldyYXBHcm91cCA9IGRpbWVuc2lvbnNbdGhpcy5fY2hpbGRTY3JvbGxEaW1dO1xuICAgIGxldCBzdGFydGluZ1dyYXBHcm91cEluZGV4ID1cbiAgICAgIE1hdGguZmxvb3IoYXJyYXlTdGFydEluZGV4V2l0aEJ1ZmZlciAvIGRpbWVuc2lvbnMuaXRlbXNQZXJXcmFwR3JvdXApIHx8IDA7XG5cbiAgICBpZiAoIXRoaXMuZW5hYmxlVW5lcXVhbENoaWxkcmVuU2l6ZXMpIHtcbiAgICAgIHJldHVybiBkZWZhdWx0U2Nyb2xsTGVuZ3RoUGVyV3JhcEdyb3VwICogc3RhcnRpbmdXcmFwR3JvdXBJbmRleDtcbiAgICB9XG5cbiAgICBsZXQgbnVtVW5rbm93bkNoaWxkU2l6ZXMgPSAwO1xuICAgIGxldCByZXN1bHQgPSAwO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc3RhcnRpbmdXcmFwR3JvdXBJbmRleDsgKytpKSB7XG4gICAgICBsZXQgY2hpbGRTaXplID1cbiAgICAgICAgdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLm1heENoaWxkU2l6ZVBlcldyYXBHcm91cFtpXSAmJlxuICAgICAgICB0aGlzLndyYXBHcm91cERpbWVuc2lvbnMubWF4Q2hpbGRTaXplUGVyV3JhcEdyb3VwW2ldW1xuICAgICAgICAgIHRoaXMuX2NoaWxkU2Nyb2xsRGltXG4gICAgICAgIF07XG4gICAgICBpZiAoY2hpbGRTaXplKSB7XG4gICAgICAgIHJlc3VsdCArPSBjaGlsZFNpemU7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICArK251bVVua25vd25DaGlsZFNpemVzO1xuICAgICAgfVxuICAgIH1cbiAgICByZXN1bHQgKz0gTWF0aC5yb3VuZChcbiAgICAgIG51bVVua25vd25DaGlsZFNpemVzICogZGVmYXVsdFNjcm9sbExlbmd0aFBlcldyYXBHcm91cCxcbiAgICApO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIHByb3RlY3RlZCBjYWxjdWxhdGVQYWdlSW5mbyhcbiAgICBzY3JvbGxQb3NpdGlvbjogbnVtYmVyLFxuICAgIGRpbWVuc2lvbnM6IElEaW1lbnNpb25zLFxuICApOiBJUGFnZUluZm8ge1xuICAgIGxldCBzY3JvbGxQZXJjZW50YWdlID0gMDtcbiAgICBpZiAodGhpcy5lbmFibGVVbmVxdWFsQ2hpbGRyZW5TaXplcykge1xuICAgICAgY29uc3QgbnVtYmVyT2ZXcmFwR3JvdXBzID0gTWF0aC5jZWlsKFxuICAgICAgICBkaW1lbnNpb25zLml0ZW1Db3VudCAvIGRpbWVuc2lvbnMuaXRlbXNQZXJXcmFwR3JvdXAsXG4gICAgICApO1xuICAgICAgbGV0IHRvdGFsU2Nyb2xsZWRMZW5ndGggPSAwO1xuICAgICAgbGV0IGRlZmF1bHRTY3JvbGxMZW5ndGhQZXJXcmFwR3JvdXAgPSBkaW1lbnNpb25zW3RoaXMuX2NoaWxkU2Nyb2xsRGltXTtcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZXcmFwR3JvdXBzOyArK2kpIHtcbiAgICAgICAgbGV0IGNoaWxkU2l6ZSA9XG4gICAgICAgICAgdGhpcy53cmFwR3JvdXBEaW1lbnNpb25zLm1heENoaWxkU2l6ZVBlcldyYXBHcm91cFtpXSAmJlxuICAgICAgICAgIHRoaXMud3JhcEdyb3VwRGltZW5zaW9ucy5tYXhDaGlsZFNpemVQZXJXcmFwR3JvdXBbaV1bXG4gICAgICAgICAgICB0aGlzLl9jaGlsZFNjcm9sbERpbVxuICAgICAgICAgIF07XG4gICAgICAgIGlmIChjaGlsZFNpemUpIHtcbiAgICAgICAgICB0b3RhbFNjcm9sbGVkTGVuZ3RoICs9IGNoaWxkU2l6ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICB0b3RhbFNjcm9sbGVkTGVuZ3RoICs9IGRlZmF1bHRTY3JvbGxMZW5ndGhQZXJXcmFwR3JvdXA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2Nyb2xsUG9zaXRpb24gPCB0b3RhbFNjcm9sbGVkTGVuZ3RoKSB7XG4gICAgICAgICAgc2Nyb2xsUGVyY2VudGFnZSA9IGkgLyBudW1iZXJPZldyYXBHcm91cHM7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgc2Nyb2xsUGVyY2VudGFnZSA9IHNjcm9sbFBvc2l0aW9uIC8gZGltZW5zaW9ucy5zY3JvbGxMZW5ndGg7XG4gICAgfVxuXG4gICAgbGV0IHN0YXJ0aW5nQXJyYXlJbmRleF9mcmFjdGlvbmFsID1cbiAgICAgIE1hdGgubWluKFxuICAgICAgICBNYXRoLm1heChzY3JvbGxQZXJjZW50YWdlICogZGltZW5zaW9ucy5wYWdlQ291bnRfZnJhY3Rpb25hbCwgMCksXG4gICAgICAgIGRpbWVuc2lvbnMucGFnZUNvdW50X2ZyYWN0aW9uYWwsXG4gICAgICApICogZGltZW5zaW9ucy5pdGVtc1BlclBhZ2U7XG5cbiAgICBsZXQgbWF4U3RhcnQgPSBkaW1lbnNpb25zLml0ZW1Db3VudCAtIGRpbWVuc2lvbnMuaXRlbXNQZXJQYWdlIC0gMTtcbiAgICBsZXQgYXJyYXlTdGFydEluZGV4ID0gTWF0aC5taW4oXG4gICAgICBNYXRoLmZsb29yKHN0YXJ0aW5nQXJyYXlJbmRleF9mcmFjdGlvbmFsKSxcbiAgICAgIG1heFN0YXJ0LFxuICAgICk7XG4gICAgYXJyYXlTdGFydEluZGV4IC09IGFycmF5U3RhcnRJbmRleCAlIGRpbWVuc2lvbnMuaXRlbXNQZXJXcmFwR3JvdXA7IC8vIHJvdW5kIGRvd24gdG8gc3RhcnQgb2Ygd3JhcEdyb3VwXG5cbiAgICBpZiAodGhpcy5zdHJpcGVkVGFibGUpIHtcbiAgICAgIGxldCBidWZmZXJCb3VuZGFyeSA9IDIgKiBkaW1lbnNpb25zLml0ZW1zUGVyV3JhcEdyb3VwO1xuICAgICAgaWYgKGFycmF5U3RhcnRJbmRleCAlIGJ1ZmZlckJvdW5kYXJ5ICE9PSAwKSB7XG4gICAgICAgIGFycmF5U3RhcnRJbmRleCA9IE1hdGgubWF4KFxuICAgICAgICAgIGFycmF5U3RhcnRJbmRleCAtIChhcnJheVN0YXJ0SW5kZXggJSBidWZmZXJCb3VuZGFyeSksXG4gICAgICAgICAgMCxcbiAgICAgICAgKTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICBsZXQgYXJyYXlFbmRJbmRleCA9XG4gICAgICBNYXRoLmNlaWwoc3RhcnRpbmdBcnJheUluZGV4X2ZyYWN0aW9uYWwpICsgZGltZW5zaW9ucy5pdGVtc1BlclBhZ2UgLSAxO1xuICAgIGxldCBlbmRJbmRleFdpdGhpbldyYXBHcm91cCA9XG4gICAgICAoYXJyYXlFbmRJbmRleCArIDEpICUgZGltZW5zaW9ucy5pdGVtc1BlcldyYXBHcm91cDtcbiAgICBpZiAoZW5kSW5kZXhXaXRoaW5XcmFwR3JvdXAgPiAwKSB7XG4gICAgICBhcnJheUVuZEluZGV4ICs9IGRpbWVuc2lvbnMuaXRlbXNQZXJXcmFwR3JvdXAgLSBlbmRJbmRleFdpdGhpbldyYXBHcm91cDsgLy8gcm91bmQgdXAgdG8gZW5kIG9mIHdyYXBHcm91cFxuICAgIH1cblxuICAgIGlmIChpc05hTihhcnJheVN0YXJ0SW5kZXgpKSB7XG4gICAgICBhcnJheVN0YXJ0SW5kZXggPSAwO1xuICAgIH1cbiAgICBpZiAoaXNOYU4oYXJyYXlFbmRJbmRleCkpIHtcbiAgICAgIGFycmF5RW5kSW5kZXggPSAwO1xuICAgIH1cblxuICAgIGFycmF5U3RhcnRJbmRleCA9IE1hdGgubWluKFxuICAgICAgTWF0aC5tYXgoYXJyYXlTdGFydEluZGV4LCAwKSxcbiAgICAgIGRpbWVuc2lvbnMuaXRlbUNvdW50IC0gMSxcbiAgICApO1xuICAgIGFycmF5RW5kSW5kZXggPSBNYXRoLm1pbihcbiAgICAgIE1hdGgubWF4KGFycmF5RW5kSW5kZXgsIDApLFxuICAgICAgZGltZW5zaW9ucy5pdGVtQ291bnQgLSAxLFxuICAgICk7XG5cbiAgICBsZXQgYnVmZmVyU2l6ZSA9IHRoaXMuYnVmZmVyQW1vdW50ICogZGltZW5zaW9ucy5pdGVtc1BlcldyYXBHcm91cDtcbiAgICBsZXQgc3RhcnRJbmRleFdpdGhCdWZmZXIgPSBNYXRoLm1pbihcbiAgICAgIE1hdGgubWF4KGFycmF5U3RhcnRJbmRleCAtIGJ1ZmZlclNpemUsIDApLFxuICAgICAgZGltZW5zaW9ucy5pdGVtQ291bnQgLSAxLFxuICAgICk7XG4gICAgbGV0IGVuZEluZGV4V2l0aEJ1ZmZlciA9IE1hdGgubWluKFxuICAgICAgTWF0aC5tYXgoYXJyYXlFbmRJbmRleCArIGJ1ZmZlclNpemUsIDApLFxuICAgICAgZGltZW5zaW9ucy5pdGVtQ291bnQgLSAxLFxuICAgICk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgc3RhcnRJbmRleDogYXJyYXlTdGFydEluZGV4LFxuICAgICAgZW5kSW5kZXg6IGFycmF5RW5kSW5kZXgsXG4gICAgICBzdGFydEluZGV4V2l0aEJ1ZmZlcjogc3RhcnRJbmRleFdpdGhCdWZmZXIsXG4gICAgICBlbmRJbmRleFdpdGhCdWZmZXI6IGVuZEluZGV4V2l0aEJ1ZmZlcixcbiAgICAgIHNjcm9sbFN0YXJ0UG9zaXRpb246IHNjcm9sbFBvc2l0aW9uLFxuICAgICAgc2Nyb2xsRW5kUG9zaXRpb246IHNjcm9sbFBvc2l0aW9uICsgZGltZW5zaW9ucy52aWV3cG9ydExlbmd0aCxcbiAgICAgIG1heFNjcm9sbFBvc2l0aW9uOiBkaW1lbnNpb25zLm1heFNjcm9sbFBvc2l0aW9uLFxuICAgIH07XG4gIH1cblxuICBwcm90ZWN0ZWQgY2FsY3VsYXRlVmlld3BvcnQoKTogSVZpZXdwb3J0IHtcbiAgICBsZXQgZGltZW5zaW9ucyA9IHRoaXMuY2FsY3VsYXRlRGltZW5zaW9ucygpO1xuICAgIGxldCBvZmZzZXQgPSB0aGlzLmdldEVsZW1lbnRzT2Zmc2V0KCk7XG5cbiAgICBsZXQgc2Nyb2xsU3RhcnRQb3NpdGlvbiA9IHRoaXMuZ2V0U2Nyb2xsU3RhcnRQb3NpdGlvbigpO1xuICAgIGlmIChcbiAgICAgIHNjcm9sbFN0YXJ0UG9zaXRpb24gPiBkaW1lbnNpb25zLnNjcm9sbExlbmd0aCArIG9mZnNldCAmJlxuICAgICAgISh0aGlzLnBhcmVudFNjcm9sbCBpbnN0YW5jZW9mIFdpbmRvdylcbiAgICApIHtcbiAgICAgIHNjcm9sbFN0YXJ0UG9zaXRpb24gPSBkaW1lbnNpb25zLnNjcm9sbExlbmd0aDtcbiAgICB9IGVsc2Uge1xuICAgICAgc2Nyb2xsU3RhcnRQb3NpdGlvbiAtPSBvZmZzZXQ7XG4gICAgfVxuICAgIHNjcm9sbFN0YXJ0UG9zaXRpb24gPSBNYXRoLm1heCgwLCBzY3JvbGxTdGFydFBvc2l0aW9uKTtcblxuICAgIGxldCBwYWdlSW5mbyA9IHRoaXMuY2FsY3VsYXRlUGFnZUluZm8oc2Nyb2xsU3RhcnRQb3NpdGlvbiwgZGltZW5zaW9ucyk7XG4gICAgbGV0IG5ld1BhZGRpbmcgPSB0aGlzLmNhbGN1bGF0ZVBhZGRpbmcoXG4gICAgICBwYWdlSW5mby5zdGFydEluZGV4V2l0aEJ1ZmZlcixcbiAgICAgIGRpbWVuc2lvbnMsXG4gICAgKTtcbiAgICBsZXQgbmV3U2Nyb2xsTGVuZ3RoID0gZGltZW5zaW9ucy5zY3JvbGxMZW5ndGg7XG5cbiAgICByZXR1cm4ge1xuICAgICAgc3RhcnRJbmRleDogcGFnZUluZm8uc3RhcnRJbmRleCxcbiAgICAgIGVuZEluZGV4OiBwYWdlSW5mby5lbmRJbmRleCxcbiAgICAgIHN0YXJ0SW5kZXhXaXRoQnVmZmVyOiBwYWdlSW5mby5zdGFydEluZGV4V2l0aEJ1ZmZlcixcbiAgICAgIGVuZEluZGV4V2l0aEJ1ZmZlcjogcGFnZUluZm8uZW5kSW5kZXhXaXRoQnVmZmVyLFxuICAgICAgcGFkZGluZzogTWF0aC5yb3VuZChuZXdQYWRkaW5nKSxcbiAgICAgIHNjcm9sbExlbmd0aDogTWF0aC5yb3VuZChuZXdTY3JvbGxMZW5ndGgpLFxuICAgICAgc2Nyb2xsU3RhcnRQb3NpdGlvbjogcGFnZUluZm8uc2Nyb2xsU3RhcnRQb3NpdGlvbixcbiAgICAgIHNjcm9sbEVuZFBvc2l0aW9uOiBwYWdlSW5mby5zY3JvbGxFbmRQb3NpdGlvbixcbiAgICAgIG1heFNjcm9sbFBvc2l0aW9uOiBwYWdlSW5mby5tYXhTY3JvbGxQb3NpdGlvbixcbiAgICB9O1xuICB9XG59XG5cbkBOZ01vZHVsZSh7XG4gIGV4cG9ydHM6IFtWaXJ0dWFsU2Nyb2xsZXJDb21wb25lbnRdLFxuICBkZWNsYXJhdGlvbnM6IFtWaXJ0dWFsU2Nyb2xsZXJDb21wb25lbnRdLFxuICBpbXBvcnRzOiBbQ29tbW9uTW9kdWxlXSxcbiAgcHJvdmlkZXJzOiBbXG4gICAge1xuICAgICAgcHJvdmlkZTogJ3ZpcnR1YWwtc2Nyb2xsZXItZGVmYXVsdC1vcHRpb25zJyxcbiAgICAgIHVzZUZhY3Rvcnk6IFZJUlRVQUxfU0NST0xMRVJfREVGQVVMVF9PUFRJT05TX0ZBQ1RPUlksXG4gICAgfSxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgVmlydHVhbFNjcm9sbGVyTW9kdWxlIHt9XG4iXX0=