Ai_Assistant/client/node_modules/@pixiv/three-vrm-materials-v0compat/lib/three-vrm-materials-v0compat.cjs
2026-05-24 13:31:30 +02:00

389 lines
52 KiB
JavaScript

/*!
* @pixiv/three-vrm-materials-v0compat v3.4.1
* VRM0.0 materials compatibility layer plugin for @pixiv/three-vrm
*
* Copyright (c) 2019-2025 pixiv Inc.
* @pixiv/three-vrm-materials-v0compat is distributed under MIT License
* https://github.com/pixiv/three-vrm/blob/release/LICENSE
*/
"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/index.ts
var src_exports = {};
__export(src_exports, {
VRMMaterialsV0CompatPlugin: () => VRMMaterialsV0CompatPlugin
});
module.exports = __toCommonJS(src_exports);
// src/VRMMaterialsV0CompatPlugin.ts
var THREE = __toESM(require("three"), 1);
// src/utils/gammaEOTF.ts
function gammaEOTF(e) {
return Math.pow(e, 2.2);
}
// src/VRMMaterialsV0CompatPlugin.ts
var VRMMaterialsV0CompatPlugin = class {
get name() {
return "VRMMaterialsV0CompatPlugin";
}
constructor(parser) {
var _a;
this.parser = parser;
this._renderQueueMapTransparent = /* @__PURE__ */ new Map();
this._renderQueueMapTransparentZWrite = /* @__PURE__ */ new Map();
const json = this.parser.json;
json.extensionsUsed = (_a = json.extensionsUsed) != null ? _a : [];
if (json.extensionsUsed.indexOf("KHR_texture_transform") === -1) {
json.extensionsUsed.push("KHR_texture_transform");
}
}
beforeRoot() {
return __async(this, null, function* () {
var _a;
const json = this.parser.json;
const v0VRMExtension = (_a = json.extensions) == null ? void 0 : _a["VRM"];
const v0MaterialProperties = v0VRMExtension == null ? void 0 : v0VRMExtension.materialProperties;
if (!v0MaterialProperties) {
return;
}
this._populateRenderQueueMap(v0MaterialProperties);
v0MaterialProperties.forEach((materialProperties, materialIndex) => {
var _a2, _b;
const materialDef = (_a2 = json.materials) == null ? void 0 : _a2[materialIndex];
if (materialDef == null) {
console.warn(
`VRMMaterialsV0CompatPlugin: Attempt to use materials[${materialIndex}] of glTF but the material doesn't exist`
);
return;
}
if (materialProperties.shader === "VRM/MToon") {
const material = this._parseV0MToonProperties(materialProperties, materialDef);
json.materials[materialIndex] = material;
} else if ((_b = materialProperties.shader) == null ? void 0 : _b.startsWith("VRM/Unlit")) {
const material = this._parseV0UnlitProperties(materialProperties, materialDef);
json.materials[materialIndex] = material;
} else if (materialProperties.shader === "VRM_USE_GLTFSHADER") {
} else {
console.warn(`VRMMaterialsV0CompatPlugin: Unknown shader: ${materialProperties.shader}`);
}
});
});
}
_parseV0MToonProperties(materialProperties, schemaMaterial) {
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa;
const isTransparent = (_b = (_a = materialProperties.keywordMap) == null ? void 0 : _a["_ALPHABLEND_ON"]) != null ? _b : false;
const enabledZWrite = ((_c = materialProperties.floatProperties) == null ? void 0 : _c["_ZWrite"]) === 1;
const transparentWithZWrite = enabledZWrite && isTransparent;
const renderQueueOffsetNumber = this._v0ParseRenderQueue(materialProperties);
const isCutoff = (_e = (_d = materialProperties.keywordMap) == null ? void 0 : _d["_ALPHATEST_ON"]) != null ? _e : false;
const alphaMode = isTransparent ? "BLEND" : isCutoff ? "MASK" : "OPAQUE";
const alphaCutoff = isCutoff ? (_g = (_f = materialProperties.floatProperties) == null ? void 0 : _f["_Cutoff"]) != null ? _g : 0.5 : void 0;
const cullMode = (_i = (_h = materialProperties.floatProperties) == null ? void 0 : _h["_CullMode"]) != null ? _i : 2;
const doubleSided = cullMode === 0;
const textureTransformExt = this._portTextureTransform(materialProperties);
const baseColorFactor = ((_k = (_j = materialProperties.vectorProperties) == null ? void 0 : _j["_Color"]) != null ? _k : [1, 1, 1, 1]).map(
(v, i) => i === 3 ? v : gammaEOTF(v)
// alpha channel is stored in linear
);
const baseColorTextureIndex = (_l = materialProperties.textureProperties) == null ? void 0 : _l["_MainTex"];
const baseColorTexture = baseColorTextureIndex != null ? {
index: baseColorTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const normalTextureScale = (_n = (_m = materialProperties.floatProperties) == null ? void 0 : _m["_BumpScale"]) != null ? _n : 1;
const normalTextureIndex = (_o = materialProperties.textureProperties) == null ? void 0 : _o["_BumpMap"];
const normalTexture = normalTextureIndex != null ? {
index: normalTextureIndex,
scale: normalTextureScale,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const emissiveFactor = ((_q = (_p = materialProperties.vectorProperties) == null ? void 0 : _p["_EmissionColor"]) != null ? _q : [0, 0, 0, 1]).map(
gammaEOTF
);
const emissiveTextureIndex = (_r = materialProperties.textureProperties) == null ? void 0 : _r["_EmissionMap"];
const emissiveTexture = emissiveTextureIndex != null ? {
index: emissiveTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const shadeColorFactor = ((_t = (_s = materialProperties.vectorProperties) == null ? void 0 : _s["_ShadeColor"]) != null ? _t : [0.97, 0.81, 0.86, 1]).map(
gammaEOTF
);
const shadeMultiplyTextureIndex = (_u = materialProperties.textureProperties) == null ? void 0 : _u["_ShadeTexture"];
const shadeMultiplyTexture = shadeMultiplyTextureIndex != null ? {
index: shadeMultiplyTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
let shadingShiftFactor = (_w = (_v = materialProperties.floatProperties) == null ? void 0 : _v["_ShadeShift"]) != null ? _w : 0;
let shadingToonyFactor = (_y = (_x = materialProperties.floatProperties) == null ? void 0 : _x["_ShadeToony"]) != null ? _y : 0.9;
shadingToonyFactor = THREE.MathUtils.lerp(shadingToonyFactor, 1, 0.5 + 0.5 * shadingShiftFactor);
shadingShiftFactor = -shadingShiftFactor - (1 - shadingToonyFactor);
const giIntensityFactor = (_A = (_z = materialProperties.floatProperties) == null ? void 0 : _z["_IndirectLightIntensity"]) != null ? _A : 0.1;
const giEqualizationFactor = giIntensityFactor ? 1 - giIntensityFactor : void 0;
const matcapTextureIndex = (_B = materialProperties.textureProperties) == null ? void 0 : _B["_SphereAdd"];
const matcapFactor = matcapTextureIndex != null ? [1, 1, 1] : void 0;
const matcapTexture = matcapTextureIndex != null ? {
index: matcapTextureIndex
} : void 0;
const rimLightingMixFactor = (_D = (_C = materialProperties.floatProperties) == null ? void 0 : _C["_RimLightingMix"]) != null ? _D : 0;
const rimMultiplyTextureIndex = (_E = materialProperties.textureProperties) == null ? void 0 : _E["_RimTexture"];
const rimMultiplyTexture = rimMultiplyTextureIndex != null ? {
index: rimMultiplyTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const parametricRimColorFactor = ((_G = (_F = materialProperties.vectorProperties) == null ? void 0 : _F["_RimColor"]) != null ? _G : [0, 0, 0, 1]).map(
gammaEOTF
);
const parametricRimFresnelPowerFactor = (_I = (_H = materialProperties.floatProperties) == null ? void 0 : _H["_RimFresnelPower"]) != null ? _I : 1;
const parametricRimLiftFactor = (_K = (_J = materialProperties.floatProperties) == null ? void 0 : _J["_RimLift"]) != null ? _K : 0;
const outlineWidthMode = ["none", "worldCoordinates", "screenCoordinates"][(_M = (_L = materialProperties.floatProperties) == null ? void 0 : _L["_OutlineWidthMode"]) != null ? _M : 0];
let outlineWidthFactor = (_O = (_N = materialProperties.floatProperties) == null ? void 0 : _N["_OutlineWidth"]) != null ? _O : 0;
outlineWidthFactor = 0.01 * outlineWidthFactor;
const outlineWidthMultiplyTextureIndex = (_P = materialProperties.textureProperties) == null ? void 0 : _P["_OutlineWidthTexture"];
const outlineWidthMultiplyTexture = outlineWidthMultiplyTextureIndex != null ? {
index: outlineWidthMultiplyTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const outlineColorFactor = ((_R = (_Q = materialProperties.vectorProperties) == null ? void 0 : _Q["_OutlineColor"]) != null ? _R : [0, 0, 0]).map(
gammaEOTF
);
const outlineColorMode = (_T = (_S = materialProperties.floatProperties) == null ? void 0 : _S["_OutlineColorMode"]) != null ? _T : 0;
const outlineLightingMixFactor = outlineColorMode === 1 ? (_V = (_U = materialProperties.floatProperties) == null ? void 0 : _U["_OutlineLightingMix"]) != null ? _V : 1 : 0;
const uvAnimationMaskTextureIndex = (_W = materialProperties.textureProperties) == null ? void 0 : _W["_UvAnimMaskTexture"];
const uvAnimationMaskTexture = uvAnimationMaskTextureIndex != null ? {
index: uvAnimationMaskTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const uvAnimationScrollXSpeedFactor = (_Y = (_X = materialProperties.floatProperties) == null ? void 0 : _X["_UvAnimScrollX"]) != null ? _Y : 0;
let uvAnimationScrollYSpeedFactor = (__ = (_Z = materialProperties.floatProperties) == null ? void 0 : _Z["_UvAnimScrollY"]) != null ? __ : 0;
if (uvAnimationScrollYSpeedFactor != null) {
uvAnimationScrollYSpeedFactor = -uvAnimationScrollYSpeedFactor;
}
const uvAnimationRotationSpeedFactor = (_aa = (_$ = materialProperties.floatProperties) == null ? void 0 : _$["_UvAnimRotation"]) != null ? _aa : 0;
const mtoonExtension = {
specVersion: "1.0",
transparentWithZWrite,
renderQueueOffsetNumber,
shadeColorFactor,
shadeMultiplyTexture,
shadingShiftFactor,
shadingToonyFactor,
giEqualizationFactor,
matcapFactor,
matcapTexture,
rimLightingMixFactor,
rimMultiplyTexture,
parametricRimColorFactor,
parametricRimFresnelPowerFactor,
parametricRimLiftFactor,
outlineWidthMode,
outlineWidthFactor,
outlineWidthMultiplyTexture,
outlineColorFactor,
outlineLightingMixFactor,
uvAnimationMaskTexture,
uvAnimationScrollXSpeedFactor,
uvAnimationScrollYSpeedFactor,
uvAnimationRotationSpeedFactor
};
return __spreadProps(__spreadValues({}, schemaMaterial), {
pbrMetallicRoughness: {
baseColorFactor,
baseColorTexture
},
normalTexture,
emissiveTexture,
emissiveFactor,
alphaMode,
alphaCutoff,
doubleSided,
extensions: {
// eslint-disable-next-line @typescript-eslint/naming-convention
VRMC_materials_mtoon: mtoonExtension
}
});
}
_parseV0UnlitProperties(materialProperties, schemaMaterial) {
var _a, _b, _c, _d, _e;
const isTransparentZWrite = materialProperties.shader === "VRM/UnlitTransparentZWrite";
const isTransparent = materialProperties.shader === "VRM/UnlitTransparent" || isTransparentZWrite;
const renderQueueOffsetNumber = this._v0ParseRenderQueue(materialProperties);
const isCutoff = materialProperties.shader === "VRM/UnlitCutout";
const alphaMode = isTransparent ? "BLEND" : isCutoff ? "MASK" : "OPAQUE";
const alphaCutoff = isCutoff ? (_b = (_a = materialProperties.floatProperties) == null ? void 0 : _a["_Cutoff"]) != null ? _b : 0.5 : void 0;
const textureTransformExt = this._portTextureTransform(materialProperties);
const baseColorFactor = ((_d = (_c = materialProperties.vectorProperties) == null ? void 0 : _c["_Color"]) != null ? _d : [1, 1, 1, 1]).map(gammaEOTF);
const baseColorTextureIndex = (_e = materialProperties.textureProperties) == null ? void 0 : _e["_MainTex"];
const baseColorTexture = baseColorTextureIndex != null ? {
index: baseColorTextureIndex,
extensions: __spreadValues({}, textureTransformExt)
} : void 0;
const mtoonExtension = {
specVersion: "1.0",
transparentWithZWrite: isTransparentZWrite,
renderQueueOffsetNumber,
shadeColorFactor: baseColorFactor,
shadeMultiplyTexture: baseColorTexture
};
return __spreadProps(__spreadValues({}, schemaMaterial), {
pbrMetallicRoughness: {
baseColorFactor,
baseColorTexture
},
alphaMode,
alphaCutoff,
extensions: {
// eslint-disable-next-line @typescript-eslint/naming-convention
VRMC_materials_mtoon: mtoonExtension
}
});
}
/**
* Create a glTF `KHR_texture_transform` extension from v0 texture transform info.
*/
_portTextureTransform(materialProperties) {
var _a, _b, _c, _d, _e;
const textureTransform = (_a = materialProperties.vectorProperties) == null ? void 0 : _a["_MainTex"];
if (textureTransform == null) {
return {};
}
const offset = [(_b = textureTransform == null ? void 0 : textureTransform[0]) != null ? _b : 0, (_c = textureTransform == null ? void 0 : textureTransform[1]) != null ? _c : 0];
const scale = [(_d = textureTransform == null ? void 0 : textureTransform[2]) != null ? _d : 1, (_e = textureTransform == null ? void 0 : textureTransform[3]) != null ? _e : 1];
offset[1] = 1 - scale[1] - offset[1];
return {
// eslint-disable-next-line @typescript-eslint/naming-convention
KHR_texture_transform: { offset, scale }
};
}
/**
* Convert v0 render order into v1 render order.
* This uses a map from v0 render queue to v1 compliant render queue offset which is generated in {@link _populateRenderQueueMap}.
*/
_v0ParseRenderQueue(materialProperties) {
var _a, _b;
const isTransparentZWrite = materialProperties.shader === "VRM/UnlitTransparentZWrite";
const isTransparent = ((_a = materialProperties.keywordMap) == null ? void 0 : _a["_ALPHABLEND_ON"]) != void 0 || materialProperties.shader === "VRM/UnlitTransparent" || isTransparentZWrite;
const enabledZWrite = ((_b = materialProperties.floatProperties) == null ? void 0 : _b["_ZWrite"]) === 1 || isTransparentZWrite;
let offset = 0;
if (isTransparent) {
const v0Queue = materialProperties.renderQueue;
if (v0Queue != null) {
if (enabledZWrite) {
offset = this._renderQueueMapTransparentZWrite.get(v0Queue);
} else {
offset = this._renderQueueMapTransparent.get(v0Queue);
}
}
}
return offset;
}
/**
* Create a map which maps v0 render queue to v1 compliant render queue offset.
* This lists up all render queues the model use and creates a map to new render queue offsets in the same order.
*/
_populateRenderQueueMap(materialPropertiesList) {
const renderQueuesTransparent = /* @__PURE__ */ new Set();
const renderQueuesTransparentZWrite = /* @__PURE__ */ new Set();
materialPropertiesList.forEach((materialProperties) => {
var _a, _b;
const isTransparentZWrite = materialProperties.shader === "VRM/UnlitTransparentZWrite";
const isTransparent = ((_a = materialProperties.keywordMap) == null ? void 0 : _a["_ALPHABLEND_ON"]) != void 0 || materialProperties.shader === "VRM/UnlitTransparent" || isTransparentZWrite;
const enabledZWrite = ((_b = materialProperties.floatProperties) == null ? void 0 : _b["_ZWrite"]) === 1 || isTransparentZWrite;
if (isTransparent) {
const v0Queue = materialProperties.renderQueue;
if (v0Queue != null) {
if (enabledZWrite) {
renderQueuesTransparentZWrite.add(v0Queue);
} else {
renderQueuesTransparent.add(v0Queue);
}
}
}
});
if (renderQueuesTransparent.size > 10) {
console.warn(
`VRMMaterialsV0CompatPlugin: This VRM uses ${renderQueuesTransparent.size} render queues for Transparent materials while VRM 1.0 only supports up to 10 render queues. The model might not be rendered correctly.`
);
}
if (renderQueuesTransparentZWrite.size > 10) {
console.warn(
`VRMMaterialsV0CompatPlugin: This VRM uses ${renderQueuesTransparentZWrite.size} render queues for TransparentZWrite materials while VRM 1.0 only supports up to 10 render queues. The model might not be rendered correctly.`
);
}
Array.from(renderQueuesTransparent).sort().forEach((queue, i) => {
const newQueueOffset = Math.min(Math.max(i - renderQueuesTransparent.size + 1, -9), 0);
this._renderQueueMapTransparent.set(queue, newQueueOffset);
});
Array.from(renderQueuesTransparentZWrite).sort().forEach((queue, i) => {
const newQueueOffset = Math.min(Math.max(i, 0), 9);
this._renderQueueMapTransparentZWrite.set(queue, newQueueOffset);
});
}
};
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vc3JjL2luZGV4LnRzIiwgIi4uL3NyYy9WUk1NYXRlcmlhbHNWMENvbXBhdFBsdWdpbi50cyIsICIuLi9zcmMvdXRpbHMvZ2FtbWFFT1RGLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJleHBvcnQgeyBWUk1NYXRlcmlhbHNWMENvbXBhdFBsdWdpbiB9IGZyb20gJy4vVlJNTWF0ZXJpYWxzVjBDb21wYXRQbHVnaW4nO1xuIiwgImltcG9ydCAqIGFzIFRIUkVFIGZyb20gJ3RocmVlJztcbmltcG9ydCB7IFZSTSBhcyBWMFZSTSwgTWF0ZXJpYWwgYXMgVjBNYXRlcmlhbCB9IGZyb20gJ0BwaXhpdi90eXBlcy12cm0tMC4wJztcbmltcG9ydCAqIGFzIFYxTVRvb25TY2hlbWEgZnJvbSAnQHBpeGl2L3R5cGVzLXZybWMtbWF0ZXJpYWxzLW10b29uLTEuMCc7XG5pbXBvcnQgdHlwZSB7IEdMVEZMb2FkZXJQbHVnaW4sIEdMVEZQYXJzZXIgfSBmcm9tICd0aHJlZS9leGFtcGxlcy9qc20vbG9hZGVycy9HTFRGTG9hZGVyLmpzJztcbmltcG9ydCB7IGdhbW1hRU9URiB9IGZyb20gJy4vdXRpbHMvZ2FtbWFFT1RGJztcbmltcG9ydCB7IEdMVEYgYXMgR0xURlNjaGVtYSB9IGZyb20gJ0BnbHRmLXRyYW5zZm9ybS9jb3JlJztcblxuZXhwb3J0IGNsYXNzIFZSTU1hdGVyaWFsc1YwQ29tcGF0UGx1Z2luIGltcGxlbWVudHMgR0xURkxvYWRlclBsdWdpbiB7XG4gIHB1YmxpYyByZWFkb25seSBwYXJzZXI6IEdMVEZQYXJzZXI7XG5cbiAgLyoqXG4gICAqIEEgbWFwIGZyb20gdjAgcmVuZGVyIHF1ZXVlIHRvIHYxIHJlbmRlciBxdWV1ZSBvZmZzZXQsIGZvciBUcmFuc3BhcmVudCBtYXRlcmlhbHMuXG4gICAqL1xuICBwcml2YXRlIHJlYWRvbmx5IF9yZW5kZXJRdWV1ZU1hcFRyYW5zcGFyZW50OiBNYXA8bnVtYmVyLCBudW1iZXI+O1xuXG4gIC8qKlxuICAgKiBBIG1hcCBmcm9tIHYwIHJlbmRlciBxdWV1ZSB0byB2MSByZW5kZXIgcXVldWUgb2Zmc2V0LCBmb3IgVHJhbnNwYXJlbnRaV3JpdGUgbWF0ZXJpYWxzLlxuICAgKi9cbiAgcHJpdmF0ZSByZWFkb25seSBfcmVuZGVyUXVldWVNYXBUcmFuc3BhcmVudFpXcml0ZTogTWFwPG51bWJlciwgbnVtYmVyPjtcblxuICBwdWJsaWMgZ2V0IG5hbWUoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gJ1ZSTU1hdGVyaWFsc1YwQ29tcGF0UGx1Z2luJztcbiAgfVxuXG4gIHB1YmxpYyBjb25zdHJ1Y3RvcihwYXJzZXI6IEdMVEZQYXJzZXIpIHtcbiAgICB0aGlzLnBhcnNlciA9IHBhcnNlcjtcblxuICAgIHRoaXMuX3JlbmRlclF1ZXVlTWFwVHJhbnNwYXJlbnQgPSBuZXcgTWFwKCk7XG4gICAgdGhpcy5fcmVuZGVyUXVldWVNYXBUcmFuc3BhcmVudFpXcml0ZSA9IG5ldyBNYXAoKTtcblxuICAgIC8vIFdPUktBUk9VTkQ6IEFkZCBLSFJfdGV4dHVyZV90cmFuc2Zvcm0gdG8gZXh0ZW5zaW9uc1VzZWRcbiAgICAvLyBJdCBpcyB0b28gbGF0ZSB0byBhZGQgdGhpcyBpbiBiZWZvcmVSb290XG4gICAgY29uc3QganNvbiA9IHRoaXMucGFyc2VyLmpzb24gYXMgR0xURlNjaGVtYS5JR0xURjtcblxuICAgIGpzb24uZXh0ZW5zaW9uc1VzZWQgPSBqc29uLmV4dGVuc2lvbnNVc2VkID8/IFtdO1xuICAgIGlmIChqc29uLmV4dGVuc2lvbnNVc2VkLmluZGV4T2YoJ0tIUl90ZXh0dXJlX3RyYW5zZm9ybScpID09PSAtMSkge1xuICAgICAganNvbi5leHRlbnNpb25zVXNlZC5wdXNoKCdLSFJfdGV4dHVyZV90cmFuc2Zvcm0nKTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgYXN5bmMgYmVmb3JlUm9vdCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCBqc29uID0gdGhpcy5wYXJzZXIuanNvbiBhcyBHTFRGU2NoZW1hLklHTFRGO1xuXG4gICAgLy8gZWFybHkgYWJvcnQgaWYgaXQgZG9lc24ndCB1c2UgVjBWUk1cbiAgICBjb25zdCB2MFZSTUV4dGVuc2lvbiA9IGpzb24uZXh0ZW5zaW9ucz8uWydWUk0nXSBhcyBWMFZSTSB8IHVuZGVmaW5lZDtcbiAgICBjb25zdCB2ME1hdGVyaWFsUHJvcGVydGllcyA9IHYwVlJNRXh0ZW5zaW9uPy5tYXRlcmlhbFByb3BlcnRpZXM7XG4gICAgaWYgKCF2ME1hdGVyaWFsUHJvcGVydGllcykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIHBvcHVsYXRlIHJlbmRlciBxdWV1ZSBtYXBcbiAgICB0aGlzLl9wb3B1bGF0ZVJlbmRlclF1ZXVlTWFwKHYwTWF0ZXJpYWxQcm9wZXJ0aWVzKTtcblxuICAgIC8vIGNvbnZlcnQgVjAgbWF0ZXJpYWwgcHJvcGVydGllcyBpbnRvIFYxIGNvbXBhdGlibGUgZm9ybWF0XG4gICAgdjBNYXRlcmlhbFByb3BlcnRpZXMuZm9yRWFjaCgobWF0ZXJpYWxQcm9wZXJ0aWVzLCBtYXRlcmlhbEluZGV4KSA9PiB7XG4gICAgICBjb25zdCBtYXRlcmlhbERlZiA9IGpzb24ubWF0ZXJpYWxzPy5bbWF0ZXJpYWxJbmRleF07XG5cbiAgICAgIGlmIChtYXRlcmlhbERlZiA9PSBudWxsKSB7XG4gICAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgICBgVlJNTWF0ZXJpYWxzVjBDb21wYXRQbHVnaW46IEF0dGVtcHQgdG8gdXNlIG1hdGVyaWFsc1ske21hdGVyaWFsSW5kZXh9XSBvZiBnbFRGIGJ1dCB0aGUgbWF0ZXJpYWwgZG9lc24ndCBleGlzdGAsXG4gICAgICAgICk7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgaWYgKG1hdGVyaWFsUHJvcGVydGllcy5zaGFkZXIgPT09ICdWUk0vTVRvb24nKSB7XG4gICAgICAgIGNvbnN0IG1hdGVyaWFsID0gdGhpcy5fcGFyc2VWME1Ub29uUHJvcGVydGllcyhtYXRlcmlhbFByb3BlcnRpZXMsIG1hdGVyaWFsRGVmKTtcbiAgICAgICAganNvbi5tYXRlcmlhbHMhW21hdGVyaWFsSW5kZXhdID0gbWF0ZXJpYWw7XG4gICAgICB9IGVsc2UgaWYgKG1hdGVyaWFsUHJvcGVydGllcy5zaGFkZXI/LnN0YXJ0c1dpdGgoJ1ZSTS9VbmxpdCcpKSB7XG4gICAgICAgIGNvbnN0IG1hdGVyaWFsID0gdGhpcy5fcGFyc2VWMFVubGl0UHJvcGVydGllcyhtYXRlcmlhbFByb3BlcnRpZXMsIG1hdGVyaWFsRGVmKTtcbiAgICAgICAganNvbi5tYXRlcmlhbHMhW21hdGVyaWFsSW5kZXhdID0gbWF0ZXJpYWw7XG4gICAgICB9IGVsc2UgaWYgKG1hdGVyaWFsUHJvcGVydGllcy5zaGFkZXIgPT09ICdWUk1fVVNFX0dMVEZTSEFERVInKSB7XG4gICAgICAgIC8vIGBqc29uLm1hdGVyaWFsc1ttYXRlcmlhbEluZGV4XWAgc2hvdWxkIGJlIGFscmVhZHkgdmFsaWRcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnNvbGUud2FybihgVlJNTWF0ZXJpYWxzVjBDb21wYXRQbHVnaW46IFVua25vd24gc2hhZGVyOiAke21hdGVyaWFsUHJvcGVydGllcy5zaGFkZXJ9YCk7XG4gICAgICB9XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIF9wYXJzZVYwTVRvb25Qcm9wZXJ0aWVzKFxuICAgIG1hdGVyaWFsUHJvcGVydGllczogVjBNYXRlcmlhbCxcbiAgICBzY2hlbWFNYXRlcmlhbDogR0xURlNjaGVtYS5JTWF0ZXJpYWwsXG4gICk6IEdMVEZTY2hlbWEuSU1hdGVyaWFsIHtcbiAgICBjb25zdCBpc1RyYW5zcGFyZW50ID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLmtleXdvcmRNYXA/LlsnX0FMUEhBQkxFTkRfT04nXSA/PyBmYWxzZTtcbiAgICBjb25zdCBlbmFibGVkWldyaXRlID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLmZsb2F0UHJvcGVydGllcz8uWydfWldyaXRlJ10gPT09IDE7XG4gICAgY29uc3QgdHJhbnNwYXJlbnRXaXRoWldyaXRlID0gZW5hYmxlZFpXcml0ZSAmJiBpc1RyYW5zcGFyZW50O1xuXG4gICAgY29uc3QgcmVuZGVyUXVldWVPZmZzZXROdW1iZXIgPSB0aGlzLl92MFBhcnNlUmVuZGVyUXVldWUobWF0ZXJpYWxQcm9wZXJ0aWVzKTtcblxuICAgIGNvbnN0IGlzQ3V0b2ZmID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLmtleXdvcmRNYXA/LlsnX0FMUEhBVEVTVF9PTiddID8/IGZhbHNlO1xuICAgIGNvbnN0IGFscGhhTW9kZSA9IGlzVHJhbnNwYXJlbnQgPyAnQkxFTkQnIDogaXNDdXRvZmYgPyAnTUFTSycgOiAnT1BBUVVFJztcbiAgICBjb25zdCBhbHBoYUN1dG9mZiA9IGlzQ3V0b2ZmID8gKG1hdGVyaWFsUHJvcGVydGllcy5mbG9hdFByb3BlcnRpZXM/LlsnX0N1dG9mZiddID8/IDAuNSkgOiB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBjdWxsTW9kZSA9IG1hdGVyaWFsUHJvcGVydGllcy5mbG9hdFByb3BlcnRpZXM/LlsnX0N1bGxNb2RlJ10gPz8gMjsgLy8gZW51bSwgeyBPZmYsIEZyb250LCBCYWNrIH1cbiAgICBjb25zdCBkb3VibGVTaWRlZCA9IGN1bGxNb2RlID09PSAwO1xuXG4gICAgY29uc3QgdGV4dHVyZVRyYW5zZm9ybUV4dCA9IHRoaXMuX3BvcnRUZXh0dXJlVHJhbnNmb3JtKG1hdGVyaWFsUHJvcGVydGllcyk7XG5cbiAgICBjb25zdCBiYXNlQ29sb3JGYWN0b3IgPSAobWF0ZXJpYWxQcm9wZXJ0aWVzLnZlY3RvclByb3BlcnRpZXM/LlsnX0NvbG9yJ10gPz8gWzEuMCwgMS4wLCAxLjAsIDEuMF0pLm1hcChcbiAgICAgICh2OiBudW1iZXIsIGk6IG51bWJlcikgPT4gKGkgPT09IDMgPyB2IDogZ2FtbWFFT1RGKHYpKSwgLy8gYWxwaGEgY2hhbm5lbCBpcyBzdG9yZWQgaW4gbGluZWFyXG4gICAgKTtcbiAgICBjb25zdCBiYXNlQ29sb3JUZXh0dXJlSW5kZXggPSBtYXRlcmlhbFByb3BlcnRpZXMudGV4dHVyZVByb3BlcnRpZXM/LlsnX01haW5UZXgnXTtcbiAgICBjb25zdCBiYXNlQ29sb3JUZXh0dXJlID1cbiAgICAgIGJhc2VDb2xvclRleHR1cmVJbmRleCAhPSBudWxsXG4gICAgICAgID8ge1xuICAgICAgICAgICAgaW5kZXg6IGJhc2VDb2xvclRleHR1cmVJbmRleCxcbiAgICAgICAgICAgIGV4dGVuc2lvbnM6IHtcbiAgICAgICAgICAgICAgLi4udGV4dHVyZVRyYW5zZm9ybUV4dCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfVxuICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IG5vcm1hbFRleHR1cmVTY2FsZSA9IG1hdGVyaWFsUHJvcGVydGllcy5mbG9hdFByb3BlcnRpZXM/LlsnX0J1bXBTY2FsZSddID8/IDEuMDtcbiAgICBjb25zdCBub3JtYWxUZXh0dXJlSW5kZXggPSBtYXRlcmlhbFByb3BlcnRpZXMudGV4dHVyZVByb3BlcnRpZXM/LlsnX0J1bXBNYXAnXTtcbiAgICBjb25zdCBub3JtYWxUZXh0dXJlID1cbiAgICAgIG5vcm1hbFRleHR1cmVJbmRleCAhPSBudWxsXG4gICAgICAgID8ge1xuICAgICAgICAgICAgaW5kZXg6IG5vcm1hbFRleHR1cmVJbmRleCxcbiAgICAgICAgICAgIHNjYWxlOiBub3JtYWxUZXh0dXJlU2NhbGUsXG4gICAgICAgICAgICBleHRlbnNpb25zOiB7XG4gICAgICAgICAgICAgIC4uLnRleHR1cmVUcmFuc2Zvcm1FeHQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH1cbiAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCBlbWlzc2l2ZUZhY3RvciA9IChtYXRlcmlhbFByb3BlcnRpZXMudmVjdG9yUHJvcGVydGllcz8uWydfRW1pc3Npb25Db2xvciddID8/IFswLjAsIDAuMCwgMC4wLCAxLjBdKS5tYXAoXG4gICAgICBnYW1tYUVPVEYsXG4gICAgKTtcbiAgICBjb25zdCBlbWlzc2l2ZVRleHR1cmVJbmRleCA9IG1hdGVyaWFsUHJvcGVydGllcy50ZXh0dXJlUHJvcGVydGllcz8uWydfRW1pc3Npb25NYXAnXTtcbiAgICBjb25zdCBlbWlzc2l2ZVRleHR1cmUgPVxuICAgICAgZW1pc3NpdmVUZXh0dXJlSW5kZXggIT0gbnVsbFxuICAgICAgICA/IHtcbiAgICAgICAgICAgIGluZGV4OiBlbWlzc2l2ZVRleHR1cmVJbmRleCxcbiAgICAgICAgICAgIGV4dGVuc2lvbnM6IHtcbiAgICAgICAgICAgICAgLi4udGV4dHVyZVRyYW5zZm9ybUV4dCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfVxuICAgICAgICA6IHVuZGVmaW5lZDtcblxuICAgIGNvbnN0IHNoYWRlQ29sb3JGYWN0b3IgPSAobWF0ZXJpYWxQcm9wZXJ0aWVzLnZlY3RvclByb3BlcnRpZXM/LlsnX1NoYWRlQ29sb3InXSA/PyBbMC45NywgMC44MSwgMC44NiwgMS4wXSkubWFwKFxuICAgICAgZ2FtbWFFT1RGLFxuICAgICk7XG4gICAgY29uc3Qgc2hhZGVNdWx0aXBseVRleHR1cmVJbmRleCA9IG1hdGVyaWFsUHJvcGVydGllcy50ZXh0dXJlUHJvcGVydGllcz8uWydfU2hhZGVUZXh0dXJlJ107XG4gICAgY29uc3Qgc2hhZGVNdWx0aXBseVRleHR1cmUgPVxuICAgICAgc2hhZGVNdWx0aXBseVRleHR1cmVJbmRleCAhPSBudWxsXG4gICAgICAgID8ge1xuICAgICAgICAgICAgaW5kZXg6IHNoYWRlTXVsdGlwbHlUZXh0dXJlSW5kZXgsXG4gICAgICAgICAgICBleHRlbnNpb25zOiB7XG4gICAgICAgICAgICAgIC4uLnRleHR1cmVUcmFuc2Zvcm1FeHQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH1cbiAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICAvLyAvLyBjb252ZXJ0IHYwIHNoYWRlIHNoaWZ0IC8gc2hhZGUgdG9vbnlcbiAgICBsZXQgc2hhZGluZ1NoaWZ0RmFjdG9yID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLmZsb2F0UHJvcGVydGllcz8uWydfU2hhZGVTaGlmdCddID8/IDAuMDtcbiAgICBsZXQgc2hhZGluZ1Rvb255RmFjdG9yID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLmZsb2F0UHJvcGVydGllcz8uWydfU2hhZGVUb29ueSddID8/IDAuOTtcbiAgICBzaGFkaW5nVG9vbnlGYWN0b3IgPSBUSFJFRS5NYXRoVXRpbHMubGVycChzaGFkaW5nVG9vbnlGYWN0b3IsIDEuMCwgMC41ICsgMC41ICogc2hhZGluZ1NoaWZ0RmFjdG9yKTtcbiAgICBzaGFkaW5nU2hpZnRGYWN0b3IgPSAtc2hhZGluZ1NoaWZ0RmFjdG9yIC0gKDEuMCAtIHNoYWRpbmdUb29ueUZhY3Rvcik7XG5cbiAgICBjb25zdCBnaUludGVuc2l0eUZhY3RvciA9IG1hdGVyaWFsUHJvcGVydGllcy5mbG9hdFByb3BlcnRpZXM/LlsnX0luZGlyZWN0TGlnaHRJbnRlbnNpdHknXSA/PyAwLjE7XG4gICAgY29uc3QgZ2lFcXVhbGl6YXRpb25GYWN0b3IgPSBnaUludGVuc2l0eUZhY3RvciA/IDEuMCAtIGdpSW50ZW5zaXR5RmFjdG9yIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgbWF0Y2FwVGV4dHVyZUluZGV4ID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLnRleHR1cmVQcm9wZXJ0aWVzPy5bJ19TcGhlcmVBZGQnXTtcbiAgICBjb25zdCBtYXRjYXBGYWN0b3IgPSBtYXRjYXBUZXh0dXJlSW5kZXggIT0gbnVsbCA/IFsxLjAsIDEuMCwgMS4wXSA6IHVuZGVmaW5lZDtcbiAgICBjb25zdCBtYXRjYXBUZXh0dXJlID1cbiAgICAgIG1hdGNhcFRleHR1cmVJbmRleCAhPSBudWxsXG4gICAgICAgID8ge1xuICAgICAgICAgICAgaW5kZXg6IG1hdGNhcFRleHR1cmVJbmRleCxcbiAgICAgICAgICB9XG4gICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgcmltTGlnaHRpbmdNaXhGYWN0b3IgPSBtYXRlcmlhbFByb3BlcnRpZXMuZmxvYXRQcm9wZXJ0aWVzPy5bJ19SaW1MaWdodGluZ01peCddID8/IDAuMDtcbiAgICBjb25zdCByaW1NdWx0aXBseVRleHR1cmVJbmRleCA9IG1hdGVyaWFsUHJvcGVydGllcy50ZXh0dXJlUHJvcGVydGllcz8uWydfUmltVGV4dHVyZSddO1xuICAgIGNvbnN0IHJpbU11bHRpcGx5VGV4dHVyZSA9XG4gICAgICByaW1NdWx0aXBseVRleHR1cmVJbmRleCAhPSBudWxsXG4gICAgICAgID8ge1xuICAgICAgICAgICAgaW5kZXg6IHJpbU11bHRpcGx5VGV4dHVyZUluZGV4LFxuICAgICAgICAgICAgZXh0ZW5zaW9uczoge1xuICAgICAgICAgICAgICAuLi50ZXh0dXJlVHJhbnNmb3JtRXh0LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9XG4gICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgcGFyYW1ldHJpY1JpbUNvbG9yRmFjdG9yID0gKG1hdGVyaWFsUHJvcGVydGllcy52ZWN0b3JQcm9wZXJ0aWVzPy5bJ19SaW1Db2xvciddID8/IFswLjAsIDAuMCwgMC4wLCAxLjBdKS5tYXAoXG4gICAgICBnYW1tYUVPVEYsXG4gICAgKTtcbiAgICBjb25zdCBwYXJhbWV0cmljUmltRnJlc25lbFBvd2VyRmFjdG9yID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLmZsb2F0UHJvcGVydGllcz8uWydfUmltRnJlc25lbFBvd2VyJ10gPz8gMS4wO1xuICAgIGNvbnN0IHBhcmFtZXRyaWNSaW1MaWZ0RmFjdG9yID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLmZsb2F0UHJvcGVydGllcz8uWydfUmltTGlmdCddID8/IDAuMDtcblxuICAgIGNvbnN0IG91dGxpbmVXaWR0aE1vZGUgPSBbJ25vbmUnLCAnd29ybGRDb29yZGluYXRlcycsICdzY3JlZW5Db29yZGluYXRlcyddW1xuICAgICAgbWF0ZXJpYWxQcm9wZXJ0aWVzLmZsb2F0UHJvcGVydGllcz8uWydfT3V0bGluZVdpZHRoTW9kZSddID8/IDBcbiAgICBdIGFzIFYxTVRvb25TY2hlbWEuTWF0ZXJpYWxzTVRvb25PdXRsaW5lV2lkdGhNb2RlO1xuXG4gICAgLy8gLy8gdjAgb3V0bGluZVdpZHRoRmFjdG9yIGlzIGluIGNlbnRpbWV0ZXJcbiAgICBsZXQgb3V0bGluZVdpZHRoRmFjdG9yID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLmZsb2F0UHJvcGVydGllcz8uWydfT3V0bGluZVdpZHRoJ10gPz8gMC4wO1xuICAgIG91dGxpbmVXaWR0aEZhY3RvciA9IDAuMDEgKiBvdXRsaW5lV2lkdGhGYWN0b3I7XG5cbiAgICBjb25zdCBvdXRsaW5lV2lkdGhNdWx0aXBseVRleHR1cmVJbmRleCA9IG1hdGVyaWFsUHJvcGVydGllcy50ZXh0dXJlUHJvcGVydGllcz8uWydfT3V0bGluZVdpZHRoVGV4dHVyZSddO1xuICAgIGNvbnN0IG91dGxpbmVXaWR0aE11bHRpcGx5VGV4dHVyZSA9XG4gICAgICBvdXRsaW5lV2lkdGhNdWx0aXBseVRleHR1cmVJbmRleCAhPSBudWxsXG4gICAgICAgID8ge1xuICAgICAgICAgICAgaW5kZXg6IG91dGxpbmVXaWR0aE11bHRpcGx5VGV4dHVyZUluZGV4LFxuICAgICAgICAgICAgZXh0ZW5zaW9uczoge1xuICAgICAgICAgICAgICAuLi50ZXh0dXJlVHJhbnNmb3JtRXh0LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9XG4gICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3Qgb3V0bGluZUNvbG9yRmFjdG9yID0gKG1hdGVyaWFsUHJvcGVydGllcy52ZWN0b3JQcm9wZXJ0aWVzPy5bJ19PdXRsaW5lQ29sb3InXSA/PyBbMC4wLCAwLjAsIDAuMF0pLm1hcChcbiAgICAgIGdhbW1hRU9URixcbiAgICApO1xuICAgIGNvbnN0IG91dGxpbmVDb2xvck1vZGUgPSBtYXRlcmlhbFByb3BlcnRpZXMuZmxvYXRQcm9wZXJ0aWVzPy5bJ19PdXRsaW5lQ29sb3JNb2RlJ10gPz8gMDsgLy8gZW51bSwgeyBGaXhlZCwgTWl4ZWQgfVxuICAgIGNvbnN0IG91dGxpbmVMaWdodGluZ01peEZhY3RvciA9XG4gICAgICBvdXRsaW5lQ29sb3JNb2RlID09PSAxID8gKG1hdGVyaWFsUHJvcGVydGllcy5mbG9hdFByb3BlcnRpZXM/LlsnX091dGxpbmVMaWdodGluZ01peCddID8/IDEuMCkgOiAwLjA7XG5cbiAgICBjb25zdCB1dkFuaW1hdGlvbk1hc2tUZXh0dXJlSW5kZXggPSBtYXRlcmlhbFByb3BlcnRpZXMudGV4dHVyZVByb3BlcnRpZXM/LlsnX1V2QW5pbU1hc2tUZXh0dXJlJ107XG4gICAgY29uc3QgdXZBbmltYXRpb25NYXNrVGV4dHVyZSA9XG4gICAgICB1dkFuaW1hdGlvbk1hc2tUZXh0dXJlSW5kZXggIT0gbnVsbFxuICAgICAgICA/IHtcbiAgICAgICAgICAgIGluZGV4OiB1dkFuaW1hdGlvbk1hc2tUZXh0dXJlSW5kZXgsXG4gICAgICAgICAgICBleHRlbnNpb25zOiB7XG4gICAgICAgICAgICAgIC4uLnRleHR1cmVUcmFuc2Zvcm1FeHQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgIH1cbiAgICAgICAgOiB1bmRlZmluZWQ7XG5cbiAgICBjb25zdCB1dkFuaW1hdGlvblNjcm9sbFhTcGVlZEZhY3RvciA9IG1hdGVyaWFsUHJvcGVydGllcy5mbG9hdFByb3BlcnRpZXM/LlsnX1V2QW5pbVNjcm9sbFgnXSA/PyAwLjA7XG5cbiAgICAvLyB1dkFuaW1hdGlvblNjcm9sbFlTcGVlZEZhY3RvciB3aWxsIGJlIG9wcG9zaXRlIGJldHdlZW4gVjAgYW5kIFYxXG4gICAgbGV0IHV2QW5pbWF0aW9uU2Nyb2xsWVNwZWVkRmFjdG9yID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLmZsb2F0UHJvcGVydGllcz8uWydfVXZBbmltU2Nyb2xsWSddID8/IDAuMDtcbiAgICBpZiAodXZBbmltYXRpb25TY3JvbGxZU3BlZWRGYWN0b3IgIT0gbnVsbCkge1xuICAgICAgdXZBbmltYXRpb25TY3JvbGxZU3BlZWRGYWN0b3IgPSAtdXZBbmltYXRpb25TY3JvbGxZU3BlZWRGYWN0b3I7XG4gICAgfVxuXG4gICAgY29uc3QgdXZBbmltYXRpb25Sb3RhdGlvblNwZWVkRmFjdG9yID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLmZsb2F0UHJvcGVydGllcz8uWydfVXZBbmltUm90YXRpb24nXSA/PyAwLjA7XG5cbiAgICBjb25zdCBtdG9vbkV4dGVuc2lvbjogVjFNVG9vblNjaGVtYS5WUk1DTWF0ZXJpYWxzTVRvb24gPSB7XG4gICAgICBzcGVjVmVyc2lvbjogJzEuMCcsXG4gICAgICB0cmFuc3BhcmVudFdpdGhaV3JpdGUsXG4gICAgICByZW5kZXJRdWV1ZU9mZnNldE51bWJlcixcbiAgICAgIHNoYWRlQ29sb3JGYWN0b3IsXG4gICAgICBzaGFkZU11bHRpcGx5VGV4dHVyZSxcbiAgICAgIHNoYWRpbmdTaGlmdEZhY3RvcixcbiAgICAgIHNoYWRpbmdUb29ueUZhY3RvcixcbiAgICAgIGdpRXF1YWxpemF0aW9uRmFjdG9yLFxuICAgICAgbWF0Y2FwRmFjdG9yLFxuICAgICAgbWF0Y2FwVGV4dHVyZSxcbiAgICAgIHJpbUxpZ2h0aW5nTWl4RmFjdG9yLFxuICAgICAgcmltTXVsdGlwbHlUZXh0dXJlLFxuICAgICAgcGFyYW1ldHJpY1JpbUNvbG9yRmFjdG9yLFxuICAgICAgcGFyYW1ldHJpY1JpbUZyZXNuZWxQb3dlckZhY3RvcixcbiAgICAgIHBhcmFtZXRyaWNSaW1MaWZ0RmFjdG9yLFxuICAgICAgb3V0bGluZVdpZHRoTW9kZSxcbiAgICAgIG91dGxpbmVXaWR0aEZhY3RvcixcbiAgICAgIG91dGxpbmVXaWR0aE11bHRpcGx5VGV4dHVyZSxcbiAgICAgIG91dGxpbmVDb2xvckZhY3RvcixcbiAgICAgIG91dGxpbmVMaWdodGluZ01peEZhY3RvcixcbiAgICAgIHV2QW5pbWF0aW9uTWFza1RleHR1cmUsXG4gICAgICB1dkFuaW1hdGlvblNjcm9sbFhTcGVlZEZhY3RvcixcbiAgICAgIHV2QW5pbWF0aW9uU2Nyb2xsWVNwZWVkRmFjdG9yLFxuICAgICAgdXZBbmltYXRpb25Sb3RhdGlvblNwZWVkRmFjdG9yLFxuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uc2NoZW1hTWF0ZXJpYWwsXG5cbiAgICAgIHBick1ldGFsbGljUm91Z2huZXNzOiB7XG4gICAgICAgIGJhc2VDb2xvckZhY3RvcixcbiAgICAgICAgYmFzZUNvbG9yVGV4dHVyZSxcbiAgICAgIH0sXG4gICAgICBub3JtYWxUZXh0dXJlLFxuICAgICAgZW1pc3NpdmVUZXh0dXJlLFxuICAgICAgZW1pc3NpdmVGYWN0b3IsXG4gICAgICBhbHBoYU1vZGUsXG4gICAgICBhbHBoYUN1dG9mZixcbiAgICAgIGRvdWJsZVNpZGVkLFxuICAgICAgZXh0ZW5zaW9uczoge1xuICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXG4gICAgICAgIFZSTUNfbWF0ZXJpYWxzX210b29uOiBtdG9vbkV4dGVuc2lvbixcbiAgICAgIH0sXG4gICAgfTtcbiAgfVxuXG4gIHByaXZhdGUgX3BhcnNlVjBVbmxpdFByb3BlcnRpZXMoXG4gICAgbWF0ZXJpYWxQcm9wZXJ0aWVzOiBWME1hdGVyaWFsLFxuICAgIHNjaGVtYU1hdGVyaWFsOiBHTFRGU2NoZW1hLklNYXRlcmlhbCxcbiAgKTogR0xURlNjaGVtYS5JTWF0ZXJpYWwge1xuICAgIGNvbnN0IGlzVHJhbnNwYXJlbnRaV3JpdGUgPSBtYXRlcmlhbFByb3BlcnRpZXMuc2hhZGVyID09PSAnVlJNL1VubGl0VHJhbnNwYXJlbnRaV3JpdGUnO1xuICAgIGNvbnN0IGlzVHJhbnNwYXJlbnQgPSBtYXRlcmlhbFByb3BlcnRpZXMuc2hhZGVyID09PSAnVlJNL1VubGl0VHJhbnNwYXJlbnQnIHx8IGlzVHJhbnNwYXJlbnRaV3JpdGU7XG5cbiAgICBjb25zdCByZW5kZXJRdWV1ZU9mZnNldE51bWJlciA9IHRoaXMuX3YwUGFyc2VSZW5kZXJRdWV1ZShtYXRlcmlhbFByb3BlcnRpZXMpO1xuXG4gICAgY29uc3QgaXNDdXRvZmYgPSBtYXRlcmlhbFByb3BlcnRpZXMuc2hhZGVyID09PSAnVlJNL1VubGl0Q3V0b3V0JztcbiAgICBjb25zdCBhbHBoYU1vZGUgPSBpc1RyYW5zcGFyZW50ID8gJ0JMRU5EJyA6IGlzQ3V0b2ZmID8gJ01BU0snIDogJ09QQVFVRSc7XG4gICAgY29uc3QgYWxwaGFDdXRvZmYgPSBpc0N1dG9mZiA/IChtYXRlcmlhbFByb3BlcnRpZXMuZmxvYXRQcm9wZXJ0aWVzPy5bJ19DdXRvZmYnXSA/PyAwLjUpIDogdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgdGV4dHVyZVRyYW5zZm9ybUV4dCA9IHRoaXMuX3BvcnRUZXh0dXJlVHJhbnNmb3JtKG1hdGVyaWFsUHJvcGVydGllcyk7XG5cbiAgICBjb25zdCBiYXNlQ29sb3JGYWN0b3IgPSAobWF0ZXJpYWxQcm9wZXJ0aWVzLnZlY3RvclByb3BlcnRpZXM/LlsnX0NvbG9yJ10gPz8gWzEuMCwgMS4wLCAxLjAsIDEuMF0pLm1hcChnYW1tYUVPVEYpO1xuICAgIGNvbnN0IGJhc2VDb2xvclRleHR1cmVJbmRleCA9IG1hdGVyaWFsUHJvcGVydGllcy50ZXh0dXJlUHJvcGVydGllcz8uWydfTWFpblRleCddO1xuICAgIGNvbnN0IGJhc2VDb2xvclRleHR1cmUgPVxuICAgICAgYmFzZUNvbG9yVGV4dHVyZUluZGV4ICE9IG51bGxcbiAgICAgICAgPyB7XG4gICAgICAgICAgICBpbmRleDogYmFzZUNvbG9yVGV4dHVyZUluZGV4LFxuICAgICAgICAgICAgZXh0ZW5zaW9uczoge1xuICAgICAgICAgICAgICAuLi50ZXh0dXJlVHJhbnNmb3JtRXh0LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9XG4gICAgICAgIDogdW5kZWZpbmVkO1xuXG4gICAgLy8gdXNlIG10b29uIGluc3RlYWQgb2YgdW5saXQsIHNpbmNlIHRoZXJlIG1pZ2h0IGJlIFZSTTAuMCBzcGVjaWZpYyBmZWF0dXJlcyB0aGF0IGFyZSBub3Qgc3VwcG9ydGVkIGJ5IGdsdGZcbiAgICBjb25zdCBtdG9vbkV4dGVuc2lvbjogVjFNVG9vblNjaGVtYS5WUk1DTWF0ZXJpYWxzTVRvb24gPSB7XG4gICAgICBzcGVjVmVyc2lvbjogJzEuMCcsXG4gICAgICB0cmFuc3BhcmVudFdpdGhaV3JpdGU6IGlzVHJhbnNwYXJlbnRaV3JpdGUsXG4gICAgICByZW5kZXJRdWV1ZU9mZnNldE51bWJlcixcbiAgICAgIHNoYWRlQ29sb3JGYWN0b3I6IGJhc2VDb2xvckZhY3RvcixcbiAgICAgIHNoYWRlTXVsdGlwbHlUZXh0dXJlOiBiYXNlQ29sb3JUZXh0dXJlLFxuICAgIH07XG5cbiAgICByZXR1cm4ge1xuICAgICAgLi4uc2NoZW1hTWF0ZXJpYWwsXG5cbiAgICAgIHBick1ldGFsbGljUm91Z2huZXNzOiB7XG4gICAgICAgIGJhc2VDb2xvckZhY3RvcixcbiAgICAgICAgYmFzZUNvbG9yVGV4dHVyZSxcbiAgICAgIH0sXG4gICAgICBhbHBoYU1vZGUsXG4gICAgICBhbHBoYUN1dG9mZixcbiAgICAgIGV4dGVuc2lvbnM6IHtcbiAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxuICAgICAgICBWUk1DX21hdGVyaWFsc19tdG9vbjogbXRvb25FeHRlbnNpb24sXG4gICAgICB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgZ2xURiBgS0hSX3RleHR1cmVfdHJhbnNmb3JtYCBleHRlbnNpb24gZnJvbSB2MCB0ZXh0dXJlIHRyYW5zZm9ybSBpbmZvLlxuICAgKi9cbiAgcHJpdmF0ZSBfcG9ydFRleHR1cmVUcmFuc2Zvcm0obWF0ZXJpYWxQcm9wZXJ0aWVzOiBWME1hdGVyaWFsKTogeyBbbmFtZTogc3RyaW5nXTogYW55IH0ge1xuICAgIGNvbnN0IHRleHR1cmVUcmFuc2Zvcm0gPSBtYXRlcmlhbFByb3BlcnRpZXMudmVjdG9yUHJvcGVydGllcz8uWydfTWFpblRleCddO1xuICAgIGlmICh0ZXh0dXJlVHJhbnNmb3JtID09IG51bGwpIHtcbiAgICAgIHJldHVybiB7fTtcbiAgICB9XG5cbiAgICBjb25zdCBvZmZzZXQgPSBbdGV4dHVyZVRyYW5zZm9ybT8uWzBdID8/IDAuMCwgdGV4dHVyZVRyYW5zZm9ybT8uWzFdID8/IDAuMF07XG4gICAgY29uc3Qgc2NhbGUgPSBbdGV4dHVyZVRyYW5zZm9ybT8uWzJdID8/IDEuMCwgdGV4dHVyZVRyYW5zZm9ybT8uWzNdID8/IDEuMF07XG5cbiAgICBvZmZzZXRbMV0gPSAxLjAgLSBzY2FsZVsxXSAtIG9mZnNldFsxXTtcblxuICAgIHJldHVybiB7XG4gICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXG4gICAgICBLSFJfdGV4dHVyZV90cmFuc2Zvcm06IHsgb2Zmc2V0LCBzY2FsZSB9LFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCB2MCByZW5kZXIgb3JkZXIgaW50byB2MSByZW5kZXIgb3JkZXIuXG4gICAqIFRoaXMgdXNlcyBhIG1hcCBmcm9tIHYwIHJlbmRlciBxdWV1ZSB0byB2MSBjb21wbGlhbnQgcmVuZGVyIHF1ZXVlIG9mZnNldCB3aGljaCBpcyBnZW5lcmF0ZWQgaW4ge0BsaW5rIF9wb3B1bGF0ZVJlbmRlclF1ZXVlTWFwfS5cbiAgICovXG4gIHByaXZhdGUgX3YwUGFyc2VSZW5kZXJRdWV1ZShtYXRlcmlhbFByb3BlcnRpZXM6IFYwTWF0ZXJpYWwpOiBudW1iZXIge1xuICAgIGNvbnN0IGlzVHJhbnNwYXJlbnRaV3JpdGUgPSBtYXRlcmlhbFByb3BlcnRpZXMuc2hhZGVyID09PSAnVlJNL1VubGl0VHJhbnNwYXJlbnRaV3JpdGUnO1xuICAgIGNvbnN0IGlzVHJhbnNwYXJlbnQgPVxuICAgICAgbWF0ZXJpYWxQcm9wZXJ0aWVzLmtleXdvcmRNYXA/LlsnX0FMUEhBQkxFTkRfT04nXSAhPSB1bmRlZmluZWQgfHxcbiAgICAgIG1hdGVyaWFsUHJvcGVydGllcy5zaGFkZXIgPT09ICdWUk0vVW5saXRUcmFuc3BhcmVudCcgfHxcbiAgICAgIGlzVHJhbnNwYXJlbnRaV3JpdGU7XG4gICAgY29uc3QgZW5hYmxlZFpXcml0ZSA9IG1hdGVyaWFsUHJvcGVydGllcy5mbG9hdFByb3BlcnRpZXM/LlsnX1pXcml0ZSddID09PSAxIHx8IGlzVHJhbnNwYXJlbnRaV3JpdGU7XG5cbiAgICBsZXQgb2Zmc2V0ID0gMDtcblxuICAgIGlmIChpc1RyYW5zcGFyZW50KSB7XG4gICAgICBjb25zdCB2MFF1ZXVlID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLnJlbmRlclF1ZXVlO1xuXG4gICAgICBpZiAodjBRdWV1ZSAhPSBudWxsKSB7XG4gICAgICAgIGlmIChlbmFibGVkWldyaXRlKSB7XG4gICAgICAgICAgb2Zmc2V0ID0gdGhpcy5fcmVuZGVyUXVldWVNYXBUcmFuc3BhcmVudFpXcml0ZS5nZXQodjBRdWV1ZSkhO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIG9mZnNldCA9IHRoaXMuX3JlbmRlclF1ZXVlTWFwVHJhbnNwYXJlbnQuZ2V0KHYwUXVldWUpITtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvZmZzZXQ7XG4gIH1cblxuICAvKipcbiAgICogQ3JlYXRlIGEgbWFwIHdoaWNoIG1hcHMgdjAgcmVuZGVyIHF1ZXVlIHRvIHYxIGNvbXBsaWFudCByZW5kZXIgcXVldWUgb2Zmc2V0LlxuICAgKiBUaGlzIGxpc3RzIHVwIGFsbCByZW5kZXIgcXVldWVzIHRoZSBtb2RlbCB1c2UgYW5kIGNyZWF0ZXMgYSBtYXAgdG8gbmV3IHJlbmRlciBxdWV1ZSBvZmZzZXRzIGluIHRoZSBzYW1lIG9yZGVyLlxuICAgKi9cbiAgcHJpdmF0ZSBfcG9wdWxhdGVSZW5kZXJRdWV1ZU1hcChtYXRlcmlhbFByb3BlcnRpZXNMaXN0OiBWME1hdGVyaWFsW10pIHtcbiAgICAvKipcbiAgICAgKiBBIHNldCBvZiB1c2VkIHJlbmRlciBxdWV1ZXMgaW4gVHJhbnNwYXJlbnQgbWF0ZXJpYWxzLlxuICAgICAqL1xuICAgIGNvbnN0IHJlbmRlclF1ZXVlc1RyYW5zcGFyZW50ID0gbmV3IFNldDxudW1iZXI+KCk7XG5cbiAgICAvKipcbiAgICAgKiBBIHNldCBvZiB1c2VkIHJlbmRlciBxdWV1ZXMgaW4gVHJhbnNwYXJlbnRaV3JpdGUgbWF0ZXJpYWxzLlxuICAgICAqL1xuICAgIGNvbnN0IHJlbmRlclF1ZXVlc1RyYW5zcGFyZW50WldyaXRlID0gbmV3IFNldDxudW1iZXI+KCk7XG5cbiAgICAvLyBwb3B1bGF0ZSB0aGUgcmVuZGVyIHF1ZXVlIHNldFxuICAgIG1hdGVyaWFsUHJvcGVydGllc0xpc3QuZm9yRWFjaCgobWF0ZXJpYWxQcm9wZXJ0aWVzKSA9PiB7XG4gICAgICBjb25zdCBpc1RyYW5zcGFyZW50WldyaXRlID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLnNoYWRlciA9PT0gJ1ZSTS9VbmxpdFRyYW5zcGFyZW50WldyaXRlJztcbiAgICAgIGNvbnN0IGlzVHJhbnNwYXJlbnQgPVxuICAgICAgICBtYXRlcmlhbFByb3BlcnRpZXMua2V5d29yZE1hcD8uWydfQUxQSEFCTEVORF9PTiddICE9IHVuZGVmaW5lZCB8fFxuICAgICAgICBtYXRlcmlhbFByb3BlcnRpZXMuc2hhZGVyID09PSAnVlJNL1VubGl0VHJhbnNwYXJlbnQnIHx8XG4gICAgICAgIGlzVHJhbnNwYXJlbnRaV3JpdGU7XG4gICAgICBjb25zdCBlbmFibGVkWldyaXRlID0gbWF0ZXJpYWxQcm9wZXJ0aWVzLmZsb2F0UHJvcGVydGllcz8uWydfWldyaXRlJ10gPT09IDEgfHwgaXNUcmFuc3BhcmVudFpXcml0ZTtcblxuICAgICAgaWYgKGlzVHJhbnNwYXJlbnQpIHtcbiAgICAgICAgY29uc3QgdjBRdWV1ZSA9IG1hdGVyaWFsUHJvcGVydGllcy5yZW5kZXJRdWV1ZTtcblxuICAgICAgICBpZiAodjBRdWV1ZSAhPSBudWxsKSB7XG4gICAgICAgICAgaWYgKGVuYWJsZWRaV3JpdGUpIHtcbiAgICAgICAgICAgIHJlbmRlclF1ZXVlc1RyYW5zcGFyZW50WldyaXRlLmFkZCh2MFF1ZXVlKTtcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVuZGVyUXVldWVzVHJhbnNwYXJlbnQuYWRkKHYwUXVldWUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuXG4gICAgLy8gc2hvdyBhIHdhcm5pbmcgaWYgdGhlIG1vZGVsIHVzZXMgdjEgaW5jb21wYXRpYmxlIG51bWJlciBvZiByZW5kZXIgcXVldWVzXG4gICAgaWYgKHJlbmRlclF1ZXVlc1RyYW5zcGFyZW50LnNpemUgPiAxMCkge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgVlJNTWF0ZXJpYWxzVjBDb21wYXRQbHVnaW46IFRoaXMgVlJNIHVzZXMgJHtyZW5kZXJRdWV1ZXNUcmFuc3BhcmVudC5zaXplfSByZW5kZXIgcXVldWVzIGZvciBUcmFuc3BhcmVudCBtYXRlcmlhbHMgd2hpbGUgVlJNIDEuMCBvbmx5IHN1cHBvcnRzIHVwIHRvIDEwIHJlbmRlciBxdWV1ZXMuIFRoZSBtb2RlbCBtaWdodCBub3QgYmUgcmVuZGVyZWQgY29ycmVjdGx5LmAsXG4gICAgICApO1xuICAgIH1cblxuICAgIGlmIChyZW5kZXJRdWV1ZXNUcmFuc3BhcmVudFpXcml0ZS5zaXplID4gMTApIHtcbiAgICAgIGNvbnNvbGUud2FybihcbiAgICAgICAgYFZSTU1hdGVyaWFsc1YwQ29tcGF0UGx1Z2luOiBUaGlzIFZSTSB1c2VzICR7cmVuZGVyUXVldWVzVHJhbnNwYXJlbnRaV3JpdGUuc2l6ZX0gcmVuZGVyIHF1ZXVlcyBmb3IgVHJhbnNwYXJlbnRaV3JpdGUgbWF0ZXJpYWxzIHdoaWxlIFZSTSAxLjAgb25seSBzdXBwb3J0cyB1cCB0byAxMCByZW5kZXIgcXVldWVzLiBUaGUgbW9kZWwgbWlnaHQgbm90IGJlIHJlbmRlcmVkIGNvcnJlY3RseS5gLFxuICAgICAgKTtcbiAgICB9XG5cbiAgICAvLyBjcmVhdGUgYSBtYXAgZnJvbSB2MCByZW5kZXIgcXVldWUgdG8gdjEgcmVuZGVyIHF1ZXVlIG9mZnNldFxuICAgIEFycmF5LmZyb20ocmVuZGVyUXVldWVzVHJhbnNwYXJlbnQpXG4gICAgICAuc29ydCgpXG4gICAgICAuZm9yRWFjaCgocXVldWUsIGkpID0+IHtcbiAgICAgICAgY29uc3QgbmV3UXVldWVPZmZzZXQgPSBNYXRoLm1pbihNYXRoLm1heChpIC0gcmVuZGVyUXVldWVzVHJhbnNwYXJlbnQuc2l6ZSArIDEsIC05KSwgMCk7XG4gICAgICAgIHRoaXMuX3JlbmRlclF1ZXVlTWFwVHJhbnNwYXJlbnQuc2V0KHF1ZXVlLCBuZXdRdWV1ZU9mZnNldCk7XG4gICAgICB9KTtcblxuICAgIEFycmF5LmZyb20ocmVuZGVyUXVldWVzVHJhbnNwYXJlbnRaV3JpdGUpXG4gICAgICAuc29ydCgpXG4gICAgICAuZm9yRWFjaCgocXVldWUsIGkpID0+IHtcbiAgICAgICAgY29uc3QgbmV3UXVldWVPZmZzZXQgPSBNYXRoLm1pbihNYXRoLm1heChpLCAwKSwgOSk7XG4gICAgICAgIHRoaXMuX3JlbmRlclF1ZXVlTWFwVHJhbnNwYXJlbnRaV3JpdGUuc2V0KHF1ZXVlLCBuZXdRdWV1ZU9mZnNldCk7XG4gICAgICB9KTtcbiAgfVxufVxuIiwgImV4cG9ydCBmdW5jdGlvbiBnYW1tYUVPVEYoZTogbnVtYmVyKTogbnVtYmVyIHtcbiAgcmV0dXJuIE1hdGgucG93KGUsIDIuMik7XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOzs7QUNBQSxZQUF1Qjs7O0FDQWhCLFNBQVMsVUFBVSxHQUFtQjtBQUMzQyxTQUFPLEtBQUssSUFBSSxHQUFHLEdBQUc7QUFDeEI7OztBREtPLElBQU0sNkJBQU4sTUFBNkQ7QUFBQSxFQWFsRSxJQUFXLE9BQWU7QUFDeEIsV0FBTztBQUFBLEVBQ1Q7QUFBQSxFQUVPLFlBQVksUUFBb0I7QUF4QnpDO0FBeUJJLFNBQUssU0FBUztB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