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,2524 @@
1
+ import { Component, ViewChild } from '@angular/core';
2
+ import { ReactiveFormsModule, FormsModule } from '@angular/forms';
3
+ import { CommonModule, TitleCasePipe } from '@angular/common';
4
+ import { ReactiveSelectComponent } from '../../../reactive-select/reactive-select.component';
5
+ import { StoreSelectComponent } from '../../components/store-select/store-select.component';
6
+ import { StoreDropdownComponent } from '../../components/store-dropdown/store-dropdown.component';
7
+ import { FormControl } from '@angular/forms';
8
+ import { Subject, takeUntil } from 'rxjs';
9
+ import * as fabric from "fabric";
10
+ import { StoreFixtureComponent } from '../../components/store-fixture/store-fixture.component';
11
+ import { BatchConfirmationModalComponent } from './batch-confirmation-modal/batch-confirmation-modal.component';
12
+ import * as i0 from "@angular/core";
13
+ import * as i1 from "../../../../services/store-builder.service";
14
+ import * as i2 from "../../services/data.service";
15
+ import * as i3 from "@angular/common";
16
+ import * as i4 from "tango-app-ui-global";
17
+ import * as i5 from "@angular/router";
18
+ import * as i6 from "tango-app-ui-shared";
19
+ import * as i7 from "@ng-bootstrap/ng-bootstrap";
20
+ import * as i8 from "@angular/forms";
21
+ export class PrepareTemplateComponent {
22
+ storeBuilderService;
23
+ dataService;
24
+ titleCase;
25
+ cdr;
26
+ gs;
27
+ router;
28
+ route;
29
+ toastService;
30
+ modalService;
31
+ searchModes = [
32
+ { value: 'store', label: 'Stores' },
33
+ { value: 'cluster', label: 'Clusters' },
34
+ ];
35
+ selectedMode = new FormControl('store');
36
+ target = new FormControl('both');
37
+ findPrompt = new FormControl('');
38
+ replacePrompt = new FormControl('');
39
+ storeOptions = [];
40
+ clusterData = []; // Store full cluster data with stores
41
+ loading = false;
42
+ savingDraft = false;
43
+ batchProcessing = false;
44
+ destroy$ = new Subject();
45
+ selectedStores = [];
46
+ findReplaceData = null;
47
+ selectedStoreForPreview = null;
48
+ storeListForDropdown = [];
49
+ storeDropdownItems = [];
50
+ selectedStoreValues = [];
51
+ // Canvas properties
52
+ previewCanvasRef;
53
+ previewCanvasContainerRef;
54
+ previewCanvas;
55
+ planoData;
56
+ floorData;
57
+ wallThickness = 30;
58
+ verticalMargin = (1.25 / 100) * this.toPixels(1524, "mm");
59
+ cdnUrl = '';
60
+ activeHighlight = null;
61
+ cancelHighlightBlink = false;
62
+ selectedFixture;
63
+ selectedFixtureData = null;
64
+ originalFixtureData = null; // Original fixture before replace (for before/after comparison)
65
+ originalFixturesMap = new Map(); // Store original fixtures by fixtureId
66
+ isRightPanelCollapsed = false;
67
+ canvasLoading = false;
68
+ findLoading = false;
69
+ replaceLoading = false;
70
+ allFixtureInstances = [];
71
+ vmList = [];
72
+ clientId = '';
73
+ hideMetadata = false;
74
+ get hasStores() {
75
+ return !!(this.findReplaceData?.stores && this.findReplaceData.stores.length > 0);
76
+ }
77
+ getStoreCount() {
78
+ return this.findReplaceData?.storeCount || this.findReplaceData?.stores?.length || 0;
79
+ }
80
+ getCurrentFixtureData() {
81
+ return this.selectedFixtureData || this.originalFixtureData;
82
+ }
83
+ getFixtureLabel() {
84
+ const fixture = this.getCurrentFixtureData();
85
+ return fixture?.header?.label || '';
86
+ }
87
+ getFixtureCategory() {
88
+ const fixture = this.getCurrentFixtureData();
89
+ return fixture?.fixtureCategory || '';
90
+ }
91
+ getFixtureWidth() {
92
+ const fixture = this.getCurrentFixtureData();
93
+ if (!fixture?.fixtureWidth)
94
+ return '';
95
+ const width = fixture.fixtureWidth.value;
96
+ const unit = fixture.fixtureWidth.unit || 'mm';
97
+ let dimensionStr = `${width}${unit}`;
98
+ // Convert to feet if needed (1200mm = 4ft)
99
+ if (unit === 'mm' && width === 1200) {
100
+ dimensionStr = `${width}${unit}/4ft`;
101
+ }
102
+ else if (unit === 'mm' && width > 0) {
103
+ const feet = Math.round(width / 300);
104
+ if (feet > 0) {
105
+ dimensionStr = `${width}${unit}/${feet}ft`;
106
+ }
107
+ }
108
+ return dimensionStr;
109
+ }
110
+ getShelfCount() {
111
+ const fixture = this.getCurrentFixtureData();
112
+ return fixture?.shelfConfig?.length || 0;
113
+ }
114
+ getFixtureCapacity() {
115
+ const fixture = this.getCurrentFixtureData();
116
+ return fixture?.fixtureCapacity || 0;
117
+ }
118
+ constructor(storeBuilderService, dataService, titleCase, cdr, gs, router, route, toastService, modalService) {
119
+ this.storeBuilderService = storeBuilderService;
120
+ this.dataService = dataService;
121
+ this.titleCase = titleCase;
122
+ this.cdr = cdr;
123
+ this.gs = gs;
124
+ this.router = router;
125
+ this.route = route;
126
+ this.toastService = toastService;
127
+ this.modalService = modalService;
128
+ }
129
+ previousSearchMode = null;
130
+ isInitialLoad = true;
131
+ hasRestoredData = false;
132
+ isUpdatingFromService = false;
133
+ ngOnInit() {
134
+ // Get client ID and CDN URL
135
+ this.gs.environment
136
+ .pipe(takeUntil(this.destroy$))
137
+ .subscribe((env) => {
138
+ this.cdnUrl = env.planogramCDN || '';
139
+ });
140
+ this.gs.dataRangeValue
141
+ .pipe(takeUntil(this.destroy$))
142
+ .subscribe((data) => {
143
+ if (data?.client) {
144
+ this.clientId = data.client;
145
+ }
146
+ else {
147
+ const headerData = JSON.parse(localStorage.getItem("header-filters"));
148
+ if (headerData?.client) {
149
+ this.clientId = headerData.client;
150
+ }
151
+ }
152
+ });
153
+ // Subscribe to data service to restore saved data
154
+ this.dataService.getFindReplaceData()
155
+ .pipe(takeUntil(this.destroy$))
156
+ .subscribe((data) => {
157
+ // Prevent infinite loops by skipping updates when we're updating from form changes
158
+ if (this.isUpdatingFromService) {
159
+ return;
160
+ }
161
+ this.findReplaceData = data;
162
+ // Update store dropdown items when stores change
163
+ this.updateStoreDropdownItems();
164
+ if (data && !this.hasRestoredData) {
165
+ // Restore all form values on first data load
166
+ this.restoreFormValues(data);
167
+ this.hasRestoredData = true;
168
+ }
169
+ else if (data && this.hasRestoredData) {
170
+ // If data already restored, only handle searchMode changes
171
+ if (data.searchMode && data.searchMode !== this.previousSearchMode) {
172
+ this.selectedMode.setValue(data.searchMode, { emitEvent: false });
173
+ this.previousSearchMode = data.searchMode;
174
+ this.loadStoresOrClusters(data);
175
+ }
176
+ // Update selected store for preview if stores exist
177
+ if (data.stores && data.stores.length > 0 && !this.selectedStoreForPreview) {
178
+ const newStore = this.storeDropdownItems[0];
179
+ if (newStore && (!this.selectedStoreForPreview || this.selectedStoreForPreview.storeId !== newStore.storeId)) {
180
+ this.selectedStoreForPreview = newStore;
181
+ this.updateSelectedStoreValues();
182
+ // Restore findResponseData and replaceResponseData for the selected store if available
183
+ this.restoreStoreResponseData(newStore.storeName);
184
+ // Load planogram for the selected store
185
+ this.cdr.detectChanges();
186
+ setTimeout(() => {
187
+ if (this.initializeCanvas()) {
188
+ this.loadPlanogramForStore(newStore.storeName);
189
+ }
190
+ }, 50);
191
+ }
192
+ }
193
+ }
194
+ else if (!data && this.isInitialLoad) {
195
+ // Load initial data if no saved data
196
+ this.loadStoresOrClusters();
197
+ this.isInitialLoad = false;
198
+ }
199
+ });
200
+ // Subscribe to save draft loading state
201
+ this.dataService.getLoadingState()
202
+ .pipe(takeUntil(this.destroy$))
203
+ .subscribe((isLoading) => {
204
+ this.savingDraft = isLoading;
205
+ });
206
+ // Watch for mode changes
207
+ this.selectedMode.valueChanges
208
+ .pipe(takeUntil(this.destroy$))
209
+ .subscribe((newMode) => {
210
+ if (newMode !== this.previousSearchMode && !this.isUpdatingFromService) {
211
+ this.previousSearchMode = newMode;
212
+ this.loadStoresOrClusters();
213
+ // Clear selected stores when mode changes manually
214
+ this.selectedStores = [];
215
+ // Clear selectedClusters when switching to store mode
216
+ if (newMode === 'store') {
217
+ this.dataService.updateData({ selectedClusters: undefined });
218
+ }
219
+ }
220
+ });
221
+ // Watch for target changes - debounce to prevent excessive updates
222
+ this.target.valueChanges
223
+ .pipe(takeUntil(this.destroy$))
224
+ .subscribe((value) => {
225
+ if (value && !this.isUpdatingFromService) {
226
+ this.isUpdatingFromService = true;
227
+ this.dataService.updateData({ target: value });
228
+ setTimeout(() => {
229
+ this.isUpdatingFromService = false;
230
+ }, 0);
231
+ }
232
+ });
233
+ // Watch for find prompt changes - debounce to prevent excessive updates
234
+ this.findPrompt.valueChanges
235
+ .pipe(takeUntil(this.destroy$))
236
+ .subscribe((value) => {
237
+ if (!this.isUpdatingFromService) {
238
+ this.isUpdatingFromService = true;
239
+ this.dataService.updateData({ findPrompt: value || '' });
240
+ setTimeout(() => {
241
+ this.isUpdatingFromService = false;
242
+ }, 0);
243
+ }
244
+ });
245
+ // Watch for replace prompt changes - debounce to prevent excessive updates
246
+ this.replacePrompt.valueChanges
247
+ .pipe(takeUntil(this.destroy$))
248
+ .subscribe((value) => {
249
+ if (!this.isUpdatingFromService) {
250
+ this.isUpdatingFromService = true;
251
+ this.dataService.updateData({ replacePrompt: value || '' });
252
+ setTimeout(() => {
253
+ this.isUpdatingFromService = false;
254
+ }, 0);
255
+ }
256
+ });
257
+ }
258
+ restoreFormValues(data) {
259
+ // Restore searchMode
260
+ if (data.searchMode) {
261
+ this.selectedMode.setValue(data.searchMode, { emitEvent: false });
262
+ this.previousSearchMode = data.searchMode;
263
+ }
264
+ // Restore target
265
+ if (data.target) {
266
+ this.target.setValue(data.target, { emitEvent: false });
267
+ }
268
+ // Restore findPrompt
269
+ if (data.findPrompt) {
270
+ this.findPrompt.setValue(data.findPrompt, { emitEvent: false });
271
+ }
272
+ // Restore replacePrompt
273
+ if (data.replacePrompt) {
274
+ this.replacePrompt.setValue(data.replacePrompt, { emitEvent: false });
275
+ }
276
+ // Load stores/clusters and restore selections
277
+ if (data.searchMode) {
278
+ this.loadStoresOrClusters(data);
279
+ }
280
+ else {
281
+ this.loadStoresOrClusters();
282
+ }
283
+ // Set initial selected store for preview
284
+ if (data.stores && data.stores.length > 0) {
285
+ this.updateStoreDropdownItems();
286
+ if (this.storeDropdownItems.length > 0) {
287
+ this.selectedStoreForPreview = this.storeDropdownItems[0];
288
+ this.updateSelectedStoreValues();
289
+ // Load planogram after view is initialized
290
+ this.cdr.detectChanges();
291
+ setTimeout(() => {
292
+ if (this.initializeCanvas() && this.selectedStoreForPreview) {
293
+ this.loadPlanogramForStore(this.selectedStoreForPreview.storeName);
294
+ }
295
+ else {
296
+ // Retry if canvas not ready
297
+ setTimeout(() => {
298
+ if (this.initializeCanvas() && this.selectedStoreForPreview) {
299
+ this.loadPlanogramForStore(this.selectedStoreForPreview.storeName);
300
+ }
301
+ }, 200);
302
+ }
303
+ }, 100);
304
+ }
305
+ }
306
+ this.isInitialLoad = false;
307
+ }
308
+ updateStoreDropdownItems() {
309
+ if (!this.findReplaceData?.stores) {
310
+ this.storeDropdownItems = [];
311
+ this.selectedStoreValues = [];
312
+ return;
313
+ }
314
+ const newItems = this.findReplaceData.stores.map((store) => ({
315
+ storeId: store.storeId || store.storeName,
316
+ storeName: store.storeName,
317
+ _id: store.storeId || store.storeName
318
+ }));
319
+ // Only update if items actually changed
320
+ const itemsChanged = JSON.stringify(newItems) !== JSON.stringify(this.storeDropdownItems);
321
+ if (itemsChanged) {
322
+ this.storeDropdownItems = newItems;
323
+ this.updateSelectedStoreValues();
324
+ }
325
+ }
326
+ updateSelectedStoreValues() {
327
+ if (this.selectedStoreForPreview) {
328
+ this.selectedStoreValues = [this.selectedStoreForPreview];
329
+ }
330
+ else {
331
+ this.selectedStoreValues = [];
332
+ }
333
+ }
334
+ ngAfterViewInit() {
335
+ // Canvas will be initialized when store is selected and canvas element is available
336
+ }
337
+ initializeCanvas() {
338
+ if (this.previewCanvas) {
339
+ return true; // Already initialized
340
+ }
341
+ if (this.previewCanvasRef?.nativeElement) {
342
+ try {
343
+ this.previewCanvas = new fabric.Canvas(this.previewCanvasRef.nativeElement, {
344
+ selectionFullyContained: true,
345
+ perPixelTargetFind: true,
346
+ targetFindTolerance: 5,
347
+ });
348
+ this.setupZoomHandlers(this.previewCanvas);
349
+ return true;
350
+ }
351
+ catch (error) {
352
+ console.error('Error initializing canvas:', error);
353
+ return false;
354
+ }
355
+ }
356
+ return false;
357
+ }
358
+ onStoreSelectedForPreview(store) {
359
+ if (store && (!this.selectedStoreForPreview || this.selectedStoreForPreview.storeId !== store.storeId)) {
360
+ this.selectedStoreForPreview = store;
361
+ this.updateSelectedStoreValues();
362
+ // Clear selected fixture when switching stores
363
+ this.selectedFixture = null;
364
+ this.selectedFixtureData = null;
365
+ this.originalFixtureData = null;
366
+ this.originalFixturesMap.clear(); // Clear the map when switching stores
367
+ // Restore findResponseData and replaceResponseData for the selected store if available
368
+ this.restoreStoreResponseData(store.storeName);
369
+ // Force change detection to ensure canvas element is in DOM
370
+ this.cdr.detectChanges();
371
+ // Initialize canvas if not already done, then load planogram
372
+ setTimeout(() => {
373
+ if (this.initializeCanvas()) {
374
+ this.loadPlanogramForStore(store.storeName);
375
+ }
376
+ else {
377
+ // Retry after a short delay if canvas element not ready
378
+ setTimeout(() => {
379
+ if (this.initializeCanvas()) {
380
+ this.loadPlanogramForStore(store.storeName);
381
+ }
382
+ }, 100);
383
+ }
384
+ }, 50);
385
+ }
386
+ }
387
+ // Restore findResponseData and replaceResponseData for a specific store
388
+ restoreStoreResponseData(storeName) {
389
+ if (!this.findReplaceData?.stores) {
390
+ return;
391
+ }
392
+ const store = this.findReplaceData.stores.find((s) => s.storeName === storeName);
393
+ if (!store) {
394
+ return;
395
+ }
396
+ // findResponseData is a string (fixture _id)
397
+ // replaceResponseData is an object with vmConfig and/or shelfConfig
398
+ const fixtureId = store.findResponseData;
399
+ if (!fixtureId)
400
+ return;
401
+ this.selectedFixture = { fixtureId, fixtureType: undefined };
402
+ // We'll re-hydrate selectedFixtureData from the loaded planogram (floorData) after load.
403
+ this.selectedFixtureData = null;
404
+ }
405
+ // Apply stored findResponseData and replaceResponseData to floor data
406
+ applyStoredResponseData() {
407
+ if (!this.findReplaceData?.stores || !this.selectedStoreForPreview || !this.floorData) {
408
+ return;
409
+ }
410
+ const store = this.findReplaceData.stores.find((s) => s.storeName === this.selectedStoreForPreview.storeName);
411
+ if (!store) {
412
+ return;
413
+ }
414
+ // findResponseData is a string (fixture _id) - use it to find the fixture
415
+ const fixtureId = store.findResponseData;
416
+ if (!fixtureId)
417
+ return;
418
+ // Find the fixture in floorData
419
+ const fixture = this.getFixtureByIdFromFloor(fixtureId);
420
+ if (!fixture)
421
+ return;
422
+ // Apply replaceResponseData configs if available (merge with existing fixture)
423
+ if (store.replaceResponseData) {
424
+ // Store the original fixture (before replace) for before/after comparison
425
+ const originalFixture = structuredClone(fixture);
426
+ this.originalFixtureData = originalFixture;
427
+ // Also store it in the map so it persists when clicking other fixtures
428
+ this.originalFixturesMap.set(fixtureId, originalFixture);
429
+ const updatedFixture = { ...fixture };
430
+ // Merge vmConfig if present in replaceResponseData
431
+ if (store.replaceResponseData.vmConfig) {
432
+ updatedFixture.vmConfig = store.replaceResponseData.vmConfig;
433
+ }
434
+ // Merge shelfConfig if present in replaceResponseData
435
+ if (store.replaceResponseData.shelfConfig) {
436
+ updatedFixture.shelfConfig = store.replaceResponseData.shelfConfig;
437
+ }
438
+ // Update the fixture in floorData
439
+ this.updateAiResponseFixture(updatedFixture);
440
+ // Set selected fixture data (after replace)
441
+ this.selectedFixture = {
442
+ fixtureId: updatedFixture._id,
443
+ fixtureType: updatedFixture.fixtureType,
444
+ };
445
+ this.selectedFixtureData = updatedFixture;
446
+ }
447
+ else {
448
+ // No replaceResponseData, clear original fixture and just set the selected fixture from findResponseData
449
+ this.originalFixtureData = null;
450
+ this.selectedFixture = {
451
+ fixtureId: fixture._id,
452
+ fixtureType: fixture.fixtureType,
453
+ };
454
+ this.selectedFixtureData = fixture;
455
+ }
456
+ }
457
+ getFixtureByIdFromFloor(fixtureId) {
458
+ if (!fixtureId || !this.floorData)
459
+ return null;
460
+ for (const element of this.floorData.layoutPolygon || []) {
461
+ if (element?.elementType === "wall" && Array.isArray(element.fixtures)) {
462
+ const hit = element.fixtures.find((fx) => fx?._id === fixtureId);
463
+ if (hit)
464
+ return hit;
465
+ }
466
+ }
467
+ for (const fx of this.floorData.centerFixture || []) {
468
+ if (fx?._id === fixtureId)
469
+ return fx;
470
+ }
471
+ return null;
472
+ }
473
+ async loadPlanogramForStore(storeName) {
474
+ if (!storeName) {
475
+ console.warn('Cannot load planogram: storeName not available');
476
+ return;
477
+ }
478
+ if (!this.previewCanvas) {
479
+ console.warn('Canvas not initialized, attempting to initialize...');
480
+ if (!this.initializeCanvas()) {
481
+ console.error('Failed to initialize canvas');
482
+ return;
483
+ }
484
+ }
485
+ this.canvasLoading = true;
486
+ try {
487
+ // Get planoId from store name
488
+ const response = await this.storeBuilderService.getPlanoId({ stores: [storeName.toUpperCase()] }).toPromise();
489
+ if (response?.code === 200 && response?.data?.length > 0) {
490
+ const planoId = response.data[0]._id;
491
+ await this.getStoreFixtures(planoId);
492
+ }
493
+ else {
494
+ console.warn('No planogram found for store:', storeName);
495
+ this.canvasLoading = false;
496
+ }
497
+ }
498
+ catch (error) {
499
+ console.error('Error loading planogram:', error);
500
+ this.canvasLoading = false;
501
+ }
502
+ }
503
+ loadStoresOrClusters(savedData) {
504
+ const searchMode = this.selectedMode.value;
505
+ if (!searchMode)
506
+ return;
507
+ this.loading = true;
508
+ this.storeBuilderService.getStoreOrClusterList({ searchMode })
509
+ .pipe(takeUntil(this.destroy$))
510
+ .subscribe({
511
+ next: (response) => {
512
+ this.loading = false;
513
+ if (response?.code === 200 && response?.data && Array.isArray(response.data)) {
514
+ if (searchMode === 'store') {
515
+ // For store mode, use data directly
516
+ this.storeOptions = response.data.map((item) => ({
517
+ id: item.id,
518
+ label: item.label
519
+ }));
520
+ this.clusterData = []; // Clear cluster data
521
+ // Restore saved selections for store mode
522
+ if (savedData?.stores && savedData.stores.length > 0) {
523
+ this.restoreStoreSelections(savedData.stores);
524
+ }
525
+ }
526
+ else {
527
+ // For cluster mode, show clusters in the dropdown
528
+ // Store full cluster data for later use
529
+ this.clusterData = response.data;
530
+ this.storeOptions = response.data.map((cluster) => ({
531
+ id: cluster.id,
532
+ label: cluster.label
533
+ }));
534
+ // Restore saved selections for cluster mode
535
+ if (savedData?.stores && savedData.stores.length > 0) {
536
+ this.restoreClusterSelections(savedData.stores);
537
+ }
538
+ }
539
+ }
540
+ else {
541
+ this.storeOptions = [];
542
+ this.clusterData = [];
543
+ }
544
+ },
545
+ error: (error) => {
546
+ this.loading = false;
547
+ console.error('Error loading stores/clusters:', error);
548
+ this.storeOptions = [];
549
+ }
550
+ });
551
+ }
552
+ restoreStoreSelections(savedStores) {
553
+ // Match saved stores by storeName
554
+ const savedStoreNames = new Set(savedStores.map(s => s.storeName));
555
+ this.selectedStores = this.storeOptions.filter(option => savedStoreNames.has(option.label));
556
+ }
557
+ restoreClusterSelections(_savedStores) {
558
+ // Restore cluster selection ONLY from selectedClusters (no derivation from stores)
559
+ const savedClusters = this.findReplaceData?.selectedClusters || [];
560
+ if (!savedClusters.length) {
561
+ this.selectedStores = [];
562
+ return;
563
+ }
564
+ const savedClusterIds = new Set(savedClusters.map(c => c.id));
565
+ const selectedClusters = [];
566
+ this.clusterData.forEach((cluster) => {
567
+ if (savedClusterIds.has(cluster.id)) {
568
+ selectedClusters.push({
569
+ id: cluster.id,
570
+ label: cluster.label
571
+ });
572
+ }
573
+ });
574
+ this.selectedStores = selectedClusters;
575
+ }
576
+ onStoresSelected(stores) {
577
+ this.selectedStores = stores;
578
+ }
579
+ async onReviewAndReplace() {
580
+ if (!this.findReplaceData?._id) {
581
+ console.error('No find replace ID available');
582
+ return;
583
+ }
584
+ // Show confirmation modal
585
+ const modalRef = this.modalService.open(BatchConfirmationModalComponent, {
586
+ centered: true,
587
+ size: 'md',
588
+ backdrop: 'static',
589
+ windowClass: 'batch-confirmation-modal'
590
+ });
591
+ // Pass store count to modal
592
+ modalRef.componentInstance.storeCount = this.getStoreCount();
593
+ try {
594
+ const result = await modalRef.result;
595
+ if (result) {
596
+ // User confirmed, proceed with batch process
597
+ this.proceedWithBatchProcess();
598
+ }
599
+ }
600
+ catch (error) {
601
+ // User dismissed the modal
602
+ console.log('Batch confirmation modal dismissed');
603
+ }
604
+ }
605
+ proceedWithBatchProcess() {
606
+ if (!this.findReplaceData?._id) {
607
+ console.error('No find replace ID available');
608
+ return;
609
+ }
610
+ this.loading = true;
611
+ this.batchProcessing = true;
612
+ const findReplaceId = this.findReplaceData._id;
613
+ this.storeBuilderService.batchFindReplace({ findReplaceId })
614
+ .pipe(takeUntil(this.destroy$))
615
+ .subscribe({
616
+ next: (response) => {
617
+ this.loading = false;
618
+ this.batchProcessing = false;
619
+ if (response?.code === 200) {
620
+ // Refetch find replace data to update UI
621
+ this.dataService.loadAndSetFindReplaceDataById(findReplaceId);
622
+ }
623
+ else {
624
+ console.error('Failed to start batch find replace:', response?.message);
625
+ }
626
+ },
627
+ error: (error) => {
628
+ this.loading = false;
629
+ this.batchProcessing = false;
630
+ console.error('Error starting batch find replace:', error);
631
+ }
632
+ });
633
+ }
634
+ onApply() {
635
+ const searchMode = this.selectedMode.value;
636
+ let stores = [];
637
+ let selectedClusters = undefined;
638
+ if (searchMode === 'store') {
639
+ // For store mode, convert selected stores directly
640
+ stores = this.selectedStores.map((storeOption) => ({
641
+ storeName: storeOption.label,
642
+ }));
643
+ }
644
+ else {
645
+ // For cluster mode, save selected clusters and extract all stores from selected clusters
646
+ selectedClusters = this.selectedStores.map((storeOption) => ({
647
+ id: storeOption.id,
648
+ label: storeOption.label
649
+ }));
650
+ const selectedClusterIds = new Set(this.selectedStores.map(s => s.id));
651
+ stores = [];
652
+ // Find selected clusters and extract their stores
653
+ this.clusterData.forEach((cluster) => {
654
+ if (selectedClusterIds.has(cluster.id) && cluster.stores && Array.isArray(cluster.stores)) {
655
+ cluster.stores.forEach((store) => {
656
+ stores.push({
657
+ storeName: store.label,
658
+ });
659
+ });
660
+ }
661
+ });
662
+ }
663
+ // Update data service with all current values
664
+ const updateData = {
665
+ searchMode: searchMode,
666
+ stores: stores,
667
+ storeCount: stores.length,
668
+ target: this.target.value,
669
+ findPrompt: this.findPrompt.value || '',
670
+ replacePrompt: this.replacePrompt.value || ''
671
+ };
672
+ // Add selectedClusters only when searchMode is cluster
673
+ if (searchMode === 'cluster' && selectedClusters) {
674
+ updateData.selectedClusters = selectedClusters;
675
+ }
676
+ this.dataService.updateData(updateData);
677
+ // Trigger save as draft
678
+ this.dataService.triggerSaveDraft();
679
+ }
680
+ // Canvas setup methods
681
+ setupZoomHandlers(canvas) {
682
+ // Disable object selection globally
683
+ canvas.selection = false;
684
+ canvas.on("mouse:wheel", (opt) => {
685
+ const e = opt.e;
686
+ if (e.ctrlKey || e.metaKey) {
687
+ const delta = e.deltaY;
688
+ let zoom = canvas.getZoom();
689
+ zoom *= 0.995 ** delta;
690
+ zoom = Math.max(0.2, Math.min(zoom, 3));
691
+ canvas.zoomToPoint({ x: e.offsetX, y: e.offsetY }, zoom);
692
+ e.preventDefault();
693
+ e.stopPropagation();
694
+ }
695
+ });
696
+ let isDragging = false;
697
+ let lastPosX = 0;
698
+ let lastPosY = 0;
699
+ canvas.on("mouse:down", (opt) => {
700
+ // Handle fixture clicks - use findTarget to get the actual group
701
+ if (opt.target) {
702
+ const obj = opt.target;
703
+ // Check if it's a fixture group or nested within one
704
+ let fixtureGroup = obj;
705
+ // Traverse up to find the fixture group
706
+ let attempts = 0;
707
+ while (fixtureGroup && !fixtureGroup.fixtureId && !fixtureGroup.objType && attempts < 10) {
708
+ if (fixtureGroup.parent) {
709
+ fixtureGroup = fixtureGroup.parent;
710
+ }
711
+ else if (fixtureGroup.group) {
712
+ fixtureGroup = fixtureGroup.group;
713
+ }
714
+ else {
715
+ break;
716
+ }
717
+ attempts++;
718
+ }
719
+ // Check if we found a fixture group
720
+ if (fixtureGroup.objType === "fixture" || fixtureGroup.fixtureId) {
721
+ this.onFixtureClick(fixtureGroup);
722
+ canvas.setActiveObject(fixtureGroup);
723
+ canvas.requestRenderAll();
724
+ return;
725
+ }
726
+ // For other elements, just highlight
727
+ canvas.setActiveObject(opt.target);
728
+ canvas.requestRenderAll();
729
+ return;
730
+ }
731
+ if (!opt.target) {
732
+ isDragging = true;
733
+ canvas.selection = false;
734
+ const e = opt.e;
735
+ lastPosX = e.clientX;
736
+ lastPosY = e.clientY;
737
+ }
738
+ });
739
+ canvas.on("mouse:move", (opt) => {
740
+ if (isDragging && canvas.viewportTransform && !opt.target) {
741
+ const e = opt.e;
742
+ const vpt = canvas.viewportTransform;
743
+ vpt[4] += e.clientX - lastPosX;
744
+ vpt[5] += e.clientY - lastPosY;
745
+ canvas.requestRenderAll();
746
+ lastPosX = e.clientX;
747
+ lastPosY = e.clientY;
748
+ }
749
+ });
750
+ canvas.on("mouse:up", () => {
751
+ isDragging = false;
752
+ canvas.selection = false;
753
+ });
754
+ // Prevent all object movement (walls, entrances, fixtures, other elements)
755
+ canvas.on("object:moving", (e) => {
756
+ const obj = e.target;
757
+ if (obj && obj.objType) {
758
+ e.e.preventDefault();
759
+ e.e.stopPropagation();
760
+ // Reset position
761
+ obj.setCoords();
762
+ canvas.requestRenderAll();
763
+ }
764
+ });
765
+ // Prevent all object modifications (scaling, rotating, etc.)
766
+ canvas.on("object:modified", (e) => {
767
+ const obj = e.target;
768
+ if (obj && obj.objType) {
769
+ // Reset any changes
770
+ obj.setCoords();
771
+ canvas.requestRenderAll();
772
+ }
773
+ });
774
+ // Prevent object scaling
775
+ canvas.on("object:scaling", (e) => {
776
+ const obj = e.target;
777
+ if (obj && obj.objType) {
778
+ e.e.preventDefault();
779
+ e.e.stopPropagation();
780
+ obj.setCoords();
781
+ canvas.requestRenderAll();
782
+ }
783
+ });
784
+ // Prevent object rotating
785
+ canvas.on("object:rotating", (e) => {
786
+ const obj = e.target;
787
+ if (obj && obj.objType) {
788
+ e.e.preventDefault();
789
+ e.e.stopPropagation();
790
+ obj.setCoords();
791
+ canvas.requestRenderAll();
792
+ }
793
+ });
794
+ }
795
+ async getStoreFixtures(storeId) {
796
+ if (!this.previewCanvas) {
797
+ console.warn('Canvas not initialized');
798
+ this.canvasLoading = false;
799
+ return;
800
+ }
801
+ this.canvasLoading = true;
802
+ this.storeBuilderService.getStoreFixtures({ id: [storeId] })
803
+ .pipe(takeUntil(this.destroy$))
804
+ .subscribe({
805
+ next: async (res) => {
806
+ if (!res?.data?.[0]?.floors?.length) {
807
+ this.canvasLoading = false;
808
+ return;
809
+ }
810
+ this.planoData = structuredClone(res.data[0]);
811
+ this.floorData = structuredClone(res.data[0].floors[0]);
812
+ // Apply stored findResponseData and replaceResponseData if available for this store
813
+ // This updates the floorData with the stored fixture changes and sets selectedFixtureData
814
+ this.applyStoredResponseData();
815
+ // Open panel if we have selected fixture data
816
+ if (this.selectedFixtureData) {
817
+ this.isRightPanelCollapsed = false;
818
+ }
819
+ // Collect all fixtures for preview
820
+ this.collectAllFixtures();
821
+ // Ensure canvas is initialized before rendering
822
+ if (!this.previewCanvas) {
823
+ this.initializeCanvas();
824
+ }
825
+ if (this.previewCanvas) {
826
+ // Render the planogram with the updated floorData (which includes stored response data)
827
+ await this.renderFloor(this.previewCanvas);
828
+ this.canvasLoading = false;
829
+ // Re-center and highlight the selected fixture if stored response data exists
830
+ setTimeout(() => {
831
+ if (this.previewCanvasContainerRef?.nativeElement) {
832
+ this.resizeCanvas(this.previewCanvas, this.previewCanvasContainerRef);
833
+ this.fitCanvasToLayoutAnimated(this.previewCanvas);
834
+ // Highlight the fixture if we have stored response data
835
+ if (this.selectedFixture?.fixtureId) {
836
+ const actionFixture = this.previewCanvas.getObjects().find((obj) => obj.objType === "fixture" && obj.fixtureId === this.selectedFixture.fixtureId);
837
+ if (actionFixture) {
838
+ this.highlightFixture(this.previewCanvas, actionFixture, false);
839
+ }
840
+ }
841
+ }
842
+ // Automatically trigger find and replace if prompts are available and store doesn't have results
843
+ this.autoFindAndReplaceIfNeeded();
844
+ }, 300);
845
+ }
846
+ else {
847
+ this.canvasLoading = false;
848
+ }
849
+ },
850
+ error: (err) => {
851
+ this.canvasLoading = false;
852
+ console.error('Error fetching plano:', err);
853
+ },
854
+ });
855
+ }
856
+ resizeCanvas(canvas, container) {
857
+ const containerEl = container.nativeElement;
858
+ canvas.setDimensions({
859
+ width: containerEl.clientWidth,
860
+ height: containerEl.clientHeight,
861
+ });
862
+ canvas.requestRenderAll();
863
+ }
864
+ fitCanvasToLayoutAnimated(canvas) {
865
+ if (!canvas)
866
+ return;
867
+ const bounds = this.getFullLayoutBounds(canvas);
868
+ if (!bounds.width || !bounds.height)
869
+ return;
870
+ const canvasW = canvas.getWidth();
871
+ const canvasH = canvas.getHeight();
872
+ const scaleX = canvasW / bounds.width;
873
+ const scaleY = canvasH / bounds.height;
874
+ const targetZoom = Math.min(scaleX, scaleY) * 0.9;
875
+ const targetVpt = [...(canvas.viewportTransform || [1, 0, 0, 1, 0, 0])];
876
+ targetVpt[0] = targetZoom;
877
+ targetVpt[3] = targetZoom;
878
+ targetVpt[4] = canvasW / 2 - (bounds.left + bounds.width / 2) * targetZoom;
879
+ targetVpt[5] = canvasH / 2 - (bounds.top + bounds.height / 2) * targetZoom;
880
+ const startVpt = [...canvas.viewportTransform];
881
+ fabric.util.animate({
882
+ startValue: 0,
883
+ endValue: 1,
884
+ duration: 100,
885
+ easing: fabric.util.ease.easeOutCubic,
886
+ onChange: (value) => {
887
+ const vpt = canvas.viewportTransform;
888
+ vpt[0] = startVpt[0] + (targetVpt[0] - startVpt[0]) * value;
889
+ vpt[3] = startVpt[3] + (targetVpt[3] - startVpt[3]) * value;
890
+ vpt[4] = startVpt[4] + (targetVpt[4] - startVpt[4]) * value;
891
+ vpt[5] = startVpt[5] + (targetVpt[5] - startVpt[5]) * value;
892
+ canvas.requestRenderAll();
893
+ },
894
+ });
895
+ }
896
+ getFullLayoutBounds(canvas) {
897
+ const objects = canvas.getObjects();
898
+ if (!objects.length)
899
+ return { left: 0, top: 0, width: 0, height: 0 };
900
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
901
+ for (const obj of objects) {
902
+ const rect = obj.getBoundingRect();
903
+ minX = Math.min(minX, rect.left);
904
+ minY = Math.min(minY, rect.top);
905
+ maxX = Math.max(maxX, rect.left + rect.width);
906
+ maxY = Math.max(maxY, rect.top + rect.height);
907
+ }
908
+ return { left: minX, top: minY, width: maxX - minX, height: maxY - minY };
909
+ }
910
+ async renderFloor(canvas) {
911
+ await this.drawInitialContent(canvas);
912
+ }
913
+ async drawInitialContent(canvas) {
914
+ canvas.clear();
915
+ await this.drawLayoutElements(canvas);
916
+ }
917
+ // Automatically trigger find and replace if prompts are available and store doesn't have results
918
+ autoFindAndReplaceIfNeeded() {
919
+ if (!this.selectedStoreForPreview || !this.findReplaceData) {
920
+ return;
921
+ }
922
+ // Check if prompts are available
923
+ const hasFindPrompt = this.findReplaceData.findPrompt && this.findReplaceData.findPrompt.trim().length > 0;
924
+ const hasReplacePrompt = this.findReplaceData.replacePrompt && this.findReplaceData.replacePrompt.trim().length > 0;
925
+ if (!hasFindPrompt || !hasReplacePrompt) {
926
+ return;
927
+ }
928
+ // Check if current store already has findResponseData and replaceResponseData
929
+ const store = this.findReplaceData.stores?.find((s) => s.storeName === this.selectedStoreForPreview.storeName);
930
+ // If store already has findResponseData, skip auto-find to preserve the highlight
931
+ // Only auto-run find if store doesn't already have findResponseData
932
+ if (store?.findResponseData) {
933
+ // If store has findResponseData but not replaceResponseData, we could auto-run replace
934
+ // but for now, we'll skip to preserve the highlight that was just set
935
+ return;
936
+ }
937
+ // Set the prompts in the form controls if not already set
938
+ if (!this.findPrompt.value && this.findReplaceData.findPrompt) {
939
+ this.findPrompt.setValue(this.findReplaceData.findPrompt, { emitEvent: false });
940
+ }
941
+ if (!this.replacePrompt.value && this.findReplaceData.replacePrompt) {
942
+ this.replacePrompt.setValue(this.findReplaceData.replacePrompt, { emitEvent: false });
943
+ }
944
+ // Automatically trigger find first, then replace after find completes
945
+ this.autoFind();
946
+ }
947
+ // Auto find - will trigger replace after completion
948
+ autoFind() {
949
+ if (!this.findPrompt.value || !this.selectedStoreForPreview) {
950
+ return;
951
+ }
952
+ this.findLoading = true;
953
+ this.canvasLoading = true;
954
+ const payload = {
955
+ selectionCriteria: this.findPrompt.value,
956
+ stores: [this.selectedStoreForPreview.storeName],
957
+ };
958
+ this.storeBuilderService.findFixture(payload)
959
+ .pipe(takeUntil(this.destroy$))
960
+ .subscribe({
961
+ next: (res) => {
962
+ this.findLoading = false;
963
+ this.canvasLoading = false;
964
+ if (res.code === 200) {
965
+ // Check if the response indicates "NOT FOUND"
966
+ if (res.status === 'success' && res.message === 'NOT FOUND') {
967
+ this.toastService.getWarningToast('No matching fixture found for the given prompt');
968
+ return;
969
+ }
970
+ // Check if res.data exists before processing
971
+ if (!res.data) {
972
+ this.toastService.getWarningToast('No matching fixture found for the given prompt');
973
+ return;
974
+ }
975
+ this.updateAiResponseFixture(res.data);
976
+ // Store the found fixture for potential replace operation
977
+ this.selectedFixture = {
978
+ fixtureId: res.data._id,
979
+ fixtureType: res.data.fixtureType,
980
+ };
981
+ this.selectedFixtureData = res.data;
982
+ // Save findResponseData to the specific store
983
+ this.saveFindResponseData(res.data);
984
+ // Render the floor and wait for it to complete
985
+ this.renderFloor(this.previewCanvas).then(() => {
986
+ // Wait for canvas to fully render before highlighting
987
+ setTimeout(() => {
988
+ const actionFixture = this.previewCanvas.getObjects().find((obj) => obj.objType === "fixture" && obj.fixtureId === res.data._id);
989
+ if (actionFixture) {
990
+ this.highlightFixture(this.previewCanvas, actionFixture, true);
991
+ }
992
+ // After find completes, automatically trigger replace
993
+ setTimeout(() => {
994
+ this.autoReplace();
995
+ }, 500);
996
+ }, 300);
997
+ });
998
+ }
999
+ },
1000
+ error: () => {
1001
+ this.findLoading = false;
1002
+ this.canvasLoading = false;
1003
+ },
1004
+ });
1005
+ }
1006
+ // Auto replace - called after auto find completes
1007
+ autoReplace() {
1008
+ if (!this.replacePrompt.value) {
1009
+ return;
1010
+ }
1011
+ // Check if a fixture is selected for replacement
1012
+ if (!this.selectedFixture?.fixtureId && !this.selectedFixtureData?._id) {
1013
+ return;
1014
+ }
1015
+ // Use Replace API for selected fixture
1016
+ const fixtureId = this.selectedFixture?.fixtureId || this.selectedFixtureData?._id;
1017
+ this.replaceLoading = true;
1018
+ this.canvasLoading = true;
1019
+ const payload = {
1020
+ fixtureId: fixtureId,
1021
+ updateType: this.target.value,
1022
+ updationCriteria: this.replacePrompt.value,
1023
+ };
1024
+ // Store the original fixture before replace for before/after comparison
1025
+ const originalFixture = this.selectedFixtureData ? structuredClone(this.selectedFixtureData) : null;
1026
+ this.storeBuilderService.replaceFixture(payload)
1027
+ .pipe(takeUntil(this.destroy$))
1028
+ .subscribe({
1029
+ next: (res) => {
1030
+ this.replaceLoading = false;
1031
+ this.canvasLoading = false;
1032
+ if (res.code === 200) {
1033
+ // Store original fixture for before/after comparison
1034
+ this.originalFixtureData = originalFixture;
1035
+ this.updateAiResponseFixture(res.data);
1036
+ // Save replaceResponseData to the specific store
1037
+ this.saveReplaceResponseData(res.data);
1038
+ // Update selected fixture data (after replace)
1039
+ this.selectedFixture = {
1040
+ fixtureId: res.data._id,
1041
+ fixtureType: res.data.fixtureType,
1042
+ };
1043
+ this.selectedFixtureData = res.data;
1044
+ // Render the floor and wait for it to complete
1045
+ this.renderFloor(this.previewCanvas).then(() => {
1046
+ // Wait for canvas to fully render before highlighting
1047
+ setTimeout(() => {
1048
+ const actionFixture = this.previewCanvas.getObjects().find((obj) => obj.objType === "fixture" && obj.fixtureId === res.data._id);
1049
+ if (actionFixture) {
1050
+ this.highlightFixture(this.previewCanvas, actionFixture, true);
1051
+ }
1052
+ }, 300);
1053
+ });
1054
+ }
1055
+ },
1056
+ error: () => {
1057
+ this.replaceLoading = false;
1058
+ this.canvasLoading = false;
1059
+ },
1060
+ });
1061
+ }
1062
+ // Find and Replace button handlers
1063
+ onFind() {
1064
+ if (!this.findPrompt.value || !this.selectedStoreForPreview) {
1065
+ return;
1066
+ }
1067
+ this.findLoading = true;
1068
+ this.canvasLoading = true;
1069
+ const payload = {
1070
+ selectionCriteria: this.findPrompt.value,
1071
+ stores: [this.selectedStoreForPreview.storeName],
1072
+ };
1073
+ this.storeBuilderService.findFixture(payload)
1074
+ .pipe(takeUntil(this.destroy$))
1075
+ .subscribe({
1076
+ next: (res) => {
1077
+ this.findLoading = false;
1078
+ this.canvasLoading = false;
1079
+ if (res.code === 200) {
1080
+ // Check if the response indicates "NOT FOUND"
1081
+ if (res.status === 'success' && res.message === 'NOT FOUND') {
1082
+ this.toastService.getWarningToast('No matching fixture found for the given prompt');
1083
+ return;
1084
+ }
1085
+ // Check if res.data exists before processing
1086
+ if (!res.data) {
1087
+ this.toastService.getWarningToast('No matching fixture found for the given prompt');
1088
+ return;
1089
+ }
1090
+ this.updateAiResponseFixture(res.data);
1091
+ // Store the found fixture for potential replace operation
1092
+ this.selectedFixture = {
1093
+ fixtureId: res.data._id,
1094
+ fixtureType: res.data.fixtureType,
1095
+ };
1096
+ this.selectedFixtureData = res.data;
1097
+ // Save findResponseData to the specific store
1098
+ this.saveFindResponseData(res.data);
1099
+ // Render the floor and wait for it to complete
1100
+ this.renderFloor(this.previewCanvas).then(() => {
1101
+ // Wait for canvas to fully render before highlighting
1102
+ setTimeout(() => {
1103
+ const actionFixture = this.previewCanvas.getObjects().find((obj) => obj.objType === "fixture" && obj.fixtureId === res.data._id);
1104
+ if (actionFixture) {
1105
+ this.highlightFixture(this.previewCanvas, actionFixture, true);
1106
+ }
1107
+ }, 300);
1108
+ });
1109
+ }
1110
+ },
1111
+ error: () => {
1112
+ this.findLoading = false;
1113
+ this.canvasLoading = false;
1114
+ },
1115
+ });
1116
+ }
1117
+ onReplace() {
1118
+ if (!this.replacePrompt.value) {
1119
+ return;
1120
+ }
1121
+ // Check if a fixture is selected for replacement
1122
+ if (!this.selectedFixture?.fixtureId && !this.selectedFixtureData?._id) {
1123
+ return;
1124
+ }
1125
+ // Use Replace API for selected fixture
1126
+ const fixtureId = this.selectedFixture?.fixtureId || this.selectedFixtureData?._id;
1127
+ this.replaceLoading = true;
1128
+ this.canvasLoading = true;
1129
+ const payload = {
1130
+ fixtureId: fixtureId,
1131
+ updateType: this.target.value,
1132
+ updationCriteria: this.replacePrompt.value,
1133
+ };
1134
+ // Store the original fixture before replace for before/after comparison
1135
+ const originalFixture = this.selectedFixtureData ? structuredClone(this.selectedFixtureData) : null;
1136
+ this.storeBuilderService.replaceFixture(payload)
1137
+ .pipe(takeUntil(this.destroy$))
1138
+ .subscribe({
1139
+ next: (res) => {
1140
+ this.replaceLoading = false;
1141
+ this.canvasLoading = false;
1142
+ if (res.code === 200) {
1143
+ // Store original fixture for before/after comparison
1144
+ this.originalFixtureData = originalFixture;
1145
+ this.updateAiResponseFixture(res.data);
1146
+ // Save replaceResponseData to the specific store
1147
+ this.saveReplaceResponseData(res.data);
1148
+ // Update selected fixture data (after replace)
1149
+ this.selectedFixture = {
1150
+ fixtureId: res.data._id,
1151
+ fixtureType: res.data.fixtureType,
1152
+ };
1153
+ this.selectedFixtureData = res.data;
1154
+ // Render the floor and wait for it to complete
1155
+ this.renderFloor(this.previewCanvas).then(() => {
1156
+ // Wait for canvas to fully render before highlighting
1157
+ setTimeout(() => {
1158
+ const actionFixture = this.previewCanvas.getObjects().find((obj) => obj.objType === "fixture" && obj.fixtureId === res.data._id);
1159
+ if (actionFixture) {
1160
+ this.highlightFixture(this.previewCanvas, actionFixture, true);
1161
+ }
1162
+ }, 300);
1163
+ });
1164
+ }
1165
+ },
1166
+ error: () => {
1167
+ this.replaceLoading = false;
1168
+ this.canvasLoading = false;
1169
+ },
1170
+ });
1171
+ }
1172
+ // Helper method to get findResponseData for current store
1173
+ getCurrentStoreFindResponseData() {
1174
+ if (!this.findReplaceData?.stores || !this.selectedStoreForPreview) {
1175
+ return null;
1176
+ }
1177
+ const store = this.findReplaceData.stores.find((s) => s.storeName === this.selectedStoreForPreview.storeName);
1178
+ return store?.findResponseData || null;
1179
+ }
1180
+ // Save findResponseData to specific store and trigger save as draft
1181
+ saveFindResponseData(responseData) {
1182
+ if (!this.findReplaceData || !this.selectedStoreForPreview) {
1183
+ return;
1184
+ }
1185
+ const updatedStores = (this.findReplaceData.stores || []).map((store) => {
1186
+ if (store.storeName === this.selectedStoreForPreview.storeName) {
1187
+ return {
1188
+ ...store,
1189
+ findResponseData: responseData?._id
1190
+ };
1191
+ }
1192
+ return store;
1193
+ });
1194
+ // Update local findReplaceData immediately
1195
+ this.findReplaceData = {
1196
+ ...this.findReplaceData,
1197
+ stores: updatedStores
1198
+ };
1199
+ // Update the data service
1200
+ this.dataService.updateData({
1201
+ stores: updatedStores
1202
+ });
1203
+ // Trigger save as draft
1204
+ this.dataService.triggerSaveDraft();
1205
+ }
1206
+ // Save replaceResponseData to specific store and trigger save as draft
1207
+ // Only saves vmConfig and/or shelfConfig based on target
1208
+ saveReplaceResponseData(responseData) {
1209
+ if (!this.findReplaceData || !this.selectedStoreForPreview) {
1210
+ return;
1211
+ }
1212
+ const target = this.target.value;
1213
+ const replaceData = {};
1214
+ // Extract only the relevant configs based on target
1215
+ if (target === 'vm' || target === 'both') {
1216
+ if (responseData?.vmConfig) {
1217
+ replaceData.vmConfig = responseData.vmConfig;
1218
+ }
1219
+ }
1220
+ if (target === 'merch' || target === 'both') {
1221
+ if (responseData?.shelfConfig) {
1222
+ replaceData.shelfConfig = responseData.shelfConfig;
1223
+ }
1224
+ }
1225
+ const updatedStores = (this.findReplaceData.stores || []).map((store) => {
1226
+ if (store.storeName === this.selectedStoreForPreview.storeName) {
1227
+ return {
1228
+ ...store,
1229
+ replaceResponseData: replaceData
1230
+ };
1231
+ }
1232
+ return store;
1233
+ });
1234
+ // Update local findReplaceData immediately
1235
+ this.findReplaceData = {
1236
+ ...this.findReplaceData,
1237
+ stores: updatedStores
1238
+ };
1239
+ // Update the data service
1240
+ this.dataService.updateData({
1241
+ stores: updatedStores
1242
+ });
1243
+ // Trigger save as draft
1244
+ this.dataService.triggerSaveDraft();
1245
+ }
1246
+ updateAiResponseFixture(fixture) {
1247
+ let matchFound = false;
1248
+ for (let i = 0; i < this.floorData.layoutPolygon.length; i++) {
1249
+ const element = this.floorData.layoutPolygon[i];
1250
+ if (element.elementType === 'wall' && Array.isArray(element.fixtures)) {
1251
+ for (let j = 0; j < element.fixtures.length; j++) {
1252
+ const fx = element.fixtures[j];
1253
+ if (fx._id === fixture._id) {
1254
+ // Preserve existing vmConfig if the new fixture doesn't have it
1255
+ const existingVmConfig = fx.vmConfig || [];
1256
+ const updatedFixture = {
1257
+ ...fixture,
1258
+ // Preserve vmConfig from existing fixture if new fixture doesn't have it
1259
+ vmConfig: fixture.vmConfig || existingVmConfig
1260
+ };
1261
+ this.floorData.layoutPolygon[i].fixtures[j] = updatedFixture;
1262
+ matchFound = true;
1263
+ this.selectedFixture = updatedFixture;
1264
+ break;
1265
+ }
1266
+ }
1267
+ }
1268
+ }
1269
+ if (matchFound)
1270
+ return;
1271
+ for (let i = 0; i < this.floorData?.centerFixture.length; i++) {
1272
+ const fx = this.floorData?.centerFixture[i];
1273
+ if (fx._id === fixture._id) {
1274
+ // Preserve existing vmConfig if the new fixture doesn't have it
1275
+ const existingVmConfig = fx.vmConfig || [];
1276
+ const updatedFixture = {
1277
+ ...fixture,
1278
+ // Preserve vmConfig from existing fixture if new fixture doesn't have it
1279
+ vmConfig: fixture.vmConfig || existingVmConfig
1280
+ };
1281
+ this.floorData.centerFixture[i] = updatedFixture;
1282
+ this.selectedFixture = updatedFixture;
1283
+ break;
1284
+ }
1285
+ }
1286
+ }
1287
+ highlightFixture(canvas, group, blink = false) {
1288
+ this.removeHighlight(canvas);
1289
+ this.cancelHighlightBlink = false;
1290
+ const center = group.getCenterPoint();
1291
+ const realWidth = group.width * group.scaleX;
1292
+ const realHeight = group.height * group.scaleY;
1293
+ const rect = new fabric.Rect({
1294
+ left: center.x,
1295
+ top: center.y,
1296
+ width: realWidth + 8,
1297
+ height: realHeight + 8,
1298
+ rx: 5,
1299
+ ry: 5,
1300
+ stroke: "#00aaff",
1301
+ strokeWidth: 3,
1302
+ fill: "transparent",
1303
+ selectable: false,
1304
+ evented: false,
1305
+ originX: "center",
1306
+ originY: "center",
1307
+ angle: group.angle || 0,
1308
+ opacity: blink ? 0 : 1,
1309
+ });
1310
+ rect.data = { type: "fixture-highlight" };
1311
+ canvas.add(rect);
1312
+ canvas.moveObjectTo(rect, canvas.getObjects().length - 1);
1313
+ canvas.requestRenderAll();
1314
+ this.activeHighlight = rect;
1315
+ if (!blink)
1316
+ return;
1317
+ let cycles = 0;
1318
+ const blinkOnce = () => {
1319
+ if (this.cancelHighlightBlink) {
1320
+ this.removeHighlight(canvas);
1321
+ return;
1322
+ }
1323
+ rect.animate({ opacity: 1 }, {
1324
+ duration: 200,
1325
+ onChange: () => canvas.requestRenderAll(),
1326
+ onComplete: () => {
1327
+ if (this.cancelHighlightBlink) {
1328
+ this.removeHighlight(canvas);
1329
+ return;
1330
+ }
1331
+ rect.animate({ opacity: 0 }, {
1332
+ duration: 200,
1333
+ onChange: () => canvas.requestRenderAll(),
1334
+ onComplete: () => {
1335
+ if (this.cancelHighlightBlink) {
1336
+ this.removeHighlight(canvas);
1337
+ return;
1338
+ }
1339
+ cycles++;
1340
+ if (cycles < 20) {
1341
+ blinkOnce();
1342
+ }
1343
+ else {
1344
+ if (!this.cancelHighlightBlink) {
1345
+ rect.set({ opacity: 1 });
1346
+ canvas.requestRenderAll();
1347
+ }
1348
+ }
1349
+ },
1350
+ });
1351
+ },
1352
+ });
1353
+ };
1354
+ blinkOnce();
1355
+ }
1356
+ removeHighlight(canvas) {
1357
+ this.cancelHighlightBlink = true;
1358
+ canvas.getObjects().forEach((obj) => {
1359
+ if (obj.data?.type === "fixture-highlight") {
1360
+ canvas.remove(obj);
1361
+ }
1362
+ });
1363
+ this.activeHighlight = null;
1364
+ canvas.requestRenderAll();
1365
+ }
1366
+ // Planogram rendering methods (simplified versions from collection-update-ai)
1367
+ toPixels(value, unit, dpi = 2.8) {
1368
+ let pixels;
1369
+ if (unit === "mm") {
1370
+ pixels = (value / 25.4) * dpi;
1371
+ }
1372
+ else if (unit === "ft") {
1373
+ pixels = value * 12 * dpi;
1374
+ }
1375
+ else {
1376
+ throw new Error("Unsupported unit. Use 'mm' or 'ft'.");
1377
+ }
1378
+ return Number(pixels.toFixed(4));
1379
+ }
1380
+ async drawLayoutElements(canvas) {
1381
+ if (!this.floorData)
1382
+ return;
1383
+ for (let index = 0; index < this.floorData.layoutPolygon.length; index++) {
1384
+ const element = this.floorData.layoutPolygon[index];
1385
+ let wall;
1386
+ element.relativePosition ??= { x: 0, y: 0, unit: "ft" };
1387
+ const x = this.toPixels(element.relativePosition.x, element.unit);
1388
+ const y = this.toPixels(element.relativePosition.y, element.unit);
1389
+ if (element.elementType === "wall") {
1390
+ const height = this.wallThickness;
1391
+ const width = this.toPixels(element.distance, element.unit);
1392
+ wall = await this.drawWall(canvas, x, y, height, width, element);
1393
+ }
1394
+ else if (element.elementType === "entrance") {
1395
+ this.drawEntrance(canvas, x, y, 80, 75, 40, element);
1396
+ }
1397
+ if (element.elementType === "wall") {
1398
+ const fixtureGroups = [];
1399
+ for (let j = 0; j < element?.fixtures?.length; j++) {
1400
+ const fixture = element.fixtures[j];
1401
+ const fx = this.toPixels(fixture.relativePosition.x, fixture.relativePosition.unit);
1402
+ const fy = this.toPixels(fixture.relativePosition.y, fixture.relativePosition.unit);
1403
+ const fh = this.toPixels(fixture.fixtureStaticLength.value, fixture.fixtureStaticLength.unit);
1404
+ const fw = this.toPixels(fixture.fixtureStaticWidth.value, fixture.fixtureStaticWidth.unit);
1405
+ const fixtureObj = await this.drawFixture(canvas, fx, fy, fh, fw, fixture);
1406
+ fixtureGroups.push(fixtureObj);
1407
+ }
1408
+ if (element.isLocked && wall) {
1409
+ canvas.remove(wall);
1410
+ fixtureGroups.forEach((f) => canvas.remove(f));
1411
+ const combinedGroup = new fabric.Group([wall, ...fixtureGroups], {
1412
+ hasControls: false,
1413
+ selectable: false,
1414
+ lockMovementX: true,
1415
+ lockMovementY: true,
1416
+ lockRotation: true,
1417
+ lockScalingX: true,
1418
+ lockScalingY: true,
1419
+ subTargetCheck: true,
1420
+ });
1421
+ combinedGroup.set({ isLocked: true });
1422
+ canvas.add(combinedGroup);
1423
+ }
1424
+ for (let j = 0; j < element?.otherElements?.length; j++) {
1425
+ const otherElement = element.otherElements[j];
1426
+ const ox = this.toPixels(otherElement.relativePosition.x, "ft");
1427
+ const oy = this.toPixels(otherElement.relativePosition.y, "ft");
1428
+ const oa = otherElement.relativePosition.angle;
1429
+ const oh = this.toPixels(otherElement.fixtureStaticLength.value, otherElement.fixtureStaticLength.unit);
1430
+ const ow = this.toPixels(otherElement.fixtureStaticWidth.value, otherElement.fixtureStaticWidth.unit);
1431
+ this.drawOtherElementsWithLabel(canvas, ox, oy, oa, ow, oh, otherElement);
1432
+ }
1433
+ }
1434
+ }
1435
+ for (let i = 0; i < this.floorData?.centerFixture?.length; i++) {
1436
+ const fixture = this.floorData.centerFixture[i];
1437
+ const x = this.toPixels(fixture.relativePosition.x, fixture.relativePosition.unit);
1438
+ const y = this.toPixels(fixture.relativePosition.y, fixture.relativePosition.unit);
1439
+ const h = this.toPixels(fixture.fixtureStaticLength.value, fixture.fixtureStaticLength.unit);
1440
+ const w = this.toPixels(fixture.fixtureStaticWidth.value, fixture.fixtureStaticWidth.unit);
1441
+ await this.drawFixture(canvas, x, y, h, w, fixture);
1442
+ }
1443
+ for (let j = 0; j < this.floorData?.otherElements?.length; j++) {
1444
+ const otherElement = this.floorData.otherElements[j];
1445
+ const x = this.toPixels(otherElement.relativePosition.x, "ft");
1446
+ const y = this.toPixels(otherElement.relativePosition.y, "ft");
1447
+ const a = otherElement.relativePosition.angle;
1448
+ const h = this.toPixels(otherElement.fixtureStaticLength.value, otherElement.fixtureStaticLength.unit);
1449
+ const w = this.toPixels(otherElement.fixtureStaticWidth.value, otherElement.fixtureStaticWidth.unit);
1450
+ this.drawOtherElementsWithLabel(canvas, x, y, a, w, h, otherElement);
1451
+ }
1452
+ return true;
1453
+ }
1454
+ async drawWall(canvas, x, y, height, width, elementData) {
1455
+ const radius = 5;
1456
+ const fillColor = "#F6FCFF";
1457
+ const strokeColor = "#D0D5DD";
1458
+ const labelColor = "#009BF3";
1459
+ let text = `${this.titleCase.transform(elementData.elementType)} ${elementData.elementNumber}`;
1460
+ const wall = new fabric.Rect({
1461
+ left: 0,
1462
+ top: 0,
1463
+ width,
1464
+ height,
1465
+ rx: radius,
1466
+ ry: radius,
1467
+ fill: fillColor,
1468
+ stroke: strokeColor,
1469
+ strokeWidth: 0.27,
1470
+ selectable: false,
1471
+ strokeUniform: true,
1472
+ });
1473
+ const centerX = width / 2;
1474
+ const centerY = height / 2;
1475
+ const isVertical = height > width;
1476
+ const label = new fabric.FabricText(text, {
1477
+ left: centerX,
1478
+ top: centerY,
1479
+ fontSize: 10,
1480
+ fontFamily: "Inter",
1481
+ fontWeight: "500",
1482
+ fill: labelColor,
1483
+ originX: "center",
1484
+ originY: "center",
1485
+ angle: isVertical ? -90 : 0,
1486
+ selectable: false,
1487
+ });
1488
+ const arrowHead = 5;
1489
+ const elements = [wall, label];
1490
+ if (isVertical) {
1491
+ const textWidth = label.width || 0;
1492
+ const topArrowY = 5;
1493
+ const topArrowEndY = centerY - textWidth / 2 - 5;
1494
+ if (topArrowEndY > topArrowY + arrowHead) {
1495
+ elements.push(new fabric.Line([centerX, topArrowY, centerX, topArrowEndY], {
1496
+ stroke: labelColor,
1497
+ strokeWidth: 1,
1498
+ selectable: false,
1499
+ }), new fabric.Triangle({
1500
+ left: centerX,
1501
+ top: topArrowY,
1502
+ width: arrowHead,
1503
+ height: arrowHead,
1504
+ angle: 0,
1505
+ fill: labelColor,
1506
+ originX: "center",
1507
+ originY: "bottom",
1508
+ selectable: false,
1509
+ }));
1510
+ }
1511
+ const bottomArrowStartY = centerY + textWidth / 2 + 5;
1512
+ const bottomArrowEndY = height - 5;
1513
+ if (bottomArrowEndY > bottomArrowStartY + arrowHead) {
1514
+ elements.push(new fabric.Line([centerX, bottomArrowStartY, centerX, bottomArrowEndY], {
1515
+ stroke: labelColor,
1516
+ strokeWidth: 1,
1517
+ selectable: false,
1518
+ }), new fabric.Triangle({
1519
+ left: centerX,
1520
+ top: bottomArrowEndY,
1521
+ width: arrowHead,
1522
+ height: arrowHead,
1523
+ angle: 180,
1524
+ fill: labelColor,
1525
+ originX: "center",
1526
+ originY: "top",
1527
+ selectable: false,
1528
+ }));
1529
+ }
1530
+ }
1531
+ else {
1532
+ const textWidth = label.width || 0;
1533
+ const leftArrowStartX = 5;
1534
+ const leftArrowEndX = centerX - textWidth / 2 - 5;
1535
+ if (leftArrowEndX > leftArrowStartX + arrowHead) {
1536
+ elements.push(new fabric.Line([leftArrowStartX, centerY, leftArrowEndX, centerY], {
1537
+ stroke: labelColor,
1538
+ strokeWidth: 1,
1539
+ selectable: false,
1540
+ }), new fabric.Triangle({
1541
+ left: leftArrowStartX,
1542
+ top: centerY,
1543
+ width: arrowHead,
1544
+ height: arrowHead,
1545
+ angle: -90,
1546
+ fill: labelColor,
1547
+ originX: "center",
1548
+ originY: "center",
1549
+ selectable: false,
1550
+ }));
1551
+ }
1552
+ const rightArrowStartX = centerX + textWidth / 2 + 5;
1553
+ const rightArrowEndX = width - 5;
1554
+ if (rightArrowEndX > rightArrowStartX + arrowHead) {
1555
+ elements.push(new fabric.Line([rightArrowStartX, centerY, rightArrowEndX, centerY], {
1556
+ stroke: labelColor,
1557
+ strokeWidth: 1,
1558
+ selectable: false,
1559
+ }), new fabric.Triangle({
1560
+ left: rightArrowEndX,
1561
+ top: centerY,
1562
+ width: arrowHead,
1563
+ height: arrowHead,
1564
+ angle: 90,
1565
+ fill: labelColor,
1566
+ originX: "center",
1567
+ originY: "center",
1568
+ selectable: false,
1569
+ }));
1570
+ }
1571
+ }
1572
+ const group = new fabric.Group(elements, {
1573
+ left: x,
1574
+ top: y,
1575
+ hasControls: false,
1576
+ selectable: false,
1577
+ lockScalingX: true,
1578
+ lockScalingY: true,
1579
+ lockRotation: true,
1580
+ lockMovementX: true,
1581
+ lockMovementY: true,
1582
+ evented: true,
1583
+ hoverCursor: "default",
1584
+ angle: elementData.angle,
1585
+ subTargetCheck: true,
1586
+ });
1587
+ group.objType = elementData.elementType;
1588
+ group.data = elementData;
1589
+ canvas.add(group);
1590
+ // If newly added, focus it once
1591
+ if (elementData?.newAdded) {
1592
+ try {
1593
+ canvas.setActiveObject(group);
1594
+ canvas.requestRenderAll();
1595
+ }
1596
+ catch { }
1597
+ delete elementData.newAdded;
1598
+ }
1599
+ return group;
1600
+ }
1601
+ drawEntrance(canvas, x, y, width, height, arrowWidth, elementData) {
1602
+ const bodyWidth = width - arrowWidth;
1603
+ const pathData = [
1604
+ `M 0 0`,
1605
+ `L ${bodyWidth} 0`,
1606
+ `L ${bodyWidth} ${-height / 2}`,
1607
+ `L ${width} ${height / 2}`,
1608
+ `L ${bodyWidth} ${height + height / 2}`,
1609
+ `L ${bodyWidth} ${height}`,
1610
+ `L 0 ${height}`,
1611
+ `Z`,
1612
+ ].join(" ");
1613
+ const arrow = new fabric.Path(pathData, {
1614
+ fill: "#03A9F4",
1615
+ selectable: false,
1616
+ evented: false,
1617
+ });
1618
+ const maxTextHeight = height - 6;
1619
+ const text = new fabric.Text("Entrance", {
1620
+ fontFamily: "Arial",
1621
+ fontWeight: "bold",
1622
+ fill: "white",
1623
+ angle: -90,
1624
+ originX: "center",
1625
+ originY: "center",
1626
+ left: 15,
1627
+ top: height / 2,
1628
+ fontSize: 20,
1629
+ selectable: false,
1630
+ evented: false,
1631
+ });
1632
+ const textBounds = text.getBoundingRect();
1633
+ if (textBounds.height > maxTextHeight) {
1634
+ const scale = maxTextHeight / textBounds.height;
1635
+ text.set("fontSize", text.fontSize * scale);
1636
+ }
1637
+ const group = new fabric.Group([arrow, text], {
1638
+ left: x,
1639
+ top: y,
1640
+ hasControls: false,
1641
+ selectable: false,
1642
+ lockScalingX: true,
1643
+ lockScalingY: true,
1644
+ lockScalingFlip: true,
1645
+ lockRotation: true,
1646
+ lockMovementX: true,
1647
+ lockMovementY: true,
1648
+ evented: true,
1649
+ hoverCursor: "default",
1650
+ angle: elementData.angle,
1651
+ });
1652
+ group.objType = elementData.elementType;
1653
+ group.data = elementData;
1654
+ canvas.add(group);
1655
+ }
1656
+ async drawFixture(canvas, x, y, height, width, fixtureData) {
1657
+ let fixtureColor;
1658
+ // if (["fixture", "fixture-redo"].includes(this.publishingState)) {
1659
+ // fixtureColor = {
1660
+ // primary:
1661
+ // fixtureData.status == "" && fixtureData.taskStatus == "submit"
1662
+ // ? "#a5a6a8"
1663
+ // : fixtureData.status == "agree"
1664
+ // ? "#6CE9A6"
1665
+ // : "#51C1FF",
1666
+ // fill:
1667
+ // fixtureData.status == "" && fixtureData.taskStatus == "submit"
1668
+ // ? "#f3f4f8"
1669
+ // : fixtureData.status == "agree"
1670
+ // ? "#6CE9A6"
1671
+ // : "#EAF8FF",
1672
+ // vmFill:
1673
+ // fixtureData.status == "" && fixtureData.taskStatus == "submit"
1674
+ // ? "#a5a6a8"
1675
+ // : "#6938EF",
1676
+ // };
1677
+ // }
1678
+ if (fixtureData.fixtureName === "space")
1679
+ return;
1680
+ const radius = 5;
1681
+ const mainContainer = new fabric.Rect({
1682
+ left: x,
1683
+ top: y,
1684
+ width: width,
1685
+ height: height,
1686
+ rx: radius,
1687
+ ry: radius,
1688
+ stroke: fixtureColor?.primary ?? "#51C1FF",
1689
+ strokeWidth: 0.27,
1690
+ fill: "white",
1691
+ });
1692
+ const topWidth = width / 1.05;
1693
+ const topHeight = (15 / 100) * height;
1694
+ const topX = x + (width - topWidth) / 2;
1695
+ const topY = y + this.verticalMargin;
1696
+ const topContainer = new fabric.Rect({
1697
+ left: topX,
1698
+ top: topY,
1699
+ width: topWidth,
1700
+ height: topHeight,
1701
+ rx: radius,
1702
+ ry: radius,
1703
+ stroke: fixtureColor?.primary ?? "#51C1FF",
1704
+ strokeWidth: 0.27,
1705
+ fill: "white",
1706
+ });
1707
+ const innerBoxHeight = topHeight / 2;
1708
+ const innerTopBox = new fabric.Path(`M ${topX + radius} ${topY}
1709
+ L ${topX + topWidth - radius} ${topY}
1710
+ Q ${topX + topWidth} ${topY} ${topX + topWidth} ${topY + radius}
1711
+ L ${topX + topWidth} ${topY + innerBoxHeight}
1712
+ L ${topX} ${topY + innerBoxHeight}
1713
+ L ${topX} ${topY + radius}
1714
+ Q ${topX} ${topY} ${topX + radius} ${topY} Z`, {
1715
+ stroke: fixtureColor?.primary ?? "#51C1FF",
1716
+ strokeWidth: 0.27,
1717
+ fill: "transparent",
1718
+ });
1719
+ const topText = new fabric.Textbox(`Fixture ${fixtureData.associatedElementFixtureNumber
1720
+ ? fixtureData.associatedElementFixtureNumber +
1721
+ (fixtureData?.fixtureNumber
1722
+ ? " - FX-" + fixtureData.fixtureNumber
1723
+ : "")
1724
+ : "new"}`, {
1725
+ left: topX + topWidth / 2,
1726
+ top: topY + innerBoxHeight / 2,
1727
+ fontSize: 5,
1728
+ fontFamily: "Inter",
1729
+ fontWeight: "500",
1730
+ fill: "#101828",
1731
+ originX: "center",
1732
+ originY: "center",
1733
+ width: topWidth,
1734
+ height: innerBoxHeight,
1735
+ textAlign: "center",
1736
+ });
1737
+ const secondBoxY = topY + innerBoxHeight;
1738
+ const innerBottomBox = new fabric.Path(`M ${topX} ${secondBoxY}
1739
+ L ${topX + topWidth} ${secondBoxY}
1740
+ L ${topX + topWidth} ${secondBoxY + innerBoxHeight - radius}
1741
+ Q ${topX + topWidth} ${secondBoxY + innerBoxHeight} ${topX + topWidth - radius} ${secondBoxY + innerBoxHeight}
1742
+ L ${topX + radius} ${secondBoxY + innerBoxHeight}
1743
+ Q ${topX} ${secondBoxY + innerBoxHeight} ${topX} ${secondBoxY + innerBoxHeight - radius}
1744
+ L ${topX} ${secondBoxY} Z`, {
1745
+ fill: "#344054",
1746
+ stroke: fixtureColor?.primary ?? "#51C1FF",
1747
+ strokeWidth: 0.27,
1748
+ });
1749
+ let fontSize = 5;
1750
+ let bottomText;
1751
+ const textContent = `${fixtureData?.fixtureName} - ${fixtureData?.fixtureWidth.value} ${fixtureData?.fixtureWidth.unit}`;
1752
+ const createBottomText = (fs) => new fabric.Textbox(textContent, {
1753
+ left: topX + topWidth / 2,
1754
+ top: secondBoxY + innerBoxHeight / 2,
1755
+ fontSize: fs,
1756
+ fontFamily: "Inter",
1757
+ fontWeight: "500",
1758
+ fill: "#FFFFFF",
1759
+ originX: "center",
1760
+ originY: "center",
1761
+ textAlign: "center",
1762
+ width: topWidth,
1763
+ });
1764
+ do {
1765
+ bottomText = createBottomText(fontSize);
1766
+ fontSize -= 0.5;
1767
+ } while (bottomText.height > innerBoxHeight && fontSize > 2);
1768
+ const midWidth = width / 1.05;
1769
+ const midHeight = (77 / 100) * height;
1770
+ const midX = x + (width - midWidth) / 2;
1771
+ const midY = topY + topHeight + this.verticalMargin;
1772
+ const midContainer = new fabric.Rect({
1773
+ left: midX,
1774
+ top: midY,
1775
+ width: midWidth,
1776
+ height: midHeight,
1777
+ rx: radius,
1778
+ ry: radius,
1779
+ stroke: fixtureColor?.primary ?? "#51C1FF",
1780
+ strokeWidth: 0.27,
1781
+ fill: "white",
1782
+ });
1783
+ const shelfCount = fixtureData.shelfConfig?.length;
1784
+ const boxHeight = midHeight / (shelfCount + 2);
1785
+ const firstBoxY = midY;
1786
+ const firstBox = new fabric.Path(`M ${midX + radius} ${firstBoxY}
1787
+ L ${midX + midWidth - radius} ${firstBoxY}
1788
+ Q ${midX + midWidth} ${firstBoxY} ${midX + midWidth} ${firstBoxY + radius}
1789
+ L ${midX + midWidth} ${firstBoxY + boxHeight}
1790
+ L ${midX} ${firstBoxY + boxHeight}
1791
+ L ${midX} ${firstBoxY + radius}
1792
+ Q ${midX} ${firstBoxY} ${midX + radius} ${firstBoxY} Z`, {
1793
+ fill: fixtureColor?.fill
1794
+ ? fixtureColor?.fill
1795
+ : fixtureData.issue
1796
+ ? "#D92D20"
1797
+ : "#EAF8FF",
1798
+ stroke: fixtureColor?.primary
1799
+ ? fixtureColor?.primary
1800
+ : fixtureData.issue
1801
+ ? "#D92D20"
1802
+ : "#6BCAFF",
1803
+ strokeWidth: 0.27,
1804
+ });
1805
+ const firstBoxText = new fabric.Textbox(`${fixtureData?.header?.label ? fixtureData.header.label : ""}`, {
1806
+ left: midX + midWidth / 2,
1807
+ top: firstBoxY + boxHeight / 2,
1808
+ fontSize: 7,
1809
+ fontFamily: "Inter",
1810
+ fontWeight: "600",
1811
+ fill: fixtureData.issue ? "#fff" : "#101828",
1812
+ originX: "center",
1813
+ originY: "center",
1814
+ width: midWidth,
1815
+ height: boxHeight,
1816
+ textAlign: "center",
1817
+ });
1818
+ const shelves = [];
1819
+ const shelfHeight = midHeight - 2 * boxHeight;
1820
+ if (fixtureData.productResolutionLevel === "L1") {
1821
+ const boxY = firstBoxY + boxHeight;
1822
+ const shelf = new fabric.Rect({
1823
+ left: midX,
1824
+ top: boxY,
1825
+ width: midWidth,
1826
+ height: shelfHeight,
1827
+ // stroke: '#51C1FF',
1828
+ stroke: fixtureColor?.primary
1829
+ ? fixtureColor?.primary
1830
+ : fixtureData.issue
1831
+ ? "#D92D20"
1832
+ : "#51C1FF",
1833
+ strokeWidth: 0.27,
1834
+ fill: "white",
1835
+ });
1836
+ const text = fixtureData?.productBrandName?.join(" + ") || "";
1837
+ // Wrap text within fixture width and shrink to fit vertical space
1838
+ const maxTextWidth = midWidth * 0.9;
1839
+ const maxTextHeight = shelfHeight * 0.8;
1840
+ let fontSizeL1 = 6;
1841
+ const createWrappedTextbox = (fs) => new fabric.Textbox(text, {
1842
+ left: midX + midWidth / 2,
1843
+ top: boxY + shelfHeight / 2,
1844
+ originX: "center",
1845
+ originY: "center",
1846
+ width: maxTextWidth,
1847
+ fontSize: fs,
1848
+ fontFamily: "Inter",
1849
+ fontWeight: "500",
1850
+ textAlign: "center",
1851
+ fill: "#333",
1852
+ selectable: false,
1853
+ evented: false,
1854
+ });
1855
+ let wrappedText = createWrappedTextbox(fontSizeL1);
1856
+ while (wrappedText.height > maxTextHeight && fontSizeL1 > 2) {
1857
+ fontSizeL1 -= 0.5;
1858
+ wrappedText = createWrappedTextbox(fontSizeL1);
1859
+ }
1860
+ const padding = 2;
1861
+ const background = new fabric.Rect({
1862
+ left: midX + midWidth / 2,
1863
+ top: boxY + shelfHeight / 2,
1864
+ originX: "center",
1865
+ originY: "center",
1866
+ width: Math.min(maxTextWidth, wrappedText.width) + padding,
1867
+ height: wrappedText.getScaledHeight() + 2,
1868
+ fill: "rgba(255, 255, 255, 0.5)",
1869
+ selectable: false,
1870
+ evented: false,
1871
+ rx: 1,
1872
+ ry: 1,
1873
+ });
1874
+ shelves.push(shelf, background, wrappedText);
1875
+ }
1876
+ else if (fixtureData.productResolutionLevel === "L2") {
1877
+ for (let i = 0; i < shelfCount; i++) {
1878
+ const boxY = firstBoxY + boxHeight * (i + 1);
1879
+ const shelf = new fabric.Rect({
1880
+ left: midX,
1881
+ top: boxY,
1882
+ width: midWidth,
1883
+ height: boxHeight,
1884
+ stroke: fixtureColor?.primary
1885
+ ? fixtureColor?.primary
1886
+ : fixtureData.issue
1887
+ ? "#D92D20"
1888
+ : "#51C1FF",
1889
+ strokeWidth: 0.27,
1890
+ fill: "white",
1891
+ });
1892
+ shelves.push(shelf);
1893
+ if (fixtureData.shelfConfig?.[i].shelfType === "tray") {
1894
+ const trayRows = fixtureData.shelfConfig?.[i].trayRows || 1;
1895
+ const rowSpacing = boxHeight / trayRows;
1896
+ for (let r = 1; r < trayRows; r++) {
1897
+ const lineY = boxY + r * rowSpacing;
1898
+ const trayLine = new fabric.Line([midX, lineY, midX + midWidth, lineY], {
1899
+ stroke: "#999",
1900
+ strokeWidth: 0.2,
1901
+ selectable: false,
1902
+ evented: false,
1903
+ });
1904
+ shelves.push(trayLine);
1905
+ }
1906
+ }
1907
+ const text = fixtureData.shelfConfig?.[i].productBrandName?.join(" + ") || "";
1908
+ // L2: Single-line ellipsis against full shelf width
1909
+ const horizontalPadding = 6;
1910
+ const maxTextWidth = Math.max(0, midWidth - horizontalPadding);
1911
+ const maxTextHeight = boxHeight * 0.8;
1912
+ const baseFontSize = 5;
1913
+ const measure = (t) => new fabric.Text(t, {
1914
+ fontSize: baseFontSize,
1915
+ fontFamily: "Inter",
1916
+ fontWeight: "500",
1917
+ });
1918
+ let displayText = text;
1919
+ let measured = measure(displayText);
1920
+ if ((measured.width ?? 0) > maxTextWidth) {
1921
+ const ellipsis = "...";
1922
+ let leftIdx = 0;
1923
+ let rightIdx = text.length;
1924
+ while (leftIdx < rightIdx) {
1925
+ const midIdx = Math.floor((leftIdx + rightIdx) / 2);
1926
+ const candidate = text.slice(0, midIdx) + ellipsis;
1927
+ measured = measure(candidate);
1928
+ if ((measured.width ?? 0) > maxTextWidth) {
1929
+ rightIdx = midIdx;
1930
+ }
1931
+ else {
1932
+ leftIdx = midIdx + 1;
1933
+ }
1934
+ }
1935
+ displayText = text.slice(0, Math.max(0, leftIdx - 1)) + ellipsis;
1936
+ measured = measure(displayText);
1937
+ }
1938
+ const background = new fabric.Rect({
1939
+ left: midX + midWidth / 2,
1940
+ top: boxY + boxHeight / 2,
1941
+ originX: "center",
1942
+ originY: "center",
1943
+ width: midWidth,
1944
+ height: Math.min(maxTextHeight, measured.height ?? 10) + 2,
1945
+ fill: "rgba(255, 255, 255, 0.5)",
1946
+ selectable: false,
1947
+ evented: false,
1948
+ rx: 1,
1949
+ ry: 1,
1950
+ });
1951
+ const finalText = new fabric.Text(displayText, {
1952
+ left: midX + midWidth / 2,
1953
+ top: boxY + boxHeight / 2,
1954
+ originX: "center",
1955
+ originY: "center",
1956
+ fontSize: baseFontSize,
1957
+ fontFamily: "Inter",
1958
+ fontWeight: "500",
1959
+ fill: "#333",
1960
+ selectable: false,
1961
+ evented: false,
1962
+ });
1963
+ shelves.push(background, finalText);
1964
+ }
1965
+ }
1966
+ else if (fixtureData.productResolutionLevel === "L3") {
1967
+ const sequentialGroups = [];
1968
+ let previousZone = null;
1969
+ for (const shelf of fixtureData.shelfConfig) {
1970
+ const zone = shelf.zone || "Unknown";
1971
+ if (zone !== previousZone) {
1972
+ sequentialGroups.push({ zone, shelves: [shelf] });
1973
+ previousZone = zone;
1974
+ }
1975
+ else {
1976
+ sequentialGroups[sequentialGroups.length - 1].shelves.push(shelf);
1977
+ }
1978
+ }
1979
+ let currentShelfIndex = 0;
1980
+ for (const group of sequentialGroups) {
1981
+ const { zone, shelves: shelvesInGroup } = group;
1982
+ const groupStartIndex = currentShelfIndex;
1983
+ const groupLength = shelvesInGroup.length;
1984
+ const groupTopY = firstBoxY + boxHeight * (groupStartIndex + 1);
1985
+ const groupBottomY = groupTopY + boxHeight * groupLength;
1986
+ for (let j = 0; j < shelvesInGroup.length; j++) {
1987
+ const shelfData = shelvesInGroup[j];
1988
+ const boxY = firstBoxY + boxHeight * (currentShelfIndex + 1);
1989
+ const shelfRect = new fabric.Rect({
1990
+ left: midX,
1991
+ top: boxY,
1992
+ width: midWidth,
1993
+ height: boxHeight,
1994
+ stroke: fixtureColor?.primary
1995
+ ? fixtureColor?.primary
1996
+ : fixtureData.issue
1997
+ ? "#D92D20"
1998
+ : "#51C1FF",
1999
+ strokeWidth: 0.27,
2000
+ fill: "white",
2001
+ });
2002
+ shelves.push(shelfRect);
2003
+ if (shelfData.shelfType === "tray") {
2004
+ const trayRows = shelfData.trayRows || 0;
2005
+ const productPerShelf = shelfData.productPerShelf || 0;
2006
+ const rowSpacing = boxHeight / trayRows;
2007
+ const columnSpacing = midWidth / productPerShelf;
2008
+ for (let r = 1; r < trayRows; r++) {
2009
+ const lineY = boxY + r * rowSpacing;
2010
+ const trayLine = new fabric.Line([midX, lineY, midX + midWidth, lineY], {
2011
+ stroke: "#999",
2012
+ strokeWidth: 0.2,
2013
+ selectable: false,
2014
+ evented: false,
2015
+ });
2016
+ shelves.push(trayLine);
2017
+ }
2018
+ for (let c = 1; c < productPerShelf; c++) {
2019
+ const lineX = midX + c * columnSpacing;
2020
+ const verticalLine = new fabric.Line([lineX, boxY, lineX, boxY + boxHeight], {
2021
+ stroke: "#999",
2022
+ strokeWidth: 0.2,
2023
+ selectable: false,
2024
+ evented: false,
2025
+ });
2026
+ shelves.push(verticalLine);
2027
+ }
2028
+ }
2029
+ currentShelfIndex++;
2030
+ }
2031
+ const groupBottomLine = new fabric.Line([midX, groupBottomY, midX + midWidth, groupBottomY], {
2032
+ stroke: fixtureColor?.primary
2033
+ ? fixtureColor?.primary
2034
+ : fixtureData.issue
2035
+ ? "#D92D20"
2036
+ : "#51C1FF",
2037
+ strokeWidth: 1,
2038
+ selectable: false,
2039
+ evented: false,
2040
+ });
2041
+ shelves.push(groupBottomLine);
2042
+ if (fixtureData.fixtureType === "wall") {
2043
+ const labelPadding = 2;
2044
+ const labelText = new fabric.Textbox(zone, {
2045
+ left: midX + midWidth - labelPadding,
2046
+ top: groupBottomY,
2047
+ fontSize: 5,
2048
+ fontFamily: "Inter",
2049
+ fontWeight: "600",
2050
+ fill: "#707070",
2051
+ originX: "right",
2052
+ originY: "bottom",
2053
+ width: midWidth / 2,
2054
+ textAlign: "right",
2055
+ });
2056
+ shelves.push(labelText);
2057
+ }
2058
+ const groupCenterX = midX + midWidth / 2;
2059
+ const groupCenterY = groupTopY + (groupBottomY - groupTopY) / 2;
2060
+ const sectionBrands = new Set();
2061
+ shelvesInGroup?.forEach((shelf) => {
2062
+ shelf.productBrandName?.forEach((brand) => {
2063
+ sectionBrands.add(brand);
2064
+ });
2065
+ });
2066
+ if ([...sectionBrands].length) {
2067
+ const text = [...sectionBrands].join(" + ");
2068
+ const padding = 2;
2069
+ const maxTextWidth = midWidth;
2070
+ const rectWidth = midWidth * 0.9;
2071
+ const maxTextHeight = 20;
2072
+ let fontSize = 6;
2073
+ let wrappedText;
2074
+ const createTextbox = (fs) => {
2075
+ return new fabric.Textbox(text, {
2076
+ fontSize: fs,
2077
+ fontFamily: "Inter",
2078
+ fontWeight: "400",
2079
+ width: maxTextWidth,
2080
+ textAlign: "center",
2081
+ originX: "center",
2082
+ originY: "center",
2083
+ fill: "#101828",
2084
+ selectable: false,
2085
+ evented: false,
2086
+ left: groupCenterX,
2087
+ top: groupCenterY,
2088
+ });
2089
+ };
2090
+ do {
2091
+ wrappedText = createTextbox(fontSize);
2092
+ fontSize -= 0.5;
2093
+ } while (wrappedText.height > maxTextHeight && fontSize > 2);
2094
+ const rectHeight = wrappedText.getScaledHeight() + padding;
2095
+ const groupCenterText = new fabric.Rect({
2096
+ left: groupCenterX,
2097
+ top: groupCenterY,
2098
+ originX: "center",
2099
+ originY: "center",
2100
+ width: rectWidth,
2101
+ height: rectHeight,
2102
+ fill: "rgba(255, 255, 255, 0.5)",
2103
+ selectable: false,
2104
+ evented: false,
2105
+ rx: 1,
2106
+ ry: 1,
2107
+ });
2108
+ shelves.push(groupCenterText, wrappedText);
2109
+ }
2110
+ }
2111
+ }
2112
+ if (fixtureData?.vmConfig?.length) {
2113
+ for (let i = 0; i < fixtureData.vmConfig.length; i++) {
2114
+ const vm = fixtureData.vmConfig[i];
2115
+ const startIndex = vm.startYPosition - 1;
2116
+ const endIndex = vm.endYPosition - 1;
2117
+ const shelfTopY = firstBoxY + boxHeight * (startIndex + 1);
2118
+ const shelfHeightSpan = boxHeight * (endIndex - startIndex + 1);
2119
+ let vmHeightPx = shelfHeightSpan;
2120
+ let y = shelfTopY;
2121
+ if (vm.yZone && vm.yZone !== "stretch") {
2122
+ vmHeightPx = shelfHeightSpan / 3;
2123
+ switch (vm.yZone) {
2124
+ case "top":
2125
+ y = shelfTopY;
2126
+ break;
2127
+ case "middle":
2128
+ y = shelfTopY + vmHeightPx;
2129
+ break;
2130
+ case "bottom":
2131
+ y = shelfTopY + 2 * vmHeightPx;
2132
+ break;
2133
+ default:
2134
+ y = shelfTopY;
2135
+ }
2136
+ }
2137
+ let x = midX;
2138
+ let width = midWidth;
2139
+ if (!vm.xZone || vm.xZone === "stretch") {
2140
+ width = midWidth;
2141
+ x = midX;
2142
+ }
2143
+ else {
2144
+ const sectionWidth = midWidth / 3;
2145
+ switch (vm.xZone) {
2146
+ case "left":
2147
+ width = sectionWidth;
2148
+ x = midX;
2149
+ break;
2150
+ case "middle":
2151
+ width = sectionWidth;
2152
+ x = midX + sectionWidth;
2153
+ break;
2154
+ case "right":
2155
+ width = sectionWidth;
2156
+ x = midX + 2 * sectionWidth;
2157
+ break;
2158
+ default:
2159
+ width = midWidth;
2160
+ x = midX;
2161
+ }
2162
+ }
2163
+ if (vm.vmImageUrl) {
2164
+ try {
2165
+ const vmImage = await fabric.FabricImage.fromURL(`${this.cdnUrl}${vm.vmImageUrl}?v=${Date.now()}`, {
2166
+ crossOrigin: "anonymous",
2167
+ });
2168
+ vmImage.set({
2169
+ left: x + width / 2,
2170
+ top: y + vmHeightPx / 2,
2171
+ originX: "center",
2172
+ originY: "center",
2173
+ scaleX: width / vmImage.width,
2174
+ scaleY: vmHeightPx / vmImage.height,
2175
+ selectable: false,
2176
+ evented: false,
2177
+ });
2178
+ shelves.push(vmImage);
2179
+ }
2180
+ catch (err) {
2181
+ console.error(`Error loading image for VM: ${vm.vmImageUrl}`, err);
2182
+ }
2183
+ }
2184
+ else {
2185
+ const vmBox = new fabric.Rect({
2186
+ left: x,
2187
+ top: y,
2188
+ width,
2189
+ height: vmHeightPx,
2190
+ fill: fixtureColor?.vmFill ?? "#6938EF",
2191
+ selectable: false,
2192
+ evented: false,
2193
+ });
2194
+ let fontSize = 5;
2195
+ let vmText;
2196
+ const createVmText = (fs) => new fabric.Textbox(vm.vmName || "", {
2197
+ left: x + width / 2,
2198
+ top: y + vmHeightPx / 2,
2199
+ originX: "center",
2200
+ originY: "center",
2201
+ fontSize: fs,
2202
+ fontFamily: "Inter",
2203
+ fontWeight: "600",
2204
+ fill: "white",
2205
+ textAlign: "center",
2206
+ width: width,
2207
+ selectable: false,
2208
+ evented: false,
2209
+ });
2210
+ do {
2211
+ vmText = createVmText(fontSize);
2212
+ fontSize -= 0.5;
2213
+ } while (vmText.height > vmHeightPx && fontSize > 2);
2214
+ shelves.push(vmBox, vmText);
2215
+ }
2216
+ }
2217
+ }
2218
+ const lastBoxY = firstBoxY + boxHeight * (shelfCount + 1);
2219
+ const lastBox = new fabric.Path(`M ${midX} ${lastBoxY}
2220
+ L ${midX + midWidth} ${lastBoxY}
2221
+ L ${midX + midWidth} ${lastBoxY + boxHeight - radius}
2222
+ Q ${midX + midWidth} ${lastBoxY + boxHeight} ${midX + midWidth - radius} ${lastBoxY + boxHeight}
2223
+ L ${midX + radius} ${lastBoxY + boxHeight}
2224
+ Q ${midX} ${lastBoxY + boxHeight} ${midX} ${lastBoxY + boxHeight - radius}
2225
+ L ${midX} ${lastBoxY} Z`, {
2226
+ fill: fixtureColor?.fill
2227
+ ? fixtureColor?.fill
2228
+ : fixtureData.issue
2229
+ ? "#FEE4E2"
2230
+ : "#EAF8FF",
2231
+ stroke: fixtureColor?.primary
2232
+ ? fixtureColor?.primary
2233
+ : fixtureData.issue
2234
+ ? "#D92D20"
2235
+ : "#6BCAFF",
2236
+ strokeWidth: 0.27,
2237
+ });
2238
+ const lastBoxText = new fabric.Textbox(`${fixtureData?.footer?.label ? fixtureData.footer.label : ""}`, {
2239
+ left: midX + midWidth / 2,
2240
+ top: lastBoxY + boxHeight / 2,
2241
+ fontSize: 5,
2242
+ fontFamily: "Inter",
2243
+ fontWeight: "600",
2244
+ fill: "#101828",
2245
+ originX: "center",
2246
+ originY: "center",
2247
+ textAlign: "center",
2248
+ width: midWidth,
2249
+ heigth: boxHeight,
2250
+ });
2251
+ const bottomWidth = width / 1.05;
2252
+ const bottomHeight = (3 / 100) * height;
2253
+ const bottomX = x + (width - bottomWidth) / 2;
2254
+ const bottomY = midY + midHeight + this.verticalMargin;
2255
+ const bottomContainer = new fabric.Rect({
2256
+ left: bottomX,
2257
+ top: bottomY,
2258
+ width: bottomWidth,
2259
+ height: bottomHeight,
2260
+ rx: radius,
2261
+ ry: radius,
2262
+ stroke: "transparent",
2263
+ fill: "transparent",
2264
+ });
2265
+ const bottomTextContent = new fabric.Textbox(`Shelves - ${fixtureData.shelfConfig?.length} . Products - ${fixtureData.fixtureCapacity} . VM - ${fixtureData.vmConfig?.length}`, {
2266
+ left: bottomX + bottomWidth / 2,
2267
+ top: bottomY + bottomHeight / 2,
2268
+ fontSize: 5,
2269
+ fontFamily: "Inter",
2270
+ fontWeight: "500",
2271
+ fill: "#333",
2272
+ originX: "center",
2273
+ originY: "center",
2274
+ textAlign: "center",
2275
+ width: bottomWidth,
2276
+ height: bottomHeight,
2277
+ });
2278
+ const fixtureGroup = new fabric.Group([
2279
+ mainContainer,
2280
+ topContainer,
2281
+ innerTopBox,
2282
+ topText,
2283
+ innerBottomBox,
2284
+ bottomText,
2285
+ midContainer,
2286
+ firstBox,
2287
+ firstBoxText,
2288
+ ...shelves,
2289
+ lastBox,
2290
+ lastBoxText,
2291
+ bottomContainer,
2292
+ bottomTextContent,
2293
+ ], {
2294
+ left: x,
2295
+ top: y,
2296
+ evented: true,
2297
+ selectable: false,
2298
+ hoverCursor: "default",
2299
+ lockScalingX: true,
2300
+ lockScalingY: true,
2301
+ lockMovementX: true,
2302
+ lockMovementY: true,
2303
+ lockRotation: true,
2304
+ hasControls: false,
2305
+ subTargetCheck: true,
2306
+ angle: fixtureData.relativePosition?.angle ?? 0,
2307
+ });
2308
+ fixtureGroup.fixtureType = fixtureData.fixtureType;
2309
+ fixtureGroup.wallIndex = fixtureData.associatedElementNumber;
2310
+ fixtureGroup.fixtureIndex = fixtureData.associatedElementFixtureNumber;
2311
+ fixtureGroup.fixtureId = fixtureData._id;
2312
+ fixtureGroup.issue = fixtureData.issue;
2313
+ fixtureGroup.issueData = fixtureData.issueData;
2314
+ fixtureGroup.taskType = fixtureData.taskType;
2315
+ fixtureGroup.vmConfig = fixtureData.vmConfig;
2316
+ fixtureGroup.objType = "fixture";
2317
+ // Add click handler directly on the fixture group
2318
+ fixtureGroup.on("mousedown", (event) => {
2319
+ // Use the fixture group itself (which has all the fixture properties)
2320
+ // The event.target might be a child element, so we use fixtureGroup directly
2321
+ if (fixtureGroup && fixtureGroup.fixtureId) {
2322
+ this.onFixtureClick(fixtureGroup);
2323
+ }
2324
+ });
2325
+ canvas.add(fixtureGroup);
2326
+ // If newly added, focus it once
2327
+ if (fixtureData?.newAdded) {
2328
+ try {
2329
+ canvas.setActiveObject(fixtureGroup);
2330
+ canvas.requestRenderAll();
2331
+ }
2332
+ catch { }
2333
+ delete fixtureData.newAdded;
2334
+ }
2335
+ return fixtureGroup;
2336
+ }
2337
+ drawOtherElementsWithLabel(canvas, x, y, a, width, height, element) {
2338
+ const rect = new fabric.Rect({
2339
+ width,
2340
+ height,
2341
+ rx: 2,
2342
+ ry: 2,
2343
+ fill: "#DAF1FF",
2344
+ stroke: "#6BCAFF",
2345
+ strokeWidth: 2,
2346
+ originX: "center",
2347
+ originY: "center",
2348
+ });
2349
+ const text = new fabric.Textbox(element.fixtureName, {
2350
+ width: width - 8,
2351
+ fontSize: 14,
2352
+ fontFamily: "Inter",
2353
+ fontWeight: "500",
2354
+ fill: "#101828",
2355
+ originX: "center",
2356
+ originY: "center",
2357
+ textAlign: "center",
2358
+ editable: false,
2359
+ splitByGrapheme: true,
2360
+ });
2361
+ const textBounds = text.getBoundingRect();
2362
+ if (textBounds.height > height - 8) {
2363
+ const scale = (height - 8) / textBounds.height;
2364
+ text.set("fontSize", text.fontSize * scale);
2365
+ }
2366
+ const group = new fabric.Group([rect, text], {
2367
+ left: x,
2368
+ top: y,
2369
+ angle: a,
2370
+ originX: "center",
2371
+ originY: "center",
2372
+ hasControls: false,
2373
+ selectable: false,
2374
+ lockScalingX: true,
2375
+ lockScalingY: true,
2376
+ lockRotation: true,
2377
+ lockMovementX: true,
2378
+ lockMovementY: true,
2379
+ evented: true,
2380
+ hoverCursor: "default",
2381
+ });
2382
+ group.objType = "others";
2383
+ group.data = element;
2384
+ canvas.add(group);
2385
+ if (element?.newAdded) {
2386
+ try {
2387
+ canvas.setActiveObject(group);
2388
+ canvas.requestRenderAll();
2389
+ }
2390
+ catch { }
2391
+ delete element.newAdded;
2392
+ }
2393
+ return group;
2394
+ }
2395
+ collectAllFixtures() {
2396
+ this.allFixtureInstances = [];
2397
+ // Collect wall fixtures
2398
+ if (this.floorData?.layoutPolygon) {
2399
+ for (const element of this.floorData.layoutPolygon) {
2400
+ if (element.fixtures && Array.isArray(element.fixtures)) {
2401
+ this.allFixtureInstances.push(...element.fixtures);
2402
+ }
2403
+ }
2404
+ }
2405
+ // Collect floor fixtures
2406
+ if (this.floorData?.centerFixture && Array.isArray(this.floorData.centerFixture)) {
2407
+ this.allFixtureInstances.push(...this.floorData.centerFixture);
2408
+ }
2409
+ }
2410
+ onFixtureClick(target) {
2411
+ if (!target || !this.floorData)
2412
+ return;
2413
+ const fixtureId = target.fixtureId;
2414
+ const fixtureType = target.fixtureType;
2415
+ if (!fixtureId) {
2416
+ console.warn('Fixture click: No fixtureId found on target', target);
2417
+ return;
2418
+ }
2419
+ // Find the fixture data
2420
+ let fixtureData = null;
2421
+ if (fixtureType === "wall") {
2422
+ const wallIndex = target.wallIndex;
2423
+ if (this.floorData.layoutPolygon && wallIndex !== undefined && wallIndex !== null) {
2424
+ // Find wall by elementNumber (wallIndex is the elementNumber)
2425
+ const wall = this.floorData.layoutPolygon.find((w) => w.elementNumber === wallIndex);
2426
+ if (wall && wall.fixtures) {
2427
+ // Always use fixtureId to find the fixture (more reliable than index-based lookup)
2428
+ fixtureData = wall.fixtures.find((f) => f._id === fixtureId);
2429
+ }
2430
+ }
2431
+ }
2432
+ else if (fixtureType === "floor") {
2433
+ fixtureData = this.floorData.centerFixture?.find((f) => f._id === fixtureId);
2434
+ }
2435
+ if (!fixtureData) {
2436
+ console.warn('Fixture click: Fixture data not found', {
2437
+ fixtureId,
2438
+ fixtureType,
2439
+ wallIndex: target.wallIndex,
2440
+ fixtureIndex: target.fixtureIndex,
2441
+ floorData: this.floorData
2442
+ });
2443
+ return;
2444
+ }
2445
+ // Ensure vmConfig is always an array (even if empty) to avoid display issues
2446
+ // Handle cases where vmConfig might be null, undefined, or not an array
2447
+ if (!Array.isArray(fixtureData.vmConfig)) {
2448
+ fixtureData.vmConfig = [];
2449
+ }
2450
+ // Create a deep clone to ensure change detection works
2451
+ const clonedData = structuredClone(fixtureData);
2452
+ this.selectedFixture = {
2453
+ fixtureId: fixtureId,
2454
+ fixtureType: fixtureType,
2455
+ wallIndex: target.wallIndex,
2456
+ fixtureIndex: target.fixtureIndex,
2457
+ };
2458
+ // Check if this fixture has replaceResponseData (for before/after comparison)
2459
+ const store = this.findReplaceData?.stores?.find((s) => s.storeName === this.selectedStoreForPreview?.storeName);
2460
+ // If this fixture matches the findResponseData and has replaceResponseData,
2461
+ // restore the original fixture data for before/after comparison
2462
+ if (store?.findResponseData === fixtureId && store?.replaceResponseData) {
2463
+ // Restore originalFixtureData from the map (persists even when clicking other fixtures)
2464
+ const storedOriginal = this.originalFixturesMap.get(fixtureId);
2465
+ if (storedOriginal) {
2466
+ this.originalFixtureData = structuredClone(storedOriginal);
2467
+ }
2468
+ else {
2469
+ // If not in map (shouldn't happen if applyStoredResponseData ran),
2470
+ // use current fixture as fallback
2471
+ this.originalFixtureData = structuredClone(clonedData);
2472
+ }
2473
+ }
2474
+ else {
2475
+ // No replace data for this fixture, clear original
2476
+ this.originalFixtureData = null;
2477
+ }
2478
+ // Force change detection by creating a new object reference
2479
+ this.selectedFixtureData = null;
2480
+ this.cdr.detectChanges();
2481
+ setTimeout(() => {
2482
+ this.selectedFixtureData = clonedData;
2483
+ this.isRightPanelCollapsed = false;
2484
+ this.cdr.detectChanges();
2485
+ // Re-center planogram when panel opens (similar to manage-planogram)
2486
+ setTimeout(() => {
2487
+ if (this.previewCanvas && this.previewCanvasContainerRef?.nativeElement) {
2488
+ this.resizeCanvas(this.previewCanvas, this.previewCanvasContainerRef);
2489
+ this.fitCanvasToLayoutAnimated(this.previewCanvas);
2490
+ }
2491
+ }, 400);
2492
+ }, 0);
2493
+ }
2494
+ toggleRightPanel() {
2495
+ this.isRightPanelCollapsed = !this.isRightPanelCollapsed;
2496
+ // Resize canvas when panel is toggled
2497
+ setTimeout(() => {
2498
+ if (this.previewCanvas && this.previewCanvasContainerRef?.nativeElement) {
2499
+ this.resizeCanvas(this.previewCanvas, this.previewCanvasContainerRef);
2500
+ this.fitCanvasToLayoutAnimated(this.previewCanvas);
2501
+ }
2502
+ }, 400);
2503
+ }
2504
+ ngOnDestroy() {
2505
+ if (this.previewCanvas) {
2506
+ this.previewCanvas.dispose();
2507
+ }
2508
+ this.destroy$.next();
2509
+ this.destroy$.complete();
2510
+ }
2511
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PrepareTemplateComponent, deps: [{ token: i1.StoreBuilderService }, { token: i2.CollectionUpdateAiDataService }, { token: i3.TitleCasePipe }, { token: i0.ChangeDetectorRef }, { token: i4.GlobalStateService }, { token: i5.Router }, { token: i5.ActivatedRoute }, { token: i6.ToastService }, { token: i7.NgbModal }], target: i0.ɵɵFactoryTarget.Component });
2512
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: PrepareTemplateComponent, isStandalone: true, selector: "lib-prepare-template", providers: [TitleCasePipe], viewQueries: [{ propertyName: "previewCanvasRef", first: true, predicate: ["previewCanvas"], descendants: true }, { propertyName: "previewCanvasContainerRef", first: true, predicate: ["previewCanvasContainer"], descendants: true }], ngImport: i0, template: "<div class=\"main-card\">\r\n <form>\r\n <!-- Section 1: Add Stores -->\r\n <div class=\"section-row\">\r\n <div class=\"section-number\">1</div>\r\n <div class=\"section-content\">\r\n <h2 class=\"section-title\">Add stores</h2>\r\n <div class=\"store-input-wrapper\">\r\n <div class=\"store-dropdown\">\r\n <lib-reactive-select\r\n [idField]=\"'value'\"\r\n [nameField]=\"'label'\"\r\n [data]=\"searchModes\"\r\n [formControl]=\"selectedMode\" \r\n >\r\n </lib-reactive-select>\r\n </div> \r\n <lib-store-select \r\n [options]=\"storeOptions\"\r\n [initialSelected]=\"selectedStores\"\r\n (selectedChange)=\"onStoresSelected($event)\">\r\n </lib-store-select>\r\n <button class=\"btn-apply\" type=\"button\" (click)=\"onApply()\" [disabled]=\"loading || findLoading || replaceLoading || savingDraft\">\r\n {{ savingDraft ? 'Saving...' : 'Apply' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Section 2: Choose Target -->\r\n <div class=\"section-row\" *ngIf=\"hasStores\">\r\n <div class=\"section-number\">2</div>\r\n <div class=\"section-content\">\r\n <h2 class=\"section-title\">Choose target</h2>\r\n <div class=\"target-buttons\">\r\n <label class=\"target-btn\" [class.active]=\"target.value === 'both'\">\r\n <input type=\"radio\" name=\"target\" value=\"both\" [formControl]=\"target\">\r\n Both\r\n </label>\r\n <label class=\"target-btn\" [class.active]=\"target.value === 'merch'\">\r\n <input type=\"radio\" name=\"target\" value=\"merch\" [formControl]=\"target\">\r\n Merchandise\r\n </label>\r\n <label class=\"target-btn\" [class.active]=\"target.value === 'vm'\">\r\n <input type=\"radio\" name=\"target\" value=\"vm\" [formControl]=\"target\">\r\n Visual Merchandise\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Section 3: Find and Replace -->\r\n <div class=\"section-row\" *ngIf=\"hasStores\">\r\n <div class=\"section-number\">3</div>\r\n <div class=\"section-content\">\r\n <h2 class=\"section-title\">Provide an instruction to find and replace in the selected store</h2>\r\n </div>\r\n </div>\r\n \r\n <!-- Find and Replace Inputs -->\r\n <div class=\"find-replace-wrapper\" *ngIf=\"hasStores\">\r\n <div class=\"find-replace-box\">\r\n <label class=\"find-replace-label\">Target</label>\r\n <div class=\"find-replace-input\">\r\n <textarea \r\n placeholder=\"Instruct what to find it in the selected store\"\r\n [formControl]=\"findPrompt\"></textarea>\r\n <div class=\"input-btn-container\">\r\n <button \r\n class=\"btn-find\" \r\n type=\"button\"\r\n (click)=\"onFind()\"\r\n [disabled]=\"findLoading || replaceLoading || !selectedStoreForPreview\">\r\n {{ findLoading ? 'Processing...' : 'Find' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <div class=\"arrow-icon\">\r\n <svg width=\"27\" height=\"15\" viewBox=\"0 0 27 15\" fill=\"none\">\r\n <path d=\"M26.7071 8.07107C27.0976 7.68054 27.0976 7.04738 26.7071 6.65685L20.3431 0.292893C19.9526 -0.097631 19.3195 -0.097631 18.9289 0.292893C18.5384 0.683418 18.5384 1.31658 18.9289 1.70711L24.5858 7.36396L18.9289 13.0208C18.5384 13.4113 18.5384 14.0445 18.9289 14.435C19.3195 14.8256 19.9526 14.8256 20.3431 14.435L26.7071 8.07107ZM0 7.36396V8.36396H26V7.36396V6.36396H0V7.36396Z\" fill=\"#98A2B3\"/>\r\n </svg>\r\n </div>\r\n \r\n <div class=\"find-replace-box\">\r\n <label class=\"find-replace-label\">Change</label>\r\n <div class=\"find-replace-input\">\r\n <textarea \r\n placeholder=\"Type what would you like to replace in the selected fixture\"\r\n [formControl]=\"replacePrompt\"></textarea>\r\n <div class=\"input-btn-container\">\r\n <button \r\n class=\"btn-replace\" \r\n type=\"button\"\r\n (click)=\"onReplace()\"\r\n [disabled]=\"!findPrompt.value || !replacePrompt.value || findLoading || replaceLoading || !getCurrentStoreFindResponseData()\">\r\n {{ replaceLoading ? 'Processing...' : 'Replace' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Preview Section -->\r\n <div class=\"preview-wrapper\" *ngIf=\"hasStores\">\r\n <div class=\"row g-0 preview-layout\">\r\n <!-- Left Column: Canvas -->\r\n <div class=\"col\" [ngClass]=\"{ \r\n 'col-6': !isRightPanelCollapsed && selectedFixtureData && originalFixtureData,\r\n 'col-9': !isRightPanelCollapsed && selectedFixtureData && !originalFixtureData, \r\n 'col-12': isRightPanelCollapsed || !selectedFixtureData \r\n }\">\r\n <div class=\"d-flex align-items-start gap-3 mb-3\">\r\n <!-- Store Dropdown -->\r\n <lib-store-dropdown \r\n *ngIf=\"hasStores && storeDropdownItems.length > 0\"\r\n [items]=\"storeDropdownItems\"\r\n [idField]=\"'storeId'\"\r\n [searchField]=\"'storeName'\"\r\n [multi]=\"false\"\r\n [selectedValues]=\"selectedStoreValues\"\r\n (selected)=\"onStoreSelectedForPreview($event)\">\r\n </lib-store-dropdown>\r\n \r\n <!-- Content Area -->\r\n <div class=\"flex-grow-1\">\r\n <!-- Preview Title -->\r\n <p class=\"fw-semibold mb-1\" style=\"font-size: 14px; color: #1d2939;\">\r\n Preview \r\n <span *ngIf=\"getStoreCount() > 0\" style=\"font-weight: 400; color: #667085;\">\r\n ({{ getStoreCount() }} {{ getStoreCount() === 1 ? 'Store' : 'Stores' }})\r\n </span>\r\n </p>\r\n \r\n <!-- Description -->\r\n <p class=\"mb-0\" style=\"font-size: 14px; color: #475467;\">Check if the prompt fit into the expected results in order to proceed to review and approve</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Canvas Container -->\r\n <div class=\"canvas-container\" #previewCanvasContainer *ngIf=\"selectedStoreForPreview\">\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 </div>\r\n\r\n <!-- Right Column: Fixture Preview -->\r\n <div class=\"fixture-preview-panel\" \r\n *ngIf=\"selectedFixtureData && !isRightPanelCollapsed\"\r\n [ngClass]=\"{ 'col-6': originalFixtureData, 'col-3': !originalFixtureData }\"\r\n [style.min-width]=\"originalFixtureData ? '680px' : '340px'\">\r\n <div class=\"s-card\">\r\n <!-- Panel Header -->\r\n <div class=\"fixture-preview-header\">\r\n <div class=\"header-card\">\r\n <div class=\"card-content\">\r\n <!-- <div class=\"product-image-container\">\r\n <img \r\n alt=\"Product\" \r\n class=\"product-image\"\r\n />\r\n </div> -->\r\n <div class=\"name\">{{ getFixtureLabel() }}</div>\r\n <div class=\"specs-container\" *ngIf=\"getFixtureCategory() || getFixtureWidth() || getShelfCount() > 0 || getFixtureCapacity() > 0\">\r\n <span class=\"spec-text\" *ngIf=\"getFixtureCategory()\">{{ getFixtureCategory() }}</span>\r\n <div class=\"dot\" *ngIf=\"getFixtureCategory() && (getFixtureWidth() || getShelfCount() > 0 || getFixtureCapacity() > 0)\"></div>\r\n <span class=\"spec-text\" *ngIf=\"getFixtureWidth()\">{{ getFixtureWidth() }}</span>\r\n <div class=\"dot\" *ngIf=\"getFixtureWidth() && (getShelfCount() > 0 || getFixtureCapacity() > 0)\"></div>\r\n <span class=\"spec-text\" *ngIf=\"getShelfCount() > 0\">{{ getShelfCount() }} {{ getShelfCount() === 1 ? 'Shelf' : 'Shelves' }}</span>\r\n <div class=\"dot\" *ngIf=\"getShelfCount() > 0 && getFixtureCapacity() > 0\"></div>\r\n <span class=\"spec-text\" *ngIf=\"getFixtureCapacity() > 0\">{{ getFixtureCapacity() }} Capacity</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Fixture Component -->\r\n <div class=\"fixture-preview-content\">\r\n <!-- Show Before/After when replace data exists -->\r\n <div *ngIf=\"originalFixtureData\" class=\"before-after-container\">\r\n <div class=\"before-section\">\r\n <div class=\"section-header\">\r\n <h6 class=\"section-label mb-0\">Before</h6>\r\n </div>\r\n <div class=\"fixture-wrapper\">\r\n <lib-store-fixture \r\n [fixture]=\"originalFixtureData\" \r\n [showColors]=\"true\"\r\n [showVMs]=\"true\"\r\n [showBCs]=\"true\">\r\n </lib-store-fixture>\r\n </div>\r\n </div>\r\n <div class=\"after-section\">\r\n <div class=\"section-header\">\r\n <h6 class=\"section-label mb-0\">After</h6>\r\n </div>\r\n <div class=\"fixture-wrapper\">\r\n <lib-store-fixture \r\n [fixture]=\"selectedFixtureData\" \r\n [showColors]=\"true\"\r\n [showVMs]=\"true\"\r\n [showBCs]=\"true\">\r\n </lib-store-fixture>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Show single fixture when no replace data -->\r\n <div *ngIf=\"!originalFixtureData\" class=\"single-fixture-container\">\r\n <div class=\"fixture-wrapper\">\r\n <lib-store-fixture \r\n [fixture]=\"selectedFixtureData\" \r\n [showColors]=\"true\"\r\n [showVMs]=\"true\"\r\n [showBCs]=\"true\">\r\n </lib-store-fixture>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Collapse Button -->\r\n <div class=\"collapse-handler right\" \r\n *ngIf=\"selectedFixtureData\"\r\n (click)=\"toggleRightPanel()\">\r\n <svg *ngIf=\"isRightPanelCollapsed\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\"\r\n viewBox=\"0 0 18 18\" fill=\"none\">\r\n <path d=\"M8.27308 12.636L4.63672 8.99964L8.27308 5.36328M13.364 12.636L9.72763 8.99964L13.364 5.36328\"\r\n stroke=\"#101828\" stroke-width=\"1.45455\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n <svg *ngIf=\"!isRightPanelCollapsed\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\"\r\n viewBox=\"0 0 18 18\" fill=\"none\">\r\n <path d=\"M9.72692 5.36399L13.3633 9.00036L9.72692 12.6367M4.63601 5.36399L8.27237 9.00036L4.63601 12.6367\"\r\n stroke=\"#101828\" stroke-width=\"1.45455\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n <!-- No Preview Section -->\r\n <div class=\"no-preview\" *ngIf=\"hasStores && !selectedStoreForPreview\">\r\n <div >\r\n <svg width=\"315\" height=\"155\" viewBox=\"0 0 315 155\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M103.81 47.0195C89.5463 47.0197 77.9834 58.5824 77.9834 72.8457C77.9834 78.7617 73.9803 85.5059 68.0643 85.5059H45.2588C30.9953 85.5059 19.4316 97.0686 19.4316 111.332C19.4316 125.596 30.9953 137.158 45.2588 137.158H183.357C200.248 137.158 216.32 123.992 233.21 123.992H299.245C304 123.992 307.854 120.137 307.854 115.383C307.853 110.629 303.999 106.774 299.245 106.774H211.625C209.98 106.774 208.588 105.553 208.12 103.976C207.381 101.486 209.082 98.6719 211.679 98.6719H241.909C256.172 98.6717 267.735 87.109 267.735 72.8457C267.735 58.5824 256.172 47.0198 241.909 47.0195H103.81Z\" fill=\"#EAECF0\"/>\r\n <rect width=\"240.694\" height=\"16.9956\" rx=\"8.4978\" transform=\"matrix(-1 0 0 1 246.603 48.8574)\" fill=\"#EAECF0\"/>\r\n <circle cx=\"5.42147\" cy=\"5.42147\" r=\"5.42147\" transform=\"matrix(-1 0 0 1 56.2979 113.281)\" fill=\"#6BCAFF\"/>\r\n <circle cx=\"3.25288\" cy=\"3.25288\" r=\"3.25288\" transform=\"matrix(-1 0 0 1 244.965 68.8262)\" fill=\"#00A3FF\"/>\r\n <circle cx=\"3.25288\" cy=\"3.25288\" r=\"3.25288\" transform=\"matrix(-1 0 0 1 215.689 13.5273)\" fill=\"#00A3FF\"/>\r\n <circle cx=\"2.16859\" cy=\"2.16859\" r=\"2.16859\" transform=\"matrix(-1 0 0 1 104.006 138.221)\" fill=\"#00A3FF\"/>\r\n <rect x=\"68.501\" y=\"44.1523\" width=\"166.999\" height=\"97.9371\" rx=\"15.1015\" fill=\"#6BCAFF\" stroke=\"#00A3FF\" stroke-width=\"3\"/>\r\n <mask id=\"path-8-inside-1_936_150383\" fill=\"white\">\r\n <path d=\"M93.1172 19C94.0625 19 94.9892 19.0828 95.8887 19.2422V116.784C94.9892 116.625 94.0625 116.542 93.1172 116.542H82.7744C74.0642 116.542 67.0031 123.603 67.0029 132.313V34.7715C67.0029 26.0612 74.0641 19 82.7744 19H93.1172Z\"/>\r\n </mask>\r\n <path d=\"M93.1172 19C94.0625 19 94.9892 19.0828 95.8887 19.2422V116.784C94.9892 116.625 94.0625 116.542 93.1172 116.542H82.7744C74.0642 116.542 67.0031 123.603 67.0029 132.313V34.7715C67.0029 26.0612 74.0641 19 82.7744 19H93.1172Z\" fill=\"#6BCAFF\"/>\r\n <path d=\"M93.1172 19L93.1173 16H93.1172V19ZM95.8887 19.2422H98.8887V16.7271L96.4122 16.2882L95.8887 19.2422ZM95.8887 116.784L95.3651 119.738L98.8887 120.363V116.784H95.8887ZM93.1172 116.542L93.1173 113.542H93.1172V116.542ZM67.0029 132.313H64.0029L70.0029 132.314L67.0029 132.313ZM93.1172 19L93.1171 22C93.8872 22 94.6387 22.0674 95.3651 22.1961L95.8887 19.2422L96.4122 16.2882C95.3396 16.0981 94.2377 16 93.1173 16L93.1172 19ZM95.8887 19.2422H92.8887V116.784H95.8887H98.8887V19.2422H95.8887ZM95.8887 116.784L96.4122 113.83C95.3396 113.64 94.2377 113.542 93.1173 113.542L93.1172 116.542L93.1171 119.542C93.8872 119.542 94.6387 119.609 95.3651 119.738L95.8887 116.784ZM93.1172 116.542V113.542H82.7744V116.542V119.542H93.1172V116.542ZM82.7744 116.542V113.542C72.4073 113.542 64.0032 121.947 64.0029 132.313L67.0029 132.313L70.0029 132.314C70.0031 125.26 75.7212 119.542 82.7744 119.542V116.542ZM67.0029 132.313H70.0029V34.7715H67.0029H64.0029V132.313H67.0029ZM67.0029 34.7715H70.0029C70.0029 27.718 75.721 22 82.7744 22V19V16C72.4072 16 64.0029 24.4043 64.0029 34.7715H67.0029ZM82.7744 19V22H93.1172V19V16H82.7744V19Z\" fill=\"#00A3FF\" mask=\"url(#path-8-inside-1_936_150383)\"/>\r\n <line x1=\"76.9619\" y1=\"42.6523\" x2=\"76.9619\" y2=\"84.4881\" stroke=\"#99DAFF\" stroke-width=\"3.98436\" stroke-linecap=\"round\"/>\r\n <circle cx=\"218.206\" cy=\"70.1755\" r=\"3.29663\" fill=\"white\"/>\r\n <circle cx=\"111.787\" cy=\"55.167\" r=\"2.52637\" fill=\"#99DAFF\"/>\r\n <circle cx=\"99.3845\" cy=\"124.986\" r=\"3.44505\" fill=\"white\"/>\r\n <path d=\"M135.529 33.4717C151.285 24.3749 171.432 29.7732 180.529 45.5293C188.56 59.4398 185.291 76.7707 173.573 86.9004L193.457 121.339C194.932 123.894 194.056 127.161 191.501 128.636C188.946 130.111 185.679 129.236 184.204 126.681L164.466 92.4932C149.447 98.6552 131.814 92.92 123.472 78.4717C114.375 62.7156 119.773 42.5685 135.529 33.4717ZM172.698 50.0518C166.099 38.6209 151.482 34.7041 140.051 41.3037C128.62 47.9035 124.703 62.5204 131.303 73.9512C137.902 85.3817 152.519 89.2977 163.95 82.6982C175.381 76.0987 179.297 61.4826 172.698 50.0518Z\" fill=\"white\"/>\r\n <circle cx=\"153.001\" cy=\"57.0017\" r=\"23.8994\" transform=\"rotate(-30 153.001 57.0017)\" fill=\"#99DAFF\"/>\r\n <mask id=\"path-16-inside-2_936_150383\" fill=\"white\">\r\n <path d=\"M153.384 40.9957C153.435 39.7001 152.423 38.5927 151.131 38.7095C148.858 38.9151 146.636 39.5491 144.586 40.5854C141.835 41.976 139.484 44.045 137.755 46.597C136.026 49.149 134.977 52.0996 134.706 55.1701C134.504 57.4583 134.739 59.7568 135.391 61.9447C135.762 63.1872 137.166 63.7169 138.35 63.1891C139.534 62.6612 140.044 61.2746 139.73 60.0165C139.37 58.5735 139.251 57.0753 139.383 55.583C139.584 53.3078 140.361 51.1214 141.642 49.2304C142.924 47.3394 144.666 45.8063 146.704 44.7758C148.041 44.1 149.477 43.6551 150.95 43.4542C152.235 43.2792 153.333 42.2913 153.384 40.9957Z\"/>\r\n </mask>\r\n <path d=\"M153.384 40.9957C153.435 39.7001 152.423 38.5927 151.131 38.7095C148.858 38.9151 146.636 39.5491 144.586 40.5854C141.835 41.976 139.484 44.045 137.755 46.597C136.026 49.149 134.977 52.0996 134.706 55.1701C134.504 57.4583 134.739 59.7568 135.391 61.9447C135.762 63.1872 137.166 63.7169 138.35 63.1891C139.534 62.6612 140.044 61.2746 139.73 60.0165C139.37 58.5735 139.251 57.0753 139.383 55.583C139.584 53.3078 140.361 51.1214 141.642 49.2304C142.924 47.3394 144.666 45.8063 146.704 44.7758C148.041 44.1 149.477 43.6551 150.95 43.4542C152.235 43.2792 153.333 42.2913 153.384 40.9957Z\" stroke=\"white\" stroke-width=\"6\" mask=\"url(#path-16-inside-2_936_150383)\"/>\r\n <path d=\"M136.529 28.4717C152.285 19.3749 172.432 24.7732 181.529 40.5293C189.56 54.4398 186.291 71.7707 174.573 81.9004L194.457 116.339C195.932 118.894 195.056 122.161 192.501 123.636C189.946 125.111 186.679 124.236 185.204 121.681L165.466 87.4932C150.447 93.6552 132.814 87.92 124.472 73.4717C115.375 57.7156 120.773 37.5685 136.529 28.4717ZM173.698 45.0518C167.099 33.6209 152.482 29.7041 141.051 36.3037C129.62 42.9035 125.703 57.5204 132.303 68.9512C138.902 80.3817 153.519 84.2977 164.95 77.6982C176.381 71.0987 180.297 56.4826 173.698 45.0518Z\" fill=\"#00A3FF\"/>\r\n </svg> \r\n </div>\r\n <h3>No preview yet</h3>\r\n <p>Add a find and replacement to preview.</p>\r\n </div>\r\n\r\n <!-- Action Button Section -->\r\n <div class=\"action-button-section\" *ngIf=\"hasStores\">\r\n <button class=\"btn-apply\" type=\"button\" (click)=\"onReviewAndReplace()\" [disabled]=\"loading || findLoading || replaceLoading || batchProcessing\">\r\n {{ batchProcessing ? 'Processing...' : 'Review And Replace' }}\r\n </button>\r\n </div>\r\n </form>\r\n</div>\r\n", styles: [".btn-apply{padding:10px 18px;font-size:16px;font-weight:600;color:#fff;background:#00a3ff;border:1px solid #00a3ff;border-radius:8px;box-shadow:0 1px 2px #1018280d;height:44px;flex-shrink:0;white-space:nowrap;transition:background-color .2s ease,border-color .2s ease;cursor:pointer}.btn-apply:hover{background:#0092e6;border-color:#0092e6}.action-button-section{display:flex;justify-content:flex-end;margin-top:32px;margin-left:34px}.main-card{background:#fff;border-radius:12px;padding:24px;box-shadow:0 1px 3px #0000001a}.section-row{display:flex;gap:8px;margin-bottom:32px}.section-connector{display:flex;gap:8px;margin-bottom:32px;margin-top:-24px}.connector-line{width:24px;flex-shrink:0;display:flex;align-items:flex-start;justify-content:center}.connector-line svg{display:block}.connector-spacer{flex:1}.section-number{width:24px;height:24px;background:#f2f4f7;border-radius:100px;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:600;flex-shrink:0}.section-content{flex:1}.section-title{font-size:14px;font-weight:600;color:#1d2939;margin:0 0 12px}.store-input-wrapper{display:flex;gap:8px;align-items:center}.store-dropdown{width:124px;flex-shrink:0}.store-dropdown select{padding:10px 14px;font-size:16px;font-weight:500;color:#101828;background:#fff;border:1px solid #d0d5dd;border-radius:8px;box-shadow:0 1px 2px #1018280d;width:100%}lib-store-select{flex:1;min-width:0}.tags-input{flex:1;padding:10px 14px;background:#fff;border:1px solid #d0d5dd;border-radius:8px;box-shadow:0 1px 2px #1018280d;display:flex;gap:8px;flex-wrap:wrap;min-height:44px}.tag{background:#f2f4f7;padding:2px 6px 2px 8px;border-radius:16px;display:inline-flex;align-items:center;gap:4px;font-size:12px;font-weight:500;color:#344054}.tag-close{width:12px;height:12px;cursor:pointer;display:flex;align-items:center;justify-content:center}.target-buttons{display:flex;border:1px solid #d0d5dd;border-radius:8px;overflow:hidden;box-shadow:0 1px 2px #1018280d;width:fit-content}.target-btn{padding:10px 16px;font-size:14px;font-weight:500;background:#fff;border:none;border-right:1px solid #d0d5dd;color:#344054;cursor:pointer;transition:background-color .2s;min-width:140px;display:flex;align-items:center;justify-content:center}.target-btn:last-child{border-right:none}.target-btn.active{background:#eaf8ff;color:#1d2939}.target-btn input[type=radio]{display:none}.find-replace-wrapper{margin-left:34px;display:flex;gap:16px;align-items:center}.preview-wrapper{margin-left:34px;margin-top:24px;margin-bottom:32px}.preview-wrapper lib-store-dropdown{width:180px;flex-shrink:0}.preview-wrapper .btn-find,.preview-wrapper .btn-replace{padding:8px 16px;font-size:14px;font-weight:500;border-radius:8px;border:1px solid #d0d5dd;background:#fff;color:#344054;cursor:pointer;transition:all .2s ease}.preview-wrapper .btn-find:hover:not(:disabled),.preview-wrapper .btn-replace:hover:not(:disabled){background:#f9fafb;border-color:#98a2b3}.preview-wrapper .btn-find:disabled,.preview-wrapper .btn-replace:disabled{opacity:.5;cursor:not-allowed}.preview-wrapper .btn-find{border-color:#00a3ff;color:#00a3ff}.preview-wrapper .btn-find:hover:not(:disabled){background:#eaf8ff}.preview-wrapper .btn-replace{border-color:#16a34a;color:#16a34a}.preview-wrapper .btn-replace:hover:not(:disabled){background:#f0fdf4}.preview-wrapper .btn-replace:disabled{background:#f2f4f7!important;border-color:#d0d5dd!important;color:#98a2b3!important;opacity:1;cursor:not-allowed}.preview-wrapper .canvas-container{position:relative;border:1px solid #e5e7eb;border-radius:8px;padding:0;background:#f9fafb;min-height:77vh;width:100%;overflow:hidden;flex:1}.preview-wrapper .canvas-container .canvas-loading{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10}.preview-wrapper .canvas-container canvas{background:#fff;width:100%!important;height:100%!important;display:block}.find-replace-box{flex:1;display:flex;flex-direction:column;gap:4px}.find-replace-label{font-size:14px;font-weight:400;color:#1d2939}.find-replace-input{background:#fff;border:1px solid #d0d5dd;border-radius:8px;padding:10px;min-height:120px;display:flex;flex-direction:column;justify-content:space-between}.find-replace-input:focus,.find-replace-input:focus-within{outline:none;box-shadow:none;border-color:#d0d5dd}.find-replace-input textarea{border:none;outline:none;font-size:14px;color:#1d2939;resize:none;flex:1;font-family:Inter,sans-serif}.find-replace-input textarea:focus{outline:none;box-shadow:none}.find-replace-input textarea::placeholder{color:#98a2b3}.input-btn-container{display:flex;justify-content:flex-end}.btn-find{padding:9px 14px;font-size:11px;font-weight:600;color:#344054;background:#fff;border:1px solid #d0d5dd;border-radius:7px;box-shadow:0 1px 2px #1018280d}.btn-replace{padding:9px 14px;font-size:11px;font-weight:600;color:#fff;background:#00a3ff;border:1px solid #00a3ff;border-radius:7px;box-shadow:0 1px 2px #1018280d;transition:background-color .2s ease,border-color .2s ease,color .2s ease;cursor:pointer}.btn-replace:hover:not(:disabled){background:#0092e6;border-color:#0092e6}.btn-replace:disabled{background:#f2f4f7!important;border-color:#d0d5dd!important;color:#98a2b3!important;opacity:1;cursor:not-allowed;box-shadow:none}.arrow-icon{width:26px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.no-preview{text-align:center;padding:60px 20px}.no-preview h3{font-size:18px;font-weight:600;color:#1d2939;margin-bottom:8px}.no-preview p{font-size:14px;color:#667085;margin:0}@media (max-width: 992px){.header-card{flex-wrap:wrap}.stepper-container{order:2;width:100%;margin-top:16px}.find-replace-wrapper{flex-direction:column;margin-left:0}.arrow-icon{transform:rotate(90deg)}}@media (max-width: 768px){.header-card .d-flex{flex-direction:column;gap:16px}.stepper-line{width:30px}.store-input-wrapper{flex-direction:column}.store-dropdown{width:100%}.target-buttons{flex-direction:column;width:100%}.target-btn{border-right:none;border-bottom:1px solid #d0d5dd;width:100%}.target-btn:last-child{border-bottom:none}.section-row{flex-direction:column}}@media (max-width: 576px){body,.header-card,.main-card{padding:12px}.stepper-text{font-size:12px}}.preview-layout{position:relative;display:flex;align-items:stretch}.preview-layout>.col,.preview-layout>.fixture-preview-panel{display:flex;flex-direction:column}.fixture-preview-panel{background:#fafbfc;height:100%;overflow-y:auto;display:flex;flex-direction:column}.fixture-preview-panel .s-card{background:#fff;border-radius:8px;margin:12px;box-shadow:0 1px 3px #0000001a;min-height:77vh;display:flex;flex-direction:column;flex:1}.fixture-preview-panel .s-card .fixture-preview-header{padding:16px;border-bottom:1px solid #EAECF0}.fixture-preview-panel .s-card .fixture-preview-header .header-card{background:#f9fafb;border-radius:6.536px;padding:9.804px 6.536px;display:flex;flex-direction:column;align-items:center}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content{display:flex;flex-direction:column;gap:6.536px;align-items:center}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content .product-image-container{width:25.651px;height:25.651px;position:relative;overflow:hidden}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content .product-image-container .product-image{position:absolute;width:300.85%;height:160.87%;left:-100.43%;top:-30.43%;max-width:none;object-fit:cover}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content .name{font-family:Inter,sans-serif;font-weight:600;font-size:16px;line-height:19.608px;color:#101828;text-align:center}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content .specs-container{display:flex;gap:4.664px;align-items:center;flex-wrap:wrap;justify-content:center}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content .specs-container .spec-text{font-family:Inter,sans-serif;font-weight:500;font-size:14px;line-height:16.34px;color:#475467}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content .specs-container .dot{width:2.332px;height:2.332px;background:#98a2b3;border-radius:50%;flex-shrink:0}.fixture-preview-panel .s-card .fixture-preview-content{padding:16px;max-height:calc(100vh - 200px);overflow-y:auto}.fixture-preview-panel .s-card .fixture-preview-content .before-after-container{display:flex;flex-direction:row;gap:16px;align-items:flex-start}.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .before-section,.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .after-section{display:flex;flex-direction:column;flex:1;min-width:0;background:#f9fafb;border-radius:8px;padding:12px}.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .before-section .section-header,.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .after-section .section-header{display:flex;align-items:center;justify-content:center;margin-bottom:12px;gap:8px}.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .before-section .section-header .section-label,.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .after-section .section-header .section-label{font-size:14px;font-weight:600;color:#1d2939;letter-spacing:.5px;margin:0}.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .before-section .section-header .brand-name-small,.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .after-section .section-header .brand-name-small{font-size:14px;font-weight:500;color:#475467}.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .before-section .fixture-wrapper,.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .after-section .fixture-wrapper,.fixture-preview-panel .s-card .fixture-preview-content .single-fixture-container .fixture-wrapper{background:#fff;border-radius:4px;padding:8px;box-shadow:0 1px 2px #0000000d}.collapse-handler{position:absolute;right:0;top:50%;transform:translateY(-50%);width:32px;height:64px;background:#fff;border:1px solid #EAECF0;border-left:none;border-radius:0 8px 8px 0;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:10;box-shadow:-2px 0 4px #0000000d}.collapse-handler:hover{background:#f9fafb}.collapse-handler svg{width:18px;height:18px}.collapse-handler.right{right:0}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i8.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i8.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: i8.RadioControlValueAccessor, selector: "input[type=radio][formControlName],input[type=radio][formControl],input[type=radio][ngModel]", inputs: ["name", "formControlName", "value"] }, { kind: "directive", type: i8.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i8.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i8.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i8.NgForm, selector: "form:not([ngNoForm]):not([formGroup]),ng-form,[ngForm]", inputs: ["ngFormOptions"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: ReactiveSelectComponent, selector: "lib-reactive-select", inputs: ["idField", "nameField", "subTextField", "searchField", "label", "data", "action", "search", "prefix", "actionLabel"], outputs: ["actionClick"] }, { kind: "component", type: StoreSelectComponent, selector: "lib-store-select", inputs: ["options", "initialSelected"], outputs: ["selectedChange"] }, { kind: "component", type: StoreDropdownComponent, selector: "lib-store-dropdown", inputs: ["items", "searchField", "multi", "idField", "selectedValues", "disabled", "label"], outputs: ["selected"] }, { kind: "component", type: StoreFixtureComponent, selector: "lib-store-fixture", inputs: ["fixture", "showColors", "showVMs", "showBCs"] }] });
2513
+ }
2514
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: PrepareTemplateComponent, decorators: [{
2515
+ type: Component,
2516
+ args: [{ selector: 'lib-prepare-template', standalone: true, imports: [CommonModule, ReactiveFormsModule, FormsModule, ReactiveSelectComponent, StoreSelectComponent, StoreDropdownComponent, StoreFixtureComponent], providers: [TitleCasePipe], template: "<div class=\"main-card\">\r\n <form>\r\n <!-- Section 1: Add Stores -->\r\n <div class=\"section-row\">\r\n <div class=\"section-number\">1</div>\r\n <div class=\"section-content\">\r\n <h2 class=\"section-title\">Add stores</h2>\r\n <div class=\"store-input-wrapper\">\r\n <div class=\"store-dropdown\">\r\n <lib-reactive-select\r\n [idField]=\"'value'\"\r\n [nameField]=\"'label'\"\r\n [data]=\"searchModes\"\r\n [formControl]=\"selectedMode\" \r\n >\r\n </lib-reactive-select>\r\n </div> \r\n <lib-store-select \r\n [options]=\"storeOptions\"\r\n [initialSelected]=\"selectedStores\"\r\n (selectedChange)=\"onStoresSelected($event)\">\r\n </lib-store-select>\r\n <button class=\"btn-apply\" type=\"button\" (click)=\"onApply()\" [disabled]=\"loading || findLoading || replaceLoading || savingDraft\">\r\n {{ savingDraft ? 'Saving...' : 'Apply' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Section 2: Choose Target -->\r\n <div class=\"section-row\" *ngIf=\"hasStores\">\r\n <div class=\"section-number\">2</div>\r\n <div class=\"section-content\">\r\n <h2 class=\"section-title\">Choose target</h2>\r\n <div class=\"target-buttons\">\r\n <label class=\"target-btn\" [class.active]=\"target.value === 'both'\">\r\n <input type=\"radio\" name=\"target\" value=\"both\" [formControl]=\"target\">\r\n Both\r\n </label>\r\n <label class=\"target-btn\" [class.active]=\"target.value === 'merch'\">\r\n <input type=\"radio\" name=\"target\" value=\"merch\" [formControl]=\"target\">\r\n Merchandise\r\n </label>\r\n <label class=\"target-btn\" [class.active]=\"target.value === 'vm'\">\r\n <input type=\"radio\" name=\"target\" value=\"vm\" [formControl]=\"target\">\r\n Visual Merchandise\r\n </label>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Section 3: Find and Replace -->\r\n <div class=\"section-row\" *ngIf=\"hasStores\">\r\n <div class=\"section-number\">3</div>\r\n <div class=\"section-content\">\r\n <h2 class=\"section-title\">Provide an instruction to find and replace in the selected store</h2>\r\n </div>\r\n </div>\r\n \r\n <!-- Find and Replace Inputs -->\r\n <div class=\"find-replace-wrapper\" *ngIf=\"hasStores\">\r\n <div class=\"find-replace-box\">\r\n <label class=\"find-replace-label\">Target</label>\r\n <div class=\"find-replace-input\">\r\n <textarea \r\n placeholder=\"Instruct what to find it in the selected store\"\r\n [formControl]=\"findPrompt\"></textarea>\r\n <div class=\"input-btn-container\">\r\n <button \r\n class=\"btn-find\" \r\n type=\"button\"\r\n (click)=\"onFind()\"\r\n [disabled]=\"findLoading || replaceLoading || !selectedStoreForPreview\">\r\n {{ findLoading ? 'Processing...' : 'Find' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <div class=\"arrow-icon\">\r\n <svg width=\"27\" height=\"15\" viewBox=\"0 0 27 15\" fill=\"none\">\r\n <path d=\"M26.7071 8.07107C27.0976 7.68054 27.0976 7.04738 26.7071 6.65685L20.3431 0.292893C19.9526 -0.097631 19.3195 -0.097631 18.9289 0.292893C18.5384 0.683418 18.5384 1.31658 18.9289 1.70711L24.5858 7.36396L18.9289 13.0208C18.5384 13.4113 18.5384 14.0445 18.9289 14.435C19.3195 14.8256 19.9526 14.8256 20.3431 14.435L26.7071 8.07107ZM0 7.36396V8.36396H26V7.36396V6.36396H0V7.36396Z\" fill=\"#98A2B3\"/>\r\n </svg>\r\n </div>\r\n \r\n <div class=\"find-replace-box\">\r\n <label class=\"find-replace-label\">Change</label>\r\n <div class=\"find-replace-input\">\r\n <textarea \r\n placeholder=\"Type what would you like to replace in the selected fixture\"\r\n [formControl]=\"replacePrompt\"></textarea>\r\n <div class=\"input-btn-container\">\r\n <button \r\n class=\"btn-replace\" \r\n type=\"button\"\r\n (click)=\"onReplace()\"\r\n [disabled]=\"!findPrompt.value || !replacePrompt.value || findLoading || replaceLoading || !getCurrentStoreFindResponseData()\">\r\n {{ replaceLoading ? 'Processing...' : 'Replace' }}\r\n </button>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Preview Section -->\r\n <div class=\"preview-wrapper\" *ngIf=\"hasStores\">\r\n <div class=\"row g-0 preview-layout\">\r\n <!-- Left Column: Canvas -->\r\n <div class=\"col\" [ngClass]=\"{ \r\n 'col-6': !isRightPanelCollapsed && selectedFixtureData && originalFixtureData,\r\n 'col-9': !isRightPanelCollapsed && selectedFixtureData && !originalFixtureData, \r\n 'col-12': isRightPanelCollapsed || !selectedFixtureData \r\n }\">\r\n <div class=\"d-flex align-items-start gap-3 mb-3\">\r\n <!-- Store Dropdown -->\r\n <lib-store-dropdown \r\n *ngIf=\"hasStores && storeDropdownItems.length > 0\"\r\n [items]=\"storeDropdownItems\"\r\n [idField]=\"'storeId'\"\r\n [searchField]=\"'storeName'\"\r\n [multi]=\"false\"\r\n [selectedValues]=\"selectedStoreValues\"\r\n (selected)=\"onStoreSelectedForPreview($event)\">\r\n </lib-store-dropdown>\r\n \r\n <!-- Content Area -->\r\n <div class=\"flex-grow-1\">\r\n <!-- Preview Title -->\r\n <p class=\"fw-semibold mb-1\" style=\"font-size: 14px; color: #1d2939;\">\r\n Preview \r\n <span *ngIf=\"getStoreCount() > 0\" style=\"font-weight: 400; color: #667085;\">\r\n ({{ getStoreCount() }} {{ getStoreCount() === 1 ? 'Store' : 'Stores' }})\r\n </span>\r\n </p>\r\n \r\n <!-- Description -->\r\n <p class=\"mb-0\" style=\"font-size: 14px; color: #475467;\">Check if the prompt fit into the expected results in order to proceed to review and approve</p>\r\n </div>\r\n </div>\r\n\r\n <!-- Canvas Container -->\r\n <div class=\"canvas-container\" #previewCanvasContainer *ngIf=\"selectedStoreForPreview\">\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 </div>\r\n\r\n <!-- Right Column: Fixture Preview -->\r\n <div class=\"fixture-preview-panel\" \r\n *ngIf=\"selectedFixtureData && !isRightPanelCollapsed\"\r\n [ngClass]=\"{ 'col-6': originalFixtureData, 'col-3': !originalFixtureData }\"\r\n [style.min-width]=\"originalFixtureData ? '680px' : '340px'\">\r\n <div class=\"s-card\">\r\n <!-- Panel Header -->\r\n <div class=\"fixture-preview-header\">\r\n <div class=\"header-card\">\r\n <div class=\"card-content\">\r\n <!-- <div class=\"product-image-container\">\r\n <img \r\n alt=\"Product\" \r\n class=\"product-image\"\r\n />\r\n </div> -->\r\n <div class=\"name\">{{ getFixtureLabel() }}</div>\r\n <div class=\"specs-container\" *ngIf=\"getFixtureCategory() || getFixtureWidth() || getShelfCount() > 0 || getFixtureCapacity() > 0\">\r\n <span class=\"spec-text\" *ngIf=\"getFixtureCategory()\">{{ getFixtureCategory() }}</span>\r\n <div class=\"dot\" *ngIf=\"getFixtureCategory() && (getFixtureWidth() || getShelfCount() > 0 || getFixtureCapacity() > 0)\"></div>\r\n <span class=\"spec-text\" *ngIf=\"getFixtureWidth()\">{{ getFixtureWidth() }}</span>\r\n <div class=\"dot\" *ngIf=\"getFixtureWidth() && (getShelfCount() > 0 || getFixtureCapacity() > 0)\"></div>\r\n <span class=\"spec-text\" *ngIf=\"getShelfCount() > 0\">{{ getShelfCount() }} {{ getShelfCount() === 1 ? 'Shelf' : 'Shelves' }}</span>\r\n <div class=\"dot\" *ngIf=\"getShelfCount() > 0 && getFixtureCapacity() > 0\"></div>\r\n <span class=\"spec-text\" *ngIf=\"getFixtureCapacity() > 0\">{{ getFixtureCapacity() }} Capacity</span>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Fixture Component -->\r\n <div class=\"fixture-preview-content\">\r\n <!-- Show Before/After when replace data exists -->\r\n <div *ngIf=\"originalFixtureData\" class=\"before-after-container\">\r\n <div class=\"before-section\">\r\n <div class=\"section-header\">\r\n <h6 class=\"section-label mb-0\">Before</h6>\r\n </div>\r\n <div class=\"fixture-wrapper\">\r\n <lib-store-fixture \r\n [fixture]=\"originalFixtureData\" \r\n [showColors]=\"true\"\r\n [showVMs]=\"true\"\r\n [showBCs]=\"true\">\r\n </lib-store-fixture>\r\n </div>\r\n </div>\r\n <div class=\"after-section\">\r\n <div class=\"section-header\">\r\n <h6 class=\"section-label mb-0\">After</h6>\r\n </div>\r\n <div class=\"fixture-wrapper\">\r\n <lib-store-fixture \r\n [fixture]=\"selectedFixtureData\" \r\n [showColors]=\"true\"\r\n [showVMs]=\"true\"\r\n [showBCs]=\"true\">\r\n </lib-store-fixture>\r\n </div>\r\n </div>\r\n </div>\r\n \r\n <!-- Show single fixture when no replace data -->\r\n <div *ngIf=\"!originalFixtureData\" class=\"single-fixture-container\">\r\n <div class=\"fixture-wrapper\">\r\n <lib-store-fixture \r\n [fixture]=\"selectedFixtureData\" \r\n [showColors]=\"true\"\r\n [showVMs]=\"true\"\r\n [showBCs]=\"true\">\r\n </lib-store-fixture>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n </div>\r\n\r\n <!-- Collapse Button -->\r\n <div class=\"collapse-handler right\" \r\n *ngIf=\"selectedFixtureData\"\r\n (click)=\"toggleRightPanel()\">\r\n <svg *ngIf=\"isRightPanelCollapsed\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\"\r\n viewBox=\"0 0 18 18\" fill=\"none\">\r\n <path d=\"M8.27308 12.636L4.63672 8.99964L8.27308 5.36328M13.364 12.636L9.72763 8.99964L13.364 5.36328\"\r\n stroke=\"#101828\" stroke-width=\"1.45455\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n <svg *ngIf=\"!isRightPanelCollapsed\" xmlns=\"http://www.w3.org/2000/svg\" width=\"18\" height=\"18\"\r\n viewBox=\"0 0 18 18\" fill=\"none\">\r\n <path d=\"M9.72692 5.36399L13.3633 9.00036L9.72692 12.6367M4.63601 5.36399L8.27237 9.00036L4.63601 12.6367\"\r\n stroke=\"#101828\" stroke-width=\"1.45455\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\r\n </svg>\r\n </div>\r\n </div>\r\n </div>\r\n <!-- No Preview Section -->\r\n <div class=\"no-preview\" *ngIf=\"hasStores && !selectedStoreForPreview\">\r\n <div >\r\n <svg width=\"315\" height=\"155\" viewBox=\"0 0 315 155\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\r\n <path d=\"M103.81 47.0195C89.5463 47.0197 77.9834 58.5824 77.9834 72.8457C77.9834 78.7617 73.9803 85.5059 68.0643 85.5059H45.2588C30.9953 85.5059 19.4316 97.0686 19.4316 111.332C19.4316 125.596 30.9953 137.158 45.2588 137.158H183.357C200.248 137.158 216.32 123.992 233.21 123.992H299.245C304 123.992 307.854 120.137 307.854 115.383C307.853 110.629 303.999 106.774 299.245 106.774H211.625C209.98 106.774 208.588 105.553 208.12 103.976C207.381 101.486 209.082 98.6719 211.679 98.6719H241.909C256.172 98.6717 267.735 87.109 267.735 72.8457C267.735 58.5824 256.172 47.0198 241.909 47.0195H103.81Z\" fill=\"#EAECF0\"/>\r\n <rect width=\"240.694\" height=\"16.9956\" rx=\"8.4978\" transform=\"matrix(-1 0 0 1 246.603 48.8574)\" fill=\"#EAECF0\"/>\r\n <circle cx=\"5.42147\" cy=\"5.42147\" r=\"5.42147\" transform=\"matrix(-1 0 0 1 56.2979 113.281)\" fill=\"#6BCAFF\"/>\r\n <circle cx=\"3.25288\" cy=\"3.25288\" r=\"3.25288\" transform=\"matrix(-1 0 0 1 244.965 68.8262)\" fill=\"#00A3FF\"/>\r\n <circle cx=\"3.25288\" cy=\"3.25288\" r=\"3.25288\" transform=\"matrix(-1 0 0 1 215.689 13.5273)\" fill=\"#00A3FF\"/>\r\n <circle cx=\"2.16859\" cy=\"2.16859\" r=\"2.16859\" transform=\"matrix(-1 0 0 1 104.006 138.221)\" fill=\"#00A3FF\"/>\r\n <rect x=\"68.501\" y=\"44.1523\" width=\"166.999\" height=\"97.9371\" rx=\"15.1015\" fill=\"#6BCAFF\" stroke=\"#00A3FF\" stroke-width=\"3\"/>\r\n <mask id=\"path-8-inside-1_936_150383\" fill=\"white\">\r\n <path d=\"M93.1172 19C94.0625 19 94.9892 19.0828 95.8887 19.2422V116.784C94.9892 116.625 94.0625 116.542 93.1172 116.542H82.7744C74.0642 116.542 67.0031 123.603 67.0029 132.313V34.7715C67.0029 26.0612 74.0641 19 82.7744 19H93.1172Z\"/>\r\n </mask>\r\n <path d=\"M93.1172 19C94.0625 19 94.9892 19.0828 95.8887 19.2422V116.784C94.9892 116.625 94.0625 116.542 93.1172 116.542H82.7744C74.0642 116.542 67.0031 123.603 67.0029 132.313V34.7715C67.0029 26.0612 74.0641 19 82.7744 19H93.1172Z\" fill=\"#6BCAFF\"/>\r\n <path d=\"M93.1172 19L93.1173 16H93.1172V19ZM95.8887 19.2422H98.8887V16.7271L96.4122 16.2882L95.8887 19.2422ZM95.8887 116.784L95.3651 119.738L98.8887 120.363V116.784H95.8887ZM93.1172 116.542L93.1173 113.542H93.1172V116.542ZM67.0029 132.313H64.0029L70.0029 132.314L67.0029 132.313ZM93.1172 19L93.1171 22C93.8872 22 94.6387 22.0674 95.3651 22.1961L95.8887 19.2422L96.4122 16.2882C95.3396 16.0981 94.2377 16 93.1173 16L93.1172 19ZM95.8887 19.2422H92.8887V116.784H95.8887H98.8887V19.2422H95.8887ZM95.8887 116.784L96.4122 113.83C95.3396 113.64 94.2377 113.542 93.1173 113.542L93.1172 116.542L93.1171 119.542C93.8872 119.542 94.6387 119.609 95.3651 119.738L95.8887 116.784ZM93.1172 116.542V113.542H82.7744V116.542V119.542H93.1172V116.542ZM82.7744 116.542V113.542C72.4073 113.542 64.0032 121.947 64.0029 132.313L67.0029 132.313L70.0029 132.314C70.0031 125.26 75.7212 119.542 82.7744 119.542V116.542ZM67.0029 132.313H70.0029V34.7715H67.0029H64.0029V132.313H67.0029ZM67.0029 34.7715H70.0029C70.0029 27.718 75.721 22 82.7744 22V19V16C72.4072 16 64.0029 24.4043 64.0029 34.7715H67.0029ZM82.7744 19V22H93.1172V19V16H82.7744V19Z\" fill=\"#00A3FF\" mask=\"url(#path-8-inside-1_936_150383)\"/>\r\n <line x1=\"76.9619\" y1=\"42.6523\" x2=\"76.9619\" y2=\"84.4881\" stroke=\"#99DAFF\" stroke-width=\"3.98436\" stroke-linecap=\"round\"/>\r\n <circle cx=\"218.206\" cy=\"70.1755\" r=\"3.29663\" fill=\"white\"/>\r\n <circle cx=\"111.787\" cy=\"55.167\" r=\"2.52637\" fill=\"#99DAFF\"/>\r\n <circle cx=\"99.3845\" cy=\"124.986\" r=\"3.44505\" fill=\"white\"/>\r\n <path d=\"M135.529 33.4717C151.285 24.3749 171.432 29.7732 180.529 45.5293C188.56 59.4398 185.291 76.7707 173.573 86.9004L193.457 121.339C194.932 123.894 194.056 127.161 191.501 128.636C188.946 130.111 185.679 129.236 184.204 126.681L164.466 92.4932C149.447 98.6552 131.814 92.92 123.472 78.4717C114.375 62.7156 119.773 42.5685 135.529 33.4717ZM172.698 50.0518C166.099 38.6209 151.482 34.7041 140.051 41.3037C128.62 47.9035 124.703 62.5204 131.303 73.9512C137.902 85.3817 152.519 89.2977 163.95 82.6982C175.381 76.0987 179.297 61.4826 172.698 50.0518Z\" fill=\"white\"/>\r\n <circle cx=\"153.001\" cy=\"57.0017\" r=\"23.8994\" transform=\"rotate(-30 153.001 57.0017)\" fill=\"#99DAFF\"/>\r\n <mask id=\"path-16-inside-2_936_150383\" fill=\"white\">\r\n <path d=\"M153.384 40.9957C153.435 39.7001 152.423 38.5927 151.131 38.7095C148.858 38.9151 146.636 39.5491 144.586 40.5854C141.835 41.976 139.484 44.045 137.755 46.597C136.026 49.149 134.977 52.0996 134.706 55.1701C134.504 57.4583 134.739 59.7568 135.391 61.9447C135.762 63.1872 137.166 63.7169 138.35 63.1891C139.534 62.6612 140.044 61.2746 139.73 60.0165C139.37 58.5735 139.251 57.0753 139.383 55.583C139.584 53.3078 140.361 51.1214 141.642 49.2304C142.924 47.3394 144.666 45.8063 146.704 44.7758C148.041 44.1 149.477 43.6551 150.95 43.4542C152.235 43.2792 153.333 42.2913 153.384 40.9957Z\"/>\r\n </mask>\r\n <path d=\"M153.384 40.9957C153.435 39.7001 152.423 38.5927 151.131 38.7095C148.858 38.9151 146.636 39.5491 144.586 40.5854C141.835 41.976 139.484 44.045 137.755 46.597C136.026 49.149 134.977 52.0996 134.706 55.1701C134.504 57.4583 134.739 59.7568 135.391 61.9447C135.762 63.1872 137.166 63.7169 138.35 63.1891C139.534 62.6612 140.044 61.2746 139.73 60.0165C139.37 58.5735 139.251 57.0753 139.383 55.583C139.584 53.3078 140.361 51.1214 141.642 49.2304C142.924 47.3394 144.666 45.8063 146.704 44.7758C148.041 44.1 149.477 43.6551 150.95 43.4542C152.235 43.2792 153.333 42.2913 153.384 40.9957Z\" stroke=\"white\" stroke-width=\"6\" mask=\"url(#path-16-inside-2_936_150383)\"/>\r\n <path d=\"M136.529 28.4717C152.285 19.3749 172.432 24.7732 181.529 40.5293C189.56 54.4398 186.291 71.7707 174.573 81.9004L194.457 116.339C195.932 118.894 195.056 122.161 192.501 123.636C189.946 125.111 186.679 124.236 185.204 121.681L165.466 87.4932C150.447 93.6552 132.814 87.92 124.472 73.4717C115.375 57.7156 120.773 37.5685 136.529 28.4717ZM173.698 45.0518C167.099 33.6209 152.482 29.7041 141.051 36.3037C129.62 42.9035 125.703 57.5204 132.303 68.9512C138.902 80.3817 153.519 84.2977 164.95 77.6982C176.381 71.0987 180.297 56.4826 173.698 45.0518Z\" fill=\"#00A3FF\"/>\r\n </svg> \r\n </div>\r\n <h3>No preview yet</h3>\r\n <p>Add a find and replacement to preview.</p>\r\n </div>\r\n\r\n <!-- Action Button Section -->\r\n <div class=\"action-button-section\" *ngIf=\"hasStores\">\r\n <button class=\"btn-apply\" type=\"button\" (click)=\"onReviewAndReplace()\" [disabled]=\"loading || findLoading || replaceLoading || batchProcessing\">\r\n {{ batchProcessing ? 'Processing...' : 'Review And Replace' }}\r\n </button>\r\n </div>\r\n </form>\r\n</div>\r\n", styles: [".btn-apply{padding:10px 18px;font-size:16px;font-weight:600;color:#fff;background:#00a3ff;border:1px solid #00a3ff;border-radius:8px;box-shadow:0 1px 2px #1018280d;height:44px;flex-shrink:0;white-space:nowrap;transition:background-color .2s ease,border-color .2s ease;cursor:pointer}.btn-apply:hover{background:#0092e6;border-color:#0092e6}.action-button-section{display:flex;justify-content:flex-end;margin-top:32px;margin-left:34px}.main-card{background:#fff;border-radius:12px;padding:24px;box-shadow:0 1px 3px #0000001a}.section-row{display:flex;gap:8px;margin-bottom:32px}.section-connector{display:flex;gap:8px;margin-bottom:32px;margin-top:-24px}.connector-line{width:24px;flex-shrink:0;display:flex;align-items:flex-start;justify-content:center}.connector-line svg{display:block}.connector-spacer{flex:1}.section-number{width:24px;height:24px;background:#f2f4f7;border-radius:100px;display:flex;align-items:center;justify-content:center;font-size:14px;font-weight:600;flex-shrink:0}.section-content{flex:1}.section-title{font-size:14px;font-weight:600;color:#1d2939;margin:0 0 12px}.store-input-wrapper{display:flex;gap:8px;align-items:center}.store-dropdown{width:124px;flex-shrink:0}.store-dropdown select{padding:10px 14px;font-size:16px;font-weight:500;color:#101828;background:#fff;border:1px solid #d0d5dd;border-radius:8px;box-shadow:0 1px 2px #1018280d;width:100%}lib-store-select{flex:1;min-width:0}.tags-input{flex:1;padding:10px 14px;background:#fff;border:1px solid #d0d5dd;border-radius:8px;box-shadow:0 1px 2px #1018280d;display:flex;gap:8px;flex-wrap:wrap;min-height:44px}.tag{background:#f2f4f7;padding:2px 6px 2px 8px;border-radius:16px;display:inline-flex;align-items:center;gap:4px;font-size:12px;font-weight:500;color:#344054}.tag-close{width:12px;height:12px;cursor:pointer;display:flex;align-items:center;justify-content:center}.target-buttons{display:flex;border:1px solid #d0d5dd;border-radius:8px;overflow:hidden;box-shadow:0 1px 2px #1018280d;width:fit-content}.target-btn{padding:10px 16px;font-size:14px;font-weight:500;background:#fff;border:none;border-right:1px solid #d0d5dd;color:#344054;cursor:pointer;transition:background-color .2s;min-width:140px;display:flex;align-items:center;justify-content:center}.target-btn:last-child{border-right:none}.target-btn.active{background:#eaf8ff;color:#1d2939}.target-btn input[type=radio]{display:none}.find-replace-wrapper{margin-left:34px;display:flex;gap:16px;align-items:center}.preview-wrapper{margin-left:34px;margin-top:24px;margin-bottom:32px}.preview-wrapper lib-store-dropdown{width:180px;flex-shrink:0}.preview-wrapper .btn-find,.preview-wrapper .btn-replace{padding:8px 16px;font-size:14px;font-weight:500;border-radius:8px;border:1px solid #d0d5dd;background:#fff;color:#344054;cursor:pointer;transition:all .2s ease}.preview-wrapper .btn-find:hover:not(:disabled),.preview-wrapper .btn-replace:hover:not(:disabled){background:#f9fafb;border-color:#98a2b3}.preview-wrapper .btn-find:disabled,.preview-wrapper .btn-replace:disabled{opacity:.5;cursor:not-allowed}.preview-wrapper .btn-find{border-color:#00a3ff;color:#00a3ff}.preview-wrapper .btn-find:hover:not(:disabled){background:#eaf8ff}.preview-wrapper .btn-replace{border-color:#16a34a;color:#16a34a}.preview-wrapper .btn-replace:hover:not(:disabled){background:#f0fdf4}.preview-wrapper .btn-replace:disabled{background:#f2f4f7!important;border-color:#d0d5dd!important;color:#98a2b3!important;opacity:1;cursor:not-allowed}.preview-wrapper .canvas-container{position:relative;border:1px solid #e5e7eb;border-radius:8px;padding:0;background:#f9fafb;min-height:77vh;width:100%;overflow:hidden;flex:1}.preview-wrapper .canvas-container .canvas-loading{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);z-index:10}.preview-wrapper .canvas-container canvas{background:#fff;width:100%!important;height:100%!important;display:block}.find-replace-box{flex:1;display:flex;flex-direction:column;gap:4px}.find-replace-label{font-size:14px;font-weight:400;color:#1d2939}.find-replace-input{background:#fff;border:1px solid #d0d5dd;border-radius:8px;padding:10px;min-height:120px;display:flex;flex-direction:column;justify-content:space-between}.find-replace-input:focus,.find-replace-input:focus-within{outline:none;box-shadow:none;border-color:#d0d5dd}.find-replace-input textarea{border:none;outline:none;font-size:14px;color:#1d2939;resize:none;flex:1;font-family:Inter,sans-serif}.find-replace-input textarea:focus{outline:none;box-shadow:none}.find-replace-input textarea::placeholder{color:#98a2b3}.input-btn-container{display:flex;justify-content:flex-end}.btn-find{padding:9px 14px;font-size:11px;font-weight:600;color:#344054;background:#fff;border:1px solid #d0d5dd;border-radius:7px;box-shadow:0 1px 2px #1018280d}.btn-replace{padding:9px 14px;font-size:11px;font-weight:600;color:#fff;background:#00a3ff;border:1px solid #00a3ff;border-radius:7px;box-shadow:0 1px 2px #1018280d;transition:background-color .2s ease,border-color .2s ease,color .2s ease;cursor:pointer}.btn-replace:hover:not(:disabled){background:#0092e6;border-color:#0092e6}.btn-replace:disabled{background:#f2f4f7!important;border-color:#d0d5dd!important;color:#98a2b3!important;opacity:1;cursor:not-allowed;box-shadow:none}.arrow-icon{width:26px;flex-shrink:0;display:flex;align-items:center;justify-content:center}.no-preview{text-align:center;padding:60px 20px}.no-preview h3{font-size:18px;font-weight:600;color:#1d2939;margin-bottom:8px}.no-preview p{font-size:14px;color:#667085;margin:0}@media (max-width: 992px){.header-card{flex-wrap:wrap}.stepper-container{order:2;width:100%;margin-top:16px}.find-replace-wrapper{flex-direction:column;margin-left:0}.arrow-icon{transform:rotate(90deg)}}@media (max-width: 768px){.header-card .d-flex{flex-direction:column;gap:16px}.stepper-line{width:30px}.store-input-wrapper{flex-direction:column}.store-dropdown{width:100%}.target-buttons{flex-direction:column;width:100%}.target-btn{border-right:none;border-bottom:1px solid #d0d5dd;width:100%}.target-btn:last-child{border-bottom:none}.section-row{flex-direction:column}}@media (max-width: 576px){body,.header-card,.main-card{padding:12px}.stepper-text{font-size:12px}}.preview-layout{position:relative;display:flex;align-items:stretch}.preview-layout>.col,.preview-layout>.fixture-preview-panel{display:flex;flex-direction:column}.fixture-preview-panel{background:#fafbfc;height:100%;overflow-y:auto;display:flex;flex-direction:column}.fixture-preview-panel .s-card{background:#fff;border-radius:8px;margin:12px;box-shadow:0 1px 3px #0000001a;min-height:77vh;display:flex;flex-direction:column;flex:1}.fixture-preview-panel .s-card .fixture-preview-header{padding:16px;border-bottom:1px solid #EAECF0}.fixture-preview-panel .s-card .fixture-preview-header .header-card{background:#f9fafb;border-radius:6.536px;padding:9.804px 6.536px;display:flex;flex-direction:column;align-items:center}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content{display:flex;flex-direction:column;gap:6.536px;align-items:center}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content .product-image-container{width:25.651px;height:25.651px;position:relative;overflow:hidden}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content .product-image-container .product-image{position:absolute;width:300.85%;height:160.87%;left:-100.43%;top:-30.43%;max-width:none;object-fit:cover}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content .name{font-family:Inter,sans-serif;font-weight:600;font-size:16px;line-height:19.608px;color:#101828;text-align:center}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content .specs-container{display:flex;gap:4.664px;align-items:center;flex-wrap:wrap;justify-content:center}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content .specs-container .spec-text{font-family:Inter,sans-serif;font-weight:500;font-size:14px;line-height:16.34px;color:#475467}.fixture-preview-panel .s-card .fixture-preview-header .header-card .card-content .specs-container .dot{width:2.332px;height:2.332px;background:#98a2b3;border-radius:50%;flex-shrink:0}.fixture-preview-panel .s-card .fixture-preview-content{padding:16px;max-height:calc(100vh - 200px);overflow-y:auto}.fixture-preview-panel .s-card .fixture-preview-content .before-after-container{display:flex;flex-direction:row;gap:16px;align-items:flex-start}.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .before-section,.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .after-section{display:flex;flex-direction:column;flex:1;min-width:0;background:#f9fafb;border-radius:8px;padding:12px}.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .before-section .section-header,.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .after-section .section-header{display:flex;align-items:center;justify-content:center;margin-bottom:12px;gap:8px}.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .before-section .section-header .section-label,.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .after-section .section-header .section-label{font-size:14px;font-weight:600;color:#1d2939;letter-spacing:.5px;margin:0}.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .before-section .section-header .brand-name-small,.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .after-section .section-header .brand-name-small{font-size:14px;font-weight:500;color:#475467}.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .before-section .fixture-wrapper,.fixture-preview-panel .s-card .fixture-preview-content .before-after-container .after-section .fixture-wrapper,.fixture-preview-panel .s-card .fixture-preview-content .single-fixture-container .fixture-wrapper{background:#fff;border-radius:4px;padding:8px;box-shadow:0 1px 2px #0000000d}.collapse-handler{position:absolute;right:0;top:50%;transform:translateY(-50%);width:32px;height:64px;background:#fff;border:1px solid #EAECF0;border-left:none;border-radius:0 8px 8px 0;display:flex;align-items:center;justify-content:center;cursor:pointer;z-index:10;box-shadow:-2px 0 4px #0000000d}.collapse-handler:hover{background:#f9fafb}.collapse-handler svg{width:18px;height:18px}.collapse-handler.right{right:0}\n"] }]
2517
+ }], ctorParameters: () => [{ type: i1.StoreBuilderService }, { type: i2.CollectionUpdateAiDataService }, { type: i3.TitleCasePipe }, { type: i0.ChangeDetectorRef }, { type: i4.GlobalStateService }, { type: i5.Router }, { type: i5.ActivatedRoute }, { type: i6.ToastService }, { type: i7.NgbModal }], propDecorators: { previewCanvasRef: [{
2518
+ type: ViewChild,
2519
+ args: ['previewCanvas']
2520
+ }], previewCanvasContainerRef: [{
2521
+ type: ViewChild,
2522
+ args: ['previewCanvasContainer']
2523
+ }] } });
2524
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJlcGFyZS10ZW1wbGF0ZS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90YW5nby1zdG9yZS1idWlsZGVyL3NyYy9saWIvY29tcG9uZW50cy9jb2xsZWN0aW9uLXVwZGF0ZS1haS9maW5kLXJlcGxhY2UtbGF5b3V0L3ByZXBhcmUtdGVtcGxhdGUvcHJlcGFyZS10ZW1wbGF0ZS5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy90YW5nby1zdG9yZS1idWlsZGVyL3NyYy9saWIvY29tcG9uZW50cy9jb2xsZWN0aW9uLXVwZGF0ZS1haS9maW5kLXJlcGxhY2UtbGF5b3V0L3ByZXBhcmUtdGVtcGxhdGUvcHJlcGFyZS10ZW1wbGF0ZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFvQyxTQUFTLEVBQWlDLE1BQU0sZUFBZSxDQUFDO0FBQ3RILE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUNsRSxPQUFPLEVBQUUsWUFBWSxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBRTlELE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxNQUFNLG9EQUFvRCxDQUFDO0FBQzdGLE9BQU8sRUFBRSxvQkFBb0IsRUFBZSxNQUFNLHNEQUFzRCxDQUFDO0FBQ3pHLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDBEQUEwRCxDQUFDO0FBQ2xHLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUk3QyxPQUFPLEVBQUUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUMxQyxPQUFPLEtBQUssTUFBTSxNQUFNLFFBQVEsQ0FBQztBQUNqQyxPQUFPLEVBQUUscUJBQXFCLEVBQUUsTUFBTSx3REFBd0QsQ0FBQztB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Q0FBQyxHQUFHLEVBQUU7WUFDZCxJQUFJLElBQUksQ0FBQyxhQUFhLElBQUksSUFBSSxDQUFDLHlCQUF5QixFQUFFLGFBQWEsRUFBRTtnQkFDdkUsSUFBSSxDQUFDLFlBQVksQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxDQUFDO2dCQUN0RSxJQUFJLENBQUMseUJBQXlCLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDO2FBQ3BEO1FBQ0gsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ1YsQ0FBQztJQUVELFdBQVc7UUFDVCxJQUFJLElBQUksQ0FBQyxhQUFhLEVBQUU7WUFDdEIsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztTQUM5QjtRQUNELElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUMzQixDQUFDO3dHQTMzRlUsd0JBQXdCOzRGQUF4Qix3QkFBd0IsbUVBSHhCLENBQUMsYUFBYSxDQUFDLG1RQzFCNUIsaWlzQkE4UkEsKzJVRHZRWSxZQUFZLGdPQUFFLG1CQUFtQixpaUNBQUUsV0FBVyxtTkFBRSx1QkFBdUIseU5BQUUsb0JBQW9CLGtJQUFFLHNCQUFzQixtTEFBRSxxQkFBcUI7OzRGQU0zSSx3QkFBd0I7a0JBVHBDLFNBQVM7K0JBQ0Usc0JBQXNCLGNBQ3BCLElBQUksV0FDUCxDQUFDLFlBQVksRUFBRSxtQkFBbUIsRUFBRSxXQUFXLEVBQUUsdUJBQXVCLEVBQUUsb0JBQW9CLEVBQUUsc0JBQXNCLEVBQUUscUJBQXFCLENBQUMsYUFHNUksQ0FBQyxhQUFhLENBQUM7cVVBNEJFLGdCQUFnQjtzQkFBM0MsU0FBUzt1QkFBQyxlQUFlO2dCQUNXLHlCQUF5QjtzQkFBN0QsU0FBUzt1QkFBQyx3QkFBd0IiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIE9uSW5pdCwgT25EZXN0cm95LCBBZnRlclZpZXdJbml0LCBWaWV3Q2hpbGQsIEVsZW1lbnRSZWYsIENoYW5nZURldGVjdG9yUmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XHJcbmltcG9ydCB7IFJlYWN0aXZlRm9ybXNNb2R1bGUsIEZvcm1zTW9kdWxlIH0gZnJvbSAnQGFuZ3VsYXIvZm9ybXMnO1xyXG5pbXBvcnQgeyBDb21tb25Nb2R1bGUsIFRpdGxlQ2FzZVBpcGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5pbXBvcnQgeyBSb3V0ZXIsIEFjdGl2YXRlZFJvdXRlIH0gZnJvbSAnQGFuZ3VsYXIvcm91dGVyJztcclxuaW1wb3J0IHsgUmVhY3RpdmVTZWxlY3RDb21wb25lbnQgfSBmcm9tICcuLi8uLi8uLi9yZWFjdGl2ZS1zZWxlY3QvcmVhY3RpdmUtc2VsZWN0LmNvbXBvbmVudCc7XHJcbmltcG9ydCB7IFN0b3JlU2VsZWN0Q29tcG9uZW50LCBTdG9yZU9wdGlvbiB9IGZyb20gJy4uLy4uL2NvbXBvbmVudHMvc3RvcmUtc2VsZWN0L3N0b3JlLXNlbGVjdC5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBTdG9yZURyb3Bkb3duQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vY29tcG9uZW50cy9zdG9yZS1kcm9wZG93bi9zdG9yZS1kcm9wZG93bi5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBGb3JtQ29udHJvbCB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcclxuaW1wb3J0IHsgU3RvcmVCdWlsZGVyU2VydmljZSB9IGZyb20gJy4uLy4uLy4uLy4uL3NlcnZpY2VzL3N0b3JlLWJ1aWxkZXIuc2VydmljZSc7XHJcbmltcG9ydCB7IENvbGxlY3Rpb25VcGRhdGVBaURhdGFTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vc2VydmljZXMvZGF0YS5zZXJ2aWNlJztcclxuaW1wb3J0IHsgU3RvcmUsIEZpbmRSZXBsYWNlIH0gZnJvbSAnLi4vLi4vbW9kZWxzL2ZpbmQtcmVwbGFjZS5tb2RlbCc7XHJcbmltcG9ydCB7IFN1YmplY3QsIHRha2VVbnRpbCB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgKiBhcyBmYWJyaWMgZnJvbSBcImZhYnJpY1wiO1xyXG5pbXBvcnQgeyBTdG9yZUZpeHR1cmVDb21wb25lbnQgfSBmcm9tICcuLi8uLi9jb21wb25lbnRzL3N0b3JlLWZpeHR1cmUvc3RvcmUtZml4dHVyZS5jb21wb25lbnQnO1xyXG5pbXBvcnQgeyBWbUxpYnJhcnlMaXN0IH0gZnJvbSAnLi4vLi4vLi4vLi4vaW50ZXJmYWNlcy92bS1saWJyYXJ5LmludGVyZmFjZSc7XHJcbmltcG9ydCB7IEdsb2JhbFN0YXRlU2VydmljZSB9IGZyb20gJ3RhbmdvLWFwcC11aS1nbG9iYWwnO1xyXG5pbXBvcnQgeyBUb2FzdFNlcnZpY2UgfSBmcm9tICd0YW5nby1hcHAtdWktc2hhcmVkJztcclxuaW1wb3J0IHsgTmdiTW9kYWwgfSBmcm9tICdAbmctYm9vdHN0cmFwL25nLWJvb3RzdHJhcCc7XHJcbmltcG9ydCB7IEJhdGNoQ29uZmlybWF0aW9uTW9kYWxDb21wb25lbnQgfSBmcm9tICcuL2JhdGNoLWNvbmZpcm1hdGlvbi1tb2RhbC9iYXRjaC1jb25maXJtYXRpb24tbW9kYWwuY29tcG9uZW50JztcclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnbGliLXByZXBhcmUtdGVtcGxhdGUnLFxyXG4gIHN0YW5kYWxvbmU6IHRydWUsXHJcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgUmVhY3RpdmVGb3Jtc01vZHVsZSwgRm9ybXNNb2R1bGUsIFJlYWN0aXZlU2VsZWN0Q29tcG9uZW50LCBTdG9yZVNlbGVjdENvbXBvbmVudCwgU3RvcmVEcm9wZG93bkNvbXBvbmVudCwgU3RvcmVGaXh0dXJlQ29tcG9uZW50XSxcclxuICB0ZW1wbGF0ZVVybDogJy4vcHJlcGFyZS10ZW1wbGF0ZS5jb21wb25lbnQuaHRtbCcsXHJcbiAgc3R5bGVVcmw6ICcuL3ByZXBhcmUtdGVtcGxhdGUuY29tcG9uZW50LnNjc3MnLFxyXG4gIHByb3ZpZGVyczogW1RpdGxlQ2FzZVBpcGVdXHJcbn0pXHJcblxyXG5leHBvcnQgY2xhc3MgUHJlcGFyZVRlbXBsYXRlQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIEFmdGVyVmlld0luaXQge1xyXG4gIHNlYXJjaE1vZGVzID0gW1xyXG4gICAgeyB2YWx1ZTogJ3N0b3JlJywgbGFiZWw6ICdTdG9yZXMnIH0sXHJcbiAgICB7IHZhbHVlOiAnY2x1c3RlcicsIGxhYmVsOiAnQ2x1c3RlcnMnIH0sXHJcbiAgXTtcclxuICBzZWxlY3RlZE1vZGUgPSBuZXcgRm9ybUNvbnRyb2woJ3N0b3JlJyk7XHJcbiAgdGFyZ2V0ID0gbmV3IEZvcm1Db250cm9sKCdib3RoJyk7XHJcbiAgZmluZFByb21wdCA9IG5ldyBGb3JtQ29udHJvbCgnJyk7XHJcbiAgcmVwbGFjZVByb21wdCA9IG5ldyBGb3JtQ29udHJvbCgnJyk7XHJcbiAgXHJcbiAgc3RvcmVPcHRpb25zOiBTdG9yZU9wdGlvbltdID0gW107XHJcbiAgY2x1c3RlckRhdGE6IGFueVtdID0gW107IC8vIFN0b3JlIGZ1bGwgY2x1c3RlciBkYXRhIHdpdGggc3RvcmVzXHJcbiAgbG9hZGluZzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIHNhdmluZ0RyYWZ0OiBib29sZWFuID0gZmFsc2U7XHJcbiAgYmF0Y2hQcm9jZXNzaW5nOiBib29sZWFuID0gZmFsc2U7XHJcbiAgcHJpdmF0ZSBkZXN0cm95JCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XHJcbiAgXHJcbiAgc2VsZWN0ZWRTdG9yZXM6IFN0b3JlT3B0aW9uW10gPSBbXTtcclxuICBmaW5kUmVwbGFjZURhdGE6IEZpbmRSZXBsYWNlIHwgbnVsbCA9IG51bGw7XHJcbiAgc2VsZWN0ZWRTdG9yZUZvclByZXZpZXc6IGFueSA9IG51bGw7XHJcbiAgc3RvcmVMaXN0Rm9yRHJvcGRvd246IGFueVtdID0gW107XHJcbiAgc3RvcmVEcm9wZG93bkl0ZW1zOiBhbnlbXSA9IFtdO1xyXG4gIHNlbGVjdGVkU3RvcmVWYWx1ZXM6IGFueVtdID0gW107XHJcblxyXG4gIC8vIENhbnZhcyBwcm9wZXJ0aWVzXHJcbiAgQFZpZXdDaGlsZCgncHJldmlld0NhbnZhcycpIHByZXZpZXdDYW52YXNSZWYhOiBFbGVtZW50UmVmPEhUTUxDYW52YXNFbGVtZW50PjtcclxuICBAVmlld0NoaWxkKCdwcmV2aWV3Q2FudmFzQ29udGFpbmVyJykgcHJldmlld0NhbnZhc0NvbnRhaW5lclJlZiE6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+O1xyXG4gIHByZXZpZXdDYW52YXMhOiBmYWJyaWMuQ2FudmFzO1xyXG4gIHBsYW5vRGF0YTogYW55O1xyXG4gIGZsb29yRGF0YTogYW55O1xyXG4gIHdhbGxUaGlja25lc3MgPSAzMDtcclxuICB2ZXJ0aWNhbE1hcmdpbiA9ICgxLjI1IC8gMTAwKSAqIHRoaXMudG9QaXhlbHMoMTUyNCwgXCJtbVwiKTtcclxuICBjZG5Vcmw6IHN0cmluZyA9ICcnO1xyXG4gIGFjdGl2ZUhpZ2hsaWdodDogZmFicmljLlJlY3QgfCBudWxsID0gbnVsbDtcclxuICBjYW5jZWxIaWdobGlnaHRCbGluayA9IGZhbHNlO1xyXG4gIHNlbGVjdGVkRml4dHVyZTogYW55O1xyXG4gIHNlbGVjdGVkRml4dHVyZURhdGE6IGFueSA9IG51bGw7XHJcbiAgb3JpZ2luYWxGaXh0dXJlRGF0YTogYW55ID0gbnVsbDsgLy8gT3JpZ2luYWwgZml4dHVyZSBiZWZvcmUgcmVwbGFjZSAoZm9yIGJlZm9yZS9hZnRlciBjb21wYXJpc29uKVxyXG4gIHByaXZhdGUgb3JpZ2luYWxGaXh0dXJlc01hcDogTWFwPHN0cmluZywgYW55PiA9IG5ldyBNYXAoKTsgLy8gU3RvcmUgb3JpZ2luYWwgZml4dHVyZXMgYnkgZml4dHVyZUlkXHJcbiAgaXNSaWdodFBhbmVsQ29sbGFwc2VkID0gZmFsc2U7XHJcbiAgY2FudmFzTG9hZGluZyA9IGZhbHNlO1xyXG4gIGZpbmRMb2FkaW5nID0gZmFsc2U7XHJcbiAgcmVwbGFjZUxvYWRpbmcgPSBmYWxzZTtcclxuICBhbGxGaXh0dXJlSW5zdGFuY2VzOiBhbnlbXSA9IFtdO1xyXG4gIHZtTGlzdDogVm1MaWJyYXJ5TGlzdFtdID0gW107XHJcbiAgY2xpZW50SWQ6IHN0cmluZyA9ICcnO1xyXG4gIGhpZGVNZXRhZGF0YTogYm9vbGVhbiA9IGZhbHNlO1xyXG5cclxuICBnZXQgaGFzU3RvcmVzKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuICEhKHRoaXMuZmluZFJlcGxhY2VEYXRhPy5zdG9yZXMgJiYgdGhpcy5maW5kUmVwbGFjZURhdGEuc3RvcmVzLmxlbmd0aCA+IDApO1xyXG4gIH1cclxuXHJcbiAgZ2V0U3RvcmVDb3VudCgpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHRoaXMuZmluZFJlcGxhY2VEYXRhPy5zdG9yZUNvdW50IHx8IHRoaXMuZmluZFJlcGxhY2VEYXRhPy5zdG9yZXM/Lmxlbmd0aCB8fCAwO1xyXG4gIH1cclxuXHJcbiAgZ2V0Q3VycmVudEZpeHR1cmVEYXRhKCk6IGFueSB7XHJcbiAgICByZXR1cm4gdGhpcy5zZWxlY3RlZEZpeHR1cmVEYXRhIHx8IHRoaXMub3JpZ2luYWxGaXh0dXJlRGF0YTtcclxuICB9XHJcblxyXG4gIGdldEZpeHR1cmVMYWJlbCgpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgZml4dHVyZSA9IHRoaXMuZ2V0Q3VycmVudEZpeHR1cmVEYXRhKCk7XHJcbiAgICByZXR1cm4gZml4dHVyZT8uaGVhZGVyPy5sYWJlbCB8fCAnJztcclxuICB9XHJcblxyXG4gIGdldEZpeHR1cmVDYXRlZ29yeSgpOiBzdHJpbmcge1xyXG4gICAgY29uc3QgZml4dHVyZSA9IHRoaXMuZ2V0Q3VycmVudEZpeHR1cmVEYXRhKCk7XHJcbiAgICByZXR1cm4gZml4dHVyZT8uZml4dHVyZUNhdGVnb3J5IHx8ICcnO1xyXG4gIH1cclxuXHJcbiAgZ2V0Rml4dHVyZVdpZHRoKCk6IHN0cmluZyB7XHJcbiAgICBjb25zdCBmaXh0dXJlID0gdGhpcy5nZXRDdXJyZW50Rml4dHVyZURhdGEoKTtcclxuICAgIGlmICghZml4dHVyZT8uZml4dHVyZVdpZHRoKSByZXR1cm4gJyc7XHJcbiAgICBjb25zdCB3aWR0aCA9IGZpeHR1cmUuZml4dHVyZVdpZHRoLnZhbHVlO1xyXG4gICAgY29uc3QgdW5pdCA9IGZpeHR1cmUuZml4dHVyZVdpZHRoLnVuaXQgfHwgJ21tJztcclxuICAgIGxldCBkaW1lbnNpb25TdHIgPSBgJHt3aWR0aH0ke3VuaXR9YDtcclxuICAgIC8vIENvbnZlcnQgdG8gZmVldCBpZiBuZWVkZWQgKDEyMDBtbSA9IDRmdClcclxuICAgIGlmICh1bml0ID09PSAnbW0nICYmIHdpZHRoID09PSAxMjAwKSB7XHJcbiAgICAgIGRpbWVuc2lvblN0ciA9IGAke3dpZHRofSR7dW5pdH0vNGZ0YDtcclxuICAgIH0gZWxzZSBpZiAodW5pdCA9PT0gJ21tJyAmJiB3aWR0aCA+IDApIHtcclxuICAgICAgY29uc3QgZmVldCA9IE1hdGgucm91bmQod2lkdGggLyAzMDApO1xyXG4gICAgICBpZiAoZmVldCA+IDApIHtcclxuICAgICAgICBkaW1lbnNpb25TdHIgPSBgJHt3aWR0aH0ke3VuaXR9LyR7ZmVldH1mdGA7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIHJldHVybiBkaW1lbnNpb25TdHI7XHJcbiAgfVxyXG5cclxuICBnZXRTaGVsZkNvdW50KCk6IG51bWJlciB7XHJcbiAgICBjb25zdCBmaXh0dXJlID0gdGhpcy5nZXRDdXJyZW50Rml4dHVyZURhdGEoKTtcclxuICAgIHJldHVybiBmaXh0dXJlPy5zaGVsZkNvbmZpZz8ubGVuZ3RoIHx8IDA7XHJcbiAgfVxyXG5cclxuICBnZXRGaXh0dXJlQ2FwYWNpdHkoKTogbnVtYmVyIHtcclxuICAgIGNvbnN0IGZpeHR1cmUgPSB0aGlzLmdldEN1cnJlbnRGaXh0dXJlRGF0YSgpO1xyXG4gICAgcmV0dXJuIGZpeHR1cmU/LmZpeHR1cmVDYXBhY2l0eSB8fCAwO1xyXG4gIH1cclxuXHJcbiAgY29uc3RydWN0b3IoXHJcbiAgICBwcml2YXRlIHN0b3JlQnVpbGRlclNlcnZpY2U6IFN0b3JlQnVpbGRlclNlcnZpY2UsXHJcbiAgICBwcml2YXRlIGRhdGFTZXJ2aWNlOiBDb2xsZWN0aW9uVXBkYXRlQWlEYXRhU2VydmljZSxcclxuICAgIHByaXZhdGUgdGl0bGVDYXNlOiBUaXRsZUNhc2VQaXBlLFxyXG4gICAgcHJpdmF0ZSBjZHI6IENoYW5nZURldGVjdG9yUmVmLFxyXG4gICAgcHJpdmF0ZSBnczogR2xvYmFsU3RhdGVTZXJ2aWNlLFxyXG4gICAgcHJpdmF0ZSByb3V0ZXI6IFJvdXRlcixcclxuICAgIHByaXZhdGUgcm91dGU6IEFjdGl2YXRlZFJvdXRlLFxyXG4gICAgcHJpdmF0ZSB0b2FzdFNlcnZpY2U6IFRvYXN0U2VydmljZSxcclxuICAgIHByaXZhdGUgbW9kYWxTZXJ2aWNlOiBOZ2JNb2RhbFxyXG4gICkge31cclxuXHJcbiAgcHJpdmF0ZSBwcmV2aW91c1NlYXJjaE1vZGU6ICdzdG9yZScgfCAnY2x1c3RlcicgfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIGlzSW5pdGlhbExvYWQgPSB0cnVlO1xyXG4gIHByaXZhdGUgaGFzUmVzdG9yZWREYXRhID0gZmFsc2U7XHJcbiAgcHJpdmF0ZSBpc1VwZGF0aW5nRnJvbVNlcnZpY2UgPSBmYWxzZTtcclxuXHJcbiAgbmdPbkluaXQoKTogdm9pZCB7XHJcbiAgICAvLyBHZXQgY2xpZW50IElEIGFuZCBDRE4gVVJMXHJcbiAgICB0aGlzLmdzLmVudmlyb25tZW50XHJcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcclxuICAgICAgLnN1YnNjcmliZSgoZW52KSA9PiB7XHJcbiAgICAgICAgdGhpcy5jZG5VcmwgPSBlbnYucGxhbm9ncmFtQ0ROIHx8ICcnO1xyXG4gICAgICB9KTtcclxuXHJcbiAgICB0aGlzLmdzLmRhdGFSYW5nZVZhbHVlXHJcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcclxuICAgICAgLnN1YnNjcmliZSgoZGF0YSkgPT4ge1xyXG4gICAgICAgIGlmIChkYXRhPy5jbGllbnQpIHtcclxuICAgICAgICAgIHRoaXMuY2xpZW50SWQgPSBkYXRhLmNsaWVudDtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgY29uc3QgaGVhZGVyRGF0YSA9IEpTT04ucGFyc2UoXHJcbiAgICAgICAgICAgIGxvY2FsU3RvcmFnZS5nZXRJdGVtKFwiaGVhZGVyLWZpbHRlcnNcIikgYXMgc3RyaW5nXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgaWYgKGhlYWRlckRhdGE/LmNsaWVudCkge1xyXG4gICAgICAgICAgICB0aGlzLmNsaWVudElkID0gaGVhZGVyRGF0YS5jbGllbnQ7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAvLyBTdWJzY3JpYmUgdG8gZGF0YSBzZXJ2aWNlIHRvIHJlc3RvcmUgc2F2ZWQgZGF0YVxyXG4gICAgdGhpcy5kYXRhU2VydmljZS5nZXRGaW5kUmVwbGFjZURhdGEoKVxyXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXHJcbiAgICAgIC5zdWJzY3JpYmUoKGRhdGEpID0+IHtcclxuICAgICAgICAvLyBQcmV2ZW50IGluZmluaXRlIGxvb3BzIGJ5IHNraXBwaW5nIHVwZGF0ZXMgd2hlbiB3ZSdyZSB1cGRhdGluZyBmcm9tIGZvcm0gY2hhbmdlc1xyXG4gICAgICAgIGlmICh0aGlzLmlzVXBkYXRpbmdGcm9tU2VydmljZSkge1xyXG4gICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICB0aGlzLmZpbmRSZXBsYWNlRGF0YSA9IGRhdGE7XHJcbiAgICAgICAgXHJcbiAgICAgICAgLy8gVXBkYXRlIHN0b3JlIGRyb3Bkb3duIGl0ZW1zIHdoZW4gc3RvcmVzIGNoYW5nZVxyXG4gICAgICAgIHRoaXMudXBkYXRlU3RvcmVEcm9wZG93bkl0ZW1zKCk7XHJcbiAgICAgICAgXHJcbiAgICAgICAgaWYgKGRhdGEgJiYgIXRoaXMuaGFzUmVzdG9yZWREYXRhKSB7XHJcbiAgICAgICAgICAvLyBSZXN0b3JlIGFsbCBmb3JtIHZhbHVlcyBvbiBmaXJzdCBkYXRhIGxvYWRcclxuICAgICAgICAgIHRoaXMucmVzdG9yZUZvcm1WYWx1ZXMoZGF0YSk7XHJcbiAgICAgICAgICB0aGlzLmhhc1Jlc3RvcmVkRGF0YSA9IHRydWU7XHJcbiAgICAgICAgfSBlbHNlIGlmIChkYXRhICYmIHRoaXMuaGFzUmVzdG9yZWREYXRhKSB7XHJcbiAgICAgICAgICAvLyBJZiBkYXRhIGFscmVhZHkgcmVzdG9yZWQsIG9ubHkgaGFuZGxlIHNlYXJjaE1vZGUgY2hhbmdlc1xyXG4gICAgICAgICAgaWYgKGRhdGEuc2VhcmNoTW9kZSAmJiBkYXRhLnNlYXJjaE1vZGUgIT09IHRoaXMucHJldmlvdXNTZWFyY2hNb2RlKSB7XHJcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRNb2RlLnNldFZhbHVlKGRhdGEuc2VhcmNoTW9kZSwgeyBlbWl0RXZlbnQ6IGZhbHNlIH0pO1xyXG4gICAgICAgICAgICB0aGlzLnByZXZpb3VzU2VhcmNoTW9kZSA9IGRhdGEuc2VhcmNoTW9kZTtcclxuICAgICAgICAgICAgdGhpcy5sb2FkU3RvcmVzT3JDbHVzdGVycyhkYXRhKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIC8vIFVwZGF0ZSBzZWxlY3RlZCBzdG9yZSBmb3IgcHJldmlldyBpZiBzdG9yZXMgZXhpc3RcclxuICAgICAgICAgIGlmIChkYXRhLnN0b3JlcyAmJiBkYXRhLnN0b3Jlcy5sZW5ndGggPiAwICYmICF0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3KSB7XHJcbiAgICAgICAgICAgIGNvbnN0IG5ld1N0b3JlID0gdGhpcy5zdG9yZURyb3Bkb3duSXRlbXNbMF07XHJcbiAgICAgICAgICAgIGlmIChuZXdTdG9yZSAmJiAoIXRoaXMuc2VsZWN0ZWRTdG9yZUZvclByZXZpZXcgfHwgdGhpcy5zZWxlY3RlZFN0b3JlRm9yUHJldmlldy5zdG9yZUlkICE9PSBuZXdTdG9yZS5zdG9yZUlkKSkge1xyXG4gICAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRTdG9yZUZvclByZXZpZXcgPSBuZXdTdG9yZTtcclxuICAgICAgICAgICAgICB0aGlzLnVwZGF0ZVNlbGVjdGVkU3RvcmVWYWx1ZXMoKTtcclxuICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAvLyBSZXN0b3JlIGZpbmRSZXNwb25zZURhdGEgYW5kIHJlcGxhY2VSZXNwb25zZURhdGEgZm9yIHRoZSBzZWxlY3RlZCBzdG9yZSBpZiBhdmFpbGFibGVcclxuICAgICAgICAgICAgICB0aGlzLnJlc3RvcmVTdG9yZVJlc3BvbnNlRGF0YShuZXdTdG9yZS5zdG9yZU5hbWUpO1xyXG4gICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgIC8vIExvYWQgcGxhbm9ncmFtIGZvciB0aGUgc2VsZWN0ZWQgc3RvcmVcclxuICAgICAgICAgICAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pbml0aWFsaXplQ2FudmFzKCkpIHtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkUGxhbm9ncmFtRm9yU3RvcmUobmV3U3RvcmUuc3RvcmVOYW1lKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9LCA1MCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2UgaWYgKCFkYXRhICYmIHRoaXMuaXNJbml0aWFsTG9hZCkge1xyXG4gICAgICAgICAgLy8gTG9hZCBpbml0aWFsIGRhdGEgaWYgbm8gc2F2ZWQgZGF0YVxyXG4gICAgICAgICAgdGhpcy5sb2FkU3RvcmVzT3JDbHVzdGVycygpO1xyXG4gICAgICAgICAgdGhpcy5pc0luaXRpYWxMb2FkID0gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAvLyBTdWJzY3JpYmUgdG8gc2F2ZSBkcmFmdCBsb2FkaW5nIHN0YXRlXHJcbiAgICB0aGlzLmRhdGFTZXJ2aWNlLmdldExvYWRpbmdTdGF0ZSgpXHJcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcclxuICAgICAgLnN1YnNjcmliZSgoaXNMb2FkaW5nKSA9PiB7XHJcbiAgICAgICAgdGhpcy5zYXZpbmdEcmFmdCA9IGlzTG9hZGluZztcclxuICAgICAgfSk7XHJcblxyXG4gICAgLy8gV2F0Y2ggZm9yIG1vZGUgY2hhbmdlc1xyXG4gICAgdGhpcy5zZWxlY3RlZE1vZGUudmFsdWVDaGFuZ2VzXHJcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcclxuICAgICAgLnN1YnNjcmliZSgobmV3TW9kZSkgPT4ge1xyXG4gICAgICAgIGlmIChuZXdNb2RlICE9PSB0aGlzLnByZXZpb3VzU2VhcmNoTW9kZSAmJiAhdGhpcy5pc1VwZGF0aW5nRnJvbVNlcnZpY2UpIHtcclxuICAgICAgICAgIHRoaXMucHJldmlvdXNTZWFyY2hNb2RlID0gbmV3TW9kZSBhcyAnc3RvcmUnIHwgJ2NsdXN0ZXInO1xyXG4gICAgICAgICAgdGhpcy5sb2FkU3RvcmVzT3JDbHVzdGVycygpO1xyXG4gICAgICAgICAgLy8gQ2xlYXIgc2VsZWN0ZWQgc3RvcmVzIHdoZW4gbW9kZSBjaGFuZ2VzIG1hbnVhbGx5XHJcbiAgICAgICAgICB0aGlzLnNlbGVjdGVkU3RvcmVzID0gW107XHJcbiAgICAgICAgICAvLyBDbGVhciBzZWxlY3RlZENsdXN0ZXJzIHdoZW4gc3dpdGNoaW5nIHRvIHN0b3JlIG1vZGVcclxuICAgICAgICAgIGlmIChuZXdNb2RlID09PSAnc3RvcmUnKSB7XHJcbiAgICAgICAgICAgIHRoaXMuZGF0YVNlcnZpY2UudXBkYXRlRGF0YSh7IHNlbGVjdGVkQ2x1c3RlcnM6IHVuZGVmaW5lZCB9KTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgIC8vIFdhdGNoIGZvciB0YXJnZXQgY2hhbmdlcyAtIGRlYm91bmNlIHRvIHByZXZlbnQgZXhjZXNzaXZlIHVwZGF0ZXNcclxuICAgIHRoaXMudGFyZ2V0LnZhbHVlQ2hhbmdlc1xyXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXHJcbiAgICAgIC5zdWJzY3JpYmUoKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgaWYgKHZhbHVlICYmICF0aGlzLmlzVXBkYXRpbmdGcm9tU2VydmljZSkge1xyXG4gICAgICAgICAgdGhpcy5pc1VwZGF0aW5nRnJvbVNlcnZpY2UgPSB0cnVlO1xyXG4gICAgICAgICAgdGhpcy5kYXRhU2VydmljZS51cGRhdGVEYXRhKHsgdGFyZ2V0OiB2YWx1ZSBhcyAnbWVyY2gnIHwgJ3ZtJyB8ICdib3RoJyB9KTtcclxuICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLmlzVXBkYXRpbmdGcm9tU2VydmljZSA9IGZhbHNlO1xyXG4gICAgICAgICAgfSwgMCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuXHJcbiAgICAvLyBXYXRjaCBmb3IgZmluZCBwcm9tcHQgY2hhbmdlcyAtIGRlYm91bmNlIHRvIHByZXZlbnQgZXhjZXNzaXZlIHVwZGF0ZXNcclxuICAgIHRoaXMuZmluZFByb21wdC52YWx1ZUNoYW5nZXNcclxuICAgICAgLnBpcGUodGFrZVVudGlsKHRoaXMuZGVzdHJveSQpKVxyXG4gICAgICAuc3Vic2NyaWJlKCh2YWx1ZSkgPT4ge1xyXG4gICAgICAgIGlmICghdGhpcy5pc1VwZGF0aW5nRnJvbVNlcnZpY2UpIHtcclxuICAgICAgICAgIHRoaXMuaXNVcGRhdGluZ0Zyb21TZXJ2aWNlID0gdHJ1ZTtcclxuICAgICAgICAgIHRoaXMuZGF0YVNlcnZpY2UudXBkYXRlRGF0YSh7IGZpbmRQcm9tcHQ6IHZhbHVlIHx8ICcnIH0pO1xyXG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuaXNVcGRhdGluZ0Zyb21TZXJ2aWNlID0gZmFsc2U7XHJcbiAgICAgICAgICB9LCAwKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG5cclxuICAgIC8vIFdhdGNoIGZvciByZXBsYWNlIHByb21wdCBjaGFuZ2VzIC0gZGVib3VuY2UgdG8gcHJldmVudCBleGNlc3NpdmUgdXBkYXRlc1xyXG4gICAgdGhpcy5yZXBsYWNlUHJvbXB0LnZhbHVlQ2hhbmdlc1xyXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXHJcbiAgICAgIC5zdWJzY3JpYmUoKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgaWYgKCF0aGlzLmlzVXBkYXRpbmdGcm9tU2VydmljZSkge1xyXG4gICAgICAgICAgdGhpcy5pc1VwZGF0aW5nRnJvbVNlcnZpY2UgPSB0cnVlO1xyXG4gICAgICAgICAgdGhpcy5kYXRhU2VydmljZS51cGRhdGVEYXRhKHsgcmVwbGFjZVByb21wdDogdmFsdWUgfHwgJycgfSk7XHJcbiAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5pc1VwZGF0aW5nRnJvbVNlcnZpY2UgPSBmYWxzZTtcclxuICAgICAgICAgIH0sIDApO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHJlc3RvcmVGb3JtVmFsdWVzKGRhdGE6IEZpbmRSZXBsYWNlKTogdm9pZCB7XHJcbiAgICAvLyBSZXN0b3JlIHNlYXJjaE1vZGVcclxuICAgIGlmIChkYXRhLnNlYXJjaE1vZGUpIHtcclxuICAgICAgdGhpcy5zZWxlY3RlZE1vZGUuc2V0VmFsdWUoZGF0YS5zZWFyY2hNb2RlLCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgICAgIHRoaXMucHJldmlvdXNTZWFyY2hNb2RlID0gZGF0YS5zZWFyY2hNb2RlO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBSZXN0b3JlIHRhcmdldFxyXG4gICAgaWYgKGRhdGEudGFyZ2V0KSB7XHJcbiAgICAgIHRoaXMudGFyZ2V0LnNldFZhbHVlKGRhdGEudGFyZ2V0LCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIFJlc3RvcmUgZmluZFByb21wdFxyXG4gICAgaWYgKGRhdGEuZmluZFByb21wdCkge1xyXG4gICAgICB0aGlzLmZpbmRQcm9tcHQuc2V0VmFsdWUoZGF0YS5maW5kUHJvbXB0LCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIFJlc3RvcmUgcmVwbGFjZVByb21wdFxyXG4gICAgaWYgKGRhdGEucmVwbGFjZVByb21wdCkge1xyXG4gICAgICB0aGlzLnJlcGxhY2VQcm9tcHQuc2V0VmFsdWUoZGF0YS5yZXBsYWNlUHJvbXB0LCB7IGVtaXRFdmVudDogZmFsc2UgfSk7XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIExvYWQgc3RvcmVzL2NsdXN0ZXJzIGFuZCByZXN0b3JlIHNlbGVjdGlvbnNcclxuICAgIGlmIChkYXRhLnNlYXJjaE1vZGUpIHtcclxuICAgICAgdGhpcy5sb2FkU3RvcmVzT3JDbHVzdGVycyhkYXRhKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMubG9hZFN0b3Jlc09yQ2x1c3RlcnMoKTtcclxuICAgIH1cclxuICAgIFxyXG4gICAgLy8gU2V0IGluaXRpYWwgc2VsZWN0ZWQgc3RvcmUgZm9yIHByZXZpZXdcclxuICAgIGlmIChkYXRhLnN0b3JlcyAmJiBkYXRhLnN0b3Jlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgIHRoaXMudXBkYXRlU3RvcmVEcm9wZG93bkl0ZW1zKCk7XHJcbiAgICAgIGlmICh0aGlzLnN0b3JlRHJvcGRvd25JdGVtcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgdGhpcy5zZWxlY3RlZFN0b3JlRm9yUHJldmlldyA9IHRoaXMuc3RvcmVEcm9wZG93bkl0ZW1zWzBdO1xyXG4gICAgICAgIHRoaXMudXBkYXRlU2VsZWN0ZWRTdG9yZVZhbHVlcygpO1xyXG4gICAgICAgIC8vIExvYWQgcGxhbm9ncmFtIGFmdGVyIHZpZXcgaXMgaW5pdGlhbGl6ZWRcclxuICAgICAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICBpZiAodGhpcy5pbml0aWFsaXplQ2FudmFzKCkgJiYgdGhpcy5zZWxlY3RlZFN0b3JlRm9yUHJldmlldykge1xyXG4gICAgICAgICAgICB0aGlzLmxvYWRQbGFub2dyYW1Gb3JTdG9yZSh0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3LnN0b3JlTmFtZSk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyBSZXRyeSBpZiBjYW52YXMgbm90IHJlYWR5XHJcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICAgIGlmICh0aGlzLmluaXRpYWxpemVDYW52YXMoKSAmJiB0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3KSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRQbGFub2dyYW1Gb3JTdG9yZSh0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3LnN0b3JlTmFtZSk7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9LCAyMDApO1xyXG4gICAgICAgICAgfVxyXG4gICAgICAgIH0sIDEwMCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICAgIFxyXG4gICAgdGhpcy5pc0luaXRpYWxMb2FkID0gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIHVwZGF0ZVN0b3JlRHJvcGRvd25JdGVtcygpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5maW5kUmVwbGFjZURhdGE/LnN0b3Jlcykge1xyXG4gICAgICB0aGlzLnN0b3JlRHJvcGRvd25JdGVtcyA9IFtdO1xyXG4gICAgICB0aGlzLnNlbGVjdGVkU3RvcmVWYWx1ZXMgPSBbXTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICBjb25zdCBuZXdJdGVtcyA9IHRoaXMuZmluZFJlcGxhY2VEYXRhLnN0b3Jlcy5tYXAoKHN0b3JlOiBTdG9yZSkgPT4gKHtcclxuICAgICAgc3RvcmVJZDogc3RvcmUuc3RvcmVJZCB8fCBzdG9yZS5zdG9yZU5hbWUsXHJcbiAgICAgIHN0b3JlTmFtZTogc3RvcmUuc3RvcmVOYW1lLFxyXG4gICAgICBfaWQ6IHN0b3JlLnN0b3JlSWQgfHwgc3RvcmUuc3RvcmVOYW1lXHJcbiAgICB9KSk7XHJcbiAgICBcclxuICAgIC8vIE9ubHkgdXBkYXRlIGlmIGl0ZW1zIGFjdHVhbGx5IGNoYW5nZWRcclxuICAgIGNvbnN0IGl0ZW1zQ2hhbmdlZCA9IEpTT04uc3RyaW5naWZ5KG5ld0l0ZW1zKSAhPT0gSlNPTi5zdHJpbmdpZnkodGhpcy5zdG9yZURyb3Bkb3duSXRlbXMpO1xyXG4gICAgaWYgKGl0ZW1zQ2hhbmdlZCkge1xyXG4gICAgICB0aGlzLnN0b3JlRHJvcGRvd25JdGVtcyA9IG5ld0l0ZW1zO1xyXG4gICAgICB0aGlzLnVwZGF0ZVNlbGVjdGVkU3RvcmVWYWx1ZXMoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgdXBkYXRlU2VsZWN0ZWRTdG9yZVZhbHVlcygpOiB2b2lkIHtcclxuICAgIGlmICh0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3KSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRTdG9yZVZhbHVlcyA9IFt0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3XTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRTdG9yZVZhbHVlcyA9IFtdO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xyXG4gICAgLy8gQ2FudmFzIHdpbGwgYmUgaW5pdGlhbGl6ZWQgd2hlbiBzdG9yZSBpcyBzZWxlY3RlZCBhbmQgY2FudmFzIGVsZW1lbnQgaXMgYXZhaWxhYmxlXHJcbiAgfVxyXG5cclxuICBpbml0aWFsaXplQ2FudmFzKCk6IGJvb2xlYW4ge1xyXG4gICAgaWYgKHRoaXMucHJldmlld0NhbnZhcykge1xyXG4gICAgICByZXR1cm4gdHJ1ZTsgLy8gQWxyZWFkeSBpbml0aWFsaXplZFxyXG4gICAgfVxyXG4gICAgXHJcbiAgICBpZiAodGhpcy5wcmV2aWV3Q2FudmFzUmVmPy5uYXRpdmVFbGVtZW50KSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgdGhpcy5wcmV2aWV3Q2FudmFzID0gbmV3IGZhYnJpYy5DYW52YXModGhpcy5wcmV2aWV3Q2FudmFzUmVmLm5hdGl2ZUVsZW1lbnQsIHtcclxuICAgICAgICAgIHNlbGVjdGlvbkZ1bGx5Q29udGFpbmVkOiB0cnVlLFxyXG4gICAgICAgICAgcGVyUGl4ZWxUYXJnZXRGaW5kOiB0cnVlLFxyXG4gICAgICAgICAgdGFyZ2V0RmluZFRvbGVyYW5jZTogNSxcclxuICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLnNldHVwWm9vbUhhbmRsZXJzKHRoaXMucHJldmlld0NhbnZhcyk7XHJcbiAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgaW5pdGlhbGl6aW5nIGNhbnZhczonLCBlcnJvcik7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG5cclxuICBvblN0b3JlU2VsZWN0ZWRGb3JQcmV2aWV3KHN0b3JlOiBhbnkpOiB2b2lkIHtcclxuICAgIGlmIChzdG9yZSAmJiAoIXRoaXMuc2VsZWN0ZWRTdG9yZUZvclByZXZpZXcgfHwgdGhpcy5zZWxlY3RlZFN0b3JlRm9yUHJldmlldy5zdG9yZUlkICE9PSBzdG9yZS5zdG9yZUlkKSkge1xyXG4gICAgICB0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3ID0gc3RvcmU7XHJcbiAgICAgIHRoaXMudXBkYXRlU2VsZWN0ZWRTdG9yZVZhbHVlcygpO1xyXG4gICAgICBcclxuICAgICAgLy8gQ2xlYXIgc2VsZWN0ZWQgZml4dHVyZSB3aGVuIHN3aXRjaGluZyBzdG9yZXNcclxuICAgICAgdGhpcy5zZWxlY3RlZEZpeHR1cmUgPSBudWxsO1xyXG4gICAgICB0aGlzLnNlbGVjdGVkRml4dHVyZURhdGEgPSBudWxsO1xyXG4gICAgICB0aGlzLm9yaWdpbmFsRml4dHVyZURhdGEgPSBudWxsO1xyXG4gICAgICB0aGlzLm9yaWdpbmFsRml4dHVyZXNNYXAuY2xlYXIoKTsgLy8gQ2xlYXIgdGhlIG1hcCB3aGVuIHN3aXRjaGluZyBzdG9yZXNcclxuICAgICAgXHJcbiAgICAgIC8vIFJlc3RvcmUgZmluZFJlc3BvbnNlRGF0YSBhbmQgcmVwbGFjZVJlc3BvbnNlRGF0YSBmb3IgdGhlIHNlbGVjdGVkIHN0b3JlIGlmIGF2YWlsYWJsZVxyXG4gICAgICB0aGlzLnJlc3RvcmVTdG9yZVJlc3BvbnNlRGF0YShzdG9yZS5zdG9yZU5hbWUpO1xyXG4gICAgICBcclxuICAgICAgLy8gRm9yY2UgY2hhbmdlIGRldGVjdGlvbiB0byBlbnN1cmUgY2FudmFzIGVsZW1lbnQgaXMgaW4gRE9NXHJcbiAgICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcclxuICAgICAgXHJcbiAgICAgIC8vIEluaXRpYWxpemUgY2FudmFzIGlmIG5vdCBhbHJlYWR5IGRvbmUsIHRoZW4gbG9hZCBwbGFub2dyYW1cclxuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgaWYgKHRoaXMuaW5pdGlhbGl6ZUNhbnZhcygpKSB7XHJcbiAgICAgICAgICB0aGlzLmxvYWRQbGFub2dyYW1Gb3JTdG9yZShzdG9yZS5zdG9yZU5hbWUpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAvLyBSZXRyeSBhZnRlciBhIHNob3J0IGRlbGF5IGlmIGNhbnZhcyBlbGVtZW50IG5vdCByZWFkeVxyXG4gICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLmluaXRpYWxpemVDYW52YXMoKSkge1xyXG4gICAgICAgICAgICAgIHRoaXMubG9hZFBsYW5vZ3JhbUZvclN0b3JlKHN0b3JlLnN0b3JlTmFtZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0sIDEwMCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9LCA1MCk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvLyBSZXN0b3JlIGZpbmRSZXNwb25zZURhdGEgYW5kIHJlcGxhY2VSZXNwb25zZURhdGEgZm9yIGEgc3BlY2lmaWMgc3RvcmVcclxuICBwcml2YXRlIHJlc3RvcmVTdG9yZVJlc3BvbnNlRGF0YShzdG9yZU5hbWU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLmZpbmRSZXBsYWNlRGF0YT8uc3RvcmVzKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBzdG9yZSA9IHRoaXMuZmluZFJlcGxhY2VEYXRhLnN0b3Jlcy5maW5kKFxyXG4gICAgICAoczogU3RvcmUpID0+IHMuc3RvcmVOYW1lID09PSBzdG9yZU5hbWVcclxuICAgICk7XHJcblxyXG4gICAgaWYgKCFzdG9yZSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gZmluZFJlc3BvbnNlRGF0YSBpcyBhIHN0cmluZyAoZml4dHVyZSBfaWQpXHJcbiAgICAvLyByZXBsYWNlUmVzcG9uc2VEYXRhIGlzIGFuIG9iamVjdCB3aXRoIHZtQ29uZmlnIGFuZC9vciBzaGVsZkNvbmZpZ1xyXG4gICAgY29uc3QgZml4dHVyZUlkID0gc3RvcmUuZmluZFJlc3BvbnNlRGF0YTtcclxuICAgIGlmICghZml4dHVyZUlkKSByZXR1cm47XHJcblxyXG4gICAgdGhpcy5zZWxlY3RlZEZpeHR1cmUgPSB7IGZpeHR1cmVJZCwgZml4dHVyZVR5cGU6IHVuZGVmaW5lZCB9O1xyXG4gICAgLy8gV2UnbGwgcmUtaHlkcmF0ZSBzZWxlY3RlZEZpeHR1cmVEYXRhIGZyb20gdGhlIGxvYWRlZCBwbGFub2dyYW0gKGZsb29yRGF0YSkgYWZ0ZXIgbG9hZC5cclxuICAgIHRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YSA9IG51bGw7XHJcbiAgfVxyXG5cclxuICAvLyBBcHBseSBzdG9yZWQgZmluZFJlc3BvbnNlRGF0YSBhbmQgcmVwbGFjZVJlc3BvbnNlRGF0YSB0byBmbG9vciBkYXRhXHJcbiAgcHJpdmF0ZSBhcHBseVN0b3JlZFJlc3BvbnNlRGF0YSgpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5maW5kUmVwbGFjZURhdGE/LnN0b3JlcyB8fCAhdGhpcy5zZWxlY3RlZFN0b3JlRm9yUHJldmlldyB8fCAhdGhpcy5mbG9vckRhdGEpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHN0b3JlID0gdGhpcy5maW5kUmVwbGFjZURhdGEuc3RvcmVzLmZpbmQoXHJcbiAgICAgIChzOiBTdG9yZSkgPT4gcy5zdG9yZU5hbWUgPT09IHRoaXMuc2VsZWN0ZWRTdG9yZUZvclByZXZpZXcuc3RvcmVOYW1lXHJcbiAgICApO1xyXG5cclxuICAgIGlmICghc3RvcmUpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIGZpbmRSZXNwb25zZURhdGEgaXMgYSBzdHJpbmcgKGZpeHR1cmUgX2lkKSAtIHVzZSBpdCB0byBmaW5kIHRoZSBmaXh0dXJlXHJcbiAgICBjb25zdCBmaXh0dXJlSWQgPSBzdG9yZS5maW5kUmVzcG9uc2VEYXRhO1xyXG4gICAgaWYgKCFmaXh0dXJlSWQpIHJldHVybjtcclxuXHJcbiAgICAvLyBGaW5kIHRoZSBmaXh0dXJlIGluIGZsb29yRGF0YVxyXG4gICAgY29uc3QgZml4dHVyZSA9IHRoaXMuZ2V0Rml4dHVyZUJ5SWRGcm9tRmxvb3IoZml4dHVyZUlkKTtcclxuICAgIGlmICghZml4dHVyZSkgcmV0dXJuO1xyXG5cclxuICAgIC8vIEFwcGx5IHJlcGxhY2VSZXNwb25zZURhdGEgY29uZmlncyBpZiBhdmFpbGFibGUgKG1lcmdlIHdpdGggZXhpc3RpbmcgZml4dHVyZSlcclxuICAgIGlmIChzdG9yZS5yZXBsYWNlUmVzcG9uc2VEYXRhKSB7XHJcbiAgICAgIC8vIFN0b3JlIHRoZSBvcmlnaW5hbCBmaXh0dXJlIChiZWZvcmUgcmVwbGFjZSkgZm9yIGJlZm9yZS9hZnRlciBjb21wYXJpc29uXHJcbiAgICAgIGNvbnN0IG9yaWdpbmFsRml4dHVyZSA9IHN0cnVjdHVyZWRDbG9uZShmaXh0dXJlKTtcclxuICAgICAgdGhpcy5vcmlnaW5hbEZpeHR1cmVEYXRhID0gb3JpZ2luYWxGaXh0dXJlO1xyXG4gICAgICAvLyBBbHNvIHN0b3JlIGl0IGluIHRoZSBtYXAgc28gaXQgcGVyc2lzdHMgd2hlbiBjbGlja2luZyBvdGhlciBmaXh0dXJlc1xyXG4gICAgICB0aGlzLm9yaWdpbmFsRml4dHVyZXNNYXAuc2V0KGZpeHR1cmVJZCwgb3JpZ2luYWxGaXh0dXJlKTtcclxuICAgICAgXHJcbiAgICAgIGNvbnN0IHVwZGF0ZWRGaXh0dXJlID0geyAuLi5maXh0dXJlIH07XHJcbiAgICAgIFxyXG4gICAgICAvLyBNZXJnZSB2bUNvbmZpZyBpZiBwcmVzZW50IGluIHJlcGxhY2VSZXNwb25zZURhdGFcclxuICAgICAgaWYgKHN0b3JlLnJlcGxhY2VSZXNwb25zZURhdGEudm1Db25maWcpIHtcclxuICAgICAgICB1cGRhdGVkRml4dHVyZS52bUNvbmZpZyA9IHN0b3JlLnJlcGxhY2VSZXNwb25zZURhdGEudm1Db25maWc7XHJcbiAgICAgIH1cclxuICAgICAgXHJcbiAgICAgIC8vIE1lcmdlIHNoZWxmQ29uZmlnIGlmIHByZXNlbnQgaW4gcmVwbGFjZVJlc3BvbnNlRGF0YVxyXG4gICAgICBpZiAoc3RvcmUucmVwbGFjZVJlc3BvbnNlRGF0YS5zaGVsZkNvbmZpZykge1xyXG4gICAgICAgIHVwZGF0ZWRGaXh0dXJlLnNoZWxmQ29uZmlnID0gc3RvcmUucmVwbGFjZVJlc3BvbnNlRGF0YS5zaGVsZkNvbmZpZztcclxuICAgICAgfVxyXG5cclxuICAgICAgLy8gVXBkYXRlIHRoZSBmaXh0dXJlIGluIGZsb29yRGF0YVxyXG4gICAgICB0aGlzLnVwZGF0ZUFpUmVzcG9uc2VGaXh0dXJlKHVwZGF0ZWRGaXh0dXJlKTtcclxuICAgICAgXHJcbiAgICAgIC8vIFNldCBzZWxlY3RlZCBmaXh0dXJlIGRhdGEgKGFmdGVyIHJlcGxhY2UpXHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRGaXh0dXJlID0ge1xyXG4gICAgICAgIGZpeHR1cmVJZDogdXBkYXRlZEZpeHR1cmUuX2lkLFxyXG4gICAgICAgIGZpeHR1cmVUeXBlOiB1cGRhdGVkRml4dHVyZS5maXh0dXJlVHlwZSxcclxuICAgICAgfTtcclxuICAgICAgdGhpcy5zZWxlY3RlZEZpeHR1cmVEYXRhID0gdXBkYXRlZEZpeHR1cmU7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICAvLyBObyByZXBsYWNlUmVzcG9uc2VEYXRhLCBjbGVhciBvcmlnaW5hbCBmaXh0dXJlIGFuZCBqdXN0IHNldCB0aGUgc2VsZWN0ZWQgZml4dHVyZSBmcm9tIGZpbmRSZXNwb25zZURhdGFcclxuICAgICAgdGhpcy5vcmlnaW5hbEZpeHR1cmVEYXRhID0gbnVsbDtcclxuICAgICAgdGhpcy5zZWxlY3RlZEZpeHR1cmUgPSB7XHJcbiAgICAgICAgZml4dHVyZUlkOiBmaXh0dXJlLl9pZCxcclxuICAgICAgICBmaXh0dXJlVHlwZTogZml4dHVyZS5maXh0dXJlVHlwZSxcclxuICAgICAgfTtcclxuICAgICAgdGhpcy5zZWxlY3RlZEZpeHR1cmVEYXRhID0gZml4dHVyZTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgZ2V0Rml4dHVyZUJ5SWRGcm9tRmxvb3IoZml4dHVyZUlkOiBzdHJpbmcpOiBhbnkgfCBudWxsIHtcclxuICAgIGlmICghZml4dHVyZUlkIHx8ICF0aGlzLmZsb29yRGF0YSkgcmV0dXJuIG51bGw7XHJcblxyXG4gICAgZm9yIChjb25zdCBlbGVtZW50IG9mIHRoaXMuZmxvb3JEYXRhLmxheW91dFBvbHlnb24gfHwgW10pIHtcclxuICAgICAgaWYgKGVsZW1lbnQ/LmVsZW1lbnRUeXBlID09PSBcIndhbGxcIiAmJiBBcnJheS5pc0FycmF5KGVsZW1lbnQuZml4dHVyZXMpKSB7XHJcbiAgICAgICAgY29uc3QgaGl0ID0gZWxlbWVudC5maXh0dXJlcy5maW5kKChmeDogYW55KSA9PiBmeD8uX2lkID09PSBmaXh0dXJlSWQpO1xyXG4gICAgICAgIGlmIChoaXQpIHJldHVybiBoaXQ7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBmb3IgKGNvbnN0IGZ4IG9mIHRoaXMuZmxvb3JEYXRhLmNlbnRlckZpeHR1cmUgfHwgW10pIHtcclxuICAgICAgaWYgKGZ4Py5faWQgPT09IGZpeHR1cmVJZCkgcmV0dXJuIGZ4O1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBudWxsO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgbG9hZFBsYW5vZ3JhbUZvclN0b3JlKHN0b3JlTmFtZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBpZiAoIXN0b3JlTmFtZSkge1xyXG4gICAgICBjb25zb2xlLndhcm4oJ0Nhbm5vdCBsb2FkIHBsYW5vZ3JhbTogc3RvcmVOYW1lIG5vdCBhdmFpbGFibGUnKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICBpZiAoIXRoaXMucHJldmlld0NhbnZhcykge1xyXG4gICAgICBjb25zb2xlLndhcm4oJ0NhbnZhcyBub3QgaW5pdGlhbGl6ZWQsIGF0dGVtcHRpbmcgdG8gaW5pdGlhbGl6ZS4uLicpO1xyXG4gICAgICBpZiAoIXRoaXMuaW5pdGlhbGl6ZUNhbnZhcygpKSB7XHJcbiAgICAgICAgY29uc29sZS5lcnJvcignRmFpbGVkIHRvIGluaXRpYWxpemUgY2FudmFzJyk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBcclxuICAgIHRoaXMuY2FudmFzTG9hZGluZyA9IHRydWU7XHJcbiAgICB0cnkge1xyXG4gICAgICAvLyBHZXQgcGxhbm9JZCBmcm9tIHN0b3JlIG5hbWVcclxuICAgICAgY29uc3QgcmVzcG9uc2U6IGFueSA9IGF3YWl0IHRoaXMuc3RvcmVCdWlsZGVyU2VydmljZS5nZXRQbGFub0lkKHsgc3RvcmVzOiBbc3RvcmVOYW1lLnRvVXBwZXJDYXNlKCldIH0pLnRvUHJvbWlzZSgpO1xyXG4gICAgICBcclxuICAgICAgaWYgKHJlc3BvbnNlPy5jb2RlID09PSAyMDAgJiYgcmVzcG9uc2U/LmRhdGE/Lmxlbmd0aCA+IDApIHtcclxuICAgICAgICBjb25zdCBwbGFub0lkID0gcmVzcG9uc2UuZGF0YVswXS5faWQ7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5nZXRTdG9yZUZpeHR1cmVzKHBsYW5vSWQpO1xyXG4gICAgICB9IGVsc2Uge1xyXG4gICAgICAgIGNvbnNvbGUud2FybignTm8gcGxhbm9ncmFtIGZvdW5kIGZvciBzdG9yZTonLCBzdG9yZU5hbWUpO1xyXG4gICAgICAgIHRoaXMuY2FudmFzTG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICB9XHJcbiAgICB9IGNhdGNoIChlcnJvcikge1xyXG4gICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBsb2FkaW5nIHBsYW5vZ3JhbTonLCBlcnJvcik7XHJcbiAgICAgIHRoaXMuY2FudmFzTG9hZGluZyA9IGZhbHNlO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgbG9hZFN0b3Jlc09yQ2x1c3RlcnMoc2F2ZWREYXRhPzogRmluZFJlcGxhY2UpOiB2b2lkIHtcclxuICAgIGNvbnN0IHNlYXJjaE1vZGUgPSB0aGlzLnNlbGVjdGVkTW9kZS52YWx1ZSBhcyAnc3RvcmUnIHwgJ2NsdXN0ZXInO1xyXG4gICAgaWYgKCFzZWFyY2hNb2RlKSByZXR1cm47XHJcblxyXG4gICAgdGhpcy5sb2FkaW5nID0gdHJ1ZTtcclxuICAgIHRoaXMuc3RvcmVCdWlsZGVyU2VydmljZS5nZXRTdG9yZU9yQ2x1c3Rlckxpc3QoeyBzZWFyY2hNb2RlIH0pXHJcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcclxuICAgICAgLnN1YnNjcmliZSh7XHJcbiAgICAgICAgbmV4dDogKHJlc3BvbnNlOiBhbnkpID0+IHtcclxuICAgICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgaWYgKHJlc3BvbnNlPy5jb2RlID09PSAyMDAgJiYgcmVzcG9uc2U/LmRhdGEgJiYgQXJyYXkuaXNBcnJheShyZXNwb25zZS5kYXRhKSkge1xyXG4gICAgICAgICAgICBpZiAoc2VhcmNoTW9kZSA9PT0gJ3N0b3JlJykge1xyXG4gICAgICAgICAgICAgIC8vIEZvciBzdG9yZSBtb2RlLCB1c2UgZGF0YSBkaXJlY3RseVxyXG4gICAgICAgICAgICAgIHRoaXMuc3RvcmVPcHRpb25zID0gcmVzcG9uc2UuZGF0YS5tYXAoKGl0ZW06IGFueSkgPT4gKHtcclxuICAgICAgICAgICAgICAgIGlkOiBpdGVtLmlkLFxyXG4gICAgICAgICAgICAgICAgbGFiZWw6IGl0ZW0ubGFiZWxcclxuICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgdGhpcy5jbHVzdGVyRGF0YSA9IFtdOyAvLyBDbGVhciBjbHVzdGVyIGRhdGFcclxuICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAvLyBSZXN0b3JlIHNhdmVkIHNlbGVjdGlvbnMgZm9yIHN0b3JlIG1vZGVcclxuICAgICAgICAgICAgICBpZiAoc2F2ZWREYXRhPy5zdG9yZXMgJiYgc2F2ZWREYXRhLnN0b3Jlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJlc3RvcmVTdG9yZVNlbGVjdGlvbnMoc2F2ZWREYXRhLnN0b3Jlcyk7XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgIC8vIEZvciBjbHVzdGVyIG1vZGUsIHNob3cgY2x1c3RlcnMgaW4gdGhlIGRyb3Bkb3duXHJcbiAgICAgICAgICAgICAgLy8gU3RvcmUgZnVsbCBjbHVzdGVyIGRhdGEgZm9yIGxhdGVyIHVzZVxyXG4gICAgICAgICAgICAgIHRoaXMuY2x1c3RlckRhdGEgPSByZXNwb25zZS5kYXRhO1xyXG4gICAgICAgICAgICAgIHRoaXMuc3RvcmVPcHRpb25zID0gcmVzcG9uc2UuZGF0YS5tYXAoKGNsdXN0ZXI6IGFueSkgPT4gKHtcclxuICAgICAgICAgICAgICAgIGlkOiBjbHVzdGVyLmlkLFxyXG4gICAgICAgICAgICAgICAgbGFiZWw6IGNsdXN0ZXIubGFiZWxcclxuICAgICAgICAgICAgICB9KSk7XHJcbiAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgLy8gUmVzdG9yZSBzYXZlZCBzZWxlY3Rpb25zIGZvciBjbHVzdGVyIG1vZGVcclxuICAgICAgICAgICAgICBpZiAoc2F2ZWREYXRhPy5zdG9yZXMgJiYgc2F2ZWREYXRhLnN0b3Jlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnJlc3RvcmVDbHVzdGVyU2VsZWN0aW9ucyhzYXZlZERhdGEuc3RvcmVzKTtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMuc3RvcmVPcHRpb25zID0gW107XHJcbiAgICAgICAgICAgIHRoaXMuY2x1c3RlckRhdGEgPSBbXTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG4gICAgICAgIGVycm9yOiAoZXJyb3IpID0+IHtcclxuICAgICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgbG9hZGluZyBzdG9yZXMvY2x1c3RlcnM6JywgZXJyb3IpO1xyXG4gICAgICAgICAgdGhpcy5zdG9yZU9wdGlvbnMgPSBbXTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcmVzdG9yZVN0b3JlU2VsZWN0aW9ucyhzYXZlZFN0b3JlczogU3RvcmVbXSk6IHZvaWQge1xyXG4gICAgLy8gTWF0Y2ggc2F2ZWQgc3RvcmVzIGJ5IHN0b3JlTmFtZVxyXG4gICAgY29uc3Qgc2F2ZWRTdG9yZU5hbWVzID0gbmV3IFNldChzYXZlZFN0b3Jlcy5tYXAocyA9PiBzLnN0b3JlTmFtZSkpO1xyXG4gICAgdGhpcy5zZWxlY3RlZFN0b3JlcyA9IHRoaXMuc3RvcmVPcHRpb25zLmZpbHRlcihvcHRpb24gPT4gXHJcbiAgICAgIHNhdmVkU3RvcmVOYW1lcy5oYXMob3B0aW9uLmxhYmVsKVxyXG4gICAgKTtcclxuICB9XHJcblxyXG4gIHJlc3RvcmVDbHVzdGVyU2VsZWN0aW9ucyhfc2F2ZWRTdG9yZXM6IFN0b3JlW10pOiB2b2lkIHtcclxuICAgIC8vIFJlc3RvcmUgY2x1c3RlciBzZWxlY3Rpb24gT05MWSBmcm9tIHNlbGVjdGVkQ2x1c3RlcnMgKG5vIGRlcml2YXRpb24gZnJvbSBzdG9yZXMpXHJcbiAgICBjb25zdCBzYXZlZENsdXN0ZXJzID0gdGhpcy5maW5kUmVwbGFjZURhdGE/LnNlbGVjdGVkQ2x1c3RlcnMgfHwgW107XHJcbiAgICBpZiAoIXNhdmVkQ2x1c3RlcnMubGVuZ3RoKSB7XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRTdG9yZXMgPSBbXTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHNhdmVkQ2x1c3RlcklkcyA9IG5ldyBTZXQoc2F2ZWRDbHVzdGVycy5tYXAoYyA9PiBjLmlkKSk7XHJcbiAgICBjb25zdCBzZWxlY3RlZENsdXN0ZXJzOiBTdG9yZU9wdGlvbltdID0gW107XHJcblxyXG4gICAgdGhpcy5jbHVzdGVyRGF0YS5mb3JFYWNoKChjbHVzdGVyOiBhbnkpID0+IHtcclxuICAgICAgaWYgKHNhdmVkQ2x1c3Rlcklkcy5oYXMoY2x1c3Rlci5pZCkpIHtcclxuICAgICAgICBzZWxlY3RlZENsdXN0ZXJzLnB1c2goe1xyXG4gICAgICAgICAgaWQ6IGNsdXN0ZXIuaWQsXHJcbiAgICAgICAgICBsYWJlbDogY2x1c3Rlci5sYWJlbFxyXG4gICAgICAgIH0pO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLnNlbGVjdGVkU3RvcmVzID0gc2VsZWN0ZWRDbHVzdGVycztcclxuICB9XHJcblxyXG4gIG9uU3RvcmVzU2VsZWN0ZWQoc3RvcmVzOiBTdG9yZU9wdGlvbltdKSB7XHJcbiAgICB0aGlzLnNlbGVjdGVkU3RvcmVzID0gc3RvcmVzO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgb25SZXZpZXdBbmRSZXBsYWNlKCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgaWYgKCF0aGlzLmZpbmRSZXBsYWNlRGF0YT8uX2lkKSB7XHJcbiAgICAgIGNvbnNvbGUuZXJyb3IoJ05vIGZpbmQgcmVwbGFjZSBJRCBhdmFpbGFibGUnKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFNob3cgY29uZmlybWF0aW9uIG1vZGFsXHJcbiAgICBjb25zdCBtb2RhbFJlZiA9IHRoaXMubW9kYWxTZXJ2aWNlLm9wZW4oQmF0Y2hDb25maXJtYXRpb25Nb2RhbENvbXBvbmVudCwge1xyXG4gICAgICBjZW50ZXJlZDogdHJ1ZSxcclxuICAgICAgc2l6ZTogJ21kJyxcclxuICAgICAgYmFja2Ryb3A6ICdzdGF0aWMnLFxyXG4gICAgICB3aW5kb3dDbGFzczogJ2JhdGNoLWNvbmZpcm1hdGlvbi1tb2RhbCdcclxuICAgIH0pO1xyXG5cclxuICAgIC8vIFBhc3Mgc3RvcmUgY291bnQgdG8gbW9kYWxcclxuICAgIG1vZGFsUmVmLmNvbXBvbmVudEluc3RhbmNlLnN0b3JlQ291bnQgPSB0aGlzLmdldFN0b3JlQ291bnQoKTtcclxuXHJcbiAgICB0cnkge1xyXG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBtb2RhbFJlZi5yZXN1bHQ7XHJcbiAgICAgIGlmIChyZXN1bHQpIHtcclxuICAgICAgICAvLyBVc2VyIGNvbmZpcm1lZCwgcHJvY2VlZCB3aXRoIGJhdGNoIHByb2Nlc3NcclxuICAgICAgICB0aGlzLnByb2NlZWRXaXRoQmF0Y2hQcm9jZXNzKCk7XHJcbiAgICAgIH1cclxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XHJcbiAgICAgIC8vIFVzZXIgZGlzbWlzc2VkIHRoZSBtb2RhbFxyXG4gICAgICBjb25zb2xlLmxvZygnQmF0Y2ggY29uZmlybWF0aW9uIG1vZGFsIGRpc21pc3NlZCcpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBwcm9jZWVkV2l0aEJhdGNoUHJvY2VzcygpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5maW5kUmVwbGFjZURhdGE/Ll9pZCkge1xyXG4gICAgICBjb25zb2xlLmVycm9yKCdObyBmaW5kIHJlcGxhY2UgSUQgYXZhaWxhYmxlJyk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmxvYWRpbmcgPSB0cnVlO1xyXG4gICAgdGhpcy5iYXRjaFByb2Nlc3NpbmcgPSB0cnVlO1xyXG4gICAgY29uc3QgZmluZFJlcGxhY2VJZCA9IHRoaXMuZmluZFJlcGxhY2VEYXRhLl9pZDtcclxuICAgIFxyXG4gICAgdGhpcy5zdG9yZUJ1aWxkZXJTZXJ2aWNlLmJhdGNoRmluZFJlcGxhY2UoeyBmaW5kUmVwbGFjZUlkIH0pXHJcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcclxuICAgICAgLnN1YnNjcmliZSh7XHJcbiAgICAgICAgbmV4dDogKHJlc3BvbnNlOiBhbnkpID0+IHtcclxuICAgICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgdGhpcy5iYXRjaFByb2Nlc3NpbmcgPSBmYWxzZTtcclxuICAgICAgICAgIGlmIChyZXNwb25zZT8uY29kZSA9PT0gMjAwKSB7XHJcbiAgICAgICAgICAgIC8vIFJlZmV0Y2ggZmluZCByZXBsYWNlIGRhdGEgdG8gdXBkYXRlIFVJXHJcbiAgICAgICAgICAgIHRoaXMuZGF0YVNlcnZpY2UubG9hZEFuZFNldEZpbmRSZXBsYWNlRGF0YUJ5SWQoZmluZFJlcGxhY2VJZCk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKCdGYWlsZWQgdG8gc3RhcnQgYmF0Y2ggZmluZCByZXBsYWNlOicsIHJlc3BvbnNlPy5tZXNzYWdlKTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG4gICAgICAgIGVycm9yOiAoZXJyb3IpID0+IHtcclxuICAgICAgICAgIHRoaXMubG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgdGhpcy5iYXRjaFByb2Nlc3NpbmcgPSBmYWxzZTtcclxuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIHN0YXJ0aW5nIGJhdGNoIGZpbmQgcmVwbGFjZTonLCBlcnJvcik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIG9uQXBwbHkoKTogdm9pZCB7XHJcbiAgICBjb25zdCBzZWFyY2hNb2RlID0gdGhpcy5zZWxlY3RlZE1vZGUudmFsdWUgYXMgJ3N0b3JlJyB8ICdjbHVzdGVyJztcclxuICAgIGxldCBzdG9yZXM6IFN0b3JlW10gPSBbXTtcclxuICAgIGxldCBzZWxlY3RlZENsdXN0ZXJzOiBBcnJheTx7IGlkOiBzdHJpbmc7IGxhYmVsOiBzdHJpbmcgfT4gfCB1bmRlZmluZWQgPSB1bmRlZmluZWQ7XHJcbiAgICBcclxuICAgIGlmIChzZWFyY2hNb2RlID09PSAnc3RvcmUnKSB7XHJcbiAgICAgIC8vIEZvciBzdG9yZSBtb2RlLCBjb252ZXJ0IHNlbGVjdGVkIHN0b3JlcyBkaXJlY3RseVxyXG4gICAgICBzdG9yZXMgPSB0aGlzLnNlbGVjdGVkU3RvcmVzLm1hcCgoc3RvcmVPcHRpb246IFN0b3JlT3B0aW9uKSA9PiAoe1xyXG4gICAgICAgIHN0b3JlTmFtZTogc3RvcmVPcHRpb24ubGFiZWwsXHJcbiAgICAgIH0pKTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIEZvciBjbHVzdGVyIG1vZGUsIHNhdmUgc2VsZWN0ZWQgY2x1c3RlcnMgYW5kIGV4dHJhY3QgYWxsIHN0b3JlcyBmcm9tIHNlbGVjdGVkIGNsdXN0ZXJzXHJcbiAgICAgIHNlbGVjdGVkQ2x1c3RlcnMgPSB0aGlzLnNlbGVjdGVkU3RvcmVzLm1hcCgoc3RvcmVPcHRpb246IFN0b3JlT3B0aW9uKSA9PiAoe1xyXG4gICAgICAgIGlkOiBzdG9yZU9wdGlvbi5pZCxcclxuICAgICAgICBsYWJlbDogc3RvcmVPcHRpb24ubGFiZWxcclxuICAgICAgfSkpO1xyXG4gICAgICBcclxuICAgICAgY29uc3Qgc2VsZWN0ZWRDbHVzdGVySWRzID0gbmV3IFNldCh0aGlzLnNlbGVjdGVkU3RvcmVzLm1hcChzID0+IHMuaWQpKTtcclxuICAgICAgc3RvcmVzID0gW107XHJcbiAgICAgIFxyXG4gICAgICAvLyBGaW5kIHNlbGVjdGVkIGNsdXN0ZXJzIGFuZCBleHRyYWN0IHRoZWlyIHN0b3Jlc1xyXG4gICAgICB0aGlzLmNsdXN0ZXJEYXRhLmZvckVhY2goKGNsdXN0ZXI6IGFueSkgPT4ge1xyXG4gICAgICAgIGlmIChzZWxlY3RlZENsdXN0ZXJJZHMuaGFzKGNsdXN0ZXIuaWQpICYmIGNsdXN0ZXIuc3RvcmVzICYmIEFycmF5LmlzQXJyYXkoY2x1c3Rlci5zdG9yZXMpKSB7XHJcbiAgICAgICAgICBjbHVzdGVyLnN0b3Jlcy5mb3JFYWNoKChzdG9yZTogYW55KSA9PiB7XHJcbiAgICAgICAgICAgIHN0b3Jlcy5wdXNoKHtcclxuICAgICAgICAgICAgICBzdG9yZU5hbWU6IHN0b3JlLmxhYmVsICxcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFVwZGF0ZSBkYXRhIHNlcnZpY2Ugd2l0aCBhbGwgY3VycmVudCB2YWx1ZXNcclxuICAgIGNvbnN0IHVwZGF0ZURhdGE6IGFueSA9IHtcclxuICAgICAgc2VhcmNoTW9kZTogc2VhcmNoTW9kZSxcclxuICAgICAgc3RvcmVzOiBzdG9yZXMsXHJcbiAgICAgIHN0b3JlQ291bnQ6IHN0b3Jlcy5sZW5ndGgsXHJcbiAgICAgIHRhcmdldDogdGhpcy50YXJnZXQudmFsdWUgYXMgJ21lcmNoJyB8ICd2bScgfCAnYm90aCcsXHJcbiAgICAgIGZpbmRQcm9tcHQ6IHRoaXMuZmluZFByb21wdC52YWx1ZSB8fCAnJyxcclxuICAgICAgcmVwbGFjZVByb21wdDogdGhpcy5yZXBsYWNlUHJvbXB0LnZhbHVlIHx8ICcnXHJcbiAgICB9O1xyXG5cclxuICAgIC8vIEFkZCBzZWxlY3RlZENsdXN0ZXJzIG9ubHkgd2hlbiBzZWFyY2hNb2RlIGlzIGNsdXN0ZXJcclxuICAgIGlmIChzZWFyY2hNb2RlID09PSAnY2x1c3RlcicgJiYgc2VsZWN0ZWRDbHVzdGVycykge1xyXG4gICAgICB1cGRhdGVEYXRhLnNlbGVjdGVkQ2x1c3RlcnMgPSBzZWxlY3RlZENsdXN0ZXJzO1xyXG4gICAgfVxyXG5cclxuICAgIHRoaXMuZGF0YVNlcnZpY2UudXBkYXRlRGF0YSh1cGRhdGVEYXRhKTtcclxuXHJcbiAgICAvLyBUcmlnZ2VyIHNhdmUgYXMgZHJhZnRcclxuICAgIHRoaXMuZGF0YVNlcnZpY2UudHJpZ2dlclNhdmVEcmFmdCgpO1xyXG4gIH1cclxuXHJcbiAgLy8gQ2FudmFzIHNldHVwIG1ldGhvZHNcclxuICBzZXR1cFpvb21IYW5kbGVycyhjYW52YXM6IGZhYnJpYy5DYW52YXMpOiB2b2lkIHtcclxuICAgIC8vIERpc2FibGUgb2JqZWN0IHNlbGVjdGlvbiBnbG9iYWxseVxyXG4gICAgY2FudmFzLnNlbGVjdGlvbiA9IGZhbHNlO1xyXG4gICAgXHJcbiAgICBjYW52YXMub24oXCJtb3VzZTp3aGVlbFwiLCAob3B0OiBmYWJyaWMuVEV2ZW50PFdoZWVsRXZlbnQ+KSA9PiB7XHJcbiAgICAgIGNvbnN0IGUgPSBvcHQuZTtcclxuICAgICAgaWYgKGUuY3RybEtleSB8fCBlLm1ldGFLZXkpIHtcclxuICAgICAgICBjb25zdCBkZWx0YSA9IGUuZGVsdGFZO1xyXG4gICAgICAgIGxldCB6b29tID0gY2FudmFzLmdldFpvb20oKTtcclxuICAgICAgICB6b29tICo9IDAuOTk1ICoqIGRlbHRhO1xyXG4gICAgICAgIHpvb20gPSBNYXRoLm1heCgwLjIsIE1hdGgubWluKHpvb20sIDMpKTtcclxuICAgICAgICBjYW52YXMuem9vbVRvUG9pbnQoeyB4OiBlLm9mZnNldFgsIHk6IGUub2Zmc2V0WSB9IGFzIGZhYnJpYy5Qb2ludCwgem9vbSk7XHJcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIGUuc3RvcFByb3BhZ2F0aW9uKCk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIGxldCBpc0RyYWdnaW5nID0gZmFsc2U7XHJcbiAgICBsZXQgbGFzdFBvc1ggPSAwO1xyXG4gICAgbGV0IGxhc3RQb3NZID0gMDtcclxuXHJcbiAgICBjYW52YXMub24oXCJtb3VzZTpkb3duXCIsIChvcHQ6IGFueSkgPT4ge1xyXG4gICAgICAvLyBIYW5kbGUgZml4dHVyZSBjbGlja3MgLSB1c2UgZmluZFRhcmdldCB0byBnZXQgdGhlIGFjdHVhbCBncm91cFxyXG4gICAgICBpZiAob3B0LnRhcmdldCkge1xyXG4gICAgICAgIGNvbnN0IG9iaiA9IG9wdC50YXJnZXQgYXMgYW55O1xyXG4gICAgICAgIC8vIENoZWNrIGlmIGl0J3MgYSBmaXh0dXJlIGdyb3VwIG9yIG5lc3RlZCB3aXRoaW4gb25lXHJcbiAgICAgICAgbGV0IGZpeHR1cmVHcm91cCA9IG9iajtcclxuICAgICAgICBcclxuICAgICAgICAvLyBUcmF2ZXJzZSB1cCB0byBmaW5kIHRoZSBmaXh0dXJlIGdyb3VwXHJcbiAgICAgICAgbGV0IGF0dGVtcHRzID0gMDtcclxuICAgICAgICB3aGlsZSAoZml4dHVyZUdyb3VwICYmICEoZml4dHVyZUdyb3VwIGFzIGFueSkuZml4dHVyZUlkICYmICEoZml4dHVyZUdyb3VwIGFzIGFueSkub2JqVHlwZSAmJiBhdHRlbXB0cyA8IDEwKSB7XHJcbiAgICAgICAgICBpZiAoKGZpeHR1cmVHcm91cCBhcyBhbnkpLnBhcmVudCkge1xyXG4gICAgICAgICAgICBmaXh0dXJlR3JvdXAgPSAoZml4dHVyZUdyb3VwIGFzIGFueSkucGFyZW50O1xyXG4gICAgICAgICAgfSBlbHNlIGlmICgoZml4dHVyZUdyb3VwIGFzIGFueSkuZ3JvdXApIHtcclxuICAgICAgICAgICAgZml4dHVyZUdyb3VwID0gKGZpeHR1cmVHcm91cCBhcyBhbnkpLmdyb3VwO1xyXG4gICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBhdHRlbXB0cysrO1xyXG4gICAgICAgIH1cclxuICAgICAgICBcclxuICAgICAgICAvLyBDaGVjayBpZiB3ZSBmb3VuZCBhIGZpeHR1cmUgZ3JvdXBcclxuICAgICAgICBpZiAoKGZpeHR1cmVHcm91cCBhcyBhbnkpLm9ialR5cGUgPT09IFwiZml4dHVyZVwiIHx8IChmaXh0dXJlR3JvdXAgYXMgYW55KS5maXh0dXJlSWQpIHtcclxuICAgICAgICAgIHRoaXMub25GaXh0dXJlQ2xpY2soZml4dHVyZUdyb3VwKTtcclxuICAgICAgICAgIGNhbnZhcy5zZXRBY3RpdmVPYmplY3QoZml4dHVyZUdyb3VwKTtcclxuICAgICAgICAgIGNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCk7XHJcbiAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG4gICAgICAgIFxyXG4gICAgICAgIC8vIEZvciBvdGhlciBlbGVtZW50cywganVzdCBoaWdobGlnaHRcclxuICAgICAgICBjYW52YXMuc2V0QWN0aXZlT2JqZWN0KG9wdC50YXJnZXQpO1xyXG4gICAgICAgIGNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCk7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgICB9XHJcbiAgICAgIFxyXG4gICAgICBpZiAoIW9wdC50YXJnZXQpIHtcclxuICAgICAgICBpc0RyYWdnaW5nID0gdHJ1ZTtcclxuICAgICAgICBjYW52YXMuc2VsZWN0aW9uID0gZmFsc2U7XHJcbiAgICAgICAgY29uc3QgZSA9IG9wdC5lO1xyXG4gICAgICAgIGxhc3RQb3NYID0gZS5jbGllbnRYO1xyXG4gICAgICAgIGxhc3RQb3NZID0gZS5jbGllbnRZO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBjYW52YXMub24oXCJtb3VzZTptb3ZlXCIsIChvcHQ6IGFueSkgPT4ge1xyXG4gICAgICBpZiAoaXNEcmFnZ2luZyAmJiBjYW52YXMudmlld3BvcnRUcmFuc2Zvcm0gJiYgIW9wdC50YXJnZXQpIHtcclxuICAgICAgICBjb25zdCBlID0gb3B0LmU7XHJcbiAgICAgICAgY29uc3QgdnB0ID0gY2FudmFzLnZpZXdwb3J0VHJhbnNmb3JtO1xyXG4gICAgICAgIHZwdFs0XSArPSBlLmNsaWVudFggLSBsYXN0UG9zWDtcclxuICAgICAgICB2cHRbNV0gKz0gZS5jbGllbnRZIC0gbGFzdFBvc1k7XHJcbiAgICAgICAgY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgICAgICBsYXN0UG9zWCA9IGUuY2xpZW50WDtcclxuICAgICAgICBsYXN0UG9zWSA9IGUuY2xpZW50WTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgY2FudmFzLm9uKFwibW91c2U6dXBcIiwgKCkgPT4ge1xyXG4gICAgICBpc0RyYWdnaW5nID0gZmFsc2U7XHJcbiAgICAgIGNhbnZhcy5zZWxlY3Rpb24gPSBmYWxzZTtcclxuICAgIH0pO1xyXG5cclxuICAgIC8vIFByZXZlbnQgYWxsIG9iamVjdCBtb3ZlbWVudCAod2FsbHMsIGVudHJhbmNlcywgZml4dHVyZXMsIG90aGVyIGVsZW1lbnRzKVxyXG4gICAgY2FudmFzLm9uKFwib2JqZWN0Om1vdmluZ1wiLCAoZTogYW55KSA9PiB7XHJcbiAgICAgIGNvbnN0IG9iaiA9IGUudGFyZ2V0O1xyXG4gICAgICBpZiAob2JqICYmIChvYmogYXMgYW55KS5vYmpUeXBlKSB7XHJcbiAgICAgICAgZS5lLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgZS5lLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgIC8vIFJlc2V0IHBvc2l0aW9uXHJcbiAgICAgICAgb2JqLnNldENvb3JkcygpO1xyXG4gICAgICAgIGNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIC8vIFByZXZlbnQgYWxsIG9iamVjdCBtb2RpZmljYXRpb25zIChzY2FsaW5nLCByb3RhdGluZywgZXRjLilcclxuICAgIGNhbnZhcy5vbihcIm9iamVjdDptb2RpZmllZFwiLCAoZTogYW55KSA9PiB7XHJcbiAgICAgIGNvbnN0IG9iaiA9IGUudGFyZ2V0O1xyXG4gICAgICBpZiAob2JqICYmIChvYmogYXMgYW55KS5vYmpUeXBlKSB7XHJcbiAgICAgICAgLy8gUmVzZXQgYW55IGNoYW5nZXNcclxuICAgICAgICBvYmouc2V0Q29vcmRzKCk7XHJcbiAgICAgICAgY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gUHJldmVudCBvYmplY3Qgc2NhbGluZ1xyXG4gICAgY2FudmFzLm9uKFwib2JqZWN0OnNjYWxpbmdcIiwgKGU6IGFueSkgPT4ge1xyXG4gICAgICBjb25zdCBvYmogPSBlLnRhcmdldDtcclxuICAgICAgaWYgKG9iaiAmJiAob2JqIGFzIGFueSkub2JqVHlwZSkge1xyXG4gICAgICAgIGUuZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgICAgIGUuZS5zdG9wUHJvcGFnYXRpb24oKTtcclxuICAgICAgICBvYmouc2V0Q29vcmRzKCk7XHJcbiAgICAgICAgY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gUHJldmVudCBvYmplY3Qgcm90YXRpbmdcclxuICAgIGNhbnZhcy5vbihcIm9iamVjdDpyb3RhdGluZ1wiLCAoZTogYW55KSA9PiB7XHJcbiAgICAgIGNvbnN0IG9iaiA9IGUudGFyZ2V0O1xyXG4gICAgICBpZiAob2JqICYmIChvYmogYXMgYW55KS5vYmpUeXBlKSB7XHJcbiAgICAgICAgZS5lLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICAgICAgZS5lLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICAgIG9iai5zZXRDb29yZHMoKTtcclxuICAgICAgICBjYW52YXMucmVxdWVzdFJlbmRlckFsbCgpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGdldFN0b3JlRml4dHVyZXMoc3RvcmVJZDogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICBpZiAoIXRoaXMucHJldmlld0NhbnZhcykge1xyXG4gICAgICBjb25zb2xlLndhcm4oJ0NhbnZhcyBub3QgaW5pdGlhbGl6ZWQnKTtcclxuICAgICAgdGhpcy5jYW52YXNMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmNhbnZhc0xvYWRpbmcgPSB0cnVlO1xyXG4gICAgdGhpcy5zdG9yZUJ1aWxkZXJTZXJ2aWNlLmdldFN0b3JlRml4dHVyZXMoeyBpZDogW3N0b3JlSWRdIH0pXHJcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcclxuICAgICAgLnN1YnNjcmliZSh7XHJcbiAgICAgICAgbmV4dDogYXN5bmMgKHJlczogYW55KSA9PiB7XHJcbiAgICAgICAgICBpZiAoIXJlcz8uZGF0YT8uWzBdPy5mbG9vcnM/Lmxlbmd0aCkge1xyXG4gICAgICAgICAgICB0aGlzLmNhbnZhc0xvYWRpbmcgPSBmYWxzZTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgfVxyXG5cclxuICAgICAgICAgIHRoaXMucGxhbm9EYXRhID0gc3RydWN0dXJlZENsb25lKHJlcy5kYXRhWzBdKTtcclxuICAgICAgICAgIHRoaXMuZmxvb3JEYXRhID0gc3RydWN0dXJlZENsb25lKHJlcy5kYXRhWzBdLmZsb29yc1swXSk7XHJcbiAgICAgICAgICBcclxuICAgICAgICAgIC8vIEFwcGx5IHN0b3JlZCBmaW5kUmVzcG9uc2VEYXRhIGFuZCByZXBsYWNlUmVzcG9uc2VEYXRhIGlmIGF2YWlsYWJsZSBmb3IgdGhpcyBzdG9yZVxyXG4gICAgICAgICAgLy8gVGhpcyB1cGRhdGVzIHRoZSBmbG9vckRhdGEgd2l0aCB0aGUgc3RvcmVkIGZpeHR1cmUgY2hhbmdlcyBhbmQgc2V0cyBzZWxlY3RlZEZpeHR1cmVEYXRhXHJcbiAgICAgICAgICB0aGlzLmFwcGx5U3RvcmVkUmVzcG9uc2VEYXRhKCk7XHJcbiAgICAgICAgICBcclxuICAgICAgICAgIC8vIE9wZW4gcGFuZWwgaWYgd2UgaGF2ZSBzZWxlY3RlZCBmaXh0dXJlIGRhdGFcclxuICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGVkRml4dHVyZURhdGEpIHtcclxuICAgICAgICAgICAgdGhpcy5pc1JpZ2h0UGFuZWxDb2xsYXBzZWQgPSBmYWxzZTtcclxuICAgICAgICAgIH1cclxuICAgICAgICAgIFxyXG4gICAgICAgICAgLy8gQ29sbGVjdCBhbGwgZml4dHVyZXMgZm9yIHByZXZpZXdcclxuICAgICAgICAgIHRoaXMuY29sbGVjdEFsbEZpeHR1cmVzKCk7XHJcbiAgICAgICAgICBcclxuICAgICAgICAgIC8vIEVuc3VyZSBjYW52YXMgaXMgaW5pdGlhbGl6ZWQgYmVmb3JlIHJlbmRlcmluZ1xyXG4gICAgICAgICAgaWYgKCF0aGlzLnByZXZpZXdDYW52YXMpIHtcclxuICAgICAgICAgICAgdGhpcy5pbml0aWFsaXplQ2FudmFzKCk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICBcclxuICAgICAgICAgIGlmICh0aGlzLnByZXZpZXdDYW52YXMpIHtcclxuICAgICAgICAgICAgLy8gUmVuZGVyIHRoZSBwbGFub2dyYW0gd2l0aCB0aGUgdXBkYXRlZCBmbG9vckRhdGEgKHdoaWNoIGluY2x1ZGVzIHN0b3JlZCByZXNwb25zZSBkYXRhKVxyXG4gICAgICAgICAgICBhd2FpdCB0aGlzLnJlbmRlckZsb29yKHRoaXMucHJldmlld0NhbnZhcyk7XHJcbiAgICAgICAgICAgIHRoaXMuY2FudmFzTG9hZGluZyA9IGZhbHNlO1xyXG5cclxuICAgICAgICAgICAgLy8gUmUtY2VudGVyIGFuZCBoaWdobGlnaHQgdGhlIHNlbGVjdGVkIGZpeHR1cmUgaWYgc3RvcmVkIHJlc3BvbnNlIGRhdGEgZXhpc3RzXHJcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICAgIGlmICh0aGlzLnByZXZpZXdDYW52YXNDb250YWluZXJSZWY/Lm5hdGl2ZUVsZW1lbnQpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMucmVzaXplQ2FudmFzKHRoaXMucHJldmlld0NhbnZhcywgdGhpcy5wcmV2aWV3Q2FudmFzQ29udGFpbmVyUmVmKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuZml0Q2FudmFzVG9MYXlvdXRBbmltYXRlZCh0aGlzLnByZXZpZXdDYW52YXMpO1xyXG4gICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAvLyBIaWdobGlnaHQgdGhlIGZpeHR1cmUgaWYgd2UgaGF2ZSBzdG9yZWQgcmVzcG9uc2UgZGF0YVxyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRGaXh0dXJlPy5maXh0dXJlSWQpIHtcclxuICAgICAgICAgICAgICAgICAgY29uc3QgYWN0aW9uRml4dHVyZSA9IHRoaXMucHJldmlld0NhbnZhcy5nZXRPYmplY3RzKCkuZmluZChcclxuICAgICAgICAgICAgICAgICAgICAob2JqOiBhbnkpID0+IG9iai5vYmpUeXBlID09PSBcImZpeHR1cmVcIiAmJiBvYmouZml4dHVyZUlkID09PSB0aGlzLnNlbGVjdGVkRml4dHVyZS5maXh0dXJlSWRcclxuICAgICAgICAgICAgICAgICAgKSBhcyBmYWJyaWMuR3JvdXAgfCB1bmRlZmluZWQ7XHJcbiAgICAgICAgICAgICAgICAgIGlmIChhY3Rpb25GaXh0dXJlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRGaXh0dXJlKHRoaXMucHJldmlld0NhbnZhcywgYWN0aW9uRml4dHVyZSwgZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgIC8vIEF1dG9tYXRpY2FsbHkgdHJpZ2dlciBmaW5kIGFuZCByZXBsYWNlIGlmIHByb21wdHMgYXJlIGF2YWlsYWJsZSBhbmQgc3RvcmUgZG9lc24ndCBoYXZlIHJlc3VsdHNcclxuICAgICAgICAgICAgICB0aGlzLmF1dG9GaW5kQW5kUmVwbGFjZUlmTmVlZGVkKCk7XHJcbiAgICAgICAgICAgIH0sIDMwMCk7XHJcbiAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLmNhbnZhc0xvYWRpbmcgPSBmYWxzZTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG4gICAgICAgIGVycm9yOiAoZXJyOiBhbnkpID0+IHtcclxuICAgICAgICAgIHRoaXMuY2FudmFzTG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZmV0Y2hpbmcgcGxhbm86JywgZXJyKTtcclxuICAgICAgICB9LFxyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIHJlc2l6ZUNhbnZhcyhjYW52YXM6IGZhYnJpYy5DYW52YXMsIGNvbnRhaW5lcjogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD4pOiB2b2lkIHtcclxuICAgIGNvbnN0IGNvbnRhaW5lckVsID0gY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICBjYW52YXMuc2V0RGltZW5zaW9ucyh7XHJcbiAgICAgIHdpZHRoOiBjb250YWluZXJFbC5jbGllbnRXaWR0aCxcclxuICAgICAgaGVpZ2h0OiBjb250YWluZXJFbC5jbGllbnRIZWlnaHQsXHJcbiAgICB9KTtcclxuICAgIGNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCk7XHJcbiAgfVxyXG5cclxuICBwcml2YXRlIGZpdENhbnZhc1RvTGF5b3V0QW5pbWF0ZWQoY2FudmFzOiBmYWJyaWMuQ2FudmFzKSB7XHJcbiAgICBpZiAoIWNhbnZhcykgcmV0dXJuO1xyXG4gICAgY29uc3QgYm91bmRzID0gdGhpcy5nZXRGdWxsTGF5b3V0Qm91bmRzKGNhbnZhcyk7XHJcbiAgICBpZiAoIWJvdW5kcy53aWR0aCB8fCAhYm91bmRzLmhlaWdodCkgcmV0dXJuO1xyXG5cclxuICAgIGNvbnN0IGNhbnZhc1cgPSBjYW52YXMuZ2V0V2lkdGgoKTtcclxuICAgIGNvbnN0IGNhbnZhc0ggPSBjYW52YXMuZ2V0SGVpZ2h0KCk7XHJcbiAgICBjb25zdCBzY2FsZVggPSBjYW52YXNXIC8gYm91bmRzLndpZHRoO1xyXG4gICAgY29uc3Qgc2NhbGVZID0gY2FudmFzSCAvIGJvdW5kcy5oZWlnaHQ7XHJcbiAgICBjb25zdCB0YXJnZXRab29tID0gTWF0aC5taW4oc2NhbGVYLCBzY2FsZVkpICogMC45O1xyXG5cclxuICAgIGNvbnN0IHRhcmdldFZwdCA9IFsuLi4oY2FudmFzLnZpZXdwb3J0VHJhbnNmb3JtIHx8IFsxLCAwLCAwLCAxLCAwLCAwXSldIGFzIGZhYnJpYy5UTWF0MkQ7XHJcbiAgICB0YXJnZXRWcHRbMF0gPSB0YXJnZXRab29tO1xyXG4gICAgdGFyZ2V0VnB0WzNdID0gdGFyZ2V0Wm9vbTtcclxuICAgIHRhcmdldFZwdFs0XSA9IGNhbnZhc1cgLyAyIC0gKGJvdW5kcy5sZWZ0ICsgYm91bmRzLndpZHRoIC8gMikgKiB0YXJnZXRab29tO1xyXG4gICAgdGFyZ2V0VnB0WzVdID0gY2FudmFzSCAvIDIgLSAoYm91bmRzLnRvcCArIGJvdW5kcy5oZWlnaHQgLyAyKSAqIHRhcmdldFpvb207XHJcblxyXG4gICAgY29uc3Qgc3RhcnRWcHQgPSBbLi4uY2FudmFzLnZpZXdwb3J0VHJhbnNmb3JtIV0gYXMgZmFicmljLlRNYXQyRDtcclxuXHJcbiAgICBmYWJyaWMudXRpbC5hbmltYXRlKHtcclxuICAgICAgc3RhcnRWYWx1ZTogMCxcclxuICAgICAgZW5kVmFsdWU6IDEsXHJcbiAgICAgIGR1cmF0aW9uOiAxMDAsXHJcbiAgICAgIGVhc2luZzogZmFicmljLnV0aWwuZWFzZS5lYXNlT3V0Q3ViaWMsXHJcbiAgICAgIG9uQ2hhbmdlOiAodmFsdWU6IG51bWJlcikgPT4ge1xyXG4gICAgICAgIGNvbnN0IHZwdCA9IGNhbnZhcy52aWV3cG9ydFRyYW5zZm9ybSE7XHJcbiAgICAgICAgdnB0WzBdID0gc3RhcnRWcHRbMF0gKyAodGFyZ2V0VnB0WzBdIC0gc3RhcnRWcHRbMF0pICogdmFsdWU7XHJcbiAgICAgICAgdnB0WzNdID0gc3RhcnRWcHRbM10gKyAodGFyZ2V0VnB0WzNdIC0gc3RhcnRWcHRbM10pICogdmFsdWU7XHJcbiAgICAgICAgdnB0WzRdID0gc3RhcnRWcHRbNF0gKyAodGFyZ2V0VnB0WzRdIC0gc3RhcnRWcHRbNF0pICogdmFsdWU7XHJcbiAgICAgICAgdnB0WzVdID0gc3RhcnRWcHRbNV0gKyAodGFyZ2V0VnB0WzVdIC0gc3RhcnRWcHRbNV0pICogdmFsdWU7XHJcbiAgICAgICAgY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgICAgfSxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZXRGdWxsTGF5b3V0Qm91bmRzKGNhbnZhczogZmFicmljLkNhbnZhcykge1xyXG4gICAgY29uc3Qgb2JqZWN0cyA9IGNhbnZhcy5nZXRPYmplY3RzKCk7XHJcbiAgICBpZiAoIW9iamVjdHMubGVuZ3RoKSByZXR1cm4geyBsZWZ0OiAwLCB0b3A6IDAsIHdpZHRoOiAwLCBoZWlnaHQ6IDAgfTtcclxuXHJcbiAgICBsZXQgbWluWCA9IEluZmluaXR5LCBtaW5ZID0gSW5maW5pdHksIG1heFggPSAtSW5maW5pdHksIG1heFkgPSAtSW5maW5pdHk7XHJcblxyXG4gICAgZm9yIChjb25zdCBvYmogb2Ygb2JqZWN0cykge1xyXG4gICAgICBjb25zdCByZWN0ID0gb2JqLmdldEJvdW5kaW5nUmVjdCgpO1xyXG4gICAgICBtaW5YID0gTWF0aC5taW4obWluWCwgcmVjdC5sZWZ0KTtcclxuICAgICAgbWluWSA9IE1hdGgubWluKG1pblksIHJlY3QudG9wKTtcclxuICAgICAgbWF4WCA9IE1hdGgubWF4KG1heFgsIHJlY3QubGVmdCArIHJlY3Qud2lkdGgpO1xyXG4gICAgICBtYXhZID0gTWF0aC5tYXgobWF4WSwgcmVjdC50b3AgKyByZWN0LmhlaWdodCk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIHsgbGVmdDogbWluWCwgdG9wOiBtaW5ZLCB3aWR0aDogbWF4WCAtIG1pblgsIGhlaWdodDogbWF4WSAtIG1pblkgfTtcclxuICB9XHJcblxyXG4gIGFzeW5jIHJlbmRlckZsb29yKGNhbnZhczogZmFicmljLkNhbnZhcykge1xyXG4gICAgYXdhaXQgdGhpcy5kcmF3SW5pdGlhbENvbnRlbnQoY2FudmFzKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGRyYXdJbml0aWFsQ29udGVudChjYW52YXM6IGZhYnJpYy5DYW52YXMpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgIGNhbnZhcy5jbGVhcigpO1xyXG4gICAgYXdhaXQgdGhpcy5kcmF3TGF5b3V0RWxlbWVudHMoY2FudmFzKTtcclxuICB9XHJcblxyXG4gIC8vIEF1dG9tYXRpY2FsbHkgdHJpZ2dlciBmaW5kIGFuZCByZXBsYWNlIGlmIHByb21wdHMgYXJlIGF2YWlsYWJsZSBhbmQgc3RvcmUgZG9lc24ndCBoYXZlIHJlc3VsdHNcclxuICBwcml2YXRlIGF1dG9GaW5kQW5kUmVwbGFjZUlmTmVlZGVkKCk6IHZvaWQge1xyXG4gICAgaWYgKCF0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3IHx8ICF0aGlzLmZpbmRSZXBsYWNlRGF0YSkge1xyXG4gICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ2hlY2sgaWYgcHJvbXB0cyBhcmUgYXZhaWxhYmxlXHJcbiAgICBjb25zdCBoYXNGaW5kUHJvbXB0ID0gdGhpcy5maW5kUmVwbGFjZURhdGEuZmluZFByb21wdCAmJiB0aGlzLmZpbmRSZXBsYWNlRGF0YS5maW5kUHJvbXB0LnRyaW0oKS5sZW5ndGggPiAwO1xyXG4gICAgY29uc3QgaGFzUmVwbGFjZVByb21wdCA9IHRoaXMuZmluZFJlcGxhY2VEYXRhLnJlcGxhY2VQcm9tcHQgJiYgdGhpcy5maW5kUmVwbGFjZURhdGEucmVwbGFjZVByb21wdC50cmltKCkubGVuZ3RoID4gMDtcclxuXHJcbiAgICBpZiAoIWhhc0ZpbmRQcm9tcHQgfHwgIWhhc1JlcGxhY2VQcm9tcHQpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIENoZWNrIGlmIGN1cnJlbnQgc3RvcmUgYWxyZWFkeSBoYXMgZmluZFJlc3BvbnNlRGF0YSBhbmQgcmVwbGFjZVJlc3BvbnNlRGF0YVxyXG4gICAgY29uc3Qgc3RvcmUgPSB0aGlzLmZpbmRSZXBsYWNlRGF0YS5zdG9yZXM/LmZpbmQoXHJcbiAgICAgIChzOiBTdG9yZSkgPT4gcy5zdG9yZU5hbWUgPT09IHRoaXMuc2VsZWN0ZWRTdG9yZUZvclByZXZpZXcuc3RvcmVOYW1lXHJcbiAgICApO1xyXG5cclxuICAgIC8vIElmIHN0b3JlIGFscmVhZHkgaGFzIGZpbmRSZXNwb25zZURhdGEsIHNraXAgYXV0by1maW5kIHRvIHByZXNlcnZlIHRoZSBoaWdobGlnaHRcclxuICAgIC8vIE9ubHkgYXV0by1ydW4gZmluZCBpZiBzdG9yZSBkb2Vzbid0IGFscmVhZHkgaGF2ZSBmaW5kUmVzcG9uc2VEYXRhXHJcbiAgICBpZiAoc3RvcmU/LmZpbmRSZXNwb25zZURhdGEpIHtcclxuICAgICAgLy8gSWYgc3RvcmUgaGFzIGZpbmRSZXNwb25zZURhdGEgYnV0IG5vdCByZXBsYWNlUmVzcG9uc2VEYXRhLCB3ZSBjb3VsZCBhdXRvLXJ1biByZXBsYWNlXHJcbiAgICAgIC8vIGJ1dCBmb3Igbm93LCB3ZSdsbCBza2lwIHRvIHByZXNlcnZlIHRoZSBoaWdobGlnaHQgdGhhdCB3YXMganVzdCBzZXRcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFNldCB0aGUgcHJvbXB0cyBpbiB0aGUgZm9ybSBjb250cm9scyBpZiBub3QgYWxyZWFkeSBzZXRcclxuICAgIGlmICghdGhpcy5maW5kUHJvbXB0LnZhbHVlICYmIHRoaXMuZmluZFJlcGxhY2VEYXRhLmZpbmRQcm9tcHQpIHtcclxuICAgICAgdGhpcy5maW5kUHJvbXB0LnNldFZhbHVlKHRoaXMuZmluZFJlcGxhY2VEYXRhLmZpbmRQcm9tcHQsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcclxuICAgIH1cclxuICAgIGlmICghdGhpcy5yZXBsYWNlUHJvbXB0LnZhbHVlICYmIHRoaXMuZmluZFJlcGxhY2VEYXRhLnJlcGxhY2VQcm9tcHQpIHtcclxuICAgICAgdGhpcy5yZXBsYWNlUHJvbXB0LnNldFZhbHVlKHRoaXMuZmluZFJlcGxhY2VEYXRhLnJlcGxhY2VQcm9tcHQsIHsgZW1pdEV2ZW50OiBmYWxzZSB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBBdXRvbWF0aWNhbGx5IHRyaWdnZXIgZmluZCBmaXJzdCwgdGhlbiByZXBsYWNlIGFmdGVyIGZpbmQgY29tcGxldGVzXHJcbiAgICB0aGlzLmF1dG9GaW5kKCk7XHJcbiAgfVxyXG5cclxuICAvLyBBdXRvIGZpbmQgLSB3aWxsIHRyaWdnZXIgcmVwbGFjZSBhZnRlciBjb21wbGV0aW9uXHJcbiAgcHJpdmF0ZSBhdXRvRmluZCgpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5maW5kUHJvbXB0LnZhbHVlIHx8ICF0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3KSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmZpbmRMb2FkaW5nID0gdHJ1ZTtcclxuICAgIHRoaXMuY2FudmFzTG9hZGluZyA9IHRydWU7XHJcbiAgICBjb25zdCBwYXlsb2FkID0ge1xyXG4gICAgICBzZWxlY3Rpb25Dcml0ZXJpYTogdGhpcy5maW5kUHJvbXB0LnZhbHVlLFxyXG4gICAgICBzdG9yZXM6IFt0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3LnN0b3JlTmFtZV0sXHJcbiAgICB9O1xyXG5cclxuICAgIHRoaXMuc3RvcmVCdWlsZGVyU2VydmljZS5maW5kRml4dHVyZShwYXlsb2FkKVxyXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXHJcbiAgICAgIC5zdWJzY3JpYmUoe1xyXG4gICAgICAgIG5leHQ6IChyZXM6IGFueSkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5maW5kTG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgdGhpcy5jYW52YXNMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICBpZiAocmVzLmNvZGUgPT09IDIwMCkge1xyXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgcmVzcG9uc2UgaW5kaWNhdGVzIFwiTk9UIEZPVU5EXCJcclxuICAgICAgICAgICAgaWYgKHJlcy5zdGF0dXMgPT09ICdzdWNjZXNzJyAmJiByZXMubWVzc2FnZSA9PT0gJ05PVCBGT1VORCcpIHtcclxuICAgICAgICAgICAgICB0aGlzLnRvYXN0U2VydmljZS5nZXRXYXJuaW5nVG9hc3QoJ05vIG1hdGNoaW5nIGZpeHR1cmUgZm91bmQgZm9yIHRoZSBnaXZlbiBwcm9tcHQnKTtcclxuICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHJlcy5kYXRhIGV4aXN0cyBiZWZvcmUgcHJvY2Vzc2luZ1xyXG4gICAgICAgICAgICBpZiAoIXJlcy5kYXRhKSB7XHJcbiAgICAgICAgICAgICAgdGhpcy50b2FzdFNlcnZpY2UuZ2V0V2FybmluZ1RvYXN0KCdObyBtYXRjaGluZyBmaXh0dXJlIGZvdW5kIGZvciB0aGUgZ2l2ZW4gcHJvbXB0Jyk7XHJcbiAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUFpUmVzcG9uc2VGaXh0dXJlKHJlcy5kYXRhKTtcclxuICAgICAgICAgICAgLy8gU3RvcmUgdGhlIGZvdW5kIGZpeHR1cmUgZm9yIHBvdGVudGlhbCByZXBsYWNlIG9wZXJhdGlvblxyXG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRml4dHVyZSA9IHtcclxuICAgICAgICAgICAgICBmaXh0dXJlSWQ6IHJlcy5kYXRhLl9pZCxcclxuICAgICAgICAgICAgICBmaXh0dXJlVHlwZTogcmVzLmRhdGEuZml4dHVyZVR5cGUsXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YSA9IHJlcy5kYXRhO1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gU2F2ZSBmaW5kUmVzcG9uc2VEYXRhIHRvIHRoZSBzcGVjaWZpYyBzdG9yZVxyXG4gICAgICAgICAgICB0aGlzLnNhdmVGaW5kUmVzcG9uc2VEYXRhKHJlcy5kYXRhKTtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIFJlbmRlciB0aGUgZmxvb3IgYW5kIHdhaXQgZm9yIGl0IHRvIGNvbXBsZXRlXHJcbiAgICAgICAgICAgIHRoaXMucmVuZGVyRmxvb3IodGhpcy5wcmV2aWV3Q2FudmFzKS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgICAvLyBXYWl0IGZvciBjYW52YXMgdG8gZnVsbHkgcmVuZGVyIGJlZm9yZSBoaWdobGlnaHRpbmdcclxuICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGFjdGlvbkZpeHR1cmUgPSB0aGlzLnByZXZpZXdDYW52YXMuZ2V0T2JqZWN0cygpLmZpbmQoXHJcbiAgICAgICAgICAgICAgICAgIChvYmo6IGFueSkgPT4gb2JqLm9ialR5cGUgPT09IFwiZml4dHVyZVwiICYmIG9iai5maXh0dXJlSWQgPT09IHJlcy5kYXRhLl9pZFxyXG4gICAgICAgICAgICAgICAgKSBhcyBmYWJyaWMuR3JvdXAgfCB1bmRlZmluZWQ7XHJcbiAgICAgICAgICAgICAgICBpZiAoYWN0aW9uRml4dHVyZSkge1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLmhpZ2hsaWdodEZpeHR1cmUodGhpcy5wcmV2aWV3Q2FudmFzLCBhY3Rpb25GaXh0dXJlLCB0cnVlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgLy8gQWZ0ZXIgZmluZCBjb21wbGV0ZXMsIGF1dG9tYXRpY2FsbHkgdHJpZ2dlciByZXBsYWNlXHJcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5hdXRvUmVwbGFjZSgpO1xyXG4gICAgICAgICAgICAgICAgfSwgNTAwKTtcclxuICAgICAgICAgICAgICB9LCAzMDApO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG4gICAgICAgIGVycm9yOiAoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmZpbmRMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICB0aGlzLmNhbnZhc0xvYWRpbmcgPSBmYWxzZTtcclxuICAgICAgICB9LFxyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIC8vIEF1dG8gcmVwbGFjZSAtIGNhbGxlZCBhZnRlciBhdXRvIGZpbmQgY29tcGxldGVzXHJcbiAgcHJpdmF0ZSBhdXRvUmVwbGFjZSgpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5yZXBsYWNlUHJvbXB0LnZhbHVlKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBDaGVjayBpZiBhIGZpeHR1cmUgaXMgc2VsZWN0ZWQgZm9yIHJlcGxhY2VtZW50XHJcbiAgICBpZiAoIXRoaXMuc2VsZWN0ZWRGaXh0dXJlPy5maXh0dXJlSWQgJiYgIXRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YT8uX2lkKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBVc2UgUmVwbGFjZSBBUEkgZm9yIHNlbGVjdGVkIGZpeHR1cmVcclxuICAgIGNvbnN0IGZpeHR1cmVJZCA9IHRoaXMuc2VsZWN0ZWRGaXh0dXJlPy5maXh0dXJlSWQgfHwgdGhpcy5zZWxlY3RlZEZpeHR1cmVEYXRhPy5faWQ7XHJcbiAgICBcclxuICAgIHRoaXMucmVwbGFjZUxvYWRpbmcgPSB0cnVlO1xyXG4gICAgdGhpcy5jYW52YXNMb2FkaW5nID0gdHJ1ZTtcclxuICAgIGNvbnN0IHBheWxvYWQgPSB7XHJcbiAgICAgIGZpeHR1cmVJZDogZml4dHVyZUlkLFxyXG4gICAgICB1cGRhdGVUeXBlOiB0aGlzLnRhcmdldC52YWx1ZSxcclxuICAgICAgdXBkYXRpb25Dcml0ZXJpYTogdGhpcy5yZXBsYWNlUHJvbXB0LnZhbHVlLFxyXG4gICAgfTtcclxuXHJcbiAgICAvLyBTdG9yZSB0aGUgb3JpZ2luYWwgZml4dHVyZSBiZWZvcmUgcmVwbGFjZSBmb3IgYmVmb3JlL2FmdGVyIGNvbXBhcmlzb25cclxuICAgIGNvbnN0IG9yaWdpbmFsRml4dHVyZSA9IHRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YSA/IHN0cnVjdHVyZWRDbG9uZSh0aGlzLnNlbGVjdGVkRml4dHVyZURhdGEpIDogbnVsbDtcclxuICAgIFxyXG4gICAgdGhpcy5zdG9yZUJ1aWxkZXJTZXJ2aWNlLnJlcGxhY2VGaXh0dXJlKHBheWxvYWQpXHJcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcclxuICAgICAgLnN1YnNjcmliZSh7XHJcbiAgICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XHJcbiAgICAgICAgICB0aGlzLnJlcGxhY2VMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICB0aGlzLmNhbnZhc0xvYWRpbmcgPSBmYWxzZTtcclxuICAgICAgICAgIGlmIChyZXMuY29kZSA9PT0gMjAwKSB7XHJcbiAgICAgICAgICAgIC8vIFN0b3JlIG9yaWdpbmFsIGZpeHR1cmUgZm9yIGJlZm9yZS9hZnRlciBjb21wYXJpc29uXHJcbiAgICAgICAgICAgIHRoaXMub3JpZ2luYWxGaXh0dXJlRGF0YSA9IG9yaWdpbmFsRml4dHVyZTtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlQWlSZXNwb25zZUZpeHR1cmUocmVzLmRhdGEpO1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gU2F2ZSByZXBsYWNlUmVzcG9uc2VEYXRhIHRvIHRoZSBzcGVjaWZpYyBzdG9yZVxyXG4gICAgICAgICAgICB0aGlzLnNhdmVSZXBsYWNlUmVzcG9uc2VEYXRhKHJlcy5kYXRhKTtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIFVwZGF0ZSBzZWxlY3RlZCBmaXh0dXJlIGRhdGEgKGFmdGVyIHJlcGxhY2UpXHJcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRGaXh0dXJlID0ge1xyXG4gICAgICAgICAgICAgIGZpeHR1cmVJZDogcmVzLmRhdGEuX2lkLFxyXG4gICAgICAgICAgICAgIGZpeHR1cmVUeXBlOiByZXMuZGF0YS5maXh0dXJlVHlwZSxcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEZpeHR1cmVEYXRhID0gcmVzLmRhdGE7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAvLyBSZW5kZXIgdGhlIGZsb29yIGFuZCB3YWl0IGZvciBpdCB0byBjb21wbGV0ZVxyXG4gICAgICAgICAgICB0aGlzLnJlbmRlckZsb29yKHRoaXMucHJldmlld0NhbnZhcykudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgICAgLy8gV2FpdCBmb3IgY2FudmFzIHRvIGZ1bGx5IHJlbmRlciBiZWZvcmUgaGlnaGxpZ2h0aW5nXHJcbiAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBhY3Rpb25GaXh0dXJlID0gdGhpcy5wcmV2aWV3Q2FudmFzLmdldE9iamVjdHMoKS5maW5kKFxyXG4gICAgICAgICAgICAgICAgICAob2JqOiBhbnkpID0+IG9iai5vYmpUeXBlID09PSBcImZpeHR1cmVcIiAmJiBvYmouZml4dHVyZUlkID09PSByZXMuZGF0YS5faWRcclxuICAgICAgICAgICAgICAgICkgYXMgZmFicmljLkdyb3VwIHwgdW5kZWZpbmVkO1xyXG4gICAgICAgICAgICAgICAgaWYgKGFjdGlvbkZpeHR1cmUpIHtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRGaXh0dXJlKHRoaXMucHJldmlld0NhbnZhcywgYWN0aW9uRml4dHVyZSwgdHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfSwgMzAwKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuICAgICAgICBlcnJvcjogKCkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5yZXBsYWNlTG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgdGhpcy5jYW52YXNMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgfSxcclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICAvLyBGaW5kIGFuZCBSZXBsYWNlIGJ1dHRvbiBoYW5kbGVyc1xyXG4gIG9uRmluZCgpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5maW5kUHJvbXB0LnZhbHVlIHx8ICF0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3KSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICB0aGlzLmZpbmRMb2FkaW5nID0gdHJ1ZTtcclxuICAgIHRoaXMuY2FudmFzTG9hZGluZyA9IHRydWU7XHJcbiAgICBjb25zdCBwYXlsb2FkID0ge1xyXG4gICAgICBzZWxlY3Rpb25Dcml0ZXJpYTogdGhpcy5maW5kUHJvbXB0LnZhbHVlLFxyXG4gICAgICBzdG9yZXM6IFt0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3LnN0b3JlTmFtZV0sXHJcbiAgICB9O1xyXG5cclxuICAgIHRoaXMuc3RvcmVCdWlsZGVyU2VydmljZS5maW5kRml4dHVyZShwYXlsb2FkKVxyXG4gICAgICAucGlwZSh0YWtlVW50aWwodGhpcy5kZXN0cm95JCkpXHJcbiAgICAgIC5zdWJzY3JpYmUoe1xyXG4gICAgICAgIG5leHQ6IChyZXM6IGFueSkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5maW5kTG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgdGhpcy5jYW52YXNMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICBpZiAocmVzLmNvZGUgPT09IDIwMCkge1xyXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgcmVzcG9uc2UgaW5kaWNhdGVzIFwiTk9UIEZPVU5EXCJcclxuICAgICAgICAgICAgaWYgKHJlcy5zdGF0dXMgPT09ICdzdWNjZXNzJyAmJiByZXMubWVzc2FnZSA9PT0gJ05PVCBGT1VORCcpIHtcclxuICAgICAgICAgICAgICB0aGlzLnRvYXN0U2VydmljZS5nZXRXYXJuaW5nVG9hc3QoJ05vIG1hdGNoaW5nIGZpeHR1cmUgZm91bmQgZm9yIHRoZSBnaXZlbiBwcm9tcHQnKTtcclxuICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHJlcy5kYXRhIGV4aXN0cyBiZWZvcmUgcHJvY2Vzc2luZ1xyXG4gICAgICAgICAgICBpZiAoIXJlcy5kYXRhKSB7XHJcbiAgICAgICAgICAgICAgdGhpcy50b2FzdFNlcnZpY2UuZ2V0V2FybmluZ1RvYXN0KCdObyBtYXRjaGluZyBmaXh0dXJlIGZvdW5kIGZvciB0aGUgZ2l2ZW4gcHJvbXB0Jyk7XHJcbiAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICB0aGlzLnVwZGF0ZUFpUmVzcG9uc2VGaXh0dXJlKHJlcy5kYXRhKTtcclxuICAgICAgICAgICAgLy8gU3RvcmUgdGhlIGZvdW5kIGZpeHR1cmUgZm9yIHBvdGVudGlhbCByZXBsYWNlIG9wZXJhdGlvblxyXG4gICAgICAgICAgICB0aGlzLnNlbGVjdGVkRml4dHVyZSA9IHtcclxuICAgICAgICAgICAgICBmaXh0dXJlSWQ6IHJlcy5kYXRhLl9pZCxcclxuICAgICAgICAgICAgICBmaXh0dXJlVHlwZTogcmVzLmRhdGEuZml4dHVyZVR5cGUsXHJcbiAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YSA9IHJlcy5kYXRhO1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gU2F2ZSBmaW5kUmVzcG9uc2VEYXRhIHRvIHRoZSBzcGVjaWZpYyBzdG9yZVxyXG4gICAgICAgICAgICB0aGlzLnNhdmVGaW5kUmVzcG9uc2VEYXRhKHJlcy5kYXRhKTtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIFJlbmRlciB0aGUgZmxvb3IgYW5kIHdhaXQgZm9yIGl0IHRvIGNvbXBsZXRlXHJcbiAgICAgICAgICAgIHRoaXMucmVuZGVyRmxvb3IodGhpcy5wcmV2aWV3Q2FudmFzKS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgICAvLyBXYWl0IGZvciBjYW52YXMgdG8gZnVsbHkgcmVuZGVyIGJlZm9yZSBoaWdobGlnaHRpbmdcclxuICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGFjdGlvbkZpeHR1cmUgPSB0aGlzLnByZXZpZXdDYW52YXMuZ2V0T2JqZWN0cygpLmZpbmQoXHJcbiAgICAgICAgICAgICAgICAgIChvYmo6IGFueSkgPT4gb2JqLm9ialR5cGUgPT09IFwiZml4dHVyZVwiICYmIG9iai5maXh0dXJlSWQgPT09IHJlcy5kYXRhLl9pZFxyXG4gICAgICAgICAgICAgICAgKSBhcyBmYWJyaWMuR3JvdXAgfCB1bmRlZmluZWQ7XHJcbiAgICAgICAgICAgICAgICBpZiAoYWN0aW9uRml4dHVyZSkge1xyXG4gICAgICAgICAgICAgICAgICB0aGlzLmhpZ2hsaWdodEZpeHR1cmUodGhpcy5wcmV2aWV3Q2FudmFzLCBhY3Rpb25GaXh0dXJlLCB0cnVlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9LCAzMDApO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgIH1cclxuICAgICAgICB9LFxyXG4gICAgICAgIGVycm9yOiAoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmZpbmRMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICB0aGlzLmNhbnZhc0xvYWRpbmcgPSBmYWxzZTtcclxuICAgICAgICB9LFxyXG4gICAgICB9KTtcclxuICB9XHJcblxyXG4gIG9uUmVwbGFjZSgpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5yZXBsYWNlUHJvbXB0LnZhbHVlKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBDaGVjayBpZiBhIGZpeHR1cmUgaXMgc2VsZWN0ZWQgZm9yIHJlcGxhY2VtZW50XHJcbiAgICBpZiAoIXRoaXMuc2VsZWN0ZWRGaXh0dXJlPy5maXh0dXJlSWQgJiYgIXRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YT8uX2lkKSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBVc2UgUmVwbGFjZSBBUEkgZm9yIHNlbGVjdGVkIGZpeHR1cmVcclxuICAgIGNvbnN0IGZpeHR1cmVJZCA9IHRoaXMuc2VsZWN0ZWRGaXh0dXJlPy5maXh0dXJlSWQgfHwgdGhpcy5zZWxlY3RlZEZpeHR1cmVEYXRhPy5faWQ7XHJcbiAgICBcclxuICAgIHRoaXMucmVwbGFjZUxvYWRpbmcgPSB0cnVlO1xyXG4gICAgdGhpcy5jYW52YXNMb2FkaW5nID0gdHJ1ZTtcclxuICAgIGNvbnN0IHBheWxvYWQgPSB7XHJcbiAgICAgIGZpeHR1cmVJZDogZml4dHVyZUlkLFxyXG4gICAgICB1cGRhdGVUeXBlOiB0aGlzLnRhcmdldC52YWx1ZSxcclxuICAgICAgdXBkYXRpb25Dcml0ZXJpYTogdGhpcy5yZXBsYWNlUHJvbXB0LnZhbHVlLFxyXG4gICAgfTtcclxuXHJcbiAgICAvLyBTdG9yZSB0aGUgb3JpZ2luYWwgZml4dHVyZSBiZWZvcmUgcmVwbGFjZSBmb3IgYmVmb3JlL2FmdGVyIGNvbXBhcmlzb25cclxuICAgIGNvbnN0IG9yaWdpbmFsRml4dHVyZSA9IHRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YSA/IHN0cnVjdHVyZWRDbG9uZSh0aGlzLnNlbGVjdGVkRml4dHVyZURhdGEpIDogbnVsbDtcclxuICAgIFxyXG4gICAgdGhpcy5zdG9yZUJ1aWxkZXJTZXJ2aWNlLnJlcGxhY2VGaXh0dXJlKHBheWxvYWQpXHJcbiAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSlcclxuICAgICAgLnN1YnNjcmliZSh7XHJcbiAgICAgICAgbmV4dDogKHJlczogYW55KSA9PiB7XHJcbiAgICAgICAgICB0aGlzLnJlcGxhY2VMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgICB0aGlzLmNhbnZhc0xvYWRpbmcgPSBmYWxzZTtcclxuICAgICAgICAgIGlmIChyZXMuY29kZSA9PT0gMjAwKSB7XHJcbiAgICAgICAgICAgIC8vIFN0b3JlIG9yaWdpbmFsIGZpeHR1cmUgZm9yIGJlZm9yZS9hZnRlciBjb21wYXJpc29uXHJcbiAgICAgICAgICAgIHRoaXMub3JpZ2luYWxGaXh0dXJlRGF0YSA9IG9yaWdpbmFsRml4dHVyZTtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIHRoaXMudXBkYXRlQWlSZXNwb25zZUZpeHR1cmUocmVzLmRhdGEpO1xyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgLy8gU2F2ZSByZXBsYWNlUmVzcG9uc2VEYXRhIHRvIHRoZSBzcGVjaWZpYyBzdG9yZVxyXG4gICAgICAgICAgICB0aGlzLnNhdmVSZXBsYWNlUmVzcG9uc2VEYXRhKHJlcy5kYXRhKTtcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIC8vIFVwZGF0ZSBzZWxlY3RlZCBmaXh0dXJlIGRhdGEgKGFmdGVyIHJlcGxhY2UpXHJcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0ZWRGaXh0dXJlID0ge1xyXG4gICAgICAgICAgICAgIGZpeHR1cmVJZDogcmVzLmRhdGEuX2lkLFxyXG4gICAgICAgICAgICAgIGZpeHR1cmVUeXBlOiByZXMuZGF0YS5maXh0dXJlVHlwZSxcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEZpeHR1cmVEYXRhID0gcmVzLmRhdGE7XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAvLyBSZW5kZXIgdGhlIGZsb29yIGFuZCB3YWl0IGZvciBpdCB0byBjb21wbGV0ZVxyXG4gICAgICAgICAgICB0aGlzLnJlbmRlckZsb29yKHRoaXMucHJldmlld0NhbnZhcykudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgICAgLy8gV2FpdCBmb3IgY2FudmFzIHRvIGZ1bGx5IHJlbmRlciBiZWZvcmUgaGlnaGxpZ2h0aW5nXHJcbiAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBhY3Rpb25GaXh0dXJlID0gdGhpcy5wcmV2aWV3Q2FudmFzLmdldE9iamVjdHMoKS5maW5kKFxyXG4gICAgICAgICAgICAgICAgICAob2JqOiBhbnkpID0+IG9iai5vYmpUeXBlID09PSBcImZpeHR1cmVcIiAmJiBvYmouZml4dHVyZUlkID09PSByZXMuZGF0YS5faWRcclxuICAgICAgICAgICAgICAgICkgYXMgZmFicmljLkdyb3VwIHwgdW5kZWZpbmVkO1xyXG4gICAgICAgICAgICAgICAgaWYgKGFjdGlvbkZpeHR1cmUpIHtcclxuICAgICAgICAgICAgICAgICAgdGhpcy5oaWdobGlnaHRGaXh0dXJlKHRoaXMucHJldmlld0NhbnZhcywgYWN0aW9uRml4dHVyZSwgdHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgfSwgMzAwKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfSxcclxuICAgICAgICBlcnJvcjogKCkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5yZXBsYWNlTG9hZGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgdGhpcy5jYW52YXNMb2FkaW5nID0gZmFsc2U7XHJcbiAgICAgICAgfSxcclxuICAgICAgfSk7XHJcbiAgfVxyXG5cclxuICAvLyBIZWxwZXIgbWV0aG9kIHRvIGdldCBmaW5kUmVzcG9uc2VEYXRhIGZvciBjdXJyZW50IHN0b3JlXHJcbiAgZ2V0Q3VycmVudFN0b3JlRmluZFJlc3BvbnNlRGF0YSgpOiBzdHJpbmcgfCBudWxsIHtcclxuICAgIGlmICghdGhpcy5maW5kUmVwbGFjZURhdGE/LnN0b3JlcyB8fCAhdGhpcy5zZWxlY3RlZFN0b3JlRm9yUHJldmlldykge1xyXG4gICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuICAgIGNvbnN0IHN0b3JlID0gdGhpcy5maW5kUmVwbGFjZURhdGEuc3RvcmVzLmZpbmQoXHJcbiAgICAgIChzOiBTdG9yZSkgPT4gcy5zdG9yZU5hbWUgPT09IHRoaXMuc2VsZWN0ZWRTdG9yZUZvclByZXZpZXcuc3RvcmVOYW1lXHJcbiAgICApO1xyXG4gICAgcmV0dXJuIHN0b3JlPy5maW5kUmVzcG9uc2VEYXRhIHx8IG51bGw7XHJcbiAgfVxyXG5cclxuICAvLyBTYXZlIGZpbmRSZXNwb25zZURhdGEgdG8gc3BlY2lmaWMgc3RvcmUgYW5kIHRyaWdnZXIgc2F2ZSBhcyBkcmFmdFxyXG4gIHByaXZhdGUgc2F2ZUZpbmRSZXNwb25zZURhdGEocmVzcG9uc2VEYXRhOiBhbnkpOiB2b2lkIHtcclxuICAgIGlmICghdGhpcy5maW5kUmVwbGFjZURhdGEgfHwgIXRoaXMuc2VsZWN0ZWRTdG9yZUZvclByZXZpZXcpIHtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHVwZGF0ZWRTdG9yZXMgPSAodGhpcy5maW5kUmVwbGFjZURhdGEuc3RvcmVzIHx8IFtdKS5tYXAoKHN0b3JlOiBTdG9yZSkgPT4ge1xyXG4gICAgICBpZiAoc3RvcmUuc3RvcmVOYW1lID09PSB0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3LnN0b3JlTmFtZSkge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAuLi5zdG9yZSxcclxuICAgICAgICAgIGZpbmRSZXNwb25zZURhdGE6IHJlc3BvbnNlRGF0YT8uX2lkXHJcbiAgICAgICAgfTtcclxuICAgICAgfVxyXG4gICAgICByZXR1cm4gc3RvcmU7XHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyBVcGRhdGUgbG9jYWwgZmluZFJlcGxhY2VEYXRhIGltbWVkaWF0ZWx5XHJcbiAgICB0aGlzLmZpbmRSZXBsYWNlRGF0YSA9IHtcclxuICAgICAgLi4udGhpcy5maW5kUmVwbGFjZURhdGEsXHJcbiAgICAgIHN0b3JlczogdXBkYXRlZFN0b3Jlc1xyXG4gICAgfTtcclxuXHJcbiAgICAvLyBVcGRhdGUgdGhlIGRhdGEgc2VydmljZVxyXG4gICAgdGhpcy5kYXRhU2VydmljZS51cGRhdGVEYXRhKHtcclxuICAgICAgc3RvcmVzOiB1cGRhdGVkU3RvcmVzXHJcbiAgICB9KTtcclxuXHJcbiAgICAvLyBUcmlnZ2VyIHNhdmUgYXMgZHJhZnRcclxuICAgIHRoaXMuZGF0YVNlcnZpY2UudHJpZ2dlclNhdmVEcmFmdCgpO1xyXG4gIH1cclxuXHJcbiAgLy8gU2F2ZSByZXBsYWNlUmVzcG9uc2VEYXRhIHRvIHNwZWNpZmljIHN0b3JlIGFuZCB0cmlnZ2VyIHNhdmUgYXMgZHJhZnRcclxuICAvLyBPbmx5IHNhdmVzIHZtQ29uZmlnIGFuZC9vciBzaGVsZkNvbmZpZyBiYXNlZCBvbiB0YXJnZXRcclxuICBwcml2YXRlIHNhdmVSZXBsYWNlUmVzcG9uc2VEYXRhKHJlc3BvbnNlRGF0YTogYW55KTogdm9pZCB7XHJcbiAgICBpZiAoIXRoaXMuZmluZFJlcGxhY2VEYXRhIHx8ICF0aGlzLnNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3KSB7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB0YXJnZXQgPSB0aGlzLnRhcmdldC52YWx1ZSBhcyAnbWVyY2gnIHwgJ3ZtJyB8ICdib3RoJztcclxuICAgIGNvbnN0IHJlcGxhY2VEYXRhOiB7IHZtQ29uZmlnPzogYW55W107IHNoZWxmQ29uZmlnPzogYW55W10gfSA9IHt9O1xyXG5cclxuICAgIC8vIEV4dHJhY3Qgb25seSB0aGUgcmVsZXZhbnQgY29uZmlncyBiYXNlZCBvbiB0YXJnZXRcclxuICAgIGlmICh0YXJnZXQgPT09ICd2bScgfHwgdGFyZ2V0ID09PSAnYm90aCcpIHtcclxuICAgICAgaWYgKHJlc3BvbnNlRGF0YT8udm1Db25maWcpIHtcclxuICAgICAgICByZXBsYWNlRGF0YS52bUNvbmZpZyA9IHJlc3BvbnNlRGF0YS52bUNvbmZpZztcclxuICAgICAgfVxyXG4gICAgfVxyXG4gICAgXHJcbiAgICBpZiAodGFyZ2V0ID09PSAnbWVyY2gnIHx8IHRhcmdldCA9PT0gJ2JvdGgnKSB7XHJcbiAgICAgIGlmIChyZXNwb25zZURhdGE/LnNoZWxmQ29uZmlnKSB7XHJcbiAgICAgICAgcmVwbGFjZURhdGEuc2hlbGZDb25maWcgPSByZXNwb25zZURhdGEuc2hlbGZDb25maWc7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCB1cGRhdGVkU3RvcmVzID0gKHRoaXMuZmluZFJlcGxhY2VEYXRhLnN0b3JlcyB8fCBbXSkubWFwKChzdG9yZTogU3RvcmUpID0+IHtcclxuICAgICAgaWYgKHN0b3JlLnN0b3JlTmFtZSA9PT0gdGhpcy5zZWxlY3RlZFN0b3JlRm9yUHJldmlldy5zdG9yZU5hbWUpIHtcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgLi4uc3RvcmUsXHJcbiAgICAgICAgICByZXBsYWNlUmVzcG9uc2VEYXRhOiByZXBsYWNlRGF0YVxyXG4gICAgICAgIH07XHJcbiAgICAgIH1cclxuICAgICAgcmV0dXJuIHN0b3JlO1xyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gVXBkYXRlIGxvY2FsIGZpbmRSZXBsYWNlRGF0YSBpbW1lZGlhdGVseVxyXG4gICAgdGhpcy5maW5kUmVwbGFjZURhdGEgPSB7XHJcbiAgICAgIC4uLnRoaXMuZmluZFJlcGxhY2VEYXRhLFxyXG4gICAgICBzdG9yZXM6IHVwZGF0ZWRTdG9yZXNcclxuICAgIH07XHJcblxyXG4gICAgLy8gVXBkYXRlIHRoZSBkYXRhIHNlcnZpY2VcclxuICAgIHRoaXMuZGF0YVNlcnZpY2UudXBkYXRlRGF0YSh7XHJcbiAgICAgIHN0b3JlczogdXBkYXRlZFN0b3Jlc1xyXG4gICAgfSk7XHJcblxyXG4gICAgLy8gVHJpZ2dlciBzYXZlIGFzIGRyYWZ0XHJcbiAgICB0aGlzLmRhdGFTZXJ2aWNlLnRyaWdnZXJTYXZlRHJhZnQoKTtcclxuICB9XHJcblxyXG4gIHVwZGF0ZUFpUmVzcG9uc2VGaXh0dXJlKGZpeHR1cmU6IGFueSkge1xyXG4gICAgbGV0IG1hdGNoRm91bmQgPSBmYWxzZTtcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5mbG9vckRhdGEubGF5b3V0UG9seWdvbi5sZW5ndGg7IGkrKykge1xyXG4gICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5mbG9vckRhdGEubGF5b3V0UG9seWdvbltpXTtcclxuICAgICAgaWYgKGVsZW1lbnQuZWxlbWVudFR5cGUgPT09ICd3YWxsJyAmJiBBcnJheS5pc0FycmF5KGVsZW1lbnQuZml4dHVyZXMpKSB7XHJcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBlbGVtZW50LmZpeHR1cmVzLmxlbmd0aDsgaisrKSB7XHJcbiAgICAgICAgICBjb25zdCBmeCA9IGVsZW1lbnQuZml4dHVyZXNbal07XHJcbiAgICAgICAgICBpZiAoZnguX2lkID09PSBmaXh0dXJlLl9pZCkge1xyXG4gICAgICAgICAgICAvLyBQcmVzZXJ2ZSBleGlzdGluZyB2bUNvbmZpZyBpZiB0aGUgbmV3IGZpeHR1cmUgZG9lc24ndCBoYXZlIGl0XHJcbiAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nVm1Db25maWcgPSBmeC52bUNvbmZpZyB8fCBbXTtcclxuICAgICAgICAgICAgY29uc3QgdXBkYXRlZEZpeHR1cmUgPSB7IFxyXG4gICAgICAgICAgICAgIC4uLmZpeHR1cmUsXHJcbiAgICAgICAgICAgICAgLy8gUHJlc2VydmUgdm1Db25maWcgZnJvbSBleGlzdGluZyBmaXh0dXJlIGlmIG5ldyBmaXh0dXJlIGRvZXNuJ3QgaGF2ZSBpdFxyXG4gICAgICAgICAgICAgIHZtQ29uZmlnOiBmaXh0dXJlLnZtQ29uZmlnIHx8IGV4aXN0aW5nVm1Db25maWdcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgdGhpcy5mbG9vckRhdGEubGF5b3V0UG9seWdvbltpXS5maXh0dXJlc1tqXSA9IHVwZGF0ZWRGaXh0dXJlO1xyXG4gICAgICAgICAgICBtYXRjaEZvdW5kID0gdHJ1ZTtcclxuICAgICAgICAgICAgdGhpcy5zZWxlY3RlZEZpeHR1cmUgPSB1cGRhdGVkRml4dHVyZTtcclxuICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKG1hdGNoRm91bmQpIHJldHVybjtcclxuXHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuZmxvb3JEYXRhPy5jZW50ZXJGaXh0dXJlLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGNvbnN0IGZ4ID0gdGhpcy5mbG9vckRhdGE/LmNlbnRlckZpeHR1cmVbaV07XHJcbiAgICAgIGlmIChmeC5faWQgPT09IGZpeHR1cmUuX2lkKSB7XHJcbiAgICAgICAgLy8gUHJlc2VydmUgZXhpc3Rpbmcgdm1Db25maWcgaWYgdGhlIG5ldyBmaXh0dXJlIGRvZXNuJ3QgaGF2ZSBpdFxyXG4gICAgICAgIGNvbnN0IGV4aXN0aW5nVm1Db25maWcgPSBmeC52bUNvbmZpZyB8fCBbXTtcclxuICAgICAgICBjb25zdCB1cGRhdGVkRml4dHVyZSA9IHsgXHJcbiAgICAgICAgICAuLi5maXh0dXJlLFxyXG4gICAgICAgICAgLy8gUHJlc2VydmUgdm1Db25maWcgZnJvbSBleGlzdGluZyBmaXh0dXJlIGlmIG5ldyBmaXh0dXJlIGRvZXNuJ3QgaGF2ZSBpdFxyXG4gICAgICAgICAgdm1Db25maWc6IGZpeHR1cmUudm1Db25maWcgfHwgZXhpc3RpbmdWbUNvbmZpZ1xyXG4gICAgICAgIH07XHJcbiAgICAgICAgdGhpcy5mbG9vckRhdGEuY2VudGVyRml4dHVyZVtpXSA9IHVwZGF0ZWRGaXh0dXJlO1xyXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRGaXh0dXJlID0gdXBkYXRlZEZpeHR1cmU7XHJcbiAgICAgICAgYnJlYWs7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGhpZ2hsaWdodEZpeHR1cmUoY2FudmFzOiBmYWJyaWMuQ2FudmFzLCBncm91cDogYW55LCBibGluazogYm9vbGVhbiA9IGZhbHNlKSB7XHJcbiAgICB0aGlzLnJlbW92ZUhpZ2hsaWdodChjYW52YXMpO1xyXG4gICAgdGhpcy5jYW5jZWxIaWdobGlnaHRCbGluayA9IGZhbHNlO1xyXG5cclxuICAgIGNvbnN0IGNlbnRlciA9IGdyb3VwLmdldENlbnRlclBvaW50KCk7XHJcbiAgICBjb25zdCByZWFsV2lkdGggPSBncm91cC53aWR0aCEgKiBncm91cC5zY2FsZVghO1xyXG4gICAgY29uc3QgcmVhbEhlaWdodCA9IGdyb3VwLmhlaWdodCEgKiBncm91cC5zY2FsZVkhO1xyXG5cclxuICAgIGNvbnN0IHJlY3QgPSBuZXcgZmFicmljLlJlY3Qoe1xyXG4gICAgICBsZWZ0OiBjZW50ZXIueCxcclxuICAgICAgdG9wOiBjZW50ZXIueSxcclxuICAgICAgd2lkdGg6IHJlYWxXaWR0aCArIDgsXHJcbiAgICAgIGhlaWdodDogcmVhbEhlaWdodCArIDgsXHJcbiAgICAgIHJ4OiA1LFxyXG4gICAgICByeTogNSxcclxuICAgICAgc3Ryb2tlOiBcIiMwMGFhZmZcIixcclxuICAgICAgc3Ryb2tlV2lkdGg6IDMsXHJcbiAgICAgIGZpbGw6IFwidHJhbnNwYXJlbnRcIixcclxuICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgIGV2ZW50ZWQ6IGZhbHNlLFxyXG4gICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICBhbmdsZTogZ3JvdXAuYW5nbGUgfHwgMCxcclxuICAgICAgb3BhY2l0eTogYmxpbmsgPyAwIDogMSxcclxuICAgIH0pO1xyXG5cclxuICAgIChyZWN0IGFzIGFueSkuZGF0YSA9IHsgdHlwZTogXCJmaXh0dXJlLWhpZ2hsaWdodFwiIH07XHJcbiAgICBjYW52YXMuYWRkKHJlY3QpO1xyXG4gICAgY2FudmFzLm1vdmVPYmplY3RUbyhyZWN0LCBjYW52YXMuZ2V0T2JqZWN0cygpLmxlbmd0aCAtIDEpO1xyXG4gICAgY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgIHRoaXMuYWN0aXZlSGlnaGxpZ2h0ID0gcmVjdDtcclxuXHJcbiAgICBpZiAoIWJsaW5rKSByZXR1cm47XHJcblxyXG4gICAgbGV0IGN5Y2xlcyA9IDA7XHJcbiAgICBjb25zdCBibGlua09uY2UgPSAoKSA9PiB7XHJcbiAgICAgIGlmICh0aGlzLmNhbmNlbEhpZ2hsaWdodEJsaW5rKSB7XHJcbiAgICAgICAgdGhpcy5yZW1vdmVIaWdobGlnaHQoY2FudmFzKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICAgIH1cclxuICAgICAgcmVjdC5hbmltYXRlKHsgb3BhY2l0eTogMSB9LCB7XHJcbiAgICAgICAgZHVyYXRpb246IDIwMCxcclxuICAgICAgICBvbkNoYW5nZTogKCkgPT4gY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKSxcclxuICAgICAgICBvbkNvbXBsZXRlOiAoKSA9PiB7XHJcbiAgICAgICAgICBpZiAodGhpcy5jYW5jZWxIaWdobGlnaHRCbGluaykge1xyXG4gICAgICAgICAgICB0aGlzLnJlbW92ZUhpZ2hsaWdodChjYW52YXMpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICB9XHJcbiAgICAgICAgICByZWN0LmFuaW1hdGUoeyBvcGFjaXR5OiAwIH0sIHtcclxuICAgICAgICAgICAgZHVyYXRpb246IDIwMCxcclxuICAgICAgICAgICAgb25DaGFuZ2U6ICgpID0+IGNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCksXHJcbiAgICAgICAgICAgIG9uQ29tcGxldGU6ICgpID0+IHtcclxuICAgICAgICAgICAgICBpZiAodGhpcy5jYW5jZWxIaWdobGlnaHRCbGluaykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVIaWdobGlnaHQoY2FudmFzKTtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgY3ljbGVzKys7XHJcbiAgICAgICAgICAgICAgaWYgKGN5Y2xlcyA8IDIwKSB7XHJcbiAgICAgICAgICAgICAgICBibGlua09uY2UoKTtcclxuICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNhbmNlbEhpZ2hsaWdodEJsaW5rKSB7XHJcbiAgICAgICAgICAgICAgICAgIHJlY3Quc2V0KHsgb3BhY2l0eTogMSB9KTtcclxuICAgICAgICAgICAgICAgICAgY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICB9KTtcclxuICAgICAgICB9LFxyXG4gICAgICB9KTtcclxuICAgIH07XHJcbiAgICBibGlua09uY2UoKTtcclxuICB9XHJcblxyXG4gIHJlbW92ZUhpZ2hsaWdodChjYW52YXM6IGZhYnJpYy5DYW52YXMpIHtcclxuICAgIHRoaXMuY2FuY2VsSGlnaGxpZ2h0QmxpbmsgPSB0cnVlO1xyXG4gICAgY2FudmFzLmdldE9iamVjdHMoKS5mb3JFYWNoKChvYmopID0+IHtcclxuICAgICAgaWYgKChvYmogYXMgYW55KS5kYXRhPy50eXBlID09PSBcImZpeHR1cmUtaGlnaGxpZ2h0XCIpIHtcclxuICAgICAgICBjYW52YXMucmVtb3ZlKG9iaik7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG4gICAgdGhpcy5hY3RpdmVIaWdobGlnaHQgPSBudWxsO1xyXG4gICAgY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICB9XHJcblxyXG4gIC8vIFBsYW5vZ3JhbSByZW5kZXJpbmcgbWV0aG9kcyAoc2ltcGxpZmllZCB2ZXJzaW9ucyBmcm9tIGNvbGxlY3Rpb24tdXBkYXRlLWFpKVxyXG4gIHRvUGl4ZWxzKHZhbHVlOiBudW1iZXIsIHVuaXQ6IHN0cmluZywgZHBpID0gMi44KSB7XHJcbiAgICBsZXQgcGl4ZWxzOiBudW1iZXI7XHJcbiAgICBpZiAodW5pdCA9PT0gXCJtbVwiKSB7XHJcbiAgICAgIHBpeGVscyA9ICh2YWx1ZSAvIDI1LjQpICogZHBpO1xyXG4gICAgfSBlbHNlIGlmICh1bml0ID09PSBcImZ0XCIpIHtcclxuICAgICAgcGl4ZWxzID0gdmFsdWUgKiAxMiAqIGRwaTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuc3VwcG9ydGVkIHVuaXQuIFVzZSAnbW0nIG9yICdmdCcuXCIpO1xyXG4gICAgfVxyXG4gICAgcmV0dXJuIE51bWJlcihwaXhlbHMudG9GaXhlZCg0KSk7XHJcbiAgfVxyXG5cclxuICBhc3luYyBkcmF3TGF5b3V0RWxlbWVudHMoY2FudmFzOiBmYWJyaWMuQ2FudmFzKSB7XHJcbiAgICBpZiAoIXRoaXMuZmxvb3JEYXRhKSByZXR1cm47XHJcbiAgICBcclxuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCB0aGlzLmZsb29yRGF0YS5sYXlvdXRQb2x5Z29uLmxlbmd0aDsgaW5kZXgrKykge1xyXG4gICAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5mbG9vckRhdGEubGF5b3V0UG9seWdvbltpbmRleF07XHJcbiAgICAgIGxldCB3YWxsO1xyXG5cclxuICAgICAgZWxlbWVudC5yZWxhdGl2ZVBvc2l0aW9uID8/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/IGZpeHR1cmVEYXRhLmZvb3Rlci5sYWJlbCA6IFwiXCJ9YCxcclxuICAgICAge1xyXG4gICAgICAgIGxlZnQ6IG1pZFggKyBtaWRXaWR0aCAvIDIsXHJcbiAgICAgICAgdG9wOiBsYXN0Qm94WSArIGJveEhlaWdodCAvIDIsXHJcbiAgICAgICAgZm9udFNpemU6IDUsXHJcbiAgICAgICAgZm9udEZhbWlseTogXCJJbnRlclwiLFxyXG4gICAgICAgIGZvbnRXZWlnaHQ6IFwiNjAwXCIsXHJcbiAgICAgICAgZmlsbDogXCIjMTAxODI4XCIsXHJcbiAgICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICAgIHRleHRBbGlnbjogXCJjZW50ZXJcIixcclxuICAgICAgICB3aWR0aDogbWlkV2lkdGgsXHJcbiAgICAgICAgaGVpZ3RoOiBib3hIZWlnaHQsXHJcbiAgICAgIH1cclxuICAgICk7XHJcblxyXG4gICAgY29uc3QgYm90dG9tV2lkdGggPSB3aWR0aCAvIDEuMDU7XHJcbiAgICBjb25zdCBib3R0b21IZWlnaHQgPSAoMyAvIDEwMCkgKiBoZWlnaHQ7XHJcbiAgICBjb25zdCBib3R0b21YID0geCArICh3aWR0aCAtIGJvdHRvbVdpZHRoKSAvIDI7XHJcbiAgICBjb25zdCBib3R0b21ZID0gbWlkWSArIG1pZEhlaWdodCArIHRoaXMudmVydGljYWxNYXJnaW47XHJcblxyXG4gICAgY29uc3QgYm90dG9tQ29udGFpbmVyID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgbGVmdDogYm90dG9tWCxcclxuICAgICAgdG9wOiBib3R0b21ZLFxyXG4gICAgICB3aWR0aDogYm90dG9tV2lkdGgsXHJcbiAgICAgIGhlaWdodDogYm90dG9tSGVpZ2h0LFxyXG4gICAgICByeDogcmFkaXVzLFxyXG4gICAgICByeTogcmFkaXVzLFxyXG4gICAgICBzdHJva2U6IFwidHJhbnNwYXJlbnRcIixcclxuICAgICAgZmlsbDogXCJ0cmFuc3BhcmVudFwiLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgYm90dG9tVGV4dENvbnRlbnQgPSBuZXcgZmFicmljLlRleHRib3goXHJcbiAgICAgIGBTaGVsdmVzIC0gJHtmaXh0dXJlRGF0YS5zaGVsZkNvbmZpZz8ubGVuZ3RofSAuIFByb2R1Y3RzIC0gICR7Zml4dHVyZURhdGEuZml4dHVyZUNhcGFjaXR5fSAuIFZNIC0gJHtmaXh0dXJlRGF0YS52bUNvbmZpZz8ubGVuZ3RofWAsXHJcbiAgICAgIHtcclxuICAgICAgICBsZWZ0OiBib3R0b21YICsgYm90dG9tV2lkdGggLyAyLFxyXG4gICAgICAgIHRvcDogYm90dG9tWSArIGJvdHRvbUhlaWdodCAvIDIsXHJcbiAgICAgICAgZm9udFNpemU6IDUsXHJcbiAgICAgICAgZm9udEZhbWlseTogXCJJbnRlclwiLFxyXG4gICAgICAgIGZvbnRXZWlnaHQ6IFwiNTAwXCIsXHJcbiAgICAgICAgZmlsbDogXCIjMzMzXCIsXHJcbiAgICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICAgIHRleHRBbGlnbjogXCJjZW50ZXJcIixcclxuICAgICAgICB3aWR0aDogYm90dG9tV2lkdGgsXHJcbiAgICAgICAgaGVpZ2h0OiBib3R0b21IZWlnaHQsXHJcbiAgICAgIH1cclxuICAgICk7XHJcblxyXG5cclxuICAgIGNvbnN0IGZpeHR1cmVHcm91cCA9IG5ldyBmYWJyaWMuR3JvdXAoXHJcbiAgICAgIFtcclxuICAgICAgICBtYWluQ29udGFpbmVyLFxyXG4gICAgICAgIHRvcENvbnRhaW5lcixcclxuICAgICAgICBpbm5lclRvcEJveCxcclxuICAgICAgICB0b3BUZXh0LFxyXG4gICAgICAgIGlubmVyQm90dG9tQm94LFxyXG4gICAgICAgIGJvdHRvbVRleHQsXHJcbiAgICAgICAgbWlkQ29udGFpbmVyLFxyXG4gICAgICAgIGZpcnN0Qm94LFxyXG4gICAgICAgIGZpcnN0Qm94VGV4dCxcclxuICAgICAgICAuLi5zaGVsdmVzLFxyXG4gICAgICAgIGxhc3RCb3gsXHJcbiAgICAgICAgbGFzdEJveFRleHQsXHJcbiAgICAgICAgYm90dG9tQ29udGFpbmVyLFxyXG4gICAgICAgIGJvdHRvbVRleHRDb250ZW50LFxyXG4gICAgICBdLFxyXG4gICAgICB7XHJcbiAgICAgICAgbGVmdDogeCxcclxuICAgICAgICB0b3A6IHksXHJcbiAgICAgICAgZXZlbnRlZDogdHJ1ZSxcclxuICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICBob3ZlckN1cnNvcjogXCJkZWZhdWx0XCIsXHJcbiAgICAgICAgbG9ja1NjYWxpbmdYOiB0cnVlLFxyXG4gICAgICAgIGxvY2tTY2FsaW5nWTogdHJ1ZSxcclxuICAgICAgICBsb2NrTW92ZW1lbnRYOiB0cnVlLFxyXG4gICAgICAgIGxvY2tNb3ZlbWVudFk6IHRydWUsXHJcbiAgICAgICAgbG9ja1JvdGF0aW9uOiB0cnVlLFxyXG4gICAgICAgIGhhc0NvbnRyb2xzOiBmYWxzZSxcclxuICAgICAgICBzdWJUYXJnZXRDaGVjazogdHJ1ZSxcclxuICAgICAgICBhbmdsZTogZml4dHVyZURhdGEucmVsYXRpdmVQb3NpdGlvbj8uYW5nbGUgPz8gMCxcclxuICAgICAgfVxyXG4gICAgKSBhcyBmYWJyaWMuR3JvdXAgJiB7XHJcbiAgICAgIHdhbGxJbmRleDogbnVtYmVyO1xyXG4gICAgICBmaXh0dXJlSW5kZXg6IG51bWJlcjtcclxuICAgICAgZml4dHVyZUlkOiBzdHJpbmc7XHJcbiAgICAgIGZpeHR1cmVUeXBlOiBcIndhbGxcIiB8IFwiZmxvb3JcIjtcclxuICAgICAgaXNzdWU6IGJvb2xlYW47XHJcbiAgICAgIGlzc3VlRGF0YTogYW55O1xyXG4gICAgICB0YXNrVHlwZTogc3RyaW5nO1xyXG4gICAgICB2bUNvbmZpZzogW107XHJcbiAgICAgIG9ialR5cGU6IHN0cmluZztcclxuICAgIH07XHJcblxyXG5cclxuXHJcbiAgICBmaXh0dXJlR3JvdXAuZml4dHVyZVR5cGUgPSBmaXh0dXJlRGF0YS5maXh0dXJlVHlwZTtcclxuICAgIGZpeHR1cmVHcm91cC53YWxsSW5kZXggPSBmaXh0dXJlRGF0YS5hc3NvY2lhdGVkRWxlbWVudE51bWJlcjtcclxuICAgIGZpeHR1cmVHcm91cC5maXh0dXJlSW5kZXggPSBmaXh0dXJlRGF0YS5hc3NvY2lhdGVkRWxlbWVudEZpeHR1cmVOdW1iZXI7XHJcbiAgICBmaXh0dXJlR3JvdXAuZml4dHVyZUlkID0gZml4dHVyZURhdGEuX2lkO1xyXG4gICAgZml4dHVyZUdyb3VwLmlzc3VlID0gZml4dHVyZURhdGEuaXNzdWU7XHJcbiAgICBmaXh0dXJlR3JvdXAuaXNzdWVEYXRhID0gZml4dHVyZURhdGEuaXNzdWVEYXRhO1xyXG4gICAgZml4dHVyZUdyb3VwLnRhc2tUeXBlID0gZml4dHVyZURhdGEudGFza1R5cGU7XHJcbiAgICBmaXh0dXJlR3JvdXAudm1Db25maWcgPSBmaXh0dXJlRGF0YS52bUNvbmZpZztcclxuICAgIGZpeHR1cmVHcm91cC5vYmpUeXBlID0gXCJmaXh0dXJlXCI7XHJcblxyXG4gICAgLy8gQWRkIGNsaWNrIGhhbmRsZXIgZGlyZWN0bHkgb24gdGhlIGZpeHR1cmUgZ3JvdXBcclxuICAgIGZpeHR1cmVHcm91cC5vbihcIm1vdXNlZG93blwiLCAoZXZlbnQ6IGFueSkgPT4ge1xyXG4gICAgICAvLyBVc2UgdGhlIGZpeHR1cmUgZ3JvdXAgaXRzZWxmICh3aGljaCBoYXMgYWxsIHRoZSBmaXh0dXJlIHByb3BlcnRpZXMpXHJcbiAgICAgIC8vIFRoZSBldmVudC50YXJnZXQgbWlnaHQgYmUgYSBjaGlsZCBlbGVtZW50LCBzbyB3ZSB1c2UgZml4dHVyZUdyb3VwIGRpcmVjdGx5XHJcbiAgICAgIGlmIChmaXh0dXJlR3JvdXAgJiYgKGZpeHR1cmVHcm91cCBhcyBhbnkpLmZpeHR1cmVJZCkge1xyXG4gICAgICAgIHRoaXMub25GaXh0dXJlQ2xpY2soZml4dHVyZUdyb3VwKTtcclxuICAgICAgfVxyXG4gICAgfSk7XHJcblxyXG4gICAgY2FudmFzLmFkZChmaXh0dXJlR3JvdXApO1xyXG5cclxuICAgIC8vIElmIG5ld2x5IGFkZGVkLCBmb2N1cyBpdCBvbmNlXHJcbiAgICBpZiAoKGZpeHR1cmVEYXRhIGFzIGFueSk/Lm5ld0FkZGVkKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgY2FudmFzLnNldEFjdGl2ZU9iamVjdChmaXh0dXJlR3JvdXApO1xyXG4gICAgICAgIGNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCk7XHJcbiAgICAgIH0gY2F0Y2ggeyB9XHJcbiAgICAgIGRlbGV0ZSAoZml4dHVyZURhdGEgYXMgYW55KS5uZXdBZGRlZDtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gZml4dHVyZUdyb3VwO1xyXG4gIH1cclxuXHJcbiAgZHJhd090aGVyRWxlbWVudHNXaXRoTGFiZWwoXHJcbiAgICBjYW52YXM6IGZhYnJpYy5DYW52YXMsXHJcbiAgICB4OiBudW1iZXIsXHJcbiAgICB5OiBudW1iZXIsXHJcbiAgICBhOiBudW1iZXIsXHJcbiAgICB3aWR0aDogbnVtYmVyLFxyXG4gICAgaGVpZ2h0OiBudW1iZXIsXHJcbiAgICBlbGVtZW50OiBhbnlcclxuICApOiBmYWJyaWMuR3JvdXAge1xyXG4gICAgY29uc3QgcmVjdCA9IG5ldyBmYWJyaWMuUmVjdCh7XHJcbiAgICAgIHdpZHRoLFxyXG4gICAgICBoZWlnaHQsXHJcbiAgICAgIHJ4OiAyLFxyXG4gICAgICByeTogMixcclxuICAgICAgZmlsbDogXCIjREFGMUZGXCIsXHJcbiAgICAgIHN0cm9rZTogXCIjNkJDQUZGXCIsXHJcbiAgICAgIHN0cm9rZVdpZHRoOiAyLFxyXG4gICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgdGV4dCA9IG5ldyBmYWJyaWMuVGV4dGJveChlbGVtZW50LmZpeHR1cmVOYW1lLCB7XHJcbiAgICAgIHdpZHRoOiB3aWR0aCAtIDgsXHJcbiAgICAgIGZvbnRTaXplOiAxNCxcclxuICAgICAgZm9udEZhbWlseTogXCJJbnRlclwiLFxyXG4gICAgICBmb250V2VpZ2h0OiBcIjUwMFwiLFxyXG4gICAgICBmaWxsOiBcIiMxMDE4MjhcIixcclxuICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgb3JpZ2luWTogXCJjZW50ZXJcIixcclxuICAgICAgdGV4dEFsaWduOiBcImNlbnRlclwiLFxyXG4gICAgICBlZGl0YWJsZTogZmFsc2UsXHJcbiAgICAgIHNwbGl0QnlHcmFwaGVtZTogdHJ1ZSxcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IHRleHRCb3VuZHMgPSB0ZXh0LmdldEJvdW5kaW5nUmVjdCgpO1xyXG5cclxuICAgIGlmICh0ZXh0Qm91bmRzLmhlaWdodCA+IGhlaWdodCAtIDgpIHtcclxuICAgICAgY29uc3Qgc2NhbGUgPSAoaGVpZ2h0IC0gOCkgLyB0ZXh0Qm91bmRzLmhlaWdodDtcclxuICAgICAgdGV4dC5zZXQoXCJmb250U2l6ZVwiLCB0ZXh0LmZvbnRTaXplISAqIHNjYWxlKTtcclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBncm91cCA9IG5ldyBmYWJyaWMuR3JvdXAoW3JlY3QsIHRleHRdLCB7XHJcbiAgICAgIGxlZnQ6IHgsXHJcbiAgICAgIHRvcDogeSxcclxuICAgICAgYW5nbGU6IGEsXHJcbiAgICAgIG9yaWdpblg6IFwiY2VudGVyXCIsXHJcbiAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgIGhhc0NvbnRyb2xzOiBmYWxzZSxcclxuICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgIGxvY2tTY2FsaW5nWDogdHJ1ZSxcclxuICAgICAgbG9ja1NjYWxpbmdZOiB0cnVlLFxyXG4gICAgICBsb2NrUm90YXRpb246IHRydWUsXHJcbiAgICAgIGxvY2tNb3ZlbWVudFg6IHRydWUsXHJcbiAgICAgIGxvY2tNb3ZlbWVudFk6IHRydWUsXHJcbiAgICAgIGV2ZW50ZWQ6IHRydWUsXHJcbiAgICAgIGhvdmVyQ3Vyc29yOiBcImRlZmF1bHRcIixcclxuICAgIH0pIGFzIGZhYnJpYy5Hcm91cCAmIHtcclxuICAgICAgb2JqVHlwZTogc3RyaW5nO1xyXG4gICAgICBkYXRhOiBhbnk7XHJcbiAgICB9O1xyXG5cclxuICAgIGdyb3VwLm9ialR5cGUgPSBcIm90aGVyc1wiO1xyXG4gICAgZ3JvdXAuZGF0YSA9IGVsZW1lbnQ7XHJcblxyXG4gICAgY2FudmFzLmFkZChncm91cCk7XHJcblxyXG4gICAgaWYgKChlbGVtZW50IGFzIGFueSk/Lm5ld0FkZGVkKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgY2FudmFzLnNldEFjdGl2ZU9iamVjdChncm91cCk7XHJcbiAgICAgICAgY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgICAgfSBjYXRjaCB7IH1cclxuICAgICAgZGVsZXRlIChlbGVtZW50IGFzIGFueSkubmV3QWRkZWQ7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGdyb3VwO1xyXG4gIH1cclxuXHJcbiAgY29sbGVjdEFsbEZpeHR1cmVzKCk6IHZvaWQge1xyXG4gICAgdGhpcy5hbGxGaXh0dXJlSW5zdGFuY2VzID0gW107XHJcbiAgICBcclxuICAgIC8vIENvbGxlY3Qgd2FsbCBmaXh0dXJlc1xyXG4gICAgaWYgKHRoaXMuZmxvb3JEYXRhPy5sYXlvdXRQb2x5Z29uKSB7XHJcbiAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiB0aGlzLmZsb29yRGF0YS5sYXlvdXRQb2x5Z29uKSB7XHJcbiAgICAgICAgaWYgKGVsZW1lbnQuZml4dHVyZXMgJiYgQXJyYXkuaXNBcnJheShlbGVtZW50LmZpeHR1cmVzKSkge1xyXG4gICAgICAgICAgdGhpcy5hbGxGaXh0dXJlSW5zdGFuY2VzLnB1c2goLi4uZWxlbWVudC5maXh0dXJlcyk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICBcclxuICAgIC8vIENvbGxlY3QgZmxvb3IgZml4dHVyZXNcclxuICAgIGlmICh0aGlzLmZsb29yRGF0YT8uY2VudGVyRml4dHVyZSAmJiBBcnJheS5pc0FycmF5KHRoaXMuZmxvb3JEYXRhLmNlbnRlckZpeHR1cmUpKSB7XHJcbiAgICAgIHRoaXMuYWxsRml4dHVyZUluc3RhbmNlcy5wdXNoKC4uLnRoaXMuZmxvb3JEYXRhLmNlbnRlckZpeHR1cmUpO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgb25GaXh0dXJlQ2xpY2sodGFyZ2V0OiBhbnkpOiB2b2lkIHtcclxuICAgIGlmICghdGFyZ2V0IHx8ICF0aGlzLmZsb29yRGF0YSkgcmV0dXJuO1xyXG4gICAgXHJcbiAgICBjb25zdCBmaXh0dXJlSWQgPSAodGFyZ2V0IGFzIGFueSkuZml4dHVyZUlkO1xyXG4gICAgY29uc3QgZml4dHVyZVR5cGUgPSAodGFyZ2V0IGFzIGFueSkuZml4dHVyZVR5cGU7XHJcbiAgICBcclxuICAgIGlmICghZml4dHVyZUlkKSB7XHJcbiAgICAgIGNvbnNvbGUud2FybignRml4dHVyZSBjbGljazogTm8gZml4dHVyZUlkIGZvdW5kIG9uIHRhcmdldCcsIHRhcmdldCk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIFxyXG4gICAgLy8gRmluZCB0aGUgZml4dHVyZSBkYXRhXHJcbiAgICBsZXQgZml4dHVyZURhdGE6IGFueSA9IG51bGw7XHJcbiAgICBcclxuICAgIGlmIChmaXh0dXJlVHlwZSA9PT0gXCJ3YWxsXCIpIHtcclxuICAgICAgY29uc3Qgd2FsbEluZGV4ID0gKHRhcmdldCBhcyBhbnkpLndhbGxJbmRleDtcclxuICAgICAgXHJcbiAgICAgIGlmICh0aGlzLmZsb29yRGF0YS5sYXlvdXRQb2x5Z29uICYmIHdhbGxJbmRleCAhPT0gdW5kZWZpbmVkICYmIHdhbGxJbmRleCAhPT0gbnVsbCkge1xyXG4gICAgICAgIC8vIEZpbmQgd2FsbCBieSBlbGVtZW50TnVtYmVyICh3YWxsSW5kZXggaXMgdGhlIGVsZW1lbnROdW1iZXIpXHJcbiAgICAgICAgY29uc3Qgd2FsbCA9IHRoaXMuZmxvb3JEYXRhLmxheW91dFBvbHlnb24uZmluZChcclxuICAgICAgICAgICh3OiBhbnkpID0+IHcuZWxlbWVudE51bWJlciA9PT0gd2FsbEluZGV4XHJcbiAgICAgICAgKTtcclxuICAgICAgICBpZiAod2FsbCAmJiB3YWxsLmZpeHR1cmVzKSB7XHJcbiAgICAgICAgICAvLyBBbHdheXMgdXNlIGZpeHR1cmVJZCB0byBmaW5kIHRoZSBmaXh0dXJlIChtb3JlIHJlbGlhYmxlIHRoYW4gaW5kZXgtYmFzZWQgbG9va3VwKVxyXG4gICAgICAgICAgZml4dHVyZURhdGEgPSB3YWxsLmZpeHR1cmVzLmZpbmQoKGY6IGFueSkgPT4gZi5faWQgPT09IGZpeHR1cmVJZCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9IGVsc2UgaWYgKGZpeHR1cmVUeXBlID09PSBcImZsb29yXCIpIHtcclxuICAgICAgZml4dHVyZURhdGEgPSB0aGlzLmZsb29yRGF0YS5jZW50ZXJGaXh0dXJlPy5maW5kKChmOiBhbnkpID0+IGYuX2lkID09PSBmaXh0dXJlSWQpO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICBpZiAoIWZpeHR1cmVEYXRhKSB7XHJcbiAgICAgIGNvbnNvbGUud2FybignRml4dHVyZSBjbGljazogRml4dHVyZSBkYXRhIG5vdCBmb3VuZCcsIHsgXHJcbiAgICAgICAgZml4dHVyZUlkLCBcclxuICAgICAgICBmaXh0dXJlVHlwZSwgXHJcbiAgICAgICAgd2FsbEluZGV4OiAodGFyZ2V0IGFzIGFueSkud2FsbEluZGV4LCBcclxuICAgICAgICBmaXh0dXJlSW5kZXg6ICh0YXJnZXQgYXMgYW55KS5maXh0dXJlSW5kZXgsXHJcbiAgICAgICAgZmxvb3JEYXRhOiB0aGlzLmZsb29yRGF0YSBcclxuICAgICAgfSk7XHJcbiAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIFxyXG4gICAgLy8gRW5zdXJlIHZtQ29uZmlnIGlzIGFsd2F5cyBhbiBhcnJheSAoZXZlbiBpZiBlbXB0eSkgdG8gYXZvaWQgZGlzcGxheSBpc3N1ZXNcclxuICAgIC8vIEhhbmRsZSBjYXNlcyB3aGVyZSB2bUNvbmZpZyBtaWdodCBiZSBudWxsLCB1bmRlZmluZWQsIG9yIG5vdCBhbiBhcnJheVxyXG4gICAgaWYgKCFBcnJheS5pc0FycmF5KGZpeHR1cmVEYXRhLnZtQ29uZmlnKSkge1xyXG4gICAgICBmaXh0dXJlRGF0YS52bUNvbmZpZyA9IFtdO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBDcmVhdGUgYSBkZWVwIGNsb25lIHRvIGVuc3VyZSBjaGFuZ2UgZGV0ZWN0aW9uIHdvcmtzXHJcbiAgICBjb25zdCBjbG9uZWREYXRhID0gc3RydWN0dXJlZENsb25lKGZpeHR1cmVEYXRhKTtcclxuICAgIFxyXG4gICAgdGhpcy5zZWxlY3RlZEZpeHR1cmUgPSB7XHJcbiAgICAgIGZpeHR1cmVJZDogZml4dHVyZUlkLFxyXG4gICAgICBmaXh0dXJlVHlwZTogZml4dHVyZVR5cGUsXHJcbiAgICAgIHdhbGxJbmRleDogKHRhcmdldCBhcyBhbnkpLndhbGxJbmRleCxcclxuICAgICAgZml4dHVyZUluZGV4OiAodGFyZ2V0IGFzIGFueSkuZml4dHVyZUluZGV4LFxyXG4gICAgfTtcclxuICAgIFxyXG4gICAgLy8gQ2hlY2sgaWYgdGhpcyBmaXh0dXJlIGhhcyByZXBsYWNlUmVzcG9uc2VEYXRhIChmb3IgYmVmb3JlL2FmdGVyIGNvbXBhcmlzb24pXHJcbiAgICBjb25zdCBzdG9yZSA9IHRoaXMuZmluZFJlcGxhY2VEYXRhPy5zdG9yZXM/LmZpbmQoXHJcbiAgICAgIChzOiBTdG9yZSkgPT4gcy5zdG9yZU5hbWUgPT09IHRoaXMuc2VsZWN0ZWRTdG9yZUZvclByZXZpZXc/LnN0b3JlTmFtZVxyXG4gICAgKTtcclxuICAgIFxyXG4gICAgLy8gSWYgdGhpcyBmaXh0dXJlIG1hdGNoZXMgdGhlIGZpbmRSZXNwb25zZURhdGEgYW5kIGhhcyByZXBsYWNlUmVzcG9uc2VEYXRhLFxyXG4gICAgLy8gcmVzdG9yZSB0aGUgb3JpZ2luYWwgZml4dHVyZSBkYXRhIGZvciBiZWZvcmUvYWZ0ZXIgY29tcGFyaXNvblxyXG4gICAgaWYgKHN0b3JlPy5maW5kUmVzcG9uc2VEYXRhID09PSBmaXh0dXJlSWQgJiYgc3RvcmU/LnJlcGxhY2VSZXNwb25zZURhdGEpIHtcclxuICAgICAgLy8gUmVzdG9yZSBvcmlnaW5hbEZpeHR1cmVEYXRhIGZyb20gdGhlIG1hcCAocGVyc2lzdHMgZXZlbiB3aGVuIGNsaWNraW5nIG90aGVyIGZpeHR1cmVzKVxyXG4gICAgICBjb25zdCBzdG9yZWRPcmlnaW5hbCA9IHRoaXMub3JpZ2luYWxGaXh0dXJlc01hcC5nZXQoZml4dHVyZUlkKTtcclxuICAgICAgaWYgKHN0b3JlZE9yaWdpbmFsKSB7XHJcbiAgICAgICAgdGhpcy5vcmlnaW5hbEZpeHR1cmVEYXRhID0gc3RydWN0dXJlZENsb25lKHN0b3JlZE9yaWdpbmFsKTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICAvLyBJZiBub3QgaW4gbWFwIChzaG91bGRuJ3QgaGFwcGVuIGlmIGFwcGx5U3RvcmVkUmVzcG9uc2VEYXRhIHJhbiksIFxyXG4gICAgICAgIC8vIHVzZSBjdXJyZW50IGZpeHR1cmUgYXMgZmFsbGJhY2tcclxuICAgICAgICB0aGlzLm9yaWdpbmFsRml4dHVyZURhdGEgPSBzdHJ1Y3R1cmVkQ2xvbmUoY2xvbmVkRGF0YSk7XHJcbiAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIC8vIE5vIHJlcGxhY2UgZGF0YSBmb3IgdGhpcyBmaXh0dXJlLCBjbGVhciBvcmlnaW5hbFxyXG4gICAgICB0aGlzLm9yaWdpbmFsRml4dHVyZURhdGEgPSBudWxsO1xyXG4gICAgfVxyXG4gICAgXHJcbiAgICAvLyBGb3JjZSBjaGFuZ2UgZGV0ZWN0aW9uIGJ5IGNyZWF0aW5nIGEgbmV3IG9iamVjdCByZWZlcmVuY2VcclxuICAgIHRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YSA9IG51bGw7XHJcbiAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICBcclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICB0aGlzLnNlbGVjdGVkRml4dHVyZURhdGEgPSBjbG9uZWREYXRhO1xyXG4gICAgICB0aGlzLmlzUmlnaHRQYW5lbENvbGxhcHNlZCA9IGZhbHNlO1xyXG4gICAgICB0aGlzLmNkci5kZXRlY3RDaGFuZ2VzKCk7XHJcbiAgICAgIFxyXG4gICAgICAvLyBSZS1jZW50ZXIgcGxhbm9ncmFtIHdoZW4gcGFuZWwgb3BlbnMgKHNpbWlsYXIgdG8gbWFuYWdlLXBsYW5vZ3JhbSlcclxuICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgaWYgKHRoaXMucHJldmlld0NhbnZhcyAmJiB0aGlzLnByZXZpZXdDYW52YXNDb250YWluZXJSZWY/Lm5hdGl2ZUVsZW1lbnQpIHtcclxuICAgICAgICAgIHRoaXMucmVzaXplQ2FudmFzKHRoaXMucHJldmlld0NhbnZhcywgdGhpcy5wcmV2aWV3Q2FudmFzQ29udGFpbmVyUmVmKTtcclxuICAgICAgICAgIHRoaXMuZml0Q2FudmFzVG9MYXlvdXRBbmltYXRlZCh0aGlzLnByZXZpZXdDYW52YXMpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSwgNDAwKTtcclxuICAgIH0sIDApO1xyXG4gIH1cclxuXHJcbiAgdG9nZ2xlUmlnaHRQYW5lbCgpOiB2b2lkIHtcclxuICAgIHRoaXMuaXNSaWdodFBhbmVsQ29sbGFwc2VkID0gIXRoaXMuaXNSaWdodFBhbmVsQ29sbGFwc2VkO1xyXG4gICAgXHJcbiAgICAvLyBSZXNpemUgY2FudmFzIHdoZW4gcGFuZWwgaXMgdG9nZ2xlZFxyXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgIGlmICh0aGlzLnByZXZpZXdDYW52YXMgJiYgdGhpcy5wcmV2aWV3Q2FudmFzQ29udGFpbmVyUmVmPy5uYXRpdmVFbGVtZW50KSB7XHJcbiAgICAgICAgdGhpcy5yZXNpemVDYW52YXModGhpcy5wcmV2aWV3Q2FudmFzLCB0aGlzLnByZXZpZXdDYW52YXNDb250YWluZXJSZWYpO1xyXG4gICAgICAgIHRoaXMuZml0Q2FudmFzVG9MYXlvdXRBbmltYXRlZCh0aGlzLnByZXZpZXdDYW52YXMpO1xyXG4gICAgICB9XHJcbiAgICB9LCA0MDApO1xyXG4gIH1cclxuXHJcbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XHJcbiAgICBpZiAodGhpcy5wcmV2aWV3Q2FudmFzKSB7XHJcbiAgICAgIHRoaXMucHJldmlld0NhbnZhcy5kaXNwb3NlKCk7XHJcbiAgICB9XHJcbiAgICB0aGlzLmRlc3Ryb3kkLm5leHQoKTtcclxuICAgIHRoaXMuZGVzdHJveSQuY29tcGxldGUoKTtcclxuICB9XHJcbn1cclxuIiwiPGRpdiBjbGFzcz1cIm1haW4tY2FyZFwiPlxyXG4gICAgPGZvcm0+XHJcbiAgICAgICAgPCEtLSBTZWN0aW9uIDE6IEFkZCBTdG9yZXMgLS0+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInNlY3Rpb24tcm93XCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWN0aW9uLW51bWJlclwiPjE8L2Rpdj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNlY3Rpb24tY29udGVudFwiPlxyXG4gICAgICAgICAgICAgICAgPGgyIGNsYXNzPVwic2VjdGlvbi10aXRsZVwiPkFkZCBzdG9yZXM8L2gyPlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0b3JlLWlucHV0LXdyYXBwZXJcIj5cclxuICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdG9yZS1kcm9wZG93blwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8bGliLXJlYWN0aXZlLXNlbGVjdFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2lkRmllbGRdPVwiJ3ZhbHVlJ1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbmFtZUZpZWxkXT1cIidsYWJlbCdcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2RhdGFdPVwic2VhcmNoTW9kZXNcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cInNlbGVjdGVkTW9kZVwiIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2xpYi1yZWFjdGl2ZS1zZWxlY3Q+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+IFxyXG4gICAgICAgICAgICAgICAgICAgIDxsaWItc3RvcmUtc2VsZWN0IFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbb3B0aW9uc109XCJzdG9yZU9wdGlvbnNcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBbaW5pdGlhbFNlbGVjdGVkXT1cInNlbGVjdGVkU3RvcmVzXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgKHNlbGVjdGVkQ2hhbmdlKT1cIm9uU3RvcmVzU2VsZWN0ZWQoJGV2ZW50KVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvbGliLXN0b3JlLXNlbGVjdD5cclxuICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuLWFwcGx5XCIgdHlwZT1cImJ1dHRvblwiIChjbGljayk9XCJvbkFwcGx5KClcIiBbZGlzYWJsZWRdPVwibG9hZGluZyB8fCBmaW5kTG9hZGluZyB8fCByZXBsYWNlTG9hZGluZyB8fCBzYXZpbmdEcmFmdFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICB7eyBzYXZpbmdEcmFmdCA/ICdTYXZpbmcuLi4nIDogJ0FwcGx5JyB9fVxyXG4gICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICAgIFxyXG4gICAgICAgIDwhLS0gU2VjdGlvbiAyOiBDaG9vc2UgVGFyZ2V0IC0tPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzZWN0aW9uLXJvd1wiICpuZ0lmPVwiaGFzU3RvcmVzXCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWN0aW9uLW51bWJlclwiPjI8L2Rpdj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNlY3Rpb24tY29udGVudFwiPlxyXG4gICAgICAgICAgICAgICAgPGgyIGNsYXNzPVwic2VjdGlvbi10aXRsZVwiPkNob29zZSB0YXJnZXQ8L2gyPlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInRhcmdldC1idXR0b25zXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGxhYmVsIGNsYXNzPVwidGFyZ2V0LWJ0blwiIFtjbGFzcy5hY3RpdmVdPVwidGFyZ2V0LnZhbHVlID09PSAnYm90aCdcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJyYWRpb1wiIG5hbWU9XCJ0YXJnZXRcIiB2YWx1ZT1cImJvdGhcIiBbZm9ybUNvbnRyb2xdPVwidGFyZ2V0XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIEJvdGhcclxuICAgICAgICAgICAgICAgICAgICA8L2xhYmVsPlxyXG4gICAgICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cInRhcmdldC1idG5cIiBbY2xhc3MuYWN0aXZlXT1cInRhcmdldC52YWx1ZSA9PT0gJ21lcmNoJ1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8aW5wdXQgdHlwZT1cInJhZGlvXCIgbmFtZT1cInRhcmdldFwiIHZhbHVlPVwibWVyY2hcIiBbZm9ybUNvbnRyb2xdPVwidGFyZ2V0XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIE1lcmNoYW5kaXNlXHJcbiAgICAgICAgICAgICAgICAgICAgPC9sYWJlbD5cclxuICAgICAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJ0YXJnZXQtYnRuXCIgW2NsYXNzLmFjdGl2ZV09XCJ0YXJnZXQudmFsdWUgPT09ICd2bSdcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGlucHV0IHR5cGU9XCJyYWRpb1wiIG5hbWU9XCJ0YXJnZXRcIiB2YWx1ZT1cInZtXCIgW2Zvcm1Db250cm9sXT1cInRhcmdldFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICBWaXN1YWwgTWVyY2hhbmRpc2VcclxuICAgICAgICAgICAgICAgICAgICA8L2xhYmVsPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICAgIFxyXG4gICAgICAgIDwhLS0gU2VjdGlvbiAzOiBGaW5kIGFuZCBSZXBsYWNlIC0tPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzZWN0aW9uLXJvd1wiICpuZ0lmPVwiaGFzU3RvcmVzXCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWN0aW9uLW51bWJlclwiPjM8L2Rpdj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cInNlY3Rpb24tY29udGVudFwiPlxyXG4gICAgICAgICAgICAgICAgPGgyIGNsYXNzPVwic2VjdGlvbi10aXRsZVwiPlByb3ZpZGUgYW4gaW5zdHJ1Y3Rpb24gdG8gZmluZCBhbmQgcmVwbGFjZSBpbiB0aGUgc2VsZWN0ZWQgc3RvcmU8L2gyPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgICAgICBcclxuICAgICAgICA8IS0tIEZpbmQgYW5kIFJlcGxhY2UgSW5wdXRzIC0tPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJmaW5kLXJlcGxhY2Utd3JhcHBlclwiICpuZ0lmPVwiaGFzU3RvcmVzXCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaW5kLXJlcGxhY2UtYm94XCI+XHJcbiAgICAgICAgICAgICAgICA8bGFiZWwgY2xhc3M9XCJmaW5kLXJlcGxhY2UtbGFiZWxcIj5UYXJnZXQ8L2xhYmVsPlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbmQtcmVwbGFjZS1pbnB1dFwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDx0ZXh0YXJlYSBcclxuICAgICAgICAgICAgICAgICAgICAgICAgcGxhY2Vob2xkZXI9XCJJbnN0cnVjdCB3aGF0IHRvIGZpbmQgaXQgaW4gdGhlIHNlbGVjdGVkIHN0b3JlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cImZpbmRQcm9tcHRcIj48L3RleHRhcmVhPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1idG4tY29udGFpbmVyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImJ0bi1maW5kXCIgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvbkZpbmQoKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiZmluZExvYWRpbmcgfHwgcmVwbGFjZUxvYWRpbmcgfHwgIXNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB7eyBmaW5kTG9hZGluZyA/ICdQcm9jZXNzaW5nLi4uJyA6ICdGaW5kJyB9fVxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2J1dHRvbj5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhcnJvdy1pY29uXCI+XHJcbiAgICAgICAgICAgICAgICA8c3ZnIHdpZHRoPVwiMjdcIiBoZWlnaHQ9XCIxNVwiIHZpZXdCb3g9XCIwIDAgMjcgMTVcIiBmaWxsPVwibm9uZVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNMjYuNzA3MSA4LjA3MTA3QzI3LjA5NzYgNy42ODA1NCAyNy4wOTc2IDcuMDQ3MzggMjYuNzA3MSA2LjY1Njg1TDIwLjM0MzEgMC4yOTI4OTNDMTkuOTUyNiAtMC4wOTc2MzEgMTkuMzE5NSAtMC4wOTc2MzEgMTguOTI4OSAwLjI5Mjg5M0MxOC41Mzg0IDAuNjgzNDE4IDE4LjUzODQgMS4zMTY1OCAxOC45Mjg5IDEuNzA3MTFMMjQuNTg1OCA3LjM2Mzk2TDE4LjkyODkgMTMuMDIwOEMxOC41Mzg0IDEzLjQxMTMgMTguNTM4NCAxNC4wNDQ1IDE4LjkyODkgMTQuNDM1QzE5LjMxOTUgMTQuODI1NiAxOS45NTI2IDE0LjgyNTYgMjAuMzQzMSAxNC40MzVMMjYuNzA3MSA4LjA3MTA3Wk0wIDcuMzYzOTZWOC4zNjM5NkgyNlY3LjM2Mzk2VjYuMzYzOTZIMFY3LjM2Mzk2WlwiIGZpbGw9XCIjOThBMkIzXCIvPlxyXG4gICAgICAgICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICBcclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpbmQtcmVwbGFjZS1ib3hcIj5cclxuICAgICAgICAgICAgICAgIDxsYWJlbCBjbGFzcz1cImZpbmQtcmVwbGFjZS1sYWJlbFwiPkNoYW5nZTwvbGFiZWw+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZmluZC1yZXBsYWNlLWlucHV0XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPHRleHRhcmVhIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBwbGFjZWhvbGRlcj1cIlR5cGUgd2hhdCB3b3VsZCB5b3UgbGlrZSB0byByZXBsYWNlIGluIHRoZSBzZWxlY3RlZCBmaXh0dXJlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgW2Zvcm1Db250cm9sXT1cInJlcGxhY2VQcm9tcHRcIj48L3RleHRhcmVhPlxyXG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJpbnB1dC1idG4tY29udGFpbmVyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxidXR0b24gXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGFzcz1cImJ0bi1yZXBsYWNlXCIgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvblJlcGxhY2UoKVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiIWZpbmRQcm9tcHQudmFsdWUgfHwgIXJlcGxhY2VQcm9tcHQudmFsdWUgfHwgZmluZExvYWRpbmcgfHwgcmVwbGFjZUxvYWRpbmcgfHwgIWdldEN1cnJlbnRTdG9yZUZpbmRSZXNwb25zZURhdGEoKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAge3sgcmVwbGFjZUxvYWRpbmcgPyAnUHJvY2Vzc2luZy4uLicgOiAnUmVwbGFjZScgfX1cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgXHJcbiAgICAgICAgPCEtLSBQcmV2aWV3IFNlY3Rpb24gLS0+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cInByZXZpZXctd3JhcHBlclwiICpuZ0lmPVwiaGFzU3RvcmVzXCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3cgZy0wIHByZXZpZXctbGF5b3V0XCI+XHJcbiAgICAgICAgICAgICAgICA8IS0tIExlZnQgQ29sdW1uOiBDYW52YXMgLS0+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY29sXCIgW25nQ2xhc3NdPVwieyBcclxuICAgICAgICAgICAgICAgICAgICAnY29sLTYnOiAhaXNSaWdodFBhbmVsQ29sbGFwc2VkICYmIHNlbGVjdGVkRml4dHVyZURhdGEgJiYgb3JpZ2luYWxGaXh0dXJlRGF0YSxcclxuICAgICAgICAgICAgICAgICAgICAnY29sLTknOiAhaXNSaWdodFBhbmVsQ29sbGFwc2VkICYmIHNlbGVjdGVkRml4dHVyZURhdGEgJiYgIW9yaWdpbmFsRml4dHVyZURhdGEsIFxyXG4gICAgICAgICAgICAgICAgICAgICdjb2wtMTInOiBpc1JpZ2h0UGFuZWxDb2xsYXBzZWQgfHwgIXNlbGVjdGVkRml4dHVyZURhdGEgXHJcbiAgICAgICAgICAgICAgICB9XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImQtZmxleCBhbGlnbi1pdGVtcy1zdGFydCBnYXAtMyBtYi0zXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gU3RvcmUgRHJvcGRvd24gLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxsaWItc3RvcmUtZHJvcGRvd24gXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImhhc1N0b3JlcyAmJiBzdG9yZURyb3Bkb3duSXRlbXMubGVuZ3RoID4gMFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbaXRlbXNdPVwic3RvcmVEcm9wZG93bkl0ZW1zXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtpZEZpZWxkXT1cIidzdG9yZUlkJ1wiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc2VhcmNoRmllbGRdPVwiJ3N0b3JlTmFtZSdcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgW211bHRpXT1cImZhbHNlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzZWxlY3RlZFZhbHVlc109XCJzZWxlY3RlZFN0b3JlVmFsdWVzXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChzZWxlY3RlZCk9XCJvblN0b3JlU2VsZWN0ZWRGb3JQcmV2aWV3KCRldmVudClcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9saWItc3RvcmUtZHJvcGRvd24+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8IS0tIENvbnRlbnQgQXJlYSAtLT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZsZXgtZ3Jvdy0xXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIFByZXZpZXcgVGl0bGUgLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cCBjbGFzcz1cImZ3LXNlbWlib2xkIG1iLTFcIiBzdHlsZT1cImZvbnQtc2l6ZTogMTRweDsgY29sb3I6ICMxZDI5Mzk7XCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgUHJldmlldyBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiAqbmdJZj1cImdldFN0b3JlQ291bnQoKSA+IDBcIiBzdHlsZT1cImZvbnQtd2VpZ2h0OiA0MDA7IGNvbG9yOiAjNjY3MDg1O1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoe3sgZ2V0U3RvcmVDb3VudCgpIH19IHt7IGdldFN0b3JlQ291bnQoKSA9PT0gMSA/ICdTdG9yZScgOiAnU3RvcmVzJyB9fSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L3A+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gRGVzY3JpcHRpb24gLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8cCBjbGFzcz1cIm1iLTBcIiBzdHlsZT1cImZvbnQtc2l6ZTogMTRweDsgY29sb3I6ICM0NzU0Njc7XCI+Q2hlY2sgaWYgdGhlIHByb21wdCBmaXQgaW50byB0aGUgZXhwZWN0ZWQgcmVzdWx0cyBpbiBvcmRlciB0byBwcm9jZWVkIHRvIHJldmlldyBhbmQgYXBwcm92ZTwvcD5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIDwhLS0gQ2FudmFzIENvbnRhaW5lciAtLT5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiY2FudmFzLWNvbnRhaW5lclwiICNwcmV2aWV3Q2FudmFzQ29udGFpbmVyICpuZ0lmPVwic2VsZWN0ZWRTdG9yZUZvclByZXZpZXdcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhbnZhcy1sb2FkaW5nXCIgKm5nSWY9XCJjYW52YXNMb2FkaW5nXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Bpbm5lci1ib3JkZXIgdGV4dC1wcmltYXJ5XCIgcm9sZT1cInN0YXR1c1wiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwidmlzdWFsbHktaGlkZGVuXCI+TG9hZGluZy4uLjwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgPGNhbnZhcyAjcHJldmlld0NhbnZhcz48L2NhbnZhcz5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgICAgICAgIDwhLS0gUmlnaHQgQ29sdW1uOiBGaXh0dXJlIFByZXZpZXcgLS0+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZml4dHVyZS1wcmV2aWV3LXBhbmVsXCIgXHJcbiAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwic2VsZWN0ZWRGaXh0dXJlRGF0YSAmJiAhaXNSaWdodFBhbmVsQ29sbGFwc2VkXCJcclxuICAgICAgICAgICAgICAgICAgICAgW25nQ2xhc3NdPVwieyAnY29sLTYnOiBvcmlnaW5hbEZpeHR1cmVEYXRhLCAnY29sLTMnOiAhb3JpZ2luYWxGaXh0dXJlRGF0YSB9XCJcclxuICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLm1pbi13aWR0aF09XCJvcmlnaW5hbEZpeHR1cmVEYXRhID8gJzY4MHB4JyA6ICczNDBweCdcIj5cclxuICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicy1jYXJkXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gUGFuZWwgSGVhZGVyIC0tPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZml4dHVyZS1wcmV2aWV3LWhlYWRlclwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImhlYWRlci1jYXJkXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNhcmQtY29udGVudFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIDxkaXYgY2xhc3M9XCJwcm9kdWN0LWltYWdlLWNvbnRhaW5lclwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGltZyBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbHQ9XCJQcm9kdWN0XCIgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3M9XCJwcm9kdWN0LWltYWdlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PiAtLT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5hbWVcIj57eyBnZXRGaXh0dXJlTGFiZWwoKSB9fTwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3BlY3MtY29udGFpbmVyXCIgKm5nSWY9XCJnZXRGaXh0dXJlQ2F0ZWdvcnkoKSB8fCBnZXRGaXh0dXJlV2lkdGgoKSB8fCBnZXRTaGVsZkNvdW50KCkgPiAwIHx8IGdldEZpeHR1cmVDYXBhY2l0eSgpID4gMFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzcGVjLXRleHRcIiAqbmdJZj1cImdldEZpeHR1cmVDYXRlZ29yeSgpXCI+e3sgZ2V0Rml4dHVyZUNhdGVnb3J5KCkgfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZG90XCIgKm5nSWY9XCJnZXRGaXh0dXJlQ2F0ZWdvcnkoKSAmJiAoZ2V0Rml4dHVyZVdpZHRoKCkgfHwgZ2V0U2hlbGZDb3VudCgpID4gMCB8fCBnZXRGaXh0dXJlQ2FwYWNpdHkoKSA+IDApXCI+PC9kaXY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiBjbGFzcz1cInNwZWMtdGV4dFwiICpuZ0lmPVwiZ2V0Rml4dHVyZVdpZHRoKClcIj57eyBnZXRGaXh0dXJlV2lkdGgoKSB9fTwvc3Bhbj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJkb3RcIiAqbmdJZj1cImdldEZpeHR1cmVXaWR0aCgpICYmIChnZXRTaGVsZkNvdW50KCkgPiAwIHx8IGdldEZpeHR1cmVDYXBhY2l0eSgpID4gMClcIj48L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwic3BlYy10ZXh0XCIgKm5nSWY9XCJnZXRTaGVsZkNvdW50KCkgPiAwXCI+e3sgZ2V0U2hlbGZDb3VudCgpIH19IHt7IGdldFNoZWxmQ291bnQoKSA9PT0gMSA/ICdTaGVsZicgOiAnU2hlbHZlcycgfX08L3NwYW4+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZG90XCIgKm5nSWY9XCJnZXRTaGVsZkNvdW50KCkgPiAwICYmIGdldEZpeHR1cmVDYXBhY2l0eSgpID4gMFwiPjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJzcGVjLXRleHRcIiAqbmdJZj1cImdldEZpeHR1cmVDYXBhY2l0eSgpID4gMFwiPnt7IGdldEZpeHR1cmVDYXBhY2l0eSgpIH19IENhcGFjaXR5PC9zcGFuPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDwhLS0gRml4dHVyZSBDb21wb25lbnQgLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaXh0dXJlLXByZXZpZXctY29udGVudFwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPCEtLSBTaG93IEJlZm9yZS9BZnRlciB3aGVuIHJlcGxhY2UgZGF0YSBleGlzdHMgLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwib3JpZ2luYWxGaXh0dXJlRGF0YVwiIGNsYXNzPVwiYmVmb3JlLWFmdGVyLWNvbnRhaW5lclwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJiZWZvcmUtc2VjdGlvblwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic2VjdGlvbi1oZWFkZXJcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxoNiBjbGFzcz1cInNlY3Rpb24tbGFiZWwgbWItMFwiPkJlZm9yZTwvaDY+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwiZml4dHVyZS13cmFwcGVyXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8bGliLXN0b3JlLWZpeHR1cmUgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2ZpeHR1cmVdPVwib3JpZ2luYWxGaXh0dXJlRGF0YVwiIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzaG93Q29sb3JzXT1cInRydWVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzaG93Vk1zXT1cInRydWVcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzaG93QkNzXT1cInRydWVcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvbGliLXN0b3JlLWZpeHR1cmU+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJhZnRlci1zZWN0aW9uXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzZWN0aW9uLWhlYWRlclwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGg2IGNsYXNzPVwic2VjdGlvbi1sYWJlbCBtYi0wXCI+QWZ0ZXI8L2g2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImZpeHR1cmUtd3JhcHBlclwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxpYi1zdG9yZS1maXh0dXJlIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtmaXh0dXJlXT1cInNlbGVjdGVkRml4dHVyZURhdGFcIiBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc2hvd0NvbG9yc109XCJ0cnVlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc2hvd1ZNc109XCJ0cnVlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc2hvd0JDc109XCJ0cnVlXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2xpYi1zdG9yZS1maXh0dXJlPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8IS0tIFNob3cgc2luZ2xlIGZpeHR1cmUgd2hlbiBubyByZXBsYWNlIGRhdGEgLS0+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8ZGl2ICpuZ0lmPVwiIW9yaWdpbmFsRml4dHVyZURhdGFcIiBjbGFzcz1cInNpbmdsZS1maXh0dXJlLWNvbnRhaW5lclwiPlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJmaXh0dXJlLXdyYXBwZXJcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPGxpYi1zdG9yZS1maXh0dXJlIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW2ZpeHR1cmVdPVwic2VsZWN0ZWRGaXh0dXJlRGF0YVwiIFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3Nob3dDb2xvcnNdPVwidHJ1ZVwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbc2hvd1ZNc109XCJ0cnVlXCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFtzaG93QkNzXT1cInRydWVcIj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9saWItc3RvcmUtZml4dHVyZT5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG5cclxuICAgICAgICAgICAgICAgIDwhLS0gQ29sbGFwc2UgQnV0dG9uIC0tPlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cImNvbGxhcHNlLWhhbmRsZXIgcmlnaHRcIiBcclxuICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJzZWxlY3RlZEZpeHR1cmVEYXRhXCJcclxuICAgICAgICAgICAgICAgICAgICAgKGNsaWNrKT1cInRvZ2dsZVJpZ2h0UGFuZWwoKVwiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxzdmcgKm5nSWY9XCJpc1JpZ2h0UGFuZWxDb2xsYXBzZWRcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgd2lkdGg9XCIxOFwiIGhlaWdodD1cIjE4XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmlld0JveD1cIjAgMCAxOCAxOFwiIGZpbGw9XCJub25lXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNOC4yNzMwOCAxMi42MzZMNC42MzY3MiA4Ljk5OTY0TDguMjczMDggNS4zNjMyOE0xMy4zNjQgMTIuNjM2TDkuNzI3NjMgOC45OTk2NEwxMy4zNjQgNS4zNjMyOFwiXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJva2U9XCIjMTAxODI4XCIgc3Ryb2tlLXdpZHRoPVwiMS40NTQ1NVwiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIC8+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9zdmc+XHJcbiAgICAgICAgICAgICAgICAgICAgPHN2ZyAqbmdJZj1cIiFpc1JpZ2h0UGFuZWxDb2xsYXBzZWRcIiB4bWxucz1cImh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnXCIgd2lkdGg9XCIxOFwiIGhlaWdodD1cIjE4XCJcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmlld0JveD1cIjAgMCAxOCAxOFwiIGZpbGw9XCJub25lXCI+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNOS43MjY5MiA1LjM2Mzk5TDEzLjM2MzMgOS4wMDAzNkw5LjcyNjkyIDEyLjYzNjdNNC42MzYwMSA1LjM2Mzk5TDguMjcyMzcgOS4wMDAzNkw0LjYzNjAxIDEyLjYzNjdcIlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3Ryb2tlPVwiIzEwMTgyOFwiIHN0cm9rZS13aWR0aD1cIjEuNDU0NTVcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIiAvPlxyXG4gICAgICAgICAgICAgICAgICAgIDwvc3ZnPlxyXG4gICAgICAgICAgICAgICAgPC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwhLS0gTm8gUHJldmlldyBTZWN0aW9uIC0tPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJuby1wcmV2aWV3XCIgKm5nSWY9XCJoYXNTdG9yZXMgJiYgIXNlbGVjdGVkU3RvcmVGb3JQcmV2aWV3XCI+XHJcbiAgICAgICAgICAgIDxkaXYgPlxyXG4gICAgICAgICAgICAgICAgPHN2ZyB3aWR0aD1cIjMxNVwiIGhlaWdodD1cIjE1NVwiIHZpZXdCb3g9XCIwIDAgMzE1IDE1NVwiIGZpbGw9XCJub25lXCIgeG1sbnM9XCJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2Z1wiPlxyXG4gICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNMTAzLjgxIDQ3LjAxOTVDODkuNTQ2MyA0Ny4wMTk3IDc3Ljk4MzQgNTguNTgyNCA3Ny45ODM0IDcyLjg0NTdDNzcuOTgzNCA3OC43NjE3IDczLjk4MDMgODUuNTA1OSA2OC4wNjQzIDg1LjUwNTlINDUuMjU4OEMzMC45OTUzIDg1LjUwNTkgMTkuNDMxNiA5Ny4wNjg2IDE5LjQzMTYgMTExLjMzMkMxOS40MzE2IDEyNS41OTYgMzAuOTk1MyAxMzcuMTU4IDQ1LjI1ODggMTM3LjE1OEgxODMuMzU3QzIwMC4yNDggMTM3LjE1OCAyMTYuMzIgMTIzLjk5MiAyMzMuMjEgMTIzLjk5MkgyOTkuMjQ1QzMwNCAxMjMuOTkyIDMwNy44NTQgMTIwLjEzNyAzMDcuODU0IDExNS4zODNDMzA3Ljg1MyAxMTAuNjI5IDMwMy45OTkgMTA2Ljc3NCAyOTkuMjQ1IDEwNi43NzRIMjExLjYyNUMyMDkuOTggMTA2Ljc3NCAyMDguNTg4IDEwNS41NTMgMjA4LjEyIDEwMy45NzZDMjA3LjM4MSAxMDEuNDg2IDIwOS4wODIgOTguNjcxOSAyMTEuNjc5IDk4LjY3MTlIMjQxLjkwOUMyNTYuMTcyIDk4LjY3MTcgMjY3LjczNSA4Ny4xMDkgMjY3LjczNSA3Mi44NDU3QzI2Ny43MzUgNTguNTgyNCAyNTYuMTcyIDQ3LjAxOTggMjQxLjkwOSA0Ny4wMTk1SDEwMy44MVpcIiBmaWxsPVwiI0VBRUNGMFwiLz5cclxuICAgICAgICAgICAgICAgICAgICA8cmVjdCB3aWR0aD1cIjI0MC42OTRcIiBoZWlnaHQ9XCIxNi45OTU2XCIgcng9XCI4LjQ5NzhcIiB0cmFuc2Zvcm09XCJtYXRyaXgoLTEgMCAwIDEgMjQ2LjYwMyA0OC44NTc0KVwiIGZpbGw9XCIjRUFFQ0YwXCIvPlxyXG4gICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgY3g9XCI1LjQyMTQ3XCIgY3k9XCI1LjQyMTQ3XCIgcj1cIjUuNDIxNDdcIiB0cmFuc2Zvcm09XCJtYXRyaXgoLTEgMCAwIDEgNTYuMjk3OSAxMTMuMjgxKVwiIGZpbGw9XCIjNkJDQUZGXCIvPlxyXG4gICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgY3g9XCIzLjI1Mjg4XCIgY3k9XCIzLjI1Mjg4XCIgcj1cIjMuMjUyODhcIiB0cmFuc2Zvcm09XCJtYXRyaXgoLTEgMCAwIDEgMjQ0Ljk2NSA2OC44MjYyKVwiIGZpbGw9XCIjMDBBM0ZGXCIvPlxyXG4gICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgY3g9XCIzLjI1Mjg4XCIgY3k9XCIzLjI1Mjg4XCIgcj1cIjMuMjUyODhcIiB0cmFuc2Zvcm09XCJtYXRyaXgoLTEgMCAwIDEgMjE1LjY4OSAxMy41MjczKVwiIGZpbGw9XCIjMDBBM0ZGXCIvPlxyXG4gICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgY3g9XCIyLjE2ODU5XCIgY3k9XCIyLjE2ODU5XCIgcj1cIjIuMTY4NTlcIiB0cmFuc2Zvcm09XCJtYXRyaXgoLTEgMCAwIDEgMTA0LjAwNiAxMzguMjIxKVwiIGZpbGw9XCIjMDBBM0ZGXCIvPlxyXG4gICAgICAgICAgICAgICAgICAgIDxyZWN0IHg9XCI2OC41MDFcIiB5PVwiNDQuMTUyM1wiIHdpZHRoPVwiMTY2Ljk5OVwiIGhlaWdodD1cIjk3LjkzNzFcIiByeD1cIjE1LjEwMTVcIiBmaWxsPVwiIzZCQ0FGRlwiIHN0cm9rZT1cIiMwMEEzRkZcIiBzdHJva2Utd2lkdGg9XCIzXCIvPlxyXG4gICAgICAgICAgICAgICAgICAgIDxtYXNrIGlkPVwicGF0aC04LWluc2lkZS0xXzkzNl8xNTAzODNcIiBmaWxsPVwid2hpdGVcIj5cclxuICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPVwiTTkzLjExNzIgMTlDOTQuMDYyNSAxOSA5NC45ODkyIDE5LjA4MjggOTUuODg4NyAxOS4yNDIyVjExNi43ODRDOTQuOTg5MiAxMTYuNjI1IDk0LjA2MjUgMTE2LjU0MiA5My4xMTcyIDExNi41NDJIODIuNzc0NEM3NC4wNjQyIDExNi41NDIgNjcuMDAzMSAxMjMuNjAzIDY3LjAwMjkgMTMyLjMxM1YzNC43NzE1QzY3LjAwMjkgMjYuMDYxMiA3NC4wNjQxIDE5IDgyLjc3NDQgMTlIOTMuMTE3MlpcIi8+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9tYXNrPlxyXG4gICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNOTMuMTE3MiAxOUM5NC4wNjI1IDE5IDk0Ljk4OTIgMTkuMDgyOCA5NS44ODg3IDE5LjI0MjJWMTE2Ljc4NEM5NC45ODkyIDExNi42MjUgOTQuMDYyNSAxMTYuNTQyIDkzLjExNzIgMTE2LjU0Mkg4Mi43NzQ0Qzc0LjA2NDIgMTE2LjU0MiA2Ny4wMDMxIDEyMy42MDMgNjcuMDAyOSAxMzIuMzEzVjM0Ljc3MTVDNjcuMDAyOSAyNi4wNjEyIDc0LjA2NDEgMTkgODIuNzc0NCAxOUg5My4xMTcyWlwiIGZpbGw9XCIjNkJDQUZGXCIvPlxyXG4gICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNOTMuMTE3MiAxOUw5My4xMTczIDE2SDkzLjExNzJWMTlaTTk1Ljg4ODcgMTkuMjQyMkg5OC44ODg3VjE2LjcyNzFMOTYuNDEyMiAxNi4yODgyTDk1Ljg4ODcgMTkuMjQyMlpNOTUuODg4NyAxMTYuNzg0TDk1LjM2NTEgMTE5LjczOEw5OC44ODg3IDEyMC4zNjNWMTE2Ljc4NEg5NS44ODg3Wk05My4xMTcyIDExNi41NDJMOTMuMTE3MyAxMTMuNTQySDkzLjExNzJWMTE2LjU0MlpNNjcuMDAyOSAxMzIuMzEzSDY0LjAwMjlMNzAuMDAyOSAxMzIuMzE0TDY3LjAwMjkgMTMyLjMxM1pNOTMuMTE3MiAxOUw5My4xMTcxIDIyQzkzLjg4NzIgMjIgOTQuNjM4NyAyMi4wNjc0IDk1LjM2NTEgMjIuMTk2MUw5NS44ODg3IDE5LjI0MjJMOTYuNDEyMiAxNi4yODgyQzk1LjMzOTYgMTYuMDk4MSA5NC4yMzc3IDE2IDkzLjExNzMgMTZMOTMuMTE3MiAxOVpNOTUuODg4NyAxOS4yNDIySDkyLjg4ODdWMTE2Ljc4NEg5NS44ODg3SDk4Ljg4ODdWMTkuMjQyMkg5NS44ODg3Wk05NS44ODg3IDExNi43ODRMOTYuNDEyMiAxMTMuODNDOTUuMzM5NiAxMTMuNjQgOTQuMjM3NyAxMTMuNTQyIDkzLjExNzMgMTEzLjU0Mkw5My4xMTcyIDExNi41NDJMOTMuMTE3MSAxMTkuNTQyQzkzLjg4NzIgMTE5LjU0MiA5NC42Mzg3IDExOS42MDkgOTUuMzY1MSAxMTkuNzM4TDk1Ljg4ODcgMTE2Ljc4NFpNOTMuMTE3MiAxMTYuNTQyVjExMy41NDJIODIuNzc0NFYxMTYuNTQyVjExOS41NDJIOTMuMTE3MlYxMTYuNTQyWk04Mi43NzQ0IDExNi41NDJWMTEzLjU0MkM3Mi40MDczIDExMy41NDIgNjQuMDAzMiAxMjEuOTQ3IDY0LjAwMjkgMTMyLjMxM0w2Ny4wMDI5IDEzMi4zMTNMNzAuMDAyOSAxMzIuMzE0QzcwLjAwMzEgMTI1LjI2IDc1LjcyMTIgMTE5LjU0MiA4Mi43NzQ0IDExOS41NDJWMTE2LjU0MlpNNjcuMDAyOSAxMzIuMzEzSDcwLjAwMjlWMzQuNzcxNUg2Ny4wMDI5SDY0LjAwMjlWMTMyLjMxM0g2Ny4wMDI5Wk02Ny4wMDI5IDM0Ljc3MTVINzAuMDAyOUM3MC4wMDI5IDI3LjcxOCA3NS43MjEgMjIgODIuNzc0NCAyMlYxOVYxNkM3Mi40MDcyIDE2IDY0LjAwMjkgMjQuNDA0MyA2NC4wMDI5IDM0Ljc3MTVINjcuMDAyOVpNODIuNzc0NCAxOVYyMkg5My4xMTcyVjE5VjE2SDgyLjc3NDRWMTlaXCIgZmlsbD1cIiMwMEEzRkZcIiBtYXNrPVwidXJsKCNwYXRoLTgtaW5zaWRlLTFfOTM2XzE1MDM4MylcIi8+XHJcbiAgICAgICAgICAgICAgICAgICAgPGxpbmUgeDE9XCI3Ni45NjE5XCIgeTE9XCI0Mi42NTIzXCIgeDI9XCI3Ni45NjE5XCIgeTI9XCI4NC40ODgxXCIgc3Ryb2tlPVwiIzk5REFGRlwiIHN0cm9rZS13aWR0aD1cIjMuOTg0MzZcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIvPlxyXG4gICAgICAgICAgICAgICAgICAgIDxjaXJjbGUgY3g9XCIyMTguMjA2XCIgY3k9XCI3MC4xNzU1XCIgcj1cIjMuMjk2NjNcIiBmaWxsPVwid2hpdGVcIi8+XHJcbiAgICAgICAgICAgICAgICAgICAgPGNpcmNsZSBjeD1cIjExMS43ODdcIiBjeT1cIjU1LjE2N1wiIHI9XCIyLjUyNjM3XCIgZmlsbD1cIiM5OURBRkZcIi8+XHJcbiAgICAgICAgICAgICAgICAgICAgPGNpcmNsZSBjeD1cIjk5LjM4NDVcIiBjeT1cIjEyNC45ODZcIiByPVwiMy40NDUwNVwiIGZpbGw9XCJ3aGl0ZVwiLz5cclxuICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPVwiTTEzNS41MjkgMzMuNDcxN0MxNTEuMjg1IDI0LjM3NDkgMTcxLjQzMiAyOS43NzMyIDE4MC41MjkgNDUuNTI5M0MxODguNTYgNTkuNDM5OCAxODUuMjkxIDc2Ljc3MDcgMTczLjU3MyA4Ni45MDA0TDE5My40NTcgMTIxLjMzOUMxOTQuOTMyIDEyMy44OTQgMTk0LjA1NiAxMjcuMTYxIDE5MS41MDEgMTI4LjYzNkMxODguOTQ2IDEzMC4xMTEgMTg1LjY3OSAxMjkuMjM2IDE4NC4yMDQgMTI2LjY4MUwxNjQuNDY2IDkyLjQ5MzJDMTQ5LjQ0NyA5OC42NTUyIDEzMS44MTQgOTIuOTIgMTIzLjQ3MiA3OC40NzE3QzExNC4zNzUgNjIuNzE1NiAxMTkuNzczIDQyLjU2ODUgMTM1LjUyOSAzMy40NzE3Wk0xNzIuNjk4IDUwLjA1MThDMTY2LjA5OSAzOC42MjA5IDE1MS40ODIgMzQuNzA0MSAxNDAuMDUxIDQxLjMwMzdDMTI4LjYyIDQ3LjkwMzUgMTI0LjcwMyA2Mi41MjA0IDEzMS4zMDMgNzMuOTUxMkMxMzcuOTAyIDg1LjM4MTcgMTUyLjUxOSA4OS4yOTc3IDE2My45NSA4Mi42OTgyQzE3NS4zODEgNzYuMDk4NyAxNzkuMjk3IDYxLjQ4MjYgMTcyLjY5OCA1MC4wNTE4WlwiIGZpbGw9XCJ3aGl0ZVwiLz5cclxuICAgICAgICAgICAgICAgICAgICA8Y2lyY2xlIGN4PVwiMTUzLjAwMVwiIGN5PVwiNTcuMDAxN1wiIHI9XCIyMy44OTk0XCIgdHJhbnNmb3JtPVwicm90YXRlKC0zMCAxNTMuMDAxIDU3LjAwMTcpXCIgZmlsbD1cIiM5OURBRkZcIi8+XHJcbiAgICAgICAgICAgICAgICAgICAgPG1hc2sgaWQ9XCJwYXRoLTE2LWluc2lkZS0yXzkzNl8xNTAzODNcIiBmaWxsPVwid2hpdGVcIj5cclxuICAgICAgICAgICAgICAgICAgICA8cGF0aCBkPVwiTTE1My4zODQgNDAuOTk1N0MxNTMuNDM1IDM5LjcwMDEgMTUyLjQyMyAzOC41OTI3IDE1MS4xMzEgMzguNzA5NUMxNDguODU4IDM4LjkxNTEgMTQ2LjYzNiAzOS41NDkxIDE0NC41ODYgNDAuNTg1NEMxNDEuODM1IDQxLjk3NiAxMzkuNDg0IDQ0LjA0NSAxMzcuNzU1IDQ2LjU5N0MxMzYuMDI2IDQ5LjE0OSAxMzQuOTc3IDUyLjA5OTYgMTM0LjcwNiA1NS4xNzAxQzEzNC41MDQgNTcuNDU4MyAxMzQuNzM5IDU5Ljc1NjggMTM1LjM5MSA2MS45NDQ3QzEzNS43NjIgNjMuMTg3MiAxMzcuMTY2IDYzLjcxNjkgMTM4LjM1IDYzLjE4OTFDMTM5LjUzNCA2Mi42NjEyIDE0MC4wNDQgNjEuMjc0NiAxMzkuNzMgNjAuMDE2NUMxMzkuMzcgNTguNTczNSAxMzkuMjUxIDU3LjA3NTMgMTM5LjM4MyA1NS41ODNDMTM5LjU4NCA1My4zMDc4IDE0MC4zNjEgNTEuMTIxNCAxNDEuNjQyIDQ5LjIzMDRDMTQyLjkyNCA0Ny4zMzk0IDE0NC42NjYgNDUuODA2MyAxNDYuNzA0IDQ0Ljc3NThDMTQ4LjA0MSA0NC4xIDE0OS40NzcgNDMuNjU1MSAxNTAuOTUgNDMuNDU0MkMxNTIuMjM1IDQzLjI3OTIgMTUzLjMzMyA0Mi4yOTEzIDE1My4zODQgNDAuOTk1N1pcIi8+XHJcbiAgICAgICAgICAgICAgICAgICAgPC9tYXNrPlxyXG4gICAgICAgICAgICAgICAgICAgIDxwYXRoIGQ9XCJNMTUzLjM4NCA0MC45OTU3QzE1My40MzUgMzkuNzAwMSAxNTIuNDIzIDM4LjU5MjcgMTUxLjEzMSAzOC43MDk1QzE0OC44NTggMzguOTE1MSAxNDYuNjM2IDM5LjU0OTEgMTQ0LjU4NiA0MC41ODU0QzE0MS44MzUgNDEuOTc2IDEzOS40ODQgNDQuMDQ1IDEzNy43NTUgNDYuNTk3QzEzNi4wMjYgNDkuMTQ5IDEzNC45NzcgNTIuMDk5NiAxMzQuNzA2IDU1LjE3MDFDMTM0LjUwNCA1Ny40NTgzIDEzNC43MzkgNTkuNzU2OCAxMzUuMzkxIDYxLjk0NDdDMTM1Ljc2MiA2My4xODcyIDEzNy4xNjYgNjMuNzE2OSAxMzguMzUgNjMuMTg5MUMxMzkuNTM0IDYyLjY2MTIgMTQwLjA0NCA2MS4yNzQ2IDEzOS43MyA2MC4wMTY1QzEzOS4zNyA1OC41NzM1IDEzOS4yNTEgNTcuMDc1MyAxMzkuMzgzIDU1LjU4M0MxMzkuNTg0IDUzLjMwNzggMTQwLjM2MSA1MS4xMjE0IDE0MS42NDIgNDkuMjMwNEMxNDIuOTI0IDQ3LjMzOTQgMTQ0LjY2NiA0NS44MDYzIDE0Ni43MDQgNDQuNzc1OEMxNDguMDQxIDQ0LjEgMTQ5LjQ3NyA0My42NTUxIDE1MC45NSA0My40NTQyQzE1Mi4yMzUgNDMuMjc5MiAxNTMuMzMzIDQyLjI5MTMgMTUzLjM4NCA0MC45OTU3WlwiIHN0cm9rZT1cIndoaXRlXCIgc3Ryb2tlLXdpZHRoPVwiNlwiIG1hc2s9XCJ1cmwoI3BhdGgtMTYtaW5zaWRlLTJfOTM2XzE1MDM4MylcIi8+XHJcbiAgICAgICAgICAgICAgICAgICAgPHBhdGggZD1cIk0xMzYuNTI5IDI4LjQ3MTdDMTUyLjI4NSAxOS4zNzQ5IDE3Mi40MzIgMjQuNzczMiAxODEuNTI5IDQwLjUyOTNDMTg5LjU2IDU0LjQzOTggMTg2LjI5MSA3MS43NzA3IDE3NC41NzMgODEuOTAwNEwxOTQuNDU3IDExNi4zMzlDMTk1LjkzMiAxMTguODk0IDE5NS4wNTYgMTIyLjE2MSAxOTIuNTAxIDEyMy42MzZDMTg5Ljk0NiAxMjUuMTExIDE4Ni42NzkgMTI0LjIzNiAxODUuMjA0IDEyMS42ODFMMTY1LjQ2NiA4Ny40OTMyQzE1MC40NDcgOTMuNjU1MiAxMzIuODE0IDg3LjkyIDEyNC40NzIgNzMuNDcxN0MxMTUuMzc1IDU3LjcxNTYgMTIwLjc3MyAzNy41Njg1IDEzNi41MjkgMjguNDcxN1pNMTczLjY5OCA0NS4wNTE4QzE2Ny4wOTkgMzMuNjIwOSAxNTIuNDgyIDI5LjcwNDEgMTQxLjA1MSAzNi4zMDM3QzEyOS42MiA0Mi45MDM1IDEyNS43MDMgNTcuNTIwNCAxMzIuMzAzIDY4Ljk1MTJDMTM4LjkwMiA4MC4zODE3IDE1My41MTkgODQuMjk3NyAxNjQuOTUgNzcuNjk4MkMxNzYuMzgxIDcxLjA5ODcgMTgwLjI5NyA1Ni40ODI2IDE3My42OTggNDUuMDUxOFpcIiBmaWxsPVwiIzAwQTNGRlwiLz5cclxuICAgICAgICAgICAgICAgICAgICA8L3N2Zz4gICAgICAgICAgICAgICAgICAgIFxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICAgICAgPGgzPk5vIHByZXZpZXcgeWV0PC9oMz5cclxuICAgICAgICAgICAgPHA+QWRkIGEgZmluZCBhbmQgcmVwbGFjZW1lbnQgdG8gcHJldmlldy48L3A+XHJcbiAgICAgICAgPC9kaXY+XHJcblxyXG4gICAgICAgIDwhLS0gQWN0aW9uIEJ1dHRvbiBTZWN0aW9uIC0tPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJhY3Rpb24tYnV0dG9uLXNlY3Rpb25cIiAqbmdJZj1cImhhc1N0b3Jlc1wiPlxyXG4gICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwiYnRuLWFwcGx5XCIgdHlwZT1cImJ1dHRvblwiIChjbGljayk9XCJvblJldmlld0FuZFJlcGxhY2UoKVwiIFtkaXNhYmxlZF09XCJsb2FkaW5nIHx8IGZpbmRMb2FkaW5nIHx8IHJlcGxhY2VMb2FkaW5nIHx8IGJhdGNoUHJvY2Vzc2luZ1wiPlxyXG4gICAgICAgICAgICAgICAge3sgYmF0Y2hQcm9jZXNzaW5nID8gJ1Byb2Nlc3NpbmcuLi4nIDogJ1JldmlldyBBbmQgUmVwbGFjZScgfX1cclxuICAgICAgICAgICAgPC9idXR0b24+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICA8L2Zvcm0+XHJcbjwvZGl2PlxyXG4iXX0=