@jax-data-science/sci-image-visualizer 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. package/esm2022/lib/contracts/display-types.mjs +28 -1
  2. package/esm2022/lib/contracts/plot-type-contribution.contract.mjs +1 -1
  3. package/esm2022/lib/contracts/ports/spatial-data.port.mjs +3 -1
  4. package/esm2022/lib/contracts/spatial-dataset.contract.mjs +3 -1
  5. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  6. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +73 -0
  7. package/esm2022/lib/implementations/napari-js/napari-navigator.mjs +195 -0
  8. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +10 -2
  9. package/esm2022/lib/implementations/napari-js/napari-spatial-tiles.mjs +1487 -0
  10. package/esm2022/lib/implementations/napari-js/napari-spatial-tooltip.mjs +6 -3
  11. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +219 -8
  12. package/esm2022/lib/implementations/osd/openseadragon-visualizer.service.mjs +8 -1
  13. package/esm2022/lib/implementations/spatial-data-http/spatial-data-http.service.mjs +131 -2
  14. package/esm2022/lib/implementations/spatial-data-http/spatial-wire.mjs +77 -1
  15. package/esm2022/lib/routing-visualizer.service.mjs +14 -1
  16. package/esm2022/lib/spatial/spatial-tiles.mjs +649 -0
  17. package/esm2022/lib/spatial-controls/spatial-controls.component.mjs +848 -19
  18. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +3773 -78
  19. package/fesm2022/jax-data-science-sci-image-visualizer.mjs.map +1 -1
  20. package/lib/contracts/display-types.d.ts +96 -1
  21. package/lib/contracts/plot-type-contribution.contract.d.ts +9 -0
  22. package/lib/contracts/ports/spatial-data.port.d.ts +70 -1
  23. package/lib/contracts/spatial-dataset.contract.d.ts +197 -0
  24. package/lib/contracts/visualizer.contract.d.ts +28 -1
  25. package/lib/implementations/napari-js/napari-loading-badge.d.ts +20 -0
  26. package/lib/implementations/napari-js/napari-navigator.d.ts +72 -0
  27. package/lib/implementations/napari-js/napari-region-overlay.d.ts +3 -0
  28. package/lib/implementations/napari-js/napari-spatial-tiles.d.ts +315 -0
  29. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +49 -2
  30. package/lib/implementations/spatial-data-http/spatial-data-http.service.d.ts +28 -2
  31. package/lib/implementations/spatial-data-http/spatial-wire.d.ts +35 -1
  32. package/lib/spatial/spatial-tiles.d.ts +259 -0
  33. package/lib/spatial-controls/spatial-controls.component.d.ts +288 -3
  34. package/package.json +1 -1
@@ -0,0 +1,649 @@
1
+ /**
2
+ * Level-of-detail planning for tiled spatial geometry — cell outlines and transcripts.
3
+ *
4
+ * The renderer knows its camera (a world-space centre, a zoom in canvas pixels per world
5
+ * unit, a canvas size); a tiled dataset knows its grids (one per level, in observation
6
+ * units). This module is the bridge: which level the zoom calls for, which tiles are on
7
+ * screen, how big a transcript marker should be. Everything here is pure, so the policy
8
+ * — the part that decides whether the view is fast and legible — is testable without a
9
+ * GPU.
10
+ *
11
+ * Observation units map onto world units through the dataset's `imageRef` affine
12
+ * (`world = data · scale + translate`), so "pixels per observation unit" is
13
+ * `zoom · scale`. For a Xenium bundle the data unit is the micron and the world unit the
14
+ * morphology pixel.
15
+ */
16
+ /** Whether cell outlines are drawn: the user's choice, else on when the dataset has any. */
17
+ export function cellsShown(dataset, view) {
18
+ const available = !!(dataset?.polygonTiles || dataset?.polygons);
19
+ return available && (view.showCells ?? true);
20
+ }
21
+ /** A column holding a hand-curated cell-type annotation, by naming convention. */
22
+ export function isCuratedColumn(name) {
23
+ return /curated/i.test(name);
24
+ }
25
+ /**
26
+ * The categorical column that names each cell's type: the view's choice when it is a
27
+ * column of this dataset, else the first categorical column that is not a curated
28
+ * annotation (a pipeline's clustering is the default; curation is opted into), else
29
+ * any categorical column.
30
+ */
31
+ export function cellTypeColumnFor(dataset, view) {
32
+ const categorical = dataset.columns.filter((c) => c.kind === 'categorical');
33
+ if (view.cellTypeColumn && categorical.some((c) => c.name === view.cellTypeColumn)) {
34
+ return view.cellTypeColumn;
35
+ }
36
+ return (categorical.find((c) => !isCuratedColumn(c.name)) ?? categorical[0])?.name ?? null;
37
+ }
38
+ export function tileId(k) {
39
+ return `${k.level}/${k.gx}/${k.gy}`;
40
+ }
41
+ /** Canvas pixels per observation unit along x, for a camera zoom and a data→world affine. */
42
+ export function pixelsPerDataUnit(zoom, ref) {
43
+ return zoom * Math.abs(ref?.scale?.[0] ?? 1);
44
+ }
45
+ /**
46
+ * The part of observation space the camera shows, padded by `margin` (a fraction of the
47
+ * viewport) so tiles just off screen are already there when a pan brings them in.
48
+ */
49
+ export function visibleDataRect(center, zoom, canvasW, canvasH, ref, margin = 0.15) {
50
+ if (!(zoom > 0) || !(canvasW > 0) || !(canvasH > 0))
51
+ return null;
52
+ const sx = ref?.scale?.[0] ?? 1;
53
+ const sy = ref?.scale?.[1] ?? 1;
54
+ const tx = ref?.translate?.[0] ?? 0;
55
+ const ty = ref?.translate?.[1] ?? 0;
56
+ const halfW = (canvasW / zoom / 2) * (1 + 2 * margin);
57
+ const halfH = (canvasH / zoom / 2) * (1 + 2 * margin);
58
+ const wx0 = center[0] - halfW;
59
+ const wx1 = center[0] + halfW;
60
+ const wy0 = center[1] - halfH;
61
+ const wy1 = center[1] + halfH;
62
+ const ax = (wx0 - tx) / sx;
63
+ const bx = (wx1 - tx) / sx;
64
+ const ay = (wy0 - ty) / sy;
65
+ const by = (wy1 - ty) / sy;
66
+ return { x0: Math.min(ax, bx), y0: Math.min(ay, by), x1: Math.max(ax, bx), y1: Math.max(ay, by) };
67
+ }
68
+ /**
69
+ * Tiles of one level intersecting `rect`, clipped to the dataset's `bounds` (so zooming
70
+ * out over empty canvas does not ask for tiles that cannot exist). Ordered from the
71
+ * rectangle's centre outward, so the middle of the screen fills in first.
72
+ */
73
+ export function tilesInRect(rect, level, levels, bounds, limit = Infinity) {
74
+ const size = levels[level]?.tileSize;
75
+ if (!(size > 0))
76
+ return [];
77
+ let { x0, y0, x1, y1 } = rect;
78
+ if (bounds) {
79
+ x0 = Math.max(x0, bounds[0]);
80
+ y0 = Math.max(y0, bounds[1]);
81
+ x1 = Math.min(x1, bounds[2]);
82
+ y1 = Math.min(y1, bounds[3]);
83
+ if (x1 < x0 || y1 < y0)
84
+ return [];
85
+ }
86
+ const gx0 = Math.floor(x0 / size);
87
+ const gx1 = Math.floor(x1 / size);
88
+ const gy0 = Math.floor(y0 / size);
89
+ const gy1 = Math.floor(y1 / size);
90
+ const cx = (rect.x0 + rect.x1) / 2 / size;
91
+ const cy = (rect.y0 + rect.y1) / 2 / size;
92
+ const out = [];
93
+ for (let gy = gy0; gy <= gy1; gy++) {
94
+ for (let gx = gx0; gx <= gx1; gx++)
95
+ out.push({ level, gx, gy });
96
+ }
97
+ out.sort((a, b) => ((a.gx + 0.5 - cx) ** 2 + (a.gy + 0.5 - cy) ** 2)
98
+ - ((b.gx + 0.5 - cx) ** 2 + (b.gy + 0.5 - cy) ** 2));
99
+ return out.length > limit ? out.slice(0, limit) : out;
100
+ }
101
+ /**
102
+ * Typical cell diameter, in observation units, used to judge how large cells appear.
103
+ * Derived from the per-observation radius when there is one; 12 µm otherwise.
104
+ */
105
+ export function typicalCellDiameter(radius, fallback = 12) {
106
+ if (typeof radius === 'number')
107
+ return radius > 0 ? radius * 2 : fallback;
108
+ if (!radius?.length)
109
+ return fallback;
110
+ // The median of a sample is plenty — this sets a threshold, not a measurement.
111
+ const step = Math.max(1, Math.floor(radius.length / 2048));
112
+ const sample = [];
113
+ for (let i = 0; i < radius.length; i += step) {
114
+ if (radius[i] > 0)
115
+ sample.push(radius[i]);
116
+ }
117
+ if (!sample.length)
118
+ return fallback;
119
+ sample.sort((a, b) => a - b);
120
+ return sample[sample.length >> 1] * 2;
121
+ }
122
+ /**
123
+ * On-screen cell diameter (px) at or above which each polygon level is used. A level
124
+ * halves the vertices of the one below, so each should take over when the cell is about
125
+ * half as large on screen. Below the last finite threshold outlines are not drawn at
126
+ * all — a cell a few pixels wide is a dot, and the observation markers already draw it
127
+ * as one.
128
+ *
129
+ * Xenium's fourth level (3 vertices per cell) is deliberately never used: seen on
130
+ * screen it is a field of triangles, which reads as an artefact rather than as cells.
131
+ * The dots below 8 px say the same thing more honestly.
132
+ */
133
+ export const POLYGON_LEVEL_MIN_CELL_PX = [36, 18, 8, Infinity];
134
+ /**
135
+ * Which polygon level suits this zoom, or -1 for "too small to outline".
136
+ * `detail` > 1 prefers finer levels (sharper, slower); < 1 coarser.
137
+ */
138
+ export function polygonLevelFor(pxPerUnit, cellDiameter, levelCount, detail = 1) {
139
+ const cellPx = pxPerUnit * cellDiameter * detail;
140
+ const table = POLYGON_LEVEL_MIN_CELL_PX;
141
+ for (let l = 0; l < levelCount; l++) {
142
+ // Past the table, keep halving: each level still halves the vertices.
143
+ const min = table[l] ?? table[table.length - 1] / 2 ** (l - table.length + 1);
144
+ if (cellPx >= min)
145
+ return l;
146
+ }
147
+ return -1;
148
+ }
149
+ /**
150
+ * Which transcript level suits this zoom: the one whose tiles come out closest to
151
+ * `targetTilePx` on screen. Coarser levels aggregate more, so this keeps the number of
152
+ * markers per screen roughly constant however far out the camera is — the property that
153
+ * keeps the view fast.
154
+ */
155
+ export function transcriptLevelFor(pxPerUnit, levels, targetTilePx = 512) {
156
+ if (!levels.length || !(pxPerUnit > 0))
157
+ return 0;
158
+ let best = 0;
159
+ let bestErr = Infinity;
160
+ for (let l = 0; l < levels.length; l++) {
161
+ const err = Math.abs(Math.log2((levels[l].tileSize * pxPerUnit) / targetTilePx));
162
+ if (err < bestErr) {
163
+ bestErr = err;
164
+ best = l;
165
+ }
166
+ }
167
+ return best;
168
+ }
169
+ /**
170
+ * The bin a selection of genes is grouped into at this zoom, in observation units, or null
171
+ * to draw every transcript. Bins follow the all-gene pyramid's ladder (`baseBin` × 2^m) so a
172
+ * gene selection and "all genes" group alike: the finest bin whose markers land at least
173
+ * `spacingPx` apart on screen. Once the finest bin is that wide, transcripts are drawn as
174
+ * themselves.
175
+ */
176
+ export function geneBinSize(pxPerUnit, baseBin, levels = 7, spacingPx = GROUP_MIN_SPACING_PX) {
177
+ if (!(pxPerUnit > 0) || !(baseBin > 0))
178
+ return null;
179
+ if (baseBin * pxPerUnit >= spacingPx)
180
+ return null;
181
+ for (let m = 1; m < levels; m++) {
182
+ const bin = baseBin * 2 ** m;
183
+ if (bin * pxPerUnit >= spacingPx)
184
+ return bin;
185
+ }
186
+ return baseBin * 2 ** (levels - 1);
187
+ }
188
+ /** The entries of `t` inside `rect` (observation units). */
189
+ export function clipTranscripts(t, rect) {
190
+ const keep = [];
191
+ for (let i = 0; i < t.count; i++) {
192
+ if (t.x[i] >= rect.x0 && t.x[i] <= rect.x1 && t.y[i] >= rect.y0 && t.y[i] <= rect.y1)
193
+ keep.push(i);
194
+ }
195
+ if (keep.length === t.count)
196
+ return t;
197
+ const pick = (a) => {
198
+ const out = new a.constructor(keep.length);
199
+ keep.forEach((src, i) => { out[i] = a[src]; });
200
+ return out;
201
+ };
202
+ return {
203
+ count: keep.length, aggregated: t.aggregated,
204
+ x: pick(t.x), y: pick(t.y), z: pick(t.z), weight: pick(t.weight), observation: pick(t.observation),
205
+ gene: pick(t.gene),
206
+ };
207
+ }
208
+ /**
209
+ * Group transcripts into `bin`-wide squares of a grid anchored at the origin (so a pan does
210
+ * not move them), one entry per (group, square): `groupOf(gene slot)` says which group a gene
211
+ * is in — its cluster in the gene tree, or itself. Each entry sits at its transcripts'
212
+ * centroid, weighted by how many each stands for; it takes the gene and the cell holding most
213
+ * of them, each summed over all its transcripts in the entry. `group[i]` is entry i's group.
214
+ */
215
+ export function groupTranscripts(t, bin, groupOf = (g) => g) {
216
+ const index = new Map();
217
+ const sx = [];
218
+ const sy = [];
219
+ const sz = [];
220
+ const w = [];
221
+ const grp = [];
222
+ // Per entry, how many transcripts of each gene (the dominant one gives the icon and colour)
223
+ // and in each cell (the dominant one is the entry's cell).
224
+ const geneW = [];
225
+ const obsW = [];
226
+ for (let i = 0; i < t.count; i++) {
227
+ const gk = groupOf(t.gene[i]);
228
+ const key = `${gk}|${Math.floor(t.x[i] / bin)}|${Math.floor(t.y[i] / bin)}`;
229
+ let k = index.get(key);
230
+ const wi = t.weight[i] || 1;
231
+ if (k === undefined) {
232
+ k = w.length;
233
+ index.set(key, k);
234
+ sx.push(0);
235
+ sy.push(0);
236
+ sz.push(0);
237
+ w.push(0);
238
+ grp.push(gk);
239
+ geneW.push(new Map());
240
+ obsW.push(new Map());
241
+ }
242
+ sx[k] += t.x[i] * wi;
243
+ sy[k] += t.y[i] * wi;
244
+ sz[k] += t.z[i] * wi;
245
+ w[k] += wi;
246
+ geneW[k].set(t.gene[i], (geneW[k].get(t.gene[i]) ?? 0) + wi);
247
+ obsW[k].set(t.observation[i], (obsW[k].get(t.observation[i]) ?? 0) + wi);
248
+ }
249
+ const n = w.length;
250
+ const tile = {
251
+ count: n, aggregated: true,
252
+ x: new Float32Array(n), y: new Float32Array(n), z: new Float32Array(n),
253
+ weight: new Uint32Array(n), observation: new Uint32Array(n), gene: new Uint16Array(n),
254
+ };
255
+ const group = new Int32Array(n);
256
+ for (let k = 0; k < n; k++) {
257
+ tile.x[k] = sx[k] / w[k];
258
+ tile.y[k] = sy[k] / w[k];
259
+ tile.z[k] = sz[k] / w[k];
260
+ tile.weight[k] = w[k];
261
+ tile.observation[k] = dominant(obsW[k]);
262
+ tile.gene[k] = dominant(geneW[k]);
263
+ group[k] = grp[k];
264
+ }
265
+ return { tile, group };
266
+ }
267
+ /** The key with the largest total; the first seen on a tie. */
268
+ function dominant(totals) {
269
+ let best = 0;
270
+ let top = -1;
271
+ for (const [key, v] of totals)
272
+ if (v > top) {
273
+ top = v;
274
+ best = key;
275
+ }
276
+ return best;
277
+ }
278
+ /**
279
+ * The colour of each gene-tree cluster of a selection, for colouring transcripts by cluster: a
280
+ * cluster named like a group of the cells' grouping takes that group's colour (its cells and its
281
+ * transcripts agree); the others take palette colours in tree order. Clusters are the tree's
282
+ * groups holding a selected gene, then each ungrouped selected gene on its own. Every gene of a
283
+ * cluster gets the same colour — the tree's swatches and the markers use this one map.
284
+ */
285
+ export function clusterColorMap(genes, groups, cellColors, palette) {
286
+ const chosen = new Set(genes);
287
+ const names = [];
288
+ const grouped = new Set();
289
+ for (const g of groups) {
290
+ const mine = g.genes.filter((x) => chosen.has(x) && !grouped.has(x));
291
+ if (!mine.length)
292
+ continue;
293
+ mine.forEach((x) => grouped.add(x));
294
+ names.push(g.name);
295
+ }
296
+ for (const gene of genes)
297
+ if (!grouped.has(gene))
298
+ names.push(gene);
299
+ const out = new Map();
300
+ let k = 0;
301
+ for (const name of names) {
302
+ if (out.has(name))
303
+ continue;
304
+ out.set(name, cellColors.get(name) ?? palette[k++ % palette.length]);
305
+ }
306
+ return out;
307
+ }
308
+ /** The cluster a selected gene is in: its first gene-tree group holding it, else itself. */
309
+ export function clusterOfGene(gene, groups) {
310
+ return groups.find((g) => g.genes.includes(gene))?.name ?? gene;
311
+ }
312
+ /** Smallest and largest transcript marker, in canvas pixels. */
313
+ export const TRANSCRIPT_MIN_PX = 4;
314
+ export const TRANSCRIPT_MAX_PX = 32;
315
+ /**
316
+ * Physical diameter a single transcript is drawn at, in µm — clearly larger than the
317
+ * imaged spot (~0.3 µm) so it stays legible, and small enough that neighbouring
318
+ * molecules inside one cell stay apart.
319
+ */
320
+ export const TRANSCRIPT_PHYSICAL_UM = 1.2;
321
+ /**
322
+ * Marker diameter in canvas pixels for an entry standing for `weight` transcripts.
323
+ *
324
+ * The convention spatial viewers share (deck.gl's `radiusMinPixels`/`radiusMaxPixels`,
325
+ * Xenium Explorer's transcript size): a PHYSICAL size, clamped to a screen-pixel range.
326
+ * Zoomed out, markers sit at the minimum and never vanish; zoomed in, they grow with the
327
+ * tissue instead of shrinking to specks next to cells hundreds of pixels wide. A fixed
328
+ * screen size does the opposite at high zoom, which is what made transcripts disappear
329
+ * at pixel-level zoom.
330
+ *
331
+ * Aggregates grow with the cube root of their count: area ∝ count would let one dense
332
+ * aggregate swallow its neighbours, the cube root keeps a 1000-transcript cluster clearly
333
+ * larger than a 10-transcript one without covering the tile.
334
+ *
335
+ * `pxPerMicron` is omitted for data with no known physical unit; the marker is then
336
+ * screen-sized only.
337
+ */
338
+ export function transcriptMarkerPx(weight, scale = 1, pxPerMicron) {
339
+ const counted = TRANSCRIPT_MIN_PX * Math.cbrt(Math.max(1, weight));
340
+ const physical = pxPerMicron ? TRANSCRIPT_PHYSICAL_UM * pxPerMicron : 0;
341
+ const px = Math.max(counted, physical) * scale;
342
+ return Math.min(TRANSCRIPT_MAX_PX * Math.max(scale, 1), Math.max(TRANSCRIPT_MIN_PX * scale, px));
343
+ }
344
+ // ── Glyphs ────────────────────────────────────────────────────────────────────────────
345
+ /** Marker shapes for the transcript "icon" mode. All star-convex, so a fan fills them. */
346
+ export const TRANSCRIPT_GLYPHS = [
347
+ 'circle', 'star', 'triangle', 'square', 'diamond', 'cross', 'hexagon', 'triangle-down',
348
+ 'pentagon', 'x',
349
+ ];
350
+ // The view state names glyphs without importing this module; keep the two in step.
351
+ const _glyphNamesMatch = true;
352
+ void _glyphNamesMatch;
353
+ /** Unit outline of a glyph, radius ≈ 1, centred on the origin, as `[x0, y0, x1, y1, …]`. */
354
+ export function glyphOutline(glyph) {
355
+ const poly = (n, rot = -Math.PI / 2, r = 1) => {
356
+ const out = new Float32Array(n * 2);
357
+ for (let i = 0; i < n; i++) {
358
+ const a = rot + (i * 2 * Math.PI) / n;
359
+ out[2 * i] = Math.cos(a) * r;
360
+ out[2 * i + 1] = Math.sin(a) * r;
361
+ }
362
+ return out;
363
+ };
364
+ const star = (points, inner, rot = -Math.PI / 2) => {
365
+ const out = new Float32Array(points * 4);
366
+ for (let i = 0; i < points * 2; i++) {
367
+ const a = rot + (i * Math.PI) / points;
368
+ const r = i % 2 === 0 ? 1 : inner;
369
+ out[2 * i] = Math.cos(a) * r;
370
+ out[2 * i + 1] = Math.sin(a) * r;
371
+ }
372
+ return out;
373
+ };
374
+ // A plus built as a 12-gon: arms of half-width w.
375
+ const plus = (w, rotate) => {
376
+ const pts = [
377
+ [w, -1], [w, -w], [1, -w], [1, w], [w, w], [w, 1],
378
+ [-w, 1], [-w, w], [-1, w], [-1, -w], [-w, -w], [-w, -1],
379
+ ];
380
+ const out = new Float32Array(pts.length * 2);
381
+ const c = Math.SQRT1_2;
382
+ pts.forEach(([x, y], i) => {
383
+ out[2 * i] = rotate ? (x - y) * c : x;
384
+ out[2 * i + 1] = rotate ? (x + y) * c : y;
385
+ });
386
+ return out;
387
+ };
388
+ switch (glyph) {
389
+ case 'circle': return poly(12);
390
+ case 'star': return star(5, 0.45);
391
+ case 'triangle': return poly(3);
392
+ case 'triangle-down': return poly(3, Math.PI / 2);
393
+ case 'square': return poly(4, Math.PI / 4, Math.SQRT2 * 0.8);
394
+ case 'diamond': return poly(4, -Math.PI / 2);
395
+ case 'hexagon': return poly(6, 0);
396
+ case 'pentagon': return poly(5);
397
+ case 'cross': return plus(0.32, false);
398
+ case 'x': return plus(0.28, true);
399
+ }
400
+ }
401
+ /** The glyph a gene gets by default: by its position in the selected list. */
402
+ export function defaultGlyphFor(slot) {
403
+ return TRANSCRIPT_GLYPHS[slot % TRANSCRIPT_GLYPHS.length];
404
+ }
405
+ /**
406
+ * Expand point markers into glyph rings for a shapes layer: entry `i` becomes a copy of
407
+ * `glyphs[gene[i]]` scaled to `radius[i]` and centred on `(x[i], y[i])`.
408
+ */
409
+ export function glyphRings(x, y, radius, glyphOf) {
410
+ const n = x.length;
411
+ const offsets = new Uint32Array(n + 1);
412
+ let total = 0;
413
+ for (let i = 0; i < n; i++) {
414
+ offsets[i] = total;
415
+ total += glyphOf(i).length / 2;
416
+ }
417
+ offsets[n] = total;
418
+ const coords = new Float32Array(total * 2);
419
+ for (let i = 0; i < n; i++) {
420
+ const g = glyphOf(i);
421
+ const r = radius[i];
422
+ let o = offsets[i] * 2;
423
+ for (let k = 0; k < g.length; k += 2) {
424
+ coords[o++] = x[i] + g[k] * r;
425
+ coords[o++] = y[i] + g[k + 1] * r;
426
+ }
427
+ }
428
+ return { coords, offsets };
429
+ }
430
+ // ── Discrete colouring through a colormap ─────────────────────────────────────────────
431
+ /**
432
+ * A shapes layer colours through a colormap LUT, not per-shape RGBA. A categorical
433
+ * palette becomes a piecewise-constant colormap: category `c` of `n` owns the band
434
+ * `[c/n, (c+1)/n)`, and a shape takes the value at its band's centre, so the LUT's
435
+ * linear filtering never blends two categories.
436
+ *
437
+ * Returns the stops (linear 0..1 RGB) and a function mapping a category code to the
438
+ * value to hand the layer. `missing` is the colour of the extra band used for "no
439
+ * category".
440
+ */
441
+ export function discreteColormapStops(rgb, missing) {
442
+ const bands = [...rgb, missing];
443
+ const n = bands.length;
444
+ const stops = [];
445
+ const eps = 1e-6;
446
+ bands.forEach((c, i) => {
447
+ const color = [c[0] / 255, c[1] / 255, c[2] / 255];
448
+ stops.push({ t: i / n + (i === 0 ? 0 : eps), color });
449
+ stops.push({ t: (i + 1) / n - (i === n - 1 ? 0 : eps), color });
450
+ });
451
+ const missingCode = n - 1;
452
+ return {
453
+ stops,
454
+ valueOf: (code) => ((code < 0 || code >= missingCode ? missingCode : code) + 0.5) / n,
455
+ };
456
+ }
457
+ // ── Density raster ────────────────────────────────────────────────────────────────────
458
+ /**
459
+ * Separable Gaussian blur of a row-major raster, `sigma` in raster cells.
460
+ *
461
+ * A per-gene count raster at 10 µm is mostly zeros and ones — drawn as-is it is speckle,
462
+ * not a density. A σ of one to two cells (10–20 µm, about a cell diameter) turns it into
463
+ * a field that reads as territory while keeping structures a few cells wide.
464
+ */
465
+ export function smoothRaster(values, rows, cols, sigma) {
466
+ if (!(sigma > 0))
467
+ return values.slice();
468
+ const r = Math.max(1, Math.ceil(sigma * 3));
469
+ const kernel = new Float32Array(2 * r + 1);
470
+ let sum = 0;
471
+ for (let i = -r; i <= r; i++)
472
+ sum += (kernel[i + r] = Math.exp(-(i * i) / (2 * sigma * sigma)));
473
+ for (let i = 0; i < kernel.length; i++)
474
+ kernel[i] /= sum;
475
+ const tmp = new Float32Array(values.length);
476
+ const out = new Float32Array(values.length);
477
+ for (let y = 0; y < rows; y++) {
478
+ const row = y * cols;
479
+ for (let x = 0; x < cols; x++) {
480
+ let acc = 0;
481
+ for (let k = -r; k <= r; k++) {
482
+ const xx = x + k;
483
+ if (xx >= 0 && xx < cols)
484
+ acc += values[row + xx] * kernel[k + r];
485
+ }
486
+ tmp[row + x] = acc;
487
+ }
488
+ }
489
+ for (let y = 0; y < rows; y++) {
490
+ for (let x = 0; x < cols; x++) {
491
+ let acc = 0;
492
+ for (let k = -r; k <= r; k++) {
493
+ const yy = y + k;
494
+ if (yy >= 0 && yy < rows)
495
+ acc += tmp[yy * cols + x] * kernel[k + r];
496
+ }
497
+ out[y * cols + x] = acc;
498
+ }
499
+ }
500
+ return out;
501
+ }
502
+ /**
503
+ * Colour a density raster as RGBA bytes: log-scaled, windowed at a high percentile of the
504
+ * non-zero values, and faded in from transparent so empty tissue shows what is under it.
505
+ */
506
+ export function colorDensity(values, lut, opacity, { log = true, percentile = 0.995 } = {}) {
507
+ const n = values.length;
508
+ const t = log ? values.map((v) => Math.log1p(Math.max(0, v))) : values;
509
+ const positive = [];
510
+ for (let i = 0; i < n; i++)
511
+ if (t[i] > 0)
512
+ positive.push(t[i]);
513
+ positive.sort((a, b) => a - b);
514
+ const at = Math.min(positive.length - 1, Math.floor(percentile * positive.length));
515
+ const hi = positive.length ? positive[at] : 1;
516
+ const rgba = new Uint8Array(n * 4);
517
+ for (let i = 0; i < n; i++) {
518
+ const f = Math.min(1, t[i] / (hi || 1));
519
+ if (f < 0.02)
520
+ continue;
521
+ const c = lut[Math.min(lut.length - 1, Math.round(f * (lut.length - 1)))];
522
+ rgba[4 * i] = c[0];
523
+ rgba[4 * i + 1] = c[1];
524
+ rgba[4 * i + 2] = c[2];
525
+ rgba[4 * i + 3] = Math.round(255 * opacity * Math.pow(f, 0.6));
526
+ }
527
+ return rgba;
528
+ }
529
+ // ── All-gene transcripts: grouping under a marker budget ─────────────────────────────
530
+ /** Smallest on-screen spacing between groups, in px — below it groups read as noise. */
531
+ export const GROUP_MIN_SPACING_PX = 14;
532
+ /** Area of `rect` inside `bounds` (the whole rect when there are none). */
533
+ export function visibleArea(rect, bounds) {
534
+ const x0 = bounds ? Math.max(rect.x0, bounds[0]) : rect.x0;
535
+ const y0 = bounds ? Math.max(rect.y0, bounds[1]) : rect.y0;
536
+ const x1 = bounds ? Math.min(rect.x1, bounds[2]) : rect.x1;
537
+ const y1 = bounds ? Math.min(rect.y1, bounds[3]) : rect.y1;
538
+ return Math.max(0, x1 - x0) * Math.max(0, y1 - y0);
539
+ }
540
+ /**
541
+ * How to draw every transcript in view without exceeding `budget` markers.
542
+ *
543
+ * - The transcripts themselves, once the estimated count in view fits the budget.
544
+ * - Otherwise the finest pyramid level whose bins are at least `minSpacingPx` apart on
545
+ * screen and number no more than the budget — groups big enough to read, few enough
546
+ * to draw.
547
+ *
548
+ * The count in view is estimated from the average density, which over- or under-shoots
549
+ * locally; the renderer still caps what it draws, so an estimate is enough to choose.
550
+ */
551
+ export function allGenesPlan(o) {
552
+ const area = visibleArea(o.rect, o.bounds);
553
+ if (!(area > 0))
554
+ return { kind: 'none' };
555
+ const b = o.bounds;
556
+ const density = o.total / Math.max(1, (b[2] - b[0]) * (b[3] - b[1]));
557
+ if (o.canIndividual && density * area <= o.budget)
558
+ return { kind: 'individual' };
559
+ if (!o.levels.length)
560
+ return { kind: 'none' };
561
+ const spacing = o.minSpacingPx ?? GROUP_MIN_SPACING_PX;
562
+ for (let l = 0; l < o.levels.length; l++) {
563
+ const bin = o.levels[l].binSize;
564
+ // Tissue rarely fills the view; 0.7 of the bins occupied is a fair guess.
565
+ if (bin * o.pxPerUnit >= spacing && (area / (bin * bin)) * 0.7 <= o.budget) {
566
+ return { kind: 'bins', level: l };
567
+ }
568
+ }
569
+ return { kind: 'bins', level: o.levels.length - 1 };
570
+ }
571
+ /**
572
+ * Diameter in px of a group of `count` transcripts in a bin `binPx` wide, where
573
+ * `refCount` is a typical busy bin in view (its 95th percentile).
574
+ *
575
+ * Area grows with the count — a bin with a quarter of the transcripts gets half the
576
+ * diameter — between a third of the bin (so a sparse bin is still visible) and a little
577
+ * over the full bin (so dense neighbours just touch rather than pile up).
578
+ */
579
+ export function groupedMarkerPx(count, refCount, binPx, scale = 1) {
580
+ const f = Math.sqrt(Math.min(1, count / Math.max(1, refCount)));
581
+ const d = binPx * (0.35 + 0.75 * f) * scale;
582
+ return Math.max(TRANSCRIPT_MIN_PX * scale, Math.min(d, binPx * 1.2 * Math.max(scale, 1)));
583
+ }
584
+ /** The `p` quantile (0..1) of a count vector — a sample of it for large vectors. */
585
+ export function quantileOf(values, p) {
586
+ const n = values.length;
587
+ if (!n)
588
+ return 0;
589
+ const step = Math.max(1, Math.floor(n / 4096));
590
+ const sample = [];
591
+ for (let i = 0; i < n; i += step)
592
+ sample.push(values[i]);
593
+ sample.sort((a, b) => a - b);
594
+ return sample[Math.min(sample.length - 1, Math.floor(p * sample.length))];
595
+ }
596
+ /** {@link tilesInRect} for a grid whose tile (0, 0) starts at `origin`. */
597
+ export function tilesInRectFrom(origin, rect, level, levels, bounds, limit = Infinity) {
598
+ const [ox, oy] = origin;
599
+ const shifted = { x0: rect.x0 - ox, y0: rect.y0 - oy, x1: rect.x1 - ox, y1: rect.y1 - oy };
600
+ const b = bounds ? [bounds[0] - ox, bounds[1] - oy, bounds[2] - ox, bounds[3] - oy] : null;
601
+ return tilesInRect(shifted, level, levels, b, limit);
602
+ }
603
+ /** A density window from the non-empty bins: 1st to 99th percentile. */
604
+ export function densityAutoRange(values) {
605
+ const positive = [];
606
+ for (let i = 0; i < values.length; i++)
607
+ if (values[i] > 0)
608
+ positive.push(values[i]);
609
+ if (!positive.length)
610
+ return [0, 1];
611
+ positive.sort((a, b) => a - b);
612
+ const at = (p) => positive[Math.min(positive.length - 1, Math.floor(p * positive.length))];
613
+ const lo = at(0.01);
614
+ const hi = at(0.99);
615
+ return hi > lo ? [lo, hi] : [0, hi || 1];
616
+ }
617
+ /**
618
+ * Colour density bins through `lut` over the window `[lo, hi]` — Xenium Explorer's
619
+ * "scale threshold". Bins at or below `lo` are transparent, so empty tissue shows the
620
+ * image under it; bins at or above `hi` saturate.
621
+ */
622
+ export function colorDensityWindow(values, lut, opacity, lo, hi) {
623
+ const n = values.length;
624
+ const rgba = new Uint8Array(n * 4);
625
+ const span = hi > lo ? hi - lo : 1;
626
+ const a = Math.round(255 * opacity);
627
+ for (let i = 0; i < n; i++) {
628
+ const v = values[i];
629
+ if (!(v > lo))
630
+ continue;
631
+ const f = Math.min(1, (v - lo) / span);
632
+ const c = lut[Math.min(lut.length - 1, Math.round(f * (lut.length - 1)))];
633
+ rgba[4 * i] = c[0];
634
+ rgba[4 * i + 1] = c[1];
635
+ rgba[4 * i + 2] = c[2];
636
+ rgba[4 * i + 3] = a;
637
+ }
638
+ return rgba;
639
+ }
640
+ /**
641
+ * Inferno (matplotlib), as an inline `[stop, colour]` scale: the density map's default,
642
+ * as in Xenium Explorer. Inline because the colormap tree's `INFERNO_LUT` key is resolved
643
+ * at runtime by the store, which the renderer does not see.
644
+ */
645
+ export const INFERNO_SCALE = [
646
+ [0, '#000004'], [0.125, '#1b0c41'], [0.25, '#4a0c6b'], [0.375, '#781c6d'], [0.5, '#a52c60'],
647
+ [0.625, '#cf4446'], [0.75, '#ed6925'], [0.875, '#fb9b06'], [1, '#fcffa4'],
648
+ ];
649
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhdGlhbC10aWxlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc3BhdGlhbC9zcGF0aWFsLXRpbGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBdUJILDRGQUE0RjtBQUM1RixNQUFNLFVBQVUsVUFBVSxDQUN4QixPQUFpRSxFQUNqRSxJQUF5QztJQUV6QyxNQUFNLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsWUFBWSxJQUFJLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNqRSxPQUFPLFNBQVMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLENBQUM7QUFDL0MsQ0FBQztBQUVELGtGQUFrRjtBQUNsRixNQUFNLFVBQVUsZUFBZSxDQUFDLElBQVk7SUFDMUMsT0FBTyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQy9CLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FDL0IsT0FBdUIsRUFBRSxJQUE4QztJQUV2RSxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxhQUFhLENBQUMsQ0FBQztJQUM1RSxJQUFJLElBQUksQ0FBQyxjQUFjLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQztRQUNuRixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUM7SUFDN0IsQ0FBQztJQUNELE9BQU8sQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLElBQUksSUFBSSxDQUFDO0FBQzdGLENBQUM7QUFFRCxNQUFNLFVBQVUsTUFBTSxDQUFDLENBQVU7SUFDL0IsT0FBTyxHQUFHLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUM7QUFDdEMsQ0FBQztBQUVELDZGQUE2RjtBQUM3RixNQUFNLFVBQVUsaUJBQWlCLENBQUMsSUFBWSxFQUFFLEdBQTRCO0lBQzFFLE9BQU8sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQy9DLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsZUFBZSxDQUM3QixNQUFpQyxFQUFFLElBQVksRUFBRSxPQUFlLEVBQUUsT0FBZSxFQUNqRixHQUE0QixFQUFFLE1BQU0sR0FBRyxJQUFJO0lBRTNDLElBQUksQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDakUsTUFBTSxFQUFFLEdBQUcsR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoQyxNQUFNLEVBQUUsR0FBRyxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2hDLE1BQU0sRUFBRSxHQUFHLEdBQUcsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEMsTUFBTSxFQUFFLEdBQUcsR0FBRyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNwQyxNQUFNLEtBQUssR0FBRyxDQUFDLE9BQU8sR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDO0lBQ3RELE1BQU0sS0FBSyxHQUFHLENBQUMsT0FBTyxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUM7SUFDdEQsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQztJQUM5QixNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDO0lBQzlCLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUM7SUFDOUIsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQztJQUM5QixNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDM0IsTUFBTSxFQUFFLEdBQUcsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQzNCLE1BQU0sRUFBRSxHQUFHLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUMzQixNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDM0IsT0FBTyxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDO0FBQ3BHLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLFdBQVcsQ0FDekIsSUFBYyxFQUFFLEtBQWEsRUFBRSxNQUFtQyxFQUNsRSxNQUE2QixFQUFFLEtBQUssR0FBRyxRQUFRO0lBRS9DLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxRQUFRLENBQUM7SUFDckMsSUFBSSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztRQUFFLE9BQU8sRUFBRSxDQUFDO0lBQzNCLElBQUksRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFDOUIsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUNYLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3QixFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0IsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzdCLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3QixJQUFJLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUU7WUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNwQyxDQUFDO0lBQ0QsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDO0lBQzFDLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztJQUMxQyxNQUFNLEdBQUcsR0FBYyxFQUFFLENBQUM7SUFDMUIsS0FBSyxJQUFJLEVBQUUsR0FBRyxHQUFHLEVBQUUsRUFBRSxJQUFJLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO1FBQ25DLEtBQUssSUFBSSxFQUFFLEdBQUcsR0FBRyxFQUFFLEVBQUUsSUFBSSxHQUFHLEVBQUUsRUFBRSxFQUFFO1lBQUUsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBQ0QsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7VUFDaEUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkQsT0FBTyxHQUFHLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUs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RUFBRSxFQUFFLENBQUM7UUFDakMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLElBQUksQ0FBQyxFQUFFO1lBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNyRyxDQUFDO0lBQ0QsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQyxLQUFLO1FBQUUsT0FBTyxDQUFDLENBQUM7SUFDdEMsTUFBTSxJQUFJLEdBQUcsQ0FBcUQsQ0FBSSxFQUFLLEVBQUU7UUFDM0UsTUFBTSxHQUFHLEdBQUcsSUFBSyxDQUFDLENBQUMsV0FBb0MsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUM7UUFDckUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMvQyxPQUFPLEdBQUcsQ0FBQztJQUNiLENBQUMsQ0FBQztJQUNGLE9BQU87UUFDTCxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxVQUFVLEVBQUUsQ0FBQyxDQUFDLFVBQVU7UUFDNUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDO1FBQ2xHLElBQUksRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztLQUNuQixDQUFDO0FBQ0osQ0FBQztBQUVEOzs7Ozs7R0FNRztBQUNILE1BQU0sVUFBVSxnQkFBZ0IsQ0FDOUIsQ0FBd0IsRUFBRSxHQUFXLEVBQUUsVUFBd0MsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFFdkYsTUFBTSxLQUFLLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7SUFDeEMsTUFBTSxFQUFFLEdBQWEsRUFBRSxDQUFDO0lBQ3hCLE1BQU0sRUFBRSxHQUFhLEVBQUUsQ0FBQztJQUN4QixNQUFNLEVBQUUsR0FBYSxFQUFFLENBQUM7SUFDeEIsTUFBTSxDQUFDLEdBQWEsRUFBRSxDQUFDO0lBQ3ZCLE1BQU0sR0FBRyxHQUFhLEVBQUUsQ0FBQztJQUN6Qiw0RkFBNEY7SUFDNUYsMkRBQTJEO0lBQzNELE1BQU0sS0FBSyxHQUEwQixFQUFFLENBQUM7SUFDeEMsTUFBTSxJQUFJLEdBQTBCLEVBQUUsQ0FBQztJQUN2QyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQ2pDLE1BQU0sRUFBRSxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDOUIsTUFBTSxHQUFHLEdBQUcsR0FBRyxFQUFFLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQzVFLElBQUksQ0FBQyxHQUFHLEtBQUssQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDdkIsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDNUIsSUFBSSxDQUFDLEtBQUssU0FBUyxFQUFFLENBQUM7WUFDcEIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFNLENBQUM7WUFDYixLQUFLLENBQUMsR0FBRyxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNsQixFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7WUFBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzlDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7WUFBQyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksR0FBRyxFQUFFLENBQUMsQ0FBQztZQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLEVBQUUsQ0FBQyxDQUFDO1FBQzVELENBQUM7UUFDRCxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxFQUFFLENBQUM7UUFDckIsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDO1FBQ3JCLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQztRQUNyQixDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ1gsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFD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UUFDMUUsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDbkIsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QixJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDdEIsQ0FBQztJQUNELE9BQU8sSUFBSSxDQUFDO0FBQ2QsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLENBQUMsTUFBTSxhQUFhLEdBQXVCO0lBQy9DLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxFQUFFLENBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQztJQUMzRixDQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsRUFBRSxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsRUFBRSxDQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxTQUFTLENBQUM7Q0FDMUUsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogTGV2ZWwtb2YtZGV0YWlsIHBsYW5uaW5nIGZvciB0aWxlZCBzcGF0aWFsIGdlb21ldHJ5IOKAlCBjZWxsIG91dGxpbmVzIGFuZCB0cmFuc2NyaXB0cy5cbiAqXG4gKiBUaGUgcmVuZGVyZXIga25vd3MgaXRzIGNhbWVyYSAoYSB3b3JsZC1zcGFjZSBjZW50cmUsIGEgem9vbSBpbiBjYW52YXMgcGl4ZWxzIHBlciB3b3JsZFxuICogdW5pdCwgYSBjYW52YXMgc2l6ZSk7IGEgdGlsZWQgZGF0YXNldCBrbm93cyBpdHMgZ3JpZHMgKG9uZSBwZXIgbGV2ZWwsIGluIG9ic2VydmF0aW9uXG4gKiB1bml0cykuIFRoaXMgbW9kdWxlIGlzIHRoZSBicmlkZ2U6IHdoaWNoIGxldmVsIHRoZSB6b29tIGNhbGxzIGZvciwgd2hpY2ggdGlsZXMgYXJlIG9uXG4gKiBzY3JlZW4sIGhvdyBiaWcgYSB0cmFuc2NyaXB0IG1hcmtlciBzaG91bGQgYmUuIEV2ZXJ5dGhpbmcgaGVyZSBpcyBwdXJlLCBzbyB0aGUgcG9saWN5XG4gKiDigJQgdGhlIHBhcnQgdGhhdCBkZWNpZGVzIHdoZXRoZXIgdGhlIHZpZXcgaXMgZmFzdCBhbmQgbGVnaWJsZSDigJQgaXMgdGVzdGFibGUgd2l0aG91dCBhXG4gKiBHUFUuXG4gKlxuICogT2JzZXJ2YXRpb24gdW5pdHMgbWFwIG9udG8gd29ybGQgdW5pdHMgdGhyb3VnaCB0aGUgZGF0YXNldCdzIGBpbWFnZVJlZmAgYWZmaW5lXG4gKiAoYHdvcmxkID0gZGF0YSDCtyBzY2FsZSArIHRyYW5zbGF0ZWApLCBzbyBcInBpeGVscyBwZXIgb2JzZXJ2YXRpb24gdW5pdFwiIGlzXG4gKiBgem9vbSDCtyBzY2FsZWAuIEZvciBhIFhlbml1bSBidW5kbGUgdGhlIGRhdGEgdW5pdCBpcyB0aGUgbWljcm9uIGFuZCB0aGUgd29ybGQgdW5pdCB0aGVcbiAqIG1vcnBob2xvZ3kgcGl4ZWwuXG4gKi9cblxuaW1wb3J0IHR5cGUge1xuICBTcGF0aWFsQm91bmRzLCBTcGF0aWFsSW1hZ2VSZWYsIFNwYXRpYWxUaWxlTGV2ZWwsIFNwYXRpYWxUcmFuc2NyaXB0VGlsZSxcbn0gZnJvbSAnLi4vY29udHJhY3RzL3NwYXRpYWwtZGF0YXNldC5jb250cmFjdCc7XG5pbXBvcnQgdHlwZSB7IFNwYXRpYWxWaWV3U3RhdGUsIFRyYW5zY3JpcHRHbHlwaE5hbWUgfSBmcm9tICcuLi9jb250cmFjdHMvZGlzcGxheS10eXBlcyc7XG5pbXBvcnQgdHlwZSB7IFNwYXRpYWxEYXRhc2V0IH0gZnJvbSAnLi4vY29udHJhY3RzL3NwYXRpYWwtZGF0YXNldC5jb250cmFjdCc7XG5cbi8qKiBBIHJlY3RhbmdsZSBpbiBvYnNlcnZhdGlvbiBjb29yZGluYXRlcy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGF0YVJlY3Qge1xuICB4MDogbnVtYmVyO1xuICB5MDogbnVtYmVyO1xuICB4MTogbnVtYmVyO1xuICB5MTogbnVtYmVyO1xufVxuXG4vKiogVGlsZSBhZGRyZXNzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBUaWxlS2V5IHtcbiAgbGV2ZWw6IG51bWJlcjtcbiAgZ3g6IG51bWJlcjtcbiAgZ3k6IG51bWJlcjtcbn1cblxuLyoqIFdoZXRoZXIgY2VsbCBvdXRsaW5lcyBhcmUgZHJhd246IHRoZSB1c2VyJ3MgY2hvaWNlLCBlbHNlIG9uIHdoZW4gdGhlIGRhdGFzZXQgaGFzIGFueS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjZWxsc1Nob3duKFxuICBkYXRhc2V0OiBQaWNrPFNwYXRpYWxEYXRhc2V0LCAncG9seWdvblRpbGVzJyB8ICdwb2x5Z29ucyc+IHwgbnVsbCxcbiAgdmlldzogUGljazxTcGF0aWFsVmlld1N0YXRlLCAnc2hvd0NlbGxzJz4sXG4pOiBib29sZWFuIHtcbiAgY29uc3QgYXZhaWxhYmxlID0gISEoZGF0YXNldD8ucG9seWdvblRpbGVzIHx8IGRhdGFzZXQ/LnBvbHlnb25zKTtcbiAgcmV0dXJuIGF2YWlsYWJsZSAmJiAodmlldy5zaG93Q2VsbHMgPz8gdHJ1ZSk7XG59XG5cbi8qKiBBIGNvbHVtbiBob2xkaW5nIGEgaGFuZC1jdXJhdGVkIGNlbGwtdHlwZSBhbm5vdGF0aW9uLCBieSBuYW1pbmcgY29udmVudGlvbi4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0N1cmF0ZWRDb2x1bW4obmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiAvY3VyYXRlZC9pLnRlc3QobmFtZSk7XG59XG5cbi8qKlxuICogVGhlIGNhdGVnb3JpY2FsIGNvbHVtbiB0aGF0IG5hbWVzIGVhY2ggY2VsbCdzIHR5cGU6IHRoZSB2aWV3J3MgY2hvaWNlIHdoZW4gaXQgaXMgYVxuICogY29sdW1uIG9mIHRoaXMgZGF0YXNldCwgZWxzZSB0aGUgZmlyc3QgY2F0ZWdvcmljYWwgY29sdW1uIHRoYXQgaXMgbm90IGEgY3VyYXRlZFxuICogYW5ub3RhdGlvbiAoYSBwaXBlbGluZSdzIGNsdXN0ZXJpbmcgaXMgdGhlIGRlZmF1bHQ7IGN1cmF0aW9uIGlzIG9wdGVkIGludG8pLCBlbHNlXG4gKiBhbnkgY2F0ZWdvcmljYWwgY29sdW1uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2VsbFR5cGVDb2x1bW5Gb3IoXG4gIGRhdGFzZXQ6IFNwYXRpYWxEYXRhc2V0LCB2aWV3OiBQaWNrPFNwYXRpYWxWaWV3U3RhdGUsICdjZWxsVHlwZUNvbHVtbic+LFxuKTogc3RyaW5nIHwgbnVsbCB7XG4gIGNvbnN0IGNhdGVnb3JpY2FsID0gZGF0YXNldC5jb2x1bW5zLmZpbHRlcigoYykgPT4gYy5raW5kID09PSAnY2F0ZWdvcmljYWwnKTtcbiAgaWYgKHZpZXcuY2VsbFR5cGVDb2x1bW4gJiYgY2F0ZWdvcmljYWwuc29tZSgoYykgPT4gYy5uYW1lID09PSB2aWV3LmNlbGxUeXBlQ29sdW1uKSkge1xuICAgIHJldHVybiB2aWV3LmNlbGxUeXBlQ29sdW1uO1xuICB9XG4gIHJldHVybiAoY2F0ZWdvcmljYWwuZmluZCgoYykgPT4gIWlzQ3VyYXRlZENvbHVtbihjLm5hbWUpKSA/PyBjYXRlZ29yaWNhbFswXSk/Lm5hbWUgPz8gbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRpbGVJZChrOiBUaWxlS2V5KTogc3RyaW5nIHtcbiAgcmV0dXJuIGAke2subGV2ZWx9LyR7ay5neH0vJHtrLmd5fWA7XG59XG5cbi8qKiBDYW52YXMgcGl4ZWxzIHBlciBvYnNlcnZhdGlvbiB1bml0IGFsb25nIHgsIGZvciBhIGNhbWVyYSB6b29tIGFuZCBhIGRhdGHihpJ3b3JsZCBhZmZpbmUuICovXG5leHBvcnQgZnVuY3Rpb24gcGl4ZWxzUGVyRGF0YVVuaXQoem9vbTogbnVtYmVyLCByZWY/OiBTcGF0aWFsSW1hZ2VSZWYgfCBudWxsKTogbnVtYmVyIHtcbiAgcmV0dXJuIHpvb20gKiBNYXRoLmFicyhyZWY/LnNjYWxlPy5bMF0gPz8gMSk7XG59XG5cbi8qKlxuICogVGhlIHBhcnQgb2Ygb2JzZXJ2YXRpb24gc3BhY2UgdGhlIGNhbWVyYSBzaG93cywgcGFkZGVkIGJ5IGBtYXJnaW5gIChhIGZyYWN0aW9uIG9mIHRoZVxuICogdmlld3BvcnQpIHNvIHRpbGVzIGp1c3Qgb2ZmIHNjcmVlbiBhcmUgYWxyZWFkeSB0aGVyZSB3aGVuIGEgcGFuIGJyaW5ncyB0aGVtIGluLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmlzaWJsZURhdGFSZWN0KFxuICBjZW50ZXI6IHJlYWRvbmx5IFtudW1iZXIsIG51bWJlcl0sIHpvb206IG51bWJlciwgY2FudmFzVzogbnVtYmVyLCBjYW52YXNIOiBudW1iZXIsXG4gIHJlZj86IFNwYXRpYWxJbWFnZVJlZiB8IG51bGwsIG1hcmdpbiA9IDAuMTUsXG4pOiBEYXRhUmVjdCB8IG51bGwge1xuICBpZiAoISh6b29tID4gMCkgfHwgIShjYW52YXNXID4gMCkgfHwgIShjYW52YXNIID4gMCkpIHJldHVybiBudWxsO1xuICBjb25zdCBzeCA9IHJlZj8uc2NhbGU/LlswXSA/PyAxO1xuICBjb25zdCBzeSA9IHJlZj8uc2NhbGU/LlsxXSA/PyAxO1xuICBjb25zdCB0eCA9IHJlZj8udHJhbnNsYXRlPy5bMF0gPz8gMDtcbiAgY29uc3QgdHkgPSByZWY/LnRyYW5zbGF0ZT8uWzFdID8/IDA7XG4gIGNvbnN0IGhhbGZXID0gKGNhbnZhc1cgLyB6b29tIC8gMikgKiAoMSArIDIgKiBtYXJnaW4pO1xuICBjb25zdCBoYWxmSCA9IChjYW52YXNIIC8gem9vbSAvIDIpICogKDEgKyAyICogbWFyZ2luKTtcbiAgY29uc3Qgd3gwID0gY2VudGVyWzBdIC0gaGFsZlc7XG4gIGNvbnN0IHd4MSA9IGNlbnRlclswXSArIGhhbGZXO1xuICBjb25zdCB3eTAgPSBjZW50ZXJbMV0gLSBoYWxmSDtcbiAgY29uc3Qgd3kxID0gY2VudGVyWzFdICsgaGFsZkg7XG4gIGNvbnN0IGF4ID0gKHd4MCAtIHR4KSAvIHN4O1xuICBjb25zdCBieCA9ICh3eDEgLSB0eCkgLyBzeDtcbiAgY29uc3QgYXkgPSAod3kwIC0gdHkpIC8gc3k7XG4gIGNvbnN0IGJ5ID0gKHd5MSAtIHR5KSAvIHN5O1xuICByZXR1cm4geyB4MDogTWF0aC5taW4oYXgsIGJ4KSwgeTA6IE1hdGgubWluKGF5LCBieSksIHgxOiBNYXRoLm1heChheCwgYngpLCB5MTogTWF0aC5tYXgoYXksIGJ5KSB9O1xufVxuXG4vKipcbiAqIFRpbGVzIG9mIG9uZSBsZXZlbCBpbnRlcnNlY3RpbmcgYHJlY3RgLCBjbGlwcGVkIHRvIHRoZSBkYXRhc2V0J3MgYGJvdW5kc2AgKHNvIHpvb21pbmdcbiAqIG91dCBvdmVyIGVtcHR5IGNhbnZhcyBkb2VzIG5vdCBhc2sgZm9yIHRpbGVzIHRoYXQgY2Fubm90IGV4aXN0KS4gT3JkZXJlZCBmcm9tIHRoZVxuICogcmVjdGFuZ2xlJ3MgY2VudHJlIG91dHdhcmQsIHNvIHRoZSBtaWRkbGUgb2YgdGhlIHNjcmVlbiBmaWxscyBpbiBmaXJzdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRpbGVzSW5SZWN0KFxuICByZWN0OiBEYXRhUmVjdCwgbGV2ZWw6IG51bWJlciwgbGV2ZWxzOiByZWFkb25seSBTcGF0aWFsVGlsZUxldmVsW10sXG4gIGJvdW5kcz86IFNwYXRpYWxCb3VuZHMgfCBudWxsLCBsaW1pdCA9IEluZmluaXR5LFxuKTogVGlsZUtleVtdIHtcbiAgY29uc3Qgc2l6ZSA9IGxldmVsc1tsZXZlbF0/LnRpbGVTaXplO1xuICBpZiAoIShzaXplID4gMCkpIHJldHVybiBbXTtcbiAgbGV0IHsgeDAsIHkwLCB4MSwgeTEgfSA9IHJlY3Q7XG4gIGlmIChib3VuZHMpIHtcbiAgICB4MCA9IE1hdGgubWF4KHgwLCBib3VuZHNbMF0pO1xuICAgIHkwID0gTWF0aC5tYXgoeTAsIGJvdW5kc1sxXSk7XG4gICAgeDEgPSBNYXRoLm1pbih4MSwgYm91bmRzWzJdKTtcbiAgICB5MSA9IE1hdGgubWluKHkxLCBib3VuZHNbM10pO1xuICAgIGlmICh4MSA8IHgwIHx8IHkxIDwgeTApIHJldHVybiBbXTtcbiAgfVxuICBjb25zdCBneDAgPSBNYXRoLmZsb29yKHgwIC8gc2l6ZSk7XG4gIGNvbnN0IGd4MSA9IE1hdGguZmxvb3IoeDEgLyBzaXplKTtcbiAgY29uc3QgZ3kwID0gTWF0aC5mbG9vcih5MCAvIHNpemUpO1xuICBjb25zdCBneTEgPSBNYXRoLmZsb29yKHkxIC8gc2l6ZSk7XG4gIGNvbnN0IGN4ID0gKHJlY3QueDAgKyByZWN0LngxKSAvIDIgLyBzaXplO1xuICBjb25zdCBjeSA9IChyZWN0LnkwICsgcmVjdC55MSkgLyAyIC8gc2l6ZTtcbiAgY29uc3Qgb3V0OiBUaWxlS2V5W10gPSBbXTtcbiAgZm9yIChsZXQgZ3kgPSBneTA7IGd5IDw9IGd5MTsgZ3krKykge1xuICAgIGZvciAobGV0IGd4ID0gZ3gwOyBneCA8PSBneDE7IGd4KyspIG91dC5wdXNoKHsgbGV2ZWwsIGd4LCBneSB9KTtcbiAgfVxuICBvdXQuc29ydCgoYSwgYikgPT4gKChhLmd4ICsgMC41IC0gY3gpICoqIDIgKyAoYS5neSArIDAuNSAtIGN5KSAqKiAyKVxuICAgIC0gKChiLmd4ICsgMC41IC0gY3gpICoqIDIgKyAoYi5neSArIDAuNSAtIGN5KSAqKiAyKSk7XG4gIHJldHVybiBvdXQubGVuZ3RoID4gbGltaXQgPyBvdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0O1xufVxuXG4vKipcbiAqIFR5cGljYWwgY2VsbCBkaWFtZXRlciwgaW4gb2JzZXJ2YXRpb24gdW5pdHMsIHVzZWQgdG8ganVkZ2UgaG93IGxhcmdlIGNlbGxzIGFwcGVhci5cbiAqIERlcml2ZWQgZnJvbSB0aGUgcGVyLW9ic2VydmF0aW9uIHJhZGl1cyB3aGVuIHRoZXJlIGlzIG9uZTsgMTIgwrVtIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR5cGljYWxDZWxsRGlhbWV0ZXIocmFkaXVzOiBGbG9hdDMyQXJyYXkgfCBudW1iZXIgfCB1bmRlZmluZWQsIGZhbGxiYWNrID0gMTIpOiBudW1iZXIge1xuICBpZiAodHlwZW9mIHJhZGl1cyA9PT0gJ251bWJlcicpIHJldHVybiByYWRpdXMgPiAwID8gcmFkaXVzICogMiA6IGZhbGxiYWNrO1xuICBpZiAoIXJhZGl1cz8ubGVuZ3RoKSByZXR1cm4gZmFsbGJhY2s7XG4gIC8vIFRoZSBtZWRpYW4gb2YgYSBzYW1wbGUgaXMgcGxlbnR5IOKAlCB0aGlzIHNldHMgYSB0aHJlc2hvbGQsIG5vdCBhIG1lYXN1cmVtZW50LlxuICBjb25zdCBzdGVwID0gTWF0aC5tYXgoMSwgTWF0aC5mbG9vcihyYWRpdXMubGVuZ3RoIC8gMjA0OCkpO1xuICBjb25zdCBzYW1wbGU6IG51bWJlcltdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcmFkaXVzLmxlbmd0aDsgaSArPSBzdGVwKSB7XG4gICAgaWYgKHJhZGl1c1tpXSA+IDApIHNhbXBsZS5wdXNoKHJhZGl1c1tpXSk7XG4gIH1cbiAgaWYgKCFzYW1wbGUubGVuZ3RoKSByZXR1cm4gZmFsbGJhY2s7XG4gIHNhbXBsZS5zb3J0KChhLCBiKSA9PiBhIC0gYik7XG4gIHJldHVybiBzYW1wbGVbc2FtcGxlLmxlbmd0aCA+PiAxXSAqIDI7XG59XG5cbi8qKlxuICogT24tc2NyZWVuIGNlbGwgZGlhbWV0ZXIgKHB4KSBhdCBvciBhYm92ZSB3aGljaCBlYWNoIHBvbHlnb24gbGV2ZWwgaXMgdXNlZC4gQSBsZXZlbFxuICogaGFsdmVzIHRoZSB2ZXJ0aWNlcyBvZiB0aGUgb25lIGJlbG93LCBzbyBlYWNoIHNob3VsZCB0YWtlIG92ZXIgd2hlbiB0aGUgY2VsbCBpcyBhYm91dFxuICogaGFsZiBhcyBsYXJnZSBvbiBzY3JlZW4uIEJlbG93IHRoZSBsYXN0IGZpbml0ZSB0aHJlc2hvbGQgb3V0bGluZXMgYXJlIG5vdCBkcmF3biBhdFxuICogYWxsIOKAlCBhIGNlbGwgYSBmZXcgcGl4ZWxzIHdpZGUgaXMgYSBkb3QsIGFuZCB0aGUgb2JzZXJ2YXRpb24gbWFya2VycyBhbHJlYWR5IGRyYXcgaXRcbiAqIGFzIG9uZS5cbiAqXG4gKiBYZW5pdW0ncyBmb3VydGggbGV2ZWwgKDMgdmVydGljZXMgcGVyIGNlbGwpIGlzIGRlbGliZXJhdGVseSBuZXZlciB1c2VkOiBzZWVuIG9uXG4gKiBzY3JlZW4gaXQgaXMgYSBmaWVsZCBvZiB0cmlhbmdsZXMsIHdoaWNoIHJlYWRzIGFzIGFuIGFydGVmYWN0IHJhdGhlciB0aGFuIGFzIGNlbGxzLlxuICogVGhlIGRvdHMgYmVsb3cgOCBweCBzYXkgdGhlIHNhbWUgdGhpbmcgbW9yZSBob25lc3RseS5cbiAqL1xuZXhwb3J0IGNvbnN0IFBPTFlHT05fTEVWRUxfTUlOX0NFTExfUFggPSBbMzYsIDE4LCA4LCBJbmZpbml0eV07XG5cbi8qKlxuICogV2hpY2ggcG9seWdvbiBsZXZlbCBzdWl0cyB0aGlzIHpvb20sIG9yIC0xIGZvciBcInRvbyBzbWFsbCB0byBvdXRsaW5lXCIuXG4gKiBgZGV0YWlsYCA+IDEgcHJlZmVycyBmaW5lciBsZXZlbHMgKHNoYXJwZXIsIHNsb3dlcik7IDwgMSBjb2Fyc2VyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcG9seWdvbkxldmVsRm9yKFxuICBweFBlclVuaXQ6IG51bWJlciwgY2VsbERpYW1ldGVyOiBudW1iZXIsIGxldmVsQ291bnQ6IG51bWJlciwgZGV0YWlsID0gMSxcbik6IG51bWJlciB7XG4gIGNvbnN0IGNlbGxQeCA9IHB4UGVyVW5pdCAqIGNlbGxEaWFtZXRlciAqIGRldGFpbDtcbiAgY29uc3QgdGFibGUgPSBQT0xZR09OX0xFVkVMX01JTl9DRUxMX1BYO1xuICBmb3IgKGxldCBsID0gMDsgbCA8IGxldmVsQ291bnQ7IGwrKykge1xuICAgIC8vIFBhc3QgdGhlIHRhYmxlLCBrZWVwIGhhbHZpbmc6IGVhY2ggbGV2ZWwgc3RpbGwgaGFsdmVzIHRoZSB2ZXJ0aWNlcy5cbiAgICBjb25zdCBtaW4gPSB0YWJsZVtsXSA/PyB0YWJsZVt0YWJsZS5sZW5ndGggLSAxXSAvIDIgKiogKGwgLSB0YWJsZS5sZW5ndGggKyAxKTtcbiAgICBpZiAoY2VsbFB4ID49IG1pbikgcmV0dXJuIGw7XG4gIH1cbiAgcmV0dXJuIC0xO1xufVxuXG4vKipcbiAqIFdoaWNoIHRyYW5zY3JpcHQgbGV2ZWwgc3VpdHMgdGhpcyB6b29tOiB0aGUgb25lIHdob3NlIHRpbGVzIGNvbWUgb3V0IGNsb3Nlc3QgdG9cbiAqIGB0YXJnZXRUaWxlUHhgIG9uIHNjcmVlbi4gQ29hcnNlciBsZXZlbHMgYWdncmVnYXRlIG1vcmUsIHNvIHRoaXMga2VlcHMgdGhlIG51bWJlciBvZlxuICogbWFya2VycyBwZXIgc2NyZWVuIHJvdWdobHkgY29uc3RhbnQgaG93ZXZlciBmYXIgb3V0IHRoZSBjYW1lcmEgaXMg4oCUIHRoZSBwcm9wZXJ0eSB0aGF0XG4gKiBrZWVwcyB0aGUgdmlldyBmYXN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNjcmlwdExldmVsRm9yKFxuICBweFBlclVuaXQ6IG51bWJlciwgbGV2ZWxzOiByZWFkb25seSBTcGF0aWFsVGlsZUxldmVsW10sIHRhcmdldFRpbGVQeCA9IDUxMixcbik6IG51bWJlciB7XG4gIGlmICghbGV2ZWxzLmxlbmd0aCB8fCAhKHB4UGVyVW5pdCA+IDApKSByZXR1cm4gMDtcbiAgbGV0IGJlc3QgPSAwO1xuICBsZXQgYmVzdEVyciA9IEluZmluaXR5O1xuICBmb3IgKGxldCBsID0gMDsgbCA8IGxldmVscy5sZW5ndGg7IGwrKykge1xuICAgIGNvbnN0IGVyciA9IE1hdGguYWJzKE1hdGgubG9nMigobGV2ZWxzW2xdLnRpbGVTaXplICogcHhQZXJVbml0KSAvIHRhcmdldFRpbGVQeCkpO1xuICAgIGlmIChlcnIgPCBiZXN0RXJyKSB7XG4gICAgICBiZXN0RXJyID0gZXJyO1xuICAgICAgYmVzdCA9IGw7XG4gICAgfVxuICB9XG4gIHJldHVybiBiZXN0O1xufVxuXG4vKipcbiAqIFRoZSBiaW4gYSBzZWxlY3Rpb24gb2YgZ2VuZXMgaXMgZ3JvdXBlZCBpbnRvIGF0IHRoaXMgem9vbSwgaW4gb2JzZXJ2YXRpb24gdW5pdHMsIG9yIG51bGxcbiAqIHRvIGRyYXcgZXZlcnkgdHJhbnNjcmlwdC4gQmlucyBmb2xsb3cgdGhlIGFsbC1nZW5lIHB5cmFtaWQncyBsYWRkZXIgKGBiYXNlQmluYCDDlyAyXm0pIHNvIGFcbiAqIGdlbmUgc2VsZWN0aW9uIGFuZCBcImFsbCBnZW5lc1wiIGdyb3VwIGFsaWtlOiB0aGUgZmluZXN0IGJpbiB3aG9zZSBtYXJrZXJzIGxhbmQgYXQgbGVhc3RcbiAqIGBzcGFjaW5nUHhgIGFwYXJ0IG9uIHNjcmVlbi4gT25jZSB0aGUgZmluZXN0IGJpbiBpcyB0aGF0IHdpZGUsIHRyYW5zY3JpcHRzIGFyZSBkcmF3biBhc1xuICogdGhlbXNlbHZlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdlbmVCaW5TaXplKFxuICBweFBlclVuaXQ6IG51bWJlciwgYmFzZUJpbjogbnVtYmVyLCBsZXZlbHMgPSA3LCBzcGFjaW5nUHggPSBHUk9VUF9NSU5fU1BBQ0lOR19QWCxcbik6IG51bWJlciB8IG51bGwge1xuICBpZiAoIShweFBlclVuaXQgPiAwKSB8fCAhKGJhc2VCaW4gPiAwKSkgcmV0dXJuIG51bGw7XG4gIGlmIChiYXNlQmluICogcHhQZXJVbml0ID49IHNwYWNpbmdQeCkgcmV0dXJuIG51bGw7XG4gIGZvciAobGV0IG0gPSAxOyBtIDwgbGV2ZWxzOyBtKyspIHtcbiAgICBjb25zdCBiaW4gPSBiYXNlQmluICogMiAqKiBtO1xuICAgIGlmIChiaW4gKiBweFBlclVuaXQgPj0gc3BhY2luZ1B4KSByZXR1cm4gYmluO1xuICB9XG4gIHJldHVybiBiYXNlQmluICogMiAqKiAobGV2ZWxzIC0gMSk7XG59XG5cbi8qKiBUaGUgZW50cmllcyBvZiBgdGAgaW5zaWRlIGByZWN0YCAob2JzZXJ2YXRpb24gdW5pdHMpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsaXBUcmFuc2NyaXB0cyh0OiBTcGF0aWFsVHJhbnNjcmlwdFRpbGUsIHJlY3Q6IERhdGFSZWN0KTogU3BhdGlhbFRyYW5zY3JpcHRUaWxlIHtcbiAgY29uc3Qga2VlcDogbnVtYmVyW10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB0LmNvdW50OyBpKyspIHtcbiAgICBpZiAodC54W2ldID49IHJlY3QueDAgJiYgdC54W2ldIDw9IHJlY3QueDEgJiYgdC55W2ldID49IHJlY3QueTAgJiYgdC55W2ldIDw9IHJlY3QueTEpIGtlZXAucHVzaChpKTtcbiAgfVxuICBpZiAoa2VlcC5sZW5ndGggPT09IHQuY291bnQpIHJldHVybiB0O1xuICBjb25zdCBwaWNrID0gPEEgZXh0ZW5kcyBGbG9hdDMyQXJyYXkgfCBVaW50MzJBcnJheSB8IFVpbnQxNkFycmF5PihhOiBBKTogQSA9PiB7XG4gICAgY29uc3Qgb3V0ID0gbmV3IChhLmNvbnN0cnVjdG9yIGFzIG5ldyAobjogbnVtYmVyKSA9PiBBKShrZWVwLmxlbmd0aCk7XG4gICAga2VlcC5mb3JFYWNoKChzcmMsIGkpID0+IHsgb3V0W2ldID0gYVtzcmNdOyB9KTtcbiAgICByZXR1cm4gb3V0O1xuICB9O1xuICByZXR1cm4ge1xuICAgIGNvdW50OiBrZWVwLmxlbmd0aCwgYWdncmVnYXRlZDogdC5hZ2dyZWdhdGVkLFxuICAgIHg6IHBpY2sodC54KSwgeTogcGljayh0LnkpLCB6OiBwaWNrKHQueiksIHdlaWdodDogcGljayh0LndlaWdodCksIG9ic2VydmF0aW9uOiBwaWNrKHQub2JzZXJ2YXRpb24pLFxuICAgIGdlbmU6IHBpY2sodC5nZW5lKSxcbiAgfTtcbn1cblxuLyoqXG4gKiBHcm91cCB0cmFuc2NyaXB0cyBpbnRvIGBiaW5gLXdpZGUgc3F1YXJlcyBvZiBhIGdyaWQgYW5jaG9yZWQgYXQgdGhlIG9yaWdpbiAoc28gYSBwYW4gZG9lc1xuICogbm90IG1vdmUgdGhlbSksIG9uZSBlbnRyeSBwZXIgKGdyb3VwLCBzcXVhcmUpOiBgZ3JvdXBPZihnZW5lIHNsb3QpYCBzYXlzIHdoaWNoIGdyb3VwIGEgZ2VuZVxuICogaXMgaW4g4oCUIGl0cyBjbHVzdGVyIGluIHRoZSBnZW5lIHRyZWUsIG9yIGl0c2VsZi4gRWFjaCBlbnRyeSBzaXRzIGF0IGl0cyB0cmFuc2NyaXB0cydcbiAqIGNlbnRyb2lkLCB3ZWlnaHRlZCBieSBob3cgbWFueSBlYWNoIHN0YW5kcyBmb3I7IGl0IHRha2VzIHRoZSBnZW5lIGFuZCB0aGUgY2VsbCBob2xkaW5nIG1vc3RcbiAqIG9mIHRoZW0sIGVhY2ggc3VtbWVkIG92ZXIgYWxsIGl0cyB0cmFuc2NyaXB0cyBpbiB0aGUgZW50cnkuIGBncm91cFtpXWAgaXMgZW50cnkgaSdzIGdyb3VwLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ3JvdXBUcmFuc2NyaXB0cyhcbiAgdDogU3BhdGlhbFRyYW5zY3JpcHRUaWxlLCBiaW46IG51bWJlciwgZ3JvdXBPZjogKGdlbmVTbG90OiBudW1iZXIpID0+IG51bWJlciA9IChnKSA9PiBnLFxuKTogeyB0aWxlOiBTcGF0aWFsVHJhbnNjcmlwdFRpbGU7IGdyb3VwOiBJbnQzMkFycmF5IH0ge1xuICBjb25zdCBpbmRleCA9IG5ldyBNYXA8c3RyaW5nLCBudW1iZXI+KCk7XG4gIGNvbnN0IHN4OiBudW1iZXJbXSA9IFtdO1xuICBjb25zdCBzeTogbnVtYmVyW10gPSBbXTtcbiAgY29uc3Qgc3o6IG51bWJlcltdID0gW107XG4gIGNvbnN0IHc6IG51bWJlcltdID0gW107XG4gIGNvbnN0IGdycDogbnVtYmVyW10gPSBbXTtcbiAgLy8gUGVyIGVudHJ5LCBob3cgbWFueSB0cmFuc2NyaXB0cyBvZiBlYWNoIGdlbmUgKHRoZSBkb21pbmFudCBvbmUgZ2l2ZXMgdGhlIGljb24gYW5kIGNvbG91cilcbiAgLy8gYW5kIGluIGVhY2ggY2VsbCAodGhlIGRvbWluYW50IG9uZSBpcyB0aGUgZW50cnkncyBjZWxsKS5cbiAgY29uc3QgZ2VuZVc6IE1hcDxudW1iZXIsIG51bWJlcj5bXSA9IFtdO1xuICBjb25zdCBvYnNXOiBNYXA8bnVtYmVyLCBudW1iZXI+W10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB0LmNvdW50OyBpKyspIHtcbiAgICBjb25zdCBnayA9IGdyb3VwT2YodC5nZW5lW2ldKTtcbiAgICBjb25zdCBrZXkgPSBgJHtna318JHtNYXRoLmZsb29yKHQueFtpXSAvIGJpbil9fCR7TWF0aC5mbG9vcih0LnlbaV0gLyBiaW4pfWA7XG4gICAgbGV0IGsgPSBpbmRleC5nZXQoa2V5KTtcbiAgICBjb25zdCB3aSA9IHQud2VpZ2h0W2ldIHx8IDE7XG4gICAgaWYgKGsgPT09IHVuZGVmaW5lZCkge1xuICAgICAgayA9IHcubGVuZ3RoO1xuICAgICAgaW5kZXguc2V0KGtleSwgayk7XG4gICAgICBzeC5wdXNoKDApOyBzeS5wdXNoKDApOyBzei5wdXNoKDApOyB3LnB1c2goMCk7XG4gICAgICBncnAucHVzaChnayk7IGdlbmVXLnB1c2gobmV3IE1hcCgpKTsgb2JzVy5wdXNoKG5ldyBNYXAoKSk7XG4gICAgfVxuICAgIHN4W2tdICs9IHQueFtpXSAqIHdpO1xuICAgIHN5W2tdICs9IHQueVtpXSAqIHdpO1xuICAgIHN6W2tdICs9IHQueltpXSAqIHdpO1xuICAgIHdba10gKz0gd2k7XG4gICAgZ2VuZVdba10uc2V0KHQuZ2VuZVtpXSwgKGdlbmVXW2tdLmdldCh0LmdlbmVbaV0pID8/IDApICsgd2kpO1xuICAgIG9ic1dba10uc2V0KHQub2JzZXJ2YXRpb25baV0sIChvYnNXW2tdLmdldCh0Lm9ic2VydmF0aW9uW2ldKSA/PyAwKSArIHdpKTtcbiAgfVxuICBjb25zdCBuID0gdy5sZW5ndGg7XG4gIGNvbnN0IHRpbGU6IFNwYXRpYWxUcmFuc2NyaXB0VGlsZSA9IHtcbiAgICBjb3VudDogbiwgYWdncmVnYXRlZDogdHJ1ZSxcbiAgICB4OiBuZXcgRmxvYXQzMkFycmF5KG4pLCB5OiBuZXcgRmxvYXQzMkFycmF5KG4pLCB6OiBuZXcgRmxvYXQzMkFycmF5KG4pLFxuICAgIHdlaWdodDogbmV3IFVpbnQzMkFycmF5KG4pLCBvYnNlcnZhdGlvbjogbmV3IFVpbnQzMkFycmF5KG4pLCBnZW5lOiBuZXcgVWludDE2QXJyYXkobiksXG4gIH07XG4gIGNvbnN0IGdyb3VwID0gbmV3IEludDMyQXJyYXkobik7XG4gIGZvciAobGV0IGsgPSAwOyBrIDwgbjsgaysrKSB7XG4gICAgdGlsZS54W2tdID0gc3hba10gLyB3W2tdO1xuICAgIHRpbGUueVtrXSA9IHN5W2tdIC8gd1trXTtcbiAgICB0aWxlLnpba10gPSBzeltrXSAvIHdba107XG4gICAgdGlsZS53ZWlnaHRba10gPSB3W2tdO1xuICAgIHRpbGUub2JzZXJ2YXRpb25ba10gPSBkb21pbmFudChvYnNXW2tdKTtcbiAgICB0aWxlLmdlbmVba10gPSBkb21pbmFudChnZW5lV1trXSk7XG4gICAgZ3JvdXBba10gPSBncnBba107XG4gIH1cbiAgcmV0dXJuIHsgdGlsZSwgZ3JvdXAgfTtcbn1cblxuLyoqIFRoZSBrZXkgd2l0aCB0aGUgbGFyZ2VzdCB0b3RhbDsgdGhlIGZpcnN0IHNlZW4gb24gYSB0aWUuICovXG5mdW5jdGlvbiBkb21pbmFudCh0b3RhbHM6IE1hcDxudW1iZXIsIG51bWJlcj4pOiBudW1iZXIge1xuICBsZXQgYmVzdCA9IDA7XG4gIGxldCB0b3AgPSAtMTtcbiAgZm9yIChjb25zdCBba2V5LCB2XSBvZiB0b3RhbHMpIGlmICh2ID4gdG9wKSB7IHRvcCA9IHY7IGJlc3QgPSBrZXk7IH1cbiAgcmV0dXJuIGJlc3Q7XG59XG5cbi8qKlxuICogVGhlIGNvbG91ciBvZiBlYWNoIGdlbmUtdHJlZSBjbHVzdGVyIG9mIGEgc2VsZWN0aW9uLCBmb3IgY29sb3VyaW5nIHRyYW5zY3JpcHRzIGJ5IGNsdXN0ZXI6IGFcbiAqIGNsdXN0ZXIgbmFtZWQgbGlrZSBhIGdyb3VwIG9mIHRoZSBjZWxscycgZ3JvdXBpbmcgdGFrZXMgdGhhdCBncm91cCdzIGNvbG91ciAoaXRzIGNlbGxzIGFuZCBpdHNcbiAqIHRyYW5zY3JpcHRzIGFncmVlKTsgdGhlIG90aGVycyB0YWtlIHBhbGV0dGUgY29sb3VycyBpbiB0cmVlIG9yZGVyLiBDbHVzdGVycyBhcmUgdGhlIHRyZWUnc1xuICogZ3JvdXBzIGhvbGRpbmcgYSBzZWxlY3RlZCBnZW5lLCB0aGVuIGVhY2ggdW5ncm91cGVkIHNlbGVjdGVkIGdlbmUgb24gaXRzIG93bi4gRXZlcnkgZ2VuZSBvZiBhXG4gKiBjbHVzdGVyIGdldHMgdGhlIHNhbWUgY29sb3VyIOKAlCB0aGUgdHJlZSdzIHN3YXRjaGVzIGFuZCB0aGUgbWFya2VycyB1c2UgdGhpcyBvbmUgbWFwLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2x1c3RlckNvbG9yTWFwKFxuICBnZW5lczogcmVhZG9ubHkgc3RyaW5nW10sIGdyb3VwczogcmVhZG9ubHkgeyBuYW1lOiBzdHJpbmc7IGdlbmVzOiByZWFkb25seSBzdHJpbmdbXSB9W10sXG4gIGNlbGxDb2xvcnM6IFJlYWRvbmx5TWFwPHN0cmluZywgc3RyaW5nPiwgcGFsZXR0ZTogcmVhZG9ubHkgc3RyaW5nW10sXG4pOiBNYXA8c3RyaW5nLCBzdHJpbmc+IHtcbiAgY29uc3QgY2hvc2VuID0gbmV3IFNldChnZW5lcyk7XG4gIGNvbnN0IG5hbWVzOiBzdHJpbmdbXSA9IFtdO1xuICBjb25zdCBncm91cGVkID0gbmV3IFNldDxzdHJpbmc+KCk7XG4gIGZvciAoY29uc3QgZyBvZiBncm91cHMpIHtcbiAgICBjb25zdCBtaW5lID0gZy5nZW5lcy5maWx0ZXIoKHgpID0+IGNob3Nlbi5oYXMoeCkgJiYgIWdyb3VwZWQuaGFzKHgpKTtcbiAgICBpZiAoIW1pbmUubGVuZ3RoKSBjb250aW51ZTtcbiAgICBtaW5lLmZvckVhY2goKHgpID0+IGdyb3VwZWQuYWRkKHgpKTtcbiAgICBuYW1lcy5wdXNoKGcubmFtZSk7XG4gIH1cbiAgZm9yIChjb25zdCBnZW5lIG9mIGdlbmVzKSBpZiAoIWdyb3VwZWQuaGFzKGdlbmUpKSBuYW1lcy5wdXNoKGdlbmUpO1xuICBjb25zdCBvdXQgPSBuZXcgTWFwPHN0cmluZywgc3RyaW5nPigpO1xuICBsZXQgayA9IDA7XG4gIGZvciAoY29uc3QgbmFtZSBvZiBuYW1lcykge1xuICAgIGlmIChvdXQuaGFzKG5hbWUpKSBjb250aW51ZTtcbiAgICBvdXQuc2V0KG5hbWUsIGNlbGxDb2xvcnMuZ2V0KG5hbWUpID8/IHBhbGV0dGVbaysrICUgcGFsZXR0ZS5sZW5ndGhdKTtcbiAgfVxuICByZXR1cm4gb3V0O1xufVxuXG4vKiogVGhlIGNsdXN0ZXIgYSBzZWxlY3RlZCBnZW5lIGlzIGluOiBpdHMgZmlyc3QgZ2VuZS10cmVlIGdyb3VwIGhvbGRpbmcgaXQsIGVsc2UgaXRzZWxmLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNsdXN0ZXJPZkdlbmUoXG4gIGdlbmU6IHN0cmluZywgZ3JvdXBzOiByZWFkb25seSB7IG5hbWU6IHN0cmluZzsgZ2VuZXM6IHJlYWRvbmx5IHN0cmluZ1tdIH1bXSxcbik6IHN0cmluZyB7XG4gIHJldHVybiBncm91cHMuZmluZCgoZykgPT4gZy5nZW5lcy5pbmNsdWRlcyhnZW5lKSk/Lm5hbWUgPz8gZ2VuZTtcbn1cblxuLyoqIFNtYWxsZXN0IGFuZCBsYXJnZXN0IHRyYW5zY3JpcHQgbWFya2VyLCBpbiBjYW52YXMgcGl4ZWxzLiAqL1xuZXhwb3J0IGNvbnN0IFRSQU5TQ1JJUFRfTUlOX1BYID0gNDtcbmV4cG9ydCBjb25zdCBUUkFOU0NSSVBUX01BWF9QWCA9IDMyO1xuLyoqXG4gKiBQaHlzaWNhbCBkaWFtZXRlciBhIHNpbmdsZSB0cmFuc2NyaXB0IGlzIGRyYXduIGF0LCBpbiDCtW0g4oCUIGNsZWFybHkgbGFyZ2VyIHRoYW4gdGhlXG4gKiBpbWFnZWQgc3BvdCAofjAuMyDCtW0pIHNvIGl0IHN0YXlzIGxlZ2libGUsIGFuZCBzbWFsbCBlbm91Z2ggdGhhdCBuZWlnaGJvdXJpbmdcbiAqIG1vbGVjdWxlcyBpbnNpZGUgb25lIGNlbGwgc3RheSBhcGFydC5cbiAqL1xuZXhwb3J0IGNvbnN0IFRSQU5TQ1JJUFRfUEhZU0lDQUxfVU0gPSAxLjI7XG5cbi8qKlxuICogTWFya2VyIGRpYW1ldGVyIGluIGNhbnZhcyBwaXhlbHMgZm9yIGFuIGVudHJ5IHN0YW5kaW5nIGZvciBgd2VpZ2h0YCB0cmFuc2NyaXB0cy5cbiAqXG4gKiBUaGUgY29udmVudGlvbiBzcGF0aWFsIHZpZXdlcnMgc2hhcmUgKGRlY2suZ2wncyBgcmFkaXVzTWluUGl4ZWxzYC9gcmFkaXVzTWF4UGl4ZWxzYCxcbiAqIFhlbml1bSBFeHBsb3JlcidzIHRyYW5zY3JpcHQgc2l6ZSk6IGEgUEhZU0lDQUwgc2l6ZSwgY2xhbXBlZCB0byBhIHNjcmVlbi1waXhlbCByYW5nZS5cbiAqIFpvb21lZCBvdXQsIG1hcmtlcnMgc2l0IGF0IHRoZSBtaW5pbXVtIGFuZCBuZXZlciB2YW5pc2g7IHpvb21lZCBpbiwgdGhleSBncm93IHdpdGggdGhlXG4gKiB0aXNzdWUgaW5zdGVhZCBvZiBzaHJpbmtpbmcgdG8gc3BlY2tzIG5leHQgdG8gY2VsbHMgaHVuZHJlZHMgb2YgcGl4ZWxzIHdpZGUuIEEgZml4ZWRcbiAqIHNjcmVlbiBzaXplIGRvZXMgdGhlIG9wcG9zaXRlIGF0IGhpZ2ggem9vbSwgd2hpY2ggaXMgd2hhdCBtYWRlIHRyYW5zY3JpcHRzIGRpc2FwcGVhclxuICogYXQgcGl4ZWwtbGV2ZWwgem9vbS5cbiAqXG4gKiBBZ2dyZWdhdGVzIGdyb3cgd2l0aCB0aGUgY3ViZSByb290IG9mIHRoZWlyIGNvdW50OiBhcmVhIOKInSBjb3VudCB3b3VsZCBsZXQgb25lIGRlbnNlXG4gKiBhZ2dyZWdhdGUgc3dhbGxvdyBpdHMgbmVpZ2hib3VycywgdGhlIGN1YmUgcm9vdCBrZWVwcyBhIDEwMDAtdHJhbnNjcmlwdCBjbHVzdGVyIGNsZWFybHlcbiAqIGxhcmdlciB0aGFuIGEgMTAtdHJhbnNjcmlwdCBvbmUgd2l0aG91dCBjb3ZlcmluZyB0aGUgdGlsZS5cbiAqXG4gKiBgcHhQZXJNaWNyb25gIGlzIG9taXR0ZWQgZm9yIGRhdGEgd2l0aCBubyBrbm93biBwaHlzaWNhbCB1bml0OyB0aGUgbWFya2VyIGlzIHRoZW5cbiAqIHNjcmVlbi1zaXplZCBvbmx5LlxuICovXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNjcmlwdE1hcmtlclB4KHdlaWdodDogbnVtYmVyLCBzY2FsZSA9IDEsIHB4UGVyTWljcm9uPzogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgY291bnRlZCA9IFRSQU5TQ1JJUFRfTUlOX1BYICogTWF0aC5jYnJ0KE1hdGgubWF4KDEsIHdlaWdodCkpO1xuICBjb25zdCBwaHlzaWNhbCA9IHB4UGVyTWljcm9uID8gVFJBTlNDUklQVF9QSFlTSUNBTF9VTSAqIHB4UGVyTWljcm9uIDogMDtcbiAgY29uc3QgcHggPSBNYXRoLm1heChjb3VudGVkLCBwaHlzaWNhbCkgKiBzY2FsZTtcbiAgcmV0dXJuIE1hdGgubWluKFRSQU5TQ1JJUFRfTUFYX1BYICogTWF0aC5tYXgoc2NhbGUsIDEpLCBNYXRoLm1heChUUkFOU0NSSVBUX01JTl9QWCAqIHNjYWxlLCBweCkpO1xufVxuXG4vLyDilIDilIAgR2x5cGhzIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4vKiogTWFya2VyIHNoYXBlcyBmb3IgdGhlIHRyYW5zY3JpcHQgXCJpY29uXCIgbW9kZS4gQWxsIHN0YXItY29udmV4LCBzbyBhIGZhbiBmaWxscyB0aGVtLiAqL1xuZXhwb3J0IGNvbnN0IFRSQU5TQ1JJUFRfR0xZUEhTID0gW1xuICAnY2lyY2xlJywgJ3N0YXInLCAndHJpYW5nbGUnLCAnc3F1YXJlJywgJ2RpYW1vbmQnLCAnY3Jvc3MnLCAnaGV4YWdvbicsICd0cmlhbmdsZS1kb3duJyxcbiAgJ3BlbnRhZ29uJywgJ3gnLFxuXSBhcyBjb25zdDtcbmV4cG9ydCB0eXBlIFRyYW5zY3JpcHRHbHlwaCA9IHR5cGVvZiBUUkFOU0NSSVBUX0dMWVBIU1tudW1iZXJdO1xuLy8gVGhlIHZpZXcgc3RhdGUgbmFtZXMgZ2x5cGhzIHdpdGhvdXQgaW1wb3J0aW5nIHRoaXMgbW9kdWxlOyBrZWVwIHRoZSB0d28gaW4gc3RlcC5cbmNvbnN0IF9nbHlwaE5hbWVzTWF0Y2g6IFRyYW5zY3JpcHRHbHlwaCBleHRlbmRzIFRyYW5zY3JpcHRHbHlwaE5hbWVcbiAgPyAoVHJhbnNjcmlwdEdseXBoTmFtZSBleHRlbmRzIFRyYW5zY3JpcHRHbHlwaCA/IHRydWUgOiBuZXZlcikgOiBuZXZlciA9IHRydWU7XG52b2lkIF9nbHlwaE5hbWVzTWF0Y2g7XG5cbi8qKiBVbml0IG91dGxpbmUgb2YgYSBnbHlwaCwgcmFkaXVzIOKJiCAxLCBjZW50cmVkIG9uIHRoZSBvcmlnaW4sIGFzIGBbeDAsIHkwLCB4MSwgeTEsIOKApl1gLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdseXBoT3V0bGluZShnbHlwaDogVHJhbnNjcmlwdEdseXBoKTogRmxvYXQzMkFycmF5IHtcbiAgY29uc3QgcG9seSA9IChuOiBudW1iZXIsIHJvdCA9IC1NYXRoLlBJIC8gMiwgciA9IDEpID0+IHtcbiAgICBjb25zdCBvdXQgPSBuZXcgRmxvYXQzMkFycmF5KG4gKiAyKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgY29uc3QgYSA9IHJvdCArIChpICogMiAqIE1hdGguUEkpIC8gbjtcbiAgICAgIG91dFsyICogaV0gPSBNYXRoLmNvcyhhKSAqIHI7XG4gICAgICBvdXRbMiAqIGkgKyAxXSA9IE1hdGguc2luKGEpICogcjtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbiAgfTtcbiAgY29uc3Qgc3RhciA9IChwb2ludHM6IG51bWJlciwgaW5uZXI6IG51bWJlciwgcm90ID0gLU1hdGguUEkgLyAyKSA9PiB7XG4gICAgY29uc3Qgb3V0ID0gbmV3IEZsb2F0MzJBcnJheShwb2ludHMgKiA0KTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBvaW50cyAqIDI7IGkrKykge1xuICAgICAgY29uc3QgYSA9IHJvdCArIChpICogTWF0aC5QSSkgLyBwb2ludHM7XG4gICAgICBjb25zdCByID0gaSAlIDIgPT09IDAgPyAxIDogaW5uZXI7XG4gICAgICBvdXRbMiAqIGldID0gTWF0aC5jb3MoYSkgKiByO1xuICAgICAgb3V0WzIgKiBpICsgMV0gPSBNYXRoLnNpbihhKSAqIHI7XG4gICAgfVxuICAgIHJldHVybiBvdXQ7XG4gIH07XG4gIC8vIEEgcGx1cyBidWlsdCBhcyBhIDEyLWdvbjogYXJtcyBvZiBoYWxmLXdpZHRoIHcuXG4gIGNvbnN0IHBsdXMgPSAodzogbnVtYmVyLCByb3RhdGU6IGJvb2xlYW4pID0+IHtcbiAgICBjb25zdCBwdHMgPSBbXG4gICAgICBbdywgLTFdLCBbdywgLXddLCBbMSwgLXddLCBbMSwgd10sIFt3LCB3XSwgW3csIDFdLFxuICAgICAgWy13LCAxXSwgWy13LCB3XSwgWy0xLCB3XSwgWy0xLCAtd10sIFstdywgLXddLCBbLXcsIC0xXSxcbiAgICBdO1xuICAgIGNvbnN0IG91dCA9IG5ldyBGbG9hdDMyQXJyYXkocHRzLmxlbmd0aCAqIDIpO1xuICAgIGNvbnN0IGMgPSBNYXRoLlNRUlQxXzI7XG4gICAgcHRzLmZvckVhY2goKFt4LCB5XSwgaSkgPT4ge1xuICAgICAgb3V0WzIgKiBpXSA9IHJvdGF0ZSA/ICh4IC0geSkgKiBjIDogeDtcbiAgICAgIG91dFsyICogaSArIDFdID0gcm90YXRlID8gKHggKyB5KSAqIGMgOiB5O1xuICAgIH0pO1xuICAgIHJldHVybiBvdXQ7XG4gIH07XG4gIHN3aXRjaCAoZ2x5cGgpIHtcbiAgICBjYXNlICdjaXJjbGUnOiByZXR1cm4gcG9seSgxMik7XG4gICAgY2FzZSAnc3Rhcic6IHJldHVybiBzdGFyKDUsIDAuNDUpO1xuICAgIGNhc2UgJ3RyaWFuZ2xlJzogcmV0dXJuIHBvbHkoMyk7XG4gICAgY2FzZSAndHJpYW5nbGUtZG93bic6IHJldHVybiBwb2x5KDMsIE1hdGguUEkgLyAyKTtcbiAgICBjYXNlICdzcXVhcmUnOiByZXR1cm4gcG9seSg0LCBNYXRoLlBJIC8gNCwgTWF0aC5TUVJUMiAqIDAuOCk7XG4gICAgY2FzZSAnZGlhbW9uZCc6IHJldHVybiBwb2x5KDQsIC1NYXRoLlBJIC8gMik7XG4gICAgY2FzZSAnaGV4YWdvbic6IHJldHVybiBwb2x5KDYsIDApO1xuICAgIGNhc2UgJ3BlbnRhZ29uJzogcmV0dXJuIHBvbHkoNSk7XG4gICAgY2FzZSAnY3Jvc3MnOiByZXR1cm4gcGx1cygwLjMyLCBmYWxzZSk7XG4gICAgY2FzZSAneCc6IHJldHVybiBwbHVzKDAuMjgsIHRydWUpO1xuICB9XG59XG5cbi8qKiBUaGUgZ2x5cGggYSBnZW5lIGdldHMgYnkgZGVmYXVsdDogYnkgaXRzIHBvc2l0aW9uIGluIHRoZSBzZWxlY3RlZCBsaXN0LiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlZmF1bHRHbHlwaEZvcihzbG90OiBudW1iZXIpOiBUcmFuc2NyaXB0R2x5cGgge1xuICByZXR1cm4gVFJBTlNDUklQVF9HTFlQSFNbc2xvdCAlIFRSQU5TQ1JJUFRfR0xZUEhTLmxlbmd0aF07XG59XG5cbi8qKlxuICogRXhwYW5kIHBvaW50IG1hcmtlcnMgaW50byBnbHlwaCByaW5ncyBmb3IgYSBzaGFwZXMgbGF5ZXI6IGVudHJ5IGBpYCBiZWNvbWVzIGEgY29weSBvZlxuICogYGdseXBoc1tnZW5lW2ldXWAgc2NhbGVkIHRvIGByYWRpdXNbaV1gIGFuZCBjZW50cmVkIG9uIGAoeFtpXSwgeVtpXSlgLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2x5cGhSaW5ncyhcbiAgeDogRmxvYXQzMkFycmF5LCB5OiBGbG9hdDMyQXJyYXksIHJhZGl1czogRmxvYXQzMkFycmF5LCBnbHlwaE9mOiAoaTogbnVtYmVyKSA9PiBGbG9hdDMyQXJyYXksXG4pOiB7IGNvb3JkczogRmxvYXQzMkFycmF5OyBvZmZzZXRzOiBVaW50MzJBcnJheSB9IHtcbiAgY29uc3QgbiA9IHgubGVuZ3RoO1xuICBjb25zdCBvZmZzZXRzID0gbmV3IFVpbnQzMkFycmF5KG4gKyAxKTtcbiAgbGV0IHRvdGFsID0gMDtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICBvZmZzZXRzW2ldID0gdG90YWw7XG4gICAgdG90YWwgKz0gZ2x5cGhPZihpKS5sZW5ndGggLyAyO1xuICB9XG4gIG9mZnNldHNbbl0gPSB0b3RhbDtcbiAgY29uc3QgY29vcmRzID0gbmV3IEZsb2F0MzJBcnJheSh0b3RhbCAqIDIpO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIGNvbnN0IGcgPSBnbHlwaE9mKGkpO1xuICAgIGNvbnN0IHIgPSByYWRpdXNbaV07XG4gICAgbGV0IG8gPSBvZmZzZXRzW2ldICogMjtcbiAgICBmb3IgKGxldCBrID0gMDsgayA8IGcubGVuZ3RoOyBrICs9IDIpIHtcbiAgICAgIGNvb3Jkc1tvKytdID0geFtpXSArIGdba10gKiByO1xuICAgICAgY29vcmRzW28rK10gPSB5W2ldICsgZ1trICsgMV0gKiByO1xuICAgIH1cbiAgfVxuICByZXR1cm4geyBjb29yZHMsIG9mZnNldHMgfTtcbn1cblxuLy8g4pSA4pSAIERpc2NyZXRlIGNvbG91cmluZyB0aHJvdWdoIGEgY29sb3JtYXAg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbi8qKlxuICogQSBzaGFwZXMgbGF5ZXIgY29sb3VycyB0aHJvdWdoIGEgY29sb3JtYXAgTFVULCBub3QgcGVyLXNoYXBlIFJHQkEuIEEgY2F0ZWdvcmljYWxcbiAqIHBhbGV0dGUgYmVjb21lcyBhIHBpZWNld2lzZS1jb25zdGFudCBjb2xvcm1hcDogY2F0ZWdvcnkgYGNgIG9mIGBuYCBvd25zIHRoZSBiYW5kXG4gKiBgW2MvbiwgKGMrMSkvbilgLCBhbmQgYSBzaGFwZSB0YWtlcyB0aGUgdmFsdWUgYXQgaXRzIGJhbmQncyBjZW50cmUsIHNvIHRoZSBMVVQnc1xuICogbGluZWFyIGZpbHRlcmluZyBuZXZlciBibGVuZHMgdHdvIGNhdGVnb3JpZXMuXG4gKlxuICogUmV0dXJucyB0aGUgc3RvcHMgKGxpbmVhciAwLi4xIFJHQikgYW5kIGEgZnVuY3Rpb24gbWFwcGluZyBhIGNhdGVnb3J5IGNvZGUgdG8gdGhlXG4gKiB2YWx1ZSB0byBoYW5kIHRoZSBsYXllci4gYG1pc3NpbmdgIGlzIHRoZSBjb2xvdXIgb2YgdGhlIGV4dHJhIGJhbmQgdXNlZCBmb3IgXCJub1xuICogY2F0ZWdvcnlcIi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRpc2NyZXRlQ29sb3JtYXBTdG9wcyhcbiAgcmdiOiByZWFkb25seSAocmVhZG9ubHkgW251bWJlciwgbnVtYmVyLCBudW1iZXJdKVtdLCBtaXNzaW5nOiByZWFkb25seSBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0sXG4pOiB7IHN0b3BzOiB7IHQ6IG51bWJlcjsgY29sb3I6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSB9W107IHZhbHVlT2Y6IChjb2RlOiBudW1iZXIpID0+IG51bWJlciB9IHtcbiAgY29uc3QgYmFuZHMgPSBbLi4ucmdiLCBtaXNzaW5nXTtcbiAgY29uc3QgbiA9IGJhbmRzLmxlbmd0aDtcbiAgY29uc3Qgc3RvcHM6IHsgdDogbnVtYmVyOyBjb2xvcjogW251bWJlciwgbnVtYmVyLCBudW1iZXJdIH1bXSA9IFtdO1xuICBjb25zdCBlcHMgPSAxZS02O1xuICBiYW5kcy5mb3JFYWNoKChjLCBpKSA9PiB7XG4gICAgY29uc3QgY29sb3I6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSA9IFtjWzBdIC8gMjU1LCBjWzFdIC8gMjU1LCBjWzJdIC8gMjU1XTtcbiAgICBzdG9wcy5wdXNoKHsgdDogaSAvIG4gKyAoaSA9PT0gMCA/IDAgOiBlcHMpLCBjb2xvciB9KTtcbiAgICBzdG9wcy5wdXNoKHsgdDogKGkgKyAxKSAvIG4gLSAoaSA9PT0gbiAtIDEgPyAwIDogZXBzKSwgY29sb3IgfSk7XG4gIH0pO1xuICBjb25zdCBtaXNzaW5nQ29kZSA9IG4gLSAxO1xuICByZXR1cm4ge1xuICAgIHN0b3BzLFxuICAgIHZhbHVlT2Y6IChjb2RlOiBudW1iZXIpID0+ICgoY29kZSA8IDAgfHwgY29kZSA+PSBtaXNzaW5nQ29kZSA/IG1pc3NpbmdDb2RlIDogY29kZSkgKyAwLjUpIC8gbixcbiAgfTtcbn1cblxuLy8g4pSA4pSAIERlbnNpdHkgcmFzdGVyIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4vKipcbiAqIFNlcGFyYWJsZSBHYXVzc2lhbiBibHVyIG9mIGEgcm93LW1ham9yIHJhc3RlciwgYHNpZ21hYCBpbiByYXN0ZXIgY2VsbHMuXG4gKlxuICogQSBwZXItZ2VuZSBjb3VudCByYXN0ZXIgYXQgMTAgwrVtIGlzIG1vc3RseSB6ZXJvcyBhbmQgb25lcyDigJQgZHJhd24gYXMtaXMgaXQgaXMgc3BlY2tsZSxcbiAqIG5vdCBhIGRlbnNpdHkuIEEgz4Mgb2Ygb25lIHRvIHR3byBjZWxscyAoMTDigJMyMCDCtW0sIGFib3V0IGEgY2VsbCBkaWFtZXRlcikgdHVybnMgaXQgaW50b1xuICogYSBmaWVsZCB0aGF0IHJlYWRzIGFzIHRlcnJpdG9yeSB3aGlsZSBrZWVwaW5nIHN0cnVjdHVyZXMgYSBmZXcgY2VsbHMgd2lkZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNtb290aFJhc3Rlcih2YWx1ZXM6IEZsb2F0MzJBcnJheSwgcm93czogbnVtYmVyLCBjb2xzOiBudW1iZXIsIHNpZ21hOiBudW1iZXIpOiBGbG9hdDMyQXJyYXkge1xuICBpZiAoIShzaWdtYSA+IDApKSByZXR1cm4gdmFsdWVzLnNsaWNlKCk7XG4gIGNvbnN0IHIgPSBNYXRoLm1heCgxLCBNYXRoLmNlaWwoc2lnbWEgKiAzKSk7XG4gIGNvbnN0IGtlcm5lbCA9IG5ldyBGbG9hdDMyQXJyYXkoMiAqIHIgKyAxKTtcbiAgbGV0IHN1bSA9IDA7XG4gIGZvciAobGV0IGkgPSAtcjsgaSA8PSByOyBpKyspIHN1bSArPSAoa2VybmVsW2kgKyByXSA9IE1hdGguZXhwKC0oaSAqIGkpIC8gKDIgKiBzaWdtYSAqIHNpZ21hKSkpO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IGtlcm5lbC5sZW5ndGg7IGkrKykga2VybmVsW2ldIC89IHN1bTtcbiAgY29uc3QgdG1wID0gbmV3IEZsb2F0MzJBcnJheSh2YWx1ZXMubGVuZ3RoKTtcbiAgY29uc3Qgb3V0ID0gbmV3IEZsb2F0MzJBcnJheSh2YWx1ZXMubGVuZ3RoKTtcbiAgZm9yIChsZXQgeSA9IDA7IHkgPCByb3dzOyB5KyspIHtcbiAgICBjb25zdCByb3cgPSB5ICogY29scztcbiAgICBmb3IgKGxldCB4ID0gMDsgeCA8IGNvbHM7IHgrKykge1xuICAgICAgbGV0IGFjYyA9IDA7XG4gICAgICBmb3IgKGxldCBrID0gLXI7IGsgPD0gcjsgaysrKSB7XG4gICAgICAgIGNvbnN0IHh4ID0geCArIGs7XG4gICAgICAgIGlmICh4eCA+PSAwICYmIHh4IDwgY29scykgYWNjICs9IHZhbHVlc1tyb3cgKyB4eF0gKiBrZXJuZWxbayArIHJdO1xuICAgICAgfVxuICAgICAgdG1wW3JvdyArIHhdID0gYWNjO1xuICAgIH1cbiAgfVxuICBmb3IgKGxldCB5ID0gMDsgeSA8IHJvd3M7IHkrKykge1xuICAgIGZvciAobGV0IHggPSAwOyB4IDwgY29sczsgeCsrKSB7XG4gICAgICBsZXQgYWNjID0gMDtcbiAgICAgIGZvciAobGV0IGsgPSAtcjsgayA8PSByOyBrKyspIHtcbiAgICAgICAgY29uc3QgeXkgPSB5ICsgaztcbiAgICAgICAgaWYgKHl5ID49IDAgJiYgeXkgPCByb3dzKSBhY2MgKz0gdG1wW3l5ICogY29scyArIHhdICoga2VybmVsW2sgKyByXTtcbiAgICAgIH1cbiAgICAgIG91dFt5ICogY29scyArIHhdID0gYWNjO1xuICAgIH1cbiAgfVxuICByZXR1cm4gb3V0O1xufVxuXG4vKipcbiAqIENvbG91ciBhIGRlbnNpdHkgcmFzdGVyIGFzIFJHQkEgYnl0ZXM6IGxvZy1zY2FsZWQsIHdpbmRvd2VkIGF0IGEgaGlnaCBwZXJjZW50aWxlIG9mIHRoZVxuICogbm9uLXplcm8gdmFsdWVzLCBhbmQgZmFkZWQgaW4gZnJvbSB0cmFuc3BhcmVudCBzbyBlbXB0eSB0aXNzdWUgc2hvd3Mgd2hhdCBpcyB1bmRlciBpdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbG9yRGVuc2l0eShcbiAgdmFsdWVzOiBGbG9hdDMyQXJyYXksIGx1dDogcmVhZG9ubHkgKHJlYWRvbmx5IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSlbXSwgb3BhY2l0eTogbnVtYmVyLFxuICB7IGxvZyA9IHRydWUsIHBlcmNlbnRpbGUgPSAwLjk5NSB9ID0ge30sXG4pOiBVaW50OEFycmF5IHtcbiAgY29uc3QgbiA9IHZhbHVlcy5sZW5ndGg7XG4gIGNvbnN0IHQgPSBsb2cgPyB2YWx1ZXMubWFwKCh2KSA9PiBNYXRoLmxvZzFwKE1hdGgubWF4KDAsIHYpKSkgOiB2YWx1ZXM7XG4gIGNvbnN0IHBvc2l0aXZlOiBudW1iZXJbXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG47IGkrKykgaWYgKHRbaV0gPiAwKSBwb3NpdGl2ZS5wdXNoKHRbaV0pO1xuICBwb3NpdGl2ZS5zb3J0KChhLCBiKSA9PiBhIC0gYik7XG4gIGNvbnN0IGF0ID0gTWF0aC5taW4ocG9zaXRpdmUubGVuZ3RoIC0gMSwgTWF0aC5mbG9vcihwZXJjZW50aWxlICogcG9zaXRpdmUubGVuZ3RoKSk7XG4gIGNvbnN0IGhpID0gcG9zaXRpdmUubGVuZ3RoID8gcG9zaXRpdmVbYXRdIDogMTtcbiAgY29uc3QgcmdiYSA9IG5ldyBVaW50OEFycmF5KG4gKiA0KTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICBjb25zdCBmID0gTWF0aC5taW4oMSwgdFtpXSAvIChoaSB8fCAxKSk7XG4gICAgaWYgKGYgPCAwLjAyKSBjb250aW51ZTtcbiAgICBjb25zdCBjID0gbHV0W01hdGgubWluKGx1dC5sZW5ndGggLSAxLCBNYXRoLnJvdW5kKGYgKiAobHV0Lmxlbmd0aCAtIDEpKSldO1xuICAgIHJnYmFbNCAqIGldID0gY1swXTtcbiAgICByZ2JhWzQgKiBpICsgMV0gPSBjWzFdO1xuICAgIHJnYmFbNCAqIGkgKyAyXSA9IGNbMl07XG4gICAgcmdiYVs0ICogaSArIDNdID0gTWF0aC5yb3VuZCgyNTUgKiBvcGFjaXR5ICogTWF0aC5wb3coZiwgMC42KSk7XG4gIH1cbiAgcmV0dXJuIHJnYmE7XG59XG5cbi8vIOKUgOKUgCBBbGwtZ2VuZSB0cmFuc2NyaXB0czogZ3JvdXBpbmcgdW5kZXIgYSBtYXJrZXIgYnVkZ2V0IOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4vKiogU21hbGxlc3Qgb24tc2NyZWVuIHNwYWNpbmcgYmV0d2VlbiBncm91cHMsIGluIHB4IOKAlCBiZWxvdyBpdCBncm91cHMgcmVhZCBhcyBub2lzZS4gKi9cbmV4cG9ydCBjb25zdCBHUk9VUF9NSU5fU1BBQ0lOR19QWCA9IDE0O1xuXG4vKiogQXJlYSBvZiBgcmVjdGAgaW5zaWRlIGBib3VuZHNgICh0aGUgd2hvbGUgcmVjdCB3aGVuIHRoZXJlIGFyZSBub25lKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiB2aXNpYmxlQXJlYShyZWN0OiBEYXRhUmVjdCwgYm91bmRzPzogU3BhdGlhbEJvdW5kcyB8IG51bGwpOiBudW1iZXIge1xuICBjb25zdCB4MCA9IGJvdW5kcyA/IE1hdGgubWF4KHJlY3QueDAsIGJvdW5kc1swXSkgOiByZWN0LngwO1xuICBjb25zdCB5MCA9IGJvdW5kcyA/IE1hdGgubWF4KHJlY3QueTAsIGJvdW5kc1sxXSkgOiByZWN0LnkwO1xuICBjb25zdCB4MSA9IGJvdW5kcyA/IE1hdGgubWluKHJlY3QueDEsIGJvdW5kc1syXSkgOiByZWN0LngxO1xuICBjb25zdCB5MSA9IGJvdW5kcyA/IE1hdGgubWluKHJlY3QueTEsIGJvdW5kc1szXSkgOiByZWN0LnkxO1xuICByZXR1cm4gTWF0aC5tYXgoMCwgeDEgLSB4MCkgKiBNYXRoLm1heCgwLCB5MSAtIHkwKTtcbn1cblxuZXhwb3J0IHR5cGUgQWxsR2VuZXNQbGFuID0geyBraW5kOiAnaW5kaXZpZHVhbCcgfSB8IHsga2luZDogJ2JpbnMnOyBsZXZlbDogbnVtYmVyIH0gfCB7IGtpbmQ6ICdub25lJyB9O1xuXG4vKipcbiAqIEhvdyB0byBkcmF3IGV2ZXJ5IHRyYW5zY3JpcHQgaW4gdmlldyB3aXRob3V0IGV4Y2VlZGluZyBgYnVkZ2V0YCBtYXJrZXJzLlxuICpcbiAqIC0gVGhlIHRyYW5zY3JpcHRzIHRoZW1zZWx2ZXMsIG9uY2UgdGhlIGVzdGltYXRlZCBjb3VudCBpbiB2aWV3IGZpdHMgdGhlIGJ1ZGdldC5cbiAqIC0gT3RoZXJ3aXNlIHRoZSBmaW5lc3QgcHlyYW1pZCBsZXZlbCB3aG9zZSBiaW5zIGFyZSBhdCBsZWFzdCBgbWluU3BhY2luZ1B4YCBhcGFydCBvblxuICogICBzY3JlZW4gYW5kIG51bWJlciBubyBtb3JlIHRoYW4gdGhlIGJ1ZGdldCDigJQgZ3JvdXBzIGJpZyBlbm91Z2ggdG8gcmVhZCwgZmV3IGVub3VnaFxuICogICB0byBkcmF3LlxuICpcbiAqIFRoZSBjb3VudCBpbiB2aWV3IGlzIGVzdGltYXRlZCBmcm9tIHRoZSBhdmVyYWdlIGRlbnNpdHksIHdoaWNoIG92ZXItIG9yIHVuZGVyLXNob290c1xuICogbG9jYWxseTsgdGhlIHJlbmRlcmVyIHN0aWxsIGNhcHMgd2hhdCBpdCBkcmF3cywgc28gYW4gZXN0aW1hdGUgaXMgZW5vdWdoIHRvIGNob29zZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGFsbEdlbmVzUGxhbihvOiB7XG4gIHJlY3Q6IERhdGFSZWN0OyBib3VuZHM6IFNwYXRpYWxCb3VuZHM7IHRvdGFsOiBudW1iZXI7IHB4UGVyVW5pdDogbnVtYmVyO1xuICBsZXZlbHM6IHJlYWRvbmx5IHsgYmluU2l6ZTogbnVtYmVyIH1bXTsgYnVkZ2V0OiBudW1iZXI7IGNhbkluZGl2aWR1YWw6IGJvb2xlYW47XG4gIG1pblNwYWNpbmdQeD86IG51bWJlcjtcbn0pOiBBbGxHZW5lc1BsYW4ge1xuICBjb25zdCBhcmVhID0gdmlzaWJsZUFyZWEoby5yZWN0LCBvLmJvdW5kcyk7XG4gIGlmICghKGFyZWEgPiAwKSkgcmV0dXJuIHsga2luZDogJ25vbmUnIH07XG4gIGNvbnN0IGIgPSBvLmJvdW5kcztcbiAgY29uc3QgZGVuc2l0eSA9IG8udG90YWwgLyBNYXRoLm1heCgxLCAoYlsyXSAtIGJbMF0pICogKGJbM10gLSBiWzFdKSk7XG4gIGlmIChvLmNhbkluZGl2aWR1YWwgJiYgZGVuc2l0eSAqIGFyZWEgPD0gby5idWRnZXQpIHJldHVybiB7IGtpbmQ6ICdpbmRpdmlkdWFsJyB9O1xuICBpZiAoIW8ubGV2ZWxzLmxlbmd0aCkgcmV0dXJuIHsga2luZDogJ25vbmUnIH07XG4gIGNvbnN0IHNwYWNpbmcgPSBvLm1pblNwYWNpbmdQeCA/PyBHUk9VUF9NSU5fU1BBQ0lOR19QWDtcbiAgZm9yIChsZXQgbCA9IDA7IGwgPCBvLmxldmVscy5sZW5ndGg7IGwrKykge1xuICAgIGNvbnN0IGJpbiA9IG8ubGV2ZWxzW2xdLmJpblNpemU7XG4gICAgLy8gVGlzc3VlIHJhcmVseSBmaWxscyB0aGUgdmlldzsgMC43IG9mIHRoZSBiaW5zIG9jY3VwaWVkIGlzIGEgZmFpciBndWVzcy5cbiAgICBpZiAoYmluICogby5weFBlclVuaXQgPj0gc3BhY2luZyAmJiAoYXJlYSAvIChiaW4gKiBiaW4pKSAqIDAuNyA8PSBvLmJ1ZGdldCkge1xuICAgICAgcmV0dXJuIHsga2luZDogJ2JpbnMnLCBsZXZlbDogbCB9O1xuICAgIH1cbiAgfVxuICByZXR1cm4geyBraW5kOiAnYmlucycsIGxldmVsOiBvLmxldmVscy5sZW5ndGggLSAxIH07XG59XG5cbi8qKlxuICogRGlhbWV0ZXIgaW4gcHggb2YgYSBncm91cCBvZiBgY291bnRgIHRyYW5zY3JpcHRzIGluIGEgYmluIGBiaW5QeGAgd2lkZSwgd2hlcmVcbiAqIGByZWZDb3VudGAgaXMgYSB0eXBpY2FsIGJ1c3kgYmluIGluIHZpZXcgKGl0cyA5NXRoIHBlcmNlbnRpbGUpLlxuICpcbiAqIEFyZWEgZ3Jvd3Mgd2l0aCB0aGUgY291bnQg4oCUIGEgYmluIHdpdGggYSBxdWFydGVyIG9mIHRoZSB0cmFuc2NyaXB0cyBnZXRzIGhhbGYgdGhlXG4gKiBkaWFtZXRlciDigJQgYmV0d2VlbiBhIHRoaXJkIG9mIHRoZSBiaW4gKHNvIGEgc3BhcnNlIGJpbiBpcyBzdGlsbCB2aXNpYmxlKSBhbmQgYSBsaXR0bGVcbiAqIG92ZXIgdGhlIGZ1bGwgYmluIChzbyBkZW5zZSBuZWlnaGJvdXJzIGp1c3QgdG91Y2ggcmF0aGVyIHRoYW4gcGlsZSB1cCkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBncm91cGVkTWFya2VyUHgoY291bnQ6IG51bWJlciwgcmVmQ291bnQ6IG51bWJlciwgYmluUHg6IG51bWJlciwgc2NhbGUgPSAxKTogbnVtYmVyIHtcbiAgY29uc3QgZiA9IE1hdGguc3FydChNYXRoLm1pbigxLCBjb3VudCAvIE1hdGgubWF4KDEsIHJlZkNvdW50KSkpO1xuICBjb25zdCBkID0gYmluUHggKiAoMC4zNSArIDAuNzUgKiBmKSAqIHNjYWxlO1xuICByZXR1cm4gTWF0aC5tYXgoVFJBTlNDUklQVF9NSU5fUFggKiBzY2FsZSwgTWF0aC5taW4oZCwgYmluUHggKiAxLjIgKiBNYXRoLm1heChzY2FsZSwgMSkpKTtcbn1cblxuLyoqIFRoZSBgcGAgcXVhbnRpbGUgKDAuLjEpIG9mIGEgY291bnQgdmVjdG9yIOKAlCBhIHNhbXBsZSBvZiBpdCBmb3IgbGFyZ2UgdmVjdG9ycy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBxdWFudGlsZU9mKHZhbHVlczogQXJyYXlMaWtlPG51bWJlcj4sIHA6IG51bWJlcik6IG51bWJlciB7XG4gIGNvbnN0IG4gPSB2YWx1ZXMubGVuZ3RoO1xuICBpZiAoIW4pIHJldHVybiAwO1xuICBjb25zdCBzdGVwID0gTWF0aC5tYXgoMSwgTWF0aC5mbG9vcihuIC8gNDA5NikpO1xuICBjb25zdCBzYW1wbGU6IG51bWJlcltdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSArPSBzdGVwKSBzYW1wbGUucHVzaCh2YWx1ZXNbaV0pO1xuICBzYW1wbGUuc29ydCgoYSwgYikgPT4gYSAtIGIpO1xuICByZXR1cm4gc2FtcGxlW01hdGgubWluKHNhbXBsZS5sZW5ndGggLSAxLCBNYXRoLmZsb29yKHAgKiBzYW1wbGUubGVuZ3RoKSldO1xufVxuXG4vKioge0BsaW5rIHRpbGVzSW5SZWN0fSBmb3IgYSBncmlkIHdob3NlIHRpbGUgKDAsIDApIHN0YXJ0cyBhdCBgb3JpZ2luYC4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0aWxlc0luUmVjdEZyb20oXG4gIG9yaWdpbjogcmVhZG9ubHkgW251bWJlciwgbnVtYmVyXSwgcmVjdDogRGF0YVJlY3QsIGxldmVsOiBudW1iZXIsXG4gIGxldmVsczogcmVhZG9ubHkgU3BhdGlhbFRpbGVMZXZlbFtdLCBib3VuZHM/OiBTcGF0aWFsQm91bmRzIHwgbnVsbCwgbGltaXQgPSBJbmZpbml0eSxcbik6IFRpbGVLZXlbXSB7XG4gIGNvbnN0IFtveCwgb3ldID0gb3JpZ2luO1xuICBjb25zdCBzaGlmdGVkID0geyB4MDogcmVjdC54MCAtIG94LCB5MDogcmVjdC55MCAtIG95LCB4MTogcmVjdC54MSAtIG94LCB5MTogcmVjdC55MSAtIG95IH07XG4gIGNvbnN0IGI6IFNwYXRpYWxCb3VuZHMgfCBudWxsID0gYm91bmRzID8gW2JvdW5kc1swXSAtIG94LCBib3VuZHNbMV0gLSBveSwgYm91bmRzWzJdIC0gb3gsIGJvdW5kc1szXSAtIG95XSA6IG51bGw7XG4gIHJldHVybiB0aWxlc0luUmVjdChzaGlmdGVkLCBsZXZlbCwgbGV2ZWxzLCBiLCBsaW1pdCk7XG59XG5cbi8qKiBBIGRlbnNpdHkgd2luZG93IGZyb20gdGhlIG5vbi1lbXB0eSBiaW5zOiAxc3QgdG8gOTl0aCBwZXJjZW50aWxlLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlbnNpdHlBdXRvUmFuZ2UodmFsdWVzOiBBcnJheUxpa2U8bnVtYmVyPik6IFtudW1iZXIsIG51bWJlcl0ge1xuICBjb25zdCBwb3NpdGl2ZTogbnVtYmVyW10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx1ZXMubGVuZ3RoOyBpKyspIGlmICh2YWx1ZXNbaV0gPiAwKSBwb3NpdGl2ZS5wdXNoKHZhbHVlc1tpXSk7XG4gIGlmICghcG9zaXRpdmUubGVuZ3RoKSByZXR1cm4gWzAsIDFdO1xuICBwb3NpdGl2ZS5zb3J0KChhLCBiKSA9PiBhIC0gYik7XG4gIGNvbnN0IGF0ID0gKHA6IG51bWJlcikgPT4gcG9zaXRpdmVbTWF0aC5taW4ocG9zaXRpdmUubGVuZ3RoIC0gMSwgTWF0aC5mbG9vcihwICogcG9zaXRpdmUubGVuZ3RoKSldO1xuICBjb25zdCBsbyA9IGF0KDAuMDEpO1xuICBjb25zdCBoaSA9IGF0KDAuOTkpO1xuICByZXR1cm4gaGkgPiBsbyA/IFtsbywgaGldIDogWzAsIGhpIHx8IDFdO1xufVxuXG4vKipcbiAqIENvbG91ciBkZW5zaXR5IGJpbnMgdGhyb3VnaCBgbHV0YCBvdmVyIHRoZSB3aW5kb3cgYFtsbywgaGldYCDigJQgWGVuaXVtIEV4cGxvcmVyJ3NcbiAqIFwic2NhbGUgdGhyZXNob2xkXCIuIEJpbnMgYXQgb3IgYmVsb3cgYGxvYCBhcmUgdHJhbnNwYXJlbnQsIHNvIGVtcHR5IHRpc3N1ZSBzaG93cyB0aGVcbiAqIGltYWdlIHVuZGVyIGl0OyBiaW5zIGF0IG9yIGFib3ZlIGBoaWAgc2F0dXJhdGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjb2xvckRlbnNpdHlXaW5kb3coXG4gIHZhbHVlczogQXJyYXlMaWtlPG51bWJlcj4sIGx1dDogcmVhZG9ubHkgKHJlYWRvbmx5IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSlbXSxcbiAgb3BhY2l0eTogbnVtYmVyLCBsbzogbnVtYmVyLCBoaTogbnVtYmVyLFxuKTogVWludDhBcnJheSB7XG4gIGNvbnN0IG4gPSB2YWx1ZXMubGVuZ3RoO1xuICBjb25zdCByZ2JhID0gbmV3IFVpbnQ4QXJyYXkobiAqIDQpO1xuICBjb25zdCBzcGFuID0gaGkgPiBsbyA/IGhpIC0gbG8gOiAxO1xuICBjb25zdCBhID0gTWF0aC5yb3VuZCgyNTUgKiBvcGFjaXR5KTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyBpKyspIHtcbiAgICBjb25zdCB2ID0gdmFsdWVzW2ldO1xuICAgIGlmICghKHYgPiBsbykpIGNvbnRpbnVlO1xuICAgIGNvbnN0IGYgPSBNYXRoLm1pbigxLCAodiAtIGxvKSAvIHNwYW4pO1xuICAgIGNvbnN0IGMgPSBsdXRbTWF0aC5taW4obHV0Lmxlbmd0aCAtIDEsIE1hdGgucm91bmQoZiAqIChsdXQubGVuZ3RoIC0gMSkpKV07XG4gICAgcmdiYVs0ICogaV0gPSBjWzBdO1xuICAgIHJnYmFbNCAqIGkgKyAxXSA9IGNbMV07XG4gICAgcmdiYVs0ICogaSArIDJdID0gY1syXTtcbiAgICByZ2JhWzQgKiBpICsgM10gPSBhO1xuICB9XG4gIHJldHVybiByZ2JhO1xufVxuXG4vKipcbiAqIEluZmVybm8gKG1hdHBsb3RsaWIpLCBhcyBhbiBpbmxpbmUgYFtzdG9wLCBjb2xvdXJdYCBzY2FsZTogdGhlIGRlbnNpdHkgbWFwJ3MgZGVmYXVsdCxcbiAqIGFzIGluIFhlbml1bSBFeHBsb3Jlci4gSW5saW5lIGJlY2F1c2UgdGhlIGNvbG9ybWFwIHRyZWUncyBgSU5GRVJOT19MVVRgIGtleSBpcyByZXNvbHZlZFxuICogYXQgcnVudGltZSBieSB0aGUgc3RvcmUsIHdoaWNoIHRoZSByZW5kZXJlciBkb2VzIG5vdCBzZWUuXG4gKi9cbmV4cG9ydCBjb25zdCBJTkZFUk5PX1NDQUxFOiBbbnVtYmVyLCBzdHJpbmddW10gPSBbXG4gIFswLCAnIzAwMDAwNCddLCBbMC4xMjUsICcjMWIwYzQxJ10sIFswLjI1LCAnIzRhMGM2YiddLCBbMC4zNzUsICcjNzgxYzZkJ10sIFswLjUsICcjYTUyYzYwJ10sXG4gIFswLjYyNSwgJyNjZjQ0NDYnXSwgWzAuNzUsICcjZWQ2OTI1J10sIFswLjg3NSwgJyNmYjliMDYnXSwgWzEsICcjZmNmZmE0J10sXG5dO1xuIl19