tango-app-ui-store-builder 1.0.46 → 1.0.48

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 (94) hide show
  1. package/esm2022/lib/components/collection-update-ai/collection-update-ai.component.mjs +3 -3
  2. package/esm2022/lib/components/collection-update-ai/components/dynamic-filter/dynamic-filter.component.mjs +183 -0
  3. package/esm2022/lib/components/collection-update-ai/components/store-dropdown/store-dropdown.component.mjs +211 -0
  4. package/esm2022/lib/components/collection-update-ai/components/store-fixture/store-fixture.component.mjs +422 -0
  5. package/esm2022/lib/components/collection-update-ai/components/store-select/store-select.component.mjs +148 -0
  6. package/esm2022/lib/components/collection-update-ai/find-replace-layout/cancel-confirmation-modal/cancel-confirmation-modal.component.mjs +20 -0
  7. package/esm2022/lib/components/collection-update-ai/find-replace-layout/find-replace-layout.component.mjs +359 -0
  8. package/esm2022/lib/components/collection-update-ai/find-replace-layout/prepare-template/batch-confirmation-modal/batch-confirmation-modal.component.mjs +23 -0
  9. package/esm2022/lib/components/collection-update-ai/find-replace-layout/prepare-template/prepare-template.component.mjs +2524 -0
  10. package/esm2022/lib/components/collection-update-ai/find-replace-layout/review-replace/approve-complete-modal/approve-complete-modal.component.mjs +66 -0
  11. package/esm2022/lib/components/collection-update-ai/find-replace-layout/review-replace/fixture-before-after/fixture-before-after.component.mjs +85 -0
  12. package/esm2022/lib/components/collection-update-ai/find-replace-layout/review-replace/review-replace.component.mjs +2039 -0
  13. package/esm2022/lib/components/collection-update-ai/find-replace-table/find-replace-table.component.mjs +433 -0
  14. package/esm2022/lib/components/collection-update-ai/find-replace-table/reschedule-modal/reschedule-modal.component.mjs +76 -0
  15. package/esm2022/lib/components/collection-update-ai/models/find-replace.model.mjs +2 -0
  16. package/esm2022/lib/components/collection-update-ai/services/data.service.mjs +291 -0
  17. package/esm2022/lib/components/create-fixture/create-fixture.component.mjs +233 -138
  18. package/esm2022/lib/components/fixture-template/template-assign-stores/preview-modal/preview-modal.component.mjs +4 -2
  19. package/esm2022/lib/components/fixture-template/template-assign-stores/template-assign-stores.component.mjs +4 -2
  20. package/esm2022/lib/components/fixture-template/template-basic-details/template-basic-details.component.mjs +40 -4
  21. package/esm2022/lib/components/fixture-template/template-products/template-products.component.mjs +3 -3
  22. package/esm2022/lib/components/fixture-template/template-summary/template-summary.component.mjs +3 -3
  23. package/esm2022/lib/components/fixture-template/template-vms/template-vms.component.mjs +108 -79
  24. package/esm2022/lib/components/fixture-template-table/fixture-template-table.component.mjs +33 -4
  25. package/esm2022/lib/components/fixture-template-tree/fixture-template-tree.component.mjs +7 -3
  26. package/esm2022/lib/components/manage-plano/rollout-table/rollout-table.component.mjs +25 -3
  27. package/esm2022/lib/components/manage-store-plano/manage-store-plano.component.mjs +4 -2
  28. package/esm2022/lib/components/manage-store-plano/template-basic-details/template-basic-details.component.mjs +27 -4
  29. package/esm2022/lib/components/manage-store-plano/template-products/template-products.component.mjs +3 -3
  30. package/esm2022/lib/components/manage-store-plano/template-vms/template-vms.component.mjs +10 -14
  31. package/esm2022/lib/components/manage-store-plano/verification-feedback/editable-fixture/editable-fixture.component.mjs +3 -3
  32. package/esm2022/lib/components/manage-store-plano/verification-feedback/verification-feedback.component.mjs +3 -3
  33. package/esm2022/lib/components/planogram/merch-compliance/fixture-products/fixture-products.component.mjs +75 -31
  34. package/esm2022/lib/components/planogram/merch-compliance/merch-compliance.component.mjs +7 -8
  35. package/esm2022/lib/components/planogram/merch-compliance/product-locator/misplaced-product-fixture/misplaced-product-fixture.component.mjs +234 -0
  36. package/esm2022/lib/components/planogram/merch-compliance/product-locator/product-locator.component.mjs +1110 -0
  37. package/esm2022/lib/components/planogram/merch-compliance/product-locator/product-zone-locator/product-zone-locator.component.mjs +52 -0
  38. package/esm2022/lib/components/planogram/merch-compliance/zone-products/zone-products.component.mjs +36 -10
  39. package/esm2022/lib/components/planogram/plano-analytics/analytics-popup/analytics-popup.component.mjs +68 -0
  40. package/esm2022/lib/components/planogram/plano-analytics/date-range-picker/date-range-picker.component.mjs +92 -0
  41. package/esm2022/lib/components/planogram/plano-analytics/fixture-analytics/fixture-analytics.component.mjs +645 -0
  42. package/esm2022/lib/components/planogram/plano-analytics/plano-analytics.component.mjs +1276 -0
  43. package/esm2022/lib/components/planogram/plano-details-parent/plano-details-parent.component.mjs +33 -15
  44. package/esm2022/lib/components/planogram/plano-overview/fixture-overview/fixture-overview.component.mjs +41 -35
  45. package/esm2022/lib/components/planogram/plano-overview/plano-comparison/plano-comparison.component.mjs +8 -4
  46. package/esm2022/lib/components/planogram/plano-overview/plano-overview.component.mjs +19 -12
  47. package/esm2022/lib/components/planogram/plano-table/plano-table.component.mjs +3 -3
  48. package/esm2022/lib/components/store-plano/store-plano-tree-view/store-plano-tree-view.component.mjs +3 -2
  49. package/esm2022/lib/components/store-plano/store-plano.component.mjs +4 -2
  50. package/esm2022/lib/interfaces/fixture-library.interface.mjs +1 -1
  51. package/esm2022/lib/services/store-builder.service.mjs +49 -1
  52. package/esm2022/lib/tango-store-builder-routing.module.mjs +23 -1
  53. package/esm2022/lib/tango-store-builder.module.mjs +42 -5
  54. package/fesm2022/tango-app-ui-store-builder.mjs +12677 -2064
  55. package/fesm2022/tango-app-ui-store-builder.mjs.map +1 -1
  56. package/lib/components/collection-update-ai/components/dynamic-filter/dynamic-filter.component.d.ts +51 -0
  57. package/lib/components/collection-update-ai/components/store-dropdown/store-dropdown.component.d.ts +36 -0
  58. package/lib/components/collection-update-ai/components/store-fixture/store-fixture.component.d.ts +50 -0
  59. package/lib/components/collection-update-ai/components/store-select/store-select.component.d.ts +33 -0
  60. package/lib/components/collection-update-ai/find-replace-layout/cancel-confirmation-modal/cancel-confirmation-modal.component.d.ts +9 -0
  61. package/lib/components/collection-update-ai/find-replace-layout/find-replace-layout.component.d.ts +58 -0
  62. package/lib/components/collection-update-ai/find-replace-layout/prepare-template/batch-confirmation-modal/batch-confirmation-modal.component.d.ts +10 -0
  63. package/lib/components/collection-update-ai/find-replace-layout/prepare-template/prepare-template.component.d.ts +141 -0
  64. package/lib/components/collection-update-ai/find-replace-layout/review-replace/approve-complete-modal/approve-complete-modal.component.d.ts +18 -0
  65. package/lib/components/collection-update-ai/find-replace-layout/review-replace/fixture-before-after/fixture-before-after.component.d.ts +19 -0
  66. package/lib/components/collection-update-ai/find-replace-layout/review-replace/review-replace.component.d.ts +116 -0
  67. package/lib/components/collection-update-ai/find-replace-table/find-replace-table.component.d.ts +63 -0
  68. package/lib/components/collection-update-ai/find-replace-table/reschedule-modal/reschedule-modal.component.d.ts +19 -0
  69. package/lib/components/collection-update-ai/models/find-replace.model.d.ts +55 -0
  70. package/lib/components/collection-update-ai/services/data.service.d.ts +70 -0
  71. package/lib/components/create-fixture/create-fixture.component.d.ts +15 -14
  72. package/lib/components/fixture-template/template-basic-details/template-basic-details.component.d.ts +2 -0
  73. package/lib/components/fixture-template/template-vms/template-vms.component.d.ts +12 -12
  74. package/lib/components/fixture-template-table/fixture-template-table.component.d.ts +2 -0
  75. package/lib/components/manage-plano/rollout-table/rollout-table.component.d.ts +4 -2
  76. package/lib/components/manage-plano/verification-table/verification-table.component.d.ts +4 -4
  77. package/lib/components/manage-store-plano/template-basic-details/template-basic-details.component.d.ts +2 -0
  78. package/lib/components/manage-store-plano/template-vms/template-vms.component.d.ts +0 -1
  79. package/lib/components/planogram/merch-compliance/fixture-products/fixture-products.component.d.ts +8 -2
  80. package/lib/components/planogram/merch-compliance/merch-compliance.component.d.ts +1 -3
  81. package/lib/components/planogram/merch-compliance/product-locator/misplaced-product-fixture/misplaced-product-fixture.component.d.ts +47 -0
  82. package/lib/components/planogram/merch-compliance/product-locator/product-locator.component.d.ts +70 -0
  83. package/lib/components/planogram/merch-compliance/product-locator/product-zone-locator/product-zone-locator.component.d.ts +16 -0
  84. package/lib/components/planogram/merch-compliance/zone-products/zone-products.component.d.ts +13 -3
  85. package/lib/components/planogram/plano-analytics/analytics-popup/analytics-popup.component.d.ts +25 -0
  86. package/lib/components/planogram/plano-analytics/date-range-picker/date-range-picker.component.d.ts +24 -0
  87. package/lib/components/planogram/plano-analytics/fixture-analytics/fixture-analytics.component.d.ts +93 -0
  88. package/lib/components/planogram/plano-analytics/plano-analytics.component.d.ts +97 -0
  89. package/lib/components/planogram/plano-details-parent/plano-details-parent.component.d.ts +8 -3
  90. package/lib/components/planogram/plano-overview/fixture-overview/fixture-overview.component.d.ts +2 -4
  91. package/lib/interfaces/fixture-library.interface.d.ts +1 -1
  92. package/lib/services/store-builder.service.d.ts +25 -0
  93. package/lib/tango-store-builder.module.d.ts +31 -21
  94. package/package.json +1 -1
@@ -0,0 +1,2039 @@
1
+ import { Component, ViewChild } from '@angular/core';
2
+ import { CommonModule, TitleCasePipe } from '@angular/common';
3
+ import { FormsModule } from '@angular/forms';
4
+ import { RouterModule } from '@angular/router';
5
+ import { Subject, takeUntil } from 'rxjs';
6
+ import * as fabric from "fabric";
7
+ import { CommonSharedModule } from 'tango-app-ui-shared';
8
+ import { NgbDropdownModule } from '@ng-bootstrap/ng-bootstrap';
9
+ import { FixtureBeforeAfterComponent } from './fixture-before-after/fixture-before-after.component';
10
+ import { ApproveCompleteModalComponent } from './approve-complete-modal/approve-complete-modal.component';
11
+ import * as i0 from "@angular/core";
12
+ import * as i1 from "../../services/data.service";
13
+ import * as i2 from "../../../../services/store-builder.service";
14
+ import * as i3 from "tango-app-ui-global";
15
+ import * as i4 from "@angular/common";
16
+ import * as i5 from "@ng-bootstrap/ng-bootstrap";
17
+ import * as i6 from "@angular/router";
18
+ import * as i7 from "@angular/forms";
19
+ import * as i8 from "tango-app-ui-shared";
20
+ export class ReviewReplaceComponent {
21
+ dataService;
22
+ storeBuilderService;
23
+ cdr;
24
+ gs;
25
+ titleCase;
26
+ offcanvasService;
27
+ modalService;
28
+ router;
29
+ findReplaceData = null;
30
+ stores = [];
31
+ filteredStores = [];
32
+ selectedStores = new Set();
33
+ searchTerm = '';
34
+ selectedStore = null;
35
+ // Filter properties
36
+ selectedStatusFilters = new Set();
37
+ statusOptions = [
38
+ { value: 'match', label: 'Match' },
39
+ { value: 'no-match', label: 'No Match' }
40
+ ];
41
+ // Canvas properties
42
+ previewCanvasRef;
43
+ previewCanvasContainerRef;
44
+ previewCanvas;
45
+ planoData;
46
+ floorData;
47
+ canvasLoading = false;
48
+ approveLoading = false;
49
+ cdnUrl = '';
50
+ wallThickness = 30;
51
+ verticalMargin = (1.25 / 100) * this.toPixels(1524, "mm");
52
+ allFixtureInstances = [];
53
+ // Fixture selection and highlighting
54
+ selectedFixture = null;
55
+ selectedFixtureData = null;
56
+ originalFixtureData = null; // Original fixture before replace (for before/after comparison)
57
+ originalFixturesMap = new Map(); // Store original fixtures by fixtureId
58
+ activeHighlight = null;
59
+ cancelHighlightBlink = false;
60
+ destroy$ = new Subject();
61
+ // Pagination properties
62
+ limit = 10;
63
+ offset = 1;
64
+ totalItems = 0;
65
+ paginationSizes = [10, 20, 30];
66
+ constructor(dataService, storeBuilderService, cdr, gs, titleCase, offcanvasService, modalService, router) {
67
+ this.dataService = dataService;
68
+ this.storeBuilderService = storeBuilderService;
69
+ this.cdr = cdr;
70
+ this.gs = gs;
71
+ this.titleCase = titleCase;
72
+ this.offcanvasService = offcanvasService;
73
+ this.modalService = modalService;
74
+ this.router = router;
75
+ }
76
+ ngOnInit() {
77
+ // Get CDN URL
78
+ this.gs.environment
79
+ .pipe(takeUntil(this.destroy$))
80
+ .subscribe((env) => {
81
+ this.cdnUrl = env.planogramCDN || '';
82
+ });
83
+ // Subscribe to data service
84
+ this.dataService.getFindReplaceData()
85
+ .pipe(takeUntil(this.destroy$))
86
+ .subscribe((data) => {
87
+ this.findReplaceData = data;
88
+ if (data?.stores) {
89
+ this.stores = data.stores;
90
+ // Restore checkbox state from isApproved property
91
+ this.selectedStores.clear();
92
+ this.stores.forEach(store => {
93
+ if (store.isApproved && !this.hasNoMatch(store)) {
94
+ this.selectedStores.add(store.storeName);
95
+ }
96
+ });
97
+ this.applyFilters();
98
+ // Select first store by default if none selected
99
+ if (!this.selectedStore && this.filteredStores.length > 0) {
100
+ this.onStoreSelect(this.filteredStores[0]);
101
+ }
102
+ }
103
+ });
104
+ }
105
+ ngAfterViewInit() {
106
+ // Canvas will be initialized when store is selected
107
+ }
108
+ initializeCanvas() {
109
+ if (this.previewCanvas) {
110
+ return true;
111
+ }
112
+ if (this.previewCanvasRef?.nativeElement && this.previewCanvasContainerRef?.nativeElement) {
113
+ try {
114
+ const containerEl = this.previewCanvasContainerRef.nativeElement;
115
+ this.previewCanvas = new fabric.Canvas(this.previewCanvasRef.nativeElement, {
116
+ selectionFullyContained: true,
117
+ perPixelTargetFind: true,
118
+ targetFindTolerance: 5,
119
+ width: containerEl.clientWidth,
120
+ height: containerEl.clientHeight,
121
+ });
122
+ this.setupZoomHandlers(this.previewCanvas);
123
+ return true;
124
+ }
125
+ catch (error) {
126
+ console.error('Error initializing canvas:', error);
127
+ return false;
128
+ }
129
+ }
130
+ return false;
131
+ }
132
+ setupZoomHandlers(canvas) {
133
+ canvas.selection = false;
134
+ canvas.on("mouse:wheel", (opt) => {
135
+ const e = opt.e;
136
+ if (e.ctrlKey || e.metaKey) {
137
+ const delta = e.deltaY;
138
+ let zoom = canvas.getZoom();
139
+ zoom *= 0.995 ** delta;
140
+ zoom = Math.max(0.2, Math.min(zoom, 3));
141
+ canvas.zoomToPoint({ x: e.offsetX, y: e.offsetY }, zoom);
142
+ e.preventDefault();
143
+ e.stopPropagation();
144
+ }
145
+ });
146
+ let isDragging = false;
147
+ let lastPosX = 0;
148
+ let lastPosY = 0;
149
+ canvas.on("mouse:down", (opt) => {
150
+ // Handle fixture clicks - use findTarget to get the actual group
151
+ if (opt.target) {
152
+ const obj = opt.target;
153
+ // Check if it's a fixture group or nested within one
154
+ let fixtureGroup = obj;
155
+ // Traverse up to find the fixture group
156
+ let attempts = 0;
157
+ while (fixtureGroup && !fixtureGroup.fixtureId && !fixtureGroup.objType && attempts < 10) {
158
+ if (fixtureGroup.parent) {
159
+ fixtureGroup = fixtureGroup.parent;
160
+ }
161
+ else if (fixtureGroup.group) {
162
+ fixtureGroup = fixtureGroup.group;
163
+ }
164
+ else {
165
+ break;
166
+ }
167
+ attempts++;
168
+ }
169
+ // Check if we found a fixture group
170
+ if (fixtureGroup.objType === "fixture" || fixtureGroup.fixtureId) {
171
+ this.onFixtureClick(fixtureGroup);
172
+ canvas.setActiveObject(fixtureGroup);
173
+ canvas.requestRenderAll();
174
+ return;
175
+ }
176
+ }
177
+ // For non-fixture clicks, enable dragging
178
+ if (!opt.target) {
179
+ isDragging = true;
180
+ canvas.selection = false;
181
+ const e = opt.e;
182
+ lastPosX = e.clientX;
183
+ lastPosY = e.clientY;
184
+ }
185
+ });
186
+ canvas.on("mouse:move", (opt) => {
187
+ if (isDragging && canvas.viewportTransform && !opt.target) {
188
+ const e = opt.e;
189
+ const vpt = canvas.viewportTransform;
190
+ vpt[4] += e.clientX - lastPosX;
191
+ vpt[5] += e.clientY - lastPosY;
192
+ canvas.requestRenderAll();
193
+ lastPosX = e.clientX;
194
+ lastPosY = e.clientY;
195
+ }
196
+ });
197
+ canvas.on("mouse:up", () => {
198
+ isDragging = false;
199
+ canvas.selection = false;
200
+ });
201
+ }
202
+ onStoreSelect(store) {
203
+ // Allow viewing planogram even for stores with no-match status
204
+ this.selectedStore = store;
205
+ this.cdr.detectChanges();
206
+ setTimeout(() => {
207
+ if (this.initializeCanvas()) {
208
+ // Resize canvas to container size
209
+ if (this.previewCanvasContainerRef?.nativeElement) {
210
+ this.resizeCanvas(this.previewCanvas, this.previewCanvasContainerRef);
211
+ }
212
+ this.loadPlanogramForStore(store.storeName);
213
+ }
214
+ }, 100);
215
+ }
216
+ async loadPlanogramForStore(storeName) {
217
+ if (!storeName || !this.previewCanvas) {
218
+ return;
219
+ }
220
+ this.canvasLoading = true;
221
+ try {
222
+ const response = await this.storeBuilderService.getPlanoId({ stores: [storeName.toUpperCase()] }).toPromise();
223
+ if (response?.code === 200 && response?.data?.length > 0) {
224
+ const planoId = response.data[0]._id;
225
+ await this.getStoreFixtures(planoId);
226
+ }
227
+ else {
228
+ this.canvasLoading = false;
229
+ this.cdr.detectChanges();
230
+ }
231
+ }
232
+ catch (error) {
233
+ console.error('Error loading planogram:', error);
234
+ this.canvasLoading = false;
235
+ this.cdr.detectChanges();
236
+ }
237
+ }
238
+ async getStoreFixtures(storeId) {
239
+ if (!this.previewCanvas) {
240
+ this.canvasLoading = false;
241
+ this.cdr.detectChanges();
242
+ return;
243
+ }
244
+ this.storeBuilderService.getStoreFixtures({ id: [storeId] })
245
+ .pipe(takeUntil(this.destroy$))
246
+ .subscribe({
247
+ next: async (res) => {
248
+ if (!res?.data?.[0]?.floors?.length) {
249
+ this.canvasLoading = false;
250
+ this.cdr.detectChanges();
251
+ return;
252
+ }
253
+ this.planoData = structuredClone(res.data[0]);
254
+ this.floorData = structuredClone(res.data[0].floors[0]);
255
+ // Apply stored response data if available
256
+ this.applyStoredResponseData();
257
+ // Collect all fixtures
258
+ this.collectAllFixtures();
259
+ if (this.previewCanvas) {
260
+ // Render the planogram first
261
+ await this.renderFloor(this.previewCanvas);
262
+ this.canvasLoading = false;
263
+ this.cdr.detectChanges();
264
+ // Wait for all objects to be rendered, then resize and recenter
265
+ setTimeout(() => {
266
+ if (this.previewCanvasContainerRef?.nativeElement && this.previewCanvas) {
267
+ // Resize canvas to container dimensions
268
+ this.resizeCanvas(this.previewCanvas, this.previewCanvasContainerRef);
269
+ // Wait a bit more for canvas to update, then recenter
270
+ setTimeout(() => {
271
+ if (this.previewCanvas) {
272
+ this.fitCanvasToLayoutAnimated(this.previewCanvas);
273
+ // Highlight fixture if it has replaceResponseData
274
+ const store = this.findReplaceData?.stores?.find((s) => s.storeName === this.selectedStore?.storeName);
275
+ if (store?.findResponseData && store?.replaceResponseData) {
276
+ const fixtureGroup = this.previewCanvas.getObjects().find((obj) => obj.objType === "fixture" && obj.fixtureId === store.findResponseData);
277
+ if (fixtureGroup) {
278
+ this.highlightFixture(this.previewCanvas, fixtureGroup, false);
279
+ }
280
+ }
281
+ }
282
+ }, 100);
283
+ }
284
+ }, 300);
285
+ }
286
+ else {
287
+ this.canvasLoading = false;
288
+ this.cdr.detectChanges();
289
+ }
290
+ },
291
+ error: (err) => {
292
+ this.canvasLoading = false;
293
+ this.cdr.detectChanges();
294
+ console.error('Error fetching plano:', err);
295
+ },
296
+ });
297
+ }
298
+ applyStoredResponseData() {
299
+ if (!this.findReplaceData?.stores || !this.selectedStore || !this.floorData) {
300
+ return;
301
+ }
302
+ const store = this.findReplaceData.stores.find((s) => s.storeName === this.selectedStore?.storeName);
303
+ if (!store?.replaceResponseData) {
304
+ return;
305
+ }
306
+ const fixtureId = store.findResponseData;
307
+ if (!fixtureId)
308
+ return;
309
+ const fixture = this.getFixtureByIdFromFloor(fixtureId);
310
+ if (!fixture)
311
+ return;
312
+ // Store the original fixture (before replace) for before/after comparison
313
+ const originalFixture = structuredClone(fixture);
314
+ this.originalFixturesMap.set(fixtureId, originalFixture);
315
+ // Create a deep copy of the fixture to preserve all original properties
316
+ const updatedFixture = structuredClone(fixture);
317
+ // Merge replaceResponseData properties while preserving all other fixture properties
318
+ if (store.replaceResponseData.vmConfig) {
319
+ updatedFixture.vmConfig = Array.isArray(store.replaceResponseData.vmConfig)
320
+ ? store.replaceResponseData.vmConfig
321
+ : [];
322
+ }
323
+ // Merge shelfConfig intelligently - preserve original shelf structure and only update provided properties
324
+ if (store.replaceResponseData.shelfConfig && Array.isArray(store.replaceResponseData.shelfConfig)) {
325
+ const originalShelfConfig = Array.isArray(fixture.shelfConfig) ? fixture.shelfConfig : [];
326
+ // Create a map of original shelves by shelf identifier (shelfType + shelfNumber)
327
+ const originalShelvesMap = new Map();
328
+ originalShelfConfig.forEach((shelf) => {
329
+ const key = `${shelf.shelfType || ''}_${shelf.shelfNumber || ''}`;
330
+ originalShelvesMap.set(key, shelf);
331
+ });
332
+ // Merge: for each shelf in replaceResponseData, find the original and merge
333
+ updatedFixture.shelfConfig = store.replaceResponseData.shelfConfig.map((newShelf) => {
334
+ const key = `${newShelf.shelfType || ''}_${newShelf.shelfNumber || ''}`;
335
+ const originalShelf = originalShelvesMap.get(key);
336
+ if (originalShelf) {
337
+ // Merge: preserve all original properties, update with new ones
338
+ return {
339
+ ...originalShelf,
340
+ ...newShelf,
341
+ // Ensure critical numeric properties are preserved
342
+ productPerShelf: newShelf.productPerShelf !== undefined ? newShelf.productPerShelf : originalShelf.productPerShelf,
343
+ trayRows: newShelf.trayRows !== undefined ? newShelf.trayRows : originalShelf.trayRows,
344
+ shelfType: newShelf.shelfType || originalShelf.shelfType,
345
+ shelfNumber: newShelf.shelfNumber !== undefined ? newShelf.shelfNumber : originalShelf.shelfNumber,
346
+ };
347
+ }
348
+ else {
349
+ // New shelf not in original - use as is but ensure required properties
350
+ return {
351
+ ...newShelf,
352
+ productPerShelf: newShelf.productPerShelf || 0,
353
+ trayRows: newShelf.trayRows || 1,
354
+ };
355
+ }
356
+ });
357
+ }
358
+ else if (!Array.isArray(updatedFixture.shelfConfig)) {
359
+ updatedFixture.shelfConfig = [];
360
+ }
361
+ // Ensure arrays are always arrays
362
+ if (!Array.isArray(updatedFixture.vmConfig)) {
363
+ updatedFixture.vmConfig = [];
364
+ }
365
+ if (!Array.isArray(updatedFixture.shelfConfig)) {
366
+ updatedFixture.shelfConfig = [];
367
+ }
368
+ this.updateAiResponseFixture(updatedFixture);
369
+ }
370
+ getFixtureByIdFromFloor(fixtureId) {
371
+ if (!fixtureId || !this.floorData)
372
+ return null;
373
+ for (const element of this.floorData.layoutPolygon || []) {
374
+ if (element?.elementType === "wall" && Array.isArray(element.fixtures)) {
375
+ const hit = element.fixtures.find((fx) => fx?._id === fixtureId);
376
+ if (hit)
377
+ return hit;
378
+ }
379
+ }
380
+ for (const fx of this.floorData.centerFixture || []) {
381
+ if (fx?._id === fixtureId)
382
+ return fx;
383
+ }
384
+ return null;
385
+ }
386
+ updateAiResponseFixture(updatedFixture) {
387
+ if (!this.floorData)
388
+ return;
389
+ for (const element of this.floorData.layoutPolygon || []) {
390
+ if (element?.elementType === "wall" && Array.isArray(element.fixtures)) {
391
+ const index = element.fixtures.findIndex((fx) => fx?._id === updatedFixture._id);
392
+ if (index !== -1) {
393
+ element.fixtures[index] = updatedFixture;
394
+ return;
395
+ }
396
+ }
397
+ }
398
+ for (let i = 0; i < (this.floorData.centerFixture || []).length; i++) {
399
+ if (this.floorData.centerFixture[i]?._id === updatedFixture._id) {
400
+ this.floorData.centerFixture[i] = updatedFixture;
401
+ return;
402
+ }
403
+ }
404
+ }
405
+ collectAllFixtures() {
406
+ this.allFixtureInstances = [];
407
+ // Collect wall fixtures
408
+ if (this.floorData?.layoutPolygon) {
409
+ for (const element of this.floorData.layoutPolygon) {
410
+ if (element.fixtures && Array.isArray(element.fixtures)) {
411
+ this.allFixtureInstances.push(...element.fixtures);
412
+ }
413
+ }
414
+ }
415
+ // Collect floor fixtures
416
+ if (this.floorData?.centerFixture && Array.isArray(this.floorData.centerFixture)) {
417
+ this.allFixtureInstances.push(...this.floorData.centerFixture);
418
+ }
419
+ }
420
+ async renderFloor(canvas) {
421
+ await this.drawInitialContent(canvas);
422
+ }
423
+ async drawInitialContent(canvas) {
424
+ // Clear canvas and reset viewport
425
+ canvas.clear();
426
+ canvas.setViewportTransform([1, 0, 0, 1, 0, 0]);
427
+ await this.drawLayoutElements(canvas);
428
+ // Force render after drawing
429
+ canvas.requestRenderAll();
430
+ }
431
+ async drawLayoutElements(canvas) {
432
+ if (!this.floorData)
433
+ return;
434
+ for (let index = 0; index < this.floorData.layoutPolygon.length; index++) {
435
+ const element = this.floorData.layoutPolygon[index];
436
+ let wall;
437
+ element.relativePosition ??= { x: 0, y: 0, unit: "ft" };
438
+ const x = this.toPixels(element.relativePosition.x, element.unit);
439
+ const y = this.toPixels(element.relativePosition.y, element.unit);
440
+ if (element.elementType === "wall") {
441
+ const height = this.wallThickness;
442
+ const width = this.toPixels(element.distance, element.unit);
443
+ wall = await this.drawWall(canvas, x, y, height, width, element);
444
+ }
445
+ else if (element.elementType === "entrance") {
446
+ this.drawEntrance(canvas, x, y, 80, 75, 40, element);
447
+ }
448
+ if (element.elementType === "wall") {
449
+ const fixtureGroups = [];
450
+ for (let j = 0; j < element?.fixtures?.length; j++) {
451
+ const fixture = element.fixtures[j];
452
+ const fx = this.toPixels(fixture.relativePosition.x, fixture.relativePosition.unit);
453
+ const fy = this.toPixels(fixture.relativePosition.y, fixture.relativePosition.unit);
454
+ const fh = this.toPixels(fixture.fixtureStaticLength.value, fixture.fixtureStaticLength.unit);
455
+ const fw = this.toPixels(fixture.fixtureStaticWidth.value, fixture.fixtureStaticWidth.unit);
456
+ const fixtureObj = await this.drawFixture(canvas, fx, fy, fh, fw, fixture);
457
+ fixtureGroups.push(fixtureObj);
458
+ }
459
+ if (element.isLocked && wall) {
460
+ canvas.remove(wall);
461
+ fixtureGroups.forEach((f) => canvas.remove(f));
462
+ const combinedGroup = new fabric.Group([wall, ...fixtureGroups], {
463
+ hasControls: false,
464
+ selectable: false,
465
+ lockMovementX: true,
466
+ lockMovementY: true,
467
+ lockRotation: true,
468
+ lockScalingX: true,
469
+ lockScalingY: true,
470
+ subTargetCheck: true,
471
+ });
472
+ combinedGroup.set({ isLocked: true });
473
+ canvas.add(combinedGroup);
474
+ }
475
+ for (let j = 0; j < element?.otherElements?.length; j++) {
476
+ const otherElement = element.otherElements[j];
477
+ const ox = this.toPixels(otherElement.relativePosition.x, "ft");
478
+ const oy = this.toPixels(otherElement.relativePosition.y, "ft");
479
+ const oa = otherElement.relativePosition.angle;
480
+ const oh = this.toPixels(otherElement.fixtureStaticLength.value, otherElement.fixtureStaticLength.unit);
481
+ const ow = this.toPixels(otherElement.fixtureStaticWidth.value, otherElement.fixtureStaticWidth.unit);
482
+ this.drawOtherElementsWithLabel(canvas, ox, oy, oa, ow, oh, otherElement);
483
+ }
484
+ }
485
+ }
486
+ for (let i = 0; i < this.floorData?.centerFixture?.length; i++) {
487
+ const fixture = this.floorData.centerFixture[i];
488
+ const x = this.toPixels(fixture.relativePosition.x, fixture.relativePosition.unit);
489
+ const y = this.toPixels(fixture.relativePosition.y, fixture.relativePosition.unit);
490
+ const h = this.toPixels(fixture.fixtureStaticLength.value, fixture.fixtureStaticLength.unit);
491
+ const w = this.toPixels(fixture.fixtureStaticWidth.value, fixture.fixtureStaticWidth.unit);
492
+ await this.drawFixture(canvas, x, y, h, w, fixture);
493
+ }
494
+ for (let j = 0; j < this.floorData?.otherElements?.length; j++) {
495
+ const otherElement = this.floorData.otherElements[j];
496
+ const x = this.toPixels(otherElement.relativePosition.x, "ft");
497
+ const y = this.toPixels(otherElement.relativePosition.y, "ft");
498
+ const a = otherElement.relativePosition.angle;
499
+ const h = this.toPixels(otherElement.fixtureStaticLength.value, otherElement.fixtureStaticLength.unit);
500
+ const w = this.toPixels(otherElement.fixtureStaticWidth.value, otherElement.fixtureStaticWidth.unit);
501
+ this.drawOtherElementsWithLabel(canvas, x, y, a, w, h, otherElement);
502
+ }
503
+ return true;
504
+ }
505
+ async drawWall(canvas, x, y, height, width, elementData) {
506
+ const radius = 5;
507
+ const fillColor = "#F6FCFF";
508
+ const strokeColor = "#D0D5DD";
509
+ const labelColor = "#009BF3";
510
+ let text = `${this.titleCase.transform(elementData.elementType)} ${elementData.elementNumber}`;
511
+ const wall = new fabric.Rect({
512
+ left: 0,
513
+ top: 0,
514
+ width,
515
+ height,
516
+ rx: radius,
517
+ ry: radius,
518
+ fill: fillColor,
519
+ stroke: strokeColor,
520
+ strokeWidth: 0.27,
521
+ selectable: false,
522
+ strokeUniform: true,
523
+ });
524
+ const centerX = width / 2;
525
+ const centerY = height / 2;
526
+ const isVertical = height > width;
527
+ const label = new fabric.FabricText(text, {
528
+ left: centerX,
529
+ top: centerY,
530
+ fontSize: 10,
531
+ fontFamily: "Inter",
532
+ fontWeight: "500",
533
+ fill: labelColor,
534
+ originX: "center",
535
+ originY: "center",
536
+ angle: isVertical ? -90 : 0,
537
+ selectable: false,
538
+ });
539
+ const arrowHead = 5;
540
+ const elements = [wall, label];
541
+ if (isVertical) {
542
+ const textWidth = label.width || 0;
543
+ const topArrowY = 5;
544
+ const topArrowEndY = centerY - textWidth / 2 - 5;
545
+ if (topArrowEndY > topArrowY + arrowHead) {
546
+ elements.push(new fabric.Line([centerX, topArrowY, centerX, topArrowEndY], {
547
+ stroke: labelColor,
548
+ strokeWidth: 1,
549
+ selectable: false,
550
+ }), new fabric.Triangle({
551
+ left: centerX,
552
+ top: topArrowY,
553
+ width: arrowHead,
554
+ height: arrowHead,
555
+ angle: 0,
556
+ fill: labelColor,
557
+ originX: "center",
558
+ originY: "bottom",
559
+ selectable: false,
560
+ }));
561
+ }
562
+ const bottomArrowStartY = centerY + textWidth / 2 + 5;
563
+ const bottomArrowEndY = height - 5;
564
+ if (bottomArrowEndY > bottomArrowStartY + arrowHead) {
565
+ elements.push(new fabric.Line([centerX, bottomArrowStartY, centerX, bottomArrowEndY], {
566
+ stroke: labelColor,
567
+ strokeWidth: 1,
568
+ selectable: false,
569
+ }), new fabric.Triangle({
570
+ left: centerX,
571
+ top: bottomArrowEndY,
572
+ width: arrowHead,
573
+ height: arrowHead,
574
+ angle: 180,
575
+ fill: labelColor,
576
+ originX: "center",
577
+ originY: "top",
578
+ selectable: false,
579
+ }));
580
+ }
581
+ }
582
+ else {
583
+ const textWidth = label.width || 0;
584
+ const leftArrowStartX = 5;
585
+ const leftArrowEndX = centerX - textWidth / 2 - 5;
586
+ if (leftArrowEndX > leftArrowStartX + arrowHead) {
587
+ elements.push(new fabric.Line([leftArrowStartX, centerY, leftArrowEndX, centerY], {
588
+ stroke: labelColor,
589
+ strokeWidth: 1,
590
+ selectable: false,
591
+ }), new fabric.Triangle({
592
+ left: leftArrowStartX,
593
+ top: centerY,
594
+ width: arrowHead,
595
+ height: arrowHead,
596
+ angle: -90,
597
+ fill: labelColor,
598
+ originX: "center",
599
+ originY: "center",
600
+ selectable: false,
601
+ }));
602
+ }
603
+ const rightArrowStartX = centerX + textWidth / 2 + 5;
604
+ const rightArrowEndX = width - 5;
605
+ if (rightArrowEndX > rightArrowStartX + arrowHead) {
606
+ elements.push(new fabric.Line([rightArrowStartX, centerY, rightArrowEndX, centerY], {
607
+ stroke: labelColor,
608
+ strokeWidth: 1,
609
+ selectable: false,
610
+ }), new fabric.Triangle({
611
+ left: rightArrowEndX,
612
+ top: centerY,
613
+ width: arrowHead,
614
+ height: arrowHead,
615
+ angle: 90,
616
+ fill: labelColor,
617
+ originX: "center",
618
+ originY: "center",
619
+ selectable: false,
620
+ }));
621
+ }
622
+ }
623
+ const group = new fabric.Group(elements, {
624
+ left: x,
625
+ top: y,
626
+ hasControls: false,
627
+ selectable: false,
628
+ lockScalingX: true,
629
+ lockScalingY: true,
630
+ lockRotation: true,
631
+ lockMovementX: true,
632
+ lockMovementY: true,
633
+ evented: true,
634
+ hoverCursor: "default",
635
+ angle: elementData.angle,
636
+ subTargetCheck: true,
637
+ });
638
+ group.objType = elementData.elementType;
639
+ group.data = elementData;
640
+ canvas.add(group);
641
+ // If newly added, focus it once
642
+ if (elementData?.newAdded) {
643
+ try {
644
+ canvas.setActiveObject(group);
645
+ canvas.requestRenderAll();
646
+ }
647
+ catch { }
648
+ delete elementData.newAdded;
649
+ }
650
+ return group;
651
+ }
652
+ drawEntrance(canvas, x, y, width, height, arrowWidth, elementData) {
653
+ const bodyWidth = width - arrowWidth;
654
+ const pathData = [
655
+ `M 0 0`,
656
+ `L ${bodyWidth} 0`,
657
+ `L ${bodyWidth} ${-height / 2}`,
658
+ `L ${width} ${height / 2}`,
659
+ `L ${bodyWidth} ${height + height / 2}`,
660
+ `L ${bodyWidth} ${height}`,
661
+ `L 0 ${height}`,
662
+ `Z`,
663
+ ].join(" ");
664
+ const arrow = new fabric.Path(pathData, {
665
+ fill: "#03A9F4",
666
+ selectable: false,
667
+ evented: false,
668
+ });
669
+ const maxTextHeight = height - 6;
670
+ const text = new fabric.Text("Entrance", {
671
+ fontFamily: "Arial",
672
+ fontWeight: "bold",
673
+ fill: "white",
674
+ angle: -90,
675
+ originX: "center",
676
+ originY: "center",
677
+ left: 15,
678
+ top: height / 2,
679
+ fontSize: 20,
680
+ selectable: false,
681
+ evented: false,
682
+ });
683
+ const textBounds = text.getBoundingRect();
684
+ if (textBounds.height > maxTextHeight) {
685
+ const scale = maxTextHeight / textBounds.height;
686
+ text.set("fontSize", text.fontSize * scale);
687
+ }
688
+ const group = new fabric.Group([arrow, text], {
689
+ left: x,
690
+ top: y,
691
+ hasControls: false,
692
+ selectable: false,
693
+ lockScalingX: true,
694
+ lockScalingY: true,
695
+ lockScalingFlip: true,
696
+ lockRotation: true,
697
+ lockMovementX: true,
698
+ lockMovementY: true,
699
+ evented: true,
700
+ hoverCursor: "default",
701
+ angle: elementData.angle,
702
+ });
703
+ group.objType = elementData.elementType;
704
+ group.data = elementData;
705
+ canvas.add(group);
706
+ }
707
+ async drawFixture(canvas, x, y, height, width, fixtureData) {
708
+ let fixtureColor;
709
+ // if (["fixture", "fixture-redo"].includes(this.publishingState)) {
710
+ // fixtureColor = {
711
+ // primary:
712
+ // fixtureData.status == "" && fixtureData.taskStatus == "submit"
713
+ // ? "#a5a6a8"
714
+ // : fixtureData.status == "agree"
715
+ // ? "#6CE9A6"
716
+ // : "#51C1FF",
717
+ // fill:
718
+ // fixtureData.status == "" && fixtureData.taskStatus == "submit"
719
+ // ? "#f3f4f8"
720
+ // : fixtureData.status == "agree"
721
+ // ? "#6CE9A6"
722
+ // : "#EAF8FF",
723
+ // vmFill:
724
+ // fixtureData.status == "" && fixtureData.taskStatus == "submit"
725
+ // ? "#a5a6a8"
726
+ // : "#6938EF",
727
+ // };
728
+ // }
729
+ if (fixtureData.fixtureName === "space")
730
+ return;
731
+ const radius = 5;
732
+ const mainContainer = new fabric.Rect({
733
+ left: x,
734
+ top: y,
735
+ width: width,
736
+ height: height,
737
+ rx: radius,
738
+ ry: radius,
739
+ stroke: fixtureColor?.primary ?? "#51C1FF",
740
+ strokeWidth: 0.27,
741
+ fill: "white",
742
+ });
743
+ const topWidth = width / 1.05;
744
+ const topHeight = (15 / 100) * height;
745
+ const topX = x + (width - topWidth) / 2;
746
+ const topY = y + this.verticalMargin;
747
+ const topContainer = new fabric.Rect({
748
+ left: topX,
749
+ top: topY,
750
+ width: topWidth,
751
+ height: topHeight,
752
+ rx: radius,
753
+ ry: radius,
754
+ stroke: fixtureColor?.primary ?? "#51C1FF",
755
+ strokeWidth: 0.27,
756
+ fill: "white",
757
+ });
758
+ const innerBoxHeight = topHeight / 2;
759
+ const innerTopBox = new fabric.Path(`M ${topX + radius} ${topY}
760
+ L ${topX + topWidth - radius} ${topY}
761
+ Q ${topX + topWidth} ${topY} ${topX + topWidth} ${topY + radius}
762
+ L ${topX + topWidth} ${topY + innerBoxHeight}
763
+ L ${topX} ${topY + innerBoxHeight}
764
+ L ${topX} ${topY + radius}
765
+ Q ${topX} ${topY} ${topX + radius} ${topY} Z`, {
766
+ stroke: fixtureColor?.primary ?? "#51C1FF",
767
+ strokeWidth: 0.27,
768
+ fill: "transparent",
769
+ });
770
+ const topText = new fabric.Textbox(`Fixture ${fixtureData.associatedElementFixtureNumber
771
+ ? fixtureData.associatedElementFixtureNumber +
772
+ (fixtureData?.fixtureNumber
773
+ ? " - FX-" + fixtureData.fixtureNumber
774
+ : "")
775
+ : "new"}`, {
776
+ left: topX + topWidth / 2,
777
+ top: topY + innerBoxHeight / 2,
778
+ fontSize: 5,
779
+ fontFamily: "Inter",
780
+ fontWeight: "500",
781
+ fill: "#101828",
782
+ originX: "center",
783
+ originY: "center",
784
+ width: topWidth,
785
+ height: innerBoxHeight,
786
+ textAlign: "center",
787
+ });
788
+ const secondBoxY = topY + innerBoxHeight;
789
+ const innerBottomBox = new fabric.Path(`M ${topX} ${secondBoxY}
790
+ L ${topX + topWidth} ${secondBoxY}
791
+ L ${topX + topWidth} ${secondBoxY + innerBoxHeight - radius}
792
+ Q ${topX + topWidth} ${secondBoxY + innerBoxHeight} ${topX + topWidth - radius} ${secondBoxY + innerBoxHeight}
793
+ L ${topX + radius} ${secondBoxY + innerBoxHeight}
794
+ Q ${topX} ${secondBoxY + innerBoxHeight} ${topX} ${secondBoxY + innerBoxHeight - radius}
795
+ L ${topX} ${secondBoxY} Z`, {
796
+ fill: "#344054",
797
+ stroke: fixtureColor?.primary ?? "#51C1FF",
798
+ strokeWidth: 0.27,
799
+ });
800
+ let fontSize = 5;
801
+ let bottomText;
802
+ const textContent = `${fixtureData?.fixtureName} - ${fixtureData?.fixtureWidth.value} ${fixtureData?.fixtureWidth.unit}`;
803
+ const createBottomText = (fs) => new fabric.Textbox(textContent, {
804
+ left: topX + topWidth / 2,
805
+ top: secondBoxY + innerBoxHeight / 2,
806
+ fontSize: fs,
807
+ fontFamily: "Inter",
808
+ fontWeight: "500",
809
+ fill: "#FFFFFF",
810
+ originX: "center",
811
+ originY: "center",
812
+ textAlign: "center",
813
+ width: topWidth,
814
+ });
815
+ do {
816
+ bottomText = createBottomText(fontSize);
817
+ fontSize -= 0.5;
818
+ } while (bottomText.height > innerBoxHeight && fontSize > 2);
819
+ const midWidth = width / 1.05;
820
+ const midHeight = (77 / 100) * height;
821
+ const midX = x + (width - midWidth) / 2;
822
+ const midY = topY + topHeight + this.verticalMargin;
823
+ const midContainer = new fabric.Rect({
824
+ left: midX,
825
+ top: midY,
826
+ width: midWidth,
827
+ height: midHeight,
828
+ rx: radius,
829
+ ry: radius,
830
+ stroke: fixtureColor?.primary ?? "#51C1FF",
831
+ strokeWidth: 0.27,
832
+ fill: "white",
833
+ });
834
+ const shelfCount = fixtureData.shelfConfig?.length;
835
+ const boxHeight = midHeight / (shelfCount + 2);
836
+ const firstBoxY = midY;
837
+ const firstBox = new fabric.Path(`M ${midX + radius} ${firstBoxY}
838
+ L ${midX + midWidth - radius} ${firstBoxY}
839
+ Q ${midX + midWidth} ${firstBoxY} ${midX + midWidth} ${firstBoxY + radius}
840
+ L ${midX + midWidth} ${firstBoxY + boxHeight}
841
+ L ${midX} ${firstBoxY + boxHeight}
842
+ L ${midX} ${firstBoxY + radius}
843
+ Q ${midX} ${firstBoxY} ${midX + radius} ${firstBoxY} Z`, {
844
+ fill: fixtureColor?.fill
845
+ ? fixtureColor?.fill
846
+ : fixtureData.issue
847
+ ? "#D92D20"
848
+ : "#EAF8FF",
849
+ stroke: fixtureColor?.primary
850
+ ? fixtureColor?.primary
851
+ : fixtureData.issue
852
+ ? "#D92D20"
853
+ : "#6BCAFF",
854
+ strokeWidth: 0.27,
855
+ });
856
+ const firstBoxText = new fabric.Textbox(`${fixtureData?.header?.label ? fixtureData.header.label : ""}`, {
857
+ left: midX + midWidth / 2,
858
+ top: firstBoxY + boxHeight / 2,
859
+ fontSize: 7,
860
+ fontFamily: "Inter",
861
+ fontWeight: "600",
862
+ fill: fixtureData.issue ? "#fff" : "#101828",
863
+ originX: "center",
864
+ originY: "center",
865
+ width: midWidth,
866
+ height: boxHeight,
867
+ textAlign: "center",
868
+ });
869
+ const shelves = [];
870
+ const shelfHeight = midHeight - 2 * boxHeight;
871
+ if (fixtureData.productResolutionLevel === "L1") {
872
+ const boxY = firstBoxY + boxHeight;
873
+ const shelf = new fabric.Rect({
874
+ left: midX,
875
+ top: boxY,
876
+ width: midWidth,
877
+ height: shelfHeight,
878
+ // stroke: '#51C1FF',
879
+ stroke: fixtureColor?.primary
880
+ ? fixtureColor?.primary
881
+ : fixtureData.issue
882
+ ? "#D92D20"
883
+ : "#51C1FF",
884
+ strokeWidth: 0.27,
885
+ fill: "white",
886
+ });
887
+ const text = fixtureData?.productBrandName?.join(" + ") || "";
888
+ // Wrap text within fixture width and shrink to fit vertical space
889
+ const maxTextWidth = midWidth * 0.9;
890
+ const maxTextHeight = shelfHeight * 0.8;
891
+ let fontSizeL1 = 6;
892
+ const createWrappedTextbox = (fs) => new fabric.Textbox(text, {
893
+ left: midX + midWidth / 2,
894
+ top: boxY + shelfHeight / 2,
895
+ originX: "center",
896
+ originY: "center",
897
+ width: maxTextWidth,
898
+ fontSize: fs,
899
+ fontFamily: "Inter",
900
+ fontWeight: "500",
901
+ textAlign: "center",
902
+ fill: "#333",
903
+ selectable: false,
904
+ evented: false,
905
+ });
906
+ let wrappedText = createWrappedTextbox(fontSizeL1);
907
+ while (wrappedText.height > maxTextHeight && fontSizeL1 > 2) {
908
+ fontSizeL1 -= 0.5;
909
+ wrappedText = createWrappedTextbox(fontSizeL1);
910
+ }
911
+ const padding = 2;
912
+ const background = new fabric.Rect({
913
+ left: midX + midWidth / 2,
914
+ top: boxY + shelfHeight / 2,
915
+ originX: "center",
916
+ originY: "center",
917
+ width: Math.min(maxTextWidth, wrappedText.width) + padding,
918
+ height: wrappedText.getScaledHeight() + 2,
919
+ fill: "rgba(255, 255, 255, 0.5)",
920
+ selectable: false,
921
+ evented: false,
922
+ rx: 1,
923
+ ry: 1,
924
+ });
925
+ shelves.push(shelf, background, wrappedText);
926
+ }
927
+ else if (fixtureData.productResolutionLevel === "L2") {
928
+ for (let i = 0; i < shelfCount; i++) {
929
+ const boxY = firstBoxY + boxHeight * (i + 1);
930
+ const shelf = new fabric.Rect({
931
+ left: midX,
932
+ top: boxY,
933
+ width: midWidth,
934
+ height: boxHeight,
935
+ stroke: fixtureColor?.primary
936
+ ? fixtureColor?.primary
937
+ : fixtureData.issue
938
+ ? "#D92D20"
939
+ : "#51C1FF",
940
+ strokeWidth: 0.27,
941
+ fill: "white",
942
+ });
943
+ shelves.push(shelf);
944
+ if (fixtureData.shelfConfig?.[i].shelfType === "tray") {
945
+ const trayRows = fixtureData.shelfConfig?.[i].trayRows || 1;
946
+ const rowSpacing = boxHeight / trayRows;
947
+ for (let r = 1; r < trayRows; r++) {
948
+ const lineY = boxY + r * rowSpacing;
949
+ const trayLine = new fabric.Line([midX, lineY, midX + midWidth, lineY], {
950
+ stroke: "#999",
951
+ strokeWidth: 0.2,
952
+ selectable: false,
953
+ evented: false,
954
+ });
955
+ shelves.push(trayLine);
956
+ }
957
+ }
958
+ const text = fixtureData.shelfConfig?.[i].productBrandName?.join(" + ") || "";
959
+ // L2: Single-line ellipsis against full shelf width
960
+ const horizontalPadding = 6;
961
+ const maxTextWidth = Math.max(0, midWidth - horizontalPadding);
962
+ const maxTextHeight = boxHeight * 0.8;
963
+ const baseFontSize = 5;
964
+ const measure = (t) => new fabric.Text(t, {
965
+ fontSize: baseFontSize,
966
+ fontFamily: "Inter",
967
+ fontWeight: "500",
968
+ });
969
+ let displayText = text;
970
+ let measured = measure(displayText);
971
+ if ((measured.width ?? 0) > maxTextWidth) {
972
+ const ellipsis = "...";
973
+ let leftIdx = 0;
974
+ let rightIdx = text.length;
975
+ while (leftIdx < rightIdx) {
976
+ const midIdx = Math.floor((leftIdx + rightIdx) / 2);
977
+ const candidate = text.slice(0, midIdx) + ellipsis;
978
+ measured = measure(candidate);
979
+ if ((measured.width ?? 0) > maxTextWidth) {
980
+ rightIdx = midIdx;
981
+ }
982
+ else {
983
+ leftIdx = midIdx + 1;
984
+ }
985
+ }
986
+ displayText = text.slice(0, Math.max(0, leftIdx - 1)) + ellipsis;
987
+ measured = measure(displayText);
988
+ }
989
+ const background = new fabric.Rect({
990
+ left: midX + midWidth / 2,
991
+ top: boxY + boxHeight / 2,
992
+ originX: "center",
993
+ originY: "center",
994
+ width: midWidth,
995
+ height: Math.min(maxTextHeight, measured.height ?? 10) + 2,
996
+ fill: "rgba(255, 255, 255, 0.5)",
997
+ selectable: false,
998
+ evented: false,
999
+ rx: 1,
1000
+ ry: 1,
1001
+ });
1002
+ const finalText = new fabric.Text(displayText, {
1003
+ left: midX + midWidth / 2,
1004
+ top: boxY + boxHeight / 2,
1005
+ originX: "center",
1006
+ originY: "center",
1007
+ fontSize: baseFontSize,
1008
+ fontFamily: "Inter",
1009
+ fontWeight: "500",
1010
+ fill: "#333",
1011
+ selectable: false,
1012
+ evented: false,
1013
+ });
1014
+ shelves.push(background, finalText);
1015
+ }
1016
+ }
1017
+ else if (fixtureData.productResolutionLevel === "L3") {
1018
+ const sequentialGroups = [];
1019
+ let previousZone = null;
1020
+ for (const shelf of fixtureData.shelfConfig) {
1021
+ const zone = shelf.zone || "Unknown";
1022
+ if (zone !== previousZone) {
1023
+ sequentialGroups.push({ zone, shelves: [shelf] });
1024
+ previousZone = zone;
1025
+ }
1026
+ else {
1027
+ sequentialGroups[sequentialGroups.length - 1].shelves.push(shelf);
1028
+ }
1029
+ }
1030
+ let currentShelfIndex = 0;
1031
+ for (const group of sequentialGroups) {
1032
+ const { zone, shelves: shelvesInGroup } = group;
1033
+ const groupStartIndex = currentShelfIndex;
1034
+ const groupLength = shelvesInGroup.length;
1035
+ const groupTopY = firstBoxY + boxHeight * (groupStartIndex + 1);
1036
+ const groupBottomY = groupTopY + boxHeight * groupLength;
1037
+ for (let j = 0; j < shelvesInGroup.length; j++) {
1038
+ const shelfData = shelvesInGroup[j];
1039
+ const boxY = firstBoxY + boxHeight * (currentShelfIndex + 1);
1040
+ const shelfRect = new fabric.Rect({
1041
+ left: midX,
1042
+ top: boxY,
1043
+ width: midWidth,
1044
+ height: boxHeight,
1045
+ stroke: fixtureColor?.primary
1046
+ ? fixtureColor?.primary
1047
+ : fixtureData.issue
1048
+ ? "#D92D20"
1049
+ : "#51C1FF",
1050
+ strokeWidth: 0.27,
1051
+ fill: "white",
1052
+ });
1053
+ shelves.push(shelfRect);
1054
+ if (shelfData.shelfType === "tray") {
1055
+ const trayRows = shelfData.trayRows || 0;
1056
+ const productPerShelf = shelfData.productPerShelf || 0;
1057
+ const rowSpacing = boxHeight / trayRows;
1058
+ const columnSpacing = midWidth / productPerShelf;
1059
+ for (let r = 1; r < trayRows; r++) {
1060
+ const lineY = boxY + r * rowSpacing;
1061
+ const trayLine = new fabric.Line([midX, lineY, midX + midWidth, lineY], {
1062
+ stroke: "#999",
1063
+ strokeWidth: 0.2,
1064
+ selectable: false,
1065
+ evented: false,
1066
+ });
1067
+ shelves.push(trayLine);
1068
+ }
1069
+ for (let c = 1; c < productPerShelf; c++) {
1070
+ const lineX = midX + c * columnSpacing;
1071
+ const verticalLine = new fabric.Line([lineX, boxY, lineX, boxY + boxHeight], {
1072
+ stroke: "#999",
1073
+ strokeWidth: 0.2,
1074
+ selectable: false,
1075
+ evented: false,
1076
+ });
1077
+ shelves.push(verticalLine);
1078
+ }
1079
+ }
1080
+ currentShelfIndex++;
1081
+ }
1082
+ const groupBottomLine = new fabric.Line([midX, groupBottomY, midX + midWidth, groupBottomY], {
1083
+ stroke: fixtureColor?.primary
1084
+ ? fixtureColor?.primary
1085
+ : fixtureData.issue
1086
+ ? "#D92D20"
1087
+ : "#51C1FF",
1088
+ strokeWidth: 1,
1089
+ selectable: false,
1090
+ evented: false,
1091
+ });
1092
+ shelves.push(groupBottomLine);
1093
+ if (fixtureData.fixtureType === "wall") {
1094
+ const labelPadding = 2;
1095
+ const labelText = new fabric.Textbox(zone, {
1096
+ left: midX + midWidth - labelPadding,
1097
+ top: groupBottomY,
1098
+ fontSize: 5,
1099
+ fontFamily: "Inter",
1100
+ fontWeight: "600",
1101
+ fill: "#707070",
1102
+ originX: "right",
1103
+ originY: "bottom",
1104
+ width: midWidth / 2,
1105
+ textAlign: "right",
1106
+ });
1107
+ shelves.push(labelText);
1108
+ }
1109
+ const groupCenterX = midX + midWidth / 2;
1110
+ const groupCenterY = groupTopY + (groupBottomY - groupTopY) / 2;
1111
+ const sectionBrands = new Set();
1112
+ shelvesInGroup?.forEach((shelf) => {
1113
+ shelf.productBrandName?.forEach((brand) => {
1114
+ sectionBrands.add(brand);
1115
+ });
1116
+ });
1117
+ if ([...sectionBrands].length) {
1118
+ const text = [...sectionBrands].join(" + ");
1119
+ const padding = 2;
1120
+ const maxTextWidth = midWidth;
1121
+ const rectWidth = midWidth * 0.9;
1122
+ const maxTextHeight = 20;
1123
+ let fontSize = 6;
1124
+ let wrappedText;
1125
+ const createTextbox = (fs) => {
1126
+ return new fabric.Textbox(text, {
1127
+ fontSize: fs,
1128
+ fontFamily: "Inter",
1129
+ fontWeight: "400",
1130
+ width: maxTextWidth,
1131
+ textAlign: "center",
1132
+ originX: "center",
1133
+ originY: "center",
1134
+ fill: "#101828",
1135
+ selectable: false,
1136
+ evented: false,
1137
+ left: groupCenterX,
1138
+ top: groupCenterY,
1139
+ });
1140
+ };
1141
+ do {
1142
+ wrappedText = createTextbox(fontSize);
1143
+ fontSize -= 0.5;
1144
+ } while (wrappedText.height > maxTextHeight && fontSize > 2);
1145
+ const rectHeight = wrappedText.getScaledHeight() + padding;
1146
+ const groupCenterText = new fabric.Rect({
1147
+ left: groupCenterX,
1148
+ top: groupCenterY,
1149
+ originX: "center",
1150
+ originY: "center",
1151
+ width: rectWidth,
1152
+ height: rectHeight,
1153
+ fill: "rgba(255, 255, 255, 0.5)",
1154
+ selectable: false,
1155
+ evented: false,
1156
+ rx: 1,
1157
+ ry: 1,
1158
+ });
1159
+ shelves.push(groupCenterText, wrappedText);
1160
+ }
1161
+ }
1162
+ }
1163
+ if (fixtureData?.vmConfig?.length) {
1164
+ for (let i = 0; i < fixtureData.vmConfig.length; i++) {
1165
+ const vm = fixtureData.vmConfig[i];
1166
+ const startIndex = vm.startYPosition - 1;
1167
+ const endIndex = vm.endYPosition - 1;
1168
+ const shelfTopY = firstBoxY + boxHeight * (startIndex + 1);
1169
+ const shelfHeightSpan = boxHeight * (endIndex - startIndex + 1);
1170
+ let vmHeightPx = shelfHeightSpan;
1171
+ let y = shelfTopY;
1172
+ if (vm.yZone && vm.yZone !== "stretch") {
1173
+ vmHeightPx = shelfHeightSpan / 3;
1174
+ switch (vm.yZone) {
1175
+ case "top":
1176
+ y = shelfTopY;
1177
+ break;
1178
+ case "middle":
1179
+ y = shelfTopY + vmHeightPx;
1180
+ break;
1181
+ case "bottom":
1182
+ y = shelfTopY + 2 * vmHeightPx;
1183
+ break;
1184
+ default:
1185
+ y = shelfTopY;
1186
+ }
1187
+ }
1188
+ let x = midX;
1189
+ let width = midWidth;
1190
+ if (!vm.xZone || vm.xZone === "stretch") {
1191
+ width = midWidth;
1192
+ x = midX;
1193
+ }
1194
+ else {
1195
+ const sectionWidth = midWidth / 3;
1196
+ switch (vm.xZone) {
1197
+ case "left":
1198
+ width = sectionWidth;
1199
+ x = midX;
1200
+ break;
1201
+ case "middle":
1202
+ width = sectionWidth;
1203
+ x = midX + sectionWidth;
1204
+ break;
1205
+ case "right":
1206
+ width = sectionWidth;
1207
+ x = midX + 2 * sectionWidth;
1208
+ break;
1209
+ default:
1210
+ width = midWidth;
1211
+ x = midX;
1212
+ }
1213
+ }
1214
+ if (vm.vmImageUrl) {
1215
+ try {
1216
+ const vmImage = await fabric.FabricImage.fromURL(`${this.cdnUrl}${vm.vmImageUrl}?v=${Date.now()}`, {
1217
+ crossOrigin: "anonymous",
1218
+ });
1219
+ vmImage.set({
1220
+ left: x + width / 2,
1221
+ top: y + vmHeightPx / 2,
1222
+ originX: "center",
1223
+ originY: "center",
1224
+ scaleX: width / vmImage.width,
1225
+ scaleY: vmHeightPx / vmImage.height,
1226
+ selectable: false,
1227
+ evented: false,
1228
+ });
1229
+ shelves.push(vmImage);
1230
+ }
1231
+ catch (err) {
1232
+ console.error(`Error loading image for VM: ${vm.vmImageUrl}`, err);
1233
+ }
1234
+ }
1235
+ else {
1236
+ const vmBox = new fabric.Rect({
1237
+ left: x,
1238
+ top: y,
1239
+ width,
1240
+ height: vmHeightPx,
1241
+ fill: fixtureColor?.vmFill ?? "#6938EF",
1242
+ selectable: false,
1243
+ evented: false,
1244
+ });
1245
+ let fontSize = 5;
1246
+ let vmText;
1247
+ const createVmText = (fs) => new fabric.Textbox(vm.vmName || "", {
1248
+ left: x + width / 2,
1249
+ top: y + vmHeightPx / 2,
1250
+ originX: "center",
1251
+ originY: "center",
1252
+ fontSize: fs,
1253
+ fontFamily: "Inter",
1254
+ fontWeight: "600",
1255
+ fill: "white",
1256
+ textAlign: "center",
1257
+ width: width,
1258
+ selectable: false,
1259
+ evented: false,
1260
+ });
1261
+ do {
1262
+ vmText = createVmText(fontSize);
1263
+ fontSize -= 0.5;
1264
+ } while (vmText.height > vmHeightPx && fontSize > 2);
1265
+ shelves.push(vmBox, vmText);
1266
+ }
1267
+ }
1268
+ }
1269
+ const lastBoxY = firstBoxY + boxHeight * (shelfCount + 1);
1270
+ const lastBox = new fabric.Path(`M ${midX} ${lastBoxY}
1271
+ L ${midX + midWidth} ${lastBoxY}
1272
+ L ${midX + midWidth} ${lastBoxY + boxHeight - radius}
1273
+ Q ${midX + midWidth} ${lastBoxY + boxHeight} ${midX + midWidth - radius} ${lastBoxY + boxHeight}
1274
+ L ${midX + radius} ${lastBoxY + boxHeight}
1275
+ Q ${midX} ${lastBoxY + boxHeight} ${midX} ${lastBoxY + boxHeight - radius}
1276
+ L ${midX} ${lastBoxY} Z`, {
1277
+ fill: fixtureColor?.fill
1278
+ ? fixtureColor?.fill
1279
+ : fixtureData.issue
1280
+ ? "#FEE4E2"
1281
+ : "#EAF8FF",
1282
+ stroke: fixtureColor?.primary
1283
+ ? fixtureColor?.primary
1284
+ : fixtureData.issue
1285
+ ? "#D92D20"
1286
+ : "#6BCAFF",
1287
+ strokeWidth: 0.27,
1288
+ });
1289
+ const lastBoxText = new fabric.Textbox(`${fixtureData?.footer?.label ? fixtureData.footer.label : ""}`, {
1290
+ left: midX + midWidth / 2,
1291
+ top: lastBoxY + boxHeight / 2,
1292
+ fontSize: 5,
1293
+ fontFamily: "Inter",
1294
+ fontWeight: "600",
1295
+ fill: "#101828",
1296
+ originX: "center",
1297
+ originY: "center",
1298
+ textAlign: "center",
1299
+ width: midWidth,
1300
+ heigth: boxHeight,
1301
+ });
1302
+ const bottomWidth = width / 1.05;
1303
+ const bottomHeight = (3 / 100) * height;
1304
+ const bottomX = x + (width - bottomWidth) / 2;
1305
+ const bottomY = midY + midHeight + this.verticalMargin;
1306
+ const bottomContainer = new fabric.Rect({
1307
+ left: bottomX,
1308
+ top: bottomY,
1309
+ width: bottomWidth,
1310
+ height: bottomHeight,
1311
+ rx: radius,
1312
+ ry: radius,
1313
+ stroke: "transparent",
1314
+ fill: "transparent",
1315
+ });
1316
+ const bottomTextContent = new fabric.Textbox(`Shelves - ${fixtureData.shelfConfig?.length} . Products - ${fixtureData.fixtureCapacity} . VM - ${fixtureData.vmConfig?.length}`, {
1317
+ left: bottomX + bottomWidth / 2,
1318
+ top: bottomY + bottomHeight / 2,
1319
+ fontSize: 5,
1320
+ fontFamily: "Inter",
1321
+ fontWeight: "500",
1322
+ fill: "#333",
1323
+ originX: "center",
1324
+ originY: "center",
1325
+ textAlign: "center",
1326
+ width: bottomWidth,
1327
+ height: bottomHeight,
1328
+ });
1329
+ const fixtureGroup = new fabric.Group([
1330
+ mainContainer,
1331
+ topContainer,
1332
+ innerTopBox,
1333
+ topText,
1334
+ innerBottomBox,
1335
+ bottomText,
1336
+ midContainer,
1337
+ firstBox,
1338
+ firstBoxText,
1339
+ ...shelves,
1340
+ lastBox,
1341
+ lastBoxText,
1342
+ bottomContainer,
1343
+ bottomTextContent,
1344
+ ], {
1345
+ left: x,
1346
+ top: y,
1347
+ evented: true,
1348
+ selectable: false,
1349
+ hoverCursor: "default",
1350
+ lockScalingX: true,
1351
+ lockScalingY: true,
1352
+ lockMovementX: true,
1353
+ lockMovementY: true,
1354
+ lockRotation: true,
1355
+ hasControls: false,
1356
+ subTargetCheck: true,
1357
+ angle: fixtureData.relativePosition?.angle ?? 0,
1358
+ });
1359
+ fixtureGroup.fixtureType = fixtureData.fixtureType;
1360
+ fixtureGroup.wallIndex = fixtureData.associatedElementNumber;
1361
+ fixtureGroup.fixtureIndex = fixtureData.associatedElementFixtureNumber;
1362
+ fixtureGroup.fixtureId = fixtureData._id;
1363
+ fixtureGroup.issue = fixtureData.issue;
1364
+ fixtureGroup.issueData = fixtureData.issueData;
1365
+ fixtureGroup.taskType = fixtureData.taskType;
1366
+ fixtureGroup.vmConfig = fixtureData.vmConfig;
1367
+ fixtureGroup.objType = "fixture";
1368
+ // Add click handler directly on the fixture group
1369
+ fixtureGroup.on("mousedown", (event) => {
1370
+ // Use the fixture group itself (which has all the fixture properties)
1371
+ // The event.target might be a child element, so we use fixtureGroup directly
1372
+ if (fixtureGroup && fixtureGroup.fixtureId) {
1373
+ // this.onFixtureClick(fixtureGroup);
1374
+ }
1375
+ });
1376
+ canvas.add(fixtureGroup);
1377
+ // If newly added, focus it once
1378
+ if (fixtureData?.newAdded) {
1379
+ try {
1380
+ canvas.setActiveObject(fixtureGroup);
1381
+ canvas.requestRenderAll();
1382
+ }
1383
+ catch { }
1384
+ delete fixtureData.newAdded;
1385
+ }
1386
+ return fixtureGroup;
1387
+ }
1388
+ drawOtherElementsWithLabel(canvas, x, y, a, width, height, element) {
1389
+ const rect = new fabric.Rect({
1390
+ width,
1391
+ height,
1392
+ rx: 2,
1393
+ ry: 2,
1394
+ fill: "#DAF1FF",
1395
+ stroke: "#6BCAFF",
1396
+ strokeWidth: 2,
1397
+ originX: "center",
1398
+ originY: "center",
1399
+ });
1400
+ const text = new fabric.Textbox(element.fixtureName, {
1401
+ width: width - 8,
1402
+ fontSize: 14,
1403
+ fontFamily: "Inter",
1404
+ fontWeight: "500",
1405
+ fill: "#101828",
1406
+ originX: "center",
1407
+ originY: "center",
1408
+ textAlign: "center",
1409
+ editable: false,
1410
+ splitByGrapheme: true,
1411
+ });
1412
+ const textBounds = text.getBoundingRect();
1413
+ if (textBounds.height > height - 8) {
1414
+ const scale = (height - 8) / textBounds.height;
1415
+ text.set("fontSize", text.fontSize * scale);
1416
+ }
1417
+ const group = new fabric.Group([rect, text], {
1418
+ left: x,
1419
+ top: y,
1420
+ angle: a,
1421
+ originX: "center",
1422
+ originY: "center",
1423
+ hasControls: false,
1424
+ selectable: false,
1425
+ lockScalingX: true,
1426
+ lockScalingY: true,
1427
+ lockRotation: true,
1428
+ lockMovementX: true,
1429
+ lockMovementY: true,
1430
+ evented: true,
1431
+ hoverCursor: "default",
1432
+ });
1433
+ group.objType = "others";
1434
+ group.data = element;
1435
+ canvas.add(group);
1436
+ if (element?.newAdded) {
1437
+ try {
1438
+ canvas.setActiveObject(group);
1439
+ canvas.requestRenderAll();
1440
+ }
1441
+ catch { }
1442
+ delete element.newAdded;
1443
+ }
1444
+ return group;
1445
+ }
1446
+ resizeCanvas(canvas, container) {
1447
+ const containerEl = container.nativeElement;
1448
+ const width = containerEl.clientWidth || containerEl.offsetWidth;
1449
+ const height = containerEl.clientHeight || containerEl.offsetHeight;
1450
+ if (width > 0 && height > 0) {
1451
+ canvas.setDimensions({
1452
+ width: width,
1453
+ height: height,
1454
+ });
1455
+ canvas.calcOffset();
1456
+ canvas.requestRenderAll();
1457
+ }
1458
+ }
1459
+ fitCanvasToLayoutAnimated(canvas) {
1460
+ if (!canvas)
1461
+ return;
1462
+ // Ensure canvas has objects before calculating bounds
1463
+ const objects = canvas.getObjects();
1464
+ if (!objects || objects.length === 0) {
1465
+ console.warn('No objects on canvas to fit');
1466
+ return;
1467
+ }
1468
+ // Force recalculation of object coordinates
1469
+ canvas.calcOffset();
1470
+ const bounds = this.getFullLayoutBounds(canvas);
1471
+ if (!bounds.width || !bounds.height || bounds.width === 0 || bounds.height === 0) {
1472
+ console.warn('Invalid bounds for canvas fitting', bounds);
1473
+ return;
1474
+ }
1475
+ const canvasW = canvas.getWidth();
1476
+ const canvasH = canvas.getHeight();
1477
+ if (canvasW === 0 || canvasH === 0) {
1478
+ console.warn('Canvas dimensions are zero');
1479
+ return;
1480
+ }
1481
+ const scaleX = canvasW / bounds.width;
1482
+ const scaleY = canvasH / bounds.height;
1483
+ // Use smaller multiplier (0.5) to zoom out more and ensure planogram fits with more padding inside canvas
1484
+ const targetZoom = Math.min(scaleX, scaleY) * 0.9;
1485
+ // Ensure zoom is within reasonable bounds
1486
+ const finalZoom = Math.max(0.1, Math.min(targetZoom, 3));
1487
+ const targetVpt = [...(canvas.viewportTransform || [1, 0, 0, 1, 0, 0])];
1488
+ targetVpt[0] = finalZoom;
1489
+ targetVpt[3] = finalZoom;
1490
+ // Calculate center of layout bounds for horizontal centering
1491
+ const centerX = bounds.left + bounds.width / 2;
1492
+ // Position from top with very minimal padding (use top space)
1493
+ const topPadding = 10; // Fixed 10px padding from top
1494
+ // Calculate translation: center horizontally, position from top
1495
+ targetVpt[4] = canvasW / 2 - centerX * finalZoom;
1496
+ targetVpt[5] = topPadding - bounds.top * finalZoom;
1497
+ const startVpt = [...canvas.viewportTransform];
1498
+ fabric.util.animate({
1499
+ startValue: 0,
1500
+ endValue: 1,
1501
+ duration: 500,
1502
+ onChange: (value) => {
1503
+ const vpt = [...startVpt];
1504
+ vpt[0] = startVpt[0] + (targetVpt[0] - startVpt[0]) * value;
1505
+ vpt[3] = startVpt[3] + (targetVpt[3] - startVpt[3]) * value;
1506
+ vpt[4] = startVpt[4] + (targetVpt[4] - startVpt[4]) * value;
1507
+ vpt[5] = startVpt[5] + (targetVpt[5] - startVpt[5]) * value;
1508
+ canvas.setViewportTransform(vpt);
1509
+ canvas.requestRenderAll();
1510
+ },
1511
+ });
1512
+ }
1513
+ getFullLayoutBounds(canvas) {
1514
+ const objects = canvas.getObjects();
1515
+ if (!objects.length)
1516
+ return { left: 0, top: 0, width: 0, height: 0 };
1517
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
1518
+ for (const obj of objects) {
1519
+ // Get bounding rect which accounts for object's position, rotation, and scale
1520
+ const boundingRect = obj.getBoundingRect();
1521
+ // Get the actual bounding box
1522
+ const left = boundingRect.left;
1523
+ const top = boundingRect.top;
1524
+ const right = left + boundingRect.width;
1525
+ const bottom = top + boundingRect.height;
1526
+ minX = Math.min(minX, left);
1527
+ minY = Math.min(minY, top);
1528
+ maxX = Math.max(maxX, right);
1529
+ maxY = Math.max(maxY, bottom);
1530
+ }
1531
+ return { left: minX, top: minY, width: maxX - minX, height: maxY - minY };
1532
+ }
1533
+ toPixels(value, unit, dpi = 2.8) {
1534
+ let pixels;
1535
+ if (unit === "mm") {
1536
+ pixels = (value / 25.4) * dpi;
1537
+ }
1538
+ else if (unit === "ft") {
1539
+ pixels = value * 12 * dpi;
1540
+ }
1541
+ else {
1542
+ throw new Error("Unsupported unit. Use 'mm' or 'ft'.");
1543
+ }
1544
+ return Number(pixels.toFixed(4));
1545
+ }
1546
+ // Store list methods
1547
+ onSelectAll(checked) {
1548
+ if (checked) {
1549
+ // Only select stores that don't have no-match status
1550
+ this.filteredStores.forEach(store => {
1551
+ if (!this.hasNoMatch(store)) {
1552
+ store.isApproved = true;
1553
+ this.selectedStores.add(store.storeName);
1554
+ }
1555
+ });
1556
+ }
1557
+ else {
1558
+ // Deselect all stores
1559
+ this.filteredStores.forEach(store => {
1560
+ store.isApproved = false;
1561
+ });
1562
+ this.selectedStores.clear();
1563
+ }
1564
+ // Update findReplaceData stores array and notify data service
1565
+ if (this.findReplaceData?.stores) {
1566
+ const stores = this.findReplaceData.stores;
1567
+ this.filteredStores.forEach(filteredStore => {
1568
+ if (filteredStore && stores) {
1569
+ const storeIndex = stores.findIndex(s => s && s.storeName === filteredStore.storeName);
1570
+ if (storeIndex !== -1 && stores[storeIndex]) {
1571
+ stores[storeIndex].isApproved = filteredStore.isApproved;
1572
+ }
1573
+ }
1574
+ });
1575
+ // Update data service to preserve state
1576
+ if (stores) {
1577
+ this.dataService.updateData({ stores: stores });
1578
+ }
1579
+ }
1580
+ }
1581
+ onStoreCheckboxChange(store, checked) {
1582
+ // Prevent selection if store has no-match status
1583
+ if (this.hasNoMatch(store)) {
1584
+ return;
1585
+ }
1586
+ if (!store) {
1587
+ return;
1588
+ }
1589
+ // Update isApproved property on the store object
1590
+ store.isApproved = checked;
1591
+ // Update the store in the local stores array
1592
+ const localStoreIndex = this.stores.findIndex(s => s.storeName === store.storeName);
1593
+ if (localStoreIndex !== -1 && this.stores[localStoreIndex]) {
1594
+ this.stores[localStoreIndex].isApproved = checked;
1595
+ }
1596
+ // Update selectedStores set for backward compatibility
1597
+ if (checked) {
1598
+ this.selectedStores.add(store.storeName);
1599
+ }
1600
+ else {
1601
+ this.selectedStores.delete(store.storeName);
1602
+ }
1603
+ // Update the store in findReplaceData stores array and notify data service to preserve state
1604
+ if (this.findReplaceData?.stores) {
1605
+ const storeIndex = this.findReplaceData.stores.findIndex(s => s.storeName === store.storeName);
1606
+ if (storeIndex !== -1 && this.findReplaceData.stores[storeIndex]) {
1607
+ this.findReplaceData.stores[storeIndex].isApproved = checked;
1608
+ // Update data service to preserve state when save as draft is called
1609
+ this.dataService.updateData({ stores: this.findReplaceData.stores });
1610
+ }
1611
+ }
1612
+ }
1613
+ isStoreSelected(storeName) {
1614
+ // Check both selectedStores set and isApproved property
1615
+ const store = this.stores.find(s => s.storeName === storeName);
1616
+ return this.selectedStores.has(storeName) || (store?.isApproved === true);
1617
+ }
1618
+ isAllSelected() {
1619
+ // Only consider selectable stores (exclude no-match stores)
1620
+ const selectableStores = this.filteredStores.filter(store => !this.hasNoMatch(store));
1621
+ return selectableStores.length > 0 && selectableStores.every(store => store.isApproved === true);
1622
+ }
1623
+ onSearch() {
1624
+ this.applyFilters();
1625
+ }
1626
+ applyFilters() {
1627
+ let filtered = [...this.stores];
1628
+ // Apply search filter
1629
+ if (this.searchTerm.trim()) {
1630
+ const term = this.searchTerm.toLowerCase();
1631
+ filtered = filtered.filter(store => store.storeName.toLowerCase().includes(term));
1632
+ }
1633
+ // Apply status filter
1634
+ if (this.selectedStatusFilters.size > 0) {
1635
+ filtered = filtered.filter(store => {
1636
+ if (!store.responseStatus) {
1637
+ return this.selectedStatusFilters.has('unknown');
1638
+ }
1639
+ return this.selectedStatusFilters.has(store.responseStatus);
1640
+ });
1641
+ }
1642
+ this.filteredStores = filtered;
1643
+ this.totalItems = this.filteredStores.length;
1644
+ this.offset = 1; // Reset to first page when filters change
1645
+ }
1646
+ get paginatedStores() {
1647
+ const startIndex = (this.offset - 1) * this.limit;
1648
+ const endIndex = startIndex + this.limit;
1649
+ return this.filteredStores.slice(startIndex, endIndex);
1650
+ }
1651
+ onDownload() {
1652
+ if (!this.stores || this.stores.length === 0) {
1653
+ console.warn('No stores to export');
1654
+ return;
1655
+ }
1656
+ // Prepare data for Excel export
1657
+ const exportData = this.stores.map(store => ({
1658
+ 'Store Name': store.storeName,
1659
+ 'Status': store.responseStatus === 'match' ? 'Match' :
1660
+ store.responseStatus === 'no-match' ? 'No Match' :
1661
+ 'Unknown'
1662
+ }));
1663
+ // Export to Excel
1664
+ const fileName = `Stores_Export_${new Date().toISOString().split('T')[0]}`;
1665
+ this.storeBuilderService.exportAsExcelFile(exportData, fileName);
1666
+ }
1667
+ onFilter() {
1668
+ // Filter functionality is handled via dropdown in template
1669
+ }
1670
+ onStatusFilterChange(status, event) {
1671
+ const isChecked = event.target.checked;
1672
+ if (isChecked) {
1673
+ this.selectedStatusFilters.add(status);
1674
+ }
1675
+ else {
1676
+ this.selectedStatusFilters.delete(status);
1677
+ }
1678
+ this.applyFilters();
1679
+ }
1680
+ isStatusFilterSelected(status) {
1681
+ return this.selectedStatusFilters.has(status);
1682
+ }
1683
+ clearFilters() {
1684
+ this.selectedStatusFilters.clear();
1685
+ this.searchTerm = '';
1686
+ this.applyFilters();
1687
+ }
1688
+ hasActiveFilters() {
1689
+ return this.selectedStatusFilters.size > 0 || this.searchTerm.trim().length > 0;
1690
+ }
1691
+ async onApproveAndComplete() {
1692
+ try {
1693
+ const modalRef = this.modalService.open(ApproveCompleteModalComponent, {
1694
+ centered: true,
1695
+ size: 'lg',
1696
+ backdrop: 'static',
1697
+ windowClass: 'approve-complete-modal'
1698
+ });
1699
+ // Pre-fill modal with existing schedule values if available
1700
+ modalRef.componentInstance.initialSchedule = this.findReplaceData?.schedule || false;
1701
+ modalRef.componentInstance.initialScheduleDate = this.findReplaceData?.scheduleDate || null;
1702
+ const result = await modalRef.result;
1703
+ if (result) {
1704
+ // Handle the approve and complete action
1705
+ console.log('Approve and complete with schedule:', result.schedule, 'scheduleDate:', result.scheduleDate);
1706
+ // Get findReplaceId from findReplaceData
1707
+ if (!this.findReplaceData?._id) {
1708
+ console.error('FindReplace ID is missing');
1709
+ return;
1710
+ }
1711
+ // Save stores, schedule, and scheduleDate using save as draft first
1712
+ const draftData = {};
1713
+ if (this.findReplaceData.stores && this.findReplaceData.stores.length > 0) {
1714
+ draftData.stores = this.findReplaceData.stores;
1715
+ }
1716
+ if (result.schedule !== undefined) {
1717
+ draftData.schedule = result.schedule;
1718
+ }
1719
+ if (result.scheduleDate !== undefined) {
1720
+ draftData.scheduleDate = result.scheduleDate;
1721
+ }
1722
+ // Wait for save as draft to complete before calling approveReplace
1723
+ this.approveLoading = true;
1724
+ try {
1725
+ // Save all the data using save as draft and wait for it to complete
1726
+ if (Object.keys(draftData).length > 0) {
1727
+ const saveResponse = await this.dataService.saveDraftAndWait(draftData).toPromise();
1728
+ if (saveResponse?.code !== 200) {
1729
+ console.error('Failed to save as draft:', saveResponse?.message || 'Unknown error');
1730
+ this.approveLoading = false;
1731
+ return;
1732
+ }
1733
+ }
1734
+ // Call the approveReplace API with only findReplaceId after save as draft completes
1735
+ const response = await this.storeBuilderService.approveReplace({
1736
+ findReplaceId: this.findReplaceData._id,
1737
+ }).toPromise();
1738
+ console.log('Approve replace response:', response);
1739
+ this.approveLoading = false;
1740
+ // Navigate to table page on successful response
1741
+ if (response?.code === 200) {
1742
+ this.router.navigate(['/manage/planogram/find-replace-table']);
1743
+ }
1744
+ }
1745
+ catch (error) {
1746
+ console.error('Error approving replace:', error);
1747
+ this.approveLoading = false;
1748
+ // TODO: Handle error (e.g., show error message)
1749
+ }
1750
+ }
1751
+ }
1752
+ catch (error) {
1753
+ console.log('Modal dismissed');
1754
+ }
1755
+ }
1756
+ hasNoMatch(store) {
1757
+ return store.responseStatus === 'no-match';
1758
+ }
1759
+ isApproved() {
1760
+ return this.findReplaceData?.status === 'approved';
1761
+ }
1762
+ previousNext(step) {
1763
+ if (!this.selectedStore || this.filteredStores.length === 0)
1764
+ return;
1765
+ const curIdx = this.filteredStores.findIndex((store) => store.storeName === this.selectedStore?.storeName);
1766
+ let newIdx;
1767
+ if (step === 'previous') {
1768
+ if (curIdx === 0)
1769
+ return;
1770
+ newIdx = curIdx - 1;
1771
+ }
1772
+ else {
1773
+ if (curIdx === this.filteredStores.length - 1)
1774
+ return;
1775
+ newIdx = curIdx + 1;
1776
+ }
1777
+ // Update pagination if the new store is on a different page
1778
+ const newPage = Math.floor(newIdx / this.limit) + 1;
1779
+ if (newPage !== this.offset) {
1780
+ this.offset = newPage;
1781
+ // Scroll to top of store list when page changes
1782
+ const listContainer = document.querySelector('.list-container');
1783
+ if (listContainer) {
1784
+ listContainer.scrollTop = 0;
1785
+ }
1786
+ }
1787
+ this.onStoreSelect(this.filteredStores[newIdx]);
1788
+ }
1789
+ paginationSize() {
1790
+ return this.limit;
1791
+ }
1792
+ onPageChange(page) {
1793
+ this.offset = page;
1794
+ // Scroll to top of store list when page changes
1795
+ const listContainer = document.querySelector('.list-container');
1796
+ if (listContainer) {
1797
+ listContainer.scrollTop = 0;
1798
+ }
1799
+ }
1800
+ onPageSizeChange(size) {
1801
+ this.limit = size;
1802
+ this.offset = 1; // Reset to first page when page size changes
1803
+ // Scroll to top of store list when page size changes
1804
+ const listContainer = document.querySelector('.list-container');
1805
+ if (listContainer) {
1806
+ listContainer.scrollTop = 0;
1807
+ }
1808
+ }
1809
+ highlightFixture(canvas, group, blink = false) {
1810
+ this.removeHighlight(canvas);
1811
+ this.cancelHighlightBlink = false;
1812
+ const center = group.getCenterPoint();
1813
+ const realWidth = group.width * group.scaleX;
1814
+ const realHeight = group.height * group.scaleY;
1815
+ const rect = new fabric.Rect({
1816
+ left: center.x,
1817
+ top: center.y,
1818
+ width: realWidth + 8,
1819
+ height: realHeight + 8,
1820
+ rx: 5,
1821
+ ry: 5,
1822
+ stroke: "#00aaff",
1823
+ strokeWidth: 3,
1824
+ fill: "transparent",
1825
+ selectable: false,
1826
+ evented: false,
1827
+ originX: "center",
1828
+ originY: "center",
1829
+ angle: group.angle || 0,
1830
+ opacity: blink ? 0 : 1,
1831
+ });
1832
+ rect.data = { type: "fixture-highlight" };
1833
+ canvas.add(rect);
1834
+ canvas.moveObjectTo(rect, canvas.getObjects().length - 1);
1835
+ canvas.requestRenderAll();
1836
+ this.activeHighlight = rect;
1837
+ if (!blink)
1838
+ return;
1839
+ let cycles = 0;
1840
+ const blinkOnce = () => {
1841
+ if (this.cancelHighlightBlink) {
1842
+ this.removeHighlight(canvas);
1843
+ return;
1844
+ }
1845
+ rect.animate({ opacity: 1 }, {
1846
+ duration: 200,
1847
+ onChange: () => canvas.requestRenderAll(),
1848
+ onComplete: () => {
1849
+ if (this.cancelHighlightBlink) {
1850
+ this.removeHighlight(canvas);
1851
+ return;
1852
+ }
1853
+ rect.animate({ opacity: 0 }, {
1854
+ duration: 200,
1855
+ onChange: () => canvas.requestRenderAll(),
1856
+ onComplete: () => {
1857
+ if (this.cancelHighlightBlink) {
1858
+ this.removeHighlight(canvas);
1859
+ return;
1860
+ }
1861
+ cycles++;
1862
+ if (cycles < 20) {
1863
+ blinkOnce();
1864
+ }
1865
+ else {
1866
+ if (!this.cancelHighlightBlink) {
1867
+ rect.set({ opacity: 1 });
1868
+ canvas.requestRenderAll();
1869
+ }
1870
+ }
1871
+ },
1872
+ });
1873
+ },
1874
+ });
1875
+ };
1876
+ blinkOnce();
1877
+ }
1878
+ removeHighlight(canvas) {
1879
+ this.cancelHighlightBlink = true;
1880
+ canvas.getObjects().forEach((obj) => {
1881
+ if (obj.data?.type === "fixture-highlight") {
1882
+ canvas.remove(obj);
1883
+ }
1884
+ });
1885
+ this.activeHighlight = null;
1886
+ canvas.requestRenderAll();
1887
+ }
1888
+ onFixtureClick(target) {
1889
+ if (!target || !this.floorData)
1890
+ return;
1891
+ const fixtureId = target.fixtureId;
1892
+ const fixtureType = target.fixtureType;
1893
+ if (!fixtureId) {
1894
+ console.warn('Fixture click: No fixtureId found on target', target);
1895
+ return;
1896
+ }
1897
+ // Find the fixture data
1898
+ let fixtureData = null;
1899
+ if (fixtureType === "wall") {
1900
+ const wallIndex = target.wallIndex;
1901
+ if (this.floorData.layoutPolygon && wallIndex !== undefined && wallIndex !== null) {
1902
+ // Find wall by elementNumber (wallIndex is the elementNumber)
1903
+ const wall = this.floorData.layoutPolygon.find((w) => w.elementNumber === wallIndex);
1904
+ if (wall && wall.fixtures) {
1905
+ fixtureData = wall.fixtures.find((f) => f._id === fixtureId);
1906
+ }
1907
+ }
1908
+ }
1909
+ else if (fixtureType === "floor") {
1910
+ fixtureData = this.floorData.centerFixture?.find((f) => f._id === fixtureId);
1911
+ }
1912
+ if (!fixtureData) {
1913
+ console.warn('Fixture click: Fixture data not found', {
1914
+ fixtureId,
1915
+ fixtureType,
1916
+ wallIndex: target.wallIndex,
1917
+ fixtureIndex: target.fixtureIndex,
1918
+ floorData: this.floorData
1919
+ });
1920
+ return;
1921
+ }
1922
+ // Ensure vmConfig is always an array (even if empty) to avoid display issues
1923
+ if (!Array.isArray(fixtureData.vmConfig)) {
1924
+ fixtureData.vmConfig = [];
1925
+ }
1926
+ // Ensure shelfConfig is always an array (even if empty) to avoid display issues
1927
+ if (!Array.isArray(fixtureData.shelfConfig)) {
1928
+ fixtureData.shelfConfig = [];
1929
+ }
1930
+ // Create a deep clone to ensure change detection works
1931
+ const clonedData = structuredClone(fixtureData);
1932
+ // Ensure cloned data also has proper array structures
1933
+ if (!Array.isArray(clonedData.vmConfig)) {
1934
+ clonedData.vmConfig = [];
1935
+ }
1936
+ if (!Array.isArray(clonedData.shelfConfig)) {
1937
+ clonedData.shelfConfig = [];
1938
+ }
1939
+ this.selectedFixture = {
1940
+ fixtureId: fixtureId,
1941
+ fixtureType: fixtureType,
1942
+ wallIndex: target.wallIndex,
1943
+ fixtureIndex: target.fixtureIndex,
1944
+ };
1945
+ // Check if this fixture has replaceResponseData (for before/after comparison)
1946
+ const store = this.findReplaceData?.stores?.find((s) => s.storeName === this.selectedStore?.storeName);
1947
+ // If this fixture matches the findResponseData and has replaceResponseData,
1948
+ // restore the original fixture data for before/after comparison
1949
+ if (store?.findResponseData === fixtureId && store?.replaceResponseData) {
1950
+ // Restore originalFixtureData from the map (persists even when clicking other fixtures)
1951
+ const storedOriginal = this.originalFixturesMap.get(fixtureId);
1952
+ if (storedOriginal) {
1953
+ this.originalFixtureData = structuredClone(storedOriginal);
1954
+ // Ensure original data has proper array structures
1955
+ if (!Array.isArray(this.originalFixtureData.vmConfig)) {
1956
+ this.originalFixtureData.vmConfig = [];
1957
+ }
1958
+ if (!Array.isArray(this.originalFixtureData.shelfConfig)) {
1959
+ this.originalFixtureData.shelfConfig = [];
1960
+ }
1961
+ }
1962
+ else {
1963
+ // If not in map (shouldn't happen if applyStoredResponseData ran),
1964
+ // use current fixture as fallback
1965
+ this.originalFixtureData = structuredClone(clonedData);
1966
+ if (!Array.isArray(this.originalFixtureData.vmConfig)) {
1967
+ this.originalFixtureData.vmConfig = [];
1968
+ }
1969
+ if (!Array.isArray(this.originalFixtureData.shelfConfig)) {
1970
+ this.originalFixtureData.shelfConfig = [];
1971
+ }
1972
+ }
1973
+ }
1974
+ else {
1975
+ // No replace data for this fixture, clear original
1976
+ this.originalFixtureData = null;
1977
+ }
1978
+ // Set selected fixture data (this is the "after" data with replaceResponseData applied)
1979
+ // For fixtures with replaceResponseData, ensure all original properties are preserved
1980
+ if (store?.findResponseData === fixtureId && store?.replaceResponseData) {
1981
+ const storedOriginal = this.originalFixturesMap.get(fixtureId);
1982
+ if (storedOriginal) {
1983
+ // Merge: start with original to preserve all base properties, then apply updates
1984
+ this.selectedFixtureData = {
1985
+ ...storedOriginal,
1986
+ ...clonedData,
1987
+ // Explicitly ensure arrays are correct
1988
+ vmConfig: Array.isArray(clonedData.vmConfig) ? clonedData.vmConfig : (storedOriginal.vmConfig || []),
1989
+ shelfConfig: Array.isArray(clonedData.shelfConfig) ? clonedData.shelfConfig : (storedOriginal.shelfConfig || [])
1990
+ };
1991
+ }
1992
+ else {
1993
+ this.selectedFixtureData = clonedData;
1994
+ }
1995
+ }
1996
+ else {
1997
+ this.selectedFixtureData = clonedData;
1998
+ }
1999
+ // Don't highlight on click - keep highlight fixed on the fixture with findResponseData
2000
+ // The highlight is set when the planogram loads and should remain fixed
2001
+ // Open offcanvas with before/after comparison
2002
+ this.openFixtureOffcanvas();
2003
+ }
2004
+ openFixtureOffcanvas() {
2005
+ // Use wider offcanvas when showing before/after comparison
2006
+ const hasBeforeAfter = !!this.originalFixtureData;
2007
+ const panelClass = hasBeforeAfter
2008
+ ? 'fixture-before-after-offcanvas-wide'
2009
+ : 'fixture-before-after-offcanvas';
2010
+ const offcanvasRef = this.offcanvasService.open(FixtureBeforeAfterComponent, {
2011
+ position: 'end',
2012
+ panelClass: panelClass,
2013
+ backdrop: true,
2014
+ backdropClass: 'offcanvas-backdrop'
2015
+ });
2016
+ offcanvasRef.componentInstance.selectedFixtureData = this.selectedFixtureData;
2017
+ offcanvasRef.componentInstance.originalFixtureData = this.originalFixtureData;
2018
+ }
2019
+ ngOnDestroy() {
2020
+ this.destroy$.next();
2021
+ this.destroy$.complete();
2022
+ if (this.previewCanvas) {
2023
+ this.previewCanvas.dispose();
2024
+ }
2025
+ }
2026
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ReviewReplaceComponent, deps: [{ token: i1.CollectionUpdateAiDataService }, { token: i2.StoreBuilderService }, { token: i0.ChangeDetectorRef }, { token: i3.GlobalStateService }, { token: i4.TitleCasePipe }, { token: i5.NgbOffcanvas }, { token: i5.NgbModal }, { token: i6.Router }], target: i0.ɵɵFactoryTarget.Component });
2027
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ReviewReplaceComponent, isStandalone: true, selector: "lib-review-replace", providers: [TitleCasePipe], viewQueries: [{ propertyName: "previewCanvasRef", first: true, predicate: ["previewCanvas"], descendants: true }, { propertyName: "previewCanvasContainerRef", first: true, predicate: ["previewCanvasContainer"], descendants: true }], ngImport: i0, template: "<div class=\"review-replace-container\">\r\n <div class=\"row g-0 h-100\">\r\n <!-- Left Sidebar: Store List -->\r\n <div class=\"col-3 sidebar-container\">\r\n <div class=\"sidebar-content\">\r\n <!-- Header Section -->\r\n <div class=\"header-section\">\r\n <div class=\"all-stores-box\">\r\n <p class=\"all-stores-text\">All stores</p>\r\n </div>\r\n <button class=\"download-btn\" (click)=\"onDownload()\" aria-label=\"Download\">\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\r\n <path d=\"M17.5 12.5V13.5C17.5 14.9001 17.5 15.6002 17.2275 16.135C16.9878 16.6054 16.6054 16.9878 16.135 17.2275C15.6002 17.5 14.9001 17.5 13.5 17.5H6.5C5.09987 17.5 4.3998 17.5 3.86502 17.2275C3.39462 16.9878 3.01217 16.6054 2.77248 16.135C2.5 15.6002 2.5 14.9001 2.5 13.5V12.5M14.1667 8.33333L10 12.5M10 12.5L5.83333 8.33333M10 12.5V2.5\" stroke=\"#344054\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <!-- Select All Section -->\r\n <div class=\"select-all-section\">\r\n <div class=\"form-check\">\r\n <input \r\n class=\"form-check-input\" \r\n type=\"checkbox\" \r\n id=\"selectAll\"\r\n [checked]=\"isAllSelected()\"\r\n (change)=\"onSelectAll($any($event.target).checked)\">\r\n <label class=\"form-check-label select-all-label\" for=\"selectAll\">\r\n Select all ({{ filteredStores.length }})\r\n </label>\r\n </div>\r\n </div>\r\n\r\n <!-- Search and Filter Section -->\r\n <div class=\"search-filter-section\">\r\n <div class=\"search-input-wrapper\">\r\n <svg class=\"search-icon\" viewBox=\"0 0 20 20\" fill=\"none\">\r\n <path d=\"M17.5 17.5L13.875 13.875M15.8333 9.16667C15.8333 12.8486 12.8486 15.8333 9.16667 15.8333C5.48477 15.8333 2.5 12.8486 2.5 9.16667C2.5 5.48477 5.48477 2.5 9.16667 2.5C12.8486 2.5 15.8333 5.48477 15.8333 9.16667Z\" stroke=\"#667085\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n <input \r\n type=\"text\" \r\n class=\"search-input\" \r\n placeholder=\"Search\"\r\n [(ngModel)]=\"searchTerm\"\r\n (input)=\"onSearch()\">\r\n </div>\r\n <div class=\"dropdown\" ngbDropdown>\r\n <button \r\n class=\"filter-btn\" \r\n [class.active]=\"hasActiveFilters()\"\r\n id=\"filterDropdown\" \r\n ngbDropdownToggle\r\n aria-label=\"Filter\">\r\n <svg width=\"19\" height=\"17\" viewBox=\"0 0 19 17\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M17.5026 0.835938H0.835938L7.5026 8.71927V14.1693L10.8359 15.8359V8.71927L17.5026 0.835938Z\" stroke=\"#344054\" stroke-width=\"1.67\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n <span *ngIf=\"hasActiveFilters()\" class=\"filter-badge\">{{ selectedStatusFilters.size }}</span>\r\n </button>\r\n <div class=\"dropdown-menu filter-dropdown\" ngbDropdownMenu aria-labelledby=\"filterDropdown\">\r\n <div class=\"filter-dropdown-header\">\r\n <h6 class=\"filter-title\">Filter by Status</h6>\r\n <button \r\n *ngIf=\"hasActiveFilters()\" \r\n class=\"clear-filters-btn\" \r\n (click)=\"clearFilters()\">\r\n Clear\r\n </button>\r\n </div>\r\n <div class=\"filter-dropdown-body\">\r\n <div \r\n *ngFor=\"let option of statusOptions\" \r\n class=\"filter-option\">\r\n <input \r\n class=\"form-check-input\" \r\n type=\"checkbox\" \r\n [id]=\"'statusFilter' + option.value\"\r\n [checked]=\"isStatusFilterSelected(option.value)\"\r\n (change)=\"onStatusFilterChange(option.value, $event)\">\r\n <label \r\n [for]=\"'statusFilter' + option.value\" \r\n class=\"filter-option-label\">\r\n {{ option.label }}\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Store List Container (Scrollable) -->\r\n <div class=\"list-container\">\r\n <!-- Store List -->\r\n <div class=\"store-list\">\r\n <div \r\n *ngFor=\"let store of paginatedStores; let i = index\" \r\n class=\"store-item\"\r\n [class.selected]=\"selectedStore?.storeName === store.storeName\"\r\n (click)=\"onStoreSelect(store)\">\r\n <div class=\"store-item-content\" [class.disabled-content]=\"hasNoMatch(store)\">\r\n <input \r\n class=\"form-check-input\" \r\n type=\"checkbox\" \r\n [id]=\"'store' + i\"\r\n [checked]=\"store.isApproved === true\"\r\n [disabled]=\"hasNoMatch(store)\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"onStoreCheckboxChange(store, $any($event.target).checked)\">\r\n <label \r\n class=\"store-item-text\" \r\n [for]=\"'store' + i\"\r\n [class.disabled]=\"hasNoMatch(store)\"\r\n (click)=\"hasNoMatch(store) && $event.stopPropagation()\">\r\n {{ store.storeName }}\r\n </label>\r\n </div>\r\n <span *ngIf=\"hasNoMatch(store)\" class=\"badge-error\">Didn't match</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Side: Canvas Area -->\r\n <div class=\"col-9 canvas-area-container\">\r\n <div class=\"canvas-wrapper\">\r\n <!-- Header Section with Store Slider and Approve Button -->\r\n <div class=\"canvas-header\" *ngIf=\"selectedStore && !canvasLoading\">\r\n <!-- Store Slider Navigation -->\r\n <div class=\"store-slider\">\r\n <div (click)=\"previousNext('previous')\" class=\"arrow\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"23\" height=\"24\" viewBox=\"0 0 23 24\" fill=\"none\">\r\n <path\r\n d=\"M14.3942 6.33329L8.72756 12L14.3942 17.6666\"\r\n stroke=\"#344054\"\r\n stroke-width=\"1.88889\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n <div\r\n class=\"storename\"\r\n [routerLink]=\"['/manage/stores/plano']\"\r\n [queryParams]=\"{ storeId: selectedStore.storeId }\"\r\n >\r\n <span class=\"txt me-3\">{{ selectedStore.storeName }} - Plano</span>\r\n <svg\r\n style=\"cursor: pointer\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"24\"\r\n height=\"24\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n >\r\n <path\r\n d=\"M17.6261 12.9688V18.7819C17.6261 19.2958 17.422 19.7886 17.0586 20.152C16.6952 20.5154 16.2023 20.7195 15.6884 20.7195H5.03119C4.51728 20.7195 4.02443 20.5154 3.66104 20.152C3.29765 19.7886 3.09351 19.2958 3.09351 18.7819V8.1246C3.09351 7.6107 3.29765 7.11784 3.66104 6.75445C4.02443 6.39107 4.51728 6.18692 5.03119 6.18692H10.8442M14.7196 3.2804H20.5326M20.5326 3.2804V9.09344M20.5326 3.2804L9.87539 13.9376\"\r\n stroke=\"#008EDF\"\r\n stroke-width=\"1.93768\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n <div (click)=\"previousNext('next')\" class=\"arrow\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"23\" height=\"24\" viewBox=\"0 0 23 24\" fill=\"none\">\r\n <path\r\n d=\"M8.6059 17.6667L14.2726 12L8.6059 6.33337\"\r\n stroke=\"#344054\"\r\n stroke-width=\"1.88889\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n </div>\r\n <!-- Approve And Complete Button -->\r\n <button class=\"approve-complete-btn\" (click)=\"onApproveAndComplete()\" [disabled]=\"approveLoading || isApproved()\">\r\n {{ approveLoading ? 'Processing...' : (isApproved() ? 'Approved' : 'Approve & Complete') }}\r\n </button>\r\n </div>\r\n\r\n <!-- Canvas Container -->\r\n <div class=\"canvas-container\" #previewCanvasContainer *ngIf=\"selectedStore\">\r\n <!-- Loading State - Centered on Canvas -->\r\n <div class=\"canvas-loading\" *ngIf=\"canvasLoading\">\r\n <div class=\"spinner-border text-primary\" role=\"status\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n <canvas #previewCanvas></canvas>\r\n </div>\r\n\r\n <!-- Empty State -->\r\n <div class=\"empty-state\" *ngIf=\"!selectedStore\">\r\n <p>Select a store to view its planogram</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Pagination -->\r\n <lib-pagination\r\n *ngIf=\"filteredStores.length > 0\"\r\n [itemsPerPage]=\"limit\"\r\n [currentPage]=\"offset\"\r\n [totalItems]=\"totalItems\"\r\n [paginationSizes]=\"paginationSizes\"\r\n [pageSize]=\"paginationSize()\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (pageSizeChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".review-replace-container{height:calc(100vh - 200px);display:flex;flex-direction:column;background-color:#fff;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif}.review-replace-container .row{height:100%;margin:0}.sidebar-container{border-right:1px solid #d0d5dd;height:100%;overflow:hidden;display:flex;flex-direction:column;background:#fff}.sidebar-content{display:flex;flex-direction:column;height:100%;padding:16px}.header-section{display:flex;gap:8px;align-items:flex-start;margin-bottom:8px}.all-stores-box{flex:1;background:#fff;border-radius:6px;padding:8px 16px}.all-stores-text{font-weight:600;font-size:16px;line-height:24px;color:#344054;margin:0}.download-btn{background:#fff;border:1px solid #d0d5dd;border-radius:8px;padding:12px;cursor:pointer;box-shadow:0 1px 2px #1018280d;transition:all .2s;display:flex;align-items:center;justify-content:center}.download-btn:hover{background:#f9fafb}.select-all-section{background:#fff;border-radius:6px;border-bottom:1px solid #eaecf0;padding:8px 16px;margin-bottom:12px;flex-shrink:0}.select-all-label{font-size:16px;line-height:24px;color:#344054;margin-left:12px;cursor:pointer;margin-bottom:0}.search-filter-section{display:flex;gap:12px;margin-bottom:16px;flex-shrink:0}.search-input-wrapper{flex:1;position:relative}.search-input{width:100%;background:#fff;border:1px solid #d0d5dd;border-radius:8px;padding:10px 14px 10px 42px;font-size:16px;line-height:24px;color:#344054;box-shadow:0 1px 2px #1018280d}.search-input::placeholder{color:#667085}.search-input:focus{outline:none;border-color:#00a3ff}.search-icon{position:absolute;left:14px;top:50%;transform:translateY(-50%);width:20px;height:20px;pointer-events:none}.dropdown{position:relative}.filter-btn{background:#fff;border:1px solid #d0d5dd;border-radius:8px;padding:12px;cursor:pointer;box-shadow:0 1px 2px #1018280d;transition:all .2s;display:flex;align-items:center;justify-content:center;position:relative}.filter-btn:hover{background:#f9fafb}.filter-btn.active{border-color:#00a3ff;background:#eaf8ff}.filter-badge{position:absolute;top:-4px;right:-4px;background:#00a3ff;color:#fff;border-radius:10px;min-width:18px;height:18px;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;padding:0 4px}.filter-dropdown{min-width:220px;padding:0;border-radius:8px;box-shadow:0 4px 6px -2px #10182808,0 12px 16px -4px #10182814;border:1px solid #d0d5dd;margin-top:8px}.filter-dropdown-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid #eaecf0}.filter-title{font-size:14px;font-weight:600;color:#1d2939;margin:0}.clear-filters-btn{background:none;border:none;color:#00a3ff;font-size:14px;font-weight:500;cursor:pointer;padding:0;transition:color .2s}.clear-filters-btn:hover{color:#0090e6;text-decoration:underline}.filter-dropdown-body{padding:8px}.filter-option{display:flex;align-items:center;gap:12px;padding:8px 12px;border-radius:6px;cursor:pointer;transition:background-color .2s}.filter-option:hover{background-color:#f9fafb}.filter-option-label{font-size:14px;font-weight:400;color:#344054;cursor:pointer;margin:0;flex:1}.list-container{flex:1;overflow-y:auto;overflow-x:hidden;min-height:0;padding-bottom:45px}.store-list{display:flex;flex-direction:column;gap:16px}.store-item{background:#fff;border-radius:6px;padding:8px 12px;display:flex;align-items:center;justify-content:space-between;min-height:42px;cursor:pointer;transition:all .2s}.store-item:hover{background:#f9fafb}.store-item.selected{background:#eaf8ff}.store-item-content{display:flex;align-items:center;gap:12px;min-width:120px;flex:1}.store-item-content.disabled-content{opacity:.6}.store-item-text{font-size:16px;line-height:24px;color:#1d2939;margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer}.store-item-text.disabled{color:#98a2b3;cursor:not-allowed;pointer-events:none}.store-item.selected .store-item-text{color:#009bf3}.badge-error{background:#fef3f2;color:#b42318;font-size:12px;line-height:18px;font-weight:500;padding:2px 8px;border-radius:16px;white-space:nowrap}.form-check-input{width:16px;height:16px;border:1px solid #d0d5dd;border-radius:4px;cursor:pointer;margin-top:0;flex-shrink:0}.form-check-input:checked{background-color:#00a3ff;border-color:#00a3ff}.form-check-input:focus{box-shadow:0 0 0 .2rem #00a3ff40}.canvas-area-container{height:100%;display:flex;flex-direction:column;background:#f9fafb;overflow:hidden}.canvas-wrapper{display:flex;flex-direction:column;overflow:hidden;flex:1;min-height:0}.canvas-header{display:flex;align-items:center;justify-content:space-between;padding:16px;background:#fff;gap:16px}.store-slider{display:flex;align-items:center;justify-content:center;flex:1}.store-slider .arrow{border-radius:17px;background:var(--Gray-100, #F2F4F7);width:34px;height:34px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background-color .2s}.store-slider .arrow:hover{background:#e5e7eb}.store-slider .storename{display:flex;align-items:center;margin-right:60px;margin-left:60px;cursor:pointer}.store-slider .storename .txt{color:#008edf;font-size:16px;font-weight:500;cursor:pointer}.approve-complete-btn{background:#00a3ff;color:#fff;border:none;border-radius:8px;padding:10px 20px;font-size:16px;font-weight:500;line-height:24px;cursor:pointer;box-shadow:0 1px 2px #1018280d;transition:all .2s;white-space:nowrap;flex-shrink:0}.approve-complete-btn:hover{background:#0090e6;box-shadow:0 2px 4px #1018281a}.approve-complete-btn:active{background:#007acc}.canvas-container{position:relative;flex:1;background:#f9fafb;overflow:hidden;min-height:0;padding:0;height:100%}.canvas-container canvas{background:#fff;width:100%!important;height:100%!important;display:block}.canvas-loading{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10}.empty-state{display:flex;align-items:center;justify-content:center;height:100%;color:#667085;font-size:16px}lib-pagination{flex-shrink:0;background:#f9fafb}::ng-deep .fixture-before-after-offcanvas{width:500px!important;max-width:90vw}::ng-deep .fixture-before-after-offcanvas-wide{width:1000px!important;max-width:90vw}::ng-deep .offcanvas-backdrop{background-color:#00000080}::ng-deep .approve-complete-modal .modal-dialog{max-width:650px}::ng-deep .approve-complete-modal .modal-content{border:none;border-radius:12px;box-shadow:0 20px 24px -4px #10182814,0 8px 8px -4px #10182808;padding:0}::ng-deep .approve-complete-modal .modal-header{border-bottom:none;padding:24px 16px 0}::ng-deep .approve-complete-modal .modal-body{padding:0 16px}::ng-deep .approve-complete-modal .modal-footer{border-top:none;padding:0 16px 24px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i4.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i7.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i7.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i7.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i6.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "ngmodule", type: CommonSharedModule }, { kind: "component", type: i8.PaginationComponent, selector: "lib-pagination", inputs: ["collection", "itemsPerPage", "currentPage", "totalItems", "directionLinks", "pageSize", "paginationSizes"], outputs: ["pageChange", "pageSizeChange"] }, { kind: "ngmodule", type: NgbDropdownModule }, { kind: "directive", type: i5.NgbDropdown, selector: "[ngbDropdown]", inputs: ["autoClose", "dropdownClass", "open", "placement", "popperOptions", "container", "display"], outputs: ["openChange"], exportAs: ["ngbDropdown"] }, { kind: "directive", type: i5.NgbDropdownToggle, selector: "[ngbDropdownToggle]" }, { kind: "directive", type: i5.NgbDropdownMenu, selector: "[ngbDropdownMenu]" }] });
2028
+ }
2029
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ReviewReplaceComponent, decorators: [{
2030
+ type: Component,
2031
+ args: [{ selector: 'lib-review-replace', standalone: true, imports: [CommonModule, FormsModule, RouterModule, CommonSharedModule, NgbDropdownModule], providers: [TitleCasePipe], template: "<div class=\"review-replace-container\">\r\n <div class=\"row g-0 h-100\">\r\n <!-- Left Sidebar: Store List -->\r\n <div class=\"col-3 sidebar-container\">\r\n <div class=\"sidebar-content\">\r\n <!-- Header Section -->\r\n <div class=\"header-section\">\r\n <div class=\"all-stores-box\">\r\n <p class=\"all-stores-text\">All stores</p>\r\n </div>\r\n <button class=\"download-btn\" (click)=\"onDownload()\" aria-label=\"Download\">\r\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 20 20\" fill=\"none\">\r\n <path d=\"M17.5 12.5V13.5C17.5 14.9001 17.5 15.6002 17.2275 16.135C16.9878 16.6054 16.6054 16.9878 16.135 17.2275C15.6002 17.5 14.9001 17.5 13.5 17.5H6.5C5.09987 17.5 4.3998 17.5 3.86502 17.2275C3.39462 16.9878 3.01217 16.6054 2.77248 16.135C2.5 15.6002 2.5 14.9001 2.5 13.5V12.5M14.1667 8.33333L10 12.5M10 12.5L5.83333 8.33333M10 12.5V2.5\" stroke=\"#344054\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n </button>\r\n </div>\r\n\r\n <!-- Select All Section -->\r\n <div class=\"select-all-section\">\r\n <div class=\"form-check\">\r\n <input \r\n class=\"form-check-input\" \r\n type=\"checkbox\" \r\n id=\"selectAll\"\r\n [checked]=\"isAllSelected()\"\r\n (change)=\"onSelectAll($any($event.target).checked)\">\r\n <label class=\"form-check-label select-all-label\" for=\"selectAll\">\r\n Select all ({{ filteredStores.length }})\r\n </label>\r\n </div>\r\n </div>\r\n\r\n <!-- Search and Filter Section -->\r\n <div class=\"search-filter-section\">\r\n <div class=\"search-input-wrapper\">\r\n <svg class=\"search-icon\" viewBox=\"0 0 20 20\" fill=\"none\">\r\n <path d=\"M17.5 17.5L13.875 13.875M15.8333 9.16667C15.8333 12.8486 12.8486 15.8333 9.16667 15.8333C5.48477 15.8333 2.5 12.8486 2.5 9.16667C2.5 5.48477 5.48477 2.5 9.16667 2.5C12.8486 2.5 15.8333 5.48477 15.8333 9.16667Z\" stroke=\"#667085\" stroke-width=\"1.66667\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n <input \r\n type=\"text\" \r\n class=\"search-input\" \r\n placeholder=\"Search\"\r\n [(ngModel)]=\"searchTerm\"\r\n (input)=\"onSearch()\">\r\n </div>\r\n <div class=\"dropdown\" ngbDropdown>\r\n <button \r\n class=\"filter-btn\" \r\n [class.active]=\"hasActiveFilters()\"\r\n id=\"filterDropdown\" \r\n ngbDropdownToggle\r\n aria-label=\"Filter\">\r\n <svg width=\"19\" height=\"17\" viewBox=\"0 0 19 17\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M17.5026 0.835938H0.835938L7.5026 8.71927V14.1693L10.8359 15.8359V8.71927L17.5026 0.835938Z\" stroke=\"#344054\" stroke-width=\"1.67\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\r\n </svg>\r\n <span *ngIf=\"hasActiveFilters()\" class=\"filter-badge\">{{ selectedStatusFilters.size }}</span>\r\n </button>\r\n <div class=\"dropdown-menu filter-dropdown\" ngbDropdownMenu aria-labelledby=\"filterDropdown\">\r\n <div class=\"filter-dropdown-header\">\r\n <h6 class=\"filter-title\">Filter by Status</h6>\r\n <button \r\n *ngIf=\"hasActiveFilters()\" \r\n class=\"clear-filters-btn\" \r\n (click)=\"clearFilters()\">\r\n Clear\r\n </button>\r\n </div>\r\n <div class=\"filter-dropdown-body\">\r\n <div \r\n *ngFor=\"let option of statusOptions\" \r\n class=\"filter-option\">\r\n <input \r\n class=\"form-check-input\" \r\n type=\"checkbox\" \r\n [id]=\"'statusFilter' + option.value\"\r\n [checked]=\"isStatusFilterSelected(option.value)\"\r\n (change)=\"onStatusFilterChange(option.value, $event)\">\r\n <label \r\n [for]=\"'statusFilter' + option.value\" \r\n class=\"filter-option-label\">\r\n {{ option.label }}\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Store List Container (Scrollable) -->\r\n <div class=\"list-container\">\r\n <!-- Store List -->\r\n <div class=\"store-list\">\r\n <div \r\n *ngFor=\"let store of paginatedStores; let i = index\" \r\n class=\"store-item\"\r\n [class.selected]=\"selectedStore?.storeName === store.storeName\"\r\n (click)=\"onStoreSelect(store)\">\r\n <div class=\"store-item-content\" [class.disabled-content]=\"hasNoMatch(store)\">\r\n <input \r\n class=\"form-check-input\" \r\n type=\"checkbox\" \r\n [id]=\"'store' + i\"\r\n [checked]=\"store.isApproved === true\"\r\n [disabled]=\"hasNoMatch(store)\"\r\n (click)=\"$event.stopPropagation()\"\r\n (change)=\"onStoreCheckboxChange(store, $any($event.target).checked)\">\r\n <label \r\n class=\"store-item-text\" \r\n [for]=\"'store' + i\"\r\n [class.disabled]=\"hasNoMatch(store)\"\r\n (click)=\"hasNoMatch(store) && $event.stopPropagation()\">\r\n {{ store.storeName }}\r\n </label>\r\n </div>\r\n <span *ngIf=\"hasNoMatch(store)\" class=\"badge-error\">Didn't match</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Right Side: Canvas Area -->\r\n <div class=\"col-9 canvas-area-container\">\r\n <div class=\"canvas-wrapper\">\r\n <!-- Header Section with Store Slider and Approve Button -->\r\n <div class=\"canvas-header\" *ngIf=\"selectedStore && !canvasLoading\">\r\n <!-- Store Slider Navigation -->\r\n <div class=\"store-slider\">\r\n <div (click)=\"previousNext('previous')\" class=\"arrow\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"23\" height=\"24\" viewBox=\"0 0 23 24\" fill=\"none\">\r\n <path\r\n d=\"M14.3942 6.33329L8.72756 12L14.3942 17.6666\"\r\n stroke=\"#344054\"\r\n stroke-width=\"1.88889\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n <div\r\n class=\"storename\"\r\n [routerLink]=\"['/manage/stores/plano']\"\r\n [queryParams]=\"{ storeId: selectedStore.storeId }\"\r\n >\r\n <span class=\"txt me-3\">{{ selectedStore.storeName }} - Plano</span>\r\n <svg\r\n style=\"cursor: pointer\"\r\n xmlns=\"http://www.w3.org/2000/svg\"\r\n width=\"24\"\r\n height=\"24\"\r\n viewBox=\"0 0 24 24\"\r\n fill=\"none\"\r\n >\r\n <path\r\n d=\"M17.6261 12.9688V18.7819C17.6261 19.2958 17.422 19.7886 17.0586 20.152C16.6952 20.5154 16.2023 20.7195 15.6884 20.7195H5.03119C4.51728 20.7195 4.02443 20.5154 3.66104 20.152C3.29765 19.7886 3.09351 19.2958 3.09351 18.7819V8.1246C3.09351 7.6107 3.29765 7.11784 3.66104 6.75445C4.02443 6.39107 4.51728 6.18692 5.03119 6.18692H10.8442M14.7196 3.2804H20.5326M20.5326 3.2804V9.09344M20.5326 3.2804L9.87539 13.9376\"\r\n stroke=\"#008EDF\"\r\n stroke-width=\"1.93768\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n <div (click)=\"previousNext('next')\" class=\"arrow\">\r\n <svg xmlns=\"http://www.w3.org/2000/svg\" width=\"23\" height=\"24\" viewBox=\"0 0 23 24\" fill=\"none\">\r\n <path\r\n d=\"M8.6059 17.6667L14.2726 12L8.6059 6.33337\"\r\n stroke=\"#344054\"\r\n stroke-width=\"1.88889\"\r\n stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\"\r\n />\r\n </svg>\r\n </div>\r\n </div>\r\n <!-- Approve And Complete Button -->\r\n <button class=\"approve-complete-btn\" (click)=\"onApproveAndComplete()\" [disabled]=\"approveLoading || isApproved()\">\r\n {{ approveLoading ? 'Processing...' : (isApproved() ? 'Approved' : 'Approve & Complete') }}\r\n </button>\r\n </div>\r\n\r\n <!-- Canvas Container -->\r\n <div class=\"canvas-container\" #previewCanvasContainer *ngIf=\"selectedStore\">\r\n <!-- Loading State - Centered on Canvas -->\r\n <div class=\"canvas-loading\" *ngIf=\"canvasLoading\">\r\n <div class=\"spinner-border text-primary\" role=\"status\">\r\n <span class=\"visually-hidden\">Loading...</span>\r\n </div>\r\n </div>\r\n <canvas #previewCanvas></canvas>\r\n </div>\r\n\r\n <!-- Empty State -->\r\n <div class=\"empty-state\" *ngIf=\"!selectedStore\">\r\n <p>Select a store to view its planogram</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Pagination -->\r\n <lib-pagination\r\n *ngIf=\"filteredStores.length > 0\"\r\n [itemsPerPage]=\"limit\"\r\n [currentPage]=\"offset\"\r\n [totalItems]=\"totalItems\"\r\n [paginationSizes]=\"paginationSizes\"\r\n [pageSize]=\"paginationSize()\"\r\n (pageChange)=\"onPageChange($event)\"\r\n (pageSizeChange)=\"onPageSizeChange($event)\">\r\n </lib-pagination>\r\n </div>\r\n </div>\r\n</div>\r\n", styles: [".review-replace-container{height:calc(100vh - 200px);display:flex;flex-direction:column;background-color:#fff;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif}.review-replace-container .row{height:100%;margin:0}.sidebar-container{border-right:1px solid #d0d5dd;height:100%;overflow:hidden;display:flex;flex-direction:column;background:#fff}.sidebar-content{display:flex;flex-direction:column;height:100%;padding:16px}.header-section{display:flex;gap:8px;align-items:flex-start;margin-bottom:8px}.all-stores-box{flex:1;background:#fff;border-radius:6px;padding:8px 16px}.all-stores-text{font-weight:600;font-size:16px;line-height:24px;color:#344054;margin:0}.download-btn{background:#fff;border:1px solid #d0d5dd;border-radius:8px;padding:12px;cursor:pointer;box-shadow:0 1px 2px #1018280d;transition:all .2s;display:flex;align-items:center;justify-content:center}.download-btn:hover{background:#f9fafb}.select-all-section{background:#fff;border-radius:6px;border-bottom:1px solid #eaecf0;padding:8px 16px;margin-bottom:12px;flex-shrink:0}.select-all-label{font-size:16px;line-height:24px;color:#344054;margin-left:12px;cursor:pointer;margin-bottom:0}.search-filter-section{display:flex;gap:12px;margin-bottom:16px;flex-shrink:0}.search-input-wrapper{flex:1;position:relative}.search-input{width:100%;background:#fff;border:1px solid #d0d5dd;border-radius:8px;padding:10px 14px 10px 42px;font-size:16px;line-height:24px;color:#344054;box-shadow:0 1px 2px #1018280d}.search-input::placeholder{color:#667085}.search-input:focus{outline:none;border-color:#00a3ff}.search-icon{position:absolute;left:14px;top:50%;transform:translateY(-50%);width:20px;height:20px;pointer-events:none}.dropdown{position:relative}.filter-btn{background:#fff;border:1px solid #d0d5dd;border-radius:8px;padding:12px;cursor:pointer;box-shadow:0 1px 2px #1018280d;transition:all .2s;display:flex;align-items:center;justify-content:center;position:relative}.filter-btn:hover{background:#f9fafb}.filter-btn.active{border-color:#00a3ff;background:#eaf8ff}.filter-badge{position:absolute;top:-4px;right:-4px;background:#00a3ff;color:#fff;border-radius:10px;min-width:18px;height:18px;display:flex;align-items:center;justify-content:center;font-size:11px;font-weight:600;padding:0 4px}.filter-dropdown{min-width:220px;padding:0;border-radius:8px;box-shadow:0 4px 6px -2px #10182808,0 12px 16px -4px #10182814;border:1px solid #d0d5dd;margin-top:8px}.filter-dropdown-header{display:flex;justify-content:space-between;align-items:center;padding:12px 16px;border-bottom:1px solid #eaecf0}.filter-title{font-size:14px;font-weight:600;color:#1d2939;margin:0}.clear-filters-btn{background:none;border:none;color:#00a3ff;font-size:14px;font-weight:500;cursor:pointer;padding:0;transition:color .2s}.clear-filters-btn:hover{color:#0090e6;text-decoration:underline}.filter-dropdown-body{padding:8px}.filter-option{display:flex;align-items:center;gap:12px;padding:8px 12px;border-radius:6px;cursor:pointer;transition:background-color .2s}.filter-option:hover{background-color:#f9fafb}.filter-option-label{font-size:14px;font-weight:400;color:#344054;cursor:pointer;margin:0;flex:1}.list-container{flex:1;overflow-y:auto;overflow-x:hidden;min-height:0;padding-bottom:45px}.store-list{display:flex;flex-direction:column;gap:16px}.store-item{background:#fff;border-radius:6px;padding:8px 12px;display:flex;align-items:center;justify-content:space-between;min-height:42px;cursor:pointer;transition:all .2s}.store-item:hover{background:#f9fafb}.store-item.selected{background:#eaf8ff}.store-item-content{display:flex;align-items:center;gap:12px;min-width:120px;flex:1}.store-item-content.disabled-content{opacity:.6}.store-item-text{font-size:16px;line-height:24px;color:#1d2939;margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;cursor:pointer}.store-item-text.disabled{color:#98a2b3;cursor:not-allowed;pointer-events:none}.store-item.selected .store-item-text{color:#009bf3}.badge-error{background:#fef3f2;color:#b42318;font-size:12px;line-height:18px;font-weight:500;padding:2px 8px;border-radius:16px;white-space:nowrap}.form-check-input{width:16px;height:16px;border:1px solid #d0d5dd;border-radius:4px;cursor:pointer;margin-top:0;flex-shrink:0}.form-check-input:checked{background-color:#00a3ff;border-color:#00a3ff}.form-check-input:focus{box-shadow:0 0 0 .2rem #00a3ff40}.canvas-area-container{height:100%;display:flex;flex-direction:column;background:#f9fafb;overflow:hidden}.canvas-wrapper{display:flex;flex-direction:column;overflow:hidden;flex:1;min-height:0}.canvas-header{display:flex;align-items:center;justify-content:space-between;padding:16px;background:#fff;gap:16px}.store-slider{display:flex;align-items:center;justify-content:center;flex:1}.store-slider .arrow{border-radius:17px;background:var(--Gray-100, #F2F4F7);width:34px;height:34px;display:flex;align-items:center;justify-content:center;cursor:pointer;transition:background-color .2s}.store-slider .arrow:hover{background:#e5e7eb}.store-slider .storename{display:flex;align-items:center;margin-right:60px;margin-left:60px;cursor:pointer}.store-slider .storename .txt{color:#008edf;font-size:16px;font-weight:500;cursor:pointer}.approve-complete-btn{background:#00a3ff;color:#fff;border:none;border-radius:8px;padding:10px 20px;font-size:16px;font-weight:500;line-height:24px;cursor:pointer;box-shadow:0 1px 2px #1018280d;transition:all .2s;white-space:nowrap;flex-shrink:0}.approve-complete-btn:hover{background:#0090e6;box-shadow:0 2px 4px #1018281a}.approve-complete-btn:active{background:#007acc}.canvas-container{position:relative;flex:1;background:#f9fafb;overflow:hidden;min-height:0;padding:0;height:100%}.canvas-container canvas{background:#fff;width:100%!important;height:100%!important;display:block}.canvas-loading{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10}.empty-state{display:flex;align-items:center;justify-content:center;height:100%;color:#667085;font-size:16px}lib-pagination{flex-shrink:0;background:#f9fafb}::ng-deep .fixture-before-after-offcanvas{width:500px!important;max-width:90vw}::ng-deep .fixture-before-after-offcanvas-wide{width:1000px!important;max-width:90vw}::ng-deep .offcanvas-backdrop{background-color:#00000080}::ng-deep .approve-complete-modal .modal-dialog{max-width:650px}::ng-deep .approve-complete-modal .modal-content{border:none;border-radius:12px;box-shadow:0 20px 24px -4px #10182814,0 8px 8px -4px #10182808;padding:0}::ng-deep .approve-complete-modal .modal-header{border-bottom:none;padding:24px 16px 0}::ng-deep .approve-complete-modal .modal-body{padding:0 16px}::ng-deep .approve-complete-modal .modal-footer{border-top:none;padding:0 16px 24px}\n"] }]
2032
+ }], ctorParameters: () => [{ type: i1.CollectionUpdateAiDataService }, { type: i2.StoreBuilderService }, { type: i0.ChangeDetectorRef }, { type: i3.GlobalStateService }, { type: i4.TitleCasePipe }, { type: i5.NgbOffcanvas }, { type: i5.NgbModal }, { type: i6.Router }], propDecorators: { previewCanvasRef: [{
2033
+ type: ViewChild,
2034
+ args: ['previewCanvas']
2035
+ }], previewCanvasContainerRef: [{
2036
+ type: ViewChild,
2037
+ args: ['previewCanvasContainer']
2038
+ }] } });
2039
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmV2aWV3LXJlcGxhY2UuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tc3RvcmUtYnVpbGRlci9zcmMvbGliL2NvbXBvbmVudHMvY29sbGVjdGlvbi11cGRhdGUtYWkvZmluZC1yZXBsYWNlLWxheW91dC9yZXZpZXctcmVwbGFjZS9yZXZpZXctcmVwbGFjZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90YW5nby1zdG9yZS1idWlsZGVyL3NyYy9saWIvY29tcG9uZW50cy9jb2xsZWN0aW9uLXVwZGF0ZS1haS9maW5kLXJlcGxhY2UtbGF5b3V0L3Jldmlldy1yZXBsYWNlL3Jldmlldy1yZXBsYWNlLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQW9DLFNBQVMsRUFBaUMsTUFBTSxlQUFlLENBQUM7QUFDdEgsT0FBTyxFQUFFLFlBQVksRUFBRSxhQUFhLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUM5RCxPQUFPLEVBQUUsV0FBVyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBVSxNQUFNLGlCQUFpQixDQUFDO0FBSXZELE9BQU8sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQzFDLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDO0FBRWpDLE9BQU8sRUFBRSxrQkFBa0IsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3pELE9BQU8sRUFBMEIsaUJBQWlCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN2RixPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSx1REFBdUQsQ0FBQztBQUNwRyxPQUFPLEVBQUUsNkJBQTZCLEVBQUUsTUFBTSwyREFBMkQsQ0FBQzs7Ozs7Ozs7OztBQVUxRyxNQUFNLE9B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QVksRUFBRSxrQkFBa0IsRUFBRSxpQkFBaUIsQ0FBQyxhQUc5RSxDQUFDLGFBQWEsQ0FBQzt3U0FrQkUsZ0JBQWdCO3NCQUEzQyxTQUFTO3VCQUFDLGVBQWU7Z0JBQ1cseUJBQXlCO3NCQUE3RCxTQUFTO3VCQUFDLHdCQUF3QiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgT25Jbml0LCBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQsIFZpZXdDaGlsZCwgRWxlbWVudFJlZiwgQ2hhbmdlRGV0ZWN0b3JSZWYgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgQ29tbW9uTW9kdWxlLCBUaXRsZUNhc2VQaXBlIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcclxuaW1wb3J0IHsgRm9ybXNNb2R1bGUgfSBmcm9tICdAYW5ndWxhci9mb3Jtcyc7XHJcbmltcG9ydCB7IFJvdXRlck1vZHVsZSwgUm91dGVyIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcclxuaW1wb3J0IHsgQ29sbGVjdGlvblVwZGF0ZUFpRGF0YVNlcnZpY2UgfSBmcm9tICcuLi8uLi9zZXJ2aWNlcy9kYXRhLnNlcnZpY2UnO1xyXG5pbXBvcnQgeyBTdG9yZSwgRmluZFJlcGxhY2UgfSBmcm9tICcuLi8uLi9tb2RlbHMvZmluZC1yZXBsYWNlLm1vZGVsJztcclxuaW1wb3J0IHsgU3RvcmVCdWlsZGVyU2VydmljZSB9IGZyb20gJy4uLy4uLy4uLy4uL3NlcnZpY2VzL3N0b3JlLWJ1aWxkZXIuc2VydmljZSc7XHJcbmltcG9ydCB7IFN1YmplY3QsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgKiBhcyBmYWJyaWMgZnJvbSBcImZhYnJpY1wiO1xyXG5pbXBvcnQgeyBHbG9iYWxTdGF0ZVNlcnZpY2UgfSBmcm9tICd0YW5nby1hcHAtdWktZ2xvYmFsJztcclxuaW1wb3J0IHsgQ29tbW9uU2hhcmVkTW9kdWxlIH0gZnJvbSAndGFuZ28tYXBwLXVpLXNoYXJlZCc7XHJcbmltcG9ydCB7IE5nYk9mZmNhbnZhcywgTmdiTW9kYWwsIE5nYkRyb3Bkb3duTW9kdWxlIH0gZnJvbSAnQG5nLWJvb3RzdHJhcC9uZy1ib290c3RyYXAnO1xyXG5pbXBvcnQgeyBGaXh0dXJlQmVmb3JlQWZ0ZXJDb21wb25lbnQgfSBmcm9tICcuL2ZpeHR1cmUtYmVmb3JlLWFmdGVyL2ZpeHR1cmUtYmVmb3JlLWFmdGVyLmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IEFwcHJvdmVDb21wbGV0ZU1vZGFsQ29tcG9uZW50IH0gZnJvbSAnLi9hcHByb3ZlLWNvbXBsZXRlLW1vZGFsL2FwcHJvdmUtY29tcGxldGUtbW9kYWwuY29tcG9uZW50JztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbGliLXJldmlldy1yZXBsYWNlJyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGUsIEZvcm1zTW9kdWxlLCBSb3V0ZXJNb2R1bGUsIENvbW1vblNoYXJlZE1vZHVsZSwgTmdiRHJvcGRvd25Nb2R1bGVdLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9yZXZpZXctcmVwbGFjZS5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmw6ICcuL3Jldmlldy1yZXBsYWNlLmNvbXBvbmVudC5zY3NzJyxcclxuICBwcm92aWRlcnM6IFtUaXRsZUNhc2VQaXBlXVxyXG59KVxyXG5leHBvcnQgY2xhc3MgUmV2aWV3UmVwbGFjZUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95LCBBZnRlclZpZXdJbml0IHtcclxuICBmaW5kUmVwbGFjZURhdGE6IEZpbmRSZXBsYWNlIHwgbnVsbCA9IG51bGw7XHJcbiAgc3RvcmVzOiBTdG9yZVtdID0gW107XHJcbiAgZmlsdGVyZWRTdG9yZXM6IFN0b3JlW10gPSBbXTtcclxuICBzZWxlY3RlZFN0b3JlczogU2V0PHN0cmluZz4gPSBuZXcgU2V0KCk7XHJcbiAgc2VhcmNoVGVybTogc3RyaW5nID0gJyc7XHJcbiAgc2VsZWN0ZWRTdG9yZTogU3RvcmUgfCBudWxsID0gbnVsbDtcclxuXHJcbiAgLy8gRmlsdGVyIHByb3BlcnRpZXNcclxuICBzZWxlY3RlZFN0YXR1c0ZpbHRlcnM6IFNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xyXG4gIHN0YXR1c09wdGlvbnMgPSBbXHJcbiAgICB7IHZhbHVlOiAnbWF0Y2gnLCBsYWJlbDogJ01hdGNoJyB9LFxyXG4gICAgeyB2YWx1ZTogJ25vLW1hdGNoJywgbGFiZWw6ICdObyBNYXRjaCcgfVxyXG4gIF07XHJcblxyXG4gIC8vIENhbnZhcyBwcm9wZXJ0aWVzXHJcbiAgQFZpZXdDaGlsZCgncHJldmlld0NhbnZhcycpIHByZXZpZXdDYW52YXNSZWYhOiBFbGVtZW50UmVmPEhUTUxDYW52YXNFbGVtZW50PjtcclxuICBAVmlld0NoaWxkKCdwcmV2aWV3Q2FudmFzQ29udGFpbmVyJykgcHJldmlld0NhbnZhc0NvbnRhaW5lclJlZiE6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+O1xyXG4gIHByZXZpZXdDYW52YXMhOiBmYWJyaWMuQ2FudmFzO1xyXG4gIHBsYW5vRGF0YTogYW55O1xyXG4gIGZsb29yRGF0YTogYW55O1xyXG4gIGNhbnZhc0xvYWRpbmcgPSBmYWxzZTtcclxuICBhcHByb3ZlTG9hZGluZyA9IGZhbHNlO1xyXG4gIGNkblVybDogc3RyaW5nID0gJyc7XHJcbiAgd2FsbFRoaWNrbmVzcyA9IDMwO1xyXG4gIHZlcnRpY2FsTWFyZ2luID0gKDEuMjUgLyAxMDApICogdGhpcy50b1BpeGVscygxNTI0LCBcIm1tXCIpO1xyXG4gIGFsbEZpeHR1cmVJbnN0YW5jZXM6IGFueVtdID0gW107XHJcblxyXG4gIC8vIEZpeHR1cmUgc2VsZWN0aW9uIGFuZCBoaWdobGlnaHRpbmdcclxuICBzZWxlY3RlZEZpeHR1cmU6IGFueSA9IG51bGw7XHJcbiAgc2VsZWN0ZWRGaXh0dXJlRGF0YTogYW55ID0gbnVsbDtcclxuICBvcmlnaW5hbEZpeHR1cmVEYXRhOiBhbnkgPSBudWxsOyAvLyBPcmlnaW5hbCBmaXh0dXJlIGJlZm9yZSByZXBsYWNlIChmb3IgYmVmb3JlL2FmdGVyIGNvbXBhcmlzb24pXHJcbiAgcHJpdmF0ZSBvcmlnaW5hbEZpeHR1cmVzTWFwOiBNYXA8c3RyaW5nLCBhbnk+ID0gbmV3IE1hcCgpOyAvLyBTdG9yZSBvcmlnaW5hbCBmaXh0dXJlcyBieSBmaXh0dXJlSWRcclxuICBwcml2YXRlIGFjdGl2ZUhpZ2hsaWdodDogZmFicmljLlJlY3QgfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIGNhbmNlbEhpZ2hsaWdodEJsaW5rID0gZmFsc2U7XHJcblxyXG4gIHByaXZhdGUgZGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xyXG5cclxuICAvLyBQYWdpbmF0aW9uIHByb3BlcnRpZXNcclxuICBsaW1pdDogbnVtYmVyID0gMTA7XHJcbiAgb2Zmc2V0OiBudW1iZXIgPSAxO1xyXG4gIHRvdGFsSXRlbXM6IG51bWJlciA9IDA7XHJcbiAgcGFnaW5hdGlvblNpemVzID0gWzEwLCAyMCwgMzBdO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgZGF0YVNlcnZpY2U6IENvbGxlY3Rpb25VcGRhdGVBaURhdGFTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBzdG9yZUJ1aWxkZXJTZXJ2aWNlOiBTdG9yZUJ1aWxkZXJTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxyXG4gICAgcHJpdmF0ZSBnczogR2xvYmFsU3RhdGVTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSB0aXRsZUNhc2U6IFRpdGxlQ2FzZVBpcGUsXHJcbiAgICBwcml2YXRlIG9mZmNhbnZhc1NlcnZpY2U6IE5nYk9mZmNhbnZhcyxcclxuICAgIHByaXZhdGUgbW9kYWxTZXJ2aWNlOiBOZ2JNb2RhbCxcclxuICAgIHByaXZhdGUgcm91dGVyOiBSb3V0ZXJcclxuICApIHsgfVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIC8vIEdldCBDRE4gVVJMXHJcbiAgICB0aGlzLmdzLmVudmlyb25tZW50XHJcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcclxuICAgICAgLnN1YnNjcmliZSgoZW52KSA9PiB7XHJcbiAgICAgICAgdGhpcy5jZG5VcmwgPSBlbnYucGxhbm9ncmFtQ0ROIHx8ICcnO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAvLyBTdWJzY3JpYmUgdG8gZGF0YSBzZXJ2aWNlXHJcbiAgICB0aGlzLmRhdGFTZXJ2aWNlLmdldEZpbmRSZXBsYWNlRGF0YSgpXHJcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcclxuICAgICAgLnN1YnNjcmliZSgoZGF0YSkgPT4ge1xyXG4gICAgICAgIHRoaXMuZmluZFJlcGxhY2VEYXRhID0gZGF0YTtcclxuICAgICAgICBpZiAoZGF0YT8uc3RvcmVzKSB7XHJcbiAgICAgICAgICB0aGlzLnN0b3JlcyA9IGRhdGEuc3RvcmVzO1xyXG5cclxuICAgICAgICAgIC8vIFJlc3RvcmUgY2hlY2tib3ggc3RhdGUgZnJvbSBpc0FwcHJvdmVkIHByb3BlcnR5XHJcbiAgICAgICAgICB0aGlzLnNlbGVjdGVkU3RvcmVzLmNsZWFyKCk7XHJcbiAgICAgICAgICB0aGlzLnN0b3Jlcy5mb3JFYWNoKHN0b3JlID0+IHtcclxuICAgICAgICAgICAgaWYgKHN0b3JlLmlzQXBwcm92ZWQgJiYgIXRoaXMuaGFzTm9NYXRjaChzdG9yZSkpIHtcclxuICAgICAgICAgICAgICB0aGlzLnNlbGVjdGVkU3RvcmVzLmFkZChzdG9yZS5zdG9yZU5hbWUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICB0aGlzLmFwcGx5RmlsdGVycygpO1xyXG5cclxuICAgICAgICAgIC8vIFNlbGVjdCBmaXJzdCBzdG9yZSBieSBkZWZhdWx0IGlmIG5vbmUgc2VsZWN0ZWRcclxuICAgICAgICAgIGlmICghdGhpcy5zZWxlY3RlZFN0b3JlICYmIHRoaXMuZmlsdGVyZWRTdG9yZXMubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICB0aGlzLm9uU3RvcmVTZWxlY3QodGhpcy5maWx0ZXJlZFN0b3Jlc1swXSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcclxuICAgIC8vIENhbnZhcyB3aWxsIGJlIGluaXRpYWxpemVkIHdoZW4gc3RvcmUgaXMgc2VsZWN0ZWRcclxuICB9XHJcblxyXG4gIGluaXRpYWxpemVDYW52YXMoKTogYm9vbGVhbiB7XHJcbiAgICBpZiAodGhpcy5wcmV2aWV3Q2FudmFzKSB7XHJcbiAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh0aGlzLnByZXZpZXdDYW52YXNSZWY/Lm5hdGl2ZUVsZW1lbnQgJiYgdGhpcy5wcmV2aWV3Q2FudmFzQ29udGFpbmVyUmVmPy5uYXRpdmVFbGVtZW50KSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgY29uc3QgY29udGFpbmVyRWwgPSB0aGlzLnByZXZpZXdDYW52YXNDb250YWluZXJSZWYubmF0aXZlRWxlbWVudDtcclxuICAgICAgICB0aGlzLnByZXZpZXdDYW52YXMgPSBuZXcgZmFicmljLkNhbnZhcyh0aGlzLnByZXZpZXdDYW52YXNSZWYubmF0aXZlRWxlbWVudCwge1xyXG4gICAgICAgICAgc2VsZWN0aW9uRnVsbHlDb250YWluZWQ6IHRydWUsXHJcbiAgICAgICAgICBwZXJQaXhlbFRhcmdldEZpbmQ6IHRydWUsXHJcbiAgICAgICAgICB0YXJnZXRGaW5kVG9sZXJhbmNlOiA1LFxyXG4gICAgICAgICAgd2lkdGg6IGNvbnRhaW5lckVsLmNsaWVudFdpZHRoLFxyXG4gICAgICAgICAgaGVpZ2h0OiBjb250YWluZXJFbC5jbGllbnRIZWlnaHQsXHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgdGhpcy5zZXR1cFpvb21IYW5kbGVycyh0aGlzLnByZXZpZXdDYW52YXMpO1xyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGluaXRpYWxpemluZyBjYW52YXM6JywgZXJyb3IpO1xyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgcmV0dXJuIGZhbHNlO1xyXG4gIH1cclxuXHJcbiAgc2V0dXBab29tSGFuZGxlcnMoY2FudmFzOiBmYWJyaWMuQ2FudmFzKTogdm9pZCB7XHJcbiAgICBjYW52YXMuc2VsZWN0aW9uID0gZmFsc2U7XHJcblxyXG4gICAgY2FudmFzLm9uKFwibW91c2U6d2hlZWxcIiwgKG9wdDogZmFicmljLlRFdmVudDxXaGVlbEV2ZW50PikgPT4ge1xyXG4gICAgICBjb25zdCBlID0gb3B0LmU7XHJcbiAgICAgIGlmIChlLmN0cmxLZXkgfHwgZS5tZXRhS2V5KSB7XHJcbiAgICAgICAgY29uc3QgZGVsdGEgPSBlLmRlbHRhWTtcclxuICAgICAgICBsZXQgem9vbSA9IGNhbnZhcy5nZXRab29tKCk7XHJcbiAgICAgICAgem9vbSAqPSAwLjk5NSAqKiBkZWx0YTtcclxuICAgICAgICB6b29tID0gTWF0aC5tYXgoMC4yLCBNYXRoLm1pbih6b29tLCAzKSk7XHJcbiAgICAgICAgY2FudmFzLnpvb21Ub1BvaW50KHsgeDogZS5vZmZzZXRYLCB5OiBlLm9mZnNldFkgfSBhcyBmYWJyaWMuUG9pbnQsIHpvb20pO1xyXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBsZXQgaXNEcmFnZ2luZyA9IGZhbHNlO1xyXG4gICAgbGV0IGxhc3RQb3NYID0gMDtcclxuICAgIGxldCBsYXN0UG9zWSA9IDA7XHJcblxyXG4gICAgY2FudmFzLm9uKFwibW91c2U6ZG93blwiLCAob3B0OiBhbnkpID0+IHtcclxuICAgICAgLy8gSGFuZGxlIGZpeHR1cmUgY2xpY2tzIC0gdXNlIGZpbmRUYXJnZXQgdG8gZ2V0IHRoZSBhY3R1YWwgZ3JvdXBcclxuICAgICAgaWYgKG9wdC50YXJnZXQpIHtcclxuICAgICAgICBjb25zdCBvYmogPSBvcHQudGFyZ2V0IGFzIGFueTtcclxuICAgICAgICAvLyBDaGVjayBpZiBpdCdzIGEgZml4dHVyZSBncm91cCBvciBuZXN0ZWQgd2l0aGluIG9uZVxyXG4gICAgICAgIGxldCBmaXh0dXJlR3JvdXAgPSBvYmo7XHJcblxyXG4gICAgICAgIC8vIFRyYXZlcnNlIHVwIHRvIGZpbmQgdGhlIGZpeHR1cmUgZ3JvdXBcclxuICAgICAgICBsZXQgYXR0ZW1wdHMgPSAwO1xyXG4gICAgICAgIHdoaWxlIChmaXh0dXJlR3JvdXAgJiYgIShmaXh0dXJlR3JvdXAgYXMgYW55KS5maXh0dXJlSWQgJiYgIShmaXh0dXJlR3JvdXAgYXMgYW55KS5vYmpUeXBlICYmIGF0dGVtcHRzIDwgMTApIHtcclxuICAgICAgICAgIGlmICgoZml4dHVyZUdyb3VwIGFzIGFueSkucGFyZW50KSB7XHJcbiAgICAgICAgICAgIGZpeHR1cmVHcm91cCA9IChmaXh0dXJlR3JvdXAgYXMgYW55KS5wYXJlbnQ7XHJcbiAgICAgICAgICB9IGVsc2UgaWYgKChmaXh0dXJlR3JvdXAgYXMgYW55KS5ncm91cCkge1xyXG4gICAgICAgICAgICBmaXh0dXJlR3JvdXAgPSAoZml4dHVyZUdyb3VwIGFzIGFueSkuZ3JvdXA7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGF0dGVtcHRzKys7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBDaGVjayBpZiB3ZSBmb3VuZCBhIGZpeHR1cmUgZ3JvdXBcclxuICAgICAgICBpZiAoKGZpeHR1cmVHcm91cCBhcyBhbnkpLm9ialR5cGUgPT09IFwiZml4dHVyZVwiIHx8IChmaXh0dXJlR3JvdXAgYXMgYW55KS5maXh0dXJlSWQpIHtcclxuICAgICAgICAgIHRoaXMub25GaXh0dXJlQ2xpY2soZml4dHVyZUdyb3VwKTtcclxuICAgICAgICAgIGNhbnZhcy5zZXRBY3RpdmVPYmplY3QoZml4dHVyZUdyb3VwKTtcclxuICAgICAgICAgIGNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCk7XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICAvLyBGb3Igbm9uLWZpeHR1cmUgY2xpY2tzLCBlbmFibGUgZHJhZ2dpbmdcclxuICAgICAgaWYgKCFvcHQudGFyZ2V0KSB7XHJcbiAgICAgICAgaXNEcmFnZ2luZyA9IHRydWU7XHJcbiAgICAgICAgY2FudmFzLnNlbGVjdGlvbiA9IGZhbHNlO1xyXG4gICAgICAgIGNvbnN0IGUgPSBvcHQuZTtcclxuICAgICAgICBsYXN0UG9zWCA9IGUuY2xpZW50WDtcclxuICAgICAgICBsYXN0UG9zWSA9IGUuY2xpZW50WTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgY2FudmFzLm9uKFwibW91c2U6bW92ZVwiLCAob3B0OiBhbnkpID0+IHtcclxuICAgICAgaWYgKGlzRHJhZ2dpbmcgJiYgY2FudmFzLnZpZXdwb3J0VHJhbnNmb3JtICYmICFvcHQudGFyZ2V0KSB7XHJcbiAgICAgICAgY29uc3QgZSA9IG9wdC5lO1xyXG4gICAgICAgIGNvbnN0IHZwdCA9IGNhbnZhcy52aWV3cG9ydFRyYW5zZm9ybTtcclxuICAgICAgICB2cHRbNF0gKz0gZS5jbGllbnRYIC0gbGFzdFBvc1g7XHJcbiAgICAgICAgdnB0WzVdICs9IGUuY2xpZW50WSAtIGxhc3RQb3NZO1xyXG4gICAgICAgIGNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCk7XHJcbiAgICAgICAgbGFzdFBvc1ggPSBlLmNsaWVudFg7XHJcbiAgICAgICAgbGFzdFBvc1kgPSBlLmNsaWVudFk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIGNhbnZhcy5vbihcIm1vdXNlOnVwXCIsICgpID0+IHtcclxuICAgICAgaXNEcmFnZ2luZyA9IGZhbHNlO1xyXG4gICAgICBjYW52YXMuc2VsZWN0aW9uID0gZmFsc2U7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIG9uU3RvcmVTZWxlY3Qoc3RvcmU6IFN0b3JlKTogdm9pZCB7XHJcbiAgICAvLyBBbGxvdyB2aWV3aW5nIHBsYW5vZ3JhbSBldmVuIGZvciBzdG9yZXMgd2l0aCBuby1tYXRjaCBzdGF0dXNcclxuICAgIHRoaXMuc2VsZWN0ZWRTdG9yZSA9IHN0b3JlO1xyXG4gICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xyXG5cclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICBpZiAodGhpcy5pbml0aWFsaXplQ2FudmFzKCkpIHtcclxuICAgICAgICAvLyBSZXNpemUgY2FudmFzIHRvIGNvbnRhaW5lciBzaXplXHJcbiAgICAgICAgaWYgKHRoaXMucHJldmlld0NhbnZhc0NvbnRhaW5lclJlZj8ubmF0aXZlRWxlbWVudCkge1xyXG4gICAgICAgICAgdGhpcy5yZXNpemVDYW52YXModGhpcy5wcmV2aWV3Q2FudmFzLCB0aGlzLnByZXZpZXdDYW52YXNDb250YWluZXJSZWYpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLmxvYWRQbGFub2dyYW1Gb3JTdG9yZShzdG9yZS5zdG9yZU5hbWUpO1xyXG4gICAgICB9XHJcbiAgICB9LCAxMDApO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgbG9hZFBsYW5vZ3JhbUZvclN0b3JlKHN0b3JlTmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBpZiAoIXN0b3JlTmFtZSB8fCAhdGhpcy5wcmV2aWV3Q2FudmFzKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmNhbnZhc0xvYWRpbmcgPSB0cnVlO1xyXG4gICAgdHJ5IHtcclxuICAgICAgY29uc3QgcmVzcG9uc2U6IGFueSA9IGF3YWl0IHRoaXMuc3RvcmVCdWlsZGVyU2VydmljZS5nZXRQbGFub0lkKHsgc3RvcmVzOiBbc3RvcmVOYW1lLnRvVXBwZXJDYXNlKCldIH0pLnRvUHJvbWlzZSgpO1xyXG5cclxuICAgICAgaWYgKHJlc3BvbnNlPy5jb2RlID09PSAyMDAgJiYgcmVzcG9uc2U/LmRhdGE/Lmxlbmd0aCA+IDApIHtcclxuICAgICAgICBjb25zdCBwbGFub0lkID0gcmVzcG9uc2UuZGF0YVswXS5faWQ7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5nZXRTdG9yZUZpeHR1cmVzKHBsYW5vSWQpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuY2FudmFzTG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcclxuICAgICAgfVxyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgbG9hZGluZyBwbGFub2dyYW06JywgZXJyb3IpO1xyXG4gICAgICB0aGlzLmNhbnZhc0xvYWRpbmcgPSBmYWxzZTtcclxuICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgYXN5bmMgZ2V0U3RvcmVGaXh0dXJlcyhzdG9yZUlkOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGlmICghdGhpcy5wcmV2aWV3Q2FudmFzKSB7XHJcbiAgICAgIHRoaXMuY2FudmFzTG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnN0b3JlQnVpbGRlclNlcnZpY2UuZ2V0U3RvcmVGaXh0dXJlcyh7IGlkOiBbc3RvcmVJZF0gfSlcclxuICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKVxyXG4gICAgICAuc3Vic2NyaWJlKHtcclxuICAgICAgICBuZXh0OiBhc3luYyAocmVzOiBhbnkpID0+IHtcclxuICAgICAgICAgIGlmICghcmVzPy5kYXRhPy5bMF0/LmZsb29ycz8ubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIHRoaXMuY2FudmFzTG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICB0aGlzLnBsYW5vRGF0YSA9IHN0cnVjdHVyZWRDbG9uZShyZXMuZGF0YVswXSk7XHJcbiAgICAgICAgICB0aGlzLmZsb29yRGF0YSA9IHN0cnVjdHVyZWRDbG9uZShyZXMuZGF0YVswXS5mbG9vcnNbMF0pO1xyXG5cclxuICAgICAgICAgIC8vIEFwcGx5IHN0b3JlZCByZXNwb25zZSBkYXRhIGlmIGF2YWlsYWJsZVxyXG4gICAgICAgICAgdGhpcy5hcHBseVN0b3JlZFJlc3BvbnNlRGF0YSgpO1xyXG5cclxuICAgICAgICAgIC8vIENvbGxlY3QgYWxsIGZpeHR1cmVzXHJcbiAgICAgICAgICB0aGlzLmNvbGxlY3RBbGxGaXh0dXJlcygpO1xyXG5cclxuICAgICAgICAgIGlmICh0aGlzLnByZXZpZXdDYW52YXMpIHtcclxuICAgICAgICAgICAgLy8gUmVuZGVyIHRoZSBwbGFub2dyYW0gZmlyc3RcclxuICAgICAgICAgICAgYXdhaXQgdGhpcy5yZW5kZXJGbG9vcih0aGlzLnByZXZpZXdDYW52YXMpO1xyXG4gICAgICAgICAgICB0aGlzLmNhbnZhc0xvYWRpbmcgPSBmYWxzZTtcclxuICAgICAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xyXG5cclxuICAgICAgICAgICAgLy8gV2FpdCBmb3IgYWxsIG9iamVjdHMgdG8gYmUgcmVuZGVyZWQsIHRoZW4gcmVzaXplIGFuZCByZWNlbnRlclxyXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICBpZiAodGhpcy5wcmV2aWV3Q2FudmFzQ29udGFpbmVyUmVmPy5uYXRpdmVFbGVtZW50ICYmIHRoaXMucHJldmlld0NhbnZhcykge1xyXG4gICAgICAgICAgICAgICAgLy8gUmVzaXplIGNhbnZhcyB0byBjb250YWluZXIgZGltZW5zaW9uc1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yZXNpemVDYW52YXModGhpcy5wcmV2aWV3Q2FudmFzLCB0aGlzLnByZXZpZXdDYW52YXNDb250YWluZXJSZWYpO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIFdhaXQgYSBiaXQgbW9yZSBmb3IgY2FudmFzIHRvIHVwZGF0ZSwgdGhlbiByZWNlbnRlclxyXG4gICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnByZXZpZXdDYW52YXMpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmZpdENhbnZhc1RvTGF5b3V0QW5pbWF0ZWQodGhpcy5wcmV2aWV3Q2FudmFzKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gSGlnaGxpZ2h0IGZpeHR1cmUgaWYgaXQgaGFzIHJlcGxhY2VSZXNwb25zZURhdGFcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBzdG9yZSA9IHRoaXMuZmluZFJlcGxhY2VEYXRhPy5zdG9yZXM/LmZpbmQoXHJcbiAgICAgICAgICAgICAgICAgICAgICAoczogU3RvcmUpID0+IHMuc3RvcmVOYW1lID09PSB0aGlzLnNlbGVjdGVkU3RvcmU/LnN0b3JlTmFtZVxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHN0b3JlPy5maW5kUmVzcG9uc2VEYXRhICYmIHN0b3JlPy5yZXBsYWNlUmVzcG9uc2VEYXRhKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaXh0dXJlR3JvdXAgPSB0aGlzLnByZXZpZXdDYW52YXMuZ2V0T2JqZWN0cygpLmZpbmQoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIChvYmo6IGFueSkgPT4gb2JqLm9ialR5cGUgPT09IFwiZml4dHVyZVwiICYmIG9iai5maXh0dXJlSWQgPT09IHN0b3JlLmZpbmRSZXNwb25zZURhdGFcclxuICAgICAgICAgICAgICAgICAgICAgICkgYXMgZmFicmljLkdyb3VwIHwgdW5kZWZpbmVkO1xyXG4gICAgICAgICAgICAgICAgICAgICAgaWYgKGZpeHR1cmVHcm91cCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmhpZ2hsaWdodEZpeHR1cmUodGhpcy5wcmV2aWV3Q2FudmFzLCBmaXh0dXJlR3JvdXAsIGZhbHNlKTtcclxuICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0sIDEwMCk7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LCAzMDApO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy5jYW52YXNMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG4gICAgICAgIGVycm9yOiAoZXJyOiBhbnkpID0+IHtcclxuICAgICAgICAgIHRoaXMuY2FudmFzTG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgdGhpcy5jZHIuZGV0ZWN0Q2hhbmdlcygpO1xyXG4gICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZmV0Y2hpbmcgcGxhbm86JywgZXJyKTtcclxuICAgICAgICB9LFxyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgYXBwbHlTdG9yZWRSZXNwb25zZURhdGEoKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuZmluZFJlcGxhY2VEYXRhPy5zdG9yZXMgfHwgIXRoaXMuc2VsZWN0ZWRTdG9yZSB8fCAhdGhpcy5mbG9vckRhdGEpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHN0b3JlID0gdGhpcy5maW5kUmVwbGFjZURhdGEuc3RvcmVzLmZpbmQoXHJcbiAgICAgIChzOiBTdG9yZSkgPT4gcy5zdG9yZU5hbWUgPT09IHRoaXMuc2VsZWN0ZWRTdG9yZT8uc3RvcmVOYW1lXHJcbiAgICApO1xyXG5cclxuICAgIGlmICghc3RvcmU/LnJlcGxhY2VSZXNwb25zZURhdGEpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGZpeHR1cmVJZCA9IHN0b3JlLmZpbmRSZXNwb25zZURhdGE7XHJcbiAgICBpZiAoIWZpeHR1cmVJZCkgcmV0dXJuO1xyXG5cclxuICAgIGNvbnN0IGZpeHR1cmUgPSB0aGlzLmdldEZpeHR1cmVCeUlkRnJvbUZsb29yKGZpeHR1cmVJZCk7XHJcbiAgICBpZiAoIWZpeHR1cmUpIHJldHVybjtcclxuXHJcbiAgICAvLyBTdG9yZSB0aGUgb3JpZ2luYWwgZml4dHVyZSAoYmVmb3JlIHJlcGxhY2UpIGZvciBiZWZvcmUvYWZ0ZXIgY29tcGFyaXNvblxyXG4gICAgY29uc3Qgb3JpZ2luYWxGaXh0dXJlID0gc3RydWN0dXJlZENsb25lKGZpeHR1cmUpO1xyXG4gICAgdGhpcy5vcmlnaW5hbEZpeHR1cmVzTWFwLnNldChmaXh0dXJlSWQsIG9yaWdpbmFsRml4dHVyZSk7XHJcblxyXG4gICAgLy8gQ3JlYXRlIGEgZGVlcCBjb3B5IG9mIHRoZSBmaXh0dXJlIHRvIHByZXNlcnZlIGFsbCBvcmlnaW5hbCBwcm9wZXJ0aWVzXHJcbiAgICBjb25zdCB1cGRhdGVkRml4dHVyZSA9IHN0cnVjdHVyZWRDbG9uZShmaXh0dXJlKTtcclxuXHJcbiAgICAvLyBNZXJnZSByZXBsYWNlUmVzcG9uc2VEYXRhIHByb3BlcnRpZXMgd2hpbGUgcHJlc2VydmluZyBhbGwgb3RoZXIgZml4dHVyZSBwcm9wZXJ0aWVzXHJcbiAgICBpZiAoc3RvcmUucmVwbGFjZVJlc3BvbnNlRGF0YS52bUNvbmZpZykge1xyXG4gICAgICB1cGRhdGVkRml4dHVyZS52bUNvbmZpZyA9IEFycmF5LmlzQXJyYXkoc3RvcmUucmVwbGFjZVJlc3BvbnNlRGF0YS52bUNvbmZpZylcclxuICAgICAgICA/IHN0b3JlLnJlcGxhY2VSZXNwb25zZURhdGEudm1Db25maWdcclxuICAgICAgICA6IFtdO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIE1lcmdlIHNoZWxmQ29uZmlnIGludGVsbGlnZW50bHkgLSBwcmVzZXJ2ZSBvcmlnaW5hbCBzaGVsZiBzdHJ1Y3R1cmUgYW5kIG9ubHkgdXBkYXRlIHByb3ZpZGVkIHByb3BlcnRpZXNcclxuICAgIGlmIChzdG9yZS5yZXBsYWNlUmVzcG9uc2VEYXRhLnNoZWxmQ29uZmlnICYmIEFycmF5LmlzQXJyYXkoc3RvcmUucmVwbGFjZVJlc3BvbnNlRGF0YS5zaGVsZkNvbmZpZykpIHtcclxuICAgICAgY29uc3Qgb3JpZ2luYWxTaGVsZkNvbmZpZyA9IEFycmF5LmlzQXJyYXkoZml4dHVyZS5zaGVsZkNvbmZpZykgPyBmaXh0dXJlLnNoZWxmQ29uZmlnIDogW107XHJcblxyXG4gICAgICAvLyBDcmVhdGUgYSBtYXAgb2Ygb3JpZ2luYWwgc2hlbHZlcyBieSBzaGVsZiBpZGVudGlmaWVyIChzaGVsZlR5cGUgKyBzaGVsZk51bWJlcilcclxuICAgICAgY29uc3Qgb3JpZ2luYWxTaGVsdmVzTWFwID0gbmV3IE1hcCgpO1xyXG4gICAgICBvcmlnaW5hbFNoZWxmQ29uZmlnLmZvckVhY2goKHNoZWxmOiBhbnkpID0+IHtcclxuICAgICAgICBjb25zdCBrZXkgPSBgJHtzaGVsZi5zaGVsZlR5cGUgfHwgJyd9XyR7c2hlbGYuc2hlbGZOdW1iZXIgfHwgJyd9YDtcclxuICAgICAgICBvcmlnaW5hbFNoZWx2ZXNNYXAuc2V0KGtleSwgc2hlbGYpO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICAgIC8vIE1lcmdlOiBmb3IgZWFjaCBzaGVsZiBpbiByZXBsYWNlUmVzcG9uc2VEYXRhLCBmaW5kIHRoZSBvcmlnaW5hbCBhbmQgbWVyZ2VcclxuICAgICAgdXBkYXRlZEZpeHR1cmUuc2hlbGZDb25maWcgPSBzdG9yZS5yZXBsYWNlUmVzcG9uc2VEYXRhLnNoZWxmQ29uZmlnLm1hcCgobmV3U2hlbGY6IGFueSkgPT4ge1xyXG4gICAgICAgIGNvbnN0IGtleSA9IGAke25ld1NoZWxmLnNoZWxmVHlwZSB8fCAnJ31fJHtuZXdTaGVsZi5zaGVsZk51bWJlciB8fCAnJ31gO1xyXG4gICAgICAgIGNvbnN0IG9yaWdpbmFsU2hlbGYgPSBvcmlnaW5hbFNoZWx2ZXNNYXAuZ2V0KGtleSk7XHJcblxyXG4gICAgICAgIGlmIChvcmlnaW5hbFNoZWxmKSB7XHJcbiAgICAgICAgICAvLyBNZXJnZTogcHJlc2VydmUgYWxsIG9yaWdpbmFsIHByb3BlcnRpZXMsIHVwZGF0ZSB3aXRoIG5ldyBvbmVzXHJcbiAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAuLi5vcmlnaW5hbFNoZWxmLFxyXG4gICAgICAgICAgICAuLi5uZXdTaGVsZixcclxuICAgICAgICAgICAgLy8gRW5zdXJlIGNyaXRpY2FsIG51bWVyaWMgcHJvcGVydGllcyBhcmUgcHJlc2VydmVkXHJcbiAgICAgICAgICAgIHByb2R1Y3RQZXJTaGVsZjogbmV3U2hlbGYucHJvZHVjdFBlclNoZWxmICE9PSB1bmRlZmluZWQgPyBuZXdTaGVsZi5wcm9kdWN0UGVyU2hlbGYgOiBvcmlnaW5hbFNoZWxmLnByb2R1Y3RQZXJTaGVsZixcclxuICAgICAgICAgICAgdHJheVJvd3M6IG5ld1NoZWxmLnRyYXlSb3dzICE9PSB1bmRlZmluZWQgPyBuZXdTaGVsZi50cmF5Um93cyA6IG9yaWdpbmFsU2hlbGYudHJheVJvd3MsXHJcbiAgICAgICAgICAgIHNoZWxmVHlwZTogbmV3U2hlbGYuc2hlbGZUeXBlIHx8IG9yaWdpbmFsU2hlbGYuc2hlbGZUeXBlLFxyXG4gICAgICAgICAgICBzaGVsZk51bWJlcjogbmV3U2hlbGYuc2hlbGZOdW1iZXIgIT09IHVuZGVmaW5lZCA/IG5ld1NoZWxmLnNoZWxmTnVtYmVyIDogb3JpZ2luYWxTaGVsZi5zaGVsZk51bWJlcixcclxuICAgICAgICAgIH07XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIC8vIE5ldyBzaGVsZiBub3QgaW4gb3JpZ2luYWwgLSB1c2UgYXMgaXMgYnV0IGVuc3VyZSByZXF1aXJlZCBwcm9wZXJ0aWVzXHJcbiAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAuLi5uZXdTaGVsZixcclxuICAgICAgICAgICAgcHJvZHVjdFBlclNoZWxmOiBuZXdTaGVsZi5wcm9kdWN0UGVyU2hlbGYgfHwgMCxcclxuICAgICAgICAgICAgdHJheVJvd3M6IG5ld1NoZWxmLnRyYXlSb3dzIHx8IDEsXHJcbiAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9IGVsc2UgaWYgKCFBcnJheS5pc0FycmF5KHVwZGF0ZWRGaXh0dXJlLnNoZWxmQ29uZmlnKSkge1xyXG4gICAgICB1cGRhdGVkRml4dHVyZS5zaGVsZkNvbmZpZyA9IFtdO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEVuc3VyZSBhcnJheXMgYXJlIGFsd2F5cyBhcnJheXNcclxuICAgIGlmICghQXJyYXkuaXNBcnJheSh1cGRhdGVkRml4dHVyZS52bUNvbmZpZykpIHtcclxuICAgICAgdXBkYXRlZEZpeHR1cmUudm1Db25maWcgPSBbXTtcclxuICAgIH1cclxuICAgIGlmICghQXJyYXkuaXNBcnJheSh1cGRhdGVkRml4dHVyZS5zaGVsZkNvbmZpZykpIHtcclxuICAgICAgdXBkYXRlZEZpeHR1cmUuc2hlbGZDb25maWcgPSBbXTtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLnVwZGF0ZUFpUmVzcG9uc2VGaXh0dXJlKHVwZGF0ZWRGaXh0dXJlKTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0Rml4dHVyZUJ5SWRGcm9tRmxvb3IoZml4dHVyZUlkOiBzdHJpbmcpOiBhbnkgfCBudWxsIHtcclxuICAgIGlmICghZml4dHVyZUlkIHx8ICF0aGlzLmZsb29yRGF0YSkgcmV0dXJuIG51bGw7XHJcblxyXG4gICAgZm9yIChjb25zdCBlbGVtZW50IG9mIHRoaXMuZmxvb3JEYXRhLmxheW91dFBvbHlnb24gfHwgW10pIHtcclxuICAgICAgaWYgKGVsZW1lbnQ/LmVsZW1lbnRUeXBlID09PSBcIndhbGxcIiAmJiBBcnJheS5pc0FycmF5KGVsZW1lbnQuZml4dHVyZXMpKSB7XHJcbiAgICAgICAgY29uc3QgaGl0ID0gZWxlbWVudC5maXh0dXJlcy5maW5kKChmeDogYW55KSA9PiBmeD8uX2lkID09PSBmaXh0dXJlSWQpO1xyXG4gICAgICAgIGlmIChoaXQpIHJldHVybiBoaXQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBmb3IgKGNvbnN0IGZ4IG9mIHRoaXMuZmxvb3JEYXRhLmNlbnRlckZpeHR1cmUgfHwgW10pIHtcclxuICAgICAgaWYgKGZ4Py5faWQgPT09IGZpeHR1cmVJZCkgcmV0dXJuIGZ4O1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSB1cGRhdGVBaVJlc3BvbnNlRml4dHVyZSh1cGRhdGVkRml4dHVyZTogYW55KTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuZmxvb3JEYXRhKSByZXR1cm47XHJcblxyXG4gICAgZm9yIChjb25zdCBlbGVtZW50IG9mIHRoaXMuZmxvb3JEYXRhLmxheW91dFBvbHlnb24gfHwgW10pIHtcclxuICAgICAgaWYgKGVsZW1lbnQ/LmVsZW1lbnRUeXBlID09PSBcIndhbGxcIiAmJiBBcnJheS5pc0FycmF5KGVsZW1lbnQuZml4dHVyZXMpKSB7XHJcbiAgICAgICAgY29uc3QgaW5kZXggPSBlbGVtZW50LmZpeHR1cmVzLmZpbmRJbmRleCgoZng6IGFueSkgPT4gZng/Ll9pZCA9PT0gdXBkYXRlZEZpeHR1cmUuX2lkKTtcclxuICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XHJcbiAgICAgICAgICBlbGVtZW50LmZpeHR1cmVzW2luZGV4XSA9IHVwZGF0ZWRGaXh0dXJlO1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgKHRoaXMuZmxvb3JEYXRhLmNlbnRlckZpeHR1cmUgfHwgW10pLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGlmICh0aGlzLmZsb29yRGF0YS5jZW50ZXJGaXh0dXJlW2ldPy5faWQgPT09IHVwZGF0ZWRGaXh0dXJlLl9pZCkge1xyXG4gICAgICAgIHRoaXMuZmxvb3JEYXRhLmNlbnRlckZpeHR1cmVbaV0gPSB1cGRhdGVkRml4dHVyZTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGNvbGxlY3RBbGxGaXh0dXJlcygpOiB2b2lkIHtcclxuICAgIHRoaXMuYWxsRml4dHVyZUluc3RhbmNlcyA9IFtdO1xyXG5cclxuICAgIC8vIENvbGxlY3Qgd2FsbCBmaXh0dXJlc1xyXG4gICAgaWYgKHRoaXMuZmxvb3JEYXRhPy5sYXlvdXRQb2x5Z29uKSB7XHJcbiAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiB0aGlzLmZsb29yRGF0YS5sYXlvdXRQb2x5Z29uKSB7XHJcbiAgICAgICAgaWYgKGVsZW1lbnQuZml4dHVyZXMgJiYgQXJyYXkuaXNBcnJheShlbGVtZW50LmZpeHR1cmVzKSkge1xyXG4gICAgICAgICAgdGhpcy5hbGxGaXh0dXJlSW5zdGFuY2VzLnB1c2goLi4uZWxlbWVudC5maXh0dXJlcyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ29sbGVjdCBmbG9vciBmaXh0dXJlc1xyXG4gICAgaWYgKHRoaXMuZmxvb3JEYXRhPy5jZW50ZXJGaXh0dXJlICYmIEFycmF5LmlzQXJyYXkodGhpcy5mbG9vckRhdGEuY2VudGVyRml4dHVyZSkpIHtcclxuICAgICAgdGhpcy5hbGxGaXh0dXJlSW5zdGFuY2VzLnB1c2goLi4udGhpcy5mbG9vckRhdGEuY2VudGVyRml4dHVyZSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBhc3luYyByZW5kZXJGbG9vcihjYW52YXM6IGZhYnJpYy5DYW52YXMpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGF3YWl0IHRoaXMuZHJhd0luaXRpYWxDb250ZW50KGNhbnZhcyk7XHJcbiAgfVxyXG5cclxuICBhc3luYyBkcmF3SW5pdGlhbENvbnRlbnQoY2FudmFzOiBmYWJyaWMuQ2FudmFzKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAvLyBDbGVhciBjYW52YXMgYW5kIHJlc2V0IHZpZXdwb3J0XHJcbiAgICBjYW52YXMuY2xlYXIoKTtcclxuICAgIGNhbnZhcy5zZXRWaWV3cG9ydFRyYW5zZm9ybShbMSwgMCwgMCwgMSwgMCwgMF0pO1xyXG4gICAgYXdhaXQgdGhpcy5kcmF3TGF5b3V0RWxlbWVudHMoY2FudmFzKTtcclxuICAgIC8vIEZvcmNlIHJlbmRlciBhZnRlciBkcmF3aW5nXHJcbiAgICBjYW52YXMucmVxdWVzdFJlbmRlckFsbCgpO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgZHJhd0xheW91dEVsZW1lbnRzKGNhbnZhczogZmFicmljLkNhbnZhcykge1xyXG4gICAgaWYgKCF0aGlzLmZsb29yRGF0YSkgcmV0dXJuO1xyXG5cclxuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCB0aGlzLmZsb29yRGF0YS5sYXlvdXRQb2x5Z29uLmxlbmd0aDsgaW5kZXgrKykge1xyXG4gICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5mbG9vckRhdGEubGF5b3V0UG9seWdvbltpbmRleF07XHJcbiAgICAgIGxldCB3YWxsO1xyXG5cclxuICAgICAgZWxlbWVudC5yZWxhdGl2ZVBvc2l0aW9uID8/PSB7IHg6IDAsIHk6IDAsIHVuaXQ6IFwiZnRcIiB9O1xyXG4gICAgICBjb25zdCB4ID0gdGhpcy50b1BpeGVscyhlbGVtZW50LnJlbGF0aXZlUG9zaXRpb24ueCwgZWxlbWVudC51bml0KTtcclxuICAgICAgY29uc3QgeSA9IHRoaXMudG9QaXhlbHMoZWxlbWVudC5yZWxhdGl2ZVBvc2l0aW9uLnksIGVsZW1lbnQudW5pdCk7XHJcblxyXG4gICAgICBpZiAoZWxlbWVudC5lbGVtZW50VHlwZSA9PT0gXCJ3YWxsXCIpIHtcclxuICAgICAgICBjb25zdCBoZWlnaHQgPSB0aGlzLndhbGxUaGlja25lc3M7XHJcbiAgICAgICAgY29uc3Qgd2lkdGggPSB0aGlzLnRvUGl4ZWxzKGVsZW1lbnQuZGlzdGFuY2UsIGVsZW1lbnQudW5pdCk7XHJcbiAgICAgICAgd2FsbCA9IGF3YWl0IHRoaXMuZHJhd1dhbGwoY2FudmFzLCB4LCB5LCBoZWlnaHQsIHdpZHRoLCBlbGVtZW50KTtcclxuICAgICAgfSBlbHNlIGlmIChlbGVtZW50LmVsZW1lbnRUeXBlID09PSBcImVudHJhbmNlXCIpIHtcclxuICAgICAgICB0aGlzLmRyYXdFbnRyYW5jZShjYW52YXMsIHgsIHksIDgwLCA3NSwgNDAsIGVsZW1lbnQpO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoZWxlbWVudC5lbGVtZW50VHlwZSA9PT0gXCJ3YWxsXCIpIHtcclxuICAgICAgICBjb25zdCBmaXh0dXJlR3JvdXBzOiBmYWJyaWMuR3JvdXBbXSA9IFtdO1xyXG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgZWxlbWVudD8uZml4dHVyZXM/Lmxlbmd0aDsgaisrKSB7XHJcbiAgICAgICAgICBjb25zdCBmaXh0dXJlID0gZWxlbWVudC5maXh0dXJlc1tqXTtcclxuICAgICAgICAgIGNvbnN0IGZ4ID0gdGhpcy50b1BpeGVscyhmaXh0dXJlLnJlbGF0aXZlUG9zaXRpb24ueCwgZml4dHVyZS5yZWxhdGl2ZVBvc2l0aW9uLnVuaXQpO1xyXG4gICAgICAgICAgY29uc3QgZnkgPSB0aGlzLnRvUGl4ZWxzKGZpeHR1cmUucmVsYXRpdmVQb3NpdGlvbi55LCBmaXh0dXJlLnJlbGF0aXZlUG9zaXRpb24udW5pdCk7XHJcbiAgICAgICAgICBjb25zdCBmaCA9IHRoaXMudG9QaXhlbHMoZml4dHVyZS5maXh0dXJlU3RhdGljTGVuZ3RoLnZhbHVlLCBmaXh0dXJlLmZpeHR1cmVTdGF0aWNMZW5ndGgudW5pdCk7XHJcbiAgICAgICAgICBjb25zdCBmdyA9IHRoaXMudG9QaXhlbHMoZml4dHVyZS5maXh0dXJlU3RhdGljV2lkdGgudmFsdWUsIGZpeHR1cmUuZml4dHVyZVN0YXRpY1dpZHRoLnVuaXQpO1xyXG4gICAgICAgICAgY29uc3QgZml4dHVyZU9iaiA9IGF3YWl0IHRoaXMuZHJhd0ZpeHR1cmUoY2FudmFzLCBmeCwgZnksIGZoLCBmdywgZml4dHVyZSk7XHJcbiAgICAgICAgICBmaXh0dXJlR3JvdXBzLnB1c2goZml4dHVyZU9iaiBhcyBmYWJyaWMuR3JvdXApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGVsZW1lbnQuaXNMb2NrZWQgJiYgd2FsbCkge1xyXG4gICAgICAgICAgY2FudmFzLnJlbW92ZSh3YWxsKTtcclxuICAgICAgICAgIGZpeHR1cmVHcm91cHMuZm9yRWFjaCgoZikgPT4gY2FudmFzLnJlbW92ZShmKSk7XHJcbiAgICAgICAgICBjb25zdCBjb21iaW5lZEdyb3VwID0gbmV3IGZhYnJpYy5Hcm91cChbd2FsbCwgLi4uZml4dHVyZUdyb3Vwc10sIHtcclxuICAgICAgICAgICAgaGFzQ29udHJvbHM6IGZhbHNlLFxyXG4gICAgICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICAgICAgbG9ja01vdmVtZW50WDogdHJ1ZSxcclxuICAgICAgICAgICAgbG9ja01vdmVtZW50WTogdHJ1ZSxcclxuICAgICAgICAgICAgbG9ja1JvdGF0aW9uOiB0cnVlLFxyXG4gICAgICAgICAgICBsb2NrU2NhbGluZ1g6IHRydWUsXHJcbiAgICAgICAgICAgIGxvY2tTY2FsaW5nWTogdHJ1ZSxcclxuICAgICAgICAgICAgc3ViVGFyZ2V0Q2hlY2s6IHRydWUsXHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICAgIGNvbWJpbmVkR3JvdXAuc2V0KHsgaXNMb2NrZWQ6IHRydWUgfSk7XHJcbiAgICAgICAgICBjYW52YXMuYWRkKGNvbWJpbmVkR3JvdXApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBlbGVtZW50Py5vdGhlckVsZW1lbnRzPy5sZW5ndGg7IGorKykge1xyXG4gICAgICAgICAgY29uc3Qgb3RoZXJFbGVtZW50ID0gZWxlbWVudC5vdGhlckVsZW1lbnRzW2pdO1xyXG4gICAgICAgICAgY29uc3Qgb3ggPSB0aGlzLnRvUGl4ZWxzKG90aGVyRWxlbWVudC5yZWxhdGl2ZVBvc2l0aW9uLngsIFwiZnRcIik7XHJcbiAgICAgICAgICBjb25zdCBveSA9IHRoaXMudG9QaXhlbHMob3RoZXJFbGVtZW50LnJlbGF0aXZlUG9zaXRpb24ueSwgXCJmdFwiKTtcclxuICAgICAgICAgIGNvbnN0IG9hID0gb3RoZXJFbGVtZW50LnJlbGF0aXZlUG9zaXRpb24uYW5nbGU7XHJcbiAgICAgICAgICBjb25zdCBvaCA9IHRoaXMudG9QaXhlbHMob3RoZXJFbGVtZW50LmZpeHR1cmVTdGF0aWNMZW5ndGgudmFsdWUsIG90aGVyRWxlbWVudC5maXh0dXJlU3RhdGljTGVuZ3RoLnVuaXQpO1xyXG4gICAgICAgICAgY29uc3Qgb3cgPSB0aGlzLnRvUGl4ZWxzKG90aGVyRWxlbWVudC5maXh0dXJlU3RhdGljV2lkdGgudmFsdWUsIG90aGVyRWxlbWVudC5maXh0dXJlU3RhdGljV2lkdGgudW5pdCk7XHJcbiAgICAgICAgICB0aGlzLmRyYXdPdGhlckVsZW1lbnRzV2l0aExhYmVsKGNhbnZhcywgb3gsIG95LCBvYSwgb3csIG9oLCBvdGhlckVsZW1lbnQpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5mbG9vckRhdGE/LmNlbnRlckZpeHR1cmU/Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGNvbnN0IGZpeHR1cmUgPSB0aGlzLmZsb29yRGF0YS5jZW50ZXJGaXh0dXJlW2ldO1xyXG4gICAgICBjb25zdCB4ID0gdGhpcy50b1BpeGVscyhmaXh0dXJlLnJlbGF0aXZlUG9zaXRpb24ueCwgZml4dHVyZS5yZWxhdGl2ZVBvc2l0aW9uLnVuaXQpO1xyXG4gICAgICBjb25zdCB5ID0gdGhpcy50b1BpeGVscyhmaXh0dXJlLnJlbGF0aXZlUG9zaXRpb24ueSwgZml4dHVyZS5yZWxhdGl2ZVBvc2l0aW9uLnVuaXQpO1xyXG4gICAgICBjb25zdCBoID0gdGhpcy50b1BpeGVscyhmaXh0dXJlLmZpeHR1cmVTdGF0aWNMZW5ndGgudmFsdWUsIGZpeHR1cmUuZml4dHVyZVN0YXRpY0xlbmd0aC51bml0KTtcclxuICAgICAgY29uc3QgdyA9IHRoaXMudG9QaXhlbHMoZml4dHVyZS5maXh0dXJlU3RhdGljV2lkdGgudmFsdWUsIGZpeHR1cmUuZml4dHVyZVN0YXRpY1dpZHRoLnVuaXQpO1xyXG4gICAgICBhd2FpdCB0aGlzLmRyYXdGaXh0dXJlKGNhbnZhcywgeCwgeSwgaCwgdywgZml4dHVyZSk7XHJcbiAgICB9XHJcblxyXG4gICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLmZsb29yRGF0YT8ub3RoZXJFbGVtZW50cz8ubGVuZ3RoOyBqKyspIHtcclxuICAgICAgY29uc3Qgb3RoZXJFbGVtZW50ID0gdGhpcy5mbG9vckRhdGEub3RoZXJFbGVtZW50c1tqXTtcclxuICAgICAgY29uc3QgeCA9IHRoaXMudG9QaXhlbHMob3RoZXJFbGVtZW50LnJlbGF0aXZlUG9zaXRpb24ueCwgXCJmdFwiKTtcclxuICAgICAgY29uc3QgeSA9IHRoaXMudG9QaXhlbHMob3RoZXJFbGVtZW50LnJlbGF0aXZlUG9zaXRpb24ueSwgXCJmdFwiKTtcclxuICAgICAgY29uc3QgYSA9IG90aGVyRWxlbWVudC5yZWxhdGl2ZVBvc2l0aW9uLmFuZ2xlO1xyXG4gICAgICBjb25zdCBoID0gdGhpcy50b1BpeGVscyhvdGhlckVsZW1lbnQuZml4dHVyZVN0YXRpY0xlbmd0aC52YWx1ZSwgb3RoZXJFbGVtZW50LmZpeHR1cmVTdGF0aWNMZW5ndGgudW5pdCk7XHJcbiAgICAgIGNvbnN0IHcgPSB0aGlzLnRvUGl4ZWxzKG90aGVyRWxlbWVudC5maXh0dXJlU3RhdGljV2lkdGgudmFsdWUsIG90aGVyRWxlbWVudC5maXh0dXJlU3RhdGljV2lkdGgudW5pdCk7XHJcbiAgICAgIHRoaXMuZHJhd090aGVyRWxlbWVudHNXaXRoTGFiZWwoY2FudmFzLCB4LCB5LCBhLCB3LCBoLCBvdGhlckVsZW1lbnQpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0cnVlO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgZHJhd1dhbGwoXHJcbiAgICBjYW52YXM6IGZhYnJpYy5DYW52YXMsXHJcbiAgICB4OiBudW1iZXIsXHJcbiAgICB5OiBudW1iZXIsXHJcbiAgICBoZWlnaHQ6IG51bWJlcixcclxuICAgIHdpZHRoOiBudW1iZXIsXHJcbiAgICBlbGVtZW50RGF0YTogYW55XHJcbiAgKSB7XHJcbiAgICBjb25zdCByYWRpdXMgPSA1O1xyXG4gICAgY29uc3QgZmlsbENvbG9yID0gXCIjRjZGQ0ZGXCI7XHJcbiAgICBjb25zdCBzdHJva2VDb2xvciA9IFwiI0QwRDVERFwiO1xyXG4gICAgY29uc3QgbGFiZWxDb2xvciA9IFwiIzAwOUJGM1wiO1xyXG4gICAgbGV0IHRleHQgPSBgJHt0aGlzLnRpdGxlQ2FzZS50cmFuc2Zvcm0oZWxlbWVudERhdGEuZWxlbWVudFR5cGUpfSAke2VsZW1lbnREYXRhLmVsZW1lbnROdW1iZXJcclxuICAgICAgfWA7XHJcblxyXG4gICAgY29uc3Qgd2FsbCA9IG5ldyBmYWJyaWMuUmVjdCh7XHJcbiAgICAgIGxlZnQ6IDAsXHJcbiAgICAgIHRvcDogMCxcclxuICAgICAgd2lkdGgsXHJcbiAgICAgIGhlaWdodCxcclxuICAgICAgcng6IHJhZGl1cyxcclxuICAgICAgcnk6IHJhZGl1cyxcclxuICAgICAgZmlsbDogZmlsbENvbG9yLFxyXG4gICAgICBzdHJva2U6IHN0cm9rZUNvbG9yLFxyXG4gICAgICBzdHJva2VXaWR0aDogMC4yNyxcclxuICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgIHN0cm9rZVVuaWZvcm06IHRydWUsXHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCBjZW50ZXJYID0gd2lkdGggLyAyO1xyXG4gICAgY29uc3QgY2VudGVyWSA9IGhlaWdodCAvIDI7XHJcbiAgICBjb25zdCBpc1ZlcnRpY2FsID0gaGVpZ2h0ID4gd2lkdGg7XHJcblxyXG4gICAgY29uc3QgbGFiZWwgPSBuZXcgZmFicmljLkZhYnJpY1RleHQodGV4dCwge1xyXG4gICAgICBsZWZ0OiBjZW50ZXJYLFxyXG4gICAgICB0b3A6IGNlbnRlclksXHJcbiAgICAgIGZvbnRTaXplOiAxMCxcclxuICAgICAgZm9udEZhbWlseTogXCJJbnRlclwiLFxyXG4gICAgICBmb250V2VpZ2h0OiBcIjUwMFwiLFxyXG4gICAgICBmaWxsOiBsYWJlbENvbG9yLFxyXG4gICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICBhbmdsZTogaXNWZXJ0aWNhbCA/IC05MCA6IDAsXHJcbiAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgYXJyb3dIZWFkID0gNTtcclxuICAgIGNvbnN0IGVsZW1lbnRzOiBmYWJyaWMuT2JqZWN0W10gPSBbd2FsbCwgbGFiZWxdO1xyXG5cclxuICAgIGlmIChpc1ZlcnRpY2FsKSB7XHJcbiAgICAgIGNvbnN0IHRleHRXaWR0aCA9IGxhYmVsLndpZHRoIHx8IDA7XHJcbiAgICAgIGNvbnN0IHRvcEFycm93WSA9IDU7XHJcbiAgICAgIGNvbnN0IHRvcEFycm93RW5kWSA9IGNlbnRlclkgLSB0ZXh0V2lkdGggLyAyIC0gNTtcclxuXHJcbiAgICAgIGlmICh0b3BBcnJvd0VuZFkgPiB0b3BBcnJvd1kgKyBhcnJvd0hlYWQpIHtcclxuICAgICAgICBlbGVtZW50cy5wdXNoKFxyXG4gICAgICAgICAgbmV3IGZhYnJpYy5MaW5lKFtjZW50ZXJYLCB0b3BBcnJvd1ksIGNlbnRlclgsIHRvcEFycm93RW5kWV0sIHtcclxuICAgICAgICAgICAgc3Ryb2tlOiBsYWJlbENvbG9yLFxyXG4gICAgICAgICAgICBzdHJva2VXaWR0aDogMSxcclxuICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICB9KSxcclxuICAgICAgICAgIG5ldyBmYWJyaWMuVHJpYW5nbGUoe1xyXG4gICAgICAgICAgICBsZWZ0OiBjZW50ZXJYLFxyXG4gICAgICAgICAgICB0b3A6IHRvcEFycm93WSxcclxuICAgICAgICAgICAgd2lkdGg6IGFycm93SGVhZCxcclxuICAgICAgICAgICAgaGVpZ2h0OiBhcnJvd0hlYWQsXHJcbiAgICAgICAgICAgIGFuZ2xlOiAwLFxyXG4gICAgICAgICAgICBmaWxsOiBsYWJlbENvbG9yLFxyXG4gICAgICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgICBvcmlnaW5ZOiBcImJvdHRvbVwiLFxyXG4gICAgICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG5cclxuICAgICAgY29uc3QgYm90dG9tQXJyb3dTdGFydFkgPSBjZW50ZXJZICsgdGV4dFdpZHRoIC8gMiArIDU7XHJcbiAgICAgIGNvbnN0IGJvdHRvbUFycm93RW5kWSA9IGhlaWdodCAtIDU7XHJcblxyXG4gICAgICBpZiAoYm90dG9tQXJyb3dFbmRZID4gYm90dG9tQXJyb3dTdGFydFkgKyBhcnJvd0hlYWQpIHtcclxuICAgICAgICBlbGVtZW50cy5wdXNoKFxyXG4gICAgICAgICAgbmV3IGZhYnJpYy5MaW5lKFxyXG4gICAgICAgICAgICBbY2VudGVyWCwgYm90dG9tQXJyb3dTdGFydFksIGNlbnRlclgsIGJvdHRvbUFycm93RW5kWV0sXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICBzdHJva2U6IGxhYmVsQ29sb3IsXHJcbiAgICAgICAgICAgICAgc3Ryb2tlV2lkdGg6IDEsXHJcbiAgICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICksXHJcbiAgICAgICAgICBuZXcgZmFicmljLlRyaWFuZ2xlKHtcclxuICAgICAgICAgICAgbGVmdDogY2VudGVyWCxcclxuICAgICAgICAgICAgdG9wOiBib3R0b21BcnJvd0VuZFksXHJcbiAgICAgICAgICAgIHdpZHRoOiBhcnJvd0hlYWQsXHJcbiAgICAgICAgICAgIGhlaWdodDogYXJyb3dIZWFkLFxyXG4gICAgICAgICAgICBhbmdsZTogMTgwLFxyXG4gICAgICAgICAgICBmaWxsOiBsYWJlbENvbG9yLFxyXG4gICAgICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgICBvcmlnaW5ZOiBcInRvcFwiLFxyXG4gICAgICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgY29uc3QgdGV4dFdpZHRoID0gbGFiZWwud2lkdGggfHwgMDtcclxuICAgICAgY29uc3QgbGVmdEFycm93U3RhcnRYID0gNTtcclxuICAgICAgY29uc3QgbGVmdEFycm93RW5kWCA9IGNlbnRlclggLSB0ZXh0V2lkdGggLyAyIC0gNTtcclxuXHJcbiAgICAgIGlmIChsZWZ0QXJyb3dFbmRYID4gbGVmdEFycm93U3RhcnRYICsgYXJyb3dIZWFkKSB7XHJcbiAgICAgICAgZWxlbWVudHMucHVzaChcclxuICAgICAgICAgIG5ldyBmYWJyaWMuTGluZShbbGVmdEFycm93U3RhcnRYLCBjZW50ZXJZLCBsZWZ0QXJyb3dFbmRYLCBjZW50ZXJZXSwge1xyXG4gICAgICAgICAgICBzdHJva2U6IGxhYmVsQ29sb3IsXHJcbiAgICAgICAgICAgIHN0cm9rZVdpZHRoOiAxLFxyXG4gICAgICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICAgIH0pLFxyXG4gICAgICAgICAgbmV3IGZhYnJpYy5UcmlhbmdsZSh7XHJcbiAgICAgICAgICAgIGxlZnQ6IGxlZnRBcnJvd1N0YXJ0WCxcclxuICAgICAgICAgICAgdG9wOiBjZW50ZXJZLFxyXG4gICAgICAgICAgICB3aWR0aDogYXJyb3dIZWFkLFxyXG4gICAgICAgICAgICBoZWlnaHQ6IGFycm93SGVhZCxcclxuICAgICAgICAgICAgYW5nbGU6IC05MCxcclxuICAgICAgICAgICAgZmlsbDogbGFiZWxDb2xvcixcclxuICAgICAgICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgICAgICAgb3JpZ2luWTogXCJjZW50ZXJcIixcclxuICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICB9KVxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IHJpZ2h0QXJyb3dTdGFydFggPSBjZW50ZXJYICsgdGV4dFdpZHRoIC8gMiArIDU7XHJcbiAgICAgIGNvbnN0IHJpZ2h0QXJyb3dFbmRYID0gd2lkdGggLSA1O1xyXG5cclxuICAgICAgaWYgKHJpZ2h0QXJyb3dFbmRYID4gcmlnaHRBcnJvd1N0YXJ0WCArIGFycm93SGVhZCkge1xyXG4gICAgICAgIGVsZW1lbnRzLnB1c2goXHJcbiAgICAgICAgICBuZXcgZmFicmljLkxpbmUoXHJcbiAgICAgICAgICAgIFtyaWdodEFycm93U3RhcnRYLCBjZW50ZXJZLCByaWdodEFycm93RW5kWCwgY2VudGVyWV0sXHJcbiAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICBzdHJva2U6IGxhYmVsQ29sb3IsXHJcbiAgICAgICAgICAgICAgc3Ryb2tlV2lkdGg6IDEsXHJcbiAgICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICksXHJcbiAgICAgICAgICBuZXcgZmFicmljLlRyaWFuZ2xlKHtcclxuICAgICAgICAgICAgbGVmdDogcmlnaHRBcnJvd0VuZFgsXHJcbiAgICAgICAgICAgIHRvcDogY2VudGVyWSxcclxuICAgICAgICAgICAgd2lkdGg6IGFycm93SGVhZCxcclxuICAgICAgICAgICAgaGVpZ2h0OiBhcnJvd0hlYWQsXHJcbiAgICAgICAgICAgIGFuZ2xlOiA5MCxcclxuICAgICAgICAgICAgZmlsbDogbGFiZWxDb2xvcixcclxuICAgICAgICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgICAgICAgb3JpZ2luWTogXCJjZW50ZXJcIixcclxuICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICB9KVxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcblxyXG4gICAgY29uc3QgZ3JvdXAgPSBuZXcgZmFicmljLkdyb3VwKGVsZW1lbnRzLCB7XHJcbiAgICAgIGxlZnQ6IHgsXHJcbiAgICAgIHRvcDogeSxcclxuICAgICAgaGFzQ29udHJvbHM6IGZhbHNlLFxyXG4gICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgbG9ja1NjYWxpbmdYOiB0cnVlLFxyXG4gICAgICBsb2NrU2NhbGluZ1k6IHRydWUsXHJcbiAgICAgIGxvY2tSb3RhdGlvbjogdHJ1ZSxcclxuICAgICAgbG9ja01vdmVtZW50WDogdHJ1ZSxcclxuICAgICAgbG9ja01vdmVtZW50WTogdHJ1ZSxcclxuICAgICAgZXZlbnRlZDogdHJ1ZSxcclxuICAgICAgaG92ZXJDdXJzb3I6IFwiZGVmYXVsdFwiLFxyXG4gICAgICBhbmdsZTogZWxlbWVudERhdGEuYW5nbGUsXHJcbiAgICAgIHN1YlRhcmdldENoZWNrOiB0cnVlLFxyXG4gICAgfSkgYXMgZmFicmljLkdyb3VwICYge1xyXG4gICAgICBvYmpUeXBlOiBzdHJpbmc7XHJcbiAgICAgIGRhdGE6IGFueTtcclxuICAgIH07XHJcblxyXG4gICAgZ3JvdXAub2JqVHlwZSA9IGVsZW1lbnREYXRhLmVsZW1lbnRUeXBlO1xyXG4gICAgZ3JvdXAuZGF0YSA9IGVsZW1lbnREYXRhO1xyXG5cclxuXHJcbiAgICBjYW52YXMuYWRkKGdyb3VwKTtcclxuXHJcbiAgICAvLyBJZiBuZXdseSBhZGRlZCwgZm9jdXMgaXQgb25jZVxyXG4gICAgaWYgKChlbGVtZW50RGF0YSBhcyBhbnkpPy5uZXdBZGRlZCkge1xyXG4gICAgICB0cnkge1xyXG4gICAgICAgIGNhbnZhcy5zZXRBY3RpdmVPYmplY3QoZ3JvdXApO1xyXG4gICAgICAgIGNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCk7XHJcbiAgICAgIH0gY2F0Y2ggeyB9XHJcbiAgICAgIGRlbGV0ZSAoZWxlbWVudERhdGEgYXMgYW55KS5uZXdBZGRlZDtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gZ3JvdXA7XHJcbiAgfVxyXG5cclxuICBkcmF3RW50cmFuY2UoXHJcbiAgICBjYW52YXM6IGZhYnJpYy5DYW52YXMsXHJcbiAgICB4OiBudW1iZXIsXHJcbiAgICB5OiBudW1iZXIsXHJcbiAgICB3aWR0aDogbnVtYmVyLFxyXG4gICAgaGVpZ2h0OiBudW1iZXIsXHJcbiAgICBhcnJvd1dpZHRoOiBudW1iZXIsXHJcbiAgICBlbGVtZW50RGF0YTogYW55XHJcbiAgKSB7XHJcbiAgICBjb25zdCBib2R5V2lkdGggPSB3aWR0aCAtIGFycm93V2lkdGg7XHJcblxyXG4gICAgY29uc3QgcGF0aERhdGEgPSBbXHJcbiAgICAgIGBNIDAgMGAsXHJcbiAgICAgIGBMICR7Ym9keVdpZHRofSAwYCxcclxuICAgICAgYEwgJHtib2R5V2lkdGh9ICR7LWhlaWdodCAvIDJ9YCxcclxuICAgICAgYEwgJHt3aWR0aH0gJHtoZWlnaHQgLyAyfWAsXHJcbiAgICAgIGBMICR7Ym9keVdpZHRofSAke2hlaWdodCArIGhlaWdodCAvIDJ9YCxcclxuICAgICAgYEwgJHtib2R5V2lkdGh9ICR7aGVpZ2h0fWAsXHJcbiAgICAgIGBMIDAgJHtoZWlnaHR9YCxcclxuICAgICAgYFpgLFxyXG4gICAgXS5qb2luKFwiIFwiKTtcclxuXHJcbiAgICBjb25zdCBhcnJvdyA9IG5ldyBmYWJyaWMuUGF0aChwYXRoRGF0YSwge1xyXG4gICAgICBmaWxsOiBcIiMwM0E5RjRcIixcclxuICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgIGV2ZW50ZWQ6IGZhbHNlLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgbWF4VGV4dEhlaWdodCA9IGhlaWdodCAtIDY7XHJcbiAgICBjb25zdCB0ZXh0ID0gbmV3IGZhYnJpYy5UZXh0KFwiRW50cmFuY2VcIiwge1xyXG4gICAgICBmb250RmFtaWx5OiBcIkFyaWFsXCIsXHJcbiAgICAgIGZvbnRXZWlnaHQ6IFwiYm9sZFwiLFxyXG4gICAgICBmaWxsOiBcIndoaXRlXCIsXHJcbiAgICAgIGFuZ2xlOiAtOTAsXHJcbiAgICAgIG9yaWdpblg6IFwiY2VudGVyXCIsXHJcbiAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgIGxlZnQ6IDE1LFxyXG4gICAgICB0b3A6IGhlaWdodCAvIDIsXHJcbiAgICAgIGZvbnRTaXplOiAyMCxcclxuICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgIGV2ZW50ZWQ6IGZhbHNlLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgdGV4dEJvdW5kcyA9IHRleHQuZ2V0Qm91bmRpbmdSZWN0KCk7XHJcbiAgICBpZiAodGV4dEJvdW5kcy5oZWlnaHQgPiBtYXhUZXh0SGVpZ2h0KSB7XHJcbiAgICAgIGNvbnN0IHNjYWxlID0gbWF4VGV4dEhlaWdodCAvIHRleHRCb3VuZHMuaGVpZ2h0O1xyXG4gICAgICB0ZXh0LnNldChcImZvbnRTaXplXCIsIHRleHQuZm9udFNpemUhICogc2NhbGUpO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGdyb3VwID0gbmV3IGZhYnJpYy5Hcm91cChbYXJyb3csIHRleHRdLCB7XHJcbiAgICAgIGxlZnQ6IHgsXHJcbiAgICAgIHRvcDogeSxcclxuICAgICAgaGFzQ29udHJvbHM6IGZhbHNlLFxyXG4gICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgbG9ja1NjYWxpbmdYOiB0cnVlLFxyXG4gICAgICBsb2NrU2NhbGluZ1k6IHRydWUsXHJcbiAgICAgIGxvY2tTY2FsaW5nRmxpcDogdHJ1ZSxcclxuICAgICAgbG9ja1JvdGF0aW9uOiB0cnVlLFxyXG4gICAgICBsb2NrTW92ZW1lbnRYOiB0cnVlLFxyXG4gICAgICBsb2NrTW92ZW1lbnRZOiB0cnVlLFxyXG4gICAgICBldmVudGVkOiB0cnVlLFxyXG4gICAgICBob3ZlckN1cnNvcjogXCJkZWZhdWx0XCIsXHJcbiAgICAgIGFuZ2xlOiBlbGVtZW50RGF0YS5hbmdsZSxcclxuICAgIH0pIGFzIGZhYnJpYy5Hcm91cCAmIHtcclxuICAgICAgb2JqVHlwZTogc3RyaW5nO1xyXG4gICAgICBkYXRhOiBhbnk7XHJcbiAgICB9O1xyXG5cclxuICAgIGdyb3VwLm9ialR5cGUgPSBlbGVtZW50RGF0YS5lbGVtZW50VHlwZTtcclxuICAgIGdyb3VwLmRhdGEgPSBlbGVtZW50RGF0YTtcclxuXHJcbiAgICBjYW52YXMuYWRkKGdyb3VwKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGRyYXdGaXh0dXJlKFxyXG4gICAgY2FudmFzOiBmYWJyaWMuQ2FudmFzLFxyXG4gICAgeDogbnVtYmVyLFxyXG4gICAgeTogbnVtYmVyLFxyXG4gICAgaGVpZ2h0OiBudW1iZXIsXHJcbiAgICB3aWR0aDogbnVtYmVyLFxyXG4gICAgZml4dHVyZURhdGE6IGFueVxyXG4gICkge1xyXG4gICAgbGV0IGZpeHR1cmVDb2xvcjogYW55O1xyXG4gICAgLy8gaWYgKFtcImZpeHR1cmVcIiwgXCJmaXh0dXJlLXJlZG9cIl0uaW5jbHVkZXModGhpcy5wdWJsaXNoaW5nU3RhdGUpKSB7XHJcbiAgICAvLyAgIGZpeHR1cmVDb2xvciA9IHtcclxuICAgIC8vICAgICBwcmltYXJ5OlxyXG4gICAgLy8gICAgICAgZml4dHVyZURhdGEuc3RhdHVzID09IFwiXCIgJiYgZml4dHVyZURhdGEudGFza1N0YXR1cyA9PSBcInN1Ym1pdFwiXHJcbiAgICAvLyAgICAgICAgID8gXCIjYTVhNmE4XCJcclxuICAgIC8vICAgICAgICAgOiBmaXh0dXJlRGF0YS5zdGF0dXMgPT0gXCJhZ3JlZVwiXHJcbiAgICAvLyAgICAgICAgID8gXCIjNkNFOUE2XCJcclxuICAgIC8vICAgICAgICAgOiBcIiM1MUMxRkZcIixcclxuICAgIC8vICAgICBmaWxsOlxyXG4gICAgLy8gICAgICAgZml4dHVyZURhdGEuc3RhdHVzID09IFwiXCIgJiYgZml4dHVyZURhdGEudGFza1N0YXR1cyA9PSBcInN1Ym1pdFwiXHJcbiAgICAvLyAgICAgICAgID8gXCIjZjNmNGY4XCJcclxuICAgIC8vICAgICAgICAgOiBmaXh0dXJlRGF0YS5zdGF0dXMgPT0gXCJhZ3JlZVwiXHJcbiAgICAvLyAgICAgICAgID8gXCIjNkNFOUE2XCJcclxuICAgIC8vICAgICAgICAgOiBcIiNFQUY4RkZcIixcclxuICAgIC8vICAgICB2bUZpbGw6XHJcbiAgICAvLyAgICAgICBmaXh0dXJlRGF0YS5zdGF0dXMgPT0gXCJcIiAmJiBmaXh0dXJlRGF0YS50YXNrU3RhdHVzID09IFwic3VibWl0XCJcclxuICAgIC8vICAgICAgICAgPyBcIiNhNWE2YThcIlxyXG4gICAgLy8gICAgICAgICA6IFwiIzY5MzhFRlwiLFxyXG4gICAgLy8gICB9O1xyXG4gICAgLy8gfVxyXG4gICAgaWYgKGZpeHR1cmVEYXRhLmZpeHR1cmVOYW1lID09PSBcInNwYWNlXCIpIHJldHVybjtcclxuICAgIGNvbnN0IHJhZGl1cyA9IDU7XHJcbiAgICBjb25zdCBtYWluQ29udGFpbmVyID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgbGVmdDogeCxcclxuICAgICAgdG9wOiB5LFxyXG4gICAgICB3aWR0aDogd2lkdGgsXHJcbiAgICAgIGhlaWdodDogaGVpZ2h0LFxyXG4gICAgICByeDogcmFkaXVzLFxyXG4gICAgICByeTogcmFkaXVzLFxyXG4gICAgICBzdHJva2U6IGZpeHR1cmVDb2xvcj8ucHJpbWFyeSA/PyBcIiM1MUMxRkZcIixcclxuICAgICAgc3Ryb2tlV2lkdGg6IDAuMjcsXHJcbiAgICAgIGZpbGw6IFwid2hpdGVcIixcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IHRvcFdpZHRoID0gd2lkdGggLyAxLjA1O1xyXG4gICAgY29uc3QgdG9wSGVpZ2h0ID0gKDE1IC8gMTAwKSAqIGhlaWdodDtcclxuICAgIGNvbnN0IHRvcFggPSB4ICsgKHdpZHRoIC0gdG9wV2lkdGgpIC8gMjtcclxuICAgIGNvbnN0IHRvcFkgPSB5ICsgdGhpcy52ZXJ0aWNhbE1hcmdpbjtcclxuXHJcbiAgICBjb25zdCB0b3BDb250YWluZXIgPSBuZXcgZmFicmljLlJlY3Qoe1xyXG4gICAgICBsZWZ0OiB0b3BYLFxyXG4gICAgICB0b3A6IHRvcFksXHJcbiAgICAgIHdpZHRoOiB0b3BXaWR0aCxcclxuICAgICAgaGVpZ2h0OiB0b3BIZWlnaHQsXHJcbiAgICAgIHJ4OiByYWRpdXMsXHJcbiAgICAgIHJ5OiByYWRpdXMsXHJcbiAgICAgIHN0cm9rZTogZml4dHVyZUNvbG9yPy5wcmltYXJ5ID8/IFwiIzUxQzFGRlwiLFxyXG4gICAgICBzdHJva2VXaWR0aDogMC4yNyxcclxuICAgICAgZmlsbDogXCJ3aGl0ZVwiLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgaW5uZXJCb3hIZWlnaHQgPSB0b3BIZWlnaHQgLyAyO1xyXG4gICAgY29uc3QgaW5uZXJUb3BCb3ggPSBuZXcgZmFicmljLlBhdGgoXHJcbiAgICAgIGBNICR7dG9wWCArIHJhZGl1c30gJHt0b3BZfSBcclxuICAgICAgICAgICAgICBMICR7dG9wWCArIHRvcFdpZHRoIC0gcmFkaXVzfSAke3RvcFl9IFxyXG4gICAgICAgICAgICAgIFEgJHt0b3BYICsgdG9wV2lkdGh9ICR7dG9wWX0gJHt0b3BYICsgdG9wV2lkdGh9ICR7dG9wWSArIHJhZGl1c30gXHJcbiAgICAgICAgICAgICAgTCAke3RvcFggKyB0b3BXaWR0aH0gJHt0b3BZICsgaW5uZXJCb3hIZWlnaHR9IFxyXG4gICAgICAgICAgICAgIEwgJHt0b3BYfSAke3RvcFkgKyBpbm5lckJveEhlaWdodH0gXHJcbiAgICAgICAgICAgICAgTCAke3RvcFh9ICR7dG9wWSArIHJhZGl1c30gXHJcbiAgICAgICAgICAgICAgUSAke3RvcFh9ICR7dG9wWX0gJHt0b3BYICsgcmFkaXVzfSAke3RvcFl9IFpgLFxyXG4gICAgICB7XHJcbiAgICAgICAgc3Ryb2tlOiBmaXh0dXJlQ29sb3I/LnByaW1hcnkgPz8gXCIjNTFDMUZGXCIsXHJcbiAgICAgICAgc3Ryb2tlV2lkdGg6IDAuMjcsXHJcbiAgICAgICAgZmlsbDogXCJ0cmFuc3BhcmVudFwiLFxyXG4gICAgICB9XHJcbiAgICApO1xyXG5cclxuICAgIGNvbnN0IHRvcFRleHQgPSBuZXcgZmFicmljLlRleHRib3goXHJcbiAgICAgIGBGaXh0dXJlICR7Zml4dHVyZURhdGEuYXNzb2NpYXRlZEVsZW1lbnRGaXh0dXJlTnVtYmVyXHJcbiAgICAgICAgPyBmaXh0dXJlRGF0YS5hc3NvY2lhdGVkRWxlbWVudEZpeHR1cmVOdW1iZXIgK1xyXG4gICAgICAgIChmaXh0dXJlRGF0YT8uZml4dHVyZU51bWJlclxyXG4gICAgICAgICAgPyBcIiAtIEZYLVwiICsgZml4dHVyZURhdGEuZml4dHVyZU51bWJlclxyXG4gICAgICAgICAgOiBcIlwiKVxyXG4gICAgICAgIDogXCJuZXdcIlxyXG4gICAgICB9YCxcclxuICAgICAge1xyXG4gICAgICAgIGxlZnQ6IHRvcFggKyB0b3BXaWR0aCAvIDIsXHJcbiAgICAgICAgdG9wOiB0b3BZICsgaW5uZXJCb3hIZWlnaHQgLyAyLFxyXG4gICAgICAgIGZvbnRTaXplOiA1LFxyXG4gICAgICAgIGZvbnRGYW1pbHk6IFwiSW50ZXJcIixcclxuICAgICAgICBmb250V2VpZ2h0OiBcIjUwMFwiLFxyXG4gICAgICAgIGZpbGw6IFwiIzEwMTgyOFwiLFxyXG4gICAgICAgIG9yaWdpblg6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgb3JpZ2luWTogXCJjZW50ZXJcIixcclxuICAgICAgICB3aWR0aDogdG9wV2lkdGgsXHJcbiAgICAgICAgaGVpZ2h0OiBpbm5lckJveEhlaWdodCxcclxuICAgICAgICB0ZXh0QWxpZ246IFwiY2VudGVyXCIsXHJcbiAgICAgIH1cclxuICAgICk7XHJcblxyXG4gICAgY29uc3Qgc2Vjb25kQm94WSA9IHRvcFkgKyBpbm5lckJveEhlaWdodDtcclxuXHJcbiAgICBjb25zdCBpbm5lckJvdHRvbUJveCA9IG5ldyBmYWJyaWMuUGF0aChcclxuICAgICAgYE0gJHt0b3BYfSAke3NlY29uZEJveFl9IFxyXG4gICAgICAgICAgTCAke3RvcFggKyB0b3BXaWR0aH0gJHtzZWNvbmRCb3hZfSBcclxuICAgICAgICAgIEwgJHt0b3BYICsgdG9wV2lkdGh9ICR7c2Vjb25kQm94WSArIGlubmVyQm94SGVpZ2h0IC0gcmFkaXVzfSBcclxuICAgICAgICAgIFEgJHt0b3BYICsgdG9wV2lkdGh9ICR7c2Vjb25kQm94WSArIGlubmVyQm94SGVpZ2h0fSAke3RvcFggKyB0b3BXaWR0aCAtIHJhZGl1c1xyXG4gICAgICB9ICR7c2Vjb25kQm94WSArIGlubmVyQm94SGVpZ2h0fSBcclxuICAgICAgICAgIEwgJHt0b3BYICsgcmFkaXVzfSAke3NlY29uZEJveFkgKyBpbm5lckJveEhlaWdodH0gXHJcbiAgICAgICAgICBRICR7dG9wWH0gJHtzZWNvbmRCb3hZICsgaW5uZXJCb3hIZWlnaHR9ICR7dG9wWH0gJHtzZWNvbmRCb3hZICsgaW5uZXJCb3hIZWlnaHQgLSByYWRpdXNcclxuICAgICAgfSBcclxuICAgICAgICAgIEwgJHt0b3BYfSAke3NlY29uZEJveFl9IFpgLFxyXG4gICAgICB7XHJcbiAgICAgICAgZmlsbDogXCIjMzQ0MDU0XCIsXHJcbiAgICAgICAgc3Ryb2tlOiBmaXh0dXJlQ29sb3I/LnByaW1hcnkgPz8gXCIjNTFDMUZGXCIsXHJcbiAgICAgICAgc3Ryb2tlV2lkdGg6IDAuMjcsXHJcbiAgICAgIH1cclxuICAgICk7XHJcblxyXG4gICAgbGV0IGZvbnRTaXplID0gNTtcclxuICAgIGxldCBib3R0b21UZXh0O1xyXG5cclxuICAgIGNvbnN0IHRleHRDb250ZW50ID0gYCR7Zml4dHVyZURhdGE/LmZpeHR1cmVOYW1lfSAtICR7Zml4dHVyZURhdGE/LmZpeHR1cmVXaWR0aC52YWx1ZX0gJHtmaXh0dXJlRGF0YT8uZml4dHVyZVdpZHRoLnVuaXR9YDtcclxuXHJcbiAgICBjb25zdCBjcmVhdGVCb3R0b21UZXh0ID0gKGZzOiBhbnkpID0+XHJcbiAgICAgIG5ldyBmYWJyaWMuVGV4dGJveCh0ZXh0Q29udGVudCwge1xyXG4gICAgICAgIGxlZnQ6IHRvcFggKyB0b3BXaWR0aCAvIDIsXHJcbiAgICAgICAgdG9wOiBzZWNvbmRCb3hZICsgaW5uZXJCb3hIZWlnaHQgLyAyLFxyXG4gICAgICAgIGZvbnRTaXplOiBmcyxcclxuICAgICAgICBmb250RmFtaWx5OiBcIkludGVyXCIsXHJcbiAgICAgICAgZm9udFdlaWdodDogXCI1MDBcIixcclxuICAgICAgICBmaWxsOiBcIiNGRkZGRkZcIixcclxuICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgdGV4dEFsaWduOiBcImNlbnRlclwiLFxyXG4gICAgICAgIHdpZHRoOiB0b3BXaWR0aCxcclxuICAgICAgfSk7XHJcblxyXG4gICAgZG8ge1xyXG4gICAgICBib3R0b21UZXh0ID0gY3JlYXRlQm90dG9tVGV4dChmb250U2l6ZSk7XHJcbiAgICAgIGZvbnRTaXplIC09IDAuNTtcclxuICAgIH0gd2hpbGUgKGJvdHRvbVRleHQuaGVpZ2h0ID4gaW5uZXJCb3hIZWlnaHQgJiYgZm9udFNpemUgPiAyKTtcclxuXHJcbiAgICBjb25zdCBtaWRXaWR0aCA9IHdpZHRoIC8gMS4wNTtcclxuICAgIGNvbnN0IG1pZEhlaWdodCA9ICg3NyAvIDEwMCkgKiBoZWlnaHQ7XHJcbiAgICBjb25zdCBtaWRYID0geCArICh3aWR0aCAtIG1pZFdpZHRoKSAvIDI7XHJcbiAgICBjb25zdCBtaWRZID0gdG9wWSArIHRvcEhlaWdodCArIHRoaXMudmVydGljYWxNYXJnaW47XHJcblxyXG4gICAgY29uc3QgbWlkQ29udGFpbmVyID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgbGVmdDogbWlkWCxcclxuICAgICAgdG9wOiBtaWRZLFxyXG4gICAgICB3aWR0aDogbWlkV2lkdGgsXHJcbiAgICAgIGhlaWdodDogbWlkSGVpZ2h0LFxyXG4gICAgICByeDogcmFkaXVzLFxyXG4gICAgICByeTogcmFkaXVzLFxyXG4gICAgICBzdHJva2U6IGZpeHR1cmVDb2xvcj8ucHJpbWFyeSA/PyBcIiM1MUMxRkZcIixcclxuICAgICAgc3Ryb2tlV2lkdGg6IDAuMjcsXHJcbiAgICAgIGZpbGw6IFwid2hpdGVcIixcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IHNoZWxmQ291bnQgPSBmaXh0dXJlRGF0YS5zaGVsZkNvbmZpZz8ubGVuZ3RoO1xyXG4gICAgY29uc3QgYm94SGVpZ2h0ID0gbWlkSGVpZ2h0IC8gKHNoZWxmQ291bnQgKyAyKTtcclxuICAgIGNvbnN0IGZpcnN0Qm94WSA9IG1pZFk7XHJcblxyXG4gICAgY29uc3QgZmlyc3RCb3ggPSBuZXcgZmFicmljLlBhdGgoXHJcbiAgICAgIGBNICR7bWlkWCArIHJhZGl1c30gJHtmaXJzdEJveFl9IFxyXG4gICAgICAgICAgICAgIEwgJHttaWRYICsgbWlkV2lkdGggLSByYWRpdXN9ICR7Zmlyc3RCb3hZfSBcclxuICAgICAgICAgICAgICBRICR7bWlkWCArIG1pZFdpZHRofSAke2ZpcnN0Qm94WX0gJHttaWRYICsgbWlkV2lkdGh9ICR7Zmlyc3RCb3hZICsgcmFkaXVzXHJcbiAgICAgIH0gXHJcbiAgICAgICAgICAgICAgTCAke21pZFggKyBtaWRXaWR0aH0gJHtmaXJzdEJveFkgKyBib3hIZWlnaHR9IFxyXG4gICAgICAgICAgICAgIEwgJHttaWRYfSAke2ZpcnN0Qm94WSArIGJveEhlaWdodH0gXHJcbiAgICAgICAgICAgICAgTCAke21pZFh9ICR7Zmlyc3RCb3hZICsgcmFkaXVzfSBcclxuICAgICAgICAgICAgICBRICR7bWlkWH0gJHtmaXJzdEJveFl9ICR7bWlkWCArIHJhZGl1c30gJHtmaXJzdEJveFl9IFpgLFxyXG4gICAgICB7XHJcbiAgICAgICAgZmlsbDogZml4dHVyZUNvbG9yPy5maWxsXHJcbiAgICAgICAgICA/IGZpeHR1cmVDb2xvcj8uZmlsbFxyXG4gICAgICAgICAgOiBmaXh0dXJlRGF0YS5pc3N1ZVxyXG4gICAgICAgICAgICA/IFwiI0Q5MkQyMFwiXHJcbiAgICAgICAgICAgIDogXCIjRUFGOEZGXCIsXHJcbiAgICAgICAgc3Ryb2tlOiBmaXh0dXJlQ29sb3I/LnByaW1hcnlcclxuICAgICAgICAgID8gZml4dHVyZUNvbG9yPy5wcmltYXJ5XHJcbiAgICAgICAgICA6IGZpeHR1cmVEYXRhLmlzc3VlXHJcbiAgICAgICAgICAgID8gXCIjRDkyRDIwXCJcclxuICAgICAgICAgICAgOiBcIiM2QkNBRkZcIixcclxuICAgICAgICBzdHJva2VXaWR0aDogMC4yNyxcclxuICAgICAgfVxyXG4gICAgKTtcclxuXHJcbiAgICBjb25zdCBmaXJzdEJveFRleHQgPSBuZXcgZmFicmljLlRleHRib3goXHJcbiAgICAgIGAke2ZpeHR1cmVEYXRhPy5oZWFkZXI/LmxhYmVsID8gZml4dHVyZURhdGEuaGVhZGVyLmxhYmVsIDogXCJcIn1gLFxyXG4gICAgICB7XHJcbiAgICAgICAgbGVmdDogbWlkWCArIG1pZFdpZHRoIC8gMixcclxuICAgICAgICB0b3A6IGZpcnN0Qm94WSArIGJveEhlaWdodCAvIDIsXHJcbiAgICAgICAgZm9udFNpemU6IDcsXHJcbiAgICAgICAgZm9udEZhbWlseTogXCJJbnRlclwiLFxyXG4gICAgICAgIGZvbnRXZWlnaHQ6IFwiNjAwXCIsXHJcbiAgICAgICAgZmlsbDogZml4dHVyZURhdGEuaXNzdWUgPyBcIiNmZmZcIiA6IFwiIzEwMTgyOFwiLFxyXG4gICAgICAgIG9yaWdpblg6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgb3JpZ2luWTogXCJjZW50ZXJcIixcclxuICAgICAgICB3aWR0aDogbWlkV2lkdGgsXHJcbiAgICAgICAgaGVpZ2h0OiBib3hIZWlnaHQsXHJcbiAgICAgICAgdGV4dEFsaWduOiBcImNlbnRlclwiLFxyXG4gICAgICB9XHJcbiAgICApO1xyXG5cclxuICAgIGNvbnN0IHNoZWx2ZXM6IGZhYnJpYy5PYmplY3RbXSA9IFtdO1xyXG4gICAgY29uc3Qgc2hlbGZIZWlnaHQgPSBtaWRIZWlnaHQgLSAyICogYm94SGVpZ2h0O1xyXG5cclxuICAgIGlmIChmaXh0dXJlRGF0YS5wcm9kdWN0UmVzb2x1dGlvbkxldmVsID09PSBcIkwxXCIpIHtcclxuICAgICAgY29uc3QgYm94WSA9IGZpcnN0Qm94WSArIGJveEhlaWdodDtcclxuXHJcbiAgICAgIGNvbnN0IHNoZWxmID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgICBsZWZ0OiBtaWRYLFxyXG4gICAgICAgIHRvcDogYm94WSxcclxuICAgICAgICB3aWR0aDogbWlkV2lkdGgsXHJcbiAgICAgICAgaGVpZ2h0OiBzaGVsZkhlaWdodCxcclxuICAgICAgICAvLyBzdHJva2U6ICcjNTFDMUZGJyxcclxuICAgICAgICBzdHJva2U6IGZpeHR1cmVDb2xvcj8ucHJpbWFyeVxyXG4gICAgICAgICAgPyBmaXh0dXJlQ29sb3I/LnByaW1hcnlcclxuICAgICAgICAgIDogZml4dHVyZURhdGEuaXNzdWVcclxuICAgICAgICAgICAgPyBcIiNEOTJEMjBcIlxyXG4gICAgICAgICAgICA6IFwiIzUxQzFGRlwiLFxyXG4gICAgICAgIHN0cm9rZVdpZHRoOiAwLjI3LFxyXG4gICAgICAgIGZpbGw6IFwid2hpdGVcIixcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBjb25zdCB0ZXh0ID0gZml4dHVyZURhdGE/LnByb2R1Y3RCcmFuZE5hbWU/LmpvaW4oXCIgKyBcIikgfHwgXCJcIjtcclxuXHJcbiAgICAgIC8vIFdyYXAgdGV4dCB3aXRoaW4gZml4dHVyZSB3aWR0aCBhbmQgc2hyaW5rIHRvIGZpdCB2ZXJ0aWNhbCBzcGFjZVxyXG4gICAgICBjb25zdCBtYXhUZXh0V2lkdGggPSBtaWRXaWR0aCAqIDAuOTtcclxuICAgICAgY29uc3QgbWF4VGV4dEhlaWdodCA9IHNoZWxmSGVpZ2h0ICogMC44O1xyXG4gICAgICBsZXQgZm9udFNpemVMMSA9IDY7XHJcblxyXG4gICAgICBjb25zdCBjcmVhdGVXcmFwcGVkVGV4dGJveCA9IChmczogbnVtYmVyKSA9PlxyXG4gICAgICAgIG5ldyBmYWJyaWMuVGV4dGJveCh0ZXh0LCB7XHJcbiAgICAgICAgICBsZWZ0OiBtaWRYICsgbWlkV2lkdGggLyAyLFxyXG4gICAgICAgICAgdG9wOiBib3hZICsgc2hlbGZIZWlnaHQgLyAyLFxyXG4gICAgICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgICB3aWR0aDogbWF4VGV4dFdpZHRoLFxyXG4gICAgICAgICAgZm9udFNpemU6IGZzLFxyXG4gICAgICAgICAgZm9udEZhbWlseTogXCJJbnRlclwiLFxyXG4gICAgICAgICAgZm9udFdlaWdodDogXCI1MDBcIixcclxuICAgICAgICAgIHRleHRBbGlnbjogXCJjZW50ZXJcIixcclxuICAgICAgICAgIGZpbGw6IFwiIzMzM1wiLFxyXG4gICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICBldmVudGVkOiBmYWxzZSxcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgIGxldCB3cmFwcGVkVGV4dCA9IGNyZWF0ZVdyYXBwZWRUZXh0Ym94KGZvbnRTaXplTDEpO1xyXG4gICAgICB3aGlsZSAod3JhcHBlZFRleHQuaGVpZ2h0ID4gbWF4VGV4dEhlaWdodCAmJiBmb250U2l6ZUwxID4gMikge1xyXG4gICAgICAgIGZvbnRTaXplTDEgLT0gMC41O1xyXG4gICAgICAgIHdyYXBwZWRUZXh0ID0gY3JlYXRlV3JhcHBlZFRleHRib3goZm9udFNpemVMMSk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IHBhZGRpbmcgPSAyO1xyXG4gICAgICBjb25zdCBiYWNrZ3JvdW5kID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgICBsZWZ0OiBtaWRYICsgbWlkV2lkdGggLyAyLFxyXG4gICAgICAgIHRvcDogYm94WSArIHNoZWxmSGVpZ2h0IC8gMixcclxuICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgd2lkdGg6IE1hdGgubWluKG1heFRleHRXaWR0aCwgd3JhcHBlZFRleHQud2lkdGghKSArIHBhZGRpbmcsXHJcbiAgICAgICAgaGVpZ2h0OiB3cmFwcGVkVGV4dC5nZXRTY2FsZWRIZWlnaHQoKSArIDIsXHJcbiAgICAgICAgZmlsbDogXCJyZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNSlcIixcclxuICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICBldmVudGVkOiBmYWxzZSxcclxuICAgICAgICByeDogMSxcclxuICAgICAgICByeTogMSxcclxuICAgICAgfSk7XHJcblxyXG4gICAgICBzaGVsdmVzLnB1c2goc2hlbGYsIGJhY2tncm91bmQsIHdyYXBwZWRUZXh0KTtcclxuICAgIH0gZWxzZSBpZiAoZml4dHVyZURhdGEucHJvZHVjdFJlc29sdXRpb25MZXZlbCA9PT0gXCJMMlwiKSB7XHJcbiAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2hlbGZDb3VudDsgaSsrKSB7XHJcbiAgICAgICAgY29uc3QgYm94WSA9IGZpcnN0Qm94WSArIGJveEhlaWdodCAqIChpICsgMSk7XHJcblxyXG4gICAgICAgIGNvbnN0IHNoZWxmID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgICAgIGxlZnQ6IG1pZFgsXHJcbiAgICAgICAgICB0b3A6IGJveFksXHJcbiAgICAgICAgICB3aWR0aDogbWlkV2lkdGgsXHJcbiAgICAgICAgICBoZWlnaHQ6IGJveEhlaWdodCxcclxuICAgICAgICAgIHN0cm9rZTogZml4dHVyZUNvbG9yPy5wcmltYXJ5XHJcbiAgICAgICAgICAgID8gZml4dHVyZUNvbG9yPy5wcmltYXJ5XHJcbiAgICAgICAgICAgIDogZml4dHVyZURhdGEuaXNzdWVcclxuICAgICAgICAgICAgICA/IFwiI0Q5MkQyMFwiXHJcbiAgICAgICAgICAgICAgOiBcIiM1MUMxRkZcIixcclxuICAgICAgICAgIHN0cm9rZVdpZHRoOiAwLjI3LFxyXG4gICAgICAgICAgZmlsbDogXCJ3aGl0ZVwiLFxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICBzaGVsdmVzLnB1c2goc2hlbGYpO1xyXG5cclxuICAgICAgICBpZiAoZml4dHVyZURhdGEuc2hlbGZDb25maWc/LltpXS5zaGVsZlR5cGUgPT09IFwidHJheVwiKSB7XHJcbiAgICAgICAgICBjb25zdCB0cmF5Um93cyA9IGZpeHR1cmVEYXRhLnNoZWxmQ29uZmlnPy5baV0udHJheVJvd3MgfHwgMTtcclxuICAgICAgICAgIGNvbnN0IHJvd1NwYWNpbmcgPSBib3hIZWlnaHQgLyB0cmF5Um93cztcclxuXHJcbiAgICAgICAgICBmb3IgKGxldCByID0gMTsgciA8IHRyYXlSb3dzOyByKyspIHtcclxuICAgICAgICAgICAgY29uc3QgbGluZVkgPSBib3hZICsgciAqIHJvd1NwYWNpbmc7XHJcblxyXG4gICAgICAgICAgICBjb25zdCB0cmF5TGluZSA9IG5ldyBmYWJyaWMuTGluZShcclxuICAgICAgICAgICAgICBbbWlkWCwgbGluZVksIG1pZFggKyBtaWRXaWR0aCwgbGluZVldLFxyXG4gICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIHN0cm9rZTogXCIjOTk5XCIsXHJcbiAgICAgICAgICAgICAgICBzdHJva2VXaWR0aDogMC4yLFxyXG4gICAgICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICBldmVudGVkOiBmYWxzZSxcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICBzaGVsdmVzLnB1c2godHJheUxpbmUpO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgdGV4dCA9XHJcbiAgICAgICAgICBmaXh0dXJlRGF0YS5zaGVsZkNvbmZpZz8uW2ldLnByb2R1Y3RCcmFuZE5hbWU/LmpvaW4oXCIgKyBcIikgfHwgXCJcIjtcclxuXHJcbiAgICAgICAgLy8gTDI6IFNpbmdsZS1saW5lIGVsbGlwc2lzIGFnYWluc3QgZnVsbCBzaGVsZiB3aWR0aFxyXG4gICAgICAgIGNvbnN0IGhvcml6b250YWxQYWRkaW5nID0gNjtcclxuICAgICAgICBjb25zdCBtYXhUZXh0V2lkdGggPSBNYXRoLm1heCgwLCBtaWRXaWR0aCAtIGhvcml6b250YWxQYWRkaW5nKTtcclxuICAgICAgICBjb25zdCBtYXhUZXh0SGVpZ2h0ID0gYm94SGVpZ2h0ICogMC44O1xyXG4gICAgICAgIGNvbnN0IGJhc2VGb250U2l6ZSA9IDU7XHJcblxyXG4gICAgICAgIGNvbnN0IG1lYXN1cmUgPSAodDogc3RyaW5nKSA9PlxyXG4gICAgICAgICAgbmV3IGZhYnJpYy5UZXh0KHQsIHtcclxuICAgICAgICAgICAgZm9udFNpemU6IGJhc2VGb250U2l6ZSxcclxuICAgICAgICAgICAgZm9udEZhbWlseTogXCJJbnRlclwiLFxyXG4gICAgICAgICAgICBmb250V2VpZ2h0OiBcIjUwMFwiLFxyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIGxldCBkaXNwbGF5VGV4dCA9IHRleHQ7XHJcbiAgICAgICAgbGV0IG1lYXN1cmVkID0gbWVhc3VyZShkaXNwbGF5VGV4dCk7XHJcblxyXG4gICAgICAgIGlmICgobWVhc3VyZWQud2lkdGggPz8gMCkgPiBtYXhUZXh0V2lkdGgpIHtcclxuICAgICAgICAgIGNvbnN0IGVsbGlwc2lzID0gXCIuLi5cIjtcclxuICAgICAgICAgIGxldCBsZWZ0SWR4ID0gMDtcclxuICAgICAgICAgIGxldCByaWdodElkeCA9IHRleHQubGVuZ3RoO1xyXG5cclxuICAgICAgICAgIHdoaWxlIChsZWZ0SWR4IDwgcmlnaHRJZHgpIHtcclxuICAgICAgICAgICAgY29uc3QgbWlkSWR4ID0gTWF0aC5mbG9vcigobGVmdElkeCArIHJpZ2h0SWR4KSAvIDIpO1xyXG4gICAgICAgICAgICBjb25zdCBjYW5kaWRhdGUgPSB0ZXh0LnNsaWNlKDAsIG1pZElkeCkgKyBlbGxpcHNpcztcclxuICAgICAgICAgICAgbWVhc3VyZWQgPSBtZWFzdXJlKGNhbmRpZGF0ZSk7XHJcbiAgICAgICAgICAgIGlmICgobWVhc3VyZWQud2lkdGggPz8gMCkgPiBtYXhUZXh0V2lkdGgpIHtcclxuICAgICAgICAgICAgICByaWdodElkeCA9IG1pZElkeDtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICBsZWZ0SWR4ID0gbWlkSWR4ICsgMTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgfVxyXG4gICAgICAgICAgZGlzcGxheVRleHQgPSB0ZXh0LnNsaWNlKDAsIE1hdGgubWF4KDAsIGxlZnRJZHggLSAxKSkgKyBlbGxpcHNpcztcclxuICAgICAgICAgIG1lYXN1cmVkID0gbWVhc3VyZShkaXNwbGF5VGV4dCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBiYWNrZ3JvdW5kID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgICAgIGxlZnQ6IG1pZFggKyBtaWRXaWR0aCAvIDIsXHJcbiAgICAgICAgICB0b3A6IGJveFkgKyBib3hIZWlnaHQgLyAyLFxyXG4gICAgICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgICB3aWR0aDogbWlkV2lkdGgsXHJcbiAgICAgICAgICBoZWlnaHQ6IE1hdGgubWluKG1heFRleHRIZWlnaHQsIG1lYXN1cmVkLmhlaWdodCA/PyAxMCkgKyAyLFxyXG4gICAgICAgICAgZmlsbDogXCJyZ2JhKDI1NSwgMjU1LCAyNTUsIDAuNSlcIixcclxuICAgICAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgZXZlbnRlZDogZmFsc2UsXHJcbiAgICAgICAgICByeDogMSxcclxuICAgICAgICAgIHJ5OiAxLFxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICBjb25zdCBmaW5hbFRleHQgPSBuZXcgZmFicmljLlRleHQoZGlzcGxheVRleHQsIHtcclxuICAgICAgICAgIGxlZnQ6IG1pZFggKyBtaWRXaWR0aCAvIDIsXHJcbiAgICAgICAgICB0b3A6IGJveFkgKyBib3hIZWlnaHQgLyAyLFxyXG4gICAgICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgICBmb250U2l6ZTogYmFzZUZvbnRTaXplLFxyXG4gICAgICAgICAgZm9udEZhbWlseTogXCJJbnRlclwiLFxyXG4gICAgICAgICAgZm9udFdlaWdodDogXCI1MDBcIixcclxuICAgICAgICAgIGZpbGw6IFwiIzMzM1wiLFxyXG4gICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICBldmVudGVkOiBmYWxzZSxcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgc2hlbHZlcy5wdXNoKGJhY2tncm91bmQsIGZpbmFsVGV4dCk7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSBpZiAoZml4dHVyZURhdGEucHJvZHVjdFJlc29sdXRpb25MZXZlbCA9PT0gXCJMM1wiKSB7XHJcbiAgICAgIGNvbnN0IHNlcXVlbnRpYWxHcm91cHM6IHsgem9uZTogc3RyaW5nOyBzaGVsdmVzOiBhbnlbXSB9W10gPSBbXTtcclxuXHJcbiAgICAgIGxldCBwcmV2aW91c1pvbmU6IHN0cmluZyB8IG51bGwgPSBudWxsO1xyXG5cclxuICAgICAgZm9yIChjb25zdCBzaGVsZiBvZiBmaXh0dXJlRGF0YS5zaGVsZkNvbmZpZykge1xyXG4gICAgICAgIGNvbnN0IHpvbmUgPSBzaGVsZi56b25lIHx8IFwiVW5rbm93blwiO1xyXG4gICAgICAgIGlmICh6b25lICE9PSBwcmV2aW91c1pvbmUpIHtcclxuICAgICAgICAgIHNlcXVlbnRpYWxHcm91cHMucHVzaCh7IHpvbmUsIHNoZWx2ZXM6IFtzaGVsZl0gfSk7XHJcbiAgICAgICAgICBwcmV2aW91c1pvbmUgPSB6b25lO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBzZXF1ZW50aWFsR3JvdXBzW3NlcXVlbnRpYWxHcm91cHMubGVuZ3RoIC0gMV0uc2hlbHZlcy5wdXNoKHNoZWxmKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGxldCBjdXJyZW50U2hlbGZJbmRleCA9IDA7XHJcblxyXG4gICAgICBmb3IgKGNvbnN0IGdyb3VwIG9mIHNlcXVlbnRpYWxHcm91cHMpIHtcclxuICAgICAgICBjb25zdCB7IHpvbmUsIHNoZWx2ZXM6IHNoZWx2ZXNJbkdyb3VwIH0gPSBncm91cDtcclxuXHJcbiAgICAgICAgY29uc3QgZ3JvdXBTdGFydEluZGV4ID0gY3VycmVudFNoZWxmSW5kZXg7XHJcbiAgICAgICAgY29uc3QgZ3JvdXBMZW5ndGggPSBzaGVsdmVzSW5Hcm91cC5sZW5ndGg7XHJcblxyXG4gICAgICAgIGNvbnN0IGdyb3VwVG9wWSA9IGZpcnN0Qm94WSArIGJveEhlaWdodCAqIChncm91cFN0YXJ0SW5kZXggKyAxKTtcclxuICAgICAgICBjb25zdCBncm91cEJvdHRvbVkgPSBncm91cFRvcFkgKyBib3hIZWlnaHQgKiBncm91cExlbmd0aDtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBzaGVsdmVzSW5Hcm91cC5sZW5ndGg7IGorKykge1xyXG4gICAgICAgICAgY29uc3Qgc2hlbGZEYXRhID0gc2hlbHZlc0luR3JvdXBbal07XHJcbiAgICAgICAgICBjb25zdCBib3hZID0gZmlyc3RCb3hZICsgYm94SGVpZ2h0ICogKGN1cnJlbnRTaGVsZkluZGV4ICsgMSk7XHJcblxyXG4gICAgICAgICAgY29uc3Qgc2hlbGZSZWN0ID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgICAgICAgbGVmdDogbWlkWCxcclxuICAgICAgICAgICAgdG9wOiBib3hZLFxyXG4gICAgICAgICAgICB3aWR0aDogbWlkV2lkdGgsXHJcbiAgICAgICAgICAgIGhlaWdodDogYm94SGVpZ2h0LFxyXG4gICAgICAgICAgICBzdHJva2U6IGZpeHR1cmVDb2xvcj8ucHJpbWFyeVxyXG4gICAgICAgICAgICAgID8gZml4dHVyZUNvbG9yPy5wcmltYXJ5XHJcbiAgICAgICAgICAgICAgOiBmaXh0dXJlRGF0YS5pc3N1ZVxyXG4gICAgICAgICAgICAgICAgPyBcIiNEOTJEMjBcIlxyXG4gICAgICAgICAgICAgICAgOiBcIiM1MUMxRkZcIixcclxuICAgICAgICAgICAgc3Ryb2tlV2lkdGg6IDAuMjcsXHJcbiAgICAgICAgICAgIGZpbGw6IFwid2hpdGVcIixcclxuICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgIHNoZWx2ZXMucHVzaChzaGVsZlJlY3QpO1xyXG5cclxuICAgICAgICAgIGlmIChzaGVsZkRhdGEuc2hlbGZUeXBlID09PSBcInRyYXlcIikge1xyXG4gICAgICAgICAgICBjb25zdCB0cmF5Um93cyA9IHNoZWxmRGF0YS50cmF5Um93cyB8fCAwO1xyXG4gICAgICAgICAgICBjb25zdCBwcm9kdWN0UGVyU2hlbGYgPSBzaGVsZkRhdGEucHJvZHVjdFBlclNoZWxmIHx8IDA7XHJcblxyXG4gICAgICAgICAgICBjb25zdCByb3dTcGFjaW5nID0gYm94SGVpZ2h0IC8gdHJheVJvd3M7XHJcbiAgICAgICAgICAgIGNvbnN0IGNvbHVtblNwYWNpbmcgPSBtaWRXaWR0aCAvIHByb2R1Y3RQZXJTaGVsZjtcclxuXHJcbiAgICAgICAgICAgIGZvciAobGV0IHIgPSAxOyByIDwgdHJheVJvd3M7IHIrKykge1xyXG4gICAgICAgICAgICAgIGNvbnN0IGxpbmVZID0gYm94WSArIHIgKiByb3dTcGFjaW5nO1xyXG5cclxuICAgICAgICAgICAgICBjb25zdCB0cmF5TGluZSA9IG5ldyBmYWJyaWMuTGluZShcclxuICAgICAgICAgICAgICAgIFttaWRYLCBsaW5lWSwgbWlkWCArIG1pZFdpZHRoLCBsaW5lWV0sXHJcbiAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgIHN0cm9rZTogXCIjOTk5XCIsXHJcbiAgICAgICAgICAgICAgICAgIHN0cm9rZVdpZHRoOiAwLjIsXHJcbiAgICAgICAgICAgICAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgICBldmVudGVkOiBmYWxzZSxcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgICAgICBzaGVsdmVzLnB1c2godHJheUxpbmUpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBmb3IgKGxldCBjID0gMTsgYyA8IHByb2R1Y3RQZXJTaGVsZjsgYysrKSB7XHJcbiAgICAgICAgICAgICAgY29uc3QgbGluZVggPSBtaWRYICsgYyAqIGNvbHVtblNwYWNpbmc7XHJcblxyXG4gICAgICAgICAgICAgIGNvbnN0IHZlcnRpY2FsTGluZSA9IG5ldyBmYWJyaWMuTGluZShcclxuICAgICAgICAgICAgICAgIFtsaW5lWCwgYm94WSwgbGluZVgsIGJveFkgKyBib3hIZWlnaHRdLFxyXG4gICAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgICBzdHJva2U6IFwiIzk5OVwiLFxyXG4gICAgICAgICAgICAgICAgICBzdHJva2VXaWR0aDogMC4yLFxyXG4gICAgICAgICAgICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICAgICAgICAgICAgZXZlbnRlZDogZmFsc2UsXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgICAgc2hlbHZlcy5wdXNoKHZlcnRpY2FsTGluZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICBjdXJyZW50U2hlbGZJbmRleCsrO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgZ3JvdXBCb3R0b21MaW5lID0gbmV3IGZhYnJpYy5MaW5lKFxyXG4gICAgICAgICAgW21pZFgsIGdyb3VwQm90dG9tWSwgbWlkWCArIG1pZFdpZHRoLCBncm91cEJvdHRvbVldLFxyXG4gICAgICAgICAge1xyXG4gICAgICAgICAgICBzdHJva2U6IGZpeHR1cmVDb2xvcj8ucHJpbWFyeVxyXG4gICAgICAgICAgICAgID8gZml4dHVyZUNvbG9yPy5wcmltYXJ5XHJcbiAgICAgICAgICAgICAgOiBmaXh0dXJlRGF0YS5pc3N1ZVxyXG4gICAgICAgICAgICAgICAgPyBcIiNEOTJEMjBcIlxyXG4gICAgICAgICAgICAgICAgOiBcIiM1MUMxRkZcIixcclxuICAgICAgICAgICAgc3Ryb2tlV2lkdGg6IDEsXHJcbiAgICAgICAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgICBldmVudGVkOiBmYWxzZSxcclxuICAgICAgICAgIH1cclxuICAgICAgICApO1xyXG5cclxuICAgICAgICBzaGVsdmVzLnB1c2goZ3JvdXBCb3R0b21MaW5lKTtcclxuXHJcbiAgICAgICAgaWYgKGZpeHR1cmVEYXRhLmZpeHR1cmVUeXBlID09PSBcIndhbGxcIikge1xyXG4gICAgICAgICAgY29uc3QgbGFiZWxQYWRkaW5nID0gMjtcclxuICAgICAgICAgIGNvbnN0IGxhYmVsVGV4dCA9IG5ldyBmYWJyaWMuVGV4dGJveCh6b25lLCB7XHJcbiAgICAgICAgICAgIGxlZnQ6IG1pZFggKyBtaWRXaWR0aCAtIGxhYmVsUGFkZGluZyxcclxuICAgICAgICAgICAgdG9wOiBncm91cEJvdHRvbVksXHJcbiAgICAgICAgICAgIGZvbnRTaXplOiA1LFxyXG4gICAgICAgICAgICBmb250RmFtaWx5OiBcIkludGVyXCIsXHJcbiAgICAgICAgICAgIGZvbnRXZWlnaHQ6IFwiNjAwXCIsXHJcbiAgICAgICAgICAgIGZpbGw6IFwiIzcwNzA3MFwiLFxyXG4gICAgICAgICAgICBvcmlnaW5YOiBcInJpZ2h0XCIsXHJcbiAgICAgICAgICAgIG9yaWdpblk6IFwiYm90dG9tXCIsXHJcbiAgICAgICAgICAgIHdpZHRoOiBtaWRXaWR0aCAvIDIsXHJcbiAgICAgICAgICAgIHRleHRBbGlnbjogXCJyaWdodFwiLFxyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgc2hlbHZlcy5wdXNoKGxhYmVsVGV4dCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBncm91cENlbnRlclggPSBtaWRYICsgbWlkV2lkdGggLyAyO1xyXG4gICAgICAgIGNvbnN0IGdyb3VwQ2VudGVyWSA9IGdyb3VwVG9wWSArIChncm91cEJvdHRvbVkgLSBncm91cFRvcFkpIC8gMjtcclxuXHJcbiAgICAgICAgY29uc3Qgc2VjdGlvbkJyYW5kcyA9IG5ldyBTZXQoKTtcclxuXHJcbiAgICAgICAgc2hlbHZlc0luR3JvdXA/LmZvckVhY2goKHNoZWxmKSA9PiB7XHJcbiAgICAgICAgICBzaGVsZi5wcm9kdWN0QnJhbmROYW1lPy5mb3JFYWNoKChicmFuZDogc3RyaW5nKSA9PiB7XHJcbiAgICAgICAgICAgIHNlY3Rpb25CcmFuZHMuYWRkKGJyYW5kKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICBpZiAoWy4uLnNlY3Rpb25CcmFuZHNdLmxlbmd0aCkge1xyXG4gICAgICAgICAgY29uc3QgdGV4dCA9IFsuLi5zZWN0aW9uQnJhbmRzXS5qb2luKFwiICsgXCIpO1xyXG4gICAgICAgICAgY29uc3QgcGFkZGluZyA9IDI7XHJcbiAgICAgICAgICBjb25zdCBtYXhUZXh0V2lkdGggPSBtaWRXaWR0aDtcclxuICAgICAgICAgIGNvbnN0IHJlY3RXaWR0aCA9IG1pZFdpZHRoICogMC45O1xyXG4gICAgICAgICAgY29uc3QgbWF4VGV4dEhlaWdodCA9IDIwO1xyXG5cclxuICAgICAgICAgIGxldCBmb250U2l6ZSA9IDY7XHJcbiAgICAgICAgICBsZXQgd3JhcHBlZFRleHQ7XHJcblxyXG4gICAgICAgICAgY29uc3QgY3JlYXRlVGV4dGJveCA9IChmczogYW55KSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiBuZXcgZmFicmljLlRleHRib3godGV4dCwge1xyXG4gICAgICAgICAgICAgIGZvbnRTaXplOiBmcyxcclxuICAgICAgICAgICAgICBmb250RmFtaWx5OiBcIkludGVyXCIsXHJcbiAgICAgICAgICAgICAgZm9udFdlaWdodDogXCI0MDBcIixcclxuICAgICAgICAgICAgICB3aWR0aDogbWF4VGV4dFdpZHRoLFxyXG4gICAgICAgICAgICAgIHRleHRBbGlnbjogXCJjZW50ZXJcIixcclxuICAgICAgICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgICAgICAgZmlsbDogXCIjMTAxODI4XCIsXHJcbiAgICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgICAgZXZlbnRlZDogZmFsc2UsXHJcbiAgICAgICAgICAgICAgbGVmdDogZ3JvdXBDZW50ZXJYLFxyXG4gICAgICAgICAgICAgIHRvcDogZ3JvdXBDZW50ZXJZLFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgZG8ge1xyXG4gICAgICAgICAgICB3cmFwcGVkVGV4dCA9IGNyZWF0ZVRleHRib3goZm9udFNpemUpO1xyXG4gICAgICAgICAgICBmb250U2l6ZSAtPSAwLjU7XHJcbiAgICAgICAgICB9IHdoaWxlICh3cmFwcGVkVGV4dC5oZWlnaHQgPiBtYXhUZXh0SGVpZ2h0ICYmIGZvbnRTaXplID4gMik7XHJcblxyXG4gICAgICAgICAgY29uc3QgcmVjdEhlaWdodCA9IHdyYXBwZWRUZXh0LmdldFNjYWxlZEhlaWdodCgpICsgcGFkZGluZztcclxuXHJcbiAgICAgICAgICBjb25zdCBncm91cENlbnRlclRleHQgPSBuZXcgZmFicmljLlJlY3Qoe1xyXG4gICAgICAgICAgICBsZWZ0OiBncm91cENlbnRlclgsXHJcbiAgICAgICAgICAgIHRvcDogZ3JvdXBDZW50ZXJZLFxyXG4gICAgICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgICB3aWR0aDogcmVjdFdpZHRoLFxyXG4gICAgICAgICAgICBoZWlnaHQ6IHJlY3RIZWlnaHQsXHJcbiAgICAgICAgICAgIGZpbGw6IFwicmdiYSgyNTUsIDI1NSwgMjU1LCAwLjUpXCIsXHJcbiAgICAgICAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgICBldmVudGVkOiBmYWxzZSxcclxuICAgICAgICAgICAgcng6IDEsXHJcbiAgICAgICAgICAgIHJ5OiAxLFxyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgc2hlbHZlcy5wdXNoKGdyb3VwQ2VudGVyVGV4dCwgd3JhcHBlZFRleHQpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmIChmaXh0dXJlRGF0YT8udm1Db25maWc/Lmxlbmd0aCkge1xyXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGZpeHR1cmVEYXRhLnZtQ29uZmlnLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgY29uc3Qgdm0gPSBmaXh0dXJlRGF0YS52bUNvbmZpZ1tpXTtcclxuXHJcbiAgICAgICAgY29uc3Qgc3RhcnRJbmRleCA9IHZtLnN0YXJ0WVBvc2l0aW9uIC0gMTtcclxuICAgICAgICBjb25zdCBlbmRJbmRleCA9IHZtLmVuZFlQb3NpdGlvbiAtIDE7XHJcblxyXG4gICAgICAgIGNvbnN0IHNoZWxmVG9wWSA9IGZpcnN0Qm94WSArIGJveEhlaWdodCAqIChzdGFydEluZGV4ICsgMSk7XHJcbiAgICAgICAgY29uc3Qgc2hlbGZIZWlnaHRTcGFuID0gYm94SGVpZ2h0ICogKGVuZEluZGV4IC0gc3RhcnRJbmRleCArIDEpO1xyXG5cclxuICAgICAgICBsZXQgdm1IZWlnaHRQeDogbnVtYmVyID0gc2hlbGZIZWlnaHRTcGFuO1xyXG4gICAgICAgIGxldCB5OiBudW1iZXIgPSBzaGVsZlRvcFk7XHJcblxyXG4gICAgICAgIGlmICh2bS55Wm9uZSAmJiB2bS55Wm9uZSAhPT0gXCJzdHJldGNoXCIpIHtcclxuICAgICAgICAgIHZtSGVpZ2h0UHggPSBzaGVsZkhlaWdodFNwYW4gLyAzO1xyXG5cclxuICAgICAgICAgIHN3aXRjaCAodm0ueVpvbmUpIHtcclxuICAgICAgICAgICAgY2FzZSBcInRvcFwiOlxyXG4gICAgICAgICAgICAgIHkgPSBzaGVsZlRvcFk7XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGNhc2UgXCJtaWRkbGVcIjpcclxuICAgICAgICAgICAgICB5ID0gc2hlbGZUb3BZICsgdm1IZWlnaHRQeDtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSBcImJvdHRvbVwiOlxyXG4gICAgICAgICAgICAgIHkgPSBzaGVsZlRvcFkgKyAyICogdm1IZWlnaHRQeDtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICB5ID0gc2hlbGZUb3BZO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IHggPSBtaWRYO1xyXG4gICAgICAgIGxldCB3aWR0aCA9IG1pZFdpZHRoO1xyXG5cclxuICAgICAgICBpZiAoIXZtLnhab25lIHx8IHZtLnhab25lID09PSBcInN0cmV0Y2hcIikge1xyXG4gICAgICAgICAgd2lkdGggPSBtaWRXaWR0aDtcclxuICAgICAgICAgIHggPSBtaWRYO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICBjb25zdCBzZWN0aW9uV2lkdGggPSBtaWRXaWR0aCAvIDM7XHJcbiAgICAgICAgICBzd2l0Y2ggKHZtLnhab25lKSB7XHJcbiAgICAgICAgICAgIGNhc2UgXCJsZWZ0XCI6XHJcbiAgICAgICAgICAgICAgd2lkdGggPSBzZWN0aW9uV2lkdGg7XHJcbiAgICAgICAgICAgICAgeCA9IG1pZFg7XHJcbiAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIGNhc2UgXCJtaWRkbGVcIjpcclxuICAgICAgICAgICAgICB3aWR0aCA9IHNlY3Rpb25XaWR0aDtcclxuICAgICAgICAgICAgICB4ID0gbWlkWCArIHNlY3Rpb25XaWR0aDtcclxuICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgY2FzZSBcInJpZ2h0XCI6XHJcbiAgICAgICAgICAgICAgd2lkdGggPSBzZWN0aW9uV2lkdGg7XHJcbiAgICAgICAgICAgICAgeCA9IG1pZFggKyAyICogc2VjdGlvbldpZHRoO1xyXG4gICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgIHdpZHRoID0gbWlkV2lkdGg7XHJcbiAgICAgICAgICAgICAgeCA9IG1pZFg7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodm0udm1JbWFnZVVybCkge1xyXG4gICAgICAgICAgdHJ5IHtcclxuICAgICAgICAgICAgY29uc3Qgdm1JbWFnZTogYW55ID0gYXdhaXQgZmFicmljLkZhYnJpY0ltYWdlLmZyb21VUkwoXHJcbiAgICAgICAgICAgICAgYCR7dGhpcy5jZG5Vcmx9JHt2bS52bUltYWdlVXJsfT92PSR7RGF0ZS5ub3coKX1gLFxyXG4gICAgICAgICAgICAgIHtcclxuICAgICAgICAgICAgICAgIGNyb3NzT3JpZ2luOiBcImFub255bW91c1wiLFxyXG4gICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgIHZtSW1hZ2Uuc2V0KHtcclxuICAgICAgICAgICAgICBsZWZ0OiB4ICsgd2lkdGggLyAyLFxyXG4gICAgICAgICAgICAgIHRvcDogeSArIHZtSGVpZ2h0UHggLyAyLFxyXG4gICAgICAgICAgICAgIG9yaWdpblg6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgICAgICAgb3JpZ2luWTogXCJjZW50ZXJcIixcclxuICAgICAgICAgICAgICBzY2FsZVg6IHdpZHRoIC8gdm1JbWFnZS53aWR0aCEsXHJcbiAgICAgICAgICAgICAgc2NhbGVZOiB2bUhlaWdodFB4IC8gdm1JbWFnZS5oZWlnaHQhLFxyXG4gICAgICAgICAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgICAgIGV2ZW50ZWQ6IGZhbHNlLFxyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIHNoZWx2ZXMucHVzaCh2bUltYWdlKTtcclxuICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xyXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGBFcnJvciBsb2FkaW5nIGltYWdlIGZvciBWTTogJHt2bS52bUltYWdlVXJsfWAsIGVycik7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgIGNvbnN0IHZtQm94ID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgICAgICAgbGVmdDogeCxcclxuICAgICAgICAgICAgdG9wOiB5LFxyXG4gICAgICAgICAgICB3aWR0aCxcclxuICAgICAgICAgICAgaGVpZ2h0OiB2bUhlaWdodFB4LFxyXG4gICAgICAgICAgICBmaWxsOiBmaXh0dXJlQ29sb3I/LnZtRmlsbCA/PyBcIiM2OTM4RUZcIixcclxuICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgIGV2ZW50ZWQ6IGZhbHNlLFxyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgbGV0IGZvbnRTaXplID0gNTtcclxuICAgICAgICAgIGxldCB2bVRleHQ7XHJcblxyXG4gICAgICAgICAgY29uc3QgY3JlYXRlVm1UZXh0ID0gKGZzOiBudW1iZXIpID0+XHJcbiAgICAgICAgICAgIG5ldyBmYWJyaWMuVGV4dGJveCh2bS52bU5hbWUgfHwgXCJcIiwge1xyXG4gICAgICAgICAgICAgIGxlZnQ6IHggKyB3aWR0aCAvIDIsXHJcbiAgICAgICAgICAgICAgdG9wOiB5ICsgdm1IZWlnaHRQeCAvIDIsXHJcbiAgICAgICAgICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgICAgICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgICAgIGZvbnRTaXplOiBmcyxcclxuICAgICAgICAgICAgICBmb250RmFtaWx5OiBcIkludGVyXCIsXHJcbiAgICAgICAgICAgICAgZm9udFdlaWdodDogXCI2MDBcIixcclxuICAgICAgICAgICAgICBmaWxsOiBcIndoaXRlXCIsXHJcbiAgICAgICAgICAgICAgdGV4dEFsaWduOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgICAgIHdpZHRoOiB3aWR0aCxcclxuICAgICAgICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICAgICAgICBldmVudGVkOiBmYWxzZSxcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgZG8ge1xyXG4gICAgICAgICAgICB2bVRleHQgPSBjcmVhdGVWbVRleHQoZm9udFNpemUpO1xyXG4gICAgICAgICAgICBmb250U2l6ZSAtPSAwLjU7XHJcbiAgICAgICAgICB9IHdoaWxlICh2bVRleHQuaGVpZ2h0ID4gdm1IZWlnaHRQeCAmJiBmb250U2l6ZSA+IDIpO1xyXG5cclxuICAgICAgICAgIHNoZWx2ZXMucHVzaCh2bUJveCwgdm1UZXh0KTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBsYXN0Qm94WSA9IGZpcnN0Qm94WSArIGJveEhlaWdodCAqIChzaGVsZkNvdW50ICsgMSk7XHJcbiAgICBjb25zdCBsYXN0Qm94ID0gbmV3IGZhYnJpYy5QYXRoKFxyXG4gICAgICBgTSAke21pZFh9ICR7bGFzdEJveFl9IFxyXG4gICAgICAgICAgICAgIEwgJHttaWRYICsgbWlkV2lkdGh9ICR7bGFzdEJveFl9IFxyXG4gICAgICAgICAgICAgIEwgJHttaWRYICsgbWlkV2lkdGh9ICR7bGFzdEJveFkgKyBib3hIZWlnaHQgLSByYWRpdXN9IFxyXG4gICAgICAgICAgICAgIFEgJHttaWRYICsgbWlkV2lkdGh9ICR7bGFzdEJveFkgKyBib3hIZWlnaHR9ICR7bWlkWCArIG1pZFdpZHRoIC0gcmFkaXVzXHJcbiAgICAgIH0gJHtsYXN0Qm94WSArIGJveEhlaWdodH0gXHJcbiAgICAgICAgICAgICAgTCAke21pZFggKyByYWRpdXN9ICR7bGFzdEJveFkgKyBib3hIZWlnaHR9IFxyXG4gICAgICAgICAgICAgIFEgJHttaWRYfSAke2xhc3RCb3hZICsgYm94SGVpZ2h0fSAke21pZFh9ICR7bGFzdEJveFkgKyBib3hIZWlnaHQgLSByYWRpdXNcclxuICAgICAgfSBcclxuICAgICAgICAgICAgICBMICR7bWlkWH0gJHtsYXN0Qm94WX0gWmAsXHJcbiAgICAgIHtcclxuICAgICAgICBmaWxsOiBmaXh0dXJlQ29sb3I/LmZpbGxcclxuICAgICAgICAgID8gZml4dHVyZUNvbG9yPy5maWxsXHJcbiAgICAgICAgICA6IGZpeHR1cmVEYXRhLmlzc3VlXHJcbiAgICAgICAgICAgID8gXCIjRkVFNEUyXCJcclxuICAgICAgICAgICAgOiBcIiNFQUY4RkZcIixcclxuICAgICAgICBzdHJva2U6IGZpeHR1cmVDb2xvcj8ucHJpbWFyeVxyXG4gICAgICAgICAgPyBmaXh0dXJlQ29sb3I/LnByaW1hcnlcclxuICAgICAgICAgIDogZml4dHVyZURhdGEuaXNzdWVcclxuICAgICAgICAgICAgPyBcIiNEOTJEMjBcIlxyXG4gICAgICAgICAgICA6IFwiIzZCQ0FGRlwiLFxyXG4gICAgICAgIHN0cm9rZVdpZHRoOiAwLjI3LFxyXG4gICAgICB9XHJcbiAgICApO1xyXG5cclxuICAgIGNvbnN0IGxhc3RCb3hUZXh0ID0gbmV3IGZhYnJpYy5UZXh0Ym94KFxyXG4gICAgICBgJHtmaXh0dXJlRGF0YT8uZm9vdGVyPy5sYWJlbCA/IGZpeHR1cmVEYXRhLmZvb3Rlci5sYWJlbCA6IFwiXCJ9YCxcclxuICAgICAge1xyXG4gICAgICAgIGxlZnQ6IG1pZFggKyBtaWRXaWR0aCAvIDIsXHJcbiAgICAgICAgdG9wOiBsYXN0Qm94WSArIGJveEhlaWdodCAvIDIsXHJcbiAgICAgICAgZm9udFNpemU6IDUsXHJcbiAgICAgICAgZm9udEZhbWlseTogXCJJbnRlclwiLFxyXG4gICAgICAgIGZvbnRXZWlnaHQ6IFwiNjAwXCIsXHJcbiAgICAgICAgZmlsbDogXCIjMTAxODI4XCIsXHJcbiAgICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICAgIHRleHRBbGlnbjogXCJjZW50ZXJcIixcclxuICAgICAgICB3aWR0aDogbWlkV2lkdGgsXHJcbiAgICAgICAgaGVpZ3RoOiBib3hIZWlnaHQsXHJcbiAgICAgIH1cclxuICAgICk7XHJcblxyXG4gICAgY29uc3QgYm90dG9tV2lkdGggPSB3aWR0aCAvIDEuMDU7XHJcbiAgICBjb25zdCBib3R0b21IZWlnaHQgPSAoMyAvIDEwMCkgKiBoZWlnaHQ7XHJcbiAgICBjb25zdCBib3R0b21YID0geCArICh3aWR0aCAtIGJvdHRvbVdpZHRoKSAvIDI7XHJcbiAgICBjb25zdCBib3R0b21ZID0gbWlkWSArIG1pZEhlaWdodCArIHRoaXMudmVydGljYWxNYXJnaW47XHJcblxyXG4gICAgY29uc3QgYm90dG9tQ29udGFpbmVyID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgbGVmdDogYm90dG9tWCxcclxuICAgICAgdG9wOiBib3R0b21ZLFxyXG4gICAgICB3aWR0aDogYm90dG9tV2lkdGgsXHJcbiAgICAgIGhlaWdodDogYm90dG9tSGVpZ2h0LFxyXG4gICAgICByeDogcmFkaXVzLFxyXG4gICAgICByeTogcmFkaXVzLFxyXG4gICAgICBzdHJva2U6IFwidHJhbnNwYXJlbnRcIixcclxuICAgICAgZmlsbDogXCJ0cmFuc3BhcmVudFwiLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgYm90dG9tVGV4dENvbnRlbnQgPSBuZXcgZmFicmljLlRleHRib3goXHJcbiAgICAgIGBTaGVsdmVzIC0gJHtmaXh0dXJlRGF0YS5zaGVsZkNvbmZpZz8ubGVuZ3RofSAuIFByb2R1Y3RzIC0gICR7Zml4dHVyZURhdGEuZml4dHVyZUNhcGFjaXR5fSAuIFZNIC0gJHtmaXh0dXJlRGF0YS52bUNvbmZpZz8ubGVuZ3RofWAsXHJcbiAgICAgIHtcclxuICAgICAgICBsZWZ0OiBib3R0b21YICsgYm90dG9tV2lkdGggLyAyLFxyXG4gICAgICAgIHRvcDogYm90dG9tWSArIGJvdHRvbUhlaWdodCAvIDIsXHJcbiAgICAgICAgZm9udFNpemU6IDUsXHJcbiAgICAgICAgZm9udEZhbWlseTogXCJJbnRlclwiLFxyXG4gICAgICAgIGZvbnRXZWlnaHQ6IFwiNTAwXCIsXHJcbiAgICAgICAgZmlsbDogXCIjMzMzXCIsXHJcbiAgICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICAgIHRleHRBbGlnbjogXCJjZW50ZXJcIixcclxuICAgICAgICB3aWR0aDogYm90dG9tV2lkdGgsXHJcbiAgICAgICAgaGVpZ2h0OiBib3R0b21IZWlnaHQsXHJcbiAgICAgIH1cclxuICAgICk7XHJcblxyXG5cclxuICAgIGNvbnN0IGZpeHR1cmVHcm91cCA9IG5ldyBmYWJyaWMuR3JvdXAoXHJcbiAgICAgIFtcclxuICAgICAgICBtYWluQ29udGFpbmVyLFxyXG4gICAgICAgIHRvcENvbnRhaW5lcixcclxuICAgICAgICBpbm5lclRvcEJveCxcclxuICAgICAgICB0b3BUZXh0LFxyXG4gICAgICAgIGlubmVyQm90dG9tQm94LFxyXG4gICAgICAgIGJvdHRvbVRleHQsXHJcbiAgICAgICAgbWlkQ29udGFpbmVyLFxyXG4gICAgICAgIGZpcnN0Qm94LFxyXG4gICAgICAgIGZpcnN0Qm94VGV4dCxcclxuICAgICAgICAuLi5zaGVsdmVzLFxyXG4gICAgICAgIGxhc3RCb3gsXHJcbiAgICAgICAgbGFzdEJveFRleHQsXHJcbiAgICAgICAgYm90dG9tQ29udGFpbmVyLFxyXG4gICAgICAgIGJvdHRvbVRleHRDb250ZW50LFxyXG4gICAgICBdLFxyXG4gICAgICB7XHJcbiAgICAgICAgbGVmdDogeCxcclxuICAgICAgICB0b3A6IHksXHJcbiAgICAgICAgZXZlbnRlZDogdHJ1ZSxcclxuICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICBob3ZlckN1cnNvcjogXCJkZWZhdWx0XCIsXHJcbiAgICAgICAgbG9ja1NjYWxpbmdYOiB0cnVlLFxyXG4gICAgICAgIGxvY2tTY2FsaW5nWTogdHJ1ZSxcclxuICAgICAgICBsb2NrTW92ZW1lbnRYOiB0cnVlLFxyXG4gICAgICAgIGxvY2tNb3ZlbWVudFk6IHRydWUsXHJcbiAgICAgICAgbG9ja1JvdGF0aW9uOiB0cnVlLFxyXG4gICAgICAgIGhhc0NvbnRyb2xzOiBmYWxzZSxcclxuICAgICAgICBzdWJUYXJnZXRDaGVjazogdHJ1ZSxcclxuICAgICAgICBhbmdsZTogZml4dHVyZURhdGEucmVsYXRpdmVQb3NpdGlvbj8uYW5nbGUgPz8gMCxcclxuICAgICAgfVxyXG4gICAgKSBhcyBmYWJyaWMuR3JvdXAgJiB7XHJcbiAgICAgIHdhbGxJbmRleDogbnVtYmVyO1xyXG4gICAgICBmaXh0dXJlSW5kZXg6IG51bWJlcjtcclxuICAgICAgZml4dHVyZUlkOiBzdHJpbmc7XHJcbiAgICAgIGZpeHR1cmVUeXBlOiBcIndhbGxcIiB8IFwiZmxvb3JcIjtcclxuICAgICAgaXNzdWU6IGJvb2xlYW47XHJcbiAgICAgIGlzc3VlRGF0YTogYW55O1xyXG4gICAgICB0YXNrVHlwZTogc3RyaW5nO1xyXG4gICAgICB2bUNvbmZpZzogW107XHJcbiAgICAgIG9ialR5cGU6IHN0cmluZztcclxuICAgIH07XHJcblxyXG5cclxuXHJcbiAgICBmaXh0dXJlR3JvdXAuZml4dHVyZVR5cGUgPSBmaXh0dXJlRGF0YS5maXh0dXJlVHlwZTtcclxuICAgIGZpeHR1cmVHcm91cC53YWxsSW5kZXggPSBmaXh0dXJlRGF0YS5hc3NvY2lhdGVkRWxlbWVudE51bWJlcjtcclxuICAgIGZpeHR1cmVHcm91cC5maXh0dXJlSW5kZXggPSBmaXh0dXJlRGF0YS5hc3NvY2lhdGVkRWxlbWVudEZpeHR1cmVOdW1iZXI7XHJcbiAgICBmaXh0dXJlR3JvdXAuZml4dHVyZUlkID0gZml4dHVyZURhdGEuX2lkO1xyXG4gICAgZml4dHVyZUdyb3VwLmlzc3VlID0gZml4dHVyZURhdGEuaXNzdWU7XHJcbiAgICBmaXh0dXJlR3JvdXAuaXNzdWVEYXRhID0gZml4dHVyZURhdGEuaXNzdWVEYXRhO1xyXG4gICAgZml4dHVyZUdyb3VwLnRhc2tUeXBlID0gZml4dHVyZURhdGEudGFza1R5cGU7XHJcbiAgICBmaXh0dXJlR3JvdXAudm1Db25maWcgPSBmaXh0dXJlRGF0YS52bUNvbmZpZztcclxuICAgIGZpeHR1cmVHcm91cC5vYmpUeXBlID0gXCJmaXh0dXJlXCI7XHJcblxyXG4gICAgLy8gQWRkIGNsaWNrIGhhbmRsZXIgZGlyZWN0bHkgb24gdGhlIGZpeHR1cmUgZ3JvdXBcclxuICAgIGZpeHR1cmVHcm91cC5vbihcIm1vdXNlZG93blwiLCAoZXZlbnQ6IGFueSkgPT4ge1xyXG4gICAgICAvLyBVc2UgdGhlIGZpeHR1cmUgZ3JvdXAgaXRzZWxmICh3aGljaCBoYXMgYWxsIHRoZSBmaXh0dXJlIHByb3BlcnRpZXMpXHJcbiAgICAgIC8vIFRoZSBldmVudC50YXJnZXQgbWlnaHQgYmUgYSBjaGlsZCBlbGVtZW50LCBzbyB3ZSB1c2UgZml4dHVyZUdyb3VwIGRpcmVjdGx5XHJcbiAgICAgIGlmIChmaXh0dXJlR3JvdXAgJiYgKGZpeHR1cmVHcm91cCBhcyBhbnkpLmZpeHR1cmVJZCkge1xyXG4gICAgICAgIC8vIHRoaXMub25GaXh0dXJlQ2xpY2soZml4dHVyZUdyb3VwKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgY2FudmFzLmFkZChmaXh0dXJlR3JvdXApO1xyXG5cclxuICAgIC8vIElmIG5ld2x5IGFkZGVkLCBmb2N1cyBpdCBvbmNlXHJcbiAgICBpZiAoKGZpeHR1cmVEYXRhIGFzIGFueSk/Lm5ld0FkZGVkKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgY2FudmFzLnNldEFjdGl2ZU9iamVjdChmaXh0dXJlR3JvdXApO1xyXG4gICAgICAgIGNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCk7XHJcbiAgICAgIH0gY2F0Y2ggeyB9XHJcbiAgICAgIGRlbGV0ZSAoZml4dHVyZURhdGEgYXMgYW55KS5uZXdBZGRlZDtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gZml4dHVyZUdyb3VwO1xyXG4gIH1cclxuXHJcbiAgZHJhd090aGVyRWxlbWVudHNXaXRoTGFiZWwoXHJcbiAgICBjYW52YXM6IGZhYnJpYy5DYW52YXMsXHJcbiAgICB4OiBudW1iZXIsXHJcbiAgICB5OiBudW1iZXIsXHJcbiAgICBhOiBudW1iZXIsXHJcbiAgICB3aWR0aDogbnVtYmVyLFxyXG4gICAgaGVpZ2h0OiBudW1iZXIsXHJcbiAgICBlbGVtZW50OiBhbnlcclxuICApOiBmYWJyaWMuR3JvdXAge1xyXG4gICAgY29uc3QgcmVjdCA9IG5ldyBmYWJyaWMuUmVjdCh7XHJcbiAgICAgIHdpZHRoLFxyXG4gICAgICBoZWlnaHQsXHJcbiAgICAgIHJ4OiAyLFxyXG4gICAgICByeTogMixcclxuICAgICAgZmlsbDogXCIjREFGMUZGXCIsXHJcbiAgICAgIHN0cm9rZTogXCIjNkJDQUZGXCIsXHJcbiAgICAgIHN0cm9rZVdpZHRoOiAyLFxyXG4gICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgdGV4dCA9IG5ldyBmYWJyaWMuVGV4dGJveChlbGVtZW50LmZpeHR1cmVOYW1lLCB7XHJcbiAgICAgIHdpZHRoOiB3aWR0aCAtIDgsXHJcbiAgICAgIGZvbnRTaXplOiAxNCxcclxuICAgICAgZm9udEZhbWlseTogXCJJbnRlclwiLFxyXG4gICAgICBmb250V2VpZ2h0OiBcIjUwMFwiLFxyXG4gICAgICBmaWxsOiBcIiMxMDE4MjhcIixcclxuICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgb3JpZ2luWTogXCJjZW50ZXJcIixcclxuICAgICAgdGV4dEFsaWduOiBcImNlbnRlclwiLFxyXG4gICAgICBlZGl0YWJsZTogZmFsc2UsXHJcbiAgICAgIHNwbGl0QnlHcmFwaGVtZTogdHJ1ZSxcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IHRleHRCb3VuZHMgPSB0ZXh0LmdldEJvdW5kaW5nUmVjdCgpO1xyXG5cclxuICAgIGlmICh0ZXh0Qm91bmRzLmhlaWdodCA+IGhlaWdodCAtIDgpIHtcclxuICAgICAgY29uc3Qgc2NhbGUgPSAoaGVpZ2h0IC0gOCkgLyB0ZXh0Qm91bmRzLmhlaWdodDtcclxuICAgICAgdGV4dC5zZXQoXCJmb250U2l6ZVwiLCB0ZXh0LmZvbnRTaXplISAqIHNjYWxlKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBncm91cCA9IG5ldyBmYWJyaWMuR3JvdXAoW3JlY3QsIHRleHRdLCB7XHJcbiAgICAgIGxlZnQ6IHgsXHJcbiAgICAgIHRvcDogeSxcclxuICAgICAgYW5nbGU6IGEsXHJcbiAgICAgIG9yaWdpblg6IFwiY2VudGVyXCIsXHJcbiAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgIGhhc0NvbnRyb2xzOiBmYWxzZSxcclxuICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgIGxvY2tTY2FsaW5nWDogdHJ1ZSxcclxuICAgICAgbG9ja1NjYWxpbmdZOiB0cnVlLFxyXG4gICAgICBsb2NrUm90YXRpb246IHRydWUsXHJcbiAgICAgIGxvY2tNb3ZlbWVudFg6IHRydWUsXHJcbiAgICAgIGxvY2tNb3ZlbWVudFk6IHRydWUsXHJcbiAgICAgIGV2ZW50ZWQ6IHRydWUsXHJcbiAgICAgIGhvdmVyQ3Vyc29yOiBcImRlZmF1bHRcIixcclxuICAgIH0pIGFzIGZhYnJpYy5Hcm91cCAmIHtcclxuICAgICAgb2JqVHlwZTogc3RyaW5nO1xyXG4gICAgICBkYXRhOiBhbnk7XHJcbiAgICB9O1xyXG5cclxuICAgIGdyb3VwLm9ialR5cGUgPSBcIm90aGVyc1wiO1xyXG4gICAgZ3JvdXAuZGF0YSA9IGVsZW1lbnQ7XHJcblxyXG4gICAgY2FudmFzLmFkZChncm91cCk7XHJcblxyXG4gICAgaWYgKChlbGVtZW50IGFzIGFueSk/Lm5ld0FkZGVkKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgY2FudmFzLnNldEFjdGl2ZU9iamVjdChncm91cCk7XHJcbiAgICAgICAgY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgICAgfSBjYXRjaCB7IH1cclxuICAgICAgZGVsZXRlIChlbGVtZW50IGFzIGFueSkubmV3QWRkZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGdyb3VwO1xyXG4gIH1cclxuXHJcbiAgcmVzaXplQ2FudmFzKGNhbnZhczogZmFicmljLkNhbnZhcywgY29udGFpbmVyOiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50Pik6IHZvaWQge1xyXG4gICAgY29uc3QgY29udGFpbmVyRWwgPSBjb250YWluZXIubmF0aXZlRWxlbWVudDtcclxuICAgIGNvbnN0IHdpZHRoID0gY29udGFpbmVyRWwuY2xpZW50V2lkdGggfHwgY29udGFpbmVyRWwub2Zmc2V0V2lkdGg7XHJcbiAgICBjb25zdCBoZWlnaHQgPSBjb250YWluZXJFbC5jbGllbnRIZWlnaHQgfHwgY29udGFpbmVyRWwub2Zmc2V0SGVpZ2h0O1xyXG5cclxuICAgIGlmICh3aWR0aCA+IDAgJiYgaGVpZ2h0ID4gMCkge1xyXG4gICAgICBjYW52YXMuc2V0RGltZW5zaW9ucyh7XHJcbiAgICAgICAgd2lkdGg6IHdpZHRoLFxyXG4gICAgICAgIGhlaWdodDogaGVpZ2h0LFxyXG4gICAgICB9KTtcclxuICAgICAgY2FudmFzLmNhbGNPZmZzZXQoKTtcclxuICAgICAgY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgZml0Q2FudmFzVG9MYXlvdXRBbmltYXRlZChjYW52YXM6IGZhYnJpYy5DYW52YXMpIHtcclxuICAgIGlmICghY2FudmFzKSByZXR1cm47XHJcblxyXG4gICAgLy8gRW5zdXJlIGNhbnZhcyBoYXMgb2JqZWN0cyBiZWZvcmUgY2FsY3VsYXRpbmcgYm91bmRzXHJcbiAgICBjb25zdCBvYmplY3RzID0gY2FudmFzLmdldE9iamVjdHMoKTtcclxuICAgIGlmICghb2JqZWN0cyB8fCBvYmplY3RzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICBjb25zb2xlLndhcm4oJ05vIG9iamVjdHMgb24gY2FudmFzIHRvIGZpdCcpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRm9yY2UgcmVjYWxjdWxhdGlvbiBvZiBvYmplY3QgY29vcmRpbmF0ZXNcclxuICAgIGNhbnZhcy5jYWxjT2Zmc2V0KCk7XHJcblxyXG4gICAgY29uc3QgYm91bmRzID0gdGhpcy5nZXRGdWxsTGF5b3V0Qm91bmRzKGNhbnZhcyk7XHJcbiAgICBpZiAoIWJvdW5kcy53aWR0aCB8fCAhYm91bmRzLmhlaWdodCB8fCBib3VuZHMud2lkdGggPT09IDAgfHwgYm91bmRzLmhlaWdodCA9PT0gMCkge1xyXG4gICAgICBjb25zb2xlLndhcm4oJ0ludmFsaWQgYm91bmRzIGZvciBjYW52YXMgZml0dGluZycsIGJvdW5kcyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBjYW52YXNXID0gY2FudmFzLmdldFdpZHRoKCk7XHJcbiAgICBjb25zdCBjYW52YXNIID0gY2FudmFzLmdldEhlaWdodCgpO1xyXG5cclxuICAgIGlmIChjYW52YXNXID09PSAwIHx8IGNhbnZhc0ggPT09IDApIHtcclxuICAgICAgY29uc29sZS53YXJuKCdDYW52YXMgZGltZW5zaW9ucyBhcmUgemVybycpO1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3Qgc2NhbGVYID0gY2FudmFzVyAvIGJvdW5kcy53aWR0aDtcclxuICAgIGNvbnN0IHNjYWxlWSA9IGNhbnZhc0ggLyBib3VuZHMuaGVpZ2h0O1xyXG4gICAgLy8gVXNlIHNtYWxsZXIgbXVsdGlwbGllciAoMC41KSB0byB6b29tIG91dCBtb3JlIGFuZCBlbnN1cmUgcGxhbm9ncmFtIGZpdHMgd2l0aCBtb3JlIHBhZGRpbmcgaW5zaWRlIGNhbnZhc1xyXG4gICAgY29uc3QgdGFyZ2V0Wm9vbSA9IE1hdGgubWluKHNjYWxlWCwgc2NhbGVZKSAqIDAuOTtcclxuXHJcbiAgICAvLyBFbnN1cmUgem9vbSBpcyB3aXRoaW4gcmVhc29uYWJsZSBib3VuZHNcclxuICAgIGNvbnN0IGZpbmFsWm9vbSA9IE1hdGgubWF4KDAuMSwgTWF0aC5taW4odGFyZ2V0Wm9vbSwgMykpO1xyXG5cclxuICAgIGNvbnN0IHRhcmdldFZwdCA9IFsuLi4oY2FudmFzLnZpZXdwb3J0VHJhbnNmb3JtIHx8IFsxLCAwLCAwLCAxLCAwLCAwXSldIGFzIGZhYnJpYy5UTWF0MkQ7XHJcbiAgICB0YXJnZXRWcHRbMF0gPSBmaW5hbFpvb207XHJcbiAgICB0YXJnZXRWcHRbM10gPSBmaW5hbFpvb207XHJcblxyXG4gICAgLy8gQ2FsY3VsYXRlIGNlbnRlciBvZiBsYXlvdXQgYm91bmRzIGZvciBob3Jpem9udGFsIGNlbnRlcmluZ1xyXG4gICAgY29uc3QgY2VudGVyWCA9IGJvdW5kcy5sZWZ0ICsgYm91bmRzLndpZHRoIC8gMjtcclxuXHJcbiAgICAvLyBQb3NpdGlvbiBmcm9tIHRvcCB3aXRoIHZlcnkgbWluaW1hbCBwYWRkaW5nICh1c2UgdG9wIHNwYWNlKVxyXG4gICAgY29uc3QgdG9wUGFkZGluZyA9IDEwOyAvLyBGaXhlZCAxMHB4IHBhZGRpbmcgZnJvbSB0b3BcclxuXHJcbiAgICAvLyBDYWxjdWxhdGUgdHJhbnNsYXRpb246IGNlbnRlciBob3Jpem9udGFsbHksIHBvc2l0aW9uIGZyb20gdG9wXHJcbiAgICB0YXJnZXRWcHRbNF0gPSBjYW52YXNXIC8gMiAtIGNlbnRlclggKiBmaW5hbFpvb207XHJcbiAgICB0YXJnZXRWcHRbNV0gPSB0b3BQYWRkaW5nIC0gYm91bmRzLnRvcCAqIGZpbmFsWm9vbTtcclxuXHJcbiAgICBjb25zdCBzdGFydFZwdCA9IFsuLi5jYW52YXMudmlld3BvcnRUcmFuc2Zvcm0hXSBhcyBmYWJyaWMuVE1hdDJEO1xyXG5cclxuICAgIGZhYnJpYy51dGlsLmFuaW1hdGUoe1xyXG4gICAgICBzdGFydFZhbHVlOiAwLFxyXG4gICAgICBlbmRWYWx1ZTogMSxcclxuICAgICAgZHVyYXRpb246IDUwMCxcclxuICAgICAgb25DaGFuZ2U6ICh2YWx1ZTogbnVtYmVyKSA9PiB7XHJcbiAgICAgICAgY29uc3QgdnB0ID0gWy4uLnN0YXJ0VnB0XSBhcyBmYWJyaWMuVE1hdDJEO1xyXG4gICAgICAgIHZwdFswXSA9IHN0YXJ0VnB0WzBdICsgKHRhcmdldFZwdFswXSAtIHN0YXJ0VnB0WzBdKSAqIHZhbHVlO1xyXG4gICAgICAgIHZwdFszXSA9IHN0YXJ0VnB0WzNdICsgKHRhcmdldFZwdFszXSAtIHN0YXJ0VnB0WzNdKSAqIHZhbHVlO1xyXG4gICAgICAgIHZwdFs0XSA9IHN0YXJ0VnB0WzRdICsgKHRhcmdldFZwdFs0XSAtIHN0YXJ0VnB0WzRdKSAqIHZhbHVlO1xyXG4gICAgICAgIHZwdFs1XSA9IHN0YXJ0VnB0WzVdICsgKHRhcmdldFZwdFs1XSAtIHN0YXJ0VnB0WzVdKSAqIHZhbHVlO1xyXG4gICAgICAgIGNhbnZhcy5zZXRWaWV3cG9ydFRyYW5zZm9ybSh2cHQpO1xyXG4gICAgICAgIGNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCk7XHJcbiAgICAgIH0sXHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0RnVsbExheW91dEJvdW5kcyhjYW52YXM6IGZhYnJpYy5DYW52YXMpIHtcclxuICAgIGNvbnN0IG9iamVjdHMgPSBjYW52YXMuZ2V0T2JqZWN0cygpO1xyXG4gICAgaWYgKCFvYmplY3RzLmxlbmd0aCkgcmV0dXJuIHsgbGVmdDogMCwgdG9wOiAwLCB3aWR0aDogMCwgaGVpZ2h0OiAwIH07XHJcblxyXG4gICAgbGV0IG1pblggPSBJbmZpbml0eSwgbWluWSA9IEluZmluaXR5LCBtYXhYID0gLUluZmluaXR5LCBtYXhZID0gLUluZmluaXR5O1xyXG5cclxuICAgIGZvciAoY29uc3Qgb2JqIG9mIG9iamVjdHMpIHtcclxuICAgICAgLy8gR2V0IGJvdW5kaW5nIHJlY3Qgd2hpY2ggYWNjb3VudHMgZm9yIG9iamVjdCdzIHBvc2l0aW9uLCByb3RhdGlvbiwgYW5kIHNjYWxlXHJcbiAgICAgIGNvbnN0IGJvdW5kaW5nUmVjdCA9IG9iai5nZXRCb3VuZGluZ1JlY3QoKTtcclxuXHJcbiAgICAgIC8vIEdldCB0aGUgYWN0dWFsIGJvdW5kaW5nIGJveFxyXG4gICAgICBjb25zdCBsZWZ0ID0gYm91bmRpbmdSZWN0LmxlZnQ7XHJcbiAgICAgIGNvbnN0IHRvcCA9IGJvdW5kaW5nUmVjdC50b3A7XHJcbiAgICAgIGNvbnN0IHJpZ2h0ID0gbGVmdCArIGJvdW5kaW5nUmVjdC53aWR0aDtcclxuICAgICAgY29uc3QgYm90dG9tID0gdG9wICsgYm91bmRpbmdSZWN0LmhlaWdodDtcclxuXHJcbiAgICAgIG1pblggPSBNYXRoLm1pbihtaW5YLCBsZWZ0KTtcclxuICAgICAgbWluWSA9IE1hdGgubWluKG1pblksIHRvcCk7XHJcbiAgICAgIG1heFggPSBNYXRoLm1heChtYXhYLCByaWdodCk7XHJcbiAgICAgIG1heFkgPSBNYXRoLm1heChtYXhZLCBib3R0b20pO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB7IGxlZnQ6IG1pblgsIHRvcDogbWluWSwgd2lkdGg6IG1heFggLSBtaW5YLCBoZWlnaHQ6IG1heFkgLSBtaW5ZIH07XHJcbiAgfVxyXG5cclxuICB0b1BpeGVscyh2YWx1ZTogbnVtYmVyLCB1bml0OiBzdHJpbmcsIGRwaSA9IDIuOCk6IG51bWJlciB7XHJcbiAgICBsZXQgcGl4ZWxzOiBudW1iZXI7XHJcbiAgICBpZiAodW5pdCA9PT0gXCJtbVwiKSB7XHJcbiAgICAgIHBpeGVscyA9ICh2YWx1ZSAvIDI1LjQpICogZHBpO1xyXG4gICAgfSBlbHNlIGlmICh1bml0ID09PSBcImZ0XCIpIHtcclxuICAgICAgcGl4ZWxzID0gdmFsdWUgKiAxMiAqIGRwaTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuc3VwcG9ydGVkIHVuaXQuIFVzZSAnbW0nIG9yICdmdCcuXCIpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIE51bWJlcihwaXhlbHMudG9GaXhlZCg0KSk7XHJcbiAgfVxyXG5cclxuICAvLyBTdG9yZSBsaXN0IG1ldGhvZHNcclxuICBvblNlbGVjdEFsbChjaGVja2VkOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICBpZiAoY2hlY2tlZCkge1xyXG4gICAgICAvLyBPbmx5IHNlbGVjdCBzdG9yZXMgdGhhdCBkb24ndCBoYXZlIG5vLW1hdGNoIHN0YXR1c1xyXG4gICAgICB0aGlzLmZpbHRlcmVkU3RvcmVzLmZvckVhY2goc3RvcmUgPT4ge1xyXG4gICAgICAgIGlmICghdGhpcy5oYXNOb01hdGNoKHN0b3JlKSkge1xyXG4gICAgICAgICAgc3RvcmUuaXNBcHByb3ZlZCA9IHRydWU7XHJcbiAgICAgICAgICB0aGlzLnNlbGVjdGVkU3RvcmVzLmFkZChzdG9yZS5zdG9yZU5hbWUpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBEZXNlbGVjdCBhbGwgc3RvcmVzXHJcbiAgICAgIHRoaXMuZmlsdGVyZWRTdG9yZXMuZm9yRWFjaChzdG9yZSA9PiB7XHJcbiAgICAgICAgc3RvcmUuaXNBcHByb3ZlZCA9IGZhbHNlO1xyXG4gICAgICB9KTtcclxuICAgICAgdGhpcy5zZWxlY3RlZFN0b3Jlcy5jbGVhcigpO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFVwZGF0ZSBmaW5kUmVwbGFjZURhdGEgc3RvcmVzIGFycmF5IGFuZCBub3RpZnkgZGF0YSBzZXJ2aWNlXHJcbiAgICBpZiAodGhpcy5maW5kUmVwbGFjZURhdGE/LnN0b3Jlcykge1xyXG4gICAgICBjb25zdCBzdG9yZXMgPSB0aGlzLmZpbmRSZXBsYWNlRGF0YS5zdG9yZXM7XHJcbiAgICAgIHRoaXMuZmlsdGVyZWRTdG9yZXMuZm9yRWFjaChmaWx0ZXJlZFN0b3JlID0+IHtcclxuICAgICAgICBpZiAoZmlsdGVyZWRTdG9yZSAmJiBzdG9yZXMpIHtcclxuICAgICAgICAgIGNvbnN0IHN0b3JlSW5kZXggPSBzdG9yZXMuZmluZEluZGV4KHMgPT4gcyAmJiBzLnN0b3JlTmFtZSA9PT0gZmlsdGVyZWRTdG9yZS5zdG9yZU5hbWUpO1xyXG4gICAgICAgICAgaWYgKHN0b3JlSW5kZXggIT09IC0xICYmIHN0b3Jlc1tzdG9yZUluZGV4XSkge1xyXG4gICAgICAgICAgICBzdG9yZXNbc3RvcmVJbmRleF0uaXNBcHByb3ZlZCA9IGZpbHRlcmVkU3RvcmUuaXNBcHByb3ZlZDtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgICAvLyBVcGRhdGUgZGF0YSBzZXJ2aWNlIHRvIHByZXNlcnZlIHN0YXRlXHJcbiAgICAgIGlmIChzdG9yZXMpIHtcclxuICAgICAgICB0aGlzLmRhdGFTZXJ2aWNlLnVwZGF0ZURhdGEoeyBzdG9yZXM6IHN0b3JlcyB9KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25TdG9yZUNoZWNrYm94Q2hhbmdlKHN0b3JlOiBTdG9yZSwgY2hlY2tlZDogYm9vbGVhbik6IHZvaWQge1xyXG4gICAgLy8gUHJldmVudCBzZWxlY3Rpb24gaWYgc3RvcmUgaGFzIG5vLW1hdGNoIHN0YXR1c1xyXG4gICAgaWYgKHRoaXMuaGFzTm9NYXRjaChzdG9yZSkpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghc3RvcmUpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFVwZGF0ZSBpc0FwcHJvdmVkIHByb3BlcnR5IG9uIHRoZSBzdG9yZSBvYmplY3RcclxuICAgIHN0b3JlLmlzQXBwcm92ZWQgPSBjaGVja2VkO1xyXG5cclxuICAgIC8vIFVwZGF0ZSB0aGUgc3RvcmUgaW4gdGhlIGxvY2FsIHN0b3JlcyBhcnJheVxyXG4gICAgY29uc3QgbG9jYWxTdG9yZUluZGV4ID0gdGhpcy5zdG9yZXMuZmluZEluZGV4KHMgPT4gcy5zdG9yZU5hbWUgPT09IHN0b3JlLnN0b3JlTmFtZSk7XHJcbiAgICBpZiAobG9jYWxTdG9yZUluZGV4ICE9PSAtMSAmJiB0aGlzLnN0b3Jlc1tsb2NhbFN0b3JlSW5kZXhdKSB7XHJcbiAgICAgIHRoaXMuc3RvcmVzW2xvY2FsU3RvcmVJbmRleF0uaXNBcHByb3ZlZCA9IGNoZWNrZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gVXBkYXRlIHNlbGVjdGVkU3RvcmVzIHNldCBmb3IgYmFja3dhcmQgY29tcGF0aWJpbGl0eVxyXG4gICAgaWYgKGNoZWNrZWQpIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZFN0b3Jlcy5hZGQoc3RvcmUuc3RvcmVOYW1lKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRTdG9yZXMuZGVsZXRlKHN0b3JlLnN0b3JlTmFtZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gVXBkYXRlIHRoZSBzdG9yZSBpbiBmaW5kUmVwbGFjZURhdGEgc3RvcmVzIGFycmF5IGFuZCBub3RpZnkgZGF0YSBzZXJ2aWNlIHRvIHByZXNlcnZlIHN0YXRlXHJcbiAgICBpZiAodGhpcy5maW5kUmVwbGFjZURhdGE/LnN0b3Jlcykge1xyXG4gICAgICBjb25zdCBzdG9yZUluZGV4ID0gdGhpcy5maW5kUmVwbGFjZURhdGEuc3RvcmVzLmZpbmRJbmRleChzID0+IHMuc3RvcmVOYW1lID09PSBzdG9yZS5zdG9yZU5hbWUpO1xyXG4gICAgICBpZiAoc3RvcmVJbmRleCAhPT0gLTEgJiYgdGhpcy5maW5kUmVwbGFjZURhdGEuc3RvcmVzW3N0b3JlSW5kZXhdKSB7XHJcbiAgICAgICAgdGhpcy5maW5kUmVwbGFjZURhdGEuc3RvcmVzW3N0b3JlSW5kZXhdLmlzQXBwcm92ZWQgPSBjaGVja2VkO1xyXG4gICAgICAgIC8vIFVwZGF0ZSBkYXRhIHNlcnZpY2UgdG8gcHJlc2VydmUgc3RhdGUgd2hlbiBzYXZlIGFzIGRyYWZ0IGlzIGNhbGxlZFxyXG4gICAgICAgIHRoaXMuZGF0YVNlcnZpY2UudXBkYXRlRGF0YSh7IHN0b3JlczogdGhpcy5maW5kUmVwbGFjZURhdGEuc3RvcmVzIH0pO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBpc1N0b3JlU2VsZWN0ZWQoc3RvcmVOYW1lOiBzdHJpbmcpOiBib29sZWFuIHtcclxuICAgIC8vIENoZWNrIGJvdGggc2VsZWN0ZWRTdG9yZXMgc2V0IGFuZCBpc0FwcHJvdmVkIHByb3BlcnR5XHJcbiAgICBjb25zdCBzdG9yZSA9IHRoaXMuc3RvcmVzLmZpbmQocyA9PiBzLnN0b3JlTmFtZSA9PT0gc3RvcmVOYW1lKTtcclxuICAgIHJldHVybiB0aGlzLnNlbGVjdGVkU3RvcmVzLmhhcyhzdG9yZU5hbWUpIHx8IChzdG9yZT8uaXNBcHByb3ZlZCA9PT0gdHJ1ZSk7XHJcbiAgfVxyXG5cclxuICBpc0FsbFNlbGVjdGVkKCk6IGJvb2xlYW4ge1xyXG4gICAgLy8gT25seSBjb25zaWRlciBzZWxlY3RhYmxlIHN0b3JlcyAoZXhjbHVkZSBuby1tYXRjaCBzdG9yZXMpXHJcbiAgICBjb25zdCBzZWxlY3RhYmxlU3RvcmVzID0gdGhpcy5maWx0ZXJlZFN0b3Jlcy5maWx0ZXIoc3RvcmUgPT4gIXRoaXMuaGFzTm9NYXRjaChzdG9yZSkpO1xyXG4gICAgcmV0dXJuIHNlbGVjdGFibGVTdG9yZXMubGVuZ3RoID4gMCAmJiBzZWxlY3RhYmxlU3RvcmVzLmV2ZXJ5KHN0b3JlID0+IHN0b3JlLmlzQXBwcm92ZWQgPT09IHRydWUpO1xyXG4gIH1cclxuXHJcbiAgb25TZWFyY2goKTogdm9pZCB7XHJcbiAgICB0aGlzLmFwcGx5RmlsdGVycygpO1xyXG4gIH1cclxuXHJcbiAgYXBwbHlGaWx0ZXJzKCk6IHZvaWQge1xyXG4gICAgbGV0IGZpbHRlcmVkID0gWy4uLnRoaXMuc3RvcmVzXTtcclxuXHJcbiAgICAvLyBBcHBseSBzZWFyY2ggZmlsdGVyXHJcbiAgICBpZiAodGhpcy5zZWFyY2hUZXJtLnRyaW0oKSkge1xyXG4gICAgICBjb25zdCB0ZXJtID0gdGhpcy5zZWFyY2hUZXJtLnRvTG93ZXJDYXNlKCk7XHJcbiAgICAgIGZpbHRlcmVkID0gZmlsdGVyZWQuZmlsdGVyKHN0b3JlID0+XHJcbiAgICAgICAgc3RvcmUuc3RvcmVOYW1lLnRvTG93ZXJDYXNlKCkuaW5jbHVkZXModGVybSlcclxuICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBBcHBseSBzdGF0dXMgZmlsdGVyXHJcbiAgICBpZiAodGhpcy5zZWxlY3RlZFN0YXR1c0ZpbHRlcnMuc2l6ZSA+IDApIHtcclxuICAgICAgZmlsdGVyZWQgPSBmaWx0ZXJlZC5maWx0ZXIoc3RvcmUgPT4ge1xyXG4gICAgICAgIGlmICghc3RvcmUucmVzcG9uc2VTdGF0dXMpIHtcclxuICAgICAgICAgIHJldHVybiB0aGlzLnNlbGVjdGVkU3RhdHVzRmlsdGVycy5oYXMoJ3Vua25vd24nKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRTdGF0dXNGaWx0ZXJzLmhhcyhzdG9yZS5yZXNwb25zZVN0YXR1cyk7XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuZmlsdGVyZWRTdG9yZXMgPSBmaWx0ZXJlZDtcclxuICAgIHRoaXMudG90YWxJdGVtcyA9IHRoaXMuZmlsdGVyZWRTdG9yZXMubGVuZ3RoO1xyXG4gICAgdGhpcy5vZmZzZXQgPSAxOyAvLyBSZXNldCB0byBmaXJzdCBwYWdlIHdoZW4gZmlsdGVycyBjaGFuZ2VcclxuICB9XHJcblxyXG4gIGdldCBwYWdpbmF0ZWRTdG9yZXMoKTogU3RvcmVbXSB7XHJcbiAgICBjb25zdCBzdGFydEluZGV4ID0gKHRoaXMub2Zmc2V0IC0gMSkgKiB0aGlzLmxpbWl0O1xyXG4gICAgY29uc3QgZW5kSW5kZXggPSBzdGFydEluZGV4ICsgdGhpcy5saW1pdDtcclxuICAgIHJldHVybiB0aGlzLmZpbHRlcmVkU3RvcmVzLnNsaWNlKHN0YXJ0SW5kZXgsIGVuZEluZGV4KTtcclxuICB9XHJcblxyXG4gIG9uRG93bmxvYWQoKTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuc3RvcmVzIHx8IHRoaXMuc3RvcmVzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICBjb25zb2xlLndhcm4oJ05vIHN0b3JlcyB0byBleHBvcnQnKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFByZXBhcmUgZGF0YSBmb3IgRXhjZWwgZXhwb3J0XHJcbiAgICBjb25zdCBleHBvcnREYXRhID0gdGhpcy5zdG9yZXMubWFwKHN0b3JlID0+ICh7XHJcbiAgICAgICdTdG9yZSBOYW1lJzogc3RvcmUuc3RvcmVOYW1lLFxyXG4gICAgICAnU3RhdHVzJzogc3RvcmUucmVzcG9uc2VTdGF0dXMgPT09ICdtYXRjaCcgPyAnTWF0Y2gnIDpcclxuICAgICAgICBzdG9yZS5yZXNwb25zZVN0YXR1cyA9PT0gJ25vLW1hdGNoJyA/ICdObyBNYXRjaCcgOlxyXG4gICAgICAgICAgJ1Vua25vd24nXHJcbiAgICB9KSk7XHJcblxyXG4gICAgLy8gRXhwb3J0IHRvIEV4Y2VsXHJcbiAgICBjb25zdCBmaWxlTmFtZSA9IGBTdG9yZXNfRXhwb3J0XyR7bmV3IERhdGUoKS50b0lTT1N0cmluZygpLnNwbGl0KCdUJylbMF19YDtcclxuICAgIHRoaXMuc3RvcmVCdWlsZGVyU2VydmljZS5leHBvcnRBc0V4Y2VsRmlsZShleHBvcnREYXRhLCBmaWxlTmFtZSk7XHJcbiAgfVxyXG5cclxuICBvbkZpbHRlcigpOiB2b2lkIHtcclxuICAgIC8vIEZpbHRlciBmdW5jdGlvbmFsaXR5IGlzIGhhbmRsZWQgdmlhIGRyb3Bkb3duIGluIHRlbXBsYXRlXHJcbiAgfVxyXG5cclxuICBvblN0YXR1c0ZpbHRlckNoYW5nZShzdGF0dXM6IHN0cmluZywgZXZlbnQ6IGFueSk6IHZvaWQge1xyXG4gICAgY29uc3QgaXNDaGVja2VkID0gZXZlbnQudGFyZ2V0LmNoZWNrZWQ7XHJcbiAgICBpZiAoaXNDaGVja2VkKSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRTdGF0dXNGaWx0ZXJzLmFkZChzdGF0dXMpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZFN0YXR1c0ZpbHRlcnMuZGVsZXRlKHN0YXR1cyk7XHJcbiAgICB9XHJcbiAgICB0aGlzLmFwcGx5RmlsdGVycygpO1xyXG4gIH1cclxuXHJcbiAgaXNTdGF0dXNGaWx0ZXJTZWxlY3RlZChzdGF0dXM6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0ZWRTdGF0dXNGaWx0ZXJzLmhhcyhzdGF0dXMpO1xyXG4gIH1cclxuXHJcbiAgY2xlYXJGaWx0ZXJzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5zZWxlY3RlZFN0YXR1c0ZpbHRlcnMuY2xlYXIoKTtcclxuICAgIHRoaXMuc2VhcmNoVGVybSA9ICcnO1xyXG4gICAgdGhpcy5hcHBseUZpbHRlcnMoKTtcclxuICB9XHJcblxyXG4gIGhhc0FjdGl2ZUZpbHRlcnMoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RlZFN0YXR1c0ZpbHRlcnMuc2l6ZSA+IDAgfHwgdGhpcy5zZWFyY2hUZXJtLnRyaW0oKS5sZW5ndGggPiAwO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgb25BcHByb3ZlQW5kQ29tcGxldGUoKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICB0cnkge1xyXG4gICAgICBjb25zdCBtb2RhbFJlZiA9IHRoaXMubW9kYWxTZXJ2aWNlLm9wZW4oQXBwcm92ZUNvbXBsZXRlTW9kYWxDb21wb25lbnQsIHtcclxuICAgICAgICBjZW50ZXJlZDogdHJ1ZSxcclxuICAgICAgICBzaXplOiAnbGcnLFxyXG4gICAgICAgIGJhY2tkcm9wOiAnc3RhdGljJyxcclxuICAgICAgICB3aW5kb3dDbGFzczogJ2FwcHJvdmUtY29tcGxldGUtbW9kYWwnXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgLy8gUHJlLWZpbGwgbW9kYWwgd2l0aCBleGlzdGluZyBzY2hlZHVsZSB2YWx1ZXMgaWYgYXZhaWxhYmxlXHJcbiAgICAgIG1vZGFsUmVmLmNvbXBvbmVudEluc3RhbmNlLmluaXRpYWxTY2hlZHVsZSA9IHRoaXMuZmluZFJlcGxhY2VEYXRhPy5zY2hlZHVsZSB8fCBmYWxzZTtcclxuICAgICAgbW9kYWxSZWYuY29tcG9uZW50SW5zdGFuY2UuaW5pdGlhbFNjaGVkdWxlRGF0ZSA9IHRoaXMuZmluZFJlcGxhY2VEYXRhPy5zY2hlZHVsZURhdGUgfHwgbnVsbDtcclxuXHJcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IG1vZGFsUmVmLnJlc3VsdDtcclxuICAgICAgaWYgKHJlc3VsdCkge1xyXG4gICAgICAgIC8vIEhhbmRsZSB0aGUgYXBwcm92ZSBhbmQgY29tcGxldGUgYWN0aW9uXHJcbiAgICAgICAgY29uc29sZS5sb2coJ0FwcHJvdmUgYW5kIGNvbXBsZXRlIHdpdGggc2NoZWR1bGU6JywgcmVzdWx0LnNjaGVkdWxlLCAnc2NoZWR1bGVEYXRlOicsIHJlc3VsdC5zY2hlZHVsZURhdGUpO1xyXG5cclxuICAgICAgICAvLyBHZXQgZmluZFJlcGxhY2VJZCBmcm9tIGZpbmRSZXBsYWNlRGF0YVxyXG4gICAgICAgIGlmICghdGhpcy5maW5kUmVwbGFjZURhdGE/Ll9pZCkge1xyXG4gICAgICAgICAgY29uc29sZS5lcnJvcignRmluZFJlcGxhY2UgSUQgaXMgbWlzc2luZycpO1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gU2F2ZSBzdG9yZXMsIHNjaGVkdWxlLCBhbmQgc2NoZWR1bGVEYXRlIHVzaW5nIHNhdmUgYXMgZHJhZnQgZmlyc3RcclxuICAgICAgICBjb25zdCBkcmFmdERhdGE6IGFueSA9IHt9O1xyXG4gICAgICAgIGlmICh0aGlzLmZpbmRSZXBsYWNlRGF0YS5zdG9yZXMgJiYgdGhpcy5maW5kUmVwbGFjZURhdGEuc3RvcmVzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgIGRyYWZ0RGF0YS5zdG9yZXMgPSB0aGlzLmZpbmRSZXBsYWNlRGF0YS5zdG9yZXM7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChyZXN1bHQuc2NoZWR1bGUgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgZHJhZnREYXRhLnNjaGVkdWxlID0gcmVzdWx0LnNjaGVkdWxlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAocmVzdWx0LnNjaGVkdWxlRGF0ZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICBkcmFmdERhdGEuc2NoZWR1bGVEYXRlID0gcmVzdWx0LnNjaGVkdWxlRGF0ZTtcclxuICAgICAgICB9XHJcbiAgICAgICAgXHJcbiAgICAgICAgLy8gV2FpdCBmb3Igc2F2ZSBhcyBkcmFmdCB0byBjb21wbGV0ZSBiZWZvcmUgY2FsbGluZyBhcHByb3ZlUmVwbGFjZVxyXG4gICAgICAgIHRoaXMuYXBwcm92ZUxvYWRpbmcgPSB0cnVlO1xyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAvLyBTYXZlIGFsbCB0aGUgZGF0YSB1c2luZyBzYXZlIGFzIGRyYWZ0IGFuZCB3YWl0IGZvciBpdCB0byBjb21wbGV0ZVxyXG4gICAgICAgICAgaWYgKE9iamVjdC5rZXlzKGRyYWZ0RGF0YSkubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICBjb25zdCBzYXZlUmVzcG9uc2U6IGFueSA9IGF3YWl0IHRoaXMuZGF0YVNlcnZpY2Uuc2F2ZURyYWZ0QW5kV2FpdChkcmFmdERhdGEpLnRvUHJvbWlzZSgpO1xyXG4gICAgICAgICAgICBpZiAoc2F2ZVJlc3BvbnNlPy5jb2RlICE9PSAyMDApIHtcclxuICAgICAgICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gc2F2ZSBhcyBkcmFmdDonLCBzYXZlUmVzcG9uc2U/Lm1lc3NhZ2UgfHwgJ1Vua25vd24gZXJyb3InKTtcclxuICAgICAgICAgICAgICB0aGlzLmFwcHJvdmVMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgLy8gQ2FsbCB0aGUgYXBwcm92ZVJlcGxhY2UgQVBJIHdpdGggb25seSBmaW5kUmVwbGFjZUlkIGFmdGVyIHNhdmUgYXMgZHJhZnQgY29tcGxldGVzXHJcbiAgICAgICAgICBjb25zdCByZXNwb25zZTogYW55ID0gYXdhaXQgdGhpcy5zdG9yZUJ1aWxkZXJTZXJ2aWNlLmFwcHJvdmVSZXBsYWNlKHtcclxuICAgICAgICAgICAgZmluZFJlcGxhY2VJZDogdGhpcy5maW5kUmVwbGFjZURhdGEuX2lkLFxyXG4gICAgICAgICAgfSkudG9Qcm9taXNlKCk7XHJcblxyXG4gICAgICAgICAgY29uc29sZS5sb2coJ0FwcHJvdmUgcmVwbGFjZSByZXNwb25zZTonLCByZXNwb25zZSk7XHJcbiAgICAgICAgICB0aGlzLmFwcHJvdmVMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICBcclxuICAgICAgICAgIC8vIE5hdmlnYXRlIHRvIHRhYmxlIHBhZ2Ugb24gc3VjY2Vzc2Z1bCByZXNwb25zZVxyXG4gICAgICAgICAgaWYgKHJlc3BvbnNlPy5jb2RlID09PSAyMDApIHtcclxuICAgICAgICAgICAgdGhpcy5yb3V0ZXIubmF2aWdhdGUoWycvbWFuYWdlL3BsYW5vZ3JhbS9maW5kLXJlcGxhY2UtdGFibGUnXSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGFwcHJvdmluZyByZXBsYWNlOicsIGVycm9yKTtcclxuICAgICAgICAgIHRoaXMuYXBwcm92ZUxvYWRpbmcgPSBmYWxzZTtcclxuICAgICAgICAgIC8vIFRPRE86IEhhbmRsZSBlcnJvciAoZS5nLiwgc2hvdyBlcnJvciBtZXNzYWdlKVxyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcclxuICAgICAgY29uc29sZS5sb2coJ01vZGFsIGRpc21pc3NlZCcpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgaGFzTm9NYXRjaChzdG9yZTogU3RvcmUpOiBib29sZWFuIHtcclxuICAgIHJldHVybiBzdG9yZS5yZXNwb25zZVN0YXR1cyA9PT0gJ25vLW1hdGNoJztcclxuICB9XHJcblxyXG4gIGlzQXBwcm92ZWQoKTogYm9vbGVhbiB7XHJcbiAgICByZXR1cm4gdGhpcy5maW5kUmVwbGFjZURhdGE/LnN0YXR1cyA9PT0gJ2FwcHJvdmVkJyA7XHJcbiAgfVxyXG5cclxuXHJcbiAgcHJldmlvdXNOZXh0KHN0ZXA6ICdwcmV2aW91cycgfCAnbmV4dCcpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5zZWxlY3RlZFN0b3JlIHx8IHRoaXMuZmlsdGVyZWRTdG9yZXMubGVuZ3RoID09PSAwKSByZXR1cm47XHJcblxyXG4gICAgY29uc3QgY3VySWR4ID0gdGhpcy5maWx0ZXJlZFN0b3Jlcy5maW5kSW5kZXgoXHJcbiAgICAgIChzdG9yZTogU3RvcmUpID0+IHN0b3JlLnN0b3JlTmFtZSA9PT0gdGhpcy5zZWxlY3RlZFN0b3JlPy5zdG9yZU5hbWVcclxuICAgICk7XHJcblxyXG4gICAgbGV0IG5ld0lkeDogbnVtYmVyO1xyXG4gICAgaWYgKHN0ZXAgPT09ICdwcmV2aW91cycpIHtcclxuICAgICAgaWYgKGN1cklkeCA9PT0gMCkgcmV0dXJuO1xyXG4gICAgICBuZXdJZHggPSBjdXJJZHggLSAxO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgaWYgKGN1cklkeCA9PT0gdGhpcy5maWx0ZXJlZFN0b3Jlcy5sZW5ndGggLSAxKSByZXR1cm47XHJcbiAgICAgIG5ld0lkeCA9IGN1cklkeCArIDE7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gVXBkYXRlIHBhZ2luYXRpb24gaWYgdGhlIG5ldyBzdG9yZSBpcyBvbiBhIGRpZmZlcmVudCBwYWdlXHJcbiAgICBjb25zdCBuZXdQYWdlID0gTWF0aC5mbG9vcihuZXdJZHggLyB0aGlzLmxpbWl0KSArIDE7XHJcbiAgICBpZiAobmV3UGFnZSAhPT0gdGhpcy5vZmZzZXQpIHtcclxuICAgICAgdGhpcy5vZmZzZXQgPSBuZXdQYWdlO1xyXG4gICAgICAvLyBTY3JvbGwgdG8gdG9wIG9mIHN0b3JlIGxpc3Qgd2hlbiBwYWdlIGNoYW5nZXNcclxuICAgICAgY29uc3QgbGlzdENvbnRhaW5lciA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJy5saXN0LWNvbnRhaW5lcicpO1xyXG4gICAgICBpZiAobGlzdENvbnRhaW5lcikge1xyXG4gICAgICAgIGxpc3RDb250YWluZXIuc2Nyb2xsVG9wID0gMDtcclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHRoaXMub25TdG9yZVNlbGVjdCh0aGlzLmZpbHRlcmVkU3RvcmVzW25ld0lkeF0pO1xyXG4gIH1cclxuXHJcbiAgcGFnaW5hdGlvblNpemUoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiB0aGlzLmxpbWl0O1xyXG4gIH1cclxuXHJcbiAgb25QYWdlQ2hhbmdlKHBhZ2U6IG51bWJlcik6IHZvaWQge1xyXG4gICAgdGhpcy5vZmZzZXQgPSBwYWdlO1xyXG4gICAgLy8gU2Nyb2xsIHRvIHRvcCBvZiBzdG9yZSBsaXN0IHdoZW4gcGFnZSBjaGFuZ2VzXHJcbiAgICBjb25zdCBsaXN0Q29udGFpbmVyID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcignLmxpc3QtY29udGFpbmVyJyk7XHJcbiAgICBpZiAobGlzdENvbnRhaW5lcikge1xyXG4gICAgICBsaXN0Q29udGFpbmVyLnNjcm9sbFRvcCA9IDA7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBvblBhZ2VTaXplQ2hhbmdlKHNpemU6IG51bWJlcik6IHZvaWQge1xyXG4gICAgdGhpcy5saW1pdCA9IHNpemU7XHJcbiAgICB0aGlzLm9mZnNldCA9IDE7IC8vIFJlc2V0IHRvIGZpcnN0IHBhZ2Ugd2hlbiBwYWdlIHNpemUgY2hhbmdlc1xyXG4gICAgLy8gU2Nyb2xsIHRvIHRvcCBvZiBzdG9yZSBsaXN0IHdoZW4gcGFnZSBzaXplIGNoYW5nZXNcclxuICAgIGNvbnN0IGxpc3RDb250YWluZXIgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKCcubGlzdC1jb250YWluZXInKTtcclxuICAgIGlmIChsaXN0Q29udGFpbmVyKSB7XHJcbiAgICAgIGxpc3RDb250YWluZXIuc2Nyb2xsVG9wID0gMDtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGhpZ2hsaWdodEZpeHR1cmUoY2FudmFzOiBmYWJyaWMuQ2FudmFzLCBncm91cDogYW55LCBibGluazogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICB0aGlzLnJlbW92ZUhpZ2hsaWdodChjYW52YXMpO1xyXG4gICAgdGhpcy5jYW5jZWxIaWdobGlnaHRCbGluayA9IGZhbHNlO1xyXG5cclxuICAgIGNvbnN0IGNlbnRlciA9IGdyb3VwLmdldENlbnRlclBvaW50KCk7XHJcbiAgICBjb25zdCByZWFsV2lkdGggPSBncm91cC53aWR0aCEgKiBncm91cC5zY2FsZVghO1xyXG4gICAgY29uc3QgcmVhbEhlaWdodCA9IGdyb3VwLmhlaWdodCEgKiBncm91cC5zY2FsZVkhO1xyXG5cclxuICAgIGNvbnN0IHJlY3QgPSBuZXcgZmFicmljLlJlY3Qoe1xyXG4gICAgICBsZWZ0OiBjZW50ZXIueCxcclxuICAgICAgdG9wOiBjZW50ZXIueSxcclxuICAgICAgd2lkdGg6IHJlYWxXaWR0aCArIDgsXHJcbiAgICAgIGhlaWdodDogcmVhbEhlaWdodCArIDgsXHJcbiAgICAgIHJ4OiA1LFxyXG4gICAgICByeTogNSxcclxuICAgICAgc3Ryb2tlOiBcIiMwMGFhZmZcIixcclxuICAgICAgc3Ryb2tlV2lkdGg6IDMsXHJcbiAgICAgIGZpbGw6IFwidHJhbnNwYXJlbnRcIixcclxuICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgIGV2ZW50ZWQ6IGZhbHNlLFxyXG4gICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICBhbmdsZTogZ3JvdXAuYW5nbGUgfHwgMCxcclxuICAgICAgb3BhY2l0eTogYmxpbmsgPyAwIDogMSxcclxuICAgIH0pO1xyXG5cclxuICAgIChyZWN0IGFzIGFueSkuZGF0YSA9IHsgdHlwZTogXCJmaXh0dXJlLWhpZ2hsaWdodFwiIH07XHJcbiAgICBjYW52YXMuYWRkKHJlY3QpO1xyXG4gICAgY2FudmFzLm1vdmVPYmplY3RUbyhyZWN0LCBjYW52YXMuZ2V0T2JqZWN0cygpLmxlbmd0aCAtIDEpO1xyXG4gICAgY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgIHRoaXMuYWN0aXZlSGlnaGxpZ2h0ID0gcmVjdDtcclxuXHJcbiAgICBpZiAoIWJsaW5rKSByZXR1cm47XHJcblxyXG4gICAgbGV0IGN5Y2xlcyA9IDA7XHJcbiAgICBjb25zdCBibGlua09uY2UgPSAoKSA9PiB7XHJcbiAgICAgIGlmICh0aGlzLmNhbmNlbEhpZ2hsaWdodEJsaW5rKSB7XHJcbiAgICAgICAgdGhpcy5yZW1vdmVIaWdobGlnaHQoY2FudmFzKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgcmVjdC5hbmltYXRlKHsgb3BhY2l0eTogMSB9LCB7XHJcbiAgICAgICAgZHVyYXRpb246IDIwMCxcclxuICAgICAgICBvbkNoYW5nZTogKCkgPT4gY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKSxcclxuICAgICAgICBvbkNvbXBsZXRlOiAoKSA9PiB7XHJcbiAgICAgICAgICBpZiAodGhpcy5jYW5jZWxIaWdobGlnaHRCbGluaykge1xyXG4gICAgICAgICAgICB0aGlzLnJlbW92ZUhpZ2hsaWdodChjYW52YXMpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICByZWN0LmFuaW1hdGUoeyBvcGFjaXR5OiAwIH0sIHtcclxuICAgICAgICAgICAgZHVyYXRpb246IDIwMCxcclxuICAgICAgICAgICAgb25DaGFuZ2U6ICgpID0+IGNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCksXHJcbiAgICAgICAgICAgIG9uQ29tcGxldGU6ICgpID0+IHtcclxuICAgICAgICAgICAgICBpZiAodGhpcy5jYW5jZWxIaWdobGlnaHRCbGluaykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVIaWdobGlnaHQoY2FudmFzKTtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgY3ljbGVzKys7XHJcbiAgICAgICAgICAgICAgaWYgKGN5Y2xlcyA8IDIwKSB7XHJcbiAgICAgICAgICAgICAgICBibGlua09uY2UoKTtcclxuICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNhbmNlbEhpZ2hsaWdodEJsaW5rKSB7XHJcbiAgICAgICAgICAgICAgICAgIHJlY3Quc2V0KHsgb3BhY2l0eTogMSB9KTtcclxuICAgICAgICAgICAgICAgICAgY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9LFxyXG4gICAgICB9KTtcclxuICAgIH07XHJcbiAgICBibGlua09uY2UoKTtcclxuICB9XHJcblxyXG4gIHJlbW92ZUhpZ2hsaWdodChjYW52YXM6IGZhYnJpYy5DYW52YXMpIHtcclxuICAgIHRoaXMuY2FuY2VsSGlnaGxpZ2h0QmxpbmsgPSB0cnVlO1xyXG4gICAgY2FudmFzLmdldE9iamVjdHMoKS5mb3JFYWNoKChvYmopID0+IHtcclxuICAgICAgaWYgKChvYmogYXMgYW55KS5kYXRhPy50eXBlID09PSBcImZpeHR1cmUtaGlnaGxpZ2h0XCIpIHtcclxuICAgICAgICBjYW52YXMucmVtb3ZlKG9iaik7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgdGhpcy5hY3RpdmVIaWdobGlnaHQgPSBudWxsO1xyXG4gICAgY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICB9XHJcblxyXG4gIG9uRml4dHVyZUNsaWNrKHRhcmdldDogYW55KTogdm9pZCB7XHJcbiAgICBpZiAoIXRhcmdldCB8fCAhdGhpcy5mbG9vckRhdGEpIHJldHVybjtcclxuXHJcbiAgICBjb25zdCBmaXh0dXJlSWQgPSAodGFyZ2V0IGFzIGFueSkuZml4dHVyZUlkO1xyXG4gICAgY29uc3QgZml4dHVyZVR5cGUgPSAodGFyZ2V0IGFzIGFueSkuZml4dHVyZVR5cGU7XHJcblxyXG4gICAgaWYgKCFmaXh0dXJlSWQpIHtcclxuICAgICAgY29uc29sZS53YXJuKCdGaXh0dXJlIGNsaWNrOiBObyBmaXh0dXJlSWQgZm91bmQgb24gdGFyZ2V0JywgdGFyZ2V0KTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEZpbmQgdGhlIGZpeHR1cmUgZGF0YVxyXG4gICAgbGV0IGZpeHR1cmVEYXRhOiBhbnkgPSBudWxsO1xyXG5cclxuICAgIGlmIChmaXh0dXJlVHlwZSA9PT0gXCJ3YWxsXCIpIHtcclxuICAgICAgY29uc3Qgd2FsbEluZGV4ID0gKHRhcmdldCBhcyBhbnkpLndhbGxJbmRleDtcclxuXHJcbiAgICAgIGlmICh0aGlzLmZsb29yRGF0YS5sYXlvdXRQb2x5Z29uICYmIHdhbGxJbmRleCAhPT0gdW5kZWZpbmVkICYmIHdhbGxJbmRleCAhPT0gbnVsbCkge1xyXG4gICAgICAgIC8vIEZpbmQgd2FsbCBieSBlbGVtZW50TnVtYmVyICh3YWxsSW5kZXggaXMgdGhlIGVsZW1lbnROdW1iZXIpXHJcbiAgICAgICAgY29uc3Qgd2FsbCA9IHRoaXMuZmxvb3JEYXRhLmxheW91dFBvbHlnb24uZmluZChcclxuICAgICAgICAgICh3OiBhbnkpID0+IHcuZWxlbWVudE51bWJlciA9PT0gd2FsbEluZGV4XHJcbiAgICAgICAgKTtcclxuICAgICAgICBpZiAod2FsbCAmJiB3YWxsLmZpeHR1cmVzKSB7XHJcbiAgICAgICAgICBmaXh0dXJlRGF0YSA9IHdhbGwuZml4dHVyZXMuZmluZCgoZjogYW55KSA9PiBmLl9pZCA9PT0gZml4dHVyZUlkKTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSBpZiAoZml4dHVyZVR5cGUgPT09IFwiZmxvb3JcIikge1xyXG4gICAgICBmaXh0dXJlRGF0YSA9IHRoaXMuZmxvb3JEYXRhLmNlbnRlckZpeHR1cmU/LmZpbmQoKGY6IGFueSkgPT4gZi5faWQgPT09IGZpeHR1cmVJZCk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFmaXh0dXJlRGF0YSkge1xyXG4gICAgICBjb25zb2xlLndhcm4oJ0ZpeHR1cmUgY2xpY2s6IEZpeHR1cmUgZGF0YSBub3QgZm91bmQnLCB7XHJcbiAgICAgICAgZml4dHVyZUlkLFxyXG4gICAgICAgIGZpeHR1cmVUeXBlLFxyXG4gICAgICAgIHdhbGxJbmRleDogKHRhcmdldCBhcyBhbnkpLndhbGxJbmRleCxcclxuICAgICAgICBmaXh0dXJlSW5kZXg6ICh0YXJnZXQgYXMgYW55KS5maXh0dXJlSW5kZXgsXHJcbiAgICAgICAgZmxvb3JEYXRhOiB0aGlzLmZsb29yRGF0YVxyXG4gICAgICB9KTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEVuc3VyZSB2bUNvbmZpZyBpcyBhbHdheXMgYW4gYXJyYXkgKGV2ZW4gaWYgZW1wdHkpIHRvIGF2b2lkIGRpc3BsYXkgaXNzdWVzXHJcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZml4dHVyZURhdGEudm1Db25maWcpKSB7XHJcbiAgICAgIGZpeHR1cmVEYXRhLnZtQ29uZmlnID0gW107XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRW5zdXJlIHNoZWxmQ29uZmlnIGlzIGFsd2F5cyBhbiBhcnJheSAoZXZlbiBpZiBlbXB0eSkgdG8gYXZvaWQgZGlzcGxheSBpc3N1ZXNcclxuICAgIGlmICghQXJyYXkuaXNBcnJheShmaXh0dXJlRGF0YS5zaGVsZkNvbmZpZykpIHtcclxuICAgICAgZml4dHVyZURhdGEuc2hlbGZDb25maWcgPSBbXTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBDcmVhdGUgYSBkZWVwIGNsb25lIHRvIGVuc3VyZSBjaGFuZ2UgZGV0ZWN0aW9uIHdvcmtzXHJcbiAgICBjb25zdCBjbG9uZWREYXRhID0gc3RydWN0dXJlZENsb25lKGZpeHR1cmVEYXRhKTtcclxuXHJcbiAgICAvLyBFbnN1cmUgY2xvbmVkIGRhdGEgYWxzbyBoYXMgcHJvcGVyIGFycmF5IHN0cnVjdHVyZXNcclxuICAgIGlmICghQXJyYXkuaXNBcnJheShjbG9uZWREYXRhLnZtQ29uZmlnKSkge1xyXG4gICAgICBjbG9uZWREYXRhLnZtQ29uZmlnID0gW107XHJcbiAgICB9XHJcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoY2xvbmVkRGF0YS5zaGVsZkNvbmZpZykpIHtcclxuICAgICAgY2xvbmVkRGF0YS5zaGVsZkNvbmZpZyA9IFtdO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuc2VsZWN0ZWRGaXh0dXJlID0ge1xyXG4gICAgICBmaXh0dXJlSWQ6IGZpeHR1cmVJZCxcclxuICAgICAgZml4dHVyZVR5cGU6IGZpeHR1cmVUeXBlLFxyXG4gICAgICB3YWxsSW5kZXg6ICh0YXJnZXQgYXMgYW55KS53YWxsSW5kZXgsXHJcbiAgICAgIGZpeHR1cmVJbmRleDogKHRhcmdldCBhcyBhbnkpLmZpeHR1cmVJbmRleCxcclxuICAgIH07XHJcblxyXG4gICAgLy8gQ2hlY2sgaWYgdGhpcyBmaXh0dXJlIGhhcyByZXBsYWNlUmVzcG9uc2VEYXRhIChmb3IgYmVmb3JlL2FmdGVyIGNvbXBhcmlzb24pXHJcbiAgICBjb25zdCBzdG9yZSA9IHRoaXMuZmluZFJlcGxhY2VEYXRhPy5zdG9yZXM/LmZpbmQoXHJcbiAgICAgIChzOiBTdG9yZSkgPT4gcy5zdG9yZU5hbWUgPT09IHRoaXMuc2VsZWN0ZWRTdG9yZT8uc3RvcmVOYW1lXHJcbiAgICApO1xyXG5cclxuICAgIC8vIElmIHRoaXMgZml4dHVyZSBtYXRjaGVzIHRoZSBmaW5kUmVzcG9uc2VEYXRhIGFuZCBoYXMgcmVwbGFjZVJlc3BvbnNlRGF0YSxcclxuICAgIC8vIHJlc3RvcmUgdGhlIG9yaWdpbmFsIGZpeHR1cmUgZGF0YSBmb3IgYmVmb3JlL2FmdGVyIGNvbXBhcmlzb25cclxuICAgIGlmIChzdG9yZT8uZmluZFJlc3BvbnNlRGF0YSA9PT0gZml4dHVyZUlkICYmIHN0b3JlPy5yZXBsYWNlUmVzcG9uc2VEYXRhKSB7XHJcbiAgICAgIC8vIFJlc3RvcmUgb3JpZ2luYWxGaXh0dXJlRGF0YSBmcm9tIHRoZSBtYXAgKHBlcnNpc3RzIGV2ZW4gd2hlbiBjbGlja2luZyBvdGhlciBmaXh0dXJlcylcclxuICAgICAgY29uc3Qgc3RvcmVkT3JpZ2luYWwgPSB0aGlzLm9yaWdpbmFsRml4dHVyZXNNYXAuZ2V0KGZpeHR1cmVJZCk7XHJcbiAgICAgIGlmIChzdG9yZWRPcmlnaW5hbCkge1xyXG4gICAgICAgIHRoaXMub3JpZ2luYWxGaXh0dXJlRGF0YSA9IHN0cnVjdHVyZWRDbG9uZShzdG9yZWRPcmlnaW5hbCk7XHJcbiAgICAgICAgLy8gRW5zdXJlIG9yaWdpbmFsIGRhdGEgaGFzIHByb3BlciBhcnJheSBzdHJ1Y3R1cmVzXHJcbiAgICAgICAgaWYgKCFBcnJheS5pc0FycmF5KHRoaXMub3JpZ2luYWxGaXh0dXJlRGF0YS52bUNvbmZpZykpIHtcclxuICAgICAgICAgIHRoaXMub3JpZ2luYWxGaXh0dXJlRGF0YS52bUNvbmZpZyA9IFtdO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy5vcmlnaW5hbEZpeHR1cmVEYXRhLnNoZWxmQ29uZmlnKSkge1xyXG4gICAgICAgICAgdGhpcy5vcmlnaW5hbEZpeHR1cmVEYXRhLnNoZWxmQ29uZmlnID0gW107XHJcbiAgICAgICAgfVxyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIC8vIElmIG5vdCBpbiBtYXAgKHNob3VsZG4ndCBoYXBwZW4gaWYgYXBwbHlTdG9yZWRSZXNwb25zZURhdGEgcmFuKSwgXHJcbiAgICAgICAgLy8gdXNlIGN1cnJlbnQgZml4dHVyZSBhcyBmYWxsYmFja1xyXG4gICAgICAgIHRoaXMub3JpZ2luYWxGaXh0dXJlRGF0YSA9IHN0cnVjdHVyZWRDbG9uZShjbG9uZWREYXRhKTtcclxuICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkodGhpcy5vcmlnaW5hbEZpeHR1cmVEYXRhLnZtQ29uZmlnKSkge1xyXG4gICAgICAgICAgdGhpcy5vcmlnaW5hbEZpeHR1cmVEYXRhLnZtQ29uZmlnID0gW107XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmICghQXJyYXkuaXNBcnJheSh0aGlzLm9yaWdpbmFsRml4dHVyZURhdGEuc2hlbGZDb25maWcpKSB7XHJcbiAgICAgICAgICB0aGlzLm9yaWdpbmFsRml4dHVyZURhdGEuc2hlbGZDb25maWcgPSBbXTtcclxuICAgICAgICB9XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIE5vIHJlcGxhY2UgZGF0YSBmb3IgdGhpcyBmaXh0dXJlLCBjbGVhciBvcmlnaW5hbFxyXG4gICAgICB0aGlzLm9yaWdpbmFsRml4dHVyZURhdGEgPSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFNldCBzZWxlY3RlZCBmaXh0dXJlIGRhdGEgKHRoaXMgaXMgdGhlIFwiYWZ0ZXJcIiBkYXRhIHdpdGggcmVwbGFjZVJlc3BvbnNlRGF0YSBhcHBsaWVkKVxyXG4gICAgLy8gRm9yIGZpeHR1cmVzIHdpdGggcmVwbGFjZVJlc3BvbnNlRGF0YSwgZW5zdXJlIGFsbCBvcmlnaW5hbCBwcm9wZXJ0aWVzIGFyZSBwcmVzZXJ2ZWRcclxuICAgIGlmIChzdG9yZT8uZmluZFJlc3BvbnNlRGF0YSA9PT0gZml4dHVyZUlkICYmIHN0b3JlPy5yZXBsYWNlUmVzcG9uc2VEYXRhKSB7XHJcbiAgICAgIGNvbnN0IHN0b3JlZE9yaWdpbmFsID0gdGhpcy5vcmlnaW5hbEZpeHR1cmVzTWFwLmdldChmaXh0dXJlSWQpO1xyXG4gICAgICBpZiAoc3RvcmVkT3JpZ2luYWwpIHtcclxuICAgICAgICAvLyBNZXJnZTogc3RhcnQgd2l0aCBvcmlnaW5hbCB0byBwcmVzZXJ2ZSBhbGwgYmFzZSBwcm9wZXJ0aWVzLCB0aGVuIGFwcGx5IHVwZGF0ZXNcclxuICAgICAgICB0aGlzLnNlbGVjdGVkRml4dHVyZURhdGEgPSB7XHJcbiAgICAgICAgICAuLi5zdG9yZWRPcmlnaW5hbCwgIC8vIFByZXNlcnZlIGFsbCBvcmlnaW5hbCBwcm9wZXJ0aWVzIChmaXh0dXJlVHlwZSwgaGVhZGVyLCBmb290ZXIsIGV0Yy4pXHJcbiAgICAgICAgICAuLi5jbG9uZWREYXRhLCAgICAgIC8vIEFwcGx5IHVwZGF0ZWQgZGF0YSAod2hpY2ggaGFzIHJlcGxhY2VSZXNwb25zZURhdGEgYXBwbGllZClcclxuICAgICAgICAgIC8vIEV4cGxpY2l0bHkgZW5zdXJlIGFycmF5cyBhcmUgY29ycmVjdFxyXG4gICAgICAgICAgdm1Db25maWc6IEFycmF5LmlzQXJyYXkoY2xvbmVkRGF0YS52bUNvbmZpZykgPyBjbG9uZWREYXRhLnZtQ29uZmlnIDogKHN0b3JlZE9yaWdpbmFsLnZtQ29uZmlnIHx8IFtdKSxcclxuICAgICAgICAgIHNoZWxmQ29uZmlnOiBBcnJheS5pc0FycmF5KGNsb25lZERhdGEuc2hlbGZDb25maWcpID8gY2xvbmVkRGF0YS5zaGVsZkNvbmZpZyA6IChzdG9yZWRPcmlnaW5hbC5zaGVsZkNvbmZpZyB8fCBbXSlcclxuICAgICAgICB9O1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YSA9IGNsb25lZERhdGE7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YSA9IGNsb25lZERhdGE7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRG9uJ3QgaGlnaGxpZ2h0IG9uIGNsaWNrIC0ga2VlcCBoaWdobGlnaHQgZml4ZWQgb24gdGhlIGZpeHR1cmUgd2l0aCBmaW5kUmVzcG9uc2VEYXRhXHJcbiAgICAvLyBUaGUgaGlnaGxpZ2h0IGlzIHNldCB3aGVuIHRoZSBwbGFub2dyYW0gbG9hZHMgYW5kIHNob3VsZCByZW1haW4gZml4ZWRcclxuXHJcbiAgICAvLyBPcGVuIG9mZmNhbnZhcyB3aXRoIGJlZm9yZS9hZnRlciBjb21wYXJpc29uXHJcbiAgICB0aGlzLm9wZW5GaXh0dXJlT2ZmY2FudmFzKCk7XHJcbiAgfVxyXG5cclxuICBvcGVuRml4dHVyZU9mZmNhbnZhcygpOiB2b2lkIHtcclxuICAgIC8vIFVzZSB3aWRlciBvZmZjYW52YXMgd2hlbiBzaG93aW5nIGJlZm9yZS9hZnRlciBjb21wYXJpc29uXHJcbiAgICBjb25zdCBoYXNCZWZvcmVBZnRlciA9ICEhdGhpcy5vcmlnaW5hbEZpeHR1cmVEYXRhO1xyXG4gICAgY29uc3QgcGFuZWxDbGFzcyA9IGhhc0JlZm9yZUFmdGVyXHJcbiAgICAgID8gJ2ZpeHR1cmUtYmVmb3JlLWFmdGVyLW9mZmNhbnZhcy13aWRlJ1xyXG4gICAgICA6ICdmaXh0dXJlLWJlZm9yZS1hZnRlci1vZmZjYW52YXMnO1xyXG5cclxuICAgIGNvbnN0IG9mZmNhbnZhc1JlZiA9IHRoaXMub2ZmY2FudmFzU2VydmljZS5vcGVuKEZpeHR1cmVCZWZvcmVBZnRlckNvbXBvbmVudCwge1xyXG4gICAgICBwb3NpdGlvbjogJ2VuZCcsXHJcbiAgICAgIHBhbmVsQ2xhc3M6IHBhbmVsQ2xhc3MsXHJcbiAgICAgIGJhY2tkcm9wOiB0cnVlLFxyXG4gICAgICBiYWNrZHJvcENsYXNzOiAnb2ZmY2FudmFzLWJhY2tkcm9wJ1xyXG4gICAgfSk7XHJcblxyXG4gICAgb2ZmY2FudmFzUmVmLmNvbXBvbmVudEluc3RhbmNlLnNlbGVjdGVkRml4dHVyZURhdGEgPSB0aGlzLnNlbGVjdGVkRml4dHVyZURhdGE7XHJcbiAgICBvZmZjYW52YXNSZWYuY29tcG9uZW50SW5zdGFuY2Uub3JpZ2luYWxGaXh0dXJlRGF0YSA9IHRoaXMub3JpZ2luYWxGaXh0dXJlRGF0YTtcclxuICB9XHJcblxyXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xyXG4gICAgdGhpcy5kZXN0cm95JC5uZXh0KCk7XHJcbiAgICB0aGlzLmRlc3Ryb3kkLmNvbXBsZXRlKCk7XHJcbiAgICBpZiAodGhpcy5wcmV2aWV3Q2FudmFzKSB7XHJcbiAgICAgIHRoaXMucHJldmlld0NhbnZhcy5kaXNwb3NlKCk7XHJcbiAgICB9XHJcbiAgfVxyXG59XHJcbiIsIjxkaXYgY2xhc3M9XCJyZXZpZXctcmVwbGFjZS1jb250YWluZXJcIj5cclxuICAgIDxkaXYgY2xhc3M9XCJyb3cgZy0wIGgtMTAwXCI+XHJcbiAgICAgICAgPCEtLSBMZWZ0IFNpZGViYXI6IFN0b3JlIExpc3QgLS0+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC0zIHNpZGViYXItY29udGFpbmVyXCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzaWRlYmFyLWNvbnRlbnRcIj5cclxuICAgICAgICAgICAgICAgIDwhLS0gSGVhZGVyIFNlY3Rpb24gLS0+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiaGVhZGVyLXNlY3Rpb25cIj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiYWxsLXN0b3Jlcy1ib3hcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHAgY2xhc3M9XCJhbGwtc3RvcmVzLXRleHRcIj5BbGwgc3RvcmVzPC9wPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDxidXR0b24gY2xhc3M9XCJkb3dubG9hZC1idG5cIiAoY2xpY2spPVwib25Eb3dubG9hZCgpXCIgYXJpYS1sYWJlbD1cIkRvd25sb2FkXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxzdmcgd2lkdGg9XCIyMFwiIGhlaWdodD1cIjIwXCIgdmlld0JveD1cIjAgMCAyMCAyMFwiIGZpbGw9XCJub25lXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPVwiTTE3LjUgMTIuNVYxMy41QzE3LjUgMTQuOTAwMSAxNy41IDE1LjYwMDIgMTcuMjI3NSAxNi4xMzVDMTYuOTg3OCAxNi42MDU0IDE2LjYwNTQgMTYuOTg3OCAxNi4xMzUgMTcuMjI3NUMxNS42MDAyIDE3LjUgMTQuOTAwMSAxNy41IDEzLjUgMTcuNUg2LjVDNS4wOTk4NyAxNy41IDQuMzk5OCAxNy41IDMuODY1MDIgMTcuMjI3NUMzLjM5NDYyIDE2Ljk4NzggMy4wMTIxNyAxNi42MDU0IDIuNzcyNDggMTYuMTM1QzIuNSAxNS42MDAyIDIuNSAxNC45MDAxIDIuNSAxMy41VjEyLjVNMTQuMTY2NyA4LjMzMzMzTDEwIDEyLjVNMTAgMTIuNUw1LjgzMzMzIDguMzMzMzNNMTAgMTIuNVYyLjVcIiBzdHJva2U9XCIjMzQ0MDU0XCIgc3Ryb2tlLXdpZHRoPVwiMlwiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiLz5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICAgICAgICA8IS0tIFNlbGVjdCBBbGwgU2VjdGlvbiAtLT5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWxlY3QtYWxsLXNlY3Rpb25cIj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZm9ybS1jaGVja1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIiBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWQ9XCJzZWxlY3RBbGxcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2NoZWNrZWRdPVwiaXNBbGxTZWxlY3RlZCgpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjaGFuZ2UpPVwib25TZWxlY3RBbGwoJGFueSgkZXZlbnQudGFyZ2V0KS5jaGVja2VkKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJmb3JtLWNoZWNrLWxhYmVsIHNlbGVjdC1hbGwtbGFiZWxcIiBmb3I9XCJzZWxlY3RBbGxcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFNlbGVjdCBhbGwgKHt7IGZpbHRlcmVkU3RvcmVzLmxlbmd0aCB9fSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9sYWJlbD5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgICAgICAgIDwhLS0gU2VhcmNoIGFuZCBGaWx0ZXIgU2VjdGlvbiAtLT5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWFyY2gtZmlsdGVyLXNlY3Rpb25cIj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2VhcmNoLWlucHV0LXdyYXBwZXJcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHN2ZyBjbGFzcz1cInNlYXJjaC1pY29uXCIgdmlld0JveD1cIjAgMCAyMCAyMFwiIGZpbGw9XCJub25lXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPVwiTTE3LjUgMTcuNUwxMy44NzUgMTMuODc1TTE1LjgzMzMgOS4xNjY2N0MxNS44MzMzIDEyLjg0ODYgMTIuODQ4NiAxNS44MzMzIDkuMTY2NjcgMTUuODMzM0M1LjQ4NDc3IDE1LjgzMzMgMi41IDEyLjg0ODYgMi41IDkuMTY2NjdDMi41IDUuNDg0NzcgNS40ODQ3NyAyLjUgOS4xNjY2NyAyLjVDMTIuODQ4NiAyLjUgMTUuODMzMyA1LjQ4NDc3IDE1LjgzMzMgOS4xNjY2N1pcIiBzdHJva2U9XCIjNjY3MDg1XCIgc3Ryb2tlLXdpZHRoPVwiMS42NjY2N1wiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiLz5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxpbnB1dCBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJ0ZXh0XCIgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cInNlYXJjaC1pbnB1dFwiIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJTZWFyY2hcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgWyhuZ01vZGVsKV09XCJzZWFyY2hUZXJtXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChpbnB1dCk9XCJvblNlYXJjaCgpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImRyb3Bkb3duXCIgbmdiRHJvcGRvd24+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZpbHRlci1idG5cIiBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtjbGFzcy5hY3RpdmVdPVwiaGFzQWN0aXZlRmlsdGVycygpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlkPVwiZmlsdGVyRHJvcGRvd25cIiBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5nYkRyb3Bkb3duVG9nZ2xlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhcmlhLWxhYmVsPVwiRmlsdGVyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3ZnIHdpZHRoPVwiMTlcIiBoZWlnaHQ9XCIxN1wiIHZpZXdCb3g9XCIwIDAgMTkgMTdcIiBmaWxsPVwibm9uZVwiIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPVwiTTE3LjUwMjYgMC44MzU5MzhIMC44MzU5MzhMNy41MDI2IDguNzE5MjdWMTQuMTY5M0wxMC44MzU5IDE1LjgzNTlWOC43MTkyN0wxNy41MDI2IDAuODM1OTM4WlwiIHN0cm9rZT1cIiMzNDQwNTRcIiBzdHJva2Utd2lkdGg9XCIxLjY3XCIgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCIvPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cImhhc0FjdGl2ZUZpbHRlcnMoKVwiIGNsYXNzPVwiZmlsdGVyLWJhZGdlXCI+e3sgc2VsZWN0ZWRTdGF0dXNGaWx0ZXJzLnNpemUgfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZHJvcGRvd24tbWVudSBmaWx0ZXItZHJvcGRvd25cIiBuZ2JEcm9wZG93bk1lbnUgYXJpYS1sYWJlbGxlZGJ5PVwiZmlsdGVyRHJvcGRvd25cIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaWx0ZXItZHJvcGRvd24taGVhZGVyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGg2IGNsYXNzPVwiZmlsdGVyLXRpdGxlXCI+RmlsdGVyIGJ5IFN0YXR1czwvaDY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGJ1dHRvbiBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJoYXNBY3RpdmVGaWx0ZXJzKClcIiBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJjbGVhci1maWx0ZXJzLWJ0blwiIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwiY2xlYXJGaWx0ZXJzKClcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ2xlYXJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbHRlci1kcm9wZG93bi1ib2R5XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKm5nRm9yPVwibGV0IG9wdGlvbiBvZiBzdGF0dXNPcHRpb25zXCIgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZmlsdGVyLW9wdGlvblwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZvcm0tY2hlY2staW5wdXRcIiBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGU9XCJjaGVja2JveFwiIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2lkXT1cIidzdGF0dXNGaWx0ZXInICsgb3B0aW9uLnZhbHVlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtjaGVja2VkXT1cImlzU3RhdHVzRmlsdGVyU2VsZWN0ZWQob3B0aW9uLnZhbHVlKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2hhbmdlKT1cIm9uU3RhdHVzRmlsdGVyQ2hhbmdlKG9wdGlvbi52YWx1ZSwgJGV2ZW50KVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGFiZWwgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZm9yXT1cIidzdGF0dXNGaWx0ZXInICsgb3B0aW9uLnZhbHVlXCIgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImZpbHRlci1vcHRpb24tbGFiZWxcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7IG9wdGlvbi5sYWJlbCB9fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xhYmVsPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgICAgICAgPCEtLSBTdG9yZSBMaXN0IENvbnRhaW5lciAoU2Nyb2xsYWJsZSkgLS0+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwibGlzdC1jb250YWluZXJcIj5cclxuICAgICAgICAgICAgICAgICAgICA8IS0tIFN0b3JlIExpc3QgLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0b3JlLWxpc3RcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICpuZ0Zvcj1cImxldCBzdG9yZSBvZiBwYWdpbmF0ZWRTdG9yZXM7IGxldCBpID0gaW5kZXhcIiBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwic3RvcmUtaXRlbVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbY2xhc3Muc2VsZWN0ZWRdPVwic2VsZWN0ZWRTdG9yZT8uc3RvcmVOYW1lID09PSBzdG9yZS5zdG9yZU5hbWVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cIm9uU3RvcmVTZWxlY3Qoc3RvcmUpXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3RvcmUtaXRlbS1jb250ZW50XCIgW2NsYXNzLmRpc2FibGVkLWNvbnRlbnRdPVwiaGFzTm9NYXRjaChzdG9yZSlcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwiZm9ybS1jaGVjay1pbnB1dFwiIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiY2hlY2tib3hcIiBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2lkXT1cIidzdG9yZScgKyBpXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2NoZWNrZWRdPVwic3RvcmUuaXNBcHByb3ZlZCA9PT0gdHJ1ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtkaXNhYmxlZF09XCJoYXNOb01hdGNoKHN0b3JlKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCIkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2hhbmdlKT1cIm9uU3RvcmVDaGVja2JveENoYW5nZShzdG9yZSwgJGFueSgkZXZlbnQudGFyZ2V0KS5jaGVja2VkKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxsYWJlbCBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJzdG9yZS1pdGVtLXRleHRcIiBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Zvcl09XCInc3RvcmUnICsgaVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtjbGFzcy5kaXNhYmxlZF09XCJoYXNOb01hdGNoKHN0b3JlKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJoYXNOb01hdGNoKHN0b3JlKSAmJiAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgc3RvcmUuc3RvcmVOYW1lIH19XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9sYWJlbD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJoYXNOb01hdGNoKHN0b3JlKVwiIGNsYXNzPVwiYmFkZ2UtZXJyb3JcIj5EaWRuJ3QgbWF0Y2g8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICA8IS0tIFJpZ2h0IFNpZGU6IENhbnZhcyBBcmVhIC0tPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtOSBjYW52YXMtYXJlYS1jb250YWluZXJcIj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhbnZhcy13cmFwcGVyXCI+XHJcbiAgICAgICAgICAgICAgICA8IS0tIEhlYWRlciBTZWN0aW9uIHdpdGggU3RvcmUgU2xpZGVyIGFuZCBBcHByb3ZlIEJ1dHRvbiAtLT5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjYW52YXMtaGVhZGVyXCIgKm5nSWY9XCJzZWxlY3RlZFN0b3JlICYmICFjYW52YXNMb2FkaW5nXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPCEtLSBTdG9yZSBTbGlkZXIgTmF2aWdhdGlvbiAtLT5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3RvcmUtc2xpZGVyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiAoY2xpY2spPVwicHJldmlvdXNOZXh0KCdwcmV2aW91cycpXCIgY2xhc3M9XCJhcnJvd1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIjIzXCIgaGVpZ2h0PVwiMjRcIiB2aWV3Qm94PVwiMCAwIDIzIDI0XCIgZmlsbD1cIm5vbmVcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZD1cIk0xNC4zOTQyIDYuMzMzMjlMOC43Mjc1NiAxMkwxNC4zOTQyIDE3LjY2NjZcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cm9rZT1cIiMzNDQwNTRcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cm9rZS13aWR0aD1cIjEuODg4ODlcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvc3ZnPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXZcclxuICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJzdG9yZW5hbWVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbcm91dGVyTGlua109XCJbJy9tYW5hZ2Uvc3RvcmVzL3BsYW5vJ11cIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbcXVlcnlQYXJhbXNdPVwieyBzdG9yZUlkOiBzZWxlY3RlZFN0b3JlLnN0b3JlSWQgfVwiXHJcbiAgICAgICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInR4dCBtZS0zXCI+e3sgc2VsZWN0ZWRTdG9yZS5zdG9yZU5hbWUgfX0gLSBQbGFubzwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPHN2Z1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3R5bGU9XCJjdXJzb3I6IHBvaW50ZXJcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aWR0aD1cIjI0XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhlaWdodD1cIjI0XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZpZXdCb3g9XCIwIDAgMjQgMjRcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZmlsbD1cIm5vbmVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cGF0aFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGQ9XCJNMTcuNjI2MSAxMi45Njg4VjE4Ljc4MTlDMTcuNjI2MSAxOS4yOTU4IDE3LjQyMiAxOS43ODg2IDE3LjA1ODYgMjAuMTUyQzE2LjY5NTIgMjAuNTE1NCAxNi4yMDIzIDIwLjcxOTUgMTUuNjg4NCAyMC43MTk1SDUuMDMxMTlDNC41MTcyOCAyMC43MTk1IDQuMDI0NDMgMjAuNTE1NCAzLjY2MTA0IDIwLjE1MkMzLjI5NzY1IDE5Ljc4ODYgMy4wOTM1MSAxOS4yOTU4IDMuMDkzNTEgMTguNzgxOVY4LjEyNDZDMy4wOTM1MSA3LjYxMDcgMy4yOTc2NSA3LjExNzg0IDMuNjYxMDQgNi43NTQ0NUM0LjAyNDQzIDYuMzkxMDcgNC41MTcyOCA2LjE4NjkyIDUuMDMxMTkgNi4xODY5MkgxMC44NDQyTTE0LjcxOTYgMy4yODA0SDIwLjUzMjZNMjAuNTMyNiAzLjI4MDRWOS4wOTM0NE0yMC41MzI2IDMuMjgwNEw5Ljg3NTM5IDEzLjkzNzZcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cm9rZT1cIiMwMDhFREZcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cm9rZS13aWR0aD1cIjEuOTM3NjhcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvc3ZnPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgKGNsaWNrKT1cInByZXZpb3VzTmV4dCgnbmV4dCcpXCIgY2xhc3M9XCJhcnJvd1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8c3ZnIHhtbG5zPVwiaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmdcIiB3aWR0aD1cIjIzXCIgaGVpZ2h0PVwiMjRcIiB2aWV3Qm94PVwiMCAwIDIzIDI0XCIgZmlsbD1cIm5vbmVcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZD1cIk04LjYwNTkgMTcuNjY2N0wxNC4yNzI2IDEyTDguNjA1OSA2LjMzMzM3XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2U9XCIjMzQ0MDU0XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2Utd2lkdGg9XCIxLjg4ODg5XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2UtbGluZWNhcD1cInJvdW5kXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L3N2Zz5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICA8IS0tIEFwcHJvdmUgQW5kIENvbXBsZXRlIEJ1dHRvbiAtLT5cclxuICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYXBwcm92ZS1jb21wbGV0ZS1idG5cIiAoY2xpY2spPVwib25BcHByb3ZlQW5kQ29tcGxldGUoKVwiIFtkaXNhYmxlZF09XCJhcHByb3ZlTG9hZGluZyB8fCBpc0FwcHJvdmVkKClcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAge3sgYXBwcm92ZUxvYWRpbmcgPyAnUHJvY2Vzc2luZy4uLicgOiAoaXNBcHByb3ZlZCgpID8gJ0FwcHJvdmVkJyA6ICdBcHByb3ZlICYgQ29tcGxldGUnKSB9fVxyXG4gICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgICAgICAgPCEtLSBDYW52YXMgQ29udGFpbmVyIC0tPlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhbnZhcy1jb250YWluZXJcIiAjcHJldmlld0NhbnZhc0NvbnRhaW5lciAqbmdJZj1cInNlbGVjdGVkU3RvcmVcIj5cclxuICAgICAgICAgICAgICAgICAgICA8IS0tIExvYWRpbmcgU3RhdGUgLSBDZW50ZXJlZCBvbiBDYW52YXMgLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhbnZhcy1sb2FkaW5nXCIgKm5nSWY9XCJjYW52YXNMb2FkaW5nXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzcGlubmVyLWJvcmRlciB0ZXh0LXByaW1hcnlcIiByb2xlPVwic3RhdHVzXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInZpc3VhbGx5LWhpZGRlblwiPkxvYWRpbmcuLi48L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgIDxjYW52YXMgI3ByZXZpZXdDYW52YXM+PC9jYW52YXM+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICAgICAgICA8IS0tIEVtcHR5IFN0YXRlIC0tPlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImVtcHR5LXN0YXRlXCIgKm5nSWY9XCIhc2VsZWN0ZWRTdG9yZVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxwPlNlbGVjdCBhIHN0b3JlIHRvIHZpZXcgaXRzIHBsYW5vZ3JhbTwvcD5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICAgIDwhLS0gUGFnaW5hdGlvbiAtLT5cclxuICAgICAgICAgICAgPGxpYi1wYWdpbmF0aW9uXHJcbiAgICAgICAgICAgICAgICAqbmdJZj1cImZpbHRlcmVkU3RvcmVzLmxlbmd0aCA+IDBcIlxyXG4gICAgICAgICAgICAgICAgW2l0ZW1zUGVyUGFnZV09XCJsaW1pdFwiXHJcbiAgICAgICAgICAgICAgICBbY3VycmVudFBhZ2VdPVwib2Zmc2V0XCJcclxuICAgICAgICAgICAgICAgIFt0b3RhbEl0ZW1zXT1cInRvdGFsSXRlbXNcIlxyXG4gICAgICAgICAgICAgICAgW3BhZ2luYXRpb25TaXplc109XCJwYWdpbmF0aW9uU2l6ZXNcIlxyXG4gICAgICAgICAgICAgICAgW3BhZ2VTaXplXT1cInBhZ2luYXRpb25TaXplKClcIlxyXG4gICAgICAgICAgICAgICAgKHBhZ2VDaGFuZ2UpPVwib25QYWdlQ2hhbmdlKCRldmVudClcIlxyXG4gICAgICAgICAgICAgICAgKHBhZ2VTaXplQ2hhbmdlKT1cIm9uUGFnZVNpemVDaGFuZ2UoJGV2ZW50KVwiPlxyXG4gICAgICAgICAgICA8L2xpYi1wYWdpbmF0aW9uPlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbjwvZGl2PlxyXG4iXX0=