@libs-ui/services-diagram-draw 0.2.356-37

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 (33) hide show
  1. package/README.md +279 -0
  2. package/canvas.service.d.ts +42 -0
  3. package/diagram-draw.service.d.ts +91 -0
  4. package/direction.service.d.ts +43 -0
  5. package/esm2022/canvas.service.mjs +628 -0
  6. package/esm2022/diagram-draw.service.mjs +711 -0
  7. package/esm2022/direction.service.mjs +255 -0
  8. package/esm2022/index.mjs +6 -0
  9. package/esm2022/interfaces/canvas.interface.mjs +2 -0
  10. package/esm2022/interfaces/coordinates.interface.mjs +2 -0
  11. package/esm2022/interfaces/diagram.interface.mjs +2 -0
  12. package/esm2022/libs-ui-services-diagram-draw.mjs +5 -0
  13. package/esm2022/utils/calculator-branch.util.mjs +187 -0
  14. package/esm2022/utils/calculator-element.util.mjs +335 -0
  15. package/esm2022/utils/canvas.util.mjs +176 -0
  16. package/esm2022/utils/diagram.util.mjs +54 -0
  17. package/esm2022/utils/direction.util.mjs +103 -0
  18. package/esm2022/utils/horizontal/calculator-branch.util.mjs +243 -0
  19. package/esm2022/utils/horizontal/calculator-coordinates.util.mjs +315 -0
  20. package/fesm2022/libs-ui-services-diagram-draw.mjs +2982 -0
  21. package/fesm2022/libs-ui-services-diagram-draw.mjs.map +1 -0
  22. package/index.d.ts +5 -0
  23. package/interfaces/canvas.interface.d.ts +21 -0
  24. package/interfaces/coordinates.interface.d.ts +40 -0
  25. package/interfaces/diagram.interface.d.ts +109 -0
  26. package/package.json +27 -0
  27. package/utils/calculator-branch.util.d.ts +16 -0
  28. package/utils/calculator-element.util.d.ts +24 -0
  29. package/utils/canvas.util.d.ts +21 -0
  30. package/utils/diagram.util.d.ts +6 -0
  31. package/utils/direction.util.d.ts +6 -0
  32. package/utils/horizontal/calculator-branch.util.d.ts +67 -0
  33. package/utils/horizontal/calculator-coordinates.util.d.ts +42 -0
@@ -0,0 +1,315 @@
1
+ import { canvasConfigReadonly } from '../../diagram-draw.service';
2
+ import { checkMaxTop } from '../calculator-element.util';
3
+ import { buildFlatElement } from '../diagram.util';
4
+ import { MoLibDiagramHorizontalCalculatorBranchUtil } from './calculator-branch.util';
5
+ /**
6
+ * Horizontal layout calculator.
7
+ * Mirrors MoLibDiagramCalculatorCoordinatesUtil (vertical) but rotated 90°:
8
+ * - Elements grow LEFT → RIGHT (specific_x advances along main axis)
9
+ * - Branches split UP / DOWN (specific_y for branch offset)
10
+ * - "above" branch = upper side (y decreases)
11
+ * - "under" branch = lower side (y increases)
12
+ *
13
+ * Key axis mapping vs. vertical:
14
+ * vertical: specific_y ↕ specific_x centered
15
+ * horizontal: specific_x → specific_y centered
16
+ */
17
+ export class MoLibDiagramHorizontalCalculatorCoordinatesUtil {
18
+ static setXYElements(elements, config, positionY) {
19
+ if (!elements || !elements.length) {
20
+ return;
21
+ }
22
+ elements.forEach((currentElement, index) => {
23
+ currentElement.specific_y = (currentElement.specific_y ?? 0) + (positionY ?? 0);
24
+ const preElement = elements[index - 1];
25
+ if (preElement) {
26
+ // Trong horizontal: y (chiều cao) căn giữa theo preElement, x tiến sang phải
27
+ currentElement.specific_y = (preElement.specific_y ?? 0) + (preElement.specific_height ?? 0) / 2 - (currentElement.specific_height ?? 0) / 2;
28
+ currentElement.specific_x = (preElement.specific_x ?? 0) + (preElement.specific_width ?? 0) + this.checkElementGetMargin(preElement.nodeOtherConfig);
29
+ if (preElement.position_end_branch) {
30
+ currentElement.specific_x = preElement.position_end_branch;
31
+ }
32
+ }
33
+ checkMaxTop(config, currentElement.specific_y, currentElement.branches?.[0]?.positionMaxTop);
34
+ const top = currentElement.specific_y ?? 0;
35
+ const left = (currentElement.specific_x ?? 0) + (currentElement.specific_width ?? 0) / 2; // điểm giữa theo X (điểm vẽ SVG)
36
+ let lineBetweenElements = (currentElement.specific_width ?? 0) + this.checkElementGetMargin(currentElement.nodeOtherConfig);
37
+ if (currentElement.branches && currentElement.branches.length) {
38
+ lineBetweenElements = (currentElement.specific_width ?? 0) + canvasConfigReadonly().ELEMENT_MARGIN_DEFAULT_BRANCH;
39
+ }
40
+ const maxY = (currentElement.specific_y ?? 0) + (currentElement.specific_height ?? 0) + 200;
41
+ const maxXRight = (currentElement.specific_x ?? 0) + (currentElement.specific_width ?? 0) + 200;
42
+ const configSvg = config.widthHeightSvgCanvas;
43
+ configSvg.heightSvg = maxY > configSvg.heightSvg ? maxY : configSvg.heightSvg;
44
+ configSvg.widthSvg = maxXRight > configSvg.widthSvg ? maxXRight : configSvg.widthSvg;
45
+ if (!currentElement.branches || !currentElement.branches.length) {
46
+ // Element không có nhánh: vẽ đường thẳng ngang
47
+ const drawFormToWidthExit = (currentElement.subCodeOfElement || currentElement.code) === canvasConfigReadonly().TYPE_ELEMENT_EXIT ? (currentElement.specific_width ?? 0) / 2 : lineBetweenElements;
48
+ currentElement.attributeSvgD = `M ${currentElement.specific_x ?? 0} ${top + (currentElement.specific_height ?? 0) / 2} l ${drawFormToWidthExit} 0`;
49
+ currentElement.position_end = (currentElement.specific_x ?? 0) + lineBetweenElements;
50
+ if (currentElement.nodeOtherConfig) {
51
+ const waitWidth = this.getWidthWaitConfig(currentElement.nodeOtherConfig);
52
+ const distanceElementToWait = (currentElement.specific_width ?? 0) + canvasConfigReadonly().DISTANCE_TO_WAIT;
53
+ const leftStartLine2 = (currentElement.specific_x ?? 0) + distanceElementToWait + waitWidth;
54
+ currentElement.attributeSvgD = `M ${currentElement.specific_x ?? 0} ${top + (currentElement.specific_height ?? 0) / 2} l ${distanceElementToWait} 0`;
55
+ currentElement.position_end = leftStartLine2 + lineBetweenElements;
56
+ currentElement.nodeOtherConfig.specific_x = (currentElement.specific_x ?? 0) + distanceElementToWait;
57
+ // specific_y = tâm Y của đường line — setTranslatePositions sẽ trừ height/2 để căn giữa dọc
58
+ currentElement.nodeOtherConfig.specific_y = top + (currentElement.specific_height ?? 0) / 2;
59
+ // Đảm bảo có kích thước để setTranslatePositions tính offset đúng
60
+ if (!currentElement.nodeOtherConfig.specific_height) {
61
+ currentElement.nodeOtherConfig.specific_height = canvasConfigReadonly().ELEMENT_WAIT_DEFAULT;
62
+ }
63
+ if (!currentElement.nodeOtherConfig.specific_width) {
64
+ currentElement.nodeOtherConfig.specific_width = canvasConfigReadonly().ELEMENT_WAIT_DEFAULT;
65
+ }
66
+ delete currentElement.nodeOtherConfig.attributeSvgD;
67
+ if (currentElement.subCodeOfElement !== canvasConfigReadonly().TYPE_ELEMENT_EXIT) {
68
+ currentElement.nodeOtherConfig.attributeSvgD = `M ${leftStartLine2} ${top + (currentElement.specific_height ?? 0) / 2} l ${canvasConfigReadonly().WAIT_TO_ELEMENT} 0`;
69
+ }
70
+ }
71
+ return;
72
+ }
73
+ // Elements có nhánh
74
+ const half = Math.ceil(currentElement.branches.length / 2);
75
+ const aboveHalf = currentElement.branches.slice(0, half);
76
+ const underHalf = currentElement.branches.slice(half);
77
+ let brachMiddle;
78
+ if (aboveHalf.length !== underHalf.length) {
79
+ brachMiddle = aboveHalf.pop();
80
+ }
81
+ // TÍNH CHIỀU CAO TỐI ĐA CỦA NHÁNH (đây là chiều rộng trong horizontal context nhưng
82
+ // dùng chung maxHeightBranch để đơn giản, ý nghĩa là "khoảng trống tối thiểu dành cho nhánh không có element")
83
+ const maxWidthBranch = { width: 0 };
84
+ this.calculatorMaxBranchWidth(currentElement, maxWidthBranch);
85
+ currentElement.maxHeightBranch = maxWidthBranch.width;
86
+ const maxWidthBrachMiddle = { width: 0, aboveWidth: 0, underWidth: 0 };
87
+ const lineFormElementToBranching = (currentElement.specific_width ?? 0) + canvasConfigReadonly().ELEMENT_MARGIN_DEFAULT_BRANCH;
88
+ // top = y + height/2: điểm giữa theo chiều Y → dùng làm tọa độ Y của đường ngang chính
89
+ const topMid = top + (currentElement.specific_height ?? 0) / 2;
90
+ if (brachMiddle) {
91
+ brachMiddle.onTheSide = 'center';
92
+ this.calculatorHeightBranch(brachMiddle.elements, maxWidthBrachMiddle);
93
+ brachMiddle.widthBranch = {
94
+ width: maxWidthBrachMiddle.width,
95
+ above: maxWidthBrachMiddle.aboveWidth,
96
+ under: maxWidthBrachMiddle.underWidth,
97
+ };
98
+ MoLibDiagramHorizontalCalculatorBranchUtil.drawStraightLine(topMid, lineFormElementToBranching, currentElement.specific_x ?? 0, brachMiddle, maxWidthBranch.width, config);
99
+ }
100
+ let hasNextSameParentElementNext = false;
101
+ const aboveHalfReverse = aboveHalf.reverse();
102
+ aboveHalfReverse.forEach((branch, indexBranch) => {
103
+ if (!hasNextSameParentElementNext) {
104
+ const flatElementOnBranch = [];
105
+ buildFlatElement(branch.elements, flatElementOnBranch);
106
+ hasNextSameParentElementNext = !flatElementOnBranch || !flatElementOnBranch.length ? true : flatElementOnBranch.find((item) => item.next_id === currentElement.next_id) ? true : false;
107
+ }
108
+ branch.onTheSide = 'above';
109
+ const maxWidthB = { width: 0, aboveWidth: 0, underWidth: 0 };
110
+ this.calculatorHeightBranch(branch.elements, maxWidthB);
111
+ branch.widthBranch = {
112
+ width: maxWidthB.width,
113
+ above: maxWidthB.aboveWidth,
114
+ under: maxWidthB.underWidth,
115
+ };
116
+ const branchPre = aboveHalfReverse[indexBranch - 1];
117
+ let lineBetweenBranch = maxWidthB.underWidth + canvasConfigReadonly().ELEMENT_MARGIN_BETWEEN_BRANCH_DEFAULT / 2;
118
+ if (branchPre) {
119
+ lineBetweenBranch += (branchPre.widthBranch?.width ?? 0) + canvasConfigReadonly().ELEMENT_MARGIN_BETWEEN_BRANCH_DEFAULT;
120
+ }
121
+ if (brachMiddle) {
122
+ lineBetweenBranch += (brachMiddle.widthBranch?.above ?? 0) + canvasConfigReadonly().ELEMENT_MARGIN_BETWEEN_BRANCH_DEFAULT / 2;
123
+ }
124
+ MoLibDiagramHorizontalCalculatorBranchUtil.aboveLine(topMid, lineFormElementToBranching, currentElement.specific_x ?? 0, lineBetweenBranch, branch, maxWidthBranch.width, currentElement, config);
125
+ });
126
+ underHalf.forEach((branch, indexBranch) => {
127
+ if (!hasNextSameParentElementNext) {
128
+ const flatElementOnBranch = [];
129
+ buildFlatElement(branch.elements, flatElementOnBranch);
130
+ hasNextSameParentElementNext = !flatElementOnBranch || !flatElementOnBranch.length ? true : flatElementOnBranch.find((item) => item.next_id === currentElement.next_id) ? true : false;
131
+ }
132
+ branch.onTheSide = 'under';
133
+ const maxWidthB = { width: 0, aboveWidth: 0, underWidth: 0 };
134
+ this.calculatorHeightBranch(branch.elements, maxWidthB);
135
+ branch.widthBranch = {
136
+ width: maxWidthB.width,
137
+ above: maxWidthB.aboveWidth,
138
+ under: maxWidthB.underWidth,
139
+ };
140
+ const branchPre = underHalf[indexBranch - 1];
141
+ let lineBetweenBranch = maxWidthB.aboveWidth + canvasConfigReadonly().ELEMENT_MARGIN_BETWEEN_BRANCH_DEFAULT / 2;
142
+ if (branchPre) {
143
+ lineBetweenBranch += (branchPre.widthBranch?.width ?? 0) + canvasConfigReadonly().ELEMENT_MARGIN_BETWEEN_BRANCH_DEFAULT;
144
+ }
145
+ if (brachMiddle) {
146
+ lineBetweenBranch += (brachMiddle.widthBranch?.under ?? 0) + canvasConfigReadonly().ELEMENT_MARGIN_BETWEEN_BRANCH_DEFAULT / 2;
147
+ }
148
+ MoLibDiagramHorizontalCalculatorBranchUtil.underLine(topMid, lineFormElementToBranching, currentElement.specific_x ?? 0, lineBetweenBranch, branch, maxWidthBranch.width, currentElement, config);
149
+ });
150
+ });
151
+ this.setTranslatePositions(elements);
152
+ }
153
+ /**
154
+ * Set translateX/Y cho tất cả elements (bao gồm branches và nodeOtherConfig)
155
+ */
156
+ static setTranslatePositions(elements) {
157
+ elements.forEach((element) => {
158
+ element.translateX = element.specific_x;
159
+ element.translateY = element.specific_y;
160
+ if (element.nodeOtherConfig) {
161
+ const offsetY = (element.nodeOtherConfig.specific_height ?? 0) / 2;
162
+ element.nodeOtherConfig.translateX = element.nodeOtherConfig.specific_x;
163
+ element.nodeOtherConfig.translateY = (element.nodeOtherConfig.specific_y ?? 0) - offsetY;
164
+ }
165
+ if (element.branches && element.branches.length > 0) {
166
+ element.branches.forEach((branch) => {
167
+ if (branch.nodeOtherConfig) {
168
+ const offsetY = (branch.nodeOtherConfig.specific_height ?? 0) / 2;
169
+ branch.nodeOtherConfig.translateX = branch.nodeOtherConfig.specific_x;
170
+ branch.nodeOtherConfig.translateY = (branch.nodeOtherConfig.specific_y ?? 0) - offsetY;
171
+ }
172
+ if (branch.elements && branch.elements.length > 0) {
173
+ this.setTranslatePositions(branch.elements);
174
+ }
175
+ });
176
+ }
177
+ });
178
+ }
179
+ /** Tính chiều rộng tối đa của nhánh (trong horizontal = chiều cao thực của nhánh không có element) */
180
+ static calculatorMaxBranchWidth(element, maxWidthBranch) {
181
+ if (!element.branches || !element.branches.length) {
182
+ return;
183
+ }
184
+ element.branches.forEach((branch) => {
185
+ if (!branch.elements || !branch.elements.length) {
186
+ const lineBranchNoHasElement = canvasConfigReadonly().ELEMENT_WIDTH_DEFAULT_BRANCH_WHEN_NOT_ELEMENT;
187
+ maxWidthBranch.width = lineBranchNoHasElement > maxWidthBranch.width ? lineBranchNoHasElement : maxWidthBranch.width;
188
+ return;
189
+ }
190
+ const total = { height: 0 };
191
+ this.plusWidthElementInBranch(branch.elements, total);
192
+ maxWidthBranch.width = total.height > maxWidthBranch.width ? total.height : maxWidthBranch.width;
193
+ });
194
+ }
195
+ /** Tính tổng chiều rộng các elements trong nhánh (dọc theo trục X) */
196
+ static plusWidthElementInBranch(elements, total) {
197
+ elements.forEach((element) => {
198
+ const margin = !element.branches || !element.branches.length ? this.checkElementGetMargin(element.nodeOtherConfig) : canvasConfigReadonly().ELEMENT_MARGIN_DEFAULT_BRANCH;
199
+ total.height += (element.specific_width ?? 0) + margin;
200
+ if (!element.branches || !element.branches.length) {
201
+ return;
202
+ }
203
+ total.height += 64;
204
+ const theMostElementsInBranch = { height: 0 };
205
+ element.branches.forEach((branch) => {
206
+ const widthInBranch = { height: 0 };
207
+ widthInBranch.height += canvasConfigReadonly().ELEMENT_MARGIN_DEFAULT_BRANCH_TO_ELEMENT_FIRST + 20;
208
+ if (!branch.elements || !branch.elements.length) {
209
+ widthInBranch.height += canvasConfigReadonly().ELEMENT_WIDTH_DEFAULT_BRANCH_WHEN_NOT_ELEMENT;
210
+ if (theMostElementsInBranch.height < widthInBranch.height) {
211
+ theMostElementsInBranch.height = widthInBranch.height;
212
+ }
213
+ return;
214
+ }
215
+ this.plusWidthElementInBranch(branch.elements, widthInBranch);
216
+ if (theMostElementsInBranch.height < widthInBranch.height) {
217
+ theMostElementsInBranch.height = widthInBranch.height;
218
+ }
219
+ });
220
+ total.height += theMostElementsInBranch.height;
221
+ });
222
+ }
223
+ /**
224
+ * Tính chiều cao (Y span) của một nhánh — dùng để offset các nhánh trên/dưới.
225
+ * Trong horizontal context: mỗi nhánh trải dài theo Y (lên/xuống).
226
+ */
227
+ static calculatorHeightBranch(elements, maxWidth) {
228
+ if (!elements || !elements.length) {
229
+ const w = canvasConfigReadonly().DEFAULT_BRANCH_WHEN_NO_ELEMENT;
230
+ maxWidth.width = w;
231
+ maxWidth.aboveWidth = w / 2;
232
+ maxWidth.underWidth = w / 2;
233
+ return;
234
+ }
235
+ const maxWidthInElements = { width: 0, aboveWidth: 0, underWidth: 0 };
236
+ elements.forEach((element) => {
237
+ if (!element.branches || !element.branches.length) {
238
+ // element không nhánh: dùng specific_height làm Y span
239
+ if ((element.specific_height ?? 0) < maxWidthInElements.width) {
240
+ return;
241
+ }
242
+ const h = element.specific_height ?? 0;
243
+ maxWidthInElements.width = h;
244
+ maxWidthInElements.aboveWidth = h / 2;
245
+ maxWidthInElements.underWidth = h / 2;
246
+ return;
247
+ }
248
+ const widthElementIncludeBranch = { width: 0, aboveWidth: 0, underWidth: 0 };
249
+ const h = element.specific_height ?? 0;
250
+ if (h > widthElementIncludeBranch.width) {
251
+ widthElementIncludeBranch.width = h;
252
+ widthElementIncludeBranch.aboveWidth = h / 2;
253
+ widthElementIncludeBranch.underWidth = h / 2;
254
+ }
255
+ const half = Math.ceil(element.branches.length / 2);
256
+ const aboveHalf = element.branches.slice(0, half);
257
+ const underHalf = element.branches.slice(half);
258
+ let brachMiddle;
259
+ if (aboveHalf.length !== underHalf.length) {
260
+ brachMiddle = aboveHalf.pop();
261
+ }
262
+ if (brachMiddle)
263
+ brachMiddle.onTheSide = 'center';
264
+ aboveHalf.forEach((branch) => (branch.onTheSide = 'above'));
265
+ underHalf.forEach((branch) => (branch.onTheSide = 'under'));
266
+ const widthBranch = { width: 0, aboveWidth: 0, underWidth: 0 };
267
+ element.branches.forEach((branch) => {
268
+ const w = { width: 0, aboveWidth: 0, underWidth: 0 };
269
+ this.calculatorHeightBranch(branch.elements, w);
270
+ switch (branch.onTheSide) {
271
+ case 'above':
272
+ widthBranch.aboveWidth += w.width;
273
+ break;
274
+ case 'under':
275
+ widthBranch.underWidth += w.width;
276
+ break;
277
+ case 'center':
278
+ widthBranch.aboveWidth += w.aboveWidth;
279
+ widthBranch.underWidth += w.underWidth;
280
+ break;
281
+ }
282
+ });
283
+ const marginBetweenBranch = (element.branches.length - 1) * canvasConfigReadonly().ELEMENT_MARGIN_BETWEEN_BRANCH_DEFAULT;
284
+ widthBranch.aboveWidth += marginBetweenBranch / 2;
285
+ widthBranch.underWidth += marginBetweenBranch / 2;
286
+ const maxAboveWidth = Math.max(widthElementIncludeBranch.aboveWidth, widthBranch.aboveWidth);
287
+ const maxUnderWidth = Math.max(widthElementIncludeBranch.underWidth, widthBranch.underWidth);
288
+ if (maxWidthInElements.aboveWidth < maxAboveWidth) {
289
+ maxWidthInElements.aboveWidth = maxAboveWidth;
290
+ }
291
+ if (maxWidthInElements.underWidth < maxUnderWidth) {
292
+ maxWidthInElements.underWidth = maxUnderWidth;
293
+ }
294
+ maxWidthInElements.width = maxWidthInElements.aboveWidth + maxWidthInElements.underWidth;
295
+ });
296
+ maxWidth.width += maxWidthInElements.aboveWidth + maxWidthInElements.underWidth;
297
+ maxWidth.aboveWidth += maxWidthInElements.aboveWidth;
298
+ maxWidth.underWidth += maxWidthInElements.underWidth;
299
+ }
300
+ /** Tính khoảng cách thêm vào sau element (bao gồm wait config nếu có) */
301
+ static checkElementGetMargin(hasWaitConfig) {
302
+ if (hasWaitConfig) {
303
+ return canvasConfigReadonly().DISTANCE_TO_WAIT + this.getWidthWaitConfig(hasWaitConfig) + canvasConfigReadonly().WAIT_TO_ELEMENT;
304
+ }
305
+ return canvasConfigReadonly().ELEMENT_MARGIN_DEFAULT;
306
+ }
307
+ /** Tính chiều rộng của wait config node */
308
+ static getWidthWaitConfig(hasWaitConfig) {
309
+ if (hasWaitConfig) {
310
+ return (hasWaitConfig.specific_width ?? canvasConfigReadonly().ELEMENT_WAIT_DEFAULT) + canvasConfigReadonly().DISTANCE_WAIT_TO_NEXT_LINE;
311
+ }
312
+ return canvasConfigReadonly().ELEMENT_WAIT_DEFAULT + canvasConfigReadonly().DISTANCE_WAIT_TO_NEXT_LINE;
313
+ }
314
+ }
315
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2FsY3VsYXRvci1jb29yZGluYXRlcy51dGlsLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vbGlicy11aS9zZXJ2aWNlcy9kaWFncmFtLWRyYXcvc3JjL3V0aWxzL2hvcml6b250YWwvY2FsY3VsYXRvci1jb29yZGluYXRlcy51dGlsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRWxFLE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUV6RCxPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUNuRCxPQUFPLEVBQUUsMENBQTBDLEVBQUUsTUFBTSwwQkFBMEIsQ0FBQztBQUV0Rjs7Ozs7Ozs7Ozs7R0FXRztBQUNILE1BQU0sT0FBTywrQ0FBK0M7SUFDMUQsTUFBTSxDQUFDLGFBQWEsQ0FBQyxRQUFnQyxFQUFFLE1BQTZCLEVBQUUsU0FBa0I7UUFDdEcsSUFBSSxDQUFDLFFBQVEsSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLEVBQUUsQ0FBQztZQUNsQyxPQUFPO1FBQ1QsQ0FBQztRQUVELFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxjQUFjLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDekMsY0FBYyxDQUFDLFVBQVUsR0FBRyxDQUFDLGNBQWMsQ0FBQyxVQUFVLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxTQUFTLElBQUksQ0FBQyxDQUFDLENBQUM7WUFDaEYsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFDLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQztZQUV2QyxJQUFJLFVBQVUsRUFBRSxDQUFDO2dCQUNmLDZFQUE2RTtnQkFDN0UsY0FBYyxDQUFDLFVBQVUsR0FBRyxDQUFDLFVBQVUsQ0FBQyxVQUFVLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsZUFBZSxJQUFJLENB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QVUsSUFBSSxrQkFBa0IsQ0FBQyxVQUFVLENBQUM7SUFDdkQsQ0FBQztJQUVELHlFQUF5RTtJQUNqRSxNQUFNLENBQUMscUJBQXFCLENBQUMsYUFBK0I7UUFDbEUsSUFBSSxhQUFhLEVBQUUsQ0FBQztZQUNsQixPQUFPLG9CQUFvQixFQUFFLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLGtCQUFrQixDQUFDLGFBQWEsQ0FBQyxHQUFHLG9CQUFvQixFQUFFLENBQUMsZUFBZSxDQUFDO1FBQ25JLENBQUM7UUFDRCxPQUFPLG9CQUFvQixFQUFFLENBQUMsc0JBQXNCLENBQUM7SUFDdkQsQ0FBQztJQUVELDJDQUEyQztJQUNuQyxNQUFNLENBQUMsa0JBQWtCLENBQUMsYUFBK0I7UUFDL0QsSUFBSSxhQUFhLEVBQUUsQ0FBQztZQUNsQixPQUFPLENBQUMsYUFBYSxDQUFDLGNBQWMsSUFBSSxvQkFBb0IsRUFBRSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsb0JBQW9CLEVBQUUsQ0FBQywwQkFBMEIsQ0FBQztRQUMzSSxDQUFDO1FBQ0QsT0FBTyxvQkFBb0IsRUFBRSxDQUFDLG9CQUFvQixHQUFHLG9CQUFvQixFQUFFLENBQUMsMEJBQTBCLENBQUM7SUFDekcsQ0FBQztDQUNGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgY2FudmFzQ29uZmlnUmVhZG9ubHkgfSBmcm9tICcuLi8uLi9kaWFncmFtLWRyYXcuc2VydmljZSc7XG5pbXBvcnQgeyBJRGF0YURpYWdyYW1Db25maWdTdmcgfSBmcm9tICcuLi8uLi9pbnRlcmZhY2VzL2Nvb3JkaW5hdGVzLmludGVyZmFjZSc7XG5pbXBvcnQgeyBjaGVja01heFRvcCB9IGZyb20gJy4uL2NhbGN1bGF0b3ItZWxlbWVudC51dGlsJztcbmltcG9ydCB7IElEaWFncmFtRWxlbWVudCwgSURpYWdyYW1FbGVtZW50QnJhbmNoIH0gZnJvbSAnLi4vLi4vaW50ZXJmYWNlcy9kaWFncmFtLmludGVyZmFjZSc7XG5pbXBvcnQgeyBidWlsZEZsYXRFbGVtZW50IH0gZnJvbSAnLi4vZGlhZ3JhbS51dGlsJztcbmltcG9ydCB7IE1vTGliRGlhZ3JhbUhvcml6b250YWxDYWxjdWxhdG9yQnJhbmNoVXRpbCB9IGZyb20gJy4vY2FsY3VsYXRvci1icmFuY2gudXRpbCc7XG5cbi8qKlxuICogSG9yaXpvbnRhbCBsYXlvdXQgY2FsY3VsYXRvci5cbiAqIE1pcnJvcnMgTW9MaWJEaWFncmFtQ2FsY3VsYXRvckNvb3JkaW5hdGVzVXRpbCAodmVydGljYWwpIGJ1dCByb3RhdGVkIDkwwrA6XG4gKiAgLSBFbGVtZW50cyBncm93IExFRlQg4oaSIFJJR0hUICAoc3BlY2lmaWNfeCBhZHZhbmNlcyBhbG9uZyBtYWluIGF4aXMpXG4gKiAgLSBCcmFuY2hlcyBzcGxpdCBVUCAvIERPV04gICAgKHNwZWNpZmljX3kgZm9yIGJyYW5jaCBvZmZzZXQpXG4gKiAgLSBcImFib3ZlXCIgYnJhbmNoID0gdXBwZXIgc2lkZSAoeSBkZWNyZWFzZXMpXG4gKiAgLSBcInVuZGVyXCIgYnJhbmNoID0gbG93ZXIgc2lkZSAoeSBpbmNyZWFzZXMpXG4gKlxuICogS2V5IGF4aXMgbWFwcGluZyB2cy4gdmVydGljYWw6XG4gKiAgIHZlcnRpY2FsOiBzcGVjaWZpY195IOKGlSAgc3BlY2lmaWNfeCBjZW50ZXJlZFxuICogICBob3Jpem9udGFsOiBzcGVjaWZpY194IOKGkiBzcGVjaWZpY195IGNlbnRlcmVkXG4gKi9cbmV4cG9ydCBjbGFzcyBNb0xpYkRpYWdyYW1Ib3Jpem9udGFsQ2FsY3VsYXRvckNvb3JkaW5hdGVzVXRpbCB7XG4gIHN0YXRpYyBzZXRYWUVsZW1lbnRzKGVsZW1lbnRzOiBBcnJheTxJRGlhZ3JhbUVsZW1lbnQ+LCBjb25maWc6IElEYXRhRGlhZ3JhbUNvbmZpZ1N2ZywgcG9zaXRpb25ZPzogbnVtYmVyKSB7XG4gICAgaWYgKCFlbGVtZW50cyB8fCAhZWxlbWVudHMubGVuZ3RoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgZWxlbWVudHMuZm9yRWFjaCgoY3VycmVudEVsZW1lbnQsIGluZGV4KSA9PiB7XG4gICAgICBjdXJyZW50RWxlbWVudC5zcGVjaWZpY195ID0gKGN1cnJlbnRFbGVtZW50LnNwZWNpZmljX3kgPz8gMCkgKyAocG9zaXRpb25ZID8/IDApO1xuICAgICAgY29uc3QgcHJlRWxlbWVudCA9IGVsZW1lbnRzW2luZGV4IC0gMV07XG5cbiAgICAgIGlmIChwcmVFbGVtZW50KSB7XG4gICAgICAgIC8vIFRyb25nIGhvcml6b250YWw6IHkgKGNoaeG7gXUgY2FvKSBjxINuIGdp4buvYSB0aGVvIHByZUVsZW1lbnQsIHggdGnhur9uIHNhbmcgcGjhuqNpXG4gICAgICAgIGN1cnJlbnRFbGVtZW50LnNwZWNpZmljX3kgPSAocHJlRWxlbWVudC5zcGVjaWZpY195ID8/IDApICsgKHByZUVsZW1lbnQuc3BlY2lmaWNfaGVpZ2h0ID8/IDApIC8gMiAtIChjdXJyZW50RWxlbWVudC5zcGVjaWZpY19oZWlnaHQgPz8gMCkgLyAyO1xuICAgICAgICBjdXJyZW50RWxlbWVudC5zcGVjaWZpY194ID0gKHByZUVsZW1lbnQuc3BlY2lmaWNfeCA/PyAwKSArIChwcmVFbGVtZW50LnNwZWNpZmljX3dpZHRoID8/IDApICsgdGhpcy5jaGVja0VsZW1lbnRHZXRNYXJnaW4ocHJlRWxlbWVudC5ub2RlT3RoZXJDb25maWcpO1xuXG4gICAgICAgIGlmIChwcmVFbGVtZW50LnBvc2l0aW9uX2VuZF9icmFuY2gpIHtcbiAgICAgICAgICBjdXJyZW50RWxlbWVudC5zcGVjaWZpY194ID0gcHJlRWxlbWVudC5wb3NpdGlvbl9lbmRfYnJhbmNoO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNoZWNrTWF4VG9wKGNvbmZpZywgY3VycmVudEVsZW1lbnQuc3BlY2lmaWNfeSwgY3VycmVudEVsZW1lbnQuYnJhbmNoZXM/LlswXT8ucG9zaXRpb25NYXhUb3ApO1xuXG4gICAgICBjb25zdCB0b3AgPSBjdXJyZW50RWxlbWVudC5zcGVjaWZpY195ID8/IDA7XG4gICAgICBjb25zdCBsZWZ0ID0gKGN1cnJlbnRFbGVtZW50LnNwZWNpZmljX3ggPz8gMCkgKyAoY3VycmVudEVsZW1lbnQuc3BlY2lmaWNfd2lkdGggPz8gMCkgLyAyOyAvLyDEkWnhu4NtIGdp4buvYSB0aGVvIFggKMSRaeG7g20gduG6vSBTVkcpXG4gICAgICBsZXQgbGluZUJldHdlZW5FbGVtZW50cyA9IChjdXJyZW50RWxlbWVudC5zcGVjaWZpY193aWR0aCA/PyAwKSArIHRoaXMuY2hlY2tFbGVtZW50R2V0TWFyZ2luKGN1cnJlbnRFbGVtZW50Lm5vZGVPdGhlckNvbmZpZyk7XG5cbiAgICAgIGlmIChjdXJyZW50RWxlbWVudC5icmFuY2hlcyAmJiBjdXJyZW50RWxlbWVudC5icmFuY2hlcy5sZW5ndGgpIHtcbiAgICAgICAgbGluZUJldHdlZW5FbGVtZW50cyA9IChjdXJyZW50RWxlbWVudC5zcGVjaWZpY193aWR0aCA/PyAwKSArIGNhbnZhc0NvbmZpZ1JlYWRvbmx5KCkuRUxFTUVOVF9NQVJHSU5fREVGQVVMVF9CUkFOQ0g7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG1heFkgPSAoY3VycmVudEVsZW1lbnQuc3BlY2lmaWNfeSA/PyAwKSArIChjdXJyZW50RWxlbWVudC5zcGVjaWZpY19oZWlnaHQgPz8gMCkgKyAyMDA7XG4gICAgICBjb25zdCBtYXhYUmlnaHQgPSAoY3VycmVudEVsZW1lbnQuc3BlY2lmaWNfeCA/PyAwKSArIChjdXJyZW50RWxlbWVudC5zcGVjaWZpY193aWR0aCA/PyAwKSArIDIwMDtcbiAgICAgIGNvbnN0IGNvbmZpZ1N2ZyA9IGNvbmZpZy53aWR0aEhlaWdodFN2Z0NhbnZhcztcblxuICAgICAgY29uZmlnU3ZnLmhlaWdodFN2ZyA9IG1heFkgPiBjb25maWdTdmcuaGVpZ2h0U3ZnID8gbWF4WSA6IGNvbmZpZ1N2Zy5oZWlnaHRTdmc7XG4gICAgICBjb25maWdTdmcud2lkdGhTdmcgPSBtYXhYUmlnaHQgPiBjb25maWdTdmcud2lkdGhTdmcgPyBtYXhYUmlnaHQgOiBjb25maWdTdmcud2lkdGhTdmc7XG5cbiAgICAgIGlmICghY3VycmVudEVsZW1lbnQuYnJhbmNoZXMgfHwgIWN1cnJlbnRFbGVtZW50LmJyYW5jaGVzLmxlbmd0aCkge1xuICAgICAgICAvLyBFbGVtZW50IGtow7RuZyBjw7MgbmjDoW5oOiB24bq9IMSRxrDhu51uZyB0aOG6s25nIG5nYW5nXG4gICAgICAgIGNvbnN0IGRyYXdGb3JtVG9XaWR0aEV4aXQgPSAoY3VycmVudEVsZW1lbnQuc3ViQ29kZU9mRWxlbWVudCB8fCBjdXJyZW50RWxlbWVudC5jb2RlKSA9PT0gY2FudmFzQ29uZmlnUmVhZG9ubHkoKS5UWVBFX0VMRU1FTlRfRVhJVCA/IChjdXJyZW50RWxlbWVudC5zcGVjaWZpY193aWR0aCA/PyAwKSAvIDIgOiBsaW5lQmV0d2VlbkVsZW1lbnRzO1xuXG4gICAgICAgIGN1cnJlbnRFbGVtZW50LmF0dHJpYnV0ZVN2Z0QgPSBgTSAke2N1cnJlbnRFbGVtZW50LnNwZWNpZmljX3ggPz8gMH0gJHt0b3AgKyAoY3VycmVudEVsZW1lbnQuc3BlY2lmaWNfaGVpZ2h0ID8/IDApIC8gMn0gbCAke2RyYXdGb3JtVG9XaWR0aEV4aXR9IDBgO1xuICAgICAgICBjdXJyZW50RWxlbWVudC5wb3NpdGlvbl9lbmQgPSAoY3VycmVudEVsZW1lbnQuc3BlY2lmaWNfeCA/PyAwKSArIGxpbmVCZXR3ZWVuRWxlbWVudHM7XG5cbiAgICAgICAgaWYgKGN1cnJlbnRFbGVtZW50Lm5vZGVPdGhlckNvbmZpZykge1xuICAgICAgICAgIGNvbnN0IHdhaXRXaWR0aCA9IHRoaXMuZ2V0V2lkdGhXYWl0Q29uZmlnKGN1cnJlbnRFbGVtZW50Lm5vZGVPdGhlckNvbmZpZyk7XG4gICAgICAgICAgY29uc3QgZGlzdGFuY2VFbGVtZW50VG9XYWl0ID0gKGN1cnJlbnRFbGVtZW50LnNwZWNpZmljX3dpZHRoID8/IDApICsgY2FudmFzQ29uZmlnUmVhZG9ubHkoKS5ESVNUQU5DRV9UT19XQUlUO1xuICAgICAgICAgIGNvbnN0IGxlZnRTdGFydExpbmUyID0gKGN1cnJlbnRFbGVtZW50LnNwZWNpZmljX3ggPz8gMCkgKyBkaXN0YW5jZUVsZW1lbnRUb1dhaXQgKyB3YWl0V2lkdGg7XG5cbiAgICAgICAgICBjdXJyZW50RWxlbWVudC5hdHRyaWJ1dGVTdmdEID0gYE0gJHtjdXJyZW50RWxlbWVudC5zcGVjaWZpY194ID8/IDB9ICR7dG9wICsgKGN1cnJlbnRFbGVtZW50LnNwZWNpZmljX2hlaWdodCA/PyAwKSAvIDJ9IGwgJHtkaXN0YW5jZUVsZW1lbnRUb1dhaXR9IDBgO1xuICAgICAgICAgIGN1cnJlbnRFbGVtZW50LnBvc2l0aW9uX2VuZCA9IGxlZnRTdGFydExpbmUyICsgbGluZUJldHdlZW5FbGVtZW50cztcblxuICAgICAgICAgIGN1cnJlbnRFbGVtZW50Lm5vZGVPdGhlckNvbmZpZy5zcGVjaWZpY194ID0gKGN1cnJlbnRFbGVtZW50LnNwZWNpZmljX3ggPz8gMCkgKyBkaXN0YW5jZUVsZW1lbnRUb1dhaXQ7XG4gICAgICAgICAgLy8gc3BlY2lmaWNfeSA9IHTDom0gWSBj4bunYSDEkcaw4budbmcgbGluZSDigJQgc2V0VHJhbnNsYXRlUG9zaXRpb25zIHPhur0gdHLhu6sgaGVpZ2h0LzIgxJHhu4MgY8SDbiBnaeG7r2EgZOG7jWNcbiAgICAgICAgICBjdXJyZW50RWxlbWVudC5ub2RlT3RoZXJDb25maWcuc3BlY2lmaWNfeSA9IHRvcCArIChjdXJyZW50RWxlbWVudC5zcGVjaWZpY19oZWlnaHQgPz8gMCkgLyAyO1xuICAgICAgICAgIC8vIMSQ4bqjbSBi4bqjbyBjw7Mga8OtY2ggdGjGsOG7m2MgxJHhu4Mgc2V0VHJhbnNsYXRlUG9zaXRpb25zIHTDrW5oIG9mZnNldCDEkcO6bmdcbiAgICAgICAgICBpZiAoIWN1cnJlbnRFbGVtZW50Lm5vZGVPdGhlckNvbmZpZy5zcGVjaWZpY19oZWlnaHQpIHtcbiAgICAgICAgICAgIGN1cnJlbnRFbGVtZW50Lm5vZGVPdGhlckNvbmZpZy5zcGVjaWZpY19oZWlnaHQgPSBjYW52YXNDb25maWdSZWFkb25seSgpLkVMRU1FTlRfV0FJVF9ERUZBVUxUO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIWN1cnJlbnRFbGVtZW50Lm5vZGVPdGhlckNvbmZpZy5zcGVjaWZpY193aWR0aCkge1xuICAgICAgICAgICAgY3VycmVudEVsZW1lbnQubm9kZU90aGVyQ29uZmlnLnNwZWNpZmljX3dpZHRoID0gY2FudmFzQ29uZmlnUmVhZG9ubHkoKS5FTEVNRU5UX1dBSVRfREVGQVVMVDtcbiAgICAgICAgICB9XG4gICAgICAgICAgZGVsZXRlIGN1cnJlbnRFbGVtZW50Lm5vZGVPdGhlckNvbmZpZy5hdHRyaWJ1dGVTdmdEO1xuXG4gICAgICAgICAgaWYgKGN1cnJlbnRFbGVtZW50LnN1YkNvZGVPZkVsZW1lbnQgIT09IGNhbnZhc0NvbmZpZ1JlYWRvbmx5KCkuVFlQRV9FTEVNRU5UX0VYSVQpIHtcbiAgICAgICAgICAgIGN1cnJlbnRFbGVtZW50Lm5vZGVPdGhlckNvbmZpZy5hdHRyaWJ1dGVTdmdEID0gYE0gJHtsZWZ0U3RhcnRMaW5lMn0gJHt0b3AgKyAoY3VycmVudEVsZW1lbnQuc3BlY2lmaWNfaGVpZ2h0ID8/IDApIC8gMn0gbCAke2NhbnZhc0NvbmZpZ1JlYWRvbmx5KCkuV0FJVF9UT19FTEVNRU5UfSAwYDtcbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIC8vIEVsZW1lbnRzIGPDsyBuaMOhbmhcbiAgICAgIGNvbnN0IGhhbGYgPSBNYXRoLmNlaWwoY3VycmVudEVsZW1lbnQuYnJhbmNoZXMubGVuZ3RoIC8gMik7XG4gICAgICBjb25zdCBhYm92ZUhhbGYgPSBjdXJyZW50RWxlbWVudC5icmFuY2hlcy5zbGljZSgwLCBoYWxmKTtcbiAgICAgIGNvbnN0IHVuZGVySGFsZiA9IGN1cnJlbnRFbGVtZW50LmJyYW5jaGVzLnNsaWNlKGhhbGYpO1xuICAgICAgbGV0IGJyYWNoTWlkZGxlOiBJRGlhZ3JhbUVsZW1lbnRCcmFuY2ggfCB1bmRlZmluZWQ7XG5cbiAgICAgIGlmIChhYm92ZUhhbGYubGVuZ3RoICE9PSB1bmRlckhhbGYubGVuZ3RoKSB7XG4gICAgICAgIGJyYWNoTWlkZGxlID0gYWJvdmVIYWxmLnBvcCgpO1xuICAgICAgfVxuXG4gICAgICAvLyBUw41OSCBDSEnhu4BVIENBTyBU4buQSSDEkEEgQ+G7pkEgTkjDgU5IICjEkcOieSBsw6AgY2hp4buBdSBy4buZbmcgdHJvbmcgaG9yaXpvbnRhbCBjb250ZXh0IG5oxrBuZ1xuICAgICAgLy8gZMO5bmcgY2h1bmcgbWF4SGVpZ2h0QnJhbmNoIMSR4buDIMSRxqFuIGdp4bqjbiwgw70gbmdoxKlhIGzDoCBcImtob+G6o25nIHRy4buRbmcgdOG7kWkgdGhp4buDdSBkw6BuaCBjaG8gbmjDoW5oIGtow7RuZyBjw7MgZWxlbWVudFwiKVxuICAgICAgY29uc3QgbWF4V2lkdGhCcmFuY2ggPSB7IHdpZHRoOiAwIH07XG5cbiAgICAgIHRoaXMuY2FsY3VsYXRvck1heEJyYW5jaFdpZHRoKGN1cnJlbnRFbGVtZW50LCBtYXhXaWR0aEJyYW5jaCk7XG4gICAgICBjdXJyZW50RWxlbWVudC5tYXhIZWlnaHRCcmFuY2ggPSBtYXhXaWR0aEJyYW5jaC53aWR0aDtcblxuICAgICAgY29uc3QgbWF4V2lkdGhCcmFjaE1pZGRsZSA9IHsgd2lkdGg6IDAsIGFib3ZlV2lkdGg6IDAsIHVuZGVyV2lkdGg6IDAgfTtcbiAgICAgIGNvbnN0IGxpbmVGb3JtRWxlbWVudFRvQnJhbmNoaW5nID0gKGN1cnJlbnRFbGVtZW50LnNwZWNpZmljX3dpZHRoID8/IDApICsgY2FudmFzQ29uZmlnUmVhZG9ubHkoKS5FTEVNRU5UX01BUkdJTl9ERUZBVUxUX0JSQU5DSDtcblxuICAgICAgLy8gdG9wID0geSArIGhlaWdodC8yOiDEkWnhu4NtIGdp4buvYSB0aGVvIGNoaeG7gXUgWSDihpIgZMO5bmcgbMOgbSB04buNYSDEkeG7mSBZIGPhu6dhIMSRxrDhu51uZyBuZ2FuZyBjaMOtbmhcbiAgICAgIGNvbnN0IHRvcE1pZCA9IHRvcCArIChjdXJyZW50RWxlbWVudC5zcGVjaWZpY19oZWlnaHQgPz8gMCkgLyAyO1xuXG4gICAgICBpZiAoYnJhY2hNaWRkbGUpIHtcbiAgICAgICAgYnJhY2hNaWRkbGUub25UaGVTaWRlID0gJ2NlbnRlcic7XG4gICAgICAgIHRoaXMuY2FsY3VsYXRvckhlaWdodEJyYW5jaChicmFjaE1pZGRsZS5lbGVtZW50cywgbWF4V2lkdGhCcmFjaE1pZGRsZSk7XG4gICAgICAgIGJyYWNoTWlkZGxlLndpZHRoQnJhbmNoID0ge1xuICAgICAgICAgIHdpZHRoOiBtYXhXaWR0aEJyYWNoTWlkZGxlLndpZHRoLFxuICAgICAgICAgIGFib3ZlOiBtYXhXaWR0aEJyYWNoTWlkZGxlLmFib3ZlV2lkdGgsXG4gICAgICAgICAgdW5kZXI6IG1heFdpZHRoQnJhY2hNaWRkbGUudW5kZXJXaWR0aCxcbiAgICAgICAgfTtcbiAgICAgICAgTW9MaWJEaWFncmFtSG9yaXpvbnRhbENhbGN1bGF0b3JCcmFuY2hVdGlsLmRyYXdTdHJhaWdodExpbmUodG9wTWlkLCBsaW5lRm9ybUVsZW1lbnRUb0JyYW5jaGluZywgY3VycmVudEVsZW1lbnQuc3BlY2lmaWNfeCA/PyAwLCBicmFjaE1pZGRsZSwgbWF4V2lkdGhCcmFuY2gud2lkdGgsIGNvbmZpZyk7XG4gICAgICB9XG5cbiAgICAgIGxldCBoYXNOZXh0U2FtZVBhcmVudEVsZW1lbnROZXh0ID0gZmFsc2U7XG4gICAgICBjb25zdCBhYm92ZUhhbGZSZXZlcnNlID0gYWJvdmVIYWxmLnJldmVyc2UoKTtcblxuICAgICAgYWJvdmVIYWxmUmV2ZXJzZS5mb3JFYWNoKChicmFuY2gsIGluZGV4QnJhbmNoKSA9PiB7XG4gICAgICAgIGlmICghaGFzTmV4dFNhbWVQYXJlbnRFbGVtZW50TmV4dCkge1xuICAgICAgICAgIGNvbnN0IGZsYXRFbGVtZW50T25CcmFuY2g6IElEaWFncmFtRWxlbWVudFtdID0gW107XG5cbiAgICAgICAgICBidWlsZEZsYXRFbGVtZW50KGJyYW5jaC5lbGVtZW50cywgZmxhdEVsZW1lbnRPbkJyYW5jaCk7XG4gICAgICAgICAgaGFzTmV4dFNhbWVQYXJlbnRFbGVtZW50TmV4dCA9ICFmbGF0RWxlbWVudE9uQnJhbmNoIHx8ICFmbGF0RWxlbWVudE9uQnJhbmNoLmxlbmd0aCA/IHRydWUgOiBmbGF0RWxlbWVudE9uQnJhbmNoLmZpbmQoKGl0ZW0pID0+IGl0ZW0ubmV4dF9pZCA9PT0gY3VycmVudEVsZW1lbnQubmV4dF9pZCkgPyB0cnVlIDogZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBicmFuY2gub25UaGVTaWRlID0gJ2Fib3ZlJztcbiAgICAgICAgY29uc3QgbWF4V2lkdGhCID0geyB3aWR0aDogMCwgYWJvdmVXaWR0aDogMCwgdW5kZXJXaWR0aDogMCB9O1xuXG4gICAgICAgIHRoaXMuY2FsY3VsYXRvckhlaWdodEJyYW5jaChicmFuY2guZWxlbWVudHMsIG1heFdpZHRoQik7XG4gICAgICAgIGJyYW5jaC53aWR0aEJyYW5jaCA9IHtcbiAgICAgICAgICB3aWR0aDogbWF4V2lkdGhCLndpZHRoLFxuICAgICAgICAgIGFib3ZlOiBtYXhXaWR0aEIuYWJvdmVXaWR0aCxcbiAgICAgICAgICB1bmRlcjogbWF4V2lkdGhCLnVuZGVyV2lkdGgsXG4gICAgICAgIH07XG5cbiAgICAgICAgY29uc3QgYnJhbmNoUHJlID0gYWJvdmVIYWxmUmV2ZXJzZVtpbmRleEJyYW5jaCAtIDFdO1xuICAgICAgICBsZXQgbGluZUJldHdlZW5CcmFuY2ggPSBtYXhXaWR0aEIudW5kZXJXaWR0aCArIGNhbnZhc0NvbmZpZ1JlYWRvbmx5KCkuRUxFTUVOVF9NQVJHSU5fQkVUV0VFTl9CUkFOQ0hfREVGQVVMVCAvIDI7XG5cbiAgICAgICAgaWYgKGJyYW5jaFByZSkge1xuICAgICAgICAgIGxpbmVCZXR3ZWVuQnJhbmNoICs9IChicmFuY2hQcmUud2lkdGhCcmFuY2g/LndpZHRoID8/IDApICsgY2FudmFzQ29uZmlnUmVhZG9ubHkoKS5FTEVNRU5UX01BUkdJTl9CRVRXRUVOX0JSQU5DSF9ERUZBVUxUO1xuICAgICAgICB9XG4gICAgICAgIGlmIChicmFjaE1pZGRsZSkge1xuICAgICAgICAgIGxpbmVCZXR3ZWVuQnJhbmNoICs9IChicmFjaE1pZGRsZS53aWR0aEJyYW5jaD8uYWJvdmUgPz8gMCkgKyBjYW52YXNDb25maWdSZWFkb25seSgpLkVMRU1FTlRfTUFSR0lOX0JFVFdFRU5fQlJBTkNIX0RFRkFVTFQgLyAyO1xuICAgICAgICB9XG5cbiAgICAgICAgTW9MaWJEaWFncmFtSG9yaXpvbnRhbENhbGN1bGF0b3JCcmFuY2hVdGlsLmFib3ZlTGluZSh0b3BNaWQsIGxpbmVGb3JtRWxlbWVudFRvQnJhbmNoaW5nLCBjdXJyZW50RWxlbWVudC5zcGVjaWZpY194ID8/IDAsIGxpbmVCZXR3ZWVuQnJhbmNoLCBicmFuY2gsIG1heFdpZHRoQnJhbmNoLndpZHRoLCBjdXJyZW50RWxlbWVudCwgY29uZmlnKTtcbiAgICAgIH0pO1xuXG4gICAgICB1bmRlckhhbGYuZm9yRWFjaCgoYnJhbmNoLCBpbmRleEJyYW5jaCkgPT4ge1xuICAgICAgICBpZiAoIWhhc05leHRTYW1lUGFyZW50RWxlbWVudE5leHQpIHtcbiAgICAgICAgICBjb25zdCBmbGF0RWxlbWVudE9uQnJhbmNoOiBJRGlhZ3JhbUVsZW1lbnRbXSA9IFtdO1xuXG4gICAgICAgICAgYnVpbGRGbGF0RWxlbWVudChicmFuY2guZWxlbWVudHMsIGZsYXRFbGVtZW50T25CcmFuY2gpO1xuICAgICAgICAgIGhhc05leHRTYW1lUGFyZW50RWxlbWVudE5leHQgPSAhZmxhdEVsZW1lbnRPbkJyYW5jaCB8fCAhZmxhdEVsZW1lbnRPbkJyYW5jaC5sZW5ndGggPyB0cnVlIDogZmxhdEVsZW1lbnRPbkJyYW5jaC5maW5kKChpdGVtKSA9PiBpdGVtLm5leHRfaWQgPT09IGN1cnJlbnRFbGVtZW50Lm5leHRfaWQpID8gdHJ1ZSA6IGZhbHNlO1xuICAgICAgICB9XG4gICAgICAgIGJyYW5jaC5vblRoZVNpZGUgPSAndW5kZXInO1xuICAgICAgICBjb25zdCBtYXhXaWR0aEIgPSB7IHdpZHRoOiAwLCBhYm92ZVdpZHRoOiAwLCB1bmRlcldpZHRoOiAwIH07XG5cbiAgICAgICAgdGhpcy5jYWxjdWxhdG9ySGVpZ2h0QnJhbmNoKGJyYW5jaC5lbGVtZW50cywgbWF4V2lkdGhCKTtcbiAgICAgICAgYnJhbmNoLndpZHRoQnJhbmNoID0ge1xuICAgICAgICAgIHdpZHRoOiBtYXhXaWR0aEIud2lkdGgsXG4gICAgICAgICAgYWJvdmU6IG1heFdpZHRoQi5hYm92ZVdpZHRoLFxuICAgICAgICAgIHVuZGVyOiBtYXhXaWR0aEIudW5kZXJXaWR0aCxcbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBicmFuY2hQcmUgPSB1bmRlckhhbGZbaW5kZXhCcmFuY2ggLSAxXTtcbiAgICAgICAgbGV0IGxpbmVCZXR3ZWVuQnJhbmNoID0gbWF4V2lkdGhCLmFib3ZlV2lkdGggKyBjYW52YXNDb25maWdSZWFkb25seSgpLkVMRU1FTlRfTUFSR0lOX0JFVFdFRU5fQlJBTkNIX0RFRkFVTFQgLyAyO1xuXG4gICAgICAgIGlmIChicmFuY2hQcmUpIHtcbiAgICAgICAgICBsaW5lQmV0d2VlbkJyYW5jaCArPSAoYnJhbmNoUHJlLndpZHRoQnJhbmNoPy53aWR0aCA/PyAwKSArIGNhbnZhc0NvbmZpZ1JlYWRvbmx5KCkuRUxFTUVOVF9NQVJHSU5fQkVUV0VFTl9CUkFOQ0hfREVGQVVMVDtcbiAgICAgICAgfVxuICAgICAgICBpZiAoYnJhY2hNaWRkbGUpIHtcbiAgICAgICAgICBsaW5lQmV0d2VlbkJyYW5jaCArPSAoYnJhY2hNaWRkbGUud2lkdGhCcmFuY2g/LnVuZGVyID8/IDApICsgY2FudmFzQ29uZmlnUmVhZG9ubHkoKS5FTEVNRU5UX01BUkdJTl9CRVRXRUVOX0JSQU5DSF9ERUZBVUxUIC8gMjtcbiAgICAgICAgfVxuXG4gICAgICAgIE1vTGliRGlhZ3JhbUhvcml6b250YWxDYWxjdWxhdG9yQnJhbmNoVXRpbC51bmRlckxpbmUodG9wTWlkLCBsaW5lRm9ybUVsZW1lbnRUb0JyYW5jaGluZywgY3VycmVudEVsZW1lbnQuc3BlY2lmaWNfeCA/PyAwLCBsaW5lQmV0d2VlbkJyYW5jaCwgYnJhbmNoLCBtYXhXaWR0aEJyYW5jaC53aWR0aCwgY3VycmVudEVsZW1lbnQsIGNvbmZpZyk7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIHRoaXMuc2V0VHJhbnNsYXRlUG9zaXRpb25zKGVsZW1lbnRzKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdHJhbnNsYXRlWC9ZIGNobyB04bqldCBj4bqjIGVsZW1lbnRzIChiYW8gZ+G7k20gYnJhbmNoZXMgdsOgIG5vZGVPdGhlckNvbmZpZylcbiAgICovXG4gIHByaXZhdGUgc3RhdGljIHNldFRyYW5zbGF0ZVBvc2l0aW9ucyhlbGVtZW50czogQXJyYXk8SURpYWdyYW1FbGVtZW50Pikge1xuICAgIGVsZW1lbnRzLmZvckVhY2goKGVsZW1lbnQpID0+IHtcbiAgICAgIGVsZW1lbnQudHJhbnNsYXRlWCA9IGVsZW1lbnQuc3BlY2lmaWNfeDtcbiAgICAgIGVsZW1lbnQudHJhbnNsYXRlWSA9IGVsZW1lbnQuc3BlY2lmaWNfeTtcblxuICAgICAgaWYgKGVsZW1lbnQubm9kZU90aGVyQ29uZmlnKSB7XG4gICAgICAgIGNvbnN0IG9mZnNldFkgPSAoZWxlbWVudC5ub2RlT3RoZXJDb25maWcuc3BlY2lmaWNfaGVpZ2h0ID8/IDApIC8gMjtcblxuICAgICAgICBlbGVtZW50Lm5vZGVPdGhlckNvbmZpZy50cmFuc2xhdGVYID0gZWxlbWVudC5ub2RlT3RoZXJDb25maWcuc3BlY2lmaWNfeDtcbiAgICAgICAgZWxlbWVudC5ub2RlT3RoZXJDb25maWcudHJhbnNsYXRlWSA9IChlbGVtZW50Lm5vZGVPdGhlckNvbmZpZy5zcGVjaWZpY195ID8/IDApIC0gb2Zmc2V0WTtcbiAgICAgIH1cblxuICAgICAgaWYgKGVsZW1lbnQuYnJhbmNoZXMgJiYgZWxlbWVudC5icmFuY2hlcy5sZW5ndGggPiAwKSB7XG4gICAgICAgIGVsZW1lbnQuYnJhbmNoZXMuZm9yRWFjaCgoYnJhbmNoKSA9PiB7XG4gICAgICAgICAgaWYgKGJyYW5jaC5ub2RlT3RoZXJDb25maWcpIHtcbiAgICAgICAgICAgIGNvbnN0IG9mZnNldFkgPSAoYnJhbmNoLm5vZGVPdGhlckNvbmZpZy5zcGVjaWZpY19oZWlnaHQgPz8gMCkgLyAyO1xuXG4gICAgICAgICAgICBicmFuY2gubm9kZU90aGVyQ29uZmlnLnRyYW5zbGF0ZVggPSBicmFuY2gubm9kZU90aGVyQ29uZmlnLnNwZWNpZmljX3g7XG4gICAgICAgICAgICBicmFuY2gubm9kZU90aGVyQ29uZmlnLnRyYW5zbGF0ZVkgPSAoYnJhbmNoLm5vZGVPdGhlckNvbmZpZy5zcGVjaWZpY195ID8/IDApIC0gb2Zmc2V0WTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAoYnJhbmNoLmVsZW1lbnRzICYmIGJyYW5jaC5lbGVtZW50cy5sZW5ndGggPiAwKSB7XG4gICAgICAgICAgICB0aGlzLnNldFRyYW5zbGF0ZVBvc2l0aW9ucyhicmFuY2guZWxlbWVudHMpO1xuICAgICAgICAgIH1cbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICAvKiogVMOtbmggY2hp4buBdSBy4buZbmcgdOG7kWkgxJFhIGPhu6dhIG5ow6FuaCAodHJvbmcgaG9yaXpvbnRhbCA9IGNoaeG7gXUgY2FvIHRo4buxYyBj4bunYSBuaMOhbmgga2jDtG5nIGPDsyBlbGVtZW50KSAqL1xuICBzdGF0aWMgY2FsY3VsYXRvck1heEJyYW5jaFdpZHRoKGVsZW1lbnQ6IElEaWFncmFtRWxlbWVudCwgbWF4V2lkdGhCcmFuY2g6IHsgd2lkdGg6IG51bWJlciB9KSB7XG4gICAgaWYgKCFlbGVtZW50LmJyYW5jaGVzIHx8ICFlbGVtZW50LmJyYW5jaGVzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGVsZW1lbnQuYnJhbmNoZXMuZm9yRWFjaCgoYnJhbmNoKSA9PiB7XG4gICAgICBpZiAoIWJyYW5jaC5lbGVtZW50cyB8fCAhYnJhbmNoLmVsZW1lbnRzLmxlbmd0aCkge1xuICAgICAgICBjb25zdCBsaW5lQnJhbmNoTm9IYXNFbGVtZW50ID0gY2FudmFzQ29uZmlnUmVhZG9ubHkoKS5FTEVNRU5UX1dJRFRIX0RFRkFVTFRfQlJBTkNIX1dIRU5fTk9UX0VMRU1FTlQ7XG5cbiAgICAgICAgbWF4V2lkdGhCcmFuY2gud2lkdGggPSBsaW5lQnJhbmNoTm9IYXNFbGVtZW50ID4gbWF4V2lkdGhCcmFuY2gud2lkdGggPyBsaW5lQnJhbmNoTm9IYXNFbGVtZW50IDogbWF4V2lkdGhCcmFuY2gud2lkdGg7XG5cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB0b3RhbCA9IHsgaGVpZ2h0OiAwIH07XG5cbiAgICAgIHRoaXMucGx1c1dpZHRoRWxlbWVudEluQnJhbmNoKGJyYW5jaC5lbGVtZW50cywgdG90YWwpO1xuICAgICAgbWF4V2lkdGhCcmFuY2gud2lkdGggPSB0b3RhbC5oZWlnaHQgPiBtYXhXaWR0aEJyYW5jaC53aWR0aCA/IHRvdGFsLmhlaWdodCA6IG1heFdpZHRoQnJhbmNoLndpZHRoO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqIFTDrW5oIHThu5VuZyBjaGnhu4F1IHLhu5luZyBjw6FjIGVsZW1lbnRzIHRyb25nIG5ow6FuaCAoZOG7jWMgdGhlbyB0cuG7pWMgWCkgKi9cbiAgc3RhdGljIHBsdXNXaWR0aEVsZW1lbnRJbkJyYW5jaChlbGVtZW50czogSURpYWdyYW1FbGVtZW50W10sIHRvdGFsOiB7IGhlaWdodDogbnVtYmVyIH0pIHtcbiAgICBlbGVtZW50cy5mb3JFYWNoKChlbGVtZW50KSA9PiB7XG4gICAgICBjb25zdCBtYXJnaW4gPSAhZWxlbWVudC5icmFuY2hlcyB8fCAhZWxlbWVudC5icmFuY2hlcy5sZW5ndGggPyB0aGlzLmNoZWNrRWxlbWVudEdldE1hcmdpbihlbGVtZW50Lm5vZGVPdGhlckNvbmZpZykgOiBjYW52YXNDb25maWdSZWFkb25seSgpLkVMRU1FTlRfTUFSR0lOX0RFRkFVTFRfQlJBTkNIO1xuXG4gICAgICB0b3RhbC5oZWlnaHQgKz0gKGVsZW1lbnQuc3BlY2lmaWNfd2lkdGggPz8gMCkgKyBtYXJnaW47XG4gICAgICBpZiAoIWVsZW1lbnQuYnJhbmNoZXMgfHwgIWVsZW1lbnQuYnJhbmNoZXMubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHRvdGFsLmhlaWdodCArPSA2NDtcbiAgICAgIGNvbnN0IHRoZU1vc3RFbGVtZW50c0luQnJhbmNoID0geyBoZWlnaHQ6IDAgfTtcblxuICAgICAgZWxlbWVudC5icmFuY2hlcy5mb3JFYWNoKChicmFuY2gpID0+IHtcbiAgICAgICAgY29uc3Qgd2lkdGhJbkJyYW5jaCA9IHsgaGVpZ2h0OiAwIH07XG5cbiAgICAgICAgd2lkdGhJbkJyYW5jaC5oZWlnaHQgKz0gY2FudmFzQ29uZmlnUmVhZG9ubHkoKS5FTEVNRU5UX01BUkdJTl9ERUZBVUxUX0JSQU5DSF9UT19FTEVNRU5UX0ZJUlNUICsgMjA7XG4gICAgICAgIGlmICghYnJhbmNoLmVsZW1lbnRzIHx8ICFicmFuY2guZWxlbWVudHMubGVuZ3RoKSB7XG4gICAgICAgICAgd2lkdGhJbkJyYW5jaC5oZWlnaHQgKz0gY2FudmFzQ29uZmlnUmVhZG9ubHkoKS5FTEVNRU5UX1dJRFRIX0RFRkFVTFRfQlJBTkNIX1dIRU5fTk9UX0VMRU1FTlQ7XG4gICAgICAgICAgaWYgKHRoZU1vc3RFbGVtZW50c0luQnJhbmNoLmhlaWdodCA8IHdpZHRoSW5CcmFuY2guaGVpZ2h0KSB7XG4gICAgICAgICAgICB0aGVNb3N0RWxlbWVudHNJbkJyYW5jaC5oZWlnaHQgPSB3aWR0aEluQnJhbmNoLmhlaWdodDtcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIHRoaXMucGx1c1dpZHRoRWxlbWVudEluQnJhbmNoKGJyYW5jaC5lbGVtZW50cywgd2lkdGhJbkJyYW5jaCk7XG4gICAgICAgIGlmICh0aGVNb3N0RWxlbWVudHNJbkJyYW5jaC5oZWlnaHQgPCB3aWR0aEluQnJhbmNoLmhlaWdodCkge1xuICAgICAgICAgIHRoZU1vc3RFbGVtZW50c0luQnJhbmNoLmhlaWdodCA9IHdpZHRoSW5CcmFuY2guaGVpZ2h0O1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgdG90YWwuaGVpZ2h0ICs9IHRoZU1vc3RFbGVtZW50c0luQnJhbmNoLmhlaWdodDtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUw61uaCBjaGnhu4F1IGNhbyAoWSBzcGFuKSBj4bunYSBt4buZdCBuaMOhbmgg4oCUIGTDuW5nIMSR4buDIG9mZnNldCBjw6FjIG5ow6FuaCB0csOqbi9kxrDhu5tpLlxuICAgKiBUcm9uZyBob3Jpem9udGFsIGNvbnRleHQ6IG3hu5dpIG5ow6FuaCB0cuG6o2kgZMOgaSB0aGVvIFkgKGzDqm4veHXhu5FuZykuXG4gICAqL1xuICBzdGF0aWMgY2FsY3VsYXRvckhlaWdodEJyYW5jaChlbGVtZW50czogSURpYWdyYW1FbGVtZW50W10gfCB1bmRlZmluZWQsIG1heFdpZHRoOiB7IHdpZHRoOiBudW1iZXI7IGFib3ZlV2lkdGg6IG51bWJlcjsgdW5kZXJXaWR0aDogbnVtYmVyIH0pIHtcbiAgICBpZiAoIWVsZW1lbnRzIHx8ICFlbGVtZW50cy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHcgPSBjYW52YXNDb25maWdSZWFkb25seSgpLkRFRkFVTFRfQlJBTkNIX1dIRU5fTk9fRUxFTUVOVDtcblxuICAgICAgbWF4V2lkdGgud2lkdGggPSB3O1xuICAgICAgbWF4V2lkdGguYWJvdmVXaWR0aCA9IHcgLyAyO1xuICAgICAgbWF4V2lkdGgudW5kZXJXaWR0aCA9IHcgLyAyO1xuXG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgbWF4V2lkdGhJbkVsZW1lbnRzID0geyB3aWR0aDogMCwgYWJvdmVXaWR0aDogMCwgdW5kZXJXaWR0aDogMCB9O1xuXG4gICAgZWxlbWVudHMuZm9yRWFjaCgoZWxlbWVudCkgPT4ge1xuICAgICAgaWYgKCFlbGVtZW50LmJyYW5jaGVzIHx8ICFlbGVtZW50LmJyYW5jaGVzLmxlbmd0aCkge1xuICAgICAgICAvLyBlbGVtZW50IGtow7RuZyBuaMOhbmg6IGTDuW5nIHNwZWNpZmljX2hlaWdodCBsw6BtIFkgc3BhblxuICAgICAgICBpZiAoKGVsZW1lbnQuc3BlY2lmaWNfaGVpZ2h0ID8/IDApIDwgbWF4V2lkdGhJbkVsZW1lbnRzLndpZHRoKSB7XG4gICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IGggPSBlbGVtZW50LnNwZWNpZmljX2hlaWdodCA/PyAwO1xuXG4gICAgICAgIG1heFdpZHRoSW5FbGVtZW50cy53aWR0aCA9IGg7XG4gICAgICAgIG1heFdpZHRoSW5FbGVtZW50cy5hYm92ZVdpZHRoID0gaCAvIDI7XG4gICAgICAgIG1heFdpZHRoSW5FbGVtZW50cy51bmRlcldpZHRoID0gaCAvIDI7XG5cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB3aWR0aEVsZW1lbnRJbmNsdWRlQnJhbmNoID0geyB3aWR0aDogMCwgYWJvdmVXaWR0aDogMCwgdW5kZXJXaWR0aDogMCB9O1xuICAgICAgY29uc3QgaCA9IGVsZW1lbnQuc3BlY2lmaWNfaGVpZ2h0ID8/IDA7XG5cbiAgICAgIGlmIChoID4gd2lkdGhFbGVtZW50SW5jbHVkZUJyYW5jaC53aWR0aCkge1xuICAgICAgICB3aWR0aEVsZW1lbnRJbmNsdWRlQnJhbmNoLndpZHRoID0gaDtcbiAgICAgICAgd2lkdGhFbGVtZW50SW5jbHVkZUJyYW5jaC5hYm92ZVdpZHRoID0gaCAvIDI7XG4gICAgICAgIHdpZHRoRWxlbWVudEluY2x1ZGVCcmFuY2gudW5kZXJXaWR0aCA9IGggLyAyO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBoYWxmID0gTWF0aC5jZWlsKGVsZW1lbnQuYnJhbmNoZXMubGVuZ3RoIC8gMik7XG4gICAgICBjb25zdCBhYm92ZUhhbGYgPSBlbGVtZW50LmJyYW5jaGVzLnNsaWNlKDAsIGhhbGYpO1xuICAgICAgY29uc3QgdW5kZXJIYWxmID0gZWxlbWVudC5icmFuY2hlcy5zbGljZShoYWxmKTtcbiAgICAgIGxldCBicmFjaE1pZGRsZTogSURpYWdyYW1FbGVtZW50QnJhbmNoIHwgdW5kZWZpbmVkO1xuXG4gICAgICBpZiAoYWJvdmVIYWxmLmxlbmd0aCAhPT0gdW5kZXJIYWxmLmxlbmd0aCkge1xuICAgICAgICBicmFjaE1pZGRsZSA9IGFib3ZlSGFsZi5wb3AoKTtcbiAgICAgIH1cbiAgICAgIGlmIChicmFjaE1pZGRsZSkgYnJhY2hNaWRkbGUub25UaGVTaWRlID0gJ2NlbnRlcic7XG4gICAgICBhYm92ZUhhbGYuZm9yRWFjaCgoYnJhbmNoKSA9PiAoYnJhbmNoLm9uVGhlU2lkZSA9ICdhYm92ZScpKTtcbiAgICAgIHVuZGVySGFsZi5mb3JFYWNoKChicmFuY2gpID0+IChicmFuY2gub25UaGVTaWRlID0gJ3VuZGVyJykpO1xuXG4gICAgICBjb25zdCB3aWR0aEJyYW5jaCA9IHsgd2lkdGg6IDAsIGFib3ZlV2lkdGg6IDAsIHVuZGVyV2lkdGg6IDAgfTtcblxuICAgICAgZWxlbWVudC5icmFuY2hlcy5mb3JFYWNoKChicmFuY2gpID0+IHtcbiAgICAgICAgY29uc3QgdyA9IHsgd2lkdGg6IDAsIGFib3ZlV2lkdGg6IDAsIHVuZGVyV2lkdGg6IDAgfTtcblxuICAgICAgICB0aGlzLmNhbGN1bGF0b3JIZWlnaHRCcmFuY2goYnJhbmNoLmVsZW1lbnRzLCB3KTtcbiAgICAgICAgc3dpdGNoIChicmFuY2gub25UaGVTaWRlKSB7XG4gICAgICAgICAgY2FzZSAnYWJvdmUnOlxuICAgICAgICAgICAgd2lkdGhCcmFuY2guYWJvdmVXaWR0aCArPSB3LndpZHRoO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAndW5kZXInOlxuICAgICAgICAgICAgd2lkdGhCcmFuY2gudW5kZXJXaWR0aCArPSB3LndpZHRoO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnY2VudGVyJzpcbiAgICAgICAgICAgIHdpZHRoQnJhbmNoLmFib3ZlV2lkdGggKz0gdy5hYm92ZVdpZHRoO1xuICAgICAgICAgICAgd2lkdGhCcmFuY2gudW5kZXJXaWR0aCArPSB3LnVuZGVyV2lkdGg7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IG1hcmdpbkJldHdlZW5CcmFuY2ggPSAoZWxlbWVudC5icmFuY2hlcy5sZW5ndGggLSAxKSAqIGNhbnZhc0NvbmZpZ1JlYWRvbmx5KCkuRUxFTUVOVF9NQVJHSU5fQkVUV0VFTl9CUkFOQ0hfREVGQVVMVDtcblxuICAgICAgd2lkdGhCcmFuY2guYWJvdmVXaWR0aCArPSBtYXJnaW5CZXR3ZWVuQnJhbmNoIC8gMjtcbiAgICAgIHdpZHRoQnJhbmNoLnVuZGVyV2lkdGggKz0gbWFyZ2luQmV0d2VlbkJyYW5jaCAvIDI7XG4gICAgICBjb25zdCBtYXhBYm92ZVdpZHRoID0gTWF0aC5tYXgod2lkdGhFbGVtZW50SW5jbHVkZUJyYW5jaC5hYm92ZVdpZHRoLCB3aWR0aEJyYW5jaC5hYm92ZVdpZHRoKTtcbiAgICAgIGNvbnN0IG1heFVuZGVyV2lkdGggPSBNYXRoLm1heCh3aWR0aEVsZW1lbnRJbmNsdWRlQnJhbmNoLnVuZGVyV2lkdGgsIHdpZHRoQnJhbmNoLnVuZGVyV2lkdGgpO1xuXG4gICAgICBpZiAobWF4V2lkdGhJbkVsZW1lbnRzLmFib3ZlV2lkdGggPCBtYXhBYm92ZVdpZHRoKSB7XG4gICAgICAgIG1heFdpZHRoSW5FbGVtZW50cy5hYm92ZVdpZHRoID0gbWF4QWJvdmVXaWR0aDtcbiAgICAgIH1cbiAgICAgIGlmIChtYXhXaWR0aEluRWxlbWVudHMudW5kZXJXaWR0aCA8IG1heFVuZGVyV2lkdGgpIHtcbiAgICAgICAgbWF4V2lkdGhJbkVsZW1lbnRzLnVuZGVyV2lkdGggPSBtYXhVbmRlcldpZHRoO1xuICAgICAgfVxuXG4gICAgICBtYXhXaWR0aEluRWxlbWVudHMud2lkdGggPSBtYXhXaWR0aEluRWxlbWVudHMuYWJvdmVXaWR0aCArIG1heFdpZHRoSW5FbGVtZW50cy51bmRlcldpZHRoO1xuICAgIH0pO1xuXG4gICAgbWF4V2lkdGgud2lkdGggKz0gbWF4V2lkdGhJbkVsZW1lbnRzLmFib3ZlV2lkdGggKyBtYXhXaWR0aEluRWxlbWVudHMudW5kZXJXaWR0aDtcbiAgICBtYXhXaWR0aC5hYm92ZVdpZHRoICs9IG1heFdpZHRoSW5FbGVtZW50cy5hYm92ZVdpZHRoO1xuICAgIG1heFdpZHRoLnVuZGVyV2lkdGggKz0gbWF4V2lkdGhJbkVsZW1lbnRzLnVuZGVyV2lkdGg7XG4gIH1cblxuICAvKiogVMOtbmgga2hv4bqjbmcgY8OhY2ggdGjDqm0gdsOgbyBzYXUgZWxlbWVudCAoYmFvIGfhu5NtIHdhaXQgY29uZmlnIG7hur91IGPDsykgKi9cbiAgcHJpdmF0ZSBzdGF0aWMgY2hlY2tFbGVtZW50R2V0TWFyZ2luKGhhc1dhaXRDb25maWc/OiBJRGlhZ3JhbUVsZW1lbnQpOiBudW1iZXIge1xuICAgIGlmIChoYXNXYWl0Q29uZmlnKSB7XG4gICAgICByZXR1cm4gY2FudmFzQ29uZmlnUmVhZG9ubHkoKS5ESVNUQU5DRV9UT19XQUlUICsgdGhpcy5nZXRXaWR0aFdhaXRDb25maWcoaGFzV2FpdENvbmZpZykgKyBjYW52YXNDb25maWdSZWFkb25seSgpLldBSVRfVE9fRUxFTUVOVDtcbiAgICB9XG4gICAgcmV0dXJuIGNhbnZhc0NvbmZpZ1JlYWRvbmx5KCkuRUxFTUVOVF9NQVJHSU5fREVGQVVMVDtcbiAgfVxuXG4gIC8qKiBUw61uaCBjaGnhu4F1IHLhu5luZyBj4bunYSB3YWl0IGNvbmZpZyBub2RlICovXG4gIHByaXZhdGUgc3RhdGljIGdldFdpZHRoV2FpdENvbmZpZyhoYXNXYWl0Q29uZmlnPzogSURpYWdyYW1FbGVtZW50KTogbnVtYmVyIHtcbiAgICBpZiAoaGFzV2FpdENvbmZpZykge1xuICAgICAgcmV0dXJuIChoYXNXYWl0Q29uZmlnLnNwZWNpZmljX3dpZHRoID8/IGNhbnZhc0NvbmZpZ1JlYWRvbmx5KCkuRUxFTUVOVF9XQUlUX0RFRkFVTFQpICsgY2FudmFzQ29uZmlnUmVhZG9ubHkoKS5ESVNUQU5DRV9XQUlUX1RPX05FWFRfTElORTtcbiAgICB9XG4gICAgcmV0dXJuIGNhbnZhc0NvbmZpZ1JlYWRvbmx5KCkuRUxFTUVOVF9XQUlUX0RFRkFVTFQgKyBjYW52YXNDb25maWdSZWFkb25seSgpLkRJU1RBTkNFX1dBSVRfVE9fTkVYVF9MSU5FO1xuICB9XG59XG4iXX0=