@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.
- package/README.md +24 -24
- package/esm2022/lib/components/csv-export/csv-export.component.mjs +3 -3
- package/esm2022/lib/components/loader/loader.component.mjs +3 -3
- package/esm2022/lib/components/menu-bar/avatar/avatar.component.mjs +1 -1
- package/esm2022/lib/components/menu-bar/menu-bar.component.mjs +3 -3
- package/esm2022/lib/components/menu-bar/navigation-bar/navigation-bar.component.mjs +3 -3
- package/esm2022/lib/components/modal-switch-visit/modal-switch-visit.component.mjs +3 -3
- package/esm2022/lib/components/search-bar/search-bar.component.mjs +3 -3
- package/esm2022/lib/components/splat-viewer/splat-viewer.component.mjs +361 -0
- package/esm2022/lib/components/support-modal/support-modal.component.mjs +3 -3
- package/esm2022/lib/config.mjs +1 -1
- package/esm2022/lib/helpers.service.mjs +1 -1
- package/esm2022/lib/matterport-extensions/nest-thermostat/CanvasImage.mjs +1 -1
- package/esm2022/lib/matterport-extensions/nest-thermostat/CanvasRenderer.mjs +1 -1
- package/esm2022/lib/matterport-extensions/nest-thermostat/NestThermostat.mjs +1 -1
- package/esm2022/lib/matterport-extensions/nest-thermostat/PlaneRenderer.mjs +1 -1
- package/esm2022/lib/matterport-extensions/scene-component/SceneComponent.mjs +1 -1
- package/esm2022/lib/matterport-extensions/security-camera/SecurityCamera.mjs +22 -22
- package/esm2022/lib/matterport-extensions/tv-player/TvPlayer.mjs +1 -1
- package/esm2022/lib/matterport-extensions/view-frustum-mesh/ViewFrustumMesh.mjs +22 -22
- package/esm2022/lib/mattertagData.mjs +1 -1
- package/esm2022/lib/ngx-smarterplan-core.module.mjs +9 -4
- package/esm2022/lib/ngx-smarterplan-core.service.mjs +1 -1
- package/esm2022/lib/pipes/duration-to-string.pipe.mjs +1 -1
- package/esm2022/lib/pipes/format-date-number-to-digits.pipe.mjs +1 -1
- package/esm2022/lib/pipes/hashtag-from-id.pipe.mjs +1 -1
- package/esm2022/lib/pipes/safe-url.pipe.mjs +1 -1
- package/esm2022/lib/pipes/time-date-to-local-string.pipe.mjs +1 -1
- package/esm2022/lib/pipes/username-from-id.pipe.mjs +1 -1
- package/esm2022/lib/services/amplify-cache.service.mjs +1 -1
- package/esm2022/lib/services/base-tab.service.mjs +1 -1
- package/esm2022/lib/services/baseVisibility.service.mjs +1 -1
- package/esm2022/lib/services/content.service.mjs +1 -1
- package/esm2022/lib/services/filter.service.mjs +1 -1
- package/esm2022/lib/services/intervention.service.mjs +1 -1
- package/esm2022/lib/services/locale.service.mjs +1 -1
- package/esm2022/lib/services/matterport-import.service.mjs +1 -1
- package/esm2022/lib/services/matterport-measurement.service.mjs +1 -1
- package/esm2022/lib/services/matterport-navigation.service.mjs +1 -1
- package/esm2022/lib/services/matterport-pointer.service.mjs +6 -6
- package/esm2022/lib/services/matterport-tag-copy.service.mjs +1 -1
- package/esm2022/lib/services/matterport-tag.service.mjs +12 -7
- package/esm2022/lib/services/matterport.service.mjs +17 -17
- package/esm2022/lib/services/models/affectation.service.mjs +1 -1
- package/esm2022/lib/services/models/base-object.service.mjs +1 -1
- package/esm2022/lib/services/models/capture.service.mjs +1 -1
- package/esm2022/lib/services/models/comment.service.mjs +1 -1
- package/esm2022/lib/services/models/domain.service.mjs +1 -1
- package/esm2022/lib/services/models/equipment.service.mjs +1 -1
- package/esm2022/lib/services/models/event.service.mjs +1 -1
- package/esm2022/lib/services/models/feature.service.mjs +1 -1
- package/esm2022/lib/services/models/hashtag.service.mjs +1 -1
- package/esm2022/lib/services/models/layer.service.mjs +1 -1
- package/esm2022/lib/services/models/measurement.service.mjs +1 -1
- package/esm2022/lib/services/models/mission.service.mjs +1 -1
- package/esm2022/lib/services/models/navigation.service.mjs +1 -1
- package/esm2022/lib/services/models/node.service.mjs +1 -1
- package/esm2022/lib/services/models/object3D.service.mjs +1 -1
- package/esm2022/lib/services/models/operation.service.mjs +1 -1
- package/esm2022/lib/services/models/organisation.service.mjs +1 -1
- package/esm2022/lib/services/models/plan.service.mjs +1 -1
- package/esm2022/lib/services/models/poi.service.mjs +27 -27
- package/esm2022/lib/services/models/profile.service.mjs +1 -1
- package/esm2022/lib/services/models/property.service.mjs +1 -1
- package/esm2022/lib/services/models/space.service.mjs +1 -1
- package/esm2022/lib/services/models/template.service.mjs +1 -1
- package/esm2022/lib/services/models/ticket.service.mjs +1 -1
- package/esm2022/lib/services/models/visit.service.mjs +1 -1
- package/esm2022/lib/services/models/zone.service.mjs +1 -1
- package/esm2022/lib/services/navigator.service.mjs +1 -1
- package/esm2022/lib/services/obj-to-glb.mjs +649 -0
- package/esm2022/lib/services/s3.service.mjs +43 -3
- package/esm2022/lib/services/search.service.mjs +1 -1
- package/esm2022/lib/services/support.service.mjs +1 -1
- package/esm2022/lib/services/sweep-locator.service.mjs +1 -1
- package/esm2022/lib/services/tag.service.mjs +16 -16
- package/esm2022/lib/services/threejs-import.service.mjs +6 -4
- package/esm2022/lib/services/threejs.service.mjs +867 -95
- package/esm2022/lib/services/user.service.mjs +1 -1
- package/esm2022/lib/services/utils/matterport-transform.util.mjs +1 -1
- package/esm2022/lib/services/validators.service.mjs +1 -1
- package/esm2022/lib/services/viewer.service.mjs +189 -7
- package/esm2022/lib/services/zone-drawer.service.mjs +1 -1
- package/esm2022/lib/services/zoneChange.service.mjs +1 -1
- package/esm2022/lib/tokens/matterport-sdk-key.token.mjs +1 -1
- package/esm2022/lib/validators/email.directive.mjs +1 -1
- package/esm2022/lib/validators/no-empty.directive.mjs +1 -1
- package/esm2022/lib/validators/number.directive.mjs +1 -1
- package/esm2022/lib/validators/text.directive.mjs +1 -1
- package/esm2022/public-api.mjs +3 -1
- package/fesm2022/smarterplan-ngx-smarterplan-core.mjs +2239 -233
- package/fesm2022/smarterplan-ngx-smarterplan-core.mjs.map +1 -1
- package/lib/components/splat-viewer/splat-viewer.component.d.ts +98 -0
- package/lib/ngx-smarterplan-core.module.d.ts +7 -6
- package/lib/services/matterport-tag.service.d.ts +5 -5
- package/lib/services/obj-to-glb.d.ts +66 -0
- package/lib/services/s3.service.d.ts +7 -0
- package/lib/services/threejs.service.d.ts +336 -16
- package/lib/services/viewer.service.d.ts +110 -8
- package/package.json +1 -1
- package/public-api.d.ts +2 -0
- package/src/assets/viewers/splat/chunk-BYLI4YBI.js +17037 -0
- package/src/assets/viewers/splat/chunk-LDV6YPMG.js +1 -0
- package/src/assets/viewers/splat/chunk-WZ5Z4TU3.js +105719 -0
- package/src/assets/viewers/splat/convert-4DRLH77X.js +1 -0
- package/src/assets/viewers/splat/convert.html +11 -0
- package/src/assets/viewers/splat/converter-SLBB5MHG.js +1 -0
- package/src/assets/viewers/splat/index.html +90 -0
- package/src/assets/viewers/splat/spz-DEYRea_v-QE6YSGIB.js +5292 -0
- package/src/assets/viewers/splat/viewer-W4X3FWQJ.js +2704 -0
- package/src/assets/viewers/splat/viewer.css +1096 -0
- package/src/assets/viewers/splat/webp.wasm +0 -0
- package/src/assets/viewers/splat/worker.mjs +1383 -0
- 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==
|