@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,506 @@
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
+ /** Smallest and largest transcript marker, in canvas pixels. */
170
+ export const TRANSCRIPT_MIN_PX = 4;
171
+ export const TRANSCRIPT_MAX_PX = 32;
172
+ /**
173
+ * Physical diameter a single transcript is drawn at, in µm — clearly larger than the
174
+ * imaged spot (~0.3 µm) so it stays legible, and small enough that neighbouring
175
+ * molecules inside one cell stay apart.
176
+ */
177
+ export const TRANSCRIPT_PHYSICAL_UM = 1.2;
178
+ /**
179
+ * Marker diameter in canvas pixels for an entry standing for `weight` transcripts.
180
+ *
181
+ * The convention spatial viewers share (deck.gl's `radiusMinPixels`/`radiusMaxPixels`,
182
+ * Xenium Explorer's transcript size): a PHYSICAL size, clamped to a screen-pixel range.
183
+ * Zoomed out, markers sit at the minimum and never vanish; zoomed in, they grow with the
184
+ * tissue instead of shrinking to specks next to cells hundreds of pixels wide. A fixed
185
+ * screen size does the opposite at high zoom, which is what made transcripts disappear
186
+ * at pixel-level zoom.
187
+ *
188
+ * Aggregates grow with the cube root of their count: area ∝ count would let one dense
189
+ * aggregate swallow its neighbours, the cube root keeps a 1000-transcript cluster clearly
190
+ * larger than a 10-transcript one without covering the tile.
191
+ *
192
+ * `pxPerMicron` is omitted for data with no known physical unit; the marker is then
193
+ * screen-sized only.
194
+ */
195
+ export function transcriptMarkerPx(weight, scale = 1, pxPerMicron) {
196
+ const counted = TRANSCRIPT_MIN_PX * Math.cbrt(Math.max(1, weight));
197
+ const physical = pxPerMicron ? TRANSCRIPT_PHYSICAL_UM * pxPerMicron : 0;
198
+ const px = Math.max(counted, physical) * scale;
199
+ return Math.min(TRANSCRIPT_MAX_PX * Math.max(scale, 1), Math.max(TRANSCRIPT_MIN_PX * scale, px));
200
+ }
201
+ // ── Glyphs ────────────────────────────────────────────────────────────────────────────
202
+ /** Marker shapes for the transcript "icon" mode. All star-convex, so a fan fills them. */
203
+ export const TRANSCRIPT_GLYPHS = [
204
+ 'circle', 'star', 'triangle', 'square', 'diamond', 'cross', 'hexagon', 'triangle-down',
205
+ 'pentagon', 'x',
206
+ ];
207
+ // The view state names glyphs without importing this module; keep the two in step.
208
+ const _glyphNamesMatch = true;
209
+ void _glyphNamesMatch;
210
+ /** Unit outline of a glyph, radius ≈ 1, centred on the origin, as `[x0, y0, x1, y1, …]`. */
211
+ export function glyphOutline(glyph) {
212
+ const poly = (n, rot = -Math.PI / 2, r = 1) => {
213
+ const out = new Float32Array(n * 2);
214
+ for (let i = 0; i < n; i++) {
215
+ const a = rot + (i * 2 * Math.PI) / n;
216
+ out[2 * i] = Math.cos(a) * r;
217
+ out[2 * i + 1] = Math.sin(a) * r;
218
+ }
219
+ return out;
220
+ };
221
+ const star = (points, inner, rot = -Math.PI / 2) => {
222
+ const out = new Float32Array(points * 4);
223
+ for (let i = 0; i < points * 2; i++) {
224
+ const a = rot + (i * Math.PI) / points;
225
+ const r = i % 2 === 0 ? 1 : inner;
226
+ out[2 * i] = Math.cos(a) * r;
227
+ out[2 * i + 1] = Math.sin(a) * r;
228
+ }
229
+ return out;
230
+ };
231
+ // A plus built as a 12-gon: arms of half-width w.
232
+ const plus = (w, rotate) => {
233
+ const pts = [
234
+ [w, -1], [w, -w], [1, -w], [1, w], [w, w], [w, 1],
235
+ [-w, 1], [-w, w], [-1, w], [-1, -w], [-w, -w], [-w, -1],
236
+ ];
237
+ const out = new Float32Array(pts.length * 2);
238
+ const c = Math.SQRT1_2;
239
+ pts.forEach(([x, y], i) => {
240
+ out[2 * i] = rotate ? (x - y) * c : x;
241
+ out[2 * i + 1] = rotate ? (x + y) * c : y;
242
+ });
243
+ return out;
244
+ };
245
+ switch (glyph) {
246
+ case 'circle': return poly(12);
247
+ case 'star': return star(5, 0.45);
248
+ case 'triangle': return poly(3);
249
+ case 'triangle-down': return poly(3, Math.PI / 2);
250
+ case 'square': return poly(4, Math.PI / 4, Math.SQRT2 * 0.8);
251
+ case 'diamond': return poly(4, -Math.PI / 2);
252
+ case 'hexagon': return poly(6, 0);
253
+ case 'pentagon': return poly(5);
254
+ case 'cross': return plus(0.32, false);
255
+ case 'x': return plus(0.28, true);
256
+ }
257
+ }
258
+ /** The glyph a gene gets by default: by its position in the selected list. */
259
+ export function defaultGlyphFor(slot) {
260
+ return TRANSCRIPT_GLYPHS[slot % TRANSCRIPT_GLYPHS.length];
261
+ }
262
+ /**
263
+ * Expand point markers into glyph rings for a shapes layer: entry `i` becomes a copy of
264
+ * `glyphs[gene[i]]` scaled to `radius[i]` and centred on `(x[i], y[i])`.
265
+ */
266
+ export function glyphRings(x, y, radius, glyphOf) {
267
+ const n = x.length;
268
+ const offsets = new Uint32Array(n + 1);
269
+ let total = 0;
270
+ for (let i = 0; i < n; i++) {
271
+ offsets[i] = total;
272
+ total += glyphOf(i).length / 2;
273
+ }
274
+ offsets[n] = total;
275
+ const coords = new Float32Array(total * 2);
276
+ for (let i = 0; i < n; i++) {
277
+ const g = glyphOf(i);
278
+ const r = radius[i];
279
+ let o = offsets[i] * 2;
280
+ for (let k = 0; k < g.length; k += 2) {
281
+ coords[o++] = x[i] + g[k] * r;
282
+ coords[o++] = y[i] + g[k + 1] * r;
283
+ }
284
+ }
285
+ return { coords, offsets };
286
+ }
287
+ // ── Discrete colouring through a colormap ─────────────────────────────────────────────
288
+ /**
289
+ * A shapes layer colours through a colormap LUT, not per-shape RGBA. A categorical
290
+ * palette becomes a piecewise-constant colormap: category `c` of `n` owns the band
291
+ * `[c/n, (c+1)/n)`, and a shape takes the value at its band's centre, so the LUT's
292
+ * linear filtering never blends two categories.
293
+ *
294
+ * Returns the stops (linear 0..1 RGB) and a function mapping a category code to the
295
+ * value to hand the layer. `missing` is the colour of the extra band used for "no
296
+ * category".
297
+ */
298
+ export function discreteColormapStops(rgb, missing) {
299
+ const bands = [...rgb, missing];
300
+ const n = bands.length;
301
+ const stops = [];
302
+ const eps = 1e-6;
303
+ bands.forEach((c, i) => {
304
+ const color = [c[0] / 255, c[1] / 255, c[2] / 255];
305
+ stops.push({ t: i / n + (i === 0 ? 0 : eps), color });
306
+ stops.push({ t: (i + 1) / n - (i === n - 1 ? 0 : eps), color });
307
+ });
308
+ const missingCode = n - 1;
309
+ return {
310
+ stops,
311
+ valueOf: (code) => ((code < 0 || code >= missingCode ? missingCode : code) + 0.5) / n,
312
+ };
313
+ }
314
+ // ── Density raster ────────────────────────────────────────────────────────────────────
315
+ /**
316
+ * Separable Gaussian blur of a row-major raster, `sigma` in raster cells.
317
+ *
318
+ * A per-gene count raster at 10 µm is mostly zeros and ones — drawn as-is it is speckle,
319
+ * not a density. A σ of one to two cells (10–20 µm, about a cell diameter) turns it into
320
+ * a field that reads as territory while keeping structures a few cells wide.
321
+ */
322
+ export function smoothRaster(values, rows, cols, sigma) {
323
+ if (!(sigma > 0))
324
+ return values.slice();
325
+ const r = Math.max(1, Math.ceil(sigma * 3));
326
+ const kernel = new Float32Array(2 * r + 1);
327
+ let sum = 0;
328
+ for (let i = -r; i <= r; i++)
329
+ sum += (kernel[i + r] = Math.exp(-(i * i) / (2 * sigma * sigma)));
330
+ for (let i = 0; i < kernel.length; i++)
331
+ kernel[i] /= sum;
332
+ const tmp = new Float32Array(values.length);
333
+ const out = new Float32Array(values.length);
334
+ for (let y = 0; y < rows; y++) {
335
+ const row = y * cols;
336
+ for (let x = 0; x < cols; x++) {
337
+ let acc = 0;
338
+ for (let k = -r; k <= r; k++) {
339
+ const xx = x + k;
340
+ if (xx >= 0 && xx < cols)
341
+ acc += values[row + xx] * kernel[k + r];
342
+ }
343
+ tmp[row + x] = acc;
344
+ }
345
+ }
346
+ for (let y = 0; y < rows; y++) {
347
+ for (let x = 0; x < cols; x++) {
348
+ let acc = 0;
349
+ for (let k = -r; k <= r; k++) {
350
+ const yy = y + k;
351
+ if (yy >= 0 && yy < rows)
352
+ acc += tmp[yy * cols + x] * kernel[k + r];
353
+ }
354
+ out[y * cols + x] = acc;
355
+ }
356
+ }
357
+ return out;
358
+ }
359
+ /**
360
+ * Colour a density raster as RGBA bytes: log-scaled, windowed at a high percentile of the
361
+ * non-zero values, and faded in from transparent so empty tissue shows what is under it.
362
+ */
363
+ export function colorDensity(values, lut, opacity, { log = true, percentile = 0.995 } = {}) {
364
+ const n = values.length;
365
+ const t = log ? values.map((v) => Math.log1p(Math.max(0, v))) : values;
366
+ const positive = [];
367
+ for (let i = 0; i < n; i++)
368
+ if (t[i] > 0)
369
+ positive.push(t[i]);
370
+ positive.sort((a, b) => a - b);
371
+ const at = Math.min(positive.length - 1, Math.floor(percentile * positive.length));
372
+ const hi = positive.length ? positive[at] : 1;
373
+ const rgba = new Uint8Array(n * 4);
374
+ for (let i = 0; i < n; i++) {
375
+ const f = Math.min(1, t[i] / (hi || 1));
376
+ if (f < 0.02)
377
+ continue;
378
+ const c = lut[Math.min(lut.length - 1, Math.round(f * (lut.length - 1)))];
379
+ rgba[4 * i] = c[0];
380
+ rgba[4 * i + 1] = c[1];
381
+ rgba[4 * i + 2] = c[2];
382
+ rgba[4 * i + 3] = Math.round(255 * opacity * Math.pow(f, 0.6));
383
+ }
384
+ return rgba;
385
+ }
386
+ // ── All-gene transcripts: grouping under a marker budget ─────────────────────────────
387
+ /** Smallest on-screen spacing between groups, in px — below it groups read as noise. */
388
+ export const GROUP_MIN_SPACING_PX = 14;
389
+ /** Area of `rect` inside `bounds` (the whole rect when there are none). */
390
+ export function visibleArea(rect, bounds) {
391
+ const x0 = bounds ? Math.max(rect.x0, bounds[0]) : rect.x0;
392
+ const y0 = bounds ? Math.max(rect.y0, bounds[1]) : rect.y0;
393
+ const x1 = bounds ? Math.min(rect.x1, bounds[2]) : rect.x1;
394
+ const y1 = bounds ? Math.min(rect.y1, bounds[3]) : rect.y1;
395
+ return Math.max(0, x1 - x0) * Math.max(0, y1 - y0);
396
+ }
397
+ /**
398
+ * How to draw every transcript in view without exceeding `budget` markers.
399
+ *
400
+ * - The transcripts themselves, once the estimated count in view fits the budget.
401
+ * - Otherwise the finest pyramid level whose bins are at least `minSpacingPx` apart on
402
+ * screen and number no more than the budget — groups big enough to read, few enough
403
+ * to draw.
404
+ *
405
+ * The count in view is estimated from the average density, which over- or under-shoots
406
+ * locally; the renderer still caps what it draws, so an estimate is enough to choose.
407
+ */
408
+ export function allGenesPlan(o) {
409
+ const area = visibleArea(o.rect, o.bounds);
410
+ if (!(area > 0))
411
+ return { kind: 'none' };
412
+ const b = o.bounds;
413
+ const density = o.total / Math.max(1, (b[2] - b[0]) * (b[3] - b[1]));
414
+ if (o.canIndividual && density * area <= o.budget)
415
+ return { kind: 'individual' };
416
+ if (!o.levels.length)
417
+ return { kind: 'none' };
418
+ const spacing = o.minSpacingPx ?? GROUP_MIN_SPACING_PX;
419
+ for (let l = 0; l < o.levels.length; l++) {
420
+ const bin = o.levels[l].binSize;
421
+ // Tissue rarely fills the view; 0.7 of the bins occupied is a fair guess.
422
+ if (bin * o.pxPerUnit >= spacing && (area / (bin * bin)) * 0.7 <= o.budget) {
423
+ return { kind: 'bins', level: l };
424
+ }
425
+ }
426
+ return { kind: 'bins', level: o.levels.length - 1 };
427
+ }
428
+ /**
429
+ * Diameter in px of a group of `count` transcripts in a bin `binPx` wide, where
430
+ * `refCount` is a typical busy bin in view (its 95th percentile).
431
+ *
432
+ * Area grows with the count — a bin with a quarter of the transcripts gets half the
433
+ * diameter — between a third of the bin (so a sparse bin is still visible) and a little
434
+ * over the full bin (so dense neighbours just touch rather than pile up).
435
+ */
436
+ export function groupedMarkerPx(count, refCount, binPx, scale = 1) {
437
+ const f = Math.sqrt(Math.min(1, count / Math.max(1, refCount)));
438
+ const d = binPx * (0.35 + 0.75 * f) * scale;
439
+ return Math.max(TRANSCRIPT_MIN_PX * scale, Math.min(d, binPx * 1.2 * Math.max(scale, 1)));
440
+ }
441
+ /** The `p` quantile (0..1) of a count vector — a sample of it for large vectors. */
442
+ export function quantileOf(values, p) {
443
+ const n = values.length;
444
+ if (!n)
445
+ return 0;
446
+ const step = Math.max(1, Math.floor(n / 4096));
447
+ const sample = [];
448
+ for (let i = 0; i < n; i += step)
449
+ sample.push(values[i]);
450
+ sample.sort((a, b) => a - b);
451
+ return sample[Math.min(sample.length - 1, Math.floor(p * sample.length))];
452
+ }
453
+ /** {@link tilesInRect} for a grid whose tile (0, 0) starts at `origin`. */
454
+ export function tilesInRectFrom(origin, rect, level, levels, bounds, limit = Infinity) {
455
+ const [ox, oy] = origin;
456
+ const shifted = { x0: rect.x0 - ox, y0: rect.y0 - oy, x1: rect.x1 - ox, y1: rect.y1 - oy };
457
+ const b = bounds ? [bounds[0] - ox, bounds[1] - oy, bounds[2] - ox, bounds[3] - oy] : null;
458
+ return tilesInRect(shifted, level, levels, b, limit);
459
+ }
460
+ /** A density window from the non-empty bins: 1st to 99th percentile. */
461
+ export function densityAutoRange(values) {
462
+ const positive = [];
463
+ for (let i = 0; i < values.length; i++)
464
+ if (values[i] > 0)
465
+ positive.push(values[i]);
466
+ if (!positive.length)
467
+ return [0, 1];
468
+ positive.sort((a, b) => a - b);
469
+ const at = (p) => positive[Math.min(positive.length - 1, Math.floor(p * positive.length))];
470
+ const lo = at(0.01);
471
+ const hi = at(0.99);
472
+ return hi > lo ? [lo, hi] : [0, hi || 1];
473
+ }
474
+ /**
475
+ * Colour density bins through `lut` over the window `[lo, hi]` — Xenium Explorer's
476
+ * "scale threshold". Bins at or below `lo` are transparent, so empty tissue shows the
477
+ * image under it; bins at or above `hi` saturate.
478
+ */
479
+ export function colorDensityWindow(values, lut, opacity, lo, hi) {
480
+ const n = values.length;
481
+ const rgba = new Uint8Array(n * 4);
482
+ const span = hi > lo ? hi - lo : 1;
483
+ const a = Math.round(255 * opacity);
484
+ for (let i = 0; i < n; i++) {
485
+ const v = values[i];
486
+ if (!(v > lo))
487
+ continue;
488
+ const f = Math.min(1, (v - lo) / span);
489
+ const c = lut[Math.min(lut.length - 1, Math.round(f * (lut.length - 1)))];
490
+ rgba[4 * i] = c[0];
491
+ rgba[4 * i + 1] = c[1];
492
+ rgba[4 * i + 2] = c[2];
493
+ rgba[4 * i + 3] = a;
494
+ }
495
+ return rgba;
496
+ }
497
+ /**
498
+ * Inferno (matplotlib), as an inline `[stop, colour]` scale: the density map's default,
499
+ * as in Xenium Explorer. Inline because the colormap tree's `INFERNO_LUT` key is resolved
500
+ * at runtime by the store, which the renderer does not see.
501
+ */
502
+ export const INFERNO_SCALE = [
503
+ [0, '#000004'], [0.125, '#1b0c41'], [0.25, '#4a0c6b'], [0.375, '#781c6d'], [0.5, '#a52c60'],
504
+ [0.625, '#cf4446'], [0.75, '#ed6925'], [0.875, '#fb9b06'], [1, '#fcffa4'],
505
+ ];
506
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3BhdGlhbC10aWxlcy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9saWIvc3BhdGlhbC9zcGF0aWFsLXRpbGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7Ozs7Ozs7OztHQWNHO0FBdUJILDRGQUE0RjtBQUM1RixNQUFNLFVBQVUsVUFBVSxDQUN4QixPQUFpRSxFQUNqRSxJQUF5QztJQUV6QyxNQUFNLFNBQVMsR0FBRyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsWUFBWSxJQUFJLE9BQU8sRUFBRSxRQUFRLENBQUMsQ0FBQztJQUNqRSxPQUFPLFNBQVMsSUFBSSxDQUFDLElBQUksQ0FBQyxTQUFTLElBQUksSUFBSSxDQUFDLENBQUM7QUFDL0MsQ0FBQztBQUVELGtGQUFrRjtBQUNsRixNQUFNLFVBQVUsZUFBZSxDQUFDLElBQVk7SUFDMUMsT0FBTyxVQUFVLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO0FBQy9CLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxpQkFBaUIsQ0FDL0IsT0FBdUIsRUFBRSxJQUE4QztJQUV2RSxNQUFNLFdBQVcsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxhQUFhLENBQUMsQ0FBQztJQUM1RSxJQUFJLElBQUksQ0FBQyxjQUFjLElBQUksV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxJQUFJLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQztRQUNuRixPQUFPLElBQUksQ0FBQyxjQUFjLENBQUM7SUFDN0IsQ0FBQztJQUNELE9BQU8sQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxJQUFJLElBQUksSUFBSSxDQUFDO0FBQzdGLENBQUM7QUFFRCxNQUFNLFVBQVUsTUFBTSxDQUFDLENBQVU7SUFDL0IsT0FBTyxHQUFHLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUM7QUFDdEMsQ0FBQztBQUVELDZGQUE2RjtBQUM3RixNQUFNLFVBQVUsaUJBQWlCLENBQUMsSUFBWSxFQUFFLEdBQTRCO0lBQzFFLE9BQU8sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDO0FBQy9DLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsZUFBZSxDQUM3QixNQUFpQyxFQUFFLElBQVksRUFBRSxPQUFlLEVBQUUsT0FBZSxFQUNqRixHQUE0QixFQUFFLE1BQU0sR0FBRyxJQUFJO0lBRTNDLElBQUksQ0FBQyxDQUFDLElBQUksR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsT0FBTyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxPQUFPLEdBQUcsQ0FBQyxDQUFDO1FBQUUsT0FBTyxJQUFJLENBQUM7SUFDakUsTUFBTSxFQUFFLEdBQUcsR0FBRyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoQyxNQUFNLEVBQUUsR0FBRyxHQUFHLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2hDLE1BQU0sRUFBRSxHQUFHLEdBQUcsRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDcEMsTUFBTSxFQUFFLEdBQUcsR0FBRyxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNwQyxNQUFNLEtBQUssR0FBRyxDQUFDLE9BQU8sR0FBRyxJQUFJLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDO0lBQ3RELE1BQU0sS0FBSyxHQUFHLENBQUMsT0FBTyxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsTUFBTSxDQUFDLENBQUM7SUFDdEQsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQztJQUM5QixNQUFNLEdBQUcsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsS0FBSyxDQUFDO0lBQzlCLE1BQU0sR0FBRyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUM7SUFDOUIsTUFBTSxHQUFHLEdBQUcsTUFBTSxDQUFDLENBQUMsQ0FBQyxHQUFHLEtBQUssQ0FBQztJQUM5QixNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDM0IsTUFBTSxFQUFFLEdBQUcsQ0FBQyxHQUFHLEdBQUcsRUFBRSxDQUFDLEdBQUcsRUFBRSxDQUFDO0lBQzNCLE1BQU0sRUFBRSxHQUFHLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLEVBQUUsQ0FBQztJQUMzQixNQUFNLEVBQUUsR0FBRyxDQUFDLEdBQUcsR0FBRyxFQUFFLENBQUMsR0FBRyxFQUFFLENBQUM7SUFDM0IsT0FBTyxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxFQUFFLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQUUsRUFBRSxFQUFFLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLEVBQUUsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLENBQUMsRUFBRSxDQUFDO0FBQ3BHLENBQUM7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLFdBQVcsQ0FDekIsSUFBYyxFQUFFLEtBQWEsRUFBRSxNQUFtQyxFQUNsRSxNQUE2QixFQUFFLEtBQUssR0FBRyxRQUFRO0lBRS9DLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxRQUFRLENBQUM7SUFDckMsSUFBSSxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsQ0FBQztRQUFFLE9BQU8sRUFBRSxDQUFDO0lBQzNCLElBQUksRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsR0FBRyxJQUFJLENBQUM7SUFDOUIsSUFBSSxNQUFNLEVBQUUsQ0FBQztRQUNYLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3QixFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDN0IsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzdCLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUM3QixJQUFJLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUU7WUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNwQyxDQUFDO0lBQ0QsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDbEMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDO0lBQzFDLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztJQUMxQyxNQUFNLEdBQUcsR0FBYyxFQUFFLENBQUM7SUFDMUIsS0FBSyxJQUFJLEVBQUUsR0FBRyxHQUFHLEVBQUUsRUFBRSxJQUFJLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO1FBQ25DLEtBQUssSUFBSSxFQUFFLEdBQUcsR0FBRyxFQUFFLEVBQUUsSUFBSSxHQUFHLEVBQUUsRUFBRSxFQUFFO1lBQUUsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztJQUNsRSxDQUFDO0lBQ0QsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7VUFDaEUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsR0FBRyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDdkQsT0FBTyxHQUFHLENBQUMsTUFBTSxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztBQUN4RCxDQUFDO0FBRUQ7OztHQUdHO0FBQ0gsTUFBTSxVQUFVLG1CQUFtQixDQUFDLE1BQXlDLEVBQUUsUUFBUSxHQUFHLEVBQUU7SUFDMUYsSUFBSSxPQUFPLE1BQU0sS0FBSyxRQUFRO1FBQUUsT0FBTyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUM7SUFDMUUsSUFBSSxDQUFDLE1BQU0sRUFBRSxNQUFNO1FBQUUsT0FBTyxRQUFRLENBQUM7SUFDckMsK0VBQStFO0lBQy9FLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDO0lBQzNELE1BQU0sTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUM1QixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsTUFBTSxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksSUFBSSxFQUFFLENBQUM7UUFDN0MsSUFBSSxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztZQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDNUMsQ0FBQztJQUNELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTTtRQUFFLE9BQU8sUUFBUSxDQUFDO0lBQ3BDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7SUFDN0IsT0FBTyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7QUFDeEMsQ0FBQztBQUVEOzs7Ozs7Ozs7O0dBVUc7QUFDSCxNQUFNLENBQUMsTUFBTSx5QkFBeUIsR0FBRyxDQUFDLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0FBRS9EOzs7R0FHRztBQUNILE1BQU0sVUFBVSxlQUFlLENBQzdCLFNBQWlCLEVBQUUsWUFBb0IsRUFBRSxVQUFrQixFQUFFLE1BQU0sR0FBRyxDQUFDO0lBRXZFLE1BQU0sTUFBTSxHQUFHLFNBQVMsR0FBRyxZQUFZLEdBQUcsTUFBTSxDQUFDO0lBQ2pELE1BQU0sS0FBSyxHQUFHLHlCQUF5QixDQUFDO0lBQ3hDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxVQUFVLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUNwQyxzRUFBc0U7UUFDdEUsTUFBTSxHQUFHLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLEtBQUssQ0FBQyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQzlFLElBQUksTUFBTSxJQUFJLEdBQUc7WUFBRSxPQUFPLENBQUMsQ0FBQztJQUM5QixDQUFDO0lBQ0QsT0FBTyxDQUFDLENBQUMsQ0FBQztBQUNaLENBQUM7QUFFRDs7Ozs7R0FLRztBQUNILE1BQU0sVUFBVSxrQkFBa0IsQ0FDaEMsU0FBaUIsRUFBRSxNQUFtQyxFQUFFLFlBQVksR0FBRyxHQUFHO0lBRTFFLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxJQUFJLENBQUMsQ0FBQyxTQUFTLEdBQUcsQ0FBQyxDQUFDO1FBQUUsT0FBTyxDQUFDLENBQUM7SUFDakQsSUFBSSxJQUFJLEdBQUcsQ0FBQyxDQUFDO0lBQ2IsSUFBSSxPQUFPLEdBQUcsUUFBUSxDQUFDO0lBQ3ZCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxNQUFNLENBQUMsTUFBTSxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDdkMsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsR0FBRyxTQUFTLENBQUMsR0FBRyxZQUFZLENBQUMsQ0FBQyxDQUFDO1FBQ2pGLElBQUksR0FBRyxHQUFHLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLE9BQU8sR0FBRyxHQUFHLENBQUM7WUFDZCxJQUFJLEdBQUcsQ0FBQyxDQUFDO1FBQ1gsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLElBQUksQ0FBQztBQUNkLENBQUM7QUFFRCxnRUFBZ0U7QUFDaEUsTUFBTSxDQUFDLE1BQU0saUJBQWlCLEdBQUcsQ0FBQyxDQUFDO0FBQ25DLE1BQU0sQ0FBQyxNQUFNLGlCQUFpQixHQUFHLEVBQUUsQ0FBQztBQUNwQzs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sc0JBQXNCLEdBQUcsR0FBRyxDQUFDO0FBRTFDOzs7Ozs7Ozs7Ozs7Ozs7O0dBZ0JHO0FBQ0gsTUFBTSxVQUFVLGtCQUFrQixDQUFDLE1BQWMsRUFBRSxLQUFLLEdBQUcsQ0FBQyxFQUFFLFdBQW9CO0lBQ2hGLE1BQU0sT0FBTyxHQUFHLGlCQUFpQixHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQztJQUNuRSxNQUFNLFFBQVEsR0FBRyxXQUFXLENBQUMsQ0FBQyxDQUFDLHNCQUFzQixHQUFHLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3hFLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLFFBQVEsQ0FBQyxHQUFHLEtBQUssQ0FBQztJQUMvQyxPQUFPLElBQUksQ0FBQyxHQUFHLENBQUMsaUJBQWlCLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLEVBQUUsSUFBSSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsR0FBRyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztBQUNuRyxDQUFDO0FBRUQseUZBQXlGO0FBRXpGLDBGQUEwRjtBQUMxRixNQUFNLENBQUMsTUFBTSxpQkFBaUIsR0FBRztJQUMvQixRQUFRLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsZUFBZTtJQUN0RixVQUFVLEVBQUUsR0FBRztDQUNQLENBQUM7QUFFWCxtRkFBbUY7QUFDbkYsTUFBTSxnQkFBZ0IsR0FDcUQsSUFBSSxDQUFDO0FBQ2hGLEtBQUssZ0JBQWdCLENBQUM7QUFFdEIsNEZBQTRGO0FBQzVGLE1BQU0sVUFBVSxZQUFZLENBQUMsS0FBc0I7SUFDakQsTUFBTSxJQUFJLEdBQUcsQ0FBQyxDQUFTLEVBQUUsR0FBRyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFO1FBQ3BELE1BQU0sR0FBRyxHQUFHLElBQUksWUFBWSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNwQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDM0IsTUFBTSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxDQUFDO1lBQ3RDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDN0IsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkMsQ0FBQztRQUNELE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQyxDQUFDO0lBQ0YsTUFBTSxJQUFJLEdBQUcsQ0FBQyxNQUFjLEVBQUUsS0FBYSxFQUFFLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsQ0FBQyxFQUFFLEVBQUU7UUFDakUsTUFBTSxHQUFHLEdBQUcsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3pDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxNQUFNLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7WUFDcEMsTUFBTSxDQUFDLEdBQUcsR0FBRyxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxNQUFNLENBQUM7WUFDdkMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDO1lBQ2xDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDN0IsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUM7UUFDbkMsQ0FBQztRQUNELE9BQU8sR0FBRyxDQUFDO0lBQ2IsQ0FBQyxDQUFDO0lBQ0Ysa0RBQWtEO0lBQ2xELE1BQU0sSUFBSSxHQUFHLENBQUMsQ0FBUyxFQUFFLE1BQWUsRUFBRSxFQUFFO1FBQzFDLE1BQU0sR0FBRyxHQUFHO1lBQ1YsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQ2pELENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEVB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QUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzVDLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztRQUM5QixNQUFNLEdBQUcsR0FBRyxDQUFDLEdBQUcsSUFBSSxDQUFDO1FBQ3JCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUM5QixJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7WUFDWixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQkFDN0IsTUFBTSxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDakIsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsR0FBRyxJQUFJO29CQUFFLEdBQUcsSUFBSSxNQUFNLENBQUMsR0FBRyxHQUFHLEVBQUUsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDcEUsQ0FBQztZQUNELEdBQUcsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLEdBQUcsR0FBRyxDQUFDO1FBQ3JCLENBQUM7SUFDSCxDQUFDO0lBQ0QsS0FBSyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLElBQUksRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1FBQzlCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUM5QixJQUFJLEdBQUcsR0FBRyxDQUFDLENBQUM7WUFDWixLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztnQkFDN0IsTUFBTSxFQUFFLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQztnQkFDakIsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJLEVBQUUsR0FBRyxJQUFJO29CQUFFLEdBQUcsSUFBSSxHQUFHLENBQUMsRUFBRSxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsR0FBRyxNQUFNLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDO1lBQ3RFLENBQUM7WUFDRCxHQUFHLENBQUMsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLENBQUMsR0FBRyxHQUFHLENBQUM7UUFDMUIsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLEdBQUcsQ0FBQztBQUNiLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsWUFBWSxDQUMxQixNQUFvQixFQUFFLEdBQW1ELEVBQUUsT0FBZSxFQUMxRixFQUFFLEdBQUcsR0FBRyxJQUFJLEVBQUUsVUFBVSxHQUFHLEtBQUssRUFBRSxHQUFHLEVBQUU7SUFFdkMsTUFBTSxDQUFDLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQztJQUN4QixNQUFNLENBQUMsR0FBRyxHQUFHLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUM7SUFDdkUsTUFBTSxRQUFRLEdBQWEsRUFBRSxDQUFDO0lBQzlCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFO1FBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztZQUFFLFFBQVEsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDOUQsUUFBUSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUMvQixNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDO0lBQ25GLE1BQU0sRUFBRSxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQzlDLE1BQU0sSUFBSSxHQUFHLElBQUksVUFBVSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNuQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDM0IsTUFBTSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDeEMsSUFBSSxDQUFDLEdBQUcsSUFBSTtZQUFFLFNBQVM7UUFDdkIsTUFBTSxDQUFDLEdBQUcsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQzFFLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ25CLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUN2QixJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkIsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFD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Q0FBQyxLQUFLLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMxRSxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNuQixJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdkIsSUFBSSxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1FBQ3ZCLElBQUksQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN0QixDQUFDO0lBQ0QsT0FBTyxJQUFJLENBQUM7QUFDZCxDQUFDO0FBRUQ7Ozs7R0FJRztBQUNILE1BQU0sQ0FBQyxNQUFNLGFBQWEsR0FBdUI7SUFDL0MsQ0FBQyxDQUFDLEVBQUUsU0FBUyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLEVBQUUsQ0FBQyxJQUFJLEVBQUUsU0FBUyxDQUFDLEVBQUUsQ0FBQyxLQUFLLEVBQUUsU0FBUyxDQUFDLEVBQUUsQ0FBQyxHQUFHLEVBQUUsU0FBUyxDQUFDO0lBQzNGLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxFQUFFLENBQUMsSUFBSSxFQUFFLFNBQVMsQ0FBQyxFQUFFLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxFQUFFLFNBQVMsQ0FBQztDQUMxRSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBMZXZlbC1vZi1kZXRhaWwgcGxhbm5pbmcgZm9yIHRpbGVkIHNwYXRpYWwgZ2VvbWV0cnkg4oCUIGNlbGwgb3V0bGluZXMgYW5kIHRyYW5zY3JpcHRzLlxuICpcbiAqIFRoZSByZW5kZXJlciBrbm93cyBpdHMgY2FtZXJhIChhIHdvcmxkLXNwYWNlIGNlbnRyZSwgYSB6b29tIGluIGNhbnZhcyBwaXhlbHMgcGVyIHdvcmxkXG4gKiB1bml0LCBhIGNhbnZhcyBzaXplKTsgYSB0aWxlZCBkYXRhc2V0IGtub3dzIGl0cyBncmlkcyAob25lIHBlciBsZXZlbCwgaW4gb2JzZXJ2YXRpb25cbiAqIHVuaXRzKS4gVGhpcyBtb2R1bGUgaXMgdGhlIGJyaWRnZTogd2hpY2ggbGV2ZWwgdGhlIHpvb20gY2FsbHMgZm9yLCB3aGljaCB0aWxlcyBhcmUgb25cbiAqIHNjcmVlbiwgaG93IGJpZyBhIHRyYW5zY3JpcHQgbWFya2VyIHNob3VsZCBiZS4gRXZlcnl0aGluZyBoZXJlIGlzIHB1cmUsIHNvIHRoZSBwb2xpY3lcbiAqIOKAlCB0aGUgcGFydCB0aGF0IGRlY2lkZXMgd2hldGhlciB0aGUgdmlldyBpcyBmYXN0IGFuZCBsZWdpYmxlIOKAlCBpcyB0ZXN0YWJsZSB3aXRob3V0IGFcbiAqIEdQVS5cbiAqXG4gKiBPYnNlcnZhdGlvbiB1bml0cyBtYXAgb250byB3b3JsZCB1bml0cyB0aHJvdWdoIHRoZSBkYXRhc2V0J3MgYGltYWdlUmVmYCBhZmZpbmVcbiAqIChgd29ybGQgPSBkYXRhIMK3IHNjYWxlICsgdHJhbnNsYXRlYCksIHNvIFwicGl4ZWxzIHBlciBvYnNlcnZhdGlvbiB1bml0XCIgaXNcbiAqIGB6b29tIMK3IHNjYWxlYC4gRm9yIGEgWGVuaXVtIGJ1bmRsZSB0aGUgZGF0YSB1bml0IGlzIHRoZSBtaWNyb24gYW5kIHRoZSB3b3JsZCB1bml0IHRoZVxuICogbW9ycGhvbG9neSBwaXhlbC5cbiAqL1xuXG5pbXBvcnQgdHlwZSB7XG4gIFNwYXRpYWxCb3VuZHMsIFNwYXRpYWxJbWFnZVJlZiwgU3BhdGlhbFRpbGVMZXZlbCxcbn0gZnJvbSAnLi4vY29udHJhY3RzL3NwYXRpYWwtZGF0YXNldC5jb250cmFjdCc7XG5pbXBvcnQgdHlwZSB7IFNwYXRpYWxWaWV3U3RhdGUsIFRyYW5zY3JpcHRHbHlwaE5hbWUgfSBmcm9tICcuLi9jb250cmFjdHMvZGlzcGxheS10eXBlcyc7XG5pbXBvcnQgdHlwZSB7IFNwYXRpYWxEYXRhc2V0IH0gZnJvbSAnLi4vY29udHJhY3RzL3NwYXRpYWwtZGF0YXNldC5jb250cmFjdCc7XG5cbi8qKiBBIHJlY3RhbmdsZSBpbiBvYnNlcnZhdGlvbiBjb29yZGluYXRlcy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgRGF0YVJlY3Qge1xuICB4MDogbnVtYmVyO1xuICB5MDogbnVtYmVyO1xuICB4MTogbnVtYmVyO1xuICB5MTogbnVtYmVyO1xufVxuXG4vKiogVGlsZSBhZGRyZXNzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBUaWxlS2V5IHtcbiAgbGV2ZWw6IG51bWJlcjtcbiAgZ3g6IG51bWJlcjtcbiAgZ3k6IG51bWJlcjtcbn1cblxuLyoqIFdoZXRoZXIgY2VsbCBvdXRsaW5lcyBhcmUgZHJhd246IHRoZSB1c2VyJ3MgY2hvaWNlLCBlbHNlIG9uIHdoZW4gdGhlIGRhdGFzZXQgaGFzIGFueS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjZWxsc1Nob3duKFxuICBkYXRhc2V0OiBQaWNrPFNwYXRpYWxEYXRhc2V0LCAncG9seWdvblRpbGVzJyB8ICdwb2x5Z29ucyc+IHwgbnVsbCxcbiAgdmlldzogUGljazxTcGF0aWFsVmlld1N0YXRlLCAnc2hvd0NlbGxzJz4sXG4pOiBib29sZWFuIHtcbiAgY29uc3QgYXZhaWxhYmxlID0gISEoZGF0YXNldD8ucG9seWdvblRpbGVzIHx8IGRhdGFzZXQ/LnBvbHlnb25zKTtcbiAgcmV0dXJuIGF2YWlsYWJsZSAmJiAodmlldy5zaG93Q2VsbHMgPz8gdHJ1ZSk7XG59XG5cbi8qKiBBIGNvbHVtbiBob2xkaW5nIGEgaGFuZC1jdXJhdGVkIGNlbGwtdHlwZSBhbm5vdGF0aW9uLCBieSBuYW1pbmcgY29udmVudGlvbi4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc0N1cmF0ZWRDb2x1bW4obmFtZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gIHJldHVybiAvY3VyYXRlZC9pLnRlc3QobmFtZSk7XG59XG5cbi8qKlxuICogVGhlIGNhdGVnb3JpY2FsIGNvbHVtbiB0aGF0IG5hbWVzIGVhY2ggY2VsbCdzIHR5cGU6IHRoZSB2aWV3J3MgY2hvaWNlIHdoZW4gaXQgaXMgYVxuICogY29sdW1uIG9mIHRoaXMgZGF0YXNldCwgZWxzZSB0aGUgZmlyc3QgY2F0ZWdvcmljYWwgY29sdW1uIHRoYXQgaXMgbm90IGEgY3VyYXRlZFxuICogYW5ub3RhdGlvbiAoYSBwaXBlbGluZSdzIGNsdXN0ZXJpbmcgaXMgdGhlIGRlZmF1bHQ7IGN1cmF0aW9uIGlzIG9wdGVkIGludG8pLCBlbHNlXG4gKiBhbnkgY2F0ZWdvcmljYWwgY29sdW1uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gY2VsbFR5cGVDb2x1bW5Gb3IoXG4gIGRhdGFzZXQ6IFNwYXRpYWxEYXRhc2V0LCB2aWV3OiBQaWNrPFNwYXRpYWxWaWV3U3RhdGUsICdjZWxsVHlwZUNvbHVtbic+LFxuKTogc3RyaW5nIHwgbnVsbCB7XG4gIGNvbnN0IGNhdGVnb3JpY2FsID0gZGF0YXNldC5jb2x1bW5zLmZpbHRlcigoYykgPT4gYy5raW5kID09PSAnY2F0ZWdvcmljYWwnKTtcbiAgaWYgKHZpZXcuY2VsbFR5cGVDb2x1bW4gJiYgY2F0ZWdvcmljYWwuc29tZSgoYykgPT4gYy5uYW1lID09PSB2aWV3LmNlbGxUeXBlQ29sdW1uKSkge1xuICAgIHJldHVybiB2aWV3LmNlbGxUeXBlQ29sdW1uO1xuICB9XG4gIHJldHVybiAoY2F0ZWdvcmljYWwuZmluZCgoYykgPT4gIWlzQ3VyYXRlZENvbHVtbihjLm5hbWUpKSA/PyBjYXRlZ29yaWNhbFswXSk/Lm5hbWUgPz8gbnVsbDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHRpbGVJZChrOiBUaWxlS2V5KTogc3RyaW5nIHtcbiAgcmV0dXJuIGAke2subGV2ZWx9LyR7ay5neH0vJHtrLmd5fWA7XG59XG5cbi8qKiBDYW52YXMgcGl4ZWxzIHBlciBvYnNlcnZhdGlvbiB1bml0IGFsb25nIHgsIGZvciBhIGNhbWVyYSB6b29tIGFuZCBhIGRhdGHihpJ3b3JsZCBhZmZpbmUuICovXG5leHBvcnQgZnVuY3Rpb24gcGl4ZWxzUGVyRGF0YVVuaXQoem9vbTogbnVtYmVyLCByZWY/OiBTcGF0aWFsSW1hZ2VSZWYgfCBudWxsKTogbnVtYmVyIHtcbiAgcmV0dXJuIHpvb20gKiBNYXRoLmFicyhyZWY/LnNjYWxlPy5bMF0gPz8gMSk7XG59XG5cbi8qKlxuICogVGhlIHBhcnQgb2Ygb2JzZXJ2YXRpb24gc3BhY2UgdGhlIGNhbWVyYSBzaG93cywgcGFkZGVkIGJ5IGBtYXJnaW5gIChhIGZyYWN0aW9uIG9mIHRoZVxuICogdmlld3BvcnQpIHNvIHRpbGVzIGp1c3Qgb2ZmIHNjcmVlbiBhcmUgYWxyZWFkeSB0aGVyZSB3aGVuIGEgcGFuIGJyaW5ncyB0aGVtIGluLlxuICovXG5leHBvcnQgZnVuY3Rpb24gdmlzaWJsZURhdGFSZWN0KFxuICBjZW50ZXI6IHJlYWRvbmx5IFtudW1iZXIsIG51bWJlcl0sIHpvb206IG51bWJlciwgY2FudmFzVzogbnVtYmVyLCBjYW52YXNIOiBudW1iZXIsXG4gIHJlZj86IFNwYXRpYWxJbWFnZVJlZiB8IG51bGwsIG1hcmdpbiA9IDAuMTUsXG4pOiBEYXRhUmVjdCB8IG51bGwge1xuICBpZiAoISh6b29tID4gMCkgfHwgIShjYW52YXNXID4gMCkgfHwgIShjYW52YXNIID4gMCkpIHJldHVybiBudWxsO1xuICBjb25zdCBzeCA9IHJlZj8uc2NhbGU/LlswXSA/PyAxO1xuICBjb25zdCBzeSA9IHJlZj8uc2NhbGU/LlsxXSA/PyAxO1xuICBjb25zdCB0eCA9IHJlZj8udHJhbnNsYXRlPy5bMF0gPz8gMDtcbiAgY29uc3QgdHkgPSByZWY/LnRyYW5zbGF0ZT8uWzFdID8/IDA7XG4gIGNvbnN0IGhhbGZXID0gKGNhbnZhc1cgLyB6b29tIC8gMikgKiAoMSArIDIgKiBtYXJnaW4pO1xuICBjb25zdCBoYWxmSCA9IChjYW52YXNIIC8gem9vbSAvIDIpICogKDEgKyAyICogbWFyZ2luKTtcbiAgY29uc3Qgd3gwID0gY2VudGVyWzBdIC0gaGFsZlc7XG4gIGNvbnN0IHd4MSA9IGNlbnRlclswXSArIGhhbGZXO1xuICBjb25zdCB3eTAgPSBjZW50ZXJbMV0gLSBoYWxmSDtcbiAgY29uc3Qgd3kxID0gY2VudGVyWzFdICsgaGFsZkg7XG4gIGNvbnN0IGF4ID0gKHd4MCAtIHR4KSAvIHN4O1xuICBjb25zdCBieCA9ICh3eDEgLSB0eCkgLyBzeDtcbiAgY29uc3QgYXkgPSAod3kwIC0gdHkpIC8gc3k7XG4gIGNvbnN0IGJ5ID0gKHd5MSAtIHR5KSAvIHN5O1xuICByZXR1cm4geyB4MDogTWF0aC5taW4oYXgsIGJ4KSwgeTA6IE1hdGgubWluKGF5LCBieSksIHgxOiBNYXRoLm1heChheCwgYngpLCB5MTogTWF0aC5tYXgoYXksIGJ5KSB9O1xufVxuXG4vKipcbiAqIFRpbGVzIG9mIG9uZSBsZXZlbCBpbnRlcnNlY3RpbmcgYHJlY3RgLCBjbGlwcGVkIHRvIHRoZSBkYXRhc2V0J3MgYGJvdW5kc2AgKHNvIHpvb21pbmdcbiAqIG91dCBvdmVyIGVtcHR5IGNhbnZhcyBkb2VzIG5vdCBhc2sgZm9yIHRpbGVzIHRoYXQgY2Fubm90IGV4aXN0KS4gT3JkZXJlZCBmcm9tIHRoZVxuICogcmVjdGFuZ2xlJ3MgY2VudHJlIG91dHdhcmQsIHNvIHRoZSBtaWRkbGUgb2YgdGhlIHNjcmVlbiBmaWxscyBpbiBmaXJzdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRpbGVzSW5SZWN0KFxuICByZWN0OiBEYXRhUmVjdCwgbGV2ZWw6IG51bWJlciwgbGV2ZWxzOiByZWFkb25seSBTcGF0aWFsVGlsZUxldmVsW10sXG4gIGJvdW5kcz86IFNwYXRpYWxCb3VuZHMgfCBudWxsLCBsaW1pdCA9IEluZmluaXR5LFxuKTogVGlsZUtleVtdIHtcbiAgY29uc3Qgc2l6ZSA9IGxldmVsc1tsZXZlbF0/LnRpbGVTaXplO1xuICBpZiAoIShzaXplID4gMCkpIHJldHVybiBbXTtcbiAgbGV0IHsgeDAsIHkwLCB4MSwgeTEgfSA9IHJlY3Q7XG4gIGlmIChib3VuZHMpIHtcbiAgICB4MCA9IE1hdGgubWF4KHgwLCBib3VuZHNbMF0pO1xuICAgIHkwID0gTWF0aC5tYXgoeTAsIGJvdW5kc1sxXSk7XG4gICAgeDEgPSBNYXRoLm1pbih4MSwgYm91bmRzWzJdKTtcbiAgICB5MSA9IE1hdGgubWluKHkxLCBib3VuZHNbM10pO1xuICAgIGlmICh4MSA8IHgwIHx8IHkxIDwgeTApIHJldHVybiBbXTtcbiAgfVxuICBjb25zdCBneDAgPSBNYXRoLmZsb29yKHgwIC8gc2l6ZSk7XG4gIGNvbnN0IGd4MSA9IE1hdGguZmxvb3IoeDEgLyBzaXplKTtcbiAgY29uc3QgZ3kwID0gTWF0aC5mbG9vcih5MCAvIHNpemUpO1xuICBjb25zdCBneTEgPSBNYXRoLmZsb29yKHkxIC8gc2l6ZSk7XG4gIGNvbnN0IGN4ID0gKHJlY3QueDAgKyByZWN0LngxKSAvIDIgLyBzaXplO1xuICBjb25zdCBjeSA9IChyZWN0LnkwICsgcmVjdC55MSkgLyAyIC8gc2l6ZTtcbiAgY29uc3Qgb3V0OiBUaWxlS2V5W10gPSBbXTtcbiAgZm9yIChsZXQgZ3kgPSBneTA7IGd5IDw9IGd5MTsgZ3krKykge1xuICAgIGZvciAobGV0IGd4ID0gZ3gwOyBneCA8PSBneDE7IGd4KyspIG91dC5wdXNoKHsgbGV2ZWwsIGd4LCBneSB9KTtcbiAgfVxuICBvdXQuc29ydCgoYSwgYikgPT4gKChhLmd4ICsgMC41IC0gY3gpICoqIDIgKyAoYS5neSArIDAuNSAtIGN5KSAqKiAyKVxuICAgIC0gKChiLmd4ICsgMC41IC0gY3gpICoqIDIgKyAoYi5neSArIDAuNSAtIGN5KSAqKiAyKSk7XG4gIHJldHVybiBvdXQubGVuZ3RoID4gbGltaXQgPyBvdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0O1xufVxuXG4vKipcbiAqIFR5cGljYWwgY2VsbCBkaWFtZXRlciwgaW4gb2JzZXJ2YXRpb24gdW5pdHMsIHVzZWQgdG8ganVkZ2UgaG93IGxhcmdlIGNlbGxzIGFwcGVhci5cbiAqIERlcml2ZWQgZnJvbSB0aGUgcGVyLW9ic2VydmF0aW9uIHJhZGl1cyB3aGVuIHRoZXJlIGlzIG9uZTsgMTIgwrVtIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHR5cGljYWxDZWxsRGlhbWV0ZXIocmFkaXVzOiBGbG9hdDMyQXJyYXkgfCBudW1iZXIgfCB1bmRlZmluZWQsIGZhbGxiYWNrID0gMTIpOiBudW1iZXIge1xuICBpZiAodHlwZW9mIHJhZGl1cyA9PT0gJ251bWJlcicpIHJldHVybiByYWRpdXMgPiAwID8gcmFkaXVzICogMiA6IGZhbGxiYWNrO1xuICBpZiAoIXJhZGl1cz8ubGVuZ3RoKSByZXR1cm4gZmFsbGJhY2s7XG4gIC8vIFRoZSBtZWRpYW4gb2YgYSBzYW1wbGUgaXMgcGxlbnR5IOKAlCB0aGlzIHNldHMgYSB0aHJlc2hvbGQsIG5vdCBhIG1lYXN1cmVtZW50LlxuICBjb25zdCBzdGVwID0gTWF0aC5tYXgoMSwgTWF0aC5mbG9vcihyYWRpdXMubGVuZ3RoIC8gMjA0OCkpO1xuICBjb25zdCBzYW1wbGU6IG51bWJlcltdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgcmFkaXVzLmxlbmd0aDsgaSArPSBzdGVwKSB7XG4gICAgaWYgKHJhZGl1c1tpXSA+IDApIHNhbXBsZS5wdXNoKHJhZGl1c1tpXSk7XG4gIH1cbiAgaWYgKCFzYW1wbGUubGVuZ3RoKSByZXR1cm4gZmFsbGJhY2s7XG4gIHNhbXBsZS5zb3J0KChhLCBiKSA9PiBhIC0gYik7XG4gIHJldHVybiBzYW1wbGVbc2FtcGxlLmxlbmd0aCA+PiAxXSAqIDI7XG59XG5cbi8qKlxuICogT24tc2NyZWVuIGNlbGwgZGlhbWV0ZXIgKHB4KSBhdCBvciBhYm92ZSB3aGljaCBlYWNoIHBvbHlnb24gbGV2ZWwgaXMgdXNlZC4gQSBsZXZlbFxuICogaGFsdmVzIHRoZSB2ZXJ0aWNlcyBvZiB0aGUgb25lIGJlbG93LCBzbyBlYWNoIHNob3VsZCB0YWtlIG92ZXIgd2hlbiB0aGUgY2VsbCBpcyBhYm91dFxuICogaGFsZiBhcyBsYXJnZSBvbiBzY3JlZW4uIEJlbG93IHRoZSBsYXN0IGZpbml0ZSB0aHJlc2hvbGQgb3V0bGluZXMgYXJlIG5vdCBkcmF3biBhdFxuICogYWxsIOKAlCBhIGNlbGwgYSBmZXcgcGl4ZWxzIHdpZGUgaXMgYSBkb3QsIGFuZCB0aGUgb2JzZXJ2YXRpb24gbWFya2VycyBhbHJlYWR5IGRyYXcgaXRcbiAqIGFzIG9uZS5cbiAqXG4gKiBYZW5pdW0ncyBmb3VydGggbGV2ZWwgKDMgdmVydGljZXMgcGVyIGNlbGwpIGlzIGRlbGliZXJhdGVseSBuZXZlciB1c2VkOiBzZWVuIG9uXG4gKiBzY3JlZW4gaXQgaXMgYSBmaWVsZCBvZiB0cmlhbmdsZXMsIHdoaWNoIHJlYWRzIGFzIGFuIGFydGVmYWN0IHJhdGhlciB0aGFuIGFzIGNlbGxzLlxuICogVGhlIGRvdHMgYmVsb3cgOCBweCBzYXkgdGhlIHNhbWUgdGhpbmcgbW9yZSBob25lc3RseS5cbiAqL1xuZXhwb3J0IGNvbnN0IFBPTFlHT05fTEVWRUxfTUlOX0NFTExfUFggPSBbMzYsIDE4LCA4LCBJbmZpbml0eV07XG5cbi8qKlxuICogV2hpY2ggcG9seWdvbiBsZXZlbCBzdWl0cyB0aGlzIHpvb20sIG9yIC0xIGZvciBcInRvbyBzbWFsbCB0byBvdXRsaW5lXCIuXG4gKiBgZGV0YWlsYCA+IDEgcHJlZmVycyBmaW5lciBsZXZlbHMgKHNoYXJwZXIsIHNsb3dlcik7IDwgMSBjb2Fyc2VyLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcG9seWdvbkxldmVsRm9yKFxuICBweFBlclVuaXQ6IG51bWJlciwgY2VsbERpYW1ldGVyOiBudW1iZXIsIGxldmVsQ291bnQ6IG51bWJlciwgZGV0YWlsID0gMSxcbik6IG51bWJlciB7XG4gIGNvbnN0IGNlbGxQeCA9IHB4UGVyVW5pdCAqIGNlbGxEaWFtZXRlciAqIGRldGFpbDtcbiAgY29uc3QgdGFibGUgPSBQT0xZR09OX0xFVkVMX01JTl9DRUxMX1BYO1xuICBmb3IgKGxldCBsID0gMDsgbCA8IGxldmVsQ291bnQ7IGwrKykge1xuICAgIC8vIFBhc3QgdGhlIHRhYmxlLCBrZWVwIGhhbHZpbmc6IGVhY2ggbGV2ZWwgc3RpbGwgaGFsdmVzIHRoZSB2ZXJ0aWNlcy5cbiAgICBjb25zdCBtaW4gPSB0YWJsZVtsXSA/PyB0YWJsZVt0YWJsZS5sZW5ndGggLSAxXSAvIDIgKiogKGwgLSB0YWJsZS5sZW5ndGggKyAxKTtcbiAgICBpZiAoY2VsbFB4ID49IG1pbikgcmV0dXJuIGw7XG4gIH1cbiAgcmV0dXJuIC0xO1xufVxuXG4vKipcbiAqIFdoaWNoIHRyYW5zY3JpcHQgbGV2ZWwgc3VpdHMgdGhpcyB6b29tOiB0aGUgb25lIHdob3NlIHRpbGVzIGNvbWUgb3V0IGNsb3Nlc3QgdG9cbiAqIGB0YXJnZXRUaWxlUHhgIG9uIHNjcmVlbi4gQ29hcnNlciBsZXZlbHMgYWdncmVnYXRlIG1vcmUsIHNvIHRoaXMga2VlcHMgdGhlIG51bWJlciBvZlxuICogbWFya2VycyBwZXIgc2NyZWVuIHJvdWdobHkgY29uc3RhbnQgaG93ZXZlciBmYXIgb3V0IHRoZSBjYW1lcmEgaXMg4oCUIHRoZSBwcm9wZXJ0eSB0aGF0XG4gKiBrZWVwcyB0aGUgdmlldyBmYXN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gdHJhbnNjcmlwdExldmVsRm9yKFxuICBweFBlclVuaXQ6IG51bWJlciwgbGV2ZWxzOiByZWFkb25seSBTcGF0aWFsVGlsZUxldmVsW10sIHRhcmdldFRpbGVQeCA9IDUxMixcbik6IG51bWJlciB7XG4gIGlmICghbGV2ZWxzLmxlbmd0aCB8fCAhKHB4UGVyVW5pdCA+IDApKSByZXR1cm4gMDtcbiAgbGV0IGJlc3QgPSAwO1xuICBsZXQgYmVzdEVyciA9IEluZmluaXR5O1xuICBmb3IgKGxldCBsID0gMDsgbCA8IGxldmVscy5sZW5ndGg7IGwrKykge1xuICAgIGNvbnN0IGVyciA9IE1hdGguYWJzKE1hdGgubG9nMigobGV2ZWxzW2xdLnRpbGVTaXplICogcHhQZXJVbml0KSAvIHRhcmdldFRpbGVQeCkpO1xuICAgIGlmIChlcnIgPCBiZXN0RXJyKSB7XG4gICAgICBiZXN0RXJyID0gZXJyO1xuICAgICAgYmVzdCA9IGw7XG4gICAgfVxuICB9XG4gIHJldHVybiBiZXN0O1xufVxuXG4vKiogU21hbGxlc3QgYW5kIGxhcmdlc3QgdHJhbnNjcmlwdCBtYXJrZXIsIGluIGNhbnZhcyBwaXhlbHMuICovXG5leHBvcnQgY29uc3QgVFJBTlNDUklQVF9NSU5fUFggPSA0O1xuZXhwb3J0IGNvbnN0IFRSQU5TQ1JJUFRfTUFYX1BYID0gMzI7XG4vKipcbiAqIFBoeXNpY2FsIGRpYW1ldGVyIGEgc2luZ2xlIHRyYW5zY3JpcHQgaXMgZHJhd24gYXQsIGluIMK1bSDigJQgY2xlYXJseSBsYXJnZXIgdGhhbiB0aGVcbiAqIGltYWdlZCBzcG90ICh+MC4zIMK1bSkgc28gaXQgc3RheXMgbGVnaWJsZSwgYW5kIHNtYWxsIGVub3VnaCB0aGF0IG5laWdoYm91cmluZ1xuICogbW9sZWN1bGVzIGluc2lkZSBvbmUgY2VsbCBzdGF5IGFwYXJ0LlxuICovXG5leHBvcnQgY29uc3QgVFJBTlNDUklQVF9QSFlTSUNBTF9VTSA9IDEuMjtcblxuLyoqXG4gKiBNYXJrZXIgZGlhbWV0ZXIgaW4gY2FudmFzIHBpeGVscyBmb3IgYW4gZW50cnkgc3RhbmRpbmcgZm9yIGB3ZWlnaHRgIHRyYW5zY3JpcHRzLlxuICpcbiAqIFRoZSBjb252ZW50aW9uIHNwYXRpYWwgdmlld2VycyBzaGFyZSAoZGVjay5nbCdzIGByYWRpdXNNaW5QaXhlbHNgL2ByYWRpdXNNYXhQaXhlbHNgLFxuICogWGVuaXVtIEV4cGxvcmVyJ3MgdHJhbnNjcmlwdCBzaXplKTogYSBQSFlTSUNBTCBzaXplLCBjbGFtcGVkIHRvIGEgc2NyZWVuLXBpeGVsIHJhbmdlLlxuICogWm9vbWVkIG91dCwgbWFya2VycyBzaXQgYXQgdGhlIG1pbmltdW0gYW5kIG5ldmVyIHZhbmlzaDsgem9vbWVkIGluLCB0aGV5IGdyb3cgd2l0aCB0aGVcbiAqIHRpc3N1ZSBpbnN0ZWFkIG9mIHNocmlua2luZyB0byBzcGVja3MgbmV4dCB0byBjZWxscyBodW5kcmVkcyBvZiBwaXhlbHMgd2lkZS4gQSBmaXhlZFxuICogc2NyZWVuIHNpemUgZG9lcyB0aGUgb3Bwb3NpdGUgYXQgaGlnaCB6b29tLCB3aGljaCBpcyB3aGF0IG1hZGUgdHJhbnNjcmlwdHMgZGlzYXBwZWFyXG4gKiBhdCBwaXhlbC1sZXZlbCB6b29tLlxuICpcbiAqIEFnZ3JlZ2F0ZXMgZ3JvdyB3aXRoIHRoZSBjdWJlIHJvb3Qgb2YgdGhlaXIgY291bnQ6IGFyZWEg4oidIGNvdW50IHdvdWxkIGxldCBvbmUgZGVuc2VcbiAqIGFnZ3JlZ2F0ZSBzd2FsbG93IGl0cyBuZWlnaGJvdXJzLCB0aGUgY3ViZSByb290IGtlZXBzIGEgMTAwMC10cmFuc2NyaXB0IGNsdXN0ZXIgY2xlYXJseVxuICogbGFyZ2VyIHRoYW4gYSAxMC10cmFuc2NyaXB0IG9uZSB3aXRob3V0IGNvdmVyaW5nIHRoZSB0aWxlLlxuICpcbiAqIGBweFBlck1pY3JvbmAgaXMgb21pdHRlZCBmb3IgZGF0YSB3aXRoIG5vIGtub3duIHBoeXNpY2FsIHVuaXQ7IHRoZSBtYXJrZXIgaXMgdGhlblxuICogc2NyZWVuLXNpemVkIG9ubHkuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0cmFuc2NyaXB0TWFya2VyUHgod2VpZ2h0OiBudW1iZXIsIHNjYWxlID0gMSwgcHhQZXJNaWNyb24/OiBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCBjb3VudGVkID0gVFJBTlNDUklQVF9NSU5fUFggKiBNYXRoLmNicnQoTWF0aC5tYXgoMSwgd2VpZ2h0KSk7XG4gIGNvbnN0IHBoeXNpY2FsID0gcHhQZXJNaWNyb24gPyBUUkFOU0NSSVBUX1BIWVNJQ0FMX1VNICogcHhQZXJNaWNyb24gOiAwO1xuICBjb25zdCBweCA9IE1hdGgubWF4KGNvdW50ZWQsIHBoeXNpY2FsKSAqIHNjYWxlO1xuICByZXR1cm4gTWF0aC5taW4oVFJBTlNDUklQVF9NQVhfUFggKiBNYXRoLm1heChzY2FsZSwgMSksIE1hdGgubWF4KFRSQU5TQ1JJUFRfTUlOX1BYICogc2NhbGUsIHB4KSk7XG59XG5cbi8vIOKUgOKUgCBHbHlwaHMg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbi8qKiBNYXJrZXIgc2hhcGVzIGZvciB0aGUgdHJhbnNjcmlwdCBcImljb25cIiBtb2RlLiBBbGwgc3Rhci1jb252ZXgsIHNvIGEgZmFuIGZpbGxzIHRoZW0uICovXG5leHBvcnQgY29uc3QgVFJBTlNDUklQVF9HTFlQSFMgPSBbXG4gICdjaXJjbGUnLCAnc3RhcicsICd0cmlhbmdsZScsICdzcXVhcmUnLCAnZGlhbW9uZCcsICdjcm9zcycsICdoZXhhZ29uJywgJ3RyaWFuZ2xlLWRvd24nLFxuICAncGVudGFnb24nLCAneCcsXG5dIGFzIGNvbnN0O1xuZXhwb3J0IHR5cGUgVHJhbnNjcmlwdEdseXBoID0gdHlwZW9mIFRSQU5TQ1JJUFRfR0xZUEhTW251bWJlcl07XG4vLyBUaGUgdmlldyBzdGF0ZSBuYW1lcyBnbHlwaHMgd2l0aG91dCBpbXBvcnRpbmcgdGhpcyBtb2R1bGU7IGtlZXAgdGhlIHR3byBpbiBzdGVwLlxuY29uc3QgX2dseXBoTmFtZXNNYXRjaDogVHJhbnNjcmlwdEdseXBoIGV4dGVuZHMgVHJhbnNjcmlwdEdseXBoTmFtZVxuICA/IChUcmFuc2NyaXB0R2x5cGhOYW1lIGV4dGVuZHMgVHJhbnNjcmlwdEdseXBoID8gdHJ1ZSA6IG5ldmVyKSA6IG5ldmVyID0gdHJ1ZTtcbnZvaWQgX2dseXBoTmFtZXNNYXRjaDtcblxuLyoqIFVuaXQgb3V0bGluZSBvZiBhIGdseXBoLCByYWRpdXMg4omIIDEsIGNlbnRyZWQgb24gdGhlIG9yaWdpbiwgYXMgYFt4MCwgeTAsIHgxLCB5MSwg4oCmXWAuICovXG5leHBvcnQgZnVuY3Rpb24gZ2x5cGhPdXRsaW5lKGdseXBoOiBUcmFuc2NyaXB0R2x5cGgpOiBGbG9hdDMyQXJyYXkge1xuICBjb25zdCBwb2x5ID0gKG46IG51bWJlciwgcm90ID0gLU1hdGguUEkgLyAyLCByID0gMSkgPT4ge1xuICAgIGNvbnN0IG91dCA9IG5ldyBGbG9hdDMyQXJyYXkobiAqIDIpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgICBjb25zdCBhID0gcm90ICsgKGkgKiAyICogTWF0aC5QSSkgLyBuO1xuICAgICAgb3V0WzIgKiBpXSA9IE1hdGguY29zKGEpICogcjtcbiAgICAgIG91dFsyICogaSArIDFdID0gTWF0aC5zaW4oYSkgKiByO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xuICB9O1xuICBjb25zdCBzdGFyID0gKHBvaW50czogbnVtYmVyLCBpbm5lcjogbnVtYmVyLCByb3QgPSAtTWF0aC5QSSAvIDIpID0+IHtcbiAgICBjb25zdCBvdXQgPSBuZXcgRmxvYXQzMkFycmF5KHBvaW50cyAqIDQpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcG9pbnRzICogMjsgaSsrKSB7XG4gICAgICBjb25zdCBhID0gcm90ICsgKGkgKiBNYXRoLlBJKSAvIHBvaW50cztcbiAgICAgIGNvbnN0IHIgPSBpICUgMiA9PT0gMCA/IDEgOiBpbm5lcjtcbiAgICAgIG91dFsyICogaV0gPSBNYXRoLmNvcyhhKSAqIHI7XG4gICAgICBvdXRbMiAqIGkgKyAxXSA9IE1hdGguc2luKGEpICogcjtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbiAgfTtcbiAgLy8gQSBwbHVzIGJ1aWx0IGFzIGEgMTItZ29uOiBhcm1zIG9mIGhhbGYtd2lkdGggdy5cbiAgY29uc3QgcGx1cyA9ICh3OiBudW1iZXIsIHJvdGF0ZTogYm9vbGVhbikgPT4ge1xuICAgIGNvbnN0IHB0cyA9IFtcbiAgICAgIFt3LCAtMV0sIFt3LCAtd10sIFsxLCAtd10sIFsxLCB3XSwgW3csIHddLCBbdywgMV0sXG4gICAgICBbLXcsIDFdLCBbLXcsIHddLCBbLTEsIHddLCBbLTEsIC13XSwgWy13LCAtd10sIFstdywgLTFdLFxuICAgIF07XG4gICAgY29uc3Qgb3V0ID0gbmV3IEZsb2F0MzJBcnJheShwdHMubGVuZ3RoICogMik7XG4gICAgY29uc3QgYyA9IE1hdGguU1FSVDFfMjtcbiAgICBwdHMuZm9yRWFjaCgoW3gsIHldLCBpKSA9PiB7XG4gICAgICBvdXRbMiAqIGldID0gcm90YXRlID8gKHggLSB5KSAqIGMgOiB4O1xuICAgICAgb3V0WzIgKiBpICsgMV0gPSByb3RhdGUgPyAoeCArIHkpICogYyA6IHk7XG4gICAgfSk7XG4gICAgcmV0dXJuIG91dDtcbiAgfTtcbiAgc3dpdGNoIChnbHlwaCkge1xuICAgIGNhc2UgJ2NpcmNsZSc6IHJldHVybiBwb2x5KDEyKTtcbiAgICBjYXNlICdzdGFyJzogcmV0dXJuIHN0YXIoNSwgMC40NSk7XG4gICAgY2FzZSAndHJpYW5nbGUnOiByZXR1cm4gcG9seSgzKTtcbiAgICBjYXNlICd0cmlhbmdsZS1kb3duJzogcmV0dXJuIHBvbHkoMywgTWF0aC5QSSAvIDIpO1xuICAgIGNhc2UgJ3NxdWFyZSc6IHJldHVybiBwb2x5KDQsIE1hdGguUEkgLyA0LCBNYXRoLlNRUlQyICogMC44KTtcbiAgICBjYXNlICdkaWFtb25kJzogcmV0dXJuIHBvbHkoNCwgLU1hdGguUEkgLyAyKTtcbiAgICBjYXNlICdoZXhhZ29uJzogcmV0dXJuIHBvbHkoNiwgMCk7XG4gICAgY2FzZSAncGVudGFnb24nOiByZXR1cm4gcG9seSg1KTtcbiAgICBjYXNlICdjcm9zcyc6IHJldHVybiBwbHVzKDAuMzIsIGZhbHNlKTtcbiAgICBjYXNlICd4JzogcmV0dXJuIHBsdXMoMC4yOCwgdHJ1ZSk7XG4gIH1cbn1cblxuLyoqIFRoZSBnbHlwaCBhIGdlbmUgZ2V0cyBieSBkZWZhdWx0OiBieSBpdHMgcG9zaXRpb24gaW4gdGhlIHNlbGVjdGVkIGxpc3QuICovXG5leHBvcnQgZnVuY3Rpb24gZGVmYXVsdEdseXBoRm9yKHNsb3Q6IG51bWJlcik6IFRyYW5zY3JpcHRHbHlwaCB7XG4gIHJldHVybiBUUkFOU0NSSVBUX0dMWVBIU1tzbG90ICUgVFJBTlNDUklQVF9HTFlQSFMubGVuZ3RoXTtcbn1cblxuLyoqXG4gKiBFeHBhbmQgcG9pbnQgbWFya2VycyBpbnRvIGdseXBoIHJpbmdzIGZvciBhIHNoYXBlcyBsYXllcjogZW50cnkgYGlgIGJlY29tZXMgYSBjb3B5IG9mXG4gKiBgZ2x5cGhzW2dlbmVbaV1dYCBzY2FsZWQgdG8gYHJhZGl1c1tpXWAgYW5kIGNlbnRyZWQgb24gYCh4W2ldLCB5W2ldKWAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnbHlwaFJpbmdzKFxuICB4OiBGbG9hdDMyQXJyYXksIHk6IEZsb2F0MzJBcnJheSwgcmFkaXVzOiBGbG9hdDMyQXJyYXksIGdseXBoT2Y6IChpOiBudW1iZXIpID0+IEZsb2F0MzJBcnJheSxcbik6IHsgY29vcmRzOiBGbG9hdDMyQXJyYXk7IG9mZnNldHM6IFVpbnQzMkFycmF5IH0ge1xuICBjb25zdCBuID0geC5sZW5ndGg7XG4gIGNvbnN0IG9mZnNldHMgPSBuZXcgVWludDMyQXJyYXkobiArIDEpO1xuICBsZXQgdG90YWwgPSAwO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIG9mZnNldHNbaV0gPSB0b3RhbDtcbiAgICB0b3RhbCArPSBnbHlwaE9mKGkpLmxlbmd0aCAvIDI7XG4gIH1cbiAgb2Zmc2V0c1tuXSA9IHRvdGFsO1xuICBjb25zdCBjb29yZHMgPSBuZXcgRmxvYXQzMkFycmF5KHRvdGFsICogMik7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgY29uc3QgZyA9IGdseXBoT2YoaSk7XG4gICAgY29uc3QgciA9IHJhZGl1c1tpXTtcbiAgICBsZXQgbyA9IG9mZnNldHNbaV0gKiAyO1xuICAgIGZvciAobGV0IGsgPSAwOyBrIDwgZy5sZW5ndGg7IGsgKz0gMikge1xuICAgICAgY29vcmRzW28rK10gPSB4W2ldICsgZ1trXSAqIHI7XG4gICAgICBjb29yZHNbbysrXSA9IHlbaV0gKyBnW2sgKyAxXSAqIHI7XG4gICAgfVxuICB9XG4gIHJldHVybiB7IGNvb3Jkcywgb2Zmc2V0cyB9O1xufVxuXG4vLyDilIDilIAgRGlzY3JldGUgY29sb3VyaW5nIHRocm91Z2ggYSBjb2xvcm1hcCDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIDilIBcblxuLyoqXG4gKiBBIHNoYXBlcyBsYXllciBjb2xvdXJzIHRocm91Z2ggYSBjb2xvcm1hcCBMVVQsIG5vdCBwZXItc2hhcGUgUkdCQS4gQSBjYXRlZ29yaWNhbFxuICogcGFsZXR0ZSBiZWNvbWVzIGEgcGllY2V3aXNlLWNvbnN0YW50IGNvbG9ybWFwOiBjYXRlZ29yeSBgY2Agb2YgYG5gIG93bnMgdGhlIGJhbmRcbiAqIGBbYy9uLCAoYysxKS9uKWAsIGFuZCBhIHNoYXBlIHRha2VzIHRoZSB2YWx1ZSBhdCBpdHMgYmFuZCdzIGNlbnRyZSwgc28gdGhlIExVVCdzXG4gKiBsaW5lYXIgZmlsdGVyaW5nIG5ldmVyIGJsZW5kcyB0d28gY2F0ZWdvcmllcy5cbiAqXG4gKiBSZXR1cm5zIHRoZSBzdG9wcyAobGluZWFyIDAuLjEgUkdCKSBhbmQgYSBmdW5jdGlvbiBtYXBwaW5nIGEgY2F0ZWdvcnkgY29kZSB0byB0aGVcbiAqIHZhbHVlIHRvIGhhbmQgdGhlIGxheWVyLiBgbWlzc2luZ2AgaXMgdGhlIGNvbG91ciBvZiB0aGUgZXh0cmEgYmFuZCB1c2VkIGZvciBcIm5vXG4gKiBjYXRlZ29yeVwiLlxuICovXG5leHBvcnQgZnVuY3Rpb24gZGlzY3JldGVDb2xvcm1hcFN0b3BzKFxuICByZ2I6IHJlYWRvbmx5IChyZWFkb25seSBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0pW10sIG1pc3Npbmc6IHJlYWRvbmx5IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXSxcbik6IHsgc3RvcHM6IHsgdDogbnVtYmVyOyBjb2xvcjogW251bWJlciwgbnVtYmVyLCBudW1iZXJdIH1bXTsgdmFsdWVPZjogKGNvZGU6IG51bWJlcikgPT4gbnVtYmVyIH0ge1xuICBjb25zdCBiYW5kcyA9IFsuLi5yZ2IsIG1pc3NpbmddO1xuICBjb25zdCBuID0gYmFuZHMubGVuZ3RoO1xuICBjb25zdCBzdG9wczogeyB0OiBudW1iZXI7IGNvbG9yOiBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0gfVtdID0gW107XG4gIGNvbnN0IGVwcyA9IDFlLTY7XG4gIGJhbmRzLmZvckVhY2goKGMsIGkpID0+IHtcbiAgICBjb25zdCBjb2xvcjogW251bWJlciwgbnVtYmVyLCBudW1iZXJdID0gW2NbMF0gLyAyNTUsIGNbMV0gLyAyNTUsIGNbMl0gLyAyNTVdO1xuICAgIHN0b3BzLnB1c2goeyB0OiBpIC8gbiArIChpID09PSAwID8gMCA6IGVwcyksIGNvbG9yIH0pO1xuICAgIHN0b3BzLnB1c2goeyB0OiAoaSArIDEpIC8gbiAtIChpID09PSBuIC0gMSA/IDAgOiBlcHMpLCBjb2xvciB9KTtcbiAgfSk7XG4gIGNvbnN0IG1pc3NpbmdDb2RlID0gbiAtIDE7XG4gIHJldHVybiB7XG4gICAgc3RvcHMsXG4gICAgdmFsdWVPZjogKGNvZGU6IG51bWJlcikgPT4gKChjb2RlIDwgMCB8fCBjb2RlID49IG1pc3NpbmdDb2RlID8gbWlzc2luZ0NvZGUgOiBjb2RlKSArIDAuNSkgLyBuLFxuICB9O1xufVxuXG4vLyDilIDilIAgRGVuc2l0eSByYXN0ZXIg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbi8qKlxuICogU2VwYXJhYmxlIEdhdXNzaWFuIGJsdXIgb2YgYSByb3ctbWFqb3IgcmFzdGVyLCBgc2lnbWFgIGluIHJhc3RlciBjZWxscy5cbiAqXG4gKiBBIHBlci1nZW5lIGNvdW50IHJhc3RlciBhdCAxMCDCtW0gaXMgbW9zdGx5IHplcm9zIGFuZCBvbmVzIOKAlCBkcmF3biBhcy1pcyBpdCBpcyBzcGVja2xlLFxuICogbm90IGEgZGVuc2l0eS4gQSDPgyBvZiBvbmUgdG8gdHdvIGNlbGxzICgxMOKAkzIwIMK1bSwgYWJvdXQgYSBjZWxsIGRpYW1ldGVyKSB0dXJucyBpdCBpbnRvXG4gKiBhIGZpZWxkIHRoYXQgcmVhZHMgYXMgdGVycml0b3J5IHdoaWxlIGtlZXBpbmcgc3RydWN0dXJlcyBhIGZldyBjZWxscyB3aWRlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc21vb3RoUmFzdGVyKHZhbHVlczogRmxvYXQzMkFycmF5LCByb3dzOiBudW1iZXIsIGNvbHM6IG51bWJlciwgc2lnbWE6IG51bWJlcik6IEZsb2F0MzJBcnJheSB7XG4gIGlmICghKHNpZ21hID4gMCkpIHJldHVybiB2YWx1ZXMuc2xpY2UoKTtcbiAgY29uc3QgciA9IE1hdGgubWF4KDEsIE1hdGguY2VpbChzaWdtYSAqIDMpKTtcbiAgY29uc3Qga2VybmVsID0gbmV3IEZsb2F0MzJBcnJheSgyICogciArIDEpO1xuICBsZXQgc3VtID0gMDtcbiAgZm9yIChsZXQgaSA9IC1yOyBpIDw9IHI7IGkrKykgc3VtICs9IChrZXJuZWxbaSArIHJdID0gTWF0aC5leHAoLShpICogaSkgLyAoMiAqIHNpZ21hICogc2lnbWEpKSk7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwga2VybmVsLmxlbmd0aDsgaSsrKSBrZXJuZWxbaV0gLz0gc3VtO1xuICBjb25zdCB0bXAgPSBuZXcgRmxvYXQzMkFycmF5KHZhbHVlcy5sZW5ndGgpO1xuICBjb25zdCBvdXQgPSBuZXcgRmxvYXQzMkFycmF5KHZhbHVlcy5sZW5ndGgpO1xuICBmb3IgKGxldCB5ID0gMDsgeSA8IHJvd3M7IHkrKykge1xuICAgIGNvbnN0IHJvdyA9IHkgKiBjb2xzO1xuICAgIGZvciAobGV0IHggPSAwOyB4IDwgY29sczsgeCsrKSB7XG4gICAgICBsZXQgYWNjID0gMDtcbiAgICAgIGZvciAobGV0IGsgPSAtcjsgayA8PSByOyBrKyspIHtcbiAgICAgICAgY29uc3QgeHggPSB4ICsgaztcbiAgICAgICAgaWYgKHh4ID49IDAgJiYgeHggPCBjb2xzKSBhY2MgKz0gdmFsdWVzW3JvdyArIHh4XSAqIGtlcm5lbFtrICsgcl07XG4gICAgICB9XG4gICAgICB0bXBbcm93ICsgeF0gPSBhY2M7XG4gICAgfVxuICB9XG4gIGZvciAobGV0IHkgPSAwOyB5IDwgcm93czsgeSsrKSB7XG4gICAgZm9yIChsZXQgeCA9IDA7IHggPCBjb2xzOyB4KyspIHtcbiAgICAgIGxldCBhY2MgPSAwO1xuICAgICAgZm9yIChsZXQgayA9IC1yOyBrIDw9IHI7IGsrKykge1xuICAgICAgICBjb25zdCB5eSA9IHkgKyBrO1xuICAgICAgICBpZiAoeXkgPj0gMCAmJiB5eSA8IHJvd3MpIGFjYyArPSB0bXBbeXkgKiBjb2xzICsgeF0gKiBrZXJuZWxbayArIHJdO1xuICAgICAgfVxuICAgICAgb3V0W3kgKiBjb2xzICsgeF0gPSBhY2M7XG4gICAgfVxuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbi8qKlxuICogQ29sb3VyIGEgZGVuc2l0eSByYXN0ZXIgYXMgUkdCQSBieXRlczogbG9nLXNjYWxlZCwgd2luZG93ZWQgYXQgYSBoaWdoIHBlcmNlbnRpbGUgb2YgdGhlXG4gKiBub24temVybyB2YWx1ZXMsIGFuZCBmYWRlZCBpbiBmcm9tIHRyYW5zcGFyZW50IHNvIGVtcHR5IHRpc3N1ZSBzaG93cyB3aGF0IGlzIHVuZGVyIGl0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gY29sb3JEZW5zaXR5KFxuICB2YWx1ZXM6IEZsb2F0MzJBcnJheSwgbHV0OiByZWFkb25seSAocmVhZG9ubHkgW251bWJlciwgbnVtYmVyLCBudW1iZXJdKVtdLCBvcGFjaXR5OiBudW1iZXIsXG4gIHsgbG9nID0gdHJ1ZSwgcGVyY2VudGlsZSA9IDAuOTk1IH0gPSB7fSxcbik6IFVpbnQ4QXJyYXkge1xuICBjb25zdCBuID0gdmFsdWVzLmxlbmd0aDtcbiAgY29uc3QgdCA9IGxvZyA/IHZhbHVlcy5tYXAoKHYpID0+IE1hdGgubG9nMXAoTWF0aC5tYXgoMCwgdikpKSA6IHZhbHVlcztcbiAgY29uc3QgcG9zaXRpdmU6IG51bWJlcltdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSBpZiAodFtpXSA+IDApIHBvc2l0aXZlLnB1c2godFtpXSk7XG4gIHBvc2l0aXZlLnNvcnQoKGEsIGIpID0+IGEgLSBiKTtcbiAgY29uc3QgYXQgPSBNYXRoLm1pbihwb3NpdGl2ZS5sZW5ndGggLSAxLCBNYXRoLmZsb29yKHBlcmNlbnRpbGUgKiBwb3NpdGl2ZS5sZW5ndGgpKTtcbiAgY29uc3QgaGkgPSBwb3NpdGl2ZS5sZW5ndGggPyBwb3NpdGl2ZVthdF0gOiAxO1xuICBjb25zdCByZ2JhID0gbmV3IFVpbnQ4QXJyYXkobiAqIDQpO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIGNvbnN0IGYgPSBNYXRoLm1pbigxLCB0W2ldIC8gKGhpIHx8IDEpKTtcbiAgICBpZiAoZiA8IDAuMDIpIGNvbnRpbnVlO1xuICAgIGNvbnN0IGMgPSBsdXRbTWF0aC5taW4obHV0Lmxlbmd0aCAtIDEsIE1hdGgucm91bmQoZiAqIChsdXQubGVuZ3RoIC0gMSkpKV07XG4gICAgcmdiYVs0ICogaV0gPSBjWzBdO1xuICAgIHJnYmFbNCAqIGkgKyAxXSA9IGNbMV07XG4gICAgcmdiYVs0ICogaSArIDJdID0gY1syXTtcbiAgICByZ2JhWzQgKiBpICsgM10gPSBNYXRoLnJvdW5kKDI1NSAqIG9wYWNpdHkgKiBNYXRoLnBvdyhmLCAwLjYpKTtcbiAgfVxuICByZXR1cm4gcmdiYTtcbn1cblxuLy8g4pSA4pSAIEFsbC1nZW5lIHRyYW5zY3JpcHRzOiBncm91cGluZyB1bmRlciBhIG1hcmtlciBidWRnZXQg4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbi8qKiBTbWFsbGVzdCBvbi1zY3JlZW4gc3BhY2luZyBiZXR3ZWVuIGdyb3VwcywgaW4gcHgg4oCUIGJlbG93IGl0IGdyb3VwcyByZWFkIGFzIG5vaXNlLiAqL1xuZXhwb3J0IGNvbnN0IEdST1VQX01JTl9TUEFDSU5HX1BYID0gMTQ7XG5cbi8qKiBBcmVhIG9mIGByZWN0YCBpbnNpZGUgYGJvdW5kc2AgKHRoZSB3aG9sZSByZWN0IHdoZW4gdGhlcmUgYXJlIG5vbmUpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHZpc2libGVBcmVhKHJlY3Q6IERhdGFSZWN0LCBib3VuZHM/OiBTcGF0aWFsQm91bmRzIHwgbnVsbCk6IG51bWJlciB7XG4gIGNvbnN0IHgwID0gYm91bmRzID8gTWF0aC5tYXgocmVjdC54MCwgYm91bmRzWzBdKSA6IHJlY3QueDA7XG4gIGNvbnN0IHkwID0gYm91bmRzID8gTWF0aC5tYXgocmVjdC55MCwgYm91bmRzWzFdKSA6IHJlY3QueTA7XG4gIGNvbnN0IHgxID0gYm91bmRzID8gTWF0aC5taW4ocmVjdC54MSwgYm91bmRzWzJdKSA6IHJlY3QueDE7XG4gIGNvbnN0IHkxID0gYm91bmRzID8gTWF0aC5taW4ocmVjdC55MSwgYm91bmRzWzNdKSA6IHJlY3QueTE7XG4gIHJldHVybiBNYXRoLm1heCgwLCB4MSAtIHgwKSAqIE1hdGgubWF4KDAsIHkxIC0geTApO1xufVxuXG5leHBvcnQgdHlwZSBBbGxHZW5lc1BsYW4gPSB7IGtpbmQ6ICdpbmRpdmlkdWFsJyB9IHwgeyBraW5kOiAnYmlucyc7IGxldmVsOiBudW1iZXIgfSB8IHsga2luZDogJ25vbmUnIH07XG5cbi8qKlxuICogSG93IHRvIGRyYXcgZXZlcnkgdHJhbnNjcmlwdCBpbiB2aWV3IHdpdGhvdXQgZXhjZWVkaW5nIGBidWRnZXRgIG1hcmtlcnMuXG4gKlxuICogLSBUaGUgdHJhbnNjcmlwdHMgdGhlbXNlbHZlcywgb25jZSB0aGUgZXN0aW1hdGVkIGNvdW50IGluIHZpZXcgZml0cyB0aGUgYnVkZ2V0LlxuICogLSBPdGhlcndpc2UgdGhlIGZpbmVzdCBweXJhbWlkIGxldmVsIHdob3NlIGJpbnMgYXJlIGF0IGxlYXN0IGBtaW5TcGFjaW5nUHhgIGFwYXJ0IG9uXG4gKiAgIHNjcmVlbiBhbmQgbnVtYmVyIG5vIG1vcmUgdGhhbiB0aGUgYnVkZ2V0IOKAlCBncm91cHMgYmlnIGVub3VnaCB0byByZWFkLCBmZXcgZW5vdWdoXG4gKiAgIHRvIGRyYXcuXG4gKlxuICogVGhlIGNvdW50IGluIHZpZXcgaXMgZXN0aW1hdGVkIGZyb20gdGhlIGF2ZXJhZ2UgZGVuc2l0eSwgd2hpY2ggb3Zlci0gb3IgdW5kZXItc2hvb3RzXG4gKiBsb2NhbGx5OyB0aGUgcmVuZGVyZXIgc3RpbGwgY2FwcyB3aGF0IGl0IGRyYXdzLCBzbyBhbiBlc3RpbWF0ZSBpcyBlbm91Z2ggdG8gY2hvb3NlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gYWxsR2VuZXNQbGFuKG86IHtcbiAgcmVjdDogRGF0YVJlY3Q7IGJvdW5kczogU3BhdGlhbEJvdW5kczsgdG90YWw6IG51bWJlcjsgcHhQZXJVbml0OiBudW1iZXI7XG4gIGxldmVsczogcmVhZG9ubHkgeyBiaW5TaXplOiBudW1iZXIgfVtdOyBidWRnZXQ6IG51bWJlcjsgY2FuSW5kaXZpZHVhbDogYm9vbGVhbjtcbiAgbWluU3BhY2luZ1B4PzogbnVtYmVyO1xufSk6IEFsbEdlbmVzUGxhbiB7XG4gIGNvbnN0IGFyZWEgPSB2aXNpYmxlQXJlYShvLnJlY3QsIG8uYm91bmRzKTtcbiAgaWYgKCEoYXJlYSA+IDApKSByZXR1cm4geyBraW5kOiAnbm9uZScgfTtcbiAgY29uc3QgYiA9IG8uYm91bmRzO1xuICBjb25zdCBkZW5zaXR5ID0gby50b3RhbCAvIE1hdGgubWF4KDEsIChiWzJdIC0gYlswXSkgKiAoYlszXSAtIGJbMV0pKTtcbiAgaWYgKG8uY2FuSW5kaXZpZHVhbCAmJiBkZW5zaXR5ICogYXJlYSA8PSBvLmJ1ZGdldCkgcmV0dXJuIHsga2luZDogJ2luZGl2aWR1YWwnIH07XG4gIGlmICghby5sZXZlbHMubGVuZ3RoKSByZXR1cm4geyBraW5kOiAnbm9uZScgfTtcbiAgY29uc3Qgc3BhY2luZyA9IG8ubWluU3BhY2luZ1B4ID8/IEdST1VQX01JTl9TUEFDSU5HX1BYO1xuICBmb3IgKGxldCBsID0gMDsgbCA8IG8ubGV2ZWxzLmxlbmd0aDsgbCsrKSB7XG4gICAgY29uc3QgYmluID0gby5sZXZlbHNbbF0uYmluU2l6ZTtcbiAgICAvLyBUaXNzdWUgcmFyZWx5IGZpbGxzIHRoZSB2aWV3OyAwLjcgb2YgdGhlIGJpbnMgb2NjdXBpZWQgaXMgYSBmYWlyIGd1ZXNzLlxuICAgIGlmIChiaW4gKiBvLnB4UGVyVW5pdCA+PSBzcGFjaW5nICYmIChhcmVhIC8gKGJpbiAqIGJpbikpICogMC43IDw9IG8uYnVkZ2V0KSB7XG4gICAgICByZXR1cm4geyBraW5kOiAnYmlucycsIGxldmVsOiBsIH07XG4gICAgfVxuICB9XG4gIHJldHVybiB7IGtpbmQ6ICdiaW5zJywgbGV2ZWw6IG8ubGV2ZWxzLmxlbmd0aCAtIDEgfTtcbn1cblxuLyoqXG4gKiBEaWFtZXRlciBpbiBweCBvZiBhIGdyb3VwIG9mIGBjb3VudGAgdHJhbnNjcmlwdHMgaW4gYSBiaW4gYGJpblB4YCB3aWRlLCB3aGVyZVxuICogYHJlZkNvdW50YCBpcyBhIHR5cGljYWwgYnVzeSBiaW4gaW4gdmlldyAoaXRzIDk1dGggcGVyY2VudGlsZSkuXG4gKlxuICogQXJlYSBncm93cyB3aXRoIHRoZSBjb3VudCDigJQgYSBiaW4gd2l0aCBhIHF1YXJ0ZXIgb2YgdGhlIHRyYW5zY3JpcHRzIGdldHMgaGFsZiB0aGVcbiAqIGRpYW1ldGVyIOKAlCBiZXR3ZWVuIGEgdGhpcmQgb2YgdGhlIGJpbiAoc28gYSBzcGFyc2UgYmluIGlzIHN0aWxsIHZpc2libGUpIGFuZCBhIGxpdHRsZVxuICogb3ZlciB0aGUgZnVsbCBiaW4gKHNvIGRlbnNlIG5laWdoYm91cnMganVzdCB0b3VjaCByYXRoZXIgdGhhbiBwaWxlIHVwKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdyb3VwZWRNYXJrZXJQeChjb3VudDogbnVtYmVyLCByZWZDb3VudDogbnVtYmVyLCBiaW5QeDogbnVtYmVyLCBzY2FsZSA9IDEpOiBudW1iZXIge1xuICBjb25zdCBmID0gTWF0aC5zcXJ0KE1hdGgubWluKDEsIGNvdW50IC8gTWF0aC5tYXgoMSwgcmVmQ291bnQpKSk7XG4gIGNvbnN0IGQgPSBiaW5QeCAqICgwLjM1ICsgMC43NSAqIGYpICogc2NhbGU7XG4gIHJldHVybiBNYXRoLm1heChUUkFOU0NSSVBUX01JTl9QWCAqIHNjYWxlLCBNYXRoLm1pbihkLCBiaW5QeCAqIDEuMiAqIE1hdGgubWF4KHNjYWxlLCAxKSkpO1xufVxuXG4vKiogVGhlIGBwYCBxdWFudGlsZSAoMC4uMSkgb2YgYSBjb3VudCB2ZWN0b3Ig4oCUIGEgc2FtcGxlIG9mIGl0IGZvciBsYXJnZSB2ZWN0b3JzLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHF1YW50aWxlT2YodmFsdWVzOiBBcnJheUxpa2U8bnVtYmVyPiwgcDogbnVtYmVyKTogbnVtYmVyIHtcbiAgY29uc3QgbiA9IHZhbHVlcy5sZW5ndGg7XG4gIGlmICghbikgcmV0dXJuIDA7XG4gIGNvbnN0IHN0ZXAgPSBNYXRoLm1heCgxLCBNYXRoLmZsb29yKG4gLyA0MDk2KSk7XG4gIGNvbnN0IHNhbXBsZTogbnVtYmVyW10gPSBbXTtcbiAgZm9yIChsZXQgaSA9IDA7IGkgPCBuOyBpICs9IHN0ZXApIHNhbXBsZS5wdXNoKHZhbHVlc1tpXSk7XG4gIHNhbXBsZS5zb3J0KChhLCBiKSA9PiBhIC0gYik7XG4gIHJldHVybiBzYW1wbGVbTWF0aC5taW4oc2FtcGxlLmxlbmd0aCAtIDEsIE1hdGguZmxvb3IocCAqIHNhbXBsZS5sZW5ndGgpKV07XG59XG5cbi8qKiB7QGxpbmsgdGlsZXNJblJlY3R9IGZvciBhIGdyaWQgd2hvc2UgdGlsZSAoMCwgMCkgc3RhcnRzIGF0IGBvcmlnaW5gLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRpbGVzSW5SZWN0RnJvbShcbiAgb3JpZ2luOiByZWFkb25seSBbbnVtYmVyLCBudW1iZXJdLCByZWN0OiBEYXRhUmVjdCwgbGV2ZWw6IG51bWJlcixcbiAgbGV2ZWxzOiByZWFkb25seSBTcGF0aWFsVGlsZUxldmVsW10sIGJvdW5kcz86IFNwYXRpYWxCb3VuZHMgfCBudWxsLCBsaW1pdCA9IEluZmluaXR5LFxuKTogVGlsZUtleVtdIHtcbiAgY29uc3QgW294LCBveV0gPSBvcmlnaW47XG4gIGNvbnN0IHNoaWZ0ZWQgPSB7IHgwOiByZWN0LngwIC0gb3gsIHkwOiByZWN0LnkwIC0gb3ksIHgxOiByZWN0LngxIC0gb3gsIHkxOiByZWN0LnkxIC0gb3kgfTtcbiAgY29uc3QgYjogU3BhdGlhbEJvdW5kcyB8IG51bGwgPSBib3VuZHMgPyBbYm91bmRzWzBdIC0gb3gsIGJvdW5kc1sxXSAtIG95LCBib3VuZHNbMl0gLSBveCwgYm91bmRzWzNdIC0gb3ldIDogbnVsbDtcbiAgcmV0dXJuIHRpbGVzSW5SZWN0KHNoaWZ0ZWQsIGxldmVsLCBsZXZlbHMsIGIsIGxpbWl0KTtcbn1cblxuLyoqIEEgZGVuc2l0eSB3aW5kb3cgZnJvbSB0aGUgbm9uLWVtcHR5IGJpbnM6IDFzdCB0byA5OXRoIHBlcmNlbnRpbGUuICovXG5leHBvcnQgZnVuY3Rpb24gZGVuc2l0eUF1dG9SYW5nZSh2YWx1ZXM6IEFycmF5TGlrZTxudW1iZXI+KTogW251bWJlciwgbnVtYmVyXSB7XG4gIGNvbnN0IHBvc2l0aXZlOiBudW1iZXJbXSA9IFtdO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IHZhbHVlcy5sZW5ndGg7IGkrKykgaWYgKHZhbHVlc1tpXSA+IDApIHBvc2l0aXZlLnB1c2godmFsdWVzW2ldKTtcbiAgaWYgKCFwb3NpdGl2ZS5sZW5ndGgpIHJldHVybiBbMCwgMV07XG4gIHBvc2l0aXZlLnNvcnQoKGEsIGIpID0+IGEgLSBiKTtcbiAgY29uc3QgYXQgPSAocDogbnVtYmVyKSA9PiBwb3NpdGl2ZVtNYXRoLm1pbihwb3NpdGl2ZS5sZW5ndGggLSAxLCBNYXRoLmZsb29yKHAgKiBwb3NpdGl2ZS5sZW5ndGgpKV07XG4gIGNvbnN0IGxvID0gYXQoMC4wMSk7XG4gIGNvbnN0IGhpID0gYXQoMC45OSk7XG4gIHJldHVybiBoaSA+IGxvID8gW2xvLCBoaV0gOiBbMCwgaGkgfHwgMV07XG59XG5cbi8qKlxuICogQ29sb3VyIGRlbnNpdHkgYmlucyB0aHJvdWdoIGBsdXRgIG92ZXIgdGhlIHdpbmRvdyBgW2xvLCBoaV1gIOKAlCBYZW5pdW0gRXhwbG9yZXInc1xuICogXCJzY2FsZSB0aHJlc2hvbGRcIi4gQmlucyBhdCBvciBiZWxvdyBgbG9gIGFyZSB0cmFuc3BhcmVudCwgc28gZW1wdHkgdGlzc3VlIHNob3dzIHRoZVxuICogaW1hZ2UgdW5kZXIgaXQ7IGJpbnMgYXQgb3IgYWJvdmUgYGhpYCBzYXR1cmF0ZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNvbG9yRGVuc2l0eVdpbmRvdyhcbiAgdmFsdWVzOiBBcnJheUxpa2U8bnVtYmVyPiwgbHV0OiByZWFkb25seSAocmVhZG9ubHkgW251bWJlciwgbnVtYmVyLCBudW1iZXJdKVtdLFxuICBvcGFjaXR5OiBudW1iZXIsIGxvOiBudW1iZXIsIGhpOiBudW1iZXIsXG4pOiBVaW50OEFycmF5IHtcbiAgY29uc3QgbiA9IHZhbHVlcy5sZW5ndGg7XG4gIGNvbnN0IHJnYmEgPSBuZXcgVWludDhBcnJheShuICogNCk7XG4gIGNvbnN0IHNwYW4gPSBoaSA+IGxvID8gaGkgLSBsbyA6IDE7XG4gIGNvbnN0IGEgPSBNYXRoLnJvdW5kKDI1NSAqIG9wYWNpdHkpO1xuICBmb3IgKGxldCBpID0gMDsgaSA8IG47IGkrKykge1xuICAgIGNvbnN0IHYgPSB2YWx1ZXNbaV07XG4gICAgaWYgKCEodiA+IGxvKSkgY29udGludWU7XG4gICAgY29uc3QgZiA9IE1hdGgubWluKDEsICh2IC0gbG8pIC8gc3Bhbik7XG4gICAgY29uc3QgYyA9IGx1dFtNYXRoLm1pbihsdXQubGVuZ3RoIC0gMSwgTWF0aC5yb3VuZChmICogKGx1dC5sZW5ndGggLSAxKSkpXTtcbiAgICByZ2JhWzQgKiBpXSA9IGNbMF07XG4gICAgcmdiYVs0ICogaSArIDFdID0gY1sxXTtcbiAgICByZ2JhWzQgKiBpICsgMl0gPSBjWzJdO1xuICAgIHJnYmFbNCAqIGkgKyAzXSA9IGE7XG4gIH1cbiAgcmV0dXJuIHJnYmE7XG59XG5cbi8qKlxuICogSW5mZXJubyAobWF0cGxvdGxpYiksIGFzIGFuIGlubGluZSBgW3N0b3AsIGNvbG91cl1gIHNjYWxlOiB0aGUgZGVuc2l0eSBtYXAncyBkZWZhdWx0LFxuICogYXMgaW4gWGVuaXVtIEV4cGxvcmVyLiBJbmxpbmUgYmVjYXVzZSB0aGUgY29sb3JtYXAgdHJlZSdzIGBJTkZFUk5PX0xVVGAga2V5IGlzIHJlc29sdmVkXG4gKiBhdCBydW50aW1lIGJ5IHRoZSBzdG9yZSwgd2hpY2ggdGhlIHJlbmRlcmVyIGRvZXMgbm90IHNlZS5cbiAqL1xuZXhwb3J0IGNvbnN0IElORkVSTk9fU0NBTEU6IFtudW1iZXIsIHN0cmluZ11bXSA9IFtcbiAgWzAsICcjMDAwMDA0J10sIFswLjEyNSwgJyMxYjBjNDEnXSwgWzAuMjUsICcjNGEwYzZiJ10sIFswLjM3NSwgJyM3ODFjNmQnXSwgWzAuNSwgJyNhNTJjNjAnXSxcbiAgWzAuNjI1LCAnI2NmNDQ0NiddLCBbMC43NSwgJyNlZDY5MjUnXSwgWzAuODc1LCAnI2ZiOWIwNiddLCBbMSwgJyNmY2ZmYTQnXSxcbl07XG4iXX0=