@jax-data-science/sci-image-visualizer 0.17.0 → 0.18.1
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/esm2022/lib/contracts/display-types.mjs +3 -2
- package/esm2022/lib/contracts/image.contract.mjs +1 -1
- package/esm2022/lib/contracts/ports/spatial-data.port.mjs +1 -1
- package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
- package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
- package/esm2022/lib/contracts/spatial-dataset.contract.mjs +1 -1
- package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
- package/esm2022/lib/geometry/cell-meshes.mjs +37 -0
- package/esm2022/lib/geometry/place.mjs +47 -0
- package/esm2022/lib/implementations/napari-js/napari-camera-depth.mjs +93 -0
- package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +1 -1
- package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +2 -2
- package/esm2022/lib/implementations/napari-js/napari-scene.mjs +1 -1
- package/esm2022/lib/implementations/napari-js/napari-spatial-2d-scene.mjs +81 -15
- package/esm2022/lib/implementations/napari-js/napari-spatial-3d-cells.mjs +746 -0
- package/esm2022/lib/implementations/napari-js/napari-spatial-3d-scene.mjs +325 -18
- package/esm2022/lib/implementations/napari-js/napari-spatial-3d-transcripts.mjs +182 -24
- package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +95 -5
- package/esm2022/lib/implementations/napari-js/napari-spatial-scene.mjs +15 -1
- package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +30 -2
- package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +40 -1
- package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +111 -28
- package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +14 -2
- package/esm2022/lib/implementations/napari-js/spatial-tiles/cell-layers.mjs +180 -48
- package/esm2022/lib/implementations/napari-js/spatial-tiles/transcript-layers.mjs +28 -8
- package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +2 -2
- package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +10 -1
- package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +30 -3
- package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +15 -3
- package/esm2022/lib/region-editor/region-editor.component.mjs +24 -4
- package/esm2022/lib/region-source/region-source-ops.mjs +7 -1
- package/esm2022/lib/region-source/region-tiles.mjs +1 -1
- package/esm2022/lib/region-source/worker-region-source.mjs +24 -1
- package/esm2022/lib/routing-visualizer.service.mjs +404 -7
- package/esm2022/lib/spatial/observations-in-selection.mjs +83 -0
- package/esm2022/lib/spatial/plane-cells.mjs +119 -0
- package/esm2022/lib/spatial/spatial-controls.facade.mjs +298 -5
- package/esm2022/lib/spatial/spatial-encoding.mjs +35 -3
- package/esm2022/lib/spatial/spatial-hover.mjs +34 -1
- package/esm2022/lib/spatial/spatial-planes.mjs +49 -0
- package/esm2022/lib/spatial/spatial-selection.mjs +2 -2
- package/esm2022/lib/spatial/spatial-tile-merge.mjs +38 -1
- package/esm2022/lib/spatial/transcripts-in-selection.mjs +208 -0
- package/esm2022/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.mjs +42 -65
- package/esm2022/lib/spatial-controls/spatial-color-by/spatial-color-by.component.mjs +187 -0
- package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +47 -12
- package/esm2022/lib/spatial-controls/spatial-gene-tree/spatial-gene-tree.component.mjs +3 -3
- package/esm2022/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.mjs +38 -10
- package/esm2022/lib/spatial-controls/spatial-key/spatial-key.component.mjs +3 -3
- package/esm2022/lib/spatial-controls/spatial-marker-genes-form/spatial-marker-genes-form.component.mjs +3 -3
- package/esm2022/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.mjs +79 -57
- package/esm2022/lib/spatial-controls/spatial-selection-observations/spatial-selection-observations.component.mjs +101 -0
- package/esm2022/lib/spatial-controls/spatial-selection-transcripts/spatial-selection-transcripts.component.mjs +94 -0
- package/esm2022/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.mjs +9 -3
- package/esm2022/lib/store/region-source-scope.mjs +10 -1
- package/esm2022/lib/store/region-store.service.mjs +33 -2
- package/esm2022/lib/toolbar/toolbar.component.mjs +10 -3
- package/esm2022/lib/visualizer/spatial-region-set.mjs +95 -0
- package/esm2022/lib/visualizer.component.mjs +40 -4
- package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DHrHO2ay.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-YrNqv8wH.mjs} +4521 -759
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-YrNqv8wH.mjs.map +1 -0
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-CKEUwNta.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-Dph35S7m.mjs} +2 -2
- package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-CKEUwNta.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-Dph35S7m.mjs.map} +1 -1
- package/fesm2022/jax-data-science-sci-image-visualizer.mjs +1 -1
- package/fesm2022/region-source.worker.js +84 -2
- package/lib/contracts/display-types.d.ts +90 -4
- package/lib/contracts/image.contract.d.ts +6 -0
- package/lib/contracts/ports/spatial-data.port.d.ts +7 -0
- package/lib/contracts/region-editor-api.contract.d.ts +9 -0
- package/lib/contracts/region-store.contract.d.ts +6 -0
- package/lib/contracts/spatial-dataset.contract.d.ts +7 -1
- package/lib/contracts/visualizer.contract.d.ts +43 -1
- package/lib/geometry/cell-meshes.d.ts +27 -0
- package/lib/geometry/place.d.ts +45 -0
- package/lib/implementations/napari-js/napari-camera-depth.d.ts +23 -0
- package/lib/implementations/napari-js/napari-loading-state.d.ts +1 -1
- package/lib/implementations/napari-js/napari-scene.d.ts +12 -0
- package/lib/implementations/napari-js/napari-spatial-2d-scene.d.ts +19 -3
- package/lib/implementations/napari-js/napari-spatial-3d-cells.d.ts +141 -0
- package/lib/implementations/napari-js/napari-spatial-3d-scene.d.ts +87 -0
- package/lib/implementations/napari-js/napari-spatial-3d-transcripts.d.ts +49 -8
- package/lib/implementations/napari-js/napari-spatial-hover.d.ts +22 -0
- package/lib/implementations/napari-js/napari-spatial-scene.d.ts +12 -0
- package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +15 -0
- package/lib/implementations/napari-js/napari-visualizer.service.d.ts +27 -1
- package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +38 -19
- package/lib/implementations/napari-js/napari-volume-scene.d.ts +2 -0
- package/lib/implementations/napari-js/spatial-tiles/cell-layers.d.ts +53 -0
- package/lib/implementations/napari-js/spatial-tiles/transcript-layers.d.ts +11 -2
- package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +7 -0
- package/lib/region-editor/class-tree/class-tree.component.d.ts +16 -1
- package/lib/region-editor/classes-panel/classes-panel.component.d.ts +10 -1
- package/lib/region-editor/region-editor.component.d.ts +4 -0
- package/lib/region-source/region-source-ops.d.ts +12 -0
- package/lib/region-source/region-tiles.d.ts +8 -0
- package/lib/region-source/worker-region-source.d.ts +18 -0
- package/lib/routing-visualizer.service.d.ts +140 -1
- package/lib/spatial/observations-in-selection.d.ts +43 -0
- package/lib/spatial/plane-cells.d.ts +37 -0
- package/lib/spatial/spatial-controls.facade.d.ts +59 -0
- package/lib/spatial/spatial-encoding.d.ts +14 -1
- package/lib/spatial/spatial-hover.d.ts +23 -0
- package/lib/spatial/spatial-planes.d.ts +22 -0
- package/lib/spatial/spatial-selection.d.ts +2 -1
- package/lib/spatial/spatial-tile-merge.d.ts +9 -0
- package/lib/spatial/transcripts-in-selection.d.ts +95 -0
- package/lib/spatial-controls/spatial-cells-panel/spatial-cells-panel.component.d.ts +19 -28
- package/lib/spatial-controls/spatial-color-by/spatial-color-by.component.d.ts +64 -0
- package/lib/spatial-controls/spatial-controls.component.d.ts +17 -2
- package/lib/spatial-controls/spatial-groups-panel/spatial-groups-panel.component.d.ts +16 -6
- package/lib/spatial-controls/spatial-observations-panel/spatial-observations-panel.component.d.ts +26 -23
- package/lib/spatial-controls/spatial-selection-observations/spatial-selection-observations.component.d.ts +48 -0
- package/lib/spatial-controls/spatial-selection-transcripts/spatial-selection-transcripts.component.d.ts +43 -0
- package/lib/spatial-controls/spatial-transcripts-panel/spatial-transcripts-panel.component.d.ts +3 -1
- package/lib/store/region-source-scope.d.ts +4 -0
- package/lib/store/region-store.service.d.ts +21 -0
- package/lib/toolbar/toolbar.component.d.ts +6 -1
- package/lib/visualizer/spatial-region-set.d.ts +55 -0
- package/lib/visualizer.component.d.ts +14 -0
- package/package.json +1 -1
- package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-DHrHO2ay.mjs.map +0 -1
|
@@ -0,0 +1,746 @@
|
|
|
1
|
+
import { regionTilesInRect } from '../../region-source/region-tiles';
|
|
2
|
+
import { placeInWorker, reconstructCellsInWorker } from '../../region-source/worker-region-source';
|
|
3
|
+
import { cellOutlinesFromTiles, observationIndex } from '../../spatial/plane-cells';
|
|
4
|
+
import { typicalCellDiameter } from '../../spatial/lod';
|
|
5
|
+
import { datasetRegionSet } from '../../visualizer/spatial-region-set';
|
|
6
|
+
import { REGION_MESH_DIMMED_OPACITY, toWorld } from './napari-volume-region-meshes';
|
|
7
|
+
/**
|
|
8
|
+
* A 3D segmentation's cells in the spatial 3D view, each reconstructed by itself (see
|
|
9
|
+
* `geometry/cell-meshes`), where the region classes are otherwise one merged surface per class.
|
|
10
|
+
*
|
|
11
|
+
* Built to stay out of the way of the UI thread and the GPU:
|
|
12
|
+
* - the space is cut into chunks (a grid over the region set's bounds); each chunk is one surface
|
|
13
|
+
* layer of its cells, meshed in the cells' own worker, a few hundred cells per call, so the
|
|
14
|
+
* work is cancelled between calls when the view moves on (and the region tiles the 2D view
|
|
15
|
+
* reads never wait behind it);
|
|
16
|
+
* - level of detail by chunk: a coarse mesh everywhere first, then the chunks on screen are meshed
|
|
17
|
+
* finer as the camera comes close, within a triangle budget for the whole scene; the region
|
|
18
|
+
* set's tiles are read at the level of detail that mesh needs;
|
|
19
|
+
* - at most {@link CELLS_3D_MAX_CELLS} cells and {@link CELLS_3D_TRIANGLE_BUDGET} triangles, the
|
|
20
|
+
* chunks nearest the centre of the view first (one chunk over either by itself is meshed in
|
|
21
|
+
* part), planned again as each chunk's real size is learnt; the status says when cells are left
|
|
22
|
+
* out, so the view never claims to show them all;
|
|
23
|
+
* - colour and visibility change no geometry: colours are per vertex (each vertex's cell), and a
|
|
24
|
+
* hidden cell's triangles are left out of what is drawn.
|
|
25
|
+
* Builds report on the canvas's loading badge.
|
|
26
|
+
*/
|
|
27
|
+
/** The most cells drawn at once. */
|
|
28
|
+
export const CELLS_3D_MAX_CELLS = 20_000;
|
|
29
|
+
/** The most triangles every chunk together may have. */
|
|
30
|
+
export const CELLS_3D_TRIANGLE_BUDGET = 3_000_000;
|
|
31
|
+
/** Chunks across the longer side of the region set's bounds. */
|
|
32
|
+
const CHUNKS_ACROSS = 8;
|
|
33
|
+
/** A redraw yields the main thread after this long. */
|
|
34
|
+
const REDRAW_SLICE_MS = 8;
|
|
35
|
+
/** Cells per worker call: the build can be dropped between calls. */
|
|
36
|
+
const BATCH = 400;
|
|
37
|
+
/** A pause in the camera's movement this long re-plans the detail. */
|
|
38
|
+
const CAMERA_IDLE_MS = 250;
|
|
39
|
+
/** A voxel at least this many screen pixels across is detail enough. */
|
|
40
|
+
const MIN_VOXEL_PX = 3;
|
|
41
|
+
/** Each tier's voxel edge, as a fraction of a cell's diameter: coarse to fine. */
|
|
42
|
+
const TIER_FRACTIONS = [1 / 4, 1 / 8, 1 / 16];
|
|
43
|
+
/** A first guess at a coarse cell's triangles, before any chunk was built. */
|
|
44
|
+
const COARSE_TRIANGLES_PER_CELL = 300;
|
|
45
|
+
export class Spatial3dCells {
|
|
46
|
+
constructor(host) {
|
|
47
|
+
this.host = host;
|
|
48
|
+
this.dataset = null;
|
|
49
|
+
this.source = null;
|
|
50
|
+
this.classes = null;
|
|
51
|
+
this.hidden = new Set();
|
|
52
|
+
this.colors = null;
|
|
53
|
+
this.visible = null;
|
|
54
|
+
/** The selection (null: none): the cells it leaves out fade, keeping their colours. */
|
|
55
|
+
this.selected = null;
|
|
56
|
+
this.opacity = 1;
|
|
57
|
+
this.placement = null;
|
|
58
|
+
this.zScale = 1;
|
|
59
|
+
this.chunks = [];
|
|
60
|
+
this.byLayer = new Map();
|
|
61
|
+
this.generation = 0;
|
|
62
|
+
this.timer = null;
|
|
63
|
+
this.running = false;
|
|
64
|
+
this.disposed = false;
|
|
65
|
+
/** Each surface's geometry as last set: a recolour that leaves it so uploads none again. */
|
|
66
|
+
this.installed = new WeakMap();
|
|
67
|
+
this.redrawGeneration = 0;
|
|
68
|
+
/** Tell the host how the cells stand, only when that changed (the camera re-plans often). */
|
|
69
|
+
this.lastStatus = 'null';
|
|
70
|
+
this.cameraOff = host.viewer.camera3d.changed.connect(() => this.schedule(CAMERA_IDLE_MS));
|
|
71
|
+
}
|
|
72
|
+
/** The dataset whose region set the cells are read from. */
|
|
73
|
+
setDataset(dataset) {
|
|
74
|
+
if (dataset === this.dataset)
|
|
75
|
+
return;
|
|
76
|
+
const id = datasetRegionSet(dataset);
|
|
77
|
+
const sameSet = !!id && id === this.source?.id && dataset?.id === this.dataset?.id;
|
|
78
|
+
this.dataset = dataset;
|
|
79
|
+
if (sameSet)
|
|
80
|
+
return;
|
|
81
|
+
this.reset();
|
|
82
|
+
this.closeSource();
|
|
83
|
+
if (id && this.host.port?.openRegionSet) {
|
|
84
|
+
const open = this.host.port.openRegionSet(id);
|
|
85
|
+
this.source = { id, open };
|
|
86
|
+
open.catch(() => {
|
|
87
|
+
if (this.source?.open === open)
|
|
88
|
+
this.source = null;
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
this.schedule(0);
|
|
92
|
+
}
|
|
93
|
+
/** The classes drawn as cells (none: the cells are not drawn). */
|
|
94
|
+
setClasses(classes) {
|
|
95
|
+
const next = classes?.size ? classes : null;
|
|
96
|
+
if (sameSet(next, this.classes))
|
|
97
|
+
return;
|
|
98
|
+
this.classes = next;
|
|
99
|
+
this.reset();
|
|
100
|
+
this.schedule(0);
|
|
101
|
+
}
|
|
102
|
+
/** Classes hidden (the Region Editor's eyes): their cells are left out of what is drawn. */
|
|
103
|
+
setHiddenClasses(classes) {
|
|
104
|
+
const next = new Set(classes);
|
|
105
|
+
if (sameSet(next, this.hidden))
|
|
106
|
+
return;
|
|
107
|
+
this.hidden = next;
|
|
108
|
+
this.redraw();
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Each observation's colour (RGBA 0..1) and whether it is shown (null: all), and the surfaces'
|
|
112
|
+
* opacity: the panel's Cell Color, groups and selection. Changes no geometry.
|
|
113
|
+
*/
|
|
114
|
+
setStyle(colors, visible, opacity, selected = null) {
|
|
115
|
+
this.colors = colors;
|
|
116
|
+
this.visible = visible;
|
|
117
|
+
this.opacity = opacity;
|
|
118
|
+
this.selected = selected;
|
|
119
|
+
this.redraw();
|
|
120
|
+
}
|
|
121
|
+
/** Where the planes are among the observations (null: nowhere, nothing drawn), and the Z stretch. */
|
|
122
|
+
setPlacement(placement, zScale) {
|
|
123
|
+
const moved = !samePlacement(placement, this.placement);
|
|
124
|
+
// The same placement kept as it was (a scene passes a new object each time): a placement in
|
|
125
|
+
// flight for it is still good when it lands.
|
|
126
|
+
if (moved)
|
|
127
|
+
this.placement = placement;
|
|
128
|
+
this.zScale = zScale;
|
|
129
|
+
for (const c of this.chunks) {
|
|
130
|
+
if (c.layer)
|
|
131
|
+
c.layer.scale3d = [1, 1, zScale];
|
|
132
|
+
if (c.selectedLayer)
|
|
133
|
+
c.selectedLayer.scale3d = [1, 1, zScale];
|
|
134
|
+
}
|
|
135
|
+
if (!moved)
|
|
136
|
+
return;
|
|
137
|
+
for (const c of this.chunks) {
|
|
138
|
+
c.world = null;
|
|
139
|
+
c.placing = null; // one in flight was for the old placement: it is dropped when it lands
|
|
140
|
+
}
|
|
141
|
+
if (!placement) {
|
|
142
|
+
for (const c of this.chunks)
|
|
143
|
+
this.dropLayer(c);
|
|
144
|
+
}
|
|
145
|
+
else {
|
|
146
|
+
this.redraw();
|
|
147
|
+
}
|
|
148
|
+
this.schedule(0);
|
|
149
|
+
}
|
|
150
|
+
/** The observation of the cell drawn under canvas point (`x`, `y`) (CSS px), or -1. */
|
|
151
|
+
pick(x, y) {
|
|
152
|
+
if (!this.byLayer.size)
|
|
153
|
+
return -1;
|
|
154
|
+
const hit = this.host.viewer.pickSurface(x, y, { pickable: (l) => this.byLayer.has(l) });
|
|
155
|
+
const chunk = hit ? this.byLayer.get(hit.layer) : undefined;
|
|
156
|
+
const faces = hit && chunk && hit.layer === chunk.selectedLayer ? chunk.drawnSelected : chunk?.drawn;
|
|
157
|
+
if (!hit || !faces || !chunk?.mesh)
|
|
158
|
+
return -1;
|
|
159
|
+
const vertex = faces[hit.face * 3];
|
|
160
|
+
return vertex === undefined ? -1 : chunk.mesh.vertexCell[vertex];
|
|
161
|
+
}
|
|
162
|
+
/** Whether `layer` is one of the cells' surfaces. */
|
|
163
|
+
owns(layer) {
|
|
164
|
+
return this.byLayer.has(layer);
|
|
165
|
+
}
|
|
166
|
+
dispose() {
|
|
167
|
+
this.disposed = true;
|
|
168
|
+
this.cameraOff?.();
|
|
169
|
+
this.cameraOff = null;
|
|
170
|
+
if (this.timer)
|
|
171
|
+
clearTimeout(this.timer);
|
|
172
|
+
this.timer = null;
|
|
173
|
+
this.reset();
|
|
174
|
+
this.closeSource();
|
|
175
|
+
this.emit(null);
|
|
176
|
+
}
|
|
177
|
+
// ── planning ──────────────────────────────────────────────────────────────────────
|
|
178
|
+
schedule(delay) {
|
|
179
|
+
if (this.disposed)
|
|
180
|
+
return;
|
|
181
|
+
if (this.timer)
|
|
182
|
+
clearTimeout(this.timer);
|
|
183
|
+
this.timer = setTimeout(() => {
|
|
184
|
+
this.timer = null;
|
|
185
|
+
void this.plan();
|
|
186
|
+
}, delay);
|
|
187
|
+
}
|
|
188
|
+
/** Drop every chunk (their layers) and any build in flight. */
|
|
189
|
+
reset() {
|
|
190
|
+
this.generation++;
|
|
191
|
+
for (const c of this.chunks)
|
|
192
|
+
this.dropLayer(c);
|
|
193
|
+
this.chunks = [];
|
|
194
|
+
}
|
|
195
|
+
closeSource() {
|
|
196
|
+
const s = this.source;
|
|
197
|
+
this.source = null;
|
|
198
|
+
void s?.open.then((src) => src.dispose(), () => undefined);
|
|
199
|
+
}
|
|
200
|
+
/** Decide each chunk's detail (and whether it is drawn at all), then build what changed. */
|
|
201
|
+
async plan() {
|
|
202
|
+
const dataset = this.dataset;
|
|
203
|
+
const index = dataset ? observationIndex(dataset.observations) : null;
|
|
204
|
+
if (!this.classes || !this.source || !dataset || !index || !this.placement) {
|
|
205
|
+
if (this.chunks.length)
|
|
206
|
+
this.reset();
|
|
207
|
+
this.emit(null);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const generation = this.generation;
|
|
211
|
+
let source;
|
|
212
|
+
try {
|
|
213
|
+
source = await this.source.open;
|
|
214
|
+
}
|
|
215
|
+
catch (err) {
|
|
216
|
+
console.warn("[napari-js] the cells' region set could not be opened", err);
|
|
217
|
+
this.emit(null);
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (generation !== this.generation)
|
|
221
|
+
return;
|
|
222
|
+
if (!this.chunks.length)
|
|
223
|
+
this.chunks = makeChunks(source);
|
|
224
|
+
const steps = this.steps(dataset);
|
|
225
|
+
this.replanTiers(steps);
|
|
226
|
+
this.report(false);
|
|
227
|
+
if (!this.running)
|
|
228
|
+
void this.run(source, index, steps);
|
|
229
|
+
}
|
|
230
|
+
/** {@link assignTiers} from the view as it is now, taking down what it leaves out. */
|
|
231
|
+
replanTiers(steps) {
|
|
232
|
+
this.assignTiers(this.priority(), steps);
|
|
233
|
+
for (const c of this.chunks)
|
|
234
|
+
if (c.want < 0)
|
|
235
|
+
this.dropLayer(c);
|
|
236
|
+
}
|
|
237
|
+
/** Voxel edge of each tier, image px: fractions of a typical cell's diameter. */
|
|
238
|
+
steps(dataset) {
|
|
239
|
+
const sx = dataset.imageRef?.scale?.[0] ?? 1;
|
|
240
|
+
const d = Math.max(4, typicalCellDiameter(dataset.observations.radius) * Math.abs(sx || 1));
|
|
241
|
+
return TIER_FRACTIONS.map((f) => Math.max(1, d * f));
|
|
242
|
+
}
|
|
243
|
+
/**
|
|
244
|
+
* The chunks, nearest the centre of the view first, with how many screen pixels an image pixel
|
|
245
|
+
* of each takes (0 off screen).
|
|
246
|
+
*/
|
|
247
|
+
priority() {
|
|
248
|
+
const viewer = this.host.viewer;
|
|
249
|
+
const [vw, vh] = viewer.viewportSize();
|
|
250
|
+
const pts = new Float32Array(this.chunks.length * 6);
|
|
251
|
+
const zMid = this.placement ? midZ(this.placement) : 0;
|
|
252
|
+
this.chunks.forEach((c, i) => {
|
|
253
|
+
const [x0, y0, x1, y1] = c.box;
|
|
254
|
+
const cy = (y0 + y1) / 2;
|
|
255
|
+
const a = this.toWorldPoint((x0 + x1) / 2, cy, zMid);
|
|
256
|
+
const b = this.toWorldPoint(x1, cy, zMid);
|
|
257
|
+
pts.set(a, i * 6);
|
|
258
|
+
pts.set(b, i * 6 + 3);
|
|
259
|
+
});
|
|
260
|
+
const proj = vw > 0 && vh > 0 ? viewer.projectPoints(pts) : null;
|
|
261
|
+
const out = this.chunks.map((chunk, i) => {
|
|
262
|
+
const sx = proj?.screen[i * 4] ?? NaN;
|
|
263
|
+
const sy = proj?.screen[i * 4 + 1] ?? NaN;
|
|
264
|
+
const ex = proj?.screen[i * 4 + 2] ?? NaN;
|
|
265
|
+
const ey = proj?.screen[i * 4 + 3] ?? NaN;
|
|
266
|
+
const half = Math.hypot(ex - sx, ey - sy);
|
|
267
|
+
const width = (chunk.box[2] - chunk.box[0]) / 2;
|
|
268
|
+
const ppi = Number.isFinite(half) && width > 0 ? half / width : 0;
|
|
269
|
+
const onScreen = Number.isFinite(sx) && sx > -half && sx < vw + half && sy > -half && sy < vh + half && ppi > 0;
|
|
270
|
+
const d2 = Number.isFinite(sx) ? (sx - vw / 2) ** 2 + (sy - vh / 2) ** 2 : Number.MAX_VALUE;
|
|
271
|
+
return { chunk, ppi: onScreen ? ppi : 0, onScreen, d2 };
|
|
272
|
+
});
|
|
273
|
+
return out.sort((a, b) => Number(b.onScreen) - Number(a.onScreen) || a.d2 - b.d2);
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Each chunk's tier: in order, within the cell cap, as fine as the screen asks within the
|
|
277
|
+
* triangle budget. The chunks last in order give up their detail first, then are left out; the
|
|
278
|
+
* first is never left out, but one over the cap or the budget by itself meshes only the cells
|
|
279
|
+
* that fit (its {@link Chunk.limit}).
|
|
280
|
+
*/
|
|
281
|
+
assignTiers(order, steps) {
|
|
282
|
+
const known = this.chunks.filter((c) => c.cells >= 0);
|
|
283
|
+
const avgCells = known.length ? known.reduce((s, c) => s + c.cells, 0) / known.length : 200;
|
|
284
|
+
let cells = 0;
|
|
285
|
+
const included = [];
|
|
286
|
+
for (const { chunk, ppi } of order) {
|
|
287
|
+
const n = chunk.cells >= 0 ? chunk.cells : avgCells;
|
|
288
|
+
const room = CELLS_3D_MAX_CELLS - cells;
|
|
289
|
+
if (n > room && included.length) {
|
|
290
|
+
chunk.want = -1;
|
|
291
|
+
continue;
|
|
292
|
+
}
|
|
293
|
+
const take = Math.min(n, room);
|
|
294
|
+
cells += take;
|
|
295
|
+
let tier = 0;
|
|
296
|
+
for (let t = steps.length - 1; t > 0; t--) {
|
|
297
|
+
if (ppi * steps[t] >= MIN_VOXEL_PX) {
|
|
298
|
+
tier = t;
|
|
299
|
+
break;
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
included.push({ chunk, tier, take, room });
|
|
303
|
+
}
|
|
304
|
+
const triangles = (e) => this.trianglesAt(e.chunk, e.tier, steps, avgCells);
|
|
305
|
+
// The budget: the chunks last in order give up their detail first, then their place.
|
|
306
|
+
let total = included.reduce((s, e) => s + triangles(e), 0);
|
|
307
|
+
for (let i = included.length - 1; i >= 0 && total > CELLS_3D_TRIANGLE_BUDGET; i--) {
|
|
308
|
+
const e = included[i];
|
|
309
|
+
while (e.tier > 0 && total > CELLS_3D_TRIANGLE_BUDGET) {
|
|
310
|
+
total -= triangles(e) - triangles({ chunk: e.chunk, tier: e.tier - 1 });
|
|
311
|
+
e.tier--;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
while (included.length > 1 && total > CELLS_3D_TRIANGLE_BUDGET) {
|
|
315
|
+
const e = included.pop();
|
|
316
|
+
total -= triangles(e);
|
|
317
|
+
e.chunk.want = -1;
|
|
318
|
+
}
|
|
319
|
+
for (const e of included) {
|
|
320
|
+
const n = e.chunk.cells >= 0 ? e.chunk.cells : avgCells;
|
|
321
|
+
let take = e.take;
|
|
322
|
+
// The first chunk alone over the budget, at its coarsest: as many cells as fit in it.
|
|
323
|
+
const all = triangles(e);
|
|
324
|
+
if (all > CELLS_3D_TRIANGLE_BUDGET) {
|
|
325
|
+
const perCell = all / Math.max(1, e.chunk.meshed > 0 ? e.chunk.meshed : n);
|
|
326
|
+
take = Math.min(take, CELLS_3D_TRIANGLE_BUDGET / perCell);
|
|
327
|
+
}
|
|
328
|
+
e.chunk.want = e.tier;
|
|
329
|
+
// Cut short when over; and one not built yet, which may have more cells than the guess, to
|
|
330
|
+
// the room the cap leaves it.
|
|
331
|
+
const most = take < n ? take : e.chunk.cells < 0 ? e.room : Infinity;
|
|
332
|
+
e.chunk.limit = Number.isFinite(most) ? Math.max(1, Math.floor(most)) : Infinity;
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
/** A chunk's triangles at `tier`: as built, else scaled from a tier built (by the step's square). */
|
|
336
|
+
trianglesAt(chunk, tier, steps, avgCells) {
|
|
337
|
+
const at = chunk.triangles.get(tier);
|
|
338
|
+
if (at !== undefined)
|
|
339
|
+
return at;
|
|
340
|
+
for (const [t, n] of chunk.triangles)
|
|
341
|
+
return n * (steps[t] / steps[tier]) ** 2;
|
|
342
|
+
const cells = chunk.cells >= 0 ? chunk.cells : avgCells;
|
|
343
|
+
return cells * COARSE_TRIANGLES_PER_CELL * (steps[0] / steps[tier]) ** 2;
|
|
344
|
+
}
|
|
345
|
+
// ── building ──────────────────────────────────────────────────────────────────────
|
|
346
|
+
/** Build every chunk whose tier changed, nearest first, one at a time, until none is left. */
|
|
347
|
+
async run(source, index, steps) {
|
|
348
|
+
this.running = true;
|
|
349
|
+
let stale = false;
|
|
350
|
+
const end = this.host.beginTask('Cells');
|
|
351
|
+
try {
|
|
352
|
+
for (;;) {
|
|
353
|
+
const generation = this.generation;
|
|
354
|
+
const next = this.priority()
|
|
355
|
+
.map((e) => e.chunk)
|
|
356
|
+
.find((c) => needsBuild(c));
|
|
357
|
+
if (!next)
|
|
358
|
+
break;
|
|
359
|
+
this.report(true);
|
|
360
|
+
try {
|
|
361
|
+
await this.build(next, next.want, source, index, steps, generation);
|
|
362
|
+
}
|
|
363
|
+
catch (err) {
|
|
364
|
+
console.warn('[napari-js] cells could not be built in 3D', err);
|
|
365
|
+
next.want = next.tier; // not retried until the view asks again
|
|
366
|
+
}
|
|
367
|
+
if (generation !== this.generation) {
|
|
368
|
+
// Superseded (other classes, another dataset): the plan made for those found this run
|
|
369
|
+
// still going and started none of its own. Plan again, now that it has stopped.
|
|
370
|
+
stale = true;
|
|
371
|
+
break;
|
|
372
|
+
}
|
|
373
|
+
// The chunk's real size is known now, where the plan guessed: plan again by it.
|
|
374
|
+
this.replanTiers(steps);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
finally {
|
|
378
|
+
end();
|
|
379
|
+
this.running = false;
|
|
380
|
+
this.report(false);
|
|
381
|
+
if (stale)
|
|
382
|
+
this.schedule(0);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
async build(chunk, tier, source, index, steps, generation) {
|
|
386
|
+
const info = source.info;
|
|
387
|
+
const step = steps[tier];
|
|
388
|
+
const level = Math.max(0, Math.min(info.levels - 1, Math.floor(Math.log2(step))));
|
|
389
|
+
// Tiles around the chunk: a cell crossing its edge is the chunk's its centre is in.
|
|
390
|
+
const margin = steps[0] * 8;
|
|
391
|
+
const [x0, y0, x1, y1] = chunk.box;
|
|
392
|
+
const keys = regionTilesInRect([x0 - margin, y0 - margin, x1 + margin, y1 + margin], level, info.tileSize, info.bounds);
|
|
393
|
+
const planes = await Promise.all(info.planes.map(async (z, slice) => ({
|
|
394
|
+
slice,
|
|
395
|
+
tiles: await Promise.all(keys.map((k) => source.getTile(z, k))),
|
|
396
|
+
})));
|
|
397
|
+
if (generation !== this.generation)
|
|
398
|
+
return;
|
|
399
|
+
const found = cellOutlinesFromTiles(planes, index, this.classes, chunk.box);
|
|
400
|
+
const limit = chunk.limit;
|
|
401
|
+
const cells = found.length > limit ? found.slice(0, limit) : found;
|
|
402
|
+
const labels = new Map(cells.map((c) => [c.cell, c.label]));
|
|
403
|
+
const parts = [];
|
|
404
|
+
for (let i = 0; i < cells.length; i += BATCH) {
|
|
405
|
+
const batch = cells.slice(i, i + BATCH).map((c) => ({ cell: c.cell, slices: c.slices }));
|
|
406
|
+
parts.push(await reconstructCellsInWorker(batch, { pixelStep: step }));
|
|
407
|
+
if (generation !== this.generation)
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
const mesh = concatMeshes(parts);
|
|
411
|
+
chunk.mesh = mesh;
|
|
412
|
+
chunk.labels = labels;
|
|
413
|
+
chunk.tier = tier;
|
|
414
|
+
chunk.cells = found.length;
|
|
415
|
+
chunk.meshed = mesh.cells.length;
|
|
416
|
+
chunk.builtLimit = limit;
|
|
417
|
+
chunk.triangles.set(tier, mesh.faces.length / 3);
|
|
418
|
+
chunk.world = null;
|
|
419
|
+
this.draw(chunk);
|
|
420
|
+
}
|
|
421
|
+
// ── drawing ───────────────────────────────────────────────────────────────────────
|
|
422
|
+
/**
|
|
423
|
+
* Draw every chunk again (a recolour, a hidden class, a selection): a few at a time, yielding the
|
|
424
|
+
* main thread between them so that a click selecting a cell never holds a frame; a newer redraw
|
|
425
|
+
* takes over from this one.
|
|
426
|
+
*/
|
|
427
|
+
redraw() {
|
|
428
|
+
const generation = ++this.redrawGeneration;
|
|
429
|
+
const chunks = this.chunks.filter((c) => c.mesh);
|
|
430
|
+
void (async () => {
|
|
431
|
+
let start = performance.now();
|
|
432
|
+
for (const c of chunks) {
|
|
433
|
+
if (generation !== this.redrawGeneration)
|
|
434
|
+
return;
|
|
435
|
+
this.draw(c);
|
|
436
|
+
if (performance.now() - start > REDRAW_SLICE_MS) {
|
|
437
|
+
this.host.viewer.requestRender();
|
|
438
|
+
await new Promise((r) => setTimeout(r));
|
|
439
|
+
start = performance.now();
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
this.host.viewer.requestRender();
|
|
443
|
+
})();
|
|
444
|
+
}
|
|
445
|
+
/** Place a chunk's vertices in the world, in the cells' worker, then draw it (unless superseded). */
|
|
446
|
+
placeChunk(chunk, placement) {
|
|
447
|
+
const mesh = chunk.mesh;
|
|
448
|
+
if (!mesh || (chunk.placing?.mesh === mesh && chunk.placing.placement === placement))
|
|
449
|
+
return;
|
|
450
|
+
// This request's own token: one superseded (another mesh, or placement) is dropped when it
|
|
451
|
+
// lands, without dropping the request that replaced it.
|
|
452
|
+
const placing = { mesh, placement };
|
|
453
|
+
chunk.placing = placing;
|
|
454
|
+
placeInWorker(mesh.vertices, { size: [1, 1, 1], world: [1, 1, 1], planes: placement }).then((world) => {
|
|
455
|
+
if (chunk.placing !== placing)
|
|
456
|
+
return;
|
|
457
|
+
chunk.placing = null;
|
|
458
|
+
if (chunk.mesh !== mesh || this.placement !== placement)
|
|
459
|
+
return;
|
|
460
|
+
chunk.world = world;
|
|
461
|
+
this.draw(chunk);
|
|
462
|
+
this.host.viewer.requestRender();
|
|
463
|
+
}, (err) => {
|
|
464
|
+
if (chunk.placing === placing)
|
|
465
|
+
chunk.placing = null;
|
|
466
|
+
console.warn('[napari-js] cells could not be placed in 3D', err);
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
/** Draw a chunk's visible cells, in their colours: its layer updated in place, or added. */
|
|
470
|
+
draw(chunk) {
|
|
471
|
+
const mesh = chunk.mesh;
|
|
472
|
+
const placement = this.placement;
|
|
473
|
+
if (!mesh || !placement || chunk.want < 0) {
|
|
474
|
+
this.dropLayer(chunk);
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
if (!chunk.world) {
|
|
478
|
+
// Placed off the main thread; drawn when it lands.
|
|
479
|
+
this.placeChunk(chunk, placement);
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
const visible = this.visibleFaces(chunk);
|
|
483
|
+
// With a selection, its cells in a surface of their own (see Chunk.selectedLayer).
|
|
484
|
+
const [selected, rest] = this.selected
|
|
485
|
+
? splitFaces(visible, mesh.vertexCell, this.selected)
|
|
486
|
+
: [new Uint32Array(0), visible];
|
|
487
|
+
chunk.drawn = rest;
|
|
488
|
+
chunk.drawnSelected = selected;
|
|
489
|
+
chunk.layer = this.drawSurface(chunk, chunk.layer, rest, this.vertexColors(mesh), this.opacity, 'cells');
|
|
490
|
+
chunk.selectedLayer = this.drawSurface(chunk, chunk.selectedLayer, selected, selected.length ? this.vertexColors(mesh, true) : null, 1, 'selected cells');
|
|
491
|
+
}
|
|
492
|
+
/**
|
|
493
|
+
* One of a chunk's surfaces with these triangles and colours: updated in place, added, or hidden
|
|
494
|
+
* when it has none. Returns the layer (null: none was ever needed).
|
|
495
|
+
*/
|
|
496
|
+
drawSurface(chunk, layer, faces, colors, opacity, name) {
|
|
497
|
+
if (!faces.length || !colors || !chunk.world) {
|
|
498
|
+
if (layer)
|
|
499
|
+
layer.visible = false;
|
|
500
|
+
return layer;
|
|
501
|
+
}
|
|
502
|
+
if (layer) {
|
|
503
|
+
// A recolour, a new opacity: the geometry stays as uploaded.
|
|
504
|
+
const had = this.installed.get(layer);
|
|
505
|
+
if (!had || had.world !== chunk.world || !sameFaces(had.faces, faces)) {
|
|
506
|
+
layer.setData(chunk.world, faces);
|
|
507
|
+
this.installed.set(layer, { world: chunk.world, faces });
|
|
508
|
+
}
|
|
509
|
+
layer.vertexColors = colors;
|
|
510
|
+
layer.opacity = opacity;
|
|
511
|
+
layer.visible = true;
|
|
512
|
+
return layer;
|
|
513
|
+
}
|
|
514
|
+
const added = this.host.viewer.addSurface(chunk.world, faces, undefined, {
|
|
515
|
+
name: `${name} ${chunk.key}`,
|
|
516
|
+
vertexColors: colors,
|
|
517
|
+
opacity,
|
|
518
|
+
blending: 'translucent',
|
|
519
|
+
scale3d: [1, 1, this.zScale],
|
|
520
|
+
fit: 'never',
|
|
521
|
+
});
|
|
522
|
+
this.byLayer.set(added, chunk);
|
|
523
|
+
this.installed.set(added, { world: chunk.world, faces });
|
|
524
|
+
return added;
|
|
525
|
+
}
|
|
526
|
+
/** The triangles of the cells shown: their class not hidden, the observation shown. */
|
|
527
|
+
visibleFaces(chunk) {
|
|
528
|
+
const mesh = chunk.mesh;
|
|
529
|
+
const { faces, vertexCell } = mesh;
|
|
530
|
+
const visible = this.visible;
|
|
531
|
+
const hidden = this.hidden;
|
|
532
|
+
const shown = new Map();
|
|
533
|
+
const isShown = (cell) => {
|
|
534
|
+
let s = shown.get(cell);
|
|
535
|
+
if (s === undefined) {
|
|
536
|
+
const label = chunk.labels.get(cell) ?? null;
|
|
537
|
+
s = !(label !== null && hidden.has(label)) && (!visible || !!visible[cell]);
|
|
538
|
+
shown.set(cell, s);
|
|
539
|
+
}
|
|
540
|
+
return s;
|
|
541
|
+
};
|
|
542
|
+
if (!hidden.size && !visible)
|
|
543
|
+
return faces;
|
|
544
|
+
const out = new Uint32Array(faces.length);
|
|
545
|
+
let n = 0;
|
|
546
|
+
for (let f = 0; f < faces.length; f += 3) {
|
|
547
|
+
if (!isShown(vertexCell[faces[f]]))
|
|
548
|
+
continue;
|
|
549
|
+
out[n++] = faces[f];
|
|
550
|
+
out[n++] = faces[f + 1];
|
|
551
|
+
out[n++] = faces[f + 2];
|
|
552
|
+
}
|
|
553
|
+
return n === faces.length ? faces : out.slice(0, n);
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* Each vertex its cell's colour (white without colours). With a selection, a cell it leaves out
|
|
557
|
+
* keeps its colour and fades, as a picked region fades the others: its alpha brought down to the
|
|
558
|
+
* dimmed regions' opacity. `solid`: the selected cells' own surface, every vertex opaque.
|
|
559
|
+
*/
|
|
560
|
+
vertexColors(mesh, solid = false) {
|
|
561
|
+
const out = new Float32Array(mesh.vertexCell.length * 4);
|
|
562
|
+
const colors = this.colors;
|
|
563
|
+
const selected = this.selected;
|
|
564
|
+
const o = this.opacity > 0 ? this.opacity : 1;
|
|
565
|
+
const dim = Math.min(1, REGION_MESH_DIMMED_OPACITY / o);
|
|
566
|
+
for (let v = 0; v < mesh.vertexCell.length; v++) {
|
|
567
|
+
const o = mesh.vertexCell[v] * 4;
|
|
568
|
+
if (colors && o + 3 < colors.length) {
|
|
569
|
+
out[v * 4] = colors[o];
|
|
570
|
+
out[v * 4 + 1] = colors[o + 1];
|
|
571
|
+
out[v * 4 + 2] = colors[o + 2];
|
|
572
|
+
out[v * 4 + 3] = colors[o + 3];
|
|
573
|
+
}
|
|
574
|
+
else {
|
|
575
|
+
out.fill(1, v * 4, v * 4 + 4);
|
|
576
|
+
}
|
|
577
|
+
if (solid)
|
|
578
|
+
out[v * 4 + 3] = 1;
|
|
579
|
+
else if (selected && !selected[mesh.vertexCell[v]])
|
|
580
|
+
out[v * 4 + 3] *= dim;
|
|
581
|
+
}
|
|
582
|
+
return out;
|
|
583
|
+
}
|
|
584
|
+
dropLayer(chunk) {
|
|
585
|
+
for (const layer of [chunk.layer, chunk.selectedLayer]) {
|
|
586
|
+
if (!layer)
|
|
587
|
+
continue;
|
|
588
|
+
this.byLayer.delete(layer);
|
|
589
|
+
this.host.viewer.layers.remove(layer);
|
|
590
|
+
}
|
|
591
|
+
chunk.layer = null;
|
|
592
|
+
chunk.selectedLayer = null;
|
|
593
|
+
}
|
|
594
|
+
report(building) {
|
|
595
|
+
if (!this.classes) {
|
|
596
|
+
this.emit(null);
|
|
597
|
+
return;
|
|
598
|
+
}
|
|
599
|
+
const drawn = this.chunks.filter((c) => c.layer && c.want >= 0);
|
|
600
|
+
const shown = drawn.reduce((s, c) => s + Math.max(0, c.meshed), 0);
|
|
601
|
+
const capped = this.chunks.some((c) => c.want < 0 || (c.want >= 0 && c.builtLimit < c.cells));
|
|
602
|
+
this.emit({ shown, capped, building: building || this.running });
|
|
603
|
+
}
|
|
604
|
+
emit(status) {
|
|
605
|
+
const key = JSON.stringify(status);
|
|
606
|
+
if (key === this.lastStatus)
|
|
607
|
+
return;
|
|
608
|
+
this.lastStatus = key;
|
|
609
|
+
this.host.status(status);
|
|
610
|
+
}
|
|
611
|
+
toWorldPoint(x, y, z) {
|
|
612
|
+
return this.placement
|
|
613
|
+
? toWorld(Float32Array.of(x, y, z), { size: [1, 1, 1], world: [1, 1, 1], planes: this.placement })
|
|
614
|
+
: Float32Array.of(x, y, z);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
/** The chunk grid over a region set's bounds, {@link CHUNKS_ACROSS} along its longer side. */
|
|
618
|
+
function makeChunks(source) {
|
|
619
|
+
const b = source.info.bounds;
|
|
620
|
+
if (!b)
|
|
621
|
+
return [];
|
|
622
|
+
const size = Math.max(b[2] - b[0], b[3] - b[1]) / CHUNKS_ACROSS || 1;
|
|
623
|
+
const out = [];
|
|
624
|
+
for (let y = b[1]; y < b[3]; y += size) {
|
|
625
|
+
for (let x = b[0]; x < b[2]; x += size) {
|
|
626
|
+
// The last chunk of a row (column) reaches past the bounds: a cell centred on them is in it.
|
|
627
|
+
const x1 = x + size >= b[2] ? b[2] + 1 : x + size;
|
|
628
|
+
const y1 = y + size >= b[3] ? b[3] + 1 : y + size;
|
|
629
|
+
out.push({
|
|
630
|
+
key: `${Math.round(x)},${Math.round(y)}`,
|
|
631
|
+
box: [x, y, x1, y1],
|
|
632
|
+
tier: -1,
|
|
633
|
+
want: -1,
|
|
634
|
+
cells: -1,
|
|
635
|
+
triangles: new Map(),
|
|
636
|
+
limit: Infinity,
|
|
637
|
+
builtLimit: Infinity,
|
|
638
|
+
meshed: -1,
|
|
639
|
+
mesh: null,
|
|
640
|
+
labels: new Map(),
|
|
641
|
+
world: null,
|
|
642
|
+
drawn: null,
|
|
643
|
+
drawnSelected: null,
|
|
644
|
+
selectedLayer: null,
|
|
645
|
+
layer: null,
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
return out;
|
|
650
|
+
}
|
|
651
|
+
/** Meshes concatenated, each vertex keeping its cell. */
|
|
652
|
+
function concatMeshes(parts) {
|
|
653
|
+
if (parts.length === 1)
|
|
654
|
+
return parts[0];
|
|
655
|
+
const nv = parts.reduce((s, p) => s + p.vertexCell.length, 0);
|
|
656
|
+
const nf = parts.reduce((s, p) => s + p.faces.length, 0);
|
|
657
|
+
const nc = parts.reduce((s, p) => s + p.cells.length, 0);
|
|
658
|
+
const out = {
|
|
659
|
+
vertices: new Float32Array(nv * 3),
|
|
660
|
+
faces: new Uint32Array(nf),
|
|
661
|
+
vertexCell: new Uint32Array(nv),
|
|
662
|
+
cells: new Uint32Array(nc),
|
|
663
|
+
};
|
|
664
|
+
let v = 0;
|
|
665
|
+
let f = 0;
|
|
666
|
+
let c = 0;
|
|
667
|
+
for (const p of parts) {
|
|
668
|
+
out.vertices.set(p.vertices, v * 3);
|
|
669
|
+
out.vertexCell.set(p.vertexCell, v);
|
|
670
|
+
for (let i = 0; i < p.faces.length; i++)
|
|
671
|
+
out.faces[f + i] = p.faces[i] + v;
|
|
672
|
+
out.cells.set(p.cells, c);
|
|
673
|
+
v += p.vertexCell.length;
|
|
674
|
+
f += p.faces.length;
|
|
675
|
+
c += p.cells.length;
|
|
676
|
+
}
|
|
677
|
+
return out;
|
|
678
|
+
}
|
|
679
|
+
/** The middle of the planes' slice range (slice units). */
|
|
680
|
+
function midZ(p) {
|
|
681
|
+
return (p.z.length - 1) / 2;
|
|
682
|
+
}
|
|
683
|
+
/**
|
|
684
|
+
* Whether a chunk is to be built (again): its tier changed, or it was meshed in part and the plan
|
|
685
|
+
* now lets it have more of its cells, or fewer.
|
|
686
|
+
*/
|
|
687
|
+
function needsBuild(c) {
|
|
688
|
+
if (c.want < 0)
|
|
689
|
+
return false;
|
|
690
|
+
if (c.want !== c.tier)
|
|
691
|
+
return true;
|
|
692
|
+
return c.cells >= 0 && Math.min(c.builtLimit, c.cells) !== Math.min(c.limit, c.cells);
|
|
693
|
+
}
|
|
694
|
+
/** Whether two face lists are the same triangles. */
|
|
695
|
+
function sameFaces(a, b) {
|
|
696
|
+
if (a === b)
|
|
697
|
+
return true;
|
|
698
|
+
if (a.length !== b.length)
|
|
699
|
+
return false;
|
|
700
|
+
for (let i = 0; i < a.length; i++)
|
|
701
|
+
if (a[i] !== b[i])
|
|
702
|
+
return false;
|
|
703
|
+
return true;
|
|
704
|
+
}
|
|
705
|
+
function sameSet(a, b) {
|
|
706
|
+
if (a === b)
|
|
707
|
+
return true;
|
|
708
|
+
if (!a || !b || a.size !== b.size)
|
|
709
|
+
return false;
|
|
710
|
+
for (const x of a)
|
|
711
|
+
if (!b.has(x))
|
|
712
|
+
return false;
|
|
713
|
+
return true;
|
|
714
|
+
}
|
|
715
|
+
function samePlacement(a, b) {
|
|
716
|
+
if (a === b)
|
|
717
|
+
return true;
|
|
718
|
+
if (!a || !b || a.z.length !== b.z.length)
|
|
719
|
+
return false;
|
|
720
|
+
return (a.z.every((v, i) => v === b.z[i]) &&
|
|
721
|
+
a.scale.every((v, i) => v === b.scale[i]) &&
|
|
722
|
+
a.offset.every((v, i) => v === b.offset[i]));
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Triangles `faces` split by whether their cell (`vertexCell` of their first vertex) is selected:
|
|
726
|
+
* the selected cells' triangles, then the others'.
|
|
727
|
+
*/
|
|
728
|
+
export function splitFaces(faces, vertexCell, selected) {
|
|
729
|
+
const sel = new Uint32Array(faces.length);
|
|
730
|
+
const rest = new Uint32Array(faces.length);
|
|
731
|
+
let s = 0;
|
|
732
|
+
let r = 0;
|
|
733
|
+
for (let f = 0; f < faces.length; f += 3) {
|
|
734
|
+
const out = selected[vertexCell[faces[f]]] ? sel : rest;
|
|
735
|
+
const at = out === sel ? s : r;
|
|
736
|
+
out[at] = faces[f];
|
|
737
|
+
out[at + 1] = faces[f + 1];
|
|
738
|
+
out[at + 2] = faces[f + 2];
|
|
739
|
+
if (out === sel)
|
|
740
|
+
s += 3;
|
|
741
|
+
else
|
|
742
|
+
r += 3;
|
|
743
|
+
}
|
|
744
|
+
return [sel.slice(0, s), rest.slice(0, r)];
|
|
745
|
+
}
|
|
746
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFwYXJpLXNwYXRpYWwtM2QtY2VsbHMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2ltcGxlbWVudGF0aW9ucy9uYXBhcmktanMvbmFwYXJpLXNwYXRpYWwtM2QtY2VsbHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBT0EsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sa0NBQWtDLENBQUM7QUFDckUsT0FBTyxFQUFFLGFBQWEsRUFBRSx3QkFBd0IsRUFBRSxNQUFNLDBDQUEwQyxDQUFDO0FBQ25HLE9BQU8sRUFBRSxxQkFBcUIsRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3BGLE9BQU8sRUFBRSxtQkFBbUIsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBQ3hELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3ZFLE9BQU8sRUFBa0IsMEJBQTBCLEVBQUUsT0FBTyxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFcEc7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQkc7QUFFSCxvQ0FBb0M7QUFDcEMsTUFBTSxDQUFDLE1BQU0sa0JBQWtCLEdBQUcsTUFBTSxDQUFDO0FBQ3pDLHdEQUF3RDtBQUN4RCxNQUFNLENBQUMsTUFBTSx3QkFBd0IsR0FBRyxTQUFTLENBQUM7QUFDbEQsZ0VBQWdFO0FBQ2hFLE1BQU0sYUFBYSxHQUFHLENBQUMsQ0FBQztBQUN4Qix1REFBdUQ7QUFDdkQsTUFBTSxlQUFlLEdBQUcsQ0FBQyxDQUFDO0FBQzFCLHFFQUFxRTtBQUNyRSxNQUFNLEtBQUssR0FBRyxHQUFHLENBQUM7QUFDbEIsc0VBQXNFO0FBQ3RFLE1BQU0sY0FBYyxHQUFHLEdBQUcsQ0FBQztBQUMzQix3RUFBd0U7QUFDeEUsTUFBTSxZQUFZLEdBQUcsQ0FBQyxDQUFDO0FBQ3ZCLGtGQUFrRjtBQUNsRixNQUFNLGNBQWMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEVBQUUs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QUksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUU7WUFDM0IsTUFBTSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUM7WUFDL0IsTUFBTSxFQUFFLEdBQUcsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3pCLE1BQU0sQ0FBQyxHQUFHLElBQUksQ0FBQyxZQUFZLENBQUMsQ0FBQyxFQUFFLEdBQUcsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsQ0FBQztZQUNyRCxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsWUFBWSxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUM7WUFDMUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ2xCLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDeEIsQ0FBQyxDQUFDLENBQUM7UUFDSCxNQUFNLElBQUksR0FBRyxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNqRSxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRTtZQUN2QyxNQUFNLEVBQUUsR0FBRyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUM7WUFDdEMsTUFBTSxFQUFFLEdBQUcsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLEdBQUcsQ0FBQztZQUMxQyxNQUFNLEVBQUUsR0FBRyxJQUFJLEVBQUUsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDO1lBQzFDLE1BQU0sRUFBRSxHQUFHLElBQUksRUFBRSxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUM7WUFDMUMsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsR0FBRyxFQUFFLENBQUMsQ0FBQztZQUMxQyxNQUFNLEtBQUssR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNoRCxNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUNsRSxNQUFNLFFBQVEsR0FDWixNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLElBQUksSUFBSSxFQUFFLEdBQUcsRUFBRSxHQUFHLElBQUksSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJLElBQUksRUFBRSxHQUFHLEVBQUUsR0FBRyxJQUFJLElBQUksR0FBRyxHQUFHLENBQUMsQ0FBQztZQUNqRyxNQUFNLEVBQUUsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFH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QUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDaEQsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDakMsSUFBSSxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUM7Z0JBQ3BDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUN2QixHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUMvQixHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO2dCQUMvQixHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ2pDLENBQUM7aUJBQU0sQ0FBQztnQkFDTixHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDaEMsQ0FBQztZQUNELElBQUksS0FBSztnQkFBRSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7aUJBQ3pCLElBQUksUUFBUSxJQUFJLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQUUsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDO1FBQzVFLENBQUM7UUFDRCxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUM7SUFFTyxTQUFTLENBQUMsS0FBWTtRQUM1QixLQUFLLE1BQU0sS0FBSyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztZQUN2RCxJQUFJLENBQUMsS0FBSztnQkFBRSxTQUFTO1lBQ3JCLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQzNCLElBQUksQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDeEMsQ0FBQztRQUNELEtBQUssQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDO1FBQ25CLEtBQUssQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO0lBQzdCLENBQUM7SUFFTyxNQUFNLENBQUMsUUFBaUI7UUFDOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNsQixJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ2hCLE9BQU87UUFDVCxDQUFDO1FBQ0QsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLENBQUMsQ0FBQztRQUNoRSxNQUFNLEtBQUssR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNuRSxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsVUFBVSxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQzlGLElBQUksQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxRQUFRLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7SUFDbkUsQ0FBQztJQUlPLElBQUksQ0FBQyxNQUE0QjtRQUN2QyxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBQ25DLElBQUksR0FBRyxLQUFLLElBQUksQ0FBQyxVQUFVO1lBQUUsT0FBTztRQUNwQyxJQUFJLENBQUMsVUFBVSxHQUFHLEdBQUcsQ0FBQztRQUN0QixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUMzQixDQUFDO0lBRU8sWUFBWSxDQUFDLENBQVMsRUFBRSxDQUFTLEVBQUUsQ0FBUztRQUNsRCxPQUFPLElBQUksQ0FBQyxTQUFTO1lBQ25CLENBQUMsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUM7WUFDbEcsQ0FBQyxDQUFDLFlBQVksQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUMvQixDQUFDO0NBQ0Y7QUFFRCw4RkFBOEY7QUFDOUYsU0FBUyxVQUFVLENBQUMsTUFBb0I7SUFDdEMsTUFBTSxDQUFDLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUM7SUFDN0IsSUFBSSxDQUFDLENBQUM7UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNsQixNQUFNLElBQUksR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLGFBQWEsSUFBSSxDQUFDLENBQUM7SUFDckUsTUFBTSxHQUFHLEdBQVksRUFBRSxDQUFDO0lBQ3hCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO1FBQ3ZDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDO1lBQ3ZDLDZGQUE2RjtZQUM3RixNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQztZQUNsRCxNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQztZQUNsRCxHQUFHLENBQUMsSUFBSSxDQUFDO2dCQUNQLEdBQUcsRUFBRSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDeEMsR0FBRyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO2dCQUNuQixJQUFJLEVBQUUsQ0FBQyxDQUFDO2dCQUNSLElBQUksRUFBRSxDQUFDLENBQUM7Z0JBQ1IsS0FBSyxFQUFFLENBQUMsQ0FBQztnQkFDVCxTQUFTLEVBQUUsSUFBSSxHQUFHLEVBQUU7Z0JBQ3BCLEtBQUssRUFBRSxRQUFRO2dCQUNmLFVBQVUsRUFBRSxRQUFRO2dCQUNwQixNQUFNLEVBQUUsQ0FBQyxDQUFDO2dCQUNWLElBQUksRUFBRSxJQUFJO2dCQUNWLE1BQU0sRUFBRSxJQUFJLEdBQUcsRUFBRTtnQkFDakIsS0FBSyxFQUFFLElBQUk7Z0JBQ1gsS0FBSyxFQUFFLElBQUk7Z0JBQ1gsYUFBYSxFQUFFLElBQUk7Z0JBQ25CLGFBQWEsRUFBRSxJQUFJO2dCQUNuQixLQUFLLEVBQUUsSUFBSTthQUNaLENBQUMsQ0FBQztRQUNMLENBQUM7SUFDSCxDQUFDO0lBQ0QsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBRUQseURBQXlEO0FBQ3pELFNBQVMsWUFBWSxDQUFDLEtBQTJCO0lBQy9DLElBQUksS0FBSyxDQUFDLE1BQU0sS0FBSyxDQUFDO1FBQUUsT0FBTyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDeEMsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsVUFBVSxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztJQUM5RCxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQ3pELE1BQU0sRUFBRSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxDQUFDLENBQUM7SUFDekQsTUFBTSxHQUFHLEdBQWM7UUFDckIsUUFBUSxFQUFFLElBQUksWUFBWSxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUM7UUFDbEMsS0FBSyxFQUFFLElBQUksV0FBVyxDQUFDLEVBQUUsQ0FBQztRQUMxQixVQUFVLEVBQUUsSUFBSSxXQUFXLENBQUMsRUFBRSxDQUFDO1FBQy9CLEtBQUssRUFBRSxJQUFJLFdBQVcsQ0FBQyxFQUFFLENBQUM7S0FDM0IsQ0FBQztJQUNGLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNWLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNWLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNWLEtBQUssTUFBTSxDQUFDLElBQUksS0FBSyxFQUFFLENBQUM7UUFDdEIsR0FBRyxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDcEMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUNwQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFO1lBQUUsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDM0UsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQztRQUMxQixDQUFDLElBQUksQ0FBQyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7UUFDekIsQ0FBQyxJQUFJLENBQUMsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDO1FBQ3BCLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQztJQUN0QixDQUFDO0lBQ0QsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBRUQsMkRBQTJEO0FBQzNELFNBQVMsSUFBSSxDQUFDLENBQWlCO0lBQzdCLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDOUIsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsVUFBVSxDQUFDLENBQVE7SUFDMUIsSUFBSSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUM7UUFBRSxPQUFPLEtBQUssQ0FBQztJQUM3QixJQUFJLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxDQUFDLElBQUk7UUFBRSxPQUFPLElBQUksQ0FBQztJQUNuQyxPQUFPLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxJQUFJLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztBQUN4RixDQUFDO0FBRUQscURBQXFEO0FBQ3JELFNBQVMsU0FBUyxDQUFDLENBQWMsRUFBRSxDQUFjO0lBQy9DLElBQUksQ0FBQyxLQUFLLENBQUM7UUFBRSxPQUFPLElBQUksQ0FBQztJQUN6QixJQUFJLENBQUMsQ0FBQyxNQUFNLEtBQUssQ0FBQyxDQUFDLE1BQU07UUFBRSxPQUFPLEtBQUssQ0FBQztJQUN4QyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUU7UUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQUUsT0FBTyxLQUFLLENBQUM7SUFDbkUsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQsU0FBUyxPQUFPLENBQUMsQ0FBNkIsRUFBRSxDQUE2QjtJQUMzRSxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDekIsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxLQUFLLENBQUMsQ0FBQyxJQUFJO1FBQUUsT0FBTyxLQUFLLENBQUM7SUFDaEQsS0FBSyxNQUFNLENBQUMsSUFBSSxDQUFDO1FBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQUUsT0FBTyxLQUFLLENBQUM7SUFDL0MsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQsU0FBUyxhQUFhLENBQUMsQ0FBd0IsRUFBRSxDQUF3QjtJQUN2RSxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDekIsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU07UUFBRSxPQUFPLEtBQUssQ0FBQztJQUN4RCxPQUFPLENBQ0wsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNqQyxDQUFDLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3pDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FDNUMsQ0FBQztBQUNKLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsVUFBVSxDQUN4QixLQUFrQixFQUNsQixVQUF1QixFQUN2QixRQUFvQjtJQUVwQixNQUFNLEdBQUcsR0FBRyxJQUFJLFdBQVcsQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7SUFDMUMsTUFBTSxJQUFJLEdBQUcsSUFBSSxXQUFXLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzNDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNWLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUNWLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUN6QyxNQUFNLEdBQUcsR0FBRyxRQUFRLENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ3hELE1BQU0sRUFBRSxHQUFHLEdBQUcsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQy9CLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkIsR0FBRyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzNCLEdBQUcsQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUMzQixJQUFJLEdBQUcsS0FBSyxHQUFHO1lBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQzs7WUFDbkIsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNkLENBQUM7SUFDRCxPQUFPLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQztBQUM3QyxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBMYXllciwgU3VyZmFjZUxheWVyLCBWaWV3ZXIgfSBmcm9tICduYXBhcmktanMnO1xuXG5pbXBvcnQgdHlwZSB7IENlbGxzM2RTdGF0dXMgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvZGlzcGxheS10eXBlcyc7XG5pbXBvcnQgdHlwZSB7IFNwYXRpYWxEYXRhUG9ydCB9IGZyb20gJy4uLy4uL2NvbnRyYWN0cy9wb3J0cy9zcGF0aWFsLWRhdGEucG9ydCc7XG5pbXBvcnQgdHlwZSB7IFNwYXRpYWxEYXRhc2V0IH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL3NwYXRpYWwtZGF0YXNldC5jb250cmFjdCc7XG5pbXBvcnQgdHlwZSB7IENlbGxzTWVzaCB9IGZyb20gJy4uLy4uL2dlb21ldHJ5L2NlbGwtbWVzaGVzJztcbmltcG9ydCB0eXBlIHsgUmVnaW9uU291cmNlIH0gZnJvbSAnLi4vLi4vcmVnaW9uLXNvdXJjZS9yZWdpb24tc291cmNlJztcbmltcG9ydCB7IHJlZ2lvblRpbGVzSW5SZWN0IH0gZnJvbSAnLi4vLi4vcmVnaW9uLXNvdXJjZS9yZWdpb24tdGlsZXMnO1xuaW1wb3J0IHsgcGxhY2VJbldvcmtlciwgcmVjb25zdHJ1Y3RDZWxsc0luV29ya2VyIH0gZnJvbSAnLi4vLi4vcmVnaW9uLXNvdXJjZS93b3JrZXItcmVnaW9uLXNvdXJjZSc7XG5pbXBvcnQgeyBjZWxsT3V0bGluZXNGcm9tVGlsZXMsIG9ic2VydmF0aW9uSW5kZXggfSBmcm9tICcuLi8uLi9zcGF0aWFsL3BsYW5lLWNlbGxzJztcbmltcG9ydCB7IHR5cGljYWxDZWxsRGlhbWV0ZXIgfSBmcm9tICcuLi8uLi9zcGF0aWFsL2xvZCc7XG5pbXBvcnQgeyBkYXRhc2V0UmVnaW9uU2V0IH0gZnJvbSAnLi4vLi4vdmlzdWFsaXplci9zcGF0aWFsLXJlZ2lvbi1zZXQnO1xuaW1wb3J0IHsgUGxhbmVQbGFjZW1lbnQsIFJFR0lPTl9NRVNIX0RJTU1FRF9PUEFDSVRZLCB0b1dvcmxkIH0gZnJvbSAnLi9uYXBhcmktdm9sdW1lLXJlZ2lvbi1tZXNoZXMnO1xuXG4vKipcbiAqIEEgM0Qgc2VnbWVudGF0aW9uJ3MgY2VsbHMgaW4gdGhlIHNwYXRpYWwgM0QgdmlldywgZWFjaCByZWNvbnN0cnVjdGVkIGJ5IGl0c2VsZiAoc2VlXG4gKiBgZ2VvbWV0cnkvY2VsbC1tZXNoZXNgKSwgd2hlcmUgdGhlIHJlZ2lvbiBjbGFzc2VzIGFyZSBvdGhlcndpc2Ugb25lIG1lcmdlZCBzdXJmYWNlIHBlciBjbGFzcy5cbiAqXG4gKiBCdWlsdCB0byBzdGF5IG91dCBvZiB0aGUgd2F5IG9mIHRoZSBVSSB0aHJlYWQgYW5kIHRoZSBHUFU6XG4gKiAgLSB0aGUgc3BhY2UgaXMgY3V0IGludG8gY2h1bmtzIChhIGdyaWQgb3ZlciB0aGUgcmVnaW9uIHNldCdzIGJvdW5kcyk7IGVhY2ggY2h1bmsgaXMgb25lIHN1cmZhY2VcbiAqICAgIGxheWVyIG9mIGl0cyBjZWxscywgbWVzaGVkIGluIHRoZSBjZWxscycgb3duIHdvcmtlciwgYSBmZXcgaHVuZHJlZCBjZWxscyBwZXIgY2FsbCwgc28gdGhlXG4gKiAgICB3b3JrIGlzIGNhbmNlbGxlZCBiZXR3ZWVuIGNhbGxzIHdoZW4gdGhlIHZpZXcgbW92ZXMgb24gKGFuZCB0aGUgcmVnaW9uIHRpbGVzIHRoZSAyRCB2aWV3XG4gKiAgICByZWFkcyBuZXZlciB3YWl0IGJlaGluZCBpdCk7XG4gKiAgLSBsZXZlbCBvZiBkZXRhaWwgYnkgY2h1bms6IGEgY29hcnNlIG1lc2ggZXZlcnl3aGVyZSBmaXJzdCwgdGhlbiB0aGUgY2h1bmtzIG9uIHNjcmVlbiBhcmUgbWVzaGVkXG4gKiAgICBmaW5lciBhcyB0aGUgY2FtZXJhIGNvbWVzIGNsb3NlLCB3aXRoaW4gYSB0cmlhbmdsZSBidWRnZXQgZm9yIHRoZSB3aG9sZSBzY2VuZTsgdGhlIHJlZ2lvblxuICogICAgc2V0J3MgdGlsZXMgYXJlIHJlYWQgYXQgdGhlIGxldmVsIG9mIGRldGFpbCB0aGF0IG1lc2ggbmVlZHM7XG4gKiAgLSBhdCBtb3N0IHtAbGluayBDRUxMU18zRF9NQVhfQ0VMTFN9IGNlbGxzIGFuZCB7QGxpbmsgQ0VMTFNfM0RfVFJJQU5HTEVfQlVER0VUfSB0cmlhbmdsZXMsIHRoZVxuICogICAgY2h1bmtzIG5lYXJlc3QgdGhlIGNlbnRyZSBvZiB0aGUgdmlldyBmaXJzdCAob25lIGNodW5rIG92ZXIgZWl0aGVyIGJ5IGl0c2VsZiBpcyBtZXNoZWQgaW5cbiAqICAgIHBhcnQpLCBwbGFubmVkIGFnYWluIGFzIGVhY2ggY2h1bmsncyByZWFsIHNpemUgaXMgbGVhcm50OyB0aGUgc3RhdHVzIHNheXMgd2hlbiBjZWxscyBhcmUgbGVmdFxuICogICAgb3V0LCBzbyB0aGUgdmlldyBuZXZlciBjbGFpbXMgdG8gc2hvdyB0aGVtIGFsbDtcbiAqICAtIGNvbG91ciBhbmQgdmlzaWJpbGl0eSBjaGFuZ2Ugbm8gZ2VvbWV0cnk6IGNvbG91cnMgYXJlIHBlciB2ZXJ0ZXggKGVhY2ggdmVydGV4J3MgY2VsbCksIGFuZCBhXG4gKiAgICBoaWRkZW4gY2VsbCdzIHRyaWFuZ2xlcyBhcmUgbGVmdCBvdXQgb2Ygd2hhdCBpcyBkcmF3bi5cbiAqIEJ1aWxkcyByZXBvcnQgb24gdGhlIGNhbnZhcydzIGxvYWRpbmcgYmFkZ2UuXG4gKi9cblxuLyoqIFRoZSBtb3N0IGNlbGxzIGRyYXduIGF0IG9uY2UuICovXG5leHBvcnQgY29uc3QgQ0VMTFNfM0RfTUFYX0NFTExTID0gMjBfMDAwO1xuLyoqIFRoZSBtb3N0IHRyaWFuZ2xlcyBldmVyeSBjaHVuayB0b2dldGhlciBtYXkgaGF2ZS4gKi9cbmV4cG9ydCBjb25zdCBDRUxMU18zRF9UUklBTkdMRV9CVURHRVQgPSAzXzAwMF8wMDA7XG4vKiogQ2h1bmtzIGFjcm9zcyB0aGUgbG9uZ2VyIHNpZGUgb2YgdGhlIHJlZ2lvbiBzZXQncyBib3VuZHMuICovXG5jb25zdCBDSFVOS1NfQUNST1NTID0gODtcbi8qKiBBIHJlZHJhdyB5aWVsZHMgdGhlIG1haW4gdGhyZWFkIGFmdGVyIHRoaXMgbG9uZy4gKi9cbmNvbnN0IFJFRFJBV19TTElDRV9NUyA9IDg7XG4vKiogQ2VsbHMgcGVyIHdvcmtlciBjYWxsOiB0aGUgYnVpbGQgY2FuIGJlIGRyb3BwZWQgYmV0d2VlbiBjYWxscy4gKi9cbmNvbnN0IEJBVENIID0gNDAwO1xuLyoqIEEgcGF1c2UgaW4gdGhlIGNhbWVyYSdzIG1vdmVtZW50IHRoaXMgbG9uZyByZS1wbGFucyB0aGUgZGV0YWlsLiAqL1xuY29uc3QgQ0FNRVJBX0lETEVfTVMgPSAyNTA7XG4vKiogQSB2b3hlbCBhdCBsZWFzdCB0aGlzIG1hbnkgc2NyZWVuIHBpeGVscyBhY3Jvc3MgaXMgZGV0YWlsIGVub3VnaC4gKi9cbmNvbnN0IE1JTl9WT1hFTF9QWCA9IDM7XG4vKiogRWFjaCB0aWVyJ3Mgdm94ZWwgZWRnZSwgYXMgYSBmcmFjdGlvbiBvZiBhIGNlbGwncyBkaWFtZXRlcjogY29hcnNlIHRvIGZpbmUuICovXG5jb25zdCBUSUVSX0ZSQUNUSU9OUyA9IFsxIC8gNCwgMSAvIDgsIDEgLyAxNl0gYXMgY29uc3Q7XG4vKiogQSBmaXJzdCBndWVzcyBhdCBhIGNvYXJzZSBjZWxsJ3MgdHJpYW5nbGVzLCBiZWZvcmUgYW55IGNodW5rIHdhcyBidWlsdC4gKi9cbmNvbnN0IENPQVJTRV9UUklBTkdMRVNfUEVSX0NFTEwgPSAzMDA7XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2VsbHMzZEhvc3Qge1xuICByZWFkb25seSB2aWV3ZXI6IFZpZXdlcjtcbiAgcmVhZG9ubHkgcG9ydDogU3BhdGlhbERhdGFQb3J0IHwgbnVsbDtcbiAgLyoqIFNob3cgdGhlIGNlbGxzIGxvYWRpbmcgb24gdGhlIGNhbnZhcyB1bnRpbCB0aGUgcmV0dXJuZWQgZnVuY3Rpb24gaXMgY2FsbGVkLiAqL1xuICBiZWdpblRhc2sobGFiZWw6ICdDZWxscycpOiAoKSA9PiB2b2lkO1xuICBzdGF0dXMoc3RhdHVzOiBDZWxsczNkU3RhdHVzIHwgbnVsbCk6IHZvaWQ7XG59XG5cbmludGVyZmFjZSBDaHVuayB7XG4gIGtleTogc3RyaW5nO1xuICAvKiogSW1hZ2UgcHguICovXG4gIGJveDogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl07XG4gIC8qKiBUaGUgdGllciBidWlsdCAoLTE6IG5vbmUpLCBhbmQgd2FudGVkIGJ5IHRoZSBsYXN0IHBsYW4gKC0xOiBub25lLCBvdXQgb2YgdGhlIGNhcCkuICovXG4gIHRpZXI6IG51bWJlcjtcbiAgd2FudDogbnVtYmVyO1xuICAvKiogQ2VsbHMgaXQgaGFzICgtMSB1bnRpbCBidWlsdCksIGFuZCBpdHMgdHJpYW5nbGVzIGJ5IHRpZXIgYnVpbHQuICovXG4gIGNlbGxzOiBudW1iZXI7XG4gIHRyaWFuZ2xlczogTWFwPG51bWJlciwgbnVtYmVyPjtcbiAgLyoqIFRoZSBtb3N0IGNlbGxzIGl0IG1heSBtZXNoICh0aGUgY2FwLCBvciB0aGUgYnVkZ2V0LCBsZWZ0IGZvciBpdDsgSW5maW5pdHk6IGFsbCkuICovXG4gIGxpbWl0OiBudW1iZXI7XG4gIC8qKiBUaGUgbGltaXQgaXQgd2FzIGJ1aWx0IHdpdGgsIGFuZCB0aGUgY2VsbHMgaXQgbWVzaGVkICgtMSB1bnRpbCBidWlsdCkuICovXG4gIGJ1aWx0TGltaXQ6IG51bWJlcjtcbiAgbWVzaGVkOiBudW1iZXI7XG4gIG1lc2g6IENlbGxzTWVzaCB8IG51bGw7XG4gIC8qKiBFYWNoIG1lc2hlZCBjZWxsJ3MgY2xhc3MuICovXG4gIGxhYmVsczogTWFwPG51bWJlciwgc3RyaW5nIHwgbnVsbD47XG4gIHdvcmxkOiBGbG9hdDMyQXJyYXkgfCBudWxsO1xuICAvKipcbiAgICogVGhlIHRyaWFuZ2xlcyBkcmF3biBpbiB7QGxpbmsgbGF5ZXJ9ICh0aGUgdmlzaWJsZSBjZWxscycsIG9yIHdpdGggYSBzZWxlY3Rpb24gdGhvc2UgaXQgbGVhdmVzXG4gICAqIG91dCksIGFzIGluZGljZXMgaW50byB0aGUgbWVzaCdzIHZlcnRpY2VzLlxuICAgKi9cbiAgZHJhd246IFVpbnQzMkFycmF5IHwgbnVsbDtcbiAgbGF5ZXI6IFN1cmZhY2VMYXllciB8IG51bGw7XG4gIC8qKlxuICAgKiBXaXRoIGEgc2VsZWN0aW9uLCBpdHMgY2VsbHMnIHRyaWFuZ2xlcywgZHJhd24gaW4ge0BsaW5rIHNlbGVjdGVkTGF5ZXJ9OiBhbiBvcGFxdWUgc3VyZmFjZSBvZlxuICAgKiB0aGVpciBvd24sIHNvIHRoZSBmYWRlZCBjZWxscyBpbiBmcm9udCBvZiB0aGVtIChhIHRyYW5zbHVjZW50IHN1cmZhY2UgZHJhd3Mgb25seSBpdHMgbmVhcmVzdFxuICAgKiBmYWNlcykgc2hvdyB0aGVtIHRocm91Z2ggcmF0aGVyIHRoYW4gaGlkZSB0aGVtLlxuICAgKi9cbiAgZHJhd25TZWxlY3RlZDogVWludDMyQXJyYXkgfCBudWxsO1xuICBzZWxlY3RlZExheWVyOiBTdXJmYWNlTGF5ZXIgfCBudWxsO1xuICAvKiogVGhlIHBsYWNlbWVudCBpbiBmbGlnaHQgKGl0cyBtZXNoIGFuZCB3aGVyZSBpdCBwbGFjZXMgaXQpLCBpZiBhbnkuICovXG4gIHBsYWNpbmc/OiB7IG1lc2g6IENlbGxzTWVzaDsgcGxhY2VtZW50OiBQbGFuZVBsYWNlbWVudCB9IHwgbnVsbDtcbn1cblxuZXhwb3J0IHR5cGUgeyBDZWxsczNkU3RhdHVzIH07XG5cbmV4cG9ydCBjbGFzcyBTcGF0aWFsM2RDZWxscyB7XG4gIHByaXZhdGUgZGF0YXNldDogU3BhdGlhbERhdGFzZXQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBzb3VyY2U6IHsgaWQ6IHN0cmluZzsgb3BlbjogUHJvbWlzZTxSZWdpb25Tb3VyY2U+IH0gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBjbGFzc2VzOiBSZWFkb25seVNldDxzdHJpbmc+IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgaGlkZGVuOiBSZWFkb25seVNldDxzdHJpbmc+ID0gbmV3IFNldCgpO1xuICBwcml2YXRlIGNvbG9yczogRmxvYXQzMkFycmF5IHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgdmlzaWJsZTogVWludDhBcnJheSB8IG51bGwgPSBudWxsO1xuICAvKiogVGhlIHNlbGVjdGlvbiAobnVsbDogbm9uZSk6IHRoZSBjZWxscyBpdCBsZWF2ZXMgb3V0IGZhZGUsIGtlZXBpbmcgdGhlaXIgY29sb3Vycy4gKi9cbiAgcHJpdmF0ZSBzZWxlY3RlZDogVWludDhBcnJheSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIG9wYWNpdHkgPSAxO1xuICBwcml2YXRlIHBsYWNlbWVudDogUGxhbmVQbGFjZW1lbnQgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSB6U2NhbGUgPSAxO1xuICBwcml2YXRlIGNodW5rczogQ2h1bmtbXSA9IFtdO1xuICBwcml2YXRlIHJlYWRvbmx5IGJ5TGF5ZXIgPSBuZXcgTWFwPExheWVyLCBDaHVuaz4oKTtcbiAgcHJpdmF0ZSBnZW5lcmF0aW9uID0gMDtcbiAgcHJpdmF0ZSB0aW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBydW5uaW5nID0gZmFsc2U7XG4gIHByaXZhdGUgZGlzcG9zZWQgPSBmYWxzZTtcbiAgLyoqIEVhY2ggc3VyZmFjZSdzIGdlb21ldHJ5IGFzIGxhc3Qgc2V0OiBhIHJlY29sb3VyIHRoYXQgbGVhdmVzIGl0IHNvIHVwbG9hZHMgbm9uZSBhZ2Fpbi4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBpbnN0YWxsZWQgPSBuZXcgV2Vha01hcDxTdXJmYWNlTGF5ZXIsIHsgd29ybGQ6IEZsb2F0MzJBcnJheTsgZmFjZXM6IFVpbnQzMkFycmF5IH0+KCk7XG4gIHByaXZhdGUgY2FtZXJhT2ZmOiAoKCkgPT4gdm9pZCkgfCBudWxsO1xuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgcmVhZG9ubHkgaG9zdDogQ2VsbHMzZEhvc3QpIHtcbiAgICB0aGlzLmNhbWVyYU9mZiA9IGhvc3Qudmlld2VyLmNhbWVyYTNkLmNoYW5nZWQuY29ubmVjdCgoKSA9PiB0aGlzLnNjaGVkdWxlKENBTUVSQV9JRExFX01TKSk7XG4gIH1cblxuICAvKiogVGhlIGRhdGFzZXQgd2hvc2UgcmVnaW9uIHNldCB0aGUgY2VsbHMgYXJlIHJlYWQgZnJvbS4gKi9cbiAgc2V0RGF0YXNldChkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCB8IG51bGwpOiB2b2lkIHtcbiAgICBpZiAoZGF0YXNldCA9PT0gdGhpcy5kYXRhc2V0KSByZXR1cm47XG4gICAgY29uc3QgaWQgPSBkYXRhc2V0UmVnaW9uU2V0KGRhdGFzZXQpO1xuICAgIGNvbnN0IHNhbWVTZXQgPSAhIWlkICYmIGlkID09PSB0aGlzLnNvdXJjZT8uaWQgJiYgZGF0YXNldD8uaWQgPT09IHRoaXMuZGF0YXNldD8uaWQ7XG4gICAgdGhpcy5kYXRhc2V0ID0gZGF0YXNldDtcbiAgICBpZiAoc2FtZVNldCkgcmV0dXJuO1xuICAgIHRoaXMucmVzZXQoKTtcbiAgICB0aGlzLmNsb3NlU291cmNlKCk7XG4gICAgaWYgKGlkICYmIHRoaXMuaG9zdC5wb3J0Py5vcGVuUmVnaW9uU2V0KSB7XG4gICAgICBjb25zdCBvcGVuID0gdGhpcy5ob3N0LnBvcnQub3BlblJlZ2lvblNldChpZCk7XG4gICAgICB0aGlzLnNvdXJjZSA9IHsgaWQsIG9wZW4gfTtcbiAgICAgIG9wZW4uY2F0Y2goKCkgPT4ge1xuICAgICAgICBpZiAodGhpcy5zb3VyY2U/Lm9wZW4gPT09IG9wZW4pIHRoaXMuc291cmNlID0gbnVsbDtcbiAgICAgIH0pO1xuICAgIH1cbiAgICB0aGlzLnNjaGVkdWxlKDApO1xuICB9XG5cbiAgLyoqIFRoZSBjbGFzc2VzIGRyYXduIGFzIGNlbGxzIChub25lOiB0aGUgY2VsbHMgYXJlIG5vdCBkcmF3bikuICovXG4gIHNldENsYXNzZXMoY2xhc3NlczogUmVhZG9ubHlTZXQ8c3RyaW5nPiB8IG51bGwpOiB2b2lkIHtcbiAgICBjb25zdCBuZXh0ID0gY2xhc3Nlcz8uc2l6ZSA/IGNsYXNzZXMgOiBudWxsO1xuICAgIGlmIChzYW1lU2V0KG5leHQsIHRoaXMuY2xhc3NlcykpIHJldHVybjtcbiAgICB0aGlzLmNsYXNzZXMgPSBuZXh0O1xuICAgIHRoaXMucmVzZXQoKTtcbiAgICB0aGlzLnNjaGVkdWxlKDApO1xuICB9XG5cbiAgLyoqIENsYXNzZXMgaGlkZGVuICh0aGUgUmVnaW9uIEVkaXRvcidzIGV5ZXMpOiB0aGVpciBjZWxscyBhcmUgbGVmdCBvdXQgb2Ygd2hhdCBpcyBkcmF3bi4gKi9cbiAgc2V0SGlkZGVuQ2xhc3NlcyhjbGFzc2VzOiByZWFkb25seSBzdHJpbmdbXSk6IHZvaWQge1xuICAgIGNvbnN0IG5leHQgPSBuZXcgU2V0KGNsYXNzZXMpO1xuICAgIGlmIChzYW1lU2V0KG5leHQsIHRoaXMuaGlkZGVuKSkgcmV0dXJuO1xuICAgIHRoaXMuaGlkZGVuID0gbmV4dDtcbiAgICB0aGlzLnJlZHJhdygpO1xuICB9XG5cbiAgLyoqXG4gICAqIEVhY2ggb2JzZXJ2YXRpb24ncyBjb2xvdXIgKFJHQkEgMC4uMSkgYW5kIHdoZXRoZXIgaXQgaXMgc2hvd24gKG51bGw6IGFsbCksIGFuZCB0aGUgc3VyZmFjZXMnXG4gICAqIG9wYWNpdHk6IHRoZSBwYW5lbCdzIENlbGwgQ29sb3IsIGdyb3VwcyBhbmQgc2VsZWN0aW9uLiBDaGFuZ2VzIG5vIGdlb21ldHJ5LlxuICAgKi9cbiAgc2V0U3R5bGUoXG4gICAgY29sb3JzOiBGbG9hdDMyQXJyYXkgfCBudWxsLFxuICAgIHZpc2libGU6IFVpbnQ4QXJyYXkgfCBudWxsLFxuICAgIG9wYWNpdHk6IG51bWJlcixcbiAgICBzZWxlY3RlZDogVWludDhBcnJheSB8IG51bGwgPSBudWxsLFxuICApOiB2b2lkIHtcbiAgICB0aGlzLmNvbG9ycyA9IGNvbG9ycztcbiAgICB0aGlzLnZpc2libGUgPSB2aXNpYmxlO1xuICAgIHRoaXMub3BhY2l0eSA9IG9wYWNpdHk7XG4gICAgdGhpcy5zZWxlY3RlZCA9IHNlbGVjdGVkO1xuICAgIHRoaXMucmVkcmF3KCk7XG4gIH1cblxuICAvKiogV2hlcmUgdGhlIHBsYW5lcyBhcmUgYW1vbmcgdGhlIG9ic2VydmF0aW9ucyAobnVsbDogbm93aGVyZSwgbm90aGluZyBkcmF3biksIGFuZCB0aGUgWiBzdHJldGNoLiAqL1xuICBzZXRQbGFjZW1lbnQocGxhY2VtZW50OiBQbGFuZVBsYWNlbWVudCB8IG51bGwsIHpTY2FsZTogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgbW92ZWQgPSAhc2FtZVBsYWNlbWVudChwbGFjZW1lbnQsIHRoaXMucGxhY2VtZW50KTtcbiAgICAvLyBUaGUgc2FtZSBwbGFjZW1lbnQga2VwdCBhcyBpdCB3YXMgKGEgc2NlbmUgcGFzc2VzIGEgbmV3IG9iamVjdCBlYWNoIHRpbWUpOiBhIHBsYWNlbWVudCBpblxuICAgIC8vIGZsaWdodCBmb3IgaXQgaXMgc3RpbGwgZ29vZCB3aGVuIGl0IGxhbmRzLlxuICAgIGlmIChtb3ZlZCkgdGhpcy5wbGFjZW1lbnQgPSBwbGFjZW1lbnQ7XG4gICAgdGhpcy56U2NhbGUgPSB6U2NhbGU7XG4gICAgZm9yIChjb25zdCBjIG9mIHRoaXMuY2h1bmtzKSB7XG4gICAgICBpZiAoYy5sYXllcikgYy5sYXllci5zY2FsZTNkID0gWzEsIDEsIHpTY2FsZV07XG4gICAgICBpZiAoYy5zZWxlY3RlZExheWVyKSBjLnNlbGVjdGVkTGF5ZXIuc2NhbGUzZCA9IFsxLCAxLCB6U2NhbGVdO1xuICAgIH1cbiAgICBpZiAoIW1vdmVkKSByZXR1cm47XG4gICAgZm9yIChjb25zdCBjIG9mIHRoaXMuY2h1bmtzKSB7XG4gICAgICBjLndvcmxkID0gbnVsbDtcbiAgICAgIGMucGxhY2luZyA9IG51bGw7IC8vIG9uZSBpbiBmbGlnaHQgd2FzIGZvciB0aGUgb2xkIHBsYWNlbWVudDogaXQgaXMgZHJvcHBlZCB3aGVuIGl0IGxhbmRzXG4gICAgfVxuICAgIGlmICghcGxhY2VtZW50KSB7XG4gICAgICBmb3IgKGNvbnN0IGMgb2YgdGhpcy5jaHVua3MpIHRoaXMuZHJvcExheWVyKGMpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnJlZHJhdygpO1xuICAgIH1cbiAgICB0aGlzLnNjaGVkdWxlKDApO1xuICB9XG5cbiAgLyoqIFRoZSBvYnNlcnZhdGlvbiBvZiB0aGUgY2VsbCBkcmF3biB1bmRlciBjYW52YXMgcG9pbnQgKGB4YCwgYHlgKSAoQ1NTIHB4KSwgb3IgLTEuICovXG4gIHBpY2soeDogbnVtYmVyLCB5OiBudW1iZXIpOiBudW1iZXIge1xuICAgIGlmICghdGhpcy5ieUxheWVyLnNpemUpIHJldHVybiAtMTtcbiAgICBjb25zdCBoaXQgPSB0aGlzLmhvc3Qudmlld2VyLnBpY2tTdXJmYWNlKHgsIHksIHsgcGlja2FibGU6IChsKSA9PiB0aGlzLmJ5TGF5ZXIuaGFzKGwpIH0pO1xuICAgIGNvbnN0IGNodW5rID0gaGl0ID8gdGhpcy5ieUxheWVyLmdldChoaXQubGF5ZXIpIDogdW5kZWZpbmVkO1xuICAgIGNvbnN0IGZhY2VzID0gaGl0ICYmIGNodW5rICYmIGhpdC5sYXllciA9PT0gY2h1bmsuc2VsZWN0ZWRMYXllciA/IGNodW5rLmRyYXduU2VsZWN0ZWQgOiBjaHVuaz8uZHJhd247XG4gICAgaWYgKCFoaXQgfHwgIWZhY2VzIHx8ICFjaHVuaz8ubWVzaCkgcmV0dXJuIC0xO1xuICAgIGNvbnN0IHZlcnRleCA9IGZhY2VzW2hpdC5mYWNlICogM107XG4gICAgcmV0dXJuIHZlcnRleCA9PT0gdW5kZWZpbmVkID8gLTEgOiBjaHVuay5tZXNoLnZlcnRleENlbGxbdmVydGV4XTtcbiAgfVxuXG4gIC8qKiBXaGV0aGVyIGBsYXllcmAgaXMgb25lIG9mIHRoZSBjZWxscycgc3VyZmFjZXMuICovXG4gIG93bnMobGF5ZXI6IExheWVyKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuYnlMYXllci5oYXMobGF5ZXIpO1xuICB9XG5cbiAgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICB0aGlzLmRpc3Bvc2VkID0gdHJ1ZTtcbiAgICB0aGlzLmNhbWVyYU9mZj8uKCk7XG4gICAgdGhpcy5jYW1lcmFPZmYgPSBudWxsO1xuICAgIGlmICh0aGlzLnRpbWVyKSBjbGVhclRpbWVvdXQodGhpcy50aW1lcik7XG4gICAgdGhpcy50aW1lciA9IG51bGw7XG4gICAgdGhpcy5yZXNldCgpO1xuICAgIHRoaXMuY2xvc2VTb3VyY2UoKTtcbiAgICB0aGlzLmVtaXQobnVsbCk7XG4gIH1cblxuICAvLyDilIDilIAgcGxhbm5pbmcg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJpdmF0ZSBzY2hlZHVsZShkZWxheTogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuZGlzcG9zZWQpIHJldHVybjtcbiAgICBpZiAodGhpcy50aW1lcikgY2xlYXJUaW1lb3V0KHRoaXMudGltZXIpO1xuICAgIHRoaXMudGltZXIgPSBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgIHRoaXMudGltZXIgPSBudWxsO1xuICAgICAgdm9pZCB0aGlzLnBsYW4oKTtcbiAgICB9LCBkZWxheSk7XG4gIH1cblxuICAvKiogRHJvcCBldmVyeSBjaHVuayAodGhlaXIgbGF5ZXJzKSBhbmQgYW55IGJ1aWxkIGluIGZsaWdodC4gKi9cbiAgcHJpdmF0ZSByZXNldCgpOiB2b2lkIHtcbiAgICB0aGlzLmdlbmVyYXRpb24rKztcbiAgICBmb3IgKGNvbnN0IGMgb2YgdGhpcy5jaHVua3MpIHRoaXMuZHJvcExheWVyKGMpO1xuICAgIHRoaXMuY2h1bmtzID0gW107XG4gIH1cblxuICBwcml2YXRlIGNsb3NlU291cmNlKCk6IHZvaWQge1xuICAgIGNvbnN0IHMgPSB0aGlzLnNvdXJjZTtcbiAgICB0aGlzLnNvdXJjZSA9IG51bGw7XG4gICAgdm9pZCBzPy5vcGVuLnRoZW4oXG4gICAgICAoc3JjKSA9PiBzcmMuZGlzcG9zZSgpLFxuICAgICAgKCkgPT4gdW5kZWZpbmVkLFxuICAgICk7XG4gIH1cblxuICAvKiogRGVjaWRlIGVhY2ggY2h1bmsncyBkZXRhaWwgKGFuZCB3aGV0aGVyIGl0IGlzIGRyYXduIGF0IGFsbCksIHRoZW4gYnVpbGQgd2hhdCBjaGFuZ2VkLiAqL1xuICBwcml2YXRlIGFzeW5jIHBsYW4oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZGF0YXNldCA9IHRoaXMuZGF0YXNldDtcbiAgICBjb25zdCBpbmRleCA9IGRhdGFzZXQgPyBvYnNlcnZhdGlvbkluZGV4KGRhdGFzZXQub2JzZXJ2YXRpb25zKSA6IG51bGw7XG4gICAgaWYgKCF0aGlzLmNsYXNzZXMgfHwgIXRoaXMuc291cmNlIHx8ICFkYXRhc2V0IHx8ICFpbmRleCB8fCAhdGhpcy5wbGFjZW1lbnQpIHtcbiAgICAgIGlmICh0aGlzLmNodW5rcy5sZW5ndGgpIHRoaXMucmVzZXQoKTtcbiAgICAgIHRoaXMuZW1pdChudWxsKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZ2VuZXJhdGlvbiA9IHRoaXMuZ2VuZXJhdGlvbjtcbiAgICBsZXQgc291cmNlOiBSZWdpb25Tb3VyY2U7XG4gICAgdHJ5IHtcbiAgICAgIHNvdXJjZSA9IGF3YWl0IHRoaXMuc291cmNlLm9wZW47XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLndhcm4oXCJbbmFwYXJpLWpzXSB0aGUgY2VsbHMnIHJlZ2lvbiBzZXQgY291bGQgbm90IGJlIG9wZW5lZFwiLCBlcnIpO1xuICAgICAgdGhpcy5lbWl0KG51bGwpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoZ2VuZXJhdGlvbiAhPT0gdGhpcy5nZW5lcmF0aW9uKSByZXR1cm47XG4gICAgaWYgKCF0aGlzLmNodW5rcy5sZW5ndGgpIHRoaXMuY2h1bmtzID0gbWFrZUNodW5rcyhzb3VyY2UpO1xuICAgIGNvbnN0IHN0ZXBzID0gdGhpcy5zdGVwcyhkYXRhc2V0KTtcbiAgICB0aGlzLnJlcGxhblRpZXJzKHN0ZXBzKTtcbiAgICB0aGlzLnJlcG9ydChmYWxzZSk7XG4gICAgaWYgKCF0aGlzLnJ1bm5pbmcpIHZvaWQgdGhpcy5ydW4oc291cmNlLCBpbmRleCwgc3RlcHMpO1xuICB9XG5cbiAgLyoqIHtAbGluayBhc3NpZ25UaWVyc30gZnJvbSB0aGUgdmlldyBhcyBpdCBpcyBub3csIHRha2luZyBkb3duIHdoYXQgaXQgbGVhdmVzIG91dC4gKi9cbiAgcHJpdmF0ZSByZXBsYW5UaWVycyhzdGVwczogbnVtYmVyW10pOiB2b2lkIHtcbiAgICB0aGlzLmFzc2lnblRpZXJzKHRoaXMucHJpb3JpdHkoKSwgc3RlcHMpO1xuICAgIGZvciAoY29uc3QgYyBvZiB0aGlzLmNodW5rcykgaWYgKGMud2FudCA8IDApIHRoaXMuZHJvcExheWVyKGMpO1xuICB9XG5cbiAgLyoqIFZveGVsIGVkZ2Ugb2YgZWFjaCB0aWVyLCBpbWFnZSBweDogZnJhY3Rpb25zIG9mIGEgdHlwaWNhbCBjZWxsJ3MgZGlhbWV0ZXIuICovXG4gIHByaXZhdGUgc3RlcHMoZGF0YXNldDogU3BhdGlhbERhdGFzZXQpOiBudW1iZXJbXSB7XG4gICAgY29uc3Qgc3ggPSBkYXRhc2V0LmltYWdlUmVmPy5zY2FsZT8uWzBdID8/IDE7XG4gICAgY29uc3QgZCA9IE1hdGgubWF4KDQsIHR5cGljYWxDZWxsRGlhbWV0ZXIoZGF0YXNldC5vYnNlcnZhdGlvbnMucmFkaXVzKSAqIE1hdGguYWJzKHN4IHx8IDEpKTtcbiAgICByZXR1cm4gVElFUl9GUkFDVElPTlMubWFwKChmKSA9PiBNYXRoLm1heCgxLCBkICogZikpO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBjaHVua3MsIG5lYXJlc3QgdGhlIGNlbnRyZSBvZiB0aGUgdmlldyBmaXJzdCwgd2l0aCBob3cgbWFueSBzY3JlZW4gcGl4ZWxzIGFuIGltYWdlIHBpeGVsXG4gICAqIG9mIGVhY2ggdGFrZXMgKDAgb2ZmIHNjcmVlbikuXG4gICAqL1xuICBwcml2YXRlIHByaW9yaXR5KCk6IHsgY2h1bms6IENodW5rOyBwcGk6IG51bWJlcjsgb25TY3JlZW46IGJvb2xlYW47IGQyOiBudW1iZXIgfVtdIHtcbiAgICBjb25zdCB2aWV3ZXIgPSB0aGlzLmhvc3Qudmlld2VyO1xuICAgIGNvbnN0IFt2dywgdmhdID0gdmlld2VyLnZpZXdwb3J0U2l6ZSgpO1xuICAgIGNvbnN0IHB0cyA9IG5ldyBGbG9hdDMyQXJyYXkodGhpcy5jaHVua3MubGVuZ3RoICogNik7XG4gICAgY29uc3Qgek1pZCA9IHRoaXMucGxhY2VtZW50ID8gbWlkWih0aGlzLnBsYWNlbWVudCkgOiAwO1xuICAgIHRoaXMuY2h1bmtzLmZvckVhY2goKGMsIGkpID0+IHtcbiAgICAgIGNvbnN0IFt4MCwgeTAsIHgxLCB5MV0gPSBjLmJveDtcbiAgICAgIGNvbnN0IGN5ID0gKHkwICsgeTEpIC8gMjtcbiAgICAgIGNvbnN0IGEgPSB0aGlzLnRvV29ybGRQb2ludCgoeDAgKyB4MSkgLyAyLCBjeSwgek1pZCk7XG4gICAgICBjb25zdCBiID0gdGhpcy50b1dvcmxkUG9pbnQoeDEsIGN5LCB6TWlkKTtcbiAgICAgIHB0cy5zZXQoYSwgaSAqIDYpO1xuICAgICAgcHRzLnNldChiLCBpICogNiArIDMpO1xuICAgIH0pO1xuICAgIGNvbnN0IHByb2ogPSB2dyA+IDAgJiYgdmggPiAwID8gdmlld2VyLnByb2plY3RQb2ludHMocHRzKSA6IG51bGw7XG4gICAgY29uc3Qgb3V0ID0gdGhpcy5jaHVua3MubWFwKChjaHVuaywgaSkgPT4ge1xuICAgICAgY29uc3Qgc3ggPSBwcm9qPy5zY3JlZW5baSAqIDRdID8/IE5hTjtcbiAgICAgIGNvbnN0IHN5ID0gcHJvaj8uc2NyZWVuW2kgKiA0ICsgMV0gPz8gTmFOO1xuICAgICAgY29uc3QgZXggPSBwcm9qPy5zY3JlZW5baSAqIDQgKyAyXSA/PyBOYU47XG4gICAgICBjb25zdCBleSA9IHByb2o/LnNjcmVlbltpICogNCArIDNdID8/IE5hTjtcbiAgICAgIGNvbnN0IGhhbGYgPSBNYXRoLmh5cG90KGV4IC0gc3gsIGV5IC0gc3kpO1xuICAgICAgY29uc3Qgd2lkdGggPSAoY2h1bmsuYm94WzJdIC0gY2h1bmsuYm94WzBdKSAvIDI7XG4gICAgICBjb25zdCBwcGkgPSBOdW1iZXIuaXNGaW5pdGUoaGFsZikgJiYgd2lkdGggPiAwID8gaGFsZiAvIHdpZHRoIDogMDtcbiAgICAgIGNvbnN0IG9uU2NyZWVuID1cbiAgICAgICAgTnVtYmVyLmlzRmluaXRlKHN4KSAmJiBzeCA+IC1oYWxmICYmIHN4IDwgdncgKyBoYWxmICYmIHN5ID4gLWhhbGYgJiYgc3kgPCB2aCArIGhhbGYgJiYgcHBpID4gMDtcbiAgICAgIGNvbnN0IGQyID0gTnVtYmVyLmlzRmluaXRlKHN4KSA/IChzeCAtIHZ3IC8gMikgKiogMiArIChzeSAtIHZoIC8gMikgKiogMiA6IE51bWJlci5NQVhfVkFMVUU7XG4gICAgICByZXR1cm4geyBjaHVuaywgcHBpOiBvblNjcmVlbiA/IHBwaSA6IDAsIG9uU2NyZWVuLCBkMiB9O1xuICAgIH0pO1xuICAgIHJldHVybiBvdXQuc29ydCgoYSwgYikgPT4gTnVtYmVyKGIub25TY3JlZW4pIC0gTnVtYmVyKGEub25TY3JlZW4pIHx8IGEuZDIgLSBiLmQyKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFYWNoIGNodW5rJ3MgdGllcjogaW4gb3JkZXIsIHdpdGhpbiB0aGUgY2VsbCBjYXAsIGFzIGZpbmUgYXMgdGhlIHNjcmVlbiBhc2tzIHdpdGhpbiB0aGVcbiAgICogdHJpYW5nbGUgYnVkZ2V0LiBUaGUgY2h1bmtzIGxhc3QgaW4gb3JkZXIgZ2l2ZSB1cCB0aGVpciBkZXRhaWwgZmlyc3QsIHRoZW4gYXJlIGxlZnQgb3V0OyB0aGVcbiAgICogZmlyc3QgaXMgbmV2ZXIgbGVmdCBvdXQsIGJ1dCBvbmUgb3ZlciB0aGUgY2FwIG9yIHRoZSBidWRnZXQgYnkgaXRzZWxmIG1lc2hlcyBvbmx5IHRoZSBjZWxsc1xuICAgKiB0aGF0IGZpdCAoaXRzIHtAbGluayBDaHVuay5saW1pdH0pLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3NpZ25UaWVycyhvcmRlcjogeyBjaHVuazogQ2h1bms7IHBwaTogbnVtYmVyIH1bXSwgc3RlcHM6IG51bWJlcltdKTogdm9pZCB7XG4gICAgY29uc3Qga25vd24gPSB0aGlzLmNodW5rcy5maWx0ZXIoKGMpID0+IGMuY2VsbHMgPj0gMCk7XG4gICAgY29uc3QgYXZnQ2VsbHMgPSBrbm93bi5sZW5ndGggPyBrbm93bi5yZWR1Y2UoKHMsIGMpID0+IHMgKyBjLmNlbGxzLCAwKSAvIGtub3duLmxlbmd0aCA6IDIwMDtcbiAgICBsZXQgY2VsbHMgPSAwO1xuICAgIGNvbnN0IGluY2x1ZGVkOiB7IGNodW5rOiBDaHVuazsgdGllcjogbnVtYmVyOyB0YWtlOiBudW1iZXI7IHJvb206IG51bWJlciB9W10gPSBbXTtcbiAgICBmb3IgKGNvbnN0IHsgY2h1bmssIHBwaSB9IG9mIG9yZGVyKSB7XG4gICAgICBjb25zdCBuID0gY2h1bmsuY2VsbHMgPj0gMCA/IGNodW5rLmNlbGxzIDogYXZnQ2VsbHM7XG4gICAgICBjb25zdCByb29tID0gQ0VMTFNfM0RfTUFYX0NFTExTIC0gY2VsbHM7XG4gICAgICBpZiAobiA+IHJvb20gJiYgaW5jbHVkZWQubGVuZ3RoKSB7XG4gICAgICAgIGNodW5rLndhbnQgPSAtMTtcbiAgICAgICAgY29udGludWU7XG4gICAgICB9XG4gICAgICBjb25zdCB0YWtlID0gTWF0aC5taW4obiwgcm9vbSk7XG4gICAgICBjZWxscyArPSB0YWtlO1xuICAgICAgbGV0IHRpZXIgPSAwO1xuICAgICAgZm9yIChsZXQgdCA9IHN0ZXBzLmxlbmd0aCAtIDE7IHQgPiAwOyB0LS0pIHtcbiAgICAgICAgaWYgKHBwaSAqIHN0ZXBzW3RdID49IE1JTl9WT1hFTF9QWCkge1xuICAgICAgICAgIHRpZXIgPSB0O1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICBpbmNsdWRlZC5wdXNoKHsgY2h1bmssIHRpZXIsIHRha2UsIHJvb20gfSk7XG4gICAgfVxuICAgIGNvbnN0IHRyaWFuZ2xlcyA9IChlOiB7IGNodW5rOiBDaHVuazsgdGllcjogbnVtYmVyIH0pID0+IHRoaXMudHJpYW5nbGVzQXQoZS5jaHVuaywgZS50aWVyLCBzdGVwcywgYXZnQ2VsbHMpO1xuICAgIC8vIFRoZSBidWRnZXQ6IHRoZSBjaHVua3MgbGFzdCBpbiBvcmRlciBnaXZlIHVwIHRoZWlyIGRldGFpbCBmaXJzdCwgdGhlbiB0aGVpciBwbGFjZS5cbiAgICBsZXQgdG90YWwgPSBpbmNsdWRlZC5yZWR1Y2UoKHMsIGUpID0+IHMgKyB0cmlhbmdsZXMoZSksIDApO1xuICAgIGZvciAobGV0IGkgPSBpbmNsdWRlZC5sZW5ndGggLSAxOyBpID49IDAgJiYgdG90YWwgPiBDRUxMU18zRF9UUklBTkdMRV9CVURHRVQ7IGktLSkge1xuICAgICAgY29uc3QgZSA9IGluY2x1ZGVkW2ldO1xuICAgICAgd2hpbGUgKGUudGllciA+IDAgJiYgdG90YWwgPiBDRUxMU18zRF9UUklBTkdMRV9CVURHRVQpIHtcbiAgICAgICAgdG90YWwgLT0gdHJpYW5nbGVzKGUpIC0gdHJpYW5nbGVzKHsgY2h1bms6IGUuY2h1bmssIHRpZXI6IGUudGllciAtIDEgfSk7XG4gICAgICAgIGUudGllci0tO1xuICAgICAgfVxuICAgIH1cbiAgICB3aGlsZSAoaW5jbHVkZWQubGVuZ3RoID4gMSAmJiB0b3RhbCA+IENFTExTXzNEX1RSSUFOR0xFX0JVREdFVCkge1xuICAgICAgY29uc3QgZSA9IGluY2x1ZGVkLnBvcCgpITtcbiAgICAgIHRvdGFsIC09IHRyaWFuZ2xlcyhlKTtcbiAgICAgIGUuY2h1bmsud2FudCA9IC0xO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGUgb2YgaW5jbHVkZWQpIHtcbiAgICAgIGNvbnN0IG4gPSBlLmNodW5rLmNlbGxzID49IDAgPyBlLmNodW5rLmNlbGxzIDogYXZnQ2VsbHM7XG4gICAgICBsZXQgdGFrZSA9IGUudGFrZTtcbiAgICAgIC8vIFRoZSBmaXJzdCBjaHVuayBhbG9uZSBvdmVyIHRoZSBidWRnZXQsIGF0IGl0cyBjb2Fyc2VzdDogYXMgbWFueSBjZWxscyBhcyBmaXQgaW4gaXQuXG4gICAgICBjb25zdCBhbGwgPSB0cmlhbmdsZXMoZSk7XG4gICAgICBpZiAoYWxsID4gQ0VMTFNfM0RfVFJJQU5HTEVfQlVER0VUKSB7XG4gICAgICAgIGNvbnN0IHBlckNlbGwgPSBhbGwgLyBNYXRoLm1heCgxLCBlLmNodW5rLm1lc2hlZCA+IDAgPyBlLmNodW5rLm1lc2hlZCA6IG4pO1xuICAgICAgICB0YWtlID0gTWF0aC5taW4odGFrZSwgQ0VMTFNfM0RfVFJJQU5HTEVfQlVER0VUIC8gcGVyQ2VsbCk7XG4gICAgICB9XG4gICAgICBlLmNodW5rLndhbnQgPSBlLnRpZXI7XG4gICAgICAvLyBDdXQgc2hvcnQgd2hlbiBvdmVyOyBhbmQgb25lIG5vdCBidWlsdCB5ZXQsIHdoaWNoIG1heSBoYXZlIG1vcmUgY2VsbHMgdGhhbiB0aGUgZ3Vlc3MsIHRvXG4gICAgICAvLyB0aGUgcm9vbSB0aGUgY2FwIGxlYXZlcyBpdC5cbiAgICAgIGNvbnN0IG1vc3QgPSB0YWtlIDwgbiA/IHRha2UgOiBlLmNodW5rLmNlbGxzIDwgMCA/IGUucm9vbSA6IEluZmluaXR5O1xuICAgICAgZS5jaHVuay5saW1pdCA9IE51bWJlci5pc0Zpbml0ZShtb3N0KSA/IE1hdGgubWF4KDEsIE1hdGguZmxvb3IobW9zdCkpIDogSW5maW5pdHk7XG4gICAgfVxuICB9XG5cbiAgLyoqIEEgY2h1bmsncyB0cmlhbmdsZXMgYXQgYHRpZXJgOiBhcyBidWlsdCwgZWxzZSBzY2FsZWQgZnJvbSBhIHRpZXIgYnVpbHQgKGJ5IHRoZSBzdGVwJ3Mgc3F1YXJlKS4gKi9cbiAgcHJpdmF0ZSB0cmlhbmdsZXNBdChjaHVuazogQ2h1bmssIHRpZXI6IG51bWJlciwgc3RlcHM6IG51bWJlcltdLCBhdmdDZWxsczogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBjb25zdCBhdCA9IGNodW5rLnRyaWFuZ2xlcy5nZXQodGllcik7XG4gICAgaWYgKGF0ICE9PSB1bmRlZmluZWQpIHJldHVybiBhdDtcbiAgICBmb3IgKGNvbnN0IFt0LCBuXSBvZiBjaHVuay50cmlhbmdsZXMpIHJldHVybiBuICogKHN0ZXBzW3RdIC8gc3RlcHNbdGllcl0pICoqIDI7XG4gICAgY29uc3QgY2VsbHMgPSBjaHVuay5jZWxscyA+PSAwID8gY2h1bmsuY2VsbHMgOiBhdmdDZWxscztcbiAgICByZXR1cm4gY2VsbHMgKiBDT0FSU0VfVFJJQU5HTEVTX1BFUl9DRUxMICogKHN0ZXBzWzBdIC8gc3RlcHNbdGllcl0pICoqIDI7XG4gIH1cblxuICAvLyDilIDilIAgYnVpbGRpbmcg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgLyoqIEJ1aWxkIGV2ZXJ5IGNodW5rIHdob3NlIHRpZXIgY2hhbmdlZCwgbmVhcmVzdCBmaXJzdCwgb25lIGF0IGEgdGltZSwgdW50aWwgbm9uZSBpcyBsZWZ0LiAqL1xuICBwcml2YXRlIGFzeW5jIHJ1bihzb3VyY2U6IFJlZ2lvblNvdXJjZSwgaW5kZXg6IFJlYWRvbmx5TWFwPHN0cmluZywgbnVtYmVyPiwgc3RlcHM6IG51bWJlcltdKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5ydW5uaW5nID0gdHJ1ZTtcbiAgICBsZXQgc3RhbGUgPSBmYWxzZTtcbiAgICBjb25zdCBlbmQgPSB0aGlzLmhvc3QuYmVnaW5UYXNrKCdDZWxscycpO1xuICAgIHRyeSB7XG4gICAgICBmb3IgKDs7KSB7XG4gICAgICAgIGNvbnN0IGdlbmVyYXRpb24gPSB0aGlzLmdlbmVyYXRpb247XG4gICAgICAgIGNvbnN0IG5leHQgPSB0aGlzLnByaW9yaXR5KClcbiAgICAgICAgICAubWFwKChlKSA9PiBlLmNodW5rKVxuICAgICAgICAgIC5maW5kKChjKSA9PiBuZWVkc0J1aWxkKGMpKTtcbiAgICAgICAgaWYgKCFuZXh0KSBicmVhaztcbiAgICAgICAgdGhpcy5yZXBvcnQodHJ1ZSk7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgdGhpcy5idWlsZChuZXh0LCBuZXh0LndhbnQsIHNvdXJjZSwgaW5kZXgsIHN0ZXBzLCBnZW5lcmF0aW9uKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgY29uc29sZS53YXJuKCdbbmFwYXJpLWpzXSBjZWxscyBjb3VsZCBub3QgYmUgYnVpbHQgaW4gM0QnLCBlcnIpO1xuICAgICAgICAgIG5leHQud2FudCA9IG5leHQudGllcjsgLy8gbm90IHJldHJpZWQgdW50aWwgdGhlIHZpZXcgYXNrcyBhZ2FpblxuICAgICAgICB9XG4gICAgICAgIGlmIChnZW5lcmF0aW9uICE9PSB0aGlzLmdlbmVyYXRpb24pIHtcbiAgICAgICAgICAvLyBTdXBlcnNlZGVkIChvdGhlciBjbGFzc2VzLCBhbm90aGVyIGRhdGFzZXQpOiB0aGUgcGxhbiBtYWRlIGZvciB0aG9zZSBmb3VuZCB0aGlzIHJ1blxuICAgICAgICAgIC8vIHN0aWxsIGdvaW5nIGFuZCBzdGFydGVkIG5vbmUgb2YgaXRzIG93bi4gUGxhbiBhZ2Fpbiwgbm93IHRoYXQgaXQgaGFzIHN0b3BwZWQuXG4gICAgICAgICAgc3RhbGUgPSB0cnVlO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIC8vIFRoZSBjaHVuaydzIHJlYWwgc2l6ZSBpcyBrbm93biBub3csIHdoZXJlIHRoZSBwbGFuIGd1ZXNzZWQ6IHBsYW4gYWdhaW4gYnkgaXQuXG4gICAgICAgIHRoaXMucmVwbGFuVGllcnMoc3RlcHMpO1xuICAgICAgfVxuICAgIH0gZmluYWxseSB7XG4gICAgICBlbmQoKTtcbiAgICAgIHRoaXMucnVubmluZyA9IGZhbHNlO1xuICAgICAgdGhpcy5yZXBvcnQoZmFsc2UpO1xuICAgICAgaWYgKHN0YWxlKSB0aGlzLnNjaGVkdWxlKDApO1xuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYnVpbGQoXG4gICAgY2h1bms6IENodW5rLFxuICAgIHRpZXI6IG51bWJlcixcbiAgICBzb3VyY2U6IFJlZ2lvblNvdXJjZSxcbiAgICBpbmRleDogUmVhZG9ubHlNYXA8c3RyaW5nLCBudW1iZXI+LFxuICAgIHN0ZXBzOiBudW1iZXJbXSxcbiAgICBnZW5lcmF0aW9uOiBudW1iZXIsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGluZm8gPSBzb3VyY2UuaW5mbztcbiAgICBjb25zdCBzdGVwID0gc3RlcHNbdGllcl07XG4gICAgY29uc3QgbGV2ZWwgPSBNYXRoLm1heCgwLCBNYXRoLm1pbihpbmZvLmxldmVscyAtIDEsIE1hdGguZmxvb3IoTWF0aC5sb2cyKHN0ZXApKSkpO1xuICAgIC8vIFRpbGVzIGFyb3VuZCB0aGUgY2h1bms6IGEgY2VsbCBjcm9zc2luZyBpdHMgZWRnZSBpcyB0aGUgY2h1bmsncyBpdHMgY2VudHJlIGlzIGluLlxuICAgIGNvbnN0IG1hcmdpbiA9IHN0ZXBzWzBdICogODtcbiAgICBjb25zdCBbeDAsIHkwLCB4MSwgeTFdID0gY2h1bmsuYm94O1xuICAgIGNvbnN0IGtleXMgPSByZWdpb25UaWxlc0luUmVjdChcbiAgICAgIFt4MCAtIG1hcmdpbiwgeTAgLSBtYXJnaW4sIHgxICsgbWFyZ2luLCB5MSArIG1hcmdpbl0sXG4gICAgICBsZXZlbCxcbiAgICAgIGluZm8udGlsZVNpemUsXG4gICAgICBpbmZvLmJvdW5kcyxcbiAgICApO1xuICAgIGNvbnN0IHBsYW5lcyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgaW5mby5wbGFuZXMubWFwKGFzeW5jICh6LCBzbGljZSkgPT4gKHtcbiAgICAgICAgc2xpY2UsXG4gICAgICAgIHRpbGVzOiBhd2FpdCBQcm9taXNlLmFsbChrZXlzLm1hcCgoaykgPT4gc291cmNlLmdldFRpbGUoeiwgaykpKSxcbiAgICAgIH0pKSxcbiAgICApO1xuICAgIGlmIChnZW5lcmF0aW9uICE9PSB0aGlzLmdlbmVyYXRpb24pIHJldHVybjtcbiAgICBjb25zdCBmb3VuZCA9IGNlbGxPdXRsaW5lc0Zyb21UaWxlcyhwbGFuZXMsIGluZGV4LCB0aGlzLmNsYXNzZXMsIGNodW5rLmJveCk7XG4gICAgY29uc3QgbGltaXQgPSBjaHVuay5saW1pdDtcbiAgICBjb25zdCBjZWxscyA9IGZvdW5kLmxlbmd0aCA+IGxpbWl0ID8gZm91bmQuc2xpY2UoMCwgbGltaXQpIDogZm91bmQ7XG4gICAgY29uc3QgbGFiZWxzID0gbmV3IE1hcChjZWxscy5tYXAoKGMpID0+IFtjLmNlbGwsIGMubGFiZWxdIGFzIFtudW1iZXIsIHN0cmluZyB8IG51bGxdKSk7XG4gICAgY29uc3QgcGFydHM6IENlbGxzTWVzaFtdID0gW107XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjZWxscy5sZW5ndGg7IGkgKz0gQkFUQ0gpIHtcbiAgICAgIGNvbnN0IGJhdGNoID0gY2VsbHMuc2xpY2UoaSwgaSArIEJBVENIKS5tYXAoKGMpID0+ICh7IGNlbGw6IGMuY2VsbCwgc2xpY2VzOiBjLnNsaWNlcyB9KSk7XG4gICAgICBwYXJ0cy5wdXNoKGF3YWl0IHJlY29uc3RydWN0Q2VsbHNJbldvcmtlcihiYXRjaCwgeyBwaXhlbFN0ZXA6IHN0ZXAgfSkpO1xuICAgICAgaWYgKGdlbmVyYXRpb24gIT09IHRoaXMuZ2VuZXJhdGlvbikgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBtZXNoID0gY29uY2F0TWVzaGVzKHBhcnRzKTtcbiAgICBjaHVuay5tZXNoID0gbWVzaDtcbiAgICBjaHVuay5sYWJlbHMgPSBsYWJlbHM7XG4gICAgY2h1bmsudGllciA9IHRpZXI7XG4gICAgY2h1bmsuY2VsbHMgPSBmb3VuZC5sZW5ndGg7XG4gICAgY2h1bmsubWVzaGVkID0gbWVzaC5jZWxscy5sZW5ndGg7XG4gICAgY2h1bmsuYnVpbHRMaW1pdCA9IGxpbWl0O1xuICAgIGNodW5rLnRyaWFuZ2xlcy5zZXQodGllciwgbWVzaC5mYWNlcy5sZW5ndGggLyAzKTtcbiAgICBjaHVuay53b3JsZCA9IG51bGw7XG4gICAgdGhpcy5kcmF3KGNodW5rKTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBkcmF3aW5nIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIC8qKlxuICAgKiBEcmF3IGV2ZXJ5IGNodW5rIGFnYWluIChhIHJlY29sb3VyLCBhIGhpZGRlbiBjbGFzcywgYSBzZWxlY3Rpb24pOiBhIGZldyBhdCBhIHRpbWUsIHlpZWxkaW5nIHRoZVxuICAgKiBtYWluIHRocmVhZCBiZXR3ZWVuIHRoZW0gc28gdGhhdCBhIGNsaWNrIHNlbGVjdGluZyBhIGNlbGwgbmV2ZXIgaG9sZHMgYSBmcmFtZTsgYSBuZXdlciByZWRyYXdcbiAgICogdGFrZXMgb3ZlciBmcm9tIHRoaXMgb25lLlxuICAgKi9cbiAgcHJpdmF0ZSByZWRyYXcoKTogdm9pZCB7XG4gICAgY29uc3QgZ2VuZXJhdGlvbiA9ICsrdGhpcy5yZWRyYXdHZW5lcmF0aW9uO1xuICAgIGNvbnN0IGNodW5rcyA9IHRoaXMuY2h1bmtzLmZpbHRlcigoYykgPT4gYy5tZXNoKTtcbiAgICB2b2lkIChhc3luYyAoKSA9PiB7XG4gICAgICBsZXQgc3RhcnQgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgIGZvciAoY29uc3QgYyBvZiBjaHVua3MpIHtcbiAgICAgICAgaWYgKGdlbmVyYXRpb24gIT09IHRoaXMucmVkcmF3R2VuZXJhdGlvbikgcmV0dXJuO1xuICAgICAgICB0aGlzLmRyYXcoYyk7XG4gICAgICAgIGlmIChwZXJmb3JtYW5jZS5ub3coKSAtIHN0YXJ0ID4gUkVEUkFXX1NMSUNFX01TKSB7XG4gICAgICAgICAgdGhpcy5ob3N0LnZpZXdlci5yZXF1ZXN0UmVuZGVyKCk7XG4gICAgICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHIpID0+IHNldFRpbWVvdXQocikpO1xuICAgICAgICAgIHN0YXJ0ID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHRoaXMuaG9zdC52aWV3ZXIucmVxdWVzdFJlbmRlcigpO1xuICAgIH0pKCk7XG4gIH1cbiAgcHJpdmF0ZSByZWRyYXdHZW5lcmF0aW9uID0gMDtcblxuICAvKiogUGxhY2UgYSBjaHVuaydzIHZlcnRpY2VzIGluIHRoZSB3b3JsZCwgaW4gdGhlIGNlbGxzJyB3b3JrZXIsIHRoZW4gZHJhdyBpdCAodW5sZXNzIHN1cGVyc2VkZWQpLiAqL1xuICBwcml2YXRlIHBsYWNlQ2h1bmsoY2h1bms6IENodW5rLCBwbGFjZW1lbnQ6IFBsYW5lUGxhY2VtZW50KTogdm9pZCB7XG4gICAgY29uc3QgbWVzaCA9IGNodW5rLm1lc2g7XG4gICAgaWYgKCFtZXNoIHx8IChjaHVuay5wbGFjaW5nPy5tZXNoID09PSBtZXNoICYmIGNodW5rLnBsYWNpbmcucGxhY2VtZW50ID09PSBwbGFjZW1lbnQpKSByZXR1cm47XG4gICAgLy8gVGhpcyByZXF1ZXN0J3Mgb3duIHRva2VuOiBvbmUgc3VwZXJzZWRlZCAoYW5vdGhlciBtZXNoLCBvciBwbGFjZW1lbnQpIGlzIGRyb3BwZWQgd2hlbiBpdFxuICAgIC8vIGxhbmRzLCB3aXRob3V0IGRyb3BwaW5nIHRoZSByZXF1ZXN0IHRoYXQgcmVwbGFjZWQgaXQuXG4gICAgY29uc3QgcGxhY2luZyA9IHsgbWVzaCwgcGxhY2VtZW50IH07XG4gICAgY2h1bmsucGxhY2luZyA9IHBsYWNpbmc7XG4gICAgcGxhY2VJbldvcmtlcihtZXNoLnZlcnRpY2VzLCB7IHNpemU6IFsxLCAxLCAxXSwgd29ybGQ6IFsxLCAxLCAxXSwgcGxhbmVzOiBwbGFjZW1lbnQgfSkudGhlbihcbiAgICAgICh3b3JsZCkgPT4ge1xuICAgICAgICBpZiAoY2h1bmsucGxhY2luZyAhPT0gcGxhY2luZykgcmV0dXJuO1xuICAgICAgICBjaHVuay5wbGFjaW5nID0gbnVsbDtcbiAgICAgICAgaWYgKGNodW5rLm1lc2ggIT09IG1lc2ggfHwgdGhpcy5wbGFjZW1lbnQgIT09IHBsYWNlbWVudCkgcmV0dXJuO1xuICAgICAgICBjaHVuay53b3JsZCA9IHdvcmxkO1xuICAgICAgICB0aGlzLmRyYXcoY2h1bmspO1xuICAgICAgICB0aGlzLmhvc3Qudmlld2VyLnJlcXVlc3RSZW5kZXIoKTtcbiAgICAgIH0sXG4gICAgICAoZXJyKSA9PiB7XG4gICAgICAgIGlmIChjaHVuay5wbGFjaW5nID09PSBwbGFjaW5nKSBjaHVuay5wbGFjaW5nID0gbnVsbDtcbiAgICAgICAgY29uc29sZS53YXJuKCdbbmFwYXJpLWpzXSBjZWxscyBjb3VsZCBub3QgYmUgcGxhY2VkIGluIDNEJywgZXJyKTtcbiAgICAgIH0sXG4gICAgKTtcbiAgfVxuXG4gIC8qKiBEcmF3IGEgY2h1bmsncyB2aXNpYmxlIGNlbGxzLCBpbiB0aGVpciBjb2xvdXJzOiBpdHMgbGF5ZXIgdXBkYXRlZCBpbiBwbGFjZSwgb3IgYWRkZWQuICovXG4gIHByaXZhdGUgZHJhdyhjaHVuazogQ2h1bmspOiB2b2lkIHtcbiAgICBjb25zdCBtZXNoID0gY2h1bmsubWVzaDtcbiAgICBjb25zdCBwbGFjZW1lbnQgPSB0aGlzLnBsYWNlbWVudDtcbiAgICBpZiAoIW1lc2ggfHwgIXBsYWNlbWVudCB8fCBjaHVuay53YW50IDwgMCkge1xuICAgICAgdGhpcy5kcm9wTGF5ZXIoY2h1bmspO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAoIWNodW5rLndvcmxkKSB7XG4gICAgICAvLyBQbGFjZWQgb2ZmIHRoZSBtYWluIHRocmVhZDsgZHJhd24gd2hlbiBpdCBsYW5kcy5cbiAgICAgIHRoaXMucGxhY2VDaHVuayhjaHVuaywgcGxhY2VtZW50KTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgdmlzaWJsZSA9IHRoaXMudmlzaWJsZUZhY2VzKGNodW5rKTtcbiAgICAvLyBXaXRoIGEgc2VsZWN0aW9uLCBpdHMgY2VsbHMgaW4gYSBzdXJmYWNlIG9mIHRoZWlyIG93biAoc2VlIENodW5rLnNlbGVjdGVkTGF5ZXIpLlxuICAgIGNvbnN0IFtzZWxlY3RlZCwgcmVzdF0gPSB0aGlzLnNlbGVjdGVkXG4gICAgICA/IHNwbGl0RmFjZXModmlzaWJsZSwgbWVzaC52ZXJ0ZXhDZWxsLCB0aGlzLnNlbGVjdGVkKVxuICAgICAgOiBbbmV3IFVpbnQzMkFycmF5KDApLCB2aXNpYmxlXTtcbiAgICBjaHVuay5kcmF3biA9IHJlc3Q7XG4gICAgY2h1bmsuZHJhd25TZWxlY3RlZCA9IHNlbGVjdGVkO1xuICAgIGNodW5rLmxheWVyID0gdGhpcy5kcmF3U3VyZmFjZShjaHVuaywgY2h1bmsubGF5ZXIsIHJlc3QsIHRoaXMudmVydGV4Q29sb3JzKG1lc2gpLCB0aGlzLm9wYWNpdHksICdjZWxscycpO1xuICAgIGNodW5rLnNlbGVjdGVkTGF5ZXIgPSB0aGlzLmRyYXdTdXJmYWNlKFxuICAgICAgY2h1bmssXG4gICAgICBjaHVuay5zZWxlY3RlZExheWVyLFxuICAgICAgc2VsZWN0ZWQsXG4gICAgICBzZWxlY3RlZC5sZW5ndGggPyB0aGlzLnZlcnRleENvbG9ycyhtZXNoLCB0cnVlKSA6IG51bGwsXG4gICAgICAxLFxuICAgICAgJ3NlbGVjdGVkIGNlbGxzJyxcbiAgICApO1xuICB9XG5cbiAgLyoqXG4gICAqIE9uZSBvZiBhIGNodW5rJ3Mgc3VyZmFjZXMgd2l0aCB0aGVzZSB0cmlhbmdsZXMgYW5kIGNvbG91cnM6IHVwZGF0ZWQgaW4gcGxhY2UsIGFkZGVkLCBvciBoaWRkZW5cbiAgICogd2hlbiBpdCBoYXMgbm9uZS4gUmV0dXJucyB0aGUgbGF5ZXIgKG51bGw6IG5vbmUgd2FzIGV2ZXIgbmVlZGVkKS5cbiAgICovXG4gIHByaXZhdGUgZHJhd1N1cmZhY2UoXG4gICAgY2h1bms6IENodW5rLFxuICAgIGxheWVyOiBTdXJmYWNlTGF5ZXIgfCBudWxsLFxuICAgIGZhY2VzOiBVaW50MzJBcnJheSxcbiAgICBjb2xvcnM6IEZsb2F0MzJBcnJheSB8IG51bGwsXG4gICAgb3BhY2l0eTogbnVtYmVyLFxuICAgIG5hbWU6IHN0cmluZyxcbiAgKTogU3VyZmFjZUxheWVyIHwgbnVsbCB7XG4gICAgaWYgKCFmYWNlcy5sZW5ndGggfHwgIWNvbG9ycyB8fCAhY2h1bmsud29ybGQpIHtcbiAgICAgIGlmIChsYXllcikgbGF5ZXIudmlzaWJsZSA9IGZhbHNlO1xuICAgICAgcmV0dXJuIGxheWVyO1xuICAgIH1cbiAgICBpZiAobGF5ZXIpIHtcbiAgICAgIC8vIEEgcmVjb2xvdXIsIGEgbmV3IG9wYWNpdHk6IHRoZSBnZW9tZXRyeSBzdGF5cyBhcyB1cGxvYWRlZC5cbiAgICAgIGNvbnN0IGhhZCA9IHRoaXMuaW5zdGFsbGVkLmdldChsYXllcik7XG4gICAgICBpZiAoIWhhZCB8fCBoYWQud29ybGQgIT09IGNodW5rLndvcmxkIHx8ICFzYW1lRmFjZXMoaGFkLmZhY2VzLCBmYWNlcykpIHtcbiAgICAgICAgbGF5ZXIuc2V0RGF0YShjaHVuay53b3JsZCwgZmFjZXMpO1xuICAgICAgICB0aGlzLmluc3RhbGxlZC5zZXQobGF5ZXIsIHsgd29ybGQ6IGNodW5rLndvcmxkLCBmYWNlcyB9KTtcbiAgICAgIH1cbiAgICAgIGxheWVyLnZlcnRleENvbG9ycyA9IGNvbG9ycztcbiAgICAgIGxheWVyLm9wYWNpdHkgPSBvcGFjaXR5O1xuICAgICAgbGF5ZXIudmlzaWJsZSA9IHRydWU7XG4gICAgICByZXR1cm4gbGF5ZXI7XG4gICAgfVxuICAgIGNvbnN0IGFkZGVkID0gdGhpcy5ob3N0LnZpZXdlci5hZGRTdXJmYWNlKGNodW5rLndvcmxkLCBmYWNlcywgdW5kZWZpbmVkLCB7XG4gICAgICBuYW1lOiBgJHtuYW1lfSAke2NodW5rLmtleX1gLFxuICAgICAgdmVydGV4Q29sb3JzOiBjb2xvcnMsXG4gICAgICBvcGFjaXR5LFxuICAgICAgYmxlbmRpbmc6ICd0cmFuc2x1Y2VudCcsXG4gICAgICBzY2FsZTNkOiBbMSwgMSwgdGhpcy56U2NhbGVdLFxuICAgICAgZml0OiAnbmV2ZXInLFxuICAgIH0pO1xuICAgIHRoaXMuYnlMYXllci5zZXQoYWRkZWQsIGNodW5rKTtcbiAgICB0aGlzLmluc3RhbGxlZC5zZXQoYWRkZWQsIHsgd29ybGQ6IGNodW5rLndvcmxkLCBmYWNlcyB9KTtcbiAgICByZXR1cm4gYWRkZWQ7XG4gIH1cblxuICAvKiogVGhlIHRyaWFuZ2xlcyBvZiB0aGUgY2VsbHMgc2hvd246IHRoZWlyIGNsYXNzIG5vdCBoaWRkZW4sIHRoZSBvYnNlcnZhdGlvbiBzaG93bi4gKi9cbiAgcHJpdmF0ZSB2aXNpYmxlRmFjZXMoY2h1bms6IENodW5rKTogVWludDMyQXJyYXkge1xuICAgIGNvbnN0IG1lc2ggPSBjaHVuay5tZXNoITtcbiAgICBjb25zdCB7IGZhY2VzLCB2ZXJ0ZXhDZWxsIH0gPSBtZXNoO1xuICAgIGNvbnN0IHZpc2libGUgPSB0aGlzLnZpc2libGU7XG4gICAgY29uc3QgaGlkZGVuID0gdGhpcy5oaWRkZW47XG4gICAgY29uc3Qgc2hvd24gPSBuZXcgTWFwPG51bWJlciwgYm9vbGVhbj4oKTtcbiAgICBjb25zdCBpc1Nob3duID0gKGNlbGw6IG51bWJlcikgPT4ge1xuICAgICAgbGV0IHMgPSBzaG93bi5nZXQoY2VsbCk7XG4gICAgICBpZiAocyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGNvbnN0IGxhYmVsID0gY2h1bmsubGFiZWxzLmdldChjZWxsKSA/PyBudWxsO1xuICAgICAgICBzID0gIShsYWJlbCAhPT0gbnVsbCAmJiBoaWRkZW4uaGFzKGxhYmVsKSkgJiYgKCF2aXNpYmxlIHx8ICEhdmlzaWJsZVtjZWxsXSk7XG4gICAgICAgIHNob3duLnNldChjZWxsLCBzKTtcbiAgICAgIH1cbiAgICAgIHJldHVybiBzO1xuICAgIH07XG4gICAgaWYgKCFoaWRkZW4uc2l6ZSAmJiAhdmlzaWJsZSkgcmV0dXJuIGZhY2VzO1xuICAgIGNvbnN0IG91dCA9IG5ldyBVaW50MzJBcnJheShmYWNlcy5sZW5ndGgpO1xuICAgIGxldCBuID0gMDtcbiAgICBmb3IgKGxldCBmID0gMDsgZiA8IGZhY2VzLmxlbmd0aDsgZiArPSAzKSB7XG4gICAgICBpZiAoIWlzU2hvd24odmVydGV4Q2VsbFtmYWNlc1tmXV0pKSBjb250aW51ZTtcbiAgICAgIG91dFtuKytdID0gZmFjZXNbZl07XG4gICAgICBvdXRbbisrXSA9IGZhY2VzW2YgKyAxXTtcbiAgICAgIG91dFtuKytdID0gZmFjZXNbZiArIDJdO1xuICAgIH1cbiAgICByZXR1cm4gbiA9PT0gZmFjZXMubGVuZ3RoID8gZmFjZXMgOiBvdXQuc2xpY2UoMCwgbik7XG4gIH1cblxuICAvKipcbiAgICogRWFjaCB2ZXJ0ZXggaXRzIGNlbGwncyBjb2xvdXIgKHdoaXRlIHdpdGhvdXQgY29sb3VycykuIFdpdGggYSBzZWxlY3Rpb24sIGEgY2VsbCBpdCBsZWF2ZXMgb3V0XG4gICAqIGtlZXBzIGl0cyBjb2xvdXIgYW5kIGZhZGVzLCBhcyBhIHBpY2tlZCByZWdpb24gZmFkZXMgdGhlIG90aGVyczogaXRzIGFscGhhIGJyb3VnaHQgZG93biB0byB0aGVcbiAgICogZGltbWVkIHJlZ2lvbnMnIG9wYWNpdHkuIGBzb2xpZGA6IHRoZSBzZWxlY3RlZCBjZWxscycgb3duIHN1cmZhY2UsIGV2ZXJ5IHZlcnRleCBvcGFxdWUuXG4gICAqL1xuICBwcml2YXRlIHZlcnRleENvbG9ycyhtZXNoOiBDZWxsc01lc2gsIHNvbGlkID0gZmFsc2UpOiBGbG9hdDMyQXJyYXkge1xuICAgIGNvbnN0IG91dCA9IG5ldyBGbG9hdDMyQXJyYXkobWVzaC52ZXJ0ZXhDZWxsLmxlbmd0aCAqIDQpO1xuICAgIGNvbnN0IGNvbG9ycyA9IHRoaXMuY29sb3JzO1xuICAgIGNvbnN0IHNlbGVjdGVkID0gdGhpcy5zZWxlY3RlZDtcbiAgICBjb25zdCBvID0gdGhpcy5vcGFjaXR5ID4gMCA/IHRoaXMub3BhY2l0eSA6IDE7XG4gICAgY29uc3QgZGltID0gTWF0aC5taW4oMSwgUkVHSU9OX01FU0hfRElNTUVEX09QQUNJVFkgLyBvKTtcbiAgICBmb3IgKGxldCB2ID0gMDsgdiA8IG1lc2gudmVydGV4Q2VsbC5sZW5ndGg7IHYrKykge1xuICAgICAgY29uc3QgbyA9IG1lc2gudmVydGV4Q2VsbFt2XSAqIDQ7XG4gICAgICBpZiAoY29sb3JzICYmIG8gKyAzIDwgY29sb3JzLmxlbmd0aCkge1xuICAgICAgICBvdXRbdiAqIDRdID0gY29sb3JzW29dO1xuICAgICAgICBvdXRbdiAqIDQgKyAxXSA9IGNvbG9yc1tvICsgMV07XG4gICAgICAgIG91dFt2ICogNCArIDJdID0gY29sb3JzW28gKyAyXTtcbiAgICAgICAgb3V0W3YgKiA0ICsgM10gPSBjb2xvcnNbbyArIDNdO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgb3V0LmZpbGwoMSwgdiAqIDQsIHYgKiA0ICsgNCk7XG4gICAgICB9XG4gICAgICBpZiAoc29saWQpIG91dFt2ICogNCArIDNdID0gMTtcbiAgICAgIGVsc2UgaWYgKHNlbGVjdGVkICYmICFzZWxlY3RlZFttZXNoLnZlcnRleENlbGxbdl1dKSBvdXRbdiAqIDQgKyAzXSAqPSBkaW07XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG4gIH1cblxuICBwcml2YXRlIGRyb3BMYXllcihjaHVuazogQ2h1bmspOiB2b2lkIHtcbiAgICBmb3IgKGNvbnN0IGxheWVyIG9mIFtjaHVuay5sYXllciwgY2h1bmsuc2VsZWN0ZWRMYXllcl0pIHtcbiAgICAgIGlmICghbGF5ZXIpIGNvbnRpbnVlO1xuICAgICAgdGhpcy5ieUxheWVyLmRlbGV0ZShsYXllcik7XG4gICAgICB0aGlzLmhvc3Qudmlld2VyLmxheWVycy5yZW1vdmUobGF5ZXIpO1xuICAgIH1cbiAgICBjaHVuay5sYXllciA9IG51bGw7XG4gICAgY2h1bmsuc2VsZWN0ZWRMYXllciA9IG51bGw7XG4gIH1cblxuICBwcml2YXRlIHJlcG9ydChidWlsZGluZzogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmICghdGhpcy5jbGFzc2VzKSB7XG4gICAgICB0aGlzLmVtaXQobnVsbCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGRyYXduID0gdGhpcy5jaHVua3MuZmlsdGVyKChjKSA9PiBjLmxheWVyICYmIGMud2FudCA+PSAwKTtcbiAgICBjb25zdCBzaG93biA9IGRyYXduLnJlZHVjZSgocywgYykgPT4gcyArIE1hdGgubWF4KDAsIGMubWVzaGVkKSwgMCk7XG4gICAgY29uc3QgY2FwcGVkID0gdGhpcy5jaHVua3Muc29tZSgoYykgPT4gYy53YW50IDwgMCB8fCAoYy53YW50ID49IDAgJiYgYy5idWlsdExpbWl0IDwgYy5jZWxscykpO1xuICAgIHRoaXMuZW1pdCh7IHNob3duLCBjYXBwZWQsIGJ1aWxkaW5nOiBidWlsZGluZyB8fCB0aGlzLnJ1bm5pbmcgfSk7XG4gIH1cblxuICAvKiogVGVsbCB0aGUgaG9zdCBob3cgdGhlIGNlbGxzIHN0YW5kLCBvbmx5IHdoZW4gdGhhdCBjaGFuZ2VkICh0aGUgY2FtZXJhIHJlLXBsYW5zIG9mdGVuKS4gKi9cbiAgcHJpdmF0ZSBsYXN0U3RhdHVzID0gJ251bGwnO1xuICBwcml2YXRlIGVtaXQoc3RhdHVzOiBDZWxsczNkU3RhdHVzIHwgbnVsbCk6IHZvaWQge1xuICAgIGNvbnN0IGtleSA9IEpTT04uc3RyaW5naWZ5KHN0YXR1cyk7XG4gICAgaWYgKGtleSA9PT0gdGhpcy5sYXN0U3RhdHVzKSByZXR1cm47XG4gICAgdGhpcy5sYXN0U3RhdHVzID0ga2V5O1xuICAgIHRoaXMuaG9zdC5zdGF0dXMoc3RhdHVzKTtcbiAgfVxuXG4gIHByaXZhdGUgdG9Xb3JsZFBvaW50KHg6IG51bWJlciwgeTogbnVtYmVyLCB6OiBudW1iZXIpOiBGbG9hdDMyQXJyYXkge1xuICAgIHJldHVybiB0aGlzLnBsYWNlbWVudFxuICAgICAgPyB0b1dvcmxkKEZsb2F0MzJBcnJheS5vZih4LCB5LCB6KSwgeyBzaXplOiBbMSwgMSwgMV0sIHdvcmxkOiBbMSwgMSwgMV0sIHBsYW5lczogdGhpcy5wbGFjZW1lbnQgfSlcbiAgICAgIDogRmxvYXQzMkFycmF5Lm9mKHgsIHksIHopO1xuICB9XG59XG5cbi8qKiBUaGUgY2h1bmsgZ3JpZCBvdmVyIGEgcmVnaW9uIHNldCdzIGJvdW5kcywge0BsaW5rIENIVU5LU19BQ1JPU1N9IGFsb25nIGl0cyBsb25nZXIgc2lkZS4gKi9cbmZ1bmN0aW9uIG1ha2VDaHVua3Moc291cmNlOiBSZWdpb25Tb3VyY2UpOiBDaHVua1tdIHtcbiAgY29uc3QgYiA9IHNvdXJjZS5pbmZvLmJvdW5kcztcbiAgaWYgKCFiKSByZXR1cm4gW107XG4gIGNvbnN0IHNpemUgPSBNYXRoLm1heChiWzJdIC0gYlswXSwgYlszXSAtIGJbMV0pIC8gQ0hVTktTX0FDUk9TUyB8fCAxO1xuICBjb25zdCBvdXQ6IENodW5rW10gPSBbXTtcbiAgZm9yIChsZXQgeSA9IGJbMV07IHkgPCBiWzNdOyB5ICs9IHNpemUpIHtcbiAgICBmb3IgKGxldCB4ID0gYlswXTsgeCA8IGJbMl07IHggKz0gc2l6ZSkge1xuICAgICAgLy8gVGhlIGxhc3QgY2h1bmsgb2YgYSByb3cgKGNvbHVtbikgcmVhY2hlcyBwYXN0IHRoZSBib3VuZHM6IGEgY2VsbCBjZW50cmVkIG9uIHRoZW0gaXMgaW4gaXQuXG4gICAgICBjb25zdCB4MSA9IHggKyBzaXplID49IGJbMl0gPyBiWzJdICsgMSA6IHggKyBzaXplO1xuICAgICAgY29uc3QgeTEgPSB5ICsgc2l6ZSA+PSBiWzNdID8gYlszXSArIDEgOiB5ICsgc2l6ZTtcbiAgICAgIG91dC5wdXNoKHtcbiAgICAgICAga2V5OiBgJHtNYXRoLnJvdW5kKHgpfSwke01hdGgucm91bmQoeSl9YCxcbiAgICAgICAgYm94OiBbeCwgeSwgeDEsIHkxXSxcbiAgICAgICAgdGllcjogLTEsXG4gICAgICAgIHdhbnQ6IC0xLFxuICAgICAgICBjZWxsczogLTEsXG4gICAgICAgIHRyaWFuZ2xlczogbmV3IE1hcCgpLFxuICAgICAgICBsaW1pdDogSW5maW5pdHksXG4gICAgICAgIGJ1aWx0TGltaXQ6IEluZmluaXR5LFxuICAgICAgICBtZXNoZWQ6IC0xLFxuICAgICAgICBtZXNoOiBudWxsLFxuICAgICAgICBsYWJlbHM6IG5ldyBNYXAoKSxcbiAgICAgICAgd29ybGQ6IG51bGwsXG4gICAgICAgIGRyYXduOiBudWxsLFxuICAgICAgICBkcmF3blNlbGVjdGVkOiBudWxsLFxuICAgICAgICBzZWxlY3RlZExheWVyOiBudWxsLFxuICAgICAgICBsYXllcjogbnVsbCxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuICByZXR1cm4gb3V0O1xufVxuXG4vKiogTWVzaGVzIGNvbmNhdGVuYXRlZCwgZWFjaCB2ZXJ0ZXgga2VlcGluZyBpdHMgY2VsbC4gKi9cbmZ1bmN0aW9uIGNvbmNhdE1lc2hlcyhwYXJ0czogcmVhZG9ubHkgQ2VsbHNNZXNoW10pOiBDZWxsc01lc2gge1xuICBpZiAocGFydHMubGVuZ3RoID09PSAxKSByZXR1cm4gcGFydHNbMF07XG4gIGNvbnN0IG52ID0gcGFydHMucmVkdWNlKChzLCBwKSA9PiBzICsgcC52ZXJ0ZXhDZWxsLmxlbmd0aCwgMCk7XG4gIGNvbnN0IG5mID0gcGFydHMucmVkdWNlKChzLCBwKSA9PiBzICsgcC5mYWNlcy5sZW5ndGgsIDApO1xuICBjb25zdCBuYyA9IHBhcnRzLnJlZHVjZSgocywgcCkgPT4gcyArIHAuY2VsbHMubGVuZ3RoLCAwKTtcbiAgY29uc3Qgb3V0OiBDZWxsc01lc2ggPSB7XG4gICAgdmVydGljZXM6IG5ldyBGbG9hdDMyQXJyYXkobnYgKiAzKSxcbiAgICBmYWNlczogbmV3IFVpbnQzMkFycmF5KG5mKSxcbiAgICB2ZXJ0ZXhDZWxsOiBuZXcgVWludDMyQXJyYXkobnYpLFxuICAgIGNlbGxzOiBuZXcgVWludDMyQXJyYXkobmMpLFxuICB9O1xuICBsZXQgdiA9IDA7XG4gIGxldCBmID0gMDtcbiAgbGV0IGMgPSAwO1xuICBmb3IgKGNvbnN0IHAgb2YgcGFydHMpIHtcbiAgICBvdXQudmVydGljZXMuc2V0KHAudmVydGljZXMsIHYgKiAzKTtcbiAgICBvdXQudmVydGV4Q2VsbC5zZXQocC52ZXJ0ZXhDZWxsLCB2KTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHAuZmFjZXMubGVuZ3RoOyBpKyspIG91dC5mYWNlc1tmICsgaV0gPSBwLmZhY2VzW2ldICsgdjtcbiAgICBvdXQuY2VsbHMuc2V0KHAuY2VsbHMsIGMpO1xuICAgIHYgKz0gcC52ZXJ0ZXhDZWxsLmxlbmd0aDtcbiAgICBmICs9IHAuZmFjZXMubGVuZ3RoO1xuICAgIGMgKz0gcC5jZWxscy5sZW5ndGg7XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqIFRoZSBtaWRkbGUgb2YgdGhlIHBsYW5lcycgc2xpY2UgcmFuZ2UgKHNsaWNlIHVuaXRzKS4gKi9cbmZ1bmN0aW9uIG1pZFoocDogUGxhbmVQbGFjZW1lbnQpOiBudW1iZXIge1xuICByZXR1cm4gKHAuei5sZW5ndGggLSAxKSAvIDI7XG59XG5cbi8qKlxuICogV2hldGhlciBhIGNodW5rIGlzIHRvIGJlIGJ1aWx0IChhZ2Fpbik6IGl0cyB0aWVyIGNoYW5nZWQsIG9yIGl0IHdhcyBtZXNoZWQgaW4gcGFydCBhbmQgdGhlIHBsYW5cbiAqIG5vdyBsZXRzIGl0IGhhdmUgbW9yZSBvZiBpdHMgY2VsbHMsIG9yIGZld2VyLlxuICovXG5mdW5jdGlvbiBuZWVkc0J1aWxkKGM6IENodW5rKTogYm9vbGVhbiB7XG4gIGlmIChjLndhbnQgPCAwKSByZXR1cm4gZmFsc2U7XG4gIGlmIChjLndhbnQgIT09IGMudGllcikgcmV0dXJuIHRydWU7XG4gIHJldHVybiBjLmNlbGxzID49IDAgJiYgTWF0aC5taW4oYy5idWlsdExpbWl0LCBjLmNlbGxzKSAhPT0gTWF0aC5taW4oYy5saW1pdCwgYy5jZWxscyk7XG59XG5cbi8qKiBXaGV0aGVyIHR3byBmYWNlIGxpc3RzIGFyZSB0aGUgc2FtZSB0cmlhbmdsZXMuICovXG5mdW5jdGlvbiBzYW1lRmFjZXMoYTogVWludDMyQXJyYXksIGI6IFVpbnQzMkFycmF5KTogYm9vbGVhbiB7XG4gIGlmIChhID09PSBiKSByZXR1cm4gdHJ1ZTtcbiAgaWYgKGEubGVuZ3RoICE9PSBiLmxlbmd0aCkgcmV0dXJuIGZhbHNlO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGEubGVuZ3RoOyBpKyspIGlmIChhW2ldICE9PSBiW2ldKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiB0cnVlO1xufVxuXG5mdW5jdGlvbiBzYW1lU2V0KGE6IFJlYWRvbmx5U2V0PHN0cmluZz4gfCBudWxsLCBiOiBSZWFkb25seVNldDxzdHJpbmc+IHwgbnVsbCk6IGJvb2xlYW4ge1xuICBpZiAoYSA9PT0gYikgcmV0dXJuIHRydWU7XG4gIGlmICghYSB8fCAhYiB8fCBhLnNpemUgIT09IGIuc2l6ZSkgcmV0dXJuIGZhbHNlO1xuICBmb3IgKGNvbnN0IHggb2YgYSkgaWYgKCFiLmhhcyh4KSkgcmV0dXJuIGZhbHNlO1xuICByZXR1cm4gdHJ1ZTtcbn1cblxuZnVuY3Rpb24gc2FtZVBsYWNlbWVudChhOiBQbGFuZVBsYWNlbWVudCB8IG51bGwsIGI6IFBsYW5lUGxhY2VtZW50IHwgbnVsbCk6IGJvb2xlYW4ge1xuICBpZiAoYSA9PT0gYikgcmV0dXJuIHRydWU7XG4gIGlmICghYSB8fCAhYiB8fCBhLnoubGVuZ3RoICE9PSBiLnoubGVuZ3RoKSByZXR1cm4gZmFsc2U7XG4gIHJldHVybiAoXG4gICAgYS56LmV2ZXJ5KCh2LCBpKSA9PiB2ID09PSBiLnpbaV0pICYmXG4gICAgYS5zY2FsZS5ldmVyeSgodiwgaSkgPT4gdiA9PT0gYi5zY2FsZVtpXSkgJiZcbiAgICBhLm9mZnNldC5ldmVyeSgodiwgaSkgPT4gdiA9PT0gYi5vZmZzZXRbaV0pXG4gICk7XG59XG5cbi8qKlxuICogVHJpYW5nbGVzIGBmYWNlc2Agc3BsaXQgYnkgd2hldGhlciB0aGVpciBjZWxsIChgdmVydGV4Q2VsbGAgb2YgdGhlaXIgZmlyc3QgdmVydGV4KSBpcyBzZWxlY3RlZDpcbiAqIHRoZSBzZWxlY3RlZCBjZWxscycgdHJpYW5nbGVzLCB0aGVuIHRoZSBvdGhlcnMnLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc3BsaXRGYWNlcyhcbiAgZmFjZXM6IFVpbnQzMkFycmF5LFxuICB2ZXJ0ZXhDZWxsOiBVaW50MzJBcnJheSxcbiAgc2VsZWN0ZWQ6IFVpbnQ4QXJyYXksXG4pOiBbVWludDMyQXJyYXksIFVpbnQzMkFycmF5XSB7XG4gIGNvbnN0IHNlbCA9IG5ldyBVaW50MzJBcnJheShmYWNlcy5sZW5ndGgpO1xuICBjb25zdCByZXN0ID0gbmV3IFVpbnQzMkFycmF5KGZhY2VzLmxlbmd0aCk7XG4gIGxldCBzID0gMDtcbiAgbGV0IHIgPSAwO1xuICBmb3IgKGxldCBmID0gMDsgZiA8IGZhY2VzLmxlbmd0aDsgZiArPSAzKSB7XG4gICAgY29uc3Qgb3V0ID0gc2VsZWN0ZWRbdmVydGV4Q2VsbFtmYWNlc1tmXV1dID8gc2VsIDogcmVzdDtcbiAgICBjb25zdCBhdCA9IG91dCA9PT0gc2VsID8gcyA6IHI7XG4gICAgb3V0W2F0XSA9IGZhY2VzW2ZdO1xuICAgIG91dFthdCArIDFdID0gZmFjZXNbZiArIDFdO1xuICAgIG91dFthdCArIDJdID0gZmFjZXNbZiArIDJdO1xuICAgIGlmIChvdXQgPT09IHNlbCkgcyArPSAzO1xuICAgIGVsc2UgciArPSAzO1xuICB9XG4gIHJldHVybiBbc2VsLnNsaWNlKDAsIHMpLCByZXN0LnNsaWNlKDAsIHIpXTtcbn1cbiJdfQ==
|