@jax-data-science/sci-image-visualizer 0.9.0 → 0.10.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 (131) hide show
  1. package/esm2022/index.mjs +7 -1
  2. package/esm2022/lib/contracts/image.contract.mjs +1 -1
  3. package/esm2022/lib/contracts/region-editor-api.contract.mjs +1 -1
  4. package/esm2022/lib/contracts/region-store.contract.mjs +1 -1
  5. package/esm2022/lib/contracts/section-view.contract.mjs +2 -0
  6. package/esm2022/lib/contracts/visualizer.contract.mjs +1 -1
  7. package/esm2022/lib/contracts/viz-config.mjs +1 -1
  8. package/esm2022/lib/geometry/loft.mjs +128 -0
  9. package/esm2022/lib/geometry/polylabel.mjs +156 -0
  10. package/esm2022/lib/geometry/reconstruct.mjs +315 -0
  11. package/esm2022/lib/geometry/reslice-image.mjs +57 -0
  12. package/esm2022/lib/geometry/section.mjs +215 -0
  13. package/esm2022/lib/implementations/napari-js/napari-loading-badge.mjs +11 -7
  14. package/esm2022/lib/implementations/napari-js/napari-loading-state.mjs +20 -3
  15. package/esm2022/lib/implementations/napari-js/napari-region-mesh-pointer.mjs +100 -0
  16. package/esm2022/lib/implementations/napari-js/napari-region-overlay.mjs +28 -5
  17. package/esm2022/lib/implementations/napari-js/napari-scene.mjs +1 -1
  18. package/esm2022/lib/implementations/napari-js/napari-spatial-hover.mjs +9 -2
  19. package/esm2022/lib/implementations/napari-js/napari-tool-bridge.mjs +5 -2
  20. package/esm2022/lib/implementations/napari-js/napari-visualizer.service.mjs +81 -1
  21. package/esm2022/lib/implementations/napari-js/napari-volume-region-meshes.mjs +129 -0
  22. package/esm2022/lib/implementations/napari-js/napari-volume-scene.mjs +115 -4
  23. package/esm2022/lib/implementations/napari-js/napari-volume-slice-planes.mjs +103 -0
  24. package/esm2022/lib/implementations/napari-js/region-overlay/region-svg-renderer.mjs +15 -3
  25. package/esm2022/lib/implementations/osd/osd-region-overlay-draw.mjs +18 -7
  26. package/esm2022/lib/implementations/osd/osd-region-overlay.mjs +38 -8
  27. package/esm2022/lib/implementations/tile-server/tile-protocol.mjs +1 -1
  28. package/esm2022/lib/models/class-preset.mjs +1 -1
  29. package/esm2022/lib/models/polygon-factory.mjs +17 -1
  30. package/esm2022/lib/models/region-geojson.mjs +44 -6
  31. package/esm2022/lib/models/region.mjs +1 -1
  32. package/esm2022/lib/region-editor/class-tree/class-tree.component.mjs +156 -0
  33. package/esm2022/lib/region-editor/class-tree/class-tree.mjs +108 -0
  34. package/esm2022/lib/region-editor/classes-panel/classes-panel.component.mjs +77 -13
  35. package/esm2022/lib/region-editor/region-editor.component.mjs +527 -42
  36. package/esm2022/lib/region-editor/region-metrics.mjs +20 -2
  37. package/esm2022/lib/region-editor/region-persistence.service.mjs +36 -10
  38. package/esm2022/lib/region-editor/region-table/region-table.component.mjs +24 -8
  39. package/esm2022/lib/region-overlay/region-geometry.mjs +3 -3
  40. package/esm2022/lib/region-overlay/region-source-layer.mjs +378 -0
  41. package/esm2022/lib/region-overlay/region-style.mjs +97 -0
  42. package/esm2022/lib/region-source/http-region-source.mjs +104 -0
  43. package/esm2022/lib/region-source/region-source-ops.mjs +53 -0
  44. package/esm2022/lib/region-source/region-source-worker.mjs +10 -0
  45. package/esm2022/lib/region-source/region-source.mjs +67 -0
  46. package/esm2022/lib/region-source/region-tiles.mjs +708 -0
  47. package/esm2022/lib/region-source/worker-region-source.mjs +229 -0
  48. package/esm2022/lib/routing-visualizer.service.mjs +418 -22
  49. package/esm2022/lib/section-pane/section-pane.component.mjs +299 -0
  50. package/esm2022/lib/store/class-color.util.mjs +10 -5
  51. package/esm2022/lib/store/class-signatures.mjs +63 -0
  52. package/esm2022/lib/store/region-scope-cache.mjs +5 -1
  53. package/esm2022/lib/store/region-source-scope.mjs +171 -0
  54. package/esm2022/lib/store/region-store.service.mjs +724 -12
  55. package/esm2022/lib/store/visualizer-store.service.mjs +33 -6
  56. package/esm2022/lib/toolbar/region-tools/region-tools.component.mjs +8 -2
  57. package/esm2022/lib/toolbar/stack-controls/stack-controls.component.mjs +55 -15
  58. package/esm2022/lib/toolbar/toolbar.component.mjs +19 -5
  59. package/esm2022/lib/visualizer/region-load.mjs +67 -4
  60. package/esm2022/lib/visualizer/volume-sections.mjs +175 -0
  61. package/esm2022/lib/visualizer.component.mjs +128 -6
  62. package/fesm2022/{jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs → jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs} +7239 -1153
  63. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-BKQhpbHv.mjs.map +1 -0
  64. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs → jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs} +4 -4
  65. package/fesm2022/{jax-data-science-sci-image-visualizer-onnx-sam-session-Bkujqg7m.mjs.map → jax-data-science-sci-image-visualizer-onnx-sam-session-z1IN-F7w.mjs.map} +1 -1
  66. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs +12 -0
  67. package/fesm2022/jax-data-science-sci-image-visualizer-region-source-worker-CAqBjM5L.mjs.map +1 -0
  68. package/fesm2022/jax-data-science-sci-image-visualizer.mjs +3 -3
  69. package/fesm2022/region-source.worker.js +1067 -0
  70. package/index.d.ts +6 -0
  71. package/lib/contracts/image.contract.d.ts +4 -0
  72. package/lib/contracts/region-editor-api.contract.d.ts +84 -0
  73. package/lib/contracts/region-store.contract.d.ts +22 -0
  74. package/lib/contracts/section-view.contract.d.ts +44 -0
  75. package/lib/contracts/visualizer.contract.d.ts +10 -0
  76. package/lib/contracts/viz-config.d.ts +8 -0
  77. package/lib/geometry/loft.d.ts +22 -0
  78. package/lib/geometry/polylabel.d.ts +23 -0
  79. package/lib/geometry/reconstruct.d.ts +54 -0
  80. package/lib/geometry/reslice-image.d.ts +33 -0
  81. package/lib/geometry/section.d.ts +52 -0
  82. package/lib/implementations/napari-js/napari-loading-badge.d.ts +4 -2
  83. package/lib/implementations/napari-js/napari-loading-state.d.ts +8 -1
  84. package/lib/implementations/napari-js/napari-region-mesh-pointer.d.ts +32 -0
  85. package/lib/implementations/napari-js/napari-region-overlay.d.ts +6 -1
  86. package/lib/implementations/napari-js/napari-scene.d.ts +33 -0
  87. package/lib/implementations/napari-js/napari-spatial-hover.d.ts +3 -1
  88. package/lib/implementations/napari-js/napari-visualizer.service.d.ts +48 -0
  89. package/lib/implementations/napari-js/napari-volume-region-meshes.d.ts +66 -0
  90. package/lib/implementations/napari-js/napari-volume-scene.d.ts +45 -1
  91. package/lib/implementations/napari-js/napari-volume-slice-planes.d.ts +43 -0
  92. package/lib/implementations/osd/osd-region-overlay-draw.d.ts +4 -3
  93. package/lib/implementations/osd/osd-region-overlay.d.ts +10 -3
  94. package/lib/implementations/tile-server/tile-protocol.d.ts +3 -0
  95. package/lib/models/class-preset.d.ts +7 -0
  96. package/lib/models/polygon-factory.d.ts +5 -0
  97. package/lib/models/region-geojson.d.ts +40 -0
  98. package/lib/models/region.d.ts +19 -0
  99. package/lib/region-editor/class-tree/class-tree.component.d.ts +78 -0
  100. package/lib/region-editor/class-tree/class-tree.d.ts +31 -0
  101. package/lib/region-editor/classes-panel/classes-panel.component.d.ts +36 -6
  102. package/lib/region-editor/region-editor.component.d.ts +133 -17
  103. package/lib/region-editor/region-metrics.d.ts +8 -0
  104. package/lib/region-editor/region-persistence.service.d.ts +12 -4
  105. package/lib/region-editor/region-table/region-table.component.d.ts +10 -4
  106. package/lib/region-overlay/region-geometry.d.ts +4 -3
  107. package/lib/region-overlay/region-source-layer.d.ts +96 -0
  108. package/lib/region-overlay/region-style.d.ts +52 -0
  109. package/lib/region-source/http-region-source.d.ts +45 -0
  110. package/lib/region-source/region-source-ops.d.ts +89 -0
  111. package/lib/region-source/region-source-worker.d.ts +7 -0
  112. package/lib/region-source/region-source.d.ts +82 -0
  113. package/lib/region-source/region-tiles.d.ts +289 -0
  114. package/lib/region-source/worker-region-source.d.ts +65 -0
  115. package/lib/routing-visualizer.service.d.ts +138 -1
  116. package/lib/section-pane/section-pane.component.d.ts +47 -0
  117. package/lib/store/class-color.util.d.ts +6 -3
  118. package/lib/store/class-signatures.d.ts +11 -0
  119. package/lib/store/region-scope-cache.d.ts +2 -0
  120. package/lib/store/region-source-scope.d.ts +68 -0
  121. package/lib/store/region-store.service.d.ts +206 -2
  122. package/lib/store/visualizer-store.service.d.ts +10 -0
  123. package/lib/toolbar/region-tools/region-tools.component.d.ts +3 -1
  124. package/lib/toolbar/stack-controls/stack-controls.component.d.ts +20 -9
  125. package/lib/toolbar/toolbar.component.d.ts +9 -2
  126. package/lib/visualizer/region-load.d.ts +23 -4
  127. package/lib/visualizer/volume-sections.d.ts +64 -0
  128. package/lib/visualizer.component.d.ts +31 -0
  129. package/package.json +2 -2
  130. package/src/lib/assets/slice.svg +23 -0
  131. package/fesm2022/jax-data-science-sci-image-visualizer-jax-data-science-sci-image-visualizer-Csxlnq7I.mjs.map +0 -1
@@ -0,0 +1,708 @@
1
+ /**
2
+ * The pure core of a tiled region source: a large GeoJSON region set cut into tiles per level
3
+ * of detail, the outlines simplified per level, so a view only ever holds and draws what is on
4
+ * screen at the detail the zoom can show.
5
+ *
6
+ * Levels: level 0 is exact; a level-k tile covers `tileSize · 2ᵏ` image pixels and its outlines
7
+ * are simplified (Douglas–Peucker) to `2ᵏ⁻¹` image pixels — half to one screen pixel at the zooms
8
+ * that pick that level ({@link regionLevelFor}). A feature under `2ᵏ` image pixels (one to two
9
+ * screen pixels there) is left out of the level. A tile holds the WHOLE simplified feature (not
10
+ * clipped) for every feature whose box meets it, so a view de-duplicates features by id, and at
11
+ * level 0 the tiles in view hold the exact outline of everything visible.
12
+ *
13
+ * No DOM, no Angular: the same code runs in the region-source worker and, where workers do not
14
+ * exist, on the main thread.
15
+ */
16
+ import { rgbToHex } from '../contracts/color';
17
+ import { simplifyRing } from '../geometry/ring';
18
+ import { polylabel } from '../geometry/polylabel';
19
+ import { ringsArea } from '../geometry/reconstruct';
20
+ /** Edge of a level-0 tile, in image pixels. */
21
+ export const REGION_TILE_SIZE = 512;
22
+ /**
23
+ * The level whose tiles suit a zoom of `pxPerImagePx` screen pixels per image pixel: exact (0)
24
+ * at 1:1 and closer, else level k for zooms in [2⁻ᵏ, 2¹⁻ᵏ), where its tolerance is half to one
25
+ * screen pixel and the features it leaves out are under one or two.
26
+ */
27
+ export function regionLevelFor(pxPerImagePx, levels) {
28
+ if (!(pxPerImagePx > 0) || levels <= 1)
29
+ return 0;
30
+ const level = Math.ceil(-Math.log2(pxPerImagePx) - 1e-9);
31
+ return Math.max(0, Math.min(levels - 1, level));
32
+ }
33
+ /** Simplification tolerance of a level, in image pixels (0 = exact). */
34
+ export function levelTolerance(level) {
35
+ return level <= 0 ? 0 : 2 ** (level - 1);
36
+ }
37
+ /** Features smaller than this (their box's longer side, image pixels) are left out of a level. */
38
+ export function levelMinExtent(level) {
39
+ return level <= 0 ? 0 : 2 ** level;
40
+ }
41
+ /** Tile edge of a level, in image pixels. */
42
+ export function levelTileSize(level, tileSize = REGION_TILE_SIZE) {
43
+ return tileSize * 2 ** level;
44
+ }
45
+ /**
46
+ * Tiles of `level` that meet `rect`, clipped to `bounds` (none past the data), ordered from the
47
+ * rectangle's centre outward so the middle of the screen fills first. At most `limit`.
48
+ */
49
+ export function regionTilesInRect(rect, level, tileSize, bounds, limit = Infinity) {
50
+ if (!bounds)
51
+ return [];
52
+ const x0 = Math.max(rect[0], bounds[0]);
53
+ const y0 = Math.max(rect[1], bounds[1]);
54
+ const x1 = Math.min(rect[2], bounds[2]);
55
+ const y1 = Math.min(rect[3], bounds[3]);
56
+ if (x1 < x0 || y1 < y0)
57
+ return [];
58
+ const size = levelTileSize(level, tileSize);
59
+ const gx0 = Math.floor(x0 / size);
60
+ const gy0 = Math.floor(y0 / size);
61
+ const gx1 = Math.floor(x1 / size);
62
+ const gy1 = Math.floor(y1 / size);
63
+ const cx = (rect[0] + rect[2]) / 2 / size;
64
+ const cy = (rect[1] + rect[3]) / 2 / size;
65
+ const out = [];
66
+ for (let gy = gy0; gy <= gy1; gy++) {
67
+ for (let gx = gx0; gx <= gx1; gx++)
68
+ out.push({ level, gx, gy });
69
+ }
70
+ const d = (k) => (k.gx + 0.5 - cx) ** 2 + (k.gy + 0.5 - cy) ** 2;
71
+ out.sort((a, b) => d(a) - d(b));
72
+ return out.length > limit ? out.slice(0, limit) : out;
73
+ }
74
+ /** `level/gx/gy`, a tile's id within one plane. */
75
+ export function regionTileId(k) {
76
+ return `${k.level}/${k.gx}/${k.gy}`;
77
+ }
78
+ /** The tile of `level` holding image point (x, y). */
79
+ export function tileAt(x, y, level, tileSize = REGION_TILE_SIZE) {
80
+ const size = levelTileSize(level, tileSize);
81
+ return { level, gx: Math.floor(x / size), gy: Math.floor(y / size) };
82
+ }
83
+ /** True when two boxes meet (edges included). */
84
+ export function bboxesMeet(a, b) {
85
+ return a[0] <= b[2] && a[2] >= b[0] && a[1] <= b[3] && a[3] >= b[1];
86
+ }
87
+ // ── Picking ──────────────────────────────────────────────────────────────────────────────
88
+ /**
89
+ * The feature under image point (x, y): inside an area (even-odd over its rings, so holes are
90
+ * outside) or within `tolerance` image pixels of a polyline. Of several, the one with the
91
+ * smallest box — the innermost of nested outlines. Null when none is.
92
+ */
93
+ export function featureAt(features, x, y, tolerance = 0) {
94
+ let best = null;
95
+ let bestArea = Infinity;
96
+ for (const f of features) {
97
+ const b = f.bbox;
98
+ if (x < b[0] - tolerance || x > b[2] + tolerance || y < b[1] - tolerance || y > b[3] + tolerance)
99
+ continue;
100
+ const hit = f.open ? nearPolylines(f.rings, x, y, tolerance) : insideRings(f.rings, x, y);
101
+ if (!hit)
102
+ continue;
103
+ const area = (b[2] - b[0]) * (b[3] - b[1]);
104
+ if (area < bestArea) {
105
+ best = f;
106
+ bestArea = area;
107
+ }
108
+ }
109
+ return best;
110
+ }
111
+ /** Features whose box meets `rect` (the rubber band's rule for regions). */
112
+ export function featuresInRect(features, rect) {
113
+ const out = [];
114
+ for (const f of features)
115
+ if (bboxesMeet(f.bbox, rect))
116
+ out.push(f);
117
+ return out;
118
+ }
119
+ /** Even-odd containment over interleaved rings. */
120
+ export function insideRings(rings, x, y) {
121
+ let inside = false;
122
+ for (const r of rings) {
123
+ const n = r.length >> 1;
124
+ if (n < 3)
125
+ continue;
126
+ for (let i = 0, j = n - 1; i < n; j = i++) {
127
+ const xi = r[2 * i], yi = r[2 * i + 1], xj = r[2 * j], yj = r[2 * j + 1];
128
+ if (yi > y !== yj > y && x < ((xj - xi) * (y - yi)) / (yj - yi) + xi)
129
+ inside = !inside;
130
+ }
131
+ }
132
+ return inside;
133
+ }
134
+ function nearPolylines(lines, x, y, tolerance) {
135
+ for (const l of lines) {
136
+ for (let i = 2; i + 1 < l.length; i += 2) {
137
+ if (segmentDistance(x, y, l[i - 2], l[i - 1], l[i], l[i + 1]) <= tolerance)
138
+ return true;
139
+ }
140
+ }
141
+ return false;
142
+ }
143
+ function segmentDistance(px, py, ax, ay, bx, by) {
144
+ const dx = bx - ax, dy = by - ay;
145
+ const len2 = dx * dx + dy * dy;
146
+ const t = len2 === 0 ? 0 : Math.max(0, Math.min(1, ((px - ax) * dx + (py - ay) * dy) / len2));
147
+ return Math.hypot(px - (ax + t * dx), py - (ay + t * dy));
148
+ }
149
+ // ── Simplification ───────────────────────────────────────────────────────────────────────
150
+ /** Douglas–Peucker over an open polyline (both ends kept). */
151
+ export function simplifyPolyline(xs, ys, epsilon) {
152
+ const n = xs.length;
153
+ if (n <= 2 || !(epsilon > 0))
154
+ return { xs: xs.slice(), ys: ys.slice() };
155
+ const keep = new Uint8Array(n);
156
+ keep[0] = keep[n - 1] = 1;
157
+ const stack = [[0, n - 1]];
158
+ while (stack.length) {
159
+ const [a, b] = stack.pop();
160
+ let maxD = -1, idx = -1;
161
+ for (let i = a + 1; i < b; i++) {
162
+ const d = segmentDistance(xs[i], ys[i], xs[a], ys[a], xs[b], ys[b]);
163
+ if (d > maxD) {
164
+ maxD = d;
165
+ idx = i;
166
+ }
167
+ }
168
+ if (maxD > epsilon) {
169
+ keep[idx] = 1;
170
+ stack.push([a, idx], [idx, b]);
171
+ }
172
+ }
173
+ const ox = [], oy = [];
174
+ for (let i = 0; i < n; i++) {
175
+ if (keep[i]) {
176
+ ox.push(xs[i]);
177
+ oy.push(ys[i]);
178
+ }
179
+ }
180
+ return { xs: ox, ys: oy };
181
+ }
182
+ /**
183
+ * Rings simplified for a level: every ring through Douglas–Peucker at the level's tolerance,
184
+ * rings whose box is under the level's minimum extent dropped, and rings left with too few
185
+ * vertices to draw (3 for a closed ring, 2 for a polyline) dropped. Level 0 returns the rings
186
+ * as they are.
187
+ */
188
+ export function simplifyRings(rings, open, level) {
189
+ const tol = levelTolerance(level);
190
+ const minExtent = levelMinExtent(level);
191
+ const minVertices = open ? 2 : 3;
192
+ const out = [];
193
+ for (const ring of rings) {
194
+ const n = ring.length >> 1;
195
+ if (n < minVertices)
196
+ continue;
197
+ if (tol === 0) {
198
+ out.push(Float32Array.from(ring));
199
+ continue;
200
+ }
201
+ const xs = new Array(n), ys = new Array(n);
202
+ let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
203
+ for (let i = 0; i < n; i++) {
204
+ const x = ring[2 * i], y = ring[2 * i + 1];
205
+ xs[i] = x;
206
+ ys[i] = y;
207
+ if (x < x0)
208
+ x0 = x;
209
+ if (x > x1)
210
+ x1 = x;
211
+ if (y < y0)
212
+ y0 = y;
213
+ if (y > y1)
214
+ y1 = y;
215
+ }
216
+ if (Math.max(x1 - x0, y1 - y0) < minExtent)
217
+ continue;
218
+ const s = open ? simplifyPolyline(xs, ys, tol) : simplifyRing(xs, ys, tol);
219
+ if (s.xs.length < minVertices)
220
+ continue;
221
+ const flat = new Float32Array(s.xs.length * 2);
222
+ for (let i = 0; i < s.xs.length; i++) {
223
+ flat[2 * i] = s.xs[i];
224
+ flat[2 * i + 1] = s.ys[i];
225
+ }
226
+ out.push(flat);
227
+ }
228
+ return out;
229
+ }
230
+ // ── The feature table ────────────────────────────────────────────────────────────────────
231
+ /** Features (and their simplified outlines) cached per level, past which the oldest go. */
232
+ const SIMPLIFIED_CACHE_LIMIT = 200_000;
233
+ /**
234
+ * A parsed GeoJSON region set, indexed for tiles. Holds the raw features (for the exact
235
+ * geometry and the export), each feature's rings, box, plane and class, and builds a level's
236
+ * tile buckets the first time that level of a plane is asked for.
237
+ */
238
+ export class RegionFeatureTable {
239
+ constructor(raw, tileSize = REGION_TILE_SIZE) {
240
+ this.raw = raw;
241
+ this.tileSize = tileSize;
242
+ this.ids = [];
243
+ this.labels = [];
244
+ this.colors = [];
245
+ this.planes = [];
246
+ this.boxes = [];
247
+ this.rings = [];
248
+ this.open = [];
249
+ /** Per feature, its parts as ring indices (the exterior first, then its holes). */
250
+ this.parts = [];
251
+ this.labelPoints = new Map();
252
+ /** Each feature's area, worked out the first time its row is asked for. */
253
+ this.areas = new Map();
254
+ this.byId = new Map();
255
+ this.buckets = new Map();
256
+ this.simplified = new Map();
257
+ let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
258
+ raw.forEach((feature, i) => {
259
+ const own = featureIdOf(feature);
260
+ let id = own;
261
+ if (id === undefined || this.byId.has(id)) {
262
+ // Its position, unless a feature already has that id (an explicit "#1", say): ids are unique,
263
+ // or a take, an exclusion or an export would act on both.
264
+ id = `#${i}`;
265
+ for (let k = 1; this.byId.has(id); k++)
266
+ id = `#${i}-${k}`;
267
+ }
268
+ this.byId.set(id, i);
269
+ this.ids.push(id);
270
+ const { label, color } = classificationOf(feature);
271
+ this.labels.push(label);
272
+ this.colors.push(color);
273
+ this.planes.push(feature?.geometry?.plane?.z ?? 0);
274
+ const { rings, open, parts } = ringsOf(feature);
275
+ this.rings.push(rings);
276
+ this.open.push(open);
277
+ this.parts.push(parts);
278
+ const box = ringsBox(rings);
279
+ this.boxes.push(box);
280
+ if (rings.length) {
281
+ x0 = Math.min(x0, box[0]);
282
+ y0 = Math.min(y0, box[1]);
283
+ x1 = Math.max(x1, box[2]);
284
+ y1 = Math.max(y1, box[3]);
285
+ }
286
+ });
287
+ this.bounds = x0 <= x1 ? [x0, y0, x1, y1] : null;
288
+ const extent = this.bounds ? Math.max(Math.abs(x0), Math.abs(y0), Math.abs(x1), Math.abs(y1)) : 0;
289
+ this.levels = 1 + Math.max(0, Math.ceil(Math.log2(Math.max(extent, tileSize) / tileSize)));
290
+ }
291
+ /** Parse a GeoJSON FeatureCollection string. Throws on invalid JSON or no `features`. */
292
+ static fromGeoJson(text, tileSize = REGION_TILE_SIZE) {
293
+ const parsed = JSON.parse(text);
294
+ if (!parsed || !Array.isArray(parsed.features)) {
295
+ throw new Error("Invalid GeoJson file: must contain the 'features' key.");
296
+ }
297
+ const table = new RegionFeatureTable(parsed.features, tileSize);
298
+ table.describe(parsed.classHierarchy, parsed.style);
299
+ return table;
300
+ }
301
+ /** Attach a class hierarchy and a style hint (each ignored when not well formed). */
302
+ describe(hierarchy, style) {
303
+ this.hierarchy = readHierarchy(hierarchy) ?? this.hierarchy;
304
+ this.style = readStyle(style) ?? this.style;
305
+ }
306
+ /**
307
+ * The outlines of every feature of these classes, plane by plane, simplified for `level` (what a
308
+ * 3D reconstruction of the classes stacks), without the `exclude`d ids: closed features' rings,
309
+ * open features' polylines as `lines`, each ring with its feature (`ringGroups`). Planes without
310
+ * one are left out. `classes` null reads every labelled feature, each outline with its class
311
+ * (`ringLabels`, `lineLabels`).
312
+ */
313
+ classOutlines(classes, level, exclude = []) {
314
+ const wanted = classes ? new Set(classes) : null;
315
+ const skip = new Set(exclude);
316
+ const byPlane = new Map();
317
+ for (let i = 0; i < this.ids.length; i++) {
318
+ const label = this.labels[i];
319
+ if (!label || (wanted && !wanted.has(label)) || skip.has(this.ids[i]))
320
+ continue;
321
+ const rings = this.ringsAt(i, level);
322
+ if (!rings.length)
323
+ continue;
324
+ const z = this.planes[i];
325
+ let plane = byPlane.get(z);
326
+ if (!plane)
327
+ byPlane.set(z, (plane = { z, rings: [] }));
328
+ if (this.open[i]) {
329
+ (plane.lines ??= []).push(...rings);
330
+ if (!wanted)
331
+ (plane.lineLabels ??= []).push(...rings.map(() => label));
332
+ }
333
+ else {
334
+ plane.rings.push(...rings);
335
+ (plane.ringGroups ??= []).push(...rings.map(() => i));
336
+ if (!wanted)
337
+ (plane.ringLabels ??= []).push(...rings.map(() => label));
338
+ }
339
+ }
340
+ return Array.from(byPlane.values()).sort((a, b) => a.z - b.z);
341
+ }
342
+ /** Features per class on plane `z` (null: on every plane), without the `exclude`d ids. */
343
+ classCounts(z, exclude = []) {
344
+ const skip = new Set(exclude);
345
+ const counts = {};
346
+ for (let i = 0; i < this.ids.length; i++) {
347
+ const label = this.labels[i];
348
+ if ((z !== null && this.planes[i] !== z) || !label || skip.has(this.ids[i]))
349
+ continue;
350
+ counts[label] = (counts[label] ?? 0) + 1;
351
+ }
352
+ return counts;
353
+ }
354
+ info() {
355
+ const classColors = {};
356
+ this.labels.forEach((label, i) => {
357
+ const color = this.colors[i];
358
+ if (label && color && !(label in classColors))
359
+ classColors[label] = color;
360
+ });
361
+ return {
362
+ featureCount: this.ids.length,
363
+ bounds: this.bounds,
364
+ tileSize: this.tileSize,
365
+ levels: this.levels,
366
+ planes: Array.from(new Set(this.planes)).sort((a, b) => a - b),
367
+ classColors,
368
+ ...(this.hierarchy ? { hierarchy: this.hierarchy } : {}),
369
+ ...(this.style ? { style: this.style } : {}),
370
+ };
371
+ }
372
+ /** One tile of plane `z`. */
373
+ tile(z, level, gx, gy) {
374
+ const { cells, wide } = this.bucketsFor(z, level);
375
+ const bucket = cells.get(`${gx}/${gy}`) ?? [];
376
+ const size = levelTileSize(level, this.tileSize);
377
+ const features = [];
378
+ // The tile's cell features and the wide ones that meet it, merged back into file order.
379
+ const order = [];
380
+ for (let a = 0, w = 0; a < bucket.length || w < wide.length;) {
381
+ if (w >= wide.length || (a < bucket.length && bucket[a] < wide[w]))
382
+ order.push(bucket[a++]);
383
+ else {
384
+ const i = wide[w++];
385
+ if (cellMeets(this.boxes[i], size, gx, gy))
386
+ order.push(i);
387
+ }
388
+ }
389
+ for (const i of order) {
390
+ const rings = this.ringsAt(i, level);
391
+ if (!rings.length)
392
+ continue;
393
+ const labels = this.labelsAt(i, level);
394
+ features.push({
395
+ id: this.ids[i],
396
+ label: this.labels[i],
397
+ color: this.colors[i],
398
+ bbox: this.boxes[i],
399
+ rings,
400
+ open: this.open[i],
401
+ ...(labels ? { labels } : {}),
402
+ });
403
+ }
404
+ return { z, level, gx, gy, features };
405
+ }
406
+ /** The raw GeoJSON features with these ids, in the order asked (unknown ids skipped). */
407
+ features(ids) {
408
+ const out = [];
409
+ for (const id of ids) {
410
+ const i = this.byId.get(id);
411
+ if (i !== undefined)
412
+ out.push({ id, feature: this.raw[i] });
413
+ }
414
+ return out;
415
+ }
416
+ /** Feature `i`'s area in px² (0 for a polyline). */
417
+ areaOf(i) {
418
+ let area = this.areas.get(i);
419
+ if (area === undefined) {
420
+ area = this.open[i] ? 0 : ringsArea(this.rings[i]);
421
+ this.areas.set(i, area);
422
+ }
423
+ return area;
424
+ }
425
+ /** A page of plane `z`'s features, in file order. */
426
+ index(z, query) {
427
+ const exclude = new Set(query.exclude ?? []);
428
+ const classes = query.classes ? new Set(query.classes) : null;
429
+ const needle = query.label?.trim().toLowerCase() || null;
430
+ const rows = [];
431
+ let total = 0;
432
+ for (let i = 0; i < this.ids.length; i++) {
433
+ if (this.planes[i] !== z || exclude.has(this.ids[i]))
434
+ continue;
435
+ if (needle && !(this.labels[i] ?? '').toLowerCase().includes(needle))
436
+ continue;
437
+ if (classes && !classes.has(this.labels[i] ?? ''))
438
+ continue;
439
+ if (total >= query.offset && rows.length < query.limit) {
440
+ rows.push({
441
+ id: this.ids[i],
442
+ label: this.labels[i],
443
+ color: this.colors[i],
444
+ bbox: this.boxes[i],
445
+ area: this.areaOf(i),
446
+ });
447
+ }
448
+ total++;
449
+ }
450
+ return { total, rows };
451
+ }
452
+ /**
453
+ * The source as a GeoJSON FeatureCollection string, through the working set: features whose
454
+ * id is in `exclude` (taken for editing, or deleted) are left out, `extra` (the working set's
455
+ * features) appended. Every feature keeps an `id`; the set keeps its hierarchy and style.
456
+ */
457
+ exportGeoJson(exclude, extra) {
458
+ const skip = new Set(exclude);
459
+ const parts = [];
460
+ this.raw.forEach((feature, i) => {
461
+ const id = this.ids[i];
462
+ if (skip.has(id))
463
+ return;
464
+ parts.push(JSON.stringify(feature.id === undefined ? { type: 'Feature', id, ...feature } : feature));
465
+ });
466
+ for (const f of extra)
467
+ parts.push(JSON.stringify(f));
468
+ return featureCollectionJson(parts, this.hierarchy, this.style);
469
+ }
470
+ /**
471
+ * Feature `i`'s label points (one per part with room for a label at `level`: a part under the
472
+ * level's minimum extent is not drawn there), from the exact geometry, computed once.
473
+ */
474
+ labelsAt(i, level) {
475
+ if (this.open[i] || !this.labels[i])
476
+ return null;
477
+ let points = this.labelPoints.get(i);
478
+ if (!points) {
479
+ const out = [];
480
+ for (const part of this.parts[i]) {
481
+ const pole = polylabel(part.map((r) => this.rings[i][r]));
482
+ if (pole && pole.distance > 0)
483
+ out.push(pole.x, pole.y, pole.distance);
484
+ }
485
+ points = Float32Array.from(out);
486
+ this.labelPoints.set(i, points);
487
+ }
488
+ const min = levelMinExtent(level) / 2;
489
+ if (!min)
490
+ return points.length ? points : null;
491
+ const kept = [];
492
+ for (let k = 0; k + 2 < points.length; k += 3)
493
+ if (points[k + 2] >= min)
494
+ kept.push(points[k], points[k + 1], points[k + 2]);
495
+ return kept.length ? Float32Array.from(kept) : null;
496
+ }
497
+ /** Feature `i`'s rings at `level`, simplified once and cached. */
498
+ ringsAt(i, level) {
499
+ const key = `${level}/${i}`;
500
+ let rings = this.simplified.get(key);
501
+ if (!rings) {
502
+ rings = simplifyRings(this.rings[i], this.open[i], level);
503
+ if (this.simplified.size >= SIMPLIFIED_CACHE_LIMIT) {
504
+ const oldest = this.simplified.keys().next().value;
505
+ this.simplified.delete(oldest);
506
+ }
507
+ this.simplified.set(key, rings);
508
+ }
509
+ return rings;
510
+ }
511
+ /** Entries in plane `z`'s level-`level` index: cell listings plus wide features (tests). */
512
+ indexEntries(z, level) {
513
+ const { cells, wide } = this.bucketsFor(z, level);
514
+ let n = wide.length;
515
+ for (const list of cells.values())
516
+ n += list.length;
517
+ return n;
518
+ }
519
+ /**
520
+ * Plane `z`'s level-`level` index, built on first use: features by tile cell (`gx/gy` → feature
521
+ * indices), and the wide ones (more than {@link MAX_CELLS_PER_FEATURE} cells, or past the
522
+ * number range), tested against a tile when it is asked for.
523
+ */
524
+ bucketsFor(z, level) {
525
+ const key = `${z}/${level}`;
526
+ let index = this.buckets.get(key);
527
+ if (index)
528
+ return index;
529
+ const cells = new Map();
530
+ const wide = [];
531
+ const size = levelTileSize(level, this.tileSize);
532
+ const minExtent = levelMinExtent(level);
533
+ for (let i = 0; i < this.ids.length; i++) {
534
+ if (this.planes[i] !== z || !this.rings[i].length)
535
+ continue;
536
+ const b = this.boxes[i];
537
+ if (Math.max(b[2] - b[0], b[3] - b[1]) < minExtent)
538
+ continue;
539
+ const gx0 = Math.floor(b[0] / size), gx1 = Math.floor(b[2] / size), gy0 = Math.floor(b[1] / size), gy1 = Math.floor(b[3] / size);
540
+ // A box with a NaN coordinate meets no tile.
541
+ if ([gx0, gx1, gy0, gy1].some(Number.isNaN))
542
+ continue;
543
+ const count = (gx1 - gx0 + 1) * (gy1 - gy0 + 1);
544
+ if (!(count <= MAX_CELLS_PER_FEATURE) || ![gx0, gx1, gy0, gy1].every(Number.isSafeInteger)) {
545
+ wide.push(i);
546
+ continue;
547
+ }
548
+ for (let gy = gy0; gy <= gy1; gy++) {
549
+ for (let gx = gx0; gx <= gx1; gx++) {
550
+ const id = `${gx}/${gy}`;
551
+ const list = cells.get(id);
552
+ if (list)
553
+ list.push(i);
554
+ else
555
+ cells.set(id, [i]);
556
+ }
557
+ }
558
+ }
559
+ index = { cells, wide };
560
+ this.buckets.set(key, index);
561
+ return index;
562
+ }
563
+ }
564
+ /**
565
+ * A feature spanning more tiles than this is not listed in each of them but kept aside and tested
566
+ * against a tile when one is asked for: one huge box (an outline around a whole slide, or a corrupt
567
+ * coordinate) must not make a plane's index millions of entries.
568
+ */
569
+ export const MAX_CELLS_PER_FEATURE = 64;
570
+ /** Whether box `b` meets cell (gx, gy) of tiles `size` pixels wide, as a cell lists it. */
571
+ function cellMeets(b, size, gx, gy) {
572
+ return (Math.floor(b[0] / size) <= gx &&
573
+ gx <= Math.floor(b[2] / size) &&
574
+ Math.floor(b[1] / size) <= gy &&
575
+ gy <= Math.floor(b[3] / size));
576
+ }
577
+ /** A feature's own id (`id`, else `properties.id`) as a string. */
578
+ export function featureIdOf(feature) {
579
+ const id = feature?.id ?? feature?.properties?.id;
580
+ return typeof id === 'string' || typeof id === 'number' ? String(id) : undefined;
581
+ }
582
+ /** Class name and colour from QuPath's `classification` (`{name, color}`, or a bare name). */
583
+ function classificationOf(feature) {
584
+ const c = feature?.properties?.classification;
585
+ if (!c)
586
+ return { label: 'Cell', color: null };
587
+ if (typeof c === 'string')
588
+ return { label: c, color: null };
589
+ const color = Array.isArray(c.color) && c.color.length >= 3 ? rgbToHex([c.color[0], c.color[1], c.color[2]]) : null;
590
+ return { label: c.name ?? null, color };
591
+ }
592
+ /**
593
+ * A feature's rings, interleaved, without the closing vertex; whether it is a polyline; and its
594
+ * parts as ring indices (each part's exterior first, then its holes).
595
+ */
596
+ function ringsOf(feature) {
597
+ const g = feature?.geometry;
598
+ const coords = g?.coordinates;
599
+ if (!g || !Array.isArray(coords))
600
+ return { rings: [], open: false, parts: [] };
601
+ const polygons = (list) => {
602
+ const rings = [];
603
+ const parts = [];
604
+ for (const polygon of list) {
605
+ const part = [];
606
+ for (const r of polygon) {
607
+ part.push(rings.length);
608
+ rings.push(flatRing(r, true));
609
+ }
610
+ if (part.length)
611
+ parts.push(part);
612
+ }
613
+ return { rings, open: false, parts };
614
+ };
615
+ switch (g.type) {
616
+ case 'Polygon':
617
+ return polygons([coords]);
618
+ case 'MultiPolygon':
619
+ return polygons(coords);
620
+ case 'LineString':
621
+ return { rings: [flatRing(coords, false)], open: true, parts: [] };
622
+ case 'MultiLineString':
623
+ return { rings: coords.map((r) => flatRing(r, false)), open: true, parts: [] };
624
+ default:
625
+ return { rings: [], open: false, parts: [] };
626
+ }
627
+ }
628
+ /**
629
+ * A FeatureCollection string of `features` (each a feature's JSON), with the set's class hierarchy
630
+ * and style as its `classHierarchy` and `style` members when it has them: what
631
+ * {@link RegionFeatureTable.fromGeoJson} reads back.
632
+ */
633
+ export function featureCollectionJson(features, hierarchy, style) {
634
+ const head = ['"type":"FeatureCollection"'];
635
+ if (hierarchy?.length)
636
+ head.push(`"classHierarchy":${JSON.stringify(hierarchy)}`);
637
+ if (style)
638
+ head.push(`"style":${JSON.stringify(style)}`);
639
+ return `{${head.join(',')},"features":[${features.join(',')}]}`;
640
+ }
641
+ /** A well-formed class hierarchy from a file (colours as `#rrggbb` or `[r, g, b]`), else undefined. */
642
+ export function readHierarchy(raw) {
643
+ if (!Array.isArray(raw))
644
+ return undefined;
645
+ const out = [];
646
+ for (const n of raw) {
647
+ if (!n || typeof n.name !== 'string')
648
+ continue;
649
+ const color = Array.isArray(n.color) ? rgbToHex([+n.color[0], +n.color[1], +n.color[2]]) : n.color;
650
+ out.push({
651
+ name: n.name,
652
+ ...(typeof n.title === 'string' ? { title: n.title } : {}),
653
+ ...(typeof n.parent === 'string' ? { parent: n.parent } : {}),
654
+ ...(typeof color === 'string' ? { color } : {}),
655
+ ...(typeof n.order === 'number' ? { order: n.order } : {}),
656
+ });
657
+ }
658
+ return out.length ? out : undefined;
659
+ }
660
+ /** A well-formed style hint from a file, else undefined. */
661
+ export function readStyle(raw) {
662
+ if (!raw || typeof raw !== 'object')
663
+ return undefined;
664
+ const r = raw;
665
+ const style = {};
666
+ if (typeof r.fillOpacity === 'number')
667
+ style.fillOpacity = Math.max(0, Math.min(1, r.fillOpacity));
668
+ if (typeof r.stroke === 'string')
669
+ style.stroke = r.stroke;
670
+ if (typeof r.strokeWidth === 'number' && r.strokeWidth > 0)
671
+ style.strokeWidth = r.strokeWidth;
672
+ if (typeof r.labels === 'boolean')
673
+ style.labels = r.labels;
674
+ if (typeof r.highlight === 'string')
675
+ style.highlight = r.highlight;
676
+ return Object.keys(style).length ? style : undefined;
677
+ }
678
+ function flatRing(points, closed) {
679
+ let n = points?.length ?? 0;
680
+ if (closed && n > 1) {
681
+ const a = points[0], b = points[n - 1];
682
+ if (a[0] === b[0] && a[1] === b[1])
683
+ n--;
684
+ }
685
+ const out = new Float64Array(n * 2);
686
+ for (let i = 0; i < n; i++) {
687
+ out[2 * i] = +points[i][0];
688
+ out[2 * i + 1] = +points[i][1];
689
+ }
690
+ return out;
691
+ }
692
+ function ringsBox(rings) {
693
+ let x0 = Infinity, y0 = Infinity, x1 = -Infinity, y1 = -Infinity;
694
+ for (const r of rings) {
695
+ for (let i = 0; i + 1 < r.length; i += 2) {
696
+ if (r[i] < x0)
697
+ x0 = r[i];
698
+ if (r[i] > x1)
699
+ x1 = r[i];
700
+ if (r[i + 1] < y0)
701
+ y0 = r[i + 1];
702
+ if (r[i + 1] > y1)
703
+ y1 = r[i + 1];
704
+ }
705
+ }
706
+ return [x0, y0, x1, y1];
707
+ }
708
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmVnaW9uLXRpbGVzLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vc3JjL2xpYi9yZWdpb24tc291cmNlL3JlZ2lvbi10aWxlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQUNILE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUM5QyxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFDaEQsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ2xELE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUtwRCwrQ0FBK0M7QUFDL0MsTUFBTSxDQUFDLE1BQU0sZ0JBQWdCLEdBQUcsR0FBRyxDQUFDO0FBc0pwQzs7OztHQUlHO0FBQ0gsTUFBTSxVQUFVLGNBQWMsQ0FBQyxZQUFvQixFQUFFLE1BQWM7SUFDakUsSUFBSSxDQUFDLENBQUMsWUFBWSxHQUFHLENBQUMsQ0FBQyxJQUFJLE1BQU0sSUFBSSxDQUFDO1FBQUUsT0FBTyxDQUFDLENBQUM7SUFDakQsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsWUFBWSxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7SUFDekQsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsS0FBSyxDQUFDLENBQUMsQ0FBQztBQUNsRCxDQUFDO0FBRUQsd0VBQXdFO0FBQ3hFLE1BQU0sVUFBVSxjQUFjLENBQUMsS0FBYTtJQUMxQyxPQUFPLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDO0FBQzNDLENBQUM7QUFFRCxrR0FBa0c7QUFDbEcsTUFBTSxVQUFVLGNBQWMsQ0FBQyxLQUFhO0lBQzFDLE9BQU8sS0FBSyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksS0FBSyxDQUFDO0FBQ3JDLENBQUM7QUFFRCw2Q0FBNkM7QUFDN0MsTUFBTSxVQUFVLGFBQWEsQ0FBQyxLQUFhLEVBQUUsUUFBUSxHQUFHLGdCQUFnQjtJQUN0RSxPQUFPLFFBQVEsR0FBRyxDQUFDLElBQUksS0FBSyxDQUFDO0FBQy9CLENBQUM7QUFFRDs7O0dBR0c7QUFDSCxNQUFNLFVBQVUsaUJBQWlCLENBQy9CLElBQVUsRUFDVixLQUFhLEVBQ2IsUUFBZ0IsRUFDaEIsTUFBbUIsRUFDbkIsS0FBSyxHQUFHLFFBQVE7SUFFaEIsSUFBSSxDQUFDLE1BQU07UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUN2QixNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4QyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4QyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4QyxNQUFNLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN4QyxJQUFJLEVBQUUsR0FBRyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUU7UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNsQyxNQUFNLElBQUksR0FBRyxhQUFhLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDO0lBQzVDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ2xDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ2xDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ2xDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsRUFBRSxHQUFHLElBQUksQ0FBQyxDQUFDO0lBQ2xDLE1BQU0sRUFBRSxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUM7SUFDMUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxHQUFHLElBQUksQ0FBQztJQUMxQyxNQUFNLEdBQUcsR0FBb0IsRUFBRSxDQUFDO0lBQ2hDLEtBQUssSUFBSSxFQUFFLEdBQUcsR0FBRyxFQUFFLEVBQUUsSUFBSSxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztRQUNuQyxLQUFLLElBQUksRUFBRSxHQUFHLEdBQUcsRUFBRSxFQUFFLElBQUksR0FBRyxFQUFFLEVBQUUsRUFBRTtZQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDLENBQUM7SUFDbEUsQ0FBQztJQUNELE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBZ0IsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLEdBQUcsR0FBRyxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUM7SUFDaEYsR0FBRyxDQUFDLElBQUksQ0FB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QUFDO1lBQ2hELElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3ZCLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBQ3JCLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO1lBQ3ZCLE1BQU0sR0FBRyxHQUFHLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQztZQUM1QixJQUFJLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUNyQixJQUFJLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDakIsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUMxQixFQUFFLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzFCLEVBQUUsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDMUIsRUFBRSxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzVCLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxNQUFNLEdBQUcsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO1FBQ2pELE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUks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T0FBTyxHQUFHLElBQUksR0FBRyxDQUFDLEtBQUssQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDLENBQUM7UUFDN0MsTUFBTSxPQUFPLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsSUFBSSxHQUFHLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDOUQsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxXQUFXLEVBQUUsSUFBSSxJQUFJLENBQUM7UUFDekQsTUFBTSxJQUFJLEdBQXFCLEVBQUUsQ0FBQztRQUNsQyxJQUFJLEtBQUssR0FBRyxDQUFDLENBQUM7UUFDZCxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQztZQUN6QyxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFBRSxTQUFTO1lBQy9ELElBQUksTUFBTSxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUM7Z0JBQUUsU0FBUztZQUMvRSxJQUFJLE9BQU8sSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUM7Z0JBQUUsU0FBUztZQUM1RCxJQUFJLEtBQUssSUFBSSxLQUFLLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLEdBQUcsS0FBSyxDQUFDLEtBQUssRUFBRSxDQUFDO2dCQUN2RCxJQUFJLENBQUMsSUFBSSxDQUFDO29CQUNSLEVBQUUsRUFBRSxJQUFJLENBQUMs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RyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDO1lBQ3pDLElBQUksSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLE1BQU07Z0JBQUUsU0FBUztZQUM1RCxNQUFNLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3hCLElBQUksSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxTQUFTO2dCQUFFLFNBQVM7WUFDN0QsTUFBTSxHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLEVBQ2pDLEdBQUcsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxJQUFJLENBQUMsRUFDN0IsR0FBRyxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxFQUM3QixHQUFHLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLENBQUM7WUFDaEMsNkNBQTZDO1lBQzdDLElBQUksQ0FBQyxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQztnQkFBRSxTQUFTO1lBQ3RELE1BQU0sS0FBSyxHQUFHLENBQUMsR0FBRyxHQUFHLEdBQUcsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLEdBQUcsR0FBRyxHQUFHLEdBQUcsQ0FBQyxDQUFDLENBQUM7WUFDaEQsSUFBSSxDQUFDLENBQUMsS0FBSyxJQUFJLHFCQUFxQixDQUFDLElBQUksQ0FBQyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQztnQkFDM0YsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztnQkFDYixTQUFTO1lBQ1gsQ0FBQztZQUNELEtBQUssSUFBSSxFQUFFLEdBQUcsR0FBRyxFQUFFLEVBQUUsSUFBSSxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsQ0FBQztnQkFDbkMsS0FBSyxJQUFJLEVBQUUsR0FBRyxHQUFHLEVBQUUsRUFBRSxJQUFJLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFDO29CQUNuQyxNQUFNLEVBQUUsR0FBRyxHQUFHLEVBQUUsSUFBSSxFQUFFLEVBQUUsQ0FBQztvQkFDekIsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsQ0FBQztvQkFDM0IsSUFBSSxJQUFJO3dCQUFFLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUM7O3dCQUNsQixLQUFLLENBQUMsR0FBRyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQzFCLENBQUM7WUFDSCxDQUFDO1FBQ0gsQ0FBQztRQUNELEtBQUssR0FBRyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQztRQUN4QixJQUFJLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEVBQUUsS0FBSyxDQUFDLENBQUM7UUFDN0IsT0FBTyxLQUFLLENBQUM7SUFDZixDQUFDO0NBQ0Y7QUFFRDs7OztHQUlHO0FBQ0gsTUFBTSxDQUFDLE1BQU0scUJBQXFCLEdBQUcsRUFBRSxDQUFDO0FBUXhDLDJGQUEyRjtBQUMzRixTQUFTLFNBQVMsQ0FBQyxDQUFpQixFQUFFLElBQVksRUFBRSxFQUFVLEVBQUUsRUFBVTtJQUN4RSxPQUFPLENBQ0wsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDLElBQUksRUFBRTtRQUM3QixFQUFFLElBQUksSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsSUFBSSxDQUFDO1FBQzdCLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxJQUFJLEVBQUU7UUFDN0IsRUFBRSxJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxDQUM5QixDQUFDO0FBQ0osQ0FBQztBQUVELG1FQUFtRTtBQUNuRSxNQUFNLFVBQVUsV0FBVyxDQUFDLE9BQTJCO0lBQ3JELE1BQU0sRUFBRSxHQUFHLE9BQU8sRUFBRSxFQUFFLElBQUksT0FBTyxFQUFFLFVBQVUsRUFBRSxFQUFFLENBQUM7SUFDbEQsT0FBTyxPQUFPLEVBQUUsS0FBSyxRQUFRLElBQUksT0FBTyxFQUFFLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztBQUNuRixDQUFDO0FBRUQsOEZBQThGO0FBQzlGLFNBQVMsZ0JBQWdCLENBQUMsT0FBMkI7SUFDbkQsTUFBTSxDQUFDLEdBQUcsT0FBTyxFQUFFLFVBQVUsRUFBRSxjQUEwRSxDQUFDO0lBQzFHLElBQUksQ0FBQyxDQUFDO1FBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksRUFBRSxDQUFDO0lBQzlDLElBQUksT0FBTyxDQUFDLEtBQUssUUFBUTtRQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQztJQUM1RCxNQUFNLEtBQUssR0FDVCxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsS0FBSyxDQUFDLE1BQU0sSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDO0lBQ3hHLE9BQU8sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLElBQUksSUFBSSxJQUFJLEVBQUUsS0FBSyxFQUFFLENBQUM7QUFDMUMsQ0FBQztBQUVEOzs7R0FHRztBQUNILFNBQVMsT0FBTyxDQUFDLE9BQTJCO0lBQzFDLE1BQU0sQ0FBQyxHQUFHLE9BQU8sRUFBRSxRQUFRLENBQUM7SUFDNUIsTUFBTSxNQUFNLEdBQUcsQ0FBQyxFQUFFLFdBQXNCLENBQUM7SUFDekMsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDO1FBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLENBQUM7SUFDL0UsTUFBTSxRQUFRLEdBQUcsQ0FBQyxJQUFvQixFQUFFLEVBQUU7UUFDeEMsTUFBTSxLQUFLLEdBQW1CLEVBQUUsQ0FBQztRQUNqQyxNQUFNLEtBQUssR0FBZSxFQUFFLENBQUM7UUFDN0IsS0FBSyxNQUFNLE9BQU8sSUFBSSxJQUFJLEVBQUUsQ0FBQztZQUMzQixNQUFNLElBQUksR0FBYSxFQUFFLENBQUM7WUFDMUIsS0FBSyxNQUFNLENBQUMsSUFBSSxPQUFPLEVBQUUsQ0FBQztnQkFDeEIsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLENBQUM7Z0JBQ3hCLEtBQUssQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDO1lBQ2hDLENBQUM7WUFDRCxJQUFJLElBQUksQ0FBQyxNQUFNO2dCQUFFLEtBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDcEMsQ0FBQztRQUNELE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsQ0FBQztJQUN2QyxDQUFDLENBQUM7SUFDRixRQUFRLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUNmLEtBQUssU0FBUztZQUNaLE9BQU8sUUFBUSxDQUFDLENBQUMsTUFBc0IsQ0FBQyxDQUFDLENBQUM7UUFDNUMsS0FBSyxjQUFjO1lBQ2pCLE9BQU8sUUFBUSxDQUFDLE1BQXdCLENBQUMsQ0FBQztRQUM1QyxLQUFLLFlBQVk7WUFDZixPQUFPLEVBQUUsS0FBSyxFQUFFLENBQUMsUUFBUSxDQUFDLE1BQW9CLEVBQUUsS0FBSyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsQ0FBQztRQUNuRixLQUFLLGlCQUFpQjtZQUNwQixPQUFPLEVBQUUsS0FBSyxFQUFHLE1BQXVCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxRQUFRLENBQUMsQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFDLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxLQUFLLEVBQUUsRUFBRSxFQUFFLENBQUM7UUFDbkc7WUFDRSxPQUFPLEVBQUUsS0FBSyxFQUFFLEVBQUUsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxFQUFFLEVBQUUsQ0FBQztJQUNqRCxDQUFDO0FBQ0gsQ0FBQztBQUVEOzs7O0dBSUc7QUFDSCxNQUFNLFVBQVUscUJBQXFCLENBQ25DLFFBQTJCLEVBQzNCLFNBQXNDLEVBQ3RDLEtBQXlCO0lBRXpCLE1BQU0sSUFBSSxHQUFHLENBQUMsNEJBQTRCLENBQUMsQ0FBQztJQUM1QyxJQUFJLFNBQVMsRUFBRSxNQUFNO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsSUFBSSxDQUFDLFNBQVMsQ0FBQyxTQUFTLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDbEYsSUFBSSxLQUFLO1FBQUUsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLElBQUksQ0FBQyxTQUFTLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ3pELE9BQU8sSUFBSSxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxnQkFBZ0IsUUFBUSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDO0FBQ2xFLENBQUM7QUFFRCx1R0FBdUc7QUFDdkcsTUFBTSxVQUFVLGFBQWEsQ0FBQyxHQUFZO0lBQ3hDLElBQUksQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLEdBQUcsQ0FBQztRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQzFDLE1BQU0sR0FBRyxHQUFzQixFQUFFLENBQUM7SUFDbEMsS0FBSyxNQUFNLENBQUMsSUFBSSxHQUFxQyxFQUFFLENBQUM7UUFDdEQsSUFBSSxDQUFDLENBQUMsSUFBSSxPQUFPLENBQUMsQ0FBQyxJQUFJLEtBQUssUUFBUTtZQUFFLFNBQVM7UUFDL0MsTUFBTSxLQUFLLEdBQUcsS0FBSyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQztRQUNuRyxHQUFHLENBQUMsSUFBSSxDQUFDO1lBQ1AsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJO1lBQ1osR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1lBQzFELEdBQUcsQ0FBQyxPQUFPLENBQUMsQ0FBQyxNQUFNLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUM3RCxHQUFHLENBQUMsT0FBTyxLQUFLLEtBQUssUUFBUSxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUM7WUFDL0MsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDO1NBQzNELENBQUMsQ0FBQztJQUNMLENBQUM7SUFDRCxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ3RDLENBQUM7QUFFRCw0REFBNEQ7QUFDNUQsTUFBTSxVQUFVLFNBQVMsQ0FBQyxHQUFZO0lBQ3BDLElBQUksQ0FBQyxHQUFHLElBQUksT0FBTyxHQUFHLEtBQUssUUFBUTtRQUFFLE9BQU8sU0FBUyxDQUFDO0lBQ3RELE1BQU0sQ0FBQyxHQUFHLEdBQThCLENBQUM7SUFDekMsTUFBTSxLQUFLLEdBQXNCLEVBQUUsQ0FBQztJQUNwQyxJQUFJLE9BQU8sQ0FBQyxDQUFDLFdBQVcsS0FBSyxRQUFRO1FBQUUsS0FBSyxDQUFDLFdBQVcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQztJQUNuRyxJQUFJLE9BQU8sQ0FBQyxDQUFDLE1BQU0sS0FBSyxRQUFRO1FBQUUsS0FBSyxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDO0lBQzFELElBQUksT0FBTyxDQUFDLENBQUMsV0FBVyxLQUFLLFFBQVEsSUFBSSxDQUFDLENBQUMsV0FBVyxHQUFHLENBQUM7UUFBRSxLQUFLLENBQUMsV0FBVyxHQUFHLENBQUMsQ0FBQyxXQUFXLENBQUM7SUFDOUYsSUFBSSxPQUFPLENBQUMsQ0FBQyxNQUFNLEtBQUssU0FBUztRQUFFLEtBQUssQ0FBQyxNQUFNLEdBQUcsQ0FBQyxDQUFDLE1BQU0sQ0FBQztJQUMzRCxJQUFJLE9BQU8sQ0FBQyxDQUFDLFNBQVMsS0FBSyxRQUFRO1FBQUUsS0FBSyxDQUFDLFNBQVMsR0FBRyxDQUFDLENBQUMsU0FBUyxDQUFDO0lBQ25FLE9BQU8sTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDO0FBQ3ZELENBQUM7QUFFRCxTQUFTLFFBQVEsQ0FBQyxNQUFrQixFQUFFLE1BQWU7SUFDbkQsSUFBSSxDQUFDLEdBQUcsTUFBTSxFQUFFLE1BQU0sSUFBSSxDQUFDLENBQUM7SUFDNUIsSUFBSSxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDO1FBQ3BCLE1BQU0sQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFDakIsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDcEIsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQUUsQ0FBQyxFQUFFLENBQUM7SUFDMUMsQ0FBQztJQUNELE1BQU0sR0FBRyxHQUFHLElBQUksWUFBWSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztJQUNwQyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsRUFBRSxFQUFFLENBQUM7UUFDM0IsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUMzQixHQUFHLENBQUMsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNqQyxDQUFDO0lBQ0QsT0FBTyxHQUFHLENBQUM7QUFDYixDQUFDO0FBRUQsU0FBUyxRQUFRLENBQUMsS0FBOEI7SUFDOUMsSUFBSSxFQUFFLEdBQUcsUUFBUSxFQUNmLEVBQUUsR0FBRyxRQUFRLEVBQ2IsRUFBRSxHQUFHLENBQUMsUUFBUSxFQUNkLEVBQUUsR0FBRyxDQUFDLFFBQVEsQ0FBQztJQUNqQixLQUFLLE1BQU0sQ0FBQyxJQUFJLEtBQUssRUFBRSxDQUFDO1FBQ3RCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUM7WUFDekMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsRUFBRTtnQkFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQ3pCLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLEVBQUU7Z0JBQUUsRUFBRSxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztZQUN6QixJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRTtnQkFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztZQUNqQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLEdBQUcsRUFBRTtnQkFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUNuQyxDQUFDO0lBQ0gsQ0FBQztJQUNELE9BQU8sQ0FBQyxFQUFFLEVBQUUsRUFBRSxFQUFFLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQztBQUMxQixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBUaGUgcHVyZSBjb3JlIG9mIGEgdGlsZWQgcmVnaW9uIHNvdXJjZTogYSBsYXJnZSBHZW9KU09OIHJlZ2lvbiBzZXQgY3V0IGludG8gdGlsZXMgcGVyIGxldmVsXG4gKiBvZiBkZXRhaWwsIHRoZSBvdXRsaW5lcyBzaW1wbGlmaWVkIHBlciBsZXZlbCwgc28gYSB2aWV3IG9ubHkgZXZlciBob2xkcyBhbmQgZHJhd3Mgd2hhdCBpcyBvblxuICogc2NyZWVuIGF0IHRoZSBkZXRhaWwgdGhlIHpvb20gY2FuIHNob3cuXG4gKlxuICogTGV2ZWxzOiBsZXZlbCAwIGlzIGV4YWN0OyBhIGxldmVsLWsgdGlsZSBjb3ZlcnMgYHRpbGVTaXplIMK3IDLhtY9gIGltYWdlIHBpeGVscyBhbmQgaXRzIG91dGxpbmVzXG4gKiBhcmUgc2ltcGxpZmllZCAoRG91Z2xhc+KAk1BldWNrZXIpIHRvIGAy4bWP4oG7wrlgIGltYWdlIHBpeGVscyDigJQgaGFsZiB0byBvbmUgc2NyZWVuIHBpeGVsIGF0IHRoZSB6b29tc1xuICogdGhhdCBwaWNrIHRoYXQgbGV2ZWwgKHtAbGluayByZWdpb25MZXZlbEZvcn0pLiBBIGZlYXR1cmUgdW5kZXIgYDLhtY9gIGltYWdlIHBpeGVscyAob25lIHRvIHR3b1xuICogc2NyZWVuIHBpeGVscyB0aGVyZSkgaXMgbGVmdCBvdXQgb2YgdGhlIGxldmVsLiBBIHRpbGUgaG9sZHMgdGhlIFdIT0xFIHNpbXBsaWZpZWQgZmVhdHVyZSAobm90XG4gKiBjbGlwcGVkKSBmb3IgZXZlcnkgZmVhdHVyZSB3aG9zZSBib3ggbWVldHMgaXQsIHNvIGEgdmlldyBkZS1kdXBsaWNhdGVzIGZlYXR1cmVzIGJ5IGlkLCBhbmQgYXRcbiAqIGxldmVsIDAgdGhlIHRpbGVzIGluIHZpZXcgaG9sZCB0aGUgZXhhY3Qgb3V0bGluZSBvZiBldmVyeXRoaW5nIHZpc2libGUuXG4gKlxuICogTm8gRE9NLCBubyBBbmd1bGFyOiB0aGUgc2FtZSBjb2RlIHJ1bnMgaW4gdGhlIHJlZ2lvbi1zb3VyY2Ugd29ya2VyIGFuZCwgd2hlcmUgd29ya2VycyBkbyBub3RcbiAqIGV4aXN0LCBvbiB0aGUgbWFpbiB0aHJlYWQuXG4gKi9cbmltcG9ydCB7IHJnYlRvSGV4IH0gZnJvbSAnLi4vY29udHJhY3RzL2NvbG9yJztcbmltcG9ydCB7IHNpbXBsaWZ5UmluZyB9IGZyb20gJy4uL2dlb21ldHJ5L3JpbmcnO1xuaW1wb3J0IHsgcG9seWxhYmVsIH0gZnJvbSAnLi4vZ2VvbWV0cnkvcG9seWxhYmVsJztcbmltcG9ydCB7IHJpbmdzQXJlYSB9IGZyb20gJy4uL2dlb21ldHJ5L3JlY29uc3RydWN0JztcblxuLyoqIEFuIGF4aXMtYWxpZ25lZCBib3ggYFt4MCwgeTAsIHgxLCB5MV1gIGluIGltYWdlIHBpeGVscy4gKi9cbmV4cG9ydCB0eXBlIEJib3ggPSBbbnVtYmVyLCBudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcblxuLyoqIEVkZ2Ugb2YgYSBsZXZlbC0wIHRpbGUsIGluIGltYWdlIHBpeGVscy4gKi9cbmV4cG9ydCBjb25zdCBSRUdJT05fVElMRV9TSVpFID0gNTEyO1xuXG4vKipcbiAqIE9uZSBjbGFzcyBvZiBhIGNsYXNzIGhpZXJhcmNoeSAoZS5nLiBhIGJyYWluLWF0bGFzIG9udG9sb2d5KTogdGhlIGNsYXNzIG5hbWUgdGhlIGZlYXR1cmVzIHVzZSxcbiAqIGl0cyBsb25nIG5hbWUsIGl0cyBwYXJlbnQgY2xhc3MgYW5kIGl0cyBjb2xvdXIuIEEgcmVnaW9uIHNldCBtYXkgY2Fycnkgb25lIChhIEdlb0pTT05cbiAqIEZlYXR1cmVDb2xsZWN0aW9uJ3MgYGNsYXNzSGllcmFyY2h5YCBtZW1iZXIpOyB0aGUgUmVnaW9uIEVkaXRvciB0aGVuIGxpc3RzIHRoZSBzZXQgYXMgYSB0cmVlLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlZ2lvbkNsYXNzTm9kZSB7XG4gIC8qKiBUaGUgY2xhc3MgbmFtZSwgYXMgZmVhdHVyZXMgdXNlIGl0IChgY2xhc3NpZmljYXRpb24ubmFtZWApOiBhbiBhdGxhcyBhY3JvbnltLCBzYXkuICovXG4gIG5hbWU6IHN0cmluZztcbiAgLyoqIFRoZSBsb25nIG5hbWUsIGUuZy4gXCJTb21hdG9tb3RvciBhcmVhcywgTGF5ZXIgNVwiLiAqL1xuICB0aXRsZT86IHN0cmluZztcbiAgLyoqIFRoZSBwYXJlbnQgY2xhc3MncyBuYW1lOyBhYnNlbnQgZm9yIGEgcm9vdC4gKi9cbiAgcGFyZW50Pzogc3RyaW5nIHwgbnVsbDtcbiAgLyoqIGAjcnJnZ2JiYC4gKi9cbiAgY29sb3I/OiBzdHJpbmc7XG4gIC8qKiBQb3NpdGlvbiBhbW9uZyBpdHMgc2libGluZ3MgKGFuIGF0bGFzJ3MgZ3JhcGggb3JkZXIpOyBmaWxlIG9yZGVyIHdpdGhvdXQgb25lLiAqL1xuICBvcmRlcj86IG51bWJlcjtcbn1cblxuLyoqXG4gKiBIb3cgYSByZWdpb24gc2V0IHdhbnRzIHRvIGJlIGRyYXduLCBhIGhpbnQgdGhlIHZpZXdlciBhcHBsaWVzIHdoZW4gdGhlIHNldCBvcGVucyAoYSBHZW9KU09OXG4gKiBGZWF0dXJlQ29sbGVjdGlvbidzIGBzdHlsZWAgbWVtYmVyKTogYW4gYXRsYXMgZmlsbHMgaXRzIHN0cnVjdHVyZXMgYW5kIGxhYmVscyB0aGVtLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlZ2lvblNvdXJjZVN0eWxlIHtcbiAgLyoqIEZpbGwgcmVnaW9ucyBpbiB0aGVpciBjb2xvdXIgYXQgdGhpcyBvcGFjaXR5ICgwID0gb3V0bGluZXMgb25seSkuICovXG4gIGZpbGxPcGFjaXR5PzogbnVtYmVyO1xuICAvKiogT3V0bGluZSBjb2xvdXIgd2hlbiBmaWxsZWQgKGRlZmF1bHQ6IHRoZSByZWdpb24ncyBjb2xvdXIpLiAqL1xuICBzdHJva2U/OiBzdHJpbmc7XG4gIC8qKiBPdXRsaW5lIHdpZHRoIGluIHNjcmVlbiBweC4gKi9cbiAgc3Ryb2tlV2lkdGg/OiBudW1iZXI7XG4gIC8qKiBTaG93IGNsYXNzIGxhYmVscyBpbnNpZGUgdGhlIHJlZ2lvbnMuICovXG4gIGxhYmVscz86IGJvb2xlYW47XG4gIC8qKiBGaWxsIGNvbG91ciBvZiBzZWxlY3RlZCByZWdpb25zLiAqL1xuICBoaWdobGlnaHQ/OiBzdHJpbmc7XG59XG5cbi8qKiBXaGF0IGEgcmVnaW9uIHNvdXJjZSBob2xkcywga25vd24gb25jZSBpdCBpcyBvcGVuLiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWdpb25Tb3VyY2VJbmZvIHtcbiAgLyoqIEZlYXR1cmVzIGluIHRoZSBzb3VyY2UsIG92ZXIgZXZlcnkgcGxhbmUuICovXG4gIGZlYXR1cmVDb3VudDogbnVtYmVyO1xuICAvKiogVGhlIGJveCBhcm91bmQgZXZlcnkgZmVhdHVyZSdzIGdlb21ldHJ5OyBudWxsIHdoZW4gbm9uZSBoYXMgYW55LiAqL1xuICBib3VuZHM6IEJib3ggfCBudWxsO1xuICAvKiogRWRnZSBvZiBhIGxldmVsLTAgdGlsZSwgaW4gaW1hZ2UgcGl4ZWxzLiAqL1xuICB0aWxlU2l6ZTogbnVtYmVyO1xuICAvKiogTnVtYmVyIG9mIGxldmVsczsgdGhlIGxhc3Qgb25lJ3MgdGlsZXMgY292ZXIge0BsaW5rIGJvdW5kc30gaW4gYSBmZXcgdGlsZXMuICovXG4gIGxldmVsczogbnVtYmVyO1xuICAvKiogVGhlIHogcGxhbmVzIGZlYXR1cmVzIGFyZSBvbiAoUXVQYXRoJ3MgYGdlb21ldHJ5LnBsYW5lLnpgLCAwIHdpdGhvdXQgb25lKSwgYXNjZW5kaW5nLiAqL1xuICBwbGFuZXM6IG51bWJlcltdO1xuICAvKiogVGhlIGNvbG91ciB0aGUgZmlsZSBnaXZlcyBlYWNoIGNsYXNzIChpdHMgZmlyc3QgZmVhdHVyZSdzKSwgYnkgY2xhc3MgbmFtZS4gKi9cbiAgY2xhc3NDb2xvcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz47XG4gIC8qKiBUaGUgc2V0J3MgY2xhc3MgaGllcmFyY2h5LCB3aGVuIGl0IGhhcyBvbmUuICovXG4gIGhpZXJhcmNoeT86IFJlZ2lvbkNsYXNzTm9kZVtdO1xuICAvKiogSG93IHRoZSBzZXQgd2FudHMgdG8gYmUgZHJhd24sIHdoZW4gaXQgc2F5cy4gKi9cbiAgc3R5bGU/OiBSZWdpb25Tb3VyY2VTdHlsZTtcbn1cblxuLyoqIE9uZSBmZWF0dXJlIGFzIGEgdGlsZSBjYXJyaWVzIGl0OiBpZGVudGl0eSwgY2xhc3MgYW5kIG91dGxpbmUgYXQgdGhlIHRpbGUncyBsZXZlbC4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgVGlsZUZlYXR1cmUge1xuICBpZDogc3RyaW5nO1xuICAvKiogVGhlIGNsYXNzIG5hbWUuICovXG4gIGxhYmVsOiBzdHJpbmcgfCBudWxsO1xuICAvKiogVGhlIGZlYXR1cmUncyBvd24gY29sb3VyIChgI3JyZ2diYmApLCBmcm9tIGl0cyBjbGFzc2lmaWNhdGlvbi4gKi9cbiAgY29sb3I6IHN0cmluZyB8IG51bGw7XG4gIC8qKiBUaGUgYm94IGFyb3VuZCB0aGUgZXhhY3QgZ2VvbWV0cnkuICovXG4gIGJib3g6IEJib3g7XG4gIC8qKiBSaW5ncyBhcyBpbnRlcmxlYXZlZCBgeCwgeWAgKG5vIHJlcGVhdGVkIGNsb3NpbmcgdmVydGV4KTogZXh0ZXJpb3JzIGFuZCBob2xlcyBvZiBldmVyeVxuICAgKiAgcGFydCwgZHJhd24gYW5kIGhpdC10ZXN0ZWQgZXZlbi1vZGQuIEZvciBhbiBvcGVuIGZlYXR1cmUsIGl0cyBwb2x5bGluZXMuICovXG4gIHJpbmdzOiBGbG9hdDMyQXJyYXlbXTtcbiAgLyoqIEEgcG9seWxpbmUgKExpbmVTdHJpbmcpIHJhdGhlciB0aGFuIGFuIGFyZWEuICovXG4gIG9wZW46IGJvb2xlYW47XG4gIC8qKlxuICAgKiBXaGVyZSB0byBsYWJlbCB0aGUgZmVhdHVyZSwgcGVyIHBhcnQgYmlnIGVub3VnaDogYHgsIHksIHJvb21gIHRyaXBsZXMsIGByb29tYCB0aGUgZGlzdGFuY2VcbiAgICogZnJvbSB0aGUgcG9pbnQgdG8gdGhlIHBhcnQncyBuZWFyZXN0IGVkZ2UgKGltYWdlIHB4KSwgc28gYSBsYWJlbCBzaG93cyBvbmNlIGl0IGZpdHMuXG4gICAqL1xuICBsYWJlbHM/OiBGbG9hdDMyQXJyYXk7XG59XG5cbi8qKlxuICogQSBjbGFzcydzIG91dGxpbmVzIG9uIG9uZSBwbGFuZTogcmluZ3MgYXMgaW50ZXJsZWF2ZWQgYHgsIHlgIGltYWdlIHB4IChob2xlcyBpbmNsdWRlZCksIGFuZCBpdHNcbiAqIG9wZW4gZmVhdHVyZXMnIHBvbHlsaW5lcywgbGlrZXdpc2UgKGFic2VudCBmcm9tIGEgc2VydmVyIHRoYXQgcHJlZGF0ZXMgdGhlbSkuIFJlYWQgZm9yIGV2ZXJ5XG4gKiBjbGFzcyBhdCBvbmNlLCBlYWNoIHJpbmcncyBhbmQgbGluZSdzIGNsYXNzIGNvbWVzIHdpdGggaXQgKGByaW5nTGFiZWxzYCwgYGxpbmVMYWJlbHNgKS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDbGFzc091dGxpbmVzIHtcbiAgejogbnVtYmVyO1xuICByaW5nczogRmxvYXQzMkFycmF5W107XG4gIC8qKlxuICAgKiBUaGUgZmVhdHVyZSBlYWNoIHJpbmcgaXMgcGFydCBvZiAoc2VlIFNsaWNlT3V0bGluZXMucmluZ0dyb3Vwcyk6IGEgZmVhdHVyZSdzIHJpbmdzIGZpbGxcbiAgICogZXZlbi1vZGQsIHRoZSBmZWF0dXJlcyBhcyB0aGVpciB1bmlvbi4gQWJzZW50IGZyb20gYSBzZXJ2ZXIgdGhhdCBwcmVkYXRlcyB0aGVtLlxuICAgKi9cbiAgcmluZ0dyb3Vwcz86IG51bWJlcltdO1xuICBsaW5lcz86IEZsb2F0MzJBcnJheVtdO1xuICByaW5nTGFiZWxzPzogc3RyaW5nW107XG4gIGxpbmVMYWJlbHM/OiBzdHJpbmdbXTtcbn1cblxuLyoqIE9uZSB0aWxlIG9mIG9uZSBsZXZlbCBvZiBvbmUgcGxhbmUuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlZ2lvblRpbGUge1xuICB6OiBudW1iZXI7XG4gIGxldmVsOiBudW1iZXI7XG4gIGd4OiBudW1iZXI7XG4gIGd5OiBudW1iZXI7XG4gIGZlYXR1cmVzOiBUaWxlRmVhdHVyZVtdO1xufVxuXG4vKiogQSB0aWxlJ3MgYWRkcmVzcy4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUmVnaW9uVGlsZUtleSB7XG4gIGxldmVsOiBudW1iZXI7XG4gIGd4OiBudW1iZXI7XG4gIGd5OiBudW1iZXI7XG59XG5cbi8qKiBPbmUgcm93IG9mIGEgc291cmNlJ3MgZmVhdHVyZSBpbmRleCAodGhlIFJlZ2lvbiBFZGl0b3IncyB0YWJsZSkuICovXG5leHBvcnQgaW50ZXJmYWNlIFJlZ2lvbkluZGV4Um93IHtcbiAgaWQ6IHN0cmluZztcbiAgbGFiZWw6IHN0cmluZyB8IG51bGw7XG4gIGNvbG9yOiBzdHJpbmcgfCBudWxsO1xuICBiYm94OiBCYm94O1xuICAvKiogVGhlIGFyZWEgaW5zaWRlIHRoZSBleGFjdCBvdXRsaW5lIChob2xlcyBsZWZ0IG91dCksIGltYWdlIHB4wrI7IDAgZm9yIGEgcG9seWxpbmUuIEFic2VudCBmcm9tIGFcbiAgICogIHNlcnZlciB0aGF0IHByZWRhdGVzIGl0LiAqL1xuICBhcmVhPzogbnVtYmVyO1xufVxuXG4vKiogQSBwYWdlIG9mIGEgcGxhbmUncyBmZWF0dXJlIGluZGV4LiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWdpb25JbmRleFBhZ2Uge1xuICAvKiogUm93cyBtYXRjaGluZyB0aGUgcXVlcnksIG92ZXIgdGhlIHdob2xlIHBsYW5lLiAqL1xuICB0b3RhbDogbnVtYmVyO1xuICByb3dzOiBSZWdpb25JbmRleFJvd1tdO1xufVxuXG4vKiogV2hpY2ggcm93cyBhIHBhZ2Ugb2YgdGhlIGluZGV4IGhvbGRzLiAqL1xuZXhwb3J0IGludGVyZmFjZSBSZWdpb25JbmRleFF1ZXJ5IHtcbiAgb2Zmc2V0OiBudW1iZXI7XG4gIGxpbWl0OiBudW1iZXI7XG4gIC8qKiBPbmx5IHJvd3Mgd2hvc2UgY2xhc3MgbmFtZSBjb250YWlucyB0aGlzIChjYXNlLWluc2Vuc2l0aXZlKS4gKi9cbiAgbGFiZWw/OiBzdHJpbmc7XG4gIC8qKiBMZWF2ZSB0aGVzZSBpZHMgb3V0ICh0YWtlbiBpbnRvIHRoZSB3b3JraW5nIHNldCwgb3IgZGVsZXRlZCkuICovXG4gIGV4Y2x1ZGU/OiByZWFkb25seSBzdHJpbmdbXTtcbiAgLyoqIE9ubHkgcm93cyBvZiBleGFjdGx5IHRoZXNlIGNsYXNzZXMuICovXG4gIGNsYXNzZXM/OiByZWFkb25seSBzdHJpbmdbXTtcbn1cblxuLyoqIFRoZSBwYXJ0cyBvZiBhIEdlb0pTT04gZmVhdHVyZSB0aGUgdGlsZXIgcmVhZHMuIFBhcnNlZCBmcm9tIGEgZmlsZTogbm90aGluZyBpcyBndWFyYW50ZWVkLiAqL1xuZXhwb3J0IGludGVyZmFjZSBHZW9Kc29uRmVhdHVyZUxpa2Uge1xuICB0eXBlPzogc3RyaW5nO1xuICBpZD86IHN0cmluZyB8IG51bWJlcjtcbiAgZ2VvbWV0cnk/OiB7IHR5cGU/OiBzdHJpbmc7IGNvb3JkaW5hdGVzPzogdW5rbm93bjsgcGxhbmU/OiB7IHo/OiBudW1iZXIgfSB9IHwgbnVsbDtcbiAgcHJvcGVydGllcz86IHsgaWQ/OiBzdHJpbmcgfCBudW1iZXI7IGNsYXNzaWZpY2F0aW9uPzogdW5rbm93biB9ICYgUmVjb3JkPHN0cmluZywgdW5rbm93bj47XG59XG5cbi8qKlxuICogVGhlIGxldmVsIHdob3NlIHRpbGVzIHN1aXQgYSB6b29tIG9mIGBweFBlckltYWdlUHhgIHNjcmVlbiBwaXhlbHMgcGVyIGltYWdlIHBpeGVsOiBleGFjdCAoMClcbiAqIGF0IDE6MSBhbmQgY2xvc2VyLCBlbHNlIGxldmVsIGsgZm9yIHpvb21zIGluIFsy4oG74bWPLCAywrnigbvhtY8pLCB3aGVyZSBpdHMgdG9sZXJhbmNlIGlzIGhhbGYgdG8gb25lXG4gKiBzY3JlZW4gcGl4ZWwgYW5kIHRoZSBmZWF0dXJlcyBpdCBsZWF2ZXMgb3V0IGFyZSB1bmRlciBvbmUgb3IgdHdvLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcmVnaW9uTGV2ZWxGb3IocHhQZXJJbWFnZVB4OiBudW1iZXIsIGxldmVsczogbnVtYmVyKTogbnVtYmVyIHtcbiAgaWYgKCEocHhQZXJJbWFnZVB4ID4gMCkgfHwgbGV2ZWxzIDw9IDEpIHJldHVybiAwO1xuICBjb25zdCBsZXZlbCA9IE1hdGguY2VpbCgtTWF0aC5sb2cyKHB4UGVySW1hZ2VQeCkgLSAxZS05KTtcbiAgcmV0dXJuIE1hdGgubWF4KDAsIE1hdGgubWluKGxldmVscyAtIDEsIGxldmVsKSk7XG59XG5cbi8qKiBTaW1wbGlmaWNhdGlvbiB0b2xlcmFuY2Ugb2YgYSBsZXZlbCwgaW4gaW1hZ2UgcGl4ZWxzICgwID0gZXhhY3QpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxldmVsVG9sZXJhbmNlKGxldmVsOiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gbGV2ZWwgPD0gMCA/IDAgOiAyICoqIChsZXZlbCAtIDEpO1xufVxuXG4vKiogRmVhdHVyZXMgc21hbGxlciB0aGFuIHRoaXMgKHRoZWlyIGJveCdzIGxvbmdlciBzaWRlLCBpbWFnZSBwaXhlbHMpIGFyZSBsZWZ0IG91dCBvZiBhIGxldmVsLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxldmVsTWluRXh0ZW50KGxldmVsOiBudW1iZXIpOiBudW1iZXIge1xuICByZXR1cm4gbGV2ZWwgPD0gMCA/IDAgOiAyICoqIGxldmVsO1xufVxuXG4vKiogVGlsZSBlZGdlIG9mIGEgbGV2ZWwsIGluIGltYWdlIHBpeGVscy4gKi9cbmV4cG9ydCBmdW5jdGlvbiBsZXZlbFRpbGVTaXplKGxldmVsOiBudW1iZXIsIHRpbGVTaXplID0gUkVHSU9OX1RJTEVfU0laRSk6IG51bWJlciB7XG4gIHJldHVybiB0aWxlU2l6ZSAqIDIgKiogbGV2ZWw7XG59XG5cbi8qKlxuICogVGlsZXMgb2YgYGxldmVsYCB0aGF0IG1lZXQgYHJlY3RgLCBjbGlwcGVkIHRvIGBib3VuZHNgIChub25lIHBhc3QgdGhlIGRhdGEpLCBvcmRlcmVkIGZyb20gdGhlXG4gKiByZWN0YW5nbGUncyBjZW50cmUgb3V0d2FyZCBzbyB0aGUgbWlkZGxlIG9mIHRoZSBzY3JlZW4gZmlsbHMgZmlyc3QuIEF0IG1vc3QgYGxpbWl0YC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlZ2lvblRpbGVzSW5SZWN0KFxuICByZWN0OiBCYm94LFxuICBsZXZlbDogbnVtYmVyLFxuICB0aWxlU2l6ZTogbnVtYmVyLFxuICBib3VuZHM6IEJib3ggfCBudWxsLFxuICBsaW1pdCA9IEluZmluaXR5LFxuKTogUmVnaW9uVGlsZUtleVtdIHtcbiAgaWYgKCFib3VuZHMpIHJldHVybiBbXTtcbiAgY29uc3QgeDAgPSBNYXRoLm1heChyZWN0WzBdLCBib3VuZHNbMF0pO1xuICBjb25zdCB5MCA9IE1hdGgubWF4KHJlY3RbMV0sIGJvdW5kc1sxXSk7XG4gIGNvbnN0IHgxID0gTWF0aC5taW4ocmVjdFsyXSwgYm91bmRzWzJdKTtcbiAgY29uc3QgeTEgPSBNYXRoLm1pbihyZWN0WzNdLCBib3VuZHNbM10pO1xuICBpZiAoeDEgPCB4MCB8fCB5MSA8IHkwKSByZXR1cm4gW107XG4gIGNvbnN0IHNpemUgPSBsZXZlbFRpbGVTaXplKGxldmVsLCB0aWxlU2l6ZSk7XG4gIGNvbnN0IGd4MCA9IE1hdGguZmxvb3IoeDAgLyBzaXplKTtcbiAgY29uc3QgZ3kwID0gTWF0aC5mbG9vcih5MCAvIHNpemUpO1xuICBjb25zdCBneDEgPSBNYXRoLmZsb29yKHgxIC8gc2l6ZSk7XG4gIGNvbnN0IGd5MSA9IE1hdGguZmxvb3IoeTEgLyBzaXplKTtcbiAgY29uc3QgY3ggPSAocmVjdFswXSArIHJlY3RbMl0pIC8gMiAvIHNpemU7XG4gIGNvbnN0IGN5ID0gKHJlY3RbMV0gKyByZWN0WzNdKSAvIDIgLyBzaXplO1xuICBjb25zdCBvdXQ6IFJlZ2lvblRpbGVLZXlbXSA9IFtdO1xuICBmb3IgKGxldCBneSA9IGd5MDsgZ3kgPD0gZ3kxOyBneSsrKSB7XG4gICAgZm9yIChsZXQgZ3ggPSBneDA7IGd4IDw9IGd4MTsgZ3grKykgb3V0LnB1c2goeyBsZXZlbCwgZ3gsIGd5IH0pO1xuICB9XG4gIGNvbnN0IGQgPSAoazogUmVnaW9uVGlsZUtleSkgPT4gKGsuZ3ggKyAwLjUgLSBjeCkgKiogMiArIChrLmd5ICsgMC41IC0gY3kpICoqIDI7XG4gIG91dC5zb3J0KChhLCBiKSA9PiBkKGEpIC0gZChiKSk7XG4gIHJldHVybiBvdXQubGVuZ3RoID4gbGltaXQgPyBvdXQuc2xpY2UoMCwgbGltaXQpIDogb3V0O1xufVxuXG4vKiogYGxldmVsL2d4L2d5YCwgYSB0aWxlJ3MgaWQgd2l0aGluIG9uZSBwbGFuZS4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWdpb25UaWxlSWQoazogUmVnaW9uVGlsZUtleSk6IHN0cmluZyB7XG4gIHJldHVybiBgJHtrLmxldmVsfS8ke2suZ3h9LyR7ay5neX1gO1xufVxuXG4vKiogVGhlIHRpbGUgb2YgYGxldmVsYCBob2xkaW5nIGltYWdlIHBvaW50ICh4LCB5KS4gKi9cbmV4cG9ydCBmdW5jdGlvbiB0aWxlQXQoeDogbnVtYmVyLCB5OiBudW1iZXIsIGxldmVsOiBudW1iZXIsIHRpbGVTaXplID0gUkVHSU9OX1RJTEVfU0laRSk6IFJlZ2lvblRpbGVLZXkge1xuICBjb25zdCBzaXplID0gbGV2ZWxUaWxlU2l6ZShsZXZlbCwgdGlsZVNpemUpO1xuICByZXR1cm4geyBsZXZlbCwgZ3g6IE1hdGguZmxvb3IoeCAvIHNpemUpLCBneTogTWF0aC5mbG9vcih5IC8gc2l6ZSkgfTtcbn1cblxuLyoqIFRydWUgd2hlbiB0d28gYm94ZXMgbWVldCAoZWRnZXMgaW5jbHVkZWQpLiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGJib3hlc01lZXQoYTogUmVhZG9ubHk8QmJveD4sIGI6IFJlYWRvbmx5PEJib3g+KTogYm9vbGVhbiB7XG4gIHJldHVybiBhWzBdIDw9IGJbMl0gJiYgYVsyXSA+PSBiWzBdICYmIGFbMV0gPD0gYlszXSAmJiBhWzNdID49IGJbMV07XG59XG5cbi8vIOKUgOKUgCBQaWNraW5nIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4vKipcbiAqIFRoZSBmZWF0dXJlIHVuZGVyIGltYWdlIHBvaW50ICh4LCB5KTogaW5zaWRlIGFuIGFyZWEgKGV2ZW4tb2RkIG92ZXIgaXRzIHJpbmdzLCBzbyBob2xlcyBhcmVcbiAqIG91dHNpZGUpIG9yIHdpdGhpbiBgdG9sZXJhbmNlYCBpbWFnZSBwaXhlbHMgb2YgYSBwb2x5bGluZS4gT2Ygc2V2ZXJhbCwgdGhlIG9uZSB3aXRoIHRoZVxuICogc21hbGxlc3QgYm94IOKAlCB0aGUgaW5uZXJtb3N0IG9mIG5lc3RlZCBvdXRsaW5lcy4gTnVsbCB3aGVuIG5vbmUgaXMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmZWF0dXJlQXQoXG4gIGZlYXR1cmVzOiBJdGVyYWJsZTxUaWxlRmVhdHVyZT4sXG4gIHg6IG51bWJlcixcbiAgeTogbnVtYmVyLFxuICB0b2xlcmFuY2UgPSAwLFxuKTogVGlsZUZlYXR1cmUgfCBudWxsIHtcbiAgbGV0IGJlc3Q6IFRpbGVGZWF0dXJlIHwgbnVsbCA9IG51bGw7XG4gIGxldCBiZXN0QXJlYSA9IEluZmluaXR5O1xuICBmb3IgKGNvbnN0IGYgb2YgZmVhdHVyZXMpIHtcbiAgICBjb25zdCBiID0gZi5iYm94O1xuICAgIGlmICh4IDwgYlswXSAtIHRvbGVyYW5jZSB8fCB4ID4gYlsyXSArIHRvbGVyYW5jZSB8fCB5IDwgYlsxXSAtIHRvbGVyYW5jZSB8fCB5ID4gYlszXSArIHRvbGVyYW5jZSkgY29udGludWU7XG4gICAgY29uc3QgaGl0ID0gZi5vcGVuID8gbmVhclBvbHlsaW5lcyhmLnJpbmdzLCB4LCB5LCB0b2xlcmFuY2UpIDogaW5zaWRlUmluZ3MoZi5yaW5ncywgeCwgeSk7XG4gICAgaWYgKCFoaXQpIGNvbnRpbnVlO1xuICAgIGNvbnN0IGFyZWEgPSAoYlsyXSAtIGJbMF0pICogKGJbM10gLSBiWzFdKTtcbiAgICBpZiAoYXJlYSA8IGJlc3RBcmVhKSB7XG4gICAgICBiZXN0ID0gZjtcbiAgICAgIGJlc3RBcmVhID0gYXJlYTtcbiAgICB9XG4gIH1cbiAgcmV0dXJuIGJlc3Q7XG59XG5cbi8qKiBGZWF0dXJlcyB3aG9zZSBib3ggbWVldHMgYHJlY3RgICh0aGUgcnViYmVyIGJhbmQncyBydWxlIGZvciByZWdpb25zKS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBmZWF0dXJlc0luUmVjdChmZWF0dXJlczogSXRlcmFibGU8VGlsZUZlYXR1cmU+LCByZWN0OiBSZWFkb25seTxCYm94Pik6IFRpbGVGZWF0dXJlW10ge1xuICBjb25zdCBvdXQ6IFRpbGVGZWF0dXJlW10gPSBbXTtcbiAgZm9yIChjb25zdCBmIG9mIGZlYXR1cmVzKSBpZiAoYmJveGVzTWVldChmLmJib3gsIHJlY3QpKSBvdXQucHVzaChmKTtcbiAgcmV0dXJuIG91dDtcbn1cblxuLyoqIEV2ZW4tb2RkIGNvbnRhaW5tZW50IG92ZXIgaW50ZXJsZWF2ZWQgcmluZ3MuICovXG5leHBvcnQgZnVuY3Rpb24gaW5zaWRlUmluZ3MocmluZ3M6IHJlYWRvbmx5IEFycmF5TGlrZTxudW1iZXI+W10sIHg6IG51bWJlciwgeTogbnVtYmVyKTogYm9vbGVhbiB7XG4gIGxldCBpbnNpZGUgPSBmYWxzZTtcbiAgZm9yIChjb25zdCByIG9mIHJpbmdzKSB7XG4gICAgY29uc3QgbiA9IHIubGVuZ3RoID4+IDE7XG4gICAgaWYgKG4gPCAzKSBjb250aW51ZTtcbiAgICBmb3IgKGxldCBpID0gMCwgaiA9IG4gLSAxOyBpIDwgbjsgaiA9IGkrKykge1xuICAgICAgY29uc3QgeGkgPSByWzIgKiBpXSxcbiAgICAgICAgeWkgPSByWzIgKiBpICsgMV0sXG4gICAgICAgIHhqID0gclsyICogal0sXG4gICAgICAgIHlqID0gclsyICogaiArIDFdO1xuICAgICAgaWYgKHlpID4geSAhPT0geWogPiB5ICYmIHggPCAoKHhqIC0geGkpICogKHkgLSB5aSkpIC8gKHlqIC0geWkpICsgeGkpIGluc2lkZSA9ICFpbnNpZGU7XG4gICAgfVxuICB9XG4gIHJldHVybiBpbnNpZGU7XG59XG5cbmZ1bmN0aW9uIG5lYXJQb2x5bGluZXMobGluZXM6IHJlYWRvbmx5IEFycmF5TGlrZTxudW1iZXI+W10sIHg6IG51bWJlciwgeTogbnVtYmVyLCB0b2xlcmFuY2U6IG51bWJlcik6IGJvb2xlYW4ge1xuICBmb3IgKGNvbnN0IGwgb2YgbGluZXMpIHtcbiAgICBmb3IgKGxldCBpID0gMjsgaSArIDEgPCBsLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgICBpZiAoc2VnbWVudERpc3RhbmNlKHgsIHksIGxbaSAtIDJdLCBsW2kgLSAxXSwgbFtpXSwgbFtpICsgMV0pIDw9IHRvbGVyYW5jZSkgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cblxuZnVuY3Rpb24gc2VnbWVudERpc3RhbmNlKHB4OiBudW1iZXIsIHB5OiBudW1iZXIsIGF4OiBudW1iZXIsIGF5OiBudW1iZXIsIGJ4OiBudW1iZXIsIGJ5OiBudW1iZXIpOiBudW1iZXIge1xuICBjb25zdCBkeCA9IGJ4IC0gYXgsXG4gICAgZHkgPSBieSAtIGF5O1xuICBjb25zdCBsZW4yID0gZHggKiBkeCArIGR5ICogZHk7XG4gIGNvbnN0IHQgPSBsZW4yID09PSAwID8gMCA6IE1hdGgubWF4KDAsIE1hdGgubWluKDEsICgocHggLSBheCkgKiBkeCArIChweSAtIGF5KSAqIGR5KSAvIGxlbjIpKTtcbiAgcmV0dXJuIE1hdGguaHlwb3QocHggLSAoYXggKyB0ICogZHgpLCBweSAtIChheSArIHQgKiBkeSkpO1xufVxuXG4vLyDilIDilIAgU2ltcGxpZmljYXRpb24g4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSA4pSAXG5cbi8qKiBEb3VnbGFz4oCTUGV1Y2tlciBvdmVyIGFuIG9wZW4gcG9seWxpbmUgKGJvdGggZW5kcyBrZXB0KS4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzaW1wbGlmeVBvbHlsaW5lKHhzOiBudW1iZXJbXSwgeXM6IG51bWJlcltdLCBlcHNpbG9uOiBudW1iZXIpOiB7IHhzOiBudW1iZXJbXTsgeXM6IG51bWJlcltdIH0ge1xuICBjb25zdCBuID0geHMubGVuZ3RoO1xuICBpZiAobiA8PSAyIHx8ICEoZXBzaWxvbiA+IDApKSByZXR1cm4geyB4czogeHMuc2xpY2UoKSwgeXM6IHlzLnNsaWNlKCkgfTtcbiAgY29uc3Qga2VlcCA9IG5ldyBVaW50OEFycmF5KG4pO1xuICBrZWVwWzBdID0ga2VlcFtuIC0gMV0gPSAxO1xuICBjb25zdCBzdGFjazogQXJyYXk8W251bWJlciwgbnVtYmVyXT4gPSBbWzAsIG4gLSAxXV07XG4gIHdoaWxlIChzdGFjay5sZW5ndGgpIHtcbiAgICBjb25zdCBbYSwgYl0gPSBzdGFjay5wb3AoKSBhcyBbbnVtYmVyLCBudW1iZXJdO1xuICAgIGxldCBtYXhEID0gLTEsXG4gICAgICBpZHggPSAtMTtcbiAgICBmb3IgKGxldCBpID0gYSArIDE7IGkgPCBiOyBpKyspIHtcbiAgICAgIGNvbnN0IGQgPSBzZWdtZW50RGlzdGFuY2UoeHNbaV0sIHlzW2ldLCB4c1thXSwgeXNbYV0sIHhzW2JdLCB5c1tiXSk7XG4gICAgICBpZiAoZCA+IG1heEQpIHtcbiAgICAgICAgbWF4RCA9IGQ7XG4gICAgICAgIGlkeCA9IGk7XG4gICAgICB9XG4gICAgfVxuICAgIGlmIChtYXhEID4gZXBzaWxvbikge1xuICAgICAga2VlcFtpZHhdID0gMTtcbiAgICAgIHN0YWNrLnB1c2goW2EsIGlkeF0sIFtpZHgsIGJdKTtcbiAgICB9XG4gIH1cbiAgY29uc3Qgb3g6IG51bWJlcltdID0gW10sXG4gICAgb3k6IG51bWJlcltdID0gW107XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgaWYgKGtlZXBbaV0pIHtcbiAgICAgIG94LnB1c2goeHNbaV0pO1xuICAgICAgb3kucHVzaCh5c1tpXSk7XG4gICAgfVxuICB9XG4gIHJldHVybiB7IHhzOiBveCwgeXM6IG95IH07XG59XG5cbi8qKlxuICogUmluZ3Mgc2ltcGxpZmllZCBmb3IgYSBsZXZlbDogZXZlcnkgcmluZyB0aHJvdWdoIERvdWdsYXPigJNQZXVja2VyIGF0IHRoZSBsZXZlbCdzIHRvbGVyYW5jZSxcbiAqIHJpbmdzIHdob3NlIGJveCBpcyB1bmRlciB0aGUgbGV2ZWwncyBtaW5pbXVtIGV4dGVudCBkcm9wcGVkLCBhbmQgcmluZ3MgbGVmdCB3aXRoIHRvbyBmZXdcbiAqIHZlcnRpY2VzIHRvIGRyYXcgKDMgZm9yIGEgY2xvc2VkIHJpbmcsIDIgZm9yIGEgcG9seWxpbmUpIGRyb3BwZWQuIExldmVsIDAgcmV0dXJucyB0aGUgcmluZ3NcbiAqIGFzIHRoZXkgYXJlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gc2ltcGxpZnlSaW5ncyhyaW5nczogcmVhZG9ubHkgRmxvYXQ2NEFycmF5W10sIG9wZW46IGJvb2xlYW4sIGxldmVsOiBudW1iZXIpOiBGbG9hdDMyQXJyYXlbXSB7XG4gIGNvbnN0IHRvbCA9IGxldmVsVG9sZXJhbmNlKGxldmVsKTtcbiAgY29uc3QgbWluRXh0ZW50ID0gbGV2ZWxNaW5FeHRlbnQobGV2ZWwpO1xuICBjb25zdCBtaW5WZXJ0aWNlcyA9IG9wZW4gPyAyIDogMztcbiAgY29uc3Qgb3V0OiBGbG9hdDMyQXJyYXlbXSA9IFtdO1xuICBmb3IgKGNvbnN0IHJpbmcgb2YgcmluZ3MpIHtcbiAgICBjb25zdCBuID0gcmluZy5sZW5ndGggPj4gMTtcbiAgICBpZiAobiA8IG1pblZlcnRpY2VzKSBjb250aW51ZTtcbiAgICBpZiAodG9sID09PSAwKSB7XG4gICAgICBvdXQucHVzaChGbG9hdDMyQXJyYXkuZnJvbShyaW5nKSk7XG4gICAgICBjb250aW51ZTtcbiAgICB9XG4gICAgY29uc3QgeHMgPSBuZXcgQXJyYXk8bnVtYmVyPihuKSxcbiAgICAgIHlzID0gbmV3IEFycmF5PG51bWJlcj4obik7XG4gICAgbGV0IHgwID0gSW5maW5pdHksXG4gICAgICB5MCA9IEluZmluaXR5LFxuICAgICAgeDEgPSAtSW5maW5pdHksXG4gICAgICB5MSA9IC1JbmZpbml0eTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IG47IGkrKykge1xuICAgICAgY29uc3QgeCA9IHJpbmdbMiAqIGldLFxuICAgICAgICB5ID0gcmluZ1syICogaSArIDFdO1xuICAgICAgeHNbaV0gPSB4O1xuICAgICAgeXNbaV0gPSB5O1xuICAgICAgaWYgKHggPCB4MCkgeDAgPSB4O1xuICAgICAgaWYgKHggPiB4MSkgeDEgPSB4O1xuICAgICAgaWYgKHkgPCB5MCkgeTAgPSB5O1xuICAgICAgaWYgKHkgPiB5MSkgeTEgPSB5O1xuICAgIH1cbiAgICBpZiAoTWF0aC5tYXgoeDEgLSB4MCwgeTEgLSB5MCkgPCBtaW5FeHRlbnQpIGNvbnRpbnVlO1xuICAgIGNvbnN0IHMgPSBvcGVuID8gc2ltcGxpZnlQb2x5bGluZSh4cywgeXMsIHRvbCkgOiBzaW1wbGlmeVJpbmcoeHMsIHlzLCB0b2wpO1xuICAgIGlmIChzLnhzLmxlbmd0aCA8IG1pblZlcnRpY2VzKSBjb250aW51ZTtcbiAgICBjb25zdCBmbGF0ID0gbmV3IEZsb2F0MzJBcnJheShzLnhzLmxlbmd0aCAqIDIpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgcy54cy5sZW5ndGg7IGkrKykge1xuICAgICAgZmxhdFsyICogaV0gPSBzLnhzW2ldO1xuICAgICAgZmxhdFsyICogaSArIDFdID0gcy55c1tpXTtcbiAgICB9XG4gICAgb3V0LnB1c2goZmxhdCk7XG4gIH1cbiAgcmV0dXJuIG91dDtcbn1cblxuLy8g4pSA4pSAIFRoZSBmZWF0dXJlIHRhYmxlIOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgOKUgFxuXG4vKiogRmVhdHVyZXMgKGFuZCB0aGVpciBzaW1wbGlmaWVkIG91dGxpbmVzKSBjYWNoZWQgcGVyIGxldmVsLCBwYXN0IHdoaWNoIHRoZSBvbGRlc3QgZ28uICovXG5jb25zdCBTSU1QTElGSUVEX0NBQ0hFX0xJTUlUID0gMjAwXzAwMDtcblxuLyoqXG4gKiBBIHBhcnNlZCBHZW9KU09OIHJlZ2lvbiBzZXQsIGluZGV4ZWQgZm9yIHRpbGVzLiBIb2xkcyB0aGUgcmF3IGZlYXR1cmVzIChmb3IgdGhlIGV4YWN0XG4gKiBnZW9tZXRyeSBhbmQgdGhlIGV4cG9ydCksIGVhY2ggZmVhdHVyZSdzIHJpbmdzLCBib3gsIHBsYW5lIGFuZCBjbGFzcywgYW5kIGJ1aWxkcyBhIGxldmVsJ3NcbiAqIHRpbGUgYnVja2V0cyB0aGUgZmlyc3QgdGltZSB0aGF0IGxldmVsIG9mIGEgcGxhbmUgaXMgYXNrZWQgZm9yLlxuICovXG5leHBvcnQgY2xhc3MgUmVnaW9uRmVhdHVyZVRhYmxlIHtcbiAgcmVhZG9ubHkgaWRzOiBzdHJpbmdbXSA9IFtdO1xuICByZWFkb25seSBsYWJlbHM6IEFycmF5PHN0cmluZyB8IG51bGw+ID0gW107XG4gIHJlYWRvbmx5IGNvbG9yczogQXJyYXk8c3RyaW5nIHwgbnVsbD4gPSBbXTtcbiAgcmVhZG9ubHkgcGxhbmVzOiBudW1iZXJbXSA9IFtdO1xuICByZWFkb25seSBib3hlczogQmJveFtdID0gW107XG4gIHJlYWRvbmx5IHJpbmdzOiBGbG9hdDY0QXJyYXlbXVtdID0gW107XG4gIHJlYWRvbmx5IG9wZW46IGJvb2xlYW5bXSA9IFtdO1xuICAvKiogUGVyIGZlYXR1cmUsIGl0cyBwYXJ0cyBhcyByaW5nIGluZGljZXMgKHRoZSBleHRlcmlvciBmaXJzdCwgdGhlbiBpdHMgaG9sZXMpLiAqL1xuICByZWFkb25seSBwYXJ0czogbnVtYmVyW11bXVtdID0gW107XG4gIHByaXZhdGUgcmVhZG9ubHkgbGFiZWxQb2ludHMgPSBuZXcgTWFwPG51bWJlciwgRmxvYXQzMkFycmF5PigpO1xuICAvKiogRWFjaCBmZWF0dXJlJ3MgYXJlYSwgd29ya2VkIG91dCB0aGUgZmlyc3QgdGltZSBpdHMgcm93IGlzIGFza2VkIGZvci4gKi9cbiAgcHJpdmF0ZSByZWFkb25seSBhcmVhcyA9IG5ldyBNYXA8bnVtYmVyLCBudW1iZXI+KCk7XG4gIHByaXZhdGUgaGllcmFyY2h5PzogUmVnaW9uQ2xhc3NOb2RlW107XG4gIHByaXZhdGUgc3R5bGU/OiBSZWdpb25Tb3VyY2VTdHlsZTtcbiAgcHJpdmF0ZSByZWFkb25seSBieUlkID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcj4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBidWNrZXRzID0gbmV3IE1hcDxzdHJpbmcsIExldmVsSW5kZXg+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgc2ltcGxpZmllZCA9IG5ldyBNYXA8c3RyaW5nLCBGbG9hdDMyQXJyYXlbXT4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBib3VuZHM6IEJib3ggfCBudWxsO1xuICBwcml2YXRlIHJlYWRvbmx5IGxldmVsczogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlYWRvbmx5IHJhdzogR2VvSnNvbkZlYXR1cmVMaWtlW10sXG4gICAgcmVhZG9ubHkgdGlsZVNpemUgPSBSRUdJT05fVElMRV9TSVpFLFxuICApIHtcbiAgICBsZXQgeDAgPSBJbmZpbml0eSxcbiAgICAgIHkwID0gSW5maW5pdHksXG4gICAgICB4MSA9IC1JbmZpbml0eSxcbiAgICAgIHkxID0gLUluZmluaXR5O1xuICAgIHJhdy5mb3JFYWNoKChmZWF0dXJlLCBpKSA9PiB7XG4gICAgICBjb25zdCBvd24gPSBmZWF0dXJlSWRPZihmZWF0dXJlKTtcbiAgICAgIGxldCBpZCA9IG93bjtcbiAgICAgIGlmIChpZCA9PT0gdW5kZWZpbmVkIHx8IHRoaXMuYnlJZC5oYXMoaWQpKSB7XG4gICAgICAgIC8vIEl0cyBwb3NpdGlvbiwgdW5sZXNzIGEgZmVhdHVyZSBhbHJlYWR5IGhhcyB0aGF0IGlkIChhbiBleHBsaWNpdCBcIiMxXCIsIHNheSk6IGlkcyBhcmUgdW5pcXVlLFxuICAgICAgICAvLyBvciBhIHRha2UsIGFuIGV4Y2x1c2lvbiBvciBhbiBleHBvcnQgd291bGQgYWN0IG9uIGJvdGguXG4gICAgICAgIGlkID0gYCMke2l9YDtcbiAgICAgICAgZm9yIChsZXQgayA9IDE7IHRoaXMuYnlJZC5oYXMoaWQpOyBrKyspIGlkID0gYCMke2l9LSR7a31gO1xuICAgICAgfVxuICAgICAgdGhpcy5ieUlkLnNldChpZCwgaSk7XG4gICAgICB0aGlzLmlkcy5wdXNoKGlkKTtcbiAgICAgIGNvbnN0IHsgbGFiZWwsIGNvbG9yIH0gPSBjbGFzc2lmaWNhdGlvbk9mKGZlYXR1cmUpO1xuICAgICAgdGhpcy5sYWJlbHMucHVzaChsYWJlbCk7XG4gICAgICB0aGlzLmNvbG9ycy5wdXNoKGNvbG9yKTtcbiAgICAgIHRoaXMucGxhbmVzLnB1c2goZmVhdHVyZT8uZ2VvbWV0cnk/LnBsYW5lPy56ID8/IDApO1xuICAgICAgY29uc3QgeyByaW5ncywgb3BlbiwgcGFydHMgfSA9IHJpbmdzT2YoZmVhdHVyZSk7XG4gICAgICB0aGlzLnJpbmdzLnB1c2gocmluZ3MpO1xuICAgICAgdGhpcy5vcGVuLnB1c2gob3Blbik7XG4gICAgICB0aGlzLnBhcnRzLnB1c2gocGFydHMpO1xuICAgICAgY29uc3QgYm94ID0gcmluZ3NCb3gocmluZ3MpO1xuICAgICAgdGhpcy5ib3hlcy5wdXNoKGJveCk7XG4gICAgICBpZiAocmluZ3MubGVuZ3RoKSB7XG4gICAgICAgIHgwID0gTWF0aC5taW4oeDAsIGJveFswXSk7XG4gICAgICAgIHkwID0gTWF0aC5taW4oeTAsIGJveFsxXSk7XG4gICAgICAgIHgxID0gTWF0aC5tYXgoeDEsIGJveFsyXSk7XG4gICAgICAgIHkxID0gTWF0aC5tYXgoeTEsIGJveFszXSk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdGhpcy5ib3VuZHMgPSB4MCA8PSB4MSA/IFt4MCwgeTAsIHgxLCB5MV0gOiBudWxsO1xuICAgIGNvbnN0IGV4dGVudCA9IHRoaXMuYm91bmRzID8gTWF0aC5tYXgoTWF0aC5hYnMoeDApLCBNYXRoLmFicyh5MCksIE1hdGguYWJzKHgxKSwgTWF0aC5hYnMoeTEpKSA6IDA7XG4gICAgdGhpcy5sZXZlbHMgPSAxICsgTWF0aC5tYXgoMCwgTWF0aC5jZWlsKE1hdGgubG9nMihNYXRoLm1heChleHRlbnQsIHRpbGVTaXplKSAvIHRpbGVTaXplKSkpO1xuICB9XG5cbiAgLyoqIFBhcnNlIGEgR2VvSlNPTiBGZWF0dXJlQ29sbGVjdGlvbiBzdHJpbmcuIFRocm93cyBvbiBpbnZhbGlkIEpTT04gb3Igbm8gYGZlYXR1cmVzYC4gKi9cbiAgc3RhdGljIGZyb21HZW9Kc29uKHRleHQ6IHN0cmluZywgdGlsZVNpemUgPSBSRUdJT05fVElMRV9TSVpFKTogUmVnaW9uRmVhdHVyZVRhYmxlIHtcbiAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKHRleHQpO1xuICAgIGlmICghcGFyc2VkIHx8ICFBcnJheS5pc0FycmF5KHBhcnNlZC5mZWF0dXJlcykpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgR2VvSnNvbiBmaWxlOiBtdXN0IGNvbnRhaW4gdGhlICdmZWF0dXJlcycga2V5LlwiKTtcbiAgICB9XG4gICAgY29uc3QgdGFibGUgPSBuZXcgUmVnaW9uRmVhdHVyZVRhYmxlKHBhcnNlZC5mZWF0dXJlcywgdGlsZVNpemUpO1xuICAgIHRhYmxlLmRlc2NyaWJlKHBhcnNlZC5jbGFzc0hpZXJhcmNoeSwgcGFyc2VkLnN0eWxlKTtcbiAgICByZXR1cm4gdGFibGU7XG4gIH1cblxuICAvKiogQXR0YWNoIGEgY2xhc3MgaGllcmFyY2h5IGFuZCBhIHN0eWxlIGhpbnQgKGVhY2ggaWdub3JlZCB3aGVuIG5vdCB3ZWxsIGZvcm1lZCkuICovXG4gIGRlc2NyaWJlKGhpZXJhcmNoeT86IHVua25vd24sIHN0eWxlPzogdW5rbm93bik6IHZvaWQge1xuICAgIHRoaXMuaGllcmFyY2h5ID0gcmVhZEhpZXJhcmNoeShoaWVyYXJjaHkpID8/IHRoaXMuaGllcmFyY2h5O1xuICAgIHRoaXMuc3R5bGUgPSByZWFkU3R5bGUoc3R5bGUpID8/IHRoaXMuc3R5bGU7XG4gIH1cblxuICAvKipcbiAgICogVGhlIG91dGxpbmVzIG9mIGV2ZXJ5IGZlYXR1cmUgb2YgdGhlc2UgY2xhc3NlcywgcGxhbmUgYnkgcGxhbmUsIHNpbXBsaWZpZWQgZm9yIGBsZXZlbGAgKHdoYXQgYVxuICAgKiAzRCByZWNvbnN0cnVjdGlvbiBvZiB0aGUgY2xhc3NlcyBzdGFja3MpLCB3aXRob3V0IHRoZSBgZXhjbHVkZWBkIGlkczogY2xvc2VkIGZlYXR1cmVzJyByaW5ncyxcbiAgICogb3BlbiBmZWF0dXJlcycgcG9seWxpbmVzIGFzIGBsaW5lc2AsIGVhY2ggcmluZyB3aXRoIGl0cyBmZWF0dXJlIChgcmluZ0dyb3Vwc2ApLiBQbGFuZXMgd2l0aG91dFxuICAgKiBvbmUgYXJlIGxlZnQgb3V0LiBgY2xhc3Nlc2AgbnVsbCByZWFkcyBldmVyeSBsYWJlbGxlZCBmZWF0dXJlLCBlYWNoIG91dGxpbmUgd2l0aCBpdHMgY2xhc3NcbiAgICogKGByaW5nTGFiZWxzYCwgYGxpbmVMYWJlbHNgKS5cbiAgICovXG4gIGNsYXNzT3V0bGluZXMoXG4gICAgY2xhc3NlczogcmVhZG9ubHkgc3RyaW5nW10gfCBudWxsLFxuICAgIGxldmVsOiBudW1iZXIsXG4gICAgZXhjbHVkZTogcmVhZG9ubHkgc3RyaW5nW10gPSBbXSxcbiAgKTogQ2xhc3NPdXRsaW5lc1tdIHtcbiAgICBjb25zdCB3YW50ZWQgPSBjbGFzc2VzID8gbmV3IFNldChjbGFzc2VzKSA6IG51bGw7XG4gICAgY29uc3Qgc2tpcCA9IG5ldyBTZXQoZXhjbHVkZSk7XG4gICAgY29uc3QgYnlQbGFuZSA9IG5ldyBNYXA8bnVtYmVyLCBDbGFzc091dGxpbmVzPigpO1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgdGhpcy5pZHMubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGxhYmVsID0gdGhpcy5sYWJlbHNbaV07XG4gICAgICBpZiAoIWxhYmVsIHx8ICh3YW50ZWQgJiYgIXdhbnRlZC5oYXMobGFiZWwpKSB8fCBza2lwLmhhcyh0aGlzLmlkc1tpXSkpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgcmluZ3MgPSB0aGlzLnJpbmdzQXQoaSwgbGV2ZWwpO1xuICAgICAgaWYgKCFyaW5ncy5sZW5ndGgpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgeiA9IHRoaXMucGxhbmVzW2ldO1xuICAgICAgbGV0IHBsYW5lID0gYnlQbGFuZS5nZXQoeik7XG4gICAgICBpZiAoIXBsYW5lKSBieVBsYW5lLnNldCh6LCAocGxhbmUgPSB7IHosIHJpbmdzOiBbXSB9KSk7XG4gICAgICBpZiAodGhpcy5vcGVuW2ldKSB7XG4gICAgICAgIChwbGFuZS5saW5lcyA/Pz0gW10pLnB1c2goLi4ucmluZ3MpO1xuICAgICAgICBpZiAoIXdhbnRlZCkgKHBsYW5lLmxpbmVMYWJlbHMgPz89IFtdKS5wdXNoKC4uLnJpbmdzLm1hcCgoKSA9PiBsYWJlbCkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcGxhbmUucmluZ3MucHVzaCguLi5yaW5ncyk7XG4gICAgICAgIChwbGFuZS5yaW5nR3JvdXBzID8/PSBbXSkucHVzaCguLi5yaW5ncy5tYXAoKCkgPT4gaSkpO1xuICAgICAgICBpZiAoIXdhbnRlZCkgKHBsYW5lLnJpbmdMYWJlbHMgPz89IFtdKS5wdXNoKC4uLnJpbmdzLm1hcCgoKSA9PiBsYWJlbCkpO1xuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gQXJyYXkuZnJvbShieVBsYW5lLnZhbHVlcygpKS5zb3J0KChhLCBiKSA9PiBhLnogLSBiLnopO1xuICB9XG5cbiAgLyoqIEZlYXR1cmVzIHBlciBjbGFzcyBvbiBwbGFuZSBgemAgKG51bGw6IG9uIGV2ZXJ5IHBsYW5lKSwgd2l0aG91dCB0aGUgYGV4Y2x1ZGVgZCBpZHMuICovXG4gIGNsYXNzQ291bnRzKHo6IG51bWJlciB8IG51bGwsIGV4Y2x1ZGU6IHJlYWRvbmx5IHN0cmluZ1tdID0gW10pOiBSZWNvcmQ8c3RyaW5nLCBudW1iZXI+IHtcbiAgICBjb25zdCBza2lwID0gbmV3IFNldChleGNsdWRlKTtcbiAgICBjb25zdCBjb3VudHM6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4gPSB7fTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuaWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBjb25zdCBsYWJlbCA9IHRoaXMubGFiZWxzW2ldO1xuICAgICAgaWYgKCh6ICE9PSBudWxsICYmIHRoaXMucGxhbmVzW2ldICE9PSB6KSB8fCAhbGFiZWwgfHwgc2tpcC5oYXModGhpcy5pZHNbaV0pKSBjb250aW51ZTtcbiAgICAgIGNvdW50c1tsYWJlbF0gPSAoY291bnRzW2xhYmVsXSA/PyAwKSArIDE7XG4gICAgfVxuICAgIHJldHVybiBjb3VudHM7XG4gIH1cblxuICBpbmZvKCk6IFJlZ2lvblNvdXJjZUluZm8ge1xuICAgIGNvbnN0IGNsYXNzQ29sb3JzOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge307XG4gICAgdGhpcy5sYWJlbHMuZm9yRWFjaCgobGFiZWwsIGkpID0+IHtcbiAgICAgIGNvbnN0IGNvbG9yID0gdGhpcy5jb2xvcnNbaV07XG4gICAgICBpZiAobGFiZWwgJiYgY29sb3IgJiYgIShsYWJlbCBpbiBjbGFzc0NvbG9ycykpIGNsYXNzQ29sb3JzW2xhYmVsXSA9IGNvbG9yO1xuICAgIH0pO1xuICAgIHJldHVybiB7XG4gICAgICBmZWF0dXJlQ291bnQ6IHRoaXMuaWRzLmxlbmd0aCxcbiAgICAgIGJvdW5kczogdGhpcy5ib3VuZHMsXG4gICAgICB0aWxlU2l6ZTogdGhpcy50aWxlU2l6ZSxcbiAgICAgIGxldmVsczogdGhpcy5sZXZlbHMsXG4gICAgICBwbGFuZXM6IEFycmF5LmZyb20obmV3IFNldCh0aGlzLnBsYW5lcykpLnNvcnQoKGEsIGIpID0+IGEgLSBiKSxcbiAgICAgIGNsYXNzQ29sb3JzLFxuICAgICAgLi4uKHRoaXMuaGllcmFyY2h5ID8geyBoaWVyYXJjaHk6IHRoaXMuaGllcmFyY2h5IH0gOiB7fSksXG4gICAgICAuLi4odGhpcy5zdHlsZSA/IHsgc3R5bGU6IHRoaXMuc3R5bGUgfSA6IHt9KSxcbiAgICB9O1xuICB9XG5cbiAgLyoqIE9uZSB0aWxlIG9mIHBsYW5lIGB6YC4gKi9cbiAgdGlsZSh6OiBudW1iZXIsIGxldmVsOiBudW1iZXIsIGd4OiBudW1iZXIsIGd5OiBudW1iZXIpOiBSZWdpb25UaWxlIHtcbiAgICBjb25zdCB7IGNlbGxzLCB3aWRlIH0gPSB0aGlzLmJ1Y2tldHNGb3IoeiwgbGV2ZWwpO1xuICAgIGNvbnN0IGJ1Y2tldCA9IGNlbGxzLmdldChgJHtneH0vJHtneX1gKSA/PyBbXTtcbiAgICBjb25zdCBzaXplID0gbGV2ZWxUaWxlU2l6ZShsZXZlbCwgdGhpcy50aWxlU2l6ZSk7XG4gICAgY29uc3QgZmVhdHVyZXM6IFRpbGVGZWF0dXJlW10gPSBbXTtcbiAgICAvLyBUaGUgdGlsZSdzIGNlbGwgZmVhdHVyZXMgYW5kIHRoZSB3aWRlIG9uZXMgdGhhdCBtZWV0IGl0LCBtZXJnZWQgYmFjayBpbnRvIGZpbGUgb3JkZXIuXG4gICAgY29uc3Qgb3JkZXI6IG51bWJlcltdID0gW107XG4gICAgZm9yIChsZXQgYSA9IDAsIHcgPSAwOyBhIDwgYnVja2V0Lmxlbmd0aCB8fCB3IDwgd2lkZS5sZW5ndGg7KSB7XG4gICAgICBpZiAodyA+PSB3aWRlLmxlbmd0aCB8fCAoYSA8IGJ1Y2tldC5sZW5ndGggJiYgYnVja2V0W2FdIDwgd2lkZVt3XSkpIG9yZGVyLnB1c2goYnVja2V0W2ErK10pO1xuICAgICAgZWxzZSB7XG4gICAgICAgIGNvbnN0IGkgPSB3aWRlW3crK107XG4gICAgICAgIGlmIChjZWxsTWVldHModGhpcy5ib3hlc1tpXSwgc2l6ZSwgZ3gsIGd5KSkgb3JkZXIucHVzaChpKTtcbiAgICAgIH1cbiAgICB9XG4gICAgZm9yIChjb25zdCBpIG9mIG9yZGVyKSB7XG4gICAgICBjb25zdCByaW5ncyA9IHRoaXMucmluZ3NBdChpLCBsZXZlbCk7XG4gICAgICBpZiAoIXJpbmdzLmxlbmd0aCkgY29udGludWU7XG4gICAgICBjb25zdCBsYWJlbHMgPSB0aGlzLmxhYmVsc0F0KGksIGxldmVsKTtcbiAgICAgIGZlYXR1cmVzLnB1c2goe1xuICAgICAgICBpZDogdGhpcy5pZHNbaV0sXG4gICAgICAgIGxhYmVsOiB0aGlzLmxhYmVsc1tpXSxcbiAgICAgICAgY29sb3I6IHRoaXMuY29sb3JzW2ldLFxuICAgICAgICBiYm94OiB0aGlzLmJveGVzW2ldLFxuICAgICAgICByaW5ncyxcbiAgICAgICAgb3BlbjogdGhpcy5vcGVuW2ldLFxuICAgICAgICAuLi4obGFiZWxzID8geyBsYWJlbHMgfSA6IHt9KSxcbiAgICAgIH0pO1xuICAgIH1cbiAgICByZXR1cm4geyB6LCBsZXZlbCwgZ3gsIGd5LCBmZWF0dXJlcyB9O1xuICB9XG5cbiAgLyoqIFRoZSByYXcgR2VvSlNPTiBmZWF0dXJlcyB3aXRoIHRoZXNlIGlkcywgaW4gdGhlIG9yZGVyIGFza2VkICh1bmtub3duIGlkcyBza2lwcGVkKS4gKi9cbiAgZmVhdHVyZXMoaWRzOiByZWFkb25seSBzdHJpbmdbXSk6IEFycmF5PHsgaWQ6IHN0cmluZzsgZmVhdHVyZTogR2VvSnNvbkZlYXR1cmVMaWtlIH0+IHtcbiAgICBjb25zdCBvdXQ6IEFycmF5PHsgaWQ6IHN0cmluZzsgZmVhdHVyZTogR2VvSnNvbkZlYXR1cmVMaWtlIH0+ID0gW107XG4gICAgZm9yIChjb25zdCBpZCBvZiBpZHMpIHtcbiAgICAgIGNvbnN0IGkgPSB0aGlzLmJ5SWQuZ2V0KGlkKTtcbiAgICAgIGlmIChpICE9PSB1bmRlZmluZWQpIG91dC5wdXNoKHsgaWQsIGZlYXR1cmU6IHRoaXMucmF3W2ldIH0pO1xuICAgIH1cbiAgICByZXR1cm4gb3V0O1xuICB9XG5cbiAgLyoqIEZlYXR1cmUgYGlgJ3MgYXJlYSBpbiBweMKyICgwIGZvciBhIHBvbHlsaW5lKS4gKi9cbiAgcHJpdmF0ZSBhcmVhT2YoaTogbnVtYmVyKTogbnVtYmVyIHtcbiAgICBsZXQgYXJlYSA9IHRoaXMuYXJlYXMuZ2V0KGkpO1xuICAgIGlmIChhcmVhID09PSB1bmRlZmluZWQpIHtcbiAgICAgIGFyZWEgPSB0aGlzLm9wZW5baV0gPyAwIDogcmluZ3NBcmVhKHRoaXMucmluZ3NbaV0pO1xuICAgICAgdGhpcy5hcmVhcy5zZXQoaSwgYXJlYSk7XG4gICAgfVxuICAgIHJldHVybiBhcmVhO1xuICB9XG5cbiAgLyoqIEEgcGFnZSBvZiBwbGFuZSBgemAncyBmZWF0dXJlcywgaW4gZmlsZSBvcmRlci4gKi9cbiAgaW5kZXgoejogbnVtYmVyLCBxdWVyeTogUmVnaW9uSW5kZXhRdWVyeSk6IFJlZ2lvbkluZGV4UGFnZSB7XG4gICAgY29uc3QgZXhjbHVkZSA9IG5ldyBTZXQocXVlcnkuZXhjbHVkZSA/PyBbXSk7XG4gICAgY29uc3QgY2xhc3NlcyA9IHF1ZXJ5LmNsYXNzZXMgPyBuZXcgU2V0KHF1ZXJ5LmNsYXNzZXMpIDogbnVsbDtcbiAgICBjb25zdCBuZWVkbGUgPSBxdWVyeS5sYWJlbD8udHJpbSgpLnRvTG93ZXJDYXNlKCkgfHwgbnVsbDtcbiAgICBjb25zdCByb3dzOiBSZWdpb25JbmRleFJvd1tdID0gW107XG4gICAgbGV0IHRvdGFsID0gMDtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuaWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodGhpcy5wbGFuZXNbaV0gIT09IHogfHwgZXhjbHVkZS5oYXModGhpcy5pZHNbaV0pKSBjb250aW51ZTtcbiAgICAgIGlmIChuZWVkbGUgJiYgISh0aGlzLmxhYmVsc1tpXSA/PyAnJykudG9Mb3dlckNhc2UoKS5pbmNsdWRlcyhuZWVkbGUpKSBjb250aW51ZTtcbiAgICAgIGlmIChjbGFzc2VzICYmICFjbGFzc2VzLmhhcyh0aGlzLmxhYmVsc1tpXSA/PyAnJykpIGNvbnRpbnVlO1xuICAgICAgaWYgKHRvdGFsID49IHF1ZXJ5Lm9mZnNldCAmJiByb3dzLmxlbmd0aCA8IHF1ZXJ5LmxpbWl0KSB7XG4gICAgICAgIHJvd3MucHVzaCh7XG4gICAgICAgICAgaWQ6IHRoaXMuaWRzW2ldLFxuICAgICAgICAgIGxhYmVsOiB0aGlzLmxhYmVsc1tpXSxcbiAgICAgICAgICBjb2xvcjogdGhpcy5jb2xvcnNbaV0sXG4gICAgICAgICAgYmJveDogdGhpcy5ib3hlc1tpXSxcbiAgICAgICAgICBhcmVhOiB0aGlzLmFyZWFPZihpKSxcbiAgICAgICAgfSk7XG4gICAgICB9XG4gICAgICB0b3RhbCsrO1xuICAgIH1cbiAgICByZXR1cm4geyB0b3RhbCwgcm93cyB9O1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBzb3VyY2UgYXMgYSBHZW9KU09OIEZlYXR1cmVDb2xsZWN0aW9uIHN0cmluZywgdGhyb3VnaCB0aGUgd29ya2luZyBzZXQ6IGZlYXR1cmVzIHdob3NlXG4gICAqIGlkIGlzIGluIGBleGNsdWRlYCAodGFrZW4gZm9yIGVkaXRpbmcsIG9yIGRlbGV0ZWQpIGFyZSBsZWZ0IG91dCwgYGV4dHJhYCAodGhlIHdvcmtpbmcgc2V0J3NcbiAgICogZmVhdHVyZXMpIGFwcGVuZGVkLiBFdmVyeSBmZWF0dXJlIGtlZXBzIGFuIGBpZGA7IHRoZSBzZXQga2VlcHMgaXRzIGhpZXJhcmNoeSBhbmQgc3R5bGUuXG4gICAqL1xuICBleHBvcnRHZW9Kc29uKGV4Y2x1ZGU6IHJlYWRvbmx5IHN0cmluZ1tdLCBleHRyYTogcmVhZG9ubHkgb2JqZWN0W10pOiBzdHJpbmcge1xuICAgIGNvbnN0IHNraXAgPSBuZXcgU2V0KGV4Y2x1ZGUpO1xuICAgIGNvbnN0IHBhcnRzOiBzdHJpbmdbXSA9IFtdO1xuICAgIHRoaXMucmF3LmZvckVhY2goKGZlYXR1cmUsIGkpID0+IHtcbiAgICAgIGNvbnN0IGlkID0gdGhpcy5pZHNbaV07XG4gICAgICBpZiAoc2tpcC5oYXMoaWQpKSByZXR1cm47XG4gICAgICBwYXJ0cy5wdXNoKEpTT04uc3RyaW5naWZ5KGZlYXR1cmUuaWQgPT09IHVuZGVmaW5lZCA/IHsgdHlwZTogJ0ZlYXR1cmUnLCBpZCwgLi4uZmVhdHVyZSB9IDogZmVhdHVyZSkpO1xuICAgIH0pO1xuICAgIGZvciAoY29uc3QgZiBvZiBleHRyYSkgcGFydHMucHVzaChKU09OLnN0cmluZ2lmeShmKSk7XG4gICAgcmV0dXJuIGZlYXR1cmVDb2xsZWN0aW9uSnNvbihwYXJ0cywgdGhpcy5oaWVyYXJjaHksIHRoaXMuc3R5bGUpO1xuICB9XG5cbiAgLyoqXG4gICAqIEZlYXR1cmUgYGlgJ3MgbGFiZWwgcG9pbnRzIChvbmUgcGVyIHBhcnQgd2l0aCByb29tIGZvciBhIGxhYmVsIGF0IGBsZXZlbGA6IGEgcGFydCB1bmRlciB0aGVcbiAgICogbGV2ZWwncyBtaW5pbXVtIGV4dGVudCBpcyBub3QgZHJhd24gdGhlcmUpLCBmcm9tIHRoZSBleGFjdCBnZW9tZXRyeSwgY29tcHV0ZWQgb25jZS5cbiAgICovXG4gIHByaXZhdGUgbGFiZWxzQXQoaTogbnVtYmVyLCBsZXZlbDogbnVtYmVyKTogRmxvYXQzMkFycmF5IHwgbnVsbCB7XG4gICAgaWYgKHRoaXMub3BlbltpXSB8fCAhdGhpcy5sYWJlbHNbaV0pIHJldHVybiBudWxsO1xuICAgIGxldCBwb2ludHMgPSB0aGlzLmxhYmVsUG9pbnRzLmdldChpKTtcbiAgICBpZiAoIXBvaW50cykge1xuICAgICAgY29uc3Qgb3V0OiBudW1iZXJbXSA9IFtdO1xuICAgICAgZm9yIChjb25zdCBwYXJ0IG9mIHRoaXMucGFydHNbaV0pIHtcbiAgICAgICAgY29uc3QgcG9sZSA9IHBvbHlsYWJlbChwYXJ0Lm1hcCgocikgPT4gdGhpcy5yaW5nc1tpXVtyXSkpO1xuICAgICAgICBpZiAocG9sZSAmJiBwb2xlLmRpc3RhbmNlID4gMCkgb3V0LnB1c2gocG9sZS54LCBwb2xlLnksIHBvbGUuZGlzdGFuY2UpO1xuICAgICAgfVxuICAgICAgcG9pbnRzID0gRmxvYXQzMkFycmF5LmZyb20ob3V0KTtcbiAgICAgIHRoaXMubGFiZWxQb2ludHMuc2V0KGksIHBvaW50cyk7XG4gICAgfVxuICAgIGNvbnN0IG1pbiA9IGxldmVsTWluRXh0ZW50KGxldmVsKSAvIDI7XG4gICAgaWYgKCFtaW4pIHJldHVybiBwb2ludHMubGVuZ3RoID8gcG9pbnRzIDogbnVsbDtcbiAgICBjb25zdCBrZXB0OiBudW1iZXJbXSA9IFtdO1xuICAgIGZvciAobGV0IGsgPSAwOyBrICsgMiA8IHBvaW50cy5sZW5ndGg7IGsgKz0gMylcbiAgICAgIGlmIChwb2ludHNbayArIDJdID49IG1pbikga2VwdC5wdXNoKHBvaW50c1trXSwgcG9pbnRzW2sgKyAxXSwgcG9pbnRzW2sgKyAyXSk7XG4gICAgcmV0dXJuIGtlcHQubGVuZ3RoID8gRmxvYXQzMkFycmF5LmZyb20oa2VwdCkgOiBudWxsO1xuICB9XG5cbiAgLyoqIEZlYXR1cmUgYGlgJ3MgcmluZ3MgYXQgYGxldmVsYCwgc2ltcGxpZmllZCBvbmNlIGFuZCBjYWNoZWQuICovXG4gIHByaXZhdGUgcmluZ3NBdChpOiBudW1iZXIsIGxldmVsOiBudW1iZXIpOiBGbG9hdDMyQXJyYXlbXSB7XG4gICAgY29uc3Qga2V5ID0gYCR7bGV2ZWx9LyR7aX1gO1xuICAgIGxldCByaW5ncyA9IHRoaXMuc2ltcGxpZmllZC5nZXQoa2V5KTtcbiAgICBpZiAoIXJpbmdzKSB7XG4gICAgICByaW5ncyA9IHNpbXBsaWZ5UmluZ3ModGhpcy5yaW5nc1tpXSwgdGhpcy5vcGVuW2ldLCBsZXZlbCk7XG4gICAgICBpZiAodGhpcy5zaW1wbGlmaWVkLnNpemUgPj0gU0lNUExJRklFRF9DQUNIRV9MSU1JVCkge1xuICAgICAgICBjb25zdCBvbGRlc3QgPSB0aGlzLnNpbXBsaWZpZWQua2V5cygpLm5leHQoKS52YWx1ZSBhcyBzdHJpbmc7XG4gICAgICAgIHRoaXMuc2ltcGxpZmllZC5kZWxldGUob2xkZXN0KTtcbiAgICAgIH1cbiAgICAgIHRoaXMuc2ltcGxpZmllZC5zZXQoa2V5LCByaW5ncyk7XG4gICAgfVxuICAgIHJldHVybiByaW5ncztcbiAgfVxuXG4gIC8qKiBFbnRyaWVzIGluIHBsYW5lIGB6YCdzIGxldmVsLWBsZXZlbGAgaW5kZXg6IGNlbGwgbGlzdGluZ3MgcGx1cyB3aWRlIGZlYXR1cmVzICh0ZXN0cykuICovXG4gIGluZGV4RW50cmllcyh6OiBudW1iZXIsIGxldmVsOiBudW1iZXIpOiBudW1iZXIge1xuICAgIGNvbnN0IHsgY2VsbHMsIHdpZGUgfSA9IHRoaXMuYnVja2V0c0Zvcih6LCBsZXZlbCk7XG4gICAgbGV0IG4gPSB3aWRlLmxlbmd0aDtcbiAgICBmb3IgKGNvbnN0IGxpc3Qgb2YgY2VsbHMudmFsdWVzKCkpIG4gKz0gbGlzdC5sZW5ndGg7XG4gICAgcmV0dXJuIG47XG4gIH1cblxuICAvKipcbiAgICogUGxhbmUgYHpgJ3MgbGV2ZWwtYGxldmVsYCBpbmRleCwgYnVpbHQgb24gZmlyc3QgdXNlOiBmZWF0dXJlcyBieSB0aWxlIGNlbGwgKGBneC9neWAg4oaSIGZlYXR1cmVcbiAgICogaW5kaWNlcyksIGFuZCB0aGUgd2lkZSBvbmVzIChtb3JlIHRoYW4ge0BsaW5rIE1BWF9DRUxMU19QRVJfRkVBVFVSRX0gY2VsbHMsIG9yIHBhc3QgdGhlXG4gICAqIG51bWJlciByYW5nZSksIHRlc3RlZCBhZ2FpbnN0IGEgdGlsZSB3aGVuIGl0IGlzIGFza2VkIGZvci5cbiAgICovXG4gIHByaXZhdGUgYnVja2V0c0Zvcih6OiBudW1iZXIsIGxldmVsOiBudW1iZXIpOiBMZXZlbEluZGV4IHtcbiAgICBjb25zdCBrZXkgPSBgJHt6fS8ke2xldmVsfWA7XG4gICAgbGV0IGluZGV4ID0gdGhpcy5idWNrZXRzLmdldChrZXkpO1xuICAgIGlmIChpbmRleCkgcmV0dXJuIGluZGV4O1xuICAgIGNvbnN0IGNlbGxzID0gbmV3IE1hcDxzdHJpbmcsIG51bWJlcltdPigpO1xuICAgIGNvbnN0IHdpZGU6IG51bWJlcltdID0gW107XG4gICAgY29uc3Qgc2l6ZSA9IGxldmVsVGlsZVNpemUobGV2ZWwsIHRoaXMudGlsZVNpemUpO1xuICAgIGNvbnN0IG1pbkV4dGVudCA9IGxldmVsTWluRXh0ZW50KGxldmVsKTtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRoaXMuaWRzLmxlbmd0aDsgaSsrKSB7XG4gICAgICBpZiAodGhpcy5wbGFuZXNbaV0gIT09IHogfHwgIXRoaXMucmluZ3NbaV0ubGVuZ3RoKSBjb250aW51ZTtcbiAgICAgIGNvbnN0IGIgPSB0aGlzLmJveGVzW2ldO1xuICAgICAgaWYgKE1hdGgubWF4KGJbMl0gLSBiWzBdLCBiWzNdIC0gYlsxXSkgPCBtaW5FeHRlbnQpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgZ3gwID0gTWF0aC5mbG9vcihiWzBdIC8gc2l6ZSksXG4gICAgICAgIGd4MSA9IE1hdGguZmxvb3IoYlsyXSAvIHNpemUpLFxuICAgICAgICBneTAgPSBNYXRoLmZsb29yKGJbMV0gLyBzaXplKSxcbiAgICAgICAgZ3kxID0gTWF0aC5mbG9vcihiWzNdIC8gc2l6ZSk7XG4gICAgICAvLyBBIGJveCB3aXRoIGEgTmFOIGNvb3JkaW5hdGUgbWVldHMgbm8gdGlsZS5cbiAgICAgIGlmIChbZ3gwLCBneDEsIGd5MCwgZ3kxXS5zb21lKE51bWJlci5pc05hTikpIGNvbnRpbnVlO1xuICAgICAgY29uc3QgY291bnQgPSAoZ3gxIC0gZ3gwICsgMSkgKiAoZ3kxIC0gZ3kwICsgMSk7XG4gICAgICBpZiAoIShjb3VudCA8PSBNQVhfQ0VMTFNfUEVSX0ZFQVRVUkUpIHx8ICFbZ3gwLCBneDEsIGd5MCwgZ3kxXS5ldmVyeShOdW1iZXIuaXNTYWZlSW50ZWdlcikpIHtcbiAgICAgICAgd2lkZS5wdXNoKGkpO1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGZvciAobGV0IGd5ID0gZ3kwOyBneSA8PSBneTE7IGd5KyspIHtcbiAgICAgICAgZm9yIChsZXQgZ3ggPSBneDA7IGd4IDw9IGd4MTsgZ3grKykge1xuICAgICAgICAgIGNvbnN0IGlkID0gYCR7Z3h9LyR7Z3l9YDtcbiAgICAgICAgICBjb25zdCBsaXN0ID0gY2VsbHMuZ2V0KGlkKTtcbiAgICAgICAgICBpZiAobGlzdCkgbGlzdC5wdXNoKGkpO1xuICAgICAgICAgIGVsc2UgY2VsbHMuc2V0KGlkLCBbaV0pO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuICAgIGluZGV4ID0geyBjZWxscywgd2lkZSB9O1xuICAgIHRoaXMuYnVja2V0cy5zZXQoa2V5LCBpbmRleCk7XG4gICAgcmV0dXJuIGluZGV4O1xuICB9XG59XG5cbi8qKlxuICogQSBmZWF0dXJlIHNwYW5uaW5nIG1vcmUgdGlsZXMgdGhhbiB0aGlzIGlzIG5vdCBsaXN0ZWQgaW4gZWFjaCBvZiB0aGVtIGJ1dCBrZXB0IGFzaWRlIGFuZCB0ZXN0ZWRcbiAqIGFnYWluc3QgYSB0aWxlIHdoZW4gb25lIGlzIGFza2VkIGZvcjogb25lIGh1Z2UgYm94IChhbiBvdXRsaW5lIGFyb3VuZCBhIHdob2xlIHNsaWRlLCBvciBhIGNvcnJ1cHRcbiAqIGNvb3JkaW5hdGUpIG11c3Qgbm90IG1ha2UgYSBwbGFuZSdzIGluZGV4IG1pbGxpb25zIG9mIGVudHJpZXMuXG4gKi9cbmV4cG9ydCBjb25zdCBNQVhfQ0VMTFNfUEVSX0ZFQVRVUkUgPSA2NDtcblxuLyoqIEEgcGxhbmUncyBsZXZlbDogZmVhdHVyZXMgYnkgdGlsZSBjZWxsLCBhbmQgdGhlIHdpZGUgb25lcyAoYXNjZW5kaW5nKSwgdGVzdGVkIHBlciB0aWxlLiAqL1xuaW50ZXJmYWNlIExldmVsSW5kZXgge1xuICBjZWxsczogTWFwPHN0cmluZywgbnVtYmVyW10+O1xuICB3aWRlOiBudW1iZXJbXTtcbn1cblxuLyoqIFdoZXRoZXIgYm94IGBiYCBtZWV0cyBjZWxsIChneCwgZ3kpIG9mIHRpbGVzIGBzaXplYCBwaXhlbHMgd2lkZSwgYXMgYSBjZWxsIGxpc3RzIGl0LiAqL1xuZnVuY3Rpb24gY2VsbE1lZXRzKGI6IFJlYWRvbmx5PEJib3g+LCBzaXplOiBudW1iZXIsIGd4OiBudW1iZXIsIGd5OiBudW1iZXIpOiBib29sZWFuIHtcbiAgcmV0dXJuIChcbiAgICBNYXRoLmZsb29yKGJbMF0gLyBzaXplKSA8PSBneCAmJlxuICAgIGd4IDw9IE1hdGguZmxvb3IoYlsyXSAvIHNpemUpICYmXG4gICAgTWF0aC5mbG9vcihiWzFdIC8gc2l6ZSkgPD0gZ3kgJiZcbiAgICBneSA8PSBNYXRoLmZsb29yKGJbM10gLyBzaXplKVxuICApO1xufVxuXG4vKiogQSBmZWF0dXJlJ3Mgb3duIGlkIChgaWRgLCBlbHNlIGBwcm9wZXJ0aWVzLmlkYCkgYXMgYSBzdHJpbmcuICovXG5leHBvcnQgZnVuY3Rpb24gZmVhdHVyZUlkT2YoZmVhdHVyZTogR2VvSnNvbkZlYXR1cmVMaWtlKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgY29uc3QgaWQgPSBmZWF0dXJlPy5pZCA/PyBmZWF0dXJlPy5wcm9wZXJ0aWVzPy5pZDtcbiAgcmV0dXJuIHR5cGVvZiBpZCA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGlkID09PSAnbnVtYmVyJyA/IFN0cmluZyhpZCkgOiB1bmRlZmluZWQ7XG59XG5cbi8qKiBDbGFzcyBuYW1lIGFuZCBjb2xvdXIgZnJvbSBRdVBhdGgncyBgY2xhc3NpZmljYXRpb25gIChge25hbWUsIGNvbG9yfWAsIG9yIGEgYmFyZSBuYW1lKS4gKi9cbmZ1bmN0aW9uIGNsYXNzaWZpY2F0aW9uT2YoZmVhdHVyZTogR2VvSnNvbkZlYXR1cmVMaWtlKTogeyBsYWJlbDogc3RyaW5nIHwgbnVsbDsgY29sb3I6IHN0cmluZyB8IG51bGwgfSB7XG4gIGNvbnN0IGMgPSBmZWF0dXJlPy5wcm9wZXJ0aWVzPy5jbGFzc2lmaWNhdGlvbiBhcyB7IG5hbWU/OiBzdHJpbmc7IGNvbG9yPzogbnVtYmVyW10gfSB8IHN0cmluZyB8IHVuZGVmaW5lZDtcbiAgaWYgKCFjKSByZXR1cm4geyBsYWJlbDogJ0NlbGwnLCBjb2xvcjogbnVsbCB9O1xuICBpZiAodHlwZW9mIGMgPT09ICdzdHJpbmcnKSByZXR1cm4geyBsYWJlbDogYywgY29sb3I6IG51bGwgfTtcbiAgY29uc3QgY29sb3IgPVxuICAgIEFycmF5LmlzQXJyYXkoYy5jb2xvcikgJiYgYy5jb2xvci5sZW5ndGggPj0gMyA/IHJnYlRvSGV4KFtjLmNvbG9yWzBdLCBjLmNvbG9yWzFdLCBjLmNvbG9yWzJdXSkgOiBudWxsO1xuICByZXR1cm4geyBsYWJlbDogYy5uYW1lID8/IG51bGwsIGNvbG9yIH07XG59XG5cbi8qKlxuICogQSBmZWF0dXJlJ3MgcmluZ3MsIGludGVybGVhdmVkLCB3aXRob3V0IHRoZSBjbG9zaW5nIHZlcnRleDsgd2hldGhlciBpdCBpcyBhIHBvbHlsaW5lOyBhbmQgaXRzXG4gKiBwYXJ0cyBhcyByaW5nIGluZGljZXMgKGVhY2ggcGFydCdzIGV4dGVyaW9yIGZpcnN0LCB0aGVuIGl0cyBob2xlcykuXG4gKi9cbmZ1bmN0aW9uIHJpbmdzT2YoZmVhdHVyZTogR2VvSnNvbkZlYXR1cmVMaWtlKTogeyByaW5nczogRmxvYXQ2NEFycmF5W107IG9wZW46IGJvb2xlYW47IHBhcnRzOiBudW1iZXJbXVtdIH0ge1xuICBjb25zdCBnID0gZmVhdHVyZT8uZ2VvbWV0cnk7XG4gIGNvbnN0IGNvb3JkcyA9IGc/LmNvb3JkaW5hdGVzIGFzIHVua25vd247XG4gIGlmICghZyB8fCAhQXJyYXkuaXNBcnJheShjb29yZHMpKSByZXR1cm4geyByaW5nczogW10sIG9wZW46IGZhbHNlLCBwYXJ0czogW10gfTtcbiAgY29uc3QgcG9seWdvbnMgPSAobGlzdDogbnVtYmVyW11bXVtdW10pID0+IHtcbiAgICBjb25zdCByaW5nczogRmxvYXQ2NEFycmF5W10gPSBbXTtcbiAgICBjb25zdCBwYXJ0czogbnVtYmVyW11bXSA9IFtdO1xuICAgIGZvciAoY29uc3QgcG9seWdvbiBvZiBsaXN0KSB7XG4gICAgICBjb25zdCBwYXJ0OiBudW1iZXJbXSA9IFtdO1xuICAgICAgZm9yIChjb25zdCByIG9mIHBvbHlnb24pIHtcbiAgICAgICAgcGFydC5wdXNoKHJpbmdzLmxlbmd0aCk7XG4gICAgICAgIHJpbmdzLnB1c2goZmxhdFJpbmcociwgdHJ1ZSkpO1xuICAgICAgfVxuICAgICAgaWYgKHBhcnQubGVuZ3RoKSBwYXJ0cy5wdXNoKHBhcnQpO1xuICAgIH1cbiAgICByZXR1cm4geyByaW5ncywgb3BlbjogZmFsc2UsIHBhcnRzIH07XG4gIH07XG4gIHN3aXRjaCAoZy50eXBlKSB7XG4gICAgY2FzZSAnUG9seWdvbic6XG4gICAgICByZXR1cm4gcG9seWdvbnMoW2Nvb3JkcyBhcyBudW1iZXJbXVtdW11dKTtcbiAgICBjYXNlICdNdWx0aVBvbHlnb24nOlxuICAgICAgcmV0dXJuIHBvbHlnb25zKGNvb3JkcyBhcyBudW1iZXJbXVtdW11bXSk7XG4gICAgY2FzZSAnTGluZVN0cmluZyc6XG4gICAgICByZXR1cm4geyByaW5nczogW2ZsYXRSaW5nKGNvb3JkcyBhcyBudW1iZXJbXVtdLCBmYWxzZSldLCBvcGVuOiB0cnVlLCBwYXJ0czogW10gfTtcbiAgICBjYXNlICdNdWx0aUxpbmVTdHJpbmcnOlxuICAgICAgcmV0dXJuIHsgcmluZ3M6IChjb29yZHMgYXMgbnVtYmVyW11bXVtdKS5tYXAoKHIpID0+IGZsYXRSaW5nKHIsIGZhbHNlKSksIG9wZW46IHRydWUsIHBhcnRzOiBbXSB9O1xuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4geyByaW5nczogW10sIG9wZW46IGZhbHNlLCBwYXJ0czogW10gfTtcbiAgfVxufVxuXG4vKipcbiAqIEEgRmVhdHVyZUNvbGxlY3Rpb24gc3RyaW5nIG9mIGBmZWF0dXJlc2AgKGVhY2ggYSBmZWF0dXJlJ3MgSlNPTiksIHdpdGggdGhlIHNldCdzIGNsYXNzIGhpZXJhcmNoeVxuICogYW5kIHN0eWxlIGFzIGl0cyBgY2xhc3NIaWVyYXJjaHlgIGFuZCBgc3R5bGVgIG1lbWJlcnMgd2hlbiBpdCBoYXMgdGhlbTogd2hhdFxuICoge0BsaW5rIFJlZ2lvbkZlYXR1cmVUYWJsZS5mcm9tR2VvSnNvbn0gcmVhZHMgYmFjay5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGZlYXR1cmVDb2xsZWN0aW9uSnNvbihcbiAgZmVhdHVyZXM6IHJlYWRvbmx5IHN0cmluZ1tdLFxuICBoaWVyYXJjaHk/OiByZWFkb25seSBSZWdpb25DbGFzc05vZGVbXSxcbiAgc3R5bGU/OiBSZWdpb25Tb3VyY2VTdHlsZSxcbik6IHN0cmluZyB7XG4gIGNvbnN0IGhlYWQgPSBbJ1widHlwZVwiOlwiRmVhdHVyZUNvbGxlY3Rpb25cIiddO1xuICBpZiAoaGllcmFyY2h5Py5sZW5ndGgpIGhlYWQucHVzaChgXCJjbGFzc0hpZXJhcmNoeVwiOiR7SlNPTi5zdHJpbmdpZnkoaGllcmFyY2h5KX1gKTtcbiAgaWYgKHN0eWxlKSBoZWFkLnB1c2goYFwic3R5bGVcIjoke0pTT04uc3RyaW5naWZ5KHN0eWxlKX1gKTtcbiAgcmV0dXJuIGB7JHtoZWFkLmpvaW4oJywnKX0sXCJmZWF0dXJlc1wiOlske2ZlYXR1cmVzLmpvaW4oJywnKX1dfWA7XG59XG5cbi8qKiBBIHdlbGwtZm9ybWVkIGNsYXNzIGhpZXJhcmNoeSBmcm9tIGEgZmlsZSAoY29sb3VycyBhcyBgI3JyZ2diYmAgb3IgYFtyLCBnLCBiXWApLCBlbHNlIHVuZGVmaW5lZC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkSGllcmFyY2h5KHJhdzogdW5rbm93bik6IFJlZ2lvbkNsYXNzTm9kZVtdIHwgdW5kZWZpbmVkIHtcbiAgaWYgKCFBcnJheS5pc0FycmF5KHJhdykpIHJldHVybiB1bmRlZmluZWQ7XG4gIGNvbnN0IG91dDogUmVnaW9uQ2xhc3NOb2RlW10gPSBbXTtcbiAgZm9yIChjb25zdCBuIG9mIHJhdyBhcyBBcnJheTxSZWNvcmQ8c3RyaW5nLCB1bmtub3duPj4pIHtcbiAgICBpZiAoIW4gfHwgdHlwZW9mIG4ubmFtZSAhPT0gJ3N0cmluZycpIGNvbnRpbnVlO1xuICAgIGNvbnN0IGNvbG9yID0gQXJyYXkuaXNBcnJheShuLmNvbG9yKSA/IHJnYlRvSGV4KFsrbi5jb2xvclswXSwgK24uY29sb3JbMV0sICtuLmNvbG9yWzJdXSkgOiBuLmNvbG9yO1xuICAgIG91dC5wdXNoKHtcbiAgICAgIG5hbWU6IG4ubmFtZSxcbiAgICAgIC4uLih0eXBlb2Ygbi50aXRsZSA9PT0gJ3N0cmluZycgPyB7IHRpdGxlOiBuLnRpdGxlIH0gOiB7fSksXG4gICAgICAuLi4odHlwZW9mIG4ucGFyZW50ID09PSAnc3RyaW5nJyA/IHsgcGFyZW50OiBuLnBhcmVudCB9IDoge30pLFxuICAgICAgLi4uKHR5cGVvZiBjb2xvciA9PT0gJ3N0cmluZycgPyB7IGNvbG9yIH0gOiB7fSksXG4gICAgICAuLi4odHlwZW9mIG4ub3JkZXIgPT09ICdudW1iZXInID8geyBvcmRlcjogbi5vcmRlciB9IDoge30pLFxuICAgIH0pO1xuICB9XG4gIHJldHVybiBvdXQubGVuZ3RoID8gb3V0IDogdW5kZWZpbmVkO1xufVxuXG4vKiogQSB3ZWxsLWZvcm1lZCBzdHlsZSBoaW50IGZyb20gYSBmaWxlLCBlbHNlIHVuZGVmaW5lZC4gKi9cbmV4cG9ydCBmdW5jdGlvbiByZWFkU3R5bGUocmF3OiB1bmtub3duKTogUmVnaW9uU291cmNlU3R5bGUgfCB1bmRlZmluZWQge1xuICBpZiAoIXJhdyB8fCB0eXBlb2YgcmF3ICE9PSAnb2JqZWN0JykgcmV0dXJuIHVuZGVmaW5lZDtcbiAgY29uc3QgciA9IHJhdyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPjtcbiAgY29uc3Qgc3R5bGU6IFJlZ2lvblNvdXJjZVN0eWxlID0ge307XG4gIGlmICh0eXBlb2Ygci5maWxsT3BhY2l0eSA9PT0gJ251bWJlcicpIHN0eWxlLmZpbGxPcGFjaXR5ID0gTWF0aC5tYXgoMCwgTWF0aC5taW4oMSwgci5maWxsT3BhY2l0eSkpO1xuICBpZiAodHlwZW9mIHIuc3Ryb2tlID09PSAnc3RyaW5nJykgc3R5bGUuc3Ryb2tlID0gci5zdHJva2U7XG4gIGlmICh0eXBlb2Ygci5zdHJva2VXaWR0aCA9PT0gJ251bWJlcicgJiYgci5zdHJva2VXaWR0aCA+IDApIHN0eWxlLnN0cm9rZVdpZHRoID0gci5zdHJva2VXaWR0aDtcbiAgaWYgKHR5cGVvZiByLmxhYmVscyA9PT0gJ2Jvb2xlYW4nKSBzdHlsZS5sYWJlbHMgPSByLmxhYmVscztcbiAgaWYgKHR5cGVvZiByLmhpZ2hsaWdodCA9PT0gJ3N0cmluZycpIHN0eWxlLmhpZ2hsaWdodCA9IHIuaGlnaGxpZ2h0O1xuICByZXR1cm4gT2JqZWN0LmtleXMoc3R5bGUpLmxlbmd0aCA/IHN0eWxlIDogdW5kZWZpbmVkO1xufVxuXG5mdW5jdGlvbiBmbGF0UmluZyhwb2ludHM6IG51bWJlcltdW10sIGNsb3NlZDogYm9vbGVhbik6IEZsb2F0NjRBcnJheSB7XG4gIGxldCBuID0gcG9pbnRzPy5sZW5ndGggPz8gMDtcbiAgaWYgKGNsb3NlZCAmJiBuID4gMSkge1xuICAgIGNvbnN0IGEgPSBwb2ludHNbMF0sXG4gICAgICBiID0gcG9pbnRzW24gLSAxXTtcbiAgICBpZiAoYVswXSA9PT0gYlswXSAmJiBhWzFdID09PSBiWzFdKSBuLS07XG4gIH1cbiAgY29uc3Qgb3V0ID0gbmV3IEZsb2F0NjRBcnJheShuICogMik7XG4gIGZvciAobGV0IGkgPSAwOyBpIDwgbjsgaSsrKSB7XG4gICAgb3V0WzIgKiBpXSA9ICtwb2ludHNbaV1bMF07XG4gICAgb3V0WzIgKiBpICsgMV0gPSArcG9pbnRzW2ldWzFdO1xuICB9XG4gIHJldHVybiBvdXQ7XG59XG5cbmZ1bmN0aW9uIHJpbmdzQm94KHJpbmdzOiByZWFkb25seSBGbG9hdDY0QXJyYXlbXSk6IEJib3gge1xuICBsZXQgeDAgPSBJbmZpbml0eSxcbiAgICB5MCA9IEluZmluaXR5LFxuICAgIHgxID0gLUluZmluaXR5LFxuICAgIHkxID0gLUluZmluaXR5O1xuICBmb3IgKGNvbnN0IHIgb2YgcmluZ3MpIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSArIDEgPCByLmxlbmd0aDsgaSArPSAyKSB7XG4gICAgICBpZiAocltpXSA8IHgwKSB4MCA9IHJbaV07XG4gICAgICBpZiAocltpXSA+IHgxKSB4MSA9IHJbaV07XG4gICAgICBpZiAocltpICsgMV0gPCB5MCkgeTAgPSByW2kgKyAxXTtcbiAgICAgIGlmIChyW2kgKyAxXSA+IHkxKSB5MSA9IHJbaSArIDFdO1xuICAgIH1cbiAgfVxuICByZXR1cm4gW3gwLCB5MCwgeDEsIHkxXTtcbn1cbiJdfQ==