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,1110 @@
1
+ import { TitleCasePipe } from "@angular/common";
2
+ import { Component, EventEmitter, HostListener, Input, Output, ViewChild, } from "@angular/core";
3
+ import { Subject, takeUntil } from "rxjs";
4
+ import * as fabric from "fabric";
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "tango-app-ui-global";
7
+ import * as i2 from "@angular/common";
8
+ import * as i3 from "./misplaced-product-fixture/misplaced-product-fixture.component";
9
+ export class ProductLocatorComponent {
10
+ gs;
11
+ titleCase;
12
+ floorData;
13
+ selectedProduct;
14
+ canvasEl;
15
+ containerRef;
16
+ targetFixtureFullDetails = new EventEmitter();
17
+ onResize() {
18
+ setTimeout(() => {
19
+ this.resizeCanvas();
20
+ }, 300);
21
+ }
22
+ canvas;
23
+ clientId;
24
+ cdnUrl;
25
+ zoomLevel = 1;
26
+ fixtureHeight = this.toPixels(1524, "mm");
27
+ fixtureWidth = this.toPixels(1220, "mm");
28
+ wallThickness = 30;
29
+ verticalMargin = (1.25 / 100) * this.fixtureHeight;
30
+ isPageLoading = false;
31
+ selectedFixture;
32
+ selectedFixtureData;
33
+ activeHighlight = null;
34
+ cancelHighlightBlink = false;
35
+ destroy$ = new Subject();
36
+ constructor(gs, titleCase) {
37
+ this.gs = gs;
38
+ this.titleCase = titleCase;
39
+ this.gs.environment.pipe(takeUntil(this.destroy$)).subscribe((e) => {
40
+ if (e)
41
+ this.cdnUrl = e.planogramCDN;
42
+ });
43
+ }
44
+ ngOnChanges(changes) {
45
+ if (changes["floorData"]?.currentValue) {
46
+ this.floorData = changes["floorData"].currentValue;
47
+ if (this.floorData?.floorChange) {
48
+ this.onClickClose();
49
+ this.renderFloor();
50
+ }
51
+ }
52
+ }
53
+ ngAfterViewInit() {
54
+ this.canvas = new fabric.Canvas(this.canvasEl?.nativeElement, {
55
+ selection: false,
56
+ perPixelTargetFind: true,
57
+ targetFindTolerance: 5,
58
+ width: 560,
59
+ height: 450,
60
+ });
61
+ // this.setupZoomHandlers();
62
+ if (this.floorData) {
63
+ this.renderFloor();
64
+ }
65
+ }
66
+ resizeCanvas() {
67
+ const container = this.containerRef.nativeElement;
68
+ this.canvas.setDimensions({
69
+ width: container.clientWidth - 50,
70
+ height: container.clientHeight - 40,
71
+ });
72
+ this.canvas.requestRenderAll();
73
+ }
74
+ setupZoomHandlers() {
75
+ this.canvas.on("mouse:wheel", (opt) => {
76
+ const e = opt.e;
77
+ if (e.ctrlKey || e.metaKey) {
78
+ const delta = e.deltaY;
79
+ let zoom = this.canvas.getZoom();
80
+ zoom *= 0.995 ** delta;
81
+ zoom = Math.max(0.2, Math.min(zoom, 3));
82
+ this.canvas.zoomToPoint({
83
+ x: e.offsetX,
84
+ y: e.offsetY,
85
+ }, zoom);
86
+ e.preventDefault();
87
+ e.stopPropagation();
88
+ }
89
+ });
90
+ let isDragging = false;
91
+ let lastPosX = 0;
92
+ let lastPosY = 0;
93
+ this.canvas.on("mouse:down", (opt) => {
94
+ if (!opt.target) {
95
+ isDragging = true;
96
+ this.canvas.selection = false;
97
+ const e = opt.e;
98
+ lastPosX = e.clientX;
99
+ lastPosY = e.clientY;
100
+ }
101
+ });
102
+ this.canvas.on("mouse:move", (opt) => {
103
+ if (isDragging && this.canvas.viewportTransform) {
104
+ const e = opt.e;
105
+ const vpt = this.canvas.viewportTransform;
106
+ vpt[4] += e.clientX - lastPosX;
107
+ vpt[5] += e.clientY - lastPosY;
108
+ this.canvas.requestRenderAll();
109
+ lastPosX = e.clientX;
110
+ lastPosY = e.clientY;
111
+ }
112
+ });
113
+ this.canvas.on("mouse:up", () => {
114
+ isDragging = false;
115
+ this.canvas.selection = true;
116
+ });
117
+ }
118
+ async renderFloor() {
119
+ this.canvas?.clear();
120
+ await this.drawLayoutElements();
121
+ setTimeout(() => {
122
+ this.resizeCanvas();
123
+ this.fitCanvasToLayoutAnimated();
124
+ }, 300);
125
+ if (this.selectedProduct?.fixtureDetails) {
126
+ this.onChangeFixture(this.selectedProduct.fixtureDetails);
127
+ }
128
+ }
129
+ fitCanvasToLayoutAnimated(duration = 300) {
130
+ if (!this.canvas)
131
+ return;
132
+ const bounds = this.getFullLayoutBounds();
133
+ if (!bounds.width || !bounds.height)
134
+ return;
135
+ const canvasW = this.canvas.getWidth();
136
+ const canvasH = this.canvas.getHeight();
137
+ // Compute zoom to fit
138
+ const scaleX = canvasW / bounds.width;
139
+ const scaleY = canvasH / bounds.height;
140
+ const targetZoom = Math.min(scaleX, scaleY);
141
+ const targetVpt = [
142
+ ...(this.canvas.viewportTransform || [1, 0, 0, 1, 0, 0]),
143
+ ];
144
+ targetVpt[0] = targetZoom; // scaleX
145
+ targetVpt[3] = targetZoom; // scaleY
146
+ // Center X
147
+ targetVpt[4] = canvasW / 2 - (bounds.left + bounds.width / 2) * targetZoom;
148
+ // ----- FIXED: keep layout slightly up without stacking -----
149
+ const centeredY = canvasH / 2 - (bounds.top + bounds.height / 2) * targetZoom;
150
+ const scaledHeight = bounds.height * targetZoom;
151
+ const emptySpaceY = canvasH - scaledHeight;
152
+ const shiftUp = emptySpaceY > 0 ? emptySpaceY * 0.25 : 0;
153
+ targetVpt[5] = centeredY - shiftUp;
154
+ // Animate
155
+ const startVpt = [...this.canvas.viewportTransform];
156
+ fabric.util.animate({
157
+ startValue: 0,
158
+ endValue: 1,
159
+ duration,
160
+ easing: fabric.util.ease.easeOutCubic,
161
+ onChange: (value) => {
162
+ const vpt = this.canvas.viewportTransform;
163
+ vpt[0] = startVpt[0] + (targetVpt[0] - startVpt[0]) * value;
164
+ vpt[3] = startVpt[3] + (targetVpt[3] - startVpt[3]) * value;
165
+ vpt[4] = startVpt[4] + (targetVpt[4] - startVpt[4]) * value;
166
+ vpt[5] = startVpt[5] + (targetVpt[5] - startVpt[5]) * value;
167
+ this.canvas.requestRenderAll();
168
+ },
169
+ });
170
+ }
171
+ async drawLayoutElements() {
172
+ for (let index = 0; index < this.floorData.layoutPolygon.length; index++) {
173
+ const element = this.floorData.layoutPolygon[index];
174
+ let wall;
175
+ element.relativePosition ??= {
176
+ x: 0,
177
+ y: 0,
178
+ unit: "ft",
179
+ };
180
+ const x = this.toPixels(element.relativePosition.x, element.unit);
181
+ const y = this.toPixels(element.relativePosition.y, element.unit);
182
+ if (element.elementType === "wall") {
183
+ const height = this.wallThickness;
184
+ const width = this.toPixels(element.distance, element.unit);
185
+ wall = this.drawWall(this.canvas, x, y, height, width, element);
186
+ }
187
+ else if (element.elementType === "entrance") {
188
+ const arrowWidth = 80;
189
+ const arrowHeight = 75;
190
+ const arrowBase = 40;
191
+ this.drawEntrance(this.canvas, x, y, arrowWidth, arrowHeight, arrowBase, element);
192
+ }
193
+ if (element.elementType === "wall") {
194
+ const fixtureGroups = [];
195
+ for (let j = 0; j < element?.fixtures?.length; j++) {
196
+ const fixture = element.fixtures[j];
197
+ const x = this.toPixels(fixture.relativePosition.x, fixture.relativePosition.unit);
198
+ const y = this.toPixels(fixture.relativePosition.y, fixture.relativePosition.unit);
199
+ const fixtureHeight = this.toPixels(fixture.fixtureStaticLength.value, fixture.fixtureStaticLength.unit);
200
+ const fixtureWidth = this.toPixels(fixture.fixtureStaticWidth.value, fixture.fixtureStaticWidth.unit);
201
+ const fixtureObj = await this.drawFixture(this.canvas, x, y, fixtureHeight, fixtureWidth, fixture);
202
+ fixtureGroups.push(fixtureObj);
203
+ }
204
+ if (element.isLocked && wall) {
205
+ this.canvas.remove(wall);
206
+ fixtureGroups.forEach((f) => this.canvas.remove(f));
207
+ const combinedGroup = new fabric.Group([wall, ...fixtureGroups], {
208
+ hasControls: true,
209
+ selectable: true,
210
+ subTargetCheck: true,
211
+ });
212
+ combinedGroup.set({ isLocked: true });
213
+ this.canvas.add(combinedGroup);
214
+ }
215
+ for (let j = 0; j < element?.otherElements?.length; j++) {
216
+ const otherElement = element.otherElements[j];
217
+ const x = this.toPixels(otherElement.relativePosition.x, "ft");
218
+ const y = this.toPixels(otherElement.relativePosition.y, "ft");
219
+ const h = this.toPixels(otherElement.fixtureStaticLength.value, otherElement.fixtureStaticLength.unit);
220
+ const w = this.toPixels(otherElement.fixtureStaticWidth.value, otherElement.fixtureStaticWidth.unit);
221
+ this.drawLabeledRectangle(this.canvas, x, y, w, h, otherElement);
222
+ }
223
+ }
224
+ }
225
+ for (let i = 0; i < this.floorData?.centerFixture?.length; i++) {
226
+ const fixture = this.floorData.centerFixture[i];
227
+ const x = this.toPixels(fixture.relativePosition.x, fixture.relativePosition.unit);
228
+ const y = this.toPixels(fixture.relativePosition.y, fixture.relativePosition.unit);
229
+ const fixtureHeight = this.toPixels(fixture.fixtureStaticLength.value, fixture.fixtureStaticLength.unit);
230
+ const fixtureWidth = this.toPixels(fixture.fixtureStaticWidth.value, fixture.fixtureStaticWidth.unit);
231
+ await this.drawFixture(this.canvas, x, y, fixtureHeight, fixtureWidth, fixture);
232
+ }
233
+ for (let j = 0; j < this.floorData?.otherElements?.length; j++) {
234
+ const otherElement = this.floorData.otherElements[j];
235
+ const x = this.toPixels(otherElement.relativePosition.x, "ft");
236
+ const y = this.toPixels(otherElement.relativePosition.y, "ft");
237
+ const h = this.toPixels(otherElement.fixtureStaticLength.value, otherElement.fixtureStaticLength.unit);
238
+ const w = this.toPixels(otherElement.fixtureStaticWidth.value, otherElement.fixtureStaticWidth.unit);
239
+ this.drawLabeledRectangle(this.canvas, x, y, w, h, otherElement);
240
+ }
241
+ }
242
+ drawWall(canvas, x, y, height, width, elementData) {
243
+ const radius = 5;
244
+ const fillColor = "#F6FCFF";
245
+ const strokeColor = "#D0D5DD";
246
+ const labelColor = "#009BF3";
247
+ const text = `${this.titleCase.transform(elementData.elementType)} ${elementData.elementNumber}`;
248
+ const wall = new fabric.Rect({
249
+ left: 0,
250
+ top: 0,
251
+ width,
252
+ height,
253
+ rx: radius,
254
+ ry: radius,
255
+ fill: fillColor,
256
+ stroke: strokeColor,
257
+ strokeWidth: 0.27,
258
+ selectable: false,
259
+ });
260
+ const centerX = width / 2;
261
+ const centerY = height / 2;
262
+ const isVertical = height > width;
263
+ const label = new fabric.FabricText(text, {
264
+ left: centerX,
265
+ top: centerY,
266
+ fontSize: 10,
267
+ fontFamily: "Inter",
268
+ fontWeight: "500",
269
+ fill: labelColor,
270
+ originX: "center",
271
+ originY: "center",
272
+ angle: isVertical ? -90 : 0,
273
+ selectable: false,
274
+ });
275
+ const arrowHead = 5;
276
+ const elements = [wall, label];
277
+ if (isVertical) {
278
+ const textWidth = label.width || 0;
279
+ const topArrowY = 5;
280
+ const topArrowEndY = centerY - textWidth / 2 - 5;
281
+ if (topArrowEndY > topArrowY + arrowHead) {
282
+ elements.push(new fabric.Line([centerX, topArrowY, centerX, topArrowEndY], {
283
+ stroke: labelColor,
284
+ strokeWidth: 1,
285
+ selectable: false,
286
+ }), new fabric.Triangle({
287
+ left: centerX,
288
+ top: topArrowY,
289
+ width: arrowHead,
290
+ height: arrowHead,
291
+ angle: 0,
292
+ fill: labelColor,
293
+ originX: "center",
294
+ originY: "bottom",
295
+ selectable: false,
296
+ }));
297
+ }
298
+ const bottomArrowStartY = centerY + textWidth / 2 + 5;
299
+ const bottomArrowEndY = height - 5;
300
+ if (bottomArrowEndY > bottomArrowStartY + arrowHead) {
301
+ elements.push(new fabric.Line([centerX, bottomArrowStartY, centerX, bottomArrowEndY], {
302
+ stroke: labelColor,
303
+ strokeWidth: 1,
304
+ selectable: false,
305
+ }), new fabric.Triangle({
306
+ left: centerX,
307
+ top: bottomArrowEndY,
308
+ width: arrowHead,
309
+ height: arrowHead,
310
+ angle: 180,
311
+ fill: labelColor,
312
+ originX: "center",
313
+ originY: "top",
314
+ selectable: false,
315
+ }));
316
+ }
317
+ }
318
+ else {
319
+ const textWidth = label.width || 0;
320
+ const leftArrowStartX = 5;
321
+ const leftArrowEndX = centerX - textWidth / 2 - 5;
322
+ if (leftArrowEndX > leftArrowStartX + arrowHead) {
323
+ elements.push(new fabric.Line([leftArrowStartX, centerY, leftArrowEndX, centerY], {
324
+ stroke: labelColor,
325
+ strokeWidth: 1,
326
+ selectable: false,
327
+ }), new fabric.Triangle({
328
+ left: leftArrowStartX,
329
+ top: centerY,
330
+ width: arrowHead,
331
+ height: arrowHead,
332
+ angle: -90,
333
+ fill: labelColor,
334
+ originX: "center",
335
+ originY: "center",
336
+ selectable: false,
337
+ }));
338
+ }
339
+ const rightArrowStartX = centerX + textWidth / 2 + 5;
340
+ const rightArrowEndX = width - 5;
341
+ if (rightArrowEndX > rightArrowStartX + arrowHead) {
342
+ elements.push(new fabric.Line([rightArrowStartX, centerY, rightArrowEndX, centerY], {
343
+ stroke: labelColor,
344
+ strokeWidth: 1,
345
+ selectable: false,
346
+ }), new fabric.Triangle({
347
+ left: rightArrowEndX,
348
+ top: centerY,
349
+ width: arrowHead,
350
+ height: arrowHead,
351
+ angle: 90,
352
+ fill: labelColor,
353
+ originX: "center",
354
+ originY: "center",
355
+ selectable: false,
356
+ }));
357
+ }
358
+ }
359
+ const group = new fabric.Group(elements, {
360
+ left: x,
361
+ top: y,
362
+ hasControls: false,
363
+ lockScalingX: true,
364
+ lockScalingY: true,
365
+ lockRotation: true,
366
+ selectable: false,
367
+ angle: elementData.angle,
368
+ });
369
+ group.objType = elementData.elementType;
370
+ group.data = elementData;
371
+ canvas.add(group);
372
+ return group;
373
+ }
374
+ drawEntrance(canvas, x, y, width, height, arrowWidth, elementData) {
375
+ const bodyWidth = width - arrowWidth;
376
+ const pathData = [
377
+ `M 0 0`,
378
+ `L ${bodyWidth} 0`,
379
+ `L ${bodyWidth} ${-height / 2}`,
380
+ `L ${width} ${height / 2}`,
381
+ `L ${bodyWidth} ${height + height / 2}`,
382
+ `L ${bodyWidth} ${height}`,
383
+ `L 0 ${height}`,
384
+ `Z`,
385
+ ].join(" ");
386
+ const arrow = new fabric.Path(pathData, {
387
+ fill: "#03A9F4",
388
+ selectable: false,
389
+ evented: false,
390
+ });
391
+ const maxTextHeight = height - 6;
392
+ const text = new fabric.Text("Entrance", {
393
+ fontFamily: "Arial",
394
+ fontWeight: "bold",
395
+ fill: "white",
396
+ angle: -90,
397
+ originX: "center",
398
+ originY: "center",
399
+ left: 15,
400
+ top: height / 2,
401
+ fontSize: 20,
402
+ selectable: false,
403
+ evented: false,
404
+ });
405
+ const textBounds = text.getBoundingRect();
406
+ if (textBounds.height > maxTextHeight) {
407
+ const scale = maxTextHeight / textBounds.height;
408
+ text.set("fontSize", text.fontSize * scale);
409
+ }
410
+ const group = new fabric.Group([arrow, text], {
411
+ left: x,
412
+ top: y,
413
+ selectable: false,
414
+ lockScalingX: true,
415
+ lockScalingY: true,
416
+ lockScalingFlip: true,
417
+ angle: elementData.angle,
418
+ });
419
+ group.objType = elementData.elementType;
420
+ group.data = elementData;
421
+ canvas.add(group);
422
+ }
423
+ async drawFixture(canvas, x, y, height, width, fixtureData) {
424
+ const isTargetFixture = this.selectedProduct?.fixtureDetails?.fixtureId === fixtureData?._id;
425
+ const radius = 5;
426
+ const mainContainer = new fabric.Rect({
427
+ left: x,
428
+ top: y,
429
+ width: width,
430
+ height: height,
431
+ rx: radius,
432
+ ry: radius,
433
+ stroke: isTargetFixture ? "#51C1FF" : "#c2c2c2",
434
+ strokeWidth: 0.27,
435
+ fill: "white",
436
+ });
437
+ const topWidth = width / 1.05;
438
+ const topHeight = (15 / 100) * height;
439
+ const topX = x + (width - topWidth) / 2;
440
+ const topY = y + this.verticalMargin;
441
+ const topContainer = new fabric.Rect({
442
+ left: topX,
443
+ top: topY,
444
+ width: topWidth,
445
+ height: topHeight,
446
+ rx: radius,
447
+ ry: radius,
448
+ stroke: isTargetFixture ? "#51C1FF" : "#c2c2c2",
449
+ strokeWidth: 0.27,
450
+ fill: "white",
451
+ });
452
+ const innerBoxHeight = topHeight / 2;
453
+ const innerTopBox = new fabric.Path(`M ${topX + radius} ${topY}
454
+ L ${topX + topWidth - radius} ${topY}
455
+ Q ${topX + topWidth} ${topY} ${topX + topWidth} ${topY + radius}
456
+ L ${topX + topWidth} ${topY + innerBoxHeight}
457
+ L ${topX} ${topY + innerBoxHeight}
458
+ L ${topX} ${topY + radius}
459
+ Q ${topX} ${topY} ${topX + radius} ${topY} Z`, {
460
+ stroke: isTargetFixture ? "#51C1FF" : "#c2c2c2",
461
+ strokeWidth: 0.27,
462
+ fill: "transparent",
463
+ });
464
+ const topText = new fabric.Textbox(`Fixture ${fixtureData.associatedElementFixtureNumber
465
+ ? fixtureData.associatedElementFixtureNumber +
466
+ (fixtureData?.fixtureNumber
467
+ ? " - FX-" + fixtureData.fixtureNumber
468
+ : "")
469
+ : "new"}`, {
470
+ left: topX + topWidth / 2,
471
+ top: topY + innerBoxHeight / 2,
472
+ fontSize: 5,
473
+ fontFamily: "Inter",
474
+ fontWeight: "500",
475
+ fill: "#101828",
476
+ originX: "center",
477
+ originY: "center",
478
+ width: topWidth,
479
+ height: innerBoxHeight,
480
+ textAlign: "center",
481
+ });
482
+ const secondBoxY = topY + innerBoxHeight;
483
+ const innerBottomBox = new fabric.Path(`M ${topX} ${secondBoxY}
484
+ L ${topX + topWidth} ${secondBoxY}
485
+ L ${topX + topWidth} ${secondBoxY + innerBoxHeight - radius}
486
+ Q ${topX + topWidth} ${secondBoxY + innerBoxHeight} ${topX + topWidth - radius} ${secondBoxY + innerBoxHeight}
487
+ L ${topX + radius} ${secondBoxY + innerBoxHeight}
488
+ Q ${topX} ${secondBoxY + innerBoxHeight} ${topX} ${secondBoxY + innerBoxHeight - radius}
489
+ L ${topX} ${secondBoxY} Z`, {
490
+ fill: "#344054",
491
+ stroke: "#51C1FF",
492
+ strokeWidth: 0.27,
493
+ });
494
+ let fontSize = 5;
495
+ let bottomText;
496
+ const textContent = `${fixtureData?.fixtureName} - ${fixtureData?.fixtureWidth.value} ${fixtureData?.fixtureWidth.unit}`;
497
+ const createBottomText = (fs) => new fabric.Textbox(textContent, {
498
+ left: topX + topWidth / 2,
499
+ top: secondBoxY + innerBoxHeight / 2,
500
+ fontSize: fs,
501
+ fontFamily: "Inter",
502
+ fontWeight: "500",
503
+ fill: "#FFFFFF",
504
+ originX: "center",
505
+ originY: "center",
506
+ textAlign: "center",
507
+ width: topWidth,
508
+ });
509
+ do {
510
+ bottomText = createBottomText(fontSize);
511
+ fontSize -= 0.5;
512
+ } while (bottomText.height > innerBoxHeight && fontSize > 2);
513
+ const midWidth = width / 1.05;
514
+ const midHeight = (77 / 100) * height;
515
+ const midX = x + (width - midWidth) / 2;
516
+ const midY = topY + topHeight + this.verticalMargin;
517
+ const midContainer = new fabric.Rect({
518
+ left: midX,
519
+ top: midY,
520
+ width: midWidth,
521
+ height: midHeight,
522
+ rx: radius,
523
+ ry: radius,
524
+ stroke: "#51C1FF",
525
+ strokeWidth: 0.27,
526
+ fill: "white",
527
+ });
528
+ const shelfCount = fixtureData.shelfConfig?.length;
529
+ const boxHeight = midHeight / (shelfCount + 2);
530
+ const firstBoxY = midY;
531
+ const firstBox = new fabric.Path(`M ${midX + radius} ${firstBoxY}
532
+ L ${midX + midWidth - radius} ${firstBoxY}
533
+ Q ${midX + midWidth} ${firstBoxY} ${midX + midWidth} ${firstBoxY + radius}
534
+ L ${midX + midWidth} ${firstBoxY + boxHeight}
535
+ L ${midX} ${firstBoxY + boxHeight}
536
+ L ${midX} ${firstBoxY + radius}
537
+ Q ${midX} ${firstBoxY} ${midX + radius} ${firstBoxY} Z`, {
538
+ fill: isTargetFixture ? "#EAF8FF" : "#f9fbff",
539
+ stroke: isTargetFixture ? "#6BCAFF" : "#c2c2c2",
540
+ strokeWidth: 0.27,
541
+ });
542
+ const firstBoxText = new fabric.Textbox(`${fixtureData?.header?.label ? fixtureData.header.label : ""}`, {
543
+ left: midX + midWidth / 2,
544
+ top: firstBoxY + boxHeight / 2,
545
+ fontSize: 7,
546
+ fontFamily: "Inter",
547
+ fontWeight: "600",
548
+ fill: "#101828",
549
+ originX: "center",
550
+ originY: "center",
551
+ width: midWidth,
552
+ height: boxHeight,
553
+ textAlign: "center",
554
+ });
555
+ const shelves = [];
556
+ const shelfHeight = midHeight - 2 * boxHeight;
557
+ if (fixtureData.productResolutionLevel === "L1") {
558
+ const boxY = firstBoxY + boxHeight;
559
+ const shelf = new fabric.Rect({
560
+ left: midX,
561
+ top: boxY,
562
+ width: midWidth,
563
+ height: shelfHeight,
564
+ strokeWidth: 0.27,
565
+ stroke: isTargetFixture ? "#51C1FF" : "#c2c2c2",
566
+ fill: "#ffffff",
567
+ });
568
+ const text = fixtureData?.productBrandName?.join(" + ") || "";
569
+ // Wrap text within fixture width and shrink to fit vertical space
570
+ const maxTextWidth = midWidth * 0.9;
571
+ const maxTextHeight = shelfHeight * 0.8;
572
+ let fontSizeL1 = 6;
573
+ const createWrappedTextbox = (fs) => new fabric.Textbox(text, {
574
+ left: midX + midWidth / 2,
575
+ top: boxY + shelfHeight / 2,
576
+ originX: "center",
577
+ originY: "center",
578
+ width: maxTextWidth,
579
+ fontSize: fs,
580
+ fontFamily: "Inter",
581
+ fontWeight: "500",
582
+ textAlign: "center",
583
+ fill: "#1D2939",
584
+ selectable: false,
585
+ evented: false,
586
+ });
587
+ let wrappedText = createWrappedTextbox(fontSizeL1);
588
+ while (wrappedText.height > maxTextHeight && fontSizeL1 > 2) {
589
+ fontSizeL1 -= 0.5;
590
+ wrappedText = createWrappedTextbox(fontSizeL1);
591
+ }
592
+ shelves.push(shelf, wrappedText);
593
+ }
594
+ else if (fixtureData.productResolutionLevel === "L2") {
595
+ for (let i = 0; i < shelfCount; i++) {
596
+ const boxY = firstBoxY + boxHeight * (i + 1);
597
+ const shelf = new fabric.Rect({
598
+ left: midX,
599
+ top: boxY,
600
+ width: midWidth,
601
+ height: boxHeight,
602
+ strokeWidth: 0.27,
603
+ stroke: isTargetFixture ? "#51C1FF" : "#c2c2c2",
604
+ fill: "#ffffff",
605
+ });
606
+ shelves.push(shelf);
607
+ const text = fixtureData.shelfConfig?.[i].productBrandName?.join(" + ") || "";
608
+ // L2: Single-line ellipsis against full shelf width
609
+ const horizontalPadding = 6;
610
+ const maxTextWidth = Math.max(0, midWidth - horizontalPadding);
611
+ const baseFontSize = 5;
612
+ const measure = (t) => new fabric.Text(t, {
613
+ fontSize: baseFontSize,
614
+ fontFamily: "Inter",
615
+ fontWeight: "500",
616
+ });
617
+ let displayText = text;
618
+ let measured = measure(displayText);
619
+ if ((measured.width ?? 0) > maxTextWidth) {
620
+ const ellipsis = "...";
621
+ let leftIdx = 0;
622
+ let rightIdx = text.length;
623
+ while (leftIdx < rightIdx) {
624
+ const midIdx = Math.floor((leftIdx + rightIdx) / 2);
625
+ const candidate = text.slice(0, midIdx) + ellipsis;
626
+ measured = measure(candidate);
627
+ if ((measured.width ?? 0) > maxTextWidth) {
628
+ rightIdx = midIdx;
629
+ }
630
+ else {
631
+ leftIdx = midIdx + 1;
632
+ }
633
+ }
634
+ displayText = text.slice(0, Math.max(0, leftIdx - 1)) + ellipsis;
635
+ measured = measure(displayText);
636
+ }
637
+ const finalText = new fabric.Text(displayText, {
638
+ left: midX + midWidth / 2,
639
+ top: boxY + boxHeight / 2,
640
+ originX: "center",
641
+ originY: "center",
642
+ fontSize: baseFontSize,
643
+ fontFamily: "Inter",
644
+ fontWeight: "500",
645
+ fill: "#1D2939",
646
+ selectable: false,
647
+ evented: false,
648
+ });
649
+ shelves.push(finalText);
650
+ }
651
+ }
652
+ else if (fixtureData.productResolutionLevel === "L3") {
653
+ const sequentialGroups = [];
654
+ let previousZone = null;
655
+ for (const shelf of fixtureData.shelfConfig) {
656
+ const zone = shelf.zone || "Unknown";
657
+ if (zone !== previousZone) {
658
+ sequentialGroups.push({ zone, shelves: [shelf] });
659
+ previousZone = zone;
660
+ }
661
+ else {
662
+ sequentialGroups[sequentialGroups.length - 1].shelves.push(shelf);
663
+ }
664
+ }
665
+ let currentShelfIndex = 0;
666
+ for (const group of sequentialGroups) {
667
+ const { shelves: shelvesInGroup } = group;
668
+ const groupStartIndex = currentShelfIndex;
669
+ const groupLength = shelvesInGroup.length;
670
+ const groupTopY = firstBoxY + boxHeight * (groupStartIndex + 1);
671
+ const groupBottomY = groupTopY + boxHeight * groupLength;
672
+ const isTargetZone = shelvesInGroup.some((s) => s._id === this.selectedProduct?.fixtureDetails?.shelfId);
673
+ for (let j = 0; j < shelvesInGroup.length; j++) {
674
+ const boxY = firstBoxY + boxHeight * (currentShelfIndex + 1);
675
+ const isFirst = j === 0;
676
+ const isLast = j === shelvesInGroup.length - 1;
677
+ const fillColor = isTargetZone ? "#fef3f2" : "#f9fbff";
678
+ const borderColor = isTargetZone ? "#ffa3a3" : "#c2c2c2";
679
+ const pathData = [
680
+ `M ${midX} ${boxY} L ${midX} ${boxY + boxHeight}`,
681
+ `M ${midX + midWidth} ${boxY} L ${midX + midWidth} ${boxY + boxHeight}`,
682
+ isFirst ? `M ${midX} ${boxY} L ${midX + midWidth} ${boxY}` : "",
683
+ isLast
684
+ ? `M ${midX} ${boxY + boxHeight} L ${midX + midWidth} ${boxY + boxHeight}`
685
+ : "",
686
+ ].join(" ");
687
+ const fillRect = new fabric.Rect({
688
+ left: midX,
689
+ top: boxY,
690
+ width: midWidth,
691
+ height: boxHeight,
692
+ fill: fillColor,
693
+ selectable: false,
694
+ evented: false,
695
+ });
696
+ const borderPath = new fabric.Path(pathData, {
697
+ stroke: borderColor,
698
+ strokeWidth: 0.7,
699
+ fill: "",
700
+ selectable: false,
701
+ evented: false,
702
+ });
703
+ shelves.push(fillRect, borderPath);
704
+ currentShelfIndex++;
705
+ }
706
+ const groupBottomLine = new fabric.Line([midX, groupBottomY, midX + midWidth, groupBottomY], {
707
+ selectable: false,
708
+ evented: false,
709
+ });
710
+ shelves.push(groupBottomLine);
711
+ const groupCenterX = midX + midWidth / 2;
712
+ const groupCenterY = groupTopY + (groupBottomY - groupTopY) / 2;
713
+ const sectionBrands = new Set();
714
+ shelvesInGroup?.forEach((shelf) => {
715
+ shelf.productBrandName?.forEach((brand) => {
716
+ sectionBrands.add(brand);
717
+ });
718
+ });
719
+ if ([...sectionBrands].length) {
720
+ const text = [...sectionBrands].join(" + ");
721
+ const padding = 2;
722
+ const maxTextWidth = midWidth;
723
+ const rectWidth = midWidth * 0.9;
724
+ const maxTextHeight = 20;
725
+ let fontSize = 6;
726
+ let wrappedText;
727
+ const createTextbox = (fs) => {
728
+ return new fabric.Textbox(text, {
729
+ fontSize: fs,
730
+ fontFamily: "Inter",
731
+ fontWeight: "400",
732
+ width: maxTextWidth,
733
+ textAlign: "center",
734
+ originX: "center",
735
+ originY: "center",
736
+ fill: "#1D2939",
737
+ selectable: false,
738
+ evented: false,
739
+ left: groupCenterX,
740
+ top: groupCenterY,
741
+ });
742
+ };
743
+ do {
744
+ wrappedText = createTextbox(fontSize);
745
+ fontSize -= 0.5;
746
+ } while (wrappedText.height > maxTextHeight && fontSize > 2);
747
+ const rectHeight = wrappedText.getScaledHeight() + padding;
748
+ const groupCenterText = new fabric.Rect({
749
+ left: groupCenterX,
750
+ top: groupCenterY,
751
+ originX: "center",
752
+ originY: "center",
753
+ width: rectWidth,
754
+ height: rectHeight,
755
+ fill: "transparent",
756
+ selectable: false,
757
+ evented: false,
758
+ rx: 1,
759
+ ry: 1,
760
+ });
761
+ shelves.push(groupCenterText, wrappedText);
762
+ }
763
+ }
764
+ }
765
+ const lastBoxY = firstBoxY + boxHeight * (shelfCount + 1);
766
+ const lastBox = new fabric.Path(`M ${midX} ${lastBoxY}
767
+ L ${midX + midWidth} ${lastBoxY}
768
+ L ${midX + midWidth} ${lastBoxY + boxHeight - radius}
769
+ Q ${midX + midWidth} ${lastBoxY + boxHeight} ${midX + midWidth - radius} ${lastBoxY + boxHeight}
770
+ L ${midX + radius} ${lastBoxY + boxHeight}
771
+ Q ${midX} ${lastBoxY + boxHeight} ${midX} ${lastBoxY + boxHeight - radius}
772
+ L ${midX} ${lastBoxY} Z`, {
773
+ fill: isTargetFixture ? "#EAF8FF" : "#f9fbff",
774
+ stroke: isTargetFixture ? "#6BCAFF" : "#c2c2c2",
775
+ strokeWidth: 0.27,
776
+ });
777
+ const lastBoxText = new fabric.Textbox(`${fixtureData?.footer?.label ? fixtureData.footer.label : ""}`, {
778
+ left: midX + midWidth / 2,
779
+ top: lastBoxY + boxHeight / 2,
780
+ fontSize: 5,
781
+ fontFamily: "Inter",
782
+ fontWeight: "600",
783
+ fill: "#101828",
784
+ originX: "center",
785
+ originY: "center",
786
+ textAlign: "center",
787
+ width: midWidth,
788
+ heigth: boxHeight,
789
+ });
790
+ const bottomWidth = width / 1.05;
791
+ const bottomHeight = (3 / 100) * height;
792
+ const bottomX = x + (width - bottomWidth) / 2;
793
+ const bottomY = midY + midHeight + this.verticalMargin;
794
+ const bottomContainer = new fabric.Rect({
795
+ left: bottomX,
796
+ top: bottomY,
797
+ width: bottomWidth,
798
+ height: bottomHeight,
799
+ rx: radius,
800
+ ry: radius,
801
+ stroke: "transparent",
802
+ fill: "transparent",
803
+ });
804
+ const actualShelfCount = fixtureData?.shelfConfig?.filter((s) => s.shelfType != "vmonly")
805
+ ?.length ?? 0;
806
+ const bottomTextContent = new fabric.Textbox(`Shelves - ${actualShelfCount} . Products - ${fixtureData.fixtureCapacity} . VM - ${fixtureData.vmConfig?.length}`, {
807
+ left: bottomX + bottomWidth / 2,
808
+ top: bottomY + bottomHeight / 2,
809
+ fontSize: 5,
810
+ fontFamily: "Inter",
811
+ fontWeight: "500",
812
+ fill: "#333",
813
+ originX: "center",
814
+ originY: "center",
815
+ textAlign: "center",
816
+ width: bottomWidth,
817
+ height: bottomHeight,
818
+ });
819
+ const fixtureGroup = new fabric.Group([
820
+ mainContainer,
821
+ topContainer,
822
+ innerTopBox,
823
+ topText,
824
+ innerBottomBox,
825
+ bottomText,
826
+ midContainer,
827
+ firstBox,
828
+ firstBoxText,
829
+ ...shelves,
830
+ lastBox,
831
+ lastBoxText,
832
+ bottomContainer,
833
+ bottomTextContent,
834
+ ], {
835
+ left: x,
836
+ top: y,
837
+ evented: true,
838
+ // hoverCursor: "pointer",
839
+ selectable: false,
840
+ lockScalingX: true,
841
+ lockScalingY: true,
842
+ subTargetCheck: true,
843
+ hasControls: false,
844
+ lockRotation: true,
845
+ lockMovementX: true,
846
+ lockMovementY: true,
847
+ angle: fixtureData.relativePosition?.angle ?? 0,
848
+ });
849
+ // fixtureGroup.on("mousedown", (event: any) => {
850
+ // const target = event.target;
851
+ // setTimeout(() => {
852
+ // this.resizeCanvas();
853
+ // this.fitCanvasToLayoutAnimated();
854
+ // }, 300);
855
+ // this.highlightFixture(target);
856
+ // this.selectFixture(target);
857
+ // });
858
+ fixtureGroup.fixtureType = fixtureData.fixtureType;
859
+ fixtureGroup.wallIndex = fixtureData.associatedElementNumber;
860
+ fixtureGroup.fixtureIndex = fixtureData.associatedElementFixtureNumber;
861
+ fixtureGroup.fixtureId = fixtureData._id;
862
+ fixtureGroup.issue = fixtureData.issue;
863
+ fixtureGroup.issueData = fixtureData.issueData;
864
+ fixtureGroup.taskType = fixtureData.taskType;
865
+ fixtureGroup.vmConfig = fixtureData.vmConfig;
866
+ fixtureGroup.objType = "fixture";
867
+ canvas.add(fixtureGroup);
868
+ return fixtureGroup;
869
+ }
870
+ selectFixture(target) {
871
+ if (target) {
872
+ this.selectedFixture = {
873
+ fixtureType: target.fixtureType,
874
+ wallIndex: target.wallIndex,
875
+ fixtureIndex: target.fixtureIndex,
876
+ fixtureId: target.fixtureId,
877
+ issue: target.issue,
878
+ issueData: target.issueData,
879
+ taskType: target.taskType,
880
+ };
881
+ if (this.selectedFixture.fixtureType === "wall") {
882
+ const wall = this.floorData.layoutPolygon.find((wall) => wall.elementNumber === this.selectedFixture.wallIndex);
883
+ const fixture = wall.fixtures.find((fixture) => fixture._id === this.selectedFixture.fixtureId);
884
+ this.selectedFixtureData = fixture;
885
+ this.selectedFixtureData["revisionId"] = this.floorData.revisionId;
886
+ }
887
+ else if (this.selectedFixture.fixtureType === "floor") {
888
+ const fixture = this.floorData.centerFixture.find((fixture) => fixture._id === this.selectedFixture.fixtureId);
889
+ this.selectedFixtureData = fixture;
890
+ this.selectedFixtureData["revisionId"] = this.floorData.revisionId;
891
+ }
892
+ if (this.selectedFixtureData?.header?.label != "CL") {
893
+ this.selectedFixture.fixtureData = this.selectedFixtureData;
894
+ }
895
+ else {
896
+ this.selectedFixture.fixtureData = null;
897
+ }
898
+ }
899
+ }
900
+ drawLabeledRectangle(canvas, x, y, width, height, element) {
901
+ const rect = new fabric.Rect({
902
+ width,
903
+ height,
904
+ rx: 2,
905
+ ry: 2,
906
+ fill: "#DAF1FF",
907
+ stroke: "#6BCAFF",
908
+ strokeWidth: 2,
909
+ originX: "center",
910
+ originY: "center",
911
+ });
912
+ const text = new fabric.Textbox(element.fixtureName, {
913
+ width: width - 8,
914
+ fontSize: 14,
915
+ fontFamily: "Inter",
916
+ fontWeight: "500",
917
+ fill: "#101828",
918
+ originX: "center",
919
+ originY: "center",
920
+ textAlign: "center",
921
+ editable: false,
922
+ splitByGrapheme: true,
923
+ });
924
+ const textBounds = text.getBoundingRect();
925
+ if (textBounds.height > height - 8) {
926
+ const scale = (height - 8) / textBounds.height;
927
+ text.set("fontSize", text.fontSize * scale);
928
+ }
929
+ const group = new fabric.Group([rect, text], {
930
+ left: x,
931
+ top: y,
932
+ angle: element.relativePosition.angle,
933
+ selectable: false,
934
+ originX: "center",
935
+ originY: "center",
936
+ });
937
+ group.objType = "others";
938
+ group.data = element;
939
+ canvas.add(group);
940
+ return group;
941
+ }
942
+ toPixels(value, unit, dpi = 2.8) {
943
+ let pixels;
944
+ if (unit === "mm") {
945
+ pixels = (value / 25.4) * dpi;
946
+ }
947
+ else if (unit === "ft") {
948
+ pixels = value * 12 * dpi;
949
+ }
950
+ else {
951
+ throw new Error("Unsupported unit. Use 'mm' or 'ft'.");
952
+ }
953
+ return Number(pixels.toFixed(2));
954
+ }
955
+ calcMerchCompliancePercentage() {
956
+ const allFixtures = [
957
+ ...this.floorData?.layoutPolygon.flatMap((e) => e.fixtures),
958
+ ...this.floorData?.centerFixture,
959
+ ];
960
+ const allShelves = allFixtures.flatMap((f) => f.shelfConfig);
961
+ const compliances = allShelves.map((s) => s?.compliance);
962
+ const total = compliances.length;
963
+ const properCount = compliances.filter((p) => p === "proper").length;
964
+ const successPercentage = (properCount / total) * 100;
965
+ return Math.round(successPercentage);
966
+ }
967
+ getFullLayoutBounds() {
968
+ const objects = this.canvas.getObjects();
969
+ if (!objects.length)
970
+ return { left: 0, top: 0, width: 0, height: 0 };
971
+ let minX = Infinity, minY = Infinity, maxX = -Infinity, maxY = -Infinity;
972
+ for (const obj of objects) {
973
+ const rect = obj.getBoundingRect();
974
+ minX = Math.min(minX, rect.left);
975
+ minY = Math.min(minY, rect.top);
976
+ maxX = Math.max(maxX, rect.left + rect.width);
977
+ maxY = Math.max(maxY, rect.top + rect.height);
978
+ }
979
+ return {
980
+ left: minX,
981
+ top: minY,
982
+ width: maxX - minX,
983
+ height: maxY - minY,
984
+ };
985
+ }
986
+ highlightFixture(group, blink = false) {
987
+ this.removeHighlight();
988
+ this.cancelHighlightBlink = false;
989
+ const center = group.getCenterPoint();
990
+ const realWidth = group.width * group.scaleX;
991
+ const realHeight = group.height * group.scaleY;
992
+ const rect = new fabric.Rect({
993
+ left: center.x,
994
+ top: center.y,
995
+ width: realWidth + 8,
996
+ height: realHeight + 8,
997
+ rx: 5,
998
+ ry: 5,
999
+ stroke: "#00aaff",
1000
+ strokeWidth: 3,
1001
+ fill: "transparent",
1002
+ selectable: false,
1003
+ evented: false,
1004
+ originX: "center",
1005
+ originY: "center",
1006
+ angle: group.angle || 0,
1007
+ opacity: blink ? 0 : 1,
1008
+ });
1009
+ this.canvas.add(rect);
1010
+ this.canvas.moveObjectTo(rect, this.canvas.getObjects().length - 1);
1011
+ this.canvas.requestRenderAll();
1012
+ this.activeHighlight = rect;
1013
+ // --- No blinking needed ---
1014
+ if (!blink)
1015
+ return;
1016
+ let cycles = 0;
1017
+ const blinkOnce = () => {
1018
+ if (this.cancelHighlightBlink) {
1019
+ this.removeHighlight();
1020
+ return;
1021
+ }
1022
+ rect.animate({ opacity: 1 }, {
1023
+ duration: 200,
1024
+ onChange: () => this.canvas.requestRenderAll(),
1025
+ onComplete: () => {
1026
+ if (this.cancelHighlightBlink) {
1027
+ this.removeHighlight();
1028
+ return;
1029
+ }
1030
+ rect.animate({ opacity: 0 }, {
1031
+ duration: 200,
1032
+ onChange: () => this.canvas.requestRenderAll(),
1033
+ onComplete: () => {
1034
+ if (this.cancelHighlightBlink) {
1035
+ this.removeHighlight();
1036
+ return;
1037
+ }
1038
+ cycles++;
1039
+ if (cycles < 20) {
1040
+ blinkOnce();
1041
+ }
1042
+ else {
1043
+ if (!this.cancelHighlightBlink) {
1044
+ rect.set({ opacity: 1 });
1045
+ this.canvas.requestRenderAll();
1046
+ }
1047
+ }
1048
+ },
1049
+ });
1050
+ },
1051
+ });
1052
+ };
1053
+ blinkOnce();
1054
+ }
1055
+ removeHighlight() {
1056
+ this.cancelHighlightBlink = true;
1057
+ if (this.activeHighlight) {
1058
+ this.canvas.remove(this.activeHighlight);
1059
+ this.activeHighlight = null;
1060
+ this.canvas.requestRenderAll();
1061
+ }
1062
+ }
1063
+ onChangeFixture({ fixtureId, fixtureName, shelfId, zone, }) {
1064
+ const actionFixture = this.canvas
1065
+ .getObjects()
1066
+ .find((obj) => obj.objType === "fixture" && obj.fixtureId === fixtureId);
1067
+ if (!actionFixture)
1068
+ return;
1069
+ setTimeout(() => {
1070
+ this.resizeCanvas();
1071
+ this.fitCanvasToLayoutAnimated();
1072
+ }, 300);
1073
+ this.highlightFixture(actionFixture, true);
1074
+ this.selectFixture(actionFixture);
1075
+ }
1076
+ onClickClose() {
1077
+ this.selectedFixture = null;
1078
+ setTimeout(() => {
1079
+ this.resizeCanvas();
1080
+ this.fitCanvasToLayoutAnimated();
1081
+ }, 300);
1082
+ this.removeHighlight();
1083
+ }
1084
+ ngOnDestroy() {
1085
+ this.destroy$.next();
1086
+ this.destroy$.complete();
1087
+ }
1088
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ProductLocatorComponent, deps: [{ token: i1.GlobalStateService }, { token: i2.TitleCasePipe }], target: i0.ɵɵFactoryTarget.Component });
1089
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.12", type: ProductLocatorComponent, selector: "product-fixture-locator", inputs: { floorData: "floorData", selectedProduct: "selectedProduct" }, outputs: { targetFixtureFullDetails: "targetFixtureFullDetails" }, host: { listeners: { "window:resize": "onResize()" } }, providers: [TitleCasePipe], viewQueries: [{ propertyName: "canvasEl", first: true, predicate: ["baseCanvas"], descendants: true }, { propertyName: "containerRef", first: true, predicate: ["canvasContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<section id=\"product-locator\">\r\n <div *ngIf=\"isPageLoading\" class=\"row\">\r\n <div class=\"col-12 m-0\"><ng-container *ngTemplateOutlet=\"headerSkeleton\"></ng-container></div>\r\n <div class=\"col-12\"><ng-container *ngTemplateOutlet=\"skeletonLoader\"></ng-container></div>\r\n </div>\r\n\r\n <div [ngClass]=\"{ 'd-none': isPageLoading }\">\r\n <div id=\"body\" class=\"row\">\r\n <div class=\"col overflow-hidden position-relative compliance-canvas\">\r\n <div id=\"canvas-card\" class=\"w-100 position-relative\" #canvasContainer>\r\n <canvas id=\"base-canvas\" #baseCanvas></canvas>\r\n </div>\r\n </div>\r\n\r\n <div [ngClass]=\"{'d-none':!selectedFixture?.fixtureData}\" class=\"col bg-white rounded p-3 fixture-overview\">\r\n <misplaced-product-fixture [fixtureDetails]=\"selectedFixture?.fixtureData\"\r\n [selectedProduct]=\"selectedProduct\"\r\n (targetFixtureFullDetails)=\"targetFixtureFullDetails.emit($event)\"></misplaced-product-fixture>\r\n </div>\r\n </div>\r\n </div>\r\n</section>\r\n\r\n\r\n<ng-template #headerSkeleton>\r\n <div class=\"row m-0 g-0 loader d-flex justify-content-center align-items-center overflow-hidden\">\r\n <div class=\"shimmer w-100 p-4 rounded\">\r\n <div class=\"wrapper\">\r\n <div class=\"stroke mt-0 animate title\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #skeletonLoader>\r\n <div class=\"row loader d-flex justify-content-center align-items-center overflow-hidden\">\r\n <div class=\"shimmer rounded\">\r\n <div class=\"wrapper\">\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n <br />\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n <br />\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n <br />\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n <br />\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>", styles: ["#product-locator #header .title{color:var(--Gray-800, #1d2939);font-size:16px;font-weight:600;line-height:24px;margin:0}#product-locator #header .compliance{font-size:36px;font-weight:600}#product-locator #header .last-check{font-size:16px;font-weight:500}#product-locator #body{max-height:calc(100vh - 100px)}#product-locator #body #canvas-card{border-radius:8px;background:#fff;padding:20px 16px;height:100%;overflow:hidden;width:100%}#product-locator #body .collapsed-col{transition:all .3s ease;width:0px!important}#product-locator #body .fixture-overview{max-width:290px;max-height:calc(100vh - 100px);overflow:auto}#product-locator #body .compliance-canvas{max-height:calc(100vh - 100px)}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i2.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: i3.MisplacedProductFixtureComponent, selector: "misplaced-product-fixture", inputs: ["fixtureDetails", "selectedProduct"], outputs: ["targetFixtureFullDetails"] }] });
1090
+ }
1091
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.12", ngImport: i0, type: ProductLocatorComponent, decorators: [{
1092
+ type: Component,
1093
+ args: [{ selector: "product-fixture-locator", providers: [TitleCasePipe], template: "<section id=\"product-locator\">\r\n <div *ngIf=\"isPageLoading\" class=\"row\">\r\n <div class=\"col-12 m-0\"><ng-container *ngTemplateOutlet=\"headerSkeleton\"></ng-container></div>\r\n <div class=\"col-12\"><ng-container *ngTemplateOutlet=\"skeletonLoader\"></ng-container></div>\r\n </div>\r\n\r\n <div [ngClass]=\"{ 'd-none': isPageLoading }\">\r\n <div id=\"body\" class=\"row\">\r\n <div class=\"col overflow-hidden position-relative compliance-canvas\">\r\n <div id=\"canvas-card\" class=\"w-100 position-relative\" #canvasContainer>\r\n <canvas id=\"base-canvas\" #baseCanvas></canvas>\r\n </div>\r\n </div>\r\n\r\n <div [ngClass]=\"{'d-none':!selectedFixture?.fixtureData}\" class=\"col bg-white rounded p-3 fixture-overview\">\r\n <misplaced-product-fixture [fixtureDetails]=\"selectedFixture?.fixtureData\"\r\n [selectedProduct]=\"selectedProduct\"\r\n (targetFixtureFullDetails)=\"targetFixtureFullDetails.emit($event)\"></misplaced-product-fixture>\r\n </div>\r\n </div>\r\n </div>\r\n</section>\r\n\r\n\r\n<ng-template #headerSkeleton>\r\n <div class=\"row m-0 g-0 loader d-flex justify-content-center align-items-center overflow-hidden\">\r\n <div class=\"shimmer w-100 p-4 rounded\">\r\n <div class=\"wrapper\">\r\n <div class=\"stroke mt-0 animate title\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>\r\n\r\n<ng-template #skeletonLoader>\r\n <div class=\"row loader d-flex justify-content-center align-items-center overflow-hidden\">\r\n <div class=\"shimmer rounded\">\r\n <div class=\"wrapper\">\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n <br />\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n <br />\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n <br />\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n <br />\r\n <div class=\"stroke animate title\"></div>\r\n <div class=\"stroke animate link\"></div>\r\n <div class=\"stroke animate description\"></div>\r\n </div>\r\n </div>\r\n </div>\r\n</ng-template>", styles: ["#product-locator #header .title{color:var(--Gray-800, #1d2939);font-size:16px;font-weight:600;line-height:24px;margin:0}#product-locator #header .compliance{font-size:36px;font-weight:600}#product-locator #header .last-check{font-size:16px;font-weight:500}#product-locator #body{max-height:calc(100vh - 100px)}#product-locator #body #canvas-card{border-radius:8px;background:#fff;padding:20px 16px;height:100%;overflow:hidden;width:100%}#product-locator #body .collapsed-col{transition:all .3s ease;width:0px!important}#product-locator #body .fixture-overview{max-width:290px;max-height:calc(100vh - 100px);overflow:auto}#product-locator #body .compliance-canvas{max-height:calc(100vh - 100px)}\n"] }]
1094
+ }], ctorParameters: () => [{ type: i1.GlobalStateService }, { type: i2.TitleCasePipe }], propDecorators: { floorData: [{
1095
+ type: Input
1096
+ }], selectedProduct: [{
1097
+ type: Input
1098
+ }], canvasEl: [{
1099
+ type: ViewChild,
1100
+ args: ["baseCanvas", { static: false }]
1101
+ }], containerRef: [{
1102
+ type: ViewChild,
1103
+ args: ["canvasContainer"]
1104
+ }], targetFixtureFullDetails: [{
1105
+ type: Output
1106
+ }], onResize: [{
1107
+ type: HostListener,
1108
+ args: ["window:resize"]
1109
+ }] } });
1110
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvZHVjdC1sb2NhdG9yLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3RhbmdvLXN0b3JlLWJ1aWxkZXIvc3JjL2xpYi9jb21wb25lbnRzL3BsYW5vZ3JhbS9tZXJjaC1jb21wbGlhbmNlL3Byb2R1Y3QtbG9jYXRvci9wcm9kdWN0LWxvY2F0b3IuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvdGFuZ28tc3RvcmUtYnVpbGRlci9zcmMvbGliL2NvbXBvbmVudHMvcGxhbm9ncmFtL21lcmNoLWNvbXBsaWFuY2UvcHJvZHVjdC1sb2NhdG9yL3Byb2R1Y3QtbG9jYXRvci5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsYUFBYSxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDaEQsT0FBTyxFQUVMLFNBQVMsRUFFVCxZQUFZLEVBQ1osWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEVBRU4sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBRzFDLE9BQU8sS0FBSyxNQUFNLE1BQU0sUUFBUSxDQUFDOzs7OztBQVFqQyxNQUFNLE9BQU8sdUJBQXVCO0lBc0N4QjtJQUNBO0lBcENELFNBQVMsQ0FBTTtJQUNmLGVBQWUsQ0FBTztJQUUvQixRQUFRLENBQWlDO0lBQ1gsWUFBWSxDQUE4QjtJQUM5RCx3QkFBd0IsR0FBRyxJQUFJLFlBQVksRUFBTyxDQUFDO0lBRTdELFFBQVE7UUFDTixVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2QsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3RCLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztJQUNWLENBQUM7SUFFRCxNQUFNLENBQWlCO0lBQ3ZCLFFBQVEsQ0FBUztJQUVq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UUFDVixJQUFJLENBQUMsZUFBZSxHQUFHLElBQUksQ0FBQztRQUM1QixVQUFVLENBQUMsR0FBRyxFQUFFO1lBQ2QsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3BCLElBQUksQ0FBQyx5QkFBeUIsRUFBRSxDQUFDO1FBQ25DLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztRQUNSLElBQUksQ0FBQyxlQUFlLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRUQsV0FBVztRQUNULElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUM7UUFDckIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQztJQUMzQixDQUFDO3dHQXo3Q1UsdUJBQXVCOzRGQUF2Qix1QkFBdUIscVBBRnZCLENBQUMsYUFBYSxDQUFDLHlQQ3ZCNUIscS9GQThEYzs7NEZEckNELHVCQUF1QjtrQkFObkMsU0FBUzsrQkFDRSx5QkFBeUIsYUFHeEIsQ0FBQyxhQUFhLENBQUM7bUhBS2pCLFNBQVM7c0JBQWpCLEtBQUs7Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFFTixRQUFRO3NCQURQLFNBQVM7dUJBQUMsWUFBWSxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRTtnQkFFWixZQUFZO3NCQUF6QyxTQUFTO3VCQUFDLGlCQUFpQjtnQkFDbEIsd0JBQXdCO3NCQUFqQyxNQUFNO2dCQUVQLFFBQVE7c0JBRFAsWUFBWTt1QkFBQyxlQUFlIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgVGl0bGVDYXNlUGlwZSB9IGZyb20gXCJAYW5ndWxhci9jb21tb25cIjtcclxuaW1wb3J0IHtcclxuICBBZnRlclZpZXdJbml0LFxyXG4gIENvbXBvbmVudCxcclxuICBFbGVtZW50UmVmLFxyXG4gIEV2ZW50RW1pdHRlcixcclxuICBIb3N0TGlzdGVuZXIsXHJcbiAgSW5wdXQsXHJcbiAgT25DaGFuZ2VzLFxyXG4gIE9uRGVzdHJveSxcclxuICBPdXRwdXQsXHJcbiAgU2ltcGxlQ2hhbmdlcyxcclxuICBWaWV3Q2hpbGQsXHJcbn0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuaW1wb3J0IHsgU3ViamVjdCwgdGFrZVVudGlsIH0gZnJvbSBcInJ4anNcIjtcclxuaW1wb3J0IHsgR2xvYmFsU3RhdGVTZXJ2aWNlIH0gZnJvbSBcInRhbmdvLWFwcC11aS1nbG9iYWxcIjtcclxuXHJcbmltcG9ydCAqIGFzIGZhYnJpYyBmcm9tIFwiZmFicmljXCI7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogXCJwcm9kdWN0LWZpeHR1cmUtbG9jYXRvclwiLFxyXG4gIHRlbXBsYXRlVXJsOiBcIi4vcHJvZHVjdC1sb2NhdG9yLmNvbXBvbmVudC5odG1sXCIsXHJcbiAgc3R5bGVVcmw6IFwiLi9wcm9kdWN0LWxvY2F0b3IuY29tcG9uZW50LnNjc3NcIixcclxuICBwcm92aWRlcnM6IFtUaXRsZUNhc2VQaXBlXSxcclxufSlcclxuZXhwb3J0IGNsYXNzIFByb2R1Y3RMb2NhdG9yQ29tcG9uZW50XHJcbiAgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkNoYW5nZXMsIE9uRGVzdHJveVxyXG57XHJcbiAgQElucHV0KCkgZmxvb3JEYXRhOiBhbnk7XHJcbiAgQElucHV0KCkgc2VsZWN0ZWRQcm9kdWN0PzogYW55O1xyXG4gIEBWaWV3Q2hpbGQoXCJiYXNlQ2FudmFzXCIsIHsgc3RhdGljOiBmYWxzZSB9KVxyXG4gIGNhbnZhc0VsITogRWxlbWVudFJlZjxIVE1MQ2FudmFzRWxlbWVudD47XHJcbiAgQFZpZXdDaGlsZChcImNhbnZhc0NvbnRhaW5lclwiKSBjb250YWluZXJSZWYhOiBFbGVtZW50UmVmPEhUTUxEaXZFbGVtZW50PjtcclxuICBAT3V0cHV0KCkgdGFyZ2V0Rml4dHVyZUZ1bGxEZXRhaWxzID0gbmV3IEV2ZW50RW1pdHRlcjxhbnk+KCk7XHJcbiAgQEhvc3RMaXN0ZW5lcihcIndpbmRvdzpyZXNpemVcIilcclxuICBvblJlc2l6ZSgpOiB2b2lkIHtcclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICB0aGlzLnJlc2l6ZUNhbnZhcygpO1xyXG4gICAgfSwgMzAwKTtcclxuICB9XHJcblxyXG4gIGNhbnZhcyE6IGZhYnJpYy5DYW52YXM7XHJcbiAgY2xpZW50SWQ6IHN0cmluZztcclxuXHJcbiAgY2RuVXJsOiBzdHJpbmc7XHJcblxyXG4gIHpvb21MZXZlbDogbnVtYmVyID0gMTtcclxuICBmaXh0dXJlSGVpZ2h0ID0gdGhpcy50b1BpeGVscygxNTI0LCBcIm1tXCIpO1xyXG4gIGZpeHR1cmVXaWR0aCA9IHRoaXMudG9QaXhlbHMoMTIyMCwgXCJtbVwiKTtcclxuICB3YWxsVGhpY2tuZXNzID0gMzA7XHJcbiAgdmVydGljYWxNYXJnaW4gPSAoMS4yNSAvIDEwMCkgKiB0aGlzLmZpeHR1cmVIZWlnaHQ7XHJcblxyXG4gIGlzUGFnZUxvYWRpbmc6IGJvb2xlYW4gPSBmYWxzZTtcclxuXHJcbiAgc2VsZWN0ZWRGaXh0dXJlOiBhbnk7XHJcbiAgc2VsZWN0ZWRGaXh0dXJlRGF0YTogYW55O1xyXG5cclxuICBwcml2YXRlIGFjdGl2ZUhpZ2hsaWdodDogZmFicmljLlJlY3QgfCBudWxsID0gbnVsbDtcclxuICBwcml2YXRlIGNhbmNlbEhpZ2hsaWdodEJsaW5rID0gZmFsc2U7XHJcblxyXG4gIHByaXZhdGUgcmVhZG9ubHkgZGVzdHJveSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xyXG5cclxuICBjb25zdHJ1Y3RvcihcclxuICAgIHByaXZhdGUgZ3M6IEdsb2JhbFN0YXRlU2VydmljZSxcclxuICAgIHByaXZhdGUgdGl0bGVDYXNlOiBUaXRsZUNhc2VQaXBlLFxyXG4gICkge1xyXG4gICAgdGhpcy5ncy5lbnZpcm9ubWVudC5waXBlKHRha2VVbnRpbCh0aGlzLmRlc3Ryb3kkKSkuc3Vic2NyaWJlKChlKSA9PiB7XHJcbiAgICAgIGlmIChlKSB0aGlzLmNkblVybCA9IGUucGxhbm9ncmFtQ0ROO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKTogdm9pZCB7XHJcbiAgICBpZiAoY2hhbmdlc1tcImZsb29yRGF0YVwiXT8uY3VycmVudFZhbHVlKSB7XHJcbiAgICAgIHRoaXMuZmxvb3JEYXRhID0gY2hhbmdlc1tcImZsb29yRGF0YVwiXS5jdXJyZW50VmFsdWU7XHJcblxyXG4gICAgICBpZiAodGhpcy5mbG9vckRhdGE/LmZsb29yQ2hhbmdlKSB7XHJcbiAgICAgICAgdGhpcy5vbkNsaWNrQ2xvc2UoKTtcclxuICAgICAgICB0aGlzLnJlbmRlckZsb29yKCk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIG5nQWZ0ZXJWaWV3SW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuY2FudmFzID0gbmV3IGZhYnJpYy5DYW52YXModGhpcy5jYW52YXNFbD8ubmF0aXZlRWxlbWVudCwge1xyXG4gICAgICBzZWxlY3Rpb246IGZhbHNlLFxyXG4gICAgICBwZXJQaXhlbFRhcmdldEZpbmQ6IHRydWUsXHJcbiAgICAgIHRhcmdldEZpbmRUb2xlcmFuY2U6IDUsXHJcbiAgICAgIHdpZHRoOiA1NjAsXHJcbiAgICAgIGhlaWdodDogNDUwLFxyXG4gICAgfSk7XHJcbiAgICAvLyB0aGlzLnNldHVwWm9vbUhhbmRsZXJzKCk7XHJcblxyXG4gICAgaWYgKHRoaXMuZmxvb3JEYXRhKSB7XHJcbiAgICAgIHRoaXMucmVuZGVyRmxvb3IoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHJlc2l6ZUNhbnZhcygpOiB2b2lkIHtcclxuICAgIGNvbnN0IGNvbnRhaW5lciA9IHRoaXMuY29udGFpbmVyUmVmLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICB0aGlzLmNhbnZhcy5zZXREaW1lbnNpb25zKHtcclxuICAgICAgd2lkdGg6IGNvbnRhaW5lci5jbGllbnRXaWR0aCAtIDUwLFxyXG4gICAgICBoZWlnaHQ6IGNvbnRhaW5lci5jbGllbnRIZWlnaHQgLSA0MCxcclxuICAgIH0pO1xyXG4gICAgdGhpcy5jYW52YXMucmVxdWVzdFJlbmRlckFsbCgpO1xyXG4gIH1cclxuXHJcbiAgc2V0dXBab29tSGFuZGxlcnMoKTogdm9pZCB7XHJcbiAgICB0aGlzLmNhbnZhcy5vbihcIm1vdXNlOndoZWVsXCIsIChvcHQ6IGZhYnJpYy5URXZlbnQ8V2hlZWxFdmVudD4pID0+IHtcclxuICAgICAgY29uc3QgZSA9IG9wdC5lO1xyXG5cclxuICAgICAgaWYgKGUuY3RybEtleSB8fCBlLm1ldGFLZXkpIHtcclxuICAgICAgICBjb25zdCBkZWx0YSA9IGUuZGVsdGFZO1xyXG4gICAgICAgIGxldCB6b29tID0gdGhpcy5jYW52YXMuZ2V0Wm9vbSgpO1xyXG4gICAgICAgIHpvb20gKj0gMC45OTUgKiogZGVsdGE7XHJcblxyXG4gICAgICAgIHpvb20gPSBNYXRoLm1heCgwLjIsIE1hdGgubWluKHpvb20sIDMpKTtcclxuXHJcbiAgICAgICAgdGhpcy5jYW52YXMuem9vbVRvUG9pbnQoXHJcbiAgICAgICAgICB7XHJcbiAgICAgICAgICAgIHg6IGUub2Zmc2V0WCxcclxuICAgICAgICAgICAgeTogZS5vZmZzZXRZLFxyXG4gICAgICAgICAgfSBhcyBmYWJyaWMuUG9pbnQsXHJcbiAgICAgICAgICB6b29tLFxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICBlLnN0b3BQcm9wYWdhdGlvbigpO1xyXG4gICAgICB9XHJcbiAgICB9KTtcclxuXHJcbiAgICBsZXQgaXNEcmFnZ2luZyA9IGZhbHNlO1xyXG4gICAgbGV0IGxhc3RQb3NYID0gMDtcclxuICAgIGxldCBsYXN0UG9zWSA9IDA7XHJcblxyXG4gICAgdGhpcy5jYW52YXMub24oXCJtb3VzZTpkb3duXCIsIChvcHQ6IGFueSkgPT4ge1xyXG4gICAgICBpZiAoIW9wdC50YXJnZXQpIHtcclxuICAgICAgICBpc0RyYWdnaW5nID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLmNhbnZhcy5zZWxlY3Rpb24gPSBmYWxzZTtcclxuICAgICAgICBjb25zdCBlID0gb3B0LmU7XHJcbiAgICAgICAgbGFzdFBvc1ggPSBlLmNsaWVudFg7XHJcbiAgICAgICAgbGFzdFBvc1kgPSBlLmNsaWVudFk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIHRoaXMuY2FudmFzLm9uKFwibW91c2U6bW92ZVwiLCAob3B0OiBhbnkpID0+IHtcclxuICAgICAgaWYgKGlzRHJhZ2dpbmcgJiYgdGhpcy5jYW52YXMudmlld3BvcnRUcmFuc2Zvcm0pIHtcclxuICAgICAgICBjb25zdCBlID0gb3B0LmU7XHJcbiAgICAgICAgY29uc3QgdnB0ID0gdGhpcy5jYW52YXMudmlld3BvcnRUcmFuc2Zvcm07XHJcbiAgICAgICAgdnB0WzRdICs9IGUuY2xpZW50WCAtIGxhc3RQb3NYO1xyXG4gICAgICAgIHZwdFs1XSArPSBlLmNsaWVudFkgLSBsYXN0UG9zWTtcclxuICAgICAgICB0aGlzLmNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCk7XHJcbiAgICAgICAgbGFzdFBvc1ggPSBlLmNsaWVudFg7XHJcbiAgICAgICAgbGFzdFBvc1kgPSBlLmNsaWVudFk7XHJcbiAgICAgIH1cclxuICAgIH0pO1xyXG5cclxuICAgIHRoaXMuY2FudmFzLm9uKFwibW91c2U6dXBcIiwgKCkgPT4ge1xyXG4gICAgICBpc0RyYWdnaW5nID0gZmFsc2U7XHJcbiAgICAgIHRoaXMuY2FudmFzLnNlbGVjdGlvbiA9IHRydWU7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIGFzeW5jIHJlbmRlckZsb29yKCkge1xyXG4gICAgdGhpcy5jYW52YXM/LmNsZWFyKCk7XHJcbiAgICBhd2FpdCB0aGlzLmRyYXdMYXlvdXRFbGVtZW50cygpO1xyXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgIHRoaXMucmVzaXplQ2FudmFzKCk7XHJcbiAgICAgIHRoaXMuZml0Q2FudmFzVG9MYXlvdXRBbmltYXRlZCgpO1xyXG4gICAgfSwgMzAwKTtcclxuXHJcbiAgICBpZiAodGhpcy5zZWxlY3RlZFByb2R1Y3Q/LmZpeHR1cmVEZXRhaWxzKSB7XHJcbiAgICAgIHRoaXMub25DaGFuZ2VGaXh0dXJlKHRoaXMuc2VsZWN0ZWRQcm9kdWN0LmZpeHR1cmVEZXRhaWxzKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIHByaXZhdGUgZml0Q2FudmFzVG9MYXlvdXRBbmltYXRlZChkdXJhdGlvbiA9IDMwMCkge1xyXG4gICAgaWYgKCF0aGlzLmNhbnZhcykgcmV0dXJuO1xyXG5cclxuICAgIGNvbnN0IGJvdW5kcyA9IHRoaXMuZ2V0RnVsbExheW91dEJvdW5kcygpO1xyXG4gICAgaWYgKCFib3VuZHMud2lkdGggfHwgIWJvdW5kcy5oZWlnaHQpIHJldHVybjtcclxuXHJcbiAgICBjb25zdCBjYW52YXNXID0gdGhpcy5jYW52YXMuZ2V0V2lkdGgoKTtcclxuICAgIGNvbnN0IGNhbnZhc0ggPSB0aGlzLmNhbnZhcy5nZXRIZWlnaHQoKTtcclxuXHJcbiAgICAvLyBDb21wdXRlIHpvb20gdG8gZml0XHJcbiAgICBjb25zdCBzY2FsZVggPSBjYW52YXNXIC8gYm91bmRzLndpZHRoO1xyXG4gICAgY29uc3Qgc2NhbGVZID0gY2FudmFzSCAvIGJvdW5kcy5oZWlnaHQ7XHJcbiAgICBjb25zdCB0YXJnZXRab29tID0gTWF0aC5taW4oc2NhbGVYLCBzY2FsZVkpO1xyXG5cclxuICAgIGNvbnN0IHRhcmdldFZwdCA9IFtcclxuICAgICAgLi4uKHRoaXMuY2FudmFzLnZpZXdwb3J0VHJhbnNmb3JtIHx8IFsxLCAwLCAwLCAxLCAwLCAwXSksXHJcbiAgICBdIGFzIGZhYnJpYy5UTWF0MkQ7XHJcblxyXG4gICAgdGFyZ2V0VnB0WzBdID0gdGFyZ2V0Wm9vbTsgLy8gc2NhbGVYXHJcbiAgICB0YXJnZXRWcHRbM10gPSB0YXJnZXRab29tOyAvLyBzY2FsZVlcclxuXHJcbiAgICAvLyBDZW50ZXIgWFxyXG4gICAgdGFyZ2V0VnB0WzRdID0gY2FudmFzVyAvIDIgLSAoYm91bmRzLmxlZnQgKyBib3VuZHMud2lkdGggLyAyKSAqIHRhcmdldFpvb207XHJcblxyXG4gICAgLy8gLS0tLS0gRklYRUQ6IGtlZXAgbGF5b3V0IHNsaWdodGx5IHVwIHdpdGhvdXQgc3RhY2tpbmcgLS0tLS1cclxuICAgIGNvbnN0IGNlbnRlcmVkWSA9XHJcbiAgICAgIGNhbnZhc0ggLyAyIC0gKGJvdW5kcy50b3AgKyBib3VuZHMuaGVpZ2h0IC8gMikgKiB0YXJnZXRab29tO1xyXG5cclxuICAgIGNvbnN0IHNjYWxlZEhlaWdodCA9IGJvdW5kcy5oZWlnaHQgKiB0YXJnZXRab29tO1xyXG4gICAgY29uc3QgZW1wdHlTcGFjZVkgPSBjYW52YXNIIC0gc2NhbGVkSGVpZ2h0O1xyXG5cclxuICAgIGNvbnN0IHNoaWZ0VXAgPSBlbXB0eVNwYWNlWSA+IDAgPyBlbXB0eVNwYWNlWSAqIDAuMjUgOiAwO1xyXG5cclxuICAgIHRhcmdldFZwdFs1XSA9IGNlbnRlcmVkWSAtIHNoaWZ0VXA7XHJcblxyXG4gICAgLy8gQW5pbWF0ZVxyXG4gICAgY29uc3Qgc3RhcnRWcHQgPSBbLi4udGhpcy5jYW52YXMudmlld3BvcnRUcmFuc2Zvcm0hXSBhcyBmYWJyaWMuVE1hdDJEO1xyXG5cclxuICAgIGZhYnJpYy51dGlsLmFuaW1hdGUoe1xyXG4gICAgICBzdGFydFZhbHVlOiAwLFxyXG4gICAgICBlbmRWYWx1ZTogMSxcclxuICAgICAgZHVyYXRpb24sXHJcbiAgICAgIGVhc2luZzogZmFicmljLnV0aWwuZWFzZS5lYXNlT3V0Q3ViaWMsXHJcbiAgICAgIG9uQ2hhbmdlOiAodmFsdWU6IG51bWJlcikgPT4ge1xyXG4gICAgICAgIGNvbnN0IHZwdCA9IHRoaXMuY2FudmFzLnZpZXdwb3J0VHJhbnNmb3JtITtcclxuXHJcbiAgICAgICAgdnB0WzBdID0gc3RhcnRWcHRbMF0gKyAodGFyZ2V0VnB0WzBdIC0gc3RhcnRWcHRbMF0pICogdmFsdWU7XHJcbiAgICAgICAgdnB0WzNdID0gc3RhcnRWcHRbM10gKyAodGFyZ2V0VnB0WzNdIC0gc3RhcnRWcHRbM10pICogdmFsdWU7XHJcbiAgICAgICAgdnB0WzRdID0gc3RhcnRWcHRbNF0gKyAodGFyZ2V0VnB0WzRdIC0gc3RhcnRWcHRbNF0pICogdmFsdWU7XHJcbiAgICAgICAgdnB0WzVdID0gc3RhcnRWcHRbNV0gKyAodGFyZ2V0VnB0WzVdIC0gc3RhcnRWcHRbNV0pICogdmFsdWU7XHJcblxyXG4gICAgICAgIHRoaXMuY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgICAgfSxcclxuICAgIH0pO1xyXG4gIH1cclxuXHJcbiAgYXN5bmMgZHJhd0xheW91dEVsZW1lbnRzKCkge1xyXG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IHRoaXMuZmxvb3JEYXRhLmxheW91dFBvbHlnb24ubGVuZ3RoOyBpbmRleCsrKSB7XHJcbiAgICAgIGNvbnN0IGVsZW1lbnQgPSB0aGlzLmZsb29yRGF0YS5sYXlvdXRQb2x5Z29uW2luZGV4XTtcclxuXHJcbiAgICAgIGxldCB3YWxsO1xyXG5cclxuICAgICAgZWxlbWVudC5yZWxhdGl2ZVBvc2l0aW9uID8/PSB7XHJcbiAgICAgICAgeDogMCxcclxuICAgICAgICB5OiAwLFxyXG4gICAgICAgIHVuaXQ6IFwiZnRcIixcclxuICAgICAgfTtcclxuXHJcbiAgICAgIGNvbnN0IHggPSB0aGlzLnRvUGl4ZWxzKGVsZW1lbnQucmVsYXRpdmVQb3NpdGlvbi54LCBlbGVtZW50LnVuaXQpO1xyXG4gICAgICBjb25zdCB5ID0gdGhpcy50b1BpeGVscyhlbGVtZW50LnJlbGF0aXZlUG9zaXRpb24ueSwgZWxlbWVudC51bml0KTtcclxuXHJcbiAgICAgIGlmIChlbGVtZW50LmVsZW1lbnRUeXBlID09PSBcIndhbGxcIikge1xyXG4gICAgICAgIGNvbnN0IGhlaWdodCA9IHRoaXMud2FsbFRoaWNrbmVzcztcclxuICAgICAgICBjb25zdCB3aWR0aCA9IHRoaXMudG9QaXhlbHMoZWxlbWVudC5kaXN0YW5jZSwgZWxlbWVudC51bml0KTtcclxuICAgICAgICB3YWxsID0gdGhpcy5kcmF3V2FsbCh0aGlzLmNhbnZhcywgeCwgeSwgaGVpZ2h0LCB3aWR0aCwgZWxlbWVudCk7XHJcbiAgICAgIH0gZWxzZSBpZiAoZWxlbWVudC5lbGVtZW50VHlwZSA9PT0gXCJlbnRyYW5jZVwiKSB7XHJcbiAgICAgICAgY29uc3QgYXJyb3dXaWR0aCA9IDgwO1xyXG4gICAgICAgIGNvbnN0IGFycm93SGVpZ2h0ID0gNzU7XHJcbiAgICAgICAgY29uc3QgYXJyb3dCYXNlID0gNDA7XHJcbiAgICAgICAgdGhpcy5kcmF3RW50cmFuY2UoXHJcbiAgICAgICAgICB0aGlzLmNhbnZhcyxcclxuICAgICAgICAgIHgsXHJcbiAgICAgICAgICB5LFxyXG4gICAgICAgICAgYXJyb3dXaWR0aCxcclxuICAgICAgICAgIGFycm93SGVpZ2h0LFxyXG4gICAgICAgICAgYXJyb3dCYXNlLFxyXG4gICAgICAgICAgZWxlbWVudCxcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBpZiAoZWxlbWVudC5lbGVtZW50VHlwZSA9PT0gXCJ3YWxsXCIpIHtcclxuICAgICAgICBjb25zdCBmaXh0dXJlR3JvdXBzOiBmYWJyaWMuR3JvdXBbXSA9IFtdO1xyXG5cclxuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGVsZW1lbnQ/LmZpeHR1cmVzPy5sZW5ndGg7IGorKykge1xyXG4gICAgICAgICAgY29uc3QgZml4dHVyZSA9IGVsZW1lbnQuZml4dHVyZXNbal07XHJcbiAgICAgICAgICBjb25zdCB4ID0gdGhpcy50b1BpeGVscyhcclxuICAgICAgICAgICAgZml4dHVyZS5yZWxhdGl2ZVBvc2l0aW9uLngsXHJcbiAgICAgICAgICAgIGZpeHR1cmUucmVsYXRpdmVQb3NpdGlvbi51bml0LFxyXG4gICAgICAgICAgKTtcclxuICAgICAgICAgIGNvbnN0IHkgPSB0aGlzLnRvUGl4ZWxzKFxyXG4gICAgICAgICAgICBmaXh0dXJlLnJlbGF0aXZlUG9zaXRpb24ueSxcclxuICAgICAgICAgICAgZml4dHVyZS5yZWxhdGl2ZVBvc2l0aW9uLnVuaXQsXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgY29uc3QgZml4dHVyZUhlaWdodCA9IHRoaXMudG9QaXhlbHMoXHJcbiAgICAgICAgICAgIGZpeHR1cmUuZml4dHVyZVN0YXRpY0xlbmd0aC52YWx1ZSxcclxuICAgICAgICAgICAgZml4dHVyZS5maXh0dXJlU3RhdGljTGVuZ3RoLnVuaXQsXHJcbiAgICAgICAgICApO1xyXG4gICAgICAgICAgY29uc3QgZml4dHVyZVdpZHRoID0gdGhpcy50b1BpeGVscyhcclxuICAgICAgICAgICAgZml4dHVyZS5maXh0dXJlU3RhdGljV2lkdGgudmFsdWUsXHJcbiAgICAgICAgICAgIGZpeHR1cmUuZml4dHVyZVN0YXRpY1dpZHRoLnVuaXQsXHJcbiAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgIGNvbnN0IGZpeHR1cmVPYmogPSBhd2FpdCB0aGlzLmRyYXdGaXh0dXJlKFxyXG4gICAgICAgICAgICB0aGlzLmNhbnZhcyxcclxuICAgICAgICAgICAgeCxcclxuICAgICAgICAgICAgeSxcclxuICAgICAgICAgICAgZml4dHVyZUhlaWdodCxcclxuICAgICAgICAgICAgZml4dHVyZVdpZHRoLFxyXG4gICAgICAgICAgICBmaXh0dXJlLFxyXG4gICAgICAgICAgKTtcclxuICAgICAgICAgIGZpeHR1cmVHcm91cHMucHVzaChmaXh0dXJlT2JqIGFzIGZhYnJpYy5Hcm91cCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoZWxlbWVudC5pc0xvY2tlZCAmJiB3YWxsKSB7XHJcbiAgICAgICAgICB0aGlzLmNhbnZhcy5yZW1vdmUod2FsbCk7XHJcbiAgICAgICAgICBmaXh0dXJlR3JvdXBzLmZvckVhY2goKGYpID0+IHRoaXMuY2FudmFzLnJlbW92ZShmKSk7XHJcblxyXG4gICAgICAgICAgY29uc3QgY29tYmluZWRHcm91cCA9IG5ldyBmYWJyaWMuR3JvdXAoW3dhbGwsIC4uLmZpeHR1cmVHcm91cHNdLCB7XHJcbiAgICAgICAgICAgIGhhc0NvbnRyb2xzOiB0cnVlLFxyXG4gICAgICAgICAgICBzZWxlY3RhYmxlOiB0cnVlLFxyXG4gICAgICAgICAgICBzdWJUYXJnZXRDaGVjazogdHJ1ZSxcclxuICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgIGNvbWJpbmVkR3JvdXAuc2V0KHsgaXNMb2NrZWQ6IHRydWUgfSk7XHJcbiAgICAgICAgICB0aGlzLmNhbnZhcy5hZGQoY29tYmluZWRHcm91cCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGVsZW1lbnQ/Lm90aGVyRWxlbWVudHM/Lmxlbmd0aDsgaisrKSB7XHJcbiAgICAgICAgICBjb25zdCBvdGhlckVsZW1lbnQgPSBlbGVtZW50Lm90aGVyRWxlbWVudHNbal07XHJcbiAgICAgICAgICBjb25zdCB4ID0gdGhpcy50b1BpeGVscyhvdGhlckVsZW1lbnQucmVsYXRpdmVQb3NpdGlvbi54LCBcImZ0XCIpO1xyXG4gICAgICAgICAgY29uc3QgeSA9IHRoaXMudG9QaXhlbHMob3RoZXJFbGVtZW50LnJlbGF0aXZlUG9zaXRpb24ueSwgXCJmdFwiKTtcclxuICAgICAgICAgIGNvbnN0IGggPSB0aGlzLnRvUGl4ZWxzKFxyXG4gICAgICAgICAgICBvdGhlckVsZW1lbnQuZml4dHVyZVN0YXRpY0xlbmd0aC52YWx1ZSxcclxuICAgICAgICAgICAgb3RoZXJFbGVtZW50LmZpeHR1cmVTdGF0aWNMZW5ndGgudW5pdCxcclxuICAgICAgICAgICk7XHJcbiAgICAgICAgICBjb25zdCB3ID0gdGhpcy50b1BpeGVscyhcclxuICAgICAgICAgICAgb3RoZXJFbGVtZW50LmZpeHR1cmVTdGF0aWNXaWR0aC52YWx1ZSxcclxuICAgICAgICAgICAgb3RoZXJFbGVtZW50LmZpeHR1cmVTdGF0aWNXaWR0aC51bml0LFxyXG4gICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICB0aGlzLmRyYXdMYWJlbGVkUmVjdGFuZ2xlKHRoaXMuY2FudmFzLCB4LCB5LCB3LCBoLCBvdGhlckVsZW1lbnQpO1xyXG4gICAgICAgIH1cclxuICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5mbG9vckRhdGE/LmNlbnRlckZpeHR1cmU/Lmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgIGNvbnN0IGZpeHR1cmUgPSB0aGlzLmZsb29yRGF0YS5jZW50ZXJGaXh0dXJlW2ldO1xyXG4gICAgICBjb25zdCB4ID0gdGhpcy50b1BpeGVscyhcclxuICAgICAgICBmaXh0dXJlLnJlbGF0aXZlUG9zaXRpb24ueCxcclxuICAgICAgICBmaXh0dXJlLnJlbGF0aXZlUG9zaXRpb24udW5pdCxcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgeSA9IHRoaXMudG9QaXhlbHMoXHJcbiAgICAgICAgZml4dHVyZS5yZWxhdGl2ZVBvc2l0aW9uLnksXHJcbiAgICAgICAgZml4dHVyZS5yZWxhdGl2ZVBvc2l0aW9uLnVuaXQsXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IGZpeHR1cmVIZWlnaHQgPSB0aGlzLnRvUGl4ZWxzKFxyXG4gICAgICAgIGZpeHR1cmUuZml4dHVyZVN0YXRpY0xlbmd0aC52YWx1ZSxcclxuICAgICAgICBmaXh0dXJlLmZpeHR1cmVTdGF0aWNMZW5ndGgudW5pdCxcclxuICAgICAgKTtcclxuICAgICAgY29uc3QgZml4dHVyZVdpZHRoID0gdGhpcy50b1BpeGVscyhcclxuICAgICAgICBmaXh0dXJlLmZpeHR1cmVTdGF0aWNXaWR0aC52YWx1ZSxcclxuICAgICAgICBmaXh0dXJlLmZpeHR1cmVTdGF0aWNXaWR0aC51bml0LFxyXG4gICAgICApO1xyXG4gICAgICBhd2FpdCB0aGlzLmRyYXdGaXh0dXJlKFxyXG4gICAgICAgIHRoaXMuY2FudmFzLFxyXG4gICAgICAgIHgsXHJcbiAgICAgICAgeSxcclxuICAgICAgICBmaXh0dXJlSGVpZ2h0LFxyXG4gICAgICAgIGZpeHR1cmVXaWR0aCxcclxuICAgICAgICBmaXh0dXJlLFxyXG4gICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIGZvciAobGV0IGogPSAwOyBqIDwgdGhpcy5mbG9vckRhdGE/Lm90aGVyRWxlbWVudHM/Lmxlbmd0aDsgaisrKSB7XHJcbiAgICAgIGNvbnN0IG90aGVyRWxlbWVudCA9IHRoaXMuZmxvb3JEYXRhLm90aGVyRWxlbWVudHNbal07XHJcbiAgICAgIGNvbnN0IHggPSB0aGlzLnRvUGl4ZWxzKG90aGVyRWxlbWVudC5yZWxhdGl2ZVBvc2l0aW9uLngsIFwiZnRcIik7XHJcbiAgICAgIGNvbnN0IHkgPSB0aGlzLnRvUGl4ZWxzKG90aGVyRWxlbWVudC5yZWxhdGl2ZVBvc2l0aW9uLnksIFwiZnRcIik7XHJcbiAgICAgIGNvbnN0IGggPSB0aGlzLnRvUGl4ZWxzKFxyXG4gICAgICAgIG90aGVyRWxlbWVudC5maXh0dXJlU3RhdGljTGVuZ3RoLnZhbHVlLFxyXG4gICAgICAgIG90aGVyRWxlbWVudC5maXh0dXJlU3RhdGljTGVuZ3RoLnVuaXQsXHJcbiAgICAgICk7XHJcbiAgICAgIGNvbnN0IHcgPSB0aGlzLnRvUGl4ZWxzKFxyXG4gICAgICAgIG90aGVyRWxlbWVudC5maXh0dXJlU3RhdGljV2lkdGgudmFsdWUsXHJcbiAgICAgICAgb3RoZXJFbGVtZW50LmZpeHR1cmVTdGF0aWNXaWR0aC51bml0LFxyXG4gICAgICApO1xyXG5cclxuICAgICAgdGhpcy5kcmF3TGFiZWxlZFJlY3RhbmdsZSh0aGlzLmNhbnZhcywgeCwgeSwgdywgaCwgb3RoZXJFbGVtZW50KTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIGRyYXdXYWxsKFxyXG4gICAgY2FudmFzOiBmYWJyaWMuQ2FudmFzLFxyXG4gICAgeDogbnVtYmVyLFxyXG4gICAgeTogbnVtYmVyLFxyXG4gICAgaGVpZ2h0OiBudW1iZXIsXHJcbiAgICB3aWR0aDogbnVtYmVyLFxyXG4gICAgZWxlbWVudERhdGE6IGFueSxcclxuICApIHtcclxuICAgIGNvbnN0IHJhZGl1cyA9IDU7XHJcbiAgICBjb25zdCBmaWxsQ29sb3IgPSBcIiNGNkZDRkZcIjtcclxuICAgIGNvbnN0IHN0cm9rZUNvbG9yID0gXCIjRDBENUREXCI7XHJcbiAgICBjb25zdCBsYWJlbENvbG9yID0gXCIjMDA5QkYzXCI7XHJcbiAgICBjb25zdCB0ZXh0ID0gYCR7dGhpcy50aXRsZUNhc2UudHJhbnNmb3JtKGVsZW1lbnREYXRhLmVsZW1lbnRUeXBlKX0gJHtcclxuICAgICAgZWxlbWVudERhdGEuZWxlbWVudE51bWJlclxyXG4gICAgfWA7XHJcblxyXG4gICAgY29uc3Qgd2FsbCA9IG5ldyBmYWJyaWMuUmVjdCh7XHJcbiAgICAgIGxlZnQ6IDAsXHJcbiAgICAgIHRvcDogMCxcclxuICAgICAgd2lkdGgsXHJcbiAgICAgIGhlaWdodCxcclxuICAgICAgcng6IHJhZGl1cyxcclxuICAgICAgcnk6IHJhZGl1cyxcclxuICAgICAgZmlsbDogZmlsbENvbG9yLFxyXG4gICAgICBzdHJva2U6IHN0cm9rZUNvbG9yLFxyXG4gICAgICBzdHJva2VXaWR0aDogMC4yNyxcclxuICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCBjZW50ZXJYID0gd2lkdGggLyAyO1xyXG4gICAgY29uc3QgY2VudGVyWSA9IGhlaWdodCAvIDI7XHJcbiAgICBjb25zdCBpc1ZlcnRpY2FsID0gaGVpZ2h0ID4gd2lkdGg7XHJcblxyXG4gICAgY29uc3QgbGFiZWwgPSBuZXcgZmFicmljLkZhYnJpY1RleHQodGV4dCwge1xyXG4gICAgICBsZWZ0OiBjZW50ZXJYLFxyXG4gICAgICB0b3A6IGNlbnRlclksXHJcbiAgICAgIGZvbnRTaXplOiAxMCxcclxuICAgICAgZm9udEZhbWlseTogXCJJbnRlclwiLFxyXG4gICAgICBmb250V2VpZ2h0OiBcIjUwMFwiLFxyXG4gICAgICBmaWxsOiBsYWJlbENvbG9yLFxyXG4gICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICBhbmdsZTogaXNWZXJ0aWNhbCA/IC05MCA6IDAsXHJcbiAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgYXJyb3dIZWFkID0gNTtcclxuICAgIGNvbnN0IGVsZW1lbnRzOiBmYWJyaWMuT2JqZWN0W10gPSBbd2FsbCwgbGFiZWxdO1xyXG5cclxuICAgIGlmIChpc1ZlcnRpY2FsKSB7XHJcbiAgICAgIGNvbnN0IHRleHRXaWR0aCA9IGxhYmVsLndpZHRoIHx8IDA7XHJcbiAgICAgIGNvbnN0IHRvcEFycm93WSA9IDU7XHJcbiAgICAgIGNvbnN0IHRvcEFycm93RW5kWSA9IGNlbnRlclkgLSB0ZXh0V2lkdGggLyAyIC0gNTtcclxuXHJcbiAgICAgIGlmICh0b3BBcnJvd0VuZFkgPiB0b3BBcnJvd1kgKyBhcnJvd0hlYWQpIHtcclxuICAgICAgICBlbGVtZW50cy5wdXNoKFxyXG4gICAgICAgICAgbmV3IGZhYnJpYy5MaW5lKFtjZW50ZXJYLCB0b3BBcnJvd1ksIGNlbnRlclgsIHRvcEFycm93RW5kWV0sIHtcclxuICAgICAgICAgICAgc3Ryb2tlOiBsYWJlbENvbG9yLFxyXG4gICAgICAgICAgICBzdHJva2VXaWR0aDogMSxcclxuICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICB9KSxcclxuICAgICAgICAgIG5ldyBmYWJyaWMuVHJpYW5nbGUoe1xyXG4gICAgICAgICAgICBsZWZ0OiBjZW50ZXJYLFxyXG4gICAgICAgICAgICB0b3A6IHRvcEFycm93WSxcclxuICAgICAgICAgICAgd2lkdGg6IGFycm93SGVhZCxcclxuICAgICAgICAgICAgaGVpZ2h0OiBhcnJvd0hlYWQsXHJcbiAgICAgICAgICAgIGFuZ2xlOiAwLFxyXG4gICAgICAgICAgICBmaWxsOiBsYWJlbENvbG9yLFxyXG4gICAgICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgICBvcmlnaW5ZOiBcImJvdHRvbVwiLFxyXG4gICAgICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICAgIH0pLFxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuXHJcbiAgICAgIGNvbnN0IGJvdHRvbUFycm93U3RhcnRZID0gY2VudGVyWSArIHRleHRXaWR0aCAvIDIgKyA1O1xyXG4gICAgICBjb25zdCBib3R0b21BcnJvd0VuZFkgPSBoZWlnaHQgLSA1O1xyXG5cclxuICAgICAgaWYgKGJvdHRvbUFycm93RW5kWSA+IGJvdHRvbUFycm93U3RhcnRZICsgYXJyb3dIZWFkKSB7XHJcbiAgICAgICAgZWxlbWVudHMucHVzaChcclxuICAgICAgICAgIG5ldyBmYWJyaWMuTGluZShcclxuICAgICAgICAgICAgW2NlbnRlclgsIGJvdHRvbUFycm93U3RhcnRZLCBjZW50ZXJYLCBib3R0b21BcnJvd0VuZFldLFxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgc3Ryb2tlOiBsYWJlbENvbG9yLFxyXG4gICAgICAgICAgICAgIHN0cm9rZVdpZHRoOiAxLFxyXG4gICAgICAgICAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgKSxcclxuICAgICAgICAgIG5ldyBmYWJyaWMuVHJpYW5nbGUoe1xyXG4gICAgICAgICAgICBsZWZ0OiBjZW50ZXJYLFxyXG4gICAgICAgICAgICB0b3A6IGJvdHRvbUFycm93RW5kWSxcclxuICAgICAgICAgICAgd2lkdGg6IGFycm93SGVhZCxcclxuICAgICAgICAgICAgaGVpZ2h0OiBhcnJvd0hlYWQsXHJcbiAgICAgICAgICAgIGFuZ2xlOiAxODAsXHJcbiAgICAgICAgICAgIGZpbGw6IGxhYmVsQ29sb3IsXHJcbiAgICAgICAgICAgIG9yaWdpblg6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgICAgIG9yaWdpblk6IFwidG9wXCIsXHJcbiAgICAgICAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgfSksXHJcbiAgICAgICAgKTtcclxuICAgICAgfVxyXG4gICAgfSBlbHNlIHtcclxuICAgICAgY29uc3QgdGV4dFdpZHRoID0gbGFiZWwud2lkdGggfHwgMDtcclxuICAgICAgY29uc3QgbGVmdEFycm93U3RhcnRYID0gNTtcclxuICAgICAgY29uc3QgbGVmdEFycm93RW5kWCA9IGNlbnRlclggLSB0ZXh0V2lkdGggLyAyIC0gNTtcclxuXHJcbiAgICAgIGlmIChsZWZ0QXJyb3dFbmRYID4gbGVmdEFycm93U3RhcnRYICsgYXJyb3dIZWFkKSB7XHJcbiAgICAgICAgZWxlbWVudHMucHVzaChcclxuICAgICAgICAgIG5ldyBmYWJyaWMuTGluZShbbGVmdEFycm93U3RhcnRYLCBjZW50ZXJZLCBsZWZ0QXJyb3dFbmRYLCBjZW50ZXJZXSwge1xyXG4gICAgICAgICAgICBzdHJva2U6IGxhYmVsQ29sb3IsXHJcbiAgICAgICAgICAgIHN0cm9rZVdpZHRoOiAxLFxyXG4gICAgICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICAgIH0pLFxyXG4gICAgICAgICAgbmV3IGZhYnJpYy5UcmlhbmdsZSh7XHJcbiAgICAgICAgICAgIGxlZnQ6IGxlZnRBcnJvd1N0YXJ0WCxcclxuICAgICAgICAgICAgdG9wOiBjZW50ZXJZLFxyXG4gICAgICAgICAgICB3aWR0aDogYXJyb3dIZWFkLFxyXG4gICAgICAgICAgICBoZWlnaHQ6IGFycm93SGVhZCxcclxuICAgICAgICAgICAgYW5nbGU6IC05MCxcclxuICAgICAgICAgICAgZmlsbDogbGFiZWxDb2xvcixcclxuICAgICAgICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgICAgICAgb3JpZ2luWTogXCJjZW50ZXJcIixcclxuICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICB9KSxcclxuICAgICAgICApO1xyXG4gICAgICB9XHJcblxyXG4gICAgICBjb25zdCByaWdodEFycm93U3RhcnRYID0gY2VudGVyWCArIHRleHRXaWR0aCAvIDIgKyA1O1xyXG4gICAgICBjb25zdCByaWdodEFycm93RW5kWCA9IHdpZHRoIC0gNTtcclxuXHJcbiAgICAgIGlmIChyaWdodEFycm93RW5kWCA+IHJpZ2h0QXJyb3dTdGFydFggKyBhcnJvd0hlYWQpIHtcclxuICAgICAgICBlbGVtZW50cy5wdXNoKFxyXG4gICAgICAgICAgbmV3IGZhYnJpYy5MaW5lKFxyXG4gICAgICAgICAgICBbcmlnaHRBcnJvd1N0YXJ0WCwgY2VudGVyWSwgcmlnaHRBcnJvd0VuZFgsIGNlbnRlclldLFxyXG4gICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgc3Ryb2tlOiBsYWJlbENvbG9yLFxyXG4gICAgICAgICAgICAgIHN0cm9rZVdpZHRoOiAxLFxyXG4gICAgICAgICAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgKSxcclxuICAgICAgICAgIG5ldyBmYWJyaWMuVHJpYW5nbGUoe1xyXG4gICAgICAgICAgICBsZWZ0OiByaWdodEFycm93RW5kWCxcclxuICAgICAgICAgICAgdG9wOiBjZW50ZXJZLFxyXG4gICAgICAgICAgICB3aWR0aDogYXJyb3dIZWFkLFxyXG4gICAgICAgICAgICBoZWlnaHQ6IGFycm93SGVhZCxcclxuICAgICAgICAgICAgYW5nbGU6IDkwLFxyXG4gICAgICAgICAgICBmaWxsOiBsYWJlbENvbG9yLFxyXG4gICAgICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICAgIH0pLFxyXG4gICAgICAgICk7XHJcbiAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBjb25zdCBncm91cCA9IG5ldyBmYWJyaWMuR3JvdXAoZWxlbWVudHMsIHtcclxuICAgICAgbGVmdDogeCxcclxuICAgICAgdG9wOiB5LFxyXG4gICAgICBoYXNDb250cm9sczogZmFsc2UsXHJcbiAgICAgIGxvY2tTY2FsaW5nWDogdHJ1ZSxcclxuICAgICAgbG9ja1NjYWxpbmdZOiB0cnVlLFxyXG4gICAgICBsb2NrUm90YXRpb246IHRydWUsXHJcbiAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgICBhbmdsZTogZWxlbWVudERhdGEuYW5nbGUsXHJcbiAgICB9KSBhcyBmYWJyaWMuR3JvdXAgJiB7XHJcbiAgICAgIG9ialR5cGU6IHN0cmluZztcclxuICAgICAgZGF0YTogYW55O1xyXG4gICAgfTtcclxuICAgIGdyb3VwLm9ialR5cGUgPSBlbGVtZW50RGF0YS5lbGVtZW50VHlwZTtcclxuICAgIGdyb3VwLmRhdGEgPSBlbGVtZW50RGF0YTtcclxuICAgIGNhbnZhcy5hZGQoZ3JvdXApO1xyXG5cclxuICAgIHJldHVybiBncm91cDtcclxuICB9XHJcblxyXG4gIGRyYXdFbnRyYW5jZShcclxuICAgIGNhbnZhczogZmFicmljLkNhbnZhcyxcclxuICAgIHg6IG51bWJlcixcclxuICAgIHk6IG51bWJlcixcclxuICAgIHdpZHRoOiBudW1iZXIsXHJcbiAgICBoZWlnaHQ6IG51bWJlcixcclxuICAgIGFycm93V2lkdGg6IG51bWJlcixcclxuICAgIGVsZW1lbnREYXRhOiBhbnksXHJcbiAgKSB7XHJcbiAgICBjb25zdCBib2R5V2lkdGggPSB3aWR0aCAtIGFycm93V2lkdGg7XHJcblxyXG4gICAgY29uc3QgcGF0aERhdGEgPSBbXHJcbiAgICAgIGBNIDAgMGAsXHJcbiAgICAgIGBMICR7Ym9keVdpZHRofSAwYCxcclxuICAgICAgYEwgJHtib2R5V2lkdGh9ICR7LWhlaWdodCAvIDJ9YCxcclxuICAgICAgYEwgJHt3aWR0aH0gJHtoZWlnaHQgLyAyfWAsXHJcbiAgICAgIGBMICR7Ym9keVdpZHRofSAke2hlaWdodCArIGhlaWdodCAvIDJ9YCxcclxuICAgICAgYEwgJHtib2R5V2lkdGh9ICR7aGVpZ2h0fWAsXHJcbiAgICAgIGBMIDAgJHtoZWlnaHR9YCxcclxuICAgICAgYFpgLFxyXG4gICAgXS5qb2luKFwiIFwiKTtcclxuXHJcbiAgICBjb25zdCBhcnJvdyA9IG5ldyBmYWJyaWMuUGF0aChwYXRoRGF0YSwge1xyXG4gICAgICBmaWxsOiBcIiMwM0E5RjRcIixcclxuICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgIGV2ZW50ZWQ6IGZhbHNlLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgbWF4VGV4dEhlaWdodCA9IGhlaWdodCAtIDY7XHJcbiAgICBjb25zdCB0ZXh0ID0gbmV3IGZhYnJpYy5UZXh0KFwiRW50cmFuY2VcIiwge1xyXG4gICAgICBmb250RmFtaWx5OiBcIkFyaWFsXCIsXHJcbiAgICAgIGZvbnRXZWlnaHQ6IFwiYm9sZFwiLFxyXG4gICAgICBmaWxsOiBcIndoaXRlXCIsXHJcbiAgICAgIGFuZ2xlOiAtOTAsXHJcbiAgICAgIG9yaWdpblg6IFwiY2VudGVyXCIsXHJcbiAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgIGxlZnQ6IDE1LFxyXG4gICAgICB0b3A6IGhlaWdodCAvIDIsXHJcbiAgICAgIGZvbnRTaXplOiAyMCxcclxuICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgIGV2ZW50ZWQ6IGZhbHNlLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgdGV4dEJvdW5kcyA9IHRleHQuZ2V0Qm91bmRpbmdSZWN0KCk7XHJcbiAgICBpZiAodGV4dEJvdW5kcy5oZWlnaHQgPiBtYXhUZXh0SGVpZ2h0KSB7XHJcbiAgICAgIGNvbnN0IHNjYWxlID0gbWF4VGV4dEhlaWdodCAvIHRleHRCb3VuZHMuaGVpZ2h0O1xyXG4gICAgICB0ZXh0LnNldChcImZvbnRTaXplXCIsIHRleHQuZm9udFNpemUhICogc2NhbGUpO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGdyb3VwID0gbmV3IGZhYnJpYy5Hcm91cChbYXJyb3csIHRleHRdLCB7XHJcbiAgICAgIGxlZnQ6IHgsXHJcbiAgICAgIHRvcDogeSxcclxuICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgIGxvY2tTY2FsaW5nWDogdHJ1ZSxcclxuICAgICAgbG9ja1NjYWxpbmdZOiB0cnVlLFxyXG4gICAgICBsb2NrU2NhbGluZ0ZsaXA6IHRydWUsXHJcbiAgICAgIGFuZ2xlOiBlbGVtZW50RGF0YS5hbmdsZSxcclxuICAgIH0pIGFzIGZhYnJpYy5Hcm91cCAmIHtcclxuICAgICAgb2JqVHlwZTogc3RyaW5nO1xyXG4gICAgICBkYXRhOiBhbnk7XHJcbiAgICB9O1xyXG5cclxuICAgIGdyb3VwLm9ialR5cGUgPSBlbGVtZW50RGF0YS5lbGVtZW50VHlwZTtcclxuICAgIGdyb3VwLmRhdGEgPSBlbGVtZW50RGF0YTtcclxuXHJcbiAgICBjYW52YXMuYWRkKGdyb3VwKTtcclxuICB9XHJcblxyXG4gIGFzeW5jIGRyYXdGaXh0dXJlKFxyXG4gICAgY2FudmFzOiBmYWJyaWMuQ2FudmFzLFxyXG4gICAgeDogbnVtYmVyLFxyXG4gICAgeTogbnVtYmVyLFxyXG4gICAgaGVpZ2h0OiBudW1iZXIsXHJcbiAgICB3aWR0aDogbnVtYmVyLFxyXG4gICAgZml4dHVyZURhdGE6IGFueSxcclxuICApIHtcclxuICAgIGNvbnN0IGlzVGFyZ2V0Rml4dHVyZSA9XHJcbiAgICAgIHRoaXMuc2VsZWN0ZWRQcm9kdWN0Py5maXh0dXJlRGV0YWlscz8uZml4dHVyZUlkID09PSBmaXh0dXJlRGF0YT8uX2lkO1xyXG4gICAgY29uc3QgcmFkaXVzID0gNTtcclxuICAgIGNvbnN0IG1haW5Db250YWluZXIgPSBuZXcgZmFicmljLlJlY3Qoe1xyXG4gICAgICBsZWZ0OiB4LFxyXG4gICAgICB0b3A6IHksXHJcbiAgICAgIHdpZHRoOiB3aWR0aCxcclxuICAgICAgaGVpZ2h0OiBoZWlnaHQsXHJcbiAgICAgIHJ4OiByYWRpdXMsXHJcbiAgICAgIHJ5OiByYWRpdXMsXHJcbiAgICAgIHN0cm9rZTogaXNUYXJnZXRGaXh0dXJlID8gXCIjNTFDMUZGXCIgOiBcIiNjMmMyYzJcIixcclxuICAgICAgc3Ryb2tlV2lkdGg6IDAuMjcsXHJcbiAgICAgIGZpbGw6IFwid2hpdGVcIixcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IHRvcFdpZHRoID0gd2lkdGggLyAxLjA1O1xyXG4gICAgY29uc3QgdG9wSGVpZ2h0ID0gKDE1IC8gMTAwKSAqIGhlaWdodDtcclxuICAgIGNvbnN0IHRvcFggPSB4ICsgKHdpZHRoIC0gdG9wV2lkdGgpIC8gMjtcclxuICAgIGNvbnN0IHRvcFkgPSB5ICsgdGhpcy52ZXJ0aWNhbE1hcmdpbjtcclxuXHJcbiAgICBjb25zdCB0b3BDb250YWluZXIgPSBuZXcgZmFicmljLlJlY3Qoe1xyXG4gICAgICBsZWZ0OiB0b3BYLFxyXG4gICAgICB0b3A6IHRvcFksXHJcbiAgICAgIHdpZHRoOiB0b3BXaWR0aCxcclxuICAgICAgaGVpZ2h0OiB0b3BIZWlnaHQsXHJcbiAgICAgIHJ4OiByYWRpdXMsXHJcbiAgICAgIHJ5OiByYWRpdXMsXHJcbiAgICAgIHN0cm9rZTogaXNUYXJnZXRGaXh0dXJlID8gXCIjNTFDMUZGXCIgOiBcIiNjMmMyYzJcIixcclxuICAgICAgc3Ryb2tlV2lkdGg6IDAuMjcsXHJcbiAgICAgIGZpbGw6IFwid2hpdGVcIixcclxuICAgIH0pO1xyXG5cclxuICAgIGNvbnN0IGlubmVyQm94SGVpZ2h0ID0gdG9wSGVpZ2h0IC8gMjtcclxuICAgIGNvbnN0IGlubmVyVG9wQm94ID0gbmV3IGZhYnJpYy5QYXRoKFxyXG4gICAgICBgTSAke3RvcFggKyByYWRpdXN9ICR7dG9wWX0gXHJcbiAgICAgICAgTCAke3RvcFggKyB0b3BXaWR0aCAtIHJhZGl1c30gJHt0b3BZfSBcclxuICAgICAgICBRICR7dG9wWCArIHRvcFdpZHRofSAke3RvcFl9ICR7dG9wWCArIHRvcFdpZHRofSAke3RvcFkgKyByYWRpdXN9IFxyXG4gICAgICAgIEwgJHt0b3BYICsgdG9wV2lkdGh9ICR7dG9wWSArIGlubmVyQm94SGVpZ2h0fSBcclxuICAgICAgICBMICR7dG9wWH0gJHt0b3BZICsgaW5uZXJCb3hIZWlnaHR9IFxyXG4gICAgICAgIEwgJHt0b3BYfSAke3RvcFkgKyByYWRpdXN9IFxyXG4gICAgICAgIFEgJHt0b3BYfSAke3RvcFl9ICR7dG9wWCArIHJhZGl1c30gJHt0b3BZfSBaYCxcclxuICAgICAge1xyXG4gICAgICAgIHN0cm9rZTogaXNUYXJnZXRGaXh0dXJlID8gXCIjNTFDMUZGXCIgOiBcIiNjMmMyYzJcIixcclxuICAgICAgICBzdHJva2VXaWR0aDogMC4yNyxcclxuICAgICAgICBmaWxsOiBcInRyYW5zcGFyZW50XCIsXHJcbiAgICAgIH0sXHJcbiAgICApO1xyXG5cclxuICAgIGNvbnN0IHRvcFRleHQgPSBuZXcgZmFicmljLlRleHRib3goXHJcbiAgICAgIGBGaXh0dXJlICR7XHJcbiAgICAgICAgZml4dHVyZURhdGEuYXNzb2NpYXRlZEVsZW1lbnRGaXh0dXJlTnVtYmVyXHJcbiAgICAgICAgICA/IGZpeHR1cmVEYXRhLmFzc29jaWF0ZWRFbGVtZW50Rml4dHVyZU51bWJlciArXHJcbiAgICAgICAgICAgIChmaXh0dXJlRGF0YT8uZml4dHVyZU51bWJlclxyXG4gICAgICAgICAgICAgID8gXCIgLSBGWC1cIiArIGZpeHR1cmVEYXRhLmZpeHR1cmVOdW1iZXJcclxuICAgICAgICAgICAgICA6IFwiXCIpXHJcbiAgICAgICAgICA6IFwibmV3XCJcclxuICAgICAgfWAsXHJcbiAgICAgIHtcclxuICAgICAgICBsZWZ0OiB0b3BYICsgdG9wV2lkdGggLyAyLFxyXG4gICAgICAgIHRvcDogdG9wWSArIGlubmVyQm94SGVpZ2h0IC8gMixcclxuICAgICAgICBmb250U2l6ZTogNSxcclxuICAgICAgICBmb250RmFtaWx5OiBcIkludGVyXCIsXHJcbiAgICAgICAgZm9udFdlaWdodDogXCI1MDBcIixcclxuICAgICAgICBmaWxsOiBcIiMxMDE4MjhcIixcclxuICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgd2lkdGg6IHRvcFdpZHRoLFxyXG4gICAgICAgIGhlaWdodDogaW5uZXJCb3hIZWlnaHQsXHJcbiAgICAgICAgdGV4dEFsaWduOiBcImNlbnRlclwiLFxyXG4gICAgICB9LFxyXG4gICAgKTtcclxuXHJcbiAgICBjb25zdCBzZWNvbmRCb3hZID0gdG9wWSArIGlubmVyQm94SGVpZ2h0O1xyXG5cclxuICAgIGNvbnN0IGlubmVyQm90dG9tQm94ID0gbmV3IGZhYnJpYy5QYXRoKFxyXG4gICAgICBgTSAke3RvcFh9ICR7c2Vjb25kQm94WX0gXHJcbiAgICBMICR7dG9wWCArIHRvcFdpZHRofSAke3NlY29uZEJveFl9IFxyXG4gICAgTCAke3RvcFggKyB0b3BXaWR0aH0gJHtzZWNvbmRCb3hZICsgaW5uZXJCb3hIZWlnaHQgLSByYWRpdXN9IFxyXG4gICAgUSAke3RvcFggKyB0b3BXaWR0aH0gJHtzZWNvbmRCb3hZICsgaW5uZXJCb3hIZWlnaHR9ICR7XHJcbiAgICAgIHRvcFggKyB0b3BXaWR0aCAtIHJhZGl1c1xyXG4gICAgfSAke3NlY29uZEJveFkgKyBpbm5lckJveEhlaWdodH0gXHJcbiAgICBMICR7dG9wWCArIHJhZGl1c30gJHtzZWNvbmRCb3hZICsgaW5uZXJCb3hIZWlnaHR9IFxyXG4gICAgUSAke3RvcFh9ICR7c2Vjb25kQm94WSArIGlubmVyQm94SGVpZ2h0fSAke3RvcFh9ICR7XHJcbiAgICAgIHNlY29uZEJveFkgKyBpbm5lckJveEhlaWdodCAtIHJhZGl1c1xyXG4gICAgfSBcclxuICAgIEwgJHt0b3BYfSAke3NlY29uZEJveFl9IFpgLFxyXG4gICAgICB7XHJcbiAgICAgICAgZmlsbDogXCIjMzQ0MDU0XCIsXHJcbiAgICAgICAgc3Ryb2tlOiBcIiM1MUMxRkZcIixcclxuICAgICAgICBzdHJva2VXaWR0aDogMC4yNyxcclxuICAgICAgfSxcclxuICAgICk7XHJcblxyXG4gICAgbGV0IGZvbnRTaXplID0gNTtcclxuICAgIGxldCBib3R0b21UZXh0O1xyXG5cclxuICAgIGNvbnN0IHRleHRDb250ZW50ID0gYCR7Zml4dHVyZURhdGE/LmZpeHR1cmVOYW1lfSAtICR7Zml4dHVyZURhdGE/LmZpeHR1cmVXaWR0aC52YWx1ZX0gJHtmaXh0dXJlRGF0YT8uZml4dHVyZVdpZHRoLnVuaXR9YDtcclxuXHJcbiAgICBjb25zdCBjcmVhdGVCb3R0b21UZXh0ID0gKGZzOiBhbnkpID0+XHJcbiAgICAgIG5ldyBmYWJyaWMuVGV4dGJveCh0ZXh0Q29udGVudCwge1xyXG4gICAgICAgIGxlZnQ6IHRvcFggKyB0b3BXaWR0aCAvIDIsXHJcbiAgICAgICAgdG9wOiBzZWNvbmRCb3hZICsgaW5uZXJCb3hIZWlnaHQgLyAyLFxyXG4gICAgICAgIGZvbnRTaXplOiBmcyxcclxuICAgICAgICBmb250RmFtaWx5OiBcIkludGVyXCIsXHJcbiAgICAgICAgZm9udFdlaWdodDogXCI1MDBcIixcclxuICAgICAgICBmaWxsOiBcIiNGRkZGRkZcIixcclxuICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgdGV4dEFsaWduOiBcImNlbnRlclwiLFxyXG4gICAgICAgIHdpZHRoOiB0b3BXaWR0aCxcclxuICAgICAgfSk7XHJcblxyXG4gICAgZG8ge1xyXG4gICAgICBib3R0b21UZXh0ID0gY3JlYXRlQm90dG9tVGV4dChmb250U2l6ZSk7XHJcbiAgICAgIGZvbnRTaXplIC09IDAuNTtcclxuICAgIH0gd2hpbGUgKGJvdHRvbVRleHQuaGVpZ2h0ID4gaW5uZXJCb3hIZWlnaHQgJiYgZm9udFNpemUgPiAyKTtcclxuXHJcbiAgICBjb25zdCBtaWRXaWR0aCA9IHdpZHRoIC8gMS4wNTtcclxuICAgIGNvbnN0IG1pZEhlaWdodCA9ICg3NyAvIDEwMCkgKiBoZWlnaHQ7XHJcbiAgICBjb25zdCBtaWRYID0geCArICh3aWR0aCAtIG1pZFdpZHRoKSAvIDI7XHJcbiAgICBjb25zdCBtaWRZID0gdG9wWSArIHRvcEhlaWdodCArIHRoaXMudmVydGljYWxNYXJnaW47XHJcblxyXG4gICAgY29uc3QgbWlkQ29udGFpbmVyID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgbGVmdDogbWlkWCxcclxuICAgICAgdG9wOiBtaWRZLFxyXG4gICAgICB3aWR0aDogbWlkV2lkdGgsXHJcbiAgICAgIGhlaWdodDogbWlkSGVpZ2h0LFxyXG4gICAgICByeDogcmFkaXVzLFxyXG4gICAgICByeTogcmFkaXVzLFxyXG4gICAgICBzdHJva2U6IFwiIzUxQzFGRlwiLFxyXG4gICAgICBzdHJva2VXaWR0aDogMC4yNyxcclxuICAgICAgZmlsbDogXCJ3aGl0ZVwiLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3Qgc2hlbGZDb3VudCA9IGZpeHR1cmVEYXRhLnNoZWxmQ29uZmlnPy5sZW5ndGg7XHJcbiAgICBjb25zdCBib3hIZWlnaHQgPSBtaWRIZWlnaHQgLyAoc2hlbGZDb3VudCArIDIpO1xyXG4gICAgY29uc3QgZmlyc3RCb3hZID0gbWlkWTtcclxuXHJcbiAgICBjb25zdCBmaXJzdEJveCA9IG5ldyBmYWJyaWMuUGF0aChcclxuICAgICAgYE0gJHttaWRYICsgcmFkaXVzfSAke2ZpcnN0Qm94WX0gXHJcbiAgICAgICAgTCAke21pZFggKyBtaWRXaWR0aCAtIHJhZGl1c30gJHtmaXJzdEJveFl9IFxyXG4gICAgICAgIFEgJHttaWRYICsgbWlkV2lkdGh9ICR7Zmlyc3RCb3hZfSAke21pZFggKyBtaWRXaWR0aH0gJHtcclxuICAgICAgICAgIGZpcnN0Qm94WSArIHJhZGl1c1xyXG4gICAgICAgIH0gXHJcbiAgICAgICAgTCAke21pZFggKyBtaWRXaWR0aH0gJHtmaXJzdEJveFkgKyBib3hIZWlnaHR9IFxyXG4gICAgICAgIEwgJHttaWRYfSAke2ZpcnN0Qm94WSArIGJveEhlaWdodH0gXHJcbiAgICAgICAgTCAke21pZFh9ICR7Zmlyc3RCb3hZICsgcmFkaXVzfSBcclxuICAgICAgICBRICR7bWlkWH0gJHtmaXJzdEJveFl9ICR7bWlkWCArIHJhZGl1c30gJHtmaXJzdEJveFl9IFpgLFxyXG4gICAgICB7XHJcbiAgICAgICAgZmlsbDogaXNUYXJnZXRGaXh0dXJlID8gXCIjRUFGOEZGXCIgOiBcIiNmOWZiZmZcIixcclxuICAgICAgICBzdHJva2U6IGlzVGFyZ2V0Rml4dHVyZSA/IFwiIzZCQ0FGRlwiIDogXCIjYzJjMmMyXCIsXHJcbiAgICAgICAgc3Ryb2tlV2lkdGg6IDAuMjcsXHJcbiAgICAgIH0sXHJcbiAgICApO1xyXG5cclxuICAgIGNvbnN0IGZpcnN0Qm94VGV4dCA9IG5ldyBmYWJyaWMuVGV4dGJveChcclxuICAgICAgYCR7Zml4dHVyZURhdGE/LmhlYWRlcj8ubGFiZWwgPyBmaXh0dXJlRGF0YS5oZWFkZXIubGFiZWwgOiBcIlwifWAsXHJcbiAgICAgIHtcclxuICAgICAgICBsZWZ0OiBtaWRYICsgbWlkV2lkdGggLyAyLFxyXG4gICAgICAgIHRvcDogZmlyc3RCb3hZICsgYm94SGVpZ2h0IC8gMixcclxuICAgICAgICBmb250U2l6ZTogNyxcclxuICAgICAgICBmb250RmFtaWx5OiBcIkludGVyXCIsXHJcbiAgICAgICAgZm9udFdlaWdodDogXCI2MDBcIixcclxuICAgICAgICBmaWxsOiBcIiMxMDE4MjhcIixcclxuICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgd2lkdGg6IG1pZFdpZHRoLFxyXG4gICAgICAgIGhlaWdodDogYm94SGVpZ2h0LFxyXG4gICAgICAgIHRleHRBbGlnbjogXCJjZW50ZXJcIixcclxuICAgICAgfSxcclxuICAgICk7XHJcblxyXG4gICAgY29uc3Qgc2hlbHZlcyA9IFtdO1xyXG4gICAgY29uc3Qgc2hlbGZIZWlnaHQgPSBtaWRIZWlnaHQgLSAyICogYm94SGVpZ2h0O1xyXG5cclxuICAgIGlmIChmaXh0dXJlRGF0YS5wcm9kdWN0UmVzb2x1dGlvbkxldmVsID09PSBcIkwxXCIpIHtcclxuICAgICAgY29uc3QgYm94WSA9IGZpcnN0Qm94WSArIGJveEhlaWdodDtcclxuXHJcbiAgICAgIGNvbnN0IHNoZWxmID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgICBsZWZ0OiBtaWRYLFxyXG4gICAgICAgIHRvcDogYm94WSxcclxuICAgICAgICB3aWR0aDogbWlkV2lkdGgsXHJcbiAgICAgICAgaGVpZ2h0OiBzaGVsZkhlaWdodCxcclxuICAgICAgICBzdHJva2VXaWR0aDogMC4yNyxcclxuICAgICAgICBzdHJva2U6IGlzVGFyZ2V0Rml4dHVyZSA/IFwiIzUxQzFGRlwiIDogXCIjYzJjMmMyXCIsXHJcbiAgICAgICAgZmlsbDogXCIjZmZmZmZmXCIsXHJcbiAgICAgIH0pO1xyXG5cclxuICAgICAgY29uc3QgdGV4dCA9IGZpeHR1cmVEYXRhPy5wcm9kdWN0QnJhbmROYW1lPy5qb2luKFwiICsgXCIpIHx8IFwiXCI7XHJcblxyXG4gICAgICAvLyBXcmFwIHRleHQgd2l0aGluIGZpeHR1cmUgd2lkdGggYW5kIHNocmluayB0byBmaXQgdmVydGljYWwgc3BhY2VcclxuICAgICAgY29uc3QgbWF4VGV4dFdpZHRoID0gbWlkV2lkdGggKiAwLjk7XHJcbiAgICAgIGNvbnN0IG1heFRleHRIZWlnaHQgPSBzaGVsZkhlaWdodCAqIDAuODtcclxuICAgICAgbGV0IGZvbnRTaXplTDEgPSA2O1xyXG5cclxuICAgICAgY29uc3QgY3JlYXRlV3JhcHBlZFRleHRib3ggPSAoZnM6IG51bWJlcikgPT5cclxuICAgICAgICBuZXcgZmFicmljLlRleHRib3godGV4dCwge1xyXG4gICAgICAgICAgbGVmdDogbWlkWCArIG1pZFdpZHRoIC8gMixcclxuICAgICAgICAgIHRvcDogYm94WSArIHNoZWxmSGVpZ2h0IC8gMixcclxuICAgICAgICAgIG9yaWdpblg6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgd2lkdGg6IG1heFRleHRXaWR0aCxcclxuICAgICAgICAgIGZvbnRTaXplOiBmcyxcclxuICAgICAgICAgIGZvbnRGYW1pbHk6IFwiSW50ZXJcIixcclxuICAgICAgICAgIGZvbnRXZWlnaHQ6IFwiNTAwXCIsXHJcbiAgICAgICAgICB0ZXh0QWxpZ246IFwiY2VudGVyXCIsXHJcbiAgICAgICAgICBmaWxsOiBcIiMxRDI5MzlcIixcclxuICAgICAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgZXZlbnRlZDogZmFsc2UsXHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICBsZXQgd3JhcHBlZFRleHQgPSBjcmVhdGVXcmFwcGVkVGV4dGJveChmb250U2l6ZUwxKTtcclxuICAgICAgd2hpbGUgKHdyYXBwZWRUZXh0LmhlaWdodCA+IG1heFRleHRIZWlnaHQgJiYgZm9udFNpemVMMSA+IDIpIHtcclxuICAgICAgICBmb250U2l6ZUwxIC09IDAuNTtcclxuICAgICAgICB3cmFwcGVkVGV4dCA9IGNyZWF0ZVdyYXBwZWRUZXh0Ym94KGZvbnRTaXplTDEpO1xyXG4gICAgICB9XHJcbiAgICAgIHNoZWx2ZXMucHVzaChzaGVsZiwgd3JhcHBlZFRleHQpO1xyXG4gICAgfSBlbHNlIGlmIChmaXh0dXJlRGF0YS5wcm9kdWN0UmVzb2x1dGlvbkxldmVsID09PSBcIkwyXCIpIHtcclxuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzaGVsZkNvdW50OyBpKyspIHtcclxuICAgICAgICBjb25zdCBib3hZID0gZmlyc3RCb3hZICsgYm94SGVpZ2h0ICogKGkgKyAxKTtcclxuXHJcbiAgICAgICAgY29uc3Qgc2hlbGYgPSBuZXcgZmFicmljLlJlY3Qoe1xyXG4gICAgICAgICAgbGVmdDogbWlkWCxcclxuICAgICAgICAgIHRvcDogYm94WSxcclxuICAgICAgICAgIHdpZHRoOiBtaWRXaWR0aCxcclxuICAgICAgICAgIGhlaWdodDogYm94SGVpZ2h0LFxyXG4gICAgICAgICAgc3Ryb2tlV2lkdGg6IDAuMjcsXHJcbiAgICAgICAgICBzdHJva2U6IGlzVGFyZ2V0Rml4dHVyZSA/IFwiIzUxQzFGRlwiIDogXCIjYzJjMmMyXCIsXHJcbiAgICAgICAgICBmaWxsOiBcIiNmZmZmZmZcIixcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgc2hlbHZlcy5wdXNoKHNoZWxmKTtcclxuXHJcbiAgICAgICAgY29uc3QgdGV4dCA9XHJcbiAgICAgICAgICBmaXh0dXJlRGF0YS5zaGVsZkNvbmZpZz8uW2ldLnByb2R1Y3RCcmFuZE5hbWU/LmpvaW4oXCIgKyBcIikgfHwgXCJcIjtcclxuXHJcbiAgICAgICAgLy8gTDI6IFNpbmdsZS1saW5lIGVsbGlwc2lzIGFnYWluc3QgZnVsbCBzaGVsZiB3aWR0aFxyXG4gICAgICAgIGNvbnN0IGhvcml6b250YWxQYWRkaW5nID0gNjtcclxuICAgICAgICBjb25zdCBtYXhUZXh0V2lkdGggPSBNYXRoLm1heCgwLCBtaWRXaWR0aCAtIGhvcml6b250YWxQYWRkaW5nKTtcclxuICAgICAgICBjb25zdCBiYXNlRm9udFNpemUgPSA1O1xyXG5cclxuICAgICAgICBjb25zdCBtZWFzdXJlID0gKHQ6IHN0cmluZykgPT5cclxuICAgICAgICAgIG5ldyBmYWJyaWMuVGV4dCh0LCB7XHJcbiAgICAgICAgICAgIGZvbnRTaXplOiBiYXNlRm9udFNpemUsXHJcbiAgICAgICAgICAgIGZvbnRGYW1pbHk6IFwiSW50ZXJcIixcclxuICAgICAgICAgICAgZm9udFdlaWdodDogXCI1MDBcIixcclxuICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICBsZXQgZGlzcGxheVRleHQgPSB0ZXh0O1xyXG4gICAgICAgIGxldCBtZWFzdXJlZCA9IG1lYXN1cmUoZGlzcGxheVRleHQpO1xyXG5cclxuICAgICAgICBpZiAoKG1lYXN1cmVkLndpZHRoID8/IDApID4gbWF4VGV4dFdpZHRoKSB7XHJcbiAgICAgICAgICBjb25zdCBlbGxpcHNpcyA9IFwiLi4uXCI7XHJcbiAgICAgICAgICBsZXQgbGVmdElkeCA9IDA7XHJcbiAgICAgICAgICBsZXQgcmlnaHRJZHggPSB0ZXh0Lmxlbmd0aDtcclxuXHJcbiAgICAgICAgICB3aGlsZSAobGVmdElkeCA8IHJpZ2h0SWR4KSB7XHJcbiAgICAgICAgICAgIGNvbnN0IG1pZElkeCA9IE1hdGguZmxvb3IoKGxlZnRJZHggKyByaWdodElkeCkgLyAyKTtcclxuICAgICAgICAgICAgY29uc3QgY2FuZGlkYXRlID0gdGV4dC5zbGljZSgwLCBtaWRJZHgpICsgZWxsaXBzaXM7XHJcbiAgICAgICAgICAgIG1lYXN1cmVkID0gbWVhc3VyZShjYW5kaWRhdGUpO1xyXG4gICAgICAgICAgICBpZiAoKG1lYXN1cmVkLndpZHRoID8/IDApID4gbWF4VGV4dFdpZHRoKSB7XHJcbiAgICAgICAgICAgICAgcmlnaHRJZHggPSBtaWRJZHg7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgbGVmdElkeCA9IG1pZElkeCArIDE7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgIH1cclxuICAgICAgICAgIGRpc3BsYXlUZXh0ID0gdGV4dC5zbGljZSgwLCBNYXRoLm1heCgwLCBsZWZ0SWR4IC0gMSkpICsgZWxsaXBzaXM7XHJcbiAgICAgICAgICBtZWFzdXJlZCA9IG1lYXN1cmUoZGlzcGxheVRleHQpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgZmluYWxUZXh0ID0gbmV3IGZhYnJpYy5UZXh0KGRpc3BsYXlUZXh0LCB7XHJcbiAgICAgICAgICBsZWZ0OiBtaWRYICsgbWlkV2lkdGggLyAyLFxyXG4gICAgICAgICAgdG9wOiBib3hZICsgYm94SGVpZ2h0IC8gMixcclxuICAgICAgICAgIG9yaWdpblg6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgZm9udFNpemU6IGJhc2VGb250U2l6ZSxcclxuICAgICAgICAgIGZvbnRGYW1pbHk6IFwiSW50ZXJcIixcclxuICAgICAgICAgIGZvbnRXZWlnaHQ6IFwiNTAwXCIsXHJcbiAgICAgICAgICBmaWxsOiBcIiMxRDI5MzlcIixcclxuICAgICAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgZXZlbnRlZDogZmFsc2UsXHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHNoZWx2ZXMucHVzaChmaW5hbFRleHQpO1xyXG4gICAgICB9XHJcbiAgICB9IGVsc2UgaWYgKGZpeHR1cmVEYXRhLnByb2R1Y3RSZXNvbHV0aW9uTGV2ZWwgPT09IFwiTDNcIikge1xyXG4gICAgICBjb25zdCBzZXF1ZW50aWFsR3JvdXBzOiB7IHpvbmU6IHN0cmluZzsgc2hlbHZlczogYW55W10gfVtdID0gW107XHJcblxyXG4gICAgICBsZXQgcHJldmlvdXNab25lOiBzdHJpbmcgfCBudWxsID0gbnVsbDtcclxuXHJcbiAgICAgIGZvciAoY29uc3Qgc2hlbGYgb2YgZml4dHVyZURhdGEuc2hlbGZDb25maWcpIHtcclxuICAgICAgICBjb25zdCB6b25lID0gc2hlbGYuem9uZSB8fCBcIlVua25vd25cIjtcclxuICAgICAgICBpZiAoem9uZSAhPT0gcHJldmlvdXNab25lKSB7XHJcbiAgICAgICAgICBzZXF1ZW50aWFsR3JvdXBzLnB1c2goeyB6b25lLCBzaGVsdmVzOiBbc2hlbGZdIH0pO1xyXG4gICAgICAgICAgcHJldmlvdXNab25lID0gem9uZTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgc2VxdWVudGlhbEdyb3Vwc1tzZXF1ZW50aWFsR3JvdXBzLmxlbmd0aCAtIDFdLnNoZWx2ZXMucHVzaChzaGVsZik7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcblxyXG4gICAgICBsZXQgY3VycmVudFNoZWxmSW5kZXggPSAwO1xyXG5cclxuICAgICAgZm9yIChjb25zdCBncm91cCBvZiBzZXF1ZW50aWFsR3JvdXBzKSB7XHJcbiAgICAgICAgY29uc3QgeyBzaGVsdmVzOiBzaGVsdmVzSW5Hcm91cCB9ID0gZ3JvdXA7XHJcblxyXG4gICAgICAgIGNvbnN0IGdyb3VwU3RhcnRJbmRleCA9IGN1cnJlbnRTaGVsZkluZGV4O1xyXG4gICAgICAgIGNvbnN0IGdyb3VwTGVuZ3RoID0gc2hlbHZlc0luR3JvdXAubGVuZ3RoO1xyXG5cclxuICAgICAgICBjb25zdCBncm91cFRvcFkgPSBmaXJzdEJveFkgKyBib3hIZWlnaHQgKiAoZ3JvdXBTdGFydEluZGV4ICsgMSk7XHJcbiAgICAgICAgY29uc3QgZ3JvdXBCb3R0b21ZID0gZ3JvdXBUb3BZICsgYm94SGVpZ2h0ICogZ3JvdXBMZW5ndGg7XHJcblxyXG4gICAgICAgIGNvbnN0IGlzVGFyZ2V0Wm9uZSA9IHNoZWx2ZXNJbkdyb3VwLnNvbWUoXHJcbiAgICAgICAgICAoczogYW55KSA9PiBzLl9pZCA9PT0gdGhpcy5zZWxlY3RlZFByb2R1Y3Q/LmZpeHR1cmVEZXRhaWxzPy5zaGVsZklkLFxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgc2hlbHZlc0luR3JvdXAubGVuZ3RoOyBqKyspIHtcclxuICAgICAgICAgIGNvbnN0IGJveFkgPSBmaXJzdEJveFkgKyBib3hIZWlnaHQgKiAoY3VycmVudFNoZWxmSW5kZXggKyAxKTtcclxuXHJcbiAgICAgICAgICBjb25zdCBpc0ZpcnN0ID0gaiA9PT0gMDtcclxuICAgICAgICAgIGNvbnN0IGlzTGFzdCA9IGogPT09IHNoZWx2ZXNJbkdyb3VwLmxlbmd0aCAtIDE7XHJcblxyXG4gICAgICAgICAgY29uc3QgZmlsbENvbG9yID0gaXNUYXJnZXRab25lID8gXCIjZmVmM2YyXCIgOiBcIiNmOWZiZmZcIjtcclxuICAgICAgICAgIGNvbnN0IGJvcmRlckNvbG9yID0gaXNUYXJnZXRab25lID8gXCIjZmZhM2EzXCIgOiBcIiNjMmMyYzJcIjtcclxuXHJcbiAgICAgICAgICBjb25zdCBwYXRoRGF0YSA9IFtcclxuICAgICAgICAgICAgYE0gJHttaWRYfSAke2JveFl9IEwgJHttaWRYfSAke2JveFkgKyBib3hIZWlnaHR9YCxcclxuICAgICAgICAgICAgYE0gJHttaWRYICsgbWlkV2lkdGh9ICR7Ym94WX0gTCAke21pZFggKyBtaWRXaWR0aH0gJHtcclxuICAgICAgICAgICAgICBib3hZICsgYm94SGVpZ2h0XHJcbiAgICAgICAgICAgIH1gLFxyXG4gICAgICAgICAgICBpc0ZpcnN0ID8gYE0gJHttaWRYfSAke2JveFl9IEwgJHttaWRYICsgbWlkV2lkdGh9ICR7Ym94WX1gIDogXCJcIixcclxuICAgICAgICAgICAgaXNMYXN0XHJcbiAgICAgICAgICAgICAgPyBgTSAke21pZFh9ICR7Ym94WSArIGJveEhlaWdodH0gTCAke21pZFggKyBtaWRXaWR0aH0gJHtcclxuICAgICAgICAgICAgICAgICAgYm94WSArIGJveEhlaWdodFxyXG4gICAgICAgICAgICAgICAgfWBcclxuICAgICAgICAgICAgICA6IFwiXCIsXHJcbiAgICAgICAgICBdLmpvaW4oXCIgXCIpO1xyXG5cclxuICAgICAgICAgIGNvbnN0IGZpbGxSZWN0ID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgICAgICAgbGVmdDogbWlkWCxcclxuICAgICAgICAgICAgdG9wOiBib3hZLFxyXG4gICAgICAgICAgICB3aWR0aDogbWlkV2lkdGgsXHJcbiAgICAgICAgICAgIGhlaWdodDogYm94SGVpZ2h0LFxyXG4gICAgICAgICAgICBmaWxsOiBmaWxsQ29sb3IsXHJcbiAgICAgICAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgICAgICAgICBldmVudGVkOiBmYWxzZSxcclxuICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgIGNvbnN0IGJvcmRlclBhdGggPSBuZXcgZmFicmljLlBhdGgocGF0aERhdGEsIHtcclxuICAgICAgICAgICAgc3Ryb2tlOiBib3JkZXJDb2xvcixcclxuICAgICAgICAgICAgc3Ryb2tlV2lkdGg6IDAuNyxcclxuICAgICAgICAgICAgZmlsbDogXCJcIixcclxuICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgIGV2ZW50ZWQ6IGZhbHNlLFxyXG4gICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgc2hlbHZlcy5wdXNoKGZpbGxSZWN0LCBib3JkZXJQYXRoKTtcclxuXHJcbiAgICAgICAgICBjdXJyZW50U2hlbGZJbmRleCsrO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgZ3JvdXBCb3R0b21MaW5lID0gbmV3IGZhYnJpYy5MaW5lKFxyXG4gICAgICAgICAgW21pZFgsIGdyb3VwQm90dG9tWSwgbWlkWCArIG1pZFdpZHRoLCBncm91cEJvdHRvbVldLFxyXG4gICAgICAgICAge1xyXG4gICAgICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICAgICAgZXZlbnRlZDogZmFsc2UsXHJcbiAgICAgICAgICB9LFxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIHNoZWx2ZXMucHVzaChncm91cEJvdHRvbUxpbmUpO1xyXG5cclxuICAgICAgICBjb25zdCBncm91cENlbnRlclggPSBtaWRYICsgbWlkV2lkdGggLyAyO1xyXG4gICAgICAgIGNvbnN0IGdyb3VwQ2VudGVyWSA9IGdyb3VwVG9wWSArIChncm91cEJvdHRvbVkgLSBncm91cFRvcFkpIC8gMjtcclxuXHJcbiAgICAgICAgY29uc3Qgc2VjdGlvbkJyYW5kcyA9IG5ldyBTZXQoKTtcclxuXHJcbiAgICAgICAgc2hlbHZlc0luR3JvdXA/LmZvckVhY2goKHNoZWxmKSA9PiB7XHJcbiAgICAgICAgICBzaGVsZi5wcm9kdWN0QnJhbmROYW1lPy5mb3JFYWNoKChicmFuZDogc3RyaW5nKSA9PiB7XHJcbiAgICAgICAgICAgIHNlY3Rpb25CcmFuZHMuYWRkKGJyYW5kKTtcclxuICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICBpZiAoWy4uLnNlY3Rpb25CcmFuZHNdLmxlbmd0aCkge1xyXG4gICAgICAgICAgY29uc3QgdGV4dCA9IFsuLi5zZWN0aW9uQnJhbmRzXS5qb2luKFwiICsgXCIpO1xyXG4gICAgICAgICAgY29uc3QgcGFkZGluZyA9IDI7XHJcbiAgICAgICAgICBjb25zdCBtYXhUZXh0V2lkdGggPSBtaWRXaWR0aDtcclxuICAgICAgICAgIGNvbnN0IHJlY3RXaWR0aCA9IG1pZFdpZHRoICogMC45O1xyXG4gICAgICAgICAgY29uc3QgbWF4VGV4dEhlaWdodCA9IDIwO1xyXG5cclxuICAgICAgICAgIGxldCBmb250U2l6ZSA9IDY7XHJcbiAgICAgICAgICBsZXQgd3JhcHBlZFRleHQ7XHJcblxyXG4gICAgICAgICAgY29uc3QgY3JlYXRlVGV4dGJveCA9IChmczogYW55KSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiBuZXcgZmFicmljLlRleHRib3godGV4dCwge1xyXG4gICAgICAgICAgICAgIGZvbnRTaXplOiBmcyxcclxuICAgICAgICAgICAgICBmb250RmFtaWx5OiBcIkludGVyXCIsXHJcbiAgICAgICAgICAgICAgZm9udFdlaWdodDogXCI0MDBcIixcclxuICAgICAgICAgICAgICB3aWR0aDogbWF4VGV4dFdpZHRoLFxyXG4gICAgICAgICAgICAgIHRleHRBbGlnbjogXCJjZW50ZXJcIixcclxuICAgICAgICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgICAgICAgZmlsbDogXCIjMUQyOTM5XCIsXHJcbiAgICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgICAgZXZlbnRlZDogZmFsc2UsXHJcbiAgICAgICAgICAgICAgbGVmdDogZ3JvdXBDZW50ZXJYLFxyXG4gICAgICAgICAgICAgIHRvcDogZ3JvdXBDZW50ZXJZLFxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgZG8ge1xyXG4gICAgICAgICAgICB3cmFwcGVkVGV4dCA9IGNyZWF0ZVRleHRib3goZm9udFNpemUpO1xyXG4gICAgICAgICAgICBmb250U2l6ZSAtPSAwLjU7XHJcbiAgICAgICAgICB9IHdoaWxlICh3cmFwcGVkVGV4dC5oZWlnaHQgPiBtYXhUZXh0SGVpZ2h0ICYmIGZvbnRTaXplID4gMik7XHJcblxyXG4gICAgICAgICAgY29uc3QgcmVjdEhlaWdodCA9IHdyYXBwZWRUZXh0LmdldFNjYWxlZEhlaWdodCgpICsgcGFkZGluZztcclxuXHJcbiAgICAgICAgICBjb25zdCBncm91cENlbnRlclRleHQgPSBuZXcgZmFicmljLlJlY3Qoe1xyXG4gICAgICAgICAgICBsZWZ0OiBncm91cENlbnRlclgsXHJcbiAgICAgICAgICAgIHRvcDogZ3JvdXBDZW50ZXJZLFxyXG4gICAgICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICAgICAgICB3aWR0aDogcmVjdFdpZHRoLFxyXG4gICAgICAgICAgICBoZWlnaHQ6IHJlY3RIZWlnaHQsXHJcbiAgICAgICAgICAgIGZpbGw6IFwidHJhbnNwYXJlbnRcIixcclxuICAgICAgICAgICAgc2VsZWN0YWJsZTogZmFsc2UsXHJcbiAgICAgICAgICAgIGV2ZW50ZWQ6IGZhbHNlLFxyXG4gICAgICAgICAgICByeDogMSxcclxuICAgICAgICAgICAgcnk6IDEsXHJcbiAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICBzaGVsdmVzLnB1c2goZ3JvdXBDZW50ZXJUZXh0LCB3cmFwcGVkVGV4dCk7XHJcbiAgICAgICAgfVxyXG4gICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgY29uc3QgbGFzdEJveFkgPSBmaXJzdEJveFkgKyBib3hIZWlnaHQgKiAoc2hlbGZDb3VudCArIDEpO1xyXG4gICAgY29uc3QgbGFzdEJveCA9IG5ldyBmYWJyaWMuUGF0aChcclxuICAgICAgYE0gJHttaWRYfSAke2xhc3RCb3hZfSBcclxuICAgICAgICBMICR7bWlkWCArIG1pZFdpZHRofSAke2xhc3RCb3hZfSBcclxuICAgICAgICBMICR7bWlkWCArIG1pZFdpZHRofSAke2xhc3RCb3hZICsgYm94SGVpZ2h0IC0gcmFkaXVzfSBcclxuICAgICAgICBRICR7bWlkWCArIG1pZFdpZHRofSAke2xhc3RCb3hZICsgYm94SGVpZ2h0fSAke1xyXG4gICAgICAgICAgbWlkWCArIG1pZFdpZHRoIC0gcmFkaXVzXHJcbiAgICAgICAgfSAke2xhc3RCb3hZICsgYm94SGVpZ2h0fSBcclxuICAgICAgICBMICR7bWlkWCArIHJhZGl1c30gJHtsYXN0Qm94WSArIGJveEhlaWdodH0gXHJcbiAgICAgICAgUSAke21pZFh9ICR7bGFzdEJveFkgKyBib3hIZWlnaHR9ICR7bWlkWH0gJHtcclxuICAgICAgICAgIGxhc3RCb3hZICsgYm94SGVpZ2h0IC0gcmFkaXVzXHJcbiAgICAgICAgfSBcclxuICAgICAgICBMICR7bWlkWH0gJHtsYXN0Qm94WX0gWmAsXHJcbiAgICAgIHtcclxuICAgICAgICBmaWxsOiBpc1RhcmdldEZpeHR1cmUgPyBcIiNFQUY4RkZcIiA6IFwiI2Y5ZmJmZlwiLFxyXG4gICAgICAgIHN0cm9rZTogaXNUYXJnZXRGaXh0dXJlID8gXCIjNkJDQUZGXCIgOiBcIiNjMmMyYzJcIixcclxuICAgICAgICBzdHJva2VXaWR0aDogMC4yNyxcclxuICAgICAgfSxcclxuICAgICk7XHJcblxyXG4gICAgY29uc3QgbGFzdEJveFRleHQgPSBuZXcgZmFicmljLlRleHRib3goXHJcbiAgICAgIGAke2ZpeHR1cmVEYXRhPy5mb290ZXI/LmxhYmVsID8gZml4dHVyZURhdGEuZm9vdGVyLmxhYmVsIDogXCJcIn1gLFxyXG4gICAgICB7XHJcbiAgICAgICAgbGVmdDogbWlkWCArIG1pZFdpZHRoIC8gMixcclxuICAgICAgICB0b3A6IGxhc3RCb3hZICsgYm94SGVpZ2h0IC8gMixcclxuICAgICAgICBmb250U2l6ZTogNSxcclxuICAgICAgICBmb250RmFtaWx5OiBcIkludGVyXCIsXHJcbiAgICAgICAgZm9udFdlaWdodDogXCI2MDBcIixcclxuICAgICAgICBmaWxsOiBcIiMxMDE4MjhcIixcclxuICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgdGV4dEFsaWduOiBcImNlbnRlclwiLFxyXG4gICAgICAgIHdpZHRoOiBtaWRXaWR0aCxcclxuICAgICAgICBoZWlndGg6IGJveEhlaWdodCxcclxuICAgICAgfSxcclxuICAgICk7XHJcblxyXG4gICAgY29uc3QgYm90dG9tV2lkdGggPSB3aWR0aCAvIDEuMDU7XHJcbiAgICBjb25zdCBib3R0b21IZWlnaHQgPSAoMyAvIDEwMCkgKiBoZWlnaHQ7XHJcbiAgICBjb25zdCBib3R0b21YID0geCArICh3aWR0aCAtIGJvdHRvbVdpZHRoKSAvIDI7XHJcbiAgICBjb25zdCBib3R0b21ZID0gbWlkWSArIG1pZEhlaWdodCArIHRoaXMudmVydGljYWxNYXJnaW47XHJcblxyXG4gICAgY29uc3QgYm90dG9tQ29udGFpbmVyID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgbGVmdDogYm90dG9tWCxcclxuICAgICAgdG9wOiBib3R0b21ZLFxyXG4gICAgICB3aWR0aDogYm90dG9tV2lkdGgsXHJcbiAgICAgIGhlaWdodDogYm90dG9tSGVpZ2h0LFxyXG4gICAgICByeDogcmFkaXVzLFxyXG4gICAgICByeTogcmFkaXVzLFxyXG4gICAgICBzdHJva2U6IFwidHJhbnNwYXJlbnRcIixcclxuICAgICAgZmlsbDogXCJ0cmFuc3BhcmVudFwiLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgYWN0dWFsU2hlbGZDb3VudCA9XHJcbiAgICAgIGZpeHR1cmVEYXRhPy5zaGVsZkNvbmZpZz8uZmlsdGVyKChzOiBhbnkpID0+IHMuc2hlbGZUeXBlICE9IFwidm1vbmx5XCIpXHJcbiAgICAgICAgPy5sZW5ndGggPz8gMDtcclxuXHJcbiAgICBjb25zdCBib3R0b21UZXh0Q29udGVudCA9IG5ldyBmYWJyaWMuVGV4dGJveChcclxuICAgICAgYFNoZWx2ZXMgLSAke2FjdHVhbFNoZWxmQ291bnR9IC4gUHJvZHVjdHMgLSAgJHtmaXh0dXJlRGF0YS5maXh0dXJlQ2FwYWNpdHl9IC4gVk0gLSAke2ZpeHR1cmVEYXRhLnZtQ29uZmlnPy5sZW5ndGh9YCxcclxuICAgICAge1xyXG4gICAgICAgIGxlZnQ6IGJvdHRvbVggKyBib3R0b21XaWR0aCAvIDIsXHJcbiAgICAgICAgdG9wOiBib3R0b21ZICsgYm90dG9tSGVpZ2h0IC8gMixcclxuICAgICAgICBmb250U2l6ZTogNSxcclxuICAgICAgICBmb250RmFtaWx5OiBcIkludGVyXCIsXHJcbiAgICAgICAgZm9udFdlaWdodDogXCI1MDBcIixcclxuICAgICAgICBmaWxsOiBcIiMzMzNcIixcclxuICAgICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICAgICAgdGV4dEFsaWduOiBcImNlbnRlclwiLFxyXG4gICAgICAgIHdpZHRoOiBib3R0b21XaWR0aCxcclxuICAgICAgICBoZWlnaHQ6IGJvdHRvbUhlaWdodCxcclxuICAgICAgfSxcclxuICAgICk7XHJcblxyXG4gICAgY29uc3QgZml4dHVyZUdyb3VwID0gbmV3IGZhYnJpYy5Hcm91cChcclxuICAgICAgW1xyXG4gICAgICAgIG1haW5Db250YWluZXIsXHJcbiAgICAgICAgdG9wQ29udGFpbmVyLFxyXG4gICAgICAgIGlubmVyVG9wQm94LFxyXG4gICAgICAgIHRvcFRleHQsXHJcbiAgICAgICAgaW5uZXJCb3R0b21Cb3gsXHJcbiAgICAgICAgYm90dG9tVGV4dCxcclxuICAgICAgICBtaWRDb250YWluZXIsXHJcbiAgICAgICAgZmlyc3RCb3gsXHJcbiAgICAgICAgZmlyc3RCb3hUZXh0LFxyXG4gICAgICAgIC4uLnNoZWx2ZXMsXHJcbiAgICAgICAgbGFzdEJveCxcclxuICAgICAgICBsYXN0Qm94VGV4dCxcclxuICAgICAgICBib3R0b21Db250YWluZXIsXHJcbiAgICAgICAgYm90dG9tVGV4dENvbnRlbnQsXHJcbiAgICAgIF0sXHJcbiAgICAgIHtcclxuICAgICAgICBsZWZ0OiB4LFxyXG4gICAgICAgIHRvcDogeSxcclxuICAgICAgICBldmVudGVkOiB0cnVlLFxyXG4gICAgICAgIC8vIGhvdmVyQ3Vyc29yOiBcInBvaW50ZXJcIixcclxuICAgICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgICBsb2NrU2NhbGluZ1g6IHRydWUsXHJcbiAgICAgICAgbG9ja1NjYWxpbmdZOiB0cnVlLFxyXG4gICAgICAgIHN1YlRhcmdldENoZWNrOiB0cnVlLFxyXG4gICAgICAgIGhhc0NvbnRyb2xzOiBmYWxzZSxcclxuICAgICAgICBsb2NrUm90YXRpb246IHRydWUsXHJcbiAgICAgICAgbG9ja01vdmVtZW50WDogdHJ1ZSxcclxuICAgICAgICBsb2NrTW92ZW1lbnRZOiB0cnVlLFxyXG4gICAgICAgIGFuZ2xlOiBmaXh0dXJlRGF0YS5yZWxhdGl2ZVBvc2l0aW9uPy5hbmdsZSA/PyAwLFxyXG4gICAgICB9LFxyXG4gICAgKSBhcyBmYWJyaWMuR3JvdXAgJiB7XHJcbiAgICAgIHdhbGxJbmRleDogbnVtYmVyO1xyXG4gICAgICBmaXh0dXJlSW5kZXg6IG51bWJlcjtcclxuICAgICAgZml4dHVyZUlkOiBzdHJpbmc7XHJcbiAgICAgIGZpeHR1cmVUeXBlOiBcIndhbGxcIiB8IFwiZmxvb3JcIjtcclxuICAgICAgaXNzdWU6IGJvb2xlYW47XHJcbiAgICAgIGlzc3VlRGF0YTogYW55O1xyXG4gICAgICB0YXNrVHlwZTogc3RyaW5nO1xyXG4gICAgICB2bUNvbmZpZzogW107XHJcbiAgICAgIG9ialR5cGU6IHN0cmluZztcclxuICAgIH07XHJcblxyXG4gICAgLy8gZml4dHVyZUdyb3VwLm9uKFwibW91c2Vkb3duXCIsIChldmVudDogYW55KSA9PiB7XHJcbiAgICAvLyAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldDtcclxuICAgIC8vICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAvLyAgICAgdGhpcy5yZXNpemVDYW52YXMoKTtcclxuICAgIC8vICAgICB0aGlzLmZpdENhbnZhc1RvTGF5b3V0QW5pbWF0ZWQoKTtcclxuICAgIC8vICAgfSwgMzAwKTtcclxuICAgIC8vICAgdGhpcy5oaWdobGlnaHRGaXh0dXJlKHRhcmdldCk7XHJcbiAgICAvLyAgIHRoaXMuc2VsZWN0Rml4dHVyZSh0YXJnZXQpO1xyXG4gICAgLy8gfSk7XHJcblxyXG4gICAgZml4dHVyZUdyb3VwLmZpeHR1cmVUeXBlID0gZml4dHVyZURhdGEuZml4dHVyZVR5cGU7XHJcbiAgICBmaXh0dXJlR3JvdXAud2FsbEluZGV4ID0gZml4dHVyZURhdGEuYXNzb2NpYXRlZEVsZW1lbnROdW1iZXI7XHJcbiAgICBmaXh0dXJlR3JvdXAuZml4dHVyZUluZGV4ID0gZml4dHVyZURhdGEuYXNzb2NpYXRlZEVsZW1lbnRGaXh0dXJlTnVtYmVyO1xyXG4gICAgZml4dHVyZUdyb3VwLmZpeHR1cmVJZCA9IGZpeHR1cmVEYXRhLl9pZDtcclxuICAgIGZpeHR1cmVHcm91cC5pc3N1ZSA9IGZpeHR1cmVEYXRhLmlzc3VlO1xyXG4gICAgZml4dHVyZUdyb3VwLmlzc3VlRGF0YSA9IGZpeHR1cmVEYXRhLmlzc3VlRGF0YTtcclxuICAgIGZpeHR1cmVHcm91cC50YXNrVHlwZSA9IGZpeHR1cmVEYXRhLnRhc2tUeXBlO1xyXG4gICAgZml4dHVyZUdyb3VwLnZtQ29uZmlnID0gZml4dHVyZURhdGEudm1Db25maWc7XHJcbiAgICBmaXh0dXJlR3JvdXAub2JqVHlwZSA9IFwiZml4dHVyZVwiO1xyXG5cclxuICAgIGNhbnZhcy5hZGQoZml4dHVyZUdyb3VwKTtcclxuXHJcbiAgICByZXR1cm4gZml4dHVyZUdyb3VwO1xyXG4gIH1cclxuXHJcbiAgc2VsZWN0Rml4dHVyZSh0YXJnZXQ6IGFueSkge1xyXG4gICAgaWYgKHRhcmdldCkge1xyXG4gICAgICB0aGlzLnNlbGVjdGVkRml4dHVyZSA9IHtcclxuICAgICAgICBmaXh0dXJlVHlwZTogdGFyZ2V0LmZpeHR1cmVUeXBlLFxyXG4gICAgICAgIHdhbGxJbmRleDogdGFyZ2V0LndhbGxJbmRleCxcclxuICAgICAgICBmaXh0dXJlSW5kZXg6IHRhcmdldC5maXh0dXJlSW5kZXgsXHJcbiAgICAgICAgZml4dHVyZUlkOiB0YXJnZXQuZml4dHVyZUlkLFxyXG4gICAgICAgIGlzc3VlOiB0YXJnZXQuaXNzdWUsXHJcbiAgICAgICAgaXNzdWVEYXRhOiB0YXJnZXQuaXNzdWVEYXRhLFxyXG4gICAgICAgIHRhc2tUeXBlOiB0YXJnZXQudGFza1R5cGUsXHJcbiAgICAgIH07XHJcblxyXG4gICAgICBpZiAodGhpcy5zZWxlY3RlZEZpeHR1cmUuZml4dHVyZVR5cGUgPT09IFwid2FsbFwiKSB7XHJcbiAgICAgICAgY29uc3Qgd2FsbCA9IHRoaXMuZmxvb3JEYXRhLmxheW91dFBvbHlnb24uZmluZChcclxuICAgICAgICAgICh3YWxsOiBhbnkpID0+IHdhbGwuZWxlbWVudE51bWJlciA9PT0gdGhpcy5zZWxlY3RlZEZpeHR1cmUud2FsbEluZGV4LFxyXG4gICAgICAgICk7XHJcbiAgICAgICAgY29uc3QgZml4dHVyZSA9IHdhbGwuZml4dHVyZXMuZmluZChcclxuICAgICAgICAgIChmaXh0dXJlOiBhbnkpID0+IGZpeHR1cmUuX2lkID09PSB0aGlzLnNlbGVjdGVkRml4dHVyZS5maXh0dXJlSWQsXHJcbiAgICAgICAgKTtcclxuICAgICAgICB0aGlzLnNlbGVjdGVkRml4dHVyZURhdGEgPSBmaXh0dXJlO1xyXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YVtcInJldmlzaW9uSWRcIl0gPSB0aGlzLmZsb29yRGF0YS5yZXZpc2lvbklkO1xyXG4gICAgICB9IGVsc2UgaWYgKHRoaXMuc2VsZWN0ZWRGaXh0dXJlLmZpeHR1cmVUeXBlID09PSBcImZsb29yXCIpIHtcclxuICAgICAgICBjb25zdCBmaXh0dXJlID0gdGhpcy5mbG9vckRhdGEuY2VudGVyRml4dHVyZS5maW5kKFxyXG4gICAgICAgICAgKGZpeHR1cmU6IGFueSkgPT4gZml4dHVyZS5faWQgPT09IHRoaXMuc2VsZWN0ZWRGaXh0dXJlLmZpeHR1cmVJZCxcclxuICAgICAgICApO1xyXG4gICAgICAgIHRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YSA9IGZpeHR1cmU7XHJcbiAgICAgICAgdGhpcy5zZWxlY3RlZEZpeHR1cmVEYXRhW1wicmV2aXNpb25JZFwiXSA9IHRoaXMuZmxvb3JEYXRhLnJldmlzaW9uSWQ7XHJcbiAgICAgIH1cclxuICAgICAgaWYgKHRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YT8uaGVhZGVyPy5sYWJlbCAhPSBcIkNMXCIpIHtcclxuICAgICAgICB0aGlzLnNlbGVjdGVkRml4dHVyZS5maXh0dXJlRGF0YSA9IHRoaXMuc2VsZWN0ZWRGaXh0dXJlRGF0YTtcclxuICAgICAgfSBlbHNlIHtcclxuICAgICAgICB0aGlzLnNlbGVjdGVkRml4dHVyZS5maXh0dXJlRGF0YSA9IG51bGw7XHJcbiAgICAgIH1cclxuICAgIH1cclxuICB9XHJcblxyXG4gIGRyYXdMYWJlbGVkUmVjdGFuZ2xlKFxyXG4gICAgY2FudmFzOiBmYWJyaWMuQ2FudmFzLFxyXG4gICAgeDogbnVtYmVyLFxyXG4gICAgeTogbnVtYmVyLFxyXG4gICAgd2lkdGg6IG51bWJlcixcclxuICAgIGhlaWdodDogbnVtYmVyLFxyXG4gICAgZWxlbWVudDogYW55LFxyXG4gICk6IGZhYnJpYy5Hcm91cCB7XHJcbiAgICBjb25zdCByZWN0ID0gbmV3IGZhYnJpYy5SZWN0KHtcclxuICAgICAgd2lkdGgsXHJcbiAgICAgIGhlaWdodCxcclxuICAgICAgcng6IDIsXHJcbiAgICAgIHJ5OiAyLFxyXG4gICAgICBmaWxsOiBcIiNEQUYxRkZcIixcclxuICAgICAgc3Ryb2tlOiBcIiM2QkNBRkZcIixcclxuICAgICAgc3Ryb2tlV2lkdGg6IDIsXHJcbiAgICAgIG9yaWdpblg6IFwiY2VudGVyXCIsXHJcbiAgICAgIG9yaWdpblk6IFwiY2VudGVyXCIsXHJcbiAgICB9KTtcclxuXHJcbiAgICBjb25zdCB0ZXh0ID0gbmV3IGZhYnJpYy5UZXh0Ym94KGVsZW1lbnQuZml4dHVyZU5hbWUsIHtcclxuICAgICAgd2lkdGg6IHdpZHRoIC0gOCxcclxuICAgICAgZm9udFNpemU6IDE0LFxyXG4gICAgICBmb250RmFtaWx5OiBcIkludGVyXCIsXHJcbiAgICAgIGZvbnRXZWlnaHQ6IFwiNTAwXCIsXHJcbiAgICAgIGZpbGw6IFwiIzEwMTgyOFwiLFxyXG4gICAgICBvcmlnaW5YOiBcImNlbnRlclwiLFxyXG4gICAgICBvcmlnaW5ZOiBcImNlbnRlclwiLFxyXG4gICAgICB0ZXh0QWxpZ246IFwiY2VudGVyXCIsXHJcbiAgICAgIGVkaXRhYmxlOiBmYWxzZSxcclxuICAgICAgc3BsaXRCeUdyYXBoZW1lOiB0cnVlLFxyXG4gICAgfSk7XHJcblxyXG4gICAgY29uc3QgdGV4dEJvdW5kcyA9IHRleHQuZ2V0Qm91bmRpbmdSZWN0KCk7XHJcblxyXG4gICAgaWYgKHRleHRCb3VuZHMuaGVpZ2h0ID4gaGVpZ2h0IC0gOCkge1xyXG4gICAgICBjb25zdCBzY2FsZSA9IChoZWlnaHQgLSA4KSAvIHRleHRCb3VuZHMuaGVpZ2h0O1xyXG4gICAgICB0ZXh0LnNldChcImZvbnRTaXplXCIsIHRleHQuZm9udFNpemUhICogc2NhbGUpO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGdyb3VwID0gbmV3IGZhYnJpYy5Hcm91cChbcmVjdCwgdGV4dF0sIHtcclxuICAgICAgbGVmdDogeCxcclxuICAgICAgdG9wOiB5LFxyXG4gICAgICBhbmdsZTogZWxlbWVudC5yZWxhdGl2ZVBvc2l0aW9uLmFuZ2xlLFxyXG4gICAgICBzZWxlY3RhYmxlOiBmYWxzZSxcclxuICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgb3JpZ2luWTogXCJjZW50ZXJcIixcclxuICAgIH0pIGFzIGZhYnJpYy5Hcm91cCAmIHtcclxuICAgICAgb2JqVHlwZTogc3RyaW5nO1xyXG4gICAgICBkYXRhOiBhbnk7XHJcbiAgICB9O1xyXG5cclxuICAgIGdyb3VwLm9ialR5cGUgPSBcIm90aGVyc1wiO1xyXG4gICAgZ3JvdXAuZGF0YSA9IGVsZW1lbnQ7XHJcblxyXG4gICAgY2FudmFzLmFkZChncm91cCk7XHJcblxyXG4gICAgcmV0dXJuIGdyb3VwO1xyXG4gIH1cclxuXHJcbiAgdG9QaXhlbHModmFsdWU6IG51bWJlciwgdW5pdDogc3RyaW5nLCBkcGkgPSAyLjgpIHtcclxuICAgIGxldCBwaXhlbHM6IG51bWJlcjtcclxuXHJcbiAgICBpZiAodW5pdCA9PT0gXCJtbVwiKSB7XHJcbiAgICAgIHBpeGVscyA9ICh2YWx1ZSAvIDI1LjQpICogZHBpO1xyXG4gICAgfSBlbHNlIGlmICh1bml0ID09PSBcImZ0XCIpIHtcclxuICAgICAgcGl4ZWxzID0gdmFsdWUgKiAxMiAqIGRwaTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIlVuc3VwcG9ydGVkIHVuaXQuIFVzZSAnbW0nIG9yICdmdCcuXCIpO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBOdW1iZXIocGl4ZWxzLnRvRml4ZWQoMikpO1xyXG4gIH1cclxuXHJcbiAgY2FsY01lcmNoQ29tcGxpYW5jZVBlcmNlbnRhZ2UoKSB7XHJcbiAgICBjb25zdCBhbGxGaXh0dXJlcyA9IFtcclxuICAgICAgLi4udGhpcy5mbG9vckRhdGE/LmxheW91dFBvbHlnb24uZmxhdE1hcCgoZTogYW55KSA9PiBlLmZpeHR1cmVzKSxcclxuICAgICAgLi4udGhpcy5mbG9vckRhdGE/LmNlbnRlckZpeHR1cmUsXHJcbiAgICBdO1xyXG5cclxuICAgIGNvbnN0IGFsbFNoZWx2ZXMgPSBhbGxGaXh0dXJlcy5mbGF0TWFwKChmOiBhbnkpID0+IGYuc2hlbGZDb25maWcpO1xyXG5cclxuICAgIGNvbnN0IGNvbXBsaWFuY2VzID0gYWxsU2hlbHZlcy5tYXAoKHM6IGFueSkgPT4gcz8uY29tcGxpYW5jZSk7XHJcblxyXG4gICAgY29uc3QgdG90YWwgPSBjb21wbGlhbmNlcy5sZW5ndGg7XHJcbiAgICBjb25zdCBwcm9wZXJDb3VudCA9IGNvbXBsaWFuY2VzLmZpbHRlcigocCkgPT4gcCA9PT0gXCJwcm9wZXJcIikubGVuZ3RoO1xyXG4gICAgY29uc3Qgc3VjY2Vzc1BlcmNlbnRhZ2UgPSAocHJvcGVyQ291bnQgLyB0b3RhbCkgKiAxMDA7XHJcblxyXG4gICAgcmV0dXJuIE1hdGgucm91bmQoc3VjY2Vzc1BlcmNlbnRhZ2UpO1xyXG4gIH1cclxuXHJcbiAgcHJpdmF0ZSBnZXRGdWxsTGF5b3V0Qm91bmRzKCkge1xyXG4gICAgY29uc3Qgb2JqZWN0cyA9IHRoaXMuY2FudmFzLmdldE9iamVjdHMoKTtcclxuICAgIGlmICghb2JqZWN0cy5sZW5ndGgpIHJldHVybiB7IGxlZnQ6IDAsIHRvcDogMCwgd2lkdGg6IDAsIGhlaWdodDogMCB9O1xyXG5cclxuICAgIGxldCBtaW5YID0gSW5maW5pdHksXHJcbiAgICAgIG1pblkgPSBJbmZpbml0eSxcclxuICAgICAgbWF4WCA9IC1JbmZpbml0eSxcclxuICAgICAgbWF4WSA9IC1JbmZpbml0eTtcclxuXHJcbiAgICBmb3IgKGNvbnN0IG9iaiBvZiBvYmplY3RzKSB7XHJcbiAgICAgIGNvbnN0IHJlY3QgPSBvYmouZ2V0Qm91bmRpbmdSZWN0KCk7XHJcbiAgICAgIG1pblggPSBNYXRoLm1pbihtaW5YLCByZWN0LmxlZnQpO1xyXG4gICAgICBtaW5ZID0gTWF0aC5taW4obWluWSwgcmVjdC50b3ApO1xyXG4gICAgICBtYXhYID0gTWF0aC5tYXgobWF4WCwgcmVjdC5sZWZ0ICsgcmVjdC53aWR0aCk7XHJcbiAgICAgIG1heFkgPSBNYXRoLm1heChtYXhZLCByZWN0LnRvcCArIHJlY3QuaGVpZ2h0KTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4ge1xyXG4gICAgICBsZWZ0OiBtaW5YLFxyXG4gICAgICB0b3A6IG1pblksXHJcbiAgICAgIHdpZHRoOiBtYXhYIC0gbWluWCxcclxuICAgICAgaGVpZ2h0OiBtYXhZIC0gbWluWSxcclxuICAgIH07XHJcbiAgfVxyXG5cclxuICBoaWdobGlnaHRGaXh0dXJlKGdyb3VwOiBhbnksIGJsaW5rOiBib29sZWFuID0gZmFsc2UpIHtcclxuICAgIHRoaXMucmVtb3ZlSGlnaGxpZ2h0KCk7XHJcbiAgICB0aGlzLmNhbmNlbEhpZ2hsaWdodEJsaW5rID0gZmFsc2U7XHJcblxyXG4gICAgY29uc3QgY2VudGVyID0gZ3JvdXAuZ2V0Q2VudGVyUG9pbnQoKTtcclxuXHJcbiAgICBjb25zdCByZWFsV2lkdGggPSBncm91cC53aWR0aCEgKiBncm91cC5zY2FsZVghO1xyXG4gICAgY29uc3QgcmVhbEhlaWdodCA9IGdyb3VwLmhlaWdodCEgKiBncm91cC5zY2FsZVkhO1xyXG5cclxuICAgIGNvbnN0IHJlY3QgPSBuZXcgZmFicmljLlJlY3Qoe1xyXG4gICAgICBsZWZ0OiBjZW50ZXIueCxcclxuICAgICAgdG9wOiBjZW50ZXIueSxcclxuICAgICAgd2lkdGg6IHJlYWxXaWR0aCArIDgsIC8vIGNvbnNpc3RlbnQgcGFkZGluZ1xyXG4gICAgICBoZWlnaHQ6IHJlYWxIZWlnaHQgKyA4LFxyXG4gICAgICByeDogNSxcclxuICAgICAgcnk6IDUsXHJcbiAgICAgIHN0cm9rZTogXCIjMDBhYWZmXCIsXHJcbiAgICAgIHN0cm9rZVdpZHRoOiAzLFxyXG4gICAgICBmaWxsOiBcInRyYW5zcGFyZW50XCIsXHJcbiAgICAgIHNlbGVjdGFibGU6IGZhbHNlLFxyXG4gICAgICBldmVudGVkOiBmYWxzZSxcclxuICAgICAgb3JpZ2luWDogXCJjZW50ZXJcIixcclxuICAgICAgb3JpZ2luWTogXCJjZW50ZXJcIixcclxuICAgICAgYW5nbGU6IGdyb3VwLmFuZ2xlIHx8IDAsXHJcbiAgICAgIG9wYWNpdHk6IGJsaW5rID8gMCA6IDEsXHJcbiAgICB9KTtcclxuXHJcbiAgICB0aGlzLmNhbnZhcy5hZGQocmVjdCk7XHJcbiAgICB0aGlzLmNhbnZhcy5tb3ZlT2JqZWN0VG8ocmVjdCwgdGhpcy5jYW52YXMuZ2V0T2JqZWN0cygpLmxlbmd0aCAtIDEpO1xyXG4gICAgdGhpcy5jYW52YXMucmVxdWVzdFJlbmRlckFsbCgpO1xyXG5cclxuICAgIHRoaXMuYWN0aXZlSGlnaGxpZ2h0ID0gcmVjdDtcclxuXHJcbiAgICAvLyAtLS0gTm8gYmxpbmtpbmcgbmVlZGVkIC0tLVxyXG4gICAgaWYgKCFibGluaykgcmV0dXJuO1xyXG5cclxuICAgIGxldCBjeWNsZXMgPSAwO1xyXG5cclxuICAgIGNvbnN0IGJsaW5rT25jZSA9ICgpID0+IHtcclxuICAgICAgaWYgKHRoaXMuY2FuY2VsSGlnaGxpZ2h0QmxpbmspIHtcclxuICAgICAgICB0aGlzLnJlbW92ZUhpZ2hsaWdodCgpO1xyXG4gICAgICAgIHJldHVybjtcclxuICAgICAgfVxyXG5cclxuICAgICAgcmVjdC5hbmltYXRlKFxyXG4gICAgICAgIHsgb3BhY2l0eTogMSB9LFxyXG4gICAgICAgIHtcclxuICAgICAgICAgIGR1cmF0aW9uOiAyMDAsXHJcbiAgICAgICAgICBvbkNoYW5nZTogKCkgPT4gdGhpcy5jYW52YXMucmVxdWVzdFJlbmRlckFsbCgpLFxyXG4gICAgICAgICAgb25Db21wbGV0ZTogKCkgPT4ge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5jYW5jZWxIaWdobGlnaHRCbGluaykge1xyXG4gICAgICAgICAgICAgIHRoaXMucmVtb3ZlSGlnaGxpZ2h0KCk7XHJcbiAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICByZWN0LmFuaW1hdGUoXHJcbiAgICAgICAgICAgICAgeyBvcGFjaXR5OiAwIH0sXHJcbiAgICAgICAgICAgICAge1xyXG4gICAgICAgICAgICAgICAgZHVyYXRpb246IDIwMCxcclxuICAgICAgICAgICAgICAgIG9uQ2hhbmdlOiAoKSA9PiB0aGlzLmNhbnZhcy5yZXF1ZXN0UmVuZGVyQWxsKCksXHJcbiAgICAgICAgICAgICAgICBvbkNvbXBsZXRlOiAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmNhbmNlbEhpZ2hsaWdodEJsaW5rKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZW1vdmVIaWdobGlnaHQoKTtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgIGN5Y2xlcysrO1xyXG4gICAgICAgICAgICAgICAgICBpZiAoY3ljbGVzIDwgMjApIHtcclxuICAgICAgICAgICAgICAgICAgICBibGlua09uY2UoKTtcclxuICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY2FuY2VsSGlnaGxpZ2h0QmxpbmspIHtcclxuICAgICAgICAgICAgICAgICAgICAgIHJlY3Quc2V0KHsgb3BhY2l0eTogMSB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgKTtcclxuICAgIH07XHJcblxyXG4gICAgYmxpbmtPbmNlKCk7XHJcbiAgfVxyXG5cclxuICByZW1vdmVIaWdobGlnaHQoKSB7XHJcbiAgICB0aGlzLmNhbmNlbEhpZ2hsaWdodEJsaW5rID0gdHJ1ZTtcclxuICAgIGlmICh0aGlzLmFjdGl2ZUhpZ2hsaWdodCkge1xyXG4gICAgICB0aGlzLmNhbnZhcy5yZW1vdmUodGhpcy5hY3RpdmVIaWdobGlnaHQpO1xyXG4gICAgICB0aGlzLmFjdGl2ZUhpZ2hsaWdodCA9IG51bGw7XHJcbiAgICAgIHRoaXMuY2FudmFzLnJlcXVlc3RSZW5kZXJBbGwoKTtcclxuICAgIH1cclxuICB9XHJcblxyXG4gIG9uQ2hhbmdlRml4dHVyZSh7XHJcbiAgICBmaXh0dXJlSWQsXHJcbiAgICBmaXh0dXJlTmFtZSxcclxuICAgIHNoZWxmSWQsXHJcbiAgICB6b25lLFxyXG4gIH06IHtcclxuICAgIGZpeHR1cmVJZDogc3RyaW5nO1xyXG4gICAgZml4dHVyZU5hbWU6IHN0cmluZztcclxuICAgIHNoZWxmSWQ6IHN0cmluZztcclxuICAgIHpvbmU6IHN0cmluZztcclxuICB9KSB7XHJcbiAgICBjb25zdCBhY3Rpb25GaXh0dXJlID0gdGhpcy5jYW52YXNcclxuICAgICAgLmdldE9iamVjdHMoKVxyXG4gICAgICAuZmluZChcclxuICAgICAgICAob2JqOiBhbnkpID0+IG9iai5vYmpUeXBlID09PSBcImZpeHR1cmVcIiAmJiBvYmouZml4dHVyZUlkID09PSBmaXh0dXJlSWQsXHJcbiAgICAgICkgYXMgZmFicmljLkdyb3VwIHwgdW5kZWZpbmVkO1xyXG5cclxuICAgIGlmICghYWN0aW9uRml4dHVyZSkgcmV0dXJuO1xyXG5cclxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICB0aGlzLnJlc2l6ZUNhbnZhcygpO1xyXG4gICAgICB0aGlzLmZpdENhbnZhc1RvTGF5b3V0QW5pbWF0ZWQoKTtcclxuICAgIH0sIDMwMCk7XHJcblxyXG4gICAgdGhpcy5oaWdobGlnaHRGaXh0dXJlKGFjdGlvbkZpeHR1cmUsIHRydWUpO1xyXG4gICAgdGhpcy5zZWxlY3RGaXh0dXJlKGFjdGlvbkZpeHR1cmUpO1xyXG4gIH1cclxuXHJcbiAgb25DbGlja0Nsb3NlKCkge1xyXG4gICAgdGhpcy5zZWxlY3RlZEZpeHR1cmUgPSBudWxsO1xyXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgIHRoaXMucmVzaXplQ2FudmFzKCk7XHJcbiAgICAgIHRoaXMuZml0Q2FudmFzVG9MYXlvdXRBbmltYXRlZCgpO1xyXG4gICAgfSwgMzAwKTtcclxuICAgIHRoaXMucmVtb3ZlSGlnaGxpZ2h0KCk7XHJcbiAgfVxyXG5cclxuICBuZ09uRGVzdHJveSgpOiB2b2lkIHtcclxuICAgIHRoaXMuZGVzdHJveSQubmV4dCgpO1xyXG4gICAgdGhpcy5kZXN0cm95JC5jb21wbGV0ZSgpO1xyXG4gIH1cclxufVxyXG4iLCI8c2VjdGlvbiBpZD1cInByb2R1Y3QtbG9jYXRvclwiPlxyXG4gICAgPGRpdiAqbmdJZj1cImlzUGFnZUxvYWRpbmdcIiBjbGFzcz1cInJvd1wiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJjb2wtMTIgbS0wXCI+PG5nLWNvbnRhaW5lciAqbmdUZW1wbGF0ZU91dGxldD1cImhlYWRlclNrZWxldG9uXCI+PC9uZy1jb250YWluZXI+PC9kaXY+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImNvbC0xMlwiPjxuZy1jb250YWluZXIgKm5nVGVtcGxhdGVPdXRsZXQ9XCJza2VsZXRvbkxvYWRlclwiPjwvbmctY29udGFpbmVyPjwvZGl2PlxyXG4gICAgPC9kaXY+XHJcblxyXG4gICAgPGRpdiBbbmdDbGFzc109XCJ7ICdkLW5vbmUnOiBpc1BhZ2VMb2FkaW5nIH1cIj5cclxuICAgICAgICA8ZGl2IGlkPVwiYm9keVwiIGNsYXNzPVwicm93XCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJjb2wgb3ZlcmZsb3ctaGlkZGVuIHBvc2l0aW9uLXJlbGF0aXZlIGNvbXBsaWFuY2UtY2FudmFzXCI+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGlkPVwiY2FudmFzLWNhcmRcIiBjbGFzcz1cInctMTAwIHBvc2l0aW9uLXJlbGF0aXZlXCIgI2NhbnZhc0NvbnRhaW5lcj5cclxuICAgICAgICAgICAgICAgICAgICA8Y2FudmFzIGlkPVwiYmFzZS1jYW52YXNcIiAjYmFzZUNhbnZhcz48L2NhbnZhcz5cclxuICAgICAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuXHJcbiAgICAgICAgICAgIDxkaXYgW25nQ2xhc3NdPVwieydkLW5vbmUnOiFzZWxlY3RlZEZpeHR1cmU/LmZpeHR1cmVEYXRhfVwiIGNsYXNzPVwiY29sIGJnLXdoaXRlIHJvdW5kZWQgcC0zIGZpeHR1cmUtb3ZlcnZpZXdcIj5cclxuICAgICAgICAgICAgICAgIDxtaXNwbGFjZWQtcHJvZHVjdC1maXh0dXJlIFtmaXh0dXJlRGV0YWlsc109XCJzZWxlY3RlZEZpeHR1cmU/LmZpeHR1cmVEYXRhXCJcclxuICAgICAgICAgICAgICAgICAgICBbc2VsZWN0ZWRQcm9kdWN0XT1cInNlbGVjdGVkUHJvZHVjdFwiXHJcbiAgICAgICAgICAgICAgICAgICAgKHRhcmdldEZpeHR1cmVGdWxsRGV0YWlscyk9XCJ0YXJnZXRGaXh0dXJlRnVsbERldGFpbHMuZW1pdCgkZXZlbnQpXCI+PC9taXNwbGFjZWQtcHJvZHVjdC1maXh0dXJlPlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG48L3NlY3Rpb24+XHJcblxyXG5cclxuPG5nLXRlbXBsYXRlICNoZWFkZXJTa2VsZXRvbj5cclxuICAgIDxkaXYgY2xhc3M9XCJyb3cgbS0wIGctMCBsb2FkZXIgZC1mbGV4IGp1c3RpZnktY29udGVudC1jZW50ZXIgYWxpZ24taXRlbXMtY2VudGVyIG92ZXJmbG93LWhpZGRlblwiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzaGltbWVyIHctMTAwIHAtNCByb3VuZGVkXCI+XHJcbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJ3cmFwcGVyXCI+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Ryb2tlIG10LTAgYW5pbWF0ZSB0aXRsZVwiPjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0cm9rZSBhbmltYXRlIGRlc2NyaXB0aW9uXCI+PC9kaXY+XHJcbiAgICAgICAgICAgIDwvZGl2PlxyXG4gICAgICAgIDwvZGl2PlxyXG4gICAgPC9kaXY+XHJcbjwvbmctdGVtcGxhdGU+XHJcblxyXG48bmctdGVtcGxhdGUgI3NrZWxldG9uTG9hZGVyPlxyXG4gICAgPGRpdiBjbGFzcz1cInJvdyBsb2FkZXIgZC1mbGV4IGp1c3RpZnktY29udGVudC1jZW50ZXIgYWxpZ24taXRlbXMtY2VudGVyIG92ZXJmbG93LWhpZGRlblwiPlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJzaGltbWVyIHJvdW5kZWRcIj5cclxuICAgICAgICAgICAgPGRpdiBjbGFzcz1cIndyYXBwZXJcIj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdHJva2UgYW5pbWF0ZSB0aXRsZVwiPjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0cm9rZSBhbmltYXRlIGxpbmtcIj48L2Rpdj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdHJva2UgYW5pbWF0ZSBkZXNjcmlwdGlvblwiPjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0cm9rZSBhbmltYXRlIGRlc2NyaXB0aW9uXCI+PC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8YnIgLz5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdHJva2UgYW5pbWF0ZSB0aXRsZVwiPjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0cm9rZSBhbmltYXRlIGxpbmtcIj48L2Rpdj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdHJva2UgYW5pbWF0ZSBkZXNjcmlwdGlvblwiPjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPGJyIC8+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Ryb2tlIGFuaW1hdGUgdGl0bGVcIj48L2Rpdj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdHJva2UgYW5pbWF0ZSBsaW5rXCI+PC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Ryb2tlIGFuaW1hdGUgZGVzY3JpcHRpb25cIj48L2Rpdj5cclxuICAgICAgICAgICAgICAgIDxiciAvPlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0cm9rZSBhbmltYXRlIHRpdGxlXCI+PC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwic3Ryb2tlIGFuaW1hdGUgbGlua1wiPjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0cm9rZSBhbmltYXRlIGRlc2NyaXB0aW9uXCI+PC9kaXY+XHJcbiAgICAgICAgICAgICAgICA8YnIgLz5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdHJva2UgYW5pbWF0ZSB0aXRsZVwiPjwvZGl2PlxyXG4gICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cInN0cm9rZSBhbmltYXRlIGxpbmtcIj48L2Rpdj5cclxuICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJzdHJva2UgYW5pbWF0ZSBkZXNjcmlwdGlvblwiPjwvZGl2PlxyXG4gICAgICAgICAgICA8L2Rpdj5cclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvZGl2PlxyXG48L25nLXRlbXBsYXRlPiJdfQ==