@datagrok-libraries/statistics 1.9.2 → 1.12.0

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 (34) hide show
  1. package/css/styles.css +229 -0
  2. package/package.json +3 -2
  3. package/src/fit/const.d.ts +58 -0
  4. package/src/fit/const.d.ts.map +1 -0
  5. package/src/fit/const.js +63 -0
  6. package/src/fit/fit-data.d.ts.map +1 -1
  7. package/src/fit/fit-data.js +37 -5
  8. package/src/fit/new-fit-API.d.ts +6 -0
  9. package/src/fit/new-fit-API.d.ts.map +1 -1
  10. package/src/fit/new-fit-API.js +2 -8
  11. package/src/mpo/dialogs/desirability-mode-dialog.d.ts +14 -0
  12. package/src/mpo/dialogs/desirability-mode-dialog.d.ts.map +1 -0
  13. package/src/mpo/dialogs/desirability-mode-dialog.js +198 -0
  14. package/src/mpo/editors/desirability-editor-factory.d.ts +15 -0
  15. package/src/mpo/editors/desirability-editor-factory.d.ts.map +1 -0
  16. package/src/mpo/editors/desirability-editor-factory.js +11 -0
  17. package/src/mpo/editors/mpo-categorical-editor.d.ts +24 -0
  18. package/src/mpo/editors/mpo-categorical-editor.d.ts.map +1 -0
  19. package/src/mpo/editors/mpo-categorical-editor.js +113 -0
  20. package/src/mpo/editors/mpo-line-editor.d.ts +46 -0
  21. package/src/mpo/editors/mpo-line-editor.d.ts.map +1 -0
  22. package/src/mpo/editors/mpo-line-editor.js +583 -0
  23. package/src/mpo/mpo-profile-editor.d.ts +42 -6
  24. package/src/mpo/mpo-profile-editor.d.ts.map +1 -1
  25. package/src/mpo/mpo-profile-editor.js +368 -59
  26. package/src/mpo/mpo.d.ts +53 -3
  27. package/src/mpo/mpo.d.ts.map +1 -1
  28. package/src/mpo/mpo.js +92 -16
  29. package/src/mpo/utils.d.ts +6 -0
  30. package/src/mpo/utils.d.ts.map +1 -0
  31. package/src/mpo/utils.js +17 -0
  32. package/src/mpo/mpo-line-editor.d.ts +0 -10
  33. package/src/mpo/mpo-line-editor.d.ts.map +0 -1
  34. package/src/mpo/mpo-line-editor.js +0 -258
@@ -1,258 +0,0 @@
1
- /* eslint-disable max-len */
2
- import * as grok from 'datagrok-api/grok';
3
- import * as ui from 'datagrok-api/ui';
4
- import Konva from 'konva';
5
- import { Subject } from 'rxjs'; // Import type from mpo.ts
6
- // Constants for the editor layout
7
- const EDITOR_PADDING = { top: 10, right: 10, bottom: 20, left: 30 };
8
- const POINT_RADIUS = 3;
9
- export class MpoDesirabilityLineEditor {
10
- constructor(prop, width, height) {
11
- this.root = ui.div();
12
- this.onChanged = new Subject();
13
- this._prop = prop;
14
- this.root.style.width = `${width}px`;
15
- this.root.style.height = `${height}px`;
16
- this.root.style.position = 'relative'; // Needed for absolute positioning of Konva stage
17
- const that = this;
18
- // Delay Konva initialization slightly to ensure this.container is in DOM
19
- setTimeout(() => {
20
- var _a, _b;
21
- if (!this.root.parentElement) {
22
- console.warn('Konva this.container not attached to DOM yet.');
23
- // Optionally, retry or handle error
24
- return;
25
- }
26
- const stage = new Konva.Stage({
27
- container: this.root,
28
- width: width,
29
- height: height,
30
- });
31
- const layer = new Konva.Layer();
32
- stage.add(layer);
33
- const minX = (_a = prop.min) !== null && _a !== void 0 ? _a : Math.min(...prop.line.map((p) => p[0]));
34
- const maxX = (_b = prop.max) !== null && _b !== void 0 ? _b : Math.max(...prop.line.map((p) => p[0]));
35
- // --- Draw Axes ---
36
- const xAxis = new Konva.Line({
37
- points: [EDITOR_PADDING.left, height - EDITOR_PADDING.bottom, width - EDITOR_PADDING.right, height - EDITOR_PADDING.bottom],
38
- stroke: 'grey',
39
- strokeWidth: 1,
40
- });
41
- const yAxis = new Konva.Line({
42
- points: [EDITOR_PADDING.left, EDITOR_PADDING.top, EDITOR_PADDING.left, height - EDITOR_PADDING.bottom],
43
- stroke: 'grey',
44
- strokeWidth: 1,
45
- });
46
- layer.add(xAxis, yAxis);
47
- // --- Draw Axis Labels/Ticks (Simplified) ---
48
- const minXLabel = new Konva.Text({
49
- x: EDITOR_PADDING.left,
50
- y: height - EDITOR_PADDING.bottom + 3,
51
- text: minX.toFixed(1),
52
- fontSize: 9,
53
- fill: 'grey',
54
- });
55
- const maxXLabel = new Konva.Text({
56
- x: width - EDITOR_PADDING.right - 15,
57
- y: height - EDITOR_PADDING.bottom + 3,
58
- text: maxX.toFixed(1),
59
- fontSize: 9,
60
- align: 'right',
61
- fill: 'grey',
62
- });
63
- const zeroYLabel = new Konva.Text({
64
- x: EDITOR_PADDING.left - 20,
65
- y: height - EDITOR_PADDING.bottom - 5,
66
- text: '0.0',
67
- fontSize: 9,
68
- fill: 'grey',
69
- });
70
- const oneYLabel = new Konva.Text({
71
- x: EDITOR_PADDING.left - 20,
72
- y: EDITOR_PADDING.top - 5,
73
- text: '1.0',
74
- fontSize: 9,
75
- fill: 'grey',
76
- });
77
- layer.add(minXLabel, maxXLabel, zeroYLabel, oneYLabel);
78
- // --- Draw Line and Points ---
79
- const konvaLine = new Konva.Line({
80
- points: [],
81
- stroke: '#2077b4',
82
- strokeWidth: 2,
83
- lineCap: 'round',
84
- lineJoin: 'round',
85
- });
86
- layer.add(konvaLine);
87
- const pointsGroup = new Konva.Group(); // Group for draggable points
88
- layer.add(pointsGroup);
89
- // Function to redraw everything based on prop.line
90
- function redraw(notify = true) {
91
- pointsGroup.destroyChildren(); // Clear old points
92
- const konvaPoints = [];
93
- prop.line.sort((a, b) => a[0] - b[0]); // Ensure sorted
94
- prop.line.forEach((p, index) => {
95
- const coords = toCanvasCoords(p[0], p[1], minX, maxX, width, height);
96
- konvaPoints.push(coords.x, coords.y);
97
- const pointCircle = new Konva.Circle({
98
- x: coords.x,
99
- y: coords.y,
100
- radius: POINT_RADIUS,
101
- fill: '#d72f30',
102
- stroke: 'black',
103
- strokeWidth: 1,
104
- draggable: true,
105
- hitStrokeWidth: 5, // Easier to hit for dragging/clicking
106
- });
107
- // Store index directly on the node for easy access
108
- pointCircle.setAttr('_pointIndex', index);
109
- // --- Dragging Logic ---
110
- pointCircle.on('dragmove', (evt) => {
111
- const circle = evt.target;
112
- const pos = circle.position();
113
- const currentPointIndex = circle.getAttr('_pointIndex');
114
- // Constrain dragging horizontally between neighbors (or bounds)
115
- const prevX = currentPointIndex > 0 ? prop.line[currentPointIndex - 1][0] : minX;
116
- const nextX = currentPointIndex < prop.line.length - 1 ? prop.line[currentPointIndex + 1][0] : maxX;
117
- // Add a small buffer to avoid points overlapping exactly
118
- const buffer = (maxX - minX === 0) ? 0 : 0.001 * (maxX - minX); // Avoid NaN if minX === maxX
119
- const minCanvasX = toCanvasCoords(prevX + (currentPointIndex > 0 ? buffer : 0), 0, minX, maxX, width, height).x;
120
- const maxCanvasX = toCanvasCoords(nextX - (currentPointIndex < prop.line.length - 1 ? buffer : 0), 0, minX, maxX, width, height).x;
121
- pos.x = Math.max(minCanvasX, Math.min(maxCanvasX, pos.x));
122
- // Constrain dragging vertically
123
- const plotTop = EDITOR_PADDING.top;
124
- const plotBottom = height - EDITOR_PADDING.bottom;
125
- pos.y = Math.max(plotTop, Math.min(plotBottom, pos.y));
126
- circle.position(pos); // Update position after constraints
127
- // Update data array
128
- const dataCoords = toDataCoords(pos.x, pos.y, minX, maxX, width, height);
129
- prop.line[currentPointIndex][0] = dataCoords.x;
130
- prop.line[currentPointIndex][1] = dataCoords.y;
131
- // Update the connecting line during drag
132
- const currentKonvaPoints = prop.line.map((pData, idx) => {
133
- // Use dragged circle position directly for the point being dragged
134
- if (idx === currentPointIndex)
135
- return [pos.x, pos.y];
136
- else {
137
- const c = toCanvasCoords(pData[0], pData[1], minX, maxX, width, height);
138
- return [c.x, c.y];
139
- }
140
- }).flat();
141
- konvaLine.points(currentKonvaPoints);
142
- layer.batchDraw(); // More efficient redraw
143
- });
144
- pointCircle.on('dragend', (evt) => {
145
- // Ensure data is sorted after drag, although constraints should handle it
146
- prop.line.sort((a, b) => a[0] - b[0]);
147
- redraw(); // Full redraw on drag end to fix indices and line path
148
- });
149
- // --- Right-click to Remove ---
150
- pointCircle.on('contextmenu', (evt) => {
151
- evt.evt.preventDefault(); // Prevent browser context menu
152
- // Keep at least 2 points for a line segment
153
- if (prop.line.length <= 2) {
154
- // Use DG tooltip or simple alert/warning
155
- grok.shell.warning('Cannot remove points, minimum of 2 required.');
156
- return;
157
- }
158
- const circle = evt.target;
159
- const indexToRemove = circle.getAttr('_pointIndex');
160
- prop.line.splice(indexToRemove, 1);
161
- redraw(); // Redraw after removal
162
- });
163
- // Enhance usability: change cursor on hover and show tooltip
164
- pointCircle.on('mouseenter', (evt) => {
165
- stage.container().style.cursor = 'pointer';
166
- const circle = evt.target;
167
- const pos = circle.position();
168
- const dataCoords = toDataCoords(pos.x, pos.y, minX, maxX, width, height);
169
- const tooltipText = `X: ${dataCoords.x.toFixed(2)}, Y: ${dataCoords.y.toFixed(2)}<br><br>Drag to move, right-click to delete`;
170
- ui.tooltip.show(tooltipText, evt.evt.clientX, evt.evt.clientY);
171
- });
172
- pointCircle.on('mouseleave', (evt) => {
173
- stage.container().style.cursor = 'default';
174
- ui.tooltip.hide();
175
- });
176
- pointsGroup.add(pointCircle);
177
- });
178
- konvaLine.points(konvaPoints);
179
- layer.batchDraw();
180
- if (notify)
181
- that.onChanged.next();
182
- }
183
- // --- Left-click to Add Point ---
184
- stage.on('click tap', (evt) => {
185
- // Ignore clicks on existing points (circles) or non-left clicks
186
- if (evt.target instanceof Konva.Circle || evt.evt.button !== 0)
187
- return;
188
- const pos = stage.getPointerPosition();
189
- if (!pos)
190
- return;
191
- // Ensure click is within the plot area boundaries
192
- if (pos.x < EDITOR_PADDING.left || pos.x > width - EDITOR_PADDING.right ||
193
- pos.y < EDITOR_PADDING.top || pos.y > height - EDITOR_PADDING.bottom)
194
- return;
195
- const dataCoords = toDataCoords(pos.x, pos.y, minX, maxX, width, height);
196
- // Add the new point
197
- prop.line.push([dataCoords.x, dataCoords.y]);
198
- // No need to sort here, redraw() handles sorting
199
- redraw();
200
- });
201
- // Change cursor when over the stage plot area for adding points
202
- stage.on('mouseenter', (evt) => {
203
- if (!(evt.target instanceof Konva.Circle)) {
204
- const pos = stage.getPointerPosition();
205
- if (pos && pos.x >= EDITOR_PADDING.left && pos.x <= width - EDITOR_PADDING.right &&
206
- pos.y >= EDITOR_PADDING.top && pos.y <= height - EDITOR_PADDING.bottom)
207
- stage.container().style.cursor = 'crosshair';
208
- }
209
- });
210
- stage.on('mouseleave', (evt) => {
211
- if (!(evt.target instanceof Konva.Circle))
212
- stage.container().style.cursor = 'default';
213
- });
214
- stage.on('mousemove', (evt) => {
215
- if (!(evt.target instanceof Konva.Circle)) {
216
- const pos = stage.getPointerPosition();
217
- if (pos && pos.x >= EDITOR_PADDING.left && pos.x <= width - EDITOR_PADDING.right &&
218
- pos.y >= EDITOR_PADDING.top && pos.y <= height - EDITOR_PADDING.bottom)
219
- stage.container().style.cursor = 'crosshair';
220
- else
221
- stage.container().style.cursor = 'default';
222
- }
223
- });
224
- stage.on('mouseout', (_) => ui.tooltip.hide());
225
- // Initial draw
226
- redraw(false);
227
- }, 0);
228
- }
229
- get line() {
230
- return this._prop.line;
231
- }
232
- }
233
- // Function to transform data coordinates to canvas coordinates
234
- function toCanvasCoords(x, y, minX, maxX, width, height) {
235
- const plotWidth = width - EDITOR_PADDING.left - EDITOR_PADDING.right;
236
- const plotHeight = height - EDITOR_PADDING.top - EDITOR_PADDING.bottom;
237
- // Handle case where minX === maxX to avoid division by zero
238
- const scaleX = (maxX - minX === 0) ? 1 : plotWidth / (maxX - minX);
239
- const scaleY = plotHeight; // y data is 0-1
240
- const canvasX = EDITOR_PADDING.left + (x - minX) * scaleX;
241
- const canvasY = EDITOR_PADDING.top + plotHeight - (y * scaleY); // Flip y-axis
242
- return { x: canvasX, y: canvasY };
243
- }
244
- // Function to transform canvas coordinates to data coordinates
245
- function toDataCoords(canvasX, canvasY, minX, maxX, width, height) {
246
- const plotWidth = width - EDITOR_PADDING.left - EDITOR_PADDING.right;
247
- const plotHeight = height - EDITOR_PADDING.top - EDITOR_PADDING.bottom;
248
- // Handle case where minX === maxX
249
- const scaleX = (maxX - minX === 0) ? 1 : plotWidth / (maxX - minX);
250
- const scaleY = plotHeight;
251
- let dataX = minX + (canvasX - EDITOR_PADDING.left) / scaleX;
252
- let dataY = (EDITOR_PADDING.top + plotHeight - canvasY) / scaleY;
253
- // Clamp values
254
- dataX = Math.max(minX, Math.min(maxX, dataX));
255
- dataY = Math.max(0, Math.min(1, dataY));
256
- return { x: dataX, y: dataY };
257
- }
258
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXBvLWxpbmUtZWRpdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibXBvLWxpbmUtZWRpdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDRCQUE0QjtBQUM1QixPQUFPLEtBQUssSUFBSSxNQUFNLG1CQUFtQixDQUFDO0FBQzFDLE9BQU8sS0FBSyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFFdEMsT0FBTyxLQUFLLE1BQU0sT0FBTyxDQUFDO0FBRTFCLE9BQU8sRUFBQyxPQUFPLEVBQUMsTUFBTSxNQUFNLENBQUMsQ0FBQywwQkFBMEI7QUFFeEQsa0NBQWtDO0FBQ2xDLE1BQU0sY0FBYyxHQUFHLEVBQUMsR0FBRyxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLE1BQU0sRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBQyxDQUFDO0FBQ2xFLE1BQU0sWUFBWSxHQUFHLENBQUMsQ0FBQztBQUd2QixNQUFNLE9BQU8seUJBQXlCO0lBS3BDLFlBQVksSUFBMEIsRUFBRSxLQUFhLEVBQUUsTUFBYztRQUpyRSxTQUFJLEdBQUcsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ2hCLGNBQVMsR0FBRyxJQUFJLE9BQU8sRUFBRSxDQUFDO1FBSXhCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBQ2xCLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssR0FBRyxHQUFHLEtBQUssSUFBSSxDQUFDO1FBQ3JDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sR0FBRyxHQUFHLE1BQU0sSUFBSSxDQUFDO1FBQ3ZDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsR0FBRyxVQUFVLENBQUMsQ0FBQyxpREFBaUQ7UUFDeEYsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDO1FBRWxCLHlFQUF5RTtRQUN6RSxVQUFVLENBQUMsR0FBRyxFQUFFOztZQUNkLElBQUksQ0FBQyxJ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QyxjQUFjLENBQUMsR0FBRyxHQUFHLFVBQVUsR0FBRyxPQUFPLENBQUMsR0FBRyxNQUFNLENBQUM7SUFFakUsZUFBZTtJQUNmLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBQzlDLEtBQUssR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFDO0lBRXhDLE9BQU8sRUFBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsRUFBRSxLQUFLLEVBQUMsQ0FBQztBQUM5QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgbWF4LWxlbiAqL1xuaW1wb3J0ICogYXMgZ3JvayBmcm9tICdkYXRhZ3Jvay1hcGkvZ3Jvayc7XG5pbXBvcnQgKiBhcyB1aSBmcm9tICdkYXRhZ3Jvay1hcGkvdWknO1xuXG5pbXBvcnQgS29udmEgZnJvbSAna29udmEnO1xuaW1wb3J0IHtEZXNpcmFiaWxpdHlMaW5lLCBQcm9wZXJ0eURlc2lyYWJpbGl0eX0gZnJvbSAnLi9tcG8nO1xuaW1wb3J0IHtTdWJqZWN0fSBmcm9tICdyeGpzJzsgLy8gSW1wb3J0IHR5cGUgZnJvbSBtcG8udHNcblxuLy8gQ29uc3RhbnRzIGZvciB0aGUgZWRpdG9yIGxheW91dFxuY29uc3QgRURJVE9SX1BBRERJTkcgPSB7dG9wOiAxMCwgcmlnaHQ6IDEwLCBib3R0b206IDIwLCBsZWZ0OiAzMH07XG5jb25zdCBQT0lOVF9SQURJVVMgPSAzO1xuXG5cbmV4cG9ydCBjbGFzcyBNcG9EZXNpcmFiaWxpdHlMaW5lRWRpdG9yIHtcbiAgcm9vdCA9IHVpLmRpdigpO1xuICBvbkNoYW5nZWQgPSBuZXcgU3ViamVjdCgpO1xuICBwcml2YXRlIF9wcm9wOiBQcm9wZXJ0eURlc2lyYWJpbGl0eTtcblxuICBjb25zdHJ1Y3Rvcihwcm9wOiBQcm9wZXJ0eURlc2lyYWJpbGl0eSwgd2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpIHtcbiAgICB0aGlzLl9wcm9wID0gcHJvcDtcbiAgICB0aGlzLnJvb3Quc3R5bGUud2lkdGggPSBgJHt3aWR0aH1weGA7XG4gICAgdGhpcy5yb290LnN0eWxlLmhlaWdodCA9IGAke2hlaWdodH1weGA7XG4gICAgdGhpcy5yb290LnN0eWxlLnBvc2l0aW9uID0gJ3JlbGF0aXZlJzsgLy8gTmVlZGVkIGZvciBhYnNvbHV0ZSBwb3NpdGlvbmluZyBvZiBLb252YSBzdGFnZVxuICAgIGNvbnN0IHRoYXQgPSB0aGlzO1xuXG4gICAgLy8gRGVsYXkgS29udmEgaW5pdGlhbGl6YXRpb24gc2xpZ2h0bHkgdG8gZW5zdXJlIHRoaXMuY29udGFpbmVyIGlzIGluIERPTVxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgaWYgKCF0aGlzLnJvb3QucGFyZW50RWxlbWVudCkge1xuICAgICAgICBjb25zb2xlLndhcm4oJ0tvbnZhIHRoaXMuY29udGFpbmVyIG5vdCBhdHRhY2hlZCB0byBET00geWV0LicpO1xuICAgICAgICAvLyBPcHRpb25hbGx5LCByZXRyeSBvciBoYW5kbGUgZXJyb3JcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBjb25zdCBzdGFnZSA9IG5ldyBLb252YS5TdGFnZSh7XG4gICAgICAgIGNvbnRhaW5lcjogdGhpcy5yb290LCAvLyBVc2UgdGhlIHRoaXMuY29udGFpbmVyIGRpdlxuICAgICAgICB3aWR0aDogd2lkdGgsXG4gICAgICAgIGhlaWdodDogaGVpZ2h0LFxuICAgICAgfSk7XG5cbiAgICAgIGNvbnN0IGxheWVyID0gbmV3IEtvbnZhLkxheWVyKCk7XG4gICAgICBzdGFnZS5hZGQobGF5ZXIpO1xuXG4gICAgICBjb25zdCBtaW5YID0gcHJvcC5taW4gPz8gTWF0aC5taW4oLi4ucHJvcC5saW5lLm1hcCgocCkgPT4gcFswXSkpO1xuICAgICAgY29uc3QgbWF4WCA9IHByb3AubWF4ID8/IE1hdGgubWF4KC4uLnByb3AubGluZS5tYXAoKHApID0+IHBbMF0pKTtcblxuICAgICAgLy8gLS0tIERyYXcgQXhlcyAtLS1cbiAgICAgIGNvbnN0IHhBeGlzID0gbmV3IEtvbnZhLkxpbmUoe1xuICAgICAgICBwb2ludHM6IFtFRElUT1JfUEFERElORy5sZWZ0LCBoZWlnaHQgLSBFRElUT1JfUEFERElORy5ib3R0b20sIHdpZHRoIC0gRURJVE9SX1BBRERJTkcucmlnaHQsIGhlaWdodCAtIEVESVRPUl9QQURESU5HLmJvdHRvbV0sXG4gICAgICAgIHN0cm9rZTogJ2dyZXknLCAvLyBMaWdodGVyIGNvbG9yIGZvciBheGVzXG4gICAgICAgIHN0cm9rZVdpZHRoOiAxLFxuICAgICAgfSk7XG4gICAgICBjb25zdCB5QXhpcyA9IG5ldyBLb252YS5MaW5lKHtcbiAgICAgICAgcG9pbnRzOiBbRURJVE9SX1BBRERJTkcubGVmdCwgRURJVE9SX1BBRERJTkcudG9wLCBFRElUT1JfUEFERElORy5sZWZ0LCBoZWlnaHQgLSBFRElUT1JfUEFERElORy5ib3R0b21dLFxuICAgICAgICBzdHJva2U6ICdncmV5JywgLy8gTGlnaHRlciBjb2xvciBmb3IgYXhlc1xuICAgICAgICBzdHJva2VXaWR0aDogMSxcbiAgICAgIH0pO1xuICAgICAgbGF5ZXIuYWRkKHhBeGlzLCB5QXhpcyk7XG5cbiAgICAgIC8vIC0tLSBEcmF3IEF4aXMgTGFiZWxzL1RpY2tzIChTaW1wbGlmaWVkKSAtLS1cbiAgICAgIGNvbnN0IG1pblhMYWJlbCA9IG5ldyBLb252YS5UZXh0KHtcbiAgICAgICAgeDogRURJVE9SX1BBRERJTkcubGVmdCxcbiAgICAgICAgeTogaGVpZ2h0IC0gRURJVE9SX1BBRERJTkcuYm90dG9tICsgMywgLy8gQmVsb3cgYXhpc1xuICAgICAgICB0ZXh0OiBtaW5YLnRvRml4ZWQoMSksIC8vIEZld2VyIGRlY2ltYWxzIGZvciBzbWFsbGVyIHNwYWNlXG4gICAgICAgIGZvbnRTaXplOiA5LFxuICAgICAgICBmaWxsOiAnZ3JleScsXG4gICAgICB9KTtcbiAgICAgIGNvbnN0IG1heFhMYWJlbCA9IG5ldyBLb252YS5UZXh0KHtcbiAgICAgICAgeDogd2lkdGggLSBFRElUT1JfUEFERElORy5yaWdodCAtIDE1LCAvLyBBZGp1c3QgcG9zaXRpb25cbiAgICAgICAgeTogaGVpZ2h0IC0gRURJVE9SX1BBRERJTkcuYm90dG9tICsgMywgLy8gQmVsb3cgYXhpc1xuICAgICAgICB0ZXh0OiBtYXhYLnRvRml4ZWQoMSksIC8vIEZld2VyIGRlY2ltYWxzXG4gICAgICAgIGZvbnRTaXplOiA5LFxuICAgICAgICBhbGlnbjogJ3JpZ2h0JyxcbiAgICAgICAgZmlsbDogJ2dyZXknLFxuICAgICAgfSk7XG4gICAgICBjb25zdCB6ZXJvWUxhYmVsID0gbmV3IEtvbnZhLlRleHQoe1xuICAgICAgICB4OiBFRElUT1JfUEFERElORy5sZWZ0IC0gMjAsIC8vIExlZnQgb2YgYXhpc1xuICAgICAgICB5OiBoZWlnaHQgLSBFRElUT1JfUEFERElORy5ib3R0b20gLSA1LCAvLyBBbGlnbiB3aXRoIGF4aXMgYm90dG9tXG4gICAgICAgIHRleHQ6ICcwLjAnLFxuICAgICAgICBmb250U2l6ZTogOSxcbiAgICAgICAgZmlsbDogJ2dyZXknLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBvbmVZTGFiZWwgPSBuZXcgS29udmEuVGV4dCh7XG4gICAgICAgIHg6IEVESVRPUl9QQURESU5HLmxlZnQgLSAyMCwgLy8gTGVmdCBvZiBheGlzXG4gICAgICAgIHk6IEVESVRPUl9QQURESU5HLnRvcCAtIDUsIC8vIEFsaWduIHdpdGggYXhpcyB0b3BcbiAgICAgICAgdGV4dDogJzEuMCcsXG4gICAgICAgIGZvbnRTaXplOiA5LFxuICAgICAgICBmaWxsOiAnZ3JleScsXG4gICAgICB9KTtcbiAgICAgIGxheWVyLmFkZChtaW5YTGFiZWwsIG1heFhMYWJlbCwgemVyb1lMYWJlbCwgb25lWUxhYmVsKTtcblxuXG4gICAgICAvLyAtLS0gRHJhdyBMaW5lIGFuZCBQb2ludHMgLS0tXG4gICAgICBjb25zdCBrb252YUxpbmUgPSBuZXcgS29udmEuTGluZSh7XG4gICAgICAgIHBvaW50czogW10sIC8vIFdpbGwgYmUgcG9wdWxhdGVkIGJ5IHBvaW50c1xuICAgICAgICBzdHJva2U6ICcjMjA3N2I0JyxcbiAgICAgICAgc3Ryb2tlV2lkdGg6IDIsXG4gICAgICAgIGxpbmVDYXA6ICdyb3VuZCcsXG4gICAgICAgIGxpbmVKb2luOiAncm91bmQnLFxuICAgICAgfSk7XG4gICAgICBsYXllci5hZGQoa29udmFMaW5lKTtcblxuICAgICAgY29uc3QgcG9pbnRzR3JvdXAgPSBuZXcgS29udmEuR3JvdXAoKTsgLy8gR3JvdXAgZm9yIGRyYWdnYWJsZSBwb2ludHNcbiAgICAgIGxheWVyLmFkZChwb2ludHNHcm91cCk7XG5cbiAgICAgIC8vIEZ1bmN0aW9uIHRvIHJlZHJhdyBldmVyeXRoaW5nIGJhc2VkIG9uIHByb3AubGluZVxuICAgICAgZnVuY3Rpb24gcmVkcmF3KG5vdGlmeTogYm9vbGVhbiA9IHRydWUpIHtcbiAgICAgICAgcG9pbnRzR3JvdXAuZGVzdHJveUNoaWxkcmVuKCk7IC8vIENsZWFyIG9sZCBwb2ludHNcbiAgICAgICAgY29uc3Qga29udmFQb2ludHM6IG51bWJlcltdID0gW107XG5cbiAgICAgICAgcHJvcC5saW5lLnNvcnQoKGEsIGIpID0+IGFbMF0gLSBiWzBdKTsgLy8gRW5zdXJlIHNvcnRlZFxuXG4gICAgICAgIHByb3AubGluZS5mb3JFYWNoKChwLCBpbmRleCkgPT4ge1xuICAgICAgICAgIGNvbnN0IGNvb3JkcyA9IHRvQ2FudmFzQ29vcmRzKHBbMF0sIHBbMV0sIG1pblgsIG1heFgsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgIGtvbnZhUG9pbnRzLnB1c2goY29vcmRzLngsIGNvb3Jkcy55KTtcblxuICAgICAgICAgIGNvbnN0IHBvaW50Q2lyY2xlID0gbmV3IEtvbnZhLkNpcmNsZSh7XG4gICAgICAgICAgICB4OiBjb29yZHMueCxcbiAgICAgICAgICAgIHk6IGNvb3Jkcy55LFxuICAgICAgICAgICAgcmFkaXVzOiBQT0lOVF9SQURJVVMsXG4gICAgICAgICAgICBmaWxsOiAnI2Q3MmYzMCcsXG4gICAgICAgICAgICBzdHJva2U6ICdibGFjaycsXG4gICAgICAgICAgICBzdHJva2VXaWR0aDogMSxcbiAgICAgICAgICAgIGRyYWdnYWJsZTogdHJ1ZSwgLy8gTWFrZSBwb2ludHMgZHJhZ2dhYmxlXG4gICAgICAgICAgICBoaXRTdHJva2VXaWR0aDogNSwgLy8gRWFzaWVyIHRvIGhpdCBmb3IgZHJhZ2dpbmcvY2xpY2tpbmdcbiAgICAgICAgICB9KTtcbiAgICAgICAgICAvLyBTdG9yZSBpbmRleCBkaXJlY3RseSBvbiB0aGUgbm9kZSBmb3IgZWFzeSBhY2Nlc3NcbiAgICAgICAgICBwb2ludENpcmNsZS5zZXRBdHRyKCdfcG9pbnRJbmRleCcsIGluZGV4KTtcblxuICAgICAgICAgIC8vIC0tLSBEcmFnZ2luZyBMb2dpYyAtLS1cbiAgICAgICAgICBwb2ludENpcmNsZS5vbignZHJhZ21vdmUnLCAoZXZ0OiBLb252YS5Lb252YUV2ZW50T2JqZWN0PERyYWdFdmVudD4pID0+IHtcbiAgICAgICAgICAgIGNvbnN0IGNpcmNsZSA9IGV2dC50YXJnZXQgYXMgS29udmEuQ2lyY2xlO1xuICAgICAgICAgICAgY29uc3QgcG9zID0gY2lyY2xlLnBvc2l0aW9uKCk7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW50UG9pbnRJbmRleCA9IGNpcmNsZS5nZXRBdHRyKCdfcG9pbnRJbmRleCcpO1xuXG4gICAgICAgICAgICAvLyBDb25zdHJhaW4gZHJhZ2dpbmcgaG9yaXpvbnRhbGx5IGJldHdlZW4gbmVpZ2hib3JzIChvciBib3VuZHMpXG4gICAgICAgICAgICBjb25zdCBwcmV2WCA9IGN1cnJlbnRQb2ludEluZGV4ID4gMCA/IHByb3AubGluZVtjdXJyZW50UG9pbnRJbmRleCAtIDFdWzBdIDogbWluWDtcbiAgICAgICAgICAgIGNvbnN0IG5leHRYID0gY3VycmVudFBvaW50SW5kZXggPCBwcm9wLmxpbmUubGVuZ3RoIC0gMSA/IHByb3AubGluZVtjdXJyZW50UG9pbnRJbmRleCArIDFdWzBdIDogbWF4WDtcbiAgICAgICAgICAgIC8vIEFkZCBhIHNtYWxsIGJ1ZmZlciB0byBhdm9pZCBwb2ludHMgb3ZlcmxhcHBpbmcgZXhhY3RseVxuICAgICAgICAgICAgY29uc3QgYnVmZmVyID0gKG1heFggLSBtaW5YID09PSAwKSA/IDAgOiAwLjAwMSAqIChtYXhYIC0gbWluWCk7IC8vIEF2b2lkIE5hTiBpZiBtaW5YID09PSBtYXhYXG4gICAgICAgICAgICBjb25zdCBtaW5DYW52YXNYID0gdG9DYW52YXNDb29yZHMocHJldlggKyAoY3VycmVudFBvaW50SW5kZXggPiAwID8gYnVmZmVyIDogMCksIDAsIG1pblgsIG1heFgsIHdpZHRoLCBoZWlnaHQpLng7XG4gICAgICAgICAgICBjb25zdCBtYXhDYW52YXNYID0gdG9DYW52YXNDb29yZHMobmV4dFggLSAoY3VycmVudFBvaW50SW5kZXggPCBwcm9wLmxpbmUubGVuZ3RoIC0gMSA/IGJ1ZmZlciA6IDApLCAwLCBtaW5YLCBtYXhYLCB3aWR0aCwgaGVpZ2h0KS54O1xuXG4gICAgICAgICAgICBwb3MueCA9IE1hdGgubWF4KG1pbkNhbnZhc1gsIE1hdGgubWluKG1heENhbnZhc1gsIHBvcy54KSk7XG5cbiAgICAgICAgICAgIC8vIENvbnN0cmFpbiBkcmFnZ2luZyB2ZXJ0aWNhbGx5XG4gICAgICAgICAgICBjb25zdCBwbG90VG9wID0gRURJVE9SX1BBRERJTkcudG9wO1xuICAgICAgICAgICAgY29uc3QgcGxvdEJvdHRvbSA9IGhlaWdodCAtIEVESVRPUl9QQURESU5HLmJvdHRvbTtcbiAgICAgICAgICAgIHBvcy55ID0gTWF0aC5tYXgocGxvdFRvcCwgTWF0aC5taW4ocGxvdEJvdHRvbSwgcG9zLnkpKTtcblxuICAgICAgICAgICAgY2lyY2xlLnBvc2l0aW9uKHBvcyk7IC8vIFVwZGF0ZSBwb3NpdGlvbiBhZnRlciBjb25zdHJhaW50c1xuXG4gICAgICAgICAgICAvLyBVcGRhdGUgZGF0YSBhcnJheVxuICAgICAgICAgICAgY29uc3QgZGF0YUNvb3JkcyA9IHRvRGF0YUNvb3Jkcyhwb3MueCwgcG9zLnksIG1pblgsIG1heFgsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgcHJvcC5saW5lW2N1cnJlbnRQb2ludEluZGV4XVswXSA9IGRhdGFDb29yZHMueDtcbiAgICAgICAgICAgIHByb3AubGluZVtjdXJyZW50UG9pbnRJbmRleF1bMV0gPSBkYXRhQ29vcmRzLnk7XG5cbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgY29ubmVjdGluZyBsaW5lIGR1cmluZyBkcmFnXG4gICAgICAgICAgICBjb25zdCBjdXJyZW50S29udmFQb2ludHMgPSBwcm9wLmxpbmUubWFwKChwRGF0YSwgaWR4KSA9PiB7XG4gICAgICAgICAgICAgIC8vIFVzZSBkcmFnZ2VkIGNpcmNsZSBwb3NpdGlvbiBkaXJlY3RseSBmb3IgdGhlIHBvaW50IGJlaW5nIGRyYWdnZWRcbiAgICAgICAgICAgICAgaWYgKGlkeCA9PT0gY3VycmVudFBvaW50SW5kZXgpXG4gICAgICAgICAgICAgICAgcmV0dXJuIFtwb3MueCwgcG9zLnldO1xuICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBjb25zdCBjID0gdG9DYW52YXNDb29yZHMocERhdGFbMF0sIHBEYXRhWzFdLCBtaW5YLCBtYXhYLCB3aWR0aCwgaGVpZ2h0KTtcbiAgICAgICAgICAgICAgICByZXR1cm4gW2MueCwgYy55XTtcbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSkuZmxhdCgpO1xuICAgICAgICAgICAga29udmFMaW5lLnBvaW50cyhjdXJyZW50S29udmFQb2ludHMpO1xuICAgICAgICAgICAgbGF5ZXIuYmF0Y2hEcmF3KCk7IC8vIE1vcmUgZWZmaWNpZW50IHJlZHJhd1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgcG9pbnRDaXJjbGUub24oJ2RyYWdlbmQnLCAoZXZ0OiBLb252YS5Lb252YUV2ZW50T2JqZWN0PERyYWdFdmVudD4pID0+IHtcbiAgICAgICAgICAgIC8vIEVuc3VyZSBkYXRhIGlzIHNvcnRlZCBhZnRlciBkcmFnLCBhbHRob3VnaCBjb25zdHJhaW50cyBzaG91bGQgaGFuZGxlIGl0XG4gICAgICAgICAgICBwcm9wLmxpbmUuc29ydCgoYSwgYikgPT4gYVswXSAtIGJbMF0pO1xuICAgICAgICAgICAgcmVkcmF3KCk7IC8vIEZ1bGwgcmVkcmF3IG9uIGRyYWcgZW5kIHRvIGZpeCBpbmRpY2VzIGFuZCBsaW5lIHBhdGhcbiAgICAgICAgICB9KTtcblxuICAgICAgICAgIC8vIC0tLSBSaWdodC1jbGljayB0byBSZW1vdmUgLS0tXG4gICAgICAgICAgcG9pbnRDaXJjbGUub24oJ2NvbnRleHRtZW51JywgKGV2dDogS29udmEuS29udmFFdmVudE9iamVjdDxNb3VzZUV2ZW50PikgPT4ge1xuICAgICAgICAgICAgZXZ0LmV2dC5wcmV2ZW50RGVmYXVsdCgpOyAvLyBQcmV2ZW50IGJyb3dzZXIgY29udGV4dCBtZW51XG4gICAgICAgICAgICAvLyBLZWVwIGF0IGxlYXN0IDIgcG9pbnRzIGZvciBhIGxpbmUgc2VnbWVudFxuICAgICAgICAgICAgaWYgKHByb3AubGluZS5sZW5ndGggPD0gMikge1xuICAgICAgICAgICAgICAvLyBVc2UgREcgdG9vbHRpcCBvciBzaW1wbGUgYWxlcnQvd2FybmluZ1xuICAgICAgICAgICAgICBncm9rLnNoZWxsLndhcm5pbmcoJ0Nhbm5vdCByZW1vdmUgcG9pbnRzLCBtaW5pbXVtIG9mIDIgcmVxdWlyZWQuJyk7XG4gICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgY2lyY2xlID0gZXZ0LnRhcmdldCBhcyBLb252YS5DaXJjbGU7XG4gICAgICAgICAgICBjb25zdCBpbmRleFRvUmVtb3ZlID0gY2lyY2xlLmdldEF0dHIoJ19wb2ludEluZGV4Jyk7XG4gICAgICAgICAgICBwcm9wLmxpbmUuc3BsaWNlKGluZGV4VG9SZW1vdmUsIDEpO1xuICAgICAgICAgICAgcmVkcmF3KCk7IC8vIFJlZHJhdyBhZnRlciByZW1vdmFsXG4gICAgICAgICAgfSk7XG5cbiAgICAgICAgICAvLyBFbmhhbmNlIHVzYWJpbGl0eTogY2hhbmdlIGN1cnNvciBvbiBob3ZlciBhbmQgc2hvdyB0b29sdGlwXG4gICAgICAgICAgcG9pbnRDaXJjbGUub24oJ21vdXNlZW50ZXInLCAoZXZ0OiBLb252YS5Lb252YUV2ZW50T2JqZWN0PE1vdXNlRXZlbnQ+KSA9PiB7XG4gICAgICAgICAgICBzdGFnZS5jb250YWluZXIoKS5zdHlsZS5jdXJzb3IgPSAncG9pbnRlcic7XG4gICAgICAgICAgICBjb25zdCBjaXJjbGUgPSBldnQudGFyZ2V0IGFzIEtvbnZhLkNpcmNsZTtcbiAgICAgICAgICAgIGNvbnN0IHBvcyA9IGNpcmNsZS5wb3NpdGlvbigpO1xuICAgICAgICAgICAgY29uc3QgZGF0YUNvb3JkcyA9IHRvRGF0YUNvb3Jkcyhwb3MueCwgcG9zLnksIG1pblgsIG1heFgsIHdpZHRoLCBoZWlnaHQpO1xuICAgICAgICAgICAgY29uc3QgdG9vbHRpcFRleHQgPSBgWDogJHtkYXRhQ29vcmRzLngudG9GaXhlZCgyKX0sIFk6ICR7ZGF0YUNvb3Jkcy55LnRvRml4ZWQoMil9PGJyPjxicj5EcmFnIHRvIG1vdmUsIHJpZ2h0LWNsaWNrIHRvIGRlbGV0ZWA7XG4gICAgICAgICAgICB1aS50b29sdGlwLnNob3codG9vbHRpcFRleHQsIGV2dC5ldnQuY2xpZW50WCwgZXZ0LmV2dC5jbGllbnRZKTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgICBwb2ludENpcmNsZS5vbignbW91c2VsZWF2ZScsIChldnQ6IEtvbnZhLktvbnZhRXZlbnRPYmplY3Q8TW91c2VFdmVudD4pID0+IHtcbiAgICAgICAgICAgIHN0YWdlLmNvbnRhaW5lcigpLnN0eWxlLmN1cnNvciA9ICdkZWZhdWx0JztcbiAgICAgICAgICAgIHVpLnRvb2x0aXAuaGlkZSgpO1xuICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgcG9pbnRzR3JvdXAuYWRkKHBvaW50Q2lyY2xlKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAga29udmFMaW5lLnBvaW50cyhrb252YVBvaW50cyk7XG4gICAgICAgIGxheWVyLmJhdGNoRHJhdygpO1xuXG4gICAgICAgIGlmIChub3RpZnkpXG4gICAgICAgICAgdGhhdC5vbkNoYW5nZWQubmV4dCgpO1xuICAgICAgfVxuXG4gICAgICAvLyAtLS0gTGVmdC1jbGljayB0byBBZGQgUG9pbnQgLS0tXG4gICAgICBzdGFnZS5vbignY2xpY2sgdGFwJywgKGV2dDogS29udmEuS29udmFFdmVudE9iamVjdDxQb2ludGVyRXZlbnQ+KSA9PiB7XG4gICAgICAgIC8vIElnbm9yZSBjbGlja3Mgb24gZXhpc3RpbmcgcG9pbnRzIChjaXJjbGVzKSBvciBub24tbGVmdCBjbGlja3NcbiAgICAgICAgaWYgKGV2dC50YXJnZXQgaW5zdGFuY2VvZiBLb252YS5DaXJjbGUgfHwgZXZ0LmV2dC5idXR0b24gIT09IDApIHJldHVybjtcblxuICAgICAgICBjb25zdCBwb3MgPSBzdGFnZS5nZXRQb2ludGVyUG9zaXRpb24oKTtcbiAgICAgICAgaWYgKCFwb3MpIHJldHVybjtcblxuICAgICAgICAvLyBFbnN1cmUgY2xpY2sgaXMgd2l0aGluIHRoZSBwbG90IGFyZWEgYm91bmRhcmllc1xuICAgICAgICBpZiAocG9zLnggPCBFRElUT1JfUEFERElORy5sZWZ0IHx8IHBvcy54ID4gd2lkdGggLSBFRElUT1JfUEFERElORy5yaWdodCB8fFxuICAgICAgICAgIHBvcy55IDwgRURJVE9SX1BBRERJTkcudG9wIHx8IHBvcy55ID4gaGVpZ2h0IC0gRURJVE9SX1BBRERJTkcuYm90dG9tKVxuICAgICAgICAgIHJldHVybjtcblxuICAgICAgICBjb25zdCBkYXRhQ29vcmRzID0gdG9EYXRhQ29vcmRzKHBvcy54LCBwb3MueSwgbWluWCwgbWF4WCwgd2lkdGgsIGhlaWdodCk7XG4gICAgICAgIC8vIEFkZCB0aGUgbmV3IHBvaW50XG4gICAgICAgIHByb3AubGluZS5wdXNoKFtkYXRhQ29vcmRzLngsIGRhdGFDb29yZHMueV0pO1xuXG4gICAgICAgIC8vIE5vIG5lZWQgdG8gc29ydCBoZXJlLCByZWRyYXcoKSBoYW5kbGVzIHNvcnRpbmdcbiAgICAgICAgcmVkcmF3KCk7XG4gICAgICB9KTtcblxuICAgICAgLy8gQ2hhbmdlIGN1cnNvciB3aGVuIG92ZXIgdGhlIHN0YWdlIHBsb3QgYXJlYSBmb3IgYWRkaW5nIHBvaW50c1xuICAgICAgc3RhZ2Uub24oJ21vdXNlZW50ZXInLCAoZXZ0OiBLb252YS5Lb252YUV2ZW50T2JqZWN0PE1vdXNlRXZlbnQ+KSA9PiB7XG4gICAgICAgIGlmICghKGV2dC50YXJnZXQgaW5zdGFuY2VvZiBLb252YS5DaXJjbGUpKSB7XG4gICAgICAgICAgY29uc3QgcG9zID0gc3RhZ2UuZ2V0UG9pbnRlclBvc2l0aW9uKCk7XG4gICAgICAgICAgaWYgKHBvcyAmJiBwb3MueCA+PSBFRElUT1JfUEFERElORy5sZWZ0ICYmIHBvcy54IDw9IHdpZHRoIC0gRURJVE9SX1BBRERJTkcucmlnaHQgJiZcbiAgICAgICAgICAgIHBvcy55ID49IEVESVRPUl9QQURESU5HLnRvcCAmJiBwb3MueSA8PSBoZWlnaHQgLSBFRElUT1JfUEFERElORy5ib3R0b20pXG4gICAgICAgICAgICBzdGFnZS5jb250YWluZXIoKS5zdHlsZS5jdXJzb3IgPSAnY3Jvc3NoYWlyJztcbiAgICAgICAgfVxuICAgICAgfSk7XG5cbiAgICAgIHN0YWdlLm9uKCdtb3VzZWxlYXZlJywgKGV2dDogS29udmEuS29udmFFdmVudE9iamVjdDxNb3VzZUV2ZW50PikgPT4ge1xuICAgICAgICBpZiAoIShldnQudGFyZ2V0IGluc3RhbmNlb2YgS29udmEuQ2lyY2xlKSlcbiAgICAgICAgICBzdGFnZS5jb250YWluZXIoKS5zdHlsZS5jdXJzb3IgPSAnZGVmYXVsdCc7XG4gICAgICB9KTtcblxuICAgICAgc3RhZ2Uub24oJ21vdXNlbW92ZScsIChldnQ6IEtvbnZhLktvbnZhRXZlbnRPYmplY3Q8TW91c2VFdmVudD4pID0+IHtcbiAgICAgICAgaWYgKCEoZXZ0LnRhcmdldCBpbnN0YW5jZW9mIEtvbnZhLkNpcmNsZSkpIHtcbiAgICAgICAgICBjb25zdCBwb3MgPSBzdGFnZS5nZXRQb2ludGVyUG9zaXRpb24oKTtcbiAgICAgICAgICBpZiAocG9zICYmIHBvcy54ID49IEVESVRPUl9QQURESU5HLmxlZnQgJiYgcG9zLnggPD0gd2lkdGggLSBFRElUT1JfUEFERElORy5yaWdodCAmJlxuICAgICAgICAgICAgcG9zLnkgPj0gRURJVE9SX1BBRERJTkcudG9wICYmIHBvcy55IDw9IGhlaWdodCAtIEVESVRPUl9QQURESU5HLmJvdHRvbSlcbiAgICAgICAgICAgIHN0YWdlLmNvbnRhaW5lcigpLnN0eWxlLmN1cnNvciA9ICdjcm9zc2hhaXInO1xuXG4gICAgICAgICAgZWxzZVxuICAgICAgICAgICAgc3RhZ2UuY29udGFpbmVyKCkuc3R5bGUuY3Vyc29yID0gJ2RlZmF1bHQnO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgICAgc3RhZ2Uub24oJ21vdXNlb3V0JywgKF8pID0+IHVpLnRvb2x0aXAuaGlkZSgpKTtcblxuICAgICAgLy8gSW5pdGlhbCBkcmF3XG4gICAgICByZWRyYXcoZmFsc2UpO1xuICAgIH0sIDApO1xuICB9XG5cbiAgZ2V0IGxpbmUoKTogRGVzaXJhYmlsaXR5TGluZSB7XG4gICAgcmV0dXJuIHRoaXMuX3Byb3AubGluZTtcbiAgfVxufVxuXG5cbi8vIEZ1bmN0aW9uIHRvIHRyYW5zZm9ybSBkYXRhIGNvb3JkaW5hdGVzIHRvIGNhbnZhcyBjb29yZGluYXRlc1xuZnVuY3Rpb24gdG9DYW52YXNDb29yZHMoeDogbnVtYmVyLCB5OiBudW1iZXIsIG1pblg6IG51bWJlciwgbWF4WDogbnVtYmVyLCB3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcik6IHsgeDogbnVtYmVyLCB5OiBudW1iZXIgfSB7XG4gIGNvbnN0IHBsb3RXaWR0aCA9IHdpZHRoIC0gRURJVE9SX1BBRERJTkcubGVmdCAtIEVESVRPUl9QQURESU5HLnJpZ2h0O1xuICBjb25zdCBwbG90SGVpZ2h0ID0gaGVpZ2h0IC0gRURJVE9SX1BBRERJTkcudG9wIC0gRURJVE9SX1BBRERJTkcuYm90dG9tO1xuICAvLyBIYW5kbGUgY2FzZSB3aGVyZSBtaW5YID09PSBtYXhYIHRvIGF2b2lkIGRpdmlzaW9uIGJ5IHplcm9cbiAgY29uc3Qgc2NhbGVYID0gKG1heFggLSBtaW5YID09PSAwKSA/IDEgOiBwbG90V2lkdGggLyAobWF4WCAtIG1pblgpO1xuICBjb25zdCBzY2FsZVkgPSBwbG90SGVpZ2h0OyAvLyB5IGRhdGEgaXMgMC0xXG5cbiAgY29uc3QgY2FudmFzWCA9IEVESVRPUl9QQURESU5HLmxlZnQgKyAoeCAtIG1pblgpICogc2NhbGVYO1xuICBjb25zdCBjYW52YXNZID0gRURJVE9SX1BBRERJTkcudG9wICsgcGxvdEhlaWdodCAtICh5ICogc2NhbGVZKTsgLy8gRmxpcCB5LWF4aXNcblxuICByZXR1cm4ge3g6IGNhbnZhc1gsIHk6IGNhbnZhc1l9O1xufVxuXG4vLyBGdW5jdGlvbiB0byB0cmFuc2Zvcm0gY2FudmFzIGNvb3JkaW5hdGVzIHRvIGRhdGEgY29vcmRpbmF0ZXNcbmZ1bmN0aW9uIHRvRGF0YUNvb3JkcyhjYW52YXNYOiBudW1iZXIsIGNhbnZhc1k6IG51bWJlciwgbWluWDogbnVtYmVyLCBtYXhYOiBudW1iZXIsIHdpZHRoOiBudW1iZXIsIGhlaWdodDogbnVtYmVyKTogeyB4OiBudW1iZXIsIHk6IG51bWJlciB9IHtcbiAgY29uc3QgcGxvdFdpZHRoID0gd2lkdGggLSBFRElUT1JfUEFERElORy5sZWZ0IC0gRURJVE9SX1BBRERJTkcucmlnaHQ7XG4gIGNvbnN0IHBsb3RIZWlnaHQgPSBoZWlnaHQgLSBFRElUT1JfUEFERElORy50b3AgLSBFRElUT1JfUEFERElORy5ib3R0b207XG4gIC8vIEhhbmRsZSBjYXNlIHdoZXJlIG1pblggPT09IG1heFhcbiAgY29uc3Qgc2NhbGVYID0gKG1heFggLSBtaW5YID09PSAwKSA/IDEgOiBwbG90V2lkdGggLyAobWF4WCAtIG1pblgpO1xuICBjb25zdCBzY2FsZVkgPSBwbG90SGVpZ2h0O1xuXG4gIGxldCBkYXRhWCA9IG1pblggKyAoY2FudmFzWCAtIEVESVRPUl9QQURESU5HLmxlZnQpIC8gc2NhbGVYO1xuICBsZXQgZGF0YVkgPSAoRURJVE9SX1BBRERJTkcudG9wICsgcGxvdEhlaWdodCAtIGNhbnZhc1kpIC8gc2NhbGVZO1xuXG4gIC8vIENsYW1wIHZhbHVlc1xuICBkYXRhWCA9IE1hdGgubWF4KG1pblgsIE1hdGgubWluKG1heFgsIGRhdGFYKSk7XG4gIGRhdGFZID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgZGF0YVkpKTtcblxuICByZXR1cm4ge3g6IGRhdGFYLCB5OiBkYXRhWX07XG59XG4iXX0=