@jax-data-science/sci-image-visualizer 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +49 -0
  2. package/esm2022/lib/contracts/display-types.mjs +28 -1
  3. package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
  4. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +3 -1
  5. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
  6. package/esm2022/lib/contracts/toolbar-tool.contract.mjs +46 -4
  7. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  8. package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +195 -0
  9. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +10 -2
  10. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +1098 -0
  11. package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +6 -3
  12. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +186 -10
  13. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +2 -2
  14. package/esm2022/lib/implementations/plotly/plotly.service.mjs +2 -3
  15. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +120 -2
  16. package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +76 -1
  17. package/esm2022/lib/routing-visualizer.service.mjs +10 -1
  18. package/esm2022/lib/spatial/spatial-tiles.mjs +506 -0
  19. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +659 -19
  20. package/esm2022/lib/toolbar/brush/brush-tool.service.mjs +44 -3
  21. package/esm2022/lib/toolbar/toolbar.component.mjs +15 -3
  22. package/esm2022/lib/visualizer.component.mjs +221 -7
  23. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +3238 -84
  24. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  25. package/lib/contracts/display-types.d.ts +104 -1
  26. package/lib/contracts/plot-type-contribution.contract.d.ts +27 -0
  27. package/lib/contracts/ports/spatial-data.port.d.ts +59 -1
  28. package/lib/contracts/spatial-dataset.contract.d.ts +167 -0
  29. package/lib/contracts/toolbar-tool.contract.d.ts +84 -5
  30. package/lib/contracts/visualizer.contract.d.ts +22 -1
  31. package/lib/implementations/napari-js/napari-navigator.d.ts +72 -0
  32. package/lib/implementations/napari-js/napari-region-overlay.d.ts +3 -0
  33. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +240 -0
  34. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +42 -2
  35. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +26 -2
  36. package/lib/implementations/spatial-data-http/spatial-wire.d.ts +34 -1
  37. package/lib/spatial/spatial-tiles.d.ts +222 -0
  38. package/lib/spatial-controls/spatial-controls.component.d.ts +234 -3
  39. package/lib/toolbar/brush/brush-tool.service.d.ts +21 -0
  40. package/lib/toolbar/toolbar.component.d.ts +11 -3
  41. package/lib/visualizer.component.d.ts +54 -2
  42. package/package.json +1 -1
@@ -0,0 +1,1098 @@
1
+ import { Colormap, colormapFromLut } from 'napari-js';
2
+ import { ALL_GENES } from '../../contracts/ports/spatial-data.port';
3
+ import { NO_CATEGORY, NO_OBSERVATION, isCategoricalColumn, } from '../../contracts/spatial-dataset.contract';
4
+ import { DEFAULT_CATEGORICAL_PALETTE, MISSING_COLOR, contrastWindow, lutFor, parseHex, resolveCategoryColors, } from '../../spatial/spatial-encoding';
5
+ import { INFERNO_SCALE, POLYGON_LEVEL_MIN_CELL_PX, allGenesPlan, cellTypeColumnFor, cellsShown, colorDensityWindow, densityAutoRange, groupedMarkerPx, quantileOf, tilesInRectFrom, defaultGlyphFor, discreteColormapStops, glyphOutline, glyphRings, pixelsPerDataUnit, polygonLevelFor, tileId, tilesInRect, transcriptLevelFor, transcriptMarkerPx, typicalCellDiameter, visibleArea, visibleDataRect, } from '../../spatial/spatial-tiles';
6
+ const ORDER = [
7
+ 'cellFill', 'cellOutline', 'nucleusOutline', 'density', 'transcripts', 'transcriptOutline',
8
+ ];
9
+ /** Transcripts drawn at once. Past this a screen is solid colour anyway; the level
10
+ * policy keeps a normal view far below it. */
11
+ const MAX_TRANSCRIPTS = 400_000;
12
+ const MAX_CELL_TILES = 48;
13
+ const MAX_TRANSCRIPT_TILES = 36;
14
+ const MAX_BIN_TILES = 64;
15
+ const CAMERA_IDLE_MS = 120;
16
+ /** First retry of a view with a failed tile; doubles each time, up to MAX_TILE_RETRIES. */
17
+ const TILE_RETRY_MS = 1000;
18
+ const MAX_TILE_RETRIES = 3;
19
+ const UNASSIGNED_RGBA = [0.62, 0.62, 0.62, 0.55];
20
+ export class NapariSpatialTileLayers {
21
+ constructor(port, host) {
22
+ this.port = port;
23
+ this.host = host;
24
+ this.viewer = null;
25
+ this.cameraOff = null;
26
+ this.timer = null;
27
+ /** Set when a tile of the current plan failed to load (see fetchAll). */
28
+ this.planIncomplete = false;
29
+ /** Consecutive retries of an incomplete view. */
30
+ this.tileRetries = 0;
31
+ this.token = 0;
32
+ this.layers = new Map();
33
+ /** What each group currently shows, so an unchanged plan is a no-op. */
34
+ this.keys = new Map();
35
+ this.polygonsShown = false;
36
+ /** Rings currently drawn and the (dataset, set, tiles) they came from. */
37
+ this.currentRings = null;
38
+ this.cellGeometryKey = null;
39
+ this.currentNuclei = null;
40
+ this.cellStyleKey = null;
41
+ /** Selection identity → revision, so a change key can name a selection cheaply. */
42
+ this.lastSelection = null;
43
+ this.selectionRevision = 0;
44
+ // ── hover ─────────────────────────────────────────────────────────────────────────
45
+ this.drawn = null;
46
+ this.hoverTypes = null;
47
+ /** Details already fetched, by hovered entry. */
48
+ this.hoverCache = new Map();
49
+ this.hoverKey = null;
50
+ this.hoverTimer = null;
51
+ this.countsCache = null;
52
+ /** The density window in use and the densest bin, for the panel's threshold control. */
53
+ this.densityStats = null;
54
+ }
55
+ // ── lifecycle ─────────────────────────────────────────────────────────────────────
56
+ attach(viewer) {
57
+ if (this.viewer === viewer)
58
+ return;
59
+ this.detach();
60
+ this.viewer = viewer;
61
+ this.cameraOff = viewer.camera.changed.connect(() => this.schedule());
62
+ }
63
+ /** Whether `layer` is one of the overlays drawn here (density, cells, transcripts). */
64
+ owns(layer) {
65
+ for (const l of this.layers.values())
66
+ if (l === layer)
67
+ return true;
68
+ return false;
69
+ }
70
+ detach() {
71
+ if (this.hoverTimer)
72
+ clearTimeout(this.hoverTimer);
73
+ this.hoverTimer = null;
74
+ this.drawn = null;
75
+ this.cameraOff?.();
76
+ this.cameraOff = null;
77
+ if (this.timer)
78
+ clearTimeout(this.timer);
79
+ this.timer = null;
80
+ this.token++;
81
+ this.tileRetries = 0;
82
+ if (this.viewer) {
83
+ for (const layer of this.layers.values()) {
84
+ if (this.viewer.layers.items.includes(layer))
85
+ this.viewer.layers.remove(layer);
86
+ }
87
+ }
88
+ this.layers.clear();
89
+ this.keys.clear();
90
+ this.setPolygonsShown(false);
91
+ this.viewer = null;
92
+ }
93
+ /** True while outlines are on screen — the service hides its dots then. */
94
+ get outlinesShown() {
95
+ return this.polygonsShown;
96
+ }
97
+ /** Dataset, view or selection changed: re-plan now rather than on camera idle. */
98
+ refresh() {
99
+ this.schedule(0);
100
+ }
101
+ /** Called right after the service adds its marker layer: everything goes back on top. */
102
+ afterObservations() {
103
+ const v = this.viewer;
104
+ if (!v)
105
+ return;
106
+ for (const g of ORDER) {
107
+ const layer = this.layers.get(g);
108
+ if (!layer)
109
+ continue;
110
+ if (v.layers.items.includes(layer))
111
+ v.layers.remove(layer);
112
+ v.layers.add(layer);
113
+ }
114
+ }
115
+ // ── planning ──────────────────────────────────────────────────────────────────────
116
+ schedule(delay = CAMERA_IDLE_MS) {
117
+ if (this.timer)
118
+ clearTimeout(this.timer);
119
+ this.timer = setTimeout(() => {
120
+ this.timer = null;
121
+ void this.plan();
122
+ }, delay);
123
+ }
124
+ async plan() {
125
+ const viewer = this.viewer;
126
+ const latest = this.host.latest();
127
+ if (!viewer || !latest)
128
+ return;
129
+ const [dataset, view, selection] = latest;
130
+ const token = ++this.token;
131
+ const stale = () => token !== this.token || this.viewer !== viewer;
132
+ this.planIncomplete = false;
133
+ if (!dataset) {
134
+ for (const g of ORDER)
135
+ this.drop(g);
136
+ this.dropCells();
137
+ return;
138
+ }
139
+ const [w, h] = this.host.canvasSize();
140
+ const ref = dataset.imageRef;
141
+ const rect = visibleDataRect(viewer.camera.center, viewer.camera.zoom, w, h, ref);
142
+ const pxPerUnit = pixelsPerDataUnit(viewer.camera.zoom, ref);
143
+ if (!rect)
144
+ return;
145
+ void this.planEstimate(dataset, view, viewer, w, h, stale);
146
+ await Promise.all([
147
+ this.planDensity(dataset, view, stale),
148
+ this.planCells(dataset, view, selection, rect, pxPerUnit, stale),
149
+ this.planTranscripts(dataset, view, rect, pxPerUnit, stale),
150
+ ]);
151
+ if (stale())
152
+ return;
153
+ // A tile that failed left a hole the cache keys do not record, so try the same view
154
+ // again, backing off, a bounded number of times.
155
+ if (!this.planIncomplete) {
156
+ this.tileRetries = 0;
157
+ }
158
+ else if (this.tileRetries < MAX_TILE_RETRIES) {
159
+ this.schedule(TILE_RETRY_MS * 2 ** this.tileRetries++);
160
+ }
161
+ }
162
+ // ── cells ─────────────────────────────────────────────────────────────────────────
163
+ async planCells(dataset, view, selection, rect, pxPerUnit, stale) {
164
+ const tiled = dataset.polygonTiles;
165
+ const whole = !tiled && dataset.polygons && this.port.getPolygons;
166
+ if (!cellsShown(dataset, view) || (!tiled && !whole)) {
167
+ this.dropCells();
168
+ return;
169
+ }
170
+ const diameter = typicalCellDiameter(dataset.observations.radius);
171
+ // Whole-dataset rings have one level and no coarser fallback, so they are drawn as
172
+ // soon as a cell is big enough to read as a shape rather than a dot.
173
+ const level = tiled
174
+ ? polygonLevelFor(pxPerUnit, diameter, tiled.levels.length)
175
+ : (pxPerUnit * diameter >= POLYGON_LEVEL_MIN_CELL_PX[2] ? 0 : -1);
176
+ if (level < 0) {
177
+ this.dropCells();
178
+ return;
179
+ }
180
+ // Groups switched off in the list: their cells are left out of the geometry.
181
+ const hidden = await this.hiddenCodes(dataset, view);
182
+ if (stale())
183
+ return;
184
+ const geometry = await this.cellGeometry(dataset, view, rect, level, hidden, stale);
185
+ if (!geometry)
186
+ return;
187
+ const { rings, nuclei, geometryKey } = geometry;
188
+ const geometryChanged = geometryKey !== this.cellGeometryKey;
189
+ const styleKey = [
190
+ geometryKey, view.cellColorMode, view.cellColorGene, view.cellSingleColor,
191
+ this.cellTypeColumnName(dataset, view),
192
+ this.selectionRev(selection), view.logScale, view.percentileClip.join(),
193
+ JSON.stringify(view.continuousColormap), view.cellDraw, view.cellOpacity,
194
+ ].join('|');
195
+ const present = ['cellFill', 'cellOutline', 'nucleusOutline'].some((g) => {
196
+ const l = this.layers.get(g);
197
+ return l && this.viewer.layers.items.includes(l);
198
+ });
199
+ if (!geometryChanged && styleKey === this.cellStyleKey && present) {
200
+ this.setPolygonsShown(true);
201
+ return;
202
+ }
203
+ const colors = await this.cellColors(dataset, view, selection, rings.observation);
204
+ if (stale())
205
+ return;
206
+ this.currentRings = rings;
207
+ this.currentNuclei = nuclei;
208
+ // A geometry missing a failed tile is drawn but not remembered, so the retry refetches it.
209
+ this.cellGeometryKey = this.planIncomplete ? null : geometryKey;
210
+ this.cellStyleKey = styleKey;
211
+ const ref = dataset.imageRef;
212
+ const common = { scale: ref?.scale ?? [1, 1], translate: ref?.translate ?? [0, 0] };
213
+ const fill = view.cellDraw !== 'outline';
214
+ const outline = view.cellDraw !== 'fill';
215
+ this.upsertShapes('cellFill', fill, geometryChanged, rings, {
216
+ name: 'cells', draw: 'fill', opacity: view.cellOpacity, ...colors, ...common,
217
+ });
218
+ this.upsertShapes('cellOutline', outline, geometryChanged, rings, fill
219
+ // Over a fill, a dark outline separates neighbours of the same type.
220
+ ? { name: 'cell outlines', draw: 'outline', color: [0.08, 0.08, 0.1, 1], opacity: 0.7, ...common }
221
+ : { name: 'cell outlines', draw: 'outline', opacity: 1, ...colors, ...common });
222
+ // "Both": nuclei outlined over the cells, light so they read against any fill.
223
+ if (nuclei) {
224
+ this.upsertShapes('nucleusOutline', true, geometryChanged, nuclei, {
225
+ name: 'nucleus outlines', draw: 'outline', color: [0.95, 0.95, 0.98, 1], opacity: 0.8, ...common,
226
+ });
227
+ }
228
+ else {
229
+ this.drop('nucleusOutline');
230
+ }
231
+ this.setPolygonsShown(true);
232
+ }
233
+ selectionRev(selection) {
234
+ if (selection !== this.lastSelection) {
235
+ this.lastSelection = selection;
236
+ this.selectionRevision++;
237
+ }
238
+ return this.selectionRevision;
239
+ }
240
+ /** Per-shape values + colormap for the rings' owners. */
241
+ /**
242
+ * Per-shape values + colormap for the rings' owners, by the view's cell-colour mode
243
+ * (Xenium Explorer's "Cell Color"). A selection mutes what it leaves out.
244
+ */
245
+ async cellColors(dataset, view, selection, owners) {
246
+ const muted = selection.count > 0 ? selection.mask : null;
247
+ const mode = view.cellColorMode;
248
+ if (mode === 'single') {
249
+ const [r, g, b] = parseHex(view.cellSingleColor);
250
+ return { color: [r / 255, g / 255, b / 255, 1] };
251
+ }
252
+ const continuous = async (raw, log) => {
253
+ const values = new Float32Array(owners.length);
254
+ for (let i = 0; i < owners.length; i++) {
255
+ const v = raw[owners[i]] ?? NaN;
256
+ values[i] = log ? Math.log1p(Math.max(0, v)) : v;
257
+ }
258
+ const [lo, hi] = contrastWindow(log ? raw.map((v) => Math.log1p(Math.max(0, v))) : raw, view.percentileClip[0], view.percentileClip[1]);
259
+ return {
260
+ values,
261
+ colormap: colormapFromLut('spatial-continuous', this.host.continuousLut(view)),
262
+ contrastLimits: [lo, hi],
263
+ };
264
+ };
265
+ if (mode === 'gene' && view.cellColorGene) {
266
+ return continuous(await this.port.getFeatureVector(view.cellColorGene), true);
267
+ }
268
+ if (mode === 'transcriptDensity' && dataset.columns.some((c) => c.name === 'transcript_density')) {
269
+ const column = await this.port.getColumn('transcript_density');
270
+ if (!isCategoricalColumn(column))
271
+ return continuous(column.values, false);
272
+ }
273
+ const name = mode === 'segmentation' && dataset.columns.some((c) => c.name === 'segmentation_method')
274
+ ? 'segmentation_method'
275
+ : this.cellTypeColumnName(dataset, view);
276
+ const codes = name ? await this.categoricalCodes(name) : null;
277
+ const { colormap, valueOf } = this.categoricalColormap(codes?.meta ?? null);
278
+ const values = new Float32Array(owners.length);
279
+ for (let i = 0; i < owners.length; i++) {
280
+ const o = owners[i];
281
+ const code = !codes || (muted && !muted[o]) ? -1 : codes.codes[o];
282
+ values[i] = valueOf(code === NO_CATEGORY ? -1 : code);
283
+ }
284
+ return { values, colormap, contrastLimits: [0, 1] };
285
+ }
286
+ /** Codes of the group column that are switched off, or null when none are. */
287
+ async hiddenCodes(dataset, view) {
288
+ if (!view.hiddenGroups.length)
289
+ return null;
290
+ const name = this.cellTypeColumnName(dataset, view);
291
+ const col = name ? await this.categoricalCodes(name) : null;
292
+ if (!col || col.meta.kind !== 'categorical')
293
+ return null;
294
+ const off = new Set(view.hiddenGroups);
295
+ const hidden = Uint8Array.from(col.meta.categories, (c) => (off.has(c) ? 1 : 0));
296
+ return { codes: col.codes, hidden };
297
+ }
298
+ cellTypeColumnName(dataset, view) {
299
+ return cellTypeColumnFor(dataset, view);
300
+ }
301
+ async categoricalCodes(name) {
302
+ const column = await this.port.getColumn(name);
303
+ return isCategoricalColumn(column) ? { codes: column.codes, meta: column.meta } : null;
304
+ }
305
+ categoricalColormap(meta) {
306
+ const hex = meta && meta.kind === 'categorical'
307
+ ? resolveCategoryColors(meta)
308
+ : [DEFAULT_CATEGORICAL_PALETTE[0]];
309
+ const rgb = hex.map(parseHex);
310
+ const { stops, valueOf } = discreteColormapStops(rgb, MISSING_COLOR);
311
+ return { colormap: new Colormap('spatial-categories', stops), valueOf, rgb };
312
+ }
313
+ /**
314
+ * The cell rings (and, for "both", the nucleus rings) covering `rect` at `level`, minus
315
+ * the hidden groups — reused when nothing that decides them changed. Null when the
316
+ * view went stale or the dataset has no set to draw.
317
+ */
318
+ async cellGeometry(dataset, view, rect, level, hidden, stale) {
319
+ const tiled = dataset.polygonTiles;
320
+ const hiddenKey = view.hiddenGroups.join('\u0001');
321
+ let rings;
322
+ let nuclei = null;
323
+ let geometryKey;
324
+ if (tiled) {
325
+ const both = view.cellSet === 'both';
326
+ const set = !both && view.cellSet && tiled.sets.some((s) => s.name === view.cellSet)
327
+ ? view.cellSet : (tiled.defaultSet ?? tiled.sets[0]?.name);
328
+ if (!set)
329
+ return null;
330
+ const nucleusSet = both ? tiled.sets.find((s) => s.name !== set)?.name : undefined;
331
+ const keys = tilesInRect(rect, level, tiled.levels, tiled.bounds, MAX_CELL_TILES);
332
+ geometryKey = `${dataset.id}|${set}|${nucleusSet ?? ''}|${hiddenKey}|${keys.map(tileId).join(',')}`;
333
+ if (geometryKey === this.cellGeometryKey && this.currentRings) {
334
+ rings = this.currentRings;
335
+ nuclei = this.currentNuclei;
336
+ }
337
+ else {
338
+ const [tiles, nucleusTiles] = await Promise.all([
339
+ this.fetchAll(keys, (k) => this.port.getPolygonTile(set, k.level, k.gx, k.gy)),
340
+ nucleusSet
341
+ ? this.fetchAll(keys, (k) => this.port.getPolygonTile(nucleusSet, k.level, k.gx, k.gy))
342
+ : Promise.resolve(null),
343
+ ]);
344
+ if (stale())
345
+ return null;
346
+ rings = filterRings(mergePolygonTiles(tiles), hidden);
347
+ nuclei = nucleusTiles ? filterRings(mergePolygonTiles(nucleusTiles), hidden) : null;
348
+ }
349
+ }
350
+ else {
351
+ geometryKey = `${dataset.id}|whole|${hiddenKey}`;
352
+ if (geometryKey === this.cellGeometryKey && this.currentRings) {
353
+ rings = this.currentRings;
354
+ }
355
+ else {
356
+ const polys = await this.port.getPolygons();
357
+ if (stale())
358
+ return null;
359
+ // Whole-dataset rings are index-aligned with the observations.
360
+ rings = filterRings({ ...polys, observation: Uint32Array.from({ length: polys.count }, (_v, i) => i) }, hidden);
361
+ }
362
+ }
363
+ return { rings, nuclei, geometryKey };
364
+ }
365
+ // ── transcripts ───────────────────────────────────────────────────────────────────
366
+ async planTranscripts(dataset, view, rect, pxPerUnit, stale) {
367
+ const mode = view.transcriptMode;
368
+ const job = (mode === 'circles' || mode === 'glyphs') && this.port.getTranscriptTile
369
+ ? (view.transcriptAllGenes
370
+ ? this.allGenesJob(dataset, view, rect, pxPerUnit)
371
+ : this.geneJob(dataset, view, rect, pxPerUnit))
372
+ : null;
373
+ if (!job) {
374
+ this.drop('transcripts');
375
+ this.drop('transcriptOutline');
376
+ this.drawn = null;
377
+ return;
378
+ }
379
+ // Marker sizes follow the zoom, so the zoom is part of the key; a pan that keeps
380
+ // the same tiles on screen changes nothing.
381
+ const planKey = [
382
+ dataset.id, mode, job.key, view.transcriptColorBy, this.cellTypeColumnName(dataset, view),
383
+ view.transcriptScale, view.transcriptOpacity, JSON.stringify(view.transcriptGlyphs),
384
+ pxPerUnit.toPrecision(4), view.hiddenGroups.join('\u0001'), view.transcriptHiddenGenes.join(','),
385
+ JSON.stringify(view.transcriptGeneColors),
386
+ ].join('|');
387
+ const current = this.layers.get('transcripts');
388
+ if (planKey === this.keys.get('transcripts') && current && this.viewer.layers.items.includes(current)) {
389
+ return;
390
+ }
391
+ const loaded = await job.load();
392
+ if (stale())
393
+ return;
394
+ const hidden = await this.hiddenCodes(dataset, view);
395
+ if (stale())
396
+ return;
397
+ const { merged, px } = filterTranscripts(loaded.merged, loaded.px, hidden, (loaded.kind ?? job.kind) === 'genes' ? hiddenGeneSlots(view) : null);
398
+ // A bin of the all-gene pyramid mixes genes and carries none, so it cannot be coloured
399
+ // by gene: colour it by its dominant cell's type until individual transcripts show.
400
+ const kind = loaded.kind ?? job.kind;
401
+ const colorView = kind === 'bins' && view.transcriptColorBy === 'gene'
402
+ ? { ...view, transcriptColorBy: 'cellType' } : view;
403
+ const faces = await this.transcriptColors(dataset, colorView, merged);
404
+ if (stale())
405
+ return;
406
+ if (this.planIncomplete)
407
+ this.keys.delete('transcripts');
408
+ else
409
+ this.keys.set('transcripts', planKey);
410
+ const diam = px.map((d) => d / pxPerUnit);
411
+ this.drawn = {
412
+ kind: loaded.kind ?? job.kind, bin: loaded.kind ? loaded.bin : job.bin,
413
+ merged, radius: diam.map((d) => d / 2),
414
+ genes: [...view.transcriptGenes], ref: dataset.imageRef ?? null, grid: null,
415
+ };
416
+ this.hoverCache.clear();
417
+ const typeColumn = this.cellTypeColumnName(dataset, view);
418
+ this.hoverTypes = typeColumn ? await this.categoricalCodes(typeColumn).catch(() => null) : null;
419
+ if (stale())
420
+ return;
421
+ const ref = dataset.imageRef;
422
+ const place = { scale: ref?.scale ?? [1, 1], translate: ref?.translate ?? [0, 0] };
423
+ if (mode === 'circles') {
424
+ this.drop('transcriptOutline');
425
+ this.drawTranscriptCircles(merged, diam, faces.rgba, view, place);
426
+ }
427
+ else {
428
+ this.drawTranscriptGlyphs(merged, diam, faces, view, place);
429
+ }
430
+ }
431
+ /** One sized circle per entry, the size saying how many transcripts it stands for. */
432
+ drawTranscriptCircles(merged, diam, rgba, view, { scale, translate }) {
433
+ const positions = new Float32Array(merged.count * 2);
434
+ for (let i = 0; i < merged.count; i++) {
435
+ positions[2 * i] = merged.x[i];
436
+ positions[2 * i + 1] = merged.y[i];
437
+ }
438
+ const layer = this.viewer.addPoints(positions, {
439
+ name: 'transcripts',
440
+ size: diam,
441
+ faceColor: rgba,
442
+ // A dark rim: a transcript coloured by its cell's type is otherwise the same
443
+ // colour as the cell fill it sits on, and vanishes into it.
444
+ borderColor: [0.04, 0.04, 0.05, 0.9],
445
+ borderWidth: 0.18 * median(diam),
446
+ opacity: view.transcriptOpacity,
447
+ scale,
448
+ translate,
449
+ });
450
+ this.replace('transcripts', layer);
451
+ }
452
+ drawTranscriptGlyphs(merged, diam, faces, view, { scale, translate }) {
453
+ // Glyphs: each entry becomes its gene's icon polygon, filled through a discrete
454
+ // colormap and outlined dark so small icons stay readable over the tissue. With every
455
+ // gene drawn there is one icon for all of them — 18,000 shapes would say nothing.
456
+ const genes = view.transcriptGenes;
457
+ const glyphFor = (slot) => view.transcriptGlyphs[genes[slot]] ?? defaultGlyphFor(slot);
458
+ const single = view.transcriptAllGenes
459
+ ? glyphOutline(view.transcriptGlyphs[ALL_GENES] ?? 'circle')
460
+ : null;
461
+ const outlines = single ? [] : genes.map((_g, slot) => glyphOutline(glyphFor(slot)));
462
+ const radius = diam.map((d) => d / 2);
463
+ const { coords, offsets } = glyphRings(merged.x, merged.y, radius, (i) => single ?? outlines[merged.gene[i]]);
464
+ const fill = this.viewer.addShapes(coords, offsets, {
465
+ name: 'transcripts',
466
+ draw: 'fill',
467
+ values: faces.values,
468
+ colormap: faces.colormap,
469
+ contrastLimits: [0, 1],
470
+ opacity: view.transcriptOpacity,
471
+ scale,
472
+ translate,
473
+ });
474
+ this.replace('transcripts', fill);
475
+ const edge = this.viewer.addShapes(coords, offsets, {
476
+ name: 'transcript outlines',
477
+ draw: 'outline',
478
+ color: [0.05, 0.05, 0.05, 1],
479
+ opacity: Math.min(1, view.transcriptOpacity + 0.1),
480
+ scale,
481
+ translate,
482
+ });
483
+ this.replace('transcriptOutline', edge);
484
+ }
485
+ /**
486
+ * Tooltip lines for the transcript marker under world point `(wx, wy)`, or null.
487
+ *
488
+ * Returns what is known at once (gene, count, cell type); anything that needs the
489
+ * server — distinct genes in a group, its top genes and cells, the cell's display id —
490
+ * arrives through `onDetails` once the pointer has rested on the marker briefly.
491
+ */
492
+ hoverAt(wx, wy, radiusWorld, onDetails) {
493
+ const d = this.drawn;
494
+ const layer = this.layers.get('transcripts');
495
+ if (!d || !layer || !this.viewer?.layers.items.includes(layer) || !d.merged.count) {
496
+ this.hoverKey = null;
497
+ return null;
498
+ }
499
+ const sx = d.ref?.scale?.[0] ?? 1;
500
+ const sy = d.ref?.scale?.[1] ?? 1;
501
+ const x = (wx - (d.ref?.translate?.[0] ?? 0)) / sx;
502
+ const y = (wy - (d.ref?.translate?.[1] ?? 0)) / sy;
503
+ const i = pickNearest(d, x, y, radiusWorld / Math.abs(sx));
504
+ if (i < 0) {
505
+ this.hoverKey = null;
506
+ return null;
507
+ }
508
+ const key = `${d.kind}|${d.merged.x[i]}|${d.merged.y[i]}|${d.merged.gene[i]}`;
509
+ const cached = this.hoverCache.get(key);
510
+ if (cached)
511
+ return cached;
512
+ if (key !== this.hoverKey) {
513
+ this.hoverKey = key;
514
+ if (this.hoverTimer)
515
+ clearTimeout(this.hoverTimer);
516
+ this.hoverTimer = setTimeout(() => void this.fetchDetails(d, i, key, onDetails), 150);
517
+ }
518
+ return this.describe(d, i, null);
519
+ }
520
+ async fetchDetails(d, i, key, onDetails) {
521
+ if (!this.port.getTranscriptSummary || this.hoverKey !== key)
522
+ return;
523
+ const obs = d.merged.observation[i];
524
+ const cells = obs === NO_OBSERVATION ? [] : [obs];
525
+ let box;
526
+ if (d.kind === 'bins' && d.bin) {
527
+ const { size, origin } = d.bin;
528
+ const bx = Math.floor((d.merged.x[i] - origin[0]) / size);
529
+ const by = Math.floor((d.merged.y[i] - origin[1]) / size);
530
+ const x0 = origin[0] + bx * size;
531
+ const y0 = origin[1] + by * size;
532
+ box = [x0, y0, x0 + size, y0 + size];
533
+ }
534
+ else if (d.kind === 'individual') {
535
+ const e = 0.02;
536
+ box = [d.merged.x[i] - e, d.merged.y[i] - e, d.merged.x[i] + e, d.merged.y[i] + e];
537
+ }
538
+ try {
539
+ const summary = await this.port.getTranscriptSummary({ box, cells });
540
+ const lines = this.describe(d, i, summary);
541
+ this.hoverCache.set(key, lines);
542
+ if (this.hoverKey === key)
543
+ onDetails(lines);
544
+ }
545
+ catch (err) {
546
+ console.warn('[napari-js] transcript details unavailable', err);
547
+ }
548
+ }
549
+ /** The tooltip text for entry `i`, with the server's details when they have arrived. */
550
+ describe(d, i, s) {
551
+ const t = d.merged;
552
+ const n = t.weight[i];
553
+ const obs = t.observation[i];
554
+ const fmt = (v) => v.toLocaleString();
555
+ const typeOf = (o) => {
556
+ const types = this.hoverTypes;
557
+ if (!types || o === NO_OBSERVATION || types.meta.kind !== 'categorical')
558
+ return null;
559
+ const c = types.codes[o];
560
+ return c === NO_CATEGORY ? null : types.meta.categories[c] ?? null;
561
+ };
562
+ const cellLine = (o, prefix) => {
563
+ if (o === NO_OBSERVATION)
564
+ return 'outside any cell';
565
+ const id = s?.cellIds?.[o] ?? `#${o}`;
566
+ const type = typeOf(o);
567
+ return `${prefix} ${id}${type ? ` · ${type}` : ''}`;
568
+ };
569
+ if (d.kind === 'bins') {
570
+ const lines = [`${fmt(n)} transcripts · all genes`];
571
+ if (d.bin)
572
+ lines.push(`${d.bin.size.toFixed(1)} × ${d.bin.size.toFixed(1)} µm area`);
573
+ if (s?.transcripts !== undefined) {
574
+ lines.push(`${fmt(s.genes ?? 0)} distinct genes · ${fmt(s.cells ?? 0)} cell${s.cells === 1 ? '' : 's'}`
575
+ + (s.unassigned ? ` · ${fmt(s.unassigned)} outside cells` : ''));
576
+ if (s.topGenes?.length) {
577
+ lines.push(`top genes: ${s.topGenes.slice(0, 5).map((g) => `${g.name} ${fmt(g.count)}`).join(', ')}`);
578
+ }
579
+ }
580
+ lines.push(cellLine(obs, 'mostly cell'));
581
+ if (!s && this.port.getTranscriptSummary)
582
+ lines.push('loading details…');
583
+ return lines;
584
+ }
585
+ if (d.kind === 'individual') {
586
+ const gene = s?.topGenes?.[0]?.name;
587
+ return [
588
+ gene ? `${gene} transcript` : 'Transcript',
589
+ cellLine(obs, 'in cell'),
590
+ ...(!s && this.port.getTranscriptSummary ? ['loading details…'] : []),
591
+ ];
592
+ }
593
+ const gene = d.genes[t.gene[i]] ?? 'transcript';
594
+ return n > 1
595
+ ? [`${gene} · ${fmt(n)} transcripts`, 'grouped: zoom in to split', cellLine(obs, 'near cell')]
596
+ : [`${gene} transcript`, cellLine(obs, 'in cell')];
597
+ }
598
+ /** Physical marker size needs µm; null when the dataset's unit is unknown. */
599
+ pxPerMicron(dataset, pxPerUnit) {
600
+ return dataset.micronsPerUnit ? pxPerUnit / dataset.micronsPerUnit : undefined;
601
+ }
602
+ /**
603
+ * The chosen genes, at the level the zoom calls for — or coarser, while the markers in
604
+ * view would exceed the budget.
605
+ */
606
+ geneJob(dataset, view, rect, pxPerUnit) {
607
+ const meta = dataset.transcriptTiles;
608
+ const genes = view.transcriptGenes;
609
+ if (!meta || !genes.length)
610
+ return null;
611
+ const first = transcriptLevelFor(pxPerUnit, meta.levels);
612
+ const keysAt = (l) => tilesInRect(rect, l, meta.levels, meta.bounds, MAX_TRANSCRIPT_TILES);
613
+ const query = { genes, quality: view.transcriptQuality };
614
+ const pxPerMicron = this.pxPerMicron(dataset, pxPerUnit);
615
+ return {
616
+ kind: 'genes',
617
+ key: `genes|${genes.join(',')}|${view.transcriptQuality}|${view.transcriptBudget}|${keysAt(first).map(tileId)}`,
618
+ load: async () => {
619
+ let level = first;
620
+ let merged;
621
+ for (;;) {
622
+ const tiles = await this.fetchAll(keysAt(level), (k) => this.port.getTranscriptTile(k.level, k.gx, k.gy, query));
623
+ merged = mergeTranscriptTiles(tiles, MAX_TRANSCRIPTS);
624
+ if (merged.count <= view.transcriptBudget || level >= meta.levels.length - 1)
625
+ break;
626
+ level++;
627
+ }
628
+ const px = new Float32Array(merged.count);
629
+ for (let i = 0; i < merged.count; i++) {
630
+ px[i] = transcriptMarkerPx(merged.weight[i], view.transcriptScale, pxPerMicron);
631
+ }
632
+ return { merged, px };
633
+ },
634
+ };
635
+ }
636
+ /**
637
+ * Every gene: the transcripts themselves once they fit the budget, else bins of the
638
+ * all-gene pyramid sized by how many transcripts each holds.
639
+ */
640
+ allGenesJob(dataset, view, rect, pxPerUnit) {
641
+ const bins = dataset.transcriptBins;
642
+ const tiles = dataset.transcriptTiles;
643
+ const bounds = bins?.bounds ?? tiles?.bounds;
644
+ if (!bounds)
645
+ return null;
646
+ const plan = allGenesPlan({
647
+ rect, bounds, pxPerUnit, budget: view.transcriptBudget,
648
+ total: bins?.count ?? tiles?.count ?? 0,
649
+ levels: bins && this.port.getTranscriptBins ? bins.levels : [],
650
+ canIndividual: !!tiles,
651
+ });
652
+ if (plan.kind === 'individual' && tiles) {
653
+ const keys = tilesInRect(rect, 0, tiles.levels, tiles.bounds, MAX_TRANSCRIPT_TILES);
654
+ // Each tile clipped to the view, rounded outward to 10 units so small pans hit cache.
655
+ const r10 = (v, up) => (up ? Math.ceil(v / 10) : Math.floor(v / 10)) * 10;
656
+ const size = tiles.levels[0].tileSize;
657
+ const boxes = keys.map((k) => [
658
+ Math.max(k.gx * size, r10(rect.x0, false)), Math.max(k.gy * size, r10(rect.y0, false)),
659
+ Math.min((k.gx + 1) * size, r10(rect.x1, true)), Math.min((k.gy + 1) * size, r10(rect.y1, true)),
660
+ ]);
661
+ const pxPerMicron = this.pxPerMicron(dataset, pxPerUnit);
662
+ return {
663
+ kind: 'individual',
664
+ key: `all|individual|${view.transcriptBudget}|${boxes.map((b) => b.join(',')).join(';')}`,
665
+ load: async () => {
666
+ const got = await this.fetchAll(keys.map((k, i) => ({ ...k, box: boxes[i] })), (k) => this.port.getTranscriptTile(0, k.gx, k.gy, { genes: [ALL_GENES], box: k.box }));
667
+ // The plan estimated the view from the dataset's average density; expression is
668
+ // uneven, so a dense view can hold far more. Rather than cut the excess off, show
669
+ // it grouped — the bin level the planner would pick if it had known.
670
+ const cap = Math.max(view.transcriptBudget * 1.5, 1);
671
+ const loaded = got.reduce((n, t) => n + t.count, 0);
672
+ if (loaded > cap && bins && this.port.getTranscriptBins) {
673
+ const fallback = allGenesPlan({
674
+ rect, bounds, pxPerUnit, budget: view.transcriptBudget, total: bins.count,
675
+ levels: bins.levels, canIndividual: false,
676
+ });
677
+ if (fallback.kind === 'bins') {
678
+ const job = this.binsJob(view, rect, pxPerUnit, bounds, bins, fallback.level);
679
+ return { ...(await job.load()), kind: job.kind, bin: job.bin };
680
+ }
681
+ }
682
+ const merged = mergeTranscriptTiles(got, cap);
683
+ const px = new Float32Array(merged.count);
684
+ for (let i = 0; i < merged.count; i++)
685
+ px[i] = transcriptMarkerPx(1, view.transcriptScale, pxPerMicron);
686
+ return { merged, px };
687
+ },
688
+ };
689
+ }
690
+ if (plan.kind === 'bins' && bins && this.port.getTranscriptBins) {
691
+ return this.binsJob(view, rect, pxPerUnit, bounds, bins, plan.level);
692
+ }
693
+ return null;
694
+ }
695
+ /** Bins of the all-gene pyramid at `level`, sized by how many transcripts each holds. */
696
+ binsJob(view, rect, pxPerUnit, bounds, bins, level) {
697
+ const lv = bins.levels[level];
698
+ const keys = tilesInRectFrom(bins.origin, rect, level, bins.levels.map((l) => ({ tileSize: l.tileSize })), bounds, MAX_BIN_TILES);
699
+ return {
700
+ kind: 'bins',
701
+ bin: { size: lv.binSize, origin: bins.origin },
702
+ key: `all|bins|${level}|${view.transcriptBudget}|${keys.map(tileId)}`,
703
+ load: async () => {
704
+ const got = await this.fetchAll(keys, (k) => this.port.getTranscriptBins(k.level, k.gx, k.gy));
705
+ const merged = mergeTranscriptTiles(got, Math.max(view.transcriptBudget * 1.5, 1));
706
+ const refCount = quantileOf(merged.weight, 0.95);
707
+ const binPx = lv.binSize * pxPerUnit;
708
+ const px = new Float32Array(merged.count);
709
+ for (let i = 0; i < merged.count; i++) {
710
+ px[i] = groupedMarkerPx(merged.weight[i], refCount, binPx, view.transcriptScale);
711
+ }
712
+ return { merged, px };
713
+ },
714
+ };
715
+ }
716
+ /** Per-entry colours both as RGBA (points) and as colormap values (glyph shapes). */
717
+ async transcriptColors(dataset, view, t) {
718
+ let rgb;
719
+ let codeOf;
720
+ if (view.transcriptColorBy === 'gene') {
721
+ // All genes: codes are the dataset's gene indices, folded onto the palette.
722
+ const n = view.transcriptAllGenes ? DEFAULT_CATEGORICAL_PALETTE.length : view.transcriptGenes.length;
723
+ rgb = Array.from({ length: n }, (_g, i) => parseHex((!view.transcriptAllGenes && view.transcriptGeneColors[view.transcriptGenes[i]])
724
+ || DEFAULT_CATEGORICAL_PALETTE[i % DEFAULT_CATEGORICAL_PALETTE.length]));
725
+ codeOf = view.transcriptAllGenes ? (i) => t.gene[i] % n : (i) => t.gene[i];
726
+ }
727
+ else {
728
+ const name = this.cellTypeColumnName(dataset, view);
729
+ const codes = name ? await this.categoricalCodes(name) : null;
730
+ rgb = codes?.meta.kind === 'categorical' ? resolveCategoryColors(codes.meta).map(parseHex) : [];
731
+ codeOf = (i) => {
732
+ const o = t.observation[i];
733
+ if (!codes || o === NO_OBSERVATION)
734
+ return -1;
735
+ const c = codes.codes[o];
736
+ return c === NO_CATEGORY ? -1 : c;
737
+ };
738
+ }
739
+ const { stops, valueOf } = discreteColormapStops(rgb, MISSING_COLOR);
740
+ const rgba = new Array(t.count);
741
+ const values = new Float32Array(t.count);
742
+ const tuples = rgb.map(([r, g, b]) => [r / 255, g / 255, b / 255, 1]);
743
+ for (let i = 0; i < t.count; i++) {
744
+ const c = codeOf(i);
745
+ rgba[i] = c < 0 ? UNASSIGNED_RGBA : tuples[c];
746
+ values[i] = valueOf(c);
747
+ }
748
+ return { rgba, values, colormap: new Colormap('transcript-categories', stops) };
749
+ }
750
+ // ── density ───────────────────────────────────────────────────────────────────────
751
+ async planDensity(dataset, view, stale) {
752
+ const hiddenGenes = new Set(view.transcriptHiddenGenes);
753
+ const genes = view.transcriptAllGenes
754
+ ? [ALL_GENES]
755
+ : view.transcriptGenes.filter((g) => !hiddenGenes.has(g));
756
+ if (!dataset.density || !this.port.getDensity || view.transcriptMode !== 'density' || !genes.length) {
757
+ this.drop('density');
758
+ this.densityStats = null;
759
+ return;
760
+ }
761
+ const lut = lutFor(view.densityColormap ?? INFERNO_SCALE);
762
+ const key = [dataset.id, genes.join(','), view.densityBin, view.densityOpacity,
763
+ JSON.stringify(view.densityRange), JSON.stringify(view.densityColormap)].join('|');
764
+ if (key === this.keys.get('density') && this.layers.has('density'))
765
+ return;
766
+ const raster = await this.port.getDensity(genes, view.densityBin);
767
+ if (stale())
768
+ return;
769
+ // Bins drawn as squares, as Xenium Explorer does; the window is in transcripts/µm².
770
+ const meta = raster.meta;
771
+ const area = meta.gridSize[0] * meta.gridSize[1];
772
+ const perArea = raster.values.map((v) => v / area);
773
+ const [lo, hi] = view.densityRange ?? densityAutoRange(perArea);
774
+ this.densityStats = { lo, hi, max: perArea.reduce((m, v) => (v > m ? v : m), 0) };
775
+ const rgba = colorDensityWindow(perArea, lut, view.densityOpacity, lo, hi);
776
+ const ref = dataset.imageRef;
777
+ const sx = ref?.scale?.[0] ?? 1;
778
+ const sy = ref?.scale?.[1] ?? 1;
779
+ const layer = this.viewer.addImage({ kind: 'typed', width: meta.cols, height: meta.rows, channels: 4, dtype: 'uint8', data: rgba }, {
780
+ name: `density · ${view.transcriptAllGenes ? 'all genes' : genes.join(', ')}`,
781
+ scale: [meta.gridSize[0] * sx, meta.gridSize[1] * sy],
782
+ translate: [
783
+ meta.origin[0] * sx + (ref?.translate?.[0] ?? 0),
784
+ meta.origin[1] * sy + (ref?.translate?.[1] ?? 0),
785
+ ],
786
+ blending: 'translucent',
787
+ interpolation: 'nearest',
788
+ });
789
+ this.keys.set('density', key);
790
+ this.replace('density', layer);
791
+ this.host.densityChanged?.(this.densityStats);
792
+ }
793
+ /**
794
+ * Transcripts in view for the visible genes: each gene's dataset total times the share
795
+ * of the tissue on screen. An estimate — expression is not uniform — which is also what
796
+ * Xenium Explorer shows; it tells the user whether the budget will force grouping.
797
+ */
798
+ async planEstimate(dataset, view, viewer, w, h, stale) {
799
+ const tiles = dataset.transcriptTiles;
800
+ if (!tiles || !this.port.getTranscriptCounts || view.transcriptMode === 'off') {
801
+ this.host.estimateChanged?.(null);
802
+ return;
803
+ }
804
+ const hiddenGenes = new Set(view.transcriptHiddenGenes);
805
+ const genes = view.transcriptAllGenes ? [] : view.transcriptGenes.filter((g) => !hiddenGenes.has(g));
806
+ const key = `${dataset.id}|${genes.join(',')}`;
807
+ if (this.countsCache?.key !== key) {
808
+ this.countsCache = { key, counts: this.port.getTranscriptCounts(genes) };
809
+ }
810
+ let counts;
811
+ try {
812
+ counts = await this.countsCache.counts;
813
+ }
814
+ catch {
815
+ this.countsCache = null;
816
+ return;
817
+ }
818
+ if (stale())
819
+ return;
820
+ const inView = visibleDataRect(viewer.camera.center, viewer.camera.zoom, w, h, dataset.imageRef, 0);
821
+ if (!inView)
822
+ return;
823
+ const b = counts.bounds;
824
+ const share = Math.min(1, visibleArea(inView, b) / Math.max(1, (b[2] - b[0]) * (b[3] - b[1])));
825
+ const selected = view.transcriptAllGenes
826
+ ? counts.total
827
+ : genes.reduce((sum, g) => sum + (counts.counts[g] ?? 0), 0);
828
+ this.host.estimateChanged?.({ points: Math.round(selected * share), max: view.transcriptBudget });
829
+ }
830
+ // ── layer bookkeeping ─────────────────────────────────────────────────────────────
831
+ /**
832
+ * Fetch every tile, drawing what arrived. A failure does not fail the view, but it marks the
833
+ * plan incomplete: the caller must not cache it as done, and `plan()` retries it.
834
+ */
835
+ async fetchAll(keys, load) {
836
+ const settled = await Promise.allSettled(keys.map(load));
837
+ const out = [];
838
+ for (const s of settled) {
839
+ if (s.status === 'fulfilled')
840
+ out.push(s.value);
841
+ else
842
+ console.warn('[napari-js] spatial tile failed', s.reason);
843
+ }
844
+ if (out.length < keys.length)
845
+ this.planIncomplete = true;
846
+ return out;
847
+ }
848
+ /**
849
+ * Put a shapes layer in place for `group`: a geometry change builds a new layer, a
850
+ * colour-only change mutates values/colormap on the existing one.
851
+ */
852
+ upsertShapes(group, wanted, geometryChanged, rings, opts) {
853
+ if (!wanted) {
854
+ this.drop(group);
855
+ return;
856
+ }
857
+ const existing = this.layers.get(group);
858
+ if (existing && !geometryChanged && this.viewer.layers.items.includes(existing)) {
859
+ // Flat colour has no values; clearing them is what switches the layer to `color`.
860
+ existing.values = opts.values ?? null;
861
+ if (opts.colormap)
862
+ existing.colormap = opts.colormap;
863
+ if (opts.contrastLimits)
864
+ existing.contrastLimits = opts.contrastLimits;
865
+ if (opts.color)
866
+ existing.color = opts.color;
867
+ if (opts.opacity !== undefined)
868
+ existing.opacity = opts.opacity;
869
+ this.viewer.requestRender();
870
+ return;
871
+ }
872
+ const layer = this.viewer.addShapes(rings.coords, rings.offsets, opts);
873
+ this.replace(group, layer);
874
+ }
875
+ /**
876
+ * Install `layer` as `group`'s layer and restore the order of the groups above it.
877
+ * The layer was just added by the caller (so it is on top); groups that belong above
878
+ * it are removed and re-added.
879
+ */
880
+ replace(group, layer) {
881
+ const v = this.viewer;
882
+ const old = this.layers.get(group);
883
+ if (old && old !== layer && v.layers.items.includes(old))
884
+ v.layers.remove(old);
885
+ this.layers.set(group, layer);
886
+ for (const g of ORDER.slice(ORDER.indexOf(group) + 1)) {
887
+ const above = this.layers.get(g);
888
+ if (!above || !v.layers.items.includes(above))
889
+ continue;
890
+ v.layers.remove(above);
891
+ v.layers.add(above);
892
+ }
893
+ v.requestRender();
894
+ }
895
+ drop(group) {
896
+ const layer = this.layers.get(group);
897
+ if (layer && this.viewer?.layers.items.includes(layer))
898
+ this.viewer.layers.remove(layer);
899
+ this.layers.delete(group);
900
+ this.keys.delete(group);
901
+ }
902
+ dropCells() {
903
+ this.drop('cellFill');
904
+ this.drop('cellOutline');
905
+ this.drop('nucleusOutline');
906
+ this.currentNuclei = null;
907
+ this.cellGeometryKey = null;
908
+ this.cellStyleKey = null;
909
+ this.currentRings = null;
910
+ this.setPolygonsShown(false);
911
+ }
912
+ setPolygonsShown(shown) {
913
+ if (shown === this.polygonsShown)
914
+ return;
915
+ this.polygonsShown = shown;
916
+ this.host.polygonsShownChanged(shown);
917
+ }
918
+ }
919
+ /** Index of the entry under `(x, y)` — within its own radius or `tolerance` — or -1. */
920
+ export function pickNearest(d, x, y, tolerance) {
921
+ const t = d.merged;
922
+ if (!d.grid) {
923
+ let maxR = 0;
924
+ for (let i = 0; i < t.count; i++)
925
+ if (d.radius[i] > maxR)
926
+ maxR = d.radius[i];
927
+ const size = Math.max(maxR * 2, tolerance * 2, 1e-6);
928
+ const buckets = new Map();
929
+ for (let i = 0; i < t.count; i++) {
930
+ const k = bucketKey(Math.floor(t.x[i] / size), Math.floor(t.y[i] / size));
931
+ let b = buckets.get(k);
932
+ if (!b)
933
+ buckets.set(k, (b = []));
934
+ b.push(i);
935
+ }
936
+ d.grid = { size, buckets };
937
+ }
938
+ const { size, buckets } = d.grid;
939
+ const gx = Math.floor(x / size);
940
+ const gy = Math.floor(y / size);
941
+ let best = -1;
942
+ let bestD = Infinity;
943
+ for (let dy = -1; dy <= 1; dy++) {
944
+ for (let dx = -1; dx <= 1; dx++) {
945
+ for (const i of buckets.get(bucketKey(gx + dx, gy + dy)) ?? []) {
946
+ const dist = Math.hypot(t.x[i] - x, t.y[i] - y);
947
+ if (dist <= Math.max(d.radius[i], tolerance) && dist < bestD) {
948
+ bestD = dist;
949
+ best = i;
950
+ }
951
+ }
952
+ }
953
+ }
954
+ return best;
955
+ }
956
+ function bucketKey(gx, gy) {
957
+ return (gx + 32768) * 65536 + (gy + 32768);
958
+ }
959
+ /** Rings whose owning cell is in a switched-off group removed. */
960
+ export function filterRings(rings, hidden) {
961
+ if (!hidden)
962
+ return rings;
963
+ const keep = [];
964
+ let vertices = 0;
965
+ for (let i = 0; i < rings.count; i++) {
966
+ const code = hidden.codes[rings.observation[i]];
967
+ if (code !== NO_CATEGORY && hidden.hidden[code])
968
+ continue;
969
+ keep.push(i);
970
+ vertices += rings.offsets[i + 1] - rings.offsets[i];
971
+ }
972
+ if (keep.length === rings.count)
973
+ return rings;
974
+ const observation = new Uint32Array(keep.length);
975
+ const offsets = new Uint32Array(keep.length + 1);
976
+ const coords = new Float32Array(vertices * 2);
977
+ let v = 0;
978
+ keep.forEach((i, r) => {
979
+ observation[r] = rings.observation[i];
980
+ offsets[r] = v;
981
+ const a = rings.offsets[i] * 2;
982
+ const b = rings.offsets[i + 1] * 2;
983
+ coords.set(rings.coords.subarray(a, b), v * 2);
984
+ v += (b - a) / 2;
985
+ });
986
+ offsets[keep.length] = v;
987
+ return { count: keep.length, observation, offsets, coords };
988
+ }
989
+ /** Slots (indices into the selected genes) switched off with their eye toggle. */
990
+ function hiddenGeneSlots(view) {
991
+ if (!view.transcriptHiddenGenes.length)
992
+ return null;
993
+ const off = new Set(view.transcriptHiddenGenes);
994
+ return Uint8Array.from(view.transcriptGenes, (g) => (off.has(g) ? 1 : 0));
995
+ }
996
+ /** Entries in a hidden group's cell, or of a hidden gene, removed (with their sizes). */
997
+ export function filterTranscripts(t, px, hidden, hiddenGenes) {
998
+ if (!hidden && !hiddenGenes)
999
+ return { merged: t, px };
1000
+ const keep = [];
1001
+ for (let i = 0; i < t.count; i++) {
1002
+ if (hiddenGenes && hiddenGenes[t.gene[i]])
1003
+ continue;
1004
+ const o = t.observation[i];
1005
+ if (hidden && o !== NO_OBSERVATION) {
1006
+ const code = hidden.codes[o];
1007
+ if (code !== NO_CATEGORY && hidden.hidden[code])
1008
+ continue;
1009
+ }
1010
+ keep.push(i);
1011
+ }
1012
+ const pick = (a) => {
1013
+ const out = new a.constructor(keep.length);
1014
+ keep.forEach((i, k) => { out[k] = a[i]; });
1015
+ return out;
1016
+ };
1017
+ return {
1018
+ merged: {
1019
+ count: keep.length, aggregated: t.aggregated, x: pick(t.x), y: pick(t.y), z: pick(t.z),
1020
+ weight: pick(t.weight), observation: pick(t.observation), gene: pick(t.gene),
1021
+ },
1022
+ px: pick(px),
1023
+ };
1024
+ }
1025
+ function median(v) {
1026
+ if (!v.length)
1027
+ return 0;
1028
+ const step = Math.max(1, Math.floor(v.length / 1024));
1029
+ const sample = [];
1030
+ for (let i = 0; i < v.length; i += step)
1031
+ sample.push(v[i]);
1032
+ sample.sort((a, b) => a - b);
1033
+ return sample[sample.length >> 1];
1034
+ }
1035
+ /** Concatenate tiles' rings into one set, dropping rings already seen (a cell straddling
1036
+ * two tiles may be listed by both). */
1037
+ export function mergePolygonTiles(tiles) {
1038
+ const seen = new Set();
1039
+ let rings = 0;
1040
+ let vertices = 0;
1041
+ for (const t of tiles) {
1042
+ for (let i = 0; i < t.count; i++) {
1043
+ if (seen.has(t.observation[i]))
1044
+ continue;
1045
+ seen.add(t.observation[i]);
1046
+ rings++;
1047
+ vertices += t.offsets[i + 1] - t.offsets[i];
1048
+ }
1049
+ }
1050
+ seen.clear();
1051
+ const observation = new Uint32Array(rings);
1052
+ const offsets = new Uint32Array(rings + 1);
1053
+ const coords = new Float32Array(vertices * 2);
1054
+ let r = 0;
1055
+ let v = 0;
1056
+ for (const t of tiles) {
1057
+ for (let i = 0; i < t.count; i++) {
1058
+ const o = t.observation[i];
1059
+ if (seen.has(o))
1060
+ continue;
1061
+ seen.add(o);
1062
+ observation[r] = o;
1063
+ offsets[r] = v;
1064
+ const a = t.offsets[i] * 2;
1065
+ const b = t.offsets[i + 1] * 2;
1066
+ coords.set(t.coords.subarray(a, b), v * 2);
1067
+ v += (b - a) / 2;
1068
+ r++;
1069
+ }
1070
+ }
1071
+ offsets[rings] = v;
1072
+ return { count: rings, observation, offsets, coords };
1073
+ }
1074
+ /** Concatenate transcript tiles, stopping at `limit` entries. */
1075
+ export function mergeTranscriptTiles(tiles, limit = Infinity) {
1076
+ let n = 0;
1077
+ for (const t of tiles)
1078
+ n += t.count;
1079
+ n = Math.min(n, limit);
1080
+ const out = {
1081
+ count: n,
1082
+ aggregated: tiles.some((t) => t.aggregated),
1083
+ x: new Float32Array(n), y: new Float32Array(n), z: new Float32Array(n),
1084
+ weight: new Uint32Array(n), observation: new Uint32Array(n), gene: new Uint16Array(n),
1085
+ };
1086
+ let o = 0;
1087
+ for (const t of tiles) {
1088
+ const k = Math.min(t.count, n - o);
1089
+ if (k <= 0)
1090
+ break;
1091
+ for (const f of ['x', 'y', 'z', 'weight', 'observation', 'gene']) {
1092
+ out[f].set(t[f].subarray(0, k), o);
1093
+ }
1094
+ o += k;
1095
+ }
1096
+ return out;
1097
+ }
1098
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibmFwYXJpLXNwYXRpYWwtdGlsZXMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9zcmMvbGliL2ltcGxlbWVudGF0aW9ucy9uYXBhcmktanMvbmFwYXJpLXNwYXRpYWwtdGlsZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFFBQVEsRUFBRSxlQUFlLEVBQUUsTUFBTSxXQUFXLENBQUM7QUFJdEQsT0FBTyxFQUFFLFNBQVMsRUFBd0IsTUFBTSx5Q0FBeUMsQ0FBQztBQUUxRixPQUFPLEVBQ0wsV0FBVyxFQUFFLGNBQWMsRUFFM0IsbUJBQW1CLEdBQ3BCLE1BQU0sMENBQTBDLENBQUM7QUFDbEQsT0FBTyxFQUNMLDJCQUEyQixFQUFFLGFBQWEsRUFBRSxjQUFjLEVBQUUsTUFBTSxFQUFFLFFBQVEsRUFBRSxxQkFBcUIsR0FDcEcsTUFBTSxnQ0FBZ0MsQ0FBQztBQUV4QyxPQUFPLEVBQ0ssYUFBYSxFQUFFLHlCQUF5QixFQUFtQixZQUFZLEVBQUUsaUJBQWlCLEVBQ3BHLFVBQVUsRUFBRSxrQkFBa0IsRUFBRSxnQkFBZ0IsRUFBRSxlQUFlLEVBQUUsVUFBVSxFQUFFLGVBQWUsRUFDOUYsZUFBZSxFQUFFLHFCQUFxQixFQUFFLFlBQVksRUFBRSxVQUFVLEVBQUUsaUJBQWlCLEVBQ25GLGVBQWUsRUFBRSxNQUFNLEVBQUUsV0FBVyxFQUFFLGtCQUFrQixFQUFFLGtCQUFrQixFQUM1RSxtQkFBbUIsRUFBRSxXQUFXLEVBQUUsZUFBZSxHQUNsRCxNQUFNLDZCQUE2QixDQUFDO0FBb0RyQyxNQUFNLEtBQUssR0FBWTtJQUNyQixVQUFVLEVBQUUsYUFBYSxFQUFFLGdCQUFnQixFQUFFLFNBQVMsRUFBRSxhQUFhLEVBQUUsbUJBQW1CO0NBQzNGLENBQUM7QUFFRjsrQ0FDK0M7QUFDL0MsTUFBTSxlQUFlLEdBQUcsT0FBTyxDQUFDO0FBQ2hDLE1BQU0sY0FBYyxHQUFHLEVBQUUsQ0FBQztBQUMxQixNQUFN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QUMsS0FBSyxDQUFDLENBQUM7UUFDbkMsSUFBSSxHQUFHLElBQUksR0FBRyxLQUFLLEtBQUssSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDO1lBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDL0UsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxFQUFFLEtBQUssQ0FBQyxDQUFDO1FBQzlCLEtBQUssTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDdEQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDakMsSUFBSSxDQUFDLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUM7Z0JBQUUsU0FBUztZQUN4RCxDQUFDLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUN2QixDQUFDLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN0QixDQUFDO1FBQ0QsQ0FBQyxDQUFDLGFBQWEsRUFBRSxDQUFDO0lBQ3BCLENBQUM7SUFFTyxJQUFJLENBQUMsS0FBWTtRQUN2QixNQUFNLEtBQUssR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUNyQyxJQUFJLEtBQUssSUFBSSxJQUFJLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQztZQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6RixJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUMxQixJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUMxQixDQUFDO0lBRU8sU0FBUztRQUNmLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFDdEIsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztRQUN6QixJQUFJLENBQUMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLGFBQWEsR0FBRyxJQUFJLENBQUM7UUFDMUIsSUFBSSxDQUFDLGVBQWUsR0FBRyxJQUFJLENBQUM7UUFDNUIsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7UUFDekIsSUFBSSxDQUFDLFlBQVksR0FBRyxJQUFJLENBQUM7UUFDekIsSUFBSSxDQUFDLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQy9CLENBQUM7SUFFTyxnQkFBZ0IsQ0FBQyxLQUFjO1FBQ3JDLElBQUksS0FBSyxLQUFLLElBQUksQ0FBQyxhQUFhO1lBQUUsT0FBTztRQUN6QyxJQUFJLENBQUMsYUFBYSxHQUFHLEtBQUssQ0FBQztRQUMzQixJQUFJLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3hDLENBQUM7Q0FDRjtBQWVELHdGQUF3RjtBQUN4RixNQUFNLFVBQVUsV0FBVyxDQUN6QixDQUF1RCxFQUFFLENBQVMsRUFBRSxDQUFTLEVBQUUsU0FBaUI7SUFFaEcsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQztJQUNuQixJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ1osSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDO1FBQ2IsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFO1lBQUUsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUk7Z0JBQUUsSUFBSSxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0UsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEdBQUcsQ0FBQyxFQUFFLFNBQVMsR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDckQsTUFBTSxPQUFPLEdBQUcsSUFBSSxHQUFHLEVBQW9CLENBQUM7UUFDNUMsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUNqQyxNQUFNLENBQUMsR0FBRyxTQUFTLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQzFFLElBQUksQ0FBQyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdkIsSUFBSSxDQUFDLENBQUM7Z0JBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNqQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ1osQ0FBQztRQUNELENBQUMsQ0FBQyxJQUFJLEdBQUcsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLENBQUM7SUFDN0IsQ0FBQztJQUNELE1BQU0sRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUNqQyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztJQUNoQyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztJ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TCxNQUFNLEVBQUU7WUFDTixLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFDdEYsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1NBQzdFO1FBQ0QsRUFBRSxFQUFFLElBQUksQ0FBQyxFQUFFLENBQUM7S0FDYixDQUFDO0FBQ0osQ0FBQztBQUVELFNBQVMsTUFBTSxDQUFDLENBQWU7SUFDN0IsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNO1FBQUUsT0FBTyxDQUFDLENBQUM7SUFDeEIsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDdEQsTUFBTSxNQUFNLEdBQWEsRUFBRSxDQUFDO0lBQzVCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxJQUFJO1FBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUMzRCxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO0lBQzdCLE9BQU8sTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFDLENBQUM7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VCxDQUFDO0lBQ0QsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29sb3JtYXAsIGNvbG9ybWFwRnJvbUx1dCB9IGZyb20gJ25hcGFyaS1qcyc7XG5pbXBvcnQgdHlwZSB7IEltYWdlTGF5ZXIsIExheWVyLCBSR0JBLCBTaGFwZXNMYXllciwgVmlld2VyIH0gZnJvbSAnbmFwYXJpLWpzJztcblxuaW1wb3J0IHR5cGUgeyBSZ2IgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvY29sb3JtYXAtbHV0JztcbmltcG9ydCB7IEFMTF9HRU5FUywgdHlwZSBTcGF0aWFsRGF0YVBvcnQgfSBmcm9tICcuLi8uLi9jb250cmFjdHMvcG9ydHMvc3BhdGlhbC1kYXRhLnBvcnQnO1xuaW1wb3J0IHR5cGUgeyBTcGF0aWFsVmlld1N0YXRlIH0gZnJvbSAnLi4vLi4vY29udHJhY3RzL2Rpc3BsYXktdHlwZXMnO1xuaW1wb3J0IHtcbiAgTk9fQ0FURUdPUlksIE5PX09CU0VSVkFUSU9OLCBTcGF0aWFsQm91bmRzLCBTcGF0aWFsQ29sdW1uLCBTcGF0aWFsRGF0YXNldCwgU3BhdGlhbEltYWdlUmVmLCBTcGF0aWFsUG9seWdvblRpbGUsXG4gIFNwYXRpYWxQb2x5Z29ucywgU3BhdGlhbFRyYW5zY3JpcHRDb3VudHMsIFNwYXRpYWxUcmFuc2NyaXB0U3VtbWFyeSwgU3BhdGlhbFRyYW5zY3JpcHRUaWxlLFxuICBpc0NhdGVnb3JpY2FsQ29sdW1uLFxufSBmcm9tICcuLi8uLi9jb250cmFjdHMvc3BhdGlhbC1kYXRhc2V0LmNvbnRyYWN0JztcbmltcG9ydCB7XG4gIERFRkFVTFRfQ0FURUdPUklDQUxfUEFMRVRURSwgTUlTU0lOR19DT0xPUiwgY29udHJhc3RXaW5kb3csIGx1dEZvciwgcGFyc2VIZXgsIHJlc29sdmVDYXRlZ29yeUNvbG9ycyxcbn0gZnJvbSAnLi4vLi4vc3BhdGlhbC9zcGF0aWFsLWVuY29kaW5nJztcbmltcG9ydCB7IFNwYXRpYWxTZWxlY3Rpb25NYXNrIH0gZnJvbSAnLi4vLi4vc3BhdGlhbC9zcGF0aWFsLXNlbGVjdGlvbic7XG5pbXBvcnQge1xuICBEYXRhUmVjdCwgSU5GRVJOT19TQ0FMRSwgUE9MWUdPTl9MRVZFTF9NSU5fQ0VMTF9QWCwgVHJhbnNjcmlwdEdseXBoLCBhbGxHZW5lc1BsYW4sIGNlbGxUeXBlQ29sdW1uRm9yLFxuICBjZWxsc1Nob3duLCBjb2xvckRlbnNpdHlXaW5kb3csIGRlbnNpdHlBdXRvUmFuZ2UsIGdyb3VwZWRNYXJrZXJQeCwgcXVhbnRpbGVPZiwgdGlsZXNJblJlY3RGcm9tLFxuICBkZWZhdWx0R2x5cGhGb3IsIGRpc2NyZXRlQ29sb3JtYXBTdG9wcywgZ2x5cGhPdXRsaW5lLCBnbHlwaFJpbmdzLCBwaXhlbHNQZXJEYXRhVW5pdCxcbiAgcG9seWdvbkxldmVsRm9yLCB0aWxlSWQsIHRpbGVzSW5SZWN0LCB0cmFuc2NyaXB0TGV2ZWxGb3IsIHRyYW5zY3JpcHRNYXJrZXJQeCxcbiAgdHlwaWNhbENlbGxEaWFtZXRlciwgdmlzaWJsZUFyZWEsIHZpc2libGVEYXRhUmVjdCxcbn0gZnJvbSAnLi4vLi4vc3BhdGlhbC9zcGF0aWFsLXRpbGVzJztcblxuLyoqXG4gKiBMZXZlbC1vZi1kZXRhaWwgY2VsbCBvdXRsaW5lcywgdHJhbnNjcmlwdHMgYW5kIHRyYW5zY3JpcHQgZGVuc2l0eSBmb3IgdGhlIDJEIHNwYXRpYWwgdmlldy5cbiAqXG4gKiBXSFkgQSBTRVBBUkFURSBDTEFTU1xuICogLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAqIEV2ZXJ5dGhpbmcgZWxzZSB0aGUgc3BhdGlhbCB2aWV3IGRyYXdzIGlzIGJ1aWx0IG9uY2UgcGVyIChkYXRhc2V0LCB2aWV3KSBhbmQgb25seVxuICogcmVzdHlsZWQgYWZ0ZXJ3YXJkcy4gVGhlc2UgbGF5ZXJzIGFsc28gZGVwZW5kIG9uIHRoZSBDQU1FUkE6IHdoaWNoIHRpbGVzIGFyZSBvbiBzY3JlZW5cbiAqIGFuZCB3aGljaCBsZXZlbCBvZiBkZXRhaWwgdGhlIHpvb20gY2FsbHMgZm9yLiBLZWVwaW5nIHRoYXQgbG9vcCDigJQgcGxhbiBvbiBjYW1lcmEgaWRsZSxcbiAqIGZldGNoIHRpbGVzLCBtZXJnZSwgZHJhdyDigJQgb3V0IG9mIHRoZSB2aXN1YWxpemVyIHNlcnZpY2Uga2VlcHMgYm90aCByZWFkYWJsZS5cbiAqXG4gKiBMQVlFUiBPUkRFUlxuICogLS0tLS0tLS0tLS1cbiAqIG5hcGFyaS1qcydzIGxheWVyIGxpc3QgaXMgYXBwZW5kLW9ubHkgKGFkZCAvIHJlbW92ZSAvIGNsZWFyKSwgc28gb3JkZXIgaXMga2VwdCBieVxuICogcmUtYWRkaW5nOiBjZWxsIGZpbGwsIGNlbGwgb3V0bGluZSwgdGhlIHRyYW5zY3JpcHQgZGVuc2l0eSwgdGhlbiB0cmFuc2NyaXB0cyBvbiB0b3AuXG4gKiBUaGUgc2VydmljZSdzIG9ic2VydmF0aW9uIG1hcmtlcnMgc2l0IHVuZGVyIGFsbCBvZiB0aGVtOyB3aGlsZSBvdXRsaW5lcyBhcmUgZHJhd24gdGhlXG4gKiBtYXJrZXJzIGFyZSBoaWRkZW4gKGEgY2VsbCBpcyBpdHMgb3V0bGluZSB0aGVuLCBub3QgYSBkb3QpLCBzbyB0aGUgY2VsbHMgbmV2ZXIgaGF2ZSB0b1xuICogYmUgb3JkZXJlZCBhZ2FpbnN0IHRoZW0uIFRoZSBkZW5zaXR5IGdvZXMgT1ZFUiB0aGUgbWFya2VycyBvbiBwdXJwb3NlOiB1bmRlciAxMF41XG4gKiBkb3RzIGl0IHdvdWxkIG9ubHkgc2hvdyBpbiB0aGUgZ2FwcyBiZXR3ZWVuIGNlbGxzLiB7QGxpbmsgYWZ0ZXJPYnNlcnZhdGlvbnN9IHJlc3RvcmVzXG4gKiB0aGUgb3JkZXIgYWZ0ZXIgdGhlIHNlcnZpY2UgcmUtYWRkcyBpdHMgbWFya2Vycy5cbiAqXG4gKiBPTkUgTEFZRVIgUEVSIEdST1VQXG4gKiAtLS0tLS0tLS0tLS0tLS0tLS0tXG4gKiBFYWNoIGdyb3VwIGlzIG9uZSBtZXJnZWQgbGF5ZXIgb3ZlciBldmVyeSB2aXNpYmxlIHRpbGUsIHJlYnVpbHQgd2hlbiB0aGUgdGlsZSBzZXQgb3JcbiAqIGxldmVsIGNoYW5nZXMuIFJlY29sb3VyaW5nIChhIG5ldyBjZWxsLXR5cGUgY29sdW1uLCBhIHNlbGVjdGlvbikgb25seSByZXdyaXRlcyB0aGVcbiAqIHBlci1zaGFwZSB2YWx1ZXMg4oCUIHRoZSBnZW9tZXRyeSBpcyBub3QgcmUtZXhwYW5kZWQuXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgU3BhdGlhbFRpbGVIb3N0IHtcbiAgLyoqIExhdGVzdCBkYXRhc2V0L3ZpZXcvc2VsZWN0aW9uLCBhcyB0aGUgc3BhdGlhbCBzdWJzY3JpcHRpb24gc2F3IHRoZW0uICovXG4gIGxhdGVzdCgpOiBbU3BhdGlhbERhdGFzZXQgfCBudWxsLCBTcGF0aWFsVmlld1N0YXRlLCBTcGF0aWFsU2VsZWN0aW9uTWFza10gfCBudWxsO1xuICAvKiogQ2FudmFzIHNpemUgaW4gQ1NTIHBpeGVscy4gKi9cbiAgY2FudmFzU2l6ZSgpOiBbbnVtYmVyLCBudW1iZXJdO1xuICAvKiogVGhlIGNvbnRpbnVvdXMgTFVUIHRoZSB2aWV3IGlzIHVzaW5nIChzbyBjZWxscyBjb2xvdXJlZCBieSBhIGdlbmUgbWF0Y2ggdGhlIG1hcmtlcnMpLiAqL1xuICBjb250aW51b3VzTHV0KHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUpOiBSZ2JbXTtcbiAgLyoqIE91dGxpbmVzIGFwcGVhcmVkIG9yIGRpc2FwcGVhcmVkOiB0aGUgbWFya2VycycgdmlzaWJpbGl0eSBmb2xsb3dzLiAqL1xuICBwb2x5Z29uc1Nob3duQ2hhbmdlZChzaG93bjogYm9vbGVhbik6IHZvaWQ7XG4gIC8qKiBUaGUgZGVuc2l0eSB3aW5kb3cgY2hhbmdlZCAoYXV0by1kZXJpdmVkIG9yIHNldCkuICovXG4gIGRlbnNpdHlDaGFuZ2VkPyhzdGF0czogeyBsbzogbnVtYmVyOyBoaTogbnVtYmVyOyBtYXg6IG51bWJlciB9KTogdm9pZDtcbiAgLyoqIEVzdGltYXRlZCB0cmFuc2NyaXB0cyBpbiB2aWV3IGZvciB0aGUgY3VycmVudCBzZWxlY3Rpb24sIGFnYWluc3QgdGhlIGJ1ZGdldC4gKi9cbiAgZXN0aW1hdGVDaGFuZ2VkPyhlc3RpbWF0ZTogVHJhbnNjcmlwdEVzdGltYXRlIHwgbnVsbCk6IHZvaWQ7XG59XG5cbi8qKiBYZW5pdW0gRXhwbG9yZXIncyBcIkVzdGltYXRlZCBUcmFuc2NyaXB0IFBvaW50c1wiLiAqL1xuZXhwb3J0IGludGVyZmFjZSBUcmFuc2NyaXB0RXN0aW1hdGUge1xuICAvKiogVHJhbnNjcmlwdHMgb2YgdGhlIHZpc2libGUgZ2VuZXMgZXN0aW1hdGVkIHRvIGJlIGluIHZpZXcuICovXG4gIHBvaW50czogbnVtYmVyO1xuICAvKiogVGhlIG1hcmtlciBidWRnZXQuICovXG4gIG1heDogbnVtYmVyO1xufVxuXG50eXBlIEdyb3VwID0gJ2RlbnNpdHknIHwgJ2NlbGxGaWxsJyB8ICdjZWxsT3V0bGluZScgfCAnbnVjbGV1c091dGxpbmUnIHwgJ3RyYW5zY3JpcHRzJyB8ICd0cmFuc2NyaXB0T3V0bGluZSc7XG5jb25zdCBPUkRFUjogR3JvdXBbXSA9IFtcbiAgJ2NlbGxGaWxsJywgJ2NlbGxPdXRsaW5lJywgJ251Y2xldXNPdXRsaW5lJywgJ2RlbnNpdHknLCAndHJhbnNjcmlwdHMnLCAndHJhbnNjcmlwdE91dGxpbmUnLFxuXTtcblxuLyoqIFRyYW5zY3JpcHRzIGRyYXduIGF0IG9uY2UuIFBhc3QgdGhpcyBhIHNjcmVlbiBpcyBzb2xpZCBjb2xvdXIgYW55d2F5OyB0aGUgbGV2ZWxcbiAqICBwb2xpY3kga2VlcHMgYSBub3JtYWwgdmlldyBmYXIgYmVsb3cgaXQuICovXG5jb25zdCBNQVhfVFJBTlNDUklQVFMgPSA0MDBfMDAwO1xuY29uc3QgTUFYX0NFTExfVElMRVMgPSA0ODtcbmNvbnN0IE1BWF9UUkFOU0NSSVBUX1RJTEVTID0gMzY7XG5jb25zdCBNQVhfQklOX1RJTEVTID0gNjQ7XG5cbi8qKiBBIHRyYW5zY3JpcHQgZmV0Y2ggdGhlIHBsYW5uZXIgY2FuIGtleSBiZWZvcmUgcnVubmluZy4gKi9cbmludGVyZmFjZSBUcmFuc2NyaXB0Sm9iIHtcbiAgLyoqIFdoYXQgb25lIGVudHJ5IGlzIOKAlCBkZWNpZGVzIHdoYXQgaG92ZXJpbmcgaXQgc2F5cy4gKi9cbiAga2luZDogJ2dlbmVzJyB8ICdpbmRpdmlkdWFsJyB8ICdiaW5zJztcbiAgLyoqIEZvciBiaW5zOiB0aGVpciBzaXplIGFuZCBncmlkIG9yaWdpbiwgc28gYSBob3ZlcmVkIGJpbidzIHNxdWFyZSBjYW4gYmUgcmVjb3ZlcmVkLiAqL1xuICBiaW4/OiB7IHNpemU6IG51bWJlcjsgb3JpZ2luOiBbbnVtYmVyLCBudW1iZXJdIH07XG4gIC8qKiBJZGVudGlmaWVzIHdoYXQgd2lsbCBiZSBkcmF3biwgc28gYW4gdW5jaGFuZ2VkIHBsYW4gaXMgYSBuby1vcC4gKi9cbiAga2V5OiBzdHJpbmc7XG4gIC8qKiBGZXRjaCBhbmQgbWVyZ2U7IGBweGAgaXMgZWFjaCBlbnRyeSdzIG1hcmtlciBkaWFtZXRlciBpbiBzY3JlZW4gcGl4ZWxzLiBBIGpvYiBtYXlcbiAgICogIHN3aXRjaCB0byBhbm90aGVyIGtpbmQgb25jZSBpdCBzZWVzIHRoZSBkYXRhIChpbmRpdmlkdWFsIOKGkiBiaW5zKTsgaXQgdGhlbiBzYXlzIHNvLiAqL1xuICBsb2FkKCk6IFByb21pc2U8VHJhbnNjcmlwdExvYWQ+O1xufVxuXG5pbnRlcmZhY2UgVHJhbnNjcmlwdExvYWQge1xuICBtZXJnZWQ6IFNwYXRpYWxUcmFuc2NyaXB0VGlsZTtcbiAgcHg6IEZsb2F0MzJBcnJheTtcbiAga2luZD86IFRyYW5zY3JpcHRKb2JbJ2tpbmQnXTtcbiAgYmluPzogVHJhbnNjcmlwdEpvYlsnYmluJ107XG59XG5cbi8qKiBXaGVyZSBhIGxheWVyIHNpdHMgaW4gd29ybGQgc3BhY2U6IHRoZSBkYXRhc2V0J3MgYWZmaW5lIG9udG8gaXRzIHRpc3N1ZSBpbWFnZS4gKi9cbmludGVyZmFjZSBQbGFjZW1lbnQgeyBzY2FsZTogW251bWJlciwgbnVtYmVyXTsgdHJhbnNsYXRlOiBbbnVtYmVyLCBudW1iZXJdIH1cblxuLyoqIFRyYW5zY3JpcHQgY29sb3VyczogcGVyLWVudHJ5IFJHQkEgZm9yIHBvaW50cywgdmFsdWVzICsgY29sb3JtYXAgZm9yIHNoYXBlcy4gKi9cbmludGVyZmFjZSBUcmFuc2NyaXB0RmFjZXMgeyByZ2JhOiBSR0JBW107IHZhbHVlczogRmxvYXQzMkFycmF5OyBjb2xvcm1hcDogQ29sb3JtYXAgfVxuY29uc3QgQ0FNRVJBX0lETEVfTVMgPSAxMjA7XG4vKiogRmlyc3QgcmV0cnkgb2YgYSB2aWV3IHdpdGggYSBmYWlsZWQgdGlsZTsgZG91YmxlcyBlYWNoIHRpbWUsIHVwIHRvIE1BWF9USUxFX1JFVFJJRVMuICovXG5jb25zdCBUSUxFX1JFVFJZX01TID0gMTAwMDtcbmNvbnN0IE1BWF9USUxFX1JFVFJJRVMgPSAzO1xuXG5jb25zdCBVTkFTU0lHTkVEX1JHQkE6IFJHQkEgPSBbMC42MiwgMC42MiwgMC42MiwgMC41NV07XG5cbmV4cG9ydCBjbGFzcyBOYXBhcmlTcGF0aWFsVGlsZUxheWVycyB7XG4gIHByaXZhdGUgdmlld2VyOiBWaWV3ZXIgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBjYW1lcmFPZmY6ICgoKSA9PiB2b2lkKSB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIHRpbWVyOiBSZXR1cm5UeXBlPHR5cGVvZiBzZXRUaW1lb3V0PiB8IG51bGwgPSBudWxsO1xuICAvKiogU2V0IHdoZW4gYSB0aWxlIG9mIHRoZSBjdXJyZW50IHBsYW4gZmFpbGVkIHRvIGxvYWQgKHNlZSBmZXRjaEFsbCkuICovXG4gIHByaXZhdGUgcGxhbkluY29tcGxldGUgPSBmYWxzZTtcbiAgLyoqIENvbnNlY3V0aXZlIHJldHJpZXMgb2YgYW4gaW5jb21wbGV0ZSB2aWV3LiAqL1xuICBwcml2YXRlIHRpbGVSZXRyaWVzID0gMDtcbiAgcHJpdmF0ZSB0b2tlbiA9IDA7XG4gIHByaXZhdGUgcmVhZG9ubHkgbGF5ZXJzID0gbmV3IE1hcDxHcm91cCwgTGF5ZXI+KCk7XG4gIC8qKiBXaGF0IGVhY2ggZ3JvdXAgY3VycmVudGx5IHNob3dzLCBzbyBhbiB1bmNoYW5nZWQgcGxhbiBpcyBhIG5vLW9wLiAqL1xuICBwcml2YXRlIHJlYWRvbmx5IGtleXMgPSBuZXcgTWFwPEdyb3VwLCBzdHJpbmc+KCk7XG4gIHByaXZhdGUgcG9seWdvbnNTaG93biA9IGZhbHNlO1xuICAvKiogUmluZ3MgY3VycmVudGx5IGRyYXduIGFuZCB0aGUgKGRhdGFzZXQsIHNldCwgdGlsZXMpIHRoZXkgY2FtZSBmcm9tLiAqL1xuICBwcml2YXRlIGN1cnJlbnRSaW5nczogU3BhdGlhbFBvbHlnb25UaWxlIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgY2VsbEdlb21ldHJ5S2V5OiBzdHJpbmcgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBjdXJyZW50TnVjbGVpOiBTcGF0aWFsUG9seWdvblRpbGUgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBjZWxsU3R5bGVLZXk6IHN0cmluZyB8IG51bGwgPSBudWxsO1xuICAvKiogU2VsZWN0aW9uIGlkZW50aXR5IOKGkiByZXZpc2lvbiwgc28gYSBjaGFuZ2Uga2V5IGNhbiBuYW1lIGEgc2VsZWN0aW9uIGNoZWFwbHkuICovXG4gIHByaXZhdGUgbGFzdFNlbGVjdGlvbjogU3BhdGlhbFNlbGVjdGlvbk1hc2sgfCBudWxsID0gbnVsbDtcbiAgcHJpdmF0ZSBzZWxlY3Rpb25SZXZpc2lvbiA9IDA7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBwb3J0OiBTcGF0aWFsRGF0YVBvcnQsIHByaXZhdGUgcmVhZG9ubHkgaG9zdDogU3BhdGlhbFRpbGVIb3N0KSB7fVxuXG4gIC8vIOKUgOKUgCBsaWZlY3ljbGUg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgYXR0YWNoKHZpZXdlcjogVmlld2VyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMudmlld2VyID09PSB2aWV3ZXIpIHJldHVybjtcbiAgICB0aGlzLmRldGFjaCgpO1xuICAgIHRoaXMudmlld2VyID0gdmlld2VyO1xuICAgIHRoaXMuY2FtZXJhT2ZmID0gdmlld2VyLmNhbWVyYS5jaGFuZ2VkLmNvbm5lY3QoKCkgPT4gdGhpcy5zY2hlZHVsZSgpKTtcbiAgfVxuXG4gIC8qKiBXaGV0aGVyIGBsYXllcmAgaXMgb25lIG9mIHRoZSBvdmVybGF5cyBkcmF3biBoZXJlIChkZW5zaXR5LCBjZWxscywgdHJhbnNjcmlwdHMpLiAqL1xuICBvd25zKGxheWVyOiBMYXllcik6IGJvb2xlYW4ge1xuICAgIGZvciAoY29uc3QgbCBvZiB0aGlzLmxheWVycy52YWx1ZXMoKSkgaWYgKGwgPT09IGxheWVyKSByZXR1cm4gdHJ1ZTtcbiAgICByZXR1cm4gZmFsc2U7XG4gIH1cblxuICBkZXRhY2goKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaG92ZXJUaW1lcikgY2xlYXJUaW1lb3V0KHRoaXMuaG92ZXJUaW1lcik7XG4gICAgdGhpcy5ob3ZlclRpbWVyID0gbnVsbDtcbiAgICB0aGlzLmRyYXduID0gbnVsbDtcbiAgICB0aGlzLmNhbWVyYU9mZj8uKCk7XG4gICAgdGhpcy5jYW1lcmFPZmYgPSBudWxsO1xuICAgIGlmICh0aGlzLnRpbWVyKSBjbGVhclRpbWVvdXQodGhpcy50aW1lcik7XG4gICAgdGhpcy50aW1lciA9IG51bGw7XG4gICAgdGhpcy50b2tlbisrO1xuICAgIHRoaXMudGlsZVJldHJpZXMgPSAwO1xuICAgIGlmICh0aGlzLnZpZXdlcikge1xuICAgICAgZm9yIChjb25zdCBsYXllciBvZiB0aGlzLmxheWVycy52YWx1ZXMoKSkge1xuICAgICAgICBpZiAodGhpcy52aWV3ZXIubGF5ZXJzLml0ZW1zLmluY2x1ZGVzKGxheWVyKSkgdGhpcy52aWV3ZXIubGF5ZXJzLnJlbW92ZShsYXllcik7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMubGF5ZXJzLmNsZWFyKCk7XG4gICAgdGhpcy5rZXlzLmNsZWFyKCk7XG4gICAgdGhpcy5zZXRQb2x5Z29uc1Nob3duKGZhbHNlKTtcbiAgICB0aGlzLnZpZXdlciA9IG51bGw7XG4gIH1cblxuICAvKiogVHJ1ZSB3aGlsZSBvdXRsaW5lcyBhcmUgb24gc2NyZWVuIOKAlCB0aGUgc2VydmljZSBoaWRlcyBpdHMgZG90cyB0aGVuLiAqL1xuICBnZXQgb3V0bGluZXNTaG93bigpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5wb2x5Z29uc1Nob3duO1xuICB9XG5cbiAgLyoqIERhdGFzZXQsIHZpZXcgb3Igc2VsZWN0aW9uIGNoYW5nZWQ6IHJlLXBsYW4gbm93IHJhdGhlciB0aGFuIG9uIGNhbWVyYSBpZGxlLiAqL1xuICByZWZyZXNoKCk6IHZvaWQge1xuICAgIHRoaXMuc2NoZWR1bGUoMCk7XG4gIH1cblxuICAvKiogQ2FsbGVkIHJpZ2h0IGFmdGVyIHRoZSBzZXJ2aWNlIGFkZHMgaXRzIG1hcmtlciBsYXllcjogZXZlcnl0aGluZyBnb2VzIGJhY2sgb24gdG9wLiAqL1xuICBhZnRlck9ic2VydmF0aW9ucygpOiB2b2lkIHtcbiAgICBjb25zdCB2ID0gdGhpcy52aWV3ZXI7XG4gICAgaWYgKCF2KSByZXR1cm47XG4gICAgZm9yIChjb25zdCBnIG9mIE9SREVSKSB7XG4gICAgICBjb25zdCBsYXllciA9IHRoaXMubGF5ZXJzLmdldChnKTtcbiAgICAgIGlmICghbGF5ZXIpIGNvbnRpbnVlO1xuICAgICAgaWYgKHYubGF5ZXJzLml0ZW1zLmluY2x1ZGVzKGxheWVyKSkgdi5sYXllcnMucmVtb3ZlKGxheWVyKTtcbiAgICAgIHYubGF5ZXJzLmFkZChsYXllcik7XG4gICAgfVxuICB9XG5cbiAgLy8g4pSA4pSAIHBsYW5uaW5nIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIHByaXZhdGUgc2NoZWR1bGUoZGVsYXkgPSBDQU1FUkFfSURMRV9NUyk6IHZvaWQge1xuICAgIGlmICh0aGlzLnRpbWVyKSBjbGVhclRpbWVvdXQodGhpcy50aW1lcik7XG4gICAgdGhpcy50aW1lciA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy50aW1lciA9IG51bGw7XG4gICAgICB2b2lkIHRoaXMucGxhbigpO1xuICAgIH0sIGRlbGF5KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgcGxhbigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB2aWV3ZXIgPSB0aGlzLnZpZXdlcjtcbiAgICBjb25zdCBsYXRlc3QgPSB0aGlzLmhvc3QubGF0ZXN0KCk7XG4gICAgaWYgKCF2aWV3ZXIgfHwgIWxhdGVzdCkgcmV0dXJuO1xuICAgIGNvbnN0IFtkYXRhc2V0LCB2aWV3LCBzZWxlY3Rpb25dID0gbGF0ZXN0O1xuICAgIGNvbnN0IHRva2VuID0gKyt0aGlzLnRva2VuO1xuICAgIGNvbnN0IHN0YWxlID0gKCkgPT4gdG9rZW4gIT09IHRoaXMudG9rZW4gfHwgdGhpcy52aWV3ZXIgIT09IHZpZXdlcjtcbiAgICB0aGlzLnBsYW5JbmNvbXBsZXRlID0gZmFsc2U7XG5cbiAgICBpZiAoIWRhdGFzZXQpIHtcbiAgICAgIGZvciAoY29uc3QgZyBvZiBPUkRFUikgdGhpcy5kcm9wKGcpO1xuICAgICAgdGhpcy5kcm9wQ2VsbHMoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgW3csIGhdID0gdGhpcy5ob3N0LmNhbnZhc1NpemUoKTtcbiAgICBjb25zdCByZWYgPSBkYXRhc2V0LmltYWdlUmVmO1xuICAgIGNvbnN0IHJlY3QgPSB2aXNpYmxlRGF0YVJlY3Qodmlld2VyLmNhbWVyYS5jZW50ZXIsIHZpZXdlci5jYW1lcmEuem9vbSwgdywgaCwgcmVmKTtcbiAgICBjb25zdCBweFBlclVuaXQgPSBwaXhlbHNQZXJEYXRhVW5pdCh2aWV3ZXIuY2FtZXJhLnpvb20sIHJlZik7XG4gICAgaWYgKCFyZWN0KSByZXR1cm47XG5cbiAgICB2b2lkIHRoaXMucGxhbkVzdGltYXRlKGRhdGFzZXQsIHZpZXcsIHZpZXdlciwgdywgaCwgc3RhbGUpO1xuICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIHRoaXMucGxhbkRlbnNpdHkoZGF0YXNldCwgdmlldywgc3RhbGUpLFxuICAgICAgdGhpcy5wbGFuQ2VsbHMoZGF0YXNldCwgdmlldywgc2VsZWN0aW9uLCByZWN0LCBweFBlclVuaXQsIHN0YWxlKSxcbiAgICAgIHRoaXMucGxhblRyYW5zY3JpcHRzKGRhdGFzZXQsIHZpZXcsIHJlY3QsIHB4UGVyVW5pdCwgc3RhbGUpLFxuICAgIF0pO1xuICAgIGlmIChzdGFsZSgpKSByZXR1cm47XG4gICAgLy8gQSB0aWxlIHRoYXQgZmFpbGVkIGxlZnQgYSBob2xlIHRoZSBjYWNoZSBrZXlzIGRvIG5vdCByZWNvcmQsIHNvIHRyeSB0aGUgc2FtZSB2aWV3XG4gICAgLy8gYWdhaW4sIGJhY2tpbmcgb2ZmLCBhIGJvdW5kZWQgbnVtYmVyIG9mIHRpbWVzLlxuICAgIGlmICghdGhpcy5wbGFuSW5jb21wbGV0ZSkge1xuICAgICAgdGhpcy50aWxlUmV0cmllcyA9IDA7XG4gICAgfSBlbHNlIGlmICh0aGlzLnRpbGVSZXRyaWVzIDwgTUFYX1RJTEVfUkVUUklFUykge1xuICAgICAgdGhpcy5zY2hlZHVsZShUSUxFX1JFVFJZX01TICogMiAqKiB0aGlzLnRpbGVSZXRyaWVzKyspO1xuICAgIH1cbiAgfVxuXG4gIC8vIOKUgOKUgCBjZWxscyDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuICBwcml2YXRlIGFzeW5jIHBsYW5DZWxscyhcbiAgICBkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCwgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSwgc2VsZWN0aW9uOiBTcGF0aWFsU2VsZWN0aW9uTWFzayxcbiAgICByZWN0OiBEYXRhUmVjdCwgcHhQZXJVbml0OiBudW1iZXIsIHN0YWxlOiAoKSA9PiBib29sZWFuLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCB0aWxlZCA9IGRhdGFzZXQucG9seWdvblRpbGVzO1xuICAgIGNvbnN0IHdob2xlID0gIXRpbGVkICYmIGRhdGFzZXQucG9seWdvbnMgJiYgdGhpcy5wb3J0LmdldFBvbHlnb25zO1xuICAgIGlmICghY2VsbHNTaG93bihkYXRhc2V0LCB2aWV3KSB8fCAoIXRpbGVkICYmICF3aG9sZSkpIHtcbiAgICAgIHRoaXMuZHJvcENlbGxzKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGRpYW1ldGVyID0gdHlwaWNhbENlbGxEaWFtZXRlcihkYXRhc2V0Lm9ic2VydmF0aW9ucy5yYWRpdXMpO1xuICAgIC8vIFdob2xlLWRhdGFzZXQgcmluZ3MgaGF2ZSBvbmUgbGV2ZWwgYW5kIG5vIGNvYXJzZXIgZmFsbGJhY2ssIHNvIHRoZXkgYXJlIGRyYXduIGFzXG4gICAgLy8gc29vbiBhcyBhIGNlbGwgaXMgYmlnIGVub3VnaCB0byByZWFkIGFzIGEgc2hhcGUgcmF0aGVyIHRoYW4gYSBkb3QuXG4gICAgY29uc3QgbGV2ZWwgPSB0aWxlZFxuICAgICAgPyBwb2x5Z29uTGV2ZWxGb3IocHhQZXJVbml0LCBkaWFtZXRlciwgdGlsZWQubGV2ZWxzLmxlbmd0aClcbiAgICAgIDogKHB4UGVyVW5pdCAqIGRpYW1ldGVyID49IFBPTFlHT05fTEVWRUxfTUlOX0NFTExfUFhbMl0gPyAwIDogLTEpO1xuICAgIGlmIChsZXZlbCA8IDApIHtcbiAgICAgIHRoaXMuZHJvcENlbGxzKCk7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gR3JvdXBzIHN3aXRjaGVkIG9mZiBpbiB0aGUgbGlzdDogdGhlaXIgY2VsbHMgYXJlIGxlZnQgb3V0IG9mIHRoZSBnZW9tZXRyeS5cbiAgICBjb25zdCBoaWRkZW4gPSBhd2FpdCB0aGlzLmhpZGRlbkNvZGVzKGRhdGFzZXQsIHZpZXcpO1xuICAgIGlmIChzdGFsZSgpKSByZXR1cm47XG4gICAgY29uc3QgZ2VvbWV0cnkgPSBhd2FpdCB0aGlzLmNlbGxHZW9tZXRyeShkYXRhc2V0LCB2aWV3LCByZWN0LCBsZXZlbCwgaGlkZGVuLCBzdGFsZSk7XG4gICAgaWYgKCFnZW9tZXRyeSkgcmV0dXJuO1xuICAgIGNvbnN0IHsgcmluZ3MsIG51Y2xlaSwgZ2VvbWV0cnlLZXkgfSA9IGdlb21ldHJ5O1xuXG4gICAgY29uc3QgZ2VvbWV0cnlDaGFuZ2VkID0gZ2VvbWV0cnlLZXkgIT09IHRoaXMuY2VsbEdlb21ldHJ5S2V5O1xuICAgIGNvbnN0IHN0eWxlS2V5ID0gW1xuICAgICAgZ2VvbWV0cnlLZXksIHZpZXcuY2VsbENvbG9yTW9kZSwgdmlldy5jZWxsQ29sb3JHZW5lLCB2aWV3LmNlbGxTaW5nbGVDb2xvcixcbiAgICAgIHRoaXMuY2VsbFR5cGVDb2x1bW5OYW1lKGRhdGFzZXQsIHZpZXcpLFxuICAgICAgdGhpcy5zZWxlY3Rpb25SZXYoc2VsZWN0aW9uKSwgdmlldy5sb2dTY2FsZSwgdmlldy5wZXJjZW50aWxlQ2xpcC5qb2luKCksXG4gICAgICBKU09OLnN0cmluZ2lmeSh2aWV3LmNvbnRpbnVvdXNDb2xvcm1hcCksIHZpZXcuY2VsbERyYXcsIHZpZXcuY2VsbE9wYWNpdHksXG4gICAgXS5qb2luKCd8Jyk7XG4gICAgY29uc3QgcHJlc2VudCA9IFsnY2VsbEZpbGwnLCAnY2VsbE91dGxpbmUnLCAnbnVjbGV1c091dGxpbmUnXS5zb21lKChnKSA9PiB7XG4gICAgICBjb25zdCBsID0gdGhpcy5sYXllcnMuZ2V0KGcgYXMgR3JvdXApO1xuICAgICAgcmV0dXJuIGwgJiYgdGhpcy52aWV3ZXIhLmxheWVycy5pdGVtcy5pbmNsdWRlcyhsKTtcbiAgICB9KTtcbiAgICBpZiAoIWdlb21ldHJ5Q2hhbmdlZCAmJiBzdHlsZUtleSA9PT0gdGhpcy5jZWxsU3R5bGVLZXkgJiYgcHJlc2VudCkge1xuICAgICAgdGhpcy5zZXRQb2x5Z29uc1Nob3duKHRydWUpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBjb2xvcnMgPSBhd2FpdCB0aGlzLmNlbGxDb2xvcnMoZGF0YXNldCwgdmlldywgc2VsZWN0aW9uLCByaW5ncy5vYnNlcnZhdGlvbik7XG4gICAgaWYgKHN0YWxlKCkpIHJldHVybjtcblxuICAgIHRoaXMuY3VycmVudFJpbmdzID0gcmluZ3M7XG4gICAgdGhpcy5jdXJyZW50TnVjbGVpID0gbnVjbGVpO1xuICAgIC8vIEEgZ2VvbWV0cnkgbWlzc2luZyBhIGZhaWxlZCB0aWxlIGlzIGRyYXduIGJ1dCBub3QgcmVtZW1iZXJlZCwgc28gdGhlIHJldHJ5IHJlZmV0Y2hlcyBpdC5cbiAgICB0aGlzLmNlbGxHZW9tZXRyeUtleSA9IHRoaXMucGxhbkluY29tcGxldGUgPyBudWxsIDogZ2VvbWV0cnlLZXk7XG4gICAgdGhpcy5jZWxsU3R5bGVLZXkgPSBzdHlsZUtleTtcbiAgICBjb25zdCByZWYgPSBkYXRhc2V0LmltYWdlUmVmO1xuICAgIGNvbnN0IGNvbW1vbiA9IHsgc2NhbGU6IHJlZj8uc2NhbGUgPz8gWzEsIDFdLCB0cmFuc2xhdGU6IHJlZj8udHJhbnNsYXRlID8/IFswLCAwXSB9IGFzIGNvbnN0O1xuICAgIGNvbnN0IGZpbGwgPSB2aWV3LmNlbGxEcmF3ICE9PSAnb3V0bGluZSc7XG4gICAgY29uc3Qgb3V0bGluZSA9IHZpZXcuY2VsbERyYXcgIT09ICdmaWxsJztcblxuICAgIHRoaXMudXBzZXJ0U2hhcGVzKCdjZWxsRmlsbCcsIGZpbGwsIGdlb21ldHJ5Q2hhbmdlZCwgcmluZ3MsIHtcbiAgICAgIG5hbWU6ICdjZWxscycsIGRyYXc6ICdmaWxsJywgb3BhY2l0eTogdmlldy5jZWxsT3BhY2l0eSwgLi4uY29sb3JzLCAuLi5jb21tb24sXG4gICAgfSk7XG4gICAgdGhpcy51cHNlcnRTaGFwZXMoJ2NlbGxPdXRsaW5lJywgb3V0bGluZSwgZ2VvbWV0cnlDaGFuZ2VkLCByaW5ncywgZmlsbFxuICAgICAgLy8gT3ZlciBhIGZpbGwsIGEgZGFyayBvdXRsaW5lIHNlcGFyYXRlcyBuZWlnaGJvdXJzIG9mIHRoZSBzYW1lIHR5cGUuXG4gICAgICA/IHsgbmFtZTogJ2NlbGwgb3V0bGluZXMnLCBkcmF3OiAnb3V0bGluZScsIGNvbG9yOiBbMC4wOCwgMC4wOCwgMC4xLCAxXSwgb3BhY2l0eTogMC43LCAuLi5jb21tb24gfVxuICAgICAgOiB7IG5hbWU6ICdjZWxsIG91dGxpbmVzJywgZHJhdzogJ291dGxpbmUnLCBvcGFjaXR5OiAxLCAuLi5jb2xvcnMsIC4uLmNvbW1vbiB9KTtcbiAgICAvLyBcIkJvdGhcIjogbnVjbGVpIG91dGxpbmVkIG92ZXIgdGhlIGNlbGxzLCBsaWdodCBzbyB0aGV5IHJlYWQgYWdhaW5zdCBhbnkgZmlsbC5cbiAgICBpZiAobnVjbGVpKSB7XG4gICAgICB0aGlzLnVwc2VydFNoYXBlcygnbnVjbGV1c091dGxpbmUnLCB0cnVlLCBnZW9tZXRyeUNoYW5nZWQsIG51Y2xlaSwge1xuICAgICAgICBuYW1lOiAnbnVjbGV1cyBvdXRsaW5lcycsIGRyYXc6ICdvdXRsaW5lJywgY29sb3I6IFswLjk1LCAwLjk1LCAwLjk4LCAxXSwgb3BhY2l0eTogMC44LCAuLi5jb21tb24sXG4gICAgICB9KTtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5kcm9wKCdudWNsZXVzT3V0bGluZScpO1xuICAgIH1cbiAgICB0aGlzLnNldFBvbHlnb25zU2hvd24odHJ1ZSk7XG4gIH1cblxuICBwcml2YXRlIHNlbGVjdGlvblJldihzZWxlY3Rpb246IFNwYXRpYWxTZWxlY3Rpb25NYXNrKTogbnVtYmVyIHtcbiAgICBpZiAoc2VsZWN0aW9uICE9PSB0aGlzLmxhc3RTZWxlY3Rpb24pIHtcbiAgICAgIHRoaXMubGFzdFNlbGVjdGlvbiA9IHNlbGVjdGlvbjtcbiAgICAgIHRoaXMuc2VsZWN0aW9uUmV2aXNpb24rKztcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc2VsZWN0aW9uUmV2aXNpb247XG4gIH1cblxuICAvKiogUGVyLXNoYXBlIHZhbHVlcyArIGNvbG9ybWFwIGZvciB0aGUgcmluZ3MnIG93bmVycy4gKi9cbiAgLyoqXG4gICAqIFBlci1zaGFwZSB2YWx1ZXMgKyBjb2xvcm1hcCBmb3IgdGhlIHJpbmdzJyBvd25lcnMsIGJ5IHRoZSB2aWV3J3MgY2VsbC1jb2xvdXIgbW9kZVxuICAgKiAoWGVuaXVtIEV4cGxvcmVyJ3MgXCJDZWxsIENvbG9yXCIpLiBBIHNlbGVjdGlvbiBtdXRlcyB3aGF0IGl0IGxlYXZlcyBvdXQuXG4gICAqL1xuICBwcml2YXRlIGFzeW5jIGNlbGxDb2xvcnMoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsIHNlbGVjdGlvbjogU3BhdGlhbFNlbGVjdGlvbk1hc2ssXG4gICAgb3duZXJzOiBVaW50MzJBcnJheSxcbiAgKTogUHJvbWlzZTx7IHZhbHVlcz86IEZsb2F0MzJBcnJheTsgY29sb3JtYXA/OiBDb2xvcm1hcDsgY29udHJhc3RMaW1pdHM/OiBbbnVtYmVyLCBudW1iZXJdOyBjb2xvcj86IFJHQkEgfT4ge1xuICAgIGNvbnN0IG11dGVkID0gc2VsZWN0aW9uLmNvdW50ID4gMCA/IHNlbGVjdGlvbi5tYXNrIDogbnVsbDtcbiAgICBjb25zdCBtb2RlID0gdmlldy5jZWxsQ29sb3JNb2RlO1xuXG4gICAgaWYgKG1vZGUgPT09ICdzaW5nbGUnKSB7XG4gICAgICBjb25zdCBbciwgZywgYl0gPSBwYXJzZUhleCh2aWV3LmNlbGxTaW5nbGVDb2xvcik7XG4gICAgICByZXR1cm4geyBjb2xvcjogW3IgLyAyNTUsIGcgLyAyNTUsIGIgLyAyNTUsIDFdIH07XG4gICAgfVxuXG4gICAgY29uc3QgY29udGludW91cyA9IGFzeW5jIChyYXc6IEZsb2F0MzJBcnJheSwgbG9nOiBib29sZWFuKSA9PiB7XG4gICAgICBjb25zdCB2YWx1ZXMgPSBuZXcgRmxvYXQzMkFycmF5KG93bmVycy5sZW5ndGgpO1xuICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBvd25lcnMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgY29uc3QgdiA9IHJhd1tvd25lcnNbaV1dID8/IE5hTjtcbiAgICAgICAgdmFsdWVzW2ldID0gbG9nID8gTWF0aC5sb2cxcChNYXRoLm1heCgwLCB2KSkgOiB2O1xuICAgICAgfVxuICAgICAgY29uc3QgW2xvLCBoaV0gPSBjb250cmFzdFdpbmRvdyhcbiAgICAgICAgbG9nID8gcmF3Lm1hcCgodikgPT4gTWF0aC5sb2cxcChNYXRoLm1heCgwLCB2KSkpIDogcmF3LFxuICAgICAgICB2aWV3LnBlcmNlbnRpbGVDbGlwWzBdLCB2aWV3LnBlcmNlbnRpbGVDbGlwWzFdLFxuICAgICAgKTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHZhbHVlcyxcbiAgICAgICAgY29sb3JtYXA6IGNvbG9ybWFwRnJvbUx1dCgnc3BhdGlhbC1jb250aW51b3VzJywgdGhpcy5ob3N0LmNvbnRpbnVvdXNMdXQodmlldykpLFxuICAgICAgICBjb250cmFzdExpbWl0czogW2xvLCBoaV0gYXMgW251bWJlciwgbnVtYmVyXSxcbiAgICAgIH07XG4gICAgfTtcbiAgICBpZiAobW9kZSA9PT0gJ2dlbmUnICYmIHZpZXcuY2VsbENvbG9yR2VuZSkge1xuICAgICAgcmV0dXJuIGNvbnRpbnVvdXMoYXdhaXQgdGhpcy5wb3J0LmdldEZlYXR1cmVWZWN0b3Iodmlldy5jZWxsQ29sb3JHZW5lKSwgdHJ1ZSk7XG4gICAgfVxuICAgIGlmIChtb2RlID09PSAndHJhbnNjcmlwdERlbnNpdHknICYmIGRhdGFzZXQuY29sdW1ucy5zb21lKChjKSA9PiBjLm5hbWUgPT09ICd0cmFuc2NyaXB0X2RlbnNpdHknKSkge1xuICAgICAgY29uc3QgY29sdW1uID0gYXdhaXQgdGhpcy5wb3J0LmdldENvbHVtbigndHJhbnNjcmlwdF9kZW5zaXR5Jyk7XG4gICAgICBpZiAoIWlzQ2F0ZWdvcmljYWxDb2x1bW4oY29sdW1uKSkgcmV0dXJuIGNvbnRpbnVvdXMoY29sdW1uLnZhbHVlcywgZmFsc2UpO1xuICAgIH1cblxuICAgIGNvbnN0IG5hbWUgPSBtb2RlID09PSAnc2VnbWVudGF0aW9uJyAmJiBkYXRhc2V0LmNvbHVtbnMuc29tZSgoYykgPT4gYy5uYW1lID09PSAnc2VnbWVudGF0aW9uX21ldGhvZCcpXG4gICAgICA/ICdzZWdtZW50YXRpb25fbWV0aG9kJ1xuICAgICAgOiB0aGlzLmNlbGxUeXBlQ29sdW1uTmFtZShkYXRhc2V0LCB2aWV3KTtcbiAgICBjb25zdCBjb2RlcyA9IG5hbWUgPyBhd2FpdCB0aGlzLmNhdGVnb3JpY2FsQ29kZXMobmFtZSkgOiBudWxsO1xuICAgIGNvbnN0IHsgY29sb3JtYXAsIHZhbHVlT2YgfSA9IHRoaXMuY2F0ZWdvcmljYWxDb2xvcm1hcChjb2Rlcz8ubWV0YSA/PyBudWxsKTtcbiAgICBjb25zdCB2YWx1ZXMgPSBuZXcgRmxvYXQzMkFycmF5KG93bmVycy5sZW5ndGgpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgb3duZXJzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBvID0gb3duZXJzW2ldO1xuICAgICAgY29uc3QgY29kZSA9ICFjb2RlcyB8fCAobXV0ZWQgJiYgIW11dGVkW29dKSA/IC0xIDogY29kZXMuY29kZXNbb107XG4gICAgICB2YWx1ZXNbaV0gPSB2YWx1ZU9mKGNvZGUgPT09IE5PX0NBVEVHT1JZID8gLTEgOiBjb2RlKTtcbiAgICB9XG4gICAgcmV0dXJuIHsgdmFsdWVzLCBjb2xvcm1hcCwgY29udHJhc3RMaW1pdHM6IFswLCAxXSB9O1xuICB9XG5cbiAgLyoqIENvZGVzIG9mIHRoZSBncm91cCBjb2x1bW4gdGhhdCBhcmUgc3dpdGNoZWQgb2ZmLCBvciBudWxsIHdoZW4gbm9uZSBhcmUuICovXG4gIHByaXZhdGUgYXN5bmMgaGlkZGVuQ29kZXMoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsXG4gICk6IFByb21pc2U8eyBjb2RlczogVWludDE2QXJyYXk7IGhpZGRlbjogVWludDhBcnJheSB9IHwgbnVsbD4ge1xuICAgIGlmICghdmlldy5oaWRkZW5Hcm91cHMubGVuZ3RoKSByZXR1cm4gbnVsbDtcbiAgICBjb25zdCBuYW1lID0gdGhpcy5jZWxsVHlwZUNvbHVtbk5hbWUoZGF0YXNldCwgdmlldyk7XG4gICAgY29uc3QgY29sID0gbmFtZSA/IGF3YWl0IHRoaXMuY2F0ZWdvcmljYWxDb2RlcyhuYW1lKSA6IG51bGw7XG4gICAgaWYgKCFjb2wgfHwgY29sLm1ldGEua2luZCAhPT0gJ2NhdGVnb3JpY2FsJykgcmV0dXJuIG51bGw7XG4gICAgY29uc3Qgb2ZmID0gbmV3IFNldCh2aWV3LmhpZGRlbkdyb3Vwcyk7XG4gICAgY29uc3QgaGlkZGVuID0gVWludDhBcnJheS5mcm9tKGNvbC5tZXRhLmNhdGVnb3JpZXMsIChjKSA9PiAob2ZmLmhhcyhjKSA/IDEgOiAwKSk7XG4gICAgcmV0dXJuIHsgY29kZXM6IGNvbC5jb2RlcywgaGlkZGVuIH07XG4gIH1cblxuICBwcml2YXRlIGNlbGxUeXBlQ29sdW1uTmFtZShkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCwgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSk6IHN0cmluZyB8IG51bGwge1xuICAgIHJldHVybiBjZWxsVHlwZUNvbHVtbkZvcihkYXRhc2V0LCB2aWV3KTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgY2F0ZWdvcmljYWxDb2RlcyhuYW1lOiBzdHJpbmcpOlxuICAgIFByb21pc2U8eyBjb2RlczogVWludDE2QXJyYXk7IG1ldGE6IFNwYXRpYWxDb2x1bW5bJ21ldGEnXSB9IHwgbnVsbD4ge1xuICAgIGNvbnN0IGNvbHVtbiA9IGF3YWl0IHRoaXMucG9ydC5nZXRDb2x1bW4obmFtZSk7XG4gICAgcmV0dXJuIGlzQ2F0ZWdvcmljYWxDb2x1bW4oY29sdW1uKSA/IHsgY29kZXM6IGNvbHVtbi5jb2RlcywgbWV0YTogY29sdW1uLm1ldGEgfSA6IG51bGw7XG4gIH1cblxuICBwcml2YXRlIGNhdGVnb3JpY2FsQ29sb3JtYXAobWV0YTogU3BhdGlhbENvbHVtblsnbWV0YSddIHwgbnVsbCk6XG4gICAgeyBjb2xvcm1hcDogQ29sb3JtYXA7IHZhbHVlT2Y6IChjb2RlOiBudW1iZXIpID0+IG51bWJlcjsgcmdiOiBSZ2JbXSB9IHtcbiAgICBjb25zdCBoZXggPSBtZXRhICYmIG1ldGEua2luZCA9PT0gJ2NhdGVnb3JpY2FsJ1xuICAgICAgPyByZXNvbHZlQ2F0ZWdvcnlDb2xvcnMobWV0YSlcbiAgICAgIDogW0RFRkFVTFRfQ0FURUdPUklDQUxfUEFMRVRURVswXV07XG4gICAgY29uc3QgcmdiID0gaGV4Lm1hcChwYXJzZUhleCk7XG4gICAgY29uc3QgeyBzdG9wcywgdmFsdWVPZiB9ID0gZGlzY3JldGVDb2xvcm1hcFN0b3BzKHJnYiwgTUlTU0lOR19DT0xPUik7XG4gICAgcmV0dXJuIHsgY29sb3JtYXA6IG5ldyBDb2xvcm1hcCgnc3BhdGlhbC1jYXRlZ29yaWVzJywgc3RvcHMpLCB2YWx1ZU9mLCByZ2IgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUaGUgY2VsbCByaW5ncyAoYW5kLCBmb3IgXCJib3RoXCIsIHRoZSBudWNsZXVzIHJpbmdzKSBjb3ZlcmluZyBgcmVjdGAgYXQgYGxldmVsYCwgbWludXNcbiAgICogdGhlIGhpZGRlbiBncm91cHMg4oCUIHJldXNlZCB3aGVuIG5vdGhpbmcgdGhhdCBkZWNpZGVzIHRoZW0gY2hhbmdlZC4gTnVsbCB3aGVuIHRoZVxuICAgKiB2aWV3IHdlbnQgc3RhbGUgb3IgdGhlIGRhdGFzZXQgaGFzIG5vIHNldCB0byBkcmF3LlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBjZWxsR2VvbWV0cnkoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsIHJlY3Q6IERhdGFSZWN0LCBsZXZlbDogbnVtYmVyLFxuICAgIGhpZGRlbjogeyBjb2RlczogVWludDE2QXJyYXk7IGhpZGRlbjogVWludDhBcnJheSB9IHwgbnVsbCwgc3RhbGU6ICgpID0+IGJvb2xlYW4sXG4gICk6IFByb21pc2U8eyByaW5nczogU3BhdGlhbFBvbHlnb25UaWxlOyBudWNsZWk6IFNwYXRpYWxQb2x5Z29uVGlsZSB8IG51bGw7IGdlb21ldHJ5S2V5OiBzdHJpbmcgfSB8IG51bGw+IHtcbiAgICBjb25zdCB0aWxlZCA9IGRhdGFzZXQucG9seWdvblRpbGVzO1xuICAgIGNvbnN0IGhpZGRlbktleSA9IHZpZXcuaGlkZGVuR3JvdXBzLmpvaW4oJ1xcdTAwMDEnKTtcbiAgICBsZXQgcmluZ3M6IFNwYXRpYWxQb2x5Z29uVGlsZTtcbiAgICBsZXQgbnVjbGVpOiBTcGF0aWFsUG9seWdvblRpbGUgfCBudWxsID0gbnVsbDtcbiAgICBsZXQgZ2VvbWV0cnlLZXk6IHN0cmluZztcbiAgICBpZiAodGlsZWQpIHtcbiAgICAgIGNvbnN0IGJvdGggPSB2aWV3LmNlbGxTZXQgPT09ICdib3RoJztcbiAgICAgIGNvbnN0IHNldCA9ICFib3RoICYmIHZpZXcuY2VsbFNldCAmJiB0aWxlZC5zZXRzLnNvbWUoKHMpID0+IHMubmFtZSA9PT0gdmlldy5jZWxsU2V0KVxuICAgICAgICA/IHZpZXcuY2VsbFNldCA6ICh0aWxlZC5kZWZhdWx0U2V0ID8/IHRpbGVkLnNldHNbMF0/Lm5hbWUpO1xuICAgICAgaWYgKCFzZXQpIHJldHVybiBudWxsO1xuICAgICAgY29uc3QgbnVjbGV1c1NldCA9IGJvdGggPyB0aWxlZC5zZXRzLmZpbmQoKHMpID0+IHMubmFtZSAhPT0gc2V0KT8ubmFtZSA6IHVuZGVmaW5lZDtcbiAgICAgIGNvbnN0IGtleXMgPSB0aWxlc0luUmVjdChyZWN0LCBsZXZlbCwgdGlsZWQubGV2ZWxzLCB0aWxlZC5ib3VuZHMsIE1BWF9DRUxMX1RJTEVTKTtcbiAgICAgIGdlb21ldHJ5S2V5ID0gYCR7ZGF0YXNldC5pZH18JHtzZXR9fCR7bnVjbGV1c1NldCA/PyAnJ318JHtoaWRkZW5LZXl9fCR7a2V5cy5tYXAodGlsZUlkKS5qb2luKCcsJyl9YDtcbiAgICAgIGlmIChnZW9tZXRyeUtleSA9PT0gdGhpcy5jZWxsR2VvbWV0cnlLZXkgJiYgdGhpcy5jdXJyZW50UmluZ3MpIHtcbiAgICAgICAgcmluZ3MgPSB0aGlzLmN1cnJlbnRSaW5ncztcbiAgICAgICAgbnVjbGVpID0gdGhpcy5jdXJyZW50TnVjbGVpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgW3RpbGVzLCBudWNsZXVzVGlsZXNdID0gYXdhaXQgUHJvbWlzZS5hbGwoW1xuICAgICAgICAgIHRoaXMuZmV0Y2hBbGwoa2V5cywgKGspID0+IHRoaXMucG9ydC5nZXRQb2x5Z29uVGlsZSEoc2V0LCBrLmxldmVsLCBrLmd4LCBrLmd5KSksXG4gICAgICAgICAgbnVjbGV1c1NldFxuICAgICAgICAgICAgPyB0aGlzLmZldGNoQWxsKGtleXMsIChrKSA9PiB0aGlzLnBvcnQuZ2V0UG9seWdvblRpbGUhKG51Y2xldXNTZXQsIGsubGV2ZWwsIGsuZ3gsIGsuZ3kpKVxuICAgICAgICAgICAgOiBQcm9taXNlLnJlc29sdmUobnVsbCksXG4gICAgICAgIF0pO1xuICAgICAgICBpZiAoc3RhbGUoKSkgcmV0dXJuIG51bGw7XG4gICAgICAgIHJpbmdzID0gZmlsdGVyUmluZ3MobWVyZ2VQb2x5Z29uVGlsZXModGlsZXMpLCBoaWRkZW4pO1xuICAgICAgICBudWNsZWkgPSBudWNsZXVzVGlsZXMgPyBmaWx0ZXJSaW5ncyhtZXJnZVBvbHlnb25UaWxlcyhudWNsZXVzVGlsZXMpLCBoaWRkZW4pIDogbnVsbDtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgZ2VvbWV0cnlLZXkgPSBgJHtkYXRhc2V0LmlkfXx3aG9sZXwke2hpZGRlbktleX1gO1xuICAgICAgaWYgKGdlb21ldHJ5S2V5ID09PSB0aGlzLmNlbGxHZW9tZXRyeUtleSAmJiB0aGlzLmN1cnJlbnRSaW5ncykge1xuICAgICAgICByaW5ncyA9IHRoaXMuY3VycmVudFJpbmdzO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgcG9seXM6IFNwYXRpYWxQb2x5Z29ucyA9IGF3YWl0IHRoaXMucG9ydC5nZXRQb2x5Z29ucyEoKTtcbiAgICAgICAgaWYgKHN0YWxlKCkpIHJldHVybiBudWxsO1xuICAgICAgICAvLyBXaG9sZS1kYXRhc2V0IHJpbmdzIGFyZSBpbmRleC1hbGlnbmVkIHdpdGggdGhlIG9ic2VydmF0aW9ucy5cbiAgICAgICAgcmluZ3MgPSBmaWx0ZXJSaW5ncyhcbiAgICAgICAgICB7IC4uLnBvbHlzLCBvYnNlcnZhdGlvbjogVWludDMyQXJyYXkuZnJvbSh7IGxlbmd0aDogcG9seXMuY291bnQgfSwgKF92LCBpKSA9PiBpKSB9LCBoaWRkZW4sXG4gICAgICAgICk7XG4gICAgICB9XG4gICAgfVxuICAgIHJldHVybiB7IHJpbmdzLCBudWNsZWksIGdlb21ldHJ5S2V5IH07XG4gIH1cblxuICAvLyDilIDilIAgdHJhbnNjcmlwdHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJpdmF0ZSBhc3luYyBwbGFuVHJhbnNjcmlwdHMoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsIHJlY3Q6IERhdGFSZWN0LCBweFBlclVuaXQ6IG51bWJlcixcbiAgICBzdGFsZTogKCkgPT4gYm9vbGVhbixcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgbW9kZSA9IHZpZXcudHJhbnNjcmlwdE1vZGU7XG4gICAgY29uc3Qgam9iID0gKG1vZGUgPT09ICdjaXJjbGVzJyB8fCBtb2RlID09PSAnZ2x5cGhzJykgJiYgdGhpcy5wb3J0LmdldFRyYW5zY3JpcHRUaWxlXG4gICAgICA/ICh2aWV3LnRyYW5zY3JpcHRBbGxHZW5lc1xuICAgICAgICA/IHRoaXMuYWxsR2VuZXNKb2IoZGF0YXNldCwgdmlldywgcmVjdCwgcHhQZXJVbml0KVxuICAgICAgICA6IHRoaXMuZ2VuZUpvYihkYXRhc2V0LCB2aWV3LCByZWN0LCBweFBlclVuaXQpKVxuICAgICAgOiBudWxsO1xuICAgIGlmICgham9iKSB7XG4gICAgICB0aGlzLmRyb3AoJ3RyYW5zY3JpcHRzJyk7XG4gICAgICB0aGlzLmRyb3AoJ3RyYW5zY3JpcHRPdXRsaW5lJyk7XG4gICAgICB0aGlzLmRyYXduID0gbnVsbDtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgLy8gTWFya2VyIHNpemVzIGZvbGxvdyB0aGUgem9vbSwgc28gdGhlIHpvb20gaXMgcGFydCBvZiB0aGUga2V5OyBhIHBhbiB0aGF0IGtlZXBzXG4gICAgLy8gdGhlIHNhbWUgdGlsZXMgb24gc2NyZWVuIGNoYW5nZXMgbm90aGluZy5cbiAgICBjb25zdCBwbGFuS2V5ID0gW1xuICAgICAgZGF0YXNldC5pZCwgbW9kZSwgam9iLmtleSwgdmlldy50cmFuc2NyaXB0Q29sb3JCeSwgdGhpcy5jZWxsVHlwZUNvbHVtbk5hbWUoZGF0YXNldCwgdmlldyksXG4gICAgICB2aWV3LnRyYW5zY3JpcHRTY2FsZSwgdmlldy50cmFuc2NyaXB0T3BhY2l0eSwgSlNPTi5zdHJpbmdpZnkodmlldy50cmFuc2NyaXB0R2x5cGhzKSxcbiAgICAgIHB4UGVyVW5pdC50b1ByZWNpc2lvbig0KSwgdmlldy5oaWRkZW5Hcm91cHMuam9pbignXFx1MDAwMScpLCB2aWV3LnRyYW5zY3JpcHRIaWRkZW5HZW5lcy5qb2luKCcsJyksXG4gICAgICBKU09OLnN0cmluZ2lmeSh2aWV3LnRyYW5zY3JpcHRHZW5lQ29sb3JzKSxcbiAgICBdLmpvaW4oJ3wnKTtcbiAgICBjb25zdCBjdXJyZW50ID0gdGhpcy5sYXllcnMuZ2V0KCd0cmFuc2NyaXB0cycpO1xuICAgIGlmIChwbGFuS2V5ID09PSB0aGlzLmtleXMuZ2V0KCd0cmFuc2NyaXB0cycpICYmIGN1cnJlbnQgJiYgdGhpcy52aWV3ZXIhLmxheWVycy5pdGVtcy5pbmNsdWRlcyhjdXJyZW50KSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBsb2FkZWQgPSBhd2FpdCBqb2IubG9hZCgpO1xuICAgIGlmIChzdGFsZSgpKSByZXR1cm47XG4gICAgY29uc3QgaGlkZGVuID0gYXdhaXQgdGhpcy5oaWRkZW5Db2RlcyhkYXRhc2V0LCB2aWV3KTtcbiAgICBpZiAoc3RhbGUoKSkgcmV0dXJuO1xuICAgIGNvbnN0IHsgbWVyZ2VkLCBweCB9ID0gZmlsdGVyVHJhbnNjcmlwdHMobG9hZGVkLm1lcmdlZCwgbG9hZGVkLnB4LCBoaWRkZW4sXG4gICAgICAobG9hZGVkLmtpbmQgPz8gam9iLmtpbmQpID09PSAnZ2VuZXMnID8gaGlkZGVuR2VuZVNsb3RzKHZpZXcpIDogbnVsbCk7XG4gICAgLy8gQSBiaW4gb2YgdGhlIGFsbC1nZW5lIHB5cmFtaWQgbWl4ZXMgZ2VuZXMgYW5kIGNhcnJpZXMgbm9uZSwgc28gaXQgY2Fubm90IGJlIGNvbG91cmVkXG4gICAgLy8gYnkgZ2VuZTogY29sb3VyIGl0IGJ5IGl0cyBkb21pbmFudCBjZWxsJ3MgdHlwZSB1bnRpbCBpbmRpdmlkdWFsIHRyYW5zY3JpcHRzIHNob3cuXG4gICAgY29uc3Qga2luZCA9IGxvYWRlZC5raW5kID8/IGpvYi5raW5kO1xuICAgIGNvbnN0IGNvbG9yVmlldyA9IGtpbmQgPT09ICdiaW5zJyAmJiB2aWV3LnRyYW5zY3JpcHRDb2xvckJ5ID09PSAnZ2VuZSdcbiAgICAgID8geyAuLi52aWV3LCB0cmFuc2NyaXB0Q29sb3JCeTogJ2NlbGxUeXBlJyBhcyBjb25zdCB9IDogdmlldztcbiAgICBjb25zdCBmYWNlcyA9IGF3YWl0IHRoaXMudHJhbnNjcmlwdENvbG9ycyhkYXRhc2V0LCBjb2xvclZpZXcsIG1lcmdlZCk7XG4gICAgaWYgKHN0YWxlKCkpIHJldHVybjtcblxuICAgIGlmICh0aGlzLnBsYW5JbmNvbXBsZXRlKSB0aGlzLmtleXMuZGVsZXRlKCd0cmFuc2NyaXB0cycpO1xuICAgIGVsc2UgdGhpcy5rZXlzLnNldCgndHJhbnNjcmlwdHMnLCBwbGFuS2V5KTtcbiAgICBjb25zdCBkaWFtID0gcHgubWFwKChkKSA9PiBkIC8gcHhQZXJVbml0KTtcbiAgICB0aGlzLmRyYXduID0ge1xuICAgICAga2luZDogbG9hZGVkLmtpbmQgPz8gam9iLmtpbmQsIGJpbjogbG9hZGVkLmtpbmQgPyBsb2FkZWQuYmluIDogam9iLmJpbixcbiAgICAgIG1lcmdlZCwgcmFkaXVzOiBkaWFtLm1hcCgoZCkgPT4gZCAvIDIpLFxuICAgICAgZ2VuZXM6IFsuLi52aWV3LnRyYW5zY3JpcHRHZW5lc10sIHJlZjogZGF0YXNldC5pbWFnZVJlZiA/PyBudWxsLCBncmlkOiBudWxsLFxuICAgIH07XG4gICAgdGhpcy5ob3ZlckNhY2hlLmNsZWFyKCk7XG4gICAgY29uc3QgdHlwZUNvbHVtbiA9IHRoaXMuY2VsbFR5cGVDb2x1bW5OYW1lKGRhdGFzZXQsIHZpZXcpO1xuICAgIHRoaXMuaG92ZXJUeXBlcyA9IHR5cGVDb2x1bW4gPyBhd2FpdCB0aGlzLmNhdGVnb3JpY2FsQ29kZXModHlwZUNvbHVtbikuY2F0Y2goKCkgPT4gbnVsbCkgOiBudWxsO1xuICAgIGlmIChzdGFsZSgpKSByZXR1cm47XG4gICAgY29uc3QgcmVmID0gZGF0YXNldC5pbWFnZVJlZjtcbiAgICBjb25zdCBwbGFjZTogUGxhY2VtZW50ID0geyBzY2FsZTogcmVmPy5zY2FsZSA/PyBbMSwgMV0sIHRyYW5zbGF0ZTogcmVmPy50cmFuc2xhdGUgPz8gWzAsIDBdIH07XG4gICAgaWYgKG1vZGUgPT09ICdjaXJjbGVzJykge1xuICAgICAgdGhpcy5kcm9wKCd0cmFuc2NyaXB0T3V0bGluZScpO1xuICAgICAgdGhpcy5kcmF3VHJhbnNjcmlwdENpcmNsZXMobWVyZ2VkLCBkaWFtLCBmYWNlcy5yZ2JhLCB2aWV3LCBwbGFjZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMuZHJhd1RyYW5zY3JpcHRHbHlwaHMobWVyZ2VkLCBkaWFtLCBmYWNlcywgdmlldywgcGxhY2UpO1xuICAgIH1cbiAgfVxuXG4gIC8qKiBPbmUgc2l6ZWQgY2lyY2xlIHBlciBlbnRyeSwgdGhlIHNpemUgc2F5aW5nIGhvdyBtYW55IHRyYW5zY3JpcHRzIGl0IHN0YW5kcyBmb3IuICovXG4gIHByaXZhdGUgZHJhd1RyYW5zY3JpcHRDaXJjbGVzKFxuICAgIG1lcmdlZDogU3BhdGlhbFRyYW5zY3JpcHRUaWxlLCBkaWFtOiBGbG9hdDMyQXJyYXksIHJnYmE6IFJHQkFbXSwgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSxcbiAgICB7IHNjYWxlLCB0cmFuc2xhdGUgfTogUGxhY2VtZW50LFxuICApOiB2b2lkIHtcbiAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KG1lcmdlZC5jb3VudCAqIDIpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWVyZ2VkLmNvdW50OyBpKyspIHtcbiAgICAgIHBvc2l0aW9uc1syICogaV0gPSBtZXJnZWQueFtpXTtcbiAgICAgIHBvc2l0aW9uc1syICogaSArIDFdID0gbWVyZ2VkLnlbaV07XG4gICAgfVxuICAgIGNvbnN0IGxheWVyID0gdGhpcy52aWV3ZXIhLmFkZFBvaW50cyhwb3NpdGlvbnMsIHtcbiAgICAgIG5hbWU6ICd0cmFuc2NyaXB0cycsXG4gICAgICBzaXplOiBkaWFtLFxuICAgICAgZmFjZUNvbG9yOiByZ2JhLFxuICAgICAgLy8gQSBkYXJrIHJpbTogYSB0cmFuc2NyaXB0IGNvbG91cmVkIGJ5IGl0cyBjZWxsJ3MgdHlwZSBpcyBvdGhlcndpc2UgdGhlIHNhbWVcbiAgICAgIC8vIGNvbG91ciBhcyB0aGUgY2VsbCBmaWxsIGl0IHNpdHMgb24sIGFuZCB2YW5pc2hlcyBpbnRvIGl0LlxuICAgICAgYm9yZGVyQ29sb3I6IFswLjA0LCAwLjA0LCAwLjA1LCAwLjldLFxuICAgICAgYm9yZGVyV2lkdGg6IDAuMTggKiBtZWRpYW4oZGlhbSksXG4gICAgICBvcGFjaXR5OiB2aWV3LnRyYW5zY3JpcHRPcGFjaXR5LFxuICAgICAgc2NhbGUsXG4gICAgICB0cmFuc2xhdGUsXG4gICAgfSk7XG4gICAgdGhpcy5yZXBsYWNlKCd0cmFuc2NyaXB0cycsIGxheWVyKTtcbiAgfVxuXG4gIHByaXZhdGUgZHJhd1RyYW5zY3JpcHRHbHlwaHMoXG4gICAgbWVyZ2VkOiBTcGF0aWFsVHJhbnNjcmlwdFRpbGUsIGRpYW06IEZsb2F0MzJBcnJheSwgZmFjZXM6IFRyYW5zY3JpcHRGYWNlcywgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSxcbiAgICB7IHNjYWxlLCB0cmFuc2xhdGUgfTogUGxhY2VtZW50LFxuICApOiB2b2lkIHtcbiAgICAvLyBHbHlwaHM6IGVhY2ggZW50cnkgYmVjb21lcyBpdHMgZ2VuZSdzIGljb24gcG9seWdvbiwgZmlsbGVkIHRocm91Z2ggYSBkaXNjcmV0ZVxuICAgIC8vIGNvbG9ybWFwIGFuZCBvdXRsaW5lZCBkYXJrIHNvIHNtYWxsIGljb25zIHN0YXkgcmVhZGFibGUgb3ZlciB0aGUgdGlzc3VlLiBXaXRoIGV2ZXJ5XG4gICAgLy8gZ2VuZSBkcmF3biB0aGVyZSBpcyBvbmUgaWNvbiBmb3IgYWxsIG9mIHRoZW0g4oCUIDE4LDAwMCBzaGFwZXMgd291bGQgc2F5IG5vdGhpbmcuXG4gICAgY29uc3QgZ2VuZXMgPSB2aWV3LnRyYW5zY3JpcHRHZW5lcztcbiAgICBjb25zdCBnbHlwaEZvciA9IChzbG90OiBudW1iZXIpOiBUcmFuc2NyaXB0R2x5cGggPT5cbiAgICAgICh2aWV3LnRyYW5zY3JpcHRHbHlwaHNbZ2VuZXNbc2xvdF1dIGFzIFRyYW5zY3JpcHRHbHlwaCB8IHVuZGVmaW5lZCkgPz8gZGVmYXVsdEdseXBoRm9yKHNsb3QpO1xuICAgIGNvbnN0IHNpbmdsZSA9IHZpZXcudHJhbnNjcmlwdEFsbEdlbmVzXG4gICAgICA/IGdseXBoT3V0bGluZSgodmlldy50cmFuc2NyaXB0R2x5cGhzW0FMTF9HRU5FU10gYXMgVHJhbnNjcmlwdEdseXBoIHwgdW5kZWZpbmVkKSA/PyAnY2lyY2xlJylcbiAgICAgIDogbnVsbDtcbiAgICBjb25zdCBvdXRsaW5lcyA9IHNpbmdsZSA/IFtdIDogZ2VuZXMubWFwKChfZywgc2xvdCkgPT4gZ2x5cGhPdXRsaW5lKGdseXBoRm9yKHNsb3QpKSk7XG4gICAgY29uc3QgcmFkaXVzID0gZGlhbS5tYXAoKGQpID0+IGQgLyAyKTtcbiAgICBjb25zdCB7IGNvb3Jkcywgb2Zmc2V0cyB9ID0gZ2x5cGhSaW5ncyhcbiAgICAgIG1lcmdlZC54LCBtZXJnZWQueSwgcmFkaXVzLCAoaSkgPT4gc2luZ2xlID8/IG91dGxpbmVzW21lcmdlZC5nZW5lW2ldXSxcbiAgICApO1xuICAgIGNvbnN0IGZpbGwgPSB0aGlzLnZpZXdlciEuYWRkU2hhcGVzKGNvb3Jkcywgb2Zmc2V0cywge1xuICAgICAgbmFtZTogJ3RyYW5zY3JpcHRzJyxcbiAgICAgIGRyYXc6ICdmaWxsJyxcbiAgICAgIHZhbHVlczogZmFjZXMudmFsdWVzLFxuICAgICAgY29sb3JtYXA6IGZhY2VzLmNvbG9ybWFwLFxuICAgICAgY29udHJhc3RMaW1pdHM6IFswLCAxXSxcbiAgICAgIG9wYWNpdHk6IHZpZXcudHJhbnNjcmlwdE9wYWNpdHksXG4gICAgICBzY2FsZSxcbiAgICAgIHRyYW5zbGF0ZSxcbiAgICB9KTtcbiAgICB0aGlzLnJlcGxhY2UoJ3RyYW5zY3JpcHRzJywgZmlsbCk7XG4gICAgY29uc3QgZWRnZSA9IHRoaXMudmlld2VyIS5hZGRTaGFwZXMoY29vcmRzLCBvZmZzZXRzLCB7XG4gICAgICBuYW1lOiAndHJhbnNjcmlwdCBvdXRsaW5lcycsXG4gICAgICBkcmF3OiAnb3V0bGluZScsXG4gICAgICBjb2xvcjogWzAuMDUsIDAuMDUsIDAuMDUsIDFdLFxuICAgICAgb3BhY2l0eTogTWF0aC5taW4oMSwgdmlldy50cmFuc2NyaXB0T3BhY2l0eSArIDAuMSksXG4gICAgICBzY2FsZSxcbiAgICAgIHRyYW5zbGF0ZSxcbiAgICB9KTtcbiAgICB0aGlzLnJlcGxhY2UoJ3RyYW5zY3JpcHRPdXRsaW5lJywgZWRnZSk7XG4gIH1cblxuICAvLyDilIDilIAgaG92ZXIg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbiAgcHJpdmF0ZSBkcmF3bjogRHJhd25UcmFuc2NyaXB0cyB8IG51bGwgPSBudWxsO1xuICBwcml2YXRlIGhvdmVyVHlwZXM6IHsgY29kZXM6IFVpbnQxNkFycmF5OyBtZXRhOiBTcGF0aWFsQ29sdW1uWydtZXRhJ10gfSB8IG51bGwgPSBudWxsO1xuICAvKiogRGV0YWlscyBhbHJlYWR5IGZldGNoZWQsIGJ5IGhvdmVyZWQgZW50cnkuICovXG4gIHByaXZhdGUgcmVhZG9ubHkgaG92ZXJDYWNoZSA9IG5ldyBNYXA8c3RyaW5nLCBzdHJpbmdbXT4oKTtcbiAgcHJpdmF0ZSBob3ZlcktleTogc3RyaW5nIHwgbnVsbCA9IG51bGw7XG4gIHByaXZhdGUgaG92ZXJUaW1lcjogUmV0dXJuVHlwZTx0eXBlb2Ygc2V0VGltZW91dD4gfCBudWxsID0gbnVsbDtcblxuICAvKipcbiAgICogVG9vbHRpcCBsaW5lcyBmb3IgdGhlIHRyYW5zY3JpcHQgbWFya2VyIHVuZGVyIHdvcmxkIHBvaW50IGAod3gsIHd5KWAsIG9yIG51bGwuXG4gICAqXG4gICAqIFJldHVybnMgd2hhdCBpcyBrbm93biBhdCBvbmNlIChnZW5lLCBjb3VudCwgY2VsbCB0eXBlKTsgYW55dGhpbmcgdGhhdCBuZWVkcyB0aGVcbiAgICogc2VydmVyIOKAlCBkaXN0aW5jdCBnZW5lcyBpbiBhIGdyb3VwLCBpdHMgdG9wIGdlbmVzIGFuZCBjZWxscywgdGhlIGNlbGwncyBkaXNwbGF5IGlkIOKAlFxuICAgKiBhcnJpdmVzIHRocm91Z2ggYG9uRGV0YWlsc2Agb25jZSB0aGUgcG9pbnRlciBoYXMgcmVzdGVkIG9uIHRoZSBtYXJrZXIgYnJpZWZseS5cbiAgICovXG4gIGhvdmVyQXQoXG4gICAgd3g6IG51bWJlciwgd3k6IG51bWJlciwgcmFkaXVzV29ybGQ6IG51bWJlciwgb25EZXRhaWxzOiAobGluZXM6IHN0cmluZ1tdKSA9PiB2b2lkLFxuICApOiBzdHJpbmdbXSB8IG51bGwge1xuICAgIGNvbnN0IGQgPSB0aGlzLmRyYXduO1xuICAgIGNvbnN0IGxheWVyID0gdGhpcy5sYXllcnMuZ2V0KCd0cmFuc2NyaXB0cycpO1xuICAgIGlmICghZCB8fCAhbGF5ZXIgfHwgIXRoaXMudmlld2VyPy5sYXllcnMuaXRlbXMuaW5jbHVkZXMobGF5ZXIpIHx8ICFkLm1lcmdlZC5jb3VudCkge1xuICAgICAgdGhpcy5ob3ZlcktleSA9IG51bGw7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3Qgc3ggPSBkLnJlZj8uc2NhbGU/LlswXSA/PyAxO1xuICAgIGNvbnN0IHN5ID0gZC5yZWY/LnNjYWxlPy5bMV0gPz8gMTtcbiAgICBjb25zdCB4ID0gKHd4IC0gKGQucmVmPy50cmFuc2xhdGU/LlswXSA/PyAwKSkgLyBzeDtcbiAgICBjb25zdCB5ID0gKHd5IC0gKGQucmVmPy50cmFuc2xhdGU/LlsxXSA/PyAwKSkgLyBzeTtcbiAgICBjb25zdCBpID0gcGlja05lYXJlc3QoZCwgeCwgeSwgcmFkaXVzV29ybGQgLyBNYXRoLmFicyhzeCkpO1xuICAgIGlmIChpIDwgMCkge1xuICAgICAgdGhpcy5ob3ZlcktleSA9IG51bGw7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3Qga2V5ID0gYCR7ZC5raW5kfXwke2QubWVyZ2VkLnhbaV19fCR7ZC5tZXJnZWQueVtpXX18JHtkLm1lcmdlZC5nZW5lW2ldfWA7XG4gICAgY29uc3QgY2FjaGVkID0gdGhpcy5ob3ZlckNhY2hlLmdldChrZXkpO1xuICAgIGlmIChjYWNoZWQpIHJldHVybiBjYWNoZWQ7XG4gICAgaWYgKGtleSAhPT0gdGhpcy5ob3ZlcktleSkge1xuICAgICAgdGhpcy5ob3ZlcktleSA9IGtleTtcbiAgICAgIGlmICh0aGlzLmhvdmVyVGltZXIpIGNsZWFyVGltZW91dCh0aGlzLmhvdmVyVGltZXIpO1xuICAgICAgdGhpcy5ob3ZlclRpbWVyID0gc2V0VGltZW91dCgoKSA9PiB2b2lkIHRoaXMuZmV0Y2hEZXRhaWxzKGQsIGksIGtleSwgb25EZXRhaWxzKSwgMTUwKTtcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuZGVzY3JpYmUoZCwgaSwgbnVsbCk7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZldGNoRGV0YWlscyhcbiAgICBkOiBEcmF3blRyYW5zY3JpcHRzLCBpOiBudW1iZXIsIGtleTogc3RyaW5nLCBvbkRldGFpbHM6IChsaW5lczogc3RyaW5nW10pID0+IHZvaWQsXG4gICk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5wb3J0LmdldFRyYW5zY3JpcHRTdW1tYXJ5IHx8IHRoaXMuaG92ZXJLZXkgIT09IGtleSkgcmV0dXJuO1xuICAgIGNvbnN0IG9icyA9IGQubWVyZ2VkLm9ic2VydmF0aW9uW2ldO1xuICAgIGNvbnN0IGNlbGxzID0gb2JzID09PSBOT19PQlNFUlZBVElPTiA/IFtdIDogW29ic107XG4gICAgbGV0IGJveDogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gfCB1bmRlZmluZWQ7XG4gICAgaWYgKGQua2luZCA9PT0gJ2JpbnMnICYmIGQuYmluKSB7XG4gICAgICBjb25zdCB7IHNpemUsIG9yaWdpbiB9ID0gZC5iaW47XG4gICAgICBjb25zdCBieCA9IE1hdGguZmxvb3IoKGQubWVyZ2VkLnhbaV0gLSBvcmlnaW5bMF0pIC8gc2l6ZSk7XG4gICAgICBjb25zdCBieSA9IE1hdGguZmxvb3IoKGQubWVyZ2VkLnlbaV0gLSBvcmlnaW5bMV0pIC8gc2l6ZSk7XG4gICAgICBjb25zdCB4MCA9IG9yaWdpblswXSArIGJ4ICogc2l6ZTtcbiAgICAgIGNvbnN0IHkwID0gb3JpZ2luWzFdICsgYnkgKiBzaXplO1xuICAgICAgYm94ID0gW3gwLCB5MCwgeDAgKyBzaXplLCB5MCArIHNpemVdO1xuICAgIH0gZWxzZSBpZiAoZC5raW5kID09PSAnaW5kaXZpZHVhbCcpIHtcbiAgICAgIGNvbnN0IGUgPSAwLjAyO1xuICAgICAgYm94ID0gW2QubWVyZ2VkLnhbaV0gLSBlLCBkLm1lcmdlZC55W2ldIC0gZSwgZC5tZXJnZWQueFtpXSArIGUsIGQubWVyZ2VkLnlbaV0gKyBlXTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHN1bW1hcnkgPSBhd2FpdCB0aGlzLnBvcnQuZ2V0VHJhbnNjcmlwdFN1bW1hcnkoeyBib3gsIGNlbGxzIH0pO1xuICAgICAgY29uc3QgbGluZXMgPSB0aGlzLmRlc2NyaWJlKGQsIGksIHN1bW1hcnkpO1xuICAgICAgdGhpcy5ob3ZlckNhY2hlLnNldChrZXksIGxpbmVzKTtcbiAgICAgIGlmICh0aGlzLmhvdmVyS2V5ID09PSBrZXkpIG9uRGV0YWlscyhsaW5lcyk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLndhcm4oJ1tuYXBhcmktanNdIHRyYW5zY3JpcHQgZGV0YWlscyB1bmF2YWlsYWJsZScsIGVycik7XG4gICAgfVxuICB9XG5cbiAgLyoqIFRoZSB0b29sdGlwIHRleHQgZm9yIGVudHJ5IGBpYCwgd2l0aCB0aGUgc2VydmVyJ3MgZGV0YWlscyB3aGVuIHRoZXkgaGF2ZSBhcnJpdmVkLiAqL1xuICBwcml2YXRlIGRlc2NyaWJlKGQ6IERyYXduVHJhbnNjcmlwdHMsIGk6IG51bWJlciwgczogU3BhdGlhbFRyYW5zY3JpcHRTdW1tYXJ5IHwgbnVsbCk6IHN0cmluZ1tdIHtcbiAgICBjb25zdCB0ID0gZC5tZXJnZWQ7XG4gICAgY29uc3QgbiA9IHQud2VpZ2h0W2ldO1xuICAgIGNvbnN0IG9icyA9IHQub2JzZXJ2YXRpb25baV07XG4gICAgY29uc3QgZm10ID0gKHY6IG51bWJlcikgPT4gdi50b0xvY2FsZVN0cmluZygpO1xuICAgIGNvbnN0IHR5cGVPZiA9IChvOiBudW1iZXIpID0+IHtcbiAgICAgIGNvbnN0IHR5cGVzID0gdGhpcy5ob3ZlclR5cGVzO1xuICAgICAgaWYgKCF0eXBlcyB8fCBvID09PSBOT19PQlNFUlZBVElPTiB8fCB0eXBlcy5tZXRhLmtpbmQgIT09ICdjYXRlZ29yaWNhbCcpIHJldHVybiBudWxsO1xuICAgICAgY29uc3QgYyA9IHR5cGVzLmNvZGVzW29dO1xuICAgICAgcmV0dXJuIGMgPT09IE5PX0NBVEVHT1JZID8gbnVsbCA6IHR5cGVzLm1ldGEuY2F0ZWdvcmllc1tjXSA/PyBudWxsO1xuICAgIH07XG4gICAgY29uc3QgY2VsbExpbmUgPSAobzogbnVtYmVyLCBwcmVmaXg6IHN0cmluZykgPT4ge1xuICAgICAgaWYgKG8gPT09IE5PX09CU0VSVkFUSU9OKSByZXR1cm4gJ291dHNpZGUgYW55IGNlbGwnO1xuICAgICAgY29uc3QgaWQgPSBzPy5jZWxsSWRzPy5bb10gPz8gYCMke299YDtcbiAgICAgIGNvbnN0IHR5cGUgPSB0eXBlT2Yobyk7XG4gICAgICByZXR1cm4gYCR7cHJlZml4fSAke2lkfSR7dHlwZSA/IGAgwrcgJHt0eXBlfWAgOiAnJ31gO1xuICAgIH07XG5cbiAgICBpZiAoZC5raW5kID09PSAnYmlucycpIHtcbiAgICAgIGNvbnN0IGxpbmVzID0gW2Ake2ZtdChuKX0gdHJhbnNjcmlwdHMgwrcgYWxsIGdlbmVzYF07XG4gICAgICBpZiAoZC5iaW4pIGxpbmVzLnB1c2goYCR7ZC5iaW4uc2l6ZS50b0ZpeGVkKDEpfSDDlyAke2QuYmluLnNpemUudG9GaXhlZCgxKX0gwrVtIGFyZWFgKTtcbiAgICAgIGlmIChzPy50cmFuc2NyaXB0cyAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIGxpbmVzLnB1c2goYCR7Zm10KHMuZ2VuZXMgPz8gMCl9IGRpc3RpbmN0IGdlbmVzIMK3ICR7Zm10KHMuY2VsbHMgPz8gMCl9IGNlbGwke3MuY2VsbHMgPT09IDEgPyAnJyA6ICdzJ31gXG4gICAgICAgICAgKyAocy51bmFzc2lnbmVkID8gYCDCtyAke2ZtdChzLnVuYXNzaWduZWQpfSBvdXRzaWRlIGNlbGxzYCA6ICcnKSk7XG4gICAgICAgIGlmIChzLnRvcEdlbmVzPy5sZW5ndGgpIHtcbiAgICAgICAgICBsaW5lcy5wdXNoKGB0b3AgZ2VuZXM6ICR7cy50b3BHZW5lcy5zbGljZSgwLCA1KS5tYXAoKGcpID0+IGAke2cubmFtZX0gJHtmbXQoZy5jb3VudCl9YCkuam9pbignLCAnKX1gKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgbGluZXMucHVzaChjZWxsTGluZShvYnMsICdtb3N0bHkgY2VsbCcpKTtcbiAgICAgIGlmICghcyAmJiB0aGlzLnBvcnQuZ2V0VHJhbnNjcmlwdFN1bW1hcnkpIGxpbmVzLnB1c2goJ2xvYWRpbmcgZGV0YWlsc+KApicpO1xuICAgICAgcmV0dXJuIGxpbmVzO1xuICAgIH1cbiAgICBpZiAoZC5raW5kID09PSAnaW5kaXZpZHVhbCcpIHtcbiAgICAgIGNvbnN0IGdlbmUgPSBzPy50b3BHZW5lcz8uWzBdPy5uYW1lO1xuICAgICAgcmV0dXJuIFtcbiAgICAgICAgZ2VuZSA/IGAke2dlbmV9IHRyYW5zY3JpcHRgIDogJ1RyYW5zY3JpcHQnLFxuICAgICAgICBjZWxsTGluZShvYnMsICdpbiBjZWxsJyksXG4gICAgICAgIC4uLighcyAmJiB0aGlzLnBvcnQuZ2V0VHJhbnNjcmlwdFN1bW1hcnkgPyBbJ2xvYWRpbmcgZGV0YWlsc+KApiddIDogW10pLFxuICAgICAgXTtcbiAgICB9XG4gICAgY29uc3QgZ2VuZSA9IGQuZ2VuZXNbdC5nZW5lW2ldXSA/PyAndHJhbnNjcmlwdCc7XG4gICAgcmV0dXJuIG4gPiAxXG4gICAgICA/IFtgJHtnZW5lfSDCtyAke2ZtdChuKX0gdHJhbnNjcmlwdHNgLCAnZ3JvdXBlZDogem9vbSBpbiB0byBzcGxpdCcsIGNlbGxMaW5lKG9icywgJ25lYXIgY2VsbCcpXVxuICAgICAgOiBbYCR7Z2VuZX0gdHJhbnNjcmlwdGAsIGNlbGxMaW5lKG9icywgJ2luIGNlbGwnKV07XG4gIH1cblxuICAvKiogUGh5c2ljYWwgbWFya2VyIHNpemUgbmVlZHMgwrVtOyBudWxsIHdoZW4gdGhlIGRhdGFzZXQncyB1bml0IGlzIHVua25vd24uICovXG4gIHByaXZhdGUgcHhQZXJNaWNyb24oZGF0YXNldDogU3BhdGlhbERhdGFzZXQsIHB4UGVyVW5pdDogbnVtYmVyKTogbnVtYmVyIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gZGF0YXNldC5taWNyb25zUGVyVW5pdCA/IHB4UGVyVW5pdCAvIGRhdGFzZXQubWljcm9uc1BlclVuaXQgOiB1bmRlZmluZWQ7XG4gIH1cblxuICAvKipcbiAgICogVGhlIGNob3NlbiBnZW5lcywgYXQgdGhlIGxldmVsIHRoZSB6b29tIGNhbGxzIGZvciDigJQgb3IgY29hcnNlciwgd2hpbGUgdGhlIG1hcmtlcnMgaW5cbiAgICogdmlldyB3b3VsZCBleGNlZWQgdGhlIGJ1ZGdldC5cbiAgICovXG4gIHByaXZhdGUgZ2VuZUpvYihcbiAgICBkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCwgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSwgcmVjdDogRGF0YVJlY3QsIHB4UGVyVW5pdDogbnVtYmVyLFxuICApOiBUcmFuc2NyaXB0Sm9iIHwgbnVsbCB7XG4gICAgY29uc3QgbWV0YSA9IGRhdGFzZXQudHJhbnNjcmlwdFRpbGVzO1xuICAgIGNvbnN0IGdlbmVzID0gdmlldy50cmFuc2NyaXB0R2VuZXM7XG4gICAgaWYgKCFtZXRhIHx8ICFnZW5lcy5sZW5ndGgpIHJldHVybiBudWxsO1xuICAgIGNvbnN0IGZpcnN0ID0gdHJhbnNjcmlwdExldmVsRm9yKHB4UGVyVW5pdCwgbWV0YS5sZXZlbHMpO1xuICAgIGNvbnN0IGtleXNBdCA9IChsOiBudW1iZXIpID0+IHRpbGVzSW5SZWN0KHJlY3QsIGwsIG1ldGEubGV2ZWxzLCBtZXRhLmJvdW5kcywgTUFYX1RSQU5TQ1JJUFRfVElMRVMpO1xuICAgIGNvbnN0IHF1ZXJ5ID0geyBnZW5lcywgcXVhbGl0eTogdmlldy50cmFuc2NyaXB0UXVhbGl0eSB9O1xuICAgIGNvbnN0IHB4UGVyTWljcm9uID0gdGhpcy5weFBlck1pY3JvbihkYXRhc2V0LCBweFBlclVuaXQpO1xuICAgIHJldHVybiB7XG4gICAgICBraW5kOiAnZ2VuZXMnLFxuICAgICAga2V5OiBgZ2VuZXN8JHtnZW5lcy5qb2luKCcsJyl9fCR7dmlldy50cmFuc2NyaXB0UXVhbGl0eX18JHt2aWV3LnRyYW5zY3JpcHRCdWRnZXR9fCR7a2V5c0F0KGZpcnN0KS5tYXAodGlsZUlkKX1gLFxuICAgICAgbG9hZDogYXN5bmMgKCkgPT4ge1xuICAgICAgICBsZXQgbGV2ZWwgPSBmaXJzdDtcbiAgICAgICAgbGV0IG1lcmdlZDogU3BhdGlhbFRyYW5zY3JpcHRUaWxlO1xuICAgICAgICBmb3IgKDs7KSB7XG4gICAgICAgICAgY29uc3QgdGlsZXMgPSBhd2FpdCB0aGlzLmZldGNoQWxsKGtleXNBdChsZXZlbCksXG4gICAgICAgICAgICAoaykgPT4gdGhpcy5wb3J0LmdldFRyYW5zY3JpcHRUaWxlIShrLmxldmVsLCBrLmd4LCBrLmd5LCBxdWVyeSkpO1xuICAgICAgICAgIG1lcmdlZCA9IG1lcmdlVHJhbnNjcmlwdFRpbGVzKHRpbGVzLCBNQVhfVFJBTlNDUklQVFMpO1xuICAgICAgICAgIGlmIChtZXJnZWQuY291bnQgPD0gdmlldy50cmFuc2NyaXB0QnVkZ2V0IHx8IGxldmVsID49IG1ldGEubGV2ZWxzLmxlbmd0aCAtIDEpIGJyZWFrO1xuICAgICAgICAgIGxldmVsKys7XG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgcHggPSBuZXcgRmxvYXQzMkFycmF5KG1lcmdlZC5jb3VudCk7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWVyZ2VkLmNvdW50OyBpKyspIHtcbiAgICAgICAgICBweFtpXSA9IHRyYW5zY3JpcHRNYXJrZXJQeChtZXJnZWQud2VpZ2h0W2ldLCB2aWV3LnRyYW5zY3JpcHRTY2FsZSwgcHhQZXJNaWNyb24pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IG1lcmdlZCwgcHggfTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBFdmVyeSBnZW5lOiB0aGUgdHJhbnNjcmlwdHMgdGhlbXNlbHZlcyBvbmNlIHRoZXkgZml0IHRoZSBidWRnZXQsIGVsc2UgYmlucyBvZiB0aGVcbiAgICogYWxsLWdlbmUgcHlyYW1pZCBzaXplZCBieSBob3cgbWFueSB0cmFuc2NyaXB0cyBlYWNoIGhvbGRzLlxuICAgKi9cbiAgcHJpdmF0ZSBhbGxHZW5lc0pvYihcbiAgICBkYXRhc2V0OiBTcGF0aWFsRGF0YXNldCwgdmlldzogU3BhdGlhbFZpZXdTdGF0ZSwgcmVjdDogRGF0YVJlY3QsIHB4UGVyVW5pdDogbnVtYmVyLFxuICApOiBUcmFuc2NyaXB0Sm9iIHwgbnVsbCB7XG4gICAgY29uc3QgYmlucyA9IGRhdGFzZXQudHJhbnNjcmlwdEJpbnM7XG4gICAgY29uc3QgdGlsZXMgPSBkYXRhc2V0LnRyYW5zY3JpcHRUaWxlcztcbiAgICBjb25zdCBib3VuZHMgPSBiaW5zPy5ib3VuZHMgPz8gdGlsZXM/LmJvdW5kcztcbiAgICBpZiAoIWJvdW5kcykgcmV0dXJuIG51bGw7XG4gICAgY29uc3QgcGxhbiA9IGFsbEdlbmVzUGxhbih7XG4gICAgICByZWN0LCBib3VuZHMsIHB4UGVyVW5pdCwgYnVkZ2V0OiB2aWV3LnRyYW5zY3JpcHRCdWRnZXQsXG4gICAgICB0b3RhbDogYmlucz8uY291bnQgPz8gdGlsZXM/LmNvdW50ID8/IDAsXG4gICAgICBsZXZlbHM6IGJpbnMgJiYgdGhpcy5wb3J0LmdldFRyYW5zY3JpcHRCaW5zID8gYmlucy5sZXZlbHMgOiBbXSxcbiAgICAgIGNhbkluZGl2aWR1YWw6ICEhdGlsZXMsXG4gICAgfSk7XG5cbiAgICBpZiAocGxhbi5raW5kID09PSAnaW5kaXZpZHVhbCcgJiYgdGlsZXMpIHtcbiAgICAgIGNvbnN0IGtleXMgPSB0aWxlc0luUmVjdChyZWN0LCAwLCB0aWxlcy5sZXZlbHMsIHRpbGVzLmJvdW5kcywgTUFYX1RSQU5TQ1JJUFRfVElMRVMpO1xuICAgICAgLy8gRWFjaCB0aWxlIGNsaXBwZWQgdG8gdGhlIHZpZXcsIHJvdW5kZWQgb3V0d2FyZCB0byAxMCB1bml0cyBzbyBzbWFsbCBwYW5zIGhpdCBjYWNoZS5cbiAgICAgIGNvbnN0IHIxMCA9ICh2OiBudW1iZXIsIHVwOiBib29sZWFuKSA9PiAodXAgPyBNYXRoLmNlaWwodiAvIDEwKSA6IE1hdGguZmxvb3IodiAvIDEwKSkgKiAxMDtcbiAgICAgIGNvbnN0IHNpemUgPSB0aWxlcy5sZXZlbHNbMF0udGlsZVNpemU7XG4gICAgICBjb25zdCBib3hlcyA9IGtleXMubWFwKChrKTogW251bWJlciwgbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gPT4gW1xuICAgICAgICBNYXRoLm1heChrLmd4ICogc2l6ZSwgcjEwKHJlY3QueDAsIGZhbHNlKSksIE1hdGgubWF4KGsuZ3kgKiBzaXplLCByMTAocmVjdC55MCwgZmFsc2UpKSxcbiAgICAgICAgTWF0aC5taW4oKGsuZ3ggKyAxKSAqIHNpemUsIHIxMChyZWN0LngxLCB0cnVlKSksIE1hdGgubWluKChrLmd5ICsgMSkgKiBzaXplLCByMTAocmVjdC55MSwgdHJ1ZSkpLFxuICAgICAgXSk7XG4gICAgICBjb25zdCBweFBlck1pY3JvbiA9IHRoaXMucHhQZXJNaWNyb24oZGF0YXNldCwgcHhQZXJVbml0KTtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGtpbmQ6ICdpbmRpdmlkdWFsJyxcbiAgICAgICAga2V5OiBgYWxsfGluZGl2aWR1YWx8JHt2aWV3LnRyYW5zY3JpcHRCdWRnZXR9fCR7Ym94ZXMubWFwKChiKSA9PiBiLmpvaW4oJywnKSkuam9pbignOycpfWAsXG4gICAgICAgIGxvYWQ6IGFzeW5jICgpID0+IHtcbiAgICAgICAgICBjb25zdCBnb3QgPSBhd2FpdCB0aGlzLmZldGNoQWxsKGtleXMubWFwKChrLCBpKSA9PiAoeyAuLi5rLCBib3g6IGJveGVzW2ldIH0pKSxcbiAgICAgICAgICAgIChrKSA9PiB0aGlzLnBvcnQuZ2V0VHJhbnNjcmlwdFRpbGUhKDAsIGsuZ3gsIGsuZ3ksIHsgZ2VuZXM6IFtBTExfR0VORVNdLCBib3g6IGsuYm94IH0pKTtcbiAgICAgICAgICAvLyBUaGUgcGxhbiBlc3RpbWF0ZWQgdGhlIHZpZXcgZnJvbSB0aGUgZGF0YXNldCdzIGF2ZXJhZ2UgZGVuc2l0eTsgZXhwcmVzc2lvbiBpc1xuICAgICAgICAgIC8vIHVuZXZlbiwgc28gYSBkZW5zZSB2aWV3IGNhbiBob2xkIGZhciBtb3JlLiBSYXRoZXIgdGhhbiBjdXQgdGhlIGV4Y2VzcyBvZmYsIHNob3dcbiAgICAgICAgICAvLyBpdCBncm91cGVkIOKAlCB0aGUgYmluIGxldmVsIHRoZSBwbGFubmVyIHdvdWxkIHBpY2sgaWYgaXQgaGFkIGtub3duLlxuICAgICAgICAgIGNvbnN0IGNhcCA9IE1hdGgubWF4KHZpZXcudHJhbnNjcmlwdEJ1ZGdldCAqIDEuNSwgMSk7XG4gICAgICAgICAgY29uc3QgbG9hZGVkID0gZ290LnJlZHVjZSgobiwgdCkgPT4gbiArIHQuY291bnQsIDApO1xuICAgICAgICAgIGlmIChsb2FkZWQgPiBjYXAgJiYgYmlucyAmJiB0aGlzLnBvcnQuZ2V0VHJhbnNjcmlwdEJpbnMpIHtcbiAgICAgICAgICAgIGNvbnN0IGZhbGxiYWNrID0gYWxsR2VuZXNQbGFuKHtcbiAgICAgICAgICAgICAgcmVjdCwgYm91bmRzLCBweFBlclVuaXQsIGJ1ZGdldDogdmlldy50cmFuc2NyaXB0QnVkZ2V0LCB0b3RhbDogYmlucy5jb3VudCxcbiAgICAgICAgICAgICAgbGV2ZWxzOiBiaW5zLmxldmVscywgY2FuSW5kaXZpZHVhbDogZmFsc2UsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmIChmYWxsYmFjay5raW5kID09PSAnYmlucycpIHtcbiAgICAgICAgICAgICAgY29uc3Qgam9iID0gdGhpcy5iaW5zSm9iKHZpZXcsIHJlY3QsIHB4UGVyVW5pdCwgYm91bmRzLCBiaW5zLCBmYWxsYmFjay5sZXZlbCk7XG4gICAgICAgICAgICAgIHJldHVybiB7IC4uLihhd2FpdCBqb2IubG9hZCgpKSwga2luZDogam9iLmtpbmQsIGJpbjogam9iLmJpbiB9O1xuICAgICAgICAgICAgfVxuICAgICAgICAgIH1cbiAgICAgICAgICBjb25zdCBtZXJnZWQgPSBtZXJnZVRyYW5zY3JpcHRUaWxlcyhnb3QsIGNhcCk7XG4gICAgICAgICAgY29uc3QgcHggPSBuZXcgRmxvYXQzMkFycmF5KG1lcmdlZC5jb3VudCk7XG4gICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtZXJnZWQuY291bnQ7IGkrKykgcHhbaV0gPSB0cmFuc2NyaXB0TWFya2VyUHgoMSwgdmlldy50cmFuc2NyaXB0U2NhbGUsIHB4UGVyTWljcm9uKTtcbiAgICAgICAgICByZXR1cm4geyBtZXJnZWQsIHB4IH07XG4gICAgICAgIH0sXG4gICAgICB9O1xuICAgIH1cblxuICAgIGlmIChwbGFuLmtpbmQgPT09ICdiaW5zJyAmJiBiaW5zICYmIHRoaXMucG9ydC5nZXRUcmFuc2NyaXB0Qmlucykge1xuICAgICAgcmV0dXJuIHRoaXMuYmluc0pvYih2aWV3LCByZWN0LCBweFBlclVuaXQsIGJvdW5kcywgYmlucywgcGxhbi5sZXZlbCk7XG4gICAgfVxuICAgIHJldHVybiBudWxsO1xuICB9XG5cbiAgLyoqIEJpbnMgb2YgdGhlIGFsbC1nZW5lIHB5cmFtaWQgYXQgYGxldmVsYCwgc2l6ZWQgYnkgaG93IG1hbnkgdHJhbnNjcmlwdHMgZWFjaCBob2xkcy4gKi9cbiAgcHJpdmF0ZSBiaW5zSm9iKFxuICAgIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsIHJlY3Q6IERhdGFSZWN0LCBweFBlclVuaXQ6IG51bWJlciwgYm91bmRzOiBTcGF0aWFsQm91bmRzLFxuICAgIGJpbnM6IE5vbk51bGxhYmxlPFNwYXRpYWxEYXRhc2V0Wyd0cmFuc2NyaXB0QmlucyddPiwgbGV2ZWw6IG51bWJlcixcbiAgKTogVHJhbnNjcmlwdEpvYiB7XG4gICAgY29uc3QgbHYgPSBiaW5zLmxldmVsc1tsZXZlbF07XG4gICAgY29uc3Qga2V5cyA9IHRpbGVzSW5SZWN0RnJvbShiaW5zLm9yaWdpbiwgcmVjdCwgbGV2ZWwsXG4gICAgICBiaW5zLmxldmVscy5tYXAoKGwpID0+ICh7IHRpbGVTaXplOiBsLnRpbGVTaXplIH0pKSwgYm91bmRzLCBNQVhfQklOX1RJTEVTKTtcbiAgICByZXR1cm4ge1xuICAgICAga2luZDogJ2JpbnMnLFxuICAgICAgYmluOiB7IHNpemU6IGx2LmJpblNpemUsIG9yaWdpbjogYmlucy5vcmlnaW4gfSxcbiAgICAgIGtleTogYGFsbHxiaW5zfCR7bGV2ZWx9fCR7dmlldy50cmFuc2NyaXB0QnVkZ2V0fXwke2tleXMubWFwKHRpbGVJZCl9YCxcbiAgICAgIGxvYWQ6IGFzeW5jICgpID0+IHtcbiAgICAgICAgY29uc3QgZ290ID0gYXdhaXQgdGhpcy5mZXRjaEFsbChrZXlzLCAoaykgPT4gdGhpcy5wb3J0LmdldFRyYW5zY3JpcHRCaW5zIShrLmxldmVsLCBrLmd4LCBrLmd5KSk7XG4gICAgICAgIGNvbnN0IG1lcmdlZCA9IG1lcmdlVHJhbnNjcmlwdFRpbGVzKGdvdCwgTWF0aC5tYXgodmlldy50cmFuc2NyaXB0QnVkZ2V0ICogMS41LCAxKSk7XG4gICAgICAgIGNvbnN0IHJlZkNvdW50ID0gcXVhbnRpbGVPZihtZXJnZWQud2VpZ2h0LCAwLjk1KTtcbiAgICAgICAgY29uc3QgYmluUHggPSBsdi5iaW5TaXplICogcHhQZXJVbml0O1xuICAgICAgICBjb25zdCBweCA9IG5ldyBGbG9hdDMyQXJyYXkobWVyZ2VkLmNvdW50KTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBtZXJnZWQuY291bnQ7IGkrKykge1xuICAgICAgICAgIHB4W2ldID0gZ3JvdXBlZE1hcmtlclB4KG1lcmdlZC53ZWlnaHRbaV0sIHJlZkNvdW50LCBiaW5QeCwgdmlldy50cmFuc2NyaXB0U2NhbGUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7IG1lcmdlZCwgcHggfTtcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIC8qKiBQZXItZW50cnkgY29sb3VycyBib3RoIGFzIFJHQkEgKHBvaW50cykgYW5kIGFzIGNvbG9ybWFwIHZhbHVlcyAoZ2x5cGggc2hhcGVzKS4gKi9cbiAgcHJpdmF0ZSBhc3luYyB0cmFuc2NyaXB0Q29sb3JzKFxuICAgIGRhdGFzZXQ6IFNwYXRpYWxEYXRhc2V0LCB2aWV3OiBTcGF0aWFsVmlld1N0YXRlLCB0OiBTcGF0aWFsVHJhbnNjcmlwdFRpbGUsXG4gICk6IFByb21pc2U8VHJhbnNjcmlwdEZhY2VzPiB7XG4gICAgbGV0IHJnYjogUmdiW107XG4gICAgbGV0IGNvZGVPZjogKGk6IG51bWJlcikgPT4gbnVtYmVyO1xuICAgIGlmICh2aWV3LnRyYW5zY3JpcHRDb2xvckJ5ID09PSAnZ2VuZScpIHtcbiAgICAgIC8vIEFsbCBnZW5lczogY29kZXMgYXJlIHRoZSBkYXRhc2V0J3MgZ2VuZSBpbmRpY2VzLCBmb2xkZWQgb250byB0aGUgcGFsZXR0ZS5cbiAgICAgIGNvbnN0IG4gPSB2aWV3LnRyYW5zY3JpcHRBbGxHZW5lcyA/IERFRkFVTFRfQ0FURUdPUklDQUxfUEFMRVRURS5sZW5ndGggOiB2aWV3LnRyYW5zY3JpcHRHZW5lcy5sZW5ndGg7XG4gICAgICByZ2IgPSBBcnJheS5mcm9tKHsgbGVuZ3RoOiBuIH0sIChfZywgaSkgPT4gcGFyc2VIZXgoXG4gICAgICAgICghdmlldy50cmFuc2NyaXB0QWxsR2VuZXMgJiYgdmlldy50cmFuc2NyaXB0R2VuZUNvbG9yc1t2aWV3LnRyYW5zY3JpcHRHZW5lc1tpXV0pXG4gICAgICAgIHx8IERFRkFVTFRfQ0FURUdPUklDQUxfUEFMRVRURVtpICUgREVGQVVMVF9DQVRFR09SSUNBTF9QQUxFVFRFLmxlbmd0aF0pKTtcbiAgICAgIGNvZGVPZiA9IHZpZXcudHJhbnNjcmlwdEFsbEdlbmVzID8gKGkpID0+IHQuZ2VuZVtpXSAlIG4gOiAoaSkgPT4gdC5nZW5lW2ldO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBuYW1lID0gdGhpcy5jZWxsVHlwZUNvbHVtbk5hbWUoZGF0YXNldCwgdmlldyk7XG4gICAgICBjb25zdCBjb2RlcyA9IG5hbWUgPyBhd2FpdCB0aGlzLmNhdGVnb3JpY2FsQ29kZXMobmFtZSkgOiBudWxsO1xuICAgICAgcmdiID0gY29kZXM/Lm1ldGEua2luZCA9PT0gJ2NhdGVnb3JpY2FsJyA/IHJlc29sdmVDYXRlZ29yeUNvbG9ycyhjb2Rlcy5tZXRhKS5tYXAocGFyc2VIZXgpIDogW107XG4gICAgICBjb2RlT2YgPSAoaSkgPT4ge1xuICAgICAgICBjb25zdCBvID0gdC5vYnNlcnZhdGlvbltpXTtcbiAgICAgICAgaWYgKCFjb2RlcyB8fCBvID09PSBOT19PQlNFUlZBVElPTikgcmV0dXJuIC0xO1xuICAgICAgICBjb25zdCBjID0gY29kZXMuY29kZXNbb107XG4gICAgICAgIHJldHVybiBjID09PSBOT19DQVRFR09SWSA/IC0xIDogYztcbiAgICAgIH07XG4gICAgfVxuICAgIGNvbnN0IHsgc3RvcHMsIHZhbHVlT2YgfSA9IGRpc2NyZXRlQ29sb3JtYXBTdG9wcyhyZ2IsIE1JU1NJTkdfQ09MT1IpO1xuICAgIGNvbnN0IHJnYmE6IFJHQkFbXSA9IG5ldyBBcnJheSh0LmNvdW50KTtcbiAgICBjb25zdCB2YWx1ZXMgPSBuZXcgRmxvYXQzMkFycmF5KHQuY291bnQpO1xuICAgIGNvbnN0IHR1cGxlczogUkdCQVtdID0gcmdiLm1hcCgoW3IsIGcsIGJdKSA9PiBbciAvIDI1NSwgZyAvIDI1NSwgYiAvIDI1NSwgMV0pO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdC5jb3VudDsgaSsrKSB7XG4gICAgICBjb25zdCBjID0gY29kZU9mKGkpO1xuICAgICAgcmdiYVtpXSA9IGMgPCAwID8gVU5BU1NJR05FRF9SR0JBIDogdHVwbGVzW2NdO1xuICAgICAgdmFsdWVzW2ldID0gdmFsdWVPZihjKTtcbiAgICB9XG4gICAgcmV0dXJuIHsgcmdiYSwgdmFsdWVzLCBjb2xvcm1hcDogbmV3IENvbG9ybWFwKCd0cmFuc2NyaXB0LWNhdGVnb3JpZXMnLCBzdG9wcykgfTtcbiAgfVxuXG4gIC8vIOKUgOKUgCBkZW5zaXR5IOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIHByaXZhdGUgYXN5bmMgcGxhbkRlbnNpdHkoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsIHN0YWxlOiAoKSA9PiBib29sZWFuLFxuICApOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBoaWRkZW5HZW5lcyA9IG5ldyBTZXQodmlldy50cmFuc2NyaXB0SGlkZGVuR2VuZXMpO1xuICAgIGNvbnN0IGdlbmVzID0gdmlldy50cmFuc2NyaXB0QWxsR2VuZXNcbiAgICAgID8gW0FMTF9HRU5FU11cbiAgICAgIDogdmlldy50cmFuc2NyaXB0R2VuZXMuZmlsdGVyKChnKSA9PiAhaGlkZGVuR2VuZXMuaGFzKGcpKTtcbiAgICBpZiAoIWRhdGFzZXQuZGVuc2l0eSB8fCAhdGhpcy5wb3J0LmdldERlbnNpdHkgfHwgdmlldy50cmFuc2NyaXB0TW9kZSAhPT0gJ2RlbnNpdHknIHx8ICFnZW5lcy5sZW5ndGgpIHtcbiAgICAgIHRoaXMuZHJvcCgnZGVuc2l0eScpO1xuICAgICAgdGhpcy5kZW5zaXR5U3RhdHMgPSBudWxsO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBsdXQgPSBsdXRGb3Iodmlldy5kZW5zaXR5Q29sb3JtYXAgPz8gSU5GRVJOT19TQ0FMRSk7XG4gICAgY29uc3Qga2V5ID0gW2RhdGFzZXQuaWQsIGdlbmVzLmpvaW4oJywnKSwgdmlldy5kZW5zaXR5QmluLCB2aWV3LmRlbnNpdHlPcGFjaXR5LFxuICAgICAgSlNPTi5zdHJpbmdpZnkodmlldy5kZW5zaXR5UmFuZ2UpLCBKU09OLnN0cmluZ2lmeSh2aWV3LmRlbnNpdHlDb2xvcm1hcCldLmpvaW4oJ3wnKTtcbiAgICBpZiAoa2V5ID09PSB0aGlzLmtleXMuZ2V0KCdkZW5zaXR5JykgJiYgdGhpcy5sYXllcnMuaGFzKCdkZW5zaXR5JykpIHJldHVybjtcbiAgICBjb25zdCByYXN0ZXIgPSBhd2FpdCB0aGlzLnBvcnQuZ2V0RGVuc2l0eShnZW5lcywgdmlldy5kZW5zaXR5QmluKTtcbiAgICBpZiAoc3RhbGUoKSkgcmV0dXJuO1xuXG4gICAgLy8gQmlucyBkcmF3biBhcyBzcXVhcmVzLCBhcyBYZW5pdW0gRXhwbG9yZXIgZG9lczsgdGhlIHdpbmRvdyBpcyBpbiB0cmFuc2NyaXB0cy/CtW3Csi5cbiAgICBjb25zdCBtZXRhID0gcmFzdGVyLm1ldGE7XG4gICAgY29uc3QgYXJlYSA9IG1ldGEuZ3JpZFNpemVbMF0gKiBtZXRhLmdyaWRTaXplWzFdO1xuICAgIGNvbnN0IHBlckFyZWEgPSByYXN0ZXIudmFsdWVzLm1hcCgodikgPT4gdiAvIGFyZWEpO1xuICAgIGNvbnN0IFtsbywgaGldID0gdmlldy5kZW5zaXR5UmFuZ2UgPz8gZGVuc2l0eUF1dG9SYW5nZShwZXJBcmVhKTtcbiAgICB0aGlzLmRlbnNpdHlTdGF0cyA9IHsgbG8sIGhpLCBtYXg6IHBlckFyZWEucmVkdWNlKChtLCB2KSA9PiAodiA+IG0gPyB2IDogbSksIDApIH07XG4gICAgY29uc3QgcmdiYSA9IGNvbG9yRGVuc2l0eVdpbmRvdyhwZXJBcmVhLCBsdXQsIHZpZXcuZGVuc2l0eU9wYWNpdHksIGxvLCBoaSk7XG4gICAgY29uc3QgcmVmID0gZGF0YXNldC5pbWFnZVJlZjtcbiAgICBjb25zdCBzeCA9IHJlZj8uc2NhbGU/LlswXSA/PyAxO1xuICAgIGNvbnN0IHN5ID0gcmVmPy5zY2FsZT8uWzFdID8/IDE7XG4gICAgY29uc3QgbGF5ZXI6IEltYWdlTGF5ZXIgPSB0aGlzLnZpZXdlciEuYWRkSW1hZ2UoXG4gICAgICB7IGtpbmQ6ICd0eXBlZCcsIHdpZHRoOiBtZXRhLmNvbHMsIGhlaWdodDogbWV0YS5yb3dzLCBjaGFubmVsczogNCwgZHR5cGU6ICd1aW50OCcsIGRhdGE6IHJnYmEgfSxcbiAgICAgIHtcbiAgICAgICAgbmFtZTogYGRlbnNpdHkgwrcgJHt2aWV3LnRyYW5zY3JpcHRBbGxHZW5lcyA/ICdhbGwgZ2VuZXMnIDogZ2VuZXMuam9pbignLCAnKX1gLFxuICAgICAgICBzY2FsZTogW21ldGEuZ3JpZFNpemVbMF0gKiBzeCwgbWV0YS5ncmlkU2l6ZVsxXSAqIHN5XSxcbiAgICAgICAgdHJhbnNsYXRlOiBbXG4gICAgICAgICAgbWV0YS5vcmlnaW5bMF0gKiBzeCArIChyZWY/LnRyYW5zbGF0ZT8uWzBdID8/IDApLFxuICAgICAgICAgIG1ldGEub3JpZ2luWzFdICogc3kgKyAocmVmPy50cmFuc2xhdGU/LlsxXSA/PyAwKSxcbiAgICAgICAgXSxcbiAgICAgICAgYmxlbmRpbmc6ICd0cmFuc2x1Y2VudCcsXG4gICAgICAgIGludGVycG9sYXRpb246ICduZWFyZXN0JyxcbiAgICAgIH0sXG4gICAgKTtcbiAgICB0aGlzLmtleXMuc2V0KCdkZW5zaXR5Jywga2V5KTtcbiAgICB0aGlzLnJlcGxhY2UoJ2RlbnNpdHknLCBsYXllcik7XG4gICAgdGhpcy5ob3N0LmRlbnNpdHlDaGFuZ2VkPy4odGhpcy5kZW5zaXR5U3RhdHMpO1xuICB9XG5cbiAgcHJpdmF0ZSBjb3VudHNDYWNoZTogeyBrZXk6IHN0cmluZzsgY291bnRzOiBQcm9taXNlPFNwYXRpYWxUcmFuc2NyaXB0Q291bnRzPiB9IHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFRyYW5zY3JpcHRzIGluIHZpZXcgZm9yIHRoZSB2aXNpYmxlIGdlbmVzOiBlYWNoIGdlbmUncyBkYXRhc2V0IHRvdGFsIHRpbWVzIHRoZSBzaGFyZVxuICAgKiBvZiB0aGUgdGlzc3VlIG9uIHNjcmVlbi4gQW4gZXN0aW1hdGUg4oCUIGV4cHJlc3Npb24gaXMgbm90IHVuaWZvcm0g4oCUIHdoaWNoIGlzIGFsc28gd2hhdFxuICAgKiBYZW5pdW0gRXhwbG9yZXIgc2hvd3M7IGl0IHRlbGxzIHRoZSB1c2VyIHdoZXRoZXIgdGhlIGJ1ZGdldCB3aWxsIGZvcmNlIGdyb3VwaW5nLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwbGFuRXN0aW1hdGUoXG4gICAgZGF0YXNldDogU3BhdGlhbERhdGFzZXQsIHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUsIHZpZXdlcjogVmlld2VyLCB3OiBudW1iZXIsIGg6IG51bWJlcixcbiAgICBzdGFsZTogKCkgPT4gYm9vbGVhbixcbiAgKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgdGlsZXMgPSBkYXRhc2V0LnRyYW5zY3JpcHRUaWxlcztcbiAgICBpZiAoIXRpbGVzIHx8ICF0aGlzLnBvcnQuZ2V0VHJhbnNjcmlwdENvdW50cyB8fCB2aWV3LnRyYW5zY3JpcHRNb2RlID09PSAnb2ZmJykge1xuICAgICAgdGhpcy5ob3N0LmVzdGltYXRlQ2hhbmdlZD8uKG51bGwpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBoaWRkZW5HZW5lcyA9IG5ldyBTZXQodmlldy50cmFuc2NyaXB0SGlkZGVuR2VuZXMpO1xuICAgIGNvbnN0IGdlbmVzID0gdmlldy50cmFuc2NyaXB0QWxsR2VuZXMgPyBbXSA6IHZpZXcudHJhbnNjcmlwdEdlbmVzLmZpbHRlcigoZykgPT4gIWhpZGRlbkdlbmVzLmhhcyhnKSk7XG4gICAgY29uc3Qga2V5ID0gYCR7ZGF0YXNldC5pZH18JHtnZW5lcy5qb2luKCcsJyl9YDtcbiAgICBpZiAodGhpcy5jb3VudHNDYWNoZT8ua2V5ICE9PSBrZXkpIHtcbiAgICAgIHRoaXMuY291bnRzQ2FjaGUgPSB7IGtleSwgY291bnRzOiB0aGlzLnBvcnQuZ2V0VHJhbnNjcmlwdENvdW50cyhnZW5lcykgfTtcbiAgICB9XG4gICAgbGV0IGNvdW50czogU3BhdGlhbFRyYW5zY3JpcHRDb3VudHM7XG4gICAgdHJ5IHtcbiAgICAgIGNvdW50cyA9IGF3YWl0IHRoaXMuY291bnRzQ2FjaGUuY291bnRzO1xuICAgIH0gY2F0Y2gge1xuICAgICAgdGhpcy5jb3VudHNDYWNoZSA9IG51bGw7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmIChzdGFsZSgpKSByZXR1cm47XG4gICAgY29uc3QgaW5WaWV3ID0gdmlzaWJsZURhdGFSZWN0KHZpZXdlci5jYW1lcmEuY2VudGVyLCB2aWV3ZXIuY2FtZXJhLnpvb20sIHcsIGgsIGRhdGFzZXQuaW1hZ2VSZWYsIDApO1xuICAgIGlmICghaW5WaWV3KSByZXR1cm47XG4gICAgY29uc3QgYiA9IGNvdW50cy5ib3VuZHM7XG4gICAgY29uc3Qgc2hhcmUgPSBNYXRoLm1pbigxLCB2aXNpYmxlQXJlYShpblZpZXcsIGIpIC8gTWF0aC5tYXgoMSwgKGJbMl0gLSBiWzBdKSAqIChiWzNdIC0gYlsxXSkpKTtcbiAgICBjb25zdCBzZWxlY3RlZCA9IHZpZXcudHJhbnNjcmlwdEFsbEdlbmVzXG4gICAgICA/IGNvdW50cy50b3RhbFxuICAgICAgOiBnZW5lcy5yZWR1Y2UoKHN1bSwgZykgPT4gc3VtICsgKGNvdW50cy5jb3VudHNbZ10gPz8gMCksIDApO1xuICAgIHRoaXMuaG9zdC5lc3RpbWF0ZUNoYW5nZWQ/Lih7IHBvaW50czogTWF0aC5yb3VuZChzZWxlY3RlZCAqIHNoYXJlKSwgbWF4OiB2aWV3LnRyYW5zY3JpcHRCdWRnZXQgfSk7XG4gIH1cblxuICAvKiogVGhlIGRlbnNpdHkgd2luZG93IGluIHVzZSBhbmQgdGhlIGRlbnNlc3QgYmluLCBmb3IgdGhlIHBhbmVsJ3MgdGhyZXNob2xkIGNvbnRyb2wuICovXG4gIGRlbnNpdHlTdGF0czogeyBsbzogbnVtYmVyOyBoaTogbnVtYmVyOyBtYXg6IG51bWJlciB9IHwgbnVsbCA9IG51bGw7XG5cbiAgLy8g4pSA4pSAIGxheWVyIGJvb2trZWVwaW5nIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4gIC8qKlxuICAgKiBGZXRjaCBldmVyeSB0aWxlLCBkcmF3aW5nIHdoYXQgYXJyaXZlZC4gQSBmYWlsdXJlIGRvZXMgbm90IGZhaWwgdGhlIHZpZXcsIGJ1dCBpdCBtYXJrcyB0aGVcbiAgICogcGxhbiBpbmNvbXBsZXRlOiB0aGUgY2FsbGVyIG11c3Qgbm90IGNhY2hlIGl0IGFzIGRvbmUsIGFuZCBgcGxhbigpYCByZXRyaWVzIGl0LlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBmZXRjaEFsbDxLLCBUPihrZXlzOiBLW10sIGxvYWQ6IChrOiBLKSA9PiBQcm9taXNlPFQ+KTogUHJvbWlzZTxUW10+IHtcbiAgICBjb25zdCBzZXR0bGVkID0gYXdhaXQgUHJvbWlzZS5hbGxTZXR0bGVkKGtleXMubWFwKGxvYWQpKTtcbiAgICBjb25zdCBvdXQ6IFRbXSA9IFtdO1xuICAgIGZvciAoY29uc3QgcyBvZiBzZXR0bGVkKSB7XG4gICAgICBpZiAocy5zdGF0dXMgPT09ICdmdWxmaWxsZWQnKSBvdXQucHVzaChzLnZhbHVlKTtcbiAgICAgIGVsc2UgY29uc29sZS53YXJuKCdbbmFwYXJpLWpzXSBzcGF0aWFsIHRpbGUgZmFpbGVkJywgcy5yZWFzb24pO1xuICAgIH1cbiAgICBpZiAob3V0Lmxlbmd0aCA8IGtleXMubGVuZ3RoKSB0aGlzLnBsYW5JbmNvbXBsZXRlID0gdHJ1ZTtcbiAgICByZXR1cm4gb3V0O1xuICB9XG5cbiAgLyoqXG4gICAqIFB1dCBhIHNoYXBlcyBsYXllciBpbiBwbGFjZSBmb3IgYGdyb3VwYDogYSBnZW9tZXRyeSBjaGFuZ2UgYnVpbGRzIGEgbmV3IGxheWVyLCBhXG4gICAqIGNvbG91ci1vbmx5IGNoYW5nZSBtdXRhdGVzIHZhbHVlcy9jb2xvcm1hcCBvbiB0aGUgZXhpc3Rpbmcgb25lLlxuICAgKi9cbiAgcHJpdmF0ZSB1cHNlcnRTaGFwZXMoXG4gICAgZ3JvdXA6IEdyb3VwLCB3YW50ZWQ6IGJvb2xlYW4sIGdlb21ldHJ5Q2hhbmdlZDogYm9vbGVhbiwgcmluZ3M6IFNwYXRpYWxQb2x5Z29ucyxcbiAgICBvcHRzOiBQYXJhbWV0ZXJzPFZpZXdlclsnYWRkU2hhcGVzJ10+WzJdICYgb2JqZWN0LFxuICApOiB2b2lkIHtcbiAgICBpZiAoIXdhbnRlZCkge1xuICAgICAgdGhpcy5kcm9wKGdyb3VwKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZXhpc3RpbmcgPSB0aGlzLmxheWVycy5nZXQoZ3JvdXApIGFzIFNoYXBlc0xheWVyIHwgdW5kZWZpbmVkO1xuICAgIGlmIChleGlzdGluZyAmJiAhZ2VvbWV0cnlDaGFuZ2VkICYmIHRoaXMudmlld2VyIS5sYXllcnMuaXRlbXMuaW5jbHVkZXMoZXhpc3RpbmcpKSB7XG4gICAgICAvLyBGbGF0IGNvbG91ciBoYXMgbm8gdmFsdWVzOyBjbGVhcmluZyB0aGVtIGlzIHdoYXQgc3dpdGNoZXMgdGhlIGxheWVyIHRvIGBjb2xvcmAuXG4gICAgICBleGlzdGluZy52YWx1ZXMgPSBvcHRzLnZhbHVlcyA/PyBudWxsO1xuICAgICAgaWYgKG9wdHMuY29sb3JtYXApIGV4aXN0aW5nLmNvbG9ybWFwID0gb3B0cy5jb2xvcm1hcDtcbiAgICAgIGlmIChvcHRzLmNvbnRyYXN0TGltaXRzKSBleGlzdGluZy5jb250cmFzdExpbWl0cyA9IG9wdHMuY29udHJhc3RMaW1pdHM7XG4gICAgICBpZiAob3B0cy5jb2xvcikgZXhpc3RpbmcuY29sb3IgPSBvcHRzLmNvbG9yO1xuICAgICAgaWYgKG9wdHMub3BhY2l0eSAhPT0gdW5kZWZpbmVkKSBleGlzdGluZy5vcGFjaXR5ID0gb3B0cy5vcGFjaXR5O1xuICAgICAgdGhpcy52aWV3ZXIhLnJlcXVlc3RSZW5kZXIoKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgbGF5ZXIgPSB0aGlzLnZpZXdlciEuYWRkU2hhcGVzKHJpbmdzLmNvb3JkcywgcmluZ3Mub2Zmc2V0cywgb3B0cyk7XG4gICAgdGhpcy5yZXBsYWNlKGdyb3VwLCBsYXllcik7XG4gIH1cblxuICAvKipcbiAgICogSW5zdGFsbCBgbGF5ZXJgIGFzIGBncm91cGAncyBsYXllciBhbmQgcmVzdG9yZSB0aGUgb3JkZXIgb2YgdGhlIGdyb3VwcyBhYm92ZSBpdC5cbiAgICogVGhlIGxheWVyIHdhcyBqdXN0IGFkZGVkIGJ5IHRoZSBjYWxsZXIgKHNvIGl0IGlzIG9uIHRvcCk7IGdyb3VwcyB0aGF0IGJlbG9uZyBhYm92ZVxuICAgKiBpdCBhcmUgcmVtb3ZlZCBhbmQgcmUtYWRkZWQuXG4gICAqL1xuICBwcml2YXRlIHJlcGxhY2UoZ3JvdXA6IEdyb3VwLCBsYXllcjogTGF5ZXIpOiB2b2lkIHtcbiAgICBjb25zdCB2ID0gdGhpcy52aWV3ZXIhO1xuICAgIGNvbnN0IG9sZCA9IHRoaXMubGF5ZXJzLmdldChncm91cCk7XG4gICAgaWYgKG9sZCAmJiBvbGQgIT09IGxheWVyICYmIHYubGF5ZXJzLml0ZW1zLmluY2x1ZGVzKG9sZCkpIHYubGF5ZXJzLnJlbW92ZShvbGQpO1xuICAgIHRoaXMubGF5ZXJzLnNldChncm91cCwgbGF5ZXIpO1xuICAgIGZvciAoY29uc3QgZyBvZiBPUkRFUi5zbGljZShPUkRFUi5pbmRleE9mKGdyb3VwKSArIDEpKSB7XG4gICAgICBjb25zdCBhYm92ZSA9IHRoaXMubGF5ZXJzLmdldChnKTtcbiAgICAgIGlmICghYWJvdmUgfHwgIXYubGF5ZXJzLml0ZW1zLmluY2x1ZGVzKGFib3ZlKSkgY29udGludWU7XG4gICAgICB2LmxheWVycy5yZW1vdmUoYWJvdmUpO1xuICAgICAgdi5sYXllcnMuYWRkKGFib3ZlKTtcbiAgICB9XG4gICAgdi5yZXF1ZXN0UmVuZGVyKCk7XG4gIH1cblxuICBwcml2YXRlIGRyb3AoZ3JvdXA6IEdyb3VwKTogdm9pZCB7XG4gICAgY29uc3QgbGF5ZXIgPSB0aGlzLmxheWVycy5nZXQoZ3JvdXApO1xuICAgIGlmIChsYXllciAmJiB0aGlzLnZpZXdlcj8ubGF5ZXJzLml0ZW1zLmluY2x1ZGVzKGxheWVyKSkgdGhpcy52aWV3ZXIubGF5ZXJzLnJlbW92ZShsYXllcik7XG4gICAgdGhpcy5sYXllcnMuZGVsZXRlKGdyb3VwKTtcbiAgICB0aGlzLmtleXMuZGVsZXRlKGdyb3VwKTtcbiAgfVxuXG4gIHByaXZhdGUgZHJvcENlbGxzKCk6IHZvaWQge1xuICAgIHRoaXMuZHJvcCgnY2VsbEZpbGwnKTtcbiAgICB0aGlzLmRyb3AoJ2NlbGxPdXRsaW5lJyk7XG4gICAgdGhpcy5kcm9wKCdudWNsZXVzT3V0bGluZScpO1xuICAgIHRoaXMuY3VycmVudE51Y2xlaSA9IG51bGw7XG4gICAgdGhpcy5jZWxsR2VvbWV0cnlLZXkgPSBudWxsO1xuICAgIHRoaXMuY2VsbFN0eWxlS2V5ID0gbnVsbDtcbiAgICB0aGlzLmN1cnJlbnRSaW5ncyA9IG51bGw7XG4gICAgdGhpcy5zZXRQb2x5Z29uc1Nob3duKGZhbHNlKTtcbiAgfVxuXG4gIHByaXZhdGUgc2V0UG9seWdvbnNTaG93bihzaG93bjogYm9vbGVhbik6IHZvaWQge1xuICAgIGlmIChzaG93biA9PT0gdGhpcy5wb2x5Z29uc1Nob3duKSByZXR1cm47XG4gICAgdGhpcy5wb2x5Z29uc1Nob3duID0gc2hvd247XG4gICAgdGhpcy5ob3N0LnBvbHlnb25zU2hvd25DaGFuZ2VkKHNob3duKTtcbiAgfVxufVxuXG4vKiogV2hhdCB0aGUgdHJhbnNjcmlwdCBsYXllciBjdXJyZW50bHkgc2hvd3Mg4oCUIHdoYXQgaG92ZXJpbmcgbmVlZHMgdG8gbmFtZSBhIG1hcmtlci4gKi9cbmludGVyZmFjZSBEcmF3blRyYW5zY3JpcHRzIHtcbiAga2luZDogVHJhbnNjcmlwdEpvYlsna2luZCddO1xuICBiaW4/OiBUcmFuc2NyaXB0Sm9iWydiaW4nXTtcbiAgbWVyZ2VkOiBTcGF0aWFsVHJhbnNjcmlwdFRpbGU7XG4gIC8qKiBNYXJrZXIgcmFkaXVzIHBlciBlbnRyeSwgaW4gb2JzZXJ2YXRpb24gdW5pdHMuICovXG4gIHJhZGl1czogRmxvYXQzMkFycmF5O1xuICBnZW5lczogc3RyaW5nW107XG4gIHJlZjogU3BhdGlhbEltYWdlUmVmIHwgbnVsbDtcbiAgLyoqIExhemlseSBidWlsdCBzcGF0aWFsIGluZGV4OiBidWNrZXQg4oaSIGVudHJ5IGluZGljZXMuICovXG4gIGdyaWQ6IHsgc2l6ZTogbnVtYmVyOyBidWNrZXRzOiBNYXA8bnVtYmVyLCBudW1iZXJbXT4gfSB8IG51bGw7XG59XG5cbi8qKiBJbmRleCBvZiB0aGUgZW50cnkgdW5kZXIgYCh4LCB5KWAg4oCUIHdpdGhpbiBpdHMgb3duIHJhZGl1cyBvciBgdG9sZXJhbmNlYCDigJQgb3IgLTEuICovXG5leHBvcnQgZnVuY3Rpb24gcGlja05lYXJlc3QoXG4gIGQ6IFBpY2s8RHJhd25UcmFuc2NyaXB0cywgJ21lcmdlZCcgfCAncmFkaXVzJyB8ICdncmlkJz4sIHg6IG51bWJlciwgeTogbnVtYmVyLCB0b2xlcmFuY2U6IG51bWJlcixcbik6IG51bWJlciB7XG4gIGNvbnN0IHQgPSBkLm1lcmdlZDtcbiAgaWYgKCFkLmdyaWQpIHtcbiAgICBsZXQgbWF4UiA9IDA7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0LmNvdW50OyBpKyspIGlmIChkLnJhZGl1c1tpXSA+IG1heFIpIG1heFIgPSBkLnJhZGl1c1tpXTtcbiAgICBjb25zdCBzaXplID0gTWF0aC5tYXgobWF4UiAqIDIsIHRvbGVyYW5jZSAqIDIsIDFlLTYpO1xuICAgIGNvbnN0IGJ1Y2tldHMgPSBuZXcgTWFwPG51bWJlciwgbnVtYmVyW10+KCk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0LmNvdW50OyBpKyspIHtcbiAgICAgIGNvbnN0IGsgPSBidWNrZXRLZXkoTWF0aC5mbG9vcih0LnhbaV0gLyBzaXplKSwgTWF0aC5mbG9vcih0LnlbaV0gLyBzaXplKSk7XG4gICAgICBsZXQgYiA9IGJ1Y2tldHMuZ2V0KGspO1xuICAgICAgaWYgKCFiKSBidWNrZXRzLnNldChrLCAoYiA9IFtdKSk7XG4gICAgICBiLnB1c2goaSk7XG4gICAgfVxuICAgIGQuZ3JpZCA9IHsgc2l6ZSwgYnVja2V0cyB9O1xuICB9XG4gIGNvbnN0IHsgc2l6ZSwgYnVja2V0cyB9ID0gZC5ncmlkO1xuICBjb25zdCBneCA9IE1hdGguZmxvb3IoeCAvIHNpemUpO1xuICBjb25zdCBneSA9IE1hdGguZmxvb3IoeSAvIHNpemUpO1xuICBsZXQgYmVzdCA9IC0xO1xuICBsZXQgYmVzdEQgPSBJbmZpbml0eTtcbiAgZm9yIChsZXQgZHkgPSAtMTsgZHkgPD0gMTsgZHkrKykge1xuICAgIGZvciAobGV0IGR4ID0gLTE7IGR4IDw9IDE7IGR4KyspIHtcbiAgICAgIGZvciAoY29uc3QgaSBvZiBidWNrZXRzLmdldChidWNrZXRLZXkoZ3ggKyBkeCwgZ3kgKyBkeSkpID8/IFtdKSB7XG4gICAgICAgIGNvbnN0IGRpc3QgPSBNYXRoLmh5cG90KHQueFtpXSAtIHgsIHQueVtpXSAtIHkpO1xuICAgICAgICBpZiAoZGlzdCA8PSBNYXRoLm1heChkLnJhZGl1c1tpXSwgdG9sZXJhbmNlKSAmJiBkaXN0IDwgYmVzdEQpIHtcbiAgICAgICAgICBiZXN0RCA9IGRpc3Q7XG4gICAgICAgICAgYmVzdCA9IGk7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgcmV0dXJuIGJlc3Q7XG59XG5cbmZ1bmN0aW9uIGJ1Y2tldEtleShneDogbnVtYmVyLCBneTogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIChneCArIDMyNzY4KSAqIDY1NTM2ICsgKGd5ICsgMzI3NjgpO1xufVxuXG4vKiogUmluZ3Mgd2hvc2Ugb3duaW5nIGNlbGwgaXMgaW4gYSBzd2l0Y2hlZC1vZmYgZ3JvdXAgcmVtb3ZlZC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmaWx0ZXJSaW5ncyhcbiAgcmluZ3M6IFNwYXRpYWxQb2x5Z29uVGlsZSwgaGlkZGVuOiB7IGNvZGVzOiBVaW50MTZBcnJheTsgaGlkZGVuOiBVaW50OEFycmF5IH0gfCBudWxsLFxuKTogU3BhdGlhbFBvbHlnb25UaWxlIHtcbiAgaWYgKCFoaWRkZW4pIHJldHVybiByaW5ncztcbiAgY29uc3Qga2VlcDogbnVtYmVyW10gPSBbXTtcbiAgbGV0IHZlcnRpY2VzID0gMDtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCByaW5ncy5jb3VudDsgaSsrKSB7XG4gICAgY29uc3QgY29kZSA9IGhpZGRlbi5jb2Rlc1tyaW5ncy5vYnNlcnZhdGlvbltpXV07XG4gICAgaWYgKGNvZGUgIT09IE5PX0NBVEVHT1JZICYmIGhpZGRlbi5oaWRkZW5bY29kZV0pIGNvbnRpbnVlO1xuICAgIGtlZXAucHVzaChpKTtcbiAgICB2ZXJ0aWNlcyArPSByaW5ncy5vZmZzZXRzW2kgKyAxXSAtIHJpbmdzLm9mZnNldHNbaV07XG4gIH1cbiAgaWYgKGtlZXAubGVuZ3RoID09PSByaW5ncy5jb3VudCkgcmV0dXJuIHJpbmdzO1xuICBjb25zdCBvYnNlcnZhdGlvbiA9IG5ldyBVaW50MzJBcnJheShrZWVwLmxlbmd0aCk7XG4gIGNvbnN0IG9mZnNldHMgPSBuZXcgVWludDMyQXJyYXkoa2VlcC5sZW5ndGggKyAxKTtcbiAgY29uc3QgY29vcmRzID0gbmV3IEZsb2F0MzJBcnJheSh2ZXJ0aWNlcyAqIDIpO1xuICBsZXQgdiA9IDA7XG4gIGtlZXAuZm9yRWFjaCgoaSwgcikgPT4ge1xuICAgIG9ic2VydmF0aW9uW3JdID0gcmluZ3Mub2JzZXJ2YXRpb25baV07XG4gICAgb2Zmc2V0c1tyXSA9IHY7XG4gICAgY29uc3QgYSA9IHJpbmdzLm9mZnNldHNbaV0gKiAyO1xuICAgIGNvbnN0IGIgPSByaW5ncy5vZmZzZXRzW2kgKyAxXSAqIDI7XG4gICAgY29vcmRzLnNldChyaW5ncy5jb29yZHMuc3ViYXJyYXkoYSwgYiksIHYgKiAyKTtcbiAgICB2ICs9IChiIC0gYSkgLyAyO1xuICB9KTtcbiAgb2Zmc2V0c1trZWVwLmxlbmd0aF0gPSB2O1xuICByZXR1cm4geyBjb3VudDoga2VlcC5sZW5ndGgsIG9ic2VydmF0aW9uLCBvZmZzZXRzLCBjb29yZHMgfTtcbn1cblxuLyoqIFNsb3RzIChpbmRpY2VzIGludG8gdGhlIHNlbGVjdGVkIGdlbmVzKSBzd2l0Y2hlZCBvZmYgd2l0aCB0aGVpciBleWUgdG9nZ2xlLiAqL1xuZnVuY3Rpb24gaGlkZGVuR2VuZVNsb3RzKHZpZXc6IFNwYXRpYWxWaWV3U3RhdGUpOiBVaW50OEFycmF5IHwgbnVsbCB7XG4gIGlmICghdmlldy50cmFuc2NyaXB0SGlkZGVuR2VuZXMubGVuZ3RoKSByZXR1cm4gbnVsbDtcbiAgY29uc3Qgb2ZmID0gbmV3IFNldCh2aWV3LnRyYW5zY3JpcHRIaWRkZW5HZW5lcyk7XG4gIHJldHVybiBVaW50OEFycmF5LmZyb20odmlldy50cmFuc2NyaXB0R2VuZXMsIChnKSA9PiAob2ZmLmhhcyhnKSA/IDEgOiAwKSk7XG59XG5cbi8qKiBFbnRyaWVzIGluIGEgaGlkZGVuIGdyb3VwJ3MgY2VsbCwgb3Igb2YgYSBoaWRkZW4gZ2VuZSwgcmVtb3ZlZCAod2l0aCB0aGVpciBzaXplcykuICovXG5leHBvcnQgZnVuY3Rpb24gZmlsdGVyVHJhbnNjcmlwdHMoXG4gIHQ6IFNwYXRpYWxUcmFuc2NyaXB0VGlsZSwgcHg6IEZsb2F0MzJBcnJheSxcbiAgaGlkZGVuOiB7IGNvZGVzOiBVaW50MTZBcnJheTsgaGlkZGVuOiBVaW50OEFycmF5IH0gfCBudWxsLCBoaWRkZW5HZW5lczogVWludDhBcnJheSB8IG51bGwsXG4pOiB7IG1lcmdlZDogU3BhdGlhbFRyYW5zY3JpcHRUaWxlOyBweDogRmxvYXQzMkFycmF5IH0ge1xuICBpZiAoIWhpZGRlbiAmJiAhaGlkZGVuR2VuZXMpIHJldHVybiB7IG1lcmdlZDogdCwgcHggfTtcbiAgY29uc3Qga2VlcDogbnVtYmVyW10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB0LmNvdW50OyBpKyspIHtcbiAgICBpZiAoaGlkZGVuR2VuZXMgJiYgaGlkZGVuR2VuZXNbdC5nZW5lW2ldXSkgY29udGludWU7XG4gICAgY29uc3QgbyA9IHQub2JzZXJ2YXRpb25baV07XG4gICAgaWYgKGhpZGRlbiAmJiBvICE9PSBOT19PQlNFUlZBVElPTikge1xuICAgICAgY29uc3QgY29kZSA9IGhpZGRlbi5jb2Rlc1tvXTtcbiAgICAgIGlmIChjb2RlICE9PSBOT19DQVRFR09SWSAmJiBoaWRkZW4uaGlkZGVuW2NvZGVdKSBjb250aW51ZTtcbiAgICB9XG4gICAga2VlcC5wdXNoKGkpO1xuICB9XG4gIGNvbnN0IHBpY2sgPSA8VCBleHRlbmRzIEZsb2F0MzJBcnJheSB8IFVpbnQzMkFycmF5IHwgVWludDE2QXJyYXk+KGE6IFQpOiBUID0+IHtcbiAgICBjb25zdCBvdXQgPSBuZXcgKGEuY29uc3RydWN0b3IgYXMgbmV3IChuOiBudW1iZXIpID0+IFQpKGtlZXAubGVuZ3RoKTtcbiAgICBrZWVwLmZvckVhY2goKGksIGspID0+IHsgb3V0W2tdID0gYVtpXTsgfSk7XG4gICAgcmV0dXJuIG91dDtcbiAgfTtcbiAgcmV0dXJuIHtcbiAgICBtZXJnZWQ6IHtcbiAgICAgIGNvdW50OiBrZWVwLmxlbmd0aCwgYWdncmVnYXRlZDogdC5hZ2dyZWdhdGVkLCB4OiBwaWNrKHQueCksIHk6IHBpY2sodC55KSwgejogcGljayh0LnopLFxuICAgICAgd2VpZ2h0OiBwaWNrKHQud2VpZ2h0KSwgb2JzZXJ2YXRpb246IHBpY2sodC5vYnNlcnZhdGlvbiksIGdlbmU6IHBpY2sodC5nZW5lKSxcbiAgICB9LFxuICAgIHB4OiBwaWNrKHB4KSxcbiAgfTtcbn1cblxuZnVuY3Rpb24gbWVkaWFuKHY6IEZsb2F0MzJBcnJheSk6IG51bWJlciB7XG4gIGlmICghdi5sZW5ndGgpIHJldHVybiAwO1xuICBjb25zdCBzdGVwID0gTWF0aC5tYXgoMSwgTWF0aC5mbG9vcih2Lmxlbmd0aCAvIDEwMjQpKTtcbiAgY29uc3Qgc2FtcGxlOiBudW1iZXJbXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHYubGVuZ3RoOyBpICs9IHN0ZXApIHNhbXBsZS5wdXNoKHZbaV0pO1xuICBzYW1wbGUuc29ydCgoYSwgYikgPT4gYSAtIGIpO1xuICByZXR1cm4gc2FtcGxlW3NhbXBsZS5sZW5ndGggPj4gMV07XG59XG5cbi8qKiBDb25jYXRlbmF0ZSB0aWxlcycgcmluZ3MgaW50byBvbmUgc2V0LCBkcm9wcGluZyByaW5ncyBhbHJlYWR5IHNlZW4gKGEgY2VsbCBzdHJhZGRsaW5nXG4gKiAgdHdvIHRpbGVzIG1heSBiZSBsaXN0ZWQgYnkgYm90aCkuICovXG5leHBvcnQgZnVuY3Rpb24gbWVyZ2VQb2x5Z29uVGlsZXModGlsZXM6IFNwYXRpYWxQb2x5Z29uVGlsZVtdKTogU3BhdGlhbFBvbHlnb25UaWxlIHtcbiAgY29uc3Qgc2VlbiA9IG5ldyBTZXQ8bnVtYmVyPigpO1xuICBsZXQgcmluZ3MgPSAwO1xuICBsZXQgdmVydGljZXMgPSAwO1xuICBmb3IgKGNvbnN0IHQgb2YgdGlsZXMpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHQuY291bnQ7IGkrKykge1xuICAgICAgaWYgKHNlZW4uaGFzKHQub2JzZXJ2YXRpb25baV0pKSBjb250aW51ZTtcbiAgICAgIHNlZW4uYWRkKHQub2JzZXJ2YXRpb25baV0pO1xuICAgICAgcmluZ3MrKztcbiAgICAgIHZlcnRpY2VzICs9IHQub2Zmc2V0c1tpICsgMV0gLSB0Lm9mZnNldHNbaV07XG4gICAgfVxuICB9XG4gIHNlZW4uY2xlYXIoKTtcbiAgY29uc3Qgb2JzZXJ2YXRpb24gPSBuZXcgVWludDMyQXJyYXkocmluZ3MpO1xuICBjb25zdCBvZmZzZXRzID0gbmV3IFVpbnQzMkFycmF5KHJpbmdzICsgMSk7XG4gIGNvbnN0IGNvb3JkcyA9IG5ldyBGbG9hdDMyQXJyYXkodmVydGljZXMgKiAyKTtcbiAgbGV0IHIgPSAwO1xuICBsZXQgdiA9IDA7XG4gIGZvciAoY29uc3QgdCBvZiB0aWxlcykge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdC5jb3VudDsgaSsrKSB7XG4gICAgICBjb25zdCBvID0gdC5vYnNlcnZhdGlvbltpXTtcbiAgICAgIGlmIChzZWVuLmhhcyhvKSkgY29udGludWU7XG4gICAgICBzZWVuLmFkZChvKTtcbiAgICAgIG9ic2VydmF0aW9uW3JdID0gbztcbiAgICAgIG9mZnNldHNbcl0gPSB2O1xuICAgICAgY29uc3QgYSA9IHQub2Zmc2V0c1tpXSAqIDI7XG4gICAgICBjb25zdCBiID0gdC5vZmZzZXRzW2kgKyAxXSAqIDI7XG4gICAgICBjb29yZHMuc2V0KHQuY29vcmRzLnN1YmFycmF5KGEsIGIpLCB2ICogMik7XG4gICAgICB2ICs9IChiIC0gYSkgLyAyO1xuICAgICAgcisrO1xuICAgIH1cbiAgfVxuICBvZmZzZXRzW3JpbmdzXSA9IHY7XG4gIHJldHVybiB7IGNvdW50OiByaW5ncywgb2JzZXJ2YXRpb24sIG9mZnNldHMsIGNvb3JkcyB9O1xufVxuXG4vKiogQ29uY2F0ZW5hdGUgdHJhbnNjcmlwdCB0aWxlcywgc3RvcHBpbmcgYXQgYGxpbWl0YCBlbnRyaWVzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIG1lcmdlVHJhbnNjcmlwdFRpbGVzKHRpbGVzOiBTcGF0aWFsVHJhbnNjcmlwdFRpbGVbXSwgbGltaXQgPSBJbmZpbml0eSk6IFNwYXRpYWxUcmFuc2NyaXB0VGlsZSB7XG4gIGxldCBuID0gMDtcbiAgZm9yIChjb25zdCB0IG9mIHRpbGVzKSBuICs9IHQuY291bnQ7XG4gIG4gPSBNYXRoLm1pbihuLCBsaW1pdCk7XG4gIGNvbnN0IG91dDogU3BhdGlhbFRyYW5zY3JpcHRUaWxlID0ge1xuICAgIGNvdW50OiBuLFxuICAgIGFnZ3JlZ2F0ZWQ6IHRpbGVzLnNvbWUoKHQpID0+IHQuYWdncmVnYXRlZCksXG4gICAgeDogbmV3IEZsb2F0MzJBcnJheShuKSwgeTogbmV3IEZsb2F0MzJBcnJheShuKSwgejogbmV3IEZsb2F0MzJBcnJheShuKSxcbiAgICB3ZWlnaHQ6IG5ldyBVaW50MzJBcnJheShuKSwgb2JzZXJ2YXRpb246IG5ldyBVaW50MzJBcnJheShuKSwgZ2VuZTogbmV3IFVpbnQxNkFycmF5KG4pLFxuICB9O1xuICBsZXQgbyA9IDA7XG4gIGZvciAoY29uc3QgdCBvZiB0aWxlcykge1xuICAgIGNvbnN0IGsgPSBNYXRoLm1pbih0LmNvdW50LCBuIC0gbyk7XG4gICAgaWYgKGsgPD0gMCkgYnJlYWs7XG4gICAgZm9yIChjb25zdCBmIG9mIFsneCcsICd5JywgJ3onLCAnd2VpZ2h0JywgJ29ic2VydmF0aW9uJywgJ2dlbmUnXSBhcyBjb25zdCkge1xuICAgICAgKG91dFtmXSBhcyBGbG9hdDMyQXJyYXkpLnNldCgodFtmXSBhcyBGbG9hdDMyQXJyYXkpLnN1YmFycmF5KDAsIGspLCBvKTtcbiAgICB9XG4gICAgbyArPSBrO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG4iXX0=