verben-workflow-ui 0.2.2 → 0.2.4

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 (47) hide show
  1. package/esm2022/lib/components/designer/models/types.mjs +1 -1
  2. package/esm2022/lib/components/designer/services/wf-mapper.service.mjs +3 -3
  3. package/esm2022/lib/components/workflow-designer/conditions-popup/conditions-popup.component.mjs +76 -0
  4. package/esm2022/lib/components/workflow-designer/decision-popup/decision-popup.component.mjs +65 -0
  5. package/esm2022/lib/components/workflow-designer/designer-canvas/designer-canvas.component.mjs +245 -17
  6. package/esm2022/lib/components/workflow-designer/designer-toolbar/designer-toolbar.component.mjs +26 -14
  7. package/esm2022/lib/components/workflow-designer/services/connection.service.mjs +220 -0
  8. package/esm2022/lib/components/workflow-designer/services/node-management.service.mjs +288 -0
  9. package/esm2022/lib/components/workflow-designer/services/popup.service.mjs +235 -0
  10. package/esm2022/lib/components/workflow-designer/services/swimlane.service.mjs +145 -0
  11. package/esm2022/lib/components/workflow-designer/services/transformer.service.mjs +260 -0
  12. package/esm2022/lib/components/workflow-designer/stage-dialog/stage-dialog.component.mjs +67 -11
  13. package/esm2022/lib/components/workflow-designer/stage-node/stage-node.component.mjs +9 -18
  14. package/esm2022/lib/components/workflow-designer/swimlane-dialog/swimlane-dialog.component.mjs +30 -24
  15. package/esm2022/lib/components/workflow-designer/workflow-data.service.mjs +2 -2
  16. package/esm2022/lib/components/workflow-designer/workflow-designer.component.mjs +138 -96
  17. package/esm2022/lib/components/workflow-designer/workflow-designer.module.mjs +27 -3
  18. package/esm2022/lib/components/workflow-designer/workflow-designer.state.mjs +243 -205
  19. package/esm2022/lib/components/workflow-designer/workflow-designer.types.mjs +1 -1
  20. package/esm2022/lib/models/SwimLane.mjs +1 -1
  21. package/esm2022/lib/models/Workflow.mjs +1 -1
  22. package/esm2022/lib/models/WorkflowStage.mjs +1 -1
  23. package/esm2022/lib/services/http-web-request.service.mjs +2 -2
  24. package/fesm2022/verben-workflow-ui.mjs +2644 -1005
  25. package/fesm2022/verben-workflow-ui.mjs.map +1 -1
  26. package/lib/components/designer/models/types.d.ts +1 -1
  27. package/lib/components/workflow-designer/conditions-popup/conditions-popup.component.d.ts +34 -0
  28. package/lib/components/workflow-designer/decision-popup/decision-popup.component.d.ts +26 -0
  29. package/lib/components/workflow-designer/designer-canvas/designer-canvas.component.d.ts +35 -1
  30. package/lib/components/workflow-designer/designer-toolbar/designer-toolbar.component.d.ts +14 -3
  31. package/lib/components/workflow-designer/services/connection.service.d.ts +85 -0
  32. package/lib/components/workflow-designer/services/node-management.service.d.ts +52 -0
  33. package/lib/components/workflow-designer/services/popup.service.d.ts +139 -0
  34. package/lib/components/workflow-designer/services/swimlane.service.d.ts +51 -0
  35. package/lib/components/workflow-designer/services/transformer.service.d.ts +36 -0
  36. package/lib/components/workflow-designer/stage-dialog/stage-dialog.component.d.ts +17 -2
  37. package/lib/components/workflow-designer/stage-node/stage-node.component.d.ts +2 -2
  38. package/lib/components/workflow-designer/swimlane-dialog/swimlane-dialog.component.d.ts +7 -1
  39. package/lib/components/workflow-designer/workflow-designer.component.d.ts +2 -1
  40. package/lib/components/workflow-designer/workflow-designer.module.d.ts +6 -4
  41. package/lib/components/workflow-designer/workflow-designer.state.d.ts +17 -1
  42. package/lib/components/workflow-designer/workflow-designer.types.d.ts +2 -0
  43. package/lib/models/SwimLane.d.ts +1 -0
  44. package/lib/models/Workflow.d.ts +1 -0
  45. package/lib/models/WorkflowStage.d.ts +1 -1
  46. package/package.json +1 -1
  47. package/styles/styles.css +23 -0
@@ -5,6 +5,8 @@ import * as i2 from "../workflow-data.service";
5
5
  import * as i3 from "@angular/common";
6
6
  import * as i4 from "verben-ng-ui";
7
7
  import * as i5 from "../stage-node/stage-node.component";
8
+ import * as i6 from "../stage-dialog/stage-dialog.component";
9
+ import * as i7 from "../conditions-popup/conditions-popup.component";
8
10
  export class DesignerCanvasComponent {
9
11
  state;
10
12
  dataService;
@@ -13,6 +15,7 @@ export class DesignerCanvasComponent {
13
15
  subflowSelected = new EventEmitter();
14
16
  pendingStagePosition = null;
15
17
  showStageDialog = new EventEmitter();
18
+ stagePropertiesUpdated = new EventEmitter();
16
19
  // Reference to the SVG element
17
20
  canvasRef;
18
21
  onWindowMouseUp(event) {
@@ -47,8 +50,20 @@ export class DesignerCanvasComponent {
47
50
  subflowPopupX = 0;
48
51
  subflowPopupY = 0;
49
52
  pendingSubflowPosition = null;
53
+ pendingDecisionConnection = null;
50
54
  pendingConnectionSourcePoint = null;
51
55
  pendingConnectionSourceSwimlaneIndex = null;
56
+ showDecisionConditionDialog = false;
57
+ showConditionsDialog = false;
58
+ activeDecisionNodeId = '';
59
+ activeConnectionId = '';
60
+ decisionConditionPopupX = 0;
61
+ decisionConditionPopupY = 0;
62
+ isCreatingStageFromDecision = false;
63
+ pendingDecisionCondition = '';
64
+ activeStageId = null;
65
+ showStageDialogLocal = false;
66
+ activeStageData = {};
52
67
  constructor(state, dataService) {
53
68
  this.state = state;
54
69
  this.dataService = dataService;
@@ -75,9 +90,59 @@ export class DesignerCanvasComponent {
75
90
  });
76
91
  }
77
92
  }
93
+ onShowShieldDialog(stageId) {
94
+ // Find the node
95
+ const nodeInfo = this.state.findNodeById(stageId);
96
+ if (nodeInfo) {
97
+ this.activeStageId = stageId;
98
+ this.activeStageData = nodeInfo.node.stageData || {};
99
+ this.showStageDialogLocal = true;
100
+ }
101
+ }
102
+ // Add this method to handle dialog closure
103
+ onStageDialogClosed() {
104
+ this.showStageDialogLocal = false;
105
+ this.activeStageId = null;
106
+ this.activeStageData = {};
107
+ }
108
+ // Add this method to handle saving stage data
109
+ onStageDialogSaved(stageData) {
110
+ if (this.activeStageId) {
111
+ // Editing an existing stage
112
+ const nodeInfo = this.state.findNodeById(this.activeStageId);
113
+ if (nodeInfo) {
114
+ // Update the stage data
115
+ nodeInfo.node.stageData = {
116
+ ...nodeInfo.node.stageData,
117
+ ...stageData,
118
+ };
119
+ console.log('Updated stage data:', nodeInfo.node.stageData);
120
+ // Emit event for parent component to know about the update
121
+ this.stagePropertiesUpdated.emit({
122
+ nodeId: this.activeStageId,
123
+ stageData: nodeInfo.node.stageData,
124
+ });
125
+ }
126
+ }
127
+ // Close the dialog
128
+ this.onStageDialogClosed();
129
+ }
78
130
  updateCanvasSize() {
79
131
  const requiredHeight = (this.state.swimlanes.length + 1) * this.swimlaneHeight;
80
132
  this.canvasHeight = Math.max(2000, requiredHeight); // Ensure we have at least our default height
133
+ // Update all the swimlane clip paths when size changes
134
+ setTimeout(() => {
135
+ this.state.swimlanes.forEach((swimlane, index) => {
136
+ const clipPathId = `swimlane-clip-${index}`;
137
+ const clipPathElement = document.getElementById(clipPathId);
138
+ if (clipPathElement) {
139
+ const rectElement = clipPathElement.querySelector('rect');
140
+ if (rectElement) {
141
+ rectElement.setAttribute('width', this.canvasWidth.toString());
142
+ }
143
+ }
144
+ });
145
+ }, 0);
81
146
  }
82
147
  // Helper method to get the mouse position relative to the SVG canvas
83
148
  getMousePosition(event) {
@@ -123,6 +188,15 @@ export class DesignerCanvasComponent {
123
188
  startConnectionDrag(event, point, swimlaneIndex) {
124
189
  event.preventDefault();
125
190
  event.stopPropagation();
191
+ // Check if this is an exit point node
192
+ const nodeInfo = this.state.findNodeById(point.nodeId);
193
+ if (nodeInfo &&
194
+ nodeInfo.node.type === 'stage' &&
195
+ nodeInfo.node.stageData?.IsExitPoint) {
196
+ // Don't allow connections from exit points
197
+ console.log('Cannot create connections from exit points');
198
+ return;
199
+ }
126
200
  const position = this.getMousePosition(event);
127
201
  this.state.startConnectionDrag(point, swimlaneIndex, position.x, position.y);
128
202
  // Add mouse move and mouse up event listeners to the document
@@ -132,8 +206,20 @@ export class DesignerCanvasComponent {
132
206
  // Use arrow functions to preserve 'this' context
133
207
  onMouseMove = (event) => {
134
208
  const position = this.getMousePosition(event);
135
- this.state.updateConnectionDrag(position.x, position.y);
209
+ this.updateConnectionDrag(position.x, position.y);
136
210
  };
211
+ updateConnectionDrag(currentX, currentY) {
212
+ if (this.state.draggingConnectionData.sourcePoint) {
213
+ this.state.draggingConnectionData.currentX = currentX;
214
+ this.state.draggingConnectionData.currentY = currentY;
215
+ // Calculate which swimlane the cursor is over
216
+ const swimlaneIndex = Math.floor(currentY / this.swimlaneHeight);
217
+ if (swimlaneIndex >= 0 && swimlaneIndex < this.state.swimlanes.length) {
218
+ // Ensure the target swimlane is fully visible
219
+ this.ensureSwimlaneInView(swimlaneIndex);
220
+ }
221
+ }
222
+ }
137
223
  onMouseUp = (event) => {
138
224
  document.removeEventListener('mousemove', this.onMouseMove);
139
225
  document.removeEventListener('mouseup', this.onMouseUp);
@@ -213,22 +299,66 @@ export class DesignerCanvasComponent {
213
299
  return;
214
300
  }
215
301
  const { endX, endY, sourceSwimlaneIndex } = pathData;
302
+ // Get source node info
303
+ const sourcePoint = this.state.draggingConnectionData.sourcePoint;
304
+ if (!sourcePoint) {
305
+ this.hideConnectionPopup();
306
+ return;
307
+ }
308
+ const sourceNodeInfo = this.state.findNodeById(sourcePoint.nodeId);
309
+ if (!sourceNodeInfo) {
310
+ this.hideConnectionPopup();
311
+ return;
312
+ }
313
+ // If connecting from a decision to a stage, show condition popup first
314
+ if (sourceNodeInfo.node.type === 'decision' && nodeType === 'stage') {
315
+ // Store information for later stage creation
316
+ this.pendingDecisionConnection = {
317
+ decisionNodeId: sourceNodeInfo.node.id,
318
+ swimlaneIndex: sourceSwimlaneIndex,
319
+ x: endX,
320
+ y: endY,
321
+ };
322
+ // Calculate popup position - position it near the decision node
323
+ const swimlaneOffsetY = sourceSwimlaneIndex * 263 + 40;
324
+ // Center the popup over the connection endpoint
325
+ this.decisionConditionPopupX = endX;
326
+ this.decisionConditionPopupY = endY - 150; // Position above the endpoint
327
+ // Set decision node ID
328
+ this.activeDecisionNodeId = sourceNodeInfo.node.id;
329
+ this.showDecisionConditionDialog = true;
330
+ // End the connection drag
331
+ this.hideConnectionPopup();
332
+ return;
333
+ }
216
334
  // Calculate swimlane-relative position
217
335
  const swimlaneOffsetY = sourceSwimlaneIndex * 263 + 40;
218
336
  const relativeY = endY - swimlaneOffsetY;
219
337
  // Handle preconditions based on node type
220
338
  if (nodeType === 'stage') {
221
- // Open stage properties dialog instead of creating node directly
222
- this.pendingStagePosition = {
223
- swimlaneIndex: sourceSwimlaneIndex,
224
- x: endX,
225
- y: endY,
226
- };
227
- console.log('Emitting showStageDialog event with position:', this.pendingStagePosition);
228
- this.showStageDialog.emit({
229
- position: this.pendingStagePosition,
230
- isFromConnection: true,
231
- });
339
+ // Create the stage directly with default properties
340
+ const newNode = this.state.addNode(sourceSwimlaneIndex, 'stage', endX, relativeY, { Name: 'New Stage' } // Add default properties
341
+ );
342
+ if (newNode &&
343
+ newNode.connectionPoints &&
344
+ newNode.connectionPoints.length > 0 &&
345
+ sourcePoint) {
346
+ // Handle connection creation
347
+ const opposingType = {
348
+ right: 'left',
349
+ left: 'right',
350
+ top: 'bottom',
351
+ bottom: 'top',
352
+ }[sourcePoint.type];
353
+ const targetPoint = newNode.connectionPoints.find((p) => p.type === opposingType);
354
+ if (targetPoint) {
355
+ // Create the connection
356
+ const connection = this.state.createConnection(newNode.id, targetPoint.id, sourceSwimlaneIndex);
357
+ if (connection) {
358
+ this.onConnectionCreated(connection);
359
+ }
360
+ }
361
+ }
232
362
  this.hideConnectionPopup();
233
363
  return;
234
364
  }
@@ -245,7 +375,6 @@ export class DesignerCanvasComponent {
245
375
  newNode.connectionPoints &&
246
376
  newNode.connectionPoints.length > 0) {
247
377
  // Find the most appropriate connection point (closest to the source)
248
- const sourcePoint = this.state.draggingConnectionData.sourcePoint;
249
378
  if (sourcePoint) {
250
379
  // For simplicity, use the first connection point of opposing type
251
380
  // In a real implementation, you'd find the closest or most appropriate point
@@ -260,13 +389,76 @@ export class DesignerCanvasComponent {
260
389
  targetPoint = newNode.connectionPoints.find((p) => p.type === opposingType);
261
390
  if (targetPoint) {
262
391
  // Create the connection
263
- this.state.createConnection(newNode.id, targetPoint.id, sourceSwimlaneIndex);
392
+ const connection = this.state.createConnection(newNode.id, targetPoint.id, sourceSwimlaneIndex);
393
+ if (connection) {
394
+ this.onConnectionCreated(connection);
395
+ }
264
396
  }
265
397
  }
266
398
  }
399
+ if (sourceNodeInfo) {
400
+ this.updateNodeConnections(sourceNodeInfo.node);
401
+ }
267
402
  // End the connection drag
268
403
  this.hideConnectionPopup();
269
404
  }
405
+ // Method to handle saving the condition
406
+ onDecisionConditionSaved(event) {
407
+ if (!this.pendingDecisionConnection) {
408
+ this.showDecisionConditionDialog = false;
409
+ return;
410
+ }
411
+ const { decisionNodeId, swimlaneIndex, x, y } = this.pendingDecisionConnection;
412
+ // Create the stage directly with default properties
413
+ const node = this.state.addNode(swimlaneIndex, 'stage', x, y, { Name: 'New Stage' } // Add default properties
414
+ );
415
+ if (node) {
416
+ const decisionNodeInfo = this.state.findNodeById(decisionNodeId);
417
+ if (decisionNodeInfo &&
418
+ node.connectionPoints &&
419
+ node.connectionPoints.length > 0) {
420
+ // Find a suitable connection point from the decision node
421
+ const decisionNode = decisionNodeInfo.node;
422
+ const decisionNodePoints = decisionNode.connectionPoints || [];
423
+ const sourcePoint = decisionNodePoints.find((p) => p.type === 'right' || p.type === 'bottom');
424
+ if (sourcePoint) {
425
+ // Find opposing type connection point on the new stage
426
+ const opposingType = {
427
+ right: 'left',
428
+ bottom: 'top',
429
+ left: 'right',
430
+ top: 'bottom',
431
+ }[sourcePoint.type];
432
+ const targetPoint = node.connectionPoints.find((p) => p.type === opposingType);
433
+ if (targetPoint) {
434
+ // Create connection with condition
435
+ const connection = {
436
+ id: `conn-${Date.now()}-${Math.floor(Math.random() * 1000)}`,
437
+ sourceNodeId: decisionNode.id,
438
+ targetNodeId: node.id,
439
+ sourcePointId: sourcePoint.id,
440
+ targetPointId: targetPoint.id,
441
+ sourceSwimlaneIndex: decisionNodeInfo.swimlaneIndex,
442
+ targetSwimlaneIndex: swimlaneIndex,
443
+ condition: event.condition,
444
+ };
445
+ // Add connection to the state
446
+ this.state.connections.push(connection);
447
+ console.log('Created decision connection with condition:', connection);
448
+ }
449
+ }
450
+ }
451
+ }
452
+ // Clear pending data
453
+ this.pendingDecisionConnection = null;
454
+ this.pendingDecisionCondition = '';
455
+ // Hide the condition popup
456
+ this.showDecisionConditionDialog = false;
457
+ }
458
+ onDecisionConditionCancelled() {
459
+ this.showDecisionConditionDialog = false;
460
+ // Don't create the stage or connection
461
+ }
270
462
  getConnectionPath() {
271
463
  const pathData = this.state.getConnectionPathData();
272
464
  if (!pathData)
@@ -496,6 +688,7 @@ export class DesignerCanvasComponent {
496
688
  this.state.connections.push(connection);
497
689
  console.log('Added connection to state:', connection);
498
690
  console.log('Connections after adding:', this.state.connections);
691
+ this.onConnectionCreated(connection);
499
692
  }
500
693
  }
501
694
  this.state.endConnectionDrag();
@@ -509,12 +702,45 @@ export class DesignerCanvasComponent {
509
702
  this.pendingConnectionSourcePoint = null;
510
703
  this.pendingConnectionSourceSwimlaneIndex = null;
511
704
  }
705
+ showDecisionConditionsPopup(event, node, swimlaneIndex) {
706
+ event.preventDefault();
707
+ event.stopPropagation();
708
+ // Get the position for the popup
709
+ const position = this.getMousePosition(event);
710
+ const globalX = position.x;
711
+ const globalY = position.y;
712
+ // Find all connections from this decision node
713
+ const connections = this.state.connections.filter((conn) => conn.sourceNodeId === node.id);
714
+ if (connections.length === 0) {
715
+ // No connections to show
716
+ return;
717
+ }
718
+ // Show the decision conditions popup
719
+ this.activeDecisionNodeId = node.id;
720
+ this.decisionConditionPopupX = globalX;
721
+ this.decisionConditionPopupY = globalY;
722
+ // Set the correct popup visibility flag - this is likely the issue
723
+ this.showDecisionConditionDialog = true;
724
+ console.log('Showing decision popup:', {
725
+ x: globalX,
726
+ y: globalY,
727
+ nodeId: node.id,
728
+ isVisible: this.showDecisionConditionDialog,
729
+ });
730
+ }
731
+ ensureSwimlaneInView(swimlaneIndex) {
732
+ // Ensure we have enough swimlanes visible
733
+ const requiredHeight = (swimlaneIndex + 1) * this.swimlaneHeight;
734
+ if (this.canvasHeight < requiredHeight) {
735
+ this.canvasHeight = requiredHeight;
736
+ }
737
+ }
512
738
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DesignerCanvasComponent, deps: [{ token: i1.WorkflowDesignerState }, { token: i2.WorkflowDataService }], target: i0.ɵɵFactoryTarget.Component });
513
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DesignerCanvasComponent, selector: "lib-designer-canvas", inputs: { selectedTool: "selectedTool" }, outputs: { clickedPosition: "clickedPosition", subflowSelected: "subflowSelected", showStageDialog: "showStageDialog" }, host: { listeners: { "window:mouseup": "onWindowMouseUp($event)", "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["canvas"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"canvas-container\">\n <svg\n #canvas\n [attr.width]=\"canvasWidth\"\n [attr.height]=\"canvasHeight\"\n class=\"designer-canvas\"\n (click)=\"onCanvasClick($event)\"\n >\n <defs>\n <!-- Grid pattern definition -->\n\n <pattern\n id=\"grid\"\n [attr.width]=\"gridSize\"\n [attr.height]=\"gridSize\"\n patternUnits=\"userSpaceOnUse\"\n >\n <path\n d=\"M 20 0 L 0 0 0 20\"\n fill=\"none\"\n stroke=\"#e2e8f0\"\n stroke-width=\"0.5\"\n />\n </pattern>\n\n <!-- Arrow head marker definition -->\n <marker\n id=\"arrowhead\"\n markerWidth=\"10\"\n markerHeight=\"7\"\n refX=\"9\"\n refY=\"3.5\"\n orient=\"auto\"\n >\n <polygon points=\"0 0, 10 3.5, 0 7\" fill=\"#D36CFF\" />\n </marker>\n\n <!-- Connection point styles -->\n <circle\n id=\"connection-point-template\"\n r=\"5\"\n fill=\"#D36CFF\"\n stroke=\"#FFFFFF\"\n stroke-width=\"1\"\n />\n\n <!-- Dashed line style for connection preview -->\n <pattern\n id=\"dashed-line\"\n width=\"10\"\n height=\"10\"\n patternUnits=\"userSpaceOnUse\"\n >\n <line\n x1=\"0\"\n y1=\"5\"\n x2=\"10\"\n y2=\"5\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n stroke-dasharray=\"5,5\"\n />\n </pattern>\n </defs>\n\n <!-- Background grid -->\n <rect width=\"100%\" height=\"100%\" fill=\"url(#grid)\" />\n\n <!-- Display a message when no swimlanes exist -->\n @if (state.swimlanes.length === 0) {\n <text\n x=\"50%\"\n y=\"50%\"\n font-family=\"sans-serif\"\n font-size=\"16\"\n fill=\"#94a3b8\"\n text-anchor=\"middle\"\n >\n Select the Swimlane tool and click on the canvas to add a swimlane\n </text>\n }\n\n <!-- This is where workflow elements will be added later -->\n @for (swimlane of state.swimlanes; track swimlane.order) {\n <g [attr.transform]=\"'translate(0,' + swimlane.order * 263 + ')'\">\n <!-- Swimlane container -->\n <rect\n x=\"0\"\n y=\"0\"\n [attr.width]=\"canvasWidth\"\n [attr.height]=\"263\"\n fill=\"#ffffff\"\n stroke=\"#e2e8f0\"\n stroke-width=\"1\"\n ></rect>\n\n <!-- Swimlane header -->\n <rect\n x=\"0\"\n y=\"0\"\n [attr.width]=\"canvasWidth\"\n height=\"40\"\n fill=\"#f8fafc\"\n stroke=\"#e2e8f0\"\n stroke-width=\"1\"\n ></rect>\n\n <!-- Swimlane label -->\n <text\n x=\"20\"\n y=\"25\"\n font-family=\"sans-serif\"\n font-size=\"14\"\n fill=\"#333333\"\n font-weight=\"bold\"\n >\n {{ swimlane.label }}\n </text>\n\n <!-- Edit button -->\n <g\n class=\"edit-swimlane-button\"\n [attr.transform]=\"'translate(200, 20)'\"\n (click)=\"\n onEditSwimlane($event, swimlane, swimlane.order);\n $event.stopPropagation()\n \"\n >\n <rect\n x=\"-5\"\n y=\"-15\"\n width=\"40\"\n height=\"20\"\n fill=\"#f3e8ff\"\n rx=\"3\"\n ry=\"3\"\n stroke=\"#d8b4fe\"\n stroke-width=\"1\"\n ></rect>\n <text\n x=\"15\"\n y=\"0\"\n font-family=\"sans-serif\"\n font-size=\"12\"\n fill=\"#7e22ce\"\n text-anchor=\"middle\"\n >\n Edit\n </text>\n </g>\n\n <!-- Tag indicators -->\n <g [attr.transform]=\"'translate(200, 20)'\">\n @for (tag of swimlane.tags.slice(0, 3); track tag.Name; let i = $index)\n {\n <text\n [attr.x]=\"i * 100\"\n y=\"5\"\n font-family=\"sans-serif\"\n font-size=\"12\"\n fill=\"#666666\"\n >\n {{ tag.Name }}\n </text>\n } @if (swimlane.tags.length > 3) {\n <text\n [attr.x]=\"3 * 100 + 10\"\n y=\"5\"\n font-family=\"sans-serif\"\n font-size=\"12\"\n fill=\"#666666\"\n >\n +{{ swimlane.tags.length - 3 }} more\n </text>\n }\n </g>\n\n <!-- Render nodes in this swimlane -->\n @for (node of swimlane.nodes; track node.id) {\n <g\n [attr.transform]=\"'translate(' + node.x + ',' + (node.y + 40) + ')'\"\n (mouseenter)=\"showConnectionPoints(node.id, swimlane.order)\"\n (mouseleave)=\"hideConnectionPoints(node.id)\"\n >\n <!-- Start node indicator (circle and arrow) for the first node -->\n @if (node.isStartNode) {\n <!-- Circle -->\n <circle\n cx=\"-30\"\n cy=\"50\"\n r=\"15\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></circle>\n <!-- Form icon for start node -->\n <svg:g\n (click)=\"\n toggleStartNodeFormPopup($event, node.x, node.y, swimlane.order)\n \"\n class=\"stage-icon\"\n transform=\"translate(-45, 42)\"\n style=\"cursor: pointer; pointer-events: all\"\n >\n <!-- Transparent rectangle to capture clicks -->\n <svg:rect\n x=\"-2\"\n y=\"-2\"\n width=\"24\"\n height=\"24\"\n fill=\"transparent\"\n style=\"cursor: pointer\"\n />\n <svg:path\n d=\"M16.5 20.475V17.475H13.5V16.475H16.5V13.475H17.5V16.475H20.5V17.475H17.5V20.475H16.5ZM3.5 17.5V16.5H4.5V17.5H3.5ZM6.5 17.5V16.5H11.517C11.5057 16.6767 11.5043 16.845 11.513 17.005C11.521 17.165 11.531 17.33 11.543 17.5H6.5ZM3.5 13.5V12.5H4.5V13.5H3.5ZM6.5 13.5V12.5H13.804C13.6127 12.6387 13.4333 12.7913 13.266 12.958C13.0993 13.1247 12.9377 13.3053 12.781 13.5H6.5ZM3.5 9.5V8.5H4.5V9.5H3.5ZM6.5 9.5V8.5H18.5V9.5H6.5ZM3.5 5.5V4.5H4.5V5.5H3.5ZM6.5 5.5V4.5H18.5V5.5H6.5Z\"\n [attr.fill]=\"state.workflowFormId ? '#D36CFF' : 'black'\"\n transform=\"scale(0.7)\"\n />\n </svg:g>\n <!-- Arrow from circle to node -->\n <path\n d=\"M -20 50 L 0 50\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n marker-end=\"url(#arrowhead)\"\n ></path>\n }\n\n <!-- Stage node -->\n @if (node.type === 'stage') {\n <!-- <rect\n x=\"0\"\n y=\"0\"\n [attr.width]=\"node.width\"\n [attr.height]=\"node.height\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></rect> -->\n <svg:g\n lib-stage-node\n [node]=\"node\"\n [isStartNode]=\"node.isStartNode\"\n (stagePropertiesUpdated)=\"onStagePropertiesUpdated($event)\"\n ></svg:g>\n }\n\n <!-- Decision node -->\n @if (node.type === 'decision') {\n <path\n [attr.d]=\"\n 'M 0 ' +\n node.height / 2 +\n ' L ' +\n node.width / 2 +\n ' 0' +\n ' L ' +\n node.width +\n ' ' +\n node.height / 2 +\n ' L ' +\n node.width / 2 +\n ' ' +\n node.height +\n ' Z'\n \"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></path>\n }\n\n <!-- Form node -->\n @if (node.type === 'form') {\n <path\n d=\"M95.0625 50.5591V95.0625C95.0625 97.9716 93.9069 100.762 91.8498 102.819C89.7928 104.876 87.0028 106.031 84.0938 106.031H32.9062C29.9972 106.031 27.2072 104.876 25.1502 102.819C23.0931 100.762 21.9375 97.9716 21.9375 95.0625V21.9375C21.9375 19.0284 23.0931 16.2385 25.1502 14.1814C27.2072 12.1244 29.9972 10.9688 32.9062 10.9688H55.4722C57.4109 10.969 59.2701 11.7392 60.6412 13.1099L92.9213 45.3901C94.292 46.7611 95.0622 48.6204 95.0625 50.5591Z\"\n transform=\"scale(0.7)\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M58.5 12.7969V40.2188C58.5 42.1581 59.2704 44.0181 60.6418 45.3895C62.0131 46.7608 63.8731 47.5312 65.8125 47.5312H93.2344\"\n transform=\"scale(0.7)\"\n stroke=\"#D36CFF\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <text\n x=\"50%\"\n y=\"50%\"\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n font-family=\"sans-serif\"\n font-size=\"14\"\n fill=\"#D36CFF\"\n >\n Form\n </text>\n }\n\n <!-- Subflow node -->\n @if (node.type === 'subflow') {\n <path\n [attr.d]=\"\n 'M 1 ' +\n node.height / 4 +\n ' L ' +\n node.width / 2 +\n ' 1 L ' +\n (node.width - 1) +\n ' ' +\n node.height / 4 +\n ' V ' +\n (node.height * 3) / 4 +\n ' L ' +\n node.width / 2 +\n ' ' +\n (node.height - 1) +\n ' L 1 ' +\n (node.height * 3) / 4 +\n ' Z'\n \"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></path>\n <text\n x=\"50%\"\n y=\"50%\"\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n font-family=\"sans-serif\"\n font-size=\"14\"\n fill=\"#000000\"\n >\n {{ node.workflowData?.name || \"Subflow\" }}\n </text>\n }\n\n <!-- Connection points for this node -->\n @for (point of node.connectionPoints || []; track point.id) { @if\n (isConnectionPointVisible(node.id)) {\n <use\n [attr.href]=\"'#connection-point-template'\"\n [attr.x]=\"point.x\"\n [attr.y]=\"point.y\"\n [attr.id]=\"point.id\"\n (mousedown)=\"startConnectionDrag($event, point, swimlane.order)\"\n />\n } }\n </g>\n <!-- A transparent hover area for improved hover detection -->\n <rect\n [attr.x]=\"node.x - 10\"\n [attr.y]=\"node.y + 40 - 10\"\n [attr.width]=\"node.width + 20\"\n [attr.height]=\"node.height + 20\"\n fill=\"transparent\"\n (mouseover)=\"showConnectionPoints(node.id, swimlane.order)\"\n (mouseout)=\"hideConnectionPoints(node.id)\"\n style=\"pointer-events: none\"\n />\n }\n </g>\n } @for (connection of state.connections; track connection.id) {\n <g>\n <path\n [attr.d]=\"getConnectionPathForSavedConnection(connection)\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n fill=\"none\"\n marker-end=\"url(#arrowhead)\"\n ></path>\n </g>\n }\n\n <!-- Connection preview line -->\n @if (state.isConnectionDragging()) {\n <g>\n <path\n [attr.d]=\"getConnectionPath()\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n stroke-dasharray=\"5,5\"\n fill=\"none\"\n ></path>\n </g>\n }\n </svg>\n\n <div\n *ngIf=\"popupVisible\"\n [style.position]=\"'absolute'\"\n [style.left.px]=\"popupX\"\n [style.top.px]=\"popupY\"\n >\n <verben-pop-Up\n [dropdownOpen]=\"true\"\n [customStyles]=\"{ 'z-index': '99' }\"\n [enableMouseLeave]=\"false\"\n >\n <div dropdown-trigger style=\"display: none\">\n <!-- Hidden trigger element -->\n </div>\n <div\n class=\"p-3 bg-white border border-gray-200 rounded shadow-md\"\n dropdown-content\n >\n <h4 class=\"mb-2 font-medium\">Create Connection</h4>\n <div class=\"flex flex-col gap-2\">\n <ng-container *ngFor=\"let type of allowedNodeTypes\">\n <button\n class=\"px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50\"\n (click)=\"createNodeConnection(type)\"\n >\n Create {{ type | titlecase }}\n </button>\n </ng-container>\n <button\n class=\"px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50\"\n (click)=\"hideConnectionPopup()\"\n >\n Cancel\n </button>\n </div>\n </div>\n </verben-pop-Up>\n </div>\n\n <div\n *ngIf=\"showStartNodeFormPopup\"\n [style.position]=\"'absolute'\"\n [style.left.px]=\"startNodeFormPopupX\"\n [style.top.px]=\"startNodeFormPopupY\"\n >\n <verben-pop-Up [dropdownOpen]=\"true\" [customStyles]=\"{ 'z-index': '100' }\">\n <div dropdown-trigger style=\"display: none\">\n <!-- Hidden trigger element -->\n </div>\n <div\n class=\"p-3 bg-white border border-gray-200 rounded shadow-md w-64\"\n dropdown-content\n style=\"background-color: white; z-index: 1000\"\n >\n <h4 class=\"mb-2 font-medium\">Select Workflow Form</h4>\n <div *ngIf=\"isLoadingStartNodeForms\" class=\"text-center py-2\">\n Loading forms...\n </div>\n <div *ngIf=\"!isLoadingStartNodeForms\" class=\"max-h-48 overflow-y-auto\">\n <div class=\"mb-2\">\n <button\n class=\"w-full px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50 text-left\"\n (click)=\"selectStartNodeForm(null)\"\n >\n Clear form selection\n </button>\n </div>\n <div *ngFor=\"let form of startNodeFormsList\" class=\"mb-1\">\n <button\n class=\"w-full px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50 text-left\"\n (click)=\"selectStartNodeForm(form)\"\n >\n {{ form.Name }}\n </button>\n </div>\n <div\n *ngIf=\"startNodeFormsList.length === 0\"\n class=\"text-center py-2 text-gray-500\"\n >\n No forms available\n </div>\n </div>\n </div>\n </verben-pop-Up>\n </div>\n\n <div\n *ngIf=\"showSubflowPopup\"\n [style.position]=\"'fiabsolutexed'\"\n [style.left.px]=\"subflowPopupX\"\n [style.top.px]=\"subflowPopupY\"\n >\n <verben-pop-Up [dropdownOpen]=\"true\" [customStyles]=\"{ 'z-index': '100' }\">\n <div dropdown-trigger style=\"display: none\">\n <!-- Hidden trigger element -->\n </div>\n <div\n class=\"p-3 bg-white border border-gray-200 rounded shadow-md w-64\"\n dropdown-content\n style=\"background-color: white; z-index: 1000\"\n >\n <h4 class=\"mb-2 font-medium\">Select Workflow</h4>\n <div *ngIf=\"isLoadingWorkflows\" class=\"text-center py-2\">\n Loading workflows...\n </div>\n <div *ngIf=\"!isLoadingWorkflows\" class=\"max-h-48 overflow-y-auto\">\n <div *ngFor=\"let workflow of workflowsList\" class=\"mb-1\">\n <button\n class=\"w-full px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50 text-left\"\n (click)=\"selectSubflowWorkflow(workflow)\"\n >\n {{ workflow.Name }}\n </button>\n </div>\n <div\n *ngIf=\"workflowsList.length === 0\"\n class=\"text-center py-2 text-gray-500\"\n >\n No workflows available\n </div>\n </div>\n </div>\n </verben-pop-Up>\n </div>\n</div>\n", styles: [".canvas-container{flex:1;overflow:auto;background-color:#fff}.designer-canvas{min-width:100%;min-height:100%;cursor:default}.designer-canvas:focus{outline:none}.edit-swimlane-button{cursor:pointer}.edit-swimlane-button:hover rect{fill:#ddd6fe}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.VerbenPopUpComponent, selector: "verben-pop-Up", inputs: ["dropdownOpen", "dropdownWidth", "color", "customStyles", "popUpClass", "border", "borderRadius", "enableMouseLeave"], outputs: ["dropdownOpenChange", "close"] }, { kind: "component", type: i5.StageNodeComponent, selector: "svg:g[lib-stage-node]", inputs: ["node", "isStartNode", "stageData"], outputs: ["stagePropertiesUpdated", "parallelExecutionToggled"] }, { kind: "pipe", type: i3.TitleCasePipe, name: "titlecase" }] });
739
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: DesignerCanvasComponent, selector: "lib-designer-canvas", inputs: { selectedTool: "selectedTool" }, outputs: { clickedPosition: "clickedPosition", subflowSelected: "subflowSelected", showStageDialog: "showStageDialog", stagePropertiesUpdated: "stagePropertiesUpdated" }, host: { listeners: { "window:mouseup": "onWindowMouseUp($event)", "document:click": "onDocumentClick($event)" } }, viewQueries: [{ propertyName: "canvasRef", first: true, predicate: ["canvas"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"canvas-container\">\n <svg\n #canvas\n [attr.width]=\"canvasWidth\"\n [attr.height]=\"canvasHeight\"\n class=\"designer-canvas\"\n (click)=\"onCanvasClick($event)\"\n >\n <defs>\n <!-- Grid pattern definition -->\n\n <pattern\n id=\"grid\"\n [attr.width]=\"gridSize\"\n [attr.height]=\"gridSize\"\n patternUnits=\"userSpaceOnUse\"\n >\n <path\n d=\"M 20 0 L 0 0 0 20\"\n fill=\"none\"\n stroke=\"#e2e8f0\"\n stroke-width=\"0.5\"\n />\n </pattern>\n\n <!-- Arrow head marker definition -->\n <marker\n id=\"arrowhead\"\n markerWidth=\"10\"\n markerHeight=\"7\"\n refX=\"9\"\n refY=\"3.5\"\n orient=\"auto\"\n >\n <polygon points=\"0 0, 10 3.5, 0 7\" fill=\"#D36CFF\" />\n </marker>\n\n <!-- Connection point styles -->\n <circle\n id=\"connection-point-template\"\n r=\"5\"\n fill=\"#D36CFF\"\n stroke=\"#FFFFFF\"\n stroke-width=\"1\"\n />\n\n <!-- Dashed line style for connection preview -->\n <pattern\n id=\"dashed-line\"\n width=\"10\"\n height=\"10\"\n patternUnits=\"userSpaceOnUse\"\n >\n <line\n x1=\"0\"\n y1=\"5\"\n x2=\"10\"\n y2=\"5\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n stroke-dasharray=\"5,5\"\n />\n </pattern>\n\n @for (swimlane of state.swimlanes; track swimlane.order) {\n <clipPath [attr.id]=\"'swimlane-clip-' + swimlane.order\">\n <rect x=\"0\" y=\"0\" [attr.width]=\"canvasWidth\" height=\"263\" />\n </clipPath>\n }\n </defs>\n\n <!-- Background grid -->\n <rect width=\"100%\" height=\"100%\" fill=\"url(#grid)\" />\n\n <!-- Display a message when no swimlanes exist -->\n @if (state.swimlanes.length === 0) {\n <text\n x=\"50%\"\n y=\"50%\"\n font-family=\"sans-serif\"\n font-size=\"16\"\n fill=\"#94a3b8\"\n text-anchor=\"middle\"\n >\n Select the Swimlane tool and click on the canvas to add a swimlane\n </text>\n }\n\n <!-- This is where workflow elements will be added later -->\n @for (swimlane of state.swimlanes; track swimlane.order) {\n <g\n [attr.transform]=\"'translate(0,' + swimlane.order * 263 + ')'\"\n [attr.clip-path]=\"'url(#swimlane-clip-' + swimlane.order + ')'\"\n >\n <!-- Swimlane container -->\n <rect\n x=\"0\"\n y=\"0\"\n [attr.width]=\"canvasWidth\"\n [attr.height]=\"263\"\n fill=\"#ffffff\"\n stroke=\"#e2e8f0\"\n stroke-width=\"1\"\n ></rect>\n\n <!-- Swimlane header -->\n <rect\n x=\"0\"\n y=\"0\"\n [attr.width]=\"canvasWidth\"\n height=\"40\"\n fill=\"#f8fafc\"\n stroke=\"#e2e8f0\"\n stroke-width=\"1\"\n ></rect>\n\n <!-- Swimlane label -->\n <text\n x=\"20\"\n y=\"25\"\n font-family=\"sans-serif\"\n font-size=\"14\"\n fill=\"#333333\"\n font-weight=\"bold\"\n >\n {{ swimlane.label }}\n </text>\n\n <!-- Edit button -->\n <g\n class=\"edit-swimlane-button\"\n [attr.transform]=\"'translate(100, 20)'\"\n (click)=\"\n onEditSwimlane($event, swimlane, swimlane.order);\n $event.stopPropagation()\n \"\n >\n <rect\n x=\"-5\"\n y=\"-15\"\n width=\"40\"\n height=\"20\"\n fill=\"#f3e8ff\"\n rx=\"3\"\n ry=\"3\"\n stroke=\"#d8b4fe\"\n stroke-width=\"1\"\n ></rect>\n <text\n x=\"15\"\n y=\"0\"\n font-family=\"sans-serif\"\n font-size=\"12\"\n fill=\"#7e22ce\"\n text-anchor=\"middle\"\n >\n Edit\n </text>\n </g>\n\n <!-- Tag indicators -->\n <g [attr.transform]=\"'translate(200, 20)'\">\n @for (tag of swimlane.tags.slice(0, 3); track tag.Name; let i = $index)\n {\n <text\n [attr.x]=\"i * 100\"\n y=\"5\"\n font-family=\"sans-serif\"\n font-size=\"12\"\n fill=\"#666666\"\n >\n {{ tag.Name }}\n </text>\n } @if (swimlane.tags.length > 3) {\n <text\n [attr.x]=\"3 * 100 + 10\"\n y=\"5\"\n font-family=\"sans-serif\"\n font-size=\"12\"\n fill=\"#666666\"\n >\n +{{ swimlane.tags.length - 3 }} more\n </text>\n }\n </g>\n </g>\n }\n\n <!-- Nodes -->\n @for (swimlane of state.swimlanes; track swimlane.order) {\n <!-- Render nodes in this swimlane -->\n @for (node of swimlane.nodes; track node.id) {\n <g\n class=\"node-element\"\n [attr.transform]=\"'translate(' + node.x + ',' + (node.y + 40) + ')'\"\n (mouseenter)=\"showConnectionPoints(node.id, swimlane.order)\"\n (mouseleave)=\"hideConnectionPoints(node.id)\"\n >\n <!-- Start node indicator (circle and arrow) for the first node -->\n @if (node.isStartNode) {\n <!-- Circle -->\n <circle\n cx=\"-30\"\n cy=\"50\"\n r=\"15\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></circle>\n <!-- Form icon for start node -->\n <svg:g\n (click)=\"\n toggleStartNodeFormPopup($event, node.x, node.y, swimlane.order)\n \"\n class=\"stage-icon\"\n transform=\"translate(-45, 42)\"\n style=\"cursor: pointer; pointer-events: all\"\n >\n <!-- Transparent rectangle to capture clicks -->\n <svg:rect\n x=\"-2\"\n y=\"-2\"\n width=\"24\"\n height=\"24\"\n fill=\"transparent\"\n style=\"cursor: pointer\"\n />\n <svg:path\n d=\"M16.5 20.475V17.475H13.5V16.475H16.5V13.475H17.5V16.475H20.5V17.475H17.5V20.475H16.5ZM3.5 17.5V16.5H4.5V17.5H3.5ZM6.5 17.5V16.5H11.517C11.5057 16.6767 11.5043 16.845 11.513 17.005C11.521 17.165 11.531 17.33 11.543 17.5H6.5ZM3.5 13.5V12.5H4.5V13.5H3.5ZM6.5 13.5V12.5H13.804C13.6127 12.6387 13.4333 12.7913 13.266 12.958C13.0993 13.1247 12.9377 13.3053 12.781 13.5H6.5ZM3.5 9.5V8.5H4.5V9.5H3.5ZM6.5 9.5V8.5H18.5V9.5H6.5ZM3.5 5.5V4.5H4.5V5.5H3.5ZM6.5 5.5V4.5H18.5V5.5H6.5Z\"\n [attr.fill]=\"state.workflowFormId ? '#D36CFF' : 'black'\"\n transform=\"scale(0.7)\"\n />\n </svg:g>\n <!-- Arrow from circle to node -->\n <path\n d=\"M -20 50 L 0 50\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n marker-end=\"url(#arrowhead)\"\n ></path>\n }\n\n <!-- Exit point indicator (circle and arrow) -->\n @if (node.stageData?.IsExitPoint) {\n <!-- Arrow from node to circle -->\n <path\n [attr.d]=\"'M ' + node.width + ' 50 L ' + (node.width + 20) + ' 50'\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n marker-end=\"url(#arrowhead)\"\n ></path>\n <!-- Circle -->\n <circle\n [attr.cx]=\"node.width + 50\"\n cy=\"50\"\n r=\"30\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n ></circle>\n }\n\n <!-- Stage node -->\n @if (node.type === 'stage') {\n <!-- <rect\n x=\"0\"\n y=\"0\"\n [attr.width]=\"node.width\"\n [attr.height]=\"node.height\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></rect> -->\n <svg:g\n lib-stage-node\n [node]=\"node\"\n [isStartNode]=\"node.isStartNode\"\n (stagePropertiesUpdated)=\"onStagePropertiesUpdated($event)\"\n (showShieldDialog)=\"onShowShieldDialog($event)\"\n ></svg:g>\n }\n\n <!-- Decision node -->\n @if (node.type === 'decision') {\n <path\n [attr.d]=\"\n 'M 0 ' +\n node.height / 2 +\n ' L ' +\n node.width / 2 +\n ' 0' +\n ' L ' +\n node.width +\n ' ' +\n node.height / 2 +\n ' L ' +\n node.width / 2 +\n ' ' +\n node.height +\n ' Z'\n \"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></path>\n\n <!-- Decision node condition indicator icon -->\n <svg:g\n (click)=\"showDecisionConditionsPopup($event, node, swimlane.order)\"\n class=\"decision-condition-icon\"\n [attr.transform]=\"\n 'translate(' +\n (node.width / 2 - 10) +\n ',' +\n (node.height / 2 - 10) +\n ')'\n \"\n >\n <svg:rect\n x=\"-5\"\n y=\"-5\"\n width=\"30\"\n height=\"30\"\n fill=\"transparent\"\n style=\"cursor: pointer\"\n />\n <svg:path\n d=\"M10 0H20V2H10V0ZM10 8H20V10H10V8ZM10 4H20V6H10V4ZM0 0H8V2H0V0ZM0 8H8V10H0V8ZM0 4H8V6H0V4Z\"\n fill=\"#D36CFF\"\n />\n </svg:g>\n }\n\n <!-- Form node -->\n @if (node.type === 'form') {\n <path\n d=\"M95.0625 50.5591V95.0625C95.0625 97.9716 93.9069 100.762 91.8498 102.819C89.7928 104.876 87.0028 106.031 84.0938 106.031H32.9062C29.9972 106.031 27.2072 104.876 25.1502 102.819C23.0931 100.762 21.9375 97.9716 21.9375 95.0625V21.9375C21.9375 19.0284 23.0931 16.2385 25.1502 14.1814C27.2072 12.1244 29.9972 10.9688 32.9062 10.9688H55.4722C57.4109 10.969 59.2701 11.7392 60.6412 13.1099L92.9213 45.3901C94.292 46.7611 95.0622 48.6204 95.0625 50.5591Z\"\n transform=\"scale(0.7)\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M58.5 12.7969V40.2188C58.5 42.1581 59.2704 44.0181 60.6418 45.3895C62.0131 46.7608 63.8731 47.5312 65.8125 47.5312H93.2344\"\n transform=\"scale(0.7)\"\n stroke=\"#D36CFF\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <text\n x=\"50%\"\n y=\"50%\"\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n font-family=\"sans-serif\"\n font-size=\"14\"\n fill=\"#D36CFF\"\n >\n Form\n </text>\n }\n\n <!-- Subflow node -->\n @if (node.type === 'subflow') {\n <path\n [attr.d]=\"\n 'M 1 ' +\n node.height / 4 +\n ' L ' +\n node.width / 2 +\n ' 1 L ' +\n (node.width - 1) +\n ' ' +\n node.height / 4 +\n ' V ' +\n (node.height * 3) / 4 +\n ' L ' +\n node.width / 2 +\n ' ' +\n (node.height - 1) +\n ' L 1 ' +\n (node.height * 3) / 4 +\n ' Z'\n \"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></path>\n <text\n [attr.x]=\"node.width / 2\"\n [attr.y]=\"node.height / 2\"\n text-anchor=\"middle\"\n alignment-baseline=\"middle\"\n font-family=\"sans-serif\"\n font-size=\"10\"\n fill=\"#000000\"\n >\n <!-- Limit text length -->\n {{\n (node.workflowData?.name || \"Subflow\").length > 12\n ? (node.workflowData?.name || \"Subflow\").substring(0, 10) + \"...\"\n : node.workflowData?.name || \"Subflow\"\n }}\n </text>\n }\n\n <!-- Connection points for this node -->\n @for (point of node.connectionPoints || []; track point.id) { @if\n (isConnectionPointVisible(node.id)) {\n <use\n [attr.href]=\"'#connection-point-template'\"\n [attr.x]=\"point.x\"\n [attr.y]=\"point.y\"\n [attr.id]=\"point.id\"\n (mousedown)=\"startConnectionDrag($event, point, swimlane.order)\"\n />\n } }\n </g>\n <!-- A transparent hover area for improved hover detection -->\n <rect\n [attr.x]=\"node.x - 10\"\n [attr.y]=\"node.y + 40 - 10\"\n [attr.width]=\"node.width + 20\"\n [attr.height]=\"node.height + 20\"\n fill=\"transparent\"\n (mouseover)=\"showConnectionPoints(node.id, swimlane.order)\"\n (mouseout)=\"hideConnectionPoints(node.id)\"\n style=\"pointer-events: none\"\n />\n } }\n\n <!-- Connections -->\n @for (connection of state.connections; track connection.id) {\n <g class=\"connection-element\">\n <path\n [attr.d]=\"getConnectionPathForSavedConnection(connection)\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n fill=\"none\"\n marker-end=\"url(#arrowhead)\"\n ></path>\n </g>\n }\n\n <!-- Connection preview line -->\n @if (state.isConnectionDragging()) {\n <g>\n <path\n [attr.d]=\"getConnectionPath()\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n stroke-dasharray=\"5,5\"\n fill=\"none\"\n ></path>\n </g>\n }\n </svg>\n\n <div\n *ngIf=\"popupVisible\"\n [style.position]=\"'absolute'\"\n [style.left.px]=\"popupX\"\n [style.top.px]=\"popupY\"\n >\n <verben-pop-Up\n [dropdownOpen]=\"true\"\n [customStyles]=\"{ 'z-index': '99' }\"\n [enableMouseLeave]=\"false\"\n >\n <div dropdown-trigger style=\"display: none\">\n <!-- Hidden trigger element -->\n </div>\n <div\n class=\"p-3 bg-white border border-gray-200 rounded shadow-md\"\n dropdown-content\n >\n <h4 class=\"mb-2 font-medium\">Create Connection</h4>\n <div class=\"flex flex-col gap-2\">\n <ng-container *ngFor=\"let type of allowedNodeTypes\">\n <button\n class=\"px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50\"\n (click)=\"createNodeConnection(type)\"\n >\n Create {{ type | titlecase }}\n </button>\n </ng-container>\n <button\n class=\"px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50\"\n (click)=\"hideConnectionPopup()\"\n >\n Cancel\n </button>\n </div>\n </div>\n </verben-pop-Up>\n </div>\n\n <div\n *ngIf=\"showStartNodeFormPopup\"\n [style.position]=\"'absolute'\"\n [style.left.px]=\"startNodeFormPopupX\"\n [style.top.px]=\"startNodeFormPopupY\"\n >\n <verben-pop-Up [dropdownOpen]=\"true\" [customStyles]=\"{ 'z-index': '100' }\">\n <div dropdown-trigger style=\"display: none\">\n <!-- Hidden trigger element -->\n </div>\n <div\n class=\"p-3 bg-white border border-gray-200 rounded shadow-md w-64\"\n dropdown-content\n style=\"background-color: white; z-index: 1000\"\n >\n <h4 class=\"mb-2 font-medium\">Select Workflow Form</h4>\n <div *ngIf=\"isLoadingStartNodeForms\" class=\"text-center py-2\">\n Loading forms...\n </div>\n <div *ngIf=\"!isLoadingStartNodeForms\" class=\"max-h-48 overflow-y-auto\">\n <div class=\"mb-2\">\n <button\n class=\"w-full px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50 text-left\"\n (click)=\"selectStartNodeForm(null)\"\n >\n Clear form selection\n </button>\n </div>\n <div *ngFor=\"let form of startNodeFormsList\" class=\"mb-1\">\n <button\n class=\"w-full px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50 text-left\"\n (click)=\"selectStartNodeForm(form)\"\n >\n {{ form.Name }}\n </button>\n </div>\n <div\n *ngIf=\"startNodeFormsList.length === 0\"\n class=\"text-center py-2 text-gray-500\"\n >\n No forms available\n </div>\n </div>\n </div>\n </verben-pop-Up>\n </div>\n\n <div\n *ngIf=\"showSubflowPopup\"\n [style.position]=\"'absolute'\"\n [style.left.px]=\"subflowPopupX\"\n [style.top.px]=\"subflowPopupY\"\n >\n <verben-pop-Up [dropdownOpen]=\"true\" [customStyles]=\"{ 'z-index': '100' }\">\n <div dropdown-trigger style=\"display: none\">\n <!-- Hidden trigger element -->\n </div>\n <div\n class=\"p-3 bg-white border border-gray-200 rounded shadow-md w-64\"\n dropdown-content\n style=\"background-color: white; z-index: 1000\"\n >\n <h4 class=\"mb-2 font-medium\">Select Workflow</h4>\n <div *ngIf=\"isLoadingWorkflows\" class=\"text-center py-2\">\n Loading workflows...\n </div>\n <div *ngIf=\"!isLoadingWorkflows\" class=\"max-h-48 overflow-y-auto\">\n <div *ngFor=\"let workflow of workflowsList\" class=\"mb-1\">\n <button\n class=\"w-full px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50 text-left\"\n (click)=\"selectSubflowWorkflow(workflow)\"\n >\n {{ workflow.Name }}\n </button>\n </div>\n <div\n *ngIf=\"workflowsList.length === 0\"\n class=\"text-center py-2 text-gray-500\"\n >\n No workflows available\n </div>\n </div>\n </div>\n </verben-pop-Up>\n </div>\n\n <lib-conditions-popup\n [visible]=\"showDecisionConditionDialog\"\n [decisionNodeId]=\"activeDecisionNodeId\"\n [newConnectionId]=\"activeConnectionId\"\n [popupX]=\"decisionConditionPopupX\"\n [popupY]=\"decisionConditionPopupY\"\n (closed)=\"onDecisionConditionCancelled()\"\n (saved)=\"onDecisionConditionSaved($event)\"\n ></lib-conditions-popup>\n\n <!-- <lib-decision-popup\n [visible]=\"showConditionsDialog\"\n [decisionNodeId]=\"activeDecisionNodeId\"\n [popupX]=\"decisionConditionPopupX\"\n [popupY]=\"decisionConditionPopupY\"\n (closed)=\"onDecisionConditionCancelled()\"\n ></lib-decision-popup> -->\n\n <lib-stage-dialog\n [visible]=\"showStageDialogLocal\"\n [stageData]=\"activeStageData || {}\"\n (closed)=\"onStageDialogClosed()\"\n (saved)=\"onStageDialogSaved($event)\"\n ></lib-stage-dialog>\n</div>\n", styles: [".canvas-container{flex:1;overflow:auto;background-color:#fff}.designer-canvas{min-width:100%;min-height:100%;cursor:default}.designer-canvas:focus{outline:none}.edit-swimlane-button{cursor:pointer}.edit-swimlane-button:hover rect{fill:#ddd6fe}.decision-condition-icon{cursor:pointer}.decision-condition-icon:hover path{fill:#c084fc}.swimlane-label{z-index:10;cursor:default}.plus-icon:hover{fill:#d36cff}.swimlane-container{pointer-events:none}.swimlane-container>*{pointer-events:auto}.node-element{z-index:10}.connection-element{z-index:5}\n"], dependencies: [{ kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.VerbenPopUpComponent, selector: "verben-pop-Up", inputs: ["dropdownOpen", "dropdownWidth", "color", "customStyles", "popUpClass", "border", "borderRadius", "enableMouseLeave"], outputs: ["dropdownOpenChange", "close"] }, { kind: "component", type: i5.StageNodeComponent, selector: "svg:g[lib-stage-node]", inputs: ["node", "isStartNode", "stageData"], outputs: ["stagePropertiesUpdated", "parallelExecutionToggled", "showShieldDialog"] }, { kind: "component", type: i6.StageDialogComponent, selector: "lib-stage-dialog", inputs: ["visible", "stageData"], outputs: ["closed", "saved"] }, { kind: "component", type: i7.ConditionsPopupComponent, selector: "lib-conditions-popup", inputs: ["visible", "decisionNodeId", "newConnectionId", "popupX", "popupY"], outputs: ["closed", "saved"] }, { kind: "pipe", type: i3.TitleCasePipe, name: "titlecase" }] });
514
740
  }
515
741
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: DesignerCanvasComponent, decorators: [{
516
742
  type: Component,
517
- args: [{ selector: 'lib-designer-canvas', template: "<div class=\"canvas-container\">\n <svg\n #canvas\n [attr.width]=\"canvasWidth\"\n [attr.height]=\"canvasHeight\"\n class=\"designer-canvas\"\n (click)=\"onCanvasClick($event)\"\n >\n <defs>\n <!-- Grid pattern definition -->\n\n <pattern\n id=\"grid\"\n [attr.width]=\"gridSize\"\n [attr.height]=\"gridSize\"\n patternUnits=\"userSpaceOnUse\"\n >\n <path\n d=\"M 20 0 L 0 0 0 20\"\n fill=\"none\"\n stroke=\"#e2e8f0\"\n stroke-width=\"0.5\"\n />\n </pattern>\n\n <!-- Arrow head marker definition -->\n <marker\n id=\"arrowhead\"\n markerWidth=\"10\"\n markerHeight=\"7\"\n refX=\"9\"\n refY=\"3.5\"\n orient=\"auto\"\n >\n <polygon points=\"0 0, 10 3.5, 0 7\" fill=\"#D36CFF\" />\n </marker>\n\n <!-- Connection point styles -->\n <circle\n id=\"connection-point-template\"\n r=\"5\"\n fill=\"#D36CFF\"\n stroke=\"#FFFFFF\"\n stroke-width=\"1\"\n />\n\n <!-- Dashed line style for connection preview -->\n <pattern\n id=\"dashed-line\"\n width=\"10\"\n height=\"10\"\n patternUnits=\"userSpaceOnUse\"\n >\n <line\n x1=\"0\"\n y1=\"5\"\n x2=\"10\"\n y2=\"5\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n stroke-dasharray=\"5,5\"\n />\n </pattern>\n </defs>\n\n <!-- Background grid -->\n <rect width=\"100%\" height=\"100%\" fill=\"url(#grid)\" />\n\n <!-- Display a message when no swimlanes exist -->\n @if (state.swimlanes.length === 0) {\n <text\n x=\"50%\"\n y=\"50%\"\n font-family=\"sans-serif\"\n font-size=\"16\"\n fill=\"#94a3b8\"\n text-anchor=\"middle\"\n >\n Select the Swimlane tool and click on the canvas to add a swimlane\n </text>\n }\n\n <!-- This is where workflow elements will be added later -->\n @for (swimlane of state.swimlanes; track swimlane.order) {\n <g [attr.transform]=\"'translate(0,' + swimlane.order * 263 + ')'\">\n <!-- Swimlane container -->\n <rect\n x=\"0\"\n y=\"0\"\n [attr.width]=\"canvasWidth\"\n [attr.height]=\"263\"\n fill=\"#ffffff\"\n stroke=\"#e2e8f0\"\n stroke-width=\"1\"\n ></rect>\n\n <!-- Swimlane header -->\n <rect\n x=\"0\"\n y=\"0\"\n [attr.width]=\"canvasWidth\"\n height=\"40\"\n fill=\"#f8fafc\"\n stroke=\"#e2e8f0\"\n stroke-width=\"1\"\n ></rect>\n\n <!-- Swimlane label -->\n <text\n x=\"20\"\n y=\"25\"\n font-family=\"sans-serif\"\n font-size=\"14\"\n fill=\"#333333\"\n font-weight=\"bold\"\n >\n {{ swimlane.label }}\n </text>\n\n <!-- Edit button -->\n <g\n class=\"edit-swimlane-button\"\n [attr.transform]=\"'translate(200, 20)'\"\n (click)=\"\n onEditSwimlane($event, swimlane, swimlane.order);\n $event.stopPropagation()\n \"\n >\n <rect\n x=\"-5\"\n y=\"-15\"\n width=\"40\"\n height=\"20\"\n fill=\"#f3e8ff\"\n rx=\"3\"\n ry=\"3\"\n stroke=\"#d8b4fe\"\n stroke-width=\"1\"\n ></rect>\n <text\n x=\"15\"\n y=\"0\"\n font-family=\"sans-serif\"\n font-size=\"12\"\n fill=\"#7e22ce\"\n text-anchor=\"middle\"\n >\n Edit\n </text>\n </g>\n\n <!-- Tag indicators -->\n <g [attr.transform]=\"'translate(200, 20)'\">\n @for (tag of swimlane.tags.slice(0, 3); track tag.Name; let i = $index)\n {\n <text\n [attr.x]=\"i * 100\"\n y=\"5\"\n font-family=\"sans-serif\"\n font-size=\"12\"\n fill=\"#666666\"\n >\n {{ tag.Name }}\n </text>\n } @if (swimlane.tags.length > 3) {\n <text\n [attr.x]=\"3 * 100 + 10\"\n y=\"5\"\n font-family=\"sans-serif\"\n font-size=\"12\"\n fill=\"#666666\"\n >\n +{{ swimlane.tags.length - 3 }} more\n </text>\n }\n </g>\n\n <!-- Render nodes in this swimlane -->\n @for (node of swimlane.nodes; track node.id) {\n <g\n [attr.transform]=\"'translate(' + node.x + ',' + (node.y + 40) + ')'\"\n (mouseenter)=\"showConnectionPoints(node.id, swimlane.order)\"\n (mouseleave)=\"hideConnectionPoints(node.id)\"\n >\n <!-- Start node indicator (circle and arrow) for the first node -->\n @if (node.isStartNode) {\n <!-- Circle -->\n <circle\n cx=\"-30\"\n cy=\"50\"\n r=\"15\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></circle>\n <!-- Form icon for start node -->\n <svg:g\n (click)=\"\n toggleStartNodeFormPopup($event, node.x, node.y, swimlane.order)\n \"\n class=\"stage-icon\"\n transform=\"translate(-45, 42)\"\n style=\"cursor: pointer; pointer-events: all\"\n >\n <!-- Transparent rectangle to capture clicks -->\n <svg:rect\n x=\"-2\"\n y=\"-2\"\n width=\"24\"\n height=\"24\"\n fill=\"transparent\"\n style=\"cursor: pointer\"\n />\n <svg:path\n d=\"M16.5 20.475V17.475H13.5V16.475H16.5V13.475H17.5V16.475H20.5V17.475H17.5V20.475H16.5ZM3.5 17.5V16.5H4.5V17.5H3.5ZM6.5 17.5V16.5H11.517C11.5057 16.6767 11.5043 16.845 11.513 17.005C11.521 17.165 11.531 17.33 11.543 17.5H6.5ZM3.5 13.5V12.5H4.5V13.5H3.5ZM6.5 13.5V12.5H13.804C13.6127 12.6387 13.4333 12.7913 13.266 12.958C13.0993 13.1247 12.9377 13.3053 12.781 13.5H6.5ZM3.5 9.5V8.5H4.5V9.5H3.5ZM6.5 9.5V8.5H18.5V9.5H6.5ZM3.5 5.5V4.5H4.5V5.5H3.5ZM6.5 5.5V4.5H18.5V5.5H6.5Z\"\n [attr.fill]=\"state.workflowFormId ? '#D36CFF' : 'black'\"\n transform=\"scale(0.7)\"\n />\n </svg:g>\n <!-- Arrow from circle to node -->\n <path\n d=\"M -20 50 L 0 50\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n marker-end=\"url(#arrowhead)\"\n ></path>\n }\n\n <!-- Stage node -->\n @if (node.type === 'stage') {\n <!-- <rect\n x=\"0\"\n y=\"0\"\n [attr.width]=\"node.width\"\n [attr.height]=\"node.height\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></rect> -->\n <svg:g\n lib-stage-node\n [node]=\"node\"\n [isStartNode]=\"node.isStartNode\"\n (stagePropertiesUpdated)=\"onStagePropertiesUpdated($event)\"\n ></svg:g>\n }\n\n <!-- Decision node -->\n @if (node.type === 'decision') {\n <path\n [attr.d]=\"\n 'M 0 ' +\n node.height / 2 +\n ' L ' +\n node.width / 2 +\n ' 0' +\n ' L ' +\n node.width +\n ' ' +\n node.height / 2 +\n ' L ' +\n node.width / 2 +\n ' ' +\n node.height +\n ' Z'\n \"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></path>\n }\n\n <!-- Form node -->\n @if (node.type === 'form') {\n <path\n d=\"M95.0625 50.5591V95.0625C95.0625 97.9716 93.9069 100.762 91.8498 102.819C89.7928 104.876 87.0028 106.031 84.0938 106.031H32.9062C29.9972 106.031 27.2072 104.876 25.1502 102.819C23.0931 100.762 21.9375 97.9716 21.9375 95.0625V21.9375C21.9375 19.0284 23.0931 16.2385 25.1502 14.1814C27.2072 12.1244 29.9972 10.9688 32.9062 10.9688H55.4722C57.4109 10.969 59.2701 11.7392 60.6412 13.1099L92.9213 45.3901C94.292 46.7611 95.0622 48.6204 95.0625 50.5591Z\"\n transform=\"scale(0.7)\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M58.5 12.7969V40.2188C58.5 42.1581 59.2704 44.0181 60.6418 45.3895C62.0131 46.7608 63.8731 47.5312 65.8125 47.5312H93.2344\"\n transform=\"scale(0.7)\"\n stroke=\"#D36CFF\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <text\n x=\"50%\"\n y=\"50%\"\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n font-family=\"sans-serif\"\n font-size=\"14\"\n fill=\"#D36CFF\"\n >\n Form\n </text>\n }\n\n <!-- Subflow node -->\n @if (node.type === 'subflow') {\n <path\n [attr.d]=\"\n 'M 1 ' +\n node.height / 4 +\n ' L ' +\n node.width / 2 +\n ' 1 L ' +\n (node.width - 1) +\n ' ' +\n node.height / 4 +\n ' V ' +\n (node.height * 3) / 4 +\n ' L ' +\n node.width / 2 +\n ' ' +\n (node.height - 1) +\n ' L 1 ' +\n (node.height * 3) / 4 +\n ' Z'\n \"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></path>\n <text\n x=\"50%\"\n y=\"50%\"\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n font-family=\"sans-serif\"\n font-size=\"14\"\n fill=\"#000000\"\n >\n {{ node.workflowData?.name || \"Subflow\" }}\n </text>\n }\n\n <!-- Connection points for this node -->\n @for (point of node.connectionPoints || []; track point.id) { @if\n (isConnectionPointVisible(node.id)) {\n <use\n [attr.href]=\"'#connection-point-template'\"\n [attr.x]=\"point.x\"\n [attr.y]=\"point.y\"\n [attr.id]=\"point.id\"\n (mousedown)=\"startConnectionDrag($event, point, swimlane.order)\"\n />\n } }\n </g>\n <!-- A transparent hover area for improved hover detection -->\n <rect\n [attr.x]=\"node.x - 10\"\n [attr.y]=\"node.y + 40 - 10\"\n [attr.width]=\"node.width + 20\"\n [attr.height]=\"node.height + 20\"\n fill=\"transparent\"\n (mouseover)=\"showConnectionPoints(node.id, swimlane.order)\"\n (mouseout)=\"hideConnectionPoints(node.id)\"\n style=\"pointer-events: none\"\n />\n }\n </g>\n } @for (connection of state.connections; track connection.id) {\n <g>\n <path\n [attr.d]=\"getConnectionPathForSavedConnection(connection)\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n fill=\"none\"\n marker-end=\"url(#arrowhead)\"\n ></path>\n </g>\n }\n\n <!-- Connection preview line -->\n @if (state.isConnectionDragging()) {\n <g>\n <path\n [attr.d]=\"getConnectionPath()\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n stroke-dasharray=\"5,5\"\n fill=\"none\"\n ></path>\n </g>\n }\n </svg>\n\n <div\n *ngIf=\"popupVisible\"\n [style.position]=\"'absolute'\"\n [style.left.px]=\"popupX\"\n [style.top.px]=\"popupY\"\n >\n <verben-pop-Up\n [dropdownOpen]=\"true\"\n [customStyles]=\"{ 'z-index': '99' }\"\n [enableMouseLeave]=\"false\"\n >\n <div dropdown-trigger style=\"display: none\">\n <!-- Hidden trigger element -->\n </div>\n <div\n class=\"p-3 bg-white border border-gray-200 rounded shadow-md\"\n dropdown-content\n >\n <h4 class=\"mb-2 font-medium\">Create Connection</h4>\n <div class=\"flex flex-col gap-2\">\n <ng-container *ngFor=\"let type of allowedNodeTypes\">\n <button\n class=\"px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50\"\n (click)=\"createNodeConnection(type)\"\n >\n Create {{ type | titlecase }}\n </button>\n </ng-container>\n <button\n class=\"px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50\"\n (click)=\"hideConnectionPopup()\"\n >\n Cancel\n </button>\n </div>\n </div>\n </verben-pop-Up>\n </div>\n\n <div\n *ngIf=\"showStartNodeFormPopup\"\n [style.position]=\"'absolute'\"\n [style.left.px]=\"startNodeFormPopupX\"\n [style.top.px]=\"startNodeFormPopupY\"\n >\n <verben-pop-Up [dropdownOpen]=\"true\" [customStyles]=\"{ 'z-index': '100' }\">\n <div dropdown-trigger style=\"display: none\">\n <!-- Hidden trigger element -->\n </div>\n <div\n class=\"p-3 bg-white border border-gray-200 rounded shadow-md w-64\"\n dropdown-content\n style=\"background-color: white; z-index: 1000\"\n >\n <h4 class=\"mb-2 font-medium\">Select Workflow Form</h4>\n <div *ngIf=\"isLoadingStartNodeForms\" class=\"text-center py-2\">\n Loading forms...\n </div>\n <div *ngIf=\"!isLoadingStartNodeForms\" class=\"max-h-48 overflow-y-auto\">\n <div class=\"mb-2\">\n <button\n class=\"w-full px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50 text-left\"\n (click)=\"selectStartNodeForm(null)\"\n >\n Clear form selection\n </button>\n </div>\n <div *ngFor=\"let form of startNodeFormsList\" class=\"mb-1\">\n <button\n class=\"w-full px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50 text-left\"\n (click)=\"selectStartNodeForm(form)\"\n >\n {{ form.Name }}\n </button>\n </div>\n <div\n *ngIf=\"startNodeFormsList.length === 0\"\n class=\"text-center py-2 text-gray-500\"\n >\n No forms available\n </div>\n </div>\n </div>\n </verben-pop-Up>\n </div>\n\n <div\n *ngIf=\"showSubflowPopup\"\n [style.position]=\"'fiabsolutexed'\"\n [style.left.px]=\"subflowPopupX\"\n [style.top.px]=\"subflowPopupY\"\n >\n <verben-pop-Up [dropdownOpen]=\"true\" [customStyles]=\"{ 'z-index': '100' }\">\n <div dropdown-trigger style=\"display: none\">\n <!-- Hidden trigger element -->\n </div>\n <div\n class=\"p-3 bg-white border border-gray-200 rounded shadow-md w-64\"\n dropdown-content\n style=\"background-color: white; z-index: 1000\"\n >\n <h4 class=\"mb-2 font-medium\">Select Workflow</h4>\n <div *ngIf=\"isLoadingWorkflows\" class=\"text-center py-2\">\n Loading workflows...\n </div>\n <div *ngIf=\"!isLoadingWorkflows\" class=\"max-h-48 overflow-y-auto\">\n <div *ngFor=\"let workflow of workflowsList\" class=\"mb-1\">\n <button\n class=\"w-full px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50 text-left\"\n (click)=\"selectSubflowWorkflow(workflow)\"\n >\n {{ workflow.Name }}\n </button>\n </div>\n <div\n *ngIf=\"workflowsList.length === 0\"\n class=\"text-center py-2 text-gray-500\"\n >\n No workflows available\n </div>\n </div>\n </div>\n </verben-pop-Up>\n </div>\n</div>\n", styles: [".canvas-container{flex:1;overflow:auto;background-color:#fff}.designer-canvas{min-width:100%;min-height:100%;cursor:default}.designer-canvas:focus{outline:none}.edit-swimlane-button{cursor:pointer}.edit-swimlane-button:hover rect{fill:#ddd6fe}\n"] }]
743
+ args: [{ selector: 'lib-designer-canvas', template: "<div class=\"canvas-container\">\n <svg\n #canvas\n [attr.width]=\"canvasWidth\"\n [attr.height]=\"canvasHeight\"\n class=\"designer-canvas\"\n (click)=\"onCanvasClick($event)\"\n >\n <defs>\n <!-- Grid pattern definition -->\n\n <pattern\n id=\"grid\"\n [attr.width]=\"gridSize\"\n [attr.height]=\"gridSize\"\n patternUnits=\"userSpaceOnUse\"\n >\n <path\n d=\"M 20 0 L 0 0 0 20\"\n fill=\"none\"\n stroke=\"#e2e8f0\"\n stroke-width=\"0.5\"\n />\n </pattern>\n\n <!-- Arrow head marker definition -->\n <marker\n id=\"arrowhead\"\n markerWidth=\"10\"\n markerHeight=\"7\"\n refX=\"9\"\n refY=\"3.5\"\n orient=\"auto\"\n >\n <polygon points=\"0 0, 10 3.5, 0 7\" fill=\"#D36CFF\" />\n </marker>\n\n <!-- Connection point styles -->\n <circle\n id=\"connection-point-template\"\n r=\"5\"\n fill=\"#D36CFF\"\n stroke=\"#FFFFFF\"\n stroke-width=\"1\"\n />\n\n <!-- Dashed line style for connection preview -->\n <pattern\n id=\"dashed-line\"\n width=\"10\"\n height=\"10\"\n patternUnits=\"userSpaceOnUse\"\n >\n <line\n x1=\"0\"\n y1=\"5\"\n x2=\"10\"\n y2=\"5\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n stroke-dasharray=\"5,5\"\n />\n </pattern>\n\n @for (swimlane of state.swimlanes; track swimlane.order) {\n <clipPath [attr.id]=\"'swimlane-clip-' + swimlane.order\">\n <rect x=\"0\" y=\"0\" [attr.width]=\"canvasWidth\" height=\"263\" />\n </clipPath>\n }\n </defs>\n\n <!-- Background grid -->\n <rect width=\"100%\" height=\"100%\" fill=\"url(#grid)\" />\n\n <!-- Display a message when no swimlanes exist -->\n @if (state.swimlanes.length === 0) {\n <text\n x=\"50%\"\n y=\"50%\"\n font-family=\"sans-serif\"\n font-size=\"16\"\n fill=\"#94a3b8\"\n text-anchor=\"middle\"\n >\n Select the Swimlane tool and click on the canvas to add a swimlane\n </text>\n }\n\n <!-- This is where workflow elements will be added later -->\n @for (swimlane of state.swimlanes; track swimlane.order) {\n <g\n [attr.transform]=\"'translate(0,' + swimlane.order * 263 + ')'\"\n [attr.clip-path]=\"'url(#swimlane-clip-' + swimlane.order + ')'\"\n >\n <!-- Swimlane container -->\n <rect\n x=\"0\"\n y=\"0\"\n [attr.width]=\"canvasWidth\"\n [attr.height]=\"263\"\n fill=\"#ffffff\"\n stroke=\"#e2e8f0\"\n stroke-width=\"1\"\n ></rect>\n\n <!-- Swimlane header -->\n <rect\n x=\"0\"\n y=\"0\"\n [attr.width]=\"canvasWidth\"\n height=\"40\"\n fill=\"#f8fafc\"\n stroke=\"#e2e8f0\"\n stroke-width=\"1\"\n ></rect>\n\n <!-- Swimlane label -->\n <text\n x=\"20\"\n y=\"25\"\n font-family=\"sans-serif\"\n font-size=\"14\"\n fill=\"#333333\"\n font-weight=\"bold\"\n >\n {{ swimlane.label }}\n </text>\n\n <!-- Edit button -->\n <g\n class=\"edit-swimlane-button\"\n [attr.transform]=\"'translate(100, 20)'\"\n (click)=\"\n onEditSwimlane($event, swimlane, swimlane.order);\n $event.stopPropagation()\n \"\n >\n <rect\n x=\"-5\"\n y=\"-15\"\n width=\"40\"\n height=\"20\"\n fill=\"#f3e8ff\"\n rx=\"3\"\n ry=\"3\"\n stroke=\"#d8b4fe\"\n stroke-width=\"1\"\n ></rect>\n <text\n x=\"15\"\n y=\"0\"\n font-family=\"sans-serif\"\n font-size=\"12\"\n fill=\"#7e22ce\"\n text-anchor=\"middle\"\n >\n Edit\n </text>\n </g>\n\n <!-- Tag indicators -->\n <g [attr.transform]=\"'translate(200, 20)'\">\n @for (tag of swimlane.tags.slice(0, 3); track tag.Name; let i = $index)\n {\n <text\n [attr.x]=\"i * 100\"\n y=\"5\"\n font-family=\"sans-serif\"\n font-size=\"12\"\n fill=\"#666666\"\n >\n {{ tag.Name }}\n </text>\n } @if (swimlane.tags.length > 3) {\n <text\n [attr.x]=\"3 * 100 + 10\"\n y=\"5\"\n font-family=\"sans-serif\"\n font-size=\"12\"\n fill=\"#666666\"\n >\n +{{ swimlane.tags.length - 3 }} more\n </text>\n }\n </g>\n </g>\n }\n\n <!-- Nodes -->\n @for (swimlane of state.swimlanes; track swimlane.order) {\n <!-- Render nodes in this swimlane -->\n @for (node of swimlane.nodes; track node.id) {\n <g\n class=\"node-element\"\n [attr.transform]=\"'translate(' + node.x + ',' + (node.y + 40) + ')'\"\n (mouseenter)=\"showConnectionPoints(node.id, swimlane.order)\"\n (mouseleave)=\"hideConnectionPoints(node.id)\"\n >\n <!-- Start node indicator (circle and arrow) for the first node -->\n @if (node.isStartNode) {\n <!-- Circle -->\n <circle\n cx=\"-30\"\n cy=\"50\"\n r=\"15\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></circle>\n <!-- Form icon for start node -->\n <svg:g\n (click)=\"\n toggleStartNodeFormPopup($event, node.x, node.y, swimlane.order)\n \"\n class=\"stage-icon\"\n transform=\"translate(-45, 42)\"\n style=\"cursor: pointer; pointer-events: all\"\n >\n <!-- Transparent rectangle to capture clicks -->\n <svg:rect\n x=\"-2\"\n y=\"-2\"\n width=\"24\"\n height=\"24\"\n fill=\"transparent\"\n style=\"cursor: pointer\"\n />\n <svg:path\n d=\"M16.5 20.475V17.475H13.5V16.475H16.5V13.475H17.5V16.475H20.5V17.475H17.5V20.475H16.5ZM3.5 17.5V16.5H4.5V17.5H3.5ZM6.5 17.5V16.5H11.517C11.5057 16.6767 11.5043 16.845 11.513 17.005C11.521 17.165 11.531 17.33 11.543 17.5H6.5ZM3.5 13.5V12.5H4.5V13.5H3.5ZM6.5 13.5V12.5H13.804C13.6127 12.6387 13.4333 12.7913 13.266 12.958C13.0993 13.1247 12.9377 13.3053 12.781 13.5H6.5ZM3.5 9.5V8.5H4.5V9.5H3.5ZM6.5 9.5V8.5H18.5V9.5H6.5ZM3.5 5.5V4.5H4.5V5.5H3.5ZM6.5 5.5V4.5H18.5V5.5H6.5Z\"\n [attr.fill]=\"state.workflowFormId ? '#D36CFF' : 'black'\"\n transform=\"scale(0.7)\"\n />\n </svg:g>\n <!-- Arrow from circle to node -->\n <path\n d=\"M -20 50 L 0 50\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n marker-end=\"url(#arrowhead)\"\n ></path>\n }\n\n <!-- Exit point indicator (circle and arrow) -->\n @if (node.stageData?.IsExitPoint) {\n <!-- Arrow from node to circle -->\n <path\n [attr.d]=\"'M ' + node.width + ' 50 L ' + (node.width + 20) + ' 50'\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n marker-end=\"url(#arrowhead)\"\n ></path>\n <!-- Circle -->\n <circle\n [attr.cx]=\"node.width + 50\"\n cy=\"50\"\n r=\"30\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n ></circle>\n }\n\n <!-- Stage node -->\n @if (node.type === 'stage') {\n <!-- <rect\n x=\"0\"\n y=\"0\"\n [attr.width]=\"node.width\"\n [attr.height]=\"node.height\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></rect> -->\n <svg:g\n lib-stage-node\n [node]=\"node\"\n [isStartNode]=\"node.isStartNode\"\n (stagePropertiesUpdated)=\"onStagePropertiesUpdated($event)\"\n (showShieldDialog)=\"onShowShieldDialog($event)\"\n ></svg:g>\n }\n\n <!-- Decision node -->\n @if (node.type === 'decision') {\n <path\n [attr.d]=\"\n 'M 0 ' +\n node.height / 2 +\n ' L ' +\n node.width / 2 +\n ' 0' +\n ' L ' +\n node.width +\n ' ' +\n node.height / 2 +\n ' L ' +\n node.width / 2 +\n ' ' +\n node.height +\n ' Z'\n \"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></path>\n\n <!-- Decision node condition indicator icon -->\n <svg:g\n (click)=\"showDecisionConditionsPopup($event, node, swimlane.order)\"\n class=\"decision-condition-icon\"\n [attr.transform]=\"\n 'translate(' +\n (node.width / 2 - 10) +\n ',' +\n (node.height / 2 - 10) +\n ')'\n \"\n >\n <svg:rect\n x=\"-5\"\n y=\"-5\"\n width=\"30\"\n height=\"30\"\n fill=\"transparent\"\n style=\"cursor: pointer\"\n />\n <svg:path\n d=\"M10 0H20V2H10V0ZM10 8H20V10H10V8ZM10 4H20V6H10V4ZM0 0H8V2H0V0ZM0 8H8V10H0V8ZM0 4H8V6H0V4Z\"\n fill=\"#D36CFF\"\n />\n </svg:g>\n }\n\n <!-- Form node -->\n @if (node.type === 'form') {\n <path\n d=\"M95.0625 50.5591V95.0625C95.0625 97.9716 93.9069 100.762 91.8498 102.819C89.7928 104.876 87.0028 106.031 84.0938 106.031H32.9062C29.9972 106.031 27.2072 104.876 25.1502 102.819C23.0931 100.762 21.9375 97.9716 21.9375 95.0625V21.9375C21.9375 19.0284 23.0931 16.2385 25.1502 14.1814C27.2072 12.1244 29.9972 10.9688 32.9062 10.9688H55.4722C57.4109 10.969 59.2701 11.7392 60.6412 13.1099L92.9213 45.3901C94.292 46.7611 95.0622 48.6204 95.0625 50.5591Z\"\n transform=\"scale(0.7)\"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M58.5 12.7969V40.2188C58.5 42.1581 59.2704 44.0181 60.6418 45.3895C62.0131 46.7608 63.8731 47.5312 65.8125 47.5312H93.2344\"\n transform=\"scale(0.7)\"\n stroke=\"#D36CFF\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <text\n x=\"50%\"\n y=\"50%\"\n text-anchor=\"middle\"\n dominant-baseline=\"middle\"\n font-family=\"sans-serif\"\n font-size=\"14\"\n fill=\"#D36CFF\"\n >\n Form\n </text>\n }\n\n <!-- Subflow node -->\n @if (node.type === 'subflow') {\n <path\n [attr.d]=\"\n 'M 1 ' +\n node.height / 4 +\n ' L ' +\n node.width / 2 +\n ' 1 L ' +\n (node.width - 1) +\n ' ' +\n node.height / 4 +\n ' V ' +\n (node.height * 3) / 4 +\n ' L ' +\n node.width / 2 +\n ' ' +\n (node.height - 1) +\n ' L 1 ' +\n (node.height * 3) / 4 +\n ' Z'\n \"\n fill=\"none\"\n stroke=\"#D36CFF\"\n stroke-width=\"1\"\n ></path>\n <text\n [attr.x]=\"node.width / 2\"\n [attr.y]=\"node.height / 2\"\n text-anchor=\"middle\"\n alignment-baseline=\"middle\"\n font-family=\"sans-serif\"\n font-size=\"10\"\n fill=\"#000000\"\n >\n <!-- Limit text length -->\n {{\n (node.workflowData?.name || \"Subflow\").length > 12\n ? (node.workflowData?.name || \"Subflow\").substring(0, 10) + \"...\"\n : node.workflowData?.name || \"Subflow\"\n }}\n </text>\n }\n\n <!-- Connection points for this node -->\n @for (point of node.connectionPoints || []; track point.id) { @if\n (isConnectionPointVisible(node.id)) {\n <use\n [attr.href]=\"'#connection-point-template'\"\n [attr.x]=\"point.x\"\n [attr.y]=\"point.y\"\n [attr.id]=\"point.id\"\n (mousedown)=\"startConnectionDrag($event, point, swimlane.order)\"\n />\n } }\n </g>\n <!-- A transparent hover area for improved hover detection -->\n <rect\n [attr.x]=\"node.x - 10\"\n [attr.y]=\"node.y + 40 - 10\"\n [attr.width]=\"node.width + 20\"\n [attr.height]=\"node.height + 20\"\n fill=\"transparent\"\n (mouseover)=\"showConnectionPoints(node.id, swimlane.order)\"\n (mouseout)=\"hideConnectionPoints(node.id)\"\n style=\"pointer-events: none\"\n />\n } }\n\n <!-- Connections -->\n @for (connection of state.connections; track connection.id) {\n <g class=\"connection-element\">\n <path\n [attr.d]=\"getConnectionPathForSavedConnection(connection)\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n fill=\"none\"\n marker-end=\"url(#arrowhead)\"\n ></path>\n </g>\n }\n\n <!-- Connection preview line -->\n @if (state.isConnectionDragging()) {\n <g>\n <path\n [attr.d]=\"getConnectionPath()\"\n stroke=\"#D36CFF\"\n stroke-width=\"2\"\n stroke-dasharray=\"5,5\"\n fill=\"none\"\n ></path>\n </g>\n }\n </svg>\n\n <div\n *ngIf=\"popupVisible\"\n [style.position]=\"'absolute'\"\n [style.left.px]=\"popupX\"\n [style.top.px]=\"popupY\"\n >\n <verben-pop-Up\n [dropdownOpen]=\"true\"\n [customStyles]=\"{ 'z-index': '99' }\"\n [enableMouseLeave]=\"false\"\n >\n <div dropdown-trigger style=\"display: none\">\n <!-- Hidden trigger element -->\n </div>\n <div\n class=\"p-3 bg-white border border-gray-200 rounded shadow-md\"\n dropdown-content\n >\n <h4 class=\"mb-2 font-medium\">Create Connection</h4>\n <div class=\"flex flex-col gap-2\">\n <ng-container *ngFor=\"let type of allowedNodeTypes\">\n <button\n class=\"px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50\"\n (click)=\"createNodeConnection(type)\"\n >\n Create {{ type | titlecase }}\n </button>\n </ng-container>\n <button\n class=\"px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50\"\n (click)=\"hideConnectionPopup()\"\n >\n Cancel\n </button>\n </div>\n </div>\n </verben-pop-Up>\n </div>\n\n <div\n *ngIf=\"showStartNodeFormPopup\"\n [style.position]=\"'absolute'\"\n [style.left.px]=\"startNodeFormPopupX\"\n [style.top.px]=\"startNodeFormPopupY\"\n >\n <verben-pop-Up [dropdownOpen]=\"true\" [customStyles]=\"{ 'z-index': '100' }\">\n <div dropdown-trigger style=\"display: none\">\n <!-- Hidden trigger element -->\n </div>\n <div\n class=\"p-3 bg-white border border-gray-200 rounded shadow-md w-64\"\n dropdown-content\n style=\"background-color: white; z-index: 1000\"\n >\n <h4 class=\"mb-2 font-medium\">Select Workflow Form</h4>\n <div *ngIf=\"isLoadingStartNodeForms\" class=\"text-center py-2\">\n Loading forms...\n </div>\n <div *ngIf=\"!isLoadingStartNodeForms\" class=\"max-h-48 overflow-y-auto\">\n <div class=\"mb-2\">\n <button\n class=\"w-full px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50 text-left\"\n (click)=\"selectStartNodeForm(null)\"\n >\n Clear form selection\n </button>\n </div>\n <div *ngFor=\"let form of startNodeFormsList\" class=\"mb-1\">\n <button\n class=\"w-full px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50 text-left\"\n (click)=\"selectStartNodeForm(form)\"\n >\n {{ form.Name }}\n </button>\n </div>\n <div\n *ngIf=\"startNodeFormsList.length === 0\"\n class=\"text-center py-2 text-gray-500\"\n >\n No forms available\n </div>\n </div>\n </div>\n </verben-pop-Up>\n </div>\n\n <div\n *ngIf=\"showSubflowPopup\"\n [style.position]=\"'absolute'\"\n [style.left.px]=\"subflowPopupX\"\n [style.top.px]=\"subflowPopupY\"\n >\n <verben-pop-Up [dropdownOpen]=\"true\" [customStyles]=\"{ 'z-index': '100' }\">\n <div dropdown-trigger style=\"display: none\">\n <!-- Hidden trigger element -->\n </div>\n <div\n class=\"p-3 bg-white border border-gray-200 rounded shadow-md w-64\"\n dropdown-content\n style=\"background-color: white; z-index: 1000\"\n >\n <h4 class=\"mb-2 font-medium\">Select Workflow</h4>\n <div *ngIf=\"isLoadingWorkflows\" class=\"text-center py-2\">\n Loading workflows...\n </div>\n <div *ngIf=\"!isLoadingWorkflows\" class=\"max-h-48 overflow-y-auto\">\n <div *ngFor=\"let workflow of workflowsList\" class=\"mb-1\">\n <button\n class=\"w-full px-3 py-2 bg-white border border-gray-200 rounded text-sm hover:bg-gray-50 text-left\"\n (click)=\"selectSubflowWorkflow(workflow)\"\n >\n {{ workflow.Name }}\n </button>\n </div>\n <div\n *ngIf=\"workflowsList.length === 0\"\n class=\"text-center py-2 text-gray-500\"\n >\n No workflows available\n </div>\n </div>\n </div>\n </verben-pop-Up>\n </div>\n\n <lib-conditions-popup\n [visible]=\"showDecisionConditionDialog\"\n [decisionNodeId]=\"activeDecisionNodeId\"\n [newConnectionId]=\"activeConnectionId\"\n [popupX]=\"decisionConditionPopupX\"\n [popupY]=\"decisionConditionPopupY\"\n (closed)=\"onDecisionConditionCancelled()\"\n (saved)=\"onDecisionConditionSaved($event)\"\n ></lib-conditions-popup>\n\n <!-- <lib-decision-popup\n [visible]=\"showConditionsDialog\"\n [decisionNodeId]=\"activeDecisionNodeId\"\n [popupX]=\"decisionConditionPopupX\"\n [popupY]=\"decisionConditionPopupY\"\n (closed)=\"onDecisionConditionCancelled()\"\n ></lib-decision-popup> -->\n\n <lib-stage-dialog\n [visible]=\"showStageDialogLocal\"\n [stageData]=\"activeStageData || {}\"\n (closed)=\"onStageDialogClosed()\"\n (saved)=\"onStageDialogSaved($event)\"\n ></lib-stage-dialog>\n</div>\n", styles: [".canvas-container{flex:1;overflow:auto;background-color:#fff}.designer-canvas{min-width:100%;min-height:100%;cursor:default}.designer-canvas:focus{outline:none}.edit-swimlane-button{cursor:pointer}.edit-swimlane-button:hover rect{fill:#ddd6fe}.decision-condition-icon{cursor:pointer}.decision-condition-icon:hover path{fill:#c084fc}.swimlane-label{z-index:10;cursor:default}.plus-icon:hover{fill:#d36cff}.swimlane-container{pointer-events:none}.swimlane-container>*{pointer-events:auto}.node-element{z-index:10}.connection-element{z-index:5}\n"] }]
518
744
  }], ctorParameters: () => [{ type: i1.WorkflowDesignerState }, { type: i2.WorkflowDataService }], propDecorators: { selectedTool: [{
519
745
  type: Input
520
746
  }], clickedPosition: [{
@@ -523,6 +749,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
523
749
  type: Output
524
750
  }], showStageDialog: [{
525
751
  type: Output
752
+ }], stagePropertiesUpdated: [{
753
+ type: Output
526
754
  }], canvasRef: [{
527
755
  type: ViewChild,
528
756
  args: ['canvas', { static: true }]
@@ -533,4 +761,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
533
761
  type: HostListener,
534
762
  args: ['document:click', ['$event']]
535
763
  }] } });
536
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVzaWduZXItY2FudmFzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3ZlcmJlbi13b3JrZmxvdy11aS9zcmMvbGliL2NvbXBvbmVudHMvd29ya2Zsb3ctZGVzaWduZXIvZGVzaWduZXItY2FudmFzL2Rlc2lnbmVyLWNhbnZhcy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy92ZXJiZW4td29ya2Zsb3ctdWkvc3JjL2xpYi9jb21wb25lbnRzL3dvcmtmbG93LWRlc2lnbmVyL2Rlc2lnbmVyLWNhbnZhcy9kZXNpZ25lci1jYW52YXMuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFFVCxZQUFZLEVBQ1osWUFBWSxFQUNaLEtBQUssRUFFTCxNQUFNLEVBQ04sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFDOzs7Ozs7O0FBbUJ2QixNQUFNLE9BQU8sdUJBQXVCO0lBK0R6QjtJQUNDO0lBL0RELFlBQVksR0FBYSxJQUFJLENBQUM7SUFDN0IsZUFBZSxHQUFHLElBQUksWUFBWSxFQUE0QixDQUFDO0lBQy9ELGVBQWUsR0FBRyxJQUFJLFlBQVksRUFBRSxDQUFDO0lBQy9DLG9CQUFvQixHQUNsQixJQUFJLENBQUM7SUFDRyxlQUFlLEdBQUcsSUFBSSxZQUFZLEVBR3hDLENBQUM7SUFFTCwrQkFBK0I7SUFDUSxTQUFTLENBQTBCO0lBRzFFLGVBQWUsQ0FBQyxLQUFpQjtRQUMvQixzRUFBc0U7UUFDdEUsSUFDRSxDQUFDLElBQUksQ0FBQyxnQkFBZ0I7WUFDdEIsQ0FBQyxJQUFJLENBQUMsc0JBQXNCO1lBQzVCLENBQUMsSUFBSSxDQUFDLFlBQVksSUFBSSx1Q0FBdUM7WUFDN0QsSUFBSSxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsRUFBRSxFQUNqQyxDQUFDO1lBQ0QsT0FBTyxDQUFDLEdBQUcsQ0FB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QyxzQkFBc0IsR0FBRyxJQUFJLENBQUM7UUFDbkMsSUFBSSxDQUFDLDRCQUE0QixHQUFHLElBQUksQ0FBQztRQUN6QyxJQUFJLENBQUMsb0NBQW9DLEdBQUcsSUFBSSxDQUFDO0lBQ25ELENBQUM7d0dBOXJCVSx1QkFBdUI7NEZBQXZCLHVCQUF1QixvY0M1QnBDLHU5ZUFvZ0JBOzs0RkR4ZWEsdUJBQXVCO2tCQUxuQyxTQUFTOytCQUNFLHFCQUFxQjs0SEFLdEIsWUFBWTtzQkFBcEIsS0FBSztnQkFDSSxlQUFlO3NCQUF4QixNQUFNO2dCQUNHLGVBQWU7c0JBQXhCLE1BQU07Z0JBR0csZUFBZTtzQkFBeEIsTUFBTTtnQkFNZ0MsU0FBUztzQkFBL0MsU0FBUzt1QkFBQyxRQUFRLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUdyQyxlQUFlO3NCQURkLFlBQVk7dUJBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBc1AxQyxlQUFlO3NCQURkLFlBQVk7dUJBQUMsZ0JBQWdCLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIEVsZW1lbnRSZWYsXG4gIEV2ZW50RW1pdHRlcixcbiAgSG9zdExpc3RlbmVyLFxuICBJbnB1dCxcbiAgT25Jbml0LFxuICBPdXRwdXQsXG4gIFZpZXdDaGlsZCxcbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1xuICBDb25uZWN0aW9uLFxuICBDb25uZWN0aW9uUG9pbnQsXG4gIE5vZGUgYXMgV0ZOb2RlLFxuICBUb29sVHlwZSxcbiAgU3dpbWxhbmVJdGVtLFxufSBmcm9tICcuLi93b3JrZmxvdy1kZXNpZ25lci50eXBlcyc7XG5pbXBvcnQgeyBXb3JrZmxvd0Rlc2lnbmVyU3RhdGUgfSBmcm9tICcuLi93b3JrZmxvdy1kZXNpZ25lci5zdGF0ZSc7XG5pbXBvcnQgeyBXb3JrZmxvd1N0YWdlIH0gZnJvbSAnLi4vLi4vLi4vbW9kZWxzL1dvcmtmbG93U3RhZ2UnO1xuaW1wb3J0IHsgRm9ybUVudGl0eSB9IGZyb20gJy4uLy4uLy4uL21vZGVscy9Gb3JtRW50aXR5JztcbmltcG9ydCB7IFdvcmtmbG93IH0gZnJvbSAnLi4vLi4vLi4vbW9kZWxzL1dvcmtmbG93JztcbmltcG9ydCB7IFdvcmtmbG93RGF0YVNlcnZpY2UgfSBmcm9tICcuLi93b3JrZmxvdy1kYXRhLnNlcnZpY2UnO1xuXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICdsaWItZGVzaWduZXItY2FudmFzJyxcbiAgdGVtcGxhdGVVcmw6ICcuL2Rlc2lnbmVyLWNhbnZhcy5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsOiAnLi9kZXNpZ25lci1jYW52YXMuY29tcG9uZW50LmNzcycsXG59KVxuZXhwb3J0IGNsYXNzIERlc2lnbmVyQ2FudmFzQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcbiAgQElucHV0KCkgc2VsZWN0ZWRUb29sOiBUb29sVHlwZSA9IG51bGw7XG4gIEBPdXRwdXQoKSBjbGlja2VkUG9zaXRpb24gPSBuZXcgRXZlbnRFbWl0dGVyPHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfT4oKTtcbiAgQE91dHB1dCgpIHN1YmZsb3dTZWxlY3RlZCA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgcGVuZGluZ1N0YWdlUG9zaXRpb246IHsgc3dpbWxhbmVJbmRleDogbnVtYmVyOyB4OiBudW1iZXI7IHk6IG51bWJlciB9IHwgbnVsbCA9XG4gICAgbnVsbDtcbiAgQE91dHB1dCgpIHNob3dTdGFnZURpYWxvZyA9IG5ldyBFdmVudEVtaXR0ZXI8e1xuICAgIHBvc2l0aW9uOiBhbnk7XG4gICAgaXNGcm9tQ29ubmVjdGlvbjogYm9vbGVhbjtcbiAgfT4oKTtcblxuICAvLyBSZWZlcmVuY2UgdG8gdGhlIFNWRyBlbGVtZW50XG4gIEBWaWV3Q2hpbGQoJ2NhbnZhcycsIHsgc3RhdGljOiB0cnVlIH0pIGNhbnZhc1JlZiE6IEVsZW1lbnRSZWY8U1ZHRWxlbWVudD47XG5cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93Om1vdXNldXAnLCBbJyRldmVudCddKVxuICBvbldpbmRvd01vdXNlVXAoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICAvLyBJZiB3ZSBoYXZlIGEgcG9wdXAgb3BlbiBidXQgdGhlIG1vdXNlIGlzIHJlbGVhc2VkIG91dHNpZGUsIGNsZWFuIHVwXG4gICAgaWYgKFxuICAgICAgIXRoaXMuc2hvd1N1YmZsb3dQb3B1cCAmJlxuICAgICAgIXRoaXMuc2hvd1N0YXJ0Tm9kZUZvcm1Qb3B1cCAmJlxuICAgICAgIXRoaXMucG9wdXBWaXNpYmxlICYmIC8vIE9ubHkgZW5kIGRyYWcgaWYgbm8gcG9wdXAgaXMgdmlzaWJsZVxuICAgICAgdGhpcy5zdGF0ZS5pc0Nvbm5lY3Rpb25EcmFnZ2luZygpXG4gICAgKSB7XG4gICAgICBjb25zb2xlLmxvZygnRXh0ZXJuYWwgbW91c2V1cCBkZXRlY3RlZCAtIGNsZWFuaW5nIHVwIGNvbm5lY3Rpb24gZHJhZycpO1xuICAgICAgdGhpcy5zdGF0ZS5lbmRDb25uZWN0aW9uRHJhZygpO1xuICAgIH1cbiAgfVxuXG4gIC8vIENhbnZhcyBkaW1lbnNpb25zXG4gIGNhbnZhc1dpZHRoID0gMzAwMDtcbiAgY2FudmFzSGVpZ2h0ID0gMjAwMDtcblxuICAvLyBHcmlkIHNpemVcbiAgZ3JpZFNpemUgPSAyMDtcblxuICBzd2ltbGFuZUhlaWdodCA9IDI2MztcbiAgdmlzaWJsZUNvbm5lY3Rpb25Qb2ludHNOb2RlSWQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBwb3B1cFZpc2libGUgPSBmYWxzZTtcbiAgcG9wdXBYID0gMDtcbiAgcG9wdXBZID0gMDtcbiAgYWxsb3dlZE5vZGVUeXBlczogc3RyaW5nW10gPSBbXTtcblxuICBzaG93U3RhcnROb2RlRm9ybVBvcHVwOiBib29sZWFuID0gZmFsc2U7XG4gIHN0YXJ0Tm9kZUZvcm1zTGlzdDogRm9ybUVudGl0eVtdID0gW107XG4gIGlzTG9hZGluZ1N0YXJ0Tm9kZUZvcm1zOiBib29sZWFuID0gZmFsc2U7XG4gIHN0YXJ0Tm9kZUZvcm1Qb3B1cFg6IG51bWJlciA9IDA7XG4gIHN0YXJ0Tm9kZUZvcm1Qb3B1cFk6IG51bWJlciA9IDA7XG5cbiAgc2hvd1N1YmZsb3dQb3B1cDogYm9vbGVhbiA9IGZhbHNlO1xuICB3b3JrZmxvd3NMaXN0OiBXb3JrZmxvd1tdID0gW107XG4gIGlzTG9hZGluZ1dvcmtmbG93czogYm9vbGVhbiA9IGZhbHNlO1xuICBzdWJmbG93UG9wdXBYOiBudW1iZXIgPSAwO1xuICBzdWJmbG93UG9wdXBZOiBudW1iZXIgPSAwO1xuICBwZW5kaW5nU3ViZmxvd1Bvc2l0aW9uOiB7XG4gICAgc3dpbWxhbmVJbmRleDogbnVtYmVyO1xuICAgIHg6IG51bWJlcjtcbiAgICB5OiBudW1iZXI7XG4gIH0gfCBudWxsID0gbnVsbDtcblxuICBwZW5kaW5nQ29ubmVjdGlvblNvdXJjZVBvaW50OiBDb25uZWN0aW9uUG9pbnQgfCBudWxsID0gbnVsbDtcbiAgcGVuZGluZ0Nvbm5lY3Rpb25Tb3VyY2VTd2ltbGFuZUluZGV4OiBudW1iZXIgfCBudWxsID0gbnVsbDtcblxuICBjb25zdHJ1Y3RvcihcbiAgICBwdWJsaWMgc3RhdGU6IFdvcmtmbG93RGVzaWduZXJTdGF0ZSxcbiAgICBwcml2YXRlIGRhdGFTZXJ2aWNlOiBXb3JrZmxvd0RhdGFTZXJ2aWNlXG4gICkge31cblxuICBuZ09uSW5pdCgpOiB2b2lkIHtcbiAgICB0aGlzLnVwZGF0ZUNhbnZhc1NpemUoKTtcbiAgfVxuXG4gIC8vIEhhbmRsZSBtb3VzZSBjbGljayBvbiBjYW52YXNcbiAgb25DYW52YXNDbGljayhldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIC8vIE9ubHkgcHJvY2VzcyBjYW52YXMgY2xpY2tzIGlmIGEgdG9vbCBpcyBzZWxlY3RlZFxuICAgIGlmICghdGhpcy5zZWxlY3RlZFRvb2wpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBHZXQgdGhlIHBvc2l0aW9uIHdoZXJlIHRoZSBjbGljayBvY2N1cnJlZFxuICAgIGNvbnN0IHBvc2l0aW9uID0gdGhpcy5nZXRNb3VzZVBvc2l0aW9uKGV2ZW50KTtcbiAgICBjb25zb2xlLmxvZyhcbiAgICAgICdDYW52YXMgY2xpY2tlZCBhdDonLFxuICAgICAgcG9zaXRpb24sXG4gICAgICAnd2l0aCB0b29sOicsXG4gICAgICB0aGlzLnNlbGVjdGVkVG9vbFxuICAgICk7XG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIHN3aW1sYW5lIGluZGV4IGJhc2VkIG9uIHBvc2l0aW9uXG4gICAgLy8gY29uc3Qgc3dpbWxhbmVJbmRleCA9IE1hdGguZmxvb3IocG9zaXRpb24ueSAvIHRoaXMuc3dpbWxhbmVIZWlnaHQpO1xuXG4gICAgLy8gT25seSBlbWl0IHRoZSBwb3NpdGlvbiBpZiB3ZSBoYXZlIGEgdG9vbCBzZWxlY3RlZCBhbmQgaXQncyBhIHZhbGlkIGNsaWNrIGFyZWFcbiAgICBpZiAodGhpcy5zZWxlY3RlZFRvb2wpIHtcbiAgICAgIHRoaXMuY2xpY2tlZFBvc2l0aW9uLmVtaXQoe1xuICAgICAgICB4OiBwb3NpdGlvbi54LFxuICAgICAgICB5OiBwb3NpdGlvbi55LFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgdXBkYXRlQ2FudmFzU2l6ZSgpOiB2b2lkIHtcbiAgICBjb25zdCByZXF1aXJlZEhlaWdodCA9XG4gICAgICAodGhpcy5zdGF0ZS5zd2ltbGFuZXMubGVuZ3RoICsgMSkgKiB0aGlzLnN3aW1sYW5lSGVpZ2h0O1xuICAgIHRoaXMuY2FudmFzSGVpZ2h0ID0gTWF0aC5tYXgoMjAwMCwgcmVxdWlyZWRIZWlnaHQpOyAvLyBFbnN1cmUgd2UgaGF2ZSBhdCBsZWFzdCBvdXIgZGVmYXVsdCBoZWlnaHRcbiAgfVxuXG4gIC8vIEhlbHBlciBtZXRob2QgdG8gZ2V0IHRoZSBtb3VzZSBwb3NpdGlvbiByZWxhdGl2ZSB0byB0aGUgU1ZHIGNhbnZhc1xuICBwcml2YXRlIGdldE1vdXNlUG9zaXRpb24oZXZlbnQ6IE1vdXNlRXZlbnQpOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0ge1xuICAgIC8vIFVzZSBjbGllbnRYL1kgYW5kIGdldEJvdW5kaW5nQ2xpZW50UmVjdCgpIGZvciBjcm9zcy1icm93c2VyIGNvbXBhdGliaWxpdHlcbiAgICBjb25zdCByZWN0ID0gdGhpcy5jYW52YXNSZWYubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICByZXR1cm4ge1xuICAgICAgeDogZXZlbnQuY2xpZW50WCAtIHJlY3QubGVmdCxcbiAgICAgIHk6IGV2ZW50LmNsaWVudFkgLSByZWN0LnRvcCxcbiAgICB9O1xuICB9XG5cbiAgc2hvd0Nvbm5lY3Rpb25Qb2ludHMobm9kZUlkOiBzdHJpbmcsIHN3aW1sYW5lSW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMudmlzaWJsZUNvbm5lY3Rpb25Qb2ludHNOb2RlSWQgPSBub2RlSWQ7XG4gIH1cblxuICBpc01vdXNlT3Zlck5vZGUoXG4gICAgZXZlbnQ6IE1vdXNlRXZlbnQsXG4gICAgbm9kZTogV0ZOb2RlLFxuICAgIHN3aW1sYW5lSW5kZXg6IG51bWJlclxuICApOiBib29sZWFuIHtcbiAgICBjb25zdCBwb3NpdGlvbiA9IHRoaXMuZ2V0TW91c2VQb3NpdGlvbihldmVudCk7XG4gICAgY29uc3Qgbm9kZUJvdW5kcyA9IHRoaXMuZ2V0Tm9kZUJvdW5kc1dpdGhQYWRkaW5nKG5vZGUsIHN3aW1sYW5lSW5kZXgpO1xuXG4gICAgcmV0dXJuIChcbiAgICAgIHBvc2l0aW9uLnggPj0gbm9kZUJvdW5kcy54ICYmXG4gICAgICBwb3NpdGlvbi54IDw9IG5vZGVCb3VuZHMueCArIG5vZGVCb3VuZHMud2lkdGggJiZcbiAgICAgIHBvc2l0aW9uLnkgPj0gbm9kZUJvdW5kcy55ICYmXG4gICAgICBwb3NpdGlvbi55IDw9IG5vZGVCb3VuZHMueSArIG5vZGVCb3VuZHMuaGVpZ2h0XG4gICAgKTtcbiAgfVxuXG4gIC8vIGhlbHBlciBtZXRob2QgdG8gY2FsY3VsYXRlIG5vZGUgYm91bmRzIHdpdGggcGFkZGluZ1xuICBnZXROb2RlQm91bmRzV2l0aFBhZGRpbmcoXG4gICAgbm9kZTogV0ZOb2RlLFxuICAgIHN3aW1sYW5lSW5kZXg6IG51bWJlclxuICApOiB7IHg6IG51bWJlcjsgeTogbnVtYmVyOyB3aWR0aDogbnVtYmVyOyBoZWlnaHQ6IG51bWJlciB9IHtcbiAgICBjb25zdCBwYWRkaW5nID0gMTA7IC8vIEFkZCAxMHB4IHBhZGRpbmcgYXJvdW5kIG5vZGVzIGZvciBlYXNpZXIgaG92ZXIgZGV0ZWN0aW9uXG5cbiAgICAvLyBDYWxjdWxhdGUgdGhlIGFic29sdXRlIFkgcG9zaXRpb24gaW5jbHVkaW5nIHN3aW1sYW5lIG9mZnNldFxuICAgIGNvbnN0IGFic29sdXRlWSA9IG5vZGUueSArIChzd2ltbGFuZUluZGV4ICogMjYzICsgNDApO1xuXG4gICAgcmV0dXJuIHtcbiAgICAgIHg6IG5vZGUueCAtIHBhZGRpbmcsXG4gICAgICB5OiBhYnNvbHV0ZVkgLSBwYWRkaW5nLFxuICAgICAgd2lkdGg6IG5vZGUud2lkdGggKyBwYWRkaW5nICogMixcbiAgICAgIGhlaWdodDogbm9kZS5oZWlnaHQgKyBwYWRkaW5nICogMixcbiAgICB9O1xuICB9XG5cbiAgaGlkZUNvbm5lY3Rpb25Qb2ludHMobm9kZUlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICBpZiAoXG4gICAgICB0aGlzLnZpc2libGVDb25uZWN0aW9uUG9pbnRzTm9kZUlkID09PSBub2RlSWQgJiZcbiAgICAgICF0aGlzLnN0YXRlLmlzQ29ubmVjdGlvbkRyYWdnaW5nKClcbiAgICApIHtcbiAgICAgIHRoaXMudmlzaWJsZUNvbm5lY3Rpb25Qb2ludHNOb2RlSWQgPSBudWxsO1xuICAgIH1cbiAgfVxuXG4gIGlzQ29ubmVjdGlvblBvaW50VmlzaWJsZShub2RlSWQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLnZpc2libGVDb25uZWN0aW9uUG9pbnRzTm9kZUlkID09PSBub2RlSWQ7XG4gIH1cblxuICBzdGFydENvbm5lY3Rpb25EcmFnKFxuICAgIGV2ZW50OiBNb3VzZUV2ZW50LFxuICAgIHBvaW50OiBDb25uZWN0aW9uUG9pbnQsXG4gICAgc3dpbWxhbmVJbmRleDogbnVtYmVyXG4gICk6IHZvaWQge1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICBjb25zdCBwb3NpdGlvbiA9IHRoaXMuZ2V0TW91c2VQb3NpdGlvbihldmVudCk7XG4gICAgdGhpcy5zdGF0ZS5zdGFydENvbm5lY3Rpb25EcmFnKFxuICAgICAgcG9pbnQsXG4gICAgICBzd2ltbGFuZUluZGV4LFxuICAgICAgcG9zaXRpb24ueCxcbiAgICAgIHBvc2l0aW9uLnlcbiAgICApO1xuXG4gICAgLy8gQWRkIG1vdXNlIG1vdmUgYW5kIG1vdXNlIHVwIGV2ZW50IGxpc3RlbmVycyB0byB0aGUgZG9jdW1lbnRcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCB0aGlzLm9uTW91c2VNb3ZlKTtcbiAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgdGhpcy5vbk1vdXNlVXApO1xuICB9XG5cbiAgLy8gVXNlIGFycm93IGZ1bmN0aW9ucyB0byBwcmVzZXJ2ZSAndGhpcycgY29udGV4dFxuICBvbk1vdXNlTW92ZSA9IChldmVudDogTW91c2VFdmVudCkgPT4ge1xuICAgIGNvbnN0IHBvc2l0aW9uID0gdGhpcy5nZXRNb3VzZVBvc2l0aW9uKGV2ZW50KTtcbiAgICB0aGlzLnN0YXRlLnVwZGF0ZUNvbm5lY3Rpb25EcmFnKHBvc2l0aW9uLngsIHBvc2l0aW9uLnkpO1xuICB9O1xuXG4gIG9uTW91c2VVcCA9IChldmVudDogTW91c2VFdmVudCkgPT4ge1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMub25Nb3VzZU1vdmUpO1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLm9uTW91c2VVcCk7XG5cbiAgICBjb25zdCBwb3NpdGlvbiA9IHRoaXMuZ2V0TW91c2VQb3NpdGlvbihldmVudCk7XG4gICAgY29uc29sZS5sb2coJ01vdXNlIHVwIGF0IHBvc2l0aW9uOicsIHBvc2l0aW9uKTtcbiAgICBjb25zb2xlLmxvZygnSXMgY29ubmVjdGlvbiBkcmFnZ2luZzonLCB0aGlzLnN0YXRlLmlzQ29ubmVjdGlvbkRyYWdnaW5nKCkpO1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIHBvc2l0aW9uIGlzIHdpdGhpbiBhbnkgc3dpbWxhbmVcbiAgICBjb25zdCBpc0luc2lkZVN3aW1sYW5lID0gdGhpcy5pc1Bvc2l0aW9uSW5zaWRlU3dpbWxhbmUocG9zaXRpb24ueSk7XG4gICAgY29uc29sZS5sb2coJ0lzIGluc2lkZSBzd2ltbGFuZTonLCBpc0luc2lkZVN3aW1sYW5lKTtcblxuICAgIC8vIE9ubHkgc2hvdyBwb3B1cCBpZiB3aXRoaW4gYSBzd2ltbGFuZVxuICAgIGlmIChpc0luc2lkZVN3aW1sYW5lICYmIHRoaXMuc3RhdGUuaXNDb25uZWN0aW9uRHJhZ2dpbmcoKSkge1xuICAgICAgY29uc29sZS5sb2coJ1Nob3dpbmcgY29ubmVjdGlvbiBwb3B1cCcpO1xuICAgICAgdGhpcy5zaG93Q29ubmVjdGlvblBvcHVwKHBvc2l0aW9uLngsIHBvc2l0aW9uLnkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBFbmQgdGhlIGNvbm5lY3Rpb24gZHJhZyBpZiBvdXRzaWRlIGEgc3dpbWxhbmVcbiAgICAgIGNvbnNvbGUubG9nKCdFbmRpbmcgY29ubmVjdGlvbiBkcmFnIHdpdGhvdXQgc2hvd2luZyBwb3B1cCcpO1xuICAgICAgdGhpcy5zdGF0ZS5lbmRDb25uZWN0aW9uRHJhZygpO1xuICAgIH1cbiAgfTtcblxuICBpc1Bvc2l0aW9uSW5zaWRlU3dpbWxhbmUoeTogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgLy8gQ2hlY2sgaWYgeSBwb3NpdGlvbiBpcyB3aXRoaW4gYW55IHN3aW1sYW5lXG4gICAgY29uc3Qgc3dpbWxhbmVDb3VudCA9IHRoaXMuc3RhdGUuc3dpbWxhbmVzLmxlbmd0aDtcbiAgICBpZiAoc3dpbWxhbmVDb3VudCA9PT0gMCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgLy8gRWFjaCBzd2ltbGFuZSBoYXMgYSBoZWlnaHQgb2YgMjYzcHhcbiAgICBjb25zdCB0b3RhbFN3aW1sYW5lSGVpZ2h0ID0gc3dpbWxhbmVDb3VudCAqIHRoaXMuc3dpbWxhbmVIZWlnaHQ7XG5cbiAgICAvLyBDaGVjayBpZiB5IGlzIHdpdGhpbiB0aGUgdG90YWwgaGVpZ2h0IG9mIGFsbCBzd2ltbGFuZXNcbiAgICByZXR1cm4geSA+PSAwICYmIHkgPCB0b3RhbFN3aW1sYW5lSGVpZ2h0O1xuICB9XG5cbiAgc2hvd0Nvbm5lY3Rpb25Qb3B1cCh4OiBudW1iZXIsIHk6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnNvbGUubG9nKCdTaG93aW5nIGNvbm5lY3Rpb24gcG9wdXAgYXQ6JywgeCwgeSk7XG4gICAgdGhpcy5wb3B1cFggPSB4O1xuICAgIHRoaXMucG9wdXBZID0geTtcblxuICAgIC8vIEdldCBhbGxvd2VkIG5vZGUgdHlwZXMgYmFzZWQgb24gdGhlIHNvdXJjZSBub2RlIHR5cGVcbiAgICB0aGlzLmFsbG93ZWROb2RlVHlwZXMgPSB0aGlzLnN0YXRlLmdldEFsbG93ZWRUYXJnZXROb2RlVHlwZXMoKTtcbiAgICBjb25zb2xlLmxvZygnQWxsb3dlZCBub2RlIHR5cGVzOicsIHRoaXMuYWxsb3dlZE5vZGVUeXBlcyk7XG5cbiAgICAvLyBPbmx5IHNob3cgdGhlIHBvcHVwIGlmIHdlIGhhdmUgYWxsb3dlZCBub2RlIHR5cGVzXG4gICAgaWYgKHRoaXMuYWxsb3dlZE5vZGVUeXBlcy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLnBvcHVwVmlzaWJsZSA9IHRydWU7XG4gICAgICBjb25zb2xlLmxvZygnUG9wdXAgdmlzaWJpbGl0eSBzZXQgdG8gdHJ1ZScpO1xuXG4gICAgICAvLyBGb3JjZSB0aGUgcG9wdXAgdG8gYmUgdmlzaWJsZSBpbiB0aGUgbmV4dCB0aWNrXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coJ0lzIHBvcHVwIHZpc2libGUgaW4gbmV4dCB0aWNrOicsIHRoaXMucG9wdXBWaXNpYmxlKTtcbiAgICAgIH0sIDApO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBObyBhbGxvd2VkIG5vZGUgdHlwZXMsIGp1c3QgZW5kIHRoZSBkcmFnXG4gICAgICBjb25zb2xlLmxvZygnTm8gYWxsb3dlZCBub2RlIHR5cGVzLCBlbmRpbmcgZHJhZycpO1xuICAgICAgdGhpcy5zdGF0ZS5lbmRDb25uZWN0aW9uRHJhZygpO1xuICAgIH1cbiAgfVxuXG4gIGhpZGVDb25uZWN0aW9uUG9wdXAoKTogdm9pZCB7XG4gICAgdGhpcy5wb3B1cFZpc2libGUgPSBmYWxzZTtcbiAgICB0aGlzLnN0YXRlLmVuZENvbm5lY3Rpb25EcmFnKCk7XG4gIH1cblxuICAvLyBBZGQgdGhpcyBoYW5kbGVyIHRvIGNsb3NlIHRoZSBwb3B1cCB3aGVuIGNsaWNraW5nIG91dHNpZGVcbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6Y2xpY2snLCBbJyRldmVudCddKVxuICBvbkRvY3VtZW50Q2xpY2soZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5wb3B1cFZpc2libGUpIHtcbiAgICAgIGNvbnN0IHBvcHVwRWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3ZlcmJlbi1wb3AtVXAnKTtcbiAgICAgIGlmIChwb3B1cEVsZW1lbnQgJiYgIXBvcHVwRWxlbWVudC5jb250YWlucyhldmVudC50YXJnZXQgYXMgTm9kZSkpIHtcbiAgICAgICAgdGhpcy5oaWRlQ29ubmVjdGlvblBvcHVwKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY3JlYXRlTm9kZUNvbm5lY3Rpb24obm9kZVR5cGU6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IHBhdGhEYXRhID0gdGhpcy5zdGF0ZS5nZXRDb25uZWN0aW9uUGF0aERhdGEoKTtcbiAgICBpZiAoIXBhdGhEYXRhKSB7XG4gICAgICB0aGlzLmhpZGVDb25uZWN0aW9uUG9wdXAoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiB0aGlzIG5vZGUgdHlwZSBpcyBhbGxvd2VkIHRvIGJlIGNyZWF0ZWRcbiAgICBjb25zdCBhbGxvd2VkVHlwZXMgPSB0aGlzLnN0YXRlLmdldEFsbG93ZWRUYXJnZXROb2RlVHlwZXMoKTtcbiAgICBpZiAoIWFsbG93ZWRUeXBlcy5pbmNsdWRlcyhub2RlVHlwZSkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgIGBDYW5ub3QgY3JlYXRlIGNvbm5lY3Rpb24gdG8gJHtub2RlVHlwZX0gZnJvbSBjdXJyZW50IG5vZGUgdHlwZWBcbiAgICAgICk7XG4gICAgICB0aGlzLmhpZGVDb25uZWN0aW9uUG9wdXAoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB7IGVuZFgsIGVuZFksIHNvdXJjZVN3aW1sYW5lSW5kZXggfSA9IHBhdGhEYXRhO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHN3aW1sYW5lLXJlbGF0aXZlIHBvc2l0aW9uXG4gICAgY29uc3Qgc3dpbWxhbmVPZmZzZXRZID0gc291cmNlU3dpbWxhbmVJbmRleCAqIDI2MyArIDQwO1xuICAgIGNvbnN0IHJlbGF0aXZlWSA9IGVuZFkgLSBzd2ltbGFuZU9mZnNldFk7XG5cbiAgICAvLyBIYW5kbGUgcHJlY29uZGl0aW9ucyBiYXNlZCBvbiBub2RlIHR5cGVcbiAgICBpZiAobm9kZVR5cGUgPT09ICdzdGFnZScpIHtcbiAgICAgIC8vIE9wZW4gc3RhZ2UgcHJvcGVydGllcyBkaWFsb2cgaW5zdGVhZCBvZiBjcmVhdGluZyBub2RlIGRpcmVjdGx5XG4gICAgICB0aGlzLnBlbmRpbmdTdGFnZVBvc2l0aW9uID0ge1xuICAgICAgICBzd2ltbGFuZUluZGV4OiBzb3VyY2VTd2ltbGFuZUluZGV4LFxuICAgICAgICB4OiBlbmRYLFxuICAgICAgICB5OiBlbmRZLFxuICAgICAgfTtcbiAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAnRW1pdHRpbmcgc2hvd1N0YWdlRGlhbG9nIGV2ZW50IHdpdGggcG9zaXRpb246JyxcbiAgICAgICAgdGhpcy5wZW5kaW5nU3RhZ2VQb3NpdGlvblxuICAgICAgKTtcbiAgICAgIHRoaXMuc2hvd1N0YWdlRGlhbG9nLmVtaXQoe1xuICAgICAgICBwb3NpdGlvbjogdGhpcy5wZW5kaW5nU3RhZ2VQb3NpdGlvbixcbiAgICAgICAgaXNGcm9tQ29ubmVjdGlvbjogdHJ1ZSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5oaWRlQ29ubmVjdGlvblBvcHVwKCk7XG4gICAgICByZXR1cm47XG4gICAgfSBlbHNlIGlmIChub2RlVHlwZSA9PT0gJ3N1YmZsb3cnKSB7XG4gICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgJ0NyZWF0aW5nIHN1YmZsb3cgZnJvbSBjb25uZWN0aW9uIGF0OicsXG4gICAgICAgIGVuZFgsXG4gICAgICAgIGVuZFksXG4gICAgICAgICdzd2ltbGFuZTonLFxuICAgICAgICBzb3VyY2VTd2ltbGFuZUluZGV4XG4gICAgICApO1xuICAgICAgLy8gU2hvdyB3b3JrZmxvdyBzZWxlY3Rpb24gcG9wdXAgYW5kIHN0b3JlIGNvbm5lY3Rpb24gZGF0YSBmb3IgbGF0ZXIgdXNlXG4gICAgICB0aGlzLnNob3dTdWJmbG93U2VsZWN0aW9uUG9wdXAoZW5kWCwgZW5kWSwgc291cmNlU3dpbWxhbmVJbmRleCk7XG4gICAgICB0aGlzLmhpZGVDb25uZWN0aW9uUG9wdXAoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBGb3Igb3RoZXIgbm9kZXMgQ3JlYXRlIHRoZSBuZXcgbm9kZSBhdCB0aGUgZW5kIHBvc2l0aW9uIG9mIHRoZSBjb25uZWN0aW9uXG4gICAgY29uc3QgbmV3Tm9kZSA9IHRoaXMuc3RhdGUuYWRkTm9kZShcbiAgICAgIHNvdXJjZVN3aW1sYW5lSW5kZXgsXG4gICAgICBub2RlVHlwZSBhcyBUb29sVHlwZSxcbiAgICAgIGVuZFgsXG4gICAgICByZWxhdGl2ZVlcbiAgICApO1xuXG4gICAgaWYgKFxuICAgICAgbmV3Tm9kZSAmJlxuICAgICAgbmV3Tm9kZS5jb25uZWN0aW9uUG9pbnRzICYmXG4gICAgICBuZXdOb2RlLmNvbm5lY3Rpb25Qb2ludHMubGVuZ3RoID4gMFxuICAgICkge1xuICAgICAgLy8gRmluZCB0aGUgbW9zdCBhcHByb3ByaWF0ZSBjb25uZWN0aW9uIHBvaW50IChjbG9zZXN0IHRvIHRoZSBzb3VyY2UpXG4gICAgICBjb25zdCBzb3VyY2VQb2ludCA9IHRoaXMuc3RhdGUuZHJhZ2dpbmdDb25uZWN0aW9uRGF0YS5zb3VyY2VQb2ludDtcbiAgICAgIGlmIChzb3VyY2VQb2ludCkge1xuICAgICAgICAvLyBGb3Igc2ltcGxpY2l0eSwgdXNlIHRoZSBmaXJzdCBjb25uZWN0aW9uIHBvaW50IG9mIG9wcG9zaW5nIHR5cGVcbiAgICAgICAgLy8gSW4gYSByZWFsIGltcGxlbWVudGF0aW9uLCB5b3UnZCBmaW5kIHRoZSBjbG9zZXN0IG9yIG1vc3QgYXBwcm9wcmlhdGUgcG9pbnRcbiAgICAgICAgbGV0IHRhcmdldFBvaW50O1xuXG4gICAgICAgIC8vIElmIHNvdXJjZSBpcyBvbiByaWdodCwgdGFyZ2V0IHNob3VsZCBiZSBvbiBsZWZ0LCBldGMuXG4gICAgICAgIGNvbnN0IG9wcG9zaW5nVHlwZSA9IHtcbiAgICAgICAgICByaWdodDogJ2xlZnQnLFxuICAgICAgICAgIGxlZnQ6ICdyaWdodCcsXG4gICAgICAgICAgdG9wOiAnYm90dG9tJyxcbiAgICAgICAgICBib3R0b206ICd0b3AnLFxuICAgICAgICB9W3NvdXJjZVBvaW50LnR5cGVdIGFzICd0b3AnIHwgJ3JpZ2h0JyB8ICdib3R0b20nIHwgJ2xlZnQnO1xuXG4gICAgICAgIHRhcmdldFBvaW50ID0gbmV3Tm9kZS5jb25uZWN0aW9uUG9pbnRzLmZpbmQoXG4gICAgICAgICAgKHApID0+IHAudHlwZSA9PT0gb3Bwb3NpbmdUeXBlXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKHRhcmdldFBvaW50KSB7XG4gICAgICAgICAgLy8gQ3JlYXRlIHRoZSBjb25uZWN0aW9uXG4gICAgICAgICAgdGhpcy5zdGF0ZS5jcmVhdGVDb25uZWN0aW9uKFxuICAgICAgICAgICAgbmV3Tm9kZS5pZCxcbiAgICAgICAgICAgIHRhcmdldFBvaW50LmlkLFxuICAgICAgICAgICAgc291cmNlU3dpbWxhbmVJbmRleFxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBFbmQgdGhlIGNvbm5lY3Rpb24gZHJhZ1xuICAgIHRoaXMuaGlkZUNvbm5lY3Rpb25Qb3B1cCgpO1xuICB9XG5cbiAgZ2V0Q29ubmVjdGlvblBhdGgoKTogc3RyaW5nIHtcbiAgICBjb25zdCBwYXRoRGF0YSA9IHRoaXMuc3RhdGUuZ2V0Q29ubmVjdGlvblBhdGhEYXRhKCk7XG4gICAgaWYgKCFwYXRoRGF0YSkgcmV0dXJuICcnO1xuXG4gICAgY29uc3QgeyBzdGFydFgsIHN0YXJ0WSwgZW5kWCwgZW5kWSB9ID0gcGF0aERhdGE7XG4gICAgY29uc3Qgc291cmNlUG9pbnQgPSB0aGlzLnN0YXRlLmRyYWdnaW5nQ29ubmVjdGlvbkRhdGEuc291cmNlUG9pbnQ7XG5cbiAgICBpZiAoIXNvdXJjZVBvaW50KSByZXR1cm4gJyc7XG5cbiAgICByZXR1cm4gdGhpcy5nZXRPcnRob2dvbmFsUGF0aChzdGFydFgsIHN0YXJ0WSwgZW5kWCwgZW5kWSwgc291cmNlUG9pbnQudHlwZSk7XG4gIH1cblxuICBnZXRDb25uZWN0aW9uUGF0aEZvclNhdmVkQ29ubmVjdGlvbihjb25uZWN0aW9uOiBDb25uZWN0aW9uKTogc3RyaW5nIHtcbiAgICB0cnkge1xuICAgICAgY29uc3QgcGF0aERhdGEgPSB0aGlzLnN0YXRlLmdldENvbm5lY3Rpb25EYXRhKGNvbm5lY3Rpb24pO1xuICAgICAgaWYgKCFwYXRoRGF0YSkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdObyBwYXRoIGRhdGEgZm9yIGNvbm5lY3Rpb246JywgY29ubmVjdGlvbik7XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIH1cblxuICAgICAgY29uc3QgeyBzdGFydFgsIHN0YXJ0WSwgZW5kWCwgZW5kWSB9ID0gcGF0aERhdGE7XG5cbiAgICAgIGNvbnN0IHNvdXJjZU5vZGVJbmZvID0gdGhpcy5zdGF0ZS5maW5kTm9kZUJ5SWQoY29ubmVjdGlvbi5zb3VyY2VOb2RlSWQpO1xuICAgICAgaWYgKCFzb3VyY2VOb2RlSW5mbykge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdTb3VyY2Ugbm9kZSBub3QgZm91bmQgZm9yIGNvbm5lY3Rpb246JywgY29ubmVjdGlvbik7XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIH1cblxuICAgICAgY29uc3Qgc291cmNlTm9kZSA9IHNvdXJjZU5vZGVJbmZvLm5vZGU7XG4gICAgICBjb25zdCBzb3VyY2VQb2ludCA9IHNvdXJjZU5vZGUuY29ubmVjdGlvblBvaW50cz8uZmluZChcbiAgICAgICAgKHApID0+IHAuaWQgPT09IGNvbm5lY3Rpb24uc291cmNlUG9pbnRJZFxuICAgICAgKTtcblxuICAgICAgaWYgKCFzb3VyY2VQb2ludCkge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdTb3VyY2UgcG9pbnQgbm90IGZvdW5kIGZvciBjb25uZWN0aW9uOicsIGNvbm5lY3Rpb24pO1xuICAgICAgICByZXR1cm4gJyc7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiB0aGlzLmdldE9ydGhvZ29uYWxQYXRoKFxuICAgICAgICBzdGFydFgsXG4gICAgICAgIHN0YXJ0WSxcbiAgICAgICAgZW5kWCxcbiAgICAgICAgZW5kWSxcbiAgICAgICAgc291cmNlUG9pbnQudHlwZVxuICAgICAgKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgZ2VuZXJhdGluZyBwYXRoIGZvciBjb25uZWN0aW9uOicsIGNvbm5lY3Rpb24sIGVycm9yKTtcbiAgICAgIHJldHVybiAnJztcbiAgICB9XG4gIH1cblxuICBnZXRPcnRob2dvbmFsUGF0aChcbiAgICBzdGFydFg6IG51bWJlcixcbiAgICBzdGFydFk6IG51bWJlcixcbiAgICBlbmRYOiBudW1iZXIsXG4gICAgZW5kWTogbnVtYmVyLFxuICAgIHBvaW50VHlwZTogJ3RvcCcgfCAncmlnaHQnIHwgJ2JvdHRvbScgfCAnbGVmdCdcbiAgKTogc3RyaW5nIHtcbiAgICAvLyBEZXRlcm1pbmUgaW5pdGlhbCBkaXJlY3Rpb24gYmFzZWQgb24gY29ubmVjdGlvbiBwb2ludCB0eXBlXG4gICAgbGV0IHBhdGggPSAnJztcblxuICAgIC8vIEZvciBzaWRlIHBvaW50cyAobGVmdC9yaWdodCksIHN0YXJ0IHdpdGggaG9yaXpvbnRhbCBsaW5lXG4gICAgaWYgKHBvaW50VHlwZSA9PT0gJ2xlZnQnIHx8IHBvaW50VHlwZSA9PT0gJ3JpZ2h0Jykge1xuICAgICAgLy8gQ2FsY3VsYXRlIGhvcml6b250YWwgZGlzdGFuY2VcbiAgICAgIGNvbnN0IGhvcml6b250YWxEaXN0ID0gZW5kWCAtIHN0YXJ0WDtcblxuICAgICAgLy8gSWYgdGhlIGVuZCBwb2ludCBpcyB2ZXJ5IGNsb3NlIGhvcml6b250YWxseSwgdXNlIGEgc2ltcGxlIDMtc2VnbWVudCBwYXRoXG4gICAgICBpZiAoTWF0aC5hYnMoaG9yaXpvbnRhbERpc3QpIDwgMzApIHtcbiAgICAgICAgY29uc3QgbWlkWSA9IChzdGFydFkgKyBlbmRZKSAvIDI7XG4gICAgICAgIHBhdGggPSBgTSAke3N0YXJ0WH0gJHtzdGFydFl9IEggJHtlbmRYfSBWICR7bWlkWX0gViAke2VuZFl9YDtcbiAgICAgIH1cbiAgICAgIC8vIE90aGVyd2lzZSwgY3JlYXRlIGEgcGF0aCB3aXRoIGhvcml6b250YWwgc2VnbWVudCBmaXJzdCwgdGhlbiB2ZXJ0aWNhbCwgdGhlbiBob3Jpem9udGFsXG4gICAgICBlbHNlIHtcbiAgICAgICAgcGF0aCA9IGBNICR7c3RhcnRYfSAke3N0YXJ0WX0gSCAke1xuICAgICAgICAgIHN0YXJ0WCArIGhvcml6b250YWxEaXN0IC8gMlxuICAgICAgICB9IFYgJHtlbmRZfSBIICR7ZW5kWH1gO1xuICAgICAgfVxuICAgIH1cbiAgICAvLyBGb3IgdG9wL2JvdHRvbSBwb2ludHMsIHN0YXJ0IHdpdGggdmVydGljYWwgbGluZVxuICAgIGVsc2UgaWYgKHBvaW50VHlwZSA9PT0gJ3RvcCcgfHwgcG9pbnRUeXBlID09PSAnYm90dG9tJykge1xuICAgICAgLy8gQ2FsY3VsYXRlIHZlcnRpY2FsIGRpc3RhbmNlXG4gICAgICBjb25zdCB2ZXJ0aWNhbERpc3QgPSBlbmRZIC0gc3RhcnRZO1xuXG4gICAgICAvLyBJZiB0aGUgZW5kIHBvaW50IGlzIHZlcnkgY2xvc2UgdmVydGljYWxseSwgdXNlIGEgc2ltcGxlIDMtc2VnbWVudCBwYXRoXG4gICAgICBpZiAoTWF0aC5hYnModmVydGljYWxEaXN0KSA8IDMwKSB7XG4gICAgICAgIGNvbnN0IG1pZFggPSAoc3RhcnRYICsgZW5kWCkgLyAyO1xuICAgICAgICBwYXRoID0gYE0gJHtzdGFydFh9ICR7c3RhcnRZfSBWICR7ZW5kWX0gSCAke21pZFh9IEggJHtlbmRYfWA7XG4gICAgICB9XG4gICAgICAvLyBPdGhlcndpc2UsIGNyZWF0ZSBhIHBhdGggd2l0aCB2ZXJ0aWNhbCBzZWdtZW50IGZpcnN0LCB0aGVuIGhvcml6b250YWwsIHRoZW4gdmVydGljYWxcbiAgICAgIGVsc2Uge1xuICAgICAgICBwYXRoID0gYE0gJHtzdGFydFh9ICR7c3RhcnRZfSBWICR7XG4gICAgICAgICAgc3RhcnRZICsgdmVydGljYWxEaXN0IC8gMlxuICAgICAgICB9IEggJHtlbmRYfSBWICR7ZW5kWX1gO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBwYXRoO1xuICB9XG5cbiAgb25TdGFnZVByb3BlcnRpZXNVcGRhdGVkKGV2ZW50OiB7XG4gICAgbm9kZUlkOiBzdHJpbmc7XG4gICAgc3RhZ2VEYXRhOiBQYXJ0aWFsPFdvcmtmbG93U3RhZ2U+O1xuICB9KTogdm9pZCB7XG4gICAgLy8gRmluZCB0aGUgbm9kZSBpbiB0aGUgc3dpbWxhbmVzXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0aGlzLnN0YXRlLnN3aW1sYW5lcy5sZW5ndGg7IGkrKykge1xuICAgICAgY29uc3Qgc3dpbWxhbmUgPSB0aGlzLnN0YXRlLnN3aW1sYW5lc1tpXTtcbiAgICAgIGNvbnN0IG5vZGVJbmRleCA9IHN3aW1sYW5lLm5vZGVzPy5maW5kSW5kZXgoKG4pID0+IG4uaWQgPT09IGV2ZW50Lm5vZGVJZCk7XG5cbiAgICAgIGlmIChub2RlSW5kZXggIT09IHVuZGVmaW5lZCAmJiBub2RlSW5kZXggPj0gMCkge1xuICAgICAgICAvLyBVcGRhdGUgdGhlIHN0YWdlIGRhdGFcbiAgICAgICAgaWYgKHN3aW1sYW5lLm5vZGVzKSB7XG4gICAgICAgICAgc3dpbWxhbmUubm9kZXNbbm9kZUluZGV4XS5zdGFnZURhdGEgPSB7XG4gICAgICAgICAgICAuLi5zd2ltbGFuZS5ub2Rlc1tub2RlSW5kZXhdLnN0YWdlRGF0YSxcbiAgICAgICAgICAgIC4uLmV2ZW50LnN0YWdlRGF0YSxcbiAgICAgICAgICB9O1xuICAgICAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAgICAgJ1VwZGF0ZWQgc3RhZ2UgZGF0YSBpbiBzd2ltbGFuZTonLFxuICAgICAgICAgICAgaSxcbiAgICAgICAgICAgICdub2RlOicsXG4gICAgICAgICAgICBub2RlSW5kZXgsXG4gICAgICAgICAgICAnZGF0YTonLFxuICAgICAgICAgICAgc3dpbWxhbmUubm9kZXNbbm9kZUluZGV4XS5zdGFnZURhdGFcbiAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgICAgIGJyZWFrO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG9uQ29ubmVjdGlvbkNyZWF0ZWQoY29ubmVjdGlvbjogQ29ubmVjdGlvbik6IHZvaWQge1xuICAgIC8vIEFmdGVyIGEgY29ubmVjdGlvbiBpcyBjcmVhdGVkLCByZWZyZXNoIHRoZSBzb3VyY2Ugbm9kZSB0byB1cGRhdGUgaXRzIHN0YXRlXG4gICAgY29uc3Qgc291cmNlTm9kZUluZm8gPSB0aGlzLnN0YXRlLmZpbmROb2RlQnlJZChjb25uZWN0aW9uLnNvdXJjZU5vZGVJZCk7XG4gICAgaWYgKHNvdXJjZU5vZGVJbmZvICYmIHNvdXJjZU5vZGVJbmZvLm5vZGUudHlwZSA9PT0gJ3N0YWdlJykge1xuICAgICAgLy8gUmVmcmVzaCBub2RlIHN0YXRlXG4gICAgICB0aGlzLnVwZGF0ZU5vZGVDb25uZWN0aW9ucyhzb3VyY2VOb2RlSW5mby5ub2RlKTtcbiAgICB9XG4gIH1cblxuICAvLyBIZWxwZXIgbWV0aG9kIHRvIHVwZGF0ZSBub2RlJ3MgY29ubmVjdGlvbiBzdGF0dXNcbiAgdXBkYXRlTm9kZUNvbm5lY3Rpb25zKG5vZGU6IFdGTm9kZSk6IHZvaWQge1xuICAgIC8vIENvdW50IHRoZSBudW1iZXIgb2Ygb3V0Z29pbmcgY29ubmVjdGlvbnMgdGhhdCBjb25uZWN0IHRvIHN0YWdlc1xuICAgIGNvbnN0IG91dGdvaW5nQ29ubmVjdGlvbnMgPSB0aGlzLnN0YXRlLmNvbm5lY3Rpb25zLmZpbHRlcihcbiAgICAgIChjb25uKSA9PiBjb25uLnNvdXJjZU5vZGVJZCA9PT0gbm9kZS5pZFxuICAgICk7XG5cbiAgICAvLyBDaGVjayBpZiB0aGUgdGFyZ2V0IG5vZGVzIGFyZSBzdGFnZXNcbiAgICBjb25zdCBjb25uZWN0ZWRTdGFnZU5vZGVzID0gb3V0Z29pbmdDb25uZWN0aW9uc1xuICAgICAgLm1hcCgoY29ubikgPT4gdGhpcy5zdGF0ZS5maW5kTm9kZUJ5SWQoY29ubi50YXJnZXROb2RlSWQpKVxuICAgICAgLmZpbHRlcigobm9kZUluZm8pID0+IG5vZGVJbmZvICYmIG5vZGVJbmZvLm5vZGUudHlwZSA9PT0gJ3N0YWdlJyk7XG5cbiAgICBub2RlLmhhc011bHRpcGxlQ29ubmVjdGVkU3RhZ2VzID0gY29ubmVjdGVkU3RhZ2VOb2Rlcy5sZW5ndGggPiAxO1xuICB9XG5cbiAgb25FZGl0U3dpbWxhbmUoXG4gICAgZXZlbnQ6IE1vdXNlRXZlbnQsXG4gICAgc3dpbWxhbmU6IFN3aW1sYW5lSXRlbSxcbiAgICBzd2ltbGFuZUluZGV4OiBudW1iZXJcbiAgKTogdm9pZCB7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7IC8vIFByZXZlbnQgdGhlIGNhbnZhcyBjbGljayBldmVudCBmcm9tIGZpcmluZ1xuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgY29uc29sZS5sb2coJ0VkaXQgc3dpbWxhbmUgYnV0dG9uIGNsaWNrZWQgZm9yIHN3aW1sYW5lOicsIHN3aW1sYW5lSW5kZXgpO1xuXG4gICAgLy8gRW1pdCBhIHNwZWNpYWwgZXZlbnQgZm9yIGVkaXRpbmcgYSBzd2ltbGFuZVxuICAgIHRoaXMuY2xpY2tlZFBvc2l0aW9uLmVtaXQoe1xuICAgICAgeDogLTEsIC8vIFNwZWNpYWwgdmFsdWUgdG8gaW5kaWNhdGUgZWRpdCBtb2RlXG4gICAgICB5OiBzd2ltbGFuZUluZGV4LFxuICAgIH0pO1xuICB9XG5cbiAgLy8gc2hvd1N0YXJ0Tm9kZUZvcm1Qb3B1cChldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAvLyAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gIC8vICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgLy8gICAvLyBJbXBsZW1lbnRhdGlvbiB3aWxsIGJlIHNpbWlsYXIgdG8gdGhlIHN0YWdlIGZvcm0gcG9wdXBcbiAgLy8gICAvLyBXZSdsbCBuZWVkIHRvIGFkZCBVSSBlbGVtZW50cyBmb3IgdGhpc1xuICAvLyAgIGNvbnNvbGUubG9nKCdTdGFydCBub2RlIGZvcm0gcG9wdXAgcmVxdWVzdGVkJyk7XG5cbiAgLy8gICAvLyBGb3Igbm93LCB0aGlzIGlzIGEgcGxhY2Vob2xkZXJcbiAgLy8gICAvLyBUaGUgYWN0dWFsIGltcGxlbWVudGF0aW9uIHdvdWxkIGxvYWQgZm9ybXMgYW5kIGFkZCB0aGVtIHRvIHRoZSB3b3JrZmxvd1xuICAvLyB9XG5cbiAgdG9nZ2xlU3RhcnROb2RlRm9ybVBvcHVwKFxuICAgIGV2ZW50OiBNb3VzZUV2ZW50LFxuICAgIG5vZGVYOiBudW1iZXIsXG4gICAgbm9kZVk6IG51bWJlcixcbiAgICBzd2ltbGFuZUluZGV4OiBudW1iZXJcbiAgKTogdm9pZCB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIC8vIFNldCBwb3B1cCBwb3NpdGlvblxuICAgIGNvbnN0IHN3aW1sYW5lT2Zmc2V0ID0gc3dpbWxhbmVJbmRleCAqIDI2MyArIDQwO1xuICAgIHRoaXMuc3RhcnROb2RlRm9ybVBvcHVwWCA9IG5vZGVYIC0gMzA7IC8vIFBvc2l0aW9uIG5lYXIgdGhlIHN0YXJ0IG5vZGVcbiAgICB0aGlzLnN0YXJ0Tm9kZUZvcm1Qb3B1cFkgPSBub2RlWSArIHN3aW1sYW5lT2Zmc2V0O1xuXG4gICAgLy8gSWYgd2UncmUgb3BlbmluZyB0aGUgcG9wdXAsIGxvYWQgZm9ybXNcbiAgICBpZiAoIXRoaXMuc2hvd1N0YXJ0Tm9kZUZvcm1Qb3B1cCkge1xuICAgICAgdGhpcy5pc0xvYWRpbmdTdGFydE5vZGVGb3JtcyA9IHRydWU7XG4gICAgICB0aGlzLmRhdGFTZXJ2aWNlXG4gICAgICAgIC5nZXRGb3JtcygpXG4gICAgICAgIC50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICAgIHRoaXMuc3RhcnROb2RlRm9ybXNMaXN0ID0gcmVzcG9uc2UuUmVzdWx0O1xuICAgICAgICAgIHRoaXMuaXNMb2FkaW5nU3RhcnROb2RlRm9ybXMgPSBmYWxzZTtcbiAgICAgICAgfSlcbiAgICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICAgIGNvbnNvbGUuZXJyb3IoJ0Vycm9yIGxvYWRpbmcgZm9ybXM6JywgZXJyb3IpO1xuICAgICAgICAgIHRoaXMuaXNMb2FkaW5nU3RhcnROb2RlRm9ybXMgPSBmYWxzZTtcbiAgICAgICAgfSk7XG4gICAgfVxuXG4gICAgdGhpcy5zaG93U3RhcnROb2RlRm9ybVBvcHVwID0gIXRoaXMuc2hvd1N0YXJ0Tm9kZUZvcm1Qb3B1cDtcbiAgfVxuXG4gIHNlbGVjdFN0YXJ0Tm9kZUZvcm0oZm9ybTogRm9ybUVudGl0eSB8IG51bGwpOiB2b2lkIHtcbiAgICBpZiAoZm9ybSkge1xuICAgICAgdGhpcy5zdGF0ZS5zZXRXb3JrZmxvd0Zvcm0oZm9ybS5JZCwgZm9ybS5OYW1lKTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5zdGF0ZS5zZXRXb3JrZmxvd0Zvcm0obnVsbCwgbnVsbCk7XG4gICAgfVxuXG4gICAgLy8gQ2xvc2UgdGhlIHBvcHVwXG4gICAgdGhpcy5zaG93U3RhcnROb2RlRm9ybVBvcHVwID0gZmFsc2U7XG4gIH1cblxuICBzaG93U3ViZmxvd1NlbGVjdGlvblBvcHVwKHg6IG51bWJlciwgeTogbnVtYmVyLCBzd2ltbGFuZUluZGV4OiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnN1YmZsb3dQb3B1cFggPSB4O1xuICAgIHRoaXMuc3ViZmxvd1BvcHVwWSA9IHk7XG4gICAgdGhpcy5wZW5kaW5nU3ViZmxvd1Bvc2l0aW9uID0geyBzd2ltbGFuZUluZGV4LCB4LCB5IH07XG5cbiAgICAvLyBTdG9yZSBjb25uZWN0aW9uIGRhdGEgaWYgd2UncmUgY3JlYXRpbmcgZnJvbSBhIGNvbm5lY3Rpb25cbiAgICBpZiAodGhpcy5zdGF0ZS5pc0Nvbm5lY3Rpb25EcmFnZ2luZygpKSB7XG4gICAgICAvLyBTdG9yZSB0aGUgc291cmNlIGNvbm5lY3Rpb24gZGF0YVxuICAgICAgdGhpcy5wZW5kaW5nQ29ubmVjdGlvblNvdXJjZVBvaW50ID1cbiAgICAgICAgdGhpcy5zdGF0ZS5kcmFnZ2luZ0Nvbm5lY3Rpb25EYXRhLnNvdXJjZVBvaW50ID8/IG51bGw7XG4gICAgICB0aGlzLnBlbmRpbmdDb25uZWN0aW9uU291cmNlU3dpbWxhbmVJbmRleCA9XG4gICAgICAgIHRoaXMuc3RhdGUuZHJhZ2dpbmdDb25uZWN0aW9uRGF0YS5zb3VyY2VTd2ltbGFuZUluZGV4ID8/IG51bGw7XG4gICAgICBjb25zb2xlLmxvZygnU3RvcmVkIGNvbm5lY3Rpb24gZGF0YSBmb3Igc3ViZmxvdzonLCB7XG4gICAgICAgIHNvdXJjZVBvaW50OiB0aGlzLnBlbmRpbmdDb25uZWN0aW9uU291cmNlUG9pbnQsXG4gICAgICAgIHNvdXJjZVN3aW1sYW5lSW5kZXg6IHRoaXMucGVuZGluZ0Nvbm5lY3Rpb25Tb3VyY2VTd2ltbGFuZUluZGV4LFxuICAgICAgfSk7XG4gICAgfVxuXG4gICAgLy8gTG9hZCB3b3JrZmxvd3NcbiAgICB0aGlzLmlzTG9hZGluZ1dvcmtmbG93cyA9IHRydWU7XG4gICAgdGhpcy5kYXRhU2VydmljZVxuICAgICAgLmdldFdvcmtmbG93cygpXG4gICAgICAudGhlbigocmVzcG9uc2UpID0+IHtcbiAgICAgICAgdGhpcy53b3JrZmxvd3NMaXN0ID0gcmVzcG9uc2UuUmVzdWx0O1xuICAgICAgICB0aGlzLmlzTG9hZGluZ1dvcmtmbG93cyA9IGZhbHNlO1xuICAgICAgfSlcbiAgICAgIC5jYXRjaCgoZXJyb3IpID0+IHtcbiAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgbG9hZGluZyB3b3JrZmxvd3M6JywgZXJyb3IpO1xuICAgICAgICB0aGlzLmlzTG9hZGluZ1dvcmtmbG93cyA9IGZhbHNlO1xuICAgICAgfSk7XG5cbiAgICB0aGlzLnNob3dTdWJmbG93UG9wdXAgPSB0cnVlO1xuICB9XG5cbiAgc2VsZWN0U3ViZmxvd1dvcmtmbG93KHdvcmtmbG93OiBXb3JrZmxvdyk6IHZvaWQge1xuICAgIGNvbnNvbGUubG9nKCdTZWxlY3Rpbmcgd29ya2Zsb3cgZm9yIHN1YmZsb3c6Jywgd29ya2Zsb3cuTmFtZSk7XG4gICAgY29uc29sZS5sb2coJ1BlbmRpbmcgY29ubmVjdGlvbiBkYXRhOicsIHtcbiAgICAgIHNvdXJjZVBvaW50OiB0aGlzLnBlbmRpbmdDb25uZWN0aW9uU291cmNlUG9pbnQsXG4gICAgICBzb3VyY2VTd2ltbGFuZUluZGV4OiB0aGlzLnBlbmRpbmdDb25uZWN0aW9uU291cmNlU3dpbWxhbmVJbmRleCxcbiAgICAgIHBvc2l0aW9uOiB0aGlzLnBlbmRpbmdTdWJmbG93UG9zaXRpb24sXG4gICAgfSk7XG5cbiAgICBpZiAodGhpcy5wZW5kaW5nU3ViZmxvd1Bvc2l0aW9uKSB7XG4gICAgICBjb25zdCB7IHN3aW1sYW5lSW5kZXgsIHgsIHkgfSA9IHRoaXMucGVuZGluZ1N1YmZsb3dQb3NpdGlvbjtcblxuICAgICAgLy8gQ3JlYXRlIHRoZSBzdWJmbG93IG5vZGUgd2l0aCB0aGUgc2VsZWN0ZWQgd29ya2Zsb3cgZGF0YVxuICAgICAgY29uc3Qgbm9kZSA9IHRoaXMuc3RhdGUuYWRkTm9kZShcbiAgICAgICAgc3dpbWxhbmVJbmRleCxcbiAgICAgICAgJ3N1YmZsb3cnLFxuICAgICAgICB4LFxuICAgICAgICB5LFxuICAgICAgICB1bmRlZmluZWQsIC8vIE5vIHN0YWdlIGRhdGFcbiAgICAgICAgeyBpZDogd29ya2Zsb3cuSWQsIG5hbWU6IHdvcmtmbG93Lk5hbWUgfVxuICAgICAgKTtcblxuICAgICAgY29uc29sZS5sb2coJ0NyZWF0ZWQgc3ViZmxvdyBub2RlOicsIG5vZGUpO1xuXG4gICAgICAvLyBJZiB0aGlzIHdhcyBjcmVhdGVkIGZyb20gYSBjb25uZWN0aW9uLCBjcmVhdGUgdGhlIGNvbm5lY3Rpb25cbiAgICAgIGlmIChub2RlICYmIHRoaXMucGVuZGluZ0Nvbm5lY3Rpb25Tb3VyY2VQb2ludCkge1xuICAgICAgICBjb25zb2xlLmxvZygnQ3JlYXRpbmcgY29ubmVjdGlvbiB0byBuZXcgc3ViZmxvdyBub2RlJyk7XG5cbiAgICAgICAgLy8gRmluZCBhIHN1aXRhYmxlIGNvbm5lY3Rpb24gcG9pbnQgb24gdGhlIG5ldyBub2RlXG4gICAgICAgIGlmIChub2RlLmNvbm5lY3Rpb25Qb2ludHMgJiYgbm9kZS5jb25uZWN0aW9uUG9pbnRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgICBjb25zdCBzb3VyY2VQb2ludCA9IHRoaXMucGVuZGluZ0Nvbm5lY3Rpb25Tb3VyY2VQb2ludDtcblxuICAgICAgICAgIC8vIEZpbmQgb3Bwb3NpbmcgdHlwZSBjb25uZWN0aW9uIHBvaW50XG4gICAgICAgICAgY29uc3Qgb3Bwb3NpbmdUeXBlID0ge1xuICAgICAgICAgICAgcmlnaHQ6ICdsZWZ0JyxcbiAgICAgICAgICAgIGxlZnQ6ICdyaWdodCcsXG4gICAgICAgICAgICB0b3A6ICdib3R0b20nLFxuICAgICAgICAgICAgYm90dG9tOiAndG9wJyxcbiAgICAgICAgICB9W3NvdXJjZVBvaW50LnR5cGVdIGFzICd0b3AnIHwgJ3JpZ2h0JyB8ICdib3R0b20nIHwgJ2xlZnQnO1xuXG4gICAgICAgICAgY29uc3QgdGFyZ2V0UG9pbnQgPSBub2RlLmNvbm5lY3Rpb25Qb2ludHMuZmluZChcbiAgICAgICAgICAgIChwKSA9PiBwLnR5cGUgPT09IG9wcG9zaW5nVHlwZVxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBpZiAodGFyZ2V0UG9pbnQpIHtcbiAgICAgICAgICAgIC8vIENyZWF0ZSBjb25uZWN0aW9uXG4gICAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0ge1xuICAgICAgICAgICAgICBpZDogYGNvbm4tJHtEYXRlLm5vdygpfS0ke01hdGguZmxvb3IoTWF0aC5yYW5kb20oKSAqIDEwMDApfWAsXG4gICAgICAgICAgICAgIHNvdXJjZU5vZGVJZDogc291cmNlUG9pbnQubm9kZUlkLFxuICAgICAgICAgICAgICB0YXJnZXROb2RlSWQ6IG5vZGUuaWQsXG4gICAgICAgICAgICAgIHNvdXJjZVBvaW50SWQ6IHNvdXJjZVBvaW50LmlkLFxuICAgICAgICAgICAgICB0YXJnZXRQb2ludElkOiB0YXJnZXRQb2ludC5pZCxcbiAgICAgICAgICAgICAgc291cmNlU3dpbWxhbmVJbmRleDogdGhpcy5wZW5kaW5nQ29ubmVjdGlvblNvdXJjZVN3aW1sYW5lSW5kZXghLFxuICAgICAgICAgICAgICB0YXJnZXRTd2ltbGFuZUluZGV4OiBzd2ltbGFuZUluZGV4LFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gQWRkIGNvbm5lY3Rpb24gZGlyZWN0bHkgdG8gdGhlIHN0YXRlJ3MgY29ubmVjdGlvbnMgYXJyYXlcbiAgICAgICAgICAgIHRoaXMuc3RhdGUuY29ubmVjdGlvbnMucHVzaChjb25uZWN0aW9uKTtcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKCdBZGRlZCBjb25uZWN0aW9uIHRvIHN0YXRlOicsIGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ0Nvbm5lY3Rpb25zIGFmdGVyIGFkZGluZzonLCB0aGlzLnN0YXRlLmNvbm5lY3Rpb25zKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5zdGF0ZS5lbmRDb25uZWN0aW9uRHJhZygpO1xuICAgICAgfVxuXG4gICAgICAvLyBSZXNldCBzZWxlY3Rpb24gdG9vbCBpbiBwYXJlbnQgY29tcG9uZW50XG4gICAgICB0aGlzLnN1YmZsb3dTZWxlY3RlZC5lbWl0KCk7XG4gICAgfVxuXG4gICAgLy8gQ2xlYW4gdXBcbiAgICB0aGlzLnNob3dTdWJmbG93UG9wdXAgPSBmYWxzZTtcbiAgICB0aGlzLnBlbmRpbmdTdWJmbG93UG9zaXRpb24gPSBudWxsO1xuICAgIHRoaXMucGVuZGluZ0Nvbm5lY3Rpb25Tb3VyY2VQb2ludCA9IG51bGw7XG4gICAgdGhpcy5wZW5kaW5nQ29ubmVjdGlvblNvdXJjZVN3aW1sYW5lSW5kZXggPSBudWxsO1xuICB9XG59XG4iLCI8ZGl2IGNsYXNzPVwiY2FudmFzLWNvbnRhaW5lclwiPlxuICA8c3ZnXG4gICAgI2NhbnZhc1xuICAgIFthdHRyLndpZHRoXT1cImNhbnZhc1dpZHRoXCJcbiAgICBbYXR0ci5oZWlnaHRdPVwiY2FudmFzSGVpZ2h0XCJcbiAgICBjbGFzcz1cImRlc2lnbmVyLWNhbnZhc1wiXG4gICAgKGNsaWNrKT1cIm9uQ2FudmFzQ2xpY2soJGV2ZW50KVwiXG4gID5cbiAgICA8ZGVmcz5cbiAgICAgIDwhLS0gR3JpZCBwYXR0ZXJuIGRlZmluaXRpb24gLS0+XG5cbiAgICAgIDxwYXR0ZXJuXG4gICAgICAgIGlkPVwiZ3JpZFwiXG4gICAgICAgIFthdHRyLndpZHRoXT1cImdyaWRTaXplXCJcbiAgICAgICAgW2F0dHIuaGVpZ2h0XT1cImdyaWRTaXplXCJcbiAgICAgICAgcGF0dGVyblVuaXRzPVwidXNlclNwYWNlT25Vc2VcIlxuICAgICAgPlxuICAgICAgICA8cGF0aFxuICAgICAgICAgIGQ9XCJNIDIwIDAgTCAwIDAgMCAyMFwiXG4gICAgICAgICAgZmlsbD1cIm5vbmVcIlxuICAgICAgICAgIHN0cm9rZT1cIiNlMmU4ZjBcIlxuICAgICAgICAgIHN0cm9rZS13aWR0aD1cIjAuNVwiXG4gICAgICAgIC8+XG4gICAgICA8L3BhdHRlcm4+XG5cbiAgICAgIDwhLS0gQXJyb3cgaGVhZCBtYXJrZXIgZGVmaW5pdGlvbiAtLT5cbiAgICAgIDxtYXJrZXJcbiAgICAgICAgaWQ9XCJhcnJvd2hlYWRcIlxuICAgICAgICBtYXJrZXJXaWR0aD1cIjEwXCJcbiAgICAgICAgbWFya2VySGVpZ2h0PVwiN1wiXG4gICAgICAgIHJlZlg9XCI5XCJcbiAgICAgICAgcmVmWT1cIjMuNVwiXG4gICAgICAgIG9yaWVudD1cImF1dG9cIlxuICAgICAgPlxuICAgICAgICA8cG9seWdvbiBwb2ludHM9XCIwIDAsIDEwIDMuNSwgMCA3XCIgZmlsbD1cIiNEMzZDRkZcIiAvPlxuICAgICAgPC9tYXJrZXI+XG5cbiAgICAgIDwhLS0gQ29ubmVjdGlvbiBwb2ludCBzdHlsZXMgLS0+XG4gICAgICA8Y2lyY2xlXG4gICAgICAgIGlkPVwiY29ubmVjdGlvbi1wb2ludC10ZW1wbGF0ZVwiXG4gICAgICAgIHI9XCI1XCJcbiAgICAgICAgZmlsbD1cIiNEMzZDRkZcIlxuICAgICAgICBzdHJva2U9XCIjRkZGRkZGXCJcbiAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMVwiXG4gICAgICAvPlxuXG4gICAgICA8IS0tIERhc2hlZCBsaW5lIHN0eWxlIGZvciBjb25uZWN0aW9uIHByZXZpZXcgLS0+XG4gICAgICA8cGF0dGVyblxuICAgICAgICBpZD1cImRhc2hlZC1saW5lXCJcbiAgICAgICAgd2lkdGg9XCIxMFwiXG4gICAgICAgIGhlaWdodD1cIjEwXCJcbiAgICAgICAgcGF0dGVyblVuaXRzPVwidXNlclNwYWNlT25Vc2VcIlxuICAgICAgPlxuICAgICAgICA8bGluZVxuICAgICAgICAgIHgxPVwiMFwiXG4gICAgICAgICAgeTE9XCI1XCJcbiAgICAgICAgICB4Mj1cIjEwXCJcbiAgICAgICAgICB5Mj1cIjVcIlxuICAgICAgICAgIHN0cm9rZT1cIiNEMzZDRkZcIlxuICAgICAgICAgIHN0cm9rZS13aWR0aD1cIjJcIlxuICAgICAgICAgIHN0cm9rZS1kYXNoYXJyYXk9XCI1LDVcIlxuICAgICAgICAvPlxuICAgICAgPC9wYXR0ZXJuPlxuICAgIDwvZGVmcz5cblxuICAgIDwhLS0gQmFja2dyb3VuZCBncmlkIC0tPlxuICAgIDxyZWN0IHdpZHRoPVwiMTAwJVwiIGhlaWdodD1cIjEwMCVcIiBmaWxsPVwidXJsKCNncmlkKVwiIC8+XG5cbiAgICA8IS0tIERpc3BsYXkgYSBtZXNzYWdlIHdoZW4gbm8gc3dpbWxhbmVzIGV4aXN0IC0tPlxuICAgIEBpZiAoc3RhdGUuc3dpbWxhbmVzLmxlbmd0aCA9PT0gMCkge1xuICAgIDx0ZXh0XG4gICAgICB4PVwiNTAlXCJcbiAgICAgIHk9XCI1MCVcIlxuICAgICAgZm9udC1mYW1pbHk9XCJzYW5zLXNlcmlmXCJcbiAgICAgIGZvbnQtc2l6ZT1cIjE2XCJcbiAgICAgIGZpbGw9XCIjOTRhM2I4XCJcbiAgICAgIHRleHQtYW5jaG9yPVwibWlkZGxlXCJcbiAgICA+XG4gICAgICBTZWxlY3QgdGhlIFN3aW1sYW5lIHRvb2wgYW5kIGNsaWNrIG9uIHRoZSBjYW52YXMgdG8gYWRkIGEgc3dpbWxhbmVcbiAgICA8L3RleHQ+XG4gICAgfVxuXG4gICAgPCEtLSBUaGlzIGlzIHdoZXJlIHdvcmtmbG93IGVsZW1lbnRzIHdpbGwgYmUgYWRkZWQgbGF0ZXIgLS0+XG4gICAgQGZvciAoc3dpbWxhbmUgb2Ygc3RhdGUuc3dpbWxhbmVzOyB0cmFjayBzd2ltbGFuZS5vcmRlcikge1xuICAgIDxnIFthdHRyLnRyYW5zZm9ybV09XCIndHJhbnNsYXRlKDAsJyArIHN3aW1sYW5lLm9yZGVyICogMjYzICsgJyknXCI+XG4gICAgICA8IS0tIFN3aW1sYW5lIGNvbnRhaW5lciAtLT5cbiAgICAgIDxyZWN0XG4gICAgICAgIHg9XCIwXCJcbiAgICAgICAgeT1cIjBcIlxuICAgICAgICBbYXR0ci53aWR0aF09XCJjYW52YXNXaWR0aFwiXG4gICAgICAgIFthdHRyLmhlaWdodF09XCIyNjNcIlxuICAgICAgICBmaWxsPVwiI2ZmZmZmZlwiXG4gICAgICAgIHN0cm9rZT1cIiNlMmU4ZjBcIlxuICAgICAgICBzdHJva2Utd2lkdGg9XCIxXCJcbiAgICAgID48L3JlY3Q+XG5cbiAgICAgIDwhLS0gU3dpbWxhbmUgaGVhZGVyIC0tPlxuICAgICAgPHJlY3RcbiAgICAgICAgeD1cIjBcIlxuICAgICAgICB5PVwiMFwiXG4gICAgICAgIFthdHRyLndpZHRoXT1cImNhbnZhc1dpZHRoXCJcbiAgICAgICAgaGVpZ2h0PVwiNDBcIlxuICAgICAgICBmaWxsPVwiI2Y4ZmFmY1wiXG4gICAgICAgIHN0cm9rZT1cIiNlMmU4ZjBcIlxuICAgICAgICBzdHJva2Utd2lkdGg9XCIxXCJcbiAgICAgID48L3JlY3Q+XG5cbiAgICAgIDwhLS0gU3dpbWxhbmUgbGFiZWwgLS0+XG4gICAgICA8dGV4dFxuICAgICAgICB4PVwiMjBcIlxuICAgICAgICB5PVwiMjVcIlxuICAgICAgICBmb250LWZhbWlseT1cInNhbnMtc2VyaWZcIlxuICAgICAgICBmb250LXNpemU9XCIxNFwiXG4gICAgICAgIGZpbGw9XCIjMzMzMzMzXCJcbiAgICAgICAgZm9udC13ZWlnaHQ9XCJib2xkXCJcbiAgICAgID5cbiAgICAgICAge3sgc3dpbWxhbmUubGFiZWwgfX1cbiAgICAgIDwvdGV4dD5cblxuICAgICAgPCEtLSBFZGl0IGJ1dHRvbiAtLT5cbiAgICAgIDxnXG4gICAgICAgIGNsYXNzPVwiZWRpdC1zd2ltbGFuZS1idXR0b25cIlxuICAgICAgICBbYXR0ci50cmFuc2Zvcm1dPVwiJ3RyYW5zbGF0ZSgyMDAsIDIwKSdcIlxuICAgICAgICAoY2xpY2spPVwiXG4gICAgICAgICAgb25FZGl0U3dpbWxhbmUoJGV2ZW50LCBzd2ltbGFuZSwgc3dpbWxhbmUub3JkZXIpO1xuICAgICAgICAgICRldmVudC5zdG9wUHJvcGFnYXRpb24oKVxuICAgICAgICBcIlxuICAgICAgPlxuICAgICAgICA8cmVjdFxuICAgICAgICAgIHg9XCItNVwiXG4gICAgICAgICAgeT1cIi0xNVwiXG4gICAgICAgICAgd2lkdGg9XCI0MFwiXG4gICAgICAgICAgaGVpZ2h0PVwiMjBcIlxuICAgICAgICAgIGZpbGw9XCIjZjNlOGZmXCJcbiAgICAgICAgICByeD1cIjNcIlxuICAgICAgICAgIHJ5PVwiM1wiXG4gICAgICAgICAgc3Ryb2tlPVwiI2Q4YjRmZVwiXG4gICAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMVwiXG4gICAgICAgID48L3JlY3Q+XG4gICAgICAgIDx0ZXh0XG4gICAgICAgICAgeD1cIjE1XCJcbiAgICAgICAgICB5PVwiMFwiXG4gICAgICAgICAgZm9udC1mYW1pbHk9XCJzYW5zLXNlcmlmXCJcbiAgICAgICAgICBmb250LXNpemU9XCIxMlwiXG4gICAgICAgICAgZmlsbD1cIiM3ZTIyY2VcIlxuICAgICAgICAgIHRleHQtYW5jaG9yPVwibWlkZGxlXCJcbiAgICAgICAgPlxuICAgICAgICAgIEVkaXRcbiAgICAgICAgPC90ZXh0PlxuICAgICAgPC9nPlxuXG4gICAgICA8IS0tIFRhZyBpbmRpY2F0b3JzIC0tPlxuICAgICAgPGcgW2F0dHIudHJhbnNmb3JtXT1cIid0cmFuc2xhdGUoMjAwLCAyMCknXCI+XG4gICAgICAgIEBmb3IgKHRhZyBvZiBzd2ltbGFuZS50YWdzLnNsaWNlKDAsIDMpOyB0cmFjayB0YWcuTmFtZTsgbGV0IGkgPSAkaW5kZXgpXG4gICAgICAgIHtcbiAgICAgICAgPHRleHRcbiAgICAgICAgICBbYXR0ci54XT1cImkgKiAxMDBcIlxuICAgICAgICAgIHk9XCI1XCJcbiAgICAgICAgICBmb250LWZhbWlseT1cInNhbnMtc2VyaWZcIlxuICAgICAgICAgIGZvbnQtc2l6ZT1cIjEyXCJcbiAgICAgICAgICBmaWxsPVwiIzY2NjY2NlwiXG4gICAgICAgID5cbiAgICAgICAgICB7eyB0YWcuTmFtZSB9fVxuICAgICAgICA8L3RleHQ+XG4gICAgICAgIH0gQGlmIChzd2ltbGFuZS50YWdzLmxlbmd0aCA+IDMpIHtcbiAgICAgICAgPHRleHRcbiAgICAgICAgICBbYXR0ci54XT1cIjMgKiAxMDAgKyAxMFwiXG4gICAgICAgICAgeT1cIjVcIlxuICAgICAgICAgIGZvbnQtZmFtaWx5PVwic2Fucy1zZXJpZlwiXG4gICAgICAgICAgZm9udC1zaXplPVwiMTJcIlxuICAgICAgICAgIGZpbGw9XCIjNjY2NjY2XCJcbiAgICAgICAgPlxuICAgICAgICAgICt7eyBzd2ltbGFuZS50YWdzLmxlbmd0aCAtIDMgfX0gbW9yZVxuICAgICAgICA8L3RleHQ+XG4gICAgICAgIH1cbiAgICAgIDwvZz5cblxuICAgICAgPCEtLSBSZW5kZXIgbm9kZXMgaW4gdGhpcyBzd2ltbGFuZSAtLT5cbiAgICAgIEBmb3IgKG5vZGUgb2Ygc3dpbWxhbmUubm9kZXM7IHRyYWNrIG5vZGUuaWQpIHtcbiAgICAgIDxnXG4gICAgICAgIFthdHRyLnRyYW5zZm9ybV09XCIndHJhbnNsYXRlKCcgKyBub2RlLnggKyAnLCcgKyAobm9kZS55ICsgNDApICsgJyknXCJcbiAgICAgICAgKG1vdXNlZW50ZXIpPVwic2hvd0Nvbm5lY3Rpb25Qb2ludHMobm9kZS5pZCwgc3dpbWxhbmUub3JkZXIpXCJcbiAgICAgICAgKG1vdXNlbGVhdmUpPVwiaGlkZUNvbm5lY3Rpb25Qb2ludHMobm9kZS5pZClcIlxuICAgICAgPlxuICAgICAgICA8IS0tIFN0YXJ0IG5vZGUgaW5kaWNhdG9yIChjaXJjbGUgYW5kIGFycm93KSBmb3IgdGhlIGZpcnN0IG5vZGUgLS0+XG4gICAgICAgIEBpZiAobm9kZS5pc1N0YXJ0Tm9kZSkge1xuICAgICAgICA8IS0tIENpcmNsZSAtLT5cbiAgICAgICAgPGNpcmNsZVxuICAgICAgICAgIGN4PVwiLTMwXCJcbiAgICAgICAgICBjeT1cIjUwXCJcbiAgICAgICAgICByPVwiMTVcIlxuICAgICAgICAgIGZpbGw9XCJub25lXCJcbiAgICAgICAgICBzdHJva2U9XCIjRDM2Q0ZGXCJcbiAgICAgICAgICBzdHJva2Utd2lkdGg9XCIxXCJcbiAgICAgICAgPjwvY2lyY2xlPlxuICAgICAgICA8IS0tIEZvcm0gaWNvbiBmb3Igc3RhcnQgbm9kZSAtLT5cbiAgICAgICAgPHN2ZzpnXG4gICAgICAgICAgKGNsaWNrKT1cIlxuICAgICAgICAgICAgdG9nZ2xlU3RhcnROb2RlRm9ybVBvcHVwKCRldmVudCwgbm9kZS54LCBub2RlLnksIHN3aW1sYW5lLm9yZGVyKVxuICAgICAgICAgIFwiXG4gICAgICAgICAgY2xhc3M9XCJzdGFnZS1pY29uXCJcbiAgICAgICAgICB0cmFuc2Zvcm09XCJ0cmFuc2xhdGUoLTQ1LCA0MilcIlxuICAgICAgICAgIHN0eWxlPVwiY3Vyc29yOiBwb2ludGVyOyBwb2ludGVyLWV2ZW50czogYWxsXCJcbiAgICAgICAgPlxuICAgICAgICAgIDwhLS0gVHJhbnNwYXJlbnQgcmVjdGFuZ2xlIHRvIGNhcHR1cmUgY2xpY2tzIC0tPlxuICAgICAgICAgIDxzdmc6cmVjdFxuICAgICAgICAgICAgeD1cIi0yXCJcbiAgICAgICAgICAgIHk9XCItMlwiXG4gICAgICAgICAgICB3aWR0aD1cIjI0XCJcbiAgICAgICAgICAgIGhlaWdodD1cIjI0XCJcbiAgICAgICAgICAgIGZpbGw9XCJ0cmFuc3BhcmVudFwiXG4gICAgICAgICAgICBzdHlsZT1cImN1cnNvcjogcG9pbnRlclwiXG4gICAgICAgICAgLz5cbiAgICAgICAgICA8c3ZnOnBhdGhcbiAgICAgICAgICAgIGQ9XCJNMTYuNSAyMC40NzVWMTcuNDc1SDEzLjVWMTYuNDc1SDE2LjVWMTMuNDc1SDE3LjVWMTYuNDc1SDIwLjVWMTcuNDc1SDE3LjVWMjAuNDc1SDE2LjVaTTMuNSAxNy41VjE2LjVINC41VjE3LjVIMy41Wk02LjUgMTcuNVYxNi41SDExLjUxN0MxMS41MDU3IDE2LjY3NjcgMTEuNTA0MyAxNi44NDUgMTEuNTEzIDE3LjAwNUMxMS41MjEgMTcuMTY1IDExLjUzMSAxNy4zMyAxMS41NDMgMTcuNUg2LjVaTTMuNSAxMy41VjEyLjVINC41VjEzLjVIMy41Wk02LjUgMTMuNVYxMi41SDEzLjgwNEMxMy42MTI3IDEyLjYzODcgMTMuNDMzMyAxMi43OTEzIDEzLjI2NiAxMi45NThDMTMuMDk5MyAxMy4xMjQ3IDEyLjkzNzcgMTMuMzA1MyAxMi43ODEgMTMuNUg2LjVaTTMuNSA5LjVWOC41SDQuNVY5LjVIMy41Wk02LjUgOS41VjguNUgxOC41VjkuNUg2LjVaTTMuNSA1LjVWNC41SDQuNVY1LjVIMy41Wk02LjUgNS41VjQuNUgxOC41VjUuNUg2LjVaXCJcbiAgICAgICAgICAgIFthdHRyLmZpbGxdPVwic3RhdGUud29ya2Zsb3dGb3JtSWQgPyAnI0QzNkNGRicgOiAnYmxhY2snXCJcbiAgICAgICAgICAgIHRyYW5zZm9ybT1cInNjYWxlKDAuNylcIlxuICAgICAgICAgIC8+XG4gICAgICAgIDwvc3ZnOmc+XG4gICAgICAgIDwhLS0gQXJyb3cgZnJvbSBjaXJjbGUgdG8gbm9kZSAtLT5cbiAgICAgICAgPHBhdGhcbiAgICAgICAgICBkPVwiTSAtMjAgNTAgTCAwIDUwXCJcbiAgICAgICAgICBzdHJva2U9XCIjRDM2Q0ZGXCJcbiAgICAgICAgICBzdHJva2Utd2lkdGg9XCIxXCJcbiAgICAgICAgICBtYXJrZXItZW5kPVwidXJsKCNhcnJvd2hlYWQpXCJcbiAgICAgICAgPjwvcGF0aD5cbiAgICAgICAgfVxuXG4gICAgICAgIDwhLS0gU3RhZ2Ugbm9kZSAtLT5cbiAgICAgICAgQGlmIChub2RlLnR5cGUgPT09ICdzdGFnZScpIHtcbiAgICAgICAgPCEtLSA8cmVjdFxuICAgICAgICAgIHg9XCIwXCJcbiAgICAgICAgICB5PVwiMFwiXG4gICAgICAgICAgW2F0dHIud2lkdGhdPVwibm9kZS53aWR0aFwiXG4gICAgICAgICAgW2F0dHIuaGVpZ2h0XT1cIm5vZGUuaGVpZ2h0XCJcbiAgICAgICAgICBmaWxsPVwibm9uZVwiXG4gICAgICAgICAgc3Ryb2tlPVwiI0QzNkNGRlwiXG4gICAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMVwiXG4gICAgICAgID48L3JlY3Q+IC0tPlxuICAgICAgICA8c3ZnOmdcbiAgICAgICAgICBsaWItc3RhZ2Utbm9kZVxuICAgICAgICAgIFtub2RlXT1cIm5vZGVcIlxuICAgICAgICAgIFtpc1N0YXJ0Tm9kZV09XCJub2RlLmlzU3RhcnROb2RlXCJcbiAgICAgICAgICAoc3RhZ2VQcm9wZXJ0aWVzVXBkYXRlZCk9XCJvblN0YWdlUHJvcGVydGllc1VwZGF0ZWQoJGV2ZW50KVwiXG4gICAgICAgID48L3N2ZzpnPlxuICAgICAgICB9XG5cbiAgICAgICAgPCEtLSBEZWNpc2lvbiBub2RlIC0tPlxuICAgICAgICBAaWYgKG5vZGUudHlwZSA9PT0gJ2RlY2lzaW9uJykge1xuICAgICAgICA8cGF0aFxuICAgICAgICAgIFthdHRyLmRdPVwiXG4gICAgICAgICAgICAnTSAwICcgK1xuICAgICAgICAgICAgbm9kZS5oZWlnaHQgLyAyICtcbiAgICAgICAgICAgICcgTCAnICtcbiAgICAgICAgICAgIG5vZGUud2lkdGggLyAyICtcbiAgICAgICAgICAgICcgMCcgK1xuICAgICAgICAgICAgJyBMICcgK1xuICAgICAgICAgICAgbm9kZS53aWR0aCArXG4gICAgICAgICAgICAnICcgK1xuICAgICAgICAgICAgbm9kZS5oZWlnaHQgLyAyICtcbiAgICAgICAgICAgICcgTCAnICtcbiAgICAgICAgICAgIG5vZGUud2lkdGggLyAyICtcbiAgICAgICAgICAgICcgJyArXG4gICAgICAgICAgICBub2RlLmhlaWdodCArXG4gICAgICAgICAgICAnIFonXG4gICAgICAgICAgXCJcbiAgICAgICAgICBmaWxsPVwibm9uZVwiXG4gICAgICAgICAgc3Ryb2tlPVwiI0QzNkNGRlwiXG4gICAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMVwiXG4gICAgICAgID48L3BhdGg+XG4gICAgICAgIH1cblxuICAgICAgICA8IS0tIEZvcm0gbm9kZSAtLT5cbiAgICAgICAgQGlmIChub2RlLnR5cGUgPT09ICdmb3JtJykge1xuICAgICAgICA8cGF0aFxuICAgICAgICAgIGQ9XCJNOTUuMDYyNSA1MC41NTkxVjk1LjA2MjVDOTUuMDYyNSA5Ny45NzE2IDkzLjkwNjkgMTAwLjc2MiA5MS44NDk4IDEwMi44MTlDODkuNzkyOCAxMDQuODc2IDg3LjAwMjggMTA2LjAzMSA4NC4wOTM4IDEwNi4wMzFIMzIuOTA2MkMyOS45OTcyIDEwNi4wMzEgMjcuMjA3MiAxMDQuODc2IDI1LjE1MDIgMTAyLjgxOUMyMy4wOTMxIDEwMC43NjIgMjEuOTM3NSA5Ny45NzE2IDIxLjkzNzUgOTUuMDYyNVYyMS45Mzc1QzIxLjkzNzUgMTkuMDI4NCAyMy4wOTMxIDE2LjIzODUgMjUuMTUwMiAxNC4xODE0QzI3LjIwNzIgMTIuMTI0NCAyOS45OTcyIDEwLjk2ODggMzIuOTA2MiAxMC45Njg4SDU1LjQ3MjJDNTcuNDEwOSAxMC45NjkgNTkuMjcwMSAxMS43MzkyIDYwLjY0MTIgMTMuMTA5OUw5Mi45MjEzIDQ1LjM5MDFDOTQuMjkyIDQ2Ljc2MTEgOTUuMDYyMiA0OC42MjA0IDk1LjA2MjUgNTAuNTU5MVpcIlxuICAgICAgICAgIHRyYW5zZm9ybT1cInNjYWxlKDAuNylcIlxuICAgICAgICAgIGZpbGw9XCJub25lXCJcbiAgICAgICAgICBzdHJva2U9XCIjRDM2Q0ZGXCJcbiAgICAgICAgICBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiXG4gICAgICAgIC8+XG4gICAgICAgIDxwYXRoXG4gICAgICAgICAgZD1cIk01OC41IDEyLjc5NjlWNDAuMjE4OEM1OC41IDQyLjE1ODEgNTkuMjcwNCA0NC4wMTgxIDYwLjY0MTggNDUuMzg5NUM2Mi4wMTMxIDQ2Ljc2MDggNjMuODczMSA0Ny41MzEyIDY1LjgxMjUgNDcuNTMxMkg5My4yMzQ0XCJcbiAgICAgICAgICB0cmFuc2Zvcm09XCJzY2FsZSgwLjcpXCJcbiAgICAgICAgICBzdHJva2U9XCIjRDM2Q0ZGXCJcbiAgICAgICAgICBzdHJva2UtbGluZWNhcD1cInJvdW5kXCJcbiAgICAgICAgICBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiXG4gICAgICAgIC8+XG4gICAgICAgIDx0ZXh0XG4gICAgICAgICAgeD1cIjUwJVwiXG4gICAgICAgICAgeT1cIjUwJVwiXG4gICAgICAgICAgdGV4dC1hbmNob3I9XCJtaWRkbGVcIlxuICAgICAgICAgIGRvbWluYW50LWJhc2VsaW5lPVwibWlkZGxlXCJcbiAgICAgICAgICBmb250LWZhbWlseT1cInNhbnMtc2VyaWZcIlxuICAgICAgICAgIGZvbnQtc2l6ZT1cIjE0XCJcbiAgICAgICAgICBmaWxsPVwiI0QzNkNGRlwiXG4gICAgICAgID5cbiAgICAgICAgICBGb3JtXG4gICAgICAgIDwvdGV4dD5cbiAgICAgICAgfVxuXG4gICAgICAgIDwhLS0gU3ViZmxvdyBub2RlIC0tPlxuICAgICAgICBAaWYgKG5vZGUudHlwZSA9PT0gJ3N1YmZsb3cnKSB7XG4gICAgICAgIDxwYXRoXG4gICAgICAgICAgW2F0dHIuZF09XCJcbiAgICAgICAgICAgICdNIDEgJyArXG4gICAgICAgICAgICBub2RlLmhlaWdodCAvIDQgK1xuICAgICAgICAgICAgJyBMICcgK1xuICAgICAgICAgICAgbm9kZS53aWR0aCAvIDIgK1xuICAgICAgICAgICAgJyAxIEwgJyArXG4gICAgICAgICAgICAobm9kZS53aWR0aCAtIDEpICtcbiAgICAgICAgICAgICcgJyArXG4gICAgICAgICAgICBub2RlLmhlaWdodCAvIDQgK1xuICAgICAgICAgICAgJyBWICcgK1xuICAgICAgICAgICAgKG5vZGUuaGVpZ2h0ICogMykgLyA0ICtcbiAgICAgICAgICAgICcgTCAnICtcbiAgICAgICAgICAgIG5vZGUud2lkdGggLyAyICtcbiAgICAgICAgICAgICcgJyArXG4gICAgICAgICAgICAobm9kZS5oZWlnaHQgLSAxKSArXG4gICAgICAgICAgICAnIEwgMSAnICtcbiAgICAgICAgICAgIChub2RlLmhlaWdodCAqIDMpIC8gNCArXG4gICAgICAgICAgICAnIFonXG4gICAgICAgICAgXCJcbiAgICAgICAgICBmaWxsPVwibm9uZVwiXG4gICAgICAgICAgc3Ryb2tlPVwiI0QzNkNGRlwiXG4gICAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMVwiXG4gICAgICAgID48L3BhdGg+XG4gICAgICAgIDx0ZXh0XG4gICAgICAgICAgeD1cIjUwJVwiXG4gICAgICAgICAgeT1cIjUwJVwiXG4gICAgICAgICAgdGV4dC1hbmNob3I9XCJtaWRkbGVcIlxuICAgICAgICAgIGRvbWluYW50LWJhc2VsaW5lPVwibWlkZGxlXCJcbiAgICAgICAgICBmb250LWZhbWlseT1cInNhbnMtc2VyaWZcIlxuICAgICAgICAgIGZvbnQtc2l6ZT1cIjE0XCJcbiAgICAgICAgICBmaWxsPVwiIzAwMDAwMFwiXG4gICAgICAgID5cbiAgICAgICAgICB7eyBub2RlLndvcmtmbG93RGF0YT8ubmFtZSB8fCBcIlN1YmZsb3dcIiB9fVxuICAgICAgICA8L3RleHQ+XG4gICAgICAgIH1cblxuICAgICAgICA8IS0tIENvbm5lY3Rpb24gcG9pbnRzIGZvciB0aGlzIG5vZGUgLS0+XG4gICAgICAgIEBmb3IgKHBvaW50IG9mIG5vZGUuY29ubmVjdGlvblBvaW50cyB8fCBbXTsgdHJhY2sgcG9pbnQuaWQpIHsgQGlmXG4gICAgICAgIChpc0Nvbm5lY3Rpb25Qb2ludFZpc2libGUobm9kZS5pZCkpIHtcbiAgICAgICAgPHVzZVxuICAgICAgICAgIFthdHRyLmhyZWZdPVwiJyNjb25uZWN0aW9uLXBvaW50LXRlbXBsYXRlJ1wiXG4gICAgICAgICAgW2F0dHIueF09XCJwb2ludC54XCJcbiAgICAgICAgICBbYXR0ci55XT1cInBvaW50LnlcIlxuICAgICAgICAgIFthdHRyLmlkXT1cInBvaW50LmlkXCJcbiAgICAgICAgICAobW91c2Vkb3duKT1cInN0YXJ0Q29ubmVjdGlvbkRyYWcoJGV2ZW50LCBwb2ludCwgc3dpbWxhbmUub3JkZXIpXCJcbiAgICAgICAgLz5cbiAgICAgICAgfSB9XG4gICAgICA8L2c+XG4gICAgICA8IS0tIEEgdHJhbnNwYXJlbnQgaG92ZXIgYXJlYSBmb3IgaW1wcm92ZWQgaG92ZXIgZGV0ZWN0aW9uIC0tPlxuICAgICAgPHJlY3RcbiAgICAgICAgW2F0dHIueF09XCJub2RlLnggLSAxMFwiXG4gICAgICAgIFthdHRyLnldPVwibm9kZS55ICsgNDAgLSAxMFwiXG4gICAgICAgIFthdHRyLndpZHRoXT1cIm5vZGUud2lkdGggKyAyMFwiXG4gICAgICAgIFthdHRyLmhlaWdodF09XCJub2RlLmhlaWdodCArIDIwXCJcbiAgICAgICAgZmlsbD1cInRyYW5zcGFyZW50XCJcbiAgICAgICAgKG1vdXNlb3Zlcik9XCJzaG93Q29ubmVjdGlvblBvaW50cyhub2RlLmlkLCBzd2ltbGFuZS5vcmRlcilcIlxuICAgICAgICAobW91c2VvdXQpPVwiaGlkZUNvbm5lY3Rpb25Qb2ludHMobm9kZS5pZClcIlxuICAgICAgICBzdHlsZT1cInBvaW50ZXItZXZlbnRzOiBub25lXCJcbiAgICAgIC8+XG4gICAgICB9XG4gICAgPC9nPlxuICAgIH0gQGZvciAoY29ubmVjdGlvbiBvZiBzdGF0ZS5jb25uZWN0aW9uczsgdHJhY2sgY29ubmVjdGlvbi5pZCkge1xuICAgIDxnPlxuICAgICAgPHBhdGhcbiAgICAgICAgW2F0dHIuZF09XCJnZXRDb25uZWN0aW9uUGF0aEZvclNhdmVkQ29ubmVjdGlvbihjb25uZWN0aW9uKVwiXG4gICAgICAgIHN0cm9rZT1cIiNEMzZDRkZcIlxuICAgICAgICBzdHJva2Utd2lkdGg9XCIyXCJcbiAgICAgICAgZmlsbD1cIm5vbmVcIlxuICAgICAgICBtYXJrZXItZW5kPVwidXJsKCNhcnJvd2hlYWQpXCJcbiAgICAgID48L3BhdGg+XG4gICAgPC9nPlxuICAgIH1cblxuICAgIDwhLS0gQ29ubmVjdGlvbiBwcmV2aWV3IGxpbmUgLS0+XG4gICAgQGlmIChzdGF0ZS5pc0Nvbm5lY3Rpb25EcmFnZ2luZygpKSB7XG4gICAgPGc+XG4gICAgICA8cGF0aFxuICAgICAgICBbYXR0ci5kXT1cImdldENvbm5lY3Rpb25QYXRoKClcIlxuICAgICAgICBzdHJva2U9XCIjRDM2Q0ZGXCJcbiAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMlwiXG4gICAgICAgIHN0cm9rZS1kYXNoYXJyYXk9XCI1LDVcIlxuICAgICAgICBmaWxsPVwibm9uZVwiXG4gICAgICA+PC9wYXRoPlxuICAgIDwvZz5cbiAgICB9XG4gIDwvc3ZnPlxuXG4gIDxkaXZcbiAgICAqbmdJZj1cInBvcHVwVmlzaWJsZVwiXG4gICAgW3N0eWxlLnBvc2l0aW9uXT1cIidhYnNvbHV0ZSdcIlxuICAgIFtzdHlsZS5sZWZ0LnB4XT1cInBvcHVwWFwiXG4gICAgW3N0eWxlLnRvcC5weF09XCJwb3B1cFlcIlxuICA+XG4gICAgPHZlcmJlbi1wb3AtVXBcbiAgICAgIFtkcm9wZG93bk9wZW5dPVwidHJ1ZVwiXG4gICAgICBbY3VzdG9tU3R5bGVzXT1cInsgJ3otaW5kZXgnOiAnOTknIH1cIlxuICAgICAgW2VuYWJsZU1vdXNlTGVhdmVdPVwiZmFsc2VcIlxuICAgID5cbiAgICAgIDxkaXYgZHJvcGRvd24tdHJpZ2dlciBzdHlsZT1cImRpc3BsYXk6IG5vbmVcIj5cbiAgICAgICAgPCEtLSBIaWRkZW4gdHJpZ2dlciBlbGVtZW50IC0tPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2XG4gICAgICAgIGNsYXNzPVwicC0zIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDAgcm91bmRlZCBzaGFkb3ctbWRcIlxuICAgICAgICBkcm9wZG93bi1jb250ZW50XG4gICAgICA+XG4gICAgICAgIDxoNCBjbGFzcz1cIm1iLTIgZm9udC1tZWRpdW1cIj5DcmVhdGUgQ29ubmVjdGlvbjwvaDQ+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtY29sIGdhcC0yXCI+XG4gICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgdHlwZSBvZiBhbGxvd2VkTm9kZVR5cGVzXCI+XG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIGNsYXNzPVwicHgtMyBweS0yIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDAgcm91bmRlZCB0ZXh0LXNtIGhvdmVyOmJnLWdyYXktNTBcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwiY3JlYXRlTm9kZUNvbm5lY3Rpb24odHlwZSlcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICBDcmVhdGUge3sgdHlwZSB8IHRpdGxlY2FzZSB9fVxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgY2xhc3M9XCJweC0zIHB5LTIgYmctd2hpdGUgYm9yZGVyIGJvcmRlci1ncmF5LTIwMCByb3VuZGVkIHRleHQtc20gaG92ZXI6YmctZ3JheS01MFwiXG4gICAgICAgICAgICAoY2xpY2spPVwiaGlkZUNvbm5lY3Rpb25Qb3B1cCgpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICBDYW5jZWxcbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L3ZlcmJlbi1wb3AtVXA+XG4gIDwvZGl2PlxuXG4gIDxkaXZcbiAgICAqbmdJZj1cInNob3dTdGFydE5vZGVGb3JtUG9wdXBcIlxuICAgIFtzdHlsZS5wb3NpdGlvbl09XCInYWJzb2x1dGUnXCJcbiAgICBbc3R5bGUubGVmdC5weF09XCJzdGFydE5vZGVGb3JtUG9wdXBYXCJcbiAgICBbc3R5bGUudG9wLnB4XT1cInN0YXJ0Tm9kZUZvcm1Qb3B1cFlcIlxuICA+XG4gICAgPHZlcmJlbi1wb3AtVXAgW2Ryb3Bkb3duT3Blbl09XCJ0cnVlXCIgW2N1c3RvbVN0eWxlc109XCJ7ICd6LWluZGV4JzogJzEwMCcgfVwiPlxuICAgICAgPGRpdiBkcm9wZG93bi10cmlnZ2VyIHN0eWxlPVwiZGlzcGxheTogbm9uZVwiPlxuICAgICAgICA8IS0tIEhpZGRlbiB0cmlnZ2VyIGVsZW1lbnQgLS0+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXZcbiAgICAgICAgY2xhc3M9XCJwLTMgYmctd2hpdGUgYm9yZGVyIGJvcmRlci1ncmF5LTIwMCByb3VuZGVkIHNoYWRvdy1tZCB3LTY0XCJcbiAgICAgICAgZHJvcGRvd24tY29udGVudFxuICAgICAgICBzdHlsZT1cImJhY2tncm91bmQtY29sb3I6IHdoaXRlOyB6LWluZGV4OiAxMDAwXCJcbiAgICAgID5cbiAgICAgICAgPGg0IGNsYXNzPVwibWItMiBmb250LW1lZGl1bVwiPlNlbGVjdCBXb3JrZmxvdyBGb3JtPC9oND5cbiAgICAgICAgPGRpdiAqbmdJZj1cImlzTG9hZGluZ1N0YXJ0Tm9kZUZvcm1zXCIgY2xhc3M9XCJ0ZXh0LWNlbnRlciBweS0yXCI+XG4gICAgICAgICAgTG9hZGluZyBmb3Jtcy4uLlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiAqbmdJZj1cIiFpc0xvYWRpbmdTdGFydE5vZGVGb3Jtc1wiIGNsYXNzPVwibWF4LWgtNDggb3ZlcmZsb3cteS1hdXRvXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTJcIj5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgY2xhc3M9XCJ3LWZ1bGwgcHgtMyBweS0yIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDAgcm91bmRlZCB0ZXh0LXNtIGhvdmVyOmJnLWdyYXktNTAgdGV4dC1sZWZ0XCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdFN0YXJ0Tm9kZUZvcm0obnVsbClcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICBDbGVhciBmb3JtIHNlbGVjdGlvblxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgZm9ybSBvZiBzdGFydE5vZGVGb3Jtc0xpc3RcIiBjbGFzcz1cIm1iLTFcIj5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgY2xhc3M9XCJ3LWZ1bGwgcHgtMyBweS0yIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDAgcm91bmRlZCB0ZXh0LXNtIGhvdmVyOmJnLWdyYXktNTAgdGV4dC1sZWZ0XCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdFN0YXJ0Tm9kZUZvcm0oZm9ybSlcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7eyBmb3JtLk5hbWUgfX1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICpuZ0lmPVwic3RhcnROb2RlRm9ybXNMaXN0Lmxlbmd0aCA9PT0gMFwiXG4gICAgICAgICAgICBjbGFzcz1cInRleHQtY2VudGVyIHB5LTIgdGV4dC1ncmF5LTUwMFwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgTm8gZm9ybXMgYXZhaWxhYmxlXG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC92ZXJiZW4tcG9wLVVwPlxuICA8L2Rpdj5cblxuICA8ZGl2XG4gICAgKm5nSWY9XCJzaG93U3ViZmxvd1BvcHVwXCJcbiAgICBbc3R5bGUucG9zaXRpb25dPVwiJ2ZpYWJzb2x1dGV4ZWQnXCJcbiAgICBbc3R5bGUubGVmdC5weF09XCJzdWJmbG93UG9wdXBYXCJcbiAgICBbc3R5bGUudG9wLnB4XT1cInN1YmZsb3dQb3B1cFlcIlxuICA+XG4gICAgPHZlcmJlbi1wb3AtVXAgW2Ryb3Bkb3duT3Blbl09XCJ0cnVlXCIgW2N1c3RvbVN0eWxlc109XCJ7ICd6LWluZGV4JzogJzEwMCcgfVwiPlxuICAgICAgPGRpdiBkcm9wZG93bi10cmlnZ2VyIHN0eWxlPVwiZGlzcGxheTogbm9uZVwiPlxuICAgICAgICA8IS0tIEhpZGRlbiB0cmlnZ2VyIGVsZW1lbnQgLS0+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXZcbiAgICAgICAgY2xhc3M9XCJwLTMgYmctd2hpdGUgYm9yZGVyIGJvcmRlci1ncmF5LTIwMCByb3VuZGVkIHNoYWRvdy1tZCB3LTY0XCJcbiAgICAgICAgZHJvcGRvd24tY29udGVudFxuICAgICAgICBzdHlsZT1cImJhY2tncm91bmQtY29sb3I6IHdoaXRlOyB6LWluZGV4OiAxMDAwXCJcbiAgICAgID5cbiAgICAgICAgPGg0IGNsYXNzPVwibWItMiBmb250LW1lZGl1bVwiPlNlbGVjdCBXb3JrZmxvdzwvaDQ+XG4gICAgICAgIDxkaXYgKm5nSWY9XCJpc0xvYWRpbmdXb3JrZmxvd3NcIiBjbGFzcz1cInRleHQtY2VudGVyIHB5LTJcIj5cbiAgICAgICAgICBMb2FkaW5nIHdvcmtmbG93cy4uLlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiAqbmdJZj1cIiFpc0xvYWRpbmdXb3JrZmxvd3NcIiBjbGFzcz1cIm1heC1oLTQ4IG92ZXJmbG93LXktYXV0b1wiPlxuICAgICAgICAgIDxkaXYgKm5nRm9yPVwibGV0IHdvcmtmbG93IG9mIHdvcmtmbG93c0xpc3RcIiBjbGFzcz1cIm1iLTFcIj5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgY2xhc3M9XCJ3LWZ1bGwgcHgtMyBweS0yIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDAgcm91bmRlZCB0ZXh0LXNtIGhvdmVyOmJnLWdyYXktNTAgdGV4dC1sZWZ0XCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdFN1YmZsb3dXb3JrZmxvdyh3b3JrZmxvdylcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7eyB3b3JrZmxvdy5OYW1lIH19XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICA8L2Rpdj5cbiAgICAgICAgICA8ZGl2XG4gICAgICAgICAgICAqbmdJZj1cIndvcmtmbG93c0xpc3QubGVuZ3RoID09PSAwXCJcbiAgICAgICAgICAgIGNsYXNzPVwidGV4dC1jZW50ZXIgcHktMiB0ZXh0LWdyYXktNTAwXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICBObyB3b3JrZmxvd3MgYXZhaWxhYmxlXG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC92ZXJiZW4tcG9wLVVwPlxuICA8L2Rpdj5cbjwvZGl2PlxuIl19
764
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVzaWduZXItY2FudmFzLmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3ZlcmJlbi13b3JrZmxvdy11aS9zcmMvbGliL2NvbXBvbmVudHMvd29ya2Zsb3ctZGVzaWduZXIvZGVzaWduZXItY2FudmFzL2Rlc2lnbmVyLWNhbnZhcy5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy92ZXJiZW4td29ya2Zsb3ctdWkvc3JjL2xpYi9jb21wb25lbnRzL3dvcmtmbG93LWRlc2lnbmVyL2Rlc2lnbmVyLWNhbnZhcy9kZXNpZ25lci1jYW52YXMuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUNMLFNBQVMsRUFFVCxZQUFZLEVBQ1osWUFBWSxFQUNaLEtBQUssRUFFTCxNQUFNLEVBQ04sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFDOzs7Ozs7Ozs7QUFtQnZCLE1BQU0sT0FBTyx1QkFBdUI7SUEwRnpCO0lBQ0M7SUExRkQsWUFBWSxHQUFhLElBQUksQ0FBQztJQUM3QixlQUFlLEdBQUcsSUFBSSxZQUFZLEVBQTRCLENBQUM7SUFDL0QsZUFBZSxHQUFHLElBQUksWUFBWSxFQUFFLENBQUM7SUFDL0Msb0JBQW9CLEdBQ2xCLElBQUksQ0FBQztJQUNHLGVBQWUsR0FBRyxJQUFJLFlBQVksRUFLeEMsQ0FBQztJQUNLLHNCQUFzQixHQUFHLElBQUksWUFBWSxFQUcvQyxDQUFDO0lBRUwsK0JBQStCO0lBQ1EsU0FBUyxDQUEwQjtJQUcxRSxlQUFlLENBQUMsS0FBaUI7UUFDL0Isc0VBQXNFO1FBQ3RFLElBQ0UsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCO1lBQ3RCLENBQUMsSUFBSSxDQUFDLHNCQUFzQjtZQUM1QixDQUFDLElBQUksQ0FBQyxZQUFZLElBQUksdUNBQXVDO1lBQzdELElBQUksQ0FBQyxLQUFLLENBQUMsb0JBQW9C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QUFDO1lBQ3ZDLElBQUksQ0FBQyxZQUFZLEdBQUcsY0FBYyxDQUFDO1FBQ3JDLENBQUM7SUFDSCxDQUFDO3dHQTMvQlUsdUJBQXVCOzRGQUF2Qix1QkFBdUIsc2ZDNUJwQyxvbWtCQWdtQkE7OzRGRHBrQmEsdUJBQXVCO2tCQUxuQyxTQUFTOytCQUNFLHFCQUFxQjs0SEFLdEIsWUFBWTtzQkFBcEIsS0FBSztnQkFDSSxlQUFlO3NCQUF4QixNQUFNO2dCQUNHLGVBQWU7c0JBQXhCLE1BQU07Z0JBR0csZUFBZTtzQkFBeEIsTUFBTTtnQkFNRyxzQkFBc0I7c0JBQS9CLE1BQU07Z0JBTWdDLFNBQVM7c0JBQS9DLFNBQVM7dUJBQUMsUUFBUSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFHckMsZUFBZTtzQkFEZCxZQUFZO3VCQUFDLGdCQUFnQixFQUFFLENBQUMsUUFBUSxDQUFDO2dCQTZWMUMsZUFBZTtzQkFEZCxZQUFZO3VCQUFDLGdCQUFnQixFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIEhvc3RMaXN0ZW5lcixcbiAgSW5wdXQsXG4gIE9uSW5pdCxcbiAgT3V0cHV0LFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHtcbiAgQ29ubmVjdGlvbixcbiAgQ29ubmVjdGlvblBvaW50LFxuICBOb2RlIGFzIFdGTm9kZSxcbiAgVG9vbFR5cGUsXG4gIFN3aW1sYW5lSXRlbSxcbn0gZnJvbSAnLi4vd29ya2Zsb3ctZGVzaWduZXIudHlwZXMnO1xuaW1wb3J0IHsgV29ya2Zsb3dEZXNpZ25lclN0YXRlIH0gZnJvbSAnLi4vd29ya2Zsb3ctZGVzaWduZXIuc3RhdGUnO1xuaW1wb3J0IHsgV29ya2Zsb3dTdGFnZSB9IGZyb20gJy4uLy4uLy4uL21vZGVscy9Xb3JrZmxvd1N0YWdlJztcbmltcG9ydCB7IEZvcm1FbnRpdHkgfSBmcm9tICcuLi8uLi8uLi9tb2RlbHMvRm9ybUVudGl0eSc7XG5pbXBvcnQgeyBXb3JrZmxvdyB9IGZyb20gJy4uLy4uLy4uL21vZGVscy9Xb3JrZmxvdyc7XG5pbXBvcnQgeyBXb3JrZmxvd0RhdGFTZXJ2aWNlIH0gZnJvbSAnLi4vd29ya2Zsb3ctZGF0YS5zZXJ2aWNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnbGliLWRlc2lnbmVyLWNhbnZhcycsXG4gIHRlbXBsYXRlVXJsOiAnLi9kZXNpZ25lci1jYW52YXMuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vZGVzaWduZXItY2FudmFzLmNvbXBvbmVudC5jc3MnLFxufSlcbmV4cG9ydCBjbGFzcyBEZXNpZ25lckNhbnZhc0NvbXBvbmVudCBpbXBsZW1lbnRzIE9uSW5pdCB7XG4gIEBJbnB1dCgpIHNlbGVjdGVkVG9vbDogVG9vbFR5cGUgPSBudWxsO1xuICBAT3V0cHV0KCkgY2xpY2tlZFBvc2l0aW9uID0gbmV3IEV2ZW50RW1pdHRlcjx7IHg6IG51bWJlcjsgeTogbnVtYmVyIH0+KCk7XG4gIEBPdXRwdXQoKSBzdWJmbG93U2VsZWN0ZWQgPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIHBlbmRpbmdTdGFnZVBvc2l0aW9uOiB7IHN3aW1sYW5lSW5kZXg6IG51bWJlcjsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSB8IG51bGwgPVxuICAgIG51bGw7XG4gIEBPdXRwdXQoKSBzaG93U3RhZ2VEaWFsb2cgPSBuZXcgRXZlbnRFbWl0dGVyPHtcbiAgICBwb3NpdGlvbjogYW55O1xuICAgIGlzRnJvbUNvbm5lY3Rpb246IGJvb2xlYW47XG4gICAgaXNGcm9tRGVjaXNpb24/OiBib29sZWFuO1xuICAgIG5vZGVJZDogc3RyaW5nO1xuICB9PigpO1xuICBAT3V0cHV0KCkgc3RhZ2VQcm9wZXJ0aWVzVXBkYXRlZCA9IG5ldyBFdmVudEVtaXR0ZXI8e1xuICAgIG5vZGVJZDogc3RyaW5nO1xuICAgIHN0YWdlRGF0YTogUGFydGlhbDxXb3JrZmxvd1N0YWdlPjtcbiAgfT4oKTtcblxuICAvLyBSZWZlcmVuY2UgdG8gdGhlIFNWRyBlbGVtZW50XG4gIEBWaWV3Q2hpbGQoJ2NhbnZhcycsIHsgc3RhdGljOiB0cnVlIH0pIGNhbnZhc1JlZiE6IEVsZW1lbnRSZWY8U1ZHRWxlbWVudD47XG5cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93Om1vdXNldXAnLCBbJyRldmVudCddKVxuICBvbldpbmRvd01vdXNlVXAoZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICAvLyBJZiB3ZSBoYXZlIGEgcG9wdXAgb3BlbiBidXQgdGhlIG1vdXNlIGlzIHJlbGVhc2VkIG91dHNpZGUsIGNsZWFuIHVwXG4gICAgaWYgKFxuICAgICAgIXRoaXMuc2hvd1N1YmZsb3dQb3B1cCAmJlxuICAgICAgIXRoaXMuc2hvd1N0YXJ0Tm9kZUZvcm1Qb3B1cCAmJlxuICAgICAgIXRoaXMucG9wdXBWaXNpYmxlICYmIC8vIE9ubHkgZW5kIGRyYWcgaWYgbm8gcG9wdXAgaXMgdmlzaWJsZVxuICAgICAgdGhpcy5zdGF0ZS5pc0Nvbm5lY3Rpb25EcmFnZ2luZygpXG4gICAgKSB7XG4gICAgICBjb25zb2xlLmxvZygnRXh0ZXJuYWwgbW91c2V1cCBkZXRlY3RlZCAtIGNsZWFuaW5nIHVwIGNvbm5lY3Rpb24gZHJhZycpO1xuICAgICAgdGhpcy5zdGF0ZS5lbmRDb25uZWN0aW9uRHJhZygpO1xuICAgIH1cbiAgfVxuXG4gIC8vIENhbnZhcyBkaW1lbnNpb25zXG4gIGNhbnZhc1dpZHRoID0gMzAwMDtcbiAgY2FudmFzSGVpZ2h0ID0gMjAwMDtcblxuICAvLyBHcmlkIHNpemVcbiAgZ3JpZFNpemUgPSAyMDtcblxuICBzd2ltbGFuZUhlaWdodCA9IDI2MztcbiAgdmlzaWJsZUNvbm5lY3Rpb25Qb2ludHNOb2RlSWQ6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICBwb3B1cFZpc2libGUgPSBmYWxzZTtcbiAgcG9wdXBYID0gMDtcbiAgcG9wdXBZID0gMDtcbiAgYWxsb3dlZE5vZGVUeXBlczogc3RyaW5nW10gPSBbXTtcblxuICBzaG93U3RhcnROb2RlRm9ybVBvcHVwOiBib29sZWFuID0gZmFsc2U7XG4gIHN0YXJ0Tm9kZUZvcm1zTGlzdDogRm9ybUVudGl0eVtdID0gW107XG4gIGlzTG9hZGluZ1N0YXJ0Tm9kZUZvcm1zOiBib29sZWFuID0gZmFsc2U7XG4gIHN0YXJ0Tm9kZUZvcm1Qb3B1cFg6IG51bWJlciA9IDA7XG4gIHN0YXJ0Tm9kZUZvcm1Qb3B1cFk6IG51bWJlciA9IDA7XG5cbiAgc2hvd1N1YmZsb3dQb3B1cDogYm9vbGVhbiA9IGZhbHNlO1xuICB3b3JrZmxvd3NMaXN0OiBXb3JrZmxvd1tdID0gW107XG4gIGlzTG9hZGluZ1dvcmtmbG93czogYm9vbGVhbiA9IGZhbHNlO1xuICBzdWJmbG93UG9wdXBYOiBudW1iZXIgPSAwO1xuICBzdWJmbG93UG9wdXBZOiBudW1iZXIgPSAwO1xuICBwZW5kaW5nU3ViZmxvd1Bvc2l0aW9uOiB7XG4gICAgc3dpbWxhbmVJbmRleDogbnVtYmVyO1xuICAgIHg6IG51bWJlcjtcbiAgICB5OiBudW1iZXI7XG4gIH0gfCBudWxsID0gbnVsbDtcblxuICBwZW5kaW5nRGVjaXNpb25Db25uZWN0aW9uOiB7XG4gICAgZGVjaXNpb25Ob2RlSWQ6IHN0cmluZztcbiAgICBzd2ltbGFuZUluZGV4OiBudW1iZXI7XG4gICAgeDogbnVtYmVyO1xuICAgIHk6IG51bWJlcjtcbiAgfSB8IG51bGwgPSBudWxsO1xuXG4gIHBlbmRpbmdDb25uZWN0aW9uU291cmNlUG9pbnQ6IENvbm5lY3Rpb25Qb2ludCB8IG51bGwgPSBudWxsO1xuICBwZW5kaW5nQ29ubmVjdGlvblNvdXJjZVN3aW1sYW5lSW5kZXg6IG51bWJlciB8IG51bGwgPSBudWxsO1xuXG4gIHNob3dEZWNpc2lvbkNvbmRpdGlvbkRpYWxvZzogYm9vbGVhbiA9IGZhbHNlO1xuICBzaG93Q29uZGl0aW9uc0RpYWxvZzogYm9vbGVhbiA9IGZhbHNlO1xuICBhY3RpdmVEZWNpc2lvbk5vZGVJZDogc3RyaW5nID0gJyc7XG4gIGFjdGl2ZUNvbm5lY3Rpb25JZDogc3RyaW5nID0gJyc7XG4gIGRlY2lzaW9uQ29uZGl0aW9uUG9wdXBYOiBudW1iZXIgPSAwO1xuICBkZWNpc2lvbkNvbmRpdGlvblBvcHVwWTogbnVtYmVyID0gMDtcblxuICBpc0NyZWF0aW5nU3RhZ2VGcm9tRGVjaXNpb246IGJvb2xlYW4gPSBmYWxzZTtcbiAgcGVuZGluZ0RlY2lzaW9uQ29uZGl0aW9uOiBzdHJpbmcgPSAnJztcbiAgYWN0aXZlU3RhZ2VJZDogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG5cbiAgc2hvd1N0YWdlRGlhbG9nTG9jYWw6IGJvb2xlYW4gPSBmYWxzZTtcbiAgYWN0aXZlU3RhZ2VEYXRhOiBQYXJ0aWFsPFdvcmtmbG93U3RhZ2U+ID0ge307XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHVibGljIHN0YXRlOiBXb3JrZmxvd0Rlc2lnbmVyU3RhdGUsXG4gICAgcHJpdmF0ZSBkYXRhU2VydmljZTogV29ya2Zsb3dEYXRhU2VydmljZVxuICApIHt9XG5cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy51cGRhdGVDYW52YXNTaXplKCk7XG4gIH1cblxuICAvLyBIYW5kbGUgbW91c2UgY2xpY2sgb24gY2FudmFzXG4gIG9uQ2FudmFzQ2xpY2soZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICAvLyBPbmx5IHByb2Nlc3MgY2FudmFzIGNsaWNrcyBpZiBhIHRvb2wgaXMgc2VsZWN0ZWRcbiAgICBpZiAoIXRoaXMuc2VsZWN0ZWRUb29sKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gR2V0IHRoZSBwb3NpdGlvbiB3aGVyZSB0aGUgY2xpY2sgb2NjdXJyZWRcbiAgICBjb25zdCBwb3NpdGlvbiA9IHRoaXMuZ2V0TW91c2VQb3NpdGlvbihldmVudCk7XG4gICAgY29uc29sZS5sb2coXG4gICAgICAnQ2FudmFzIGNsaWNrZWQgYXQ6JyxcbiAgICAgIHBvc2l0aW9uLFxuICAgICAgJ3dpdGggdG9vbDonLFxuICAgICAgdGhpcy5zZWxlY3RlZFRvb2xcbiAgICApO1xuXG4gICAgLy8gQ2FsY3VsYXRlIHRoZSBzd2ltbGFuZSBpbmRleCBiYXNlZCBvbiBwb3NpdGlvblxuICAgIC8vIGNvbnN0IHN3aW1sYW5lSW5kZXggPSBNYXRoLmZsb29yKHBvc2l0aW9uLnkgLyB0aGlzLnN3aW1sYW5lSGVpZ2h0KTtcblxuICAgIC8vIE9ubHkgZW1pdCB0aGUgcG9zaXRpb24gaWYgd2UgaGF2ZSBhIHRvb2wgc2VsZWN0ZWQgYW5kIGl0J3MgYSB2YWxpZCBjbGljayBhcmVhXG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRUb29sKSB7XG4gICAgICB0aGlzLmNsaWNrZWRQb3NpdGlvbi5lbWl0KHtcbiAgICAgICAgeDogcG9zaXRpb24ueCxcbiAgICAgICAgeTogcG9zaXRpb24ueSxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIG9uU2hvd1NoaWVsZERpYWxvZyhzdGFnZUlkOiBzdHJpbmcpOiB2b2lkIHtcbiAgICAvLyBGaW5kIHRoZSBub2RlXG4gICAgY29uc3Qgbm9kZUluZm8gPSB0aGlzLnN0YXRlLmZpbmROb2RlQnlJZChzdGFnZUlkKTtcbiAgICBpZiAobm9kZUluZm8pIHtcbiAgICAgIHRoaXMuYWN0aXZlU3RhZ2VJZCA9IHN0YWdlSWQ7XG4gICAgICB0aGlzLmFjdGl2ZVN0YWdlRGF0YSA9IG5vZGVJbmZvLm5vZGUuc3RhZ2VEYXRhIHx8IHt9O1xuICAgICAgdGhpcy5zaG93U3RhZ2VEaWFsb2dMb2NhbCA9IHRydWU7XG4gICAgfVxuICB9XG5cbiAgLy8gQWRkIHRoaXMgbWV0aG9kIHRvIGhhbmRsZSBkaWFsb2cgY2xvc3VyZVxuICBvblN0YWdlRGlhbG9nQ2xvc2VkKCk6IHZvaWQge1xuICAgIHRoaXMuc2hvd1N0YWdlRGlhbG9nTG9jYWwgPSBmYWxzZTtcbiAgICB0aGlzLmFjdGl2ZVN0YWdlSWQgPSBudWxsO1xuICAgIHRoaXMuYWN0aXZlU3RhZ2VEYXRhID0ge307XG4gIH1cblxuICAvLyBBZGQgdGhpcyBtZXRob2QgdG8gaGFuZGxlIHNhdmluZyBzdGFnZSBkYXRhXG4gIG9uU3RhZ2VEaWFsb2dTYXZlZChzdGFnZURhdGE6IFBhcnRpYWw8V29ya2Zsb3dTdGFnZT4pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5hY3RpdmVTdGFnZUlkKSB7XG4gICAgICAvLyBFZGl0aW5nIGFuIGV4aXN0aW5nIHN0YWdlXG4gICAgICBjb25zdCBub2RlSW5mbyA9IHRoaXMuc3RhdGUuZmluZE5vZGVCeUlkKHRoaXMuYWN0aXZlU3RhZ2VJZCk7XG4gICAgICBpZiAobm9kZUluZm8pIHtcbiAgICAgICAgLy8gVXBkYXRlIHRoZSBzdGFnZSBkYXRhXG4gICAgICAgIG5vZGVJbmZvLm5vZGUuc3RhZ2VEYXRhID0ge1xuICAgICAgICAgIC4uLm5vZGVJbmZvLm5vZGUuc3RhZ2VEYXRhLFxuICAgICAgICAgIC4uLnN0YWdlRGF0YSxcbiAgICAgICAgfTtcbiAgICAgICAgY29uc29sZS5sb2coJ1VwZGF0ZWQgc3RhZ2UgZGF0YTonLCBub2RlSW5mby5ub2RlLnN0YWdlRGF0YSk7XG5cbiAgICAgICAgLy8gRW1pdCBldmVudCBmb3IgcGFyZW50IGNvbXBvbmVudCB0byBrbm93IGFib3V0IHRoZSB1cGRhdGVcbiAgICAgICAgdGhpcy5zdGFnZVByb3BlcnRpZXNVcGRhdGVkLmVtaXQoe1xuICAgICAgICAgIG5vZGVJZDogdGhpcy5hY3RpdmVTdGFnZUlkLFxuICAgICAgICAgIHN0YWdlRGF0YTogbm9kZUluZm8ubm9kZS5zdGFnZURhdGEsXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENsb3NlIHRoZSBkaWFsb2dcbiAgICB0aGlzLm9uU3RhZ2VEaWFsb2dDbG9zZWQoKTtcbiAgfVxuXG4gIHVwZGF0ZUNhbnZhc1NpemUoKTogdm9pZCB7XG4gICAgY29uc3QgcmVxdWlyZWRIZWlnaHQgPVxuICAgICAgKHRoaXMuc3RhdGUuc3dpbWxhbmVzLmxlbmd0aCArIDEpICogdGhpcy5zd2ltbGFuZUhlaWdodDtcbiAgICB0aGlzLmNhbnZhc0hlaWdodCA9IE1hdGgubWF4KDIwMDAsIHJlcXVpcmVkSGVpZ2h0KTsgLy8gRW5zdXJlIHdlIGhhdmUgYXQgbGVhc3Qgb3VyIGRlZmF1bHQgaGVpZ2h0XG5cbiAgICAvLyBVcGRhdGUgYWxsIHRoZSBzd2ltbGFuZSBjbGlwIHBhdGhzIHdoZW4gc2l6ZSBjaGFuZ2VzXG4gICAgc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICB0aGlzLnN0YXRlLnN3aW1sYW5lcy5mb3JFYWNoKChzd2ltbGFuZSwgaW5kZXgpID0+IHtcbiAgICAgICAgY29uc3QgY2xpcFBhdGhJZCA9IGBzd2ltbGFuZS1jbGlwLSR7aW5kZXh9YDtcbiAgICAgICAgY29uc3QgY2xpcFBhdGhFbGVtZW50ID0gZG9jdW1lbnQuZ2V0RWxlbWVudEJ5SWQoY2xpcFBhdGhJZCk7XG4gICAgICAgIGlmIChjbGlwUGF0aEVsZW1lbnQpIHtcbiAgICAgICAgICBjb25zdCByZWN0RWxlbWVudCA9IGNsaXBQYXRoRWxlbWVudC5xdWVyeVNlbGVjdG9yKCdyZWN0Jyk7XG4gICAgICAgICAgaWYgKHJlY3RFbGVtZW50KSB7XG4gICAgICAgICAgICByZWN0RWxlbWVudC5zZXRBdHRyaWJ1dGUoJ3dpZHRoJywgdGhpcy5jYW52YXNXaWR0aC50b1N0cmluZygpKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH0sIDApO1xuICB9XG5cbiAgLy8gSGVscGVyIG1ldGhvZCB0byBnZXQgdGhlIG1vdXNlIHBvc2l0aW9uIHJlbGF0aXZlIHRvIHRoZSBTVkcgY2FudmFzXG4gIHByaXZhdGUgZ2V0TW91c2VQb3NpdGlvbihldmVudDogTW91c2VFdmVudCk6IHsgeDogbnVtYmVyOyB5OiBudW1iZXIgfSB7XG4gICAgLy8gVXNlIGNsaWVudFgvWSBhbmQgZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkgZm9yIGNyb3NzLWJyb3dzZXIgY29tcGF0aWJpbGl0eVxuICAgIGNvbnN0IHJlY3QgPSB0aGlzLmNhbnZhc1JlZi5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgIHJldHVybiB7XG4gICAgICB4OiBldmVudC5jbGllbnRYIC0gcmVjdC5sZWZ0LFxuICAgICAgeTogZXZlbnQuY2xpZW50WSAtIHJlY3QudG9wLFxuICAgIH07XG4gIH1cblxuICBzaG93Q29ubmVjdGlvblBvaW50cyhub2RlSWQ6IHN0cmluZywgc3dpbWxhbmVJbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgdGhpcy52aXNpYmxlQ29ubmVjdGlvblBvaW50c05vZGVJZCA9IG5vZGVJZDtcbiAgfVxuXG4gIGlzTW91c2VPdmVyTm9kZShcbiAgICBldmVudDogTW91c2VFdmVudCxcbiAgICBub2RlOiBXRk5vZGUsXG4gICAgc3dpbWxhbmVJbmRleDogbnVtYmVyXG4gICk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IHBvc2l0aW9uID0gdGhpcy5nZXRNb3VzZVBvc2l0aW9uKGV2ZW50KTtcbiAgICBjb25zdCBub2RlQm91bmRzID0gdGhpcy5nZXROb2RlQm91bmRzV2l0aFBhZGRpbmcobm9kZSwgc3dpbWxhbmVJbmRleCk7XG5cbiAgICByZXR1cm4gKFxuICAgICAgcG9zaXRpb24ueCA+PSBub2RlQm91bmRzLnggJiZcbiAgICAgIHBvc2l0aW9uLnggPD0gbm9kZUJvdW5kcy54ICsgbm9kZUJvdW5kcy53aWR0aCAmJlxuICAgICAgcG9zaXRpb24ueSA+PSBub2RlQm91bmRzLnkgJiZcbiAgICAgIHBvc2l0aW9uLnkgPD0gbm9kZUJvdW5kcy55ICsgbm9kZUJvdW5kcy5oZWlnaHRcbiAgICApO1xuICB9XG5cbiAgLy8gaGVscGVyIG1ldGhvZCB0byBjYWxjdWxhdGUgbm9kZSBib3VuZHMgd2l0aCBwYWRkaW5nXG4gIGdldE5vZGVCb3VuZHNXaXRoUGFkZGluZyhcbiAgICBub2RlOiBXRk5vZGUsXG4gICAgc3dpbWxhbmVJbmRleDogbnVtYmVyXG4gICk6IHsgeDogbnVtYmVyOyB5OiBudW1iZXI7IHdpZHRoOiBudW1iZXI7IGhlaWdodDogbnVtYmVyIH0ge1xuICAgIGNvbnN0IHBhZGRpbmcgPSAxMDsgLy8gQWRkIDEwcHggcGFkZGluZyBhcm91bmQgbm9kZXMgZm9yIGVhc2llciBob3ZlciBkZXRlY3Rpb25cblxuICAgIC8vIENhbGN1bGF0ZSB0aGUgYWJzb2x1dGUgWSBwb3NpdGlvbiBpbmNsdWRpbmcgc3dpbWxhbmUgb2Zmc2V0XG4gICAgY29uc3QgYWJzb2x1dGVZID0gbm9kZS55ICsgKHN3aW1sYW5lSW5kZXggKiAyNjMgKyA0MCk7XG5cbiAgICByZXR1cm4ge1xuICAgICAgeDogbm9kZS54IC0gcGFkZGluZyxcbiAgICAgIHk6IGFic29sdXRlWSAtIHBhZGRpbmcsXG4gICAgICB3aWR0aDogbm9kZS53aWR0aCArIHBhZGRpbmcgKiAyLFxuICAgICAgaGVpZ2h0OiBub2RlLmhlaWdodCArIHBhZGRpbmcgKiAyLFxuICAgIH07XG4gIH1cblxuICBoaWRlQ29ubmVjdGlvblBvaW50cyhub2RlSWQ6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmIChcbiAgICAgIHRoaXMudmlzaWJsZUNvbm5lY3Rpb25Qb2ludHNOb2RlSWQgPT09IG5vZGVJZCAmJlxuICAgICAgIXRoaXMuc3RhdGUuaXNDb25uZWN0aW9uRHJhZ2dpbmcoKVxuICAgICkge1xuICAgICAgdGhpcy52aXNpYmxlQ29ubmVjdGlvblBvaW50c05vZGVJZCA9IG51bGw7XG4gICAgfVxuICB9XG5cbiAgaXNDb25uZWN0aW9uUG9pbnRWaXNpYmxlKG5vZGVJZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMudmlzaWJsZUNvbm5lY3Rpb25Qb2ludHNOb2RlSWQgPT09IG5vZGVJZDtcbiAgfVxuXG4gIHN0YXJ0Q29ubmVjdGlvbkRyYWcoXG4gICAgZXZlbnQ6IE1vdXNlRXZlbnQsXG4gICAgcG9pbnQ6IENvbm5lY3Rpb25Qb2ludCxcbiAgICBzd2ltbGFuZUluZGV4OiBudW1iZXJcbiAgKTogdm9pZCB7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYW4gZXhpdCBwb2ludCBub2RlXG4gICAgY29uc3Qgbm9kZUluZm8gPSB0aGlzLnN0YXRlLmZpbmROb2RlQnlJZChwb2ludC5ub2RlSWQpO1xuICAgIGlmIChcbiAgICAgIG5vZGVJbmZvICYmXG4gICAgICBub2RlSW5mby5ub2RlLnR5cGUgPT09ICdzdGFnZScgJiZcbiAgICAgIG5vZGVJbmZvLm5vZGUuc3RhZ2VEYXRhPy5Jc0V4aXRQb2ludFxuICAgICkge1xuICAgICAgLy8gRG9uJ3QgYWxsb3cgY29ubmVjdGlvbnMgZnJvbSBleGl0IHBvaW50c1xuICAgICAgY29uc29sZS5sb2coJ0Nhbm5vdCBjcmVhdGUgY29ubmVjdGlvbnMgZnJvbSBleGl0IHBvaW50cycpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IHBvc2l0aW9uID0gdGhpcy5nZXRNb3VzZVBvc2l0aW9uKGV2ZW50KTtcbiAgICB0aGlzLnN0YXRlLnN0YXJ0Q29ubmVjdGlvbkRyYWcoXG4gICAgICBwb2ludCxcbiAgICAgIHN3aW1sYW5lSW5kZXgsXG4gICAgICBwb3NpdGlvbi54LFxuICAgICAgcG9zaXRpb24ueVxuICAgICk7XG5cbiAgICAvLyBBZGQgbW91c2UgbW92ZSBhbmQgbW91c2UgdXAgZXZlbnQgbGlzdGVuZXJzIHRvIHRoZSBkb2N1bWVudFxuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMub25Nb3VzZU1vdmUpO1xuICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLm9uTW91c2VVcCk7XG4gIH1cblxuICAvLyBVc2UgYXJyb3cgZnVuY3Rpb25zIHRvIHByZXNlcnZlICd0aGlzJyBjb250ZXh0XG4gIG9uTW91c2VNb3ZlID0gKGV2ZW50OiBNb3VzZUV2ZW50KSA9PiB7XG4gICAgY29uc3QgcG9zaXRpb24gPSB0aGlzLmdldE1vdXNlUG9zaXRpb24oZXZlbnQpO1xuICAgIHRoaXMudXBkYXRlQ29ubmVjdGlvbkRyYWcocG9zaXRpb24ueCwgcG9zaXRpb24ueSk7XG4gIH07XG5cbiAgdXBkYXRlQ29ubmVjdGlvbkRyYWcoY3VycmVudFg6IG51bWJlciwgY3VycmVudFk6IG51bWJlcikge1xuICAgIGlmICh0aGlzLnN0YXRlLmRyYWdnaW5nQ29ubmVjdGlvbkRhdGEuc291cmNlUG9pbnQpIHtcbiAgICAgIHRoaXMuc3RhdGUuZHJhZ2dpbmdDb25uZWN0aW9uRGF0YS5jdXJyZW50WCA9IGN1cnJlbnRYO1xuICAgICAgdGhpcy5zdGF0ZS5kcmFnZ2luZ0Nvbm5lY3Rpb25EYXRhLmN1cnJlbnRZID0gY3VycmVudFk7XG5cbiAgICAgIC8vIENhbGN1bGF0ZSB3aGljaCBzd2ltbGFuZSB0aGUgY3Vyc29yIGlzIG92ZXJcbiAgICAgIGNvbnN0IHN3aW1sYW5lSW5kZXggPSBNYXRoLmZsb29yKGN1cnJlbnRZIC8gdGhpcy5zd2ltbGFuZUhlaWdodCk7XG4gICAgICBpZiAoc3dpbWxhbmVJbmRleCA+PSAwICYmIHN3aW1sYW5lSW5kZXggPCB0aGlzLnN0YXRlLnN3aW1sYW5lcy5sZW5ndGgpIHtcbiAgICAgICAgLy8gRW5zdXJlIHRoZSB0YXJnZXQgc3dpbWxhbmUgaXMgZnVsbHkgdmlzaWJsZVxuICAgICAgICB0aGlzLmVuc3VyZVN3aW1sYW5lSW5WaWV3KHN3aW1sYW5lSW5kZXgpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG9uTW91c2VVcCA9IChldmVudDogTW91c2VFdmVudCkgPT4ge1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbW92ZScsIHRoaXMub25Nb3VzZU1vdmUpO1xuICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB0aGlzLm9uTW91c2VVcCk7XG5cbiAgICBjb25zdCBwb3NpdGlvbiA9IHRoaXMuZ2V0TW91c2VQb3NpdGlvbihldmVudCk7XG4gICAgY29uc29sZS5sb2coJ01vdXNlIHVwIGF0IHBvc2l0aW9uOicsIHBvc2l0aW9uKTtcbiAgICBjb25zb2xlLmxvZygnSXMgY29ubmVjdGlvbiBkcmFnZ2luZzonLCB0aGlzLnN0YXRlLmlzQ29ubmVjdGlvbkRyYWdnaW5nKCkpO1xuXG4gICAgLy8gQ2hlY2sgaWYgdGhlIHBvc2l0aW9uIGlzIHdpdGhpbiBhbnkgc3dpbWxhbmVcbiAgICBjb25zdCBpc0luc2lkZVN3aW1sYW5lID0gdGhpcy5pc1Bvc2l0aW9uSW5zaWRlU3dpbWxhbmUocG9zaXRpb24ueSk7XG4gICAgY29uc29sZS5sb2coJ0lzIGluc2lkZSBzd2ltbGFuZTonLCBpc0luc2lkZVN3aW1sYW5lKTtcblxuICAgIC8vIE9ubHkgc2hvdyBwb3B1cCBpZiB3aXRoaW4gYSBzd2ltbGFuZVxuICAgIGlmIChpc0luc2lkZVN3aW1sYW5lICYmIHRoaXMuc3RhdGUuaXNDb25uZWN0aW9uRHJhZ2dpbmcoKSkge1xuICAgICAgY29uc29sZS5sb2coJ1Nob3dpbmcgY29ubmVjdGlvbiBwb3B1cCcpO1xuICAgICAgdGhpcy5zaG93Q29ubmVjdGlvblBvcHVwKHBvc2l0aW9uLngsIHBvc2l0aW9uLnkpO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBFbmQgdGhlIGNvbm5lY3Rpb24gZHJhZyBpZiBvdXRzaWRlIGEgc3dpbWxhbmVcbiAgICAgIGNvbnNvbGUubG9nKCdFbmRpbmcgY29ubmVjdGlvbiBkcmFnIHdpdGhvdXQgc2hvd2luZyBwb3B1cCcpO1xuICAgICAgdGhpcy5zdGF0ZS5lbmRDb25uZWN0aW9uRHJhZygpO1xuICAgIH1cbiAgfTtcblxuICBpc1Bvc2l0aW9uSW5zaWRlU3dpbWxhbmUoeTogbnVtYmVyKTogYm9vbGVhbiB7XG4gICAgLy8gQ2hlY2sgaWYgeSBwb3NpdGlvbiBpcyB3aXRoaW4gYW55IHN3aW1sYW5lXG4gICAgY29uc3Qgc3dpbWxhbmVDb3VudCA9IHRoaXMuc3RhdGUuc3dpbWxhbmVzLmxlbmd0aDtcbiAgICBpZiAoc3dpbWxhbmVDb3VudCA9PT0gMCkgcmV0dXJuIGZhbHNlO1xuXG4gICAgLy8gRWFjaCBzd2ltbGFuZSBoYXMgYSBoZWlnaHQgb2YgMjYzcHhcbiAgICBjb25zdCB0b3RhbFN3aW1sYW5lSGVpZ2h0ID0gc3dpbWxhbmVDb3VudCAqIHRoaXMuc3dpbWxhbmVIZWlnaHQ7XG5cbiAgICAvLyBDaGVjayBpZiB5IGlzIHdpdGhpbiB0aGUgdG90YWwgaGVpZ2h0IG9mIGFsbCBzd2ltbGFuZXNcbiAgICByZXR1cm4geSA+PSAwICYmIHkgPCB0b3RhbFN3aW1sYW5lSGVpZ2h0O1xuICB9XG5cbiAgc2hvd0Nvbm5lY3Rpb25Qb3B1cCh4OiBudW1iZXIsIHk6IG51bWJlcik6IHZvaWQge1xuICAgIGNvbnNvbGUubG9nKCdTaG93aW5nIGNvbm5lY3Rpb24gcG9wdXAgYXQ6JywgeCwgeSk7XG4gICAgdGhpcy5wb3B1cFggPSB4O1xuICAgIHRoaXMucG9wdXBZID0geTtcblxuICAgIC8vIEdldCBhbGxvd2VkIG5vZGUgdHlwZXMgYmFzZWQgb24gdGhlIHNvdXJjZSBub2RlIHR5cGVcbiAgICB0aGlzLmFsbG93ZWROb2RlVHlwZXMgPSB0aGlzLnN0YXRlLmdldEFsbG93ZWRUYXJnZXROb2RlVHlwZXMoKTtcbiAgICBjb25zb2xlLmxvZygnQWxsb3dlZCBub2RlIHR5cGVzOicsIHRoaXMuYWxsb3dlZE5vZGVUeXBlcyk7XG5cbiAgICAvLyBPbmx5IHNob3cgdGhlIHBvcHVwIGlmIHdlIGhhdmUgYWxsb3dlZCBub2RlIHR5cGVzXG4gICAgaWYgKHRoaXMuYWxsb3dlZE5vZGVUeXBlcy5sZW5ndGggPiAwKSB7XG4gICAgICB0aGlzLnBvcHVwVmlzaWJsZSA9IHRydWU7XG4gICAgICBjb25zb2xlLmxvZygnUG9wdXAgdmlzaWJpbGl0eSBzZXQgdG8gdHJ1ZScpO1xuXG4gICAgICAvLyBGb3JjZSB0aGUgcG9wdXAgdG8gYmUgdmlzaWJsZSBpbiB0aGUgbmV4dCB0aWNrXG4gICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgY29uc29sZS5sb2coJ0lzIHBvcHVwIHZpc2libGUgaW4gbmV4dCB0aWNrOicsIHRoaXMucG9wdXBWaXNpYmxlKTtcbiAgICAgIH0sIDApO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyBObyBhbGxvd2VkIG5vZGUgdHlwZXMsIGp1c3QgZW5kIHRoZSBkcmFnXG4gICAgICBjb25zb2xlLmxvZygnTm8gYWxsb3dlZCBub2RlIHR5cGVzLCBlbmRpbmcgZHJhZycpO1xuICAgICAgdGhpcy5zdGF0ZS5lbmRDb25uZWN0aW9uRHJhZygpO1xuICAgIH1cbiAgfVxuXG4gIGhpZGVDb25uZWN0aW9uUG9wdXAoKTogdm9pZCB7XG4gICAgdGhpcy5wb3B1cFZpc2libGUgPSBmYWxzZTtcbiAgICB0aGlzLnN0YXRlLmVuZENvbm5lY3Rpb25EcmFnKCk7XG4gIH1cblxuICAvLyBBZGQgdGhpcyBoYW5kbGVyIHRvIGNsb3NlIHRoZSBwb3B1cCB3aGVuIGNsaWNraW5nIG91dHNpZGVcbiAgQEhvc3RMaXN0ZW5lcignZG9jdW1lbnQ6Y2xpY2snLCBbJyRldmVudCddKVxuICBvbkRvY3VtZW50Q2xpY2soZXZlbnQ6IE1vdXNlRXZlbnQpOiB2b2lkIHtcbiAgICBpZiAodGhpcy5wb3B1cFZpc2libGUpIHtcbiAgICAgIGNvbnN0IHBvcHVwRWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoJ3ZlcmJlbi1wb3AtVXAnKTtcbiAgICAgIGlmIChwb3B1cEVsZW1lbnQgJiYgIXBvcHVwRWxlbWVudC5jb250YWlucyhldmVudC50YXJnZXQgYXMgTm9kZSkpIHtcbiAgICAgICAgdGhpcy5oaWRlQ29ubmVjdGlvblBvcHVwKCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgY3JlYXRlTm9kZUNvbm5lY3Rpb24obm9kZVR5cGU6IHN0cmluZyk6IHZvaWQge1xuICAgIGNvbnN0IHBhdGhEYXRhID0gdGhpcy5zdGF0ZS5nZXRDb25uZWN0aW9uUGF0aERhdGEoKTtcbiAgICBpZiAoIXBhdGhEYXRhKSB7XG4gICAgICB0aGlzLmhpZGVDb25uZWN0aW9uUG9wdXAoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBDaGVjayBpZiB0aGlzIG5vZGUgdHlwZSBpcyBhbGxvd2VkIHRvIGJlIGNyZWF0ZWRcbiAgICBjb25zdCBhbGxvd2VkVHlwZXMgPSB0aGlzLnN0YXRlLmdldEFsbG93ZWRUYXJnZXROb2RlVHlwZXMoKTtcbiAgICBpZiAoIWFsbG93ZWRUeXBlcy5pbmNsdWRlcyhub2RlVHlwZSkpIHtcbiAgICAgIGNvbnNvbGUuZXJyb3IoXG4gICAgICAgIGBDYW5ub3QgY3JlYXRlIGNvbm5lY3Rpb24gdG8gJHtub2RlVHlwZX0gZnJvbSBjdXJyZW50IG5vZGUgdHlwZWBcbiAgICAgICk7XG4gICAgICB0aGlzLmhpZGVDb25uZWN0aW9uUG9wdXAoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB7IGVuZFgsIGVuZFksIHNvdXJjZVN3aW1sYW5lSW5kZXggfSA9IHBhdGhEYXRhO1xuXG4gICAgLy8gR2V0IHNvdXJjZSBub2RlIGluZm9cbiAgICBjb25zdCBzb3VyY2VQb2ludCA9IHRoaXMuc3RhdGUuZHJhZ2dpbmdDb25uZWN0aW9uRGF0YS5zb3VyY2VQb2ludDtcbiAgICBpZiAoIXNvdXJjZVBvaW50KSB7XG4gICAgICB0aGlzLmhpZGVDb25uZWN0aW9uUG9wdXAoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCBzb3VyY2VOb2RlSW5mbyA9IHRoaXMuc3RhdGUuZmluZE5vZGVCeUlkKHNvdXJjZVBvaW50Lm5vZGVJZCk7XG4gICAgaWYgKCFzb3VyY2VOb2RlSW5mbykge1xuICAgICAgdGhpcy5oaWRlQ29ubmVjdGlvblBvcHVwKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gSWYgY29ubmVjdGluZyBmcm9tIGEgZGVjaXNpb24gdG8gYSBzdGFnZSwgc2hvdyBjb25kaXRpb24gcG9wdXAgZmlyc3RcbiAgICBpZiAoc291cmNlTm9kZUluZm8ubm9kZS50eXBlID09PSAnZGVjaXNpb24nICYmIG5vZGVUeXBlID09PSAnc3RhZ2UnKSB7XG4gICAgICAvLyBTdG9yZSBpbmZvcm1hdGlvbiBmb3IgbGF0ZXIgc3RhZ2UgY3JlYXRpb25cbiAgICAgIHRoaXMucGVuZGluZ0RlY2lzaW9uQ29ubmVjdGlvbiA9IHtcbiAgICAgICAgZGVjaXNpb25Ob2RlSWQ6IHNvdXJjZU5vZGVJbmZvLm5vZGUuaWQsXG4gICAgICAgIHN3aW1sYW5lSW5kZXg6IHNvdXJjZVN3aW1sYW5lSW5kZXgsXG4gICAgICAgIHg6IGVuZFgsXG4gICAgICAgIHk6IGVuZFksXG4gICAgICB9O1xuXG4gICAgICAvLyBDYWxjdWxhdGUgcG9wdXAgcG9zaXRpb24gLSBwb3NpdGlvbiBpdCBuZWFyIHRoZSBkZWNpc2lvbiBub2RlXG4gICAgICBjb25zdCBzd2ltbGFuZU9mZnNldFkgPSBzb3VyY2VTd2ltbGFuZUluZGV4ICogMjYzICsgNDA7XG5cbiAgICAgIC8vIENlbnRlciB0aGUgcG9wdXAgb3ZlciB0aGUgY29ubmVjdGlvbiBlbmRwb2ludFxuICAgICAgdGhpcy5kZWNpc2lvbkNvbmRpdGlvblBvcHVwWCA9IGVuZFg7XG4gICAgICB0aGlzLmRlY2lzaW9uQ29uZGl0aW9uUG9wdXBZID0gZW5kWSAtIDE1MDsgLy8gUG9zaXRpb24gYWJvdmUgdGhlIGVuZHBvaW50XG5cbiAgICAgIC8vIFNldCBkZWNpc2lvbiBub2RlIElEXG4gICAgICB0aGlzLmFjdGl2ZURlY2lzaW9uTm9kZUlkID0gc291cmNlTm9kZUluZm8ubm9kZS5pZDtcbiAgICAgIHRoaXMuc2hvd0RlY2lzaW9uQ29uZGl0aW9uRGlhbG9nID0gdHJ1ZTtcblxuICAgICAgLy8gRW5kIHRoZSBjb25uZWN0aW9uIGRyYWdcbiAgICAgIHRoaXMuaGlkZUNvbm5lY3Rpb25Qb3B1cCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENhbGN1bGF0ZSBzd2ltbGFuZS1yZWxhdGl2ZSBwb3NpdGlvblxuICAgIGNvbnN0IHN3aW1sYW5lT2Zmc2V0WSA9IHNvdXJjZVN3aW1sYW5lSW5kZXggKiAyNjMgKyA0MDtcbiAgICBjb25zdCByZWxhdGl2ZVkgPSBlbmRZIC0gc3dpbWxhbmVPZmZzZXRZO1xuXG4gICAgLy8gSGFuZGxlIHByZWNvbmRpdGlvbnMgYmFzZWQgb24gbm9kZSB0eXBlXG4gICAgaWYgKG5vZGVUeXBlID09PSAnc3RhZ2UnKSB7XG4gICAgICAvLyBDcmVhdGUgdGhlIHN0YWdlIGRpcmVjdGx5IHdpdGggZGVmYXVsdCBwcm9wZXJ0aWVzXG4gICAgICBjb25zdCBuZXdOb2RlID0gdGhpcy5zdGF0ZS5hZGROb2RlKFxuICAgICAgICBzb3VyY2VTd2ltbGFuZUluZGV4LFxuICAgICAgICAnc3RhZ2UnLFxuICAgICAgICBlbmRYLFxuICAgICAgICByZWxhdGl2ZVksXG4gICAgICAgIHsgTmFtZTogJ05ldyBTdGFnZScgfSAvLyBBZGQgZGVmYXVsdCBwcm9wZXJ0aWVzXG4gICAgICApO1xuXG4gICAgICBpZiAoXG4gICAgICAgIG5ld05vZGUgJiZcbiAgICAgICAgbmV3Tm9kZS5jb25uZWN0aW9uUG9pbnRzICYmXG4gICAgICAgIG5ld05vZGUuY29ubmVjdGlvblBvaW50cy5sZW5ndGggPiAwICYmXG4gICAgICAgIHNvdXJjZVBvaW50XG4gICAgICApIHtcbiAgICAgICAgLy8gSGFuZGxlIGNvbm5lY3Rpb24gY3JlYXRpb25cbiAgICAgICAgY29uc3Qgb3Bwb3NpbmdUeXBlID0ge1xuICAgICAgICAgIHJpZ2h0OiAnbGVmdCcsXG4gICAgICAgICAgbGVmdDogJ3JpZ2h0JyxcbiAgICAgICAgICB0b3A6ICdib3R0b20nLFxuICAgICAgICAgIGJvdHRvbTogJ3RvcCcsXG4gICAgICAgIH1bc291cmNlUG9pbnQudHlwZV0gYXMgJ3RvcCcgfCAncmlnaHQnIHwgJ2JvdHRvbScgfCAnbGVmdCc7XG5cbiAgICAgICAgY29uc3QgdGFyZ2V0UG9pbnQgPSBuZXdOb2RlLmNvbm5lY3Rpb25Qb2ludHMuZmluZChcbiAgICAgICAgICAocCkgPT4gcC50eXBlID09PSBvcHBvc2luZ1R5cGVcbiAgICAgICAgKTtcblxuICAgICAgICBpZiAodGFyZ2V0UG9pbnQpIHtcbiAgICAgICAgICAvLyBDcmVhdGUgdGhlIGNvbm5lY3Rpb25cbiAgICAgICAgICBjb25zdCBjb25uZWN0aW9uID0gdGhpcy5zdGF0ZS5jcmVhdGVDb25uZWN0aW9uKFxuICAgICAgICAgICAgbmV3Tm9kZS5pZCxcbiAgICAgICAgICAgIHRhcmdldFBvaW50LmlkLFxuICAgICAgICAgICAgc291cmNlU3dpbWxhbmVJbmRleFxuICAgICAgICAgICk7XG5cbiAgICAgICAgICBpZiAoY29ubmVjdGlvbikge1xuICAgICAgICAgICAgdGhpcy5vbkNvbm5lY3Rpb25DcmVhdGVkKGNvbm5lY3Rpb24pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICB0aGlzLmhpZGVDb25uZWN0aW9uUG9wdXAoKTtcbiAgICAgIHJldHVybjtcbiAgICB9IGVsc2UgaWYgKG5vZGVUeXBlID09PSAnc3ViZmxvdycpIHtcbiAgICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAnQ3JlYXRpbmcgc3ViZmxvdyBmcm9tIGNvbm5lY3Rpb24gYXQ6JyxcbiAgICAgICAgZW5kWCxcbiAgICAgICAgZW5kWSxcbiAgICAgICAgJ3N3aW1sYW5lOicsXG4gICAgICAgIHNvdXJjZVN3aW1sYW5lSW5kZXhcbiAgICAgICk7XG4gICAgICAvLyBTaG93IHdvcmtmbG93IHNlbGVjdGlvbiBwb3B1cCBhbmQgc3RvcmUgY29ubmVjdGlvbiBkYXRhIGZvciBsYXRlciB1c2VcbiAgICAgIHRoaXMuc2hvd1N1YmZsb3dTZWxlY3Rpb25Qb3B1cChlbmRYLCBlbmRZLCBzb3VyY2VTd2ltbGFuZUluZGV4KTtcbiAgICAgIHRoaXMuaGlkZUNvbm5lY3Rpb25Qb3B1cCgpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIEZvciBvdGhlciBub2RlcyBDcmVhdGUgdGhlIG5ldyBub2RlIGF0IHRoZSBlbmQgcG9zaXRpb24gb2YgdGhlIGNvbm5lY3Rpb25cbiAgICBjb25zdCBuZXdOb2RlID0gdGhpcy5zdGF0ZS5hZGROb2RlKFxuICAgICAgc291cmNlU3dpbWxhbmVJbmRleCxcbiAgICAgIG5vZGVUeXBlIGFzIFRvb2xUeXBlLFxuICAgICAgZW5kWCxcbiAgICAgIHJlbGF0aXZlWVxuICAgICk7XG5cbiAgICBpZiAoXG4gICAgICBuZXdOb2RlICYmXG4gICAgICBuZXdOb2RlLmNvbm5lY3Rpb25Qb2ludHMgJiZcbiAgICAgIG5ld05vZGUuY29ubmVjdGlvblBvaW50cy5sZW5ndGggPiAwXG4gICAgKSB7XG4gICAgICAvLyBGaW5kIHRoZSBtb3N0IGFwcHJvcHJpYXRlIGNvbm5lY3Rpb24gcG9pbnQgKGNsb3Nlc3QgdG8gdGhlIHNvdXJjZSlcbiAgICAgIGlmIChzb3VyY2VQb2ludCkge1xuICAgICAgICAvLyBGb3Igc2ltcGxpY2l0eSwgdXNlIHRoZSBmaXJzdCBjb25uZWN0aW9uIHBvaW50IG9mIG9wcG9zaW5nIHR5cGVcbiAgICAgICAgLy8gSW4gYSByZWFsIGltcGxlbWVudGF0aW9uLCB5b3UnZCBmaW5kIHRoZSBjbG9zZXN0IG9yIG1vc3QgYXBwcm9wcmlhdGUgcG9pbnRcbiAgICAgICAgbGV0IHRhcmdldFBvaW50O1xuXG4gICAgICAgIC8vIElmIHNvdXJjZSBpcyBvbiByaWdodCwgdGFyZ2V0IHNob3VsZCBiZSBvbiBsZWZ0LCBldGMuXG4gICAgICAgIGNvbnN0IG9wcG9zaW5nVHlwZSA9IHtcbiAgICAgICAgICByaWdodDogJ2xlZnQnLFxuICAgICAgICAgIGxlZnQ6ICdyaWdodCcsXG4gICAgICAgICAgdG9wOiAnYm90dG9tJyxcbiAgICAgICAgICBib3R0b206ICd0b3AnLFxuICAgICAgICB9W3NvdXJjZVBvaW50LnR5cGVdIGFzICd0b3AnIHwgJ3JpZ2h0JyB8ICdib3R0b20nIHwgJ2xlZnQnO1xuXG4gICAgICAgIHRhcmdldFBvaW50ID0gbmV3Tm9kZS5jb25uZWN0aW9uUG9pbnRzLmZpbmQoXG4gICAgICAgICAgKHApID0+IHAudHlwZSA9PT0gb3Bwb3NpbmdUeXBlXG4gICAgICAgICk7XG5cbiAgICAgICAgaWYgKHRhcmdldFBvaW50KSB7XG4gICAgICAgICAgLy8gQ3JlYXRlIHRoZSBjb25uZWN0aW9uXG4gICAgICAgICAgY29uc3QgY29ubmVjdGlvbiA9IHRoaXMuc3RhdGUuY3JlYXRlQ29ubmVjdGlvbihcbiAgICAgICAgICAgIG5ld05vZGUuaWQsXG4gICAgICAgICAgICB0YXJnZXRQb2ludC5pZCxcbiAgICAgICAgICAgIHNvdXJjZVN3aW1sYW5lSW5kZXhcbiAgICAgICAgICApO1xuXG4gICAgICAgICAgaWYgKGNvbm5lY3Rpb24pIHtcbiAgICAgICAgICAgIHRoaXMub25Db25uZWN0aW9uQ3JlYXRlZChjb25uZWN0aW9uKTtcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoc291cmNlTm9kZUluZm8pIHtcbiAgICAgIHRoaXMudXBkYXRlTm9kZUNvbm5lY3Rpb25zKHNvdXJjZU5vZGVJbmZvLm5vZGUpO1xuICAgIH1cblxuICAgIC8vIEVuZCB0aGUgY29ubmVjdGlvbiBkcmFnXG4gICAgdGhpcy5oaWRlQ29ubmVjdGlvblBvcHVwKCk7XG4gIH1cblxuICAvLyBNZXRob2QgdG8gaGFuZGxlIHNhdmluZyB0aGUgY29uZGl0aW9uXG4gIG9uRGVjaXNpb25Db25kaXRpb25TYXZlZChldmVudDoge1xuICAgIGNvbm5lY3Rpb25JZDogc3RyaW5nO1xuICAgIGNvbmRpdGlvbjogc3RyaW5nO1xuICB9KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnBlbmRpbmdEZWNpc2lvbkNvbm5lY3Rpb24pIHtcbiAgICAgIHRoaXMuc2hvd0RlY2lzaW9uQ29uZGl0aW9uRGlhbG9nID0gZmFsc2U7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgeyBkZWNpc2lvbk5vZGVJZCwgc3dpbWxhbmVJbmRleCwgeCwgeSB9ID1cbiAgICAgIHRoaXMucGVuZGluZ0RlY2lzaW9uQ29ubmVjdGlvbjtcblxuICAgIC8vIENyZWF0ZSB0aGUgc3RhZ2UgZGlyZWN0bHkgd2l0aCBkZWZhdWx0IHByb3BlcnRpZXNcbiAgICBjb25zdCBub2RlID0gdGhpcy5zdGF0ZS5hZGROb2RlKFxuICAgICAgc3dpbWxhbmVJbmRleCxcbiAgICAgICdzdGFnZScsXG4gICAgICB4LFxuICAgICAgeSxcbiAgICAgIHsgTmFtZTogJ05ldyBTdGFnZScgfSAvLyBBZGQgZGVmYXVsdCBwcm9wZXJ0aWVzXG4gICAgKTtcblxuICAgIGlmIChub2RlKSB7XG4gICAgICBjb25zdCBkZWNpc2lvbk5vZGVJbmZvID0gdGhpcy5zdGF0ZS5maW5kTm9kZUJ5SWQoZGVjaXNpb25Ob2RlSWQpO1xuXG4gICAgICBpZiAoXG4gICAgICAgIGRlY2lzaW9uTm9kZUluZm8gJiZcbiAgICAgICAgbm9kZS5jb25uZWN0aW9uUG9pbnRzICYmXG4gICAgICAgIG5vZGUuY29ubmVjdGlvblBvaW50cy5sZW5ndGggPiAwXG4gICAgICApIHtcbiAgICAgICAgLy8gRmluZCBhIHN1aXRhYmxlIGNvbm5lY3Rpb24gcG9pbnQgZnJvbSB0aGUgZGVjaXNpb24gbm9kZVxuICAgICAgICBjb25zdCBkZWNpc2lvbk5vZGUgPSBkZWNpc2lvbk5vZGVJbmZvLm5vZGU7XG4gICAgICAgIGNvbnN0IGRlY2lzaW9uTm9kZVBvaW50cyA9IGRlY2lzaW9uTm9kZS5jb25uZWN0aW9uUG9pbnRzIHx8IFtdO1xuICAgICAgICBjb25zdCBzb3VyY2VQb2ludCA9IGRlY2lzaW9uTm9kZVBvaW50cy5maW5kKFxuICAgICAgICAgIChwKSA9PiBwLnR5cGUgPT09ICdyaWdodCcgfHwgcC50eXBlID09PSAnYm90dG9tJ1xuICAgICAgICApO1xuXG4gICAgICAgIGlmIChzb3VyY2VQb2ludCkge1xuICAgICAgICAgIC8vIEZpbmQgb3Bwb3NpbmcgdHlwZSBjb25uZWN0aW9uIHBvaW50IG9uIHRoZSBuZXcgc3RhZ2VcbiAgICAgICAgICBjb25zdCBvcHBvc2luZ1R5cGUgPSB7XG4gICAgICAgICAgICByaWdodDogJ2xlZnQnLFxuICAgICAgICAgICAgYm90dG9tOiAndG9wJyxcbiAgICAgICAgICAgIGxlZnQ6ICdyaWdodCcsXG4gICAgICAgICAgICB0b3A6ICdib3R0b20nLFxuICAgICAgICAgIH1bc291cmNlUG9pbnQudHlwZV0gYXMgJ3RvcCcgfCAncmlnaHQnIHwgJ2JvdHRvbScgfCAnbGVmdCc7XG5cbiAgICAgICAgICBjb25zdCB0YXJnZXRQb2ludCA9IG5vZGUuY29ubmVjdGlvblBvaW50cy5maW5kKFxuICAgICAgICAgICAgKHApID0+IHAudHlwZSA9PT0gb3Bwb3NpbmdUeXBlXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGlmICh0YXJnZXRQb2ludCkge1xuICAgICAgICAgICAgLy8gQ3JlYXRlIGNvbm5lY3Rpb24gd2l0aCBjb25kaXRpb25cbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB7XG4gICAgICAgICAgICAgIGlkOiBgY29ubi0ke0RhdGUubm93KCl9LSR7TWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMTAwMCl9YCxcbiAgICAgICAgICAgICAgc291cmNlTm9kZUlkOiBkZWNpc2lvbk5vZGUuaWQsXG4gICAgICAgICAgICAgIHRhcmdldE5vZGVJZDogbm9kZS5pZCxcbiAgICAgICAgICAgICAgc291cmNlUG9pbnRJZDogc291cmNlUG9pbnQuaWQsXG4gICAgICAgICAgICAgIHRhcmdldFBvaW50SWQ6IHRhcmdldFBvaW50LmlkLFxuICAgICAgICAgICAgICBzb3VyY2VTd2ltbGFuZUluZGV4OiBkZWNpc2lvbk5vZGVJbmZvLnN3aW1sYW5lSW5kZXgsXG4gICAgICAgICAgICAgIHRhcmdldFN3aW1sYW5lSW5kZXg6IHN3aW1sYW5lSW5kZXgsXG4gICAgICAgICAgICAgIGNvbmRpdGlvbjogZXZlbnQuY29uZGl0aW9uLFxuICAgICAgICAgICAgfTtcblxuICAgICAgICAgICAgLy8gQWRkIGNvbm5lY3Rpb24gdG8gdGhlIHN0YXRlXG4gICAgICAgICAgICB0aGlzLnN0YXRlLmNvbm5lY3Rpb25zLnB1c2goY29ubmVjdGlvbik7XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhcbiAgICAgICAgICAgICAgJ0NyZWF0ZWQgZGVjaXNpb24gY29ubmVjdGlvbiB3aXRoIGNvbmRpdGlvbjonLFxuICAgICAgICAgICAgICBjb25uZWN0aW9uXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIENsZWFyIHBlbmRpbmcgZGF0YVxuICAgIHRoaXMucGVuZGluZ0RlY2lzaW9uQ29ubmVjdGlvbiA9IG51bGw7XG4gICAgdGhpcy5wZW5kaW5nRGVjaXNpb25Db25kaXRpb24gPSAnJztcblxuICAgIC8vIEhpZGUgdGhlIGNvbmRpdGlvbiBwb3B1cFxuICAgIHRoaXMuc2hvd0RlY2lzaW9uQ29uZGl0aW9uRGlhbG9nID0gZmFsc2U7XG4gIH1cblxuICBvbkRlY2lzaW9uQ29uZGl0aW9uQ2FuY2VsbGVkKCk6IHZvaWQge1xuICAgIHRoaXMuc2hvd0RlY2lzaW9uQ29uZGl0aW9uRGlhbG9nID0gZmFsc2U7XG4gICAgLy8gRG9uJ3QgY3JlYXRlIHRoZSBzdGFnZSBvciBjb25uZWN0aW9uXG4gIH1cblxuICBnZXRDb25uZWN0aW9uUGF0aCgpOiBzdHJpbmcge1xuICAgIGNvbnN0IHBhdGhEYXRhID0gdGhpcy5zdGF0ZS5nZXRDb25uZWN0aW9uUGF0aERhdGEoKTtcbiAgICBpZiAoIXBhdGhEYXRhKSByZXR1cm4gJyc7XG5cbiAgICBjb25zdCB7IHN0YXJ0WCwgc3RhcnRZLCBlbmRYLCBlbmRZIH0gPSBwYXRoRGF0YTtcbiAgICBjb25zdCBzb3VyY2VQb2ludCA9IHRoaXMuc3RhdGUuZHJhZ2dpbmdDb25uZWN0aW9uRGF0YS5zb3VyY2VQb2ludDtcblxuICAgIGlmICghc291cmNlUG9pbnQpIHJldHVybiAnJztcblxuICAgIHJldHVybiB0aGlzLmdldE9ydGhvZ29uYWxQYXRoKHN0YXJ0WCwgc3RhcnRZLCBlbmRYLCBlbmRZLCBzb3VyY2VQb2ludC50eXBlKTtcbiAgfVxuXG4gIGdldENvbm5lY3Rpb25QYXRoRm9yU2F2ZWRDb25uZWN0aW9uKGNvbm5lY3Rpb246IENvbm5lY3Rpb24pOiBzdHJpbmcge1xuICAgIHRyeSB7XG4gICAgICBjb25zdCBwYXRoRGF0YSA9IHRoaXMuc3RhdGUuZ2V0Q29ubmVjdGlvbkRhdGEoY29ubmVjdGlvbik7XG4gICAgICBpZiAoIXBhdGhEYXRhKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ05vIHBhdGggZGF0YSBmb3IgY29ubmVjdGlvbjonLCBjb25uZWN0aW9uKTtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgICAgfVxuXG4gICAgICBjb25zdCB7IHN0YXJ0WCwgc3RhcnRZLCBlbmRYLCBlbmRZIH0gPSBwYXRoRGF0YTtcblxuICAgICAgY29uc3Qgc291cmNlTm9kZUluZm8gPSB0aGlzLnN0YXRlLmZpbmROb2RlQnlJZChjb25uZWN0aW9uLnNvdXJjZU5vZGVJZCk7XG4gICAgICBpZiAoIXNvdXJjZU5vZGVJbmZvKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ1NvdXJjZSBub2RlIG5vdCBmb3VuZCBmb3IgY29ubmVjdGlvbjonLCBjb25uZWN0aW9uKTtcbiAgICAgICAgcmV0dXJuICcnO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzb3VyY2VOb2RlID0gc291cmNlTm9kZUluZm8ubm9kZTtcbiAgICAgIGNvbnN0IHNvdXJjZVBvaW50ID0gc291cmNlTm9kZS5jb25uZWN0aW9uUG9pbnRzPy5maW5kKFxuICAgICAgICAocCkgPT4gcC5pZCA9PT0gY29ubmVjdGlvbi5zb3VyY2VQb2ludElkXG4gICAgICApO1xuXG4gICAgICBpZiAoIXNvdXJjZVBvaW50KSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoJ1NvdXJjZSBwb2ludCBub3QgZm91bmQgZm9yIGNvbm5lY3Rpb246JywgY29ubmVjdGlvbik7XG4gICAgICAgIHJldHVybiAnJztcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRoaXMuZ2V0T3J0aG9nb25hbFBhdGgoXG4gICAgICAgIHN0YXJ0WCxcbiAgICAgICAgc3RhcnRZLFxuICAgICAgICBlbmRYLFxuICAgICAgICBlbmRZLFxuICAgICAgICBzb3VyY2VQb2ludC50eXBlXG4gICAgICApO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBnZW5lcmF0aW5nIHBhdGggZm9yIGNvbm5lY3Rpb246JywgY29ubmVjdGlvbiwgZXJyb3IpO1xuICAgICAgcmV0dXJuICcnO1xuICAgIH1cbiAgfVxuXG4gIGdldE9ydGhvZ29uYWxQYXRoKFxuICAgIHN0YXJ0WDogbnVtYmVyLFxuICAgIHN0YXJ0WTogbnVtYmVyLFxuICAgIGVuZFg6IG51bWJlcixcbiAgICBlbmRZOiBudW1iZXIsXG4gICAgcG9pbnRUeXBlOiAndG9wJyB8ICdyaWdodCcgfCAnYm90dG9tJyB8ICdsZWZ0J1xuICApOiBzdHJpbmcge1xuICAgIC8vIERldGVybWluZSBpbml0aWFsIGRpcmVjdGlvbiBiYXNlZCBvbiBjb25uZWN0aW9uIHBvaW50IHR5cGVcbiAgICBsZXQgcGF0aCA9ICcnO1xuXG4gICAgLy8gRm9yIHNpZGUgcG9pbnRzIChsZWZ0L3JpZ2h0KSwgc3RhcnQgd2l0aCBob3Jpem9udGFsIGxpbmVcbiAgICBpZiAocG9pbnRUeXBlID09PSAnbGVmdCcgfHwgcG9pbnRUeXBlID09PSAncmlnaHQnKSB7XG4gICAgICAvLyBDYWxjdWxhdGUgaG9yaXpvbnRhbCBkaXN0YW5jZVxuICAgICAgY29uc3QgaG9yaXpvbnRhbERpc3QgPSBlbmRYIC0gc3RhcnRYO1xuXG4gICAgICAvLyBJZiB0aGUgZW5kIHBvaW50IGlzIHZlcnkgY2xvc2UgaG9yaXpvbnRhbGx5LCB1c2UgYSBzaW1wbGUgMy1zZWdtZW50IHBhdGhcbiAgICAgIGlmIChNYXRoLmFicyhob3Jpem9udGFsRGlzdCkgPCAzMCkge1xuICAgICAgICBjb25zdCBtaWRZID0gKHN0YXJ0WSArIGVuZFkpIC8gMjtcbiAgICAgICAgcGF0aCA9IGBNICR7c3RhcnRYfSAke3N0YXJ0WX0gSCAke2VuZFh9IFYgJHttaWRZfSBWICR7ZW5kWX1gO1xuICAgICAgfVxuICAgICAgLy8gT3RoZXJ3aXNlLCBjcmVhdGUgYSBwYXRoIHdpdGggaG9yaXpvbnRhbCBzZWdtZW50IGZpcnN0LCB0aGVuIHZlcnRpY2FsLCB0aGVuIGhvcml6b250YWxcbiAgICAgIGVsc2Uge1xuICAgICAgICBwYXRoID0gYE0gJHtzdGFydFh9ICR7c3RhcnRZfSBIICR7XG4gICAgICAgICAgc3RhcnRYICsgaG9yaXpvbnRhbERpc3QgLyAyXG4gICAgICAgIH0gViAke2VuZFl9IEggJHtlbmRYfWA7XG4gICAgICB9XG4gICAgfVxuICAgIC8vIEZvciB0b3AvYm90dG9tIHBvaW50cywgc3RhcnQgd2l0aCB2ZXJ0aWNhbCBsaW5lXG4gICAgZWxzZSBpZiAocG9pbnRUeXBlID09PSAndG9wJyB8fCBwb2ludFR5cGUgPT09ICdib3R0b20nKSB7XG4gICAgICAvLyBDYWxjdWxhdGUgdmVydGljYWwgZGlzdGFuY2VcbiAgICAgIGNvbnN0IHZlcnRpY2FsRGlzdCA9IGVuZFkgLSBzdGFydFk7XG5cbiAgICAgIC8vIElmIHRoZSBlbmQgcG9pbnQgaXMgdmVyeSBjbG9zZSB2ZXJ0aWNhbGx5LCB1c2UgYSBzaW1wbGUgMy1zZWdtZW50IHBhdGhcbiAgICAgIGlmIChNYXRoLmFicyh2ZXJ0aWNhbERpc3QpIDwgMzApIHtcbiAgICAgICAgY29uc3QgbWlkWCA9IChzdGFydFggKyBlbmRYKSAvIDI7XG4gICAgICAgIHBhdGggPSBgTSAke3N0YXJ0WH0gJHtzdGFydFl9IFYgJHtlbmRZfSBIICR7bWlkWH0gSCAke2VuZFh9YDtcbiAgICAgIH1cbiAgICAgIC8vIE90aGVyd2lzZSwgY3JlYXRlIGEgcGF0aCB3aXRoIHZlcnRpY2FsIHNlZ21lbnQgZmlyc3QsIHRoZW4gaG9yaXpvbnRhbCwgdGhlbiB2ZXJ0aWNhbFxuICAgICAgZWxzZSB7XG4gICAgICAgIHBhdGggPSBgTSAke3N0YXJ0WH0gJHtzdGFydFl9IFYgJHtcbiAgICAgICAgICBzdGFydFkgKyB2ZXJ0aWNhbERpc3QgLyAyXG4gICAgICAgIH0gSCAke2VuZFh9IFYgJHtlbmRZfWA7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHBhdGg7XG4gIH1cblxuICBvblN0YWdlUHJvcGVydGllc1VwZGF0ZWQoZXZlbnQ6IHtcbiAgICBub2RlSWQ6IHN0cmluZztcbiAgICBzdGFnZURhdGE6IFBhcnRpYWw8V29ya2Zsb3dTdGFnZT47XG4gIH0pOiB2b2lkIHtcbiAgICAvLyBGaW5kIHRoZSBub2RlIGluIHRoZSBzd2ltbGFuZXNcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuc3RhdGUuc3dpbWxhbmVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBzd2ltbGFuZSA9IHRoaXMuc3RhdGUuc3dpbWxhbmVzW2ldO1xuICAgICAgY29uc3Qgbm9kZUluZGV4ID0gc3dpbWxhbmUubm9kZXM/LmZpbmRJbmRleCgobikgPT4gbi5pZCA9PT0gZXZlbnQubm9kZUlkKTtcblxuICAgICAgaWYgKG5vZGVJbmRleCAhPT0gdW5kZWZpbmVkICYmIG5vZGVJbmRleCA+PSAwKSB7XG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgc3RhZ2UgZGF0YVxuICAgICAgICBpZiAoc3dpbWxhbmUubm9kZXMpIHtcbiAgICAgICAgICBzd2ltbGFuZS5ub2Rlc1tub2RlSW5kZXhdLnN0YWdlRGF0YSA9IHtcbiAgICAgICAgICAgIC4uLnN3aW1sYW5lLm5vZGVzW25vZGVJbmRleF0uc3RhZ2VEYXRhLFxuICAgICAgICAgICAgLi4uZXZlbnQuc3RhZ2VEYXRhLFxuICAgICAgICAgIH07XG4gICAgICAgICAgY29uc29sZS5sb2coXG4gICAgICAgICAgICAnVXBkYXRlZCBzdGFnZSBkYXRhIGluIHN3aW1sYW5lOicsXG4gICAgICAgICAgICBpLFxuICAgICAgICAgICAgJ25vZGU6JyxcbiAgICAgICAgICAgIG5vZGVJbmRleCxcbiAgICAgICAgICAgICdkYXRhOicsXG4gICAgICAgICAgICBzd2ltbGFuZS5ub2Rlc1tub2RlSW5kZXhdLnN0YWdlRGF0YVxuICAgICAgICAgICk7XG4gICAgICAgIH1cbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgb25Db25uZWN0aW9uQ3JlYXRlZChjb25uZWN0aW9uOiBDb25uZWN0aW9uKTogdm9pZCB7XG4gICAgLy8gQWZ0ZXIgYSBjb25uZWN0aW9uIGlzIGNyZWF0ZWQsIHJlZnJlc2ggdGhlIHNvdXJjZSBub2RlIHRvIHVwZGF0ZSBpdHMgc3RhdGVcbiAgICBjb25zdCBzb3VyY2VOb2RlSW5mbyA9IHRoaXMuc3RhdGUuZmluZE5vZGVCeUlkKGNvbm5lY3Rpb24uc291cmNlTm9kZUlkKTtcbiAgICBpZiAoc291cmNlTm9kZUluZm8gJiYgc291cmNlTm9kZUluZm8ubm9kZS50eXBlID09PSAnc3RhZ2UnKSB7XG4gICAgICAvLyBSZWZyZXNoIG5vZGUgc3RhdGVcbiAgICAgIHRoaXMudXBkYXRlTm9kZUNvbm5lY3Rpb25zKHNvdXJjZU5vZGVJbmZvLm5vZGUpO1xuICAgIH1cbiAgfVxuXG4gIC8vIEhlbHBlciBtZXRob2QgdG8gdXBkYXRlIG5vZGUncyBjb25uZWN0aW9uIHN0YXR1c1xuICB1cGRhdGVOb2RlQ29ubmVjdGlvbnMobm9kZTogV0ZOb2RlKTogdm9pZCB7XG4gICAgLy8gQ291bnQgdGhlIG51bWJlciBvZiBvdXRnb2luZyBjb25uZWN0aW9ucyB0aGF0IGNvbm5lY3QgdG8gc3RhZ2VzXG4gICAgY29uc3Qgb3V0Z29pbmdDb25uZWN0aW9ucyA9IHRoaXMuc3RhdGUuY29ubmVjdGlvbnMuZmlsdGVyKFxuICAgICAgKGNvbm4pID0+IGNvbm4uc291cmNlTm9kZUlkID09PSBub2RlLmlkXG4gICAgKTtcblxuICAgIC8vIENoZWNrIGlmIHRoZSB0YXJnZXQgbm9kZXMgYXJlIHN0YWdlc1xuICAgIGNvbnN0IGNvbm5lY3RlZFN0YWdlTm9kZXMgPSBvdXRnb2luZ0Nvbm5lY3Rpb25zXG4gICAgICAubWFwKChjb25uKSA9PiB0aGlzLnN0YXRlLmZpbmROb2RlQnlJZChjb25uLnRhcmdldE5vZGVJZCkpXG4gICAgICAuZmlsdGVyKChub2RlSW5mbykgPT4gbm9kZUluZm8gJiYgbm9kZUluZm8ubm9kZS50eXBlID09PSAnc3RhZ2UnKTtcblxuICAgIG5vZGUuaGFzTXVsdGlwbGVDb25uZWN0ZWRTdGFnZXMgPSBjb25uZWN0ZWRTdGFnZU5vZGVzLmxlbmd0aCA+IDE7XG4gIH1cblxuICBvbkVkaXRTd2ltbGFuZShcbiAgICBldmVudDogTW91c2VFdmVudCxcbiAgICBzd2ltbGFuZTogU3dpbWxhbmVJdGVtLFxuICAgIHN3aW1sYW5lSW5kZXg6IG51bWJlclxuICApOiB2b2lkIHtcbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTsgLy8gUHJldmVudCB0aGUgY2FudmFzIGNsaWNrIGV2ZW50IGZyb20gZmlyaW5nXG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICBjb25zb2xlLmxvZygnRWRpdCBzd2ltbGFuZSBidXR0b24gY2xpY2tlZCBmb3Igc3dpbWxhbmU6Jywgc3dpbWxhbmVJbmRleCk7XG5cbiAgICAvLyBFbWl0IGEgc3BlY2lhbCBldmVudCBmb3IgZWRpdGluZyBhIHN3aW1sYW5lXG4gICAgdGhpcy5jbGlja2VkUG9zaXRpb24uZW1pdCh7XG4gICAgICB4OiAtMSwgLy8gU3BlY2lhbCB2YWx1ZSB0byBpbmRpY2F0ZSBlZGl0IG1vZGVcbiAgICAgIHk6IHN3aW1sYW5lSW5kZXgsXG4gICAgfSk7XG4gIH1cblxuICAvLyBzaG93U3RhcnROb2RlRm9ybVBvcHVwKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gIC8vICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgLy8gICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcblxuICAvLyAgIC8vIEltcGxlbWVudGF0aW9uIHdpbGwgYmUgc2ltaWxhciB0byB0aGUgc3RhZ2UgZm9ybSBwb3B1cFxuICAvLyAgIC8vIFdlJ2xsIG5lZWQgdG8gYWRkIFVJIGVsZW1lbnRzIGZvciB0aGlzXG4gIC8vICAgY29uc29sZS5sb2coJ1N0YXJ0IG5vZGUgZm9ybSBwb3B1cCByZXF1ZXN0ZWQnKTtcblxuICAvLyAgIC8vIEZvciBub3csIHRoaXMgaXMgYSBwbGFjZWhvbGRlclxuICAvLyAgIC8vIFRoZSBhY3R1YWwgaW1wbGVtZW50YXRpb24gd291bGQgbG9hZCBmb3JtcyBhbmQgYWRkIHRoZW0gdG8gdGhlIHdvcmtmbG93XG4gIC8vIH1cblxuICB0b2dnbGVTdGFydE5vZGVGb3JtUG9wdXAoXG4gICAgZXZlbnQ6IE1vdXNlRXZlbnQsXG4gICAgbm9kZVg6IG51bWJlcixcbiAgICBub2RlWTogbnVtYmVyLFxuICAgIHN3aW1sYW5lSW5kZXg6IG51bWJlclxuICApOiB2b2lkIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgLy8gU2V0IHBvcHVwIHBvc2l0aW9uXG4gICAgY29uc3Qgc3dpbWxhbmVPZmZzZXQgPSBzd2ltbGFuZUluZGV4ICogMjYzICsgNDA7XG4gICAgdGhpcy5zdGFydE5vZGVGb3JtUG9wdXBYID0gbm9kZVggLSAzMDsgLy8gUG9zaXRpb24gbmVhciB0aGUgc3RhcnQgbm9kZVxuICAgIHRoaXMuc3RhcnROb2RlRm9ybVBvcHVwWSA9IG5vZGVZICsgc3dpbWxhbmVPZmZzZXQ7XG5cbiAgICAvLyBJZiB3ZSdyZSBvcGVuaW5nIHRoZSBwb3B1cCwgbG9hZCBmb3Jtc1xuICAgIGlmICghdGhpcy5zaG93U3RhcnROb2RlRm9ybVBvcHVwKSB7XG4gICAgICB0aGlzLmlzTG9hZGluZ1N0YXJ0Tm9kZUZvcm1zID0gdHJ1ZTtcbiAgICAgIHRoaXMuZGF0YVNlcnZpY2VcbiAgICAgICAgLmdldEZvcm1zKClcbiAgICAgICAgLnRoZW4oKHJlc3BvbnNlKSA9PiB7XG4gICAgICAgICAgdGhpcy5zdGFydE5vZGVGb3Jtc0xpc3QgPSByZXNwb25zZS5SZXN1bHQ7XG4gICAgICAgICAgdGhpcy5pc0xvYWRpbmdTdGFydE5vZGVGb3JtcyA9IGZhbHNlO1xuICAgICAgICB9KVxuICAgICAgICAuY2F0Y2goKGVycm9yKSA9PiB7XG4gICAgICAgICAgY29uc29sZS5lcnJvcignRXJyb3IgbG9hZGluZyBmb3JtczonLCBlcnJvcik7XG4gICAgICAgICAgdGhpcy5pc0xvYWRpbmdTdGFydE5vZGVGb3JtcyA9IGZhbHNlO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICB0aGlzLnNob3dTdGFydE5vZGVGb3JtUG9wdXAgPSAhdGhpcy5zaG93U3RhcnROb2RlRm9ybVBvcHVwO1xuICB9XG5cbiAgc2VsZWN0U3RhcnROb2RlRm9ybShmb3JtOiBGb3JtRW50aXR5IHwgbnVsbCk6IHZvaWQge1xuICAgIGlmIChmb3JtKSB7XG4gICAgICB0aGlzLnN0YXRlLnNldFdvcmtmbG93Rm9ybShmb3JtLklkLCBmb3JtLk5hbWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnN0YXRlLnNldFdvcmtmbG93Rm9ybShudWxsLCBudWxsKTtcbiAgICB9XG5cbiAgICAvLyBDbG9zZSB0aGUgcG9wdXBcbiAgICB0aGlzLnNob3dTdGFydE5vZGVGb3JtUG9wdXAgPSBmYWxzZTtcbiAgfVxuXG4gIHNob3dTdWJmbG93U2VsZWN0aW9uUG9wdXAoeDogbnVtYmVyLCB5OiBudW1iZXIsIHN3aW1sYW5lSW5kZXg6IG51bWJlcik6IHZvaWQge1xuICAgIHRoaXMuc3ViZmxvd1BvcHVwWCA9IHg7XG4gICAgdGhpcy5zdWJmbG93UG9wdXBZID0geTtcbiAgICB0aGlzLnBlbmRpbmdTdWJmbG93UG9zaXRpb24gPSB7IHN3aW1sYW5lSW5kZXgsIHgsIHkgfTtcblxuICAgIC8vIFN0b3JlIGNvbm5lY3Rpb24gZGF0YSBpZiB3ZSdyZSBjcmVhdGluZyBmcm9tIGEgY29ubmVjdGlvblxuICAgIGlmICh0aGlzLnN0YXRlLmlzQ29ubmVjdGlvbkRyYWdnaW5nKCkpIHtcbiAgICAgIC8vIFN0b3JlIHRoZSBzb3VyY2UgY29ubmVjdGlvbiBkYXRhXG4gICAgICB0aGlzLnBlbmRpbmdDb25uZWN0aW9uU291cmNlUG9pbnQgPVxuICAgICAgICB0aGlzLnN0YXRlLmRyYWdnaW5nQ29ubmVjdGlvbkRhdGEuc291cmNlUG9pbnQgPz8gbnVsbDtcbiAgICAgIHRoaXMucGVuZGluZ0Nvbm5lY3Rpb25Tb3VyY2VTd2ltbGFuZUluZGV4ID1cbiAgICAgICAgdGhpcy5zdGF0ZS5kcmFnZ2luZ0Nvbm5lY3Rpb25EYXRhLnNvdXJjZVN3aW1sYW5lSW5kZXggPz8gbnVsbDtcbiAgICAgIGNvbnNvbGUubG9nKCdTdG9yZWQgY29ubmVjdGlvbiBkYXRhIGZvciBzdWJmbG93OicsIHtcbiAgICAgICAgc291cmNlUG9pbnQ6IHRoaXMucGVuZGluZ0Nvbm5lY3Rpb25Tb3VyY2VQb2ludCxcbiAgICAgICAgc291cmNlU3dpbWxhbmVJbmRleDogdGhpcy5wZW5kaW5nQ29ubmVjdGlvblNvdXJjZVN3aW1sYW5lSW5kZXgsXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyBMb2FkIHdvcmtmbG93c1xuICAgIHRoaXMuaXNMb2FkaW5nV29ya2Zsb3dzID0gdHJ1ZTtcbiAgICB0aGlzLmRhdGFTZXJ2aWNlXG4gICAgICAuZ2V0V29ya2Zsb3dzKClcbiAgICAgIC50aGVuKChyZXNwb25zZSkgPT4ge1xuICAgICAgICB0aGlzLndvcmtmbG93c0xpc3QgPSByZXNwb25zZS5SZXN1bHQ7XG4gICAgICAgIHRoaXMuaXNMb2FkaW5nV29ya2Zsb3dzID0gZmFsc2U7XG4gICAgICB9KVxuICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xuICAgICAgICBjb25zb2xlLmVycm9yKCdFcnJvciBsb2FkaW5nIHdvcmtmbG93czonLCBlcnJvcik7XG4gICAgICAgIHRoaXMuaXNMb2FkaW5nV29ya2Zsb3dzID0gZmFsc2U7XG4gICAgICB9KTtcblxuICAgIHRoaXMuc2hvd1N1YmZsb3dQb3B1cCA9IHRydWU7XG4gIH1cblxuICBzZWxlY3RTdWJmbG93V29ya2Zsb3cod29ya2Zsb3c6IFdvcmtmbG93KTogdm9pZCB7XG4gICAgY29uc29sZS5sb2coJ1NlbGVjdGluZyB3b3JrZmxvdyBmb3Igc3ViZmxvdzonLCB3b3JrZmxvdy5OYW1lKTtcbiAgICBjb25zb2xlLmxvZygnUGVuZGluZyBjb25uZWN0aW9uIGRhdGE6Jywge1xuICAgICAgc291cmNlUG9pbnQ6IHRoaXMucGVuZGluZ0Nvbm5lY3Rpb25Tb3VyY2VQb2ludCxcbiAgICAgIHNvdXJjZVN3aW1sYW5lSW5kZXg6IHRoaXMucGVuZGluZ0Nvbm5lY3Rpb25Tb3VyY2VTd2ltbGFuZUluZGV4LFxuICAgICAgcG9zaXRpb246IHRoaXMucGVuZGluZ1N1YmZsb3dQb3NpdGlvbixcbiAgICB9KTtcblxuICAgIGlmICh0aGlzLnBlbmRpbmdTdWJmbG93UG9zaXRpb24pIHtcbiAgICAgIGNvbnN0IHsgc3dpbWxhbmVJbmRleCwgeCwgeSB9ID0gdGhpcy5wZW5kaW5nU3ViZmxvd1Bvc2l0aW9uO1xuXG4gICAgICAvLyBDcmVhdGUgdGhlIHN1YmZsb3cgbm9kZSB3aXRoIHRoZSBzZWxlY3RlZCB3b3JrZmxvdyBkYXRhXG4gICAgICBjb25zdCBub2RlID0gdGhpcy5zdGF0ZS5hZGROb2RlKFxuICAgICAgICBzd2ltbGFuZUluZGV4LFxuICAgICAgICAnc3ViZmxvdycsXG4gICAgICAgIHgsXG4gICAgICAgIHksXG4gICAgICAgIHVuZGVmaW5lZCwgLy8gTm8gc3RhZ2UgZGF0YVxuICAgICAgICB7IGlkOiB3b3JrZmxvdy5JZCwgbmFtZTogd29ya2Zsb3cuTmFtZSB9XG4gICAgICApO1xuXG4gICAgICBjb25zb2xlLmxvZygnQ3JlYXRlZCBzdWJmbG93IG5vZGU6Jywgbm9kZSk7XG5cbiAgICAgIC8vIElmIHRoaXMgd2FzIGNyZWF0ZWQgZnJvbSBhIGNvbm5lY3Rpb24sIGNyZWF0ZSB0aGUgY29ubmVjdGlvblxuICAgICAgaWYgKG5vZGUgJiYgdGhpcy5wZW5kaW5nQ29ubmVjdGlvblNvdXJjZVBvaW50KSB7XG4gICAgICAgIGNvbnNvbGUubG9nKCdDcmVhdGluZyBjb25uZWN0aW9uIHRvIG5ldyBzdWJmbG93IG5vZGUnKTtcblxuICAgICAgICAvLyBGaW5kIGEgc3VpdGFibGUgY29ubmVjdGlvbiBwb2ludCBvbiB0aGUgbmV3IG5vZGVcbiAgICAgICAgaWYgKG5vZGUuY29ubmVjdGlvblBvaW50cyAmJiBub2RlLmNvbm5lY3Rpb25Qb2ludHMubGVuZ3RoID4gMCkge1xuICAgICAgICAgIGNvbnN0IHNvdXJjZVBvaW50ID0gdGhpcy5wZW5kaW5nQ29ubmVjdGlvblNvdXJjZVBvaW50O1xuXG4gICAgICAgICAgLy8gRmluZCBvcHBvc2luZyB0eXBlIGNvbm5lY3Rpb24gcG9pbnRcbiAgICAgICAgICBjb25zdCBvcHBvc2luZ1R5cGUgPSB7XG4gICAgICAgICAgICByaWdodDogJ2xlZnQnLFxuICAgICAgICAgICAgbGVmdDogJ3JpZ2h0JyxcbiAgICAgICAgICAgIHRvcDogJ2JvdHRvbScsXG4gICAgICAgICAgICBib3R0b206ICd0b3AnLFxuICAgICAgICAgIH1bc291cmNlUG9pbnQudHlwZV0gYXMgJ3RvcCcgfCAncmlnaHQnIHwgJ2JvdHRvbScgfCAnbGVmdCc7XG5cbiAgICAgICAgICBjb25zdCB0YXJnZXRQb2ludCA9IG5vZGUuY29ubmVjdGlvblBvaW50cy5maW5kKFxuICAgICAgICAgICAgKHApID0+IHAudHlwZSA9PT0gb3Bwb3NpbmdUeXBlXG4gICAgICAgICAgKTtcblxuICAgICAgICAgIGlmICh0YXJnZXRQb2ludCkge1xuICAgICAgICAgICAgLy8gQ3JlYXRlIGNvbm5lY3Rpb25cbiAgICAgICAgICAgIGNvbnN0IGNvbm5lY3Rpb24gPSB7XG4gICAgICAgICAgICAgIGlkOiBgY29ubi0ke0RhdGUubm93KCl9LSR7TWF0aC5mbG9vcihNYXRoLnJhbmRvbSgpICogMTAwMCl9YCxcbiAgICAgICAgICAgICAgc291cmNlTm9kZUlkOiBzb3VyY2VQb2ludC5ub2RlSWQsXG4gICAgICAgICAgICAgIHRhcmdldE5vZGVJZDogbm9kZS5pZCxcbiAgICAgICAgICAgICAgc291cmNlUG9pbnRJZDogc291cmNlUG9pbnQuaWQsXG4gICAgICAgICAgICAgIHRhcmdldFBvaW50SWQ6IHRhcmdldFBvaW50LmlkLFxuICAgICAgICAgICAgICBzb3VyY2VTd2ltbGFuZUluZGV4OiB0aGlzLnBlbmRpbmdDb25uZWN0aW9uU291cmNlU3dpbWxhbmVJbmRleCEsXG4gICAgICAgICAgICAgIHRhcmdldFN3aW1sYW5lSW5kZXg6IHN3aW1sYW5lSW5kZXgsXG4gICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAvLyBBZGQgY29ubmVjdGlvbiBkaXJlY3RseSB0byB0aGUgc3RhdGUncyBjb25uZWN0aW9ucyBhcnJheVxuICAgICAgICAgICAgdGhpcy5zdGF0ZS5jb25uZWN0aW9ucy5wdXNoKGNvbm5lY3Rpb24pO1xuICAgICAgICAgICAgY29uc29sZS5sb2coJ0FkZGVkIGNvbm5lY3Rpb24gdG8gc3RhdGU6JywgY29ubmVjdGlvbik7XG4gICAgICAgICAgICBjb25zb2xlLmxvZygnQ29ubmVjdGlvbnMgYWZ0ZXIgYWRkaW5nOicsIHRoaXMuc3RhdGUuY29ubmVjdGlvbnMpO1xuICAgICAgICAgICAgdGhpcy5vbkNvbm5lY3Rpb25DcmVhdGVkKGNvbm5lY3Rpb24pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB0aGlzLnN0YXRlLmVuZENvbm5lY3Rpb25EcmFnKCk7XG4gICAgICB9XG5cbiAgICAgIC8vIFJlc2V0IHNlbGVjdGlvbiB0b29sIGluIHBhcmVudCBjb21wb25lbnRcbiAgICAgIHRoaXMuc3ViZmxvd1NlbGVjdGVkLmVtaXQoKTtcbiAgICB9XG5cbiAgICAvLyBDbGVhbiB1cFxuICAgIHRoaXMuc2hvd1N1YmZsb3dQb3B1cCA9IGZhbHNlO1xuICAgIHRoaXMucGVuZGluZ1N1YmZsb3dQb3NpdGlvbiA9IG51bGw7XG4gICAgdGhpcy5wZW5kaW5nQ29ubmVjdGlvblNvdXJjZVBvaW50ID0gbnVsbDtcbiAgICB0aGlzLnBlbmRpbmdDb25uZWN0aW9uU291cmNlU3dpbWxhbmVJbmRleCA9IG51bGw7XG4gIH1cblxuICBzaG93RGVjaXNpb25Db25kaXRpb25zUG9wdXAoXG4gICAgZXZlbnQ6IE1vdXNlRXZlbnQsXG4gICAgbm9kZTogV0ZOb2RlLFxuICAgIHN3aW1sYW5lSW5kZXg6IG51bWJlclxuICApOiB2b2lkIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgLy8gR2V0IHRoZSBwb3NpdGlvbiBmb3IgdGhlIHBvcHVwXG4gICAgY29uc3QgcG9zaXRpb24gPSB0aGlzLmdldE1vdXNlUG9zaXRpb24oZXZlbnQpO1xuICAgIGNvbnN0IGdsb2JhbFggPSBwb3NpdGlvbi54O1xuICAgIGNvbnN0IGdsb2JhbFkgPSBwb3NpdGlvbi55O1xuXG4gICAgLy8gRmluZCBhbGwgY29ubmVjdGlvbnMgZnJvbSB0aGlzIGRlY2lzaW9uIG5vZGVcbiAgICBjb25zdCBjb25uZWN0aW9ucyA9IHRoaXMuc3RhdGUuY29ubmVjdGlvbnMuZmlsdGVyKFxuICAgICAgKGNvbm4pID0+IGNvbm4uc291cmNlTm9kZUlkID09PSBub2RlLmlkXG4gICAgKTtcblxuICAgIGlmIChjb25uZWN0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICAgIC8vIE5vIGNvbm5lY3Rpb25zIHRvIHNob3dcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICAvLyBTaG93IHRoZSBkZWNpc2lvbiBjb25kaXRpb25zIHBvcHVwXG4gICAgdGhpcy5hY3RpdmVEZWNpc2lvbk5vZGVJZCA9IG5vZGUuaWQ7XG4gICAgdGhpcy5kZWNpc2lvbkNvbmRpdGlvblBvcHVwWCA9IGdsb2JhbFg7XG4gICAgdGhpcy5kZWNpc2lvbkNvbmRpdGlvblBvcHVwWSA9IGdsb2JhbFk7XG5cbiAgICAvLyBTZXQgdGhlIGNvcnJlY3QgcG9wdXAgdmlzaWJpbGl0eSBmbGFnIC0gdGhpcyBpcyBsaWtlbHkgdGhlIGlzc3VlXG4gICAgdGhpcy5zaG93RGVjaXNpb25Db25kaXRpb25EaWFsb2cgPSB0cnVlO1xuXG4gICAgY29uc29sZS5sb2coJ1Nob3dpbmcgZGVjaXNpb24gcG9wdXA6Jywge1xuICAgICAgeDogZ2xvYmFsWCxcbiAgICAgIHk6IGdsb2JhbFksXG4gICAgICBub2RlSWQ6IG5vZGUuaWQsXG4gICAgICBpc1Zpc2libGU6IHRoaXMuc2hvd0RlY2lzaW9uQ29uZGl0aW9uRGlhbG9nLFxuICAgIH0pO1xuICB9XG5cbiAgZW5zdXJlU3dpbWxhbmVJblZpZXcoc3dpbWxhbmVJbmRleDogbnVtYmVyKTogdm9pZCB7XG4gICAgLy8gRW5zdXJlIHdlIGhhdmUgZW5vdWdoIHN3aW1sYW5lcyB2aXNpYmxlXG4gICAgY29uc3QgcmVxdWlyZWRIZWlnaHQgPSAoc3dpbWxhbmVJbmRleCArIDEpICogdGhpcy5zd2ltbGFuZUhlaWdodDtcbiAgICBpZiAodGhpcy5jYW52YXNIZWlnaHQgPCByZXF1aXJlZEhlaWdodCkge1xuICAgICAgdGhpcy5jYW52YXNIZWlnaHQgPSByZXF1aXJlZEhlaWdodDtcbiAgICB9XG4gIH1cbn1cbiIsIjxkaXYgY2xhc3M9XCJjYW52YXMtY29udGFpbmVyXCI+XG4gIDxzdmdcbiAgICAjY2FudmFzXG4gICAgW2F0dHIud2lkdGhdPVwiY2FudmFzV2lkdGhcIlxuICAgIFthdHRyLmhlaWdodF09XCJjYW52YXNIZWlnaHRcIlxuICAgIGNsYXNzPVwiZGVzaWduZXItY2FudmFzXCJcbiAgICAoY2xpY2spPVwib25DYW52YXNDbGljaygkZXZlbnQpXCJcbiAgPlxuICAgIDxkZWZzPlxuICAgICAgPCEtLSBHcmlkIHBhdHRlcm4gZGVmaW5pdGlvbiAtLT5cblxuICAgICAgPHBhdHRlcm5cbiAgICAgICAgaWQ9XCJncmlkXCJcbiAgICAgICAgW2F0dHIud2lkdGhdPVwiZ3JpZFNpemVcIlxuICAgICAgICBbYXR0ci5oZWlnaHRdPVwiZ3JpZFNpemVcIlxuICAgICAgICBwYXR0ZXJuVW5pdHM9XCJ1c2VyU3BhY2VPblVzZVwiXG4gICAgICA+XG4gICAgICAgIDxwYXRoXG4gICAgICAgICAgZD1cIk0gMjAgMCBMIDAgMCAwIDIwXCJcbiAgICAgICAgICBmaWxsPVwibm9uZVwiXG4gICAgICAgICAgc3Ryb2tlPVwiI2UyZThmMFwiXG4gICAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMC41XCJcbiAgICAgICAgLz5cbiAgICAgIDwvcGF0dGVybj5cblxuICAgICAgPCEtLSBBcnJvdyBoZWFkIG1hcmtlciBkZWZpbml0aW9uIC0tPlxuICAgICAgPG1hcmtlclxuICAgICAgICBpZD1cImFycm93aGVhZFwiXG4gICAgICAgIG1hcmtlcldpZHRoPVwiMTBcIlxuICAgICAgICBtYXJrZXJIZWlnaHQ9XCI3XCJcbiAgICAgICAgcmVmWD1cIjlcIlxuICAgICAgICByZWZZPVwiMy41XCJcbiAgICAgICAgb3JpZW50PVwiYXV0b1wiXG4gICAgICA+XG4gICAgICAgIDxwb2x5Z29uIHBvaW50cz1cIjAgMCwgMTAgMy41LCAwIDdcIiBmaWxsPVwiI0QzNkNGRlwiIC8+XG4gICAgICA8L21hcmtlcj5cblxuICAgICAgPCEtLSBDb25uZWN0aW9uIHBvaW50IHN0eWxlcyAtLT5cbiAgICAgIDxjaXJjbGVcbiAgICAgICAgaWQ9XCJjb25uZWN0aW9uLXBvaW50LXRlbXBsYXRlXCJcbiAgICAgICAgcj1cIjVcIlxuICAgICAgICBmaWxsPVwiI0QzNkNGRlwiXG4gICAgICAgIHN0cm9rZT1cIiNGRkZGRkZcIlxuICAgICAgICBzdHJva2Utd2lkdGg9XCIxXCJcbiAgICAgIC8+XG5cbiAgICAgIDwhLS0gRGFzaGVkIGxpbmUgc3R5bGUgZm9yIGNvbm5lY3Rpb24gcHJldmlldyAtLT5cbiAgICAgIDxwYXR0ZXJuXG4gICAgICAgIGlkPVwiZGFzaGVkLWxpbmVcIlxuICAgICAgICB3aWR0aD1cIjEwXCJcbiAgICAgICAgaGVpZ2h0PVwiMTBcIlxuICAgICAgICBwYXR0ZXJuVW5pdHM9XCJ1c2VyU3BhY2VPblVzZVwiXG4gICAgICA+XG4gICAgICAgIDxsaW5lXG4gICAgICAgICAgeDE9XCIwXCJcbiAgICAgICAgICB5MT1cIjVcIlxuICAgICAgICAgIHgyPVwiMTBcIlxuICAgICAgICAgIHkyPVwiNVwiXG4gICAgICAgICAgc3Ryb2tlPVwiI0QzNkNGRlwiXG4gICAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMlwiXG4gICAgICAgICAgc3Ryb2tlLWRhc2hhcnJheT1cIjUsNVwiXG4gICAgICAgIC8+XG4gICAgICA8L3BhdHRlcm4+XG5cbiAgICAgIEBmb3IgKHN3aW1sYW5lIG9mIHN0YXRlLnN3aW1sYW5lczsgdHJhY2sgc3dpbWxhbmUub3JkZXIpIHtcbiAgICAgIDxjbGlwUGF0aCBbYXR0ci5pZF09XCInc3dpbWxhbmUtY2xpcC0nICsgc3dpbWxhbmUub3JkZXJcIj5cbiAgICAgICAgPHJlY3QgeD1cIjBcIiB5PVwiMFwiIFthdHRyLndpZHRoXT1cImNhbnZhc1dpZHRoXCIgaGVpZ2h0PVwiMjYzXCIgLz5cbiAgICAgIDwvY2xpcFBhdGg+XG4gICAgICB9XG4gICAgPC9kZWZzPlxuXG4gICAgPCEtLSBCYWNrZ3JvdW5kIGdyaWQgLS0+XG4gICAgPHJlY3Qgd2lkdGg9XCIxMDAlXCIgaGVpZ2h0PVwiMTAwJVwiIGZpbGw9XCJ1cmwoI2dyaWQpXCIgLz5cblxuICAgIDwhLS0gRGlzcGxheSBhIG1lc3NhZ2Ugd2hlbiBubyBzd2ltbGFuZXMgZXhpc3QgLS0+XG4gICAgQGlmIChzdGF0ZS5zd2ltbGFuZXMubGVuZ3RoID09PSAwKSB7XG4gICAgPHRleHRcbiAgICAgIHg9XCI1MCVcIlxuICAgICAgeT1cIjUwJVwiXG4gICAgICBmb250LWZhbWlseT1cInNhbnMtc2VyaWZcIlxuICAgICAgZm9udC1zaXplPVwiMTZcIlxuICAgICAgZmlsbD1cIiM5NGEzYjhcIlxuICAgICAgdGV4dC1hbmNob3I9XCJtaWRkbGVcIlxuICAgID5cbiAgICAgIFNlbGVjdCB0aGUgU3dpbWxhbmUgdG9vbCBhbmQgY2xpY2sgb24gdGhlIGNhbnZhcyB0byBhZGQgYSBzd2ltbGFuZVxuICAgIDwvdGV4dD5cbiAgICB9XG5cbiAgICA8IS0tIFRoaXMgaXMgd2hlcmUgd29ya2Zsb3cgZWxlbWVudHMgd2lsbCBiZSBhZGRlZCBsYXRlciAtLT5cbiAgICBAZm9yIChzd2ltbGFuZSBvZiBzdGF0ZS5zd2ltbGFuZXM7IHRyYWNrIHN3aW1sYW5lLm9yZGVyKSB7XG4gICAgPGdcbiAgICAgIFthdHRyLnRyYW5zZm9ybV09XCIndHJhbnNsYXRlKDAsJyArIHN3aW1sYW5lLm9yZGVyICogMjYzICsgJyknXCJcbiAgICAgIFthdHRyLmNsaXAtcGF0aF09XCIndXJsKCNzd2ltbGFuZS1jbGlwLScgKyBzd2ltbGFuZS5vcmRlciArICcpJ1wiXG4gICAgPlxuICAgICAgPCEtLSBTd2ltbGFuZSBjb250YWluZXIgLS0+XG4gICAgICA8cmVjdFxuICAgICAgICB4PVwiMFwiXG4gICAgICAgIHk9XCIwXCJcbiAgICAgICAgW2F0dHIud2lkdGhdPVwiY2FudmFzV2lkdGhcIlxuICAgICAgICBbYXR0ci5oZWlnaHRdPVwiMjYzXCJcbiAgICAgICAgZmlsbD1cIiNmZmZmZmZcIlxuICAgICAgICBzdHJva2U9XCIjZTJlOGYwXCJcbiAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMVwiXG4gICAgICA+PC9yZWN0PlxuXG4gICAgICA8IS0tIFN3aW1sYW5lIGhlYWRlciAtLT5cbiAgICAgIDxyZWN0XG4gICAgICAgIHg9XCIwXCJcbiAgICAgICAgeT1cIjBcIlxuICAgICAgICBbYXR0ci53aWR0aF09XCJjYW52YXNXaWR0aFwiXG4gICAgICAgIGhlaWdodD1cIjQwXCJcbiAgICAgICAgZmlsbD1cIiNmOGZhZmNcIlxuICAgICAgICBzdHJva2U9XCIjZTJlOGYwXCJcbiAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMVwiXG4gICAgICA+PC9yZWN0PlxuXG4gICAgICA8IS0tIFN3aW1sYW5lIGxhYmVsIC0tPlxuICAgICAgPHRleHRcbiAgICAgICAgeD1cIjIwXCJcbiAgICAgICAgeT1cIjI1XCJcbiAgICAgICAgZm9udC1mYW1pbHk9XCJzYW5zLXNlcmlmXCJcbiAgICAgICAgZm9udC1zaXplPVwiMTRcIlxuICAgICAgICBmaWxsPVwiIzMzMzMzM1wiXG4gICAgICAgIGZvbnQtd2VpZ2h0PVwiYm9sZFwiXG4gICAgICA+XG4gICAgICAgIHt7IHN3aW1sYW5lLmxhYmVsIH19XG4gICAgICA8L3RleHQ+XG5cbiAgICAgIDwhLS0gRWRpdCBidXR0b24gLS0+XG4gICAgICA8Z1xuICAgICAgICBjbGFzcz1cImVkaXQtc3dpbWxhbmUtYnV0dG9uXCJcbiAgICAgICAgW2F0dHIudHJhbnNmb3JtXT1cIid0cmFuc2xhdGUoMTAwLCAyMCknXCJcbiAgICAgICAgKGNsaWNrKT1cIlxuICAgICAgICAgIG9uRWRpdFN3aW1sYW5lKCRldmVudCwgc3dpbWxhbmUsIHN3aW1sYW5lLm9yZGVyKTtcbiAgICAgICAgICAkZXZlbnQuc3RvcFByb3BhZ2F0aW9uKClcbiAgICAgICAgXCJcbiAgICAgID5cbiAgICAgICAgPHJlY3RcbiAgICAgICAgICB4PVwiLTVcIlxuICAgICAgICAgIHk9XCItMTVcIlxuICAgICAgICAgIHdpZHRoPVwiNDBcIlxuICAgICAgICAgIGhlaWdodD1cIjIwXCJcbiAgICAgICAgICBmaWxsPVwiI2YzZThmZlwiXG4gICAgICAgICAgcng9XCIzXCJcbiAgICAgICAgICByeT1cIjNcIlxuICAgICAgICAgIHN0cm9rZT1cIiNkOGI0ZmVcIlxuICAgICAgICAgIHN0cm9rZS13aWR0aD1cIjFcIlxuICAgICAgICA+PC9yZWN0PlxuICAgICAgICA8dGV4dFxuICAgICAgICAgIHg9XCIxNVwiXG4gICAgICAgICAgeT1cIjBcIlxuICAgICAgICAgIGZvbnQtZmFtaWx5PVwic2Fucy1zZXJpZlwiXG4gICAgICAgICAgZm9udC1zaXplPVwiMTJcIlxuICAgICAgICAgIGZpbGw9XCIjN2UyMmNlXCJcbiAgICAgICAgICB0ZXh0LWFuY2hvcj1cIm1pZGRsZVwiXG4gICAgICAgID5cbiAgICAgICAgICBFZGl0XG4gICAgICAgIDwvdGV4dD5cbiAgICAgIDwvZz5cblxuICAgICAgPCEtLSBUYWcgaW5kaWNhdG9ycyAtLT5cbiAgICAgIDxnIFthdHRyLnRyYW5zZm9ybV09XCIndHJhbnNsYXRlKDIwMCwgMjApJ1wiPlxuICAgICAgICBAZm9yICh0YWcgb2Ygc3dpbWxhbmUudGFncy5zbGljZSgwLCAzKTsgdHJhY2sgdGFnLk5hbWU7IGxldCBpID0gJGluZGV4KVxuICAgICAgICB7XG4gICAgICAgIDx0ZXh0XG4gICAgICAgICAgW2F0dHIueF09XCJpICogMTAwXCJcbiAgICAgICAgICB5PVwiNVwiXG4gICAgICAgICAgZm9udC1mYW1pbHk9XCJzYW5zLXNlcmlmXCJcbiAgICAgICAgICBmb250LXNpemU9XCIxMlwiXG4gICAgICAgICAgZmlsbD1cIiM2NjY2NjZcIlxuICAgICAgICA+XG4gICAgICAgICAge3sgdGFnLk5hbWUgfX1cbiAgICAgICAgPC90ZXh0PlxuICAgICAgICB9IEBpZiAoc3dpbWxhbmUudGFncy5sZW5ndGggPiAzKSB7XG4gICAgICAgIDx0ZXh0XG4gICAgICAgICAgW2F0dHIueF09XCIzICogMTAwICsgMTBcIlxuICAgICAgICAgIHk9XCI1XCJcbiAgICAgICAgICBmb250LWZhbWlseT1cInNhbnMtc2VyaWZcIlxuICAgICAgICAgIGZvbnQtc2l6ZT1cIjEyXCJcbiAgICAgICAgICBmaWxsPVwiIzY2NjY2NlwiXG4gICAgICAgID5cbiAgICAgICAgICAre3sgc3dpbWxhbmUudGFncy5sZW5ndGggLSAzIH19IG1vcmVcbiAgICAgICAgPC90ZXh0PlxuICAgICAgICB9XG4gICAgICA8L2c+XG4gICAgPC9nPlxuICAgIH1cblxuICAgIDwhLS0gTm9kZXMgLS0+XG4gICAgQGZvciAoc3dpbWxhbmUgb2Ygc3RhdGUuc3dpbWxhbmVzOyB0cmFjayBzd2ltbGFuZS5vcmRlcikge1xuICAgIDwhLS0gUmVuZGVyIG5vZGVzIGluIHRoaXMgc3dpbWxhbmUgLS0+XG4gICAgQGZvciAobm9kZSBvZiBzd2ltbGFuZS5ub2RlczsgdHJhY2sgbm9kZS5pZCkge1xuICAgIDxnXG4gICAgICBjbGFzcz1cIm5vZGUtZWxlbWVudFwiXG4gICAgICBbYXR0ci50cmFuc2Zvcm1dPVwiJ3RyYW5zbGF0ZSgnICsgbm9kZS54ICsgJywnICsgKG5vZGUueSArIDQwKSArICcpJ1wiXG4gICAgICAobW91c2VlbnRlcik9XCJzaG93Q29ubmVjdGlvblBvaW50cyhub2RlLmlkLCBzd2ltbGFuZS5vcmRlcilcIlxuICAgICAgKG1vdXNlbGVhdmUpPVwiaGlkZUNvbm5lY3Rpb25Qb2ludHMobm9kZS5pZClcIlxuICAgID5cbiAgICAgIDwhLS0gU3RhcnQgbm9kZSBpbmRpY2F0b3IgKGNpcmNsZSBhbmQgYXJyb3cpIGZvciB0aGUgZmlyc3Qgbm9kZSAtLT5cbiAgICAgIEBpZiAobm9kZS5pc1N0YXJ0Tm9kZSkge1xuICAgICAgPCEtLSBDaXJjbGUgLS0+XG4gICAgICA8Y2lyY2xlXG4gICAgICAgIGN4PVwiLTMwXCJcbiAgICAgICAgY3k9XCI1MFwiXG4gICAgICAgIHI9XCIxNVwiXG4gICAgICAgIGZpbGw9XCJub25lXCJcbiAgICAgICAgc3Ryb2tlPVwiI0QzNkNGRlwiXG4gICAgICAgIHN0cm9rZS13aWR0aD1cIjFcIlxuICAgICAgPjwvY2lyY2xlPlxuICAgICAgPCEtLSBGb3JtIGljb24gZm9yIHN0YXJ0IG5vZGUgLS0+XG4gICAgICA8c3ZnOmdcbiAgICAgICAgKGNsaWNrKT1cIlxuICAgICAgICAgIHRvZ2dsZVN0YXJ0Tm9kZUZvcm1Qb3B1cCgkZXZlbnQsIG5vZGUueCwgbm9kZS55LCBzd2ltbGFuZS5vcmRlcilcbiAgICAgICAgXCJcbiAgICAgICAgY2xhc3M9XCJzdGFnZS1pY29uXCJcbiAgICAgICAgdHJhbnNmb3JtPVwidHJhbnNsYXRlKC00NSwgNDIpXCJcbiAgICAgICAgc3R5bGU9XCJjdXJzb3I6IHBvaW50ZXI7IHBvaW50ZXItZXZlbnRzOiBhbGxcIlxuICAgICAgPlxuICAgICAgICA8IS0tIFRyYW5zcGFyZW50IHJlY3RhbmdsZSB0byBjYXB0dXJlIGNsaWNrcyAtLT5cbiAgICAgICAgPHN2ZzpyZWN0XG4gICAgICAgICAgeD1cIi0yXCJcbiAgICAgICAgICB5PVwiLTJcIlxuICAgICAgICAgIHdpZHRoPVwiMjRcIlxuICAgICAgICAgIGhlaWdodD1cIjI0XCJcbiAgICAgICAgICBmaWxsPVwidHJhbnNwYXJlbnRcIlxuICAgICAgICAgIHN0eWxlPVwiY3Vyc29yOiBwb2ludGVyXCJcbiAgICAgICAgLz5cbiAgICAgICAgPHN2ZzpwYXRoXG4gICAgICAgICAgZD1cIk0xNi41IDIwLjQ3NVYxNy40NzVIMTMuNVYxNi40NzVIMTYuNVYxMy40NzVIMTcuNVYxNi40NzVIMjAuNVYxNy40NzVIMTcuNVYyMC40NzVIMTYuNVpNMy41IDE3LjVWMTYuNUg0LjVWMTcuNUgzLjVaTTYuNSAxNy41VjE2LjVIMTEuNTE3QzExLjUwNTcgMTYuNjc2NyAxMS41MDQzIDE2Ljg0NSAxMS41MTMgMTcuMDA1QzExLjUyMSAxNy4xNjUgMTEuNTMxIDE3LjMzIDExLjU0MyAxNy41SDYuNVpNMy41IDEzLjVWMTIuNUg0LjVWMTMuNUgzLjVaTTYuNSAxMy41VjEyLjVIMTMuODA0QzEzLjYxMjcgMTIuNjM4NyAxMy40MzMzIDEyLjc5MTMgMTMuMjY2IDEyLjk1OEMxMy4wOTkzIDEzLjEyNDcgMTIuOTM3NyAxMy4zMDUzIDEyLjc4MSAxMy41SDYuNVpNMy41IDkuNVY4LjVINC41VjkuNUgzLjVaTTYuNSA5LjVWOC41SDE4LjVWOS41SDYuNVpNMy41IDUuNVY0LjVINC41VjUuNUgzLjVaTTYuNSA1LjVWNC41SDE4LjVWNS41SDYuNVpcIlxuICAgICAgICAgIFthdHRyLmZpbGxdPVwic3RhdGUud29ya2Zsb3dGb3JtSWQgPyAnI0QzNkNGRicgOiAnYmxhY2snXCJcbiAgICAgICAgICB0cmFuc2Zvcm09XCJzY2FsZSgwLjcpXCJcbiAgICAgICAgLz5cbiAgICAgIDwvc3ZnOmc+XG4gICAgICA8IS0tIEFycm93IGZyb20gY2lyY2xlIHRvIG5vZGUgLS0+XG4gICAgICA8cGF0aFxuICAgICAgICBkPVwiTSAtMjAgNTAgTCAwIDUwXCJcbiAgICAgICAgc3Ryb2tlPVwiI0QzNkNGRlwiXG4gICAgICAgIHN0cm9rZS13aWR0aD1cIjFcIlxuICAgICAgICBtYXJrZXItZW5kPVwidXJsKCNhcnJvd2hlYWQpXCJcbiAgICAgID48L3BhdGg+XG4gICAgICB9XG5cbiAgICAgIDwhLS0gRXhpdCBwb2ludCBpbmRpY2F0b3IgKGNpcmNsZSBhbmQgYXJyb3cpIC0tPlxuICAgICAgQGlmIChub2RlLnN0YWdlRGF0YT8uSXNFeGl0UG9pbnQpIHtcbiAgICAgIDwhLS0gQXJyb3cgZnJvbSBub2RlIHRvIGNpcmNsZSAtLT5cbiAgICAgIDxwYXRoXG4gICAgICAgIFthdHRyLmRdPVwiJ00gJyArIG5vZGUud2lkdGggKyAnIDUwIEwgJyArIChub2RlLndpZHRoICsgMjApICsgJyA1MCdcIlxuICAgICAgICBzdHJva2U9XCIjRDM2Q0ZGXCJcbiAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMVwiXG4gICAgICAgIG1hcmtlci1lbmQ9XCJ1cmwoI2Fycm93aGVhZClcIlxuICAgICAgPjwvcGF0aD5cbiAgICAgIDwhLS0gQ2lyY2xlIC0tPlxuICAgICAgPGNpcmNsZVxuICAgICAgICBbYXR0ci5jeF09XCJub2RlLndpZHRoICsgNTBcIlxuICAgICAgICBjeT1cIjUwXCJcbiAgICAgICAgcj1cIjMwXCJcbiAgICAgICAgZmlsbD1cIm5vbmVcIlxuICAgICAgICBzdHJva2U9XCIjRDM2Q0ZGXCJcbiAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMlwiXG4gICAgICA+PC9jaXJjbGU+XG4gICAgICB9XG5cbiAgICAgIDwhLS0gU3RhZ2Ugbm9kZSAtLT5cbiAgICAgIEBpZiAobm9kZS50eXBlID09PSAnc3RhZ2UnKSB7XG4gICAgICA8IS0tIDxyZWN0XG4gICAgICAgICAgICAgICAgICB4PVwiMFwiXG4gICAgICAgICAgICAgICAgICB5PVwiMFwiXG4gICAgICAgICAgICAgICAgICBbYXR0ci53aWR0aF09XCJub2RlLndpZHRoXCJcbiAgICAgICAgICAgICAgICAgIFthdHRyLmhlaWdodF09XCJub2RlLmhlaWdodFwiXG4gICAgICAgICAgICAgICAgICBmaWxsPVwibm9uZVwiXG4gICAgICAgICAgICAgICAgICBzdHJva2U9XCIjRDM2Q0ZGXCJcbiAgICAgICAgICAgICAgICAgIHN0cm9rZS13aWR0aD1cIjFcIlxuICAgICAgICAgICAgICAgID48L3JlY3Q+IC0tPlxuICAgICAgPHN2ZzpnXG4gICAgICAgIGxpYi1zdGFnZS1ub2RlXG4gICAgICAgIFtub2RlXT1cIm5vZGVcIlxuICAgICAgICBbaXNTdGFydE5vZGVdPVwibm9kZS5pc1N0YXJ0Tm9kZVwiXG4gICAgICAgIChzdGFnZVByb3BlcnRpZXNVcGRhdGVkKT1cIm9uU3RhZ2VQcm9wZXJ0aWVzVXBkYXRlZCgkZXZlbnQpXCJcbiAgICAgICAgKHNob3dTaGllbGREaWFsb2cpPVwib25TaG93U2hpZWxkRGlhbG9nKCRldmVudClcIlxuICAgICAgPjwvc3ZnOmc+XG4gICAgICB9XG5cbiAgICAgIDwhLS0gRGVjaXNpb24gbm9kZSAtLT5cbiAgICAgIEBpZiAobm9kZS50eXBlID09PSAnZGVjaXNpb24nKSB7XG4gICAgICA8cGF0aFxuICAgICAgICBbYXR0ci5kXT1cIlxuICAgICAgICAgICdNIDAgJyArXG4gICAgICAgICAgbm9kZS5oZWlnaHQgLyAyICtcbiAgICAgICAgICAnIEwgJyArXG4gICAgICAgICAgbm9kZS53aWR0aCAvIDIgK1xuICAgICAgICAgICcgMCcgK1xuICAgICAgICAgICcgTCAnICtcbiAgICAgICAgICBub2RlLndpZHRoICtcbiAgICAgICAgICAnICcgK1xuICAgICAgICAgIG5vZGUuaGVpZ2h0IC8gMiArXG4gICAgICAgICAgJyBMICcgK1xuICAgICAgICAgIG5vZGUud2lkdGggLyAyICtcbiAgICAgICAgICAnICcgK1xuICAgICAgICAgIG5vZGUuaGVpZ2h0ICtcbiAgICAgICAgICAnIFonXG4gICAgICAgIFwiXG4gICAgICAgIGZpbGw9XCJub25lXCJcbiAgICAgICAgc3Ryb2tlPVwiI0QzNkNGRlwiXG4gICAgICAgIHN0cm9rZS13aWR0aD1cIjFcIlxuICAgICAgPjwvcGF0aD5cblxuICAgICAgPCEtLSBEZWNpc2lvbiBub2RlIGNvbmRpdGlvbiBpbmRpY2F0b3IgaWNvbiAtLT5cbiAgICAgIDxzdmc6Z1xuICAgICAgICAoY2xpY2spPVwic2hvd0RlY2lzaW9uQ29uZGl0aW9uc1BvcHVwKCRldmVudCwgbm9kZSwgc3dpbWxhbmUub3JkZXIpXCJcbiAgICAgICAgY2xhc3M9XCJkZWNpc2lvbi1jb25kaXRpb24taWNvblwiXG4gICAgICAgIFthdHRyLnRyYW5zZm9ybV09XCJcbiAgICAgICAgICAndHJhbnNsYXRlKCcgK1xuICAgICAgICAgIChub2RlLndpZHRoIC8gMiAtIDEwKSArXG4gICAgICAgICAgJywnICtcbiAgICAgICAgICAobm9kZS5oZWlnaHQgLyAyIC0gMTApICtcbiAgICAgICAgICAnKSdcbiAgICAgICAgXCJcbiAgICAgID5cbiAgICAgICAgPHN2ZzpyZWN0XG4gICAgICAgICAgeD1cIi01XCJcbiAgICAgICAgICB5PVwiLTVcIlxuICAgICAgICAgIHdpZHRoPVwiMzBcIlxuICAgICAgICAgIGhlaWdodD1cIjMwXCJcbiAgICAgICAgICBmaWxsPVwidHJhbnNwYXJlbnRcIlxuICAgICAgICAgIHN0eWxlPVwiY3Vyc29yOiBwb2ludGVyXCJcbiAgICAgICAgLz5cbiAgICAgICAgPHN2ZzpwYXRoXG4gICAgICAgICAgZD1cIk0xMCAwSDIwVjJIMTBWMFpNMTAgOEgyMFYxMEgxMFY4Wk0xMCA0SDIwVjZIMTBWNFpNMCAwSDhWMkgwVjBaTTAgOEg4VjEwSDBWOFpNMCA0SDhWNkgwVjRaXCJcbiAgICAgICAgICBmaWxsPVwiI0QzNkNGRlwiXG4gICAgICAgIC8+XG4gICAgICA8L3N2ZzpnPlxuICAgICAgfVxuXG4gICAgICA8IS0tIEZvcm0gbm9kZSAtLT5cbiAgICAgIEBpZiAobm9kZS50eXBlID09PSAnZm9ybScpIHtcbiAgICAgIDxwYXRoXG4gICAgICAgIGQ9XCJNOTUuMDYyNSA1MC41NTkxVjk1LjA2MjVDOTUuMDYyNSA5Ny45NzE2IDkzLjkwNjkgMTAwLjc2MiA5MS44NDk4IDEwMi44MTlDODkuNzkyOCAxMDQuODc2IDg3LjAwMjggMTA2LjAzMSA4NC4wOTM4IDEwNi4wMzFIMzIuOTA2MkMyOS45OTcyIDEwNi4wMzEgMjcuMjA3MiAxMDQuODc2IDI1LjE1MDIgMTAyLjgxOUMyMy4wOTMxIDEwMC43NjIgMjEuOTM3NSA5Ny45NzE2IDIxLjkzNzUgOTUuMDYyNVYyMS45Mzc1QzIxLjkzNzUgMTkuMDI4NCAyMy4wOTMxIDE2LjIzODUgMjUuMTUwMiAxNC4xODE0QzI3LjIwNzIgMTIuMTI0NCAyOS45OTcyIDEwLjk2ODggMzIuOTA2MiAxMC45Njg4SDU1LjQ3MjJDNTcuNDEwOSAxMC45NjkgNTkuMjcwMSAxMS43MzkyIDYwLjY0MTIgMTMuMTA5OUw5Mi45MjEzIDQ1LjM5MDFDOTQuMjkyIDQ2Ljc2MTEgOTUuMDYyMiA0OC42MjA0IDk1LjA2MjUgNTAuNTU5MVpcIlxuICAgICAgICB0cmFuc2Zvcm09XCJzY2FsZSgwLjcpXCJcbiAgICAgICAgZmlsbD1cIm5vbmVcIlxuICAgICAgICBzdHJva2U9XCIjRDM2Q0ZGXCJcbiAgICAgICAgc3Ryb2tlLWxpbmVqb2luPVwicm91bmRcIlxuICAgICAgLz5cbiAgICAgIDxwYXRoXG4gICAgICAgIGQ9XCJNNTguNSAxMi43OTY5VjQwLjIxODhDNTguNSA0Mi4xNTgxIDU5LjI3MDQgNDQuMDE4MSA2MC42NDE4IDQ1LjM4OTVDNjIuMDEzMSA0Ni43NjA4IDYzLjg3MzEgNDcuNTMxMiA2NS44MTI1IDQ3LjUzMTJIOTMuMjM0NFwiXG4gICAgICAgIHRyYW5zZm9ybT1cInNjYWxlKDAuNylcIlxuICAgICAgICBzdHJva2U9XCIjRDM2Q0ZGXCJcbiAgICAgICAgc3Ryb2tlLWxpbmVjYXA9XCJyb3VuZFwiXG4gICAgICAgIHN0cm9rZS1saW5lam9pbj1cInJvdW5kXCJcbiAgICAgIC8+XG4gICAgICA8dGV4dFxuICAgICAgICB4PVwiNTAlXCJcbiAgICAgICAgeT1cIjUwJVwiXG4gICAgICAgIHRleHQtYW5jaG9yPVwibWlkZGxlXCJcbiAgICAgICAgZG9taW5hbnQtYmFzZWxpbmU9XCJtaWRkbGVcIlxuICAgICAgICBmb250LWZhbWlseT1cInNhbnMtc2VyaWZcIlxuICAgICAgICBmb250LXNpemU9XCIxNFwiXG4gICAgICAgIGZpbGw9XCIjRDM2Q0ZGXCJcbiAgICAgID5cbiAgICAgICAgRm9ybVxuICAgICAgPC90ZXh0PlxuICAgICAgfVxuXG4gICAgICA8IS0tIFN1YmZsb3cgbm9kZSAtLT5cbiAgICAgIEBpZiAobm9kZS50eXBlID09PSAnc3ViZmxvdycpIHtcbiAgICAgIDxwYXRoXG4gICAgICAgIFthdHRyLmRdPVwiXG4gICAgICAgICAgJ00gMSAnICtcbiAgICAgICAgICBub2RlLmhlaWdodCAvIDQgK1xuICAgICAgICAgICcgTCAnICtcbiAgICAgICAgICBub2RlLndpZHRoIC8gMiArXG4gICAgICAgICAgJyAxIEwgJyArXG4gICAgICAgICAgKG5vZGUud2lkdGggLSAxKSArXG4gICAgICAgICAgJyAnICtcbiAgICAgICAgICBub2RlLmhlaWdodCAvIDQgK1xuICAgICAgICAgICcgViAnICtcbiAgICAgICAgICAobm9kZS5oZWlnaHQgKiAzKSAvIDQgK1xuICAgICAgICAgICcgTCAnICtcbiAgICAgICAgICBub2RlLndpZHRoIC8gMiArXG4gICAgICAgICAgJyAnICtcbiAgICAgICAgICAobm9kZS5oZWlnaHQgLSAxKSArXG4gICAgICAgICAgJyBMIDEgJyArXG4gICAgICAgICAgKG5vZGUuaGVpZ2h0ICogMykgLyA0ICtcbiAgICAgICAgICAnIFonXG4gICAgICAgIFwiXG4gICAgICAgIGZpbGw9XCJub25lXCJcbiAgICAgICAgc3Ryb2tlPVwiI0QzNkNGRlwiXG4gICAgICAgIHN0cm9rZS13aWR0aD1cIjFcIlxuICAgICAgPjwvcGF0aD5cbiAgICAgIDx0ZXh0XG4gICAgICAgIFthdHRyLnhdPVwibm9kZS53aWR0aCAvIDJcIlxuICAgICAgICBbYXR0ci55XT1cIm5vZGUuaGVpZ2h0IC8gMlwiXG4gICAgICAgIHRleHQtYW5jaG9yPVwibWlkZGxlXCJcbiAgICAgICAgYWxpZ25tZW50LWJhc2VsaW5lPVwibWlkZGxlXCJcbiAgICAgICAgZm9udC1mYW1pbHk9XCJzYW5zLXNlcmlmXCJcbiAgICAgICAgZm9udC1zaXplPVwiMTBcIlxuICAgICAgICBmaWxsPVwiIzAwMDAwMFwiXG4gICAgICA+XG4gICAgICAgIDwhLS0gTGltaXQgdGV4dCBsZW5ndGggLS0+XG4gICAgICAgIHt7XG4gICAgICAgICAgKG5vZGUud29ya2Zsb3dEYXRhPy5uYW1lIHx8IFwiU3ViZmxvd1wiKS5sZW5ndGggPiAxMlxuICAgICAgICAgICAgPyAobm9kZS53b3JrZmxvd0RhdGE/Lm5hbWUgfHwgXCJTdWJmbG93XCIpLnN1YnN0cmluZygwLCAxMCkgKyBcIi4uLlwiXG4gICAgICAgICAgICA6IG5vZGUud29ya2Zsb3dEYXRhPy5uYW1lIHx8IFwiU3ViZmxvd1wiXG4gICAgICAgIH19XG4gICAgICA8L3RleHQ+XG4gICAgICB9XG5cbiAgICAgIDwhLS0gQ29ubmVjdGlvbiBwb2ludHMgZm9yIHRoaXMgbm9kZSAtLT5cbiAgICAgIEBmb3IgKHBvaW50IG9mIG5vZGUuY29ubmVjdGlvblBvaW50cyB8fCBbXTsgdHJhY2sgcG9pbnQuaWQpIHsgQGlmXG4gICAgICAoaXNDb25uZWN0aW9uUG9pbnRWaXNpYmxlKG5vZGUuaWQpKSB7XG4gICAgICA8dXNlXG4gICAgICAgIFthdHRyLmhyZWZdPVwiJyNjb25uZWN0aW9uLXBvaW50LXRlbXBsYXRlJ1wiXG4gICAgICAgIFthdHRyLnhdPVwicG9pbnQueFwiXG4gICAgICAgIFthdHRyLnldPVwicG9pbnQueVwiXG4gICAgICAgIFthdHRyLmlkXT1cInBvaW50LmlkXCJcbiAgICAgICAgKG1vdXNlZG93bik9XCJzdGFydENvbm5lY3Rpb25EcmFnKCRldmVudCwgcG9pbnQsIHN3aW1sYW5lLm9yZGVyKVwiXG4gICAgICAvPlxuICAgICAgfSB9XG4gICAgPC9nPlxuICAgIDwhLS0gQSB0cmFuc3BhcmVudCBob3ZlciBhcmVhIGZvciBpbXByb3ZlZCBob3ZlciBkZXRlY3Rpb24gLS0+XG4gICAgPHJlY3RcbiAgICAgIFthdHRyLnhdPVwibm9kZS54IC0gMTBcIlxuICAgICAgW2F0dHIueV09XCJub2RlLnkgKyA0MCAtIDEwXCJcbiAgICAgIFthdHRyLndpZHRoXT1cIm5vZGUud2lkdGggKyAyMFwiXG4gICAgICBbYXR0ci5oZWlnaHRdPVwibm9kZS5oZWlnaHQgKyAyMFwiXG4gICAgICBmaWxsPVwidHJhbnNwYXJlbnRcIlxuICAgICAgKG1vdXNlb3Zlcik9XCJzaG93Q29ubmVjdGlvblBvaW50cyhub2RlLmlkLCBzd2ltbGFuZS5vcmRlcilcIlxuICAgICAgKG1vdXNlb3V0KT1cImhpZGVDb25uZWN0aW9uUG9pbnRzKG5vZGUuaWQpXCJcbiAgICAgIHN0eWxlPVwicG9pbnRlci1ldmVudHM6IG5vbmVcIlxuICAgIC8+XG4gICAgfSB9XG5cbiAgICA8IS0tIENvbm5lY3Rpb25zIC0tPlxuICAgIEBmb3IgKGNvbm5lY3Rpb24gb2Ygc3RhdGUuY29ubmVjdGlvbnM7IHRyYWNrIGNvbm5lY3Rpb24uaWQpIHtcbiAgICA8ZyBjbGFzcz1cImNvbm5lY3Rpb24tZWxlbWVudFwiPlxuICAgICAgPHBhdGhcbiAgICAgICAgW2F0dHIuZF09XCJnZXRDb25uZWN0aW9uUGF0aEZvclNhdmVkQ29ubmVjdGlvbihjb25uZWN0aW9uKVwiXG4gICAgICAgIHN0cm9rZT1cIiNEMzZDRkZcIlxuICAgICAgICBzdHJva2Utd2lkdGg9XCIyXCJcbiAgICAgICAgZmlsbD1cIm5vbmVcIlxuICAgICAgICBtYXJrZXItZW5kPVwidXJsKCNhcnJvd2hlYWQpXCJcbiAgICAgID48L3BhdGg+XG4gICAgPC9nPlxuICAgIH1cblxuICAgIDwhLS0gQ29ubmVjdGlvbiBwcmV2aWV3IGxpbmUgLS0+XG4gICAgQGlmIChzdGF0ZS5pc0Nvbm5lY3Rpb25EcmFnZ2luZygpKSB7XG4gICAgPGc+XG4gICAgICA8cGF0aFxuICAgICAgICBbYXR0ci5kXT1cImdldENvbm5lY3Rpb25QYXRoKClcIlxuICAgICAgICBzdHJva2U9XCIjRDM2Q0ZGXCJcbiAgICAgICAgc3Ryb2tlLXdpZHRoPVwiMlwiXG4gICAgICAgIHN0cm9rZS1kYXNoYXJyYXk9XCI1LDVcIlxuICAgICAgICBmaWxsPVwibm9uZVwiXG4gICAgICA+PC9wYXRoPlxuICAgIDwvZz5cbiAgICB9XG4gIDwvc3ZnPlxuXG4gIDxkaXZcbiAgICAqbmdJZj1cInBvcHVwVmlzaWJsZVwiXG4gICAgW3N0eWxlLnBvc2l0aW9uXT1cIidhYnNvbHV0ZSdcIlxuICAgIFtzdHlsZS5sZWZ0LnB4XT1cInBvcHVwWFwiXG4gICAgW3N0eWxlLnRvcC5weF09XCJwb3B1cFlcIlxuICA+XG4gICAgPHZlcmJlbi1wb3AtVXBcbiAgICAgIFtkcm9wZG93bk9wZW5dPVwidHJ1ZVwiXG4gICAgICBbY3VzdG9tU3R5bGVzXT1cInsgJ3otaW5kZXgnOiAnOTknIH1cIlxuICAgICAgW2VuYWJsZU1vdXNlTGVhdmVdPVwiZmFsc2VcIlxuICAgID5cbiAgICAgIDxkaXYgZHJvcGRvd24tdHJpZ2dlciBzdHlsZT1cImRpc3BsYXk6IG5vbmVcIj5cbiAgICAgICAgPCEtLSBIaWRkZW4gdHJpZ2dlciBlbGVtZW50IC0tPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2XG4gICAgICAgIGNsYXNzPVwicC0zIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDAgcm91bmRlZCBzaGFkb3ctbWRcIlxuICAgICAgICBkcm9wZG93bi1jb250ZW50XG4gICAgICA+XG4gICAgICAgIDxoNCBjbGFzcz1cIm1iLTIgZm9udC1tZWRpdW1cIj5DcmVhdGUgQ29ubmVjdGlvbjwvaDQ+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJmbGV4IGZsZXgtY29sIGdhcC0yXCI+XG4gICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgdHlwZSBvZiBhbGxvd2VkTm9kZVR5cGVzXCI+XG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIGNsYXNzPVwicHgtMyBweS0yIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDAgcm91bmRlZCB0ZXh0LXNtIGhvdmVyOmJnLWdyYXktNTBcIlxuICAgICAgICAgICAgICAoY2xpY2spPVwiY3JlYXRlTm9kZUNvbm5lY3Rpb24odHlwZSlcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICBDcmVhdGUge3sgdHlwZSB8IHRpdGxlY2FzZSB9fVxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9uZy1jb250YWluZXI+XG4gICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgY2xhc3M9XCJweC0zIHB5LTIgYmctd2hpdGUgYm9yZGVyIGJvcmRlci1ncmF5LTIwMCByb3VuZGVkIHRleHQtc20gaG92ZXI6YmctZ3JheS01MFwiXG4gICAgICAgICAgICAoY2xpY2spPVwiaGlkZUNvbm5lY3Rpb25Qb3B1cCgpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgICBDYW5jZWxcbiAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cbiAgICA8L3ZlcmJlbi1wb3AtVXA+XG4gIDwvZGl2PlxuXG4gIDxkaXZcbiAgICAqbmdJZj1cInNob3dTdGFydE5vZGVGb3JtUG9wdXBcIlxuICAgIFtzdHlsZS5wb3NpdGlvbl09XCInYWJzb2x1dGUnXCJcbiAgICBbc3R5bGUubGVmdC5weF09XCJzdGFydE5vZGVGb3JtUG9wdXBYXCJcbiAgICBbc3R5bGUudG9wLnB4XT1cInN0YXJ0Tm9kZUZvcm1Qb3B1cFlcIlxuICA+XG4gICAgPHZlcmJlbi1wb3AtVXAgW2Ryb3Bkb3duT3Blbl09XCJ0cnVlXCIgW2N1c3RvbVN0eWxlc109XCJ7ICd6LWluZGV4JzogJzEwMCcgfVwiPlxuICAgICAgPGRpdiBkcm9wZG93bi10cmlnZ2VyIHN0eWxlPVwiZGlzcGxheTogbm9uZVwiPlxuICAgICAgICA8IS0tIEhpZGRlbiB0cmlnZ2VyIGVsZW1lbnQgLS0+XG4gICAgICA8L2Rpdj5cbiAgICAgIDxkaXZcbiAgICAgICAgY2xhc3M9XCJwLTMgYmctd2hpdGUgYm9yZGVyIGJvcmRlci1ncmF5LTIwMCByb3VuZGVkIHNoYWRvdy1tZCB3LTY0XCJcbiAgICAgICAgZHJvcGRvd24tY29udGVudFxuICAgICAgICBzdHlsZT1cImJhY2tncm91bmQtY29sb3I6IHdoaXRlOyB6LWluZGV4OiAxMDAwXCJcbiAgICAgID5cbiAgICAgICAgPGg0IGNsYXNzPVwibWItMiBmb250LW1lZGl1bVwiPlNlbGVjdCBXb3JrZmxvdyBGb3JtPC9oND5cbiAgICAgICAgPGRpdiAqbmdJZj1cImlzTG9hZGluZ1N0YXJ0Tm9kZUZvcm1zXCIgY2xhc3M9XCJ0ZXh0LWNlbnRlciBweS0yXCI+XG4gICAgICAgICAgTG9hZGluZyBmb3Jtcy4uLlxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiAqbmdJZj1cIiFpc0xvYWRpbmdTdGFydE5vZGVGb3Jtc1wiIGNsYXNzPVwibWF4LWgtNDggb3ZlcmZsb3cteS1hdXRvXCI+XG4gICAgICAgICAgPGRpdiBjbGFzcz1cIm1iLTJcIj5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgY2xhc3M9XCJ3LWZ1bGwgcHgtMyBweS0yIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDAgcm91bmRlZCB0ZXh0LXNtIGhvdmVyOmJnLWdyYXktNTAgdGV4dC1sZWZ0XCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdFN0YXJ0Tm9kZUZvcm0obnVsbClcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICBDbGVhciBmb3JtIHNlbGVjdGlvblxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdiAqbmdGb3I9XCJsZXQgZm9ybSBvZiBzdGFydE5vZGVGb3Jtc0xpc3RcIiBjbGFzcz1cIm1iLTFcIj5cbiAgICAgICAgICAgIDxidXR0b25cbiAgICAgICAgICAgICAgY2xhc3M9XCJ3LWZ1bGwgcHgtMyBweS0yIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDAgcm91bmRlZCB0ZXh0LXNtIGhvdmVyOmJnLWdyYXktNTAgdGV4dC1sZWZ0XCJcbiAgICAgICAgICAgICAgKGNsaWNrKT1cInNlbGVjdFN0YXJ0Tm9kZUZvcm0oZm9ybSlcIlxuICAgICAgICAgICAgPlxuICAgICAgICAgICAgICB7eyBmb3JtLk5hbWUgfX1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDxkaXZcbiAgICAgICAgICAgICpuZ0lmPVwic3RhcnROb2RlRm9ybXNMaXN0Lmxlbmd0aCA9PT0gMFwiXG4gICAgICAgICAgICBjbGFzcz1cInRleHQtY2VudGVyIHB5LTIgdGV4dC1ncmF5LTUwMFwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgTm8gZm9ybXMgYXZhaWxhYmxlXG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9kaXY+XG4gICAgPC92ZXJiZW4tcG9wLVVwPlxuICA8L2Rpdj5cblxuICA8ZGl2XG4gICAgKm5nSWY9XCJzaG93U3ViZmxvd1BvcHVwXCJcbiAgICBbc3R5bGUucG9zaXRpb25dPVwiJ2Fic29sdXRlJ1wiXG4gICAgW3N0eWxlLmxlZnQucHhdPVwic3ViZmxvd1BvcHVwWFwiXG4gICAgW3N0eWxlLnRvcC5weF09XCJzdWJmbG93UG9wdXBZXCJcbiAgPlxuICAgIDx2ZXJiZW4tcG9wLVVwIFtkcm9wZG93bk9wZW5dPVwidHJ1ZVwiIFtjdXN0b21TdHlsZXNdPVwieyAnei1pbmRleCc6ICcxMDAnIH1cIj5cbiAgICAgIDxkaXYgZHJvcGRvd24tdHJpZ2dlciBzdHlsZT1cImRpc3BsYXk6IG5vbmVcIj5cbiAgICAgICAgPCEtLSBIaWRkZW4gdHJpZ2dlciBlbGVtZW50IC0tPlxuICAgICAgPC9kaXY+XG4gICAgICA8ZGl2XG4gICAgICAgIGNsYXNzPVwicC0zIGJnLXdoaXRlIGJvcmRlciBib3JkZXItZ3JheS0yMDAgcm91bmRlZCBzaGFkb3ctbWQgdy02NFwiXG4gICAgICAgIGRyb3Bkb3duLWNvbnRlbnRcbiAgICAgICAgc3R5bGU9XCJiYWNrZ3JvdW5kLWNvbG9yOiB3aGl0ZTsgei1pbmRleDogMTAwMFwiXG4gICAgICA+XG4gICAgICAgIDxoNCBjbGFzcz1cIm1iLTIgZm9udC1tZWRpdW1cIj5TZWxlY3QgV29ya2Zsb3c8L2g0PlxuICAgICAgICA8ZGl2ICpuZ0lmPVwiaXNMb2FkaW5nV29ya2Zsb3dzXCIgY2xhc3M9XCJ0ZXh0LWNlbnRlciBweS0yXCI+XG4gICAgICAgICAgTG9hZGluZyB3b3JrZmxvd3MuLi5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDxkaXYgKm5nSWY9XCIhaXNMb2FkaW5nV29ya2Zsb3dzXCIgY2xhc3M9XCJtYXgtaC00OCBvdmVyZmxvdy15LWF1dG9cIj5cbiAgICAgICAgICA8ZGl2ICpuZ0Zvcj1cImxldCB3b3JrZmxvdyBvZiB3b3JrZmxvd3NMaXN0XCIgY2xhc3M9XCJtYi0xXCI+XG4gICAgICAgICAgICA8YnV0dG9uXG4gICAgICAgICAgICAgIGNsYXNzPVwidy1mdWxsIHB4LTMgcHktMiBiZy13aGl0ZSBib3JkZXIgYm9yZGVyLWdyYXktMjAwIHJvdW5kZWQgdGV4dC1zbSBob3ZlcjpiZy1ncmF5LTUwIHRleHQtbGVmdFwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJzZWxlY3RTdWJmbG93V29ya2Zsb3cod29ya2Zsb3cpXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAge3sgd29ya2Zsb3cuTmFtZSB9fVxuICAgICAgICAgICAgPC9idXR0b24+XG4gICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgPGRpdlxuICAgICAgICAgICAgKm5nSWY9XCJ3b3JrZmxvd3NMaXN0Lmxlbmd0aCA9PT0gMFwiXG4gICAgICAgICAgICBjbGFzcz1cInRleHQtY2VudGVyIHB5LTIgdGV4dC1ncmF5LTUwMFwiXG4gICAgICAgICAgPlxuICAgICAgICAgICAgTm8gd29ya2Zsb3dzIGF2YWlsYWJsZVxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvdmVyYmVuLXBvcC1VcD5cbiAgPC9kaXY+XG5cbiAgPGxpYi1jb25kaXRpb25zLXBvcHVwXG4gICAgW3Zpc2libGVdPVwic2hvd0RlY2lzaW9uQ29uZGl0aW9uRGlhbG9nXCJcbiAgICBbZGVjaXNpb25Ob2RlSWRdPVwiYWN0aXZlRGVjaXNpb25Ob2RlSWRcIlxuICAgIFtuZXdDb25uZWN0aW9uSWRdPVwiYWN0aXZlQ29ubmVjdGlvbklkXCJcbiAgICBbcG9wdXBYXT1cImRlY2lzaW9uQ29uZGl0aW9uUG9wdXBYXCJcbiAgICBbcG9wdXBZXT1cImRlY2lzaW9uQ29uZGl0aW9uUG9wdXBZXCJcbiAgICAoY2xvc2VkKT1cIm9uRGVjaXNpb25Db25kaXRpb25DYW5jZWxsZWQoKVwiXG4gICAgKHNhdmVkKT1cIm9uRGVjaXNpb25Db25kaXRpb25TYXZlZCgkZXZlbnQpXCJcbiAgPjwvbGliLWNvbmRpdGlvbnMtcG9wdXA+XG5cbiAgPCEtLSA8bGliLWRlY2lzaW9uLXBvcHVwXG4gICAgW3Zpc2libGVdPVwic2hvd0NvbmRpdGlvbnNEaWFsb2dcIlxuICAgIFtkZWNpc2lvbk5vZGVJZF09XCJhY3RpdmVEZWNpc2lvbk5vZGVJZFwiXG4gICAgW3BvcHVwWF09XCJkZWNpc2lvbkNvbmRpdGlvblBvcHVwWFwiXG4gICAgW3BvcHVwWV09XCJkZWNpc2lvbkNvbmRpdGlvblBvcHVwWVwiXG4gICAgKGNsb3NlZCk9XCJvbkRlY2lzaW9uQ29uZGl0aW9uQ2FuY2VsbGVkKClcIlxuICA+PC9saWItZGVjaXNpb24tcG9wdXA+IC0tPlxuXG4gIDxsaWItc3RhZ2UtZGlhbG9nXG4gICAgW3Zpc2libGVdPVwic2hvd1N0YWdlRGlhbG9nTG9jYWxcIlxuICAgIFtzdGFnZURhdGFdPVwiYWN0aXZlU3RhZ2VEYXRhIHx8IHt9XCJcbiAgICAoY2xvc2VkKT1cIm9uU3RhZ2VEaWFsb2dDbG9zZWQoKVwiXG4gICAgKHNhdmVkKT1cIm9uU3RhZ2VEaWFsb2dTYXZlZCgkZXZlbnQpXCJcbiAgPjwvbGliLXN0YWdlLWRpYWxvZz5cbjwvZGl2PlxuIl19