@smarterplan/ngx-smarterplan-core 1.4.21 → 1.4.22

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 (114) hide show
  1. package/README.md +24 -24
  2. package/esm2022/lib/components/csv-export/csv-export.component.mjs +3 -3
  3. package/esm2022/lib/components/loader/loader.component.mjs +3 -3
  4. package/esm2022/lib/components/menu-bar/avatar/avatar.component.mjs +1 -1
  5. package/esm2022/lib/components/menu-bar/menu-bar.component.mjs +3 -3
  6. package/esm2022/lib/components/menu-bar/navigation-bar/navigation-bar.component.mjs +3 -3
  7. package/esm2022/lib/components/modal-switch-visit/modal-switch-visit.component.mjs +3 -3
  8. package/esm2022/lib/components/search-bar/search-bar.component.mjs +3 -3
  9. package/esm2022/lib/components/splat-viewer/splat-viewer.component.mjs +361 -0
  10. package/esm2022/lib/components/support-modal/support-modal.component.mjs +3 -3
  11. package/esm2022/lib/config.mjs +1 -1
  12. package/esm2022/lib/helpers.service.mjs +1 -1
  13. package/esm2022/lib/matterport-extensions/nest-thermostat/CanvasImage.mjs +1 -1
  14. package/esm2022/lib/matterport-extensions/nest-thermostat/CanvasRenderer.mjs +1 -1
  15. package/esm2022/lib/matterport-extensions/nest-thermostat/NestThermostat.mjs +1 -1
  16. package/esm2022/lib/matterport-extensions/nest-thermostat/PlaneRenderer.mjs +1 -1
  17. package/esm2022/lib/matterport-extensions/scene-component/SceneComponent.mjs +1 -1
  18. package/esm2022/lib/matterport-extensions/security-camera/SecurityCamera.mjs +22 -22
  19. package/esm2022/lib/matterport-extensions/tv-player/TvPlayer.mjs +1 -1
  20. package/esm2022/lib/matterport-extensions/view-frustum-mesh/ViewFrustumMesh.mjs +22 -22
  21. package/esm2022/lib/mattertagData.mjs +1 -1
  22. package/esm2022/lib/ngx-smarterplan-core.module.mjs +9 -4
  23. package/esm2022/lib/ngx-smarterplan-core.service.mjs +1 -1
  24. package/esm2022/lib/pipes/duration-to-string.pipe.mjs +1 -1
  25. package/esm2022/lib/pipes/format-date-number-to-digits.pipe.mjs +1 -1
  26. package/esm2022/lib/pipes/hashtag-from-id.pipe.mjs +1 -1
  27. package/esm2022/lib/pipes/safe-url.pipe.mjs +1 -1
  28. package/esm2022/lib/pipes/time-date-to-local-string.pipe.mjs +1 -1
  29. package/esm2022/lib/pipes/username-from-id.pipe.mjs +1 -1
  30. package/esm2022/lib/services/amplify-cache.service.mjs +1 -1
  31. package/esm2022/lib/services/base-tab.service.mjs +1 -1
  32. package/esm2022/lib/services/baseVisibility.service.mjs +1 -1
  33. package/esm2022/lib/services/content.service.mjs +1 -1
  34. package/esm2022/lib/services/filter.service.mjs +1 -1
  35. package/esm2022/lib/services/intervention.service.mjs +1 -1
  36. package/esm2022/lib/services/locale.service.mjs +1 -1
  37. package/esm2022/lib/services/matterport-import.service.mjs +1 -1
  38. package/esm2022/lib/services/matterport-measurement.service.mjs +1 -1
  39. package/esm2022/lib/services/matterport-navigation.service.mjs +1 -1
  40. package/esm2022/lib/services/matterport-pointer.service.mjs +6 -6
  41. package/esm2022/lib/services/matterport-tag-copy.service.mjs +1 -1
  42. package/esm2022/lib/services/matterport-tag.service.mjs +12 -7
  43. package/esm2022/lib/services/matterport.service.mjs +17 -17
  44. package/esm2022/lib/services/models/affectation.service.mjs +1 -1
  45. package/esm2022/lib/services/models/base-object.service.mjs +1 -1
  46. package/esm2022/lib/services/models/capture.service.mjs +1 -1
  47. package/esm2022/lib/services/models/comment.service.mjs +1 -1
  48. package/esm2022/lib/services/models/domain.service.mjs +1 -1
  49. package/esm2022/lib/services/models/equipment.service.mjs +1 -1
  50. package/esm2022/lib/services/models/event.service.mjs +1 -1
  51. package/esm2022/lib/services/models/feature.service.mjs +1 -1
  52. package/esm2022/lib/services/models/hashtag.service.mjs +1 -1
  53. package/esm2022/lib/services/models/layer.service.mjs +1 -1
  54. package/esm2022/lib/services/models/measurement.service.mjs +1 -1
  55. package/esm2022/lib/services/models/mission.service.mjs +1 -1
  56. package/esm2022/lib/services/models/navigation.service.mjs +1 -1
  57. package/esm2022/lib/services/models/node.service.mjs +1 -1
  58. package/esm2022/lib/services/models/object3D.service.mjs +1 -1
  59. package/esm2022/lib/services/models/operation.service.mjs +1 -1
  60. package/esm2022/lib/services/models/organisation.service.mjs +1 -1
  61. package/esm2022/lib/services/models/plan.service.mjs +1 -1
  62. package/esm2022/lib/services/models/poi.service.mjs +27 -27
  63. package/esm2022/lib/services/models/profile.service.mjs +1 -1
  64. package/esm2022/lib/services/models/property.service.mjs +1 -1
  65. package/esm2022/lib/services/models/space.service.mjs +1 -1
  66. package/esm2022/lib/services/models/template.service.mjs +1 -1
  67. package/esm2022/lib/services/models/ticket.service.mjs +1 -1
  68. package/esm2022/lib/services/models/visit.service.mjs +1 -1
  69. package/esm2022/lib/services/models/zone.service.mjs +1 -1
  70. package/esm2022/lib/services/navigator.service.mjs +1 -1
  71. package/esm2022/lib/services/obj-to-glb.mjs +649 -0
  72. package/esm2022/lib/services/s3.service.mjs +43 -3
  73. package/esm2022/lib/services/search.service.mjs +1 -1
  74. package/esm2022/lib/services/support.service.mjs +1 -1
  75. package/esm2022/lib/services/sweep-locator.service.mjs +1 -1
  76. package/esm2022/lib/services/tag.service.mjs +16 -16
  77. package/esm2022/lib/services/threejs-import.service.mjs +6 -4
  78. package/esm2022/lib/services/threejs.service.mjs +867 -95
  79. package/esm2022/lib/services/user.service.mjs +1 -1
  80. package/esm2022/lib/services/utils/matterport-transform.util.mjs +1 -1
  81. package/esm2022/lib/services/validators.service.mjs +1 -1
  82. package/esm2022/lib/services/viewer.service.mjs +189 -7
  83. package/esm2022/lib/services/zone-drawer.service.mjs +1 -1
  84. package/esm2022/lib/services/zoneChange.service.mjs +1 -1
  85. package/esm2022/lib/tokens/matterport-sdk-key.token.mjs +1 -1
  86. package/esm2022/lib/validators/email.directive.mjs +1 -1
  87. package/esm2022/lib/validators/no-empty.directive.mjs +1 -1
  88. package/esm2022/lib/validators/number.directive.mjs +1 -1
  89. package/esm2022/lib/validators/text.directive.mjs +1 -1
  90. package/esm2022/public-api.mjs +3 -1
  91. package/fesm2022/smarterplan-ngx-smarterplan-core.mjs +2239 -233
  92. package/fesm2022/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
  93. package/lib/components/splat-viewer/splat-viewer.component.d.ts +98 -0
  94. package/lib/ngx-smarterplan-core.module.d.ts +7 -6
  95. package/lib/services/matterport-tag.service.d.ts +5 -5
  96. package/lib/services/obj-to-glb.d.ts +66 -0
  97. package/lib/services/s3.service.d.ts +7 -0
  98. package/lib/services/threejs.service.d.ts +336 -16
  99. package/lib/services/viewer.service.d.ts +110 -8
  100. package/package.json +1 -1
  101. package/public-api.d.ts +2 -0
  102. package/src/assets/viewers/splat/chunk-BYLI4YBI.js +17037 -0
  103. package/src/assets/viewers/splat/chunk-LDV6YPMG.js +1 -0
  104. package/src/assets/viewers/splat/chunk-WZ5Z4TU3.js +105719 -0
  105. package/src/assets/viewers/splat/convert-4DRLH77X.js +1 -0
  106. package/src/assets/viewers/splat/convert.html +11 -0
  107. package/src/assets/viewers/splat/converter-SLBB5MHG.js +1 -0
  108. package/src/assets/viewers/splat/index.html +90 -0
  109. package/src/assets/viewers/splat/spz-DEYRea_v-QE6YSGIB.js +5292 -0
  110. package/src/assets/viewers/splat/viewer-W4X3FWQJ.js +2704 -0
  111. package/src/assets/viewers/splat/viewer.css +1096 -0
  112. package/src/assets/viewers/splat/webp.wasm +0 -0
  113. package/src/assets/viewers/splat/worker.mjs +1383 -0
  114. package/src/assets/vs-app.json +67 -67
@@ -0,0 +1,649 @@
1
+ /**
2
+ * Converts an .obj model, with its .mtl and textures, into the .glb the Three.js viewer loads - in
3
+ * the browser, as the model is added, with nothing to install.
4
+ *
5
+ * It does what obj2gltf did in converte-modelo.sh, and the reason is the same. An .obj lists every
6
+ * corner of every triangle; loaded as it is, a captured model's 2.6 million distinct vertices become
7
+ * 12.6 million, one per corner. Here each position and texture coordinate pair becomes one vertex,
8
+ * shared by every triangle that uses it, so what reaches the graphics card is the 2.6 million.
9
+ *
10
+ * Textures go in as they are, their bytes untouched: a JPEG re-encoded would lose quality and gain
11
+ * nothing. Normals are only written when the .obj has them; without, the viewer works them out as
12
+ * it loads the model. The axes are left as the .obj has them - the viewer finds which way is up.
13
+ *
14
+ * The .obj is read as a stream, so a file of hundreds of megabytes is never held whole.
15
+ */
16
+ /** Whether a set of files holds an .obj model to convert. */
17
+ export function hasObjModel(files) {
18
+ return files.some((file) => /\.obj$/i.test(file.name));
19
+ }
20
+ /**
21
+ * Converts the .obj among `files` into a .glb, using the .mtl and the images found with it.
22
+ */
23
+ export async function convertObjToGlb(files, options = {}) {
24
+ const objs = files.filter((file) => /\.obj$/i.test(file.name));
25
+ if (objs.length !== 1) {
26
+ throw new Error(objs.length === 0 ? 'No .obj file was given.' : 'Give one .obj file at a time.');
27
+ }
28
+ const obj = objs[0];
29
+ const byName = new Map(files.map((file) => [baseName(file.name).toLowerCase(), file]));
30
+ // The .obj's own reading is most of the time; the rest is shared out over what follows.
31
+ const parsed = await readObj(obj.stream(), obj.size, {
32
+ ...options,
33
+ onProgress: (fraction) => options.onProgress?.(fraction * 0.85),
34
+ });
35
+ if (parsed.triangleCount === 0) {
36
+ throw new Error(`${obj.name} has no faces.`);
37
+ }
38
+ // Materials: from the .mtl files the .obj names, or failing that any .mtl given with it.
39
+ const named = parsed.materialLibraries.map((library) => byName.get(baseName(library).toLowerCase())).filter(Boolean);
40
+ const libraries = named.length > 0 ? named : files.filter((file) => /\.mtl$/i.test(file.name));
41
+ const materials = new Map();
42
+ for (const library of libraries) {
43
+ parseMtl(await library.text()).forEach((material) => materials.set(material.name, material));
44
+ }
45
+ await pause(options.signal);
46
+ const breaks = new Breaks(options.signal, options.onProgress);
47
+ const geometry = await indexGeometry(parsed, breaks);
48
+ options.onProgress?.(0.95);
49
+ await pause(options.signal);
50
+ const missing = new Set();
51
+ const glb = await writeGlb(parsed, geometry, materials, byName, missing, obj.name, breaks);
52
+ options.onProgress?.(1);
53
+ return {
54
+ file: new File([glb], obj.name.replace(/\.obj$/i, '') + '.glb', { type: 'model/gltf-binary' }),
55
+ vertices: geometry.vertexCount,
56
+ triangles: parsed.triangleCount,
57
+ materials: parsed.groups.length,
58
+ missingTextures: [...missing],
59
+ };
60
+ }
61
+ /** The file name without its folders, which is how an .mtl or a texture is looked up. */
62
+ function baseName(path) {
63
+ return path.trim().replace(/^"|"$/g, '').split(/[\\/]/).pop() ?? path;
64
+ }
65
+ /** Lets the page draw and answer for a moment, and stops here if the conversion was cancelled. */
66
+ async function pause(signal) {
67
+ if (signal?.aborted) {
68
+ throw new DOMException('Model conversion cancelled', 'AbortError');
69
+ }
70
+ await new Promise((resolve) => setTimeout(resolve, 0));
71
+ }
72
+ /**
73
+ * Stops a long loop now and then so the page can draw and answer clicks. Checked only every few
74
+ * thousand turns of the loop: waiting on a promise every turn would cost more than the loop.
75
+ */
76
+ class Breaks {
77
+ signal;
78
+ onProgress;
79
+ last = performance.now();
80
+ constructor(signal, onProgress) {
81
+ this.signal = signal;
82
+ this.onProgress = onProgress;
83
+ }
84
+ /** Whether this turn of the loop should stop for a moment. Synchronous: it is asked every turn. */
85
+ due(turn) {
86
+ return (turn & 0x3fff) === 0 && performance.now() - this.last > 40;
87
+ }
88
+ /** Stops for a moment, reporting how far the conversion has got. */
89
+ async take(fraction) {
90
+ this.onProgress?.(fraction);
91
+ await pause(this.signal);
92
+ this.last = performance.now();
93
+ }
94
+ }
95
+ /** A growable typed array: an .obj does not say up front how many of anything it holds. */
96
+ class Growable {
97
+ data;
98
+ length = 0;
99
+ constructor(data) {
100
+ this.data = data;
101
+ }
102
+ push(value) {
103
+ if (this.length === this.data.length) {
104
+ const bigger = new this.data.constructor(this.data.length * 2);
105
+ bigger.set(this.data);
106
+ this.data = bigger;
107
+ }
108
+ this.data[this.length] = value;
109
+ this.length += 1;
110
+ }
111
+ view() {
112
+ return this.data.subarray(0, this.length);
113
+ }
114
+ }
115
+ /**
116
+ * Reads an .obj from a stream of its bytes: positions, texture coordinates, normals, and triangles
117
+ * grouped by material. Polygons are split into triangles; negative indices, counting back from the
118
+ * end, are resolved; anything else (objects, groups, smoothing) is skipped.
119
+ */
120
+ export async function readObj(stream, size, options = {}) {
121
+ const parser = new ObjParser();
122
+ const reader = stream.getReader();
123
+ let read = 0;
124
+ let lastBreak = performance.now();
125
+ try {
126
+ for (;;) {
127
+ if (options.signal?.aborted) {
128
+ throw new DOMException('Model conversion cancelled', 'AbortError');
129
+ }
130
+ const { done, value } = await reader.read();
131
+ if (done) {
132
+ break;
133
+ }
134
+ parser.push(value);
135
+ read += value.length;
136
+ if (performance.now() - lastBreak > 40) {
137
+ options.onProgress?.(size > 0 ? Math.min(read / size, 1) : 0);
138
+ await new Promise((resolve) => setTimeout(resolve, 0));
139
+ lastBreak = performance.now();
140
+ }
141
+ }
142
+ }
143
+ finally {
144
+ reader.cancel().catch(() => undefined);
145
+ }
146
+ parser.end();
147
+ options.onProgress?.(1);
148
+ return parser.result();
149
+ }
150
+ /**
151
+ * Line by line, straight from the bytes. Building a string for each of the millions of lines of a
152
+ * captured model would be most of the work; this reads the numbers off the bytes instead.
153
+ */
154
+ class ObjParser {
155
+ positions = new Growable(new Float64Array(1 << 16));
156
+ uvs = new Growable(new Float64Array(1 << 16));
157
+ normals = new Growable(new Float64Array(1 << 16));
158
+ groups = [];
159
+ groupByMaterial = new Map();
160
+ current = null;
161
+ materialLibraries = [];
162
+ triangleCount = 0;
163
+ /** The bytes of the line being read, kept across chunks. */
164
+ line = new Uint8Array(256);
165
+ lineLength = 0;
166
+ // The corners of the face being read, as position/texture/normal indices.
167
+ face = new Int32Array(3 * 64);
168
+ push(bytes) {
169
+ for (let index = 0; index < bytes.length; index += 1) {
170
+ const byte = bytes[index];
171
+ if (byte === 10) {
172
+ this.readLine();
173
+ this.lineLength = 0;
174
+ }
175
+ else {
176
+ if (this.lineLength === this.line.length) {
177
+ const longer = new Uint8Array(this.line.length * 2);
178
+ longer.set(this.line);
179
+ this.line = longer;
180
+ }
181
+ this.line[this.lineLength] = byte;
182
+ this.lineLength += 1;
183
+ }
184
+ }
185
+ }
186
+ end() {
187
+ this.readLine();
188
+ this.lineLength = 0;
189
+ }
190
+ result() {
191
+ return {
192
+ positions: this.positions.view(),
193
+ uvs: this.uvs.view(),
194
+ normals: this.normals.view(),
195
+ groups: this.groups.filter((group) => group.corners.length > 0),
196
+ materialLibraries: this.materialLibraries,
197
+ triangleCount: this.triangleCount,
198
+ };
199
+ }
200
+ readLine() {
201
+ const line = this.line;
202
+ const length = this.lineLength;
203
+ let at = 0;
204
+ while (at < length && (line[at] === 32 || line[at] === 9)) {
205
+ at += 1;
206
+ }
207
+ if (at + 1 >= length) {
208
+ return;
209
+ }
210
+ const first = line[at];
211
+ const second = line[at + 1];
212
+ if (first === 118 && (second === 32 || second === 9)) {
213
+ // v x y z
214
+ this.readNumbers(at + 2, 3, this.positions);
215
+ }
216
+ else if (first === 118 && second === 116) {
217
+ // vt u v
218
+ this.readNumbers(at + 3, 2, this.uvs);
219
+ }
220
+ else if (first === 118 && second === 110) {
221
+ // vn x y z
222
+ this.readNumbers(at + 3, 3, this.normals);
223
+ }
224
+ else if (first === 102 && (second === 32 || second === 9)) {
225
+ this.readFace(at + 2);
226
+ }
227
+ else if (this.startsWith(at, 'usemtl')) {
228
+ this.useMaterial(this.restOfLine(at + 6));
229
+ }
230
+ else if (this.startsWith(at, 'mtllib')) {
231
+ this.materialLibraries.push(...this.restOfLine(at + 6).split(/\s+(?=\S+\.mtl\b)/i).filter(Boolean));
232
+ }
233
+ }
234
+ startsWith(at, word) {
235
+ for (let index = 0; index < word.length; index += 1) {
236
+ if (this.line[at + index] !== word.charCodeAt(index)) {
237
+ return false;
238
+ }
239
+ }
240
+ const after = this.line[at + word.length];
241
+ return after === 32 || after === 9;
242
+ }
243
+ restOfLine(at) {
244
+ let end = this.lineLength;
245
+ while (end > at && (this.line[end - 1] === 13 || this.line[end - 1] === 32 || this.line[end - 1] === 9)) {
246
+ end -= 1;
247
+ }
248
+ return new TextDecoder().decode(this.line.subarray(at, end)).trim();
249
+ }
250
+ useMaterial(name) {
251
+ let group = this.groupByMaterial.get(name);
252
+ if (!group) {
253
+ group = { material: name, corners: new Growable(new Int32Array(1 << 12)) };
254
+ this.groupByMaterial.set(name, group);
255
+ this.groups.push(group);
256
+ }
257
+ this.current = group;
258
+ }
259
+ /** Reads up to `count` numbers from `at` onwards into `target`, padding a short line with 0. */
260
+ readNumbers(at, count, target) {
261
+ let read = 0;
262
+ let position = at;
263
+ while (read < count) {
264
+ const [value, next] = this.readNumber(position);
265
+ if (next === position) {
266
+ break;
267
+ }
268
+ target.push(value);
269
+ read += 1;
270
+ position = next;
271
+ }
272
+ for (; read < count; read += 1) {
273
+ target.push(0);
274
+ }
275
+ }
276
+ /** Reads one number starting at or after `at`; returns it and where it ended. */
277
+ readNumber(at) {
278
+ const line = this.line;
279
+ const length = this.lineLength;
280
+ let index = at;
281
+ while (index < length && (line[index] === 32 || line[index] === 9 || line[index] === 13)) {
282
+ index += 1;
283
+ }
284
+ const start = index;
285
+ let negative = false;
286
+ if (line[index] === 45 || line[index] === 43) {
287
+ negative = line[index] === 45;
288
+ index += 1;
289
+ }
290
+ let whole = 0;
291
+ let fraction = 0;
292
+ let scale = 1;
293
+ let digits = 0;
294
+ while (index < length && line[index] >= 48 && line[index] <= 57) {
295
+ whole = whole * 10 + (line[index] - 48);
296
+ index += 1;
297
+ digits += 1;
298
+ }
299
+ if (line[index] === 46) {
300
+ index += 1;
301
+ while (index < length && line[index] >= 48 && line[index] <= 57) {
302
+ fraction = fraction * 10 + (line[index] - 48);
303
+ scale *= 10;
304
+ index += 1;
305
+ digits += 1;
306
+ }
307
+ }
308
+ if (digits === 0) {
309
+ return [0, at];
310
+ }
311
+ let value = whole + fraction / scale;
312
+ if (line[index] === 101 || line[index] === 69) {
313
+ index += 1;
314
+ let negativeExponent = false;
315
+ if (line[index] === 45 || line[index] === 43) {
316
+ negativeExponent = line[index] === 45;
317
+ index += 1;
318
+ }
319
+ let exponent = 0;
320
+ while (index < length && line[index] >= 48 && line[index] <= 57) {
321
+ exponent = exponent * 10 + (line[index] - 48);
322
+ index += 1;
323
+ }
324
+ value *= 10 ** (negativeExponent ? -exponent : exponent);
325
+ }
326
+ return [negative ? -value : value, index === start ? at : index];
327
+ }
328
+ /** f v/vt/vn ... - any of the three forms, any number of corners, split into a fan. */
329
+ readFace(at) {
330
+ const line = this.line;
331
+ const length = this.lineLength;
332
+ let corners = 0;
333
+ let index = at;
334
+ while (index < length) {
335
+ while (index < length && (line[index] === 32 || line[index] === 9 || line[index] === 13)) {
336
+ index += 1;
337
+ }
338
+ if (index >= length) {
339
+ break;
340
+ }
341
+ // One corner: up to three integers separated by '/', any of the last two possibly empty.
342
+ const values = [0, 0, 0];
343
+ for (let slot = 0; slot < 3; slot += 1) {
344
+ let negative = false;
345
+ if (line[index] === 45) {
346
+ negative = true;
347
+ index += 1;
348
+ }
349
+ let value = 0;
350
+ let digits = 0;
351
+ while (index < length && line[index] >= 48 && line[index] <= 57) {
352
+ value = value * 10 + (line[index] - 48);
353
+ index += 1;
354
+ digits += 1;
355
+ }
356
+ values[slot] = digits === 0 ? 0 : negative ? -value : value;
357
+ if (line[index] !== 47) {
358
+ break;
359
+ }
360
+ index += 1;
361
+ }
362
+ if (corners < 64 && values[0] !== 0) {
363
+ // To zero-based indices, counting a negative one back from what has been read so far; -1
364
+ // means "none" for the texture and normal.
365
+ this.face[corners * 3] = this.resolve(values[0], this.positions.length / 3);
366
+ this.face[corners * 3 + 1] = values[1] === 0 ? -1 : this.resolve(values[1], this.uvs.length / 2);
367
+ this.face[corners * 3 + 2] = values[2] === 0 ? -1 : this.resolve(values[2], this.normals.length / 3);
368
+ corners += 1;
369
+ }
370
+ // Skip to the next separator, past anything unexpected in this token.
371
+ while (index < length && line[index] !== 32 && line[index] !== 9) {
372
+ index += 1;
373
+ }
374
+ }
375
+ if (corners < 3) {
376
+ return;
377
+ }
378
+ if (!this.current) {
379
+ this.useMaterial(null);
380
+ }
381
+ const target = this.current.corners;
382
+ for (let corner = 1; corner + 1 < corners; corner += 1) {
383
+ for (const which of [0, corner, corner + 1]) {
384
+ target.push(this.face[which * 3]);
385
+ target.push(this.face[which * 3 + 1]);
386
+ target.push(this.face[which * 3 + 2]);
387
+ }
388
+ this.triangleCount += 1;
389
+ }
390
+ }
391
+ resolve(index, count) {
392
+ return index > 0 ? index - 1 : count + index;
393
+ }
394
+ }
395
+ /**
396
+ * Turns corners into shared vertices: one vertex per distinct position, texture and normal triple.
397
+ *
398
+ * Corners are grouped by position first, and the few corners that share a position are compared
399
+ * with one another. That needs no table of every triple ever seen - which, over millions of
400
+ * corners, would cost far more memory than the model itself.
401
+ */
402
+ async function indexGeometry(parsed, breaks) {
403
+ const positionCount = parsed.positions.length / 3;
404
+ const groups = parsed.groups.map((group) => group.corners.view());
405
+ const cornerCount = groups.reduce((sum, corners) => sum + corners.length / 3, 0);
406
+ // Every corner, numbered across all groups, listed under its position.
407
+ const perPosition = new Int32Array(positionCount + 1);
408
+ groups.forEach((corners) => {
409
+ for (let at = 0; at < corners.length; at += 3) {
410
+ perPosition[corners[at] + 1] += 1;
411
+ }
412
+ });
413
+ for (let position = 0; position < positionCount; position += 1) {
414
+ perPosition[position + 1] += perPosition[position];
415
+ }
416
+ const filled = perPosition.slice(0, positionCount);
417
+ const byPosition = new Int32Array(cornerCount);
418
+ const cornerStart = [];
419
+ let numbered = 0;
420
+ groups.forEach((corners) => {
421
+ cornerStart.push(numbered);
422
+ for (let at = 0; at < corners.length; at += 3) {
423
+ byPosition[filled[corners[at]]] = numbered;
424
+ filled[corners[at]] += 1;
425
+ numbered += 1;
426
+ }
427
+ });
428
+ // Which group each corner is in, so its triple can be read back where it already is rather than
429
+ // from a copy of every corner.
430
+ const groupOf = new Uint16Array(cornerCount);
431
+ groups.forEach((corners, group) => groupOf.fill(group, cornerStart[group], cornerStart[group] + corners.length / 3));
432
+ const vertexOfCorner = new Uint32Array(cornerCount);
433
+ const sources = new Growable(new Int32Array(Math.max(16, positionCount * 3 * 1.3) | 0));
434
+ let vertexCount = 0;
435
+ for (let position = 0; position < positionCount; position += 1) {
436
+ if (breaks.due(position)) {
437
+ await breaks.take(0.85 + 0.07 * (position / positionCount));
438
+ }
439
+ const first = vertexCount;
440
+ for (let at = perPosition[position]; at < perPosition[position + 1]; at += 1) {
441
+ const corner = byPosition[at];
442
+ const group = groupOf[corner];
443
+ const triple = (corner - cornerStart[group]) * 3;
444
+ const uv = groups[group][triple + 1];
445
+ const normal = groups[group][triple + 2];
446
+ let found = -1;
447
+ for (let vertex = first; vertex < vertexCount; vertex += 1) {
448
+ if (sources.data[vertex * 3 + 1] === uv && sources.data[vertex * 3 + 2] === normal) {
449
+ found = vertex;
450
+ break;
451
+ }
452
+ }
453
+ if (found < 0) {
454
+ found = vertexCount;
455
+ sources.push(position);
456
+ sources.push(uv);
457
+ sources.push(normal);
458
+ vertexCount += 1;
459
+ }
460
+ vertexOfCorner[corner] = found;
461
+ }
462
+ }
463
+ return {
464
+ vertexCount,
465
+ sources: sources.view(),
466
+ indices: groups.map((corners, group) => vertexOfCorner.slice(cornerStart[group], cornerStart[group] + corners.length / 3)),
467
+ };
468
+ }
469
+ /** The parts of an .mtl that matter here: the colour, the opacity and the colour texture. */
470
+ function parseMtl(text) {
471
+ const materials = [];
472
+ let current = null;
473
+ text.split(/\r?\n/).forEach((raw) => {
474
+ const line = raw.trim();
475
+ const [keyword, ...rest] = line.split(/\s+/);
476
+ if (keyword === 'newmtl') {
477
+ current = { name: rest.join(' '), colour: [1, 1, 1], opacity: 1, texture: null };
478
+ materials.push(current);
479
+ }
480
+ else if (!current) {
481
+ return;
482
+ }
483
+ else if (keyword === 'Kd' && rest.length >= 3) {
484
+ current.colour = [Number(rest[0]), Number(rest[1]), Number(rest[2])];
485
+ }
486
+ else if (keyword === 'd' && rest.length >= 1) {
487
+ current.opacity = Number(rest[0]);
488
+ }
489
+ else if (keyword === 'map_Kd' && rest.length >= 1) {
490
+ // Options (-s 1 1 1, -o ..., -bm 0.5) come before the file name, which is what is left.
491
+ current.texture = rest[rest.length - 1];
492
+ }
493
+ });
494
+ return materials;
495
+ }
496
+ /**
497
+ * Writes the .glb. The binary part is assembled from the arrays and the texture files as they are,
498
+ * into a Blob - so the textures are never read into memory, nor the whole file built in one buffer.
499
+ */
500
+ async function writeGlb(parsed, geometry, materials, files, missing, name, breaks) {
501
+ const { vertexCount, sources } = geometry;
502
+ const hasUv = parsed.uvs.length > 0 && hasAny(sources, 1);
503
+ const hasNormals = parsed.normals.length > 0 && hasAny(sources, 2);
504
+ const positions = new Float32Array(vertexCount * 3);
505
+ const min = [Infinity, Infinity, Infinity];
506
+ const max = [-Infinity, -Infinity, -Infinity];
507
+ const uvs = hasUv ? new Float32Array(vertexCount * 2) : null;
508
+ const normals = hasNormals ? new Float32Array(vertexCount * 3) : null;
509
+ for (let vertex = 0; vertex < vertexCount; vertex += 1) {
510
+ if (breaks.due(vertex)) {
511
+ await breaks.take(0.95 + 0.04 * (vertex / vertexCount));
512
+ }
513
+ const position = sources[vertex * 3];
514
+ for (let axis = 0; axis < 3; axis += 1) {
515
+ const value = parsed.positions[position * 3 + axis];
516
+ positions[vertex * 3 + axis] = value;
517
+ min[axis] = Math.min(min[axis], Math.fround(value));
518
+ max[axis] = Math.max(max[axis], Math.fround(value));
519
+ }
520
+ if (uvs) {
521
+ const uv = sources[vertex * 3 + 1];
522
+ // An .obj counts v up from the bottom of the image, glTF down from the top.
523
+ uvs[vertex * 2] = uv >= 0 ? parsed.uvs[uv * 2] : 0;
524
+ uvs[vertex * 2 + 1] = uv >= 0 ? 1 - parsed.uvs[uv * 2 + 1] : 0;
525
+ }
526
+ if (normals) {
527
+ const normal = sources[vertex * 3 + 2];
528
+ for (let axis = 0; axis < 3; axis += 1) {
529
+ normals[vertex * 3 + axis] = normal >= 0 ? parsed.normals[normal * 3 + axis] : 0;
530
+ }
531
+ }
532
+ }
533
+ const parts = [];
534
+ const bufferViews = [];
535
+ let byteLength = 0;
536
+ const addView = (part, size, target) => {
537
+ const padding = (4 - (byteLength % 4)) % 4;
538
+ if (padding) {
539
+ parts.push(new Uint8Array(padding));
540
+ byteLength += padding;
541
+ }
542
+ parts.push(part);
543
+ bufferViews.push({ buffer: 0, byteOffset: byteLength, byteLength: size, ...(target ? { target } : {}) });
544
+ byteLength += size;
545
+ return bufferViews.length - 1;
546
+ };
547
+ const accessors = [];
548
+ const addAccessor = (data, type, count, extra = {}, target) => {
549
+ const view = addView(data, data.byteLength, target);
550
+ accessors.push({ bufferView: view, componentType: data instanceof Float32Array ? 5126 : 5125, count, type, ...extra });
551
+ return accessors.length - 1;
552
+ };
553
+ const attributes = {
554
+ POSITION: addAccessor(positions, 'VEC3', vertexCount, { min, max }, 34962),
555
+ };
556
+ if (normals) {
557
+ attributes['NORMAL'] = addAccessor(normals, 'VEC3', vertexCount, {}, 34962);
558
+ }
559
+ if (uvs) {
560
+ attributes['TEXCOORD_0'] = addAccessor(uvs, 'VEC2', vertexCount, {}, 34962);
561
+ }
562
+ // Materials, each texture file stored once however many materials use it.
563
+ const images = [];
564
+ const textures = [];
565
+ const textureOf = new Map();
566
+ const textureIndex = (fileName) => {
567
+ const key = baseName(fileName).toLowerCase();
568
+ if (textureOf.has(key)) {
569
+ return textureOf.get(key);
570
+ }
571
+ const file = files.get(key);
572
+ if (!file) {
573
+ missing.add(baseName(fileName));
574
+ return null;
575
+ }
576
+ const mimeType = /\.png$/i.test(file.name) ? 'image/png' : 'image/jpeg';
577
+ images.push({ bufferView: addView(file, file.size), mimeType, name: baseName(file.name) });
578
+ textures.push({ source: images.length - 1, sampler: 0 });
579
+ textureOf.set(key, textures.length - 1);
580
+ return textures.length - 1;
581
+ };
582
+ const gltfMaterials = [];
583
+ const primitives = parsed.groups.map((group, index) => {
584
+ const material = group.material !== null ? materials.get(group.material) : undefined;
585
+ const texture = material?.texture ? textureIndex(material.texture) : null;
586
+ gltfMaterials.push({
587
+ name: group.material ?? 'default',
588
+ pbrMetallicRoughness: {
589
+ ...(texture !== null ? { baseColorTexture: { index: texture } } : {}),
590
+ baseColorFactor: texture !== null ? [1, 1, 1, material?.opacity ?? 1] : [...(material?.colour ?? [0.8, 0.8, 0.8]), material?.opacity ?? 1],
591
+ metallicFactor: 0,
592
+ roughnessFactor: 1,
593
+ },
594
+ ...(material && material.opacity < 1 ? { alphaMode: 'BLEND' } : {}),
595
+ });
596
+ const triangles = geometry.indices[index];
597
+ return {
598
+ attributes,
599
+ indices: addAccessor(triangles, 'SCALAR', triangles.length, {}, 34963),
600
+ material: gltfMaterials.length - 1,
601
+ };
602
+ });
603
+ const json = {
604
+ asset: { version: '2.0', generator: 'SmarterPlan obj-to-glb' },
605
+ scene: 0,
606
+ scenes: [{ nodes: [0] }],
607
+ nodes: [{ mesh: 0, name: name.replace(/\.obj$/i, '') }],
608
+ meshes: [{ primitives }],
609
+ materials: gltfMaterials,
610
+ ...(textures.length ? {
611
+ textures,
612
+ images,
613
+ // Linear filtering with mipmaps, repeating: what a captured model's atlas expects.
614
+ samplers: [{ magFilter: 9729, minFilter: 9987, wrapS: 10497, wrapT: 10497 }],
615
+ } : {}),
616
+ accessors,
617
+ bufferViews,
618
+ buffers: [{ byteLength }],
619
+ };
620
+ let jsonBytes = new TextEncoder().encode(JSON.stringify(json));
621
+ const jsonPadding = (4 - (jsonBytes.length % 4)) % 4;
622
+ if (jsonPadding) {
623
+ const padded = new Uint8Array(jsonBytes.length + jsonPadding).fill(32);
624
+ padded.set(jsonBytes);
625
+ jsonBytes = padded;
626
+ }
627
+ const binPadding = (4 - (byteLength % 4)) % 4;
628
+ const binLength = byteLength + binPadding;
629
+ const header = new DataView(new ArrayBuffer(12 + 8));
630
+ header.setUint32(0, 0x46546c67, true); // "glTF"
631
+ header.setUint32(4, 2, true);
632
+ header.setUint32(8, 12 + 8 + jsonBytes.length + 8 + binLength, true);
633
+ header.setUint32(12, jsonBytes.length, true);
634
+ header.setUint32(16, 0x4e4f534a, true); // "JSON"
635
+ const binHeader = new DataView(new ArrayBuffer(8));
636
+ binHeader.setUint32(0, binLength, true);
637
+ binHeader.setUint32(4, 0x004e4942, true); // "BIN"
638
+ return new Blob([header, jsonBytes, binHeader, ...parts, new Uint8Array(binPadding)]);
639
+ }
640
+ /** Whether any vertex uses the given slot of its source triple (texture or normal). */
641
+ function hasAny(sources, slot) {
642
+ for (let at = slot; at < sources.length; at += 3) {
643
+ if (sources[at] >= 0) {
644
+ return true;
645
+ }
646
+ }
647
+ return false;
648
+ }
649
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2JqLXRvLWdsYi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL25neC1zbWFydGVycGxhbi1jb3JlL3NyYy9saWIvc2VydmljZXMvb2JqLXRvLWdsYi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQTs7Ozs7Ozs7Ozs7Ozs7R0FjRztBQW1CSCw2REFBNkQ7QUFDN0QsTUFBTSxVQUFVLFdBQVcsQ0FBQyxLQUF5QjtJQUNuRCxPQUFPLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7QUFDekQsQ0FBQztBQUVEOztHQUVHO0FBQ0gsTUFBTSxDQUFDLEtBQUssVUFBVSxlQUFlLENBQUMsS0FBYSxFQUFFLFVBQWdDLEVBQUU7SUFDckYsTUFBTSxJQUFJLEdBQUcsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQztJQUMvRCxJQUFJLElBQUksQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7UUFDdEIsTUFBTSxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMseUJBQXlCLENBQUMsQ0FBQyxDQUFDLCtCQUErQixDQUFDLENBQUM7SUFDbkcsQ0FBQztJQUNELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUNwQixNQUFNLE1BQU0sR0FBRyxJQUFJLEdBQUcsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxFQUFFLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsV0FBVyxFQUFFLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFD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QUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7SUFDN0QsTUFBTSxPQUFPLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLFlBQVksQ0FBQyxXQUFXLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQztJQUN0RSxLQUFLLElBQUksTUFBTSxHQUFHLENBQUMsRUFBRSxNQUFNLEdBQUcsV0FBVyxFQUFFLE1BQU0sSUFBSSxDQUFDLEVBQUUsQ0FBQztRQUN2RCxJQUFJLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQztZQUN2QixNQUFNLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxHQUFHLElBQUksR0FBRyxDQUFDLE1BQU0sR0FBRyxXQUFXLENBQUMsQ0FBQyxDQUFDO1FBQzFELENBQUM7UUFDRCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFDO1FBQ3JDLEtBQUssSUFBSSxJQUFJLEdBQUcsQ0FBQyxFQUFFLElBQUksR0FBRyxDQUFDLEVBQUUsSUFBSSxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3ZDLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxTQUFTLENBQUMsUUFBUSxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsQ0FBQztZQUNwRCxTQUFTLENBQUMsTUFBTSxHQUFHLENBQUMsR0FBRyxJQUFJLENBQUMsR0FBRyxLQUFLLENBQUM7WUFDckMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQztZQUNwRCxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDO1FBQ3RELENBQUM7UUFDRCxJQUFJLEdBQUcsRUFBRSxDQUFDO1lBQ1Is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RCxNQUFNLFVBQVUsR0FBRyxDQUFDLENBQUMsR0FBRyxDQUFDLFVBQVUsR0FBRyxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUM5QyxNQUFNLFNBQVMsR0FBRyxVQUFVLEdBQUcsVUFBVSxDQUFDO0lBQzFDLE1BQU0sTUFBTSxHQUFHLElBQUksUUFBUSxDQUFDLElBQUksV0FBVyxDQUFDLEVBQUUsR0FBRyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ3JELE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLFVBQVUsRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFDLFNBQVM7SUFDaEQsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQzdCLE1BQU0sQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLEVBQUUsR0FBRyxDQUFDLEdBQUcsU0FBUyxDQUFDLE1BQU0sR0FBRyxDQUFDLEdBQUcsU0FBUyxFQUFFLElBQUksQ0FBQyxDQUFDO0lBQ3JFLE1BQU0sQ0FBQyxTQUFTLENBQUMsRUFBRSxFQUFFLFNBQVMsQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUM7SUFDN0MsTUFBTSxDQUFDLFNBQVMsQ0FBQyxFQUFFLEVBQUUsVUFBVSxFQUFFLElBQUksQ0FBQyxDQUFDLENBQUMsU0FBUztJQUNqRCxNQUFNLFNBQVMsR0FBRyxJQUFJLFFBQVEsQ0FBQyxJQUFJLFdBQVcsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO0lBQ25ELFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQyxFQUFFLFNBQVMsRUFBRSxJQUFJLENBQUMsQ0FBQztJQUN4QyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxDQUFDLENBQUMsQ0FBQyxRQUFRO0lBQ2xELE9BQU8sSUFBSSxJQUFJLENBQUMsQ0FBQyxNQUFNLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxHQUFHLEtBQUssRUFBRSxJQUFJLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLENBQUM7QUFDeEYsQ0FBQztBQUVELHVGQUF1RjtBQUN2RixTQUFTLE1BQU0sQ0FBQyxPQUFtQixFQUFFLElBQVk7SUFDL0MsS0FBSyxJQUFJLEVBQUUsR0FBRyxJQUFJLEVBQUUsRUFBRSxHQUFHLE9BQU8sQ0FBQyxNQUFNLEVBQUUsRUFBRSxJQUFJLENBQUMsRUFBRSxDQUFDO1FBQ2pELElBQUksT0FBTyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDO1lBQ3JCLE9BQU8sSUFBSSxDQUFDO1FBQ2QsQ0FBQztJQUNILENBQUM7SUFDRCxPQUFPLEtBQUssQ0FBQztBQUNmLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIENvbnZlcnRzIGFuIC5vYmogbW9kZWwsIHdpdGggaXRzIC5tdGwgYW5kIHRleHR1cmVzLCBpbnRvIHRoZSAuZ2xiIHRoZSBUaHJlZS5qcyB2aWV3ZXIgbG9hZHMgLSBpblxuICogdGhlIGJyb3dzZXIsIGFzIHRoZSBtb2RlbCBpcyBhZGRlZCwgd2l0aCBub3RoaW5nIHRvIGluc3RhbGwuXG4gKlxuICogSXQgZG9lcyB3aGF0IG9iajJnbHRmIGRpZCBpbiBjb252ZXJ0ZS1tb2RlbG8uc2gsIGFuZCB0aGUgcmVhc29uIGlzIHRoZSBzYW1lLiBBbiAub2JqIGxpc3RzIGV2ZXJ5XG4gKiBjb3JuZXIgb2YgZXZlcnkgdHJpYW5nbGU7IGxvYWRlZCBhcyBpdCBpcywgYSBjYXB0dXJlZCBtb2RlbCdzIDIuNiBtaWxsaW9uIGRpc3RpbmN0IHZlcnRpY2VzIGJlY29tZVxuICogMTIuNiBtaWxsaW9uLCBvbmUgcGVyIGNvcm5lci4gSGVyZSBlYWNoIHBvc2l0aW9uIGFuZCB0ZXh0dXJlIGNvb3JkaW5hdGUgcGFpciBiZWNvbWVzIG9uZSB2ZXJ0ZXgsXG4gKiBzaGFyZWQgYnkgZXZlcnkgdHJpYW5nbGUgdGhhdCB1c2VzIGl0LCBzbyB3aGF0IHJlYWNoZXMgdGhlIGdyYXBoaWNzIGNhcmQgaXMgdGhlIDIuNiBtaWxsaW9uLlxuICpcbiAqIFRleHR1cmVzIGdvIGluIGFzIHRoZXkgYXJlLCB0aGVpciBieXRlcyB1bnRvdWNoZWQ6IGEgSlBFRyByZS1lbmNvZGVkIHdvdWxkIGxvc2UgcXVhbGl0eSBhbmQgZ2FpblxuICogbm90aGluZy4gTm9ybWFscyBhcmUgb25seSB3cml0dGVuIHdoZW4gdGhlIC5vYmogaGFzIHRoZW07IHdpdGhvdXQsIHRoZSB2aWV3ZXIgd29ya3MgdGhlbSBvdXQgYXNcbiAqIGl0IGxvYWRzIHRoZSBtb2RlbC4gVGhlIGF4ZXMgYXJlIGxlZnQgYXMgdGhlIC5vYmogaGFzIHRoZW0gLSB0aGUgdmlld2VyIGZpbmRzIHdoaWNoIHdheSBpcyB1cC5cbiAqXG4gKiBUaGUgLm9iaiBpcyByZWFkIGFzIGEgc3RyZWFtLCBzbyBhIGZpbGUgb2YgaHVuZHJlZHMgb2YgbWVnYWJ5dGVzIGlzIG5ldmVyIGhlbGQgd2hvbGUuXG4gKi9cblxuZXhwb3J0IGludGVyZmFjZSBDb252ZXJ0ZWRNb2RlbCB7XG4gIC8qKiBUaGUgbW9kZWwgYXMgYSAuZ2xiLiAqL1xuICBmaWxlOiBGaWxlO1xuICB2ZXJ0aWNlczogbnVtYmVyO1xuICB0cmlhbmdsZXM6IG51bWJlcjtcbiAgbWF0ZXJpYWxzOiBudW1iZXI7XG4gIC8qKiBUZXh0dXJlcyB0aGUgLm10bCBuYW1lcyB0aGF0IHdlcmUgbm90IGFtb25nIHRoZSBmaWxlcyBnaXZlbjsgdGhvc2UgbWF0ZXJpYWxzIGdvIHVudGV4dHVyZWQuICovXG4gIG1pc3NpbmdUZXh0dXJlczogc3RyaW5nW107XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT2JqQ29udmVyc2lvbk9wdGlvbnMge1xuICAvKiogQ2FsbGVkIGFzIHRoZSBjb252ZXJzaW9uIGdvZXMsIHdpdGggdGhlIHNoYXJlIGRvbmUgc28gZmFyLiAqL1xuICBvblByb2dyZXNzPzogKGZyYWN0aW9uOiBudW1iZXIpID0+IHZvaWQ7XG4gIC8qKiBTdG9wcyB0aGUgY29udmVyc2lvbjsgaXQgdGhlbiByZWplY3RzIHdpdGggYW4gQWJvcnRFcnJvci4gKi9cbiAgc2lnbmFsPzogQWJvcnRTaWduYWw7XG59XG5cbi8qKiBXaGV0aGVyIGEgc2V0IG9mIGZpbGVzIGhvbGRzIGFuIC5vYmogbW9kZWwgdG8gY29udmVydC4gKi9cbmV4cG9ydCBmdW5jdGlvbiBoYXNPYmpNb2RlbChmaWxlczogeyBuYW1lOiBzdHJpbmcgfVtdKTogYm9vbGVhbiB7XG4gIHJldHVybiBmaWxlcy5zb21lKChmaWxlKSA9PiAvXFwub2JqJC9pLnRlc3QoZmlsZS5uYW1lKSk7XG59XG5cbi8qKlxuICogQ29udmVydHMgdGhlIC5vYmogYW1vbmcgYGZpbGVzYCBpbnRvIGEgLmdsYiwgdXNpbmcgdGhlIC5tdGwgYW5kIHRoZSBpbWFnZXMgZm91bmQgd2l0aCBpdC5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNvbnZlcnRPYmpUb0dsYihmaWxlczogRmlsZVtdLCBvcHRpb25zOiBPYmpDb252ZXJzaW9uT3B0aW9ucyA9IHt9KTogUHJvbWlzZTxDb252ZXJ0ZWRNb2RlbD4ge1xuICBjb25zdCBvYmpzID0gZmlsZXMuZmlsdGVyKChmaWxlKSA9PiAvXFwub2JqJC9pLnRlc3QoZmlsZS5uYW1lKSk7XG4gIGlmIChvYmpzLmxlbmd0aCAhPT0gMSkge1xuICAgIHRocm93IG5ldyBFcnJvcihvYmpzLmxlbmd0aCA9PT0gMCA/ICdObyAub2JqIGZpbGUgd2FzIGdpdmVuLicgOiAnR2l2ZSBvbmUgLm9iaiBmaWxlIGF0IGEgdGltZS4nKTtcbiAgfVxuICBjb25zdCBvYmogPSBvYmpzWzBdO1xuICBjb25zdCBieU5hbWUgPSBuZXcgTWFwKGZpbGVzLm1hcCgoZmlsZSkgPT4gW2Jhc2VOYW1lKGZpbGUubmFtZSkudG9Mb3dlckNhc2UoKSwgZmlsZV0pKTtcblxuICAvLyBUaGUgLm9iaidzIG93biByZWFkaW5nIGlzIG1vc3Qgb2YgdGhlIHRpbWU7IHRoZSByZXN0IGlzIHNoYXJlZCBvdXQgb3ZlciB3aGF0IGZvbGxvd3MuXG4gIGNvbnN0IHBhcnNlZCA9IGF3YWl0IHJlYWRPYmoob2JqLnN0cmVhbSgpLCBvYmouc2l6ZSwge1xuICAgIC4uLm9wdGlvbnMsXG4gICAgb25Qcm9ncmVzczogKGZyYWN0aW9uKSA9PiBvcHRpb25zLm9uUHJvZ3Jlc3M/LihmcmFjdGlvbiAqIDAuODUpLFxuICB9KTtcbiAgaWYgKHBhcnNlZC50cmlhbmdsZUNvdW50ID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKGAke29iai5uYW1lfSBoYXMgbm8gZmFjZXMuYCk7XG4gIH1cblxuICAvLyBNYXRlcmlhbHM6IGZyb20gdGhlIC5tdGwgZmlsZXMgdGhlIC5vYmogbmFtZXMsIG9yIGZhaWxpbmcgdGhhdCBhbnkgLm10bCBnaXZlbiB3aXRoIGl0LlxuICBjb25zdCBuYW1lZCA9IHBhcnNlZC5tYXRlcmlhbExpYnJhcmllcy5tYXAoKGxpYnJhcnkpID0+IGJ5TmFtZS5nZXQoYmFzZU5hbWUobGlicmFyeSkudG9Mb3dlckNhc2UoKSkpLmZpbHRlcihCb29sZWFuKTtcbiAgY29uc3QgbGlicmFyaWVzID0gbmFtZWQubGVuZ3RoID4gMCA/IG5hbWVkIDogZmlsZXMuZmlsdGVyKChmaWxlKSA9PiAvXFwubXRsJC9pLnRlc3QoZmlsZS5uYW1lKSk7XG4gIGNvbnN0IG1hdGVyaWFscyA9IG5ldyBNYXA8c3RyaW5nLCBNdGxNYXRlcmlhbD4oKTtcbiAgZm9yIChjb25zdCBsaWJyYXJ5IG9mIGxpYnJhcmllcykge1xuICAgIHBhcnNlTXRsKGF3YWl0IGxpYnJhcnkudGV4dCgpKS5mb3JFYWNoKChtYXRlcmlhbCkgPT4gbWF0ZXJpYWxzLnNldChtYXRlcmlhbC5uYW1lLCBtYXRlcmlhbCkpO1xuICB9XG4gIGF3YWl0IHBhdXNlKG9wdGlvbnMuc2lnbmFsKTtcblxuICBjb25zdCBicmVha3MgPSBuZXcgQnJlYWtzKG9wdGlvbnMuc2lnbmFsLCBvcHRpb25zLm9uUHJvZ3Jlc3MpO1xuICBjb25zdCBnZW9tZXRyeSA9IGF3YWl0IGluZGV4R2VvbWV0cnkocGFyc2VkLCBicmVha3MpO1xuICBvcHRpb25zLm9uUHJvZ3Jlc3M/LigwLjk1KTtcbiAgYXdhaXQgcGF1c2Uob3B0aW9ucy5zaWduYWwpO1xuXG4gIGNvbnN0IG1pc3NpbmcgPSBuZXcgU2V0PHN0cmluZz4oKTtcbiAgY29uc3QgZ2xiID0gYXdhaXQgd3JpdGVHbGIocGFyc2VkLCBnZW9tZXRyeSwgbWF0ZXJpYWxzLCBieU5hbWUsIG1pc3NpbmcsIG9iai5uYW1lLCBicmVha3MpO1xuICBvcHRpb25zLm9uUHJvZ3Jlc3M/LigxKTtcblxuICByZXR1cm4ge1xuICAgIGZpbGU6IG5ldyBGaWxlKFtnbGJdLCBvYmoubmFtZS5yZXBsYWNlKC9cXC5vYmokL2ksICcnKSArICcuZ2xiJywgeyB0eXBlOiAnbW9kZWwvZ2x0Zi1iaW5hcnknIH0pLFxuICAgIHZlcnRpY2VzOiBnZW9tZXRyeS52ZXJ0ZXhDb3VudCxcbiAgICB0cmlhbmdsZXM6IHBhcnNlZC50cmlhbmdsZUNvdW50LFxuICAgIG1hdGVyaWFsczogcGFyc2VkLmdyb3Vwcy5sZW5ndGgsXG4gICAgbWlzc2luZ1RleHR1cmVzOiBbLi4ubWlzc2luZ10sXG4gIH07XG59XG5cbi8qKiBUaGUgZmlsZSBuYW1lIHdpdGhvdXQgaXRzIGZvbGRlcnMsIHdoaWNoIGlzIGhvdyBhbiAubXRsIG9yIGEgdGV4dHVyZSBpcyBsb29rZWQgdXAuICovXG5mdW5jdGlvbiBiYXNlTmFtZShwYXRoOiBzdHJpbmcpOiBzdHJpbmcge1xuICByZXR1cm4gcGF0aC50cmltKCkucmVwbGFjZSgvXlwifFwiJC9nLCAnJykuc3BsaXQoL1tcXFxcL10vKS5wb3AoKSA/PyBwYXRoO1xufVxuXG4vKiogTGV0cyB0aGUgcGFnZSBkcmF3IGFuZCBhbnN3ZXIgZm9yIGEgbW9tZW50LCBhbmQgc3RvcHMgaGVyZSBpZiB0aGUgY29udmVyc2lvbiB3YXMgY2FuY2VsbGVkLiAqL1xuYXN5bmMgZnVuY3Rpb24gcGF1c2Uoc2lnbmFsPzogQWJvcnRTaWduYWwpOiBQcm9taXNlPHZvaWQ+IHtcbiAgaWYgKHNpZ25hbD8uYWJvcnRlZCkge1xuICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ01vZGVsIGNvbnZlcnNpb24gY2FuY2VsbGVkJywgJ0Fib3J0RXJyb3InKTtcbiAgfVxuICBhd2FpdCBuZXcgUHJvbWlzZSgocmVzb2x2ZSkgPT4gc2V0VGltZW91dChyZXNvbHZlLCAwKSk7XG59XG5cbi8qKlxuICogU3RvcHMgYSBsb25nIGxvb3Agbm93IGFuZCB0aGVuIHNvIHRoZSBwYWdlIGNhbiBkcmF3IGFuZCBhbnN3ZXIgY2xpY2tzLiBDaGVja2VkIG9ubHkgZXZlcnkgZmV3XG4gKiB0aG91c2FuZCB0dXJucyBvZiB0aGUgbG9vcDogd2FpdGluZyBvbiBhIHByb21pc2UgZXZlcnkgdHVybiB3b3VsZCBjb3N0IG1vcmUgdGhhbiB0aGUgbG9vcC5cbiAqL1xuY2xhc3MgQnJlYWtzIHtcbiAgcHJpdmF0ZSBsYXN0ID0gcGVyZm9ybWFuY2Uubm93KCk7XG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSByZWFkb25seSBzaWduYWw/OiBBYm9ydFNpZ25hbCwgcHJpdmF0ZSByZWFkb25seSBvblByb2dyZXNzPzogKGZyYWN0aW9uOiBudW1iZXIpID0+IHZvaWQpIHt9XG5cbiAgLyoqIFdoZXRoZXIgdGhpcyB0dXJuIG9mIHRoZSBsb29wIHNob3VsZCBzdG9wIGZvciBhIG1vbWVudC4gU3luY2hyb25vdXM6IGl0IGlzIGFza2VkIGV2ZXJ5IHR1cm4uICovXG4gIGR1ZSh0dXJuOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKHR1cm4gJiAweDNmZmYpID09PSAwICYmIHBlcmZvcm1hbmNlLm5vdygpIC0gdGhpcy5sYXN0ID4gNDA7XG4gIH1cblxuICAvKiogU3RvcHMgZm9yIGEgbW9tZW50LCByZXBvcnRpbmcgaG93IGZhciB0aGUgY29udmVyc2lvbiBoYXMgZ290LiAqL1xuICBhc3luYyB0YWtlKGZyYWN0aW9uOiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICB0aGlzLm9uUHJvZ3Jlc3M/LihmcmFjdGlvbik7XG4gICAgYXdhaXQgcGF1c2UodGhpcy5zaWduYWwpO1xuICAgIHRoaXMubGFzdCA9IHBlcmZvcm1hbmNlLm5vdygpO1xuICB9XG59XG5cbi8qKiBBIGdyb3dhYmxlIHR5cGVkIGFycmF5OiBhbiAub2JqIGRvZXMgbm90IHNheSB1cCBmcm9udCBob3cgbWFueSBvZiBhbnl0aGluZyBpdCBob2xkcy4gKi9cbmNsYXNzIEdyb3dhYmxlPFQgZXh0ZW5kcyBGbG9hdDY0QXJyYXkgfCBGbG9hdDMyQXJyYXkgfCBJbnQzMkFycmF5PiB7XG4gIGxlbmd0aCA9IDA7XG5cbiAgY29uc3RydWN0b3IocHVibGljIGRhdGE6IFQpIHt9XG5cbiAgcHVzaCh2YWx1ZTogbnVtYmVyKTogdm9pZCB7XG4gICAgaWYgKHRoaXMubGVuZ3RoID09PSB0aGlzLmRhdGEubGVuZ3RoKSB7XG4gICAgICBjb25zdCBiaWdnZXIgPSBuZXcgKHRoaXMuZGF0YS5jb25zdHJ1Y3RvciBhcyBhbnkpKHRoaXMuZGF0YS5sZW5ndGggKiAyKSBhcyBUO1xuICAgICAgYmlnZ2VyLnNldCh0aGlzLmRhdGEpO1xuICAgICAgdGhpcy5kYXRhID0gYmlnZ2VyO1xuICAgIH1cbiAgICB0aGlzLmRhdGFbdGhpcy5sZW5ndGhdID0gdmFsdWU7XG4gICAgdGhpcy5sZW5ndGggKz0gMTtcbiAgfVxuXG4gIHZpZXcoKTogVCB7XG4gICAgcmV0dXJuIHRoaXMuZGF0YS5zdWJhcnJheSgwLCB0aGlzLmxlbmd0aCkgYXMgVDtcbiAgfVxufVxuXG4vKiogVGhlIHRyaWFuZ2xlcyB0aGF0IHVzZSBvbmUgbWF0ZXJpYWwsIGFzIGNvcm5lcnM6IHBvc2l0aW9uLCB0ZXh0dXJlIGFuZCBub3JtYWwgaW5kZXggZWFjaC4gKi9cbmludGVyZmFjZSBGYWNlR3JvdXAge1xuICBtYXRlcmlhbDogc3RyaW5nIHwgbnVsbDtcbiAgY29ybmVyczogR3Jvd2FibGU8SW50MzJBcnJheT47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFyc2VkT2JqIHtcbiAgcG9zaXRpb25zOiBGbG9hdDY0QXJyYXk7XG4gIHV2czogRmxvYXQ2NEFycmF5O1xuICBub3JtYWxzOiBGbG9hdDY0QXJyYXk7XG4gIGdyb3VwczogRmFjZUdyb3VwW107XG4gIG1hdGVyaWFsTGlicmFyaWVzOiBzdHJpbmdbXTtcbiAgdHJpYW5nbGVDb3VudDogbnVtYmVyO1xufVxuXG4vKipcbiAqIFJlYWRzIGFuIC5vYmogZnJvbSBhIHN0cmVhbSBvZiBpdHMgYnl0ZXM6IHBvc2l0aW9ucywgdGV4dHVyZSBjb29yZGluYXRlcywgbm9ybWFscywgYW5kIHRyaWFuZ2xlc1xuICogZ3JvdXBlZCBieSBtYXRlcmlhbC4gUG9seWdvbnMgYXJlIHNwbGl0IGludG8gdHJpYW5nbGVzOyBuZWdhdGl2ZSBpbmRpY2VzLCBjb3VudGluZyBiYWNrIGZyb20gdGhlXG4gKiBlbmQsIGFyZSByZXNvbHZlZDsgYW55dGhpbmcgZWxzZSAob2JqZWN0cywgZ3JvdXBzLCBzbW9vdGhpbmcpIGlzIHNraXBwZWQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZWFkT2JqKFxuICBzdHJlYW06IFJlYWRhYmxlU3RyZWFtPFVpbnQ4QXJyYXk+LFxuICBzaXplOiBudW1iZXIsXG4gIG9wdGlvbnM6IE9iakNvbnZlcnNpb25PcHRpb25zID0ge30sXG4pOiBQcm9taXNlPFBhcnNlZE9iaj4ge1xuICBjb25zdCBwYXJzZXIgPSBuZXcgT2JqUGFyc2VyKCk7XG4gIGNvbnN0IHJlYWRlciA9IHN0cmVhbS5nZXRSZWFkZXIoKTtcbiAgbGV0IHJlYWQgPSAwO1xuICBsZXQgbGFzdEJyZWFrID0gcGVyZm9ybWFuY2Uubm93KCk7XG4gIHRyeSB7XG4gICAgZm9yICg7Oykge1xuICAgICAgaWYgKG9wdGlvbnMuc2lnbmFsPy5hYm9ydGVkKSB7XG4gICAgICAgIHRocm93IG5ldyBET01FeGNlcHRpb24oJ01vZGVsIGNvbnZlcnNpb24gY2FuY2VsbGVkJywgJ0Fib3J0RXJyb3InKTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IHsgZG9uZSwgdmFsdWUgfSA9IGF3YWl0IHJlYWRlci5yZWFkKCk7XG4gICAgICBpZiAoZG9uZSkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIHBhcnNlci5wdXNoKHZhbHVlKTtcbiAgICAgIHJlYWQgKz0gdmFsdWUubGVuZ3RoO1xuICAgICAgaWYgKHBlcmZvcm1hbmNlLm5vdygpIC0gbGFzdEJyZWFrID4gNDApIHtcbiAgICAgICAgb3B0aW9ucy5vblByb2dyZXNzPy4oc2l6ZSA+IDAgPyBNYXRoLm1pbihyZWFkIC8gc2l6ZSwgMSkgOiAwKTtcbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2UoKHJlc29sdmUpID0+IHNldFRpbWVvdXQocmVzb2x2ZSwgMCkpO1xuICAgICAgICBsYXN0QnJlYWsgPSBwZXJmb3JtYW5jZS5ub3coKTtcbiAgICAgIH1cbiAgICB9XG4gIH0gZmluYWxseSB7XG4gICAgcmVhZGVyLmNhbmNlbCgpLmNhdGNoKCgpID0+IHVuZGVmaW5lZCk7XG4gIH1cbiAgcGFyc2VyLmVuZCgpO1xuICBvcHRpb25zLm9uUHJvZ3Jlc3M/LigxKTtcbiAgcmV0dXJuIHBhcnNlci5yZXN1bHQoKTtcbn1cblxuLyoqXG4gKiBMaW5lIGJ5IGxpbmUsIHN0cmFpZ2h0IGZyb20gdGhlIGJ5dGVzLiBCdWlsZGluZyBhIHN0cmluZyBmb3IgZWFjaCBvZiB0aGUgbWlsbGlvbnMgb2YgbGluZXMgb2YgYVxuICogY2FwdHVyZWQgbW9kZWwgd291bGQgYmUgbW9zdCBvZiB0aGUgd29yazsgdGhpcyByZWFkcyB0aGUgbnVtYmVycyBvZmYgdGhlIGJ5dGVzIGluc3RlYWQuXG4gKi9cbmNsYXNzIE9ialBhcnNlciB7XG4gIHByaXZhdGUgcmVhZG9ubHkgcG9zaXRpb25zID0gbmV3IEdyb3dhYmxlKG5ldyBGbG9hdDY0QXJyYXkoMSA8PCAxNikpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgdXZzID0gbmV3IEdyb3dhYmxlKG5ldyBGbG9hdDY0QXJyYXkoMSA8PCAxNikpO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgbm9ybWFscyA9IG5ldyBHcm93YWJsZShuZXcgRmxvYXQ2NEFycmF5KDEgPDwgMTYpKTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGdyb3VwczogRmFjZUdyb3VwW10gPSBbXTtcblxuICBwcml2YXRlIHJlYWRvbmx5IGdyb3VwQnlNYXRlcmlhbCA9IG5ldyBNYXA8c3RyaW5nIHwgbnVsbCwgRmFjZUdyb3VwPigpO1xuXG4gIHByaXZhdGUgY3VycmVudDogRmFjZUdyb3VwIHwgbnVsbCA9IG51bGw7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBtYXRlcmlhbExpYnJhcmllczogc3RyaW5nW10gPSBbXTtcblxuICBwcml2YXRlIHRyaWFuZ2xlQ291bnQgPSAwO1xuXG4gIC8qKiBUaGUgYnl0ZXMgb2YgdGhlIGxpbmUgYmVpbmcgcmVhZCwga2VwdCBhY3Jvc3MgY2h1bmtzLiAqL1xuICBwcml2YXRlIGxpbmUgPSBuZXcgVWludDhBcnJheSgyNTYpO1xuXG4gIHByaXZhdGUgbGluZUxlbmd0aCA9IDA7XG5cbiAgLy8gVGhlIGNvcm5lcnMgb2YgdGhlIGZhY2UgYmVpbmcgcmVhZCwgYXMgcG9zaXRpb24vdGV4dHVyZS9ub3JtYWwgaW5kaWNlcy5cbiAgcHJpdmF0ZSByZWFkb25seSBmYWNlID0gbmV3IEludDMyQXJyYXkoMyAqIDY0KTtcblxuICBwdXNoKGJ5dGVzOiBVaW50OEFycmF5KTogdm9pZCB7XG4gICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGJ5dGVzLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgICAgY29uc3QgYnl0ZSA9IGJ5dGVzW2luZGV4XTtcbiAgICAgIGlmIChieXRlID09PSAxMCkge1xuICAgICAgICB0aGlzLnJlYWRMaW5lKCk7XG4gICAgICAgIHRoaXMubGluZUxlbmd0aCA9IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZiAodGhpcy5saW5lTGVuZ3RoID09PSB0aGlzLmxpbmUubGVuZ3RoKSB7XG4gICAgICAgICAgY29uc3QgbG9uZ2VyID0gbmV3IFVpbnQ4QXJyYXkodGhpcy5saW5lLmxlbmd0aCAqIDIpO1xuICAgICAgICAgIGxvbmdlci5zZXQodGhpcy5saW5lKTtcbiAgICAgICAgICB0aGlzLmxpbmUgPSBsb25nZXI7XG4gICAgICAgIH1cbiAgICAgICAgdGhpcy5saW5lW3RoaXMubGluZUxlbmd0aF0gPSBieXRlO1xuICAgICAgICB0aGlzLmxpbmVMZW5ndGggKz0gMTtcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBlbmQoKTogdm9pZCB7XG4gICAgdGhpcy5yZWFkTGluZSgpO1xuICAgIHRoaXMubGluZUxlbmd0aCA9IDA7XG4gIH1cblxuICByZXN1bHQoKTogUGFyc2VkT2JqIHtcbiAgICByZXR1cm4ge1xuICAgICAgcG9zaXRpb25zOiB0aGlzLnBvc2l0aW9ucy52aWV3KCksXG4gICAgICB1dnM6IHRoaXMudXZzLnZpZXcoKSxcbiAgICAgIG5vcm1hbHM6IHRoaXMubm9ybWFscy52aWV3KCksXG4gICAgICBncm91cHM6IHRoaXMuZ3JvdXBzLmZpbHRlcigoZ3JvdXApID0+IGdyb3VwLmNvcm5lcnMubGVuZ3RoID4gMCksXG4gICAgICBtYXRlcmlhbExpYnJhcmllczogdGhpcy5tYXRlcmlhbExpYnJhcmllcyxcbiAgICAgIHRyaWFuZ2xlQ291bnQ6IHRoaXMudHJpYW5nbGVDb3VudCxcbiAgICB9O1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkTGluZSgpOiB2b2lkIHtcbiAgICBjb25zdCBsaW5lID0gdGhpcy5saW5lO1xuICAgIGNvbnN0IGxlbmd0aCA9IHRoaXMubGluZUxlbmd0aDtcbiAgICBsZXQgYXQgPSAwO1xuICAgIHdoaWxlIChhdCA8IGxlbmd0aCAmJiAobGluZVthdF0gPT09IDMyIHx8IGxpbmVbYXRdID09PSA5KSkge1xuICAgICAgYXQgKz0gMTtcbiAgICB9XG4gICAgaWYgKGF0ICsgMSA+PSBsZW5ndGgpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3QgZmlyc3QgPSBsaW5lW2F0XTtcbiAgICBjb25zdCBzZWNvbmQgPSBsaW5lW2F0ICsgMV07XG4gICAgaWYgKGZpcnN0ID09PSAxMTggJiYgKHNlY29uZCA9PT0gMzIgfHwgc2Vjb25kID09PSA5KSkge1xuICAgICAgLy8gdiB4IHkgelxuICAgICAgdGhpcy5yZWFkTnVtYmVycyhhdCArIDIsIDMsIHRoaXMucG9zaXRpb25zKTtcbiAgICB9IGVsc2UgaWYgKGZpcnN0ID09PSAxMTggJiYgc2Vjb25kID09PSAxMTYpIHtcbiAgICAgIC8vIHZ0IHUgdlxuICAgICAgdGhpcy5yZWFkTnVtYmVycyhhdCArIDMsIDIsIHRoaXMudXZzKTtcbiAgICB9IGVsc2UgaWYgKGZpcnN0ID09PSAxMTggJiYgc2Vjb25kID09PSAxMTApIHtcbiAgICAgIC8vIHZuIHggeSB6XG4gICAgICB0aGlzLnJlYWROdW1iZXJzKGF0ICsgMywgMywgdGhpcy5ub3JtYWxzKTtcbiAgICB9IGVsc2UgaWYgKGZpcnN0ID09PSAxMDIgJiYgKHNlY29uZCA9PT0gMzIgfHwgc2Vjb25kID09PSA5KSkge1xuICAgICAgdGhpcy5yZWFkRmFjZShhdCArIDIpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5zdGFydHNXaXRoKGF0LCAndXNlbXRsJykpIHtcbiAgICAgIHRoaXMudXNlTWF0ZXJpYWwodGhpcy5yZXN0T2ZMaW5lKGF0ICsgNikpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5zdGFydHNXaXRoKGF0LCAnbXRsbGliJykpIHtcbiAgICAgIHRoaXMubWF0ZXJpYWxMaWJyYXJpZXMucHVzaCguLi50aGlzLnJlc3RPZkxpbmUoYXQgKyA2KS5zcGxpdCgvXFxzKyg/PVxcUytcXC5tdGxcXGIpL2kpLmZpbHRlcihCb29sZWFuKSk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBzdGFydHNXaXRoKGF0OiBudW1iZXIsIHdvcmQ6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIGZvciAobGV0IGluZGV4ID0gMDsgaW5kZXggPCB3b3JkLmxlbmd0aDsgaW5kZXggKz0gMSkge1xuICAgICAgaWYgKHRoaXMubGluZVthdCArIGluZGV4XSAhPT0gd29yZC5jaGFyQ29kZUF0KGluZGV4KSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGFmdGVyID0gdGhpcy5saW5lW2F0ICsgd29yZC5sZW5ndGhdO1xuICAgIHJldHVybiBhZnRlciA9PT0gMzIgfHwgYWZ0ZXIgPT09IDk7XG4gIH1cblxuICBwcml2YXRlIHJlc3RPZkxpbmUoYXQ6IG51bWJlcik6IHN0cmluZyB7XG4gICAgbGV0IGVuZCA9IHRoaXMubGluZUxlbmd0aDtcbiAgICB3aGlsZSAoZW5kID4gYXQgJiYgKHRoaXMubGluZVtlbmQgLSAxXSA9PT0gMTMgfHwgdGhpcy5saW5lW2VuZCAtIDFdID09PSAzMiB8fCB0aGlzLmxpbmVbZW5kIC0gMV0gPT09IDkpKSB7XG4gICAgICBlbmQgLT0gMTtcbiAgICB9XG4gICAgcmV0dXJuIG5ldyBUZXh0RGVjb2RlcigpLmRlY29kZSh0aGlzLmxpbmUuc3ViYXJyYXkoYXQsIGVuZCkpLnRyaW0oKTtcbiAgfVxuXG4gIHByaXZhdGUgdXNlTWF0ZXJpYWwobmFtZTogc3RyaW5nIHwgbnVsbCk6IHZvaWQge1xuICAgIGxldCBncm91cCA9IHRoaXMuZ3JvdXBCeU1hdGVyaWFsLmdldChuYW1lKTtcbiAgICBpZiAoIWdyb3VwKSB7XG4gICAgICBncm91cCA9IHsgbWF0ZXJpYWw6IG5hbWUsIGNvcm5lcnM6IG5ldyBHcm93YWJsZShuZXcgSW50MzJBcnJheSgxIDw8IDEyKSkgfTtcbiAgICAgIHRoaXMuZ3JvdXBCeU1hdGVyaWFsLnNldChuYW1lLCBncm91cCk7XG4gICAgICB0aGlzLmdyb3Vwcy5wdXNoKGdyb3VwKTtcbiAgICB9XG4gICAgdGhpcy5jdXJyZW50ID0gZ3JvdXA7XG4gIH1cblxuICAvKiogUmVhZHMgdXAgdG8gYGNvdW50YCBudW1iZXJzIGZyb20gYGF0YCBvbndhcmRzIGludG8gYHRhcmdldGAsIHBhZGRpbmcgYSBzaG9ydCBsaW5lIHdpdGggMC4gKi9cbiAgcHJpdmF0ZSByZWFkTnVtYmVycyhhdDogbnVtYmVyLCBjb3VudDogbnVtYmVyLCB0YXJnZXQ6IEdyb3dhYmxlPEZsb2F0NjRBcnJheT4pOiB2b2lkIHtcbiAgICBsZXQgcmVhZCA9IDA7XG4gICAgbGV0IHBvc2l0aW9uID0gYXQ7XG4gICAgd2hpbGUgKHJlYWQgPCBjb3VudCkge1xuICAgICAgY29uc3QgW3ZhbHVlLCBuZXh0XSA9IHRoaXMucmVhZE51bWJlcihwb3NpdGlvbik7XG4gICAgICBpZiAobmV4dCA9PT0gcG9zaXRpb24pIHtcbiAgICAgICAgYnJlYWs7XG4gICAgICB9XG4gICAgICB0YXJnZXQucHVzaCh2YWx1ZSk7XG4gICAgICByZWFkICs9IDE7XG4gICAgICBwb3NpdGlvbiA9IG5leHQ7XG4gICAgfVxuICAgIGZvciAoOyByZWFkIDwgY291bnQ7IHJlYWQgKz0gMSkge1xuICAgICAgdGFyZ2V0LnB1c2goMCk7XG4gICAgfVxuICB9XG5cbiAgLyoqIFJlYWRzIG9uZSBudW1iZXIgc3RhcnRpbmcgYXQgb3IgYWZ0ZXIgYGF0YDsgcmV0dXJucyBpdCBhbmQgd2hlcmUgaXQgZW5kZWQuICovXG4gIHByaXZhdGUgcmVhZE51bWJlcihhdDogbnVtYmVyKTogW251bWJlciwgbnVtYmVyXSB7XG4gICAgY29uc3QgbGluZSA9IHRoaXMubGluZTtcbiAgICBjb25zdCBsZW5ndGggPSB0aGlzLmxpbmVMZW5ndGg7XG4gICAgbGV0IGluZGV4ID0gYXQ7XG4gICAgd2hpbGUgKGluZGV4IDwgbGVuZ3RoICYmIChsaW5lW2luZGV4XSA9PT0gMzIgfHwgbGluZVtpbmRleF0gPT09IDkgfHwgbGluZVtpbmRleF0gPT09IDEzKSkge1xuICAgICAgaW5kZXggKz0gMTtcbiAgICB9XG4gICAgY29uc3Qgc3RhcnQgPSBpbmRleDtcbiAgICBsZXQgbmVnYXRpdmUgPSBmYWxzZTtcbiAgICBpZiAobGluZVtpbmRleF0gPT09IDQ1IHx8IGxpbmVbaW5kZXhdID09PSA0Mykge1xuICAgICAgbmVnYXRpdmUgPSBsaW5lW2luZGV4XSA9PT0gNDU7XG4gICAgICBpbmRleCArPSAxO1xuICAgIH1cbiAgICBsZXQgd2hvbGUgPSAwO1xuICAgIGxldCBmcmFjdGlvbiA9IDA7XG4gICAgbGV0IHNjYWxlID0gMTtcbiAgICBsZXQgZGlnaXRzID0gMDtcbiAgICB3aGlsZSAoaW5kZXggPCBsZW5ndGggJiYgbGluZVtpbmRleF0gPj0gNDggJiYgbGluZVtpbmRleF0gPD0gNTcpIHtcbiAgICAgIHdob2xlID0gd2hvbGUgKiAxMCArIChsaW5lW2luZGV4XSAtIDQ4KTtcbiAgICAgIGluZGV4ICs9IDE7XG4gICAgICBkaWdpdHMgKz0gMTtcbiAgICB9XG4gICAgaWYgKGxpbmVbaW5kZXhdID09PSA0Nikge1xuICAgICAgaW5kZXggKz0gMTtcbiAgICAgIHdoaWxlIChpbmRleCA8IGxlbmd0aCAmJiBsaW5lW2luZGV4XSA+PSA0OCAmJiBsaW5lW2luZGV4XSA8PSA1Nykge1xuICAgICAgICBmcmFjdGlvbiA9IGZyYWN0aW9uICogMTAgKyAobGluZVtpbmRleF0gLSA0OCk7XG4gICAgICAgIHNjYWxlICo9IDEwO1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICBkaWdpdHMgKz0gMTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGRpZ2l0cyA9PT0gMCkge1xuICAgICAgcmV0dXJuIFswLCBhdF07XG4gICAgfVxuICAgIGxldCB2YWx1ZSA9IHdob2xlICsgZnJhY3Rpb24gLyBzY2FsZTtcbiAgICBpZiAobGluZVtpbmRleF0gPT09IDEwMSB8fCBsaW5lW2luZGV4XSA9PT0gNjkpIHtcbiAgICAgIGluZGV4ICs9IDE7XG4gICAgICBsZXQgbmVnYXRpdmVFeHBvbmVudCA9IGZhbHNlO1xuICAgICAgaWYgKGxpbmVbaW5kZXhdID09PSA0NSB8fCBsaW5lW2luZGV4XSA9PT0gNDMpIHtcbiAgICAgICAgbmVnYXRpdmVFeHBvbmVudCA9IGxpbmVbaW5kZXhdID09PSA0NTtcbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH1cbiAgICAgIGxldCBleHBvbmVudCA9IDA7XG4gICAgICB3aGlsZSAoaW5kZXggPCBsZW5ndGggJiYgbGluZVtpbmRleF0gPj0gNDggJiYgbGluZVtpbmRleF0gPD0gNTcpIHtcbiAgICAgICAgZXhwb25lbnQgPSBleHBvbmVudCAqIDEwICsgKGxpbmVbaW5kZXhdIC0gNDgpO1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgfVxuICAgICAgdmFsdWUgKj0gMTAgKiogKG5lZ2F0aXZlRXhwb25lbnQgPyAtZXhwb25lbnQgOiBleHBvbmVudCk7XG4gICAgfVxuICAgIHJldHVybiBbbmVnYXRpdmUgPyAtdmFsdWUgOiB2YWx1ZSwgaW5kZXggPT09IHN0YXJ0ID8gYXQgOiBpbmRleF07XG4gIH1cblxuICAvKiogZiB2L3Z0L3ZuIC4uLiAtIGFueSBvZiB0aGUgdGhyZWUgZm9ybXMsIGFueSBudW1iZXIgb2YgY29ybmVycywgc3BsaXQgaW50byBhIGZhbi4gKi9cbiAgcHJpdmF0ZSByZWFkRmFjZShhdDogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3QgbGluZSA9IHRoaXMubGluZTtcbiAgICBjb25zdCBsZW5ndGggPSB0aGlzLmxpbmVMZW5ndGg7XG4gICAgbGV0IGNvcm5lcnMgPSAwO1xuICAgIGxldCBpbmRleCA9IGF0O1xuICAgIHdoaWxlIChpbmRleCA8IGxlbmd0aCkge1xuICAgICAgd2hpbGUgKGluZGV4IDwgbGVuZ3RoICYmIChsaW5lW2luZGV4XSA9PT0gMzIgfHwgbGluZVtpbmRleF0gPT09IDkgfHwgbGluZVtpbmRleF0gPT09IDEzKSkge1xuICAgICAgICBpbmRleCArPSAxO1xuICAgICAgfVxuICAgICAgaWYgKGluZGV4ID49IGxlbmd0aCkge1xuICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIC8vIE9uZSBjb3JuZXI6IHVwIHRvIHRocmVlIGludGVnZXJzIHNlcGFyYXRlZCBieSAnLycsIGFueSBvZiB0aGUgbGFzdCB0d28gcG9zc2libHkgZW1wdHkuXG4gICAgICBjb25zdCB2YWx1ZXMgPSBbMCwgMCwgMF07XG4gICAgICBmb3IgKGxldCBzbG90ID0gMDsgc2xvdCA8IDM7IHNsb3QgKz0gMSkge1xuICAgICAgICBsZXQgbmVnYXRpdmUgPSBmYWxzZTtcbiAgICAgICAgaWYgKGxpbmVbaW5kZXhdID09PSA0NSkge1xuICAgICAgICAgIG5lZ2F0aXZlID0gdHJ1ZTtcbiAgICAgICAgICBpbmRleCArPSAxO1xuICAgICAgICB9XG4gICAgICAgIGxldCB2YWx1ZSA9IDA7XG4gICAgICAgIGxldCBkaWdpdHMgPSAwO1xuICAgICAgICB3aGlsZSAoaW5kZXggPCBsZW5ndGggJiYgbGluZVtpbmRleF0gPj0gNDggJiYgbGluZVtpbmRleF0gPD0gNTcpIHtcbiAgICAgICAgICB2YWx1ZSA9IHZhbHVlICogMTAgKyAobGluZVtpbmRleF0gLSA0OCk7XG4gICAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgICAgICBkaWdpdHMgKz0gMTtcbiAgICAgICAgfVxuICAgICAgICB2YWx1ZXNbc2xvdF0gPSBkaWdpdHMgPT09IDAgPyAwIDogbmVnYXRpdmUgPyAtdmFsdWUgOiB2YWx1ZTtcbiAgICAgICAgaWYgKGxpbmVbaW5kZXhdICE9PSA0Nykge1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICAgIGluZGV4ICs9IDE7XG4gICAgICB9XG4gICAgICBpZiAoY29ybmVycyA8IDY0ICYmIHZhbHVlc1swXSAhPT0gMCkge1xuICAgICAgICAvLyBUbyB6ZXJvLWJhc2VkIGluZGljZXMsIGNvdW50aW5nIGEgbmVnYXRpdmUgb25lIGJhY2sgZnJvbSB3aGF0IGhhcyBiZWVuIHJlYWQgc28gZmFyOyAtMVxuICAgICAgICAvLyBtZWFucyBcIm5vbmVcIiBmb3IgdGhlIHRleHR1cmUgYW5kIG5vcm1hbC5cbiAgICAgICAgdGhpcy5mYWNlW2Nvcm5lcnMgKiAzXSA9IHRoaXMucmVzb2x2ZSh2YWx1ZXNbMF0sIHRoaXMucG9zaXRpb25zLmxlbmd0aCAvIDMpO1xuICAgICAgICB0aGlzLmZhY2VbY29ybmVycyAqIDMgKyAxXSA9IHZhbHVlc1sxXSA9PT0gMCA/IC0xIDogdGhpcy5yZXNvbHZlKHZhbHVlc1sxXSwgdGhpcy51dnMubGVuZ3RoIC8gMik7XG4gICAgICAgIHRoaXMuZmFjZVtjb3JuZXJzICogMyArIDJdID0gdmFsdWVzWzJdID09PSAwID8gLTEgOiB0aGlzLnJlc29sdmUodmFsdWVzWzJdLCB0aGlzLm5vcm1hbHMubGVuZ3RoIC8gMyk7XG4gICAgICAgIGNvcm5lcnMgKz0gMTtcbiAgICAgIH1cbiAgICAgIC8vIFNraXAgdG8gdGhlIG5leHQgc2VwYXJhdG9yLCBwYXN0IGFueXRoaW5nIHVuZXhwZWN0ZWQgaW4gdGhpcyB0b2tlbi5cbiAgICAgIHdoaWxlIChpbmRleCA8IGxlbmd0aCAmJiBsaW5lW2luZGV4XSAhPT0gMzIgJiYgbGluZVtpbmRleF0gIT09IDkpIHtcbiAgICAgICAgaW5kZXggKz0gMTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGNvcm5lcnMgPCAzKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGlmICghdGhpcy5jdXJyZW50KSB7XG4gICAgICB0aGlzLnVzZU1hdGVyaWFsKG51bGwpO1xuICAgIH1cbiAgICBjb25zdCB0YXJnZXQgPSB0aGlzLmN1cnJlbnQuY29ybmVycztcbiAgICBmb3IgKGxldCBjb3JuZXIgPSAxOyBjb3JuZXIgKyAxIDwgY29ybmVyczsgY29ybmVyICs9IDEpIHtcbiAgICAgIGZvciAoY29uc3Qgd2hpY2ggb2YgWzAsIGNvcm5lciwgY29ybmVyICsgMV0pIHtcbiAgICAgICAgdGFyZ2V0LnB1c2godGhpcy5mYWNlW3doaWNoICogM10pO1xuICAgICAgICB0YXJnZXQucHVzaCh0aGlzLmZhY2Vbd2hpY2ggKiAzICsgMV0pO1xuICAgICAgICB0YXJnZXQucHVzaCh0aGlzLmZhY2Vbd2hpY2ggKiAzICsgMl0pO1xuICAgICAgfVxuICAgICAgdGhpcy50cmlhbmdsZUNvdW50ICs9IDE7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSByZXNvbHZlKGluZGV4OiBudW1iZXIsIGNvdW50OiBudW1iZXIpOiBudW1iZXIge1xuICAgIHJldHVybiBpbmRleCA+IDAgPyBpbmRleCAtIDEgOiBjb3VudCArIGluZGV4O1xuICB9XG59XG5cbmludGVyZmFjZSBJbmRleGVkR2VvbWV0cnkge1xuICB2ZXJ0ZXhDb3VudDogbnVtYmVyO1xuICAvKiogRm9yIGVhY2ggdmVydGV4LCB0aGUgcG9zaXRpb24sIHRleHR1cmUgYW5kIG5vcm1hbCBpbmRleCBpdCB3YXMgbWFkZSBmcm9tLiAqL1xuICBzb3VyY2VzOiBJbnQzMkFycmF5O1xuICAvKiogUGVyIGZhY2UgZ3JvdXAsIGl0cyB0cmlhbmdsZXMgYXMgdmVydGV4IGluZGljZXMuICovXG4gIGluZGljZXM6IFVpbnQzMkFycmF5W107XG59XG5cbi8qKlxuICogVHVybnMgY29ybmVycyBpbnRvIHNoYXJlZCB2ZXJ0aWNlczogb25lIHZlcnRleCBwZXIgZGlzdGluY3QgcG9zaXRpb24sIHRleHR1cmUgYW5kIG5vcm1hbCB0cmlwbGUuXG4gKlxuICogQ29ybmVycyBhcmUgZ3JvdXBlZCBieSBwb3NpdGlvbiBmaXJzdCwgYW5kIHRoZSBmZXcgY29ybmVycyB0aGF0IHNoYXJlIGEgcG9zaXRpb24gYXJlIGNvbXBhcmVkXG4gKiB3aXRoIG9uZSBhbm90aGVyLiBUaGF0IG5lZWRzIG5vIHRhYmxlIG9mIGV2ZXJ5IHRyaXBsZSBldmVyIHNlZW4gLSB3aGljaCwgb3ZlciBtaWxsaW9ucyBvZlxuICogY29ybmVycywgd291bGQgY29zdCBmYXIgbW9yZSBtZW1vcnkgdGhhbiB0aGUgbW9kZWwgaXRzZWxmLlxuICovXG5hc3luYyBmdW5jdGlvbiBpbmRleEdlb21ldHJ5KHBhcnNlZDogUGFyc2VkT2JqLCBicmVha3M6IEJyZWFrcyk6IFByb21pc2U8SW5kZXhlZEdlb21ldHJ5PiB7XG4gIGNvbnN0IHBvc2l0aW9uQ291bnQgPSBwYXJzZWQucG9zaXRpb25zLmxlbmd0aCAvIDM7XG4gIGNvbnN0IGdyb3VwcyA9IHBhcnNlZC5ncm91cHMubWFwKChncm91cCkgPT4gZ3JvdXAuY29ybmVycy52aWV3KCkpO1xuICBjb25zdCBjb3JuZXJDb3VudCA9IGdyb3Vwcy5yZWR1Y2UoKHN1bSwgY29ybmVycykgPT4gc3VtICsgY29ybmVycy5sZW5ndGggLyAzLCAwKTtcblxuICAvLyBFdmVyeSBjb3JuZXIsIG51bWJlcmVkIGFjcm9zcyBhbGwgZ3JvdXBzLCBsaXN0ZWQgdW5kZXIgaXRzIHBvc2l0aW9uLlxuICBjb25zdCBwZXJQb3NpdGlvbiA9IG5ldyBJbnQzMkFycmF5KHBvc2l0aW9uQ291bnQgKyAxKTtcbiAgZ3JvdXBzLmZvckVhY2goKGNvcm5lcnMpID0+IHtcbiAgICBmb3IgKGxldCBhdCA9IDA7IGF0IDwgY29ybmVycy5sZW5ndGg7IGF0ICs9IDMpIHtcbiAgICAgIHBlclBvc2l0aW9uW2Nvcm5lcnNbYXRdICsgMV0gKz0gMTtcbiAgICB9XG4gIH0pO1xuICBmb3IgKGxldCBwb3NpdGlvbiA9IDA7IHBvc2l0aW9uIDwgcG9zaXRpb25Db3VudDsgcG9zaXRpb24gKz0gMSkge1xuICAgIHBlclBvc2l0aW9uW3Bvc2l0aW9uICsgMV0gKz0gcGVyUG9zaXRpb25bcG9zaXRpb25dO1xuICB9XG4gIGNvbnN0IGZpbGxlZCA9IHBlclBvc2l0aW9uLnNsaWNlKDAsIHBvc2l0aW9uQ291bnQpO1xuICBjb25zdCBieVBvc2l0aW9uID0gbmV3IEludDMyQXJyYXkoY29ybmVyQ291bnQpO1xuICBjb25zdCBjb3JuZXJTdGFydDogbnVtYmVyW10gPSBbXTtcbiAgbGV0IG51bWJlcmVkID0gMDtcbiAgZ3JvdXBzLmZvckVhY2goKGNvcm5lcnMpID0+IHtcbiAgICBjb3JuZXJTdGFydC5wdXNoKG51bWJlcmVkKTtcbiAgICBmb3IgKGxldCBhdCA9IDA7IGF0IDwgY29ybmVycy5sZW5ndGg7IGF0ICs9IDMpIHtcbiAgICAgIGJ5UG9zaXRpb25bZmlsbGVkW2Nvcm5lcnNbYXRdXV0gPSBudW1iZXJlZDtcbiAgICAgIGZpbGxlZFtjb3JuZXJzW2F0XV0gKz0gMTtcbiAgICAgIG51bWJlcmVkICs9IDE7XG4gICAgfVxuICB9KTtcblxuICAvLyBXaGljaCBncm91cCBlYWNoIGNvcm5lciBpcyBpbiwgc28gaXRzIHRyaXBsZSBjYW4gYmUgcmVhZCBiYWNrIHdoZXJlIGl0IGFscmVhZHkgaXMgcmF0aGVyIHRoYW5cbiAgLy8gZnJvbSBhIGNvcHkgb2YgZXZlcnkgY29ybmVyLlxuICBjb25zdCBncm91cE9mID0gbmV3IFVpbnQxNkFycmF5KGNvcm5lckNvdW50KTtcbiAgZ3JvdXBzLmZvckVhY2goKGNvcm5lcnMsIGdyb3VwKSA9PiBncm91cE9mLmZpbGwoZ3JvdXAsIGNvcm5lclN0YXJ0W2dyb3VwXSwgY29ybmVyU3RhcnRbZ3JvdXBdICsgY29ybmVycy5sZW5ndGggLyAzKSk7XG5cbiAgY29uc3QgdmVydGV4T2ZDb3JuZXIgPSBuZXcgVWludDMyQXJyYXkoY29ybmVyQ291bnQpO1xuICBjb25zdCBzb3VyY2VzID0gbmV3IEdyb3dhYmxlKG5ldyBJbnQzMkFycmF5KE1hdGgubWF4KDE2LCBwb3NpdGlvbkNvdW50ICogMyAqIDEuMykgfCAwKSk7XG4gIGxldCB2ZXJ0ZXhDb3VudCA9IDA7XG4gIGZvciAobGV0IHBvc2l0aW9uID0gMDsgcG9zaXRpb24gPCBwb3NpdGlvbkNvdW50OyBwb3NpdGlvbiArPSAxKSB7XG4gICAgaWYgKGJyZWFrcy5kdWUocG9zaXRpb24pKSB7XG4gICAgICBhd2FpdCBicmVha3MudGFrZSgwLjg1ICsgMC4wNyAqIChwb3NpdGlvbiAvIHBvc2l0aW9uQ291bnQpKTtcbiAgICB9XG4gICAgY29uc3QgZmlyc3QgPSB2ZXJ0ZXhDb3VudDtcbiAgICBmb3IgKGxldCBhdCA9IHBlclBvc2l0aW9uW3Bvc2l0aW9uXTsgYXQgPCBwZXJQb3NpdGlvbltwb3NpdGlvbiArIDFdOyBhdCArPSAxKSB7XG4gICAgICBjb25zdCBjb3JuZXIgPSBieVBvc2l0aW9uW2F0XTtcbiAgICAgIGNvbnN0IGdyb3VwID0gZ3JvdXBPZltjb3JuZXJdO1xuICAgICAgY29uc3QgdHJpcGxlID0gKGNvcm5lciAtIGNvcm5lclN0YXJ0W2dyb3VwXSkgKiAzO1xuICAgICAgY29uc3QgdXYgPSBncm91cHNbZ3JvdXBdW3RyaXBsZSArIDFdO1xuICAgICAgY29uc3Qgbm9ybWFsID0gZ3JvdXBzW2dyb3VwXVt0cmlwbGUgKyAyXTtcbiAgICAgIGxldCBmb3VuZCA9IC0xO1xuICAgICAgZm9yIChsZXQgdmVydGV4ID0gZmlyc3Q7IHZlcnRleCA8IHZlcnRleENvdW50OyB2ZXJ0ZXggKz0gMSkge1xuICAgICAgICBpZiAoc291cmNlcy5kYXRhW3ZlcnRleCAqIDMgKyAxXSA9PT0gdXYgJiYgc291cmNlcy5kYXRhW3ZlcnRleCAqIDMgKyAyXSA9PT0gbm9ybWFsKSB7XG4gICAgICAgICAgZm91bmQgPSB2ZXJ0ZXg7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmIChmb3VuZCA8IDApIHtcbiAgICAgICAgZm91bmQgPSB2ZXJ0ZXhDb3VudDtcbiAgICAgICAgc291cmNlcy5wdXNoKHBvc2l0aW9uKTtcbiAgICAgICAgc291cmNlcy5wdXNoKHV2KTtcbiAgICAgICAgc291cmNlcy5wdXNoKG5vcm1hbCk7XG4gICAgICAgIHZlcnRleENvdW50ICs9IDE7XG4gICAgICB9XG4gICAgICB2ZXJ0ZXhPZkNvcm5lcltjb3JuZXJdID0gZm91bmQ7XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICB2ZXJ0ZXhDb3VudCxcbiAgICBzb3VyY2VzOiBzb3VyY2VzLnZpZXcoKSxcbiAgICBpbmRpY2VzOiBncm91cHMubWFwKChjb3JuZXJzLCBncm91cCkgPT4gdmVydGV4T2ZDb3JuZXIuc2xpY2UoY29ybmVyU3RhcnRbZ3JvdXBdLCBjb3JuZXJTdGFydFtncm91cF0gKyBjb3JuZXJzLmxlbmd0aCAvIDMpKSxcbiAgfTtcbn1cblxuaW50ZXJmYWNlIE10bE1hdGVyaWFsIHtcbiAgbmFtZTogc3RyaW5nO1xuICBjb2xvdXI6IFtudW1iZXIsIG51bWJlciwgbnVtYmVyXTtcbiAgb3BhY2l0eTogbnVtYmVyO1xuICB0ZXh0dXJlOiBzdHJpbmcgfCBudWxsO1xufVxuXG4vKiogVGhlIHBhcnRzIG9mIGFuIC5tdGwgdGhhdCBtYXR0ZXIgaGVyZTogdGhlIGNvbG91ciwgdGhlIG9wYWNpdHkgYW5kIHRoZSBjb2xvdXIgdGV4dHVyZS4gKi9cbmZ1bmN0aW9uIHBhcnNlTXRsKHRleHQ6IHN0cmluZyk6IE10bE1hdGVyaWFsW10ge1xuICBjb25zdCBtYXRlcmlhbHM6IE10bE1hdGVyaWFsW10gPSBbXTtcbiAgbGV0IGN1cnJlbnQ6IE10bE1hdGVyaWFsIHwgbnVsbCA9IG51bGw7XG4gIHRleHQuc3BsaXQoL1xccj9cXG4vKS5mb3JFYWNoKChyYXcpID0+IHtcbiAgICBjb25zdCBsaW5lID0gcmF3LnRyaW0oKTtcbiAgICBjb25zdCBba2V5d29yZCwgLi4ucmVzdF0gPSBsaW5lLnNwbGl0KC9cXHMrLyk7XG4gICAgaWYgKGtleXdvcmQgPT09ICduZXdtdGwnKSB7XG4gICAgICBjdXJyZW50ID0geyBuYW1lOiByZXN0LmpvaW4oJyAnKSwgY29sb3VyOiBbMSwgMSwgMV0sIG9wYWNpdHk6IDEsIHRleHR1cmU6IG51bGwgfTtcbiAgICAgIG1hdGVyaWFscy5wdXNoKGN1cnJlbnQpO1xuICAgIH0gZWxzZSBpZiAoIWN1cnJlbnQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9IGVsc2UgaWYgKGtleXdvcmQgPT09ICdLZCcgJiYgcmVzdC5sZW5ndGggPj0gMykge1xuICAgICAgY3VycmVudC5jb2xvdXIgPSBbTnVtYmVyKHJlc3RbMF0pLCBOdW1iZXIocmVzdFsxXSksIE51bWJlcihyZXN0WzJdKV07XG4gICAgfSBlbHNlIGlmIChrZXl3b3JkID09PSAnZCcgJiYgcmVzdC5sZW5ndGggPj0gMSkge1xuICAgICAgY3VycmVudC5vcGFjaXR5ID0gTnVtYmVyKHJlc3RbMF0pO1xuICAgIH0gZWxzZSBpZiAoa2V5d29yZCA9PT0gJ21hcF9LZCcgJiYgcmVzdC5sZW5ndGggPj0gMSkge1xuICAgICAgLy8gT3B0aW9ucyAoLXMgMSAxIDEsIC1vIC4uLiwgLWJtIDAuNSkgY29tZSBiZWZvcmUgdGhlIGZpbGUgbmFtZSwgd2hpY2ggaXMgd2hhdCBpcyBsZWZ0LlxuICAgICAgY3VycmVudC50ZXh0dXJlID0gcmVzdFtyZXN0Lmxlbmd0aCAtIDFdO1xuICAgIH1cbiAgfSk7XG4gIHJldHVybiBtYXRlcmlhbHM7XG59XG5cbi8qKlxuICogV3JpdGVzIHRoZSAuZ2xiLiBUaGUgYmluYXJ5IHBhcnQgaXMgYXNzZW1ibGVkIGZyb20gdGhlIGFycmF5cyBhbmQgdGhlIHRleHR1cmUgZmlsZXMgYXMgdGhleSBhcmUsXG4gKiBpbnRvIGEgQmxvYiAtIHNvIHRoZSB0ZXh0dXJlcyBhcmUgbmV2ZXIgcmVhZCBpbnRvIG1lbW9yeSwgbm9yIHRoZSB3aG9sZSBmaWxlIGJ1aWx0IGluIG9uZSBidWZmZXIuXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHdyaXRlR2xiKFxuICBwYXJzZWQ6IFBhcnNlZE9iaixcbiAgZ2VvbWV0cnk6IEluZGV4ZWRHZW9tZXRyeSxcbiAgbWF0ZXJpYWxzOiBNYXA8c3RyaW5nLCBNdGxNYXRlcmlhbD4sXG4gIGZpbGVzOiBNYXA8c3RyaW5nLCBGaWxlPixcbiAgbWlzc2luZzogU2V0PHN0cmluZz4sXG4gIG5hbWU6IHN0cmluZyxcbiAgYnJlYWtzOiBCcmVha3MsXG4pOiBQcm9taXNlPEJsb2I+IHtcbiAgY29uc3QgeyB2ZXJ0ZXhDb3VudCwgc291cmNlcyB9ID0gZ2VvbWV0cnk7XG4gIGNvbnN0IGhhc1V2ID0gcGFyc2VkLnV2cy5sZW5ndGggPiAwICYmIGhhc0FueShzb3VyY2VzLCAxKTtcbiAgY29uc3QgaGFzTm9ybWFscyA9IHBhcnNlZC5ub3JtYWxzLmxlbmd0aCA+IDAgJiYgaGFzQW55KHNvdXJjZXMsIDIpO1xuXG4gIGNvbnN0IHBvc2l0aW9ucyA9IG5ldyBGbG9hdDMyQXJyYXkodmVydGV4Q291bnQgKiAzKTtcbiAgY29uc3QgbWluID0gW0luZmluaXR5LCBJbmZpbml0eSwgSW5maW5pdHldO1xuICBjb25zdCBtYXggPSBbLUluZmluaXR5LCAtSW5maW5pdHksIC1JbmZpbml0eV07XG4gIGNvbnN0IHV2cyA9IGhhc1V2ID8gbmV3IEZsb2F0MzJBcnJheSh2ZXJ0ZXhDb3VudCAqIDIpIDogbnVsbDtcbiAgY29uc3Qgbm9ybWFscyA9IGhhc05vcm1hbHMgPyBuZXcgRmxvYXQzMkFycmF5KHZlcnRleENvdW50ICogMykgOiBudWxsO1xuICBmb3IgKGxldCB2ZXJ0ZXggPSAwOyB2ZXJ0ZXggPCB2ZXJ0ZXhDb3VudDsgdmVydGV4ICs9IDEpIHtcbiAgICBpZiAoYnJlYWtzLmR1ZSh2ZXJ0ZXgpKSB7XG4gICAgICBhd2FpdCBicmVha3MudGFrZSgwLjk1ICsgMC4wNCAqICh2ZXJ0ZXggLyB2ZXJ0ZXhDb3VudCkpO1xuICAgIH1cbiAgICBjb25zdCBwb3NpdGlvbiA9IHNvdXJjZXNbdmVydGV4ICogM107XG4gICAgZm9yIChsZXQgYXhpcyA9IDA7IGF4aXMgPCAzOyBheGlzICs9IDEpIHtcbiAgICAgIGNvbnN0IHZhbHVlID0gcGFyc2VkLnBvc2l0aW9uc1twb3NpdGlvbiAqIDMgKyBheGlzXTtcbiAgICAgIHBvc2l0aW9uc1t2ZXJ0ZXggKiAzICsgYXhpc10gPSB2YWx1ZTtcbiAgICAgIG1pbltheGlzXSA9IE1hdGgubWluKG1pbltheGlzXSwgTWF0aC5mcm91bmQodmFsdWUpKTtcbiAgICAgIG1heFtheGlzXSA9IE1hdGgubWF4KG1heFtheGlzXSwgTWF0aC5mcm91bmQodmFsdWUpKTtcbiAgICB9XG4gICAgaWYgKHV2cykge1xuICAgICAgY29uc3QgdXYgPSBzb3VyY2VzW3ZlcnRleCAqIDMgKyAxXTtcbiAgICAgIC8vIEFuIC5vYmogY291bnRzIHYgdXAgZnJvbSB0aGUgYm90dG9tIG9mIHRoZSBpbWFnZSwgZ2xURiBkb3duIGZyb20gdGhlIHRvcC5cbiAgICAgIHV2c1t2ZXJ0ZXggKiAyXSA9IHV2ID49IDAgPyBwYXJzZWQudXZzW3V2ICogMl0gOiAwO1xuICAgICAgdXZzW3ZlcnRleCAqIDIgKyAxXSA9IHV2ID49IDAgPyAxIC0gcGFyc2VkLnV2c1t1diAqIDIgKyAxXSA6IDA7XG4gICAgfVxuICAgIGlmIChub3JtYWxzKSB7XG4gICAgICBjb25zdCBub3JtYWwgPSBzb3VyY2VzW3ZlcnRleCAqIDMgKyAyXTtcbiAgICAgIGZvciAobGV0IGF4aXMgPSAwOyBheGlzIDwgMzsgYXhpcyArPSAxKSB7XG4gICAgICAgIG5vcm1hbHNbdmVydGV4ICogMyArIGF4aXNdID0gbm9ybWFsID49IDAgPyBwYXJzZWQubm9ybWFsc1tub3JtYWwgKiAzICsgYXhpc10gOiAwO1xuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHBhcnRzOiBCbG9iUGFydFtdID0gW107XG4gIGNvbnN0IGJ1ZmZlclZpZXdzOiBhbnlbXSA9IFtdO1xuICBsZXQgYnl0ZUxlbmd0aCA9IDA7XG4gIGNvbnN0IGFkZFZpZXcgPSAocGFydDogQmxvYiB8IEFycmF5QnVmZmVyVmlldywgc2l6ZTogbnVtYmVyLCB0YXJnZXQ/OiBudW1iZXIpOiBudW1iZXIgPT4ge1xuICAgIGNvbnN0IHBhZGRpbmcgPSAoNCAtIChieXRlTGVuZ3RoICUgNCkpICUgNDtcbiAgICBpZiAocGFkZGluZykge1xuICAgICAgcGFydHMucHVzaChuZXcgVWludDhBcnJheShwYWRkaW5nKSk7XG4gICAgICBieXRlTGVuZ3RoICs9IHBhZGRpbmc7XG4gICAgfVxuICAgIHBhcnRzLnB1c2gocGFydCBhcyBCbG9iUGFydCk7XG4gICAgYnVmZmVyVmlld3MucHVzaCh7IGJ1ZmZlcjogMCwgYnl0ZU9mZnNldDogYnl0ZUxlbmd0aCwgYnl0ZUxlbmd0aDogc2l6ZSwgLi4uKHRhcmdldCA/IHsgdGFyZ2V0IH0gOiB7fSkgfSk7XG4gICAgYnl0ZUxlbmd0aCArPSBzaXplO1xuICAgIHJldHVybiBidWZmZXJWaWV3cy5sZW5ndGggLSAxO1xuICB9O1xuXG4gIGNvbnN0IGFjY2Vzc29yczogYW55W10gPSBbXTtcbiAgY29uc3QgYWRkQWNjZXNzb3IgPSAoZGF0YTogRmxvYXQzMkFycmF5IHwgVWludDMyQXJyYXksIHR5cGU6IHN0cmluZywgY291bnQ6IG51bWJlciwgZXh0cmE6IG9iamVjdCA9IHt9LCB0YXJnZXQ/OiBudW1iZXIpID0+IHtcbiAgICBjb25zdCB2aWV3ID0gYWRkVmlldyhkYXRhLCBkYXRhLmJ5dGVMZW5ndGgsIHRhcmdldCk7XG4gICAgYWNjZXNzb3JzLnB1c2goeyBidWZmZXJWaWV3OiB2aWV3LCBjb21wb25lbnRUeXBlOiBkYXRhIGluc3RhbmNlb2YgRmxvYXQzMkFycmF5ID8gNTEyNiA6IDUxMjUsIGNvdW50LCB0eXBlLCAuLi5leHRyYSB9KTtcbiAgICByZXR1cm4gYWNjZXNzb3JzLmxlbmd0aCAtIDE7XG4gIH07XG4gIGNvbnN0IGF0dHJpYnV0ZXM6IFJlY29yZDxzdHJpbmcsIG51bWJlcj4gPSB7XG4gICAgUE9TSVRJT046IGFkZEFjY2Vzc29yKHBvc2l0aW9ucywgJ1ZFQzMnLCB2ZXJ0ZXhDb3VudCwgeyBtaW4sIG1heCB9LCAzNDk2MiksXG4gIH07XG4gIGlmIChub3JtYWxzKSB7XG4gICAgYXR0cmlidXRlc1snTk9STUFMJ10gPSBhZGRBY2Nlc3Nvcihub3JtYWxzLCAnVkVDMycsIHZlcnRleENvdW50LCB7fSwgMzQ5NjIpO1xuICB9XG4gIGlmICh1dnMpIHtcbiAgICBhdHRyaWJ1dGVzWydURVhDT09SRF8wJ10gPSBhZGRBY2Nlc3Nvcih1dnMsICdWRUMyJywgdmVydGV4Q291bnQsIHt9LCAzNDk2Mik7XG4gIH1cblxuICAvLyBNYXRlcmlhbHMsIGVhY2ggdGV4dHVyZSBmaWxlIHN0b3JlZCBvbmNlIGhvd2V2ZXIgbWFueSBtYXRlcmlhbHMgdXNlIGl0LlxuICBjb25zdCBpbWFnZXM6IGFueVtdID0gW107XG4gIGNvbnN0IHRleHR1cmVzOiBhbnlbXSA9IFtdO1xuICBjb25zdCB0ZXh0dXJlT2YgPSBuZXcgTWFwPHN0cmluZywgbnVtYmVyPigpO1xuICBjb25zdCB0ZXh0dXJlSW5kZXggPSAoZmlsZU5hbWU6IHN0cmluZyk6IG51bWJlciB8IG51bGwgPT4ge1xuICAgIGNvbnN0IGtleSA9IGJhc2VOYW1lKGZpbGVOYW1lKS50b0xvd2VyQ2FzZSgpO1xuICAgIGlmICh0ZXh0dXJlT2YuaGFzKGtleSkpIHtcbiAgICAgIHJldHVybiB0ZXh0dXJlT2YuZ2V0KGtleSk7XG4gICAgfVxuICAgIGNvbnN0IGZpbGUgPSBmaWxlcy5nZXQoa2V5KTtcbiAgICBpZiAoIWZpbGUpIHtcbiAgICAgIG1pc3NpbmcuYWRkKGJhc2VOYW1lKGZpbGVOYW1lKSk7XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gICAgY29uc3QgbWltZVR5cGUgPSAvXFwucG5nJC9pLnRlc3QoZmlsZS5uYW1lKSA/ICdpbWFnZS9wbmcnIDogJ2ltYWdlL2pwZWcnO1xuICAgIGltYWdlcy5wdXNoKHsgYnVmZmVyVmlldzogYWRkVmlldyhmaWxlLCBmaWxlLnNpemUpLCBtaW1lVHlwZSwgbmFtZTogYmFzZU5hbWUoZmlsZS5uYW1lKSB9KTtcbiAgICB0ZXh0dXJlcy5wdXNoKHsgc291cmNlOiBpbWFnZXMubGVuZ3RoIC0gMSwgc2FtcGxlcjogMCB9KTtcbiAgICB0ZXh0dXJlT2Yuc2V0KGtleSwgdGV4dHVyZXMubGVuZ3RoIC0gMSk7XG4gICAgcmV0dXJuIHRleHR1cmVzLmxlbmd0aCAtIDE7XG4gIH07XG4gIGNvbnN0IGdsdGZNYXRlcmlhbHM6IGFueVtdID0gW107XG4gIGNvbnN0IHByaW1pdGl2ZXMgPSBwYXJzZWQuZ3JvdXBzLm1hcCgoZ3JvdXAsIGluZGV4KSA9PiB7XG4gICAgY29uc3QgbWF0ZXJpYWwgPSBncm91cC5tYXRlcmlhbCAhPT0gbnVsbCA/IG1hdGVyaWFscy5nZXQoZ3JvdXAubWF0ZXJpYWwpIDogdW5kZWZpbmVkO1xuICAgIGNvbnN0IHRleHR1cmUgPSBtYXRlcmlhbD8udGV4dHVyZSA/IHRleHR1cmVJbmRleChtYXRlcmlhbC50ZXh0dXJlKSA6IG51bGw7XG4gICAgZ2x0Zk1hdGVyaWFscy5wdXNoKHtcbiAgICAgIG5hbWU6IGdyb3VwLm1hdGVyaWFsID8/ICdkZWZhdWx0JyxcbiAgICAgIHBick1ldGFsbGljUm91Z2huZXNzOiB7XG4gICAgICAgIC4uLih0ZXh0dXJlICE9PSBudWxsID8geyBiYXNlQ29sb3JUZXh0dXJlOiB7IGluZGV4OiB0ZXh0dXJlIH0gfSA6IHt9KSxcbiAgICAgICAgYmFzZUNvbG9yRmFjdG9yOiB0ZXh0dXJlICE9PSBudWxsID8gWzEsIDEsIDEsIG1hdGVyaWFsPy5vcGFjaXR5ID8/IDFdIDogWy4uLihtYXRlcmlhbD8uY29sb3VyID8/IFswLjgsIDAuOCwgMC44XSksIG1hdGVyaWFsPy5vcGFjaXR5ID8/IDFdLFxuICAgICAgICBtZXRhbGxpY0ZhY3RvcjogMCxcbiAgICAgICAgcm91Z2huZXNzRmFjdG9yOiAxLFxuICAgICAgfSxcbiAgICAgIC4uLihtYXRlcmlhbCAmJiBtYXRlcmlhbC5vcGFjaXR5IDwgMSA/IHsgYWxwaGFNb2RlOiAnQkxFTkQnIH0gOiB7fSksXG4gICAgfSk7XG4gICAgY29uc3QgdHJpYW5nbGVzID0gZ2VvbWV0cnkuaW5kaWNlc1tpbmRleF07XG4gICAgcmV0dXJuIHtcbiAgICAgIGF0dHJpYnV0ZXMsXG4gICAgICBpbmRpY2VzOiBhZGRBY2Nlc3Nvcih0cmlhbmdsZXMsICdTQ0FMQVInLCB0cmlhbmdsZXMubGVuZ3RoLCB7fSwgMzQ5NjMpLFxuICAgICAgbWF0ZXJpYWw6IGdsdGZNYXRlcmlhbHMubGVuZ3RoIC0gMSxcbiAgICB9O1xuICB9KTtcblxuICBjb25zdCBqc29uID0ge1xuICAgIGFzc2V0OiB7IHZlcnNpb246ICcyLjAnLCBnZW5lcmF0b3I6ICdTbWFydGVyUGxhbiBvYmotdG8tZ2xiJyB9LFxuICAgIHNjZW5lOiAwLFxuICAgIHNjZW5lczogW3sgbm9kZXM6IFswXSB9XSxcbiAgICBub2RlczogW3sgbWVzaDogMCwgbmFtZTogbmFtZS5yZXBsYWNlKC9cXC5vYmokL2ksICcnKSB9XSxcbiAgICBtZXNoZXM6IFt7IHByaW1pdGl2ZXMgfV0sXG4gICAgbWF0ZXJpYWxzOiBnbHRmTWF0ZXJpYWxzLFxuICAgIC4uLih0ZXh0dXJlcy5sZW5ndGggPyB7XG4gICAgICB0ZXh0dXJlcyxcbiAgICAgIGltYWdlcyxcbiAgICAgIC8vIExpbmVhciBmaWx0ZXJpbmcgd2l0aCBtaXBtYXBzLCByZXBlYXRpbmc6IHdoYXQgYSBjYXB0dXJlZCBtb2RlbCdzIGF0bGFzIGV4cGVjdHMuXG4gICAgICBzYW1wbGVyczogW3sgbWFnRmlsdGVyOiA5NzI5LCBtaW5GaWx0ZXI6IDk5ODcsIHdyYXBTOiAxMDQ5Nywgd3JhcFQ6IDEwNDk3IH1dLFxuICAgIH0gOiB7fSksXG4gICAgYWNjZXNzb3JzLFxuICAgIGJ1ZmZlclZpZXdzLFxuICAgIGJ1ZmZlcnM6IFt7IGJ5dGVMZW5ndGggfV0sXG4gIH07XG5cbiAgbGV0IGpzb25CeXRlcyA9IG5ldyBUZXh0RW5jb2RlcigpLmVuY29kZShKU09OLnN0cmluZ2lmeShqc29uKSk7XG4gIGNvbnN0IGpzb25QYWRkaW5nID0gKDQgLSAoanNvbkJ5dGVzLmxlbmd0aCAlIDQpKSAlIDQ7XG4gIGlmIChqc29uUGFkZGluZykge1xuICAgIGNvbnN0IHBhZGRlZCA9IG5ldyBVaW50OEFycmF5KGpzb25CeXRlcy5sZW5ndGggKyBqc29uUGFkZGluZykuZmlsbCgzMik7XG4gICAgcGFkZGVkLnNldChqc29uQnl0ZXMpO1xuICAgIGpzb25CeXRlcyA9IHBhZGRlZDtcbiAgfVxuICBjb25zdCBiaW5QYWRkaW5nID0gKDQgLSAoYnl0ZUxlbmd0aCAlIDQpKSAlIDQ7XG4gIGNvbnN0IGJpbkxlbmd0aCA9IGJ5dGVMZW5ndGggKyBiaW5QYWRkaW5nO1xuICBjb25zdCBoZWFkZXIgPSBuZXcgRGF0YVZpZXcobmV3IEFycmF5QnVmZmVyKDEyICsgOCkpO1xuICBoZWFkZXIuc2V0VWludDMyKDAsIDB4NDY1NDZjNjcsIHRydWUpOyAvLyBcImdsVEZcIlxuICBoZWFkZXIuc2V0VWludDMyKDQsIDIsIHRydWUpO1xuICBoZWFkZXIuc2V0VWludDMyKDgsIDEyICsgOCArIGpzb25CeXRlcy5sZW5ndGggKyA4ICsgYmluTGVuZ3RoLCB0cnVlKTtcbiAgaGVhZGVyLnNldFVpbnQzMigxMiwganNvbkJ5dGVzLmxlbmd0aCwgdHJ1ZSk7XG4gIGhlYWRlci5zZXRVaW50MzIoMTYsIDB4NGU0ZjUzNGEsIHRydWUpOyAvLyBcIkpTT05cIlxuICBjb25zdCBiaW5IZWFkZXIgPSBuZXcgRGF0YVZpZXcobmV3IEFycmF5QnVmZmVyKDgpKTtcbiAgYmluSGVhZGVyLnNldFVpbnQzMigwLCBiaW5MZW5ndGgsIHRydWUpO1xuICBiaW5IZWFkZXIuc2V0VWludDMyKDQsIDB4MDA0ZTQ5NDIsIHRydWUpOyAvLyBcIkJJTlwiXG4gIHJldHVybiBuZXcgQmxvYihbaGVhZGVyLCBqc29uQnl0ZXMsIGJpbkhlYWRlciwgLi4ucGFydHMsIG5ldyBVaW50OEFycmF5KGJpblBhZGRpbmcpXSk7XG59XG5cbi8qKiBXaGV0aGVyIGFueSB2ZXJ0ZXggdXNlcyB0aGUgZ2l2ZW4gc2xvdCBvZiBpdHMgc291cmNlIHRyaXBsZSAodGV4dHVyZSBvciBub3JtYWwpLiAqL1xuZnVuY3Rpb24gaGFzQW55KHNvdXJjZXM6IEludDMyQXJyYXksIHNsb3Q6IG51bWJlcik6IGJvb2xlYW4ge1xuICBmb3IgKGxldCBhdCA9IHNsb3Q7IGF0IDwgc291cmNlcy5sZW5ndGg7IGF0ICs9IDMpIHtcbiAgICBpZiAoc291cmNlc1thdF0gPj0gMCkge1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICB9XG4gIHJldHVybiBmYWxzZTtcbn1cbiJdfQ==