@visuno/angular 0.0.0-stage → 0.1.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/LICENSE +24 -0
- package/README.md +56 -2
- package/account-table/account-table.component.d.ts +72 -0
- package/action-log/action-log.component.d.ts +41 -0
- package/activity-heatmap/activity-heatmap.component.d.ts +67 -0
- package/agent-inbox/agent-inbox.component.d.ts +75 -0
- package/agent-lanes/agent-lanes.component.d.ts +152 -0
- package/agent-phases/agent-phases.component.d.ts +62 -0
- package/agent-run-timeline/agent-run-timeline.component.d.ts +113 -0
- package/agent-tree/agent-tree.component.d.ts +80 -0
- package/answer-action-bar/answer-action-bar.component.d.ts +110 -0
- package/artifact-card/artifact-card.component.d.ts +145 -0
- package/attachment-tray/attachment-tray.component.d.ts +84 -0
- package/badge/badge.component.d.ts +25 -0
- package/bar-chart/bar-chart.component.d.ts +87 -0
- package/browser-session/browser-session.component.d.ts +70 -0
- package/buttons/buttons.component.d.ts +63 -0
- package/card/card.component.d.ts +21 -0
- package/change-review/change-review.component.d.ts +97 -0
- package/citation-hover-card/citation-hover-card.component.d.ts +95 -0
- package/code-viewer/code-viewer.component.d.ts +86 -0
- package/composer/composer.component.d.ts +114 -0
- package/context-meter/context-meter.component.d.ts +60 -0
- package/core/icon.component.d.ts +10 -0
- package/core/reduced-motion.service.d.ts +15 -0
- package/decision-prompt/decision-prompt.component.d.ts +56 -0
- package/design-review/design-review.component.d.ts +108 -0
- package/design-tuner/design-tuner.component.d.ts +75 -0
- package/details-panel/details-panel.component.d.ts +150 -0
- package/donut-chart/donut-chart.component.d.ts +63 -0
- package/draft-review/draft-review.component.d.ts +128 -0
- package/error-recovery/error-recovery.component.d.ts +59 -0
- package/esm2022/account-table/account-table.component.mjs +399 -0
- package/esm2022/action-log/action-log.component.mjs +177 -0
- package/esm2022/activity-heatmap/activity-heatmap.component.mjs +285 -0
- package/esm2022/agent-inbox/agent-inbox.component.mjs +284 -0
- package/esm2022/agent-lanes/agent-lanes.component.mjs +600 -0
- package/esm2022/agent-phases/agent-phases.component.mjs +300 -0
- package/esm2022/agent-run-timeline/agent-run-timeline.component.mjs +412 -0
- package/esm2022/agent-tree/agent-tree.component.mjs +393 -0
- package/esm2022/answer-action-bar/answer-action-bar.component.mjs +636 -0
- package/esm2022/artifact-card/artifact-card.component.mjs +916 -0
- package/esm2022/attachment-tray/attachment-tray.component.mjs +402 -0
- package/esm2022/badge/badge.component.mjs +97 -0
- package/esm2022/bar-chart/bar-chart.component.mjs +300 -0
- package/esm2022/browser-session/browser-session.component.mjs +352 -0
- package/esm2022/buttons/buttons.component.mjs +215 -0
- package/esm2022/card/card.component.mjs +107 -0
- package/esm2022/change-review/change-review.component.mjs +398 -0
- package/esm2022/citation-hover-card/citation-hover-card.component.mjs +360 -0
- package/esm2022/code-viewer/code-viewer.component.mjs +291 -0
- package/esm2022/composer/composer.component.mjs +743 -0
- package/esm2022/context-meter/context-meter.component.mjs +275 -0
- package/esm2022/core/icon.component.mjs +111 -0
- package/esm2022/core/reduced-motion.service.mjs +34 -0
- package/esm2022/decision-prompt/decision-prompt.component.mjs +259 -0
- package/esm2022/design-review/design-review.component.mjs +428 -0
- package/esm2022/design-tuner/design-tuner.component.mjs +341 -0
- package/esm2022/details-panel/details-panel.component.mjs +537 -0
- package/esm2022/donut-chart/donut-chart.component.mjs +240 -0
- package/esm2022/draft-review/draft-review.component.mjs +549 -0
- package/esm2022/error-recovery/error-recovery.component.mjs +231 -0
- package/esm2022/eval-results/eval-results.component.mjs +368 -0
- package/esm2022/feedback-sheet/feedback-sheet.component.mjs +411 -0
- package/esm2022/field-extraction/field-extraction.component.mjs +368 -0
- package/esm2022/funnel-chart/funnel-chart.component.mjs +258 -0
- package/esm2022/grid/grid.component.mjs +66 -0
- package/esm2022/health-score/health-score.component.mjs +420 -0
- package/esm2022/human-handoff/human-handoff.component.mjs +676 -0
- package/esm2022/image-generation/image-generation.component.mjs +1028 -0
- package/esm2022/inline-text-diff/inline-text-diff.component.mjs +390 -0
- package/esm2022/launch-checklist/launch-checklist.component.mjs +229 -0
- package/esm2022/line-chart/line-chart.component.mjs +417 -0
- package/esm2022/live-answer/live-answer.component.mjs +411 -0
- package/esm2022/metric-insight/metric-insight.component.mjs +511 -0
- package/esm2022/modal/modal.component.mjs +202 -0
- package/esm2022/model-picker/model-picker.component.mjs +491 -0
- package/esm2022/permission-gate/permission-gate.component.mjs +498 -0
- package/esm2022/plan-review/plan-review.component.mjs +432 -0
- package/esm2022/progress/progress.component.mjs +503 -0
- package/esm2022/prompt-library/prompt-library.component.mjs +453 -0
- package/esm2022/prompt-starters/prompt-starters.component.mjs +272 -0
- package/esm2022/proposal-card/proposal-card.component.mjs +402 -0
- package/esm2022/public-api.mjs +88 -0
- package/esm2022/radar-chart/radar-chart.component.mjs +500 -0
- package/esm2022/radial-goals/radial-goals.component.mjs +418 -0
- package/esm2022/reasoning-trail/reasoning-trail.component.mjs +284 -0
- package/esm2022/response-versions/response-versions.component.mjs +288 -0
- package/esm2022/rewrite-toolbar/rewrite-toolbar.component.mjs +397 -0
- package/esm2022/rich-text-editor/rich-text-editor.component.mjs +1755 -0
- package/esm2022/run-cost/run-cost.component.mjs +215 -0
- package/esm2022/run-queue/run-queue.component.mjs +481 -0
- package/esm2022/run-summary/run-summary.component.mjs +331 -0
- package/esm2022/scatter-chart/scatter-chart.component.mjs +705 -0
- package/esm2022/score-breakdown/score-breakdown.component.mjs +460 -0
- package/esm2022/segmented-control/segmented-control.component.mjs +180 -0
- package/esm2022/source-stack/source-stack.component.mjs +245 -0
- package/esm2022/stat-cards/stat-cards.component.mjs +258 -0
- package/esm2022/status-pill/status-pill.component.mjs +305 -0
- package/esm2022/steering/steering.component.mjs +343 -0
- package/esm2022/step-loader/step-loader.component.mjs +209 -0
- package/esm2022/task-table/task-table.component.mjs +534 -0
- package/esm2022/terminal-stream/terminal-stream.component.mjs +583 -0
- package/esm2022/thinking/thinking.component.mjs +276 -0
- package/esm2022/thinking-states/thinking-states.component.mjs +333 -0
- package/esm2022/thread-panel/thread-panel.component.mjs +271 -0
- package/esm2022/toast/toast.component.mjs +195 -0
- package/esm2022/toast-stack/toast-stack.component.mjs +301 -0
- package/esm2022/tool-call/tool-call.component.mjs +273 -0
- package/esm2022/tooltip/tooltip.component.mjs +417 -0
- package/esm2022/top-pages/top-pages.component.mjs +240 -0
- package/esm2022/trace-view/trace-view.component.mjs +440 -0
- package/esm2022/visuno-angular.mjs +5 -0
- package/esm2022/voice-capture/voice-capture.component.mjs +650 -0
- package/esm2022/voice-orb/voice-orb.component.mjs +538 -0
- package/esm2022/web-search/web-search.component.mjs +374 -0
- package/eval-results/eval-results.component.d.ts +67 -0
- package/feedback-sheet/feedback-sheet.component.d.ts +74 -0
- package/fesm2022/visuno-angular.mjs +31992 -0
- package/fesm2022/visuno-angular.mjs.map +1 -0
- package/field-extraction/field-extraction.component.d.ts +82 -0
- package/funnel-chart/funnel-chart.component.d.ts +70 -0
- package/grid/grid.component.d.ts +22 -0
- package/health-score/health-score.component.d.ts +87 -0
- package/human-handoff/human-handoff.component.d.ts +125 -0
- package/image-generation/image-generation.component.d.ts +253 -0
- package/index.d.ts +5 -0
- package/inline-text-diff/inline-text-diff.component.d.ts +76 -0
- package/launch-checklist/launch-checklist.component.d.ts +46 -0
- package/line-chart/line-chart.component.d.ts +89 -0
- package/live-answer/live-answer.component.d.ts +110 -0
- package/metric-insight/metric-insight.component.d.ts +110 -0
- package/modal/modal.component.d.ts +37 -0
- package/model-picker/model-picker.component.d.ts +97 -0
- package/package.json +51 -4
- package/permission-gate/permission-gate.component.d.ts +100 -0
- package/plan-review/plan-review.component.d.ts +86 -0
- package/progress/progress.component.d.ts +91 -0
- package/prompt-library/prompt-library.component.d.ts +121 -0
- package/prompt-starters/prompt-starters.component.d.ts +65 -0
- package/proposal-card/proposal-card.component.d.ts +101 -0
- package/public-api.d.ts +82 -0
- package/radar-chart/radar-chart.component.d.ts +110 -0
- package/radial-goals/radial-goals.component.d.ts +90 -0
- package/reasoning-trail/reasoning-trail.component.d.ts +73 -0
- package/response-versions/response-versions.component.d.ts +54 -0
- package/rewrite-toolbar/rewrite-toolbar.component.d.ts +92 -0
- package/rich-text-editor/rich-text-editor.component.d.ts +180 -0
- package/run-cost/run-cost.component.d.ts +43 -0
- package/run-queue/run-queue.component.d.ts +93 -0
- package/run-summary/run-summary.component.d.ts +81 -0
- package/scatter-chart/scatter-chart.component.d.ts +139 -0
- package/score-breakdown/score-breakdown.component.d.ts +107 -0
- package/segmented-control/segmented-control.component.d.ts +44 -0
- package/source-stack/source-stack.component.d.ts +60 -0
- package/stat-cards/stat-cards.component.d.ts +86 -0
- package/status-pill/status-pill.component.d.ts +64 -0
- package/steering/steering.component.d.ts +75 -0
- package/step-loader/step-loader.component.d.ts +40 -0
- package/styles.css +424 -0
- package/task-table/task-table.component.d.ts +114 -0
- package/terminal-stream/terminal-stream.component.d.ts +110 -0
- package/thinking/thinking.component.d.ts +63 -0
- package/thinking-states/thinking-states.component.d.ts +51 -0
- package/thread-panel/thread-panel.component.d.ts +75 -0
- package/toast/toast.component.d.ts +56 -0
- package/toast-stack/toast-stack.component.d.ts +72 -0
- package/tokens.css +424 -0
- package/tool-call/tool-call.component.d.ts +61 -0
- package/tooltip/tooltip.component.d.ts +89 -0
- package/top-pages/top-pages.component.d.ts +75 -0
- package/trace-view/trace-view.component.d.ts +95 -0
- package/voice-capture/voice-capture.component.d.ts +103 -0
- package/voice-orb/voice-orb.component.d.ts +78 -0
- package/web-search/web-search.component.d.ts +77 -0
|
@@ -0,0 +1,705 @@
|
|
|
1
|
+
// framework/angular/scatter-chart/scatter-chart.component.ts
|
|
2
|
+
//
|
|
3
|
+
// Native Angular port of framework/react/scatter-chart/ScatterChart.tsx.
|
|
4
|
+
// Every run is a dot by cost (along) and eval score (up), sized by tokens, with
|
|
5
|
+
// a colour and a shape per series. Dashed median lines cut the plot into four
|
|
6
|
+
// named quadrants; pointing snaps to the nearest run and a drag draws a box that
|
|
7
|
+
// selects the runs in it. Inputs mirror the React props; React callbacks become
|
|
8
|
+
// @Output EventEmitters. The plot measures itself with a ResizeObserver set up
|
|
9
|
+
// in ngAfterViewInit and torn down in ngOnDestroy, mirroring the vanilla JS
|
|
10
|
+
// (scatter-chart.js). Styling flows only through the --vo-* tokens.
|
|
11
|
+
//
|
|
12
|
+
// Icons: only the "spark" glyph is used (the note and the "Ask the agent why"
|
|
13
|
+
// button), via VoIconComponent — the same glyph the React/Vanilla originals use.
|
|
14
|
+
import { ChangeDetectorRef, Component, EventEmitter, Input, Output, ViewChild, ViewEncapsulation, inject, } from '@angular/core';
|
|
15
|
+
import { VoIconComponent } from '../core/icon.component';
|
|
16
|
+
import { ReducedMotionService } from '../core/reduced-motion.service';
|
|
17
|
+
import * as i0 from "@angular/core";
|
|
18
|
+
const PAL = [
|
|
19
|
+
'var(--vo-c1)',
|
|
20
|
+
'var(--vo-c2)',
|
|
21
|
+
'var(--vo-c3)',
|
|
22
|
+
'var(--vo-c4)',
|
|
23
|
+
'var(--vo-c5)',
|
|
24
|
+
'var(--vo-c6)',
|
|
25
|
+
];
|
|
26
|
+
const SHAPES = ['circle', 'square', 'triangle'];
|
|
27
|
+
const median = (a) => {
|
|
28
|
+
if (!a.length)
|
|
29
|
+
return 0;
|
|
30
|
+
const s = [...a].sort((p, q) => p - q);
|
|
31
|
+
const m = s.length >> 1;
|
|
32
|
+
return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;
|
|
33
|
+
};
|
|
34
|
+
export class ScatterChartComponent {
|
|
35
|
+
constructor() {
|
|
36
|
+
this.runs = [];
|
|
37
|
+
this.series = [];
|
|
38
|
+
this.className = '';
|
|
39
|
+
this.title = 'Cost vs quality';
|
|
40
|
+
/** [min, max] of each axis. */
|
|
41
|
+
this.xDomain = [0, 0.6];
|
|
42
|
+
this.yDomain = [60, 100];
|
|
43
|
+
/** Where the labels go along the bottom. A narrow chart keeps the two ends and the middle. */
|
|
44
|
+
this.xTicks = [0, 0.2, 0.4, 0.6];
|
|
45
|
+
/** Where the gridlines and their labels go up the side. A narrow chart keeps the two ends and the middle. */
|
|
46
|
+
this.yTicks = [60, 80, 100];
|
|
47
|
+
this.xTitle = 'Cost per run (USD)';
|
|
48
|
+
this.yTitle = 'Eval score (%)';
|
|
49
|
+
this.formatX = (x) => '$' + x.toFixed(2);
|
|
50
|
+
this.formatY = (y) => Math.round(y) + '%';
|
|
51
|
+
this.formatSize = (s) => Math.round(s) + 'k tokens';
|
|
52
|
+
/** The four quadrants the medians make, from the top left, clockwise. A narrow chart keeps the median lines and leaves the names out. */
|
|
53
|
+
this.quadrants = [
|
|
54
|
+
'Cheap, good',
|
|
55
|
+
'Costly, good',
|
|
56
|
+
'Costly, weaker',
|
|
57
|
+
'Cheap, weaker',
|
|
58
|
+
];
|
|
59
|
+
/** Runs to ring, like outliers the agent found. */
|
|
60
|
+
this.ringed = [];
|
|
61
|
+
this.selectedChange = new EventEmitter();
|
|
62
|
+
/** Adds "Ask the agent why" to a selection. Return the answer and it streams in. */
|
|
63
|
+
this.ask = new EventEmitter();
|
|
64
|
+
this.reduced = inject(ReducedMotionService);
|
|
65
|
+
this.cdr = inject(ChangeDetectorRef);
|
|
66
|
+
// measured geometry
|
|
67
|
+
this.W = 0;
|
|
68
|
+
this.H = 0;
|
|
69
|
+
this.narrow = false;
|
|
70
|
+
this.l = 44;
|
|
71
|
+
this.b = 40;
|
|
72
|
+
this.t = 6;
|
|
73
|
+
this.rr = 8;
|
|
74
|
+
// render state
|
|
75
|
+
this.dots = [];
|
|
76
|
+
this.ringDots = [];
|
|
77
|
+
this.xt = [];
|
|
78
|
+
this.yt = [];
|
|
79
|
+
this.mx = 0;
|
|
80
|
+
this.my = 0;
|
|
81
|
+
this.hot = -1;
|
|
82
|
+
this.hr = null;
|
|
83
|
+
this.box = null;
|
|
84
|
+
this.ttX = 0;
|
|
85
|
+
this.ttY = 0;
|
|
86
|
+
this.focused = false;
|
|
87
|
+
this.order = [];
|
|
88
|
+
this.selectedRuns = [];
|
|
89
|
+
this.avgX = 0;
|
|
90
|
+
this.avgY = 0;
|
|
91
|
+
this.answer = null;
|
|
92
|
+
this.off = [];
|
|
93
|
+
this.sel = [];
|
|
94
|
+
this.controlled = false;
|
|
95
|
+
this.ready = false;
|
|
96
|
+
this.asked = 0;
|
|
97
|
+
this.drag = null;
|
|
98
|
+
this.timers = [];
|
|
99
|
+
// template helpers
|
|
100
|
+
this.min = Math.min;
|
|
101
|
+
this.abs = Math.abs;
|
|
102
|
+
this.pendingAsk = 0;
|
|
103
|
+
}
|
|
104
|
+
/** The selected runs, by id. Leave it out to let the chart hold the selection. */
|
|
105
|
+
set selected(value) {
|
|
106
|
+
this.controlled = value !== undefined;
|
|
107
|
+
if (value !== undefined) {
|
|
108
|
+
this.sel = value;
|
|
109
|
+
this.asked++;
|
|
110
|
+
this.answer = null;
|
|
111
|
+
if (this.ready)
|
|
112
|
+
this.draw();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
get defaultNote() {
|
|
116
|
+
return `Medians split the runs: ${this.formatX(this.mx)} and ${this.formatY(this.my)}. Drag across the chart to select runs.`;
|
|
117
|
+
}
|
|
118
|
+
ngAfterViewInit() {
|
|
119
|
+
const el = this.plotRef.nativeElement;
|
|
120
|
+
this.ro = new ResizeObserver(() => {
|
|
121
|
+
this.W = el.clientWidth;
|
|
122
|
+
this.H = el.clientHeight;
|
|
123
|
+
this.draw();
|
|
124
|
+
});
|
|
125
|
+
this.ro.observe(el);
|
|
126
|
+
this.ready = true;
|
|
127
|
+
this.W = el.clientWidth;
|
|
128
|
+
this.H = el.clientHeight;
|
|
129
|
+
this.draw();
|
|
130
|
+
this.cdr.detectChanges();
|
|
131
|
+
}
|
|
132
|
+
// ----- series look-ups -----
|
|
133
|
+
si(key) {
|
|
134
|
+
return Math.max(0, this.series.findIndex((s) => s.key === key));
|
|
135
|
+
}
|
|
136
|
+
colorOf(key) {
|
|
137
|
+
return this.series[this.si(key)]?.color ?? PAL[this.si(key) % PAL.length];
|
|
138
|
+
}
|
|
139
|
+
shapeOf(key) {
|
|
140
|
+
return this.series[this.si(key)]?.shape ?? SHAPES[this.si(key) % SHAPES.length];
|
|
141
|
+
}
|
|
142
|
+
labelOf(key) {
|
|
143
|
+
return this.series[this.si(key)]?.label ?? '';
|
|
144
|
+
}
|
|
145
|
+
/** The triangle mark's path, so a dot reads without colour too. */
|
|
146
|
+
triPath(x, y, s) {
|
|
147
|
+
return `M${x} ${y - s * 1.15}L${x + s * 1.05} ${y + s * 0.75}L${x - s * 1.05} ${y + s * 0.75}Z`;
|
|
148
|
+
}
|
|
149
|
+
// ----- geometry -----
|
|
150
|
+
X(v) {
|
|
151
|
+
return this.l + ((v - this.xDomain[0]) / (this.xDomain[1] - this.xDomain[0])) * (this.W - this.l - this.rr);
|
|
152
|
+
}
|
|
153
|
+
Y(v) {
|
|
154
|
+
return this.t + (1 - (v - this.yDomain[0]) / (this.yDomain[1] - this.yDomain[0])) * (this.H - this.t - this.b);
|
|
155
|
+
}
|
|
156
|
+
R(run) {
|
|
157
|
+
const sMin = Math.min(...this.runs.map((r) => r.size));
|
|
158
|
+
const sMax = Math.max(...this.runs.map((r) => r.size));
|
|
159
|
+
return (3 + ((run.size - sMin) / Math.max(1, sMax - sMin)) * 4.5) * (this.narrow ? 0.85 : 1);
|
|
160
|
+
}
|
|
161
|
+
shownIdx() {
|
|
162
|
+
return this.runs.map((_, i) => i).filter((i) => !this.off.includes(this.runs[i].series));
|
|
163
|
+
}
|
|
164
|
+
// ----- draw: recompute every view model, mirroring the React render -----
|
|
165
|
+
draw() {
|
|
166
|
+
if (!this.ready || this.W <= 0) {
|
|
167
|
+
this.cdr.markForCheck();
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
this.narrow = this.W > 0 && this.W <= 340;
|
|
171
|
+
this.l = this.narrow ? 38 : 44;
|
|
172
|
+
const ends = (a, d) => this.narrow && a.length > 3 ? [a[0], (d[0] + d[1]) / 2, a[a.length - 1]] : a;
|
|
173
|
+
this.xt = ends(this.xTicks, this.xDomain);
|
|
174
|
+
this.yt = ends(this.yTicks, this.yDomain);
|
|
175
|
+
const shown = this.shownIdx();
|
|
176
|
+
this.mx = median(shown.map((i) => this.runs[i].x));
|
|
177
|
+
this.my = median(shown.map((i) => this.runs[i].y));
|
|
178
|
+
const sel = this.sel;
|
|
179
|
+
this.dots = this.runs.map((run, i) => {
|
|
180
|
+
const off = this.off.includes(run.series);
|
|
181
|
+
const dim = this.hr != null && this.hr.series !== run.series && !off;
|
|
182
|
+
const cls = ['vo-d', off ? 'vo-off' : '', dim ? 'vo-dim' : '', i === this.hot ? 'vo-on' : '', sel.includes(run.id) ? 'vo-sel' : '']
|
|
183
|
+
.filter(Boolean)
|
|
184
|
+
.join(' ');
|
|
185
|
+
return {
|
|
186
|
+
run,
|
|
187
|
+
index: i,
|
|
188
|
+
cls,
|
|
189
|
+
fill: this.colorOf(run.series),
|
|
190
|
+
shape: this.shapeOf(run.series),
|
|
191
|
+
cx: +this.X(run.x).toFixed(1),
|
|
192
|
+
cy: +this.Y(run.y).toFixed(1),
|
|
193
|
+
r: +this.R(run).toFixed(1),
|
|
194
|
+
};
|
|
195
|
+
});
|
|
196
|
+
this.ringDots = this.runs
|
|
197
|
+
.filter((run) => this.ringed.includes(run.id) && !this.off.includes(run.series))
|
|
198
|
+
.map((run) => ({
|
|
199
|
+
run,
|
|
200
|
+
index: this.runs.indexOf(run),
|
|
201
|
+
cls: '',
|
|
202
|
+
fill: this.colorOf(run.series),
|
|
203
|
+
shape: this.shapeOf(run.series),
|
|
204
|
+
cx: this.X(run.x),
|
|
205
|
+
cy: this.Y(run.y),
|
|
206
|
+
r: this.R(run),
|
|
207
|
+
}));
|
|
208
|
+
this.order = [...shown].sort((a, c) => this.runs[a].x - this.runs[c].x || this.runs[c].y - this.runs[a].y);
|
|
209
|
+
this.hr = this.hot >= 0 ? this.runs[this.hot] : null;
|
|
210
|
+
if (this.hr && this.tipRef) {
|
|
211
|
+
const w = this.tipRef.nativeElement.offsetWidth;
|
|
212
|
+
this.ttX = Math.max(w / 2, Math.min(this.W - w / 2, this.X(this.hr.x)));
|
|
213
|
+
this.ttY = this.Y(this.hr.y) - this.R(this.hr);
|
|
214
|
+
}
|
|
215
|
+
this.selectedRuns = this.runs.filter((r) => sel.includes(r.id));
|
|
216
|
+
if (this.selectedRuns.length) {
|
|
217
|
+
this.avgX = this.selectedRuns.reduce((a, r) => a + r.x, 0) / this.selectedRuns.length;
|
|
218
|
+
this.avgY = this.selectedRuns.reduce((a, r) => a + r.y, 0) / this.selectedRuns.length;
|
|
219
|
+
}
|
|
220
|
+
this.cdr.markForCheck();
|
|
221
|
+
}
|
|
222
|
+
// ----- legend -----
|
|
223
|
+
toggle(key) {
|
|
224
|
+
if (!this.off.includes(key) && this.off.length === this.series.length - 1)
|
|
225
|
+
return;
|
|
226
|
+
this.hot = -1;
|
|
227
|
+
this.off = this.off.includes(key) ? this.off.filter((k) => k !== key) : [...this.off, key];
|
|
228
|
+
this.draw();
|
|
229
|
+
}
|
|
230
|
+
// ----- pointer / selection -----
|
|
231
|
+
local(e) {
|
|
232
|
+
const r = this.plotRef.nativeElement.getBoundingClientRect();
|
|
233
|
+
return [e.clientX - r.left, e.clientY - r.top];
|
|
234
|
+
}
|
|
235
|
+
near(px, py) {
|
|
236
|
+
let best = -1;
|
|
237
|
+
let bd = 26 * 26;
|
|
238
|
+
for (const i of this.shownIdx()) {
|
|
239
|
+
const dx = this.X(this.runs[i].x) - px;
|
|
240
|
+
const dy = this.Y(this.runs[i].y) - py;
|
|
241
|
+
const d = dx * dx + dy * dy;
|
|
242
|
+
if (d < bd) {
|
|
243
|
+
bd = d;
|
|
244
|
+
best = i;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
return best;
|
|
248
|
+
}
|
|
249
|
+
setSel(ids) {
|
|
250
|
+
if (!this.controlled) {
|
|
251
|
+
this.sel = ids;
|
|
252
|
+
this.asked++;
|
|
253
|
+
this.answer = null;
|
|
254
|
+
}
|
|
255
|
+
this.selectedChange.emit(ids);
|
|
256
|
+
this.draw();
|
|
257
|
+
}
|
|
258
|
+
onPointerDown(e) {
|
|
259
|
+
if (e.button)
|
|
260
|
+
return;
|
|
261
|
+
const [x, y] = this.local(e);
|
|
262
|
+
this.drag = { x, y, id: e.pointerId, moved: false };
|
|
263
|
+
}
|
|
264
|
+
onPointerMove(e) {
|
|
265
|
+
const [x, y] = this.local(e);
|
|
266
|
+
const d = this.drag;
|
|
267
|
+
if (d && (d.moved || Math.abs(x - d.x) + Math.abs(y - d.y) > 5)) {
|
|
268
|
+
if (!d.moved) {
|
|
269
|
+
d.moved = true;
|
|
270
|
+
this.plotRef.nativeElement.setPointerCapture(d.id);
|
|
271
|
+
this.hot = -1;
|
|
272
|
+
}
|
|
273
|
+
this.box = [
|
|
274
|
+
d.x,
|
|
275
|
+
d.y,
|
|
276
|
+
Math.max(this.l, Math.min(this.W - this.rr, x)),
|
|
277
|
+
Math.max(this.t, Math.min(this.H - this.b, y)),
|
|
278
|
+
];
|
|
279
|
+
this.draw();
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
if (e.pointerType !== 'touch') {
|
|
283
|
+
const i = this.near(x, y);
|
|
284
|
+
if (i !== this.hot) {
|
|
285
|
+
this.hot = i;
|
|
286
|
+
this.draw();
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
onPointerUp() {
|
|
291
|
+
const d = this.drag;
|
|
292
|
+
this.drag = null;
|
|
293
|
+
if (!d)
|
|
294
|
+
return;
|
|
295
|
+
if (d.moved && this.box) {
|
|
296
|
+
const [a, b2, x2, y2] = this.box;
|
|
297
|
+
const lo = Math.min(a, x2);
|
|
298
|
+
const hi = Math.max(a, x2);
|
|
299
|
+
const top = Math.min(b2, y2);
|
|
300
|
+
const bot = Math.max(b2, y2);
|
|
301
|
+
const ids = this.shownIdx()
|
|
302
|
+
.filter((i) => this.X(this.runs[i].x) >= lo &&
|
|
303
|
+
this.X(this.runs[i].x) <= hi &&
|
|
304
|
+
this.Y(this.runs[i].y) >= top &&
|
|
305
|
+
this.Y(this.runs[i].y) <= bot)
|
|
306
|
+
.map((i) => this.runs[i].id);
|
|
307
|
+
this.box = null;
|
|
308
|
+
this.setSel(ids);
|
|
309
|
+
}
|
|
310
|
+
else if (this.hot < 0 && this.sel.length) {
|
|
311
|
+
this.box = null;
|
|
312
|
+
this.setSel([]);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
onPointerCancel() {
|
|
316
|
+
this.drag = null;
|
|
317
|
+
this.box = null;
|
|
318
|
+
this.draw();
|
|
319
|
+
}
|
|
320
|
+
onPointerLeave() {
|
|
321
|
+
if (!this.drag && document.activeElement !== this.plotRef.nativeElement && this.hot >= 0) {
|
|
322
|
+
this.hot = -1;
|
|
323
|
+
this.draw();
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
onBlur() {
|
|
327
|
+
this.focused = false;
|
|
328
|
+
if (this.hot >= 0) {
|
|
329
|
+
this.hot = -1;
|
|
330
|
+
this.draw();
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
onKeyDown(e) {
|
|
334
|
+
this.focused = true;
|
|
335
|
+
const o = this.order;
|
|
336
|
+
let k = o.indexOf(this.hot);
|
|
337
|
+
if (e.key === 'ArrowRight' || e.key === 'ArrowDown')
|
|
338
|
+
k = Math.min(o.length - 1, k + 1);
|
|
339
|
+
else if (e.key === 'ArrowLeft' || e.key === 'ArrowUp')
|
|
340
|
+
k = Math.max(0, k < 0 ? 0 : k - 1);
|
|
341
|
+
else if (e.key === 'Home')
|
|
342
|
+
k = 0;
|
|
343
|
+
else if (e.key === 'End')
|
|
344
|
+
k = o.length - 1;
|
|
345
|
+
else if (e.key === 'Escape' && this.sel.length) {
|
|
346
|
+
this.box = null;
|
|
347
|
+
this.setSel([]);
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
else
|
|
351
|
+
return;
|
|
352
|
+
e.preventDefault();
|
|
353
|
+
this.hot = o[k];
|
|
354
|
+
this.draw();
|
|
355
|
+
}
|
|
356
|
+
// ----- ask the agent -----
|
|
357
|
+
runAsk() {
|
|
358
|
+
if (!this.ask.observed)
|
|
359
|
+
return;
|
|
360
|
+
this.asked++;
|
|
361
|
+
const id = this.asked;
|
|
362
|
+
this.answer = { text: '', busy: true };
|
|
363
|
+
this.ask.emit(this.selectedRuns);
|
|
364
|
+
this.cdr.markForCheck();
|
|
365
|
+
// the host answers via streamAnswer(); until then the shimmer shows
|
|
366
|
+
this.pendingAsk = id;
|
|
367
|
+
}
|
|
368
|
+
/** The host calls this with the answer; it streams in word by word. */
|
|
369
|
+
streamAnswer(text) {
|
|
370
|
+
const id = this.pendingAsk;
|
|
371
|
+
if (id !== this.asked)
|
|
372
|
+
return;
|
|
373
|
+
const ws = text.split(' ');
|
|
374
|
+
const step = (i) => {
|
|
375
|
+
if (id !== this.asked)
|
|
376
|
+
return;
|
|
377
|
+
this.answer = { text: ws.slice(0, i).join(' '), busy: false };
|
|
378
|
+
this.cdr.markForCheck();
|
|
379
|
+
if (i < ws.length) {
|
|
380
|
+
this.timers.push(setTimeout(() => step(i + 1), this.reduced.reduce() ? 0 : 45));
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
step(1);
|
|
384
|
+
}
|
|
385
|
+
ngOnDestroy() {
|
|
386
|
+
this.ro?.disconnect();
|
|
387
|
+
this.timers.forEach(clearTimeout);
|
|
388
|
+
this.timers = [];
|
|
389
|
+
}
|
|
390
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScatterChartComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
391
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: ScatterChartComponent, isStandalone: true, selector: "vo-scatter-chart", inputs: { runs: "runs", series: "series", className: "className", title: "title", subtitle: "subtitle", xDomain: "xDomain", yDomain: "yDomain", xTicks: "xTicks", yTicks: "yTicks", xTitle: "xTitle", yTitle: "yTitle", formatX: "formatX", formatY: "formatY", formatSize: "formatSize", quadrants: "quadrants", ringed: "ringed", note: "note", selected: "selected" }, outputs: { selectedChange: "selectedChange", ask: "ask" }, viewQueries: [{ propertyName: "plotRef", first: true, predicate: ["plot"], descendants: true }, { propertyName: "tipRef", first: true, predicate: ["tip"], descendants: true }], ngImport: i0, template: `
|
|
392
|
+
<div data-vo="" class="vo-cvq vo-panel" [class]="className">
|
|
393
|
+
<div class="vo-cvq-h">
|
|
394
|
+
<div class="vo-cvq-t">
|
|
395
|
+
<b>{{ title }}</b>
|
|
396
|
+
@if (subtitle) {
|
|
397
|
+
<span class="vo-muted">{{ subtitle }}</span>
|
|
398
|
+
}
|
|
399
|
+
</div>
|
|
400
|
+
<div class="vo-cvq-lg">
|
|
401
|
+
@for (s of series; track s.key) {
|
|
402
|
+
<button
|
|
403
|
+
type="button"
|
|
404
|
+
class="vo-cvq-k"
|
|
405
|
+
[attr.aria-pressed]="!off.includes(s.key)"
|
|
406
|
+
(click)="toggle(s.key)"
|
|
407
|
+
>
|
|
408
|
+
<svg viewBox="-6 -6 12 12" [style.fill]="colorOf(s.key)" aria-hidden="true">
|
|
409
|
+
@switch (shapeOf(s.key)) {
|
|
410
|
+
@case ('circle') { <circle [attr.cx]="0" [attr.cy]="0" [attr.r]="4.5" /> }
|
|
411
|
+
@case ('square') { <rect [attr.x]="-4.05" [attr.y]="-4.05" [attr.width]="8.1" [attr.height]="8.1" [attr.rx]="1.125" /> }
|
|
412
|
+
@default { <path [attr.d]="triPath(0, 0, 4.5)" /> }
|
|
413
|
+
}
|
|
414
|
+
</svg>{{ s.label }}
|
|
415
|
+
</button>
|
|
416
|
+
}
|
|
417
|
+
</div>
|
|
418
|
+
</div>
|
|
419
|
+
|
|
420
|
+
<div
|
|
421
|
+
#plot
|
|
422
|
+
class="vo-cvq-pl"
|
|
423
|
+
tabindex="0"
|
|
424
|
+
role="group"
|
|
425
|
+
aria-roledescription="scatter chart"
|
|
426
|
+
[attr.aria-label]="title + '. Arrow keys step through the runs'"
|
|
427
|
+
(pointerdown)="onPointerDown($event)"
|
|
428
|
+
(pointermove)="onPointerMove($event)"
|
|
429
|
+
(pointerup)="onPointerUp()"
|
|
430
|
+
(pointercancel)="onPointerCancel()"
|
|
431
|
+
(pointerleave)="onPointerLeave()"
|
|
432
|
+
(blur)="onBlur()"
|
|
433
|
+
(keydown)="onKeyDown($event)"
|
|
434
|
+
>
|
|
435
|
+
@if (W > 0) {
|
|
436
|
+
<svg class="vo-cvq-svg" [attr.viewBox]="'0 0 ' + W + ' ' + H" aria-hidden="true">
|
|
437
|
+
<!-- a few light gridlines and quiet tick labels; the axis titles sit well clear of the ticks -->
|
|
438
|
+
@for (v of yt; track v) {
|
|
439
|
+
<g>
|
|
440
|
+
<line class="vo-gl" [attr.x1]="l" [attr.x2]="W - rr" [attr.y1]="Y(v)" [attr.y2]="Y(v)" />
|
|
441
|
+
<text [attr.x]="l - 6" [attr.y]="Y(v) + 3.5" text-anchor="end">{{ v }}</text>
|
|
442
|
+
</g>
|
|
443
|
+
}
|
|
444
|
+
@for (v of xt; track $index) {
|
|
445
|
+
<text
|
|
446
|
+
[attr.x]="X(v)"
|
|
447
|
+
[attr.y]="H - b + 15"
|
|
448
|
+
[attr.text-anchor]="$index === 0 ? 'start' : $index === xt.length - 1 ? 'end' : 'middle'"
|
|
449
|
+
>{{ formatX(v) }}</text>
|
|
450
|
+
}
|
|
451
|
+
<line class="vo-ax" [attr.x1]="l" [attr.x2]="W - rr" [attr.y1]="H - b" [attr.y2]="H - b" />
|
|
452
|
+
<text class="vo-at" [attr.x]="W - rr" [attr.y]="H - 1" text-anchor="end">{{ xTitle }}</text>
|
|
453
|
+
<text class="vo-at" [attr.x]="-t" [attr.y]="9" transform="rotate(-90)" text-anchor="end">{{ yTitle }}</text>
|
|
454
|
+
<line class="vo-md" [attr.x1]="X(mx)" [attr.x2]="X(mx)" [attr.y1]="t" [attr.y2]="H - b" />
|
|
455
|
+
<line class="vo-md" [attr.x1]="l" [attr.x2]="W - rr" [attr.y1]="Y(my)" [attr.y2]="Y(my)" />
|
|
456
|
+
@if (!narrow) {
|
|
457
|
+
<text class="vo-q" [attr.x]="l + 6" [attr.y]="t + 11">{{ quadrants[0] }}</text>
|
|
458
|
+
<text class="vo-q" [attr.x]="W - rr - 4" [attr.y]="t + 11" text-anchor="end">{{ quadrants[1] }}</text>
|
|
459
|
+
<text class="vo-q" [attr.x]="W - rr - 4" [attr.y]="H - b - 6" text-anchor="end">{{ quadrants[2] }}</text>
|
|
460
|
+
<text class="vo-q" [attr.x]="l + 6" [attr.y]="H - b - 6">{{ quadrants[3] }}</text>
|
|
461
|
+
}
|
|
462
|
+
@for (d of dots; track d.run.id) {
|
|
463
|
+
<g [class]="d.cls" [style.fill]="d.fill">
|
|
464
|
+
@switch (d.shape) {
|
|
465
|
+
@case ('circle') { <circle [attr.cx]="d.cx" [attr.cy]="d.cy" [attr.r]="d.r" /> }
|
|
466
|
+
@case ('square') { <rect [attr.x]="d.cx - d.r * 0.9" [attr.y]="d.cy - d.r * 0.9" [attr.width]="d.r * 1.8" [attr.height]="d.r * 1.8" [attr.rx]="d.r * 0.25" /> }
|
|
467
|
+
@default { <path [attr.d]="triPath(d.cx, d.cy, d.r)" /> }
|
|
468
|
+
}
|
|
469
|
+
</g>
|
|
470
|
+
}
|
|
471
|
+
@for (d of ringDots; track d.run.id) {
|
|
472
|
+
<circle class="vo-ring" [attr.cx]="d.cx" [attr.cy]="d.cy" [attr.r]="d.r + 6" />
|
|
473
|
+
}
|
|
474
|
+
@if (box) {
|
|
475
|
+
<rect
|
|
476
|
+
class="vo-box"
|
|
477
|
+
[attr.x]="min(box[0], box[2])"
|
|
478
|
+
[attr.y]="min(box[1], box[3])"
|
|
479
|
+
[attr.width]="abs(box[2] - box[0])"
|
|
480
|
+
[attr.height]="abs(box[3] - box[1])"
|
|
481
|
+
[attr.rx]="3"
|
|
482
|
+
/>
|
|
483
|
+
}
|
|
484
|
+
</svg>
|
|
485
|
+
}
|
|
486
|
+
<div #tip class="vo-cvq-tt" [class.vo-on]="hr" [style.left.px]="ttX" [style.top.px]="ttY">
|
|
487
|
+
@if (hr) {
|
|
488
|
+
<b class="vo-num">{{ formatX(hr.x) }} · {{ formatY(hr.y) }}</b>
|
|
489
|
+
<span>Run {{ hr.id }}, {{ labelOf(hr.series) }}, {{ formatSize(hr.size) }}</span>
|
|
490
|
+
}
|
|
491
|
+
</div>
|
|
492
|
+
</div>
|
|
493
|
+
|
|
494
|
+
<div class="vo-cvq-ft" aria-live="polite">
|
|
495
|
+
@if (hr && focused) {
|
|
496
|
+
<span class="vo-cvq-msg">
|
|
497
|
+
<span><b>Run {{ hr.id }}</b>, {{ labelOf(hr.series) }}: {{ formatX(hr.x) }}, {{ formatY(hr.y) }}, {{ formatSize(hr.size) }}. {{ order.indexOf(hot) + 1 }} of {{ order.length }}</span>
|
|
498
|
+
</span>
|
|
499
|
+
} @else if (answer) {
|
|
500
|
+
<span class="vo-cvq-msg">
|
|
501
|
+
<vo-icon class="vo-i" name="spark" size="xs"></vo-icon>
|
|
502
|
+
<span [class.vo-shim]="answer.busy">{{ answer.busy ? 'Looking at ' + selectedRuns.length + ' runs' : answer.text }}</span>
|
|
503
|
+
</span>
|
|
504
|
+
} @else if (selectedRuns.length) {
|
|
505
|
+
<span class="vo-cvq-msg">
|
|
506
|
+
<span><b>{{ selectedRuns.length }} runs selected</b>, {{ formatX(avgX) }} and {{ formatY(avgY) }} on average</span>
|
|
507
|
+
</span>
|
|
508
|
+
@if (ask.observed) {
|
|
509
|
+
<button type="button" class="vo-pill vo-soft vo-sm" (click)="runAsk()">
|
|
510
|
+
<vo-icon name="spark" size="xs"></vo-icon>Ask the agent why
|
|
511
|
+
</button>
|
|
512
|
+
}
|
|
513
|
+
} @else {
|
|
514
|
+
<span class="vo-cvq-msg">
|
|
515
|
+
<vo-icon class="vo-i" name="spark" size="xs"></vo-icon>
|
|
516
|
+
<span>{{ note ?? defaultNote }}</span>
|
|
517
|
+
</span>
|
|
518
|
+
}
|
|
519
|
+
</div>
|
|
520
|
+
</div>
|
|
521
|
+
`, isInline: true, styles: [".vo-cvq{padding:var(--vo-s-4);display:flex;flex-direction:column;gap:var(--vo-s-3)}.vo-cvq-h{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;flex-wrap:wrap}.vo-cvq-t{display:flex;flex-direction:column;font-size:13.5px;line-height:1.4}.vo-cvq-t b{font-weight:500}.vo-cvq-t .vo-muted{font-size:12px}.vo-cvq-lg{display:flex;gap:2px}.vo-cvq-k{display:flex;align-items:center;gap:6px;height:26px;padding:0 8px;border-radius:var(--vo-r-pill);font-size:12px;color:var(--vo-muted);transition:color .2s,background .2s}@media (hover:hover) and (pointer:fine){.vo-cvq-k:hover{background:var(--vo-row)}}.vo-cvq-k[aria-pressed=true]{color:var(--vo-fg)}.vo-cvq-k svg{width:10px;height:10px;overflow:visible;transition:opacity .3s,transform .3s var(--vo-ease)}.vo-cvq-k[aria-pressed=false] svg{opacity:.3;transform:scale(.7)}.vo-cvq-pl{position:relative;height:244px;touch-action:pan-y;cursor:crosshair;user-select:none;-webkit-user-select:none;border-radius:var(--vo-r-sm)}.vo-cvq-pl:focus-visible{outline-offset:4px}.vo-cvq-svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}.vo-cvq-svg .vo-gl{stroke:color-mix(in srgb,var(--vo-line) 40%,transparent);stroke-width:1}.vo-cvq-svg .vo-ax{stroke:color-mix(in srgb,var(--vo-line) 80%,transparent);stroke-width:1}.vo-cvq-svg .vo-md{stroke:color-mix(in srgb,var(--vo-faint) 75%,transparent);stroke-width:1;stroke-dasharray:3 3}.vo-cvq-svg text{font-size:10.5px;fill:var(--vo-muted);font-family:var(--vo-sans)}.vo-cvq-svg text.vo-q{font-size:10px}.vo-cvq-svg text.vo-at{font-size:10.5px}.vo-cvq-svg .vo-d{stroke:var(--vo-surface);stroke-width:1;fill-opacity:.85;transition:opacity .25s,fill-opacity .25s}.vo-cvq-svg .vo-d.vo-dim{opacity:.18}.vo-cvq-svg .vo-d.vo-off{opacity:0}.vo-cvq-svg .vo-d.vo-sel{fill-opacity:1;stroke:var(--vo-fg);stroke-width:1.2}.vo-cvq-svg .vo-d.vo-on{fill-opacity:1;stroke:var(--vo-fg);stroke-width:1.5}.vo-cvq-svg .vo-ring{fill:none;stroke:var(--vo-fg2);stroke-width:1.2;stroke-dasharray:3 2.5}.vo-cvq-svg .vo-box{fill:color-mix(in srgb,var(--vo-fg) 5%,transparent);stroke:var(--vo-fg2);stroke-width:1;stroke-dasharray:4 3}.vo-cvq-tt{position:absolute;left:0;top:0;padding:6px 9px;border-radius:calc(10px * var(--vo-rk));background:var(--vo-ink);color:var(--vo-on-ink);font-size:11.5px;display:flex;flex-direction:column;opacity:0;transform:translate(-50%,-100%) translateY(-6px);transition:opacity .15s;pointer-events:none;white-space:nowrap;z-index:2}.vo-cvq-tt span{opacity:.75}.vo-cvq-tt.vo-on{opacity:1}.vo-cvq-ft{min-height:72px;display:flex;align-items:center;gap:var(--vo-s-2);padding:var(--vo-s-2) var(--vo-s-3);border-radius:var(--vo-r-in);background:var(--vo-row);font-size:12.5px;color:var(--vo-fg2)}.vo-cvq-msg{flex:1;min-width:0;display:flex;align-items:center;gap:var(--vo-s-2)}.vo-cvq-msg .vo-i{flex:none;color:var(--vo-accent-fg,var(--vo-accent))}.vo-cvq-msg b{font-weight:500;color:var(--vo-fg)}.vo-cvq-ft .vo-pill{flex:none}.vo-cvq-ft .vo-ib{flex:none;width:26px;height:26px}.vo-cvq-ft{flex-wrap:wrap}.vo-cvq-msg{flex:1 1 180px}.vo-cvq{container-type:inline-size}@container (max-width:340px){.vo-cvq-pl{height:228px}.vo-cvq-ft{flex-direction:column;align-items:stretch;justify-content:center;gap:10px}.vo-cvq-msg{flex:none}.vo-cvq-msg:has(>.vo-pill){flex-direction:column;align-items:stretch;gap:10px}.vo-cvq-ft .vo-pill{justify-content:center}}.vo-pill{display:inline-flex;align-items:center;justify-content:center;gap:7px;height:32px;padding:0 14px;border-radius:var(--vo-r-pill);font-size:13px;font-weight:500;white-space:nowrap;cursor:pointer;transition:background var(--vo-t-fast),color var(--vo-t-fast),opacity var(--vo-t-fast),transform .15s}.vo-pill:active{transform:scale(.97)}.vo-pill.vo-soft{background:var(--vo-chip);color:var(--vo-fg2)}@media (hover:hover) and (pointer:fine){.vo-pill.vo-soft:hover{background:var(--vo-row,var(--vo-hover));color:var(--vo-fg)}}.vo-pill.vo-sm{height:28px;padding:0 11px;font-size:12.5px}.vo-shim{background:linear-gradient(90deg,var(--vo-muted) 25%,var(--vo-fg) 50%,var(--vo-muted) 75%);background-size:200% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;animation:vo-shim 1.4s linear infinite}@keyframes vo-shim{to{background-position:-200% 0}}@media (prefers-reduced-motion:reduce){.vo-shim{color:var(--vo-fg);background:none}}\n"], dependencies: [{ kind: "component", type: VoIconComponent, selector: "vo-icon", inputs: ["name", "size"] }], encapsulation: i0.ViewEncapsulation.None }); }
|
|
522
|
+
}
|
|
523
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: ScatterChartComponent, decorators: [{
|
|
524
|
+
type: Component,
|
|
525
|
+
args: [{ selector: 'vo-scatter-chart', standalone: true, encapsulation: ViewEncapsulation.None, imports: [VoIconComponent], template: `
|
|
526
|
+
<div data-vo="" class="vo-cvq vo-panel" [class]="className">
|
|
527
|
+
<div class="vo-cvq-h">
|
|
528
|
+
<div class="vo-cvq-t">
|
|
529
|
+
<b>{{ title }}</b>
|
|
530
|
+
@if (subtitle) {
|
|
531
|
+
<span class="vo-muted">{{ subtitle }}</span>
|
|
532
|
+
}
|
|
533
|
+
</div>
|
|
534
|
+
<div class="vo-cvq-lg">
|
|
535
|
+
@for (s of series; track s.key) {
|
|
536
|
+
<button
|
|
537
|
+
type="button"
|
|
538
|
+
class="vo-cvq-k"
|
|
539
|
+
[attr.aria-pressed]="!off.includes(s.key)"
|
|
540
|
+
(click)="toggle(s.key)"
|
|
541
|
+
>
|
|
542
|
+
<svg viewBox="-6 -6 12 12" [style.fill]="colorOf(s.key)" aria-hidden="true">
|
|
543
|
+
@switch (shapeOf(s.key)) {
|
|
544
|
+
@case ('circle') { <circle [attr.cx]="0" [attr.cy]="0" [attr.r]="4.5" /> }
|
|
545
|
+
@case ('square') { <rect [attr.x]="-4.05" [attr.y]="-4.05" [attr.width]="8.1" [attr.height]="8.1" [attr.rx]="1.125" /> }
|
|
546
|
+
@default { <path [attr.d]="triPath(0, 0, 4.5)" /> }
|
|
547
|
+
}
|
|
548
|
+
</svg>{{ s.label }}
|
|
549
|
+
</button>
|
|
550
|
+
}
|
|
551
|
+
</div>
|
|
552
|
+
</div>
|
|
553
|
+
|
|
554
|
+
<div
|
|
555
|
+
#plot
|
|
556
|
+
class="vo-cvq-pl"
|
|
557
|
+
tabindex="0"
|
|
558
|
+
role="group"
|
|
559
|
+
aria-roledescription="scatter chart"
|
|
560
|
+
[attr.aria-label]="title + '. Arrow keys step through the runs'"
|
|
561
|
+
(pointerdown)="onPointerDown($event)"
|
|
562
|
+
(pointermove)="onPointerMove($event)"
|
|
563
|
+
(pointerup)="onPointerUp()"
|
|
564
|
+
(pointercancel)="onPointerCancel()"
|
|
565
|
+
(pointerleave)="onPointerLeave()"
|
|
566
|
+
(blur)="onBlur()"
|
|
567
|
+
(keydown)="onKeyDown($event)"
|
|
568
|
+
>
|
|
569
|
+
@if (W > 0) {
|
|
570
|
+
<svg class="vo-cvq-svg" [attr.viewBox]="'0 0 ' + W + ' ' + H" aria-hidden="true">
|
|
571
|
+
<!-- a few light gridlines and quiet tick labels; the axis titles sit well clear of the ticks -->
|
|
572
|
+
@for (v of yt; track v) {
|
|
573
|
+
<g>
|
|
574
|
+
<line class="vo-gl" [attr.x1]="l" [attr.x2]="W - rr" [attr.y1]="Y(v)" [attr.y2]="Y(v)" />
|
|
575
|
+
<text [attr.x]="l - 6" [attr.y]="Y(v) + 3.5" text-anchor="end">{{ v }}</text>
|
|
576
|
+
</g>
|
|
577
|
+
}
|
|
578
|
+
@for (v of xt; track $index) {
|
|
579
|
+
<text
|
|
580
|
+
[attr.x]="X(v)"
|
|
581
|
+
[attr.y]="H - b + 15"
|
|
582
|
+
[attr.text-anchor]="$index === 0 ? 'start' : $index === xt.length - 1 ? 'end' : 'middle'"
|
|
583
|
+
>{{ formatX(v) }}</text>
|
|
584
|
+
}
|
|
585
|
+
<line class="vo-ax" [attr.x1]="l" [attr.x2]="W - rr" [attr.y1]="H - b" [attr.y2]="H - b" />
|
|
586
|
+
<text class="vo-at" [attr.x]="W - rr" [attr.y]="H - 1" text-anchor="end">{{ xTitle }}</text>
|
|
587
|
+
<text class="vo-at" [attr.x]="-t" [attr.y]="9" transform="rotate(-90)" text-anchor="end">{{ yTitle }}</text>
|
|
588
|
+
<line class="vo-md" [attr.x1]="X(mx)" [attr.x2]="X(mx)" [attr.y1]="t" [attr.y2]="H - b" />
|
|
589
|
+
<line class="vo-md" [attr.x1]="l" [attr.x2]="W - rr" [attr.y1]="Y(my)" [attr.y2]="Y(my)" />
|
|
590
|
+
@if (!narrow) {
|
|
591
|
+
<text class="vo-q" [attr.x]="l + 6" [attr.y]="t + 11">{{ quadrants[0] }}</text>
|
|
592
|
+
<text class="vo-q" [attr.x]="W - rr - 4" [attr.y]="t + 11" text-anchor="end">{{ quadrants[1] }}</text>
|
|
593
|
+
<text class="vo-q" [attr.x]="W - rr - 4" [attr.y]="H - b - 6" text-anchor="end">{{ quadrants[2] }}</text>
|
|
594
|
+
<text class="vo-q" [attr.x]="l + 6" [attr.y]="H - b - 6">{{ quadrants[3] }}</text>
|
|
595
|
+
}
|
|
596
|
+
@for (d of dots; track d.run.id) {
|
|
597
|
+
<g [class]="d.cls" [style.fill]="d.fill">
|
|
598
|
+
@switch (d.shape) {
|
|
599
|
+
@case ('circle') { <circle [attr.cx]="d.cx" [attr.cy]="d.cy" [attr.r]="d.r" /> }
|
|
600
|
+
@case ('square') { <rect [attr.x]="d.cx - d.r * 0.9" [attr.y]="d.cy - d.r * 0.9" [attr.width]="d.r * 1.8" [attr.height]="d.r * 1.8" [attr.rx]="d.r * 0.25" /> }
|
|
601
|
+
@default { <path [attr.d]="triPath(d.cx, d.cy, d.r)" /> }
|
|
602
|
+
}
|
|
603
|
+
</g>
|
|
604
|
+
}
|
|
605
|
+
@for (d of ringDots; track d.run.id) {
|
|
606
|
+
<circle class="vo-ring" [attr.cx]="d.cx" [attr.cy]="d.cy" [attr.r]="d.r + 6" />
|
|
607
|
+
}
|
|
608
|
+
@if (box) {
|
|
609
|
+
<rect
|
|
610
|
+
class="vo-box"
|
|
611
|
+
[attr.x]="min(box[0], box[2])"
|
|
612
|
+
[attr.y]="min(box[1], box[3])"
|
|
613
|
+
[attr.width]="abs(box[2] - box[0])"
|
|
614
|
+
[attr.height]="abs(box[3] - box[1])"
|
|
615
|
+
[attr.rx]="3"
|
|
616
|
+
/>
|
|
617
|
+
}
|
|
618
|
+
</svg>
|
|
619
|
+
}
|
|
620
|
+
<div #tip class="vo-cvq-tt" [class.vo-on]="hr" [style.left.px]="ttX" [style.top.px]="ttY">
|
|
621
|
+
@if (hr) {
|
|
622
|
+
<b class="vo-num">{{ formatX(hr.x) }} · {{ formatY(hr.y) }}</b>
|
|
623
|
+
<span>Run {{ hr.id }}, {{ labelOf(hr.series) }}, {{ formatSize(hr.size) }}</span>
|
|
624
|
+
}
|
|
625
|
+
</div>
|
|
626
|
+
</div>
|
|
627
|
+
|
|
628
|
+
<div class="vo-cvq-ft" aria-live="polite">
|
|
629
|
+
@if (hr && focused) {
|
|
630
|
+
<span class="vo-cvq-msg">
|
|
631
|
+
<span><b>Run {{ hr.id }}</b>, {{ labelOf(hr.series) }}: {{ formatX(hr.x) }}, {{ formatY(hr.y) }}, {{ formatSize(hr.size) }}. {{ order.indexOf(hot) + 1 }} of {{ order.length }}</span>
|
|
632
|
+
</span>
|
|
633
|
+
} @else if (answer) {
|
|
634
|
+
<span class="vo-cvq-msg">
|
|
635
|
+
<vo-icon class="vo-i" name="spark" size="xs"></vo-icon>
|
|
636
|
+
<span [class.vo-shim]="answer.busy">{{ answer.busy ? 'Looking at ' + selectedRuns.length + ' runs' : answer.text }}</span>
|
|
637
|
+
</span>
|
|
638
|
+
} @else if (selectedRuns.length) {
|
|
639
|
+
<span class="vo-cvq-msg">
|
|
640
|
+
<span><b>{{ selectedRuns.length }} runs selected</b>, {{ formatX(avgX) }} and {{ formatY(avgY) }} on average</span>
|
|
641
|
+
</span>
|
|
642
|
+
@if (ask.observed) {
|
|
643
|
+
<button type="button" class="vo-pill vo-soft vo-sm" (click)="runAsk()">
|
|
644
|
+
<vo-icon name="spark" size="xs"></vo-icon>Ask the agent why
|
|
645
|
+
</button>
|
|
646
|
+
}
|
|
647
|
+
} @else {
|
|
648
|
+
<span class="vo-cvq-msg">
|
|
649
|
+
<vo-icon class="vo-i" name="spark" size="xs"></vo-icon>
|
|
650
|
+
<span>{{ note ?? defaultNote }}</span>
|
|
651
|
+
</span>
|
|
652
|
+
}
|
|
653
|
+
</div>
|
|
654
|
+
</div>
|
|
655
|
+
`, styles: [".vo-cvq{padding:var(--vo-s-4);display:flex;flex-direction:column;gap:var(--vo-s-3)}.vo-cvq-h{display:flex;align-items:flex-start;justify-content:space-between;gap:10px;flex-wrap:wrap}.vo-cvq-t{display:flex;flex-direction:column;font-size:13.5px;line-height:1.4}.vo-cvq-t b{font-weight:500}.vo-cvq-t .vo-muted{font-size:12px}.vo-cvq-lg{display:flex;gap:2px}.vo-cvq-k{display:flex;align-items:center;gap:6px;height:26px;padding:0 8px;border-radius:var(--vo-r-pill);font-size:12px;color:var(--vo-muted);transition:color .2s,background .2s}@media (hover:hover) and (pointer:fine){.vo-cvq-k:hover{background:var(--vo-row)}}.vo-cvq-k[aria-pressed=true]{color:var(--vo-fg)}.vo-cvq-k svg{width:10px;height:10px;overflow:visible;transition:opacity .3s,transform .3s var(--vo-ease)}.vo-cvq-k[aria-pressed=false] svg{opacity:.3;transform:scale(.7)}.vo-cvq-pl{position:relative;height:244px;touch-action:pan-y;cursor:crosshair;user-select:none;-webkit-user-select:none;border-radius:var(--vo-r-sm)}.vo-cvq-pl:focus-visible{outline-offset:4px}.vo-cvq-svg{position:absolute;inset:0;width:100%;height:100%;overflow:visible}.vo-cvq-svg .vo-gl{stroke:color-mix(in srgb,var(--vo-line) 40%,transparent);stroke-width:1}.vo-cvq-svg .vo-ax{stroke:color-mix(in srgb,var(--vo-line) 80%,transparent);stroke-width:1}.vo-cvq-svg .vo-md{stroke:color-mix(in srgb,var(--vo-faint) 75%,transparent);stroke-width:1;stroke-dasharray:3 3}.vo-cvq-svg text{font-size:10.5px;fill:var(--vo-muted);font-family:var(--vo-sans)}.vo-cvq-svg text.vo-q{font-size:10px}.vo-cvq-svg text.vo-at{font-size:10.5px}.vo-cvq-svg .vo-d{stroke:var(--vo-surface);stroke-width:1;fill-opacity:.85;transition:opacity .25s,fill-opacity .25s}.vo-cvq-svg .vo-d.vo-dim{opacity:.18}.vo-cvq-svg .vo-d.vo-off{opacity:0}.vo-cvq-svg .vo-d.vo-sel{fill-opacity:1;stroke:var(--vo-fg);stroke-width:1.2}.vo-cvq-svg .vo-d.vo-on{fill-opacity:1;stroke:var(--vo-fg);stroke-width:1.5}.vo-cvq-svg .vo-ring{fill:none;stroke:var(--vo-fg2);stroke-width:1.2;stroke-dasharray:3 2.5}.vo-cvq-svg .vo-box{fill:color-mix(in srgb,var(--vo-fg) 5%,transparent);stroke:var(--vo-fg2);stroke-width:1;stroke-dasharray:4 3}.vo-cvq-tt{position:absolute;left:0;top:0;padding:6px 9px;border-radius:calc(10px * var(--vo-rk));background:var(--vo-ink);color:var(--vo-on-ink);font-size:11.5px;display:flex;flex-direction:column;opacity:0;transform:translate(-50%,-100%) translateY(-6px);transition:opacity .15s;pointer-events:none;white-space:nowrap;z-index:2}.vo-cvq-tt span{opacity:.75}.vo-cvq-tt.vo-on{opacity:1}.vo-cvq-ft{min-height:72px;display:flex;align-items:center;gap:var(--vo-s-2);padding:var(--vo-s-2) var(--vo-s-3);border-radius:var(--vo-r-in);background:var(--vo-row);font-size:12.5px;color:var(--vo-fg2)}.vo-cvq-msg{flex:1;min-width:0;display:flex;align-items:center;gap:var(--vo-s-2)}.vo-cvq-msg .vo-i{flex:none;color:var(--vo-accent-fg,var(--vo-accent))}.vo-cvq-msg b{font-weight:500;color:var(--vo-fg)}.vo-cvq-ft .vo-pill{flex:none}.vo-cvq-ft .vo-ib{flex:none;width:26px;height:26px}.vo-cvq-ft{flex-wrap:wrap}.vo-cvq-msg{flex:1 1 180px}.vo-cvq{container-type:inline-size}@container (max-width:340px){.vo-cvq-pl{height:228px}.vo-cvq-ft{flex-direction:column;align-items:stretch;justify-content:center;gap:10px}.vo-cvq-msg{flex:none}.vo-cvq-msg:has(>.vo-pill){flex-direction:column;align-items:stretch;gap:10px}.vo-cvq-ft .vo-pill{justify-content:center}}.vo-pill{display:inline-flex;align-items:center;justify-content:center;gap:7px;height:32px;padding:0 14px;border-radius:var(--vo-r-pill);font-size:13px;font-weight:500;white-space:nowrap;cursor:pointer;transition:background var(--vo-t-fast),color var(--vo-t-fast),opacity var(--vo-t-fast),transform .15s}.vo-pill:active{transform:scale(.97)}.vo-pill.vo-soft{background:var(--vo-chip);color:var(--vo-fg2)}@media (hover:hover) and (pointer:fine){.vo-pill.vo-soft:hover{background:var(--vo-row,var(--vo-hover));color:var(--vo-fg)}}.vo-pill.vo-sm{height:28px;padding:0 11px;font-size:12.5px}.vo-shim{background:linear-gradient(90deg,var(--vo-muted) 25%,var(--vo-fg) 50%,var(--vo-muted) 75%);background-size:200% 100%;-webkit-background-clip:text;background-clip:text;color:transparent;animation:vo-shim 1.4s linear infinite}@keyframes vo-shim{to{background-position:-200% 0}}@media (prefers-reduced-motion:reduce){.vo-shim{color:var(--vo-fg);background:none}}\n"] }]
|
|
656
|
+
}], propDecorators: { runs: [{
|
|
657
|
+
type: Input,
|
|
658
|
+
args: [{ required: true }]
|
|
659
|
+
}], series: [{
|
|
660
|
+
type: Input,
|
|
661
|
+
args: [{ required: true }]
|
|
662
|
+
}], className: [{
|
|
663
|
+
type: Input
|
|
664
|
+
}], title: [{
|
|
665
|
+
type: Input
|
|
666
|
+
}], subtitle: [{
|
|
667
|
+
type: Input
|
|
668
|
+
}], xDomain: [{
|
|
669
|
+
type: Input
|
|
670
|
+
}], yDomain: [{
|
|
671
|
+
type: Input
|
|
672
|
+
}], xTicks: [{
|
|
673
|
+
type: Input
|
|
674
|
+
}], yTicks: [{
|
|
675
|
+
type: Input
|
|
676
|
+
}], xTitle: [{
|
|
677
|
+
type: Input
|
|
678
|
+
}], yTitle: [{
|
|
679
|
+
type: Input
|
|
680
|
+
}], formatX: [{
|
|
681
|
+
type: Input
|
|
682
|
+
}], formatY: [{
|
|
683
|
+
type: Input
|
|
684
|
+
}], formatSize: [{
|
|
685
|
+
type: Input
|
|
686
|
+
}], quadrants: [{
|
|
687
|
+
type: Input
|
|
688
|
+
}], ringed: [{
|
|
689
|
+
type: Input
|
|
690
|
+
}], note: [{
|
|
691
|
+
type: Input
|
|
692
|
+
}], selected: [{
|
|
693
|
+
type: Input
|
|
694
|
+
}], selectedChange: [{
|
|
695
|
+
type: Output
|
|
696
|
+
}], ask: [{
|
|
697
|
+
type: Output
|
|
698
|
+
}], plotRef: [{
|
|
699
|
+
type: ViewChild,
|
|
700
|
+
args: ['plot']
|
|
701
|
+
}], tipRef: [{
|
|
702
|
+
type: ViewChild,
|
|
703
|
+
args: ['tip']
|
|
704
|
+
}] } });
|
|
705
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2NhdHRlci1jaGFydC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9zY2F0dGVyLWNoYXJ0L3NjYXR0ZXItY2hhcnQuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDZEQUE2RDtBQUM3RCxFQUFFO0FBQ0YseUVBQXlFO0FBQ3pFLGdGQUFnRjtBQUNoRiw4RUFBOEU7QUFDOUUsaUZBQWlGO0FBQ2pGLGdGQUFnRjtBQUNoRiwrRUFBK0U7QUFDL0UsNEVBQTRFO0FBQzVFLG9FQUFvRTtBQUNwRSxFQUFFO0FBQ0YsOEVBQThFO0FBQzlFLGlGQUFpRjtBQUVqRixPQUFPLEVBRUwsaUJBQWlCLEVBQ2pCLFNBQVMsRUFFVCxZQUFZLEVBQ1osS0FBSyxFQUVMLE1BQU0sRUFDTixTQUFTLEVBQ1QsaUJBQWlCLEVBQ2pCLE1BQU0sR0FDUCxNQUFNLGVBQWUsQ0FBQztBQUN2QixPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sd0JBQXdCLENBQUM7QUFDekQsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7O0FBd0N0RSxNQUFNLEdBQUcsR0FBRztJQUNWLGNBQWM7SUFDZCxjQUFjO0lBQ2QsY0FBYztJQUNkLGNBQWM7SUFDZCxjQUFjO0lBQ2QsY0FBYztDQUNmLENBQUM7QUFDRixNQUFNLE1BQU0sR0FBbUIsQ0FBQyxRQUFRLEVBQUUsUUFBUSxFQUFFLFVBQVUsQ0FBQyxDQUFDO0FBRWhFLE1BQU0sTUFBTSxHQUFHLENBQUMsQ0FBVyxFQUFVLEVBQUU7SUFDckMsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNO1FBQUUsT0FBTyxDQUFDLENBQUM7SUFDeEIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUN2QyxNQUFNLENBQUMsR0FB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S0FBSyxJQUFJLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDL0IsSUFBSSxDQUFDLEdBQUcsQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUN4QixPQUFPO1FBQ1QsQ0FBQztRQUNELElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUM7UUFDMUMsSUFBSSxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztRQUUvQixNQUFNLElBQUksR0FBRyxDQUFDLENBQVcsRUFBRSxDQUFtQixFQUFZLEVBQUUsQ0FDMUQsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMvRSxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUMxQyxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQztRQUUxQyxNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7UUFDOUIsSUFBSSxDQUFDLEVBQUUsR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMs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QUMsQ0FBQyxDQUFDO1lBQ2pCLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztTQUNmLENBQUMsQ0FBQyxDQUFDO1FBRU4sSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUUzRyxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ3JELElBQUksSUFBSSxDQUFDLEVBQUUsSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLENBQUM7WUFDM0IsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsV0FBVyxDQUFDO1lBQ2hELElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDeEUsSUFBSSxDQUFDLEdBQUcsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxJ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QUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBRUcsT0FBTztzQkFBZixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFFRyxNQUFNO3NCQUFkLEtBQUs7Z0JBRUcsTUFBTTtzQkFBZCxLQUFLO2dCQUNHLE1BQU07c0JBQWQsS0FBSztnQkFDRyxNQUFNO3NCQUFkLEtBQUs7Z0JBQ0csT0FBTztzQkFBZixLQUFLO2dCQUNHLE9BQU87c0JBQWYsS0FBSztnQkFDRyxVQUFVO3NCQUFsQixLQUFLO2dCQUVHLFNBQVM7c0JBQWpCLEtBQUs7Z0JBT0csTUFBTTtzQkFBZCxLQUFLO2dCQUVHLElBQUk7c0JBQVosS0FBSztnQkFFTyxRQUFRO3NCQUFwQixLQUFLO2dCQVVJLGNBQWM7c0JBQXZCLE1BQU07Z0JBRUcsR0FBRztzQkFBWixNQUFNO2dCQUVZLE9BQU87c0JBQXpCLFNBQVM7dUJBQUMsTUFBTTtnQkFDQyxNQUFNO3NCQUF2QixTQUFTO3VCQUFDLEtBQUsiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBmcmFtZXdvcmsvYW5ndWxhci9zY2F0dGVyLWNoYXJ0L3NjYXR0ZXItY2hhcnQuY29tcG9uZW50LnRzXG4vL1xuLy8gTmF0aXZlIEFuZ3VsYXIgcG9ydCBvZiBmcmFtZXdvcmsvcmVhY3Qvc2NhdHRlci1jaGFydC9TY2F0dGVyQ2hhcnQudHN4LlxuLy8gRXZlcnkgcnVuIGlzIGEgZG90IGJ5IGNvc3QgKGFsb25nKSBhbmQgZXZhbCBzY29yZSAodXApLCBzaXplZCBieSB0b2tlbnMsIHdpdGhcbi8vIGEgY29sb3VyIGFuZCBhIHNoYXBlIHBlciBzZXJpZXMuIERhc2hlZCBtZWRpYW4gbGluZXMgY3V0IHRoZSBwbG90IGludG8gZm91clxuLy8gbmFtZWQgcXVhZHJhbnRzOyBwb2ludGluZyBzbmFwcyB0byB0aGUgbmVhcmVzdCBydW4gYW5kIGEgZHJhZyBkcmF3cyBhIGJveCB0aGF0XG4vLyBzZWxlY3RzIHRoZSBydW5zIGluIGl0LiBJbnB1dHMgbWlycm9yIHRoZSBSZWFjdCBwcm9wczsgUmVhY3QgY2FsbGJhY2tzIGJlY29tZVxuLy8gQE91dHB1dCBFdmVudEVtaXR0ZXJzLiBUaGUgcGxvdCBtZWFzdXJlcyBpdHNlbGYgd2l0aCBhIFJlc2l6ZU9ic2VydmVyIHNldCB1cFxuLy8gaW4gbmdBZnRlclZpZXdJbml0IGFuZCB0b3JuIGRvd24gaW4gbmdPbkRlc3Ryb3ksIG1pcnJvcmluZyB0aGUgdmFuaWxsYSBKU1xuLy8gKHNjYXR0ZXItY2hhcnQuanMpLiBTdHlsaW5nIGZsb3dzIG9ubHkgdGhyb3VnaCB0aGUgLS12by0qIHRva2Vucy5cbi8vXG4vLyBJY29uczogb25seSB0aGUgXCJzcGFya1wiIGdseXBoIGlzIHVzZWQgKHRoZSBub3RlIGFuZCB0aGUgXCJBc2sgdGhlIGFnZW50IHdoeVwiXG4vLyBidXR0b24pLCB2aWEgVm9JY29uQ29tcG9uZW50IOKAlCB0aGUgc2FtZSBnbHlwaCB0aGUgUmVhY3QvVmFuaWxsYSBvcmlnaW5hbHMgdXNlLlxuXG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3RvclJlZixcbiAgQ29tcG9uZW50LFxuICBFbGVtZW50UmVmLFxuICBFdmVudEVtaXR0ZXIsXG4gIElucHV0LFxuICBPbkRlc3Ryb3ksXG4gIE91dHB1dCxcbiAgVmlld0NoaWxkLFxuICBWaWV3RW5jYXBzdWxhdGlvbixcbiAgaW5qZWN0LFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFZvSWNvbkNvbXBvbmVudCB9IGZyb20gJy4uL2NvcmUvaWNvbi5jb21wb25lbnQnO1xuaW1wb3J0IHsgUmVkdWNlZE1vdGlvblNlcnZpY2UgfSBmcm9tICcuLi9jb3JlL3JlZHVjZWQtbW90aW9uLnNlcnZpY2UnO1xuXG4vKiogQSBzaGFwZSBmb3IgYSBzZXJpZXMsIHNvIGl0IHJlYWRzIHdpdGhvdXQgY29sb3VyIHRvby4gKi9cbmV4cG9ydCB0eXBlIFNjYXR0ZXJTaGFwZSA9ICdjaXJjbGUnIHwgJ3NxdWFyZScgfCAndHJpYW5nbGUnO1xuXG4vKiogT25lIHJ1bjogYSBkb3Qgb24gdGhlIGNoYXJ0LiAqL1xuZXhwb3J0IGludGVyZmFjZSBTY2F0dGVyUnVuIHtcbiAgaWQ6IHN0cmluZyB8IG51bWJlcjtcbiAgLyoqIFdoaWNoIHNlcmllcyBpdCBiZWxvbmdzIHRvLCBieSBrZXkuICovXG4gIHNlcmllczogc3RyaW5nO1xuICAvKiogQWxvbmcgdGhlIGJvdHRvbSwgbGlrZSBjb3N0IHBlciBydW4gaW4gZG9sbGFycy4gKi9cbiAgeDogbnVtYmVyO1xuICAvKiogVXAgdGhlIHNpZGUsIGxpa2UgYW4gZXZhbCBzY29yZSBpbiAlLiAqL1xuICB5OiBudW1iZXI7XG4gIC8qKiBJdHMgZG90J3Mgc2l6ZSwgbGlrZSB0aG91c2FuZHMgb2YgdG9rZW5zLiAqL1xuICBzaXplOiBudW1iZXI7XG59XG5cbi8qKiBPbmUgc2VyaWVzOiBhIGNvbG91ciBhbmQgYSBzaGFwZSwgd2l0aCBhIGxlZ2VuZCBsYWJlbC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU2NhdHRlclNlcmllcyB7XG4gIGtleTogc3RyaW5nO1xuICBsYWJlbDogc3RyaW5nO1xuICAvKiogRGVmYXVsdHMgdG8gdGhlIGNoYXJ0IHBhbGV0dGUgaW4gb3JkZXI6IC0tdm8tYzEsIC0tdm8tYzIsIC0tdm8tYzMuICovXG4gIGNvbG9yPzogc3RyaW5nO1xuICAvKiogRWFjaCBzZXJpZXMgaGFzIGEgc2hhcGUgYXMgd2VsbCBhcyBhIGNvbG91ciwgc28gaXQgcmVhZHMgd2l0aG91dCBjb2xvdXIgdG9vLiAqL1xuICBzaGFwZT86IFNjYXR0ZXJTaGFwZTtcbn1cblxuLyoqIEludGVybmFsIHBlci1kb3QgcmVuZGVyIGRhdGEuICovXG5pbnRlcmZhY2UgRG90VmlldyB7XG4gIHJ1bjogU2NhdHRlclJ1bjtcbiAgaW5kZXg6IG51bWJlcjtcbiAgY2xzOiBzdHJpbmc7XG4gIGZpbGw6IHN0cmluZztcbiAgc2hhcGU6IFNjYXR0ZXJTaGFwZTtcbiAgY3g6IG51bWJlcjtcbiAgY3k6IG51bWJlcjtcbiAgcjogbnVtYmVyO1xufVxuXG5jb25zdCBQQUwgPSBbXG4gICd2YXIoLS12by1jMSknLFxuICAndmFyKC0tdm8tYzIpJyxcbiAgJ3ZhcigtLXZvLWMzKScsXG4gICd2YXIoLS12by1jNCknLFxuICAndmFyKC0tdm8tYzUpJyxcbiAgJ3ZhcigtLXZvLWM2KScsXG5dO1xuY29uc3QgU0hBUEVTOiBTY2F0dGVyU2hhcGVbXSA9IFsnY2lyY2xlJywgJ3NxdWFyZScsICd0cmlhbmdsZSddO1xuXG5jb25zdCBtZWRpYW4gPSAoYTogbnVtYmVyW10pOiBudW1iZXIgPT4ge1xuICBpZiAoIWEubGVuZ3RoKSByZXR1cm4gMDtcbiAgY29uc3QgcyA9IFsuLi5hXS5zb3J0KChwLCBxKSA9PiBwIC0gcSk7XG4gIGNvbnN0IG0gPSBzLmxlbmd0aCA+PiAxO1xuICByZXR1cm4gcy5sZW5ndGggJSAyID8gc1ttXSA6IChzW20gLSAxXSArIHNbbV0pIC8gMjtcbn07XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3ZvLXNjYXR0ZXItY2hhcnQnLFxuICBzdGFuZGFsb25lOiB0cnVlLFxuICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxuICBpbXBvcnRzOiBbVm9JY29uQ29tcG9uZW50XSxcbiAgdGVtcGxhdGU6IGBcbiAgICA8ZGl2IGRhdGEtdm89XCJcIiBjbGFzcz1cInZvLWN2cSB2by1wYW5lbFwiIFtjbGFzc109XCJjbGFzc05hbWVcIj5cbiAgICAgIDxkaXYgY2xhc3M9XCJ2by1jdnEtaFwiPlxuICAgICAgICA8ZGl2IGNsYXNzPVwidm8tY3ZxLXRcIj5cbiAgICAgICAgICA8Yj57eyB0aXRsZSB9fTwvYj5cbiAgICAgICAgICBAaWYgKHN1YnRpdGxlKSB7XG4gICAgICAgICAgICA8c3BhbiBjbGFzcz1cInZvLW11dGVkXCI+e3sgc3VidGl0bGUgfX08L3NwYW4+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgICAgPGRpdiBjbGFzcz1cInZvLWN2cS1sZ1wiPlxuICAgICAgICAgIEBmb3IgKHMgb2Ygc2VyaWVzOyB0cmFjayBzLmtleSkge1xuICAgICAgICAgICAgPGJ1dHRvblxuICAgICAgICAgICAgICB0eXBlPVwiYnV0dG9uXCJcbiAgICAgICAgICAgICAgY2xhc3M9XCJ2by1jdnEta1wiXG4gICAgICAgICAgICAgIFthdHRyLmFyaWEtcHJlc3NlZF09XCIhb2ZmLmluY2x1ZGVzKHMua2V5KVwiXG4gICAgICAgICAgICAgIChjbGljayk9XCJ0b2dnbGUocy5rZXkpXCJcbiAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgPHN2ZyB2aWV3Qm94PVwiLTYgLTYgMTIgMTJcIiBbc3R5bGUuZmlsbF09XCJjb2xvck9mKHMua2V5KVwiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPlxuICAgICAgICAgICAgICAgIEBzd2l0Y2ggKHNoYXBlT2Yocy5rZXkpKSB7XG4gICAgICAgICAgICAgICAgICBAY2FzZSAoJ2NpcmNsZScpIHsgPGNpcmNsZSBbYXR0ci5jeF09XCIwXCIgW2F0dHIuY3ldPVwiMFwiIFthdHRyLnJdPVwiNC41XCIgLz4gfVxuICAgICAgICAgICAgICAgICAgQGNhc2UgKCdzcXVhcmUnKSB7IDxyZWN0IFthdHRyLnhdPVwiLTQuMDVcIiBbYXR0ci55XT1cIi00LjA1XCIgW2F0dHIud2lkdGhdPVwiOC4xXCIgW2F0dHIuaGVpZ2h0XT1cIjguMVwiIFthdHRyLnJ4XT1cIjEuMTI1XCIgLz4gfVxuICAgICAgICAgICAgICAgICAgQGRlZmF1bHQgeyA8cGF0aCBbYXR0ci5kXT1cInRyaVBhdGgoMCwgMCwgNC41KVwiIC8+IH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgIDwvc3ZnPnt7IHMubGFiZWwgfX1cbiAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgIH1cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L2Rpdj5cblxuICAgICAgPGRpdlxuICAgICAgICAjcGxvdFxuICAgICAgICBjbGFzcz1cInZvLWN2cS1wbFwiXG4gICAgICAgIHRhYmluZGV4PVwiMFwiXG4gICAgICAgIHJvbGU9XCJncm91cFwiXG4gICAgICAgIGFyaWEtcm9sZWRlc2NyaXB0aW9uPVwic2NhdHRlciBjaGFydFwiXG4gICAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwidGl0bGUgKyAnLiBBcnJvdyBrZXlzIHN0ZXAgdGhyb3VnaCB0aGUgcnVucydcIlxuICAgICAgICAocG9pbnRlcmRvd24pPVwib25Qb2ludGVyRG93bigkZXZlbnQpXCJcbiAgICAgICAgKHBvaW50ZXJtb3ZlKT1cIm9uUG9pbnRlck1vdmUoJGV2ZW50KVwiXG4gICAgICAgIChwb2ludGVydXApPVwib25Qb2ludGVyVXAoKVwiXG4gICAgICAgIChwb2ludGVyY2FuY2VsKT1cIm9uUG9pbnRlckNhbmNlbCgpXCJcbiAgICAgICAgKHBvaW50ZXJsZWF2ZSk9XCJvblBvaW50ZXJMZWF2ZSgpXCJcbiAgICAgICAgKGJsdXIpPVwib25CbHVyKClcIlxuICAgICAgICAoa2V5ZG93bik9XCJvbktleURvd24oJGV2ZW50KVwiXG4gICAgICA+XG4gICAgICAgIEBpZiAoVyA+IDApIHtcbiAgICAgICAgICA8c3ZnIGNsYXNzPVwidm8tY3ZxLXN2Z1wiIFthdHRyLnZpZXdCb3hdPVwiJzAgMCAnICsgVyArICcgJyArIEhcIiBhcmlhLWhpZGRlbj1cInRydWVcIj5cbiAgICAgICAgICAgIDwhLS0gYSBmZXcgbGlnaHQgZ3JpZGxpbmVzIGFuZCBxdWlldCB0aWNrIGxhYmVsczsgdGhlIGF4aXMgdGl0bGVzIHNpdCB3ZWxsIGNsZWFyIG9mIHRoZSB0aWNrcyAtLT5cbiAgICAgICAgICAgIEBmb3IgKHYgb2YgeXQ7IHRyYWNrIHYpIHtcbiAgICAgICAgICAgICAgPGc+XG4gICAgICAgICAgICAgICAgPGxpbmUgY2xhc3M9XCJ2by1nbFwiIFthdHRyLngxXT1cImxcIiBbYXR0ci54Ml09XCJXIC0gcnJcIiBbYXR0ci55MV09XCJZKHYpXCIgW2F0dHIueTJdPVwiWSh2KVwiIC8+XG4gICAgICAgICAgICAgICAgPHRleHQgW2F0dHIueF09XCJsIC0gNlwiIFthdHRyLnldPVwiWSh2KSArIDMuNVwiIHRleHQtYW5jaG9yPVwiZW5kXCI+e3sgdiB9fTwvdGV4dD5cbiAgICAgICAgICAgICAgPC9nPlxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgQGZvciAodiBvZiB4dDsgdHJhY2sgJGluZGV4KSB7XG4gICAgICAgICAgICAgIDx0ZXh0XG4gICAgICAgICAgICAgICAgW2F0dHIueF09XCJYKHYpXCJcbiAgICAgICAgICAgICAgICBbYXR0ci55XT1cIkggLSBiICsgMTVcIlxuICAgICAgICAgICAgICAgIFthdHRyLnRleHQtYW5jaG9yXT1cIiRpbmRleCA9PT0gMCA/ICdzdGFydCcgOiAkaW5kZXggPT09IHh0Lmxlbmd0aCAtIDEgPyAnZW5kJyA6ICdtaWRkbGUnXCJcbiAgICAgICAgICAgICAgPnt7IGZvcm1hdFgodikgfX08L3RleHQ+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICA8bGluZSBjbGFzcz1cInZvLWF4XCIgW2F0dHIueDFdPVwibFwiIFthdHRyLngyXT1cIlcgLSByclwiIFthdHRyLnkxXT1cIkggLSBiXCIgW2F0dHIueTJdPVwiSCAtIGJcIiAvPlxuICAgICAgICAgICAgPHRleHQgY2xhc3M9XCJ2by1hdFwiIFthdHRyLnhdPVwiVyAtIHJyXCIgW2F0dHIueV09XCJIIC0gMVwiIHRleHQtYW5jaG9yPVwiZW5kXCI+e3sgeFRpdGxlIH19PC90ZXh0PlxuICAgICAgICAgICAgPHRleHQgY2xhc3M9XCJ2by1hdFwiIFthdHRyLnhdPVwiLXRcIiBbYXR0ci55XT1cIjlcIiB0cmFuc2Zvcm09XCJyb3RhdGUoLTkwKVwiIHRleHQtYW5jaG9yPVwiZW5kXCI+e3sgeVRpdGxlIH19PC90ZXh0PlxuICAgICAgICAgICAgPGxpbmUgY2xhc3M9XCJ2by1tZFwiIFthdHRyLngxXT1cIlgobXgpXCIgW2F0dHIueDJdPVwiWChteClcIiBbYXR0ci55MV09XCJ0XCIgW2F0dHIueTJdPVwiSCAtIGJcIiAvPlxuICAgICAgICAgICAgPGxpbmUgY2xhc3M9XCJ2by1tZFwiIFthdHRyLngxXT1cImxcIiBbYXR0ci54Ml09XCJXIC0gcnJcIiBbYXR0ci55MV09XCJZKG15KVwiIFthdHRyLnkyXT1cIlkobXkpXCIgLz5cbiAgICAgICAgICAgIEBpZiAoIW5hcnJvdykge1xuICAgICAgICAgICAgICA8dGV4dCBjbGFzcz1cInZvLXFcIiBbYXR0ci54XT1cImwgKyA2XCIgW2F0dHIueV09XCJ0ICsgMTFcIj57eyBxdWFkcmFudHNbMF0gfX08L3RleHQ+XG4gICAgICAgICAgICAgIDx0ZXh0IGNsYXNzPVwidm8tcVwiIFthdHRyLnhdPVwiVyAtIHJyIC0gNFwiIFthdHRyLnldPVwidCArIDExXCIgdGV4dC1hbmNob3I9XCJlbmRcIj57eyBxdWFkcmFudHNbMV0gfX08L3RleHQ+XG4gICAgICAgICAgICAgIDx0ZXh0IGNsYXNzPVwidm8tcVwiIFthdHRyLnhdPVwiVyAtIHJyIC0gNFwiIFthdHRyLnldPVwiSCAtIGIgLSA2XCIgdGV4dC1hbmNob3I9XCJlbmRcIj57eyBxdWFkcmFudHNbMl0gfX08L3RleHQ+XG4gICAgICAgICAgICAgIDx0ZXh0IGNsYXNzPVwidm8tcVwiIFthdHRyLnhdPVwibCArIDZcIiBbYXR0ci55XT1cIkggLSBiIC0gNlwiPnt7IHF1YWRyYW50c1szXSB9fTwvdGV4dD5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIEBmb3IgKGQgb2YgZG90czsgdHJhY2sgZC5ydW4uaWQpIHtcbiAgICAgICAgICAgICAgPGcgW2NsYXNzXT1cImQuY2xzXCIgW3N0eWxlLmZpbGxdPVwiZC5maWxsXCI+XG4gICAgICAgICAgICAgICAgQHN3aXRjaCAoZC5zaGFwZSkge1xuICAgICAgICAgICAgICAgICAgQGNhc2UgKCdjaXJjbGUnKSB7IDxjaXJjbGUgW2F0dHIuY3hdPVwiZC5jeFwiIFthdHRyLmN5XT1cImQuY3lcIiBbYXR0ci5yXT1cImQuclwiIC8+IH1cbiAgICAgICAgICAgICAgICAgIEBjYXNlICgnc3F1YXJlJykgeyA8cmVjdCBbYXR0ci54XT1cImQuY3ggLSBkLnIgKiAwLjlcIiBbYXR0ci55XT1cImQuY3kgLSBkLnIgKiAwLjlcIiBbYXR0ci53aWR0aF09XCJkLnIgKiAxLjhcIiBbYXR0ci5oZWlnaHRdPVwiZC5yICogMS44XCIgW2F0dHIucnhdPVwiZC5yICogMC4yNVwiIC8+IH1cbiAgICAgICAgICAgICAgICAgIEBkZWZhdWx0IHsgPHBhdGggW2F0dHIuZF09XCJ0cmlQYXRoKGQuY3gsIGQuY3ksIGQucilcIiAvPiB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICA8L2c+XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBAZm9yIChkIG9mIHJpbmdEb3RzOyB0cmFjayBkLnJ1bi5pZCkge1xuICAgICAgICAgICAgICA8Y2lyY2xlIGNsYXNzPVwidm8tcmluZ1wiIFthdHRyLmN4XT1cImQuY3hcIiBbYXR0ci5jeV09XCJkLmN5XCIgW2F0dHIucl09XCJkLnIgKyA2XCIgLz5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIEBpZiAoYm94KSB7XG4gICAgICAgICAgICAgIDxyZWN0XG4gICAgICAgICAgICAgICAgY2xhc3M9XCJ2by1ib3hcIlxuICAgICAgICAgICAgICAgIFthdHRyLnhdPVwibWluKGJveFswXSwgYm94WzJdKVwiXG4gICAgICAgICAgICAgICAgW2F0dHIueV09XCJtaW4oYm94WzFdLCBib3hbM10pXCJcbiAgICAgICAgICAgICAgICBbYXR0ci53aWR0aF09XCJhYnMoYm94WzJdIC0gYm94WzBdKVwiXG4gICAgICAgICAgICAgICAgW2F0dHIuaGVpZ2h0XT1cImFicyhib3hbM10gLSBib3hbMV0pXCJcbiAgICAgICAgICAgICAgICBbYXR0ci5yeF09XCIzXCJcbiAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIH1cbiAgICAgICAgICA8L3N2Zz5cbiAgICAgICAgfVxuICAgICAgICA8ZGl2ICN0aXAgY2xhc3M9XCJ2by1jdnEtdHRcIiBbY2xhc3Mudm8tb25dPVwiaHJcIiBbc3R5bGUubGVmdC5weF09XCJ0dFhcIiBbc3R5bGUudG9wLnB4XT1cInR0WVwiPlxuICAgICAgICAgIEBpZiAoaHIpIHtcbiAgICAgICAgICAgIDxiIGNsYXNzPVwidm8tbnVtXCI+e3sgZm9ybWF0WChoci54KSB9fSDCtyB7eyBmb3JtYXRZKGhyLnkpIH19PC9iPlxuICAgICAgICAgICAgPHNwYW4+UnVuIHt7IGhyLmlkIH19LCB7eyBsYWJlbE9mKGhyLnNlcmllcykgfX0sIHt7IGZvcm1hdFNpemUoaHIuc2l6ZSkgfX08L3NwYW4+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2IGNsYXNzPVwidm8tY3ZxLWZ0XCIgYXJpYS1saXZlPVwicG9saXRlXCI+XG4gICAgICAgIEBpZiAoaHIgJiYgZm9jdXNlZCkge1xuICAgICAgICAgIDxzcGFuIGNsYXNzPVwidm8tY3ZxLW1zZ1wiPlxuICAgICAgICAgICAgPHNwYW4+PGI+UnVuIHt7IGhyLmlkIH19PC9iPiwge3sgbGFiZWxPZihoci5zZXJpZXMpIH19OiB7eyBmb3JtYXRYKGhyLngpIH19LCB7eyBmb3JtYXRZKGhyLnkpIH19LCB7eyBmb3JtYXRTaXplKGhyLnNpemUpIH19LiB7eyBvcmRlci5pbmRleE9mKGhvdCkgKyAxIH19IG9mIHt7IG9yZGVyLmxlbmd0aCB9fTwvc3Bhbj5cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgIH0gQGVsc2UgaWYgKGFuc3dlcikge1xuICAgICAgICAgIDxzcGFuIGNsYXNzPVwidm8tY3ZxLW1zZ1wiPlxuICAgICAgICAgICAgPHZvLWljb24gY2xhc3M9XCJ2by1pXCIgbmFtZT1cInNwYXJrXCIgc2l6ZT1cInhzXCI+PC92by1pY29uPlxuICAgICAgICAgICAgPHNwYW4gW2NsYXNzLnZvLXNoaW1dPVwiYW5zd2VyLmJ1c3lcIj57eyBhbnN3ZXIuYnVzeSA/ICdMb29raW5nIGF0ICcgKyBzZWxlY3RlZFJ1bnMubGVuZ3RoICsgJyBydW5zJyA6IGFuc3dlci50ZXh0IH19PC9zcGFuPlxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgfSBAZWxzZSBpZiAoc2VsZWN0ZWRSdW5zLmxlbmd0aCkge1xuICAgICAgICAgIDxzcGFuIGNsYXNzPVwidm8tY3ZxLW1zZ1wiPlxuICAgICAgICAgICAgPHNwYW4+PGI+e3sgc2VsZWN0ZWRSdW5zLmxlbmd0aCB9fSBydW5zIHNlbGVjdGVkPC9iPiwge3sgZm9ybWF0WChhdmdYKSB9fSBhbmQge3sgZm9ybWF0WShhdmdZKSB9fSBvbiBhdmVyYWdlPC9zcGFuPlxuICAgICAgICAgIDwvc3Bhbj5cbiAgICAgICAgICBAaWYgKGFzay5vYnNlcnZlZCkge1xuICAgICAgICAgICAgPGJ1dHRvbiB0eXBlPVwiYnV0dG9uXCIgY2xhc3M9XCJ2by1waWxsIHZvLXNvZnQgdm8tc21cIiAoY2xpY2spPVwicnVuQXNrKClcIj5cbiAgICAgICAgICAgICAgPHZvLWljb24gbmFtZT1cInNwYXJrXCIgc2l6ZT1cInhzXCI+PC92by1pY29uPkFzayB0aGUgYWdlbnQgd2h5XG4gICAgICAgICAgICA8L2J1dHRvbj5cbiAgICAgICAgICB9XG4gICAgICAgIH0gQGVsc2Uge1xuICAgICAgICAgIDxzcGFuIGNsYXNzPVwidm8tY3ZxLW1zZ1wiPlxuICAgICAgICAgICAgPHZvLWljb24gY2xhc3M9XCJ2by1pXCIgbmFtZT1cInNwYXJrXCIgc2l6ZT1cInhzXCI+PC92by1pY29uPlxuICAgICAgICAgICAgPHNwYW4+e3sgbm90ZSA/PyBkZWZhdWx0Tm90ZSB9fTwvc3Bhbj5cbiAgICAgICAgICA8L3NwYW4+XG4gICAgICAgIH1cbiAgICAgIDwvZGl2PlxuICAgIDwvZGl2PlxuICBgLFxuICBzdHlsZVVybDogJy4vc2NhdHRlci1jaGFydC5jc3MnLFxufSlcbmV4cG9ydCBjbGFzcyBTY2F0dGVyQ2hhcnRDb21wb25lbnQgaW1wbGVtZW50cyBBZnRlclZpZXdJbml0LCBPbkRlc3Ryb3kge1xuICBASW5wdXQoeyByZXF1aXJlZDogdHJ1ZSB9KSBydW5zOiBTY2F0dGVyUnVuW10gPSBbXTtcbiAgQElucHV0KHsgcmVxdWlyZWQ6IHRydWUgfSkgc2VyaWVzOiBTY2F0dGVyU2VyaWVzW10gPSBbXTtcbiAgQElucHV0KCkgY2xhc3NOYW1lID0gJyc7XG4gIEBJbnB1dCgpIHRpdGxlID0gJ0Nvc3QgdnMgcXVhbGl0eSc7XG4gIEBJbnB1dCgpIHN1YnRpdGxlPzogc3RyaW5nO1xuICAvKiogW21pbiwgbWF4XSBvZiBlYWNoIGF4aXMuICovXG4gIEBJbnB1dCgpIHhEb21haW46IFtudW1iZXIsIG51bWJlcl0gPSBbMCwgMC42XTtcbiAgQElucHV0KCkgeURvbWFpbjogW251bWJlciwgbnVtYmVyXSA9IFs2MCwgMTAwXTtcbiAgLyoqIFdoZXJlIHRoZSBsYWJlbHMgZ28gYWxvbmcgdGhlIGJvdHRvbS4gQSBuYXJyb3cgY2hhcnQga2VlcHMgdGhlIHR3byBlbmRzIGFuZCB0aGUgbWlkZGxlLiAqL1xuICBASW5wdXQoKSB4VGlja3M6IG51bWJlcltdID0gWzAsIDAuMiwgMC40LCAwLjZdO1xuICAvKiogV2hlcmUgdGhlIGdyaWRsaW5lcyBhbmQgdGhlaXIgbGFiZWxzIGdvIHVwIHRoZSBzaWRlLiBBIG5hcnJvdyBjaGFydCBrZWVwcyB0aGUgdHdvIGVuZHMgYW5kIHRoZSBtaWRkbGUuICovXG4gIEBJbnB1dCgpIHlUaWNrczogbnVtYmVyW10gPSBbNjAsIDgwLCAxMDBdO1xuICBASW5wdXQoKSB4VGl0bGUgPSAnQ29zdCBwZXIgcnVuIChVU0QpJztcbiAgQElucHV0KCkgeVRpdGxlID0gJ0V2YWwgc2NvcmUgKCUpJztcbiAgQElucHV0KCkgZm9ybWF0WDogKHg6IG51bWJlcikgPT4gc3RyaW5nID0gKHgpID0+ICckJyArIHgudG9GaXhlZCgyKTtcbiAgQElucHV0KCkgZm9ybWF0WTogKHk6IG51bWJlcikgPT4gc3RyaW5nID0gKHkpID0+IE1hdGgucm91bmQoeSkgKyAnJSc7XG4gIEBJbnB1dCgpIGZvcm1hdFNpemU6IChzOiBudW1iZXIpID0+IHN0cmluZyA9IChzKSA9PiBNYXRoLnJvdW5kKHMpICsgJ2sgdG9rZW5zJztcbiAgLyoqIFRoZSBmb3VyIHF1YWRyYW50cyB0aGUgbWVkaWFucyBtYWtlLCBmcm9tIHRoZSB0b3AgbGVmdCwgY2xvY2t3aXNlLiBBIG5hcnJvdyBjaGFydCBrZWVwcyB0aGUgbWVkaWFuIGxpbmVzIGFuZCBsZWF2ZXMgdGhlIG5hbWVzIG91dC4gKi9cbiAgQElucHV0KCkgcXVhZHJhbnRzOiBbc3RyaW5nLCBzdHJpbmcsIHN0cmluZywgc3RyaW5nXSA9IFtcbiAgICAnQ2hlYXAsIGdvb2QnLFxuICAgICdDb3N0bHksIGdvb2QnLFxuICAgICdDb3N0bHksIHdlYWtlcicsXG4gICAgJ0NoZWFwLCB3ZWFrZXInLFxuICBdO1xuICAvKiogUnVucyB0byByaW5nLCBsaWtlIG91dGxpZXJzIHRoZSBhZ2VudCBmb3VuZC4gKi9cbiAgQElucHV0KCkgcmluZ2VkOiAoc3RyaW5nIHwgbnVtYmVyKVtdID0gW107XG4gIC8qKiBUaGUgbGluZSB1bmRlciB0aGUgY2hhcnQgd2hpbGUgbm90aGluZyBpcyBzZWxlY3RlZCBvciBpbiBmb2N1cy4gKi9cbiAgQElucHV0KCkgbm90ZT86IHN0cmluZztcbiAgLyoqIFRoZSBzZWxlY3RlZCBydW5zLCBieSBpZC4gTGVhdmUgaXQgb3V0IHRvIGxldCB0aGUgY2hhcnQgaG9sZCB0aGUgc2VsZWN0aW9uLiAqL1xuICBASW5wdXQoKSBzZXQgc2VsZWN0ZWQodmFsdWU6IChzdHJpbmcgfCBudW1iZXIpW10gfCB1bmRlZmluZWQpIHtcbiAgICB0aGlzLmNvbnRyb2xsZWQgPSB2YWx1ZSAhPT0gdW5kZWZpbmVkO1xuICAgIGlmICh2YWx1ZSAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aGlzLnNlbCA9IHZhbHVlO1xuICAgICAgdGhpcy5hc2tlZCsrO1xuICAgICAgdGhpcy5hbnN3ZXIgPSBudWxsO1xuICAgICAgaWYgKHRoaXMucmVhZHkpIHRoaXMuZHJhdygpO1xuICAgIH1cbiAgfVxuXG4gIEBPdXRwdXQoKSBzZWxlY3RlZENoYW5nZSA9IG5ldyBFdmVudEVtaXR0ZXI8KHN0cmluZyB8IG51bWJlcilbXT4oKTtcbiAgLyoqIEFkZHMgXCJBc2sgdGhlIGFnZW50IHdoeVwiIHRvIGEgc2VsZWN0aW9uLiBSZXR1cm4gdGhlIGFuc3dlciBhbmQgaXQgc3RyZWFtcyBpbi4gKi9cbiAgQE91dHB1dCgpIGFzayA9IG5ldyBFdmVudEVtaXR0ZXI8U2NhdHRlclJ1bltdPigpO1xuXG4gIEBWaWV3Q2hpbGQoJ3Bsb3QnKSBwbG90UmVmITogRWxlbWVudFJlZjxIVE1MRGl2RWxlbWVudD47XG4gIEBWaWV3Q2hpbGQoJ3RpcCcpIHRpcFJlZiE6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+O1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgcmVkdWNlZCA9IGluamVjdChSZWR1Y2VkTW90aW9uU2VydmljZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2RyID0gaW5qZWN0KENoYW5nZURldGVjdG9yUmVmKTtcblxuICAvLyBtZWFzdXJlZCBnZW9tZXRyeVxuICBXID0gMDtcbiAgSCA9IDA7XG4gIG5hcnJvdyA9IGZhbHNlO1xuICBsID0gNDQ7XG4gIGIgPSA0MDtcbiAgdCA9IDY7XG4gIHJyID0gODtcblxuICAvLyByZW5kZXIgc3RhdGVcbiAgZG90czogRG90Vmlld1tdID0gW107XG4gIHJpbmdEb3RzOiBEb3RWaWV3W10gPSBbXTtcbiAgeHQ6IG51bWJlcltdID0gW107XG4gIHl0OiBudW1iZXJbXSA9IFtdO1xuICBteCA9IDA7XG4gIG15ID0gMDtcbiAgaG90ID0gLTE7XG4gIGhyOiBTY2F0dGVyUnVuIHwgbnVsbCA9IG51bGw7XG4gIGJveDogbnVtYmVyW10gfCBudWxsID0gbnVsbDtcbiAgdHRYID0gMDtcbiAgdHRZID0gMDtcbiAgZm9jdXNlZCA9IGZhbHNlO1xuICBvcmRlcjogbnVtYmVyW10gPSBbXTtcbiAgc2VsZWN0ZWRSdW5zOiBTY2F0dGVyUnVuW10gPSBbXTtcbiAgYXZnWCA9IDA7XG4gIGF2Z1kgPSAwO1xuICBhbnN3ZXI6IHsgdGV4dDogc3RyaW5nOyBidXN5OiBib29sZWFuIH0gfCBudWxsID0gbnVsbDtcblxuICBvZmY6IHN0cmluZ1tdID0gW107XG4gIHByaXZhdGUgc2VsOiAoc3RyaW5nIHwgbnVtYmVyKVtdID0gW107XG4gIHByaXZhdGUgY29udHJvbGxlZCA9IGZhbHNlO1xuICBwcml2YXRlIHJlYWR5ID0gZmFsc2U7XG4gIHByaXZhdGUgYXNrZWQgPSAwO1xuICBwcml2YXRlIGRyYWc6IHsgeDogbnVtYmVyOyB5OiBudW1iZXI7IGlkOiBudW1iZXI7IG1vdmVkOiBib29sZWFuIH0gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBybz86IFJlc2l6ZU9ic2VydmVyO1xuICBwcml2YXRlIHRpbWVyczogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD5bXSA9IFtdO1xuXG4gIC8vIHRlbXBsYXRlIGhlbHBlcnNcbiAgcmVhZG9ubHkgbWluID0gTWF0aC5taW47XG4gIHJlYWRvbmx5IGFicyA9IE1hdGguYWJzO1xuXG4gIGdldCBkZWZhdWx0Tm90ZSgpOiBzdHJpbmcge1xuICAgIHJldHVybiBgTWVkaWFucyBzcGxpdCB0aGUgcnVuczogJHt0aGlzLmZvcm1hdFgodGhpcy5teCl9IGFuZCAke3RoaXMuZm9ybWF0WSh0aGlzLm15KX0uIERyYWcgYWNyb3NzIHRoZSBjaGFydCB0byBzZWxlY3QgcnVucy5gO1xuICB9XG5cbiAgbmdBZnRlclZpZXdJbml0KCk6IHZvaWQge1xuICAgIGNvbnN0IGVsID0gdGhpcy5wbG90UmVmLm5hdGl2ZUVsZW1lbnQ7XG4gICAgdGhpcy5ybyA9IG5ldyBSZXNpemVPYnNlcnZlcigoKSA9PiB7XG4gICAgICB0aGlzLlcgPSBlbC5jbGllbnRXaWR0aDtcbiAgICAgIHRoaXMuSCA9IGVsLmNsaWVudEhlaWdodDtcbiAgICAgIHRoaXMuZHJhdygpO1xuICAgIH0pO1xuICAgIHRoaXMucm8ub2JzZXJ2ZShlbCk7XG4gICAgdGhpcy5yZWFkeSA9IHRydWU7XG4gICAgdGhpcy5XID0gZWwuY2xpZW50V2lkdGg7XG4gICAgdGhpcy5IID0gZWwuY2xpZW50SGVpZ2h0O1xuICAgIHRoaXMuZHJhdygpO1xuICAgIHRoaXMuY2RyLmRldGVjdENoYW5nZXMoKTtcbiAgfVxuXG4gIC8vIC0tLS0tIHNlcmllcyBsb29rLXVwcyAtLS0tLVxuICBwcml2YXRlIHNpKGtleTogc3RyaW5nKTogbnVtYmVyIHtcbiAgICByZXR1cm4gTWF0aC5tYXgoMCwgdGhpcy5zZXJpZXMuZmluZEluZGV4KChzKSA9PiBzLmtleSA9PT0ga2V5KSk7XG4gIH1cbiAgY29sb3JPZihrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHRoaXMuc2VyaWVzW3RoaXMuc2koa2V5KV0/LmNvbG9yID8/IFBBTFt0aGlzLnNpKGtleSkgJSBQQUwubGVuZ3RoXTtcbiAgfVxuICBzaGFwZU9mKGtleTogc3RyaW5nKTogU2NhdHRlclNoYXBlIHtcbiAgICByZXR1cm4gdGhpcy5zZXJpZXNbdGhpcy5zaShrZXkpXT8uc2hhcGUgPz8gU0hBUEVTW3RoaXMuc2koa2V5KSAlIFNIQVBFUy5sZW5ndGhdO1xuICB9XG4gIGxhYmVsT2Yoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnNlcmllc1t0aGlzLnNpKGtleSldPy5sYWJlbCA/PyAnJztcbiAgfVxuXG4gIC8qKiBUaGUgdHJpYW5nbGUgbWFyaydzIHBhdGgsIHNvIGEgZG90IHJlYWRzIHdpdGhvdXQgY29sb3VyIHRvby4gKi9cbiAgdHJpUGF0aCh4OiBudW1iZXIsIHk6IG51bWJlciwgczogbnVtYmVyKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYE0ke3h9ICR7eSAtIHMgKiAxLjE1fUwke3ggKyBzICogMS4wNX0gJHt5ICsgcyAqIDAuNzV9TCR7eCAtIHMgKiAxLjA1fSAke3kgKyBzICogMC43NX1aYDtcbiAgfVxuXG4gIC8vIC0tLS0tIGdlb21ldHJ5IC0tLS0tXG4gIFgodjogbnVtYmVyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5sICsgKCh2IC0gdGhpcy54RG9tYWluWzBdKSAvICh0aGlzLnhEb21haW5bMV0gLSB0aGlzLnhEb21haW5bMF0pKSAqICh0aGlzLlcgLSB0aGlzLmwgLSB0aGlzLnJyKTtcbiAgfVxuICBZKHY6IG51bWJlcik6IG51bWJlciB7XG4gICAgcmV0dXJuIHRoaXMudCArICgxIC0gKHYgLSB0aGlzLnlEb21haW5bMF0pIC8gKHRoaXMueURvbWFpblsxXSAtIHRoaXMueURvbWFpblswXSkpICogKHRoaXMuSCAtIHRoaXMudCAtIHRoaXMuYik7XG4gIH1cbiAgcHJpdmF0ZSBSKHJ1bjogU2NhdHRlclJ1bik6IG51bWJlciB7XG4gICAgY29uc3Qgc01pbiA9IE1hdGgubWluKC4uLnRoaXMucnVucy5tYXAoKHIpID0+IHIuc2l6ZSkpO1xuICAgIGNvbnN0IHNNYXggPSBNYXRoLm1heCguLi50aGlzLnJ1bnMubWFwKChyKSA9PiByLnNpemUpKTtcbiAgICByZXR1cm4gKDMgKyAoKHJ1bi5zaXplIC0gc01pbikgLyBNYXRoLm1heCgxLCBzTWF4IC0gc01pbikpICogNC41KSAqICh0aGlzLm5hcnJvdyA/IDAuODUgOiAxKTtcbiAgfVxuXG4gIHByaXZhdGUgc2hvd25JZHgoKTogbnVtYmVyW10ge1xuICAgIHJldHVybiB0aGlzLnJ1bnMubWFwKChfLCBpKSA9PiBpKS5maWx0ZXIoKGkpID0+ICF0aGlzLm9mZi5pbmNsdWRlcyh0aGlzLnJ1bnNbaV0uc2VyaWVzKSk7XG4gIH1cblxuICAvLyAtLS0tLSBkcmF3OiByZWNvbXB1dGUgZXZlcnkgdmlldyBtb2RlbCwgbWlycm9yaW5nIHRoZSBSZWFjdCByZW5kZXIgLS0tLS1cbiAgZHJhdygpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMucmVhZHkgfHwgdGhpcy5XIDw9IDApIHtcbiAgICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLm5hcnJvdyA9IHRoaXMuVyA+IDAgJiYgdGhpcy5XIDw9IDM0MDtcbiAgICB0aGlzLmwgPSB0aGlzLm5hcnJvdyA/IDM4IDogNDQ7XG5cbiAgICBjb25zdCBlbmRzID0gKGE6IG51bWJlcltdLCBkOiBbbnVtYmVyLCBudW1iZXJdKTogbnVtYmVyW10gPT5cbiAgICAgIHRoaXMubmFycm93ICYmIGEubGVuZ3RoID4gMyA/IFthWzBdLCAoZFswXSArIGRbMV0pIC8gMiwgYVthLmxlbmd0aCAtIDFdXSA6IGE7XG4gICAgdGhpcy54dCA9IGVuZHModGhpcy54VGlja3MsIHRoaXMueERvbWFpbik7XG4gICAgdGhpcy55dCA9IGVuZHModGhpcy55VGlja3MsIHRoaXMueURvbWFpbik7XG5cbiAgICBjb25zdCBzaG93biA9IHRoaXMuc2hvd25JZHgoKTtcbiAgICB0aGlzLm14ID0gbWVkaWFuKHNob3duLm1hcCgoaSkgPT4gdGhpcy5ydW5zW2ldLngpKTtcbiAgICB0aGlzLm15ID0gbWVkaWFuKHNob3duLm1hcCgoaSkgPT4gdGhpcy5ydW5zW2ldLnkpKTtcblxuICAgIGNvbnN0IHNlbCA9IHRoaXMuc2VsO1xuICAgIHRoaXMuZG90cyA9IHRoaXMucnVucy5tYXAoKHJ1biwgaSkgPT4ge1xuICAgICAgY29uc3Qgb2ZmID0gdGhpcy5vZmYuaW5jbHVkZXMocnVuLnNlcmllcyk7XG4gICAgICBjb25zdCBkaW0gPSB0aGlzLmhyICE9IG51bGwgJiYgdGhpcy5oci5zZXJpZXMgIT09IHJ1bi5zZXJpZXMgJiYgIW9mZjtcbiAgICAgIGNvbnN0IGNscyA9IFsndm8tZCcsIG9mZiA/ICd2by1vZmYnIDogJycsIGRpbSA/ICd2by1kaW0nIDogJycsIGkgPT09IHRoaXMuaG90ID8gJ3ZvLW9uJyA6ICcnLCBzZWwuaW5jbHVkZXMocnVuLmlkKSA/ICd2by1zZWwnIDogJyddXG4gICAgICAgIC5maWx0ZXIoQm9vbGVhbilcbiAgICAgICAgLmpvaW4oJyAnKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHJ1bixcbiAgICAgICAgaW5kZXg6IGksXG4gICAgICAgIGNscyxcbiAgICAgICAgZmlsbDogdGhpcy5jb2xvck9mKHJ1bi5zZXJpZXMpLFxuICAgICAgICBzaGFwZTogdGhpcy5zaGFwZU9mKHJ1bi5zZXJpZXMpLFxuICAgICAgICBjeDogK3RoaXMuWChydW4ueCkudG9GaXhlZCgxKSxcbiAgICAgICAgY3k6ICt0aGlzLlkocnVuLnkpLnRvRml4ZWQoMSksXG4gICAgICAgIHI6ICt0aGlzLlIocnVuKS50b0ZpeGVkKDEpLFxuICAgICAgfTtcbiAgICB9KTtcblxuICAgIHRoaXMucmluZ0RvdHMgPSB0aGlzLnJ1bnNcbiAgICAgIC5maWx0ZXIoKHJ1bikgPT4gdGhpcy5yaW5nZWQuaW5jbHVkZXMocnVuLmlkKSAmJiAhdGhpcy5vZmYuaW5jbHVkZXMocnVuLnNlcmllcykpXG4gICAgICAubWFwKChydW4pID0+ICh7XG4gICAgICAgIHJ1bixcbiAgICAgICAgaW5kZXg6IHRoaXMucnVucy5pbmRleE9mKHJ1biksXG4gICAgICAgIGNsczogJycsXG4gICAgICAgIGZpbGw6IHRoaXMuY29sb3JPZihydW4uc2VyaWVzKSxcbiAgICAgICAgc2hhcGU6IHRoaXMuc2hhcGVPZihydW4uc2VyaWVzKSxcbiAgICAgICAgY3g6IHRoaXMuWChydW4ueCksXG4gICAgICAgIGN5OiB0aGlzLlkocnVuLnkpLFxuICAgICAgICByOiB0aGlzLlIocnVuKSxcbiAgICAgIH0pKTtcblxuICAgIHRoaXMub3JkZXIgPSBbLi4uc2hvd25dLnNvcnQoKGEsIGMpID0+IHRoaXMucnVuc1thXS54IC0gdGhpcy5ydW5zW2NdLnggfHwgdGhpcy5ydW5zW2NdLnkgLSB0aGlzLnJ1bnNbYV0ueSk7XG5cbiAgICB0aGlzLmhyID0gdGhpcy5ob3QgPj0gMCA/IHRoaXMucnVuc1t0aGlzLmhvdF0gOiBudWxsO1xuICAgIGlmICh0aGlzLmhyICYmIHRoaXMudGlwUmVmKSB7XG4gICAgICBjb25zdCB3ID0gdGhpcy50aXBSZWYubmF0aXZlRWxlbWVudC5vZmZzZXRXaWR0aDtcbiAgICAgIHRoaXMudHRYID0gTWF0aC5tYXgodyAvIDIsIE1hdGgubWluKHRoaXMuVyAtIHcgLyAyLCB0aGlzLlgodGhpcy5oci54KSkpO1xuICAgICAgdGhpcy50dFkgPSB0aGlzLlkodGhpcy5oci55KSAtIHRoaXMuUih0aGlzLmhyKTtcbiAgICB9XG5cbiAgICB0aGlzLnNlbGVjdGVkUnVucyA9IHRoaXMucnVucy5maWx0ZXIoKHIpID0+IHNlbC5pbmNsdWRlcyhyLmlkKSk7XG4gICAgaWYgKHRoaXMuc2VsZWN0ZWRSdW5zLmxlbmd0aCkge1xuICAgICAgdGhpcy5hdmdYID0gdGhpcy5zZWxlY3RlZFJ1bnMucmVkdWNlKChhLCByKSA9PiBhICsgci54LCAwKSAvIHRoaXMuc2VsZWN0ZWRSdW5zLmxlbmd0aDtcbiAgICAgIHRoaXMuYXZnWSA9IHRoaXMuc2VsZWN0ZWRSdW5zLnJlZHVjZSgoYSwgcikgPT4gYSArIHIueSwgMCkgLyB0aGlzLnNlbGVjdGVkUnVucy5sZW5ndGg7XG4gICAgfVxuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICB9XG5cbiAgLy8gLS0tLS0gbGVnZW5kIC0tLS0tXG4gIHRvZ2dsZShrZXk6IHN0cmluZyk6IHZvaWQge1xuICAgIGlmICghdGhpcy5vZmYuaW5jbHVkZXMoa2V5KSAmJiB0aGlzLm9mZi5sZW5ndGggPT09IHRoaXMuc2VyaWVzLmxlbmd0aCAtIDEpIHJldHVybjtcbiAgICB0aGlzLmhvdCA9IC0xO1xuICAgIHRoaXMub2ZmID0gdGhpcy5vZmYuaW5jbHVkZXMoa2V5KSA/IHRoaXMub2ZmLmZpbHRlcigoaykgPT4gayAhPT0ga2V5KSA6IFsuLi50aGlzLm9mZiwga2V5XTtcbiAgICB0aGlzLmRyYXcoKTtcbiAgfVxuXG4gIC8vIC0tLS0tIHBvaW50ZXIgLyBzZWxlY3Rpb24gLS0tLS1cbiAgcHJpdmF0ZSBsb2NhbChlOiBQb2ludGVyRXZlbnQpOiBbbnVtYmVyLCBudW1iZXJdIHtcbiAgICBjb25zdCByID0gdGhpcy5wbG90UmVmLm5hdGl2ZUVsZW1lbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCk7XG4gICAgcmV0dXJuIFtlLmNsaWVudFggLSByLmxlZnQsIGUuY2xpZW50WSAtIHIudG9wXTtcbiAgfVxuICBwcml2YXRlIG5lYXIocHg6IG51bWJlciwgcHk6IG51bWJlcik6IG51bWJlciB7XG4gICAgbGV0IGJlc3QgPSAtMTtcbiAgICBsZXQgYmQgPSAyNiAqIDI2O1xuICAgIGZvciAoY29uc3QgaSBvZiB0aGlzLnNob3duSWR4KCkpIHtcbiAgICAgIGNvbnN0IGR4ID0gdGhpcy5YKHRoaXMucnVuc1tpXS54KSAtIHB4O1xuICAgICAgY29uc3QgZHkgPSB0aGlzLlkodGhpcy5ydW5zW2ldLnkpIC0gcHk7XG4gICAgICBjb25zdCBkID0gZHggKiBkeCArIGR5ICogZHk7XG4gICAgICBpZiAoZCA8IGJkKSB7XG4gICAgICAgIGJkID0gZDtcbiAgICAgICAgYmVzdCA9IGk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiBiZXN0O1xuICB9XG5cbiAgcHJpdmF0ZSBzZXRTZWwoaWRzOiAoc3RyaW5nIHwgbnVtYmVyKVtdKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLmNvbnRyb2xsZWQpIHtcbiAgICAgIHRoaXMuc2VsID0gaWRzO1xuICAgICAgdGhpcy5hc2tlZCsrO1xuICAgICAgdGhpcy5hbnN3ZXIgPSBudWxsO1xuICAgIH1cbiAgICB0aGlzLnNlbGVjdGVkQ2hhbmdlLmVtaXQoaWRzKTtcbiAgICB0aGlzLmRyYXcoKTtcbiAgfVxuXG4gIG9uUG9pbnRlckRvd24oZTogUG9pbnRlckV2ZW50KTogdm9pZCB7XG4gICAgaWYgKGUuYnV0dG9uKSByZXR1cm47XG4gICAgY29uc3QgW3gsIHldID0gdGhpcy5sb2NhbChlKTtcbiAgICB0aGlzLmRyYWcgPSB7IHgsIHksIGlkOiBlLnBvaW50ZXJJZCwgbW92ZWQ6IGZhbHNlIH07XG4gIH1cblxuICBvblBvaW50ZXJNb3ZlKGU6IFBvaW50ZXJFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IFt4LCB5XSA9IHRoaXMubG9jYWwoZSk7XG4gICAgY29uc3QgZCA9IHRoaXMuZHJhZztcbiAgICBpZiAoZCAmJiAoZC5tb3ZlZCB8fCBNYXRoLmFicyh4IC0gZC54KSArIE1hdGguYWJzKHkgLSBkLnkpID4gNSkpIHtcbiAgICAgIGlmICghZC5tb3ZlZCkge1xuICAgICAgICBkLm1vdmVkID0gdHJ1ZTtcbiAgICAgICAgdGhpcy5wbG90UmVmLm5hdGl2ZUVsZW1lbnQuc2V0UG9pbnRlckNhcHR1cmUoZC5pZCk7XG4gICAgICAgIHRoaXMuaG90ID0gLTE7XG4gICAgICB9XG4gICAgICB0aGlzLmJveCA9IFtcbiAgICAgICAgZC54LFxuICAgICAgICBkLnksXG4gICAgICAgIE1hdGgubWF4KHRoaXMubCwgTWF0aC5taW4odGhpcy5XIC0gdGhpcy5yciwgeCkpLFxuICAgICAgICBNYXRoLm1heCh0aGlzLnQsIE1hdGgubWluKHRoaXMuSCAtIHRoaXMuYiwgeSkpLFxuICAgICAgXTtcbiAgICAgIHRoaXMuZHJhdygpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoZS5wb2ludGVyVHlwZSAhPT0gJ3RvdWNoJykge1xuICAgICAgY29uc3QgaSA9IHRoaXMubmVhcih4LCB5KTtcbiAgICAgIGlmIChpICE9PSB0aGlzLmhvdCkge1xuICAgICAgICB0aGlzLmhvdCA9IGk7XG4gICAgICAgIHRoaXMuZHJhdygpO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIG9uUG9pbnRlclVwKCk6IHZvaWQge1xuICAgIGNvbnN0IGQgPSB0aGlzLmRyYWc7XG4gICAgdGhpcy5kcmFnID0gbnVsbDtcbiAgICBpZiAoIWQpIHJldHVybjtcbiAgICBpZiAoZC5tb3ZlZCAmJiB0aGlzLmJveCkge1xuICAgICAgY29uc3QgW2EsIGIyLCB4MiwgeTJdID0gdGhpcy5ib3g7XG4gICAgICBjb25zdCBsbyA9IE1hdGgubWluKGEsIHgyKTtcbiAgICAgIGNvbnN0IGhpID0gTWF0aC5tYXgoYSwgeDIpO1xuICAgICAgY29uc3QgdG9wID0gTWF0aC5taW4oYjIsIHkyKTtcbiAgICAgIGNvbnN0IGJvdCA9IE1hdGgubWF4KGIyLCB5Mik7XG4gICAgICBjb25zdCBpZHMgPSB0aGlzLnNob3duSWR4KClcbiAgICAgICAgLmZpbHRlcihcbiAgICAgICAgICAoaSkgPT5cbiAgICAgICAgICAgIHRoaXMuWCh0aGlzLnJ1bnNbaV0ueCkgPj0gbG8gJiZcbiAgICAgICAgICAgIHRoaXMuWCh0aGlzLnJ1bnNbaV0ueCkgPD0gaGkgJiZcbiAgICAgICAgICAgIHRoaXMuWSh0aGlzLnJ1bnNbaV0ueSkgPj0gdG9wICYmXG4gICAgICAgICAgICB0aGlzLlkodGhpcy5ydW5zW2ldLnkpIDw9IGJvdCxcbiAgICAgICAgKVxuICAgICAgICAubWFwKChpKSA9PiB0aGlzLnJ1bnNbaV0uaWQpO1xuICAgICAgdGhpcy5ib3ggPSBudWxsO1xuICAgICAgdGhpcy5zZXRTZWwoaWRzKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuaG90IDwgMCAmJiB0aGlzLnNlbC5sZW5ndGgpIHtcbiAgICAgIHRoaXMuYm94ID0gbnVsbDtcbiAgICAgIHRoaXMuc2V0U2VsKFtdKTtcbiAgICB9XG4gIH1cblxuICBvblBvaW50ZXJDYW5jZWwoKTogdm9pZCB7XG4gICAgdGhpcy5kcmFnID0gbnVsbDtcbiAgICB0aGlzLmJveCA9IG51bGw7XG4gICAgdGhpcy5kcmF3KCk7XG4gIH1cblxuICBvblBvaW50ZXJMZWF2ZSgpOiB2b2lkIHtcbiAgICBpZiAoIXRoaXMuZHJhZyAmJiBkb2N1bWVudC5hY3RpdmVFbGVtZW50ICE9PSB0aGlzLnBsb3RSZWYubmF0aXZlRWxlbWVudCAmJiB0aGlzLmhvdCA+PSAwKSB7XG4gICAgICB0aGlzLmhvdCA9IC0xO1xuICAgICAgdGhpcy5kcmF3KCk7XG4gICAgfVxuICB9XG5cbiAgb25CbHVyKCk6IHZvaWQge1xuICAgIHRoaXMuZm9jdXNlZCA9IGZhbHNlO1xuICAgIGlmICh0aGlzLmhvdCA+PSAwKSB7XG4gICAgICB0aGlzLmhvdCA9IC0xO1xuICAgICAgdGhpcy5kcmF3KCk7XG4gICAgfVxuICB9XG5cbiAgb25LZXlEb3duKGU6IEtleWJvYXJkRXZlbnQpOiB2b2lkIHtcbiAgICB0aGlzLmZvY3VzZWQgPSB0cnVlO1xuICAgIGNvbnN0IG8gPSB0aGlzLm9yZGVyO1xuICAgIGxldCBrID0gby5pbmRleE9mKHRoaXMuaG90KTtcbiAgICBpZiAoZS5rZXkgPT09ICdBcnJvd1JpZ2h0JyB8fCBlLmtleSA9PT0gJ0Fycm93RG93bicpIGsgPSBNYXRoLm1pbihvLmxlbmd0aCAtIDEsIGsgKyAxKTtcbiAgICBlbHNlIGlmIChlLmtleSA9PT0gJ0Fycm93TGVmdCcgfHwgZS5rZXkgPT09ICdBcnJvd1VwJykgayA9IE1hdGgubWF4KDAsIGsgPCAwID8gMCA6IGsgLSAxKTtcbiAgICBlbHNlIGlmIChlLmtleSA9PT0gJ0hvbWUnKSBrID0gMDtcbiAgICBlbHNlIGlmIChlLmtleSA9PT0gJ0VuZCcpIGsgPSBvLmxlbmd0aCAtIDE7XG4gICAgZWxzZSBpZiAoZS5rZXkgPT09ICdFc2NhcGUnICYmIHRoaXMuc2VsLmxlbmd0aCkge1xuICAgICAgdGhpcy5ib3ggPSBudWxsO1xuICAgICAgdGhpcy5zZXRTZWwoW10pO1xuICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSByZXR1cm47XG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIHRoaXMuaG90ID0gb1trXTtcbiAgICB0aGlzLmRyYXcoKTtcbiAgfVxuXG4gIC8vIC0tLS0tIGFzayB0aGUgYWdlbnQgLS0tLS1cbiAgcnVuQXNrKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5hc2sub2JzZXJ2ZWQpIHJldHVybjtcbiAgICB0aGlzLmFza2VkKys7XG4gICAgY29uc3QgaWQgPSB0aGlzLmFza2VkO1xuICAgIHRoaXMuYW5zd2VyID0geyB0ZXh0OiAnJywgYnVzeTogdHJ1ZSB9O1xuICAgIHRoaXMuYXNrLmVtaXQodGhpcy5zZWxlY3RlZFJ1bnMpO1xuICAgIHRoaXMuY2RyLm1hcmtGb3JDaGVjaygpO1xuICAgIC8vIHRoZSBob3N0IGFuc3dlcnMgdmlhIHN0cmVhbUFuc3dlcigpOyB1bnRpbCB0aGVuIHRoZSBzaGltbWVyIHNob3dzXG4gICAgdGhpcy5wZW5kaW5nQXNrID0gaWQ7XG4gIH1cblxuICBwcml2YXRlIHBlbmRpbmdBc2sgPSAwO1xuXG4gIC8qKiBUaGUgaG9zdCBjYWxscyB0aGlzIHdpdGggdGhlIGFuc3dlcjsgaXQgc3RyZWFtcyBpbiB3b3JkIGJ5IHdvcmQuICovXG4gIHN0cmVhbUFuc3dlcih0ZXh0OiBzdHJpbmcpOiB2b2lkIHtcbiAgICBjb25zdCBpZCA9IHRoaXMucGVuZGluZ0FzaztcbiAgICBpZiAoaWQgIT09IHRoaXMuYXNrZWQpIHJldHVybjtcbiAgICBjb25zdCB3cyA9IHRleHQuc3BsaXQoJyAnKTtcbiAgICBjb25zdCBzdGVwID0gKGk6IG51bWJlcik6IHZvaWQgPT4ge1xuICAgICAgaWYgKGlkICE9PSB0aGlzLmFza2VkKSByZXR1cm47XG4gICAgICB0aGlzLmFuc3dlciA9IHsgdGV4dDogd3Muc2xpY2UoMCwgaSkuam9pbignICcpLCBidXN5OiBmYWxzZSB9O1xuICAgICAgdGhpcy5jZHIubWFya0ZvckNoZWNrKCk7XG4gICAgICBpZiAoaSA8IHdzLmxlbmd0aCkge1xuICAgICAgICB0aGlzLnRpbWVycy5wdXNoKHNldFRpbWVvdXQoKCkgPT4gc3RlcChpICsgMSksIHRoaXMucmVkdWNlZC5yZWR1Y2UoKSA/IDAgOiA0NSkpO1xuICAgICAgfVxuICAgIH07XG4gICAgc3RlcCgxKTtcbiAgfVxuXG4gIG5nT25EZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMucm8/LmRpc2Nvbm5lY3QoKTtcbiAgICB0aGlzLnRpbWVycy5mb3JFYWNoKGNsZWFyVGltZW91dCk7XG4gICAgdGhpcy50aW1lcnMgPSBbXTtcbiAgfVxufVxuIl19
|