@pixiv/three-vrm-springbone 2.1.1 → 3.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/three-vrm-springbone.cjs +1135 -0
- package/lib/three-vrm-springbone.min.cjs +2 -0
- package/lib/three-vrm-springbone.module.js +1041 -1075
- package/lib/three-vrm-springbone.module.min.js +2 -2
- package/package.json +21 -20
- package/lib/three-vrm-springbone.js +0 -1175
- package/lib/three-vrm-springbone.min.js +0 -2
- package/ts3.4/types/VRMSpringBoneCollider.d.ts +0 -12
- package/ts3.4/types/VRMSpringBoneColliderGroup.d.ts +0 -14
- package/ts3.4/types/VRMSpringBoneColliderShape.d.ts +0 -21
- package/ts3.4/types/VRMSpringBoneColliderShapeCapsule.d.ts +0 -23
- package/ts3.4/types/VRMSpringBoneColliderShapeSphere.d.ts +0 -18
- package/ts3.4/types/VRMSpringBoneJoint.d.ts +0 -116
- package/ts3.4/types/VRMSpringBoneJointSettings.d.ts +0 -11
- package/ts3.4/types/VRMSpringBoneLoaderPlugin.d.ts +0 -34
- package/ts3.4/types/VRMSpringBoneLoaderPluginOptions.d.ts +0 -15
- package/ts3.4/types/VRMSpringBoneManager.d.ts +0 -47
- package/ts3.4/types/helpers/VRMSpringBoneColliderHelper.d.ts +0 -10
- package/ts3.4/types/helpers/VRMSpringBoneJointHelper.d.ts +0 -10
- package/ts3.4/types/helpers/index.d.ts +0 -2
- package/ts3.4/types/helpers/utils/ColliderShapeBufferGeometry.d.ts +0 -5
- package/ts3.4/types/helpers/utils/ColliderShapeCapsuleBufferGeometry.d.ts +0 -16
- package/ts3.4/types/helpers/utils/ColliderShapeSphereBufferGeometry.d.ts +0 -15
- package/ts3.4/types/helpers/utils/SpringBoneBufferGeometry.d.ts +0 -14
- package/ts3.4/types/index.d.ts +0 -10
- package/ts3.4/types/tests/VRMSpringBoneColliderShapeCapsule.test.d.ts +0 -1
- package/ts3.4/types/tests/VRMSpringBoneColliderShapeSphere.test.d.ts +0 -1
- package/ts3.4/types/tests/matchers/toBeCloseToArray.d.ts +0 -9
- package/ts3.4/types/tests/matchers/toBeCloseToVector3.d.ts +0 -10
- package/ts3.4/types/utils/Matrix4InverseCache.d.ts +0 -28
- package/ts3.4/types/utils/getWorldQuaternionLite.d.ts +0 -10
- package/ts3.4/types/utils/mat4InvertCompat.d.ts +0 -8
- package/ts3.4/types/utils/traverseAncestorsFromRoot.d.ts +0 -2
- package/ts3.4/types/utils/traverseChildrenUntilConditionMet.d.ts +0 -9
- package/types/tests/VRMSpringBoneColliderShapeCapsule.test.d.ts +0 -1
- package/types/tests/VRMSpringBoneColliderShapeSphere.test.d.ts +0 -1
- package/types/tests/matchers/toBeCloseToArray.d.ts +0 -9
- package/types/tests/matchers/toBeCloseToVector3.d.ts +0 -10
|
@@ -0,0 +1,1135 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* @pixiv/three-vrm-springbone v3.0.0-beta.0
|
|
3
|
+
* Spring bone module for @pixiv/three-vrm
|
|
4
|
+
*
|
|
5
|
+
* Copyright (c) 2019-2024 pixiv Inc.
|
|
6
|
+
* @pixiv/three-vrm-springbone is distributed under MIT License
|
|
7
|
+
* https://github.com/pixiv/three-vrm/blob/release/LICENSE
|
|
8
|
+
*/
|
|
9
|
+
"use strict";
|
|
10
|
+
var __create = Object.create;
|
|
11
|
+
var __defProp = Object.defineProperty;
|
|
12
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
13
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
14
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
15
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
16
|
+
var __export = (target, all) => {
|
|
17
|
+
for (var name in all)
|
|
18
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
19
|
+
};
|
|
20
|
+
var __copyProps = (to, from, except, desc) => {
|
|
21
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
22
|
+
for (let key of __getOwnPropNames(from))
|
|
23
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
24
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
25
|
+
}
|
|
26
|
+
return to;
|
|
27
|
+
};
|
|
28
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
29
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
30
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
31
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
32
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
33
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
34
|
+
mod
|
|
35
|
+
));
|
|
36
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
37
|
+
var __async = (__this, __arguments, generator) => {
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
var fulfilled = (value) => {
|
|
40
|
+
try {
|
|
41
|
+
step(generator.next(value));
|
|
42
|
+
} catch (e) {
|
|
43
|
+
reject(e);
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
var rejected = (value) => {
|
|
47
|
+
try {
|
|
48
|
+
step(generator.throw(value));
|
|
49
|
+
} catch (e) {
|
|
50
|
+
reject(e);
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
54
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
55
|
+
});
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// src/index.ts
|
|
59
|
+
var src_exports = {};
|
|
60
|
+
__export(src_exports, {
|
|
61
|
+
VRMSpringBoneCollider: () => VRMSpringBoneCollider,
|
|
62
|
+
VRMSpringBoneColliderHelper: () => VRMSpringBoneColliderHelper,
|
|
63
|
+
VRMSpringBoneColliderShape: () => VRMSpringBoneColliderShape,
|
|
64
|
+
VRMSpringBoneColliderShapeCapsule: () => VRMSpringBoneColliderShapeCapsule,
|
|
65
|
+
VRMSpringBoneColliderShapeSphere: () => VRMSpringBoneColliderShapeSphere,
|
|
66
|
+
VRMSpringBoneJoint: () => VRMSpringBoneJoint,
|
|
67
|
+
VRMSpringBoneJointHelper: () => VRMSpringBoneJointHelper,
|
|
68
|
+
VRMSpringBoneLoaderPlugin: () => VRMSpringBoneLoaderPlugin,
|
|
69
|
+
VRMSpringBoneManager: () => VRMSpringBoneManager
|
|
70
|
+
});
|
|
71
|
+
module.exports = __toCommonJS(src_exports);
|
|
72
|
+
|
|
73
|
+
// src/helpers/VRMSpringBoneColliderHelper.ts
|
|
74
|
+
var THREE5 = __toESM(require("three"), 1);
|
|
75
|
+
|
|
76
|
+
// src/VRMSpringBoneColliderShapeCapsule.ts
|
|
77
|
+
var THREE = __toESM(require("three"), 1);
|
|
78
|
+
|
|
79
|
+
// src/VRMSpringBoneColliderShape.ts
|
|
80
|
+
var VRMSpringBoneColliderShape = class {
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
// src/VRMSpringBoneColliderShapeCapsule.ts
|
|
84
|
+
var _v3A = new THREE.Vector3();
|
|
85
|
+
var _v3B = new THREE.Vector3();
|
|
86
|
+
var VRMSpringBoneColliderShapeCapsule = class extends VRMSpringBoneColliderShape {
|
|
87
|
+
get type() {
|
|
88
|
+
return "capsule";
|
|
89
|
+
}
|
|
90
|
+
constructor(params) {
|
|
91
|
+
var _a, _b, _c;
|
|
92
|
+
super();
|
|
93
|
+
this.offset = (_a = params == null ? void 0 : params.offset) != null ? _a : new THREE.Vector3(0, 0, 0);
|
|
94
|
+
this.tail = (_b = params == null ? void 0 : params.tail) != null ? _b : new THREE.Vector3(0, 0, 0);
|
|
95
|
+
this.radius = (_c = params == null ? void 0 : params.radius) != null ? _c : 0;
|
|
96
|
+
}
|
|
97
|
+
calculateCollision(colliderMatrix, objectPosition, objectRadius, target) {
|
|
98
|
+
_v3A.copy(this.offset).applyMatrix4(colliderMatrix);
|
|
99
|
+
_v3B.copy(this.tail).applyMatrix4(colliderMatrix);
|
|
100
|
+
_v3B.sub(_v3A);
|
|
101
|
+
const lengthSqCapsule = _v3B.lengthSq();
|
|
102
|
+
target.copy(objectPosition).sub(_v3A);
|
|
103
|
+
const dot = _v3B.dot(target);
|
|
104
|
+
if (dot <= 0) {
|
|
105
|
+
} else if (lengthSqCapsule <= dot) {
|
|
106
|
+
target.sub(_v3B);
|
|
107
|
+
} else {
|
|
108
|
+
_v3B.multiplyScalar(dot / lengthSqCapsule);
|
|
109
|
+
target.sub(_v3B);
|
|
110
|
+
}
|
|
111
|
+
const radius = objectRadius + this.radius;
|
|
112
|
+
const distance = target.length() - radius;
|
|
113
|
+
target.normalize();
|
|
114
|
+
return distance;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
// src/VRMSpringBoneColliderShapeSphere.ts
|
|
119
|
+
var THREE2 = __toESM(require("three"), 1);
|
|
120
|
+
var VRMSpringBoneColliderShapeSphere = class extends VRMSpringBoneColliderShape {
|
|
121
|
+
get type() {
|
|
122
|
+
return "sphere";
|
|
123
|
+
}
|
|
124
|
+
constructor(params) {
|
|
125
|
+
var _a, _b;
|
|
126
|
+
super();
|
|
127
|
+
this.offset = (_a = params == null ? void 0 : params.offset) != null ? _a : new THREE2.Vector3(0, 0, 0);
|
|
128
|
+
this.radius = (_b = params == null ? void 0 : params.radius) != null ? _b : 0;
|
|
129
|
+
}
|
|
130
|
+
calculateCollision(colliderMatrix, objectPosition, objectRadius, target) {
|
|
131
|
+
target.copy(this.offset).applyMatrix4(colliderMatrix);
|
|
132
|
+
target.negate().add(objectPosition);
|
|
133
|
+
const radius = objectRadius + this.radius;
|
|
134
|
+
const distance = target.length() - radius;
|
|
135
|
+
target.normalize();
|
|
136
|
+
return distance;
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
// src/helpers/utils/ColliderShapeCapsuleBufferGeometry.ts
|
|
141
|
+
var THREE3 = __toESM(require("three"), 1);
|
|
142
|
+
var _v3A2 = new THREE3.Vector3();
|
|
143
|
+
var ColliderShapeCapsuleBufferGeometry = class extends THREE3.BufferGeometry {
|
|
144
|
+
constructor(shape) {
|
|
145
|
+
super();
|
|
146
|
+
this.worldScale = 1;
|
|
147
|
+
this._currentRadius = 0;
|
|
148
|
+
this._currentOffset = new THREE3.Vector3();
|
|
149
|
+
this._currentTail = new THREE3.Vector3();
|
|
150
|
+
this._shape = shape;
|
|
151
|
+
this._attrPos = new THREE3.BufferAttribute(new Float32Array(396), 3);
|
|
152
|
+
this.setAttribute("position", this._attrPos);
|
|
153
|
+
this._attrIndex = new THREE3.BufferAttribute(new Uint16Array(264), 1);
|
|
154
|
+
this.setIndex(this._attrIndex);
|
|
155
|
+
this._buildIndex();
|
|
156
|
+
this.update();
|
|
157
|
+
}
|
|
158
|
+
update() {
|
|
159
|
+
let shouldUpdateGeometry = false;
|
|
160
|
+
const radius = this._shape.radius / this.worldScale;
|
|
161
|
+
if (this._currentRadius !== radius) {
|
|
162
|
+
this._currentRadius = radius;
|
|
163
|
+
shouldUpdateGeometry = true;
|
|
164
|
+
}
|
|
165
|
+
if (!this._currentOffset.equals(this._shape.offset)) {
|
|
166
|
+
this._currentOffset.copy(this._shape.offset);
|
|
167
|
+
shouldUpdateGeometry = true;
|
|
168
|
+
}
|
|
169
|
+
const tail = _v3A2.copy(this._shape.tail).divideScalar(this.worldScale);
|
|
170
|
+
if (this._currentTail.distanceToSquared(tail) > 1e-10) {
|
|
171
|
+
this._currentTail.copy(tail);
|
|
172
|
+
shouldUpdateGeometry = true;
|
|
173
|
+
}
|
|
174
|
+
if (shouldUpdateGeometry) {
|
|
175
|
+
this._buildPosition();
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
_buildPosition() {
|
|
179
|
+
_v3A2.copy(this._currentTail).sub(this._currentOffset);
|
|
180
|
+
const l = _v3A2.length() / this._currentRadius;
|
|
181
|
+
for (let i = 0; i <= 16; i++) {
|
|
182
|
+
const t = i / 16 * Math.PI;
|
|
183
|
+
this._attrPos.setXYZ(i, -Math.sin(t), -Math.cos(t), 0);
|
|
184
|
+
this._attrPos.setXYZ(17 + i, l + Math.sin(t), Math.cos(t), 0);
|
|
185
|
+
this._attrPos.setXYZ(34 + i, -Math.sin(t), 0, -Math.cos(t));
|
|
186
|
+
this._attrPos.setXYZ(51 + i, l + Math.sin(t), 0, Math.cos(t));
|
|
187
|
+
}
|
|
188
|
+
for (let i = 0; i < 32; i++) {
|
|
189
|
+
const t = i / 16 * Math.PI;
|
|
190
|
+
this._attrPos.setXYZ(68 + i, 0, Math.sin(t), Math.cos(t));
|
|
191
|
+
this._attrPos.setXYZ(100 + i, l, Math.sin(t), Math.cos(t));
|
|
192
|
+
}
|
|
193
|
+
const theta = Math.atan2(_v3A2.y, Math.sqrt(_v3A2.x * _v3A2.x + _v3A2.z * _v3A2.z));
|
|
194
|
+
const phi = -Math.atan2(_v3A2.z, _v3A2.x);
|
|
195
|
+
this.rotateZ(theta);
|
|
196
|
+
this.rotateY(phi);
|
|
197
|
+
this.scale(this._currentRadius, this._currentRadius, this._currentRadius);
|
|
198
|
+
this.translate(this._currentOffset.x, this._currentOffset.y, this._currentOffset.z);
|
|
199
|
+
this._attrPos.needsUpdate = true;
|
|
200
|
+
}
|
|
201
|
+
_buildIndex() {
|
|
202
|
+
for (let i = 0; i < 34; i++) {
|
|
203
|
+
const i1 = (i + 1) % 34;
|
|
204
|
+
this._attrIndex.setXY(i * 2, i, i1);
|
|
205
|
+
this._attrIndex.setXY(68 + i * 2, 34 + i, 34 + i1);
|
|
206
|
+
}
|
|
207
|
+
for (let i = 0; i < 32; i++) {
|
|
208
|
+
const i1 = (i + 1) % 32;
|
|
209
|
+
this._attrIndex.setXY(136 + i * 2, 68 + i, 68 + i1);
|
|
210
|
+
this._attrIndex.setXY(200 + i * 2, 100 + i, 100 + i1);
|
|
211
|
+
}
|
|
212
|
+
this._attrIndex.needsUpdate = true;
|
|
213
|
+
}
|
|
214
|
+
};
|
|
215
|
+
|
|
216
|
+
// src/helpers/utils/ColliderShapeSphereBufferGeometry.ts
|
|
217
|
+
var THREE4 = __toESM(require("three"), 1);
|
|
218
|
+
var ColliderShapeSphereBufferGeometry = class extends THREE4.BufferGeometry {
|
|
219
|
+
constructor(shape) {
|
|
220
|
+
super();
|
|
221
|
+
this.worldScale = 1;
|
|
222
|
+
this._currentRadius = 0;
|
|
223
|
+
this._currentOffset = new THREE4.Vector3();
|
|
224
|
+
this._shape = shape;
|
|
225
|
+
this._attrPos = new THREE4.BufferAttribute(new Float32Array(32 * 3 * 3), 3);
|
|
226
|
+
this.setAttribute("position", this._attrPos);
|
|
227
|
+
this._attrIndex = new THREE4.BufferAttribute(new Uint16Array(64 * 3), 1);
|
|
228
|
+
this.setIndex(this._attrIndex);
|
|
229
|
+
this._buildIndex();
|
|
230
|
+
this.update();
|
|
231
|
+
}
|
|
232
|
+
update() {
|
|
233
|
+
let shouldUpdateGeometry = false;
|
|
234
|
+
const radius = this._shape.radius / this.worldScale;
|
|
235
|
+
if (this._currentRadius !== radius) {
|
|
236
|
+
this._currentRadius = radius;
|
|
237
|
+
shouldUpdateGeometry = true;
|
|
238
|
+
}
|
|
239
|
+
if (!this._currentOffset.equals(this._shape.offset)) {
|
|
240
|
+
this._currentOffset.copy(this._shape.offset);
|
|
241
|
+
shouldUpdateGeometry = true;
|
|
242
|
+
}
|
|
243
|
+
if (shouldUpdateGeometry) {
|
|
244
|
+
this._buildPosition();
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
_buildPosition() {
|
|
248
|
+
for (let i = 0; i < 32; i++) {
|
|
249
|
+
const t = i / 16 * Math.PI;
|
|
250
|
+
this._attrPos.setXYZ(i, Math.cos(t), Math.sin(t), 0);
|
|
251
|
+
this._attrPos.setXYZ(32 + i, 0, Math.cos(t), Math.sin(t));
|
|
252
|
+
this._attrPos.setXYZ(64 + i, Math.sin(t), 0, Math.cos(t));
|
|
253
|
+
}
|
|
254
|
+
this.scale(this._currentRadius, this._currentRadius, this._currentRadius);
|
|
255
|
+
this.translate(this._currentOffset.x, this._currentOffset.y, this._currentOffset.z);
|
|
256
|
+
this._attrPos.needsUpdate = true;
|
|
257
|
+
}
|
|
258
|
+
_buildIndex() {
|
|
259
|
+
for (let i = 0; i < 32; i++) {
|
|
260
|
+
const i1 = (i + 1) % 32;
|
|
261
|
+
this._attrIndex.setXY(i * 2, i, i1);
|
|
262
|
+
this._attrIndex.setXY(64 + i * 2, 32 + i, 32 + i1);
|
|
263
|
+
this._attrIndex.setXY(128 + i * 2, 64 + i, 64 + i1);
|
|
264
|
+
}
|
|
265
|
+
this._attrIndex.needsUpdate = true;
|
|
266
|
+
}
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
// src/helpers/VRMSpringBoneColliderHelper.ts
|
|
270
|
+
var _v3A3 = new THREE5.Vector3();
|
|
271
|
+
var VRMSpringBoneColliderHelper = class extends THREE5.Group {
|
|
272
|
+
constructor(collider) {
|
|
273
|
+
super();
|
|
274
|
+
this.matrixAutoUpdate = false;
|
|
275
|
+
this.collider = collider;
|
|
276
|
+
if (this.collider.shape instanceof VRMSpringBoneColliderShapeSphere) {
|
|
277
|
+
this._geometry = new ColliderShapeSphereBufferGeometry(this.collider.shape);
|
|
278
|
+
} else if (this.collider.shape instanceof VRMSpringBoneColliderShapeCapsule) {
|
|
279
|
+
this._geometry = new ColliderShapeCapsuleBufferGeometry(this.collider.shape);
|
|
280
|
+
} else {
|
|
281
|
+
throw new Error("VRMSpringBoneColliderHelper: Unknown collider shape type detected");
|
|
282
|
+
}
|
|
283
|
+
const material = new THREE5.LineBasicMaterial({
|
|
284
|
+
color: 16711935,
|
|
285
|
+
depthTest: false,
|
|
286
|
+
depthWrite: false
|
|
287
|
+
});
|
|
288
|
+
this._line = new THREE5.LineSegments(this._geometry, material);
|
|
289
|
+
this.add(this._line);
|
|
290
|
+
}
|
|
291
|
+
dispose() {
|
|
292
|
+
this._geometry.dispose();
|
|
293
|
+
}
|
|
294
|
+
updateMatrixWorld(force) {
|
|
295
|
+
this.collider.updateWorldMatrix(true, false);
|
|
296
|
+
this.matrix.copy(this.collider.matrixWorld);
|
|
297
|
+
const matrixWorldElements = this.matrix.elements;
|
|
298
|
+
this._geometry.worldScale = _v3A3.set(matrixWorldElements[0], matrixWorldElements[1], matrixWorldElements[2]).length();
|
|
299
|
+
this._geometry.update();
|
|
300
|
+
super.updateMatrixWorld(force);
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
// src/helpers/VRMSpringBoneJointHelper.ts
|
|
305
|
+
var THREE7 = __toESM(require("three"), 1);
|
|
306
|
+
|
|
307
|
+
// src/helpers/utils/SpringBoneBufferGeometry.ts
|
|
308
|
+
var THREE6 = __toESM(require("three"), 1);
|
|
309
|
+
var SpringBoneBufferGeometry = class extends THREE6.BufferGeometry {
|
|
310
|
+
constructor(springBone) {
|
|
311
|
+
super();
|
|
312
|
+
this.worldScale = 1;
|
|
313
|
+
this._currentRadius = 0;
|
|
314
|
+
this._currentTail = new THREE6.Vector3();
|
|
315
|
+
this._springBone = springBone;
|
|
316
|
+
this._attrPos = new THREE6.BufferAttribute(new Float32Array(294), 3);
|
|
317
|
+
this.setAttribute("position", this._attrPos);
|
|
318
|
+
this._attrIndex = new THREE6.BufferAttribute(new Uint16Array(194), 1);
|
|
319
|
+
this.setIndex(this._attrIndex);
|
|
320
|
+
this._buildIndex();
|
|
321
|
+
this.update();
|
|
322
|
+
}
|
|
323
|
+
update() {
|
|
324
|
+
let shouldUpdateGeometry = false;
|
|
325
|
+
const radius = this._springBone.settings.hitRadius / this.worldScale;
|
|
326
|
+
if (this._currentRadius !== radius) {
|
|
327
|
+
this._currentRadius = radius;
|
|
328
|
+
shouldUpdateGeometry = true;
|
|
329
|
+
}
|
|
330
|
+
if (!this._currentTail.equals(this._springBone.initialLocalChildPosition)) {
|
|
331
|
+
this._currentTail.copy(this._springBone.initialLocalChildPosition);
|
|
332
|
+
shouldUpdateGeometry = true;
|
|
333
|
+
}
|
|
334
|
+
if (shouldUpdateGeometry) {
|
|
335
|
+
this._buildPosition();
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
_buildPosition() {
|
|
339
|
+
for (let i = 0; i < 32; i++) {
|
|
340
|
+
const t = i / 16 * Math.PI;
|
|
341
|
+
this._attrPos.setXYZ(i, Math.cos(t), Math.sin(t), 0);
|
|
342
|
+
this._attrPos.setXYZ(32 + i, 0, Math.cos(t), Math.sin(t));
|
|
343
|
+
this._attrPos.setXYZ(64 + i, Math.sin(t), 0, Math.cos(t));
|
|
344
|
+
}
|
|
345
|
+
this.scale(this._currentRadius, this._currentRadius, this._currentRadius);
|
|
346
|
+
this.translate(this._currentTail.x, this._currentTail.y, this._currentTail.z);
|
|
347
|
+
this._attrPos.setXYZ(96, 0, 0, 0);
|
|
348
|
+
this._attrPos.setXYZ(97, this._currentTail.x, this._currentTail.y, this._currentTail.z);
|
|
349
|
+
this._attrPos.needsUpdate = true;
|
|
350
|
+
}
|
|
351
|
+
_buildIndex() {
|
|
352
|
+
for (let i = 0; i < 32; i++) {
|
|
353
|
+
const i1 = (i + 1) % 32;
|
|
354
|
+
this._attrIndex.setXY(i * 2, i, i1);
|
|
355
|
+
this._attrIndex.setXY(64 + i * 2, 32 + i, 32 + i1);
|
|
356
|
+
this._attrIndex.setXY(128 + i * 2, 64 + i, 64 + i1);
|
|
357
|
+
}
|
|
358
|
+
this._attrIndex.setXY(192, 96, 97);
|
|
359
|
+
this._attrIndex.needsUpdate = true;
|
|
360
|
+
}
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
// src/helpers/VRMSpringBoneJointHelper.ts
|
|
364
|
+
var _v3A4 = new THREE7.Vector3();
|
|
365
|
+
var VRMSpringBoneJointHelper = class extends THREE7.Group {
|
|
366
|
+
constructor(springBone) {
|
|
367
|
+
super();
|
|
368
|
+
this.matrixAutoUpdate = false;
|
|
369
|
+
this.springBone = springBone;
|
|
370
|
+
this._geometry = new SpringBoneBufferGeometry(this.springBone);
|
|
371
|
+
const material = new THREE7.LineBasicMaterial({
|
|
372
|
+
color: 16776960,
|
|
373
|
+
depthTest: false,
|
|
374
|
+
depthWrite: false
|
|
375
|
+
});
|
|
376
|
+
this._line = new THREE7.LineSegments(this._geometry, material);
|
|
377
|
+
this.add(this._line);
|
|
378
|
+
}
|
|
379
|
+
dispose() {
|
|
380
|
+
this._geometry.dispose();
|
|
381
|
+
}
|
|
382
|
+
updateMatrixWorld(force) {
|
|
383
|
+
this.springBone.bone.updateWorldMatrix(true, false);
|
|
384
|
+
this.matrix.copy(this.springBone.bone.matrixWorld);
|
|
385
|
+
const matrixWorldElements = this.matrix.elements;
|
|
386
|
+
this._geometry.worldScale = _v3A4.set(matrixWorldElements[0], matrixWorldElements[1], matrixWorldElements[2]).length();
|
|
387
|
+
this._geometry.update();
|
|
388
|
+
super.updateMatrixWorld(force);
|
|
389
|
+
}
|
|
390
|
+
};
|
|
391
|
+
|
|
392
|
+
// src/VRMSpringBoneCollider.ts
|
|
393
|
+
var THREE8 = __toESM(require("three"), 1);
|
|
394
|
+
var VRMSpringBoneCollider = class extends THREE8.Object3D {
|
|
395
|
+
constructor(shape) {
|
|
396
|
+
super();
|
|
397
|
+
this.shape = shape;
|
|
398
|
+
}
|
|
399
|
+
};
|
|
400
|
+
|
|
401
|
+
// src/VRMSpringBoneJoint.ts
|
|
402
|
+
var THREE11 = __toESM(require("three"), 1);
|
|
403
|
+
|
|
404
|
+
// src/utils/mat4InvertCompat.ts
|
|
405
|
+
var THREE9 = __toESM(require("three"), 1);
|
|
406
|
+
var _matA = new THREE9.Matrix4();
|
|
407
|
+
function mat4InvertCompat(target) {
|
|
408
|
+
if (target.invert) {
|
|
409
|
+
target.invert();
|
|
410
|
+
} else {
|
|
411
|
+
target.getInverse(_matA.copy(target));
|
|
412
|
+
}
|
|
413
|
+
return target;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// src/utils/Matrix4InverseCache.ts
|
|
417
|
+
var THREE10 = __toESM(require("three"), 1);
|
|
418
|
+
var Matrix4InverseCache = class {
|
|
419
|
+
constructor(matrix) {
|
|
420
|
+
/**
|
|
421
|
+
* A cache of inverse of current matrix.
|
|
422
|
+
*/
|
|
423
|
+
this._inverseCache = new THREE10.Matrix4();
|
|
424
|
+
/**
|
|
425
|
+
* A flag that makes it want to recalculate its {@link _inverseCache}.
|
|
426
|
+
* Will be set `true` when `elements` are mutated and be used in `getInverse`.
|
|
427
|
+
*/
|
|
428
|
+
this._shouldUpdateInverse = true;
|
|
429
|
+
this.matrix = matrix;
|
|
430
|
+
const handler = {
|
|
431
|
+
set: (obj, prop, newVal) => {
|
|
432
|
+
this._shouldUpdateInverse = true;
|
|
433
|
+
obj[prop] = newVal;
|
|
434
|
+
return true;
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
this._originalElements = matrix.elements;
|
|
438
|
+
matrix.elements = new Proxy(matrix.elements, handler);
|
|
439
|
+
}
|
|
440
|
+
/**
|
|
441
|
+
* Inverse of given matrix.
|
|
442
|
+
* Note that it will return its internal private instance.
|
|
443
|
+
* Make sure copying this before mutate this.
|
|
444
|
+
*/
|
|
445
|
+
get inverse() {
|
|
446
|
+
if (this._shouldUpdateInverse) {
|
|
447
|
+
this._inverseCache.copy(this.matrix);
|
|
448
|
+
mat4InvertCompat(this._inverseCache);
|
|
449
|
+
this._shouldUpdateInverse = false;
|
|
450
|
+
}
|
|
451
|
+
return this._inverseCache;
|
|
452
|
+
}
|
|
453
|
+
revert() {
|
|
454
|
+
this.matrix.elements = this._originalElements;
|
|
455
|
+
}
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
// src/VRMSpringBoneJoint.ts
|
|
459
|
+
var IDENTITY_MATRIX4 = new THREE11.Matrix4();
|
|
460
|
+
var _v3A5 = new THREE11.Vector3();
|
|
461
|
+
var _v3B2 = new THREE11.Vector3();
|
|
462
|
+
var _v3C = new THREE11.Vector3();
|
|
463
|
+
var _worldSpacePosition = new THREE11.Vector3();
|
|
464
|
+
var _centerSpacePosition = new THREE11.Vector3();
|
|
465
|
+
var _nextTail = new THREE11.Vector3();
|
|
466
|
+
var _quatA = new THREE11.Quaternion();
|
|
467
|
+
var _matA2 = new THREE11.Matrix4();
|
|
468
|
+
var _matB = new THREE11.Matrix4();
|
|
469
|
+
var VRMSpringBoneJoint = class {
|
|
470
|
+
/**
|
|
471
|
+
* Create a new VRMSpringBone.
|
|
472
|
+
*
|
|
473
|
+
* @param bone An Object3D that will be attached to this bone
|
|
474
|
+
* @param child An Object3D that will be used as a tail of this spring bone. It can be null when the spring bone is imported from VRM 0.0
|
|
475
|
+
* @param settings Several parameters related to behavior of the spring bone
|
|
476
|
+
* @param colliderGroups Collider groups that will be collided with this spring bone
|
|
477
|
+
*/
|
|
478
|
+
constructor(bone, child, settings = {}, colliderGroups = []) {
|
|
479
|
+
/**
|
|
480
|
+
* Current position of child tail, in center unit. Will be used for verlet integration.
|
|
481
|
+
*/
|
|
482
|
+
this._currentTail = new THREE11.Vector3();
|
|
483
|
+
/**
|
|
484
|
+
* Previous position of child tail, in center unit. Will be used for verlet integration.
|
|
485
|
+
*/
|
|
486
|
+
this._prevTail = new THREE11.Vector3();
|
|
487
|
+
/**
|
|
488
|
+
* Initial axis of the bone, in local unit.
|
|
489
|
+
*/
|
|
490
|
+
this._boneAxis = new THREE11.Vector3();
|
|
491
|
+
/**
|
|
492
|
+
* Length of the bone in world unit.
|
|
493
|
+
* Will be used for normalization in update loop, will be updated by {@link _calcWorldSpaceBoneLength}.
|
|
494
|
+
*
|
|
495
|
+
* It's same as local unit length unless there are scale transformations in the world space.
|
|
496
|
+
*/
|
|
497
|
+
this._worldSpaceBoneLength = 0;
|
|
498
|
+
/**
|
|
499
|
+
* This springbone will be calculated based on the space relative from this object.
|
|
500
|
+
* If this is `null`, springbone will be calculated in world space.
|
|
501
|
+
*/
|
|
502
|
+
this._center = null;
|
|
503
|
+
/**
|
|
504
|
+
* Initial state of the local matrix of the bone.
|
|
505
|
+
*/
|
|
506
|
+
this._initialLocalMatrix = new THREE11.Matrix4();
|
|
507
|
+
/**
|
|
508
|
+
* Initial state of the rotation of the bone.
|
|
509
|
+
*/
|
|
510
|
+
this._initialLocalRotation = new THREE11.Quaternion();
|
|
511
|
+
/**
|
|
512
|
+
* Initial state of the position of its child.
|
|
513
|
+
*/
|
|
514
|
+
this._initialLocalChildPosition = new THREE11.Vector3();
|
|
515
|
+
var _a, _b, _c, _d, _e, _f;
|
|
516
|
+
this.bone = bone;
|
|
517
|
+
this.bone.matrixAutoUpdate = false;
|
|
518
|
+
this.child = child;
|
|
519
|
+
this.settings = {
|
|
520
|
+
hitRadius: (_a = settings.hitRadius) != null ? _a : 0,
|
|
521
|
+
stiffness: (_b = settings.stiffness) != null ? _b : 1,
|
|
522
|
+
gravityPower: (_c = settings.gravityPower) != null ? _c : 0,
|
|
523
|
+
gravityDir: (_e = (_d = settings.gravityDir) == null ? void 0 : _d.clone()) != null ? _e : new THREE11.Vector3(0, -1, 0),
|
|
524
|
+
dragForce: (_f = settings.dragForce) != null ? _f : 0.4
|
|
525
|
+
};
|
|
526
|
+
this.colliderGroups = colliderGroups;
|
|
527
|
+
}
|
|
528
|
+
get center() {
|
|
529
|
+
return this._center;
|
|
530
|
+
}
|
|
531
|
+
set center(center) {
|
|
532
|
+
var _a;
|
|
533
|
+
if ((_a = this._center) == null ? void 0 : _a.userData.inverseCacheProxy) {
|
|
534
|
+
this._center.userData.inverseCacheProxy.revert();
|
|
535
|
+
delete this._center.userData.inverseCacheProxy;
|
|
536
|
+
}
|
|
537
|
+
this._center = center;
|
|
538
|
+
if (this._center) {
|
|
539
|
+
if (!this._center.userData.inverseCacheProxy) {
|
|
540
|
+
this._center.userData.inverseCacheProxy = new Matrix4InverseCache(this._center.matrixWorld);
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
get initialLocalChildPosition() {
|
|
545
|
+
return this._initialLocalChildPosition;
|
|
546
|
+
}
|
|
547
|
+
/**
|
|
548
|
+
* Returns the world matrix of its parent object.
|
|
549
|
+
* Note that it returns a reference to the matrix. Don't mutate this directly!
|
|
550
|
+
*/
|
|
551
|
+
get _parentMatrixWorld() {
|
|
552
|
+
return this.bone.parent ? this.bone.parent.matrixWorld : IDENTITY_MATRIX4;
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Set the initial state of this spring bone.
|
|
556
|
+
* You might want to call {@link VRMSpringBoneManager.setInitState} instead.
|
|
557
|
+
*/
|
|
558
|
+
setInitState() {
|
|
559
|
+
this._initialLocalMatrix.copy(this.bone.matrix);
|
|
560
|
+
this._initialLocalRotation.copy(this.bone.quaternion);
|
|
561
|
+
if (this.child) {
|
|
562
|
+
this._initialLocalChildPosition.copy(this.child.position);
|
|
563
|
+
} else {
|
|
564
|
+
this._initialLocalChildPosition.copy(this.bone.position).normalize().multiplyScalar(0.07);
|
|
565
|
+
}
|
|
566
|
+
const matrixWorldToCenter = this._getMatrixWorldToCenter(_matA2);
|
|
567
|
+
this.bone.localToWorld(this._currentTail.copy(this._initialLocalChildPosition)).applyMatrix4(matrixWorldToCenter);
|
|
568
|
+
this._prevTail.copy(this._currentTail);
|
|
569
|
+
this._boneAxis.copy(this._initialLocalChildPosition).normalize();
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Reset the state of this bone.
|
|
573
|
+
* You might want to call [[VRMSpringBoneManager.reset]] instead.
|
|
574
|
+
*/
|
|
575
|
+
reset() {
|
|
576
|
+
this.bone.quaternion.copy(this._initialLocalRotation);
|
|
577
|
+
this.bone.updateMatrix();
|
|
578
|
+
this.bone.matrixWorld.multiplyMatrices(this._parentMatrixWorld, this.bone.matrix);
|
|
579
|
+
const matrixWorldToCenter = this._getMatrixWorldToCenter(_matA2);
|
|
580
|
+
this.bone.localToWorld(this._currentTail.copy(this._initialLocalChildPosition)).applyMatrix4(matrixWorldToCenter);
|
|
581
|
+
this._prevTail.copy(this._currentTail);
|
|
582
|
+
}
|
|
583
|
+
/**
|
|
584
|
+
* Update the state of this bone.
|
|
585
|
+
* You might want to call [[VRMSpringBoneManager.update]] instead.
|
|
586
|
+
*
|
|
587
|
+
* @param delta deltaTime
|
|
588
|
+
*/
|
|
589
|
+
update(delta) {
|
|
590
|
+
if (delta <= 0) return;
|
|
591
|
+
this._calcWorldSpaceBoneLength();
|
|
592
|
+
_worldSpacePosition.setFromMatrixPosition(this.bone.matrixWorld);
|
|
593
|
+
let matrixWorldToCenter = this._getMatrixWorldToCenter(_matA2);
|
|
594
|
+
_centerSpacePosition.copy(_worldSpacePosition).applyMatrix4(matrixWorldToCenter);
|
|
595
|
+
const quatWorldToCenter = _quatA.setFromRotationMatrix(matrixWorldToCenter);
|
|
596
|
+
const centerSpaceParentMatrix = _matB.copy(matrixWorldToCenter).multiply(this._parentMatrixWorld);
|
|
597
|
+
const centerSpaceBoneAxis = _v3B2.copy(this._boneAxis).applyMatrix4(this._initialLocalMatrix).applyMatrix4(centerSpaceParentMatrix).sub(_centerSpacePosition).normalize();
|
|
598
|
+
const centerSpaceGravity = _v3C.copy(this.settings.gravityDir).applyQuaternion(quatWorldToCenter).normalize();
|
|
599
|
+
const matrixCenterToWorld = this._getMatrixCenterToWorld(_matA2);
|
|
600
|
+
_nextTail.copy(this._currentTail).add(
|
|
601
|
+
_v3A5.copy(this._currentTail).sub(this._prevTail).multiplyScalar(1 - this.settings.dragForce)
|
|
602
|
+
).add(_v3A5.copy(centerSpaceBoneAxis).multiplyScalar(this.settings.stiffness * delta)).add(_v3A5.copy(centerSpaceGravity).multiplyScalar(this.settings.gravityPower * delta)).applyMatrix4(matrixCenterToWorld);
|
|
603
|
+
_nextTail.sub(_worldSpacePosition).normalize().multiplyScalar(this._worldSpaceBoneLength).add(_worldSpacePosition);
|
|
604
|
+
this._collision(_nextTail);
|
|
605
|
+
matrixWorldToCenter = this._getMatrixWorldToCenter(_matA2);
|
|
606
|
+
this._prevTail.copy(this._currentTail);
|
|
607
|
+
this._currentTail.copy(_v3A5.copy(_nextTail).applyMatrix4(matrixWorldToCenter));
|
|
608
|
+
const worldSpaceInitialMatrixInv = mat4InvertCompat(
|
|
609
|
+
_matA2.copy(this._parentMatrixWorld).multiply(this._initialLocalMatrix)
|
|
610
|
+
);
|
|
611
|
+
const applyRotation = _quatA.setFromUnitVectors(
|
|
612
|
+
this._boneAxis,
|
|
613
|
+
_v3A5.copy(_nextTail).applyMatrix4(worldSpaceInitialMatrixInv).normalize()
|
|
614
|
+
);
|
|
615
|
+
this.bone.quaternion.copy(this._initialLocalRotation).multiply(applyRotation);
|
|
616
|
+
this.bone.updateMatrix();
|
|
617
|
+
this.bone.matrixWorld.multiplyMatrices(this._parentMatrixWorld, this.bone.matrix);
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* Do collision math against every colliders attached to this bone.
|
|
621
|
+
*
|
|
622
|
+
* @param tail The tail you want to process
|
|
623
|
+
*/
|
|
624
|
+
_collision(tail) {
|
|
625
|
+
this.colliderGroups.forEach((colliderGroup) => {
|
|
626
|
+
colliderGroup.colliders.forEach((collider) => {
|
|
627
|
+
const dist = collider.shape.calculateCollision(collider.matrixWorld, tail, this.settings.hitRadius, _v3A5);
|
|
628
|
+
if (dist < 0) {
|
|
629
|
+
tail.add(_v3A5.multiplyScalar(-dist));
|
|
630
|
+
tail.sub(_worldSpacePosition).normalize().multiplyScalar(this._worldSpaceBoneLength).add(_worldSpacePosition);
|
|
631
|
+
}
|
|
632
|
+
});
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
/**
|
|
636
|
+
* Calculate the {@link _worldSpaceBoneLength}.
|
|
637
|
+
* Intended to be used in {@link update}.
|
|
638
|
+
*/
|
|
639
|
+
_calcWorldSpaceBoneLength() {
|
|
640
|
+
_v3A5.setFromMatrixPosition(this.bone.matrixWorld);
|
|
641
|
+
if (this.child) {
|
|
642
|
+
_v3B2.setFromMatrixPosition(this.child.matrixWorld);
|
|
643
|
+
} else {
|
|
644
|
+
_v3B2.copy(this._initialLocalChildPosition);
|
|
645
|
+
_v3B2.applyMatrix4(this.bone.matrixWorld);
|
|
646
|
+
}
|
|
647
|
+
this._worldSpaceBoneLength = _v3A5.sub(_v3B2).length();
|
|
648
|
+
}
|
|
649
|
+
/**
|
|
650
|
+
* Create a matrix that converts center space into world space.
|
|
651
|
+
* @param target Target matrix
|
|
652
|
+
*/
|
|
653
|
+
_getMatrixCenterToWorld(target) {
|
|
654
|
+
if (this._center) {
|
|
655
|
+
target.copy(this._center.matrixWorld);
|
|
656
|
+
} else {
|
|
657
|
+
target.identity();
|
|
658
|
+
}
|
|
659
|
+
return target;
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Create a matrix that converts world space into center space.
|
|
663
|
+
* @param target Target matrix
|
|
664
|
+
*/
|
|
665
|
+
_getMatrixWorldToCenter(target) {
|
|
666
|
+
if (this._center) {
|
|
667
|
+
target.copy(this._center.userData.inverseCacheProxy.inverse);
|
|
668
|
+
} else {
|
|
669
|
+
target.identity();
|
|
670
|
+
}
|
|
671
|
+
return target;
|
|
672
|
+
}
|
|
673
|
+
};
|
|
674
|
+
|
|
675
|
+
// src/VRMSpringBoneLoaderPlugin.ts
|
|
676
|
+
var THREE12 = __toESM(require("three"), 1);
|
|
677
|
+
|
|
678
|
+
// src/utils/traverseAncestorsFromRoot.ts
|
|
679
|
+
function traverseAncestorsFromRoot(object, callback) {
|
|
680
|
+
const ancestors = [];
|
|
681
|
+
let head = object;
|
|
682
|
+
while (head !== null) {
|
|
683
|
+
ancestors.unshift(head);
|
|
684
|
+
head = head.parent;
|
|
685
|
+
}
|
|
686
|
+
ancestors.forEach((ancestor) => {
|
|
687
|
+
callback(ancestor);
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// src/utils/traverseChildrenUntilConditionMet.ts
|
|
692
|
+
function traverseChildrenUntilConditionMet(object, callback) {
|
|
693
|
+
object.children.forEach((child) => {
|
|
694
|
+
const result = callback(child);
|
|
695
|
+
if (!result) {
|
|
696
|
+
traverseChildrenUntilConditionMet(child, callback);
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// src/VRMSpringBoneManager.ts
|
|
702
|
+
var VRMSpringBoneManager = class {
|
|
703
|
+
constructor() {
|
|
704
|
+
this._joints = /* @__PURE__ */ new Set();
|
|
705
|
+
this._objectSpringBonesMap = /* @__PURE__ */ new Map();
|
|
706
|
+
}
|
|
707
|
+
get joints() {
|
|
708
|
+
return this._joints;
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* @deprecated Use {@link joints} instead.
|
|
712
|
+
*/
|
|
713
|
+
get springBones() {
|
|
714
|
+
console.warn("VRMSpringBoneManager: springBones is deprecated. use joints instead.");
|
|
715
|
+
return this._joints;
|
|
716
|
+
}
|
|
717
|
+
get colliderGroups() {
|
|
718
|
+
const set = /* @__PURE__ */ new Set();
|
|
719
|
+
this._joints.forEach((springBone) => {
|
|
720
|
+
springBone.colliderGroups.forEach((colliderGroup) => {
|
|
721
|
+
set.add(colliderGroup);
|
|
722
|
+
});
|
|
723
|
+
});
|
|
724
|
+
return Array.from(set);
|
|
725
|
+
}
|
|
726
|
+
get colliders() {
|
|
727
|
+
const set = /* @__PURE__ */ new Set();
|
|
728
|
+
this.colliderGroups.forEach((colliderGroup) => {
|
|
729
|
+
colliderGroup.colliders.forEach((collider) => {
|
|
730
|
+
set.add(collider);
|
|
731
|
+
});
|
|
732
|
+
});
|
|
733
|
+
return Array.from(set);
|
|
734
|
+
}
|
|
735
|
+
addJoint(joint) {
|
|
736
|
+
this._joints.add(joint);
|
|
737
|
+
let objectSet = this._objectSpringBonesMap.get(joint.bone);
|
|
738
|
+
if (objectSet == null) {
|
|
739
|
+
objectSet = /* @__PURE__ */ new Set();
|
|
740
|
+
this._objectSpringBonesMap.set(joint.bone, objectSet);
|
|
741
|
+
}
|
|
742
|
+
objectSet.add(joint);
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* @deprecated Use {@link addJoint} instead.
|
|
746
|
+
*/
|
|
747
|
+
addSpringBone(joint) {
|
|
748
|
+
console.warn("VRMSpringBoneManager: addSpringBone() is deprecated. use addJoint() instead.");
|
|
749
|
+
this.addJoint(joint);
|
|
750
|
+
}
|
|
751
|
+
deleteJoint(joint) {
|
|
752
|
+
this._joints.delete(joint);
|
|
753
|
+
const objectSet = this._objectSpringBonesMap.get(joint.bone);
|
|
754
|
+
objectSet.delete(joint);
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* @deprecated Use {@link deleteJoint} instead.
|
|
758
|
+
*/
|
|
759
|
+
deleteSpringBone(joint) {
|
|
760
|
+
console.warn("VRMSpringBoneManager: deleteSpringBone() is deprecated. use deleteJoint() instead.");
|
|
761
|
+
this.deleteJoint(joint);
|
|
762
|
+
}
|
|
763
|
+
setInitState() {
|
|
764
|
+
const springBonesTried = /* @__PURE__ */ new Set();
|
|
765
|
+
const springBonesDone = /* @__PURE__ */ new Set();
|
|
766
|
+
const objectUpdated = /* @__PURE__ */ new Set();
|
|
767
|
+
for (const springBone of this._joints) {
|
|
768
|
+
this._processSpringBone(
|
|
769
|
+
springBone,
|
|
770
|
+
springBonesTried,
|
|
771
|
+
springBonesDone,
|
|
772
|
+
objectUpdated,
|
|
773
|
+
(springBone2) => springBone2.setInitState()
|
|
774
|
+
);
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
reset() {
|
|
778
|
+
const springBonesTried = /* @__PURE__ */ new Set();
|
|
779
|
+
const springBonesDone = /* @__PURE__ */ new Set();
|
|
780
|
+
const objectUpdated = /* @__PURE__ */ new Set();
|
|
781
|
+
for (const springBone of this._joints) {
|
|
782
|
+
this._processSpringBone(
|
|
783
|
+
springBone,
|
|
784
|
+
springBonesTried,
|
|
785
|
+
springBonesDone,
|
|
786
|
+
objectUpdated,
|
|
787
|
+
(springBone2) => springBone2.reset()
|
|
788
|
+
);
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
update(delta) {
|
|
792
|
+
const springBonesTried = /* @__PURE__ */ new Set();
|
|
793
|
+
const springBonesDone = /* @__PURE__ */ new Set();
|
|
794
|
+
const objectUpdated = /* @__PURE__ */ new Set();
|
|
795
|
+
for (const springBone of this._joints) {
|
|
796
|
+
this._processSpringBone(
|
|
797
|
+
springBone,
|
|
798
|
+
springBonesTried,
|
|
799
|
+
springBonesDone,
|
|
800
|
+
objectUpdated,
|
|
801
|
+
(springBone2) => springBone2.update(delta)
|
|
802
|
+
);
|
|
803
|
+
traverseChildrenUntilConditionMet(springBone.bone, (object) => {
|
|
804
|
+
var _a, _b;
|
|
805
|
+
if (((_b = (_a = this._objectSpringBonesMap.get(object)) == null ? void 0 : _a.size) != null ? _b : 0) > 0) {
|
|
806
|
+
return true;
|
|
807
|
+
}
|
|
808
|
+
object.updateWorldMatrix(false, false);
|
|
809
|
+
return false;
|
|
810
|
+
});
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
/**
|
|
814
|
+
* Update a spring bone.
|
|
815
|
+
* If there are other spring bone that are dependant, it will try to update them recursively.
|
|
816
|
+
* It updates matrixWorld of all ancestors and myself.
|
|
817
|
+
* It might throw an error if there are circular dependencies.
|
|
818
|
+
*
|
|
819
|
+
* Intended to be used in {@link update} and {@link _processSpringBone} itself recursively.
|
|
820
|
+
*
|
|
821
|
+
* @param springBone A springBone you want to update
|
|
822
|
+
* @param springBonesTried Set of springBones that are already tried to be updated
|
|
823
|
+
* @param springBonesDone Set of springBones that are already up to date
|
|
824
|
+
* @param objectUpdated Set of object3D whose matrixWorld is updated
|
|
825
|
+
*/
|
|
826
|
+
_processSpringBone(springBone, springBonesTried, springBonesDone, objectUpdated, callback) {
|
|
827
|
+
if (springBonesDone.has(springBone)) {
|
|
828
|
+
return;
|
|
829
|
+
}
|
|
830
|
+
if (springBonesTried.has(springBone)) {
|
|
831
|
+
throw new Error("VRMSpringBoneManager: Circular dependency detected while updating springbones");
|
|
832
|
+
}
|
|
833
|
+
springBonesTried.add(springBone);
|
|
834
|
+
const depObjects = this._getDependencies(springBone);
|
|
835
|
+
for (const depObject of depObjects) {
|
|
836
|
+
traverseAncestorsFromRoot(depObject, (depObjectAncestor) => {
|
|
837
|
+
const objectSet = this._objectSpringBonesMap.get(depObjectAncestor);
|
|
838
|
+
if (objectSet) {
|
|
839
|
+
for (const depSpringBone of objectSet) {
|
|
840
|
+
this._processSpringBone(depSpringBone, springBonesTried, springBonesDone, objectUpdated, callback);
|
|
841
|
+
}
|
|
842
|
+
} else if (!objectUpdated.has(depObjectAncestor)) {
|
|
843
|
+
depObjectAncestor.updateWorldMatrix(false, false);
|
|
844
|
+
objectUpdated.add(depObjectAncestor);
|
|
845
|
+
}
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
springBone.bone.updateMatrix();
|
|
849
|
+
springBone.bone.updateWorldMatrix(false, false);
|
|
850
|
+
callback(springBone);
|
|
851
|
+
objectUpdated.add(springBone.bone);
|
|
852
|
+
springBonesDone.add(springBone);
|
|
853
|
+
}
|
|
854
|
+
/**
|
|
855
|
+
* Return a set of objects that are dependant of given spring bone.
|
|
856
|
+
* @param springBone A spring bone
|
|
857
|
+
* @return A set of objects that are dependant of given spring bone
|
|
858
|
+
*/
|
|
859
|
+
_getDependencies(springBone) {
|
|
860
|
+
const set = /* @__PURE__ */ new Set();
|
|
861
|
+
const parent = springBone.bone.parent;
|
|
862
|
+
if (parent) {
|
|
863
|
+
set.add(parent);
|
|
864
|
+
}
|
|
865
|
+
springBone.colliderGroups.forEach((colliderGroup) => {
|
|
866
|
+
colliderGroup.colliders.forEach((collider) => {
|
|
867
|
+
set.add(collider);
|
|
868
|
+
});
|
|
869
|
+
});
|
|
870
|
+
return set;
|
|
871
|
+
}
|
|
872
|
+
};
|
|
873
|
+
|
|
874
|
+
// src/VRMSpringBoneLoaderPlugin.ts
|
|
875
|
+
var POSSIBLE_SPEC_VERSIONS = /* @__PURE__ */ new Set(["1.0", "1.0-beta"]);
|
|
876
|
+
var _VRMSpringBoneLoaderPlugin = class _VRMSpringBoneLoaderPlugin {
|
|
877
|
+
get name() {
|
|
878
|
+
return _VRMSpringBoneLoaderPlugin.EXTENSION_NAME;
|
|
879
|
+
}
|
|
880
|
+
constructor(parser, options) {
|
|
881
|
+
this.parser = parser;
|
|
882
|
+
this.jointHelperRoot = options == null ? void 0 : options.jointHelperRoot;
|
|
883
|
+
this.colliderHelperRoot = options == null ? void 0 : options.colliderHelperRoot;
|
|
884
|
+
}
|
|
885
|
+
afterRoot(gltf) {
|
|
886
|
+
return __async(this, null, function* () {
|
|
887
|
+
gltf.userData.vrmSpringBoneManager = yield this._import(gltf);
|
|
888
|
+
});
|
|
889
|
+
}
|
|
890
|
+
/**
|
|
891
|
+
* Import spring bones from a GLTF and return a {@link VRMSpringBoneManager}.
|
|
892
|
+
* It might return `null` instead when it does not need to be created or something go wrong.
|
|
893
|
+
*
|
|
894
|
+
* @param gltf A parsed result of GLTF taken from GLTFLoader
|
|
895
|
+
*/
|
|
896
|
+
_import(gltf) {
|
|
897
|
+
return __async(this, null, function* () {
|
|
898
|
+
const v1Result = yield this._v1Import(gltf);
|
|
899
|
+
if (v1Result != null) {
|
|
900
|
+
return v1Result;
|
|
901
|
+
}
|
|
902
|
+
const v0Result = yield this._v0Import(gltf);
|
|
903
|
+
if (v0Result != null) {
|
|
904
|
+
return v0Result;
|
|
905
|
+
}
|
|
906
|
+
return null;
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
_v1Import(gltf) {
|
|
910
|
+
return __async(this, null, function* () {
|
|
911
|
+
var _a, _b, _c, _d, _e;
|
|
912
|
+
const json = gltf.parser.json;
|
|
913
|
+
const isSpringBoneUsed = ((_a = json.extensionsUsed) == null ? void 0 : _a.indexOf(_VRMSpringBoneLoaderPlugin.EXTENSION_NAME)) !== -1;
|
|
914
|
+
if (!isSpringBoneUsed) {
|
|
915
|
+
return null;
|
|
916
|
+
}
|
|
917
|
+
const manager = new VRMSpringBoneManager();
|
|
918
|
+
const threeNodes = yield gltf.parser.getDependencies("node");
|
|
919
|
+
const extension = (_b = json.extensions) == null ? void 0 : _b[_VRMSpringBoneLoaderPlugin.EXTENSION_NAME];
|
|
920
|
+
if (!extension) {
|
|
921
|
+
return null;
|
|
922
|
+
}
|
|
923
|
+
const specVersion = extension.specVersion;
|
|
924
|
+
if (!POSSIBLE_SPEC_VERSIONS.has(specVersion)) {
|
|
925
|
+
console.warn(
|
|
926
|
+
`VRMSpringBoneLoaderPlugin: Unknown ${_VRMSpringBoneLoaderPlugin.EXTENSION_NAME} specVersion "${specVersion}"`
|
|
927
|
+
);
|
|
928
|
+
return null;
|
|
929
|
+
}
|
|
930
|
+
const colliders = (_c = extension.colliders) == null ? void 0 : _c.map((schemaCollider, iCollider) => {
|
|
931
|
+
var _a2, _b2, _c2, _d2, _e2;
|
|
932
|
+
const node = threeNodes[schemaCollider.node];
|
|
933
|
+
const schemaShape = schemaCollider.shape;
|
|
934
|
+
if (schemaShape.sphere) {
|
|
935
|
+
return this._importSphereCollider(node, {
|
|
936
|
+
offset: new THREE12.Vector3().fromArray((_a2 = schemaShape.sphere.offset) != null ? _a2 : [0, 0, 0]),
|
|
937
|
+
radius: (_b2 = schemaShape.sphere.radius) != null ? _b2 : 0
|
|
938
|
+
});
|
|
939
|
+
} else if (schemaShape.capsule) {
|
|
940
|
+
return this._importCapsuleCollider(node, {
|
|
941
|
+
offset: new THREE12.Vector3().fromArray((_c2 = schemaShape.capsule.offset) != null ? _c2 : [0, 0, 0]),
|
|
942
|
+
radius: (_d2 = schemaShape.capsule.radius) != null ? _d2 : 0,
|
|
943
|
+
tail: new THREE12.Vector3().fromArray((_e2 = schemaShape.capsule.tail) != null ? _e2 : [0, 0, 0])
|
|
944
|
+
});
|
|
945
|
+
}
|
|
946
|
+
throw new Error(`VRMSpringBoneLoaderPlugin: The collider #${iCollider} has no valid shape`);
|
|
947
|
+
});
|
|
948
|
+
const colliderGroups = (_d = extension.colliderGroups) == null ? void 0 : _d.map(
|
|
949
|
+
(schemaColliderGroup, iColliderGroup) => {
|
|
950
|
+
var _a2;
|
|
951
|
+
const cols = ((_a2 = schemaColliderGroup.colliders) != null ? _a2 : []).map((iCollider) => {
|
|
952
|
+
const col = colliders == null ? void 0 : colliders[iCollider];
|
|
953
|
+
if (col == null) {
|
|
954
|
+
throw new Error(
|
|
955
|
+
`VRMSpringBoneLoaderPlugin: The colliderGroup #${iColliderGroup} attempted to use a collider #${iCollider} but not found`
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
return col;
|
|
959
|
+
});
|
|
960
|
+
return {
|
|
961
|
+
colliders: cols,
|
|
962
|
+
name: schemaColliderGroup.name
|
|
963
|
+
};
|
|
964
|
+
}
|
|
965
|
+
);
|
|
966
|
+
(_e = extension.springs) == null ? void 0 : _e.forEach((schemaSpring, iSpring) => {
|
|
967
|
+
var _a2;
|
|
968
|
+
const schemaJoints = schemaSpring.joints;
|
|
969
|
+
const colliderGroupsForSpring = (_a2 = schemaSpring.colliderGroups) == null ? void 0 : _a2.map((iColliderGroup) => {
|
|
970
|
+
const group = colliderGroups == null ? void 0 : colliderGroups[iColliderGroup];
|
|
971
|
+
if (group == null) {
|
|
972
|
+
throw new Error(
|
|
973
|
+
`VRMSpringBoneLoaderPlugin: The spring #${iSpring} attempted to use a colliderGroup ${iColliderGroup} but not found`
|
|
974
|
+
);
|
|
975
|
+
}
|
|
976
|
+
return group;
|
|
977
|
+
});
|
|
978
|
+
const center = schemaSpring.center != null ? threeNodes[schemaSpring.center] : void 0;
|
|
979
|
+
let prevSchemaJoint;
|
|
980
|
+
schemaJoints.forEach((schemaJoint) => {
|
|
981
|
+
if (prevSchemaJoint) {
|
|
982
|
+
const nodeIndex = prevSchemaJoint.node;
|
|
983
|
+
const node = threeNodes[nodeIndex];
|
|
984
|
+
const childIndex = schemaJoint.node;
|
|
985
|
+
const child = threeNodes[childIndex];
|
|
986
|
+
const setting = {
|
|
987
|
+
hitRadius: prevSchemaJoint.hitRadius,
|
|
988
|
+
dragForce: prevSchemaJoint.dragForce,
|
|
989
|
+
gravityPower: prevSchemaJoint.gravityPower,
|
|
990
|
+
stiffness: prevSchemaJoint.stiffness,
|
|
991
|
+
gravityDir: prevSchemaJoint.gravityDir != null ? new THREE12.Vector3().fromArray(prevSchemaJoint.gravityDir) : void 0
|
|
992
|
+
};
|
|
993
|
+
const joint = this._importJoint(node, child, setting, colliderGroupsForSpring);
|
|
994
|
+
if (center) {
|
|
995
|
+
joint.center = center;
|
|
996
|
+
}
|
|
997
|
+
manager.addJoint(joint);
|
|
998
|
+
}
|
|
999
|
+
prevSchemaJoint = schemaJoint;
|
|
1000
|
+
});
|
|
1001
|
+
});
|
|
1002
|
+
manager.setInitState();
|
|
1003
|
+
return manager;
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
_v0Import(gltf) {
|
|
1007
|
+
return __async(this, null, function* () {
|
|
1008
|
+
var _a, _b, _c;
|
|
1009
|
+
const json = gltf.parser.json;
|
|
1010
|
+
const isVRMUsed = ((_a = json.extensionsUsed) == null ? void 0 : _a.indexOf("VRM")) !== -1;
|
|
1011
|
+
if (!isVRMUsed) {
|
|
1012
|
+
return null;
|
|
1013
|
+
}
|
|
1014
|
+
const extension = (_b = json.extensions) == null ? void 0 : _b["VRM"];
|
|
1015
|
+
const schemaSecondaryAnimation = extension == null ? void 0 : extension.secondaryAnimation;
|
|
1016
|
+
if (!schemaSecondaryAnimation) {
|
|
1017
|
+
return null;
|
|
1018
|
+
}
|
|
1019
|
+
const schemaBoneGroups = schemaSecondaryAnimation == null ? void 0 : schemaSecondaryAnimation.boneGroups;
|
|
1020
|
+
if (!schemaBoneGroups) {
|
|
1021
|
+
return null;
|
|
1022
|
+
}
|
|
1023
|
+
const manager = new VRMSpringBoneManager();
|
|
1024
|
+
const threeNodes = yield gltf.parser.getDependencies("node");
|
|
1025
|
+
const colliderGroups = (_c = schemaSecondaryAnimation.colliderGroups) == null ? void 0 : _c.map(
|
|
1026
|
+
(schemaColliderGroup) => {
|
|
1027
|
+
var _a2;
|
|
1028
|
+
const node = threeNodes[schemaColliderGroup.node];
|
|
1029
|
+
const colliders = ((_a2 = schemaColliderGroup.colliders) != null ? _a2 : []).map((schemaCollider, iCollider) => {
|
|
1030
|
+
var _a3, _b2, _c2;
|
|
1031
|
+
const offset = new THREE12.Vector3(0, 0, 0);
|
|
1032
|
+
if (schemaCollider.offset) {
|
|
1033
|
+
offset.set(
|
|
1034
|
+
(_a3 = schemaCollider.offset.x) != null ? _a3 : 0,
|
|
1035
|
+
(_b2 = schemaCollider.offset.y) != null ? _b2 : 0,
|
|
1036
|
+
schemaCollider.offset.z ? -schemaCollider.offset.z : 0
|
|
1037
|
+
// z is opposite in VRM0.0
|
|
1038
|
+
);
|
|
1039
|
+
}
|
|
1040
|
+
return this._importSphereCollider(node, {
|
|
1041
|
+
offset,
|
|
1042
|
+
radius: (_c2 = schemaCollider.radius) != null ? _c2 : 0
|
|
1043
|
+
});
|
|
1044
|
+
});
|
|
1045
|
+
return { colliders };
|
|
1046
|
+
}
|
|
1047
|
+
);
|
|
1048
|
+
schemaBoneGroups == null ? void 0 : schemaBoneGroups.forEach((schemaBoneGroup, iBoneGroup) => {
|
|
1049
|
+
const rootIndices = schemaBoneGroup.bones;
|
|
1050
|
+
if (!rootIndices) {
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
rootIndices.forEach((rootIndex) => {
|
|
1054
|
+
var _a2, _b2, _c2, _d;
|
|
1055
|
+
const root = threeNodes[rootIndex];
|
|
1056
|
+
const gravityDir = new THREE12.Vector3();
|
|
1057
|
+
if (schemaBoneGroup.gravityDir) {
|
|
1058
|
+
gravityDir.set(
|
|
1059
|
+
(_a2 = schemaBoneGroup.gravityDir.x) != null ? _a2 : 0,
|
|
1060
|
+
(_b2 = schemaBoneGroup.gravityDir.y) != null ? _b2 : 0,
|
|
1061
|
+
(_c2 = schemaBoneGroup.gravityDir.z) != null ? _c2 : 0
|
|
1062
|
+
);
|
|
1063
|
+
} else {
|
|
1064
|
+
gravityDir.set(0, -1, 0);
|
|
1065
|
+
}
|
|
1066
|
+
const center = schemaBoneGroup.center != null ? threeNodes[schemaBoneGroup.center] : void 0;
|
|
1067
|
+
const setting = {
|
|
1068
|
+
hitRadius: schemaBoneGroup.hitRadius,
|
|
1069
|
+
dragForce: schemaBoneGroup.dragForce,
|
|
1070
|
+
gravityPower: schemaBoneGroup.gravityPower,
|
|
1071
|
+
stiffness: schemaBoneGroup.stiffiness,
|
|
1072
|
+
gravityDir
|
|
1073
|
+
};
|
|
1074
|
+
const colliderGroupsForSpring = (_d = schemaBoneGroup.colliderGroups) == null ? void 0 : _d.map((iColliderGroup) => {
|
|
1075
|
+
const group = colliderGroups == null ? void 0 : colliderGroups[iColliderGroup];
|
|
1076
|
+
if (group == null) {
|
|
1077
|
+
throw new Error(
|
|
1078
|
+
`VRMSpringBoneLoaderPlugin: The spring #${iBoneGroup} attempted to use a colliderGroup ${iColliderGroup} but not found`
|
|
1079
|
+
);
|
|
1080
|
+
}
|
|
1081
|
+
return group;
|
|
1082
|
+
});
|
|
1083
|
+
root.traverse((node) => {
|
|
1084
|
+
var _a3;
|
|
1085
|
+
const child = (_a3 = node.children[0]) != null ? _a3 : null;
|
|
1086
|
+
const joint = this._importJoint(node, child, setting, colliderGroupsForSpring);
|
|
1087
|
+
if (center) {
|
|
1088
|
+
joint.center = center;
|
|
1089
|
+
}
|
|
1090
|
+
manager.addJoint(joint);
|
|
1091
|
+
});
|
|
1092
|
+
});
|
|
1093
|
+
});
|
|
1094
|
+
gltf.scene.updateMatrixWorld();
|
|
1095
|
+
manager.setInitState();
|
|
1096
|
+
return manager;
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
_importJoint(node, child, setting, colliderGroupsForSpring) {
|
|
1100
|
+
const springBone = new VRMSpringBoneJoint(node, child, setting, colliderGroupsForSpring);
|
|
1101
|
+
if (this.jointHelperRoot) {
|
|
1102
|
+
const helper = new VRMSpringBoneJointHelper(springBone);
|
|
1103
|
+
this.jointHelperRoot.add(helper);
|
|
1104
|
+
helper.renderOrder = this.jointHelperRoot.renderOrder;
|
|
1105
|
+
}
|
|
1106
|
+
return springBone;
|
|
1107
|
+
}
|
|
1108
|
+
_importSphereCollider(destination, params) {
|
|
1109
|
+
const { offset, radius } = params;
|
|
1110
|
+
const shape = new VRMSpringBoneColliderShapeSphere({ offset, radius });
|
|
1111
|
+
const collider = new VRMSpringBoneCollider(shape);
|
|
1112
|
+
destination.add(collider);
|
|
1113
|
+
if (this.colliderHelperRoot) {
|
|
1114
|
+
const helper = new VRMSpringBoneColliderHelper(collider);
|
|
1115
|
+
this.colliderHelperRoot.add(helper);
|
|
1116
|
+
helper.renderOrder = this.colliderHelperRoot.renderOrder;
|
|
1117
|
+
}
|
|
1118
|
+
return collider;
|
|
1119
|
+
}
|
|
1120
|
+
_importCapsuleCollider(destination, params) {
|
|
1121
|
+
const { offset, radius, tail } = params;
|
|
1122
|
+
const shape = new VRMSpringBoneColliderShapeCapsule({ offset, radius, tail });
|
|
1123
|
+
const collider = new VRMSpringBoneCollider(shape);
|
|
1124
|
+
destination.add(collider);
|
|
1125
|
+
if (this.colliderHelperRoot) {
|
|
1126
|
+
const helper = new VRMSpringBoneColliderHelper(collider);
|
|
1127
|
+
this.colliderHelperRoot.add(helper);
|
|
1128
|
+
helper.renderOrder = this.colliderHelperRoot.renderOrder;
|
|
1129
|
+
}
|
|
1130
|
+
return collider;
|
|
1131
|
+
}
|
|
1132
|
+
};
|
|
1133
|
+
_VRMSpringBoneLoaderPlugin.EXTENSION_NAME = "VRMC_springBone";
|
|
1134
|
+
var VRMSpringBoneLoaderPlugin = _VRMSpringBoneLoaderPlugin;
|
|
1135
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIiwgIi4uL3NyYy9oZWxwZXJzL1ZSTVNwcmluZ0JvbmVDb2xsaWRlckhlbHBlci50cyIsICIuLi9zcmMvVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVDYXBzdWxlLnRzIiwgIi4uL3NyYy9WUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZS50cyIsICIuLi9zcmMvVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVTcGhlcmUudHMiLCAiLi4vc3JjL2hlbHBlcnMvdXRpbHMvQ29sbGlkZXJTaGFwZUNhcHN1bGVCdWZmZXJHZW9tZXRyeS50cyIsICIuLi9zcmMvaGVscGVycy91dGlscy9Db2xsaWRlclNoYXBlU3BoZXJlQnVmZmVyR2VvbWV0cnkudHMiLCAiLi4vc3JjL2hlbHBlcnMvVlJNU3ByaW5nQm9uZUpvaW50SGVscGVyLnRzIiwgIi4uL3NyYy9oZWxwZXJzL3V0aWxzL1NwcmluZ0JvbmVCdWZmZXJHZW9tZXRyeS50cyIsICIuLi9zcmMvVlJNU3ByaW5nQm9uZUNvbGxpZGVyLnRzIiwgIi4uL3NyYy9WUk1TcHJpbmdCb25lSm9pbnQudHMiLCAiLi4vc3JjL3V0aWxzL21hdDRJbnZlcnRDb21wYXQudHMiLCAiLi4vc3JjL3V0aWxzL01hdHJpeDRJbnZlcnNlQ2FjaGUudHMiLCAiLi4vc3JjL1ZSTVNwcmluZ0JvbmVMb2FkZXJQbHVnaW4udHMiLCAiLi4vc3JjL3V0aWxzL3RyYXZlcnNlQW5jZXN0b3JzRnJvbVJvb3QudHMiLCAiLi4vc3JjL3V0aWxzL3RyYXZlcnNlQ2hpbGRyZW5VbnRpbENvbmRpdGlvbk1ldC50cyIsICIuLi9zcmMvVlJNU3ByaW5nQm9uZU1hbmFnZXIudHMiXSwKICAic291cmNlc0NvbnRlbnQiOiBbImV4cG9ydCAqIGZyb20gJy4vaGVscGVycyc7XG5leHBvcnQgKiBmcm9tICcuL1ZSTVNwcmluZ0JvbmVDb2xsaWRlcic7XG5leHBvcnQgKiBmcm9tICcuL1ZSTVNwcmluZ0JvbmVDb2xsaWRlckdyb3VwJztcbmV4cG9ydCAqIGZyb20gJy4vVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGUnO1xuZXhwb3J0ICogZnJvbSAnLi9WUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZUNhcHN1bGUnO1xuZXhwb3J0ICogZnJvbSAnLi9WUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZVNwaGVyZSc7XG5leHBvcnQgKiBmcm9tICcuL1ZSTVNwcmluZ0JvbmVKb2ludCc7XG5leHBvcnQgKiBmcm9tICcuL1ZSTVNwcmluZ0JvbmVMb2FkZXJQbHVnaW4nO1xuZXhwb3J0ICogZnJvbSAnLi9WUk1TcHJpbmdCb25lTWFuYWdlcic7XG5leHBvcnQgKiBmcm9tICcuL1ZSTVNwcmluZ0JvbmVKb2ludFNldHRpbmdzJztcbiIsICJpbXBvcnQgKiBhcyBUSFJFRSBmcm9tICd0aHJlZSc7XG5pbXBvcnQgeyBWUk1TcHJpbmdCb25lQ29sbGlkZXIgfSBmcm9tICcuLi9WUk1TcHJpbmdCb25lQ29sbGlkZXInO1xuaW1wb3J0IHsgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVDYXBzdWxlIH0gZnJvbSAnLi4vVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVDYXBzdWxlJztcbmltcG9ydCB7IFZSTVNwcmluZ0JvbmVDb2xsaWRlclNoYXBlU3BoZXJlIH0gZnJvbSAnLi4vVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVTcGhlcmUnO1xuaW1wb3J0IHsgQ29sbGlkZXJTaGFwZUJ1ZmZlckdlb21ldHJ5IH0gZnJvbSAnLi91dGlscy9Db2xsaWRlclNoYXBlQnVmZmVyR2VvbWV0cnknO1xuaW1wb3J0IHsgQ29sbGlkZXJTaGFwZUNhcHN1bGVCdWZmZXJHZW9tZXRyeSB9IGZyb20gJy4vdXRpbHMvQ29sbGlkZXJTaGFwZUNhcHN1bGVCdWZmZXJHZW9tZXRyeSc7XG5pbXBvcnQgeyBDb2xsaWRlclNoYXBlU3BoZXJlQnVmZmVyR2VvbWV0cnkgfSBmcm9tICcuL3V0aWxzL0NvbGxpZGVyU2hhcGVTcGhlcmVCdWZmZXJHZW9tZXRyeSc7XG5cbmNvbnN0IF92M0EgPSBuZXcgVEhSRUUuVmVjdG9yMygpO1xuXG5leHBvcnQgY2xhc3MgVlJNU3ByaW5nQm9uZUNvbGxpZGVySGVscGVyIGV4dGVuZHMgVEhSRUUuR3JvdXAge1xuICBwdWJsaWMgcmVhZG9ubHkgY29sbGlkZXI6IFZSTVNwcmluZ0JvbmVDb2xsaWRlcjtcbiAgcHJpdmF0ZSByZWFkb25seSBfZ2VvbWV0cnk6IENvbGxpZGVyU2hhcGVCdWZmZXJHZW9tZXRyeTtcbiAgcHJpdmF0ZSByZWFkb25seSBfbGluZTogVEhSRUUuTGluZVNlZ21lbnRzO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3Rvcihjb2xsaWRlcjogVlJNU3ByaW5nQm9uZUNvbGxpZGVyKSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLm1hdHJpeEF1dG9VcGRhdGUgPSBmYWxzZTtcblxuICAgIHRoaXMuY29sbGlkZXIgPSBjb2xsaWRlcjtcblxuICAgIGlmICh0aGlzLmNvbGxpZGVyLnNoYXBlIGluc3RhbmNlb2YgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVTcGhlcmUpIHtcbiAgICAgIHRoaXMuX2dlb21ldHJ5ID0gbmV3IENvbGxpZGVyU2hhcGVTcGhlcmVCdWZmZXJHZW9tZXRyeSh0aGlzLmNvbGxpZGVyLnNoYXBlKTtcbiAgICB9IGVsc2UgaWYgKHRoaXMuY29sbGlkZXIuc2hhcGUgaW5zdGFuY2VvZiBWUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZUNhcHN1bGUpIHtcbiAgICAgIHRoaXMuX2dlb21ldHJ5ID0gbmV3IENvbGxpZGVyU2hhcGVDYXBzdWxlQnVmZmVyR2VvbWV0cnkodGhpcy5jb2xsaWRlci5zaGFwZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVlJNU3ByaW5nQm9uZUNvbGxpZGVySGVscGVyOiBVbmtub3duIGNvbGxpZGVyIHNoYXBlIHR5cGUgZGV0ZWN0ZWQnKTtcbiAgICB9XG5cbiAgICBjb25zdCBtYXRlcmlhbCA9IG5ldyBUSFJFRS5MaW5lQmFzaWNNYXRlcmlhbCh7XG4gICAgICBjb2xvcjogMHhmZjAwZmYsXG4gICAgICBkZXB0aFRlc3Q6IGZhbHNlLFxuICAgICAgZGVwdGhXcml0ZTogZmFsc2UsXG4gICAgfSk7XG5cbiAgICB0aGlzLl9saW5lID0gbmV3IFRIUkVFLkxpbmVTZWdtZW50cyh0aGlzLl9nZW9tZXRyeSwgbWF0ZXJpYWwpO1xuICAgIHRoaXMuYWRkKHRoaXMuX2xpbmUpO1xuICB9XG5cbiAgcHVibGljIGRpc3Bvc2UoKTogdm9pZCB7XG4gICAgdGhpcy5fZ2VvbWV0cnkuZGlzcG9zZSgpO1xuICB9XG5cbiAgcHVibGljIHVwZGF0ZU1hdHJpeFdvcmxkKGZvcmNlOiBib29sZWFuKTogdm9pZCB7XG4gICAgdGhpcy5jb2xsaWRlci51cGRhdGVXb3JsZE1hdHJpeCh0cnVlLCBmYWxzZSk7XG5cbiAgICB0aGlzLm1hdHJpeC5jb3B5KHRoaXMuY29sbGlkZXIubWF0cml4V29ybGQpO1xuXG4gICAgY29uc3QgbWF0cml4V29ybGRFbGVtZW50cyA9IHRoaXMubWF0cml4LmVsZW1lbnRzO1xuICAgIHRoaXMuX2dlb21ldHJ5LndvcmxkU2NhbGUgPSBfdjNBXG4gICAgICAuc2V0KG1hdHJpeFdvcmxkRWxlbWVudHNbMF0sIG1hdHJpeFdvcmxkRWxlbWVudHNbMV0sIG1hdHJpeFdvcmxkRWxlbWVudHNbMl0pXG4gICAgICAubGVuZ3RoKCk7IC8vIGNhbGN1bGF0ZSBzY2FsZSBvZiB4IGNvbXBvbmVudFxuXG4gICAgdGhpcy5fZ2VvbWV0cnkudXBkYXRlKCk7XG5cbiAgICBzdXBlci51cGRhdGVNYXRyaXhXb3JsZChmb3JjZSk7XG4gIH1cbn1cbiIsICJpbXBvcnQgKiBhcyBUSFJFRSBmcm9tICd0aHJlZSc7XG5pbXBvcnQgeyBWUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZSB9IGZyb20gJy4vVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGUnO1xuXG5jb25zdCBfdjNBID0gbmV3IFRIUkVFLlZlY3RvcjMoKTtcbmNvbnN0IF92M0IgPSBuZXcgVEhSRUUuVmVjdG9yMygpO1xuXG5leHBvcnQgY2xhc3MgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVDYXBzdWxlIGV4dGVuZHMgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGUge1xuICBwdWJsaWMgZ2V0IHR5cGUoKTogJ2NhcHN1bGUnIHtcbiAgICByZXR1cm4gJ2NhcHN1bGUnO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBvZmZzZXQgb2YgdGhlIGhlYWQgZnJvbSB0aGUgb3JpZ2luLlxuICAgKi9cbiAgcHVibGljIG9mZnNldDogVEhSRUUuVmVjdG9yMztcblxuICAvKipcbiAgICogVGhlIG9mZnNldCBvZiB0aGUgdGFpbCBmcm9tIHRoZSBvcmlnaW4uXG4gICAqL1xuICBwdWJsaWMgdGFpbDogVEhSRUUuVmVjdG9yMztcblxuICAvKipcbiAgICogVGhlIHJhZGl1cy5cbiAgICovXG4gIHB1YmxpYyByYWRpdXM6IG51bWJlcjtcblxuICBwdWJsaWMgY29uc3RydWN0b3IocGFyYW1zPzogeyByYWRpdXM/OiBudW1iZXI7IG9mZnNldD86IFRIUkVFLlZlY3RvcjM7IHRhaWw/OiBUSFJFRS5WZWN0b3IzIH0pIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5vZmZzZXQgPSBwYXJhbXM/Lm9mZnNldCA/PyBuZXcgVEhSRUUuVmVjdG9yMygwLjAsIDAuMCwgMC4wKTtcbiAgICB0aGlzLnRhaWwgPSBwYXJhbXM/LnRhaWwgPz8gbmV3IFRIUkVFLlZlY3RvcjMoMC4wLCAwLjAsIDAuMCk7XG4gICAgdGhpcy5yYWRpdXMgPSBwYXJhbXM/LnJhZGl1cyA/PyAwLjA7XG4gIH1cblxuICBwdWJsaWMgY2FsY3VsYXRlQ29sbGlzaW9uKFxuICAgIGNvbGxpZGVyTWF0cml4OiBUSFJFRS5NYXRyaXg0LFxuICAgIG9iamVjdFBvc2l0aW9uOiBUSFJFRS5WZWN0b3IzLFxuICAgIG9iamVjdFJhZGl1czogbnVtYmVyLFxuICAgIHRhcmdldDogVEhSRUUuVmVjdG9yMyxcbiAgKTogbnVtYmVyIHtcbiAgICBfdjNBLmNvcHkodGhpcy5vZmZzZXQpLmFwcGx5TWF0cml4NChjb2xsaWRlck1hdHJpeCk7IC8vIHRyYW5zZm9ybWVkIGhlYWRcbiAgICBfdjNCLmNvcHkodGhpcy50YWlsKS5hcHBseU1hdHJpeDQoY29sbGlkZXJNYXRyaXgpOyAvLyB0cmFuc2Zvcm1lZCB0YWlsXG4gICAgX3YzQi5zdWIoX3YzQSk7IC8vIGZyb20gaGVhZCB0byB0YWlsXG4gICAgY29uc3QgbGVuZ3RoU3FDYXBzdWxlID0gX3YzQi5sZW5ndGhTcSgpO1xuXG4gICAgdGFyZ2V0LmNvcHkob2JqZWN0UG9zaXRpb24pLnN1YihfdjNBKTsgLy8gZnJvbSBoZWFkIHRvIG9iamVjdFxuICAgIGNvbnN0IGRvdCA9IF92M0IuZG90KHRhcmdldCk7IC8vIGRvdCBwcm9kdWN0IG9mIG9mZnNldFRvVGFpbCBhbmQgb2Zmc2V0VG9PYmplY3RcblxuICAgIGlmIChkb3QgPD0gMC4wKSB7XG4gICAgICAvLyBpZiBvYmplY3QgaXMgbmVhciBmcm9tIHRoZSBoZWFkXG4gICAgICAvLyBkbyBub3RoaW5nLCB1c2UgdGhlIGN1cnJlbnQgdmFsdWUgZGlyZWN0bHlcbiAgICB9IGVsc2UgaWYgKGxlbmd0aFNxQ2Fwc3VsZSA8PSBkb3QpIHtcbiAgICAgIC8vIGlmIG9iamVjdCBpcyBuZWFyIGZyb20gdGhlIHRhaWxcbiAgICAgIHRhcmdldC5zdWIoX3YzQik7IC8vIGZyb20gdGFpbCB0byBvYmplY3RcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gaWYgb2JqZWN0IGlzIGJldHdlZW4gdHdvIGVuZHNcbiAgICAgIF92M0IubXVsdGlwbHlTY2FsYXIoZG90IC8gbGVuZ3RoU3FDYXBzdWxlKTsgLy8gZnJvbSBoZWFkIHRvIHRoZSBuZWFyZXN0IHBvaW50IG9mIHRoZSBzaGFmdFxuICAgICAgdGFyZ2V0LnN1YihfdjNCKTsgLy8gZnJvbSB0aGUgc2hhZnQgcG9pbnQgdG8gb2JqZWN0XG4gICAgfVxuXG4gICAgY29uc3QgcmFkaXVzID0gb2JqZWN0UmFkaXVzICsgdGhpcy5yYWRpdXM7XG4gICAgY29uc3QgZGlzdGFuY2UgPSB0YXJnZXQubGVuZ3RoKCkgLSByYWRpdXM7XG4gICAgdGFyZ2V0Lm5vcm1hbGl6ZSgpO1xuICAgIHJldHVybiBkaXN0YW5jZTtcbiAgfVxufVxuIiwgImltcG9ydCB0eXBlICogYXMgVEhSRUUgZnJvbSAndGhyZWUnO1xuXG4vKipcbiAqIFJlcHJlc2VudHMgYSBzaGFwZSBvZiBhIGNvbGxpZGVyLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGUge1xuICAvKipcbiAgICogVGhlIHR5cGUgb2YgdGhlIHNoYXBlLlxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IGdldCB0eXBlKCk6IHN0cmluZztcblxuICAvKipcbiAgICogQ2FsY3VsYXRlIGEgZGlzdGFuY2UgYW5kIGEgZGlyZWN0aW9uIGZyb20gdGhlIGNvbGxpZGVyIHRvIGEgdGFyZ2V0IG9iamVjdC5cbiAgICogSXQncyBoaXQgaWYgdGhlIGRpc3RhbmNlIGlzIG5lZ2F0aXZlLlxuICAgKiBUaGUgZGlyZWN0aW9uIHdpbGwgYmUgY29udGFpbmVkIGluIHRoZSBnaXZlbiB0YXJnZXQgdmVjdG9yLlxuICAgKlxuICAgKiBAcGFyYW0gY29sbGlkZXJNYXRyaXggQSBtYXRyaXggcmVwcmVzZW50cyB0aGUgdHJhbnNmb3JtIG9mIHRoZSBjb2xsaWRlclxuICAgKiBAcGFyYW0gb2JqZWN0UG9zaXRpb24gQSB2ZWN0b3IgcmVwcmVzZW50cyB0aGUgcG9zaXRpb24gb2YgdGhlIHRhcmdldCBvYmplY3RcbiAgICogQHBhcmFtIG9iamVjdFJhZGl1cyBUaGUgcmFkaXVzIG9mIHRoZSBvYmplY3RcbiAgICogQHBhcmFtIHRhcmdldCBUaGUgcmVzdWx0IGRpcmVjdGlvbiB3aWxsIGJlIGNvbnRhaW5lZCBpbiB0aGlzIHZlY3RvclxuICAgKi9cbiAgcHVibGljIGFic3RyYWN0IGNhbGN1bGF0ZUNvbGxpc2lvbihcbiAgICBjb2xsaWRlck1hdHJpeDogVEhSRUUuTWF0cml4NCxcbiAgICBvYmplY3RQb3NpdGlvbjogVEhSRUUuVmVjdG9yMyxcbiAgICBvYmplY3RSYWRpdXM6IG51bWJlcixcbiAgICB0YXJnZXQ6IFRIUkVFLlZlY3RvcjMsXG4gICk6IG51bWJlcjtcbn1cbiIsICJpbXBvcnQgKiBhcyBUSFJFRSBmcm9tICd0aHJlZSc7XG5pbXBvcnQgeyBWUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZSB9IGZyb20gJy4vVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGUnO1xuXG5leHBvcnQgY2xhc3MgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVTcGhlcmUgZXh0ZW5kcyBWUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZSB7XG4gIHB1YmxpYyBnZXQgdHlwZSgpOiAnc3BoZXJlJyB7XG4gICAgcmV0dXJuICdzcGhlcmUnO1xuICB9XG5cbiAgLyoqXG4gICAqIFRoZSBvZmZzZXQgZnJvbSB0aGUgb3JpZ2luLlxuICAgKi9cbiAgcHVibGljIG9mZnNldDogVEhSRUUuVmVjdG9yMztcblxuICAvKipcbiAgICogVGhlIHJhZGl1cy5cbiAgICovXG4gIHB1YmxpYyByYWRpdXM6IG51bWJlcjtcblxuICBwdWJsaWMgY29uc3RydWN0b3IocGFyYW1zPzogeyByYWRpdXM/OiBudW1iZXI7IG9mZnNldD86IFRIUkVFLlZlY3RvcjMgfSkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLm9mZnNldCA9IHBhcmFtcz8ub2Zmc2V0ID8/IG5ldyBUSFJFRS5WZWN0b3IzKDAuMCwgMC4wLCAwLjApO1xuICAgIHRoaXMucmFkaXVzID0gcGFyYW1zPy5yYWRpdXMgPz8gMC4wO1xuICB9XG5cbiAgcHVibGljIGNhbGN1bGF0ZUNvbGxpc2lvbihcbiAgICBjb2xsaWRlck1hdHJpeDogVEhSRUUuTWF0cml4NCxcbiAgICBvYmplY3RQb3NpdGlvbjogVEhSRUUuVmVjdG9yMyxcbiAgICBvYmplY3RSYWRpdXM6IG51bWJlcixcbiAgICB0YXJnZXQ6IFRIUkVFLlZlY3RvcjMsXG4gICk6IG51bWJlciB7XG4gICAgdGFyZ2V0LmNvcHkodGhpcy5vZmZzZXQpLmFwcGx5TWF0cml4NChjb2xsaWRlck1hdHJpeCk7IC8vIHRyYW5zZm9ybWVkIG9mZnNldFxuICAgIHRhcmdldC5uZWdhdGUoKS5hZGQob2JqZWN0UG9zaXRpb24pOyAvLyBhIHZlY3RvciBmcm9tIGNvbGxpZGVyIGNlbnRlciB0byBvYmplY3QgcG9zaXRpb25cbiAgICBjb25zdCByYWRpdXMgPSBvYmplY3RSYWRpdXMgKyB0aGlzLnJhZGl1cztcbiAgICBjb25zdCBkaXN0YW5jZSA9IHRhcmdldC5sZW5ndGgoKSAtIHJhZGl1cztcbiAgICB0YXJnZXQubm9ybWFsaXplKCk7XG4gICAgcmV0dXJuIGRpc3RhbmNlO1xuICB9XG59XG4iLCAiaW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnO1xuaW1wb3J0IHsgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVDYXBzdWxlIH0gZnJvbSAnLi4vLi4vVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVDYXBzdWxlJztcbmltcG9ydCB7IENvbGxpZGVyU2hhcGVCdWZmZXJHZW9tZXRyeSB9IGZyb20gJy4vQ29sbGlkZXJTaGFwZUJ1ZmZlckdlb21ldHJ5JztcblxuY29uc3QgX3YzQSA9IG5ldyBUSFJFRS5WZWN0b3IzKCk7XG5cbmV4cG9ydCBjbGFzcyBDb2xsaWRlclNoYXBlQ2Fwc3VsZUJ1ZmZlckdlb21ldHJ5IGV4dGVuZHMgVEhSRUUuQnVmZmVyR2VvbWV0cnkgaW1wbGVtZW50cyBDb2xsaWRlclNoYXBlQnVmZmVyR2VvbWV0cnkge1xuICBwdWJsaWMgd29ybGRTY2FsZSA9IDEuMDtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9hdHRyUG9zOiBUSFJFRS5CdWZmZXJBdHRyaWJ1dGU7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2F0dHJJbmRleDogVEhSRUUuQnVmZmVyQXR0cmlidXRlO1xuICBwcml2YXRlIHJlYWRvbmx5IF9zaGFwZTogVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVDYXBzdWxlO1xuICBwcml2YXRlIF9jdXJyZW50UmFkaXVzID0gMDtcbiAgcHJpdmF0ZSByZWFkb25seSBfY3VycmVudE9mZnNldCA9IG5ldyBUSFJFRS5WZWN0b3IzKCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2N1cnJlbnRUYWlsID0gbmV3IFRIUkVFLlZlY3RvcjMoKTtcblxuICBwdWJsaWMgY29uc3RydWN0b3Ioc2hhcGU6IFZSTVNwcmluZ0JvbmVDb2xsaWRlclNoYXBlQ2Fwc3VsZSkge1xuICAgIHN1cGVyKCk7XG5cbiAgICB0aGlzLl9zaGFwZSA9IHNoYXBlO1xuXG4gICAgdGhpcy5fYXR0clBvcyA9IG5ldyBUSFJFRS5CdWZmZXJBdHRyaWJ1dGUobmV3IEZsb2F0MzJBcnJheSgzOTYpLCAzKTtcbiAgICB0aGlzLnNldEF0dHJpYnV0ZSgncG9zaXRpb24nLCB0aGlzLl9hdHRyUG9zKTtcblxuICAgIHRoaXMuX2F0dHJJbmRleCA9IG5ldyBUSFJFRS5CdWZmZXJBdHRyaWJ1dGUobmV3IFVpbnQxNkFycmF5KDI2NCksIDEpO1xuICAgIHRoaXMuc2V0SW5kZXgodGhpcy5fYXR0ckluZGV4KTtcblxuICAgIHRoaXMuX2J1aWxkSW5kZXgoKTtcbiAgICB0aGlzLnVwZGF0ZSgpO1xuICB9XG5cbiAgcHVibGljIHVwZGF0ZSgpOiB2b2lkIHtcbiAgICBsZXQgc2hvdWxkVXBkYXRlR2VvbWV0cnkgPSBmYWxzZTtcblxuICAgIGNvbnN0IHJhZGl1cyA9IHRoaXMuX3NoYXBlLnJhZGl1cyAvIHRoaXMud29ybGRTY2FsZTtcbiAgICBpZiAodGhpcy5fY3VycmVudFJhZGl1cyAhPT0gcmFkaXVzKSB7XG4gICAgICB0aGlzLl9jdXJyZW50UmFkaXVzID0gcmFkaXVzO1xuICAgICAgc2hvdWxkVXBkYXRlR2VvbWV0cnkgPSB0cnVlO1xuICAgIH1cblxuICAgIGlmICghdGhpcy5fY3VycmVudE9mZnNldC5lcXVhbHModGhpcy5fc2hhcGUub2Zmc2V0KSkge1xuICAgICAgdGhpcy5fY3VycmVudE9mZnNldC5jb3B5KHRoaXMuX3NoYXBlLm9mZnNldCk7XG4gICAgICBzaG91bGRVcGRhdGVHZW9tZXRyeSA9IHRydWU7XG4gICAgfVxuXG4gICAgY29uc3QgdGFpbCA9IF92M0EuY29weSh0aGlzLl9zaGFwZS50YWlsKS5kaXZpZGVTY2FsYXIodGhpcy53b3JsZFNjYWxlKTtcbiAgICBpZiAodGhpcy5fY3VycmVudFRhaWwuZGlzdGFuY2VUb1NxdWFyZWQodGFpbCkgPiAxZS0xMCkge1xuICAgICAgdGhpcy5fY3VycmVudFRhaWwuY29weSh0YWlsKTtcbiAgICAgIHNob3VsZFVwZGF0ZUdlb21ldHJ5ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAoc2hvdWxkVXBkYXRlR2VvbWV0cnkpIHtcbiAgICAgIHRoaXMuX2J1aWxkUG9zaXRpb24oKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9idWlsZFBvc2l0aW9uKCk6IHZvaWQge1xuICAgIF92M0EuY29weSh0aGlzLl9jdXJyZW50VGFpbCkuc3ViKHRoaXMuX2N1cnJlbnRPZmZzZXQpO1xuICAgIGNvbnN0IGwgPSBfdjNBLmxlbmd0aCgpIC8gdGhpcy5fY3VycmVudFJhZGl1cztcblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDw9IDE2OyBpKyspIHtcbiAgICAgIGNvbnN0IHQgPSAoaSAvIDE2LjApICogTWF0aC5QSTtcblxuICAgICAgdGhpcy5fYXR0clBvcy5zZXRYWVooaSwgLU1hdGguc2luKHQpLCAtTWF0aC5jb3ModCksIDAuMCk7XG4gICAgICB0aGlzLl9hdHRyUG9zLnNldFhZWigxNyArIGksIGwgKyBNYXRoLnNpbih0KSwgTWF0aC5jb3ModCksIDAuMCk7XG4gICAgICB0aGlzLl9hdHRyUG9zLnNldFhZWigzNCArIGksIC1NYXRoLnNpbih0KSwgMC4wLCAtTWF0aC5jb3ModCkpO1xuICAgICAgdGhpcy5fYXR0clBvcy5zZXRYWVooNTEgKyBpLCBsICsgTWF0aC5zaW4odCksIDAuMCwgTWF0aC5jb3ModCkpO1xuICAgIH1cblxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMzI7IGkrKykge1xuICAgICAgY29uc3QgdCA9IChpIC8gMTYuMCkgKiBNYXRoLlBJO1xuICAgICAgdGhpcy5fYXR0clBvcy5zZXRYWVooNjggKyBpLCAwLjAsIE1hdGguc2luKHQpLCBNYXRoLmNvcyh0KSk7XG4gICAgICB0aGlzLl9hdHRyUG9zLnNldFhZWigxMDAgKyBpLCBsLCBNYXRoLnNpbih0KSwgTWF0aC5jb3ModCkpO1xuICAgIH1cblxuICAgIGNvbnN0IHRoZXRhID0gTWF0aC5hdGFuMihfdjNBLnksIE1hdGguc3FydChfdjNBLnggKiBfdjNBLnggKyBfdjNBLnogKiBfdjNBLnopKTtcbiAgICBjb25zdCBwaGkgPSAtTWF0aC5hdGFuMihfdjNBLnosIF92M0EueCk7XG5cbiAgICB0aGlzLnJvdGF0ZVoodGhldGEpO1xuICAgIHRoaXMucm90YXRlWShwaGkpO1xuICAgIHRoaXMuc2NhbGUodGhpcy5fY3VycmVudFJhZGl1cywgdGhpcy5fY3VycmVudFJhZGl1cywgdGhpcy5fY3VycmVudFJhZGl1cyk7XG4gICAgdGhpcy50cmFuc2xhdGUodGhpcy5fY3VycmVudE9mZnNldC54LCB0aGlzLl9jdXJyZW50T2Zmc2V0LnksIHRoaXMuX2N1cnJlbnRPZmZzZXQueik7XG5cbiAgICB0aGlzLl9hdHRyUG9zLm5lZWRzVXBkYXRlID0gdHJ1ZTtcbiAgfVxuXG4gIHByaXZhdGUgX2J1aWxkSW5kZXgoKTogdm9pZCB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCAzNDsgaSsrKSB7XG4gICAgICBjb25zdCBpMSA9IChpICsgMSkgJSAzNDtcblxuICAgICAgdGhpcy5fYXR0ckluZGV4LnNldFhZKGkgKiAyLCBpLCBpMSk7XG4gICAgICB0aGlzLl9hdHRySW5kZXguc2V0WFkoNjggKyBpICogMiwgMzQgKyBpLCAzNCArIGkxKTtcbiAgICB9XG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDMyOyBpKyspIHtcbiAgICAgIGNvbnN0IGkxID0gKGkgKyAxKSAlIDMyO1xuXG4gICAgICB0aGlzLl9hdHRySW5kZXguc2V0WFkoMTM2ICsgaSAqIDIsIDY4ICsgaSwgNjggKyBpMSk7XG4gICAgICB0aGlzLl9hdHRySW5kZXguc2V0WFkoMjAwICsgaSAqIDIsIDEwMCArIGksIDEwMCArIGkxKTtcbiAgICB9XG5cbiAgICB0aGlzLl9hdHRySW5kZXgubmVlZHNVcGRhdGUgPSB0cnVlO1xuICB9XG59XG4iLCAiaW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnO1xuaW1wb3J0IHsgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVTcGhlcmUgfSBmcm9tICcuLi8uLi9WUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZVNwaGVyZSc7XG5pbXBvcnQgeyBDb2xsaWRlclNoYXBlQnVmZmVyR2VvbWV0cnkgfSBmcm9tICcuL0NvbGxpZGVyU2hhcGVCdWZmZXJHZW9tZXRyeSc7XG5cbmV4cG9ydCBjbGFzcyBDb2xsaWRlclNoYXBlU3BoZXJlQnVmZmVyR2VvbWV0cnkgZXh0ZW5kcyBUSFJFRS5CdWZmZXJHZW9tZXRyeSBpbXBsZW1lbnRzIENvbGxpZGVyU2hhcGVCdWZmZXJHZW9tZXRyeSB7XG4gIHB1YmxpYyB3b3JsZFNjYWxlID0gMS4wO1xuXG4gIHByaXZhdGUgcmVhZG9ubHkgX2F0dHJQb3M6IFRIUkVFLkJ1ZmZlckF0dHJpYnV0ZTtcbiAgcHJpdmF0ZSByZWFkb25seSBfYXR0ckluZGV4OiBUSFJFRS5CdWZmZXJBdHRyaWJ1dGU7XG4gIHByaXZhdGUgcmVhZG9ubHkgX3NoYXBlOiBWUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZVNwaGVyZTtcbiAgcHJpdmF0ZSBfY3VycmVudFJhZGl1cyA9IDA7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2N1cnJlbnRPZmZzZXQgPSBuZXcgVEhSRUUuVmVjdG9yMygpO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihzaGFwZTogVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVTcGhlcmUpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fc2hhcGUgPSBzaGFwZTtcblxuICAgIHRoaXMuX2F0dHJQb3MgPSBuZXcgVEhSRUUuQnVmZmVyQXR0cmlidXRlKG5ldyBGbG9hdDMyQXJyYXkoMzIgKiAzICogMyksIDMpO1xuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdwb3NpdGlvbicsIHRoaXMuX2F0dHJQb3MpO1xuXG4gICAgdGhpcy5fYXR0ckluZGV4ID0gbmV3IFRIUkVFLkJ1ZmZlckF0dHJpYnV0ZShuZXcgVWludDE2QXJyYXkoNjQgKiAzKSwgMSk7XG4gICAgdGhpcy5zZXRJbmRleCh0aGlzLl9hdHRySW5kZXgpO1xuXG4gICAgdGhpcy5fYnVpbGRJbmRleCgpO1xuICAgIHRoaXMudXBkYXRlKCk7XG4gIH1cblxuICBwdWJsaWMgdXBkYXRlKCk6IHZvaWQge1xuICAgIGxldCBzaG91bGRVcGRhdGVHZW9tZXRyeSA9IGZhbHNlO1xuXG4gICAgY29uc3QgcmFkaXVzID0gdGhpcy5fc2hhcGUucmFkaXVzIC8gdGhpcy53b3JsZFNjYWxlO1xuICAgIGlmICh0aGlzLl9jdXJyZW50UmFkaXVzICE9PSByYWRpdXMpIHtcbiAgICAgIHRoaXMuX2N1cnJlbnRSYWRpdXMgPSByYWRpdXM7XG4gICAgICBzaG91bGRVcGRhdGVHZW9tZXRyeSA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLl9jdXJyZW50T2Zmc2V0LmVxdWFscyh0aGlzLl9zaGFwZS5vZmZzZXQpKSB7XG4gICAgICB0aGlzLl9jdXJyZW50T2Zmc2V0LmNvcHkodGhpcy5fc2hhcGUub2Zmc2V0KTtcbiAgICAgIHNob3VsZFVwZGF0ZUdlb21ldHJ5ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAoc2hvdWxkVXBkYXRlR2VvbWV0cnkpIHtcbiAgICAgIHRoaXMuX2J1aWxkUG9zaXRpb24oKTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIF9idWlsZFBvc2l0aW9uKCk6IHZvaWQge1xuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgMzI7IGkrKykge1xuICAgICAgY29uc3QgdCA9IChpIC8gMTYuMCkgKiBNYXRoLlBJO1xuXG4gICAgICB0aGlzLl9hdHRyUG9zLnNldFhZWihpLCBNYXRoLmNvcyh0KSwgTWF0aC5zaW4odCksIDAuMCk7XG4gICAgICB0aGlzLl9hdHRyUG9zLnNldFhZWigzMiArIGksIDAuMCwgTWF0aC5jb3ModCksIE1hdGguc2luKHQpKTtcbiAgICAgIHRoaXMuX2F0dHJQb3Muc2V0WFlaKDY0ICsgaSwgTWF0aC5zaW4odCksIDAuMCwgTWF0aC5jb3ModCkpO1xuICAgIH1cblxuICAgIHRoaXMuc2NhbGUodGhpcy5fY3VycmVudFJhZGl1cywgdGhpcy5fY3VycmVudFJhZGl1cywgdGhpcy5fY3VycmVudFJhZGl1cyk7XG4gICAgdGhpcy50cmFuc2xhdGUodGhpcy5fY3VycmVudE9mZnNldC54LCB0aGlzLl9jdXJyZW50T2Zmc2V0LnksIHRoaXMuX2N1cnJlbnRPZmZzZXQueik7XG5cbiAgICB0aGlzLl9hdHRyUG9zLm5lZWRzVXBkYXRlID0gdHJ1ZTtcbiAgfVxuXG4gIHByaXZhdGUgX2J1aWxkSW5kZXgoKTogdm9pZCB7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCAzMjsgaSsrKSB7XG4gICAgICBjb25zdCBpMSA9IChpICsgMSkgJSAzMjtcblxuICAgICAgdGhpcy5fYXR0ckluZGV4LnNldFhZKGkgKiAyLCBpLCBpMSk7XG4gICAgICB0aGlzLl9hdHRySW5kZXguc2V0WFkoNjQgKyBpICogMiwgMzIgKyBpLCAzMiArIGkxKTtcbiAgICAgIHRoaXMuX2F0dHJJbmRleC5zZXRYWSgxMjggKyBpICogMiwgNjQgKyBpLCA2NCArIGkxKTtcbiAgICB9XG5cbiAgICB0aGlzLl9hdHRySW5kZXgubmVlZHNVcGRhdGUgPSB0cnVlO1xuICB9XG59XG4iLCAiaW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnO1xuaW1wb3J0IHsgVlJNU3ByaW5nQm9uZUpvaW50IH0gZnJvbSAnLi4vVlJNU3ByaW5nQm9uZUpvaW50JztcbmltcG9ydCB7IFNwcmluZ0JvbmVCdWZmZXJHZW9tZXRyeSB9IGZyb20gJy4vdXRpbHMvU3ByaW5nQm9uZUJ1ZmZlckdlb21ldHJ5JztcblxuY29uc3QgX3YzQSA9IG5ldyBUSFJFRS5WZWN0b3IzKCk7XG5cbmV4cG9ydCBjbGFzcyBWUk1TcHJpbmdCb25lSm9pbnRIZWxwZXIgZXh0ZW5kcyBUSFJFRS5Hcm91cCB7XG4gIHB1YmxpYyByZWFkb25seSBzcHJpbmdCb25lOiBWUk1TcHJpbmdCb25lSm9pbnQ7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2dlb21ldHJ5OiBTcHJpbmdCb25lQnVmZmVyR2VvbWV0cnk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2xpbmU6IFRIUkVFLkxpbmVTZWdtZW50cztcblxuICBwdWJsaWMgY29uc3RydWN0b3Ioc3ByaW5nQm9uZTogVlJNU3ByaW5nQm9uZUpvaW50KSB7XG4gICAgc3VwZXIoKTtcbiAgICB0aGlzLm1hdHJpeEF1dG9VcGRhdGUgPSBmYWxzZTtcblxuICAgIHRoaXMuc3ByaW5nQm9uZSA9IHNwcmluZ0JvbmU7XG5cbiAgICB0aGlzLl9nZW9tZXRyeSA9IG5ldyBTcHJpbmdCb25lQnVmZmVyR2VvbWV0cnkodGhpcy5zcHJpbmdCb25lKTtcblxuICAgIGNvbnN0IG1hdGVyaWFsID0gbmV3IFRIUkVFLkxpbmVCYXNpY01hdGVyaWFsKHtcbiAgICAgIGNvbG9yOiAweGZmZmYwMCxcbiAgICAgIGRlcHRoVGVzdDogZmFsc2UsXG4gICAgICBkZXB0aFdyaXRlOiBmYWxzZSxcbiAgICB9KTtcblxuICAgIHRoaXMuX2xpbmUgPSBuZXcgVEhSRUUuTGluZVNlZ21lbnRzKHRoaXMuX2dlb21ldHJ5LCBtYXRlcmlhbCk7XG4gICAgdGhpcy5hZGQodGhpcy5fbGluZSk7XG4gIH1cblxuICBwdWJsaWMgZGlzcG9zZSgpOiB2b2lkIHtcbiAgICB0aGlzLl9nZW9tZXRyeS5kaXNwb3NlKCk7XG4gIH1cblxuICBwdWJsaWMgdXBkYXRlTWF0cml4V29ybGQoZm9yY2U6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICB0aGlzLnNwcmluZ0JvbmUuYm9uZS51cGRhdGVXb3JsZE1hdHJpeCh0cnVlLCBmYWxzZSk7XG5cbiAgICB0aGlzLm1hdHJpeC5jb3B5KHRoaXMuc3ByaW5nQm9uZS5ib25lLm1hdHJpeFdvcmxkKTtcblxuICAgIGNvbnN0IG1hdHJpeFdvcmxkRWxlbWVudHMgPSB0aGlzLm1hdHJpeC5lbGVtZW50cztcbiAgICB0aGlzLl9nZW9tZXRyeS53b3JsZFNjYWxlID0gX3YzQVxuICAgICAgLnNldChtYXRyaXhXb3JsZEVsZW1lbnRzWzBdLCBtYXRyaXhXb3JsZEVsZW1lbnRzWzFdLCBtYXRyaXhXb3JsZEVsZW1lbnRzWzJdKVxuICAgICAgLmxlbmd0aCgpOyAvLyBjYWxjdWxhdGUgc2NhbGUgb2YgeCBjb21wb25lbnRcblxuICAgIHRoaXMuX2dlb21ldHJ5LnVwZGF0ZSgpO1xuXG4gICAgc3VwZXIudXBkYXRlTWF0cml4V29ybGQoZm9yY2UpO1xuICB9XG59XG4iLCAiaW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnO1xuaW1wb3J0IHsgVlJNU3ByaW5nQm9uZUpvaW50IH0gZnJvbSAnLi4vLi4vVlJNU3ByaW5nQm9uZUpvaW50JztcblxuZXhwb3J0IGNsYXNzIFNwcmluZ0JvbmVCdWZmZXJHZW9tZXRyeSBleHRlbmRzIFRIUkVFLkJ1ZmZlckdlb21ldHJ5IHtcbiAgcHVibGljIHdvcmxkU2NhbGUgPSAxLjA7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfYXR0clBvczogVEhSRUUuQnVmZmVyQXR0cmlidXRlO1xuICBwcml2YXRlIHJlYWRvbmx5IF9hdHRySW5kZXg6IFRIUkVFLkJ1ZmZlckF0dHJpYnV0ZTtcbiAgcHJpdmF0ZSByZWFkb25seSBfc3ByaW5nQm9uZTogVlJNU3ByaW5nQm9uZUpvaW50O1xuICBwcml2YXRlIF9jdXJyZW50UmFkaXVzID0gMDtcbiAgcHJpdmF0ZSByZWFkb25seSBfY3VycmVudFRhaWwgPSBuZXcgVEhSRUUuVmVjdG9yMygpO1xuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihzcHJpbmdCb25lOiBWUk1TcHJpbmdCb25lSm9pbnQpIHtcbiAgICBzdXBlcigpO1xuXG4gICAgdGhpcy5fc3ByaW5nQm9uZSA9IHNwcmluZ0JvbmU7XG5cbiAgICB0aGlzLl9hdHRyUG9zID0gbmV3IFRIUkVFLkJ1ZmZlckF0dHJpYnV0ZShuZXcgRmxvYXQzMkFycmF5KDI5NCksIDMpO1xuICAgIHRoaXMuc2V0QXR0cmlidXRlKCdwb3NpdGlvbicsIHRoaXMuX2F0dHJQb3MpO1xuXG4gICAgdGhpcy5fYXR0ckluZGV4ID0gbmV3IFRIUkVFLkJ1ZmZlckF0dHJpYnV0ZShuZXcgVWludDE2QXJyYXkoMTk0KSwgMSk7XG4gICAgdGhpcy5zZXRJbmRleCh0aGlzLl9hdHRySW5kZXgpO1xuXG4gICAgdGhpcy5fYnVpbGRJbmRleCgpO1xuICAgIHRoaXMudXBkYXRlKCk7XG4gIH1cblxuICBwdWJsaWMgdXBkYXRlKCk6IHZvaWQge1xuICAgIGxldCBzaG91bGRVcGRhdGVHZW9tZXRyeSA9IGZhbHNlO1xuXG4gICAgY29uc3QgcmFkaXVzID0gdGhpcy5fc3ByaW5nQm9uZS5zZXR0aW5ncy5oaXRSYWRpdXMgLyB0aGlzLndvcmxkU2NhbGU7XG4gICAgaWYgKHRoaXMuX2N1cnJlbnRSYWRpdXMgIT09IHJhZGl1cykge1xuICAgICAgdGhpcy5fY3VycmVudFJhZGl1cyA9IHJhZGl1cztcbiAgICAgIHNob3VsZFVwZGF0ZUdlb21ldHJ5ID0gdHJ1ZTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuX2N1cnJlbnRUYWlsLmVxdWFscyh0aGlzLl9zcHJpbmdCb25lLmluaXRpYWxMb2NhbENoaWxkUG9zaXRpb24pKSB7XG4gICAgICB0aGlzLl9jdXJyZW50VGFpbC5jb3B5KHRoaXMuX3NwcmluZ0JvbmUuaW5pdGlhbExvY2FsQ2hpbGRQb3NpdGlvbik7XG4gICAgICBzaG91bGRVcGRhdGVHZW9tZXRyeSA9IHRydWU7XG4gICAgfVxuXG4gICAgaWYgKHNob3VsZFVwZGF0ZUdlb21ldHJ5KSB7XG4gICAgICB0aGlzLl9idWlsZFBvc2l0aW9uKCk7XG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSBfYnVpbGRQb3NpdGlvbigpOiB2b2lkIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDMyOyBpKyspIHtcbiAgICAgIGNvbnN0IHQgPSAoaSAvIDE2LjApICogTWF0aC5QSTtcblxuICAgICAgdGhpcy5fYXR0clBvcy5zZXRYWVooaSwgTWF0aC5jb3ModCksIE1hdGguc2luKHQpLCAwLjApO1xuICAgICAgdGhpcy5fYXR0clBvcy5zZXRYWVooMzIgKyBpLCAwLjAsIE1hdGguY29zKHQpLCBNYXRoLnNpbih0KSk7XG4gICAgICB0aGlzLl9hdHRyUG9zLnNldFhZWig2NCArIGksIE1hdGguc2luKHQpLCAwLjAsIE1hdGguY29zKHQpKTtcbiAgICB9XG5cbiAgICB0aGlzLnNjYWxlKHRoaXMuX2N1cnJlbnRSYWRpdXMsIHRoaXMuX2N1cnJlbnRSYWRpdXMsIHRoaXMuX2N1cnJlbnRSYWRpdXMpO1xuICAgIHRoaXMudHJhbnNsYXRlKHRoaXMuX2N1cnJlbnRUYWlsLngsIHRoaXMuX2N1cnJlbnRUYWlsLnksIHRoaXMuX2N1cnJlbnRUYWlsLnopO1xuXG4gICAgdGhpcy5fYXR0clBvcy5zZXRYWVooOTYsIDAsIDAsIDApO1xuICAgIHRoaXMuX2F0dHJQb3Muc2V0WFlaKDk3LCB0aGlzLl9jdXJyZW50VGFpbC54LCB0aGlzLl9jdXJyZW50VGFpbC55LCB0aGlzLl9jdXJyZW50VGFpbC56KTtcblxuICAgIHRoaXMuX2F0dHJQb3MubmVlZHNVcGRhdGUgPSB0cnVlO1xuICB9XG5cbiAgcHJpdmF0ZSBfYnVpbGRJbmRleCgpOiB2b2lkIHtcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IDMyOyBpKyspIHtcbiAgICAgIGNvbnN0IGkxID0gKGkgKyAxKSAlIDMyO1xuXG4gICAgICB0aGlzLl9hdHRySW5kZXguc2V0WFkoaSAqIDIsIGksIGkxKTtcbiAgICAgIHRoaXMuX2F0dHJJbmRleC5zZXRYWSg2NCArIGkgKiAyLCAzMiArIGksIDMyICsgaTEpO1xuICAgICAgdGhpcy5fYXR0ckluZGV4LnNldFhZKDEyOCArIGkgKiAyLCA2NCArIGksIDY0ICsgaTEpO1xuICAgIH1cbiAgICB0aGlzLl9hdHRySW5kZXguc2V0WFkoMTkyLCA5NiwgOTcpO1xuXG4gICAgdGhpcy5fYXR0ckluZGV4Lm5lZWRzVXBkYXRlID0gdHJ1ZTtcbiAgfVxufVxuIiwgImltcG9ydCAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcbmltcG9ydCB0eXBlIHsgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGUgfSBmcm9tICcuL1ZSTVNwcmluZ0JvbmVDb2xsaWRlclNoYXBlJztcblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgY29sbGlkZXIgb2YgYSBWUk0uXG4gKi9cbmV4cG9ydCBjbGFzcyBWUk1TcHJpbmdCb25lQ29sbGlkZXIgZXh0ZW5kcyBUSFJFRS5PYmplY3QzRCB7XG4gIC8qKlxuICAgKiBUaGUgc2hhcGUgb2YgdGhlIGNvbGxpZGVyLlxuICAgKi9cbiAgcHVibGljIHJlYWRvbmx5IHNoYXBlOiBWUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZTtcblxuICBwdWJsaWMgY29uc3RydWN0b3Ioc2hhcGU6IFZSTVNwcmluZ0JvbmVDb2xsaWRlclNoYXBlKSB7XG4gICAgc3VwZXIoKTtcblxuICAgIHRoaXMuc2hhcGUgPSBzaGFwZTtcbiAgfVxufVxuIiwgImltcG9ydCAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcbmltcG9ydCB7IG1hdDRJbnZlcnRDb21wYXQgfSBmcm9tICcuL3V0aWxzL21hdDRJbnZlcnRDb21wYXQnO1xuaW1wb3J0IHsgTWF0cml4NEludmVyc2VDYWNoZSB9IGZyb20gJy4vdXRpbHMvTWF0cml4NEludmVyc2VDYWNoZSc7XG5pbXBvcnQgdHlwZSB7IFZSTVNwcmluZ0JvbmVDb2xsaWRlckdyb3VwIH0gZnJvbSAnLi9WUk1TcHJpbmdCb25lQ29sbGlkZXJHcm91cCc7XG5pbXBvcnQgdHlwZSB7IFZSTVNwcmluZ0JvbmVKb2ludFNldHRpbmdzIH0gZnJvbSAnLi9WUk1TcHJpbmdCb25lSm9pbnRTZXR0aW5ncyc7XG5cbi8vIGJhc2VkIG9uXG4vLyBodHRwOi8vcm9ja2V0anVtcC5za3IuanAvdW5pdHkzZC8xMDkvXG4vLyBodHRwczovL2dpdGh1Yi5jb20vZHdhbmdvL1VuaVZSTS9ibG9iL21hc3Rlci9TY3JpcHRzL1NwcmluZ0JvbmUvVlJNU3ByaW5nQm9uZS5jc1xuXG5jb25zdCBJREVOVElUWV9NQVRSSVg0ID0gbmV3IFRIUkVFLk1hdHJpeDQoKTtcblxuLy8gXHU4QTA4XHU3Qjk3XHU0RTJEXHUzMDZFXHU0RTAwXHU2NjQyXHU0RkREXHU1QjU4XHU3NTI4XHU1OTA5XHU2NTcwXHVGRjA4XHU0RTAwXHU1RUE2XHUzMEE0XHUzMEYzXHUzMEI5XHUzMEJGXHUzMEYzXHUzMEI5XHUzMDkyXHU0RjVDXHUzMDYzXHUzMDVGXHUzMDg5XHUzMDQyXHUzMDY4XHUzMDZGXHU0RjdGXHUzMDQ0XHU1NkRFXHUzMDU5XHVGRjA5XG5jb25zdCBfdjNBID0gbmV3IFRIUkVFLlZlY3RvcjMoKTtcbmNvbnN0IF92M0IgPSBuZXcgVEhSRUUuVmVjdG9yMygpO1xuY29uc3QgX3YzQyA9IG5ldyBUSFJFRS5WZWN0b3IzKCk7XG5cbi8qKlxuICogQSB0ZW1wb3JhcnkgdmFyaWFibGUgd2hpY2ggaXMgdXNlZCBpbiBgdXBkYXRlYFxuICovXG5jb25zdCBfd29ybGRTcGFjZVBvc2l0aW9uID0gbmV3IFRIUkVFLlZlY3RvcjMoKTtcblxuLyoqXG4gKiBBIHRlbXBvcmFyeSB2YXJpYWJsZSB3aGljaCBpcyB1c2VkIGluIGB1cGRhdGVgXG4gKi9cbmNvbnN0IF9jZW50ZXJTcGFjZVBvc2l0aW9uID0gbmV3IFRIUkVFLlZlY3RvcjMoKTtcblxuLyoqXG4gKiBBIHRlbXBvcmFyeSB2YXJpYWJsZSB3aGljaCBpcyB1c2VkIGluIGB1cGRhdGVgXG4gKi9cbmNvbnN0IF9uZXh0VGFpbCA9IG5ldyBUSFJFRS5WZWN0b3IzKCk7XG5cbmNvbnN0IF9xdWF0QSA9IG5ldyBUSFJFRS5RdWF0ZXJuaW9uKCk7XG5jb25zdCBfbWF0QSA9IG5ldyBUSFJFRS5NYXRyaXg0KCk7XG5jb25zdCBfbWF0QiA9IG5ldyBUSFJFRS5NYXRyaXg0KCk7XG5cbi8qKlxuICogQSBjbGFzcyByZXByZXNlbnRzIGEgc2luZ2xlIGpvaW50IG9mIGEgc3ByaW5nIGJvbmUuXG4gKiBJdCBzaG91bGQgYmUgbWFuYWdlZCBieSBhIFtbVlJNU3ByaW5nQm9uZU1hbmFnZXJdXS5cbiAqL1xuZXhwb3J0IGNsYXNzIFZSTVNwcmluZ0JvbmVKb2ludCB7XG4gIC8qKlxuICAgKiBTZXR0aW5ncyBvZiB0aGUgYm9uZS5cbiAgICovXG4gIHB1YmxpYyBzZXR0aW5nczogVlJNU3ByaW5nQm9uZUpvaW50U2V0dGluZ3M7XG5cbiAgLyoqXG4gICAqIENvbGxpZGVyIGdyb3VwcyBhdHRhY2hlZCB0byB0aGlzIGJvbmUuXG4gICAqL1xuICBwdWJsaWMgY29sbGlkZXJHcm91cHM6IFZSTVNwcmluZ0JvbmVDb2xsaWRlckdyb3VwW107XG5cbiAgLyoqXG4gICAqIEFuIE9iamVjdDNEIGF0dGFjaGVkIHRvIHRoaXMgYm9uZS5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBib25lOiBUSFJFRS5PYmplY3QzRDtcblxuICAvKipcbiAgICogQW4gT2JqZWN0M0QgdGhhdCB3aWxsIGJlIHVzZWQgYXMgYSB0YWlsIG9mIHRoaXMgc3ByaW5nIGJvbmUuXG4gICAqIEl0IGNhbiBiZSBudWxsIHdoZW4gdGhlIHNwcmluZyBib25lIGlzIGltcG9ydGVkIGZyb20gVlJNIDAuMC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBjaGlsZDogVEhSRUUuT2JqZWN0M0QgfCBudWxsO1xuXG4gIC8qKlxuICAgKiBDdXJyZW50IHBvc2l0aW9uIG9mIGNoaWxkIHRhaWwsIGluIGNlbnRlciB1bml0LiBXaWxsIGJlIHVzZWQgZm9yIHZlcmxldCBpbnRlZ3JhdGlvbi5cbiAgICovXG4gIHByaXZhdGUgX2N1cnJlbnRUYWlsID0gbmV3IFRIUkVFLlZlY3RvcjMoKTtcblxuICAvKipcbiAgICogUHJldmlvdXMgcG9zaXRpb24gb2YgY2hpbGQgdGFpbCwgaW4gY2VudGVyIHVuaXQuIFdpbGwgYmUgdXNlZCBmb3IgdmVybGV0IGludGVncmF0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBfcHJldlRhaWwgPSBuZXcgVEhSRUUuVmVjdG9yMygpO1xuXG4gIC8qKlxuICAgKiBJbml0aWFsIGF4aXMgb2YgdGhlIGJvbmUsIGluIGxvY2FsIHVuaXQuXG4gICAqL1xuICBwcml2YXRlIF9ib25lQXhpcyA9IG5ldyBUSFJFRS5WZWN0b3IzKCk7XG5cbiAgLyoqXG4gICAqIExlbmd0aCBvZiB0aGUgYm9uZSBpbiB3b3JsZCB1bml0LlxuICAgKiBXaWxsIGJlIHVzZWQgZm9yIG5vcm1hbGl6YXRpb24gaW4gdXBkYXRlIGxvb3AsIHdpbGwgYmUgdXBkYXRlZCBieSB7QGxpbmsgX2NhbGNXb3JsZFNwYWNlQm9uZUxlbmd0aH0uXG4gICAqXG4gICAqIEl0J3Mgc2FtZSBhcyBsb2NhbCB1bml0IGxlbmd0aCB1bmxlc3MgdGhlcmUgYXJlIHNjYWxlIHRyYW5zZm9ybWF0aW9ucyBpbiB0aGUgd29ybGQgc3BhY2UuXG4gICAqL1xuICBwcml2YXRlIF93b3JsZFNwYWNlQm9uZUxlbmd0aCA9IDAuMDtcblxuICAvKipcbiAgICogVGhpcyBzcHJpbmdib25lIHdpbGwgYmUgY2FsY3VsYXRlZCBiYXNlZCBvbiB0aGUgc3BhY2UgcmVsYXRpdmUgZnJvbSB0aGlzIG9iamVjdC5cbiAgICogSWYgdGhpcyBpcyBgbnVsbGAsIHNwcmluZ2JvbmUgd2lsbCBiZSBjYWxjdWxhdGVkIGluIHdvcmxkIHNwYWNlLlxuICAgKi9cbiAgcHJpdmF0ZSBfY2VudGVyOiBUSFJFRS5PYmplY3QzRCB8IG51bGwgPSBudWxsO1xuICBwdWJsaWMgZ2V0IGNlbnRlcigpOiBUSFJFRS5PYmplY3QzRCB8IG51bGwge1xuICAgIHJldHVybiB0aGlzLl9jZW50ZXI7XG4gIH1cbiAgcHVibGljIHNldCBjZW50ZXIoY2VudGVyOiBUSFJFRS5PYmplY3QzRCB8IG51bGwpIHtcbiAgICAvLyB1bmluc3RhbGwgaW52ZXJzZSBjYWNoZVxuICAgIGlmICh0aGlzLl9jZW50ZXI/LnVzZXJEYXRhLmludmVyc2VDYWNoZVByb3h5KSB7XG4gICAgICAodGhpcy5fY2VudGVyLnVzZXJEYXRhLmludmVyc2VDYWNoZVByb3h5IGFzIE1hdHJpeDRJbnZlcnNlQ2FjaGUpLnJldmVydCgpO1xuICAgICAgZGVsZXRlIHRoaXMuX2NlbnRlci51c2VyRGF0YS5pbnZlcnNlQ2FjaGVQcm94eTtcbiAgICB9XG5cbiAgICAvLyBjaGFuZ2UgdGhlIGNlbnRlclxuICAgIHRoaXMuX2NlbnRlciA9IGNlbnRlcjtcblxuICAgIC8vIGluc3RhbGwgaW52ZXJzZSBjYWNoZVxuICAgIGlmICh0aGlzLl9jZW50ZXIpIHtcbiAgICAgIGlmICghdGhpcy5fY2VudGVyLnVzZXJEYXRhLmludmVyc2VDYWNoZVByb3h5KSB7XG4gICAgICAgIHRoaXMuX2NlbnRlci51c2VyRGF0YS5pbnZlcnNlQ2FjaGVQcm94eSA9IG5ldyBNYXRyaXg0SW52ZXJzZUNhY2hlKHRoaXMuX2NlbnRlci5tYXRyaXhXb3JsZCk7XG4gICAgICB9XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEluaXRpYWwgc3RhdGUgb2YgdGhlIGxvY2FsIG1hdHJpeCBvZiB0aGUgYm9uZS5cbiAgICovXG4gIHByaXZhdGUgX2luaXRpYWxMb2NhbE1hdHJpeCA9IG5ldyBUSFJFRS5NYXRyaXg0KCk7XG5cbiAgLyoqXG4gICAqIEluaXRpYWwgc3RhdGUgb2YgdGhlIHJvdGF0aW9uIG9mIHRoZSBib25lLlxuICAgKi9cbiAgcHJpdmF0ZSBfaW5pdGlhbExvY2FsUm90YXRpb24gPSBuZXcgVEhSRUUuUXVhdGVybmlvbigpO1xuXG4gIC8qKlxuICAgKiBJbml0aWFsIHN0YXRlIG9mIHRoZSBwb3NpdGlvbiBvZiBpdHMgY2hpbGQuXG4gICAqL1xuICBwcml2YXRlIF9pbml0aWFsTG9jYWxDaGlsZFBvc2l0aW9uID0gbmV3IFRIUkVFLlZlY3RvcjMoKTtcbiAgcHVibGljIGdldCBpbml0aWFsTG9jYWxDaGlsZFBvc2l0aW9uKCk6IFRIUkVFLlZlY3RvcjMge1xuICAgIHJldHVybiB0aGlzLl9pbml0aWFsTG9jYWxDaGlsZFBvc2l0aW9uO1xuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIHdvcmxkIG1hdHJpeCBvZiBpdHMgcGFyZW50IG9iamVjdC5cbiAgICogTm90ZSB0aGF0IGl0IHJldHVybnMgYSByZWZlcmVuY2UgdG8gdGhlIG1hdHJpeC4gRG9uJ3QgbXV0YXRlIHRoaXMgZGlyZWN0bHkhXG4gICAqL1xuICBwcml2YXRlIGdldCBfcGFyZW50TWF0cml4V29ybGQoKTogVEhSRUUuTWF0cml4NCB7XG4gICAgcmV0dXJuIHRoaXMuYm9uZS5wYXJlbnQgPyB0aGlzLmJvbmUucGFyZW50Lm1hdHJpeFdvcmxkIDogSURFTlRJVFlfTUFUUklYNDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBuZXcgVlJNU3ByaW5nQm9uZS5cbiAgICpcbiAgICogQHBhcmFtIGJvbmUgQW4gT2JqZWN0M0QgdGhhdCB3aWxsIGJlIGF0dGFjaGVkIHRvIHRoaXMgYm9uZVxuICAgKiBAcGFyYW0gY2hpbGQgQW4gT2JqZWN0M0QgdGhhdCB3aWxsIGJlIHVzZWQgYXMgYSB0YWlsIG9mIHRoaXMgc3ByaW5nIGJvbmUuIEl0IGNhbiBiZSBudWxsIHdoZW4gdGhlIHNwcmluZyBib25lIGlzIGltcG9ydGVkIGZyb20gVlJNIDAuMFxuICAgKiBAcGFyYW0gc2V0dGluZ3MgU2V2ZXJhbCBwYXJhbWV0ZXJzIHJlbGF0ZWQgdG8gYmVoYXZpb3Igb2YgdGhlIHNwcmluZyBib25lXG4gICAqIEBwYXJhbSBjb2xsaWRlckdyb3VwcyBDb2xsaWRlciBncm91cHMgdGhhdCB3aWxsIGJlIGNvbGxpZGVkIHdpdGggdGhpcyBzcHJpbmcgYm9uZVxuICAgKi9cbiAgY29uc3RydWN0b3IoXG4gICAgYm9uZTogVEhSRUUuT2JqZWN0M0QsXG4gICAgY2hpbGQ6IFRIUkVFLk9iamVjdDNEIHwgbnVsbCxcbiAgICBzZXR0aW5nczogUGFydGlhbDxWUk1TcHJpbmdCb25lSm9pbnRTZXR0aW5ncz4gPSB7fSxcbiAgICBjb2xsaWRlckdyb3VwczogVlJNU3ByaW5nQm9uZUNvbGxpZGVyR3JvdXBbXSA9IFtdLFxuICApIHtcbiAgICB0aGlzLmJvbmUgPSBib25lOyAvLyB1bmlWUk1cdTMwNjdcdTMwNkUgcGFyZW50XG4gICAgdGhpcy5ib25lLm1hdHJpeEF1dG9VcGRhdGUgPSBmYWxzZTsgLy8gdXBkYXRlXHUzMDZCXHUzMDg4XHUzMDhBXHU4QTA4XHU3Qjk3XHUzMDU1XHUzMDhDXHUzMDhCXHUzMDZFXHUzMDY3dGhyZWUuanNcdTUxODVcdTMwNjdcdTMwNkVcdTgxRUFcdTUyRDVcdTUxRTZcdTc0MDZcdTMwNkZcdTRFMERcdTg5ODFcblxuICAgIHRoaXMuY2hpbGQgPSBjaGlsZDtcblxuICAgIHRoaXMuc2V0dGluZ3MgPSB7XG4gICAgICBoaXRSYWRpdXM6IHNldHRpbmdzLmhpdFJhZGl1cyA/PyAwLjAsXG4gICAgICBzdGlmZm5lc3M6IHNldHRpbmdzLnN0aWZmbmVzcyA/PyAxLjAsXG4gICAgICBncmF2aXR5UG93ZXI6IHNldHRpbmdzLmdyYXZpdHlQb3dlciA/PyAwLjAsXG4gICAgICBncmF2aXR5RGlyOiBzZXR0aW5ncy5ncmF2aXR5RGlyPy5jbG9uZSgpID8/IG5ldyBUSFJFRS5WZWN0b3IzKDAuMCwgLTEuMCwgMC4wKSxcbiAgICAgIGRyYWdGb3JjZTogc2V0dGluZ3MuZHJhZ0ZvcmNlID8/IDAuNCxcbiAgICB9O1xuXG4gICAgdGhpcy5jb2xsaWRlckdyb3VwcyA9IGNvbGxpZGVyR3JvdXBzO1xuICB9XG5cbiAgLyoqXG4gICAqIFNldCB0aGUgaW5pdGlhbCBzdGF0ZSBvZiB0aGlzIHNwcmluZyBib25lLlxuICAgKiBZb3UgbWlnaHQgd2FudCB0byBjYWxsIHtAbGluayBWUk1TcHJpbmdCb25lTWFuYWdlci5zZXRJbml0U3RhdGV9IGluc3RlYWQuXG4gICAqL1xuICBwdWJsaWMgc2V0SW5pdFN0YXRlKCk6IHZvaWQge1xuICAgIC8vIHJlbWVtYmVyIGluaXRpYWwgcG9zaXRpb24gb2YgaXRzZWxmXG4gICAgdGhpcy5faW5pdGlhbExvY2FsTWF0cml4LmNvcHkodGhpcy5ib25lLm1hdHJpeCk7XG4gICAgdGhpcy5faW5pdGlhbExvY2FsUm90YXRpb24uY29weSh0aGlzLmJvbmUucXVhdGVybmlvbik7XG5cbiAgICAvLyBzZWUgaW5pdGlhbCBwb3NpdGlvbiBvZiBpdHMgbG9jYWwgY2hpbGRcbiAgICBpZiAodGhpcy5jaGlsZCkge1xuICAgICAgdGhpcy5faW5pdGlhbExvY2FsQ2hpbGRQb3NpdGlvbi5jb3B5KHRoaXMuY2hpbGQucG9zaXRpb24pO1xuICAgIH0gZWxzZSB7XG4gICAgICAvLyB2cm0wIHJlcXVpcmVzIGEgN2NtIGZpeGVkIGJvbmUgbGVuZ3RoIGZvciB0aGUgZmluYWwgbm9kZSBpbiBhIGNoYWluXG4gICAgICAvLyBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS92cm0tYy92cm0tc3BlY2lmaWNhdGlvbi90cmVlL21hc3Rlci9zcGVjaWZpY2F0aW9uL1ZSTUNfc3ByaW5nQm9uZS0xLjAjYWJvdXQtc3ByaW5nLWNvbmZpZ3VyYXRpb25cbiAgICAgIHRoaXMuX2luaXRpYWxMb2NhbENoaWxkUG9zaXRpb24uY29weSh0aGlzLmJvbmUucG9zaXRpb24pLm5vcm1hbGl6ZSgpLm11bHRpcGx5U2NhbGFyKDAuMDcpO1xuICAgIH1cblxuICAgIC8vIGNvcHkgdGhlIGNoaWxkIHBvc2l0aW9uIHRvIHRhaWxzXG4gICAgY29uc3QgbWF0cml4V29ybGRUb0NlbnRlciA9IHRoaXMuX2dldE1hdHJpeFdvcmxkVG9DZW50ZXIoX21hdEEpO1xuICAgIHRoaXMuYm9uZS5sb2NhbFRvV29ybGQodGhpcy5fY3VycmVudFRhaWwuY29weSh0aGlzLl9pbml0aWFsTG9jYWxDaGlsZFBvc2l0aW9uKSkuYXBwbHlNYXRyaXg0KG1hdHJpeFdvcmxkVG9DZW50ZXIpO1xuICAgIHRoaXMuX3ByZXZUYWlsLmNvcHkodGhpcy5fY3VycmVudFRhaWwpO1xuXG4gICAgLy8gc2V0IGluaXRpYWwgc3RhdGVzIHRoYXQgYXJlIHJlbGF0ZWQgdG8gbG9jYWwgY2hpbGQgcG9zaXRpb25cbiAgICB0aGlzLl9ib25lQXhpcy5jb3B5KHRoaXMuX2luaXRpYWxMb2NhbENoaWxkUG9zaXRpb24pLm5vcm1hbGl6ZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlc2V0IHRoZSBzdGF0ZSBvZiB0aGlzIGJvbmUuXG4gICAqIFlvdSBtaWdodCB3YW50IHRvIGNhbGwgW1tWUk1TcHJpbmdCb25lTWFuYWdlci5yZXNldF1dIGluc3RlYWQuXG4gICAqL1xuICBwdWJsaWMgcmVzZXQoKTogdm9pZCB7XG4gICAgdGhpcy5ib25lLnF1YXRlcm5pb24uY29weSh0aGlzLl9pbml0aWFsTG9jYWxSb3RhdGlvbik7XG5cbiAgICAvLyBXZSBuZWVkIHRvIHVwZGF0ZSBpdHMgbWF0cml4V29ybGQgbWFudWFsbHksIHNpbmNlIHdlIHR3ZWFrZWQgdGhlIGJvbmUgYnkgb3VyIGhhbmRcbiAgICB0aGlzLmJvbmUudXBkYXRlTWF0cml4KCk7XG4gICAgdGhpcy5ib25lLm1hdHJpeFdvcmxkLm11bHRpcGx5TWF0cmljZXModGhpcy5fcGFyZW50TWF0cml4V29ybGQsIHRoaXMuYm9uZS5tYXRyaXgpO1xuXG4gICAgLy8gQXBwbHkgdXBkYXRlZCBwb3NpdGlvbiB0byB0YWlsIHN0YXRlc1xuICAgIGNvbnN0IG1hdHJpeFdvcmxkVG9DZW50ZXIgPSB0aGlzLl9nZXRNYXRyaXhXb3JsZFRvQ2VudGVyKF9tYXRBKTtcbiAgICB0aGlzLmJvbmUubG9jYWxUb1dvcmxkKHRoaXMuX2N1cnJlbnRUYWlsLmNvcHkodGhpcy5faW5pdGlhbExvY2FsQ2hpbGRQb3NpdGlvbikpLmFwcGx5TWF0cml4NChtYXRyaXhXb3JsZFRvQ2VudGVyKTtcbiAgICB0aGlzLl9wcmV2VGFpbC5jb3B5KHRoaXMuX2N1cnJlbnRUYWlsKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGUgdGhlIHN0YXRlIG9mIHRoaXMgYm9uZS5cbiAgICogWW91IG1pZ2h0IHdhbnQgdG8gY2FsbCBbW1ZSTVNwcmluZ0JvbmVNYW5hZ2VyLnVwZGF0ZV1dIGluc3RlYWQuXG4gICAqXG4gICAqIEBwYXJhbSBkZWx0YSBkZWx0YVRpbWVcbiAgICovXG4gIHB1YmxpYyB1cGRhdGUoZGVsdGE6IG51bWJlcik6IHZvaWQge1xuICAgIGlmIChkZWx0YSA8PSAwKSByZXR1cm47XG5cbiAgICAvLyBVcGRhdGUgdGhlIF93b3JsZFNwYWNlQm9uZUxlbmd0aFxuICAgIHRoaXMuX2NhbGNXb3JsZFNwYWNlQm9uZUxlbmd0aCgpO1xuXG4gICAgLy8gR2V0IGJvbmUgcG9zaXRpb24gaW4gY2VudGVyIHNwYWNlXG4gICAgX3dvcmxkU3BhY2VQb3NpdGlvbi5zZXRGcm9tTWF0cml4UG9zaXRpb24odGhpcy5ib25lLm1hdHJpeFdvcmxkKTtcbiAgICBsZXQgbWF0cml4V29ybGRUb0NlbnRlciA9IHRoaXMuX2dldE1hdHJpeFdvcmxkVG9DZW50ZXIoX21hdEEpO1xuICAgIF9jZW50ZXJTcGFjZVBvc2l0aW9uLmNvcHkoX3dvcmxkU3BhY2VQb3NpdGlvbikuYXBwbHlNYXRyaXg0KG1hdHJpeFdvcmxkVG9DZW50ZXIpO1xuICAgIGNvbnN0IHF1YXRXb3JsZFRvQ2VudGVyID0gX3F1YXRBLnNldEZyb21Sb3RhdGlvbk1hdHJpeChtYXRyaXhXb3JsZFRvQ2VudGVyKTtcblxuICAgIC8vIEdldCBwYXJlbnQgbWF0cml4IGluIGNlbnRlciBzcGFjZVxuICAgIGNvbnN0IGNlbnRlclNwYWNlUGFyZW50TWF0cml4ID0gX21hdEIuY29weShtYXRyaXhXb3JsZFRvQ2VudGVyKS5tdWx0aXBseSh0aGlzLl9wYXJlbnRNYXRyaXhXb3JsZCk7XG5cbiAgICAvLyBHZXQgYm9uZUF4aXMgaW4gY2VudGVyIHNwYWNlXG4gICAgY29uc3QgY2VudGVyU3BhY2VCb25lQXhpcyA9IF92M0JcbiAgICAgIC5jb3B5KHRoaXMuX2JvbmVBeGlzKVxuICAgICAgLmFwcGx5TWF0cml4NCh0aGlzLl9pbml0aWFsTG9jYWxNYXRyaXgpXG4gICAgICAuYXBwbHlNYXRyaXg0KGNlbnRlclNwYWNlUGFyZW50TWF0cml4KVxuICAgICAgLnN1YihfY2VudGVyU3BhY2VQb3NpdGlvbilcbiAgICAgIC5ub3JtYWxpemUoKTtcblxuICAgIC8vIGdyYXZpdHkgaW4gY2VudGVyIHNwYWNlXG4gICAgY29uc3QgY2VudGVyU3BhY2VHcmF2aXR5ID0gX3YzQy5jb3B5KHRoaXMuc2V0dGluZ3MuZ3Jhdml0eURpcikuYXBwbHlRdWF0ZXJuaW9uKHF1YXRXb3JsZFRvQ2VudGVyKS5ub3JtYWxpemUoKTtcblxuICAgIGNvbnN0IG1hdHJpeENlbnRlclRvV29ybGQgPSB0aGlzLl9nZXRNYXRyaXhDZW50ZXJUb1dvcmxkKF9tYXRBKTtcblxuICAgIC8vIHZlcmxldFx1N0E0RFx1NTIwNlx1MzA2N1x1NkIyMVx1MzA2RVx1NEY0RFx1N0Y2RVx1MzA5Mlx1OEEwOFx1N0I5N1xuICAgIF9uZXh0VGFpbFxuICAgICAgLmNvcHkodGhpcy5fY3VycmVudFRhaWwpXG4gICAgICAuYWRkKFxuICAgICAgICBfdjNBXG4gICAgICAgICAgLmNvcHkodGhpcy5fY3VycmVudFRhaWwpXG4gICAgICAgICAgLnN1Yih0aGlzLl9wcmV2VGFpbClcbiAgICAgICAgICAubXVsdGlwbHlTY2FsYXIoMSAtIHRoaXMuc2V0dGluZ3MuZHJhZ0ZvcmNlKSxcbiAgICAgICkgLy8gXHU1MjREXHUzMEQ1XHUzMEVDXHUzMEZDXHUzMEUwXHUzMDZFXHU3OUZCXHU1MkQ1XHUzMDkyXHU3RDk5XHU3RDlBXHUzMDU5XHUzMDhCKFx1NkUxQlx1ODg3MFx1MzA4Mlx1MzA0Mlx1MzA4Qlx1MzA4OClcbiAgICAgIC5hZGQoX3YzQS5jb3B5KGNlbnRlclNwYWNlQm9uZUF4aXMpLm11bHRpcGx5U2NhbGFyKHRoaXMuc2V0dGluZ3Muc3RpZmZuZXNzICogZGVsdGEpKSAvLyBcdTg5QUFcdTMwNkVcdTU2REVcdThFRTJcdTMwNkJcdTMwODhcdTMwOEJcdTVCNTBcdTMwRENcdTMwRkNcdTMwRjNcdTMwNkVcdTc5RkJcdTUyRDVcdTc2RUVcdTZBMTlcbiAgICAgIC5hZGQoX3YzQS5jb3B5KGNlbnRlclNwYWNlR3Jhdml0eSkubXVsdGlwbHlTY2FsYXIodGhpcy5zZXR0aW5ncy5ncmF2aXR5UG93ZXIgKiBkZWx0YSkpIC8vIFx1NTkxNlx1NTI5Qlx1MzA2Qlx1MzA4OFx1MzA4Qlx1NzlGQlx1NTJENVx1OTFDRlxuICAgICAgLmFwcGx5TWF0cml4NChtYXRyaXhDZW50ZXJUb1dvcmxkKTsgLy8gdGFpbFx1MzA5MndvcmxkIHNwYWNlXHUzMDZCXHU2MjNCXHUzMDU5XG5cbiAgICAvLyBub3JtYWxpemUgYm9uZSBsZW5ndGhcbiAgICBfbmV4dFRhaWwuc3ViKF93b3JsZFNwYWNlUG9zaXRpb24pLm5vcm1hbGl6ZSgpLm11bHRpcGx5U2NhbGFyKHRoaXMuX3dvcmxkU3BhY2VCb25lTGVuZ3RoKS5hZGQoX3dvcmxkU3BhY2VQb3NpdGlvbik7XG5cbiAgICAvLyBDb2xsaXNpb25cdTMwNjdcdTc5RkJcdTUyRDVcbiAgICB0aGlzLl9jb2xsaXNpb24oX25leHRUYWlsKTtcblxuICAgIC8vIHVwZGF0ZSBwcmV2VGFpbCBhbmQgY3VycmVudFRhaWxcbiAgICBtYXRyaXhXb3JsZFRvQ2VudGVyID0gdGhpcy5fZ2V0TWF0cml4V29ybGRUb0NlbnRlcihfbWF0QSk7XG5cbiAgICB0aGlzLl9wcmV2VGFpbC5jb3B5KHRoaXMuX2N1cnJlbnRUYWlsKTtcbiAgICB0aGlzLl9jdXJyZW50VGFpbC5jb3B5KF92M0EuY29weShfbmV4dFRhaWwpLmFwcGx5TWF0cml4NChtYXRyaXhXb3JsZFRvQ2VudGVyKSk7XG5cbiAgICAvLyBBcHBseSByb3RhdGlvbiwgY29udmVydCB2ZWN0b3IzIHRoaW5nIGludG8gYWN0dWFsIHF1YXRlcm5pb25cbiAgICAvLyBPcmlnaW5hbCBVbmlWUk0gaXMgZG9pbmcgY2VudGVyIHVuaXQgY2FsY3VsdXMgYXQgaGVyZSBidXQgd2UncmUgZ29ubmEgZG8gdGhpcyBvbiBsb2NhbCB1bml0XG4gICAgY29uc3Qgd29ybGRTcGFjZUluaXRpYWxNYXRyaXhJbnYgPSBtYXQ0SW52ZXJ0Q29tcGF0KFxuICAgICAgX21hdEEuY29weSh0aGlzLl9wYXJlbnRNYXRyaXhXb3JsZCkubXVsdGlwbHkodGhpcy5faW5pdGlhbExvY2FsTWF0cml4KSxcbiAgICApO1xuICAgIGNvbnN0IGFwcGx5Um90YXRpb24gPSBfcXVhdEEuc2V0RnJvbVVuaXRWZWN0b3JzKFxuICAgICAgdGhpcy5fYm9uZUF4aXMsXG4gICAgICBfdjNBLmNvcHkoX25leHRUYWlsKS5hcHBseU1hdHJpeDQod29ybGRTcGFjZUluaXRpYWxNYXRyaXhJbnYpLm5vcm1hbGl6ZSgpLFxuICAgICk7XG5cbiAgICB0aGlzLmJvbmUucXVhdGVybmlvbi5jb3B5KHRoaXMuX2luaXRpYWxMb2NhbFJvdGF0aW9uKS5tdWx0aXBseShhcHBseVJvdGF0aW9uKTtcblxuICAgIC8vIFdlIG5lZWQgdG8gdXBkYXRlIGl0cyBtYXRyaXhXb3JsZCBtYW51YWxseSwgc2luY2Ugd2UgdHdlYWtlZCB0aGUgYm9uZSBieSBvdXIgaGFuZFxuICAgIHRoaXMuYm9uZS51cGRhdGVNYXRyaXgoKTtcbiAgICB0aGlzLmJvbmUubWF0cml4V29ybGQubXVsdGlwbHlNYXRyaWNlcyh0aGlzLl9wYXJlbnRNYXRyaXhXb3JsZCwgdGhpcy5ib25lLm1hdHJpeCk7XG4gIH1cblxuICAvKipcbiAgICogRG8gY29sbGlzaW9uIG1hdGggYWdhaW5zdCBldmVyeSBjb2xsaWRlcnMgYXR0YWNoZWQgdG8gdGhpcyBib25lLlxuICAgKlxuICAgKiBAcGFyYW0gdGFpbCBUaGUgdGFpbCB5b3Ugd2FudCB0byBwcm9jZXNzXG4gICAqL1xuICBwcml2YXRlIF9jb2xsaXNpb24odGFpbDogVEhSRUUuVmVjdG9yMyk6IHZvaWQge1xuICAgIHRoaXMuY29sbGlkZXJHcm91cHMuZm9yRWFjaCgoY29sbGlkZXJHcm91cCkgPT4ge1xuICAgICAgY29sbGlkZXJHcm91cC5jb2xsaWRlcnMuZm9yRWFjaCgoY29sbGlkZXIpID0+IHtcbiAgICAgICAgY29uc3QgZGlzdCA9IGNvbGxpZGVyLnNoYXBlLmNhbGN1bGF0ZUNvbGxpc2lvbihjb2xsaWRlci5tYXRyaXhXb3JsZCwgdGFpbCwgdGhpcy5zZXR0aW5ncy5oaXRSYWRpdXMsIF92M0EpO1xuXG4gICAgICAgIGlmIChkaXN0IDwgMC4wKSB7XG4gICAgICAgICAgLy8gaGl0XG4gICAgICAgICAgdGFpbC5hZGQoX3YzQS5tdWx0aXBseVNjYWxhcigtZGlzdCkpO1xuXG4gICAgICAgICAgLy8gbm9ybWFsaXplIGJvbmUgbGVuZ3RoXG4gICAgICAgICAgdGFpbC5zdWIoX3dvcmxkU3BhY2VQb3NpdGlvbikubm9ybWFsaXplKCkubXVsdGlwbHlTY2FsYXIodGhpcy5fd29ybGRTcGFjZUJvbmVMZW5ndGgpLmFkZChfd29ybGRTcGFjZVBvc2l0aW9uKTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIHRoZSB7QGxpbmsgX3dvcmxkU3BhY2VCb25lTGVuZ3RofS5cbiAgICogSW50ZW5kZWQgdG8gYmUgdXNlZCBpbiB7QGxpbmsgdXBkYXRlfS5cbiAgICovXG4gIHByaXZhdGUgX2NhbGNXb3JsZFNwYWNlQm9uZUxlbmd0aCgpOiB2b2lkIHtcbiAgICBfdjNBLnNldEZyb21NYXRyaXhQb3NpdGlvbih0aGlzLmJvbmUubWF0cml4V29ybGQpOyAvLyBnZXQgd29ybGQgcG9zaXRpb24gb2YgdGhpcy5ib25lXG5cbiAgICBpZiAodGhpcy5jaGlsZCkge1xuICAgICAgX3YzQi5zZXRGcm9tTWF0cml4UG9zaXRpb24odGhpcy5jaGlsZC5tYXRyaXhXb3JsZCk7IC8vIGdldCB3b3JsZCBwb3NpdGlvbiBvZiB0aGlzLmNoaWxkXG4gICAgfSBlbHNlIHtcbiAgICAgIF92M0IuY29weSh0aGlzLl9pbml0aWFsTG9jYWxDaGlsZFBvc2l0aW9uKTtcbiAgICAgIF92M0IuYXBwbHlNYXRyaXg0KHRoaXMuYm9uZS5tYXRyaXhXb3JsZCk7XG4gICAgfVxuXG4gICAgdGhpcy5fd29ybGRTcGFjZUJvbmVMZW5ndGggPSBfdjNBLnN1YihfdjNCKS5sZW5ndGgoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDcmVhdGUgYSBtYXRyaXggdGhhdCBjb252ZXJ0cyBjZW50ZXIgc3BhY2UgaW50byB3b3JsZCBzcGFjZS5cbiAgICogQHBhcmFtIHRhcmdldCBUYXJnZXQgbWF0cml4XG4gICAqL1xuICBwcml2YXRlIF9nZXRNYXRyaXhDZW50ZXJUb1dvcmxkKHRhcmdldDogVEhSRUUuTWF0cml4NCk6IFRIUkVFLk1hdHJpeDQge1xuICAgIGlmICh0aGlzLl9jZW50ZXIpIHtcbiAgICAgIHRhcmdldC5jb3B5KHRoaXMuX2NlbnRlci5tYXRyaXhXb3JsZCk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRhcmdldC5pZGVudGl0eSgpO1xuICAgIH1cblxuICAgIHJldHVybiB0YXJnZXQ7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbWF0cml4IHRoYXQgY29udmVydHMgd29ybGQgc3BhY2UgaW50byBjZW50ZXIgc3BhY2UuXG4gICAqIEBwYXJhbSB0YXJnZXQgVGFyZ2V0IG1hdHJpeFxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0TWF0cml4V29ybGRUb0NlbnRlcih0YXJnZXQ6IFRIUkVFLk1hdHJpeDQpOiBUSFJFRS5NYXRyaXg0IHtcbiAgICBpZiAodGhpcy5fY2VudGVyKSB7XG4gICAgICB0YXJnZXQuY29weSgodGhpcy5fY2VudGVyLnVzZXJEYXRhLmludmVyc2VDYWNoZVByb3h5IGFzIE1hdHJpeDRJbnZlcnNlQ2FjaGUpLmludmVyc2UpO1xuICAgIH0gZWxzZSB7XG4gICAgICB0YXJnZXQuaWRlbnRpdHkoKTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGFyZ2V0O1xuICB9XG59XG4iLCAiaW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnO1xuXG5jb25zdCBfbWF0QSA9IG5ldyBUSFJFRS5NYXRyaXg0KCk7XG5cbi8qKlxuICogQSBjb21wYXQgZnVuY3Rpb24gZm9yIGBNYXRyaXg0LmludmVydCgpYCAvIGBNYXRyaXg0LmdldEludmVyc2UoKWAuXG4gKiBgTWF0cml4NC5pbnZlcnQoKWAgaXMgaW50cm9kdWNlZCBpbiByMTIzIGFuZCBgTWF0cml4NC5nZXRJbnZlcnNlKClgIGVtaXRzIGEgd2FybmluZy5cbiAqIFdlIGFyZSBnb2luZyB0byB1c2UgdGhpcyBjb21wYXQgZm9yIGEgd2hpbGUuXG4gKiBAcGFyYW0gdGFyZ2V0IEEgdGFyZ2V0IG1hdHJpeFxuICovXG5leHBvcnQgZnVuY3Rpb24gbWF0NEludmVydENvbXBhdDxUIGV4dGVuZHMgVEhSRUUuTWF0cml4ND4odGFyZ2V0OiBUKTogVCB7XG4gIGlmICgodGFyZ2V0IGFzIGFueSkuaW52ZXJ0KSB7XG4gICAgdGFyZ2V0LmludmVydCgpO1xuICB9IGVsc2Uge1xuICAgICh0YXJnZXQgYXMgYW55KS5nZXRJbnZlcnNlKF9tYXRBLmNvcHkodGFyZ2V0KSk7XG4gIH1cblxuICByZXR1cm4gdGFyZ2V0O1xufVxuIiwgImltcG9ydCAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcbmltcG9ydCB7IG1hdDRJbnZlcnRDb21wYXQgfSBmcm9tICcuL21hdDRJbnZlcnRDb21wYXQnO1xuXG5leHBvcnQgY2xhc3MgTWF0cml4NEludmVyc2VDYWNoZSB7XG4gIC8qKlxuICAgKiBUaGUgdGFyZ2V0IG1hdHJpeC5cbiAgICovXG4gIHB1YmxpYyByZWFkb25seSBtYXRyaXg6IFRIUkVFLk1hdHJpeDQ7XG5cbiAgLyoqXG4gICAqIEEgY2FjaGUgb2YgaW52ZXJzZSBvZiBjdXJyZW50IG1hdHJpeC5cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX2ludmVyc2VDYWNoZSA9IG5ldyBUSFJFRS5NYXRyaXg0KCk7XG5cbiAgLyoqXG4gICAqIEEgZmxhZyB0aGF0IG1ha2VzIGl0IHdhbnQgdG8gcmVjYWxjdWxhdGUgaXRzIHtAbGluayBfaW52ZXJzZUNhY2hlfS5cbiAgICogV2lsbCBiZSBzZXQgYHRydWVgIHdoZW4gYGVsZW1lbnRzYCBhcmUgbXV0YXRlZCBhbmQgYmUgdXNlZCBpbiBgZ2V0SW52ZXJzZWAuXG4gICAqL1xuICBwcml2YXRlIF9zaG91bGRVcGRhdGVJbnZlcnNlID0gdHJ1ZTtcblxuICAvKipcbiAgICogVGhlIG9yaWdpbmFsIG9mIGBtYXRyaXguZWxlbWVudHNgXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IF9vcmlnaW5hbEVsZW1lbnRzOiBudW1iZXJbXTtcblxuICAvKipcbiAgICogSW52ZXJzZSBvZiBnaXZlbiBtYXRyaXguXG4gICAqIE5vdGUgdGhhdCBpdCB3aWxsIHJldHVybiBpdHMgaW50ZXJuYWwgcHJpdmF0ZSBpbnN0YW5jZS5cbiAgICogTWFrZSBzdXJlIGNvcHlpbmcgdGhpcyBiZWZvcmUgbXV0YXRlIHRoaXMuXG4gICAqL1xuICBwdWJsaWMgZ2V0IGludmVyc2UoKTogVEhSRUUuTWF0cml4NCB7XG4gICAgaWYgKHRoaXMuX3Nob3VsZFVwZGF0ZUludmVyc2UpIHtcbiAgICAgIHRoaXMuX2ludmVyc2VDYWNoZS5jb3B5KHRoaXMubWF0cml4KTtcbiAgICAgIG1hdDRJbnZlcnRDb21wYXQodGhpcy5faW52ZXJzZUNhY2hlKTtcbiAgICAgIHRoaXMuX3Nob3VsZFVwZGF0ZUludmVyc2UgPSBmYWxzZTtcbiAgICB9XG5cbiAgICByZXR1cm4gdGhpcy5faW52ZXJzZUNhY2hlO1xuICB9XG5cbiAgcHVibGljIGNvbnN0cnVjdG9yKG1hdHJpeDogVEhSRUUuTWF0cml4NCkge1xuICAgIHRoaXMubWF0cml4ID0gbWF0cml4O1xuXG4gICAgY29uc3QgaGFuZGxlcjogUHJveHlIYW5kbGVyPG51bWJlcltdPiA9IHtcbiAgICAgIHNldDogKG9iaiwgcHJvcDogYW55LCBuZXdWYWwpID0+IHtcbiAgICAgICAgdGhpcy5fc2hvdWxkVXBkYXRlSW52ZXJzZSA9IHRydWU7XG4gICAgICAgIG9ialtwcm9wXSA9IG5ld1ZhbDtcblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgIH0sXG4gICAgfTtcblxuICAgIHRoaXMuX29yaWdpbmFsRWxlbWVudHMgPSBtYXRyaXguZWxlbWVudHM7XG4gICAgbWF0cml4LmVsZW1lbnRzID0gbmV3IFByb3h5KG1hdHJpeC5lbGVtZW50cywgaGFuZGxlcik7XG4gIH1cblxuICBwdWJsaWMgcmV2ZXJ0KCk6IHZvaWQge1xuICAgIHRoaXMubWF0cml4LmVsZW1lbnRzID0gdGhpcy5fb3JpZ2luYWxFbGVtZW50cztcbiAgfVxufVxuIiwgImltcG9ydCB0eXBlICogYXMgVjBWUk0gZnJvbSAnQHBpeGl2L3R5cGVzLXZybS0wLjAnO1xuaW1wb3J0IHR5cGUgKiBhcyBWMVNwcmluZ0JvbmVTY2hlbWEgZnJvbSAnQHBpeGl2L3R5cGVzLXZybWMtc3ByaW5nYm9uZS0xLjAnO1xuaW1wb3J0ICogYXMgVEhSRUUgZnJvbSAndGhyZWUnO1xuaW1wb3J0IHR5cGUgeyBHTFRGLCBHTFRGTG9hZGVyUGx1Z2luLCBHTFRGUGFyc2VyIH0gZnJvbSAndGhyZWUvZXhhbXBsZXMvanNtL2xvYWRlcnMvR0xURkxvYWRlci5qcyc7XG5pbXBvcnQgeyBWUk1TcHJpbmdCb25lQ29sbGlkZXJIZWxwZXIsIFZSTVNwcmluZ0JvbmVKb2ludEhlbHBlciB9IGZyb20gJy4vaGVscGVycyc7XG5pbXBvcnQgeyBWUk1TcHJpbmdCb25lQ29sbGlkZXIgfSBmcm9tICcuL1ZSTVNwcmluZ0JvbmVDb2xsaWRlcic7XG5pbXBvcnQgdHlwZSB7IFZSTVNwcmluZ0JvbmVDb2xsaWRlckdyb3VwIH0gZnJvbSAnLi9WUk1TcHJpbmdCb25lQ29sbGlkZXJHcm91cCc7XG5pbXBvcnQgeyBWUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZUNhcHN1bGUgfSBmcm9tICcuL1ZSTVNwcmluZ0JvbmVDb2xsaWRlclNoYXBlQ2Fwc3VsZSc7XG5pbXBvcnQgeyBWUk1TcHJpbmdCb25lQ29sbGlkZXJTaGFwZVNwaGVyZSB9IGZyb20gJy4vVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVTcGhlcmUnO1xuaW1wb3J0IHsgVlJNU3ByaW5nQm9uZUpvaW50IH0gZnJvbSAnLi9WUk1TcHJpbmdCb25lSm9pbnQnO1xuaW1wb3J0IHR5cGUgeyBWUk1TcHJpbmdCb25lTG9hZGVyUGx1Z2luT3B0aW9ucyB9IGZyb20gJy4vVlJNU3ByaW5nQm9uZUxvYWRlclBsdWdpbk9wdGlvbnMnO1xuaW1wb3J0IHsgVlJNU3ByaW5nQm9uZU1hbmFnZXIgfSBmcm9tICcuL1ZSTVNwcmluZ0JvbmVNYW5hZ2VyJztcbmltcG9ydCB0eXBlIHsgVlJNU3ByaW5nQm9uZUpvaW50U2V0dGluZ3MgfSBmcm9tICcuL1ZSTVNwcmluZ0JvbmVKb2ludFNldHRpbmdzJztcbmltcG9ydCB7IEdMVEYgYXMgR0xURlNjaGVtYSB9IGZyb20gJ0BnbHRmLXRyYW5zZm9ybS9jb3JlJztcblxuLyoqXG4gKiBQb3NzaWJsZSBzcGVjIHZlcnNpb25zIGl0IHJlY29nbml6ZXMuXG4gKi9cbmNvbnN0IFBPU1NJQkxFX1NQRUNfVkVSU0lPTlMgPSBuZXcgU2V0KFsnMS4wJywgJzEuMC1iZXRhJ10pO1xuXG5leHBvcnQgY2xhc3MgVlJNU3ByaW5nQm9uZUxvYWRlclBsdWdpbiBpbXBsZW1lbnRzIEdMVEZMb2FkZXJQbHVnaW4ge1xuICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IEVYVEVOU0lPTl9OQU1FID0gJ1ZSTUNfc3ByaW5nQm9uZSc7XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgYW4gT2JqZWN0M0QgdG8gYWRkIHtAbGluayBWUk1TcHJpbmdCb25lSm9pbnRIZWxwZXJ9IHMuXG4gICAqIElmIG5vdCBzcGVjaWZpZWQsIGhlbHBlciB3aWxsIG5vdCBiZSBjcmVhdGVkLlxuICAgKiBJZiBgcmVuZGVyT3JkZXJgIGlzIHNldCB0byB0aGUgcm9vdCwgaGVscGVycyB3aWxsIGNvcHkgdGhlIHNhbWUgYHJlbmRlck9yZGVyYCAuXG4gICAqL1xuICBwdWJsaWMgam9pbnRIZWxwZXJSb290PzogVEhSRUUuT2JqZWN0M0Q7XG5cbiAgLyoqXG4gICAqIFNwZWNpZnkgYW4gT2JqZWN0M0QgdG8gYWRkIHtAbGluayBWUk1TcHJpbmdCb25lSm9pbnRIZWxwZXJ9IHMuXG4gICAqIElmIG5vdCBzcGVjaWZpZWQsIGhlbHBlciB3aWxsIG5vdCBiZSBjcmVhdGVkLlxuICAgKiBJZiBgcmVuZGVyT3JkZXJgIGlzIHNldCB0byB0aGUgcm9vdCwgaGVscGVycyB3aWxsIGNvcHkgdGhlIHNhbWUgYHJlbmRlck9yZGVyYCAuXG4gICAqL1xuICBwdWJsaWMgY29sbGlkZXJIZWxwZXJSb290PzogVEhSRUUuT2JqZWN0M0Q7XG5cbiAgcHVibGljIHJlYWRvbmx5IHBhcnNlcjogR0xURlBhcnNlcjtcblxuICBwdWJsaWMgZ2V0IG5hbWUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gVlJNU3ByaW5nQm9uZUxvYWRlclBsdWdpbi5FWFRFTlNJT05fTkFNRTtcbiAgfVxuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwYXJzZXI6IEdMVEZQYXJzZXIsIG9wdGlvbnM/OiBWUk1TcHJpbmdCb25lTG9hZGVyUGx1Z2luT3B0aW9ucykge1xuICAgIHRoaXMucGFyc2VyID0gcGFyc2VyO1xuXG4gICAgdGhpcy5qb2ludEhlbHBlclJvb3QgPSBvcHRpb25zPy5qb2ludEhlbHBlclJvb3Q7XG4gICAgdGhpcy5jb2xsaWRlckhlbHBlclJvb3QgPSBvcHRpb25zPy5jb2xsaWRlckhlbHBlclJvb3Q7XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgYWZ0ZXJSb290KGdsdGY6IEdMVEYpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBnbHRmLnVzZXJEYXRhLnZybVNwcmluZ0JvbmVNYW5hZ2VyID0gYXdhaXQgdGhpcy5faW1wb3J0KGdsdGYpO1xuICB9XG5cbiAgLyoqXG4gICAqIEltcG9ydCBzcHJpbmcgYm9uZXMgZnJvbSBhIEdMVEYgYW5kIHJldHVybiBhIHtAbGluayBWUk1TcHJpbmdCb25lTWFuYWdlcn0uXG4gICAqIEl0IG1pZ2h0IHJldHVybiBgbnVsbGAgaW5zdGVhZCB3aGVuIGl0IGRvZXMgbm90IG5lZWQgdG8gYmUgY3JlYXRlZCBvciBzb21ldGhpbmcgZ28gd3JvbmcuXG4gICAqXG4gICAqIEBwYXJhbSBnbHRmIEEgcGFyc2VkIHJlc3VsdCBvZiBHTFRGIHRha2VuIGZyb20gR0xURkxvYWRlclxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBfaW1wb3J0KGdsdGY6IEdMVEYpOiBQcm9taXNlPFZSTVNwcmluZ0JvbmVNYW5hZ2VyIHwgbnVsbD4ge1xuICAgIGNvbnN0IHYxUmVzdWx0ID0gYXdhaXQgdGhpcy5fdjFJbXBvcnQoZ2x0Zik7XG4gICAgaWYgKHYxUmVzdWx0ICE9IG51bGwpIHtcbiAgICAgIHJldHVybiB2MVJlc3VsdDtcbiAgICB9XG5cbiAgICBjb25zdCB2MFJlc3VsdCA9IGF3YWl0IHRoaXMuX3YwSW1wb3J0KGdsdGYpO1xuICAgIGlmICh2MFJlc3VsdCAhPSBudWxsKSB7XG4gICAgICByZXR1cm4gdjBSZXN1bHQ7XG4gICAgfVxuXG4gICAgcmV0dXJuIG51bGw7XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIF92MUltcG9ydChnbHRmOiBHTFRGKTogUHJvbWlzZTxWUk1TcHJpbmdCb25lTWFuYWdlciB8IG51bGw+IHtcbiAgICBjb25zdCBqc29uID0gZ2x0Zi5wYXJzZXIuanNvbiBhcyBHTFRGU2NoZW1hLklHTFRGO1xuXG4gICAgLy8gZWFybHkgYWJvcnQgaWYgaXQgZG9lc24ndCB1c2Ugc3ByaW5nIGJvbmVzXG4gICAgY29uc3QgaXNTcHJpbmdCb25lVXNlZCA9IGpzb24uZXh0ZW5zaW9uc1VzZWQ/LmluZGV4T2YoVlJNU3ByaW5nQm9uZUxvYWRlclBsdWdpbi5FWFRFTlNJT05fTkFNRSkgIT09IC0xO1xuICAgIGlmICghaXNTcHJpbmdCb25lVXNlZCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgbWFuYWdlciA9IG5ldyBWUk1TcHJpbmdCb25lTWFuYWdlcigpO1xuXG4gICAgY29uc3QgdGhyZWVOb2RlczogVEhSRUUuT2JqZWN0M0RbXSA9IGF3YWl0IGdsdGYucGFyc2VyLmdldERlcGVuZGVuY2llcygnbm9kZScpO1xuXG4gICAgY29uc3QgZXh0ZW5zaW9uID0ganNvbi5leHRlbnNpb25zPy5bVlJNU3ByaW5nQm9uZUxvYWRlclBsdWdpbi5FWFRFTlNJT05fTkFNRV0gYXNcbiAgICAgIHwgVjFTcHJpbmdCb25lU2NoZW1hLlZSTUNTcHJpbmdCb25lXG4gICAgICB8IHVuZGVmaW5lZDtcbiAgICBpZiAoIWV4dGVuc2lvbikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3Qgc3BlY1ZlcnNpb24gPSBleHRlbnNpb24uc3BlY1ZlcnNpb247XG4gICAgaWYgKCFQT1NTSUJMRV9TUEVDX1ZFUlNJT05TLmhhcyhzcGVjVmVyc2lvbikpIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFZSTVNwcmluZ0JvbmVMb2FkZXJQbHVnaW46IFVua25vd24gJHtWUk1TcHJpbmdCb25lTG9hZGVyUGx1Z2luLkVYVEVOU0lPTl9OQU1FfSBzcGVjVmVyc2lvbiBcIiR7c3BlY1ZlcnNpb259XCJgLFxuICAgICAgKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbGxpZGVycyA9IGV4dGVuc2lvbi5jb2xsaWRlcnM/Lm1hcCgoc2NoZW1hQ29sbGlkZXIsIGlDb2xsaWRlcikgPT4ge1xuICAgICAgY29uc3Qgbm9kZSA9IHRocmVlTm9kZXNbc2NoZW1hQ29sbGlkZXIubm9kZSFdO1xuICAgICAgY29uc3Qgc2NoZW1hU2hhcGUgPSBzY2hlbWFDb2xsaWRlci5zaGFwZSE7XG5cbiAgICAgIGlmIChzY2hlbWFTaGFwZS5zcGhlcmUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2ltcG9ydFNwaGVyZUNvbGxpZGVyKG5vZGUsIHtcbiAgICAgICAgICBvZmZzZXQ6IG5ldyBUSFJFRS5WZWN0b3IzKCkuZnJvbUFycmF5KHNjaGVtYVNoYXBlLnNwaGVyZS5vZmZzZXQgPz8gWzAuMCwgMC4wLCAwLjBdKSxcbiAgICAgICAgICByYWRpdXM6IHNjaGVtYVNoYXBlLnNwaGVyZS5yYWRpdXMgPz8gMC4wLFxuICAgICAgICB9KTtcbiAgICAgIH0gZWxzZSBpZiAoc2NoZW1hU2hhcGUuY2Fwc3VsZSkge1xuICAgICAgICByZXR1cm4gdGhpcy5faW1wb3J0Q2Fwc3VsZUNvbGxpZGVyKG5vZGUsIHtcbiAgICAgICAgICBvZmZzZXQ6IG5ldyBUSFJFRS5WZWN0b3IzKCkuZnJvbUFycmF5KHNjaGVtYVNoYXBlLmNhcHN1bGUub2Zmc2V0ID8/IFswLjAsIDAuMCwgMC4wXSksXG4gICAgICAgICAgcmFkaXVzOiBzY2hlbWFTaGFwZS5jYXBzdWxlLnJhZGl1cyA/PyAwLjAsXG4gICAgICAgICAgdGFpbDogbmV3IFRIUkVFLlZlY3RvcjMoKS5mcm9tQXJyYXkoc2NoZW1hU2hhcGUuY2Fwc3VsZS50YWlsID8/IFswLjAsIDAuMCwgMC4wXSksXG4gICAgICAgIH0pO1xuICAgICAgfVxuXG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFZSTVNwcmluZ0JvbmVMb2FkZXJQbHVnaW46IFRoZSBjb2xsaWRlciAjJHtpQ29sbGlkZXJ9IGhhcyBubyB2YWxpZCBzaGFwZWApO1xuICAgIH0pO1xuXG4gICAgY29uc3QgY29sbGlkZXJHcm91cHMgPSBleHRlbnNpb24uY29sbGlkZXJHcm91cHM/Lm1hcChcbiAgICAgIChzY2hlbWFDb2xsaWRlckdyb3VwLCBpQ29sbGlkZXJHcm91cCk6IFZSTVNwcmluZ0JvbmVDb2xsaWRlckdyb3VwID0+IHtcbiAgICAgICAgY29uc3QgY29scyA9IChzY2hlbWFDb2xsaWRlckdyb3VwLmNvbGxpZGVycyA/PyBbXSkubWFwKChpQ29sbGlkZXIpID0+IHtcbiAgICAgICAgICBjb25zdCBjb2wgPSBjb2xsaWRlcnM/LltpQ29sbGlkZXJdO1xuXG4gICAgICAgICAgaWYgKGNvbCA9PSBudWxsKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgICAgICAgIGBWUk1TcHJpbmdCb25lTG9hZGVyUGx1Z2luOiBUaGUgY29sbGlkZXJHcm91cCAjJHtpQ29sbGlkZXJHcm91cH0gYXR0ZW1wdGVkIHRvIHVzZSBhIGNvbGxpZGVyICMke2lDb2xsaWRlcn0gYnV0IG5vdCBmb3VuZGAsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBjb2w7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgY29sbGlkZXJzOiBjb2xzLFxuICAgICAgICAgIG5hbWU6IHNjaGVtYUNvbGxpZGVyR3JvdXAubmFtZSxcbiAgICAgICAgfTtcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIGV4dGVuc2lvbi5zcHJpbmdzPy5mb3JFYWNoKChzY2hlbWFTcHJpbmcsIGlTcHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IHNjaGVtYUpvaW50cyA9IHNjaGVtYVNwcmluZy5qb2ludHM7XG5cbiAgICAgIC8vIHByZXBhcmUgY29sbGlkZXJzXG4gICAgICBjb25zdCBjb2xsaWRlckdyb3Vwc0ZvclNwcmluZyA9IHNjaGVtYVNwcmluZy5jb2xsaWRlckdyb3Vwcz8ubWFwKChpQ29sbGlkZXJHcm91cCkgPT4ge1xuICAgICAgICBjb25zdCBncm91cCA9IGNvbGxpZGVyR3JvdXBzPy5baUNvbGxpZGVyR3JvdXBdO1xuXG4gICAgICAgIGlmIChncm91cCA9PSBudWxsKSB7XG4gICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFxuICAgICAgICAgICAgYFZSTVNwcmluZ0JvbmVMb2FkZXJQbHVnaW46IFRoZSBzcHJpbmcgIyR7aVNwcmluZ30gYXR0ZW1wdGVkIHRvIHVzZSBhIGNvbGxpZGVyR3JvdXAgJHtpQ29sbGlkZXJHcm91cH0gYnV0IG5vdCBmb3VuZGAsXG4gICAgICAgICAgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBncm91cDtcbiAgICAgIH0pO1xuXG4gICAgICBjb25zdCBjZW50ZXIgPSBzY2hlbWFTcHJpbmcuY2VudGVyICE9IG51bGwgPyB0aHJlZU5vZGVzW3NjaGVtYVNwcmluZy5jZW50ZXJdIDogdW5kZWZpbmVkO1xuXG4gICAgICBsZXQgcHJldlNjaGVtYUpvaW50OiBWMVNwcmluZ0JvbmVTY2hlbWEuU3ByaW5nQm9uZUpvaW50IHwgdW5kZWZpbmVkO1xuICAgICAgc2NoZW1hSm9pbnRzLmZvckVhY2goKHNjaGVtYUpvaW50KSA9PiB7XG4gICAgICAgIGlmIChwcmV2U2NoZW1hSm9pbnQpIHtcbiAgICAgICAgICAvLyBwcmVwYXJlIG5vZGVcbiAgICAgICAgICBjb25zdCBub2RlSW5kZXggPSBwcmV2U2NoZW1hSm9pbnQubm9kZTtcbiAgICAgICAgICBjb25zdCBub2RlID0gdGhyZWVOb2Rlc1tub2RlSW5kZXhdO1xuICAgICAgICAgIGNvbnN0IGNoaWxkSW5kZXggPSBzY2hlbWFKb2ludC5ub2RlO1xuICAgICAgICAgIGNvbnN0IGNoaWxkID0gdGhyZWVOb2Rlc1tjaGlsZEluZGV4XTtcblxuICAgICAgICAgIC8vIHByZXBhcmUgc2V0dGluZ1xuICAgICAgICAgIGNvbnN0IHNldHRpbmc6IFBhcnRpYWw8VlJNU3ByaW5nQm9uZUpvaW50U2V0dGluZ3M+ID0ge1xuICAgICAgICAgICAgaGl0UmFkaXVzOiBwcmV2U2NoZW1hSm9pbnQuaGl0UmFkaXVzLFxuICAgICAgICAgICAgZHJhZ0ZvcmNlOiBwcmV2U2NoZW1hSm9pbnQuZHJhZ0ZvcmNlLFxuICAgICAgICAgICAgZ3Jhdml0eVBvd2VyOiBwcmV2U2NoZW1hSm9pbnQuZ3Jhdml0eVBvd2VyLFxuICAgICAgICAgICAgc3RpZmZuZXNzOiBwcmV2U2NoZW1hSm9pbnQuc3RpZmZuZXNzLFxuICAgICAgICAgICAgZ3Jhdml0eURpcjpcbiAgICAgICAgICAgICAgcHJldlNjaGVtYUpvaW50LmdyYXZpdHlEaXIgIT0gbnVsbFxuICAgICAgICAgICAgICAgID8gbmV3IFRIUkVFLlZlY3RvcjMoKS5mcm9tQXJyYXkocHJldlNjaGVtYUpvaW50LmdyYXZpdHlEaXIpXG4gICAgICAgICAgICAgICAgOiB1bmRlZmluZWQsXG4gICAgICAgICAgfTtcblxuICAgICAgICAgIC8vIGNyZWF0ZSBzcHJpbmcgYm9uZXNcbiAgICAgICAgICBjb25zdCBqb2ludCA9IHRoaXMuX2ltcG9ydEpvaW50KG5vZGUsIGNoaWxkLCBzZXR0aW5nLCBjb2xsaWRlckdyb3Vwc0ZvclNwcmluZyk7XG4gICAgICAgICAgaWYgKGNlbnRlcikge1xuICAgICAgICAgICAgam9pbnQuY2VudGVyID0gY2VudGVyO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIG1hbmFnZXIuYWRkSm9pbnQoam9pbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcHJldlNjaGVtYUpvaW50ID0gc2NoZW1hSm9pbnQ7XG4gICAgICB9KTtcbiAgICB9KTtcblxuICAgIC8vIGluaXQgc3ByaW5nIGJvbmVzXG4gICAgbWFuYWdlci5zZXRJbml0U3RhdGUoKTtcblxuICAgIHJldHVybiBtYW5hZ2VyO1xuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBfdjBJbXBvcnQoZ2x0ZjogR0xURik6IFByb21pc2U8VlJNU3ByaW5nQm9uZU1hbmFnZXIgfCBudWxsPiB7XG4gICAgY29uc3QganNvbiA9IGdsdGYucGFyc2VyLmpzb24gYXMgR0xURlNjaGVtYS5JR0xURjtcblxuICAgIC8vIGVhcmx5IGFib3J0IGlmIGl0IGRvZXNuJ3QgdXNlIHZybVxuICAgIGNvbnN0IGlzVlJNVXNlZCA9IGpzb24uZXh0ZW5zaW9uc1VzZWQ/LmluZGV4T2YoJ1ZSTScpICE9PSAtMTtcbiAgICBpZiAoIWlzVlJNVXNlZCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gZWFybHkgYWJvcnQgaWYgaXQgZG9lc24ndCBoYXZlIGJvbmUgZ3JvdXBzXG4gICAgY29uc3QgZXh0ZW5zaW9uID0ganNvbi5leHRlbnNpb25zPy5bJ1ZSTSddIGFzIFYwVlJNLlZSTSB8IHVuZGVmaW5lZDtcbiAgICBjb25zdCBzY2hlbWFTZWNvbmRhcnlBbmltYXRpb24gPSBleHRlbnNpb24/LnNlY29uZGFyeUFuaW1hdGlvbjtcbiAgICBpZiAoIXNjaGVtYVNlY29uZGFyeUFuaW1hdGlvbikge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3Qgc2NoZW1hQm9uZUdyb3VwcyA9IHNjaGVtYVNlY29uZGFyeUFuaW1hdGlvbj8uYm9uZUdyb3VwcztcbiAgICBpZiAoIXNjaGVtYUJvbmVHcm91cHMpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IG1hbmFnZXIgPSBuZXcgVlJNU3ByaW5nQm9uZU1hbmFnZXIoKTtcblxuICAgIGNvbnN0IHRocmVlTm9kZXM6IFRIUkVFLk9iamVjdDNEW10gPSBhd2FpdCBnbHRmLnBhcnNlci5nZXREZXBlbmRlbmNpZXMoJ25vZGUnKTtcblxuICAgIGNvbnN0IGNvbGxpZGVyR3JvdXBzID0gc2NoZW1hU2Vjb25kYXJ5QW5pbWF0aW9uLmNvbGxpZGVyR3JvdXBzPy5tYXAoXG4gICAgICAoc2NoZW1hQ29sbGlkZXJHcm91cCk6IFZSTVNwcmluZ0JvbmVDb2xsaWRlckdyb3VwID0+IHtcbiAgICAgICAgY29uc3Qgbm9kZSA9IHRocmVlTm9kZXNbc2NoZW1hQ29sbGlkZXJHcm91cC5ub2RlIV07XG4gICAgICAgIGNvbnN0IGNvbGxpZGVycyA9IChzY2hlbWFDb2xsaWRlckdyb3VwLmNvbGxpZGVycyA/PyBbXSkubWFwKChzY2hlbWFDb2xsaWRlciwgaUNvbGxpZGVyKSA9PiB7XG4gICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gbmV3IFRIUkVFLlZlY3RvcjMoMC4wLCAwLjAsIDAuMCk7XG4gICAgICAgICAgaWYgKHNjaGVtYUNvbGxpZGVyLm9mZnNldCkge1xuICAgICAgICAgICAgb2Zmc2V0LnNldChcbiAgICAgICAgICAgICAgc2NoZW1hQ29sbGlkZXIub2Zmc2V0LnggPz8gMC4wLFxuICAgICAgICAgICAgICBzY2hlbWFDb2xsaWRlci5vZmZzZXQueSA/PyAwLjAsXG4gICAgICAgICAgICAgIHNjaGVtYUNvbGxpZGVyLm9mZnNldC56ID8gLXNjaGVtYUNvbGxpZGVyLm9mZnNldC56IDogMC4wLCAvLyB6IGlzIG9wcG9zaXRlIGluIFZSTTAuMFxuICAgICAgICAgICAgKTtcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4gdGhpcy5faW1wb3J0U3BoZXJlQ29sbGlkZXIobm9kZSwge1xuICAgICAgICAgICAgb2Zmc2V0LFxuICAgICAgICAgICAgcmFkaXVzOiBzY2hlbWFDb2xsaWRlci5yYWRpdXMgPz8gMC4wLFxuICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4geyBjb2xsaWRlcnMgfTtcbiAgICAgIH0sXG4gICAgKTtcblxuICAgIC8vIGltcG9ydCBzcHJpbmcgYm9uZXMgZm9yIGVhY2ggc3ByaW5nIGJvbmUgZ3JvdXBzXG4gICAgc2NoZW1hQm9uZUdyb3Vwcz8uZm9yRWFjaCgoc2NoZW1hQm9uZUdyb3VwLCBpQm9uZUdyb3VwKSA9PiB7XG4gICAgICBjb25zdCByb290SW5kaWNlcyA9IHNjaGVtYUJvbmVHcm91cC5ib25lcztcbiAgICAgIGlmICghcm9vdEluZGljZXMpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICByb290SW5kaWNlcy5mb3JFYWNoKChyb290SW5kZXgpID0+IHtcbiAgICAgICAgY29uc3Qgcm9vdCA9IHRocmVlTm9kZXNbcm9vdEluZGV4XTtcblxuICAgICAgICAvLyBwcmVwYXJlIHNldHRpbmdcbiAgICAgICAgY29uc3QgZ3Jhdml0eURpciA9IG5ldyBUSFJFRS5WZWN0b3IzKCk7XG4gICAgICAgIGlmIChzY2hlbWFCb25lR3JvdXAuZ3Jhdml0eURpcikge1xuICAgICAgICAgIGdyYXZpdHlEaXIuc2V0KFxuICAgICAgICAgICAgc2NoZW1hQm9uZUdyb3VwLmdyYXZpdHlEaXIueCA/PyAwLjAsXG4gICAgICAgICAgICBzY2hlbWFCb25lR3JvdXAuZ3Jhdml0eURpci55ID8/IDAuMCxcbiAgICAgICAgICAgIHNjaGVtYUJvbmVHcm91cC5ncmF2aXR5RGlyLnogPz8gMC4wLFxuICAgICAgICAgICk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgZ3Jhdml0eURpci5zZXQoMC4wLCAtMS4wLCAwLjApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY2VudGVyID0gc2NoZW1hQm9uZUdyb3VwLmNlbnRlciAhPSBudWxsID8gdGhyZWVOb2Rlc1tzY2hlbWFCb25lR3JvdXAuY2VudGVyXSA6IHVuZGVmaW5lZDtcblxuICAgICAgICBjb25zdCBzZXR0aW5nOiBQYXJ0aWFsPFZSTVNwcmluZ0JvbmVKb2ludFNldHRpbmdzPiA9IHtcbiAgICAgICAgICBoaXRSYWRpdXM6IHNjaGVtYUJvbmVHcm91cC5oaXRSYWRpdXMsXG4gICAgICAgICAgZHJhZ0ZvcmNlOiBzY2hlbWFCb25lR3JvdXAuZHJhZ0ZvcmNlLFxuICAgICAgICAgIGdyYXZpdHlQb3dlcjogc2NoZW1hQm9uZUdyb3VwLmdyYXZpdHlQb3dlcixcbiAgICAgICAgICBzdGlmZm5lc3M6IHNjaGVtYUJvbmVHcm91cC5zdGlmZmluZXNzLFxuICAgICAgICAgIGdyYXZpdHlEaXIsXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gcHJlcGFyZSBjb2xsaWRlcnNcbiAgICAgICAgY29uc3QgY29sbGlkZXJHcm91cHNGb3JTcHJpbmcgPSBzY2hlbWFCb25lR3JvdXAuY29sbGlkZXJHcm91cHM/Lm1hcCgoaUNvbGxpZGVyR3JvdXApID0+IHtcbiAgICAgICAgICBjb25zdCBncm91cCA9IGNvbGxpZGVyR3JvdXBzPy5baUNvbGxpZGVyR3JvdXBdO1xuXG4gICAgICAgICAgaWYgKGdyb3VwID09IG51bGwpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcbiAgICAgICAgICAgICAgYFZSTVNwcmluZ0JvbmVMb2FkZXJQbHVnaW46IFRoZSBzcHJpbmcgIyR7aUJvbmVHcm91cH0gYXR0ZW1wdGVkIHRvIHVzZSBhIGNvbGxpZGVyR3JvdXAgJHtpQ29sbGlkZXJHcm91cH0gYnV0IG5vdCBmb3VuZGAsXG4gICAgICAgICAgICApO1xuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBncm91cDtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gY3JlYXRlIHNwcmluZyBib25lc1xuICAgICAgICByb290LnRyYXZlcnNlKChub2RlKSA9PiB7XG4gICAgICAgICAgY29uc3QgY2hpbGQ6IFRIUkVFLk9iamVjdDNEIHwgbnVsbCA9IG5vZGUuY2hpbGRyZW5bMF0gPz8gbnVsbDtcblxuICAgICAgICAgIGNvbnN0IGpvaW50ID0gdGhpcy5faW1wb3J0Sm9pbnQobm9kZSwgY2hpbGQsIHNldHRpbmcsIGNvbGxpZGVyR3JvdXBzRm9yU3ByaW5nKTtcbiAgICAgICAgICBpZiAoY2VudGVyKSB7XG4gICAgICAgICAgICBqb2ludC5jZW50ZXIgPSBjZW50ZXI7XG4gICAgICAgICAgfVxuXG4gICAgICAgICAgbWFuYWdlci5hZGRKb2ludChqb2ludCk7XG4gICAgICAgIH0pO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICAvLyBpbml0IHNwcmluZyBib25lc1xuICAgIGdsdGYuc2NlbmUudXBkYXRlTWF0cml4V29ybGQoKTtcbiAgICBtYW5hZ2VyLnNldEluaXRTdGF0ZSgpO1xuXG4gICAgcmV0dXJuIG1hbmFnZXI7XG4gIH1cblxuICBwcml2YXRlIF9pbXBvcnRKb2ludChcbiAgICBub2RlOiBUSFJFRS5PYmplY3QzRCxcbiAgICBjaGlsZDogVEhSRUUuT2JqZWN0M0QsXG4gICAgc2V0dGluZz86IFBhcnRpYWw8VlJNU3ByaW5nQm9uZUpvaW50U2V0dGluZ3M+LFxuICAgIGNvbGxpZGVyR3JvdXBzRm9yU3ByaW5nPzogVlJNU3ByaW5nQm9uZUNvbGxpZGVyR3JvdXBbXSxcbiAgKTogVlJNU3ByaW5nQm9uZUpvaW50IHtcbiAgICBjb25zdCBzcHJpbmdCb25lID0gbmV3IFZSTVNwcmluZ0JvbmVKb2ludChub2RlLCBjaGlsZCwgc2V0dGluZywgY29sbGlkZXJHcm91cHNGb3JTcHJpbmcpO1xuXG4gICAgaWYgKHRoaXMuam9pbnRIZWxwZXJSb290KSB7XG4gICAgICBjb25zdCBoZWxwZXIgPSBuZXcgVlJNU3ByaW5nQm9uZUpvaW50SGVscGVyKHNwcmluZ0JvbmUpO1xuICAgICAgdGhpcy5qb2ludEhlbHBlclJvb3QuYWRkKGhlbHBlcik7XG4gICAgICBoZWxwZXIucmVuZGVyT3JkZXIgPSB0aGlzLmpvaW50SGVscGVyUm9vdC5yZW5kZXJPcmRlcjtcbiAgICB9XG5cbiAgICByZXR1cm4gc3ByaW5nQm9uZTtcbiAgfVxuXG4gIHByaXZhdGUgX2ltcG9ydFNwaGVyZUNvbGxpZGVyKFxuICAgIGRlc3RpbmF0aW9uOiBUSFJFRS5PYmplY3QzRCxcbiAgICBwYXJhbXM6IHtcbiAgICAgIG9mZnNldDogVEhSRUUuVmVjdG9yMztcbiAgICAgIHJhZGl1czogbnVtYmVyO1xuICAgIH0sXG4gICk6IFZSTVNwcmluZ0JvbmVDb2xsaWRlciB7XG4gICAgY29uc3QgeyBvZmZzZXQsIHJhZGl1cyB9ID0gcGFyYW1zO1xuXG4gICAgY29uc3Qgc2hhcGUgPSBuZXcgVlJNU3ByaW5nQm9uZUNvbGxpZGVyU2hhcGVTcGhlcmUoeyBvZmZzZXQsIHJhZGl1cyB9KTtcblxuICAgIGNvbnN0IGNvbGxpZGVyID0gbmV3IFZSTVNwcmluZ0JvbmVDb2xsaWRlcihzaGFwZSk7XG5cbiAgICBkZXN0aW5hdGlvbi5hZGQoY29sbGlkZXIpO1xuXG4gICAgaWYgKHRoaXMuY29sbGlkZXJIZWxwZXJSb290KSB7XG4gICAgICBjb25zdCBoZWxwZXIgPSBuZXcgVlJNU3ByaW5nQm9uZUNvbGxpZGVySGVscGVyKGNvbGxpZGVyKTtcbiAgICAgIHRoaXMuY29sbGlkZXJIZWxwZXJSb290LmFkZChoZWxwZXIpO1xuICAgICAgaGVscGVyLnJlbmRlck9yZGVyID0gdGhpcy5jb2xsaWRlckhlbHBlclJvb3QucmVuZGVyT3JkZXI7XG4gICAgfVxuXG4gICAgcmV0dXJuIGNvbGxpZGVyO1xuICB9XG5cbiAgcHJpdmF0ZSBfaW1wb3J0Q2Fwc3VsZUNvbGxpZGVyKFxuICAgIGRlc3RpbmF0aW9uOiBUSFJFRS5PYmplY3QzRCxcbiAgICBwYXJhbXM6IHtcbiAgICAgIG9mZnNldDogVEhSRUUuVmVjdG9yMztcbiAgICAgIHJhZGl1czogbnVtYmVyO1xuICAgICAgdGFpbDogVEhSRUUuVmVjdG9yMztcbiAgICB9LFxuICApOiBWUk1TcHJpbmdCb25lQ29sbGlkZXIge1xuICAgIGNvbnN0IHsgb2Zmc2V0LCByYWRpdXMsIHRhaWwgfSA9IHBhcmFtcztcblxuICAgIGNvbnN0IHNoYXBlID0gbmV3IFZSTVNwcmluZ0JvbmVDb2xsaWRlclNoYXBlQ2Fwc3VsZSh7IG9mZnNldCwgcmFkaXVzLCB0YWlsIH0pO1xuXG4gICAgY29uc3QgY29sbGlkZXIgPSBuZXcgVlJNU3ByaW5nQm9uZUNvbGxpZGVyKHNoYXBlKTtcblxuICAgIGRlc3RpbmF0aW9uLmFkZChjb2xsaWRlcik7XG5cbiAgICBpZiAodGhpcy5jb2xsaWRlckhlbHBlclJvb3QpIHtcbiAgICAgIGNvbnN0IGhlbHBlciA9IG5ldyBWUk1TcHJpbmdCb25lQ29sbGlkZXJIZWxwZXIoY29sbGlkZXIpO1xuICAgICAgdGhpcy5jb2xsaWRlckhlbHBlclJvb3QuYWRkKGhlbHBlcik7XG4gICAgICBoZWxwZXIucmVuZGVyT3JkZXIgPSB0aGlzLmNvbGxpZGVySGVscGVyUm9vdC5yZW5kZXJPcmRlcjtcbiAgICB9XG5cbiAgICByZXR1cm4gY29sbGlkZXI7XG4gIH1cbn1cbiIsICJpbXBvcnQgdHlwZSAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcblxuZXhwb3J0IGZ1bmN0aW9uIHRyYXZlcnNlQW5jZXN0b3JzRnJvbVJvb3Qob2JqZWN0OiBUSFJFRS5PYmplY3QzRCwgY2FsbGJhY2s6IChvYmplY3Q6IFRIUkVFLk9iamVjdDNEKSA9PiB2b2lkKTogdm9pZCB7XG4gIGNvbnN0IGFuY2VzdG9yczogVEhSRUUuT2JqZWN0M0RbXSA9IFtdO1xuXG4gIGxldCBoZWFkOiBUSFJFRS5PYmplY3QzRCB8IG51bGwgPSBvYmplY3Q7XG4gIHdoaWxlIChoZWFkICE9PSBudWxsKSB7XG4gICAgYW5jZXN0b3JzLnVuc2hpZnQoaGVhZCk7XG4gICAgaGVhZCA9IGhlYWQucGFyZW50O1xuICB9XG5cbiAgYW5jZXN0b3JzLmZvckVhY2goKGFuY2VzdG9yKSA9PiB7XG4gICAgY2FsbGJhY2soYW5jZXN0b3IpO1xuICB9KTtcbn1cbiIsICJpbXBvcnQgdHlwZSAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcblxuLyoqXG4gKiBUcmF2ZXJzZSBjaGlsZHJlbiBvZiBnaXZlbiBvYmplY3QgYW5kIGV4ZWN1dGUgZ2l2ZW4gY2FsbGJhY2suXG4gKiBUaGUgZ2l2ZW4gb2JqZWN0IGl0c2VsZiB3b250IGJlIGdpdmVuIHRvIHRoZSBjYWxsYmFjay5cbiAqIElmIHRoZSByZXR1cm4gdmFsdWUgb2YgdGhlIGNhbGxiYWNrIGlzIGB0cnVlYCwgaXQgd2lsbCBoYWx0IHRoZSB0cmF2ZXJzYWwgb2YgaXRzIGNoaWxkcmVuLlxuICogQHBhcmFtIG9iamVjdCBBIHJvb3Qgb2JqZWN0XG4gKiBAcGFyYW0gY2FsbGJhY2sgQSBjYWxsYmFjayBmdW5jdGlvbiBjYWxsZWQgZm9yIGVhY2ggY2hpbGRyZW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRyYXZlcnNlQ2hpbGRyZW5VbnRpbENvbmRpdGlvbk1ldChcbiAgb2JqZWN0OiBUSFJFRS5PYmplY3QzRCxcbiAgY2FsbGJhY2s6IChvYmplY3Q6IFRIUkVFLk9iamVjdDNEKSA9PiBib29sZWFuLFxuKTogdm9pZCB7XG4gIG9iamVjdC5jaGlsZHJlbi5mb3JFYWNoKChjaGlsZCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IGNhbGxiYWNrKGNoaWxkKTtcbiAgICBpZiAoIXJlc3VsdCkge1xuICAgICAgdHJhdmVyc2VDaGlsZHJlblVudGlsQ29uZGl0aW9uTWV0KGNoaWxkLCBjYWxsYmFjayk7XG4gICAgfVxuICB9KTtcbn1cbiIsICJpbXBvcnQgdHlwZSAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcbmltcG9ydCB0eXBlIHsgVlJNU3ByaW5nQm9uZUpvaW50IH0gZnJvbSAnLi9WUk1TcHJpbmdCb25lSm9pbnQnO1xuaW1wb3J0IHsgdHJhdmVyc2VBbmNlc3RvcnNGcm9tUm9vdCB9IGZyb20gJy4vdXRpbHMvdHJhdmVyc2VBbmNlc3RvcnNGcm9tUm9vdCc7XG5pbXBvcnQgdHlwZSB7IFZSTVNwcmluZ0JvbmVDb2xsaWRlciB9IGZyb20gJy4vVlJNU3ByaW5nQm9uZUNvbGxpZGVyJztcbmltcG9ydCB0eXBlIHsgVlJNU3ByaW5nQm9uZUNvbGxpZGVyR3JvdXAgfSBmcm9tICcuL1ZSTVNwcmluZ0JvbmVDb2xsaWRlckdyb3VwJztcbmltcG9ydCB7IHRyYXZlcnNlQ2hpbGRyZW5VbnRpbENvbmRpdGlvbk1ldCB9IGZyb20gJy4vdXRpbHMvdHJhdmVyc2VDaGlsZHJlblVudGlsQ29uZGl0aW9uTWV0JztcblxuZXhwb3J0IGNsYXNzIFZSTVNwcmluZ0JvbmVNYW5hZ2VyIHtcbiAgcHJpdmF0ZSBfam9pbnRzID0gbmV3IFNldDxWUk1TcHJpbmdCb25lSm9pbnQ+KCk7XG4gIHB1YmxpYyBnZXQgam9pbnRzKCk6IFNldDxWUk1TcHJpbmdCb25lSm9pbnQ+IHtcbiAgICByZXR1cm4gdGhpcy5fam9pbnRzO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgam9pbnRzfSBpbnN0ZWFkLlxuICAgKi9cbiAgcHVibGljIGdldCBzcHJpbmdCb25lcygpOiBTZXQ8VlJNU3ByaW5nQm9uZUpvaW50PiB7XG4gICAgY29uc29sZS53YXJuKCdWUk1TcHJpbmdCb25lTWFuYWdlcjogc3ByaW5nQm9uZXMgaXMgZGVwcmVjYXRlZC4gdXNlIGpvaW50cyBpbnN0ZWFkLicpO1xuXG4gICAgcmV0dXJuIHRoaXMuX2pvaW50cztcbiAgfVxuXG4gIHB1YmxpYyBnZXQgY29sbGlkZXJHcm91cHMoKTogVlJNU3ByaW5nQm9uZUNvbGxpZGVyR3JvdXBbXSB7XG4gICAgY29uc3Qgc2V0ID0gbmV3IFNldDxWUk1TcHJpbmdCb25lQ29sbGlkZXJHcm91cD4oKTtcbiAgICB0aGlzLl9qb2ludHMuZm9yRWFjaCgoc3ByaW5nQm9uZSkgPT4ge1xuICAgICAgc3ByaW5nQm9uZS5jb2xsaWRlckdyb3Vwcy5mb3JFYWNoKChjb2xsaWRlckdyb3VwKSA9PiB7XG4gICAgICAgIHNldC5hZGQoY29sbGlkZXJHcm91cCk7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gQXJyYXkuZnJvbShzZXQpO1xuICB9XG5cbiAgcHVibGljIGdldCBjb2xsaWRlcnMoKTogVlJNU3ByaW5nQm9uZUNvbGxpZGVyW10ge1xuICAgIGNvbnN0IHNldCA9IG5ldyBTZXQ8VlJNU3ByaW5nQm9uZUNvbGxpZGVyPigpO1xuICAgIHRoaXMuY29sbGlkZXJHcm91cHMuZm9yRWFjaCgoY29sbGlkZXJHcm91cCkgPT4ge1xuICAgICAgY29sbGlkZXJHcm91cC5jb2xsaWRlcnMuZm9yRWFjaCgoY29sbGlkZXIpID0+IHtcbiAgICAgICAgc2V0LmFkZChjb2xsaWRlcik7XG4gICAgICB9KTtcbiAgICB9KTtcbiAgICByZXR1cm4gQXJyYXkuZnJvbShzZXQpO1xuICB9XG5cbiAgcHJpdmF0ZSBfb2JqZWN0U3ByaW5nQm9uZXNNYXAgPSBuZXcgTWFwPFRIUkVFLk9iamVjdDNELCBTZXQ8VlJNU3ByaW5nQm9uZUpvaW50Pj4oKTtcblxuICBwdWJsaWMgYWRkSm9pbnQoam9pbnQ6IFZSTVNwcmluZ0JvbmVKb2ludCk6IHZvaWQge1xuICAgIHRoaXMuX2pvaW50cy5hZGQoam9pbnQpO1xuXG4gICAgbGV0IG9iamVjdFNldCA9IHRoaXMuX29iamVjdFNwcmluZ0JvbmVzTWFwLmdldChqb2ludC5ib25lKTtcbiAgICBpZiAob2JqZWN0U2V0ID09IG51bGwpIHtcbiAgICAgIG9iamVjdFNldCA9IG5ldyBTZXQ8VlJNU3ByaW5nQm9uZUpvaW50PigpO1xuICAgICAgdGhpcy5fb2JqZWN0U3ByaW5nQm9uZXNNYXAuc2V0KGpvaW50LmJvbmUsIG9iamVjdFNldCk7XG4gICAgfVxuICAgIG9iamVjdFNldC5hZGQoam9pbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgYWRkSm9pbnR9IGluc3RlYWQuXG4gICAqL1xuICBwdWJsaWMgYWRkU3ByaW5nQm9uZShqb2ludDogVlJNU3ByaW5nQm9uZUpvaW50KTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdWUk1TcHJpbmdCb25lTWFuYWdlcjogYWRkU3ByaW5nQm9uZSgpIGlzIGRlcHJlY2F0ZWQuIHVzZSBhZGRKb2ludCgpIGluc3RlYWQuJyk7XG5cbiAgICB0aGlzLmFkZEpvaW50KGpvaW50KTtcbiAgfVxuXG4gIHB1YmxpYyBkZWxldGVKb2ludChqb2ludDogVlJNU3ByaW5nQm9uZUpvaW50KTogdm9pZCB7XG4gICAgdGhpcy5fam9pbnRzLmRlbGV0ZShqb2ludCk7XG5cbiAgICBjb25zdCBvYmplY3RTZXQgPSB0aGlzLl9vYmplY3RTcHJpbmdCb25lc01hcC5nZXQoam9pbnQuYm9uZSkhO1xuICAgIG9iamVjdFNldC5kZWxldGUoam9pbnQpO1xuICB9XG5cbiAgLyoqXG4gICAqIEBkZXByZWNhdGVkIFVzZSB7QGxpbmsgZGVsZXRlSm9pbnR9IGluc3RlYWQuXG4gICAqL1xuICBwdWJsaWMgZGVsZXRlU3ByaW5nQm9uZShqb2ludDogVlJNU3ByaW5nQm9uZUpvaW50KTogdm9pZCB7XG4gICAgY29uc29sZS53YXJuKCdWUk1TcHJpbmdCb25lTWFuYWdlcjogZGVsZXRlU3ByaW5nQm9uZSgpIGlzIGRlcHJlY2F0ZWQuIHVzZSBkZWxldGVKb2ludCgpIGluc3RlYWQuJyk7XG5cbiAgICB0aGlzLmRlbGV0ZUpvaW50KGpvaW50KTtcbiAgfVxuXG4gIHB1YmxpYyBzZXRJbml0U3RhdGUoKTogdm9pZCB7XG4gICAgY29uc3Qgc3ByaW5nQm9uZXNUcmllZCA9IG5ldyBTZXQ8VlJNU3ByaW5nQm9uZUpvaW50PigpO1xuICAgIGNvbnN0IHNwcmluZ0JvbmVzRG9uZSA9IG5ldyBTZXQ8VlJNU3ByaW5nQm9uZUpvaW50PigpO1xuICAgIGNvbnN0IG9iamVjdFVwZGF0ZWQgPSBuZXcgU2V0PFRIUkVFLk9iamVjdDNEPigpO1xuXG4gICAgZm9yIChjb25zdCBzcHJpbmdCb25lIG9mIHRoaXMuX2pvaW50cykge1xuICAgICAgdGhpcy5fcHJvY2Vzc1NwcmluZ0JvbmUoc3ByaW5nQm9uZSwgc3ByaW5nQm9uZXNUcmllZCwgc3ByaW5nQm9uZXNEb25lLCBvYmplY3RVcGRhdGVkLCAoc3ByaW5nQm9uZSkgPT5cbiAgICAgICAgc3ByaW5nQm9uZS5zZXRJbml0U3RhdGUoKSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHJlc2V0KCk6IHZvaWQge1xuICAgIGNvbnN0IHNwcmluZ0JvbmVzVHJpZWQgPSBuZXcgU2V0PFZSTVNwcmluZ0JvbmVKb2ludD4oKTtcbiAgICBjb25zdCBzcHJpbmdCb25lc0RvbmUgPSBuZXcgU2V0PFZSTVNwcmluZ0JvbmVKb2ludD4oKTtcbiAgICBjb25zdCBvYmplY3RVcGRhdGVkID0gbmV3IFNldDxUSFJFRS5PYmplY3QzRD4oKTtcblxuICAgIGZvciAoY29uc3Qgc3ByaW5nQm9uZSBvZiB0aGlzLl9qb2ludHMpIHtcbiAgICAgIHRoaXMuX3Byb2Nlc3NTcHJpbmdCb25lKHNwcmluZ0JvbmUsIHNwcmluZ0JvbmVzVHJpZWQsIHNwcmluZ0JvbmVzRG9uZSwgb2JqZWN0VXBkYXRlZCwgKHNwcmluZ0JvbmUpID0+XG4gICAgICAgIHNwcmluZ0JvbmUucmVzZXQoKSxcbiAgICAgICk7XG4gICAgfVxuICB9XG5cbiAgcHVibGljIHVwZGF0ZShkZWx0YTogbnVtYmVyKTogdm9pZCB7XG4gICAgY29uc3Qgc3ByaW5nQm9uZXNUcmllZCA9IG5ldyBTZXQ8VlJNU3ByaW5nQm9uZUpvaW50PigpO1xuICAgIGNvbnN0IHNwcmluZ0JvbmVzRG9uZSA9IG5ldyBTZXQ8VlJNU3ByaW5nQm9uZUpvaW50PigpO1xuICAgIGNvbnN0IG9iamVjdFVwZGF0ZWQgPSBuZXcgU2V0PFRIUkVFLk9iamVjdDNEPigpO1xuXG4gICAgZm9yIChjb25zdCBzcHJpbmdCb25lIG9mIHRoaXMuX2pvaW50cykge1xuICAgICAgLy8gdXBkYXRlIHRoZSBzcHJpbmdib25lXG4gICAgICB0aGlzLl9wcm9jZXNzU3ByaW5nQm9uZShzcHJpbmdCb25lLCBzcHJpbmdCb25lc1RyaWVkLCBzcHJpbmdCb25lc0RvbmUsIG9iamVjdFVwZGF0ZWQsIChzcHJpbmdCb25lKSA9PlxuICAgICAgICBzcHJpbmdCb25lLnVwZGF0ZShkZWx0YSksXG4gICAgICApO1xuXG4gICAgICAvLyB1cGRhdGUgY2hpbGRyZW4gd29ybGQgbWF0cmljZXNcbiAgICAgIC8vIGl0IGlzIHJlcXVpcmVkIHdoZW4gdGhlIHNwcmluZyBib25lIGNoYWluIGlzIHNwYXJzZVxuICAgICAgdHJhdmVyc2VDaGlsZHJlblVudGlsQ29uZGl0aW9uTWV0KHNwcmluZ0JvbmUuYm9uZSwgKG9iamVjdCkgPT4ge1xuICAgICAgICAvLyBpZiB0aGUgb2JqZWN0IGhhcyBhdHRhY2hlZCBzcHJpbmdib25lLCBoYWx0IHRoZSB0cmF2ZXJzYWxcbiAgICAgICAgaWYgKCh0aGlzLl9vYmplY3RTcHJpbmdCb25lc01hcC5nZXQob2JqZWN0KT8uc2l6ZSA/PyAwKSA+IDApIHtcbiAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIG90aGVyd2lzZSB1cGRhdGUgaXRzIHdvcmxkIG1hdHJpeFxuICAgICAgICBvYmplY3QudXBkYXRlV29ybGRNYXRyaXgoZmFsc2UsIGZhbHNlKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZSBhIHNwcmluZyBib25lLlxuICAgKiBJZiB0aGVyZSBhcmUgb3RoZXIgc3ByaW5nIGJvbmUgdGhhdCBhcmUgZGVwZW5kYW50LCBpdCB3aWxsIHRyeSB0byB1cGRhdGUgdGhlbSByZWN1cnNpdmVseS5cbiAgICogSXQgdXBkYXRlcyBtYXRyaXhXb3JsZCBvZiBhbGwgYW5jZXN0b3JzIGFuZCBteXNlbGYuXG4gICAqIEl0IG1pZ2h0IHRocm93IGFuIGVycm9yIGlmIHRoZXJlIGFyZSBjaXJjdWxhciBkZXBlbmRlbmNpZXMuXG4gICAqXG4gICAqIEludGVuZGVkIHRvIGJlIHVzZWQgaW4ge0BsaW5rIHVwZGF0ZX0gYW5kIHtAbGluayBfcHJvY2Vzc1NwcmluZ0JvbmV9IGl0c2VsZiByZWN1cnNpdmVseS5cbiAgICpcbiAgICogQHBhcmFtIHNwcmluZ0JvbmUgQSBzcHJpbmdCb25lIHlvdSB3YW50IHRvIHVwZGF0ZVxuICAgKiBAcGFyYW0gc3ByaW5nQm9uZXNUcmllZCBTZXQgb2Ygc3ByaW5nQm9uZXMgdGhhdCBhcmUgYWxyZWFkeSB0cmllZCB0byBiZSB1cGRhdGVkXG4gICAqIEBwYXJhbSBzcHJpbmdCb25lc0RvbmUgU2V0IG9mIHNwcmluZ0JvbmVzIHRoYXQgYXJlIGFscmVhZHkgdXAgdG8gZGF0ZVxuICAgKiBAcGFyYW0gb2JqZWN0VXBkYXRlZCBTZXQgb2Ygb2JqZWN0M0Qgd2hvc2UgbWF0cml4V29ybGQgaXMgdXBkYXRlZFxuICAgKi9cbiAgcHJpdmF0ZSBfcHJvY2Vzc1NwcmluZ0JvbmUoXG4gICAgc3ByaW5nQm9uZTogVlJNU3ByaW5nQm9uZUpvaW50LFxuICAgIHNwcmluZ0JvbmVzVHJpZWQ6IFNldDxWUk1TcHJpbmdCb25lSm9pbnQ+LFxuICAgIHNwcmluZ0JvbmVzRG9uZTogU2V0PFZSTVNwcmluZ0JvbmVKb2ludD4sXG4gICAgb2JqZWN0VXBkYXRlZDogU2V0PFRIUkVFLk9iamVjdDNEPixcbiAgICBjYWxsYmFjazogKHNwcmluZ0JvbmU6IFZSTVNwcmluZ0JvbmVKb2ludCkgPT4gdm9pZCxcbiAgKTogdm9pZCB7XG4gICAgaWYgKHNwcmluZ0JvbmVzRG9uZS5oYXMoc3ByaW5nQm9uZSkpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoc3ByaW5nQm9uZXNUcmllZC5oYXMoc3ByaW5nQm9uZSkpIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignVlJNU3ByaW5nQm9uZU1hbmFnZXI6IENpcmN1bGFyIGRlcGVuZGVuY3kgZGV0ZWN0ZWQgd2hpbGUgdXBkYXRpbmcgc3ByaW5nYm9uZXMnKTtcbiAgICB9XG4gICAgc3ByaW5nQm9uZXNUcmllZC5hZGQoc3ByaW5nQm9uZSk7XG5cbiAgICBjb25zdCBkZXBPYmplY3RzID0gdGhpcy5fZ2V0RGVwZW5kZW5jaWVzKHNwcmluZ0JvbmUpO1xuICAgIGZvciAoY29uc3QgZGVwT2JqZWN0IG9mIGRlcE9iamVjdHMpIHtcbiAgICAgIHRyYXZlcnNlQW5jZXN0b3JzRnJvbVJvb3QoZGVwT2JqZWN0LCAoZGVwT2JqZWN0QW5jZXN0b3IpID0+IHtcbiAgICAgICAgY29uc3Qgb2JqZWN0U2V0ID0gdGhpcy5fb2JqZWN0U3ByaW5nQm9uZXNNYXAuZ2V0KGRlcE9iamVjdEFuY2VzdG9yKTtcbiAgICAgICAgaWYgKG9iamVjdFNldCkge1xuICAgICAgICAgIGZvciAoY29uc3QgZGVwU3ByaW5nQm9uZSBvZiBvYmplY3RTZXQpIHtcbiAgICAgICAgICAgIHRoaXMuX3Byb2Nlc3NTcHJpbmdCb25lKGRlcFNwcmluZ0JvbmUsIHNwcmluZ0JvbmVzVHJpZWQsIHNwcmluZ0JvbmVzRG9uZSwgb2JqZWN0VXBkYXRlZCwgY2FsbGJhY2spO1xuICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICghb2JqZWN0VXBkYXRlZC5oYXMoZGVwT2JqZWN0QW5jZXN0b3IpKSB7XG4gICAgICAgICAgLy8gdXBkYXRlIG1hdHJpeCBvZiBub24tc3ByaW5nYm9uZVxuICAgICAgICAgIGRlcE9iamVjdEFuY2VzdG9yLnVwZGF0ZVdvcmxkTWF0cml4KGZhbHNlLCBmYWxzZSk7XG4gICAgICAgICAgb2JqZWN0VXBkYXRlZC5hZGQoZGVwT2JqZWN0QW5jZXN0b3IpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9XG5cbiAgICAvLyB1cGRhdGUgbXkgbWF0cml4XG4gICAgc3ByaW5nQm9uZS5ib25lLnVwZGF0ZU1hdHJpeCgpO1xuICAgIHNwcmluZ0JvbmUuYm9uZS51cGRhdGVXb3JsZE1hdHJpeChmYWxzZSwgZmFsc2UpO1xuXG4gICAgY2FsbGJhY2soc3ByaW5nQm9uZSk7XG5cbiAgICBvYmplY3RVcGRhdGVkLmFkZChzcHJpbmdCb25lLmJvbmUpO1xuXG4gICAgc3ByaW5nQm9uZXNEb25lLmFkZChzcHJpbmdCb25lKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm4gYSBzZXQgb2Ygb2JqZWN0cyB0aGF0IGFyZSBkZXBlbmRhbnQgb2YgZ2l2ZW4gc3ByaW5nIGJvbmUuXG4gICAqIEBwYXJhbSBzcHJpbmdCb25lIEEgc3ByaW5nIGJvbmVcbiAgICogQHJldHVybiBBIHNldCBvZiBvYmplY3RzIHRoYXQgYXJlIGRlcGVuZGFudCBvZiBnaXZlbiBzcHJpbmcgYm9uZVxuICAgKi9cbiAgcHJpdmF0ZSBfZ2V0RGVwZW5kZW5jaWVzKHNwcmluZ0JvbmU6IFZSTVNwcmluZ0JvbmVKb2ludCk6IFNldDxUSFJFRS5PYmplY3QzRD4ge1xuICAgIGNvbnN0IHNldCA9IG5ldyBTZXQ8VEhSRUUuT2JqZWN0M0Q+KCk7XG5cbiAgICBjb25zdCBwYXJlbnQgPSBzcHJpbmdCb25lLmJvbmUucGFyZW50O1xuICAgIGlmIChwYXJlbnQpIHtcbiAgICAgIHNldC5hZGQocGFyZW50KTtcbiAgICB9XG5cbiAgICBzcHJpbmdCb25lLmNvbGxpZGVyR3JvdXBzLmZvckVhY2goKGNvbGxpZGVyR3JvdXApID0+IHtcbiAgICAgIGNvbGxpZGVyR3JvdXAuY29sbGlkZXJzLmZvckVhY2goKGNvbGxpZGVyKSA9PiB7XG4gICAgICAgIHNldC5hZGQoY29sbGlkZXIpO1xuICAgICAgfSk7XG4gICAgfSk7XG5cbiAgICByZXR1cm4gc2V0O1xuICB9XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7OztBQ0FBLElBQUFBLFNBQXVCOzs7QUNBdkIsWUFBdUI7OztBQ0toQixJQUFlLDZCQUFmLE1BQTBDO0FB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QUNBLFFBSXVCO0FBQ3ZCLFVBQU0sRUFBRSxRQUFRLE9BQU8sSUFBSTtBQUUzQixVQUFNLFFBQVEsSUFBSSxpQ0FBaUMsRUFBRSxRQUFRLE9BQU8sQ0FBQztBQUVyRSxVQUFNLFdBQVcsSUFBSSxzQkFBc0IsS0FBSztBQUVoRCxnQkFBWSxJQUFJLFFBQVE7QUFFeEIsUUFBSSxLQUFLLG9CQUFvQjtBQUMzQixZQUFNLFNBQVMsSUFBSSw0QkFBNEIsUUFBUTtBQUN2RCxXQUFLLG1CQUFtQixJQUFJLE1BQU07QUFDbEMsYUFBTyxjQUFjLEtBQUssbUJBQW1CO0FBQUEsSUFDL0M7QUFFQSxXQUFPO0FBQUEsRUFDVDtBQUFBLEVBRVEsdUJBQ04sYUFDQSxRQUt1QjtBQUN2QixVQUFNLEVBQUUsUUFBUSxRQUFRLEtBQUssSUFBSTtBQUVqQyxVQUFNLFFBQVEsSUFBSSxrQ0FBa0MsRUFBRSxRQUFRLFFBQVEsS0FBSyxDQUFDO0FBRTVFLFVBQU0sV0FBVyxJQUFJLHNCQUFzQixLQUFLO0FBRWhELGdCQUFZLElBQUksUUFBUTtBQUV4QixRQUFJLEtBQUssb0JBQW9CO0FBQzNCLFlBQU0sU0FBUyxJQUFJLDRCQUE0QixRQUFRO0FBQ3ZELFdBQUssbUJBQW1CLElBQUksTUFBTTtBQUNsQyxhQUFPLGNBQWMsS0FBSyxtQkFBbUI7QUFBQSxJQUMvQztBQUVBLFdBQU87QUFBQSxFQUNUO0FBQ0Y7QUF4V2EsMkJBQ1ksaUJBQWlCO0FBRG5DLElBQU0sNEJBQU47IiwKICAibmFtZXMiOiBbIlRIUkVFIiwgIlRIUkVFIiwgIlRIUkVFIiwgIl92M0EiLCAiVEhSRUUiLCAiX3YzQSIsICJUSFJFRSIsICJUSFJFRSIsICJfdjNBIiwgIlRIUkVFIiwgIlRIUkVFIiwgIlRIUkVFIiwgIlRIUkVFIiwgIl92M0EiLCAiX3YzQiIsICJfbWF0QSIsICJUSFJFRSIsICJzcHJpbmdCb25lIiwgIl9hIiwgIl9iIiwgIl9jIiwgIl9kIiwgIl9lIl0KfQo=
|