@datagrok-libraries/statistics 1.7.0 → 1.8.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.
package/package.json CHANGED
@@ -4,24 +4,27 @@
4
4
  "access": "public"
5
5
  },
6
6
  "friendlyName": "statistics",
7
- "version": "1.7.0",
7
+ "version": "1.8.0",
8
8
  "description": "Statistics utilities",
9
9
  "author": {
10
10
  "name": "Dmytro Kovalyov",
11
11
  "email": "dkovalyov@datagrok.ai"
12
12
  },
13
13
  "dependencies": {
14
- "@datagrok-libraries/utils": "^4.3.0",
14
+ "@datagrok-libraries/utils": "^4.5.7",
15
+ "@types/seedrandom": "^3.0.8",
15
16
  "cash-dom": "^8.0.0",
16
17
  "datagrok-api": "^1.20.0",
17
18
  "dayjs": "^1.11.7",
18
19
  "jstat": "^1.9.6",
19
- "seedrandom": "^3.0.5",
20
- "@types/seedrandom": "^3.0.8"
20
+ "konva": "^9.3.20",
21
+ "rxjs": "^6.5.5",
22
+ "seedrandom": "^3.0.5"
21
23
  },
22
24
  "devDependencies": {
23
25
  "@typescript-eslint/eslint-plugin": "^8.8.1",
24
26
  "@typescript-eslint/parser": "^8.8.1",
27
+ "datagrok-tools": "^4.14.20",
25
28
  "eslint": "^8.57.1",
26
29
  "eslint-config-google": "^0.14.0",
27
30
  "ts-loader": "^9.2.6",
@@ -35,9 +38,9 @@
35
38
  "debug-statistics": "grok publish",
36
39
  "release-statistics": "grok publish --release",
37
40
  "build-statistics": "tsc",
38
- "build": "tsc",
41
+ "build": "grok check --soft && tsc",
39
42
  "lint": "eslint src --ext .ts",
40
43
  "lint-fix": "eslint src --ext .ts --fix",
41
44
  "build-all": "npm --prefix ./../../js-api run build && npm --prefix ./../../libraries/utils run build && npm run build"
42
45
  }
43
- }
46
+ }
@@ -0,0 +1,10 @@
1
+ import { DesirabilityLine, PropertyDesirability } from './mpo';
2
+ import { Subject } from 'rxjs';
3
+ export declare class MpoDesirabilityLineEditor {
4
+ root: HTMLDivElement;
5
+ onChanged: Subject<unknown>;
6
+ private _prop;
7
+ constructor(prop: PropertyDesirability, width: number, height: number);
8
+ get line(): DesirabilityLine;
9
+ }
10
+ //# sourceMappingURL=mpo-line-editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mpo-line-editor.d.ts","sourceRoot":"","sources":["mpo-line-editor.ts"],"names":[],"mappings":"AAKA,OAAO,EAAC,gBAAgB,EAAE,oBAAoB,EAAC,MAAM,OAAO,CAAC;AAC7D,OAAO,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;AAO7B,qBAAa,yBAAyB;IACpC,IAAI,iBAAY;IAChB,SAAS,mBAAiB;IAC1B,OAAO,CAAC,KAAK,CAAuB;gBAExB,IAAI,EAAE,oBAAoB,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IA6PrE,IAAI,IAAI,IAAI,gBAAgB,CAE3B;CACF"}
@@ -0,0 +1,258 @@
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=
@@ -0,0 +1,13 @@
1
+ import * as DG from 'datagrok-api/dg';
2
+ import { DesirabilityProfile } from './mpo';
3
+ import { Subject } from 'rxjs';
4
+ export declare class MpoProfileEditor {
5
+ root: HTMLDivElement;
6
+ dataFrame?: DG.DataFrame;
7
+ onChanged: Subject<unknown>;
8
+ profile?: DesirabilityProfile;
9
+ constructor(dataFrame?: DG.DataFrame);
10
+ getProfile(): DesirabilityProfile | undefined;
11
+ setProfile(profile?: DesirabilityProfile): void;
12
+ }
13
+ //# sourceMappingURL=mpo-profile-editor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mpo-profile-editor.d.ts","sourceRoot":"","sources":["mpo-profile-editor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAGtC,OAAO,EAAC,mBAAmB,EAAC,MAAM,OAAO,CAAC;AAE1C,OAAO,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;AAG7B,qBAAa,gBAAgB;IAC3B,IAAI,iBAAc;IAClB,SAAS,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC;IACzB,SAAS,mBAAiB;IAC1B,OAAO,CAAC,EAAE,mBAAmB,CAAC;gBAElB,SAAS,CAAC,EAAE,EAAE,CAAC,SAAS;IAKpC,UAAU,IAAI,mBAAmB,GAAG,SAAS;IAI7C,UAAU,CAAC,OAAO,CAAC,EAAE,mBAAmB;CAsEzC"}
@@ -0,0 +1,79 @@
1
+ import * as ui from 'datagrok-api/ui';
2
+ import { MpoDesirabilityLineEditor } from './mpo-line-editor';
3
+ import { Subject } from 'rxjs';
4
+ export class MpoProfileEditor {
5
+ constructor(dataFrame) {
6
+ this.root = ui.div([]);
7
+ this.onChanged = new Subject();
8
+ this.dataFrame = dataFrame;
9
+ this.setProfile();
10
+ }
11
+ getProfile() {
12
+ return this.profile;
13
+ }
14
+ setProfile(profile) {
15
+ this.profile = profile;
16
+ ui.empty(this.root);
17
+ if (!profile) {
18
+ this.root.append(ui.divText('No profile specified.'));
19
+ return;
20
+ }
21
+ // Create header row for the table
22
+ const header = ui.divH([
23
+ ui.divText('Property', { style: { fontWeight: 'bold', width: '150px' } }),
24
+ ui.divText('Weight', { style: { fontWeight: 'bold', width: '60px' } }),
25
+ ui.divText('Desirability', { style: { fontWeight: 'bold', flexGrow: '1' } }), // Let editor take space
26
+ ], { style: {
27
+ marginTop: '10px',
28
+ paddingBottom: '5px',
29
+ borderBottom: '1px solid #ccc',
30
+ },
31
+ });
32
+ const propertyRows = Object.entries(profile.properties).map(([propertyName, prop]) => {
33
+ var _a, _b, _c;
34
+ const lineEditor = new MpoDesirabilityLineEditor(prop, 300, 80);
35
+ lineEditor.onChanged.subscribe((_) => this.onChanged.next());
36
+ // Input for weight - updates the *copy* of the template data
37
+ const weightInput = ui.input.float('', {
38
+ value: prop.weight, min: 0, max: 1,
39
+ onValueChanged: (newValue) => {
40
+ if (profile && profile.properties[propertyName]) {
41
+ // Update the weight in the temporary template object
42
+ let clampedWeight = newValue !== null && newValue !== void 0 ? newValue : 0;
43
+ clampedWeight = Math.max(0, Math.min(1, clampedWeight)); // Clamp 0-1
44
+ profile.properties[propertyName].weight = clampedWeight;
45
+ }
46
+ },
47
+ });
48
+ weightInput.root.style.width = '60px';
49
+ weightInput.root.style.marginTop = '21px';
50
+ const matchedColumnName = this.dataFrame ?
51
+ this.dataFrame.columns.names().find((name) => name.toLowerCase() == propertyName.toLowerCase()) :
52
+ null;
53
+ const columnInput = ui.input.choice('', {
54
+ nullable: true,
55
+ items: (_c = (_b = (_a = this.dataFrame) === null || _a === void 0 ? void 0 : _a.columns) === null || _b === void 0 ? void 0 : _b.names()) !== null && _c !== void 0 ? _c : [''],
56
+ value: matchedColumnName !== null && matchedColumnName !== void 0 ? matchedColumnName : ''
57
+ });
58
+ const rowDiv = ui.divH([
59
+ ui.divV([
60
+ ui.divText(propertyName, { style: { width: '150px', paddingTop: '5px', marginLeft: '4px' } }),
61
+ this.dataFrame ? columnInput.root : null,
62
+ ]),
63
+ weightInput.root,
64
+ lineEditor.root, // Add the Konva container div
65
+ ]);
66
+ rowDiv.style.alignItems = 'center'; // Vertically align items in the row
67
+ rowDiv.style.marginBottom = '5px'; // Space between rows
68
+ rowDiv.style.minHeight = '70px'; // Ensure consistent row height even if editor takes time
69
+ return rowDiv;
70
+ }).filter((el) => el !== null); // Filter out skipped properties
71
+ if (propertyRows.length > 0) {
72
+ this.root.append(header);
73
+ this.root.append(ui.divV(propertyRows)); // Cast needed after filter
74
+ }
75
+ else
76
+ this.root.append(ui.divText('No matching properties found in the table for this template.'));
77
+ }
78
+ }
79
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXBvLXByb2ZpbGUtZWRpdG9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibXBvLXByb2ZpbGUtZWRpdG9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUNBLE9BQU8sS0FBSyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFHdEMsT0FBTyxFQUFDLHlCQUF5QixFQUFDLE1BQU0sbUJBQW1CLENBQUM7QUFDNUQsT0FBTyxFQUFDLE9BQU8sRUFBQyxNQUFNLE1BQU0sQ0FBQztBQUc3QixNQUFNLE9BQU8sZ0JBQWdCO0lBTTNCLFlBQVksU0FBd0I7UUFMcEMsU0FBSSxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUM7UUFFbEIsY0FBUyxHQUFHLElBQUksT0FBTyxFQUFFLENBQUM7UUFJeEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUM7UUFDM0IsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDO0lBQ3BCLENBQUM7SUFFRCxVQUFVO1FBQ1IsT0FBTyxJQUFJLENBQUMsT0FBTyxDQUFDO0lBQ3RCLENBQUM7SUFFRCxVQUFVLENBQUMsT0FBNkI7UUFDdEMsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEIsSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNaLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsdUJBQXVCLENBQUMsQ0FBQyxDQUFDO1lBQ3RELE9BQU87U0FDUjtRQUVELGtDQUFrQztRQUNsQyxNQUFNLE1BQU0sR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDO1lBQ3JCLEVBQUUsQ0FBQyxPQUFPLENBQUMsVUFBVSxFQUFFLEVBQUMsS0FBSyxFQUFFLEVBQUMsVUFBVSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsT0FBTyxFQUFDLEVBQUMsQ0FBQztZQUNyRSxFQUFFLENBQUMs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QVksRUFBRSxFQUFDLEtBQUssRUFBRSxFQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQUUsS0FBSyxFQUFDLEVBQUMsQ0FBQztvQkFDekYsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSTtpQkFDekMsQ0FBQztnQkFDRixXQUFXLENBQUMsSUFBSTtnQkFDaEIsVUFBVSxDQUFDLElBQUksRUFBRSw4QkFBOEI7YUFDaEQsQ0FBQyxDQUFDO1lBQ0gsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLEdBQUcsUUFBUSxDQUFDLENBQUMsb0NBQW9DO1lBQ3hFLE1BQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQyxDQUFDLHFCQUFxQjtZQUN4RCxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsR0FBRyxNQUFNLENBQUMsQ0FBQyx5REFBeUQ7WUFFMUYsT0FBTyxNQUFNLENBQUM7UUFDaEIsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxnQ0FBZ0M7UUFFaEUsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUMzQixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUN6QixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLFlBQTZCLENBQUMsQ0FBQyxDQUFDLENBQUMsMkJBQTJCO1NBQ3RGOztZQUNDLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsOERBQThELENBQUMsQ0FBQyxDQUFDO0lBQ2pHLENBQUM7Q0FDRiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIERHIGZyb20gJ2RhdGFncm9rLWFwaS9kZyc7XG5pbXBvcnQgKiBhcyB1aSBmcm9tICdkYXRhZ3Jvay1hcGkvdWknO1xuXG5pbXBvcnQge0Rlc2lyYWJpbGl0eVByb2ZpbGV9IGZyb20gJy4vbXBvJztcbmltcG9ydCB7TXBvRGVzaXJhYmlsaXR5TGluZUVkaXRvcn0gZnJvbSAnLi9tcG8tbGluZS1lZGl0b3InO1xuaW1wb3J0IHtTdWJqZWN0fSBmcm9tICdyeGpzJztcblxuXG5leHBvcnQgY2xhc3MgTXBvUHJvZmlsZUVkaXRvciB7XG4gIHJvb3QgPSB1aS5kaXYoW10pO1xuICBkYXRhRnJhbWU/OiBERy5EYXRhRnJhbWU7XG4gIG9uQ2hhbmdlZCA9IG5ldyBTdWJqZWN0KCk7XG4gIHByb2ZpbGU/OiBEZXNpcmFiaWxpdHlQcm9maWxlO1xuXG4gIGNvbnN0cnVjdG9yKGRhdGFGcmFtZT86IERHLkRhdGFGcmFtZSkge1xuICAgIHRoaXMuZGF0YUZyYW1lID0gZGF0YUZyYW1lO1xuICAgIHRoaXMuc2V0UHJvZmlsZSgpO1xuICB9XG5cbiAgZ2V0UHJvZmlsZSgpOiBEZXNpcmFiaWxpdHlQcm9maWxlIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5wcm9maWxlO1xuICB9XG5cbiAgc2V0UHJvZmlsZShwcm9maWxlPzogRGVzaXJhYmlsaXR5UHJvZmlsZSkge1xuICAgIHRoaXMucHJvZmlsZSA9IHByb2ZpbGU7XG4gICAgdWkuZW1wdHkodGhpcy5yb290KTtcbiAgICBpZiAoIXByb2ZpbGUpIHtcbiAgICAgIHRoaXMucm9vdC5hcHBlbmQodWkuZGl2VGV4dCgnTm8gcHJvZmlsZSBzcGVjaWZpZWQuJykpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENyZWF0ZSBoZWFkZXIgcm93IGZvciB0aGUgdGFibGVcbiAgICBjb25zdCBoZWFkZXIgPSB1aS5kaXZIKFtcbiAgICAgIHVpLmRpdlRleHQoJ1Byb3BlcnR5Jywge3N0eWxlOiB7Zm9udFdlaWdodDogJ2JvbGQnLCB3aWR0aDogJzE1MHB4J319KSxcbiAgICAgIHVpLmRpdlRleHQoJ1dlaWdodCcsIHtzdHlsZToge2ZvbnRXZWlnaHQ6ICdib2xkJywgd2lkdGg6ICc2MHB4J319KSxcbiAgICAgIHVpLmRpdlRleHQoJ0Rlc2lyYWJpbGl0eScsIHtzdHlsZToge2ZvbnRXZWlnaHQ6ICdib2xkJywgZmxleEdyb3c6ICcxJ319KSwgLy8gTGV0IGVkaXRvciB0YWtlIHNwYWNlXG4gICAgXSwge3N0eWxlOiB7XG4gICAgICBtYXJnaW5Ub3A6ICcxMHB4JyxcbiAgICAgIHBhZGRpbmdCb3R0b206ICc1cHgnLFxuICAgICAgYm9yZGVyQm90dG9tOiAnMXB4IHNvbGlkICNjY2MnLFxuICAgIH0sXG4gICAgfSk7XG5cbiAgICBjb25zdCBwcm9wZXJ0eVJvd3MgPSBPYmplY3QuZW50cmllcyhwcm9maWxlLnByb3BlcnRpZXMpLm1hcCgoW3Byb3BlcnR5TmFtZSwgcHJvcF0pID0+IHtcbiAgICAgIGNvbnN0IGxpbmVFZGl0b3IgPSBuZXcgTXBvRGVzaXJhYmlsaXR5TGluZUVkaXRvcihwcm9wLCAzMDAsIDgwKTtcbiAgICAgIGxpbmVFZGl0b3Iub25DaGFuZ2VkLnN1YnNjcmliZSgoXykgPT4gdGhpcy5vbkNoYW5nZWQubmV4dCgpKTtcblxuICAgICAgLy8gSW5wdXQgZm9yIHdlaWdodCAtIHVwZGF0ZXMgdGhlICpjb3B5KiBvZiB0aGUgdGVtcGxhdGUgZGF0YVxuICAgICAgY29uc3Qgd2VpZ2h0SW5wdXQgPSB1aS5pbnB1dC5mbG9hdCgnJywgeyAvLyBObyBsYWJlbCBuZWVkZWQgaGVyZVxuICAgICAgICB2YWx1ZTogcHJvcC53ZWlnaHQsIG1pbjogMCwgbWF4OiAxLFxuICAgICAgICBvblZhbHVlQ2hhbmdlZDogKG5ld1ZhbHVlKSA9PiB7IC8vIENoYW5nZWQgcGFyYW1ldGVyIG5hbWUgZm9yIGNsYXJpdHlcbiAgICAgICAgICBpZiAocHJvZmlsZSAmJiBwcm9maWxlLnByb3BlcnRpZXNbcHJvcGVydHlOYW1lXSkge1xuICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSB3ZWlnaHQgaW4gdGhlIHRlbXBvcmFyeSB0ZW1wbGF0ZSBvYmplY3RcbiAgICAgICAgICAgIGxldCBjbGFtcGVkV2VpZ2h0ID0gbmV3VmFsdWUgPz8gMDtcbiAgICAgICAgICAgIGNsYW1wZWRXZWlnaHQgPSBNYXRoLm1heCgwLCBNYXRoLm1pbigxLCBjbGFtcGVkV2VpZ2h0KSk7IC8vIENsYW1wIDAtMVxuICAgICAgICAgICAgcHJvZmlsZS5wcm9wZXJ0aWVzW3Byb3BlcnR5TmFtZV0ud2VpZ2h0ID0gY2xhbXBlZFdlaWdodDtcbiAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgICB9KTtcblxuICAgICAgd2VpZ2h0SW5wdXQucm9vdC5zdHlsZS53aWR0aCA9ICc2MHB4JztcbiAgICAgIHdlaWdodElucHV0LnJvb3Quc3R5bGUubWFyZ2luVG9wID0gJzIxcHgnO1xuXG4gICAgICBjb25zdCBtYXRjaGVkQ29sdW1uTmFtZSA9IHRoaXMuZGF0YUZyYW1lID9cbiAgICAgICAgdGhpcy5kYXRhRnJhbWUuY29sdW1ucy5uYW1lcygpLmZpbmQoKG5hbWUpID0+IG5hbWUudG9Mb3dlckNhc2UoKSA9PSBwcm9wZXJ0eU5hbWUudG9Mb3dlckNhc2UoKSkgOlxuICAgICAgICBudWxsO1xuXG4gICAgICBjb25zdCBjb2x1bW5JbnB1dCA9IHVpLmlucHV0LmNob2ljZSgnJywge1xuICAgICAgICBudWxsYWJsZTogdHJ1ZSxcbiAgICAgICAgaXRlbXM6IHRoaXMuZGF0YUZyYW1lPy5jb2x1bW5zPy5uYW1lcygpID8/IFsnJ10sXG4gICAgICAgIHZhbHVlOiBtYXRjaGVkQ29sdW1uTmFtZSA/PyAnJ30pO1xuXG4gICAgICBjb25zdCByb3dEaXYgPSB1aS5kaXZIKFtcbiAgICAgICAgdWkuZGl2VihbXG4gICAgICAgICAgdWkuZGl2VGV4dChwcm9wZXJ0eU5hbWUsIHtzdHlsZToge3dpZHRoOiAnMTUwcHgnLCBwYWRkaW5nVG9wOiAnNXB4JywgbWFyZ2luTGVmdDogJzRweCd9fSksXG4gICAgICAgICAgdGhpcy5kYXRhRnJhbWUgPyBjb2x1bW5JbnB1dC5yb290IDogbnVsbCxcbiAgICAgICAgXSksXG4gICAgICAgIHdlaWdodElucHV0LnJvb3QsXG4gICAgICAgIGxpbmVFZGl0b3Iucm9vdCwgLy8gQWRkIHRoZSBLb252YSBjb250YWluZXIgZGl2XG4gICAgICBdKTtcbiAgICAgIHJvd0Rpdi5zdHlsZS5hbGlnbkl0ZW1zID0gJ2NlbnRlcic7IC8vIFZlcnRpY2FsbHkgYWxpZ24gaXRlbXMgaW4gdGhlIHJvd1xuICAgICAgcm93RGl2LnN0eWxlLm1hcmdpbkJvdHRvbSA9ICc1cHgnOyAvLyBTcGFjZSBiZXR3ZWVuIHJvd3NcbiAgICAgIHJvd0Rpdi5zdHlsZS5taW5IZWlnaHQgPSAnNzBweCc7IC8vIEVuc3VyZSBjb25zaXN0ZW50IHJvdyBoZWlnaHQgZXZlbiBpZiBlZGl0b3IgdGFrZXMgdGltZVxuXG4gICAgICByZXR1cm4gcm93RGl2O1xuICAgIH0pLmZpbHRlcigoZWwpID0+IGVsICE9PSBudWxsKTsgLy8gRmlsdGVyIG91dCBza2lwcGVkIHByb3BlcnRpZXNcblxuICAgIGlmIChwcm9wZXJ0eVJvd3MubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5yb290LmFwcGVuZChoZWFkZXIpO1xuICAgICAgdGhpcy5yb290LmFwcGVuZCh1aS5kaXZWKHByb3BlcnR5Um93cyBhcyBIVE1MRWxlbWVudFtdKSk7IC8vIENhc3QgbmVlZGVkIGFmdGVyIGZpbHRlclxuICAgIH0gZWxzZVxuICAgICAgdGhpcy5yb290LmFwcGVuZCh1aS5kaXZUZXh0KCdObyBtYXRjaGluZyBwcm9wZXJ0aWVzIGZvdW5kIGluIHRoZSB0YWJsZSBmb3IgdGhpcyB0ZW1wbGF0ZS4nKSk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,19 @@
1
+ import * as DG from 'datagrok-api/dg';
2
+ export type DesirabilityLine = number[][];
3
+ export type PropertyDesirability = {
4
+ line: DesirabilityLine;
5
+ min?: number;
6
+ max?: number;
7
+ weight: number;
8
+ };
9
+ export type DesirabilityProfile = {
10
+ name: string;
11
+ description: string;
12
+ properties: {
13
+ [key: string]: PropertyDesirability;
14
+ };
15
+ };
16
+ export declare function desirabilityScore(x: number, desirabilityLine: DesirabilityLine): number;
17
+ /** Calculates the multi parameter optimization score, 0-100, 100 is the maximum */
18
+ export declare function mpo(dataFrame: DG.DataFrame, columns: DG.Column[]): DG.Column;
19
+ //# sourceMappingURL=mpo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mpo.d.ts","sourceRoot":"","sources":["mpo.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAItC,MAAM,MAAM,gBAAgB,GAAG,MAAM,EAAE,EAAE,CAAC;AAG1C,MAAM,MAAM,oBAAoB,GAAG;IACjC,IAAI,EAAE,gBAAgB,CAAC;IACvB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CAChB,CAAA;AAGD,MAAM,MAAM,mBAAmB,GAAG;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAAA;KAAE,CAAC;CACrD,CAAA;AAKD,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,gBAAgB,GAAG,MAAM,CAoBvF;AAED,mFAAmF;AACnF,wBAAgB,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,MAAM,CA8B5E"}
package/src/mpo/mpo.js ADDED
@@ -0,0 +1,52 @@
1
+ /* eslint-disable guard-for-in */
2
+ /* eslint-disable max-len */
3
+ import * as DG from 'datagrok-api/dg';
4
+ /// Calculates the desirability score for a given x value
5
+ /// Returns 0 if x is outside the range of the desirability line
6
+ /// Otherwise, returns the y value of the desirability line at x
7
+ export function desirabilityScore(x, desirabilityLine) {
8
+ // If the line is empty or x is outside the range, return 0
9
+ if (desirabilityLine.length === 0 || x < desirabilityLine[0][0] || x > desirabilityLine[desirabilityLine.length - 1][0])
10
+ return 0;
11
+ // Find the two points that x lies between
12
+ for (let i = 0; i < desirabilityLine.length - 1; i++) {
13
+ const [x1, y1] = desirabilityLine[i];
14
+ const [x2, y2] = desirabilityLine[i + 1];
15
+ if (x >= x1 && x <= x2) {
16
+ // Linear interpolation between the two points
17
+ if (x1 === x2)
18
+ return y1;
19
+ const slope = (y2 - y1) / (x2 - x1);
20
+ return y1 + slope * (x - x1);
21
+ }
22
+ }
23
+ // Should not happen if x is within bounds, but return 0 as fallback
24
+ return 0;
25
+ }
26
+ /** Calculates the multi parameter optimization score, 0-100, 100 is the maximum */
27
+ export function mpo(dataFrame, columns) {
28
+ if (columns.length === 0)
29
+ throw new Error('No columns provided for MPO calculation.');
30
+ const resultColumnName = dataFrame.columns.getUnusedName('MPO'); // Ensure unique name
31
+ const resultColumn = DG.Column.float(resultColumnName, columns[0].length);
32
+ const desirabilityTemplates = columns.map((column) => {
33
+ const tag = column.getTag('desirabilityTemplate');
34
+ return JSON.parse(tag);
35
+ });
36
+ resultColumn.init((i) => {
37
+ let totalScore = 0;
38
+ let maxScore = 0;
39
+ for (let j = 0; j < columns.length; j++) {
40
+ const desirability = desirabilityTemplates[j];
41
+ const value = columns[j].get(i);
42
+ const score = desirabilityScore(value, desirability.line);
43
+ totalScore += desirability.weight * score;
44
+ maxScore += desirability.weight;
45
+ }
46
+ return 100 * (totalScore / maxScore);
47
+ });
48
+ // Add the column to the table
49
+ dataFrame.columns.add(resultColumn);
50
+ return resultColumn;
51
+ }
52
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibXBvLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsibXBvLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLGlDQUFpQztBQUNqQyw0QkFBNEI7QUFDNUIsT0FBTyxLQUFLLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQXFCdEMseURBQXlEO0FBQ3pELGdFQUFnRTtBQUNoRSxnRUFBZ0U7QUFDaEUsTUFBTSxVQUFVLGlCQUFpQixDQUFDLENBQVMsRUFBRSxnQkFBa0M7SUFDN0UsMkRBQTJEO0lBQzNELElBQUksZ0JBQWdCLENBQUMsTUFBTSxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsZ0JBQWdCLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLGdCQUFnQixDQUFDLGdCQUFnQixDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDckgsT0FBTyxDQUFDLENBQUM7SUFFWCwwQ0FBMEM7SUFDMUMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLGdCQUFnQixDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7UUFDcEQsTUFBTSxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsR0FBRyxnQkFBZ0IsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNyQyxNQUFNLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLGdCQUFnQixDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUV6QyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRTtZQUN0Qiw4Q0FBOEM7WUFDOUMsSUFBSSxFQUFFLEtBQUssRUFBRTtnQkFBRSxPQUFPLEVBQUUsQ0FBQztZQUN6QixNQUFNLEtBQUssR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUNwQyxPQUFPLEVBQUUsR0FBRyxLQUFLLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUM7U0FDOUI7S0FDRjtJQUVELG9FQUFvRTtJQUNwRSxPQUFPLENBQUMsQ0FBQztBQUNYLENBQUM7QUFFRCxtRkFBbUY7QUFDbkYsTUFBTSxVQUFVLEdBQUcsQ0FBQyxTQUF1QixFQUFFLE9BQW9CO0lBQy9ELElBQUksT0FBTyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQ3RCLE1BQU0sSUFBSSxLQUFLLENBQUMsMENBQTBDLENBQUMsQ0FBQztJQUU5RCxNQUFNLGdCQUFnQixHQUFHLFNBQVMsQ0FBQyxPQUFPLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMscUJBQXFCO0lBQ3RGLE1BQU0sWUFBWSxHQUFHLEVBQUUsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLGdCQUFnQixFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUUxRSxNQUFNLHFCQUFxQixHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtRQUNuRCxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLHNCQUFzQixDQUFDLENBQUM7UUFDbEQsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBeUIsQ0FBQztJQUNqRCxDQUFDLENBQUMsQ0FBQztJQUVILFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTtRQUN0QixJQUFJLFVBQVUsR0FBRyxDQUFDLENBQUM7UUFDbkIsSUFBSSxRQUFRLEdBQUcsQ0FBQyxDQUFDO1FBRWpCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxPQUFPLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ3ZDLE1BQU0sWUFBWSxHQUFHLHFCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzlDLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDaEMsTUFBTSxLQUFLLEdBQUcsaUJBQWlCLENBQUMsS0FBSyxFQUFFLFlBQVksQ0FBQyxJQUFJLENBQUMsQ0FBQztZQUMxRCxVQUFVLElBQUksWUFBWSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7WUFDMUMsUUFBUSxJQUFJLFlBQVksQ0FBQyxNQUFNLENBQUM7U0FDakM7UUFFRCxPQUFPLEdBQUcsR0FBRyxDQUFDLFVBQVUsR0FBRyxRQUFRLENBQUMsQ0FBQztJQUN2QyxDQUFDLENBQUMsQ0FBQztJQUVILDhCQUE4QjtJQUM5QixTQUFTLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQztJQUNwQyxPQUFPLFlBQVksQ0FBQztBQUN0QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyogZXNsaW50LWRpc2FibGUgZ3VhcmQtZm9yLWluICovXG4vKiBlc2xpbnQtZGlzYWJsZSBtYXgtbGVuICovXG5pbXBvcnQgKiBhcyBERyBmcm9tICdkYXRhZ3Jvay1hcGkvZGcnO1xuXG4vLy8gQW4gYXJyYXkgb2YgW3gsIHldIHBvaW50cyByZXByZXNlbnRpbmcgdGhlIGRlc2lyYWJpbGl0eSBsaW5lXG4vLy8gW3gsIHldIHBhaXJzIGFyZSBzb3J0ZWQgYnkgeCBpbiBhc2NlbmRpbmcgb3JkZXJcbmV4cG9ydCB0eXBlIERlc2lyYWJpbGl0eUxpbmUgPSBudW1iZXJbXVtdO1xuXG4vLy8gQSBkZXNpcmFiaWxpdHkgbGluZSB3aXRoIGl0cyB3ZWlnaHRcbmV4cG9ydCB0eXBlIFByb3BlcnR5RGVzaXJhYmlsaXR5ID0ge1xuICBsaW5lOiBEZXNpcmFiaWxpdHlMaW5lO1xuICBtaW4/OiBudW1iZXI7IC8vLyBtaW4gdmFsdWUgb2YgdGhlIHByb3BlcnR5IChvcHRpb25hbDsgdXNlZCBmb3IgZWRpdGluZyB0aGUgbGluZSlcbiAgbWF4PzogbnVtYmVyOyAvLy8gbWF4IHZhbHVlIG9mIHRoZSBwcm9wZXJ0eSAob3B0aW9uYWw7IHVzZWQgZm9yIGVkaXRpbmcgdGhlIGxpbmUpXG4gIHdlaWdodDogbnVtYmVyOyAvLy8gMC0xXG59XG5cbi8vLyBBIG1hcCBvZiBkZXNpcmFiaWxpdHkgbGluZXMgd2l0aCB0aGVpciB3ZWlnaHRzXG5leHBvcnQgdHlwZSBEZXNpcmFiaWxpdHlQcm9maWxlID0ge1xuICBuYW1lOiBzdHJpbmc7XG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIHByb3BlcnRpZXM6IHsgW2tleTogc3RyaW5nXTogUHJvcGVydHlEZXNpcmFiaWxpdHkgfTtcbn1cblxuLy8vIENhbGN1bGF0ZXMgdGhlIGRlc2lyYWJpbGl0eSBzY29yZSBmb3IgYSBnaXZlbiB4IHZhbHVlXG4vLy8gUmV0dXJucyAwIGlmIHggaXMgb3V0c2lkZSB0aGUgcmFuZ2Ugb2YgdGhlIGRlc2lyYWJpbGl0eSBsaW5lXG4vLy8gT3RoZXJ3aXNlLCByZXR1cm5zIHRoZSB5IHZhbHVlIG9mIHRoZSBkZXNpcmFiaWxpdHkgbGluZSBhdCB4XG5leHBvcnQgZnVuY3Rpb24gZGVzaXJhYmlsaXR5U2NvcmUoeDogbnVtYmVyLCBkZXNpcmFiaWxpdHlMaW5lOiBEZXNpcmFiaWxpdHlMaW5lKTogbnVtYmVyIHtcbiAgLy8gSWYgdGhlIGxpbmUgaXMgZW1wdHkgb3IgeCBpcyBvdXRzaWRlIHRoZSByYW5nZSwgcmV0dXJuIDBcbiAgaWYgKGRlc2lyYWJpbGl0eUxpbmUubGVuZ3RoID09PSAwIHx8IHggPCBkZXNpcmFiaWxpdHlMaW5lWzBdWzBdIHx8IHggPiBkZXNpcmFiaWxpdHlMaW5lW2Rlc2lyYWJpbGl0eUxpbmUubGVuZ3RoIC0gMV1bMF0pXG4gICAgcmV0dXJuIDA7XG5cbiAgLy8gRmluZCB0aGUgdHdvIHBvaW50cyB0aGF0IHggbGllcyBiZXR3ZWVuXG4gIGZvciAobGV0IGkgPSAwOyBpIDwgZGVzaXJhYmlsaXR5TGluZS5sZW5ndGggLSAxOyBpKyspIHtcbiAgICBjb25zdCBbeDEsIHkxXSA9IGRlc2lyYWJpbGl0eUxpbmVbaV07XG4gICAgY29uc3QgW3gyLCB5Ml0gPSBkZXNpcmFiaWxpdHlMaW5lW2kgKyAxXTtcblxuICAgIGlmICh4ID49IHgxICYmIHggPD0geDIpIHtcbiAgICAgIC8vIExpbmVhciBpbnRlcnBvbGF0aW9uIGJldHdlZW4gdGhlIHR3byBwb2ludHNcbiAgICAgIGlmICh4MSA9PT0geDIpIHJldHVybiB5MTtcbiAgICAgIGNvbnN0IHNsb3BlID0gKHkyIC0geTEpIC8gKHgyIC0geDEpO1xuICAgICAgcmV0dXJuIHkxICsgc2xvcGUgKiAoeCAtIHgxKTtcbiAgICB9XG4gIH1cblxuICAvLyBTaG91bGQgbm90IGhhcHBlbiBpZiB4IGlzIHdpdGhpbiBib3VuZHMsIGJ1dCByZXR1cm4gMCBhcyBmYWxsYmFja1xuICByZXR1cm4gMDtcbn1cblxuLyoqIENhbGN1bGF0ZXMgdGhlIG11bHRpIHBhcmFtZXRlciBvcHRpbWl6YXRpb24gc2NvcmUsIDAtMTAwLCAxMDAgaXMgdGhlIG1heGltdW0gKi9cbmV4cG9ydCBmdW5jdGlvbiBtcG8oZGF0YUZyYW1lOiBERy5EYXRhRnJhbWUsIGNvbHVtbnM6IERHLkNvbHVtbltdKTogREcuQ29sdW1uIHtcbiAgaWYgKGNvbHVtbnMubGVuZ3RoID09PSAwKVxuICAgIHRocm93IG5ldyBFcnJvcignTm8gY29sdW1ucyBwcm92aWRlZCBmb3IgTVBPIGNhbGN1bGF0aW9uLicpO1xuXG4gIGNvbnN0IHJlc3VsdENvbHVtbk5hbWUgPSBkYXRhRnJhbWUuY29sdW1ucy5nZXRVbnVzZWROYW1lKCdNUE8nKTsgLy8gRW5zdXJlIHVuaXF1ZSBuYW1lXG4gIGNvbnN0IHJlc3VsdENvbHVtbiA9IERHLkNvbHVtbi5mbG9hdChyZXN1bHRDb2x1bW5OYW1lLCBjb2x1bW5zWzBdLmxlbmd0aCk7XG5cbiAgY29uc3QgZGVzaXJhYmlsaXR5VGVtcGxhdGVzID0gY29sdW1ucy5tYXAoKGNvbHVtbikgPT4ge1xuICAgIGNvbnN0IHRhZyA9IGNvbHVtbi5nZXRUYWcoJ2Rlc2lyYWJpbGl0eVRlbXBsYXRlJyk7XG4gICAgcmV0dXJuIEpTT04ucGFyc2UodGFnKSBhcyBQcm9wZXJ0eURlc2lyYWJpbGl0eTtcbiAgfSk7XG5cbiAgcmVzdWx0Q29sdW1uLmluaXQoKGkpID0+IHtcbiAgICBsZXQgdG90YWxTY29yZSA9IDA7XG4gICAgbGV0IG1heFNjb3JlID0gMDtcblxuICAgIGZvciAobGV0IGogPSAwOyBqIDwgY29sdW1ucy5sZW5ndGg7IGorKykge1xuICAgICAgY29uc3QgZGVzaXJhYmlsaXR5ID0gZGVzaXJhYmlsaXR5VGVtcGxhdGVzW2pdO1xuICAgICAgY29uc3QgdmFsdWUgPSBjb2x1bW5zW2pdLmdldChpKTtcbiAgICAgIGNvbnN0IHNjb3JlID0gZGVzaXJhYmlsaXR5U2NvcmUodmFsdWUsIGRlc2lyYWJpbGl0eS5saW5lKTtcbiAgICAgIHRvdGFsU2NvcmUgKz0gZGVzaXJhYmlsaXR5LndlaWdodCAqIHNjb3JlO1xuICAgICAgbWF4U2NvcmUgKz0gZGVzaXJhYmlsaXR5LndlaWdodDtcbiAgICB9XG5cbiAgICByZXR1cm4gMTAwICogKHRvdGFsU2NvcmUgLyBtYXhTY29yZSk7XG4gIH0pO1xuXG4gIC8vIEFkZCB0aGUgY29sdW1uIHRvIHRoZSB0YWJsZVxuICBkYXRhRnJhbWUuY29sdW1ucy5hZGQocmVzdWx0Q29sdW1uKTtcbiAgcmV0dXJuIHJlc3VsdENvbHVtbjtcbn1cbiJdfQ==