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