(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(require("babylonjs")); else if(typeof define === 'function' && define.amd) define("babylonjs-loaders", ["babylonjs"], factory); else if(typeof exports === 'object') exports["babylonjs-loaders"] = factory(require("babylonjs")); else root["LOADERS"] = factory(root["BABYLON"]); })((typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : this), (__WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_observable__) => { return /******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ "../../../dev/loaders/src/OBJ/index.ts": /*!*********************************************!*\ !*** ../../../dev/loaders/src/OBJ/index.ts ***! \*********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MTLFileLoader: () => (/* reexport safe */ _mtlFileLoader__WEBPACK_IMPORTED_MODULE_0__.MTLFileLoader), /* harmony export */ OBJFileLoader: () => (/* reexport safe */ _objFileLoader__WEBPACK_IMPORTED_MODULE_3__.OBJFileLoader), /* harmony export */ SolidParser: () => (/* reexport safe */ _solidParser__WEBPACK_IMPORTED_MODULE_2__.SolidParser) /* harmony export */ }); /* harmony import */ var _mtlFileLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./mtlFileLoader */ "../../../dev/loaders/src/OBJ/mtlFileLoader.ts"); /* harmony import */ var _objLoadingOptions__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./objLoadingOptions */ "../../../dev/loaders/src/OBJ/objLoadingOptions.ts"); /* harmony import */ var _solidParser__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./solidParser */ "../../../dev/loaders/src/OBJ/solidParser.ts"); /* harmony import */ var _objFileLoader__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./objFileLoader */ "../../../dev/loaders/src/OBJ/objFileLoader.ts"); /***/ }), /***/ "../../../dev/loaders/src/OBJ/mtlFileLoader.ts": /*!*****************************************************!*\ !*** ../../../dev/loaders/src/OBJ/mtlFileLoader.ts ***! \*****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MTLFileLoader: () => (/* binding */ MTLFileLoader) /* harmony export */ }); /* harmony import */ var babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/standardMaterial */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__); /** * Class reading and parsing the MTL file bundled with the obj file. */ var MTLFileLoader = /** @class */ (function () { function MTLFileLoader() { /** * All material loaded from the mtl will be set here */ this.materials = []; } /** * This function will read the mtl file and create each material described inside * This function could be improve by adding : * -some component missing (Ni, Tf...) * -including the specific options available * * @param scene defines the scene the material will be created in * @param data defines the mtl data to parse * @param rootUrl defines the rooturl to use in order to load relative dependencies * @param assetContainer defines the asset container to store the material in (can be null) */ MTLFileLoader.prototype.parseMTL = function (scene, data, rootUrl, assetContainer) { if (data instanceof ArrayBuffer) { return; } //Split the lines from the file var lines = data.split("\n"); // whitespace char ie: [ \t\r\n\f] var delimiter_pattern = /\s+/; //Array with RGB colors var color; //New material var material = null; //Look at each line for (var i = 0; i < lines.length; i++) { var line = lines[i].trim(); // Blank line or comment if (line.length === 0 || line.charAt(0) === "#") { continue; } //Get the first parameter (keyword) var pos = line.indexOf(" "); var key = pos >= 0 ? line.substring(0, pos) : line; key = key.toLowerCase(); //Get the data following the key var value = pos >= 0 ? line.substring(pos + 1).trim() : ""; //This mtl keyword will create the new material if (key === "newmtl") { //Check if it is the first material. // Materials specifications are described after this keyword. if (material) { //Add the previous material in the material array. this.materials.push(material); } //Create a new material. // value is the name of the material read in the mtl file scene._blockEntityCollection = !!assetContainer; material = new babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.StandardMaterial(value, scene); material._parentContainer = assetContainer; scene._blockEntityCollection = false; } else if (key === "kd" && material) { // Diffuse color (color under white light) using RGB values //value = "r g b" color = value.split(delimiter_pattern, 3).map(parseFloat); //color = [r,g,b] //Set tghe color into the material material.diffuseColor = babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(color); } else if (key === "ka" && material) { // Ambient color (color under shadow) using RGB values //value = "r g b" color = value.split(delimiter_pattern, 3).map(parseFloat); //color = [r,g,b] //Set tghe color into the material material.ambientColor = babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(color); } else if (key === "ks" && material) { // Specular color (color when light is reflected from shiny surface) using RGB values //value = "r g b" color = value.split(delimiter_pattern, 3).map(parseFloat); //color = [r,g,b] //Set the color into the material material.specularColor = babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(color); } else if (key === "ke" && material) { // Emissive color using RGB values color = value.split(delimiter_pattern, 3).map(parseFloat); material.emissiveColor = babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(color); } else if (key === "ns" && material) { //value = "Integer" material.specularPower = parseFloat(value); } else if (key === "d" && material) { //d is dissolve for current material. It mean alpha for BABYLON material.alpha = parseFloat(value); //Texture //This part can be improved by adding the possible options of texture } else if (key === "map_ka" && material) { // ambient texture map with a loaded image //We must first get the folder of the image material.ambientTexture = MTLFileLoader._GetTexture(rootUrl, value, scene); } else if (key === "map_kd" && material) { // Diffuse texture map with a loaded image material.diffuseTexture = MTLFileLoader._GetTexture(rootUrl, value, scene); } else if (key === "map_ks" && material) { // Specular texture map with a loaded image //We must first get the folder of the image material.specularTexture = MTLFileLoader._GetTexture(rootUrl, value, scene); } else if (key === "map_ns") { //Specular //Specular highlight component //We must first get the folder of the image // //Not supported by BABYLON // // continue; } else if (key === "map_bump" && material) { //The bump texture var values = value.split(delimiter_pattern); var bumpMultiplierIndex = values.indexOf("-bm"); var bumpMultiplier = null; if (bumpMultiplierIndex >= 0) { bumpMultiplier = values[bumpMultiplierIndex + 1]; values.splice(bumpMultiplierIndex, 2); // remove } material.bumpTexture = MTLFileLoader._GetTexture(rootUrl, values.join(" "), scene); if (material.bumpTexture && bumpMultiplier !== null) { material.bumpTexture.level = parseFloat(bumpMultiplier); } } else if (key === "map_d" && material) { // The dissolve of the material material.opacityTexture = MTLFileLoader._GetTexture(rootUrl, value, scene); //Options for illumination } else if (key === "illum") { //Illumination if (value === "0") { //That mean Kd == Kd } else if (value === "1") { //Color on and Ambient on } else if (value === "2") { //Highlight on } else if (value === "3") { //Reflection on and Ray trace on } else if (value === "4") { //Transparency: Glass on, Reflection: Ray trace on } else if (value === "5") { //Reflection: Fresnel on and Ray trace on } else if (value === "6") { //Transparency: Refraction on, Reflection: Fresnel off and Ray trace on } else if (value === "7") { //Transparency: Refraction on, Reflection: Fresnel on and Ray trace on } else if (value === "8") { //Reflection on and Ray trace off } else if (value === "9") { //Transparency: Glass on, Reflection: Ray trace off } else if (value === "10") { //Casts shadows onto invisible surfaces } } else { // console.log("Unhandled expression at line : " + i +'\n' + "with value : " + line); } } //At the end of the file, add the last material if (material) { this.materials.push(material); } }; /** * Gets the texture for the material. * * If the material is imported from input file, * We sanitize the url to ensure it takes the texture from aside the material. * * @param rootUrl The root url to load from * @param value The value stored in the mtl * @param scene * @returns The Texture */ MTLFileLoader._GetTexture = function (rootUrl, value, scene) { if (!value) { return null; } var url = rootUrl; // Load from input file. if (rootUrl === "file:") { var lastDelimiter = value.lastIndexOf("\\"); if (lastDelimiter === -1) { lastDelimiter = value.lastIndexOf("/"); } if (lastDelimiter > -1) { url += value.substr(lastDelimiter + 1); } else { url += value; } } // Not from input file. else { url += value; } return new babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Texture(url, scene, false, MTLFileLoader.INVERT_TEXTURE_Y); }; /** * Invert Y-Axis of referenced textures on load */ MTLFileLoader.INVERT_TEXTURE_Y = true; return MTLFileLoader; }()); /***/ }), /***/ "../../../dev/loaders/src/OBJ/objFileLoader.ts": /*!*****************************************************!*\ !*** ../../../dev/loaders/src/OBJ/objFileLoader.ts ***! \*****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ OBJFileLoader: () => (/* binding */ OBJFileLoader) /* harmony export */ }); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/assetContainer */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _mtlFileLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./mtlFileLoader */ "../../../dev/loaders/src/OBJ/mtlFileLoader.ts"); /* harmony import */ var _solidParser__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./solidParser */ "../../../dev/loaders/src/OBJ/solidParser.ts"); /** * OBJ file type loader. * This is a babylon scene loader plugin. */ var OBJFileLoader = /** @class */ (function () { /** * Creates loader for .OBJ files * * @param loadingOptions options for loading and parsing OBJ/MTL files. */ function OBJFileLoader(loadingOptions) { /** * Defines the name of the plugin. */ this.name = "obj"; /** * Defines the extension the plugin is able to load. */ this.extensions = ".obj"; this._assetContainer = null; this._loadingOptions = loadingOptions || OBJFileLoader._DefaultLoadingOptions; } Object.defineProperty(OBJFileLoader, "INVERT_TEXTURE_Y", { /** * Invert Y-Axis of referenced textures on load */ get: function () { return _mtlFileLoader__WEBPACK_IMPORTED_MODULE_1__.MTLFileLoader.INVERT_TEXTURE_Y; }, set: function (value) { _mtlFileLoader__WEBPACK_IMPORTED_MODULE_1__.MTLFileLoader.INVERT_TEXTURE_Y = value; }, enumerable: false, configurable: true }); Object.defineProperty(OBJFileLoader, "_DefaultLoadingOptions", { get: function () { return { computeNormals: OBJFileLoader.COMPUTE_NORMALS, optimizeNormals: OBJFileLoader.OPTIMIZE_NORMALS, importVertexColors: OBJFileLoader.IMPORT_VERTEX_COLORS, invertY: OBJFileLoader.INVERT_Y, invertTextureY: OBJFileLoader.INVERT_TEXTURE_Y, // eslint-disable-next-line @typescript-eslint/naming-convention UVScaling: OBJFileLoader.UV_SCALING, materialLoadingFailsSilently: OBJFileLoader.MATERIAL_LOADING_FAILS_SILENTLY, optimizeWithUV: OBJFileLoader.OPTIMIZE_WITH_UV, skipMaterials: OBJFileLoader.SKIP_MATERIALS, }; }, enumerable: false, configurable: true }); /** * Calls synchronously the MTL file attached to this obj. * Load function or importMesh function don't enable to load 2 files in the same time asynchronously. * Without this function materials are not displayed in the first frame (but displayed after). * In consequence it is impossible to get material information in your HTML file * * @param url The URL of the MTL file * @param rootUrl defines where to load data from * @param onSuccess Callback function to be called when the MTL file is loaded * @param onFailure */ OBJFileLoader.prototype._loadMTL = function (url, rootUrl, onSuccess, onFailure) { //The complete path to the mtl file var pathOfFile = rootUrl + url; // Loads through the babylon tools to allow fileInput search. babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Tools.LoadFile(pathOfFile, onSuccess, undefined, undefined, false, function (request, exception) { onFailure(pathOfFile, exception); }); }; /** * Instantiates a OBJ file loader plugin. * @returns the created plugin */ OBJFileLoader.prototype.createPlugin = function () { return new OBJFileLoader(OBJFileLoader._DefaultLoadingOptions); }; /** * If the data string can be loaded directly. * @returns if the data can be loaded directly */ OBJFileLoader.prototype.canDirectLoad = function () { return false; }; /** * Imports one or more meshes from the loaded OBJ data and adds them to the scene * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file * @param scene the scene the meshes should be added to * @param data the OBJ data to load * @param rootUrl root url to load from * @returns a promise containing the loaded meshes, particles, skeletons and animations */ OBJFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl) { //get the meshes from OBJ file return this._parseSolid(meshesNames, scene, data, rootUrl).then(function (meshes) { return { meshes: meshes, particleSystems: [], skeletons: [], animationGroups: [], transformNodes: [], geometries: [], lights: [], }; }); }; /** * Imports all objects from the loaded OBJ data and adds them to the scene * @param scene the scene the objects should be added to * @param data the OBJ data to load * @param rootUrl root url to load from * @returns a promise which completes when objects have been loaded to the scene */ OBJFileLoader.prototype.loadAsync = function (scene, data, rootUrl) { //Get the 3D model return this.importMeshAsync(null, scene, data, rootUrl).then(function () { // return void }); }; /** * Load into an asset container. * @param scene The scene to load into * @param data The data to import * @param rootUrl The root url for scene and resources * @returns The loaded asset container */ OBJFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl) { var _this = this; var container = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.AssetContainer(scene); this._assetContainer = container; return this.importMeshAsync(null, scene, data, rootUrl) .then(function (result) { result.meshes.forEach(function (mesh) { return container.meshes.push(mesh); }); result.meshes.forEach(function (mesh) { var material = mesh.material; if (material) { // Materials if (container.materials.indexOf(material) == -1) { container.materials.push(material); // Textures var textures = material.getActiveTextures(); textures.forEach(function (t) { if (container.textures.indexOf(t) == -1) { container.textures.push(t); } }); } } }); _this._assetContainer = null; return container; }) .catch(function (ex) { _this._assetContainer = null; throw ex; }); }; /** * Read the OBJ file and create an Array of meshes. * Each mesh contains all information given by the OBJ and the MTL file. * i.e. vertices positions and indices, optional normals values, optional UV values, optional material * @param meshesNames defines a string or array of strings of the mesh names that should be loaded from the file * @param scene defines the scene where are displayed the data * @param data defines the content of the obj file * @param rootUrl defines the path to the folder * @returns the list of loaded meshes */ OBJFileLoader.prototype._parseSolid = function (meshesNames, scene, data, rootUrl) { var _this = this; var fileToLoad = ""; //The name of the mtlFile to load var materialsFromMTLFile = new _mtlFileLoader__WEBPACK_IMPORTED_MODULE_1__.MTLFileLoader(); var materialToUse = new Array(); var babylonMeshesArray = []; //The mesh for babylon // Main function var solidParser = new _solidParser__WEBPACK_IMPORTED_MODULE_2__.SolidParser(materialToUse, babylonMeshesArray, this._loadingOptions); solidParser.parse(meshesNames, data, scene, this._assetContainer, function (fileName) { fileToLoad = fileName; }); // load the materials var mtlPromises = []; // Check if we have a file to load if (fileToLoad !== "" && !this._loadingOptions.skipMaterials) { //Load the file synchronously mtlPromises.push(new Promise(function (resolve, reject) { _this._loadMTL(fileToLoad, rootUrl, function (dataLoaded) { try { //Create materials thanks MTLLoader function materialsFromMTLFile.parseMTL(scene, dataLoaded, rootUrl, _this._assetContainer); //Look at each material loaded in the mtl file for (var n = 0; n < materialsFromMTLFile.materials.length; n++) { //Three variables to get all meshes with the same material var startIndex = 0; var _indices = []; var _index = void 0; //The material from MTL file is used in the meshes loaded //Push the indice in an array //Check if the material is not used for another mesh while ((_index = materialToUse.indexOf(materialsFromMTLFile.materials[n].name, startIndex)) > -1) { _indices.push(_index); startIndex = _index + 1; } //If the material is not used dispose it if (_index === -1 && _indices.length === 0) { //If the material is not needed, remove it materialsFromMTLFile.materials[n].dispose(); } else { for (var o = 0; o < _indices.length; o++) { //Apply the material to the Mesh for each mesh with the material var mesh = babylonMeshesArray[_indices[o]]; var material = materialsFromMTLFile.materials[n]; mesh.material = material; if (!mesh.getTotalIndices()) { // No indices, we need to turn on point cloud material.pointsCloud = true; } } } } resolve(); } catch (e) { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Tools.Warn("Error processing MTL file: '".concat(fileToLoad, "'")); if (_this._loadingOptions.materialLoadingFailsSilently) { resolve(); } else { reject(e); } } }, function (pathOfFile, exception) { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Tools.Warn("Error downloading MTL file: '".concat(fileToLoad, "'")); if (_this._loadingOptions.materialLoadingFailsSilently) { resolve(); } else { reject(exception); } }); })); } //Return an array with all Mesh return Promise.all(mtlPromises).then(function () { return babylonMeshesArray; }); }; /** * Defines if UVs are optimized by default during load. */ OBJFileLoader.OPTIMIZE_WITH_UV = true; /** * Invert model on y-axis (does a model scaling inversion) */ OBJFileLoader.INVERT_Y = false; /** * Include in meshes the vertex colors available in some OBJ files. This is not part of OBJ standard. */ OBJFileLoader.IMPORT_VERTEX_COLORS = false; /** * Compute the normals for the model, even if normals are present in the file. */ OBJFileLoader.COMPUTE_NORMALS = false; /** * Optimize the normals for the model. Lighting can be uneven if you use OptimizeWithUV = true because new vertices can be created for the same location if they pertain to different faces. * Using OptimizehNormals = true will help smoothing the lighting by averaging the normals of those vertices. */ OBJFileLoader.OPTIMIZE_NORMALS = false; /** * Defines custom scaling of UV coordinates of loaded meshes. */ OBJFileLoader.UV_SCALING = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Vector2(1, 1); /** * Skip loading the materials even if defined in the OBJ file (materials are ignored). */ OBJFileLoader.SKIP_MATERIALS = false; /** * When a material fails to load OBJ loader will silently fail and onSuccess() callback will be triggered. * * Defaults to true for backwards compatibility. */ OBJFileLoader.MATERIAL_LOADING_FAILS_SILENTLY = true; return OBJFileLoader; }()); if (babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.SceneLoader) { //Add this loader into the register plugin babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.SceneLoader.RegisterPlugin(new OBJFileLoader()); } /***/ }), /***/ "../../../dev/loaders/src/OBJ/objLoadingOptions.ts": /*!*********************************************************!*\ !*** ../../../dev/loaders/src/OBJ/objLoadingOptions.ts ***! \*********************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /***/ }), /***/ "../../../dev/loaders/src/OBJ/solidParser.ts": /*!***************************************************!*\ !*** ../../../dev/loaders/src/OBJ/solidParser.ts ***! \***************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ SolidParser: () => (/* binding */ SolidParser) /* harmony export */ }); /* harmony import */ var babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Meshes/mesh.vertexData */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__); /** * Class used to load mesh data from OBJ content */ var SolidParser = /** @class */ (function () { /** * Creates a new SolidParser * @param materialToUse defines the array to fill with the list of materials to use (it will be filled by the parse function) * @param babylonMeshesArray defines the array to fill with the list of loaded meshes (it will be filled by the parse function) * @param loadingOptions defines the loading options to use */ function SolidParser(materialToUse, babylonMeshesArray, loadingOptions) { this._positions = []; //values for the positions of vertices this._normals = []; //Values for the normals this._uvs = []; //Values for the textures this._colors = []; this._meshesFromObj = []; //[mesh] Contains all the obj meshes this._indicesForBabylon = []; //The list of indices for VertexData this._wrappedPositionForBabylon = []; //The list of position in vectors this._wrappedUvsForBabylon = []; //Array with all value of uvs to match with the indices this._wrappedColorsForBabylon = []; // Array with all color values to match with the indices this._wrappedNormalsForBabylon = []; //Array with all value of normals to match with the indices this._tuplePosNorm = []; //Create a tuple with indice of Position, Normal, UV [pos, norm, uvs] this._curPositionInIndices = 0; this._hasMeshes = false; //Meshes are defined in the file this._unwrappedPositionsForBabylon = []; //Value of positionForBabylon w/o Vector3() [x,y,z] this._unwrappedColorsForBabylon = []; // Value of colorForBabylon w/o Color4() [r,g,b,a] this._unwrappedNormalsForBabylon = []; //Value of normalsForBabylon w/o Vector3() [x,y,z] this._unwrappedUVForBabylon = []; //Value of uvsForBabylon w/o Vector3() [x,y,z] this._triangles = []; //Indices from new triangles coming from polygons this._materialNameFromObj = ""; //The name of the current material this._objMeshName = ""; //The name of the current obj mesh this._increment = 1; //Id for meshes created by the multimaterial this._isFirstMaterial = true; this._grayColor = new babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Color4(0.5, 0.5, 0.5, 1); this._materialToUse = materialToUse; this._babylonMeshesArray = babylonMeshesArray; this._loadingOptions = loadingOptions; } /** * Search for obj in the given array. * This function is called to check if a couple of data already exists in an array. * * If found, returns the index of the founded tuple index. Returns -1 if not found * @param arr Array<{ normals: Array, idx: Array }> * @param obj Array * @returns {boolean} */ SolidParser.prototype._isInArray = function (arr, obj) { if (!arr[obj[0]]) { arr[obj[0]] = { normals: [], idx: [] }; } var idx = arr[obj[0]].normals.indexOf(obj[1]); return idx === -1 ? -1 : arr[obj[0]].idx[idx]; }; SolidParser.prototype._isInArrayUV = function (arr, obj) { if (!arr[obj[0]]) { arr[obj[0]] = { normals: [], idx: [], uv: [] }; } var idx = arr[obj[0]].normals.indexOf(obj[1]); if (idx != 1 && obj[2] === arr[obj[0]].uv[idx]) { return arr[obj[0]].idx[idx]; } return -1; }; /** * This function set the data for each triangle. * Data are position, normals and uvs * If a tuple of (position, normal) is not set, add the data into the corresponding array * If the tuple already exist, add only their indice * * @param indicePositionFromObj Integer The index in positions array * @param indiceUvsFromObj Integer The index in uvs array * @param indiceNormalFromObj Integer The index in normals array * @param positionVectorFromOBJ Vector3 The value of position at index objIndice * @param textureVectorFromOBJ Vector3 The value of uvs * @param normalsVectorFromOBJ Vector3 The value of normals at index objNormale * @param positionColorsFromOBJ */ SolidParser.prototype._setData = function (indicePositionFromObj, indiceUvsFromObj, indiceNormalFromObj, positionVectorFromOBJ, textureVectorFromOBJ, normalsVectorFromOBJ, positionColorsFromOBJ) { //Check if this tuple already exists in the list of tuples var _index; if (this._loadingOptions.optimizeWithUV) { _index = this._isInArrayUV(this._tuplePosNorm, [indicePositionFromObj, indiceNormalFromObj, indiceUvsFromObj]); } else { _index = this._isInArray(this._tuplePosNorm, [indicePositionFromObj, indiceNormalFromObj]); } //If it not exists if (_index === -1) { //Add an new indice. //The array of indices is only an array with his length equal to the number of triangles - 1. //We add vertices data in this order this._indicesForBabylon.push(this._wrappedPositionForBabylon.length); //Push the position of vertice for Babylon //Each element is a Vector3(x,y,z) this._wrappedPositionForBabylon.push(positionVectorFromOBJ); //Push the uvs for Babylon //Each element is a Vector3(u,v) this._wrappedUvsForBabylon.push(textureVectorFromOBJ); //Push the normals for Babylon //Each element is a Vector3(x,y,z) this._wrappedNormalsForBabylon.push(normalsVectorFromOBJ); if (positionColorsFromOBJ !== undefined) { //Push the colors for Babylon //Each element is a BABYLON.Color4(r,g,b,a) this._wrappedColorsForBabylon.push(positionColorsFromOBJ); } //Add the tuple in the comparison list this._tuplePosNorm[indicePositionFromObj].normals.push(indiceNormalFromObj); this._tuplePosNorm[indicePositionFromObj].idx.push(this._curPositionInIndices++); if (this._loadingOptions.optimizeWithUV) { this._tuplePosNorm[indicePositionFromObj].uv.push(indiceUvsFromObj); } } else { //The tuple already exists //Add the index of the already existing tuple //At this index we can get the value of position, normal, color and uvs of vertex this._indicesForBabylon.push(_index); } }; /** * Transform Vector() and BABYLON.Color() objects into numbers in an array */ SolidParser.prototype._unwrapData = function () { //Every array has the same length for (var l = 0; l < this._wrappedPositionForBabylon.length; l++) { //Push the x, y, z values of each element in the unwrapped array this._unwrappedPositionsForBabylon.push(this._wrappedPositionForBabylon[l].x, this._wrappedPositionForBabylon[l].y, this._wrappedPositionForBabylon[l].z); this._unwrappedNormalsForBabylon.push(this._wrappedNormalsForBabylon[l].x, this._wrappedNormalsForBabylon[l].y, this._wrappedNormalsForBabylon[l].z); this._unwrappedUVForBabylon.push(this._wrappedUvsForBabylon[l].x, this._wrappedUvsForBabylon[l].y); //z is an optional value not supported by BABYLON if (this._loadingOptions.importVertexColors) { //Push the r, g, b, a values of each element in the unwrapped array this._unwrappedColorsForBabylon.push(this._wrappedColorsForBabylon[l].r, this._wrappedColorsForBabylon[l].g, this._wrappedColorsForBabylon[l].b, this._wrappedColorsForBabylon[l].a); } } // Reset arrays for the next new meshes this._wrappedPositionForBabylon.length = 0; this._wrappedNormalsForBabylon.length = 0; this._wrappedUvsForBabylon.length = 0; this._wrappedColorsForBabylon.length = 0; this._tuplePosNorm.length = 0; this._curPositionInIndices = 0; }; /** * Create triangles from polygons * It is important to notice that a triangle is a polygon * We get 5 patterns of face defined in OBJ File : * facePattern1 = ["1","2","3","4","5","6"] * facePattern2 = ["1/1","2/2","3/3","4/4","5/5","6/6"] * facePattern3 = ["1/1/1","2/2/2","3/3/3","4/4/4","5/5/5","6/6/6"] * facePattern4 = ["1//1","2//2","3//3","4//4","5//5","6//6"] * facePattern5 = ["-1/-1/-1","-2/-2/-2","-3/-3/-3","-4/-4/-4","-5/-5/-5","-6/-6/-6"] * Each pattern is divided by the same method * @param faces Array[String] The indices of elements * @param v Integer The variable to increment */ SolidParser.prototype._getTriangles = function (faces, v) { //Work for each element of the array for (var faceIndex = v; faceIndex < faces.length - 1; faceIndex++) { //Add on the triangle variable the indexes to obtain triangles this._triangles.push(faces[0], faces[faceIndex], faces[faceIndex + 1]); } //Result obtained after 2 iterations: //Pattern1 => triangle = ["1","2","3","1","3","4"]; //Pattern2 => triangle = ["1/1","2/2","3/3","1/1","3/3","4/4"]; //Pattern3 => triangle = ["1/1/1","2/2/2","3/3/3","1/1/1","3/3/3","4/4/4"]; //Pattern4 => triangle = ["1//1","2//2","3//3","1//1","3//3","4//4"]; //Pattern5 => triangle = ["-1/-1/-1","-2/-2/-2","-3/-3/-3","-1/-1/-1","-3/-3/-3","-4/-4/-4"]; }; /** * Create triangles and push the data for each polygon for the pattern 1 * In this pattern we get vertice positions * @param face * @param v */ SolidParser.prototype._setDataForCurrentFaceWithPattern1 = function (face, v) { //Get the indices of triangles for each polygon this._getTriangles(face, v); //For each element in the triangles array. //This var could contains 1 to an infinity of triangles for (var k = 0; k < this._triangles.length; k++) { // Set position indice var indicePositionFromObj = parseInt(this._triangles[k]) - 1; this._setData(indicePositionFromObj, 0, 0, // In the pattern 1, normals and uvs are not defined this._positions[indicePositionFromObj], // Get the vectors data babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector2.Zero(), babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector3.Up(), // Create default vectors this._loadingOptions.importVertexColors ? this._colors[indicePositionFromObj] : undefined); } //Reset variable for the next line this._triangles.length = 0; }; /** * Create triangles and push the data for each polygon for the pattern 2 * In this pattern we get vertice positions and uvs * @param face * @param v */ SolidParser.prototype._setDataForCurrentFaceWithPattern2 = function (face, v) { //Get the indices of triangles for each polygon this._getTriangles(face, v); for (var k = 0; k < this._triangles.length; k++) { //triangle[k] = "1/1" //Split the data for getting position and uv var point = this._triangles[k].split("/"); // ["1", "1"] //Set position indice var indicePositionFromObj = parseInt(point[0]) - 1; //Set uv indice var indiceUvsFromObj = parseInt(point[1]) - 1; this._setData(indicePositionFromObj, indiceUvsFromObj, 0, //Default value for normals this._positions[indicePositionFromObj], //Get the values for each element this._uvs[indiceUvsFromObj], babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector3.Up(), //Default value for normals this._loadingOptions.importVertexColors ? this._colors[indicePositionFromObj] : undefined); } //Reset variable for the next line this._triangles.length = 0; }; /** * Create triangles and push the data for each polygon for the pattern 3 * In this pattern we get vertice positions, uvs and normals * @param face * @param v */ SolidParser.prototype._setDataForCurrentFaceWithPattern3 = function (face, v) { //Get the indices of triangles for each polygon this._getTriangles(face, v); for (var k = 0; k < this._triangles.length; k++) { //triangle[k] = "1/1/1" //Split the data for getting position, uv, and normals var point = this._triangles[k].split("/"); // ["1", "1", "1"] // Set position indice var indicePositionFromObj = parseInt(point[0]) - 1; // Set uv indice var indiceUvsFromObj = parseInt(point[1]) - 1; // Set normal indice var indiceNormalFromObj = parseInt(point[2]) - 1; this._setData(indicePositionFromObj, indiceUvsFromObj, indiceNormalFromObj, this._positions[indicePositionFromObj], this._uvs[indiceUvsFromObj], this._normals[indiceNormalFromObj] //Set the vector for each component ); } //Reset variable for the next line this._triangles.length = 0; }; /** * Create triangles and push the data for each polygon for the pattern 4 * In this pattern we get vertice positions and normals * @param face * @param v */ SolidParser.prototype._setDataForCurrentFaceWithPattern4 = function (face, v) { this._getTriangles(face, v); for (var k = 0; k < this._triangles.length; k++) { //triangle[k] = "1//1" //Split the data for getting position and normals var point = this._triangles[k].split("//"); // ["1", "1"] // We check indices, and normals var indicePositionFromObj = parseInt(point[0]) - 1; var indiceNormalFromObj = parseInt(point[1]) - 1; this._setData(indicePositionFromObj, 1, //Default value for uv indiceNormalFromObj, this._positions[indicePositionFromObj], //Get each vector of data babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector2.Zero(), this._normals[indiceNormalFromObj], this._loadingOptions.importVertexColors ? this._colors[indicePositionFromObj] : undefined); } //Reset variable for the next line this._triangles.length = 0; }; /* * Create triangles and push the data for each polygon for the pattern 3 * In this pattern we get vertice positions, uvs and normals * @param face * @param v */ SolidParser.prototype._setDataForCurrentFaceWithPattern5 = function (face, v) { //Get the indices of triangles for each polygon this._getTriangles(face, v); for (var k = 0; k < this._triangles.length; k++) { //triangle[k] = "-1/-1/-1" //Split the data for getting position, uv, and normals var point = this._triangles[k].split("/"); // ["-1", "-1", "-1"] // Set position indice var indicePositionFromObj = this._positions.length + parseInt(point[0]); // Set uv indice var indiceUvsFromObj = this._uvs.length + parseInt(point[1]); // Set normal indice var indiceNormalFromObj = this._normals.length + parseInt(point[2]); this._setData(indicePositionFromObj, indiceUvsFromObj, indiceNormalFromObj, this._positions[indicePositionFromObj], this._uvs[indiceUvsFromObj], this._normals[indiceNormalFromObj], //Set the vector for each component this._loadingOptions.importVertexColors ? this._colors[indicePositionFromObj] : undefined); } //Reset variable for the next line this._triangles.length = 0; }; SolidParser.prototype._addPreviousObjMesh = function () { //Check if it is not the first mesh. Otherwise we don't have data. if (this._meshesFromObj.length > 0) { //Get the previous mesh for applying the data about the faces //=> in obj file, faces definition append after the name of the mesh this._handledMesh = this._meshesFromObj[this._meshesFromObj.length - 1]; //Set the data into Array for the mesh this._unwrapData(); // Reverse tab. Otherwise face are displayed in the wrong sens this._indicesForBabylon.reverse(); //Set the information for the mesh //Slice the array to avoid rewriting because of the fact this is the same var which be rewrited this._handledMesh.indices = this._indicesForBabylon.slice(); this._handledMesh.positions = this._unwrappedPositionsForBabylon.slice(); this._handledMesh.normals = this._unwrappedNormalsForBabylon.slice(); this._handledMesh.uvs = this._unwrappedUVForBabylon.slice(); if (this._loadingOptions.importVertexColors) { this._handledMesh.colors = this._unwrappedColorsForBabylon.slice(); } //Reset the array for the next mesh this._indicesForBabylon.length = 0; this._unwrappedPositionsForBabylon.length = 0; this._unwrappedColorsForBabylon.length = 0; this._unwrappedNormalsForBabylon.length = 0; this._unwrappedUVForBabylon.length = 0; } }; SolidParser.prototype._optimizeNormals = function (mesh) { var positions = mesh.getVerticesData(babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.PositionKind); var normals = mesh.getVerticesData(babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.NormalKind); var mapVertices = {}; if (!positions || !normals) { return; } for (var i = 0; i < positions.length / 3; i++) { var x = positions[i * 3 + 0]; var y = positions[i * 3 + 1]; var z = positions[i * 3 + 2]; var key = x + "_" + y + "_" + z; var lst = mapVertices[key]; if (!lst) { lst = []; mapVertices[key] = lst; } lst.push(i); } var normal = new babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector3(); for (var key in mapVertices) { var lst = mapVertices[key]; if (lst.length < 2) { continue; } var v0Idx = lst[0]; for (var i = 1; i < lst.length; ++i) { var vIdx = lst[i]; normals[v0Idx * 3 + 0] += normals[vIdx * 3 + 0]; normals[v0Idx * 3 + 1] += normals[vIdx * 3 + 1]; normals[v0Idx * 3 + 2] += normals[vIdx * 3 + 2]; } normal.copyFromFloats(normals[v0Idx * 3 + 0], normals[v0Idx * 3 + 1], normals[v0Idx * 3 + 2]); normal.normalize(); for (var i = 0; i < lst.length; ++i) { var vIdx = lst[i]; normals[vIdx * 3 + 0] = normal.x; normals[vIdx * 3 + 1] = normal.y; normals[vIdx * 3 + 2] = normal.z; } } mesh.setVerticesData(babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.NormalKind, normals); }; /** * Function used to parse an OBJ string * @param meshesNames defines the list of meshes to load (all if not defined) * @param data defines the OBJ string * @param scene defines the hosting scene * @param assetContainer defines the asset container to load data in * @param onFileToLoadFound defines a callback that will be called if a MTL file is found */ SolidParser.prototype.parse = function (meshesNames, data, scene, assetContainer, onFileToLoadFound) { var _a; // Split the file into lines var lines = data.split("\n"); // Look at each line for (var i = 0; i < lines.length; i++) { var line = lines[i].trim().replace(/\s\s/g, " "); var result = void 0; // Comment or newLine if (line.length === 0 || line.charAt(0) === "#") { continue; //Get information about one position possible for the vertices } else if (SolidParser.VertexPattern.test(line)) { result = line.match(/[^ ]+/g); // match will return non-null due to passing regex pattern // Value of result with line: "v 1.0 2.0 3.0" // ["v", "1.0", "2.0", "3.0"] // Create a Vector3 with the position x, y, z this._positions.push(new babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector3(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]))); if (this._loadingOptions.importVertexColors) { if (result.length >= 7) { var r = parseFloat(result[4]); var g = parseFloat(result[5]); var b = parseFloat(result[6]); this._colors.push(new babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Color4(r > 1 ? r / 255 : r, g > 1 ? g / 255 : g, b > 1 ? b / 255 : b, result.length === 7 || result[7] === undefined ? 1 : parseFloat(result[7]))); } else { // TODO: maybe push NULL and if all are NULL to skip (and remove grayColor var). this._colors.push(this._grayColor); } } } else if ((result = SolidParser.NormalPattern.exec(line)) !== null) { //Create a Vector3 with the normals x, y, z //Value of result // ["vn 1.0 2.0 3.0", "1.0", "2.0", "3.0"] //Add the Vector in the list of normals this._normals.push(new babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector3(parseFloat(result[1]), parseFloat(result[2]), parseFloat(result[3]))); } else if ((result = SolidParser.UVPattern.exec(line)) !== null) { //Create a Vector2 with the normals u, v //Value of result // ["vt 0.1 0.2 0.3", "0.1", "0.2"] //Add the Vector in the list of uvs this._uvs.push(new babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Vector2(parseFloat(result[1]) * this._loadingOptions.UVScaling.x, parseFloat(result[2]) * this._loadingOptions.UVScaling.y)); //Identify patterns of faces //Face could be defined in different type of pattern } else if ((result = SolidParser.FacePattern3.exec(line)) !== null) { //Value of result: //["f 1/1/1 2/2/2 3/3/3", "1/1/1 2/2/2 3/3/3"...] //Set the data for this face this._setDataForCurrentFaceWithPattern3(result[1].trim().split(" "), // ["1/1/1", "2/2/2", "3/3/3"] 1); } else if ((result = SolidParser.FacePattern4.exec(line)) !== null) { //Value of result: //["f 1//1 2//2 3//3", "1//1 2//2 3//3"...] //Set the data for this face this._setDataForCurrentFaceWithPattern4(result[1].trim().split(" "), // ["1//1", "2//2", "3//3"] 1); } else if ((result = SolidParser.FacePattern5.exec(line)) !== null) { //Value of result: //["f -1/-1/-1 -2/-2/-2 -3/-3/-3", "-1/-1/-1 -2/-2/-2 -3/-3/-3"...] //Set the data for this face this._setDataForCurrentFaceWithPattern5(result[1].trim().split(" "), // ["-1/-1/-1", "-2/-2/-2", "-3/-3/-3"] 1); } else if ((result = SolidParser.FacePattern2.exec(line)) !== null) { //Value of result: //["f 1/1 2/2 3/3", "1/1 2/2 3/3"...] //Set the data for this face this._setDataForCurrentFaceWithPattern2(result[1].trim().split(" "), // ["1/1", "2/2", "3/3"] 1); } else if ((result = SolidParser.FacePattern1.exec(line)) !== null) { //Value of result //["f 1 2 3", "1 2 3"...] //Set the data for this face this._setDataForCurrentFaceWithPattern1(result[1].trim().split(" "), // ["1", "2", "3"] 1); // Define a mesh or an object // Each time this keyword is analyzed, create a new Object with all data for creating a babylonMesh } else if ((result = SolidParser.LinePattern1.exec(line)) !== null) { //Value of result //["l 1 2"] //Set the data for this face this._setDataForCurrentFaceWithPattern1(result[1].trim().split(" "), // ["1", "2"] 0); // Define a mesh or an object // Each time this keyword is analyzed, create a new Object with all data for creating a babylonMesh } else if ((result = SolidParser.LinePattern2.exec(line)) !== null) { //Value of result //["l 1/1 2/2"] //Set the data for this face this._setDataForCurrentFaceWithPattern2(result[1].trim().split(" "), // ["1/1", "2/2"] 0); // Define a mesh or an object // Each time this keyword is analyzed, create a new Object with all data for creating a babylonMesh } else if ((result = SolidParser.LinePattern3.exec(line)) !== null) { //Value of result //["l 1/1/1 2/2/2"] //Set the data for this face this._setDataForCurrentFaceWithPattern3(result[1].trim().split(" "), // ["1/1/1", "2/2/2"] 0); // Define a mesh or an object // Each time this keyword is analyzed, create a new Object with all data for creating a babylonMesh } else if (SolidParser.GroupDescriptor.test(line) || SolidParser.ObjectDescriptor.test(line)) { // Create a new mesh corresponding to the name of the group. // Definition of the mesh var objMesh = { name: line.substring(2).trim(), indices: undefined, positions: undefined, normals: undefined, uvs: undefined, colors: undefined, materialName: this._materialNameFromObj, }; this._addPreviousObjMesh(); //Push the last mesh created with only the name this._meshesFromObj.push(objMesh); //Set this variable to indicate that now meshesFromObj has objects defined inside this._hasMeshes = true; this._isFirstMaterial = true; this._increment = 1; //Keyword for applying a material } else if (SolidParser.UseMtlDescriptor.test(line)) { //Get the name of the material this._materialNameFromObj = line.substring(7).trim(); //If this new material is in the same mesh if (!this._isFirstMaterial || !this._hasMeshes) { //Set the data for the previous mesh this._addPreviousObjMesh(); //Create a new mesh var objMesh = //Set the name of the current obj mesh { name: (this._objMeshName || "mesh") + "_mm" + this._increment.toString(), indices: undefined, positions: undefined, normals: undefined, uvs: undefined, colors: undefined, materialName: this._materialNameFromObj, }; this._increment++; //If meshes are already defined this._meshesFromObj.push(objMesh); this._hasMeshes = true; } //Set the material name if the previous line define a mesh if (this._hasMeshes && this._isFirstMaterial) { //Set the material name to the previous mesh (1 material per mesh) this._meshesFromObj[this._meshesFromObj.length - 1].materialName = this._materialNameFromObj; this._isFirstMaterial = false; } // Keyword for loading the mtl file } else if (SolidParser.MtlLibGroupDescriptor.test(line)) { // Get the name of mtl file onFileToLoadFound(line.substring(7).trim()); // Apply smoothing } else if (SolidParser.SmoothDescriptor.test(line)) { // smooth shading => apply smoothing // Today I don't know it work with babylon and with obj. // With the obj file an integer is set } else { //If there is another possibility console.log("Unhandled expression at line : " + line); } } // At the end of the file, add the last mesh into the meshesFromObj array if (this._hasMeshes) { // Set the data for the last mesh this._handledMesh = this._meshesFromObj[this._meshesFromObj.length - 1]; //Reverse indices for displaying faces in the good sense this._indicesForBabylon.reverse(); //Get the good array this._unwrapData(); //Set array this._handledMesh.indices = this._indicesForBabylon; this._handledMesh.positions = this._unwrappedPositionsForBabylon; this._handledMesh.normals = this._unwrappedNormalsForBabylon; this._handledMesh.uvs = this._unwrappedUVForBabylon; if (this._loadingOptions.importVertexColors) { this._handledMesh.colors = this._unwrappedColorsForBabylon; } } // If any o or g keyword not found, create a mesh with a random id if (!this._hasMeshes) { var newMaterial = null; if (this._indicesForBabylon.length) { // reverse tab of indices this._indicesForBabylon.reverse(); //Get positions normals uvs this._unwrapData(); } else { // There is no indices in the file. We will have to switch to point cloud rendering for (var _i = 0, _b = this._positions; _i < _b.length; _i++) { var pos = _b[_i]; this._unwrappedPositionsForBabylon.push(pos.x, pos.y, pos.z); } if (this._normals.length) { for (var _c = 0, _d = this._normals; _c < _d.length; _c++) { var normal = _d[_c]; this._unwrappedNormalsForBabylon.push(normal.x, normal.y, normal.z); } } if (this._uvs.length) { for (var _e = 0, _f = this._uvs; _e < _f.length; _e++) { var uv = _f[_e]; this._unwrappedUVForBabylon.push(uv.x, uv.y); } } if (this._colors.length) { for (var _g = 0, _h = this._colors; _g < _h.length; _g++) { var color = _h[_g]; this._unwrappedColorsForBabylon.push(color.r, color.g, color.b, color.a); } } if (!this._materialNameFromObj) { // Create a material with point cloud on newMaterial = new babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.StandardMaterial(babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Geometry.RandomId(), scene); newMaterial.pointsCloud = true; this._materialNameFromObj = newMaterial.name; if (!this._normals.length) { newMaterial.disableLighting = true; newMaterial.emissiveColor = babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Color3.White(); } } } //Set data for one mesh this._meshesFromObj.push({ name: babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Geometry.RandomId(), indices: this._indicesForBabylon, positions: this._unwrappedPositionsForBabylon, colors: this._unwrappedColorsForBabylon, normals: this._unwrappedNormalsForBabylon, uvs: this._unwrappedUVForBabylon, materialName: this._materialNameFromObj, directMaterial: newMaterial, }); } //Set data for each mesh for (var j = 0; j < this._meshesFromObj.length; j++) { //check meshesNames (stlFileLoader) if (meshesNames && this._meshesFromObj[j].name) { if (meshesNames instanceof Array) { if (meshesNames.indexOf(this._meshesFromObj[j].name) === -1) { continue; } } else { if (this._meshesFromObj[j].name !== meshesNames) { continue; } } } //Get the current mesh //Set the data with VertexBuffer for each mesh this._handledMesh = this._meshesFromObj[j]; //Create a Mesh with the name of the obj mesh scene._blockEntityCollection = !!assetContainer; var babylonMesh = new babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.Mesh(this._meshesFromObj[j].name, scene); babylonMesh._parentContainer = assetContainer; scene._blockEntityCollection = false; //Push the name of the material to an array //This is indispensable for the importMesh function this._materialToUse.push(this._meshesFromObj[j].materialName); if (((_a = this._handledMesh.positions) === null || _a === void 0 ? void 0 : _a.length) === 0) { //Push the mesh into an array this._babylonMeshesArray.push(babylonMesh); continue; } var vertexData = new babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.VertexData(); //The container for the values //Set the data for the babylonMesh vertexData.uvs = this._handledMesh.uvs; vertexData.indices = this._handledMesh.indices; vertexData.positions = this._handledMesh.positions; if (this._loadingOptions.computeNormals) { var normals = new Array(); babylonjs_Buffers_buffer__WEBPACK_IMPORTED_MODULE_0__.VertexData.ComputeNormals(this._handledMesh.positions, this._handledMesh.indices, normals); vertexData.normals = normals; } else { vertexData.normals = this._handledMesh.normals; } if (this._loadingOptions.importVertexColors) { vertexData.colors = this._handledMesh.colors; } //Set the data from the VertexBuffer to the current Mesh vertexData.applyToMesh(babylonMesh); if (this._loadingOptions.invertY) { babylonMesh.scaling.y *= -1; } if (this._loadingOptions.optimizeNormals) { this._optimizeNormals(babylonMesh); } //Push the mesh into an array this._babylonMeshesArray.push(babylonMesh); if (this._handledMesh.directMaterial) { babylonMesh.material = this._handledMesh.directMaterial; } } }; // Descriptor /** Object descriptor */ SolidParser.ObjectDescriptor = /^o/; /** Group descriptor */ SolidParser.GroupDescriptor = /^g/; /** Material lib descriptor */ SolidParser.MtlLibGroupDescriptor = /^mtllib /; /** Use a material descriptor */ SolidParser.UseMtlDescriptor = /^usemtl /; /** Smooth descriptor */ SolidParser.SmoothDescriptor = /^s /; // Patterns /** Pattern used to detect a vertex */ SolidParser.VertexPattern = /^v(\s+[\d|.|+|\-|e|E]+){3,7}/; /** Pattern used to detect a normal */ SolidParser.NormalPattern = /^vn(\s+[\d|.|+|\-|e|E]+)( +[\d|.|+|\-|e|E]+)( +[\d|.|+|\-|e|E]+)/; /** Pattern used to detect a UV set */ SolidParser.UVPattern = /^vt(\s+[\d|.|+|\-|e|E]+)( +[\d|.|+|\-|e|E]+)/; /** Pattern used to detect a first kind of face (f vertex vertex vertex) */ SolidParser.FacePattern1 = /^f\s+(([\d]{1,}[\s]?){3,})+/; /** Pattern used to detect a second kind of face (f vertex/uvs vertex/uvs vertex/uvs) */ SolidParser.FacePattern2 = /^f\s+((([\d]{1,}\/[\d]{1,}[\s]?){3,})+)/; /** Pattern used to detect a third kind of face (f vertex/uvs/normal vertex/uvs/normal vertex/uvs/normal) */ SolidParser.FacePattern3 = /^f\s+((([\d]{1,}\/[\d]{1,}\/[\d]{1,}[\s]?){3,})+)/; /** Pattern used to detect a fourth kind of face (f vertex//normal vertex//normal vertex//normal)*/ SolidParser.FacePattern4 = /^f\s+((([\d]{1,}\/\/[\d]{1,}[\s]?){3,})+)/; /** Pattern used to detect a fifth kind of face (f -vertex/-uvs/-normal -vertex/-uvs/-normal -vertex/-uvs/-normal) */ SolidParser.FacePattern5 = /^f\s+(((-[\d]{1,}\/-[\d]{1,}\/-[\d]{1,}[\s]?){3,})+)/; /** Pattern used to detect a line(l vertex vertex) */ SolidParser.LinePattern1 = /^l\s+(([\d]{1,}[\s]?){2,})+/; /** Pattern used to detect a second kind of line (l vertex/uvs vertex/uvs) */ SolidParser.LinePattern2 = /^l\s+((([\d]{1,}\/[\d]{1,}[\s]?){2,})+)/; /** Pattern used to detect a third kind of line (l vertex/uvs/normal vertex/uvs/normal) */ SolidParser.LinePattern3 = /^l\s+((([\d]{1,}\/[\d]{1,}\/[\d]{1,}[\s]?){2,})+)/; return SolidParser; }()); /***/ }), /***/ "../../../dev/loaders/src/STL/index.ts": /*!*********************************************!*\ !*** ../../../dev/loaders/src/STL/index.ts ***! \*********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ STLFileLoader: () => (/* reexport safe */ _stlFileLoader__WEBPACK_IMPORTED_MODULE_0__.STLFileLoader) /* harmony export */ }); /* harmony import */ var _stlFileLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./stlFileLoader */ "../../../dev/loaders/src/STL/stlFileLoader.ts"); /***/ }), /***/ "../../../dev/loaders/src/STL/stlFileLoader.ts": /*!*****************************************************!*\ !*** ../../../dev/loaders/src/STL/stlFileLoader.ts ***! \*****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ STLFileLoader: () => (/* binding */ STLFileLoader) /* harmony export */ }); /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/assetContainer */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__); /** * STL file type loader. * This is a babylon scene loader plugin. */ var STLFileLoader = /** @class */ (function () { function STLFileLoader() { /** @internal */ this.solidPattern = /solid (\S*)([\S\s]*?)endsolid[ ]*(\S*)/g; /** @internal */ this.facetsPattern = /facet([\s\S]*?)endfacet/g; /** @internal */ this.normalPattern = /normal[\s]+([-+]?[0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?)+[\s]+([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)+[\s]+([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)+/g; /** @internal */ this.vertexPattern = /vertex[\s]+([-+]?[0-9]+\.?[0-9]*([eE][-+]?[0-9]+)?)+[\s]+([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)+[\s]+([-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?)+/g; /** * Defines the name of the plugin. */ this.name = "stl"; /** * Defines the extensions the stl loader is able to load. * force data to come in as an ArrayBuffer * we'll convert to string if it looks like it's an ASCII .stl */ this.extensions = { ".stl": { isBinary: true }, }; } /** * Import meshes into a scene. * @param meshesNames An array of mesh names, a single mesh name, or empty string for all meshes that filter what meshes are imported * @param scene The scene to import into * @param data The data to import * @param rootUrl The root url for scene and resources * @param meshes The meshes array to import into * @returns True if successful or false otherwise */ STLFileLoader.prototype.importMesh = function (meshesNames, scene, data, rootUrl, meshes) { var matches; if (typeof data !== "string") { if (this._isBinary(data)) { // binary .stl var babylonMesh = new babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__.Mesh("stlmesh", scene); this._parseBinary(babylonMesh, data); if (meshes) { meshes.push(babylonMesh); } return true; } // ASCII .stl // convert to string data = new TextDecoder().decode(new Uint8Array(data)); } //if arrived here, data is a string, containing the STLA data. while ((matches = this.solidPattern.exec(data))) { var meshName = matches[1]; var meshNameFromEnd = matches[3]; if (meshNameFromEnd && meshName != meshNameFromEnd) { babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__.Tools.Error("Error in STL, solid name != endsolid name"); return false; } // check meshesNames if (meshesNames && meshName) { if (meshesNames instanceof Array) { if (!meshesNames.indexOf(meshName)) { continue; } } else { if (meshName !== meshesNames) { continue; } } } // stl mesh name can be empty as well meshName = meshName || "stlmesh"; var babylonMesh = new babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__.Mesh(meshName, scene); this._parseASCII(babylonMesh, matches[2]); if (meshes) { meshes.push(babylonMesh); } } return true; }; /** * Load into a scene. * @param scene The scene to load into * @param data The data to import * @param rootUrl The root url for scene and resources * @returns true if successful or false otherwise */ STLFileLoader.prototype.load = function (scene, data, rootUrl) { var result = this.importMesh(null, scene, data, rootUrl, null); return result; }; /** * Load into an asset container. * @param scene The scene to load into * @param data The data to import * @param rootUrl The root url for scene and resources * @returns The loaded asset container */ STLFileLoader.prototype.loadAssetContainer = function (scene, data, rootUrl) { var container = new babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__.AssetContainer(scene); scene._blockEntityCollection = true; this.importMesh(null, scene, data, rootUrl, container.meshes); scene._blockEntityCollection = false; return container; }; STLFileLoader.prototype._isBinary = function (data) { // check if file size is correct for binary stl var reader = new DataView(data); // A Binary STL header is 80 bytes, if the data size is not great than // that then it's not a binary STL. if (reader.byteLength <= 80) { return false; } var faceSize = (32 / 8) * 3 + (32 / 8) * 3 * 3 + 16 / 8; var nFaces = reader.getUint32(80, true); if (80 + 32 / 8 + nFaces * faceSize === reader.byteLength) { return true; } // US-ASCII begin with 's', 'o', 'l', 'i', 'd' var ascii = [115, 111, 108, 105, 100]; for (var off = 0; off < 5; off++) { if (reader.getUint8(off) !== ascii[off]) { return true; } } return false; }; STLFileLoader.prototype._parseBinary = function (mesh, data) { var reader = new DataView(data); var faces = reader.getUint32(80, true); var dataOffset = 84; var faceLength = 12 * 4 + 2; var offset = 0; var positions = new Float32Array(faces * 3 * 3); var normals = new Float32Array(faces * 3 * 3); var indices = new Uint32Array(faces * 3); var indicesCount = 0; for (var face = 0; face < faces; face++) { var start = dataOffset + face * faceLength; var normalX = reader.getFloat32(start, true); var normalY = reader.getFloat32(start + 4, true); var normalZ = reader.getFloat32(start + 8, true); for (var i = 1; i <= 3; i++) { var vertexstart = start + i * 12; // ordering is intentional to match ascii import positions[offset] = reader.getFloat32(vertexstart, true); normals[offset] = normalX; if (!STLFileLoader.DO_NOT_ALTER_FILE_COORDINATES) { positions[offset + 2] = reader.getFloat32(vertexstart + 4, true); positions[offset + 1] = reader.getFloat32(vertexstart + 8, true); normals[offset + 2] = normalY; normals[offset + 1] = normalZ; } else { positions[offset + 1] = reader.getFloat32(vertexstart + 4, true); positions[offset + 2] = reader.getFloat32(vertexstart + 8, true); normals[offset + 1] = normalY; normals[offset + 2] = normalZ; } offset += 3; } if (STLFileLoader.DO_NOT_ALTER_FILE_COORDINATES) { indices[indicesCount] = indicesCount; indices[indicesCount + 1] = indicesCount + 2; indices[indicesCount + 2] = indicesCount + 1; indicesCount += 3; } else { indices[indicesCount] = indicesCount++; indices[indicesCount] = indicesCount++; indices[indicesCount] = indicesCount++; } } mesh.setVerticesData(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.PositionKind, positions); mesh.setVerticesData(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.NormalKind, normals); mesh.setIndices(indices); mesh.computeWorldMatrix(true); }; STLFileLoader.prototype._parseASCII = function (mesh, solidData) { var positions = []; var normals = []; var indices = []; var indicesCount = 0; //load facets, ignoring loop as the standard doesn't define it can contain more than vertices var matches; while ((matches = this.facetsPattern.exec(solidData))) { var facet = matches[1]; //one normal per face var normalMatches = this.normalPattern.exec(facet); this.normalPattern.lastIndex = 0; if (!normalMatches) { continue; } var normal = [Number(normalMatches[1]), Number(normalMatches[5]), Number(normalMatches[3])]; var vertexMatch = void 0; while ((vertexMatch = this.vertexPattern.exec(facet))) { if (!STLFileLoader.DO_NOT_ALTER_FILE_COORDINATES) { positions.push(Number(vertexMatch[1]), Number(vertexMatch[5]), Number(vertexMatch[3])); normals.push(normal[0], normal[1], normal[2]); } else { positions.push(Number(vertexMatch[1]), Number(vertexMatch[3]), Number(vertexMatch[5])); // Flipping the second and third component because inverted // when normal was declared. normals.push(normal[0], normal[2], normal[1]); } } if (STLFileLoader.DO_NOT_ALTER_FILE_COORDINATES) { indices.push(indicesCount, indicesCount + 2, indicesCount + 1); indicesCount += 3; } else { indices.push(indicesCount++, indicesCount++, indicesCount++); } this.vertexPattern.lastIndex = 0; } this.facetsPattern.lastIndex = 0; mesh.setVerticesData(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.PositionKind, positions); mesh.setVerticesData(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.NormalKind, normals); mesh.setIndices(indices); mesh.computeWorldMatrix(true); }; /** * Defines if Y and Z axes are swapped or not when loading an STL file. * The default is false to maintain backward compatibility. When set to * true, coordinates from the STL file are used without change. */ STLFileLoader.DO_NOT_ALTER_FILE_COORDINATES = false; return STLFileLoader; }()); if (babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__.SceneLoader) { babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__.SceneLoader.RegisterPlugin(new STLFileLoader()); } /***/ }), /***/ "../../../dev/loaders/src/glTF/1.0/glTFBinaryExtension.ts": /*!****************************************************************!*\ !*** ../../../dev/loaders/src/glTF/1.0/glTFBinaryExtension.ts ***! \****************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GLTFBinaryExtension: () => (/* binding */ GLTFBinaryExtension) /* harmony export */ }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! tslib */ "../../../../node_modules/tslib/tslib.es6.mjs"); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./glTFLoader */ "../../../dev/loaders/src/glTF/1.0/glTFLoader.ts"); /* harmony import */ var _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./glTFLoaderUtils */ "../../../dev/loaders/src/glTF/1.0/glTFLoaderUtils.ts"); /* harmony import */ var _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./glTFLoaderInterfaces */ "../../../dev/loaders/src/glTF/1.0/glTFLoaderInterfaces.ts"); var BinaryExtensionBufferName = "binary_glTF"; /** * @internal * @deprecated */ var GLTFBinaryExtension = /** @class */ (function (_super) { (0,tslib__WEBPACK_IMPORTED_MODULE_3__.__extends)(GLTFBinaryExtension, _super); function GLTFBinaryExtension() { return _super.call(this, "KHR_binary_glTF") || this; } GLTFBinaryExtension.prototype.loadRuntimeAsync = function (scene, data, rootUrl, onSuccess) { var extensionsUsed = data.json.extensionsUsed; if (!extensionsUsed || extensionsUsed.indexOf(this.name) === -1 || !data.bin) { return false; } this._bin = data.bin; onSuccess(_glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderBase.CreateRuntime(data.json, scene, rootUrl)); return true; }; GLTFBinaryExtension.prototype.loadBufferAsync = function (gltfRuntime, id, onSuccess, onError) { if (gltfRuntime.extensionsUsed.indexOf(this.name) === -1) { return false; } if (id !== BinaryExtensionBufferName) { return false; } this._bin.readAsync(0, this._bin.byteLength).then(onSuccess, function (error) { return onError(error.message); }); return true; }; GLTFBinaryExtension.prototype.loadTextureBufferAsync = function (gltfRuntime, id, onSuccess) { var texture = gltfRuntime.textures[id]; var source = gltfRuntime.images[texture.source]; if (!source.extensions || !(this.name in source.extensions)) { return false; } var sourceExt = source.extensions[this.name]; var bufferView = gltfRuntime.bufferViews[sourceExt.bufferView]; var buffer = _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_1__.GLTFUtils.GetBufferFromBufferView(gltfRuntime, bufferView, 0, bufferView.byteLength, _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_2__.EComponentType.UNSIGNED_BYTE); onSuccess(buffer); return true; }; GLTFBinaryExtension.prototype.loadShaderStringAsync = function (gltfRuntime, id, onSuccess) { var shader = gltfRuntime.shaders[id]; if (!shader.extensions || !(this.name in shader.extensions)) { return false; } var binaryExtensionShader = shader.extensions[this.name]; var bufferView = gltfRuntime.bufferViews[binaryExtensionShader.bufferView]; var shaderBytes = _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_1__.GLTFUtils.GetBufferFromBufferView(gltfRuntime, bufferView, 0, bufferView.byteLength, _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_2__.EComponentType.UNSIGNED_BYTE); setTimeout(function () { var shaderString = _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_1__.GLTFUtils.DecodeBufferToText(shaderBytes); onSuccess(shaderString); }); return true; }; return GLTFBinaryExtension; }(_glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderExtension)); _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.RegisterExtension(new GLTFBinaryExtension()); /***/ }), /***/ "../../../dev/loaders/src/glTF/1.0/glTFLoader.ts": /*!*******************************************************!*\ !*** ../../../dev/loaders/src/glTF/1.0/glTFLoader.ts ***! \*******************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GLTFLoader: () => (/* binding */ GLTFLoader), /* harmony export */ GLTFLoaderBase: () => (/* binding */ GLTFLoaderBase), /* harmony export */ GLTFLoaderExtension: () => (/* binding */ GLTFLoaderExtension) /* harmony export */ }); /* harmony import */ var _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./glTFLoaderInterfaces */ "../../../dev/loaders/src/glTF/1.0/glTFLoaderInterfaces.ts"); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Engines/constants */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./glTFLoaderUtils */ "../../../dev/loaders/src/glTF/1.0/glTFLoaderUtils.ts"); /* harmony import */ var _glTFFileLoader__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../glTFFileLoader */ "../../../dev/loaders/src/glTF/glTFFileLoader.ts"); /** * Tokenizer. Used for shaders compatibility * Automatically map world, view, projection, worldViewProjection, attributes and so on */ var ETokenType; (function (ETokenType) { ETokenType[ETokenType["IDENTIFIER"] = 1] = "IDENTIFIER"; ETokenType[ETokenType["UNKNOWN"] = 2] = "UNKNOWN"; ETokenType[ETokenType["END_OF_INPUT"] = 3] = "END_OF_INPUT"; })(ETokenType || (ETokenType = {})); var Tokenizer = /** @class */ (function () { function Tokenizer(toParse) { this._pos = 0; this.currentToken = ETokenType.UNKNOWN; this.currentIdentifier = ""; this.currentString = ""; this.isLetterOrDigitPattern = /^[a-zA-Z0-9]+$/; this._toParse = toParse; this._maxPos = toParse.length; } Tokenizer.prototype.getNextToken = function () { if (this.isEnd()) { return ETokenType.END_OF_INPUT; } this.currentString = this.read(); this.currentToken = ETokenType.UNKNOWN; if (this.currentString === "_" || this.isLetterOrDigitPattern.test(this.currentString)) { this.currentToken = ETokenType.IDENTIFIER; this.currentIdentifier = this.currentString; while (!this.isEnd() && (this.isLetterOrDigitPattern.test((this.currentString = this.peek())) || this.currentString === "_")) { this.currentIdentifier += this.currentString; this.forward(); } } return this.currentToken; }; Tokenizer.prototype.peek = function () { return this._toParse[this._pos]; }; Tokenizer.prototype.read = function () { return this._toParse[this._pos++]; }; Tokenizer.prototype.forward = function () { this._pos++; }; Tokenizer.prototype.isEnd = function () { return this._pos >= this._maxPos; }; return Tokenizer; }()); /** * Values */ var glTFTransforms = ["MODEL", "VIEW", "PROJECTION", "MODELVIEW", "MODELVIEWPROJECTION", "JOINTMATRIX"]; var babylonTransforms = ["world", "view", "projection", "worldView", "worldViewProjection", "mBones"]; var glTFAnimationPaths = ["translation", "rotation", "scale"]; var babylonAnimationPaths = ["position", "rotationQuaternion", "scaling"]; /** * Parse * @param parsedBuffers * @param gltfRuntime */ var parseBuffers = function (parsedBuffers, gltfRuntime) { for (var buf in parsedBuffers) { var parsedBuffer = parsedBuffers[buf]; gltfRuntime.buffers[buf] = parsedBuffer; gltfRuntime.buffersCount++; } }; var parseShaders = function (parsedShaders, gltfRuntime) { for (var sha in parsedShaders) { var parsedShader = parsedShaders[sha]; gltfRuntime.shaders[sha] = parsedShader; gltfRuntime.shaderscount++; } }; var parseObject = function (parsedObjects, runtimeProperty, gltfRuntime) { for (var object in parsedObjects) { var parsedObject = parsedObjects[object]; gltfRuntime[runtimeProperty][object] = parsedObject; } }; /** * Utils * @param buffer */ var normalizeUVs = function (buffer) { if (!buffer) { return; } for (var i = 0; i < buffer.length / 2; i++) { buffer[i * 2 + 1] = 1.0 - buffer[i * 2 + 1]; } }; var getAttribute = function (attributeParameter) { if (attributeParameter.semantic === "NORMAL") { return "normal"; } else if (attributeParameter.semantic === "POSITION") { return "position"; } else if (attributeParameter.semantic === "JOINT") { return "matricesIndices"; } else if (attributeParameter.semantic === "WEIGHT") { return "matricesWeights"; } else if (attributeParameter.semantic === "COLOR") { return "color"; } else if (attributeParameter.semantic && attributeParameter.semantic.indexOf("TEXCOORD_") !== -1) { var channel = Number(attributeParameter.semantic.split("_")[1]); return "uv" + (channel === 0 ? "" : channel + 1); } return null; }; /** * Loads and creates animations * @param gltfRuntime */ var loadAnimations = function (gltfRuntime) { for (var anim in gltfRuntime.animations) { var animation = gltfRuntime.animations[anim]; if (!animation.channels || !animation.samplers) { continue; } var lastAnimation = null; for (var i = 0; i < animation.channels.length; i++) { // Get parameters and load buffers var channel = animation.channels[i]; var sampler = animation.samplers[channel.sampler]; if (!sampler) { continue; } var inputData = null; var outputData = null; if (animation.parameters) { inputData = animation.parameters[sampler.input]; outputData = animation.parameters[sampler.output]; } else { inputData = sampler.input; outputData = sampler.output; } var bufferInput = _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_2__.GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[inputData]); var bufferOutput = _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_2__.GLTFUtils.GetBufferFromAccessor(gltfRuntime, gltfRuntime.accessors[outputData]); var targetId = channel.target.id; var targetNode = gltfRuntime.scene.getNodeById(targetId); if (targetNode === null) { targetNode = gltfRuntime.scene.getNodeByName(targetId); } if (targetNode === null) { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.Warn("Creating animation named " + anim + ". But cannot find node named " + targetId + " to attach to"); continue; } var isBone = targetNode instanceof babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Bone; // Get target path (position, rotation or scaling) var targetPath = channel.target.path; var targetPathIndex = glTFAnimationPaths.indexOf(targetPath); if (targetPathIndex !== -1) { targetPath = babylonAnimationPaths[targetPathIndex]; } // Determine animation type var animationType = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Animation.ANIMATIONTYPE_MATRIX; if (!isBone) { if (targetPath === "rotationQuaternion") { animationType = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Animation.ANIMATIONTYPE_QUATERNION; targetNode.rotationQuaternion = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Quaternion(); } else { animationType = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Animation.ANIMATIONTYPE_VECTOR3; } } // Create animation and key frames var babylonAnimation = null; var keys = []; var arrayOffset = 0; var modifyKey = false; if (isBone && lastAnimation && lastAnimation.getKeys().length === bufferInput.length) { babylonAnimation = lastAnimation; modifyKey = true; } if (!modifyKey) { gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer; babylonAnimation = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Animation(anim, isBone ? "_matrix" : targetPath, 1, animationType, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Animation.ANIMATIONLOOPMODE_CYCLE); gltfRuntime.scene._blockEntityCollection = false; } // For each frame for (var j = 0; j < bufferInput.length; j++) { var value = null; if (targetPath === "rotationQuaternion") { // VEC4 value = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Quaternion.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2], bufferOutput[arrayOffset + 3]]); arrayOffset += 4; } else { // Position and scaling are VEC3 value = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.FromArray([bufferOutput[arrayOffset], bufferOutput[arrayOffset + 1], bufferOutput[arrayOffset + 2]]); arrayOffset += 3; } if (isBone) { var bone = targetNode; var translation = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.Zero(); var rotationQuaternion = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Quaternion(); var scaling = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.Zero(); // Warning on decompose var mat = bone.getBaseMatrix(); if (modifyKey && lastAnimation) { mat = lastAnimation.getKeys()[j].value; } mat.decompose(scaling, rotationQuaternion, translation); if (targetPath === "position") { translation = value; } else if (targetPath === "rotationQuaternion") { rotationQuaternion = value; } else { scaling = value; } value = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Matrix.Compose(scaling, rotationQuaternion, translation); } if (!modifyKey) { keys.push({ frame: bufferInput[j], value: value, }); } else if (lastAnimation) { lastAnimation.getKeys()[j].value = value; } } // Finish if (!modifyKey && babylonAnimation) { babylonAnimation.setKeys(keys); targetNode.animations.push(babylonAnimation); } lastAnimation = babylonAnimation; gltfRuntime.scene.stopAnimation(targetNode); gltfRuntime.scene.beginAnimation(targetNode, 0, bufferInput[bufferInput.length - 1], true, 1.0); } } }; /** * Returns the bones transformation matrix * @param node */ var configureBoneTransformation = function (node) { var mat = null; if (node.translation || node.rotation || node.scale) { var scale = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.FromArray(node.scale || [1, 1, 1]); var rotation = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Quaternion.FromArray(node.rotation || [0, 0, 0, 1]); var position = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.FromArray(node.translation || [0, 0, 0]); mat = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Matrix.Compose(scale, rotation, position); } else { mat = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Matrix.FromArray(node.matrix); } return mat; }; /** * Returns the parent bone * @param gltfRuntime * @param skins * @param jointName * @param newSkeleton */ var getParentBone = function (gltfRuntime, skins, jointName, newSkeleton) { // Try to find for (var i = 0; i < newSkeleton.bones.length; i++) { if (newSkeleton.bones[i].name === jointName) { return newSkeleton.bones[i]; } } // Not found, search in gltf nodes var nodes = gltfRuntime.nodes; for (var nde in nodes) { var node = nodes[nde]; if (!node.jointName) { continue; } var children = node.children; for (var i = 0; i < children.length; i++) { var child = gltfRuntime.nodes[children[i]]; if (!child.jointName) { continue; } if (child.jointName === jointName) { var mat = configureBoneTransformation(node); var bone = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Bone(node.name || "", newSkeleton, getParentBone(gltfRuntime, skins, node.jointName, newSkeleton), mat); bone.id = nde; return bone; } } } return null; }; /** * Returns the appropriate root node * @param nodesToRoot * @param id */ var getNodeToRoot = function (nodesToRoot, id) { for (var i = 0; i < nodesToRoot.length; i++) { var nodeToRoot = nodesToRoot[i]; for (var j = 0; j < nodeToRoot.node.children.length; j++) { var child = nodeToRoot.node.children[j]; if (child === id) { return nodeToRoot.bone; } } } return null; }; /** * Returns the node with the joint name * @param gltfRuntime * @param jointName */ var getJointNode = function (gltfRuntime, jointName) { var nodes = gltfRuntime.nodes; var node = nodes[jointName]; if (node) { return { node: node, id: jointName, }; } for (var nde in nodes) { node = nodes[nde]; if (node.jointName === jointName) { return { node: node, id: nde, }; } } return null; }; /** * Checks if a nodes is in joints * @param skins * @param id */ var nodeIsInJoints = function (skins, id) { for (var i = 0; i < skins.jointNames.length; i++) { if (skins.jointNames[i] === id) { return true; } } return false; }; /** * Fills the nodes to root for bones and builds hierarchy * @param gltfRuntime * @param newSkeleton * @param skins * @param nodesToRoot */ var getNodesToRoot = function (gltfRuntime, newSkeleton, skins, nodesToRoot) { // Creates nodes for root for (var nde in gltfRuntime.nodes) { var node = gltfRuntime.nodes[nde]; var id = nde; if (!node.jointName || nodeIsInJoints(skins, node.jointName)) { continue; } // Create node to root bone var mat = configureBoneTransformation(node); var bone = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Bone(node.name || "", newSkeleton, null, mat); bone.id = id; nodesToRoot.push({ bone: bone, node: node, id: id }); } // Parenting for (var i = 0; i < nodesToRoot.length; i++) { var nodeToRoot = nodesToRoot[i]; var children = nodeToRoot.node.children; for (var j = 0; j < children.length; j++) { var child = null; for (var k = 0; k < nodesToRoot.length; k++) { if (nodesToRoot[k].id === children[j]) { child = nodesToRoot[k]; break; } } if (child) { child.bone._parent = nodeToRoot.bone; nodeToRoot.bone.children.push(child.bone); } } } }; /** * Imports a skeleton * @param gltfRuntime * @param skins * @param mesh * @param newSkeleton */ var importSkeleton = function (gltfRuntime, skins, mesh, newSkeleton) { if (!newSkeleton) { newSkeleton = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Skeleton(skins.name || "", "", gltfRuntime.scene); } if (!skins.babylonSkeleton) { return newSkeleton; } // Find the root bones var nodesToRoot = []; var nodesToRootToAdd = []; getNodesToRoot(gltfRuntime, newSkeleton, skins, nodesToRoot); newSkeleton.bones = []; // Joints for (var i = 0; i < skins.jointNames.length; i++) { var jointNode = getJointNode(gltfRuntime, skins.jointNames[i]); if (!jointNode) { continue; } var node = jointNode.node; if (!node) { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.Warn("Joint named " + skins.jointNames[i] + " does not exist"); continue; } var id = jointNode.id; // Optimize, if the bone already exists... var existingBone = gltfRuntime.scene.getBoneById(id); if (existingBone) { newSkeleton.bones.push(existingBone); continue; } // Search for parent bone var foundBone = false; var parentBone = null; for (var j = 0; j < i; j++) { var jointNode_1 = getJointNode(gltfRuntime, skins.jointNames[j]); if (!jointNode_1) { continue; } var joint = jointNode_1.node; if (!joint) { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.Warn("Joint named " + skins.jointNames[j] + " does not exist when looking for parent"); continue; } var children = joint.children; if (!children) { continue; } foundBone = false; for (var k = 0; k < children.length; k++) { if (children[k] === id) { parentBone = getParentBone(gltfRuntime, skins, skins.jointNames[j], newSkeleton); foundBone = true; break; } } if (foundBone) { break; } } // Create bone var mat = configureBoneTransformation(node); if (!parentBone && nodesToRoot.length > 0) { parentBone = getNodeToRoot(nodesToRoot, id); if (parentBone) { if (nodesToRootToAdd.indexOf(parentBone) === -1) { nodesToRootToAdd.push(parentBone); } } } var bone = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Bone(node.jointName || "", newSkeleton, parentBone, mat); bone.id = id; } // Polish var bones = newSkeleton.bones; newSkeleton.bones = []; for (var i = 0; i < skins.jointNames.length; i++) { var jointNode = getJointNode(gltfRuntime, skins.jointNames[i]); if (!jointNode) { continue; } for (var j = 0; j < bones.length; j++) { if (bones[j].id === jointNode.id) { newSkeleton.bones.push(bones[j]); break; } } } newSkeleton.prepare(); // Finish for (var i = 0; i < nodesToRootToAdd.length; i++) { newSkeleton.bones.push(nodesToRootToAdd[i]); } return newSkeleton; }; /** * Imports a mesh and its geometries * @param gltfRuntime * @param node * @param meshes * @param id * @param newMesh */ var importMesh = function (gltfRuntime, node, meshes, id, newMesh) { if (!newMesh) { gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer; newMesh = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Mesh(node.name || "", gltfRuntime.scene); newMesh._parentContainer = gltfRuntime.assetContainer; gltfRuntime.scene._blockEntityCollection = false; newMesh.id = id; } if (!node.babylonNode) { return newMesh; } var subMaterials = []; var vertexData = null; var verticesStarts = new Array(); var verticesCounts = new Array(); var indexStarts = new Array(); var indexCounts = new Array(); for (var meshIndex = 0; meshIndex < meshes.length; meshIndex++) { var meshId = meshes[meshIndex]; var mesh = gltfRuntime.meshes[meshId]; if (!mesh) { continue; } // Positions, normals and UVs for (var i = 0; i < mesh.primitives.length; i++) { // Temporary vertex data var tempVertexData = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.VertexData(); var primitive = mesh.primitives[i]; if (primitive.mode !== 4) { // continue; } var attributes = primitive.attributes; var accessor = null; var buffer = null; // Set positions, normal and uvs for (var semantic in attributes) { // Link accessor and buffer view accessor = gltfRuntime.accessors[attributes[semantic]]; buffer = _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_2__.GLTFUtils.GetBufferFromAccessor(gltfRuntime, accessor); if (semantic === "NORMAL") { tempVertexData.normals = new Float32Array(buffer.length); tempVertexData.normals.set(buffer); } else if (semantic === "POSITION") { if (_glTFFileLoader__WEBPACK_IMPORTED_MODULE_3__.GLTFFileLoader.HomogeneousCoordinates) { tempVertexData.positions = new Float32Array(buffer.length - buffer.length / 4); for (var j = 0; j < buffer.length; j += 4) { tempVertexData.positions[j] = buffer[j]; tempVertexData.positions[j + 1] = buffer[j + 1]; tempVertexData.positions[j + 2] = buffer[j + 2]; } } else { tempVertexData.positions = new Float32Array(buffer.length); tempVertexData.positions.set(buffer); } verticesCounts.push(tempVertexData.positions.length); } else if (semantic.indexOf("TEXCOORD_") !== -1) { var channel = Number(semantic.split("_")[1]); var uvKind = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.VertexBuffer.UVKind + (channel === 0 ? "" : channel + 1); var uvs = new Float32Array(buffer.length); uvs.set(buffer); normalizeUVs(uvs); tempVertexData.set(uvs, uvKind); } else if (semantic === "JOINT") { tempVertexData.matricesIndices = new Float32Array(buffer.length); tempVertexData.matricesIndices.set(buffer); } else if (semantic === "WEIGHT") { tempVertexData.matricesWeights = new Float32Array(buffer.length); tempVertexData.matricesWeights.set(buffer); } else if (semantic === "COLOR") { tempVertexData.colors = new Float32Array(buffer.length); tempVertexData.colors.set(buffer); } } // Indices accessor = gltfRuntime.accessors[primitive.indices]; if (accessor) { buffer = _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_2__.GLTFUtils.GetBufferFromAccessor(gltfRuntime, accessor); tempVertexData.indices = new Int32Array(buffer.length); tempVertexData.indices.set(buffer); indexCounts.push(tempVertexData.indices.length); } else { // Set indices on the fly var indices = []; for (var j = 0; j < tempVertexData.positions.length / 3; j++) { indices.push(j); } tempVertexData.indices = new Int32Array(indices); indexCounts.push(tempVertexData.indices.length); } if (!vertexData) { vertexData = tempVertexData; } else { vertexData.merge(tempVertexData); } // Sub material var material_1 = gltfRuntime.scene.getMaterialById(primitive.material); subMaterials.push(material_1 === null ? _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_2__.GLTFUtils.GetDefaultMaterial(gltfRuntime.scene) : material_1); // Update vertices start and index start verticesStarts.push(verticesStarts.length === 0 ? 0 : verticesStarts[verticesStarts.length - 1] + verticesCounts[verticesCounts.length - 2]); indexStarts.push(indexStarts.length === 0 ? 0 : indexStarts[indexStarts.length - 1] + indexCounts[indexCounts.length - 2]); } } var material; gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer; if (subMaterials.length > 1) { material = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.MultiMaterial("multimat" + id, gltfRuntime.scene); material.subMaterials = subMaterials; } else { material = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.StandardMaterial("multimat" + id, gltfRuntime.scene); } if (subMaterials.length === 1) { material = subMaterials[0]; } material._parentContainer = gltfRuntime.assetContainer; if (!newMesh.material) { newMesh.material = material; } // Apply geometry new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Geometry(id, gltfRuntime.scene, vertexData, false, newMesh); newMesh.computeWorldMatrix(true); gltfRuntime.scene._blockEntityCollection = false; // Apply submeshes newMesh.subMeshes = []; var index = 0; for (var meshIndex = 0; meshIndex < meshes.length; meshIndex++) { var meshId = meshes[meshIndex]; var mesh = gltfRuntime.meshes[meshId]; if (!mesh) { continue; } for (var i = 0; i < mesh.primitives.length; i++) { if (mesh.primitives[i].mode !== 4) { //continue; } babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.SubMesh.AddToMesh(index, verticesStarts[index], verticesCounts[index], indexStarts[index], indexCounts[index], newMesh, newMesh, true); index++; } } // Finish return newMesh; }; /** * Configure node transformation from position, rotation and scaling * @param newNode * @param position * @param rotation * @param scaling */ var configureNode = function (newNode, position, rotation, scaling) { if (newNode.position) { newNode.position = position; } if (newNode.rotationQuaternion || newNode.rotation) { newNode.rotationQuaternion = rotation; } if (newNode.scaling) { newNode.scaling = scaling; } }; /** * Configures node from transformation matrix * @param newNode * @param node */ var configureNodeFromMatrix = function (newNode, node) { if (node.matrix) { var position = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3(0, 0, 0); var rotation = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Quaternion(); var scaling = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3(0, 0, 0); var mat = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Matrix.FromArray(node.matrix); mat.decompose(scaling, rotation, position); configureNode(newNode, position, rotation, scaling); } else if (node.translation && node.rotation && node.scale) { configureNode(newNode, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.FromArray(node.translation), babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Quaternion.FromArray(node.rotation), babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.FromArray(node.scale)); } newNode.computeWorldMatrix(true); }; /** * Imports a node * @param gltfRuntime * @param node * @param id */ var importNode = function (gltfRuntime, node, id) { var lastNode = null; if (gltfRuntime.importOnlyMeshes && (node.skin || node.meshes)) { if (gltfRuntime.importMeshesNames && gltfRuntime.importMeshesNames.length > 0 && gltfRuntime.importMeshesNames.indexOf(node.name || "") === -1) { return null; } } // Meshes if (node.skin) { if (node.meshes) { var skin = gltfRuntime.skins[node.skin]; var newMesh = importMesh(gltfRuntime, node, node.meshes, id, node.babylonNode); newMesh.skeleton = gltfRuntime.scene.getLastSkeletonById(node.skin); if (newMesh.skeleton === null) { newMesh.skeleton = importSkeleton(gltfRuntime, skin, newMesh, skin.babylonSkeleton); if (!skin.babylonSkeleton) { skin.babylonSkeleton = newMesh.skeleton; } } lastNode = newMesh; } } else if (node.meshes) { /** * Improve meshes property */ var newMesh = importMesh(gltfRuntime, node, node.mesh ? [node.mesh] : node.meshes, id, node.babylonNode); lastNode = newMesh; } // Lights else if (node.light && !node.babylonNode && !gltfRuntime.importOnlyMeshes) { var light = gltfRuntime.lights[node.light]; if (light) { if (light.type === "ambient") { var ambienLight = light[light.type]; var hemiLight = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.HemisphericLight(node.light, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.Zero(), gltfRuntime.scene); hemiLight.name = node.name || ""; if (ambienLight.color) { hemiLight.diffuse = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color3.FromArray(ambienLight.color); } lastNode = hemiLight; } else if (light.type === "directional") { var directionalLight = light[light.type]; var dirLight = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.DirectionalLight(node.light, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.Zero(), gltfRuntime.scene); dirLight.name = node.name || ""; if (directionalLight.color) { dirLight.diffuse = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color3.FromArray(directionalLight.color); } lastNode = dirLight; } else if (light.type === "point") { var pointLight = light[light.type]; var ptLight = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.PointLight(node.light, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.Zero(), gltfRuntime.scene); ptLight.name = node.name || ""; if (pointLight.color) { ptLight.diffuse = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color3.FromArray(pointLight.color); } lastNode = ptLight; } else if (light.type === "spot") { var spotLight = light[light.type]; var spLight = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.SpotLight(node.light, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.Zero(), babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.Zero(), 0, 0, gltfRuntime.scene); spLight.name = node.name || ""; if (spotLight.color) { spLight.diffuse = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color3.FromArray(spotLight.color); } if (spotLight.fallOfAngle) { spLight.angle = spotLight.fallOfAngle; } if (spotLight.fallOffExponent) { spLight.exponent = spotLight.fallOffExponent; } lastNode = spLight; } } } // Cameras else if (node.camera && !node.babylonNode && !gltfRuntime.importOnlyMeshes) { var camera = gltfRuntime.cameras[node.camera]; if (camera) { gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer; if (camera.type === "orthographic") { var orthoCamera = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.FreeCamera(node.camera, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.Zero(), gltfRuntime.scene, false); orthoCamera.name = node.name || ""; orthoCamera.mode = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Camera.ORTHOGRAPHIC_CAMERA; orthoCamera.attachControl(); lastNode = orthoCamera; orthoCamera._parentContainer = gltfRuntime.assetContainer; } else if (camera.type === "perspective") { var perspectiveCamera = camera[camera.type]; var persCamera = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.FreeCamera(node.camera, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.Zero(), gltfRuntime.scene, false); persCamera.name = node.name || ""; persCamera.attachControl(); if (!perspectiveCamera.aspectRatio) { perspectiveCamera.aspectRatio = gltfRuntime.scene.getEngine().getRenderWidth() / gltfRuntime.scene.getEngine().getRenderHeight(); } if (perspectiveCamera.znear && perspectiveCamera.zfar) { persCamera.maxZ = perspectiveCamera.zfar; persCamera.minZ = perspectiveCamera.znear; } lastNode = persCamera; persCamera._parentContainer = gltfRuntime.assetContainer; } gltfRuntime.scene._blockEntityCollection = false; } } // Empty node if (!node.jointName) { if (node.babylonNode) { return node.babylonNode; } else if (lastNode === null) { gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer; var dummy = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Mesh(node.name || "", gltfRuntime.scene); dummy._parentContainer = gltfRuntime.assetContainer; gltfRuntime.scene._blockEntityCollection = false; node.babylonNode = dummy; lastNode = dummy; } } if (lastNode !== null) { if (node.matrix && lastNode instanceof babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Mesh) { configureNodeFromMatrix(lastNode, node); } else { var translation = node.translation || [0, 0, 0]; var rotation = node.rotation || [0, 0, 0, 1]; var scale = node.scale || [1, 1, 1]; configureNode(lastNode, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.FromArray(translation), babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Quaternion.FromArray(rotation), babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.FromArray(scale)); } lastNode.updateCache(true); node.babylonNode = lastNode; } return lastNode; }; /** * Traverses nodes and creates them * @param gltfRuntime * @param id * @param parent * @param meshIncluded */ var traverseNodes = function (gltfRuntime, id, parent, meshIncluded) { if (meshIncluded === void 0) { meshIncluded = false; } var node = gltfRuntime.nodes[id]; var newNode = null; if (gltfRuntime.importOnlyMeshes && !meshIncluded && gltfRuntime.importMeshesNames) { if (gltfRuntime.importMeshesNames.indexOf(node.name || "") !== -1 || gltfRuntime.importMeshesNames.length === 0) { meshIncluded = true; } else { meshIncluded = false; } } else { meshIncluded = true; } if (!node.jointName && meshIncluded) { newNode = importNode(gltfRuntime, node, id); if (newNode !== null) { newNode.id = id; newNode.parent = parent; } } if (node.children) { for (var i = 0; i < node.children.length; i++) { traverseNodes(gltfRuntime, node.children[i], newNode, meshIncluded); } } }; /** * do stuff after buffers, shaders are loaded (e.g. hook up materials, load animations, etc.) * @param gltfRuntime */ var postLoad = function (gltfRuntime) { // Nodes var currentScene = gltfRuntime.currentScene; if (currentScene) { for (var i = 0; i < currentScene.nodes.length; i++) { traverseNodes(gltfRuntime, currentScene.nodes[i], null); } } else { for (var thing in gltfRuntime.scenes) { currentScene = gltfRuntime.scenes[thing]; for (var i = 0; i < currentScene.nodes.length; i++) { traverseNodes(gltfRuntime, currentScene.nodes[i], null); } } } // Set animations loadAnimations(gltfRuntime); for (var i = 0; i < gltfRuntime.scene.skeletons.length; i++) { var skeleton = gltfRuntime.scene.skeletons[i]; gltfRuntime.scene.beginAnimation(skeleton, 0, Number.MAX_VALUE, true, 1.0); } }; /** * onBind shaderrs callback to set uniforms and matrices * @param mesh * @param gltfRuntime * @param unTreatedUniforms * @param shaderMaterial * @param technique * @param material * @param onSuccess */ var onBindShaderMaterial = function (mesh, gltfRuntime, unTreatedUniforms, shaderMaterial, technique, material, onSuccess) { var materialValues = material.values || technique.parameters; for (var unif in unTreatedUniforms) { var uniform = unTreatedUniforms[unif]; var type = uniform.type; if (type === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EParameterType.FLOAT_MAT2 || type === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EParameterType.FLOAT_MAT3 || type === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EParameterType.FLOAT_MAT4) { if (uniform.semantic && !uniform.source && !uniform.node) { _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_2__.GLTFUtils.SetMatrix(gltfRuntime.scene, mesh, uniform, unif, shaderMaterial.getEffect()); } else if (uniform.semantic && (uniform.source || uniform.node)) { var source = gltfRuntime.scene.getNodeByName(uniform.source || uniform.node || ""); if (source === null) { source = gltfRuntime.scene.getNodeById(uniform.source || uniform.node || ""); } if (source === null) { continue; } _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_2__.GLTFUtils.SetMatrix(gltfRuntime.scene, source, uniform, unif, shaderMaterial.getEffect()); } } else { var value = materialValues[technique.uniforms[unif]]; if (!value) { continue; } if (type === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EParameterType.SAMPLER_2D) { var texture = gltfRuntime.textures[material.values ? value : uniform.value].babylonTexture; if (texture === null || texture === undefined) { continue; } shaderMaterial.getEffect().setTexture(unif, texture); } else { _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_2__.GLTFUtils.SetUniform(shaderMaterial.getEffect(), unif, value, type); } } } onSuccess(shaderMaterial); }; /** * Prepare uniforms to send the only one time * Loads the appropriate textures * @param gltfRuntime * @param shaderMaterial * @param technique * @param material */ var prepareShaderMaterialUniforms = function (gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms) { var materialValues = material.values || technique.parameters; var techniqueUniforms = technique.uniforms; var _loop_1 = function (unif) { var uniform = unTreatedUniforms[unif]; var type = uniform.type; var value = materialValues[techniqueUniforms[unif]]; if (value === undefined) { // In case the value is the same for all materials value = uniform.value; } if (!value) { return "continue"; } var onLoadTexture = function (uniformName) { return function (texture) { if (uniform.value && uniformName) { // Static uniform shaderMaterial.setTexture(uniformName, texture); delete unTreatedUniforms[uniformName]; } }; }; // Texture (sampler2D) if (type === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EParameterType.SAMPLER_2D) { GLTFLoaderExtension.LoadTextureAsync(gltfRuntime, material.values ? value : uniform.value, onLoadTexture(unif), function () { return onLoadTexture(null); }); } // Others else { if (uniform.value && _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_2__.GLTFUtils.SetUniform(shaderMaterial, unif, material.values ? value : uniform.value, type)) { // Static uniform delete unTreatedUniforms[unif]; } } }; /** * Prepare values here (not matrices) */ for (var unif in unTreatedUniforms) { _loop_1(unif); } }; /** * Shader compilation failed * @param program * @param shaderMaterial * @param onError */ var onShaderCompileError = function (program, shaderMaterial, onError) { return function (effect, error) { shaderMaterial.dispose(true); onError("Cannot compile program named " + program.name + ". Error: " + error + ". Default material will be applied"); }; }; /** * Shader compilation success * @param gltfRuntime * @param shaderMaterial * @param technique * @param material * @param unTreatedUniforms * @param onSuccess */ var onShaderCompileSuccess = function (gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms, onSuccess) { return function (_) { prepareShaderMaterialUniforms(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms); shaderMaterial.onBind = function (mesh) { onBindShaderMaterial(mesh, gltfRuntime, unTreatedUniforms, shaderMaterial, technique, material, onSuccess); }; }; }; /** * Returns the appropriate uniform if already handled by babylon * @param tokenizer * @param technique */ var parseShaderUniforms = function (tokenizer, technique, unTreatedUniforms) { for (var unif in technique.uniforms) { var uniform = technique.uniforms[unif]; var uniformParameter = technique.parameters[uniform]; if (tokenizer.currentIdentifier === unif) { if (uniformParameter.semantic && !uniformParameter.source && !uniformParameter.node) { var transformIndex = glTFTransforms.indexOf(uniformParameter.semantic); if (transformIndex !== -1) { delete unTreatedUniforms[unif]; return babylonTransforms[transformIndex]; } } } } return tokenizer.currentIdentifier; }; /** * All shaders loaded. Create materials one by one * @param gltfRuntime */ var importMaterials = function (gltfRuntime) { // Create materials for (var mat in gltfRuntime.materials) { GLTFLoaderExtension.LoadMaterialAsync(gltfRuntime, mat, function () { }, function () { }); } }; /** * Implementation of the base glTF spec * @internal */ var GLTFLoaderBase = /** @class */ (function () { function GLTFLoaderBase() { } GLTFLoaderBase.CreateRuntime = function (parsedData, scene, rootUrl) { var gltfRuntime = { extensions: {}, accessors: {}, buffers: {}, bufferViews: {}, meshes: {}, lights: {}, cameras: {}, nodes: {}, images: {}, textures: {}, shaders: {}, programs: {}, samplers: {}, techniques: {}, materials: {}, animations: {}, skins: {}, extensionsUsed: [], scenes: {}, buffersCount: 0, shaderscount: 0, scene: scene, rootUrl: rootUrl, loadedBufferCount: 0, loadedBufferViews: {}, loadedShaderCount: 0, importOnlyMeshes: false, dummyNodes: [], assetContainer: null, }; // Parse if (parsedData.extensions) { parseObject(parsedData.extensions, "extensions", gltfRuntime); } if (parsedData.extensionsUsed) { parseObject(parsedData.extensionsUsed, "extensionsUsed", gltfRuntime); } if (parsedData.buffers) { parseBuffers(parsedData.buffers, gltfRuntime); } if (parsedData.bufferViews) { parseObject(parsedData.bufferViews, "bufferViews", gltfRuntime); } if (parsedData.accessors) { parseObject(parsedData.accessors, "accessors", gltfRuntime); } if (parsedData.meshes) { parseObject(parsedData.meshes, "meshes", gltfRuntime); } if (parsedData.lights) { parseObject(parsedData.lights, "lights", gltfRuntime); } if (parsedData.cameras) { parseObject(parsedData.cameras, "cameras", gltfRuntime); } if (parsedData.nodes) { parseObject(parsedData.nodes, "nodes", gltfRuntime); } if (parsedData.images) { parseObject(parsedData.images, "images", gltfRuntime); } if (parsedData.textures) { parseObject(parsedData.textures, "textures", gltfRuntime); } if (parsedData.shaders) { parseShaders(parsedData.shaders, gltfRuntime); } if (parsedData.programs) { parseObject(parsedData.programs, "programs", gltfRuntime); } if (parsedData.samplers) { parseObject(parsedData.samplers, "samplers", gltfRuntime); } if (parsedData.techniques) { parseObject(parsedData.techniques, "techniques", gltfRuntime); } if (parsedData.materials) { parseObject(parsedData.materials, "materials", gltfRuntime); } if (parsedData.animations) { parseObject(parsedData.animations, "animations", gltfRuntime); } if (parsedData.skins) { parseObject(parsedData.skins, "skins", gltfRuntime); } if (parsedData.scenes) { gltfRuntime.scenes = parsedData.scenes; } if (parsedData.scene && parsedData.scenes) { gltfRuntime.currentScene = parsedData.scenes[parsedData.scene]; } return gltfRuntime; }; GLTFLoaderBase.LoadBufferAsync = function (gltfRuntime, id, onSuccess, onError, onProgress) { var buffer = gltfRuntime.buffers[id]; if (babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.IsBase64(buffer.uri)) { setTimeout(function () { return onSuccess(new Uint8Array(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.DecodeBase64(buffer.uri))); }); } else { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.LoadFile(gltfRuntime.rootUrl + buffer.uri, function (data) { return onSuccess(new Uint8Array(data)); }, onProgress, undefined, true, function (request) { if (request) { onError(request.status + " " + request.statusText); } }); } }; GLTFLoaderBase.LoadTextureBufferAsync = function (gltfRuntime, id, onSuccess, onError) { var texture = gltfRuntime.textures[id]; if (!texture || !texture.source) { onError(""); return; } if (texture.babylonTexture) { onSuccess(null); return; } var source = gltfRuntime.images[texture.source]; if (babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.IsBase64(source.uri)) { setTimeout(function () { return onSuccess(new Uint8Array(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.DecodeBase64(source.uri))); }); } else { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.LoadFile(gltfRuntime.rootUrl + source.uri, function (data) { return onSuccess(new Uint8Array(data)); }, undefined, undefined, true, function (request) { if (request) { onError(request.status + " " + request.statusText); } }); } }; GLTFLoaderBase.CreateTextureAsync = function (gltfRuntime, id, buffer, onSuccess) { var texture = gltfRuntime.textures[id]; if (texture.babylonTexture) { onSuccess(texture.babylonTexture); return; } var sampler = gltfRuntime.samplers[texture.sampler]; var createMipMaps = sampler.minFilter === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.ETextureFilterType.NEAREST_MIPMAP_NEAREST || sampler.minFilter === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.ETextureFilterType.NEAREST_MIPMAP_LINEAR || sampler.minFilter === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.ETextureFilterType.LINEAR_MIPMAP_NEAREST || sampler.minFilter === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.ETextureFilterType.LINEAR_MIPMAP_LINEAR; var samplingMode = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Texture.BILINEAR_SAMPLINGMODE; var blob = buffer == null ? new Blob() : new Blob([buffer]); var blobURL = URL.createObjectURL(blob); var revokeBlobURL = function () { return URL.revokeObjectURL(blobURL); }; var newTexture = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Texture(blobURL, gltfRuntime.scene, !createMipMaps, true, samplingMode, revokeBlobURL, revokeBlobURL); if (sampler.wrapS !== undefined) { newTexture.wrapU = _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_2__.GLTFUtils.GetWrapMode(sampler.wrapS); } if (sampler.wrapT !== undefined) { newTexture.wrapV = _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_2__.GLTFUtils.GetWrapMode(sampler.wrapT); } newTexture.name = id; texture.babylonTexture = newTexture; onSuccess(newTexture); }; GLTFLoaderBase.LoadShaderStringAsync = function (gltfRuntime, id, onSuccess, onError) { var shader = gltfRuntime.shaders[id]; if (babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.IsBase64(shader.uri)) { var shaderString = atob(shader.uri.split(",")[1]); if (onSuccess) { onSuccess(shaderString); } } else { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.LoadFile(gltfRuntime.rootUrl + shader.uri, onSuccess, undefined, undefined, false, function (request) { if (request && onError) { onError(request.status + " " + request.statusText); } }); } }; GLTFLoaderBase.LoadMaterialAsync = function (gltfRuntime, id, onSuccess, onError) { var material = gltfRuntime.materials[id]; if (!material.technique) { if (onError) { onError("No technique found."); } return; } var technique = gltfRuntime.techniques[material.technique]; if (!technique) { gltfRuntime.scene._blockEntityCollection = !!gltfRuntime.assetContainer; var defaultMaterial = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.StandardMaterial(id, gltfRuntime.scene); defaultMaterial._parentContainer = gltfRuntime.assetContainer; gltfRuntime.scene._blockEntityCollection = false; defaultMaterial.diffuseColor = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color3(0.5, 0.5, 0.5); defaultMaterial.sideOrientation = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Material.CounterClockWiseSideOrientation; onSuccess(defaultMaterial); return; } var program = gltfRuntime.programs[technique.program]; var states = technique.states; var vertexShader = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Effect.ShadersStore[program.vertexShader + "VertexShader"]; var pixelShader = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Effect.ShadersStore[program.fragmentShader + "PixelShader"]; var newVertexShader = ""; var newPixelShader = ""; var vertexTokenizer = new Tokenizer(vertexShader); var pixelTokenizer = new Tokenizer(pixelShader); var unTreatedUniforms = {}; var uniforms = []; var attributes = []; var samplers = []; // Fill uniform, sampler2D and attributes for (var unif in technique.uniforms) { var uniform = technique.uniforms[unif]; var uniformParameter = technique.parameters[uniform]; unTreatedUniforms[unif] = uniformParameter; if (uniformParameter.semantic && !uniformParameter.node && !uniformParameter.source) { var transformIndex = glTFTransforms.indexOf(uniformParameter.semantic); if (transformIndex !== -1) { uniforms.push(babylonTransforms[transformIndex]); delete unTreatedUniforms[unif]; } else { uniforms.push(unif); } } else if (uniformParameter.type === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EParameterType.SAMPLER_2D) { samplers.push(unif); } else { uniforms.push(unif); } } for (var attr in technique.attributes) { var attribute = technique.attributes[attr]; var attributeParameter = technique.parameters[attribute]; if (attributeParameter.semantic) { var name_1 = getAttribute(attributeParameter); if (name_1) { attributes.push(name_1); } } } // Configure vertex shader while (!vertexTokenizer.isEnd() && vertexTokenizer.getNextToken()) { var tokenType = vertexTokenizer.currentToken; if (tokenType !== ETokenType.IDENTIFIER) { newVertexShader += vertexTokenizer.currentString; continue; } var foundAttribute = false; for (var attr in technique.attributes) { var attribute = technique.attributes[attr]; var attributeParameter = technique.parameters[attribute]; if (vertexTokenizer.currentIdentifier === attr && attributeParameter.semantic) { newVertexShader += getAttribute(attributeParameter); foundAttribute = true; break; } } if (foundAttribute) { continue; } newVertexShader += parseShaderUniforms(vertexTokenizer, technique, unTreatedUniforms); } // Configure pixel shader while (!pixelTokenizer.isEnd() && pixelTokenizer.getNextToken()) { var tokenType = pixelTokenizer.currentToken; if (tokenType !== ETokenType.IDENTIFIER) { newPixelShader += pixelTokenizer.currentString; continue; } newPixelShader += parseShaderUniforms(pixelTokenizer, technique, unTreatedUniforms); } // Create shader material var shaderPath = { vertex: program.vertexShader + id, fragment: program.fragmentShader + id, }; var options = { attributes: attributes, uniforms: uniforms, samplers: samplers, needAlphaBlending: states && states.enable && states.enable.indexOf(3042) !== -1, }; babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Effect.ShadersStore[program.vertexShader + id + "VertexShader"] = newVertexShader; babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Effect.ShadersStore[program.fragmentShader + id + "PixelShader"] = newPixelShader; var shaderMaterial = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.ShaderMaterial(id, gltfRuntime.scene, shaderPath, options); shaderMaterial.onError = onShaderCompileError(program, shaderMaterial, onError); shaderMaterial.onCompiled = onShaderCompileSuccess(gltfRuntime, shaderMaterial, technique, material, unTreatedUniforms, onSuccess); shaderMaterial.sideOrientation = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Material.CounterClockWiseSideOrientation; if (states && states.functions) { var functions = states.functions; if (functions.cullFace && functions.cullFace[0] !== _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.ECullingType.BACK) { shaderMaterial.backFaceCulling = false; } var blendFunc = functions.blendFuncSeparate; if (blendFunc) { if (blendFunc[0] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.SRC_ALPHA && blendFunc[1] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE_MINUS_SRC_ALPHA && blendFunc[2] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE && blendFunc[3] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE) { shaderMaterial.alphaMode = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Constants.ALPHA_COMBINE; } else if (blendFunc[0] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE && blendFunc[1] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE && blendFunc[2] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ZERO && blendFunc[3] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE) { shaderMaterial.alphaMode = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Constants.ALPHA_ONEONE; } else if (blendFunc[0] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.SRC_ALPHA && blendFunc[1] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE && blendFunc[2] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ZERO && blendFunc[3] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE) { shaderMaterial.alphaMode = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Constants.ALPHA_ADD; } else if (blendFunc[0] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ZERO && blendFunc[1] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE_MINUS_SRC_COLOR && blendFunc[2] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE && blendFunc[3] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE) { shaderMaterial.alphaMode = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Constants.ALPHA_SUBTRACT; } else if (blendFunc[0] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.DST_COLOR && blendFunc[1] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ZERO && blendFunc[2] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE && blendFunc[3] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE) { shaderMaterial.alphaMode = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Constants.ALPHA_MULTIPLY; } else if (blendFunc[0] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.SRC_ALPHA && blendFunc[1] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE_MINUS_SRC_COLOR && blendFunc[2] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE && blendFunc[3] === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EBlendingFunction.ONE) { shaderMaterial.alphaMode = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Constants.ALPHA_MAXIMIZED; } } } }; return GLTFLoaderBase; }()); /** * glTF V1 Loader * @internal * @deprecated */ var GLTFLoader = /** @class */ (function () { function GLTFLoader() { } GLTFLoader.RegisterExtension = function (extension) { if (GLTFLoader.Extensions[extension.name]) { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.Error('Tool with the same name "' + extension.name + '" already exists'); return; } GLTFLoader.Extensions[extension.name] = extension; }; GLTFLoader.prototype.dispose = function () { // do nothing }; GLTFLoader.prototype._importMeshAsync = function (meshesNames, scene, data, rootUrl, assetContainer, onSuccess, onProgress, onError) { var _this = this; scene.useRightHandedSystem = true; GLTFLoaderExtension.LoadRuntimeAsync(scene, data, rootUrl, function (gltfRuntime) { gltfRuntime.assetContainer = assetContainer; gltfRuntime.importOnlyMeshes = true; if (meshesNames === "") { gltfRuntime.importMeshesNames = []; } else if (typeof meshesNames === "string") { gltfRuntime.importMeshesNames = [meshesNames]; } else if (meshesNames && !(meshesNames instanceof Array)) { gltfRuntime.importMeshesNames = [meshesNames]; } else { gltfRuntime.importMeshesNames = []; babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.Warn("Argument meshesNames must be of type string or string[]"); } // Create nodes _this._createNodes(gltfRuntime); var meshes = new Array(); var skeletons = new Array(); // Fill arrays of meshes and skeletons for (var nde in gltfRuntime.nodes) { var node = gltfRuntime.nodes[nde]; if (node.babylonNode instanceof babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.AbstractMesh) { meshes.push(node.babylonNode); } } for (var skl in gltfRuntime.skins) { var skin = gltfRuntime.skins[skl]; if (skin.babylonSkeleton instanceof babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Skeleton) { skeletons.push(skin.babylonSkeleton); } } // Load buffers, shaders, materials, etc. _this._loadBuffersAsync(gltfRuntime, function () { _this._loadShadersAsync(gltfRuntime, function () { importMaterials(gltfRuntime); postLoad(gltfRuntime); if (!_glTFFileLoader__WEBPACK_IMPORTED_MODULE_3__.GLTFFileLoader.IncrementalLoading && onSuccess) { onSuccess(meshes, skeletons); } }); }); if (_glTFFileLoader__WEBPACK_IMPORTED_MODULE_3__.GLTFFileLoader.IncrementalLoading && onSuccess) { onSuccess(meshes, skeletons); } }, onError); return true; }; /** * Imports one or more meshes from a loaded gltf file and adds them to the scene * @param meshesNames a string or array of strings of the mesh names that should be loaded from the file * @param scene the scene the meshes should be added to * @param assetContainer defines the asset container to use (can be null) * @param data gltf data containing information of the meshes in a loaded file * @param rootUrl root url to load from * @param onProgress event that fires when loading progress has occured * @returns a promise containg the loaded meshes, particles, skeletons and animations */ GLTFLoader.prototype.importMeshAsync = function (meshesNames, scene, assetContainer, data, rootUrl, onProgress) { var _this = this; return new Promise(function (resolve, reject) { _this._importMeshAsync(meshesNames, scene, data, rootUrl, assetContainer, function (meshes, skeletons) { resolve({ meshes: meshes, particleSystems: [], skeletons: skeletons, animationGroups: [], lights: [], transformNodes: [], geometries: [], }); }, onProgress, function (message) { reject(new Error(message)); }); }); }; GLTFLoader.prototype._loadAsync = function (scene, data, rootUrl, onSuccess, onProgress, onError) { var _this = this; scene.useRightHandedSystem = true; GLTFLoaderExtension.LoadRuntimeAsync(scene, data, rootUrl, function (gltfRuntime) { // Load runtime extensios GLTFLoaderExtension.LoadRuntimeExtensionsAsync(gltfRuntime, function () { // Create nodes _this._createNodes(gltfRuntime); // Load buffers, shaders, materials, etc. _this._loadBuffersAsync(gltfRuntime, function () { _this._loadShadersAsync(gltfRuntime, function () { importMaterials(gltfRuntime); postLoad(gltfRuntime); if (!_glTFFileLoader__WEBPACK_IMPORTED_MODULE_3__.GLTFFileLoader.IncrementalLoading) { onSuccess(); } }); }); if (_glTFFileLoader__WEBPACK_IMPORTED_MODULE_3__.GLTFFileLoader.IncrementalLoading) { onSuccess(); } }, onError); }, onError); }; /** * Imports all objects from a loaded gltf file and adds them to the scene * @param scene the scene the objects should be added to * @param data gltf data containing information of the meshes in a loaded file * @param rootUrl root url to load from * @param onProgress event that fires when loading progress has occured * @returns a promise which completes when objects have been loaded to the scene */ GLTFLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress) { var _this = this; return new Promise(function (resolve, reject) { _this._loadAsync(scene, data, rootUrl, function () { resolve(); }, onProgress, function (message) { reject(new Error(message)); }); }); }; GLTFLoader.prototype._loadShadersAsync = function (gltfRuntime, onload) { var hasShaders = false; var processShader = function (sha, shader) { GLTFLoaderExtension.LoadShaderStringAsync(gltfRuntime, sha, function (shaderString) { if (shaderString instanceof ArrayBuffer) { return; } gltfRuntime.loadedShaderCount++; if (shaderString) { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Effect.ShadersStore[sha + (shader.type === _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EShaderType.VERTEX ? "VertexShader" : "PixelShader")] = shaderString; } if (gltfRuntime.loadedShaderCount === gltfRuntime.shaderscount) { onload(); } }, function () { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.Error("Error when loading shader program named " + sha + " located at " + shader.uri); }); }; for (var sha in gltfRuntime.shaders) { hasShaders = true; var shader = gltfRuntime.shaders[sha]; if (shader) { processShader.bind(this, sha, shader)(); } else { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.Error("No shader named: " + sha); } } if (!hasShaders) { onload(); } }; GLTFLoader.prototype._loadBuffersAsync = function (gltfRuntime, onLoad) { var hasBuffers = false; var processBuffer = function (buf, buffer) { GLTFLoaderExtension.LoadBufferAsync(gltfRuntime, buf, function (bufferView) { gltfRuntime.loadedBufferCount++; if (bufferView) { if (bufferView.byteLength != gltfRuntime.buffers[buf].byteLength) { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.Error("Buffer named " + buf + " is length " + bufferView.byteLength + ". Expected: " + buffer.byteLength); // Improve error message } gltfRuntime.loadedBufferViews[buf] = bufferView; } if (gltfRuntime.loadedBufferCount === gltfRuntime.buffersCount) { onLoad(); } }, function () { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.Error("Error when loading buffer named " + buf + " located at " + buffer.uri); }); }; for (var buf in gltfRuntime.buffers) { hasBuffers = true; var buffer = gltfRuntime.buffers[buf]; if (buffer) { processBuffer.bind(this, buf, buffer)(); } else { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.Error("No buffer named: " + buf); } } if (!hasBuffers) { onLoad(); } }; GLTFLoader.prototype._createNodes = function (gltfRuntime) { var currentScene = gltfRuntime.currentScene; if (currentScene) { // Only one scene even if multiple scenes are defined for (var i = 0; i < currentScene.nodes.length; i++) { traverseNodes(gltfRuntime, currentScene.nodes[i], null); } } else { // Load all scenes for (var thing in gltfRuntime.scenes) { currentScene = gltfRuntime.scenes[thing]; for (var i = 0; i < currentScene.nodes.length; i++) { traverseNodes(gltfRuntime, currentScene.nodes[i], null); } } } }; GLTFLoader.Extensions = {}; return GLTFLoader; }()); /** @internal */ var GLTFLoaderExtension = /** @class */ (function () { function GLTFLoaderExtension(name) { this._name = name; } Object.defineProperty(GLTFLoaderExtension.prototype, "name", { get: function () { return this._name; }, enumerable: false, configurable: true }); /** * Defines an override for loading the runtime * Return true to stop further extensions from loading the runtime * @param scene * @param data * @param rootUrl * @param onSuccess * @param onError */ GLTFLoaderExtension.prototype.loadRuntimeAsync = function (scene, data, rootUrl, onSuccess, onError) { return false; }; /** * Defines an onverride for creating gltf runtime * Return true to stop further extensions from creating the runtime * @param gltfRuntime * @param onSuccess * @param onError */ GLTFLoaderExtension.prototype.loadRuntimeExtensionsAsync = function (gltfRuntime, onSuccess, onError) { return false; }; /** * Defines an override for loading buffers * Return true to stop further extensions from loading this buffer * @param gltfRuntime * @param id * @param onSuccess * @param onError * @param onProgress */ GLTFLoaderExtension.prototype.loadBufferAsync = function (gltfRuntime, id, onSuccess, onError, onProgress) { return false; }; /** * Defines an override for loading texture buffers * Return true to stop further extensions from loading this texture data * @param gltfRuntime * @param id * @param onSuccess * @param onError */ GLTFLoaderExtension.prototype.loadTextureBufferAsync = function (gltfRuntime, id, onSuccess, onError) { return false; }; /** * Defines an override for creating textures * Return true to stop further extensions from loading this texture * @param gltfRuntime * @param id * @param buffer * @param onSuccess * @param onError */ GLTFLoaderExtension.prototype.createTextureAsync = function (gltfRuntime, id, buffer, onSuccess, onError) { return false; }; /** * Defines an override for loading shader strings * Return true to stop further extensions from loading this shader data * @param gltfRuntime * @param id * @param onSuccess * @param onError */ GLTFLoaderExtension.prototype.loadShaderStringAsync = function (gltfRuntime, id, onSuccess, onError) { return false; }; /** * Defines an override for loading materials * Return true to stop further extensions from loading this material * @param gltfRuntime * @param id * @param onSuccess * @param onError */ GLTFLoaderExtension.prototype.loadMaterialAsync = function (gltfRuntime, id, onSuccess, onError) { return false; }; // --------- // Utilities // --------- GLTFLoaderExtension.LoadRuntimeAsync = function (scene, data, rootUrl, onSuccess, onError) { GLTFLoaderExtension._ApplyExtensions(function (loaderExtension) { return loaderExtension.loadRuntimeAsync(scene, data, rootUrl, onSuccess, onError); }, function () { setTimeout(function () { if (!onSuccess) { return; } onSuccess(GLTFLoaderBase.CreateRuntime(data.json, scene, rootUrl)); }); }); }; GLTFLoaderExtension.LoadRuntimeExtensionsAsync = function (gltfRuntime, onSuccess, onError) { GLTFLoaderExtension._ApplyExtensions(function (loaderExtension) { return loaderExtension.loadRuntimeExtensionsAsync(gltfRuntime, onSuccess, onError); }, function () { setTimeout(function () { onSuccess(); }); }); }; GLTFLoaderExtension.LoadBufferAsync = function (gltfRuntime, id, onSuccess, onError, onProgress) { GLTFLoaderExtension._ApplyExtensions(function (loaderExtension) { return loaderExtension.loadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress); }, function () { GLTFLoaderBase.LoadBufferAsync(gltfRuntime, id, onSuccess, onError, onProgress); }); }; GLTFLoaderExtension.LoadTextureAsync = function (gltfRuntime, id, onSuccess, onError) { GLTFLoaderExtension._LoadTextureBufferAsync(gltfRuntime, id, function (buffer) { if (buffer) { GLTFLoaderExtension._CreateTextureAsync(gltfRuntime, id, buffer, onSuccess, onError); } }, onError); }; GLTFLoaderExtension.LoadShaderStringAsync = function (gltfRuntime, id, onSuccess, onError) { GLTFLoaderExtension._ApplyExtensions(function (loaderExtension) { return loaderExtension.loadShaderStringAsync(gltfRuntime, id, onSuccess, onError); }, function () { GLTFLoaderBase.LoadShaderStringAsync(gltfRuntime, id, onSuccess, onError); }); }; GLTFLoaderExtension.LoadMaterialAsync = function (gltfRuntime, id, onSuccess, onError) { GLTFLoaderExtension._ApplyExtensions(function (loaderExtension) { return loaderExtension.loadMaterialAsync(gltfRuntime, id, onSuccess, onError); }, function () { GLTFLoaderBase.LoadMaterialAsync(gltfRuntime, id, onSuccess, onError); }); }; GLTFLoaderExtension._LoadTextureBufferAsync = function (gltfRuntime, id, onSuccess, onError) { GLTFLoaderExtension._ApplyExtensions(function (loaderExtension) { return loaderExtension.loadTextureBufferAsync(gltfRuntime, id, onSuccess, onError); }, function () { GLTFLoaderBase.LoadTextureBufferAsync(gltfRuntime, id, onSuccess, onError); }); }; GLTFLoaderExtension._CreateTextureAsync = function (gltfRuntime, id, buffer, onSuccess, onError) { GLTFLoaderExtension._ApplyExtensions(function (loaderExtension) { return loaderExtension.createTextureAsync(gltfRuntime, id, buffer, onSuccess, onError); }, function () { GLTFLoaderBase.CreateTextureAsync(gltfRuntime, id, buffer, onSuccess); }); }; GLTFLoaderExtension._ApplyExtensions = function (func, defaultFunc) { for (var extensionName in GLTFLoader.Extensions) { var loaderExtension = GLTFLoader.Extensions[extensionName]; if (func(loaderExtension)) { return; } } defaultFunc(); }; return GLTFLoaderExtension; }()); _glTFFileLoader__WEBPACK_IMPORTED_MODULE_3__.GLTFFileLoader._CreateGLTF1Loader = function () { return new GLTFLoader(); }; /***/ }), /***/ "../../../dev/loaders/src/glTF/1.0/glTFLoaderInterfaces.ts": /*!*****************************************************************!*\ !*** ../../../dev/loaders/src/glTF/1.0/glTFLoaderInterfaces.ts ***! \*****************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ EBlendingFunction: () => (/* binding */ EBlendingFunction), /* harmony export */ EComponentType: () => (/* binding */ EComponentType), /* harmony export */ ECullingType: () => (/* binding */ ECullingType), /* harmony export */ EParameterType: () => (/* binding */ EParameterType), /* harmony export */ EShaderType: () => (/* binding */ EShaderType), /* harmony export */ ETextureFilterType: () => (/* binding */ ETextureFilterType), /* harmony export */ ETextureFormat: () => (/* binding */ ETextureFormat), /* harmony export */ ETextureWrapMode: () => (/* binding */ ETextureWrapMode) /* harmony export */ }); /** * Enums * @internal */ var EComponentType; (function (EComponentType) { EComponentType[EComponentType["BYTE"] = 5120] = "BYTE"; EComponentType[EComponentType["UNSIGNED_BYTE"] = 5121] = "UNSIGNED_BYTE"; EComponentType[EComponentType["SHORT"] = 5122] = "SHORT"; EComponentType[EComponentType["UNSIGNED_SHORT"] = 5123] = "UNSIGNED_SHORT"; EComponentType[EComponentType["FLOAT"] = 5126] = "FLOAT"; })(EComponentType || (EComponentType = {})); /** @internal */ var EShaderType; (function (EShaderType) { EShaderType[EShaderType["FRAGMENT"] = 35632] = "FRAGMENT"; EShaderType[EShaderType["VERTEX"] = 35633] = "VERTEX"; })(EShaderType || (EShaderType = {})); /** @internal */ var EParameterType; (function (EParameterType) { EParameterType[EParameterType["BYTE"] = 5120] = "BYTE"; EParameterType[EParameterType["UNSIGNED_BYTE"] = 5121] = "UNSIGNED_BYTE"; EParameterType[EParameterType["SHORT"] = 5122] = "SHORT"; EParameterType[EParameterType["UNSIGNED_SHORT"] = 5123] = "UNSIGNED_SHORT"; EParameterType[EParameterType["INT"] = 5124] = "INT"; EParameterType[EParameterType["UNSIGNED_INT"] = 5125] = "UNSIGNED_INT"; EParameterType[EParameterType["FLOAT"] = 5126] = "FLOAT"; EParameterType[EParameterType["FLOAT_VEC2"] = 35664] = "FLOAT_VEC2"; EParameterType[EParameterType["FLOAT_VEC3"] = 35665] = "FLOAT_VEC3"; EParameterType[EParameterType["FLOAT_VEC4"] = 35666] = "FLOAT_VEC4"; EParameterType[EParameterType["INT_VEC2"] = 35667] = "INT_VEC2"; EParameterType[EParameterType["INT_VEC3"] = 35668] = "INT_VEC3"; EParameterType[EParameterType["INT_VEC4"] = 35669] = "INT_VEC4"; EParameterType[EParameterType["BOOL"] = 35670] = "BOOL"; EParameterType[EParameterType["BOOL_VEC2"] = 35671] = "BOOL_VEC2"; EParameterType[EParameterType["BOOL_VEC3"] = 35672] = "BOOL_VEC3"; EParameterType[EParameterType["BOOL_VEC4"] = 35673] = "BOOL_VEC4"; EParameterType[EParameterType["FLOAT_MAT2"] = 35674] = "FLOAT_MAT2"; EParameterType[EParameterType["FLOAT_MAT3"] = 35675] = "FLOAT_MAT3"; EParameterType[EParameterType["FLOAT_MAT4"] = 35676] = "FLOAT_MAT4"; EParameterType[EParameterType["SAMPLER_2D"] = 35678] = "SAMPLER_2D"; })(EParameterType || (EParameterType = {})); /** @internal */ var ETextureWrapMode; (function (ETextureWrapMode) { ETextureWrapMode[ETextureWrapMode["CLAMP_TO_EDGE"] = 33071] = "CLAMP_TO_EDGE"; ETextureWrapMode[ETextureWrapMode["MIRRORED_REPEAT"] = 33648] = "MIRRORED_REPEAT"; ETextureWrapMode[ETextureWrapMode["REPEAT"] = 10497] = "REPEAT"; })(ETextureWrapMode || (ETextureWrapMode = {})); /** @internal */ var ETextureFilterType; (function (ETextureFilterType) { ETextureFilterType[ETextureFilterType["NEAREST"] = 9728] = "NEAREST"; ETextureFilterType[ETextureFilterType["LINEAR"] = 9728] = "LINEAR"; ETextureFilterType[ETextureFilterType["NEAREST_MIPMAP_NEAREST"] = 9984] = "NEAREST_MIPMAP_NEAREST"; ETextureFilterType[ETextureFilterType["LINEAR_MIPMAP_NEAREST"] = 9985] = "LINEAR_MIPMAP_NEAREST"; ETextureFilterType[ETextureFilterType["NEAREST_MIPMAP_LINEAR"] = 9986] = "NEAREST_MIPMAP_LINEAR"; ETextureFilterType[ETextureFilterType["LINEAR_MIPMAP_LINEAR"] = 9987] = "LINEAR_MIPMAP_LINEAR"; })(ETextureFilterType || (ETextureFilterType = {})); /** @internal */ var ETextureFormat; (function (ETextureFormat) { ETextureFormat[ETextureFormat["ALPHA"] = 6406] = "ALPHA"; ETextureFormat[ETextureFormat["RGB"] = 6407] = "RGB"; ETextureFormat[ETextureFormat["RGBA"] = 6408] = "RGBA"; ETextureFormat[ETextureFormat["LUMINANCE"] = 6409] = "LUMINANCE"; ETextureFormat[ETextureFormat["LUMINANCE_ALPHA"] = 6410] = "LUMINANCE_ALPHA"; })(ETextureFormat || (ETextureFormat = {})); /** @internal */ var ECullingType; (function (ECullingType) { ECullingType[ECullingType["FRONT"] = 1028] = "FRONT"; ECullingType[ECullingType["BACK"] = 1029] = "BACK"; ECullingType[ECullingType["FRONT_AND_BACK"] = 1032] = "FRONT_AND_BACK"; })(ECullingType || (ECullingType = {})); /** @internal */ var EBlendingFunction; (function (EBlendingFunction) { EBlendingFunction[EBlendingFunction["ZERO"] = 0] = "ZERO"; EBlendingFunction[EBlendingFunction["ONE"] = 1] = "ONE"; EBlendingFunction[EBlendingFunction["SRC_COLOR"] = 768] = "SRC_COLOR"; EBlendingFunction[EBlendingFunction["ONE_MINUS_SRC_COLOR"] = 769] = "ONE_MINUS_SRC_COLOR"; EBlendingFunction[EBlendingFunction["DST_COLOR"] = 774] = "DST_COLOR"; EBlendingFunction[EBlendingFunction["ONE_MINUS_DST_COLOR"] = 775] = "ONE_MINUS_DST_COLOR"; EBlendingFunction[EBlendingFunction["SRC_ALPHA"] = 770] = "SRC_ALPHA"; EBlendingFunction[EBlendingFunction["ONE_MINUS_SRC_ALPHA"] = 771] = "ONE_MINUS_SRC_ALPHA"; EBlendingFunction[EBlendingFunction["DST_ALPHA"] = 772] = "DST_ALPHA"; EBlendingFunction[EBlendingFunction["ONE_MINUS_DST_ALPHA"] = 773] = "ONE_MINUS_DST_ALPHA"; EBlendingFunction[EBlendingFunction["CONSTANT_COLOR"] = 32769] = "CONSTANT_COLOR"; EBlendingFunction[EBlendingFunction["ONE_MINUS_CONSTANT_COLOR"] = 32770] = "ONE_MINUS_CONSTANT_COLOR"; EBlendingFunction[EBlendingFunction["CONSTANT_ALPHA"] = 32771] = "CONSTANT_ALPHA"; EBlendingFunction[EBlendingFunction["ONE_MINUS_CONSTANT_ALPHA"] = 32772] = "ONE_MINUS_CONSTANT_ALPHA"; EBlendingFunction[EBlendingFunction["SRC_ALPHA_SATURATE"] = 776] = "SRC_ALPHA_SATURATE"; })(EBlendingFunction || (EBlendingFunction = {})); /***/ }), /***/ "../../../dev/loaders/src/glTF/1.0/glTFLoaderUtils.ts": /*!************************************************************!*\ !*** ../../../dev/loaders/src/glTF/1.0/glTFLoaderUtils.ts ***! \************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GLTFUtils: () => (/* binding */ GLTFUtils) /* harmony export */ }); /* harmony import */ var _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./glTFLoaderInterfaces */ "../../../dev/loaders/src/glTF/1.0/glTFLoaderInterfaces.ts"); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Materials/Textures/texture */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__); /** * Utils functions for GLTF * @internal * @deprecated */ var GLTFUtils = /** @class */ (function () { function GLTFUtils() { } /** * Sets the given "parameter" matrix * @param scene the Scene object * @param source the source node where to pick the matrix * @param parameter the GLTF technique parameter * @param uniformName the name of the shader's uniform * @param shaderMaterial the shader material */ GLTFUtils.SetMatrix = function (scene, source, parameter, uniformName, shaderMaterial) { var mat = null; if (parameter.semantic === "MODEL") { mat = source.getWorldMatrix(); } else if (parameter.semantic === "PROJECTION") { mat = scene.getProjectionMatrix(); } else if (parameter.semantic === "VIEW") { mat = scene.getViewMatrix(); } else if (parameter.semantic === "MODELVIEWINVERSETRANSPOSE") { mat = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Matrix.Transpose(source.getWorldMatrix().multiply(scene.getViewMatrix()).invert()); } else if (parameter.semantic === "MODELVIEW") { mat = source.getWorldMatrix().multiply(scene.getViewMatrix()); } else if (parameter.semantic === "MODELVIEWPROJECTION") { mat = source.getWorldMatrix().multiply(scene.getTransformMatrix()); } else if (parameter.semantic === "MODELINVERSE") { mat = source.getWorldMatrix().invert(); } else if (parameter.semantic === "VIEWINVERSE") { mat = scene.getViewMatrix().invert(); } else if (parameter.semantic === "PROJECTIONINVERSE") { mat = scene.getProjectionMatrix().invert(); } else if (parameter.semantic === "MODELVIEWINVERSE") { mat = source.getWorldMatrix().multiply(scene.getViewMatrix()).invert(); } else if (parameter.semantic === "MODELVIEWPROJECTIONINVERSE") { mat = source.getWorldMatrix().multiply(scene.getTransformMatrix()).invert(); } else if (parameter.semantic === "MODELINVERSETRANSPOSE") { mat = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Matrix.Transpose(source.getWorldMatrix().invert()); } if (mat) { switch (parameter.type) { case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EParameterType.FLOAT_MAT2: shaderMaterial.setMatrix2x2(uniformName, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Matrix.GetAsMatrix2x2(mat)); break; case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EParameterType.FLOAT_MAT3: shaderMaterial.setMatrix3x3(uniformName, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Matrix.GetAsMatrix3x3(mat)); break; case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EParameterType.FLOAT_MAT4: shaderMaterial.setMatrix(uniformName, mat); break; default: break; } } }; /** * Sets the given "parameter" matrix * @param shaderMaterial the shader material * @param uniform the name of the shader's uniform * @param value the value of the uniform * @param type the uniform's type (EParameterType FLOAT, VEC2, VEC3 or VEC4) */ GLTFUtils.SetUniform = function (shaderMaterial, uniform, value, type) { switch (type) { case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EParameterType.FLOAT: shaderMaterial.setFloat(uniform, value); return true; case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EParameterType.FLOAT_VEC2: shaderMaterial.setVector2(uniform, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector2.FromArray(value)); return true; case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EParameterType.FLOAT_VEC3: shaderMaterial.setVector3(uniform, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3.FromArray(value)); return true; case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EParameterType.FLOAT_VEC4: shaderMaterial.setVector4(uniform, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector4.FromArray(value)); return true; default: return false; } }; /** * Returns the wrap mode of the texture * @param mode the mode value */ GLTFUtils.GetWrapMode = function (mode) { switch (mode) { case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.ETextureWrapMode.CLAMP_TO_EDGE: return babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Texture.CLAMP_ADDRESSMODE; case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.ETextureWrapMode.MIRRORED_REPEAT: return babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Texture.MIRROR_ADDRESSMODE; case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.ETextureWrapMode.REPEAT: return babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Texture.WRAP_ADDRESSMODE; default: return babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Texture.WRAP_ADDRESSMODE; } }; /** * Returns the byte stride giving an accessor * @param accessor the GLTF accessor objet */ GLTFUtils.GetByteStrideFromType = function (accessor) { // Needs this function since "byteStride" isn't requiered in glTF format var type = accessor.type; switch (type) { case "VEC2": return 2; case "VEC3": return 3; case "VEC4": return 4; case "MAT2": return 4; case "MAT3": return 9; case "MAT4": return 16; default: return 1; } }; /** * Returns the texture filter mode giving a mode value * @param mode the filter mode value * @returns the filter mode (TODO - needs to be a type?) */ GLTFUtils.GetTextureFilterMode = function (mode) { switch (mode) { case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.ETextureFilterType.LINEAR: case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.ETextureFilterType.LINEAR_MIPMAP_NEAREST: case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.ETextureFilterType.LINEAR_MIPMAP_LINEAR: return babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Texture.TRILINEAR_SAMPLINGMODE; case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.ETextureFilterType.NEAREST: case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.ETextureFilterType.NEAREST_MIPMAP_NEAREST: return babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Texture.NEAREST_SAMPLINGMODE; default: return babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Texture.BILINEAR_SAMPLINGMODE; } }; GLTFUtils.GetBufferFromBufferView = function (gltfRuntime, bufferView, byteOffset, byteLength, componentType) { byteOffset = bufferView.byteOffset + byteOffset; var loadedBufferView = gltfRuntime.loadedBufferViews[bufferView.buffer]; if (byteOffset + byteLength > loadedBufferView.byteLength) { throw new Error("Buffer access is out of range"); } var buffer = loadedBufferView.buffer; byteOffset += loadedBufferView.byteOffset; switch (componentType) { case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EComponentType.BYTE: return new Int8Array(buffer, byteOffset, byteLength); case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EComponentType.UNSIGNED_BYTE: return new Uint8Array(buffer, byteOffset, byteLength); case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EComponentType.SHORT: return new Int16Array(buffer, byteOffset, byteLength); case _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_0__.EComponentType.UNSIGNED_SHORT: return new Uint16Array(buffer, byteOffset, byteLength); default: return new Float32Array(buffer, byteOffset, byteLength); } }; /** * Returns a buffer from its accessor * @param gltfRuntime the GLTF runtime * @param accessor the GLTF accessor */ GLTFUtils.GetBufferFromAccessor = function (gltfRuntime, accessor) { var bufferView = gltfRuntime.bufferViews[accessor.bufferView]; var byteLength = accessor.count * GLTFUtils.GetByteStrideFromType(accessor); return GLTFUtils.GetBufferFromBufferView(gltfRuntime, bufferView, accessor.byteOffset, byteLength, accessor.componentType); }; /** * Decodes a buffer view into a string * @param view the buffer view */ GLTFUtils.DecodeBufferToText = function (view) { var result = ""; var length = view.byteLength; for (var i = 0; i < length; ++i) { result += String.fromCharCode(view[i]); } return result; }; /** * Returns the default material of gltf. Related to * https://github.com/KhronosGroup/glTF/tree/master/specification/1.0#appendix-a-default-material * @param scene the Babylon.js scene */ GLTFUtils.GetDefaultMaterial = function (scene) { if (!GLTFUtils._DefaultMaterial) { babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Effect.ShadersStore["GLTFDefaultMaterialVertexShader"] = [ "precision highp float;", "", "uniform mat4 worldView;", "uniform mat4 projection;", "", "attribute vec3 position;", "", "void main(void)", "{", " gl_Position = projection * worldView * vec4(position, 1.0);", "}", ].join("\n"); babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Effect.ShadersStore["GLTFDefaultMaterialPixelShader"] = [ "precision highp float;", "", "uniform vec4 u_emission;", "", "void main(void)", "{", " gl_FragColor = u_emission;", "}", ].join("\n"); var shaderPath = { vertex: "GLTFDefaultMaterial", fragment: "GLTFDefaultMaterial", }; var options = { attributes: ["position"], uniforms: ["worldView", "projection", "u_emission"], samplers: new Array(), needAlphaBlending: false, }; GLTFUtils._DefaultMaterial = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.ShaderMaterial("GLTFDefaultMaterial", scene, shaderPath, options); GLTFUtils._DefaultMaterial.setColor4("u_emission", new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color4(0.5, 0.5, 0.5, 1.0)); } return GLTFUtils._DefaultMaterial; }; // The GLTF default material GLTFUtils._DefaultMaterial = null; return GLTFUtils; }()); /***/ }), /***/ "../../../dev/loaders/src/glTF/1.0/glTFMaterialsCommonExtension.ts": /*!*************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/1.0/glTFMaterialsCommonExtension.ts ***! \*************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GLTFMaterialsCommonExtension: () => (/* binding */ GLTFMaterialsCommonExtension) /* harmony export */ }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! tslib */ "../../../../node_modules/tslib/tslib.es6.mjs"); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./glTFLoader */ "../../../dev/loaders/src/glTF/1.0/glTFLoader.ts"); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Lights/spotLight */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__); /** * @internal * @deprecated */ var GLTFMaterialsCommonExtension = /** @class */ (function (_super) { (0,tslib__WEBPACK_IMPORTED_MODULE_2__.__extends)(GLTFMaterialsCommonExtension, _super); function GLTFMaterialsCommonExtension() { return _super.call(this, "KHR_materials_common") || this; } GLTFMaterialsCommonExtension.prototype.loadRuntimeExtensionsAsync = function (gltfRuntime) { if (!gltfRuntime.extensions) { return false; } var extension = gltfRuntime.extensions[this.name]; if (!extension) { return false; } // Create lights var lights = extension.lights; if (lights) { for (var thing in lights) { var light = lights[thing]; switch (light.type) { case "ambient": { var ambientLight = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.HemisphericLight(light.name, new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3(0, 1, 0), gltfRuntime.scene); var ambient = light.ambient; if (ambient) { ambientLight.diffuse = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color3.FromArray(ambient.color || [1, 1, 1]); } break; } case "point": { var pointLight = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.PointLight(light.name, new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3(10, 10, 10), gltfRuntime.scene); var point = light.point; if (point) { pointLight.diffuse = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color3.FromArray(point.color || [1, 1, 1]); } break; } case "directional": { var dirLight = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.DirectionalLight(light.name, new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3(0, -1, 0), gltfRuntime.scene); var directional = light.directional; if (directional) { dirLight.diffuse = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color3.FromArray(directional.color || [1, 1, 1]); } break; } case "spot": { var spot = light.spot; if (spot) { var spotLight = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.SpotLight(light.name, new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3(0, 10, 0), new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Vector3(0, -1, 0), spot.fallOffAngle || Math.PI, spot.fallOffExponent || 0.0, gltfRuntime.scene); spotLight.diffuse = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color3.FromArray(spot.color || [1, 1, 1]); } break; } default: babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Tools.Warn('GLTF Material Common extension: light type "' + light.type + "” not supported"); break; } } } return false; }; GLTFMaterialsCommonExtension.prototype.loadMaterialAsync = function (gltfRuntime, id, onSuccess, onError) { var material = gltfRuntime.materials[id]; if (!material || !material.extensions) { return false; } var extension = material.extensions[this.name]; if (!extension) { return false; } var standardMaterial = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.StandardMaterial(id, gltfRuntime.scene); standardMaterial.sideOrientation = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Material.CounterClockWiseSideOrientation; if (extension.technique === "CONSTANT") { standardMaterial.disableLighting = true; } standardMaterial.backFaceCulling = extension.doubleSided === undefined ? false : !extension.doubleSided; standardMaterial.alpha = extension.values.transparency === undefined ? 1.0 : extension.values.transparency; standardMaterial.specularPower = extension.values.shininess === undefined ? 0.0 : extension.values.shininess; // Ambient if (typeof extension.values.ambient === "string") { this._loadTexture(gltfRuntime, extension.values.ambient, standardMaterial, "ambientTexture", onError); } else { standardMaterial.ambientColor = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color3.FromArray(extension.values.ambient || [0, 0, 0]); } // Diffuse if (typeof extension.values.diffuse === "string") { this._loadTexture(gltfRuntime, extension.values.diffuse, standardMaterial, "diffuseTexture", onError); } else { standardMaterial.diffuseColor = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color3.FromArray(extension.values.diffuse || [0, 0, 0]); } // Emission if (typeof extension.values.emission === "string") { this._loadTexture(gltfRuntime, extension.values.emission, standardMaterial, "emissiveTexture", onError); } else { standardMaterial.emissiveColor = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color3.FromArray(extension.values.emission || [0, 0, 0]); } // Specular if (typeof extension.values.specular === "string") { this._loadTexture(gltfRuntime, extension.values.specular, standardMaterial, "specularTexture", onError); } else { standardMaterial.specularColor = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_1__.Color3.FromArray(extension.values.specular || [0, 0, 0]); } return true; }; GLTFMaterialsCommonExtension.prototype._loadTexture = function (gltfRuntime, id, material, propertyPath, onError) { // Create buffer from texture url _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderBase.LoadTextureBufferAsync(gltfRuntime, id, function (buffer) { // Create texture from buffer _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderBase.CreateTextureAsync(gltfRuntime, id, buffer, function (texture) { return (material[propertyPath] = texture); }); }, onError); }; return GLTFMaterialsCommonExtension; }(_glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderExtension)); _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.RegisterExtension(new GLTFMaterialsCommonExtension()); /***/ }), /***/ "../../../dev/loaders/src/glTF/1.0/index.ts": /*!**************************************************!*\ !*** ../../../dev/loaders/src/glTF/1.0/index.ts ***! \**************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ EBlendingFunction: () => (/* reexport safe */ _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_2__.EBlendingFunction), /* harmony export */ EComponentType: () => (/* reexport safe */ _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_2__.EComponentType), /* harmony export */ ECullingType: () => (/* reexport safe */ _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_2__.ECullingType), /* harmony export */ EParameterType: () => (/* reexport safe */ _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_2__.EParameterType), /* harmony export */ EShaderType: () => (/* reexport safe */ _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_2__.EShaderType), /* harmony export */ ETextureFilterType: () => (/* reexport safe */ _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_2__.ETextureFilterType), /* harmony export */ ETextureFormat: () => (/* reexport safe */ _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_2__.ETextureFormat), /* harmony export */ ETextureWrapMode: () => (/* reexport safe */ _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_2__.ETextureWrapMode), /* harmony export */ GLTFBinaryExtension: () => (/* reexport safe */ _glTFBinaryExtension__WEBPACK_IMPORTED_MODULE_0__.GLTFBinaryExtension), /* harmony export */ GLTFLoader: () => (/* reexport safe */ _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader), /* harmony export */ GLTFLoaderBase: () => (/* reexport safe */ _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderBase), /* harmony export */ GLTFLoaderExtension: () => (/* reexport safe */ _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderExtension), /* harmony export */ GLTFMaterialsCommonExtension: () => (/* reexport safe */ _glTFMaterialsCommonExtension__WEBPACK_IMPORTED_MODULE_4__.GLTFMaterialsCommonExtension), /* harmony export */ GLTFUtils: () => (/* reexport safe */ _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_3__.GLTFUtils) /* harmony export */ }); /* harmony import */ var _glTFBinaryExtension__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./glTFBinaryExtension */ "../../../dev/loaders/src/glTF/1.0/glTFBinaryExtension.ts"); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./glTFLoader */ "../../../dev/loaders/src/glTF/1.0/glTFLoader.ts"); /* harmony import */ var _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./glTFLoaderInterfaces */ "../../../dev/loaders/src/glTF/1.0/glTFLoaderInterfaces.ts"); /* harmony import */ var _glTFLoaderUtils__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./glTFLoaderUtils */ "../../../dev/loaders/src/glTF/1.0/glTFLoaderUtils.ts"); /* harmony import */ var _glTFMaterialsCommonExtension__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./glTFMaterialsCommonExtension */ "../../../dev/loaders/src/glTF/1.0/glTFMaterialsCommonExtension.ts"); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/EXT_lights_image_based.ts": /*!******************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/EXT_lights_image_based.ts ***! \******************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ EXT_lights_image_based: () => (/* binding */ EXT_lights_image_based) /* harmony export */ }); /* harmony import */ var babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/Textures/rawCubeTexture */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "EXT_lights_image_based"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_lights_image_based/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var EXT_lights_image_based = /** @class */ (function () { /** * @internal */ function EXT_lights_image_based(loader) { /** * The name of this extension. */ this.name = NAME; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ EXT_lights_image_based.prototype.dispose = function () { this._loader = null; delete this._lights; }; /** @internal */ EXT_lights_image_based.prototype.onLoading = function () { var extensions = this._loader.gltf.extensions; if (extensions && extensions[this.name]) { var extension = extensions[this.name]; this._lights = extension.lights; } }; /** * @internal */ EXT_lights_image_based.prototype.loadSceneAsync = function (context, scene) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, scene, this.name, function (extensionContext, extension) { _this._loader._allMaterialsDirtyRequired = true; var promises = new Array(); promises.push(_this._loader.loadSceneAsync(context, scene)); _this._loader.logOpen("".concat(extensionContext)); var light = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Get("".concat(extensionContext, "/light"), _this._lights, extension.light); promises.push(_this._loadLightAsync("/extensions/".concat(_this.name, "/lights/").concat(extension.light), light).then(function (texture) { _this._loader.babylonScene.environmentTexture = texture; })); _this._loader.logClose(); return Promise.all(promises).then(function () { }); }); }; EXT_lights_image_based.prototype._loadLightAsync = function (context, light) { var _this = this; if (!light._loaded) { var promises = new Array(); this._loader.logOpen("".concat(context)); var imageData_1 = new Array(light.specularImages.length); var _loop_1 = function (mipmap) { var faces = light.specularImages[mipmap]; imageData_1[mipmap] = new Array(faces.length); var _loop_2 = function (face) { var specularImageContext = "".concat(context, "/specularImages/").concat(mipmap, "/").concat(face); this_1._loader.logOpen("".concat(specularImageContext)); var index = faces[face]; var image = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Get(specularImageContext, this_1._loader.gltf.images, index); promises.push(this_1._loader.loadImageAsync("/images/".concat(index), image).then(function (data) { imageData_1[mipmap][face] = data; })); this_1._loader.logClose(); }; for (var face = 0; face < faces.length; face++) { _loop_2(face); } }; var this_1 = this; for (var mipmap = 0; mipmap < light.specularImages.length; mipmap++) { _loop_1(mipmap); } this._loader.logClose(); light._loaded = Promise.all(promises).then(function () { var babylonTexture = new babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__.RawCubeTexture(_this._loader.babylonScene, null, light.specularImageSize); babylonTexture.name = light.name || "environment"; light._babylonTexture = babylonTexture; if (light.intensity != undefined) { babylonTexture.level = light.intensity; } if (light.rotation) { var rotation = babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__.Quaternion.FromArray(light.rotation); // Invert the rotation so that positive rotation is counter-clockwise. if (!_this._loader.babylonScene.useRightHandedSystem) { rotation = babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__.Quaternion.Inverse(rotation); } babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__.Matrix.FromQuaternionToRef(rotation, babylonTexture.getReflectionTextureMatrix()); } if (!light.irradianceCoefficients) { throw new Error("".concat(context, ": Irradiance coefficients are missing")); } var sphericalHarmonics = babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__.SphericalHarmonics.FromArray(light.irradianceCoefficients); sphericalHarmonics.scaleInPlace(light.intensity); sphericalHarmonics.convertIrradianceToLambertianRadiance(); var sphericalPolynomial = babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__.SphericalPolynomial.FromHarmonics(sphericalHarmonics); // Compute the lod generation scale to fit exactly to the number of levels available. var lodGenerationScale = (imageData_1.length - 1) / babylonjs_Maths_math_scalar__WEBPACK_IMPORTED_MODULE_0__.Scalar.Log2(light.specularImageSize); return babylonTexture.updateRGBDAsync(imageData_1, sphericalPolynomial, lodGenerationScale); }); } return light._loaded.then(function () { return light._babylonTexture; }); }; return EXT_lights_image_based; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new EXT_lights_image_based(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.ts": /*!*******************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.ts ***! \*******************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ EXT_mesh_gpu_instancing: () => (/* binding */ EXT_mesh_gpu_instancing) /* harmony export */ }); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Meshes/thinInstanceMesh */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "EXT_mesh_gpu_instancing"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_mesh_gpu_instancing/README.md) * [Playground Sample](https://playground.babylonjs.com/#QFIGLW#9) */ // eslint-disable-next-line @typescript-eslint/naming-convention var EXT_mesh_gpu_instancing = /** @class */ (function () { /** * @internal */ function EXT_mesh_gpu_instancing(loader) { /** * The name of this extension. */ this.name = NAME; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ EXT_mesh_gpu_instancing.prototype.dispose = function () { this._loader = null; }; /** * @internal */ EXT_mesh_gpu_instancing.prototype.loadNodeAsync = function (context, node, assign) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, node, this.name, function (extensionContext, extension) { _this._loader._disableInstancedMesh++; var promise = _this._loader.loadNodeAsync("/nodes/".concat(node.index), node, assign); _this._loader._disableInstancedMesh--; if (!node._primitiveBabylonMeshes) { return promise; } var promises = new Array(); var instanceCount = 0; var loadAttribute = function (attribute) { if (extension.attributes[attribute] == undefined) { promises.push(Promise.resolve(null)); return; } var accessor = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Get("".concat(extensionContext, "/attributes/").concat(attribute), _this._loader.gltf.accessors, extension.attributes[attribute]); promises.push(_this._loader._loadFloatAccessorAsync("/accessors/".concat(accessor.bufferView), accessor)); if (instanceCount === 0) { instanceCount = accessor.count; } else if (instanceCount !== accessor.count) { throw new Error("".concat(extensionContext, "/attributes: Instance buffer accessors do not have the same count.")); } }; loadAttribute("TRANSLATION"); loadAttribute("ROTATION"); loadAttribute("SCALE"); return promise.then(function (babylonTransformNode) { return Promise.all(promises).then(function (_a) { var translationBuffer = _a[0], rotationBuffer = _a[1], scaleBuffer = _a[2]; var matrices = new Float32Array(instanceCount * 16); babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.TmpVectors.Vector3[0].copyFromFloats(0, 0, 0); // translation babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.TmpVectors.Quaternion[0].copyFromFloats(0, 0, 0, 1); // rotation babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.TmpVectors.Vector3[1].copyFromFloats(1, 1, 1); // scale for (var i = 0; i < instanceCount; ++i) { translationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Vector3.FromArrayToRef(translationBuffer, i * 3, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.TmpVectors.Vector3[0]); rotationBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Quaternion.FromArrayToRef(rotationBuffer, i * 4, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.TmpVectors.Quaternion[0]); scaleBuffer && babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Vector3.FromArrayToRef(scaleBuffer, i * 3, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.TmpVectors.Vector3[1]); babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Matrix.ComposeToRef(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.TmpVectors.Vector3[1], babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.TmpVectors.Quaternion[0], babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.TmpVectors.Vector3[0], babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.TmpVectors.Matrix[0]); babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.TmpVectors.Matrix[0].copyToArray(matrices, i * 16); } for (var _i = 0, _b = node._primitiveBabylonMeshes; _i < _b.length; _i++) { var babylonMesh = _b[_i]; babylonMesh.thinInstanceSetBuffer("matrix", matrices, 16, true); } return babylonTransformNode; }); }); }); }; return EXT_mesh_gpu_instancing; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new EXT_mesh_gpu_instancing(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/EXT_meshopt_compression.ts": /*!*******************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/EXT_meshopt_compression.ts ***! \*******************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ EXT_meshopt_compression: () => (/* binding */ EXT_meshopt_compression) /* harmony export */ }); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); /* harmony import */ var babylonjs_Meshes_Compression_meshoptCompression__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/Compression/meshoptCompression */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Meshes_Compression_meshoptCompression__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_Compression_meshoptCompression__WEBPACK_IMPORTED_MODULE_1__); var NAME = "EXT_meshopt_compression"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_meshopt_compression/README.md) * * This extension uses a WebAssembly decoder module from https://github.com/zeux/meshoptimizer/tree/master/js * @since 5.0.0 */ // eslint-disable-next-line @typescript-eslint/naming-convention var EXT_meshopt_compression = /** @class */ (function () { /** * @internal */ function EXT_meshopt_compression(loader) { /** * The name of this extension. */ this.name = NAME; this.enabled = loader.isExtensionUsed(NAME); this._loader = loader; } /** @internal */ EXT_meshopt_compression.prototype.dispose = function () { this._loader = null; }; /** * @internal */ EXT_meshopt_compression.prototype.loadBufferViewAsync = function (context, bufferView) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.LoadExtensionAsync(context, bufferView, this.name, function (extensionContext, extension) { var bufferViewMeshopt = bufferView; if (bufferViewMeshopt._meshOptData) { return bufferViewMeshopt._meshOptData; } var buffer = _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.ArrayItem.Get("".concat(context, "/buffer"), _this._loader.gltf.buffers, extension.buffer); bufferViewMeshopt._meshOptData = _this._loader.loadBufferAsync("/buffers/".concat(buffer.index), buffer, extension.byteOffset || 0, extension.byteLength).then(function (buffer) { return babylonjs_Meshes_Compression_meshoptCompression__WEBPACK_IMPORTED_MODULE_1__.MeshoptCompression.Default.decodeGltfBufferAsync(buffer, extension.count, extension.byteStride, extension.mode, extension.filter); }); return bufferViewMeshopt._meshOptData; }); }; return EXT_meshopt_compression; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new EXT_meshopt_compression(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/EXT_texture_webp.ts": /*!************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/EXT_texture_webp.ts ***! \************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ EXT_texture_webp: () => (/* binding */ EXT_texture_webp) /* harmony export */ }); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "EXT_texture_webp"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/EXT_texture_webp/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var EXT_texture_webp = /** @class */ (function () { /** * @internal */ function EXT_texture_webp(loader) { /** The name of this extension. */ this.name = NAME; this._loader = loader; this.enabled = loader.isExtensionUsed(NAME); } /** @internal */ EXT_texture_webp.prototype.dispose = function () { this._loader = null; }; /** * @internal */ EXT_texture_webp.prototype._loadTextureAsync = function (context, texture, assign) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.LoadExtensionAsync(context, texture, this.name, function (extensionContext, extension) { var sampler = texture.sampler == undefined ? _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.DefaultSampler : _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.ArrayItem.Get("".concat(context, "/sampler"), _this._loader.gltf.samplers, texture.sampler); var image = _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.ArrayItem.Get("".concat(extensionContext, "/source"), _this._loader.gltf.images, extension.source); return _this._loader._createTextureAsync(context, sampler, image, function (babylonTexture) { assign(babylonTexture); }, undefined, !texture._textureInfo.nonColorData); }); }; return EXT_texture_webp; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new EXT_texture_webp(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/ExtrasAsMetadata.ts": /*!************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/ExtrasAsMetadata.ts ***! \************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ExtrasAsMetadata: () => (/* binding */ ExtrasAsMetadata) /* harmony export */ }); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "ExtrasAsMetadata"; /** * Store glTF extras (if present) in BJS objects' metadata */ var ExtrasAsMetadata = /** @class */ (function () { /** * @internal */ function ExtrasAsMetadata(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines whether this extension is enabled. */ this.enabled = true; this._loader = loader; } ExtrasAsMetadata.prototype._assignExtras = function (babylonObject, gltfProp) { if (gltfProp.extras && Object.keys(gltfProp.extras).length > 0) { var metadata = (babylonObject.metadata = babylonObject.metadata || {}); var gltf = (metadata.gltf = metadata.gltf || {}); gltf.extras = gltfProp.extras; } }; /** @internal */ ExtrasAsMetadata.prototype.dispose = function () { this._loader = null; }; /** * @internal */ ExtrasAsMetadata.prototype.loadNodeAsync = function (context, node, assign) { var _this = this; return this._loader.loadNodeAsync(context, node, function (babylonTransformNode) { _this._assignExtras(babylonTransformNode, node); assign(babylonTransformNode); }); }; /** * @internal */ ExtrasAsMetadata.prototype.loadCameraAsync = function (context, camera, assign) { var _this = this; return this._loader.loadCameraAsync(context, camera, function (babylonCamera) { _this._assignExtras(babylonCamera, camera); assign(babylonCamera); }); }; /** * @internal */ ExtrasAsMetadata.prototype.createMaterial = function (context, material, babylonDrawMode) { var babylonMaterial = this._loader.createMaterial(context, material, babylonDrawMode); this._assignExtras(babylonMaterial, material); return babylonMaterial; }; return ExtrasAsMetadata; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new ExtrasAsMetadata(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_animation_pointer.data.ts": /*!**********************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_animation_pointer.data.ts ***! \**********************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ animationPointerTree: () => (/* binding */ animationPointerTree) /* harmony export */ }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! tslib */ "../../../../node_modules/tslib/tslib.es6.mjs"); /* harmony import */ var babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.color */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoaderAnimation__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoaderAnimation */ "../../../dev/loaders/src/glTF/2.0/glTFLoaderAnimation.ts"); /* eslint-disable @typescript-eslint/naming-convention */ function getColor3(_target, source, offset, scale) { return babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(source, offset).scale(scale); } function getAlpha(_target, source, offset, scale) { return source[offset + 3] * scale; } function getFloat(_target, source, offset, scale) { return source[offset] * scale; } function getMinusFloat(_target, source, offset, scale) { return -source[offset] * scale; } function getNextFloat(_target, source, offset, scale) { return source[offset + 1] * scale; } function getFloatBy2(_target, source, offset, scale) { return source[offset] * scale * 2; } function getTextureTransformTree(textureName) { return { scale: [ new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "".concat(textureName, ".uScale"), getFloat, function () { return 2; }), new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "".concat(textureName, ".vScale"), getNextFloat, function () { return 2; }), ], offset: [ new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "".concat(textureName, ".uOffset"), getFloat, function () { return 2; }), new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "".concat(textureName, ".vOffset"), getNextFloat, function () { return 2; }), ], rotation: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "".concat(textureName, ".wAng"), getMinusFloat, function () { return 1; })], }; } var CameraAnimationPropertyInfo = /** @class */ (function (_super) { (0,tslib__WEBPACK_IMPORTED_MODULE_2__.__extends)(CameraAnimationPropertyInfo, _super); function CameraAnimationPropertyInfo() { return _super !== null && _super.apply(this, arguments) || this; } /** @internal */ CameraAnimationPropertyInfo.prototype.buildAnimations = function (target, name, fps, keys, callback) { callback(target._babylonCamera, this._buildAnimation(name, fps, keys)); }; return CameraAnimationPropertyInfo; }(_glTFLoaderAnimation__WEBPACK_IMPORTED_MODULE_1__.AnimationPropertyInfo)); var MaterialAnimationPropertyInfo = /** @class */ (function (_super) { (0,tslib__WEBPACK_IMPORTED_MODULE_2__.__extends)(MaterialAnimationPropertyInfo, _super); function MaterialAnimationPropertyInfo() { return _super !== null && _super.apply(this, arguments) || this; } /** @internal */ MaterialAnimationPropertyInfo.prototype.buildAnimations = function (target, name, fps, keys, callback) { for (var fillMode in target._data) { callback(target._data[fillMode].babylonMaterial, this._buildAnimation(name, fps, keys)); } }; return MaterialAnimationPropertyInfo; }(_glTFLoaderAnimation__WEBPACK_IMPORTED_MODULE_1__.AnimationPropertyInfo)); var LightAnimationPropertyInfo = /** @class */ (function (_super) { (0,tslib__WEBPACK_IMPORTED_MODULE_2__.__extends)(LightAnimationPropertyInfo, _super); function LightAnimationPropertyInfo() { return _super !== null && _super.apply(this, arguments) || this; } /** @internal */ LightAnimationPropertyInfo.prototype.buildAnimations = function (target, name, fps, keys, callback) { callback(target._babylonLight, this._buildAnimation(name, fps, keys)); }; return LightAnimationPropertyInfo; }(_glTFLoaderAnimation__WEBPACK_IMPORTED_MODULE_1__.AnimationPropertyInfo)); var nodesTree = { __array__: (0,tslib__WEBPACK_IMPORTED_MODULE_2__.__assign)({ __target__: true }, _glTFLoaderAnimation__WEBPACK_IMPORTED_MODULE_1__.nodeAnimationData), }; var camerasTree = { __array__: { __target__: true, orthographic: { xmag: [ new CameraAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "orthoLeft", getMinusFloat, function () { return 1; }), new CameraAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "orthoRight", getNextFloat, function () { return 1; }), ], ymag: [ new CameraAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "orthoBottom", getMinusFloat, function () { return 1; }), new CameraAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "orthoTop", getNextFloat, function () { return 1; }), ], zfar: [new CameraAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "maxZ", getFloat, function () { return 1; })], znear: [new CameraAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "minZ", getFloat, function () { return 1; })], }, perspective: { yfov: [new CameraAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "fov", getFloat, function () { return 1; })], zfar: [new CameraAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "maxZ", getFloat, function () { return 1; })], znear: [new CameraAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "minZ", getFloat, function () { return 1; })], }, }, }; var materialsTree = { __array__: { __target__: true, pbrMetallicRoughness: { baseColorFactor: [ new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_COLOR3, "albedoColor", getColor3, function () { return 4; }), new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "alpha", getAlpha, function () { return 4; }), ], metallicFactor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "metallic", getFloat, function () { return 1; })], roughnessFactor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "roughness", getFloat, function () { return 1; })], baseColorTexture: { extensions: { KHR_texture_transform: getTextureTransformTree("albedoTexture"), }, }, }, emissiveFactor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_COLOR3, "emissiveColor", getColor3, function () { return 3; })], normalTexture: { scale: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "bumpTexture.level", getFloat, function () { return 1; })], }, occlusionTexture: { strength: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "ambientTextureStrength", getFloat, function () { return 1; })], extensions: { KHR_texture_transform: getTextureTransformTree("ambientTexture"), }, }, emissiveTexture: { extensions: { KHR_texture_transform: getTextureTransformTree("emissiveTexture"), }, }, extensions: { KHR_materials_ior: { ior: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "indexOfRefraction", getFloat, function () { return 1; })], }, KHR_materials_clearcoat: { clearcoatFactor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "clearCoat.intensity", getFloat, function () { return 1; })], clearcoatRoughnessFactor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "clearCoat.roughness", getFloat, function () { return 1; })], }, KHR_materials_sheen: { sheenColorFactor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_COLOR3, "sheen.color", getColor3, function () { return 3; })], sheenRoughnessFactor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "sheen.roughness", getFloat, function () { return 1; })], }, KHR_materials_specular: { specularFactor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "metallicF0Factor", getFloat, function () { return 1; })], specularColorFactor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_COLOR3, "metallicReflectanceColor", getColor3, function () { return 3; })], }, KHR_materials_emissive_strength: { emissiveStrength: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "emissiveIntensity", getFloat, function () { return 1; })], }, KHR_materials_transmission: { transmissionFactor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "subSurface.refractionIntensity", getFloat, function () { return 1; })], }, KHR_materials_volume: { attenuationColor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_COLOR3, "subSurface.tintColor", getColor3, function () { return 3; })], attenuationDistance: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "subSurface.tintColorAtDistance", getFloat, function () { return 1; })], thicknessFactor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "subSurface.maximumThickness", getFloat, function () { return 1; })], }, KHR_materials_iridescence: { iridescenceFactor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "iridescence.intensity", getFloat, function () { return 1; })], iridescenceIor: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "iridescence.indexOfRefraction", getFloat, function () { return 1; })], iridescenceThicknessMinimum: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "iridescence.minimumThickness", getFloat, function () { return 1; })], iridescenceThicknessMaximum: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "iridescence.maximumThickness", getFloat, function () { return 1; })], }, KHR_materials_anisotropy: { anisotropyStrength: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "anisotropy.intensity", getFloat, function () { return 1; })], anisotropyRotation: [new MaterialAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "anisotropy.angle", getFloat, function () { return 1; })], }, }, }, }; var extensionsTree = { KHR_lights_punctual: { lights: { __array__: { __target__: true, color: [new LightAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_COLOR3, "diffuse", getColor3, function () { return 3; })], intensity: [new LightAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "intensity", getFloat, function () { return 1; })], range: [new LightAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "range", getFloat, function () { return 1; })], spot: { innerConeAngle: [new LightAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "innerAngle", getFloatBy2, function () { return 1; })], outerConeAngle: [new LightAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "angle", getFloatBy2, function () { return 1; })], }, }, }, }, }; /** @internal */ var animationPointerTree = { nodes: nodesTree, materials: materialsTree, cameras: camerasTree, extensions: extensionsTree, }; /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_animation_pointer.ts": /*!*****************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_animation_pointer.ts ***! \*****************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_animation_pointer: () => (/* binding */ KHR_animation_pointer) /* harmony export */ }); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); /* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Misc/logger */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _KHR_animation_pointer_data__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./KHR_animation_pointer.data */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_animation_pointer.data.ts"); var NAME = "KHR_animation_pointer"; /** * [Specification PR](https://github.com/KhronosGroup/glTF/pull/2147) * !!! Experimental Extension Subject to Changes !!! */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_animation_pointer = /** @class */ (function () { /** * @internal */ function KHR_animation_pointer(loader) { /** * The name of this extension. */ this.name = NAME; this._loader = loader; } Object.defineProperty(KHR_animation_pointer.prototype, "enabled", { /** * Defines whether this extension is enabled. */ get: function () { return this._loader.isExtensionUsed(NAME); }, enumerable: false, configurable: true }); /** @internal */ KHR_animation_pointer.prototype.dispose = function () { this._loader = null; }; /** * Loads a glTF animation channel. * @param context The context when loading the asset * @param animationContext The context of the animation when loading the asset * @param animation The glTF animation property * @param channel The glTF animation channel property * @param onLoad Called for each animation loaded * @returns A void promise that resolves when the load is complete or null if not handled */ KHR_animation_pointer.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, onLoad) { var _a; var extension = (_a = channel.target.extensions) === null || _a === void 0 ? void 0 : _a.KHR_animation_pointer; if (!extension) { return null; } if (channel.target.path !== "pointer" /* AnimationChannelTargetPath.POINTER */) { babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Warn("".concat(context, "/target/path: Value (").concat(channel.target.path, ") must be (").concat("pointer" /* AnimationChannelTargetPath.POINTER */, ") when using the ").concat(this.name, " extension")); } if (channel.target.node != undefined) { babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Warn("".concat(context, "/target/node: Value (").concat(channel.target.node, ") must not be present when using the ").concat(this.name, " extension")); } var extensionContext = "".concat(context, "/extensions/").concat(this.name); var pointer = extension.pointer; if (!pointer) { throw new Error("".concat(extensionContext, ": Pointer is missing")); } var targetInfo = this._parseAnimationPointer("".concat(extensionContext, "/pointer"), pointer); if (!targetInfo) { babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Warn("".concat(extensionContext, "/pointer: Invalid pointer (").concat(pointer, ") skipped")); return null; } return this._loader._loadAnimationChannelFromTargetInfoAsync(context, animationContext, animation, channel, targetInfo, onLoad); }; /** * The pointer string is represented by a [JSON pointer](https://datatracker.ietf.org/doc/html/rfc6901). * := /// * := "nodes" | "materials" | "meshes" | "cameras" | "extensions" * := | * := | * := "extensions"// * := | / * := W+ * := D+ * * Examples: * - "/nodes/0/rotation" * - "/materials/2/emissiveFactor" * - "/materials/2/pbrMetallicRoughness/baseColorFactor" * - "/materials/2/extensions/KHR_materials_emissive_strength/emissiveStrength" */ KHR_animation_pointer.prototype._parseAnimationPointer = function (context, pointer) { if (!pointer.startsWith("/")) { babylonjs_Misc_logger__WEBPACK_IMPORTED_MODULE_1__.Logger.Warn("".concat(context, ": Value (").concat(pointer, ") must start with a slash")); return null; } var parts = pointer.split("/"); // Remove the first part since it will be empty string as pointers must start with a slash. parts.shift(); var node = _KHR_animation_pointer_data__WEBPACK_IMPORTED_MODULE_2__.animationPointerTree; var gltfCurrentNode = this._loader.gltf; var gltfTargetNode = undefined; for (var _i = 0, parts_1 = parts; _i < parts_1.length; _i++) { var part = parts_1[_i]; if (node.__array__) { node = node.__array__; } else { node = node[part]; if (!node) { return null; } } gltfCurrentNode = gltfCurrentNode && gltfCurrentNode[part]; if (node.__target__) { gltfTargetNode = gltfCurrentNode; } } if (!gltfTargetNode || !Array.isArray(node)) { return null; } return { target: gltfTargetNode, properties: node, }; }; return KHR_animation_pointer; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_animation_pointer(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts": /*!**********************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts ***! \**********************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_draco_mesh_compression: () => (/* binding */ KHR_draco_mesh_compression) /* harmony export */ }); /* harmony import */ var babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Buffers/buffer */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_draco_mesh_compression"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_draco_mesh_compression/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_draco_mesh_compression = /** @class */ (function () { /** * @internal */ function KHR_draco_mesh_compression(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines whether to use the normalized flag from the glTF accessor instead of the Draco data. Defaults to true. */ this.useNormalizedFlagFromAccessor = true; this._loader = loader; this.enabled = babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.DracoCompression.DecoderAvailable && this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_draco_mesh_compression.prototype.dispose = function () { delete this.dracoCompression; this._loader = null; }; /** * @internal */ KHR_draco_mesh_compression.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, primitive, this.name, function (extensionContext, extension) { if (primitive.mode != undefined) { if (primitive.mode !== 5 /* MeshPrimitiveMode.TRIANGLE_STRIP */ && primitive.mode !== 4 /* MeshPrimitiveMode.TRIANGLES */) { throw new Error("".concat(context, ": Unsupported mode ").concat(primitive.mode)); } // TODO: handle triangle strips if (primitive.mode === 5 /* MeshPrimitiveMode.TRIANGLE_STRIP */) { throw new Error("".concat(context, ": Mode ").concat(primitive.mode, " is not currently supported")); } } var attributes = {}; var normalized = {}; var loadAttribute = function (name, kind) { var uniqueId = extension.attributes[name]; if (uniqueId == undefined) { return; } babylonMesh._delayInfo = babylonMesh._delayInfo || []; if (babylonMesh._delayInfo.indexOf(kind) === -1) { babylonMesh._delayInfo.push(kind); } attributes[kind] = uniqueId; if (_this.useNormalizedFlagFromAccessor) { var accessor = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.TryGet(_this._loader.gltf.accessors, primitive.attributes[name]); if (accessor) { normalized[kind] = accessor.normalized || false; } } }; loadAttribute("POSITION", babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.PositionKind); loadAttribute("NORMAL", babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.NormalKind); loadAttribute("TANGENT", babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.TangentKind); loadAttribute("TEXCOORD_0", babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.UVKind); loadAttribute("TEXCOORD_1", babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.UV2Kind); loadAttribute("TEXCOORD_2", babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.UV3Kind); loadAttribute("TEXCOORD_3", babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.UV4Kind); loadAttribute("TEXCOORD_4", babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.UV5Kind); loadAttribute("TEXCOORD_5", babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.UV6Kind); loadAttribute("JOINTS_0", babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.MatricesIndicesKind); loadAttribute("WEIGHTS_0", babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.MatricesWeightsKind); loadAttribute("COLOR_0", babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.ColorKind); var bufferView = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Get(extensionContext, _this._loader.gltf.bufferViews, extension.bufferView); if (!bufferView._dracoBabylonGeometry) { bufferView._dracoBabylonGeometry = _this._loader.loadBufferViewAsync("/bufferViews/".concat(bufferView.index), bufferView).then(function (data) { var dracoCompression = _this.dracoCompression || babylonjs_Meshes_Compression_dracoCompression__WEBPACK_IMPORTED_MODULE_0__.DracoCompression.Default; return dracoCompression._decodeMeshToGeometryForGltfAsync(babylonMesh.name, _this._loader.babylonScene, data, attributes, normalized).catch(function (error) { throw new Error("".concat(context, ": ").concat(error.message)); }); }); } return bufferView._dracoBabylonGeometry; }); }; return KHR_draco_mesh_compression; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_draco_mesh_compression(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_lights_punctual.ts": /*!***************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_lights_punctual.ts ***! \***************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_lights: () => (/* binding */ KHR_lights) /* harmony export */ }); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Lights/light */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_lights_punctual"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_lights_punctual/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_lights = /** @class */ (function () { /** * @internal */ function KHR_lights(loader) { /** * The name of this extension. */ this.name = NAME; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_lights.prototype.dispose = function () { this._loader = null; delete this._lights; }; /** @internal */ KHR_lights.prototype.onLoading = function () { var extensions = this._loader.gltf.extensions; if (extensions && extensions[this.name]) { var extension = extensions[this.name]; this._lights = extension.lights; _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Assign(this._lights); } }; /** * @internal */ KHR_lights.prototype.loadNodeAsync = function (context, node, assign) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, node, this.name, function (extensionContext, extension) { _this._loader._allMaterialsDirtyRequired = true; return _this._loader.loadNodeAsync(context, node, function (babylonMesh) { var babylonLight; var light = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Get(extensionContext, _this._lights, extension.light); var name = light.name || babylonMesh.name; _this._loader.babylonScene._blockEntityCollection = !!_this._loader._assetContainer; switch (light.type) { case "directional" /* KHRLightsPunctual_LightType.DIRECTIONAL */: { var babylonDirectionalLight = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.DirectionalLight(name, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Vector3.Backward(), _this._loader.babylonScene); babylonDirectionalLight.position.setAll(0); babylonLight = babylonDirectionalLight; break; } case "point" /* KHRLightsPunctual_LightType.POINT */: { babylonLight = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.PointLight(name, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero(), _this._loader.babylonScene); break; } case "spot" /* KHRLightsPunctual_LightType.SPOT */: { var babylonSpotLight = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.SpotLight(name, babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero(), babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Vector3.Backward(), 0, 1, _this._loader.babylonScene); babylonSpotLight.angle = ((light.spot && light.spot.outerConeAngle) || Math.PI / 4) * 2; babylonSpotLight.innerAngle = ((light.spot && light.spot.innerConeAngle) || 0) * 2; babylonLight = babylonSpotLight; break; } default: { _this._loader.babylonScene._blockEntityCollection = false; throw new Error("".concat(extensionContext, ": Invalid light type (").concat(light.type, ")")); } } babylonLight._parentContainer = _this._loader._assetContainer; _this._loader.babylonScene._blockEntityCollection = false; light._babylonLight = babylonLight; babylonLight.falloffType = babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Light.FALLOFF_GLTF; babylonLight.diffuse = light.color ? babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(light.color) : babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Color3.White(); babylonLight.intensity = light.intensity == undefined ? 1 : light.intensity; babylonLight.range = light.range == undefined ? Number.MAX_VALUE : light.range; babylonLight.parent = babylonMesh; _this._loader._babylonLights.push(babylonLight); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.AddPointerMetadata(babylonLight, extensionContext); assign(babylonMesh); }); }); }; return KHR_lights; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_lights(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts": /*!********************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts ***! \********************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_materials_anisotropy: () => (/* binding */ KHR_materials_anisotropy) /* harmony export */ }); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/PBR/pbrMaterial */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_materials_anisotropy"; /** * [Specification](https://github.com/KhronosGroup/glTF/tree/main/extensions/2.0/Khronos/KHR_materials_anisotropy) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_materials_anisotropy = /** @class */ (function () { /** * @internal */ function KHR_materials_anisotropy(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 195; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_materials_anisotropy.prototype.dispose = function () { this._loader = null; }; /** * @internal */ KHR_materials_anisotropy.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, material, this.name, function (extensionContext, extension) { var promises = new Array(); promises.push(_this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(_this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial)); return Promise.all(promises).then(function () { }); }); }; KHR_materials_anisotropy.prototype._loadIridescencePropertiesAsync = function (context, properties, babylonMaterial) { var _a, _b; if (!(babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } var promises = new Array(); babylonMaterial.anisotropy.isEnabled = true; babylonMaterial.anisotropy.intensity = (_a = properties.anisotropyStrength) !== null && _a !== void 0 ? _a : 0; babylonMaterial.anisotropy.angle = (_b = properties.anisotropyRotation) !== null && _b !== void 0 ? _b : 0; if (properties.anisotropyTexture) { promises.push(this._loader.loadTextureInfoAsync("".concat(context, "/anisotropyTexture"), properties.anisotropyTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Anisotropy Intensity)"); babylonMaterial.anisotropy.texture = texture; })); } return Promise.all(promises).then(function () { }); }; return KHR_materials_anisotropy; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_materials_anisotropy(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts": /*!*******************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts ***! \*******************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_materials_clearcoat: () => (/* binding */ KHR_materials_clearcoat) /* harmony export */ }); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/PBR/pbrMaterial */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_materials_clearcoat"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_clearcoat/README.md) * [Playground Sample](https://www.babylonjs-playground.com/frame.html#7F7PN6#8) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_materials_clearcoat = /** @class */ (function () { /** * @internal */ function KHR_materials_clearcoat(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 190; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_materials_clearcoat.prototype.dispose = function () { this._loader = null; }; /** * @internal */ KHR_materials_clearcoat.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, material, this.name, function (extensionContext, extension) { var promises = new Array(); promises.push(_this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(_this._loadClearCoatPropertiesAsync(extensionContext, extension, babylonMaterial)); return Promise.all(promises).then(function () { }); }); }; KHR_materials_clearcoat.prototype._loadClearCoatPropertiesAsync = function (context, properties, babylonMaterial) { if (!(babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } var promises = new Array(); babylonMaterial.clearCoat.isEnabled = true; babylonMaterial.clearCoat.useRoughnessFromMainTexture = false; babylonMaterial.clearCoat.remapF0OnInterfaceChange = false; if (properties.clearcoatFactor != undefined) { babylonMaterial.clearCoat.intensity = properties.clearcoatFactor; } else { babylonMaterial.clearCoat.intensity = 0; } if (properties.clearcoatTexture) { promises.push(this._loader.loadTextureInfoAsync("".concat(context, "/clearcoatTexture"), properties.clearcoatTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (ClearCoat Intensity)"); babylonMaterial.clearCoat.texture = texture; })); } if (properties.clearcoatRoughnessFactor != undefined) { babylonMaterial.clearCoat.roughness = properties.clearcoatRoughnessFactor; } else { babylonMaterial.clearCoat.roughness = 0; } if (properties.clearcoatRoughnessTexture) { properties.clearcoatRoughnessTexture.nonColorData = true; promises.push(this._loader.loadTextureInfoAsync("".concat(context, "/clearcoatRoughnessTexture"), properties.clearcoatRoughnessTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (ClearCoat Roughness)"); babylonMaterial.clearCoat.textureRoughness = texture; })); } if (properties.clearcoatNormalTexture) { properties.clearcoatNormalTexture.nonColorData = true; promises.push(this._loader.loadTextureInfoAsync("".concat(context, "/clearcoatNormalTexture"), properties.clearcoatNormalTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (ClearCoat Normal)"); babylonMaterial.clearCoat.bumpTexture = texture; })); babylonMaterial.invertNormalMapX = !babylonMaterial.getScene().useRightHandedSystem; babylonMaterial.invertNormalMapY = babylonMaterial.getScene().useRightHandedSystem; if (properties.clearcoatNormalTexture.scale != undefined) { babylonMaterial.clearCoat.bumpTexture.level = properties.clearcoatNormalTexture.scale; } } return Promise.all(promises).then(function () { }); }; return KHR_materials_clearcoat; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_materials_clearcoat(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts": /*!***************************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts ***! \***************************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_materials_emissive_strength: () => (/* binding */ KHR_materials_emissive_strength) /* harmony export */ }); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/PBR/pbrMaterial */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_materials_emissive_strength"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_emissive_strength/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_materials_emissive_strength = /** @class */ (function () { /** * @internal */ function KHR_materials_emissive_strength(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 170; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_materials_emissive_strength.prototype.dispose = function () { this._loader = null; }; /** * @internal */ KHR_materials_emissive_strength.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, material, this.name, function (extensionContext, extension) { return _this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial).then(function () { _this._loadEmissiveProperties(extensionContext, extension, babylonMaterial); }); }); }; KHR_materials_emissive_strength.prototype._loadEmissiveProperties = function (context, properties, babylonMaterial) { if (!(babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } if (properties.emissiveStrength !== undefined) { babylonMaterial.emissiveColor.scaleToRef(properties.emissiveStrength, babylonMaterial.emissiveColor); } }; return KHR_materials_emissive_strength; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_materials_emissive_strength(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts": /*!*************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts ***! \*************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_materials_ior: () => (/* binding */ KHR_materials_ior) /* harmony export */ }); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/PBR/pbrMaterial */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_materials_ior"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_ior/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_materials_ior = /** @class */ (function () { /** * @internal */ function KHR_materials_ior(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 180; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_materials_ior.prototype.dispose = function () { this._loader = null; }; /** * @internal */ KHR_materials_ior.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, material, this.name, function (extensionContext, extension) { var promises = new Array(); promises.push(_this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(_this._loadIorPropertiesAsync(extensionContext, extension, babylonMaterial)); return Promise.all(promises).then(function () { }); }); }; KHR_materials_ior.prototype._loadIorPropertiesAsync = function (context, properties, babylonMaterial) { if (!(babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } if (properties.ior !== undefined) { babylonMaterial.indexOfRefraction = properties.ior; } else { babylonMaterial.indexOfRefraction = KHR_materials_ior._DEFAULT_IOR; } return Promise.resolve(); }; /** * Default ior Value from the spec. */ KHR_materials_ior._DEFAULT_IOR = 1.5; return KHR_materials_ior; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_materials_ior(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts": /*!*********************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts ***! \*********************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_materials_iridescence: () => (/* binding */ KHR_materials_iridescence) /* harmony export */ }); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/PBR/pbrMaterial */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_materials_iridescence"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_iridescence/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_materials_iridescence = /** @class */ (function () { /** * @internal */ function KHR_materials_iridescence(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 195; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_materials_iridescence.prototype.dispose = function () { this._loader = null; }; /** * @internal */ KHR_materials_iridescence.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, material, this.name, function (extensionContext, extension) { var promises = new Array(); promises.push(_this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(_this._loadIridescencePropertiesAsync(extensionContext, extension, babylonMaterial)); return Promise.all(promises).then(function () { }); }); }; KHR_materials_iridescence.prototype._loadIridescencePropertiesAsync = function (context, properties, babylonMaterial) { var _a, _b, _c, _d, _e; if (!(babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } var promises = new Array(); babylonMaterial.iridescence.isEnabled = true; babylonMaterial.iridescence.intensity = (_a = properties.iridescenceFactor) !== null && _a !== void 0 ? _a : 0; babylonMaterial.iridescence.indexOfRefraction = (_c = (_b = properties.iridescenceIor) !== null && _b !== void 0 ? _b : properties.iridescenceIOR) !== null && _c !== void 0 ? _c : 1.3; babylonMaterial.iridescence.minimumThickness = (_d = properties.iridescenceThicknessMinimum) !== null && _d !== void 0 ? _d : 100; babylonMaterial.iridescence.maximumThickness = (_e = properties.iridescenceThicknessMaximum) !== null && _e !== void 0 ? _e : 400; if (properties.iridescenceTexture) { promises.push(this._loader.loadTextureInfoAsync("".concat(context, "/iridescenceTexture"), properties.iridescenceTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Iridescence Intensity)"); babylonMaterial.iridescence.texture = texture; })); } if (properties.iridescenceThicknessTexture) { promises.push(this._loader.loadTextureInfoAsync("".concat(context, "/iridescenceThicknessTexture"), properties.iridescenceThicknessTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Iridescence Thickness)"); babylonMaterial.iridescence.thicknessTexture = texture; })); } return Promise.all(promises).then(function () { }); }; return KHR_materials_iridescence; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_materials_iridescence(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts": /*!*******************************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts ***! \*******************************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_materials_pbrSpecularGlossiness: () => (/* binding */ KHR_materials_pbrSpecularGlossiness) /* harmony export */ }); /* harmony import */ var babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/PBR/pbrMaterial */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_materials_pbrSpecularGlossiness"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Archived/KHR_materials_pbrSpecularGlossiness/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_materials_pbrSpecularGlossiness = /** @class */ (function () { /** * @internal */ function KHR_materials_pbrSpecularGlossiness(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 200; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_materials_pbrSpecularGlossiness.prototype.dispose = function () { this._loader = null; }; /** * @internal */ KHR_materials_pbrSpecularGlossiness.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, material, this.name, function (extensionContext, extension) { var promises = new Array(); promises.push(_this._loader.loadMaterialBasePropertiesAsync(context, material, babylonMaterial)); promises.push(_this._loadSpecularGlossinessPropertiesAsync(extensionContext, material, extension, babylonMaterial)); _this._loader.loadMaterialAlphaProperties(context, material, babylonMaterial); return Promise.all(promises).then(function () { }); }); }; KHR_materials_pbrSpecularGlossiness.prototype._loadSpecularGlossinessPropertiesAsync = function (context, material, properties, babylonMaterial) { if (!(babylonMaterial instanceof babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } var promises = new Array(); babylonMaterial.metallic = null; babylonMaterial.roughness = null; if (properties.diffuseFactor) { babylonMaterial.albedoColor = babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(properties.diffuseFactor); babylonMaterial.alpha = properties.diffuseFactor[3]; } else { babylonMaterial.albedoColor = babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.White(); } babylonMaterial.reflectivityColor = properties.specularFactor ? babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(properties.specularFactor) : babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.White(); babylonMaterial.microSurface = properties.glossinessFactor == undefined ? 1 : properties.glossinessFactor; if (properties.diffuseTexture) { promises.push(this._loader.loadTextureInfoAsync("".concat(context, "/diffuseTexture"), properties.diffuseTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Diffuse)"); babylonMaterial.albedoTexture = texture; })); } if (properties.specularGlossinessTexture) { promises.push(this._loader.loadTextureInfoAsync("".concat(context, "/specularGlossinessTexture"), properties.specularGlossinessTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Specular Glossiness)"); babylonMaterial.reflectivityTexture = texture; babylonMaterial.reflectivityTexture.hasAlpha = true; })); babylonMaterial.useMicroSurfaceFromReflectivityMapAlpha = true; } return Promise.all(promises).then(function () { }); }; return KHR_materials_pbrSpecularGlossiness; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_materials_pbrSpecularGlossiness(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts": /*!***************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts ***! \***************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_materials_sheen: () => (/* binding */ KHR_materials_sheen) /* harmony export */ }); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.color */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_materials_sheen"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_sheen/README.md) * [Playground Sample](https://www.babylonjs-playground.com/frame.html#BNIZX6#4) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_materials_sheen = /** @class */ (function () { /** * @internal */ function KHR_materials_sheen(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 190; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_materials_sheen.prototype.dispose = function () { this._loader = null; }; /** * @internal */ KHR_materials_sheen.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, material, this.name, function (extensionContext, extension) { var promises = new Array(); promises.push(_this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(_this._loadSheenPropertiesAsync(extensionContext, extension, babylonMaterial)); return Promise.all(promises).then(function () { }); }); }; KHR_materials_sheen.prototype._loadSheenPropertiesAsync = function (context, properties, babylonMaterial) { if (!(babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } var promises = new Array(); babylonMaterial.sheen.isEnabled = true; babylonMaterial.sheen.intensity = 1; if (properties.sheenColorFactor != undefined) { babylonMaterial.sheen.color = babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(properties.sheenColorFactor); } else { babylonMaterial.sheen.color = babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.Color3.Black(); } if (properties.sheenColorTexture) { promises.push(this._loader.loadTextureInfoAsync("".concat(context, "/sheenColorTexture"), properties.sheenColorTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Sheen Color)"); babylonMaterial.sheen.texture = texture; })); } if (properties.sheenRoughnessFactor !== undefined) { babylonMaterial.sheen.roughness = properties.sheenRoughnessFactor; } else { babylonMaterial.sheen.roughness = 0; } if (properties.sheenRoughnessTexture) { properties.sheenRoughnessTexture.nonColorData = true; promises.push(this._loader.loadTextureInfoAsync("".concat(context, "/sheenRoughnessTexture"), properties.sheenRoughnessTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Sheen Roughness)"); babylonMaterial.sheen.textureRoughness = texture; })); } babylonMaterial.sheen.albedoScaling = true; babylonMaterial.sheen.useRoughnessFromMainTexture = false; return Promise.all(promises).then(function () { }); }; return KHR_materials_sheen; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_materials_sheen(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts": /*!******************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts ***! \******************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_materials_specular: () => (/* binding */ KHR_materials_specular) /* harmony export */ }); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.color */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_materials_specular"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_specular/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_materials_specular = /** @class */ (function () { /** * @internal */ function KHR_materials_specular(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 190; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_materials_specular.prototype.dispose = function () { this._loader = null; }; /** * @internal */ KHR_materials_specular.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, material, this.name, function (extensionContext, extension) { var promises = new Array(); promises.push(_this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(_this._loadSpecularPropertiesAsync(extensionContext, extension, babylonMaterial)); return Promise.all(promises).then(function () { }); }); }; KHR_materials_specular.prototype._loadSpecularPropertiesAsync = function (context, properties, babylonMaterial) { if (!(babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } var promises = new Array(); if (properties.specularFactor !== undefined) { babylonMaterial.metallicF0Factor = properties.specularFactor; } if (properties.specularColorFactor !== undefined) { babylonMaterial.metallicReflectanceColor = babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(properties.specularColorFactor); } if (properties.specularTexture) { properties.specularTexture.nonColorData = true; promises.push(this._loader.loadTextureInfoAsync("".concat(context, "/specularTexture"), properties.specularTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Specular F0 Strength)"); babylonMaterial.metallicReflectanceTexture = texture; babylonMaterial.useOnlyMetallicFromMetallicReflectanceTexture = true; })); } if (properties.specularColorTexture) { promises.push(this._loader.loadTextureInfoAsync("".concat(context, "/specularColorTexture"), properties.specularColorTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Specular F0 Color)"); babylonMaterial.reflectanceTexture = texture; })); } return Promise.all(promises).then(function () { }); }; return KHR_materials_specular; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_materials_specular(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_translucency.ts": /*!**********************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_translucency.ts ***! \**********************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_materials_translucency: () => (/* binding */ KHR_materials_translucency) /* harmony export */ }); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/PBR/pbrMaterial */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_materials_translucency"; /** * [Proposed Specification](https://github.com/KhronosGroup/glTF/pull/1825) * !!! Experimental Extension Subject to Changes !!! */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_materials_translucency = /** @class */ (function () { /** * @internal */ function KHR_materials_translucency(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 174; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); if (this.enabled) { loader.parent.transparencyAsCoverage = true; } } /** @internal */ KHR_materials_translucency.prototype.dispose = function () { this._loader = null; }; /** * @internal */ KHR_materials_translucency.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, material, this.name, function (extensionContext, extension) { var promises = new Array(); promises.push(_this._loader.loadMaterialBasePropertiesAsync(context, material, babylonMaterial)); promises.push(_this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(_this._loadTranslucentPropertiesAsync(extensionContext, material, babylonMaterial, extension)); return Promise.all(promises).then(function () { }); }); }; KHR_materials_translucency.prototype._loadTranslucentPropertiesAsync = function (context, material, babylonMaterial, extension) { if (!(babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } var pbrMaterial = babylonMaterial; // Enables "translucency" texture which represents diffusely-transmitted light. pbrMaterial.subSurface.isTranslucencyEnabled = true; // Since this extension models thin-surface transmission only, we must make the // internal IOR == 1.0 and set the thickness to 0. pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; pbrMaterial.subSurface.minimumThickness = 0.0; pbrMaterial.subSurface.maximumThickness = 0.0; // Albedo colour will tint transmission. pbrMaterial.subSurface.useAlbedoToTintTranslucency = true; if (extension.translucencyFactor !== undefined) { pbrMaterial.subSurface.translucencyIntensity = extension.translucencyFactor; } else { pbrMaterial.subSurface.translucencyIntensity = 0.0; pbrMaterial.subSurface.isTranslucencyEnabled = false; return Promise.resolve(); } if (extension.translucencyTexture) { extension.translucencyTexture.nonColorData = true; return this._loader.loadTextureInfoAsync("".concat(context, "/translucencyTexture"), extension.translucencyTexture).then(function (texture) { pbrMaterial.subSurface.translucencyIntensityTexture = texture; }); } else { return Promise.resolve(); } }; return KHR_materials_translucency; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_materials_translucency(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts": /*!**********************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts ***! \**********************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_materials_transmission: () => (/* binding */ KHR_materials_transmission) /* harmony export */ }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! tslib */ "../../../../node_modules/tslib/tslib.es6.mjs"); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); /** * A class to handle setting up the rendering of opaque objects to be shown through transmissive objects. */ var TransmissionHelper = /** @class */ (function () { /** * constructor * @param options Defines the options we want to customize the helper * @param scene The scene to add the material to */ function TransmissionHelper(options, scene) { var _this = this; this._opaqueRenderTarget = null; this._opaqueMeshesCache = []; this._transparentMeshesCache = []; this._materialObservers = {}; this._options = (0,tslib__WEBPACK_IMPORTED_MODULE_2__.__assign)((0,tslib__WEBPACK_IMPORTED_MODULE_2__.__assign)({}, TransmissionHelper._GetDefaultOptions()), options); this._scene = scene; this._scene._transmissionHelper = this; this.onErrorObservable = new babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.Observable(); this._scene.onDisposeObservable.addOnce(function () { _this.dispose(); }); this._parseScene(); this._setupRenderTargets(); } /** * Creates the default options for the helper. */ TransmissionHelper._GetDefaultOptions = function () { return { renderSize: 1024, samples: 4, lodGenerationScale: 1, lodGenerationOffset: -4, renderTargetTextureType: babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.Constants.TEXTURETYPE_HALF_FLOAT, generateMipmaps: true, }; }; /** * Updates the background according to the new options * @param options */ TransmissionHelper.prototype.updateOptions = function (options) { var _this = this; // First check if any options are actually being changed. If not, exit. var newValues = Object.keys(options).filter(function (key) { return _this._options[key] !== options[key]; }); if (!newValues.length) { return; } var newOptions = (0,tslib__WEBPACK_IMPORTED_MODULE_2__.__assign)((0,tslib__WEBPACK_IMPORTED_MODULE_2__.__assign)({}, this._options), options); var oldOptions = this._options; this._options = newOptions; // If size changes, recreate everything if (newOptions.renderSize !== oldOptions.renderSize || newOptions.renderTargetTextureType !== oldOptions.renderTargetTextureType || newOptions.generateMipmaps !== oldOptions.generateMipmaps || !this._opaqueRenderTarget) { this._setupRenderTargets(); } else { this._opaqueRenderTarget.samples = newOptions.samples; this._opaqueRenderTarget.lodGenerationScale = newOptions.lodGenerationScale; this._opaqueRenderTarget.lodGenerationOffset = newOptions.lodGenerationOffset; } }; /** * Gets the opaque render target texture or null if not available. */ TransmissionHelper.prototype.getOpaqueTarget = function () { return this._opaqueRenderTarget; }; TransmissionHelper.prototype._shouldRenderAsTransmission = function (material) { if (!material) { return false; } if (material instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial && material.subSurface.isRefractionEnabled) { return true; } return false; }; TransmissionHelper.prototype._addMesh = function (mesh) { var _this = this; this._materialObservers[mesh.uniqueId] = mesh.onMaterialChangedObservable.add(this._onMeshMaterialChanged.bind(this)); // we need to defer the processing because _addMesh may be called as part as an instance mesh creation, in which case some // internal properties are not setup yet, like _sourceMesh (needed when doing mesh.material below) babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.Tools.SetImmediate(function () { if (_this._shouldRenderAsTransmission(mesh.material)) { mesh.material.refractionTexture = _this._opaqueRenderTarget; if (_this._transparentMeshesCache.indexOf(mesh) === -1) { _this._transparentMeshesCache.push(mesh); } } else { if (_this._opaqueMeshesCache.indexOf(mesh) === -1) { _this._opaqueMeshesCache.push(mesh); } } }); }; TransmissionHelper.prototype._removeMesh = function (mesh) { mesh.onMaterialChangedObservable.remove(this._materialObservers[mesh.uniqueId]); delete this._materialObservers[mesh.uniqueId]; var idx = this._transparentMeshesCache.indexOf(mesh); if (idx !== -1) { this._transparentMeshesCache.splice(idx, 1); } idx = this._opaqueMeshesCache.indexOf(mesh); if (idx !== -1) { this._opaqueMeshesCache.splice(idx, 1); } }; TransmissionHelper.prototype._parseScene = function () { this._scene.meshes.forEach(this._addMesh.bind(this)); // Listen for when a mesh is added to the scene and add it to our cache lists. this._scene.onNewMeshAddedObservable.add(this._addMesh.bind(this)); // Listen for when a mesh is removed from to the scene and remove it from our cache lists. this._scene.onMeshRemovedObservable.add(this._removeMesh.bind(this)); }; // When one of the meshes in the scene has its material changed, make sure that it's in the correct cache list. TransmissionHelper.prototype._onMeshMaterialChanged = function (mesh) { var transparentIdx = this._transparentMeshesCache.indexOf(mesh); var opaqueIdx = this._opaqueMeshesCache.indexOf(mesh); // If the material is transparent, make sure that it's added to the transparent list and removed from the opaque list var useTransmission = this._shouldRenderAsTransmission(mesh.material); if (useTransmission) { if (mesh.material instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial) { mesh.material.subSurface.refractionTexture = this._opaqueRenderTarget; } if (opaqueIdx !== -1) { this._opaqueMeshesCache.splice(opaqueIdx, 1); this._transparentMeshesCache.push(mesh); } else if (transparentIdx === -1) { this._transparentMeshesCache.push(mesh); } // If the material is opaque, make sure that it's added to the opaque list and removed from the transparent list } else { if (transparentIdx !== -1) { this._transparentMeshesCache.splice(transparentIdx, 1); this._opaqueMeshesCache.push(mesh); } else if (opaqueIdx === -1) { this._opaqueMeshesCache.push(mesh); } } }; /** * @internal * Check if the opaque render target has not been disposed and can still be used. * @returns */ TransmissionHelper.prototype._isRenderTargetValid = function () { var _a; return ((_a = this._opaqueRenderTarget) === null || _a === void 0 ? void 0 : _a.getInternalTexture()) !== null; }; /** * @internal * Setup the render targets according to the specified options. */ TransmissionHelper.prototype._setupRenderTargets = function () { var _this = this; var _a, _b; if (this._opaqueRenderTarget) { this._opaqueRenderTarget.dispose(); } this._opaqueRenderTarget = new babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.RenderTargetTexture("opaqueSceneTexture", this._options.renderSize, this._scene, this._options.generateMipmaps, undefined, this._options.renderTargetTextureType); this._opaqueRenderTarget.ignoreCameraViewport = true; this._opaqueRenderTarget.renderList = this._opaqueMeshesCache; this._opaqueRenderTarget.clearColor = (_b = (_a = this._options.clearColor) === null || _a === void 0 ? void 0 : _a.clone()) !== null && _b !== void 0 ? _b : this._scene.clearColor.clone(); this._opaqueRenderTarget.gammaSpace = false; this._opaqueRenderTarget.lodGenerationScale = this._options.lodGenerationScale; this._opaqueRenderTarget.lodGenerationOffset = this._options.lodGenerationOffset; this._opaqueRenderTarget.samples = this._options.samples; var sceneImageProcessingapplyByPostProcess; var saveSceneEnvIntensity; this._opaqueRenderTarget.onBeforeBindObservable.add(function (opaqueRenderTarget) { saveSceneEnvIntensity = _this._scene.environmentIntensity; _this._scene.environmentIntensity = 1.0; sceneImageProcessingapplyByPostProcess = _this._scene.imageProcessingConfiguration.applyByPostProcess; if (!_this._options.clearColor) { _this._scene.clearColor.toLinearSpaceToRef(opaqueRenderTarget.clearColor, _this._scene.getEngine().useExactSrgbConversions); } else { opaqueRenderTarget.clearColor.copyFrom(_this._options.clearColor); } // we do not use the applyByPostProcess setter to avoid flagging all the materials as "image processing dirty"! _this._scene.imageProcessingConfiguration._applyByPostProcess = true; }); this._opaqueRenderTarget.onAfterUnbindObservable.add(function () { _this._scene.environmentIntensity = saveSceneEnvIntensity; _this._scene.imageProcessingConfiguration._applyByPostProcess = sceneImageProcessingapplyByPostProcess; }); this._transparentMeshesCache.forEach(function (mesh) { if (_this._shouldRenderAsTransmission(mesh.material)) { mesh.material.refractionTexture = _this._opaqueRenderTarget; } }); }; /** * Dispose all the elements created by the Helper. */ TransmissionHelper.prototype.dispose = function () { this._scene._transmissionHelper = undefined; if (this._opaqueRenderTarget) { this._opaqueRenderTarget.dispose(); this._opaqueRenderTarget = null; } this._transparentMeshesCache = []; this._opaqueMeshesCache = []; }; return TransmissionHelper; }()); var NAME = "KHR_materials_transmission"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_transmission/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_materials_transmission = /** @class */ (function () { /** * @internal */ function KHR_materials_transmission(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 175; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); if (this.enabled) { loader.parent.transparencyAsCoverage = true; } } /** @internal */ KHR_materials_transmission.prototype.dispose = function () { this._loader = null; }; /** * @internal */ KHR_materials_transmission.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, material, this.name, function (extensionContext, extension) { var promises = new Array(); promises.push(_this._loader.loadMaterialBasePropertiesAsync(context, material, babylonMaterial)); promises.push(_this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(_this._loadTransparentPropertiesAsync(extensionContext, material, babylonMaterial, extension)); return Promise.all(promises).then(function () { }); }); }; KHR_materials_transmission.prototype._loadTransparentPropertiesAsync = function (context, material, babylonMaterial, extension) { var _a, _b; if (!(babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } var pbrMaterial = babylonMaterial; // Enables "refraction" texture which represents transmitted light. pbrMaterial.subSurface.isRefractionEnabled = true; // Since this extension models thin-surface transmission only, we must make IOR = 1.0 pbrMaterial.subSurface.volumeIndexOfRefraction = 1.0; // Albedo colour will tint transmission. pbrMaterial.subSurface.useAlbedoToTintRefraction = true; if (extension.transmissionFactor !== undefined) { pbrMaterial.subSurface.refractionIntensity = extension.transmissionFactor; var scene = pbrMaterial.getScene(); if (pbrMaterial.subSurface.refractionIntensity && !scene._transmissionHelper) { new TransmissionHelper({}, pbrMaterial.getScene()); } else if (pbrMaterial.subSurface.refractionIntensity && !((_a = scene._transmissionHelper) === null || _a === void 0 ? void 0 : _a._isRenderTargetValid())) { // If the render target is not valid, recreate it. (_b = scene._transmissionHelper) === null || _b === void 0 ? void 0 : _b._setupRenderTargets(); } } else { pbrMaterial.subSurface.refractionIntensity = 0.0; pbrMaterial.subSurface.isRefractionEnabled = false; return Promise.resolve(); } pbrMaterial.subSurface.minimumThickness = 0.0; pbrMaterial.subSurface.maximumThickness = 0.0; if (extension.transmissionTexture) { extension.transmissionTexture.nonColorData = true; return this._loader.loadTextureInfoAsync("".concat(context, "/transmissionTexture"), extension.transmissionTexture, undefined).then(function (texture) { pbrMaterial.subSurface.refractionIntensityTexture = texture; pbrMaterial.subSurface.useGltfStyleTextures = true; }); } else { return Promise.resolve(); } }; return KHR_materials_transmission; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_materials_transmission(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts": /*!***************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts ***! \***************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_materials_unlit: () => (/* binding */ KHR_materials_unlit) /* harmony export */ }); /* harmony import */ var babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/PBR/pbrMaterial */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_materials_unlit"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_unlit/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_materials_unlit = /** @class */ (function () { /** * @internal */ function KHR_materials_unlit(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 210; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_materials_unlit.prototype.dispose = function () { this._loader = null; }; /** * @internal */ KHR_materials_unlit.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, material, this.name, function () { return _this._loadUnlitPropertiesAsync(context, material, babylonMaterial); }); }; KHR_materials_unlit.prototype._loadUnlitPropertiesAsync = function (context, material, babylonMaterial) { if (!(babylonMaterial instanceof babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } var promises = new Array(); babylonMaterial.unlit = true; var properties = material.pbrMetallicRoughness; if (properties) { if (properties.baseColorFactor) { babylonMaterial.albedoColor = babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(properties.baseColorFactor); babylonMaterial.alpha = properties.baseColorFactor[3]; } else { babylonMaterial.albedoColor = babylonjs_Maths_math_color__WEBPACK_IMPORTED_MODULE_0__.Color3.White(); } if (properties.baseColorTexture) { promises.push(this._loader.loadTextureInfoAsync("".concat(context, "/baseColorTexture"), properties.baseColorTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Base Color)"); babylonMaterial.albedoTexture = texture; })); } } if (material.doubleSided) { babylonMaterial.backFaceCulling = false; babylonMaterial.twoSidedLighting = true; } this._loader.loadMaterialAlphaProperties(context, material, babylonMaterial); return Promise.all(promises).then(function () { }); }; return KHR_materials_unlit; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_materials_unlit(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_variants.ts": /*!******************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_variants.ts ***! \******************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_materials_variants: () => (/* binding */ KHR_materials_variants) /* harmony export */ }); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); /* harmony import */ var babylonjs_Meshes_mesh__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! babylonjs/Meshes/mesh */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Meshes_mesh__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Meshes_mesh__WEBPACK_IMPORTED_MODULE_1__); var NAME = "KHR_materials_variants"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_variants/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_materials_variants = /** @class */ (function () { /** * @internal */ function KHR_materials_variants(loader) { /** * The name of this extension. */ this.name = NAME; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_materials_variants.prototype.dispose = function () { this._loader = null; }; /** * Gets the list of available variant names for this asset. * @param rootMesh The glTF root mesh * @returns the list of all the variant names for this model */ KHR_materials_variants.GetAvailableVariants = function (rootMesh) { var extensionMetadata = this._GetExtensionMetadata(rootMesh); if (!extensionMetadata) { return []; } return Object.keys(extensionMetadata.variants); }; /** * Gets the list of available variant names for this asset. * @param rootMesh The glTF root mesh * @returns the list of all the variant names for this model */ KHR_materials_variants.prototype.getAvailableVariants = function (rootMesh) { return KHR_materials_variants.GetAvailableVariants(rootMesh); }; /** * Select a variant given a variant name or a list of variant names. * @param rootMesh The glTF root mesh * @param variantName The variant name(s) to select. */ KHR_materials_variants.SelectVariant = function (rootMesh, variantName) { var extensionMetadata = this._GetExtensionMetadata(rootMesh); if (!extensionMetadata) { throw new Error("Cannot select variant on a glTF mesh that does not have the ".concat(NAME, " extension")); } var select = function (variantName) { var entries = extensionMetadata.variants[variantName]; if (entries) { for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) { var entry = entries_1[_i]; entry.mesh.material = entry.material; } } }; if (variantName instanceof Array) { for (var _i = 0, variantName_1 = variantName; _i < variantName_1.length; _i++) { var name_1 = variantName_1[_i]; select(name_1); } } else { select(variantName); } extensionMetadata.lastSelected = variantName; }; /** * Select a variant given a variant name or a list of variant names. * @param rootMesh The glTF root mesh * @param variantName The variant name(s) to select. */ KHR_materials_variants.prototype.selectVariant = function (rootMesh, variantName) { return KHR_materials_variants.SelectVariant(rootMesh, variantName); }; /** * Reset back to the original before selecting a variant. * @param rootMesh The glTF root mesh */ KHR_materials_variants.Reset = function (rootMesh) { var extensionMetadata = this._GetExtensionMetadata(rootMesh); if (!extensionMetadata) { throw new Error("Cannot reset on a glTF mesh that does not have the ".concat(NAME, " extension")); } for (var _i = 0, _a = extensionMetadata.original; _i < _a.length; _i++) { var entry = _a[_i]; entry.mesh.material = entry.material; } extensionMetadata.lastSelected = null; }; /** * Reset back to the original before selecting a variant. * @param rootMesh The glTF root mesh */ KHR_materials_variants.prototype.reset = function (rootMesh) { return KHR_materials_variants.Reset(rootMesh); }; /** * Gets the last selected variant name(s) or null if original. * @param rootMesh The glTF root mesh * @returns The selected variant name(s). */ KHR_materials_variants.GetLastSelectedVariant = function (rootMesh) { var extensionMetadata = this._GetExtensionMetadata(rootMesh); if (!extensionMetadata) { throw new Error("Cannot get the last selected variant on a glTF mesh that does not have the ".concat(NAME, " extension")); } return extensionMetadata.lastSelected; }; /** * Gets the last selected variant name(s) or null if original. * @param rootMesh The glTF root mesh * @returns The selected variant name(s). */ KHR_materials_variants.prototype.getLastSelectedVariant = function (rootMesh) { return KHR_materials_variants.GetLastSelectedVariant(rootMesh); }; KHR_materials_variants._GetExtensionMetadata = function (rootMesh) { var _a, _b; return ((_b = (_a = rootMesh === null || rootMesh === void 0 ? void 0 : rootMesh._internalMetadata) === null || _a === void 0 ? void 0 : _a.gltf) === null || _b === void 0 ? void 0 : _b[NAME]) || null; }; /** @internal */ KHR_materials_variants.prototype.onLoading = function () { var extensions = this._loader.gltf.extensions; if (extensions && extensions[this.name]) { var extension = extensions[this.name]; this._variants = extension.variants; } }; /** * @internal */ KHR_materials_variants.prototype._loadMeshPrimitiveAsync = function (context, name, node, mesh, primitive, assign) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.LoadExtensionAsync(context, primitive, this.name, function (extensionContext, extension) { var promises = new Array(); promises.push(_this._loader._loadMeshPrimitiveAsync(context, name, node, mesh, primitive, function (babylonMesh) { assign(babylonMesh); if (babylonMesh instanceof babylonjs_Meshes_mesh__WEBPACK_IMPORTED_MODULE_1__.Mesh) { var babylonDrawMode = _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader._GetDrawMode(context, primitive.mode); var root_1 = _this._loader.rootBabylonMesh; var metadata = root_1 ? (root_1._internalMetadata = root_1._internalMetadata || {}) : {}; var gltf = (metadata.gltf = metadata.gltf || {}); var extensionMetadata_1 = (gltf[NAME] = gltf[NAME] || { lastSelected: null, original: [], variants: {} }); // Store the original material. extensionMetadata_1.original.push({ mesh: babylonMesh, material: babylonMesh.material }); var _loop_1 = function (mappingIndex) { var mapping = extension.mappings[mappingIndex]; var material = _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.ArrayItem.Get("".concat(extensionContext, "/mappings/").concat(mappingIndex, "/material"), _this._loader.gltf.materials, mapping.material); promises.push(_this._loader._loadMaterialAsync("#/materials/".concat(mapping.material), material, babylonMesh, babylonDrawMode, function (babylonMaterial) { var _loop_2 = function (mappingVariantIndex) { var variantIndex = mapping.variants[mappingVariantIndex]; var variant = _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.ArrayItem.Get("/extensions/".concat(NAME, "/variants/").concat(variantIndex), _this._variants, variantIndex); extensionMetadata_1.variants[variant.name] = extensionMetadata_1.variants[variant.name] || []; extensionMetadata_1.variants[variant.name].push({ mesh: babylonMesh, material: babylonMaterial, }); // Replace the target when original mesh is cloned babylonMesh.onClonedObservable.add(function (newOne) { var newMesh = newOne; var metadata = null; var newRoot = newMesh; // Find root to get medata do { newRoot = newRoot.parent; if (!newRoot) { return; } metadata = KHR_materials_variants._GetExtensionMetadata(newRoot); } while (metadata === null); // Need to clone the metadata on the root (first time only) if (root_1 && metadata === KHR_materials_variants._GetExtensionMetadata(root_1)) { // Copy main metadata newRoot._internalMetadata = {}; for (var key in root_1._internalMetadata) { newRoot._internalMetadata[key] = root_1._internalMetadata[key]; } // Copy the gltf metadata newRoot._internalMetadata.gltf = []; for (var key in root_1._internalMetadata.gltf) { newRoot._internalMetadata.gltf[key] = root_1._internalMetadata.gltf[key]; } // Duplicate the extension specific metadata newRoot._internalMetadata.gltf[NAME] = { lastSelected: null, original: [], variants: {} }; for (var _i = 0, _a = metadata.original; _i < _a.length; _i++) { var original = _a[_i]; newRoot._internalMetadata.gltf[NAME].original.push({ mesh: original.mesh, material: original.material, }); } for (var key in metadata.variants) { if (Object.prototype.hasOwnProperty.call(metadata.variants, key)) { newRoot._internalMetadata.gltf[NAME].variants[key] = []; for (var _b = 0, _c = metadata.variants[key]; _b < _c.length; _b++) { var variantEntry = _c[_b]; newRoot._internalMetadata.gltf[NAME].variants[key].push({ mesh: variantEntry.mesh, material: variantEntry.material, }); } } } metadata = newRoot._internalMetadata.gltf[NAME]; } // Relocate for (var _d = 0, _e = metadata.original; _d < _e.length; _d++) { var target = _e[_d]; if (target.mesh === babylonMesh) { target.mesh = newMesh; } } for (var _f = 0, _g = metadata.variants[variant.name]; _f < _g.length; _f++) { var target = _g[_f]; if (target.mesh === babylonMesh) { target.mesh = newMesh; } } }); }; for (var mappingVariantIndex = 0; mappingVariantIndex < mapping.variants.length; ++mappingVariantIndex) { _loop_2(mappingVariantIndex); } })); }; // For each mapping, look at the variants and make a new entry for them. for (var mappingIndex = 0; mappingIndex < extension.mappings.length; ++mappingIndex) { _loop_1(mappingIndex); } } })); return Promise.all(promises).then(function (_a) { var babylonMesh = _a[0]; return babylonMesh; }); }); }; return KHR_materials_variants; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_materials_variants(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts": /*!****************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts ***! \****************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_materials_volume: () => (/* binding */ KHR_materials_volume) /* harmony export */ }); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/PBR/pbrMaterial */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_materials_volume"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_materials_volume/README.md) * @since 5.0.0 */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_materials_volume = /** @class */ (function () { /** * @internal */ function KHR_materials_volume(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 173; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); if (this.enabled) { // We need to disable instance usage because the attenuation factor depends on the node scale of each individual mesh this._loader._disableInstancedMesh++; } } /** @internal */ KHR_materials_volume.prototype.dispose = function () { if (this.enabled) { this._loader._disableInstancedMesh--; } this._loader = null; }; /** * @internal */ KHR_materials_volume.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, material, this.name, function (extensionContext, extension) { var promises = new Array(); promises.push(_this._loader.loadMaterialBasePropertiesAsync(context, material, babylonMaterial)); promises.push(_this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial)); promises.push(_this._loadVolumePropertiesAsync(extensionContext, material, babylonMaterial, extension)); return Promise.all(promises).then(function () { }); }); }; KHR_materials_volume.prototype._loadVolumePropertiesAsync = function (context, material, babylonMaterial, extension) { if (!(babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } // If transparency isn't enabled already, this extension shouldn't do anything. // i.e. it requires either the KHR_materials_transmission or KHR_materials_translucency extensions. if ((!babylonMaterial.subSurface.isRefractionEnabled && !babylonMaterial.subSurface.isTranslucencyEnabled) || !extension.thicknessFactor) { return Promise.resolve(); } // IOR in this extension only affects interior. babylonMaterial.subSurface.volumeIndexOfRefraction = babylonMaterial.indexOfRefraction; var attenuationDistance = extension.attenuationDistance !== undefined ? extension.attenuationDistance : Number.MAX_VALUE; babylonMaterial.subSurface.tintColorAtDistance = attenuationDistance; if (extension.attenuationColor !== undefined && extension.attenuationColor.length == 3) { babylonMaterial.subSurface.tintColor.copyFromFloats(extension.attenuationColor[0], extension.attenuationColor[1], extension.attenuationColor[2]); } babylonMaterial.subSurface.minimumThickness = 0.0; babylonMaterial.subSurface.maximumThickness = extension.thicknessFactor; babylonMaterial.subSurface.useThicknessAsDepth = true; if (extension.thicknessTexture) { extension.thicknessTexture.nonColorData = true; return this._loader.loadTextureInfoAsync("".concat(context, "/thicknessTexture"), extension.thicknessTexture).then(function (texture) { babylonMaterial.subSurface.thicknessTexture = texture; babylonMaterial.subSurface.useGltfStyleTextures = true; }); } else { return Promise.resolve(); } }; return KHR_materials_volume; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_materials_volume(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_mesh_quantization.ts": /*!*****************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_mesh_quantization.ts ***! \*****************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_mesh_quantization: () => (/* binding */ KHR_mesh_quantization) /* harmony export */ }); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_mesh_quantization"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_mesh_quantization/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_mesh_quantization = /** @class */ (function () { /** * @internal */ function KHR_mesh_quantization(loader) { /** * The name of this extension. */ this.name = NAME; this.enabled = loader.isExtensionUsed(NAME); } /** @internal */ KHR_mesh_quantization.prototype.dispose = function () { }; return KHR_mesh_quantization; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_mesh_quantization(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_texture_basisu.ts": /*!**************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_texture_basisu.ts ***! \**************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_texture_basisu: () => (/* binding */ KHR_texture_basisu) /* harmony export */ }); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_texture_basisu"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_texture_basisu/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_texture_basisu = /** @class */ (function () { /** * @internal */ function KHR_texture_basisu(loader) { /** The name of this extension. */ this.name = NAME; this._loader = loader; this.enabled = loader.isExtensionUsed(NAME); } /** @internal */ KHR_texture_basisu.prototype.dispose = function () { this._loader = null; }; /** * @internal */ KHR_texture_basisu.prototype._loadTextureAsync = function (context, texture, assign) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.LoadExtensionAsync(context, texture, this.name, function (extensionContext, extension) { var sampler = texture.sampler == undefined ? _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.DefaultSampler : _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.ArrayItem.Get("".concat(context, "/sampler"), _this._loader.gltf.samplers, texture.sampler); var image = _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.ArrayItem.Get("".concat(extensionContext, "/source"), _this._loader.gltf.images, extension.source); return _this._loader._createTextureAsync(context, sampler, image, function (babylonTexture) { assign(babylonTexture); }, texture._textureInfo.nonColorData ? { useRGBAIfASTCBC7NotAvailableWhenUASTC: true } : undefined, !texture._textureInfo.nonColorData); }); }; return KHR_texture_basisu; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_texture_basisu(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_texture_transform.ts": /*!*****************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_texture_transform.ts ***! \*****************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_texture_transform: () => (/* binding */ KHR_texture_transform) /* harmony export */ }); /* harmony import */ var babylonjs_Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/Textures/texture */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_texture_transform"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_texture_transform/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_texture_transform = /** @class */ (function () { /** * @internal */ function KHR_texture_transform(loader) { /** * The name of this extension. */ this.name = NAME; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_texture_transform.prototype.dispose = function () { this._loader = null; }; /** * @internal */ KHR_texture_transform.prototype.loadTextureInfoAsync = function (context, textureInfo, assign) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, textureInfo, this.name, function (extensionContext, extension) { return _this._loader.loadTextureInfoAsync(context, textureInfo, function (babylonTexture) { if (!(babylonTexture instanceof babylonjs_Materials_Textures_texture__WEBPACK_IMPORTED_MODULE_0__.Texture)) { throw new Error("".concat(extensionContext, ": Texture type not supported")); } if (extension.offset) { babylonTexture.uOffset = extension.offset[0]; babylonTexture.vOffset = extension.offset[1]; } // Always rotate around the origin. babylonTexture.uRotationCenter = 0; babylonTexture.vRotationCenter = 0; if (extension.rotation) { babylonTexture.wAng = -extension.rotation; } if (extension.scale) { babylonTexture.uScale = extension.scale[0]; babylonTexture.vScale = extension.scale[1]; } if (extension.texCoord != undefined) { babylonTexture.coordinatesIndex = extension.texCoord; } assign(babylonTexture); }); }); }; return KHR_texture_transform; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_texture_transform(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_xmp_json_ld.ts": /*!***********************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/KHR_xmp_json_ld.ts ***! \***********************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ KHR_xmp_json_ld: () => (/* binding */ KHR_xmp_json_ld) /* harmony export */ }); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "KHR_xmp_json_ld"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Khronos/KHR_xmp_json_ld/README.md) * @since 5.0.0 */ // eslint-disable-next-line @typescript-eslint/naming-convention var KHR_xmp_json_ld = /** @class */ (function () { /** * @internal */ function KHR_xmp_json_ld(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 100; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ KHR_xmp_json_ld.prototype.dispose = function () { this._loader = null; }; /** * Called after the loader state changes to LOADING. */ KHR_xmp_json_ld.prototype.onLoading = function () { var _a, _b, _c; if (this._loader.rootBabylonMesh === null) { return; } var xmp_gltf = (_a = this._loader.gltf.extensions) === null || _a === void 0 ? void 0 : _a.KHR_xmp_json_ld; var xmp_node = (_c = (_b = this._loader.gltf.asset) === null || _b === void 0 ? void 0 : _b.extensions) === null || _c === void 0 ? void 0 : _c.KHR_xmp_json_ld; if (xmp_gltf && xmp_node) { var packet = +xmp_node.packet; if (xmp_gltf.packets && packet < xmp_gltf.packets.length) { this._loader.rootBabylonMesh.metadata = this._loader.rootBabylonMesh.metadata || {}; this._loader.rootBabylonMesh.metadata.xmp = xmp_gltf.packets[packet]; } } }; return KHR_xmp_json_ld; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new KHR_xmp_json_ld(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/MSFT_audio_emitter.ts": /*!**************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/MSFT_audio_emitter.ts ***! \**************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MSFT_audio_emitter: () => (/* binding */ MSFT_audio_emitter) /* harmony export */ }); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Audio/weightedsound */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "MSFT_audio_emitter"; /** * [Specification](https://github.com/najadojo/glTF/blob/MSFT_audio_emitter/extensions/2.0/Vendor/MSFT_audio_emitter/README.md) * !!! Experimental Extension Subject to Changes !!! */ // eslint-disable-next-line @typescript-eslint/naming-convention var MSFT_audio_emitter = /** @class */ (function () { /** * @internal */ function MSFT_audio_emitter(loader) { /** * The name of this extension. */ this.name = NAME; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ MSFT_audio_emitter.prototype.dispose = function () { this._loader = null; this._clips = null; this._emitters = null; }; /** @internal */ MSFT_audio_emitter.prototype.onLoading = function () { var extensions = this._loader.gltf.extensions; if (extensions && extensions[this.name]) { var extension = extensions[this.name]; this._clips = extension.clips; this._emitters = extension.emitters; _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Assign(this._clips); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Assign(this._emitters); } }; /** * @internal */ MSFT_audio_emitter.prototype.loadSceneAsync = function (context, scene) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, scene, this.name, function (extensionContext, extension) { var promises = new Array(); promises.push(_this._loader.loadSceneAsync(context, scene)); for (var _i = 0, _a = extension.emitters; _i < _a.length; _i++) { var emitterIndex = _a[_i]; var emitter = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Get("".concat(extensionContext, "/emitters"), _this._emitters, emitterIndex); if (emitter.refDistance != undefined || emitter.maxDistance != undefined || emitter.rolloffFactor != undefined || emitter.distanceModel != undefined || emitter.innerAngle != undefined || emitter.outerAngle != undefined) { throw new Error("".concat(extensionContext, ": Direction or Distance properties are not allowed on emitters attached to a scene")); } promises.push(_this._loadEmitterAsync("".concat(extensionContext, "/emitters/").concat(emitter.index), emitter)); } return Promise.all(promises).then(function () { }); }); }; /** * @internal */ MSFT_audio_emitter.prototype.loadNodeAsync = function (context, node, assign) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, node, this.name, function (extensionContext, extension) { var promises = new Array(); return _this._loader .loadNodeAsync(extensionContext, node, function (babylonMesh) { var _loop_1 = function (emitterIndex) { var emitter = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Get("".concat(extensionContext, "/emitters"), _this._emitters, emitterIndex); promises.push(_this._loadEmitterAsync("".concat(extensionContext, "/emitters/").concat(emitter.index), emitter).then(function () { for (var _i = 0, _a = emitter._babylonSounds; _i < _a.length; _i++) { var sound = _a[_i]; sound.attachToMesh(babylonMesh); if (emitter.innerAngle != undefined || emitter.outerAngle != undefined) { sound.setLocalDirectionToMesh(babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Vector3.Forward()); sound.setDirectionalCone(2 * babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Tools.ToDegrees(emitter.innerAngle == undefined ? Math.PI : emitter.innerAngle), 2 * babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Tools.ToDegrees(emitter.outerAngle == undefined ? Math.PI : emitter.outerAngle), 0); } } })); }; for (var _i = 0, _a = extension.emitters; _i < _a.length; _i++) { var emitterIndex = _a[_i]; _loop_1(emitterIndex); } assign(babylonMesh); }) .then(function (babylonMesh) { return Promise.all(promises).then(function () { return babylonMesh; }); }); }); }; /** * @internal */ MSFT_audio_emitter.prototype.loadAnimationAsync = function (context, animation) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, animation, this.name, function (extensionContext, extension) { return _this._loader.loadAnimationAsync(context, animation).then(function (babylonAnimationGroup) { var promises = new Array(); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Assign(extension.events); for (var _i = 0, _a = extension.events; _i < _a.length; _i++) { var event_1 = _a[_i]; promises.push(_this._loadAnimationEventAsync("".concat(extensionContext, "/events/").concat(event_1.index), context, animation, event_1, babylonAnimationGroup)); } return Promise.all(promises).then(function () { return babylonAnimationGroup; }); }); }); }; MSFT_audio_emitter.prototype._loadClipAsync = function (context, clip) { if (clip._objectURL) { return clip._objectURL; } var promise; if (clip.uri) { promise = this._loader.loadUriAsync(context, clip, clip.uri); } else { var bufferView = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Get("".concat(context, "/bufferView"), this._loader.gltf.bufferViews, clip.bufferView); promise = this._loader.loadBufferViewAsync("/bufferViews/".concat(bufferView.index), bufferView); } clip._objectURL = promise.then(function (data) { return URL.createObjectURL(new Blob([data], { type: clip.mimeType })); }); return clip._objectURL; }; MSFT_audio_emitter.prototype._loadEmitterAsync = function (context, emitter) { var _this = this; emitter._babylonSounds = emitter._babylonSounds || []; if (!emitter._babylonData) { var clipPromises = new Array(); var name_1 = emitter.name || "emitter".concat(emitter.index); var options_1 = { loop: false, autoplay: false, volume: emitter.volume == undefined ? 1 : emitter.volume, }; var _loop_2 = function (i) { var clipContext = "/extensions/".concat(this_1.name, "/clips"); var clip = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Get(clipContext, this_1._clips, emitter.clips[i].clip); clipPromises.push(this_1._loadClipAsync("".concat(clipContext, "/").concat(emitter.clips[i].clip), clip).then(function (objectURL) { var sound = (emitter._babylonSounds[i] = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Sound(name_1, objectURL, _this._loader.babylonScene, null, options_1)); sound.refDistance = emitter.refDistance || 1; sound.maxDistance = emitter.maxDistance || 256; sound.rolloffFactor = emitter.rolloffFactor || 1; sound.distanceModel = emitter.distanceModel || "exponential"; })); }; var this_1 = this; for (var i = 0; i < emitter.clips.length; i++) { _loop_2(i); } var promise = Promise.all(clipPromises).then(function () { var weights = emitter.clips.map(function (clip) { return clip.weight || 1; }); var weightedSound = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.WeightedSound(emitter.loop || false, emitter._babylonSounds, weights); if (emitter.innerAngle) { weightedSound.directionalConeInnerAngle = 2 * babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Tools.ToDegrees(emitter.innerAngle); } if (emitter.outerAngle) { weightedSound.directionalConeOuterAngle = 2 * babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.Tools.ToDegrees(emitter.outerAngle); } if (emitter.volume) { weightedSound.volume = emitter.volume; } emitter._babylonData.sound = weightedSound; }); emitter._babylonData = { loaded: promise, }; } return emitter._babylonData.loaded; }; MSFT_audio_emitter.prototype._getEventAction = function (context, sound, action, time, startOffset) { switch (action) { case "play" /* IMSFTAudioEmitter_AnimationEventAction.play */: { return function (currentFrame) { var frameOffset = (startOffset || 0) + (currentFrame - time); sound.play(frameOffset); }; } case "stop" /* IMSFTAudioEmitter_AnimationEventAction.stop */: { return function () { sound.stop(); }; } case "pause" /* IMSFTAudioEmitter_AnimationEventAction.pause */: { return function () { sound.pause(); }; } default: { throw new Error("".concat(context, ": Unsupported action ").concat(action)); } } }; MSFT_audio_emitter.prototype._loadAnimationEventAsync = function (context, animationContext, animation, event, babylonAnimationGroup) { var _this = this; if (babylonAnimationGroup.targetedAnimations.length == 0) { return Promise.resolve(); } var babylonAnimation = babylonAnimationGroup.targetedAnimations[0]; var emitterIndex = event.emitter; var emitter = _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Get("/extensions/".concat(this.name, "/emitters"), this._emitters, emitterIndex); return this._loadEmitterAsync(context, emitter).then(function () { var sound = emitter._babylonData.sound; if (sound) { var babylonAnimationEvent = new babylonjs_Maths_math_vector__WEBPACK_IMPORTED_MODULE_0__.AnimationEvent(event.time, _this._getEventAction(context, sound, event.action, event.time, event.startOffset)); babylonAnimation.animation.addEvent(babylonAnimationEvent); // Make sure all started audio stops when this animation is terminated. babylonAnimationGroup.onAnimationGroupEndObservable.add(function () { sound.stop(); }); babylonAnimationGroup.onAnimationGroupPauseObservable.add(function () { sound.pause(); }); } }); }; return MSFT_audio_emitter; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new MSFT_audio_emitter(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/MSFT_lod.ts": /*!****************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/MSFT_lod.ts ***! \****************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MSFT_lod: () => (/* binding */ MSFT_lod) /* harmony export */ }); /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/deferred */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "MSFT_lod"; /** * [Specification](https://github.com/KhronosGroup/glTF/blob/main/extensions/2.0/Vendor/MSFT_lod/README.md) */ // eslint-disable-next-line @typescript-eslint/naming-convention var MSFT_lod = /** @class */ (function () { /** * @internal */ function MSFT_lod(loader) { /** * The name of this extension. */ this.name = NAME; /** * Defines a number that determines the order the extensions are applied. */ this.order = 100; /** * Maximum number of LODs to load, starting from the lowest LOD. */ this.maxLODsToLoad = 10; /** * Observable raised when all node LODs of one level are loaded. * The event data is the index of the loaded LOD starting from zero. * Dispose the loader to cancel the loading of the next level of LODs. */ this.onNodeLODsLoadedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); /** * Observable raised when all material LODs of one level are loaded. * The event data is the index of the loaded LOD starting from zero. * Dispose the loader to cancel the loading of the next level of LODs. */ this.onMaterialLODsLoadedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); this._bufferLODs = new Array(); this._nodeIndexLOD = null; this._nodeSignalLODs = new Array(); this._nodePromiseLODs = new Array(); this._nodeBufferLODs = new Array(); this._materialIndexLOD = null; this._materialSignalLODs = new Array(); this._materialPromiseLODs = new Array(); this._materialBufferLODs = new Array(); this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ MSFT_lod.prototype.dispose = function () { this._loader = null; this._nodeIndexLOD = null; this._nodeSignalLODs.length = 0; this._nodePromiseLODs.length = 0; this._nodeBufferLODs.length = 0; this._materialIndexLOD = null; this._materialSignalLODs.length = 0; this._materialPromiseLODs.length = 0; this._materialBufferLODs.length = 0; this.onMaterialLODsLoadedObservable.clear(); this.onNodeLODsLoadedObservable.clear(); }; /** @internal */ MSFT_lod.prototype.onReady = function () { var _this = this; var _loop_1 = function (indexLOD) { var promise = Promise.all(this_1._nodePromiseLODs[indexLOD]).then(function () { if (indexLOD !== 0) { _this._loader.endPerformanceCounter("Node LOD ".concat(indexLOD)); _this._loader.log("Loaded node LOD ".concat(indexLOD)); } _this.onNodeLODsLoadedObservable.notifyObservers(indexLOD); if (indexLOD !== _this._nodePromiseLODs.length - 1) { _this._loader.startPerformanceCounter("Node LOD ".concat(indexLOD + 1)); _this._loadBufferLOD(_this._nodeBufferLODs, indexLOD + 1); if (_this._nodeSignalLODs[indexLOD]) { _this._nodeSignalLODs[indexLOD].resolve(); } } }); this_1._loader._completePromises.push(promise); }; var this_1 = this; for (var indexLOD = 0; indexLOD < this._nodePromiseLODs.length; indexLOD++) { _loop_1(indexLOD); } var _loop_2 = function (indexLOD) { var promise = Promise.all(this_2._materialPromiseLODs[indexLOD]).then(function () { if (indexLOD !== 0) { _this._loader.endPerformanceCounter("Material LOD ".concat(indexLOD)); _this._loader.log("Loaded material LOD ".concat(indexLOD)); } _this.onMaterialLODsLoadedObservable.notifyObservers(indexLOD); if (indexLOD !== _this._materialPromiseLODs.length - 1) { _this._loader.startPerformanceCounter("Material LOD ".concat(indexLOD + 1)); _this._loadBufferLOD(_this._materialBufferLODs, indexLOD + 1); if (_this._materialSignalLODs[indexLOD]) { _this._materialSignalLODs[indexLOD].resolve(); } } }); this_2._loader._completePromises.push(promise); }; var this_2 = this; for (var indexLOD = 0; indexLOD < this._materialPromiseLODs.length; indexLOD++) { _loop_2(indexLOD); } }; /** * @internal */ MSFT_lod.prototype.loadSceneAsync = function (context, scene) { var promise = this._loader.loadSceneAsync(context, scene); this._loadBufferLOD(this._bufferLODs, 0); return promise; }; /** * @internal */ MSFT_lod.prototype.loadNodeAsync = function (context, node, assign) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, node, this.name, function (extensionContext, extension) { var firstPromise; var nodeLODs = _this._getLODs(extensionContext, node, _this._loader.gltf.nodes, extension.ids); _this._loader.logOpen("".concat(extensionContext)); var _loop_3 = function (indexLOD) { var nodeLOD = nodeLODs[indexLOD]; if (indexLOD !== 0) { _this._nodeIndexLOD = indexLOD; _this._nodeSignalLODs[indexLOD] = _this._nodeSignalLODs[indexLOD] || new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Deferred(); } var assignWrap = function (babylonTransformNode) { assign(babylonTransformNode); babylonTransformNode.setEnabled(false); }; var promise = _this._loader.loadNodeAsync("/nodes/".concat(nodeLOD.index), nodeLOD, assignWrap).then(function (babylonMesh) { if (indexLOD !== 0) { // TODO: should not rely on _babylonTransformNode var previousNodeLOD = nodeLODs[indexLOD - 1]; if (previousNodeLOD._babylonTransformNode) { _this._disposeTransformNode(previousNodeLOD._babylonTransformNode); delete previousNodeLOD._babylonTransformNode; } } babylonMesh.setEnabled(true); return babylonMesh; }); _this._nodePromiseLODs[indexLOD] = _this._nodePromiseLODs[indexLOD] || []; if (indexLOD === 0) { firstPromise = promise; } else { _this._nodeIndexLOD = null; _this._nodePromiseLODs[indexLOD].push(promise); } }; for (var indexLOD = 0; indexLOD < nodeLODs.length; indexLOD++) { _loop_3(indexLOD); } _this._loader.logClose(); return firstPromise; }); }; /** * @internal */ MSFT_lod.prototype._loadMaterialAsync = function (context, material, babylonMesh, babylonDrawMode, assign) { var _this = this; // Don't load material LODs if already loading a node LOD. if (this._nodeIndexLOD) { return null; } return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtensionAsync(context, material, this.name, function (extensionContext, extension) { var firstPromise; var materialLODs = _this._getLODs(extensionContext, material, _this._loader.gltf.materials, extension.ids); _this._loader.logOpen("".concat(extensionContext)); var _loop_4 = function (indexLOD) { var materialLOD = materialLODs[indexLOD]; if (indexLOD !== 0) { _this._materialIndexLOD = indexLOD; } var promise = _this._loader ._loadMaterialAsync("/materials/".concat(materialLOD.index), materialLOD, babylonMesh, babylonDrawMode, function (babylonMaterial) { if (indexLOD === 0) { assign(babylonMaterial); } }) .then(function (babylonMaterial) { if (indexLOD !== 0) { assign(babylonMaterial); // TODO: should not rely on _data var previousDataLOD = materialLODs[indexLOD - 1]._data; if (previousDataLOD[babylonDrawMode]) { _this._disposeMaterials([previousDataLOD[babylonDrawMode].babylonMaterial]); delete previousDataLOD[babylonDrawMode]; } } return babylonMaterial; }); _this._materialPromiseLODs[indexLOD] = _this._materialPromiseLODs[indexLOD] || []; if (indexLOD === 0) { firstPromise = promise; } else { _this._materialIndexLOD = null; _this._materialPromiseLODs[indexLOD].push(promise); } }; for (var indexLOD = 0; indexLOD < materialLODs.length; indexLOD++) { _loop_4(indexLOD); } _this._loader.logClose(); return firstPromise; }); }; /** * @internal */ MSFT_lod.prototype._loadUriAsync = function (context, property, uri) { var _this = this; // Defer the loading of uris if loading a node or material LOD. if (this._nodeIndexLOD !== null) { this._loader.log("deferred"); var previousIndexLOD = this._nodeIndexLOD - 1; this._nodeSignalLODs[previousIndexLOD] = this._nodeSignalLODs[previousIndexLOD] || new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Deferred(); return this._nodeSignalLODs[this._nodeIndexLOD - 1].promise.then(function () { return _this._loader.loadUriAsync(context, property, uri); }); } else if (this._materialIndexLOD !== null) { this._loader.log("deferred"); var previousIndexLOD = this._materialIndexLOD - 1; this._materialSignalLODs[previousIndexLOD] = this._materialSignalLODs[previousIndexLOD] || new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Deferred(); return this._materialSignalLODs[previousIndexLOD].promise.then(function () { return _this._loader.loadUriAsync(context, property, uri); }); } return null; }; /** * @internal */ MSFT_lod.prototype.loadBufferAsync = function (context, buffer, byteOffset, byteLength) { if (this._loader.parent.useRangeRequests && !buffer.uri) { if (!this._loader.bin) { throw new Error("".concat(context, ": Uri is missing or the binary glTF is missing its binary chunk")); } var loadAsync = function (bufferLODs, indexLOD) { var start = byteOffset; var end = start + byteLength - 1; var bufferLOD = bufferLODs[indexLOD]; if (bufferLOD) { bufferLOD.start = Math.min(bufferLOD.start, start); bufferLOD.end = Math.max(bufferLOD.end, end); } else { bufferLOD = { start: start, end: end, loaded: new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Deferred() }; bufferLODs[indexLOD] = bufferLOD; } return bufferLOD.loaded.promise.then(function (data) { return new Uint8Array(data.buffer, data.byteOffset + byteOffset - bufferLOD.start, byteLength); }); }; this._loader.log("deferred"); if (this._nodeIndexLOD !== null) { return loadAsync(this._nodeBufferLODs, this._nodeIndexLOD); } else if (this._materialIndexLOD !== null) { return loadAsync(this._materialBufferLODs, this._materialIndexLOD); } else { return loadAsync(this._bufferLODs, 0); } } return null; }; MSFT_lod.prototype._loadBufferLOD = function (bufferLODs, indexLOD) { var bufferLOD = bufferLODs[indexLOD]; if (bufferLOD) { this._loader.log("Loading buffer range [".concat(bufferLOD.start, "-").concat(bufferLOD.end, "]")); this._loader.bin.readAsync(bufferLOD.start, bufferLOD.end - bufferLOD.start + 1).then(function (data) { bufferLOD.loaded.resolve(data); }, function (error) { bufferLOD.loaded.reject(error); }); } }; /** * Gets an array of LOD properties from lowest to highest. * @param context * @param property * @param array * @param ids */ MSFT_lod.prototype._getLODs = function (context, property, array, ids) { if (this.maxLODsToLoad <= 0) { throw new Error("maxLODsToLoad must be greater than zero"); } var properties = new Array(); for (var i = ids.length - 1; i >= 0; i--) { properties.push(_glTFLoader__WEBPACK_IMPORTED_MODULE_1__.ArrayItem.Get("".concat(context, "/ids/").concat(ids[i]), array, ids[i])); if (properties.length === this.maxLODsToLoad) { return properties; } } properties.push(property); return properties; }; MSFT_lod.prototype._disposeTransformNode = function (babylonTransformNode) { var _this = this; var babylonMaterials = new Array(); var babylonMaterial = babylonTransformNode.material; if (babylonMaterial) { babylonMaterials.push(babylonMaterial); } for (var _i = 0, _a = babylonTransformNode.getChildMeshes(); _i < _a.length; _i++) { var babylonMesh = _a[_i]; if (babylonMesh.material) { babylonMaterials.push(babylonMesh.material); } } babylonTransformNode.dispose(); var babylonMaterialsToDispose = babylonMaterials.filter(function (babylonMaterial) { return _this._loader.babylonScene.meshes.every(function (mesh) { return mesh.material != babylonMaterial; }); }); this._disposeMaterials(babylonMaterialsToDispose); }; MSFT_lod.prototype._disposeMaterials = function (babylonMaterials) { var babylonTextures = {}; for (var _i = 0, babylonMaterials_1 = babylonMaterials; _i < babylonMaterials_1.length; _i++) { var babylonMaterial = babylonMaterials_1[_i]; for (var _a = 0, _b = babylonMaterial.getActiveTextures(); _a < _b.length; _a++) { var babylonTexture = _b[_a]; babylonTextures[babylonTexture.uniqueId] = babylonTexture; } babylonMaterial.dispose(); } for (var uniqueId in babylonTextures) { for (var _c = 0, _d = this._loader.babylonScene.materials; _c < _d.length; _c++) { var babylonMaterial = _d[_c]; if (babylonMaterial.hasTexture(babylonTextures[uniqueId])) { delete babylonTextures[uniqueId]; } } } for (var uniqueId in babylonTextures) { babylonTextures[uniqueId].dispose(); } }; return MSFT_lod; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new MSFT_lod(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts": /*!**************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts ***! \**************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MSFT_minecraftMesh: () => (/* binding */ MSFT_minecraftMesh) /* harmony export */ }); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/PBR/pbrMaterial */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "MSFT_minecraftMesh"; /** @internal */ // eslint-disable-next-line @typescript-eslint/naming-convention var MSFT_minecraftMesh = /** @class */ (function () { /** @internal */ function MSFT_minecraftMesh(loader) { /** @internal */ this.name = NAME; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ MSFT_minecraftMesh.prototype.dispose = function () { this._loader = null; }; /** @internal */ MSFT_minecraftMesh.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtraAsync(context, material, this.name, function (extraContext, extra) { if (extra) { if (!(babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(extraContext, ": Material type not supported")); } var promise = _this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial); if (babylonMaterial.needAlphaBlending()) { babylonMaterial.forceDepthWrite = true; babylonMaterial.separateCullingPass = true; } babylonMaterial.backFaceCulling = babylonMaterial.forceDepthWrite; babylonMaterial.twoSidedLighting = true; return promise; } return null; }); }; return MSFT_minecraftMesh; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new MSFT_minecraftMesh(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts": /*!************************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts ***! \************************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MSFT_sRGBFactors: () => (/* binding */ MSFT_sRGBFactors) /* harmony export */ }); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Materials/PBR/pbrMaterial */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); var NAME = "MSFT_sRGBFactors"; /** @internal */ // eslint-disable-next-line @typescript-eslint/naming-convention var MSFT_sRGBFactors = /** @class */ (function () { /** @internal */ function MSFT_sRGBFactors(loader) { /** @internal */ this.name = NAME; this._loader = loader; this.enabled = this._loader.isExtensionUsed(NAME); } /** @internal */ MSFT_sRGBFactors.prototype.dispose = function () { this._loader = null; }; /** @internal */ MSFT_sRGBFactors.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var _this = this; return _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.LoadExtraAsync(context, material, this.name, function (extraContext, extra) { if (extra) { if (!(babylonMaterial instanceof babylonjs_Materials_PBR_pbrMaterial__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(extraContext, ": Material type not supported")); } var promise = _this._loader.loadMaterialPropertiesAsync(context, material, babylonMaterial); var useExactSrgbConversions = babylonMaterial.getScene().getEngine().useExactSrgbConversions; if (!babylonMaterial.albedoTexture) { babylonMaterial.albedoColor.toLinearSpaceToRef(babylonMaterial.albedoColor, useExactSrgbConversions); } if (!babylonMaterial.reflectivityTexture) { babylonMaterial.reflectivityColor.toLinearSpaceToRef(babylonMaterial.reflectivityColor, useExactSrgbConversions); } return promise; } return null; }); }; return MSFT_sRGBFactors; }()); _glTFLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoader.RegisterExtension(NAME, function (loader) { return new MSFT_sRGBFactors(loader); }); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/Extensions/index.ts": /*!*************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/Extensions/index.ts ***! \*************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ EXT_lights_image_based: () => (/* reexport safe */ _EXT_lights_image_based__WEBPACK_IMPORTED_MODULE_0__.EXT_lights_image_based), /* harmony export */ EXT_mesh_gpu_instancing: () => (/* reexport safe */ _EXT_mesh_gpu_instancing__WEBPACK_IMPORTED_MODULE_1__.EXT_mesh_gpu_instancing), /* harmony export */ EXT_meshopt_compression: () => (/* reexport safe */ _EXT_meshopt_compression__WEBPACK_IMPORTED_MODULE_2__.EXT_meshopt_compression), /* harmony export */ EXT_texture_webp: () => (/* reexport safe */ _EXT_texture_webp__WEBPACK_IMPORTED_MODULE_3__.EXT_texture_webp), /* harmony export */ ExtrasAsMetadata: () => (/* reexport safe */ _ExtrasAsMetadata__WEBPACK_IMPORTED_MODULE_28__.ExtrasAsMetadata), /* harmony export */ KHR_animation_pointer: () => (/* reexport safe */ _KHR_animation_pointer__WEBPACK_IMPORTED_MODULE_23__.KHR_animation_pointer), /* harmony export */ KHR_draco_mesh_compression: () => (/* reexport safe */ _KHR_draco_mesh_compression__WEBPACK_IMPORTED_MODULE_4__.KHR_draco_mesh_compression), /* harmony export */ KHR_lights: () => (/* reexport safe */ _KHR_lights_punctual__WEBPACK_IMPORTED_MODULE_5__.KHR_lights), /* harmony export */ KHR_materials_anisotropy: () => (/* reexport safe */ _KHR_materials_anisotropy__WEBPACK_IMPORTED_MODULE_10__.KHR_materials_anisotropy), /* harmony export */ KHR_materials_clearcoat: () => (/* reexport safe */ _KHR_materials_clearcoat__WEBPACK_IMPORTED_MODULE_8__.KHR_materials_clearcoat), /* harmony export */ KHR_materials_emissive_strength: () => (/* reexport safe */ _KHR_materials_emissive_strength__WEBPACK_IMPORTED_MODULE_11__.KHR_materials_emissive_strength), /* harmony export */ KHR_materials_ior: () => (/* reexport safe */ _KHR_materials_ior__WEBPACK_IMPORTED_MODULE_14__.KHR_materials_ior), /* harmony export */ KHR_materials_iridescence: () => (/* reexport safe */ _KHR_materials_iridescence__WEBPACK_IMPORTED_MODULE_9__.KHR_materials_iridescence), /* harmony export */ KHR_materials_pbrSpecularGlossiness: () => (/* reexport safe */ _KHR_materials_pbrSpecularGlossiness__WEBPACK_IMPORTED_MODULE_6__.KHR_materials_pbrSpecularGlossiness), /* harmony export */ KHR_materials_sheen: () => (/* reexport safe */ _KHR_materials_sheen__WEBPACK_IMPORTED_MODULE_12__.KHR_materials_sheen), /* harmony export */ KHR_materials_specular: () => (/* reexport safe */ _KHR_materials_specular__WEBPACK_IMPORTED_MODULE_13__.KHR_materials_specular), /* harmony export */ KHR_materials_translucency: () => (/* reexport safe */ _KHR_materials_translucency__WEBPACK_IMPORTED_MODULE_17__.KHR_materials_translucency), /* harmony export */ KHR_materials_transmission: () => (/* reexport safe */ _KHR_materials_transmission__WEBPACK_IMPORTED_MODULE_16__.KHR_materials_transmission), /* harmony export */ KHR_materials_unlit: () => (/* reexport safe */ _KHR_materials_unlit__WEBPACK_IMPORTED_MODULE_7__.KHR_materials_unlit), /* harmony export */ KHR_materials_variants: () => (/* reexport safe */ _KHR_materials_variants__WEBPACK_IMPORTED_MODULE_15__.KHR_materials_variants), /* harmony export */ KHR_materials_volume: () => (/* reexport safe */ _KHR_materials_volume__WEBPACK_IMPORTED_MODULE_18__.KHR_materials_volume), /* harmony export */ KHR_mesh_quantization: () => (/* reexport safe */ _KHR_mesh_quantization__WEBPACK_IMPORTED_MODULE_19__.KHR_mesh_quantization), /* harmony export */ KHR_texture_basisu: () => (/* reexport safe */ _KHR_texture_basisu__WEBPACK_IMPORTED_MODULE_20__.KHR_texture_basisu), /* harmony export */ KHR_texture_transform: () => (/* reexport safe */ _KHR_texture_transform__WEBPACK_IMPORTED_MODULE_21__.KHR_texture_transform), /* harmony export */ KHR_xmp_json_ld: () => (/* reexport safe */ _KHR_xmp_json_ld__WEBPACK_IMPORTED_MODULE_22__.KHR_xmp_json_ld), /* harmony export */ MSFT_audio_emitter: () => (/* reexport safe */ _MSFT_audio_emitter__WEBPACK_IMPORTED_MODULE_24__.MSFT_audio_emitter), /* harmony export */ MSFT_lod: () => (/* reexport safe */ _MSFT_lod__WEBPACK_IMPORTED_MODULE_25__.MSFT_lod), /* harmony export */ MSFT_minecraftMesh: () => (/* reexport safe */ _MSFT_minecraftMesh__WEBPACK_IMPORTED_MODULE_26__.MSFT_minecraftMesh), /* harmony export */ MSFT_sRGBFactors: () => (/* reexport safe */ _MSFT_sRGBFactors__WEBPACK_IMPORTED_MODULE_27__.MSFT_sRGBFactors) /* harmony export */ }); /* harmony import */ var _EXT_lights_image_based__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./EXT_lights_image_based */ "../../../dev/loaders/src/glTF/2.0/Extensions/EXT_lights_image_based.ts"); /* harmony import */ var _EXT_mesh_gpu_instancing__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./EXT_mesh_gpu_instancing */ "../../../dev/loaders/src/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.ts"); /* harmony import */ var _EXT_meshopt_compression__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./EXT_meshopt_compression */ "../../../dev/loaders/src/glTF/2.0/Extensions/EXT_meshopt_compression.ts"); /* harmony import */ var _EXT_texture_webp__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./EXT_texture_webp */ "../../../dev/loaders/src/glTF/2.0/Extensions/EXT_texture_webp.ts"); /* harmony import */ var _KHR_draco_mesh_compression__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./KHR_draco_mesh_compression */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_draco_mesh_compression.ts"); /* harmony import */ var _KHR_lights_punctual__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./KHR_lights_punctual */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_lights_punctual.ts"); /* harmony import */ var _KHR_materials_pbrSpecularGlossiness__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! ./KHR_materials_pbrSpecularGlossiness */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_pbrSpecularGlossiness.ts"); /* harmony import */ var _KHR_materials_unlit__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! ./KHR_materials_unlit */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_unlit.ts"); /* harmony import */ var _KHR_materials_clearcoat__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! ./KHR_materials_clearcoat */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_clearcoat.ts"); /* harmony import */ var _KHR_materials_iridescence__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! ./KHR_materials_iridescence */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_iridescence.ts"); /* harmony import */ var _KHR_materials_anisotropy__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! ./KHR_materials_anisotropy */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_anisotropy.ts"); /* harmony import */ var _KHR_materials_emissive_strength__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! ./KHR_materials_emissive_strength */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_emissive_strength.ts"); /* harmony import */ var _KHR_materials_sheen__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! ./KHR_materials_sheen */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_sheen.ts"); /* harmony import */ var _KHR_materials_specular__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! ./KHR_materials_specular */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_specular.ts"); /* harmony import */ var _KHR_materials_ior__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! ./KHR_materials_ior */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_ior.ts"); /* harmony import */ var _KHR_materials_variants__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! ./KHR_materials_variants */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_variants.ts"); /* harmony import */ var _KHR_materials_transmission__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! ./KHR_materials_transmission */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_transmission.ts"); /* harmony import */ var _KHR_materials_translucency__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! ./KHR_materials_translucency */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_translucency.ts"); /* harmony import */ var _KHR_materials_volume__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! ./KHR_materials_volume */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_materials_volume.ts"); /* harmony import */ var _KHR_mesh_quantization__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! ./KHR_mesh_quantization */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_mesh_quantization.ts"); /* harmony import */ var _KHR_texture_basisu__WEBPACK_IMPORTED_MODULE_20__ = __webpack_require__(/*! ./KHR_texture_basisu */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_texture_basisu.ts"); /* harmony import */ var _KHR_texture_transform__WEBPACK_IMPORTED_MODULE_21__ = __webpack_require__(/*! ./KHR_texture_transform */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_texture_transform.ts"); /* harmony import */ var _KHR_xmp_json_ld__WEBPACK_IMPORTED_MODULE_22__ = __webpack_require__(/*! ./KHR_xmp_json_ld */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_xmp_json_ld.ts"); /* harmony import */ var _KHR_animation_pointer__WEBPACK_IMPORTED_MODULE_23__ = __webpack_require__(/*! ./KHR_animation_pointer */ "../../../dev/loaders/src/glTF/2.0/Extensions/KHR_animation_pointer.ts"); /* harmony import */ var _MSFT_audio_emitter__WEBPACK_IMPORTED_MODULE_24__ = __webpack_require__(/*! ./MSFT_audio_emitter */ "../../../dev/loaders/src/glTF/2.0/Extensions/MSFT_audio_emitter.ts"); /* harmony import */ var _MSFT_lod__WEBPACK_IMPORTED_MODULE_25__ = __webpack_require__(/*! ./MSFT_lod */ "../../../dev/loaders/src/glTF/2.0/Extensions/MSFT_lod.ts"); /* harmony import */ var _MSFT_minecraftMesh__WEBPACK_IMPORTED_MODULE_26__ = __webpack_require__(/*! ./MSFT_minecraftMesh */ "../../../dev/loaders/src/glTF/2.0/Extensions/MSFT_minecraftMesh.ts"); /* harmony import */ var _MSFT_sRGBFactors__WEBPACK_IMPORTED_MODULE_27__ = __webpack_require__(/*! ./MSFT_sRGBFactors */ "../../../dev/loaders/src/glTF/2.0/Extensions/MSFT_sRGBFactors.ts"); /* harmony import */ var _ExtrasAsMetadata__WEBPACK_IMPORTED_MODULE_28__ = __webpack_require__(/*! ./ExtrasAsMetadata */ "../../../dev/loaders/src/glTF/2.0/Extensions/ExtrasAsMetadata.ts"); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts": /*!*******************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/glTFLoader.ts ***! \*******************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ArrayItem: () => (/* binding */ ArrayItem), /* harmony export */ GLTFLoader: () => (/* binding */ GLTFLoader) /* harmony export */ }); /* harmony import */ var babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Culling/boundingInfo */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../glTFFileLoader */ "../../../dev/loaders/src/glTF/glTFFileLoader.ts"); /* harmony import */ var _glTFLoaderAnimation__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./glTFLoaderAnimation */ "../../../dev/loaders/src/glTF/2.0/glTFLoaderAnimation.ts"); // https://stackoverflow.com/a/48218209 function mergeDeep() { var objects = []; for (var _i = 0; _i < arguments.length; _i++) { objects[_i] = arguments[_i]; } var isObject = function (obj) { return obj && typeof obj === "object"; }; return objects.reduce(function (prev, obj) { Object.keys(obj).forEach(function (key) { var pVal = prev[key]; var oVal = obj[key]; if (Array.isArray(pVal) && Array.isArray(oVal)) { prev[key] = pVal.concat.apply(pVal, oVal); } else if (isObject(pVal) && isObject(oVal)) { prev[key] = mergeDeep(pVal, oVal); } else { prev[key] = oVal; } }); return prev; }, {}); } /** * Helper class for working with arrays when loading the glTF asset */ var ArrayItem = /** @class */ (function () { function ArrayItem() { } /** * Gets an item from the given array. * @param context The context when loading the asset * @param array The array to get the item from * @param index The index to the array * @returns The array item */ ArrayItem.Get = function (context, array, index) { if (!array || index == undefined || !array[index]) { throw new Error("".concat(context, ": Failed to find index (").concat(index, ")")); } return array[index]; }; /** * Gets an item from the given array or returns null if not available. * @param array The array to get the item from * @param index The index to the array * @returns The array item or null */ ArrayItem.TryGet = function (array, index) { if (!array || index == undefined || !array[index]) { return null; } return array[index]; }; /** * Assign an `index` field to each item of the given array. * @param array The array of items */ ArrayItem.Assign = function (array) { if (array) { for (var index = 0; index < array.length; index++) { array[index].index = index; } } }; return ArrayItem; }()); /** * The glTF 2.0 loader */ var GLTFLoader = /** @class */ (function () { /** * @internal */ function GLTFLoader(parent) { /** @internal */ this._completePromises = new Array(); /** @internal */ this._assetContainer = null; /** Storage */ this._babylonLights = []; /** @internal */ this._disableInstancedMesh = 0; /** @internal */ this._allMaterialsDirtyRequired = false; this._extensions = new Array(); this._disposed = false; this._rootUrl = null; this._fileName = null; this._uniqueRootUrl = null; this._bin = null; this._rootBabylonMesh = null; this._defaultBabylonMaterialData = {}; this._postSceneLoadActions = new Array(); this._parent = parent; } /** * Registers a loader extension. * @param name The name of the loader extension. * @param factory The factory function that creates the loader extension. */ GLTFLoader.RegisterExtension = function (name, factory) { if (GLTFLoader.UnregisterExtension(name)) { babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("Extension with the name '".concat(name, "' already exists")); } GLTFLoader._RegisteredExtensions[name] = { factory: factory, }; }; /** * Unregisters a loader extension. * @param name The name of the loader extension. * @returns A boolean indicating whether the extension has been unregistered */ GLTFLoader.UnregisterExtension = function (name) { if (!GLTFLoader._RegisteredExtensions[name]) { return false; } delete GLTFLoader._RegisteredExtensions[name]; return true; }; Object.defineProperty(GLTFLoader.prototype, "gltf", { /** * The object that represents the glTF JSON. */ get: function () { if (!this._gltf) { throw new Error("glTF JSON is not available"); } return this._gltf; }, enumerable: false, configurable: true }); Object.defineProperty(GLTFLoader.prototype, "bin", { /** * The BIN chunk of a binary glTF. */ get: function () { return this._bin; }, enumerable: false, configurable: true }); Object.defineProperty(GLTFLoader.prototype, "parent", { /** * The parent file loader. */ get: function () { return this._parent; }, enumerable: false, configurable: true }); Object.defineProperty(GLTFLoader.prototype, "babylonScene", { /** * The Babylon scene when loading the asset. */ get: function () { if (!this._babylonScene) { throw new Error("Scene is not available"); } return this._babylonScene; }, enumerable: false, configurable: true }); Object.defineProperty(GLTFLoader.prototype, "rootBabylonMesh", { /** * The root Babylon mesh when loading the asset. */ get: function () { return this._rootBabylonMesh; }, enumerable: false, configurable: true }); /** @internal */ GLTFLoader.prototype.dispose = function () { if (this._disposed) { return; } this._disposed = true; this._completePromises.length = 0; this._extensions.forEach(function (extension) { return extension.dispose && extension.dispose(); }); this._extensions.length = 0; this._gltf = null; // TODO this._bin = null; this._babylonScene = null; // TODO this._rootBabylonMesh = null; this._defaultBabylonMaterialData = {}; this._postSceneLoadActions.length = 0; this._parent.dispose(); }; /** * @internal */ GLTFLoader.prototype.importMeshAsync = function (meshesNames, scene, container, data, rootUrl, onProgress, fileName) { var _this = this; if (fileName === void 0) { fileName = ""; } return Promise.resolve().then(function () { _this._babylonScene = scene; _this._assetContainer = container; _this._loadData(data); var nodes = null; if (meshesNames) { var nodeMap_1 = {}; if (_this._gltf.nodes) { for (var _i = 0, _a = _this._gltf.nodes; _i < _a.length; _i++) { var node = _a[_i]; if (node.name) { nodeMap_1[node.name] = node.index; } } } var names = meshesNames instanceof Array ? meshesNames : [meshesNames]; nodes = names.map(function (name) { var node = nodeMap_1[name]; if (node === undefined) { throw new Error("Failed to find node '".concat(name, "'")); } return node; }); } return _this._loadAsync(rootUrl, fileName, nodes, function () { return { meshes: _this._getMeshes(), particleSystems: [], skeletons: _this._getSkeletons(), animationGroups: _this._getAnimationGroups(), lights: _this._babylonLights, transformNodes: _this._getTransformNodes(), geometries: _this._getGeometries(), }; }); }); }; /** * @internal */ GLTFLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fileName) { var _this = this; if (fileName === void 0) { fileName = ""; } return Promise.resolve().then(function () { _this._babylonScene = scene; _this._loadData(data); return _this._loadAsync(rootUrl, fileName, null, function () { return undefined; }); }); }; GLTFLoader.prototype._loadAsync = function (rootUrl, fileName, nodes, resultFunc) { var _this = this; return Promise.resolve() .then(function () { _this._rootUrl = rootUrl; _this._uniqueRootUrl = !rootUrl.startsWith("file:") && fileName ? rootUrl : "".concat(rootUrl).concat(Date.now(), "/"); _this._fileName = fileName; _this._allMaterialsDirtyRequired = false; _this._loadExtensions(); _this._checkExtensions(); var loadingToReadyCounterName = "".concat(_glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderState[_glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderState.LOADING], " => ").concat(_glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderState[_glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderState.READY]); var loadingToCompleteCounterName = "".concat(_glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderState[_glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderState.LOADING], " => ").concat(_glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderState[_glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderState.COMPLETE]); _this._parent._startPerformanceCounter(loadingToReadyCounterName); _this._parent._startPerformanceCounter(loadingToCompleteCounterName); _this._parent._setState(_glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderState.LOADING); _this._extensionsOnLoading(); var promises = new Array(); // Block the marking of materials dirty until the scene is loaded. var oldBlockMaterialDirtyMechanism = _this._babylonScene.blockMaterialDirtyMechanism; _this._babylonScene.blockMaterialDirtyMechanism = true; if (!_this.parent.loadOnlyMaterials) { if (nodes) { promises.push(_this.loadSceneAsync("/nodes", { nodes: nodes, index: -1 })); } else if (_this._gltf.scene != undefined || (_this._gltf.scenes && _this._gltf.scenes[0])) { var scene = ArrayItem.Get("/scene", _this._gltf.scenes, _this._gltf.scene || 0); promises.push(_this.loadSceneAsync("/scenes/".concat(scene.index), scene)); } } if (!_this.parent.skipMaterials && _this.parent.loadAllMaterials && _this._gltf.materials) { for (var m = 0; m < _this._gltf.materials.length; ++m) { var material = _this._gltf.materials[m]; var context_1 = "/materials/" + m; var babylonDrawMode = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Material.TriangleFillMode; promises.push(_this._loadMaterialAsync(context_1, material, null, babylonDrawMode, function () { })); } } // Restore the blocking of material dirty. if (_this._allMaterialsDirtyRequired) { // This can happen if we add a light for instance as it will impact the whole scene. // This automatically resets everything if needed. _this._babylonScene.blockMaterialDirtyMechanism = oldBlockMaterialDirtyMechanism; } else { // By default a newly created material is dirty so there is no need to flag the full scene as dirty. // For perf reasons, we then bypass blockMaterialDirtyMechanism as this would "dirty" the entire scene. _this._babylonScene._forceBlockMaterialDirtyMechanism(oldBlockMaterialDirtyMechanism); } if (_this._parent.compileMaterials) { promises.push(_this._compileMaterialsAsync()); } if (_this._parent.compileShadowGenerators) { promises.push(_this._compileShadowGeneratorsAsync()); } var resultPromise = Promise.all(promises).then(function () { if (_this._rootBabylonMesh) { _this._rootBabylonMesh.setEnabled(true); } _this._extensionsOnReady(); _this._parent._setState(_glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderState.READY); _this._startAnimations(); return resultFunc(); }); return resultPromise.then(function (result) { _this._parent._endPerformanceCounter(loadingToReadyCounterName); babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Tools.SetImmediate(function () { if (!_this._disposed) { Promise.all(_this._completePromises).then(function () { _this._parent._endPerformanceCounter(loadingToCompleteCounterName); _this._parent._setState(_glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderState.COMPLETE); _this._parent.onCompleteObservable.notifyObservers(undefined); _this._parent.onCompleteObservable.clear(); _this.dispose(); }, function (error) { _this._parent.onErrorObservable.notifyObservers(error); _this._parent.onErrorObservable.clear(); _this.dispose(); }); } }); return result; }); }) .catch(function (error) { if (!_this._disposed) { _this._parent.onErrorObservable.notifyObservers(error); _this._parent.onErrorObservable.clear(); _this.dispose(); } throw error; }); }; GLTFLoader.prototype._loadData = function (data) { this._gltf = data.json; this._setupData(); if (data.bin) { var buffers = this._gltf.buffers; if (buffers && buffers[0] && !buffers[0].uri) { var binaryBuffer = buffers[0]; if (binaryBuffer.byteLength < data.bin.byteLength - 3 || binaryBuffer.byteLength > data.bin.byteLength) { babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("Binary buffer length (".concat(binaryBuffer.byteLength, ") from JSON does not match chunk length (").concat(data.bin.byteLength, ")")); } this._bin = data.bin; } else { babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("Unexpected BIN chunk"); } } }; GLTFLoader.prototype._setupData = function () { ArrayItem.Assign(this._gltf.accessors); ArrayItem.Assign(this._gltf.animations); ArrayItem.Assign(this._gltf.buffers); ArrayItem.Assign(this._gltf.bufferViews); ArrayItem.Assign(this._gltf.cameras); ArrayItem.Assign(this._gltf.images); ArrayItem.Assign(this._gltf.materials); ArrayItem.Assign(this._gltf.meshes); ArrayItem.Assign(this._gltf.nodes); ArrayItem.Assign(this._gltf.samplers); ArrayItem.Assign(this._gltf.scenes); ArrayItem.Assign(this._gltf.skins); ArrayItem.Assign(this._gltf.textures); if (this._gltf.nodes) { var nodeParents = {}; for (var _i = 0, _a = this._gltf.nodes; _i < _a.length; _i++) { var node = _a[_i]; if (node.children) { for (var _b = 0, _c = node.children; _b < _c.length; _b++) { var index = _c[_b]; nodeParents[index] = node.index; } } } var rootNode = this._createRootNode(); for (var _d = 0, _e = this._gltf.nodes; _d < _e.length; _d++) { var node = _e[_d]; var parentIndex = nodeParents[node.index]; node.parent = parentIndex === undefined ? rootNode : this._gltf.nodes[parentIndex]; } } }; GLTFLoader.prototype._loadExtensions = function () { for (var name_1 in GLTFLoader._RegisteredExtensions) { var extension = GLTFLoader._RegisteredExtensions[name_1].factory(this); if (extension.name !== name_1) { babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("The name of the glTF loader extension instance does not match the registered name: ".concat(extension.name, " !== ").concat(name_1)); } this._extensions.push(extension); this._parent.onExtensionLoadedObservable.notifyObservers(extension); } this._extensions.sort(function (a, b) { return (a.order || Number.MAX_VALUE) - (b.order || Number.MAX_VALUE); }); this._parent.onExtensionLoadedObservable.clear(); }; GLTFLoader.prototype._checkExtensions = function () { if (this._gltf.extensionsRequired) { var _loop_1 = function (name_2) { var available = this_1._extensions.some(function (extension) { return extension.name === name_2 && extension.enabled; }); if (!available) { throw new Error("Require extension ".concat(name_2, " is not available")); } }; var this_1 = this; for (var _i = 0, _a = this._gltf.extensionsRequired; _i < _a.length; _i++) { var name_2 = _a[_i]; _loop_1(name_2); } } }; GLTFLoader.prototype._createRootNode = function () { this._babylonScene._blockEntityCollection = !!this._assetContainer; this._rootBabylonMesh = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Mesh("__root__", this._babylonScene); this._rootBabylonMesh._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; this._rootBabylonMesh.setEnabled(false); var rootNode = { _babylonTransformNode: this._rootBabylonMesh, index: -1, }; switch (this._parent.coordinateSystemMode) { case _glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderCoordinateSystemMode.AUTO: { if (!this._babylonScene.useRightHandedSystem) { rootNode.rotation = [0, 1, 0, 0]; rootNode.scale = [1, 1, -1]; GLTFLoader._LoadTransform(rootNode, this._rootBabylonMesh); } break; } case _glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderCoordinateSystemMode.FORCE_RIGHT_HANDED: { this._babylonScene.useRightHandedSystem = true; break; } default: { throw new Error("Invalid coordinate system mode (".concat(this._parent.coordinateSystemMode, ")")); } } this._parent.onMeshLoadedObservable.notifyObservers(this._rootBabylonMesh); return rootNode; }; /** * Loads a glTF scene. * @param context The context when loading the asset * @param scene The glTF scene property * @returns A promise that resolves when the load is complete */ GLTFLoader.prototype.loadSceneAsync = function (context, scene) { var _this = this; var extensionPromise = this._extensionsLoadSceneAsync(context, scene); if (extensionPromise) { return extensionPromise; } var promises = new Array(); this.logOpen("".concat(context, " ").concat(scene.name || "")); if (scene.nodes) { for (var _i = 0, _a = scene.nodes; _i < _a.length; _i++) { var index = _a[_i]; var node = ArrayItem.Get("".concat(context, "/nodes/").concat(index), this._gltf.nodes, index); promises.push(this.loadNodeAsync("/nodes/".concat(node.index), node, function (babylonMesh) { babylonMesh.parent = _this._rootBabylonMesh; })); } } for (var _b = 0, _c = this._postSceneLoadActions; _b < _c.length; _b++) { var action = _c[_b]; action(); } promises.push(this._loadAnimationsAsync()); this.logClose(); return Promise.all(promises).then(function () { }); }; GLTFLoader.prototype._forEachPrimitive = function (node, callback) { if (node._primitiveBabylonMeshes) { for (var _i = 0, _a = node._primitiveBabylonMeshes; _i < _a.length; _i++) { var babylonMesh = _a[_i]; callback(babylonMesh); } } }; GLTFLoader.prototype._getGeometries = function () { var geometries = new Array(); var nodes = this._gltf.nodes; if (nodes) { for (var _i = 0, nodes_1 = nodes; _i < nodes_1.length; _i++) { var node = nodes_1[_i]; this._forEachPrimitive(node, function (babylonMesh) { var geometry = babylonMesh.geometry; if (geometry && geometries.indexOf(geometry) === -1) { geometries.push(geometry); } }); } } return geometries; }; GLTFLoader.prototype._getMeshes = function () { var meshes = new Array(); // Root mesh is always first, if available. if (this._rootBabylonMesh) { meshes.push(this._rootBabylonMesh); } var nodes = this._gltf.nodes; if (nodes) { for (var _i = 0, nodes_2 = nodes; _i < nodes_2.length; _i++) { var node = nodes_2[_i]; this._forEachPrimitive(node, function (babylonMesh) { meshes.push(babylonMesh); }); } } return meshes; }; GLTFLoader.prototype._getTransformNodes = function () { var transformNodes = new Array(); var nodes = this._gltf.nodes; if (nodes) { for (var _i = 0, nodes_3 = nodes; _i < nodes_3.length; _i++) { var node = nodes_3[_i]; if (node._babylonTransformNode && node._babylonTransformNode.getClassName() === "TransformNode") { transformNodes.push(node._babylonTransformNode); } if (node._babylonTransformNodeForSkin) { transformNodes.push(node._babylonTransformNodeForSkin); } } } return transformNodes; }; GLTFLoader.prototype._getSkeletons = function () { var skeletons = new Array(); var skins = this._gltf.skins; if (skins) { for (var _i = 0, skins_1 = skins; _i < skins_1.length; _i++) { var skin = skins_1[_i]; if (skin._data) { skeletons.push(skin._data.babylonSkeleton); } } } return skeletons; }; GLTFLoader.prototype._getAnimationGroups = function () { var animationGroups = new Array(); var animations = this._gltf.animations; if (animations) { for (var _i = 0, animations_1 = animations; _i < animations_1.length; _i++) { var animation = animations_1[_i]; if (animation._babylonAnimationGroup) { animationGroups.push(animation._babylonAnimationGroup); } } } return animationGroups; }; GLTFLoader.prototype._startAnimations = function () { switch (this._parent.animationStartMode) { case _glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderAnimationStartMode.NONE: { // do nothing break; } case _glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderAnimationStartMode.FIRST: { var babylonAnimationGroups = this._getAnimationGroups(); if (babylonAnimationGroups.length !== 0) { babylonAnimationGroups[0].start(true); } break; } case _glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFLoaderAnimationStartMode.ALL: { var babylonAnimationGroups = this._getAnimationGroups(); for (var _i = 0, babylonAnimationGroups_1 = babylonAnimationGroups; _i < babylonAnimationGroups_1.length; _i++) { var babylonAnimationGroup = babylonAnimationGroups_1[_i]; babylonAnimationGroup.start(true); } break; } default: { babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Logger.Error("Invalid animation start mode (".concat(this._parent.animationStartMode, ")")); return; } } }; /** * Loads a glTF node. * @param context The context when loading the asset * @param node The glTF node property * @param assign A function called synchronously after parsing the glTF properties * @returns A promise that resolves with the loaded Babylon mesh when the load is complete */ GLTFLoader.prototype.loadNodeAsync = function (context, node, assign) { var _this = this; if (assign === void 0) { assign = function () { }; } var extensionPromise = this._extensionsLoadNodeAsync(context, node, assign); if (extensionPromise) { return extensionPromise; } if (node._babylonTransformNode) { throw new Error("".concat(context, ": Invalid recursive node hierarchy")); } var promises = new Array(); this.logOpen("".concat(context, " ").concat(node.name || "")); var loadNode = function (babylonTransformNode) { GLTFLoader.AddPointerMetadata(babylonTransformNode, context); GLTFLoader._LoadTransform(node, babylonTransformNode); if (node.camera != undefined) { var camera = ArrayItem.Get("".concat(context, "/camera"), _this._gltf.cameras, node.camera); promises.push(_this.loadCameraAsync("/cameras/".concat(camera.index), camera, function (babylonCamera) { babylonCamera.parent = babylonTransformNode; })); } if (node.children) { for (var _i = 0, _a = node.children; _i < _a.length; _i++) { var index = _a[_i]; var childNode = ArrayItem.Get("".concat(context, "/children/").concat(index), _this._gltf.nodes, index); promises.push(_this.loadNodeAsync("/nodes/".concat(childNode.index), childNode, function (childBabylonMesh) { childBabylonMesh.parent = babylonTransformNode; })); } } assign(babylonTransformNode); }; if (node.mesh == undefined || node.skin != undefined) { var nodeName = node.name || "node".concat(node.index); this._babylonScene._blockEntityCollection = !!this._assetContainer; var transformNode = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.TransformNode(nodeName, this._babylonScene); transformNode._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; if (node.mesh == undefined) { node._babylonTransformNode = transformNode; } else { node._babylonTransformNodeForSkin = transformNode; } loadNode(transformNode); } if (node.mesh != undefined) { if (node.skin == undefined) { var mesh = ArrayItem.Get("".concat(context, "/mesh"), this._gltf.meshes, node.mesh); promises.push(this._loadMeshAsync("/meshes/".concat(mesh.index), node, mesh, loadNode)); } else { // See https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins (second implementation note) // This code path will place the skinned mesh as a sibling of the skeleton root node without loading the // transform, which effectively ignores the transform of the skinned mesh, as per spec. var mesh = ArrayItem.Get("".concat(context, "/mesh"), this._gltf.meshes, node.mesh); promises.push(this._loadMeshAsync("/meshes/".concat(mesh.index), node, mesh, function (babylonTransformNode) { var babylonTransformNodeForSkin = node._babylonTransformNodeForSkin; // Merge the metadata from the skin node to the skinned mesh in case a loader extension added metadata. babylonTransformNode.metadata = mergeDeep(babylonTransformNodeForSkin.metadata, babylonTransformNode.metadata || {}); var skin = ArrayItem.Get("".concat(context, "/skin"), _this._gltf.skins, node.skin); promises.push(_this._loadSkinAsync("/skins/".concat(skin.index), node, skin, function (babylonSkeleton) { _this._forEachPrimitive(node, function (babylonMesh) { babylonMesh.skeleton = babylonSkeleton; }); // Wait until all the nodes are parented before parenting the skinned mesh. _this._postSceneLoadActions.push(function () { if (skin.skeleton != undefined) { // Place the skinned mesh node as a sibling of the skeleton root node. // Handle special case when the parent of the skeleton root is the skinned mesh. var parentNode = ArrayItem.Get("/skins/".concat(skin.index, "/skeleton"), _this._gltf.nodes, skin.skeleton).parent; if (node.index === parentNode.index) { babylonTransformNode.parent = babylonTransformNodeForSkin.parent; } else { babylonTransformNode.parent = parentNode._babylonTransformNode; } } else { babylonTransformNode.parent = _this._rootBabylonMesh; } _this._parent.onSkinLoadedObservable.notifyObservers({ node: babylonTransformNodeForSkin, skinnedNode: babylonTransformNode }); }); })); })); } } this.logClose(); return Promise.all(promises).then(function () { _this._forEachPrimitive(node, function (babylonMesh) { if (babylonMesh.geometry && babylonMesh.geometry.useBoundingInfoFromGeometry) { // simply apply the world matrices to the bounding info - the extends are already ok babylonMesh._updateBoundingInfo(); } else { babylonMesh.refreshBoundingInfo(true); } }); return node._babylonTransformNode; }); }; GLTFLoader.prototype._loadMeshAsync = function (context, node, mesh, assign) { var primitives = mesh.primitives; if (!primitives || !primitives.length) { throw new Error("".concat(context, ": Primitives are missing")); } if (primitives[0].index == undefined) { ArrayItem.Assign(primitives); } var promises = new Array(); this.logOpen("".concat(context, " ").concat(mesh.name || "")); var name = node.name || "node".concat(node.index); if (primitives.length === 1) { var primitive = mesh.primitives[0]; promises.push(this._loadMeshPrimitiveAsync("".concat(context, "/primitives/").concat(primitive.index), name, node, mesh, primitive, function (babylonMesh) { node._babylonTransformNode = babylonMesh; node._primitiveBabylonMeshes = [babylonMesh]; })); } else { this._babylonScene._blockEntityCollection = !!this._assetContainer; node._babylonTransformNode = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.TransformNode(name, this._babylonScene); node._babylonTransformNode._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; node._primitiveBabylonMeshes = []; for (var _i = 0, primitives_1 = primitives; _i < primitives_1.length; _i++) { var primitive = primitives_1[_i]; promises.push(this._loadMeshPrimitiveAsync("".concat(context, "/primitives/").concat(primitive.index), "".concat(name, "_primitive").concat(primitive.index), node, mesh, primitive, function (babylonMesh) { babylonMesh.parent = node._babylonTransformNode; node._primitiveBabylonMeshes.push(babylonMesh); })); } } assign(node._babylonTransformNode); this.logClose(); return Promise.all(promises).then(function () { return node._babylonTransformNode; }); }; /** * @internal Define this method to modify the default behavior when loading data for mesh primitives. * @param context The context when loading the asset * @param name The mesh name when loading the asset * @param node The glTF node when loading the asset * @param mesh The glTF mesh when loading the asset * @param primitive The glTF mesh primitive property * @param assign A function called synchronously after parsing the glTF properties * @returns A promise that resolves with the loaded mesh when the load is complete or null if not handled */ GLTFLoader.prototype._loadMeshPrimitiveAsync = function (context, name, node, mesh, primitive, assign) { var _this = this; var extensionPromise = this._extensionsLoadMeshPrimitiveAsync(context, name, node, mesh, primitive, assign); if (extensionPromise) { return extensionPromise; } this.logOpen("".concat(context)); var shouldInstance = this._disableInstancedMesh === 0 && this._parent.createInstances && node.skin == undefined && !mesh.primitives[0].targets; var babylonAbstractMesh; var promise; if (shouldInstance && primitive._instanceData) { this._babylonScene._blockEntityCollection = !!this._assetContainer; babylonAbstractMesh = primitive._instanceData.babylonSourceMesh.createInstance(name); babylonAbstractMesh._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; promise = primitive._instanceData.promise; } else { var promises = new Array(); this._babylonScene._blockEntityCollection = !!this._assetContainer; var babylonMesh_1 = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Mesh(name, this._babylonScene); babylonMesh_1._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; babylonMesh_1.overrideMaterialSideOrientation = this._babylonScene.useRightHandedSystem ? babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Material.CounterClockWiseSideOrientation : babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Material.ClockWiseSideOrientation; this._createMorphTargets(context, node, mesh, primitive, babylonMesh_1); promises.push(this._loadVertexDataAsync(context, primitive, babylonMesh_1).then(function (babylonGeometry) { return _this._loadMorphTargetsAsync(context, primitive, babylonMesh_1, babylonGeometry).then(function () { if (_this._disposed) { return; } _this._babylonScene._blockEntityCollection = !!_this._assetContainer; babylonGeometry.applyToMesh(babylonMesh_1); babylonGeometry._parentContainer = _this._assetContainer; _this._babylonScene._blockEntityCollection = false; }); })); var babylonDrawMode = GLTFLoader._GetDrawMode(context, primitive.mode); if (primitive.material == undefined) { var babylonMaterial = this._defaultBabylonMaterialData[babylonDrawMode]; if (!babylonMaterial) { babylonMaterial = this._createDefaultMaterial("__GLTFLoader._default", babylonDrawMode); this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial); this._defaultBabylonMaterialData[babylonDrawMode] = babylonMaterial; } babylonMesh_1.material = babylonMaterial; } else if (!this.parent.skipMaterials) { var material = ArrayItem.Get("".concat(context, "/material"), this._gltf.materials, primitive.material); promises.push(this._loadMaterialAsync("/materials/".concat(material.index), material, babylonMesh_1, babylonDrawMode, function (babylonMaterial) { babylonMesh_1.material = babylonMaterial; })); } promise = Promise.all(promises); if (shouldInstance) { primitive._instanceData = { babylonSourceMesh: babylonMesh_1, promise: promise, }; } babylonAbstractMesh = babylonMesh_1; } GLTFLoader.AddPointerMetadata(babylonAbstractMesh, context); this._parent.onMeshLoadedObservable.notifyObservers(babylonAbstractMesh); assign(babylonAbstractMesh); this.logClose(); return promise.then(function () { return babylonAbstractMesh; }); }; GLTFLoader.prototype._loadVertexDataAsync = function (context, primitive, babylonMesh) { var _this = this; var extensionPromise = this._extensionsLoadVertexDataAsync(context, primitive, babylonMesh); if (extensionPromise) { return extensionPromise; } var attributes = primitive.attributes; if (!attributes) { throw new Error("".concat(context, ": Attributes are missing")); } var promises = new Array(); var babylonGeometry = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Geometry(babylonMesh.name, this._babylonScene); if (primitive.indices == undefined) { babylonMesh.isUnIndexed = true; } else { var accessor = ArrayItem.Get("".concat(context, "/indices"), this._gltf.accessors, primitive.indices); promises.push(this._loadIndicesAccessorAsync("/accessors/".concat(accessor.index), accessor).then(function (data) { babylonGeometry.setIndices(data); })); } var loadAttribute = function (name, kind, callback) { if (attributes[name] == undefined) { return; } babylonMesh._delayInfo = babylonMesh._delayInfo || []; if (babylonMesh._delayInfo.indexOf(kind) === -1) { babylonMesh._delayInfo.push(kind); } var accessor = ArrayItem.Get("".concat(context, "/attributes/").concat(name), _this._gltf.accessors, attributes[name]); promises.push(_this._loadVertexAccessorAsync("/accessors/".concat(accessor.index), accessor, kind).then(function (babylonVertexBuffer) { var _a, _b; if (babylonVertexBuffer.getKind() === babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.PositionKind && !_this.parent.alwaysComputeBoundingBox && !babylonMesh.skeleton) { if (accessor.min && accessor.max) { var min = (_a = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.TmpVectors.Vector3[0]).copyFromFloats.apply(_a, accessor.min); var max = (_b = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.TmpVectors.Vector3[1]).copyFromFloats.apply(_b, accessor.max); if (accessor.normalized && accessor.componentType !== 5126 /* AccessorComponentType.FLOAT */) { var divider = 1; switch (accessor.componentType) { case 5120 /* AccessorComponentType.BYTE */: divider = 127.0; break; case 5121 /* AccessorComponentType.UNSIGNED_BYTE */: divider = 255.0; break; case 5122 /* AccessorComponentType.SHORT */: divider = 32767.0; break; case 5123 /* AccessorComponentType.UNSIGNED_SHORT */: divider = 65535.0; break; } var oneOverDivider = 1 / divider; min.scaleInPlace(oneOverDivider); max.scaleInPlace(oneOverDivider); } babylonGeometry._boundingInfo = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.BoundingInfo(min, max); babylonGeometry.useBoundingInfoFromGeometry = true; } } babylonGeometry.setVerticesBuffer(babylonVertexBuffer, accessor.count); })); if (kind == babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.MatricesIndicesExtraKind) { babylonMesh.numBoneInfluencers = 8; } if (callback) { callback(accessor); } }; loadAttribute("POSITION", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.PositionKind); loadAttribute("NORMAL", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.NormalKind); loadAttribute("TANGENT", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.TangentKind); loadAttribute("TEXCOORD_0", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.UVKind); loadAttribute("TEXCOORD_1", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.UV2Kind); loadAttribute("TEXCOORD_2", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.UV3Kind); loadAttribute("TEXCOORD_3", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.UV4Kind); loadAttribute("TEXCOORD_4", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.UV5Kind); loadAttribute("TEXCOORD_5", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.UV6Kind); loadAttribute("JOINTS_0", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.MatricesIndicesKind); loadAttribute("WEIGHTS_0", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.MatricesWeightsKind); loadAttribute("JOINTS_1", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.MatricesIndicesExtraKind); loadAttribute("WEIGHTS_1", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.MatricesWeightsExtraKind); loadAttribute("COLOR_0", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.ColorKind, function (accessor) { if (accessor.type === "VEC4" /* AccessorType.VEC4 */) { babylonMesh.hasVertexAlpha = true; } }); return Promise.all(promises).then(function () { return babylonGeometry; }); }; GLTFLoader.prototype._createMorphTargets = function (context, node, mesh, primitive, babylonMesh) { if (!primitive.targets) { return; } if (node._numMorphTargets == undefined) { node._numMorphTargets = primitive.targets.length; } else if (primitive.targets.length !== node._numMorphTargets) { throw new Error("".concat(context, ": Primitives do not have the same number of targets")); } var targetNames = mesh.extras ? mesh.extras.targetNames : null; this._babylonScene._blockEntityCollection = !!this._assetContainer; babylonMesh.morphTargetManager = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.MorphTargetManager(this._babylonScene); babylonMesh.morphTargetManager._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; babylonMesh.morphTargetManager.areUpdatesFrozen = true; for (var index = 0; index < primitive.targets.length; index++) { var weight = node.weights ? node.weights[index] : mesh.weights ? mesh.weights[index] : 0; var name_3 = targetNames ? targetNames[index] : "morphTarget".concat(index); babylonMesh.morphTargetManager.addTarget(new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.MorphTarget(name_3, weight, babylonMesh.getScene())); // TODO: tell the target whether it has positions, normals, tangents } }; GLTFLoader.prototype._loadMorphTargetsAsync = function (context, primitive, babylonMesh, babylonGeometry) { if (!primitive.targets) { return Promise.resolve(); } var promises = new Array(); var morphTargetManager = babylonMesh.morphTargetManager; for (var index = 0; index < morphTargetManager.numTargets; index++) { var babylonMorphTarget = morphTargetManager.getTarget(index); promises.push(this._loadMorphTargetVertexDataAsync("".concat(context, "/targets/").concat(index), babylonGeometry, primitive.targets[index], babylonMorphTarget)); } return Promise.all(promises).then(function () { morphTargetManager.areUpdatesFrozen = false; }); }; GLTFLoader.prototype._loadMorphTargetVertexDataAsync = function (context, babylonGeometry, attributes, babylonMorphTarget) { var _this = this; var promises = new Array(); var loadAttribute = function (attribute, kind, setData) { if (attributes[attribute] == undefined) { return; } var babylonVertexBuffer = babylonGeometry.getVertexBuffer(kind); if (!babylonVertexBuffer) { return; } var accessor = ArrayItem.Get("".concat(context, "/").concat(attribute), _this._gltf.accessors, attributes[attribute]); promises.push(_this._loadFloatAccessorAsync("/accessors/".concat(accessor.index), accessor).then(function (data) { setData(babylonVertexBuffer, data); })); }; loadAttribute("POSITION", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.PositionKind, function (babylonVertexBuffer, data) { var positions = new Float32Array(data.length); babylonVertexBuffer.forEach(data.length, function (value, index) { positions[index] = data[index] + value; }); babylonMorphTarget.setPositions(positions); }); loadAttribute("NORMAL", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.NormalKind, function (babylonVertexBuffer, data) { var normals = new Float32Array(data.length); babylonVertexBuffer.forEach(normals.length, function (value, index) { normals[index] = data[index] + value; }); babylonMorphTarget.setNormals(normals); }); loadAttribute("TANGENT", babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.TangentKind, function (babylonVertexBuffer, data) { var tangents = new Float32Array((data.length / 3) * 4); var dataIndex = 0; babylonVertexBuffer.forEach((data.length / 3) * 4, function (value, index) { // Tangent data for morph targets is stored as xyz delta. // The vertexData.tangent is stored as xyzw. // So we need to skip every fourth vertexData.tangent. if ((index + 1) % 4 !== 0) { tangents[dataIndex] = data[dataIndex] + value; dataIndex++; } }); babylonMorphTarget.setTangents(tangents); }); return Promise.all(promises).then(function () { }); }; GLTFLoader._LoadTransform = function (node, babylonNode) { // Ignore the TRS of skinned nodes. // See https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#skins (second implementation note) if (node.skin != undefined) { return; } var position = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero(); var rotation = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Quaternion.Identity(); var scaling = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Vector3.One(); if (node.matrix) { var matrix = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Matrix.FromArray(node.matrix); matrix.decompose(scaling, rotation, position); } else { if (node.translation) { position = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Vector3.FromArray(node.translation); } if (node.rotation) { rotation = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Quaternion.FromArray(node.rotation); } if (node.scale) { scaling = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Vector3.FromArray(node.scale); } } babylonNode.position = position; babylonNode.rotationQuaternion = rotation; babylonNode.scaling = scaling; }; GLTFLoader.prototype._loadSkinAsync = function (context, node, skin, assign) { var _this = this; var extensionPromise = this._extensionsLoadSkinAsync(context, node, skin); if (extensionPromise) { return extensionPromise; } if (skin._data) { assign(skin._data.babylonSkeleton); return skin._data.promise; } var skeletonId = "skeleton".concat(skin.index); this._babylonScene._blockEntityCollection = !!this._assetContainer; var babylonSkeleton = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Skeleton(skin.name || skeletonId, skeletonId, this._babylonScene); babylonSkeleton._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; this._loadBones(context, skin, babylonSkeleton); var promise = this._loadSkinInverseBindMatricesDataAsync(context, skin).then(function (inverseBindMatricesData) { _this._updateBoneMatrices(babylonSkeleton, inverseBindMatricesData); }); skin._data = { babylonSkeleton: babylonSkeleton, promise: promise, }; assign(babylonSkeleton); return promise; }; GLTFLoader.prototype._loadBones = function (context, skin, babylonSkeleton) { if (skin.skeleton == undefined || this._parent.alwaysComputeSkeletonRootNode) { var rootNode = this._findSkeletonRootNode("".concat(context, "/joints"), skin.joints); if (rootNode) { if (skin.skeleton === undefined) { skin.skeleton = rootNode.index; } else { var isParent = function (a, b) { for (; b.parent; b = b.parent) { if (b.parent === a) { return true; } } return false; }; var skeletonNode = ArrayItem.Get("".concat(context, "/skeleton"), this._gltf.nodes, skin.skeleton); if (skeletonNode !== rootNode && !isParent(skeletonNode, rootNode)) { babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("".concat(context, "/skeleton: Overriding with nearest common ancestor as skeleton node is not a common root")); skin.skeleton = rootNode.index; } } } else { babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("".concat(context, ": Failed to find common root")); } } var babylonBones = {}; for (var _i = 0, _a = skin.joints; _i < _a.length; _i++) { var index = _a[_i]; var node = ArrayItem.Get("".concat(context, "/joints/").concat(index), this._gltf.nodes, index); this._loadBone(node, skin, babylonSkeleton, babylonBones); } }; GLTFLoader.prototype._findSkeletonRootNode = function (context, joints) { if (joints.length === 0) { return null; } var paths = {}; for (var _i = 0, joints_1 = joints; _i < joints_1.length; _i++) { var index = joints_1[_i]; var path = new Array(); var node = ArrayItem.Get("".concat(context, "/").concat(index), this._gltf.nodes, index); while (node.index !== -1) { path.unshift(node); node = node.parent; } paths[index] = path; } var rootNode = null; for (var i = 0;; ++i) { var path = paths[joints[0]]; if (i >= path.length) { return rootNode; } var node = path[i]; for (var j = 1; j < joints.length; ++j) { path = paths[joints[j]]; if (i >= path.length || node !== path[i]) { return rootNode; } } rootNode = node; } }; GLTFLoader.prototype._loadBone = function (node, skin, babylonSkeleton, babylonBones) { var babylonBone = babylonBones[node.index]; if (babylonBone) { return babylonBone; } var parentBabylonBone = null; if (node.index !== skin.skeleton) { if (node.parent && node.parent.index !== -1) { parentBabylonBone = this._loadBone(node.parent, skin, babylonSkeleton, babylonBones); } else if (skin.skeleton !== undefined) { babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("/skins/".concat(skin.index, "/skeleton: Skeleton node is not a common root")); } } var boneIndex = skin.joints.indexOf(node.index); babylonBone = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Bone(node.name || "joint".concat(node.index), babylonSkeleton, parentBabylonBone, this._getNodeMatrix(node), null, null, boneIndex); babylonBones[node.index] = babylonBone; // Wait until the scene is loaded to ensure the transform nodes are loaded. this._postSceneLoadActions.push(function () { // Link the Babylon bone with the corresponding Babylon transform node. // A glTF joint is a pointer to a glTF node in the glTF node hierarchy similar to Unity3D. babylonBone.linkTransformNode(node._babylonTransformNode); }); return babylonBone; }; GLTFLoader.prototype._loadSkinInverseBindMatricesDataAsync = function (context, skin) { if (skin.inverseBindMatrices == undefined) { return Promise.resolve(null); } var accessor = ArrayItem.Get("".concat(context, "/inverseBindMatrices"), this._gltf.accessors, skin.inverseBindMatrices); return this._loadFloatAccessorAsync("/accessors/".concat(accessor.index), accessor); }; GLTFLoader.prototype._updateBoneMatrices = function (babylonSkeleton, inverseBindMatricesData) { for (var _i = 0, _a = babylonSkeleton.bones; _i < _a.length; _i++) { var babylonBone = _a[_i]; var baseMatrix = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Matrix.Identity(); var boneIndex = babylonBone._index; if (inverseBindMatricesData && boneIndex !== -1) { babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Matrix.FromArrayToRef(inverseBindMatricesData, boneIndex * 16, baseMatrix); baseMatrix.invertToRef(baseMatrix); } var babylonParentBone = babylonBone.getParent(); if (babylonParentBone) { baseMatrix.multiplyToRef(babylonParentBone.getAbsoluteInverseBindMatrix(), baseMatrix); } babylonBone.updateMatrix(baseMatrix, false, false); babylonBone._updateAbsoluteBindMatrices(undefined, false); } }; GLTFLoader.prototype._getNodeMatrix = function (node) { return node.matrix ? babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Matrix.FromArray(node.matrix) : babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Matrix.Compose(node.scale ? babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Vector3.FromArray(node.scale) : babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Vector3.One(), node.rotation ? babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Quaternion.FromArray(node.rotation) : babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Quaternion.Identity(), node.translation ? babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Vector3.FromArray(node.translation) : babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero()); }; /** * Loads a glTF camera. * @param context The context when loading the asset * @param camera The glTF camera property * @param assign A function called synchronously after parsing the glTF properties * @returns A promise that resolves with the loaded Babylon camera when the load is complete */ GLTFLoader.prototype.loadCameraAsync = function (context, camera, assign) { if (assign === void 0) { assign = function () { }; } var extensionPromise = this._extensionsLoadCameraAsync(context, camera, assign); if (extensionPromise) { return extensionPromise; } var promises = new Array(); this.logOpen("".concat(context, " ").concat(camera.name || "")); this._babylonScene._blockEntityCollection = !!this._assetContainer; var babylonCamera = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.FreeCamera(camera.name || "camera".concat(camera.index), babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Vector3.Zero(), this._babylonScene, false); babylonCamera._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; babylonCamera.ignoreParentScaling = true; camera._babylonCamera = babylonCamera; babylonCamera.rotation = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Vector3(0, Math.PI, 0); switch (camera.type) { case "perspective" /* CameraType.PERSPECTIVE */: { var perspective = camera.perspective; if (!perspective) { throw new Error("".concat(context, ": Camera perspective properties are missing")); } babylonCamera.fov = perspective.yfov; babylonCamera.minZ = perspective.znear; babylonCamera.maxZ = perspective.zfar || 0; break; } case "orthographic" /* CameraType.ORTHOGRAPHIC */: { if (!camera.orthographic) { throw new Error("".concat(context, ": Camera orthographic properties are missing")); } babylonCamera.mode = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Camera.ORTHOGRAPHIC_CAMERA; babylonCamera.orthoLeft = -camera.orthographic.xmag; babylonCamera.orthoRight = camera.orthographic.xmag; babylonCamera.orthoBottom = -camera.orthographic.ymag; babylonCamera.orthoTop = camera.orthographic.ymag; babylonCamera.minZ = camera.orthographic.znear; babylonCamera.maxZ = camera.orthographic.zfar; break; } default: { throw new Error("".concat(context, ": Invalid camera type (").concat(camera.type, ")")); } } GLTFLoader.AddPointerMetadata(babylonCamera, context); this._parent.onCameraLoadedObservable.notifyObservers(babylonCamera); assign(babylonCamera); this.logClose(); return Promise.all(promises).then(function () { return babylonCamera; }); }; GLTFLoader.prototype._loadAnimationsAsync = function () { var animations = this._gltf.animations; if (!animations) { return Promise.resolve(); } var promises = new Array(); for (var index = 0; index < animations.length; index++) { var animation = animations[index]; promises.push(this.loadAnimationAsync("/animations/".concat(animation.index), animation).then(function (animationGroup) { // Delete the animation group if it ended up not having any animations in it. if (animationGroup.targetedAnimations.length === 0) { animationGroup.dispose(); } })); } return Promise.all(promises).then(function () { }); }; /** * Loads a glTF animation. * @param context The context when loading the asset * @param animation The glTF animation property * @returns A promise that resolves with the loaded Babylon animation group when the load is complete */ GLTFLoader.prototype.loadAnimationAsync = function (context, animation) { var promise = this._extensionsLoadAnimationAsync(context, animation); if (promise) { return promise; } this._babylonScene._blockEntityCollection = !!this._assetContainer; var babylonAnimationGroup = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.AnimationGroup(animation.name || "animation".concat(animation.index), this._babylonScene); babylonAnimationGroup._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; animation._babylonAnimationGroup = babylonAnimationGroup; var promises = new Array(); ArrayItem.Assign(animation.channels); ArrayItem.Assign(animation.samplers); for (var _i = 0, _a = animation.channels; _i < _a.length; _i++) { var channel = _a[_i]; promises.push(this._loadAnimationChannelAsync("".concat(context, "/channels/").concat(channel.index), context, animation, channel, function (babylonTarget, babylonAnimation) { babylonTarget.animations = babylonTarget.animations || []; babylonTarget.animations.push(babylonAnimation); babylonAnimationGroup.addTargetedAnimation(babylonAnimation, babylonTarget); })); } return Promise.all(promises).then(function () { babylonAnimationGroup.normalize(0); return babylonAnimationGroup; }); }; /** * @hidden * Loads a glTF animation channel. * @param context The context when loading the asset * @param animationContext The context of the animation when loading the asset * @param animation The glTF animation property * @param channel The glTF animation channel property * @param onLoad Called for each animation loaded * @returns A void promise that resolves when the load is complete */ GLTFLoader.prototype._loadAnimationChannelAsync = function (context, animationContext, animation, channel, onLoad) { var promise = this._extensionsLoadAnimationChannelAsync(context, animationContext, animation, channel, onLoad); if (promise) { return promise; } if (channel.target.node == undefined) { return Promise.resolve(); } var targetNode = ArrayItem.Get("".concat(context, "/target/node"), this._gltf.nodes, channel.target.node); // Ignore animations that have no animation targets. if ((channel.target.path === "weights" /* AnimationChannelTargetPath.WEIGHTS */ && !targetNode._numMorphTargets) || (channel.target.path !== "weights" /* AnimationChannelTargetPath.WEIGHTS */ && !targetNode._babylonTransformNode)) { return Promise.resolve(); } var properties; switch (channel.target.path) { case "translation" /* AnimationChannelTargetPath.TRANSLATION */: { properties = _glTFLoaderAnimation__WEBPACK_IMPORTED_MODULE_2__.nodeAnimationData.translation; break; } case "rotation" /* AnimationChannelTargetPath.ROTATION */: { properties = _glTFLoaderAnimation__WEBPACK_IMPORTED_MODULE_2__.nodeAnimationData.rotation; break; } case "scale" /* AnimationChannelTargetPath.SCALE */: { properties = _glTFLoaderAnimation__WEBPACK_IMPORTED_MODULE_2__.nodeAnimationData.scale; break; } case "weights" /* AnimationChannelTargetPath.WEIGHTS */: { properties = _glTFLoaderAnimation__WEBPACK_IMPORTED_MODULE_2__.nodeAnimationData.weights; break; } default: { throw new Error("".concat(context, "/target/path: Invalid value (").concat(channel.target.path, ")")); } } var targetInfo = { target: targetNode, properties: properties, }; return this._loadAnimationChannelFromTargetInfoAsync(context, animationContext, animation, channel, targetInfo, onLoad); }; /** * @hidden * Loads a glTF animation channel. * @param context The context when loading the asset * @param animationContext The context of the animation when loading the asset * @param animation The glTF animation property * @param channel The glTF animation channel property * @param targetInfo The glTF target and properties * @param onLoad Called for each animation loaded * @returns A void promise that resolves when the load is complete */ GLTFLoader.prototype._loadAnimationChannelFromTargetInfoAsync = function (context, animationContext, animation, channel, targetInfo, onLoad) { var fps = this.parent.targetFps; var invfps = 1 / fps; var sampler = ArrayItem.Get("".concat(context, "/sampler"), animation.samplers, channel.sampler); return this._loadAnimationSamplerAsync("".concat(animationContext, "/samplers/").concat(channel.sampler), sampler).then(function (data) { var numAnimations = 0; // Extract the corresponding values from the read value. // GLTF values may be dispatched to several Babylon properties. // For example, baseColorFactor [`r`, `g`, `b`, `a`] is dispatched to // - albedoColor as Color3(`r`, `g`, `b`) // - alpha as `a` for (var _i = 0, _a = targetInfo.properties; _i < _a.length; _i++) { var property = _a[_i]; var stride = property.getStride(targetInfo.target); var input = data.input; var output = data.output; var keys = new Array(input.length); var outputOffset = 0; switch (data.interpolation) { case "STEP" /* AnimationSamplerInterpolation.STEP */: { for (var index = 0; index < input.length; index++) { var value = property.getValue(targetInfo.target, output, outputOffset, 1); outputOffset += stride; keys[index] = { frame: input[index] * fps, value: value, interpolation: babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.AnimationKeyInterpolation.STEP, }; } break; } case "CUBICSPLINE" /* AnimationSamplerInterpolation.CUBICSPLINE */: { for (var index = 0; index < input.length; index++) { var inTangent = property.getValue(targetInfo.target, output, outputOffset, invfps); outputOffset += stride; var value = property.getValue(targetInfo.target, output, outputOffset, 1); outputOffset += stride; var outTangent = property.getValue(targetInfo.target, output, outputOffset, invfps); outputOffset += stride; keys[index] = { frame: input[index] * fps, inTangent: inTangent, value: value, outTangent: outTangent, }; } break; } case "LINEAR" /* AnimationSamplerInterpolation.LINEAR */: { for (var index = 0; index < input.length; index++) { var value = property.getValue(targetInfo.target, output, outputOffset, 1); outputOffset += stride; keys[index] = { frame: input[index] * fps, value: value, }; } break; } } if (outputOffset > 0) { var name_4 = "".concat(animation.name || "animation".concat(animation.index), "_channel").concat(channel.index, "_").concat(numAnimations); property.buildAnimations(targetInfo.target, name_4, fps, keys, function (babylonAnimatable, babylonAnimation) { ++numAnimations; onLoad(babylonAnimatable, babylonAnimation); }); } } }); }; GLTFLoader.prototype._loadAnimationSamplerAsync = function (context, sampler) { if (sampler._data) { return sampler._data; } var interpolation = sampler.interpolation || "LINEAR" /* AnimationSamplerInterpolation.LINEAR */; switch (interpolation) { case "STEP" /* AnimationSamplerInterpolation.STEP */: case "LINEAR" /* AnimationSamplerInterpolation.LINEAR */: case "CUBICSPLINE" /* AnimationSamplerInterpolation.CUBICSPLINE */: { break; } default: { throw new Error("".concat(context, "/interpolation: Invalid value (").concat(sampler.interpolation, ")")); } } var inputAccessor = ArrayItem.Get("".concat(context, "/input"), this._gltf.accessors, sampler.input); var outputAccessor = ArrayItem.Get("".concat(context, "/output"), this._gltf.accessors, sampler.output); sampler._data = Promise.all([ this._loadFloatAccessorAsync("/accessors/".concat(inputAccessor.index), inputAccessor), this._loadFloatAccessorAsync("/accessors/".concat(outputAccessor.index), outputAccessor), ]).then(function (_a) { var inputData = _a[0], outputData = _a[1]; return { input: inputData, interpolation: interpolation, output: outputData, }; }); return sampler._data; }; /** * Loads a glTF buffer. * @param context The context when loading the asset * @param buffer The glTF buffer property * @param byteOffset The byte offset to use * @param byteLength The byte length to use * @returns A promise that resolves with the loaded data when the load is complete */ GLTFLoader.prototype.loadBufferAsync = function (context, buffer, byteOffset, byteLength) { var extensionPromise = this._extensionsLoadBufferAsync(context, buffer, byteOffset, byteLength); if (extensionPromise) { return extensionPromise; } if (!buffer._data) { if (buffer.uri) { buffer._data = this.loadUriAsync("".concat(context, "/uri"), buffer, buffer.uri); } else { if (!this._bin) { throw new Error("".concat(context, ": Uri is missing or the binary glTF is missing its binary chunk")); } buffer._data = this._bin.readAsync(0, buffer.byteLength); } } return buffer._data.then(function (data) { try { return new Uint8Array(data.buffer, data.byteOffset + byteOffset, byteLength); } catch (e) { throw new Error("".concat(context, ": ").concat(e.message)); } }); }; /** * Loads a glTF buffer view. * @param context The context when loading the asset * @param bufferView The glTF buffer view property * @returns A promise that resolves with the loaded data when the load is complete */ GLTFLoader.prototype.loadBufferViewAsync = function (context, bufferView) { var extensionPromise = this._extensionsLoadBufferViewAsync(context, bufferView); if (extensionPromise) { return extensionPromise; } if (bufferView._data) { return bufferView._data; } var buffer = ArrayItem.Get("".concat(context, "/buffer"), this._gltf.buffers, bufferView.buffer); bufferView._data = this.loadBufferAsync("/buffers/".concat(buffer.index), buffer, bufferView.byteOffset || 0, bufferView.byteLength); return bufferView._data; }; GLTFLoader.prototype._loadAccessorAsync = function (context, accessor, constructor) { var _this = this; if (accessor._data) { return accessor._data; } var numComponents = GLTFLoader._GetNumComponents(context, accessor.type); var byteStride = numComponents * babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.GetTypeByteLength(accessor.componentType); var length = numComponents * accessor.count; if (accessor.bufferView == undefined) { accessor._data = Promise.resolve(new constructor(length)); } else { var bufferView_1 = ArrayItem.Get("".concat(context, "/bufferView"), this._gltf.bufferViews, accessor.bufferView); accessor._data = this.loadBufferViewAsync("/bufferViews/".concat(bufferView_1.index), bufferView_1).then(function (data) { if (accessor.componentType === 5126 /* AccessorComponentType.FLOAT */ && !accessor.normalized && (!bufferView_1.byteStride || bufferView_1.byteStride === byteStride)) { return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, length); } else { var typedArray_1 = new constructor(length); babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.ForEach(data, accessor.byteOffset || 0, bufferView_1.byteStride || byteStride, numComponents, accessor.componentType, typedArray_1.length, accessor.normalized || false, function (value, index) { typedArray_1[index] = value; }); return typedArray_1; } }); } if (accessor.sparse) { var sparse_1 = accessor.sparse; accessor._data = accessor._data.then(function (data) { var typedArray = data; var indicesBufferView = ArrayItem.Get("".concat(context, "/sparse/indices/bufferView"), _this._gltf.bufferViews, sparse_1.indices.bufferView); var valuesBufferView = ArrayItem.Get("".concat(context, "/sparse/values/bufferView"), _this._gltf.bufferViews, sparse_1.values.bufferView); return Promise.all([ _this.loadBufferViewAsync("/bufferViews/".concat(indicesBufferView.index), indicesBufferView), _this.loadBufferViewAsync("/bufferViews/".concat(valuesBufferView.index), valuesBufferView), ]).then(function (_a) { var indicesData = _a[0], valuesData = _a[1]; var indices = GLTFLoader._GetTypedArray("".concat(context, "/sparse/indices"), sparse_1.indices.componentType, indicesData, sparse_1.indices.byteOffset, sparse_1.count); var sparseLength = numComponents * sparse_1.count; var values; if (accessor.componentType === 5126 /* AccessorComponentType.FLOAT */ && !accessor.normalized) { values = GLTFLoader._GetTypedArray("".concat(context, "/sparse/values"), accessor.componentType, valuesData, sparse_1.values.byteOffset, sparseLength); } else { var sparseData = GLTFLoader._GetTypedArray("".concat(context, "/sparse/values"), accessor.componentType, valuesData, sparse_1.values.byteOffset, sparseLength); values = new constructor(sparseLength); babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.ForEach(sparseData, 0, byteStride, numComponents, accessor.componentType, values.length, accessor.normalized || false, function (value, index) { values[index] = value; }); } var valuesIndex = 0; for (var indicesIndex = 0; indicesIndex < indices.length; indicesIndex++) { var dataIndex = indices[indicesIndex] * numComponents; for (var componentIndex = 0; componentIndex < numComponents; componentIndex++) { typedArray[dataIndex++] = values[valuesIndex++]; } } return typedArray; }); }); } return accessor._data; }; /** * @internal */ GLTFLoader.prototype._loadFloatAccessorAsync = function (context, accessor) { return this._loadAccessorAsync(context, accessor, Float32Array); }; /** * @internal */ GLTFLoader.prototype._loadIndicesAccessorAsync = function (context, accessor) { if (accessor.type !== "SCALAR" /* AccessorType.SCALAR */) { throw new Error("".concat(context, "/type: Invalid value ").concat(accessor.type)); } if (accessor.componentType !== 5121 /* AccessorComponentType.UNSIGNED_BYTE */ && accessor.componentType !== 5123 /* AccessorComponentType.UNSIGNED_SHORT */ && accessor.componentType !== 5125 /* AccessorComponentType.UNSIGNED_INT */) { throw new Error("".concat(context, "/componentType: Invalid value ").concat(accessor.componentType)); } if (accessor._data) { return accessor._data; } if (accessor.sparse) { var constructor = GLTFLoader._GetTypedArrayConstructor("".concat(context, "/componentType"), accessor.componentType); accessor._data = this._loadAccessorAsync(context, accessor, constructor); } else { var bufferView = ArrayItem.Get("".concat(context, "/bufferView"), this._gltf.bufferViews, accessor.bufferView); accessor._data = this.loadBufferViewAsync("/bufferViews/".concat(bufferView.index), bufferView).then(function (data) { return GLTFLoader._GetTypedArray(context, accessor.componentType, data, accessor.byteOffset, accessor.count); }); } return accessor._data; }; /** * @internal */ GLTFLoader.prototype._loadVertexBufferViewAsync = function (bufferView) { if (bufferView._babylonBuffer) { return bufferView._babylonBuffer; } var engine = this._babylonScene.getEngine(); bufferView._babylonBuffer = this.loadBufferViewAsync("/bufferViews/".concat(bufferView.index), bufferView).then(function (data) { return new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Buffer(engine, data, false); }); return bufferView._babylonBuffer; }; /** * @internal */ GLTFLoader.prototype._loadVertexAccessorAsync = function (context, accessor, kind) { var _a; if ((_a = accessor._babylonVertexBuffer) === null || _a === void 0 ? void 0 : _a[kind]) { return accessor._babylonVertexBuffer[kind]; } if (!accessor._babylonVertexBuffer) { accessor._babylonVertexBuffer = {}; } var engine = this._babylonScene.getEngine(); if (accessor.sparse || accessor.bufferView == undefined) { accessor._babylonVertexBuffer[kind] = this._loadFloatAccessorAsync(context, accessor).then(function (data) { return new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer(engine, data, kind, false); }); } else { var bufferView_2 = ArrayItem.Get("".concat(context, "/bufferView"), this._gltf.bufferViews, accessor.bufferView); accessor._babylonVertexBuffer[kind] = this._loadVertexBufferViewAsync(bufferView_2).then(function (babylonBuffer) { var numComponents = GLTFLoader._GetNumComponents(context, accessor.type); return new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer(engine, babylonBuffer, kind, false, undefined, bufferView_2.byteStride, undefined, accessor.byteOffset, numComponents, accessor.componentType, accessor.normalized, true, undefined, true); }); } return accessor._babylonVertexBuffer[kind]; }; GLTFLoader.prototype._loadMaterialMetallicRoughnessPropertiesAsync = function (context, properties, babylonMaterial) { if (!(babylonMaterial instanceof babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } var promises = new Array(); if (properties) { if (properties.baseColorFactor) { babylonMaterial.albedoColor = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(properties.baseColorFactor); babylonMaterial.alpha = properties.baseColorFactor[3]; } else { babylonMaterial.albedoColor = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Color3.White(); } babylonMaterial.metallic = properties.metallicFactor == undefined ? 1 : properties.metallicFactor; babylonMaterial.roughness = properties.roughnessFactor == undefined ? 1 : properties.roughnessFactor; if (properties.baseColorTexture) { promises.push(this.loadTextureInfoAsync("".concat(context, "/baseColorTexture"), properties.baseColorTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Base Color)"); babylonMaterial.albedoTexture = texture; })); } if (properties.metallicRoughnessTexture) { properties.metallicRoughnessTexture.nonColorData = true; promises.push(this.loadTextureInfoAsync("".concat(context, "/metallicRoughnessTexture"), properties.metallicRoughnessTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Metallic Roughness)"); babylonMaterial.metallicTexture = texture; })); babylonMaterial.useMetallnessFromMetallicTextureBlue = true; babylonMaterial.useRoughnessFromMetallicTextureGreen = true; babylonMaterial.useRoughnessFromMetallicTextureAlpha = false; } } return Promise.all(promises).then(function () { }); }; /** * @internal */ GLTFLoader.prototype._loadMaterialAsync = function (context, material, babylonMesh, babylonDrawMode, assign) { if (assign === void 0) { assign = function () { }; } var extensionPromise = this._extensionsLoadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign); if (extensionPromise) { return extensionPromise; } material._data = material._data || {}; var babylonData = material._data[babylonDrawMode]; if (!babylonData) { this.logOpen("".concat(context, " ").concat(material.name || "")); var babylonMaterial = this.createMaterial(context, material, babylonDrawMode); babylonData = { babylonMaterial: babylonMaterial, babylonMeshes: [], promise: this.loadMaterialPropertiesAsync(context, material, babylonMaterial), }; material._data[babylonDrawMode] = babylonData; GLTFLoader.AddPointerMetadata(babylonMaterial, context); this._parent.onMaterialLoadedObservable.notifyObservers(babylonMaterial); this.logClose(); } if (babylonMesh) { babylonData.babylonMeshes.push(babylonMesh); babylonMesh.onDisposeObservable.addOnce(function () { var index = babylonData.babylonMeshes.indexOf(babylonMesh); if (index !== -1) { babylonData.babylonMeshes.splice(index, 1); } }); } assign(babylonData.babylonMaterial); return babylonData.promise.then(function () { return babylonData.babylonMaterial; }); }; GLTFLoader.prototype._createDefaultMaterial = function (name, babylonDrawMode) { this._babylonScene._blockEntityCollection = !!this._assetContainer; var babylonMaterial = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial(name, this._babylonScene); babylonMaterial._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; // Moved to mesh so user can change materials on gltf meshes: babylonMaterial.sideOrientation = this._babylonScene.useRightHandedSystem ? Material.CounterClockWiseSideOrientation : Material.ClockWiseSideOrientation; babylonMaterial.fillMode = babylonDrawMode; babylonMaterial.enableSpecularAntiAliasing = true; babylonMaterial.useRadianceOverAlpha = !this._parent.transparencyAsCoverage; babylonMaterial.useSpecularOverAlpha = !this._parent.transparencyAsCoverage; babylonMaterial.transparencyMode = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial.PBRMATERIAL_OPAQUE; babylonMaterial.metallic = 1; babylonMaterial.roughness = 1; return babylonMaterial; }; /** * Creates a Babylon material from a glTF material. * @param context The context when loading the asset * @param material The glTF material property * @param babylonDrawMode The draw mode for the Babylon material * @returns The Babylon material */ GLTFLoader.prototype.createMaterial = function (context, material, babylonDrawMode) { var extensionPromise = this._extensionsCreateMaterial(context, material, babylonDrawMode); if (extensionPromise) { return extensionPromise; } var name = material.name || "material".concat(material.index); var babylonMaterial = this._createDefaultMaterial(name, babylonDrawMode); return babylonMaterial; }; /** * Loads properties from a glTF material into a Babylon material. * @param context The context when loading the asset * @param material The glTF material property * @param babylonMaterial The Babylon material * @returns A promise that resolves when the load is complete */ GLTFLoader.prototype.loadMaterialPropertiesAsync = function (context, material, babylonMaterial) { var extensionPromise = this._extensionsLoadMaterialPropertiesAsync(context, material, babylonMaterial); if (extensionPromise) { return extensionPromise; } var promises = new Array(); promises.push(this.loadMaterialBasePropertiesAsync(context, material, babylonMaterial)); if (material.pbrMetallicRoughness) { promises.push(this._loadMaterialMetallicRoughnessPropertiesAsync("".concat(context, "/pbrMetallicRoughness"), material.pbrMetallicRoughness, babylonMaterial)); } this.loadMaterialAlphaProperties(context, material, babylonMaterial); return Promise.all(promises).then(function () { }); }; /** * Loads the normal, occlusion, and emissive properties from a glTF material into a Babylon material. * @param context The context when loading the asset * @param material The glTF material property * @param babylonMaterial The Babylon material * @returns A promise that resolves when the load is complete */ GLTFLoader.prototype.loadMaterialBasePropertiesAsync = function (context, material, babylonMaterial) { if (!(babylonMaterial instanceof babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } var promises = new Array(); babylonMaterial.emissiveColor = material.emissiveFactor ? babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Color3.FromArray(material.emissiveFactor) : new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Color3(0, 0, 0); if (material.doubleSided) { babylonMaterial.backFaceCulling = false; babylonMaterial.twoSidedLighting = true; } if (material.normalTexture) { material.normalTexture.nonColorData = true; promises.push(this.loadTextureInfoAsync("".concat(context, "/normalTexture"), material.normalTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Normal)"); babylonMaterial.bumpTexture = texture; })); babylonMaterial.invertNormalMapX = !this._babylonScene.useRightHandedSystem; babylonMaterial.invertNormalMapY = this._babylonScene.useRightHandedSystem; if (material.normalTexture.scale != undefined && babylonMaterial.bumpTexture) { babylonMaterial.bumpTexture.level = material.normalTexture.scale; } babylonMaterial.forceIrradianceInFragment = true; } if (material.occlusionTexture) { material.occlusionTexture.nonColorData = true; promises.push(this.loadTextureInfoAsync("".concat(context, "/occlusionTexture"), material.occlusionTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Occlusion)"); babylonMaterial.ambientTexture = texture; })); babylonMaterial.useAmbientInGrayScale = true; if (material.occlusionTexture.strength != undefined) { babylonMaterial.ambientTextureStrength = material.occlusionTexture.strength; } } if (material.emissiveTexture) { promises.push(this.loadTextureInfoAsync("".concat(context, "/emissiveTexture"), material.emissiveTexture, function (texture) { texture.name = "".concat(babylonMaterial.name, " (Emissive)"); babylonMaterial.emissiveTexture = texture; })); } return Promise.all(promises).then(function () { }); }; /** * Loads the alpha properties from a glTF material into a Babylon material. * Must be called after the setting the albedo texture of the Babylon material when the material has an albedo texture. * @param context The context when loading the asset * @param material The glTF material property * @param babylonMaterial The Babylon material */ GLTFLoader.prototype.loadMaterialAlphaProperties = function (context, material, babylonMaterial) { if (!(babylonMaterial instanceof babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial)) { throw new Error("".concat(context, ": Material type not supported")); } var alphaMode = material.alphaMode || "OPAQUE" /* MaterialAlphaMode.OPAQUE */; switch (alphaMode) { case "OPAQUE" /* MaterialAlphaMode.OPAQUE */: { babylonMaterial.transparencyMode = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial.PBRMATERIAL_OPAQUE; break; } case "MASK" /* MaterialAlphaMode.MASK */: { babylonMaterial.transparencyMode = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial.PBRMATERIAL_ALPHATEST; babylonMaterial.alphaCutOff = material.alphaCutoff == undefined ? 0.5 : material.alphaCutoff; if (babylonMaterial.albedoTexture) { babylonMaterial.albedoTexture.hasAlpha = true; } break; } case "BLEND" /* MaterialAlphaMode.BLEND */: { babylonMaterial.transparencyMode = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.PBRMaterial.PBRMATERIAL_ALPHABLEND; if (babylonMaterial.albedoTexture) { babylonMaterial.albedoTexture.hasAlpha = true; babylonMaterial.useAlphaFromAlbedoTexture = true; } break; } default: { throw new Error("".concat(context, "/alphaMode: Invalid value (").concat(material.alphaMode, ")")); } } }; /** * Loads a glTF texture info. * @param context The context when loading the asset * @param textureInfo The glTF texture info property * @param assign A function called synchronously after parsing the glTF properties * @returns A promise that resolves with the loaded Babylon texture when the load is complete */ GLTFLoader.prototype.loadTextureInfoAsync = function (context, textureInfo, assign) { var _this = this; if (assign === void 0) { assign = function () { }; } var extensionPromise = this._extensionsLoadTextureInfoAsync(context, textureInfo, assign); if (extensionPromise) { return extensionPromise; } this.logOpen("".concat(context)); if (textureInfo.texCoord >= 6) { throw new Error("".concat(context, "/texCoord: Invalid value (").concat(textureInfo.texCoord, ")")); } var texture = ArrayItem.Get("".concat(context, "/index"), this._gltf.textures, textureInfo.index); texture._textureInfo = textureInfo; var promise = this._loadTextureAsync("/textures/".concat(textureInfo.index), texture, function (babylonTexture) { babylonTexture.coordinatesIndex = textureInfo.texCoord || 0; GLTFLoader.AddPointerMetadata(babylonTexture, context); _this._parent.onTextureLoadedObservable.notifyObservers(babylonTexture); assign(babylonTexture); }); this.logClose(); return promise; }; /** * @internal */ GLTFLoader.prototype._loadTextureAsync = function (context, texture, assign) { if (assign === void 0) { assign = function () { }; } var extensionPromise = this._extensionsLoadTextureAsync(context, texture, assign); if (extensionPromise) { return extensionPromise; } this.logOpen("".concat(context, " ").concat(texture.name || "")); var sampler = texture.sampler == undefined ? GLTFLoader.DefaultSampler : ArrayItem.Get("".concat(context, "/sampler"), this._gltf.samplers, texture.sampler); var image = ArrayItem.Get("".concat(context, "/source"), this._gltf.images, texture.source); var promise = this._createTextureAsync(context, sampler, image, assign, undefined, !texture._textureInfo.nonColorData); this.logClose(); return promise; }; /** * @internal */ GLTFLoader.prototype._createTextureAsync = function (context, sampler, image, assign, textureLoaderOptions, useSRGBBuffer) { var _this = this; if (assign === void 0) { assign = function () { }; } var samplerData = this._loadSampler("/samplers/".concat(sampler.index), sampler); var promises = new Array(); var deferred = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Deferred(); this._babylonScene._blockEntityCollection = !!this._assetContainer; var textureCreationOptions = { noMipmap: samplerData.noMipMaps, invertY: false, samplingMode: samplerData.samplingMode, onLoad: function () { if (!_this._disposed) { deferred.resolve(); } }, onError: function (message, exception) { if (!_this._disposed) { deferred.reject(new Error("".concat(context, ": ").concat(exception && exception.message ? exception.message : message || "Failed to load texture"))); } }, mimeType: image.mimeType, loaderOptions: textureLoaderOptions, useSRGBBuffer: !!useSRGBBuffer && this._parent.useSRGBBuffers, }; var babylonTexture = new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture(null, this._babylonScene, textureCreationOptions); babylonTexture._parentContainer = this._assetContainer; this._babylonScene._blockEntityCollection = false; promises.push(deferred.promise); promises.push(this.loadImageAsync("/images/".concat(image.index), image).then(function (data) { var name = image.uri || "".concat(_this._fileName, "#image").concat(image.index); var dataUrl = "data:".concat(_this._uniqueRootUrl).concat(name); babylonTexture.updateURL(dataUrl, data); })); babylonTexture.wrapU = samplerData.wrapU; babylonTexture.wrapV = samplerData.wrapV; assign(babylonTexture); return Promise.all(promises).then(function () { return babylonTexture; }); }; GLTFLoader.prototype._loadSampler = function (context, sampler) { if (!sampler._data) { sampler._data = { noMipMaps: sampler.minFilter === 9728 /* TextureMinFilter.NEAREST */ || sampler.minFilter === 9729 /* TextureMinFilter.LINEAR */, samplingMode: GLTFLoader._GetTextureSamplingMode(context, sampler), wrapU: GLTFLoader._GetTextureWrapMode("".concat(context, "/wrapS"), sampler.wrapS), wrapV: GLTFLoader._GetTextureWrapMode("".concat(context, "/wrapT"), sampler.wrapT), }; } return sampler._data; }; /** * Loads a glTF image. * @param context The context when loading the asset * @param image The glTF image property * @returns A promise that resolves with the loaded data when the load is complete */ GLTFLoader.prototype.loadImageAsync = function (context, image) { if (!image._data) { this.logOpen("".concat(context, " ").concat(image.name || "")); if (image.uri) { image._data = this.loadUriAsync("".concat(context, "/uri"), image, image.uri); } else { var bufferView = ArrayItem.Get("".concat(context, "/bufferView"), this._gltf.bufferViews, image.bufferView); image._data = this.loadBufferViewAsync("/bufferViews/".concat(bufferView.index), bufferView); } this.logClose(); } return image._data; }; /** * Loads a glTF uri. * @param context The context when loading the asset * @param property The glTF property associated with the uri * @param uri The base64 or relative uri * @returns A promise that resolves with the loaded data when the load is complete */ GLTFLoader.prototype.loadUriAsync = function (context, property, uri) { var _this = this; var extensionPromise = this._extensionsLoadUriAsync(context, property, uri); if (extensionPromise) { return extensionPromise; } if (!GLTFLoader._ValidateUri(uri)) { throw new Error("".concat(context, ": '").concat(uri, "' is invalid")); } if ((0,babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.IsBase64DataUrl)(uri)) { var data = new Uint8Array((0,babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.DecodeBase64UrlToBinary)(uri)); this.log("".concat(context, ": Decoded ").concat(uri.substr(0, 64), "... (").concat(data.length, " bytes)")); return Promise.resolve(data); } this.log("".concat(context, ": Loading ").concat(uri)); return this._parent.preprocessUrlAsync(this._rootUrl + uri).then(function (url) { return new Promise(function (resolve, reject) { _this._parent._loadFile(_this._babylonScene, url, function (data) { if (!_this._disposed) { _this.log("".concat(context, ": Loaded ").concat(uri, " (").concat(data.byteLength, " bytes)")); resolve(new Uint8Array(data)); } }, true, function (request) { reject(new babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.LoadFileError("".concat(context, ": Failed to load '").concat(uri, "'").concat(request ? ": " + request.status + " " + request.statusText : ""), request)); }); }); }); }; /** * Adds a JSON pointer to the _internalMetadata of the Babylon object at `._internalMetadata.gltf.pointers`. * @param babylonObject the Babylon object with _internalMetadata * @param pointer the JSON pointer */ GLTFLoader.AddPointerMetadata = function (babylonObject, pointer) { babylonObject.metadata = babylonObject.metadata || {}; var metadata = (babylonObject._internalMetadata = babylonObject._internalMetadata || {}); var gltf = (metadata.gltf = metadata.gltf || {}); var pointers = (gltf.pointers = gltf.pointers || []); pointers.push(pointer); }; GLTFLoader._GetTextureWrapMode = function (context, mode) { // Set defaults if undefined mode = mode == undefined ? 10497 /* TextureWrapMode.REPEAT */ : mode; switch (mode) { case 33071 /* TextureWrapMode.CLAMP_TO_EDGE */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.CLAMP_ADDRESSMODE; case 33648 /* TextureWrapMode.MIRRORED_REPEAT */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.MIRROR_ADDRESSMODE; case 10497 /* TextureWrapMode.REPEAT */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.WRAP_ADDRESSMODE; default: babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("".concat(context, ": Invalid value (").concat(mode, ")")); return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.WRAP_ADDRESSMODE; } }; GLTFLoader._GetTextureSamplingMode = function (context, sampler) { // Set defaults if undefined var magFilter = sampler.magFilter == undefined ? 9729 /* TextureMagFilter.LINEAR */ : sampler.magFilter; var minFilter = sampler.minFilter == undefined ? 9987 /* TextureMinFilter.LINEAR_MIPMAP_LINEAR */ : sampler.minFilter; if (magFilter === 9729 /* TextureMagFilter.LINEAR */) { switch (minFilter) { case 9728 /* TextureMinFilter.NEAREST */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.LINEAR_NEAREST; case 9729 /* TextureMinFilter.LINEAR */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.LINEAR_LINEAR; case 9984 /* TextureMinFilter.NEAREST_MIPMAP_NEAREST */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.LINEAR_NEAREST_MIPNEAREST; case 9985 /* TextureMinFilter.LINEAR_MIPMAP_NEAREST */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.LINEAR_LINEAR_MIPNEAREST; case 9986 /* TextureMinFilter.NEAREST_MIPMAP_LINEAR */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.LINEAR_NEAREST_MIPLINEAR; case 9987 /* TextureMinFilter.LINEAR_MIPMAP_LINEAR */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.LINEAR_LINEAR_MIPLINEAR; default: babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("".concat(context, "/minFilter: Invalid value (").concat(minFilter, ")")); return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.LINEAR_LINEAR_MIPLINEAR; } } else { if (magFilter !== 9728 /* TextureMagFilter.NEAREST */) { babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("".concat(context, "/magFilter: Invalid value (").concat(magFilter, ")")); } switch (minFilter) { case 9728 /* TextureMinFilter.NEAREST */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.NEAREST_NEAREST; case 9729 /* TextureMinFilter.LINEAR */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.NEAREST_LINEAR; case 9984 /* TextureMinFilter.NEAREST_MIPMAP_NEAREST */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.NEAREST_NEAREST_MIPNEAREST; case 9985 /* TextureMinFilter.LINEAR_MIPMAP_NEAREST */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.NEAREST_LINEAR_MIPNEAREST; case 9986 /* TextureMinFilter.NEAREST_MIPMAP_LINEAR */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.NEAREST_NEAREST_MIPLINEAR; case 9987 /* TextureMinFilter.LINEAR_MIPMAP_LINEAR */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.NEAREST_LINEAR_MIPLINEAR; default: babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("".concat(context, "/minFilter: Invalid value (").concat(minFilter, ")")); return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Texture.NEAREST_NEAREST_MIPNEAREST; } } }; GLTFLoader._GetTypedArrayConstructor = function (context, componentType) { switch (componentType) { case 5120 /* AccessorComponentType.BYTE */: return Int8Array; case 5121 /* AccessorComponentType.UNSIGNED_BYTE */: return Uint8Array; case 5122 /* AccessorComponentType.SHORT */: return Int16Array; case 5123 /* AccessorComponentType.UNSIGNED_SHORT */: return Uint16Array; case 5125 /* AccessorComponentType.UNSIGNED_INT */: return Uint32Array; case 5126 /* AccessorComponentType.FLOAT */: return Float32Array; default: throw new Error("".concat(context, ": Invalid component type ").concat(componentType)); } }; GLTFLoader._GetTypedArray = function (context, componentType, bufferView, byteOffset, length) { var buffer = bufferView.buffer; byteOffset = bufferView.byteOffset + (byteOffset || 0); var constructor = GLTFLoader._GetTypedArrayConstructor("".concat(context, "/componentType"), componentType); var componentTypeLength = babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.VertexBuffer.GetTypeByteLength(componentType); if (byteOffset % componentTypeLength !== 0) { // HACK: Copy the buffer if byte offset is not a multiple of component type byte length. babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("".concat(context, ": Copying buffer as byte offset (").concat(byteOffset, ") is not a multiple of component type byte length (").concat(componentTypeLength, ")")); return new constructor(buffer.slice(byteOffset, byteOffset + length * componentTypeLength), 0); } return new constructor(buffer, byteOffset, length); }; GLTFLoader._GetNumComponents = function (context, type) { switch (type) { case "SCALAR": return 1; case "VEC2": return 2; case "VEC3": return 3; case "VEC4": return 4; case "MAT2": return 4; case "MAT3": return 9; case "MAT4": return 16; } throw new Error("".concat(context, ": Invalid type (").concat(type, ")")); }; GLTFLoader._ValidateUri = function (uri) { return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Tools.IsBase64(uri) || uri.indexOf("..") === -1; }; /** * @internal */ GLTFLoader._GetDrawMode = function (context, mode) { if (mode == undefined) { mode = 4 /* MeshPrimitiveMode.TRIANGLES */; } switch (mode) { case 0 /* MeshPrimitiveMode.POINTS */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Material.PointListDrawMode; case 1 /* MeshPrimitiveMode.LINES */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Material.LineListDrawMode; case 2 /* MeshPrimitiveMode.LINE_LOOP */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Material.LineLoopDrawMode; case 3 /* MeshPrimitiveMode.LINE_STRIP */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Material.LineStripDrawMode; case 4 /* MeshPrimitiveMode.TRIANGLES */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Material.TriangleFillMode; case 5 /* MeshPrimitiveMode.TRIANGLE_STRIP */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Material.TriangleStripDrawMode; case 6 /* MeshPrimitiveMode.TRIANGLE_FAN */: return babylonjs_Misc_deferred__WEBPACK_IMPORTED_MODULE_0__.Material.TriangleFanDrawMode; } throw new Error("".concat(context, ": Invalid mesh primitive mode (").concat(mode, ")")); }; GLTFLoader.prototype._compileMaterialsAsync = function () { var _this = this; this._parent._startPerformanceCounter("Compile materials"); var promises = new Array(); if (this._gltf.materials) { for (var _i = 0, _a = this._gltf.materials; _i < _a.length; _i++) { var material = _a[_i]; if (material._data) { for (var babylonDrawMode in material._data) { var babylonData = material._data[babylonDrawMode]; for (var _b = 0, _c = babylonData.babylonMeshes; _b < _c.length; _b++) { var babylonMesh = _c[_b]; // Ensure nonUniformScaling is set if necessary. babylonMesh.computeWorldMatrix(true); var babylonMaterial = babylonData.babylonMaterial; promises.push(babylonMaterial.forceCompilationAsync(babylonMesh)); promises.push(babylonMaterial.forceCompilationAsync(babylonMesh, { useInstances: true })); if (this._parent.useClipPlane) { promises.push(babylonMaterial.forceCompilationAsync(babylonMesh, { clipPlane: true })); promises.push(babylonMaterial.forceCompilationAsync(babylonMesh, { clipPlane: true, useInstances: true })); } } } } } } return Promise.all(promises).then(function () { _this._parent._endPerformanceCounter("Compile materials"); }); }; GLTFLoader.prototype._compileShadowGeneratorsAsync = function () { var _this = this; this._parent._startPerformanceCounter("Compile shadow generators"); var promises = new Array(); var lights = this._babylonScene.lights; for (var _i = 0, lights_1 = lights; _i < lights_1.length; _i++) { var light = lights_1[_i]; var generator = light.getShadowGenerator(); if (generator) { promises.push(generator.forceCompilationAsync()); } } return Promise.all(promises).then(function () { _this._parent._endPerformanceCounter("Compile shadow generators"); }); }; GLTFLoader.prototype._forEachExtensions = function (action) { for (var _i = 0, _a = this._extensions; _i < _a.length; _i++) { var extension = _a[_i]; if (extension.enabled) { action(extension); } } }; GLTFLoader.prototype._applyExtensions = function (property, functionName, actionAsync) { for (var _i = 0, _a = this._extensions; _i < _a.length; _i++) { var extension = _a[_i]; if (extension.enabled) { var id = "".concat(extension.name, ".").concat(functionName); var loaderProperty = property; loaderProperty._activeLoaderExtensionFunctions = loaderProperty._activeLoaderExtensionFunctions || {}; var activeLoaderExtensionFunctions = loaderProperty._activeLoaderExtensionFunctions; if (!activeLoaderExtensionFunctions[id]) { activeLoaderExtensionFunctions[id] = true; try { var result = actionAsync(extension); if (result) { return result; } } finally { delete activeLoaderExtensionFunctions[id]; } } } } return null; }; GLTFLoader.prototype._extensionsOnLoading = function () { this._forEachExtensions(function (extension) { return extension.onLoading && extension.onLoading(); }); }; GLTFLoader.prototype._extensionsOnReady = function () { this._forEachExtensions(function (extension) { return extension.onReady && extension.onReady(); }); }; GLTFLoader.prototype._extensionsLoadSceneAsync = function (context, scene) { return this._applyExtensions(scene, "loadScene", function (extension) { return extension.loadSceneAsync && extension.loadSceneAsync(context, scene); }); }; GLTFLoader.prototype._extensionsLoadNodeAsync = function (context, node, assign) { return this._applyExtensions(node, "loadNode", function (extension) { return extension.loadNodeAsync && extension.loadNodeAsync(context, node, assign); }); }; GLTFLoader.prototype._extensionsLoadCameraAsync = function (context, camera, assign) { return this._applyExtensions(camera, "loadCamera", function (extension) { return extension.loadCameraAsync && extension.loadCameraAsync(context, camera, assign); }); }; GLTFLoader.prototype._extensionsLoadVertexDataAsync = function (context, primitive, babylonMesh) { return this._applyExtensions(primitive, "loadVertexData", function (extension) { return extension._loadVertexDataAsync && extension._loadVertexDataAsync(context, primitive, babylonMesh); }); }; GLTFLoader.prototype._extensionsLoadMeshPrimitiveAsync = function (context, name, node, mesh, primitive, assign) { return this._applyExtensions(primitive, "loadMeshPrimitive", function (extension) { return extension._loadMeshPrimitiveAsync && extension._loadMeshPrimitiveAsync(context, name, node, mesh, primitive, assign); }); }; GLTFLoader.prototype._extensionsLoadMaterialAsync = function (context, material, babylonMesh, babylonDrawMode, assign) { return this._applyExtensions(material, "loadMaterial", function (extension) { return extension._loadMaterialAsync && extension._loadMaterialAsync(context, material, babylonMesh, babylonDrawMode, assign); }); }; GLTFLoader.prototype._extensionsCreateMaterial = function (context, material, babylonDrawMode) { return this._applyExtensions(material, "createMaterial", function (extension) { return extension.createMaterial && extension.createMaterial(context, material, babylonDrawMode); }); }; GLTFLoader.prototype._extensionsLoadMaterialPropertiesAsync = function (context, material, babylonMaterial) { return this._applyExtensions(material, "loadMaterialProperties", function (extension) { return extension.loadMaterialPropertiesAsync && extension.loadMaterialPropertiesAsync(context, material, babylonMaterial); }); }; GLTFLoader.prototype._extensionsLoadTextureInfoAsync = function (context, textureInfo, assign) { return this._applyExtensions(textureInfo, "loadTextureInfo", function (extension) { return extension.loadTextureInfoAsync && extension.loadTextureInfoAsync(context, textureInfo, assign); }); }; GLTFLoader.prototype._extensionsLoadTextureAsync = function (context, texture, assign) { return this._applyExtensions(texture, "loadTexture", function (extension) { return extension._loadTextureAsync && extension._loadTextureAsync(context, texture, assign); }); }; GLTFLoader.prototype._extensionsLoadAnimationAsync = function (context, animation) { return this._applyExtensions(animation, "loadAnimation", function (extension) { return extension.loadAnimationAsync && extension.loadAnimationAsync(context, animation); }); }; GLTFLoader.prototype._extensionsLoadAnimationChannelAsync = function (context, animationContext, animation, channel, onLoad) { return this._applyExtensions(animation, "loadAnimationChannel", function (extension) { return extension._loadAnimationChannelAsync && extension._loadAnimationChannelAsync(context, animationContext, animation, channel, onLoad); }); }; GLTFLoader.prototype._extensionsLoadSkinAsync = function (context, node, skin) { return this._applyExtensions(skin, "loadSkin", function (extension) { return extension._loadSkinAsync && extension._loadSkinAsync(context, node, skin); }); }; GLTFLoader.prototype._extensionsLoadUriAsync = function (context, property, uri) { return this._applyExtensions(property, "loadUri", function (extension) { return extension._loadUriAsync && extension._loadUriAsync(context, property, uri); }); }; GLTFLoader.prototype._extensionsLoadBufferViewAsync = function (context, bufferView) { return this._applyExtensions(bufferView, "loadBufferView", function (extension) { return extension.loadBufferViewAsync && extension.loadBufferViewAsync(context, bufferView); }); }; GLTFLoader.prototype._extensionsLoadBufferAsync = function (context, buffer, byteOffset, byteLength) { return this._applyExtensions(buffer, "loadBuffer", function (extension) { return extension.loadBufferAsync && extension.loadBufferAsync(context, buffer, byteOffset, byteLength); }); }; /** * Helper method called by a loader extension to load an glTF extension. * @param context The context when loading the asset * @param property The glTF property to load the extension from * @param extensionName The name of the extension to load * @param actionAsync The action to run * @returns The promise returned by actionAsync or null if the extension does not exist */ GLTFLoader.LoadExtensionAsync = function (context, property, extensionName, actionAsync) { if (!property.extensions) { return null; } var extensions = property.extensions; var extension = extensions[extensionName]; if (!extension) { return null; } return actionAsync("".concat(context, "/extensions/").concat(extensionName), extension); }; /** * Helper method called by a loader extension to load a glTF extra. * @param context The context when loading the asset * @param property The glTF property to load the extra from * @param extensionName The name of the extension to load * @param actionAsync The action to run * @returns The promise returned by actionAsync or null if the extra does not exist */ GLTFLoader.LoadExtraAsync = function (context, property, extensionName, actionAsync) { if (!property.extras) { return null; } var extras = property.extras; var extra = extras[extensionName]; if (!extra) { return null; } return actionAsync("".concat(context, "/extras/").concat(extensionName), extra); }; /** * Checks for presence of an extension. * @param name The name of the extension to check * @returns A boolean indicating the presence of the given extension name in `extensionsUsed` */ GLTFLoader.prototype.isExtensionUsed = function (name) { return !!this._gltf.extensionsUsed && this._gltf.extensionsUsed.indexOf(name) !== -1; }; /** * Increments the indentation level and logs a message. * @param message The message to log */ GLTFLoader.prototype.logOpen = function (message) { this._parent._logOpen(message); }; /** * Decrements the indentation level. */ GLTFLoader.prototype.logClose = function () { this._parent._logClose(); }; /** * Logs a message * @param message The message to log */ GLTFLoader.prototype.log = function (message) { this._parent._log(message); }; /** * Starts a performance counter. * @param counterName The name of the performance counter */ GLTFLoader.prototype.startPerformanceCounter = function (counterName) { this._parent._startPerformanceCounter(counterName); }; /** * Ends a performance counter. * @param counterName The name of the performance counter */ GLTFLoader.prototype.endPerformanceCounter = function (counterName) { this._parent._endPerformanceCounter(counterName); }; GLTFLoader._RegisteredExtensions = {}; /** * The default glTF sampler. */ GLTFLoader.DefaultSampler = { index: -1 }; return GLTFLoader; }()); _glTFFileLoader__WEBPACK_IMPORTED_MODULE_1__.GLTFFileLoader._CreateGLTF2Loader = function (parent) { return new GLTFLoader(parent); }; /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/glTFLoaderAnimation.ts": /*!****************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/glTFLoaderAnimation.ts ***! \****************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ AnimationPropertyInfo: () => (/* binding */ AnimationPropertyInfo), /* harmony export */ TransformNodeAnimationPropertyInfo: () => (/* binding */ TransformNodeAnimationPropertyInfo), /* harmony export */ WeightAnimationPropertyInfo: () => (/* binding */ WeightAnimationPropertyInfo), /* harmony export */ getQuaternion: () => (/* binding */ getQuaternion), /* harmony export */ getVector3: () => (/* binding */ getVector3), /* harmony export */ getWeights: () => (/* binding */ getWeights), /* harmony export */ nodeAnimationData: () => (/* binding */ nodeAnimationData) /* harmony export */ }); /* harmony import */ var tslib__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! tslib */ "../../../../node_modules/tslib/tslib.es6.mjs"); /* harmony import */ var babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Maths/math.vector */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__); /** @internal */ function getVector3(_target, source, offset, scale) { return babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Vector3.FromArray(source, offset).scaleInPlace(scale); } /** @internal */ function getQuaternion(_target, source, offset, scale) { return babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Quaternion.FromArray(source, offset).scaleInPlace(scale); } /** @internal */ function getWeights(target, source, offset, scale) { var value = new Array(target._numMorphTargets); for (var i = 0; i < value.length; i++) { value[i] = source[offset++] * scale; } return value; } /** @internal */ var AnimationPropertyInfo = /** @class */ (function () { /** @internal */ function AnimationPropertyInfo(type, name, getValue, getStride) { this.type = type; this.name = name; this.getValue = getValue; this.getStride = getStride; } AnimationPropertyInfo.prototype._buildAnimation = function (name, fps, keys) { var babylonAnimation = new babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation(name, this.name, fps, this.type); babylonAnimation.setKeys(keys); return babylonAnimation; }; return AnimationPropertyInfo; }()); /** @internal */ var TransformNodeAnimationPropertyInfo = /** @class */ (function (_super) { (0,tslib__WEBPACK_IMPORTED_MODULE_1__.__extends)(TransformNodeAnimationPropertyInfo, _super); function TransformNodeAnimationPropertyInfo() { return _super !== null && _super.apply(this, arguments) || this; } /** @internal */ TransformNodeAnimationPropertyInfo.prototype.buildAnimations = function (target, name, fps, keys, callback) { callback(target._babylonTransformNode, this._buildAnimation(name, fps, keys)); }; return TransformNodeAnimationPropertyInfo; }(AnimationPropertyInfo)); /** @internal */ var WeightAnimationPropertyInfo = /** @class */ (function (_super) { (0,tslib__WEBPACK_IMPORTED_MODULE_1__.__extends)(WeightAnimationPropertyInfo, _super); function WeightAnimationPropertyInfo() { return _super !== null && _super.apply(this, arguments) || this; } WeightAnimationPropertyInfo.prototype.buildAnimations = function (target, name, fps, keys, callback) { if (target._numMorphTargets) { var _loop_1 = function (targetIndex) { var babylonAnimation = new babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation("".concat(name, "_").concat(targetIndex), this_1.name, fps, this_1.type); babylonAnimation.setKeys(keys.map(function (key) { return ({ frame: key.frame, inTangent: key.inTangent ? key.inTangent[targetIndex] : undefined, value: key.value[targetIndex], outTangent: key.outTangent ? key.outTangent[targetIndex] : undefined, interpolation: key.interpolation, }); })); if (target._primitiveBabylonMeshes) { for (var _i = 0, _a = target._primitiveBabylonMeshes; _i < _a.length; _i++) { var babylonMesh = _a[_i]; if (babylonMesh.morphTargetManager) { var morphTarget = babylonMesh.morphTargetManager.getTarget(targetIndex); var babylonAnimationClone = babylonAnimation.clone(); morphTarget.animations.push(babylonAnimationClone); callback(morphTarget, babylonAnimationClone); } } } }; var this_1 = this; for (var targetIndex = 0; targetIndex < target._numMorphTargets; targetIndex++) { _loop_1(targetIndex); } } }; return WeightAnimationPropertyInfo; }(AnimationPropertyInfo)); /** @internal */ var nodeAnimationData = { translation: [new TransformNodeAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_VECTOR3, "position", getVector3, function () { return 3; })], rotation: [new TransformNodeAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_QUATERNION, "rotationQuaternion", getQuaternion, function () { return 4; })], scale: [new TransformNodeAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_VECTOR3, "scaling", getVector3, function () { return 3; })], weights: [new WeightAnimationPropertyInfo(babylonjs_Animations_animation__WEBPACK_IMPORTED_MODULE_0__.Animation.ANIMATIONTYPE_FLOAT, "influence", getWeights, function (target) { return target._numMorphTargets; })], }; /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts": /*!****************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts ***! \****************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/glTFLoaderInterfaces.ts": /*!*****************************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/glTFLoaderInterfaces.ts ***! \*****************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /***/ }), /***/ "../../../dev/loaders/src/glTF/2.0/index.ts": /*!**************************************************!*\ !*** ../../../dev/loaders/src/glTF/2.0/index.ts ***! \**************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ ArrayItem: () => (/* reexport safe */ _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.ArrayItem), /* harmony export */ EXT_lights_image_based: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.EXT_lights_image_based), /* harmony export */ EXT_mesh_gpu_instancing: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.EXT_mesh_gpu_instancing), /* harmony export */ EXT_meshopt_compression: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.EXT_meshopt_compression), /* harmony export */ EXT_texture_webp: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.EXT_texture_webp), /* harmony export */ ExtrasAsMetadata: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.ExtrasAsMetadata), /* harmony export */ GLTFLoader: () => (/* reexport safe */ _glTFLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoader), /* harmony export */ KHR_animation_pointer: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_animation_pointer), /* harmony export */ KHR_draco_mesh_compression: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_draco_mesh_compression), /* harmony export */ KHR_lights: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_lights), /* harmony export */ KHR_materials_anisotropy: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_materials_anisotropy), /* harmony export */ KHR_materials_clearcoat: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_materials_clearcoat), /* harmony export */ KHR_materials_emissive_strength: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_materials_emissive_strength), /* harmony export */ KHR_materials_ior: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_materials_ior), /* harmony export */ KHR_materials_iridescence: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_materials_iridescence), /* harmony export */ KHR_materials_pbrSpecularGlossiness: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_materials_pbrSpecularGlossiness), /* harmony export */ KHR_materials_sheen: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_materials_sheen), /* harmony export */ KHR_materials_specular: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_materials_specular), /* harmony export */ KHR_materials_translucency: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_materials_translucency), /* harmony export */ KHR_materials_transmission: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_materials_transmission), /* harmony export */ KHR_materials_unlit: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_materials_unlit), /* harmony export */ KHR_materials_variants: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_materials_variants), /* harmony export */ KHR_materials_volume: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_materials_volume), /* harmony export */ KHR_mesh_quantization: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_mesh_quantization), /* harmony export */ KHR_texture_basisu: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_texture_basisu), /* harmony export */ KHR_texture_transform: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_texture_transform), /* harmony export */ KHR_xmp_json_ld: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.KHR_xmp_json_ld), /* harmony export */ MSFT_audio_emitter: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.MSFT_audio_emitter), /* harmony export */ MSFT_lod: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.MSFT_lod), /* harmony export */ MSFT_minecraftMesh: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.MSFT_minecraftMesh), /* harmony export */ MSFT_sRGBFactors: () => (/* reexport safe */ _Extensions_index__WEBPACK_IMPORTED_MODULE_3__.MSFT_sRGBFactors) /* harmony export */ }); /* harmony import */ var _glTFLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./glTFLoader */ "../../../dev/loaders/src/glTF/2.0/glTFLoader.ts"); /* harmony import */ var _glTFLoaderExtension__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./glTFLoaderExtension */ "../../../dev/loaders/src/glTF/2.0/glTFLoaderExtension.ts"); /* harmony import */ var _glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./glTFLoaderInterfaces */ "../../../dev/loaders/src/glTF/2.0/glTFLoaderInterfaces.ts"); /* harmony import */ var _Extensions_index__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Extensions/index */ "../../../dev/loaders/src/glTF/2.0/Extensions/index.ts"); /* eslint-disable import/no-internal-modules */ /***/ }), /***/ "../../../dev/loaders/src/glTF/glTFFileLoader.ts": /*!*******************************************************!*\ !*** ../../../dev/loaders/src/glTF/glTFFileLoader.ts ***! \*******************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GLTFFileLoader: () => (/* binding */ GLTFFileLoader), /* harmony export */ GLTFLoaderAnimationStartMode: () => (/* binding */ GLTFLoaderAnimationStartMode), /* harmony export */ GLTFLoaderCoordinateSystemMode: () => (/* binding */ GLTFLoaderCoordinateSystemMode), /* harmony export */ GLTFLoaderState: () => (/* binding */ GLTFLoaderState) /* harmony export */ }); /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/error */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _glTFValidation__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./glTFValidation */ "../../../dev/loaders/src/glTF/glTFValidation.ts"); function readAsync(arrayBuffer, byteOffset, byteLength) { try { return Promise.resolve(new Uint8Array(arrayBuffer, byteOffset, byteLength)); } catch (e) { return Promise.reject(e); } } function readViewAsync(arrayBufferView, byteOffset, byteLength) { try { if (arrayBufferView.byteOffset + byteLength > arrayBufferView.byteLength) { throw new Error("Array length out of bounds."); } return Promise.resolve(new Uint8Array(arrayBufferView.buffer, arrayBufferView.byteOffset + byteOffset, byteLength)); } catch (e) { return Promise.reject(e); } } /** * Mode that determines the coordinate system to use. */ var GLTFLoaderCoordinateSystemMode; (function (GLTFLoaderCoordinateSystemMode) { /** * Automatically convert the glTF right-handed data to the appropriate system based on the current coordinate system mode of the scene. */ GLTFLoaderCoordinateSystemMode[GLTFLoaderCoordinateSystemMode["AUTO"] = 0] = "AUTO"; /** * Sets the useRightHandedSystem flag on the scene. */ GLTFLoaderCoordinateSystemMode[GLTFLoaderCoordinateSystemMode["FORCE_RIGHT_HANDED"] = 1] = "FORCE_RIGHT_HANDED"; })(GLTFLoaderCoordinateSystemMode || (GLTFLoaderCoordinateSystemMode = {})); /** * Mode that determines what animations will start. */ var GLTFLoaderAnimationStartMode; (function (GLTFLoaderAnimationStartMode) { /** * No animation will start. */ GLTFLoaderAnimationStartMode[GLTFLoaderAnimationStartMode["NONE"] = 0] = "NONE"; /** * The first animation will start. */ GLTFLoaderAnimationStartMode[GLTFLoaderAnimationStartMode["FIRST"] = 1] = "FIRST"; /** * All animations will start. */ GLTFLoaderAnimationStartMode[GLTFLoaderAnimationStartMode["ALL"] = 2] = "ALL"; })(GLTFLoaderAnimationStartMode || (GLTFLoaderAnimationStartMode = {})); /** * Loader state. */ var GLTFLoaderState; (function (GLTFLoaderState) { /** * The asset is loading. */ GLTFLoaderState[GLTFLoaderState["LOADING"] = 0] = "LOADING"; /** * The asset is ready for rendering. */ GLTFLoaderState[GLTFLoaderState["READY"] = 1] = "READY"; /** * The asset is completely loaded. */ GLTFLoaderState[GLTFLoaderState["COMPLETE"] = 2] = "COMPLETE"; })(GLTFLoaderState || (GLTFLoaderState = {})); /** * File loader for loading glTF files into a scene. */ var GLTFFileLoader = /** @class */ (function () { function GLTFFileLoader() { // -------------- // Common options // -------------- /** * Raised when the asset has been parsed */ this.onParsedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); // ---------- // V2 options // ---------- /** * The coordinate system mode. Defaults to AUTO. */ this.coordinateSystemMode = GLTFLoaderCoordinateSystemMode.AUTO; /** * The animation start mode. Defaults to FIRST. */ this.animationStartMode = GLTFLoaderAnimationStartMode.FIRST; /** * Defines if the loader should compile materials before raising the success callback. Defaults to false. */ this.compileMaterials = false; /** * Defines if the loader should also compile materials with clip planes. Defaults to false. */ this.useClipPlane = false; /** * Defines if the loader should compile shadow generators before raising the success callback. Defaults to false. */ this.compileShadowGenerators = false; /** * Defines if the Alpha blended materials are only applied as coverage. * If false, (default) The luminance of each pixel will reduce its opacity to simulate the behaviour of most physical materials. * If true, no extra effects are applied to transparent pixels. */ this.transparencyAsCoverage = false; /** * Defines if the loader should use range requests when load binary glTF files from HTTP. * Enabling will disable offline support and glTF validator. * Defaults to false. */ this.useRangeRequests = false; /** * Defines if the loader should create instances when multiple glTF nodes point to the same glTF mesh. Defaults to true. */ this.createInstances = true; /** * Defines if the loader should always compute the bounding boxes of meshes and not use the min/max values from the position accessor. Defaults to false. */ this.alwaysComputeBoundingBox = false; /** * If true, load all materials defined in the file, even if not used by any mesh. Defaults to false. */ this.loadAllMaterials = false; /** * If true, load only the materials defined in the file. Defaults to false. */ this.loadOnlyMaterials = false; /** * If true, do not load any materials defined in the file. Defaults to false. */ this.skipMaterials = false; /** * If true, load the color (gamma encoded) textures into sRGB buffers (if supported by the GPU), which will yield more accurate results when sampling the texture. Defaults to true. */ this.useSRGBBuffers = true; /** * When loading glTF animations, which are defined in seconds, target them to this FPS. Defaults to 60. */ this.targetFps = 60; /** * Defines if the loader should always compute the nearest common ancestor of the skeleton joints instead of using `skin.skeleton`. Defaults to false. * Set this to true if loading assets with invalid `skin.skeleton` values. */ this.alwaysComputeSkeletonRootNode = false; /** * Function called before loading a url referenced by the asset. * @param url */ this.preprocessUrlAsync = function (url) { return Promise.resolve(url); }; /** * Observable raised when the loader creates a mesh after parsing the glTF properties of the mesh. * Note that the observable is raised as soon as the mesh object is created, meaning some data may not have been setup yet for this mesh (vertex data, morph targets, material, ...) */ this.onMeshLoadedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); /** * Callback raised when the loader creates a skin after parsing the glTF properties of the skin node. * @see https://doc.babylonjs.com/features/featuresDeepDive/importers/glTF/glTFSkinning#ignoring-the-transform-of-the-skinned-mesh * @param node - the transform node that corresponds to the original glTF skin node used for animations * @param skinnedNode - the transform node that is the skinned mesh itself or the parent of the skinned meshes */ this.onSkinLoadedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); /** * Observable raised when the loader creates a texture after parsing the glTF properties of the texture. */ this.onTextureLoadedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); /** * Observable raised when the loader creates a material after parsing the glTF properties of the material. */ this.onMaterialLoadedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); /** * Observable raised when the loader creates a camera after parsing the glTF properties of the camera. */ this.onCameraLoadedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); /** * Observable raised when the asset is completely loaded, immediately before the loader is disposed. * For assets with LODs, raised when all of the LODs are complete. * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise. */ this.onCompleteObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); /** * Observable raised when an error occurs. */ this.onErrorObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); /** * Observable raised after the loader is disposed. */ this.onDisposeObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); /** * Observable raised after a loader extension is created. * Set additional options for a loader extension in this event. */ this.onExtensionLoadedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); /** * Defines if the loader should validate the asset. */ this.validate = false; /** * Observable raised after validation when validate is set to true. The event data is the result of the validation. */ this.onValidatedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); this._loader = null; this._state = null; this._requests = new Array(); /** * Name of the loader ("gltf") */ this.name = "gltf"; /** @internal */ this.extensions = { ".gltf": { isBinary: false }, ".glb": { isBinary: true }, }; /** * Observable raised when the loader state changes. */ this.onLoaderStateChangedObservable = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(); this._logIndentLevel = 0; this._loggingEnabled = false; /** @internal */ this._log = this._logDisabled; this._capturePerformanceCounters = false; /** @internal */ this._startPerformanceCounter = this._startPerformanceCounterDisabled; /** @internal */ this._endPerformanceCounter = this._endPerformanceCounterDisabled; } Object.defineProperty(GLTFFileLoader.prototype, "onParsed", { /** * Raised when the asset has been parsed */ set: function (callback) { if (this._onParsedObserver) { this.onParsedObservable.remove(this._onParsedObserver); } this._onParsedObserver = this.onParsedObservable.add(callback); }, enumerable: false, configurable: true }); Object.defineProperty(GLTFFileLoader.prototype, "onMeshLoaded", { /** * Callback raised when the loader creates a mesh after parsing the glTF properties of the mesh. * Note that the callback is called as soon as the mesh object is created, meaning some data may not have been setup yet for this mesh (vertex data, morph targets, material, ...) */ set: function (callback) { if (this._onMeshLoadedObserver) { this.onMeshLoadedObservable.remove(this._onMeshLoadedObserver); } this._onMeshLoadedObserver = this.onMeshLoadedObservable.add(callback); }, enumerable: false, configurable: true }); Object.defineProperty(GLTFFileLoader.prototype, "onTextureLoaded", { /** * Callback raised when the loader creates a texture after parsing the glTF properties of the texture. */ set: function (callback) { if (this._onTextureLoadedObserver) { this.onTextureLoadedObservable.remove(this._onTextureLoadedObserver); } this._onTextureLoadedObserver = this.onTextureLoadedObservable.add(callback); }, enumerable: false, configurable: true }); Object.defineProperty(GLTFFileLoader.prototype, "onMaterialLoaded", { /** * Callback raised when the loader creates a material after parsing the glTF properties of the material. */ set: function (callback) { if (this._onMaterialLoadedObserver) { this.onMaterialLoadedObservable.remove(this._onMaterialLoadedObserver); } this._onMaterialLoadedObserver = this.onMaterialLoadedObservable.add(callback); }, enumerable: false, configurable: true }); Object.defineProperty(GLTFFileLoader.prototype, "onCameraLoaded", { /** * Callback raised when the loader creates a camera after parsing the glTF properties of the camera. */ set: function (callback) { if (this._onCameraLoadedObserver) { this.onCameraLoadedObservable.remove(this._onCameraLoadedObserver); } this._onCameraLoadedObserver = this.onCameraLoadedObservable.add(callback); }, enumerable: false, configurable: true }); Object.defineProperty(GLTFFileLoader.prototype, "onComplete", { /** * Callback raised when the asset is completely loaded, immediately before the loader is disposed. * For assets with LODs, raised when all of the LODs are complete. * For assets without LODs, raised when the model is complete, immediately after the loader resolves the returned promise. */ set: function (callback) { if (this._onCompleteObserver) { this.onCompleteObservable.remove(this._onCompleteObserver); } this._onCompleteObserver = this.onCompleteObservable.add(callback); }, enumerable: false, configurable: true }); Object.defineProperty(GLTFFileLoader.prototype, "onError", { /** * Callback raised when an error occurs. */ set: function (callback) { if (this._onErrorObserver) { this.onErrorObservable.remove(this._onErrorObserver); } this._onErrorObserver = this.onErrorObservable.add(callback); }, enumerable: false, configurable: true }); Object.defineProperty(GLTFFileLoader.prototype, "onDispose", { /** * Callback raised after the loader is disposed. */ set: function (callback) { if (this._onDisposeObserver) { this.onDisposeObservable.remove(this._onDisposeObserver); } this._onDisposeObserver = this.onDisposeObservable.add(callback); }, enumerable: false, configurable: true }); Object.defineProperty(GLTFFileLoader.prototype, "onExtensionLoaded", { /** * Callback raised after a loader extension is created. */ set: function (callback) { if (this._onExtensionLoadedObserver) { this.onExtensionLoadedObservable.remove(this._onExtensionLoadedObserver); } this._onExtensionLoadedObserver = this.onExtensionLoadedObservable.add(callback); }, enumerable: false, configurable: true }); Object.defineProperty(GLTFFileLoader.prototype, "loggingEnabled", { /** * Defines if the loader logging is enabled. */ get: function () { return this._loggingEnabled; }, set: function (value) { if (this._loggingEnabled === value) { return; } this._loggingEnabled = value; if (this._loggingEnabled) { this._log = this._logEnabled; } else { this._log = this._logDisabled; } }, enumerable: false, configurable: true }); Object.defineProperty(GLTFFileLoader.prototype, "capturePerformanceCounters", { /** * Defines if the loader should capture performance counters. */ get: function () { return this._capturePerformanceCounters; }, set: function (value) { if (this._capturePerformanceCounters === value) { return; } this._capturePerformanceCounters = value; if (this._capturePerformanceCounters) { this._startPerformanceCounter = this._startPerformanceCounterEnabled; this._endPerformanceCounter = this._endPerformanceCounterEnabled; } else { this._startPerformanceCounter = this._startPerformanceCounterDisabled; this._endPerformanceCounter = this._endPerformanceCounterDisabled; } }, enumerable: false, configurable: true }); Object.defineProperty(GLTFFileLoader.prototype, "onValidated", { /** * Callback raised after a loader extension is created. */ set: function (callback) { if (this._onValidatedObserver) { this.onValidatedObservable.remove(this._onValidatedObserver); } this._onValidatedObserver = this.onValidatedObservable.add(callback); }, enumerable: false, configurable: true }); /** * Disposes the loader, releases resources during load, and cancels any outstanding requests. */ GLTFFileLoader.prototype.dispose = function () { if (this._loader) { this._loader.dispose(); this._loader = null; } for (var _i = 0, _a = this._requests; _i < _a.length; _i++) { var request = _a[_i]; request.abort(); } this._requests.length = 0; delete this._progressCallback; this.preprocessUrlAsync = function (url) { return Promise.resolve(url); }; this.onMeshLoadedObservable.clear(); this.onSkinLoadedObservable.clear(); this.onTextureLoadedObservable.clear(); this.onMaterialLoadedObservable.clear(); this.onCameraLoadedObservable.clear(); this.onCompleteObservable.clear(); this.onExtensionLoadedObservable.clear(); this.onDisposeObservable.notifyObservers(undefined); this.onDisposeObservable.clear(); }; /** * @internal */ GLTFFileLoader.prototype.loadFile = function (scene, fileOrUrl, rootUrl, onSuccess, onProgress, useArrayBuffer, onError, name) { var _this = this; if (ArrayBuffer.isView(fileOrUrl)) { this._loadBinary(scene, fileOrUrl, rootUrl, onSuccess, onError, name); return null; } this._progressCallback = onProgress; var fileName = fileOrUrl.name || babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Tools.GetFilename(fileOrUrl); if (useArrayBuffer) { if (this.useRangeRequests) { if (this.validate) { babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("glTF validation is not supported when range requests are enabled"); } var fileRequest_1 = { abort: function () { }, onCompleteObservable: new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Observable(), }; var dataBuffer = { readAsync: function (byteOffset, byteLength) { return new Promise(function (resolve, reject) { _this._loadFile(scene, fileOrUrl, function (data) { resolve(new Uint8Array(data)); }, true, function (error) { reject(error); }, function (webRequest) { webRequest.setRequestHeader("Range", "bytes=".concat(byteOffset, "-").concat(byteOffset + byteLength - 1)); }); }); }, byteLength: 0, }; this._unpackBinaryAsync(new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.DataReader(dataBuffer)).then(function (loaderData) { fileRequest_1.onCompleteObservable.notifyObservers(fileRequest_1); onSuccess(loaderData); }, onError ? function (error) { return onError(undefined, error); } : undefined); return fileRequest_1; } return this._loadFile(scene, fileOrUrl, function (data) { _this._validate(scene, new Uint8Array(data), rootUrl, fileName); _this._unpackBinaryAsync(new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.DataReader({ readAsync: function (byteOffset, byteLength) { return readAsync(data, byteOffset, byteLength); }, byteLength: data.byteLength, })).then(function (loaderData) { onSuccess(loaderData); }, onError ? function (error) { return onError(undefined, error); } : undefined); }, true, onError); } return this._loadFile(scene, fileOrUrl, function (data) { _this._validate(scene, new Uint8Array(data), rootUrl, fileName); onSuccess({ json: _this._parseJson(data) }); }, useArrayBuffer, onError); }; /** * @internal */ GLTFFileLoader.prototype._loadBinary = function (scene, data, rootUrl, onSuccess, onError, fileName) { this._validate(scene, data, rootUrl, fileName); this._unpackBinaryAsync(new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.DataReader({ readAsync: function (byteOffset, byteLength) { return readViewAsync(data, byteOffset, byteLength); }, byteLength: data.byteLength, })).then(function (loaderData) { onSuccess(loaderData); }, onError ? function (error) { return onError(undefined, error); } : undefined); }; /** * @internal */ GLTFFileLoader.prototype.importMeshAsync = function (meshesNames, scene, data, rootUrl, onProgress, fileName) { var _this = this; return Promise.resolve().then(function () { _this.onParsedObservable.notifyObservers(data); _this.onParsedObservable.clear(); _this._log("Loading ".concat(fileName || "")); _this._loader = _this._getLoader(data); return _this._loader.importMeshAsync(meshesNames, scene, null, data, rootUrl, onProgress, fileName); }); }; /** * @internal */ GLTFFileLoader.prototype.loadAsync = function (scene, data, rootUrl, onProgress, fileName) { var _this = this; return Promise.resolve().then(function () { _this.onParsedObservable.notifyObservers(data); _this.onParsedObservable.clear(); _this._log("Loading ".concat(fileName || "")); _this._loader = _this._getLoader(data); return _this._loader.loadAsync(scene, data, rootUrl, onProgress, fileName); }); }; /** * @internal */ GLTFFileLoader.prototype.loadAssetContainerAsync = function (scene, data, rootUrl, onProgress, fileName) { var _this = this; return Promise.resolve().then(function () { _this.onParsedObservable.notifyObservers(data); _this.onParsedObservable.clear(); _this._log("Loading ".concat(fileName || "")); _this._loader = _this._getLoader(data); // Prepare the asset container. var container = new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.AssetContainer(scene); // Get materials/textures when loading to add to container var materials = []; _this.onMaterialLoadedObservable.add(function (material) { materials.push(material); }); var textures = []; _this.onTextureLoadedObservable.add(function (texture) { textures.push(texture); }); var cameras = []; _this.onCameraLoadedObservable.add(function (camera) { cameras.push(camera); }); var morphTargetManagers = []; _this.onMeshLoadedObservable.add(function (mesh) { if (mesh.morphTargetManager) { morphTargetManagers.push(mesh.morphTargetManager); } }); return _this._loader.importMeshAsync(null, scene, container, data, rootUrl, onProgress, fileName).then(function (result) { Array.prototype.push.apply(container.geometries, result.geometries); Array.prototype.push.apply(container.meshes, result.meshes); Array.prototype.push.apply(container.particleSystems, result.particleSystems); Array.prototype.push.apply(container.skeletons, result.skeletons); Array.prototype.push.apply(container.animationGroups, result.animationGroups); Array.prototype.push.apply(container.materials, materials); Array.prototype.push.apply(container.textures, textures); Array.prototype.push.apply(container.lights, result.lights); Array.prototype.push.apply(container.transformNodes, result.transformNodes); Array.prototype.push.apply(container.cameras, cameras); Array.prototype.push.apply(container.morphTargetManagers, morphTargetManagers); return container; }); }); }; /** * @internal */ GLTFFileLoader.prototype.canDirectLoad = function (data) { return ((data.indexOf("asset") !== -1 && data.indexOf("version") !== -1) || data.startsWith("data:base64," + GLTFFileLoader._MagicBase64Encoded) || // this is technically incorrect, but will continue to support for backcompat. data.startsWith("data:;base64," + GLTFFileLoader._MagicBase64Encoded) || data.startsWith("data:application/octet-stream;base64," + GLTFFileLoader._MagicBase64Encoded) || data.startsWith("data:model/gltf-binary;base64," + GLTFFileLoader._MagicBase64Encoded)); }; /** * @internal */ GLTFFileLoader.prototype.directLoad = function (scene, data) { if (data.startsWith("base64," + GLTFFileLoader._MagicBase64Encoded) || // this is technically incorrect, but will continue to support for backcompat. data.startsWith(";base64," + GLTFFileLoader._MagicBase64Encoded) || data.startsWith("application/octet-stream;base64," + GLTFFileLoader._MagicBase64Encoded) || data.startsWith("model/gltf-binary;base64," + GLTFFileLoader._MagicBase64Encoded)) { var arrayBuffer_1 = (0,babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.DecodeBase64UrlToBinary)(data); this._validate(scene, new Uint8Array(arrayBuffer_1)); return this._unpackBinaryAsync(new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.DataReader({ readAsync: function (byteOffset, byteLength) { return readAsync(arrayBuffer_1, byteOffset, byteLength); }, byteLength: arrayBuffer_1.byteLength, })); } this._validate(scene, data); return Promise.resolve({ json: this._parseJson(data) }); }; /** @internal */ GLTFFileLoader.prototype.createPlugin = function () { return new GLTFFileLoader(); }; Object.defineProperty(GLTFFileLoader.prototype, "loaderState", { /** * The loader state or null if the loader is not active. */ get: function () { return this._state; }, enumerable: false, configurable: true }); /** * Returns a promise that resolves when the asset is completely loaded. * @returns a promise that resolves when the asset is completely loaded. */ GLTFFileLoader.prototype.whenCompleteAsync = function () { var _this = this; return new Promise(function (resolve, reject) { _this.onCompleteObservable.addOnce(function () { resolve(); }); _this.onErrorObservable.addOnce(function (reason) { reject(reason); }); }); }; /** * @internal */ GLTFFileLoader.prototype._setState = function (state) { if (this._state === state) { return; } this._state = state; this.onLoaderStateChangedObservable.notifyObservers(this._state); this._log(GLTFLoaderState[this._state]); }; /** * @internal */ GLTFFileLoader.prototype._loadFile = function (scene, fileOrUrl, onSuccess, useArrayBuffer, onError, onOpened) { var _this = this; var request = scene._loadFile(fileOrUrl, onSuccess, function (event) { _this._onProgress(event, request); }, true, useArrayBuffer, onError, onOpened); request.onCompleteObservable.add(function (request) { _this._requests.splice(_this._requests.indexOf(request), 1); }); this._requests.push(request); return request; }; GLTFFileLoader.prototype._onProgress = function (event, request) { if (!this._progressCallback) { return; } request._lengthComputable = event.lengthComputable; request._loaded = event.loaded; request._total = event.total; var lengthComputable = true; var loaded = 0; var total = 0; for (var _i = 0, _a = this._requests; _i < _a.length; _i++) { var request_1 = _a[_i]; if (request_1._lengthComputable === undefined || request_1._loaded === undefined || request_1._total === undefined) { return; } lengthComputable = lengthComputable && request_1._lengthComputable; loaded += request_1._loaded; total += request_1._total; } this._progressCallback({ lengthComputable: lengthComputable, loaded: loaded, total: lengthComputable ? total : 0, }); }; GLTFFileLoader.prototype._validate = function (scene, data, rootUrl, fileName) { var _this = this; if (rootUrl === void 0) { rootUrl = ""; } if (fileName === void 0) { fileName = ""; } if (!this.validate) { return; } this._startPerformanceCounter("Validate JSON"); _glTFValidation__WEBPACK_IMPORTED_MODULE_1__.GLTFValidation.ValidateAsync(data, rootUrl, fileName, function (uri) { return _this.preprocessUrlAsync(rootUrl + uri).then(function (url) { return scene._loadFileAsync(url, undefined, true, true); }); }).then(function (result) { _this._endPerformanceCounter("Validate JSON"); _this.onValidatedObservable.notifyObservers(result); _this.onValidatedObservable.clear(); }, function (reason) { _this._endPerformanceCounter("Validate JSON"); babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Tools.Warn("Failed to validate: ".concat(reason.message)); _this.onValidatedObservable.clear(); }); }; GLTFFileLoader.prototype._getLoader = function (loaderData) { var asset = loaderData.json.asset || {}; this._log("Asset version: ".concat(asset.version)); asset.minVersion && this._log("Asset minimum version: ".concat(asset.minVersion)); asset.generator && this._log("Asset generator: ".concat(asset.generator)); var version = GLTFFileLoader._parseVersion(asset.version); if (!version) { throw new Error("Invalid version: " + asset.version); } if (asset.minVersion !== undefined) { var minVersion = GLTFFileLoader._parseVersion(asset.minVersion); if (!minVersion) { throw new Error("Invalid minimum version: " + asset.minVersion); } if (GLTFFileLoader._compareVersion(minVersion, { major: 2, minor: 0 }) > 0) { throw new Error("Incompatible minimum version: " + asset.minVersion); } } var createLoaders = { 1: GLTFFileLoader._CreateGLTF1Loader, 2: GLTFFileLoader._CreateGLTF2Loader, }; var createLoader = createLoaders[version.major]; if (!createLoader) { throw new Error("Unsupported version: " + asset.version); } return createLoader(this); }; GLTFFileLoader.prototype._parseJson = function (json) { this._startPerformanceCounter("Parse JSON"); this._log("JSON length: ".concat(json.length)); var parsed = JSON.parse(json); this._endPerformanceCounter("Parse JSON"); return parsed; }; GLTFFileLoader.prototype._unpackBinaryAsync = function (dataReader) { var _this = this; this._startPerformanceCounter("Unpack Binary"); // Read magic + version + length + json length + json format return dataReader.loadAsync(20).then(function () { var Binary = { Magic: 0x46546c67, }; var magic = dataReader.readUint32(); if (magic !== Binary.Magic) { throw new babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.RuntimeError("Unexpected magic: " + magic, babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.ErrorCodes.GLTFLoaderUnexpectedMagicError); } var version = dataReader.readUint32(); if (_this.loggingEnabled) { _this._log("Binary version: ".concat(version)); } var length = dataReader.readUint32(); if (!_this.useRangeRequests && length !== dataReader.buffer.byteLength) { babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Logger.Warn("Length in header does not match actual data length: ".concat(length, " != ").concat(dataReader.buffer.byteLength)); } var unpacked; switch (version) { case 1: { unpacked = _this._unpackBinaryV1Async(dataReader, length); break; } case 2: { unpacked = _this._unpackBinaryV2Async(dataReader, length); break; } default: { throw new Error("Unsupported version: " + version); } } _this._endPerformanceCounter("Unpack Binary"); return unpacked; }); }; GLTFFileLoader.prototype._unpackBinaryV1Async = function (dataReader, length) { var ContentFormat = { JSON: 0, }; var contentLength = dataReader.readUint32(); var contentFormat = dataReader.readUint32(); if (contentFormat !== ContentFormat.JSON) { throw new Error("Unexpected content format: ".concat(contentFormat)); } var bodyLength = length - dataReader.byteOffset; var data = { json: this._parseJson(dataReader.readString(contentLength)), bin: null }; if (bodyLength !== 0) { var startByteOffset_1 = dataReader.byteOffset; data.bin = { readAsync: function (byteOffset, byteLength) { return dataReader.buffer.readAsync(startByteOffset_1 + byteOffset, byteLength); }, byteLength: bodyLength, }; } return Promise.resolve(data); }; GLTFFileLoader.prototype._unpackBinaryV2Async = function (dataReader, length) { var _this = this; var ChunkFormat = { JSON: 0x4e4f534a, BIN: 0x004e4942, }; // Read the JSON chunk header. var chunkLength = dataReader.readUint32(); var chunkFormat = dataReader.readUint32(); if (chunkFormat !== ChunkFormat.JSON) { throw new Error("First chunk format is not JSON"); } // Bail if there are no other chunks. if (dataReader.byteOffset + chunkLength === length) { return dataReader.loadAsync(chunkLength).then(function () { return { json: _this._parseJson(dataReader.readString(chunkLength)), bin: null }; }); } // Read the JSON chunk and the length and type of the next chunk. return dataReader.loadAsync(chunkLength + 8).then(function () { var data = { json: _this._parseJson(dataReader.readString(chunkLength)), bin: null }; var readAsync = function () { var chunkLength = dataReader.readUint32(); var chunkFormat = dataReader.readUint32(); switch (chunkFormat) { case ChunkFormat.JSON: { throw new Error("Unexpected JSON chunk"); } case ChunkFormat.BIN: { var startByteOffset_2 = dataReader.byteOffset; data.bin = { readAsync: function (byteOffset, byteLength) { return dataReader.buffer.readAsync(startByteOffset_2 + byteOffset, byteLength); }, byteLength: chunkLength, }; dataReader.skipBytes(chunkLength); break; } default: { // ignore unrecognized chunkFormat dataReader.skipBytes(chunkLength); break; } } if (dataReader.byteOffset !== length) { return dataReader.loadAsync(8).then(readAsync); } return Promise.resolve(data); }; return readAsync(); }); }; GLTFFileLoader._parseVersion = function (version) { if (version === "1.0" || version === "1.0.1") { return { major: 1, minor: 0, }; } var match = (version + "").match(/^(\d+)\.(\d+)/); if (!match) { return null; } return { major: parseInt(match[1]), minor: parseInt(match[2]), }; }; GLTFFileLoader._compareVersion = function (a, b) { if (a.major > b.major) { return 1; } if (a.major < b.major) { return -1; } if (a.minor > b.minor) { return 1; } if (a.minor < b.minor) { return -1; } return 0; }; /** * @internal */ GLTFFileLoader.prototype._logOpen = function (message) { this._log(message); this._logIndentLevel++; }; /** @internal */ GLTFFileLoader.prototype._logClose = function () { --this._logIndentLevel; }; GLTFFileLoader.prototype._logEnabled = function (message) { var spaces = GLTFFileLoader._logSpaces.substr(0, this._logIndentLevel * 2); babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Logger.Log("".concat(spaces).concat(message)); }; GLTFFileLoader.prototype._logDisabled = function (message) { }; GLTFFileLoader.prototype._startPerformanceCounterEnabled = function (counterName) { babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Tools.StartPerformanceCounter(counterName); }; GLTFFileLoader.prototype._startPerformanceCounterDisabled = function (counterName) { }; GLTFFileLoader.prototype._endPerformanceCounterEnabled = function (counterName) { babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.Tools.EndPerformanceCounter(counterName); }; GLTFFileLoader.prototype._endPerformanceCounterDisabled = function (counterName) { }; // ---------- // V1 options // ---------- /** * Set this property to false to disable incremental loading which delays the loader from calling the success callback until after loading the meshes and shaders. * Textures always loads asynchronously. For example, the success callback can compute the bounding information of the loaded meshes when incremental loading is disabled. * Defaults to true. * @internal */ GLTFFileLoader.IncrementalLoading = true; /** * Set this property to true in order to work with homogeneous coordinates, available with some converters and exporters. * Defaults to false. See https://en.wikipedia.org/wiki/Homogeneous_coordinates. * @internal */ GLTFFileLoader.HomogeneousCoordinates = false; GLTFFileLoader._MagicBase64Encoded = "Z2xURg"; // "glTF" base64 encoded (without the quotes!) GLTFFileLoader._logSpaces = " "; return GLTFFileLoader; }()); if (babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.SceneLoader) { babylonjs_Misc_observable__WEBPACK_IMPORTED_MODULE_0__.SceneLoader.RegisterPlugin(new GLTFFileLoader()); } /***/ }), /***/ "../../../dev/loaders/src/glTF/glTFValidation.ts": /*!*******************************************************!*\ !*** ../../../dev/loaders/src/glTF/glTFValidation.ts ***! \*******************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GLTFValidation: () => (/* binding */ GLTFValidation) /* harmony export */ }); /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! babylonjs/Misc/tools */ "babylonjs/Misc/observable"); /* harmony import */ var babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__); function validateAsync(data, rootUrl, fileName, getExternalResource) { var options = { externalResourceFunction: function (uri) { return getExternalResource(uri).then(function (value) { return new Uint8Array(value); }); }, }; if (fileName) { options.uri = rootUrl === "file:" ? fileName : rootUrl + fileName; } return data instanceof ArrayBuffer ? GLTFValidator.validateBytes(new Uint8Array(data), options) : GLTFValidator.validateString(data, options); } /** * The worker function that gets converted to a blob url to pass into a worker. */ function workerFunc() { var pendingExternalResources = []; onmessage = function (message) { var data = message.data; switch (data.id) { case "init": { importScripts(data.url); break; } case "validate": { validateAsync(data.data, data.rootUrl, data.fileName, function (uri) { return new Promise(function (resolve, reject) { var index = pendingExternalResources.length; pendingExternalResources.push({ resolve: resolve, reject: reject }); postMessage({ id: "getExternalResource", index: index, uri: uri }); }); }).then(function (value) { postMessage({ id: "validate.resolve", value: value }); }, function (reason) { postMessage({ id: "validate.reject", reason: reason }); }); break; } case "getExternalResource.resolve": { pendingExternalResources[data.index].resolve(data.value); break; } case "getExternalResource.reject": { pendingExternalResources[data.index].reject(data.reason); break; } } }; } /** * glTF validation */ var GLTFValidation = /** @class */ (function () { function GLTFValidation() { } /** * Validate a glTF asset using the glTF-Validator. * @param data The JSON of a glTF or the array buffer of a binary glTF * @param rootUrl The root url for the glTF * @param fileName The file name for the glTF * @param getExternalResource The callback to get external resources for the glTF validator * @returns A promise that resolves with the glTF validation results once complete */ GLTFValidation.ValidateAsync = function (data, rootUrl, fileName, getExternalResource) { var _this = this; var dataCopy = ArrayBuffer.isView(data) ? data.slice().buffer : data; if (typeof Worker === "function") { return new Promise(function (resolve, reject) { var workerContent = "".concat(validateAsync, "(").concat(workerFunc, ")()"); var workerBlobUrl = URL.createObjectURL(new Blob([workerContent], { type: "application/javascript" })); var worker = new Worker(workerBlobUrl); var onError = function (error) { worker.removeEventListener("error", onError); worker.removeEventListener("message", onMessage); reject(error); }; var onMessage = function (message) { var data = message.data; switch (data.id) { case "getExternalResource": { getExternalResource(data.uri).then(function (value) { worker.postMessage({ id: "getExternalResource.resolve", index: data.index, value: value }, [value]); }, function (reason) { worker.postMessage({ id: "getExternalResource.reject", index: data.index, reason: reason }); }); break; } case "validate.resolve": { worker.removeEventListener("error", onError); worker.removeEventListener("message", onMessage); resolve(data.value); worker.terminate(); break; } case "validate.reject": { worker.removeEventListener("error", onError); worker.removeEventListener("message", onMessage); reject(data.reason); worker.terminate(); } } }; worker.addEventListener("error", onError); worker.addEventListener("message", onMessage); worker.postMessage({ id: "init", url: babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__.Tools.GetBabylonScriptURL(_this.Configuration.url) }); worker.postMessage({ id: "validate", data: dataCopy, rootUrl: rootUrl, fileName: fileName }); }); } else { if (!this._LoadScriptPromise) { this._LoadScriptPromise = babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__.Tools.LoadBabylonScriptAsync(this.Configuration.url); } return this._LoadScriptPromise.then(function () { return validateAsync(dataCopy, rootUrl, fileName, getExternalResource); }); } }; /** * The configuration. Defaults to `{ url: "https://cdn.babylonjs.com/gltf_validator.js" }`. */ GLTFValidation.Configuration = { url: "".concat(babylonjs_Misc_tools__WEBPACK_IMPORTED_MODULE_0__.Tools._DefaultCdnUrl, "/gltf_validator.js"), }; return GLTFValidation; }()); /***/ }), /***/ "../../../dev/loaders/src/glTF/index.ts": /*!**********************************************!*\ !*** ../../../dev/loaders/src/glTF/index.ts ***! \**********************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GLTF1: () => (/* reexport module object */ _1_0_index__WEBPACK_IMPORTED_MODULE_2__), /* harmony export */ GLTF2: () => (/* reexport module object */ _2_0_index__WEBPACK_IMPORTED_MODULE_3__), /* harmony export */ GLTFFileLoader: () => (/* reexport safe */ _glTFFileLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFFileLoader), /* harmony export */ GLTFLoaderAnimationStartMode: () => (/* reexport safe */ _glTFFileLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderAnimationStartMode), /* harmony export */ GLTFLoaderCoordinateSystemMode: () => (/* reexport safe */ _glTFFileLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderCoordinateSystemMode), /* harmony export */ GLTFLoaderState: () => (/* reexport safe */ _glTFFileLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderState), /* harmony export */ GLTFValidation: () => (/* reexport safe */ _glTFValidation__WEBPACK_IMPORTED_MODULE_1__.GLTFValidation) /* harmony export */ }); /* harmony import */ var _glTFFileLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./glTFFileLoader */ "../../../dev/loaders/src/glTF/glTFFileLoader.ts"); /* harmony import */ var _glTFValidation__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./glTFValidation */ "../../../dev/loaders/src/glTF/glTFValidation.ts"); /* harmony import */ var _1_0_index__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./1.0/index */ "../../../dev/loaders/src/glTF/1.0/index.ts"); /* harmony import */ var _2_0_index__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./2.0/index */ "../../../dev/loaders/src/glTF/2.0/index.ts"); /* eslint-disable import/no-internal-modules */ /***/ }), /***/ "../../../dev/loaders/src/index.ts": /*!*****************************************!*\ !*** ../../../dev/loaders/src/index.ts ***! \*****************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GLTF1: () => (/* reexport safe */ _glTF_index__WEBPACK_IMPORTED_MODULE_0__.GLTF1), /* harmony export */ GLTF2: () => (/* reexport safe */ _glTF_index__WEBPACK_IMPORTED_MODULE_0__.GLTF2), /* harmony export */ GLTFFileLoader: () => (/* reexport safe */ _glTF_index__WEBPACK_IMPORTED_MODULE_0__.GLTFFileLoader), /* harmony export */ GLTFLoaderAnimationStartMode: () => (/* reexport safe */ _glTF_index__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderAnimationStartMode), /* harmony export */ GLTFLoaderCoordinateSystemMode: () => (/* reexport safe */ _glTF_index__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderCoordinateSystemMode), /* harmony export */ GLTFLoaderState: () => (/* reexport safe */ _glTF_index__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderState), /* harmony export */ GLTFValidation: () => (/* reexport safe */ _glTF_index__WEBPACK_IMPORTED_MODULE_0__.GLTFValidation), /* harmony export */ MTLFileLoader: () => (/* reexport safe */ _OBJ_index__WEBPACK_IMPORTED_MODULE_1__.MTLFileLoader), /* harmony export */ OBJFileLoader: () => (/* reexport safe */ _OBJ_index__WEBPACK_IMPORTED_MODULE_1__.OBJFileLoader), /* harmony export */ STLFileLoader: () => (/* reexport safe */ _STL_index__WEBPACK_IMPORTED_MODULE_2__.STLFileLoader), /* harmony export */ SolidParser: () => (/* reexport safe */ _OBJ_index__WEBPACK_IMPORTED_MODULE_1__.SolidParser) /* harmony export */ }); /* harmony import */ var _glTF_index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./glTF/index */ "../../../dev/loaders/src/glTF/index.ts"); /* harmony import */ var _OBJ_index__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./OBJ/index */ "../../../dev/loaders/src/OBJ/index.ts"); /* harmony import */ var _STL_index__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./STL/index */ "../../../dev/loaders/src/STL/index.ts"); /* eslint-disable import/no-internal-modules */ /***/ }), /***/ "../../../lts/loaders/src/legacy/legacy-glTF.ts": /*!******************************************************!*\ !*** ../../../lts/loaders/src/legacy/legacy-glTF.ts ***! \******************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GLTFFileLoader: () => (/* reexport safe */ loaders_glTF_glTFFileLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFFileLoader), /* harmony export */ GLTFLoaderAnimationStartMode: () => (/* reexport safe */ loaders_glTF_glTFFileLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderAnimationStartMode), /* harmony export */ GLTFLoaderCoordinateSystemMode: () => (/* reexport safe */ loaders_glTF_glTFFileLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderCoordinateSystemMode), /* harmony export */ GLTFLoaderState: () => (/* reexport safe */ loaders_glTF_glTFFileLoader__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderState), /* harmony export */ GLTFValidation: () => (/* reexport safe */ loaders_glTF_glTFValidation__WEBPACK_IMPORTED_MODULE_1__.GLTFValidation) /* harmony export */ }); /* harmony import */ var loaders_glTF_glTFFileLoader__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! loaders/glTF/glTFFileLoader */ "../../../dev/loaders/src/glTF/glTFFileLoader.ts"); /* harmony import */ var loaders_glTF_glTFValidation__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! loaders/glTF/glTFValidation */ "../../../dev/loaders/src/glTF/glTFValidation.ts"); /** * This is the entry point for the UMD module. * The entry point for a future ESM package should be index.ts */ var globalObject = typeof __webpack_require__.g !== "undefined" ? __webpack_require__.g : typeof window !== "undefined" ? window : undefined; if (typeof globalObject !== "undefined") { globalObject.BABYLON = globalObject.BABYLON || {}; for (var key in loaders_glTF_glTFFileLoader__WEBPACK_IMPORTED_MODULE_0__) { globalObject.BABYLON[key] = loaders_glTF_glTFFileLoader__WEBPACK_IMPORTED_MODULE_0__[key]; } for (var key in loaders_glTF_glTFValidation__WEBPACK_IMPORTED_MODULE_1__) { globalObject.BABYLON[key] = loaders_glTF_glTFValidation__WEBPACK_IMPORTED_MODULE_1__[key]; } } /***/ }), /***/ "../../../lts/loaders/src/legacy/legacy-glTF1.ts": /*!*******************************************************!*\ !*** ../../../lts/loaders/src/legacy/legacy-glTF1.ts ***! \*******************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GLTF1: () => (/* reexport module object */ loaders_glTF_1_0_index__WEBPACK_IMPORTED_MODULE_0__) /* harmony export */ }); /* harmony import */ var loaders_glTF_1_0_index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! loaders/glTF/1.0/index */ "../../../dev/loaders/src/glTF/1.0/index.ts"); /* eslint-disable import/no-internal-modules */ /** * This is the entry point for the UMD module. * The entry point for a future ESM package should be index.ts */ var globalObject = typeof __webpack_require__.g !== "undefined" ? __webpack_require__.g : typeof window !== "undefined" ? window : undefined; if (typeof globalObject !== "undefined") { globalObject.BABYLON = globalObject.BABYLON || {}; globalObject.BABYLON.GLTF1 = globalObject.BABYLON.GLTF1 || {}; for (var key in loaders_glTF_1_0_index__WEBPACK_IMPORTED_MODULE_0__) { globalObject.BABYLON.GLTF1[key] = loaders_glTF_1_0_index__WEBPACK_IMPORTED_MODULE_0__[key]; } } /***/ }), /***/ "../../../lts/loaders/src/legacy/legacy-glTF2.ts": /*!*******************************************************!*\ !*** ../../../lts/loaders/src/legacy/legacy-glTF2.ts ***! \*******************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GLTF2: () => (/* reexport module object */ loaders_glTF_2_0_index__WEBPACK_IMPORTED_MODULE_2__) /* harmony export */ }); /* harmony import */ var loaders_glTF_2_0_Extensions_index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! loaders/glTF/2.0/Extensions/index */ "../../../dev/loaders/src/glTF/2.0/Extensions/index.ts"); /* harmony import */ var loaders_glTF_2_0_glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! loaders/glTF/2.0/glTFLoaderInterfaces */ "../../../dev/loaders/src/glTF/2.0/glTFLoaderInterfaces.ts"); /* harmony import */ var loaders_glTF_2_0_index__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! loaders/glTF/2.0/index */ "../../../dev/loaders/src/glTF/2.0/index.ts"); /* eslint-disable import/no-internal-modules */ /** * This is the entry point for the UMD module. * The entry point for a future ESM package should be index.ts */ var globalObject = typeof __webpack_require__.g !== "undefined" ? __webpack_require__.g : typeof window !== "undefined" ? window : undefined; if (typeof globalObject !== "undefined") { globalObject.BABYLON = globalObject.BABYLON || {}; var BABYLON_1 = globalObject.BABYLON; BABYLON_1.GLTF2 = BABYLON_1.GLTF2 || {}; BABYLON_1.GLTF2.Loader = BABYLON_1.GLTF2.Loader || {}; BABYLON_1.GLTF2.Loader.Extensions = BABYLON_1.GLTF2.Loader.Extensions || {}; var keys = []; for (var key in loaders_glTF_2_0_Extensions_index__WEBPACK_IMPORTED_MODULE_0__) { BABYLON_1.GLTF2.Loader.Extensions[key] = loaders_glTF_2_0_Extensions_index__WEBPACK_IMPORTED_MODULE_0__[key]; keys.push(key); } for (var key in loaders_glTF_2_0_glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_1__) { BABYLON_1.GLTF2.Loader[key] = loaders_glTF_2_0_glTFLoaderInterfaces__WEBPACK_IMPORTED_MODULE_1__[key]; keys.push(key); } for (var key in loaders_glTF_2_0_index__WEBPACK_IMPORTED_MODULE_2__) { // Prevent Reassignment. if (keys.indexOf(key) > -1) { continue; } BABYLON_1.GLTF2[key] = loaders_glTF_2_0_index__WEBPACK_IMPORTED_MODULE_2__[key]; } } /***/ }), /***/ "../../../lts/loaders/src/legacy/legacy-objFileLoader.ts": /*!***************************************************************!*\ !*** ../../../lts/loaders/src/legacy/legacy-objFileLoader.ts ***! \***************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ MTLFileLoader: () => (/* reexport safe */ loaders_OBJ_index__WEBPACK_IMPORTED_MODULE_0__.MTLFileLoader), /* harmony export */ OBJFileLoader: () => (/* reexport safe */ loaders_OBJ_index__WEBPACK_IMPORTED_MODULE_0__.OBJFileLoader), /* harmony export */ SolidParser: () => (/* reexport safe */ loaders_OBJ_index__WEBPACK_IMPORTED_MODULE_0__.SolidParser) /* harmony export */ }); /* harmony import */ var loaders_OBJ_index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! loaders/OBJ/index */ "../../../dev/loaders/src/OBJ/index.ts"); /* eslint-disable import/no-internal-modules */ /** * This is the entry point for the UMD module. * The entry point for a future ESM package should be index.ts */ var globalObject = typeof __webpack_require__.g !== "undefined" ? __webpack_require__.g : typeof window !== "undefined" ? window : undefined; if (typeof globalObject !== "undefined") { for (var key in loaders_OBJ_index__WEBPACK_IMPORTED_MODULE_0__) { if (!globalObject.BABYLON[key]) { globalObject.BABYLON[key] = loaders_OBJ_index__WEBPACK_IMPORTED_MODULE_0__[key]; } } } /***/ }), /***/ "../../../lts/loaders/src/legacy/legacy-stlFileLoader.ts": /*!***************************************************************!*\ !*** ../../../lts/loaders/src/legacy/legacy-stlFileLoader.ts ***! \***************************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ STLFileLoader: () => (/* reexport safe */ loaders_STL_index__WEBPACK_IMPORTED_MODULE_0__.STLFileLoader) /* harmony export */ }); /* harmony import */ var loaders_STL_index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! loaders/STL/index */ "../../../dev/loaders/src/STL/index.ts"); /* eslint-disable import/no-internal-modules */ /** * This is the entry point for the UMD module. * The entry point for a future ESM package should be index.ts */ var globalObject = typeof __webpack_require__.g !== "undefined" ? __webpack_require__.g : typeof window !== "undefined" ? window : undefined; if (typeof globalObject !== "undefined") { for (var key in loaders_STL_index__WEBPACK_IMPORTED_MODULE_0__) { if (!globalObject.BABYLON[key]) { globalObject.BABYLON[key] = loaders_STL_index__WEBPACK_IMPORTED_MODULE_0__[key]; } } } /***/ }), /***/ "../../../lts/loaders/src/legacy/legacy.ts": /*!*************************************************!*\ !*** ../../../lts/loaders/src/legacy/legacy.ts ***! \*************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ GLTF1: () => (/* reexport safe */ loaders_index__WEBPACK_IMPORTED_MODULE_0__.GLTF1), /* harmony export */ GLTF2: () => (/* reexport safe */ loaders_index__WEBPACK_IMPORTED_MODULE_0__.GLTF2), /* harmony export */ GLTFFileLoader: () => (/* reexport safe */ loaders_index__WEBPACK_IMPORTED_MODULE_0__.GLTFFileLoader), /* harmony export */ GLTFLoaderAnimationStartMode: () => (/* reexport safe */ loaders_index__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderAnimationStartMode), /* harmony export */ GLTFLoaderCoordinateSystemMode: () => (/* reexport safe */ loaders_index__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderCoordinateSystemMode), /* harmony export */ GLTFLoaderState: () => (/* reexport safe */ loaders_index__WEBPACK_IMPORTED_MODULE_0__.GLTFLoaderState), /* harmony export */ GLTFValidation: () => (/* reexport safe */ loaders_index__WEBPACK_IMPORTED_MODULE_0__.GLTFValidation), /* harmony export */ MTLFileLoader: () => (/* reexport safe */ loaders_index__WEBPACK_IMPORTED_MODULE_0__.MTLFileLoader), /* harmony export */ OBJFileLoader: () => (/* reexport safe */ loaders_index__WEBPACK_IMPORTED_MODULE_0__.OBJFileLoader), /* harmony export */ STLFileLoader: () => (/* reexport safe */ loaders_index__WEBPACK_IMPORTED_MODULE_0__.STLFileLoader), /* harmony export */ SolidParser: () => (/* reexport safe */ loaders_index__WEBPACK_IMPORTED_MODULE_0__.SolidParser) /* harmony export */ }); /* harmony import */ var loaders_index__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! loaders/index */ "../../../dev/loaders/src/index.ts"); /* harmony import */ var _legacy_glTF__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./legacy-glTF */ "../../../lts/loaders/src/legacy/legacy-glTF.ts"); /* harmony import */ var _legacy_glTF1__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./legacy-glTF1 */ "../../../lts/loaders/src/legacy/legacy-glTF1.ts"); /* harmony import */ var _legacy_glTF2__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./legacy-glTF2 */ "../../../lts/loaders/src/legacy/legacy-glTF2.ts"); /* harmony import */ var _legacy_objFileLoader__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! ./legacy-objFileLoader */ "../../../lts/loaders/src/legacy/legacy-objFileLoader.ts"); /* harmony import */ var _legacy_stlFileLoader__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! ./legacy-stlFileLoader */ "../../../lts/loaders/src/legacy/legacy-stlFileLoader.ts"); /* eslint-disable import/export */ /* eslint-disable import/no-internal-modules */ /***/ }), /***/ "babylonjs/Misc/observable": /*!****************************************************************************************************!*\ !*** external {"root":"BABYLON","commonjs":"babylonjs","commonjs2":"babylonjs","amd":"babylonjs"} ***! \****************************************************************************************************/ /***/ ((module) => { module.exports = __WEBPACK_EXTERNAL_MODULE_babylonjs_Misc_observable__; /***/ }), /***/ "../../../../node_modules/tslib/tslib.es6.mjs": /*!****************************************************!*\ !*** ../../../../node_modules/tslib/tslib.es6.mjs ***! \****************************************************/ /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ __addDisposableResource: () => (/* binding */ __addDisposableResource), /* harmony export */ __assign: () => (/* binding */ __assign), /* harmony export */ __asyncDelegator: () => (/* binding */ __asyncDelegator), /* harmony export */ __asyncGenerator: () => (/* binding */ __asyncGenerator), /* harmony export */ __asyncValues: () => (/* binding */ __asyncValues), /* harmony export */ __await: () => (/* binding */ __await), /* harmony export */ __awaiter: () => (/* binding */ __awaiter), /* harmony export */ __classPrivateFieldGet: () => (/* binding */ __classPrivateFieldGet), /* harmony export */ __classPrivateFieldIn: () => (/* binding */ __classPrivateFieldIn), /* harmony export */ __classPrivateFieldSet: () => (/* binding */ __classPrivateFieldSet), /* harmony export */ __createBinding: () => (/* binding */ __createBinding), /* harmony export */ __decorate: () => (/* binding */ __decorate), /* harmony export */ __disposeResources: () => (/* binding */ __disposeResources), /* harmony export */ __esDecorate: () => (/* binding */ __esDecorate), /* harmony export */ __exportStar: () => (/* binding */ __exportStar), /* harmony export */ __extends: () => (/* binding */ __extends), /* harmony export */ __generator: () => (/* binding */ __generator), /* harmony export */ __importDefault: () => (/* binding */ __importDefault), /* harmony export */ __importStar: () => (/* binding */ __importStar), /* harmony export */ __makeTemplateObject: () => (/* binding */ __makeTemplateObject), /* harmony export */ __metadata: () => (/* binding */ __metadata), /* harmony export */ __param: () => (/* binding */ __param), /* harmony export */ __propKey: () => (/* binding */ __propKey), /* harmony export */ __read: () => (/* binding */ __read), /* harmony export */ __rest: () => (/* binding */ __rest), /* harmony export */ __runInitializers: () => (/* binding */ __runInitializers), /* harmony export */ __setFunctionName: () => (/* binding */ __setFunctionName), /* harmony export */ __spread: () => (/* binding */ __spread), /* harmony export */ __spreadArray: () => (/* binding */ __spreadArray), /* harmony export */ __spreadArrays: () => (/* binding */ __spreadArrays), /* harmony export */ __values: () => (/* binding */ __values), /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol */ var extendStatics = function(d, b) { extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; return extendStatics(d, b); }; function __extends(d, b) { if (typeof b !== "function" && b !== null) throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); } var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; } return __assign.apply(this, arguments); } function __rest(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; } function __decorate(decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; } function __param(paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } } function __esDecorate(ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) { function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; } var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value"; var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null; var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {}); var _, done = false; for (var i = decorators.length - 1; i >= 0; i--) { var context = {}; for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p]; for (var p in contextIn.access) context.access[p] = contextIn.access[p]; context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); }; var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context); if (kind === "accessor") { if (result === void 0) continue; if (result === null || typeof result !== "object") throw new TypeError("Object expected"); if (_ = accept(result.get)) descriptor.get = _; if (_ = accept(result.set)) descriptor.set = _; if (_ = accept(result.init)) initializers.unshift(_); } else if (_ = accept(result)) { if (kind === "field") initializers.unshift(_); else descriptor[key] = _; } } if (target) Object.defineProperty(target, contextIn.name, descriptor); done = true; }; function __runInitializers(thisArg, initializers, value) { var useValue = arguments.length > 2; for (var i = 0; i < initializers.length; i++) { value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg); } return useValue ? value : void 0; }; function __propKey(x) { return typeof x === "symbol" ? x : "".concat(x); }; function __setFunctionName(f, name, prefix) { if (typeof name === "symbol") name = name.description ? "[".concat(name.description, "]") : ""; return Object.defineProperty(f, "name", { configurable: true, value: prefix ? "".concat(prefix, " ", name) : name }); }; function __metadata(metadataKey, metadataValue) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue); } function __awaiter(thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); } function __generator(thisArg, body) { var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; function verb(n) { return function (v) { return step([n, v]); }; } function step(op) { if (f) throw new TypeError("Generator is already executing."); while (g && (g = 0, op[0] && (_ = 0)), _) try { if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; if (y = 0, t) op = [op[0] & 2, t.value]; switch (op[0]) { case 0: case 1: t = op; break; case 4: _.label++; return { value: op[1], done: false }; case 5: _.label++; y = op[1]; op = [0]; continue; case 7: op = _.ops.pop(); _.trys.pop(); continue; default: if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } if (t[2]) _.ops.pop(); _.trys.pop(); continue; } op = body.call(thisArg, _); } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; } } var __createBinding = Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; }); function __exportStar(m, o) { for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(o, p)) __createBinding(o, m, p); } function __values(o) { var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0; if (m) return m.call(o); if (o && typeof o.length === "number") return { next: function () { if (o && i >= o.length) o = void 0; return { value: o && o[i++], done: !o }; } }; throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined."); } function __read(o, n) { var m = typeof Symbol === "function" && o[Symbol.iterator]; if (!m) return o; var i = m.call(o), r, ar = [], e; try { while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); } catch (error) { e = { error: error }; } finally { try { if (r && !r.done && (m = i["return"])) m.call(i); } finally { if (e) throw e.error; } } return ar; } /** @deprecated */ function __spread() { for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i])); return ar; } /** @deprecated */ function __spreadArrays() { for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j]; return r; } function __spreadArray(to, from, pack) { if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { if (ar || !(i in from)) { if (!ar) ar = Array.prototype.slice.call(from, 0, i); ar[i] = from[i]; } } return to.concat(ar || Array.prototype.slice.call(from)); } function __await(v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } function __asyncGenerator(thisArg, _arguments, generator) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var g = generator.apply(thisArg, _arguments || []), i, q = []; return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } function fulfill(value) { resume("next", value); } function reject(value) { resume("throw", value); } function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } } function __asyncDelegator(o) { var i, p; return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i; function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: false } : f ? f(v) : v; } : f; } } function __asyncValues(o) { if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); var m = o[Symbol.asyncIterator], i; return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } } function __makeTemplateObject(cooked, raw) { if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; } return cooked; }; var __setModuleDefault = Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }; function __importStar(mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; } function __importDefault(mod) { return (mod && mod.__esModule) ? mod : { default: mod }; } function __classPrivateFieldGet(receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); } function __classPrivateFieldSet(receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; } function __classPrivateFieldIn(state, receiver) { if (receiver === null || (typeof receiver !== "object" && typeof receiver !== "function")) throw new TypeError("Cannot use 'in' operator on non-object"); return typeof state === "function" ? receiver === state : state.has(receiver); } function __addDisposableResource(env, value, async) { if (value !== null && value !== void 0) { if (typeof value !== "object" && typeof value !== "function") throw new TypeError("Object expected."); var dispose; if (async) { if (!Symbol.asyncDispose) throw new TypeError("Symbol.asyncDispose is not defined."); dispose = value[Symbol.asyncDispose]; } if (dispose === void 0) { if (!Symbol.dispose) throw new TypeError("Symbol.dispose is not defined."); dispose = value[Symbol.dispose]; } if (typeof dispose !== "function") throw new TypeError("Object not disposable."); env.stack.push({ value: value, dispose: dispose, async: async }); } else if (async) { env.stack.push({ async: true }); } return value; } var _SuppressedError = typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; function __disposeResources(env) { function fail(e) { env.error = env.hasError ? new _SuppressedError(e, env.error, "An error was suppressed during disposal.") : e; env.hasError = true; } function next() { while (env.stack.length) { var rec = env.stack.pop(); try { var result = rec.dispose && rec.dispose.call(rec.value); if (rec.async) return Promise.resolve(result).then(next, function(e) { fail(e); return next(); }); } catch (e) { fail(e); } } if (env.hasError) throw env.error; } return next(); } /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = ({ __extends, __assign, __rest, __decorate, __param, __metadata, __awaiter, __generator, __createBinding, __exportStar, __values, __read, __spread, __spreadArrays, __spreadArray, __await, __asyncGenerator, __asyncDelegator, __asyncValues, __makeTemplateObject, __importStar, __importDefault, __classPrivateFieldGet, __classPrivateFieldSet, __classPrivateFieldIn, __addDisposableResource, __disposeResources, }); /***/ }) /******/ }); /************************************************************************/ /******/ // The module cache /******/ var __webpack_module_cache__ = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ // Check if module is in cache /******/ var cachedModule = __webpack_module_cache__[moduleId]; /******/ if (cachedModule !== undefined) { /******/ return cachedModule.exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = __webpack_module_cache__[moduleId] = { /******/ // no module.id needed /******/ // no module.loaded needed /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__); /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /************************************************************************/ /******/ /* webpack/runtime/compat get default export */ /******/ (() => { /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = (module) => { /******/ var getter = module && module.__esModule ? /******/ () => (module['default']) : /******/ () => (module); /******/ __webpack_require__.d(getter, { a: getter }); /******/ return getter; /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/define property getters */ /******/ (() => { /******/ // define getter functions for harmony exports /******/ __webpack_require__.d = (exports, definition) => { /******/ for(var key in definition) { /******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) { /******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] }); /******/ } /******/ } /******/ }; /******/ })(); /******/ /******/ /* webpack/runtime/global */ /******/ (() => { /******/ __webpack_require__.g = (function() { /******/ if (typeof globalThis === 'object') return globalThis; /******/ try { /******/ return this || new Function('return this')(); /******/ } catch (e) { /******/ if (typeof window === 'object') return window; /******/ } /******/ })(); /******/ })(); /******/ /******/ /* webpack/runtime/hasOwnProperty shorthand */ /******/ (() => { /******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop)) /******/ })(); /******/ /******/ /* webpack/runtime/make namespace object */ /******/ (() => { /******/ // define __esModule on exports /******/ __webpack_require__.r = (exports) => { /******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) { /******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); /******/ } /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ })(); /******/ /************************************************************************/ var __webpack_exports__ = {}; // This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk. (() => { /*!**********************!*\ !*** ./src/index.ts ***! \**********************/ __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__), /* harmony export */ loaders: () => (/* reexport module object */ _lts_loaders_legacy_legacy__WEBPACK_IMPORTED_MODULE_0__) /* harmony export */ }); /* harmony import */ var _lts_loaders_legacy_legacy__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @lts/loaders/legacy/legacy */ "../../../lts/loaders/src/legacy/legacy.ts"); /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (_lts_loaders_legacy_legacy__WEBPACK_IMPORTED_MODULE_0__); })(); __webpack_exports__ = __webpack_exports__["default"]; /******/ return __webpack_exports__; /******/ })() ; }); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYmFieWxvbmpzLmxvYWRlcnMuanMiLCJtYXBwaW5ncyI6IkFBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNWQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNGQTtBQUNBO0FBQ0E7QUFJQTs7QUFFQTtBQUNBO0FBQUE7QUFNQTs7QUFFQTtBQUNBO0FBK01BO0FBN01BOzs7Ozs7Ozs7O0FBVUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOzs7Ozs7Ozs7O0FBVUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUF0TkE7O0FBRUE7QUFDQTtBQW9OQTtBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDak9BO0FBQ0E7QUFHQTtBQUNBO0FBR0E7QUFFQTtBQUdBOzs7QUFHQTtBQUNBO0FBNkRBOzs7O0FBSUE7QUFDQTtBQWxCQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUVBO0FBVUE7QUFDQTtBQXhEQTtBQUhBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBOzs7QUFKQTtBQXdEQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUFBO0FBRUE7Ozs7Ozs7Ozs7QUFVQTtBQUNBO0FBTUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOzs7Ozs7QUFNQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7Ozs7OztBQVNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUExU0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFZQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFFQTs7OztBQUlBO0FBQ0E7QUE2UEE7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBRWxVQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQWdCQTs7QUFFQTtBQUNBO0FBaUVBOzs7OztBQUtBO0FBQ0E7QUFqQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVdBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7Ozs7Ozs7Ozs7QUFhQTtBQUNBO0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7Ozs7Ozs7OztBQVlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUlBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFJQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBR0E7QUFFQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBT0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7Ozs7QUFPQTtBQUNBOztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFHQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFHQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFHQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFHQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFHQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBbDBCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQWl5QkE7QUFBQTs7Ozs7Ozs7Ozs7Ozs7OztBQ2gyQkE7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDRUE7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUdBOzs7QUFHQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUVBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUE2T0E7QUFwT0E7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQTFPQTs7OztBQUlBO0FBQ0E7QUFzT0E7QUFBQTtBQUVBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUN2UkE7QUFDQTtBQUlBO0FBSUE7QUFhQTs7O0FBR0E7QUFDQTtBQUFBO0FBR0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQzVEQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBRUE7QUFDQTtBQUdBOzs7QUFHQTtBQUNBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBVUE7QUFSQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFBQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7Ozs7OztBQU1BO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7Ozs7OztBQVNBO0FBQ0E7QUFTQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7Ozs7Ozs7QUFPQTtBQUNBO0FBT0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBckNBOztBQUVBO0FBQ0E7QUFBQTtBQW1DQTtBQUNBO0FBRUE7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7Ozs7QUFRQTtBQUNBO0FBUUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU1BO0FBQ0E7QUFFQTs7O0FBR0E7QUFDQTtBQUFBO0FBd2FBO0FBdmFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQU9BO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBOztBQUVBOzs7O0FBSUE7QUFDQTtBQUFBO0FBeVRBO0FBdFRBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQVVBO0FBRUE7QUFLQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFFQTs7Ozs7Ozs7O0FBU0E7QUFDQTtBQUFBO0FBUUE7QUFDQTtBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUFBO0FBUUE7QUFFQTtBQUtBO0FBQ0E7QUFHQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBR0E7QUFFQTs7Ozs7OztBQU9BO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFLQTtBQUNBO0FBR0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFJQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXZUQTtBQXdUQTtBQUFBO0FBRUE7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUNBOzs7QUFBQTtBQUVBOzs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7Ozs7O0FBUUE7QUFDQTtBQU9BO0FBQ0E7QUFFQTs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBT0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBT0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBRUE7QUFNQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFFQTtBQU9BO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUN0dkVBOzs7QUFHQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNwR0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7Ozs7QUFJQTtBQUNBO0FBQUE7QUE2UEE7QUE1UEE7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQU9BO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUM5UUE7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUF3REE7OztBQUdBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQUE7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ2xOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNIQTtBQUNBO0FBQ0E7QUFFQTtBQUtBO0FBRUE7QUFXQTs7QUFFQTtBQUNBO0FBQ0E7QUFjQTs7QUFFQTtBQUNBO0FBaEJBOztBQUVBO0FBQ0E7QUFjQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUdBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUdBOztBQVpBO0FBQUE7QUFhQTs7O0FBaEJBO0FBQUE7QUFpQkE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDaEtBO0FBSUE7QUFNQTtBQUVBO0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQWFBOztBQUVBO0FBQ0E7QUFmQTs7QUFFQTtBQUNBO0FBYUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQzlHQTtBQUdBO0FBRUE7QUFNQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFhQTs7QUFFQTtBQUNBO0FBZkE7O0FBRUE7QUFDQTtBQWFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7OztBQ2pFQTtBQU1BO0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBU0E7O0FBRUE7QUFDQTtBQVhBO0FBQ0E7QUFXQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBS0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUFBOztBQUVBOzs7Ozs7Ozs7Ozs7Ozs7O0FDakRBO0FBR0E7QUFNQTs7QUFFQTtBQUNBO0FBcUJBOztBQUVBO0FBQ0E7QUF2QkE7O0FBRUE7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFnQkE7QUFDQTtBQWJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNsRkE7O0FBRUE7QUFHQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUFBO0FBQUE7O0FBS0E7QUFKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFFQTtBQUFBO0FBQUE7O0FBT0E7QUFOQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBRUE7QUFBQTtBQUFBOztBQVdBO0FBVkE7QUFDQTtBQU9BO0FBQ0E7QUFDQTtBQUFBO0FBRUE7QUFDQTtBQUlBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ3ZNQTtBQVFBO0FBQ0E7QUFFQTtBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFRQTs7QUFFQTtBQUNBO0FBVkE7O0FBRUE7QUFDQTtBQVFBO0FBQ0E7QUFLQTtBQUhBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFBQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7Ozs7O0FBUUE7QUFDQTs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBOzs7Ozs7Ozs7Ozs7Ozs7O0FBZ0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ3RKQTtBQUVBO0FBUUE7QUFFQTtBQU1BOztBQUVBO0FBQ0E7QUFDQTtBQXVCQTs7QUFFQTtBQUNBO0FBekJBOztBQUVBO0FBQ0E7QUFZQTs7QUFFQTtBQUNBO0FBUUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBOztBQUVBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUM1SEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBT0E7QUFFQTtBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQWVBOztBQUVBO0FBQ0E7QUFqQkE7O0FBRUE7QUFDQTtBQWVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDdkhBO0FBS0E7QUFHQTtBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQWtCQTs7QUFFQTtBQUNBO0FBcEJBOztBQUVBO0FBQ0E7QUFPQTs7QUFFQTtBQUNBO0FBUUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQUE7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ2xGQTtBQUtBO0FBR0E7QUFFQTs7O0FBR0E7QUFDQTtBQUNBO0FBa0JBOztBQUVBO0FBQ0E7QUFwQkE7O0FBRUE7QUFDQTtBQU9BOztBQUVBO0FBQ0E7QUFRQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ3hIQTtBQUtBO0FBR0E7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFrQkE7O0FBRUE7QUFDQTtBQXBCQTs7QUFFQTtBQUNBO0FBT0E7O0FBRUE7QUFDQTtBQVFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ25FQTtBQUtBO0FBR0E7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUF1QkE7O0FBRUE7QUFDQTtBQXBCQTs7QUFFQTtBQUNBO0FBT0E7O0FBRUE7QUFDQTtBQVFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUEzREE7O0FBRUE7QUFDQTtBQXlEQTtBQUFBO0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQzdFQTtBQUtBO0FBR0E7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFrQkE7O0FBRUE7QUFDQTtBQXBCQTs7QUFFQTtBQUNBO0FBT0E7O0FBRUE7QUFDQTtBQVFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDN0ZBO0FBQ0E7QUFLQTtBQUdBO0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBa0JBOztBQUVBO0FBQ0E7QUFwQkE7O0FBRUE7QUFDQTtBQU9BOztBQUVBO0FBQ0E7QUFRQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDeEdBO0FBS0E7QUFDQTtBQUdBO0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQWtCQTs7QUFFQTtBQUNBO0FBcEJBOztBQUVBO0FBQ0E7QUFPQTs7QUFFQTtBQUNBO0FBUUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQzNHQTtBQUtBO0FBQ0E7QUFHQTtBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQWtCQTs7QUFFQTtBQUNBO0FBcEJBOztBQUVBO0FBQ0E7QUFPQTs7QUFFQTtBQUNBO0FBUUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQUE7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ2pHQTtBQUtBO0FBR0E7QUFFQTs7O0FBR0E7QUFDQTtBQUNBO0FBa0JBOztBQUVBO0FBQ0E7QUFwQkE7O0FBRUE7QUFDQTtBQU9BOztBQUVBO0FBQ0E7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNuR0E7QUFLQTtBQUtBO0FBRUE7QUFDQTtBQUNBO0FBZ0RBOztBQUVBO0FBQ0E7QUFpQ0E7Ozs7QUFJQTtBQUNBO0FBQUE7QUFoQkE7QUFDQTtBQUNBO0FBQ0E7QUFjQTtBQUlBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQXBEQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBMENBOzs7QUFHQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFLQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7QUFJQTtBQUNBOztBQUNBO0FBQ0E7QUFFQTs7O0FBR0E7QUFDQTtBQUFBOztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUVBO0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBa0JBOztBQUVBO0FBQ0E7QUFwQkE7O0FBRUE7QUFDQTtBQU9BOztBQUVBO0FBQ0E7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBOztBQUVBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUMxWkE7QUFDQTtBQUtBO0FBRUE7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFrQkE7O0FBRUE7QUFDQTtBQXBCQTs7QUFFQTtBQUNBO0FBT0E7O0FBRUE7QUFDQTtBQVFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDM0ZBO0FBR0E7QUFNQTtBQVlBOztBQUVBO0FBQ0E7QUFDQTtBQWVBOztBQUVBO0FBQ0E7QUFqQkE7O0FBRUE7QUFDQTtBQWVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUFBO0FBUUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUF4RUE7QUFBQTtBQXlFQTtBQUNBOztBQWhGQTtBQUNBO0FBQUE7QUFpRkE7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDMVNBO0FBS0E7QUFHQTtBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFrQkE7O0FBRUE7QUFDQTtBQXBCQTs7QUFFQTtBQUNBO0FBT0E7O0FBRUE7QUFDQTtBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7OztBQ3JHQTtBQUVBO0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBV0E7O0FBRUE7QUFDQTtBQWJBOztBQUVBO0FBQ0E7QUFXQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7QUM5QkE7QUFNQTtBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQVNBOztBQUVBO0FBQ0E7QUFYQTtBQUNBO0FBV0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDdERBO0FBSUE7QUFHQTtBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQWFBOztBQUVBO0FBQ0E7QUFmQTs7QUFFQTtBQUNBO0FBYUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7OztBQzlFQTtBQUdBO0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQWtCQTs7QUFFQTtBQUNBO0FBcEJBOztBQUVBO0FBQ0E7QUFPQTs7QUFFQTtBQUNBO0FBUUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBOztBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDN0RBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFJQTtBQUlBO0FBeUJBOzs7QUFHQTtBQUNBO0FBQ0E7QUFlQTs7QUFFQTtBQUNBO0FBakJBOztBQUVBO0FBQ0E7QUFlQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTs7QUFmQTtBQUFBO0FBQUE7QUFpQkE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBVkE7QUFBQTtBQVlBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ2pUQTtBQUNBO0FBT0E7QUFHQTtBQVFBOztBQUVBO0FBQ0E7QUFDQTtBQWlEQTs7QUFFQTtBQUNBO0FBbkRBOztBQUVBO0FBQ0E7QUFPQTs7QUFFQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUVBOzs7O0FBSUE7QUFDQTtBQUVBOzs7O0FBSUE7QUFDQTtBQUlBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQU1BO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7O0FBbEJBO0FBQUE7QUFtQkE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7O0FBbEJBO0FBQUE7QUFtQkE7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOztBQWxDQTtBQUFBO0FBbUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7O0FBbkNBO0FBQUE7QUFvQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDOVpBO0FBSUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQVNBO0FBQ0E7QUFUQTtBQUNBO0FBU0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTs7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDeERBO0FBSUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQVNBO0FBQ0E7QUFUQTtBQUNBO0FBU0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBOztBQUVBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUMzREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUMzQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUEwQ0E7QUFFQTtBQUNBO0FBRUE7QUFHQTtBQTJCQTtBQUNBO0FBQUE7QUFBQTtBQUFBOztBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQXlDQTtBQXhDQTs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTs7QUFXQTs7QUFFQTtBQUNBO0FBNEdBOztBQUVBO0FBQ0E7QUE5R0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFxRkE7QUFDQTtBQTdFQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUtBO0FBSEE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7OztBQUFBO0FBS0E7QUFIQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQUE7QUFLQTtBQUhBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFBQTtBQUtBO0FBSEE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7OztBQUFBO0FBS0E7QUFIQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQUE7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUFBO0FBT0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBSkE7QUFBQTtBQUFBO0FBS0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7Ozs7O0FBS0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7O0FBTUE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOzs7Ozs7Ozs7QUFTQTtBQUNBO0FBQUE7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFLQTtBQUVBOzs7Ozs7QUFNQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFFQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7Ozs7O0FBU0E7QUFDQTtBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTs7Ozs7Ozs7OztBQVVBO0FBQ0E7QUFRQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFTQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFRQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTs7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBZ0JBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBS0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7OztBQU1BO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUFBO0FBSUE7QUFJQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBOzs7Ozs7QUFNQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQU9BO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQVFBO0FBS0E7QUFFQTtBQU9BO0FBS0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBS0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQU9BO0FBS0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7OztBQU9BO0FBQ0E7QUFNQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBOzs7Ozs7O0FBT0E7QUFDQTtBQU1BO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBNXFGQTtBQUVBOztBQUVBO0FBQ0E7QUF3cUZBO0FBQUE7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ240RkE7QUFDQTtBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQUE7O0FBRUE7QUFDQTtBQUFBO0FBQUE7O0FBS0E7QUFKQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7O0FBRUE7QUFDQTtBQUFBO0FBQUE7O0FBNEJBO0FBM0JBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFyQkE7QUFBQTtBQXNCQTtBQUNBO0FBQ0E7QUFDQTtBQUFBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FHN0ZBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ0NBO0FBQ0E7QUFhQTtBQUNBO0FBSUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQVVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUFBO0FBQ0E7O0FBRUE7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQUNBOztBQUVBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBc0NBOztBQUVBO0FBQ0E7QUFBQTtBQUNBOztBQUVBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBZ0JBOztBQUVBO0FBQ0E7QUFBQTtBQU9BO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFpQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFFQTs7OztBQUlBO0FBQ0E7QUFFQTs7OztBQUlBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBRUE7OztBQUdBO0FBQ0E7QUFFQTs7O0FBR0E7QUFDQTtBQUVBOzs7QUFHQTtBQUNBO0FBZUE7Ozs7O0FBS0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFjQTs7QUFFQTtBQUNBO0FBY0E7O0FBRUE7QUFDQTtBQWNBOzs7O0FBSUE7QUFDQTtBQWdCQTs7QUFFQTtBQUNBO0FBY0E7O0FBRUE7QUFDQTtBQWNBOzs7QUFHQTtBQUNBO0FBMERBOztBQUVBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBY0E7QUFDQTtBQUVBO0FBSUE7O0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUErU0E7O0FBRUE7QUFDQTtBQWlVQTtBQUNBO0FBRUE7QUFDQTtBQXNCQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBYUE7QUE3L0JBO0FBSEE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUFBO0FBMkhBO0FBSkE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFBQTtBQW9CQTtBQUhBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFBQTtBQVlBO0FBSEE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUFBO0FBWUE7QUFIQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQUE7QUFnQkE7QUFMQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFBQTtBQVlBO0FBSEE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUFBO0FBWUE7QUFIQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQUE7QUFhQTtBQUhBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFBQTtBQUtBO0FBSEE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7OztBQWRBO0FBbUJBO0FBSEE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFoQkE7QUFpQ0E7QUFIQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBQUE7QUFvQkE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQVVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUdBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFFQTtBQUlBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBR0E7QUFJQTtBQUVBO0FBSUE7QUFDQTtBQUNBO0FBSUE7QUFFQTs7QUFFQTtBQUNBO0FBUUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFHQTtBQUVBOztBQUVBO0FBQ0E7QUFBQTtBQVFBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7O0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBVUE7QUFDQTtBQUNBO0FBQ0E7QUFLQTtBQUhBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOzs7QUFBQTtBQU9BOzs7QUFHQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQUE7QUFRQTtBQUlBO0FBQ0E7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFVQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBci9CQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7QUFLQTtBQUNBO0FBRUE7Ozs7QUFJQTtBQUNBO0FBMFRBO0FBNm5CQTtBQThDQTtBQUFBO0FBRUE7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7OztBQzdyQ0E7QUFTQTtBQU1BO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkE7QUFPQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBWUE7O0FBRUE7QUFDQTtBQUFBO0FBb0ZBO0FBMUVBOzs7Ozs7O0FBT0E7QUFDQTtBQUFBO0FBTUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFsRkE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUE4RUE7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQzFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNMQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDSEE7QUFDQTtBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTs7Ozs7Ozs7Ozs7Ozs7OztBQ25CQTtBQUNBO0FBRUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNoQkE7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FDckNBO0FBQ0E7QUFFQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7QUNoQkE7QUFDQTtBQUVBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQ2hCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQ1BBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUNBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7OztBQ2pYQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUN2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUNQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQ1BBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FDUEE7Ozs7O0FDQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7QUNOQTtBQUNBO0FBQ0EiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9MT0FERVJTL3dlYnBhY2svdW5pdmVyc2FsTW9kdWxlRGVmaW5pdGlvbiIsIndlYnBhY2s6Ly9MT0FERVJTLy4uLy4uLy4uL2Rldi9sb2FkZXJzL3NyYy9PQkovaW5kZXgudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvT0JKL210bEZpbGVMb2FkZXIudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvT0JKL29iakZpbGVMb2FkZXIudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvT0JKL29iakxvYWRpbmdPcHRpb25zLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL09CSi9zb2xpZFBhcnNlci50cyIsIndlYnBhY2s6Ly9MT0FERVJTLy4uLy4uLy4uL2Rldi9sb2FkZXJzL3NyYy9TVEwvaW5kZXgudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvU1RML3N0bEZpbGVMb2FkZXIudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvZ2xURi8xLjAvZ2xURkJpbmFyeUV4dGVuc2lvbi50cyIsIndlYnBhY2s6Ly9MT0FERVJTLy4uLy4uLy4uL2Rldi9sb2FkZXJzL3NyYy9nbFRGLzEuMC9nbFRGTG9hZGVyLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMS4wL2dsVEZMb2FkZXJJbnRlcmZhY2VzLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMS4wL2dsVEZMb2FkZXJVdGlscy50cyIsIndlYnBhY2s6Ly9MT0FERVJTLy4uLy4uLy4uL2Rldi9sb2FkZXJzL3NyYy9nbFRGLzEuMC9nbFRGTWF0ZXJpYWxzQ29tbW9uRXh0ZW5zaW9uLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMS4wL2luZGV4LnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvRVhUX2xpZ2h0c19pbWFnZV9iYXNlZC50cyIsIndlYnBhY2s6Ly9MT0FERVJTLy4uLy4uLy4uL2Rldi9sb2FkZXJzL3NyYy9nbFRGLzIuMC9FeHRlbnNpb25zL0VYVF9tZXNoX2dwdV9pbnN0YW5jaW5nLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvRVhUX21lc2hvcHRfY29tcHJlc3Npb24udHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvZ2xURi8yLjAvRXh0ZW5zaW9ucy9FWFRfdGV4dHVyZV93ZWJwLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvRXh0cmFzQXNNZXRhZGF0YS50cyIsIndlYnBhY2s6Ly9MT0FERVJTLy4uLy4uLy4uL2Rldi9sb2FkZXJzL3NyYy9nbFRGLzIuMC9FeHRlbnNpb25zL0tIUl9hbmltYXRpb25fcG9pbnRlci5kYXRhLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvS0hSX2FuaW1hdGlvbl9wb2ludGVyLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvS0hSX2RyYWNvX21lc2hfY29tcHJlc3Npb24udHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvZ2xURi8yLjAvRXh0ZW5zaW9ucy9LSFJfbGlnaHRzX3B1bmN0dWFsLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvS0hSX21hdGVyaWFsc19hbmlzb3Ryb3B5LnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvS0hSX21hdGVyaWFsc19jbGVhcmNvYXQudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvZ2xURi8yLjAvRXh0ZW5zaW9ucy9LSFJfbWF0ZXJpYWxzX2VtaXNzaXZlX3N0cmVuZ3RoLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvS0hSX21hdGVyaWFsc19pb3IudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvZ2xURi8yLjAvRXh0ZW5zaW9ucy9LSFJfbWF0ZXJpYWxzX2lyaWRlc2NlbmNlLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvS0hSX21hdGVyaWFsc19wYnJTcGVjdWxhckdsb3NzaW5lc3MudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvZ2xURi8yLjAvRXh0ZW5zaW9ucy9LSFJfbWF0ZXJpYWxzX3NoZWVuLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvS0hSX21hdGVyaWFsc19zcGVjdWxhci50cyIsIndlYnBhY2s6Ly9MT0FERVJTLy4uLy4uLy4uL2Rldi9sb2FkZXJzL3NyYy9nbFRGLzIuMC9FeHRlbnNpb25zL0tIUl9tYXRlcmlhbHNfdHJhbnNsdWNlbmN5LnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvS0hSX21hdGVyaWFsc190cmFuc21pc3Npb24udHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvZ2xURi8yLjAvRXh0ZW5zaW9ucy9LSFJfbWF0ZXJpYWxzX3VubGl0LnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvS0hSX21hdGVyaWFsc192YXJpYW50cy50cyIsIndlYnBhY2s6Ly9MT0FERVJTLy4uLy4uLy4uL2Rldi9sb2FkZXJzL3NyYy9nbFRGLzIuMC9FeHRlbnNpb25zL0tIUl9tYXRlcmlhbHNfdm9sdW1lLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvS0hSX21lc2hfcXVhbnRpemF0aW9uLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvS0hSX3RleHR1cmVfYmFzaXN1LnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvS0hSX3RleHR1cmVfdHJhbnNmb3JtLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvS0hSX3htcF9qc29uX2xkLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvTVNGVF9hdWRpb19lbWl0dGVyLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvTVNGVF9sb2QudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvZ2xURi8yLjAvRXh0ZW5zaW9ucy9NU0ZUX21pbmVjcmFmdE1lc2gudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvZ2xURi8yLjAvRXh0ZW5zaW9ucy9NU0ZUX3NSR0JGYWN0b3JzLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL0V4dGVuc2lvbnMvaW5kZXgudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvZ2xURi8yLjAvZ2xURkxvYWRlci50cyIsIndlYnBhY2s6Ly9MT0FERVJTLy4uLy4uLy4uL2Rldi9sb2FkZXJzL3NyYy9nbFRGLzIuMC9nbFRGTG9hZGVyQW5pbWF0aW9uLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvMi4wL2dsVEZMb2FkZXJFeHRlbnNpb24udHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvZ2xURi8yLjAvZ2xURkxvYWRlckludGVyZmFjZXMudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvZ2xURi8yLjAvaW5kZXgudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvZ2xURi9nbFRGRmlsZUxvYWRlci50cyIsIndlYnBhY2s6Ly9MT0FERVJTLy4uLy4uLy4uL2Rldi9sb2FkZXJzL3NyYy9nbFRGL2dsVEZWYWxpZGF0aW9uLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vZGV2L2xvYWRlcnMvc3JjL2dsVEYvaW5kZXgudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9kZXYvbG9hZGVycy9zcmMvaW5kZXgudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9sdHMvbG9hZGVycy9zcmMvbGVnYWN5L2xlZ2FjeS1nbFRGLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vbHRzL2xvYWRlcnMvc3JjL2xlZ2FjeS9sZWdhY3ktZ2xURjEudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9sdHMvbG9hZGVycy9zcmMvbGVnYWN5L2xlZ2FjeS1nbFRGMi50cyIsIndlYnBhY2s6Ly9MT0FERVJTLy4uLy4uLy4uL2x0cy9sb2FkZXJzL3NyYy9sZWdhY3kvbGVnYWN5LW9iakZpbGVMb2FkZXIudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy8uLi8uLi8uLi9sdHMvbG9hZGVycy9zcmMvbGVnYWN5L2xlZ2FjeS1zdGxGaWxlTG9hZGVyLnRzIiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vbHRzL2xvYWRlcnMvc3JjL2xlZ2FjeS9sZWdhY3kudHMiLCJ3ZWJwYWNrOi8vTE9BREVSUy9leHRlcm5hbCB1bWQge1wicm9vdFwiOlwiQkFCWUxPTlwiLFwiY29tbW9uanNcIjpcImJhYnlsb25qc1wiLFwiY29tbW9uanMyXCI6XCJiYWJ5bG9uanNcIixcImFtZFwiOlwiYmFieWxvbmpzXCJ9Iiwid2VicGFjazovL0xPQURFUlMvLi4vLi4vLi4vLi4vbm9kZV9tb2R1bGVzL3RzbGliL3RzbGliLmVzNi5tanMiLCJ3ZWJwYWNrOi8vTE9BREVSUy93ZWJwYWNrL2Jvb3RzdHJhcCIsIndlYnBhY2s6Ly9MT0FERVJTL3dlYnBhY2svcnVudGltZS9jb21wYXQgZ2V0IGRlZmF1bHQgZXhwb3J0Iiwid2VicGFjazovL0xPQURFUlMvd2VicGFjay9ydW50aW1lL2RlZmluZSBwcm9wZXJ0eSBnZXR0ZXJzIiwid2VicGFjazovL0xPQURFUlMvd2VicGFjay9ydW50aW1lL2dsb2JhbCIsIndlYnBhY2s6Ly9MT0FERVJTL3dlYnBhY2svcnVudGltZS9oYXNPd25Qcm9wZXJ0eSBzaG9ydGhhbmQiLCJ3ZWJwYWNrOi8vTE9BREVSUy93ZWJwYWNrL3J1bnRpbWUvbWFrZSBuYW1lc3BhY2Ugb2JqZWN0Iiwid2VicGFjazovL0xPQURFUlMvLi9zcmMvaW5kZXgudHMiXSwic291cmNlc0NvbnRlbnQiOlsiKGZ1bmN0aW9uIHdlYnBhY2tVbml2ZXJzYWxNb2R1bGVEZWZpbml0aW9uKHJvb3QsIGZhY3RvcnkpIHtcblx0aWYodHlwZW9mIGV4cG9ydHMgPT09ICdvYmplY3QnICYmIHR5cGVvZiBtb2R1bGUgPT09ICdvYmplY3QnKVxuXHRcdG1vZHVsZS5leHBvcnRzID0gZmFjdG9yeShyZXF1aXJlKFwiYmFieWxvbmpzXCIpKTtcblx0ZWxzZSBpZih0eXBlb2YgZGVmaW5lID09PSAnZnVuY3Rpb24nICYmIGRlZmluZS5hbWQpXG5cdFx0ZGVmaW5lKFwiYmFieWxvbmpzLWxvYWRlcnNcIiwgW1wiYmFieWxvbmpzXCJdLCBmYWN0b3J5KTtcblx0ZWxzZSBpZih0eXBlb2YgZXhwb3J0cyA9PT0gJ29iamVjdCcpXG5cdFx0ZXhwb3J0c1tcImJhYnlsb25qcy1sb2FkZXJzXCJdID0gZmFjdG9yeShyZXF1aXJlKFwiYmFieWxvbmpzXCIpKTtcblx0ZWxzZVxuXHRcdHJvb3RbXCJMT0FERVJTXCJdID0gZmFjdG9yeShyb290W1wiQkFCWUxPTlwiXSk7XG59KSgodHlwZW9mIHNlbGYgIT09IFwidW5kZWZpbmVkXCIgPyBzZWxmIDogdHlwZW9mIGdsb2JhbCAhPT0gXCJ1bmRlZmluZWRcIiA/IGdsb2JhbCA6IHRoaXMpLCAoX19XRUJQQUNLX0VYVEVSTkFMX01PRFVMRV9iYWJ5bG9uanNfTWlzY19vYnNlcnZhYmxlX18pID0+IHtcbnJldHVybiAiLCJleHBvcnQgKiBmcm9tIFwiLi9tdGxGaWxlTG9hZGVyXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL29iakxvYWRpbmdPcHRpb25zXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL3NvbGlkUGFyc2VyXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL29iakZpbGVMb2FkZXJcIjtcclxuIiwiaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB7IENvbG9yMyB9IGZyb20gXCJjb3JlL01hdGhzL21hdGguY29sb3JcIjtcclxuaW1wb3J0IHsgVGV4dHVyZSB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9UZXh0dXJlcy90ZXh0dXJlXCI7XHJcbmltcG9ydCB7IFN0YW5kYXJkTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvc3RhbmRhcmRNYXRlcmlhbFwiO1xyXG5cclxuaW1wb3J0IHR5cGUgeyBTY2VuZSB9IGZyb20gXCJjb3JlL3NjZW5lXCI7XHJcbmltcG9ydCB0eXBlIHsgQXNzZXRDb250YWluZXIgfSBmcm9tIFwiY29yZS9hc3NldENvbnRhaW5lclwiO1xyXG4vKipcclxuICogQ2xhc3MgcmVhZGluZyBhbmQgcGFyc2luZyB0aGUgTVRMIGZpbGUgYnVuZGxlZCB3aXRoIHRoZSBvYmogZmlsZS5cclxuICovXHJcbmV4cG9ydCBjbGFzcyBNVExGaWxlTG9hZGVyIHtcclxuICAgIC8qKlxyXG4gICAgICogSW52ZXJ0IFktQXhpcyBvZiByZWZlcmVuY2VkIHRleHR1cmVzIG9uIGxvYWRcclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBJTlZFUlRfVEVYVFVSRV9ZID0gdHJ1ZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEFsbCBtYXRlcmlhbCBsb2FkZWQgZnJvbSB0aGUgbXRsIHdpbGwgYmUgc2V0IGhlcmVcclxuICAgICAqL1xyXG4gICAgcHVibGljIG1hdGVyaWFsczogU3RhbmRhcmRNYXRlcmlhbFtdID0gW107XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIHdpbGwgcmVhZCB0aGUgbXRsIGZpbGUgYW5kIGNyZWF0ZSBlYWNoIG1hdGVyaWFsIGRlc2NyaWJlZCBpbnNpZGVcclxuICAgICAqIFRoaXMgZnVuY3Rpb24gY291bGQgYmUgaW1wcm92ZSBieSBhZGRpbmcgOlxyXG4gICAgICogLXNvbWUgY29tcG9uZW50IG1pc3NpbmcgKE5pLCBUZi4uLilcclxuICAgICAqIC1pbmNsdWRpbmcgdGhlIHNwZWNpZmljIG9wdGlvbnMgYXZhaWxhYmxlXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIHNjZW5lIGRlZmluZXMgdGhlIHNjZW5lIHRoZSBtYXRlcmlhbCB3aWxsIGJlIGNyZWF0ZWQgaW5cclxuICAgICAqIEBwYXJhbSBkYXRhIGRlZmluZXMgdGhlIG10bCBkYXRhIHRvIHBhcnNlXHJcbiAgICAgKiBAcGFyYW0gcm9vdFVybCBkZWZpbmVzIHRoZSByb290dXJsIHRvIHVzZSBpbiBvcmRlciB0byBsb2FkIHJlbGF0aXZlIGRlcGVuZGVuY2llc1xyXG4gICAgICogQHBhcmFtIGFzc2V0Q29udGFpbmVyIGRlZmluZXMgdGhlIGFzc2V0IGNvbnRhaW5lciB0byBzdG9yZSB0aGUgbWF0ZXJpYWwgaW4gKGNhbiBiZSBudWxsKVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcGFyc2VNVEwoc2NlbmU6IFNjZW5lLCBkYXRhOiBzdHJpbmcgfCBBcnJheUJ1ZmZlciwgcm9vdFVybDogc3RyaW5nLCBhc3NldENvbnRhaW5lcjogTnVsbGFibGU8QXNzZXRDb250YWluZXI+KTogdm9pZCB7XHJcbiAgICAgICAgaWYgKGRhdGEgaW5zdGFuY2VvZiBBcnJheUJ1ZmZlcikge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvL1NwbGl0IHRoZSBsaW5lcyBmcm9tIHRoZSBmaWxlXHJcbiAgICAgICAgY29uc3QgbGluZXMgPSBkYXRhLnNwbGl0KFwiXFxuXCIpO1xyXG4gICAgICAgIC8vIHdoaXRlc3BhY2UgY2hhciBpZTogWyBcXHRcXHJcXG5cXGZdXHJcbiAgICAgICAgY29uc3QgZGVsaW1pdGVyX3BhdHRlcm4gPSAvXFxzKy87XHJcbiAgICAgICAgLy9BcnJheSB3aXRoIFJHQiBjb2xvcnNcclxuICAgICAgICBsZXQgY29sb3I6IG51bWJlcltdO1xyXG4gICAgICAgIC8vTmV3IG1hdGVyaWFsXHJcbiAgICAgICAgbGV0IG1hdGVyaWFsOiBOdWxsYWJsZTxTdGFuZGFyZE1hdGVyaWFsPiA9IG51bGw7XHJcblxyXG4gICAgICAgIC8vTG9vayBhdCBlYWNoIGxpbmVcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGxpbmUgPSBsaW5lc1tpXS50cmltKCk7XHJcblxyXG4gICAgICAgICAgICAvLyBCbGFuayBsaW5lIG9yIGNvbW1lbnRcclxuICAgICAgICAgICAgaWYgKGxpbmUubGVuZ3RoID09PSAwIHx8IGxpbmUuY2hhckF0KDApID09PSBcIiNcIikge1xyXG4gICAgICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vR2V0IHRoZSBmaXJzdCBwYXJhbWV0ZXIgKGtleXdvcmQpXHJcbiAgICAgICAgICAgIGNvbnN0IHBvcyA9IGxpbmUuaW5kZXhPZihcIiBcIik7XHJcbiAgICAgICAgICAgIGxldCBrZXkgPSBwb3MgPj0gMCA/IGxpbmUuc3Vic3RyaW5nKDAsIHBvcykgOiBsaW5lO1xyXG4gICAgICAgICAgICBrZXkgPSBrZXkudG9Mb3dlckNhc2UoKTtcclxuXHJcbiAgICAgICAgICAgIC8vR2V0IHRoZSBkYXRhIGZvbGxvd2luZyB0aGUga2V5XHJcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlOiBzdHJpbmcgPSBwb3MgPj0gMCA/IGxpbmUuc3Vic3RyaW5nKHBvcyArIDEpLnRyaW0oKSA6IFwiXCI7XHJcblxyXG4gICAgICAgICAgICAvL1RoaXMgbXRsIGtleXdvcmQgd2lsbCBjcmVhdGUgdGhlIG5ldyBtYXRlcmlhbFxyXG4gICAgICAgICAgICBpZiAoa2V5ID09PSBcIm5ld210bFwiKSB7XHJcbiAgICAgICAgICAgICAgICAvL0NoZWNrIGlmIGl0IGlzIHRoZSBmaXJzdCBtYXRlcmlhbC5cclxuICAgICAgICAgICAgICAgIC8vIE1hdGVyaWFscyBzcGVjaWZpY2F0aW9ucyBhcmUgZGVzY3JpYmVkIGFmdGVyIHRoaXMga2V5d29yZC5cclxuICAgICAgICAgICAgICAgIGlmIChtYXRlcmlhbCkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vQWRkIHRoZSBwcmV2aW91cyBtYXRlcmlhbCBpbiB0aGUgbWF0ZXJpYWwgYXJyYXkuXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5tYXRlcmlhbHMucHVzaChtYXRlcmlhbCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAvL0NyZWF0ZSBhIG5ldyBtYXRlcmlhbC5cclxuICAgICAgICAgICAgICAgIC8vIHZhbHVlIGlzIHRoZSBuYW1lIG9mIHRoZSBtYXRlcmlhbCByZWFkIGluIHRoZSBtdGwgZmlsZVxyXG5cclxuICAgICAgICAgICAgICAgIHNjZW5lLl9ibG9ja0VudGl0eUNvbGxlY3Rpb24gPSAhIWFzc2V0Q29udGFpbmVyO1xyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwgPSBuZXcgU3RhbmRhcmRNYXRlcmlhbCh2YWx1ZSwgc2NlbmUpO1xyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwuX3BhcmVudENvbnRhaW5lciA9IGFzc2V0Q29udGFpbmVyO1xyXG4gICAgICAgICAgICAgICAgc2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9IGZhbHNlO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGtleSA9PT0gXCJrZFwiICYmIG1hdGVyaWFsKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBEaWZmdXNlIGNvbG9yIChjb2xvciB1bmRlciB3aGl0ZSBsaWdodCkgdXNpbmcgUkdCIHZhbHVlc1xyXG5cclxuICAgICAgICAgICAgICAgIC8vdmFsdWUgID0gXCJyIGcgYlwiXHJcbiAgICAgICAgICAgICAgICBjb2xvciA9IDxudW1iZXJbXT52YWx1ZS5zcGxpdChkZWxpbWl0ZXJfcGF0dGVybiwgMykubWFwKHBhcnNlRmxvYXQpO1xyXG4gICAgICAgICAgICAgICAgLy9jb2xvciA9IFtyLGcsYl1cclxuICAgICAgICAgICAgICAgIC8vU2V0IHRnaGUgY29sb3IgaW50byB0aGUgbWF0ZXJpYWxcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsLmRpZmZ1c2VDb2xvciA9IENvbG9yMy5Gcm9tQXJyYXkoY29sb3IpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGtleSA9PT0gXCJrYVwiICYmIG1hdGVyaWFsKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBBbWJpZW50IGNvbG9yIChjb2xvciB1bmRlciBzaGFkb3cpIHVzaW5nIFJHQiB2YWx1ZXNcclxuXHJcbiAgICAgICAgICAgICAgICAvL3ZhbHVlID0gXCJyIGcgYlwiXHJcbiAgICAgICAgICAgICAgICBjb2xvciA9IDxudW1iZXJbXT52YWx1ZS5zcGxpdChkZWxpbWl0ZXJfcGF0dGVybiwgMykubWFwKHBhcnNlRmxvYXQpO1xyXG4gICAgICAgICAgICAgICAgLy9jb2xvciA9IFtyLGcsYl1cclxuICAgICAgICAgICAgICAgIC8vU2V0IHRnaGUgY29sb3IgaW50byB0aGUgbWF0ZXJpYWxcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsLmFtYmllbnRDb2xvciA9IENvbG9yMy5Gcm9tQXJyYXkoY29sb3IpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGtleSA9PT0gXCJrc1wiICYmIG1hdGVyaWFsKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBTcGVjdWxhciBjb2xvciAoY29sb3Igd2hlbiBsaWdodCBpcyByZWZsZWN0ZWQgZnJvbSBzaGlueSBzdXJmYWNlKSB1c2luZyBSR0IgdmFsdWVzXHJcblxyXG4gICAgICAgICAgICAgICAgLy92YWx1ZSA9IFwiciBnIGJcIlxyXG4gICAgICAgICAgICAgICAgY29sb3IgPSA8bnVtYmVyW10+dmFsdWUuc3BsaXQoZGVsaW1pdGVyX3BhdHRlcm4sIDMpLm1hcChwYXJzZUZsb2F0KTtcclxuICAgICAgICAgICAgICAgIC8vY29sb3IgPSBbcixnLGJdXHJcbiAgICAgICAgICAgICAgICAvL1NldCB0aGUgY29sb3IgaW50byB0aGUgbWF0ZXJpYWxcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsLnNwZWN1bGFyQ29sb3IgPSBDb2xvcjMuRnJvbUFycmF5KGNvbG9yKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChrZXkgPT09IFwia2VcIiAmJiBtYXRlcmlhbCkge1xyXG4gICAgICAgICAgICAgICAgLy8gRW1pc3NpdmUgY29sb3IgdXNpbmcgUkdCIHZhbHVlc1xyXG4gICAgICAgICAgICAgICAgY29sb3IgPSB2YWx1ZS5zcGxpdChkZWxpbWl0ZXJfcGF0dGVybiwgMykubWFwKHBhcnNlRmxvYXQpO1xyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwuZW1pc3NpdmVDb2xvciA9IENvbG9yMy5Gcm9tQXJyYXkoY29sb3IpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGtleSA9PT0gXCJuc1wiICYmIG1hdGVyaWFsKSB7XHJcbiAgICAgICAgICAgICAgICAvL3ZhbHVlID0gXCJJbnRlZ2VyXCJcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsLnNwZWN1bGFyUG93ZXIgPSBwYXJzZUZsb2F0KHZhbHVlKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChrZXkgPT09IFwiZFwiICYmIG1hdGVyaWFsKSB7XHJcbiAgICAgICAgICAgICAgICAvL2QgaXMgZGlzc29sdmUgZm9yIGN1cnJlbnQgbWF0ZXJpYWwuIEl0IG1lYW4gYWxwaGEgZm9yIEJBQllMT05cclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsLmFscGhhID0gcGFyc2VGbG9hdCh2YWx1ZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgLy9UZXh0dXJlXHJcbiAgICAgICAgICAgICAgICAvL1RoaXMgcGFydCBjYW4gYmUgaW1wcm92ZWQgYnkgYWRkaW5nIHRoZSBwb3NzaWJsZSBvcHRpb25zIG9mIHRleHR1cmVcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChrZXkgPT09IFwibWFwX2thXCIgJiYgbWF0ZXJpYWwpIHtcclxuICAgICAgICAgICAgICAgIC8vIGFtYmllbnQgdGV4dHVyZSBtYXAgd2l0aCBhIGxvYWRlZCBpbWFnZVxyXG4gICAgICAgICAgICAgICAgLy9XZSBtdXN0IGZpcnN0IGdldCB0aGUgZm9sZGVyIG9mIHRoZSBpbWFnZVxyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwuYW1iaWVudFRleHR1cmUgPSBNVExGaWxlTG9hZGVyLl9HZXRUZXh0dXJlKHJvb3RVcmwsIHZhbHVlLCBzY2VuZSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoa2V5ID09PSBcIm1hcF9rZFwiICYmIG1hdGVyaWFsKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBEaWZmdXNlIHRleHR1cmUgbWFwIHdpdGggYSBsb2FkZWQgaW1hZ2VcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFsLmRpZmZ1c2VUZXh0dXJlID0gTVRMRmlsZUxvYWRlci5fR2V0VGV4dHVyZShyb290VXJsLCB2YWx1ZSwgc2NlbmUpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGtleSA9PT0gXCJtYXBfa3NcIiAmJiBtYXRlcmlhbCkge1xyXG4gICAgICAgICAgICAgICAgLy8gU3BlY3VsYXIgdGV4dHVyZSBtYXAgd2l0aCBhIGxvYWRlZCBpbWFnZVxyXG4gICAgICAgICAgICAgICAgLy9XZSBtdXN0IGZpcnN0IGdldCB0aGUgZm9sZGVyIG9mIHRoZSBpbWFnZVxyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwuc3BlY3VsYXJUZXh0dXJlID0gTVRMRmlsZUxvYWRlci5fR2V0VGV4dHVyZShyb290VXJsLCB2YWx1ZSwgc2NlbmUpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGtleSA9PT0gXCJtYXBfbnNcIikge1xyXG4gICAgICAgICAgICAgICAgLy9TcGVjdWxhclxyXG4gICAgICAgICAgICAgICAgLy9TcGVjdWxhciBoaWdobGlnaHQgY29tcG9uZW50XHJcbiAgICAgICAgICAgICAgICAvL1dlIG11c3QgZmlyc3QgZ2V0IHRoZSBmb2xkZXIgb2YgdGhlIGltYWdlXHJcbiAgICAgICAgICAgICAgICAvL1xyXG4gICAgICAgICAgICAgICAgLy9Ob3Qgc3VwcG9ydGVkIGJ5IEJBQllMT05cclxuICAgICAgICAgICAgICAgIC8vXHJcbiAgICAgICAgICAgICAgICAvLyAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChrZXkgPT09IFwibWFwX2J1bXBcIiAmJiBtYXRlcmlhbCkge1xyXG4gICAgICAgICAgICAgICAgLy9UaGUgYnVtcCB0ZXh0dXJlXHJcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZXMgPSB2YWx1ZS5zcGxpdChkZWxpbWl0ZXJfcGF0dGVybik7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBidW1wTXVsdGlwbGllckluZGV4ID0gdmFsdWVzLmluZGV4T2YoXCItYm1cIik7XHJcbiAgICAgICAgICAgICAgICBsZXQgYnVtcE11bHRpcGxpZXI6IE51bGxhYmxlPHN0cmluZz4gPSBudWxsO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChidW1wTXVsdGlwbGllckluZGV4ID49IDApIHtcclxuICAgICAgICAgICAgICAgICAgICBidW1wTXVsdGlwbGllciA9IHZhbHVlc1tidW1wTXVsdGlwbGllckluZGV4ICsgMV07XHJcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVzLnNwbGljZShidW1wTXVsdGlwbGllckluZGV4LCAyKTsgLy8gcmVtb3ZlXHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwuYnVtcFRleHR1cmUgPSBNVExGaWxlTG9hZGVyLl9HZXRUZXh0dXJlKHJvb3RVcmwsIHZhbHVlcy5qb2luKFwiIFwiKSwgc2NlbmUpO1xyXG4gICAgICAgICAgICAgICAgaWYgKG1hdGVyaWFsLmJ1bXBUZXh0dXJlICYmIGJ1bXBNdWx0aXBsaWVyICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWwuYnVtcFRleHR1cmUubGV2ZWwgPSBwYXJzZUZsb2F0KGJ1bXBNdWx0aXBsaWVyKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSBlbHNlIGlmIChrZXkgPT09IFwibWFwX2RcIiAmJiBtYXRlcmlhbCkge1xyXG4gICAgICAgICAgICAgICAgLy8gVGhlIGRpc3NvbHZlIG9mIHRoZSBtYXRlcmlhbFxyXG4gICAgICAgICAgICAgICAgbWF0ZXJpYWwub3BhY2l0eVRleHR1cmUgPSBNVExGaWxlTG9hZGVyLl9HZXRUZXh0dXJlKHJvb3RVcmwsIHZhbHVlLCBzY2VuZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgLy9PcHRpb25zIGZvciBpbGx1bWluYXRpb25cclxuICAgICAgICAgICAgfSBlbHNlIGlmIChrZXkgPT09IFwiaWxsdW1cIikge1xyXG4gICAgICAgICAgICAgICAgLy9JbGx1bWluYXRpb25cclxuICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gXCIwXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAvL1RoYXQgbWVhbiBLZCA9PSBLZFxyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gXCIxXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAvL0NvbG9yIG9uIGFuZCBBbWJpZW50IG9uXHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSBcIjJcIikge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vSGlnaGxpZ2h0IG9uXHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSBcIjNcIikge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vUmVmbGVjdGlvbiBvbiBhbmQgUmF5IHRyYWNlIG9uXHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSBcIjRcIikge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vVHJhbnNwYXJlbmN5OiBHbGFzcyBvbiwgUmVmbGVjdGlvbjogUmF5IHRyYWNlIG9uXHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSBcIjVcIikge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vUmVmbGVjdGlvbjogRnJlc25lbCBvbiBhbmQgUmF5IHRyYWNlIG9uXHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSBcIjZcIikge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vVHJhbnNwYXJlbmN5OiBSZWZyYWN0aW9uIG9uLCBSZWZsZWN0aW9uOiBGcmVzbmVsIG9mZiBhbmQgUmF5IHRyYWNlIG9uXHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSBcIjdcIikge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vVHJhbnNwYXJlbmN5OiBSZWZyYWN0aW9uIG9uLCBSZWZsZWN0aW9uOiBGcmVzbmVsIG9uIGFuZCBSYXkgdHJhY2Ugb25cclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodmFsdWUgPT09IFwiOFwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9SZWZsZWN0aW9uIG9uIGFuZCBSYXkgdHJhY2Ugb2ZmXHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHZhbHVlID09PSBcIjlcIikge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vVHJhbnNwYXJlbmN5OiBHbGFzcyBvbiwgUmVmbGVjdGlvbjogUmF5IHRyYWNlIG9mZlxyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh2YWx1ZSA9PT0gXCIxMFwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9DYXN0cyBzaGFkb3dzIG9udG8gaW52aXNpYmxlIHN1cmZhY2VzXHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvLyBjb25zb2xlLmxvZyhcIlVuaGFuZGxlZCBleHByZXNzaW9uIGF0IGxpbmUgOiBcIiArIGkgKydcXG4nICsgXCJ3aXRoIHZhbHVlIDogXCIgKyBsaW5lKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICAvL0F0IHRoZSBlbmQgb2YgdGhlIGZpbGUsIGFkZCB0aGUgbGFzdCBtYXRlcmlhbFxyXG4gICAgICAgIGlmIChtYXRlcmlhbCkge1xyXG4gICAgICAgICAgICB0aGlzLm1hdGVyaWFscy5wdXNoKG1hdGVyaWFsKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIHRoZSB0ZXh0dXJlIGZvciB0aGUgbWF0ZXJpYWwuXHJcbiAgICAgKlxyXG4gICAgICogSWYgdGhlIG1hdGVyaWFsIGlzIGltcG9ydGVkIGZyb20gaW5wdXQgZmlsZSxcclxuICAgICAqIFdlIHNhbml0aXplIHRoZSB1cmwgdG8gZW5zdXJlIGl0IHRha2VzIHRoZSB0ZXh0dXJlIGZyb20gYXNpZGUgdGhlIG1hdGVyaWFsLlxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSByb290VXJsIFRoZSByb290IHVybCB0byBsb2FkIGZyb21cclxuICAgICAqIEBwYXJhbSB2YWx1ZSBUaGUgdmFsdWUgc3RvcmVkIGluIHRoZSBtdGxcclxuICAgICAqIEBwYXJhbSBzY2VuZVxyXG4gICAgICogQHJldHVybnMgVGhlIFRleHR1cmVcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBzdGF0aWMgX0dldFRleHR1cmUocm9vdFVybDogc3RyaW5nLCB2YWx1ZTogc3RyaW5nLCBzY2VuZTogU2NlbmUpOiBOdWxsYWJsZTxUZXh0dXJlPiB7XHJcbiAgICAgICAgaWYgKCF2YWx1ZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCB1cmwgPSByb290VXJsO1xyXG4gICAgICAgIC8vIExvYWQgZnJvbSBpbnB1dCBmaWxlLlxyXG4gICAgICAgIGlmIChyb290VXJsID09PSBcImZpbGU6XCIpIHtcclxuICAgICAgICAgICAgbGV0IGxhc3REZWxpbWl0ZXIgPSB2YWx1ZS5sYXN0SW5kZXhPZihcIlxcXFxcIik7XHJcbiAgICAgICAgICAgIGlmIChsYXN0RGVsaW1pdGVyID09PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgbGFzdERlbGltaXRlciA9IHZhbHVlLmxhc3RJbmRleE9mKFwiL1wiKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKGxhc3REZWxpbWl0ZXIgPiAtMSkge1xyXG4gICAgICAgICAgICAgICAgdXJsICs9IHZhbHVlLnN1YnN0cihsYXN0RGVsaW1pdGVyICsgMSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB1cmwgKz0gdmFsdWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICAgICAgLy8gTm90IGZyb20gaW5wdXQgZmlsZS5cclxuICAgICAgICBlbHNlIHtcclxuICAgICAgICAgICAgdXJsICs9IHZhbHVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIG5ldyBUZXh0dXJlKHVybCwgc2NlbmUsIGZhbHNlLCBNVExGaWxlTG9hZGVyLklOVkVSVF9URVhUVVJFX1kpO1xyXG4gICAgfVxyXG59XHJcbiIsImltcG9ydCB0eXBlIHsgTnVsbGFibGUgfSBmcm9tIFwiY29yZS90eXBlc1wiO1xyXG5pbXBvcnQgeyBWZWN0b3IyIH0gZnJvbSBcImNvcmUvTWF0aHMvbWF0aC52ZWN0b3JcIjtcclxuaW1wb3J0IHsgVG9vbHMgfSBmcm9tIFwiY29yZS9NaXNjL3Rvb2xzXCI7XHJcbmltcG9ydCB0eXBlIHsgQWJzdHJhY3RNZXNoIH0gZnJvbSBcImNvcmUvTWVzaGVzL2Fic3RyYWN0TWVzaFwiO1xyXG5pbXBvcnQgdHlwZSB7IElTY2VuZUxvYWRlclBsdWdpbkFzeW5jLCBJU2NlbmVMb2FkZXJQbHVnaW5GYWN0b3J5LCBJU2NlbmVMb2FkZXJQbHVnaW4sIElTY2VuZUxvYWRlckFzeW5jUmVzdWx0IH0gZnJvbSBcImNvcmUvTG9hZGluZy9zY2VuZUxvYWRlclwiO1xyXG5pbXBvcnQgeyBTY2VuZUxvYWRlciB9IGZyb20gXCJjb3JlL0xvYWRpbmcvc2NlbmVMb2FkZXJcIjtcclxuaW1wb3J0IHsgQXNzZXRDb250YWluZXIgfSBmcm9tIFwiY29yZS9hc3NldENvbnRhaW5lclwiO1xyXG5pbXBvcnQgdHlwZSB7IFNjZW5lIH0gZnJvbSBcImNvcmUvc2NlbmVcIjtcclxuaW1wb3J0IHR5cGUgeyBXZWJSZXF1ZXN0IH0gZnJvbSBcImNvcmUvTWlzYy93ZWJSZXF1ZXN0XCI7XHJcbmltcG9ydCB7IE1UTEZpbGVMb2FkZXIgfSBmcm9tIFwiLi9tdGxGaWxlTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgT0JKTG9hZGluZ09wdGlvbnMgfSBmcm9tIFwiLi9vYmpMb2FkaW5nT3B0aW9uc1wiO1xyXG5pbXBvcnQgeyBTb2xpZFBhcnNlciB9IGZyb20gXCIuL3NvbGlkUGFyc2VyXCI7XHJcbmltcG9ydCB0eXBlIHsgTWVzaCB9IGZyb20gXCJjb3JlL01lc2hlcy9tZXNoXCI7XHJcblxyXG4vKipcclxuICogT0JKIGZpbGUgdHlwZSBsb2FkZXIuXHJcbiAqIFRoaXMgaXMgYSBiYWJ5bG9uIHNjZW5lIGxvYWRlciBwbHVnaW4uXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgT0JKRmlsZUxvYWRlciBpbXBsZW1lbnRzIElTY2VuZUxvYWRlclBsdWdpbkFzeW5jLCBJU2NlbmVMb2FkZXJQbHVnaW5GYWN0b3J5IHtcclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lcyBpZiBVVnMgYXJlIG9wdGltaXplZCBieSBkZWZhdWx0IGR1cmluZyBsb2FkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIE9QVElNSVpFX1dJVEhfVVYgPSB0cnVlO1xyXG4gICAgLyoqXHJcbiAgICAgKiBJbnZlcnQgbW9kZWwgb24geS1heGlzIChkb2VzIGEgbW9kZWwgc2NhbGluZyBpbnZlcnNpb24pXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgSU5WRVJUX1kgPSBmYWxzZTtcclxuICAgIC8qKlxyXG4gICAgICogSW52ZXJ0IFktQXhpcyBvZiByZWZlcmVuY2VkIHRleHR1cmVzIG9uIGxvYWRcclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBnZXQgSU5WRVJUX1RFWFRVUkVfWSgpIHtcclxuICAgICAgICByZXR1cm4gTVRMRmlsZUxvYWRlci5JTlZFUlRfVEVYVFVSRV9ZO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBzdGF0aWMgc2V0IElOVkVSVF9URVhUVVJFX1kodmFsdWU6IGJvb2xlYW4pIHtcclxuICAgICAgICBNVExGaWxlTG9hZGVyLklOVkVSVF9URVhUVVJFX1kgPSB2YWx1ZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEluY2x1ZGUgaW4gbWVzaGVzIHRoZSB2ZXJ0ZXggY29sb3JzIGF2YWlsYWJsZSBpbiBzb21lIE9CSiBmaWxlcy4gIFRoaXMgaXMgbm90IHBhcnQgb2YgT0JKIHN0YW5kYXJkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIElNUE9SVF9WRVJURVhfQ09MT1JTID0gZmFsc2U7XHJcbiAgICAvKipcclxuICAgICAqIENvbXB1dGUgdGhlIG5vcm1hbHMgZm9yIHRoZSBtb2RlbCwgZXZlbiBpZiBub3JtYWxzIGFyZSBwcmVzZW50IGluIHRoZSBmaWxlLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIENPTVBVVEVfTk9STUFMUyA9IGZhbHNlO1xyXG4gICAgLyoqXHJcbiAgICAgKiBPcHRpbWl6ZSB0aGUgbm9ybWFscyBmb3IgdGhlIG1vZGVsLiBMaWdodGluZyBjYW4gYmUgdW5ldmVuIGlmIHlvdSB1c2UgT3B0aW1pemVXaXRoVVYgPSB0cnVlIGJlY2F1c2UgbmV3IHZlcnRpY2VzIGNhbiBiZSBjcmVhdGVkIGZvciB0aGUgc2FtZSBsb2NhdGlvbiBpZiB0aGV5IHBlcnRhaW4gdG8gZGlmZmVyZW50IGZhY2VzLlxyXG4gICAgICogVXNpbmcgT3B0aW1pemVoTm9ybWFscyA9IHRydWUgd2lsbCBoZWxwIHNtb290aGluZyB0aGUgbGlnaHRpbmcgYnkgYXZlcmFnaW5nIHRoZSBub3JtYWxzIG9mIHRob3NlIHZlcnRpY2VzLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIE9QVElNSVpFX05PUk1BTFMgPSBmYWxzZTtcclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lcyBjdXN0b20gc2NhbGluZyBvZiBVViBjb29yZGluYXRlcyBvZiBsb2FkZWQgbWVzaGVzLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIFVWX1NDQUxJTkcgPSBuZXcgVmVjdG9yMigxLCAxKTtcclxuICAgIC8qKlxyXG4gICAgICogU2tpcCBsb2FkaW5nIHRoZSBtYXRlcmlhbHMgZXZlbiBpZiBkZWZpbmVkIGluIHRoZSBPQkogZmlsZSAobWF0ZXJpYWxzIGFyZSBpZ25vcmVkKS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBTS0lQX01BVEVSSUFMUyA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogV2hlbiBhIG1hdGVyaWFsIGZhaWxzIHRvIGxvYWQgT0JKIGxvYWRlciB3aWxsIHNpbGVudGx5IGZhaWwgYW5kIG9uU3VjY2VzcygpIGNhbGxiYWNrIHdpbGwgYmUgdHJpZ2dlcmVkLlxyXG4gICAgICpcclxuICAgICAqIERlZmF1bHRzIHRvIHRydWUgZm9yIGJhY2t3YXJkcyBjb21wYXRpYmlsaXR5LlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIE1BVEVSSUFMX0xPQURJTkdfRkFJTFNfU0lMRU5UTFkgPSB0cnVlO1xyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHRoZSBuYW1lIG9mIHRoZSBwbHVnaW4uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBuYW1lID0gXCJvYmpcIjtcclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lcyB0aGUgZXh0ZW5zaW9uIHRoZSBwbHVnaW4gaXMgYWJsZSB0byBsb2FkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZXh0ZW5zaW9ucyA9IFwiLm9ialwiO1xyXG5cclxuICAgIHByaXZhdGUgX2Fzc2V0Q29udGFpbmVyOiBOdWxsYWJsZTxBc3NldENvbnRhaW5lcj4gPSBudWxsO1xyXG5cclxuICAgIHByaXZhdGUgX2xvYWRpbmdPcHRpb25zOiBPQkpMb2FkaW5nT3B0aW9ucztcclxuXHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgbG9hZGVyIGZvciAuT0JKIGZpbGVzXHJcbiAgICAgKlxyXG4gICAgICogQHBhcmFtIGxvYWRpbmdPcHRpb25zIG9wdGlvbnMgZm9yIGxvYWRpbmcgYW5kIHBhcnNpbmcgT0JKL01UTCBmaWxlcy5cclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGluZ09wdGlvbnM/OiBPQkpMb2FkaW5nT3B0aW9ucykge1xyXG4gICAgICAgIHRoaXMuX2xvYWRpbmdPcHRpb25zID0gbG9hZGluZ09wdGlvbnMgfHwgT0JKRmlsZUxvYWRlci5fRGVmYXVsdExvYWRpbmdPcHRpb25zO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIGdldCBfRGVmYXVsdExvYWRpbmdPcHRpb25zKCk6IE9CSkxvYWRpbmdPcHRpb25zIHtcclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBjb21wdXRlTm9ybWFsczogT0JKRmlsZUxvYWRlci5DT01QVVRFX05PUk1BTFMsXHJcbiAgICAgICAgICAgIG9wdGltaXplTm9ybWFsczogT0JKRmlsZUxvYWRlci5PUFRJTUlaRV9OT1JNQUxTLFxyXG4gICAgICAgICAgICBpbXBvcnRWZXJ0ZXhDb2xvcnM6IE9CSkZpbGVMb2FkZXIuSU1QT1JUX1ZFUlRFWF9DT0xPUlMsXHJcbiAgICAgICAgICAgIGludmVydFk6IE9CSkZpbGVMb2FkZXIuSU5WRVJUX1ksXHJcbiAgICAgICAgICAgIGludmVydFRleHR1cmVZOiBPQkpGaWxlTG9hZGVyLklOVkVSVF9URVhUVVJFX1ksXHJcbiAgICAgICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cclxuICAgICAgICAgICAgVVZTY2FsaW5nOiBPQkpGaWxlTG9hZGVyLlVWX1NDQUxJTkcsXHJcbiAgICAgICAgICAgIG1hdGVyaWFsTG9hZGluZ0ZhaWxzU2lsZW50bHk6IE9CSkZpbGVMb2FkZXIuTUFURVJJQUxfTE9BRElOR19GQUlMU19TSUxFTlRMWSxcclxuICAgICAgICAgICAgb3B0aW1pemVXaXRoVVY6IE9CSkZpbGVMb2FkZXIuT1BUSU1JWkVfV0lUSF9VVixcclxuICAgICAgICAgICAgc2tpcE1hdGVyaWFsczogT0JKRmlsZUxvYWRlci5TS0lQX01BVEVSSUFMUyxcclxuICAgICAgICB9O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2FsbHMgc3luY2hyb25vdXNseSB0aGUgTVRMIGZpbGUgYXR0YWNoZWQgdG8gdGhpcyBvYmouXHJcbiAgICAgKiBMb2FkIGZ1bmN0aW9uIG9yIGltcG9ydE1lc2ggZnVuY3Rpb24gZG9uJ3QgZW5hYmxlIHRvIGxvYWQgMiBmaWxlcyBpbiB0aGUgc2FtZSB0aW1lIGFzeW5jaHJvbm91c2x5LlxyXG4gICAgICogV2l0aG91dCB0aGlzIGZ1bmN0aW9uIG1hdGVyaWFscyBhcmUgbm90IGRpc3BsYXllZCBpbiB0aGUgZmlyc3QgZnJhbWUgKGJ1dCBkaXNwbGF5ZWQgYWZ0ZXIpLlxyXG4gICAgICogSW4gY29uc2VxdWVuY2UgaXQgaXMgaW1wb3NzaWJsZSB0byBnZXQgbWF0ZXJpYWwgaW5mb3JtYXRpb24gaW4geW91ciBIVE1MIGZpbGVcclxuICAgICAqXHJcbiAgICAgKiBAcGFyYW0gdXJsIFRoZSBVUkwgb2YgdGhlIE1UTCBmaWxlXHJcbiAgICAgKiBAcGFyYW0gcm9vdFVybCBkZWZpbmVzIHdoZXJlIHRvIGxvYWQgZGF0YSBmcm9tXHJcbiAgICAgKiBAcGFyYW0gb25TdWNjZXNzIENhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBNVEwgZmlsZSBpcyBsb2FkZWRcclxuICAgICAqIEBwYXJhbSBvbkZhaWx1cmVcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBfbG9hZE1UTChcclxuICAgICAgICB1cmw6IHN0cmluZyxcclxuICAgICAgICByb290VXJsOiBzdHJpbmcsXHJcbiAgICAgICAgb25TdWNjZXNzOiAocmVzcG9uc2U6IHN0cmluZyB8IEFycmF5QnVmZmVyLCByZXNwb25zZVVybD86IHN0cmluZykgPT4gYW55LFxyXG4gICAgICAgIG9uRmFpbHVyZTogKHBhdGhPZkZpbGU6IHN0cmluZywgZXhjZXB0aW9uPzogYW55KSA9PiB2b2lkXHJcbiAgICApIHtcclxuICAgICAgICAvL1RoZSBjb21wbGV0ZSBwYXRoIHRvIHRoZSBtdGwgZmlsZVxyXG4gICAgICAgIGNvbnN0IHBhdGhPZkZpbGUgPSByb290VXJsICsgdXJsO1xyXG5cclxuICAgICAgICAvLyBMb2FkcyB0aHJvdWdoIHRoZSBiYWJ5bG9uIHRvb2xzIHRvIGFsbG93IGZpbGVJbnB1dCBzZWFyY2guXHJcbiAgICAgICAgVG9vbHMuTG9hZEZpbGUocGF0aE9mRmlsZSwgb25TdWNjZXNzLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgZmFsc2UsIChyZXF1ZXN0PzogV2ViUmVxdWVzdCB8IHVuZGVmaW5lZCwgZXhjZXB0aW9uPzogYW55KSA9PiB7XHJcbiAgICAgICAgICAgIG9uRmFpbHVyZShwYXRoT2ZGaWxlLCBleGNlcHRpb24pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW5zdGFudGlhdGVzIGEgT0JKIGZpbGUgbG9hZGVyIHBsdWdpbi5cclxuICAgICAqIEByZXR1cm5zIHRoZSBjcmVhdGVkIHBsdWdpblxyXG4gICAgICovXHJcbiAgICBjcmVhdGVQbHVnaW4oKTogSVNjZW5lTG9hZGVyUGx1Z2luQXN5bmMgfCBJU2NlbmVMb2FkZXJQbHVnaW4ge1xyXG4gICAgICAgIHJldHVybiBuZXcgT0JKRmlsZUxvYWRlcihPQkpGaWxlTG9hZGVyLl9EZWZhdWx0TG9hZGluZ09wdGlvbnMpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSWYgdGhlIGRhdGEgc3RyaW5nIGNhbiBiZSBsb2FkZWQgZGlyZWN0bHkuXHJcbiAgICAgKiBAcmV0dXJucyBpZiB0aGUgZGF0YSBjYW4gYmUgbG9hZGVkIGRpcmVjdGx5XHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjYW5EaXJlY3RMb2FkKCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEltcG9ydHMgb25lIG9yIG1vcmUgbWVzaGVzIGZyb20gdGhlIGxvYWRlZCBPQkogZGF0YSBhbmQgYWRkcyB0aGVtIHRvIHRoZSBzY2VuZVxyXG4gICAgICogQHBhcmFtIG1lc2hlc05hbWVzIGEgc3RyaW5nIG9yIGFycmF5IG9mIHN0cmluZ3Mgb2YgdGhlIG1lc2ggbmFtZXMgdGhhdCBzaG91bGQgYmUgbG9hZGVkIGZyb20gdGhlIGZpbGVcclxuICAgICAqIEBwYXJhbSBzY2VuZSB0aGUgc2NlbmUgdGhlIG1lc2hlcyBzaG91bGQgYmUgYWRkZWQgdG9cclxuICAgICAqIEBwYXJhbSBkYXRhIHRoZSBPQkogZGF0YSB0byBsb2FkXHJcbiAgICAgKiBAcGFyYW0gcm9vdFVybCByb290IHVybCB0byBsb2FkIGZyb21cclxuICAgICAqIEByZXR1cm5zIGEgcHJvbWlzZSBjb250YWluaW5nIHRoZSBsb2FkZWQgbWVzaGVzLCBwYXJ0aWNsZXMsIHNrZWxldG9ucyBhbmQgYW5pbWF0aW9uc1xyXG4gICAgICovXHJcbiAgICBwdWJsaWMgaW1wb3J0TWVzaEFzeW5jKG1lc2hlc05hbWVzOiBhbnksIHNjZW5lOiBTY2VuZSwgZGF0YTogYW55LCByb290VXJsOiBzdHJpbmcpOiBQcm9taXNlPElTY2VuZUxvYWRlckFzeW5jUmVzdWx0PiB7XHJcbiAgICAgICAgLy9nZXQgdGhlIG1lc2hlcyBmcm9tIE9CSiBmaWxlXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BhcnNlU29saWQobWVzaGVzTmFtZXMsIHNjZW5lLCBkYXRhLCByb290VXJsKS50aGVuKChtZXNoZXMpID0+IHtcclxuICAgICAgICAgICAgcmV0dXJuIHtcclxuICAgICAgICAgICAgICAgIG1lc2hlczogbWVzaGVzLFxyXG4gICAgICAgICAgICAgICAgcGFydGljbGVTeXN0ZW1zOiBbXSxcclxuICAgICAgICAgICAgICAgIHNrZWxldG9uczogW10sXHJcbiAgICAgICAgICAgICAgICBhbmltYXRpb25Hcm91cHM6IFtdLFxyXG4gICAgICAgICAgICAgICAgdHJhbnNmb3JtTm9kZXM6IFtdLFxyXG4gICAgICAgICAgICAgICAgZ2VvbWV0cmllczogW10sXHJcbiAgICAgICAgICAgICAgICBsaWdodHM6IFtdLFxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW1wb3J0cyBhbGwgb2JqZWN0cyBmcm9tIHRoZSBsb2FkZWQgT0JKIGRhdGEgYW5kIGFkZHMgdGhlbSB0byB0aGUgc2NlbmVcclxuICAgICAqIEBwYXJhbSBzY2VuZSB0aGUgc2NlbmUgdGhlIG9iamVjdHMgc2hvdWxkIGJlIGFkZGVkIHRvXHJcbiAgICAgKiBAcGFyYW0gZGF0YSB0aGUgT0JKIGRhdGEgdG8gbG9hZFxyXG4gICAgICogQHBhcmFtIHJvb3RVcmwgcm9vdCB1cmwgdG8gbG9hZCBmcm9tXHJcbiAgICAgKiBAcmV0dXJucyBhIHByb21pc2Ugd2hpY2ggY29tcGxldGVzIHdoZW4gb2JqZWN0cyBoYXZlIGJlZW4gbG9hZGVkIHRvIHRoZSBzY2VuZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZEFzeW5jKHNjZW5lOiBTY2VuZSwgZGF0YTogc3RyaW5nLCByb290VXJsOiBzdHJpbmcpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICAvL0dldCB0aGUgM0QgbW9kZWxcclxuICAgICAgICByZXR1cm4gdGhpcy5pbXBvcnRNZXNoQXN5bmMobnVsbCwgc2NlbmUsIGRhdGEsIHJvb3RVcmwpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICAvLyByZXR1cm4gdm9pZFxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTG9hZCBpbnRvIGFuIGFzc2V0IGNvbnRhaW5lci5cclxuICAgICAqIEBwYXJhbSBzY2VuZSBUaGUgc2NlbmUgdG8gbG9hZCBpbnRvXHJcbiAgICAgKiBAcGFyYW0gZGF0YSBUaGUgZGF0YSB0byBpbXBvcnRcclxuICAgICAqIEBwYXJhbSByb290VXJsIFRoZSByb290IHVybCBmb3Igc2NlbmUgYW5kIHJlc291cmNlc1xyXG4gICAgICogQHJldHVybnMgVGhlIGxvYWRlZCBhc3NldCBjb250YWluZXJcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRBc3NldENvbnRhaW5lckFzeW5jKHNjZW5lOiBTY2VuZSwgZGF0YTogc3RyaW5nLCByb290VXJsOiBzdHJpbmcpOiBQcm9taXNlPEFzc2V0Q29udGFpbmVyPiB7XHJcbiAgICAgICAgY29uc3QgY29udGFpbmVyID0gbmV3IEFzc2V0Q29udGFpbmVyKHNjZW5lKTtcclxuICAgICAgICB0aGlzLl9hc3NldENvbnRhaW5lciA9IGNvbnRhaW5lcjtcclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuaW1wb3J0TWVzaEFzeW5jKG51bGwsIHNjZW5lLCBkYXRhLCByb290VXJsKVxyXG4gICAgICAgICAgICAudGhlbigocmVzdWx0KSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXN1bHQubWVzaGVzLmZvckVhY2goKG1lc2gpID0+IGNvbnRhaW5lci5tZXNoZXMucHVzaChtZXNoKSk7XHJcbiAgICAgICAgICAgICAgICByZXN1bHQubWVzaGVzLmZvckVhY2goKG1lc2gpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXRlcmlhbCA9IG1lc2gubWF0ZXJpYWw7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1hdGVyaWFsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE1hdGVyaWFsc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoY29udGFpbmVyLm1hdGVyaWFscy5pbmRleE9mKG1hdGVyaWFsKSA9PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGFpbmVyLm1hdGVyaWFscy5wdXNoKG1hdGVyaWFsKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUZXh0dXJlc1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdGV4dHVyZXMgPSBtYXRlcmlhbC5nZXRBY3RpdmVUZXh0dXJlcygpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGV4dHVyZXMuZm9yRWFjaCgodCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChjb250YWluZXIudGV4dHVyZXMuaW5kZXhPZih0KSA9PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb250YWluZXIudGV4dHVyZXMucHVzaCh0KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fYXNzZXRDb250YWluZXIgPSBudWxsO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGNvbnRhaW5lcjtcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgLmNhdGNoKChleCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fYXNzZXRDb250YWluZXIgPSBudWxsO1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgZXg7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVhZCB0aGUgT0JKIGZpbGUgYW5kIGNyZWF0ZSBhbiBBcnJheSBvZiBtZXNoZXMuXHJcbiAgICAgKiBFYWNoIG1lc2ggY29udGFpbnMgYWxsIGluZm9ybWF0aW9uIGdpdmVuIGJ5IHRoZSBPQkogYW5kIHRoZSBNVEwgZmlsZS5cclxuICAgICAqIGkuZS4gdmVydGljZXMgcG9zaXRpb25zIGFuZCBpbmRpY2VzLCBvcHRpb25hbCBub3JtYWxzIHZhbHVlcywgb3B0aW9uYWwgVVYgdmFsdWVzLCBvcHRpb25hbCBtYXRlcmlhbFxyXG4gICAgICogQHBhcmFtIG1lc2hlc05hbWVzIGRlZmluZXMgYSBzdHJpbmcgb3IgYXJyYXkgb2Ygc3RyaW5ncyBvZiB0aGUgbWVzaCBuYW1lcyB0aGF0IHNob3VsZCBiZSBsb2FkZWQgZnJvbSB0aGUgZmlsZVxyXG4gICAgICogQHBhcmFtIHNjZW5lIGRlZmluZXMgdGhlIHNjZW5lIHdoZXJlIGFyZSBkaXNwbGF5ZWQgdGhlIGRhdGFcclxuICAgICAqIEBwYXJhbSBkYXRhIGRlZmluZXMgdGhlIGNvbnRlbnQgb2YgdGhlIG9iaiBmaWxlXHJcbiAgICAgKiBAcGFyYW0gcm9vdFVybCBkZWZpbmVzIHRoZSBwYXRoIHRvIHRoZSBmb2xkZXJcclxuICAgICAqIEByZXR1cm5zIHRoZSBsaXN0IG9mIGxvYWRlZCBtZXNoZXNcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBfcGFyc2VTb2xpZChtZXNoZXNOYW1lczogYW55LCBzY2VuZTogU2NlbmUsIGRhdGE6IHN0cmluZywgcm9vdFVybDogc3RyaW5nKTogUHJvbWlzZTxBcnJheTxBYnN0cmFjdE1lc2g+PiB7XHJcbiAgICAgICAgbGV0IGZpbGVUb0xvYWQ6IHN0cmluZyA9IFwiXCI7IC8vVGhlIG5hbWUgb2YgdGhlIG10bEZpbGUgdG8gbG9hZFxyXG4gICAgICAgIGNvbnN0IG1hdGVyaWFsc0Zyb21NVExGaWxlOiBNVExGaWxlTG9hZGVyID0gbmV3IE1UTEZpbGVMb2FkZXIoKTtcclxuICAgICAgICBjb25zdCBtYXRlcmlhbFRvVXNlID0gbmV3IEFycmF5PHN0cmluZz4oKTtcclxuICAgICAgICBjb25zdCBiYWJ5bG9uTWVzaGVzQXJyYXk6IEFycmF5PE1lc2g+ID0gW107IC8vVGhlIG1lc2ggZm9yIGJhYnlsb25cclxuXHJcbiAgICAgICAgLy8gTWFpbiBmdW5jdGlvblxyXG4gICAgICAgIGNvbnN0IHNvbGlkUGFyc2VyID0gbmV3IFNvbGlkUGFyc2VyKG1hdGVyaWFsVG9Vc2UsIGJhYnlsb25NZXNoZXNBcnJheSwgdGhpcy5fbG9hZGluZ09wdGlvbnMpO1xyXG5cclxuICAgICAgICBzb2xpZFBhcnNlci5wYXJzZShtZXNoZXNOYW1lcywgZGF0YSwgc2NlbmUsIHRoaXMuX2Fzc2V0Q29udGFpbmVyLCAoZmlsZU5hbWU6IHN0cmluZykgPT4ge1xyXG4gICAgICAgICAgICBmaWxlVG9Mb2FkID0gZmlsZU5hbWU7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIC8vIGxvYWQgdGhlIG1hdGVyaWFsc1xyXG4gICAgICAgIGNvbnN0IG10bFByb21pc2VzOiBBcnJheTxQcm9taXNlPHZvaWQ+PiA9IFtdO1xyXG4gICAgICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgYSBmaWxlIHRvIGxvYWRcclxuICAgICAgICBpZiAoZmlsZVRvTG9hZCAhPT0gXCJcIiAmJiAhdGhpcy5fbG9hZGluZ09wdGlvbnMuc2tpcE1hdGVyaWFscykge1xyXG4gICAgICAgICAgICAvL0xvYWQgdGhlIGZpbGUgc3luY2hyb25vdXNseVxyXG4gICAgICAgICAgICBtdGxQcm9taXNlcy5wdXNoKFxyXG4gICAgICAgICAgICAgICAgbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRNVEwoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVUb0xvYWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJvb3RVcmwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIChkYXRhTG9hZGVkKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vQ3JlYXRlIG1hdGVyaWFscyB0aGFua3MgTVRMTG9hZGVyIGZ1bmN0aW9uXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWxzRnJvbU1UTEZpbGUucGFyc2VNVEwoc2NlbmUsIGRhdGFMb2FkZWQsIHJvb3RVcmwsIHRoaXMuX2Fzc2V0Q29udGFpbmVyKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL0xvb2sgYXQgZWFjaCBtYXRlcmlhbCBsb2FkZWQgaW4gdGhlIG10bCBmaWxlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgbiA9IDA7IG4gPCBtYXRlcmlhbHNGcm9tTVRMRmlsZS5tYXRlcmlhbHMubGVuZ3RoOyBuKyspIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9UaHJlZSB2YXJpYWJsZXMgdG8gZ2V0IGFsbCBtZXNoZXMgd2l0aCB0aGUgc2FtZSBtYXRlcmlhbFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgc3RhcnRJbmRleCA9IDA7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IF9pbmRpY2VzID0gW107XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBfaW5kZXg7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL1RoZSBtYXRlcmlhbCBmcm9tIE1UTCBmaWxlIGlzIHVzZWQgaW4gdGhlIG1lc2hlcyBsb2FkZWRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9QdXNoIHRoZSBpbmRpY2UgaW4gYW4gYXJyYXlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9DaGVjayBpZiB0aGUgbWF0ZXJpYWwgaXMgbm90IHVzZWQgZm9yIGFub3RoZXIgbWVzaFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3aGlsZSAoKF9pbmRleCA9IG1hdGVyaWFsVG9Vc2UuaW5kZXhPZihtYXRlcmlhbHNGcm9tTVRMRmlsZS5tYXRlcmlhbHNbbl0ubmFtZSwgc3RhcnRJbmRleCkpID4gLTEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF9pbmRpY2VzLnB1c2goX2luZGV4KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0YXJ0SW5kZXggPSBfaW5kZXggKyAxO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vSWYgdGhlIG1hdGVyaWFsIGlzIG5vdCB1c2VkIGRpc3Bvc2UgaXRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKF9pbmRleCA9PT0gLTEgJiYgX2luZGljZXMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL0lmIHRoZSBtYXRlcmlhbCBpcyBub3QgbmVlZGVkLCByZW1vdmUgaXRcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hdGVyaWFsc0Zyb21NVExGaWxlLm1hdGVyaWFsc1tuXS5kaXNwb3NlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBvID0gMDsgbyA8IF9pbmRpY2VzLmxlbmd0aDsgbysrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy9BcHBseSB0aGUgbWF0ZXJpYWwgdG8gdGhlIE1lc2ggZm9yIGVhY2ggbWVzaCB3aXRoIHRoZSBtYXRlcmlhbFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1lc2ggPSBiYWJ5bG9uTWVzaGVzQXJyYXlbX2luZGljZXNbb11dO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hdGVyaWFsID0gbWF0ZXJpYWxzRnJvbU1UTEZpbGUubWF0ZXJpYWxzW25dO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc2gubWF0ZXJpYWwgPSBtYXRlcmlhbDtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFtZXNoLmdldFRvdGFsSW5kaWNlcygpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vIGluZGljZXMsIHdlIG5lZWQgdG8gdHVybiBvbiBwb2ludCBjbG91ZFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRlcmlhbC5wb2ludHNDbG91ZCA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUb29scy5XYXJuKGBFcnJvciBwcm9jZXNzaW5nIE1UTCBmaWxlOiAnJHtmaWxlVG9Mb2FkfSdgKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fbG9hZGluZ09wdGlvbnMubWF0ZXJpYWxMb2FkaW5nRmFpbHNTaWxlbnRseSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgKHBhdGhPZkZpbGU6IHN0cmluZywgZXhjZXB0aW9uPzogYW55KSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBUb29scy5XYXJuKGBFcnJvciBkb3dubG9hZGluZyBNVEwgZmlsZTogJyR7ZmlsZVRvTG9hZH0nYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fbG9hZGluZ09wdGlvbnMubWF0ZXJpYWxMb2FkaW5nRmFpbHNTaWxlbnRseSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGV4Y2VwdGlvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy9SZXR1cm4gYW4gYXJyYXkgd2l0aCBhbGwgTWVzaFxyXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChtdGxQcm9taXNlcykudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiBiYWJ5bG9uTWVzaGVzQXJyYXk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbmlmIChTY2VuZUxvYWRlcikge1xyXG4gICAgLy9BZGQgdGhpcyBsb2FkZXIgaW50byB0aGUgcmVnaXN0ZXIgcGx1Z2luXHJcbiAgICBTY2VuZUxvYWRlci5SZWdpc3RlclBsdWdpbihuZXcgT0JKRmlsZUxvYWRlcigpKTtcclxufVxyXG4iLCJpbXBvcnQgdHlwZSB7IFZlY3RvcjIgfSBmcm9tIFwiY29yZS9NYXRocy9tYXRoLnZlY3RvclwiO1xyXG5cclxuLyoqXHJcbiAqIE9wdGlvbnMgZm9yIGxvYWRpbmcgT0JKL01UTCBmaWxlc1xyXG4gKi9cclxuZXhwb3J0IHR5cGUgT0JKTG9hZGluZ09wdGlvbnMgPSB7XHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgaWYgVVZzIGFyZSBvcHRpbWl6ZWQgYnkgZGVmYXVsdCBkdXJpbmcgbG9hZC5cclxuICAgICAqL1xyXG4gICAgb3B0aW1pemVXaXRoVVY6IGJvb2xlYW47XHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgY3VzdG9tIHNjYWxpbmcgb2YgVVYgY29vcmRpbmF0ZXMgb2YgbG9hZGVkIG1lc2hlcy5cclxuICAgICAqL1xyXG4gICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxyXG4gICAgVVZTY2FsaW5nOiBWZWN0b3IyO1xyXG4gICAgLyoqXHJcbiAgICAgKiBJbnZlcnQgbW9kZWwgb24geS1heGlzIChkb2VzIGEgbW9kZWwgc2NhbGluZyBpbnZlcnNpb24pXHJcbiAgICAgKi9cclxuICAgIGludmVydFk6IGJvb2xlYW47XHJcbiAgICAvKipcclxuICAgICAqIEludmVydCBZLUF4aXMgb2YgcmVmZXJlbmNlZCB0ZXh0dXJlcyBvbiBsb2FkXHJcbiAgICAgKi9cclxuICAgIGludmVydFRleHR1cmVZOiBib29sZWFuO1xyXG4gICAgLyoqXHJcbiAgICAgKiBJbmNsdWRlIGluIG1lc2hlcyB0aGUgdmVydGV4IGNvbG9ycyBhdmFpbGFibGUgaW4gc29tZSBPQkogZmlsZXMuICBUaGlzIGlzIG5vdCBwYXJ0IG9mIE9CSiBzdGFuZGFyZC5cclxuICAgICAqL1xyXG4gICAgaW1wb3J0VmVydGV4Q29sb3JzOiBib29sZWFuO1xyXG4gICAgLyoqXHJcbiAgICAgKiBDb21wdXRlIHRoZSBub3JtYWxzIGZvciB0aGUgbW9kZWwsIGV2ZW4gaWYgbm9ybWFscyBhcmUgcHJlc2VudCBpbiB0aGUgZmlsZS5cclxuICAgICAqL1xyXG4gICAgY29tcHV0ZU5vcm1hbHM6IGJvb2xlYW47XHJcbiAgICAvKipcclxuICAgICAqIE9wdGltaXplIHRoZSBub3JtYWxzIGZvciB0aGUgbW9kZWwuIExpZ2h0aW5nIGNhbiBiZSB1bmV2ZW4gaWYgeW91IHVzZSBPcHRpbWl6ZVdpdGhVViA9IHRydWUgYmVjYXVzZSBuZXcgdmVydGljZXMgY2FuIGJlIGNyZWF0ZWQgZm9yIHRoZSBzYW1lIGxvY2F0aW9uIGlmIHRoZXkgcGVydGFpbiB0byBkaWZmZXJlbnQgZmFjZXMuXHJcbiAgICAgKiBVc2luZyBPcHRpbWl6ZWhOb3JtYWxzID0gdHJ1ZSB3aWxsIGhlbHAgc21vb3RoaW5nIHRoZSBsaWdodGluZyBieSBhdmVyYWdpbmcgdGhlIG5vcm1hbHMgb2YgdGhvc2UgdmVydGljZXMuXHJcbiAgICAgKi9cclxuICAgIG9wdGltaXplTm9ybWFsczogYm9vbGVhbjtcclxuICAgIC8qKlxyXG4gICAgICogU2tpcCBsb2FkaW5nIHRoZSBtYXRlcmlhbHMgZXZlbiBpZiBkZWZpbmVkIGluIHRoZSBPQkogZmlsZSAobWF0ZXJpYWxzIGFyZSBpZ25vcmVkKS5cclxuICAgICAqL1xyXG4gICAgc2tpcE1hdGVyaWFsczogYm9vbGVhbjtcclxuICAgIC8qKlxyXG4gICAgICogV2hlbiBhIG1hdGVyaWFsIGZhaWxzIHRvIGxvYWQgT0JKIGxvYWRlciB3aWxsIHNpbGVudGx5IGZhaWwgYW5kIG9uU3VjY2VzcygpIGNhbGxiYWNrIHdpbGwgYmUgdHJpZ2dlcmVkLlxyXG4gICAgICovXHJcbiAgICBtYXRlcmlhbExvYWRpbmdGYWlsc1NpbGVudGx5OiBib29sZWFuO1xyXG59O1xyXG4iLCJpbXBvcnQgdHlwZSB7IEFzc2V0Q29udGFpbmVyIH0gZnJvbSBcImNvcmUvYXNzZXRDb250YWluZXJcIjtcclxuaW1wb3J0IHsgVmVydGV4QnVmZmVyIH0gZnJvbSBcImNvcmUvQnVmZmVycy9idWZmZXJcIjtcclxuaW1wb3J0IHR5cGUgeyBNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9tYXRlcmlhbFwiO1xyXG5pbXBvcnQgeyBTdGFuZGFyZE1hdGVyaWFsIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL3N0YW5kYXJkTWF0ZXJpYWxcIjtcclxuaW1wb3J0IHsgQ29sb3IzLCBDb2xvcjQgfSBmcm9tIFwiY29yZS9NYXRocy9tYXRoLmNvbG9yXCI7XHJcbmltcG9ydCB7IFZlY3RvcjIsIFZlY3RvcjMgfSBmcm9tIFwiY29yZS9NYXRocy9tYXRoLnZlY3RvclwiO1xyXG5pbXBvcnQgdHlwZSB7IEFic3RyYWN0TWVzaCB9IGZyb20gXCJjb3JlL01lc2hlcy9hYnN0cmFjdE1lc2hcIjtcclxuaW1wb3J0IHsgR2VvbWV0cnkgfSBmcm9tIFwiY29yZS9NZXNoZXMvZ2VvbWV0cnlcIjtcclxuaW1wb3J0IHsgTWVzaCB9IGZyb20gXCJjb3JlL01lc2hlcy9tZXNoXCI7XHJcbmltcG9ydCB7IFZlcnRleERhdGEgfSBmcm9tIFwiY29yZS9NZXNoZXMvbWVzaC52ZXJ0ZXhEYXRhXCI7XHJcbmltcG9ydCB0eXBlIHsgU2NlbmUgfSBmcm9tIFwiY29yZS9zY2VuZVwiO1xyXG5pbXBvcnQgdHlwZSB7IEZsb2F0QXJyYXksIEluZGljZXNBcnJheSwgTnVsbGFibGUgfSBmcm9tIFwiY29yZS90eXBlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IE9CSkxvYWRpbmdPcHRpb25zIH0gZnJvbSBcIi4vb2JqTG9hZGluZ09wdGlvbnNcIjtcclxuXHJcbnR5cGUgTWVzaE9iamVjdCA9IHtcclxuICAgIG5hbWU6IHN0cmluZztcclxuICAgIGluZGljZXM/OiBBcnJheTxudW1iZXI+O1xyXG4gICAgcG9zaXRpb25zPzogQXJyYXk8bnVtYmVyPjtcclxuICAgIG5vcm1hbHM/OiBBcnJheTxudW1iZXI+O1xyXG4gICAgY29sb3JzPzogQXJyYXk8bnVtYmVyPjtcclxuICAgIHV2cz86IEFycmF5PG51bWJlcj47XHJcbiAgICBtYXRlcmlhbE5hbWU6IHN0cmluZztcclxuICAgIGRpcmVjdE1hdGVyaWFsPzogTnVsbGFibGU8TWF0ZXJpYWw+O1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIENsYXNzIHVzZWQgdG8gbG9hZCBtZXNoIGRhdGEgZnJvbSBPQkogY29udGVudFxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIFNvbGlkUGFyc2VyIHtcclxuICAgIC8vIERlc2NyaXB0b3JcclxuICAgIC8qKiBPYmplY3QgZGVzY3JpcHRvciAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBPYmplY3REZXNjcmlwdG9yID0gL15vLztcclxuICAgIC8qKiBHcm91cCBkZXNjcmlwdG9yICovXHJcbiAgICBwdWJsaWMgc3RhdGljIEdyb3VwRGVzY3JpcHRvciA9IC9eZy87XHJcbiAgICAvKiogTWF0ZXJpYWwgbGliIGRlc2NyaXB0b3IgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgTXRsTGliR3JvdXBEZXNjcmlwdG9yID0gL15tdGxsaWIgLztcclxuICAgIC8qKiBVc2UgYSBtYXRlcmlhbCBkZXNjcmlwdG9yICovXHJcbiAgICBwdWJsaWMgc3RhdGljIFVzZU10bERlc2NyaXB0b3IgPSAvXnVzZW10bCAvO1xyXG4gICAgLyoqIFNtb290aCBkZXNjcmlwdG9yICovXHJcbiAgICBwdWJsaWMgc3RhdGljIFNtb290aERlc2NyaXB0b3IgPSAvXnMgLztcclxuXHJcbiAgICAvLyBQYXR0ZXJuc1xyXG4gICAgLyoqIFBhdHRlcm4gdXNlZCB0byBkZXRlY3QgYSB2ZXJ0ZXggKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgVmVydGV4UGF0dGVybiA9IC9edihcXHMrW1xcZHwufCt8XFwtfGV8RV0rKXszLDd9LztcclxuICAgIC8qKiBQYXR0ZXJuIHVzZWQgdG8gZGV0ZWN0IGEgbm9ybWFsICovXHJcbiAgICBwdWJsaWMgc3RhdGljIE5vcm1hbFBhdHRlcm4gPSAvXnZuKFxccytbXFxkfC58K3xcXC18ZXxFXSspKCArW1xcZHwufCt8XFwtfGV8RV0rKSggK1tcXGR8LnwrfFxcLXxlfEVdKykvO1xyXG4gICAgLyoqIFBhdHRlcm4gdXNlZCB0byBkZXRlY3QgYSBVViBzZXQgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgVVZQYXR0ZXJuID0gL152dChcXHMrW1xcZHwufCt8XFwtfGV8RV0rKSggK1tcXGR8LnwrfFxcLXxlfEVdKykvO1xyXG4gICAgLyoqIFBhdHRlcm4gdXNlZCB0byBkZXRlY3QgYSBmaXJzdCBraW5kIG9mIGZhY2UgKGYgdmVydGV4IHZlcnRleCB2ZXJ0ZXgpICovXHJcbiAgICBwdWJsaWMgc3RhdGljIEZhY2VQYXR0ZXJuMSA9IC9eZlxccysoKFtcXGRdezEsfVtcXHNdPyl7Myx9KSsvO1xyXG4gICAgLyoqIFBhdHRlcm4gdXNlZCB0byBkZXRlY3QgYSBzZWNvbmQga2luZCBvZiBmYWNlIChmIHZlcnRleC91dnMgdmVydGV4L3V2cyB2ZXJ0ZXgvdXZzKSAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBGYWNlUGF0dGVybjIgPSAvXmZcXHMrKCgoW1xcZF17MSx9XFwvW1xcZF17MSx9W1xcc10/KXszLH0pKykvO1xyXG4gICAgLyoqIFBhdHRlcm4gdXNlZCB0byBkZXRlY3QgYSB0aGlyZCBraW5kIG9mIGZhY2UgKGYgdmVydGV4L3V2cy9ub3JtYWwgdmVydGV4L3V2cy9ub3JtYWwgdmVydGV4L3V2cy9ub3JtYWwpICovXHJcbiAgICBwdWJsaWMgc3RhdGljIEZhY2VQYXR0ZXJuMyA9IC9eZlxccysoKChbXFxkXXsxLH1cXC9bXFxkXXsxLH1cXC9bXFxkXXsxLH1bXFxzXT8pezMsfSkrKS87XHJcbiAgICAvKiogUGF0dGVybiB1c2VkIHRvIGRldGVjdCBhIGZvdXJ0aCBraW5kIG9mIGZhY2UgKGYgdmVydGV4Ly9ub3JtYWwgdmVydGV4Ly9ub3JtYWwgdmVydGV4Ly9ub3JtYWwpKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgRmFjZVBhdHRlcm40ID0gL15mXFxzKygoKFtcXGRdezEsfVxcL1xcL1tcXGRdezEsfVtcXHNdPyl7Myx9KSspLztcclxuICAgIC8qKiBQYXR0ZXJuIHVzZWQgdG8gZGV0ZWN0IGEgZmlmdGgga2luZCBvZiBmYWNlIChmIC12ZXJ0ZXgvLXV2cy8tbm9ybWFsIC12ZXJ0ZXgvLXV2cy8tbm9ybWFsIC12ZXJ0ZXgvLXV2cy8tbm9ybWFsKSAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBGYWNlUGF0dGVybjUgPSAvXmZcXHMrKCgoLVtcXGRdezEsfVxcLy1bXFxkXXsxLH1cXC8tW1xcZF17MSx9W1xcc10/KXszLH0pKykvO1xyXG4gICAgLyoqIFBhdHRlcm4gdXNlZCB0byBkZXRlY3QgYSBsaW5lKGwgdmVydGV4IHZlcnRleCkgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgTGluZVBhdHRlcm4xID0gL15sXFxzKygoW1xcZF17MSx9W1xcc10/KXsyLH0pKy87XHJcbiAgICAvKiogUGF0dGVybiB1c2VkIHRvIGRldGVjdCBhIHNlY29uZCBraW5kIG9mIGxpbmUgKGwgdmVydGV4L3V2cyB2ZXJ0ZXgvdXZzKSAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBMaW5lUGF0dGVybjIgPSAvXmxcXHMrKCgoW1xcZF17MSx9XFwvW1xcZF17MSx9W1xcc10/KXsyLH0pKykvO1xyXG4gICAgLyoqIFBhdHRlcm4gdXNlZCB0byBkZXRlY3QgYSB0aGlyZCBraW5kIG9mIGxpbmUgKGwgdmVydGV4L3V2cy9ub3JtYWwgdmVydGV4L3V2cy9ub3JtYWwpICovXHJcbiAgICBwdWJsaWMgc3RhdGljIExpbmVQYXR0ZXJuMyA9IC9ebFxccysoKChbXFxkXXsxLH1cXC9bXFxkXXsxLH1cXC9bXFxkXXsxLH1bXFxzXT8pezIsfSkrKS87XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZGluZ09wdGlvbnM6IE9CSkxvYWRpbmdPcHRpb25zO1xyXG4gICAgcHJpdmF0ZSBfcG9zaXRpb25zOiBBcnJheTxWZWN0b3IzPiA9IFtdOyAvL3ZhbHVlcyBmb3IgdGhlIHBvc2l0aW9ucyBvZiB2ZXJ0aWNlc1xyXG4gICAgcHJpdmF0ZSBfbm9ybWFsczogQXJyYXk8VmVjdG9yMz4gPSBbXTsgLy9WYWx1ZXMgZm9yIHRoZSBub3JtYWxzXHJcbiAgICBwcml2YXRlIF91dnM6IEFycmF5PFZlY3RvcjI+ID0gW107IC8vVmFsdWVzIGZvciB0aGUgdGV4dHVyZXNcclxuICAgIHByaXZhdGUgX2NvbG9yczogQXJyYXk8Q29sb3I0PiA9IFtdO1xyXG4gICAgcHJpdmF0ZSBfbWVzaGVzRnJvbU9iajogQXJyYXk8TWVzaE9iamVjdD4gPSBbXTsgLy9bbWVzaF0gQ29udGFpbnMgYWxsIHRoZSBvYmogbWVzaGVzXHJcbiAgICBwcml2YXRlIF9oYW5kbGVkTWVzaDogTWVzaE9iamVjdDsgLy9UaGUgY3VycmVudCBtZXNoIG9mIG1lc2hlcyBhcnJheVxyXG4gICAgcHJpdmF0ZSBfaW5kaWNlc0ZvckJhYnlsb246IEFycmF5PG51bWJlcj4gPSBbXTsgLy9UaGUgbGlzdCBvZiBpbmRpY2VzIGZvciBWZXJ0ZXhEYXRhXHJcbiAgICBwcml2YXRlIF93cmFwcGVkUG9zaXRpb25Gb3JCYWJ5bG9uOiBBcnJheTxWZWN0b3IzPiA9IFtdOyAvL1RoZSBsaXN0IG9mIHBvc2l0aW9uIGluIHZlY3RvcnNcclxuICAgIHByaXZhdGUgX3dyYXBwZWRVdnNGb3JCYWJ5bG9uOiBBcnJheTxWZWN0b3IyPiA9IFtdOyAvL0FycmF5IHdpdGggYWxsIHZhbHVlIG9mIHV2cyB0byBtYXRjaCB3aXRoIHRoZSBpbmRpY2VzXHJcbiAgICBwcml2YXRlIF93cmFwcGVkQ29sb3JzRm9yQmFieWxvbjogQXJyYXk8Q29sb3I0PiA9IFtdOyAvLyBBcnJheSB3aXRoIGFsbCBjb2xvciB2YWx1ZXMgdG8gbWF0Y2ggd2l0aCB0aGUgaW5kaWNlc1xyXG4gICAgcHJpdmF0ZSBfd3JhcHBlZE5vcm1hbHNGb3JCYWJ5bG9uOiBBcnJheTxWZWN0b3IzPiA9IFtdOyAvL0FycmF5IHdpdGggYWxsIHZhbHVlIG9mIG5vcm1hbHMgdG8gbWF0Y2ggd2l0aCB0aGUgaW5kaWNlc1xyXG4gICAgcHJpdmF0ZSBfdHVwbGVQb3NOb3JtOiBBcnJheTx7IG5vcm1hbHM6IEFycmF5PG51bWJlcj47IGlkeDogQXJyYXk8bnVtYmVyPjsgdXY6IEFycmF5PG51bWJlcj4gfT4gPSBbXTsgLy9DcmVhdGUgYSB0dXBsZSB3aXRoIGluZGljZSBvZiBQb3NpdGlvbiwgTm9ybWFsLCBVViAgW3Bvcywgbm9ybSwgdXZzXVxyXG4gICAgcHJpdmF0ZSBfY3VyUG9zaXRpb25JbkluZGljZXMgPSAwO1xyXG4gICAgcHJpdmF0ZSBfaGFzTWVzaGVzOiBCb29sZWFuID0gZmFsc2U7IC8vTWVzaGVzIGFyZSBkZWZpbmVkIGluIHRoZSBmaWxlXHJcbiAgICBwcml2YXRlIF91bndyYXBwZWRQb3NpdGlvbnNGb3JCYWJ5bG9uOiBBcnJheTxudW1iZXI+ID0gW107IC8vVmFsdWUgb2YgcG9zaXRpb25Gb3JCYWJ5bG9uIHcvbyBWZWN0b3IzKCkgW3gseSx6XVxyXG4gICAgcHJpdmF0ZSBfdW53cmFwcGVkQ29sb3JzRm9yQmFieWxvbjogQXJyYXk8bnVtYmVyPiA9IFtdOyAvLyBWYWx1ZSBvZiBjb2xvckZvckJhYnlsb24gdy9vIENvbG9yNCgpIFtyLGcsYixhXVxyXG4gICAgcHJpdmF0ZSBfdW53cmFwcGVkTm9ybWFsc0ZvckJhYnlsb246IEFycmF5PG51bWJlcj4gPSBbXTsgLy9WYWx1ZSBvZiBub3JtYWxzRm9yQmFieWxvbiB3L28gVmVjdG9yMygpICBbeCx5LHpdXHJcbiAgICBwcml2YXRlIF91bndyYXBwZWRVVkZvckJhYnlsb246IEFycmF5PG51bWJlcj4gPSBbXTsgLy9WYWx1ZSBvZiB1dnNGb3JCYWJ5bG9uIHcvbyBWZWN0b3IzKCkgICAgICBbeCx5LHpdXHJcbiAgICBwcml2YXRlIF90cmlhbmdsZXM6IEFycmF5PHN0cmluZz4gPSBbXTsgLy9JbmRpY2VzIGZyb20gbmV3IHRyaWFuZ2xlcyBjb21pbmcgZnJvbSBwb2x5Z29uc1xyXG4gICAgcHJpdmF0ZSBfbWF0ZXJpYWxOYW1lRnJvbU9iajogc3RyaW5nID0gXCJcIjsgLy9UaGUgbmFtZSBvZiB0aGUgY3VycmVudCBtYXRlcmlhbFxyXG4gICAgcHJpdmF0ZSBfb2JqTWVzaE5hbWU6IHN0cmluZyA9IFwiXCI7IC8vVGhlIG5hbWUgb2YgdGhlIGN1cnJlbnQgb2JqIG1lc2hcclxuICAgIHByaXZhdGUgX2luY3JlbWVudDogbnVtYmVyID0gMTsgLy9JZCBmb3IgbWVzaGVzIGNyZWF0ZWQgYnkgdGhlIG11bHRpbWF0ZXJpYWxcclxuICAgIHByaXZhdGUgX2lzRmlyc3RNYXRlcmlhbDogYm9vbGVhbiA9IHRydWU7XHJcbiAgICBwcml2YXRlIF9ncmF5Q29sb3IgPSBuZXcgQ29sb3I0KDAuNSwgMC41LCAwLjUsIDEpO1xyXG4gICAgcHJpdmF0ZSBfbWF0ZXJpYWxUb1VzZTogc3RyaW5nW107XHJcbiAgICBwcml2YXRlIF9iYWJ5bG9uTWVzaGVzQXJyYXk6IEFycmF5PE1lc2g+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyBhIG5ldyBTb2xpZFBhcnNlclxyXG4gICAgICogQHBhcmFtIG1hdGVyaWFsVG9Vc2UgZGVmaW5lcyB0aGUgYXJyYXkgdG8gZmlsbCB3aXRoIHRoZSBsaXN0IG9mIG1hdGVyaWFscyB0byB1c2UgKGl0IHdpbGwgYmUgZmlsbGVkIGJ5IHRoZSBwYXJzZSBmdW5jdGlvbilcclxuICAgICAqIEBwYXJhbSBiYWJ5bG9uTWVzaGVzQXJyYXkgZGVmaW5lcyB0aGUgYXJyYXkgdG8gZmlsbCB3aXRoIHRoZSBsaXN0IG9mIGxvYWRlZCBtZXNoZXMgKGl0IHdpbGwgYmUgZmlsbGVkIGJ5IHRoZSBwYXJzZSBmdW5jdGlvbilcclxuICAgICAqIEBwYXJhbSBsb2FkaW5nT3B0aW9ucyBkZWZpbmVzIHRoZSBsb2FkaW5nIG9wdGlvbnMgdG8gdXNlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcihtYXRlcmlhbFRvVXNlOiBzdHJpbmdbXSwgYmFieWxvbk1lc2hlc0FycmF5OiBBcnJheTxNZXNoPiwgbG9hZGluZ09wdGlvbnM6IE9CSkxvYWRpbmdPcHRpb25zKSB7XHJcbiAgICAgICAgdGhpcy5fbWF0ZXJpYWxUb1VzZSA9IG1hdGVyaWFsVG9Vc2U7XHJcbiAgICAgICAgdGhpcy5fYmFieWxvbk1lc2hlc0FycmF5ID0gYmFieWxvbk1lc2hlc0FycmF5O1xyXG4gICAgICAgIHRoaXMuX2xvYWRpbmdPcHRpb25zID0gbG9hZGluZ09wdGlvbnM7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTZWFyY2ggZm9yIG9iaiBpbiB0aGUgZ2l2ZW4gYXJyYXkuXHJcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCB0byBjaGVjayBpZiBhIGNvdXBsZSBvZiBkYXRhIGFscmVhZHkgZXhpc3RzIGluIGFuIGFycmF5LlxyXG4gICAgICpcclxuICAgICAqIElmIGZvdW5kLCByZXR1cm5zIHRoZSBpbmRleCBvZiB0aGUgZm91bmRlZCB0dXBsZSBpbmRleC4gUmV0dXJucyAtMSBpZiBub3QgZm91bmRcclxuICAgICAqIEBwYXJhbSBhcnIgQXJyYXk8eyBub3JtYWxzOiBBcnJheTxudW1iZXI+LCBpZHg6IEFycmF5PG51bWJlcj4gfT5cclxuICAgICAqIEBwYXJhbSBvYmogQXJyYXk8bnVtYmVyPlxyXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgX2lzSW5BcnJheShhcnI6IEFycmF5PHsgbm9ybWFsczogQXJyYXk8bnVtYmVyPjsgaWR4OiBBcnJheTxudW1iZXI+IH0+LCBvYmo6IEFycmF5PG51bWJlcj4pIHtcclxuICAgICAgICBpZiAoIWFycltvYmpbMF1dKSB7XHJcbiAgICAgICAgICAgIGFycltvYmpbMF1dID0geyBub3JtYWxzOiBbXSwgaWR4OiBbXSB9O1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCBpZHggPSBhcnJbb2JqWzBdXS5ub3JtYWxzLmluZGV4T2Yob2JqWzFdKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIGlkeCA9PT0gLTEgPyAtMSA6IGFycltvYmpbMF1dLmlkeFtpZHhdO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2lzSW5BcnJheVVWKGFycjogQXJyYXk8eyBub3JtYWxzOiBBcnJheTxudW1iZXI+OyBpZHg6IEFycmF5PG51bWJlcj47IHV2OiBBcnJheTxudW1iZXI+IH0+LCBvYmo6IEFycmF5PG51bWJlcj4pIHtcclxuICAgICAgICBpZiAoIWFycltvYmpbMF1dKSB7XHJcbiAgICAgICAgICAgIGFycltvYmpbMF1dID0geyBub3JtYWxzOiBbXSwgaWR4OiBbXSwgdXY6IFtdIH07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IGlkeCA9IGFycltvYmpbMF1dLm5vcm1hbHMuaW5kZXhPZihvYmpbMV0pO1xyXG5cclxuICAgICAgICBpZiAoaWR4ICE9IDEgJiYgb2JqWzJdID09PSBhcnJbb2JqWzBdXS51dltpZHhdKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBhcnJbb2JqWzBdXS5pZHhbaWR4XTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIC0xO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhpcyBmdW5jdGlvbiBzZXQgdGhlIGRhdGEgZm9yIGVhY2ggdHJpYW5nbGUuXHJcbiAgICAgKiBEYXRhIGFyZSBwb3NpdGlvbiwgbm9ybWFscyBhbmQgdXZzXHJcbiAgICAgKiBJZiBhIHR1cGxlIG9mIChwb3NpdGlvbiwgbm9ybWFsKSBpcyBub3Qgc2V0LCBhZGQgdGhlIGRhdGEgaW50byB0aGUgY29ycmVzcG9uZGluZyBhcnJheVxyXG4gICAgICogSWYgdGhlIHR1cGxlIGFscmVhZHkgZXhpc3QsIGFkZCBvbmx5IHRoZWlyIGluZGljZVxyXG4gICAgICpcclxuICAgICAqIEBwYXJhbSBpbmRpY2VQb3NpdGlvbkZyb21PYmogSW50ZWdlciBUaGUgaW5kZXggaW4gcG9zaXRpb25zIGFycmF5XHJcbiAgICAgKiBAcGFyYW0gaW5kaWNlVXZzRnJvbU9iaiBJbnRlZ2VyIFRoZSBpbmRleCBpbiB1dnMgYXJyYXlcclxuICAgICAqIEBwYXJhbSBpbmRpY2VOb3JtYWxGcm9tT2JqIEludGVnZXIgVGhlIGluZGV4IGluIG5vcm1hbHMgYXJyYXlcclxuICAgICAqIEBwYXJhbSBwb3NpdGlvblZlY3RvckZyb21PQkogVmVjdG9yMyBUaGUgdmFsdWUgb2YgcG9zaXRpb24gYXQgaW5kZXggb2JqSW5kaWNlXHJcbiAgICAgKiBAcGFyYW0gdGV4dHVyZVZlY3RvckZyb21PQkogVmVjdG9yMyBUaGUgdmFsdWUgb2YgdXZzXHJcbiAgICAgKiBAcGFyYW0gbm9ybWFsc1ZlY3RvckZyb21PQkogVmVjdG9yMyBUaGUgdmFsdWUgb2Ygbm9ybWFscyBhdCBpbmRleCBvYmpOb3JtYWxlXHJcbiAgICAgKiBAcGFyYW0gcG9zaXRpb25Db2xvcnNGcm9tT0JKXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgX3NldERhdGEoXHJcbiAgICAgICAgaW5kaWNlUG9zaXRpb25Gcm9tT2JqOiBudW1iZXIsXHJcbiAgICAgICAgaW5kaWNlVXZzRnJvbU9iajogbnVtYmVyLFxyXG4gICAgICAgIGluZGljZU5vcm1hbEZyb21PYmo6IG51bWJlcixcclxuICAgICAgICBwb3NpdGlvblZlY3RvckZyb21PQko6IFZlY3RvcjMsXHJcbiAgICAgICAgdGV4dHVyZVZlY3RvckZyb21PQko6IFZlY3RvcjIsXHJcbiAgICAgICAgbm9ybWFsc1ZlY3RvckZyb21PQko6IFZlY3RvcjMsXHJcbiAgICAgICAgcG9zaXRpb25Db2xvcnNGcm9tT0JKPzogQ29sb3I0XHJcbiAgICApIHtcclxuICAgICAgICAvL0NoZWNrIGlmIHRoaXMgdHVwbGUgYWxyZWFkeSBleGlzdHMgaW4gdGhlIGxpc3Qgb2YgdHVwbGVzXHJcbiAgICAgICAgbGV0IF9pbmRleDogbnVtYmVyO1xyXG4gICAgICAgIGlmICh0aGlzLl9sb2FkaW5nT3B0aW9ucy5vcHRpbWl6ZVdpdGhVVikge1xyXG4gICAgICAgICAgICBfaW5kZXggPSB0aGlzLl9pc0luQXJyYXlVVih0aGlzLl90dXBsZVBvc05vcm0sIFtpbmRpY2VQb3NpdGlvbkZyb21PYmosIGluZGljZU5vcm1hbEZyb21PYmosIGluZGljZVV2c0Zyb21PYmpdKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBfaW5kZXggPSB0aGlzLl9pc0luQXJyYXkodGhpcy5fdHVwbGVQb3NOb3JtLCBbaW5kaWNlUG9zaXRpb25Gcm9tT2JqLCBpbmRpY2VOb3JtYWxGcm9tT2JqXSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvL0lmIGl0IG5vdCBleGlzdHNcclxuICAgICAgICBpZiAoX2luZGV4ID09PSAtMSkge1xyXG4gICAgICAgICAgICAvL0FkZCBhbiBuZXcgaW5kaWNlLlxyXG4gICAgICAgICAgICAvL1RoZSBhcnJheSBvZiBpbmRpY2VzIGlzIG9ubHkgYW4gYXJyYXkgd2l0aCBoaXMgbGVuZ3RoIGVxdWFsIHRvIHRoZSBudW1iZXIgb2YgdHJpYW5nbGVzIC0gMS5cclxuICAgICAgICAgICAgLy9XZSBhZGQgdmVydGljZXMgZGF0YSBpbiB0aGlzIG9yZGVyXHJcbiAgICAgICAgICAgIHRoaXMuX2luZGljZXNGb3JCYWJ5bG9uLnB1c2godGhpcy5fd3JhcHBlZFBvc2l0aW9uRm9yQmFieWxvbi5sZW5ndGgpO1xyXG4gICAgICAgICAgICAvL1B1c2ggdGhlIHBvc2l0aW9uIG9mIHZlcnRpY2UgZm9yIEJhYnlsb25cclxuICAgICAgICAgICAgLy9FYWNoIGVsZW1lbnQgaXMgYSBWZWN0b3IzKHgseSx6KVxyXG4gICAgICAgICAgICB0aGlzLl93cmFwcGVkUG9zaXRpb25Gb3JCYWJ5bG9uLnB1c2gocG9zaXRpb25WZWN0b3JGcm9tT0JKKTtcclxuICAgICAgICAgICAgLy9QdXNoIHRoZSB1dnMgZm9yIEJhYnlsb25cclxuICAgICAgICAgICAgLy9FYWNoIGVsZW1lbnQgaXMgYSBWZWN0b3IzKHUsdilcclxuICAgICAgICAgICAgdGhpcy5fd3JhcHBlZFV2c0ZvckJhYnlsb24ucHVzaCh0ZXh0dXJlVmVjdG9yRnJvbU9CSik7XHJcbiAgICAgICAgICAgIC8vUHVzaCB0aGUgbm9ybWFscyBmb3IgQmFieWxvblxyXG4gICAgICAgICAgICAvL0VhY2ggZWxlbWVudCBpcyBhIFZlY3RvcjMoeCx5LHopXHJcbiAgICAgICAgICAgIHRoaXMuX3dyYXBwZWROb3JtYWxzRm9yQmFieWxvbi5wdXNoKG5vcm1hbHNWZWN0b3JGcm9tT0JKKTtcclxuXHJcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbkNvbG9yc0Zyb21PQkogIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgICAgLy9QdXNoIHRoZSBjb2xvcnMgZm9yIEJhYnlsb25cclxuICAgICAgICAgICAgICAgIC8vRWFjaCBlbGVtZW50IGlzIGEgQkFCWUxPTi5Db2xvcjQocixnLGIsYSlcclxuICAgICAgICAgICAgICAgIHRoaXMuX3dyYXBwZWRDb2xvcnNGb3JCYWJ5bG9uLnB1c2gocG9zaXRpb25Db2xvcnNGcm9tT0JKKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy9BZGQgdGhlIHR1cGxlIGluIHRoZSBjb21wYXJpc29uIGxpc3RcclxuICAgICAgICAgICAgdGhpcy5fdHVwbGVQb3NOb3JtW2luZGljZVBvc2l0aW9uRnJvbU9ial0ubm9ybWFscy5wdXNoKGluZGljZU5vcm1hbEZyb21PYmopO1xyXG4gICAgICAgICAgICB0aGlzLl90dXBsZVBvc05vcm1baW5kaWNlUG9zaXRpb25Gcm9tT2JqXS5pZHgucHVzaCh0aGlzLl9jdXJQb3NpdGlvbkluSW5kaWNlcysrKTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuX2xvYWRpbmdPcHRpb25zLm9wdGltaXplV2l0aFVWKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl90dXBsZVBvc05vcm1baW5kaWNlUG9zaXRpb25Gcm9tT2JqXS51di5wdXNoKGluZGljZVV2c0Zyb21PYmopO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgLy9UaGUgdHVwbGUgYWxyZWFkeSBleGlzdHNcclxuICAgICAgICAgICAgLy9BZGQgdGhlIGluZGV4IG9mIHRoZSBhbHJlYWR5IGV4aXN0aW5nIHR1cGxlXHJcbiAgICAgICAgICAgIC8vQXQgdGhpcyBpbmRleCB3ZSBjYW4gZ2V0IHRoZSB2YWx1ZSBvZiBwb3NpdGlvbiwgbm9ybWFsLCBjb2xvciBhbmQgdXZzIG9mIHZlcnRleFxyXG4gICAgICAgICAgICB0aGlzLl9pbmRpY2VzRm9yQmFieWxvbi5wdXNoKF9pbmRleCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVHJhbnNmb3JtIFZlY3RvcigpIGFuZCBCQUJZTE9OLkNvbG9yKCkgb2JqZWN0cyBpbnRvIG51bWJlcnMgaW4gYW4gYXJyYXlcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBfdW53cmFwRGF0YSgpIHtcclxuICAgICAgICAvL0V2ZXJ5IGFycmF5IGhhcyB0aGUgc2FtZSBsZW5ndGhcclxuICAgICAgICBmb3IgKGxldCBsID0gMDsgbCA8IHRoaXMuX3dyYXBwZWRQb3NpdGlvbkZvckJhYnlsb24ubGVuZ3RoOyBsKyspIHtcclxuICAgICAgICAgICAgLy9QdXNoIHRoZSB4LCB5LCB6IHZhbHVlcyBvZiBlYWNoIGVsZW1lbnQgaW4gdGhlIHVud3JhcHBlZCBhcnJheVxyXG4gICAgICAgICAgICB0aGlzLl91bndyYXBwZWRQb3NpdGlvbnNGb3JCYWJ5bG9uLnB1c2godGhpcy5fd3JhcHBlZFBvc2l0aW9uRm9yQmFieWxvbltsXS54LCB0aGlzLl93cmFwcGVkUG9zaXRpb25Gb3JCYWJ5bG9uW2xdLnksIHRoaXMuX3dyYXBwZWRQb3NpdGlvbkZvckJhYnlsb25bbF0ueik7XHJcbiAgICAgICAgICAgIHRoaXMuX3Vud3JhcHBlZE5vcm1hbHNGb3JCYWJ5bG9uLnB1c2godGhpcy5fd3JhcHBlZE5vcm1hbHNGb3JCYWJ5bG9uW2xdLngsIHRoaXMuX3dyYXBwZWROb3JtYWxzRm9yQmFieWxvbltsXS55LCB0aGlzLl93cmFwcGVkTm9ybWFsc0ZvckJhYnlsb25bbF0ueik7XHJcbiAgICAgICAgICAgIHRoaXMuX3Vud3JhcHBlZFVWRm9yQmFieWxvbi5wdXNoKHRoaXMuX3dyYXBwZWRVdnNGb3JCYWJ5bG9uW2xdLngsIHRoaXMuX3dyYXBwZWRVdnNGb3JCYWJ5bG9uW2xdLnkpOyAvL3ogaXMgYW4gb3B0aW9uYWwgdmFsdWUgbm90IHN1cHBvcnRlZCBieSBCQUJZTE9OXHJcbiAgICAgICAgICAgIGlmICh0aGlzLl9sb2FkaW5nT3B0aW9ucy5pbXBvcnRWZXJ0ZXhDb2xvcnMpIHtcclxuICAgICAgICAgICAgICAgIC8vUHVzaCB0aGUgciwgZywgYiwgYSB2YWx1ZXMgb2YgZWFjaCBlbGVtZW50IGluIHRoZSB1bndyYXBwZWQgYXJyYXlcclxuICAgICAgICAgICAgICAgIHRoaXMuX3Vud3JhcHBlZENvbG9yc0ZvckJhYnlsb24ucHVzaChcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl93cmFwcGVkQ29sb3JzRm9yQmFieWxvbltsXS5yLFxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3dyYXBwZWRDb2xvcnNGb3JCYWJ5bG9uW2xdLmcsXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fd3JhcHBlZENvbG9yc0ZvckJhYnlsb25bbF0uYixcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl93cmFwcGVkQ29sb3JzRm9yQmFieWxvbltsXS5hXHJcbiAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIFJlc2V0IGFycmF5cyBmb3IgdGhlIG5leHQgbmV3IG1lc2hlc1xyXG4gICAgICAgIHRoaXMuX3dyYXBwZWRQb3NpdGlvbkZvckJhYnlsb24ubGVuZ3RoID0gMDtcclxuICAgICAgICB0aGlzLl93cmFwcGVkTm9ybWFsc0ZvckJhYnlsb24ubGVuZ3RoID0gMDtcclxuICAgICAgICB0aGlzLl93cmFwcGVkVXZzRm9yQmFieWxvbi5sZW5ndGggPSAwO1xyXG4gICAgICAgIHRoaXMuX3dyYXBwZWRDb2xvcnNGb3JCYWJ5bG9uLmxlbmd0aCA9IDA7XHJcbiAgICAgICAgdGhpcy5fdHVwbGVQb3NOb3JtLmxlbmd0aCA9IDA7XHJcbiAgICAgICAgdGhpcy5fY3VyUG9zaXRpb25JbkluZGljZXMgPSAwO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlIHRyaWFuZ2xlcyBmcm9tIHBvbHlnb25zXHJcbiAgICAgKiBJdCBpcyBpbXBvcnRhbnQgdG8gbm90aWNlIHRoYXQgYSB0cmlhbmdsZSBpcyBhIHBvbHlnb25cclxuICAgICAqIFdlIGdldCA1IHBhdHRlcm5zIG9mIGZhY2UgZGVmaW5lZCBpbiBPQkogRmlsZSA6XHJcbiAgICAgKiBmYWNlUGF0dGVybjEgPSBbXCIxXCIsXCIyXCIsXCIzXCIsXCI0XCIsXCI1XCIsXCI2XCJdXHJcbiAgICAgKiBmYWNlUGF0dGVybjIgPSBbXCIxLzFcIixcIjIvMlwiLFwiMy8zXCIsXCI0LzRcIixcIjUvNVwiLFwiNi82XCJdXHJcbiAgICAgKiBmYWNlUGF0dGVybjMgPSBbXCIxLzEvMVwiLFwiMi8yLzJcIixcIjMvMy8zXCIsXCI0LzQvNFwiLFwiNS81LzVcIixcIjYvNi82XCJdXHJcbiAgICAgKiBmYWNlUGF0dGVybjQgPSBbXCIxLy8xXCIsXCIyLy8yXCIsXCIzLy8zXCIsXCI0Ly80XCIsXCI1Ly81XCIsXCI2Ly82XCJdXHJcbiAgICAgKiBmYWNlUGF0dGVybjUgPSBbXCItMS8tMS8tMVwiLFwiLTIvLTIvLTJcIixcIi0zLy0zLy0zXCIsXCItNC8tNC8tNFwiLFwiLTUvLTUvLTVcIixcIi02Ly02Ly02XCJdXHJcbiAgICAgKiBFYWNoIHBhdHRlcm4gaXMgZGl2aWRlZCBieSB0aGUgc2FtZSBtZXRob2RcclxuICAgICAqIEBwYXJhbSBmYWNlcyBBcnJheVtTdHJpbmddIFRoZSBpbmRpY2VzIG9mIGVsZW1lbnRzXHJcbiAgICAgKiBAcGFyYW0gdiBJbnRlZ2VyIFRoZSB2YXJpYWJsZSB0byBpbmNyZW1lbnRcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBfZ2V0VHJpYW5nbGVzKGZhY2VzOiBBcnJheTxzdHJpbmc+LCB2OiBudW1iZXIpIHtcclxuICAgICAgICAvL1dvcmsgZm9yIGVhY2ggZWxlbWVudCBvZiB0aGUgYXJyYXlcclxuICAgICAgICBmb3IgKGxldCBmYWNlSW5kZXggPSB2OyBmYWNlSW5kZXggPCBmYWNlcy5sZW5ndGggLSAxOyBmYWNlSW5kZXgrKykge1xyXG4gICAgICAgICAgICAvL0FkZCBvbiB0aGUgdHJpYW5nbGUgdmFyaWFibGUgdGhlIGluZGV4ZXMgdG8gb2J0YWluIHRyaWFuZ2xlc1xyXG4gICAgICAgICAgICB0aGlzLl90cmlhbmdsZXMucHVzaChmYWNlc1swXSwgZmFjZXNbZmFjZUluZGV4XSwgZmFjZXNbZmFjZUluZGV4ICsgMV0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy9SZXN1bHQgb2J0YWluZWQgYWZ0ZXIgMiBpdGVyYXRpb25zOlxyXG4gICAgICAgIC8vUGF0dGVybjEgPT4gdHJpYW5nbGUgPSBbXCIxXCIsXCIyXCIsXCIzXCIsXCIxXCIsXCIzXCIsXCI0XCJdO1xyXG4gICAgICAgIC8vUGF0dGVybjIgPT4gdHJpYW5nbGUgPSBbXCIxLzFcIixcIjIvMlwiLFwiMy8zXCIsXCIxLzFcIixcIjMvM1wiLFwiNC80XCJdO1xyXG4gICAgICAgIC8vUGF0dGVybjMgPT4gdHJpYW5nbGUgPSBbXCIxLzEvMVwiLFwiMi8yLzJcIixcIjMvMy8zXCIsXCIxLzEvMVwiLFwiMy8zLzNcIixcIjQvNC80XCJdO1xyXG4gICAgICAgIC8vUGF0dGVybjQgPT4gdHJpYW5nbGUgPSBbXCIxLy8xXCIsXCIyLy8yXCIsXCIzLy8zXCIsXCIxLy8xXCIsXCIzLy8zXCIsXCI0Ly80XCJdO1xyXG4gICAgICAgIC8vUGF0dGVybjUgPT4gdHJpYW5nbGUgPSBbXCItMS8tMS8tMVwiLFwiLTIvLTIvLTJcIixcIi0zLy0zLy0zXCIsXCItMS8tMS8tMVwiLFwiLTMvLTMvLTNcIixcIi00Ly00Ly00XCJdO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlIHRyaWFuZ2xlcyBhbmQgcHVzaCB0aGUgZGF0YSBmb3IgZWFjaCBwb2x5Z29uIGZvciB0aGUgcGF0dGVybiAxXHJcbiAgICAgKiBJbiB0aGlzIHBhdHRlcm4gd2UgZ2V0IHZlcnRpY2UgcG9zaXRpb25zXHJcbiAgICAgKiBAcGFyYW0gZmFjZVxyXG4gICAgICogQHBhcmFtIHZcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBfc2V0RGF0YUZvckN1cnJlbnRGYWNlV2l0aFBhdHRlcm4xKGZhY2U6IEFycmF5PHN0cmluZz4sIHY6IG51bWJlcikge1xyXG4gICAgICAgIC8vR2V0IHRoZSBpbmRpY2VzIG9mIHRyaWFuZ2xlcyBmb3IgZWFjaCBwb2x5Z29uXHJcbiAgICAgICAgdGhpcy5fZ2V0VHJpYW5nbGVzKGZhY2UsIHYpO1xyXG4gICAgICAgIC8vRm9yIGVhY2ggZWxlbWVudCBpbiB0aGUgdHJpYW5nbGVzIGFycmF5LlxyXG4gICAgICAgIC8vVGhpcyB2YXIgY291bGQgY29udGFpbnMgMSB0byBhbiBpbmZpbml0eSBvZiB0cmlhbmdsZXNcclxuICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IHRoaXMuX3RyaWFuZ2xlcy5sZW5ndGg7IGsrKykge1xyXG4gICAgICAgICAgICAvLyBTZXQgcG9zaXRpb24gaW5kaWNlXHJcbiAgICAgICAgICAgIGNvbnN0IGluZGljZVBvc2l0aW9uRnJvbU9iaiA9IHBhcnNlSW50KHRoaXMuX3RyaWFuZ2xlc1trXSkgLSAxO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5fc2V0RGF0YShcclxuICAgICAgICAgICAgICAgIGluZGljZVBvc2l0aW9uRnJvbU9iaixcclxuICAgICAgICAgICAgICAgIDAsXHJcbiAgICAgICAgICAgICAgICAwLCAvLyBJbiB0aGUgcGF0dGVybiAxLCBub3JtYWxzIGFuZCB1dnMgYXJlIG5vdCBkZWZpbmVkXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9wb3NpdGlvbnNbaW5kaWNlUG9zaXRpb25Gcm9tT2JqXSwgLy8gR2V0IHRoZSB2ZWN0b3JzIGRhdGFcclxuICAgICAgICAgICAgICAgIFZlY3RvcjIuWmVybygpLFxyXG4gICAgICAgICAgICAgICAgVmVjdG9yMy5VcCgpLCAvLyBDcmVhdGUgZGVmYXVsdCB2ZWN0b3JzXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkaW5nT3B0aW9ucy5pbXBvcnRWZXJ0ZXhDb2xvcnMgPyB0aGlzLl9jb2xvcnNbaW5kaWNlUG9zaXRpb25Gcm9tT2JqXSA6IHVuZGVmaW5lZFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuICAgICAgICAvL1Jlc2V0IHZhcmlhYmxlIGZvciB0aGUgbmV4dCBsaW5lXHJcbiAgICAgICAgdGhpcy5fdHJpYW5nbGVzLmxlbmd0aCA9IDA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGUgdHJpYW5nbGVzIGFuZCBwdXNoIHRoZSBkYXRhIGZvciBlYWNoIHBvbHlnb24gZm9yIHRoZSBwYXR0ZXJuIDJcclxuICAgICAqIEluIHRoaXMgcGF0dGVybiB3ZSBnZXQgdmVydGljZSBwb3NpdGlvbnMgYW5kIHV2c1xyXG4gICAgICogQHBhcmFtIGZhY2VcclxuICAgICAqIEBwYXJhbSB2XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgX3NldERhdGFGb3JDdXJyZW50RmFjZVdpdGhQYXR0ZXJuMihmYWNlOiBBcnJheTxzdHJpbmc+LCB2OiBudW1iZXIpIHtcclxuICAgICAgICAvL0dldCB0aGUgaW5kaWNlcyBvZiB0cmlhbmdsZXMgZm9yIGVhY2ggcG9seWdvblxyXG4gICAgICAgIHRoaXMuX2dldFRyaWFuZ2xlcyhmYWNlLCB2KTtcclxuICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IHRoaXMuX3RyaWFuZ2xlcy5sZW5ndGg7IGsrKykge1xyXG4gICAgICAgICAgICAvL3RyaWFuZ2xlW2tdID0gXCIxLzFcIlxyXG4gICAgICAgICAgICAvL1NwbGl0IHRoZSBkYXRhIGZvciBnZXR0aW5nIHBvc2l0aW9uIGFuZCB1dlxyXG4gICAgICAgICAgICBjb25zdCBwb2ludCA9IHRoaXMuX3RyaWFuZ2xlc1trXS5zcGxpdChcIi9cIik7IC8vIFtcIjFcIiwgXCIxXCJdXHJcbiAgICAgICAgICAgIC8vU2V0IHBvc2l0aW9uIGluZGljZVxyXG4gICAgICAgICAgICBjb25zdCBpbmRpY2VQb3NpdGlvbkZyb21PYmogPSBwYXJzZUludChwb2ludFswXSkgLSAxO1xyXG4gICAgICAgICAgICAvL1NldCB1diBpbmRpY2VcclxuICAgICAgICAgICAgY29uc3QgaW5kaWNlVXZzRnJvbU9iaiA9IHBhcnNlSW50KHBvaW50WzFdKSAtIDE7XHJcblxyXG4gICAgICAgICAgICB0aGlzLl9zZXREYXRhKFxyXG4gICAgICAgICAgICAgICAgaW5kaWNlUG9zaXRpb25Gcm9tT2JqLFxyXG4gICAgICAgICAgICAgICAgaW5kaWNlVXZzRnJvbU9iaixcclxuICAgICAgICAgICAgICAgIDAsIC8vRGVmYXVsdCB2YWx1ZSBmb3Igbm9ybWFsc1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fcG9zaXRpb25zW2luZGljZVBvc2l0aW9uRnJvbU9ial0sIC8vR2V0IHRoZSB2YWx1ZXMgZm9yIGVhY2ggZWxlbWVudFxyXG4gICAgICAgICAgICAgICAgdGhpcy5fdXZzW2luZGljZVV2c0Zyb21PYmpdLFxyXG4gICAgICAgICAgICAgICAgVmVjdG9yMy5VcCgpLCAvL0RlZmF1bHQgdmFsdWUgZm9yIG5vcm1hbHNcclxuICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRpbmdPcHRpb25zLmltcG9ydFZlcnRleENvbG9ycyA/IHRoaXMuX2NvbG9yc1tpbmRpY2VQb3NpdGlvbkZyb21PYmpdIDogdW5kZWZpbmVkXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvL1Jlc2V0IHZhcmlhYmxlIGZvciB0aGUgbmV4dCBsaW5lXHJcbiAgICAgICAgdGhpcy5fdHJpYW5nbGVzLmxlbmd0aCA9IDA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGUgdHJpYW5nbGVzIGFuZCBwdXNoIHRoZSBkYXRhIGZvciBlYWNoIHBvbHlnb24gZm9yIHRoZSBwYXR0ZXJuIDNcclxuICAgICAqIEluIHRoaXMgcGF0dGVybiB3ZSBnZXQgdmVydGljZSBwb3NpdGlvbnMsIHV2cyBhbmQgbm9ybWFsc1xyXG4gICAgICogQHBhcmFtIGZhY2VcclxuICAgICAqIEBwYXJhbSB2XHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgX3NldERhdGFGb3JDdXJyZW50RmFjZVdpdGhQYXR0ZXJuMyhmYWNlOiBBcnJheTxzdHJpbmc+LCB2OiBudW1iZXIpIHtcclxuICAgICAgICAvL0dldCB0aGUgaW5kaWNlcyBvZiB0cmlhbmdsZXMgZm9yIGVhY2ggcG9seWdvblxyXG4gICAgICAgIHRoaXMuX2dldFRyaWFuZ2xlcyhmYWNlLCB2KTtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCB0aGlzLl90cmlhbmdsZXMubGVuZ3RoOyBrKyspIHtcclxuICAgICAgICAgICAgLy90cmlhbmdsZVtrXSA9IFwiMS8xLzFcIlxyXG4gICAgICAgICAgICAvL1NwbGl0IHRoZSBkYXRhIGZvciBnZXR0aW5nIHBvc2l0aW9uLCB1diwgYW5kIG5vcm1hbHNcclxuICAgICAgICAgICAgY29uc3QgcG9pbnQgPSB0aGlzLl90cmlhbmdsZXNba10uc3BsaXQoXCIvXCIpOyAvLyBbXCIxXCIsIFwiMVwiLCBcIjFcIl1cclxuICAgICAgICAgICAgLy8gU2V0IHBvc2l0aW9uIGluZGljZVxyXG4gICAgICAgICAgICBjb25zdCBpbmRpY2VQb3NpdGlvbkZyb21PYmogPSBwYXJzZUludChwb2ludFswXSkgLSAxO1xyXG4gICAgICAgICAgICAvLyBTZXQgdXYgaW5kaWNlXHJcbiAgICAgICAgICAgIGNvbnN0IGluZGljZVV2c0Zyb21PYmogPSBwYXJzZUludChwb2ludFsxXSkgLSAxO1xyXG4gICAgICAgICAgICAvLyBTZXQgbm9ybWFsIGluZGljZVxyXG4gICAgICAgICAgICBjb25zdCBpbmRpY2VOb3JtYWxGcm9tT2JqID0gcGFyc2VJbnQocG9pbnRbMl0pIC0gMTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuX3NldERhdGEoXHJcbiAgICAgICAgICAgICAgICBpbmRpY2VQb3NpdGlvbkZyb21PYmosXHJcbiAgICAgICAgICAgICAgICBpbmRpY2VVdnNGcm9tT2JqLFxyXG4gICAgICAgICAgICAgICAgaW5kaWNlTm9ybWFsRnJvbU9iaixcclxuICAgICAgICAgICAgICAgIHRoaXMuX3Bvc2l0aW9uc1tpbmRpY2VQb3NpdGlvbkZyb21PYmpdLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5fdXZzW2luZGljZVV2c0Zyb21PYmpdLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5fbm9ybWFsc1tpbmRpY2VOb3JtYWxGcm9tT2JqXSAvL1NldCB0aGUgdmVjdG9yIGZvciBlYWNoIGNvbXBvbmVudFxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuICAgICAgICAvL1Jlc2V0IHZhcmlhYmxlIGZvciB0aGUgbmV4dCBsaW5lXHJcbiAgICAgICAgdGhpcy5fdHJpYW5nbGVzLmxlbmd0aCA9IDA7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGUgdHJpYW5nbGVzIGFuZCBwdXNoIHRoZSBkYXRhIGZvciBlYWNoIHBvbHlnb24gZm9yIHRoZSBwYXR0ZXJuIDRcclxuICAgICAqIEluIHRoaXMgcGF0dGVybiB3ZSBnZXQgdmVydGljZSBwb3NpdGlvbnMgYW5kIG5vcm1hbHNcclxuICAgICAqIEBwYXJhbSBmYWNlXHJcbiAgICAgKiBAcGFyYW0gdlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIF9zZXREYXRhRm9yQ3VycmVudEZhY2VXaXRoUGF0dGVybjQoZmFjZTogQXJyYXk8c3RyaW5nPiwgdjogbnVtYmVyKSB7XHJcbiAgICAgICAgdGhpcy5fZ2V0VHJpYW5nbGVzKGZhY2UsIHYpO1xyXG5cclxuICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IHRoaXMuX3RyaWFuZ2xlcy5sZW5ndGg7IGsrKykge1xyXG4gICAgICAgICAgICAvL3RyaWFuZ2xlW2tdID0gXCIxLy8xXCJcclxuICAgICAgICAgICAgLy9TcGxpdCB0aGUgZGF0YSBmb3IgZ2V0dGluZyBwb3NpdGlvbiBhbmQgbm9ybWFsc1xyXG4gICAgICAgICAgICBjb25zdCBwb2ludCA9IHRoaXMuX3RyaWFuZ2xlc1trXS5zcGxpdChcIi8vXCIpOyAvLyBbXCIxXCIsIFwiMVwiXVxyXG4gICAgICAgICAgICAvLyBXZSBjaGVjayBpbmRpY2VzLCBhbmQgbm9ybWFsc1xyXG4gICAgICAgICAgICBjb25zdCBpbmRpY2VQb3NpdGlvbkZyb21PYmogPSBwYXJzZUludChwb2ludFswXSkgLSAxO1xyXG4gICAgICAgICAgICBjb25zdCBpbmRpY2VOb3JtYWxGcm9tT2JqID0gcGFyc2VJbnQocG9pbnRbMV0pIC0gMTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuX3NldERhdGEoXHJcbiAgICAgICAgICAgICAgICBpbmRpY2VQb3NpdGlvbkZyb21PYmosXHJcbiAgICAgICAgICAgICAgICAxLCAvL0RlZmF1bHQgdmFsdWUgZm9yIHV2XHJcbiAgICAgICAgICAgICAgICBpbmRpY2VOb3JtYWxGcm9tT2JqLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5fcG9zaXRpb25zW2luZGljZVBvc2l0aW9uRnJvbU9ial0sIC8vR2V0IGVhY2ggdmVjdG9yIG9mIGRhdGFcclxuICAgICAgICAgICAgICAgIFZlY3RvcjIuWmVybygpLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5fbm9ybWFsc1tpbmRpY2VOb3JtYWxGcm9tT2JqXSxcclxuICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRpbmdPcHRpb25zLmltcG9ydFZlcnRleENvbG9ycyA/IHRoaXMuX2NvbG9yc1tpbmRpY2VQb3NpdGlvbkZyb21PYmpdIDogdW5kZWZpbmVkXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vUmVzZXQgdmFyaWFibGUgZm9yIHRoZSBuZXh0IGxpbmVcclxuICAgICAgICB0aGlzLl90cmlhbmdsZXMubGVuZ3RoID0gMDtcclxuICAgIH1cclxuXHJcbiAgICAvKlxyXG4gICAgICogQ3JlYXRlIHRyaWFuZ2xlcyBhbmQgcHVzaCB0aGUgZGF0YSBmb3IgZWFjaCBwb2x5Z29uIGZvciB0aGUgcGF0dGVybiAzXHJcbiAgICAgKiBJbiB0aGlzIHBhdHRlcm4gd2UgZ2V0IHZlcnRpY2UgcG9zaXRpb25zLCB1dnMgYW5kIG5vcm1hbHNcclxuICAgICAqIEBwYXJhbSBmYWNlXHJcbiAgICAgKiBAcGFyYW0gdlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIF9zZXREYXRhRm9yQ3VycmVudEZhY2VXaXRoUGF0dGVybjUoZmFjZTogQXJyYXk8c3RyaW5nPiwgdjogbnVtYmVyKSB7XHJcbiAgICAgICAgLy9HZXQgdGhlIGluZGljZXMgb2YgdHJpYW5nbGVzIGZvciBlYWNoIHBvbHlnb25cclxuICAgICAgICB0aGlzLl9nZXRUcmlhbmdsZXMoZmFjZSwgdik7XHJcblxyXG4gICAgICAgIGZvciAobGV0IGsgPSAwOyBrIDwgdGhpcy5fdHJpYW5nbGVzLmxlbmd0aDsgaysrKSB7XHJcbiAgICAgICAgICAgIC8vdHJpYW5nbGVba10gPSBcIi0xLy0xLy0xXCJcclxuICAgICAgICAgICAgLy9TcGxpdCB0aGUgZGF0YSBmb3IgZ2V0dGluZyBwb3NpdGlvbiwgdXYsIGFuZCBub3JtYWxzXHJcbiAgICAgICAgICAgIGNvbnN0IHBvaW50ID0gdGhpcy5fdHJpYW5nbGVzW2tdLnNwbGl0KFwiL1wiKTsgLy8gW1wiLTFcIiwgXCItMVwiLCBcIi0xXCJdXHJcbiAgICAgICAgICAgIC8vIFNldCBwb3NpdGlvbiBpbmRpY2VcclxuICAgICAgICAgICAgY29uc3QgaW5kaWNlUG9zaXRpb25Gcm9tT2JqID0gdGhpcy5fcG9zaXRpb25zLmxlbmd0aCArIHBhcnNlSW50KHBvaW50WzBdKTtcclxuICAgICAgICAgICAgLy8gU2V0IHV2IGluZGljZVxyXG4gICAgICAgICAgICBjb25zdCBpbmRpY2VVdnNGcm9tT2JqID0gdGhpcy5fdXZzLmxlbmd0aCArIHBhcnNlSW50KHBvaW50WzFdKTtcclxuICAgICAgICAgICAgLy8gU2V0IG5vcm1hbCBpbmRpY2VcclxuICAgICAgICAgICAgY29uc3QgaW5kaWNlTm9ybWFsRnJvbU9iaiA9IHRoaXMuX25vcm1hbHMubGVuZ3RoICsgcGFyc2VJbnQocG9pbnRbMl0pO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5fc2V0RGF0YShcclxuICAgICAgICAgICAgICAgIGluZGljZVBvc2l0aW9uRnJvbU9iaixcclxuICAgICAgICAgICAgICAgIGluZGljZVV2c0Zyb21PYmosXHJcbiAgICAgICAgICAgICAgICBpbmRpY2VOb3JtYWxGcm9tT2JqLFxyXG4gICAgICAgICAgICAgICAgdGhpcy5fcG9zaXRpb25zW2luZGljZVBvc2l0aW9uRnJvbU9ial0sXHJcbiAgICAgICAgICAgICAgICB0aGlzLl91dnNbaW5kaWNlVXZzRnJvbU9ial0sXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9ub3JtYWxzW2luZGljZU5vcm1hbEZyb21PYmpdLCAvL1NldCB0aGUgdmVjdG9yIGZvciBlYWNoIGNvbXBvbmVudFxyXG4gICAgICAgICAgICAgICAgdGhpcy5fbG9hZGluZ09wdGlvbnMuaW1wb3J0VmVydGV4Q29sb3JzID8gdGhpcy5fY29sb3JzW2luZGljZVBvc2l0aW9uRnJvbU9ial0gOiB1bmRlZmluZWRcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgLy9SZXNldCB2YXJpYWJsZSBmb3IgdGhlIG5leHQgbGluZVxyXG4gICAgICAgIHRoaXMuX3RyaWFuZ2xlcy5sZW5ndGggPSAwO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2FkZFByZXZpb3VzT2JqTWVzaCgpIHtcclxuICAgICAgICAvL0NoZWNrIGlmIGl0IGlzIG5vdCB0aGUgZmlyc3QgbWVzaC4gT3RoZXJ3aXNlIHdlIGRvbid0IGhhdmUgZGF0YS5cclxuICAgICAgICBpZiAodGhpcy5fbWVzaGVzRnJvbU9iai5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIC8vR2V0IHRoZSBwcmV2aW91cyBtZXNoIGZvciBhcHBseWluZyB0aGUgZGF0YSBhYm91dCB0aGUgZmFjZXNcclxuICAgICAgICAgICAgLy89PiBpbiBvYmogZmlsZSwgZmFjZXMgZGVmaW5pdGlvbiBhcHBlbmQgYWZ0ZXIgdGhlIG5hbWUgb2YgdGhlIG1lc2hcclxuICAgICAgICAgICAgdGhpcy5faGFuZGxlZE1lc2ggPSB0aGlzLl9tZXNoZXNGcm9tT2JqW3RoaXMuX21lc2hlc0Zyb21PYmoubGVuZ3RoIC0gMV07XHJcblxyXG4gICAgICAgICAgICAvL1NldCB0aGUgZGF0YSBpbnRvIEFycmF5IGZvciB0aGUgbWVzaFxyXG4gICAgICAgICAgICB0aGlzLl91bndyYXBEYXRhKCk7XHJcblxyXG4gICAgICAgICAgICAvLyBSZXZlcnNlIHRhYi4gT3RoZXJ3aXNlIGZhY2UgYXJlIGRpc3BsYXllZCBpbiB0aGUgd3Jvbmcgc2Vuc1xyXG4gICAgICAgICAgICB0aGlzLl9pbmRpY2VzRm9yQmFieWxvbi5yZXZlcnNlKCk7XHJcbiAgICAgICAgICAgIC8vU2V0IHRoZSBpbmZvcm1hdGlvbiBmb3IgdGhlIG1lc2hcclxuICAgICAgICAgICAgLy9TbGljZSB0aGUgYXJyYXkgdG8gYXZvaWQgcmV3cml0aW5nIGJlY2F1c2Ugb2YgdGhlIGZhY3QgdGhpcyBpcyB0aGUgc2FtZSB2YXIgd2hpY2ggYmUgcmV3cml0ZWRcclxuICAgICAgICAgICAgdGhpcy5faGFuZGxlZE1lc2guaW5kaWNlcyA9IHRoaXMuX2luZGljZXNGb3JCYWJ5bG9uLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIHRoaXMuX2hhbmRsZWRNZXNoLnBvc2l0aW9ucyA9IHRoaXMuX3Vud3JhcHBlZFBvc2l0aW9uc0ZvckJhYnlsb24uc2xpY2UoKTtcclxuICAgICAgICAgICAgdGhpcy5faGFuZGxlZE1lc2gubm9ybWFscyA9IHRoaXMuX3Vud3JhcHBlZE5vcm1hbHNGb3JCYWJ5bG9uLnNsaWNlKCk7XHJcbiAgICAgICAgICAgIHRoaXMuX2hhbmRsZWRNZXNoLnV2cyA9IHRoaXMuX3Vud3JhcHBlZFVWRm9yQmFieWxvbi5zbGljZSgpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuX2xvYWRpbmdPcHRpb25zLmltcG9ydFZlcnRleENvbG9ycykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5faGFuZGxlZE1lc2guY29sb3JzID0gdGhpcy5fdW53cmFwcGVkQ29sb3JzRm9yQmFieWxvbi5zbGljZSgpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvL1Jlc2V0IHRoZSBhcnJheSBmb3IgdGhlIG5leHQgbWVzaFxyXG4gICAgICAgICAgICB0aGlzLl9pbmRpY2VzRm9yQmFieWxvbi5sZW5ndGggPSAwO1xyXG4gICAgICAgICAgICB0aGlzLl91bndyYXBwZWRQb3NpdGlvbnNGb3JCYWJ5bG9uLmxlbmd0aCA9IDA7XHJcbiAgICAgICAgICAgIHRoaXMuX3Vud3JhcHBlZENvbG9yc0ZvckJhYnlsb24ubGVuZ3RoID0gMDtcclxuICAgICAgICAgICAgdGhpcy5fdW53cmFwcGVkTm9ybWFsc0ZvckJhYnlsb24ubGVuZ3RoID0gMDtcclxuICAgICAgICAgICAgdGhpcy5fdW53cmFwcGVkVVZGb3JCYWJ5bG9uLmxlbmd0aCA9IDA7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX29wdGltaXplTm9ybWFscyhtZXNoOiBBYnN0cmFjdE1lc2gpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBtZXNoLmdldFZlcnRpY2VzRGF0YShWZXJ0ZXhCdWZmZXIuUG9zaXRpb25LaW5kKTtcclxuICAgICAgICBjb25zdCBub3JtYWxzID0gbWVzaC5nZXRWZXJ0aWNlc0RhdGEoVmVydGV4QnVmZmVyLk5vcm1hbEtpbmQpO1xyXG4gICAgICAgIGNvbnN0IG1hcFZlcnRpY2VzOiB7IFtrZXk6IHN0cmluZ106IG51bWJlcltdIH0gPSB7fTtcclxuXHJcbiAgICAgICAgaWYgKCFwb3NpdGlvbnMgfHwgIW5vcm1hbHMpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBwb3NpdGlvbnMubGVuZ3RoIC8gMzsgaSsrKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHggPSBwb3NpdGlvbnNbaSAqIDMgKyAwXTtcclxuICAgICAgICAgICAgY29uc3QgeSA9IHBvc2l0aW9uc1tpICogMyArIDFdO1xyXG4gICAgICAgICAgICBjb25zdCB6ID0gcG9zaXRpb25zW2kgKiAzICsgMl07XHJcbiAgICAgICAgICAgIGNvbnN0IGtleSA9IHggKyBcIl9cIiArIHkgKyBcIl9cIiArIHo7XHJcblxyXG4gICAgICAgICAgICBsZXQgbHN0ID0gbWFwVmVydGljZXNba2V5XTtcclxuICAgICAgICAgICAgaWYgKCFsc3QpIHtcclxuICAgICAgICAgICAgICAgIGxzdCA9IFtdO1xyXG4gICAgICAgICAgICAgICAgbWFwVmVydGljZXNba2V5XSA9IGxzdDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBsc3QucHVzaChpKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IG5vcm1hbCA9IG5ldyBWZWN0b3IzKCk7XHJcbiAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gbWFwVmVydGljZXMpIHtcclxuICAgICAgICAgICAgY29uc3QgbHN0ID0gbWFwVmVydGljZXNba2V5XTtcclxuICAgICAgICAgICAgaWYgKGxzdC5sZW5ndGggPCAyKSB7XHJcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3QgdjBJZHggPSBsc3RbMF07XHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDwgbHN0Lmxlbmd0aDsgKytpKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB2SWR4ID0gbHN0W2ldO1xyXG4gICAgICAgICAgICAgICAgbm9ybWFsc1t2MElkeCAqIDMgKyAwXSArPSBub3JtYWxzW3ZJZHggKiAzICsgMF07XHJcbiAgICAgICAgICAgICAgICBub3JtYWxzW3YwSWR4ICogMyArIDFdICs9IG5vcm1hbHNbdklkeCAqIDMgKyAxXTtcclxuICAgICAgICAgICAgICAgIG5vcm1hbHNbdjBJZHggKiAzICsgMl0gKz0gbm9ybWFsc1t2SWR4ICogMyArIDJdO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBub3JtYWwuY29weUZyb21GbG9hdHMobm9ybWFsc1t2MElkeCAqIDMgKyAwXSwgbm9ybWFsc1t2MElkeCAqIDMgKyAxXSwgbm9ybWFsc1t2MElkeCAqIDMgKyAyXSk7XHJcbiAgICAgICAgICAgIG5vcm1hbC5ub3JtYWxpemUoKTtcclxuXHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbHN0Lmxlbmd0aDsgKytpKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB2SWR4ID0gbHN0W2ldO1xyXG4gICAgICAgICAgICAgICAgbm9ybWFsc1t2SWR4ICogMyArIDBdID0gbm9ybWFsLng7XHJcbiAgICAgICAgICAgICAgICBub3JtYWxzW3ZJZHggKiAzICsgMV0gPSBub3JtYWwueTtcclxuICAgICAgICAgICAgICAgIG5vcm1hbHNbdklkeCAqIDMgKyAyXSA9IG5vcm1hbC56O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgICAgIG1lc2guc2V0VmVydGljZXNEYXRhKFZlcnRleEJ1ZmZlci5Ob3JtYWxLaW5kLCBub3JtYWxzKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEZ1bmN0aW9uIHVzZWQgdG8gcGFyc2UgYW4gT0JKIHN0cmluZ1xyXG4gICAgICogQHBhcmFtIG1lc2hlc05hbWVzIGRlZmluZXMgdGhlIGxpc3Qgb2YgbWVzaGVzIHRvIGxvYWQgKGFsbCBpZiBub3QgZGVmaW5lZClcclxuICAgICAqIEBwYXJhbSBkYXRhIGRlZmluZXMgdGhlIE9CSiBzdHJpbmdcclxuICAgICAqIEBwYXJhbSBzY2VuZSBkZWZpbmVzIHRoZSBob3N0aW5nIHNjZW5lXHJcbiAgICAgKiBAcGFyYW0gYXNzZXRDb250YWluZXIgZGVmaW5lcyB0aGUgYXNzZXQgY29udGFpbmVyIHRvIGxvYWQgZGF0YSBpblxyXG4gICAgICogQHBhcmFtIG9uRmlsZVRvTG9hZEZvdW5kIGRlZmluZXMgYSBjYWxsYmFjayB0aGF0IHdpbGwgYmUgY2FsbGVkIGlmIGEgTVRMIGZpbGUgaXMgZm91bmRcclxuICAgICAqL1xyXG4gICAgcHVibGljIHBhcnNlKG1lc2hlc05hbWVzOiBhbnksIGRhdGE6IHN0cmluZywgc2NlbmU6IFNjZW5lLCBhc3NldENvbnRhaW5lcjogTnVsbGFibGU8QXNzZXRDb250YWluZXI+LCBvbkZpbGVUb0xvYWRGb3VuZDogKGZpbGVUb0xvYWQ6IHN0cmluZykgPT4gdm9pZCk6IHZvaWQge1xyXG4gICAgICAgIC8vIFNwbGl0IHRoZSBmaWxlIGludG8gbGluZXNcclxuICAgICAgICBjb25zdCBsaW5lcyA9IGRhdGEuc3BsaXQoXCJcXG5cIik7XHJcbiAgICAgICAgLy8gTG9vayBhdCBlYWNoIGxpbmVcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGxpbmVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGxpbmUgPSBsaW5lc1tpXS50cmltKCkucmVwbGFjZSgvXFxzXFxzL2csIFwiIFwiKTtcclxuICAgICAgICAgICAgbGV0IHJlc3VsdDtcclxuXHJcbiAgICAgICAgICAgIC8vIENvbW1lbnQgb3IgbmV3TGluZVxyXG4gICAgICAgICAgICBpZiAobGluZS5sZW5ndGggPT09IDAgfHwgbGluZS5jaGFyQXQoMCkgPT09IFwiI1wiKSB7XHJcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuXHJcbiAgICAgICAgICAgICAgICAvL0dldCBpbmZvcm1hdGlvbiBhYm91dCBvbmUgcG9zaXRpb24gcG9zc2libGUgZm9yIHRoZSB2ZXJ0aWNlc1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKFNvbGlkUGFyc2VyLlZlcnRleFBhdHRlcm4udGVzdChsaW5lKSkge1xyXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gbGluZS5tYXRjaCgvW14gXSsvZykhOyAvLyBtYXRjaCB3aWxsIHJldHVybiBub24tbnVsbCBkdWUgdG8gcGFzc2luZyByZWdleCBwYXR0ZXJuXHJcblxyXG4gICAgICAgICAgICAgICAgLy8gVmFsdWUgb2YgcmVzdWx0IHdpdGggbGluZTogXCJ2IDEuMCAyLjAgMy4wXCJcclxuICAgICAgICAgICAgICAgIC8vIFtcInZcIiwgXCIxLjBcIiwgXCIyLjBcIiwgXCIzLjBcIl1cclxuICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBhIFZlY3RvcjMgd2l0aCB0aGUgcG9zaXRpb24geCwgeSwgelxyXG4gICAgICAgICAgICAgICAgdGhpcy5fcG9zaXRpb25zLnB1c2gobmV3IFZlY3RvcjMocGFyc2VGbG9hdChyZXN1bHRbMV0pLCBwYXJzZUZsb2F0KHJlc3VsdFsyXSksIHBhcnNlRmxvYXQocmVzdWx0WzNdKSkpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9sb2FkaW5nT3B0aW9ucy5pbXBvcnRWZXJ0ZXhDb2xvcnMpIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAocmVzdWx0Lmxlbmd0aCA+PSA3KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHIgPSBwYXJzZUZsb2F0KHJlc3VsdFs0XSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGcgPSBwYXJzZUZsb2F0KHJlc3VsdFs1XSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGIgPSBwYXJzZUZsb2F0KHJlc3VsdFs2XSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9jb2xvcnMucHVzaChcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBDb2xvcjQociA+IDEgPyByIC8gMjU1IDogciwgZyA+IDEgPyBnIC8gMjU1IDogZywgYiA+IDEgPyBiIC8gMjU1IDogYiwgcmVzdWx0Lmxlbmd0aCA9PT0gNyB8fCByZXN1bHRbN10gPT09IHVuZGVmaW5lZCA/IDEgOiBwYXJzZUZsb2F0KHJlc3VsdFs3XSkpXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogbWF5YmUgcHVzaCBOVUxMIGFuZCBpZiBhbGwgYXJlIE5VTEwgdG8gc2tpcCAoYW5kIHJlbW92ZSBncmF5Q29sb3IgdmFyKS5cclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fY29sb3JzLnB1c2godGhpcy5fZ3JheUNvbG9yKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoKHJlc3VsdCA9IFNvbGlkUGFyc2VyLk5vcm1hbFBhdHRlcm4uZXhlYyhsaW5lKSkgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIC8vQ3JlYXRlIGEgVmVjdG9yMyB3aXRoIHRoZSBub3JtYWxzIHgsIHksIHpcclxuICAgICAgICAgICAgICAgIC8vVmFsdWUgb2YgcmVzdWx0XHJcbiAgICAgICAgICAgICAgICAvLyBbXCJ2biAxLjAgMi4wIDMuMFwiLCBcIjEuMFwiLCBcIjIuMFwiLCBcIjMuMFwiXVxyXG4gICAgICAgICAgICAgICAgLy9BZGQgdGhlIFZlY3RvciBpbiB0aGUgbGlzdCBvZiBub3JtYWxzXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9ub3JtYWxzLnB1c2gobmV3IFZlY3RvcjMocGFyc2VGbG9hdChyZXN1bHRbMV0pLCBwYXJzZUZsb2F0KHJlc3VsdFsyXSksIHBhcnNlRmxvYXQocmVzdWx0WzNdKSkpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKChyZXN1bHQgPSBTb2xpZFBhcnNlci5VVlBhdHRlcm4uZXhlYyhsaW5lKSkgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIC8vQ3JlYXRlIGEgVmVjdG9yMiB3aXRoIHRoZSBub3JtYWxzIHUsIHZcclxuICAgICAgICAgICAgICAgIC8vVmFsdWUgb2YgcmVzdWx0XHJcbiAgICAgICAgICAgICAgICAvLyBbXCJ2dCAwLjEgMC4yIDAuM1wiLCBcIjAuMVwiLCBcIjAuMlwiXVxyXG4gICAgICAgICAgICAgICAgLy9BZGQgdGhlIFZlY3RvciBpbiB0aGUgbGlzdCBvZiB1dnNcclxuICAgICAgICAgICAgICAgIHRoaXMuX3V2cy5wdXNoKG5ldyBWZWN0b3IyKHBhcnNlRmxvYXQocmVzdWx0WzFdKSAqIHRoaXMuX2xvYWRpbmdPcHRpb25zLlVWU2NhbGluZy54LCBwYXJzZUZsb2F0KHJlc3VsdFsyXSkgKiB0aGlzLl9sb2FkaW5nT3B0aW9ucy5VVlNjYWxpbmcueSkpO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vSWRlbnRpZnkgcGF0dGVybnMgb2YgZmFjZXNcclxuICAgICAgICAgICAgICAgIC8vRmFjZSBjb3VsZCBiZSBkZWZpbmVkIGluIGRpZmZlcmVudCB0eXBlIG9mIHBhdHRlcm5cclxuICAgICAgICAgICAgfSBlbHNlIGlmICgocmVzdWx0ID0gU29saWRQYXJzZXIuRmFjZVBhdHRlcm4zLmV4ZWMobGluZSkpICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAvL1ZhbHVlIG9mIHJlc3VsdDpcclxuICAgICAgICAgICAgICAgIC8vW1wiZiAxLzEvMSAyLzIvMiAzLzMvM1wiLCBcIjEvMS8xIDIvMi8yIDMvMy8zXCIuLi5dXHJcblxyXG4gICAgICAgICAgICAgICAgLy9TZXQgdGhlIGRhdGEgZm9yIHRoaXMgZmFjZVxyXG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0RGF0YUZvckN1cnJlbnRGYWNlV2l0aFBhdHRlcm4zKFxyXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFsxXS50cmltKCkuc3BsaXQoXCIgXCIpLCAvLyBbXCIxLzEvMVwiLCBcIjIvMi8yXCIsIFwiMy8zLzNcIl1cclxuICAgICAgICAgICAgICAgICAgICAxXHJcbiAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKChyZXN1bHQgPSBTb2xpZFBhcnNlci5GYWNlUGF0dGVybjQuZXhlYyhsaW5lKSkgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIC8vVmFsdWUgb2YgcmVzdWx0OlxyXG4gICAgICAgICAgICAgICAgLy9bXCJmIDEvLzEgMi8vMiAzLy8zXCIsIFwiMS8vMSAyLy8yIDMvLzNcIi4uLl1cclxuXHJcbiAgICAgICAgICAgICAgICAvL1NldCB0aGUgZGF0YSBmb3IgdGhpcyBmYWNlXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXREYXRhRm9yQ3VycmVudEZhY2VXaXRoUGF0dGVybjQoXHJcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0WzFdLnRyaW0oKS5zcGxpdChcIiBcIiksIC8vIFtcIjEvLzFcIiwgXCIyLy8yXCIsIFwiMy8vM1wiXVxyXG4gICAgICAgICAgICAgICAgICAgIDFcclxuICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoKHJlc3VsdCA9IFNvbGlkUGFyc2VyLkZhY2VQYXR0ZXJuNS5leGVjKGxpbmUpKSAhPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgLy9WYWx1ZSBvZiByZXN1bHQ6XHJcbiAgICAgICAgICAgICAgICAvL1tcImYgLTEvLTEvLTEgLTIvLTIvLTIgLTMvLTMvLTNcIiwgXCItMS8tMS8tMSAtMi8tMi8tMiAtMy8tMy8tM1wiLi4uXVxyXG5cclxuICAgICAgICAgICAgICAgIC8vU2V0IHRoZSBkYXRhIGZvciB0aGlzIGZhY2VcclxuICAgICAgICAgICAgICAgIHRoaXMuX3NldERhdGFGb3JDdXJyZW50RmFjZVdpdGhQYXR0ZXJuNShcclxuICAgICAgICAgICAgICAgICAgICByZXN1bHRbMV0udHJpbSgpLnNwbGl0KFwiIFwiKSwgLy8gW1wiLTEvLTEvLTFcIiwgXCItMi8tMi8tMlwiLCBcIi0zLy0zLy0zXCJdXHJcbiAgICAgICAgICAgICAgICAgICAgMVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmICgocmVzdWx0ID0gU29saWRQYXJzZXIuRmFjZVBhdHRlcm4yLmV4ZWMobGluZSkpICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAvL1ZhbHVlIG9mIHJlc3VsdDpcclxuICAgICAgICAgICAgICAgIC8vW1wiZiAxLzEgMi8yIDMvM1wiLCBcIjEvMSAyLzIgMy8zXCIuLi5dXHJcblxyXG4gICAgICAgICAgICAgICAgLy9TZXQgdGhlIGRhdGEgZm9yIHRoaXMgZmFjZVxyXG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0RGF0YUZvckN1cnJlbnRGYWNlV2l0aFBhdHRlcm4yKFxyXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFsxXS50cmltKCkuc3BsaXQoXCIgXCIpLCAvLyBbXCIxLzFcIiwgXCIyLzJcIiwgXCIzLzNcIl1cclxuICAgICAgICAgICAgICAgICAgICAxXHJcbiAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKChyZXN1bHQgPSBTb2xpZFBhcnNlci5GYWNlUGF0dGVybjEuZXhlYyhsaW5lKSkgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIC8vVmFsdWUgb2YgcmVzdWx0XHJcbiAgICAgICAgICAgICAgICAvL1tcImYgMSAyIDNcIiwgXCIxIDIgM1wiLi4uXVxyXG5cclxuICAgICAgICAgICAgICAgIC8vU2V0IHRoZSBkYXRhIGZvciB0aGlzIGZhY2VcclxuICAgICAgICAgICAgICAgIHRoaXMuX3NldERhdGFGb3JDdXJyZW50RmFjZVdpdGhQYXR0ZXJuMShcclxuICAgICAgICAgICAgICAgICAgICByZXN1bHRbMV0udHJpbSgpLnNwbGl0KFwiIFwiKSwgLy8gW1wiMVwiLCBcIjJcIiwgXCIzXCJdXHJcbiAgICAgICAgICAgICAgICAgICAgMVxyXG4gICAgICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBEZWZpbmUgYSBtZXNoIG9yIGFuIG9iamVjdFxyXG4gICAgICAgICAgICAgICAgLy8gRWFjaCB0aW1lIHRoaXMga2V5d29yZCBpcyBhbmFseXplZCwgY3JlYXRlIGEgbmV3IE9iamVjdCB3aXRoIGFsbCBkYXRhIGZvciBjcmVhdGluZyBhIGJhYnlsb25NZXNoXHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoKHJlc3VsdCA9IFNvbGlkUGFyc2VyLkxpbmVQYXR0ZXJuMS5leGVjKGxpbmUpKSAhPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgLy9WYWx1ZSBvZiByZXN1bHRcclxuICAgICAgICAgICAgICAgIC8vW1wibCAxIDJcIl1cclxuXHJcbiAgICAgICAgICAgICAgICAvL1NldCB0aGUgZGF0YSBmb3IgdGhpcyBmYWNlXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXREYXRhRm9yQ3VycmVudEZhY2VXaXRoUGF0dGVybjEoXHJcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0WzFdLnRyaW0oKS5zcGxpdChcIiBcIiksIC8vIFtcIjFcIiwgXCIyXCJdXHJcbiAgICAgICAgICAgICAgICAgICAgMFxyXG4gICAgICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBEZWZpbmUgYSBtZXNoIG9yIGFuIG9iamVjdFxyXG4gICAgICAgICAgICAgICAgLy8gRWFjaCB0aW1lIHRoaXMga2V5d29yZCBpcyBhbmFseXplZCwgY3JlYXRlIGEgbmV3IE9iamVjdCB3aXRoIGFsbCBkYXRhIGZvciBjcmVhdGluZyBhIGJhYnlsb25NZXNoXHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoKHJlc3VsdCA9IFNvbGlkUGFyc2VyLkxpbmVQYXR0ZXJuMi5leGVjKGxpbmUpKSAhPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgLy9WYWx1ZSBvZiByZXN1bHRcclxuICAgICAgICAgICAgICAgIC8vW1wibCAxLzEgMi8yXCJdXHJcblxyXG4gICAgICAgICAgICAgICAgLy9TZXQgdGhlIGRhdGEgZm9yIHRoaXMgZmFjZVxyXG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0RGF0YUZvckN1cnJlbnRGYWNlV2l0aFBhdHRlcm4yKFxyXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFsxXS50cmltKCkuc3BsaXQoXCIgXCIpLCAvLyBbXCIxLzFcIiwgXCIyLzJcIl1cclxuICAgICAgICAgICAgICAgICAgICAwXHJcbiAgICAgICAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIERlZmluZSBhIG1lc2ggb3IgYW4gb2JqZWN0XHJcbiAgICAgICAgICAgICAgICAvLyBFYWNoIHRpbWUgdGhpcyBrZXl3b3JkIGlzIGFuYWx5emVkLCBjcmVhdGUgYSBuZXcgT2JqZWN0IHdpdGggYWxsIGRhdGEgZm9yIGNyZWF0aW5nIGEgYmFieWxvbk1lc2hcclxuICAgICAgICAgICAgfSBlbHNlIGlmICgocmVzdWx0ID0gU29saWRQYXJzZXIuTGluZVBhdHRlcm4zLmV4ZWMobGluZSkpICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAvL1ZhbHVlIG9mIHJlc3VsdFxyXG4gICAgICAgICAgICAgICAgLy9bXCJsIDEvMS8xIDIvMi8yXCJdXHJcblxyXG4gICAgICAgICAgICAgICAgLy9TZXQgdGhlIGRhdGEgZm9yIHRoaXMgZmFjZVxyXG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0RGF0YUZvckN1cnJlbnRGYWNlV2l0aFBhdHRlcm4zKFxyXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdFsxXS50cmltKCkuc3BsaXQoXCIgXCIpLCAvLyBbXCIxLzEvMVwiLCBcIjIvMi8yXCJdXHJcbiAgICAgICAgICAgICAgICAgICAgMFxyXG4gICAgICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBEZWZpbmUgYSBtZXNoIG9yIGFuIG9iamVjdFxyXG4gICAgICAgICAgICAgICAgLy8gRWFjaCB0aW1lIHRoaXMga2V5d29yZCBpcyBhbmFseXplZCwgY3JlYXRlIGEgbmV3IE9iamVjdCB3aXRoIGFsbCBkYXRhIGZvciBjcmVhdGluZyBhIGJhYnlsb25NZXNoXHJcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoU29saWRQYXJzZXIuR3JvdXBEZXNjcmlwdG9yLnRlc3QobGluZSkgfHwgU29saWRQYXJzZXIuT2JqZWN0RGVzY3JpcHRvci50ZXN0KGxpbmUpKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBDcmVhdGUgYSBuZXcgbWVzaCBjb3JyZXNwb25kaW5nIHRvIHRoZSBuYW1lIG9mIHRoZSBncm91cC5cclxuICAgICAgICAgICAgICAgIC8vIERlZmluaXRpb24gb2YgdGhlIG1lc2hcclxuICAgICAgICAgICAgICAgIGNvbnN0IG9iak1lc2g6IE1lc2hPYmplY3QgPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogbGluZS5zdWJzdHJpbmcoMikudHJpbSgpLCAvL1NldCB0aGUgbmFtZSBvZiB0aGUgY3VycmVudCBvYmogbWVzaFxyXG4gICAgICAgICAgICAgICAgICAgIGluZGljZXM6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnM6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgICAgICAgICBub3JtYWxzOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgICAgICAgICAgdXZzOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgICAgICAgICAgY29sb3JzOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWxOYW1lOiB0aGlzLl9tYXRlcmlhbE5hbWVGcm9tT2JqLFxyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2FkZFByZXZpb3VzT2JqTWVzaCgpO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vUHVzaCB0aGUgbGFzdCBtZXNoIGNyZWF0ZWQgd2l0aCBvbmx5IHRoZSBuYW1lXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9tZXNoZXNGcm9tT2JqLnB1c2gob2JqTWVzaCk7XHJcblxyXG4gICAgICAgICAgICAgICAgLy9TZXQgdGhpcyB2YXJpYWJsZSB0byBpbmRpY2F0ZSB0aGF0IG5vdyBtZXNoZXNGcm9tT2JqIGhhcyBvYmplY3RzIGRlZmluZWQgaW5zaWRlXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9oYXNNZXNoZXMgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5faXNGaXJzdE1hdGVyaWFsID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2luY3JlbWVudCA9IDE7XHJcbiAgICAgICAgICAgICAgICAvL0tleXdvcmQgZm9yIGFwcGx5aW5nIGEgbWF0ZXJpYWxcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChTb2xpZFBhcnNlci5Vc2VNdGxEZXNjcmlwdG9yLnRlc3QobGluZSkpIHtcclxuICAgICAgICAgICAgICAgIC8vR2V0IHRoZSBuYW1lIG9mIHRoZSBtYXRlcmlhbFxyXG4gICAgICAgICAgICAgICAgdGhpcy5fbWF0ZXJpYWxOYW1lRnJvbU9iaiA9IGxpbmUuc3Vic3RyaW5nKDcpLnRyaW0oKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvL0lmIHRoaXMgbmV3IG1hdGVyaWFsIGlzIGluIHRoZSBzYW1lIG1lc2hcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX2lzRmlyc3RNYXRlcmlhbCB8fCAhdGhpcy5faGFzTWVzaGVzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9TZXQgdGhlIGRhdGEgZm9yIHRoZSBwcmV2aW91cyBtZXNoXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fYWRkUHJldmlvdXNPYmpNZXNoKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgLy9DcmVhdGUgYSBuZXcgbWVzaFxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IG9iak1lc2g6IE1lc2hPYmplY3QgPVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvL1NldCB0aGUgbmFtZSBvZiB0aGUgY3VycmVudCBvYmogbWVzaFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lOiAodGhpcy5fb2JqTWVzaE5hbWUgfHwgXCJtZXNoXCIpICsgXCJfbW1cIiArIHRoaXMuX2luY3JlbWVudC50b1N0cmluZygpLCAvL1NldCB0aGUgbmFtZSBvZiB0aGUgY3VycmVudCBvYmogbWVzaFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5kaWNlczogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25zOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBub3JtYWxzOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB1dnM6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yczogdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWxOYW1lOiB0aGlzLl9tYXRlcmlhbE5hbWVGcm9tT2JqLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2luY3JlbWVudCsrO1xyXG4gICAgICAgICAgICAgICAgICAgIC8vSWYgbWVzaGVzIGFyZSBhbHJlYWR5IGRlZmluZWRcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9tZXNoZXNGcm9tT2JqLnB1c2gob2JqTWVzaCk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5faGFzTWVzaGVzID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIC8vU2V0IHRoZSBtYXRlcmlhbCBuYW1lIGlmIHRoZSBwcmV2aW91cyBsaW5lIGRlZmluZSBhIG1lc2hcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5faGFzTWVzaGVzICYmIHRoaXMuX2lzRmlyc3RNYXRlcmlhbCkge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vU2V0IHRoZSBtYXRlcmlhbCBuYW1lIHRvIHRoZSBwcmV2aW91cyBtZXNoICgxIG1hdGVyaWFsIHBlciBtZXNoKVxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX21lc2hlc0Zyb21PYmpbdGhpcy5fbWVzaGVzRnJvbU9iai5sZW5ndGggLSAxXS5tYXRlcmlhbE5hbWUgPSB0aGlzLl9tYXRlcmlhbE5hbWVGcm9tT2JqO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2lzRmlyc3RNYXRlcmlhbCA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgLy8gS2V5d29yZCBmb3IgbG9hZGluZyB0aGUgbXRsIGZpbGVcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChTb2xpZFBhcnNlci5NdGxMaWJHcm91cERlc2NyaXB0b3IudGVzdChsaW5lKSkge1xyXG4gICAgICAgICAgICAgICAgLy8gR2V0IHRoZSBuYW1lIG9mIG10bCBmaWxlXHJcbiAgICAgICAgICAgICAgICBvbkZpbGVUb0xvYWRGb3VuZChsaW5lLnN1YnN0cmluZyg3KS50cmltKCkpO1xyXG5cclxuICAgICAgICAgICAgICAgIC8vIEFwcGx5IHNtb290aGluZ1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKFNvbGlkUGFyc2VyLlNtb290aERlc2NyaXB0b3IudGVzdChsaW5lKSkge1xyXG4gICAgICAgICAgICAgICAgLy8gc21vb3RoIHNoYWRpbmcgPT4gYXBwbHkgc21vb3RoaW5nXHJcbiAgICAgICAgICAgICAgICAvLyBUb2RheSBJIGRvbid0IGtub3cgaXQgd29yayB3aXRoIGJhYnlsb24gYW5kIHdpdGggb2JqLlxyXG4gICAgICAgICAgICAgICAgLy8gV2l0aCB0aGUgb2JqIGZpbGUgIGFuIGludGVnZXIgaXMgc2V0XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvL0lmIHRoZXJlIGlzIGFub3RoZXIgcG9zc2liaWxpdHlcclxuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiVW5oYW5kbGVkIGV4cHJlc3Npb24gYXQgbGluZSA6IFwiICsgbGluZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIEF0IHRoZSBlbmQgb2YgdGhlIGZpbGUsIGFkZCB0aGUgbGFzdCBtZXNoIGludG8gdGhlIG1lc2hlc0Zyb21PYmogYXJyYXlcclxuICAgICAgICBpZiAodGhpcy5faGFzTWVzaGVzKSB7XHJcbiAgICAgICAgICAgIC8vIFNldCB0aGUgZGF0YSBmb3IgdGhlIGxhc3QgbWVzaFxyXG4gICAgICAgICAgICB0aGlzLl9oYW5kbGVkTWVzaCA9IHRoaXMuX21lc2hlc0Zyb21PYmpbdGhpcy5fbWVzaGVzRnJvbU9iai5sZW5ndGggLSAxXTtcclxuXHJcbiAgICAgICAgICAgIC8vUmV2ZXJzZSBpbmRpY2VzIGZvciBkaXNwbGF5aW5nIGZhY2VzIGluIHRoZSBnb29kIHNlbnNlXHJcbiAgICAgICAgICAgIHRoaXMuX2luZGljZXNGb3JCYWJ5bG9uLnJldmVyc2UoKTtcclxuICAgICAgICAgICAgLy9HZXQgdGhlIGdvb2QgYXJyYXlcclxuICAgICAgICAgICAgdGhpcy5fdW53cmFwRGF0YSgpO1xyXG4gICAgICAgICAgICAvL1NldCBhcnJheVxyXG4gICAgICAgICAgICB0aGlzLl9oYW5kbGVkTWVzaC5pbmRpY2VzID0gdGhpcy5faW5kaWNlc0ZvckJhYnlsb247XHJcbiAgICAgICAgICAgIHRoaXMuX2hhbmRsZWRNZXNoLnBvc2l0aW9ucyA9IHRoaXMuX3Vud3JhcHBlZFBvc2l0aW9uc0ZvckJhYnlsb247XHJcbiAgICAgICAgICAgIHRoaXMuX2hhbmRsZWRNZXNoLm5vcm1hbHMgPSB0aGlzLl91bndyYXBwZWROb3JtYWxzRm9yQmFieWxvbjtcclxuICAgICAgICAgICAgdGhpcy5faGFuZGxlZE1lc2gudXZzID0gdGhpcy5fdW53cmFwcGVkVVZGb3JCYWJ5bG9uO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuX2xvYWRpbmdPcHRpb25zLmltcG9ydFZlcnRleENvbG9ycykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5faGFuZGxlZE1lc2guY29sb3JzID0gdGhpcy5fdW53cmFwcGVkQ29sb3JzRm9yQmFieWxvbjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gSWYgYW55IG8gb3IgZyBrZXl3b3JkIG5vdCBmb3VuZCwgY3JlYXRlIGEgbWVzaCB3aXRoIGEgcmFuZG9tIGlkXHJcbiAgICAgICAgaWYgKCF0aGlzLl9oYXNNZXNoZXMpIHtcclxuICAgICAgICAgICAgbGV0IG5ld01hdGVyaWFsOiBOdWxsYWJsZTxTdGFuZGFyZE1hdGVyaWFsPiA9IG51bGw7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLl9pbmRpY2VzRm9yQmFieWxvbi5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgIC8vIHJldmVyc2UgdGFiIG9mIGluZGljZXNcclxuICAgICAgICAgICAgICAgIHRoaXMuX2luZGljZXNGb3JCYWJ5bG9uLnJldmVyc2UoKTtcclxuICAgICAgICAgICAgICAgIC8vR2V0IHBvc2l0aW9ucyBub3JtYWxzIHV2c1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fdW53cmFwRGF0YSgpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgLy8gVGhlcmUgaXMgbm8gaW5kaWNlcyBpbiB0aGUgZmlsZS4gV2Ugd2lsbCBoYXZlIHRvIHN3aXRjaCB0byBwb2ludCBjbG91ZCByZW5kZXJpbmdcclxuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgcG9zIG9mIHRoaXMuX3Bvc2l0aW9ucykge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3Vud3JhcHBlZFBvc2l0aW9uc0ZvckJhYnlsb24ucHVzaChwb3MueCwgcG9zLnksIHBvcy56KTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fbm9ybWFscy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG5vcm1hbCBvZiB0aGlzLl9ub3JtYWxzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Vud3JhcHBlZE5vcm1hbHNGb3JCYWJ5bG9uLnB1c2gobm9ybWFsLngsIG5vcm1hbC55LCBub3JtYWwueik7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLl91dnMubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCB1diBvZiB0aGlzLl91dnMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdW53cmFwcGVkVVZGb3JCYWJ5bG9uLnB1c2godXYueCwgdXYueSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9jb2xvcnMubGVuZ3RoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBjb2xvciBvZiB0aGlzLl9jb2xvcnMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdW53cmFwcGVkQ29sb3JzRm9yQmFieWxvbi5wdXNoKGNvbG9yLnIsIGNvbG9yLmcsIGNvbG9yLmIsIGNvbG9yLmEpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX21hdGVyaWFsTmFtZUZyb21PYmopIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBDcmVhdGUgYSBtYXRlcmlhbCB3aXRoIHBvaW50IGNsb3VkIG9uXHJcbiAgICAgICAgICAgICAgICAgICAgbmV3TWF0ZXJpYWwgPSBuZXcgU3RhbmRhcmRNYXRlcmlhbChHZW9tZXRyeS5SYW5kb21JZCgpLCBzY2VuZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIG5ld01hdGVyaWFsLnBvaW50c0Nsb3VkID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbWF0ZXJpYWxOYW1lRnJvbU9iaiA9IG5ld01hdGVyaWFsLm5hbWU7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5fbm9ybWFscy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbmV3TWF0ZXJpYWwuZGlzYWJsZUxpZ2h0aW5nID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbmV3TWF0ZXJpYWwuZW1pc3NpdmVDb2xvciA9IENvbG9yMy5XaGl0ZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy9TZXQgZGF0YSBmb3Igb25lIG1lc2hcclxuICAgICAgICAgICAgdGhpcy5fbWVzaGVzRnJvbU9iai5wdXNoKHtcclxuICAgICAgICAgICAgICAgIG5hbWU6IEdlb21ldHJ5LlJhbmRvbUlkKCksXHJcbiAgICAgICAgICAgICAgICBpbmRpY2VzOiB0aGlzLl9pbmRpY2VzRm9yQmFieWxvbixcclxuICAgICAgICAgICAgICAgIHBvc2l0aW9uczogdGhpcy5fdW53cmFwcGVkUG9zaXRpb25zRm9yQmFieWxvbixcclxuICAgICAgICAgICAgICAgIGNvbG9yczogdGhpcy5fdW53cmFwcGVkQ29sb3JzRm9yQmFieWxvbixcclxuICAgICAgICAgICAgICAgIG5vcm1hbHM6IHRoaXMuX3Vud3JhcHBlZE5vcm1hbHNGb3JCYWJ5bG9uLFxyXG4gICAgICAgICAgICAgICAgdXZzOiB0aGlzLl91bndyYXBwZWRVVkZvckJhYnlsb24sXHJcbiAgICAgICAgICAgICAgICBtYXRlcmlhbE5hbWU6IHRoaXMuX21hdGVyaWFsTmFtZUZyb21PYmosXHJcbiAgICAgICAgICAgICAgICBkaXJlY3RNYXRlcmlhbDogbmV3TWF0ZXJpYWwsXHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy9TZXQgZGF0YSBmb3IgZWFjaCBtZXNoXHJcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCB0aGlzLl9tZXNoZXNGcm9tT2JqLmxlbmd0aDsgaisrKSB7XHJcbiAgICAgICAgICAgIC8vY2hlY2sgbWVzaGVzTmFtZXMgKHN0bEZpbGVMb2FkZXIpXHJcbiAgICAgICAgICAgIGlmIChtZXNoZXNOYW1lcyAmJiB0aGlzLl9tZXNoZXNGcm9tT2JqW2pdLm5hbWUpIHtcclxuICAgICAgICAgICAgICAgIGlmIChtZXNoZXNOYW1lcyBpbnN0YW5jZW9mIEFycmF5KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1lc2hlc05hbWVzLmluZGV4T2YodGhpcy5fbWVzaGVzRnJvbU9ialtqXS5uYW1lKSA9PT0gLTEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fbWVzaGVzRnJvbU9ialtqXS5uYW1lICE9PSBtZXNoZXNOYW1lcykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vR2V0IHRoZSBjdXJyZW50IG1lc2hcclxuICAgICAgICAgICAgLy9TZXQgdGhlIGRhdGEgd2l0aCBWZXJ0ZXhCdWZmZXIgZm9yIGVhY2ggbWVzaFxyXG4gICAgICAgICAgICB0aGlzLl9oYW5kbGVkTWVzaCA9IHRoaXMuX21lc2hlc0Zyb21PYmpbal07XHJcbiAgICAgICAgICAgIC8vQ3JlYXRlIGEgTWVzaCB3aXRoIHRoZSBuYW1lIG9mIHRoZSBvYmogbWVzaFxyXG5cclxuICAgICAgICAgICAgc2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9ICEhYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgICAgIGNvbnN0IGJhYnlsb25NZXNoID0gbmV3IE1lc2godGhpcy5fbWVzaGVzRnJvbU9ialtqXS5uYW1lLCBzY2VuZSk7XHJcbiAgICAgICAgICAgIGJhYnlsb25NZXNoLl9wYXJlbnRDb250YWluZXIgPSBhc3NldENvbnRhaW5lcjtcclxuICAgICAgICAgICAgc2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9IGZhbHNlO1xyXG5cclxuICAgICAgICAgICAgLy9QdXNoIHRoZSBuYW1lIG9mIHRoZSBtYXRlcmlhbCB0byBhbiBhcnJheVxyXG4gICAgICAgICAgICAvL1RoaXMgaXMgaW5kaXNwZW5zYWJsZSBmb3IgdGhlIGltcG9ydE1lc2ggZnVuY3Rpb25cclxuICAgICAgICAgICAgdGhpcy5fbWF0ZXJpYWxUb1VzZS5wdXNoKHRoaXMuX21lc2hlc0Zyb21PYmpbal0ubWF0ZXJpYWxOYW1lKTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLl9oYW5kbGVkTWVzaC5wb3NpdGlvbnM/Lmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgLy9QdXNoIHRoZSBtZXNoIGludG8gYW4gYXJyYXlcclxuICAgICAgICAgICAgICAgIHRoaXMuX2JhYnlsb25NZXNoZXNBcnJheS5wdXNoKGJhYnlsb25NZXNoKTtcclxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCB2ZXJ0ZXhEYXRhOiBWZXJ0ZXhEYXRhID0gbmV3IFZlcnRleERhdGEoKTsgLy9UaGUgY29udGFpbmVyIGZvciB0aGUgdmFsdWVzXHJcbiAgICAgICAgICAgIC8vU2V0IHRoZSBkYXRhIGZvciB0aGUgYmFieWxvbk1lc2hcclxuICAgICAgICAgICAgdmVydGV4RGF0YS51dnMgPSB0aGlzLl9oYW5kbGVkTWVzaC51dnMgYXMgRmxvYXRBcnJheTtcclxuICAgICAgICAgICAgdmVydGV4RGF0YS5pbmRpY2VzID0gdGhpcy5faGFuZGxlZE1lc2guaW5kaWNlcyBhcyBJbmRpY2VzQXJyYXk7XHJcbiAgICAgICAgICAgIHZlcnRleERhdGEucG9zaXRpb25zID0gdGhpcy5faGFuZGxlZE1lc2gucG9zaXRpb25zIGFzIEZsb2F0QXJyYXk7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLl9sb2FkaW5nT3B0aW9ucy5jb21wdXRlTm9ybWFscykge1xyXG4gICAgICAgICAgICAgICAgY29uc3Qgbm9ybWFsczogQXJyYXk8bnVtYmVyPiA9IG5ldyBBcnJheTxudW1iZXI+KCk7XHJcbiAgICAgICAgICAgICAgICBWZXJ0ZXhEYXRhLkNvbXB1dGVOb3JtYWxzKHRoaXMuX2hhbmRsZWRNZXNoLnBvc2l0aW9ucywgdGhpcy5faGFuZGxlZE1lc2guaW5kaWNlcywgbm9ybWFscyk7XHJcbiAgICAgICAgICAgICAgICB2ZXJ0ZXhEYXRhLm5vcm1hbHMgPSBub3JtYWxzO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdmVydGV4RGF0YS5ub3JtYWxzID0gdGhpcy5faGFuZGxlZE1lc2gubm9ybWFscyBhcyBGbG9hdEFycmF5O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGlmICh0aGlzLl9sb2FkaW5nT3B0aW9ucy5pbXBvcnRWZXJ0ZXhDb2xvcnMpIHtcclxuICAgICAgICAgICAgICAgIHZlcnRleERhdGEuY29sb3JzID0gdGhpcy5faGFuZGxlZE1lc2guY29sb3JzIGFzIEZsb2F0QXJyYXk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy9TZXQgdGhlIGRhdGEgZnJvbSB0aGUgVmVydGV4QnVmZmVyIHRvIHRoZSBjdXJyZW50IE1lc2hcclxuICAgICAgICAgICAgdmVydGV4RGF0YS5hcHBseVRvTWVzaChiYWJ5bG9uTWVzaCk7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLl9sb2FkaW5nT3B0aW9ucy5pbnZlcnRZKSB7XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uTWVzaC5zY2FsaW5nLnkgKj0gLTE7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKHRoaXMuX2xvYWRpbmdPcHRpb25zLm9wdGltaXplTm9ybWFscykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fb3B0aW1pemVOb3JtYWxzKGJhYnlsb25NZXNoKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy9QdXNoIHRoZSBtZXNoIGludG8gYW4gYXJyYXlcclxuICAgICAgICAgICAgdGhpcy5fYmFieWxvbk1lc2hlc0FycmF5LnB1c2goYmFieWxvbk1lc2gpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuX2hhbmRsZWRNZXNoLmRpcmVjdE1hdGVyaWFsKSB7XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uTWVzaC5tYXRlcmlhbCA9IHRoaXMuX2hhbmRsZWRNZXNoLmRpcmVjdE1hdGVyaWFsO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcbiIsImV4cG9ydCAqIGZyb20gXCIuL3N0bEZpbGVMb2FkZXJcIjtcclxuIiwiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uICovXHJcbmltcG9ydCB0eXBlIHsgTnVsbGFibGUgfSBmcm9tIFwiY29yZS90eXBlc1wiO1xyXG5pbXBvcnQgeyBUb29scyB9IGZyb20gXCJjb3JlL01pc2MvdG9vbHNcIjtcclxuaW1wb3J0IHsgVmVydGV4QnVmZmVyIH0gZnJvbSBcImNvcmUvQnVmZmVycy9idWZmZXJcIjtcclxuaW1wb3J0IHR5cGUgeyBBYnN0cmFjdE1lc2ggfSBmcm9tIFwiY29yZS9NZXNoZXMvYWJzdHJhY3RNZXNoXCI7XHJcbmltcG9ydCB7IE1lc2ggfSBmcm9tIFwiY29yZS9NZXNoZXMvbWVzaFwiO1xyXG5pbXBvcnQgdHlwZSB7IElTY2VuZUxvYWRlclBsdWdpbiwgSVNjZW5lTG9hZGVyUGx1Z2luRXh0ZW5zaW9ucyB9IGZyb20gXCJjb3JlL0xvYWRpbmcvc2NlbmVMb2FkZXJcIjtcclxuaW1wb3J0IHsgU2NlbmVMb2FkZXIgfSBmcm9tIFwiY29yZS9Mb2FkaW5nL3NjZW5lTG9hZGVyXCI7XHJcbmltcG9ydCB7IEFzc2V0Q29udGFpbmVyIH0gZnJvbSBcImNvcmUvYXNzZXRDb250YWluZXJcIjtcclxuaW1wb3J0IHR5cGUgeyBTY2VuZSB9IGZyb20gXCJjb3JlL3NjZW5lXCI7XHJcblxyXG4vKipcclxuICogU1RMIGZpbGUgdHlwZSBsb2FkZXIuXHJcbiAqIFRoaXMgaXMgYSBiYWJ5bG9uIHNjZW5lIGxvYWRlciBwbHVnaW4uXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgU1RMRmlsZUxvYWRlciBpbXBsZW1lbnRzIElTY2VuZUxvYWRlclBsdWdpbiB7XHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgc29saWRQYXR0ZXJuID0gL3NvbGlkIChcXFMqKShbXFxTXFxzXSo/KWVuZHNvbGlkWyBdKihcXFMqKS9nO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBmYWNldHNQYXR0ZXJuID0gL2ZhY2V0KFtcXHNcXFNdKj8pZW5kZmFjZXQvZztcclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBub3JtYWxQYXR0ZXJuID0gL25vcm1hbFtcXHNdKyhbLStdP1swLTldK1xcLj9bMC05XSooW2VFXVstK10/WzAtOV0rKT8pK1tcXHNdKyhbLStdP1swLTldKlxcLj9bMC05XSsoW2VFXVstK10/WzAtOV0rKT8pK1tcXHNdKyhbLStdP1swLTldKlxcLj9bMC05XSsoW2VFXVstK10/WzAtOV0rKT8pKy9nO1xyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIHZlcnRleFBhdHRlcm4gPSAvdmVydGV4W1xcc10rKFstK10/WzAtOV0rXFwuP1swLTldKihbZUVdWy0rXT9bMC05XSspPykrW1xcc10rKFstK10/WzAtOV0qXFwuP1swLTldKyhbZUVdWy0rXT9bMC05XSspPykrW1xcc10rKFstK10/WzAtOV0qXFwuP1swLTldKyhbZUVdWy0rXT9bMC05XSspPykrL2c7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHRoZSBuYW1lIG9mIHRoZSBwbHVnaW4uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBuYW1lID0gXCJzdGxcIjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgdGhlIGV4dGVuc2lvbnMgdGhlIHN0bCBsb2FkZXIgaXMgYWJsZSB0byBsb2FkLlxyXG4gICAgICogZm9yY2UgZGF0YSB0byBjb21lIGluIGFzIGFuIEFycmF5QnVmZmVyXHJcbiAgICAgKiB3ZSdsbCBjb252ZXJ0IHRvIHN0cmluZyBpZiBpdCBsb29rcyBsaWtlIGl0J3MgYW4gQVNDSUkgLnN0bFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZXh0ZW5zaW9uczogSVNjZW5lTG9hZGVyUGx1Z2luRXh0ZW5zaW9ucyA9IHtcclxuICAgICAgICBcIi5zdGxcIjogeyBpc0JpbmFyeTogdHJ1ZSB9LFxyXG4gICAgfTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgaWYgWSBhbmQgWiBheGVzIGFyZSBzd2FwcGVkIG9yIG5vdCB3aGVuIGxvYWRpbmcgYW4gU1RMIGZpbGUuXHJcbiAgICAgKiBUaGUgZGVmYXVsdCBpcyBmYWxzZSB0byBtYWludGFpbiBiYWNrd2FyZCBjb21wYXRpYmlsaXR5LiBXaGVuIHNldCB0b1xyXG4gICAgICogdHJ1ZSwgY29vcmRpbmF0ZXMgZnJvbSB0aGUgU1RMIGZpbGUgYXJlIHVzZWQgd2l0aG91dCBjaGFuZ2UuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgRE9fTk9UX0FMVEVSX0ZJTEVfQ09PUkRJTkFURVMgPSBmYWxzZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEltcG9ydCBtZXNoZXMgaW50byBhIHNjZW5lLlxyXG4gICAgICogQHBhcmFtIG1lc2hlc05hbWVzIEFuIGFycmF5IG9mIG1lc2ggbmFtZXMsIGEgc2luZ2xlIG1lc2ggbmFtZSwgb3IgZW1wdHkgc3RyaW5nIGZvciBhbGwgbWVzaGVzIHRoYXQgZmlsdGVyIHdoYXQgbWVzaGVzIGFyZSBpbXBvcnRlZFxyXG4gICAgICogQHBhcmFtIHNjZW5lIFRoZSBzY2VuZSB0byBpbXBvcnQgaW50b1xyXG4gICAgICogQHBhcmFtIGRhdGEgVGhlIGRhdGEgdG8gaW1wb3J0XHJcbiAgICAgKiBAcGFyYW0gcm9vdFVybCBUaGUgcm9vdCB1cmwgZm9yIHNjZW5lIGFuZCByZXNvdXJjZXNcclxuICAgICAqIEBwYXJhbSBtZXNoZXMgVGhlIG1lc2hlcyBhcnJheSB0byBpbXBvcnQgaW50b1xyXG4gICAgICogQHJldHVybnMgVHJ1ZSBpZiBzdWNjZXNzZnVsIG9yIGZhbHNlIG90aGVyd2lzZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgaW1wb3J0TWVzaChtZXNoZXNOYW1lczogYW55LCBzY2VuZTogU2NlbmUsIGRhdGE6IGFueSwgcm9vdFVybDogc3RyaW5nLCBtZXNoZXM6IE51bGxhYmxlPEFic3RyYWN0TWVzaFtdPik6IGJvb2xlYW4ge1xyXG4gICAgICAgIGxldCBtYXRjaGVzO1xyXG5cclxuICAgICAgICBpZiAodHlwZW9mIGRhdGEgIT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMuX2lzQmluYXJ5KGRhdGEpKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBiaW5hcnkgLnN0bFxyXG4gICAgICAgICAgICAgICAgY29uc3QgYmFieWxvbk1lc2ggPSBuZXcgTWVzaChcInN0bG1lc2hcIiwgc2NlbmUpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fcGFyc2VCaW5hcnkoYmFieWxvbk1lc2gsIGRhdGEpO1xyXG4gICAgICAgICAgICAgICAgaWYgKG1lc2hlcykge1xyXG4gICAgICAgICAgICAgICAgICAgIG1lc2hlcy5wdXNoKGJhYnlsb25NZXNoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBBU0NJSSAuc3RsXHJcblxyXG4gICAgICAgICAgICAvLyBjb252ZXJ0IHRvIHN0cmluZ1xyXG4gICAgICAgICAgICBkYXRhID0gbmV3IFRleHREZWNvZGVyKCkuZGVjb2RlKG5ldyBVaW50OEFycmF5KGRhdGEpKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vaWYgYXJyaXZlZCBoZXJlLCBkYXRhIGlzIGEgc3RyaW5nLCBjb250YWluaW5nIHRoZSBTVExBIGRhdGEuXHJcblxyXG4gICAgICAgIHdoaWxlICgobWF0Y2hlcyA9IHRoaXMuc29saWRQYXR0ZXJuLmV4ZWMoZGF0YSkpKSB7XHJcbiAgICAgICAgICAgIGxldCBtZXNoTmFtZSA9IG1hdGNoZXNbMV07XHJcbiAgICAgICAgICAgIGNvbnN0IG1lc2hOYW1lRnJvbUVuZCA9IG1hdGNoZXNbM107XHJcbiAgICAgICAgICAgIGlmIChtZXNoTmFtZUZyb21FbmQgJiYgbWVzaE5hbWUgIT0gbWVzaE5hbWVGcm9tRW5kKSB7XHJcbiAgICAgICAgICAgICAgICBUb29scy5FcnJvcihcIkVycm9yIGluIFNUTCwgc29saWQgbmFtZSAhPSBlbmRzb2xpZCBuYW1lXCIpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBjaGVjayBtZXNoZXNOYW1lc1xyXG4gICAgICAgICAgICBpZiAobWVzaGVzTmFtZXMgJiYgbWVzaE5hbWUpIHtcclxuICAgICAgICAgICAgICAgIGlmIChtZXNoZXNOYW1lcyBpbnN0YW5jZW9mIEFycmF5KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFtZXNoZXNOYW1lcy5pbmRleE9mKG1lc2hOYW1lKSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChtZXNoTmFtZSAhPT0gbWVzaGVzTmFtZXMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBzdGwgbWVzaCBuYW1lIGNhbiBiZSBlbXB0eSBhcyB3ZWxsXHJcbiAgICAgICAgICAgIG1lc2hOYW1lID0gbWVzaE5hbWUgfHwgXCJzdGxtZXNoXCI7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBiYWJ5bG9uTWVzaCA9IG5ldyBNZXNoKG1lc2hOYW1lLCBzY2VuZSk7XHJcbiAgICAgICAgICAgIHRoaXMuX3BhcnNlQVNDSUkoYmFieWxvbk1lc2gsIG1hdGNoZXNbMl0pO1xyXG4gICAgICAgICAgICBpZiAobWVzaGVzKSB7XHJcbiAgICAgICAgICAgICAgICBtZXNoZXMucHVzaChiYWJ5bG9uTWVzaCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTG9hZCBpbnRvIGEgc2NlbmUuXHJcbiAgICAgKiBAcGFyYW0gc2NlbmUgVGhlIHNjZW5lIHRvIGxvYWQgaW50b1xyXG4gICAgICogQHBhcmFtIGRhdGEgVGhlIGRhdGEgdG8gaW1wb3J0XHJcbiAgICAgKiBAcGFyYW0gcm9vdFVybCBUaGUgcm9vdCB1cmwgZm9yIHNjZW5lIGFuZCByZXNvdXJjZXNcclxuICAgICAqIEByZXR1cm5zIHRydWUgaWYgc3VjY2Vzc2Z1bCBvciBmYWxzZSBvdGhlcndpc2VcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWQoc2NlbmU6IFNjZW5lLCBkYXRhOiBhbnksIHJvb3RVcmw6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IHRoaXMuaW1wb3J0TWVzaChudWxsLCBzY2VuZSwgZGF0YSwgcm9vdFVybCwgbnVsbCk7XHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIExvYWQgaW50byBhbiBhc3NldCBjb250YWluZXIuXHJcbiAgICAgKiBAcGFyYW0gc2NlbmUgVGhlIHNjZW5lIHRvIGxvYWQgaW50b1xyXG4gICAgICogQHBhcmFtIGRhdGEgVGhlIGRhdGEgdG8gaW1wb3J0XHJcbiAgICAgKiBAcGFyYW0gcm9vdFVybCBUaGUgcm9vdCB1cmwgZm9yIHNjZW5lIGFuZCByZXNvdXJjZXNcclxuICAgICAqIEByZXR1cm5zIFRoZSBsb2FkZWQgYXNzZXQgY29udGFpbmVyXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkQXNzZXRDb250YWluZXIoc2NlbmU6IFNjZW5lLCBkYXRhOiBzdHJpbmcsIHJvb3RVcmw6IHN0cmluZyk6IEFzc2V0Q29udGFpbmVyIHtcclxuICAgICAgICBjb25zdCBjb250YWluZXIgPSBuZXcgQXNzZXRDb250YWluZXIoc2NlbmUpO1xyXG4gICAgICAgIHNjZW5lLl9ibG9ja0VudGl0eUNvbGxlY3Rpb24gPSB0cnVlO1xyXG4gICAgICAgIHRoaXMuaW1wb3J0TWVzaChudWxsLCBzY2VuZSwgZGF0YSwgcm9vdFVybCwgY29udGFpbmVyLm1lc2hlcyk7XHJcbiAgICAgICAgc2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9IGZhbHNlO1xyXG4gICAgICAgIHJldHVybiBjb250YWluZXI7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfaXNCaW5hcnkoZGF0YTogYW55KSB7XHJcbiAgICAgICAgLy8gY2hlY2sgaWYgZmlsZSBzaXplIGlzIGNvcnJlY3QgZm9yIGJpbmFyeSBzdGxcclxuICAgICAgICBjb25zdCByZWFkZXIgPSBuZXcgRGF0YVZpZXcoZGF0YSk7XHJcblxyXG4gICAgICAgIC8vIEEgQmluYXJ5IFNUTCBoZWFkZXIgaXMgODAgYnl0ZXMsIGlmIHRoZSBkYXRhIHNpemUgaXMgbm90IGdyZWF0IHRoYW5cclxuICAgICAgICAvLyB0aGF0IHRoZW4gaXQncyBub3QgYSBiaW5hcnkgU1RMLlxyXG4gICAgICAgIGlmIChyZWFkZXIuYnl0ZUxlbmd0aCA8PSA4MCkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBmYWNlU2l6ZSA9ICgzMiAvIDgpICogMyArICgzMiAvIDgpICogMyAqIDMgKyAxNiAvIDg7XHJcbiAgICAgICAgY29uc3QgbkZhY2VzID0gcmVhZGVyLmdldFVpbnQzMig4MCwgdHJ1ZSk7XHJcblxyXG4gICAgICAgIGlmICg4MCArIDMyIC8gOCArIG5GYWNlcyAqIGZhY2VTaXplID09PSByZWFkZXIuYnl0ZUxlbmd0aCkge1xyXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFVTLUFTQ0lJIGJlZ2luIHdpdGggJ3MnLCAnbycsICdsJywgJ2knLCAnZCdcclxuICAgICAgICBjb25zdCBhc2NpaSA9IFsxMTUsIDExMSwgMTA4LCAxMDUsIDEwMF07XHJcbiAgICAgICAgZm9yIChsZXQgb2ZmID0gMDsgb2ZmIDwgNTsgb2ZmKyspIHtcclxuICAgICAgICAgICAgaWYgKHJlYWRlci5nZXRVaW50OChvZmYpICE9PSBhc2NpaVtvZmZdKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX3BhcnNlQmluYXJ5KG1lc2g6IE1lc2gsIGRhdGE6IEFycmF5QnVmZmVyKSB7XHJcbiAgICAgICAgY29uc3QgcmVhZGVyID0gbmV3IERhdGFWaWV3KGRhdGEpO1xyXG4gICAgICAgIGNvbnN0IGZhY2VzID0gcmVhZGVyLmdldFVpbnQzMig4MCwgdHJ1ZSk7XHJcblxyXG4gICAgICAgIGNvbnN0IGRhdGFPZmZzZXQgPSA4NDtcclxuICAgICAgICBjb25zdCBmYWNlTGVuZ3RoID0gMTIgKiA0ICsgMjtcclxuXHJcbiAgICAgICAgbGV0IG9mZnNldCA9IDA7XHJcblxyXG4gICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IG5ldyBGbG9hdDMyQXJyYXkoZmFjZXMgKiAzICogMyk7XHJcbiAgICAgICAgY29uc3Qgbm9ybWFscyA9IG5ldyBGbG9hdDMyQXJyYXkoZmFjZXMgKiAzICogMyk7XHJcbiAgICAgICAgY29uc3QgaW5kaWNlcyA9IG5ldyBVaW50MzJBcnJheShmYWNlcyAqIDMpO1xyXG4gICAgICAgIGxldCBpbmRpY2VzQ291bnQgPSAwO1xyXG5cclxuICAgICAgICBmb3IgKGxldCBmYWNlID0gMDsgZmFjZSA8IGZhY2VzOyBmYWNlKyspIHtcclxuICAgICAgICAgICAgY29uc3Qgc3RhcnQgPSBkYXRhT2Zmc2V0ICsgZmFjZSAqIGZhY2VMZW5ndGg7XHJcbiAgICAgICAgICAgIGNvbnN0IG5vcm1hbFggPSByZWFkZXIuZ2V0RmxvYXQzMihzdGFydCwgdHJ1ZSk7XHJcbiAgICAgICAgICAgIGNvbnN0IG5vcm1hbFkgPSByZWFkZXIuZ2V0RmxvYXQzMihzdGFydCArIDQsIHRydWUpO1xyXG4gICAgICAgICAgICBjb25zdCBub3JtYWxaID0gcmVhZGVyLmdldEZsb2F0MzIoc3RhcnQgKyA4LCB0cnVlKTtcclxuXHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAxOyBpIDw9IDM7IGkrKykge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdmVydGV4c3RhcnQgPSBzdGFydCArIGkgKiAxMjtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBvcmRlcmluZyBpcyBpbnRlbnRpb25hbCB0byBtYXRjaCBhc2NpaSBpbXBvcnRcclxuICAgICAgICAgICAgICAgIHBvc2l0aW9uc1tvZmZzZXRdID0gcmVhZGVyLmdldEZsb2F0MzIodmVydGV4c3RhcnQsIHRydWUpO1xyXG4gICAgICAgICAgICAgICAgbm9ybWFsc1tvZmZzZXRdID0gbm9ybWFsWDtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoIVNUTEZpbGVMb2FkZXIuRE9fTk9UX0FMVEVSX0ZJTEVfQ09PUkRJTkFURVMpIHtcclxuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgMl0gPSByZWFkZXIuZ2V0RmxvYXQzMih2ZXJ0ZXhzdGFydCArIDQsIHRydWUpO1xyXG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyAxXSA9IHJlYWRlci5nZXRGbG9hdDMyKHZlcnRleHN0YXJ0ICsgOCwgdHJ1ZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIG5vcm1hbHNbb2Zmc2V0ICsgMl0gPSBub3JtYWxZO1xyXG4gICAgICAgICAgICAgICAgICAgIG5vcm1hbHNbb2Zmc2V0ICsgMV0gPSBub3JtYWxaO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbnNbb2Zmc2V0ICsgMV0gPSByZWFkZXIuZ2V0RmxvYXQzMih2ZXJ0ZXhzdGFydCArIDQsIHRydWUpO1xyXG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uc1tvZmZzZXQgKyAyXSA9IHJlYWRlci5nZXRGbG9hdDMyKHZlcnRleHN0YXJ0ICsgOCwgdHJ1ZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIG5vcm1hbHNbb2Zmc2V0ICsgMV0gPSBub3JtYWxZO1xyXG4gICAgICAgICAgICAgICAgICAgIG5vcm1hbHNbb2Zmc2V0ICsgMl0gPSBub3JtYWxaO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIG9mZnNldCArPSAzO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoU1RMRmlsZUxvYWRlci5ET19OT1RfQUxURVJfRklMRV9DT09SRElOQVRFUykge1xyXG4gICAgICAgICAgICAgICAgaW5kaWNlc1tpbmRpY2VzQ291bnRdID0gaW5kaWNlc0NvdW50O1xyXG4gICAgICAgICAgICAgICAgaW5kaWNlc1tpbmRpY2VzQ291bnQgKyAxXSA9IGluZGljZXNDb3VudCArIDI7XHJcbiAgICAgICAgICAgICAgICBpbmRpY2VzW2luZGljZXNDb3VudCArIDJdID0gaW5kaWNlc0NvdW50ICsgMTtcclxuICAgICAgICAgICAgICAgIGluZGljZXNDb3VudCArPSAzO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgaW5kaWNlc1tpbmRpY2VzQ291bnRdID0gaW5kaWNlc0NvdW50Kys7XHJcbiAgICAgICAgICAgICAgICBpbmRpY2VzW2luZGljZXNDb3VudF0gPSBpbmRpY2VzQ291bnQrKztcclxuICAgICAgICAgICAgICAgIGluZGljZXNbaW5kaWNlc0NvdW50XSA9IGluZGljZXNDb3VudCsrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBtZXNoLnNldFZlcnRpY2VzRGF0YShWZXJ0ZXhCdWZmZXIuUG9zaXRpb25LaW5kLCBwb3NpdGlvbnMpO1xyXG4gICAgICAgIG1lc2guc2V0VmVydGljZXNEYXRhKFZlcnRleEJ1ZmZlci5Ob3JtYWxLaW5kLCBub3JtYWxzKTtcclxuICAgICAgICBtZXNoLnNldEluZGljZXMoaW5kaWNlcyk7XHJcbiAgICAgICAgbWVzaC5jb21wdXRlV29ybGRNYXRyaXgodHJ1ZSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfcGFyc2VBU0NJSShtZXNoOiBNZXNoLCBzb2xpZERhdGE6IHN0cmluZykge1xyXG4gICAgICAgIGNvbnN0IHBvc2l0aW9ucyA9IFtdO1xyXG4gICAgICAgIGNvbnN0IG5vcm1hbHMgPSBbXTtcclxuICAgICAgICBjb25zdCBpbmRpY2VzID0gW107XHJcbiAgICAgICAgbGV0IGluZGljZXNDb3VudCA9IDA7XHJcblxyXG4gICAgICAgIC8vbG9hZCBmYWNldHMsIGlnbm9yaW5nIGxvb3AgYXMgdGhlIHN0YW5kYXJkIGRvZXNuJ3QgZGVmaW5lIGl0IGNhbiBjb250YWluIG1vcmUgdGhhbiB2ZXJ0aWNlc1xyXG4gICAgICAgIGxldCBtYXRjaGVzO1xyXG4gICAgICAgIHdoaWxlICgobWF0Y2hlcyA9IHRoaXMuZmFjZXRzUGF0dGVybi5leGVjKHNvbGlkRGF0YSkpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGZhY2V0ID0gbWF0Y2hlc1sxXTtcclxuICAgICAgICAgICAgLy9vbmUgbm9ybWFsIHBlciBmYWNlXHJcbiAgICAgICAgICAgIGNvbnN0IG5vcm1hbE1hdGNoZXMgPSB0aGlzLm5vcm1hbFBhdHRlcm4uZXhlYyhmYWNldCk7XHJcbiAgICAgICAgICAgIHRoaXMubm9ybWFsUGF0dGVybi5sYXN0SW5kZXggPSAwO1xyXG4gICAgICAgICAgICBpZiAoIW5vcm1hbE1hdGNoZXMpIHtcclxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNvbnN0IG5vcm1hbCA9IFtOdW1iZXIobm9ybWFsTWF0Y2hlc1sxXSksIE51bWJlcihub3JtYWxNYXRjaGVzWzVdKSwgTnVtYmVyKG5vcm1hbE1hdGNoZXNbM10pXTtcclxuXHJcbiAgICAgICAgICAgIGxldCB2ZXJ0ZXhNYXRjaDtcclxuICAgICAgICAgICAgd2hpbGUgKCh2ZXJ0ZXhNYXRjaCA9IHRoaXMudmVydGV4UGF0dGVybi5leGVjKGZhY2V0KSkpIHtcclxuICAgICAgICAgICAgICAgIGlmICghU1RMRmlsZUxvYWRlci5ET19OT1RfQUxURVJfRklMRV9DT09SRElOQVRFUykge1xyXG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9ucy5wdXNoKE51bWJlcih2ZXJ0ZXhNYXRjaFsxXSksIE51bWJlcih2ZXJ0ZXhNYXRjaFs1XSksIE51bWJlcih2ZXJ0ZXhNYXRjaFszXSkpO1xyXG4gICAgICAgICAgICAgICAgICAgIG5vcm1hbHMucHVzaChub3JtYWxbMF0sIG5vcm1hbFsxXSwgbm9ybWFsWzJdKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb25zLnB1c2goTnVtYmVyKHZlcnRleE1hdGNoWzFdKSwgTnVtYmVyKHZlcnRleE1hdGNoWzNdKSwgTnVtYmVyKHZlcnRleE1hdGNoWzVdKSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vIEZsaXBwaW5nIHRoZSBzZWNvbmQgYW5kIHRoaXJkIGNvbXBvbmVudCBiZWNhdXNlIGludmVydGVkXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gd2hlbiBub3JtYWwgd2FzIGRlY2xhcmVkLlxyXG4gICAgICAgICAgICAgICAgICAgIG5vcm1hbHMucHVzaChub3JtYWxbMF0sIG5vcm1hbFsyXSwgbm9ybWFsWzFdKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBpZiAoU1RMRmlsZUxvYWRlci5ET19OT1RfQUxURVJfRklMRV9DT09SRElOQVRFUykge1xyXG4gICAgICAgICAgICAgICAgaW5kaWNlcy5wdXNoKGluZGljZXNDb3VudCwgaW5kaWNlc0NvdW50ICsgMiwgaW5kaWNlc0NvdW50ICsgMSk7XHJcbiAgICAgICAgICAgICAgICBpbmRpY2VzQ291bnQgKz0gMztcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGluZGljZXMucHVzaChpbmRpY2VzQ291bnQrKywgaW5kaWNlc0NvdW50KyssIGluZGljZXNDb3VudCsrKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB0aGlzLnZlcnRleFBhdHRlcm4ubGFzdEluZGV4ID0gMDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuZmFjZXRzUGF0dGVybi5sYXN0SW5kZXggPSAwO1xyXG4gICAgICAgIG1lc2guc2V0VmVydGljZXNEYXRhKFZlcnRleEJ1ZmZlci5Qb3NpdGlvbktpbmQsIHBvc2l0aW9ucyk7XHJcbiAgICAgICAgbWVzaC5zZXRWZXJ0aWNlc0RhdGEoVmVydGV4QnVmZmVyLk5vcm1hbEtpbmQsIG5vcm1hbHMpO1xyXG4gICAgICAgIG1lc2guc2V0SW5kaWNlcyhpbmRpY2VzKTtcclxuICAgICAgICBtZXNoLmNvbXB1dGVXb3JsZE1hdHJpeCh0cnVlKTtcclxuICAgIH1cclxufVxyXG5cclxuaWYgKFNjZW5lTG9hZGVyKSB7XHJcbiAgICBTY2VuZUxvYWRlci5SZWdpc3RlclBsdWdpbihuZXcgU1RMRmlsZUxvYWRlcigpKTtcclxufVxyXG4iLCJpbXBvcnQgeyBHTFRGTG9hZGVyRXh0ZW5zaW9uLCBHTFRGTG9hZGVyLCBHTFRGTG9hZGVyQmFzZSB9IGZyb20gXCIuL2dsVEZMb2FkZXJcIjtcclxuaW1wb3J0IHsgR0xURlV0aWxzIH0gZnJvbSBcIi4vZ2xURkxvYWRlclV0aWxzXCI7XHJcbmltcG9ydCB0eXBlIHsgU2NlbmUgfSBmcm9tIFwiY29yZS9zY2VuZVwiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRGF0YSB9IGZyb20gXCIuLi9nbFRGRmlsZUxvYWRlclwiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGUnVudGltZSwgSUdMVEZUZXh0dXJlLCBJR0xURkltYWdlLCBJR0xURkJ1ZmZlclZpZXcsIElHTFRGU2hhZGVyIH0gZnJvbSBcIi4vZ2xURkxvYWRlckludGVyZmFjZXNcIjtcclxuaW1wb3J0IHsgRUNvbXBvbmVudFR5cGUgfSBmcm9tIFwiLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5cclxuaW1wb3J0IHR5cGUgeyBJRGF0YUJ1ZmZlciB9IGZyb20gXCJjb3JlL01pc2MvZGF0YVJlYWRlclwiO1xyXG5cclxuY29uc3QgQmluYXJ5RXh0ZW5zaW9uQnVmZmVyTmFtZSA9IFwiYmluYXJ5X2dsVEZcIjtcclxuXHJcbmludGVyZmFjZSBJR0xURkJpbmFyeUV4dGVuc2lvblNoYWRlciB7XHJcbiAgICBidWZmZXJWaWV3OiBzdHJpbmc7XHJcbn1cclxuXHJcbmludGVyZmFjZSBJR0xURkJpbmFyeUV4dGVuc2lvbkltYWdlIHtcclxuICAgIGJ1ZmZlclZpZXc6IHN0cmluZztcclxuICAgIG1pbWVUeXBlOiBzdHJpbmc7XHJcbiAgICBoZWlnaHQ6IG51bWJlcjtcclxuICAgIHdpZHRoOiBudW1iZXI7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBAaW50ZXJuYWxcclxuICogQGRlcHJlY2F0ZWRcclxuICovXHJcbmV4cG9ydCBjbGFzcyBHTFRGQmluYXJ5RXh0ZW5zaW9uIGV4dGVuZHMgR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICBwcml2YXRlIF9iaW46IElEYXRhQnVmZmVyO1xyXG5cclxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcigpIHtcclxuICAgICAgICBzdXBlcihcIktIUl9iaW5hcnlfZ2xURlwiKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgbG9hZFJ1bnRpbWVBc3luYyhzY2VuZTogU2NlbmUsIGRhdGE6IElHTFRGTG9hZGVyRGF0YSwgcm9vdFVybDogc3RyaW5nLCBvblN1Y2Nlc3M6IChnbHRmUnVudGltZTogSUdMVEZSdW50aW1lKSA9PiB2b2lkKTogYm9vbGVhbiB7XHJcbiAgICAgICAgY29uc3QgZXh0ZW5zaW9uc1VzZWQgPSAoPGFueT5kYXRhLmpzb24pLmV4dGVuc2lvbnNVc2VkO1xyXG4gICAgICAgIGlmICghZXh0ZW5zaW9uc1VzZWQgfHwgZXh0ZW5zaW9uc1VzZWQuaW5kZXhPZih0aGlzLm5hbWUpID09PSAtMSB8fCAhZGF0YS5iaW4pIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5fYmluID0gZGF0YS5iaW47XHJcbiAgICAgICAgb25TdWNjZXNzKEdMVEZMb2FkZXJCYXNlLkNyZWF0ZVJ1bnRpbWUoZGF0YS5qc29uLCBzY2VuZSwgcm9vdFVybCkpO1xyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBsb2FkQnVmZmVyQXN5bmMoZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSwgaWQ6IHN0cmluZywgb25TdWNjZXNzOiAoYnVmZmVyOiBBcnJheUJ1ZmZlclZpZXcpID0+IHZvaWQsIG9uRXJyb3I6IChtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQpOiBib29sZWFuIHtcclxuICAgICAgICBpZiAoZ2x0ZlJ1bnRpbWUuZXh0ZW5zaW9uc1VzZWQuaW5kZXhPZih0aGlzLm5hbWUpID09PSAtMSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoaWQgIT09IEJpbmFyeUV4dGVuc2lvbkJ1ZmZlck5hbWUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5fYmluLnJlYWRBc3luYygwLCB0aGlzLl9iaW4uYnl0ZUxlbmd0aCkudGhlbihvblN1Y2Nlc3MsIChlcnJvcikgPT4gb25FcnJvcihlcnJvci5tZXNzYWdlKSk7XHJcbiAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGxvYWRUZXh0dXJlQnVmZmVyQXN5bmMoZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSwgaWQ6IHN0cmluZywgb25TdWNjZXNzOiAoYnVmZmVyOiBBcnJheUJ1ZmZlclZpZXcpID0+IHZvaWQpOiBib29sZWFuIHtcclxuICAgICAgICBjb25zdCB0ZXh0dXJlOiBJR0xURlRleHR1cmUgPSBnbHRmUnVudGltZS50ZXh0dXJlc1tpZF07XHJcbiAgICAgICAgY29uc3Qgc291cmNlOiBJR0xURkltYWdlID0gZ2x0ZlJ1bnRpbWUuaW1hZ2VzW3RleHR1cmUuc291cmNlXTtcclxuICAgICAgICBpZiAoIXNvdXJjZS5leHRlbnNpb25zIHx8ICEodGhpcy5uYW1lIGluIHNvdXJjZS5leHRlbnNpb25zKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBzb3VyY2VFeHQ6IElHTFRGQmluYXJ5RXh0ZW5zaW9uSW1hZ2UgPSBzb3VyY2UuZXh0ZW5zaW9uc1t0aGlzLm5hbWVdO1xyXG4gICAgICAgIGNvbnN0IGJ1ZmZlclZpZXc6IElHTFRGQnVmZmVyVmlldyA9IGdsdGZSdW50aW1lLmJ1ZmZlclZpZXdzW3NvdXJjZUV4dC5idWZmZXJWaWV3XTtcclxuICAgICAgICBjb25zdCBidWZmZXIgPSBHTFRGVXRpbHMuR2V0QnVmZmVyRnJvbUJ1ZmZlclZpZXcoZ2x0ZlJ1bnRpbWUsIGJ1ZmZlclZpZXcsIDAsIGJ1ZmZlclZpZXcuYnl0ZUxlbmd0aCwgRUNvbXBvbmVudFR5cGUuVU5TSUdORURfQllURSk7XHJcbiAgICAgICAgb25TdWNjZXNzKGJ1ZmZlcik7XHJcbiAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGxvYWRTaGFkZXJTdHJpbmdBc3luYyhnbHRmUnVudGltZTogSUdMVEZSdW50aW1lLCBpZDogc3RyaW5nLCBvblN1Y2Nlc3M6IChzaGFkZXJTdHJpbmc6IHN0cmluZykgPT4gdm9pZCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGNvbnN0IHNoYWRlcjogSUdMVEZTaGFkZXIgPSBnbHRmUnVudGltZS5zaGFkZXJzW2lkXTtcclxuICAgICAgICBpZiAoIXNoYWRlci5leHRlbnNpb25zIHx8ICEodGhpcy5uYW1lIGluIHNoYWRlci5leHRlbnNpb25zKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBiaW5hcnlFeHRlbnNpb25TaGFkZXI6IElHTFRGQmluYXJ5RXh0ZW5zaW9uU2hhZGVyID0gc2hhZGVyLmV4dGVuc2lvbnNbdGhpcy5uYW1lXTtcclxuICAgICAgICBjb25zdCBidWZmZXJWaWV3OiBJR0xURkJ1ZmZlclZpZXcgPSBnbHRmUnVudGltZS5idWZmZXJWaWV3c1tiaW5hcnlFeHRlbnNpb25TaGFkZXIuYnVmZmVyVmlld107XHJcbiAgICAgICAgY29uc3Qgc2hhZGVyQnl0ZXMgPSBHTFRGVXRpbHMuR2V0QnVmZmVyRnJvbUJ1ZmZlclZpZXcoZ2x0ZlJ1bnRpbWUsIGJ1ZmZlclZpZXcsIDAsIGJ1ZmZlclZpZXcuYnl0ZUxlbmd0aCwgRUNvbXBvbmVudFR5cGUuVU5TSUdORURfQllURSk7XHJcblxyXG4gICAgICAgIHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBzaGFkZXJTdHJpbmcgPSBHTFRGVXRpbHMuRGVjb2RlQnVmZmVyVG9UZXh0KHNoYWRlckJ5dGVzKTtcclxuICAgICAgICAgICAgb25TdWNjZXNzKHNoYWRlclN0cmluZyk7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKG5ldyBHTFRGQmluYXJ5RXh0ZW5zaW9uKCkpO1xyXG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbm8tdW51c2VkLXZhcnMgKi9cclxuaW1wb3J0IHR5cGUge1xyXG4gICAgSUdMVEZSdW50aW1lLFxyXG4gICAgSUdMVEZUZWNobmlxdWVQYXJhbWV0ZXIsXHJcbiAgICBJR0xURkFuaW1hdGlvbixcclxuICAgIElHTFRGQW5pbWF0aW9uU2FtcGxlcixcclxuICAgIElHTFRGTm9kZSxcclxuICAgIElHTFRGU2tpbnMsXHJcbiAgICBJTm9kZVRvUm9vdCxcclxuICAgIElKb2ludE5vZGUsXHJcbiAgICBJR0xURk1lc2gsXHJcbiAgICBJR0xURkFjY2Vzc29yLFxyXG4gICAgSUdMVEZMaWdodCxcclxuICAgIElHTFRGQW1iaWVuTGlnaHQsXHJcbiAgICBJR0xURkRpcmVjdGlvbmFsTGlnaHQsXHJcbiAgICBJR0xURlBvaW50TGlnaHQsXHJcbiAgICBJR0xURlNwb3RMaWdodCxcclxuICAgIElHTFRGQ2FtZXJhLFxyXG4gICAgSUdMVEZDYW1lcmFQZXJzcGVjdGl2ZSxcclxuICAgIElHTFRGU2NlbmUsXHJcbiAgICBJR0xURlRlY2huaXF1ZSxcclxuICAgIElHTFRGTWF0ZXJpYWwsXHJcbiAgICBJR0xURlByb2dyYW0sXHJcbiAgICBJR0xURkJ1ZmZlcixcclxuICAgIElHTFRGVGV4dHVyZSxcclxuICAgIElHTFRGSW1hZ2UsXHJcbiAgICBJR0xURlNhbXBsZXIsXHJcbiAgICBJR0xURlNoYWRlcixcclxuICAgIElHTFRGVGVjaG5pcXVlU3RhdGVzLFxyXG59IGZyb20gXCIuL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcbmltcG9ydCB7IEVQYXJhbWV0ZXJUeXBlLCBFVGV4dHVyZUZpbHRlclR5cGUsIEVDdWxsaW5nVHlwZSwgRUJsZW5kaW5nRnVuY3Rpb24sIEVTaGFkZXJUeXBlIH0gZnJvbSBcIi4vZ2xURkxvYWRlckludGVyZmFjZXNcIjtcclxuXHJcbmltcG9ydCB0eXBlIHsgRmxvYXRBcnJheSwgTnVsbGFibGUgfSBmcm9tIFwiY29yZS90eXBlc1wiO1xyXG5pbXBvcnQgeyBRdWF0ZXJuaW9uLCBWZWN0b3IzLCBNYXRyaXggfSBmcm9tIFwiY29yZS9NYXRocy9tYXRoLnZlY3RvclwiO1xyXG5pbXBvcnQgeyBDb2xvcjMgfSBmcm9tIFwiY29yZS9NYXRocy9tYXRoLmNvbG9yXCI7XHJcbmltcG9ydCB7IFRvb2xzIH0gZnJvbSBcImNvcmUvTWlzYy90b29sc1wiO1xyXG5pbXBvcnQgeyBDYW1lcmEgfSBmcm9tIFwiY29yZS9DYW1lcmFzL2NhbWVyYVwiO1xyXG5pbXBvcnQgeyBGcmVlQ2FtZXJhIH0gZnJvbSBcImNvcmUvQ2FtZXJhcy9mcmVlQ2FtZXJhXCI7XHJcbmltcG9ydCB7IEFuaW1hdGlvbiB9IGZyb20gXCJjb3JlL0FuaW1hdGlvbnMvYW5pbWF0aW9uXCI7XHJcbmltcG9ydCB7IEJvbmUgfSBmcm9tIFwiY29yZS9Cb25lcy9ib25lXCI7XHJcbmltcG9ydCB7IFNrZWxldG9uIH0gZnJvbSBcImNvcmUvQm9uZXMvc2tlbGV0b25cIjtcclxuaW1wb3J0IHsgRWZmZWN0IH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL2VmZmVjdFwiO1xyXG5pbXBvcnQgeyBNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9tYXRlcmlhbFwiO1xyXG5pbXBvcnQgeyBNdWx0aU1hdGVyaWFsIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL211bHRpTWF0ZXJpYWxcIjtcclxuaW1wb3J0IHsgU3RhbmRhcmRNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9zdGFuZGFyZE1hdGVyaWFsXCI7XHJcbmltcG9ydCB7IFNoYWRlck1hdGVyaWFsIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL3NoYWRlck1hdGVyaWFsXCI7XHJcbmltcG9ydCB7IFRleHR1cmUgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvVGV4dHVyZXMvdGV4dHVyZVwiO1xyXG5pbXBvcnQgdHlwZSB7IE5vZGUgfSBmcm9tIFwiY29yZS9ub2RlXCI7XHJcbmltcG9ydCB7IFZlcnRleERhdGEgfSBmcm9tIFwiY29yZS9NZXNoZXMvbWVzaC52ZXJ0ZXhEYXRhXCI7XHJcbmltcG9ydCB7IFZlcnRleEJ1ZmZlciB9IGZyb20gXCJjb3JlL0J1ZmZlcnMvYnVmZmVyXCI7XHJcbmltcG9ydCB7IEdlb21ldHJ5IH0gZnJvbSBcImNvcmUvTWVzaGVzL2dlb21ldHJ5XCI7XHJcbmltcG9ydCB7IFN1Yk1lc2ggfSBmcm9tIFwiY29yZS9NZXNoZXMvc3ViTWVzaFwiO1xyXG5pbXBvcnQgeyBBYnN0cmFjdE1lc2ggfSBmcm9tIFwiY29yZS9NZXNoZXMvYWJzdHJhY3RNZXNoXCI7XHJcbmltcG9ydCB7IE1lc2ggfSBmcm9tIFwiY29yZS9NZXNoZXMvbWVzaFwiO1xyXG5pbXBvcnQgeyBIZW1pc3BoZXJpY0xpZ2h0IH0gZnJvbSBcImNvcmUvTGlnaHRzL2hlbWlzcGhlcmljTGlnaHRcIjtcclxuaW1wb3J0IHsgRGlyZWN0aW9uYWxMaWdodCB9IGZyb20gXCJjb3JlL0xpZ2h0cy9kaXJlY3Rpb25hbExpZ2h0XCI7XHJcbmltcG9ydCB7IFBvaW50TGlnaHQgfSBmcm9tIFwiY29yZS9MaWdodHMvcG9pbnRMaWdodFwiO1xyXG5pbXBvcnQgeyBTcG90TGlnaHQgfSBmcm9tIFwiY29yZS9MaWdodHMvc3BvdExpZ2h0XCI7XHJcbmltcG9ydCB0eXBlIHsgSVNjZW5lTG9hZGVyQXN5bmNSZXN1bHQsIElTY2VuZUxvYWRlclByb2dyZXNzRXZlbnQgfSBmcm9tIFwiY29yZS9Mb2FkaW5nL3NjZW5lTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgU2NlbmUgfSBmcm9tIFwiY29yZS9zY2VuZVwiO1xyXG5cclxuaW1wb3J0IHsgR0xURlV0aWxzIH0gZnJvbSBcIi4vZ2xURkxvYWRlclV0aWxzXCI7XHJcbmltcG9ydCB0eXBlIHsgSUdMVEZMb2FkZXIsIElHTFRGTG9hZGVyRGF0YSB9IGZyb20gXCIuLi9nbFRGRmlsZUxvYWRlclwiO1xyXG5pbXBvcnQgeyBHTFRGRmlsZUxvYWRlciB9IGZyb20gXCIuLi9nbFRGRmlsZUxvYWRlclwiO1xyXG5pbXBvcnQgeyBDb25zdGFudHMgfSBmcm9tIFwiY29yZS9FbmdpbmVzL2NvbnN0YW50c1wiO1xyXG5pbXBvcnQgdHlwZSB7IEFzc2V0Q29udGFpbmVyIH0gZnJvbSBcImNvcmUvYXNzZXRDb250YWluZXJcIjtcclxuXHJcbi8qKlxyXG4gKiBUb2tlbml6ZXIuIFVzZWQgZm9yIHNoYWRlcnMgY29tcGF0aWJpbGl0eVxyXG4gKiBBdXRvbWF0aWNhbGx5IG1hcCB3b3JsZCwgdmlldywgcHJvamVjdGlvbiwgd29ybGRWaWV3UHJvamVjdGlvbiwgYXR0cmlidXRlcyBhbmQgc28gb25cclxuICovXHJcbmVudW0gRVRva2VuVHlwZSB7XHJcbiAgICBJREVOVElGSUVSID0gMSxcclxuXHJcbiAgICBVTktOT1dOID0gMixcclxuICAgIEVORF9PRl9JTlBVVCA9IDMsXHJcbn1cclxuXHJcbmNsYXNzIFRva2VuaXplciB7XHJcbiAgICBwcml2YXRlIF90b1BhcnNlOiBzdHJpbmc7XHJcbiAgICBwcml2YXRlIF9wb3M6IG51bWJlciA9IDA7XHJcbiAgICBwcml2YXRlIF9tYXhQb3M6IG51bWJlcjtcclxuXHJcbiAgICBwdWJsaWMgY3VycmVudFRva2VuOiBFVG9rZW5UeXBlID0gRVRva2VuVHlwZS5VTktOT1dOO1xyXG4gICAgcHVibGljIGN1cnJlbnRJZGVudGlmaWVyOiBzdHJpbmcgPSBcIlwiO1xyXG4gICAgcHVibGljIGN1cnJlbnRTdHJpbmc6IHN0cmluZyA9IFwiXCI7XHJcbiAgICBwdWJsaWMgaXNMZXR0ZXJPckRpZ2l0UGF0dGVybjogUmVnRXhwID0gL15bYS16QS1aMC05XSskLztcclxuXHJcbiAgICBjb25zdHJ1Y3Rvcih0b1BhcnNlOiBzdHJpbmcpIHtcclxuICAgICAgICB0aGlzLl90b1BhcnNlID0gdG9QYXJzZTtcclxuICAgICAgICB0aGlzLl9tYXhQb3MgPSB0b1BhcnNlLmxlbmd0aDtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZ2V0TmV4dFRva2VuKCk6IEVUb2tlblR5cGUge1xyXG4gICAgICAgIGlmICh0aGlzLmlzRW5kKCkpIHtcclxuICAgICAgICAgICAgcmV0dXJuIEVUb2tlblR5cGUuRU5EX09GX0lOUFVUO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5jdXJyZW50U3RyaW5nID0gdGhpcy5yZWFkKCk7XHJcbiAgICAgICAgdGhpcy5jdXJyZW50VG9rZW4gPSBFVG9rZW5UeXBlLlVOS05PV047XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmN1cnJlbnRTdHJpbmcgPT09IFwiX1wiIHx8IHRoaXMuaXNMZXR0ZXJPckRpZ2l0UGF0dGVybi50ZXN0KHRoaXMuY3VycmVudFN0cmluZykpIHtcclxuICAgICAgICAgICAgdGhpcy5jdXJyZW50VG9rZW4gPSBFVG9rZW5UeXBlLklERU5USUZJRVI7XHJcbiAgICAgICAgICAgIHRoaXMuY3VycmVudElkZW50aWZpZXIgPSB0aGlzLmN1cnJlbnRTdHJpbmc7XHJcbiAgICAgICAgICAgIHdoaWxlICghdGhpcy5pc0VuZCgpICYmICh0aGlzLmlzTGV0dGVyT3JEaWdpdFBhdHRlcm4udGVzdCgodGhpcy5jdXJyZW50U3RyaW5nID0gdGhpcy5wZWVrKCkpKSB8fCB0aGlzLmN1cnJlbnRTdHJpbmcgPT09IFwiX1wiKSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5jdXJyZW50SWRlbnRpZmllciArPSB0aGlzLmN1cnJlbnRTdHJpbmc7XHJcbiAgICAgICAgICAgICAgICB0aGlzLmZvcndhcmQoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuY3VycmVudFRva2VuO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBwZWVrKCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3RvUGFyc2VbdGhpcy5fcG9zXTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgcmVhZCgpOiBzdHJpbmcge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl90b1BhcnNlW3RoaXMuX3BvcysrXTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZm9yd2FyZCgpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLl9wb3MrKztcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgaXNFbmQoKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX3BvcyA+PSB0aGlzLl9tYXhQb3M7XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBWYWx1ZXNcclxuICovXHJcbmNvbnN0IGdsVEZUcmFuc2Zvcm1zID0gW1wiTU9ERUxcIiwgXCJWSUVXXCIsIFwiUFJPSkVDVElPTlwiLCBcIk1PREVMVklFV1wiLCBcIk1PREVMVklFV1BST0pFQ1RJT05cIiwgXCJKT0lOVE1BVFJJWFwiXTtcclxuY29uc3QgYmFieWxvblRyYW5zZm9ybXMgPSBbXCJ3b3JsZFwiLCBcInZpZXdcIiwgXCJwcm9qZWN0aW9uXCIsIFwid29ybGRWaWV3XCIsIFwid29ybGRWaWV3UHJvamVjdGlvblwiLCBcIm1Cb25lc1wiXTtcclxuXHJcbmNvbnN0IGdsVEZBbmltYXRpb25QYXRocyA9IFtcInRyYW5zbGF0aW9uXCIsIFwicm90YXRpb25cIiwgXCJzY2FsZVwiXTtcclxuY29uc3QgYmFieWxvbkFuaW1hdGlvblBhdGhzID0gW1wicG9zaXRpb25cIiwgXCJyb3RhdGlvblF1YXRlcm5pb25cIiwgXCJzY2FsaW5nXCJdO1xyXG5cclxuLyoqXHJcbiAqIFBhcnNlXHJcbiAqIEBwYXJhbSBwYXJzZWRCdWZmZXJzXHJcbiAqIEBwYXJhbSBnbHRmUnVudGltZVxyXG4gKi9cclxuY29uc3QgcGFyc2VCdWZmZXJzID0gKHBhcnNlZEJ1ZmZlcnM6IGFueSwgZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSkgPT4ge1xyXG4gICAgZm9yIChjb25zdCBidWYgaW4gcGFyc2VkQnVmZmVycykge1xyXG4gICAgICAgIGNvbnN0IHBhcnNlZEJ1ZmZlciA9IHBhcnNlZEJ1ZmZlcnNbYnVmXTtcclxuICAgICAgICBnbHRmUnVudGltZS5idWZmZXJzW2J1Zl0gPSBwYXJzZWRCdWZmZXI7XHJcbiAgICAgICAgZ2x0ZlJ1bnRpbWUuYnVmZmVyc0NvdW50Kys7XHJcbiAgICB9XHJcbn07XHJcblxyXG5jb25zdCBwYXJzZVNoYWRlcnMgPSAocGFyc2VkU2hhZGVyczogYW55LCBnbHRmUnVudGltZTogSUdMVEZSdW50aW1lKSA9PiB7XHJcbiAgICBmb3IgKGNvbnN0IHNoYSBpbiBwYXJzZWRTaGFkZXJzKSB7XHJcbiAgICAgICAgY29uc3QgcGFyc2VkU2hhZGVyID0gcGFyc2VkU2hhZGVyc1tzaGFdO1xyXG4gICAgICAgIGdsdGZSdW50aW1lLnNoYWRlcnNbc2hhXSA9IHBhcnNlZFNoYWRlcjtcclxuICAgICAgICBnbHRmUnVudGltZS5zaGFkZXJzY291bnQrKztcclxuICAgIH1cclxufTtcclxuXHJcbmNvbnN0IHBhcnNlT2JqZWN0ID0gKHBhcnNlZE9iamVjdHM6IGFueSwgcnVudGltZVByb3BlcnR5OiBzdHJpbmcsIGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUpID0+IHtcclxuICAgIGZvciAoY29uc3Qgb2JqZWN0IGluIHBhcnNlZE9iamVjdHMpIHtcclxuICAgICAgICBjb25zdCBwYXJzZWRPYmplY3QgPSBwYXJzZWRPYmplY3RzW29iamVjdF07XHJcbiAgICAgICAgKDxhbnk+Z2x0ZlJ1bnRpbWUpW3J1bnRpbWVQcm9wZXJ0eV1bb2JqZWN0XSA9IHBhcnNlZE9iamVjdDtcclxuICAgIH1cclxufTtcclxuXHJcbi8qKlxyXG4gKiBVdGlsc1xyXG4gKiBAcGFyYW0gYnVmZmVyXHJcbiAqL1xyXG5jb25zdCBub3JtYWxpemVVVnMgPSAoYnVmZmVyOiBhbnkpID0+IHtcclxuICAgIGlmICghYnVmZmVyKSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYnVmZmVyLmxlbmd0aCAvIDI7IGkrKykge1xyXG4gICAgICAgIGJ1ZmZlcltpICogMiArIDFdID0gMS4wIC0gYnVmZmVyW2kgKiAyICsgMV07XHJcbiAgICB9XHJcbn07XHJcblxyXG5jb25zdCBnZXRBdHRyaWJ1dGUgPSAoYXR0cmlidXRlUGFyYW1ldGVyOiBJR0xURlRlY2huaXF1ZVBhcmFtZXRlcik6IE51bGxhYmxlPHN0cmluZz4gPT4ge1xyXG4gICAgaWYgKGF0dHJpYnV0ZVBhcmFtZXRlci5zZW1hbnRpYyA9PT0gXCJOT1JNQUxcIikge1xyXG4gICAgICAgIHJldHVybiBcIm5vcm1hbFwiO1xyXG4gICAgfSBlbHNlIGlmIChhdHRyaWJ1dGVQYXJhbWV0ZXIuc2VtYW50aWMgPT09IFwiUE9TSVRJT05cIikge1xyXG4gICAgICAgIHJldHVybiBcInBvc2l0aW9uXCI7XHJcbiAgICB9IGVsc2UgaWYgKGF0dHJpYnV0ZVBhcmFtZXRlci5zZW1hbnRpYyA9PT0gXCJKT0lOVFwiKSB7XHJcbiAgICAgICAgcmV0dXJuIFwibWF0cmljZXNJbmRpY2VzXCI7XHJcbiAgICB9IGVsc2UgaWYgKGF0dHJpYnV0ZVBhcmFtZXRlci5zZW1hbnRpYyA9PT0gXCJXRUlHSFRcIikge1xyXG4gICAgICAgIHJldHVybiBcIm1hdHJpY2VzV2VpZ2h0c1wiO1xyXG4gICAgfSBlbHNlIGlmIChhdHRyaWJ1dGVQYXJhbWV0ZXIuc2VtYW50aWMgPT09IFwiQ09MT1JcIikge1xyXG4gICAgICAgIHJldHVybiBcImNvbG9yXCI7XHJcbiAgICB9IGVsc2UgaWYgKGF0dHJpYnV0ZVBhcmFtZXRlci5zZW1hbnRpYyAmJiBhdHRyaWJ1dGVQYXJhbWV0ZXIuc2VtYW50aWMuaW5kZXhPZihcIlRFWENPT1JEX1wiKSAhPT0gLTEpIHtcclxuICAgICAgICBjb25zdCBjaGFubmVsID0gTnVtYmVyKGF0dHJpYnV0ZVBhcmFtZXRlci5zZW1hbnRpYy5zcGxpdChcIl9cIilbMV0pO1xyXG4gICAgICAgIHJldHVybiBcInV2XCIgKyAoY2hhbm5lbCA9PT0gMCA/IFwiXCIgOiBjaGFubmVsICsgMSk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG51bGw7XHJcbn07XHJcblxyXG4vKipcclxuICogTG9hZHMgYW5kIGNyZWF0ZXMgYW5pbWF0aW9uc1xyXG4gKiBAcGFyYW0gZ2x0ZlJ1bnRpbWVcclxuICovXHJcbmNvbnN0IGxvYWRBbmltYXRpb25zID0gKGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUpID0+IHtcclxuICAgIGZvciAoY29uc3QgYW5pbSBpbiBnbHRmUnVudGltZS5hbmltYXRpb25zKSB7XHJcbiAgICAgICAgY29uc3QgYW5pbWF0aW9uOiBJR0xURkFuaW1hdGlvbiA9IGdsdGZSdW50aW1lLmFuaW1hdGlvbnNbYW5pbV07XHJcblxyXG4gICAgICAgIGlmICghYW5pbWF0aW9uLmNoYW5uZWxzIHx8ICFhbmltYXRpb24uc2FtcGxlcnMpIHtcclxuICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgbGFzdEFuaW1hdGlvbjogTnVsbGFibGU8QW5pbWF0aW9uPiA9IG51bGw7XHJcblxyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgYW5pbWF0aW9uLmNoYW5uZWxzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIC8vIEdldCBwYXJhbWV0ZXJzIGFuZCBsb2FkIGJ1ZmZlcnNcclxuICAgICAgICAgICAgY29uc3QgY2hhbm5lbCA9IGFuaW1hdGlvbi5jaGFubmVsc1tpXTtcclxuICAgICAgICAgICAgY29uc3Qgc2FtcGxlcjogSUdMVEZBbmltYXRpb25TYW1wbGVyID0gYW5pbWF0aW9uLnNhbXBsZXJzW2NoYW5uZWwuc2FtcGxlcl07XHJcblxyXG4gICAgICAgICAgICBpZiAoIXNhbXBsZXIpIHtcclxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBsZXQgaW5wdXREYXRhOiBOdWxsYWJsZTxzdHJpbmc+ID0gbnVsbDtcclxuICAgICAgICAgICAgbGV0IG91dHB1dERhdGE6IE51bGxhYmxlPHN0cmluZz4gPSBudWxsO1xyXG5cclxuICAgICAgICAgICAgaWYgKGFuaW1hdGlvbi5wYXJhbWV0ZXJzKSB7XHJcbiAgICAgICAgICAgICAgICBpbnB1dERhdGEgPSBhbmltYXRpb24ucGFyYW1ldGVyc1tzYW1wbGVyLmlucHV0XTtcclxuICAgICAgICAgICAgICAgIG91dHB1dERhdGEgPSBhbmltYXRpb24ucGFyYW1ldGVyc1tzYW1wbGVyLm91dHB1dF07XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBpbnB1dERhdGEgPSBzYW1wbGVyLmlucHV0O1xyXG4gICAgICAgICAgICAgICAgb3V0cHV0RGF0YSA9IHNhbXBsZXIub3V0cHV0O1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBidWZmZXJJbnB1dCA9IEdMVEZVdGlscy5HZXRCdWZmZXJGcm9tQWNjZXNzb3IoZ2x0ZlJ1bnRpbWUsIGdsdGZSdW50aW1lLmFjY2Vzc29yc1tpbnB1dERhdGFdKTtcclxuICAgICAgICAgICAgY29uc3QgYnVmZmVyT3V0cHV0ID0gR0xURlV0aWxzLkdldEJ1ZmZlckZyb21BY2Nlc3NvcihnbHRmUnVudGltZSwgZ2x0ZlJ1bnRpbWUuYWNjZXNzb3JzW291dHB1dERhdGFdKTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldElkID0gY2hhbm5lbC50YXJnZXQuaWQ7XHJcbiAgICAgICAgICAgIGxldCB0YXJnZXROb2RlOiBhbnkgPSBnbHRmUnVudGltZS5zY2VuZS5nZXROb2RlQnlJZCh0YXJnZXRJZCk7XHJcblxyXG4gICAgICAgICAgICBpZiAodGFyZ2V0Tm9kZSA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgdGFyZ2V0Tm9kZSA9IGdsdGZSdW50aW1lLnNjZW5lLmdldE5vZGVCeU5hbWUodGFyZ2V0SWQpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAodGFyZ2V0Tm9kZSA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgVG9vbHMuV2FybihcIkNyZWF0aW5nIGFuaW1hdGlvbiBuYW1lZCBcIiArIGFuaW0gKyBcIi4gQnV0IGNhbm5vdCBmaW5kIG5vZGUgbmFtZWQgXCIgKyB0YXJnZXRJZCArIFwiIHRvIGF0dGFjaCB0b1wiKTtcclxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBpc0JvbmUgPSB0YXJnZXROb2RlIGluc3RhbmNlb2YgQm9uZTtcclxuXHJcbiAgICAgICAgICAgIC8vIEdldCB0YXJnZXQgcGF0aCAocG9zaXRpb24sIHJvdGF0aW9uIG9yIHNjYWxpbmcpXHJcbiAgICAgICAgICAgIGxldCB0YXJnZXRQYXRoID0gY2hhbm5lbC50YXJnZXQucGF0aDtcclxuICAgICAgICAgICAgY29uc3QgdGFyZ2V0UGF0aEluZGV4ID0gZ2xURkFuaW1hdGlvblBhdGhzLmluZGV4T2YodGFyZ2V0UGF0aCk7XHJcblxyXG4gICAgICAgICAgICBpZiAodGFyZ2V0UGF0aEluZGV4ICE9PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgdGFyZ2V0UGF0aCA9IGJhYnlsb25BbmltYXRpb25QYXRoc1t0YXJnZXRQYXRoSW5kZXhdO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBEZXRlcm1pbmUgYW5pbWF0aW9uIHR5cGVcclxuICAgICAgICAgICAgbGV0IGFuaW1hdGlvblR5cGUgPSBBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9NQVRSSVg7XHJcblxyXG4gICAgICAgICAgICBpZiAoIWlzQm9uZSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHRhcmdldFBhdGggPT09IFwicm90YXRpb25RdWF0ZXJuaW9uXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICBhbmltYXRpb25UeXBlID0gQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfUVVBVEVSTklPTjtcclxuICAgICAgICAgICAgICAgICAgICB0YXJnZXROb2RlLnJvdGF0aW9uUXVhdGVybmlvbiA9IG5ldyBRdWF0ZXJuaW9uKCk7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvblR5cGUgPSBBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9WRUNUT1IzO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBDcmVhdGUgYW5pbWF0aW9uIGFuZCBrZXkgZnJhbWVzXHJcbiAgICAgICAgICAgIGxldCBiYWJ5bG9uQW5pbWF0aW9uOiBOdWxsYWJsZTxBbmltYXRpb24+ID0gbnVsbDtcclxuICAgICAgICAgICAgY29uc3Qga2V5cyA9IFtdO1xyXG4gICAgICAgICAgICBsZXQgYXJyYXlPZmZzZXQgPSAwO1xyXG4gICAgICAgICAgICBsZXQgbW9kaWZ5S2V5ID0gZmFsc2U7XHJcblxyXG4gICAgICAgICAgICBpZiAoaXNCb25lICYmIGxhc3RBbmltYXRpb24gJiYgbGFzdEFuaW1hdGlvbi5nZXRLZXlzKCkubGVuZ3RoID09PSBidWZmZXJJbnB1dC5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25BbmltYXRpb24gPSBsYXN0QW5pbWF0aW9uO1xyXG4gICAgICAgICAgICAgICAgbW9kaWZ5S2V5ID0gdHJ1ZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKCFtb2RpZnlLZXkpIHtcclxuICAgICAgICAgICAgICAgIGdsdGZSdW50aW1lLnNjZW5lLl9ibG9ja0VudGl0eUNvbGxlY3Rpb24gPSAhIWdsdGZSdW50aW1lLmFzc2V0Q29udGFpbmVyO1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbkFuaW1hdGlvbiA9IG5ldyBBbmltYXRpb24oYW5pbSwgaXNCb25lID8gXCJfbWF0cml4XCIgOiB0YXJnZXRQYXRoLCAxLCBhbmltYXRpb25UeXBlLCBBbmltYXRpb24uQU5JTUFUSU9OTE9PUE1PREVfQ1lDTEUpO1xyXG4gICAgICAgICAgICAgICAgZ2x0ZlJ1bnRpbWUuc2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9IGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAvLyBGb3IgZWFjaCBmcmFtZVxyXG4gICAgICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGJ1ZmZlcklucHV0Lmxlbmd0aDsgaisrKSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgdmFsdWU6IGFueSA9IG51bGw7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKHRhcmdldFBhdGggPT09IFwicm90YXRpb25RdWF0ZXJuaW9uXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBWRUM0XHJcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBRdWF0ZXJuaW9uLkZyb21BcnJheShbYnVmZmVyT3V0cHV0W2FycmF5T2Zmc2V0XSwgYnVmZmVyT3V0cHV0W2FycmF5T2Zmc2V0ICsgMV0sIGJ1ZmZlck91dHB1dFthcnJheU9mZnNldCArIDJdLCBidWZmZXJPdXRwdXRbYXJyYXlPZmZzZXQgKyAzXV0pO1xyXG4gICAgICAgICAgICAgICAgICAgIGFycmF5T2Zmc2V0ICs9IDQ7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIFBvc2l0aW9uIGFuZCBzY2FsaW5nIGFyZSBWRUMzXHJcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBWZWN0b3IzLkZyb21BcnJheShbYnVmZmVyT3V0cHV0W2FycmF5T2Zmc2V0XSwgYnVmZmVyT3V0cHV0W2FycmF5T2Zmc2V0ICsgMV0sIGJ1ZmZlck91dHB1dFthcnJheU9mZnNldCArIDJdXSk7XHJcbiAgICAgICAgICAgICAgICAgICAgYXJyYXlPZmZzZXQgKz0gMztcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoaXNCb25lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgYm9uZSA9IDxCb25lPnRhcmdldE5vZGU7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHRyYW5zbGF0aW9uID0gVmVjdG9yMy5aZXJvKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHJvdGF0aW9uUXVhdGVybmlvbiA9IG5ldyBRdWF0ZXJuaW9uKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgbGV0IHNjYWxpbmcgPSBWZWN0b3IzLlplcm8oKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gV2FybmluZyBvbiBkZWNvbXBvc2VcclxuICAgICAgICAgICAgICAgICAgICBsZXQgbWF0ID0gYm9uZS5nZXRCYXNlTWF0cml4KCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChtb2RpZnlLZXkgJiYgbGFzdEFuaW1hdGlvbikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXQgPSBsYXN0QW5pbWF0aW9uLmdldEtleXMoKVtqXS52YWx1ZTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIG1hdC5kZWNvbXBvc2Uoc2NhbGluZywgcm90YXRpb25RdWF0ZXJuaW9uLCB0cmFuc2xhdGlvbik7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmICh0YXJnZXRQYXRoID09PSBcInBvc2l0aW9uXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRpb24gPSB2YWx1ZTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRhcmdldFBhdGggPT09IFwicm90YXRpb25RdWF0ZXJuaW9uXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb25RdWF0ZXJuaW9uID0gdmFsdWU7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGluZyA9IHZhbHVlO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSBNYXRyaXguQ29tcG9zZShzY2FsaW5nLCByb3RhdGlvblF1YXRlcm5pb24sIHRyYW5zbGF0aW9uKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoIW1vZGlmeUtleSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGtleXMucHVzaCh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZyYW1lOiBidWZmZXJJbnB1dFtqXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHZhbHVlLFxyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChsYXN0QW5pbWF0aW9uKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbGFzdEFuaW1hdGlvbi5nZXRLZXlzKClbal0udmFsdWUgPSB2YWx1ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gRmluaXNoXHJcbiAgICAgICAgICAgIGlmICghbW9kaWZ5S2V5ICYmIGJhYnlsb25BbmltYXRpb24pIHtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25BbmltYXRpb24uc2V0S2V5cyhrZXlzKTtcclxuICAgICAgICAgICAgICAgIHRhcmdldE5vZGUuYW5pbWF0aW9ucy5wdXNoKGJhYnlsb25BbmltYXRpb24pO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBsYXN0QW5pbWF0aW9uID0gYmFieWxvbkFuaW1hdGlvbjtcclxuXHJcbiAgICAgICAgICAgIGdsdGZSdW50aW1lLnNjZW5lLnN0b3BBbmltYXRpb24odGFyZ2V0Tm9kZSk7XHJcbiAgICAgICAgICAgIGdsdGZSdW50aW1lLnNjZW5lLmJlZ2luQW5pbWF0aW9uKHRhcmdldE5vZGUsIDAsIGJ1ZmZlcklucHV0W2J1ZmZlcklucHV0Lmxlbmd0aCAtIDFdLCB0cnVlLCAxLjApO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufTtcclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoZSBib25lcyB0cmFuc2Zvcm1hdGlvbiBtYXRyaXhcclxuICogQHBhcmFtIG5vZGVcclxuICovXHJcbmNvbnN0IGNvbmZpZ3VyZUJvbmVUcmFuc2Zvcm1hdGlvbiA9IChub2RlOiBJR0xURk5vZGUpOiBNYXRyaXggPT4ge1xyXG4gICAgbGV0IG1hdDogTnVsbGFibGU8TWF0cml4PiA9IG51bGw7XHJcblxyXG4gICAgaWYgKG5vZGUudHJhbnNsYXRpb24gfHwgbm9kZS5yb3RhdGlvbiB8fCBub2RlLnNjYWxlKSB7XHJcbiAgICAgICAgY29uc3Qgc2NhbGUgPSBWZWN0b3IzLkZyb21BcnJheShub2RlLnNjYWxlIHx8IFsxLCAxLCAxXSk7XHJcbiAgICAgICAgY29uc3Qgcm90YXRpb24gPSBRdWF0ZXJuaW9uLkZyb21BcnJheShub2RlLnJvdGF0aW9uIHx8IFswLCAwLCAwLCAxXSk7XHJcbiAgICAgICAgY29uc3QgcG9zaXRpb24gPSBWZWN0b3IzLkZyb21BcnJheShub2RlLnRyYW5zbGF0aW9uIHx8IFswLCAwLCAwXSk7XHJcblxyXG4gICAgICAgIG1hdCA9IE1hdHJpeC5Db21wb3NlKHNjYWxlLCByb3RhdGlvbiwgcG9zaXRpb24pO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICBtYXQgPSBNYXRyaXguRnJvbUFycmF5KG5vZGUubWF0cml4KTtcclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gbWF0O1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIHBhcmVudCBib25lXHJcbiAqIEBwYXJhbSBnbHRmUnVudGltZVxyXG4gKiBAcGFyYW0gc2tpbnNcclxuICogQHBhcmFtIGpvaW50TmFtZVxyXG4gKiBAcGFyYW0gbmV3U2tlbGV0b25cclxuICovXHJcbmNvbnN0IGdldFBhcmVudEJvbmUgPSAoZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSwgc2tpbnM6IElHTFRGU2tpbnMsIGpvaW50TmFtZTogc3RyaW5nLCBuZXdTa2VsZXRvbjogU2tlbGV0b24pOiBOdWxsYWJsZTxCb25lPiA9PiB7XHJcbiAgICAvLyBUcnkgdG8gZmluZFxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBuZXdTa2VsZXRvbi5ib25lcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIGlmIChuZXdTa2VsZXRvbi5ib25lc1tpXS5uYW1lID09PSBqb2ludE5hbWUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG5ld1NrZWxldG9uLmJvbmVzW2ldO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBOb3QgZm91bmQsIHNlYXJjaCBpbiBnbHRmIG5vZGVzXHJcbiAgICBjb25zdCBub2RlcyA9IGdsdGZSdW50aW1lLm5vZGVzO1xyXG4gICAgZm9yIChjb25zdCBuZGUgaW4gbm9kZXMpIHtcclxuICAgICAgICBjb25zdCBub2RlOiBJR0xURk5vZGUgPSBub2Rlc1tuZGVdO1xyXG5cclxuICAgICAgICBpZiAoIW5vZGUuam9pbnROYW1lKSB7XHJcbiAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgY2hpbGRyZW4gPSBub2RlLmNoaWxkcmVuO1xyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2hpbGRyZW4ubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgY29uc3QgY2hpbGQ6IElHTFRGTm9kZSA9IGdsdGZSdW50aW1lLm5vZGVzW2NoaWxkcmVuW2ldXTtcclxuICAgICAgICAgICAgaWYgKCFjaGlsZC5qb2ludE5hbWUpIHtcclxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoY2hpbGQuam9pbnROYW1lID09PSBqb2ludE5hbWUpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG1hdCA9IGNvbmZpZ3VyZUJvbmVUcmFuc2Zvcm1hdGlvbihub2RlKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGJvbmUgPSBuZXcgQm9uZShub2RlLm5hbWUgfHwgXCJcIiwgbmV3U2tlbGV0b24sIGdldFBhcmVudEJvbmUoZ2x0ZlJ1bnRpbWUsIHNraW5zLCBub2RlLmpvaW50TmFtZSwgbmV3U2tlbGV0b24pLCBtYXQpO1xyXG4gICAgICAgICAgICAgICAgYm9uZS5pZCA9IG5kZTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBib25lO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBudWxsO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIGFwcHJvcHJpYXRlIHJvb3Qgbm9kZVxyXG4gKiBAcGFyYW0gbm9kZXNUb1Jvb3RcclxuICogQHBhcmFtIGlkXHJcbiAqL1xyXG5jb25zdCBnZXROb2RlVG9Sb290ID0gKG5vZGVzVG9Sb290OiBJTm9kZVRvUm9vdFtdLCBpZDogc3RyaW5nKTogTnVsbGFibGU8Qm9uZT4gPT4ge1xyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2Rlc1RvUm9vdC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIGNvbnN0IG5vZGVUb1Jvb3QgPSBub2Rlc1RvUm9vdFtpXTtcclxuXHJcbiAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBub2RlVG9Sb290Lm5vZGUuY2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcclxuICAgICAgICAgICAgY29uc3QgY2hpbGQgPSBub2RlVG9Sb290Lm5vZGUuY2hpbGRyZW5bal07XHJcbiAgICAgICAgICAgIGlmIChjaGlsZCA9PT0gaWQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBub2RlVG9Sb290LmJvbmU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG51bGw7XHJcbn07XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGUgbm9kZSB3aXRoIHRoZSBqb2ludCBuYW1lXHJcbiAqIEBwYXJhbSBnbHRmUnVudGltZVxyXG4gKiBAcGFyYW0gam9pbnROYW1lXHJcbiAqL1xyXG5jb25zdCBnZXRKb2ludE5vZGUgPSAoZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSwgam9pbnROYW1lOiBzdHJpbmcpOiBOdWxsYWJsZTxJSm9pbnROb2RlPiA9PiB7XHJcbiAgICBjb25zdCBub2RlcyA9IGdsdGZSdW50aW1lLm5vZGVzO1xyXG4gICAgbGV0IG5vZGU6IElHTFRGTm9kZSA9IG5vZGVzW2pvaW50TmFtZV07XHJcbiAgICBpZiAobm9kZSkge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIG5vZGU6IG5vZGUsXHJcbiAgICAgICAgICAgIGlkOiBqb2ludE5hbWUsXHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICBmb3IgKGNvbnN0IG5kZSBpbiBub2Rlcykge1xyXG4gICAgICAgIG5vZGUgPSBub2Rlc1tuZGVdO1xyXG4gICAgICAgIGlmIChub2RlLmpvaW50TmFtZSA9PT0gam9pbnROYW1lKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICBub2RlOiBub2RlLFxyXG4gICAgICAgICAgICAgICAgaWQ6IG5kZSxcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG51bGw7XHJcbn07XHJcblxyXG4vKipcclxuICogQ2hlY2tzIGlmIGEgbm9kZXMgaXMgaW4gam9pbnRzXHJcbiAqIEBwYXJhbSBza2luc1xyXG4gKiBAcGFyYW0gaWRcclxuICovXHJcbmNvbnN0IG5vZGVJc0luSm9pbnRzID0gKHNraW5zOiBJR0xURlNraW5zLCBpZDogc3RyaW5nKTogYm9vbGVhbiA9PiB7XHJcbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNraW5zLmpvaW50TmFtZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICBpZiAoc2tpbnMuam9pbnROYW1lc1tpXSA9PT0gaWQpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBmYWxzZTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBGaWxscyB0aGUgbm9kZXMgdG8gcm9vdCBmb3IgYm9uZXMgYW5kIGJ1aWxkcyBoaWVyYXJjaHlcclxuICogQHBhcmFtIGdsdGZSdW50aW1lXHJcbiAqIEBwYXJhbSBuZXdTa2VsZXRvblxyXG4gKiBAcGFyYW0gc2tpbnNcclxuICogQHBhcmFtIG5vZGVzVG9Sb290XHJcbiAqL1xyXG5jb25zdCBnZXROb2Rlc1RvUm9vdCA9IChnbHRmUnVudGltZTogSUdMVEZSdW50aW1lLCBuZXdTa2VsZXRvbjogU2tlbGV0b24sIHNraW5zOiBJR0xURlNraW5zLCBub2Rlc1RvUm9vdDogSU5vZGVUb1Jvb3RbXSkgPT4ge1xyXG4gICAgLy8gQ3JlYXRlcyBub2RlcyBmb3Igcm9vdFxyXG4gICAgZm9yIChjb25zdCBuZGUgaW4gZ2x0ZlJ1bnRpbWUubm9kZXMpIHtcclxuICAgICAgICBjb25zdCBub2RlOiBJR0xURk5vZGUgPSBnbHRmUnVudGltZS5ub2Rlc1tuZGVdO1xyXG4gICAgICAgIGNvbnN0IGlkID0gbmRlO1xyXG5cclxuICAgICAgICBpZiAoIW5vZGUuam9pbnROYW1lIHx8IG5vZGVJc0luSm9pbnRzKHNraW5zLCBub2RlLmpvaW50TmFtZSkpIHtcclxuICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBDcmVhdGUgbm9kZSB0byByb290IGJvbmVcclxuICAgICAgICBjb25zdCBtYXQgPSBjb25maWd1cmVCb25lVHJhbnNmb3JtYXRpb24obm9kZSk7XHJcbiAgICAgICAgY29uc3QgYm9uZSA9IG5ldyBCb25lKG5vZGUubmFtZSB8fCBcIlwiLCBuZXdTa2VsZXRvbiwgbnVsbCwgbWF0KTtcclxuICAgICAgICBib25lLmlkID0gaWQ7XHJcbiAgICAgICAgbm9kZXNUb1Jvb3QucHVzaCh7IGJvbmU6IGJvbmUsIG5vZGU6IG5vZGUsIGlkOiBpZCB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvLyBQYXJlbnRpbmdcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbm9kZXNUb1Jvb3QubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICBjb25zdCBub2RlVG9Sb290ID0gbm9kZXNUb1Jvb3RbaV07XHJcbiAgICAgICAgY29uc3QgY2hpbGRyZW4gPSBub2RlVG9Sb290Lm5vZGUuY2hpbGRyZW47XHJcblxyXG4gICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgY2hpbGRyZW4ubGVuZ3RoOyBqKyspIHtcclxuICAgICAgICAgICAgbGV0IGNoaWxkOiBOdWxsYWJsZTxJTm9kZVRvUm9vdD4gPSBudWxsO1xyXG5cclxuICAgICAgICAgICAgZm9yIChsZXQgayA9IDA7IGsgPCBub2Rlc1RvUm9vdC5sZW5ndGg7IGsrKykge1xyXG4gICAgICAgICAgICAgICAgaWYgKG5vZGVzVG9Sb290W2tdLmlkID09PSBjaGlsZHJlbltqXSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNoaWxkID0gbm9kZXNUb1Jvb3Rba107XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmIChjaGlsZCkge1xyXG4gICAgICAgICAgICAgICAgKDxhbnk+Y2hpbGQuYm9uZSkuX3BhcmVudCA9IG5vZGVUb1Jvb3QuYm9uZTtcclxuICAgICAgICAgICAgICAgIG5vZGVUb1Jvb3QuYm9uZS5jaGlsZHJlbi5wdXNoKGNoaWxkLmJvbmUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59O1xyXG5cclxuLyoqXHJcbiAqIEltcG9ydHMgYSBza2VsZXRvblxyXG4gKiBAcGFyYW0gZ2x0ZlJ1bnRpbWVcclxuICogQHBhcmFtIHNraW5zXHJcbiAqIEBwYXJhbSBtZXNoXHJcbiAqIEBwYXJhbSBuZXdTa2VsZXRvblxyXG4gKi9cclxuY29uc3QgaW1wb3J0U2tlbGV0b24gPSAoZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSwgc2tpbnM6IElHTFRGU2tpbnMsIG1lc2g6IE1lc2gsIG5ld1NrZWxldG9uOiBTa2VsZXRvbiB8IHVuZGVmaW5lZCk6IFNrZWxldG9uID0+IHtcclxuICAgIGlmICghbmV3U2tlbGV0b24pIHtcclxuICAgICAgICBuZXdTa2VsZXRvbiA9IG5ldyBTa2VsZXRvbihza2lucy5uYW1lIHx8IFwiXCIsIFwiXCIsIGdsdGZSdW50aW1lLnNjZW5lKTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIXNraW5zLmJhYnlsb25Ta2VsZXRvbikge1xyXG4gICAgICAgIHJldHVybiBuZXdTa2VsZXRvbjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBGaW5kIHRoZSByb290IGJvbmVzXHJcbiAgICBjb25zdCBub2Rlc1RvUm9vdDogSU5vZGVUb1Jvb3RbXSA9IFtdO1xyXG4gICAgY29uc3Qgbm9kZXNUb1Jvb3RUb0FkZDogQm9uZVtdID0gW107XHJcblxyXG4gICAgZ2V0Tm9kZXNUb1Jvb3QoZ2x0ZlJ1bnRpbWUsIG5ld1NrZWxldG9uLCBza2lucywgbm9kZXNUb1Jvb3QpO1xyXG4gICAgbmV3U2tlbGV0b24uYm9uZXMgPSBbXTtcclxuXHJcbiAgICAvLyBKb2ludHNcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2tpbnMuam9pbnROYW1lcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIGNvbnN0IGpvaW50Tm9kZSA9IGdldEpvaW50Tm9kZShnbHRmUnVudGltZSwgc2tpbnMuam9pbnROYW1lc1tpXSk7XHJcblxyXG4gICAgICAgIGlmICgham9pbnROb2RlKSB7XHJcbiAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3Qgbm9kZSA9IGpvaW50Tm9kZS5ub2RlO1xyXG5cclxuICAgICAgICBpZiAoIW5vZGUpIHtcclxuICAgICAgICAgICAgVG9vbHMuV2FybihcIkpvaW50IG5hbWVkIFwiICsgc2tpbnMuam9pbnROYW1lc1tpXSArIFwiIGRvZXMgbm90IGV4aXN0XCIpO1xyXG4gICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGlkID0gam9pbnROb2RlLmlkO1xyXG5cclxuICAgICAgICAvLyBPcHRpbWl6ZSwgaWYgdGhlIGJvbmUgYWxyZWFkeSBleGlzdHMuLi5cclxuICAgICAgICBjb25zdCBleGlzdGluZ0JvbmUgPSBnbHRmUnVudGltZS5zY2VuZS5nZXRCb25lQnlJZChpZCk7XHJcbiAgICAgICAgaWYgKGV4aXN0aW5nQm9uZSkge1xyXG4gICAgICAgICAgICBuZXdTa2VsZXRvbi5ib25lcy5wdXNoKGV4aXN0aW5nQm9uZSk7XHJcbiAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gU2VhcmNoIGZvciBwYXJlbnQgYm9uZVxyXG4gICAgICAgIGxldCBmb3VuZEJvbmUgPSBmYWxzZTtcclxuICAgICAgICBsZXQgcGFyZW50Qm9uZTogTnVsbGFibGU8Qm9uZT4gPSBudWxsO1xyXG5cclxuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGk7IGorKykge1xyXG4gICAgICAgICAgICBjb25zdCBqb2ludE5vZGUgPSBnZXRKb2ludE5vZGUoZ2x0ZlJ1bnRpbWUsIHNraW5zLmpvaW50TmFtZXNbal0pO1xyXG5cclxuICAgICAgICAgICAgaWYgKCFqb2ludE5vZGUpIHtcclxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBqb2ludDogSUdMVEZOb2RlID0gam9pbnROb2RlLm5vZGU7XHJcblxyXG4gICAgICAgICAgICBpZiAoIWpvaW50KSB7XHJcbiAgICAgICAgICAgICAgICBUb29scy5XYXJuKFwiSm9pbnQgbmFtZWQgXCIgKyBza2lucy5qb2ludE5hbWVzW2pdICsgXCIgZG9lcyBub3QgZXhpc3Qgd2hlbiBsb29raW5nIGZvciBwYXJlbnRcIik7XHJcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3QgY2hpbGRyZW4gPSBqb2ludC5jaGlsZHJlbjtcclxuICAgICAgICAgICAgaWYgKCFjaGlsZHJlbikge1xyXG4gICAgICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZm91bmRCb25lID0gZmFsc2U7XHJcblxyXG4gICAgICAgICAgICBmb3IgKGxldCBrID0gMDsgayA8IGNoaWxkcmVuLmxlbmd0aDsgaysrKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoY2hpbGRyZW5ba10gPT09IGlkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcGFyZW50Qm9uZSA9IGdldFBhcmVudEJvbmUoZ2x0ZlJ1bnRpbWUsIHNraW5zLCBza2lucy5qb2ludE5hbWVzW2pdLCBuZXdTa2VsZXRvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgZm91bmRCb25lID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKGZvdW5kQm9uZSkge1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIENyZWF0ZSBib25lXHJcbiAgICAgICAgY29uc3QgbWF0ID0gY29uZmlndXJlQm9uZVRyYW5zZm9ybWF0aW9uKG5vZGUpO1xyXG5cclxuICAgICAgICBpZiAoIXBhcmVudEJvbmUgJiYgbm9kZXNUb1Jvb3QubGVuZ3RoID4gMCkge1xyXG4gICAgICAgICAgICBwYXJlbnRCb25lID0gZ2V0Tm9kZVRvUm9vdChub2Rlc1RvUm9vdCwgaWQpO1xyXG5cclxuICAgICAgICAgICAgaWYgKHBhcmVudEJvbmUpIHtcclxuICAgICAgICAgICAgICAgIGlmIChub2Rlc1RvUm9vdFRvQWRkLmluZGV4T2YocGFyZW50Qm9uZSkgPT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbm9kZXNUb1Jvb3RUb0FkZC5wdXNoKHBhcmVudEJvbmUpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBib25lID0gbmV3IEJvbmUobm9kZS5qb2ludE5hbWUgfHwgXCJcIiwgbmV3U2tlbGV0b24sIHBhcmVudEJvbmUsIG1hdCk7XHJcbiAgICAgICAgYm9uZS5pZCA9IGlkO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFBvbGlzaFxyXG4gICAgY29uc3QgYm9uZXMgPSBuZXdTa2VsZXRvbi5ib25lcztcclxuICAgIG5ld1NrZWxldG9uLmJvbmVzID0gW107XHJcblxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBza2lucy5qb2ludE5hbWVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgY29uc3Qgam9pbnROb2RlID0gZ2V0Sm9pbnROb2RlKGdsdGZSdW50aW1lLCBza2lucy5qb2ludE5hbWVzW2ldKTtcclxuXHJcbiAgICAgICAgaWYgKCFqb2ludE5vZGUpIHtcclxuICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmb3IgKGxldCBqID0gMDsgaiA8IGJvbmVzLmxlbmd0aDsgaisrKSB7XHJcbiAgICAgICAgICAgIGlmIChib25lc1tqXS5pZCA9PT0gam9pbnROb2RlLmlkKSB7XHJcbiAgICAgICAgICAgICAgICBuZXdTa2VsZXRvbi5ib25lcy5wdXNoKGJvbmVzW2pdKTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIG5ld1NrZWxldG9uLnByZXBhcmUoKTtcclxuXHJcbiAgICAvLyBGaW5pc2hcclxuICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbm9kZXNUb1Jvb3RUb0FkZC5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIG5ld1NrZWxldG9uLmJvbmVzLnB1c2gobm9kZXNUb1Jvb3RUb0FkZFtpXSk7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIG5ld1NrZWxldG9uO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIEltcG9ydHMgYSBtZXNoIGFuZCBpdHMgZ2VvbWV0cmllc1xyXG4gKiBAcGFyYW0gZ2x0ZlJ1bnRpbWVcclxuICogQHBhcmFtIG5vZGVcclxuICogQHBhcmFtIG1lc2hlc1xyXG4gKiBAcGFyYW0gaWRcclxuICogQHBhcmFtIG5ld01lc2hcclxuICovXHJcbmNvbnN0IGltcG9ydE1lc2ggPSAoZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSwgbm9kZTogSUdMVEZOb2RlLCBtZXNoZXM6IHN0cmluZ1tdLCBpZDogc3RyaW5nLCBuZXdNZXNoOiBNZXNoKTogTWVzaCA9PiB7XHJcbiAgICBpZiAoIW5ld01lc2gpIHtcclxuICAgICAgICBnbHRmUnVudGltZS5zY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gISFnbHRmUnVudGltZS5hc3NldENvbnRhaW5lcjtcclxuICAgICAgICBuZXdNZXNoID0gbmV3IE1lc2gobm9kZS5uYW1lIHx8IFwiXCIsIGdsdGZSdW50aW1lLnNjZW5lKTtcclxuICAgICAgICBuZXdNZXNoLl9wYXJlbnRDb250YWluZXIgPSBnbHRmUnVudGltZS5hc3NldENvbnRhaW5lcjtcclxuICAgICAgICBnbHRmUnVudGltZS5zY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gZmFsc2U7XHJcbiAgICAgICAgbmV3TWVzaC5pZCA9IGlkO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghbm9kZS5iYWJ5bG9uTm9kZSkge1xyXG4gICAgICAgIHJldHVybiBuZXdNZXNoO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IHN1Yk1hdGVyaWFsczogTWF0ZXJpYWxbXSA9IFtdO1xyXG5cclxuICAgIGxldCB2ZXJ0ZXhEYXRhOiBOdWxsYWJsZTxWZXJ0ZXhEYXRhPiA9IG51bGw7XHJcbiAgICBjb25zdCB2ZXJ0aWNlc1N0YXJ0cyA9IG5ldyBBcnJheTxudW1iZXI+KCk7XHJcbiAgICBjb25zdCB2ZXJ0aWNlc0NvdW50cyA9IG5ldyBBcnJheTxudW1iZXI+KCk7XHJcbiAgICBjb25zdCBpbmRleFN0YXJ0cyA9IG5ldyBBcnJheTxudW1iZXI+KCk7XHJcbiAgICBjb25zdCBpbmRleENvdW50cyA9IG5ldyBBcnJheTxudW1iZXI+KCk7XHJcblxyXG4gICAgZm9yIChsZXQgbWVzaEluZGV4ID0gMDsgbWVzaEluZGV4IDwgbWVzaGVzLmxlbmd0aDsgbWVzaEluZGV4KyspIHtcclxuICAgICAgICBjb25zdCBtZXNoSWQgPSBtZXNoZXNbbWVzaEluZGV4XTtcclxuICAgICAgICBjb25zdCBtZXNoOiBJR0xURk1lc2ggPSBnbHRmUnVudGltZS5tZXNoZXNbbWVzaElkXTtcclxuXHJcbiAgICAgICAgaWYgKCFtZXNoKSB7XHJcbiAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gUG9zaXRpb25zLCBub3JtYWxzIGFuZCBVVnNcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IG1lc2gucHJpbWl0aXZlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICAvLyBUZW1wb3JhcnkgdmVydGV4IGRhdGFcclxuICAgICAgICAgICAgY29uc3QgdGVtcFZlcnRleERhdGEgPSBuZXcgVmVydGV4RGF0YSgpO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgcHJpbWl0aXZlID0gbWVzaC5wcmltaXRpdmVzW2ldO1xyXG4gICAgICAgICAgICBpZiAocHJpbWl0aXZlLm1vZGUgIT09IDQpIHtcclxuICAgICAgICAgICAgICAgIC8vIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBhdHRyaWJ1dGVzID0gcHJpbWl0aXZlLmF0dHJpYnV0ZXM7XHJcbiAgICAgICAgICAgIGxldCBhY2Nlc3NvcjogTnVsbGFibGU8SUdMVEZBY2Nlc3Nvcj4gPSBudWxsO1xyXG4gICAgICAgICAgICBsZXQgYnVmZmVyOiBhbnkgPSBudWxsO1xyXG5cclxuICAgICAgICAgICAgLy8gU2V0IHBvc2l0aW9ucywgbm9ybWFsIGFuZCB1dnNcclxuICAgICAgICAgICAgZm9yIChjb25zdCBzZW1hbnRpYyBpbiBhdHRyaWJ1dGVzKSB7XHJcbiAgICAgICAgICAgICAgICAvLyBMaW5rIGFjY2Vzc29yIGFuZCBidWZmZXIgdmlld1xyXG4gICAgICAgICAgICAgICAgYWNjZXNzb3IgPSBnbHRmUnVudGltZS5hY2Nlc3NvcnNbYXR0cmlidXRlc1tzZW1hbnRpY11dO1xyXG4gICAgICAgICAgICAgICAgYnVmZmVyID0gR0xURlV0aWxzLkdldEJ1ZmZlckZyb21BY2Nlc3NvcihnbHRmUnVudGltZSwgYWNjZXNzb3IpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChzZW1hbnRpYyA9PT0gXCJOT1JNQUxcIikge1xyXG4gICAgICAgICAgICAgICAgICAgIHRlbXBWZXJ0ZXhEYXRhLm5vcm1hbHMgPSBuZXcgRmxvYXQzMkFycmF5KGJ1ZmZlci5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgICAgICg8RmxvYXQzMkFycmF5PnRlbXBWZXJ0ZXhEYXRhLm5vcm1hbHMpLnNldChidWZmZXIpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChzZW1hbnRpYyA9PT0gXCJQT1NJVElPTlwiKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKEdMVEZGaWxlTG9hZGVyLkhvbW9nZW5lb3VzQ29vcmRpbmF0ZXMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGVtcFZlcnRleERhdGEucG9zaXRpb25zID0gbmV3IEZsb2F0MzJBcnJheShidWZmZXIubGVuZ3RoIC0gYnVmZmVyLmxlbmd0aCAvIDQpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCBidWZmZXIubGVuZ3RoOyBqICs9IDQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlbXBWZXJ0ZXhEYXRhLnBvc2l0aW9uc1tqXSA9IGJ1ZmZlcltqXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRlbXBWZXJ0ZXhEYXRhLnBvc2l0aW9uc1tqICsgMV0gPSBidWZmZXJbaiArIDFdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGVtcFZlcnRleERhdGEucG9zaXRpb25zW2ogKyAyXSA9IGJ1ZmZlcltqICsgMl07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZW1wVmVydGV4RGF0YS5wb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KGJ1ZmZlci5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAoPEZsb2F0MzJBcnJheT50ZW1wVmVydGV4RGF0YS5wb3NpdGlvbnMpLnNldChidWZmZXIpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgdmVydGljZXNDb3VudHMucHVzaCh0ZW1wVmVydGV4RGF0YS5wb3NpdGlvbnMubGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc2VtYW50aWMuaW5kZXhPZihcIlRFWENPT1JEX1wiKSAhPT0gLTEpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBjaGFubmVsID0gTnVtYmVyKHNlbWFudGljLnNwbGl0KFwiX1wiKVsxXSk7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdXZLaW5kID0gVmVydGV4QnVmZmVyLlVWS2luZCArIChjaGFubmVsID09PSAwID8gXCJcIiA6IGNoYW5uZWwgKyAxKTtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCB1dnMgPSBuZXcgRmxvYXQzMkFycmF5KGJ1ZmZlci5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgICAgICg8RmxvYXQzMkFycmF5PnV2cykuc2V0KGJ1ZmZlcik7XHJcbiAgICAgICAgICAgICAgICAgICAgbm9ybWFsaXplVVZzKHV2cyk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGVtcFZlcnRleERhdGEuc2V0KHV2cywgdXZLaW5kKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc2VtYW50aWMgPT09IFwiSk9JTlRcIikge1xyXG4gICAgICAgICAgICAgICAgICAgIHRlbXBWZXJ0ZXhEYXRhLm1hdHJpY2VzSW5kaWNlcyA9IG5ldyBGbG9hdDMyQXJyYXkoYnVmZmVyLmxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgKDxGbG9hdDMyQXJyYXk+dGVtcFZlcnRleERhdGEubWF0cmljZXNJbmRpY2VzKS5zZXQoYnVmZmVyKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoc2VtYW50aWMgPT09IFwiV0VJR0hUXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICB0ZW1wVmVydGV4RGF0YS5tYXRyaWNlc1dlaWdodHMgPSBuZXcgRmxvYXQzMkFycmF5KGJ1ZmZlci5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgICAgICg8RmxvYXQzMkFycmF5PnRlbXBWZXJ0ZXhEYXRhLm1hdHJpY2VzV2VpZ2h0cykuc2V0KGJ1ZmZlcik7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHNlbWFudGljID09PSBcIkNPTE9SXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICB0ZW1wVmVydGV4RGF0YS5jb2xvcnMgPSBuZXcgRmxvYXQzMkFycmF5KGJ1ZmZlci5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgICAgICg8RmxvYXQzMkFycmF5PnRlbXBWZXJ0ZXhEYXRhLmNvbG9ycykuc2V0KGJ1ZmZlcik7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIEluZGljZXNcclxuICAgICAgICAgICAgYWNjZXNzb3IgPSBnbHRmUnVudGltZS5hY2Nlc3NvcnNbcHJpbWl0aXZlLmluZGljZXNdO1xyXG4gICAgICAgICAgICBpZiAoYWNjZXNzb3IpIHtcclxuICAgICAgICAgICAgICAgIGJ1ZmZlciA9IEdMVEZVdGlscy5HZXRCdWZmZXJGcm9tQWNjZXNzb3IoZ2x0ZlJ1bnRpbWUsIGFjY2Vzc29yKTtcclxuXHJcbiAgICAgICAgICAgICAgICB0ZW1wVmVydGV4RGF0YS5pbmRpY2VzID0gbmV3IEludDMyQXJyYXkoYnVmZmVyLmxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICB0ZW1wVmVydGV4RGF0YS5pbmRpY2VzLnNldChidWZmZXIpO1xyXG4gICAgICAgICAgICAgICAgaW5kZXhDb3VudHMucHVzaCh0ZW1wVmVydGV4RGF0YS5pbmRpY2VzLmxlbmd0aCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAvLyBTZXQgaW5kaWNlcyBvbiB0aGUgZmx5XHJcbiAgICAgICAgICAgICAgICBjb25zdCBpbmRpY2VzOiBudW1iZXJbXSA9IFtdO1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCAoPEZsb2F0QXJyYXk+dGVtcFZlcnRleERhdGEucG9zaXRpb25zKS5sZW5ndGggLyAzOyBqKyspIHtcclxuICAgICAgICAgICAgICAgICAgICBpbmRpY2VzLnB1c2goaik7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgdGVtcFZlcnRleERhdGEuaW5kaWNlcyA9IG5ldyBJbnQzMkFycmF5KGluZGljZXMpO1xyXG4gICAgICAgICAgICAgICAgaW5kZXhDb3VudHMucHVzaCh0ZW1wVmVydGV4RGF0YS5pbmRpY2VzLmxlbmd0aCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGlmICghdmVydGV4RGF0YSkge1xyXG4gICAgICAgICAgICAgICAgdmVydGV4RGF0YSA9IHRlbXBWZXJ0ZXhEYXRhO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgdmVydGV4RGF0YS5tZXJnZSh0ZW1wVmVydGV4RGF0YSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIFN1YiBtYXRlcmlhbFxyXG4gICAgICAgICAgICBjb25zdCBtYXRlcmlhbCA9IGdsdGZSdW50aW1lLnNjZW5lLmdldE1hdGVyaWFsQnlJZChwcmltaXRpdmUubWF0ZXJpYWwpO1xyXG5cclxuICAgICAgICAgICAgc3ViTWF0ZXJpYWxzLnB1c2gobWF0ZXJpYWwgPT09IG51bGwgPyBHTFRGVXRpbHMuR2V0RGVmYXVsdE1hdGVyaWFsKGdsdGZSdW50aW1lLnNjZW5lKSA6IG1hdGVyaWFsKTtcclxuXHJcbiAgICAgICAgICAgIC8vIFVwZGF0ZSB2ZXJ0aWNlcyBzdGFydCBhbmQgaW5kZXggc3RhcnRcclxuICAgICAgICAgICAgdmVydGljZXNTdGFydHMucHVzaCh2ZXJ0aWNlc1N0YXJ0cy5sZW5ndGggPT09IDAgPyAwIDogdmVydGljZXNTdGFydHNbdmVydGljZXNTdGFydHMubGVuZ3RoIC0gMV0gKyB2ZXJ0aWNlc0NvdW50c1t2ZXJ0aWNlc0NvdW50cy5sZW5ndGggLSAyXSk7XHJcbiAgICAgICAgICAgIGluZGV4U3RhcnRzLnB1c2goaW5kZXhTdGFydHMubGVuZ3RoID09PSAwID8gMCA6IGluZGV4U3RhcnRzW2luZGV4U3RhcnRzLmxlbmd0aCAtIDFdICsgaW5kZXhDb3VudHNbaW5kZXhDb3VudHMubGVuZ3RoIC0gMl0pO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGxldCBtYXRlcmlhbDogU3RhbmRhcmRNYXRlcmlhbCB8IE11bHRpTWF0ZXJpYWw7XHJcbiAgICBnbHRmUnVudGltZS5zY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gISFnbHRmUnVudGltZS5hc3NldENvbnRhaW5lcjtcclxuICAgIGlmIChzdWJNYXRlcmlhbHMubGVuZ3RoID4gMSkge1xyXG4gICAgICAgIG1hdGVyaWFsID0gbmV3IE11bHRpTWF0ZXJpYWwoXCJtdWx0aW1hdFwiICsgaWQsIGdsdGZSdW50aW1lLnNjZW5lKTtcclxuICAgICAgICAobWF0ZXJpYWwgYXMgTXVsdGlNYXRlcmlhbCkuc3ViTWF0ZXJpYWxzID0gc3ViTWF0ZXJpYWxzO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICBtYXRlcmlhbCA9IG5ldyBTdGFuZGFyZE1hdGVyaWFsKFwibXVsdGltYXRcIiArIGlkLCBnbHRmUnVudGltZS5zY2VuZSk7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKHN1Yk1hdGVyaWFscy5sZW5ndGggPT09IDEpIHtcclxuICAgICAgICBtYXRlcmlhbCA9IHN1Yk1hdGVyaWFsc1swXSBhcyBTdGFuZGFyZE1hdGVyaWFsO1xyXG4gICAgfVxyXG5cclxuICAgIG1hdGVyaWFsLl9wYXJlbnRDb250YWluZXIgPSBnbHRmUnVudGltZS5hc3NldENvbnRhaW5lcjtcclxuXHJcbiAgICBpZiAoIW5ld01lc2gubWF0ZXJpYWwpIHtcclxuICAgICAgICBuZXdNZXNoLm1hdGVyaWFsID0gbWF0ZXJpYWw7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQXBwbHkgZ2VvbWV0cnlcclxuICAgIG5ldyBHZW9tZXRyeShpZCwgZ2x0ZlJ1bnRpbWUuc2NlbmUsIHZlcnRleERhdGEhLCBmYWxzZSwgbmV3TWVzaCk7XHJcbiAgICBuZXdNZXNoLmNvbXB1dGVXb3JsZE1hdHJpeCh0cnVlKTtcclxuXHJcbiAgICBnbHRmUnVudGltZS5zY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gZmFsc2U7XHJcblxyXG4gICAgLy8gQXBwbHkgc3VibWVzaGVzXHJcbiAgICBuZXdNZXNoLnN1Yk1lc2hlcyA9IFtdO1xyXG4gICAgbGV0IGluZGV4ID0gMDtcclxuICAgIGZvciAobGV0IG1lc2hJbmRleCA9IDA7IG1lc2hJbmRleCA8IG1lc2hlcy5sZW5ndGg7IG1lc2hJbmRleCsrKSB7XHJcbiAgICAgICAgY29uc3QgbWVzaElkID0gbWVzaGVzW21lc2hJbmRleF07XHJcbiAgICAgICAgY29uc3QgbWVzaDogSUdMVEZNZXNoID0gZ2x0ZlJ1bnRpbWUubWVzaGVzW21lc2hJZF07XHJcblxyXG4gICAgICAgIGlmICghbWVzaCkge1xyXG4gICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbWVzaC5wcmltaXRpdmVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChtZXNoLnByaW1pdGl2ZXNbaV0ubW9kZSAhPT0gNCkge1xyXG4gICAgICAgICAgICAgICAgLy9jb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgU3ViTWVzaC5BZGRUb01lc2goaW5kZXgsIHZlcnRpY2VzU3RhcnRzW2luZGV4XSwgdmVydGljZXNDb3VudHNbaW5kZXhdLCBpbmRleFN0YXJ0c1tpbmRleF0sIGluZGV4Q291bnRzW2luZGV4XSwgbmV3TWVzaCwgbmV3TWVzaCwgdHJ1ZSk7XHJcbiAgICAgICAgICAgIGluZGV4Kys7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIEZpbmlzaFxyXG4gICAgcmV0dXJuIG5ld01lc2g7XHJcbn07XHJcblxyXG4vKipcclxuICogQ29uZmlndXJlIG5vZGUgdHJhbnNmb3JtYXRpb24gZnJvbSBwb3NpdGlvbiwgcm90YXRpb24gYW5kIHNjYWxpbmdcclxuICogQHBhcmFtIG5ld05vZGVcclxuICogQHBhcmFtIHBvc2l0aW9uXHJcbiAqIEBwYXJhbSByb3RhdGlvblxyXG4gKiBAcGFyYW0gc2NhbGluZ1xyXG4gKi9cclxuY29uc3QgY29uZmlndXJlTm9kZSA9IChuZXdOb2RlOiBhbnksIHBvc2l0aW9uOiBWZWN0b3IzLCByb3RhdGlvbjogUXVhdGVybmlvbiwgc2NhbGluZzogVmVjdG9yMykgPT4ge1xyXG4gICAgaWYgKG5ld05vZGUucG9zaXRpb24pIHtcclxuICAgICAgICBuZXdOb2RlLnBvc2l0aW9uID0gcG9zaXRpb247XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKG5ld05vZGUucm90YXRpb25RdWF0ZXJuaW9uIHx8IG5ld05vZGUucm90YXRpb24pIHtcclxuICAgICAgICBuZXdOb2RlLnJvdGF0aW9uUXVhdGVybmlvbiA9IHJvdGF0aW9uO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChuZXdOb2RlLnNjYWxpbmcpIHtcclxuICAgICAgICBuZXdOb2RlLnNjYWxpbmcgPSBzY2FsaW5nO1xyXG4gICAgfVxyXG59O1xyXG5cclxuLyoqXHJcbiAqIENvbmZpZ3VyZXMgbm9kZSBmcm9tIHRyYW5zZm9ybWF0aW9uIG1hdHJpeFxyXG4gKiBAcGFyYW0gbmV3Tm9kZVxyXG4gKiBAcGFyYW0gbm9kZVxyXG4gKi9cclxuY29uc3QgY29uZmlndXJlTm9kZUZyb21NYXRyaXggPSAobmV3Tm9kZTogTWVzaCwgbm9kZTogSUdMVEZOb2RlKSA9PiB7XHJcbiAgICBpZiAobm9kZS5tYXRyaXgpIHtcclxuICAgICAgICBjb25zdCBwb3NpdGlvbiA9IG5ldyBWZWN0b3IzKDAsIDAsIDApO1xyXG4gICAgICAgIGNvbnN0IHJvdGF0aW9uID0gbmV3IFF1YXRlcm5pb24oKTtcclxuICAgICAgICBjb25zdCBzY2FsaW5nID0gbmV3IFZlY3RvcjMoMCwgMCwgMCk7XHJcbiAgICAgICAgY29uc3QgbWF0ID0gTWF0cml4LkZyb21BcnJheShub2RlLm1hdHJpeCk7XHJcbiAgICAgICAgbWF0LmRlY29tcG9zZShzY2FsaW5nLCByb3RhdGlvbiwgcG9zaXRpb24pO1xyXG5cclxuICAgICAgICBjb25maWd1cmVOb2RlKG5ld05vZGUsIHBvc2l0aW9uLCByb3RhdGlvbiwgc2NhbGluZyk7XHJcbiAgICB9IGVsc2UgaWYgKG5vZGUudHJhbnNsYXRpb24gJiYgbm9kZS5yb3RhdGlvbiAmJiBub2RlLnNjYWxlKSB7XHJcbiAgICAgICAgY29uZmlndXJlTm9kZShuZXdOb2RlLCBWZWN0b3IzLkZyb21BcnJheShub2RlLnRyYW5zbGF0aW9uKSwgUXVhdGVybmlvbi5Gcm9tQXJyYXkobm9kZS5yb3RhdGlvbiksIFZlY3RvcjMuRnJvbUFycmF5KG5vZGUuc2NhbGUpKTtcclxuICAgIH1cclxuXHJcbiAgICBuZXdOb2RlLmNvbXB1dGVXb3JsZE1hdHJpeCh0cnVlKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBJbXBvcnRzIGEgbm9kZVxyXG4gKiBAcGFyYW0gZ2x0ZlJ1bnRpbWVcclxuICogQHBhcmFtIG5vZGVcclxuICogQHBhcmFtIGlkXHJcbiAqL1xyXG5jb25zdCBpbXBvcnROb2RlID0gKGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUsIG5vZGU6IElHTFRGTm9kZSwgaWQ6IHN0cmluZyk6IE51bGxhYmxlPE5vZGU+ID0+IHtcclxuICAgIGxldCBsYXN0Tm9kZTogTnVsbGFibGU8Tm9kZT4gPSBudWxsO1xyXG5cclxuICAgIGlmIChnbHRmUnVudGltZS5pbXBvcnRPbmx5TWVzaGVzICYmIChub2RlLnNraW4gfHwgbm9kZS5tZXNoZXMpKSB7XHJcbiAgICAgICAgaWYgKGdsdGZSdW50aW1lLmltcG9ydE1lc2hlc05hbWVzICYmIGdsdGZSdW50aW1lLmltcG9ydE1lc2hlc05hbWVzLmxlbmd0aCA+IDAgJiYgZ2x0ZlJ1bnRpbWUuaW1wb3J0TWVzaGVzTmFtZXMuaW5kZXhPZihub2RlLm5hbWUgfHwgXCJcIikgPT09IC0xKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvLyBNZXNoZXNcclxuICAgIGlmIChub2RlLnNraW4pIHtcclxuICAgICAgICBpZiAobm9kZS5tZXNoZXMpIHtcclxuICAgICAgICAgICAgY29uc3Qgc2tpbjogSUdMVEZTa2lucyA9IGdsdGZSdW50aW1lLnNraW5zW25vZGUuc2tpbl07XHJcblxyXG4gICAgICAgICAgICBjb25zdCBuZXdNZXNoID0gaW1wb3J0TWVzaChnbHRmUnVudGltZSwgbm9kZSwgbm9kZS5tZXNoZXMsIGlkLCA8TWVzaD5ub2RlLmJhYnlsb25Ob2RlKTtcclxuICAgICAgICAgICAgbmV3TWVzaC5za2VsZXRvbiA9IGdsdGZSdW50aW1lLnNjZW5lLmdldExhc3RTa2VsZXRvbkJ5SWQobm9kZS5za2luKTtcclxuXHJcbiAgICAgICAgICAgIGlmIChuZXdNZXNoLnNrZWxldG9uID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICBuZXdNZXNoLnNrZWxldG9uID0gaW1wb3J0U2tlbGV0b24oZ2x0ZlJ1bnRpbWUsIHNraW4sIG5ld01lc2gsIHNraW4uYmFieWxvblNrZWxldG9uKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoIXNraW4uYmFieWxvblNrZWxldG9uKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgc2tpbi5iYWJ5bG9uU2tlbGV0b24gPSBuZXdNZXNoLnNrZWxldG9uO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBsYXN0Tm9kZSA9IG5ld01lc2g7XHJcbiAgICAgICAgfVxyXG4gICAgfSBlbHNlIGlmIChub2RlLm1lc2hlcykge1xyXG4gICAgICAgIC8qKlxyXG4gICAgICAgICAqIEltcHJvdmUgbWVzaGVzIHByb3BlcnR5XHJcbiAgICAgICAgICovXHJcbiAgICAgICAgY29uc3QgbmV3TWVzaCA9IGltcG9ydE1lc2goZ2x0ZlJ1bnRpbWUsIG5vZGUsIG5vZGUubWVzaCA/IFtub2RlLm1lc2hdIDogbm9kZS5tZXNoZXMsIGlkLCA8TWVzaD5ub2RlLmJhYnlsb25Ob2RlKTtcclxuICAgICAgICBsYXN0Tm9kZSA9IG5ld01lc2g7XHJcbiAgICB9XHJcbiAgICAvLyBMaWdodHNcclxuICAgIGVsc2UgaWYgKG5vZGUubGlnaHQgJiYgIW5vZGUuYmFieWxvbk5vZGUgJiYgIWdsdGZSdW50aW1lLmltcG9ydE9ubHlNZXNoZXMpIHtcclxuICAgICAgICBjb25zdCBsaWdodDogSUdMVEZMaWdodCA9IGdsdGZSdW50aW1lLmxpZ2h0c1tub2RlLmxpZ2h0XTtcclxuXHJcbiAgICAgICAgaWYgKGxpZ2h0KSB7XHJcbiAgICAgICAgICAgIGlmIChsaWdodC50eXBlID09PSBcImFtYmllbnRcIikge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgYW1iaWVuTGlnaHQ6IElHTFRGQW1iaWVuTGlnaHQgPSAoPGFueT5saWdodClbbGlnaHQudHlwZV07XHJcbiAgICAgICAgICAgICAgICBjb25zdCBoZW1pTGlnaHQgPSBuZXcgSGVtaXNwaGVyaWNMaWdodChub2RlLmxpZ2h0LCBWZWN0b3IzLlplcm8oKSwgZ2x0ZlJ1bnRpbWUuc2NlbmUpO1xyXG4gICAgICAgICAgICAgICAgaGVtaUxpZ2h0Lm5hbWUgPSBub2RlLm5hbWUgfHwgXCJcIjtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoYW1iaWVuTGlnaHQuY29sb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICBoZW1pTGlnaHQuZGlmZnVzZSA9IENvbG9yMy5Gcm9tQXJyYXkoYW1iaWVuTGlnaHQuY29sb3IpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGxhc3ROb2RlID0gaGVtaUxpZ2h0O1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKGxpZ2h0LnR5cGUgPT09IFwiZGlyZWN0aW9uYWxcIikge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZGlyZWN0aW9uYWxMaWdodDogSUdMVEZEaXJlY3Rpb25hbExpZ2h0ID0gKDxhbnk+bGlnaHQpW2xpZ2h0LnR5cGVdO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZGlyTGlnaHQgPSBuZXcgRGlyZWN0aW9uYWxMaWdodChub2RlLmxpZ2h0LCBWZWN0b3IzLlplcm8oKSwgZ2x0ZlJ1bnRpbWUuc2NlbmUpO1xyXG4gICAgICAgICAgICAgICAgZGlyTGlnaHQubmFtZSA9IG5vZGUubmFtZSB8fCBcIlwiO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChkaXJlY3Rpb25hbExpZ2h0LmNvbG9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZGlyTGlnaHQuZGlmZnVzZSA9IENvbG9yMy5Gcm9tQXJyYXkoZGlyZWN0aW9uYWxMaWdodC5jb2xvcik7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbGFzdE5vZGUgPSBkaXJMaWdodDtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChsaWdodC50eXBlID09PSBcInBvaW50XCIpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHBvaW50TGlnaHQ6IElHTFRGUG9pbnRMaWdodCA9ICg8YW55PmxpZ2h0KVtsaWdodC50eXBlXTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHB0TGlnaHQgPSBuZXcgUG9pbnRMaWdodChub2RlLmxpZ2h0LCBWZWN0b3IzLlplcm8oKSwgZ2x0ZlJ1bnRpbWUuc2NlbmUpO1xyXG4gICAgICAgICAgICAgICAgcHRMaWdodC5uYW1lID0gbm9kZS5uYW1lIHx8IFwiXCI7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKHBvaW50TGlnaHQuY29sb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICBwdExpZ2h0LmRpZmZ1c2UgPSBDb2xvcjMuRnJvbUFycmF5KHBvaW50TGlnaHQuY29sb3IpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGxhc3ROb2RlID0gcHRMaWdodDtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChsaWdodC50eXBlID09PSBcInNwb3RcIikge1xyXG4gICAgICAgICAgICAgICAgY29uc3Qgc3BvdExpZ2h0OiBJR0xURlNwb3RMaWdodCA9ICg8YW55PmxpZ2h0KVtsaWdodC50eXBlXTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHNwTGlnaHQgPSBuZXcgU3BvdExpZ2h0KG5vZGUubGlnaHQsIFZlY3RvcjMuWmVybygpLCBWZWN0b3IzLlplcm8oKSwgMCwgMCwgZ2x0ZlJ1bnRpbWUuc2NlbmUpO1xyXG4gICAgICAgICAgICAgICAgc3BMaWdodC5uYW1lID0gbm9kZS5uYW1lIHx8IFwiXCI7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKHNwb3RMaWdodC5jb2xvcikge1xyXG4gICAgICAgICAgICAgICAgICAgIHNwTGlnaHQuZGlmZnVzZSA9IENvbG9yMy5Gcm9tQXJyYXkoc3BvdExpZ2h0LmNvbG9yKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoc3BvdExpZ2h0LmZhbGxPZkFuZ2xlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgc3BMaWdodC5hbmdsZSA9IHNwb3RMaWdodC5mYWxsT2ZBbmdsZTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoc3BvdExpZ2h0LmZhbGxPZmZFeHBvbmVudCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHNwTGlnaHQuZXhwb25lbnQgPSBzcG90TGlnaHQuZmFsbE9mZkV4cG9uZW50O1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGxhc3ROb2RlID0gc3BMaWdodDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIC8vIENhbWVyYXNcclxuICAgIGVsc2UgaWYgKG5vZGUuY2FtZXJhICYmICFub2RlLmJhYnlsb25Ob2RlICYmICFnbHRmUnVudGltZS5pbXBvcnRPbmx5TWVzaGVzKSB7XHJcbiAgICAgICAgY29uc3QgY2FtZXJhOiBJR0xURkNhbWVyYSA9IGdsdGZSdW50aW1lLmNhbWVyYXNbbm9kZS5jYW1lcmFdO1xyXG5cclxuICAgICAgICBpZiAoY2FtZXJhKSB7XHJcbiAgICAgICAgICAgIGdsdGZSdW50aW1lLnNjZW5lLl9ibG9ja0VudGl0eUNvbGxlY3Rpb24gPSAhIWdsdGZSdW50aW1lLmFzc2V0Q29udGFpbmVyO1xyXG4gICAgICAgICAgICBpZiAoY2FtZXJhLnR5cGUgPT09IFwib3J0aG9ncmFwaGljXCIpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG9ydGhvQ2FtZXJhID0gbmV3IEZyZWVDYW1lcmEobm9kZS5jYW1lcmEsIFZlY3RvcjMuWmVybygpLCBnbHRmUnVudGltZS5zY2VuZSwgZmFsc2UpO1xyXG5cclxuICAgICAgICAgICAgICAgIG9ydGhvQ2FtZXJhLm5hbWUgPSBub2RlLm5hbWUgfHwgXCJcIjtcclxuICAgICAgICAgICAgICAgIG9ydGhvQ2FtZXJhLm1vZGUgPSBDYW1lcmEuT1JUSE9HUkFQSElDX0NBTUVSQTtcclxuICAgICAgICAgICAgICAgIG9ydGhvQ2FtZXJhLmF0dGFjaENvbnRyb2woKTtcclxuXHJcbiAgICAgICAgICAgICAgICBsYXN0Tm9kZSA9IG9ydGhvQ2FtZXJhO1xyXG5cclxuICAgICAgICAgICAgICAgIG9ydGhvQ2FtZXJhLl9wYXJlbnRDb250YWluZXIgPSBnbHRmUnVudGltZS5hc3NldENvbnRhaW5lcjtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChjYW1lcmEudHlwZSA9PT0gXCJwZXJzcGVjdGl2ZVwiKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBwZXJzcGVjdGl2ZUNhbWVyYTogSUdMVEZDYW1lcmFQZXJzcGVjdGl2ZSA9ICg8YW55PmNhbWVyYSlbY2FtZXJhLnR5cGVdO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcGVyc0NhbWVyYSA9IG5ldyBGcmVlQ2FtZXJhKG5vZGUuY2FtZXJhLCBWZWN0b3IzLlplcm8oKSwgZ2x0ZlJ1bnRpbWUuc2NlbmUsIGZhbHNlKTtcclxuXHJcbiAgICAgICAgICAgICAgICBwZXJzQ2FtZXJhLm5hbWUgPSBub2RlLm5hbWUgfHwgXCJcIjtcclxuICAgICAgICAgICAgICAgIHBlcnNDYW1lcmEuYXR0YWNoQ29udHJvbCgpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICghcGVyc3BlY3RpdmVDYW1lcmEuYXNwZWN0UmF0aW8pIHtcclxuICAgICAgICAgICAgICAgICAgICBwZXJzcGVjdGl2ZUNhbWVyYS5hc3BlY3RSYXRpbyA9IGdsdGZSdW50aW1lLnNjZW5lLmdldEVuZ2luZSgpLmdldFJlbmRlcldpZHRoKCkgLyBnbHRmUnVudGltZS5zY2VuZS5nZXRFbmdpbmUoKS5nZXRSZW5kZXJIZWlnaHQoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAocGVyc3BlY3RpdmVDYW1lcmEuem5lYXIgJiYgcGVyc3BlY3RpdmVDYW1lcmEuemZhcikge1xyXG4gICAgICAgICAgICAgICAgICAgIHBlcnNDYW1lcmEubWF4WiA9IHBlcnNwZWN0aXZlQ2FtZXJhLnpmYXI7XHJcbiAgICAgICAgICAgICAgICAgICAgcGVyc0NhbWVyYS5taW5aID0gcGVyc3BlY3RpdmVDYW1lcmEuem5lYXI7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgbGFzdE5vZGUgPSBwZXJzQ2FtZXJhO1xyXG4gICAgICAgICAgICAgICAgcGVyc0NhbWVyYS5fcGFyZW50Q29udGFpbmVyID0gZ2x0ZlJ1bnRpbWUuYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGdsdGZSdW50aW1lLnNjZW5lLl9ibG9ja0VudGl0eUNvbGxlY3Rpb24gPSBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gRW1wdHkgbm9kZVxyXG4gICAgaWYgKCFub2RlLmpvaW50TmFtZSkge1xyXG4gICAgICAgIGlmIChub2RlLmJhYnlsb25Ob2RlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBub2RlLmJhYnlsb25Ob2RlO1xyXG4gICAgICAgIH0gZWxzZSBpZiAobGFzdE5vZGUgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgZ2x0ZlJ1bnRpbWUuc2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9ICEhZ2x0ZlJ1bnRpbWUuYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgICAgIGNvbnN0IGR1bW15ID0gbmV3IE1lc2gobm9kZS5uYW1lIHx8IFwiXCIsIGdsdGZSdW50aW1lLnNjZW5lKTtcclxuICAgICAgICAgICAgZHVtbXkuX3BhcmVudENvbnRhaW5lciA9IGdsdGZSdW50aW1lLmFzc2V0Q29udGFpbmVyO1xyXG4gICAgICAgICAgICBnbHRmUnVudGltZS5zY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gZmFsc2U7XHJcbiAgICAgICAgICAgIG5vZGUuYmFieWxvbk5vZGUgPSBkdW1teTtcclxuICAgICAgICAgICAgbGFzdE5vZGUgPSBkdW1teTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGxhc3ROb2RlICE9PSBudWxsKSB7XHJcbiAgICAgICAgaWYgKG5vZGUubWF0cml4ICYmIGxhc3ROb2RlIGluc3RhbmNlb2YgTWVzaCkge1xyXG4gICAgICAgICAgICBjb25maWd1cmVOb2RlRnJvbU1hdHJpeChsYXN0Tm9kZSwgbm9kZSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgY29uc3QgdHJhbnNsYXRpb24gPSBub2RlLnRyYW5zbGF0aW9uIHx8IFswLCAwLCAwXTtcclxuICAgICAgICAgICAgY29uc3Qgcm90YXRpb24gPSBub2RlLnJvdGF0aW9uIHx8IFswLCAwLCAwLCAxXTtcclxuICAgICAgICAgICAgY29uc3Qgc2NhbGUgPSBub2RlLnNjYWxlIHx8IFsxLCAxLCAxXTtcclxuICAgICAgICAgICAgY29uZmlndXJlTm9kZShsYXN0Tm9kZSwgVmVjdG9yMy5Gcm9tQXJyYXkodHJhbnNsYXRpb24pLCBRdWF0ZXJuaW9uLkZyb21BcnJheShyb3RhdGlvbiksIFZlY3RvcjMuRnJvbUFycmF5KHNjYWxlKSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsYXN0Tm9kZS51cGRhdGVDYWNoZSh0cnVlKTtcclxuICAgICAgICBub2RlLmJhYnlsb25Ob2RlID0gbGFzdE5vZGU7XHJcbiAgICB9XHJcblxyXG4gICAgcmV0dXJuIGxhc3ROb2RlO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIFRyYXZlcnNlcyBub2RlcyBhbmQgY3JlYXRlcyB0aGVtXHJcbiAqIEBwYXJhbSBnbHRmUnVudGltZVxyXG4gKiBAcGFyYW0gaWRcclxuICogQHBhcmFtIHBhcmVudFxyXG4gKiBAcGFyYW0gbWVzaEluY2x1ZGVkXHJcbiAqL1xyXG5jb25zdCB0cmF2ZXJzZU5vZGVzID0gKGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUsIGlkOiBzdHJpbmcsIHBhcmVudDogTnVsbGFibGU8Tm9kZT4sIG1lc2hJbmNsdWRlZDogYm9vbGVhbiA9IGZhbHNlKSA9PiB7XHJcbiAgICBjb25zdCBub2RlOiBJR0xURk5vZGUgPSBnbHRmUnVudGltZS5ub2Rlc1tpZF07XHJcbiAgICBsZXQgbmV3Tm9kZTogTnVsbGFibGU8Tm9kZT4gPSBudWxsO1xyXG5cclxuICAgIGlmIChnbHRmUnVudGltZS5pbXBvcnRPbmx5TWVzaGVzICYmICFtZXNoSW5jbHVkZWQgJiYgZ2x0ZlJ1bnRpbWUuaW1wb3J0TWVzaGVzTmFtZXMpIHtcclxuICAgICAgICBpZiAoZ2x0ZlJ1bnRpbWUuaW1wb3J0TWVzaGVzTmFtZXMuaW5kZXhPZihub2RlLm5hbWUgfHwgXCJcIikgIT09IC0xIHx8IGdsdGZSdW50aW1lLmltcG9ydE1lc2hlc05hbWVzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICBtZXNoSW5jbHVkZWQgPSB0cnVlO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIG1lc2hJbmNsdWRlZCA9IGZhbHNlO1xyXG4gICAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgICAgbWVzaEluY2x1ZGVkID0gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICBpZiAoIW5vZGUuam9pbnROYW1lICYmIG1lc2hJbmNsdWRlZCkge1xyXG4gICAgICAgIG5ld05vZGUgPSBpbXBvcnROb2RlKGdsdGZSdW50aW1lLCBub2RlLCBpZCk7XHJcblxyXG4gICAgICAgIGlmIChuZXdOb2RlICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgIG5ld05vZGUuaWQgPSBpZDtcclxuICAgICAgICAgICAgbmV3Tm9kZS5wYXJlbnQgPSBwYXJlbnQ7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGlmIChub2RlLmNoaWxkcmVuKSB7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBub2RlLmNoaWxkcmVuLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIHRyYXZlcnNlTm9kZXMoZ2x0ZlJ1bnRpbWUsIG5vZGUuY2hpbGRyZW5baV0sIG5ld05vZGUsIG1lc2hJbmNsdWRlZCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59O1xyXG5cclxuLyoqXHJcbiAqIGRvIHN0dWZmIGFmdGVyIGJ1ZmZlcnMsIHNoYWRlcnMgYXJlIGxvYWRlZCAoZS5nLiBob29rIHVwIG1hdGVyaWFscywgbG9hZCBhbmltYXRpb25zLCBldGMuKVxyXG4gKiBAcGFyYW0gZ2x0ZlJ1bnRpbWVcclxuICovXHJcbmNvbnN0IHBvc3RMb2FkID0gKGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUpID0+IHtcclxuICAgIC8vIE5vZGVzXHJcbiAgICBsZXQgY3VycmVudFNjZW5lOiBJR0xURlNjZW5lID0gPElHTFRGU2NlbmU+Z2x0ZlJ1bnRpbWUuY3VycmVudFNjZW5lO1xyXG5cclxuICAgIGlmIChjdXJyZW50U2NlbmUpIHtcclxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGN1cnJlbnRTY2VuZS5ub2Rlcy5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgICAgICB0cmF2ZXJzZU5vZGVzKGdsdGZSdW50aW1lLCBjdXJyZW50U2NlbmUubm9kZXNbaV0sIG51bGwpO1xyXG4gICAgICAgIH1cclxuICAgIH0gZWxzZSB7XHJcbiAgICAgICAgZm9yIChjb25zdCB0aGluZyBpbiBnbHRmUnVudGltZS5zY2VuZXMpIHtcclxuICAgICAgICAgICAgY3VycmVudFNjZW5lID0gPElHTFRGU2NlbmU+Z2x0ZlJ1bnRpbWUuc2NlbmVzW3RoaW5nXTtcclxuXHJcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY3VycmVudFNjZW5lLm5vZGVzLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICB0cmF2ZXJzZU5vZGVzKGdsdGZSdW50aW1lLCBjdXJyZW50U2NlbmUubm9kZXNbaV0sIG51bGwpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8vIFNldCBhbmltYXRpb25zXHJcbiAgICBsb2FkQW5pbWF0aW9ucyhnbHRmUnVudGltZSk7XHJcblxyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCBnbHRmUnVudGltZS5zY2VuZS5za2VsZXRvbnMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICBjb25zdCBza2VsZXRvbiA9IGdsdGZSdW50aW1lLnNjZW5lLnNrZWxldG9uc1tpXTtcclxuICAgICAgICBnbHRmUnVudGltZS5zY2VuZS5iZWdpbkFuaW1hdGlvbihza2VsZXRvbiwgMCwgTnVtYmVyLk1BWF9WQUxVRSwgdHJ1ZSwgMS4wKTtcclxuICAgIH1cclxufTtcclxuXHJcbi8qKlxyXG4gKiBvbkJpbmQgc2hhZGVycnMgY2FsbGJhY2sgdG8gc2V0IHVuaWZvcm1zIGFuZCBtYXRyaWNlc1xyXG4gKiBAcGFyYW0gbWVzaFxyXG4gKiBAcGFyYW0gZ2x0ZlJ1bnRpbWVcclxuICogQHBhcmFtIHVuVHJlYXRlZFVuaWZvcm1zXHJcbiAqIEBwYXJhbSBzaGFkZXJNYXRlcmlhbFxyXG4gKiBAcGFyYW0gdGVjaG5pcXVlXHJcbiAqIEBwYXJhbSBtYXRlcmlhbFxyXG4gKiBAcGFyYW0gb25TdWNjZXNzXHJcbiAqL1xyXG5jb25zdCBvbkJpbmRTaGFkZXJNYXRlcmlhbCA9IChcclxuICAgIG1lc2g6IEFic3RyYWN0TWVzaCxcclxuICAgIGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUsXHJcbiAgICB1blRyZWF0ZWRVbmlmb3JtczogeyBba2V5OiBzdHJpbmddOiBJR0xURlRlY2huaXF1ZVBhcmFtZXRlciB9LFxyXG4gICAgc2hhZGVyTWF0ZXJpYWw6IFNoYWRlck1hdGVyaWFsLFxyXG4gICAgdGVjaG5pcXVlOiBJR0xURlRlY2huaXF1ZSxcclxuICAgIG1hdGVyaWFsOiBJR0xURk1hdGVyaWFsLFxyXG4gICAgb25TdWNjZXNzOiAoc2hhZGVyTWF0ZXJpYWw6IFNoYWRlck1hdGVyaWFsKSA9PiB2b2lkXHJcbikgPT4ge1xyXG4gICAgY29uc3QgbWF0ZXJpYWxWYWx1ZXMgPSBtYXRlcmlhbC52YWx1ZXMgfHwgdGVjaG5pcXVlLnBhcmFtZXRlcnM7XHJcblxyXG4gICAgZm9yIChjb25zdCB1bmlmIGluIHVuVHJlYXRlZFVuaWZvcm1zKSB7XHJcbiAgICAgICAgY29uc3QgdW5pZm9ybTogSUdMVEZUZWNobmlxdWVQYXJhbWV0ZXIgPSB1blRyZWF0ZWRVbmlmb3Jtc1t1bmlmXTtcclxuICAgICAgICBjb25zdCB0eXBlID0gdW5pZm9ybS50eXBlO1xyXG5cclxuICAgICAgICBpZiAodHlwZSA9PT0gRVBhcmFtZXRlclR5cGUuRkxPQVRfTUFUMiB8fCB0eXBlID09PSBFUGFyYW1ldGVyVHlwZS5GTE9BVF9NQVQzIHx8IHR5cGUgPT09IEVQYXJhbWV0ZXJUeXBlLkZMT0FUX01BVDQpIHtcclxuICAgICAgICAgICAgaWYgKHVuaWZvcm0uc2VtYW50aWMgJiYgIXVuaWZvcm0uc291cmNlICYmICF1bmlmb3JtLm5vZGUpIHtcclxuICAgICAgICAgICAgICAgIEdMVEZVdGlscy5TZXRNYXRyaXgoZ2x0ZlJ1bnRpbWUuc2NlbmUsIG1lc2gsIHVuaWZvcm0sIHVuaWYsIDxFZmZlY3Q+c2hhZGVyTWF0ZXJpYWwuZ2V0RWZmZWN0KCkpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHVuaWZvcm0uc2VtYW50aWMgJiYgKHVuaWZvcm0uc291cmNlIHx8IHVuaWZvcm0ubm9kZSkpIHtcclxuICAgICAgICAgICAgICAgIGxldCBzb3VyY2UgPSBnbHRmUnVudGltZS5zY2VuZS5nZXROb2RlQnlOYW1lKHVuaWZvcm0uc291cmNlIHx8IHVuaWZvcm0ubm9kZSB8fCBcIlwiKTtcclxuICAgICAgICAgICAgICAgIGlmIChzb3VyY2UgPT09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgICAgICBzb3VyY2UgPSBnbHRmUnVudGltZS5zY2VuZS5nZXROb2RlQnlJZCh1bmlmb3JtLnNvdXJjZSB8fCB1bmlmb3JtLm5vZGUgfHwgXCJcIik7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBpZiAoc291cmNlID09PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgR0xURlV0aWxzLlNldE1hdHJpeChnbHRmUnVudGltZS5zY2VuZSwgc291cmNlLCB1bmlmb3JtLCB1bmlmLCA8RWZmZWN0PnNoYWRlck1hdGVyaWFsLmdldEVmZmVjdCgpKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gKDxhbnk+bWF0ZXJpYWxWYWx1ZXMpW3RlY2huaXF1ZS51bmlmb3Jtc1t1bmlmXV07XHJcbiAgICAgICAgICAgIGlmICghdmFsdWUpIHtcclxuICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAodHlwZSA9PT0gRVBhcmFtZXRlclR5cGUuU0FNUExFUl8yRCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdGV4dHVyZSA9IGdsdGZSdW50aW1lLnRleHR1cmVzW21hdGVyaWFsLnZhbHVlcyA/IHZhbHVlIDogdW5pZm9ybS52YWx1ZV0uYmFieWxvblRleHR1cmU7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKHRleHR1cmUgPT09IG51bGwgfHwgdGV4dHVyZSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgKDxFZmZlY3Q+c2hhZGVyTWF0ZXJpYWwuZ2V0RWZmZWN0KCkpLnNldFRleHR1cmUodW5pZiwgdGV4dHVyZSk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBHTFRGVXRpbHMuU2V0VW5pZm9ybSg8RWZmZWN0PnNoYWRlck1hdGVyaWFsLmdldEVmZmVjdCgpLCB1bmlmLCB2YWx1ZSwgdHlwZSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgb25TdWNjZXNzKHNoYWRlck1hdGVyaWFsKTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBQcmVwYXJlIHVuaWZvcm1zIHRvIHNlbmQgdGhlIG9ubHkgb25lIHRpbWVcclxuICogTG9hZHMgdGhlIGFwcHJvcHJpYXRlIHRleHR1cmVzXHJcbiAqIEBwYXJhbSBnbHRmUnVudGltZVxyXG4gKiBAcGFyYW0gc2hhZGVyTWF0ZXJpYWxcclxuICogQHBhcmFtIHRlY2huaXF1ZVxyXG4gKiBAcGFyYW0gbWF0ZXJpYWxcclxuICovXHJcbmNvbnN0IHByZXBhcmVTaGFkZXJNYXRlcmlhbFVuaWZvcm1zID0gKFxyXG4gICAgZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSxcclxuICAgIHNoYWRlck1hdGVyaWFsOiBTaGFkZXJNYXRlcmlhbCxcclxuICAgIHRlY2huaXF1ZTogSUdMVEZUZWNobmlxdWUsXHJcbiAgICBtYXRlcmlhbDogSUdMVEZNYXRlcmlhbCxcclxuICAgIHVuVHJlYXRlZFVuaWZvcm1zOiB7IFtrZXk6IHN0cmluZ106IElHTFRGVGVjaG5pcXVlUGFyYW1ldGVyIH1cclxuKSA9PiB7XHJcbiAgICBjb25zdCBtYXRlcmlhbFZhbHVlcyA9IG1hdGVyaWFsLnZhbHVlcyB8fCB0ZWNobmlxdWUucGFyYW1ldGVycztcclxuICAgIGNvbnN0IHRlY2huaXF1ZVVuaWZvcm1zID0gdGVjaG5pcXVlLnVuaWZvcm1zO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUHJlcGFyZSB2YWx1ZXMgaGVyZSAobm90IG1hdHJpY2VzKVxyXG4gICAgICovXHJcbiAgICBmb3IgKGNvbnN0IHVuaWYgaW4gdW5UcmVhdGVkVW5pZm9ybXMpIHtcclxuICAgICAgICBjb25zdCB1bmlmb3JtOiBJR0xURlRlY2huaXF1ZVBhcmFtZXRlciA9IHVuVHJlYXRlZFVuaWZvcm1zW3VuaWZdO1xyXG4gICAgICAgIGNvbnN0IHR5cGUgPSB1bmlmb3JtLnR5cGU7XHJcbiAgICAgICAgbGV0IHZhbHVlID0gKDxhbnk+bWF0ZXJpYWxWYWx1ZXMpW3RlY2huaXF1ZVVuaWZvcm1zW3VuaWZdXTtcclxuXHJcbiAgICAgICAgaWYgKHZhbHVlID09PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgLy8gSW4gY2FzZSB0aGUgdmFsdWUgaXMgdGhlIHNhbWUgZm9yIGFsbCBtYXRlcmlhbHNcclxuICAgICAgICAgICAgdmFsdWUgPSA8YW55PnVuaWZvcm0udmFsdWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIXZhbHVlKSB7XHJcbiAgICAgICAgICAgIGNvbnRpbnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3Qgb25Mb2FkVGV4dHVyZSA9ICh1bmlmb3JtTmFtZTogTnVsbGFibGU8c3RyaW5nPikgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gKHRleHR1cmU6IFRleHR1cmUpID0+IHtcclxuICAgICAgICAgICAgICAgIGlmICh1bmlmb3JtLnZhbHVlICYmIHVuaWZvcm1OYW1lKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gU3RhdGljIHVuaWZvcm1cclxuICAgICAgICAgICAgICAgICAgICBzaGFkZXJNYXRlcmlhbC5zZXRUZXh0dXJlKHVuaWZvcm1OYW1lLCB0ZXh0dXJlKTtcclxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdW5UcmVhdGVkVW5pZm9ybXNbdW5pZm9ybU5hbWVdO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8vIFRleHR1cmUgKHNhbXBsZXIyRClcclxuICAgICAgICBpZiAodHlwZSA9PT0gRVBhcmFtZXRlclR5cGUuU0FNUExFUl8yRCkge1xyXG4gICAgICAgICAgICBHTFRGTG9hZGVyRXh0ZW5zaW9uLkxvYWRUZXh0dXJlQXN5bmMoZ2x0ZlJ1bnRpbWUsIG1hdGVyaWFsLnZhbHVlcyA/IHZhbHVlIDogdW5pZm9ybS52YWx1ZSwgb25Mb2FkVGV4dHVyZSh1bmlmKSwgKCkgPT4gb25Mb2FkVGV4dHVyZShudWxsKSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIE90aGVyc1xyXG4gICAgICAgIGVsc2Uge1xyXG4gICAgICAgICAgICBpZiAodW5pZm9ybS52YWx1ZSAmJiBHTFRGVXRpbHMuU2V0VW5pZm9ybShzaGFkZXJNYXRlcmlhbCwgdW5pZiwgbWF0ZXJpYWwudmFsdWVzID8gdmFsdWUgOiB1bmlmb3JtLnZhbHVlLCB0eXBlKSkge1xyXG4gICAgICAgICAgICAgICAgLy8gU3RhdGljIHVuaWZvcm1cclxuICAgICAgICAgICAgICAgIGRlbGV0ZSB1blRyZWF0ZWRVbmlmb3Jtc1t1bmlmXTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxufTtcclxuXHJcbi8qKlxyXG4gKiBTaGFkZXIgY29tcGlsYXRpb24gZmFpbGVkXHJcbiAqIEBwYXJhbSBwcm9ncmFtXHJcbiAqIEBwYXJhbSBzaGFkZXJNYXRlcmlhbFxyXG4gKiBAcGFyYW0gb25FcnJvclxyXG4gKi9cclxuY29uc3Qgb25TaGFkZXJDb21waWxlRXJyb3IgPSAocHJvZ3JhbTogSUdMVEZQcm9ncmFtLCBzaGFkZXJNYXRlcmlhbDogU2hhZGVyTWF0ZXJpYWwsIG9uRXJyb3I6IChtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQpID0+IHtcclxuICAgIHJldHVybiAoZWZmZWN0OiBFZmZlY3QsIGVycm9yOiBzdHJpbmcpID0+IHtcclxuICAgICAgICBzaGFkZXJNYXRlcmlhbC5kaXNwb3NlKHRydWUpO1xyXG4gICAgICAgIG9uRXJyb3IoXCJDYW5ub3QgY29tcGlsZSBwcm9ncmFtIG5hbWVkIFwiICsgcHJvZ3JhbS5uYW1lICsgXCIuIEVycm9yOiBcIiArIGVycm9yICsgXCIuIERlZmF1bHQgbWF0ZXJpYWwgd2lsbCBiZSBhcHBsaWVkXCIpO1xyXG4gICAgfTtcclxufTtcclxuXHJcbi8qKlxyXG4gKiBTaGFkZXIgY29tcGlsYXRpb24gc3VjY2Vzc1xyXG4gKiBAcGFyYW0gZ2x0ZlJ1bnRpbWVcclxuICogQHBhcmFtIHNoYWRlck1hdGVyaWFsXHJcbiAqIEBwYXJhbSB0ZWNobmlxdWVcclxuICogQHBhcmFtIG1hdGVyaWFsXHJcbiAqIEBwYXJhbSB1blRyZWF0ZWRVbmlmb3Jtc1xyXG4gKiBAcGFyYW0gb25TdWNjZXNzXHJcbiAqL1xyXG5jb25zdCBvblNoYWRlckNvbXBpbGVTdWNjZXNzID0gKFxyXG4gICAgZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSxcclxuICAgIHNoYWRlck1hdGVyaWFsOiBTaGFkZXJNYXRlcmlhbCxcclxuICAgIHRlY2huaXF1ZTogSUdMVEZUZWNobmlxdWUsXHJcbiAgICBtYXRlcmlhbDogSUdMVEZNYXRlcmlhbCxcclxuICAgIHVuVHJlYXRlZFVuaWZvcm1zOiB7IFtrZXk6IHN0cmluZ106IElHTFRGVGVjaG5pcXVlUGFyYW1ldGVyIH0sXHJcbiAgICBvblN1Y2Nlc3M6IChzaGFkZXJNYXRlcmlhbDogU2hhZGVyTWF0ZXJpYWwpID0+IHZvaWRcclxuKSA9PiB7XHJcbiAgICByZXR1cm4gKF86IEVmZmVjdCkgPT4ge1xyXG4gICAgICAgIHByZXBhcmVTaGFkZXJNYXRlcmlhbFVuaWZvcm1zKGdsdGZSdW50aW1lLCBzaGFkZXJNYXRlcmlhbCwgdGVjaG5pcXVlLCBtYXRlcmlhbCwgdW5UcmVhdGVkVW5pZm9ybXMpO1xyXG5cclxuICAgICAgICBzaGFkZXJNYXRlcmlhbC5vbkJpbmQgPSAobWVzaDogQWJzdHJhY3RNZXNoKSA9PiB7XHJcbiAgICAgICAgICAgIG9uQmluZFNoYWRlck1hdGVyaWFsKG1lc2gsIGdsdGZSdW50aW1lLCB1blRyZWF0ZWRVbmlmb3Jtcywgc2hhZGVyTWF0ZXJpYWwsIHRlY2huaXF1ZSwgbWF0ZXJpYWwsIG9uU3VjY2Vzcyk7XHJcbiAgICAgICAgfTtcclxuICAgIH07XHJcbn07XHJcblxyXG4vKipcclxuICogUmV0dXJucyB0aGUgYXBwcm9wcmlhdGUgdW5pZm9ybSBpZiBhbHJlYWR5IGhhbmRsZWQgYnkgYmFieWxvblxyXG4gKiBAcGFyYW0gdG9rZW5pemVyXHJcbiAqIEBwYXJhbSB0ZWNobmlxdWVcclxuICovXHJcbmNvbnN0IHBhcnNlU2hhZGVyVW5pZm9ybXMgPSAodG9rZW5pemVyOiBUb2tlbml6ZXIsIHRlY2huaXF1ZTogSUdMVEZUZWNobmlxdWUsIHVuVHJlYXRlZFVuaWZvcm1zOiB7IFtrZXk6IHN0cmluZ106IElHTFRGVGVjaG5pcXVlUGFyYW1ldGVyIH0pOiBzdHJpbmcgPT4ge1xyXG4gICAgZm9yIChjb25zdCB1bmlmIGluIHRlY2huaXF1ZS51bmlmb3Jtcykge1xyXG4gICAgICAgIGNvbnN0IHVuaWZvcm0gPSB0ZWNobmlxdWUudW5pZm9ybXNbdW5pZl07XHJcbiAgICAgICAgY29uc3QgdW5pZm9ybVBhcmFtZXRlcjogSUdMVEZUZWNobmlxdWVQYXJhbWV0ZXIgPSB0ZWNobmlxdWUucGFyYW1ldGVyc1t1bmlmb3JtXTtcclxuXHJcbiAgICAgICAgaWYgKHRva2VuaXplci5jdXJyZW50SWRlbnRpZmllciA9PT0gdW5pZikge1xyXG4gICAgICAgICAgICBpZiAodW5pZm9ybVBhcmFtZXRlci5zZW1hbnRpYyAmJiAhdW5pZm9ybVBhcmFtZXRlci5zb3VyY2UgJiYgIXVuaWZvcm1QYXJhbWV0ZXIubm9kZSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdHJhbnNmb3JtSW5kZXggPSBnbFRGVHJhbnNmb3Jtcy5pbmRleE9mKHVuaWZvcm1QYXJhbWV0ZXIuc2VtYW50aWMpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0cmFuc2Zvcm1JbmRleCAhPT0gLTEpIHtcclxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgdW5UcmVhdGVkVW5pZm9ybXNbdW5pZl07XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGJhYnlsb25UcmFuc2Zvcm1zW3RyYW5zZm9ybUluZGV4XTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICByZXR1cm4gdG9rZW5pemVyLmN1cnJlbnRJZGVudGlmaWVyO1xyXG59O1xyXG5cclxuLyoqXHJcbiAqIEFsbCBzaGFkZXJzIGxvYWRlZC4gQ3JlYXRlIG1hdGVyaWFscyBvbmUgYnkgb25lXHJcbiAqIEBwYXJhbSBnbHRmUnVudGltZVxyXG4gKi9cclxuY29uc3QgaW1wb3J0TWF0ZXJpYWxzID0gKGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUpID0+IHtcclxuICAgIC8vIENyZWF0ZSBtYXRlcmlhbHNcclxuICAgIGZvciAoY29uc3QgbWF0IGluIGdsdGZSdW50aW1lLm1hdGVyaWFscykge1xyXG4gICAgICAgIEdMVEZMb2FkZXJFeHRlbnNpb24uTG9hZE1hdGVyaWFsQXN5bmMoXHJcbiAgICAgICAgICAgIGdsdGZSdW50aW1lLFxyXG4gICAgICAgICAgICBtYXQsXHJcbiAgICAgICAgICAgICgpID0+IHt9LFxyXG4gICAgICAgICAgICAoKSA9PiB7fVxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcbn07XHJcblxyXG4vKipcclxuICogSW1wbGVtZW50YXRpb24gb2YgdGhlIGJhc2UgZ2xURiBzcGVjXHJcbiAqIEBpbnRlcm5hbFxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEdMVEZMb2FkZXJCYXNlIHtcclxuICAgIHB1YmxpYyBzdGF0aWMgQ3JlYXRlUnVudGltZShwYXJzZWREYXRhOiBhbnksIHNjZW5lOiBTY2VuZSwgcm9vdFVybDogc3RyaW5nKTogSUdMVEZSdW50aW1lIHtcclxuICAgICAgICBjb25zdCBnbHRmUnVudGltZTogSUdMVEZSdW50aW1lID0ge1xyXG4gICAgICAgICAgICBleHRlbnNpb25zOiB7fSxcclxuICAgICAgICAgICAgYWNjZXNzb3JzOiB7fSxcclxuICAgICAgICAgICAgYnVmZmVyczoge30sXHJcbiAgICAgICAgICAgIGJ1ZmZlclZpZXdzOiB7fSxcclxuICAgICAgICAgICAgbWVzaGVzOiB7fSxcclxuICAgICAgICAgICAgbGlnaHRzOiB7fSxcclxuICAgICAgICAgICAgY2FtZXJhczoge30sXHJcbiAgICAgICAgICAgIG5vZGVzOiB7fSxcclxuICAgICAgICAgICAgaW1hZ2VzOiB7fSxcclxuICAgICAgICAgICAgdGV4dHVyZXM6IHt9LFxyXG4gICAgICAgICAgICBzaGFkZXJzOiB7fSxcclxuICAgICAgICAgICAgcHJvZ3JhbXM6IHt9LFxyXG4gICAgICAgICAgICBzYW1wbGVyczoge30sXHJcbiAgICAgICAgICAgIHRlY2huaXF1ZXM6IHt9LFxyXG4gICAgICAgICAgICBtYXRlcmlhbHM6IHt9LFxyXG4gICAgICAgICAgICBhbmltYXRpb25zOiB7fSxcclxuICAgICAgICAgICAgc2tpbnM6IHt9LFxyXG4gICAgICAgICAgICBleHRlbnNpb25zVXNlZDogW10sXHJcblxyXG4gICAgICAgICAgICBzY2VuZXM6IHt9LFxyXG5cclxuICAgICAgICAgICAgYnVmZmVyc0NvdW50OiAwLFxyXG4gICAgICAgICAgICBzaGFkZXJzY291bnQ6IDAsXHJcblxyXG4gICAgICAgICAgICBzY2VuZTogc2NlbmUsXHJcbiAgICAgICAgICAgIHJvb3RVcmw6IHJvb3RVcmwsXHJcblxyXG4gICAgICAgICAgICBsb2FkZWRCdWZmZXJDb3VudDogMCxcclxuICAgICAgICAgICAgbG9hZGVkQnVmZmVyVmlld3M6IHt9LFxyXG5cclxuICAgICAgICAgICAgbG9hZGVkU2hhZGVyQ291bnQ6IDAsXHJcblxyXG4gICAgICAgICAgICBpbXBvcnRPbmx5TWVzaGVzOiBmYWxzZSxcclxuXHJcbiAgICAgICAgICAgIGR1bW15Tm9kZXM6IFtdLFxyXG5cclxuICAgICAgICAgICAgYXNzZXRDb250YWluZXI6IG51bGwsXHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgLy8gUGFyc2VcclxuICAgICAgICBpZiAocGFyc2VkRGF0YS5leHRlbnNpb25zKSB7XHJcbiAgICAgICAgICAgIHBhcnNlT2JqZWN0KHBhcnNlZERhdGEuZXh0ZW5zaW9ucywgXCJleHRlbnNpb25zXCIsIGdsdGZSdW50aW1lKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwYXJzZWREYXRhLmV4dGVuc2lvbnNVc2VkKSB7XHJcbiAgICAgICAgICAgIHBhcnNlT2JqZWN0KHBhcnNlZERhdGEuZXh0ZW5zaW9uc1VzZWQsIFwiZXh0ZW5zaW9uc1VzZWRcIiwgZ2x0ZlJ1bnRpbWUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHBhcnNlZERhdGEuYnVmZmVycykge1xyXG4gICAgICAgICAgICBwYXJzZUJ1ZmZlcnMocGFyc2VkRGF0YS5idWZmZXJzLCBnbHRmUnVudGltZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocGFyc2VkRGF0YS5idWZmZXJWaWV3cykge1xyXG4gICAgICAgICAgICBwYXJzZU9iamVjdChwYXJzZWREYXRhLmJ1ZmZlclZpZXdzLCBcImJ1ZmZlclZpZXdzXCIsIGdsdGZSdW50aW1lKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwYXJzZWREYXRhLmFjY2Vzc29ycykge1xyXG4gICAgICAgICAgICBwYXJzZU9iamVjdChwYXJzZWREYXRhLmFjY2Vzc29ycywgXCJhY2Nlc3NvcnNcIiwgZ2x0ZlJ1bnRpbWUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHBhcnNlZERhdGEubWVzaGVzKSB7XHJcbiAgICAgICAgICAgIHBhcnNlT2JqZWN0KHBhcnNlZERhdGEubWVzaGVzLCBcIm1lc2hlc1wiLCBnbHRmUnVudGltZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocGFyc2VkRGF0YS5saWdodHMpIHtcclxuICAgICAgICAgICAgcGFyc2VPYmplY3QocGFyc2VkRGF0YS5saWdodHMsIFwibGlnaHRzXCIsIGdsdGZSdW50aW1lKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwYXJzZWREYXRhLmNhbWVyYXMpIHtcclxuICAgICAgICAgICAgcGFyc2VPYmplY3QocGFyc2VkRGF0YS5jYW1lcmFzLCBcImNhbWVyYXNcIiwgZ2x0ZlJ1bnRpbWUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHBhcnNlZERhdGEubm9kZXMpIHtcclxuICAgICAgICAgICAgcGFyc2VPYmplY3QocGFyc2VkRGF0YS5ub2RlcywgXCJub2Rlc1wiLCBnbHRmUnVudGltZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocGFyc2VkRGF0YS5pbWFnZXMpIHtcclxuICAgICAgICAgICAgcGFyc2VPYmplY3QocGFyc2VkRGF0YS5pbWFnZXMsIFwiaW1hZ2VzXCIsIGdsdGZSdW50aW1lKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwYXJzZWREYXRhLnRleHR1cmVzKSB7XHJcbiAgICAgICAgICAgIHBhcnNlT2JqZWN0KHBhcnNlZERhdGEudGV4dHVyZXMsIFwidGV4dHVyZXNcIiwgZ2x0ZlJ1bnRpbWUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHBhcnNlZERhdGEuc2hhZGVycykge1xyXG4gICAgICAgICAgICBwYXJzZVNoYWRlcnMocGFyc2VkRGF0YS5zaGFkZXJzLCBnbHRmUnVudGltZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocGFyc2VkRGF0YS5wcm9ncmFtcykge1xyXG4gICAgICAgICAgICBwYXJzZU9iamVjdChwYXJzZWREYXRhLnByb2dyYW1zLCBcInByb2dyYW1zXCIsIGdsdGZSdW50aW1lKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwYXJzZWREYXRhLnNhbXBsZXJzKSB7XHJcbiAgICAgICAgICAgIHBhcnNlT2JqZWN0KHBhcnNlZERhdGEuc2FtcGxlcnMsIFwic2FtcGxlcnNcIiwgZ2x0ZlJ1bnRpbWUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHBhcnNlZERhdGEudGVjaG5pcXVlcykge1xyXG4gICAgICAgICAgICBwYXJzZU9iamVjdChwYXJzZWREYXRhLnRlY2huaXF1ZXMsIFwidGVjaG5pcXVlc1wiLCBnbHRmUnVudGltZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocGFyc2VkRGF0YS5tYXRlcmlhbHMpIHtcclxuICAgICAgICAgICAgcGFyc2VPYmplY3QocGFyc2VkRGF0YS5tYXRlcmlhbHMsIFwibWF0ZXJpYWxzXCIsIGdsdGZSdW50aW1lKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwYXJzZWREYXRhLmFuaW1hdGlvbnMpIHtcclxuICAgICAgICAgICAgcGFyc2VPYmplY3QocGFyc2VkRGF0YS5hbmltYXRpb25zLCBcImFuaW1hdGlvbnNcIiwgZ2x0ZlJ1bnRpbWUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHBhcnNlZERhdGEuc2tpbnMpIHtcclxuICAgICAgICAgICAgcGFyc2VPYmplY3QocGFyc2VkRGF0YS5za2lucywgXCJza2luc1wiLCBnbHRmUnVudGltZSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocGFyc2VkRGF0YS5zY2VuZXMpIHtcclxuICAgICAgICAgICAgZ2x0ZlJ1bnRpbWUuc2NlbmVzID0gcGFyc2VkRGF0YS5zY2VuZXM7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocGFyc2VkRGF0YS5zY2VuZSAmJiBwYXJzZWREYXRhLnNjZW5lcykge1xyXG4gICAgICAgICAgICBnbHRmUnVudGltZS5jdXJyZW50U2NlbmUgPSBwYXJzZWREYXRhLnNjZW5lc1twYXJzZWREYXRhLnNjZW5lXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBnbHRmUnVudGltZTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgc3RhdGljIExvYWRCdWZmZXJBc3luYyhcclxuICAgICAgICBnbHRmUnVudGltZTogSUdMVEZSdW50aW1lLFxyXG4gICAgICAgIGlkOiBzdHJpbmcsXHJcbiAgICAgICAgb25TdWNjZXNzOiAoYnVmZmVyOiBBcnJheUJ1ZmZlclZpZXcpID0+IHZvaWQsXHJcbiAgICAgICAgb25FcnJvcjogKG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZCxcclxuICAgICAgICBvblByb2dyZXNzPzogKCkgPT4gdm9pZFxyXG4gICAgKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3QgYnVmZmVyOiBJR0xURkJ1ZmZlciA9IGdsdGZSdW50aW1lLmJ1ZmZlcnNbaWRdO1xyXG5cclxuICAgICAgICBpZiAoVG9vbHMuSXNCYXNlNjQoYnVmZmVyLnVyaSkpIHtcclxuICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiBvblN1Y2Nlc3MobmV3IFVpbnQ4QXJyYXkoVG9vbHMuRGVjb2RlQmFzZTY0KGJ1ZmZlci51cmkpKSkpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIFRvb2xzLkxvYWRGaWxlKFxyXG4gICAgICAgICAgICAgICAgZ2x0ZlJ1bnRpbWUucm9vdFVybCArIGJ1ZmZlci51cmksXHJcbiAgICAgICAgICAgICAgICAoZGF0YSkgPT4gb25TdWNjZXNzKG5ldyBVaW50OEFycmF5KGRhdGEgYXMgQXJyYXlCdWZmZXIpKSxcclxuICAgICAgICAgICAgICAgIG9uUHJvZ3Jlc3MsXHJcbiAgICAgICAgICAgICAgICB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgICAgICB0cnVlLFxyXG4gICAgICAgICAgICAgICAgKHJlcXVlc3QpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAocmVxdWVzdCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkVycm9yKHJlcXVlc3Quc3RhdHVzICsgXCIgXCIgKyByZXF1ZXN0LnN0YXR1c1RleHQpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyBMb2FkVGV4dHVyZUJ1ZmZlckFzeW5jKGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUsIGlkOiBzdHJpbmcsIG9uU3VjY2VzczogKGJ1ZmZlcjogTnVsbGFibGU8QXJyYXlCdWZmZXJWaWV3PikgPT4gdm9pZCwgb25FcnJvcjogKG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZCk6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IHRleHR1cmU6IElHTFRGVGV4dHVyZSA9IGdsdGZSdW50aW1lLnRleHR1cmVzW2lkXTtcclxuXHJcbiAgICAgICAgaWYgKCF0ZXh0dXJlIHx8ICF0ZXh0dXJlLnNvdXJjZSkge1xyXG4gICAgICAgICAgICBvbkVycm9yKFwiXCIpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAodGV4dHVyZS5iYWJ5bG9uVGV4dHVyZSkge1xyXG4gICAgICAgICAgICBvblN1Y2Nlc3MobnVsbCk7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHNvdXJjZTogSUdMVEZJbWFnZSA9IGdsdGZSdW50aW1lLmltYWdlc1t0ZXh0dXJlLnNvdXJjZV07XHJcblxyXG4gICAgICAgIGlmIChUb29scy5Jc0Jhc2U2NChzb3VyY2UudXJpKSkge1xyXG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IG9uU3VjY2VzcyhuZXcgVWludDhBcnJheShUb29scy5EZWNvZGVCYXNlNjQoc291cmNlLnVyaSkpKSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgVG9vbHMuTG9hZEZpbGUoXHJcbiAgICAgICAgICAgICAgICBnbHRmUnVudGltZS5yb290VXJsICsgc291cmNlLnVyaSxcclxuICAgICAgICAgICAgICAgIChkYXRhKSA9PiBvblN1Y2Nlc3MobmV3IFVpbnQ4QXJyYXkoZGF0YSBhcyBBcnJheUJ1ZmZlcikpLFxyXG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICAgICAgdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICAgICAgdHJ1ZSxcclxuICAgICAgICAgICAgICAgIChyZXF1ZXN0KSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHJlcXVlc3QpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgb25FcnJvcihyZXF1ZXN0LnN0YXR1cyArIFwiIFwiICsgcmVxdWVzdC5zdGF0dXNUZXh0KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBzdGF0aWMgQ3JlYXRlVGV4dHVyZUFzeW5jKGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUsIGlkOiBzdHJpbmcsIGJ1ZmZlcjogTnVsbGFibGU8QXJyYXlCdWZmZXJWaWV3Piwgb25TdWNjZXNzOiAodGV4dHVyZTogVGV4dHVyZSkgPT4gdm9pZCk6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IHRleHR1cmU6IElHTFRGVGV4dHVyZSA9IGdsdGZSdW50aW1lLnRleHR1cmVzW2lkXTtcclxuXHJcbiAgICAgICAgaWYgKHRleHR1cmUuYmFieWxvblRleHR1cmUpIHtcclxuICAgICAgICAgICAgb25TdWNjZXNzKHRleHR1cmUuYmFieWxvblRleHR1cmUpO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBzYW1wbGVyOiBJR0xURlNhbXBsZXIgPSBnbHRmUnVudGltZS5zYW1wbGVyc1t0ZXh0dXJlLnNhbXBsZXJdO1xyXG5cclxuICAgICAgICBjb25zdCBjcmVhdGVNaXBNYXBzID1cclxuICAgICAgICAgICAgc2FtcGxlci5taW5GaWx0ZXIgPT09IEVUZXh0dXJlRmlsdGVyVHlwZS5ORUFSRVNUX01JUE1BUF9ORUFSRVNUIHx8XHJcbiAgICAgICAgICAgIHNhbXBsZXIubWluRmlsdGVyID09PSBFVGV4dHVyZUZpbHRlclR5cGUuTkVBUkVTVF9NSVBNQVBfTElORUFSIHx8XHJcbiAgICAgICAgICAgIHNhbXBsZXIubWluRmlsdGVyID09PSBFVGV4dHVyZUZpbHRlclR5cGUuTElORUFSX01JUE1BUF9ORUFSRVNUIHx8XHJcbiAgICAgICAgICAgIHNhbXBsZXIubWluRmlsdGVyID09PSBFVGV4dHVyZUZpbHRlclR5cGUuTElORUFSX01JUE1BUF9MSU5FQVI7XHJcblxyXG4gICAgICAgIGNvbnN0IHNhbXBsaW5nTW9kZSA9IFRleHR1cmUuQklMSU5FQVJfU0FNUExJTkdNT0RFO1xyXG5cclxuICAgICAgICBjb25zdCBibG9iID0gYnVmZmVyID09IG51bGwgPyBuZXcgQmxvYigpIDogbmV3IEJsb2IoW2J1ZmZlcl0pO1xyXG4gICAgICAgIGNvbnN0IGJsb2JVUkwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKGJsb2IpO1xyXG4gICAgICAgIGNvbnN0IHJldm9rZUJsb2JVUkwgPSAoKSA9PiBVUkwucmV2b2tlT2JqZWN0VVJMKGJsb2JVUkwpO1xyXG4gICAgICAgIGNvbnN0IG5ld1RleHR1cmUgPSBuZXcgVGV4dHVyZShibG9iVVJMLCBnbHRmUnVudGltZS5zY2VuZSwgIWNyZWF0ZU1pcE1hcHMsIHRydWUsIHNhbXBsaW5nTW9kZSwgcmV2b2tlQmxvYlVSTCwgcmV2b2tlQmxvYlVSTCk7XHJcbiAgICAgICAgaWYgKHNhbXBsZXIud3JhcFMgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICBuZXdUZXh0dXJlLndyYXBVID0gR0xURlV0aWxzLkdldFdyYXBNb2RlKHNhbXBsZXIud3JhcFMpO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAoc2FtcGxlci53cmFwVCAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIG5ld1RleHR1cmUud3JhcFYgPSBHTFRGVXRpbHMuR2V0V3JhcE1vZGUoc2FtcGxlci53cmFwVCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIG5ld1RleHR1cmUubmFtZSA9IGlkO1xyXG5cclxuICAgICAgICB0ZXh0dXJlLmJhYnlsb25UZXh0dXJlID0gbmV3VGV4dHVyZTtcclxuICAgICAgICBvblN1Y2Nlc3MobmV3VGV4dHVyZSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyBMb2FkU2hhZGVyU3RyaW5nQXN5bmMoZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSwgaWQ6IHN0cmluZywgb25TdWNjZXNzOiAoc2hhZGVyU3RyaW5nOiBzdHJpbmcgfCBBcnJheUJ1ZmZlcikgPT4gdm9pZCwgb25FcnJvcj86IChtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBzaGFkZXI6IElHTFRGU2hhZGVyID0gZ2x0ZlJ1bnRpbWUuc2hhZGVyc1tpZF07XHJcblxyXG4gICAgICAgIGlmIChUb29scy5Jc0Jhc2U2NChzaGFkZXIudXJpKSkge1xyXG4gICAgICAgICAgICBjb25zdCBzaGFkZXJTdHJpbmcgPSBhdG9iKHNoYWRlci51cmkuc3BsaXQoXCIsXCIpWzFdKTtcclxuICAgICAgICAgICAgaWYgKG9uU3VjY2Vzcykge1xyXG4gICAgICAgICAgICAgICAgb25TdWNjZXNzKHNoYWRlclN0cmluZyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBUb29scy5Mb2FkRmlsZShnbHRmUnVudGltZS5yb290VXJsICsgc2hhZGVyLnVyaSwgb25TdWNjZXNzLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgZmFsc2UsIChyZXF1ZXN0KSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAocmVxdWVzdCAmJiBvbkVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgb25FcnJvcihyZXF1ZXN0LnN0YXR1cyArIFwiIFwiICsgcmVxdWVzdC5zdGF0dXNUZXh0KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBzdGF0aWMgTG9hZE1hdGVyaWFsQXN5bmMoZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSwgaWQ6IHN0cmluZywgb25TdWNjZXNzOiAobWF0ZXJpYWw6IE1hdGVyaWFsKSA9PiB2b2lkLCBvbkVycm9yOiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3QgbWF0ZXJpYWw6IElHTFRGTWF0ZXJpYWwgPSBnbHRmUnVudGltZS5tYXRlcmlhbHNbaWRdO1xyXG4gICAgICAgIGlmICghbWF0ZXJpYWwudGVjaG5pcXVlKSB7XHJcbiAgICAgICAgICAgIGlmIChvbkVycm9yKSB7XHJcbiAgICAgICAgICAgICAgICBvbkVycm9yKFwiTm8gdGVjaG5pcXVlIGZvdW5kLlwiKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCB0ZWNobmlxdWU6IElHTFRGVGVjaG5pcXVlID0gZ2x0ZlJ1bnRpbWUudGVjaG5pcXVlc1ttYXRlcmlhbC50ZWNobmlxdWVdO1xyXG4gICAgICAgIGlmICghdGVjaG5pcXVlKSB7XHJcbiAgICAgICAgICAgIGdsdGZSdW50aW1lLnNjZW5lLl9ibG9ja0VudGl0eUNvbGxlY3Rpb24gPSAhIWdsdGZSdW50aW1lLmFzc2V0Q29udGFpbmVyO1xyXG4gICAgICAgICAgICBjb25zdCBkZWZhdWx0TWF0ZXJpYWwgPSBuZXcgU3RhbmRhcmRNYXRlcmlhbChpZCwgZ2x0ZlJ1bnRpbWUuc2NlbmUpO1xyXG4gICAgICAgICAgICBkZWZhdWx0TWF0ZXJpYWwuX3BhcmVudENvbnRhaW5lciA9IGdsdGZSdW50aW1lLmFzc2V0Q29udGFpbmVyO1xyXG4gICAgICAgICAgICBnbHRmUnVudGltZS5zY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gZmFsc2U7XHJcbiAgICAgICAgICAgIGRlZmF1bHRNYXRlcmlhbC5kaWZmdXNlQ29sb3IgPSBuZXcgQ29sb3IzKDAuNSwgMC41LCAwLjUpO1xyXG4gICAgICAgICAgICBkZWZhdWx0TWF0ZXJpYWwuc2lkZU9yaWVudGF0aW9uID0gTWF0ZXJpYWwuQ291bnRlckNsb2NrV2lzZVNpZGVPcmllbnRhdGlvbjtcclxuICAgICAgICAgICAgb25TdWNjZXNzKGRlZmF1bHRNYXRlcmlhbCk7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHByb2dyYW06IElHTFRGUHJvZ3JhbSA9IGdsdGZSdW50aW1lLnByb2dyYW1zW3RlY2huaXF1ZS5wcm9ncmFtXTtcclxuICAgICAgICBjb25zdCBzdGF0ZXM6IElHTFRGVGVjaG5pcXVlU3RhdGVzID0gdGVjaG5pcXVlLnN0YXRlcztcclxuXHJcbiAgICAgICAgY29uc3QgdmVydGV4U2hhZGVyOiBzdHJpbmcgPSBFZmZlY3QuU2hhZGVyc1N0b3JlW3Byb2dyYW0udmVydGV4U2hhZGVyICsgXCJWZXJ0ZXhTaGFkZXJcIl07XHJcbiAgICAgICAgY29uc3QgcGl4ZWxTaGFkZXI6IHN0cmluZyA9IEVmZmVjdC5TaGFkZXJzU3RvcmVbcHJvZ3JhbS5mcmFnbWVudFNoYWRlciArIFwiUGl4ZWxTaGFkZXJcIl07XHJcbiAgICAgICAgbGV0IG5ld1ZlcnRleFNoYWRlciA9IFwiXCI7XHJcbiAgICAgICAgbGV0IG5ld1BpeGVsU2hhZGVyID0gXCJcIjtcclxuXHJcbiAgICAgICAgY29uc3QgdmVydGV4VG9rZW5pemVyID0gbmV3IFRva2VuaXplcih2ZXJ0ZXhTaGFkZXIpO1xyXG4gICAgICAgIGNvbnN0IHBpeGVsVG9rZW5pemVyID0gbmV3IFRva2VuaXplcihwaXhlbFNoYWRlcik7XHJcblxyXG4gICAgICAgIGNvbnN0IHVuVHJlYXRlZFVuaWZvcm1zOiB7IFtrZXk6IHN0cmluZ106IElHTFRGVGVjaG5pcXVlUGFyYW1ldGVyIH0gPSB7fTtcclxuICAgICAgICBjb25zdCB1bmlmb3Jtczogc3RyaW5nW10gPSBbXTtcclxuICAgICAgICBjb25zdCBhdHRyaWJ1dGVzOiBzdHJpbmdbXSA9IFtdO1xyXG4gICAgICAgIGNvbnN0IHNhbXBsZXJzOiBzdHJpbmdbXSA9IFtdO1xyXG5cclxuICAgICAgICAvLyBGaWxsIHVuaWZvcm0sIHNhbXBsZXIyRCBhbmQgYXR0cmlidXRlc1xyXG4gICAgICAgIGZvciAoY29uc3QgdW5pZiBpbiB0ZWNobmlxdWUudW5pZm9ybXMpIHtcclxuICAgICAgICAgICAgY29uc3QgdW5pZm9ybSA9IHRlY2huaXF1ZS51bmlmb3Jtc1t1bmlmXTtcclxuICAgICAgICAgICAgY29uc3QgdW5pZm9ybVBhcmFtZXRlcjogSUdMVEZUZWNobmlxdWVQYXJhbWV0ZXIgPSB0ZWNobmlxdWUucGFyYW1ldGVyc1t1bmlmb3JtXTtcclxuXHJcbiAgICAgICAgICAgIHVuVHJlYXRlZFVuaWZvcm1zW3VuaWZdID0gdW5pZm9ybVBhcmFtZXRlcjtcclxuXHJcbiAgICAgICAgICAgIGlmICh1bmlmb3JtUGFyYW1ldGVyLnNlbWFudGljICYmICF1bmlmb3JtUGFyYW1ldGVyLm5vZGUgJiYgIXVuaWZvcm1QYXJhbWV0ZXIuc291cmNlKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB0cmFuc2Zvcm1JbmRleCA9IGdsVEZUcmFuc2Zvcm1zLmluZGV4T2YodW5pZm9ybVBhcmFtZXRlci5zZW1hbnRpYyk7XHJcbiAgICAgICAgICAgICAgICBpZiAodHJhbnNmb3JtSW5kZXggIT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdW5pZm9ybXMucHVzaChiYWJ5bG9uVHJhbnNmb3Jtc1t0cmFuc2Zvcm1JbmRleF0pO1xyXG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSB1blRyZWF0ZWRVbmlmb3Jtc1t1bmlmXTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdW5pZm9ybXMucHVzaCh1bmlmKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSBlbHNlIGlmICh1bmlmb3JtUGFyYW1ldGVyLnR5cGUgPT09IEVQYXJhbWV0ZXJUeXBlLlNBTVBMRVJfMkQpIHtcclxuICAgICAgICAgICAgICAgIHNhbXBsZXJzLnB1c2godW5pZik7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB1bmlmb3Jtcy5wdXNoKHVuaWYpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmb3IgKGNvbnN0IGF0dHIgaW4gdGVjaG5pcXVlLmF0dHJpYnV0ZXMpIHtcclxuICAgICAgICAgICAgY29uc3QgYXR0cmlidXRlID0gdGVjaG5pcXVlLmF0dHJpYnV0ZXNbYXR0cl07XHJcbiAgICAgICAgICAgIGNvbnN0IGF0dHJpYnV0ZVBhcmFtZXRlcjogSUdMVEZUZWNobmlxdWVQYXJhbWV0ZXIgPSB0ZWNobmlxdWUucGFyYW1ldGVyc1thdHRyaWJ1dGVdO1xyXG5cclxuICAgICAgICAgICAgaWYgKGF0dHJpYnV0ZVBhcmFtZXRlci5zZW1hbnRpYykge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbmFtZSA9IGdldEF0dHJpYnV0ZShhdHRyaWJ1dGVQYXJhbWV0ZXIpO1xyXG4gICAgICAgICAgICAgICAgaWYgKG5hbWUpIHtcclxuICAgICAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzLnB1c2gobmFtZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIENvbmZpZ3VyZSB2ZXJ0ZXggc2hhZGVyXHJcbiAgICAgICAgd2hpbGUgKCF2ZXJ0ZXhUb2tlbml6ZXIuaXNFbmQoKSAmJiB2ZXJ0ZXhUb2tlbml6ZXIuZ2V0TmV4dFRva2VuKCkpIHtcclxuICAgICAgICAgICAgY29uc3QgdG9rZW5UeXBlID0gdmVydGV4VG9rZW5pemVyLmN1cnJlbnRUb2tlbjtcclxuXHJcbiAgICAgICAgICAgIGlmICh0b2tlblR5cGUgIT09IEVUb2tlblR5cGUuSURFTlRJRklFUikge1xyXG4gICAgICAgICAgICAgICAgbmV3VmVydGV4U2hhZGVyICs9IHZlcnRleFRva2VuaXplci5jdXJyZW50U3RyaW5nO1xyXG4gICAgICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGxldCBmb3VuZEF0dHJpYnV0ZSA9IGZhbHNlO1xyXG5cclxuICAgICAgICAgICAgZm9yIChjb25zdCBhdHRyIGluIHRlY2huaXF1ZS5hdHRyaWJ1dGVzKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBhdHRyaWJ1dGUgPSB0ZWNobmlxdWUuYXR0cmlidXRlc1thdHRyXTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGF0dHJpYnV0ZVBhcmFtZXRlcjogSUdMVEZUZWNobmlxdWVQYXJhbWV0ZXIgPSB0ZWNobmlxdWUucGFyYW1ldGVyc1thdHRyaWJ1dGVdO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICh2ZXJ0ZXhUb2tlbml6ZXIuY3VycmVudElkZW50aWZpZXIgPT09IGF0dHIgJiYgYXR0cmlidXRlUGFyYW1ldGVyLnNlbWFudGljKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbmV3VmVydGV4U2hhZGVyICs9IGdldEF0dHJpYnV0ZShhdHRyaWJ1dGVQYXJhbWV0ZXIpO1xyXG4gICAgICAgICAgICAgICAgICAgIGZvdW5kQXR0cmlidXRlID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKGZvdW5kQXR0cmlidXRlKSB7XHJcbiAgICAgICAgICAgICAgICBjb250aW51ZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgbmV3VmVydGV4U2hhZGVyICs9IHBhcnNlU2hhZGVyVW5pZm9ybXModmVydGV4VG9rZW5pemVyLCB0ZWNobmlxdWUsIHVuVHJlYXRlZFVuaWZvcm1zKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIENvbmZpZ3VyZSBwaXhlbCBzaGFkZXJcclxuICAgICAgICB3aGlsZSAoIXBpeGVsVG9rZW5pemVyLmlzRW5kKCkgJiYgcGl4ZWxUb2tlbml6ZXIuZ2V0TmV4dFRva2VuKCkpIHtcclxuICAgICAgICAgICAgY29uc3QgdG9rZW5UeXBlID0gcGl4ZWxUb2tlbml6ZXIuY3VycmVudFRva2VuO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRva2VuVHlwZSAhPT0gRVRva2VuVHlwZS5JREVOVElGSUVSKSB7XHJcbiAgICAgICAgICAgICAgICBuZXdQaXhlbFNoYWRlciArPSBwaXhlbFRva2VuaXplci5jdXJyZW50U3RyaW5nO1xyXG4gICAgICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIG5ld1BpeGVsU2hhZGVyICs9IHBhcnNlU2hhZGVyVW5pZm9ybXMocGl4ZWxUb2tlbml6ZXIsIHRlY2huaXF1ZSwgdW5UcmVhdGVkVW5pZm9ybXMpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gQ3JlYXRlIHNoYWRlciBtYXRlcmlhbFxyXG4gICAgICAgIGNvbnN0IHNoYWRlclBhdGggPSB7XHJcbiAgICAgICAgICAgIHZlcnRleDogcHJvZ3JhbS52ZXJ0ZXhTaGFkZXIgKyBpZCxcclxuICAgICAgICAgICAgZnJhZ21lbnQ6IHByb2dyYW0uZnJhZ21lbnRTaGFkZXIgKyBpZCxcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBjb25zdCBvcHRpb25zID0ge1xyXG4gICAgICAgICAgICBhdHRyaWJ1dGVzOiBhdHRyaWJ1dGVzLFxyXG4gICAgICAgICAgICB1bmlmb3JtczogdW5pZm9ybXMsXHJcbiAgICAgICAgICAgIHNhbXBsZXJzOiBzYW1wbGVycyxcclxuICAgICAgICAgICAgbmVlZEFscGhhQmxlbmRpbmc6IHN0YXRlcyAmJiBzdGF0ZXMuZW5hYmxlICYmIHN0YXRlcy5lbmFibGUuaW5kZXhPZigzMDQyKSAhPT0gLTEsXHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgRWZmZWN0LlNoYWRlcnNTdG9yZVtwcm9ncmFtLnZlcnRleFNoYWRlciArIGlkICsgXCJWZXJ0ZXhTaGFkZXJcIl0gPSBuZXdWZXJ0ZXhTaGFkZXI7XHJcbiAgICAgICAgRWZmZWN0LlNoYWRlcnNTdG9yZVtwcm9ncmFtLmZyYWdtZW50U2hhZGVyICsgaWQgKyBcIlBpeGVsU2hhZGVyXCJdID0gbmV3UGl4ZWxTaGFkZXI7XHJcblxyXG4gICAgICAgIGNvbnN0IHNoYWRlck1hdGVyaWFsID0gbmV3IFNoYWRlck1hdGVyaWFsKGlkLCBnbHRmUnVudGltZS5zY2VuZSwgc2hhZGVyUGF0aCwgb3B0aW9ucyk7XHJcbiAgICAgICAgc2hhZGVyTWF0ZXJpYWwub25FcnJvciA9IG9uU2hhZGVyQ29tcGlsZUVycm9yKHByb2dyYW0sIHNoYWRlck1hdGVyaWFsLCBvbkVycm9yKTtcclxuICAgICAgICBzaGFkZXJNYXRlcmlhbC5vbkNvbXBpbGVkID0gb25TaGFkZXJDb21waWxlU3VjY2VzcyhnbHRmUnVudGltZSwgc2hhZGVyTWF0ZXJpYWwsIHRlY2huaXF1ZSwgbWF0ZXJpYWwsIHVuVHJlYXRlZFVuaWZvcm1zLCBvblN1Y2Nlc3MpO1xyXG4gICAgICAgIHNoYWRlck1hdGVyaWFsLnNpZGVPcmllbnRhdGlvbiA9IE1hdGVyaWFsLkNvdW50ZXJDbG9ja1dpc2VTaWRlT3JpZW50YXRpb247XHJcblxyXG4gICAgICAgIGlmIChzdGF0ZXMgJiYgc3RhdGVzLmZ1bmN0aW9ucykge1xyXG4gICAgICAgICAgICBjb25zdCBmdW5jdGlvbnMgPSBzdGF0ZXMuZnVuY3Rpb25zO1xyXG4gICAgICAgICAgICBpZiAoZnVuY3Rpb25zLmN1bGxGYWNlICYmIGZ1bmN0aW9ucy5jdWxsRmFjZVswXSAhPT0gRUN1bGxpbmdUeXBlLkJBQ0spIHtcclxuICAgICAgICAgICAgICAgIHNoYWRlck1hdGVyaWFsLmJhY2tGYWNlQ3VsbGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBibGVuZEZ1bmMgPSBmdW5jdGlvbnMuYmxlbmRGdW5jU2VwYXJhdGU7XHJcbiAgICAgICAgICAgIGlmIChibGVuZEZ1bmMpIHtcclxuICAgICAgICAgICAgICAgIGlmIChcclxuICAgICAgICAgICAgICAgICAgICBibGVuZEZ1bmNbMF0gPT09IEVCbGVuZGluZ0Z1bmN0aW9uLlNSQ19BTFBIQSAmJlxyXG4gICAgICAgICAgICAgICAgICAgIGJsZW5kRnVuY1sxXSA9PT0gRUJsZW5kaW5nRnVuY3Rpb24uT05FX01JTlVTX1NSQ19BTFBIQSAmJlxyXG4gICAgICAgICAgICAgICAgICAgIGJsZW5kRnVuY1syXSA9PT0gRUJsZW5kaW5nRnVuY3Rpb24uT05FICYmXHJcbiAgICAgICAgICAgICAgICAgICAgYmxlbmRGdW5jWzNdID09PSBFQmxlbmRpbmdGdW5jdGlvbi5PTkVcclxuICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgIHNoYWRlck1hdGVyaWFsLmFscGhhTW9kZSA9IENvbnN0YW50cy5BTFBIQV9DT01CSU5FO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChcclxuICAgICAgICAgICAgICAgICAgICBibGVuZEZ1bmNbMF0gPT09IEVCbGVuZGluZ0Z1bmN0aW9uLk9ORSAmJlxyXG4gICAgICAgICAgICAgICAgICAgIGJsZW5kRnVuY1sxXSA9PT0gRUJsZW5kaW5nRnVuY3Rpb24uT05FICYmXHJcbiAgICAgICAgICAgICAgICAgICAgYmxlbmRGdW5jWzJdID09PSBFQmxlbmRpbmdGdW5jdGlvbi5aRVJPICYmXHJcbiAgICAgICAgICAgICAgICAgICAgYmxlbmRGdW5jWzNdID09PSBFQmxlbmRpbmdGdW5jdGlvbi5PTkVcclxuICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgIHNoYWRlck1hdGVyaWFsLmFscGhhTW9kZSA9IENvbnN0YW50cy5BTFBIQV9PTkVPTkU7XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgIGJsZW5kRnVuY1swXSA9PT0gRUJsZW5kaW5nRnVuY3Rpb24uU1JDX0FMUEhBICYmXHJcbiAgICAgICAgICAgICAgICAgICAgYmxlbmRGdW5jWzFdID09PSBFQmxlbmRpbmdGdW5jdGlvbi5PTkUgJiZcclxuICAgICAgICAgICAgICAgICAgICBibGVuZEZ1bmNbMl0gPT09IEVCbGVuZGluZ0Z1bmN0aW9uLlpFUk8gJiZcclxuICAgICAgICAgICAgICAgICAgICBibGVuZEZ1bmNbM10gPT09IEVCbGVuZGluZ0Z1bmN0aW9uLk9ORVxyXG4gICAgICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgc2hhZGVyTWF0ZXJpYWwuYWxwaGFNb2RlID0gQ29uc3RhbnRzLkFMUEhBX0FERDtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoXHJcbiAgICAgICAgICAgICAgICAgICAgYmxlbmRGdW5jWzBdID09PSBFQmxlbmRpbmdGdW5jdGlvbi5aRVJPICYmXHJcbiAgICAgICAgICAgICAgICAgICAgYmxlbmRGdW5jWzFdID09PSBFQmxlbmRpbmdGdW5jdGlvbi5PTkVfTUlOVVNfU1JDX0NPTE9SICYmXHJcbiAgICAgICAgICAgICAgICAgICAgYmxlbmRGdW5jWzJdID09PSBFQmxlbmRpbmdGdW5jdGlvbi5PTkUgJiZcclxuICAgICAgICAgICAgICAgICAgICBibGVuZEZ1bmNbM10gPT09IEVCbGVuZGluZ0Z1bmN0aW9uLk9ORVxyXG4gICAgICAgICAgICAgICAgKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgc2hhZGVyTWF0ZXJpYWwuYWxwaGFNb2RlID0gQ29uc3RhbnRzLkFMUEhBX1NVQlRSQUNUO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChcclxuICAgICAgICAgICAgICAgICAgICBibGVuZEZ1bmNbMF0gPT09IEVCbGVuZGluZ0Z1bmN0aW9uLkRTVF9DT0xPUiAmJlxyXG4gICAgICAgICAgICAgICAgICAgIGJsZW5kRnVuY1sxXSA9PT0gRUJsZW5kaW5nRnVuY3Rpb24uWkVSTyAmJlxyXG4gICAgICAgICAgICAgICAgICAgIGJsZW5kRnVuY1syXSA9PT0gRUJsZW5kaW5nRnVuY3Rpb24uT05FICYmXHJcbiAgICAgICAgICAgICAgICAgICAgYmxlbmRGdW5jWzNdID09PSBFQmxlbmRpbmdGdW5jdGlvbi5PTkVcclxuICAgICAgICAgICAgICAgICkge1xyXG4gICAgICAgICAgICAgICAgICAgIHNoYWRlck1hdGVyaWFsLmFscGhhTW9kZSA9IENvbnN0YW50cy5BTFBIQV9NVUxUSVBMWTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoXHJcbiAgICAgICAgICAgICAgICAgICAgYmxlbmRGdW5jWzBdID09PSBFQmxlbmRpbmdGdW5jdGlvbi5TUkNfQUxQSEEgJiZcclxuICAgICAgICAgICAgICAgICAgICBibGVuZEZ1bmNbMV0gPT09IEVCbGVuZGluZ0Z1bmN0aW9uLk9ORV9NSU5VU19TUkNfQ09MT1IgJiZcclxuICAgICAgICAgICAgICAgICAgICBibGVuZEZ1bmNbMl0gPT09IEVCbGVuZGluZ0Z1bmN0aW9uLk9ORSAmJlxyXG4gICAgICAgICAgICAgICAgICAgIGJsZW5kRnVuY1szXSA9PT0gRUJsZW5kaW5nRnVuY3Rpb24uT05FXHJcbiAgICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgICAgICBzaGFkZXJNYXRlcmlhbC5hbHBoYU1vZGUgPSBDb25zdGFudHMuQUxQSEFfTUFYSU1JWkVEO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogZ2xURiBWMSBMb2FkZXJcclxuICogQGludGVybmFsXHJcbiAqIEBkZXByZWNhdGVkXHJcbiAqL1xyXG5leHBvcnQgY2xhc3MgR0xURkxvYWRlciBpbXBsZW1lbnRzIElHTFRGTG9hZGVyIHtcclxuICAgIHB1YmxpYyBzdGF0aWMgRXh0ZW5zaW9uczogeyBbbmFtZTogc3RyaW5nXTogR0xURkxvYWRlckV4dGVuc2lvbiB9ID0ge307XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyBSZWdpc3RlckV4dGVuc2lvbihleHRlbnNpb246IEdMVEZMb2FkZXJFeHRlbnNpb24pOiB2b2lkIHtcclxuICAgICAgICBpZiAoR0xURkxvYWRlci5FeHRlbnNpb25zW2V4dGVuc2lvbi5uYW1lXSkge1xyXG4gICAgICAgICAgICBUb29scy5FcnJvcignVG9vbCB3aXRoIHRoZSBzYW1lIG5hbWUgXCInICsgZXh0ZW5zaW9uLm5hbWUgKyAnXCIgYWxyZWFkeSBleGlzdHMnKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgR0xURkxvYWRlci5FeHRlbnNpb25zW2V4dGVuc2lvbi5uYW1lXSA9IGV4dGVuc2lvbjtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpOiB2b2lkIHtcclxuICAgICAgICAvLyBkbyBub3RoaW5nXHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfaW1wb3J0TWVzaEFzeW5jKFxyXG4gICAgICAgIG1lc2hlc05hbWVzOiBhbnksXHJcbiAgICAgICAgc2NlbmU6IFNjZW5lLFxyXG4gICAgICAgIGRhdGE6IElHTFRGTG9hZGVyRGF0YSxcclxuICAgICAgICByb290VXJsOiBzdHJpbmcsXHJcbiAgICAgICAgYXNzZXRDb250YWluZXI6IE51bGxhYmxlPEFzc2V0Q29udGFpbmVyPixcclxuICAgICAgICBvblN1Y2Nlc3M6IChtZXNoZXM6IEFic3RyYWN0TWVzaFtdLCBza2VsZXRvbnM6IFNrZWxldG9uW10pID0+IHZvaWQsXHJcbiAgICAgICAgb25Qcm9ncmVzcz86IChldmVudDogSVNjZW5lTG9hZGVyUHJvZ3Jlc3NFdmVudCkgPT4gdm9pZCxcclxuICAgICAgICBvbkVycm9yPzogKG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZFxyXG4gICAgKTogYm9vbGVhbiB7XHJcbiAgICAgICAgc2NlbmUudXNlUmlnaHRIYW5kZWRTeXN0ZW0gPSB0cnVlO1xyXG5cclxuICAgICAgICBHTFRGTG9hZGVyRXh0ZW5zaW9uLkxvYWRSdW50aW1lQXN5bmMoXHJcbiAgICAgICAgICAgIHNjZW5lLFxyXG4gICAgICAgICAgICBkYXRhLFxyXG4gICAgICAgICAgICByb290VXJsLFxyXG4gICAgICAgICAgICAoZ2x0ZlJ1bnRpbWUpID0+IHtcclxuICAgICAgICAgICAgICAgIGdsdGZSdW50aW1lLmFzc2V0Q29udGFpbmVyID0gYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgICAgICAgICBnbHRmUnVudGltZS5pbXBvcnRPbmx5TWVzaGVzID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAobWVzaGVzTmFtZXMgPT09IFwiXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICBnbHRmUnVudGltZS5pbXBvcnRNZXNoZXNOYW1lcyA9IFtdO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgbWVzaGVzTmFtZXMgPT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgICAgICAgICAgICAgICBnbHRmUnVudGltZS5pbXBvcnRNZXNoZXNOYW1lcyA9IFttZXNoZXNOYW1lc107XHJcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG1lc2hlc05hbWVzICYmICEobWVzaGVzTmFtZXMgaW5zdGFuY2VvZiBBcnJheSkpIHtcclxuICAgICAgICAgICAgICAgICAgICBnbHRmUnVudGltZS5pbXBvcnRNZXNoZXNOYW1lcyA9IFttZXNoZXNOYW1lc107XHJcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgIGdsdGZSdW50aW1lLmltcG9ydE1lc2hlc05hbWVzID0gW107XHJcbiAgICAgICAgICAgICAgICAgICAgVG9vbHMuV2FybihcIkFyZ3VtZW50IG1lc2hlc05hbWVzIG11c3QgYmUgb2YgdHlwZSBzdHJpbmcgb3Igc3RyaW5nW11cIik7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gQ3JlYXRlIG5vZGVzXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9jcmVhdGVOb2RlcyhnbHRmUnVudGltZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgY29uc3QgbWVzaGVzID0gbmV3IEFycmF5PEFic3RyYWN0TWVzaD4oKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHNrZWxldG9ucyA9IG5ldyBBcnJheTxTa2VsZXRvbj4oKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBGaWxsIGFycmF5cyBvZiBtZXNoZXMgYW5kIHNrZWxldG9uc1xyXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBuZGUgaW4gZ2x0ZlJ1bnRpbWUubm9kZXMpIHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBub2RlOiBJR0xURk5vZGUgPSBnbHRmUnVudGltZS5ub2Rlc1tuZGVdO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAobm9kZS5iYWJ5bG9uTm9kZSBpbnN0YW5jZW9mIEFic3RyYWN0TWVzaCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBtZXNoZXMucHVzaCg8QWJzdHJhY3RNZXNoPm5vZGUuYmFieWxvbk5vZGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHNrbCBpbiBnbHRmUnVudGltZS5za2lucykge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNraW46IElHTFRGU2tpbnMgPSBnbHRmUnVudGltZS5za2luc1tza2xdO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAoc2tpbi5iYWJ5bG9uU2tlbGV0b24gaW5zdGFuY2VvZiBTa2VsZXRvbikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBza2VsZXRvbnMucHVzaChza2luLmJhYnlsb25Ta2VsZXRvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIC8vIExvYWQgYnVmZmVycywgc2hhZGVycywgbWF0ZXJpYWxzLCBldGMuXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkQnVmZmVyc0FzeW5jKGdsdGZSdW50aW1lLCAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9hZFNoYWRlcnNBc3luYyhnbHRmUnVudGltZSwgKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpbXBvcnRNYXRlcmlhbHMoZ2x0ZlJ1bnRpbWUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBwb3N0TG9hZChnbHRmUnVudGltZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUdMVEZGaWxlTG9hZGVyLkluY3JlbWVudGFsTG9hZGluZyAmJiBvblN1Y2Nlc3MpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9uU3VjY2VzcyhtZXNoZXMsIHNrZWxldG9ucyk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChHTFRGRmlsZUxvYWRlci5JbmNyZW1lbnRhbExvYWRpbmcgJiYgb25TdWNjZXNzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgb25TdWNjZXNzKG1lc2hlcywgc2tlbGV0b25zKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgb25FcnJvclxyXG4gICAgICAgICk7XHJcblxyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW1wb3J0cyBvbmUgb3IgbW9yZSBtZXNoZXMgZnJvbSBhIGxvYWRlZCBnbHRmIGZpbGUgYW5kIGFkZHMgdGhlbSB0byB0aGUgc2NlbmVcclxuICAgICAqIEBwYXJhbSBtZXNoZXNOYW1lcyBhIHN0cmluZyBvciBhcnJheSBvZiBzdHJpbmdzIG9mIHRoZSBtZXNoIG5hbWVzIHRoYXQgc2hvdWxkIGJlIGxvYWRlZCBmcm9tIHRoZSBmaWxlXHJcbiAgICAgKiBAcGFyYW0gc2NlbmUgdGhlIHNjZW5lIHRoZSBtZXNoZXMgc2hvdWxkIGJlIGFkZGVkIHRvXHJcbiAgICAgKiBAcGFyYW0gYXNzZXRDb250YWluZXIgZGVmaW5lcyB0aGUgYXNzZXQgY29udGFpbmVyIHRvIHVzZSAoY2FuIGJlIG51bGwpXHJcbiAgICAgKiBAcGFyYW0gZGF0YSBnbHRmIGRhdGEgY29udGFpbmluZyBpbmZvcm1hdGlvbiBvZiB0aGUgbWVzaGVzIGluIGEgbG9hZGVkIGZpbGVcclxuICAgICAqIEBwYXJhbSByb290VXJsIHJvb3QgdXJsIHRvIGxvYWQgZnJvbVxyXG4gICAgICogQHBhcmFtIG9uUHJvZ3Jlc3MgZXZlbnQgdGhhdCBmaXJlcyB3aGVuIGxvYWRpbmcgcHJvZ3Jlc3MgaGFzIG9jY3VyZWRcclxuICAgICAqIEByZXR1cm5zIGEgcHJvbWlzZSBjb250YWluZyB0aGUgbG9hZGVkIG1lc2hlcywgcGFydGljbGVzLCBza2VsZXRvbnMgYW5kIGFuaW1hdGlvbnNcclxuICAgICAqL1xyXG4gICAgcHVibGljIGltcG9ydE1lc2hBc3luYyhcclxuICAgICAgICBtZXNoZXNOYW1lczogYW55LFxyXG4gICAgICAgIHNjZW5lOiBTY2VuZSxcclxuICAgICAgICBhc3NldENvbnRhaW5lcjogTnVsbGFibGU8QXNzZXRDb250YWluZXI+LFxyXG4gICAgICAgIGRhdGE6IElHTFRGTG9hZGVyRGF0YSxcclxuICAgICAgICByb290VXJsOiBzdHJpbmcsXHJcbiAgICAgICAgb25Qcm9ncmVzcz86IChldmVudDogSVNjZW5lTG9hZGVyUHJvZ3Jlc3NFdmVudCkgPT4gdm9pZFxyXG4gICAgKTogUHJvbWlzZTxJU2NlbmVMb2FkZXJBc3luY1Jlc3VsdD4ge1xyXG4gICAgICAgIHJldHVybiBuZXcgUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuX2ltcG9ydE1lc2hBc3luYyhcclxuICAgICAgICAgICAgICAgIG1lc2hlc05hbWVzLFxyXG4gICAgICAgICAgICAgICAgc2NlbmUsXHJcbiAgICAgICAgICAgICAgICBkYXRhLFxyXG4gICAgICAgICAgICAgICAgcm9vdFVybCxcclxuICAgICAgICAgICAgICAgIGFzc2V0Q29udGFpbmVyLFxyXG4gICAgICAgICAgICAgICAgKG1lc2hlcywgc2tlbGV0b25zKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG1lc2hlczogbWVzaGVzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBwYXJ0aWNsZVN5c3RlbXM6IFtdLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBza2VsZXRvbnM6IHNrZWxldG9ucyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgYW5pbWF0aW9uR3JvdXBzOiBbXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgbGlnaHRzOiBbXSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNmb3JtTm9kZXM6IFtdLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBnZW9tZXRyaWVzOiBbXSxcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICBvblByb2dyZXNzLFxyXG4gICAgICAgICAgICAgICAgKG1lc3NhZ2UpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IEVycm9yKG1lc3NhZ2UpKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9sb2FkQXN5bmMoXHJcbiAgICAgICAgc2NlbmU6IFNjZW5lLFxyXG4gICAgICAgIGRhdGE6IElHTFRGTG9hZGVyRGF0YSxcclxuICAgICAgICByb290VXJsOiBzdHJpbmcsXHJcbiAgICAgICAgb25TdWNjZXNzOiAoKSA9PiB2b2lkLFxyXG4gICAgICAgIG9uUHJvZ3Jlc3M/OiAoZXZlbnQ6IElTY2VuZUxvYWRlclByb2dyZXNzRXZlbnQpID0+IHZvaWQsXHJcbiAgICAgICAgb25FcnJvcj86IChtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWRcclxuICAgICk6IHZvaWQge1xyXG4gICAgICAgIHNjZW5lLnVzZVJpZ2h0SGFuZGVkU3lzdGVtID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgR0xURkxvYWRlckV4dGVuc2lvbi5Mb2FkUnVudGltZUFzeW5jKFxyXG4gICAgICAgICAgICBzY2VuZSxcclxuICAgICAgICAgICAgZGF0YSxcclxuICAgICAgICAgICAgcm9vdFVybCxcclxuICAgICAgICAgICAgKGdsdGZSdW50aW1lKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAvLyBMb2FkIHJ1bnRpbWUgZXh0ZW5zaW9zXHJcbiAgICAgICAgICAgICAgICBHTFRGTG9hZGVyRXh0ZW5zaW9uLkxvYWRSdW50aW1lRXh0ZW5zaW9uc0FzeW5jKFxyXG4gICAgICAgICAgICAgICAgICAgIGdsdGZSdW50aW1lLFxyXG4gICAgICAgICAgICAgICAgICAgICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ3JlYXRlIG5vZGVzXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZU5vZGVzKGdsdGZSdW50aW1lKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIExvYWQgYnVmZmVycywgc2hhZGVycywgbWF0ZXJpYWxzLCBldGMuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRCdWZmZXJzQXN5bmMoZ2x0ZlJ1bnRpbWUsICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRTaGFkZXJzQXN5bmMoZ2x0ZlJ1bnRpbWUsICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpbXBvcnRNYXRlcmlhbHMoZ2x0ZlJ1bnRpbWUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBvc3RMb2FkKGdsdGZSdW50aW1lKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFHTFRGRmlsZUxvYWRlci5JbmNyZW1lbnRhbExvYWRpbmcpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb25TdWNjZXNzKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEdMVEZGaWxlTG9hZGVyLkluY3JlbWVudGFsTG9hZGluZykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25TdWNjZXNzKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgICAgIG9uRXJyb3JcclxuICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIG9uRXJyb3JcclxuICAgICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSW1wb3J0cyBhbGwgb2JqZWN0cyBmcm9tIGEgbG9hZGVkIGdsdGYgZmlsZSBhbmQgYWRkcyB0aGVtIHRvIHRoZSBzY2VuZVxyXG4gICAgICogQHBhcmFtIHNjZW5lIHRoZSBzY2VuZSB0aGUgb2JqZWN0cyBzaG91bGQgYmUgYWRkZWQgdG9cclxuICAgICAqIEBwYXJhbSBkYXRhIGdsdGYgZGF0YSBjb250YWluaW5nIGluZm9ybWF0aW9uIG9mIHRoZSBtZXNoZXMgaW4gYSBsb2FkZWQgZmlsZVxyXG4gICAgICogQHBhcmFtIHJvb3RVcmwgcm9vdCB1cmwgdG8gbG9hZCBmcm9tXHJcbiAgICAgKiBAcGFyYW0gb25Qcm9ncmVzcyBldmVudCB0aGF0IGZpcmVzIHdoZW4gbG9hZGluZyBwcm9ncmVzcyBoYXMgb2NjdXJlZFxyXG4gICAgICogQHJldHVybnMgYSBwcm9taXNlIHdoaWNoIGNvbXBsZXRlcyB3aGVuIG9iamVjdHMgaGF2ZSBiZWVuIGxvYWRlZCB0byB0aGUgc2NlbmVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRBc3luYyhzY2VuZTogU2NlbmUsIGRhdGE6IElHTFRGTG9hZGVyRGF0YSwgcm9vdFVybDogc3RyaW5nLCBvblByb2dyZXNzPzogKGV2ZW50OiBJU2NlbmVMb2FkZXJQcm9ncmVzc0V2ZW50KSA9PiB2b2lkKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5fbG9hZEFzeW5jKFxyXG4gICAgICAgICAgICAgICAgc2NlbmUsXHJcbiAgICAgICAgICAgICAgICBkYXRhLFxyXG4gICAgICAgICAgICAgICAgcm9vdFVybCxcclxuICAgICAgICAgICAgICAgICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICByZXNvbHZlKCk7XHJcbiAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgb25Qcm9ncmVzcyxcclxuICAgICAgICAgICAgICAgIChtZXNzYWdlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0KG5ldyBFcnJvcihtZXNzYWdlKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZFNoYWRlcnNBc3luYyhnbHRmUnVudGltZTogSUdMVEZSdW50aW1lLCBvbmxvYWQ6ICgpID0+IHZvaWQpOiB2b2lkIHtcclxuICAgICAgICBsZXQgaGFzU2hhZGVycyA9IGZhbHNlO1xyXG5cclxuICAgICAgICBjb25zdCBwcm9jZXNzU2hhZGVyID0gKHNoYTogc3RyaW5nLCBzaGFkZXI6IElHTFRGU2hhZGVyKSA9PiB7XHJcbiAgICAgICAgICAgIEdMVEZMb2FkZXJFeHRlbnNpb24uTG9hZFNoYWRlclN0cmluZ0FzeW5jKFxyXG4gICAgICAgICAgICAgICAgZ2x0ZlJ1bnRpbWUsXHJcbiAgICAgICAgICAgICAgICBzaGEsXHJcbiAgICAgICAgICAgICAgICAoc2hhZGVyU3RyaW5nKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHNoYWRlclN0cmluZyBpbnN0YW5jZW9mIEFycmF5QnVmZmVyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGdsdGZSdW50aW1lLmxvYWRlZFNoYWRlckNvdW50Kys7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChzaGFkZXJTdHJpbmcpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgRWZmZWN0LlNoYWRlcnNTdG9yZVtzaGEgKyAoc2hhZGVyLnR5cGUgPT09IEVTaGFkZXJUeXBlLlZFUlRFWCA/IFwiVmVydGV4U2hhZGVyXCIgOiBcIlBpeGVsU2hhZGVyXCIpXSA9IHNoYWRlclN0cmluZztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChnbHRmUnVudGltZS5sb2FkZWRTaGFkZXJDb3VudCA9PT0gZ2x0ZlJ1bnRpbWUuc2hhZGVyc2NvdW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG9ubG9hZCgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgVG9vbHMuRXJyb3IoXCJFcnJvciB3aGVuIGxvYWRpbmcgc2hhZGVyIHByb2dyYW0gbmFtZWQgXCIgKyBzaGEgKyBcIiBsb2NhdGVkIGF0IFwiICsgc2hhZGVyLnVyaSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgZm9yIChjb25zdCBzaGEgaW4gZ2x0ZlJ1bnRpbWUuc2hhZGVycykge1xyXG4gICAgICAgICAgICBoYXNTaGFkZXJzID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHNoYWRlcjogSUdMVEZTaGFkZXIgPSBnbHRmUnVudGltZS5zaGFkZXJzW3NoYV07XHJcbiAgICAgICAgICAgIGlmIChzaGFkZXIpIHtcclxuICAgICAgICAgICAgICAgIHByb2Nlc3NTaGFkZXIuYmluZCh0aGlzLCBzaGEsIHNoYWRlcikoKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIFRvb2xzLkVycm9yKFwiTm8gc2hhZGVyIG5hbWVkOiBcIiArIHNoYSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghaGFzU2hhZGVycykge1xyXG4gICAgICAgICAgICBvbmxvYWQoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZEJ1ZmZlcnNBc3luYyhnbHRmUnVudGltZTogSUdMVEZSdW50aW1lLCBvbkxvYWQ6ICgpID0+IHZvaWQpOiB2b2lkIHtcclxuICAgICAgICBsZXQgaGFzQnVmZmVycyA9IGZhbHNlO1xyXG5cclxuICAgICAgICBjb25zdCBwcm9jZXNzQnVmZmVyID0gKGJ1Zjogc3RyaW5nLCBidWZmZXI6IElHTFRGQnVmZmVyKSA9PiB7XHJcbiAgICAgICAgICAgIEdMVEZMb2FkZXJFeHRlbnNpb24uTG9hZEJ1ZmZlckFzeW5jKFxyXG4gICAgICAgICAgICAgICAgZ2x0ZlJ1bnRpbWUsXHJcbiAgICAgICAgICAgICAgICBidWYsXHJcbiAgICAgICAgICAgICAgICAoYnVmZmVyVmlldykgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGdsdGZSdW50aW1lLmxvYWRlZEJ1ZmZlckNvdW50Kys7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGlmIChidWZmZXJWaWV3KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChidWZmZXJWaWV3LmJ5dGVMZW5ndGggIT0gZ2x0ZlJ1bnRpbWUuYnVmZmVyc1tidWZdLmJ5dGVMZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRvb2xzLkVycm9yKFwiQnVmZmVyIG5hbWVkIFwiICsgYnVmICsgXCIgaXMgbGVuZ3RoIFwiICsgYnVmZmVyVmlldy5ieXRlTGVuZ3RoICsgXCIuIEV4cGVjdGVkOiBcIiArIGJ1ZmZlci5ieXRlTGVuZ3RoKTsgLy8gSW1wcm92ZSBlcnJvciBtZXNzYWdlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGdsdGZSdW50aW1lLmxvYWRlZEJ1ZmZlclZpZXdzW2J1Zl0gPSBidWZmZXJWaWV3O1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGdsdGZSdW50aW1lLmxvYWRlZEJ1ZmZlckNvdW50ID09PSBnbHRmUnVudGltZS5idWZmZXJzQ291bnQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgb25Mb2FkKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBUb29scy5FcnJvcihcIkVycm9yIHdoZW4gbG9hZGluZyBidWZmZXIgbmFtZWQgXCIgKyBidWYgKyBcIiBsb2NhdGVkIGF0IFwiICsgYnVmZmVyLnVyaSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgZm9yIChjb25zdCBidWYgaW4gZ2x0ZlJ1bnRpbWUuYnVmZmVycykge1xyXG4gICAgICAgICAgICBoYXNCdWZmZXJzID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlcjogSUdMVEZCdWZmZXIgPSBnbHRmUnVudGltZS5idWZmZXJzW2J1Zl07XHJcbiAgICAgICAgICAgIGlmIChidWZmZXIpIHtcclxuICAgICAgICAgICAgICAgIHByb2Nlc3NCdWZmZXIuYmluZCh0aGlzLCBidWYsIGJ1ZmZlcikoKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIFRvb2xzLkVycm9yKFwiTm8gYnVmZmVyIG5hbWVkOiBcIiArIGJ1Zik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghaGFzQnVmZmVycykge1xyXG4gICAgICAgICAgICBvbkxvYWQoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfY3JlYXRlTm9kZXMoZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSk6IHZvaWQge1xyXG4gICAgICAgIGxldCBjdXJyZW50U2NlbmUgPSA8SUdMVEZTY2VuZT5nbHRmUnVudGltZS5jdXJyZW50U2NlbmU7XHJcblxyXG4gICAgICAgIGlmIChjdXJyZW50U2NlbmUpIHtcclxuICAgICAgICAgICAgLy8gT25seSBvbmUgc2NlbmUgZXZlbiBpZiBtdWx0aXBsZSBzY2VuZXMgYXJlIGRlZmluZWRcclxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjdXJyZW50U2NlbmUubm9kZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIHRyYXZlcnNlTm9kZXMoZ2x0ZlJ1bnRpbWUsIGN1cnJlbnRTY2VuZS5ub2Rlc1tpXSwgbnVsbCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAvLyBMb2FkIGFsbCBzY2VuZXNcclxuICAgICAgICAgICAgZm9yIChjb25zdCB0aGluZyBpbiBnbHRmUnVudGltZS5zY2VuZXMpIHtcclxuICAgICAgICAgICAgICAgIGN1cnJlbnRTY2VuZSA9IDxJR0xURlNjZW5lPmdsdGZSdW50aW1lLnNjZW5lc1t0aGluZ107XHJcblxyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjdXJyZW50U2NlbmUubm9kZXMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgICAgICB0cmF2ZXJzZU5vZGVzKGdsdGZSdW50aW1lLCBjdXJyZW50U2NlbmUubm9kZXNbaV0sIG51bGwpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBHTFRGTG9hZGVyRXh0ZW5zaW9uIHtcclxuICAgIHByaXZhdGUgX25hbWU6IHN0cmluZztcclxuXHJcbiAgICBwdWJsaWMgY29uc3RydWN0b3IobmFtZTogc3RyaW5nKSB7XHJcbiAgICAgICAgdGhpcy5fbmFtZSA9IG5hbWU7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGdldCBuYW1lKCk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX25hbWU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGFuIG92ZXJyaWRlIGZvciBsb2FkaW5nIHRoZSBydW50aW1lXHJcbiAgICAgKiBSZXR1cm4gdHJ1ZSB0byBzdG9wIGZ1cnRoZXIgZXh0ZW5zaW9ucyBmcm9tIGxvYWRpbmcgdGhlIHJ1bnRpbWVcclxuICAgICAqIEBwYXJhbSBzY2VuZVxyXG4gICAgICogQHBhcmFtIGRhdGFcclxuICAgICAqIEBwYXJhbSByb290VXJsXHJcbiAgICAgKiBAcGFyYW0gb25TdWNjZXNzXHJcbiAgICAgKiBAcGFyYW0gb25FcnJvclxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZFJ1bnRpbWVBc3luYyhzY2VuZTogU2NlbmUsIGRhdGE6IElHTFRGTG9hZGVyRGF0YSwgcm9vdFVybDogc3RyaW5nLCBvblN1Y2Nlc3M/OiAoZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSkgPT4gdm9pZCwgb25FcnJvcj86IChtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQpOiBib29sZWFuIHtcclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGFuIG9udmVycmlkZSBmb3IgY3JlYXRpbmcgZ2x0ZiBydW50aW1lXHJcbiAgICAgKiBSZXR1cm4gdHJ1ZSB0byBzdG9wIGZ1cnRoZXIgZXh0ZW5zaW9ucyBmcm9tIGNyZWF0aW5nIHRoZSBydW50aW1lXHJcbiAgICAgKiBAcGFyYW0gZ2x0ZlJ1bnRpbWVcclxuICAgICAqIEBwYXJhbSBvblN1Y2Nlc3NcclxuICAgICAqIEBwYXJhbSBvbkVycm9yXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkUnVudGltZUV4dGVuc2lvbnNBc3luYyhnbHRmUnVudGltZTogSUdMVEZSdW50aW1lLCBvblN1Y2Nlc3M6ICgpID0+IHZvaWQsIG9uRXJyb3I/OiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lcyBhbiBvdmVycmlkZSBmb3IgbG9hZGluZyBidWZmZXJzXHJcbiAgICAgKiBSZXR1cm4gdHJ1ZSB0byBzdG9wIGZ1cnRoZXIgZXh0ZW5zaW9ucyBmcm9tIGxvYWRpbmcgdGhpcyBidWZmZXJcclxuICAgICAqIEBwYXJhbSBnbHRmUnVudGltZVxyXG4gICAgICogQHBhcmFtIGlkXHJcbiAgICAgKiBAcGFyYW0gb25TdWNjZXNzXHJcbiAgICAgKiBAcGFyYW0gb25FcnJvclxyXG4gICAgICogQHBhcmFtIG9uUHJvZ3Jlc3NcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRCdWZmZXJBc3luYyhcclxuICAgICAgICBnbHRmUnVudGltZTogSUdMVEZSdW50aW1lLFxyXG4gICAgICAgIGlkOiBzdHJpbmcsXHJcbiAgICAgICAgb25TdWNjZXNzOiAoYnVmZmVyOiBBcnJheUJ1ZmZlclZpZXcpID0+IHZvaWQsXHJcbiAgICAgICAgb25FcnJvcjogKG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZCxcclxuICAgICAgICBvblByb2dyZXNzPzogKCkgPT4gdm9pZFxyXG4gICAgKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lcyBhbiBvdmVycmlkZSBmb3IgbG9hZGluZyB0ZXh0dXJlIGJ1ZmZlcnNcclxuICAgICAqIFJldHVybiB0cnVlIHRvIHN0b3AgZnVydGhlciBleHRlbnNpb25zIGZyb20gbG9hZGluZyB0aGlzIHRleHR1cmUgZGF0YVxyXG4gICAgICogQHBhcmFtIGdsdGZSdW50aW1lXHJcbiAgICAgKiBAcGFyYW0gaWRcclxuICAgICAqIEBwYXJhbSBvblN1Y2Nlc3NcclxuICAgICAqIEBwYXJhbSBvbkVycm9yXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkVGV4dHVyZUJ1ZmZlckFzeW5jKGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUsIGlkOiBzdHJpbmcsIG9uU3VjY2VzczogKGJ1ZmZlcjogQXJyYXlCdWZmZXJWaWV3KSA9PiB2b2lkLCBvbkVycm9yOiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lcyBhbiBvdmVycmlkZSBmb3IgY3JlYXRpbmcgdGV4dHVyZXNcclxuICAgICAqIFJldHVybiB0cnVlIHRvIHN0b3AgZnVydGhlciBleHRlbnNpb25zIGZyb20gbG9hZGluZyB0aGlzIHRleHR1cmVcclxuICAgICAqIEBwYXJhbSBnbHRmUnVudGltZVxyXG4gICAgICogQHBhcmFtIGlkXHJcbiAgICAgKiBAcGFyYW0gYnVmZmVyXHJcbiAgICAgKiBAcGFyYW0gb25TdWNjZXNzXHJcbiAgICAgKiBAcGFyYW0gb25FcnJvclxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgY3JlYXRlVGV4dHVyZUFzeW5jKGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUsIGlkOiBzdHJpbmcsIGJ1ZmZlcjogQXJyYXlCdWZmZXJWaWV3LCBvblN1Y2Nlc3M6ICh0ZXh0dXJlOiBUZXh0dXJlKSA9PiB2b2lkLCBvbkVycm9yOiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lcyBhbiBvdmVycmlkZSBmb3IgbG9hZGluZyBzaGFkZXIgc3RyaW5nc1xyXG4gICAgICogUmV0dXJuIHRydWUgdG8gc3RvcCBmdXJ0aGVyIGV4dGVuc2lvbnMgZnJvbSBsb2FkaW5nIHRoaXMgc2hhZGVyIGRhdGFcclxuICAgICAqIEBwYXJhbSBnbHRmUnVudGltZVxyXG4gICAgICogQHBhcmFtIGlkXHJcbiAgICAgKiBAcGFyYW0gb25TdWNjZXNzXHJcbiAgICAgKiBAcGFyYW0gb25FcnJvclxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZFNoYWRlclN0cmluZ0FzeW5jKGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUsIGlkOiBzdHJpbmcsIG9uU3VjY2VzczogKHNoYWRlclN0cmluZzogc3RyaW5nKSA9PiB2b2lkLCBvbkVycm9yOiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lcyBhbiBvdmVycmlkZSBmb3IgbG9hZGluZyBtYXRlcmlhbHNcclxuICAgICAqIFJldHVybiB0cnVlIHRvIHN0b3AgZnVydGhlciBleHRlbnNpb25zIGZyb20gbG9hZGluZyB0aGlzIG1hdGVyaWFsXHJcbiAgICAgKiBAcGFyYW0gZ2x0ZlJ1bnRpbWVcclxuICAgICAqIEBwYXJhbSBpZFxyXG4gICAgICogQHBhcmFtIG9uU3VjY2Vzc1xyXG4gICAgICogQHBhcmFtIG9uRXJyb3JcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRNYXRlcmlhbEFzeW5jKGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUsIGlkOiBzdHJpbmcsIG9uU3VjY2VzczogKG1hdGVyaWFsOiBNYXRlcmlhbCkgPT4gdm9pZCwgb25FcnJvcjogKG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICAvLyAtLS0tLS0tLS1cclxuICAgIC8vIFV0aWxpdGllc1xyXG4gICAgLy8gLS0tLS0tLS0tXHJcblxyXG4gICAgcHVibGljIHN0YXRpYyBMb2FkUnVudGltZUFzeW5jKFxyXG4gICAgICAgIHNjZW5lOiBTY2VuZSxcclxuICAgICAgICBkYXRhOiBJR0xURkxvYWRlckRhdGEsXHJcbiAgICAgICAgcm9vdFVybDogc3RyaW5nLFxyXG4gICAgICAgIG9uU3VjY2Vzcz86IChnbHRmUnVudGltZTogSUdMVEZSdW50aW1lKSA9PiB2b2lkLFxyXG4gICAgICAgIG9uRXJyb3I/OiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkXHJcbiAgICApOiB2b2lkIHtcclxuICAgICAgICBHTFRGTG9hZGVyRXh0ZW5zaW9uLl9BcHBseUV4dGVuc2lvbnMoXHJcbiAgICAgICAgICAgIChsb2FkZXJFeHRlbnNpb24pID0+IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBsb2FkZXJFeHRlbnNpb24ubG9hZFJ1bnRpbWVBc3luYyhzY2VuZSwgZGF0YSwgcm9vdFVybCwgb25TdWNjZXNzLCBvbkVycm9yKTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgc2V0VGltZW91dCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFvblN1Y2Nlc3MpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBvblN1Y2Nlc3MoR0xURkxvYWRlckJhc2UuQ3JlYXRlUnVudGltZShkYXRhLmpzb24sIHNjZW5lLCByb290VXJsKSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyBMb2FkUnVudGltZUV4dGVuc2lvbnNBc3luYyhnbHRmUnVudGltZTogSUdMVEZSdW50aW1lLCBvblN1Y2Nlc3M6ICgpID0+IHZvaWQsIG9uRXJyb3I/OiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkKTogdm9pZCB7XHJcbiAgICAgICAgR0xURkxvYWRlckV4dGVuc2lvbi5fQXBwbHlFeHRlbnNpb25zKFxyXG4gICAgICAgICAgICAobG9hZGVyRXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbG9hZGVyRXh0ZW5zaW9uLmxvYWRSdW50aW1lRXh0ZW5zaW9uc0FzeW5jKGdsdGZSdW50aW1lLCBvblN1Y2Nlc3MsIG9uRXJyb3IpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBvblN1Y2Nlc3MoKTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgc3RhdGljIExvYWRCdWZmZXJBc3luYyhcclxuICAgICAgICBnbHRmUnVudGltZTogSUdMVEZSdW50aW1lLFxyXG4gICAgICAgIGlkOiBzdHJpbmcsXHJcbiAgICAgICAgb25TdWNjZXNzOiAoYnVmZmVyVmlldzogQXJyYXlCdWZmZXJWaWV3KSA9PiB2b2lkLFxyXG4gICAgICAgIG9uRXJyb3I6IChtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQsXHJcbiAgICAgICAgb25Qcm9ncmVzcz86ICgpID0+IHZvaWRcclxuICAgICk6IHZvaWQge1xyXG4gICAgICAgIEdMVEZMb2FkZXJFeHRlbnNpb24uX0FwcGx5RXh0ZW5zaW9ucyhcclxuICAgICAgICAgICAgKGxvYWRlckV4dGVuc2lvbikgPT4ge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGxvYWRlckV4dGVuc2lvbi5sb2FkQnVmZmVyQXN5bmMoZ2x0ZlJ1bnRpbWUsIGlkLCBvblN1Y2Nlc3MsIG9uRXJyb3IsIG9uUHJvZ3Jlc3MpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBHTFRGTG9hZGVyQmFzZS5Mb2FkQnVmZmVyQXN5bmMoZ2x0ZlJ1bnRpbWUsIGlkLCBvblN1Y2Nlc3MsIG9uRXJyb3IsIG9uUHJvZ3Jlc3MpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgc3RhdGljIExvYWRUZXh0dXJlQXN5bmMoZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSwgaWQ6IHN0cmluZywgb25TdWNjZXNzOiAodGV4dHVyZTogVGV4dHVyZSkgPT4gdm9pZCwgb25FcnJvcjogKG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZCk6IHZvaWQge1xyXG4gICAgICAgIEdMVEZMb2FkZXJFeHRlbnNpb24uX0xvYWRUZXh0dXJlQnVmZmVyQXN5bmMoXHJcbiAgICAgICAgICAgIGdsdGZSdW50aW1lLFxyXG4gICAgICAgICAgICBpZCxcclxuICAgICAgICAgICAgKGJ1ZmZlcikgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKGJ1ZmZlcikge1xyXG4gICAgICAgICAgICAgICAgICAgIEdMVEZMb2FkZXJFeHRlbnNpb24uX0NyZWF0ZVRleHR1cmVBc3luYyhnbHRmUnVudGltZSwgaWQsIGJ1ZmZlciwgb25TdWNjZXNzLCBvbkVycm9yKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgb25FcnJvclxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyBMb2FkU2hhZGVyU3RyaW5nQXN5bmMoZ2x0ZlJ1bnRpbWU6IElHTFRGUnVudGltZSwgaWQ6IHN0cmluZywgb25TdWNjZXNzOiAoc2hhZGVyRGF0YTogc3RyaW5nIHwgQXJyYXlCdWZmZXIpID0+IHZvaWQsIG9uRXJyb3I6IChtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQpOiB2b2lkIHtcclxuICAgICAgICBHTFRGTG9hZGVyRXh0ZW5zaW9uLl9BcHBseUV4dGVuc2lvbnMoXHJcbiAgICAgICAgICAgIChsb2FkZXJFeHRlbnNpb24pID0+IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBsb2FkZXJFeHRlbnNpb24ubG9hZFNoYWRlclN0cmluZ0FzeW5jKGdsdGZSdW50aW1lLCBpZCwgb25TdWNjZXNzLCBvbkVycm9yKTtcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgR0xURkxvYWRlckJhc2UuTG9hZFNoYWRlclN0cmluZ0FzeW5jKGdsdGZSdW50aW1lLCBpZCwgb25TdWNjZXNzLCBvbkVycm9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyBMb2FkTWF0ZXJpYWxBc3luYyhnbHRmUnVudGltZTogSUdMVEZSdW50aW1lLCBpZDogc3RyaW5nLCBvblN1Y2Nlc3M6IChtYXRlcmlhbDogTWF0ZXJpYWwpID0+IHZvaWQsIG9uRXJyb3I6IChtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQpOiB2b2lkIHtcclxuICAgICAgICBHTFRGTG9hZGVyRXh0ZW5zaW9uLl9BcHBseUV4dGVuc2lvbnMoXHJcbiAgICAgICAgICAgIChsb2FkZXJFeHRlbnNpb24pID0+IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBsb2FkZXJFeHRlbnNpb24ubG9hZE1hdGVyaWFsQXN5bmMoZ2x0ZlJ1bnRpbWUsIGlkLCBvblN1Y2Nlc3MsIG9uRXJyb3IpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBHTFRGTG9hZGVyQmFzZS5Mb2FkTWF0ZXJpYWxBc3luYyhnbHRmUnVudGltZSwgaWQsIG9uU3VjY2Vzcywgb25FcnJvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIF9Mb2FkVGV4dHVyZUJ1ZmZlckFzeW5jKFxyXG4gICAgICAgIGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUsXHJcbiAgICAgICAgaWQ6IHN0cmluZyxcclxuICAgICAgICBvblN1Y2Nlc3M6IChidWZmZXI6IE51bGxhYmxlPEFycmF5QnVmZmVyVmlldz4pID0+IHZvaWQsXHJcbiAgICAgICAgb25FcnJvcjogKG1lc3NhZ2U6IHN0cmluZykgPT4gdm9pZFxyXG4gICAgKTogdm9pZCB7XHJcbiAgICAgICAgR0xURkxvYWRlckV4dGVuc2lvbi5fQXBwbHlFeHRlbnNpb25zKFxyXG4gICAgICAgICAgICAobG9hZGVyRXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbG9hZGVyRXh0ZW5zaW9uLmxvYWRUZXh0dXJlQnVmZmVyQXN5bmMoZ2x0ZlJ1bnRpbWUsIGlkLCBvblN1Y2Nlc3MsIG9uRXJyb3IpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBHTFRGTG9hZGVyQmFzZS5Mb2FkVGV4dHVyZUJ1ZmZlckFzeW5jKGdsdGZSdW50aW1lLCBpZCwgb25TdWNjZXNzLCBvbkVycm9yKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdGF0aWMgX0NyZWF0ZVRleHR1cmVBc3luYyhcclxuICAgICAgICBnbHRmUnVudGltZTogSUdMVEZSdW50aW1lLFxyXG4gICAgICAgIGlkOiBzdHJpbmcsXHJcbiAgICAgICAgYnVmZmVyOiBBcnJheUJ1ZmZlclZpZXcsXHJcbiAgICAgICAgb25TdWNjZXNzOiAodGV4dHVyZTogVGV4dHVyZSkgPT4gdm9pZCxcclxuICAgICAgICBvbkVycm9yOiAobWVzc2FnZTogc3RyaW5nKSA9PiB2b2lkXHJcbiAgICApOiB2b2lkIHtcclxuICAgICAgICBHTFRGTG9hZGVyRXh0ZW5zaW9uLl9BcHBseUV4dGVuc2lvbnMoXHJcbiAgICAgICAgICAgIChsb2FkZXJFeHRlbnNpb24pID0+IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBsb2FkZXJFeHRlbnNpb24uY3JlYXRlVGV4dHVyZUFzeW5jKGdsdGZSdW50aW1lLCBpZCwgYnVmZmVyLCBvblN1Y2Nlc3MsIG9uRXJyb3IpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBHTFRGTG9hZGVyQmFzZS5DcmVhdGVUZXh0dXJlQXN5bmMoZ2x0ZlJ1bnRpbWUsIGlkLCBidWZmZXIsIG9uU3VjY2Vzcyk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIF9BcHBseUV4dGVuc2lvbnMoZnVuYzogKGxvYWRlckV4dGVuc2lvbjogR0xURkxvYWRlckV4dGVuc2lvbikgPT4gYm9vbGVhbiwgZGVmYXVsdEZ1bmM6ICgpID0+IHZvaWQpOiB2b2lkIHtcclxuICAgICAgICBmb3IgKGNvbnN0IGV4dGVuc2lvbk5hbWUgaW4gR0xURkxvYWRlci5FeHRlbnNpb25zKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGxvYWRlckV4dGVuc2lvbiA9IEdMVEZMb2FkZXIuRXh0ZW5zaW9uc1tleHRlbnNpb25OYW1lXTtcclxuICAgICAgICAgICAgaWYgKGZ1bmMobG9hZGVyRXh0ZW5zaW9uKSkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBkZWZhdWx0RnVuYygpO1xyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGRmlsZUxvYWRlci5fQ3JlYXRlR0xURjFMb2FkZXIgPSAoKSA9PiBuZXcgR0xURkxvYWRlcigpO1xyXG4iLCJpbXBvcnQgdHlwZSB7IEFzc2V0Q29udGFpbmVyIH0gZnJvbSBcImNvcmUvYXNzZXRDb250YWluZXJcIjtcclxuaW1wb3J0IHR5cGUgeyBCb25lIH0gZnJvbSBcImNvcmUvQm9uZXMvYm9uZVwiO1xyXG5pbXBvcnQgdHlwZSB7IFNrZWxldG9uIH0gZnJvbSBcImNvcmUvQm9uZXMvc2tlbGV0b25cIjtcclxuaW1wb3J0IHR5cGUgeyBUZXh0dXJlIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL1RleHR1cmVzL3RleHR1cmVcIjtcclxuaW1wb3J0IHR5cGUgeyBOb2RlIH0gZnJvbSBcImNvcmUvbm9kZVwiO1xyXG5pbXBvcnQgdHlwZSB7IFNjZW5lIH0gZnJvbSBcImNvcmUvc2NlbmVcIjtcclxuaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcblxyXG4vKipcclxuICogRW51bXNcclxuICogQGludGVybmFsXHJcbiAqL1xyXG5leHBvcnQgZW51bSBFQ29tcG9uZW50VHlwZSB7XHJcbiAgICBCWVRFID0gNTEyMCxcclxuICAgIFVOU0lHTkVEX0JZVEUgPSA1MTIxLFxyXG4gICAgU0hPUlQgPSA1MTIyLFxyXG4gICAgVU5TSUdORURfU0hPUlQgPSA1MTIzLFxyXG4gICAgRkxPQVQgPSA1MTI2LFxyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBlbnVtIEVTaGFkZXJUeXBlIHtcclxuICAgIEZSQUdNRU5UID0gMzU2MzIsXHJcbiAgICBWRVJURVggPSAzNTYzMyxcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgZW51bSBFUGFyYW1ldGVyVHlwZSB7XHJcbiAgICBCWVRFID0gNTEyMCxcclxuICAgIFVOU0lHTkVEX0JZVEUgPSA1MTIxLFxyXG4gICAgU0hPUlQgPSA1MTIyLFxyXG4gICAgVU5TSUdORURfU0hPUlQgPSA1MTIzLFxyXG4gICAgSU5UID0gNTEyNCxcclxuICAgIFVOU0lHTkVEX0lOVCA9IDUxMjUsXHJcbiAgICBGTE9BVCA9IDUxMjYsXHJcbiAgICBGTE9BVF9WRUMyID0gMzU2NjQsXHJcbiAgICBGTE9BVF9WRUMzID0gMzU2NjUsXHJcbiAgICBGTE9BVF9WRUM0ID0gMzU2NjYsXHJcbiAgICBJTlRfVkVDMiA9IDM1NjY3LFxyXG4gICAgSU5UX1ZFQzMgPSAzNTY2OCxcclxuICAgIElOVF9WRUM0ID0gMzU2NjksXHJcbiAgICBCT09MID0gMzU2NzAsXHJcbiAgICBCT09MX1ZFQzIgPSAzNTY3MSxcclxuICAgIEJPT0xfVkVDMyA9IDM1NjcyLFxyXG4gICAgQk9PTF9WRUM0ID0gMzU2NzMsXHJcbiAgICBGTE9BVF9NQVQyID0gMzU2NzQsXHJcbiAgICBGTE9BVF9NQVQzID0gMzU2NzUsXHJcbiAgICBGTE9BVF9NQVQ0ID0gMzU2NzYsXHJcbiAgICBTQU1QTEVSXzJEID0gMzU2NzgsXHJcbn1cclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGVudW0gRVRleHR1cmVXcmFwTW9kZSB7XHJcbiAgICBDTEFNUF9UT19FREdFID0gMzMwNzEsXHJcbiAgICBNSVJST1JFRF9SRVBFQVQgPSAzMzY0OCxcclxuICAgIFJFUEVBVCA9IDEwNDk3LFxyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBlbnVtIEVUZXh0dXJlRmlsdGVyVHlwZSB7XHJcbiAgICBORUFSRVNUID0gOTcyOCxcclxuICAgIExJTkVBUiA9IDk3MjgsXHJcbiAgICBORUFSRVNUX01JUE1BUF9ORUFSRVNUID0gOTk4NCxcclxuICAgIExJTkVBUl9NSVBNQVBfTkVBUkVTVCA9IDk5ODUsXHJcbiAgICBORUFSRVNUX01JUE1BUF9MSU5FQVIgPSA5OTg2LFxyXG4gICAgTElORUFSX01JUE1BUF9MSU5FQVIgPSA5OTg3LFxyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBlbnVtIEVUZXh0dXJlRm9ybWF0IHtcclxuICAgIEFMUEhBID0gNjQwNixcclxuICAgIFJHQiA9IDY0MDcsXHJcbiAgICBSR0JBID0gNjQwOCxcclxuICAgIExVTUlOQU5DRSA9IDY0MDksXHJcbiAgICBMVU1JTkFOQ0VfQUxQSEEgPSA2NDEwLFxyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBlbnVtIEVDdWxsaW5nVHlwZSB7XHJcbiAgICBGUk9OVCA9IDEwMjgsXHJcbiAgICBCQUNLID0gMTAyOSxcclxuICAgIEZST05UX0FORF9CQUNLID0gMTAzMixcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgZW51bSBFQmxlbmRpbmdGdW5jdGlvbiB7XHJcbiAgICBaRVJPID0gMCxcclxuICAgIE9ORSA9IDEsXHJcbiAgICBTUkNfQ09MT1IgPSA3NjgsXHJcbiAgICBPTkVfTUlOVVNfU1JDX0NPTE9SID0gNzY5LFxyXG4gICAgRFNUX0NPTE9SID0gNzc0LFxyXG4gICAgT05FX01JTlVTX0RTVF9DT0xPUiA9IDc3NSxcclxuICAgIFNSQ19BTFBIQSA9IDc3MCxcclxuICAgIE9ORV9NSU5VU19TUkNfQUxQSEEgPSA3NzEsXHJcbiAgICBEU1RfQUxQSEEgPSA3NzIsXHJcbiAgICBPTkVfTUlOVVNfRFNUX0FMUEhBID0gNzczLFxyXG4gICAgQ09OU1RBTlRfQ09MT1IgPSAzMjc2OSxcclxuICAgIE9ORV9NSU5VU19DT05TVEFOVF9DT0xPUiA9IDMyNzcwLFxyXG4gICAgQ09OU1RBTlRfQUxQSEEgPSAzMjc3MSxcclxuICAgIE9ORV9NSU5VU19DT05TVEFOVF9BTFBIQSA9IDMyNzcyLFxyXG4gICAgU1JDX0FMUEhBX1NBVFVSQVRFID0gNzc2LFxyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZQcm9wZXJ0eSB7XHJcbiAgICBleHRlbnNpb25zPzogeyBba2V5OiBzdHJpbmddOiBhbnkgfTtcclxuICAgIGV4dHJhcz86IE9iamVjdDtcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGQ2hpbGRSb290UHJvcGVydHkgZXh0ZW5kcyBJR0xURlByb3BlcnR5IHtcclxuICAgIG5hbWU/OiBzdHJpbmc7XHJcbn1cclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGludGVyZmFjZSBJR0xURkFjY2Vzc29yIGV4dGVuZHMgSUdMVEZDaGlsZFJvb3RQcm9wZXJ0eSB7XHJcbiAgICBidWZmZXJWaWV3OiBzdHJpbmc7XHJcbiAgICBieXRlT2Zmc2V0OiBudW1iZXI7XHJcbiAgICBieXRlU3RyaWRlOiBudW1iZXI7XHJcbiAgICBjb3VudDogbnVtYmVyO1xyXG4gICAgdHlwZTogc3RyaW5nO1xyXG4gICAgY29tcG9uZW50VHlwZTogRUNvbXBvbmVudFR5cGU7XHJcblxyXG4gICAgbWF4PzogbnVtYmVyW107XHJcbiAgICBtaW4/OiBudW1iZXJbXTtcclxuICAgIG5hbWU/OiBzdHJpbmc7XHJcbn1cclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGludGVyZmFjZSBJR0xURkJ1ZmZlclZpZXcgZXh0ZW5kcyBJR0xURkNoaWxkUm9vdFByb3BlcnR5IHtcclxuICAgIGJ1ZmZlcjogc3RyaW5nO1xyXG4gICAgYnl0ZU9mZnNldDogbnVtYmVyO1xyXG4gICAgYnl0ZUxlbmd0aDogbnVtYmVyO1xyXG4gICAgYnl0ZVN0cmlkZTogbnVtYmVyO1xyXG5cclxuICAgIHRhcmdldD86IG51bWJlcjtcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGQnVmZmVyIGV4dGVuZHMgSUdMVEZDaGlsZFJvb3RQcm9wZXJ0eSB7XHJcbiAgICB1cmk6IHN0cmluZztcclxuXHJcbiAgICBieXRlTGVuZ3RoPzogbnVtYmVyO1xyXG4gICAgdHlwZT86IHN0cmluZztcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGU2hhZGVyIGV4dGVuZHMgSUdMVEZDaGlsZFJvb3RQcm9wZXJ0eSB7XHJcbiAgICB1cmk6IHN0cmluZztcclxuICAgIHR5cGU6IEVTaGFkZXJUeXBlO1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZQcm9ncmFtIGV4dGVuZHMgSUdMVEZDaGlsZFJvb3RQcm9wZXJ0eSB7XHJcbiAgICBhdHRyaWJ1dGVzOiBzdHJpbmdbXTtcclxuICAgIGZyYWdtZW50U2hhZGVyOiBzdHJpbmc7XHJcbiAgICB2ZXJ0ZXhTaGFkZXI6IHN0cmluZztcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGVGVjaG5pcXVlUGFyYW1ldGVyIHtcclxuICAgIHR5cGU6IG51bWJlcjtcclxuXHJcbiAgICBjb3VudD86IG51bWJlcjtcclxuICAgIHNlbWFudGljPzogc3RyaW5nO1xyXG4gICAgbm9kZT86IHN0cmluZztcclxuICAgIHZhbHVlPzogbnVtYmVyIHwgYm9vbGVhbiB8IHN0cmluZyB8IEFycmF5PGFueT47XHJcbiAgICBzb3VyY2U/OiBzdHJpbmc7XHJcblxyXG4gICAgYmFieWxvblZhbHVlPzogYW55O1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZUZWNobmlxdWVDb21tb25Qcm9maWxlIHtcclxuICAgIGxpZ2h0aW5nTW9kZWw6IHN0cmluZztcclxuICAgIHRleGNvb3JkQmluZGluZ3M6IE9iamVjdDtcclxuXHJcbiAgICBwYXJhbWV0ZXJzPzogQXJyYXk8YW55PjtcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGVGVjaG5pcXVlU3RhdGVzRnVuY3Rpb25zIHtcclxuICAgIGJsZW5kQ29sb3I/OiBudW1iZXJbXTtcclxuICAgIGJsZW5kRXF1YXRpb25TZXBhcmF0ZT86IG51bWJlcltdO1xyXG4gICAgYmxlbmRGdW5jU2VwYXJhdGU/OiBudW1iZXJbXTtcclxuICAgIGNvbG9yTWFzazogYm9vbGVhbltdO1xyXG4gICAgY3VsbEZhY2U6IG51bWJlcltdO1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZUZWNobmlxdWVTdGF0ZXMge1xyXG4gICAgZW5hYmxlOiBudW1iZXJbXTtcclxuICAgIGZ1bmN0aW9uczogSUdMVEZUZWNobmlxdWVTdGF0ZXNGdW5jdGlvbnM7XHJcbn1cclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGludGVyZmFjZSBJR0xURlRlY2huaXF1ZSBleHRlbmRzIElHTFRGQ2hpbGRSb290UHJvcGVydHkge1xyXG4gICAgcGFyYW1ldGVyczogeyBba2V5OiBzdHJpbmddOiBJR0xURlRlY2huaXF1ZVBhcmFtZXRlciB9O1xyXG4gICAgcHJvZ3JhbTogc3RyaW5nO1xyXG5cclxuICAgIGF0dHJpYnV0ZXM6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH07XHJcbiAgICB1bmlmb3JtczogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfTtcclxuICAgIHN0YXRlczogSUdMVEZUZWNobmlxdWVTdGF0ZXM7XHJcbn1cclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGludGVyZmFjZSBJR0xURk1hdGVyaWFsIGV4dGVuZHMgSUdMVEZDaGlsZFJvb3RQcm9wZXJ0eSB7XHJcbiAgICB0ZWNobmlxdWU/OiBzdHJpbmc7XHJcbiAgICB2YWx1ZXM6IHN0cmluZ1tdO1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZNZXNoUHJpbWl0aXZlIGV4dGVuZHMgSUdMVEZQcm9wZXJ0eSB7XHJcbiAgICBhdHRyaWJ1dGVzOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xyXG4gICAgaW5kaWNlczogc3RyaW5nO1xyXG4gICAgbWF0ZXJpYWw6IHN0cmluZztcclxuXHJcbiAgICBtb2RlPzogbnVtYmVyO1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZNZXNoIGV4dGVuZHMgSUdMVEZDaGlsZFJvb3RQcm9wZXJ0eSB7XHJcbiAgICBwcmltaXRpdmVzOiBJR0xURk1lc2hQcmltaXRpdmVbXTtcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGSW1hZ2UgZXh0ZW5kcyBJR0xURkNoaWxkUm9vdFByb3BlcnR5IHtcclxuICAgIHVyaTogc3RyaW5nO1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZTYW1wbGVyIGV4dGVuZHMgSUdMVEZDaGlsZFJvb3RQcm9wZXJ0eSB7XHJcbiAgICBtYWdGaWx0ZXI/OiBudW1iZXI7XHJcbiAgICBtaW5GaWx0ZXI/OiBudW1iZXI7XHJcbiAgICB3cmFwUz86IG51bWJlcjtcclxuICAgIHdyYXBUPzogbnVtYmVyO1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZUZXh0dXJlIGV4dGVuZHMgSUdMVEZDaGlsZFJvb3RQcm9wZXJ0eSB7XHJcbiAgICBzYW1wbGVyOiBzdHJpbmc7XHJcbiAgICBzb3VyY2U6IHN0cmluZztcclxuXHJcbiAgICBmb3JtYXQ/OiBFVGV4dHVyZUZvcm1hdDtcclxuICAgIGludGVybmFsRm9ybWF0PzogRVRleHR1cmVGb3JtYXQ7XHJcbiAgICB0YXJnZXQ/OiBudW1iZXI7XHJcbiAgICB0eXBlPzogbnVtYmVyO1xyXG5cclxuICAgIC8vIEJhYnlsb24uanMgdmFsdWVzIChvcHRpbWl6ZSlcclxuICAgIGJhYnlsb25UZXh0dXJlPzogVGV4dHVyZTtcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGQW1iaWVuTGlnaHQge1xyXG4gICAgY29sb3I/OiBudW1iZXJbXTtcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGRGlyZWN0aW9uYWxMaWdodCB7XHJcbiAgICBjb2xvcj86IG51bWJlcltdO1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZQb2ludExpZ2h0IHtcclxuICAgIGNvbG9yPzogbnVtYmVyW107XHJcbiAgICBjb25zdGFudEF0dGVudWF0aW9uPzogbnVtYmVyO1xyXG4gICAgbGluZWFyQXR0ZW51YXRpb24/OiBudW1iZXI7XHJcbiAgICBxdWFkcmF0aWNBdHRlbnVhdGlvbj86IG51bWJlcjtcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGU3BvdExpZ2h0IHtcclxuICAgIGNvbG9yPzogbnVtYmVyW107XHJcbiAgICBjb25zdGFudEF0dGVudWF0aW9uPzogbnVtYmVyO1xyXG4gICAgZmFsbE9mQW5nbGU/OiBudW1iZXI7XHJcbiAgICBmYWxsT2ZmRXhwb25lbnQ/OiBudW1iZXI7XHJcbiAgICBsaW5lYXJBdHRlbnVhdGlvbj86IG51bWJlcjtcclxuICAgIHF1YWRyYXRpY0F0dGVudWF0aW9uPzogbnVtYmVyO1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZMaWdodCBleHRlbmRzIElHTFRGQ2hpbGRSb290UHJvcGVydHkge1xyXG4gICAgdHlwZTogc3RyaW5nO1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZDYW1lcmFPcnRob2dyYXBoaWMge1xyXG4gICAgeG1hZzogbnVtYmVyO1xyXG4gICAgeW1hZzogbnVtYmVyO1xyXG4gICAgemZhcjogbnVtYmVyO1xyXG4gICAgem5lYXI6IG51bWJlcjtcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGQ2FtZXJhUGVyc3BlY3RpdmUge1xyXG4gICAgYXNwZWN0UmF0aW86IG51bWJlcjtcclxuICAgIHlmb3Y6IG51bWJlcjtcclxuICAgIHpmYXI6IG51bWJlcjtcclxuICAgIHpuZWFyOiBudW1iZXI7XHJcbn1cclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGludGVyZmFjZSBJR0xURkNhbWVyYSBleHRlbmRzIElHTFRGQ2hpbGRSb290UHJvcGVydHkge1xyXG4gICAgdHlwZTogc3RyaW5nO1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZBbmltYXRpb25DaGFubmVsVGFyZ2V0IHtcclxuICAgIGlkOiBzdHJpbmc7XHJcbiAgICBwYXRoOiBzdHJpbmc7XHJcbn1cclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGludGVyZmFjZSBJR0xURkFuaW1hdGlvbkNoYW5uZWwge1xyXG4gICAgc2FtcGxlcjogc3RyaW5nO1xyXG4gICAgdGFyZ2V0OiBJR0xURkFuaW1hdGlvbkNoYW5uZWxUYXJnZXQ7XHJcbn1cclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGludGVyZmFjZSBJR0xURkFuaW1hdGlvblNhbXBsZXIge1xyXG4gICAgaW5wdXQ6IHN0cmluZztcclxuICAgIG91dHB1dDogc3RyaW5nO1xyXG5cclxuICAgIGludGVycG9sYXRpb24/OiBzdHJpbmc7XHJcbn1cclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGludGVyZmFjZSBJR0xURkFuaW1hdGlvbiBleHRlbmRzIElHTFRGQ2hpbGRSb290UHJvcGVydHkge1xyXG4gICAgY2hhbm5lbHM/OiBJR0xURkFuaW1hdGlvbkNoYW5uZWxbXTtcclxuICAgIHBhcmFtZXRlcnM/OiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9O1xyXG4gICAgc2FtcGxlcnM/OiB7IFtrZXk6IHN0cmluZ106IElHTFRGQW5pbWF0aW9uU2FtcGxlciB9O1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZOb2RlSW5zdGFuY2VTa2luIHtcclxuICAgIHNrZWxldG9uczogc3RyaW5nW107XHJcbiAgICBza2luOiBzdHJpbmc7XHJcbiAgICBtZXNoZXM6IHN0cmluZ1tdO1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZTa2lucyBleHRlbmRzIElHTFRGQ2hpbGRSb290UHJvcGVydHkge1xyXG4gICAgYmluZFNoYXBlTWF0cml4OiBudW1iZXJbXTtcclxuICAgIGludmVyc2VCaW5kTWF0cmljZXM6IHN0cmluZztcclxuICAgIGpvaW50TmFtZXM6IHN0cmluZ1tdO1xyXG5cclxuICAgIGJhYnlsb25Ta2VsZXRvbj86IFNrZWxldG9uO1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUdMVEZOb2RlIGV4dGVuZHMgSUdMVEZDaGlsZFJvb3RQcm9wZXJ0eSB7XHJcbiAgICBjYW1lcmE/OiBzdHJpbmc7XHJcbiAgICBjaGlsZHJlbjogc3RyaW5nW107XHJcbiAgICBza2luPzogc3RyaW5nO1xyXG4gICAgam9pbnROYW1lPzogc3RyaW5nO1xyXG4gICAgbGlnaHQ/OiBzdHJpbmc7XHJcbiAgICBtYXRyaXg6IG51bWJlcltdO1xyXG4gICAgbWVzaD86IHN0cmluZztcclxuICAgIG1lc2hlcz86IHN0cmluZ1tdO1xyXG4gICAgcm90YXRpb24/OiBudW1iZXJbXTtcclxuICAgIHNjYWxlPzogbnVtYmVyW107XHJcbiAgICB0cmFuc2xhdGlvbj86IG51bWJlcltdO1xyXG5cclxuICAgIC8vIEJhYnlsb24uanMgdmFsdWVzIChvcHRpbWl6ZSlcclxuICAgIGJhYnlsb25Ob2RlPzogTm9kZTtcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGU2NlbmUgZXh0ZW5kcyBJR0xURkNoaWxkUm9vdFByb3BlcnR5IHtcclxuICAgIG5vZGVzOiBzdHJpbmdbXTtcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGUnVudGltZSB7XHJcbiAgICBleHRlbnNpb25zOiB7IFtrZXk6IHN0cmluZ106IGFueSB9O1xyXG4gICAgYWNjZXNzb3JzOiB7IFtrZXk6IHN0cmluZ106IElHTFRGQWNjZXNzb3IgfTtcclxuICAgIGJ1ZmZlcnM6IHsgW2tleTogc3RyaW5nXTogSUdMVEZCdWZmZXIgfTtcclxuICAgIGJ1ZmZlclZpZXdzOiB7IFtrZXk6IHN0cmluZ106IElHTFRGQnVmZmVyVmlldyB9O1xyXG4gICAgbWVzaGVzOiB7IFtrZXk6IHN0cmluZ106IElHTFRGTWVzaCB9O1xyXG4gICAgbGlnaHRzOiB7IFtrZXk6IHN0cmluZ106IElHTFRGTGlnaHQgfTtcclxuICAgIGNhbWVyYXM6IHsgW2tleTogc3RyaW5nXTogSUdMVEZDYW1lcmEgfTtcclxuICAgIG5vZGVzOiB7IFtrZXk6IHN0cmluZ106IElHTFRGTm9kZSB9O1xyXG4gICAgaW1hZ2VzOiB7IFtrZXk6IHN0cmluZ106IElHTFRGSW1hZ2UgfTtcclxuICAgIHRleHR1cmVzOiB7IFtrZXk6IHN0cmluZ106IElHTFRGVGV4dHVyZSB9O1xyXG4gICAgc2hhZGVyczogeyBba2V5OiBzdHJpbmddOiBJR0xURlNoYWRlciB9O1xyXG4gICAgcHJvZ3JhbXM6IHsgW2tleTogc3RyaW5nXTogSUdMVEZQcm9ncmFtIH07XHJcbiAgICBzYW1wbGVyczogeyBba2V5OiBzdHJpbmddOiBJR0xURlNhbXBsZXIgfTtcclxuICAgIHRlY2huaXF1ZXM6IHsgW2tleTogc3RyaW5nXTogSUdMVEZUZWNobmlxdWUgfTtcclxuICAgIG1hdGVyaWFsczogeyBba2V5OiBzdHJpbmddOiBJR0xURk1hdGVyaWFsIH07XHJcbiAgICBhbmltYXRpb25zOiB7IFtrZXk6IHN0cmluZ106IElHTFRGQW5pbWF0aW9uIH07XHJcbiAgICBza2luczogeyBba2V5OiBzdHJpbmddOiBJR0xURlNraW5zIH07XHJcblxyXG4gICAgY3VycmVudFNjZW5lPzogT2JqZWN0O1xyXG4gICAgc2NlbmVzOiB7IFtrZXk6IHN0cmluZ106IElHTFRGU2NlbmUgfTsgLy8gdjEuMVxyXG5cclxuICAgIGV4dGVuc2lvbnNVc2VkOiBzdHJpbmdbXTtcclxuICAgIGV4dGVuc2lvbnNSZXF1aXJlZD86IHN0cmluZ1tdOyAvLyB2MS4xXHJcblxyXG4gICAgYnVmZmVyc0NvdW50OiBudW1iZXI7XHJcbiAgICBzaGFkZXJzY291bnQ6IG51bWJlcjtcclxuXHJcbiAgICBzY2VuZTogU2NlbmU7XHJcbiAgICByb290VXJsOiBzdHJpbmc7XHJcblxyXG4gICAgbG9hZGVkQnVmZmVyQ291bnQ6IG51bWJlcjtcclxuICAgIGxvYWRlZEJ1ZmZlclZpZXdzOiB7IFtuYW1lOiBzdHJpbmddOiBBcnJheUJ1ZmZlclZpZXcgfTtcclxuXHJcbiAgICBsb2FkZWRTaGFkZXJDb3VudDogbnVtYmVyO1xyXG5cclxuICAgIGltcG9ydE9ubHlNZXNoZXM6IGJvb2xlYW47XHJcbiAgICBpbXBvcnRNZXNoZXNOYW1lcz86IHN0cmluZ1tdO1xyXG5cclxuICAgIGR1bW15Tm9kZXM6IE5vZGVbXTtcclxuXHJcbiAgICBhc3NldENvbnRhaW5lcjogTnVsbGFibGU8QXNzZXRDb250YWluZXI+O1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSU5vZGVUb1Jvb3Qge1xyXG4gICAgYm9uZTogQm9uZTtcclxuICAgIG5vZGU6IElHTFRGTm9kZTtcclxuICAgIGlkOiBzdHJpbmc7XHJcbn1cclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGludGVyZmFjZSBJSm9pbnROb2RlIHtcclxuICAgIG5vZGU6IElHTFRGTm9kZTtcclxuICAgIGlkOiBzdHJpbmc7XHJcbn1cclxuIiwiaW1wb3J0IHR5cGUgeyBJR0xURlRlY2huaXF1ZVBhcmFtZXRlciwgSUdMVEZBY2Nlc3NvciwgSUdMVEZSdW50aW1lLCBJR0xURkJ1ZmZlclZpZXcgfSBmcm9tIFwiLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgeyBFUGFyYW1ldGVyVHlwZSwgRVRleHR1cmVXcmFwTW9kZSwgRVRleHR1cmVGaWx0ZXJUeXBlLCBFQ29tcG9uZW50VHlwZSB9IGZyb20gXCIuL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcblxyXG5pbXBvcnQgdHlwZSB7IE51bGxhYmxlIH0gZnJvbSBcImNvcmUvdHlwZXNcIjtcclxuaW1wb3J0IHsgVmVjdG9yMiwgVmVjdG9yMywgVmVjdG9yNCwgTWF0cml4IH0gZnJvbSBcImNvcmUvTWF0aHMvbWF0aC52ZWN0b3JcIjtcclxuaW1wb3J0IHsgQ29sb3I0IH0gZnJvbSBcImNvcmUvTWF0aHMvbWF0aC5jb2xvclwiO1xyXG5pbXBvcnQgeyBFZmZlY3QgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvZWZmZWN0XCI7XHJcbmltcG9ydCB7IFNoYWRlck1hdGVyaWFsIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL3NoYWRlck1hdGVyaWFsXCI7XHJcbmltcG9ydCB7IFRleHR1cmUgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvVGV4dHVyZXMvdGV4dHVyZVwiO1xyXG5pbXBvcnQgdHlwZSB7IE5vZGUgfSBmcm9tIFwiY29yZS9ub2RlXCI7XHJcbmltcG9ydCB0eXBlIHsgU2NlbmUgfSBmcm9tIFwiY29yZS9zY2VuZVwiO1xyXG5cclxuLyoqXHJcbiAqIFV0aWxzIGZ1bmN0aW9ucyBmb3IgR0xURlxyXG4gKiBAaW50ZXJuYWxcclxuICogQGRlcHJlY2F0ZWRcclxuICovXHJcbmV4cG9ydCBjbGFzcyBHTFRGVXRpbHMge1xyXG4gICAgLyoqXHJcbiAgICAgKiBTZXRzIHRoZSBnaXZlbiBcInBhcmFtZXRlclwiIG1hdHJpeFxyXG4gICAgICogQHBhcmFtIHNjZW5lIHRoZSBTY2VuZSBvYmplY3RcclxuICAgICAqIEBwYXJhbSBzb3VyY2UgdGhlIHNvdXJjZSBub2RlIHdoZXJlIHRvIHBpY2sgdGhlIG1hdHJpeFxyXG4gICAgICogQHBhcmFtIHBhcmFtZXRlciB0aGUgR0xURiB0ZWNobmlxdWUgcGFyYW1ldGVyXHJcbiAgICAgKiBAcGFyYW0gdW5pZm9ybU5hbWUgdGhlIG5hbWUgb2YgdGhlIHNoYWRlcidzIHVuaWZvcm1cclxuICAgICAqIEBwYXJhbSBzaGFkZXJNYXRlcmlhbCB0aGUgc2hhZGVyIG1hdGVyaWFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgU2V0TWF0cml4KHNjZW5lOiBTY2VuZSwgc291cmNlOiBOb2RlLCBwYXJhbWV0ZXI6IElHTFRGVGVjaG5pcXVlUGFyYW1ldGVyLCB1bmlmb3JtTmFtZTogc3RyaW5nLCBzaGFkZXJNYXRlcmlhbDogU2hhZGVyTWF0ZXJpYWwgfCBFZmZlY3QpOiB2b2lkIHtcclxuICAgICAgICBsZXQgbWF0OiBOdWxsYWJsZTxNYXRyaXg+ID0gbnVsbDtcclxuXHJcbiAgICAgICAgaWYgKHBhcmFtZXRlci5zZW1hbnRpYyA9PT0gXCJNT0RFTFwiKSB7XHJcbiAgICAgICAgICAgIG1hdCA9IHNvdXJjZS5nZXRXb3JsZE1hdHJpeCgpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAocGFyYW1ldGVyLnNlbWFudGljID09PSBcIlBST0pFQ1RJT05cIikge1xyXG4gICAgICAgICAgICBtYXQgPSBzY2VuZS5nZXRQcm9qZWN0aW9uTWF0cml4KCk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbWV0ZXIuc2VtYW50aWMgPT09IFwiVklFV1wiKSB7XHJcbiAgICAgICAgICAgIG1hdCA9IHNjZW5lLmdldFZpZXdNYXRyaXgoKTtcclxuICAgICAgICB9IGVsc2UgaWYgKHBhcmFtZXRlci5zZW1hbnRpYyA9PT0gXCJNT0RFTFZJRVdJTlZFUlNFVFJBTlNQT1NFXCIpIHtcclxuICAgICAgICAgICAgbWF0ID0gTWF0cml4LlRyYW5zcG9zZShzb3VyY2UuZ2V0V29ybGRNYXRyaXgoKS5tdWx0aXBseShzY2VuZS5nZXRWaWV3TWF0cml4KCkpLmludmVydCgpKTtcclxuICAgICAgICB9IGVsc2UgaWYgKHBhcmFtZXRlci5zZW1hbnRpYyA9PT0gXCJNT0RFTFZJRVdcIikge1xyXG4gICAgICAgICAgICBtYXQgPSBzb3VyY2UuZ2V0V29ybGRNYXRyaXgoKS5tdWx0aXBseShzY2VuZS5nZXRWaWV3TWF0cml4KCkpO1xyXG4gICAgICAgIH0gZWxzZSBpZiAocGFyYW1ldGVyLnNlbWFudGljID09PSBcIk1PREVMVklFV1BST0pFQ1RJT05cIikge1xyXG4gICAgICAgICAgICBtYXQgPSBzb3VyY2UuZ2V0V29ybGRNYXRyaXgoKS5tdWx0aXBseShzY2VuZS5nZXRUcmFuc2Zvcm1NYXRyaXgoKSk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbWV0ZXIuc2VtYW50aWMgPT09IFwiTU9ERUxJTlZFUlNFXCIpIHtcclxuICAgICAgICAgICAgbWF0ID0gc291cmNlLmdldFdvcmxkTWF0cml4KCkuaW52ZXJ0KCk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbWV0ZXIuc2VtYW50aWMgPT09IFwiVklFV0lOVkVSU0VcIikge1xyXG4gICAgICAgICAgICBtYXQgPSBzY2VuZS5nZXRWaWV3TWF0cml4KCkuaW52ZXJ0KCk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbWV0ZXIuc2VtYW50aWMgPT09IFwiUFJPSkVDVElPTklOVkVSU0VcIikge1xyXG4gICAgICAgICAgICBtYXQgPSBzY2VuZS5nZXRQcm9qZWN0aW9uTWF0cml4KCkuaW52ZXJ0KCk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbWV0ZXIuc2VtYW50aWMgPT09IFwiTU9ERUxWSUVXSU5WRVJTRVwiKSB7XHJcbiAgICAgICAgICAgIG1hdCA9IHNvdXJjZS5nZXRXb3JsZE1hdHJpeCgpLm11bHRpcGx5KHNjZW5lLmdldFZpZXdNYXRyaXgoKSkuaW52ZXJ0KCk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbWV0ZXIuc2VtYW50aWMgPT09IFwiTU9ERUxWSUVXUFJPSkVDVElPTklOVkVSU0VcIikge1xyXG4gICAgICAgICAgICBtYXQgPSBzb3VyY2UuZ2V0V29ybGRNYXRyaXgoKS5tdWx0aXBseShzY2VuZS5nZXRUcmFuc2Zvcm1NYXRyaXgoKSkuaW52ZXJ0KCk7XHJcbiAgICAgICAgfSBlbHNlIGlmIChwYXJhbWV0ZXIuc2VtYW50aWMgPT09IFwiTU9ERUxJTlZFUlNFVFJBTlNQT1NFXCIpIHtcclxuICAgICAgICAgICAgbWF0ID0gTWF0cml4LlRyYW5zcG9zZShzb3VyY2UuZ2V0V29ybGRNYXRyaXgoKS5pbnZlcnQoKSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAobWF0KSB7XHJcbiAgICAgICAgICAgIHN3aXRjaCAocGFyYW1ldGVyLnR5cGUpIHtcclxuICAgICAgICAgICAgICAgIGNhc2UgRVBhcmFtZXRlclR5cGUuRkxPQVRfTUFUMjpcclxuICAgICAgICAgICAgICAgICAgICBzaGFkZXJNYXRlcmlhbC5zZXRNYXRyaXgyeDIodW5pZm9ybU5hbWUsIE1hdHJpeC5HZXRBc01hdHJpeDJ4MihtYXQpKTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgRVBhcmFtZXRlclR5cGUuRkxPQVRfTUFUMzpcclxuICAgICAgICAgICAgICAgICAgICBzaGFkZXJNYXRlcmlhbC5zZXRNYXRyaXgzeDModW5pZm9ybU5hbWUsIE1hdHJpeC5HZXRBc01hdHJpeDN4MyhtYXQpKTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIGNhc2UgRVBhcmFtZXRlclR5cGUuRkxPQVRfTUFUNDpcclxuICAgICAgICAgICAgICAgICAgICBzaGFkZXJNYXRlcmlhbC5zZXRNYXRyaXgodW5pZm9ybU5hbWUsIG1hdCk7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2V0cyB0aGUgZ2l2ZW4gXCJwYXJhbWV0ZXJcIiBtYXRyaXhcclxuICAgICAqIEBwYXJhbSBzaGFkZXJNYXRlcmlhbCB0aGUgc2hhZGVyIG1hdGVyaWFsXHJcbiAgICAgKiBAcGFyYW0gdW5pZm9ybSB0aGUgbmFtZSBvZiB0aGUgc2hhZGVyJ3MgdW5pZm9ybVxyXG4gICAgICogQHBhcmFtIHZhbHVlIHRoZSB2YWx1ZSBvZiB0aGUgdW5pZm9ybVxyXG4gICAgICogQHBhcmFtIHR5cGUgdGhlIHVuaWZvcm0ncyB0eXBlIChFUGFyYW1ldGVyVHlwZSBGTE9BVCwgVkVDMiwgVkVDMyBvciBWRUM0KVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIFNldFVuaWZvcm0oc2hhZGVyTWF0ZXJpYWw6IFNoYWRlck1hdGVyaWFsIHwgRWZmZWN0LCB1bmlmb3JtOiBzdHJpbmcsIHZhbHVlOiBhbnksIHR5cGU6IG51bWJlcik6IGJvb2xlYW4ge1xyXG4gICAgICAgIHN3aXRjaCAodHlwZSkge1xyXG4gICAgICAgICAgICBjYXNlIEVQYXJhbWV0ZXJUeXBlLkZMT0FUOlxyXG4gICAgICAgICAgICAgICAgc2hhZGVyTWF0ZXJpYWwuc2V0RmxvYXQodW5pZm9ybSwgdmFsdWUpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgICAgIGNhc2UgRVBhcmFtZXRlclR5cGUuRkxPQVRfVkVDMjpcclxuICAgICAgICAgICAgICAgIHNoYWRlck1hdGVyaWFsLnNldFZlY3RvcjIodW5pZm9ybSwgVmVjdG9yMi5Gcm9tQXJyYXkodmFsdWUpKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgICAgICAgICBjYXNlIEVQYXJhbWV0ZXJUeXBlLkZMT0FUX1ZFQzM6XHJcbiAgICAgICAgICAgICAgICBzaGFkZXJNYXRlcmlhbC5zZXRWZWN0b3IzKHVuaWZvcm0sIFZlY3RvcjMuRnJvbUFycmF5KHZhbHVlKSk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgICAgY2FzZSBFUGFyYW1ldGVyVHlwZS5GTE9BVF9WRUM0OlxyXG4gICAgICAgICAgICAgICAgc2hhZGVyTWF0ZXJpYWwuc2V0VmVjdG9yNCh1bmlmb3JtLCBWZWN0b3I0LkZyb21BcnJheSh2YWx1ZSkpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB0aGUgd3JhcCBtb2RlIG9mIHRoZSB0ZXh0dXJlXHJcbiAgICAgKiBAcGFyYW0gbW9kZSB0aGUgbW9kZSB2YWx1ZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIEdldFdyYXBNb2RlKG1vZGU6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICAgICAgc3dpdGNoIChtb2RlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgRVRleHR1cmVXcmFwTW9kZS5DTEFNUF9UT19FREdFOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFRleHR1cmUuQ0xBTVBfQUREUkVTU01PREU7XHJcbiAgICAgICAgICAgIGNhc2UgRVRleHR1cmVXcmFwTW9kZS5NSVJST1JFRF9SRVBFQVQ6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gVGV4dHVyZS5NSVJST1JfQUREUkVTU01PREU7XHJcbiAgICAgICAgICAgIGNhc2UgRVRleHR1cmVXcmFwTW9kZS5SRVBFQVQ6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gVGV4dHVyZS5XUkFQX0FERFJFU1NNT0RFO1xyXG4gICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFRleHR1cmUuV1JBUF9BRERSRVNTTU9ERTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIHRoZSBieXRlIHN0cmlkZSBnaXZpbmcgYW4gYWNjZXNzb3JcclxuICAgICAqIEBwYXJhbSBhY2Nlc3NvciB0aGUgR0xURiBhY2Nlc3NvciBvYmpldFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIEdldEJ5dGVTdHJpZGVGcm9tVHlwZShhY2Nlc3NvcjogSUdMVEZBY2Nlc3Nvcik6IG51bWJlciB7XHJcbiAgICAgICAgLy8gTmVlZHMgdGhpcyBmdW5jdGlvbiBzaW5jZSBcImJ5dGVTdHJpZGVcIiBpc24ndCByZXF1aWVyZWQgaW4gZ2xURiBmb3JtYXRcclxuICAgICAgICBjb25zdCB0eXBlID0gYWNjZXNzb3IudHlwZTtcclxuXHJcbiAgICAgICAgc3dpdGNoICh0eXBlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgXCJWRUMyXCI6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gMjtcclxuICAgICAgICAgICAgY2FzZSBcIlZFQzNcIjpcclxuICAgICAgICAgICAgICAgIHJldHVybiAzO1xyXG4gICAgICAgICAgICBjYXNlIFwiVkVDNFwiOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIDQ7XHJcbiAgICAgICAgICAgIGNhc2UgXCJNQVQyXCI6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gNDtcclxuICAgICAgICAgICAgY2FzZSBcIk1BVDNcIjpcclxuICAgICAgICAgICAgICAgIHJldHVybiA5O1xyXG4gICAgICAgICAgICBjYXNlIFwiTUFUNFwiOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIDE2O1xyXG4gICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIDE7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmV0dXJucyB0aGUgdGV4dHVyZSBmaWx0ZXIgbW9kZSBnaXZpbmcgYSBtb2RlIHZhbHVlXHJcbiAgICAgKiBAcGFyYW0gbW9kZSB0aGUgZmlsdGVyIG1vZGUgdmFsdWVcclxuICAgICAqIEByZXR1cm5zIHRoZSBmaWx0ZXIgbW9kZSAoVE9ETyAtIG5lZWRzIHRvIGJlIGEgdHlwZT8pXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgR2V0VGV4dHVyZUZpbHRlck1vZGUobW9kZTogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgICAgICBzd2l0Y2ggKG1vZGUpIHtcclxuICAgICAgICAgICAgY2FzZSBFVGV4dHVyZUZpbHRlclR5cGUuTElORUFSOlxyXG4gICAgICAgICAgICBjYXNlIEVUZXh0dXJlRmlsdGVyVHlwZS5MSU5FQVJfTUlQTUFQX05FQVJFU1Q6XHJcbiAgICAgICAgICAgIGNhc2UgRVRleHR1cmVGaWx0ZXJUeXBlLkxJTkVBUl9NSVBNQVBfTElORUFSOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFRleHR1cmUuVFJJTElORUFSX1NBTVBMSU5HTU9ERTtcclxuICAgICAgICAgICAgY2FzZSBFVGV4dHVyZUZpbHRlclR5cGUuTkVBUkVTVDpcclxuICAgICAgICAgICAgY2FzZSBFVGV4dHVyZUZpbHRlclR5cGUuTkVBUkVTVF9NSVBNQVBfTkVBUkVTVDpcclxuICAgICAgICAgICAgICAgIHJldHVybiBUZXh0dXJlLk5FQVJFU1RfU0FNUExJTkdNT0RFO1xyXG4gICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFRleHR1cmUuQklMSU5FQVJfU0FNUExJTkdNT0RFO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgc3RhdGljIEdldEJ1ZmZlckZyb21CdWZmZXJWaWV3KFxyXG4gICAgICAgIGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUsXHJcbiAgICAgICAgYnVmZmVyVmlldzogSUdMVEZCdWZmZXJWaWV3LFxyXG4gICAgICAgIGJ5dGVPZmZzZXQ6IG51bWJlcixcclxuICAgICAgICBieXRlTGVuZ3RoOiBudW1iZXIsXHJcbiAgICAgICAgY29tcG9uZW50VHlwZTogRUNvbXBvbmVudFR5cGVcclxuICAgICk6IEFycmF5QnVmZmVyVmlldyB7XHJcbiAgICAgICAgYnl0ZU9mZnNldCA9IGJ1ZmZlclZpZXcuYnl0ZU9mZnNldCArIGJ5dGVPZmZzZXQ7XHJcblxyXG4gICAgICAgIGNvbnN0IGxvYWRlZEJ1ZmZlclZpZXcgPSBnbHRmUnVudGltZS5sb2FkZWRCdWZmZXJWaWV3c1tidWZmZXJWaWV3LmJ1ZmZlcl07XHJcbiAgICAgICAgaWYgKGJ5dGVPZmZzZXQgKyBieXRlTGVuZ3RoID4gbG9hZGVkQnVmZmVyVmlldy5ieXRlTGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkJ1ZmZlciBhY2Nlc3MgaXMgb3V0IG9mIHJhbmdlXCIpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgYnVmZmVyID0gbG9hZGVkQnVmZmVyVmlldy5idWZmZXI7XHJcbiAgICAgICAgYnl0ZU9mZnNldCArPSBsb2FkZWRCdWZmZXJWaWV3LmJ5dGVPZmZzZXQ7XHJcblxyXG4gICAgICAgIHN3aXRjaCAoY29tcG9uZW50VHlwZSkge1xyXG4gICAgICAgICAgICBjYXNlIEVDb21wb25lbnRUeXBlLkJZVEU6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IEludDhBcnJheShidWZmZXIsIGJ5dGVPZmZzZXQsIGJ5dGVMZW5ndGgpO1xyXG4gICAgICAgICAgICBjYXNlIEVDb21wb25lbnRUeXBlLlVOU0lHTkVEX0JZVEU6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoYnVmZmVyLCBieXRlT2Zmc2V0LCBieXRlTGVuZ3RoKTtcclxuICAgICAgICAgICAgY2FzZSBFQ29tcG9uZW50VHlwZS5TSE9SVDpcclxuICAgICAgICAgICAgICAgIHJldHVybiBuZXcgSW50MTZBcnJheShidWZmZXIsIGJ5dGVPZmZzZXQsIGJ5dGVMZW5ndGgpO1xyXG4gICAgICAgICAgICBjYXNlIEVDb21wb25lbnRUeXBlLlVOU0lHTkVEX1NIT1JUOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBVaW50MTZBcnJheShidWZmZXIsIGJ5dGVPZmZzZXQsIGJ5dGVMZW5ndGgpO1xyXG4gICAgICAgICAgICBkZWZhdWx0OlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBGbG9hdDMyQXJyYXkoYnVmZmVyLCBieXRlT2Zmc2V0LCBieXRlTGVuZ3RoKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIGEgYnVmZmVyIGZyb20gaXRzIGFjY2Vzc29yXHJcbiAgICAgKiBAcGFyYW0gZ2x0ZlJ1bnRpbWUgdGhlIEdMVEYgcnVudGltZVxyXG4gICAgICogQHBhcmFtIGFjY2Vzc29yIHRoZSBHTFRGIGFjY2Vzc29yXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgR2V0QnVmZmVyRnJvbUFjY2Vzc29yKGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUsIGFjY2Vzc29yOiBJR0xURkFjY2Vzc29yKTogYW55IHtcclxuICAgICAgICBjb25zdCBidWZmZXJWaWV3OiBJR0xURkJ1ZmZlclZpZXcgPSBnbHRmUnVudGltZS5idWZmZXJWaWV3c1thY2Nlc3Nvci5idWZmZXJWaWV3XTtcclxuICAgICAgICBjb25zdCBieXRlTGVuZ3RoID0gYWNjZXNzb3IuY291bnQgKiBHTFRGVXRpbHMuR2V0Qnl0ZVN0cmlkZUZyb21UeXBlKGFjY2Vzc29yKTtcclxuICAgICAgICByZXR1cm4gR0xURlV0aWxzLkdldEJ1ZmZlckZyb21CdWZmZXJWaWV3KGdsdGZSdW50aW1lLCBidWZmZXJWaWV3LCBhY2Nlc3Nvci5ieXRlT2Zmc2V0LCBieXRlTGVuZ3RoLCBhY2Nlc3Nvci5jb21wb25lbnRUeXBlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIERlY29kZXMgYSBidWZmZXIgdmlldyBpbnRvIGEgc3RyaW5nXHJcbiAgICAgKiBAcGFyYW0gdmlldyB0aGUgYnVmZmVyIHZpZXdcclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBEZWNvZGVCdWZmZXJUb1RleHQodmlldzogQXJyYXlCdWZmZXJWaWV3KTogc3RyaW5nIHtcclxuICAgICAgICBsZXQgcmVzdWx0ID0gXCJcIjtcclxuICAgICAgICBjb25zdCBsZW5ndGggPSB2aWV3LmJ5dGVMZW5ndGg7XHJcblxyXG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVuZ3RoOyArK2kpIHtcclxuICAgICAgICAgICAgcmVzdWx0ICs9IFN0cmluZy5mcm9tQ2hhckNvZGUoKDxhbnk+dmlldylbaV0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgdGhlIGRlZmF1bHQgbWF0ZXJpYWwgb2YgZ2x0Zi4gUmVsYXRlZCB0b1xyXG4gICAgICogaHR0cHM6Ly9naXRodWIuY29tL0tocm9ub3NHcm91cC9nbFRGL3RyZWUvbWFzdGVyL3NwZWNpZmljYXRpb24vMS4wI2FwcGVuZGl4LWEtZGVmYXVsdC1tYXRlcmlhbFxyXG4gICAgICogQHBhcmFtIHNjZW5lIHRoZSBCYWJ5bG9uLmpzIHNjZW5lXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgR2V0RGVmYXVsdE1hdGVyaWFsKHNjZW5lOiBTY2VuZSk6IFNoYWRlck1hdGVyaWFsIHtcclxuICAgICAgICBpZiAoIUdMVEZVdGlscy5fRGVmYXVsdE1hdGVyaWFsKSB7XHJcbiAgICAgICAgICAgIEVmZmVjdC5TaGFkZXJzU3RvcmVbXCJHTFRGRGVmYXVsdE1hdGVyaWFsVmVydGV4U2hhZGVyXCJdID0gW1xyXG4gICAgICAgICAgICAgICAgXCJwcmVjaXNpb24gaGlnaHAgZmxvYXQ7XCIsXHJcbiAgICAgICAgICAgICAgICBcIlwiLFxyXG4gICAgICAgICAgICAgICAgXCJ1bmlmb3JtIG1hdDQgd29ybGRWaWV3O1wiLFxyXG4gICAgICAgICAgICAgICAgXCJ1bmlmb3JtIG1hdDQgcHJvamVjdGlvbjtcIixcclxuICAgICAgICAgICAgICAgIFwiXCIsXHJcbiAgICAgICAgICAgICAgICBcImF0dHJpYnV0ZSB2ZWMzIHBvc2l0aW9uO1wiLFxyXG4gICAgICAgICAgICAgICAgXCJcIixcclxuICAgICAgICAgICAgICAgIFwidm9pZCBtYWluKHZvaWQpXCIsXHJcbiAgICAgICAgICAgICAgICBcIntcIixcclxuICAgICAgICAgICAgICAgIFwiICAgIGdsX1Bvc2l0aW9uID0gcHJvamVjdGlvbiAqIHdvcmxkVmlldyAqIHZlYzQocG9zaXRpb24sIDEuMCk7XCIsXHJcbiAgICAgICAgICAgICAgICBcIn1cIixcclxuICAgICAgICAgICAgXS5qb2luKFwiXFxuXCIpO1xyXG5cclxuICAgICAgICAgICAgRWZmZWN0LlNoYWRlcnNTdG9yZVtcIkdMVEZEZWZhdWx0TWF0ZXJpYWxQaXhlbFNoYWRlclwiXSA9IFtcclxuICAgICAgICAgICAgICAgIFwicHJlY2lzaW9uIGhpZ2hwIGZsb2F0O1wiLFxyXG4gICAgICAgICAgICAgICAgXCJcIixcclxuICAgICAgICAgICAgICAgIFwidW5pZm9ybSB2ZWM0IHVfZW1pc3Npb247XCIsXHJcbiAgICAgICAgICAgICAgICBcIlwiLFxyXG4gICAgICAgICAgICAgICAgXCJ2b2lkIG1haW4odm9pZClcIixcclxuICAgICAgICAgICAgICAgIFwie1wiLFxyXG4gICAgICAgICAgICAgICAgXCIgICAgZ2xfRnJhZ0NvbG9yID0gdV9lbWlzc2lvbjtcIixcclxuICAgICAgICAgICAgICAgIFwifVwiLFxyXG4gICAgICAgICAgICBdLmpvaW4oXCJcXG5cIik7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBzaGFkZXJQYXRoID0ge1xyXG4gICAgICAgICAgICAgICAgdmVydGV4OiBcIkdMVEZEZWZhdWx0TWF0ZXJpYWxcIixcclxuICAgICAgICAgICAgICAgIGZyYWdtZW50OiBcIkdMVEZEZWZhdWx0TWF0ZXJpYWxcIixcclxuICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IG9wdGlvbnMgPSB7XHJcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVzOiBbXCJwb3NpdGlvblwiXSxcclxuICAgICAgICAgICAgICAgIHVuaWZvcm1zOiBbXCJ3b3JsZFZpZXdcIiwgXCJwcm9qZWN0aW9uXCIsIFwidV9lbWlzc2lvblwiXSxcclxuICAgICAgICAgICAgICAgIHNhbXBsZXJzOiBuZXcgQXJyYXk8c3RyaW5nPigpLFxyXG4gICAgICAgICAgICAgICAgbmVlZEFscGhhQmxlbmRpbmc6IGZhbHNlLFxyXG4gICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgR0xURlV0aWxzLl9EZWZhdWx0TWF0ZXJpYWwgPSBuZXcgU2hhZGVyTWF0ZXJpYWwoXCJHTFRGRGVmYXVsdE1hdGVyaWFsXCIsIHNjZW5lLCBzaGFkZXJQYXRoLCBvcHRpb25zKTtcclxuICAgICAgICAgICAgR0xURlV0aWxzLl9EZWZhdWx0TWF0ZXJpYWwuc2V0Q29sb3I0KFwidV9lbWlzc2lvblwiLCBuZXcgQ29sb3I0KDAuNSwgMC41LCAwLjUsIDEuMCkpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIEdMVEZVdGlscy5fRGVmYXVsdE1hdGVyaWFsO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFRoZSBHTFRGIGRlZmF1bHQgbWF0ZXJpYWxcclxuICAgIHByaXZhdGUgc3RhdGljIF9EZWZhdWx0TWF0ZXJpYWw6IE51bGxhYmxlPFNoYWRlck1hdGVyaWFsPiA9IG51bGw7XHJcbn1cclxuIiwiaW1wb3J0IHsgR0xURkxvYWRlckV4dGVuc2lvbiwgR0xURkxvYWRlckJhc2UsIEdMVEZMb2FkZXIgfSBmcm9tIFwiLi9nbFRGTG9hZGVyXCI7XHJcblxyXG5pbXBvcnQgdHlwZSB7IElHTFRGUnVudGltZSwgSUdMVEZNYXRlcmlhbCB9IGZyb20gXCIuL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcblxyXG5pbXBvcnQgeyBWZWN0b3IzIH0gZnJvbSBcImNvcmUvTWF0aHMvbWF0aC52ZWN0b3JcIjtcclxuaW1wb3J0IHsgQ29sb3IzIH0gZnJvbSBcImNvcmUvTWF0aHMvbWF0aC5jb2xvclwiO1xyXG5pbXBvcnQgeyBUb29scyB9IGZyb20gXCJjb3JlL01pc2MvdG9vbHNcIjtcclxuaW1wb3J0IHsgTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvbWF0ZXJpYWxcIjtcclxuaW1wb3J0IHsgU3RhbmRhcmRNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9zdGFuZGFyZE1hdGVyaWFsXCI7XHJcbmltcG9ydCB7IEhlbWlzcGhlcmljTGlnaHQgfSBmcm9tIFwiY29yZS9MaWdodHMvaGVtaXNwaGVyaWNMaWdodFwiO1xyXG5pbXBvcnQgeyBEaXJlY3Rpb25hbExpZ2h0IH0gZnJvbSBcImNvcmUvTGlnaHRzL2RpcmVjdGlvbmFsTGlnaHRcIjtcclxuaW1wb3J0IHsgUG9pbnRMaWdodCB9IGZyb20gXCJjb3JlL0xpZ2h0cy9wb2ludExpZ2h0XCI7XHJcbmltcG9ydCB7IFNwb3RMaWdodCB9IGZyb20gXCJjb3JlL0xpZ2h0cy9zcG90TGlnaHRcIjtcclxuXHJcbmludGVyZmFjZSBJR0xURk1hdGVyaWFsc0NvbW1vbkV4dGVuc2lvblZhbHVlcyB7XHJcbiAgICBhbWJpZW50PzogbnVtYmVyW10gfCBzdHJpbmc7XHJcbiAgICBkaWZmdXNlPzogbnVtYmVyW10gfCBzdHJpbmc7XHJcbiAgICBlbWlzc2lvbj86IG51bWJlcltdIHwgc3RyaW5nO1xyXG4gICAgc3BlY3VsYXI/OiBudW1iZXJbXSB8IHN0cmluZztcclxuICAgIHNoaW5pbmVzcz86IG51bWJlcjtcclxuICAgIHRyYW5zcGFyZW5jeT86IG51bWJlcjtcclxufVxyXG5cclxuaW50ZXJmYWNlIElHTFRGTWF0ZXJpYWxzQ29tbW9uRXh0ZW5zaW9uIHtcclxuICAgIHRlY2huaXF1ZTogc3RyaW5nO1xyXG4gICAgdHJhbnNwYXJlbnQ/OiBudW1iZXI7XHJcbiAgICBkb3VibGVTaWRlZD86IGJvb2xlYW47XHJcbiAgICB2YWx1ZXM6IElHTFRGTWF0ZXJpYWxzQ29tbW9uRXh0ZW5zaW9uVmFsdWVzO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgSUdMVEZSdW50aW1lQ29tbW9uRXh0ZW5zaW9uIHtcclxuICAgIGxpZ2h0czogeyBba2V5OiBzdHJpbmddOiBJR0xURkxpZ2h0Q29tbW9uRXh0ZW5zaW9uIH07XHJcbn1cclxuXHJcbmludGVyZmFjZSBJR0xURkxpZ2h0Q29tbW9uRXh0ZW5zaW9uIHtcclxuICAgIG5hbWU6IHN0cmluZztcclxuICAgIHR5cGU6IHN0cmluZztcclxuXHJcbiAgICBhbWJpZW50PzogSUdMVEZBbWJpZW50TGlnaHRDb21tb25FeHRlbnNpb247XHJcbiAgICBwb2ludD86IElHTFRGUG9pbnRMaWdodENvbW1vbkV4dGVuc2lvbjtcclxuICAgIGRpcmVjdGlvbmFsPzogSUdMVEZEaXJlY3Rpb25hbExpZ2h0Q29tbW9uRXh0ZW5zaW9uO1xyXG4gICAgc3BvdD86IElHTFRGU3BvdExpZ2h0Q29tbW9uRXh0ZW5zaW9uO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgSUdMVEZQb2ludExpZ2h0Q29tbW9uRXh0ZW5zaW9uIHtcclxuICAgIGNvbG9yOiBudW1iZXJbXTtcclxuICAgIGNvbnN0YW50QXR0ZW51YXRpb246IG51bWJlcjtcclxuICAgIGxpbmVhckF0dGVudWF0aW9uOiBudW1iZXI7XHJcbiAgICBxdWFkcmF0aWNBdHRlbnVhdGlvbjogbnVtYmVyO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgSUdMVEZBbWJpZW50TGlnaHRDb21tb25FeHRlbnNpb24ge1xyXG4gICAgY29sb3I6IG51bWJlcltdO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgSUdMVEZEaXJlY3Rpb25hbExpZ2h0Q29tbW9uRXh0ZW5zaW9uIHtcclxuICAgIGNvbG9yOiBudW1iZXJbXTtcclxufVxyXG5cclxuaW50ZXJmYWNlIElHTFRGU3BvdExpZ2h0Q29tbW9uRXh0ZW5zaW9uIHtcclxuICAgIGNvbG9yOiBudW1iZXJbXTtcclxuICAgIGNvbnN0YW50QXR0ZW51YXRpb246IG51bWJlcjtcclxuICAgIGZhbGxPZmZBbmdsZTogbnVtYmVyO1xyXG4gICAgZmFsbE9mZkV4cG9uZW50OiBudW1iZXI7XHJcbiAgICBsaW5lYXJBdHRlbnVhdGlvbjogbnVtYmVyO1xyXG4gICAgcXVhZHJhdGljQXR0ZW51YXRpb246IG51bWJlcjtcclxufVxyXG5cclxuLyoqXHJcbiAqIEBpbnRlcm5hbFxyXG4gKiBAZGVwcmVjYXRlZFxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEdMVEZNYXRlcmlhbHNDb21tb25FeHRlbnNpb24gZXh0ZW5kcyBHTFRGTG9hZGVyRXh0ZW5zaW9uIHtcclxuICAgIGNvbnN0cnVjdG9yKCkge1xyXG4gICAgICAgIHN1cGVyKFwiS0hSX21hdGVyaWFsc19jb21tb25cIik7XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIGxvYWRSdW50aW1lRXh0ZW5zaW9uc0FzeW5jKGdsdGZSdW50aW1lOiBJR0xURlJ1bnRpbWUpOiBib29sZWFuIHtcclxuICAgICAgICBpZiAoIWdsdGZSdW50aW1lLmV4dGVuc2lvbnMpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgZXh0ZW5zaW9uOiBJR0xURlJ1bnRpbWVDb21tb25FeHRlbnNpb24gPSBnbHRmUnVudGltZS5leHRlbnNpb25zW3RoaXMubmFtZV07XHJcbiAgICAgICAgaWYgKCFleHRlbnNpb24pIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gQ3JlYXRlIGxpZ2h0c1xyXG4gICAgICAgIGNvbnN0IGxpZ2h0cyA9IGV4dGVuc2lvbi5saWdodHM7XHJcbiAgICAgICAgaWYgKGxpZ2h0cykge1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IHRoaW5nIGluIGxpZ2h0cykge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbGlnaHQ6IElHTFRGTGlnaHRDb21tb25FeHRlbnNpb24gPSBsaWdodHNbdGhpbmddO1xyXG5cclxuICAgICAgICAgICAgICAgIHN3aXRjaCAobGlnaHQudHlwZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJhbWJpZW50XCI6IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYW1iaWVudExpZ2h0ID0gbmV3IEhlbWlzcGhlcmljTGlnaHQobGlnaHQubmFtZSwgbmV3IFZlY3RvcjMoMCwgMSwgMCksIGdsdGZSdW50aW1lLnNjZW5lKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYW1iaWVudCA9IGxpZ2h0LmFtYmllbnQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhbWJpZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbWJpZW50TGlnaHQuZGlmZnVzZSA9IENvbG9yMy5Gcm9tQXJyYXkoYW1iaWVudC5jb2xvciB8fCBbMSwgMSwgMV0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBjYXNlIFwicG9pbnRcIjoge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwb2ludExpZ2h0ID0gbmV3IFBvaW50TGlnaHQobGlnaHQubmFtZSwgbmV3IFZlY3RvcjMoMTAsIDEwLCAxMCksIGdsdGZSdW50aW1lLnNjZW5lKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcG9pbnQgPSBsaWdodC5wb2ludDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHBvaW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBwb2ludExpZ2h0LmRpZmZ1c2UgPSBDb2xvcjMuRnJvbUFycmF5KHBvaW50LmNvbG9yIHx8IFsxLCAxLCAxXSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgXCJkaXJlY3Rpb25hbFwiOiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRpckxpZ2h0ID0gbmV3IERpcmVjdGlvbmFsTGlnaHQobGlnaHQubmFtZSwgbmV3IFZlY3RvcjMoMCwgLTEsIDApLCBnbHRmUnVudGltZS5zY2VuZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGRpcmVjdGlvbmFsID0gbGlnaHQuZGlyZWN0aW9uYWw7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkaXJlY3Rpb25hbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgZGlyTGlnaHQuZGlmZnVzZSA9IENvbG9yMy5Gcm9tQXJyYXkoZGlyZWN0aW9uYWwuY29sb3IgfHwgWzEsIDEsIDFdKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBcInNwb3RcIjoge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzcG90ID0gbGlnaHQuc3BvdDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHNwb3QpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNwb3RMaWdodCA9IG5ldyBTcG90TGlnaHQoXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlnaHQubmFtZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXcgVmVjdG9yMygwLCAxMCwgMCksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3IFZlY3RvcjMoMCwgLTEsIDApLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNwb3QuZmFsbE9mZkFuZ2xlIHx8IE1hdGguUEksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BvdC5mYWxsT2ZmRXhwb25lbnQgfHwgMC4wLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGdsdGZSdW50aW1lLnNjZW5lXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3BvdExpZ2h0LmRpZmZ1c2UgPSBDb2xvcjMuRnJvbUFycmF5KHNwb3QuY29sb3IgfHwgWzEsIDEsIDFdKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgICAgICAgICAgVG9vbHMuV2FybignR0xURiBNYXRlcmlhbCBDb21tb24gZXh0ZW5zaW9uOiBsaWdodCB0eXBlIFwiJyArIGxpZ2h0LnR5cGUgKyBcIuKAnSBub3Qgc3VwcG9ydGVkXCIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBsb2FkTWF0ZXJpYWxBc3luYyhnbHRmUnVudGltZTogSUdMVEZSdW50aW1lLCBpZDogc3RyaW5nLCBvblN1Y2Nlc3M6IChtYXRlcmlhbDogTWF0ZXJpYWwpID0+IHZvaWQsIG9uRXJyb3I6IChtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQpOiBib29sZWFuIHtcclxuICAgICAgICBjb25zdCBtYXRlcmlhbDogSUdMVEZNYXRlcmlhbCA9IGdsdGZSdW50aW1lLm1hdGVyaWFsc1tpZF07XHJcbiAgICAgICAgaWYgKCFtYXRlcmlhbCB8fCAhbWF0ZXJpYWwuZXh0ZW5zaW9ucykge1xyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBleHRlbnNpb246IElHTFRGTWF0ZXJpYWxzQ29tbW9uRXh0ZW5zaW9uID0gbWF0ZXJpYWwuZXh0ZW5zaW9uc1t0aGlzLm5hbWVdO1xyXG4gICAgICAgIGlmICghZXh0ZW5zaW9uKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHN0YW5kYXJkTWF0ZXJpYWwgPSBuZXcgU3RhbmRhcmRNYXRlcmlhbChpZCwgZ2x0ZlJ1bnRpbWUuc2NlbmUpO1xyXG4gICAgICAgIHN0YW5kYXJkTWF0ZXJpYWwuc2lkZU9yaWVudGF0aW9uID0gTWF0ZXJpYWwuQ291bnRlckNsb2NrV2lzZVNpZGVPcmllbnRhdGlvbjtcclxuXHJcbiAgICAgICAgaWYgKGV4dGVuc2lvbi50ZWNobmlxdWUgPT09IFwiQ09OU1RBTlRcIikge1xyXG4gICAgICAgICAgICBzdGFuZGFyZE1hdGVyaWFsLmRpc2FibGVMaWdodGluZyA9IHRydWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBzdGFuZGFyZE1hdGVyaWFsLmJhY2tGYWNlQ3VsbGluZyA9IGV4dGVuc2lvbi5kb3VibGVTaWRlZCA9PT0gdW5kZWZpbmVkID8gZmFsc2UgOiAhZXh0ZW5zaW9uLmRvdWJsZVNpZGVkO1xyXG4gICAgICAgIHN0YW5kYXJkTWF0ZXJpYWwuYWxwaGEgPSBleHRlbnNpb24udmFsdWVzLnRyYW5zcGFyZW5jeSA9PT0gdW5kZWZpbmVkID8gMS4wIDogZXh0ZW5zaW9uLnZhbHVlcy50cmFuc3BhcmVuY3k7XHJcbiAgICAgICAgc3RhbmRhcmRNYXRlcmlhbC5zcGVjdWxhclBvd2VyID0gZXh0ZW5zaW9uLnZhbHVlcy5zaGluaW5lc3MgPT09IHVuZGVmaW5lZCA/IDAuMCA6IGV4dGVuc2lvbi52YWx1ZXMuc2hpbmluZXNzO1xyXG5cclxuICAgICAgICAvLyBBbWJpZW50XHJcbiAgICAgICAgaWYgKHR5cGVvZiBleHRlbnNpb24udmFsdWVzLmFtYmllbnQgPT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgICAgICAgdGhpcy5fbG9hZFRleHR1cmUoZ2x0ZlJ1bnRpbWUsIGV4dGVuc2lvbi52YWx1ZXMuYW1iaWVudCwgc3RhbmRhcmRNYXRlcmlhbCwgXCJhbWJpZW50VGV4dHVyZVwiLCBvbkVycm9yKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBzdGFuZGFyZE1hdGVyaWFsLmFtYmllbnRDb2xvciA9IENvbG9yMy5Gcm9tQXJyYXkoZXh0ZW5zaW9uLnZhbHVlcy5hbWJpZW50IHx8IFswLCAwLCAwXSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBEaWZmdXNlXHJcbiAgICAgICAgaWYgKHR5cGVvZiBleHRlbnNpb24udmFsdWVzLmRpZmZ1c2UgPT09IFwic3RyaW5nXCIpIHtcclxuICAgICAgICAgICAgdGhpcy5fbG9hZFRleHR1cmUoZ2x0ZlJ1bnRpbWUsIGV4dGVuc2lvbi52YWx1ZXMuZGlmZnVzZSwgc3RhbmRhcmRNYXRlcmlhbCwgXCJkaWZmdXNlVGV4dHVyZVwiLCBvbkVycm9yKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBzdGFuZGFyZE1hdGVyaWFsLmRpZmZ1c2VDb2xvciA9IENvbG9yMy5Gcm9tQXJyYXkoZXh0ZW5zaW9uLnZhbHVlcy5kaWZmdXNlIHx8IFswLCAwLCAwXSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBFbWlzc2lvblxyXG4gICAgICAgIGlmICh0eXBlb2YgZXh0ZW5zaW9uLnZhbHVlcy5lbWlzc2lvbiA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgICAgICAgICB0aGlzLl9sb2FkVGV4dHVyZShnbHRmUnVudGltZSwgZXh0ZW5zaW9uLnZhbHVlcy5lbWlzc2lvbiwgc3RhbmRhcmRNYXRlcmlhbCwgXCJlbWlzc2l2ZVRleHR1cmVcIiwgb25FcnJvcik7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgc3RhbmRhcmRNYXRlcmlhbC5lbWlzc2l2ZUNvbG9yID0gQ29sb3IzLkZyb21BcnJheShleHRlbnNpb24udmFsdWVzLmVtaXNzaW9uIHx8IFswLCAwLCAwXSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBTcGVjdWxhclxyXG4gICAgICAgIGlmICh0eXBlb2YgZXh0ZW5zaW9uLnZhbHVlcy5zcGVjdWxhciA9PT0gXCJzdHJpbmdcIikge1xyXG4gICAgICAgICAgICB0aGlzLl9sb2FkVGV4dHVyZShnbHRmUnVudGltZSwgZXh0ZW5zaW9uLnZhbHVlcy5zcGVjdWxhciwgc3RhbmRhcmRNYXRlcmlhbCwgXCJzcGVjdWxhclRleHR1cmVcIiwgb25FcnJvcik7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgc3RhbmRhcmRNYXRlcmlhbC5zcGVjdWxhckNvbG9yID0gQ29sb3IzLkZyb21BcnJheShleHRlbnNpb24udmFsdWVzLnNwZWN1bGFyIHx8IFswLCAwLCAwXSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9sb2FkVGV4dHVyZShnbHRmUnVudGltZTogSUdMVEZSdW50aW1lLCBpZDogc3RyaW5nLCBtYXRlcmlhbDogU3RhbmRhcmRNYXRlcmlhbCwgcHJvcGVydHlQYXRoOiBzdHJpbmcsIG9uRXJyb3I6IChtZXNzYWdlOiBzdHJpbmcpID0+IHZvaWQpOiB2b2lkIHtcclxuICAgICAgICAvLyBDcmVhdGUgYnVmZmVyIGZyb20gdGV4dHVyZSB1cmxcclxuICAgICAgICBHTFRGTG9hZGVyQmFzZS5Mb2FkVGV4dHVyZUJ1ZmZlckFzeW5jKFxyXG4gICAgICAgICAgICBnbHRmUnVudGltZSxcclxuICAgICAgICAgICAgaWQsXHJcbiAgICAgICAgICAgIChidWZmZXIpID0+IHtcclxuICAgICAgICAgICAgICAgIC8vIENyZWF0ZSB0ZXh0dXJlIGZyb20gYnVmZmVyXHJcbiAgICAgICAgICAgICAgICBHTFRGTG9hZGVyQmFzZS5DcmVhdGVUZXh0dXJlQXN5bmMoZ2x0ZlJ1bnRpbWUsIGlkLCBidWZmZXIsICh0ZXh0dXJlKSA9PiAoKDxhbnk+bWF0ZXJpYWwpW3Byb3BlcnR5UGF0aF0gPSB0ZXh0dXJlKSk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIG9uRXJyb3JcclxuICAgICAgICApO1xyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKG5ldyBHTFRGTWF0ZXJpYWxzQ29tbW9uRXh0ZW5zaW9uKCkpO1xyXG4iLCJleHBvcnQgKiBmcm9tIFwiLi9nbFRGQmluYXJ5RXh0ZW5zaW9uXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL2dsVEZMb2FkZXJcIjtcclxuZXhwb3J0ICogZnJvbSBcIi4vZ2xURkxvYWRlckludGVyZmFjZXNcIjtcclxuZXhwb3J0ICogZnJvbSBcIi4vZ2xURkxvYWRlclV0aWxzXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL2dsVEZNYXRlcmlhbHNDb21tb25FeHRlbnNpb25cIjtcclxuIiwiaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB7IFNjYWxhciB9IGZyb20gXCJjb3JlL01hdGhzL21hdGguc2NhbGFyXCI7XHJcbmltcG9ydCB7IFNwaGVyaWNhbEhhcm1vbmljcywgU3BoZXJpY2FsUG9seW5vbWlhbCB9IGZyb20gXCJjb3JlL01hdGhzL3NwaGVyaWNhbFBvbHlub21pYWxcIjtcclxuaW1wb3J0IHsgUXVhdGVybmlvbiwgTWF0cml4IH0gZnJvbSBcImNvcmUvTWF0aHMvbWF0aC52ZWN0b3JcIjtcclxuaW1wb3J0IHR5cGUgeyBCYXNlVGV4dHVyZSB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9UZXh0dXJlcy9iYXNlVGV4dHVyZVwiO1xyXG5pbXBvcnQgeyBSYXdDdWJlVGV4dHVyZSB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9UZXh0dXJlcy9yYXdDdWJlVGV4dHVyZVwiO1xyXG5cclxuaW1wb3J0IHR5cGUgeyBJRVhUTGlnaHRzSW1hZ2VCYXNlZF9MaWdodFJlZmVyZW5jZUltYWdlQmFzZWQsIElFWFRMaWdodHNJbWFnZUJhc2VkX0xpZ2h0SW1hZ2VCYXNlZCwgSUVYVExpZ2h0c0ltYWdlQmFzZWQgfSBmcm9tIFwiYmFieWxvbmpzLWdsdGYyaW50ZXJmYWNlXCI7XHJcbmltcG9ydCB0eXBlIHsgSVNjZW5lIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcbmltcG9ydCB0eXBlIHsgSUdMVEZMb2FkZXJFeHRlbnNpb24gfSBmcm9tIFwiLi4vZ2xURkxvYWRlckV4dGVuc2lvblwiO1xyXG5pbXBvcnQgeyBHTFRGTG9hZGVyLCBBcnJheUl0ZW0gfSBmcm9tIFwiLi4vZ2xURkxvYWRlclwiO1xyXG5cclxuY29uc3QgTkFNRSA9IFwiRVhUX2xpZ2h0c19pbWFnZV9iYXNlZFwiO1xyXG5cclxuZGVjbGFyZSBtb2R1bGUgXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIiB7XHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXHJcbiAgICBpbnRlcmZhY2UgSUVYVExpZ2h0c0ltYWdlQmFzZWRfTGlnaHRJbWFnZUJhc2VkIHtcclxuICAgICAgICBfYmFieWxvblRleHR1cmU/OiBCYXNlVGV4dHVyZTtcclxuICAgICAgICBfbG9hZGVkPzogUHJvbWlzZTx2b2lkPjtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIFtTcGVjaWZpY2F0aW9uXShodHRwczovL2dpdGh1Yi5jb20vS2hyb25vc0dyb3VwL2dsVEYvYmxvYi9tYWluL2V4dGVuc2lvbnMvMi4wL1ZlbmRvci9FWFRfbGlnaHRzX2ltYWdlX2Jhc2VkL1JFQURNRS5tZClcclxuICovXHJcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cclxuZXhwb3J0IGNsYXNzIEVYVF9saWdodHNfaW1hZ2VfYmFzZWQgaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZGVyOiBHTFRGTG9hZGVyO1xyXG4gICAgcHJpdmF0ZSBfbGlnaHRzPzogSUVYVExpZ2h0c0ltYWdlQmFzZWRfTGlnaHRJbWFnZUJhc2VkW107XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGVyOiBHTFRGTG9hZGVyKSB7XHJcbiAgICAgICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyO1xyXG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IHRoaXMuX2xvYWRlci5pc0V4dGVuc2lvblVzZWQoTkFNRSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKSB7XHJcbiAgICAgICAgKHRoaXMuX2xvYWRlciBhcyBhbnkpID0gbnVsbDtcclxuICAgICAgICBkZWxldGUgdGhpcy5fbGlnaHRzO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBvbkxvYWRpbmcoKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3QgZXh0ZW5zaW9ucyA9IHRoaXMuX2xvYWRlci5nbHRmLmV4dGVuc2lvbnM7XHJcbiAgICAgICAgaWYgKGV4dGVuc2lvbnMgJiYgZXh0ZW5zaW9uc1t0aGlzLm5hbWVdKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGV4dGVuc2lvbiA9IGV4dGVuc2lvbnNbdGhpcy5uYW1lXSBhcyBJRVhUTGlnaHRzSW1hZ2VCYXNlZDtcclxuICAgICAgICAgICAgdGhpcy5fbGlnaHRzID0gZXh0ZW5zaW9uLmxpZ2h0cztcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRTY2VuZUFzeW5jKGNvbnRleHQ6IHN0cmluZywgc2NlbmU6IElTY2VuZSk6IE51bGxhYmxlPFByb21pc2U8dm9pZD4+IHtcclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SUVYVExpZ2h0c0ltYWdlQmFzZWRfTGlnaHRSZWZlcmVuY2VJbWFnZUJhc2VkPihjb250ZXh0LCBzY2VuZSwgdGhpcy5uYW1lLCAoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuX2xvYWRlci5fYWxsTWF0ZXJpYWxzRGlydHlSZXF1aXJlZCA9IHRydWU7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBwcm9taXNlcyA9IG5ldyBBcnJheTxQcm9taXNlPGFueT4+KCk7XHJcblxyXG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKHRoaXMuX2xvYWRlci5sb2FkU2NlbmVBc3luYyhjb250ZXh0LCBzY2VuZSkpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvZ09wZW4oYCR7ZXh0ZW5zaW9uQ29udGV4dH1gKTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGxpZ2h0ID0gQXJyYXlJdGVtLkdldChgJHtleHRlbnNpb25Db250ZXh0fS9saWdodGAsIHRoaXMuX2xpZ2h0cywgZXh0ZW5zaW9uLmxpZ2h0KTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaChcclxuICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRMaWdodEFzeW5jKGAvZXh0ZW5zaW9ucy8ke3RoaXMubmFtZX0vbGlnaHRzLyR7ZXh0ZW5zaW9uLmxpZ2h0fWAsIGxpZ2h0KS50aGVuKCh0ZXh0dXJlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmJhYnlsb25TY2VuZS5lbnZpcm9ubWVudFRleHR1cmUgPSB0ZXh0dXJlO1xyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuX2xvYWRlci5sb2dDbG9zZSgpO1xyXG5cclxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IHt9KTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9sb2FkTGlnaHRBc3luYyhjb250ZXh0OiBzdHJpbmcsIGxpZ2h0OiBJRVhUTGlnaHRzSW1hZ2VCYXNlZF9MaWdodEltYWdlQmFzZWQpOiBQcm9taXNlPEJhc2VUZXh0dXJlPiB7XHJcbiAgICAgICAgaWYgKCFsaWdodC5fbG9hZGVkKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuX2xvYWRlci5sb2dPcGVuKGAke2NvbnRleHR9YCk7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBpbWFnZURhdGEgPSBuZXcgQXJyYXk8QXJyYXk8QXJyYXlCdWZmZXJWaWV3Pj4obGlnaHQuc3BlY3VsYXJJbWFnZXMubGVuZ3RoKTtcclxuICAgICAgICAgICAgZm9yIChsZXQgbWlwbWFwID0gMDsgbWlwbWFwIDwgbGlnaHQuc3BlY3VsYXJJbWFnZXMubGVuZ3RoOyBtaXBtYXArKykge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZmFjZXMgPSBsaWdodC5zcGVjdWxhckltYWdlc1ttaXBtYXBdO1xyXG4gICAgICAgICAgICAgICAgaW1hZ2VEYXRhW21pcG1hcF0gPSBuZXcgQXJyYXk8QXJyYXlCdWZmZXJWaWV3PihmYWNlcy5sZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgZmFjZSA9IDA7IGZhY2UgPCBmYWNlcy5sZW5ndGg7IGZhY2UrKykge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNwZWN1bGFySW1hZ2VDb250ZXh0ID0gYCR7Y29udGV4dH0vc3BlY3VsYXJJbWFnZXMvJHttaXBtYXB9LyR7ZmFjZX1gO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRlci5sb2dPcGVuKGAke3NwZWN1bGFySW1hZ2VDb250ZXh0fWApO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBpbmRleCA9IGZhY2VzW2ZhY2VdO1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGltYWdlID0gQXJyYXlJdGVtLkdldChzcGVjdWxhckltYWdlQ29udGV4dCwgdGhpcy5fbG9hZGVyLmdsdGYuaW1hZ2VzLCBpbmRleCk7XHJcbiAgICAgICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaChcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvYWRJbWFnZUFzeW5jKGAvaW1hZ2VzLyR7aW5kZXh9YCwgaW1hZ2UpLnRoZW4oKGRhdGEpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGltYWdlRGF0YVttaXBtYXBdW2ZhY2VdID0gZGF0YTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIubG9nQ2xvc2UoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvZ0Nsb3NlKCk7XHJcblxyXG4gICAgICAgICAgICBsaWdodC5fbG9hZGVkID0gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgYmFieWxvblRleHR1cmUgPSBuZXcgUmF3Q3ViZVRleHR1cmUodGhpcy5fbG9hZGVyLmJhYnlsb25TY2VuZSwgbnVsbCwgbGlnaHQuc3BlY3VsYXJJbWFnZVNpemUpO1xyXG4gICAgICAgICAgICAgICAgYmFieWxvblRleHR1cmUubmFtZSA9IGxpZ2h0Lm5hbWUgfHwgXCJlbnZpcm9ubWVudFwiO1xyXG4gICAgICAgICAgICAgICAgbGlnaHQuX2JhYnlsb25UZXh0dXJlID0gYmFieWxvblRleHR1cmU7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGxpZ2h0LmludGVuc2l0eSAhPSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uVGV4dHVyZS5sZXZlbCA9IGxpZ2h0LmludGVuc2l0eTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAobGlnaHQucm90YXRpb24pIHtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgcm90YXRpb24gPSBRdWF0ZXJuaW9uLkZyb21BcnJheShsaWdodC5yb3RhdGlvbik7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIC8vIEludmVydCB0aGUgcm90YXRpb24gc28gdGhhdCBwb3NpdGl2ZSByb3RhdGlvbiBpcyBjb3VudGVyLWNsb2Nrd2lzZS5cclxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX2xvYWRlci5iYWJ5bG9uU2NlbmUudXNlUmlnaHRIYW5kZWRTeXN0ZW0pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcm90YXRpb24gPSBRdWF0ZXJuaW9uLkludmVyc2Uocm90YXRpb24pO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgTWF0cml4LkZyb21RdWF0ZXJuaW9uVG9SZWYocm90YXRpb24sIGJhYnlsb25UZXh0dXJlLmdldFJlZmxlY3Rpb25UZXh0dXJlTWF0cml4KCkpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmICghbGlnaHQuaXJyYWRpYW5jZUNvZWZmaWNpZW50cykge1xyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fTogSXJyYWRpYW5jZSBjb2VmZmljaWVudHMgYXJlIG1pc3NpbmdgKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBzcGhlcmljYWxIYXJtb25pY3MgPSBTcGhlcmljYWxIYXJtb25pY3MuRnJvbUFycmF5KGxpZ2h0LmlycmFkaWFuY2VDb2VmZmljaWVudHMpO1xyXG4gICAgICAgICAgICAgICAgc3BoZXJpY2FsSGFybW9uaWNzLnNjYWxlSW5QbGFjZShsaWdodC5pbnRlbnNpdHkpO1xyXG5cclxuICAgICAgICAgICAgICAgIHNwaGVyaWNhbEhhcm1vbmljcy5jb252ZXJ0SXJyYWRpYW5jZVRvTGFtYmVydGlhblJhZGlhbmNlKCk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBzcGhlcmljYWxQb2x5bm9taWFsID0gU3BoZXJpY2FsUG9seW5vbWlhbC5Gcm9tSGFybW9uaWNzKHNwaGVyaWNhbEhhcm1vbmljcyk7XHJcblxyXG4gICAgICAgICAgICAgICAgLy8gQ29tcHV0ZSB0aGUgbG9kIGdlbmVyYXRpb24gc2NhbGUgdG8gZml0IGV4YWN0bHkgdG8gdGhlIG51bWJlciBvZiBsZXZlbHMgYXZhaWxhYmxlLlxyXG4gICAgICAgICAgICAgICAgY29uc3QgbG9kR2VuZXJhdGlvblNjYWxlID0gKGltYWdlRGF0YS5sZW5ndGggLSAxKSAvIFNjYWxhci5Mb2cyKGxpZ2h0LnNwZWN1bGFySW1hZ2VTaXplKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBiYWJ5bG9uVGV4dHVyZS51cGRhdGVSR0JEQXN5bmMoaW1hZ2VEYXRhLCBzcGhlcmljYWxQb2x5bm9taWFsLCBsb2RHZW5lcmF0aW9uU2NhbGUpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBsaWdodC5fbG9hZGVkLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gbGlnaHQuX2JhYnlsb25UZXh0dXJlITtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxufVxyXG5cclxuR0xURkxvYWRlci5SZWdpc3RlckV4dGVuc2lvbihOQU1FLCAobG9hZGVyKSA9PiBuZXcgRVhUX2xpZ2h0c19pbWFnZV9iYXNlZChsb2FkZXIpKTtcclxuIiwiaW1wb3J0IHsgVmVjdG9yMywgUXVhdGVybmlvbiwgTWF0cml4LCBUbXBWZWN0b3JzIH0gZnJvbSBcImNvcmUvTWF0aHMvbWF0aC52ZWN0b3JcIjtcclxuaW1wb3J0IHR5cGUgeyBNZXNoIH0gZnJvbSBcImNvcmUvTWVzaGVzL21lc2hcIjtcclxuaW1wb3J0IHR5cGUgeyBUcmFuc2Zvcm1Ob2RlIH0gZnJvbSBcImNvcmUvTWVzaGVzL3RyYW5zZm9ybU5vZGVcIjtcclxuaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB7IEdMVEZMb2FkZXIsIEFycmF5SXRlbSB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgSUdMVEZMb2FkZXJFeHRlbnNpb24gfSBmcm9tIFwiLi4vZ2xURkxvYWRlckV4dGVuc2lvblwiO1xyXG5pbXBvcnQgdHlwZSB7IElOb2RlIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcblxyXG5pbXBvcnQgdHlwZSB7IElFWFRNZXNoR3B1SW5zdGFuY2luZyB9IGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuXHJcbmltcG9ydCBcImNvcmUvTWVzaGVzL3RoaW5JbnN0YW5jZU1lc2hcIjtcclxuXHJcbmNvbnN0IE5BTUUgPSBcIkVYVF9tZXNoX2dwdV9pbnN0YW5jaW5nXCI7XHJcblxyXG4vKipcclxuICogW1NwZWNpZmljYXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9LaHJvbm9zR3JvdXAvZ2xURi9ibG9iL21haW4vZXh0ZW5zaW9ucy8yLjAvVmVuZG9yL0VYVF9tZXNoX2dwdV9pbnN0YW5jaW5nL1JFQURNRS5tZClcclxuICogW1BsYXlncm91bmQgU2FtcGxlXShodHRwczovL3BsYXlncm91bmQuYmFieWxvbmpzLmNvbS8jUUZJR0xXIzkpXHJcbiAqL1xyXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXHJcbmV4cG9ydCBjbGFzcyBFWFRfbWVzaF9ncHVfaW5zdGFuY2luZyBpbXBsZW1lbnRzIElHTFRGTG9hZGVyRXh0ZW5zaW9uIHtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIG5hbWUgb2YgdGhpcyBleHRlbnNpb24uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyByZWFkb25seSBuYW1lID0gTkFNRTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgd2hldGhlciB0aGlzIGV4dGVuc2lvbiBpcyBlbmFibGVkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZW5hYmxlZDogYm9vbGVhbjtcclxuXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGVyOiBHTFRGTG9hZGVyKSB7XHJcbiAgICAgICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyO1xyXG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IHRoaXMuX2xvYWRlci5pc0V4dGVuc2lvblVzZWQoTkFNRSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKSB7XHJcbiAgICAgICAgKHRoaXMuX2xvYWRlciBhcyBhbnkpID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZE5vZGVBc3luYyhjb250ZXh0OiBzdHJpbmcsIG5vZGU6IElOb2RlLCBhc3NpZ246IChiYWJ5bG9uVHJhbnNmb3JtTm9kZTogVHJhbnNmb3JtTm9kZSkgPT4gdm9pZCk6IE51bGxhYmxlPFByb21pc2U8VHJhbnNmb3JtTm9kZT4+IHtcclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SUVYVE1lc2hHcHVJbnN0YW5jaW5nLCBUcmFuc2Zvcm1Ob2RlPihjb250ZXh0LCBub2RlLCB0aGlzLm5hbWUsIChleHRlbnNpb25Db250ZXh0LCBleHRlbnNpb24pID0+IHtcclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyLl9kaXNhYmxlSW5zdGFuY2VkTWVzaCsrO1xyXG5cclxuICAgICAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuX2xvYWRlci5sb2FkTm9kZUFzeW5jKGAvbm9kZXMvJHtub2RlLmluZGV4fWAsIG5vZGUsIGFzc2lnbik7XHJcblxyXG4gICAgICAgICAgICB0aGlzLl9sb2FkZXIuX2Rpc2FibGVJbnN0YW5jZWRNZXNoLS07XHJcblxyXG4gICAgICAgICAgICBpZiAoIW5vZGUuX3ByaW1pdGl2ZUJhYnlsb25NZXNoZXMpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9taXNlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBwcm9taXNlcyA9IG5ldyBBcnJheTxQcm9taXNlPE51bGxhYmxlPEZsb2F0MzJBcnJheT4+PigpO1xyXG4gICAgICAgICAgICBsZXQgaW5zdGFuY2VDb3VudCA9IDA7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBsb2FkQXR0cmlidXRlID0gKGF0dHJpYnV0ZTogc3RyaW5nKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAoZXh0ZW5zaW9uLmF0dHJpYnV0ZXNbYXR0cmlidXRlXSA9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICBwcm9taXNlcy5wdXNoKFByb21pc2UucmVzb2x2ZShudWxsKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IGFjY2Vzc29yID0gQXJyYXlJdGVtLkdldChgJHtleHRlbnNpb25Db250ZXh0fS9hdHRyaWJ1dGVzLyR7YXR0cmlidXRlfWAsIHRoaXMuX2xvYWRlci5nbHRmLmFjY2Vzc29ycywgZXh0ZW5zaW9uLmF0dHJpYnV0ZXNbYXR0cmlidXRlXSk7XHJcbiAgICAgICAgICAgICAgICBwcm9taXNlcy5wdXNoKHRoaXMuX2xvYWRlci5fbG9hZEZsb2F0QWNjZXNzb3JBc3luYyhgL2FjY2Vzc29ycy8ke2FjY2Vzc29yLmJ1ZmZlclZpZXd9YCwgYWNjZXNzb3IpKTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoaW5zdGFuY2VDb3VudCA9PT0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGluc3RhbmNlQ291bnQgPSBhY2Nlc3Nvci5jb3VudDtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoaW5zdGFuY2VDb3VudCAhPT0gYWNjZXNzb3IuY291bnQpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZXh0ZW5zaW9uQ29udGV4dH0vYXR0cmlidXRlczogSW5zdGFuY2UgYnVmZmVyIGFjY2Vzc29ycyBkbyBub3QgaGF2ZSB0aGUgc2FtZSBjb3VudC5gKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgIGxvYWRBdHRyaWJ1dGUoXCJUUkFOU0xBVElPTlwiKTtcclxuICAgICAgICAgICAgbG9hZEF0dHJpYnV0ZShcIlJPVEFUSU9OXCIpO1xyXG4gICAgICAgICAgICBsb2FkQXR0cmlidXRlKFwiU0NBTEVcIik7XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gcHJvbWlzZS50aGVuKChiYWJ5bG9uVHJhbnNmb3JtTm9kZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKChbdHJhbnNsYXRpb25CdWZmZXIsIHJvdGF0aW9uQnVmZmVyLCBzY2FsZUJ1ZmZlcl0pID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXRyaWNlcyA9IG5ldyBGbG9hdDMyQXJyYXkoaW5zdGFuY2VDb3VudCAqIDE2KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgVG1wVmVjdG9ycy5WZWN0b3IzWzBdLmNvcHlGcm9tRmxvYXRzKDAsIDAsIDApOyAvLyB0cmFuc2xhdGlvblxyXG4gICAgICAgICAgICAgICAgICAgIFRtcFZlY3RvcnMuUXVhdGVybmlvblswXS5jb3B5RnJvbUZsb2F0cygwLCAwLCAwLCAxKTsgLy8gcm90YXRpb25cclxuICAgICAgICAgICAgICAgICAgICBUbXBWZWN0b3JzLlZlY3RvcjNbMV0uY29weUZyb21GbG9hdHMoMSwgMSwgMSk7IC8vIHNjYWxlXHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgaW5zdGFuY2VDb3VudDsgKytpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRyYW5zbGF0aW9uQnVmZmVyICYmIFZlY3RvcjMuRnJvbUFycmF5VG9SZWYodHJhbnNsYXRpb25CdWZmZXIsIGkgKiAzLCBUbXBWZWN0b3JzLlZlY3RvcjNbMF0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByb3RhdGlvbkJ1ZmZlciAmJiBRdWF0ZXJuaW9uLkZyb21BcnJheVRvUmVmKHJvdGF0aW9uQnVmZmVyLCBpICogNCwgVG1wVmVjdG9ycy5RdWF0ZXJuaW9uWzBdKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc2NhbGVCdWZmZXIgJiYgVmVjdG9yMy5Gcm9tQXJyYXlUb1JlZihzY2FsZUJ1ZmZlciwgaSAqIDMsIFRtcFZlY3RvcnMuVmVjdG9yM1sxXSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICBNYXRyaXguQ29tcG9zZVRvUmVmKFRtcFZlY3RvcnMuVmVjdG9yM1sxXSwgVG1wVmVjdG9ycy5RdWF0ZXJuaW9uWzBdLCBUbXBWZWN0b3JzLlZlY3RvcjNbMF0sIFRtcFZlY3RvcnMuTWF0cml4WzBdKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFRtcFZlY3RvcnMuTWF0cml4WzBdLmNvcHlUb0FycmF5KG1hdHJpY2VzLCBpICogMTYpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBiYWJ5bG9uTWVzaCBvZiBub2RlLl9wcmltaXRpdmVCYWJ5bG9uTWVzaGVzISkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAoYmFieWxvbk1lc2ggYXMgTWVzaCkudGhpbkluc3RhbmNlU2V0QnVmZmVyKFwibWF0cml4XCIsIG1hdHJpY2VzLCAxNiwgdHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYmFieWxvblRyYW5zZm9ybU5vZGU7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbkdMVEZMb2FkZXIuUmVnaXN0ZXJFeHRlbnNpb24oTkFNRSwgKGxvYWRlcikgPT4gbmV3IEVYVF9tZXNoX2dwdV9pbnN0YW5jaW5nKGxvYWRlcikpO1xyXG4iLCJpbXBvcnQgdHlwZSB7IE51bGxhYmxlIH0gZnJvbSBcImNvcmUvdHlwZXNcIjtcclxuaW1wb3J0IHR5cGUgeyBJR0xURkxvYWRlckV4dGVuc2lvbiB9IGZyb20gXCIuLi9nbFRGTG9hZGVyRXh0ZW5zaW9uXCI7XHJcbmltcG9ydCB7IEFycmF5SXRlbSwgR0xURkxvYWRlciB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgSUJ1ZmZlclZpZXcgfSBmcm9tIFwiLi4vZ2xURkxvYWRlckludGVyZmFjZXNcIjtcclxuaW1wb3J0IHR5cGUgeyBJRVhUTWVzaG9wdENvbXByZXNzaW9uIH0gZnJvbSBcImJhYnlsb25qcy1nbHRmMmludGVyZmFjZVwiO1xyXG5pbXBvcnQgeyBNZXNob3B0Q29tcHJlc3Npb24gfSBmcm9tIFwiY29yZS9NZXNoZXMvQ29tcHJlc3Npb24vbWVzaG9wdENvbXByZXNzaW9uXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJFWFRfbWVzaG9wdF9jb21wcmVzc2lvblwiO1xyXG5cclxuaW50ZXJmYWNlIElCdWZmZXJWaWV3TWVzaG9wdCBleHRlbmRzIElCdWZmZXJWaWV3IHtcclxuICAgIF9tZXNoT3B0RGF0YT86IFByb21pc2U8QXJyYXlCdWZmZXJWaWV3PjtcclxufVxyXG5cclxuLyoqXHJcbiAqIFtTcGVjaWZpY2F0aW9uXShodHRwczovL2dpdGh1Yi5jb20vS2hyb25vc0dyb3VwL2dsVEYvYmxvYi9tYWluL2V4dGVuc2lvbnMvMi4wL1ZlbmRvci9FWFRfbWVzaG9wdF9jb21wcmVzc2lvbi9SRUFETUUubWQpXHJcbiAqXHJcbiAqIFRoaXMgZXh0ZW5zaW9uIHVzZXMgYSBXZWJBc3NlbWJseSBkZWNvZGVyIG1vZHVsZSBmcm9tIGh0dHBzOi8vZ2l0aHViLmNvbS96ZXV4L21lc2hvcHRpbWl6ZXIvdHJlZS9tYXN0ZXIvanNcclxuICogQHNpbmNlIDUuMC4wXHJcbiAqL1xyXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXHJcbmV4cG9ydCBjbGFzcyBFWFRfbWVzaG9wdF9jb21wcmVzc2lvbiBpbXBsZW1lbnRzIElHTFRGTG9hZGVyRXh0ZW5zaW9uIHtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIG5hbWUgb2YgdGhpcyBleHRlbnNpb24uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyByZWFkb25seSBuYW1lID0gTkFNRTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgd2hldGhlciB0aGlzIGV4dGVuc2lvbiBpcyBlbmFibGVkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZW5hYmxlZDogYm9vbGVhbjtcclxuXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGVyOiBHTFRGTG9hZGVyKSB7XHJcbiAgICAgICAgdGhpcy5lbmFibGVkID0gbG9hZGVyLmlzRXh0ZW5zaW9uVXNlZChOQU1FKTtcclxuICAgICAgICB0aGlzLl9sb2FkZXIgPSBsb2FkZXI7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKSB7XHJcbiAgICAgICAgKHRoaXMuX2xvYWRlciBhcyBhbnkpID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZEJ1ZmZlclZpZXdBc3luYyhjb250ZXh0OiBzdHJpbmcsIGJ1ZmZlclZpZXc6IElCdWZmZXJWaWV3KTogTnVsbGFibGU8UHJvbWlzZTxBcnJheUJ1ZmZlclZpZXc+PiB7XHJcbiAgICAgICAgcmV0dXJuIEdMVEZMb2FkZXIuTG9hZEV4dGVuc2lvbkFzeW5jPElFWFRNZXNob3B0Q29tcHJlc3Npb24sIEFycmF5QnVmZmVyVmlldz4oY29udGV4dCwgYnVmZmVyVmlldywgdGhpcy5uYW1lLCAoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlclZpZXdNZXNob3B0ID0gYnVmZmVyVmlldyBhcyBJQnVmZmVyVmlld01lc2hvcHQ7XHJcbiAgICAgICAgICAgIGlmIChidWZmZXJWaWV3TWVzaG9wdC5fbWVzaE9wdERhdGEpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiBidWZmZXJWaWV3TWVzaG9wdC5fbWVzaE9wdERhdGE7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlciA9IEFycmF5SXRlbS5HZXQoYCR7Y29udGV4dH0vYnVmZmVyYCwgdGhpcy5fbG9hZGVyLmdsdGYuYnVmZmVycywgZXh0ZW5zaW9uLmJ1ZmZlcik7XHJcbiAgICAgICAgICAgIGJ1ZmZlclZpZXdNZXNob3B0Ll9tZXNoT3B0RGF0YSA9IHRoaXMuX2xvYWRlci5sb2FkQnVmZmVyQXN5bmMoYC9idWZmZXJzLyR7YnVmZmVyLmluZGV4fWAsIGJ1ZmZlciwgZXh0ZW5zaW9uLmJ5dGVPZmZzZXQgfHwgMCwgZXh0ZW5zaW9uLmJ5dGVMZW5ndGgpLnRoZW4oKGJ1ZmZlcikgPT4ge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIE1lc2hvcHRDb21wcmVzc2lvbi5EZWZhdWx0LmRlY29kZUdsdGZCdWZmZXJBc3luYyhidWZmZXIgYXMgVWludDhBcnJheSwgZXh0ZW5zaW9uLmNvdW50LCBleHRlbnNpb24uYnl0ZVN0cmlkZSwgZXh0ZW5zaW9uLm1vZGUsIGV4dGVuc2lvbi5maWx0ZXIpO1xyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIHJldHVybiBidWZmZXJWaWV3TWVzaG9wdC5fbWVzaE9wdERhdGE7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbkdMVEZMb2FkZXIuUmVnaXN0ZXJFeHRlbnNpb24oTkFNRSwgKGxvYWRlcikgPT4gbmV3IEVYVF9tZXNob3B0X2NvbXByZXNzaW9uKGxvYWRlcikpO1xyXG4iLCJpbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciwgQXJyYXlJdGVtIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJcIjtcclxuaW1wb3J0IHR5cGUgeyBJVGV4dHVyZSB9IGZyb20gXCIuLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IEJhc2VUZXh0dXJlIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL1RleHR1cmVzL2Jhc2VUZXh0dXJlXCI7XHJcbmltcG9ydCB0eXBlIHsgTnVsbGFibGUgfSBmcm9tIFwiY29yZS90eXBlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElFWFRUZXh0dXJlV2ViUCB9IGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuXHJcbmNvbnN0IE5BTUUgPSBcIkVYVF90ZXh0dXJlX3dlYnBcIjtcclxuXHJcbi8qKlxyXG4gKiBbU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly9naXRodWIuY29tL0tocm9ub3NHcm91cC9nbFRGL2Jsb2IvbWFpbi9leHRlbnNpb25zLzIuMC9WZW5kb3IvRVhUX3RleHR1cmVfd2VicC9SRUFETUUubWQpXHJcbiAqL1xyXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXHJcbmV4cG9ydCBjbGFzcyBFWFRfdGV4dHVyZV93ZWJwIGltcGxlbWVudHMgSUdMVEZMb2FkZXJFeHRlbnNpb24ge1xyXG4gICAgLyoqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLiAqL1xyXG4gICAgcHVibGljIHJlYWRvbmx5IG5hbWUgPSBOQU1FO1xyXG5cclxuICAgIC8qKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC4gKi9cclxuICAgIHB1YmxpYyBlbmFibGVkOiBib29sZWFuO1xyXG5cclxuICAgIHByaXZhdGUgX2xvYWRlcjogR0xURkxvYWRlcjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3Rvcihsb2FkZXI6IEdMVEZMb2FkZXIpIHtcclxuICAgICAgICB0aGlzLl9sb2FkZXIgPSBsb2FkZXI7XHJcbiAgICAgICAgdGhpcy5lbmFibGVkID0gbG9hZGVyLmlzRXh0ZW5zaW9uVXNlZChOQU1FKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpIHtcclxuICAgICAgICAodGhpcy5fbG9hZGVyIGFzIGFueSkgPSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBfbG9hZFRleHR1cmVBc3luYyhjb250ZXh0OiBzdHJpbmcsIHRleHR1cmU6IElUZXh0dXJlLCBhc3NpZ246IChiYWJ5bG9uVGV4dHVyZTogQmFzZVRleHR1cmUpID0+IHZvaWQpOiBOdWxsYWJsZTxQcm9taXNlPEJhc2VUZXh0dXJlPj4ge1xyXG4gICAgICAgIHJldHVybiBHTFRGTG9hZGVyLkxvYWRFeHRlbnNpb25Bc3luYzxJRVhUVGV4dHVyZVdlYlAsIEJhc2VUZXh0dXJlPihjb250ZXh0LCB0ZXh0dXJlLCB0aGlzLm5hbWUsIChleHRlbnNpb25Db250ZXh0LCBleHRlbnNpb24pID0+IHtcclxuICAgICAgICAgICAgY29uc3Qgc2FtcGxlciA9IHRleHR1cmUuc2FtcGxlciA9PSB1bmRlZmluZWQgPyBHTFRGTG9hZGVyLkRlZmF1bHRTYW1wbGVyIDogQXJyYXlJdGVtLkdldChgJHtjb250ZXh0fS9zYW1wbGVyYCwgdGhpcy5fbG9hZGVyLmdsdGYuc2FtcGxlcnMsIHRleHR1cmUuc2FtcGxlcik7XHJcbiAgICAgICAgICAgIGNvbnN0IGltYWdlID0gQXJyYXlJdGVtLkdldChgJHtleHRlbnNpb25Db250ZXh0fS9zb3VyY2VgLCB0aGlzLl9sb2FkZXIuZ2x0Zi5pbWFnZXMsIGV4dGVuc2lvbi5zb3VyY2UpO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbG9hZGVyLl9jcmVhdGVUZXh0dXJlQXN5bmMoXHJcbiAgICAgICAgICAgICAgICBjb250ZXh0LFxyXG4gICAgICAgICAgICAgICAgc2FtcGxlcixcclxuICAgICAgICAgICAgICAgIGltYWdlLFxyXG4gICAgICAgICAgICAgICAgKGJhYnlsb25UZXh0dXJlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgYXNzaWduKGJhYnlsb25UZXh0dXJlKTtcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgICAgICAhdGV4dHVyZS5fdGV4dHVyZUluZm8ubm9uQ29sb3JEYXRhXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbkdMVEZMb2FkZXIuUmVnaXN0ZXJFeHRlbnNpb24oTkFNRSwgKGxvYWRlcikgPT4gbmV3IEVYVF90ZXh0dXJlX3dlYnAobG9hZGVyKSk7XHJcbiIsImltcG9ydCB0eXBlIHsgTnVsbGFibGUgfSBmcm9tIFwiY29yZS90eXBlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IFRyYW5zZm9ybU5vZGUgfSBmcm9tIFwiY29yZS9NZXNoZXMvdHJhbnNmb3JtTm9kZVwiO1xyXG5pbXBvcnQgdHlwZSB7IENhbWVyYSB9IGZyb20gXCJjb3JlL0NhbWVyYXMvY2FtZXJhXCI7XHJcblxyXG5pbXBvcnQgdHlwZSB7IElQcm9wZXJ0eSB9IGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuaW1wb3J0IHR5cGUgeyBJTm9kZSwgSUNhbWVyYSwgSU1hdGVyaWFsIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcbmltcG9ydCB0eXBlIHsgSUdMVEZMb2FkZXJFeHRlbnNpb24gfSBmcm9tIFwiLi4vZ2xURkxvYWRlckV4dGVuc2lvblwiO1xyXG5pbXBvcnQgeyBHTFRGTG9hZGVyIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJcIjtcclxuaW1wb3J0IHR5cGUgeyBNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9tYXRlcmlhbFwiO1xyXG5cclxuY29uc3QgTkFNRSA9IFwiRXh0cmFzQXNNZXRhZGF0YVwiO1xyXG5cclxuaW50ZXJmYWNlIE9iamVjdFdpdGhNZXRhZGF0YSB7XHJcbiAgICBtZXRhZGF0YTogYW55O1xyXG59XHJcblxyXG4vKipcclxuICogU3RvcmUgZ2xURiBleHRyYXMgKGlmIHByZXNlbnQpIGluIEJKUyBvYmplY3RzJyBtZXRhZGF0YVxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEV4dHJhc0FzTWV0YWRhdGEgaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQgPSB0cnVlO1xyXG5cclxuICAgIHByaXZhdGUgX2xvYWRlcjogR0xURkxvYWRlcjtcclxuXHJcbiAgICBwcml2YXRlIF9hc3NpZ25FeHRyYXMoYmFieWxvbk9iamVjdDogT2JqZWN0V2l0aE1ldGFkYXRhLCBnbHRmUHJvcDogSVByb3BlcnR5KTogdm9pZCB7XHJcbiAgICAgICAgaWYgKGdsdGZQcm9wLmV4dHJhcyAmJiBPYmplY3Qua2V5cyhnbHRmUHJvcC5leHRyYXMpLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgY29uc3QgbWV0YWRhdGEgPSAoYmFieWxvbk9iamVjdC5tZXRhZGF0YSA9IGJhYnlsb25PYmplY3QubWV0YWRhdGEgfHwge30pO1xyXG4gICAgICAgICAgICBjb25zdCBnbHRmID0gKG1ldGFkYXRhLmdsdGYgPSBtZXRhZGF0YS5nbHRmIHx8IHt9KTtcclxuICAgICAgICAgICAgZ2x0Zi5leHRyYXMgPSBnbHRmUHJvcC5leHRyYXM7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjb25zdHJ1Y3Rvcihsb2FkZXI6IEdMVEZMb2FkZXIpIHtcclxuICAgICAgICB0aGlzLl9sb2FkZXIgPSBsb2FkZXI7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKTogdm9pZCB7XHJcbiAgICAgICAgKHRoaXMuX2xvYWRlciBhcyBhbnkpID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZE5vZGVBc3luYyhjb250ZXh0OiBzdHJpbmcsIG5vZGU6IElOb2RlLCBhc3NpZ246IChiYWJ5bG9uVHJhbnNmb3JtTm9kZTogVHJhbnNmb3JtTm9kZSkgPT4gdm9pZCk6IE51bGxhYmxlPFByb21pc2U8VHJhbnNmb3JtTm9kZT4+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fbG9hZGVyLmxvYWROb2RlQXN5bmMoY29udGV4dCwgbm9kZSwgKGJhYnlsb25UcmFuc2Zvcm1Ob2RlKTogdm9pZCA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuX2Fzc2lnbkV4dHJhcyhiYWJ5bG9uVHJhbnNmb3JtTm9kZSwgbm9kZSk7XHJcbiAgICAgICAgICAgIGFzc2lnbihiYWJ5bG9uVHJhbnNmb3JtTm9kZSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRDYW1lcmFBc3luYyhjb250ZXh0OiBzdHJpbmcsIGNhbWVyYTogSUNhbWVyYSwgYXNzaWduOiAoYmFieWxvbkNhbWVyYTogQ2FtZXJhKSA9PiB2b2lkKTogTnVsbGFibGU8UHJvbWlzZTxDYW1lcmE+PiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xvYWRlci5sb2FkQ2FtZXJhQXN5bmMoY29udGV4dCwgY2FtZXJhLCAoYmFieWxvbkNhbWVyYSk6IHZvaWQgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLl9hc3NpZ25FeHRyYXMoYmFieWxvbkNhbWVyYSwgY2FtZXJhKTtcclxuICAgICAgICAgICAgYXNzaWduKGJhYnlsb25DYW1lcmEpO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjcmVhdGVNYXRlcmlhbChjb250ZXh0OiBzdHJpbmcsIG1hdGVyaWFsOiBJTWF0ZXJpYWwsIGJhYnlsb25EcmF3TW9kZTogbnVtYmVyKTogTnVsbGFibGU8TWF0ZXJpYWw+IHtcclxuICAgICAgICBjb25zdCBiYWJ5bG9uTWF0ZXJpYWwgPSB0aGlzLl9sb2FkZXIuY3JlYXRlTWF0ZXJpYWwoY29udGV4dCwgbWF0ZXJpYWwsIGJhYnlsb25EcmF3TW9kZSk7XHJcbiAgICAgICAgdGhpcy5fYXNzaWduRXh0cmFzKGJhYnlsb25NYXRlcmlhbCwgbWF0ZXJpYWwpO1xyXG4gICAgICAgIHJldHVybiBiYWJ5bG9uTWF0ZXJpYWw7XHJcbiAgICB9XHJcbn1cclxuXHJcbkdMVEZMb2FkZXIuUmVnaXN0ZXJFeHRlbnNpb24oTkFNRSwgKGxvYWRlcik6IElHTFRGTG9hZGVyRXh0ZW5zaW9uID0+IG5ldyBFeHRyYXNBc01ldGFkYXRhKGxvYWRlcikpO1xyXG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb24gKi9cclxuXHJcbmltcG9ydCB7IEFuaW1hdGlvbiB9IGZyb20gXCJjb3JlL0FuaW1hdGlvbnMvYW5pbWF0aW9uXCI7XHJcbmltcG9ydCB0eXBlIHsgSUNhbWVyYSwgSUtIUkxpZ2h0c1B1bmN0dWFsX0xpZ2h0LCBJTWF0ZXJpYWwgfSBmcm9tIFwiLi4vZ2xURkxvYWRlckludGVyZmFjZXNcIjtcclxuaW1wb3J0IHR5cGUgeyBJQW5pbWF0YWJsZSB9IGZyb20gXCJjb3JlL0FuaW1hdGlvbnMvYW5pbWF0YWJsZS5pbnRlcmZhY2VcIjtcclxuaW1wb3J0IHsgQW5pbWF0aW9uUHJvcGVydHlJbmZvLCBub2RlQW5pbWF0aW9uRGF0YSB9IGZyb20gXCIuLi9nbFRGTG9hZGVyQW5pbWF0aW9uXCI7XHJcbmltcG9ydCB7IENvbG9yMyB9IGZyb20gXCJjb3JlL01hdGhzL21hdGguY29sb3JcIjtcclxuXHJcbmZ1bmN0aW9uIGdldENvbG9yMyhfdGFyZ2V0OiBhbnksIHNvdXJjZTogRmxvYXQzMkFycmF5LCBvZmZzZXQ6IG51bWJlciwgc2NhbGU6IG51bWJlcik6IENvbG9yMyB7XHJcbiAgICByZXR1cm4gQ29sb3IzLkZyb21BcnJheShzb3VyY2UsIG9mZnNldCkuc2NhbGUoc2NhbGUpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRBbHBoYShfdGFyZ2V0OiBhbnksIHNvdXJjZTogRmxvYXQzMkFycmF5LCBvZmZzZXQ6IG51bWJlciwgc2NhbGU6IG51bWJlcik6IG51bWJlciB7XHJcbiAgICByZXR1cm4gc291cmNlW29mZnNldCArIDNdICogc2NhbGU7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIGdldEZsb2F0KF90YXJnZXQ6IGFueSwgc291cmNlOiBGbG9hdDMyQXJyYXksIG9mZnNldDogbnVtYmVyLCBzY2FsZTogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgIHJldHVybiBzb3VyY2Vbb2Zmc2V0XSAqIHNjYWxlO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRNaW51c0Zsb2F0KF90YXJnZXQ6IGFueSwgc291cmNlOiBGbG9hdDMyQXJyYXksIG9mZnNldDogbnVtYmVyLCBzY2FsZTogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgIHJldHVybiAtc291cmNlW29mZnNldF0gKiBzY2FsZTtcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0TmV4dEZsb2F0KF90YXJnZXQ6IGFueSwgc291cmNlOiBGbG9hdDMyQXJyYXksIG9mZnNldDogbnVtYmVyLCBzY2FsZTogbnVtYmVyKTogbnVtYmVyIHtcclxuICAgIHJldHVybiBzb3VyY2Vbb2Zmc2V0ICsgMV0gKiBzY2FsZTtcclxufVxyXG5cclxuZnVuY3Rpb24gZ2V0RmxvYXRCeTIoX3RhcmdldDogYW55LCBzb3VyY2U6IEZsb2F0MzJBcnJheSwgb2Zmc2V0OiBudW1iZXIsIHNjYWxlOiBudW1iZXIpOiBudW1iZXIge1xyXG4gICAgcmV0dXJuIHNvdXJjZVtvZmZzZXRdICogc2NhbGUgKiAyO1xyXG59XHJcblxyXG5mdW5jdGlvbiBnZXRUZXh0dXJlVHJhbnNmb3JtVHJlZSh0ZXh0dXJlTmFtZTogc3RyaW5nKSB7XHJcbiAgICByZXR1cm4ge1xyXG4gICAgICAgIHNjYWxlOiBbXHJcbiAgICAgICAgICAgIG5ldyBNYXRlcmlhbEFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgYCR7dGV4dHVyZU5hbWV9LnVTY2FsZWAsIGdldEZsb2F0LCAoKSA9PiAyKSxcclxuICAgICAgICAgICAgbmV3IE1hdGVyaWFsQW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX0ZMT0FULCBgJHt0ZXh0dXJlTmFtZX0udlNjYWxlYCwgZ2V0TmV4dEZsb2F0LCAoKSA9PiAyKSxcclxuICAgICAgICBdLFxyXG4gICAgICAgIG9mZnNldDogW1xyXG4gICAgICAgICAgICBuZXcgTWF0ZXJpYWxBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIGAke3RleHR1cmVOYW1lfS51T2Zmc2V0YCwgZ2V0RmxvYXQsICgpID0+IDIpLFxyXG4gICAgICAgICAgICBuZXcgTWF0ZXJpYWxBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIGAke3RleHR1cmVOYW1lfS52T2Zmc2V0YCwgZ2V0TmV4dEZsb2F0LCAoKSA9PiAyKSxcclxuICAgICAgICBdLFxyXG4gICAgICAgIHJvdGF0aW9uOiBbbmV3IE1hdGVyaWFsQW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX0ZMT0FULCBgJHt0ZXh0dXJlTmFtZX0ud0FuZ2AsIGdldE1pbnVzRmxvYXQsICgpID0+IDEpXSxcclxuICAgIH07XHJcbn1cclxuXHJcbmNsYXNzIENhbWVyYUFuaW1hdGlvblByb3BlcnR5SW5mbyBleHRlbmRzIEFuaW1hdGlvblByb3BlcnR5SW5mbyB7XHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgYnVpbGRBbmltYXRpb25zKHRhcmdldDogSUNhbWVyYSwgbmFtZTogc3RyaW5nLCBmcHM6IG51bWJlciwga2V5czogYW55W10sIGNhbGxiYWNrOiAoYmFieWxvbkFuaW1hdGFibGU6IElBbmltYXRhYmxlLCBiYWJ5bG9uQW5pbWF0aW9uOiBBbmltYXRpb24pID0+IHZvaWQpOiB2b2lkIHtcclxuICAgICAgICBjYWxsYmFjayh0YXJnZXQuX2JhYnlsb25DYW1lcmEhLCB0aGlzLl9idWlsZEFuaW1hdGlvbihuYW1lLCBmcHMsIGtleXMpKTtcclxuICAgIH1cclxufVxyXG5cclxuY2xhc3MgTWF0ZXJpYWxBbmltYXRpb25Qcm9wZXJ0eUluZm8gZXh0ZW5kcyBBbmltYXRpb25Qcm9wZXJ0eUluZm8ge1xyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGJ1aWxkQW5pbWF0aW9ucyh0YXJnZXQ6IElNYXRlcmlhbCwgbmFtZTogc3RyaW5nLCBmcHM6IG51bWJlciwga2V5czogYW55W10sIGNhbGxiYWNrOiAoYmFieWxvbkFuaW1hdGFibGU6IElBbmltYXRhYmxlLCBiYWJ5bG9uQW5pbWF0aW9uOiBBbmltYXRpb24pID0+IHZvaWQpOiB2b2lkIHtcclxuICAgICAgICBmb3IgKGNvbnN0IGZpbGxNb2RlIGluIHRhcmdldC5fZGF0YSEpIHtcclxuICAgICAgICAgICAgY2FsbGJhY2sodGFyZ2V0Ll9kYXRhIVtmaWxsTW9kZV0uYmFieWxvbk1hdGVyaWFsLCB0aGlzLl9idWlsZEFuaW1hdGlvbihuYW1lLCBmcHMsIGtleXMpKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbmNsYXNzIExpZ2h0QW5pbWF0aW9uUHJvcGVydHlJbmZvIGV4dGVuZHMgQW5pbWF0aW9uUHJvcGVydHlJbmZvIHtcclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBidWlsZEFuaW1hdGlvbnMoXHJcbiAgICAgICAgdGFyZ2V0OiBJS0hSTGlnaHRzUHVuY3R1YWxfTGlnaHQsXHJcbiAgICAgICAgbmFtZTogc3RyaW5nLFxyXG4gICAgICAgIGZwczogbnVtYmVyLFxyXG4gICAgICAgIGtleXM6IGFueVtdLFxyXG4gICAgICAgIGNhbGxiYWNrOiAoYmFieWxvbkFuaW1hdGFibGU6IElBbmltYXRhYmxlLCBiYWJ5bG9uQW5pbWF0aW9uOiBBbmltYXRpb24pID0+IHZvaWRcclxuICAgICk6IHZvaWQge1xyXG4gICAgICAgIGNhbGxiYWNrKHRhcmdldC5fYmFieWxvbkxpZ2h0ISwgdGhpcy5fYnVpbGRBbmltYXRpb24obmFtZSwgZnBzLCBrZXlzKSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbmNvbnN0IG5vZGVzVHJlZSA9IHtcclxuICAgIF9fYXJyYXlfXzoge1xyXG4gICAgICAgIF9fdGFyZ2V0X186IHRydWUsXHJcbiAgICAgICAgLi4ubm9kZUFuaW1hdGlvbkRhdGEsXHJcbiAgICB9LFxyXG59O1xyXG5cclxuY29uc3QgY2FtZXJhc1RyZWUgPSB7XHJcbiAgICBfX2FycmF5X186IHtcclxuICAgICAgICBfX3RhcmdldF9fOiB0cnVlLFxyXG4gICAgICAgIG9ydGhvZ3JhcGhpYzoge1xyXG4gICAgICAgICAgICB4bWFnOiBbXHJcbiAgICAgICAgICAgICAgICBuZXcgQ2FtZXJhQW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX0ZMT0FULCBcIm9ydGhvTGVmdFwiLCBnZXRNaW51c0Zsb2F0LCAoKSA9PiAxKSxcclxuICAgICAgICAgICAgICAgIG5ldyBDYW1lcmFBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIFwib3J0aG9SaWdodFwiLCBnZXROZXh0RmxvYXQsICgpID0+IDEpLFxyXG4gICAgICAgICAgICBdLFxyXG4gICAgICAgICAgICB5bWFnOiBbXHJcbiAgICAgICAgICAgICAgICBuZXcgQ2FtZXJhQW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX0ZMT0FULCBcIm9ydGhvQm90dG9tXCIsIGdldE1pbnVzRmxvYXQsICgpID0+IDEpLFxyXG4gICAgICAgICAgICAgICAgbmV3IENhbWVyYUFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJvcnRob1RvcFwiLCBnZXROZXh0RmxvYXQsICgpID0+IDEpLFxyXG4gICAgICAgICAgICBdLFxyXG4gICAgICAgICAgICB6ZmFyOiBbbmV3IENhbWVyYUFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJtYXhaXCIsIGdldEZsb2F0LCAoKSA9PiAxKV0sXHJcbiAgICAgICAgICAgIHpuZWFyOiBbbmV3IENhbWVyYUFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJtaW5aXCIsIGdldEZsb2F0LCAoKSA9PiAxKV0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICBwZXJzcGVjdGl2ZToge1xyXG4gICAgICAgICAgICB5Zm92OiBbbmV3IENhbWVyYUFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJmb3ZcIiwgZ2V0RmxvYXQsICgpID0+IDEpXSxcclxuICAgICAgICAgICAgemZhcjogW25ldyBDYW1lcmFBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIFwibWF4WlwiLCBnZXRGbG9hdCwgKCkgPT4gMSldLFxyXG4gICAgICAgICAgICB6bmVhcjogW25ldyBDYW1lcmFBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIFwibWluWlwiLCBnZXRGbG9hdCwgKCkgPT4gMSldLFxyXG4gICAgICAgIH0sXHJcbiAgICB9LFxyXG59O1xyXG5cclxuY29uc3QgbWF0ZXJpYWxzVHJlZSA9IHtcclxuICAgIF9fYXJyYXlfXzoge1xyXG4gICAgICAgIF9fdGFyZ2V0X186IHRydWUsXHJcbiAgICAgICAgcGJyTWV0YWxsaWNSb3VnaG5lc3M6IHtcclxuICAgICAgICAgICAgYmFzZUNvbG9yRmFjdG9yOiBbXHJcbiAgICAgICAgICAgICAgICBuZXcgTWF0ZXJpYWxBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfQ09MT1IzLCBcImFsYmVkb0NvbG9yXCIsIGdldENvbG9yMywgKCkgPT4gNCksXHJcbiAgICAgICAgICAgICAgICBuZXcgTWF0ZXJpYWxBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIFwiYWxwaGFcIiwgZ2V0QWxwaGEsICgpID0+IDQpLFxyXG4gICAgICAgICAgICBdLFxyXG4gICAgICAgICAgICBtZXRhbGxpY0ZhY3RvcjogW25ldyBNYXRlcmlhbEFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJtZXRhbGxpY1wiLCBnZXRGbG9hdCwgKCkgPT4gMSldLFxyXG4gICAgICAgICAgICByb3VnaG5lc3NGYWN0b3I6IFtuZXcgTWF0ZXJpYWxBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIFwicm91Z2huZXNzXCIsIGdldEZsb2F0LCAoKSA9PiAxKV0sXHJcbiAgICAgICAgICAgIGJhc2VDb2xvclRleHR1cmU6IHtcclxuICAgICAgICAgICAgICAgIGV4dGVuc2lvbnM6IHtcclxuICAgICAgICAgICAgICAgICAgICBLSFJfdGV4dHVyZV90cmFuc2Zvcm06IGdldFRleHR1cmVUcmFuc2Zvcm1UcmVlKFwiYWxiZWRvVGV4dHVyZVwiKSxcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICBlbWlzc2l2ZUZhY3RvcjogW25ldyBNYXRlcmlhbEFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9DT0xPUjMsIFwiZW1pc3NpdmVDb2xvclwiLCBnZXRDb2xvcjMsICgpID0+IDMpXSxcclxuICAgICAgICBub3JtYWxUZXh0dXJlOiB7XHJcbiAgICAgICAgICAgIHNjYWxlOiBbbmV3IE1hdGVyaWFsQW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX0ZMT0FULCBcImJ1bXBUZXh0dXJlLmxldmVsXCIsIGdldEZsb2F0LCAoKSA9PiAxKV0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICBvY2NsdXNpb25UZXh0dXJlOiB7XHJcbiAgICAgICAgICAgIHN0cmVuZ3RoOiBbbmV3IE1hdGVyaWFsQW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX0ZMT0FULCBcImFtYmllbnRUZXh0dXJlU3RyZW5ndGhcIiwgZ2V0RmxvYXQsICgpID0+IDEpXSxcclxuICAgICAgICAgICAgZXh0ZW5zaW9uczoge1xyXG4gICAgICAgICAgICAgICAgS0hSX3RleHR1cmVfdHJhbnNmb3JtOiBnZXRUZXh0dXJlVHJhbnNmb3JtVHJlZShcImFtYmllbnRUZXh0dXJlXCIpLFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgIH0sXHJcbiAgICAgICAgZW1pc3NpdmVUZXh0dXJlOiB7XHJcbiAgICAgICAgICAgIGV4dGVuc2lvbnM6IHtcclxuICAgICAgICAgICAgICAgIEtIUl90ZXh0dXJlX3RyYW5zZm9ybTogZ2V0VGV4dHVyZVRyYW5zZm9ybVRyZWUoXCJlbWlzc2l2ZVRleHR1cmVcIiksXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgfSxcclxuICAgICAgICBleHRlbnNpb25zOiB7XHJcbiAgICAgICAgICAgIEtIUl9tYXRlcmlhbHNfaW9yOiB7XHJcbiAgICAgICAgICAgICAgICBpb3I6IFtuZXcgTWF0ZXJpYWxBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIFwiaW5kZXhPZlJlZnJhY3Rpb25cIiwgZ2V0RmxvYXQsICgpID0+IDEpXSxcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgS0hSX21hdGVyaWFsc19jbGVhcmNvYXQ6IHtcclxuICAgICAgICAgICAgICAgIGNsZWFyY29hdEZhY3RvcjogW25ldyBNYXRlcmlhbEFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJjbGVhckNvYXQuaW50ZW5zaXR5XCIsIGdldEZsb2F0LCAoKSA9PiAxKV0sXHJcbiAgICAgICAgICAgICAgICBjbGVhcmNvYXRSb3VnaG5lc3NGYWN0b3I6IFtuZXcgTWF0ZXJpYWxBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIFwiY2xlYXJDb2F0LnJvdWdobmVzc1wiLCBnZXRGbG9hdCwgKCkgPT4gMSldLFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBLSFJfbWF0ZXJpYWxzX3NoZWVuOiB7XHJcbiAgICAgICAgICAgICAgICBzaGVlbkNvbG9yRmFjdG9yOiBbbmV3IE1hdGVyaWFsQW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX0NPTE9SMywgXCJzaGVlbi5jb2xvclwiLCBnZXRDb2xvcjMsICgpID0+IDMpXSxcclxuICAgICAgICAgICAgICAgIHNoZWVuUm91Z2huZXNzRmFjdG9yOiBbbmV3IE1hdGVyaWFsQW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX0ZMT0FULCBcInNoZWVuLnJvdWdobmVzc1wiLCBnZXRGbG9hdCwgKCkgPT4gMSldLFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBLSFJfbWF0ZXJpYWxzX3NwZWN1bGFyOiB7XHJcbiAgICAgICAgICAgICAgICBzcGVjdWxhckZhY3RvcjogW25ldyBNYXRlcmlhbEFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJtZXRhbGxpY0YwRmFjdG9yXCIsIGdldEZsb2F0LCAoKSA9PiAxKV0sXHJcbiAgICAgICAgICAgICAgICBzcGVjdWxhckNvbG9yRmFjdG9yOiBbbmV3IE1hdGVyaWFsQW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX0NPTE9SMywgXCJtZXRhbGxpY1JlZmxlY3RhbmNlQ29sb3JcIiwgZ2V0Q29sb3IzLCAoKSA9PiAzKV0sXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIEtIUl9tYXRlcmlhbHNfZW1pc3NpdmVfc3RyZW5ndGg6IHtcclxuICAgICAgICAgICAgICAgIGVtaXNzaXZlU3RyZW5ndGg6IFtuZXcgTWF0ZXJpYWxBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIFwiZW1pc3NpdmVJbnRlbnNpdHlcIiwgZ2V0RmxvYXQsICgpID0+IDEpXSxcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgS0hSX21hdGVyaWFsc190cmFuc21pc3Npb246IHtcclxuICAgICAgICAgICAgICAgIHRyYW5zbWlzc2lvbkZhY3RvcjogW25ldyBNYXRlcmlhbEFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJzdWJTdXJmYWNlLnJlZnJhY3Rpb25JbnRlbnNpdHlcIiwgZ2V0RmxvYXQsICgpID0+IDEpXSxcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgS0hSX21hdGVyaWFsc192b2x1bWU6IHtcclxuICAgICAgICAgICAgICAgIGF0dGVudWF0aW9uQ29sb3I6IFtuZXcgTWF0ZXJpYWxBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfQ09MT1IzLCBcInN1YlN1cmZhY2UudGludENvbG9yXCIsIGdldENvbG9yMywgKCkgPT4gMyldLFxyXG4gICAgICAgICAgICAgICAgYXR0ZW51YXRpb25EaXN0YW5jZTogW25ldyBNYXRlcmlhbEFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJzdWJTdXJmYWNlLnRpbnRDb2xvckF0RGlzdGFuY2VcIiwgZ2V0RmxvYXQsICgpID0+IDEpXSxcclxuICAgICAgICAgICAgICAgIHRoaWNrbmVzc0ZhY3RvcjogW25ldyBNYXRlcmlhbEFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJzdWJTdXJmYWNlLm1heGltdW1UaGlja25lc3NcIiwgZ2V0RmxvYXQsICgpID0+IDEpXSxcclxuICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgS0hSX21hdGVyaWFsc19pcmlkZXNjZW5jZToge1xyXG4gICAgICAgICAgICAgICAgaXJpZGVzY2VuY2VGYWN0b3I6IFtuZXcgTWF0ZXJpYWxBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIFwiaXJpZGVzY2VuY2UuaW50ZW5zaXR5XCIsIGdldEZsb2F0LCAoKSA9PiAxKV0sXHJcbiAgICAgICAgICAgICAgICBpcmlkZXNjZW5jZUlvcjogW25ldyBNYXRlcmlhbEFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJpcmlkZXNjZW5jZS5pbmRleE9mUmVmcmFjdGlvblwiLCBnZXRGbG9hdCwgKCkgPT4gMSldLFxyXG4gICAgICAgICAgICAgICAgaXJpZGVzY2VuY2VUaGlja25lc3NNaW5pbXVtOiBbbmV3IE1hdGVyaWFsQW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX0ZMT0FULCBcImlyaWRlc2NlbmNlLm1pbmltdW1UaGlja25lc3NcIiwgZ2V0RmxvYXQsICgpID0+IDEpXSxcclxuICAgICAgICAgICAgICAgIGlyaWRlc2NlbmNlVGhpY2tuZXNzTWF4aW11bTogW25ldyBNYXRlcmlhbEFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJpcmlkZXNjZW5jZS5tYXhpbXVtVGhpY2tuZXNzXCIsIGdldEZsb2F0LCAoKSA9PiAxKV0sXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIEtIUl9tYXRlcmlhbHNfYW5pc290cm9weToge1xyXG4gICAgICAgICAgICAgICAgYW5pc290cm9weVN0cmVuZ3RoOiBbbmV3IE1hdGVyaWFsQW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX0ZMT0FULCBcImFuaXNvdHJvcHkuaW50ZW5zaXR5XCIsIGdldEZsb2F0LCAoKSA9PiAxKV0sXHJcbiAgICAgICAgICAgICAgICBhbmlzb3Ryb3B5Um90YXRpb246IFtuZXcgTWF0ZXJpYWxBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIFwiYW5pc290cm9weS5hbmdsZVwiLCBnZXRGbG9hdCwgKCkgPT4gMSldLFxyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgIH0sXHJcbiAgICB9LFxyXG59O1xyXG5cclxuY29uc3QgZXh0ZW5zaW9uc1RyZWUgPSB7XHJcbiAgICBLSFJfbGlnaHRzX3B1bmN0dWFsOiB7XHJcbiAgICAgICAgbGlnaHRzOiB7XHJcbiAgICAgICAgICAgIF9fYXJyYXlfXzoge1xyXG4gICAgICAgICAgICAgICAgX190YXJnZXRfXzogdHJ1ZSxcclxuICAgICAgICAgICAgICAgIGNvbG9yOiBbbmV3IExpZ2h0QW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX0NPTE9SMywgXCJkaWZmdXNlXCIsIGdldENvbG9yMywgKCkgPT4gMyldLFxyXG4gICAgICAgICAgICAgICAgaW50ZW5zaXR5OiBbbmV3IExpZ2h0QW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX0ZMT0FULCBcImludGVuc2l0eVwiLCBnZXRGbG9hdCwgKCkgPT4gMSldLFxyXG4gICAgICAgICAgICAgICAgcmFuZ2U6IFtuZXcgTGlnaHRBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIFwicmFuZ2VcIiwgZ2V0RmxvYXQsICgpID0+IDEpXSxcclxuICAgICAgICAgICAgICAgIHNwb3Q6IHtcclxuICAgICAgICAgICAgICAgICAgICBpbm5lckNvbmVBbmdsZTogW25ldyBMaWdodEFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJpbm5lckFuZ2xlXCIsIGdldEZsb2F0QnkyLCAoKSA9PiAxKV0sXHJcbiAgICAgICAgICAgICAgICAgICAgb3V0ZXJDb25lQW5nbGU6IFtuZXcgTGlnaHRBbmltYXRpb25Qcm9wZXJ0eUluZm8oQW5pbWF0aW9uLkFOSU1BVElPTlRZUEVfRkxPQVQsIFwiYW5nbGVcIiwgZ2V0RmxvYXRCeTIsICgpID0+IDEpXSxcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgfSxcclxuICAgIH0sXHJcbn07XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBjb25zdCBhbmltYXRpb25Qb2ludGVyVHJlZSA9IHtcclxuICAgIG5vZGVzOiBub2Rlc1RyZWUsXHJcbiAgICBtYXRlcmlhbHM6IG1hdGVyaWFsc1RyZWUsXHJcbiAgICBjYW1lcmFzOiBjYW1lcmFzVHJlZSxcclxuICAgIGV4dGVuc2lvbnM6IGV4dGVuc2lvbnNUcmVlLFxyXG59O1xyXG4iLCJpbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgSUFuaW1hdGlvblRhcmdldEluZm8gfSBmcm9tIFwiLi4vZ2xURkxvYWRlclwiO1xyXG5pbXBvcnQgdHlwZSB7IE51bGxhYmxlIH0gZnJvbSBcImNvcmUvdHlwZXNcIjtcclxuaW1wb3J0IHR5cGUgeyBBbmltYXRpb24gfSBmcm9tIFwiY29yZS9BbmltYXRpb25zL2FuaW1hdGlvblwiO1xyXG5pbXBvcnQgdHlwZSB7IElBbmltYXRhYmxlIH0gZnJvbSBcImNvcmUvQW5pbWF0aW9ucy9hbmltYXRhYmxlLmludGVyZmFjZVwiO1xyXG5pbXBvcnQgdHlwZSB7IElBbmltYXRpb24sIElBbmltYXRpb25DaGFubmVsIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcbmltcG9ydCB0eXBlIHsgSUtIUkFuaW1hdGlvblBvaW50ZXIgfSBmcm9tIFwiYmFieWxvbmpzLWdsdGYyaW50ZXJmYWNlXCI7XHJcbmltcG9ydCB7IEFuaW1hdGlvbkNoYW5uZWxUYXJnZXRQYXRoIH0gZnJvbSBcImJhYnlsb25qcy1nbHRmMmludGVyZmFjZVwiO1xyXG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tIFwiY29yZS9NaXNjL2xvZ2dlclwiO1xyXG5pbXBvcnQgeyBhbmltYXRpb25Qb2ludGVyVHJlZSB9IGZyb20gXCIuL0tIUl9hbmltYXRpb25fcG9pbnRlci5kYXRhXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJLSFJfYW5pbWF0aW9uX3BvaW50ZXJcIjtcclxuXHJcbi8qKlxyXG4gKiBbU3BlY2lmaWNhdGlvbiBQUl0oaHR0cHM6Ly9naXRodWIuY29tL0tocm9ub3NHcm91cC9nbFRGL3B1bGwvMjE0NylcclxuICogISEhIEV4cGVyaW1lbnRhbCBFeHRlbnNpb24gU3ViamVjdCB0byBDaGFuZ2VzICEhIVxyXG4gKi9cclxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxyXG5leHBvcnQgY2xhc3MgS0hSX2FuaW1hdGlvbl9wb2ludGVyIGltcGxlbWVudHMgSUdMVEZMb2FkZXJFeHRlbnNpb24ge1xyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGlzIGV4dGVuc2lvbi5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHJlYWRvbmx5IG5hbWUgPSBOQU1FO1xyXG5cclxuICAgIHByaXZhdGUgX2xvYWRlcjogR0xURkxvYWRlcjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3Rvcihsb2FkZXI6IEdMVEZMb2FkZXIpIHtcclxuICAgICAgICB0aGlzLl9sb2FkZXIgPSBsb2FkZXI7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldCBlbmFibGVkKCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9sb2FkZXIuaXNFeHRlbnNpb25Vc2VkKE5BTUUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBkaXNwb3NlKCkge1xyXG4gICAgICAgICh0aGlzLl9sb2FkZXIgYXMgYW55KSA9IG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBMb2FkcyBhIGdsVEYgYW5pbWF0aW9uIGNoYW5uZWwuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gYW5pbWF0aW9uQ29udGV4dCBUaGUgY29udGV4dCBvZiB0aGUgYW5pbWF0aW9uIHdoZW4gbG9hZGluZyB0aGUgYXNzZXRcclxuICAgICAqIEBwYXJhbSBhbmltYXRpb24gVGhlIGdsVEYgYW5pbWF0aW9uIHByb3BlcnR5XHJcbiAgICAgKiBAcGFyYW0gY2hhbm5lbCBUaGUgZ2xURiBhbmltYXRpb24gY2hhbm5lbCBwcm9wZXJ0eVxyXG4gICAgICogQHBhcmFtIG9uTG9hZCBDYWxsZWQgZm9yIGVhY2ggYW5pbWF0aW9uIGxvYWRlZFxyXG4gICAgICogQHJldHVybnMgQSB2b2lkIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBsb2FkIGlzIGNvbXBsZXRlIG9yIG51bGwgaWYgbm90IGhhbmRsZWRcclxuICAgICAqL1xyXG4gICAgcHVibGljIF9sb2FkQW5pbWF0aW9uQ2hhbm5lbEFzeW5jKFxyXG4gICAgICAgIGNvbnRleHQ6IHN0cmluZyxcclxuICAgICAgICBhbmltYXRpb25Db250ZXh0OiBzdHJpbmcsXHJcbiAgICAgICAgYW5pbWF0aW9uOiBJQW5pbWF0aW9uLFxyXG4gICAgICAgIGNoYW5uZWw6IElBbmltYXRpb25DaGFubmVsLFxyXG4gICAgICAgIG9uTG9hZDogKGJhYnlsb25BbmltYXRhYmxlOiBJQW5pbWF0YWJsZSwgYmFieWxvbkFuaW1hdGlvbjogQW5pbWF0aW9uKSA9PiB2b2lkXHJcbiAgICApOiBOdWxsYWJsZTxQcm9taXNlPHZvaWQ+PiB7XHJcbiAgICAgICAgY29uc3QgZXh0ZW5zaW9uID0gY2hhbm5lbC50YXJnZXQuZXh0ZW5zaW9ucz8uS0hSX2FuaW1hdGlvbl9wb2ludGVyIGFzIElLSFJBbmltYXRpb25Qb2ludGVyO1xyXG4gICAgICAgIGlmICghZXh0ZW5zaW9uKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGNoYW5uZWwudGFyZ2V0LnBhdGggIT09IEFuaW1hdGlvbkNoYW5uZWxUYXJnZXRQYXRoLlBPSU5URVIpIHtcclxuICAgICAgICAgICAgTG9nZ2VyLldhcm4oYCR7Y29udGV4dH0vdGFyZ2V0L3BhdGg6IFZhbHVlICgke2NoYW5uZWwudGFyZ2V0LnBhdGh9KSBtdXN0IGJlICgke0FuaW1hdGlvbkNoYW5uZWxUYXJnZXRQYXRoLlBPSU5URVJ9KSB3aGVuIHVzaW5nIHRoZSAke3RoaXMubmFtZX0gZXh0ZW5zaW9uYCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoY2hhbm5lbC50YXJnZXQubm9kZSAhPSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgTG9nZ2VyLldhcm4oYCR7Y29udGV4dH0vdGFyZ2V0L25vZGU6IFZhbHVlICgke2NoYW5uZWwudGFyZ2V0Lm5vZGV9KSBtdXN0IG5vdCBiZSBwcmVzZW50IHdoZW4gdXNpbmcgdGhlICR7dGhpcy5uYW1lfSBleHRlbnNpb25gKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGV4dGVuc2lvbkNvbnRleHQgPSBgJHtjb250ZXh0fS9leHRlbnNpb25zLyR7dGhpcy5uYW1lfWA7XHJcblxyXG4gICAgICAgIGNvbnN0IHBvaW50ZXIgPSBleHRlbnNpb24ucG9pbnRlcjtcclxuICAgICAgICBpZiAoIXBvaW50ZXIpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2V4dGVuc2lvbkNvbnRleHR9OiBQb2ludGVyIGlzIG1pc3NpbmdgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHRhcmdldEluZm8gPSB0aGlzLl9wYXJzZUFuaW1hdGlvblBvaW50ZXIoYCR7ZXh0ZW5zaW9uQ29udGV4dH0vcG9pbnRlcmAsIHBvaW50ZXIpO1xyXG4gICAgICAgIGlmICghdGFyZ2V0SW5mbykge1xyXG4gICAgICAgICAgICBMb2dnZXIuV2FybihgJHtleHRlbnNpb25Db250ZXh0fS9wb2ludGVyOiBJbnZhbGlkIHBvaW50ZXIgKCR7cG9pbnRlcn0pIHNraXBwZWRgKTtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdGhpcy5fbG9hZGVyLl9sb2FkQW5pbWF0aW9uQ2hhbm5lbEZyb21UYXJnZXRJbmZvQXN5bmMoY29udGV4dCwgYW5pbWF0aW9uQ29udGV4dCwgYW5pbWF0aW9uLCBjaGFubmVsLCB0YXJnZXRJbmZvLCBvbkxvYWQpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIHBvaW50ZXIgc3RyaW5nIGlzIHJlcHJlc2VudGVkIGJ5IGEgW0pTT04gcG9pbnRlcl0oaHR0cHM6Ly9kYXRhdHJhY2tlci5pZXRmLm9yZy9kb2MvaHRtbC9yZmM2OTAxKS5cclxuICAgICAqIDxhbmltYXRpb25Qb2ludGVyPiA6PSAvPHJvb3ROb2RlPi88YXNzZXRJbmRleD4vPHByb3BlcnR5UGF0aD5cclxuICAgICAqIDxyb290Tm9kZT4gOj0gXCJub2Rlc1wiIHwgXCJtYXRlcmlhbHNcIiB8IFwibWVzaGVzXCIgfCBcImNhbWVyYXNcIiB8IFwiZXh0ZW5zaW9uc1wiXHJcbiAgICAgKiA8YXNzZXRJbmRleD4gOj0gPGRpZ2l0PiB8IDxuYW1lPlxyXG4gICAgICogPHByb3BlcnR5UGF0aD4gOj0gPGV4dGVuc2lvblBhdGg+IHwgPHN0YW5kYXJkUGF0aD5cclxuICAgICAqIDxleHRlbnNpb25QYXRoPiA6PSBcImV4dGVuc2lvbnNcIi88bmFtZT4vPHN0YW5kYXJkUGF0aD5cclxuICAgICAqIDxzdGFuZGFyZFBhdGg+IDo9IDxuYW1lPiB8IDxuYW1lPi88c3RhbmRhcmRQYXRoPlxyXG4gICAgICogPG5hbWU+IDo9IFcrXHJcbiAgICAgKiA8ZGlnaXQ+IDo9IEQrXHJcbiAgICAgKlxyXG4gICAgICogRXhhbXBsZXM6XHJcbiAgICAgKiAgLSBcIi9ub2Rlcy8wL3JvdGF0aW9uXCJcclxuICAgICAqICAtIFwiL21hdGVyaWFscy8yL2VtaXNzaXZlRmFjdG9yXCJcclxuICAgICAqICAtIFwiL21hdGVyaWFscy8yL3Bick1ldGFsbGljUm91Z2huZXNzL2Jhc2VDb2xvckZhY3RvclwiXHJcbiAgICAgKiAgLSBcIi9tYXRlcmlhbHMvMi9leHRlbnNpb25zL0tIUl9tYXRlcmlhbHNfZW1pc3NpdmVfc3RyZW5ndGgvZW1pc3NpdmVTdHJlbmd0aFwiXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgX3BhcnNlQW5pbWF0aW9uUG9pbnRlcihjb250ZXh0OiBzdHJpbmcsIHBvaW50ZXI6IHN0cmluZyk6IE51bGxhYmxlPElBbmltYXRpb25UYXJnZXRJbmZvPiB7XHJcbiAgICAgICAgaWYgKCFwb2ludGVyLnN0YXJ0c1dpdGgoXCIvXCIpKSB7XHJcbiAgICAgICAgICAgIExvZ2dlci5XYXJuKGAke2NvbnRleHR9OiBWYWx1ZSAoJHtwb2ludGVyfSkgbXVzdCBzdGFydCB3aXRoIGEgc2xhc2hgKTtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBwYXJ0cyA9IHBvaW50ZXIuc3BsaXQoXCIvXCIpO1xyXG5cclxuICAgICAgICAvLyBSZW1vdmUgdGhlIGZpcnN0IHBhcnQgc2luY2UgaXQgd2lsbCBiZSBlbXB0eSBzdHJpbmcgYXMgcG9pbnRlcnMgbXVzdCBzdGFydCB3aXRoIGEgc2xhc2guXHJcbiAgICAgICAgcGFydHMuc2hpZnQoKTtcclxuXHJcbiAgICAgICAgbGV0IG5vZGU6IGFueSA9IGFuaW1hdGlvblBvaW50ZXJUcmVlO1xyXG4gICAgICAgIGxldCBnbHRmQ3VycmVudE5vZGU6IGFueSA9IHRoaXMuX2xvYWRlci5nbHRmO1xyXG4gICAgICAgIGxldCBnbHRmVGFyZ2V0Tm9kZTogYW55ID0gdW5kZWZpbmVkO1xyXG4gICAgICAgIGZvciAoY29uc3QgcGFydCBvZiBwYXJ0cykge1xyXG4gICAgICAgICAgICBpZiAobm9kZS5fX2FycmF5X18pIHtcclxuICAgICAgICAgICAgICAgIG5vZGUgPSBub2RlLl9fYXJyYXlfXztcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIG5vZGUgPSBub2RlW3BhcnRdO1xyXG4gICAgICAgICAgICAgICAgaWYgKCFub2RlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGdsdGZDdXJyZW50Tm9kZSA9IGdsdGZDdXJyZW50Tm9kZSAmJiBnbHRmQ3VycmVudE5vZGVbcGFydF07XHJcblxyXG4gICAgICAgICAgICBpZiAobm9kZS5fX3RhcmdldF9fKSB7XHJcbiAgICAgICAgICAgICAgICBnbHRmVGFyZ2V0Tm9kZSA9IGdsdGZDdXJyZW50Tm9kZTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCFnbHRmVGFyZ2V0Tm9kZSB8fCAhQXJyYXkuaXNBcnJheShub2RlKSkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIHRhcmdldDogZ2x0ZlRhcmdldE5vZGUsXHJcbiAgICAgICAgICAgIHByb3BlcnRpZXM6IG5vZGUsXHJcbiAgICAgICAgfTtcclxuICAgIH1cclxufVxyXG5cclxuR0xURkxvYWRlci5SZWdpc3RlckV4dGVuc2lvbihOQU1FLCAobG9hZGVyKSA9PiBuZXcgS0hSX2FuaW1hdGlvbl9wb2ludGVyKGxvYWRlcikpO1xyXG4iLCJpbXBvcnQgeyBEcmFjb0NvbXByZXNzaW9uIH0gZnJvbSBcImNvcmUvTWVzaGVzL0NvbXByZXNzaW9uL2RyYWNvQ29tcHJlc3Npb25cIjtcclxuaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB7IFZlcnRleEJ1ZmZlciB9IGZyb20gXCJjb3JlL0J1ZmZlcnMvYnVmZmVyXCI7XHJcbmltcG9ydCB0eXBlIHsgR2VvbWV0cnkgfSBmcm9tIFwiY29yZS9NZXNoZXMvZ2VvbWV0cnlcIjtcclxuaW1wb3J0IHR5cGUgeyBNZXNoIH0gZnJvbSBcImNvcmUvTWVzaGVzL21lc2hcIjtcclxuXHJcbmltcG9ydCB7IE1lc2hQcmltaXRpdmVNb2RlIH0gZnJvbSBcImJhYnlsb25qcy1nbHRmMmludGVyZmFjZVwiO1xyXG5pbXBvcnQgdHlwZSB7IElLSFJEcmFjb01lc2hDb21wcmVzc2lvbiB9IGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuaW1wb3J0IHR5cGUgeyBJTWVzaFByaW1pdGl2ZSwgSUJ1ZmZlclZpZXcgfSBmcm9tIFwiLi4vZ2xURkxvYWRlckludGVyZmFjZXNcIjtcclxuaW1wb3J0IHR5cGUgeyBJR0xURkxvYWRlckV4dGVuc2lvbiB9IGZyb20gXCIuLi9nbFRGTG9hZGVyRXh0ZW5zaW9uXCI7XHJcbmltcG9ydCB7IEdMVEZMb2FkZXIsIEFycmF5SXRlbSB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJLSFJfZHJhY29fbWVzaF9jb21wcmVzc2lvblwiO1xyXG5cclxuaW50ZXJmYWNlIElCdWZmZXJWaWV3RHJhY28gZXh0ZW5kcyBJQnVmZmVyVmlldyB7XHJcbiAgICBfZHJhY29CYWJ5bG9uR2VvbWV0cnk/OiBQcm9taXNlPEdlb21ldHJ5PjtcclxufVxyXG5cclxuLyoqXHJcbiAqIFtTcGVjaWZpY2F0aW9uXShodHRwczovL2dpdGh1Yi5jb20vS2hyb25vc0dyb3VwL2dsVEYvYmxvYi9tYWluL2V4dGVuc2lvbnMvMi4wL0tocm9ub3MvS0hSX2RyYWNvX21lc2hfY29tcHJlc3Npb24vUkVBRE1FLm1kKVxyXG4gKi9cclxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxyXG5leHBvcnQgY2xhc3MgS0hSX2RyYWNvX21lc2hfY29tcHJlc3Npb24gaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgZHJhY28gY29tcHJlc3Npb24gdXNlZCB0byBkZWNvZGUgdmVydGV4IGRhdGEgb3IgRHJhY29Db21wcmVzc2lvbi5EZWZhdWx0IGlmIG5vdCBkZWZpbmVkXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBkcmFjb0NvbXByZXNzaW9uPzogRHJhY29Db21wcmVzc2lvbjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgd2hldGhlciB0aGlzIGV4dGVuc2lvbiBpcyBlbmFibGVkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZW5hYmxlZDogYm9vbGVhbjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgd2hldGhlciB0byB1c2UgdGhlIG5vcm1hbGl6ZWQgZmxhZyBmcm9tIHRoZSBnbFRGIGFjY2Vzc29yIGluc3RlYWQgb2YgdGhlIERyYWNvIGRhdGEuIERlZmF1bHRzIHRvIHRydWUuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyB1c2VOb3JtYWxpemVkRmxhZ0Zyb21BY2Nlc3NvciA9IHRydWU7XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZGVyOiBHTFRGTG9hZGVyO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKGxvYWRlcjogR0xURkxvYWRlcikge1xyXG4gICAgICAgIHRoaXMuX2xvYWRlciA9IGxvYWRlcjtcclxuICAgICAgICB0aGlzLmVuYWJsZWQgPSBEcmFjb0NvbXByZXNzaW9uLkRlY29kZXJBdmFpbGFibGUgJiYgdGhpcy5fbG9hZGVyLmlzRXh0ZW5zaW9uVXNlZChOQU1FKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpOiB2b2lkIHtcclxuICAgICAgICBkZWxldGUgdGhpcy5kcmFjb0NvbXByZXNzaW9uO1xyXG4gICAgICAgICh0aGlzLl9sb2FkZXIgYXMgYW55KSA9IG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIF9sb2FkVmVydGV4RGF0YUFzeW5jKGNvbnRleHQ6IHN0cmluZywgcHJpbWl0aXZlOiBJTWVzaFByaW1pdGl2ZSwgYmFieWxvbk1lc2g6IE1lc2gpOiBOdWxsYWJsZTxQcm9taXNlPEdlb21ldHJ5Pj4ge1xyXG4gICAgICAgIHJldHVybiBHTFRGTG9hZGVyLkxvYWRFeHRlbnNpb25Bc3luYzxJS0hSRHJhY29NZXNoQ29tcHJlc3Npb24sIEdlb21ldHJ5Pihjb250ZXh0LCBwcmltaXRpdmUsIHRoaXMubmFtZSwgKGV4dGVuc2lvbkNvbnRleHQsIGV4dGVuc2lvbikgPT4ge1xyXG4gICAgICAgICAgICBpZiAocHJpbWl0aXZlLm1vZGUgIT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAocHJpbWl0aXZlLm1vZGUgIT09IE1lc2hQcmltaXRpdmVNb2RlLlRSSUFOR0xFX1NUUklQICYmIHByaW1pdGl2ZS5tb2RlICE9PSBNZXNoUHJpbWl0aXZlTW9kZS5UUklBTkdMRVMpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29udGV4dH06IFVuc3VwcG9ydGVkIG1vZGUgJHtwcmltaXRpdmUubW9kZX1gKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiBoYW5kbGUgdHJpYW5nbGUgc3RyaXBzXHJcbiAgICAgICAgICAgICAgICBpZiAocHJpbWl0aXZlLm1vZGUgPT09IE1lc2hQcmltaXRpdmVNb2RlLlRSSUFOR0xFX1NUUklQKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBNb2RlICR7cHJpbWl0aXZlLm1vZGV9IGlzIG5vdCBjdXJyZW50bHkgc3VwcG9ydGVkYCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGF0dHJpYnV0ZXM6IHsgW2tpbmQ6IHN0cmluZ106IG51bWJlciB9ID0ge307XHJcbiAgICAgICAgICAgIGNvbnN0IG5vcm1hbGl6ZWQ6IHsgW2tpbmQ6IHN0cmluZ106IGJvb2xlYW4gfSA9IHt9O1xyXG4gICAgICAgICAgICBjb25zdCBsb2FkQXR0cmlidXRlID0gKG5hbWU6IHN0cmluZywga2luZDogc3RyaW5nKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB1bmlxdWVJZCA9IGV4dGVuc2lvbi5hdHRyaWJ1dGVzW25hbWVdO1xyXG4gICAgICAgICAgICAgICAgaWYgKHVuaXF1ZUlkID09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uTWVzaC5fZGVsYXlJbmZvID0gYmFieWxvbk1lc2guX2RlbGF5SW5mbyB8fCBbXTtcclxuICAgICAgICAgICAgICAgIGlmIChiYWJ5bG9uTWVzaC5fZGVsYXlJbmZvLmluZGV4T2Yoa2luZCkgPT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYmFieWxvbk1lc2guX2RlbGF5SW5mby5wdXNoKGtpbmQpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZXNba2luZF0gPSB1bmlxdWVJZDtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy51c2VOb3JtYWxpemVkRmxhZ0Zyb21BY2Nlc3Nvcikge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGFjY2Vzc29yID0gQXJyYXlJdGVtLlRyeUdldCh0aGlzLl9sb2FkZXIuZ2x0Zi5hY2Nlc3NvcnMsIHByaW1pdGl2ZS5hdHRyaWJ1dGVzW25hbWVdKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoYWNjZXNzb3IpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbm9ybWFsaXplZFtraW5kXSA9IGFjY2Vzc29yLm5vcm1hbGl6ZWQgfHwgZmFsc2U7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgbG9hZEF0dHJpYnV0ZShcIlBPU0lUSU9OXCIsIFZlcnRleEJ1ZmZlci5Qb3NpdGlvbktpbmQpO1xyXG4gICAgICAgICAgICBsb2FkQXR0cmlidXRlKFwiTk9STUFMXCIsIFZlcnRleEJ1ZmZlci5Ob3JtYWxLaW5kKTtcclxuICAgICAgICAgICAgbG9hZEF0dHJpYnV0ZShcIlRBTkdFTlRcIiwgVmVydGV4QnVmZmVyLlRhbmdlbnRLaW5kKTtcclxuICAgICAgICAgICAgbG9hZEF0dHJpYnV0ZShcIlRFWENPT1JEXzBcIiwgVmVydGV4QnVmZmVyLlVWS2luZCk7XHJcbiAgICAgICAgICAgIGxvYWRBdHRyaWJ1dGUoXCJURVhDT09SRF8xXCIsIFZlcnRleEJ1ZmZlci5VVjJLaW5kKTtcclxuICAgICAgICAgICAgbG9hZEF0dHJpYnV0ZShcIlRFWENPT1JEXzJcIiwgVmVydGV4QnVmZmVyLlVWM0tpbmQpO1xyXG4gICAgICAgICAgICBsb2FkQXR0cmlidXRlKFwiVEVYQ09PUkRfM1wiLCBWZXJ0ZXhCdWZmZXIuVVY0S2luZCk7XHJcbiAgICAgICAgICAgIGxvYWRBdHRyaWJ1dGUoXCJURVhDT09SRF80XCIsIFZlcnRleEJ1ZmZlci5VVjVLaW5kKTtcclxuICAgICAgICAgICAgbG9hZEF0dHJpYnV0ZShcIlRFWENPT1JEXzVcIiwgVmVydGV4QnVmZmVyLlVWNktpbmQpO1xyXG4gICAgICAgICAgICBsb2FkQXR0cmlidXRlKFwiSk9JTlRTXzBcIiwgVmVydGV4QnVmZmVyLk1hdHJpY2VzSW5kaWNlc0tpbmQpO1xyXG4gICAgICAgICAgICBsb2FkQXR0cmlidXRlKFwiV0VJR0hUU18wXCIsIFZlcnRleEJ1ZmZlci5NYXRyaWNlc1dlaWdodHNLaW5kKTtcclxuICAgICAgICAgICAgbG9hZEF0dHJpYnV0ZShcIkNPTE9SXzBcIiwgVmVydGV4QnVmZmVyLkNvbG9yS2luZCk7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBidWZmZXJWaWV3ID0gQXJyYXlJdGVtLkdldChleHRlbnNpb25Db250ZXh0LCB0aGlzLl9sb2FkZXIuZ2x0Zi5idWZmZXJWaWV3cywgZXh0ZW5zaW9uLmJ1ZmZlclZpZXcpIGFzIElCdWZmZXJWaWV3RHJhY287XHJcbiAgICAgICAgICAgIGlmICghYnVmZmVyVmlldy5fZHJhY29CYWJ5bG9uR2VvbWV0cnkpIHtcclxuICAgICAgICAgICAgICAgIGJ1ZmZlclZpZXcuX2RyYWNvQmFieWxvbkdlb21ldHJ5ID0gdGhpcy5fbG9hZGVyLmxvYWRCdWZmZXJWaWV3QXN5bmMoYC9idWZmZXJWaWV3cy8ke2J1ZmZlclZpZXcuaW5kZXh9YCwgYnVmZmVyVmlldykudGhlbigoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRyYWNvQ29tcHJlc3Npb24gPSB0aGlzLmRyYWNvQ29tcHJlc3Npb24gfHwgRHJhY29Db21wcmVzc2lvbi5EZWZhdWx0O1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkcmFjb0NvbXByZXNzaW9uLl9kZWNvZGVNZXNoVG9HZW9tZXRyeUZvckdsdGZBc3luYyhiYWJ5bG9uTWVzaC5uYW1lLCB0aGlzLl9sb2FkZXIuYmFieWxvblNjZW5lLCBkYXRhLCBhdHRyaWJ1dGVzLCBub3JtYWxpemVkKS5jYXRjaCgoZXJyb3IpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiAke2Vycm9yLm1lc3NhZ2V9YCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcmV0dXJuIGJ1ZmZlclZpZXcuX2RyYWNvQmFieWxvbkdlb21ldHJ5O1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKE5BTUUsIChsb2FkZXIpID0+IG5ldyBLSFJfZHJhY29fbWVzaF9jb21wcmVzc2lvbihsb2FkZXIpKTtcclxuIiwiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uICovXHJcbmltcG9ydCB0eXBlIHsgTnVsbGFibGUgfSBmcm9tIFwiY29yZS90eXBlc1wiO1xyXG5pbXBvcnQgeyBWZWN0b3IzIH0gZnJvbSBcImNvcmUvTWF0aHMvbWF0aC52ZWN0b3JcIjtcclxuaW1wb3J0IHsgQ29sb3IzIH0gZnJvbSBcImNvcmUvTWF0aHMvbWF0aC5jb2xvclwiO1xyXG5pbXBvcnQgeyBEaXJlY3Rpb25hbExpZ2h0IH0gZnJvbSBcImNvcmUvTGlnaHRzL2RpcmVjdGlvbmFsTGlnaHRcIjtcclxuaW1wb3J0IHsgUG9pbnRMaWdodCB9IGZyb20gXCJjb3JlL0xpZ2h0cy9wb2ludExpZ2h0XCI7XHJcbmltcG9ydCB7IFNwb3RMaWdodCB9IGZyb20gXCJjb3JlL0xpZ2h0cy9zcG90TGlnaHRcIjtcclxuaW1wb3J0IHsgTGlnaHQgfSBmcm9tIFwiY29yZS9MaWdodHMvbGlnaHRcIjtcclxuaW1wb3J0IHR5cGUgeyBUcmFuc2Zvcm1Ob2RlIH0gZnJvbSBcImNvcmUvTWVzaGVzL3RyYW5zZm9ybU5vZGVcIjtcclxuXHJcbmltcG9ydCB0eXBlIHsgSUtIUkxpZ2h0c1B1bmN0dWFsX0xpZ2h0UmVmZXJlbmNlIH0gZnJvbSBcImJhYnlsb25qcy1nbHRmMmludGVyZmFjZVwiO1xyXG5pbXBvcnQgeyBLSFJMaWdodHNQdW5jdHVhbF9MaWdodFR5cGUgfSBmcm9tIFwiYmFieWxvbmpzLWdsdGYyaW50ZXJmYWNlXCI7XHJcbmltcG9ydCB0eXBlIHsgSU5vZGUsIElLSFJMaWdodHNQdW5jdHVhbF9MaWdodCB9IGZyb20gXCIuLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciwgQXJyYXlJdGVtIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJcIjtcclxuXHJcbmNvbnN0IE5BTUUgPSBcIktIUl9saWdodHNfcHVuY3R1YWxcIjtcclxuXHJcbi8qKlxyXG4gKiBbU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly9naXRodWIuY29tL0tocm9ub3NHcm91cC9nbFRGL2Jsb2IvbWFpbi9leHRlbnNpb25zLzIuMC9LaHJvbm9zL0tIUl9saWdodHNfcHVuY3R1YWwvUkVBRE1FLm1kKVxyXG4gKi9cclxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxyXG5leHBvcnQgY2xhc3MgS0hSX2xpZ2h0cyBpbXBsZW1lbnRzIElHTFRGTG9hZGVyRXh0ZW5zaW9uIHtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIG5hbWUgb2YgdGhpcyBleHRlbnNpb24uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyByZWFkb25seSBuYW1lID0gTkFNRTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgd2hldGhlciB0aGlzIGV4dGVuc2lvbiBpcyBlbmFibGVkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZW5hYmxlZDogYm9vbGVhbjtcclxuXHJcbiAgICAvKiogaGlkZGVuICovXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcbiAgICBwcml2YXRlIF9saWdodHM/OiBJS0hSTGlnaHRzUHVuY3R1YWxfTGlnaHRbXTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3Rvcihsb2FkZXI6IEdMVEZMb2FkZXIpIHtcclxuICAgICAgICB0aGlzLl9sb2FkZXIgPSBsb2FkZXI7XHJcbiAgICAgICAgdGhpcy5lbmFibGVkID0gdGhpcy5fbG9hZGVyLmlzRXh0ZW5zaW9uVXNlZChOQU1FKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpIHtcclxuICAgICAgICAodGhpcy5fbG9hZGVyIGFzIGFueSkgPSBudWxsO1xyXG4gICAgICAgIGRlbGV0ZSB0aGlzLl9saWdodHM7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIG9uTG9hZGluZygpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBleHRlbnNpb25zID0gdGhpcy5fbG9hZGVyLmdsdGYuZXh0ZW5zaW9ucztcclxuICAgICAgICBpZiAoZXh0ZW5zaW9ucyAmJiBleHRlbnNpb25zW3RoaXMubmFtZV0pIHtcclxuICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uID0gZXh0ZW5zaW9uc1t0aGlzLm5hbWVdIGFzIGFueTtcclxuICAgICAgICAgICAgdGhpcy5fbGlnaHRzID0gZXh0ZW5zaW9uLmxpZ2h0cztcclxuICAgICAgICAgICAgQXJyYXlJdGVtLkFzc2lnbih0aGlzLl9saWdodHMpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZE5vZGVBc3luYyhjb250ZXh0OiBzdHJpbmcsIG5vZGU6IElOb2RlLCBhc3NpZ246IChiYWJ5bG9uVHJhbnNmb3JtTm9kZTogVHJhbnNmb3JtTm9kZSkgPT4gdm9pZCk6IE51bGxhYmxlPFByb21pc2U8VHJhbnNmb3JtTm9kZT4+IHtcclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SUtIUkxpZ2h0c1B1bmN0dWFsX0xpZ2h0UmVmZXJlbmNlLCBUcmFuc2Zvcm1Ob2RlPihjb250ZXh0LCBub2RlLCB0aGlzLm5hbWUsIChleHRlbnNpb25Db250ZXh0LCBleHRlbnNpb24pID0+IHtcclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyLl9hbGxNYXRlcmlhbHNEaXJ0eVJlcXVpcmVkID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9sb2FkZXIubG9hZE5vZGVBc3luYyhjb250ZXh0LCBub2RlLCAoYmFieWxvbk1lc2gpID0+IHtcclxuICAgICAgICAgICAgICAgIGxldCBiYWJ5bG9uTGlnaHQ6IExpZ2h0O1xyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IGxpZ2h0ID0gQXJyYXlJdGVtLkdldChleHRlbnNpb25Db250ZXh0LCB0aGlzLl9saWdodHMsIGV4dGVuc2lvbi5saWdodCk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBuYW1lID0gbGlnaHQubmFtZSB8fCBiYWJ5bG9uTWVzaC5uYW1lO1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRlci5iYWJ5bG9uU2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9ICEhdGhpcy5fbG9hZGVyLl9hc3NldENvbnRhaW5lcjtcclxuXHJcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGxpZ2h0LnR5cGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBjYXNlIEtIUkxpZ2h0c1B1bmN0dWFsX0xpZ2h0VHlwZS5ESVJFQ1RJT05BTDoge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBiYWJ5bG9uRGlyZWN0aW9uYWxMaWdodCA9IG5ldyBEaXJlY3Rpb25hbExpZ2h0KG5hbWUsIFZlY3RvcjMuQmFja3dhcmQoKSwgdGhpcy5fbG9hZGVyLmJhYnlsb25TY2VuZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhYnlsb25EaXJlY3Rpb25hbExpZ2h0LnBvc2l0aW9uLnNldEFsbCgwKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYmFieWxvbkxpZ2h0ID0gYmFieWxvbkRpcmVjdGlvbmFsTGlnaHQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBjYXNlIEtIUkxpZ2h0c1B1bmN0dWFsX0xpZ2h0VHlwZS5QT0lOVDoge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTGlnaHQgPSBuZXcgUG9pbnRMaWdodChuYW1lLCBWZWN0b3IzLlplcm8oKSwgdGhpcy5fbG9hZGVyLmJhYnlsb25TY2VuZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBjYXNlIEtIUkxpZ2h0c1B1bmN0dWFsX0xpZ2h0VHlwZS5TUE9UOiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJhYnlsb25TcG90TGlnaHQgPSBuZXcgU3BvdExpZ2h0KG5hbWUsIFZlY3RvcjMuWmVybygpLCBWZWN0b3IzLkJhY2t3YXJkKCksIDAsIDEsIHRoaXMuX2xvYWRlci5iYWJ5bG9uU2NlbmUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uU3BvdExpZ2h0LmFuZ2xlID0gKChsaWdodC5zcG90ICYmIGxpZ2h0LnNwb3Qub3V0ZXJDb25lQW5nbGUpIHx8IE1hdGguUEkgLyA0KSAqIDI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhYnlsb25TcG90TGlnaHQuaW5uZXJBbmdsZSA9ICgobGlnaHQuc3BvdCAmJiBsaWdodC5zcG90LmlubmVyQ29uZUFuZ2xlKSB8fCAwKSAqIDI7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhYnlsb25MaWdodCA9IGJhYnlsb25TcG90TGlnaHQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0OiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRlci5iYWJ5bG9uU2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9IGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZXh0ZW5zaW9uQ29udGV4dH06IEludmFsaWQgbGlnaHQgdHlwZSAoJHtsaWdodC50eXBlfSlgKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgYmFieWxvbkxpZ2h0Ll9wYXJlbnRDb250YWluZXIgPSB0aGlzLl9sb2FkZXIuX2Fzc2V0Q29udGFpbmVyO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmJhYnlsb25TY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gZmFsc2U7XHJcbiAgICAgICAgICAgICAgICBsaWdodC5fYmFieWxvbkxpZ2h0ID0gYmFieWxvbkxpZ2h0O1xyXG5cclxuICAgICAgICAgICAgICAgIGJhYnlsb25MaWdodC5mYWxsb2ZmVHlwZSA9IExpZ2h0LkZBTExPRkZfR0xURjtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25MaWdodC5kaWZmdXNlID0gbGlnaHQuY29sb3IgPyBDb2xvcjMuRnJvbUFycmF5KGxpZ2h0LmNvbG9yKSA6IENvbG9yMy5XaGl0ZSgpO1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbkxpZ2h0LmludGVuc2l0eSA9IGxpZ2h0LmludGVuc2l0eSA9PSB1bmRlZmluZWQgPyAxIDogbGlnaHQuaW50ZW5zaXR5O1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbkxpZ2h0LnJhbmdlID0gbGlnaHQucmFuZ2UgPT0gdW5kZWZpbmVkID8gTnVtYmVyLk1BWF9WQUxVRSA6IGxpZ2h0LnJhbmdlO1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbkxpZ2h0LnBhcmVudCA9IGJhYnlsb25NZXNoO1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRlci5fYmFieWxvbkxpZ2h0cy5wdXNoKGJhYnlsb25MaWdodCk7XHJcblxyXG4gICAgICAgICAgICAgICAgR0xURkxvYWRlci5BZGRQb2ludGVyTWV0YWRhdGEoYmFieWxvbkxpZ2h0LCBleHRlbnNpb25Db250ZXh0KTtcclxuXHJcbiAgICAgICAgICAgICAgICBhc3NpZ24oYmFieWxvbk1lc2gpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxufVxyXG5cclxuR0xURkxvYWRlci5SZWdpc3RlckV4dGVuc2lvbihOQU1FLCAobG9hZGVyKSA9PiBuZXcgS0hSX2xpZ2h0cyhsb2FkZXIpKTtcclxuIiwiaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB7IFBCUk1hdGVyaWFsIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL1BCUi9wYnJNYXRlcmlhbFwiO1xyXG5pbXBvcnQgdHlwZSB7IE1hdGVyaWFsIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL21hdGVyaWFsXCI7XHJcblxyXG5pbXBvcnQgdHlwZSB7IElNYXRlcmlhbCB9IGZyb20gXCIuLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgSUtIUk1hdGVyaWFsc0FuaXNvdHJvcHkgfSBmcm9tIFwiYmFieWxvbmpzLWdsdGYyaW50ZXJmYWNlXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJLSFJfbWF0ZXJpYWxzX2FuaXNvdHJvcHlcIjtcclxuXHJcbi8qKlxyXG4gKiBbU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly9naXRodWIuY29tL0tocm9ub3NHcm91cC9nbFRGL3RyZWUvbWFpbi9leHRlbnNpb25zLzIuMC9LaHJvbm9zL0tIUl9tYXRlcmlhbHNfYW5pc290cm9weSlcclxuICovXHJcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cclxuZXhwb3J0IGNsYXNzIEtIUl9tYXRlcmlhbHNfYW5pc290cm9weSBpbXBsZW1lbnRzIElHTFRGTG9hZGVyRXh0ZW5zaW9uIHtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIG5hbWUgb2YgdGhpcyBleHRlbnNpb24uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyByZWFkb25seSBuYW1lID0gTkFNRTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgd2hldGhlciB0aGlzIGV4dGVuc2lvbiBpcyBlbmFibGVkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZW5hYmxlZDogYm9vbGVhbjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgYSBudW1iZXIgdGhhdCBkZXRlcm1pbmVzIHRoZSBvcmRlciB0aGUgZXh0ZW5zaW9ucyBhcmUgYXBwbGllZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIG9yZGVyID0gMTk1O1xyXG5cclxuICAgIHByaXZhdGUgX2xvYWRlcjogR0xURkxvYWRlcjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3Rvcihsb2FkZXI6IEdMVEZMb2FkZXIpIHtcclxuICAgICAgICB0aGlzLl9sb2FkZXIgPSBsb2FkZXI7XHJcbiAgICAgICAgdGhpcy5lbmFibGVkID0gdGhpcy5fbG9hZGVyLmlzRXh0ZW5zaW9uVXNlZChOQU1FKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpIHtcclxuICAgICAgICAodGhpcy5fbG9hZGVyIGFzIGFueSkgPSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkTWF0ZXJpYWxQcm9wZXJ0aWVzQXN5bmMoY29udGV4dDogc3RyaW5nLCBtYXRlcmlhbDogSU1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWw6IE1hdGVyaWFsKTogTnVsbGFibGU8UHJvbWlzZTx2b2lkPj4ge1xyXG4gICAgICAgIHJldHVybiBHTFRGTG9hZGVyLkxvYWRFeHRlbnNpb25Bc3luYzxJS0hSTWF0ZXJpYWxzQW5pc290cm9weT4oY29udGV4dCwgbWF0ZXJpYWwsIHRoaXMubmFtZSwgKGV4dGVuc2lvbkNvbnRleHQsIGV4dGVuc2lvbikgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBwcm9taXNlcyA9IG5ldyBBcnJheTxQcm9taXNlPGFueT4+KCk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fbG9hZGVyLmxvYWRNYXRlcmlhbFByb3BlcnRpZXNBc3luYyhjb250ZXh0LCBtYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsKSk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fbG9hZElyaWRlc2NlbmNlUHJvcGVydGllc0FzeW5jKGV4dGVuc2lvbkNvbnRleHQsIGV4dGVuc2lvbiwgYmFieWxvbk1hdGVyaWFsKSk7XHJcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7fSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZElyaWRlc2NlbmNlUHJvcGVydGllc0FzeW5jKGNvbnRleHQ6IHN0cmluZywgcHJvcGVydGllczogSUtIUk1hdGVyaWFsc0FuaXNvdHJvcHksIGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBpZiAoIShiYWJ5bG9uTWF0ZXJpYWwgaW5zdGFuY2VvZiBQQlJNYXRlcmlhbCkpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBNYXRlcmlhbCB0eXBlIG5vdCBzdXBwb3J0ZWRgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuXHJcbiAgICAgICAgYmFieWxvbk1hdGVyaWFsLmFuaXNvdHJvcHkuaXNFbmFibGVkID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgYmFieWxvbk1hdGVyaWFsLmFuaXNvdHJvcHkuaW50ZW5zaXR5ID0gcHJvcGVydGllcy5hbmlzb3Ryb3B5U3RyZW5ndGggPz8gMDtcclxuICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuYW5pc290cm9weS5hbmdsZSA9IHByb3BlcnRpZXMuYW5pc290cm9weVJvdGF0aW9uID8/IDA7XHJcblxyXG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLmFuaXNvdHJvcHlUZXh0dXJlKSB7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIubG9hZFRleHR1cmVJbmZvQXN5bmMoYCR7Y29udGV4dH0vYW5pc290cm9weVRleHR1cmVgLCBwcm9wZXJ0aWVzLmFuaXNvdHJvcHlUZXh0dXJlLCAodGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRleHR1cmUubmFtZSA9IGAke2JhYnlsb25NYXRlcmlhbC5uYW1lfSAoQW5pc290cm9weSBJbnRlbnNpdHkpYDtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuYW5pc290cm9weS50ZXh0dXJlID0gdGV4dHVyZTtcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge30pO1xyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKE5BTUUsIChsb2FkZXIpID0+IG5ldyBLSFJfbWF0ZXJpYWxzX2FuaXNvdHJvcHkobG9hZGVyKSk7XHJcbiIsImltcG9ydCB0eXBlIHsgTnVsbGFibGUgfSBmcm9tIFwiY29yZS90eXBlc1wiO1xyXG5pbXBvcnQgeyBQQlJNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9QQlIvcGJyTWF0ZXJpYWxcIjtcclxuaW1wb3J0IHR5cGUgeyBNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9tYXRlcmlhbFwiO1xyXG5cclxuaW1wb3J0IHR5cGUgeyBJTWF0ZXJpYWwsIElUZXh0dXJlSW5mbyB9IGZyb20gXCIuLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgSUtIUk1hdGVyaWFsc0NsZWFyY29hdCB9IGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuXHJcbmNvbnN0IE5BTUUgPSBcIktIUl9tYXRlcmlhbHNfY2xlYXJjb2F0XCI7XHJcblxyXG4vKipcclxuICogW1NwZWNpZmljYXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9LaHJvbm9zR3JvdXAvZ2xURi9ibG9iL21haW4vZXh0ZW5zaW9ucy8yLjAvS2hyb25vcy9LSFJfbWF0ZXJpYWxzX2NsZWFyY29hdC9SRUFETUUubWQpXHJcbiAqIFtQbGF5Z3JvdW5kIFNhbXBsZV0oaHR0cHM6Ly93d3cuYmFieWxvbmpzLXBsYXlncm91bmQuY29tL2ZyYW1lLmh0bWwjN0Y3UE42IzgpXHJcbiAqL1xyXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXHJcbmV4cG9ydCBjbGFzcyBLSFJfbWF0ZXJpYWxzX2NsZWFyY29hdCBpbXBsZW1lbnRzIElHTFRGTG9hZGVyRXh0ZW5zaW9uIHtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIG5hbWUgb2YgdGhpcyBleHRlbnNpb24uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyByZWFkb25seSBuYW1lID0gTkFNRTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgd2hldGhlciB0aGlzIGV4dGVuc2lvbiBpcyBlbmFibGVkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZW5hYmxlZDogYm9vbGVhbjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgYSBudW1iZXIgdGhhdCBkZXRlcm1pbmVzIHRoZSBvcmRlciB0aGUgZXh0ZW5zaW9ucyBhcmUgYXBwbGllZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIG9yZGVyID0gMTkwO1xyXG5cclxuICAgIHByaXZhdGUgX2xvYWRlcjogR0xURkxvYWRlcjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3Rvcihsb2FkZXI6IEdMVEZMb2FkZXIpIHtcclxuICAgICAgICB0aGlzLl9sb2FkZXIgPSBsb2FkZXI7XHJcbiAgICAgICAgdGhpcy5lbmFibGVkID0gdGhpcy5fbG9hZGVyLmlzRXh0ZW5zaW9uVXNlZChOQU1FKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpIHtcclxuICAgICAgICAodGhpcy5fbG9hZGVyIGFzIGFueSkgPSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkTWF0ZXJpYWxQcm9wZXJ0aWVzQXN5bmMoY29udGV4dDogc3RyaW5nLCBtYXRlcmlhbDogSU1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWw6IE1hdGVyaWFsKTogTnVsbGFibGU8UHJvbWlzZTx2b2lkPj4ge1xyXG4gICAgICAgIHJldHVybiBHTFRGTG9hZGVyLkxvYWRFeHRlbnNpb25Bc3luYzxJS0hSTWF0ZXJpYWxzQ2xlYXJjb2F0Pihjb250ZXh0LCBtYXRlcmlhbCwgdGhpcy5uYW1lLCAoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkZXIubG9hZE1hdGVyaWFsUHJvcGVydGllc0FzeW5jKGNvbnRleHQsIG1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWwpKTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkQ2xlYXJDb2F0UHJvcGVydGllc0FzeW5jKGV4dGVuc2lvbkNvbnRleHQsIGV4dGVuc2lvbiwgYmFieWxvbk1hdGVyaWFsKSk7XHJcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7fSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZENsZWFyQ29hdFByb3BlcnRpZXNBc3luYyhjb250ZXh0OiBzdHJpbmcsIHByb3BlcnRpZXM6IElLSFJNYXRlcmlhbHNDbGVhcmNvYXQsIGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBpZiAoIShiYWJ5bG9uTWF0ZXJpYWwgaW5zdGFuY2VvZiBQQlJNYXRlcmlhbCkpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBNYXRlcmlhbCB0eXBlIG5vdCBzdXBwb3J0ZWRgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuXHJcbiAgICAgICAgYmFieWxvbk1hdGVyaWFsLmNsZWFyQ29hdC5pc0VuYWJsZWQgPSB0cnVlO1xyXG4gICAgICAgIGJhYnlsb25NYXRlcmlhbC5jbGVhckNvYXQudXNlUm91Z2huZXNzRnJvbU1haW5UZXh0dXJlID0gZmFsc2U7XHJcbiAgICAgICAgYmFieWxvbk1hdGVyaWFsLmNsZWFyQ29hdC5yZW1hcEYwT25JbnRlcmZhY2VDaGFuZ2UgPSBmYWxzZTtcclxuXHJcbiAgICAgICAgaWYgKHByb3BlcnRpZXMuY2xlYXJjb2F0RmFjdG9yICE9IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuY2xlYXJDb2F0LmludGVuc2l0eSA9IHByb3BlcnRpZXMuY2xlYXJjb2F0RmFjdG9yO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5jbGVhckNvYXQuaW50ZW5zaXR5ID0gMDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLmNsZWFyY29hdFRleHR1cmUpIHtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaChcclxuICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRlci5sb2FkVGV4dHVyZUluZm9Bc3luYyhgJHtjb250ZXh0fS9jbGVhcmNvYXRUZXh0dXJlYCwgcHJvcGVydGllcy5jbGVhcmNvYXRUZXh0dXJlLCAodGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRleHR1cmUubmFtZSA9IGAke2JhYnlsb25NYXRlcmlhbC5uYW1lfSAoQ2xlYXJDb2F0IEludGVuc2l0eSlgO1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5jbGVhckNvYXQudGV4dHVyZSA9IHRleHR1cmU7XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHByb3BlcnRpZXMuY2xlYXJjb2F0Um91Z2huZXNzRmFjdG9yICE9IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuY2xlYXJDb2F0LnJvdWdobmVzcyA9IHByb3BlcnRpZXMuY2xlYXJjb2F0Um91Z2huZXNzRmFjdG9yO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5jbGVhckNvYXQucm91Z2huZXNzID0gMDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLmNsZWFyY29hdFJvdWdobmVzc1RleHR1cmUpIHtcclxuICAgICAgICAgICAgKHByb3BlcnRpZXMuY2xlYXJjb2F0Um91Z2huZXNzVGV4dHVyZSBhcyBJVGV4dHVyZUluZm8pLm5vbkNvbG9yRGF0YSA9IHRydWU7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIubG9hZFRleHR1cmVJbmZvQXN5bmMoYCR7Y29udGV4dH0vY2xlYXJjb2F0Um91Z2huZXNzVGV4dHVyZWAsIHByb3BlcnRpZXMuY2xlYXJjb2F0Um91Z2huZXNzVGV4dHVyZSwgKHRleHR1cmUpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICB0ZXh0dXJlLm5hbWUgPSBgJHtiYWJ5bG9uTWF0ZXJpYWwubmFtZX0gKENsZWFyQ29hdCBSb3VnaG5lc3MpYDtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuY2xlYXJDb2F0LnRleHR1cmVSb3VnaG5lc3MgPSB0ZXh0dXJlO1xyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLmNsZWFyY29hdE5vcm1hbFRleHR1cmUpIHtcclxuICAgICAgICAgICAgKHByb3BlcnRpZXMuY2xlYXJjb2F0Tm9ybWFsVGV4dHVyZSBhcyBJVGV4dHVyZUluZm8pLm5vbkNvbG9yRGF0YSA9IHRydWU7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIubG9hZFRleHR1cmVJbmZvQXN5bmMoYCR7Y29udGV4dH0vY2xlYXJjb2F0Tm9ybWFsVGV4dHVyZWAsIHByb3BlcnRpZXMuY2xlYXJjb2F0Tm9ybWFsVGV4dHVyZSwgKHRleHR1cmUpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICB0ZXh0dXJlLm5hbWUgPSBgJHtiYWJ5bG9uTWF0ZXJpYWwubmFtZX0gKENsZWFyQ29hdCBOb3JtYWwpYDtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuY2xlYXJDb2F0LmJ1bXBUZXh0dXJlID0gdGV4dHVyZTtcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuaW52ZXJ0Tm9ybWFsTWFwWCA9ICFiYWJ5bG9uTWF0ZXJpYWwuZ2V0U2NlbmUoKS51c2VSaWdodEhhbmRlZFN5c3RlbTtcclxuICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLmludmVydE5vcm1hbE1hcFkgPSBiYWJ5bG9uTWF0ZXJpYWwuZ2V0U2NlbmUoKS51c2VSaWdodEhhbmRlZFN5c3RlbTtcclxuICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuY2xlYXJjb2F0Tm9ybWFsVGV4dHVyZS5zY2FsZSAhPSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5jbGVhckNvYXQuYnVtcFRleHR1cmUhLmxldmVsID0gcHJvcGVydGllcy5jbGVhcmNvYXROb3JtYWxUZXh0dXJlLnNjYWxlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge30pO1xyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKE5BTUUsIChsb2FkZXIpID0+IG5ldyBLSFJfbWF0ZXJpYWxzX2NsZWFyY29hdChsb2FkZXIpKTtcclxuIiwiaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB7IFBCUk1hdGVyaWFsIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL1BCUi9wYnJNYXRlcmlhbFwiO1xyXG5pbXBvcnQgdHlwZSB7IE1hdGVyaWFsIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL21hdGVyaWFsXCI7XHJcblxyXG5pbXBvcnQgdHlwZSB7IElNYXRlcmlhbCB9IGZyb20gXCIuLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgSUtIUk1hdGVyaWFsc0VtaXNzaXZlU3RyZW5ndGggfSBmcm9tIFwiYmFieWxvbmpzLWdsdGYyaW50ZXJmYWNlXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJLSFJfbWF0ZXJpYWxzX2VtaXNzaXZlX3N0cmVuZ3RoXCI7XHJcblxyXG4vKipcclxuICogW1NwZWNpZmljYXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9LaHJvbm9zR3JvdXAvZ2xURi9ibG9iL21haW4vZXh0ZW5zaW9ucy8yLjAvS2hyb25vcy9LSFJfbWF0ZXJpYWxzX2VtaXNzaXZlX3N0cmVuZ3RoL1JFQURNRS5tZClcclxuICovXHJcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cclxuZXhwb3J0IGNsYXNzIEtIUl9tYXRlcmlhbHNfZW1pc3NpdmVfc3RyZW5ndGggaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGEgbnVtYmVyIHRoYXQgZGV0ZXJtaW5lcyB0aGUgb3JkZXIgdGhlIGV4dGVuc2lvbnMgYXJlIGFwcGxpZWQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBvcmRlciA9IDE3MDtcclxuXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGVyOiBHTFRGTG9hZGVyKSB7XHJcbiAgICAgICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyO1xyXG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IHRoaXMuX2xvYWRlci5pc0V4dGVuc2lvblVzZWQoTkFNRSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKSB7XHJcbiAgICAgICAgKHRoaXMuX2xvYWRlciBhcyBhbnkpID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZE1hdGVyaWFsUHJvcGVydGllc0FzeW5jKGNvbnRleHQ6IHN0cmluZywgbWF0ZXJpYWw6IElNYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsOiBNYXRlcmlhbCk6IE51bGxhYmxlPFByb21pc2U8dm9pZD4+IHtcclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SUtIUk1hdGVyaWFsc0VtaXNzaXZlU3RyZW5ndGg+KGNvbnRleHQsIG1hdGVyaWFsLCB0aGlzLm5hbWUsIChleHRlbnNpb25Db250ZXh0LCBleHRlbnNpb24pID0+IHtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2xvYWRlci5sb2FkTWF0ZXJpYWxQcm9wZXJ0aWVzQXN5bmMoY29udGV4dCwgbWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbCkudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkRW1pc3NpdmVQcm9wZXJ0aWVzKGV4dGVuc2lvbkNvbnRleHQsIGV4dGVuc2lvbiwgYmFieWxvbk1hdGVyaWFsKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZEVtaXNzaXZlUHJvcGVydGllcyhjb250ZXh0OiBzdHJpbmcsIHByb3BlcnRpZXM6IElLSFJNYXRlcmlhbHNFbWlzc2l2ZVN0cmVuZ3RoLCBiYWJ5bG9uTWF0ZXJpYWw6IE1hdGVyaWFsKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKCEoYmFieWxvbk1hdGVyaWFsIGluc3RhbmNlb2YgUEJSTWF0ZXJpYWwpKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fTogTWF0ZXJpYWwgdHlwZSBub3Qgc3VwcG9ydGVkYCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocHJvcGVydGllcy5lbWlzc2l2ZVN0cmVuZ3RoICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLmVtaXNzaXZlQ29sb3Iuc2NhbGVUb1JlZihwcm9wZXJ0aWVzLmVtaXNzaXZlU3RyZW5ndGgsIGJhYnlsb25NYXRlcmlhbC5lbWlzc2l2ZUNvbG9yKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbkdMVEZMb2FkZXIuUmVnaXN0ZXJFeHRlbnNpb24oTkFNRSwgKGxvYWRlcikgPT4gbmV3IEtIUl9tYXRlcmlhbHNfZW1pc3NpdmVfc3RyZW5ndGgobG9hZGVyKSk7XHJcbiIsImltcG9ydCB0eXBlIHsgTnVsbGFibGUgfSBmcm9tIFwiY29yZS90eXBlc1wiO1xyXG5pbXBvcnQgeyBQQlJNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9QQlIvcGJyTWF0ZXJpYWxcIjtcclxuaW1wb3J0IHR5cGUgeyBNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9tYXRlcmlhbFwiO1xyXG5cclxuaW1wb3J0IHR5cGUgeyBJTWF0ZXJpYWwgfSBmcm9tIFwiLi4vZ2xURkxvYWRlckludGVyZmFjZXNcIjtcclxuaW1wb3J0IHR5cGUgeyBJR0xURkxvYWRlckV4dGVuc2lvbiB9IGZyb20gXCIuLi9nbFRGTG9hZGVyRXh0ZW5zaW9uXCI7XHJcbmltcG9ydCB7IEdMVEZMb2FkZXIgfSBmcm9tIFwiLi4vZ2xURkxvYWRlclwiO1xyXG5pbXBvcnQgdHlwZSB7IElLSFJNYXRlcmlhbHNJb3IgfSBmcm9tIFwiYmFieWxvbmpzLWdsdGYyaW50ZXJmYWNlXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJLSFJfbWF0ZXJpYWxzX2lvclwiO1xyXG5cclxuLyoqXHJcbiAqIFtTcGVjaWZpY2F0aW9uXShodHRwczovL2dpdGh1Yi5jb20vS2hyb25vc0dyb3VwL2dsVEYvYmxvYi9tYWluL2V4dGVuc2lvbnMvMi4wL0tocm9ub3MvS0hSX21hdGVyaWFsc19pb3IvUkVBRE1FLm1kKVxyXG4gKi9cclxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxyXG5leHBvcnQgY2xhc3MgS0hSX21hdGVyaWFsc19pb3IgaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIERlZmF1bHQgaW9yIFZhbHVlIGZyb20gdGhlIHNwZWMuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgc3RhdGljIHJlYWRvbmx5IF9ERUZBVUxUX0lPUiA9IDEuNTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGEgbnVtYmVyIHRoYXQgZGV0ZXJtaW5lcyB0aGUgb3JkZXIgdGhlIGV4dGVuc2lvbnMgYXJlIGFwcGxpZWQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBvcmRlciA9IDE4MDtcclxuXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGVyOiBHTFRGTG9hZGVyKSB7XHJcbiAgICAgICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyO1xyXG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IHRoaXMuX2xvYWRlci5pc0V4dGVuc2lvblVzZWQoTkFNRSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKSB7XHJcbiAgICAgICAgKHRoaXMuX2xvYWRlciBhcyBhbnkpID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZE1hdGVyaWFsUHJvcGVydGllc0FzeW5jKGNvbnRleHQ6IHN0cmluZywgbWF0ZXJpYWw6IElNYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsOiBNYXRlcmlhbCk6IE51bGxhYmxlPFByb21pc2U8dm9pZD4+IHtcclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SUtIUk1hdGVyaWFsc0lvcj4oY29udGV4dCwgbWF0ZXJpYWwsIHRoaXMubmFtZSwgKGV4dGVuc2lvbkNvbnRleHQsIGV4dGVuc2lvbikgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBwcm9taXNlcyA9IG5ldyBBcnJheTxQcm9taXNlPGFueT4+KCk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fbG9hZGVyLmxvYWRNYXRlcmlhbFByb3BlcnRpZXNBc3luYyhjb250ZXh0LCBtYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsKSk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fbG9hZElvclByb3BlcnRpZXNBc3luYyhleHRlbnNpb25Db250ZXh0LCBleHRlbnNpb24sIGJhYnlsb25NYXRlcmlhbCkpO1xyXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge30pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2xvYWRJb3JQcm9wZXJ0aWVzQXN5bmMoY29udGV4dDogc3RyaW5nLCBwcm9wZXJ0aWVzOiBJS0hSTWF0ZXJpYWxzSW9yLCBiYWJ5bG9uTWF0ZXJpYWw6IE1hdGVyaWFsKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgaWYgKCEoYmFieWxvbk1hdGVyaWFsIGluc3RhbmNlb2YgUEJSTWF0ZXJpYWwpKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fTogTWF0ZXJpYWwgdHlwZSBub3Qgc3VwcG9ydGVkYCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocHJvcGVydGllcy5pb3IgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuaW5kZXhPZlJlZnJhY3Rpb24gPSBwcm9wZXJ0aWVzLmlvcjtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuaW5kZXhPZlJlZnJhY3Rpb24gPSBLSFJfbWF0ZXJpYWxzX2lvci5fREVGQVVMVF9JT1I7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgICB9XHJcbn1cclxuXHJcbkdMVEZMb2FkZXIuUmVnaXN0ZXJFeHRlbnNpb24oTkFNRSwgKGxvYWRlcikgPT4gbmV3IEtIUl9tYXRlcmlhbHNfaW9yKGxvYWRlcikpO1xyXG4iLCJpbXBvcnQgdHlwZSB7IE51bGxhYmxlIH0gZnJvbSBcImNvcmUvdHlwZXNcIjtcclxuaW1wb3J0IHsgUEJSTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvUEJSL3Bick1hdGVyaWFsXCI7XHJcbmltcG9ydCB0eXBlIHsgTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvbWF0ZXJpYWxcIjtcclxuXHJcbmltcG9ydCB0eXBlIHsgSU1hdGVyaWFsIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcbmltcG9ydCB0eXBlIHsgSUdMVEZMb2FkZXJFeHRlbnNpb24gfSBmcm9tIFwiLi4vZ2xURkxvYWRlckV4dGVuc2lvblwiO1xyXG5pbXBvcnQgeyBHTFRGTG9hZGVyIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJcIjtcclxuaW1wb3J0IHR5cGUgeyBJS0hSTWF0ZXJpYWxzSXJpZGVzY2VuY2UgfSBmcm9tIFwiYmFieWxvbmpzLWdsdGYyaW50ZXJmYWNlXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJLSFJfbWF0ZXJpYWxzX2lyaWRlc2NlbmNlXCI7XHJcblxyXG4vKipcclxuICogW1NwZWNpZmljYXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9LaHJvbm9zR3JvdXAvZ2xURi9ibG9iL21haW4vZXh0ZW5zaW9ucy8yLjAvS2hyb25vcy9LSFJfbWF0ZXJpYWxzX2lyaWRlc2NlbmNlL1JFQURNRS5tZClcclxuICovXHJcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cclxuZXhwb3J0IGNsYXNzIEtIUl9tYXRlcmlhbHNfaXJpZGVzY2VuY2UgaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGEgbnVtYmVyIHRoYXQgZGV0ZXJtaW5lcyB0aGUgb3JkZXIgdGhlIGV4dGVuc2lvbnMgYXJlIGFwcGxpZWQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBvcmRlciA9IDE5NTtcclxuXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGVyOiBHTFRGTG9hZGVyKSB7XHJcbiAgICAgICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyO1xyXG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IHRoaXMuX2xvYWRlci5pc0V4dGVuc2lvblVzZWQoTkFNRSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKSB7XHJcbiAgICAgICAgKHRoaXMuX2xvYWRlciBhcyBhbnkpID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZE1hdGVyaWFsUHJvcGVydGllc0FzeW5jKGNvbnRleHQ6IHN0cmluZywgbWF0ZXJpYWw6IElNYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsOiBNYXRlcmlhbCk6IE51bGxhYmxlPFByb21pc2U8dm9pZD4+IHtcclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SUtIUk1hdGVyaWFsc0lyaWRlc2NlbmNlPihjb250ZXh0LCBtYXRlcmlhbCwgdGhpcy5uYW1lLCAoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkZXIubG9hZE1hdGVyaWFsUHJvcGVydGllc0FzeW5jKGNvbnRleHQsIG1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWwpKTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkSXJpZGVzY2VuY2VQcm9wZXJ0aWVzQXN5bmMoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uLCBiYWJ5bG9uTWF0ZXJpYWwpKTtcclxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IHt9KTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9sb2FkSXJpZGVzY2VuY2VQcm9wZXJ0aWVzQXN5bmMoY29udGV4dDogc3RyaW5nLCBwcm9wZXJ0aWVzOiBJS0hSTWF0ZXJpYWxzSXJpZGVzY2VuY2UsIGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBpZiAoIShiYWJ5bG9uTWF0ZXJpYWwgaW5zdGFuY2VvZiBQQlJNYXRlcmlhbCkpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBNYXRlcmlhbCB0eXBlIG5vdCBzdXBwb3J0ZWRgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuXHJcbiAgICAgICAgYmFieWxvbk1hdGVyaWFsLmlyaWRlc2NlbmNlLmlzRW5hYmxlZCA9IHRydWU7XHJcblxyXG4gICAgICAgIGJhYnlsb25NYXRlcmlhbC5pcmlkZXNjZW5jZS5pbnRlbnNpdHkgPSBwcm9wZXJ0aWVzLmlyaWRlc2NlbmNlRmFjdG9yID8/IDA7XHJcbiAgICAgICAgYmFieWxvbk1hdGVyaWFsLmlyaWRlc2NlbmNlLmluZGV4T2ZSZWZyYWN0aW9uID0gcHJvcGVydGllcy5pcmlkZXNjZW5jZUlvciA/PyAocHJvcGVydGllcyBhcyBhbnkpLmlyaWRlc2NlbmNlSU9SID8/IDEuMztcclxuICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuaXJpZGVzY2VuY2UubWluaW11bVRoaWNrbmVzcyA9IHByb3BlcnRpZXMuaXJpZGVzY2VuY2VUaGlja25lc3NNaW5pbXVtID8/IDEwMDtcclxuICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuaXJpZGVzY2VuY2UubWF4aW11bVRoaWNrbmVzcyA9IHByb3BlcnRpZXMuaXJpZGVzY2VuY2VUaGlja25lc3NNYXhpbXVtID8/IDQwMDtcclxuXHJcbiAgICAgICAgaWYgKHByb3BlcnRpZXMuaXJpZGVzY2VuY2VUZXh0dXJlKSB7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIubG9hZFRleHR1cmVJbmZvQXN5bmMoYCR7Y29udGV4dH0vaXJpZGVzY2VuY2VUZXh0dXJlYCwgcHJvcGVydGllcy5pcmlkZXNjZW5jZVRleHR1cmUsICh0ZXh0dXJlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGV4dHVyZS5uYW1lID0gYCR7YmFieWxvbk1hdGVyaWFsLm5hbWV9IChJcmlkZXNjZW5jZSBJbnRlbnNpdHkpYDtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuaXJpZGVzY2VuY2UudGV4dHVyZSA9IHRleHR1cmU7XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHByb3BlcnRpZXMuaXJpZGVzY2VuY2VUaGlja25lc3NUZXh0dXJlKSB7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIubG9hZFRleHR1cmVJbmZvQXN5bmMoYCR7Y29udGV4dH0vaXJpZGVzY2VuY2VUaGlja25lc3NUZXh0dXJlYCwgcHJvcGVydGllcy5pcmlkZXNjZW5jZVRoaWNrbmVzc1RleHR1cmUsICh0ZXh0dXJlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGV4dHVyZS5uYW1lID0gYCR7YmFieWxvbk1hdGVyaWFsLm5hbWV9IChJcmlkZXNjZW5jZSBUaGlja25lc3MpYDtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuaXJpZGVzY2VuY2UudGhpY2tuZXNzVGV4dHVyZSA9IHRleHR1cmU7XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IHt9KTtcclxuICAgIH1cclxufVxyXG5cclxuR0xURkxvYWRlci5SZWdpc3RlckV4dGVuc2lvbihOQU1FLCAobG9hZGVyKSA9PiBuZXcgS0hSX21hdGVyaWFsc19pcmlkZXNjZW5jZShsb2FkZXIpKTtcclxuIiwiaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB7IENvbG9yMyB9IGZyb20gXCJjb3JlL01hdGhzL21hdGguY29sb3JcIjtcclxuaW1wb3J0IHsgUEJSTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvUEJSL3Bick1hdGVyaWFsXCI7XHJcbmltcG9ydCB0eXBlIHsgTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvbWF0ZXJpYWxcIjtcclxuXHJcbmltcG9ydCB0eXBlIHsgSU1hdGVyaWFsIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcbmltcG9ydCB0eXBlIHsgSUdMVEZMb2FkZXJFeHRlbnNpb24gfSBmcm9tIFwiLi4vZ2xURkxvYWRlckV4dGVuc2lvblwiO1xyXG5pbXBvcnQgeyBHTFRGTG9hZGVyIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJcIjtcclxuaW1wb3J0IHR5cGUgeyBJS0hSTWF0ZXJpYWxzUGJyU3BlY3VsYXJHbG9zc2luZXNzIH0gZnJvbSBcImJhYnlsb25qcy1nbHRmMmludGVyZmFjZVwiO1xyXG5cclxuY29uc3QgTkFNRSA9IFwiS0hSX21hdGVyaWFsc19wYnJTcGVjdWxhckdsb3NzaW5lc3NcIjtcclxuXHJcbi8qKlxyXG4gKiBbU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly9naXRodWIuY29tL0tocm9ub3NHcm91cC9nbFRGL2Jsb2IvbWFpbi9leHRlbnNpb25zLzIuMC9BcmNoaXZlZC9LSFJfbWF0ZXJpYWxzX3BiclNwZWN1bGFyR2xvc3NpbmVzcy9SRUFETUUubWQpXHJcbiAqL1xyXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXHJcbmV4cG9ydCBjbGFzcyBLSFJfbWF0ZXJpYWxzX3BiclNwZWN1bGFyR2xvc3NpbmVzcyBpbXBsZW1lbnRzIElHTFRGTG9hZGVyRXh0ZW5zaW9uIHtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIG5hbWUgb2YgdGhpcyBleHRlbnNpb24uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyByZWFkb25seSBuYW1lID0gTkFNRTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgd2hldGhlciB0aGlzIGV4dGVuc2lvbiBpcyBlbmFibGVkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZW5hYmxlZDogYm9vbGVhbjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgYSBudW1iZXIgdGhhdCBkZXRlcm1pbmVzIHRoZSBvcmRlciB0aGUgZXh0ZW5zaW9ucyBhcmUgYXBwbGllZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIG9yZGVyID0gMjAwO1xyXG5cclxuICAgIHByaXZhdGUgX2xvYWRlcjogR0xURkxvYWRlcjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3Rvcihsb2FkZXI6IEdMVEZMb2FkZXIpIHtcclxuICAgICAgICB0aGlzLl9sb2FkZXIgPSBsb2FkZXI7XHJcbiAgICAgICAgdGhpcy5lbmFibGVkID0gdGhpcy5fbG9hZGVyLmlzRXh0ZW5zaW9uVXNlZChOQU1FKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpIHtcclxuICAgICAgICAodGhpcy5fbG9hZGVyIGFzIGFueSkgPSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkTWF0ZXJpYWxQcm9wZXJ0aWVzQXN5bmMoY29udGV4dDogc3RyaW5nLCBtYXRlcmlhbDogSU1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWw6IE1hdGVyaWFsKTogTnVsbGFibGU8UHJvbWlzZTx2b2lkPj4ge1xyXG4gICAgICAgIHJldHVybiBHTFRGTG9hZGVyLkxvYWRFeHRlbnNpb25Bc3luYzxJS0hSTWF0ZXJpYWxzUGJyU3BlY3VsYXJHbG9zc2luZXNzPihjb250ZXh0LCBtYXRlcmlhbCwgdGhpcy5uYW1lLCAoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkZXIubG9hZE1hdGVyaWFsQmFzZVByb3BlcnRpZXNBc3luYyhjb250ZXh0LCBtYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsKSk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fbG9hZFNwZWN1bGFyR2xvc3NpbmVzc1Byb3BlcnRpZXNBc3luYyhleHRlbnNpb25Db250ZXh0LCBtYXRlcmlhbCwgZXh0ZW5zaW9uLCBiYWJ5bG9uTWF0ZXJpYWwpKTtcclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvYWRNYXRlcmlhbEFscGhhUHJvcGVydGllcyhjb250ZXh0LCBtYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsKTtcclxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IHt9KTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9sb2FkU3BlY3VsYXJHbG9zc2luZXNzUHJvcGVydGllc0FzeW5jKGNvbnRleHQ6IHN0cmluZywgbWF0ZXJpYWw6IElNYXRlcmlhbCwgcHJvcGVydGllczogSUtIUk1hdGVyaWFsc1BiclNwZWN1bGFyR2xvc3NpbmVzcywgYmFieWxvbk1hdGVyaWFsOiBNYXRlcmlhbCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGlmICghKGJhYnlsb25NYXRlcmlhbCBpbnN0YW5jZW9mIFBCUk1hdGVyaWFsKSkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29udGV4dH06IE1hdGVyaWFsIHR5cGUgbm90IHN1cHBvcnRlZGApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBuZXcgQXJyYXk8UHJvbWlzZTxhbnk+PigpO1xyXG5cclxuICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwubWV0YWxsaWMgPSBudWxsO1xyXG4gICAgICAgIGJhYnlsb25NYXRlcmlhbC5yb3VnaG5lc3MgPSBudWxsO1xyXG5cclxuICAgICAgICBpZiAocHJvcGVydGllcy5kaWZmdXNlRmFjdG9yKSB7XHJcbiAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5hbGJlZG9Db2xvciA9IENvbG9yMy5Gcm9tQXJyYXkocHJvcGVydGllcy5kaWZmdXNlRmFjdG9yKTtcclxuICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLmFscGhhID0gcHJvcGVydGllcy5kaWZmdXNlRmFjdG9yWzNdO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5hbGJlZG9Db2xvciA9IENvbG9yMy5XaGl0ZSgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgYmFieWxvbk1hdGVyaWFsLnJlZmxlY3Rpdml0eUNvbG9yID0gcHJvcGVydGllcy5zcGVjdWxhckZhY3RvciA/IENvbG9yMy5Gcm9tQXJyYXkocHJvcGVydGllcy5zcGVjdWxhckZhY3RvcikgOiBDb2xvcjMuV2hpdGUoKTtcclxuICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwubWljcm9TdXJmYWNlID0gcHJvcGVydGllcy5nbG9zc2luZXNzRmFjdG9yID09IHVuZGVmaW5lZCA/IDEgOiBwcm9wZXJ0aWVzLmdsb3NzaW5lc3NGYWN0b3I7XHJcblxyXG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLmRpZmZ1c2VUZXh0dXJlKSB7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIubG9hZFRleHR1cmVJbmZvQXN5bmMoYCR7Y29udGV4dH0vZGlmZnVzZVRleHR1cmVgLCBwcm9wZXJ0aWVzLmRpZmZ1c2VUZXh0dXJlLCAodGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRleHR1cmUubmFtZSA9IGAke2JhYnlsb25NYXRlcmlhbC5uYW1lfSAoRGlmZnVzZSlgO1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5hbGJlZG9UZXh0dXJlID0gdGV4dHVyZTtcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocHJvcGVydGllcy5zcGVjdWxhckdsb3NzaW5lc3NUZXh0dXJlKSB7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIubG9hZFRleHR1cmVJbmZvQXN5bmMoYCR7Y29udGV4dH0vc3BlY3VsYXJHbG9zc2luZXNzVGV4dHVyZWAsIHByb3BlcnRpZXMuc3BlY3VsYXJHbG9zc2luZXNzVGV4dHVyZSwgKHRleHR1cmUpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICB0ZXh0dXJlLm5hbWUgPSBgJHtiYWJ5bG9uTWF0ZXJpYWwubmFtZX0gKFNwZWN1bGFyIEdsb3NzaW5lc3MpYDtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwucmVmbGVjdGl2aXR5VGV4dHVyZSA9IHRleHR1cmU7XHJcbiAgICAgICAgICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLnJlZmxlY3Rpdml0eVRleHR1cmUuaGFzQWxwaGEgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC51c2VNaWNyb1N1cmZhY2VGcm9tUmVmbGVjdGl2aXR5TWFwQWxwaGEgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IHt9KTtcclxuICAgIH1cclxufVxyXG5cclxuR0xURkxvYWRlci5SZWdpc3RlckV4dGVuc2lvbihOQU1FLCAobG9hZGVyKSA9PiBuZXcgS0hSX21hdGVyaWFsc19wYnJTcGVjdWxhckdsb3NzaW5lc3MobG9hZGVyKSk7XHJcbiIsImltcG9ydCB0eXBlIHsgTnVsbGFibGUgfSBmcm9tIFwiY29yZS90eXBlc1wiO1xyXG5pbXBvcnQgeyBQQlJNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9QQlIvcGJyTWF0ZXJpYWxcIjtcclxuaW1wb3J0IHR5cGUgeyBNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9tYXRlcmlhbFwiO1xyXG5cclxuaW1wb3J0IHR5cGUgeyBJTWF0ZXJpYWwsIElUZXh0dXJlSW5mbyB9IGZyb20gXCIuLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcbmltcG9ydCB7IENvbG9yMyB9IGZyb20gXCJjb3JlL01hdGhzL21hdGguY29sb3JcIjtcclxuaW1wb3J0IHR5cGUgeyBJS0hSTWF0ZXJpYWxzU2hlZW4gfSBmcm9tIFwiYmFieWxvbmpzLWdsdGYyaW50ZXJmYWNlXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJLSFJfbWF0ZXJpYWxzX3NoZWVuXCI7XHJcblxyXG4vKipcclxuICogW1NwZWNpZmljYXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9LaHJvbm9zR3JvdXAvZ2xURi9ibG9iL21haW4vZXh0ZW5zaW9ucy8yLjAvS2hyb25vcy9LSFJfbWF0ZXJpYWxzX3NoZWVuL1JFQURNRS5tZClcclxuICogW1BsYXlncm91bmQgU2FtcGxlXShodHRwczovL3d3dy5iYWJ5bG9uanMtcGxheWdyb3VuZC5jb20vZnJhbWUuaHRtbCNCTklaWDYjNClcclxuICovXHJcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cclxuZXhwb3J0IGNsYXNzIEtIUl9tYXRlcmlhbHNfc2hlZW4gaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGEgbnVtYmVyIHRoYXQgZGV0ZXJtaW5lcyB0aGUgb3JkZXIgdGhlIGV4dGVuc2lvbnMgYXJlIGFwcGxpZWQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBvcmRlciA9IDE5MDtcclxuXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGVyOiBHTFRGTG9hZGVyKSB7XHJcbiAgICAgICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyO1xyXG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IHRoaXMuX2xvYWRlci5pc0V4dGVuc2lvblVzZWQoTkFNRSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKSB7XHJcbiAgICAgICAgKHRoaXMuX2xvYWRlciBhcyBhbnkpID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZE1hdGVyaWFsUHJvcGVydGllc0FzeW5jKGNvbnRleHQ6IHN0cmluZywgbWF0ZXJpYWw6IElNYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsOiBNYXRlcmlhbCk6IE51bGxhYmxlPFByb21pc2U8dm9pZD4+IHtcclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SUtIUk1hdGVyaWFsc1NoZWVuPihjb250ZXh0LCBtYXRlcmlhbCwgdGhpcy5uYW1lLCAoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkZXIubG9hZE1hdGVyaWFsUHJvcGVydGllc0FzeW5jKGNvbnRleHQsIG1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWwpKTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkU2hlZW5Qcm9wZXJ0aWVzQXN5bmMoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uLCBiYWJ5bG9uTWF0ZXJpYWwpKTtcclxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IHt9KTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9sb2FkU2hlZW5Qcm9wZXJ0aWVzQXN5bmMoY29udGV4dDogc3RyaW5nLCBwcm9wZXJ0aWVzOiBJS0hSTWF0ZXJpYWxzU2hlZW4sIGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBpZiAoIShiYWJ5bG9uTWF0ZXJpYWwgaW5zdGFuY2VvZiBQQlJNYXRlcmlhbCkpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBNYXRlcmlhbCB0eXBlIG5vdCBzdXBwb3J0ZWRgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuXHJcbiAgICAgICAgYmFieWxvbk1hdGVyaWFsLnNoZWVuLmlzRW5hYmxlZCA9IHRydWU7XHJcbiAgICAgICAgYmFieWxvbk1hdGVyaWFsLnNoZWVuLmludGVuc2l0eSA9IDE7XHJcblxyXG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLnNoZWVuQ29sb3JGYWN0b3IgIT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5zaGVlbi5jb2xvciA9IENvbG9yMy5Gcm9tQXJyYXkocHJvcGVydGllcy5zaGVlbkNvbG9yRmFjdG9yKTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuc2hlZW4uY29sb3IgPSBDb2xvcjMuQmxhY2soKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLnNoZWVuQ29sb3JUZXh0dXJlKSB7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIubG9hZFRleHR1cmVJbmZvQXN5bmMoYCR7Y29udGV4dH0vc2hlZW5Db2xvclRleHR1cmVgLCBwcm9wZXJ0aWVzLnNoZWVuQ29sb3JUZXh0dXJlLCAodGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRleHR1cmUubmFtZSA9IGAke2JhYnlsb25NYXRlcmlhbC5uYW1lfSAoU2hlZW4gQ29sb3IpYDtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuc2hlZW4udGV4dHVyZSA9IHRleHR1cmU7XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHByb3BlcnRpZXMuc2hlZW5Sb3VnaG5lc3NGYWN0b3IgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuc2hlZW4ucm91Z2huZXNzID0gcHJvcGVydGllcy5zaGVlblJvdWdobmVzc0ZhY3RvcjtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuc2hlZW4ucm91Z2huZXNzID0gMDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLnNoZWVuUm91Z2huZXNzVGV4dHVyZSkge1xyXG4gICAgICAgICAgICAocHJvcGVydGllcy5zaGVlblJvdWdobmVzc1RleHR1cmUgYXMgSVRleHR1cmVJbmZvKS5ub25Db2xvckRhdGEgPSB0cnVlO1xyXG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKFxyXG4gICAgICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvYWRUZXh0dXJlSW5mb0FzeW5jKGAke2NvbnRleHR9L3NoZWVuUm91Z2huZXNzVGV4dHVyZWAsIHByb3BlcnRpZXMuc2hlZW5Sb3VnaG5lc3NUZXh0dXJlLCAodGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRleHR1cmUubmFtZSA9IGAke2JhYnlsb25NYXRlcmlhbC5uYW1lfSAoU2hlZW4gUm91Z2huZXNzKWA7XHJcbiAgICAgICAgICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLnNoZWVuLnRleHR1cmVSb3VnaG5lc3MgPSB0ZXh0dXJlO1xyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGJhYnlsb25NYXRlcmlhbC5zaGVlbi5hbGJlZG9TY2FsaW5nID0gdHJ1ZTtcclxuICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuc2hlZW4udXNlUm91Z2huZXNzRnJvbU1haW5UZXh0dXJlID0gZmFsc2U7XHJcblxyXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7fSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbkdMVEZMb2FkZXIuUmVnaXN0ZXJFeHRlbnNpb24oTkFNRSwgKGxvYWRlcikgPT4gbmV3IEtIUl9tYXRlcmlhbHNfc2hlZW4obG9hZGVyKSk7XHJcbiIsImltcG9ydCB0eXBlIHsgTnVsbGFibGUgfSBmcm9tIFwiY29yZS90eXBlc1wiO1xyXG5pbXBvcnQgeyBQQlJNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9QQlIvcGJyTWF0ZXJpYWxcIjtcclxuaW1wb3J0IHR5cGUgeyBNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9tYXRlcmlhbFwiO1xyXG5cclxuaW1wb3J0IHR5cGUgeyBJTWF0ZXJpYWwsIElUZXh0dXJlSW5mbyB9IGZyb20gXCIuLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcbmltcG9ydCB7IENvbG9yMyB9IGZyb20gXCJjb3JlL01hdGhzL21hdGguY29sb3JcIjtcclxuaW1wb3J0IHR5cGUgeyBJS0hSTWF0ZXJpYWxzU3BlY3VsYXIgfSBmcm9tIFwiYmFieWxvbmpzLWdsdGYyaW50ZXJmYWNlXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJLSFJfbWF0ZXJpYWxzX3NwZWN1bGFyXCI7XHJcblxyXG4vKipcclxuICogW1NwZWNpZmljYXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9LaHJvbm9zR3JvdXAvZ2xURi9ibG9iL21haW4vZXh0ZW5zaW9ucy8yLjAvS2hyb25vcy9LSFJfbWF0ZXJpYWxzX3NwZWN1bGFyL1JFQURNRS5tZClcclxuICovXHJcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cclxuZXhwb3J0IGNsYXNzIEtIUl9tYXRlcmlhbHNfc3BlY3VsYXIgaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGEgbnVtYmVyIHRoYXQgZGV0ZXJtaW5lcyB0aGUgb3JkZXIgdGhlIGV4dGVuc2lvbnMgYXJlIGFwcGxpZWQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBvcmRlciA9IDE5MDtcclxuXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGVyOiBHTFRGTG9hZGVyKSB7XHJcbiAgICAgICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyO1xyXG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IHRoaXMuX2xvYWRlci5pc0V4dGVuc2lvblVzZWQoTkFNRSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKSB7XHJcbiAgICAgICAgKHRoaXMuX2xvYWRlciBhcyBhbnkpID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZE1hdGVyaWFsUHJvcGVydGllc0FzeW5jKGNvbnRleHQ6IHN0cmluZywgbWF0ZXJpYWw6IElNYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsOiBNYXRlcmlhbCk6IE51bGxhYmxlPFByb21pc2U8dm9pZD4+IHtcclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SUtIUk1hdGVyaWFsc1NwZWN1bGFyPihjb250ZXh0LCBtYXRlcmlhbCwgdGhpcy5uYW1lLCAoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkZXIubG9hZE1hdGVyaWFsUHJvcGVydGllc0FzeW5jKGNvbnRleHQsIG1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWwpKTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkU3BlY3VsYXJQcm9wZXJ0aWVzQXN5bmMoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uLCBiYWJ5bG9uTWF0ZXJpYWwpKTtcclxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IHt9KTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9sb2FkU3BlY3VsYXJQcm9wZXJ0aWVzQXN5bmMoY29udGV4dDogc3RyaW5nLCBwcm9wZXJ0aWVzOiBJS0hSTWF0ZXJpYWxzU3BlY3VsYXIsIGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBpZiAoIShiYWJ5bG9uTWF0ZXJpYWwgaW5zdGFuY2VvZiBQQlJNYXRlcmlhbCkpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBNYXRlcmlhbCB0eXBlIG5vdCBzdXBwb3J0ZWRgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuXHJcbiAgICAgICAgaWYgKHByb3BlcnRpZXMuc3BlY3VsYXJGYWN0b3IgIT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwubWV0YWxsaWNGMEZhY3RvciA9IHByb3BlcnRpZXMuc3BlY3VsYXJGYWN0b3I7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocHJvcGVydGllcy5zcGVjdWxhckNvbG9yRmFjdG9yICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLm1ldGFsbGljUmVmbGVjdGFuY2VDb2xvciA9IENvbG9yMy5Gcm9tQXJyYXkocHJvcGVydGllcy5zcGVjdWxhckNvbG9yRmFjdG9yKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLnNwZWN1bGFyVGV4dHVyZSkge1xyXG4gICAgICAgICAgICAocHJvcGVydGllcy5zcGVjdWxhclRleHR1cmUgYXMgSVRleHR1cmVJbmZvKS5ub25Db2xvckRhdGEgPSB0cnVlO1xyXG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKFxyXG4gICAgICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvYWRUZXh0dXJlSW5mb0FzeW5jKGAke2NvbnRleHR9L3NwZWN1bGFyVGV4dHVyZWAsIHByb3BlcnRpZXMuc3BlY3VsYXJUZXh0dXJlLCAodGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRleHR1cmUubmFtZSA9IGAke2JhYnlsb25NYXRlcmlhbC5uYW1lfSAoU3BlY3VsYXIgRjAgU3RyZW5ndGgpYDtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwubWV0YWxsaWNSZWZsZWN0YW5jZVRleHR1cmUgPSB0ZXh0dXJlO1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC51c2VPbmx5TWV0YWxsaWNGcm9tTWV0YWxsaWNSZWZsZWN0YW5jZVRleHR1cmUgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChwcm9wZXJ0aWVzLnNwZWN1bGFyQ29sb3JUZXh0dXJlKSB7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIubG9hZFRleHR1cmVJbmZvQXN5bmMoYCR7Y29udGV4dH0vc3BlY3VsYXJDb2xvclRleHR1cmVgLCBwcm9wZXJ0aWVzLnNwZWN1bGFyQ29sb3JUZXh0dXJlLCAodGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRleHR1cmUubmFtZSA9IGAke2JhYnlsb25NYXRlcmlhbC5uYW1lfSAoU3BlY3VsYXIgRjAgQ29sb3IpYDtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwucmVmbGVjdGFuY2VUZXh0dXJlID0gdGV4dHVyZTtcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge30pO1xyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKE5BTUUsIChsb2FkZXIpID0+IG5ldyBLSFJfbWF0ZXJpYWxzX3NwZWN1bGFyKGxvYWRlcikpO1xyXG4iLCJpbXBvcnQgdHlwZSB7IE51bGxhYmxlIH0gZnJvbSBcImNvcmUvdHlwZXNcIjtcclxuaW1wb3J0IHsgUEJSTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvUEJSL3Bick1hdGVyaWFsXCI7XHJcbmltcG9ydCB0eXBlIHsgTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvbWF0ZXJpYWxcIjtcclxuaW1wb3J0IHR5cGUgeyBCYXNlVGV4dHVyZSB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9UZXh0dXJlcy9iYXNlVGV4dHVyZVwiO1xyXG5pbXBvcnQgdHlwZSB7IElNYXRlcmlhbCwgSVRleHR1cmVJbmZvIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcbmltcG9ydCB0eXBlIHsgSUdMVEZMb2FkZXJFeHRlbnNpb24gfSBmcm9tIFwiLi4vZ2xURkxvYWRlckV4dGVuc2lvblwiO1xyXG5pbXBvcnQgeyBHTFRGTG9hZGVyIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJcIjtcclxuaW1wb3J0IHR5cGUgeyBJS0hSTWF0ZXJpYWxzVHJhbnNsdWNlbmN5IH0gZnJvbSBcImJhYnlsb25qcy1nbHRmMmludGVyZmFjZVwiO1xyXG5cclxuY29uc3QgTkFNRSA9IFwiS0hSX21hdGVyaWFsc190cmFuc2x1Y2VuY3lcIjtcclxuXHJcbi8qKlxyXG4gKiBbUHJvcG9zZWQgU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly9naXRodWIuY29tL0tocm9ub3NHcm91cC9nbFRGL3B1bGwvMTgyNSlcclxuICogISEhIEV4cGVyaW1lbnRhbCBFeHRlbnNpb24gU3ViamVjdCB0byBDaGFuZ2VzICEhIVxyXG4gKi9cclxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxyXG5leHBvcnQgY2xhc3MgS0hSX21hdGVyaWFsc190cmFuc2x1Y2VuY3kgaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGEgbnVtYmVyIHRoYXQgZGV0ZXJtaW5lcyB0aGUgb3JkZXIgdGhlIGV4dGVuc2lvbnMgYXJlIGFwcGxpZWQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBvcmRlciA9IDE3NDtcclxuXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGVyOiBHTFRGTG9hZGVyKSB7XHJcbiAgICAgICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyO1xyXG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IHRoaXMuX2xvYWRlci5pc0V4dGVuc2lvblVzZWQoTkFNRSk7XHJcbiAgICAgICAgaWYgKHRoaXMuZW5hYmxlZCkge1xyXG4gICAgICAgICAgICBsb2FkZXIucGFyZW50LnRyYW5zcGFyZW5jeUFzQ292ZXJhZ2UgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpIHtcclxuICAgICAgICAodGhpcy5fbG9hZGVyIGFzIGFueSkgPSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkTWF0ZXJpYWxQcm9wZXJ0aWVzQXN5bmMoY29udGV4dDogc3RyaW5nLCBtYXRlcmlhbDogSU1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWw6IE1hdGVyaWFsKTogTnVsbGFibGU8UHJvbWlzZTx2b2lkPj4ge1xyXG4gICAgICAgIHJldHVybiBHTFRGTG9hZGVyLkxvYWRFeHRlbnNpb25Bc3luYzxJS0hSTWF0ZXJpYWxzVHJhbnNsdWNlbmN5Pihjb250ZXh0LCBtYXRlcmlhbCwgdGhpcy5uYW1lLCAoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkZXIubG9hZE1hdGVyaWFsQmFzZVByb3BlcnRpZXNBc3luYyhjb250ZXh0LCBtYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsKSk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fbG9hZGVyLmxvYWRNYXRlcmlhbFByb3BlcnRpZXNBc3luYyhjb250ZXh0LCBtYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsKSk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fbG9hZFRyYW5zbHVjZW50UHJvcGVydGllc0FzeW5jKGV4dGVuc2lvbkNvbnRleHQsIG1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWwsIGV4dGVuc2lvbikpO1xyXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge30pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2xvYWRUcmFuc2x1Y2VudFByb3BlcnRpZXNBc3luYyhjb250ZXh0OiBzdHJpbmcsIG1hdGVyaWFsOiBJTWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwsIGV4dGVuc2lvbjogSUtIUk1hdGVyaWFsc1RyYW5zbHVjZW5jeSk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGlmICghKGJhYnlsb25NYXRlcmlhbCBpbnN0YW5jZW9mIFBCUk1hdGVyaWFsKSkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29udGV4dH06IE1hdGVyaWFsIHR5cGUgbm90IHN1cHBvcnRlZGApO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCBwYnJNYXRlcmlhbCA9IGJhYnlsb25NYXRlcmlhbCBhcyBQQlJNYXRlcmlhbDtcclxuXHJcbiAgICAgICAgLy8gRW5hYmxlcyBcInRyYW5zbHVjZW5jeVwiIHRleHR1cmUgd2hpY2ggcmVwcmVzZW50cyBkaWZmdXNlbHktdHJhbnNtaXR0ZWQgbGlnaHQuXHJcbiAgICAgICAgcGJyTWF0ZXJpYWwuc3ViU3VyZmFjZS5pc1RyYW5zbHVjZW5jeUVuYWJsZWQgPSB0cnVlO1xyXG5cclxuICAgICAgICAvLyBTaW5jZSB0aGlzIGV4dGVuc2lvbiBtb2RlbHMgdGhpbi1zdXJmYWNlIHRyYW5zbWlzc2lvbiBvbmx5LCB3ZSBtdXN0IG1ha2UgdGhlXHJcbiAgICAgICAgLy8gaW50ZXJuYWwgSU9SID09IDEuMCBhbmQgc2V0IHRoZSB0aGlja25lc3MgdG8gMC5cclxuICAgICAgICBwYnJNYXRlcmlhbC5zdWJTdXJmYWNlLnZvbHVtZUluZGV4T2ZSZWZyYWN0aW9uID0gMS4wO1xyXG4gICAgICAgIHBick1hdGVyaWFsLnN1YlN1cmZhY2UubWluaW11bVRoaWNrbmVzcyA9IDAuMDtcclxuICAgICAgICBwYnJNYXRlcmlhbC5zdWJTdXJmYWNlLm1heGltdW1UaGlja25lc3MgPSAwLjA7XHJcblxyXG4gICAgICAgIC8vIEFsYmVkbyBjb2xvdXIgd2lsbCB0aW50IHRyYW5zbWlzc2lvbi5cclxuICAgICAgICBwYnJNYXRlcmlhbC5zdWJTdXJmYWNlLnVzZUFsYmVkb1RvVGludFRyYW5zbHVjZW5jeSA9IHRydWU7XHJcblxyXG4gICAgICAgIGlmIChleHRlbnNpb24udHJhbnNsdWNlbmN5RmFjdG9yICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgcGJyTWF0ZXJpYWwuc3ViU3VyZmFjZS50cmFuc2x1Y2VuY3lJbnRlbnNpdHkgPSBleHRlbnNpb24udHJhbnNsdWNlbmN5RmFjdG9yO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHBick1hdGVyaWFsLnN1YlN1cmZhY2UudHJhbnNsdWNlbmN5SW50ZW5zaXR5ID0gMC4wO1xyXG4gICAgICAgICAgICBwYnJNYXRlcmlhbC5zdWJTdXJmYWNlLmlzVHJhbnNsdWNlbmN5RW5hYmxlZCA9IGZhbHNlO1xyXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoZXh0ZW5zaW9uLnRyYW5zbHVjZW5jeVRleHR1cmUpIHtcclxuICAgICAgICAgICAgKGV4dGVuc2lvbi50cmFuc2x1Y2VuY3lUZXh0dXJlIGFzIElUZXh0dXJlSW5mbykubm9uQ29sb3JEYXRhID0gdHJ1ZTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2xvYWRlci5sb2FkVGV4dHVyZUluZm9Bc3luYyhgJHtjb250ZXh0fS90cmFuc2x1Y2VuY3lUZXh0dXJlYCwgZXh0ZW5zaW9uLnRyYW5zbHVjZW5jeVRleHR1cmUpLnRoZW4oKHRleHR1cmU6IEJhc2VUZXh0dXJlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBwYnJNYXRlcmlhbC5zdWJTdXJmYWNlLnRyYW5zbHVjZW5jeUludGVuc2l0eVRleHR1cmUgPSB0ZXh0dXJlO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKE5BTUUsIChsb2FkZXIpID0+IG5ldyBLSFJfbWF0ZXJpYWxzX3RyYW5zbHVjZW5jeShsb2FkZXIpKTtcclxuIiwiaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB7IFBCUk1hdGVyaWFsIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL1BCUi9wYnJNYXRlcmlhbFwiO1xyXG5pbXBvcnQgdHlwZSB7IE1hdGVyaWFsIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL21hdGVyaWFsXCI7XHJcbmltcG9ydCB0eXBlIHsgQmFzZVRleHR1cmUgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvVGV4dHVyZXMvYmFzZVRleHR1cmVcIjtcclxuaW1wb3J0IHR5cGUgeyBJTWF0ZXJpYWwsIElUZXh0dXJlSW5mbyB9IGZyb20gXCIuLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgSUtIUk1hdGVyaWFsc1RyYW5zbWlzc2lvbiB9IGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuaW1wb3J0IHR5cGUgeyBTY2VuZSB9IGZyb20gXCJjb3JlL3NjZW5lXCI7XHJcbmltcG9ydCB0eXBlIHsgQWJzdHJhY3RNZXNoIH0gZnJvbSBcImNvcmUvTWVzaGVzL2Fic3RyYWN0TWVzaFwiO1xyXG5pbXBvcnQgdHlwZSB7IFRleHR1cmUgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvVGV4dHVyZXMvdGV4dHVyZVwiO1xyXG5pbXBvcnQgeyBSZW5kZXJUYXJnZXRUZXh0dXJlIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL1RleHR1cmVzL3JlbmRlclRhcmdldFRleHR1cmVcIjtcclxuaW1wb3J0IHR5cGUgeyBPYnNlcnZlciB9IGZyb20gXCJjb3JlL01pc2Mvb2JzZXJ2YWJsZVwiO1xyXG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSBcImNvcmUvTWlzYy9vYnNlcnZhYmxlXCI7XHJcbmltcG9ydCB7IENvbnN0YW50cyB9IGZyb20gXCJjb3JlL0VuZ2luZXMvY29uc3RhbnRzXCI7XHJcbmltcG9ydCB7IFRvb2xzIH0gZnJvbSBcImNvcmUvTWlzYy90b29sc1wiO1xyXG5pbXBvcnQgdHlwZSB7IENvbG9yNCB9IGZyb20gXCJjb3JlL01hdGhzL21hdGguY29sb3JcIjtcclxuXHJcbmludGVyZmFjZSBJVHJhbnNtaXNzaW9uSGVscGVySG9sZGVyIHtcclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIF90cmFuc21pc3Npb25IZWxwZXI6IFRyYW5zbWlzc2lvbkhlbHBlciB8IHVuZGVmaW5lZDtcclxufVxyXG5cclxuaW50ZXJmYWNlIElUcmFuc21pc3Npb25IZWxwZXJPcHRpb25zIHtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIHNpemUgb2YgdGhlIHJlbmRlciBidWZmZXJzIChkZWZhdWx0OiAxMDI0KVxyXG4gICAgICovXHJcbiAgICByZW5kZXJTaXplOiBudW1iZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgbnVtYmVyIG9mIHNhbXBsZXMgdG8gdXNlIHdoZW4gZ2VuZXJhdGluZyB0aGUgcmVuZGVyIHRhcmdldCB0ZXh0dXJlIGZvciBvcGFxdWUgbWVzaGVzIChkZWZhdWx0OiA0KVxyXG4gICAgICovXHJcbiAgICBzYW1wbGVzOiBudW1iZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTY2FsZSB0byBhcHBseSB3aGVuIHNlbGVjdGluZyB0aGUgTE9EIGxldmVsIHRvIHNhbXBsZSB0aGUgcmVmcmFjdGlvbiB0ZXh0dXJlIChkZWZhdWx0OiAxKVxyXG4gICAgICovXHJcbiAgICBsb2RHZW5lcmF0aW9uU2NhbGU6IG51bWJlcjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIE9mZnNldCB0byBhcHBseSB3aGVuIHNlbGVjdGluZyB0aGUgTE9EIGxldmVsIHRvIHNhbXBsZSB0aGUgcmVmcmFjdGlvbiB0ZXh0dXJlIChkZWZhdWx0OiAtNClcclxuICAgICAqL1xyXG4gICAgbG9kR2VuZXJhdGlvbk9mZnNldDogbnVtYmVyO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVHlwZSBvZiB0aGUgcmVmcmFjdGlvbiByZW5kZXIgdGFyZ2V0IHRleHR1cmUgKGRlZmF1bHQ6IFRFWFRVUkVUWVBFX0hBTEZfRkxPQVQpXHJcbiAgICAgKi9cclxuICAgIHJlbmRlclRhcmdldFRleHR1cmVUeXBlOiBudW1iZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGlmIHRoZSBtaXBtYXBzIGZvciB0aGUgcmVmcmFjdGlvbiByZW5kZXIgdGFyZ2V0IHRleHR1cmUgbXVzdCBiZSBnZW5lcmF0ZWQgKGRlZmF1bHQ6IHRydWUpXHJcbiAgICAgKi9cclxuICAgIGdlbmVyYXRlTWlwbWFwczogYm9vbGVhbjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENsZWFyIGNvbG9yIG9mIHRoZSBvcGFxdWUgdGV4dHVyZS4gSWYgbm90IHByb3ZpZGVkLCB1c2UgdGhlIHNjZW5lIGNsZWFyIGNvbG9yICh3aGljaCB3aWxsIGJlIGNvbnZlcnRlZCB0byBsaW5lYXIgc3BhY2UpLlxyXG4gICAgICogSWYgcHJvdmlkZWQsIHNob3VsZCBiZSBpbiBsaW5lYXIgc3BhY2VcclxuICAgICAqL1xyXG4gICAgY2xlYXJDb2xvcj86IENvbG9yNDtcclxufVxyXG5cclxuLyoqXHJcbiAqIEEgY2xhc3MgdG8gaGFuZGxlIHNldHRpbmcgdXAgdGhlIHJlbmRlcmluZyBvZiBvcGFxdWUgb2JqZWN0cyB0byBiZSBzaG93biB0aHJvdWdoIHRyYW5zbWlzc2l2ZSBvYmplY3RzLlxyXG4gKi9cclxuY2xhc3MgVHJhbnNtaXNzaW9uSGVscGVyIHtcclxuICAgIC8qKlxyXG4gICAgICogQ3JlYXRlcyB0aGUgZGVmYXVsdCBvcHRpb25zIGZvciB0aGUgaGVscGVyLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHN0YXRpYyBfR2V0RGVmYXVsdE9wdGlvbnMoKTogSVRyYW5zbWlzc2lvbkhlbHBlck9wdGlvbnMge1xyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIHJlbmRlclNpemU6IDEwMjQsXHJcbiAgICAgICAgICAgIHNhbXBsZXM6IDQsXHJcbiAgICAgICAgICAgIGxvZEdlbmVyYXRpb25TY2FsZTogMSxcclxuICAgICAgICAgICAgbG9kR2VuZXJhdGlvbk9mZnNldDogLTQsXHJcbiAgICAgICAgICAgIHJlbmRlclRhcmdldFRleHR1cmVUeXBlOiBDb25zdGFudHMuVEVYVFVSRVRZUEVfSEFMRl9GTE9BVCxcclxuICAgICAgICAgICAgZ2VuZXJhdGVNaXBtYXBzOiB0cnVlLFxyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTdG9yZXMgdGhlIGNyZWF0aW9uIG9wdGlvbnMuXHJcbiAgICAgKi9cclxuICAgIHByaXZhdGUgcmVhZG9ubHkgX3NjZW5lOiBTY2VuZSAmIElUcmFuc21pc3Npb25IZWxwZXJIb2xkZXI7XHJcblxyXG4gICAgcHJpdmF0ZSBfb3B0aW9uczogSVRyYW5zbWlzc2lvbkhlbHBlck9wdGlvbnM7XHJcblxyXG4gICAgcHJpdmF0ZSBfb3BhcXVlUmVuZGVyVGFyZ2V0OiBOdWxsYWJsZTxSZW5kZXJUYXJnZXRUZXh0dXJlPiA9IG51bGw7XHJcbiAgICBwcml2YXRlIF9vcGFxdWVNZXNoZXNDYWNoZTogQWJzdHJhY3RNZXNoW10gPSBbXTtcclxuICAgIHByaXZhdGUgX3RyYW5zcGFyZW50TWVzaGVzQ2FjaGU6IEFic3RyYWN0TWVzaFtdID0gW107XHJcbiAgICBwcml2YXRlIF9tYXRlcmlhbE9ic2VydmVyczogeyBbaWQ6IHN0cmluZ106IE51bGxhYmxlPE9ic2VydmVyPEFic3RyYWN0TWVzaD4+IH0gPSB7fTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoaXMgb2JzZXJ2YWJsZSB3aWxsIGJlIG5vdGlmaWVkIHdpdGggYW55IGVycm9yIGR1cmluZyB0aGUgY3JlYXRpb24gb2YgdGhlIGVudmlyb25tZW50LFxyXG4gICAgICogbWFpbmx5IHRleHR1cmUgY3JlYXRpb24gZXJyb3JzLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgb25FcnJvck9ic2VydmFibGU6IE9ic2VydmFibGU8eyBtZXNzYWdlPzogc3RyaW5nOyBleGNlcHRpb24/OiBhbnkgfT47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBjb25zdHJ1Y3RvclxyXG4gICAgICogQHBhcmFtIG9wdGlvbnMgRGVmaW5lcyB0aGUgb3B0aW9ucyB3ZSB3YW50IHRvIGN1c3RvbWl6ZSB0aGUgaGVscGVyXHJcbiAgICAgKiBAcGFyYW0gc2NlbmUgVGhlIHNjZW5lIHRvIGFkZCB0aGUgbWF0ZXJpYWwgdG9cclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3Iob3B0aW9uczogUGFydGlhbDxJVHJhbnNtaXNzaW9uSGVscGVyT3B0aW9ucz4sIHNjZW5lOiBTY2VuZSkge1xyXG4gICAgICAgIHRoaXMuX29wdGlvbnMgPSB7XHJcbiAgICAgICAgICAgIC4uLlRyYW5zbWlzc2lvbkhlbHBlci5fR2V0RGVmYXVsdE9wdGlvbnMoKSxcclxuICAgICAgICAgICAgLi4ub3B0aW9ucyxcclxuICAgICAgICB9O1xyXG4gICAgICAgIHRoaXMuX3NjZW5lID0gc2NlbmUgYXMgYW55O1xyXG4gICAgICAgIHRoaXMuX3NjZW5lLl90cmFuc21pc3Npb25IZWxwZXIgPSB0aGlzO1xyXG5cclxuICAgICAgICB0aGlzLm9uRXJyb3JPYnNlcnZhYmxlID0gbmV3IE9ic2VydmFibGUoKTtcclxuICAgICAgICB0aGlzLl9zY2VuZS5vbkRpc3Bvc2VPYnNlcnZhYmxlLmFkZE9uY2UoKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLmRpc3Bvc2UoKTtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgdGhpcy5fcGFyc2VTY2VuZSgpO1xyXG4gICAgICAgIHRoaXMuX3NldHVwUmVuZGVyVGFyZ2V0cygpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVXBkYXRlcyB0aGUgYmFja2dyb3VuZCBhY2NvcmRpbmcgdG8gdGhlIG5ldyBvcHRpb25zXHJcbiAgICAgKiBAcGFyYW0gb3B0aW9uc1xyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdXBkYXRlT3B0aW9ucyhvcHRpb25zOiBQYXJ0aWFsPElUcmFuc21pc3Npb25IZWxwZXJPcHRpb25zPikge1xyXG4gICAgICAgIC8vIEZpcnN0IGNoZWNrIGlmIGFueSBvcHRpb25zIGFyZSBhY3R1YWxseSBiZWluZyBjaGFuZ2VkLiBJZiBub3QsIGV4aXQuXHJcbiAgICAgICAgY29uc3QgbmV3VmFsdWVzID0gT2JqZWN0LmtleXMob3B0aW9ucykuZmlsdGVyKChrZXk6IHN0cmluZykgPT4gKHRoaXMuX29wdGlvbnMgYXMgYW55KVtrZXldICE9PSAob3B0aW9ucyBhcyBhbnkpW2tleV0pO1xyXG4gICAgICAgIGlmICghbmV3VmFsdWVzLmxlbmd0aCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBuZXdPcHRpb25zID0ge1xyXG4gICAgICAgICAgICAuLi50aGlzLl9vcHRpb25zLFxyXG4gICAgICAgICAgICAuLi5vcHRpb25zLFxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGNvbnN0IG9sZE9wdGlvbnMgPSB0aGlzLl9vcHRpb25zO1xyXG4gICAgICAgIHRoaXMuX29wdGlvbnMgPSBuZXdPcHRpb25zO1xyXG5cclxuICAgICAgICAvLyBJZiBzaXplIGNoYW5nZXMsIHJlY3JlYXRlIGV2ZXJ5dGhpbmdcclxuICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgIG5ld09wdGlvbnMucmVuZGVyU2l6ZSAhPT0gb2xkT3B0aW9ucy5yZW5kZXJTaXplIHx8XHJcbiAgICAgICAgICAgIG5ld09wdGlvbnMucmVuZGVyVGFyZ2V0VGV4dHVyZVR5cGUgIT09IG9sZE9wdGlvbnMucmVuZGVyVGFyZ2V0VGV4dHVyZVR5cGUgfHxcclxuICAgICAgICAgICAgbmV3T3B0aW9ucy5nZW5lcmF0ZU1pcG1hcHMgIT09IG9sZE9wdGlvbnMuZ2VuZXJhdGVNaXBtYXBzIHx8XHJcbiAgICAgICAgICAgICF0aGlzLl9vcGFxdWVSZW5kZXJUYXJnZXRcclxuICAgICAgICApIHtcclxuICAgICAgICAgICAgdGhpcy5fc2V0dXBSZW5kZXJUYXJnZXRzKCk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgdGhpcy5fb3BhcXVlUmVuZGVyVGFyZ2V0LnNhbXBsZXMgPSBuZXdPcHRpb25zLnNhbXBsZXM7XHJcbiAgICAgICAgICAgIHRoaXMuX29wYXF1ZVJlbmRlclRhcmdldC5sb2RHZW5lcmF0aW9uU2NhbGUgPSBuZXdPcHRpb25zLmxvZEdlbmVyYXRpb25TY2FsZTtcclxuICAgICAgICAgICAgdGhpcy5fb3BhcXVlUmVuZGVyVGFyZ2V0LmxvZEdlbmVyYXRpb25PZmZzZXQgPSBuZXdPcHRpb25zLmxvZEdlbmVyYXRpb25PZmZzZXQ7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgb3BhcXVlIHJlbmRlciB0YXJnZXQgdGV4dHVyZSBvciBudWxsIGlmIG5vdCBhdmFpbGFibGUuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXRPcGFxdWVUYXJnZXQoKTogTnVsbGFibGU8VGV4dHVyZT4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9vcGFxdWVSZW5kZXJUYXJnZXQ7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfc2hvdWxkUmVuZGVyQXNUcmFuc21pc3Npb24obWF0ZXJpYWw6IE51bGxhYmxlPE1hdGVyaWFsPik6IGJvb2xlYW4ge1xyXG4gICAgICAgIGlmICghbWF0ZXJpYWwpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAobWF0ZXJpYWwgaW5zdGFuY2VvZiBQQlJNYXRlcmlhbCAmJiBtYXRlcmlhbC5zdWJTdXJmYWNlLmlzUmVmcmFjdGlvbkVuYWJsZWQpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9hZGRNZXNoKG1lc2g6IEFic3RyYWN0TWVzaCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuX21hdGVyaWFsT2JzZXJ2ZXJzW21lc2gudW5pcXVlSWRdID0gbWVzaC5vbk1hdGVyaWFsQ2hhbmdlZE9ic2VydmFibGUuYWRkKHRoaXMuX29uTWVzaE1hdGVyaWFsQ2hhbmdlZC5iaW5kKHRoaXMpKTtcclxuXHJcbiAgICAgICAgLy8gd2UgbmVlZCB0byBkZWZlciB0aGUgcHJvY2Vzc2luZyBiZWNhdXNlIF9hZGRNZXNoIG1heSBiZSBjYWxsZWQgYXMgcGFydCBhcyBhbiBpbnN0YW5jZSBtZXNoIGNyZWF0aW9uLCBpbiB3aGljaCBjYXNlIHNvbWVcclxuICAgICAgICAvLyBpbnRlcm5hbCBwcm9wZXJ0aWVzIGFyZSBub3Qgc2V0dXAgeWV0LCBsaWtlIF9zb3VyY2VNZXNoIChuZWVkZWQgd2hlbiBkb2luZyBtZXNoLm1hdGVyaWFsIGJlbG93KVxyXG4gICAgICAgIFRvb2xzLlNldEltbWVkaWF0ZSgoKSA9PiB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLl9zaG91bGRSZW5kZXJBc1RyYW5zbWlzc2lvbihtZXNoLm1hdGVyaWFsKSkge1xyXG4gICAgICAgICAgICAgICAgKG1lc2gubWF0ZXJpYWwgYXMgUEJSTWF0ZXJpYWwpLnJlZnJhY3Rpb25UZXh0dXJlID0gdGhpcy5fb3BhcXVlUmVuZGVyVGFyZ2V0O1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX3RyYW5zcGFyZW50TWVzaGVzQ2FjaGUuaW5kZXhPZihtZXNoKSA9PT0gLTEpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmFuc3BhcmVudE1lc2hlc0NhY2hlLnB1c2gobWVzaCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fb3BhcXVlTWVzaGVzQ2FjaGUuaW5kZXhPZihtZXNoKSA9PT0gLTEpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9vcGFxdWVNZXNoZXNDYWNoZS5wdXNoKG1lc2gpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfcmVtb3ZlTWVzaChtZXNoOiBBYnN0cmFjdE1lc2gpOiB2b2lkIHtcclxuICAgICAgICBtZXNoLm9uTWF0ZXJpYWxDaGFuZ2VkT2JzZXJ2YWJsZS5yZW1vdmUodGhpcy5fbWF0ZXJpYWxPYnNlcnZlcnNbbWVzaC51bmlxdWVJZF0pO1xyXG4gICAgICAgIGRlbGV0ZSB0aGlzLl9tYXRlcmlhbE9ic2VydmVyc1ttZXNoLnVuaXF1ZUlkXTtcclxuICAgICAgICBsZXQgaWR4ID0gdGhpcy5fdHJhbnNwYXJlbnRNZXNoZXNDYWNoZS5pbmRleE9mKG1lc2gpO1xyXG4gICAgICAgIGlmIChpZHggIT09IC0xKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX3RyYW5zcGFyZW50TWVzaGVzQ2FjaGUuc3BsaWNlKGlkeCwgMSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlkeCA9IHRoaXMuX29wYXF1ZU1lc2hlc0NhY2hlLmluZGV4T2YobWVzaCk7XHJcbiAgICAgICAgaWYgKGlkeCAhPT0gLTEpIHtcclxuICAgICAgICAgICAgdGhpcy5fb3BhcXVlTWVzaGVzQ2FjaGUuc3BsaWNlKGlkeCwgMSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX3BhcnNlU2NlbmUoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5fc2NlbmUubWVzaGVzLmZvckVhY2godGhpcy5fYWRkTWVzaC5iaW5kKHRoaXMpKTtcclxuICAgICAgICAvLyBMaXN0ZW4gZm9yIHdoZW4gYSBtZXNoIGlzIGFkZGVkIHRvIHRoZSBzY2VuZSBhbmQgYWRkIGl0IHRvIG91ciBjYWNoZSBsaXN0cy5cclxuICAgICAgICB0aGlzLl9zY2VuZS5vbk5ld01lc2hBZGRlZE9ic2VydmFibGUuYWRkKHRoaXMuX2FkZE1lc2guYmluZCh0aGlzKSk7XHJcbiAgICAgICAgLy8gTGlzdGVuIGZvciB3aGVuIGEgbWVzaCBpcyByZW1vdmVkIGZyb20gdG8gdGhlIHNjZW5lIGFuZCByZW1vdmUgaXQgZnJvbSBvdXIgY2FjaGUgbGlzdHMuXHJcbiAgICAgICAgdGhpcy5fc2NlbmUub25NZXNoUmVtb3ZlZE9ic2VydmFibGUuYWRkKHRoaXMuX3JlbW92ZU1lc2guYmluZCh0aGlzKSk7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gV2hlbiBvbmUgb2YgdGhlIG1lc2hlcyBpbiB0aGUgc2NlbmUgaGFzIGl0cyBtYXRlcmlhbCBjaGFuZ2VkLCBtYWtlIHN1cmUgdGhhdCBpdCdzIGluIHRoZSBjb3JyZWN0IGNhY2hlIGxpc3QuXHJcbiAgICBwcml2YXRlIF9vbk1lc2hNYXRlcmlhbENoYW5nZWQobWVzaDogQWJzdHJhY3RNZXNoKSB7XHJcbiAgICAgICAgY29uc3QgdHJhbnNwYXJlbnRJZHggPSB0aGlzLl90cmFuc3BhcmVudE1lc2hlc0NhY2hlLmluZGV4T2YobWVzaCk7XHJcbiAgICAgICAgY29uc3Qgb3BhcXVlSWR4ID0gdGhpcy5fb3BhcXVlTWVzaGVzQ2FjaGUuaW5kZXhPZihtZXNoKTtcclxuXHJcbiAgICAgICAgLy8gSWYgdGhlIG1hdGVyaWFsIGlzIHRyYW5zcGFyZW50LCBtYWtlIHN1cmUgdGhhdCBpdCdzIGFkZGVkIHRvIHRoZSB0cmFuc3BhcmVudCBsaXN0IGFuZCByZW1vdmVkIGZyb20gdGhlIG9wYXF1ZSBsaXN0XHJcbiAgICAgICAgY29uc3QgdXNlVHJhbnNtaXNzaW9uID0gdGhpcy5fc2hvdWxkUmVuZGVyQXNUcmFuc21pc3Npb24obWVzaC5tYXRlcmlhbCk7XHJcbiAgICAgICAgaWYgKHVzZVRyYW5zbWlzc2lvbikge1xyXG4gICAgICAgICAgICBpZiAobWVzaC5tYXRlcmlhbCBpbnN0YW5jZW9mIFBCUk1hdGVyaWFsKSB7XHJcbiAgICAgICAgICAgICAgICBtZXNoLm1hdGVyaWFsLnN1YlN1cmZhY2UucmVmcmFjdGlvblRleHR1cmUgPSB0aGlzLl9vcGFxdWVSZW5kZXJUYXJnZXQ7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKG9wYXF1ZUlkeCAhPT0gLTEpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX29wYXF1ZU1lc2hlc0NhY2hlLnNwbGljZShvcGFxdWVJZHgsIDEpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fdHJhbnNwYXJlbnRNZXNoZXNDYWNoZS5wdXNoKG1lc2gpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRyYW5zcGFyZW50SWR4ID09PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fdHJhbnNwYXJlbnRNZXNoZXNDYWNoZS5wdXNoKG1lc2gpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIC8vIElmIHRoZSBtYXRlcmlhbCBpcyBvcGFxdWUsIG1ha2Ugc3VyZSB0aGF0IGl0J3MgYWRkZWQgdG8gdGhlIG9wYXF1ZSBsaXN0IGFuZCByZW1vdmVkIGZyb20gdGhlIHRyYW5zcGFyZW50IGxpc3RcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBpZiAodHJhbnNwYXJlbnRJZHggIT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl90cmFuc3BhcmVudE1lc2hlc0NhY2hlLnNwbGljZSh0cmFuc3BhcmVudElkeCwgMSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9vcGFxdWVNZXNoZXNDYWNoZS5wdXNoKG1lc2gpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKG9wYXF1ZUlkeCA9PT0gLTEpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX29wYXF1ZU1lc2hlc0NhY2hlLnB1c2gobWVzaCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqIENoZWNrIGlmIHRoZSBvcGFxdWUgcmVuZGVyIHRhcmdldCBoYXMgbm90IGJlZW4gZGlzcG9zZWQgYW5kIGNhbiBzdGlsbCBiZSB1c2VkLlxyXG4gICAgICogQHJldHVybnNcclxuICAgICAqL1xyXG4gICAgcHVibGljIF9pc1JlbmRlclRhcmdldFZhbGlkKCkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9vcGFxdWVSZW5kZXJUYXJnZXQ/LmdldEludGVybmFsVGV4dHVyZSgpICE9PSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKiBTZXR1cCB0aGUgcmVuZGVyIHRhcmdldHMgYWNjb3JkaW5nIHRvIHRoZSBzcGVjaWZpZWQgb3B0aW9ucy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIF9zZXR1cFJlbmRlclRhcmdldHMoKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKHRoaXMuX29wYXF1ZVJlbmRlclRhcmdldCkge1xyXG4gICAgICAgICAgICB0aGlzLl9vcGFxdWVSZW5kZXJUYXJnZXQuZGlzcG9zZSgpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLl9vcGFxdWVSZW5kZXJUYXJnZXQgPSBuZXcgUmVuZGVyVGFyZ2V0VGV4dHVyZShcclxuICAgICAgICAgICAgXCJvcGFxdWVTY2VuZVRleHR1cmVcIixcclxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5yZW5kZXJTaXplLFxyXG4gICAgICAgICAgICB0aGlzLl9zY2VuZSxcclxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5nZW5lcmF0ZU1pcG1hcHMsXHJcbiAgICAgICAgICAgIHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgdGhpcy5fb3B0aW9ucy5yZW5kZXJUYXJnZXRUZXh0dXJlVHlwZVxyXG4gICAgICAgICk7XHJcbiAgICAgICAgdGhpcy5fb3BhcXVlUmVuZGVyVGFyZ2V0Lmlnbm9yZUNhbWVyYVZpZXdwb3J0ID0gdHJ1ZTtcclxuICAgICAgICB0aGlzLl9vcGFxdWVSZW5kZXJUYXJnZXQucmVuZGVyTGlzdCA9IHRoaXMuX29wYXF1ZU1lc2hlc0NhY2hlO1xyXG4gICAgICAgIHRoaXMuX29wYXF1ZVJlbmRlclRhcmdldC5jbGVhckNvbG9yID0gdGhpcy5fb3B0aW9ucy5jbGVhckNvbG9yPy5jbG9uZSgpID8/IHRoaXMuX3NjZW5lLmNsZWFyQ29sb3IuY2xvbmUoKTtcclxuICAgICAgICB0aGlzLl9vcGFxdWVSZW5kZXJUYXJnZXQuZ2FtbWFTcGFjZSA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMuX29wYXF1ZVJlbmRlclRhcmdldC5sb2RHZW5lcmF0aW9uU2NhbGUgPSB0aGlzLl9vcHRpb25zLmxvZEdlbmVyYXRpb25TY2FsZTtcclxuICAgICAgICB0aGlzLl9vcGFxdWVSZW5kZXJUYXJnZXQubG9kR2VuZXJhdGlvbk9mZnNldCA9IHRoaXMuX29wdGlvbnMubG9kR2VuZXJhdGlvbk9mZnNldDtcclxuICAgICAgICB0aGlzLl9vcGFxdWVSZW5kZXJUYXJnZXQuc2FtcGxlcyA9IHRoaXMuX29wdGlvbnMuc2FtcGxlcztcclxuXHJcbiAgICAgICAgbGV0IHNjZW5lSW1hZ2VQcm9jZXNzaW5nYXBwbHlCeVBvc3RQcm9jZXNzOiBib29sZWFuO1xyXG5cclxuICAgICAgICBsZXQgc2F2ZVNjZW5lRW52SW50ZW5zaXR5OiBudW1iZXI7XHJcbiAgICAgICAgdGhpcy5fb3BhcXVlUmVuZGVyVGFyZ2V0Lm9uQmVmb3JlQmluZE9ic2VydmFibGUuYWRkKChvcGFxdWVSZW5kZXJUYXJnZXQpID0+IHtcclxuICAgICAgICAgICAgc2F2ZVNjZW5lRW52SW50ZW5zaXR5ID0gdGhpcy5fc2NlbmUuZW52aXJvbm1lbnRJbnRlbnNpdHk7XHJcbiAgICAgICAgICAgIHRoaXMuX3NjZW5lLmVudmlyb25tZW50SW50ZW5zaXR5ID0gMS4wO1xyXG4gICAgICAgICAgICBzY2VuZUltYWdlUHJvY2Vzc2luZ2FwcGx5QnlQb3N0UHJvY2VzcyA9IHRoaXMuX3NjZW5lLmltYWdlUHJvY2Vzc2luZ0NvbmZpZ3VyYXRpb24uYXBwbHlCeVBvc3RQcm9jZXNzO1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuX29wdGlvbnMuY2xlYXJDb2xvcikge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fc2NlbmUuY2xlYXJDb2xvci50b0xpbmVhclNwYWNlVG9SZWYob3BhcXVlUmVuZGVyVGFyZ2V0LmNsZWFyQ29sb3IsIHRoaXMuX3NjZW5lLmdldEVuZ2luZSgpLnVzZUV4YWN0U3JnYkNvbnZlcnNpb25zKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIG9wYXF1ZVJlbmRlclRhcmdldC5jbGVhckNvbG9yLmNvcHlGcm9tKHRoaXMuX29wdGlvbnMuY2xlYXJDb2xvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gd2UgZG8gbm90IHVzZSB0aGUgYXBwbHlCeVBvc3RQcm9jZXNzIHNldHRlciB0byBhdm9pZCBmbGFnZ2luZyBhbGwgdGhlIG1hdGVyaWFscyBhcyBcImltYWdlIHByb2Nlc3NpbmcgZGlydHlcIiFcclxuICAgICAgICAgICAgdGhpcy5fc2NlbmUuaW1hZ2VQcm9jZXNzaW5nQ29uZmlndXJhdGlvbi5fYXBwbHlCeVBvc3RQcm9jZXNzID0gdHJ1ZTtcclxuICAgICAgICB9KTtcclxuICAgICAgICB0aGlzLl9vcGFxdWVSZW5kZXJUYXJnZXQub25BZnRlclVuYmluZE9ic2VydmFibGUuYWRkKCgpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5fc2NlbmUuZW52aXJvbm1lbnRJbnRlbnNpdHkgPSBzYXZlU2NlbmVFbnZJbnRlbnNpdHk7XHJcbiAgICAgICAgICAgIHRoaXMuX3NjZW5lLmltYWdlUHJvY2Vzc2luZ0NvbmZpZ3VyYXRpb24uX2FwcGx5QnlQb3N0UHJvY2VzcyA9IHNjZW5lSW1hZ2VQcm9jZXNzaW5nYXBwbHlCeVBvc3RQcm9jZXNzO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICB0aGlzLl90cmFuc3BhcmVudE1lc2hlc0NhY2hlLmZvckVhY2goKG1lc2g6IEFic3RyYWN0TWVzaCkgPT4ge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5fc2hvdWxkUmVuZGVyQXNUcmFuc21pc3Npb24obWVzaC5tYXRlcmlhbCkpIHtcclxuICAgICAgICAgICAgICAgIChtZXNoLm1hdGVyaWFsIGFzIFBCUk1hdGVyaWFsKS5yZWZyYWN0aW9uVGV4dHVyZSA9IHRoaXMuX29wYXF1ZVJlbmRlclRhcmdldDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGlzcG9zZSBhbGwgdGhlIGVsZW1lbnRzIGNyZWF0ZWQgYnkgdGhlIEhlbHBlci5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5fc2NlbmUuX3RyYW5zbWlzc2lvbkhlbHBlciA9IHVuZGVmaW5lZDtcclxuICAgICAgICBpZiAodGhpcy5fb3BhcXVlUmVuZGVyVGFyZ2V0KSB7XHJcbiAgICAgICAgICAgIHRoaXMuX29wYXF1ZVJlbmRlclRhcmdldC5kaXNwb3NlKCk7XHJcbiAgICAgICAgICAgIHRoaXMuX29wYXF1ZVJlbmRlclRhcmdldCA9IG51bGw7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuX3RyYW5zcGFyZW50TWVzaGVzQ2FjaGUgPSBbXTtcclxuICAgICAgICB0aGlzLl9vcGFxdWVNZXNoZXNDYWNoZSA9IFtdO1xyXG4gICAgfVxyXG59XHJcblxyXG5jb25zdCBOQU1FID0gXCJLSFJfbWF0ZXJpYWxzX3RyYW5zbWlzc2lvblwiO1xyXG5cclxuLyoqXHJcbiAqIFtTcGVjaWZpY2F0aW9uXShodHRwczovL2dpdGh1Yi5jb20vS2hyb25vc0dyb3VwL2dsVEYvYmxvYi9tYWluL2V4dGVuc2lvbnMvMi4wL0tocm9ub3MvS0hSX21hdGVyaWFsc190cmFuc21pc3Npb24vUkVBRE1FLm1kKVxyXG4gKi9cclxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxyXG5leHBvcnQgY2xhc3MgS0hSX21hdGVyaWFsc190cmFuc21pc3Npb24gaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGEgbnVtYmVyIHRoYXQgZGV0ZXJtaW5lcyB0aGUgb3JkZXIgdGhlIGV4dGVuc2lvbnMgYXJlIGFwcGxpZWQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBvcmRlciA9IDE3NTtcclxuXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGVyOiBHTFRGTG9hZGVyKSB7XHJcbiAgICAgICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyO1xyXG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IHRoaXMuX2xvYWRlci5pc0V4dGVuc2lvblVzZWQoTkFNRSk7XHJcbiAgICAgICAgaWYgKHRoaXMuZW5hYmxlZCkge1xyXG4gICAgICAgICAgICBsb2FkZXIucGFyZW50LnRyYW5zcGFyZW5jeUFzQ292ZXJhZ2UgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpIHtcclxuICAgICAgICAodGhpcy5fbG9hZGVyIGFzIGFueSkgPSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkTWF0ZXJpYWxQcm9wZXJ0aWVzQXN5bmMoY29udGV4dDogc3RyaW5nLCBtYXRlcmlhbDogSU1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWw6IE1hdGVyaWFsKTogTnVsbGFibGU8UHJvbWlzZTx2b2lkPj4ge1xyXG4gICAgICAgIHJldHVybiBHTFRGTG9hZGVyLkxvYWRFeHRlbnNpb25Bc3luYzxJS0hSTWF0ZXJpYWxzVHJhbnNtaXNzaW9uPihjb250ZXh0LCBtYXRlcmlhbCwgdGhpcy5uYW1lLCAoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkZXIubG9hZE1hdGVyaWFsQmFzZVByb3BlcnRpZXNBc3luYyhjb250ZXh0LCBtYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsKSk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fbG9hZGVyLmxvYWRNYXRlcmlhbFByb3BlcnRpZXNBc3luYyhjb250ZXh0LCBtYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsKSk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fbG9hZFRyYW5zcGFyZW50UHJvcGVydGllc0FzeW5jKGV4dGVuc2lvbkNvbnRleHQsIG1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWwsIGV4dGVuc2lvbikpO1xyXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge30pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2xvYWRUcmFuc3BhcmVudFByb3BlcnRpZXNBc3luYyhjb250ZXh0OiBzdHJpbmcsIG1hdGVyaWFsOiBJTWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwsIGV4dGVuc2lvbjogSUtIUk1hdGVyaWFsc1RyYW5zbWlzc2lvbik6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGlmICghKGJhYnlsb25NYXRlcmlhbCBpbnN0YW5jZW9mIFBCUk1hdGVyaWFsKSkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29udGV4dH06IE1hdGVyaWFsIHR5cGUgbm90IHN1cHBvcnRlZGApO1xyXG4gICAgICAgIH1cclxuICAgICAgICBjb25zdCBwYnJNYXRlcmlhbCA9IGJhYnlsb25NYXRlcmlhbCBhcyBQQlJNYXRlcmlhbDtcclxuXHJcbiAgICAgICAgLy8gRW5hYmxlcyBcInJlZnJhY3Rpb25cIiB0ZXh0dXJlIHdoaWNoIHJlcHJlc2VudHMgdHJhbnNtaXR0ZWQgbGlnaHQuXHJcbiAgICAgICAgcGJyTWF0ZXJpYWwuc3ViU3VyZmFjZS5pc1JlZnJhY3Rpb25FbmFibGVkID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgLy8gU2luY2UgdGhpcyBleHRlbnNpb24gbW9kZWxzIHRoaW4tc3VyZmFjZSB0cmFuc21pc3Npb24gb25seSwgd2UgbXVzdCBtYWtlIElPUiA9IDEuMFxyXG4gICAgICAgIHBick1hdGVyaWFsLnN1YlN1cmZhY2Uudm9sdW1lSW5kZXhPZlJlZnJhY3Rpb24gPSAxLjA7XHJcblxyXG4gICAgICAgIC8vIEFsYmVkbyBjb2xvdXIgd2lsbCB0aW50IHRyYW5zbWlzc2lvbi5cclxuICAgICAgICBwYnJNYXRlcmlhbC5zdWJTdXJmYWNlLnVzZUFsYmVkb1RvVGludFJlZnJhY3Rpb24gPSB0cnVlO1xyXG5cclxuICAgICAgICBpZiAoZXh0ZW5zaW9uLnRyYW5zbWlzc2lvbkZhY3RvciAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIHBick1hdGVyaWFsLnN1YlN1cmZhY2UucmVmcmFjdGlvbkludGVuc2l0eSA9IGV4dGVuc2lvbi50cmFuc21pc3Npb25GYWN0b3I7XHJcbiAgICAgICAgICAgIGNvbnN0IHNjZW5lID0gcGJyTWF0ZXJpYWwuZ2V0U2NlbmUoKSBhcyB1bmtub3duIGFzIElUcmFuc21pc3Npb25IZWxwZXJIb2xkZXI7XHJcbiAgICAgICAgICAgIGlmIChwYnJNYXRlcmlhbC5zdWJTdXJmYWNlLnJlZnJhY3Rpb25JbnRlbnNpdHkgJiYgIXNjZW5lLl90cmFuc21pc3Npb25IZWxwZXIpIHtcclxuICAgICAgICAgICAgICAgIG5ldyBUcmFuc21pc3Npb25IZWxwZXIoe30sIHBick1hdGVyaWFsLmdldFNjZW5lKCkpO1xyXG4gICAgICAgICAgICB9IGVsc2UgaWYgKHBick1hdGVyaWFsLnN1YlN1cmZhY2UucmVmcmFjdGlvbkludGVuc2l0eSAmJiAhc2NlbmUuX3RyYW5zbWlzc2lvbkhlbHBlcj8uX2lzUmVuZGVyVGFyZ2V0VmFsaWQoKSkge1xyXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIHJlbmRlciB0YXJnZXQgaXMgbm90IHZhbGlkLCByZWNyZWF0ZSBpdC5cclxuICAgICAgICAgICAgICAgIHNjZW5lLl90cmFuc21pc3Npb25IZWxwZXI/Ll9zZXR1cFJlbmRlclRhcmdldHMoKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHBick1hdGVyaWFsLnN1YlN1cmZhY2UucmVmcmFjdGlvbkludGVuc2l0eSA9IDAuMDtcclxuICAgICAgICAgICAgcGJyTWF0ZXJpYWwuc3ViU3VyZmFjZS5pc1JlZnJhY3Rpb25FbmFibGVkID0gZmFsc2U7XHJcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHBick1hdGVyaWFsLnN1YlN1cmZhY2UubWluaW11bVRoaWNrbmVzcyA9IDAuMDtcclxuICAgICAgICBwYnJNYXRlcmlhbC5zdWJTdXJmYWNlLm1heGltdW1UaGlja25lc3MgPSAwLjA7XHJcbiAgICAgICAgaWYgKGV4dGVuc2lvbi50cmFuc21pc3Npb25UZXh0dXJlKSB7XHJcbiAgICAgICAgICAgIChleHRlbnNpb24udHJhbnNtaXNzaW9uVGV4dHVyZSBhcyBJVGV4dHVyZUluZm8pLm5vbkNvbG9yRGF0YSA9IHRydWU7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9sb2FkZXIubG9hZFRleHR1cmVJbmZvQXN5bmMoYCR7Y29udGV4dH0vdHJhbnNtaXNzaW9uVGV4dHVyZWAsIGV4dGVuc2lvbi50cmFuc21pc3Npb25UZXh0dXJlLCB1bmRlZmluZWQpLnRoZW4oKHRleHR1cmU6IEJhc2VUZXh0dXJlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBwYnJNYXRlcmlhbC5zdWJTdXJmYWNlLnJlZnJhY3Rpb25JbnRlbnNpdHlUZXh0dXJlID0gdGV4dHVyZTtcclxuICAgICAgICAgICAgICAgIHBick1hdGVyaWFsLnN1YlN1cmZhY2UudXNlR2x0ZlN0eWxlVGV4dHVyZXMgPSB0cnVlO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKE5BTUUsIChsb2FkZXIpID0+IG5ldyBLSFJfbWF0ZXJpYWxzX3RyYW5zbWlzc2lvbihsb2FkZXIpKTtcclxuIiwiaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB7IENvbG9yMyB9IGZyb20gXCJjb3JlL01hdGhzL21hdGguY29sb3JcIjtcclxuaW1wb3J0IHsgUEJSTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvUEJSL3Bick1hdGVyaWFsXCI7XHJcbmltcG9ydCB0eXBlIHsgTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvbWF0ZXJpYWxcIjtcclxuXHJcbmltcG9ydCB0eXBlIHsgSU1hdGVyaWFsIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcbmltcG9ydCB0eXBlIHsgSUdMVEZMb2FkZXJFeHRlbnNpb24gfSBmcm9tIFwiLi4vZ2xURkxvYWRlckV4dGVuc2lvblwiO1xyXG5pbXBvcnQgeyBHTFRGTG9hZGVyIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJcIjtcclxuXHJcbmNvbnN0IE5BTUUgPSBcIktIUl9tYXRlcmlhbHNfdW5saXRcIjtcclxuXHJcbi8qKlxyXG4gKiBbU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly9naXRodWIuY29tL0tocm9ub3NHcm91cC9nbFRGL2Jsb2IvbWFpbi9leHRlbnNpb25zLzIuMC9LaHJvbm9zL0tIUl9tYXRlcmlhbHNfdW5saXQvUkVBRE1FLm1kKVxyXG4gKi9cclxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxyXG5leHBvcnQgY2xhc3MgS0hSX21hdGVyaWFsc191bmxpdCBpbXBsZW1lbnRzIElHTFRGTG9hZGVyRXh0ZW5zaW9uIHtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIG5hbWUgb2YgdGhpcyBleHRlbnNpb24uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyByZWFkb25seSBuYW1lID0gTkFNRTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgd2hldGhlciB0aGlzIGV4dGVuc2lvbiBpcyBlbmFibGVkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZW5hYmxlZDogYm9vbGVhbjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgYSBudW1iZXIgdGhhdCBkZXRlcm1pbmVzIHRoZSBvcmRlciB0aGUgZXh0ZW5zaW9ucyBhcmUgYXBwbGllZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIG9yZGVyID0gMjEwO1xyXG5cclxuICAgIHByaXZhdGUgX2xvYWRlcjogR0xURkxvYWRlcjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3Rvcihsb2FkZXI6IEdMVEZMb2FkZXIpIHtcclxuICAgICAgICB0aGlzLl9sb2FkZXIgPSBsb2FkZXI7XHJcbiAgICAgICAgdGhpcy5lbmFibGVkID0gdGhpcy5fbG9hZGVyLmlzRXh0ZW5zaW9uVXNlZChOQU1FKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpIHtcclxuICAgICAgICAodGhpcy5fbG9hZGVyIGFzIGFueSkgPSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkTWF0ZXJpYWxQcm9wZXJ0aWVzQXN5bmMoY29udGV4dDogc3RyaW5nLCBtYXRlcmlhbDogSU1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWw6IE1hdGVyaWFsKTogTnVsbGFibGU8UHJvbWlzZTx2b2lkPj4ge1xyXG4gICAgICAgIHJldHVybiBHTFRGTG9hZGVyLkxvYWRFeHRlbnNpb25Bc3luYyhjb250ZXh0LCBtYXRlcmlhbCwgdGhpcy5uYW1lLCAoKSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9sb2FkVW5saXRQcm9wZXJ0aWVzQXN5bmMoY29udGV4dCwgbWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZFVubGl0UHJvcGVydGllc0FzeW5jKGNvbnRleHQ6IHN0cmluZywgbWF0ZXJpYWw6IElNYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsOiBNYXRlcmlhbCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGlmICghKGJhYnlsb25NYXRlcmlhbCBpbnN0YW5jZW9mIFBCUk1hdGVyaWFsKSkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29udGV4dH06IE1hdGVyaWFsIHR5cGUgbm90IHN1cHBvcnRlZGApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBuZXcgQXJyYXk8UHJvbWlzZTxhbnk+PigpO1xyXG4gICAgICAgIGJhYnlsb25NYXRlcmlhbC51bmxpdCA9IHRydWU7XHJcblxyXG4gICAgICAgIGNvbnN0IHByb3BlcnRpZXMgPSBtYXRlcmlhbC5wYnJNZXRhbGxpY1JvdWdobmVzcztcclxuICAgICAgICBpZiAocHJvcGVydGllcykge1xyXG4gICAgICAgICAgICBpZiAocHJvcGVydGllcy5iYXNlQ29sb3JGYWN0b3IpIHtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5hbGJlZG9Db2xvciA9IENvbG9yMy5Gcm9tQXJyYXkocHJvcGVydGllcy5iYXNlQ29sb3JGYWN0b3IpO1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLmFscGhhID0gcHJvcGVydGllcy5iYXNlQ29sb3JGYWN0b3JbM107XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuYWxiZWRvQ29sb3IgPSBDb2xvcjMuV2hpdGUoKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuYmFzZUNvbG9yVGV4dHVyZSkge1xyXG4gICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaChcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIubG9hZFRleHR1cmVJbmZvQXN5bmMoYCR7Y29udGV4dH0vYmFzZUNvbG9yVGV4dHVyZWAsIHByb3BlcnRpZXMuYmFzZUNvbG9yVGV4dHVyZSwgKHRleHR1cmUpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dHVyZS5uYW1lID0gYCR7YmFieWxvbk1hdGVyaWFsLm5hbWV9IChCYXNlIENvbG9yKWA7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5hbGJlZG9UZXh0dXJlID0gdGV4dHVyZTtcclxuICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKG1hdGVyaWFsLmRvdWJsZVNpZGVkKSB7XHJcbiAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5iYWNrRmFjZUN1bGxpbmcgPSBmYWxzZTtcclxuICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLnR3b1NpZGVkTGlnaHRpbmcgPSB0cnVlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5fbG9hZGVyLmxvYWRNYXRlcmlhbEFscGhhUHJvcGVydGllcyhjb250ZXh0LCBtYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IHt9KTtcclxuICAgIH1cclxufVxyXG5cclxuR0xURkxvYWRlci5SZWdpc3RlckV4dGVuc2lvbihOQU1FLCAobG9hZGVyKSA9PiBuZXcgS0hSX21hdGVyaWFsc191bmxpdChsb2FkZXIpKTtcclxuIiwiaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB0eXBlIHsgSUdMVEZMb2FkZXJFeHRlbnNpb24gfSBmcm9tIFwiLi4vZ2xURkxvYWRlckV4dGVuc2lvblwiO1xyXG5pbXBvcnQgeyBHTFRGTG9hZGVyLCBBcnJheUl0ZW0gfSBmcm9tIFwiLi4vZ2xURkxvYWRlclwiO1xyXG5cclxuaW1wb3J0IHR5cGUgeyBNYXRlcmlhbCB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9tYXRlcmlhbFwiO1xyXG5pbXBvcnQgeyBNZXNoIH0gZnJvbSBcImNvcmUvTWVzaGVzL21lc2hcIjtcclxuaW1wb3J0IHR5cGUgeyBOb2RlIH0gZnJvbSBcImNvcmUvbm9kZVwiO1xyXG5pbXBvcnQgdHlwZSB7IEFic3RyYWN0TWVzaCB9IGZyb20gXCJjb3JlL01lc2hlcy9hYnN0cmFjdE1lc2hcIjtcclxuaW1wb3J0IHR5cGUgeyBJTm9kZSwgSU1lc2hQcmltaXRpdmUsIElNZXNoIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcbmltcG9ydCB0eXBlIHsgSUtIUk1hdGVyaWFsVmFyaWFudHNfTWFwcGluZywgSUtIUk1hdGVyaWFsVmFyaWFudHNfVmFyaWFudCwgSUtIUk1hdGVyaWFsVmFyaWFudHNfVmFyaWFudHMgfSBmcm9tIFwiYmFieWxvbmpzLWdsdGYyaW50ZXJmYWNlXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJLSFJfbWF0ZXJpYWxzX3ZhcmlhbnRzXCI7XHJcblxyXG5pbnRlcmZhY2UgSVZhcmlhbnRzTWFwIHtcclxuICAgIFtrZXk6IHN0cmluZ106IEFycmF5PHsgbWVzaDogQWJzdHJhY3RNZXNoOyBtYXRlcmlhbDogTnVsbGFibGU8TWF0ZXJpYWw+IH0+O1xyXG59XHJcblxyXG5pbnRlcmZhY2UgSUV4dGVuc2lvbk1ldGFkYXRhIHtcclxuICAgIGxhc3RTZWxlY3RlZDogTnVsbGFibGU8c3RyaW5nIHwgQXJyYXk8c3RyaW5nPj47XHJcbiAgICBvcmlnaW5hbDogQXJyYXk8eyBtZXNoOiBBYnN0cmFjdE1lc2g7IG1hdGVyaWFsOiBOdWxsYWJsZTxNYXRlcmlhbD4gfT47XHJcbiAgICB2YXJpYW50czogSVZhcmlhbnRzTWFwO1xyXG59XHJcblxyXG4vKipcclxuICogW1NwZWNpZmljYXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9LaHJvbm9zR3JvdXAvZ2xURi9ibG9iL21haW4vZXh0ZW5zaW9ucy8yLjAvS2hyb25vcy9LSFJfbWF0ZXJpYWxzX3ZhcmlhbnRzL1JFQURNRS5tZClcclxuICovXHJcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cclxuZXhwb3J0IGNsYXNzIEtIUl9tYXRlcmlhbHNfdmFyaWFudHMgaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZGVyOiBHTFRGTG9hZGVyO1xyXG5cclxuICAgIHByaXZhdGUgX3ZhcmlhbnRzPzogQXJyYXk8SUtIUk1hdGVyaWFsVmFyaWFudHNfVmFyaWFudD47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGVyOiBHTFRGTG9hZGVyKSB7XHJcbiAgICAgICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyO1xyXG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IHRoaXMuX2xvYWRlci5pc0V4dGVuc2lvblVzZWQoTkFNRSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKSB7XHJcbiAgICAgICAgKHRoaXMuX2xvYWRlciBhcyBhbnkpID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEdldHMgdGhlIGxpc3Qgb2YgYXZhaWxhYmxlIHZhcmlhbnQgbmFtZXMgZm9yIHRoaXMgYXNzZXQuXHJcbiAgICAgKiBAcGFyYW0gcm9vdE1lc2ggVGhlIGdsVEYgcm9vdCBtZXNoXHJcbiAgICAgKiBAcmV0dXJucyB0aGUgbGlzdCBvZiBhbGwgdGhlIHZhcmlhbnQgbmFtZXMgZm9yIHRoaXMgbW9kZWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBHZXRBdmFpbGFibGVWYXJpYW50cyhyb290TWVzaDogTWVzaCk6IHN0cmluZ1tdIHtcclxuICAgICAgICBjb25zdCBleHRlbnNpb25NZXRhZGF0YSA9IHRoaXMuX0dldEV4dGVuc2lvbk1ldGFkYXRhKHJvb3RNZXNoKTtcclxuICAgICAgICBpZiAoIWV4dGVuc2lvbk1ldGFkYXRhKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBbXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBPYmplY3Qua2V5cyhleHRlbnNpb25NZXRhZGF0YS52YXJpYW50cyk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIHRoZSBsaXN0IG9mIGF2YWlsYWJsZSB2YXJpYW50IG5hbWVzIGZvciB0aGlzIGFzc2V0LlxyXG4gICAgICogQHBhcmFtIHJvb3RNZXNoIFRoZSBnbFRGIHJvb3QgbWVzaFxyXG4gICAgICogQHJldHVybnMgdGhlIGxpc3Qgb2YgYWxsIHRoZSB2YXJpYW50IG5hbWVzIGZvciB0aGlzIG1vZGVsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXRBdmFpbGFibGVWYXJpYW50cyhyb290TWVzaDogTWVzaCk6IHN0cmluZ1tdIHtcclxuICAgICAgICByZXR1cm4gS0hSX21hdGVyaWFsc192YXJpYW50cy5HZXRBdmFpbGFibGVWYXJpYW50cyhyb290TWVzaCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTZWxlY3QgYSB2YXJpYW50IGdpdmVuIGEgdmFyaWFudCBuYW1lIG9yIGEgbGlzdCBvZiB2YXJpYW50IG5hbWVzLlxyXG4gICAgICogQHBhcmFtIHJvb3RNZXNoIFRoZSBnbFRGIHJvb3QgbWVzaFxyXG4gICAgICogQHBhcmFtIHZhcmlhbnROYW1lIFRoZSB2YXJpYW50IG5hbWUocykgdG8gc2VsZWN0LlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIFNlbGVjdFZhcmlhbnQocm9vdE1lc2g6IE1lc2gsIHZhcmlhbnROYW1lOiBzdHJpbmcgfCBzdHJpbmdbXSk6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IGV4dGVuc2lvbk1ldGFkYXRhID0gdGhpcy5fR2V0RXh0ZW5zaW9uTWV0YWRhdGEocm9vdE1lc2gpO1xyXG4gICAgICAgIGlmICghZXh0ZW5zaW9uTWV0YWRhdGEpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBDYW5ub3Qgc2VsZWN0IHZhcmlhbnQgb24gYSBnbFRGIG1lc2ggdGhhdCBkb2VzIG5vdCBoYXZlIHRoZSAke05BTUV9IGV4dGVuc2lvbmApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3Qgc2VsZWN0ID0gKHZhcmlhbnROYW1lOiBzdHJpbmcpOiB2b2lkID0+IHtcclxuICAgICAgICAgICAgY29uc3QgZW50cmllcyA9IGV4dGVuc2lvbk1ldGFkYXRhLnZhcmlhbnRzW3ZhcmlhbnROYW1lXTtcclxuICAgICAgICAgICAgaWYgKGVudHJpZXMpIHtcclxuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZW50cnkgb2YgZW50cmllcykge1xyXG4gICAgICAgICAgICAgICAgICAgIGVudHJ5Lm1lc2gubWF0ZXJpYWwgPSBlbnRyeS5tYXRlcmlhbDtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGlmICh2YXJpYW50TmFtZSBpbnN0YW5jZW9mIEFycmF5KSB7XHJcbiAgICAgICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiB2YXJpYW50TmFtZSkge1xyXG4gICAgICAgICAgICAgICAgc2VsZWN0KG5hbWUpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgc2VsZWN0KHZhcmlhbnROYW1lKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGV4dGVuc2lvbk1ldGFkYXRhLmxhc3RTZWxlY3RlZCA9IHZhcmlhbnROYW1lO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogU2VsZWN0IGEgdmFyaWFudCBnaXZlbiBhIHZhcmlhbnQgbmFtZSBvciBhIGxpc3Qgb2YgdmFyaWFudCBuYW1lcy5cclxuICAgICAqIEBwYXJhbSByb290TWVzaCBUaGUgZ2xURiByb290IG1lc2hcclxuICAgICAqIEBwYXJhbSB2YXJpYW50TmFtZSBUaGUgdmFyaWFudCBuYW1lKHMpIHRvIHNlbGVjdC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHNlbGVjdFZhcmlhbnQocm9vdE1lc2g6IE1lc2gsIHZhcmlhbnROYW1lOiBzdHJpbmcgfCBzdHJpbmdbXSk6IHZvaWQge1xyXG4gICAgICAgIHJldHVybiBLSFJfbWF0ZXJpYWxzX3ZhcmlhbnRzLlNlbGVjdFZhcmlhbnQocm9vdE1lc2gsIHZhcmlhbnROYW1lKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJlc2V0IGJhY2sgdG8gdGhlIG9yaWdpbmFsIGJlZm9yZSBzZWxlY3RpbmcgYSB2YXJpYW50LlxyXG4gICAgICogQHBhcmFtIHJvb3RNZXNoIFRoZSBnbFRGIHJvb3QgbWVzaFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIFJlc2V0KHJvb3RNZXNoOiBNZXNoKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3QgZXh0ZW5zaW9uTWV0YWRhdGEgPSB0aGlzLl9HZXRFeHRlbnNpb25NZXRhZGF0YShyb290TWVzaCk7XHJcbiAgICAgICAgaWYgKCFleHRlbnNpb25NZXRhZGF0YSkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCByZXNldCBvbiBhIGdsVEYgbWVzaCB0aGF0IGRvZXMgbm90IGhhdmUgdGhlICR7TkFNRX0gZXh0ZW5zaW9uYCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBmb3IgKGNvbnN0IGVudHJ5IG9mIGV4dGVuc2lvbk1ldGFkYXRhLm9yaWdpbmFsKSB7XHJcbiAgICAgICAgICAgIGVudHJ5Lm1lc2gubWF0ZXJpYWwgPSBlbnRyeS5tYXRlcmlhbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGV4dGVuc2lvbk1ldGFkYXRhLmxhc3RTZWxlY3RlZCA9IG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXNldCBiYWNrIHRvIHRoZSBvcmlnaW5hbCBiZWZvcmUgc2VsZWN0aW5nIGEgdmFyaWFudC5cclxuICAgICAqIEBwYXJhbSByb290TWVzaCBUaGUgZ2xURiByb290IG1lc2hcclxuICAgICAqL1xyXG4gICAgcHVibGljIHJlc2V0KHJvb3RNZXNoOiBNZXNoKTogdm9pZCB7XHJcbiAgICAgICAgcmV0dXJuIEtIUl9tYXRlcmlhbHNfdmFyaWFudHMuUmVzZXQocm9vdE1lc2gpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgbGFzdCBzZWxlY3RlZCB2YXJpYW50IG5hbWUocykgb3IgbnVsbCBpZiBvcmlnaW5hbC5cclxuICAgICAqIEBwYXJhbSByb290TWVzaCBUaGUgZ2xURiByb290IG1lc2hcclxuICAgICAqIEByZXR1cm5zIFRoZSBzZWxlY3RlZCB2YXJpYW50IG5hbWUocykuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgR2V0TGFzdFNlbGVjdGVkVmFyaWFudChyb290TWVzaDogTWVzaCk6IE51bGxhYmxlPHN0cmluZyB8IHN0cmluZ1tdPiB7XHJcbiAgICAgICAgY29uc3QgZXh0ZW5zaW9uTWV0YWRhdGEgPSB0aGlzLl9HZXRFeHRlbnNpb25NZXRhZGF0YShyb290TWVzaCk7XHJcbiAgICAgICAgaWYgKCFleHRlbnNpb25NZXRhZGF0YSkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYENhbm5vdCBnZXQgdGhlIGxhc3Qgc2VsZWN0ZWQgdmFyaWFudCBvbiBhIGdsVEYgbWVzaCB0aGF0IGRvZXMgbm90IGhhdmUgdGhlICR7TkFNRX0gZXh0ZW5zaW9uYCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gZXh0ZW5zaW9uTWV0YWRhdGEubGFzdFNlbGVjdGVkO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0cyB0aGUgbGFzdCBzZWxlY3RlZCB2YXJpYW50IG5hbWUocykgb3IgbnVsbCBpZiBvcmlnaW5hbC5cclxuICAgICAqIEBwYXJhbSByb290TWVzaCBUaGUgZ2xURiByb290IG1lc2hcclxuICAgICAqIEByZXR1cm5zIFRoZSBzZWxlY3RlZCB2YXJpYW50IG5hbWUocykuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXRMYXN0U2VsZWN0ZWRWYXJpYW50KHJvb3RNZXNoOiBNZXNoKTogTnVsbGFibGU8c3RyaW5nIHwgc3RyaW5nW10+IHtcclxuICAgICAgICByZXR1cm4gS0hSX21hdGVyaWFsc192YXJpYW50cy5HZXRMYXN0U2VsZWN0ZWRWYXJpYW50KHJvb3RNZXNoKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHN0YXRpYyBfR2V0RXh0ZW5zaW9uTWV0YWRhdGEocm9vdE1lc2g6IE51bGxhYmxlPE1lc2g+KTogTnVsbGFibGU8SUV4dGVuc2lvbk1ldGFkYXRhPiB7XHJcbiAgICAgICAgcmV0dXJuIHJvb3RNZXNoPy5faW50ZXJuYWxNZXRhZGF0YT8uZ2x0Zj8uW05BTUVdIHx8IG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIG9uTG9hZGluZygpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBleHRlbnNpb25zID0gdGhpcy5fbG9hZGVyLmdsdGYuZXh0ZW5zaW9ucztcclxuICAgICAgICBpZiAoZXh0ZW5zaW9ucyAmJiBleHRlbnNpb25zW3RoaXMubmFtZV0pIHtcclxuICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uID0gZXh0ZW5zaW9uc1t0aGlzLm5hbWVdIGFzIElLSFJNYXRlcmlhbFZhcmlhbnRzX1ZhcmlhbnRzO1xyXG4gICAgICAgICAgICB0aGlzLl92YXJpYW50cyA9IGV4dGVuc2lvbi52YXJpYW50cztcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIF9sb2FkTWVzaFByaW1pdGl2ZUFzeW5jKFxyXG4gICAgICAgIGNvbnRleHQ6IHN0cmluZyxcclxuICAgICAgICBuYW1lOiBzdHJpbmcsXHJcbiAgICAgICAgbm9kZTogSU5vZGUsXHJcbiAgICAgICAgbWVzaDogSU1lc2gsXHJcbiAgICAgICAgcHJpbWl0aXZlOiBJTWVzaFByaW1pdGl2ZSxcclxuICAgICAgICBhc3NpZ246IChiYWJ5bG9uTWVzaDogQWJzdHJhY3RNZXNoKSA9PiB2b2lkXHJcbiAgICApOiBOdWxsYWJsZTxQcm9taXNlPEFic3RyYWN0TWVzaD4+IHtcclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SUtIUk1hdGVyaWFsVmFyaWFudHNfTWFwcGluZywgQWJzdHJhY3RNZXNoPihjb250ZXh0LCBwcmltaXRpdmUsIHRoaXMubmFtZSwgKGV4dGVuc2lvbkNvbnRleHQsIGV4dGVuc2lvbikgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBwcm9taXNlcyA9IG5ldyBBcnJheTxQcm9taXNlPGFueT4+KCk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIuX2xvYWRNZXNoUHJpbWl0aXZlQXN5bmMoY29udGV4dCwgbmFtZSwgbm9kZSwgbWVzaCwgcHJpbWl0aXZlLCAoYmFieWxvbk1lc2gpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBhc3NpZ24oYmFieWxvbk1lc2gpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBpZiAoYmFieWxvbk1lc2ggaW5zdGFuY2VvZiBNZXNoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJhYnlsb25EcmF3TW9kZSA9IEdMVEZMb2FkZXIuX0dldERyYXdNb2RlKGNvbnRleHQsIHByaW1pdGl2ZS5tb2RlKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJvb3QgPSB0aGlzLl9sb2FkZXIucm9vdEJhYnlsb25NZXNoO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtZXRhZGF0YSA9IHJvb3QgPyAocm9vdC5faW50ZXJuYWxNZXRhZGF0YSA9IHJvb3QuX2ludGVybmFsTWV0YWRhdGEgfHwge30pIDoge307XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGdsdGYgPSAobWV0YWRhdGEuZ2x0ZiA9IG1ldGFkYXRhLmdsdGYgfHwge30pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBleHRlbnNpb25NZXRhZGF0YTogSUV4dGVuc2lvbk1ldGFkYXRhID0gKGdsdGZbTkFNRV0gPSBnbHRmW05BTUVdIHx8IHsgbGFzdFNlbGVjdGVkOiBudWxsLCBvcmlnaW5hbDogW10sIHZhcmlhbnRzOiB7fSB9KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFN0b3JlIHRoZSBvcmlnaW5hbCBtYXRlcmlhbC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgZXh0ZW5zaW9uTWV0YWRhdGEub3JpZ2luYWwucHVzaCh7IG1lc2g6IGJhYnlsb25NZXNoLCBtYXRlcmlhbDogYmFieWxvbk1lc2gubWF0ZXJpYWwgfSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBGb3IgZWFjaCBtYXBwaW5nLCBsb29rIGF0IHRoZSB2YXJpYW50cyBhbmQgbWFrZSBhIG5ldyBlbnRyeSBmb3IgdGhlbS5cclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgbWFwcGluZ0luZGV4ID0gMDsgbWFwcGluZ0luZGV4IDwgZXh0ZW5zaW9uLm1hcHBpbmdzLmxlbmd0aDsgKyttYXBwaW5nSW5kZXgpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hcHBpbmcgPSBleHRlbnNpb24ubWFwcGluZ3NbbWFwcGluZ0luZGV4XTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hdGVyaWFsID0gQXJyYXlJdGVtLkdldChgJHtleHRlbnNpb25Db250ZXh0fS9tYXBwaW5ncy8ke21hcHBpbmdJbmRleH0vbWF0ZXJpYWxgLCB0aGlzLl9sb2FkZXIuZ2x0Zi5tYXRlcmlhbHMsIG1hcHBpbmcubWF0ZXJpYWwpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaChcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIuX2xvYWRNYXRlcmlhbEFzeW5jKGAjL21hdGVyaWFscy8ke21hcHBpbmcubWF0ZXJpYWx9YCwgbWF0ZXJpYWwsIGJhYnlsb25NZXNoLCBiYWJ5bG9uRHJhd01vZGUsIChiYWJ5bG9uTWF0ZXJpYWwpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgbWFwcGluZ1ZhcmlhbnRJbmRleCA9IDA7IG1hcHBpbmdWYXJpYW50SW5kZXggPCBtYXBwaW5nLnZhcmlhbnRzLmxlbmd0aDsgKyttYXBwaW5nVmFyaWFudEluZGV4KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB2YXJpYW50SW5kZXggPSBtYXBwaW5nLnZhcmlhbnRzW21hcHBpbmdWYXJpYW50SW5kZXhdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFyaWFudCA9IEFycmF5SXRlbS5HZXQoYC9leHRlbnNpb25zLyR7TkFNRX0vdmFyaWFudHMvJHt2YXJpYW50SW5kZXh9YCwgdGhpcy5fdmFyaWFudHMsIHZhcmlhbnRJbmRleCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleHRlbnNpb25NZXRhZGF0YS52YXJpYW50c1t2YXJpYW50Lm5hbWVdID0gZXh0ZW5zaW9uTWV0YWRhdGEudmFyaWFudHNbdmFyaWFudC5uYW1lXSB8fCBbXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4dGVuc2lvbk1ldGFkYXRhLnZhcmlhbnRzW3ZhcmlhbnQubmFtZV0ucHVzaCh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzaDogYmFieWxvbk1lc2gsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWw6IGJhYnlsb25NYXRlcmlhbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlcGxhY2UgdGhlIHRhcmdldCB3aGVuIG9yaWdpbmFsIG1lc2ggaXMgY2xvbmVkXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWVzaC5vbkNsb25lZE9ic2VydmFibGUuYWRkKChuZXdPbmU6IE5vZGUpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBuZXdNZXNoID0gbmV3T25lIGFzIE1lc2g7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGV0IG1ldGFkYXRhOiBOdWxsYWJsZTxJRXh0ZW5zaW9uTWV0YWRhdGE+ID0gbnVsbDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgbmV3Um9vdDogTnVsbGFibGU8Tm9kZT4gPSBuZXdNZXNoO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBGaW5kIHJvb3QgdG8gZ2V0IG1lZGF0YVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRvIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Um9vdCA9IG5ld1Jvb3QhLnBhcmVudDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFuZXdSb290KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWV0YWRhdGEgPSBLSFJfbWF0ZXJpYWxzX3ZhcmlhbnRzLl9HZXRFeHRlbnNpb25NZXRhZGF0YShuZXdSb290IGFzIE1lc2gpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gd2hpbGUgKG1ldGFkYXRhID09PSBudWxsKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gTmVlZCB0byBjbG9uZSB0aGUgbWV0YWRhdGEgb24gdGhlIHJvb3QgKGZpcnN0IHRpbWUgb25seSlcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocm9vdCAmJiBtZXRhZGF0YSA9PT0gS0hSX21hdGVyaWFsc192YXJpYW50cy5fR2V0RXh0ZW5zaW9uTWV0YWRhdGEocm9vdCkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ29weSBtYWluIG1ldGFkYXRhXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1Jvb3QuX2ludGVybmFsTWV0YWRhdGEgPSB7fTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gcm9vdC5faW50ZXJuYWxNZXRhZGF0YSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmV3Um9vdC5faW50ZXJuYWxNZXRhZGF0YVtrZXldID0gcm9vdC5faW50ZXJuYWxNZXRhZGF0YVtrZXldO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBDb3B5IHRoZSBnbHRmIG1ldGFkYXRhXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1Jvb3QuX2ludGVybmFsTWV0YWRhdGEuZ2x0ZiA9IFtdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiByb290Ll9pbnRlcm5hbE1ldGFkYXRhLmdsdGYpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1Jvb3QuX2ludGVybmFsTWV0YWRhdGEuZ2x0ZltrZXldID0gcm9vdC5faW50ZXJuYWxNZXRhZGF0YS5nbHRmW2tleV07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIER1cGxpY2F0ZSB0aGUgZXh0ZW5zaW9uIHNwZWNpZmljIG1ldGFkYXRhXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1Jvb3QuX2ludGVybmFsTWV0YWRhdGEuZ2x0ZltOQU1FXSA9IHsgbGFzdFNlbGVjdGVkOiBudWxsLCBvcmlnaW5hbDogW10sIHZhcmlhbnRzOiB7fSB9O1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IG9yaWdpbmFsIG9mIG1ldGFkYXRhLm9yaWdpbmFsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdSb290Ll9pbnRlcm5hbE1ldGFkYXRhLmdsdGZbTkFNRV0ub3JpZ2luYWwucHVzaCh7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWVzaDogb3JpZ2luYWwubWVzaCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtYXRlcmlhbDogb3JpZ2luYWwubWF0ZXJpYWwsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBtZXRhZGF0YS52YXJpYW50cykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChtZXRhZGF0YS52YXJpYW50cywga2V5KSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5ld1Jvb3QuX2ludGVybmFsTWV0YWRhdGEuZ2x0ZltOQU1FXS52YXJpYW50c1trZXldID0gW107XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCB2YXJpYW50RW50cnkgb2YgbWV0YWRhdGEudmFyaWFudHNba2V5XSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuZXdSb290Ll9pbnRlcm5hbE1ldGFkYXRhLmdsdGZbTkFNRV0udmFyaWFudHNba2V5XS5wdXNoKHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1lc2g6IHZhcmlhbnRFbnRyeS5tZXNoLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbWF0ZXJpYWw6IHZhcmlhbnRFbnRyeS5tYXRlcmlhbCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRhZGF0YSA9IG5ld1Jvb3QuX2ludGVybmFsTWV0YWRhdGEuZ2x0ZltOQU1FXTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFJlbG9jYXRlXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCB0YXJnZXQgb2YgbWV0YWRhdGEhLm9yaWdpbmFsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0YXJnZXQubWVzaCA9PT0gYmFieWxvbk1lc2gpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRhcmdldC5tZXNoID0gbmV3TWVzaDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHRhcmdldCBvZiBtZXRhZGF0YSEudmFyaWFudHNbdmFyaWFudC5uYW1lXSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGFyZ2V0Lm1lc2ggPT09IGJhYnlsb25NZXNoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0YXJnZXQubWVzaCA9IG5ld01lc2g7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKChbYmFieWxvbk1lc2hdKSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gYmFieWxvbk1lc2g7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKE5BTUUsIChsb2FkZXIpID0+IG5ldyBLSFJfbWF0ZXJpYWxzX3ZhcmlhbnRzKGxvYWRlcikpO1xyXG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb24gKi9cclxuaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB7IFBCUk1hdGVyaWFsIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL1BCUi9wYnJNYXRlcmlhbFwiO1xyXG5pbXBvcnQgdHlwZSB7IE1hdGVyaWFsIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL21hdGVyaWFsXCI7XHJcbmltcG9ydCB0eXBlIHsgQmFzZVRleHR1cmUgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvVGV4dHVyZXMvYmFzZVRleHR1cmVcIjtcclxuaW1wb3J0IHR5cGUgeyBJTWF0ZXJpYWwsIElUZXh0dXJlSW5mbyB9IGZyb20gXCIuLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgSUtIUk1hdGVyaWFsc1ZvbHVtZSB9IGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuXHJcbmNvbnN0IE5BTUUgPSBcIktIUl9tYXRlcmlhbHNfdm9sdW1lXCI7XHJcblxyXG4vKipcclxuICogW1NwZWNpZmljYXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9LaHJvbm9zR3JvdXAvZ2xURi9ibG9iL21haW4vZXh0ZW5zaW9ucy8yLjAvS2hyb25vcy9LSFJfbWF0ZXJpYWxzX3ZvbHVtZS9SRUFETUUubWQpXHJcbiAqIEBzaW5jZSA1LjAuMFxyXG4gKi9cclxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxyXG5leHBvcnQgY2xhc3MgS0hSX21hdGVyaWFsc192b2x1bWUgaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGEgbnVtYmVyIHRoYXQgZGV0ZXJtaW5lcyB0aGUgb3JkZXIgdGhlIGV4dGVuc2lvbnMgYXJlIGFwcGxpZWQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBvcmRlciA9IDE3MztcclxuXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGVyOiBHTFRGTG9hZGVyKSB7XHJcbiAgICAgICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyO1xyXG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IHRoaXMuX2xvYWRlci5pc0V4dGVuc2lvblVzZWQoTkFNRSk7XHJcbiAgICAgICAgaWYgKHRoaXMuZW5hYmxlZCkge1xyXG4gICAgICAgICAgICAvLyBXZSBuZWVkIHRvIGRpc2FibGUgaW5zdGFuY2UgdXNhZ2UgYmVjYXVzZSB0aGUgYXR0ZW51YXRpb24gZmFjdG9yIGRlcGVuZHMgb24gdGhlIG5vZGUgc2NhbGUgb2YgZWFjaCBpbmRpdmlkdWFsIG1lc2hcclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyLl9kaXNhYmxlSW5zdGFuY2VkTWVzaCsrO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpIHtcclxuICAgICAgICBpZiAodGhpcy5lbmFibGVkKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2xvYWRlci5fZGlzYWJsZUluc3RhbmNlZE1lc2gtLTtcclxuICAgICAgICB9XHJcbiAgICAgICAgKHRoaXMuX2xvYWRlciBhcyBhbnkpID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZE1hdGVyaWFsUHJvcGVydGllc0FzeW5jKGNvbnRleHQ6IHN0cmluZywgbWF0ZXJpYWw6IElNYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsOiBNYXRlcmlhbCk6IE51bGxhYmxlPFByb21pc2U8dm9pZD4+IHtcclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SUtIUk1hdGVyaWFsc1ZvbHVtZT4oY29udGV4dCwgbWF0ZXJpYWwsIHRoaXMubmFtZSwgKGV4dGVuc2lvbkNvbnRleHQsIGV4dGVuc2lvbikgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBwcm9taXNlcyA9IG5ldyBBcnJheTxQcm9taXNlPGFueT4+KCk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fbG9hZGVyLmxvYWRNYXRlcmlhbEJhc2VQcm9wZXJ0aWVzQXN5bmMoY29udGV4dCwgbWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbCkpO1xyXG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKHRoaXMuX2xvYWRlci5sb2FkTWF0ZXJpYWxQcm9wZXJ0aWVzQXN5bmMoY29udGV4dCwgbWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbCkpO1xyXG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKHRoaXMuX2xvYWRWb2x1bWVQcm9wZXJ0aWVzQXN5bmMoZXh0ZW5zaW9uQ29udGV4dCwgbWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbCwgZXh0ZW5zaW9uKSk7XHJcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7fSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZFZvbHVtZVByb3BlcnRpZXNBc3luYyhjb250ZXh0OiBzdHJpbmcsIG1hdGVyaWFsOiBJTWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwsIGV4dGVuc2lvbjogSUtIUk1hdGVyaWFsc1ZvbHVtZSk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGlmICghKGJhYnlsb25NYXRlcmlhbCBpbnN0YW5jZW9mIFBCUk1hdGVyaWFsKSkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29udGV4dH06IE1hdGVyaWFsIHR5cGUgbm90IHN1cHBvcnRlZGApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gSWYgdHJhbnNwYXJlbmN5IGlzbid0IGVuYWJsZWQgYWxyZWFkeSwgdGhpcyBleHRlbnNpb24gc2hvdWxkbid0IGRvIGFueXRoaW5nLlxyXG4gICAgICAgIC8vIGkuZS4gaXQgcmVxdWlyZXMgZWl0aGVyIHRoZSBLSFJfbWF0ZXJpYWxzX3RyYW5zbWlzc2lvbiBvciBLSFJfbWF0ZXJpYWxzX3RyYW5zbHVjZW5jeSBleHRlbnNpb25zLlxyXG4gICAgICAgIGlmICgoIWJhYnlsb25NYXRlcmlhbC5zdWJTdXJmYWNlLmlzUmVmcmFjdGlvbkVuYWJsZWQgJiYgIWJhYnlsb25NYXRlcmlhbC5zdWJTdXJmYWNlLmlzVHJhbnNsdWNlbmN5RW5hYmxlZCkgfHwgIWV4dGVuc2lvbi50aGlja25lc3NGYWN0b3IpIHtcclxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gSU9SIGluIHRoaXMgZXh0ZW5zaW9uIG9ubHkgYWZmZWN0cyBpbnRlcmlvci5cclxuICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuc3ViU3VyZmFjZS52b2x1bWVJbmRleE9mUmVmcmFjdGlvbiA9IGJhYnlsb25NYXRlcmlhbC5pbmRleE9mUmVmcmFjdGlvbjtcclxuICAgICAgICBjb25zdCBhdHRlbnVhdGlvbkRpc3RhbmNlID0gZXh0ZW5zaW9uLmF0dGVudWF0aW9uRGlzdGFuY2UgIT09IHVuZGVmaW5lZCA/IGV4dGVuc2lvbi5hdHRlbnVhdGlvbkRpc3RhbmNlIDogTnVtYmVyLk1BWF9WQUxVRTtcclxuICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuc3ViU3VyZmFjZS50aW50Q29sb3JBdERpc3RhbmNlID0gYXR0ZW51YXRpb25EaXN0YW5jZTtcclxuICAgICAgICBpZiAoZXh0ZW5zaW9uLmF0dGVudWF0aW9uQ29sb3IgIT09IHVuZGVmaW5lZCAmJiBleHRlbnNpb24uYXR0ZW51YXRpb25Db2xvci5sZW5ndGggPT0gMykge1xyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuc3ViU3VyZmFjZS50aW50Q29sb3IuY29weUZyb21GbG9hdHMoZXh0ZW5zaW9uLmF0dGVudWF0aW9uQ29sb3JbMF0sIGV4dGVuc2lvbi5hdHRlbnVhdGlvbkNvbG9yWzFdLCBleHRlbnNpb24uYXR0ZW51YXRpb25Db2xvclsyXSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuc3ViU3VyZmFjZS5taW5pbXVtVGhpY2tuZXNzID0gMC4wO1xyXG4gICAgICAgIGJhYnlsb25NYXRlcmlhbC5zdWJTdXJmYWNlLm1heGltdW1UaGlja25lc3MgPSBleHRlbnNpb24udGhpY2tuZXNzRmFjdG9yO1xyXG4gICAgICAgIGJhYnlsb25NYXRlcmlhbC5zdWJTdXJmYWNlLnVzZVRoaWNrbmVzc0FzRGVwdGggPSB0cnVlO1xyXG4gICAgICAgIGlmIChleHRlbnNpb24udGhpY2tuZXNzVGV4dHVyZSkge1xyXG4gICAgICAgICAgICAoZXh0ZW5zaW9uLnRoaWNrbmVzc1RleHR1cmUgYXMgSVRleHR1cmVJbmZvKS5ub25Db2xvckRhdGEgPSB0cnVlO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbG9hZGVyLmxvYWRUZXh0dXJlSW5mb0FzeW5jKGAke2NvbnRleHR9L3RoaWNrbmVzc1RleHR1cmVgLCBleHRlbnNpb24udGhpY2tuZXNzVGV4dHVyZSkudGhlbigodGV4dHVyZTogQmFzZVRleHR1cmUpID0+IHtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5zdWJTdXJmYWNlLnRoaWNrbmVzc1RleHR1cmUgPSB0ZXh0dXJlO1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLnN1YlN1cmZhY2UudXNlR2x0ZlN0eWxlVGV4dHVyZXMgPSB0cnVlO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKE5BTUUsIChsb2FkZXIpID0+IG5ldyBLSFJfbWF0ZXJpYWxzX3ZvbHVtZShsb2FkZXIpKTtcclxuIiwiaW1wb3J0IHR5cGUgeyBJR0xURkxvYWRlckV4dGVuc2lvbiB9IGZyb20gXCIuLi9nbFRGTG9hZGVyRXh0ZW5zaW9uXCI7XHJcbmltcG9ydCB7IEdMVEZMb2FkZXIgfSBmcm9tIFwiLi4vZ2xURkxvYWRlclwiO1xyXG5cclxuY29uc3QgTkFNRSA9IFwiS0hSX21lc2hfcXVhbnRpemF0aW9uXCI7XHJcblxyXG4vKipcclxuICogW1NwZWNpZmljYXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9LaHJvbm9zR3JvdXAvZ2xURi9ibG9iL21haW4vZXh0ZW5zaW9ucy8yLjAvS2hyb25vcy9LSFJfbWVzaF9xdWFudGl6YXRpb24vUkVBRE1FLm1kKVxyXG4gKi9cclxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxyXG5leHBvcnQgY2xhc3MgS0hSX21lc2hfcXVhbnRpemF0aW9uIGltcGxlbWVudHMgSUdMVEZMb2FkZXJFeHRlbnNpb24ge1xyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGlzIGV4dGVuc2lvbi5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHJlYWRvbmx5IG5hbWUgPSBOQU1FO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lcyB3aGV0aGVyIHRoaXMgZXh0ZW5zaW9uIGlzIGVuYWJsZWQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBlbmFibGVkOiBib29sZWFuO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKGxvYWRlcjogR0xURkxvYWRlcikge1xyXG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IGxvYWRlci5pc0V4dGVuc2lvblVzZWQoTkFNRSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKSB7fVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKE5BTUUsIChsb2FkZXIpID0+IG5ldyBLSFJfbWVzaF9xdWFudGl6YXRpb24obG9hZGVyKSk7XHJcbiIsImltcG9ydCB0eXBlIHsgSUdMVEZMb2FkZXJFeHRlbnNpb24gfSBmcm9tIFwiLi4vZ2xURkxvYWRlckV4dGVuc2lvblwiO1xyXG5pbXBvcnQgeyBHTFRGTG9hZGVyLCBBcnJheUl0ZW0gfSBmcm9tIFwiLi4vZ2xURkxvYWRlclwiO1xyXG5pbXBvcnQgdHlwZSB7IElUZXh0dXJlIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcbmltcG9ydCB0eXBlIHsgQmFzZVRleHR1cmUgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvVGV4dHVyZXMvYmFzZVRleHR1cmVcIjtcclxuaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB0eXBlIHsgSUtIUlRleHR1cmVCYXNpc1UgfSBmcm9tIFwiYmFieWxvbmpzLWdsdGYyaW50ZXJmYWNlXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJLSFJfdGV4dHVyZV9iYXNpc3VcIjtcclxuXHJcbi8qKlxyXG4gKiBbU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly9naXRodWIuY29tL0tocm9ub3NHcm91cC9nbFRGL2Jsb2IvbWFpbi9leHRlbnNpb25zLzIuMC9LaHJvbm9zL0tIUl90ZXh0dXJlX2Jhc2lzdS9SRUFETUUubWQpXHJcbiAqL1xyXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXHJcbmV4cG9ydCBjbGFzcyBLSFJfdGV4dHVyZV9iYXNpc3UgaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKiogVGhlIG5hbWUgb2YgdGhpcyBleHRlbnNpb24uICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqIERlZmluZXMgd2hldGhlciB0aGlzIGV4dGVuc2lvbiBpcyBlbmFibGVkLiAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZGVyOiBHTFRGTG9hZGVyO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKGxvYWRlcjogR0xURkxvYWRlcikge1xyXG4gICAgICAgIHRoaXMuX2xvYWRlciA9IGxvYWRlcjtcclxuICAgICAgICB0aGlzLmVuYWJsZWQgPSBsb2FkZXIuaXNFeHRlbnNpb25Vc2VkKE5BTUUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBkaXNwb3NlKCkge1xyXG4gICAgICAgICh0aGlzLl9sb2FkZXIgYXMgYW55KSA9IG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIF9sb2FkVGV4dHVyZUFzeW5jKGNvbnRleHQ6IHN0cmluZywgdGV4dHVyZTogSVRleHR1cmUsIGFzc2lnbjogKGJhYnlsb25UZXh0dXJlOiBCYXNlVGV4dHVyZSkgPT4gdm9pZCk6IE51bGxhYmxlPFByb21pc2U8QmFzZVRleHR1cmU+PiB7XHJcbiAgICAgICAgcmV0dXJuIEdMVEZMb2FkZXIuTG9hZEV4dGVuc2lvbkFzeW5jPElLSFJUZXh0dXJlQmFzaXNVLCBCYXNlVGV4dHVyZT4oY29udGV4dCwgdGV4dHVyZSwgdGhpcy5uYW1lLCAoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IHNhbXBsZXIgPSB0ZXh0dXJlLnNhbXBsZXIgPT0gdW5kZWZpbmVkID8gR0xURkxvYWRlci5EZWZhdWx0U2FtcGxlciA6IEFycmF5SXRlbS5HZXQoYCR7Y29udGV4dH0vc2FtcGxlcmAsIHRoaXMuX2xvYWRlci5nbHRmLnNhbXBsZXJzLCB0ZXh0dXJlLnNhbXBsZXIpO1xyXG4gICAgICAgICAgICBjb25zdCBpbWFnZSA9IEFycmF5SXRlbS5HZXQoYCR7ZXh0ZW5zaW9uQ29udGV4dH0vc291cmNlYCwgdGhpcy5fbG9hZGVyLmdsdGYuaW1hZ2VzLCBleHRlbnNpb24uc291cmNlKTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2xvYWRlci5fY3JlYXRlVGV4dHVyZUFzeW5jKFxyXG4gICAgICAgICAgICAgICAgY29udGV4dCxcclxuICAgICAgICAgICAgICAgIHNhbXBsZXIsXHJcbiAgICAgICAgICAgICAgICBpbWFnZSxcclxuICAgICAgICAgICAgICAgIChiYWJ5bG9uVGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGFzc2lnbihiYWJ5bG9uVGV4dHVyZSk7XHJcbiAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgdGV4dHVyZS5fdGV4dHVyZUluZm8ubm9uQ29sb3JEYXRhID8geyB1c2VSR0JBSWZBU1RDQkM3Tm90QXZhaWxhYmxlV2hlblVBU1RDOiB0cnVlIH0gOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgICAgICAhdGV4dHVyZS5fdGV4dHVyZUluZm8ubm9uQ29sb3JEYXRhXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbkdMVEZMb2FkZXIuUmVnaXN0ZXJFeHRlbnNpb24oTkFNRSwgKGxvYWRlcikgPT4gbmV3IEtIUl90ZXh0dXJlX2Jhc2lzdShsb2FkZXIpKTtcclxuIiwiaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB0eXBlIHsgQmFzZVRleHR1cmUgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvVGV4dHVyZXMvYmFzZVRleHR1cmVcIjtcclxuaW1wb3J0IHsgVGV4dHVyZSB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9UZXh0dXJlcy90ZXh0dXJlXCI7XHJcblxyXG5pbXBvcnQgdHlwZSB7IElUZXh0dXJlSW5mbyB9IGZyb20gXCIuLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgSUtIUlRleHR1cmVUcmFuc2Zvcm0gfSBmcm9tIFwiYmFieWxvbmpzLWdsdGYyaW50ZXJmYWNlXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJLSFJfdGV4dHVyZV90cmFuc2Zvcm1cIjtcclxuXHJcbi8qKlxyXG4gKiBbU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly9naXRodWIuY29tL0tocm9ub3NHcm91cC9nbFRGL2Jsb2IvbWFpbi9leHRlbnNpb25zLzIuMC9LaHJvbm9zL0tIUl90ZXh0dXJlX3RyYW5zZm9ybS9SRUFETUUubWQpXHJcbiAqL1xyXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXHJcbmV4cG9ydCBjbGFzcyBLSFJfdGV4dHVyZV90cmFuc2Zvcm0gaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZGVyOiBHTFRGTG9hZGVyO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKGxvYWRlcjogR0xURkxvYWRlcikge1xyXG4gICAgICAgIHRoaXMuX2xvYWRlciA9IGxvYWRlcjtcclxuICAgICAgICB0aGlzLmVuYWJsZWQgPSB0aGlzLl9sb2FkZXIuaXNFeHRlbnNpb25Vc2VkKE5BTUUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBkaXNwb3NlKCkge1xyXG4gICAgICAgICh0aGlzLl9sb2FkZXIgYXMgYW55KSA9IG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRUZXh0dXJlSW5mb0FzeW5jKGNvbnRleHQ6IHN0cmluZywgdGV4dHVyZUluZm86IElUZXh0dXJlSW5mbywgYXNzaWduOiAoYmFieWxvblRleHR1cmU6IEJhc2VUZXh0dXJlKSA9PiB2b2lkKTogTnVsbGFibGU8UHJvbWlzZTxCYXNlVGV4dHVyZT4+IHtcclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SUtIUlRleHR1cmVUcmFuc2Zvcm0sIEJhc2VUZXh0dXJlPihjb250ZXh0LCB0ZXh0dXJlSW5mbywgdGhpcy5uYW1lLCAoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9sb2FkZXIubG9hZFRleHR1cmVJbmZvQXN5bmMoY29udGV4dCwgdGV4dHVyZUluZm8sIChiYWJ5bG9uVGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKCEoYmFieWxvblRleHR1cmUgaW5zdGFuY2VvZiBUZXh0dXJlKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtleHRlbnNpb25Db250ZXh0fTogVGV4dHVyZSB0eXBlIG5vdCBzdXBwb3J0ZWRgKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoZXh0ZW5zaW9uLm9mZnNldCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25UZXh0dXJlLnVPZmZzZXQgPSBleHRlbnNpb24ub2Zmc2V0WzBdO1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25UZXh0dXJlLnZPZmZzZXQgPSBleHRlbnNpb24ub2Zmc2V0WzFdO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIC8vIEFsd2F5cyByb3RhdGUgYXJvdW5kIHRoZSBvcmlnaW4uXHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uVGV4dHVyZS51Um90YXRpb25DZW50ZXIgPSAwO1xyXG4gICAgICAgICAgICAgICAgYmFieWxvblRleHR1cmUudlJvdGF0aW9uQ2VudGVyID0gMDtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoZXh0ZW5zaW9uLnJvdGF0aW9uKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYmFieWxvblRleHR1cmUud0FuZyA9IC1leHRlbnNpb24ucm90YXRpb247XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGV4dGVuc2lvbi5zY2FsZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25UZXh0dXJlLnVTY2FsZSA9IGV4dGVuc2lvbi5zY2FsZVswXTtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uVGV4dHVyZS52U2NhbGUgPSBleHRlbnNpb24uc2NhbGVbMV07XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGV4dGVuc2lvbi50ZXhDb29yZCAhPSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uVGV4dHVyZS5jb29yZGluYXRlc0luZGV4ID0gZXh0ZW5zaW9uLnRleENvb3JkO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGFzc2lnbihiYWJ5bG9uVGV4dHVyZSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKE5BTUUsIChsb2FkZXIpID0+IG5ldyBLSFJfdGV4dHVyZV90cmFuc2Zvcm0obG9hZGVyKSk7XHJcbiIsImltcG9ydCB0eXBlIHsgSUdMVEZMb2FkZXJFeHRlbnNpb24gfSBmcm9tIFwiLi4vZ2xURkxvYWRlckV4dGVuc2lvblwiO1xyXG5pbXBvcnQgeyBHTFRGTG9hZGVyIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJcIjtcclxuaW1wb3J0IHR5cGUgeyBJS0hSWG1wSnNvbkxkX0dsdGYsIElLSFJYbXBKc29uTGRfTm9kZSB9IGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuXHJcbmNvbnN0IE5BTUUgPSBcIktIUl94bXBfanNvbl9sZFwiO1xyXG5cclxuLyoqXHJcbiAqIFtTcGVjaWZpY2F0aW9uXShodHRwczovL2dpdGh1Yi5jb20vS2hyb25vc0dyb3VwL2dsVEYvYmxvYi9tYWluL2V4dGVuc2lvbnMvMi4wL0tocm9ub3MvS0hSX3htcF9qc29uX2xkL1JFQURNRS5tZClcclxuICogQHNpbmNlIDUuMC4wXHJcbiAqL1xyXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXHJcbmV4cG9ydCBjbGFzcyBLSFJfeG1wX2pzb25fbGQgaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGEgbnVtYmVyIHRoYXQgZGV0ZXJtaW5lcyB0aGUgb3JkZXIgdGhlIGV4dGVuc2lvbnMgYXJlIGFwcGxpZWQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBvcmRlciA9IDEwMDtcclxuXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IobG9hZGVyOiBHTFRGTG9hZGVyKSB7XHJcbiAgICAgICAgdGhpcy5fbG9hZGVyID0gbG9hZGVyO1xyXG4gICAgICAgIHRoaXMuZW5hYmxlZCA9IHRoaXMuX2xvYWRlci5pc0V4dGVuc2lvblVzZWQoTkFNRSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKSB7XHJcbiAgICAgICAgKHRoaXMuX2xvYWRlciBhcyBhbnkpID0gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENhbGxlZCBhZnRlciB0aGUgbG9hZGVyIHN0YXRlIGNoYW5nZXMgdG8gTE9BRElORy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIG9uTG9hZGluZygpOiB2b2lkIHtcclxuICAgICAgICBpZiAodGhpcy5fbG9hZGVyLnJvb3RCYWJ5bG9uTWVzaCA9PT0gbnVsbCkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCB4bXBfZ2x0ZiA9IHRoaXMuX2xvYWRlci5nbHRmLmV4dGVuc2lvbnM/LktIUl94bXBfanNvbl9sZCBhcyBJS0hSWG1wSnNvbkxkX0dsdGY7XHJcbiAgICAgICAgY29uc3QgeG1wX25vZGUgPSB0aGlzLl9sb2FkZXIuZ2x0Zi5hc3NldD8uZXh0ZW5zaW9ucz8uS0hSX3htcF9qc29uX2xkIGFzIElLSFJYbXBKc29uTGRfTm9kZTtcclxuICAgICAgICBpZiAoeG1wX2dsdGYgJiYgeG1wX25vZGUpIHtcclxuICAgICAgICAgICAgY29uc3QgcGFja2V0ID0gK3htcF9ub2RlLnBhY2tldDtcclxuICAgICAgICAgICAgaWYgKHhtcF9nbHRmLnBhY2tldHMgJiYgcGFja2V0IDwgeG1wX2dsdGYucGFja2V0cy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRlci5yb290QmFieWxvbk1lc2gubWV0YWRhdGEgPSB0aGlzLl9sb2FkZXIucm9vdEJhYnlsb25NZXNoLm1ldGFkYXRhIHx8IHt9O1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fbG9hZGVyLnJvb3RCYWJ5bG9uTWVzaC5tZXRhZGF0YS54bXAgPSB4bXBfZ2x0Zi5wYWNrZXRzW3BhY2tldF07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbkdMVEZMb2FkZXIuUmVnaXN0ZXJFeHRlbnNpb24oTkFNRSwgKGxvYWRlcikgPT4gbmV3IEtIUl94bXBfanNvbl9sZChsb2FkZXIpKTtcclxuIiwiaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB7IFZlY3RvcjMgfSBmcm9tIFwiY29yZS9NYXRocy9tYXRoLnZlY3RvclwiO1xyXG5pbXBvcnQgeyBUb29scyB9IGZyb20gXCJjb3JlL01pc2MvdG9vbHNcIjtcclxuaW1wb3J0IHR5cGUgeyBBbmltYXRpb25Hcm91cCB9IGZyb20gXCJjb3JlL0FuaW1hdGlvbnMvYW5pbWF0aW9uR3JvdXBcIjtcclxuaW1wb3J0IHsgQW5pbWF0aW9uRXZlbnQgfSBmcm9tIFwiY29yZS9BbmltYXRpb25zL2FuaW1hdGlvbkV2ZW50XCI7XHJcbmltcG9ydCB0eXBlIHsgVHJhbnNmb3JtTm9kZSB9IGZyb20gXCJjb3JlL01lc2hlcy90cmFuc2Zvcm1Ob2RlXCI7XHJcbmltcG9ydCB7IFNvdW5kIH0gZnJvbSBcImNvcmUvQXVkaW8vc291bmRcIjtcclxuaW1wb3J0IHsgV2VpZ2h0ZWRTb3VuZCB9IGZyb20gXCJjb3JlL0F1ZGlvL3dlaWdodGVkc291bmRcIjtcclxuXHJcbmltcG9ydCB0eXBlIHsgSUFycmF5SXRlbSwgSVNjZW5lLCBJTm9kZSwgSUFuaW1hdGlvbiB9IGZyb20gXCIuLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciwgQXJyYXlJdGVtIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJcIjtcclxuaW1wb3J0IHR5cGUgeyBJTVNGVEF1ZGlvRW1pdHRlcl9DbGlwLCBJTVNGVEF1ZGlvRW1pdHRlcl9FbWl0dGVyLCBJTVNGVEF1ZGlvRW1pdHRlcl9FbWl0dGVyc1JlZmVyZW5jZSwgSU1TRlRBdWRpb0VtaXR0ZXJfQW5pbWF0aW9uRXZlbnQgfSBmcm9tIFwiYmFieWxvbmpzLWdsdGYyaW50ZXJmYWNlXCI7XHJcbmltcG9ydCB7IElNU0ZUQXVkaW9FbWl0dGVyX0FuaW1hdGlvbkV2ZW50QWN0aW9uIH0gZnJvbSBcImJhYnlsb25qcy1nbHRmMmludGVyZmFjZVwiO1xyXG5cclxuY29uc3QgTkFNRSA9IFwiTVNGVF9hdWRpb19lbWl0dGVyXCI7XHJcblxyXG5pbnRlcmZhY2UgSUxvYWRlckNsaXAgZXh0ZW5kcyBJTVNGVEF1ZGlvRW1pdHRlcl9DbGlwLCBJQXJyYXlJdGVtIHtcclxuICAgIF9vYmplY3RVUkw/OiBQcm9taXNlPHN0cmluZz47XHJcbn1cclxuXHJcbmludGVyZmFjZSBJTG9hZGVyRW1pdHRlciBleHRlbmRzIElNU0ZUQXVkaW9FbWl0dGVyX0VtaXR0ZXIsIElBcnJheUl0ZW0ge1xyXG4gICAgX2JhYnlsb25EYXRhPzoge1xyXG4gICAgICAgIHNvdW5kPzogV2VpZ2h0ZWRTb3VuZDtcclxuICAgICAgICBsb2FkZWQ6IFByb21pc2U8dm9pZD47XHJcbiAgICB9O1xyXG4gICAgX2JhYnlsb25Tb3VuZHM6IFNvdW5kW107XHJcbn1cclxuXHJcbmludGVyZmFjZSBJTVNGVEF1ZGlvRW1pdHRlciB7XHJcbiAgICBjbGlwczogSUxvYWRlckNsaXBbXTtcclxuICAgIGVtaXR0ZXJzOiBJTG9hZGVyRW1pdHRlcltdO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgSUxvYWRlckFuaW1hdGlvbkV2ZW50IGV4dGVuZHMgSU1TRlRBdWRpb0VtaXR0ZXJfQW5pbWF0aW9uRXZlbnQsIElBcnJheUl0ZW0ge31cclxuXHJcbmludGVyZmFjZSBJTG9hZGVyQW5pbWF0aW9uRXZlbnRzIHtcclxuICAgIGV2ZW50czogSUxvYWRlckFuaW1hdGlvbkV2ZW50W107XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBbU3BlY2lmaWNhdGlvbl0oaHR0cHM6Ly9naXRodWIuY29tL25hamFkb2pvL2dsVEYvYmxvYi9NU0ZUX2F1ZGlvX2VtaXR0ZXIvZXh0ZW5zaW9ucy8yLjAvVmVuZG9yL01TRlRfYXVkaW9fZW1pdHRlci9SRUFETUUubWQpXHJcbiAqICEhISBFeHBlcmltZW50YWwgRXh0ZW5zaW9uIFN1YmplY3QgdG8gQ2hhbmdlcyAhISFcclxuICovXHJcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cclxuZXhwb3J0IGNsYXNzIE1TRlRfYXVkaW9fZW1pdHRlciBpbXBsZW1lbnRzIElHTFRGTG9hZGVyRXh0ZW5zaW9uIHtcclxuICAgIC8qKlxyXG4gICAgICogVGhlIG5hbWUgb2YgdGhpcyBleHRlbnNpb24uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyByZWFkb25seSBuYW1lID0gTkFNRTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgd2hldGhlciB0aGlzIGV4dGVuc2lvbiBpcyBlbmFibGVkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZW5hYmxlZDogYm9vbGVhbjtcclxuXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcbiAgICBwcml2YXRlIF9jbGlwczogQXJyYXk8SUxvYWRlckNsaXA+O1xyXG4gICAgcHJpdmF0ZSBfZW1pdHRlcnM6IEFycmF5PElMb2FkZXJFbWl0dGVyPjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBjb25zdHJ1Y3Rvcihsb2FkZXI6IEdMVEZMb2FkZXIpIHtcclxuICAgICAgICB0aGlzLl9sb2FkZXIgPSBsb2FkZXI7XHJcbiAgICAgICAgdGhpcy5lbmFibGVkID0gdGhpcy5fbG9hZGVyLmlzRXh0ZW5zaW9uVXNlZChOQU1FKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpIHtcclxuICAgICAgICAodGhpcy5fbG9hZGVyIGFzIGFueSkgPSBudWxsO1xyXG4gICAgICAgICh0aGlzLl9jbGlwcyBhcyBhbnkpID0gbnVsbDtcclxuICAgICAgICAodGhpcy5fZW1pdHRlcnMgYXMgYW55KSA9IG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIG9uTG9hZGluZygpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBleHRlbnNpb25zID0gdGhpcy5fbG9hZGVyLmdsdGYuZXh0ZW5zaW9ucztcclxuICAgICAgICBpZiAoZXh0ZW5zaW9ucyAmJiBleHRlbnNpb25zW3RoaXMubmFtZV0pIHtcclxuICAgICAgICAgICAgY29uc3QgZXh0ZW5zaW9uID0gZXh0ZW5zaW9uc1t0aGlzLm5hbWVdIGFzIElNU0ZUQXVkaW9FbWl0dGVyO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5fY2xpcHMgPSBleHRlbnNpb24uY2xpcHM7XHJcbiAgICAgICAgICAgIHRoaXMuX2VtaXR0ZXJzID0gZXh0ZW5zaW9uLmVtaXR0ZXJzO1xyXG5cclxuICAgICAgICAgICAgQXJyYXlJdGVtLkFzc2lnbih0aGlzLl9jbGlwcyk7XHJcbiAgICAgICAgICAgIEFycmF5SXRlbS5Bc3NpZ24odGhpcy5fZW1pdHRlcnMpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZFNjZW5lQXN5bmMoY29udGV4dDogc3RyaW5nLCBzY2VuZTogSVNjZW5lKTogTnVsbGFibGU8UHJvbWlzZTx2b2lkPj4ge1xyXG4gICAgICAgIHJldHVybiBHTFRGTG9hZGVyLkxvYWRFeHRlbnNpb25Bc3luYzxJTVNGVEF1ZGlvRW1pdHRlcl9FbWl0dGVyc1JlZmVyZW5jZT4oY29udGV4dCwgc2NlbmUsIHRoaXMubmFtZSwgKGV4dGVuc2lvbkNvbnRleHQsIGV4dGVuc2lvbikgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBwcm9taXNlcyA9IG5ldyBBcnJheTxQcm9taXNlPGFueT4+KCk7XHJcblxyXG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKHRoaXMuX2xvYWRlci5sb2FkU2NlbmVBc3luYyhjb250ZXh0LCBzY2VuZSkpO1xyXG5cclxuICAgICAgICAgICAgZm9yIChjb25zdCBlbWl0dGVySW5kZXggb2YgZXh0ZW5zaW9uLmVtaXR0ZXJzKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBlbWl0dGVyID0gQXJyYXlJdGVtLkdldChgJHtleHRlbnNpb25Db250ZXh0fS9lbWl0dGVyc2AsIHRoaXMuX2VtaXR0ZXJzLCBlbWl0dGVySW5kZXgpO1xyXG4gICAgICAgICAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICAgICAgICAgIGVtaXR0ZXIucmVmRGlzdGFuY2UgIT0gdW5kZWZpbmVkIHx8XHJcbiAgICAgICAgICAgICAgICAgICAgZW1pdHRlci5tYXhEaXN0YW5jZSAhPSB1bmRlZmluZWQgfHxcclxuICAgICAgICAgICAgICAgICAgICBlbWl0dGVyLnJvbGxvZmZGYWN0b3IgIT0gdW5kZWZpbmVkIHx8XHJcbiAgICAgICAgICAgICAgICAgICAgZW1pdHRlci5kaXN0YW5jZU1vZGVsICE9IHVuZGVmaW5lZCB8fFxyXG4gICAgICAgICAgICAgICAgICAgIGVtaXR0ZXIuaW5uZXJBbmdsZSAhPSB1bmRlZmluZWQgfHxcclxuICAgICAgICAgICAgICAgICAgICBlbWl0dGVyLm91dGVyQW5nbGUgIT0gdW5kZWZpbmVkXHJcbiAgICAgICAgICAgICAgICApIHtcclxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZXh0ZW5zaW9uQ29udGV4dH06IERpcmVjdGlvbiBvciBEaXN0YW5jZSBwcm9wZXJ0aWVzIGFyZSBub3QgYWxsb3dlZCBvbiBlbWl0dGVycyBhdHRhY2hlZCB0byBhIHNjZW5lYCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkRW1pdHRlckFzeW5jKGAke2V4dGVuc2lvbkNvbnRleHR9L2VtaXR0ZXJzLyR7ZW1pdHRlci5pbmRleH1gLCBlbWl0dGVyKSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7fSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWROb2RlQXN5bmMoY29udGV4dDogc3RyaW5nLCBub2RlOiBJTm9kZSwgYXNzaWduOiAoYmFieWxvblRyYW5zZm9ybU5vZGU6IFRyYW5zZm9ybU5vZGUpID0+IHZvaWQpOiBOdWxsYWJsZTxQcm9taXNlPFRyYW5zZm9ybU5vZGU+PiB7XHJcbiAgICAgICAgcmV0dXJuIEdMVEZMb2FkZXIuTG9hZEV4dGVuc2lvbkFzeW5jPElNU0ZUQXVkaW9FbWl0dGVyX0VtaXR0ZXJzUmVmZXJlbmNlLCBUcmFuc2Zvcm1Ob2RlPihjb250ZXh0LCBub2RlLCB0aGlzLm5hbWUsIChleHRlbnNpb25Db250ZXh0LCBleHRlbnNpb24pID0+IHtcclxuICAgICAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBuZXcgQXJyYXk8UHJvbWlzZTxhbnk+PigpO1xyXG5cclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX2xvYWRlclxyXG4gICAgICAgICAgICAgICAgLmxvYWROb2RlQXN5bmMoZXh0ZW5zaW9uQ29udGV4dCwgbm9kZSwgKGJhYnlsb25NZXNoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBlbWl0dGVySW5kZXggb2YgZXh0ZW5zaW9uLmVtaXR0ZXJzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVtaXR0ZXIgPSBBcnJheUl0ZW0uR2V0KGAke2V4dGVuc2lvbkNvbnRleHR9L2VtaXR0ZXJzYCwgdGhpcy5fZW1pdHRlcnMsIGVtaXR0ZXJJbmRleCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkRW1pdHRlckFzeW5jKGAke2V4dGVuc2lvbkNvbnRleHR9L2VtaXR0ZXJzLyR7ZW1pdHRlci5pbmRleH1gLCBlbWl0dGVyKS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IHNvdW5kIG9mIGVtaXR0ZXIuX2JhYnlsb25Tb3VuZHMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291bmQuYXR0YWNoVG9NZXNoKGJhYnlsb25NZXNoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGVtaXR0ZXIuaW5uZXJBbmdsZSAhPSB1bmRlZmluZWQgfHwgZW1pdHRlci5vdXRlckFuZ2xlICE9IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291bmQuc2V0TG9jYWxEaXJlY3Rpb25Ub01lc2goVmVjdG9yMy5Gb3J3YXJkKCkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc291bmQuc2V0RGlyZWN0aW9uYWxDb25lKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDIgKiBUb29scy5Ub0RlZ3JlZXMoZW1pdHRlci5pbm5lckFuZ2xlID09IHVuZGVmaW5lZCA/IE1hdGguUEkgOiBlbWl0dGVyLmlubmVyQW5nbGUpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDIgKiBUb29scy5Ub0RlZ3JlZXMoZW1pdHRlci5vdXRlckFuZ2xlID09IHVuZGVmaW5lZCA/IE1hdGguUEkgOiBlbWl0dGVyLm91dGVyQW5nbGUpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDBcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgYXNzaWduKGJhYnlsb25NZXNoKTtcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICAudGhlbigoYmFieWxvbk1lc2gpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYmFieWxvbk1lc2g7XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZEFuaW1hdGlvbkFzeW5jKGNvbnRleHQ6IHN0cmluZywgYW5pbWF0aW9uOiBJQW5pbWF0aW9uKTogTnVsbGFibGU8UHJvbWlzZTxBbmltYXRpb25Hcm91cD4+IHtcclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SUxvYWRlckFuaW1hdGlvbkV2ZW50cywgQW5pbWF0aW9uR3JvdXA+KGNvbnRleHQsIGFuaW1hdGlvbiwgdGhpcy5uYW1lLCAoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9sb2FkZXIubG9hZEFuaW1hdGlvbkFzeW5jKGNvbnRleHQsIGFuaW1hdGlvbikudGhlbigoYmFieWxvbkFuaW1hdGlvbkdyb3VwKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBwcm9taXNlcyA9IG5ldyBBcnJheTxQcm9taXNlPGFueT4+KCk7XHJcblxyXG4gICAgICAgICAgICAgICAgQXJyYXlJdGVtLkFzc2lnbihleHRlbnNpb24uZXZlbnRzKTtcclxuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgZXZlbnQgb2YgZXh0ZW5zaW9uLmV2ZW50cykge1xyXG4gICAgICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fbG9hZEFuaW1hdGlvbkV2ZW50QXN5bmMoYCR7ZXh0ZW5zaW9uQ29udGV4dH0vZXZlbnRzLyR7ZXZlbnQuaW5kZXh9YCwgY29udGV4dCwgYW5pbWF0aW9uLCBldmVudCwgYmFieWxvbkFuaW1hdGlvbkdyb3VwKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYmFieWxvbkFuaW1hdGlvbkdyb3VwO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2xvYWRDbGlwQXN5bmMoY29udGV4dDogc3RyaW5nLCBjbGlwOiBJTG9hZGVyQ2xpcCk6IFByb21pc2U8c3RyaW5nPiB7XHJcbiAgICAgICAgaWYgKGNsaXAuX29iamVjdFVSTCkge1xyXG4gICAgICAgICAgICByZXR1cm4gY2xpcC5fb2JqZWN0VVJMO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IHByb21pc2U6IFByb21pc2U8QXJyYXlCdWZmZXJWaWV3PjtcclxuICAgICAgICBpZiAoY2xpcC51cmkpIHtcclxuICAgICAgICAgICAgcHJvbWlzZSA9IHRoaXMuX2xvYWRlci5sb2FkVXJpQXN5bmMoY29udGV4dCwgY2xpcCwgY2xpcC51cmkpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlclZpZXcgPSBBcnJheUl0ZW0uR2V0KGAke2NvbnRleHR9L2J1ZmZlclZpZXdgLCB0aGlzLl9sb2FkZXIuZ2x0Zi5idWZmZXJWaWV3cywgY2xpcC5idWZmZXJWaWV3KTtcclxuICAgICAgICAgICAgcHJvbWlzZSA9IHRoaXMuX2xvYWRlci5sb2FkQnVmZmVyVmlld0FzeW5jKGAvYnVmZmVyVmlld3MvJHtidWZmZXJWaWV3LmluZGV4fWAsIGJ1ZmZlclZpZXcpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY2xpcC5fb2JqZWN0VVJMID0gcHJvbWlzZS50aGVuKChkYXRhKSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiBVUkwuY3JlYXRlT2JqZWN0VVJMKG5ldyBCbG9iKFtkYXRhXSwgeyB0eXBlOiBjbGlwLm1pbWVUeXBlIH0pKTtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgcmV0dXJuIGNsaXAuX29iamVjdFVSTDtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9sb2FkRW1pdHRlckFzeW5jKGNvbnRleHQ6IHN0cmluZywgZW1pdHRlcjogSUxvYWRlckVtaXR0ZXIpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBlbWl0dGVyLl9iYWJ5bG9uU291bmRzID0gZW1pdHRlci5fYmFieWxvblNvdW5kcyB8fCBbXTtcclxuICAgICAgICBpZiAoIWVtaXR0ZXIuX2JhYnlsb25EYXRhKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGNsaXBQcm9taXNlcyA9IG5ldyBBcnJheTxQcm9taXNlPGFueT4+KCk7XHJcbiAgICAgICAgICAgIGNvbnN0IG5hbWUgPSBlbWl0dGVyLm5hbWUgfHwgYGVtaXR0ZXIke2VtaXR0ZXIuaW5kZXh9YDtcclxuICAgICAgICAgICAgY29uc3Qgb3B0aW9ucyA9IHtcclxuICAgICAgICAgICAgICAgIGxvb3A6IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgYXV0b3BsYXk6IGZhbHNlLFxyXG4gICAgICAgICAgICAgICAgdm9sdW1lOiBlbWl0dGVyLnZvbHVtZSA9PSB1bmRlZmluZWQgPyAxIDogZW1pdHRlci52b2x1bWUsXHJcbiAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVtaXR0ZXIuY2xpcHMubGVuZ3RoOyBpKyspIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGNsaXBDb250ZXh0ID0gYC9leHRlbnNpb25zLyR7dGhpcy5uYW1lfS9jbGlwc2A7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBjbGlwID0gQXJyYXlJdGVtLkdldChjbGlwQ29udGV4dCwgdGhpcy5fY2xpcHMsIGVtaXR0ZXIuY2xpcHNbaV0uY2xpcCk7XHJcbiAgICAgICAgICAgICAgICBjbGlwUHJvbWlzZXMucHVzaChcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkQ2xpcEFzeW5jKGAke2NsaXBDb250ZXh0fS8ke2VtaXR0ZXIuY2xpcHNbaV0uY2xpcH1gLCBjbGlwKS50aGVuKChvYmplY3RVUkw6IHN0cmluZykgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzb3VuZCA9IChlbWl0dGVyLl9iYWJ5bG9uU291bmRzW2ldID0gbmV3IFNvdW5kKG5hbWUsIG9iamVjdFVSTCwgdGhpcy5fbG9hZGVyLmJhYnlsb25TY2VuZSwgbnVsbCwgb3B0aW9ucykpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzb3VuZC5yZWZEaXN0YW5jZSA9IGVtaXR0ZXIucmVmRGlzdGFuY2UgfHwgMTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc291bmQubWF4RGlzdGFuY2UgPSBlbWl0dGVyLm1heERpc3RhbmNlIHx8IDI1NjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgc291bmQucm9sbG9mZkZhY3RvciA9IGVtaXR0ZXIucm9sbG9mZkZhY3RvciB8fCAxO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBzb3VuZC5kaXN0YW5jZU1vZGVsID0gZW1pdHRlci5kaXN0YW5jZU1vZGVsIHx8IFwiZXhwb25lbnRpYWxcIjtcclxuICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3QgcHJvbWlzZSA9IFByb21pc2UuYWxsKGNsaXBQcm9taXNlcykudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB3ZWlnaHRzID0gZW1pdHRlci5jbGlwcy5tYXAoKGNsaXApID0+IHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gY2xpcC53ZWlnaHQgfHwgMTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICAgICAgY29uc3Qgd2VpZ2h0ZWRTb3VuZCA9IG5ldyBXZWlnaHRlZFNvdW5kKGVtaXR0ZXIubG9vcCB8fCBmYWxzZSwgZW1pdHRlci5fYmFieWxvblNvdW5kcywgd2VpZ2h0cyk7XHJcbiAgICAgICAgICAgICAgICBpZiAoZW1pdHRlci5pbm5lckFuZ2xlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgd2VpZ2h0ZWRTb3VuZC5kaXJlY3Rpb25hbENvbmVJbm5lckFuZ2xlID0gMiAqIFRvb2xzLlRvRGVncmVlcyhlbWl0dGVyLmlubmVyQW5nbGUpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKGVtaXR0ZXIub3V0ZXJBbmdsZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHdlaWdodGVkU291bmQuZGlyZWN0aW9uYWxDb25lT3V0ZXJBbmdsZSA9IDIgKiBUb29scy5Ub0RlZ3JlZXMoZW1pdHRlci5vdXRlckFuZ2xlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGlmIChlbWl0dGVyLnZvbHVtZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHdlaWdodGVkU291bmQudm9sdW1lID0gZW1pdHRlci52b2x1bWU7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBlbWl0dGVyLl9iYWJ5bG9uRGF0YSEuc291bmQgPSB3ZWlnaHRlZFNvdW5kO1xyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIGVtaXR0ZXIuX2JhYnlsb25EYXRhID0ge1xyXG4gICAgICAgICAgICAgICAgbG9hZGVkOiBwcm9taXNlLFxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGVtaXR0ZXIuX2JhYnlsb25EYXRhLmxvYWRlZDtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9nZXRFdmVudEFjdGlvbihcclxuICAgICAgICBjb250ZXh0OiBzdHJpbmcsXHJcbiAgICAgICAgc291bmQ6IFdlaWdodGVkU291bmQsXHJcbiAgICAgICAgYWN0aW9uOiBJTVNGVEF1ZGlvRW1pdHRlcl9BbmltYXRpb25FdmVudEFjdGlvbixcclxuICAgICAgICB0aW1lOiBudW1iZXIsXHJcbiAgICAgICAgc3RhcnRPZmZzZXQ/OiBudW1iZXJcclxuICAgICk6IChjdXJyZW50RnJhbWU6IG51bWJlcikgPT4gdm9pZCB7XHJcbiAgICAgICAgc3dpdGNoIChhY3Rpb24pIHtcclxuICAgICAgICAgICAgY2FzZSBJTVNGVEF1ZGlvRW1pdHRlcl9BbmltYXRpb25FdmVudEFjdGlvbi5wbGF5OiB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gKGN1cnJlbnRGcmFtZTogbnVtYmVyKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZnJhbWVPZmZzZXQgPSAoc3RhcnRPZmZzZXQgfHwgMCkgKyAoY3VycmVudEZyYW1lIC0gdGltZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgc291bmQucGxheShmcmFtZU9mZnNldCk7XHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNhc2UgSU1TRlRBdWRpb0VtaXR0ZXJfQW5pbWF0aW9uRXZlbnRBY3Rpb24uc3RvcDoge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuICgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBzb3VuZC5zdG9wKCk7XHJcbiAgICAgICAgICAgICAgICB9O1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNhc2UgSU1TRlRBdWRpb0VtaXR0ZXJfQW5pbWF0aW9uRXZlbnRBY3Rpb24ucGF1c2U6IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgc291bmQucGF1c2UoKTtcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZGVmYXVsdDoge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBVbnN1cHBvcnRlZCBhY3Rpb24gJHthY3Rpb259YCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZEFuaW1hdGlvbkV2ZW50QXN5bmMoXHJcbiAgICAgICAgY29udGV4dDogc3RyaW5nLFxyXG4gICAgICAgIGFuaW1hdGlvbkNvbnRleHQ6IHN0cmluZyxcclxuICAgICAgICBhbmltYXRpb246IElBbmltYXRpb24sXHJcbiAgICAgICAgZXZlbnQ6IElMb2FkZXJBbmltYXRpb25FdmVudCxcclxuICAgICAgICBiYWJ5bG9uQW5pbWF0aW9uR3JvdXA6IEFuaW1hdGlvbkdyb3VwXHJcbiAgICApOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBpZiAoYmFieWxvbkFuaW1hdGlvbkdyb3VwLnRhcmdldGVkQW5pbWF0aW9ucy5sZW5ndGggPT0gMCkge1xyXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGNvbnN0IGJhYnlsb25BbmltYXRpb24gPSBiYWJ5bG9uQW5pbWF0aW9uR3JvdXAudGFyZ2V0ZWRBbmltYXRpb25zWzBdO1xyXG4gICAgICAgIGNvbnN0IGVtaXR0ZXJJbmRleCA9IGV2ZW50LmVtaXR0ZXI7XHJcbiAgICAgICAgY29uc3QgZW1pdHRlciA9IEFycmF5SXRlbS5HZXQoYC9leHRlbnNpb25zLyR7dGhpcy5uYW1lfS9lbWl0dGVyc2AsIHRoaXMuX2VtaXR0ZXJzLCBlbWl0dGVySW5kZXgpO1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9sb2FkRW1pdHRlckFzeW5jKGNvbnRleHQsIGVtaXR0ZXIpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBzb3VuZCA9IGVtaXR0ZXIuX2JhYnlsb25EYXRhIS5zb3VuZDtcclxuICAgICAgICAgICAgaWYgKHNvdW5kKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBiYWJ5bG9uQW5pbWF0aW9uRXZlbnQgPSBuZXcgQW5pbWF0aW9uRXZlbnQoZXZlbnQudGltZSwgdGhpcy5fZ2V0RXZlbnRBY3Rpb24oY29udGV4dCwgc291bmQsIGV2ZW50LmFjdGlvbiwgZXZlbnQudGltZSwgZXZlbnQuc3RhcnRPZmZzZXQpKTtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25BbmltYXRpb24uYW5pbWF0aW9uLmFkZEV2ZW50KGJhYnlsb25BbmltYXRpb25FdmVudCk7XHJcbiAgICAgICAgICAgICAgICAvLyBNYWtlIHN1cmUgYWxsIHN0YXJ0ZWQgYXVkaW8gc3RvcHMgd2hlbiB0aGlzIGFuaW1hdGlvbiBpcyB0ZXJtaW5hdGVkLlxyXG4gICAgICAgICAgICAgICAgYmFieWxvbkFuaW1hdGlvbkdyb3VwLm9uQW5pbWF0aW9uR3JvdXBFbmRPYnNlcnZhYmxlLmFkZCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgc291bmQuc3RvcCgpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uQW5pbWF0aW9uR3JvdXAub25BbmltYXRpb25Hcm91cFBhdXNlT2JzZXJ2YWJsZS5hZGQoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHNvdW5kLnBhdXNlKCk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKE5BTUUsIChsb2FkZXIpID0+IG5ldyBNU0ZUX2F1ZGlvX2VtaXR0ZXIobG9hZGVyKSk7XHJcbiIsImltcG9ydCB0eXBlIHsgTnVsbGFibGUgfSBmcm9tIFwiY29yZS90eXBlc1wiO1xyXG5pbXBvcnQgeyBPYnNlcnZhYmxlIH0gZnJvbSBcImNvcmUvTWlzYy9vYnNlcnZhYmxlXCI7XHJcbmltcG9ydCB7IERlZmVycmVkIH0gZnJvbSBcImNvcmUvTWlzYy9kZWZlcnJlZFwiO1xyXG5pbXBvcnQgdHlwZSB7IE1hdGVyaWFsIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL21hdGVyaWFsXCI7XHJcbmltcG9ydCB0eXBlIHsgVHJhbnNmb3JtTm9kZSB9IGZyb20gXCJjb3JlL01lc2hlcy90cmFuc2Zvcm1Ob2RlXCI7XHJcbmltcG9ydCB0eXBlIHsgTWVzaCB9IGZyb20gXCJjb3JlL01lc2hlcy9tZXNoXCI7XHJcbmltcG9ydCB0eXBlIHsgQmFzZVRleHR1cmUgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvVGV4dHVyZXMvYmFzZVRleHR1cmVcIjtcclxuaW1wb3J0IHR5cGUgeyBJTm9kZSwgSU1hdGVyaWFsLCBJQnVmZmVyLCBJU2NlbmUgfSBmcm9tIFwiLi4vZ2xURkxvYWRlckludGVyZmFjZXNcIjtcclxuaW1wb3J0IHR5cGUgeyBJR0xURkxvYWRlckV4dGVuc2lvbiB9IGZyb20gXCIuLi9nbFRGTG9hZGVyRXh0ZW5zaW9uXCI7XHJcbmltcG9ydCB7IEdMVEZMb2FkZXIsIEFycmF5SXRlbSB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgSVByb3BlcnR5LCBJTVNGVExPRCB9IGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuXHJcbmNvbnN0IE5BTUUgPSBcIk1TRlRfbG9kXCI7XHJcblxyXG5pbnRlcmZhY2UgSUJ1ZmZlckluZm8ge1xyXG4gICAgc3RhcnQ6IG51bWJlcjtcclxuICAgIGVuZDogbnVtYmVyO1xyXG4gICAgbG9hZGVkOiBEZWZlcnJlZDxBcnJheUJ1ZmZlclZpZXc+O1xyXG59XHJcblxyXG4vKipcclxuICogW1NwZWNpZmljYXRpb25dKGh0dHBzOi8vZ2l0aHViLmNvbS9LaHJvbm9zR3JvdXAvZ2xURi9ibG9iL21haW4vZXh0ZW5zaW9ucy8yLjAvVmVuZG9yL01TRlRfbG9kL1JFQURNRS5tZClcclxuICovXHJcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cclxuZXhwb3J0IGNsYXNzIE1TRlRfbG9kIGltcGxlbWVudHMgSUdMVEZMb2FkZXJFeHRlbnNpb24ge1xyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgbmFtZSBvZiB0aGlzIGV4dGVuc2lvbi5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHJlYWRvbmx5IG5hbWUgPSBOQU1FO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lcyB3aGV0aGVyIHRoaXMgZXh0ZW5zaW9uIGlzIGVuYWJsZWQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBlbmFibGVkOiBib29sZWFuO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lcyBhIG51bWJlciB0aGF0IGRldGVybWluZXMgdGhlIG9yZGVyIHRoZSBleHRlbnNpb25zIGFyZSBhcHBsaWVkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgb3JkZXIgPSAxMDA7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBNYXhpbXVtIG51bWJlciBvZiBMT0RzIHRvIGxvYWQsIHN0YXJ0aW5nIGZyb20gdGhlIGxvd2VzdCBMT0QuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBtYXhMT0RzVG9Mb2FkID0gMTA7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPYnNlcnZhYmxlIHJhaXNlZCB3aGVuIGFsbCBub2RlIExPRHMgb2Ygb25lIGxldmVsIGFyZSBsb2FkZWQuXHJcbiAgICAgKiBUaGUgZXZlbnQgZGF0YSBpcyB0aGUgaW5kZXggb2YgdGhlIGxvYWRlZCBMT0Qgc3RhcnRpbmcgZnJvbSB6ZXJvLlxyXG4gICAgICogRGlzcG9zZSB0aGUgbG9hZGVyIHRvIGNhbmNlbCB0aGUgbG9hZGluZyBvZiB0aGUgbmV4dCBsZXZlbCBvZiBMT0RzLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgb25Ob2RlTE9Ec0xvYWRlZE9ic2VydmFibGUgPSBuZXcgT2JzZXJ2YWJsZTxudW1iZXI+KCk7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPYnNlcnZhYmxlIHJhaXNlZCB3aGVuIGFsbCBtYXRlcmlhbCBMT0RzIG9mIG9uZSBsZXZlbCBhcmUgbG9hZGVkLlxyXG4gICAgICogVGhlIGV2ZW50IGRhdGEgaXMgdGhlIGluZGV4IG9mIHRoZSBsb2FkZWQgTE9EIHN0YXJ0aW5nIGZyb20gemVyby5cclxuICAgICAqIERpc3Bvc2UgdGhlIGxvYWRlciB0byBjYW5jZWwgdGhlIGxvYWRpbmcgb2YgdGhlIG5leHQgbGV2ZWwgb2YgTE9Ecy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIG9uTWF0ZXJpYWxMT0RzTG9hZGVkT2JzZXJ2YWJsZSA9IG5ldyBPYnNlcnZhYmxlPG51bWJlcj4oKTtcclxuXHJcbiAgICBwcml2YXRlIF9sb2FkZXI6IEdMVEZMb2FkZXI7XHJcblxyXG4gICAgcHJpdmF0ZSBfYnVmZmVyTE9EcyA9IG5ldyBBcnJheTxJQnVmZmVySW5mbz4oKTtcclxuXHJcbiAgICBwcml2YXRlIF9ub2RlSW5kZXhMT0Q6IE51bGxhYmxlPG51bWJlcj4gPSBudWxsO1xyXG4gICAgcHJpdmF0ZSBfbm9kZVNpZ25hbExPRHMgPSBuZXcgQXJyYXk8RGVmZXJyZWQ8dm9pZD4+KCk7XHJcbiAgICBwcml2YXRlIF9ub2RlUHJvbWlzZUxPRHMgPSBuZXcgQXJyYXk8QXJyYXk8UHJvbWlzZTxhbnk+Pj4oKTtcclxuICAgIHByaXZhdGUgX25vZGVCdWZmZXJMT0RzID0gbmV3IEFycmF5PElCdWZmZXJJbmZvPigpO1xyXG5cclxuICAgIHByaXZhdGUgX21hdGVyaWFsSW5kZXhMT0Q6IE51bGxhYmxlPG51bWJlcj4gPSBudWxsO1xyXG4gICAgcHJpdmF0ZSBfbWF0ZXJpYWxTaWduYWxMT0RzID0gbmV3IEFycmF5PERlZmVycmVkPHZvaWQ+PigpO1xyXG4gICAgcHJpdmF0ZSBfbWF0ZXJpYWxQcm9taXNlTE9EcyA9IG5ldyBBcnJheTxBcnJheTxQcm9taXNlPGFueT4+PigpO1xyXG4gICAgcHJpdmF0ZSBfbWF0ZXJpYWxCdWZmZXJMT0RzID0gbmV3IEFycmF5PElCdWZmZXJJbmZvPigpO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKGxvYWRlcjogR0xURkxvYWRlcikge1xyXG4gICAgICAgIHRoaXMuX2xvYWRlciA9IGxvYWRlcjtcclxuICAgICAgICB0aGlzLmVuYWJsZWQgPSB0aGlzLl9sb2FkZXIuaXNFeHRlbnNpb25Vc2VkKE5BTUUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBkaXNwb3NlKCkge1xyXG4gICAgICAgICh0aGlzLl9sb2FkZXIgYXMgYW55KSA9IG51bGw7XHJcblxyXG4gICAgICAgIHRoaXMuX25vZGVJbmRleExPRCA9IG51bGw7XHJcbiAgICAgICAgdGhpcy5fbm9kZVNpZ25hbExPRHMubGVuZ3RoID0gMDtcclxuICAgICAgICB0aGlzLl9ub2RlUHJvbWlzZUxPRHMubGVuZ3RoID0gMDtcclxuICAgICAgICB0aGlzLl9ub2RlQnVmZmVyTE9Ecy5sZW5ndGggPSAwO1xyXG5cclxuICAgICAgICB0aGlzLl9tYXRlcmlhbEluZGV4TE9EID0gbnVsbDtcclxuICAgICAgICB0aGlzLl9tYXRlcmlhbFNpZ25hbExPRHMubGVuZ3RoID0gMDtcclxuICAgICAgICB0aGlzLl9tYXRlcmlhbFByb21pc2VMT0RzLmxlbmd0aCA9IDA7XHJcbiAgICAgICAgdGhpcy5fbWF0ZXJpYWxCdWZmZXJMT0RzLmxlbmd0aCA9IDA7XHJcblxyXG4gICAgICAgIHRoaXMub25NYXRlcmlhbExPRHNMb2FkZWRPYnNlcnZhYmxlLmNsZWFyKCk7XHJcbiAgICAgICAgdGhpcy5vbk5vZGVMT0RzTG9hZGVkT2JzZXJ2YWJsZS5jbGVhcigpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBvblJlYWR5KCk6IHZvaWQge1xyXG4gICAgICAgIGZvciAobGV0IGluZGV4TE9EID0gMDsgaW5kZXhMT0QgPCB0aGlzLl9ub2RlUHJvbWlzZUxPRHMubGVuZ3RoOyBpbmRleExPRCsrKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHByb21pc2UgPSBQcm9taXNlLmFsbCh0aGlzLl9ub2RlUHJvbWlzZUxPRHNbaW5kZXhMT0RdKS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgICAgIGlmIChpbmRleExPRCAhPT0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRlci5lbmRQZXJmb3JtYW5jZUNvdW50ZXIoYE5vZGUgTE9EICR7aW5kZXhMT0R9YCk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvZyhgTG9hZGVkIG5vZGUgTE9EICR7aW5kZXhMT0R9YCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgdGhpcy5vbk5vZGVMT0RzTG9hZGVkT2JzZXJ2YWJsZS5ub3RpZnlPYnNlcnZlcnMoaW5kZXhMT0QpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChpbmRleExPRCAhPT0gdGhpcy5fbm9kZVByb21pc2VMT0RzLmxlbmd0aCAtIDEpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIuc3RhcnRQZXJmb3JtYW5jZUNvdW50ZXIoYE5vZGUgTE9EICR7aW5kZXhMT0QgKyAxfWApO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRCdWZmZXJMT0QodGhpcy5fbm9kZUJ1ZmZlckxPRHMsIGluZGV4TE9EICsgMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX25vZGVTaWduYWxMT0RzW2luZGV4TE9EXSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9ub2RlU2lnbmFsTE9Ec1tpbmRleExPRF0ucmVzb2x2ZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLl9sb2FkZXIuX2NvbXBsZXRlUHJvbWlzZXMucHVzaChwcm9taXNlKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZvciAobGV0IGluZGV4TE9EID0gMDsgaW5kZXhMT0QgPCB0aGlzLl9tYXRlcmlhbFByb21pc2VMT0RzLmxlbmd0aDsgaW5kZXhMT0QrKykge1xyXG4gICAgICAgICAgICBjb25zdCBwcm9taXNlID0gUHJvbWlzZS5hbGwodGhpcy5fbWF0ZXJpYWxQcm9taXNlTE9Ec1tpbmRleExPRF0pLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4TE9EICE9PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmVuZFBlcmZvcm1hbmNlQ291bnRlcihgTWF0ZXJpYWwgTE9EICR7aW5kZXhMT0R9YCk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvZyhgTG9hZGVkIG1hdGVyaWFsIExPRCAke2luZGV4TE9EfWApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMub25NYXRlcmlhbExPRHNMb2FkZWRPYnNlcnZhYmxlLm5vdGlmeU9ic2VydmVycyhpbmRleExPRCk7XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4TE9EICE9PSB0aGlzLl9tYXRlcmlhbFByb21pc2VMT0RzLmxlbmd0aCAtIDEpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkZXIuc3RhcnRQZXJmb3JtYW5jZUNvdW50ZXIoYE1hdGVyaWFsIExPRCAke2luZGV4TE9EICsgMX1gKTtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkQnVmZmVyTE9EKHRoaXMuX21hdGVyaWFsQnVmZmVyTE9EcywgaW5kZXhMT0QgKyAxKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fbWF0ZXJpYWxTaWduYWxMT0RzW2luZGV4TE9EXSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9tYXRlcmlhbFNpZ25hbExPRHNbaW5kZXhMT0RdLnJlc29sdmUoKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyLl9jb21wbGV0ZVByb21pc2VzLnB1c2gocHJvbWlzZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkU2NlbmVBc3luYyhjb250ZXh0OiBzdHJpbmcsIHNjZW5lOiBJU2NlbmUpOiBOdWxsYWJsZTxQcm9taXNlPHZvaWQ+PiB7XHJcbiAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuX2xvYWRlci5sb2FkU2NlbmVBc3luYyhjb250ZXh0LCBzY2VuZSk7XHJcbiAgICAgICAgdGhpcy5fbG9hZEJ1ZmZlckxPRCh0aGlzLl9idWZmZXJMT0RzLCAwKTtcclxuICAgICAgICByZXR1cm4gcHJvbWlzZTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZE5vZGVBc3luYyhjb250ZXh0OiBzdHJpbmcsIG5vZGU6IElOb2RlLCBhc3NpZ246IChiYWJ5bG9uVHJhbnNmb3JtTm9kZTogVHJhbnNmb3JtTm9kZSkgPT4gdm9pZCk6IE51bGxhYmxlPFByb21pc2U8VHJhbnNmb3JtTm9kZT4+IHtcclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SU1TRlRMT0QsIFRyYW5zZm9ybU5vZGU+KGNvbnRleHQsIG5vZGUsIHRoaXMubmFtZSwgKGV4dGVuc2lvbkNvbnRleHQsIGV4dGVuc2lvbikgPT4ge1xyXG4gICAgICAgICAgICBsZXQgZmlyc3RQcm9taXNlOiBQcm9taXNlPFRyYW5zZm9ybU5vZGU+O1xyXG5cclxuICAgICAgICAgICAgY29uc3Qgbm9kZUxPRHMgPSB0aGlzLl9nZXRMT0RzKGV4dGVuc2lvbkNvbnRleHQsIG5vZGUsIHRoaXMuX2xvYWRlci5nbHRmLm5vZGVzLCBleHRlbnNpb24uaWRzKTtcclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvZ09wZW4oYCR7ZXh0ZW5zaW9uQ29udGV4dH1gKTtcclxuXHJcbiAgICAgICAgICAgIGZvciAobGV0IGluZGV4TE9EID0gMDsgaW5kZXhMT0QgPCBub2RlTE9Ecy5sZW5ndGg7IGluZGV4TE9EKyspIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG5vZGVMT0QgPSBub2RlTE9Ec1tpbmRleExPRF07XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4TE9EICE9PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbm9kZUluZGV4TE9EID0gaW5kZXhMT0Q7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbm9kZVNpZ25hbExPRHNbaW5kZXhMT0RdID0gdGhpcy5fbm9kZVNpZ25hbExPRHNbaW5kZXhMT0RdIHx8IG5ldyBEZWZlcnJlZCgpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IGFzc2lnbldyYXAgPSAoYmFieWxvblRyYW5zZm9ybU5vZGU6IFRyYW5zZm9ybU5vZGUpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBhc3NpZ24oYmFieWxvblRyYW5zZm9ybU5vZGUpO1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25UcmFuc2Zvcm1Ob2RlLnNldEVuYWJsZWQoZmFsc2UpO1xyXG4gICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICBjb25zdCBwcm9taXNlID0gdGhpcy5fbG9hZGVyLmxvYWROb2RlQXN5bmMoYC9ub2Rlcy8ke25vZGVMT0QuaW5kZXh9YCwgbm9kZUxPRCwgYXNzaWduV3JhcCkudGhlbigoYmFieWxvbk1lc2gpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhMT0QgIT09IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVE9ETzogc2hvdWxkIG5vdCByZWx5IG9uIF9iYWJ5bG9uVHJhbnNmb3JtTm9kZVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBwcmV2aW91c05vZGVMT0QgPSBub2RlTE9Ec1tpbmRleExPRCAtIDFdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAocHJldmlvdXNOb2RlTE9ELl9iYWJ5bG9uVHJhbnNmb3JtTm9kZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGlzcG9zZVRyYW5zZm9ybU5vZGUocHJldmlvdXNOb2RlTE9ELl9iYWJ5bG9uVHJhbnNmb3JtTm9kZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgcHJldmlvdXNOb2RlTE9ELl9iYWJ5bG9uVHJhbnNmb3JtTm9kZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgYmFieWxvbk1lc2guc2V0RW5hYmxlZCh0cnVlKTtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gYmFieWxvbk1lc2g7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9ub2RlUHJvbWlzZUxPRHNbaW5kZXhMT0RdID0gdGhpcy5fbm9kZVByb21pc2VMT0RzW2luZGV4TE9EXSB8fCBbXTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoaW5kZXhMT0QgPT09IDApIHtcclxuICAgICAgICAgICAgICAgICAgICBmaXJzdFByb21pc2UgPSBwcm9taXNlO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9ub2RlSW5kZXhMT0QgPSBudWxsO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX25vZGVQcm9taXNlTE9Ec1tpbmRleExPRF0ucHVzaChwcm9taXNlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvZ0Nsb3NlKCk7XHJcbiAgICAgICAgICAgIHJldHVybiBmaXJzdFByb21pc2UhO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBfbG9hZE1hdGVyaWFsQXN5bmMoXHJcbiAgICAgICAgY29udGV4dDogc3RyaW5nLFxyXG4gICAgICAgIG1hdGVyaWFsOiBJTWF0ZXJpYWwsXHJcbiAgICAgICAgYmFieWxvbk1lc2g6IE51bGxhYmxlPE1lc2g+LFxyXG4gICAgICAgIGJhYnlsb25EcmF3TW9kZTogbnVtYmVyLFxyXG4gICAgICAgIGFzc2lnbjogKGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwpID0+IHZvaWRcclxuICAgICk6IE51bGxhYmxlPFByb21pc2U8TWF0ZXJpYWw+PiB7XHJcbiAgICAgICAgLy8gRG9uJ3QgbG9hZCBtYXRlcmlhbCBMT0RzIGlmIGFscmVhZHkgbG9hZGluZyBhIG5vZGUgTE9ELlxyXG4gICAgICAgIGlmICh0aGlzLl9ub2RlSW5kZXhMT0QpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gR0xURkxvYWRlci5Mb2FkRXh0ZW5zaW9uQXN5bmM8SU1TRlRMT0QsIE1hdGVyaWFsPihjb250ZXh0LCBtYXRlcmlhbCwgdGhpcy5uYW1lLCAoZXh0ZW5zaW9uQ29udGV4dCwgZXh0ZW5zaW9uKSA9PiB7XHJcbiAgICAgICAgICAgIGxldCBmaXJzdFByb21pc2U6IFByb21pc2U8TWF0ZXJpYWw+O1xyXG5cclxuICAgICAgICAgICAgY29uc3QgbWF0ZXJpYWxMT0RzID0gdGhpcy5fZ2V0TE9EcyhleHRlbnNpb25Db250ZXh0LCBtYXRlcmlhbCwgdGhpcy5fbG9hZGVyLmdsdGYubWF0ZXJpYWxzLCBleHRlbnNpb24uaWRzKTtcclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvZ09wZW4oYCR7ZXh0ZW5zaW9uQ29udGV4dH1gKTtcclxuXHJcbiAgICAgICAgICAgIGZvciAobGV0IGluZGV4TE9EID0gMDsgaW5kZXhMT0QgPCBtYXRlcmlhbExPRHMubGVuZ3RoOyBpbmRleExPRCsrKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBtYXRlcmlhbExPRCA9IG1hdGVyaWFsTE9Ec1tpbmRleExPRF07XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4TE9EICE9PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbWF0ZXJpYWxJbmRleExPRCA9IGluZGV4TE9EO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IHByb21pc2UgPSB0aGlzLl9sb2FkZXJcclxuICAgICAgICAgICAgICAgICAgICAuX2xvYWRNYXRlcmlhbEFzeW5jKGAvbWF0ZXJpYWxzLyR7bWF0ZXJpYWxMT0QuaW5kZXh9YCwgbWF0ZXJpYWxMT0QsIGJhYnlsb25NZXNoLCBiYWJ5bG9uRHJhd01vZGUsIChiYWJ5bG9uTWF0ZXJpYWwpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4TE9EID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBhc3NpZ24oYmFieWxvbk1hdGVyaWFsKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICAgICAgLnRoZW4oKGJhYnlsb25NYXRlcmlhbCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW5kZXhMT0QgIT09IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFzc2lnbihiYWJ5bG9uTWF0ZXJpYWwpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRPRE86IHNob3VsZCBub3QgcmVseSBvbiBfZGF0YVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcHJldmlvdXNEYXRhTE9EID0gbWF0ZXJpYWxMT0RzW2luZGV4TE9EIC0gMV0uX2RhdGEhO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHByZXZpb3VzRGF0YUxPRFtiYWJ5bG9uRHJhd01vZGVdKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGlzcG9zZU1hdGVyaWFscyhbcHJldmlvdXNEYXRhTE9EW2JhYnlsb25EcmF3TW9kZV0uYmFieWxvbk1hdGVyaWFsXSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVsZXRlIHByZXZpb3VzRGF0YUxPRFtiYWJ5bG9uRHJhd01vZGVdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gYmFieWxvbk1hdGVyaWFsO1xyXG4gICAgICAgICAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuX21hdGVyaWFsUHJvbWlzZUxPRHNbaW5kZXhMT0RdID0gdGhpcy5fbWF0ZXJpYWxQcm9taXNlTE9Ec1tpbmRleExPRF0gfHwgW107XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKGluZGV4TE9EID09PSAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZmlyc3RQcm9taXNlID0gcHJvbWlzZTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbWF0ZXJpYWxJbmRleExPRCA9IG51bGw7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbWF0ZXJpYWxQcm9taXNlTE9Ec1tpbmRleExPRF0ucHVzaChwcm9taXNlKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvZ0Nsb3NlKCk7XHJcbiAgICAgICAgICAgIHJldHVybiBmaXJzdFByb21pc2UhO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBfbG9hZFVyaUFzeW5jKGNvbnRleHQ6IHN0cmluZywgcHJvcGVydHk6IElQcm9wZXJ0eSwgdXJpOiBzdHJpbmcpOiBOdWxsYWJsZTxQcm9taXNlPEFycmF5QnVmZmVyVmlldz4+IHtcclxuICAgICAgICAvLyBEZWZlciB0aGUgbG9hZGluZyBvZiB1cmlzIGlmIGxvYWRpbmcgYSBub2RlIG9yIG1hdGVyaWFsIExPRC5cclxuICAgICAgICBpZiAodGhpcy5fbm9kZUluZGV4TE9EICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2xvYWRlci5sb2coYGRlZmVycmVkYCk7XHJcbiAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzSW5kZXhMT0QgPSB0aGlzLl9ub2RlSW5kZXhMT0QgLSAxO1xyXG4gICAgICAgICAgICB0aGlzLl9ub2RlU2lnbmFsTE9Ec1twcmV2aW91c0luZGV4TE9EXSA9IHRoaXMuX25vZGVTaWduYWxMT0RzW3ByZXZpb3VzSW5kZXhMT0RdIHx8IG5ldyBEZWZlcnJlZDx2b2lkPigpO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbm9kZVNpZ25hbExPRHNbdGhpcy5fbm9kZUluZGV4TE9EIC0gMV0ucHJvbWlzZS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9sb2FkZXIubG9hZFVyaUFzeW5jKGNvbnRleHQsIHByb3BlcnR5LCB1cmkpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX21hdGVyaWFsSW5kZXhMT0QgIT09IG51bGwpIHtcclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvZyhgZGVmZXJyZWRgKTtcclxuICAgICAgICAgICAgY29uc3QgcHJldmlvdXNJbmRleExPRCA9IHRoaXMuX21hdGVyaWFsSW5kZXhMT0QgLSAxO1xyXG4gICAgICAgICAgICB0aGlzLl9tYXRlcmlhbFNpZ25hbExPRHNbcHJldmlvdXNJbmRleExPRF0gPSB0aGlzLl9tYXRlcmlhbFNpZ25hbExPRHNbcHJldmlvdXNJbmRleExPRF0gfHwgbmV3IERlZmVycmVkPHZvaWQ+KCk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9tYXRlcmlhbFNpZ25hbExPRHNbcHJldmlvdXNJbmRleExPRF0ucHJvbWlzZS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9sb2FkZXIubG9hZFVyaUFzeW5jKGNvbnRleHQsIHByb3BlcnR5LCB1cmkpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkQnVmZmVyQXN5bmMoY29udGV4dDogc3RyaW5nLCBidWZmZXI6IElCdWZmZXIsIGJ5dGVPZmZzZXQ6IG51bWJlciwgYnl0ZUxlbmd0aDogbnVtYmVyKTogTnVsbGFibGU8UHJvbWlzZTxBcnJheUJ1ZmZlclZpZXc+PiB7XHJcbiAgICAgICAgaWYgKHRoaXMuX2xvYWRlci5wYXJlbnQudXNlUmFuZ2VSZXF1ZXN0cyAmJiAhYnVmZmVyLnVyaSkge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuX2xvYWRlci5iaW4pIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fTogVXJpIGlzIG1pc3Npbmcgb3IgdGhlIGJpbmFyeSBnbFRGIGlzIG1pc3NpbmcgaXRzIGJpbmFyeSBjaHVua2ApO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBsb2FkQXN5bmMgPSAoYnVmZmVyTE9EczogQXJyYXk8SUJ1ZmZlckluZm8+LCBpbmRleExPRDogbnVtYmVyKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBzdGFydCA9IGJ5dGVPZmZzZXQ7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBlbmQgPSBzdGFydCArIGJ5dGVMZW5ndGggLSAxO1xyXG4gICAgICAgICAgICAgICAgbGV0IGJ1ZmZlckxPRCA9IGJ1ZmZlckxPRHNbaW5kZXhMT0RdO1xyXG4gICAgICAgICAgICAgICAgaWYgKGJ1ZmZlckxPRCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJ1ZmZlckxPRC5zdGFydCA9IE1hdGgubWluKGJ1ZmZlckxPRC5zdGFydCwgc3RhcnQpO1xyXG4gICAgICAgICAgICAgICAgICAgIGJ1ZmZlckxPRC5lbmQgPSBNYXRoLm1heChidWZmZXJMT0QuZW5kLCBlbmQpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBidWZmZXJMT0QgPSB7IHN0YXJ0OiBzdGFydCwgZW5kOiBlbmQsIGxvYWRlZDogbmV3IERlZmVycmVkKCkgfTtcclxuICAgICAgICAgICAgICAgICAgICBidWZmZXJMT0RzW2luZGV4TE9EXSA9IGJ1ZmZlckxPRDtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gYnVmZmVyTE9ELmxvYWRlZC5wcm9taXNlLnRoZW4oKGRhdGEpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFVpbnQ4QXJyYXkoZGF0YS5idWZmZXIsIGRhdGEuYnl0ZU9mZnNldCArIGJ5dGVPZmZzZXQgLSBidWZmZXJMT0Quc3RhcnQsIGJ5dGVMZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICB0aGlzLl9sb2FkZXIubG9nKGBkZWZlcnJlZGApO1xyXG5cclxuICAgICAgICAgICAgaWYgKHRoaXMuX25vZGVJbmRleExPRCAhPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGxvYWRBc3luYyh0aGlzLl9ub2RlQnVmZmVyTE9EcywgdGhpcy5fbm9kZUluZGV4TE9EKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLl9tYXRlcmlhbEluZGV4TE9EICE9PSBudWxsKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbG9hZEFzeW5jKHRoaXMuX21hdGVyaWFsQnVmZmVyTE9EcywgdGhpcy5fbWF0ZXJpYWxJbmRleExPRCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbG9hZEFzeW5jKHRoaXMuX2J1ZmZlckxPRHMsIDApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9sb2FkQnVmZmVyTE9EKGJ1ZmZlckxPRHM6IEFycmF5PElCdWZmZXJJbmZvPiwgaW5kZXhMT0Q6IG51bWJlcik6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IGJ1ZmZlckxPRCA9IGJ1ZmZlckxPRHNbaW5kZXhMT0RdO1xyXG4gICAgICAgIGlmIChidWZmZXJMT0QpIHtcclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyLmxvZyhgTG9hZGluZyBidWZmZXIgcmFuZ2UgWyR7YnVmZmVyTE9ELnN0YXJ0fS0ke2J1ZmZlckxPRC5lbmR9XWApO1xyXG4gICAgICAgICAgICB0aGlzLl9sb2FkZXIuYmluIS5yZWFkQXN5bmMoYnVmZmVyTE9ELnN0YXJ0LCBidWZmZXJMT0QuZW5kIC0gYnVmZmVyTE9ELnN0YXJ0ICsgMSkudGhlbihcclxuICAgICAgICAgICAgICAgIChkYXRhKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgYnVmZmVyTE9ELmxvYWRlZC5yZXNvbHZlKGRhdGEpO1xyXG4gICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgIChlcnJvcikgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGJ1ZmZlckxPRC5sb2FkZWQucmVqZWN0KGVycm9yKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIGFuIGFycmF5IG9mIExPRCBwcm9wZXJ0aWVzIGZyb20gbG93ZXN0IHRvIGhpZ2hlc3QuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dFxyXG4gICAgICogQHBhcmFtIHByb3BlcnR5XHJcbiAgICAgKiBAcGFyYW0gYXJyYXlcclxuICAgICAqIEBwYXJhbSBpZHNcclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBfZ2V0TE9EczxUPihjb250ZXh0OiBzdHJpbmcsIHByb3BlcnR5OiBULCBhcnJheTogQXJyYXlMaWtlPFQ+IHwgdW5kZWZpbmVkLCBpZHM6IG51bWJlcltdKTogVFtdIHtcclxuICAgICAgICBpZiAodGhpcy5tYXhMT0RzVG9Mb2FkIDw9IDApIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwibWF4TE9Ec1RvTG9hZCBtdXN0IGJlIGdyZWF0ZXIgdGhhbiB6ZXJvXCIpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgcHJvcGVydGllcyA9IG5ldyBBcnJheTxUPigpO1xyXG5cclxuICAgICAgICBmb3IgKGxldCBpID0gaWRzLmxlbmd0aCAtIDE7IGkgPj0gMDsgaS0tKSB7XHJcbiAgICAgICAgICAgIHByb3BlcnRpZXMucHVzaChBcnJheUl0ZW0uR2V0KGAke2NvbnRleHR9L2lkcy8ke2lkc1tpXX1gLCBhcnJheSwgaWRzW2ldKSk7XHJcbiAgICAgICAgICAgIGlmIChwcm9wZXJ0aWVzLmxlbmd0aCA9PT0gdGhpcy5tYXhMT0RzVG9Mb2FkKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvcGVydGllcztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcHJvcGVydGllcy5wdXNoKHByb3BlcnR5KTtcclxuICAgICAgICByZXR1cm4gcHJvcGVydGllcztcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9kaXNwb3NlVHJhbnNmb3JtTm9kZShiYWJ5bG9uVHJhbnNmb3JtTm9kZTogVHJhbnNmb3JtTm9kZSk6IHZvaWQge1xyXG4gICAgICAgIGNvbnN0IGJhYnlsb25NYXRlcmlhbHMgPSBuZXcgQXJyYXk8TWF0ZXJpYWw+KCk7XHJcbiAgICAgICAgY29uc3QgYmFieWxvbk1hdGVyaWFsID0gKGJhYnlsb25UcmFuc2Zvcm1Ob2RlIGFzIE1lc2gpLm1hdGVyaWFsO1xyXG4gICAgICAgIGlmIChiYWJ5bG9uTWF0ZXJpYWwpIHtcclxuICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFscy5wdXNoKGJhYnlsb25NYXRlcmlhbCk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGZvciAoY29uc3QgYmFieWxvbk1lc2ggb2YgYmFieWxvblRyYW5zZm9ybU5vZGUuZ2V0Q2hpbGRNZXNoZXMoKSkge1xyXG4gICAgICAgICAgICBpZiAoYmFieWxvbk1lc2gubWF0ZXJpYWwpIHtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbHMucHVzaChiYWJ5bG9uTWVzaC5tYXRlcmlhbCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGJhYnlsb25UcmFuc2Zvcm1Ob2RlLmRpc3Bvc2UoKTtcclxuXHJcbiAgICAgICAgY29uc3QgYmFieWxvbk1hdGVyaWFsc1RvRGlzcG9zZSA9IGJhYnlsb25NYXRlcmlhbHMuZmlsdGVyKChiYWJ5bG9uTWF0ZXJpYWwpID0+IHRoaXMuX2xvYWRlci5iYWJ5bG9uU2NlbmUubWVzaGVzLmV2ZXJ5KChtZXNoKSA9PiBtZXNoLm1hdGVyaWFsICE9IGJhYnlsb25NYXRlcmlhbCkpO1xyXG4gICAgICAgIHRoaXMuX2Rpc3Bvc2VNYXRlcmlhbHMoYmFieWxvbk1hdGVyaWFsc1RvRGlzcG9zZSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfZGlzcG9zZU1hdGVyaWFscyhiYWJ5bG9uTWF0ZXJpYWxzOiBNYXRlcmlhbFtdKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3QgYmFieWxvblRleHR1cmVzOiB7IFt1bmlxdWVJZDogbnVtYmVyXTogQmFzZVRleHR1cmUgfSA9IHt9O1xyXG5cclxuICAgICAgICBmb3IgKGNvbnN0IGJhYnlsb25NYXRlcmlhbCBvZiBiYWJ5bG9uTWF0ZXJpYWxzKSB7XHJcbiAgICAgICAgICAgIGZvciAoY29uc3QgYmFieWxvblRleHR1cmUgb2YgYmFieWxvbk1hdGVyaWFsLmdldEFjdGl2ZVRleHR1cmVzKCkpIHtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25UZXh0dXJlc1tiYWJ5bG9uVGV4dHVyZS51bmlxdWVJZF0gPSBiYWJ5bG9uVGV4dHVyZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLmRpc3Bvc2UoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZvciAoY29uc3QgdW5pcXVlSWQgaW4gYmFieWxvblRleHR1cmVzKSB7XHJcbiAgICAgICAgICAgIGZvciAoY29uc3QgYmFieWxvbk1hdGVyaWFsIG9mIHRoaXMuX2xvYWRlci5iYWJ5bG9uU2NlbmUubWF0ZXJpYWxzKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoYmFieWxvbk1hdGVyaWFsLmhhc1RleHR1cmUoYmFieWxvblRleHR1cmVzW3VuaXF1ZUlkXSkpIHtcclxuICAgICAgICAgICAgICAgICAgICBkZWxldGUgYmFieWxvblRleHR1cmVzW3VuaXF1ZUlkXTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yIChjb25zdCB1bmlxdWVJZCBpbiBiYWJ5bG9uVGV4dHVyZXMpIHtcclxuICAgICAgICAgICAgYmFieWxvblRleHR1cmVzW3VuaXF1ZUlkXS5kaXNwb3NlKCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG59XHJcblxyXG5HTFRGTG9hZGVyLlJlZ2lzdGVyRXh0ZW5zaW9uKE5BTUUsIChsb2FkZXIpID0+IG5ldyBNU0ZUX2xvZChsb2FkZXIpKTtcclxuIiwiaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB0eXBlIHsgTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvbWF0ZXJpYWxcIjtcclxuaW1wb3J0IHsgUEJSTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvUEJSL3Bick1hdGVyaWFsXCI7XHJcblxyXG5pbXBvcnQgdHlwZSB7IElNYXRlcmlhbCB9IGZyb20gXCIuLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJNU0ZUX21pbmVjcmFmdE1lc2hcIjtcclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxyXG5leHBvcnQgY2xhc3MgTVNGVF9taW5lY3JhZnRNZXNoIGltcGxlbWVudHMgSUdMVEZMb2FkZXJFeHRlbnNpb24ge1xyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIHJlYWRvbmx5IG5hbWUgPSBOQU1FO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBlbmFibGVkOiBib29sZWFuO1xyXG5cclxuICAgIHByaXZhdGUgX2xvYWRlcjogR0xURkxvYWRlcjtcclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBjb25zdHJ1Y3Rvcihsb2FkZXI6IEdMVEZMb2FkZXIpIHtcclxuICAgICAgICB0aGlzLl9sb2FkZXIgPSBsb2FkZXI7XHJcbiAgICAgICAgdGhpcy5lbmFibGVkID0gdGhpcy5fbG9hZGVyLmlzRXh0ZW5zaW9uVXNlZChOQU1FKTtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpIHtcclxuICAgICAgICAodGhpcy5fbG9hZGVyIGFzIGFueSkgPSBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBsb2FkTWF0ZXJpYWxQcm9wZXJ0aWVzQXN5bmMoY29udGV4dDogc3RyaW5nLCBtYXRlcmlhbDogSU1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWw6IE1hdGVyaWFsKTogTnVsbGFibGU8UHJvbWlzZTx2b2lkPj4ge1xyXG4gICAgICAgIHJldHVybiBHTFRGTG9hZGVyLkxvYWRFeHRyYUFzeW5jPGJvb2xlYW4+KGNvbnRleHQsIG1hdGVyaWFsLCB0aGlzLm5hbWUsIChleHRyYUNvbnRleHQsIGV4dHJhKSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChleHRyYSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKCEoYmFieWxvbk1hdGVyaWFsIGluc3RhbmNlb2YgUEJSTWF0ZXJpYWwpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2V4dHJhQ29udGV4dH06IE1hdGVyaWFsIHR5cGUgbm90IHN1cHBvcnRlZGApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IHByb21pc2UgPSB0aGlzLl9sb2FkZXIubG9hZE1hdGVyaWFsUHJvcGVydGllc0FzeW5jKGNvbnRleHQsIG1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWwpO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmIChiYWJ5bG9uTWF0ZXJpYWwubmVlZEFscGhhQmxlbmRpbmcoKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5mb3JjZURlcHRoV3JpdGUgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5zZXBhcmF0ZUN1bGxpbmdQYXNzID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuYmFja0ZhY2VDdWxsaW5nID0gYmFieWxvbk1hdGVyaWFsLmZvcmNlRGVwdGhXcml0ZTtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC50d29TaWRlZExpZ2h0aW5nID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgICAgICByZXR1cm4gcHJvbWlzZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcbn1cclxuXHJcbkdMVEZMb2FkZXIuUmVnaXN0ZXJFeHRlbnNpb24oTkFNRSwgKGxvYWRlcikgPT4gbmV3IE1TRlRfbWluZWNyYWZ0TWVzaChsb2FkZXIpKTtcclxuIiwiaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB0eXBlIHsgTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvbWF0ZXJpYWxcIjtcclxuaW1wb3J0IHsgUEJSTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvUEJSL3Bick1hdGVyaWFsXCI7XHJcblxyXG5pbXBvcnQgdHlwZSB7IElNYXRlcmlhbCB9IGZyb20gXCIuLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4uL2dsVEZMb2FkZXJFeHRlbnNpb25cIjtcclxuaW1wb3J0IHsgR0xURkxvYWRlciB9IGZyb20gXCIuLi9nbFRGTG9hZGVyXCI7XHJcblxyXG5jb25zdCBOQU1FID0gXCJNU0ZUX3NSR0JGYWN0b3JzXCI7XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cclxuZXhwb3J0IGNsYXNzIE1TRlRfc1JHQkZhY3RvcnMgaW1wbGVtZW50cyBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgbmFtZSA9IE5BTUU7XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGVuYWJsZWQ6IGJvb2xlYW47XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZGVyOiBHTFRGTG9hZGVyO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIGNvbnN0cnVjdG9yKGxvYWRlcjogR0xURkxvYWRlcikge1xyXG4gICAgICAgIHRoaXMuX2xvYWRlciA9IGxvYWRlcjtcclxuICAgICAgICB0aGlzLmVuYWJsZWQgPSB0aGlzLl9sb2FkZXIuaXNFeHRlbnNpb25Vc2VkKE5BTUUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBkaXNwb3NlKCkge1xyXG4gICAgICAgICh0aGlzLl9sb2FkZXIgYXMgYW55KSA9IG51bGw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGxvYWRNYXRlcmlhbFByb3BlcnRpZXNBc3luYyhjb250ZXh0OiBzdHJpbmcsIG1hdGVyaWFsOiBJTWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwpOiBOdWxsYWJsZTxQcm9taXNlPHZvaWQ+PiB7XHJcbiAgICAgICAgcmV0dXJuIEdMVEZMb2FkZXIuTG9hZEV4dHJhQXN5bmM8Ym9vbGVhbj4oY29udGV4dCwgbWF0ZXJpYWwsIHRoaXMubmFtZSwgKGV4dHJhQ29udGV4dCwgZXh0cmEpID0+IHtcclxuICAgICAgICAgICAgaWYgKGV4dHJhKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoIShiYWJ5bG9uTWF0ZXJpYWwgaW5zdGFuY2VvZiBQQlJNYXRlcmlhbCkpIHtcclxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7ZXh0cmFDb250ZXh0fTogTWF0ZXJpYWwgdHlwZSBub3Qgc3VwcG9ydGVkYCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuX2xvYWRlci5sb2FkTWF0ZXJpYWxQcm9wZXJ0aWVzQXN5bmMoY29udGV4dCwgbWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbCk7XHJcblxyXG4gICAgICAgICAgICAgICAgY29uc3QgdXNlRXhhY3RTcmdiQ29udmVyc2lvbnMgPSBiYWJ5bG9uTWF0ZXJpYWwuZ2V0U2NlbmUoKS5nZXRFbmdpbmUoKS51c2VFeGFjdFNyZ2JDb252ZXJzaW9ucztcclxuICAgICAgICAgICAgICAgIGlmICghYmFieWxvbk1hdGVyaWFsLmFsYmVkb1RleHR1cmUpIHtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuYWxiZWRvQ29sb3IudG9MaW5lYXJTcGFjZVRvUmVmKGJhYnlsb25NYXRlcmlhbC5hbGJlZG9Db2xvciwgdXNlRXhhY3RTcmdiQ29udmVyc2lvbnMpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmICghYmFieWxvbk1hdGVyaWFsLnJlZmxlY3Rpdml0eVRleHR1cmUpIHtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwucmVmbGVjdGl2aXR5Q29sb3IudG9MaW5lYXJTcGFjZVRvUmVmKGJhYnlsb25NYXRlcmlhbC5yZWZsZWN0aXZpdHlDb2xvciwgdXNlRXhhY3RTcmdiQ29udmVyc2lvbnMpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIHJldHVybiBwcm9taXNlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxufVxyXG5cclxuR0xURkxvYWRlci5SZWdpc3RlckV4dGVuc2lvbihOQU1FLCAobG9hZGVyKSA9PiBuZXcgTVNGVF9zUkdCRmFjdG9ycyhsb2FkZXIpKTtcclxuIiwiZXhwb3J0ICogZnJvbSBcIi4vRVhUX2xpZ2h0c19pbWFnZV9iYXNlZFwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9FWFRfbWVzaF9ncHVfaW5zdGFuY2luZ1wiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9FWFRfbWVzaG9wdF9jb21wcmVzc2lvblwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9FWFRfdGV4dHVyZV93ZWJwXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL0tIUl9kcmFjb19tZXNoX2NvbXByZXNzaW9uXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL0tIUl9saWdodHNfcHVuY3R1YWxcIjtcclxuZXhwb3J0ICogZnJvbSBcIi4vS0hSX21hdGVyaWFsc19wYnJTcGVjdWxhckdsb3NzaW5lc3NcIjtcclxuZXhwb3J0ICogZnJvbSBcIi4vS0hSX21hdGVyaWFsc191bmxpdFwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9LSFJfbWF0ZXJpYWxzX2NsZWFyY29hdFwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9LSFJfbWF0ZXJpYWxzX2lyaWRlc2NlbmNlXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL0tIUl9tYXRlcmlhbHNfYW5pc290cm9weVwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9LSFJfbWF0ZXJpYWxzX2VtaXNzaXZlX3N0cmVuZ3RoXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL0tIUl9tYXRlcmlhbHNfc2hlZW5cIjtcclxuZXhwb3J0ICogZnJvbSBcIi4vS0hSX21hdGVyaWFsc19zcGVjdWxhclwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9LSFJfbWF0ZXJpYWxzX2lvclwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9LSFJfbWF0ZXJpYWxzX3ZhcmlhbnRzXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL0tIUl9tYXRlcmlhbHNfdHJhbnNtaXNzaW9uXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL0tIUl9tYXRlcmlhbHNfdHJhbnNsdWNlbmN5XCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL0tIUl9tYXRlcmlhbHNfdm9sdW1lXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL0tIUl9tZXNoX3F1YW50aXphdGlvblwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9LSFJfdGV4dHVyZV9iYXNpc3VcIjtcclxuZXhwb3J0ICogZnJvbSBcIi4vS0hSX3RleHR1cmVfdHJhbnNmb3JtXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL0tIUl94bXBfanNvbl9sZFwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9LSFJfYW5pbWF0aW9uX3BvaW50ZXJcIjtcclxuZXhwb3J0ICogZnJvbSBcIi4vTVNGVF9hdWRpb19lbWl0dGVyXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL01TRlRfbG9kXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL01TRlRfbWluZWNyYWZ0TWVzaFwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9NU0ZUX3NSR0JGYWN0b3JzXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL0V4dHJhc0FzTWV0YWRhdGFcIjtcclxuIiwiaW1wb3J0IHR5cGUgeyBJbmRpY2VzQXJyYXksIE51bGxhYmxlIH0gZnJvbSBcImNvcmUvdHlwZXNcIjtcclxuaW1wb3J0IHsgRGVmZXJyZWQgfSBmcm9tIFwiY29yZS9NaXNjL2RlZmVycmVkXCI7XHJcbmltcG9ydCB7IFF1YXRlcm5pb24sIFZlY3RvcjMsIE1hdHJpeCwgVG1wVmVjdG9ycyB9IGZyb20gXCJjb3JlL01hdGhzL21hdGgudmVjdG9yXCI7XHJcbmltcG9ydCB7IENvbG9yMyB9IGZyb20gXCJjb3JlL01hdGhzL21hdGguY29sb3JcIjtcclxuaW1wb3J0IHsgVG9vbHMgfSBmcm9tIFwiY29yZS9NaXNjL3Rvb2xzXCI7XHJcbmltcG9ydCB7IENhbWVyYSB9IGZyb20gXCJjb3JlL0NhbWVyYXMvY2FtZXJhXCI7XHJcbmltcG9ydCB7IEZyZWVDYW1lcmEgfSBmcm9tIFwiY29yZS9DYW1lcmFzL2ZyZWVDYW1lcmFcIjtcclxuaW1wb3J0IHR5cGUgeyBBbmltYXRpb24gfSBmcm9tIFwiY29yZS9BbmltYXRpb25zL2FuaW1hdGlvblwiO1xyXG5pbXBvcnQgdHlwZSB7IElBbmltYXRhYmxlIH0gZnJvbSBcImNvcmUvQW5pbWF0aW9ucy9hbmltYXRhYmxlLmludGVyZmFjZVwiO1xyXG5pbXBvcnQgdHlwZSB7IElBbmltYXRpb25LZXkgfSBmcm9tIFwiY29yZS9BbmltYXRpb25zL2FuaW1hdGlvbktleVwiO1xyXG5pbXBvcnQgeyBBbmltYXRpb25LZXlJbnRlcnBvbGF0aW9uIH0gZnJvbSBcImNvcmUvQW5pbWF0aW9ucy9hbmltYXRpb25LZXlcIjtcclxuaW1wb3J0IHsgQW5pbWF0aW9uR3JvdXAgfSBmcm9tIFwiY29yZS9BbmltYXRpb25zL2FuaW1hdGlvbkdyb3VwXCI7XHJcbmltcG9ydCB7IEJvbmUgfSBmcm9tIFwiY29yZS9Cb25lcy9ib25lXCI7XHJcbmltcG9ydCB7IFNrZWxldG9uIH0gZnJvbSBcImNvcmUvQm9uZXMvc2tlbGV0b25cIjtcclxuaW1wb3J0IHsgTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvbWF0ZXJpYWxcIjtcclxuaW1wb3J0IHsgUEJSTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvUEJSL3Bick1hdGVyaWFsXCI7XHJcbmltcG9ydCB0eXBlIHsgQmFzZVRleHR1cmUgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvVGV4dHVyZXMvYmFzZVRleHR1cmVcIjtcclxuaW1wb3J0IHR5cGUgeyBJVGV4dHVyZUNyZWF0aW9uT3B0aW9ucyB9IGZyb20gXCJjb3JlL01hdGVyaWFscy9UZXh0dXJlcy90ZXh0dXJlXCI7XHJcbmltcG9ydCB7IFRleHR1cmUgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvVGV4dHVyZXMvdGV4dHVyZVwiO1xyXG5pbXBvcnQgeyBUcmFuc2Zvcm1Ob2RlIH0gZnJvbSBcImNvcmUvTWVzaGVzL3RyYW5zZm9ybU5vZGVcIjtcclxuaW1wb3J0IHsgQnVmZmVyLCBWZXJ0ZXhCdWZmZXIgfSBmcm9tIFwiY29yZS9CdWZmZXJzL2J1ZmZlclwiO1xyXG5pbXBvcnQgeyBHZW9tZXRyeSB9IGZyb20gXCJjb3JlL01lc2hlcy9nZW9tZXRyeVwiO1xyXG5pbXBvcnQgdHlwZSB7IEFic3RyYWN0TWVzaCB9IGZyb20gXCJjb3JlL01lc2hlcy9hYnN0cmFjdE1lc2hcIjtcclxuaW1wb3J0IHR5cGUgeyBJbnN0YW5jZWRNZXNoIH0gZnJvbSBcImNvcmUvTWVzaGVzL2luc3RhbmNlZE1lc2hcIjtcclxuaW1wb3J0IHsgTWVzaCB9IGZyb20gXCJjb3JlL01lc2hlcy9tZXNoXCI7XHJcbmltcG9ydCB7IE1vcnBoVGFyZ2V0IH0gZnJvbSBcImNvcmUvTW9ycGgvbW9ycGhUYXJnZXRcIjtcclxuaW1wb3J0IHsgTW9ycGhUYXJnZXRNYW5hZ2VyIH0gZnJvbSBcImNvcmUvTW9ycGgvbW9ycGhUYXJnZXRNYW5hZ2VyXCI7XHJcbmltcG9ydCB0eXBlIHsgSVNjZW5lTG9hZGVyQXN5bmNSZXN1bHQsIElTY2VuZUxvYWRlclByb2dyZXNzRXZlbnQgfSBmcm9tIFwiY29yZS9Mb2FkaW5nL3NjZW5lTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgU2NlbmUgfSBmcm9tIFwiY29yZS9zY2VuZVwiO1xyXG5pbXBvcnQgdHlwZSB7IElQcm9wZXJ0eSB9IGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuaW1wb3J0IHtcclxuICAgIEFuaW1hdGlvbkNoYW5uZWxUYXJnZXRQYXRoLFxyXG4gICAgQW5pbWF0aW9uU2FtcGxlckludGVycG9sYXRpb24sXHJcbiAgICBBY2Nlc3NvclR5cGUsXHJcbiAgICBDYW1lcmFUeXBlLFxyXG4gICAgQWNjZXNzb3JDb21wb25lbnRUeXBlLFxyXG4gICAgTWF0ZXJpYWxBbHBoYU1vZGUsXHJcbiAgICBUZXh0dXJlTWluRmlsdGVyLFxyXG4gICAgVGV4dHVyZVdyYXBNb2RlLFxyXG4gICAgVGV4dHVyZU1hZ0ZpbHRlcixcclxuICAgIE1lc2hQcmltaXRpdmVNb2RlLFxyXG59IGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuaW1wb3J0IHR5cGUge1xyXG4gICAgSUdMVEYsXHJcbiAgICBJU2FtcGxlcixcclxuICAgIElOb2RlLFxyXG4gICAgSVNjZW5lLFxyXG4gICAgSU1lc2gsXHJcbiAgICBJQWNjZXNzb3IsXHJcbiAgICBJU2tpbixcclxuICAgIElDYW1lcmEsXHJcbiAgICBJQW5pbWF0aW9uLFxyXG4gICAgSUJ1ZmZlcixcclxuICAgIElCdWZmZXJWaWV3LFxyXG4gICAgSU1hdGVyaWFsUGJyTWV0YWxsaWNSb3VnaG5lc3MsXHJcbiAgICBJTWF0ZXJpYWwsXHJcbiAgICBJVGV4dHVyZUluZm8sXHJcbiAgICBJVGV4dHVyZSxcclxuICAgIElJbWFnZSxcclxuICAgIElNZXNoUHJpbWl0aXZlLFxyXG4gICAgSUFycmF5SXRlbSxcclxuICAgIF9JU2FtcGxlckRhdGEsXHJcbiAgICBJQW5pbWF0aW9uQ2hhbm5lbCxcclxuICAgIElBbmltYXRpb25TYW1wbGVyLFxyXG4gICAgX0lBbmltYXRpb25TYW1wbGVyRGF0YSxcclxufSBmcm9tIFwiLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIH0gZnJvbSBcIi4vZ2xURkxvYWRlckV4dGVuc2lvblwiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyLCBJR0xURkxvYWRlckRhdGEgfSBmcm9tIFwiLi4vZ2xURkZpbGVMb2FkZXJcIjtcclxuaW1wb3J0IHsgR0xURkZpbGVMb2FkZXIsIEdMVEZMb2FkZXJTdGF0ZSwgR0xURkxvYWRlckNvb3JkaW5hdGVTeXN0ZW1Nb2RlLCBHTFRGTG9hZGVyQW5pbWF0aW9uU3RhcnRNb2RlIH0gZnJvbSBcIi4uL2dsVEZGaWxlTG9hZGVyXCI7XHJcbmltcG9ydCB0eXBlIHsgSURhdGFCdWZmZXIgfSBmcm9tIFwiY29yZS9NaXNjL2RhdGFSZWFkZXJcIjtcclxuaW1wb3J0IHsgRGVjb2RlQmFzZTY0VXJsVG9CaW5hcnksIElzQmFzZTY0RGF0YVVybCwgTG9hZEZpbGVFcnJvciB9IGZyb20gXCJjb3JlL01pc2MvZmlsZVRvb2xzXCI7XHJcbmltcG9ydCB7IExvZ2dlciB9IGZyb20gXCJjb3JlL01pc2MvbG9nZ2VyXCI7XHJcbmltcG9ydCB0eXBlIHsgTGlnaHQgfSBmcm9tIFwiY29yZS9MaWdodHMvbGlnaHRcIjtcclxuaW1wb3J0IHsgQm91bmRpbmdJbmZvIH0gZnJvbSBcImNvcmUvQ3VsbGluZy9ib3VuZGluZ0luZm9cIjtcclxuaW1wb3J0IHR5cGUgeyBBc3NldENvbnRhaW5lciB9IGZyb20gXCJjb3JlL2Fzc2V0Q29udGFpbmVyXCI7XHJcbmltcG9ydCB0eXBlIHsgQW5pbWF0aW9uUHJvcGVydHlJbmZvIH0gZnJvbSBcIi4vZ2xURkxvYWRlckFuaW1hdGlvblwiO1xyXG5pbXBvcnQgeyBub2RlQW5pbWF0aW9uRGF0YSB9IGZyb20gXCIuL2dsVEZMb2FkZXJBbmltYXRpb25cIjtcclxuXHJcbmludGVyZmFjZSBUeXBlZEFycmF5TGlrZSBleHRlbmRzIEFycmF5QnVmZmVyVmlldyB7XHJcbiAgICByZWFkb25seSBsZW5ndGg6IG51bWJlcjtcclxuICAgIFtuOiBudW1iZXJdOiBudW1iZXI7XHJcbn1cclxuXHJcbmludGVyZmFjZSBUeXBlZEFycmF5Q29uc3RydWN0b3Ige1xyXG4gICAgbmV3IChsZW5ndGg6IG51bWJlcik6IFR5cGVkQXJyYXlMaWtlO1xyXG4gICAgbmV3IChidWZmZXI6IEFycmF5QnVmZmVyTGlrZSwgYnl0ZU9mZnNldDogbnVtYmVyLCBsZW5ndGg/OiBudW1iZXIpOiBUeXBlZEFycmF5TGlrZTtcclxufVxyXG5cclxuaW50ZXJmYWNlIElMb2FkZXJQcm9wZXJ0eSBleHRlbmRzIElQcm9wZXJ0eSB7XHJcbiAgICBfYWN0aXZlTG9hZGVyRXh0ZW5zaW9uRnVuY3Rpb25zOiB7XHJcbiAgICAgICAgW2lkOiBzdHJpbmddOiBib29sZWFuO1xyXG4gICAgfTtcclxufVxyXG5cclxuaW50ZXJmYWNlIElSZWdpc3RlcmVkRXh0ZW5zaW9uIHtcclxuICAgIGZhY3Rvcnk6IChsb2FkZXI6IEdMVEZMb2FkZXIpID0+IElHTFRGTG9hZGVyRXh0ZW5zaW9uO1xyXG59XHJcblxyXG5pbnRlcmZhY2UgSVdpdGhNZXRhZGF0YSB7XHJcbiAgICBtZXRhZGF0YTogYW55O1xyXG4gICAgX2ludGVybmFsTWV0YWRhdGE6IGFueTtcclxufVxyXG5cclxuLy8gaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzQ4MjE4MjA5XHJcbmZ1bmN0aW9uIG1lcmdlRGVlcCguLi5vYmplY3RzOiBhbnlbXSk6IGFueSB7XHJcbiAgICBjb25zdCBpc09iamVjdCA9IChvYmo6IGFueSkgPT4gb2JqICYmIHR5cGVvZiBvYmogPT09IFwib2JqZWN0XCI7XHJcblxyXG4gICAgcmV0dXJuIG9iamVjdHMucmVkdWNlKChwcmV2LCBvYmopID0+IHtcclxuICAgICAgICBPYmplY3Qua2V5cyhvYmopLmZvckVhY2goKGtleSkgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBwVmFsID0gcHJldltrZXldO1xyXG4gICAgICAgICAgICBjb25zdCBvVmFsID0gb2JqW2tleV07XHJcblxyXG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShwVmFsKSAmJiBBcnJheS5pc0FycmF5KG9WYWwpKSB7XHJcbiAgICAgICAgICAgICAgICBwcmV2W2tleV0gPSBwVmFsLmNvbmNhdCguLi5vVmFsKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChpc09iamVjdChwVmFsKSAmJiBpc09iamVjdChvVmFsKSkge1xyXG4gICAgICAgICAgICAgICAgcHJldltrZXldID0gbWVyZ2VEZWVwKHBWYWwsIG9WYWwpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgcHJldltrZXldID0gb1ZhbDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICByZXR1cm4gcHJldjtcclxuICAgIH0sIHt9KTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEhlbHBlciBjbGFzcyBmb3Igd29ya2luZyB3aXRoIGFycmF5cyB3aGVuIGxvYWRpbmcgdGhlIGdsVEYgYXNzZXRcclxuICovXHJcbmV4cG9ydCBjbGFzcyBBcnJheUl0ZW0ge1xyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIGFuIGl0ZW0gZnJvbSB0aGUgZ2l2ZW4gYXJyYXkuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gYXJyYXkgVGhlIGFycmF5IHRvIGdldCB0aGUgaXRlbSBmcm9tXHJcbiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHRoZSBhcnJheVxyXG4gICAgICogQHJldHVybnMgVGhlIGFycmF5IGl0ZW1cclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBHZXQ8VD4oY29udGV4dDogc3RyaW5nLCBhcnJheTogQXJyYXlMaWtlPFQ+IHwgdW5kZWZpbmVkLCBpbmRleDogbnVtYmVyIHwgdW5kZWZpbmVkKTogVCB7XHJcbiAgICAgICAgaWYgKCFhcnJheSB8fCBpbmRleCA9PSB1bmRlZmluZWQgfHwgIWFycmF5W2luZGV4XSkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29udGV4dH06IEZhaWxlZCB0byBmaW5kIGluZGV4ICgke2luZGV4fSlgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBhcnJheVtpbmRleF07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBHZXRzIGFuIGl0ZW0gZnJvbSB0aGUgZ2l2ZW4gYXJyYXkgb3IgcmV0dXJucyBudWxsIGlmIG5vdCBhdmFpbGFibGUuXHJcbiAgICAgKiBAcGFyYW0gYXJyYXkgVGhlIGFycmF5IHRvIGdldCB0aGUgaXRlbSBmcm9tXHJcbiAgICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IHRvIHRoZSBhcnJheVxyXG4gICAgICogQHJldHVybnMgVGhlIGFycmF5IGl0ZW0gb3IgbnVsbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIFRyeUdldDxUPihhcnJheTogQXJyYXlMaWtlPFQ+IHwgdW5kZWZpbmVkLCBpbmRleDogbnVtYmVyIHwgdW5kZWZpbmVkKTogTnVsbGFibGU8VD4ge1xyXG4gICAgICAgIGlmICghYXJyYXkgfHwgaW5kZXggPT0gdW5kZWZpbmVkIHx8ICFhcnJheVtpbmRleF0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gYXJyYXlbaW5kZXhdO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQXNzaWduIGFuIGBpbmRleGAgZmllbGQgdG8gZWFjaCBpdGVtIG9mIHRoZSBnaXZlbiBhcnJheS5cclxuICAgICAqIEBwYXJhbSBhcnJheSBUaGUgYXJyYXkgb2YgaXRlbXNcclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBBc3NpZ24oYXJyYXk/OiBJQXJyYXlJdGVtW10pOiB2b2lkIHtcclxuICAgICAgICBpZiAoYXJyYXkpIHtcclxuICAgICAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGFycmF5Lmxlbmd0aDsgaW5kZXgrKykge1xyXG4gICAgICAgICAgICAgICAgYXJyYXlbaW5kZXhdLmluZGV4ID0gaW5kZXg7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGludGVyZmFjZSBJQW5pbWF0aW9uVGFyZ2V0SW5mbyB7XHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICB0YXJnZXQ6IGFueTtcclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwcm9wZXJ0aWVzOiBBcnJheTxBbmltYXRpb25Qcm9wZXJ0eUluZm8+O1xyXG59XHJcblxyXG4vKipcclxuICogVGhlIGdsVEYgMi4wIGxvYWRlclxyXG4gKi9cclxuZXhwb3J0IGNsYXNzIEdMVEZMb2FkZXIgaW1wbGVtZW50cyBJR0xURkxvYWRlciB7XHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgX2NvbXBsZXRlUHJvbWlzZXMgPSBuZXcgQXJyYXk8UHJvbWlzZTxhbnk+PigpO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBfYXNzZXRDb250YWluZXI6IE51bGxhYmxlPEFzc2V0Q29udGFpbmVyPiA9IG51bGw7XHJcblxyXG4gICAgLyoqIFN0b3JhZ2UgKi9cclxuICAgIHB1YmxpYyBfYmFieWxvbkxpZ2h0czogTGlnaHRbXSA9IFtdO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBfZGlzYWJsZUluc3RhbmNlZE1lc2ggPSAwO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBfYWxsTWF0ZXJpYWxzRGlydHlSZXF1aXJlZCA9IGZhbHNlO1xyXG5cclxuICAgIHByaXZhdGUgcmVhZG9ubHkgX3BhcmVudDogR0xURkZpbGVMb2FkZXI7XHJcbiAgICBwcml2YXRlIHJlYWRvbmx5IF9leHRlbnNpb25zID0gbmV3IEFycmF5PElHTFRGTG9hZGVyRXh0ZW5zaW9uPigpO1xyXG4gICAgcHJpdmF0ZSBfZGlzcG9zZWQgPSBmYWxzZTtcclxuICAgIHByaXZhdGUgX3Jvb3RVcmw6IE51bGxhYmxlPHN0cmluZz4gPSBudWxsO1xyXG4gICAgcHJpdmF0ZSBfZmlsZU5hbWU6IE51bGxhYmxlPHN0cmluZz4gPSBudWxsO1xyXG4gICAgcHJpdmF0ZSBfdW5pcXVlUm9vdFVybDogTnVsbGFibGU8c3RyaW5nPiA9IG51bGw7XHJcbiAgICBwcml2YXRlIF9nbHRmOiBJR0xURjtcclxuICAgIHByaXZhdGUgX2JpbjogTnVsbGFibGU8SURhdGFCdWZmZXI+ID0gbnVsbDtcclxuICAgIHByaXZhdGUgX2JhYnlsb25TY2VuZTogU2NlbmU7XHJcbiAgICBwcml2YXRlIF9yb290QmFieWxvbk1lc2g6IE51bGxhYmxlPE1lc2g+ID0gbnVsbDtcclxuICAgIHByaXZhdGUgX2RlZmF1bHRCYWJ5bG9uTWF0ZXJpYWxEYXRhOiB7IFtkcmF3TW9kZTogbnVtYmVyXTogTWF0ZXJpYWwgfSA9IHt9O1xyXG4gICAgcHJpdmF0ZSByZWFkb25seSBfcG9zdFNjZW5lTG9hZEFjdGlvbnMgPSBuZXcgQXJyYXk8KCkgPT4gdm9pZD4oKTtcclxuXHJcbiAgICBwcml2YXRlIHN0YXRpYyBfUmVnaXN0ZXJlZEV4dGVuc2lvbnM6IHsgW25hbWU6IHN0cmluZ106IElSZWdpc3RlcmVkRXh0ZW5zaW9uIH0gPSB7fTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBkZWZhdWx0IGdsVEYgc2FtcGxlci5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBEZWZhdWx0U2FtcGxlcjogSVNhbXBsZXIgPSB7IGluZGV4OiAtMSB9O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmVnaXN0ZXJzIGEgbG9hZGVyIGV4dGVuc2lvbi5cclxuICAgICAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBsb2FkZXIgZXh0ZW5zaW9uLlxyXG4gICAgICogQHBhcmFtIGZhY3RvcnkgVGhlIGZhY3RvcnkgZnVuY3Rpb24gdGhhdCBjcmVhdGVzIHRoZSBsb2FkZXIgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIFJlZ2lzdGVyRXh0ZW5zaW9uKG5hbWU6IHN0cmluZywgZmFjdG9yeTogKGxvYWRlcjogR0xURkxvYWRlcikgPT4gSUdMVEZMb2FkZXJFeHRlbnNpb24pOiB2b2lkIHtcclxuICAgICAgICBpZiAoR0xURkxvYWRlci5VbnJlZ2lzdGVyRXh0ZW5zaW9uKG5hbWUpKSB7XHJcbiAgICAgICAgICAgIExvZ2dlci5XYXJuKGBFeHRlbnNpb24gd2l0aCB0aGUgbmFtZSAnJHtuYW1lfScgYWxyZWFkeSBleGlzdHNgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIEdMVEZMb2FkZXIuX1JlZ2lzdGVyZWRFeHRlbnNpb25zW25hbWVdID0ge1xyXG4gICAgICAgICAgICBmYWN0b3J5OiBmYWN0b3J5LFxyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBVbnJlZ2lzdGVycyBhIGxvYWRlciBleHRlbnNpb24uXHJcbiAgICAgKiBAcGFyYW0gbmFtZSBUaGUgbmFtZSBvZiB0aGUgbG9hZGVyIGV4dGVuc2lvbi5cclxuICAgICAqIEByZXR1cm5zIEEgYm9vbGVhbiBpbmRpY2F0aW5nIHdoZXRoZXIgdGhlIGV4dGVuc2lvbiBoYXMgYmVlbiB1bnJlZ2lzdGVyZWRcclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBVbnJlZ2lzdGVyRXh0ZW5zaW9uKG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIGlmICghR0xURkxvYWRlci5fUmVnaXN0ZXJlZEV4dGVuc2lvbnNbbmFtZV0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZGVsZXRlIEdMVEZMb2FkZXIuX1JlZ2lzdGVyZWRFeHRlbnNpb25zW25hbWVdO1xyXG4gICAgICAgIHJldHVybiB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIG9iamVjdCB0aGF0IHJlcHJlc2VudHMgdGhlIGdsVEYgSlNPTi5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldCBnbHRmKCk6IElHTFRGIHtcclxuICAgICAgICBpZiAoIXRoaXMuX2dsdGYpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiZ2xURiBKU09OIGlzIG5vdCBhdmFpbGFibGVcIik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gdGhpcy5fZ2x0ZjtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBCSU4gY2h1bmsgb2YgYSBiaW5hcnkgZ2xURi5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldCBiaW4oKTogTnVsbGFibGU8SURhdGFCdWZmZXI+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fYmluO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIHBhcmVudCBmaWxlIGxvYWRlci5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldCBwYXJlbnQoKTogR0xURkZpbGVMb2FkZXIge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9wYXJlbnQ7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgQmFieWxvbiBzY2VuZSB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0LlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2V0IGJhYnlsb25TY2VuZSgpOiBTY2VuZSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLl9iYWJ5bG9uU2NlbmUpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU2NlbmUgaXMgbm90IGF2YWlsYWJsZVwiKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB0aGlzLl9iYWJ5bG9uU2NlbmU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgcm9vdCBCYWJ5bG9uIG1lc2ggd2hlbiBsb2FkaW5nIHRoZSBhc3NldC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldCByb290QmFieWxvbk1lc2goKTogTnVsbGFibGU8TWVzaD4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9yb290QmFieWxvbk1lc2g7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgY29uc3RydWN0b3IocGFyZW50OiBHTFRGRmlsZUxvYWRlcikge1xyXG4gICAgICAgIHRoaXMuX3BhcmVudCA9IHBhcmVudDtcclxuICAgIH1cclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZGlzcG9zZSgpOiB2b2lkIHtcclxuICAgICAgICBpZiAodGhpcy5fZGlzcG9zZWQpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5fZGlzcG9zZWQgPSB0cnVlO1xyXG5cclxuICAgICAgICB0aGlzLl9jb21wbGV0ZVByb21pc2VzLmxlbmd0aCA9IDA7XHJcblxyXG4gICAgICAgIHRoaXMuX2V4dGVuc2lvbnMuZm9yRWFjaCgoZXh0ZW5zaW9uKSA9PiBleHRlbnNpb24uZGlzcG9zZSAmJiBleHRlbnNpb24uZGlzcG9zZSgpKTtcclxuICAgICAgICB0aGlzLl9leHRlbnNpb25zLmxlbmd0aCA9IDA7XHJcblxyXG4gICAgICAgICh0aGlzLl9nbHRmIGFzIE51bGxhYmxlPElHTFRGPikgPSBudWxsOyAvLyBUT0RPXHJcbiAgICAgICAgdGhpcy5fYmluID0gbnVsbDtcclxuICAgICAgICAodGhpcy5fYmFieWxvblNjZW5lIGFzIE51bGxhYmxlPFNjZW5lPikgPSBudWxsOyAvLyBUT0RPXHJcbiAgICAgICAgdGhpcy5fcm9vdEJhYnlsb25NZXNoID0gbnVsbDtcclxuICAgICAgICB0aGlzLl9kZWZhdWx0QmFieWxvbk1hdGVyaWFsRGF0YSA9IHt9O1xyXG4gICAgICAgIHRoaXMuX3Bvc3RTY2VuZUxvYWRBY3Rpb25zLmxlbmd0aCA9IDA7XHJcblxyXG4gICAgICAgIHRoaXMuX3BhcmVudC5kaXNwb3NlKCk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIGltcG9ydE1lc2hBc3luYyhcclxuICAgICAgICBtZXNoZXNOYW1lczogYW55LFxyXG4gICAgICAgIHNjZW5lOiBTY2VuZSxcclxuICAgICAgICBjb250YWluZXI6IE51bGxhYmxlPEFzc2V0Q29udGFpbmVyPixcclxuICAgICAgICBkYXRhOiBJR0xURkxvYWRlckRhdGEsXHJcbiAgICAgICAgcm9vdFVybDogc3RyaW5nLFxyXG4gICAgICAgIG9uUHJvZ3Jlc3M/OiAoZXZlbnQ6IElTY2VuZUxvYWRlclByb2dyZXNzRXZlbnQpID0+IHZvaWQsXHJcbiAgICAgICAgZmlsZU5hbWUgPSBcIlwiXHJcbiAgICApOiBQcm9taXNlPElTY2VuZUxvYWRlckFzeW5jUmVzdWx0PiB7XHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLl9iYWJ5bG9uU2NlbmUgPSBzY2VuZTtcclxuICAgICAgICAgICAgdGhpcy5fYXNzZXRDb250YWluZXIgPSBjb250YWluZXI7XHJcbiAgICAgICAgICAgIHRoaXMuX2xvYWREYXRhKGRhdGEpO1xyXG5cclxuICAgICAgICAgICAgbGV0IG5vZGVzOiBOdWxsYWJsZTxBcnJheTxudW1iZXI+PiA9IG51bGw7XHJcblxyXG4gICAgICAgICAgICBpZiAobWVzaGVzTmFtZXMpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG5vZGVNYXA6IHsgW25hbWU6IHN0cmluZ106IG51bWJlciB9ID0ge307XHJcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5fZ2x0Zi5ub2Rlcykge1xyXG4gICAgICAgICAgICAgICAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiB0aGlzLl9nbHRmLm5vZGVzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChub2RlLm5hbWUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5vZGVNYXBbbm9kZS5uYW1lXSA9IG5vZGUuaW5kZXg7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgY29uc3QgbmFtZXMgPSBtZXNoZXNOYW1lcyBpbnN0YW5jZW9mIEFycmF5ID8gbWVzaGVzTmFtZXMgOiBbbWVzaGVzTmFtZXNdO1xyXG4gICAgICAgICAgICAgICAgbm9kZXMgPSBuYW1lcy5tYXAoKG5hbWUpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBub2RlID0gbm9kZU1hcFtuYW1lXTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAobm9kZSA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgRmFpbGVkIHRvIGZpbmQgbm9kZSAnJHtuYW1lfSdgKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBub2RlO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9sb2FkQXN5bmMocm9vdFVybCwgZmlsZU5hbWUsIG5vZGVzLCAoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICAgICAgICAgIG1lc2hlczogdGhpcy5fZ2V0TWVzaGVzKCksXHJcbiAgICAgICAgICAgICAgICAgICAgcGFydGljbGVTeXN0ZW1zOiBbXSxcclxuICAgICAgICAgICAgICAgICAgICBza2VsZXRvbnM6IHRoaXMuX2dldFNrZWxldG9ucygpLFxyXG4gICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbkdyb3VwczogdGhpcy5fZ2V0QW5pbWF0aW9uR3JvdXBzKCksXHJcbiAgICAgICAgICAgICAgICAgICAgbGlnaHRzOiB0aGlzLl9iYWJ5bG9uTGlnaHRzLFxyXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybU5vZGVzOiB0aGlzLl9nZXRUcmFuc2Zvcm1Ob2RlcygpLFxyXG4gICAgICAgICAgICAgICAgICAgIGdlb21ldHJpZXM6IHRoaXMuX2dldEdlb21ldHJpZXMoKSxcclxuICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkQXN5bmMoc2NlbmU6IFNjZW5lLCBkYXRhOiBJR0xURkxvYWRlckRhdGEsIHJvb3RVcmw6IHN0cmluZywgb25Qcm9ncmVzcz86IChldmVudDogSVNjZW5lTG9hZGVyUHJvZ3Jlc3NFdmVudCkgPT4gdm9pZCwgZmlsZU5hbWUgPSBcIlwiKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLl9iYWJ5bG9uU2NlbmUgPSBzY2VuZTtcclxuICAgICAgICAgICAgdGhpcy5fbG9hZERhdGEoZGF0YSk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9sb2FkQXN5bmMocm9vdFVybCwgZmlsZU5hbWUsIG51bGwsICgpID0+IHVuZGVmaW5lZCk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZEFzeW5jPFQ+KHJvb3RVcmw6IHN0cmluZywgZmlsZU5hbWU6IHN0cmluZywgbm9kZXM6IE51bGxhYmxlPEFycmF5PG51bWJlcj4+LCByZXN1bHRGdW5jOiAoKSA9PiBUKTogUHJvbWlzZTxUPiB7XHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpXHJcbiAgICAgICAgICAgIC50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX3Jvb3RVcmwgPSByb290VXJsO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fdW5pcXVlUm9vdFVybCA9ICFyb290VXJsLnN0YXJ0c1dpdGgoXCJmaWxlOlwiKSAmJiBmaWxlTmFtZSA/IHJvb3RVcmwgOiBgJHtyb290VXJsfSR7RGF0ZS5ub3coKX0vYDtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2ZpbGVOYW1lID0gZmlsZU5hbWU7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9hbGxNYXRlcmlhbHNEaXJ0eVJlcXVpcmVkID0gZmFsc2U7XHJcblxyXG4gICAgICAgICAgICAgICAgdGhpcy5fbG9hZEV4dGVuc2lvbnMoKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2NoZWNrRXh0ZW5zaW9ucygpO1xyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IGxvYWRpbmdUb1JlYWR5Q291bnRlck5hbWUgPSBgJHtHTFRGTG9hZGVyU3RhdGVbR0xURkxvYWRlclN0YXRlLkxPQURJTkddfSA9PiAke0dMVEZMb2FkZXJTdGF0ZVtHTFRGTG9hZGVyU3RhdGUuUkVBRFldfWA7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBsb2FkaW5nVG9Db21wbGV0ZUNvdW50ZXJOYW1lID0gYCR7R0xURkxvYWRlclN0YXRlW0dMVEZMb2FkZXJTdGF0ZS5MT0FESU5HXX0gPT4gJHtHTFRGTG9hZGVyU3RhdGVbR0xURkxvYWRlclN0YXRlLkNPTVBMRVRFXX1gO1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuX3BhcmVudC5fc3RhcnRQZXJmb3JtYW5jZUNvdW50ZXIobG9hZGluZ1RvUmVhZHlDb3VudGVyTmFtZSk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9wYXJlbnQuX3N0YXJ0UGVyZm9ybWFuY2VDb3VudGVyKGxvYWRpbmdUb0NvbXBsZXRlQ291bnRlck5hbWUpO1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuX3BhcmVudC5fc2V0U3RhdGUoR0xURkxvYWRlclN0YXRlLkxPQURJTkcpO1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fZXh0ZW5zaW9uc09uTG9hZGluZygpO1xyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBCbG9jayB0aGUgbWFya2luZyBvZiBtYXRlcmlhbHMgZGlydHkgdW50aWwgdGhlIHNjZW5lIGlzIGxvYWRlZC5cclxuICAgICAgICAgICAgICAgIGNvbnN0IG9sZEJsb2NrTWF0ZXJpYWxEaXJ0eU1lY2hhbmlzbSA9IHRoaXMuX2JhYnlsb25TY2VuZS5ibG9ja01hdGVyaWFsRGlydHlNZWNoYW5pc207XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9iYWJ5bG9uU2NlbmUuYmxvY2tNYXRlcmlhbERpcnR5TWVjaGFuaXNtID0gdHJ1ZTtcclxuXHJcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMucGFyZW50LmxvYWRPbmx5TWF0ZXJpYWxzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKG5vZGVzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5sb2FkU2NlbmVBc3luYyhcIi9ub2Rlc1wiLCB7IG5vZGVzOiBub2RlcywgaW5kZXg6IC0xIH0pKTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuX2dsdGYuc2NlbmUgIT0gdW5kZWZpbmVkIHx8ICh0aGlzLl9nbHRmLnNjZW5lcyAmJiB0aGlzLl9nbHRmLnNjZW5lc1swXSkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2NlbmUgPSBBcnJheUl0ZW0uR2V0KGAvc2NlbmVgLCB0aGlzLl9nbHRmLnNjZW5lcywgdGhpcy5fZ2x0Zi5zY2VuZSB8fCAwKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLmxvYWRTY2VuZUFzeW5jKGAvc2NlbmVzLyR7c2NlbmUuaW5kZXh9YCwgc2NlbmUpKTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLnBhcmVudC5za2lwTWF0ZXJpYWxzICYmIHRoaXMucGFyZW50LmxvYWRBbGxNYXRlcmlhbHMgJiYgdGhpcy5fZ2x0Zi5tYXRlcmlhbHMpIHtcclxuICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBtID0gMDsgbSA8IHRoaXMuX2dsdGYubWF0ZXJpYWxzLmxlbmd0aDsgKyttKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IG1hdGVyaWFsID0gdGhpcy5fZ2x0Zi5tYXRlcmlhbHNbbV07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGNvbnRleHQgPSBcIi9tYXRlcmlhbHMvXCIgKyBtO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBiYWJ5bG9uRHJhd01vZGUgPSBNYXRlcmlhbC5UcmlhbmdsZUZpbGxNb2RlO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkTWF0ZXJpYWxBc3luYyhjb250ZXh0LCBtYXRlcmlhbCwgbnVsbCwgYmFieWxvbkRyYXdNb2RlLCAoKSA9PiB7fSkpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAvLyBSZXN0b3JlIHRoZSBibG9ja2luZyBvZiBtYXRlcmlhbCBkaXJ0eS5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9hbGxNYXRlcmlhbHNEaXJ0eVJlcXVpcmVkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBjYW4gaGFwcGVuIGlmIHdlIGFkZCBhIGxpZ2h0IGZvciBpbnN0YW5jZSBhcyBpdCB3aWxsIGltcGFjdCB0aGUgd2hvbGUgc2NlbmUuXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhpcyBhdXRvbWF0aWNhbGx5IHJlc2V0cyBldmVyeXRoaW5nIGlmIG5lZWRlZC5cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9iYWJ5bG9uU2NlbmUuYmxvY2tNYXRlcmlhbERpcnR5TWVjaGFuaXNtID0gb2xkQmxvY2tNYXRlcmlhbERpcnR5TWVjaGFuaXNtO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAvLyBCeSBkZWZhdWx0IGEgbmV3bHkgY3JlYXRlZCBtYXRlcmlhbCBpcyBkaXJ0eSBzbyB0aGVyZSBpcyBubyBuZWVkIHRvIGZsYWcgdGhlIGZ1bGwgc2NlbmUgYXMgZGlydHkuXHJcbiAgICAgICAgICAgICAgICAgICAgLy8gRm9yIHBlcmYgcmVhc29ucywgd2UgdGhlbiBieXBhc3MgYmxvY2tNYXRlcmlhbERpcnR5TWVjaGFuaXNtIGFzIHRoaXMgd291bGQgXCJkaXJ0eVwiIHRoZSBlbnRpcmUgc2NlbmUuXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fYmFieWxvblNjZW5lLl9mb3JjZUJsb2NrTWF0ZXJpYWxEaXJ0eU1lY2hhbmlzbShvbGRCbG9ja01hdGVyaWFsRGlydHlNZWNoYW5pc20pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9wYXJlbnQuY29tcGlsZU1hdGVyaWFscykge1xyXG4gICAgICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fY29tcGlsZU1hdGVyaWFsc0FzeW5jKCkpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0aGlzLl9wYXJlbnQuY29tcGlsZVNoYWRvd0dlbmVyYXRvcnMpIHtcclxuICAgICAgICAgICAgICAgICAgICBwcm9taXNlcy5wdXNoKHRoaXMuX2NvbXBpbGVTaGFkb3dHZW5lcmF0b3JzQXN5bmMoKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0UHJvbWlzZSA9IFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fcm9vdEJhYnlsb25NZXNoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3Jvb3RCYWJ5bG9uTWVzaC5zZXRFbmFibGVkKHRydWUpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZXh0ZW5zaW9uc09uUmVhZHkoKTtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9wYXJlbnQuX3NldFN0YXRlKEdMVEZMb2FkZXJTdGF0ZS5SRUFEWSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3N0YXJ0QW5pbWF0aW9ucygpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0RnVuYygpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdFByb21pc2UudGhlbigocmVzdWx0KSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGFyZW50Ll9lbmRQZXJmb3JtYW5jZUNvdW50ZXIobG9hZGluZ1RvUmVhZHlDb3VudGVyTmFtZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIFRvb2xzLlNldEltbWVkaWF0ZSgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5fZGlzcG9zZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFByb21pc2UuYWxsKHRoaXMuX2NvbXBsZXRlUHJvbWlzZXMpLnRoZW4oXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wYXJlbnQuX2VuZFBlcmZvcm1hbmNlQ291bnRlcihsb2FkaW5nVG9Db21wbGV0ZUNvdW50ZXJOYW1lKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3BhcmVudC5fc2V0U3RhdGUoR0xURkxvYWRlclN0YXRlLkNPTVBMRVRFKTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3BhcmVudC5vbkNvbXBsZXRlT2JzZXJ2YWJsZS5ub3RpZnlPYnNlcnZlcnModW5kZWZpbmVkKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGFyZW50Lm9uQ29tcGxldGVPYnNlcnZhYmxlLmNsZWFyKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc3Bvc2UoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChlcnJvcikgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9wYXJlbnQub25FcnJvck9ic2VydmFibGUubm90aWZ5T2JzZXJ2ZXJzKGVycm9yKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGFyZW50Lm9uRXJyb3JPYnNlcnZhYmxlLmNsZWFyKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc3Bvc2UoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgLmNhdGNoKChlcnJvcikgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKCF0aGlzLl9kaXNwb3NlZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3BhcmVudC5vbkVycm9yT2JzZXJ2YWJsZS5ub3RpZnlPYnNlcnZlcnMoZXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3BhcmVudC5vbkVycm9yT2JzZXJ2YWJsZS5jbGVhcigpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmRpc3Bvc2UoKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZERhdGEoZGF0YTogSUdMVEZMb2FkZXJEYXRhKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5fZ2x0ZiA9IGRhdGEuanNvbiBhcyBJR0xURjtcclxuICAgICAgICB0aGlzLl9zZXR1cERhdGEoKTtcclxuXHJcbiAgICAgICAgaWYgKGRhdGEuYmluKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlcnMgPSB0aGlzLl9nbHRmLmJ1ZmZlcnM7XHJcbiAgICAgICAgICAgIGlmIChidWZmZXJzICYmIGJ1ZmZlcnNbMF0gJiYgIWJ1ZmZlcnNbMF0udXJpKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBiaW5hcnlCdWZmZXIgPSBidWZmZXJzWzBdO1xyXG4gICAgICAgICAgICAgICAgaWYgKGJpbmFyeUJ1ZmZlci5ieXRlTGVuZ3RoIDwgZGF0YS5iaW4uYnl0ZUxlbmd0aCAtIDMgfHwgYmluYXJ5QnVmZmVyLmJ5dGVMZW5ndGggPiBkYXRhLmJpbi5ieXRlTGVuZ3RoKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLldhcm4oYEJpbmFyeSBidWZmZXIgbGVuZ3RoICgke2JpbmFyeUJ1ZmZlci5ieXRlTGVuZ3RofSkgZnJvbSBKU09OIGRvZXMgbm90IG1hdGNoIGNodW5rIGxlbmd0aCAoJHtkYXRhLmJpbi5ieXRlTGVuZ3RofSlgKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9iaW4gPSBkYXRhLmJpbjtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIExvZ2dlci5XYXJuKFwiVW5leHBlY3RlZCBCSU4gY2h1bmtcIik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfc2V0dXBEYXRhKCk6IHZvaWQge1xyXG4gICAgICAgIEFycmF5SXRlbS5Bc3NpZ24odGhpcy5fZ2x0Zi5hY2Nlc3NvcnMpO1xyXG4gICAgICAgIEFycmF5SXRlbS5Bc3NpZ24odGhpcy5fZ2x0Zi5hbmltYXRpb25zKTtcclxuICAgICAgICBBcnJheUl0ZW0uQXNzaWduKHRoaXMuX2dsdGYuYnVmZmVycyk7XHJcbiAgICAgICAgQXJyYXlJdGVtLkFzc2lnbih0aGlzLl9nbHRmLmJ1ZmZlclZpZXdzKTtcclxuICAgICAgICBBcnJheUl0ZW0uQXNzaWduKHRoaXMuX2dsdGYuY2FtZXJhcyk7XHJcbiAgICAgICAgQXJyYXlJdGVtLkFzc2lnbih0aGlzLl9nbHRmLmltYWdlcyk7XHJcbiAgICAgICAgQXJyYXlJdGVtLkFzc2lnbih0aGlzLl9nbHRmLm1hdGVyaWFscyk7XHJcbiAgICAgICAgQXJyYXlJdGVtLkFzc2lnbih0aGlzLl9nbHRmLm1lc2hlcyk7XHJcbiAgICAgICAgQXJyYXlJdGVtLkFzc2lnbih0aGlzLl9nbHRmLm5vZGVzKTtcclxuICAgICAgICBBcnJheUl0ZW0uQXNzaWduKHRoaXMuX2dsdGYuc2FtcGxlcnMpO1xyXG4gICAgICAgIEFycmF5SXRlbS5Bc3NpZ24odGhpcy5fZ2x0Zi5zY2VuZXMpO1xyXG4gICAgICAgIEFycmF5SXRlbS5Bc3NpZ24odGhpcy5fZ2x0Zi5za2lucyk7XHJcbiAgICAgICAgQXJyYXlJdGVtLkFzc2lnbih0aGlzLl9nbHRmLnRleHR1cmVzKTtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuX2dsdGYubm9kZXMpIHtcclxuICAgICAgICAgICAgY29uc3Qgbm9kZVBhcmVudHM6IHsgW2luZGV4OiBudW1iZXJdOiBudW1iZXIgfSA9IHt9O1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IG5vZGUgb2YgdGhpcy5fZ2x0Zi5ub2Rlcykge1xyXG4gICAgICAgICAgICAgICAgaWYgKG5vZGUuY2hpbGRyZW4pIHtcclxuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGluZGV4IG9mIG5vZGUuY2hpbGRyZW4pIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgbm9kZVBhcmVudHNbaW5kZXhdID0gbm9kZS5pbmRleDtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHJvb3ROb2RlID0gdGhpcy5fY3JlYXRlUm9vdE5vZGUoKTtcclxuICAgICAgICAgICAgZm9yIChjb25zdCBub2RlIG9mIHRoaXMuX2dsdGYubm9kZXMpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHBhcmVudEluZGV4ID0gbm9kZVBhcmVudHNbbm9kZS5pbmRleF07XHJcbiAgICAgICAgICAgICAgICBub2RlLnBhcmVudCA9IHBhcmVudEluZGV4ID09PSB1bmRlZmluZWQgPyByb290Tm9kZSA6IHRoaXMuX2dsdGYubm9kZXNbcGFyZW50SW5kZXhdO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2xvYWRFeHRlbnNpb25zKCk6IHZvaWQge1xyXG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBpbiBHTFRGTG9hZGVyLl9SZWdpc3RlcmVkRXh0ZW5zaW9ucykge1xyXG4gICAgICAgICAgICBjb25zdCBleHRlbnNpb24gPSBHTFRGTG9hZGVyLl9SZWdpc3RlcmVkRXh0ZW5zaW9uc1tuYW1lXS5mYWN0b3J5KHRoaXMpO1xyXG4gICAgICAgICAgICBpZiAoZXh0ZW5zaW9uLm5hbWUgIT09IG5hbWUpIHtcclxuICAgICAgICAgICAgICAgIExvZ2dlci5XYXJuKGBUaGUgbmFtZSBvZiB0aGUgZ2xURiBsb2FkZXIgZXh0ZW5zaW9uIGluc3RhbmNlIGRvZXMgbm90IG1hdGNoIHRoZSByZWdpc3RlcmVkIG5hbWU6ICR7ZXh0ZW5zaW9uLm5hbWV9ICE9PSAke25hbWV9YCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHRoaXMuX2V4dGVuc2lvbnMucHVzaChleHRlbnNpb24pO1xyXG4gICAgICAgICAgICB0aGlzLl9wYXJlbnQub25FeHRlbnNpb25Mb2FkZWRPYnNlcnZhYmxlLm5vdGlmeU9ic2VydmVycyhleHRlbnNpb24pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5fZXh0ZW5zaW9ucy5zb3J0KChhLCBiKSA9PiAoYS5vcmRlciB8fCBOdW1iZXIuTUFYX1ZBTFVFKSAtIChiLm9yZGVyIHx8IE51bWJlci5NQVhfVkFMVUUpKTtcclxuICAgICAgICB0aGlzLl9wYXJlbnQub25FeHRlbnNpb25Mb2FkZWRPYnNlcnZhYmxlLmNsZWFyKCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfY2hlY2tFeHRlbnNpb25zKCk6IHZvaWQge1xyXG4gICAgICAgIGlmICh0aGlzLl9nbHRmLmV4dGVuc2lvbnNSZXF1aXJlZCkge1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IG5hbWUgb2YgdGhpcy5fZ2x0Zi5leHRlbnNpb25zUmVxdWlyZWQpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGF2YWlsYWJsZSA9IHRoaXMuX2V4dGVuc2lvbnMuc29tZSgoZXh0ZW5zaW9uKSA9PiBleHRlbnNpb24ubmFtZSA9PT0gbmFtZSAmJiBleHRlbnNpb24uZW5hYmxlZCk7XHJcbiAgICAgICAgICAgICAgICBpZiAoIWF2YWlsYWJsZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgUmVxdWlyZSBleHRlbnNpb24gJHtuYW1lfSBpcyBub3QgYXZhaWxhYmxlYCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfY3JlYXRlUm9vdE5vZGUoKTogSU5vZGUge1xyXG4gICAgICAgIHRoaXMuX2JhYnlsb25TY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gISF0aGlzLl9hc3NldENvbnRhaW5lcjtcclxuICAgICAgICB0aGlzLl9yb290QmFieWxvbk1lc2ggPSBuZXcgTWVzaChcIl9fcm9vdF9fXCIsIHRoaXMuX2JhYnlsb25TY2VuZSk7XHJcbiAgICAgICAgdGhpcy5fcm9vdEJhYnlsb25NZXNoLl9wYXJlbnRDb250YWluZXIgPSB0aGlzLl9hc3NldENvbnRhaW5lcjtcclxuICAgICAgICB0aGlzLl9iYWJ5bG9uU2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9IGZhbHNlO1xyXG4gICAgICAgIHRoaXMuX3Jvb3RCYWJ5bG9uTWVzaC5zZXRFbmFibGVkKGZhbHNlKTtcclxuXHJcbiAgICAgICAgY29uc3Qgcm9vdE5vZGU6IElOb2RlID0ge1xyXG4gICAgICAgICAgICBfYmFieWxvblRyYW5zZm9ybU5vZGU6IHRoaXMuX3Jvb3RCYWJ5bG9uTWVzaCxcclxuICAgICAgICAgICAgaW5kZXg6IC0xLFxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHN3aXRjaCAodGhpcy5fcGFyZW50LmNvb3JkaW5hdGVTeXN0ZW1Nb2RlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgR0xURkxvYWRlckNvb3JkaW5hdGVTeXN0ZW1Nb2RlLkFVVE86IHtcclxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5fYmFieWxvblNjZW5lLnVzZVJpZ2h0SGFuZGVkU3lzdGVtKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUucm90YXRpb24gPSBbMCwgMSwgMCwgMF07XHJcbiAgICAgICAgICAgICAgICAgICAgcm9vdE5vZGUuc2NhbGUgPSBbMSwgMSwgLTFdO1xyXG4gICAgICAgICAgICAgICAgICAgIEdMVEZMb2FkZXIuX0xvYWRUcmFuc2Zvcm0ocm9vdE5vZGUsIHRoaXMuX3Jvb3RCYWJ5bG9uTWVzaCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjYXNlIEdMVEZMb2FkZXJDb29yZGluYXRlU3lzdGVtTW9kZS5GT1JDRV9SSUdIVF9IQU5ERUQ6IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2JhYnlsb25TY2VuZS51c2VSaWdodEhhbmRlZFN5c3RlbSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBkZWZhdWx0OiB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYEludmFsaWQgY29vcmRpbmF0ZSBzeXN0ZW0gbW9kZSAoJHt0aGlzLl9wYXJlbnQuY29vcmRpbmF0ZVN5c3RlbU1vZGV9KWApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLl9wYXJlbnQub25NZXNoTG9hZGVkT2JzZXJ2YWJsZS5ub3RpZnlPYnNlcnZlcnModGhpcy5fcm9vdEJhYnlsb25NZXNoKTtcclxuICAgICAgICByZXR1cm4gcm9vdE5vZGU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBMb2FkcyBhIGdsVEYgc2NlbmUuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gc2NlbmUgVGhlIGdsVEYgc2NlbmUgcHJvcGVydHlcclxuICAgICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGxvYWQgaXMgY29tcGxldGVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRTY2VuZUFzeW5jKGNvbnRleHQ6IHN0cmluZywgc2NlbmU6IElTY2VuZSk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGNvbnN0IGV4dGVuc2lvblByb21pc2UgPSB0aGlzLl9leHRlbnNpb25zTG9hZFNjZW5lQXN5bmMoY29udGV4dCwgc2NlbmUpO1xyXG4gICAgICAgIGlmIChleHRlbnNpb25Qcm9taXNlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBleHRlbnNpb25Qcm9taXNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBuZXcgQXJyYXk8UHJvbWlzZTxhbnk+PigpO1xyXG5cclxuICAgICAgICB0aGlzLmxvZ09wZW4oYCR7Y29udGV4dH0gJHtzY2VuZS5uYW1lIHx8IFwiXCJ9YCk7XHJcblxyXG4gICAgICAgIGlmIChzY2VuZS5ub2Rlcykge1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IGluZGV4IG9mIHNjZW5lLm5vZGVzKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBub2RlID0gQXJyYXlJdGVtLkdldChgJHtjb250ZXh0fS9ub2Rlcy8ke2luZGV4fWAsIHRoaXMuX2dsdGYubm9kZXMsIGluZGV4KTtcclxuICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkTm9kZUFzeW5jKGAvbm9kZXMvJHtub2RlLmluZGV4fWAsIG5vZGUsIChiYWJ5bG9uTWVzaCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWVzaC5wYXJlbnQgPSB0aGlzLl9yb290QmFieWxvbk1lc2g7XHJcbiAgICAgICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGZvciAoY29uc3QgYWN0aW9uIG9mIHRoaXMuX3Bvc3RTY2VuZUxvYWRBY3Rpb25zKSB7XHJcbiAgICAgICAgICAgIGFjdGlvbigpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkQW5pbWF0aW9uc0FzeW5jKCkpO1xyXG5cclxuICAgICAgICB0aGlzLmxvZ0Nsb3NlKCk7XHJcblxyXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7fSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfZm9yRWFjaFByaW1pdGl2ZShub2RlOiBJTm9kZSwgY2FsbGJhY2s6IChiYWJ5bG9uTWVzaDogQWJzdHJhY3RNZXNoKSA9PiB2b2lkKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKG5vZGUuX3ByaW1pdGl2ZUJhYnlsb25NZXNoZXMpIHtcclxuICAgICAgICAgICAgZm9yIChjb25zdCBiYWJ5bG9uTWVzaCBvZiBub2RlLl9wcmltaXRpdmVCYWJ5bG9uTWVzaGVzKSB7XHJcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhiYWJ5bG9uTWVzaCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfZ2V0R2VvbWV0cmllcygpOiBHZW9tZXRyeVtdIHtcclxuICAgICAgICBjb25zdCBnZW9tZXRyaWVzID0gbmV3IEFycmF5PEdlb21ldHJ5PigpO1xyXG5cclxuICAgICAgICBjb25zdCBub2RlcyA9IHRoaXMuX2dsdGYubm9kZXM7XHJcbiAgICAgICAgaWYgKG5vZGVzKSB7XHJcbiAgICAgICAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBub2Rlcykge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fZm9yRWFjaFByaW1pdGl2ZShub2RlLCAoYmFieWxvbk1lc2gpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBnZW9tZXRyeSA9IChiYWJ5bG9uTWVzaCBhcyBNZXNoKS5nZW9tZXRyeTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoZ2VvbWV0cnkgJiYgZ2VvbWV0cmllcy5pbmRleE9mKGdlb21ldHJ5KSA9PT0gLTEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZ2VvbWV0cmllcy5wdXNoKGdlb21ldHJ5KTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGdlb21ldHJpZXM7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfZ2V0TWVzaGVzKCk6IEFic3RyYWN0TWVzaFtdIHtcclxuICAgICAgICBjb25zdCBtZXNoZXMgPSBuZXcgQXJyYXk8QWJzdHJhY3RNZXNoPigpO1xyXG5cclxuICAgICAgICAvLyBSb290IG1lc2ggaXMgYWx3YXlzIGZpcnN0LCBpZiBhdmFpbGFibGUuXHJcbiAgICAgICAgaWYgKHRoaXMuX3Jvb3RCYWJ5bG9uTWVzaCkge1xyXG4gICAgICAgICAgICBtZXNoZXMucHVzaCh0aGlzLl9yb290QmFieWxvbk1lc2gpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3Qgbm9kZXMgPSB0aGlzLl9nbHRmLm5vZGVzO1xyXG4gICAgICAgIGlmIChub2Rlcykge1xyXG4gICAgICAgICAgICBmb3IgKGNvbnN0IG5vZGUgb2Ygbm9kZXMpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2ZvckVhY2hQcmltaXRpdmUobm9kZSwgKGJhYnlsb25NZXNoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgbWVzaGVzLnB1c2goYmFieWxvbk1lc2gpO1xyXG4gICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBtZXNoZXM7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfZ2V0VHJhbnNmb3JtTm9kZXMoKTogVHJhbnNmb3JtTm9kZVtdIHtcclxuICAgICAgICBjb25zdCB0cmFuc2Zvcm1Ob2RlcyA9IG5ldyBBcnJheTxUcmFuc2Zvcm1Ob2RlPigpO1xyXG5cclxuICAgICAgICBjb25zdCBub2RlcyA9IHRoaXMuX2dsdGYubm9kZXM7XHJcbiAgICAgICAgaWYgKG5vZGVzKSB7XHJcbiAgICAgICAgICAgIGZvciAoY29uc3Qgbm9kZSBvZiBub2Rlcykge1xyXG4gICAgICAgICAgICAgICAgaWYgKG5vZGUuX2JhYnlsb25UcmFuc2Zvcm1Ob2RlICYmIG5vZGUuX2JhYnlsb25UcmFuc2Zvcm1Ob2RlLmdldENsYXNzTmFtZSgpID09PSBcIlRyYW5zZm9ybU5vZGVcIikge1xyXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybU5vZGVzLnB1c2gobm9kZS5fYmFieWxvblRyYW5zZm9ybU5vZGUpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgaWYgKG5vZGUuX2JhYnlsb25UcmFuc2Zvcm1Ob2RlRm9yU2tpbikge1xyXG4gICAgICAgICAgICAgICAgICAgIHRyYW5zZm9ybU5vZGVzLnB1c2gobm9kZS5fYmFieWxvblRyYW5zZm9ybU5vZGVGb3JTa2luKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHRyYW5zZm9ybU5vZGVzO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2dldFNrZWxldG9ucygpOiBTa2VsZXRvbltdIHtcclxuICAgICAgICBjb25zdCBza2VsZXRvbnMgPSBuZXcgQXJyYXk8U2tlbGV0b24+KCk7XHJcblxyXG4gICAgICAgIGNvbnN0IHNraW5zID0gdGhpcy5fZ2x0Zi5za2lucztcclxuICAgICAgICBpZiAoc2tpbnMpIHtcclxuICAgICAgICAgICAgZm9yIChjb25zdCBza2luIG9mIHNraW5zKSB7XHJcbiAgICAgICAgICAgICAgICBpZiAoc2tpbi5fZGF0YSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHNrZWxldG9ucy5wdXNoKHNraW4uX2RhdGEuYmFieWxvblNrZWxldG9uKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHNrZWxldG9ucztcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9nZXRBbmltYXRpb25Hcm91cHMoKTogQW5pbWF0aW9uR3JvdXBbXSB7XHJcbiAgICAgICAgY29uc3QgYW5pbWF0aW9uR3JvdXBzID0gbmV3IEFycmF5PEFuaW1hdGlvbkdyb3VwPigpO1xyXG5cclxuICAgICAgICBjb25zdCBhbmltYXRpb25zID0gdGhpcy5fZ2x0Zi5hbmltYXRpb25zO1xyXG4gICAgICAgIGlmIChhbmltYXRpb25zKSB7XHJcbiAgICAgICAgICAgIGZvciAoY29uc3QgYW5pbWF0aW9uIG9mIGFuaW1hdGlvbnMpIHtcclxuICAgICAgICAgICAgICAgIGlmIChhbmltYXRpb24uX2JhYnlsb25BbmltYXRpb25Hcm91cCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGFuaW1hdGlvbkdyb3Vwcy5wdXNoKGFuaW1hdGlvbi5fYmFieWxvbkFuaW1hdGlvbkdyb3VwKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGFuaW1hdGlvbkdyb3VwcztcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9zdGFydEFuaW1hdGlvbnMoKTogdm9pZCB7XHJcbiAgICAgICAgc3dpdGNoICh0aGlzLl9wYXJlbnQuYW5pbWF0aW9uU3RhcnRNb2RlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgR0xURkxvYWRlckFuaW1hdGlvblN0YXJ0TW9kZS5OT05FOiB7XHJcbiAgICAgICAgICAgICAgICAvLyBkbyBub3RoaW5nXHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjYXNlIEdMVEZMb2FkZXJBbmltYXRpb25TdGFydE1vZGUuRklSU1Q6IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGJhYnlsb25BbmltYXRpb25Hcm91cHMgPSB0aGlzLl9nZXRBbmltYXRpb25Hcm91cHMoKTtcclxuICAgICAgICAgICAgICAgIGlmIChiYWJ5bG9uQW5pbWF0aW9uR3JvdXBzLmxlbmd0aCAhPT0gMCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25BbmltYXRpb25Hcm91cHNbMF0uc3RhcnQodHJ1ZSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjYXNlIEdMVEZMb2FkZXJBbmltYXRpb25TdGFydE1vZGUuQUxMOiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBiYWJ5bG9uQW5pbWF0aW9uR3JvdXBzID0gdGhpcy5fZ2V0QW5pbWF0aW9uR3JvdXBzKCk7XHJcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGJhYnlsb25BbmltYXRpb25Hcm91cCBvZiBiYWJ5bG9uQW5pbWF0aW9uR3JvdXBzKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYmFieWxvbkFuaW1hdGlvbkdyb3VwLnN0YXJ0KHRydWUpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgZGVmYXVsdDoge1xyXG4gICAgICAgICAgICAgICAgTG9nZ2VyLkVycm9yKGBJbnZhbGlkIGFuaW1hdGlvbiBzdGFydCBtb2RlICgke3RoaXMuX3BhcmVudC5hbmltYXRpb25TdGFydE1vZGV9KWApO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTG9hZHMgYSBnbFRGIG5vZGUuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gbm9kZSBUaGUgZ2xURiBub2RlIHByb3BlcnR5XHJcbiAgICAgKiBAcGFyYW0gYXNzaWduIEEgZnVuY3Rpb24gY2FsbGVkIHN5bmNocm9ub3VzbHkgYWZ0ZXIgcGFyc2luZyB0aGUgZ2xURiBwcm9wZXJ0aWVzXHJcbiAgICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBsb2FkZWQgQmFieWxvbiBtZXNoIHdoZW4gdGhlIGxvYWQgaXMgY29tcGxldGVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWROb2RlQXN5bmMoY29udGV4dDogc3RyaW5nLCBub2RlOiBJTm9kZSwgYXNzaWduOiAoYmFieWxvblRyYW5zZm9ybU5vZGU6IFRyYW5zZm9ybU5vZGUpID0+IHZvaWQgPSAoKSA9PiB7fSk6IFByb21pc2U8VHJhbnNmb3JtTm9kZT4ge1xyXG4gICAgICAgIGNvbnN0IGV4dGVuc2lvblByb21pc2UgPSB0aGlzLl9leHRlbnNpb25zTG9hZE5vZGVBc3luYyhjb250ZXh0LCBub2RlLCBhc3NpZ24pO1xyXG4gICAgICAgIGlmIChleHRlbnNpb25Qcm9taXNlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBleHRlbnNpb25Qcm9taXNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKG5vZGUuX2JhYnlsb25UcmFuc2Zvcm1Ob2RlKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fTogSW52YWxpZCByZWN1cnNpdmUgbm9kZSBoaWVyYXJjaHlgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuXHJcbiAgICAgICAgdGhpcy5sb2dPcGVuKGAke2NvbnRleHR9ICR7bm9kZS5uYW1lIHx8IFwiXCJ9YCk7XHJcblxyXG4gICAgICAgIGNvbnN0IGxvYWROb2RlID0gKGJhYnlsb25UcmFuc2Zvcm1Ob2RlOiBUcmFuc2Zvcm1Ob2RlKSA9PiB7XHJcbiAgICAgICAgICAgIEdMVEZMb2FkZXIuQWRkUG9pbnRlck1ldGFkYXRhKGJhYnlsb25UcmFuc2Zvcm1Ob2RlLCBjb250ZXh0KTtcclxuICAgICAgICAgICAgR0xURkxvYWRlci5fTG9hZFRyYW5zZm9ybShub2RlLCBiYWJ5bG9uVHJhbnNmb3JtTm9kZSk7XHJcblxyXG4gICAgICAgICAgICBpZiAobm9kZS5jYW1lcmEgIT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBjYW1lcmEgPSBBcnJheUl0ZW0uR2V0KGAke2NvbnRleHR9L2NhbWVyYWAsIHRoaXMuX2dsdGYuY2FtZXJhcywgbm9kZS5jYW1lcmEpO1xyXG4gICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaChcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRDYW1lcmFBc3luYyhgL2NhbWVyYXMvJHtjYW1lcmEuaW5kZXh9YCwgY2FtZXJhLCAoYmFieWxvbkNhbWVyYSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uQ2FtZXJhLnBhcmVudCA9IGJhYnlsb25UcmFuc2Zvcm1Ob2RlO1xyXG4gICAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAobm9kZS5jaGlsZHJlbikge1xyXG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBpbmRleCBvZiBub2RlLmNoaWxkcmVuKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgY2hpbGROb2RlID0gQXJyYXlJdGVtLkdldChgJHtjb250ZXh0fS9jaGlsZHJlbi8ke2luZGV4fWAsIHRoaXMuX2dsdGYubm9kZXMsIGluZGV4KTtcclxuICAgICAgICAgICAgICAgICAgICBwcm9taXNlcy5wdXNoKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWROb2RlQXN5bmMoYC9ub2Rlcy8ke2NoaWxkTm9kZS5pbmRleH1gLCBjaGlsZE5vZGUsIChjaGlsZEJhYnlsb25NZXNoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGlsZEJhYnlsb25NZXNoLnBhcmVudCA9IGJhYnlsb25UcmFuc2Zvcm1Ob2RlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGFzc2lnbihiYWJ5bG9uVHJhbnNmb3JtTm9kZSk7XHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgaWYgKG5vZGUubWVzaCA9PSB1bmRlZmluZWQgfHwgbm9kZS5za2luICE9IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICBjb25zdCBub2RlTmFtZSA9IG5vZGUubmFtZSB8fCBgbm9kZSR7bm9kZS5pbmRleH1gO1xyXG4gICAgICAgICAgICB0aGlzLl9iYWJ5bG9uU2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9ICEhdGhpcy5fYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgICAgIGNvbnN0IHRyYW5zZm9ybU5vZGUgPSBuZXcgVHJhbnNmb3JtTm9kZShub2RlTmFtZSwgdGhpcy5fYmFieWxvblNjZW5lKTtcclxuICAgICAgICAgICAgdHJhbnNmb3JtTm9kZS5fcGFyZW50Q29udGFpbmVyID0gdGhpcy5fYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgICAgIHRoaXMuX2JhYnlsb25TY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gZmFsc2U7XHJcbiAgICAgICAgICAgIGlmIChub2RlLm1lc2ggPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICBub2RlLl9iYWJ5bG9uVHJhbnNmb3JtTm9kZSA9IHRyYW5zZm9ybU5vZGU7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBub2RlLl9iYWJ5bG9uVHJhbnNmb3JtTm9kZUZvclNraW4gPSB0cmFuc2Zvcm1Ob2RlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGxvYWROb2RlKHRyYW5zZm9ybU5vZGUpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKG5vZGUubWVzaCAhPSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgaWYgKG5vZGUuc2tpbiA9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG1lc2ggPSBBcnJheUl0ZW0uR2V0KGAke2NvbnRleHR9L21lc2hgLCB0aGlzLl9nbHRmLm1lc2hlcywgbm9kZS5tZXNoKTtcclxuICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fbG9hZE1lc2hBc3luYyhgL21lc2hlcy8ke21lc2guaW5kZXh9YCwgbm9kZSwgbWVzaCwgbG9hZE5vZGUpKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vS2hyb25vc0dyb3VwL2dsVEYvdHJlZS9tYXN0ZXIvc3BlY2lmaWNhdGlvbi8yLjAjc2tpbnMgKHNlY29uZCBpbXBsZW1lbnRhdGlvbiBub3RlKVxyXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBjb2RlIHBhdGggd2lsbCBwbGFjZSB0aGUgc2tpbm5lZCBtZXNoIGFzIGEgc2libGluZyBvZiB0aGUgc2tlbGV0b24gcm9vdCBub2RlIHdpdGhvdXQgbG9hZGluZyB0aGVcclxuICAgICAgICAgICAgICAgIC8vIHRyYW5zZm9ybSwgd2hpY2ggZWZmZWN0aXZlbHkgaWdub3JlcyB0aGUgdHJhbnNmb3JtIG9mIHRoZSBza2lubmVkIG1lc2gsIGFzIHBlciBzcGVjLlxyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IG1lc2ggPSBBcnJheUl0ZW0uR2V0KGAke2NvbnRleHR9L21lc2hgLCB0aGlzLl9nbHRmLm1lc2hlcywgbm9kZS5tZXNoKTtcclxuICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fbG9hZE1lc2hBc3luYyhgL21lc2hlcy8ke21lc2guaW5kZXh9YCwgbm9kZSwgbWVzaCwgKGJhYnlsb25UcmFuc2Zvcm1Ob2RlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJhYnlsb25UcmFuc2Zvcm1Ob2RlRm9yU2tpbiA9IG5vZGUuX2JhYnlsb25UcmFuc2Zvcm1Ob2RlRm9yU2tpbiE7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBNZXJnZSB0aGUgbWV0YWRhdGEgZnJvbSB0aGUgc2tpbiBub2RlIHRvIHRoZSBza2lubmVkIG1lc2ggaW4gY2FzZSBhIGxvYWRlciBleHRlbnNpb24gYWRkZWQgbWV0YWRhdGEuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhYnlsb25UcmFuc2Zvcm1Ob2RlLm1ldGFkYXRhID0gbWVyZ2VEZWVwKGJhYnlsb25UcmFuc2Zvcm1Ob2RlRm9yU2tpbi5tZXRhZGF0YSwgYmFieWxvblRyYW5zZm9ybU5vZGUubWV0YWRhdGEgfHwge30pO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc2tpbiA9IEFycmF5SXRlbS5HZXQoYCR7Y29udGV4dH0vc2tpbmAsIHRoaXMuX2dsdGYuc2tpbnMsIG5vZGUuc2tpbik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkU2tpbkFzeW5jKGAvc2tpbnMvJHtza2luLmluZGV4fWAsIG5vZGUsIHNraW4sIChiYWJ5bG9uU2tlbGV0b24pID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9mb3JFYWNoUHJpbWl0aXZlKG5vZGUsIChiYWJ5bG9uTWVzaCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWVzaC5za2VsZXRvbiA9IGJhYnlsb25Ta2VsZXRvbjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gV2FpdCB1bnRpbCBhbGwgdGhlIG5vZGVzIGFyZSBwYXJlbnRlZCBiZWZvcmUgcGFyZW50aW5nIHRoZSBza2lubmVkIG1lc2guXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcG9zdFNjZW5lTG9hZEFjdGlvbnMucHVzaCgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChza2luLnNrZWxldG9uICE9IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUGxhY2UgdGhlIHNraW5uZWQgbWVzaCBub2RlIGFzIGEgc2libGluZyBvZiB0aGUgc2tlbGV0b24gcm9vdCBub2RlLlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSGFuZGxlIHNwZWNpYWwgY2FzZSB3aGVuIHRoZSBwYXJlbnQgb2YgdGhlIHNrZWxldG9uIHJvb3QgaXMgdGhlIHNraW5uZWQgbWVzaC5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHBhcmVudE5vZGUgPSBBcnJheUl0ZW0uR2V0KGAvc2tpbnMvJHtza2luLmluZGV4fS9za2VsZXRvbmAsIHRoaXMuX2dsdGYubm9kZXMsIHNraW4uc2tlbGV0b24pLnBhcmVudCE7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAobm9kZS5pbmRleCA9PT0gcGFyZW50Tm9kZS5pbmRleCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhYnlsb25UcmFuc2Zvcm1Ob2RlLnBhcmVudCA9IGJhYnlsb25UcmFuc2Zvcm1Ob2RlRm9yU2tpbi5wYXJlbnQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhYnlsb25UcmFuc2Zvcm1Ob2RlLnBhcmVudCA9IHBhcmVudE5vZGUuX2JhYnlsb25UcmFuc2Zvcm1Ob2RlITtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhYnlsb25UcmFuc2Zvcm1Ob2RlLnBhcmVudCA9IHRoaXMuX3Jvb3RCYWJ5bG9uTWVzaDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGFyZW50Lm9uU2tpbkxvYWRlZE9ic2VydmFibGUubm90aWZ5T2JzZXJ2ZXJzKHsgbm9kZTogYmFieWxvblRyYW5zZm9ybU5vZGVGb3JTa2luLCBza2lubmVkTm9kZTogYmFieWxvblRyYW5zZm9ybU5vZGUgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLmxvZ0Nsb3NlKCk7XHJcblxyXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuX2ZvckVhY2hQcmltaXRpdmUobm9kZSwgKGJhYnlsb25NZXNoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBpZiAoKGJhYnlsb25NZXNoIGFzIE1lc2gpLmdlb21ldHJ5ICYmIChiYWJ5bG9uTWVzaCBhcyBNZXNoKS5nZW9tZXRyeSEudXNlQm91bmRpbmdJbmZvRnJvbUdlb21ldHJ5KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgLy8gc2ltcGx5IGFwcGx5IHRoZSB3b3JsZCBtYXRyaWNlcyB0byB0aGUgYm91bmRpbmcgaW5mbyAtIHRoZSBleHRlbmRzIGFyZSBhbHJlYWR5IG9rXHJcbiAgICAgICAgICAgICAgICAgICAgYmFieWxvbk1lc2guX3VwZGF0ZUJvdW5kaW5nSW5mbygpO1xyXG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWVzaC5yZWZyZXNoQm91bmRpbmdJbmZvKHRydWUpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIHJldHVybiBub2RlLl9iYWJ5bG9uVHJhbnNmb3JtTm9kZSE7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZE1lc2hBc3luYyhjb250ZXh0OiBzdHJpbmcsIG5vZGU6IElOb2RlLCBtZXNoOiBJTWVzaCwgYXNzaWduOiAoYmFieWxvblRyYW5zZm9ybU5vZGU6IFRyYW5zZm9ybU5vZGUpID0+IHZvaWQpOiBQcm9taXNlPFRyYW5zZm9ybU5vZGU+IHtcclxuICAgICAgICBjb25zdCBwcmltaXRpdmVzID0gbWVzaC5wcmltaXRpdmVzO1xyXG4gICAgICAgIGlmICghcHJpbWl0aXZlcyB8fCAhcHJpbWl0aXZlcy5sZW5ndGgpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBQcmltaXRpdmVzIGFyZSBtaXNzaW5nYCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAocHJpbWl0aXZlc1swXS5pbmRleCA9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgQXJyYXlJdGVtLkFzc2lnbihwcmltaXRpdmVzKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuXHJcbiAgICAgICAgdGhpcy5sb2dPcGVuKGAke2NvbnRleHR9ICR7bWVzaC5uYW1lIHx8IFwiXCJ9YCk7XHJcblxyXG4gICAgICAgIGNvbnN0IG5hbWUgPSBub2RlLm5hbWUgfHwgYG5vZGUke25vZGUuaW5kZXh9YDtcclxuXHJcbiAgICAgICAgaWYgKHByaW1pdGl2ZXMubGVuZ3RoID09PSAxKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHByaW1pdGl2ZSA9IG1lc2gucHJpbWl0aXZlc1swXTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaChcclxuICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRNZXNoUHJpbWl0aXZlQXN5bmMoYCR7Y29udGV4dH0vcHJpbWl0aXZlcy8ke3ByaW1pdGl2ZS5pbmRleH1gLCBuYW1lLCBub2RlLCBtZXNoLCBwcmltaXRpdmUsIChiYWJ5bG9uTWVzaCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIG5vZGUuX2JhYnlsb25UcmFuc2Zvcm1Ob2RlID0gYmFieWxvbk1lc2g7XHJcbiAgICAgICAgICAgICAgICAgICAgbm9kZS5fcHJpbWl0aXZlQmFieWxvbk1lc2hlcyA9IFtiYWJ5bG9uTWVzaF07XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2JhYnlsb25TY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gISF0aGlzLl9hc3NldENvbnRhaW5lcjtcclxuICAgICAgICAgICAgbm9kZS5fYmFieWxvblRyYW5zZm9ybU5vZGUgPSBuZXcgVHJhbnNmb3JtTm9kZShuYW1lLCB0aGlzLl9iYWJ5bG9uU2NlbmUpO1xyXG4gICAgICAgICAgICBub2RlLl9iYWJ5bG9uVHJhbnNmb3JtTm9kZS5fcGFyZW50Q29udGFpbmVyID0gdGhpcy5fYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgICAgIHRoaXMuX2JhYnlsb25TY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gZmFsc2U7XHJcbiAgICAgICAgICAgIG5vZGUuX3ByaW1pdGl2ZUJhYnlsb25NZXNoZXMgPSBbXTtcclxuICAgICAgICAgICAgZm9yIChjb25zdCBwcmltaXRpdmUgb2YgcHJpbWl0aXZlcykge1xyXG4gICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaChcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkTWVzaFByaW1pdGl2ZUFzeW5jKGAke2NvbnRleHR9L3ByaW1pdGl2ZXMvJHtwcmltaXRpdmUuaW5kZXh9YCwgYCR7bmFtZX1fcHJpbWl0aXZlJHtwcmltaXRpdmUuaW5kZXh9YCwgbm9kZSwgbWVzaCwgcHJpbWl0aXZlLCAoYmFieWxvbk1lc2gpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYmFieWxvbk1lc2gucGFyZW50ID0gbm9kZS5fYmFieWxvblRyYW5zZm9ybU5vZGUhO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBub2RlLl9wcmltaXRpdmVCYWJ5bG9uTWVzaGVzIS5wdXNoKGJhYnlsb25NZXNoKTtcclxuICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgYXNzaWduKG5vZGUuX2JhYnlsb25UcmFuc2Zvcm1Ob2RlISk7XHJcblxyXG4gICAgICAgIHRoaXMubG9nQ2xvc2UoKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgcmV0dXJuIG5vZGUuX2JhYnlsb25UcmFuc2Zvcm1Ob2RlITtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbCBEZWZpbmUgdGhpcyBtZXRob2QgdG8gbW9kaWZ5IHRoZSBkZWZhdWx0IGJlaGF2aW9yIHdoZW4gbG9hZGluZyBkYXRhIGZvciBtZXNoIHByaW1pdGl2ZXMuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gbmFtZSBUaGUgbWVzaCBuYW1lIHdoZW4gbG9hZGluZyB0aGUgYXNzZXRcclxuICAgICAqIEBwYXJhbSBub2RlIFRoZSBnbFRGIG5vZGUgd2hlbiBsb2FkaW5nIHRoZSBhc3NldFxyXG4gICAgICogQHBhcmFtIG1lc2ggVGhlIGdsVEYgbWVzaCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gcHJpbWl0aXZlIFRoZSBnbFRGIG1lc2ggcHJpbWl0aXZlIHByb3BlcnR5XHJcbiAgICAgKiBAcGFyYW0gYXNzaWduIEEgZnVuY3Rpb24gY2FsbGVkIHN5bmNocm9ub3VzbHkgYWZ0ZXIgcGFyc2luZyB0aGUgZ2xURiBwcm9wZXJ0aWVzXHJcbiAgICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBsb2FkZWQgbWVzaCB3aGVuIHRoZSBsb2FkIGlzIGNvbXBsZXRlIG9yIG51bGwgaWYgbm90IGhhbmRsZWRcclxuICAgICAqL1xyXG4gICAgcHVibGljIF9sb2FkTWVzaFByaW1pdGl2ZUFzeW5jKFxyXG4gICAgICAgIGNvbnRleHQ6IHN0cmluZyxcclxuICAgICAgICBuYW1lOiBzdHJpbmcsXHJcbiAgICAgICAgbm9kZTogSU5vZGUsXHJcbiAgICAgICAgbWVzaDogSU1lc2gsXHJcbiAgICAgICAgcHJpbWl0aXZlOiBJTWVzaFByaW1pdGl2ZSxcclxuICAgICAgICBhc3NpZ246IChiYWJ5bG9uTWVzaDogQWJzdHJhY3RNZXNoKSA9PiB2b2lkXHJcbiAgICApOiBQcm9taXNlPEFic3RyYWN0TWVzaD4ge1xyXG4gICAgICAgIGNvbnN0IGV4dGVuc2lvblByb21pc2UgPSB0aGlzLl9leHRlbnNpb25zTG9hZE1lc2hQcmltaXRpdmVBc3luYyhjb250ZXh0LCBuYW1lLCBub2RlLCBtZXNoLCBwcmltaXRpdmUsIGFzc2lnbik7XHJcbiAgICAgICAgaWYgKGV4dGVuc2lvblByb21pc2UpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGV4dGVuc2lvblByb21pc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLmxvZ09wZW4oYCR7Y29udGV4dH1gKTtcclxuXHJcbiAgICAgICAgY29uc3Qgc2hvdWxkSW5zdGFuY2UgPSB0aGlzLl9kaXNhYmxlSW5zdGFuY2VkTWVzaCA9PT0gMCAmJiB0aGlzLl9wYXJlbnQuY3JlYXRlSW5zdGFuY2VzICYmIG5vZGUuc2tpbiA9PSB1bmRlZmluZWQgJiYgIW1lc2gucHJpbWl0aXZlc1swXS50YXJnZXRzO1xyXG5cclxuICAgICAgICBsZXQgYmFieWxvbkFic3RyYWN0TWVzaDogQWJzdHJhY3RNZXNoO1xyXG4gICAgICAgIGxldCBwcm9taXNlOiBQcm9taXNlPGFueT47XHJcblxyXG4gICAgICAgIGlmIChzaG91bGRJbnN0YW5jZSAmJiBwcmltaXRpdmUuX2luc3RhbmNlRGF0YSkge1xyXG4gICAgICAgICAgICB0aGlzLl9iYWJ5bG9uU2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9ICEhdGhpcy5fYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgICAgIGJhYnlsb25BYnN0cmFjdE1lc2ggPSBwcmltaXRpdmUuX2luc3RhbmNlRGF0YS5iYWJ5bG9uU291cmNlTWVzaC5jcmVhdGVJbnN0YW5jZShuYW1lKSBhcyBJbnN0YW5jZWRNZXNoO1xyXG4gICAgICAgICAgICBiYWJ5bG9uQWJzdHJhY3RNZXNoLl9wYXJlbnRDb250YWluZXIgPSB0aGlzLl9hc3NldENvbnRhaW5lcjtcclxuICAgICAgICAgICAgdGhpcy5fYmFieWxvblNjZW5lLl9ibG9ja0VudGl0eUNvbGxlY3Rpb24gPSBmYWxzZTtcclxuICAgICAgICAgICAgcHJvbWlzZSA9IHByaW1pdGl2ZS5faW5zdGFuY2VEYXRhLnByb21pc2U7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBuZXcgQXJyYXk8UHJvbWlzZTxhbnk+PigpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5fYmFieWxvblNjZW5lLl9ibG9ja0VudGl0eUNvbGxlY3Rpb24gPSAhIXRoaXMuX2Fzc2V0Q29udGFpbmVyO1xyXG4gICAgICAgICAgICBjb25zdCBiYWJ5bG9uTWVzaCA9IG5ldyBNZXNoKG5hbWUsIHRoaXMuX2JhYnlsb25TY2VuZSk7XHJcbiAgICAgICAgICAgIGJhYnlsb25NZXNoLl9wYXJlbnRDb250YWluZXIgPSB0aGlzLl9hc3NldENvbnRhaW5lcjtcclxuICAgICAgICAgICAgdGhpcy5fYmFieWxvblNjZW5lLl9ibG9ja0VudGl0eUNvbGxlY3Rpb24gPSBmYWxzZTtcclxuICAgICAgICAgICAgYmFieWxvbk1lc2gub3ZlcnJpZGVNYXRlcmlhbFNpZGVPcmllbnRhdGlvbiA9IHRoaXMuX2JhYnlsb25TY2VuZS51c2VSaWdodEhhbmRlZFN5c3RlbSA/IE1hdGVyaWFsLkNvdW50ZXJDbG9ja1dpc2VTaWRlT3JpZW50YXRpb24gOiBNYXRlcmlhbC5DbG9ja1dpc2VTaWRlT3JpZW50YXRpb247XHJcblxyXG4gICAgICAgICAgICB0aGlzLl9jcmVhdGVNb3JwaFRhcmdldHMoY29udGV4dCwgbm9kZSwgbWVzaCwgcHJpbWl0aXZlLCBiYWJ5bG9uTWVzaCk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkVmVydGV4RGF0YUFzeW5jKGNvbnRleHQsIHByaW1pdGl2ZSwgYmFieWxvbk1lc2gpLnRoZW4oKGJhYnlsb25HZW9tZXRyeSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0aGlzLl9sb2FkTW9ycGhUYXJnZXRzQXN5bmMoY29udGV4dCwgcHJpbWl0aXZlLCBiYWJ5bG9uTWVzaCwgYmFieWxvbkdlb21ldHJ5KS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuX2Rpc3Bvc2VkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2JhYnlsb25TY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gISF0aGlzLl9hc3NldENvbnRhaW5lcjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYmFieWxvbkdlb21ldHJ5LmFwcGx5VG9NZXNoKGJhYnlsb25NZXNoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYmFieWxvbkdlb21ldHJ5Ll9wYXJlbnRDb250YWluZXIgPSB0aGlzLl9hc3NldENvbnRhaW5lcjtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fYmFieWxvblNjZW5lLl9ibG9ja0VudGl0eUNvbGxlY3Rpb24gPSBmYWxzZTtcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBiYWJ5bG9uRHJhd01vZGUgPSBHTFRGTG9hZGVyLl9HZXREcmF3TW9kZShjb250ZXh0LCBwcmltaXRpdmUubW9kZSk7XHJcbiAgICAgICAgICAgIGlmIChwcmltaXRpdmUubWF0ZXJpYWwgPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICBsZXQgYmFieWxvbk1hdGVyaWFsID0gdGhpcy5fZGVmYXVsdEJhYnlsb25NYXRlcmlhbERhdGFbYmFieWxvbkRyYXdNb2RlXTtcclxuICAgICAgICAgICAgICAgIGlmICghYmFieWxvbk1hdGVyaWFsKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsID0gdGhpcy5fY3JlYXRlRGVmYXVsdE1hdGVyaWFsKFwiX19HTFRGTG9hZGVyLl9kZWZhdWx0XCIsIGJhYnlsb25EcmF3TW9kZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcGFyZW50Lm9uTWF0ZXJpYWxMb2FkZWRPYnNlcnZhYmxlLm5vdGlmeU9ic2VydmVycyhiYWJ5bG9uTWF0ZXJpYWwpO1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2RlZmF1bHRCYWJ5bG9uTWF0ZXJpYWxEYXRhW2JhYnlsb25EcmF3TW9kZV0gPSBiYWJ5bG9uTWF0ZXJpYWw7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uTWVzaC5tYXRlcmlhbCA9IGJhYnlsb25NYXRlcmlhbDtcclxuICAgICAgICAgICAgfSBlbHNlIGlmICghdGhpcy5wYXJlbnQuc2tpcE1hdGVyaWFscykge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbWF0ZXJpYWwgPSBBcnJheUl0ZW0uR2V0KGAke2NvbnRleHR9L21hdGVyaWFsYCwgdGhpcy5fZ2x0Zi5tYXRlcmlhbHMsIHByaW1pdGl2ZS5tYXRlcmlhbCk7XHJcbiAgICAgICAgICAgICAgICBwcm9taXNlcy5wdXNoKFxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRNYXRlcmlhbEFzeW5jKGAvbWF0ZXJpYWxzLyR7bWF0ZXJpYWwuaW5kZXh9YCwgbWF0ZXJpYWwsIGJhYnlsb25NZXNoLCBiYWJ5bG9uRHJhd01vZGUsIChiYWJ5bG9uTWF0ZXJpYWwpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYmFieWxvbk1lc2gubWF0ZXJpYWwgPSBiYWJ5bG9uTWF0ZXJpYWw7XHJcbiAgICAgICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHByb21pc2UgPSBQcm9taXNlLmFsbChwcm9taXNlcyk7XHJcblxyXG4gICAgICAgICAgICBpZiAoc2hvdWxkSW5zdGFuY2UpIHtcclxuICAgICAgICAgICAgICAgIHByaW1pdGl2ZS5faW5zdGFuY2VEYXRhID0ge1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25Tb3VyY2VNZXNoOiBiYWJ5bG9uTWVzaCxcclxuICAgICAgICAgICAgICAgICAgICBwcm9taXNlOiBwcm9taXNlLFxyXG4gICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgYmFieWxvbkFic3RyYWN0TWVzaCA9IGJhYnlsb25NZXNoO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgR0xURkxvYWRlci5BZGRQb2ludGVyTWV0YWRhdGEoYmFieWxvbkFic3RyYWN0TWVzaCwgY29udGV4dCk7XHJcbiAgICAgICAgdGhpcy5fcGFyZW50Lm9uTWVzaExvYWRlZE9ic2VydmFibGUubm90aWZ5T2JzZXJ2ZXJzKGJhYnlsb25BYnN0cmFjdE1lc2gpO1xyXG4gICAgICAgIGFzc2lnbihiYWJ5bG9uQWJzdHJhY3RNZXNoKTtcclxuXHJcbiAgICAgICAgdGhpcy5sb2dDbG9zZSgpO1xyXG5cclxuICAgICAgICByZXR1cm4gcHJvbWlzZS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgcmV0dXJuIGJhYnlsb25BYnN0cmFjdE1lc2g7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZFZlcnRleERhdGFBc3luYyhjb250ZXh0OiBzdHJpbmcsIHByaW1pdGl2ZTogSU1lc2hQcmltaXRpdmUsIGJhYnlsb25NZXNoOiBNZXNoKTogUHJvbWlzZTxHZW9tZXRyeT4ge1xyXG4gICAgICAgIGNvbnN0IGV4dGVuc2lvblByb21pc2UgPSB0aGlzLl9leHRlbnNpb25zTG9hZFZlcnRleERhdGFBc3luYyhjb250ZXh0LCBwcmltaXRpdmUsIGJhYnlsb25NZXNoKTtcclxuICAgICAgICBpZiAoZXh0ZW5zaW9uUHJvbWlzZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZXh0ZW5zaW9uUHJvbWlzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGF0dHJpYnV0ZXMgPSBwcmltaXRpdmUuYXR0cmlidXRlcztcclxuICAgICAgICBpZiAoIWF0dHJpYnV0ZXMpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBBdHRyaWJ1dGVzIGFyZSBtaXNzaW5nYCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBwcm9taXNlcyA9IG5ldyBBcnJheTxQcm9taXNlPGFueT4+KCk7XHJcblxyXG4gICAgICAgIGNvbnN0IGJhYnlsb25HZW9tZXRyeSA9IG5ldyBHZW9tZXRyeShiYWJ5bG9uTWVzaC5uYW1lLCB0aGlzLl9iYWJ5bG9uU2NlbmUpO1xyXG5cclxuICAgICAgICBpZiAocHJpbWl0aXZlLmluZGljZXMgPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIGJhYnlsb25NZXNoLmlzVW5JbmRleGVkID0gdHJ1ZTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBjb25zdCBhY2Nlc3NvciA9IEFycmF5SXRlbS5HZXQoYCR7Y29udGV4dH0vaW5kaWNlc2AsIHRoaXMuX2dsdGYuYWNjZXNzb3JzLCBwcmltaXRpdmUuaW5kaWNlcyk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkSW5kaWNlc0FjY2Vzc29yQXN5bmMoYC9hY2Nlc3NvcnMvJHthY2Nlc3Nvci5pbmRleH1gLCBhY2Nlc3NvcikudGhlbigoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25HZW9tZXRyeS5zZXRJbmRpY2VzKGRhdGEpO1xyXG4gICAgICAgICAgICAgICAgfSlcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGxvYWRBdHRyaWJ1dGUgPSAobmFtZTogc3RyaW5nLCBraW5kOiBzdHJpbmcsIGNhbGxiYWNrPzogKGFjY2Vzc29yOiBJQWNjZXNzb3IpID0+IHZvaWQpID0+IHtcclxuICAgICAgICAgICAgaWYgKGF0dHJpYnV0ZXNbbmFtZV0gPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGJhYnlsb25NZXNoLl9kZWxheUluZm8gPSBiYWJ5bG9uTWVzaC5fZGVsYXlJbmZvIHx8IFtdO1xyXG4gICAgICAgICAgICBpZiAoYmFieWxvbk1lc2guX2RlbGF5SW5mby5pbmRleE9mKGtpbmQpID09PSAtMSkge1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbk1lc2guX2RlbGF5SW5mby5wdXNoKGtpbmQpO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBhY2Nlc3NvciA9IEFycmF5SXRlbS5HZXQoYCR7Y29udGV4dH0vYXR0cmlidXRlcy8ke25hbWV9YCwgdGhpcy5fZ2x0Zi5hY2Nlc3NvcnMsIGF0dHJpYnV0ZXNbbmFtZV0pO1xyXG4gICAgICAgICAgICBwcm9taXNlcy5wdXNoKFxyXG4gICAgICAgICAgICAgICAgdGhpcy5fbG9hZFZlcnRleEFjY2Vzc29yQXN5bmMoYC9hY2Nlc3NvcnMvJHthY2Nlc3Nvci5pbmRleH1gLCBhY2Nlc3Nvciwga2luZCkudGhlbigoYmFieWxvblZlcnRleEJ1ZmZlcikgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGlmIChiYWJ5bG9uVmVydGV4QnVmZmVyLmdldEtpbmQoKSA9PT0gVmVydGV4QnVmZmVyLlBvc2l0aW9uS2luZCAmJiAhdGhpcy5wYXJlbnQuYWx3YXlzQ29tcHV0ZUJvdW5kaW5nQm94ICYmICFiYWJ5bG9uTWVzaC5za2VsZXRvbikge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYWNjZXNzb3IubWluICYmIGFjY2Vzc29yLm1heCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgbWluID0gVG1wVmVjdG9ycy5WZWN0b3IzWzBdLmNvcHlGcm9tRmxvYXRzKC4uLihhY2Nlc3Nvci5taW4gYXMgW251bWJlciwgbnVtYmVyLCBudW1iZXJdKSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtYXggPSBUbXBWZWN0b3JzLlZlY3RvcjNbMV0uY29weUZyb21GbG9hdHMoLi4uKGFjY2Vzc29yLm1heCBhcyBbbnVtYmVyLCBudW1iZXIsIG51bWJlcl0pKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChhY2Nlc3Nvci5ub3JtYWxpemVkICYmIGFjY2Vzc29yLmNvbXBvbmVudFR5cGUgIT09IEFjY2Vzc29yQ29tcG9uZW50VHlwZS5GTE9BVCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBkaXZpZGVyID0gMTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGFjY2Vzc29yLmNvbXBvbmVudFR5cGUpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBY2Nlc3NvckNvbXBvbmVudFR5cGUuQllURTpcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRpdmlkZXIgPSAxMjcuMDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEFjY2Vzc29yQ29tcG9uZW50VHlwZS5VTlNJR05FRF9CWVRFOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGl2aWRlciA9IDI1NS4wO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQWNjZXNzb3JDb21wb25lbnRUeXBlLlNIT1JUOlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGl2aWRlciA9IDMyNzY3LjA7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBY2Nlc3NvckNvbXBvbmVudFR5cGUuVU5TSUdORURfU0hPUlQ6XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBkaXZpZGVyID0gNjU1MzUuMDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvbmVPdmVyRGl2aWRlciA9IDEgLyBkaXZpZGVyO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbi5zY2FsZUluUGxhY2Uob25lT3ZlckRpdmlkZXIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1heC5zY2FsZUluUGxhY2Uob25lT3ZlckRpdmlkZXIpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFieWxvbkdlb21ldHJ5Ll9ib3VuZGluZ0luZm8gPSBuZXcgQm91bmRpbmdJbmZvKG1pbiwgbWF4KTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJhYnlsb25HZW9tZXRyeS51c2VCb3VuZGluZ0luZm9Gcm9tR2VvbWV0cnkgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25HZW9tZXRyeS5zZXRWZXJ0aWNlc0J1ZmZlcihiYWJ5bG9uVmVydGV4QnVmZmVyLCBhY2Nlc3Nvci5jb3VudCk7XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgICAgaWYgKGtpbmQgPT0gVmVydGV4QnVmZmVyLk1hdHJpY2VzSW5kaWNlc0V4dHJhS2luZCkge1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbk1lc2gubnVtQm9uZUluZmx1ZW5jZXJzID0gODtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKGNhbGxiYWNrKSB7XHJcbiAgICAgICAgICAgICAgICBjYWxsYmFjayhhY2Nlc3Nvcik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICBsb2FkQXR0cmlidXRlKFwiUE9TSVRJT05cIiwgVmVydGV4QnVmZmVyLlBvc2l0aW9uS2luZCk7XHJcbiAgICAgICAgbG9hZEF0dHJpYnV0ZShcIk5PUk1BTFwiLCBWZXJ0ZXhCdWZmZXIuTm9ybWFsS2luZCk7XHJcbiAgICAgICAgbG9hZEF0dHJpYnV0ZShcIlRBTkdFTlRcIiwgVmVydGV4QnVmZmVyLlRhbmdlbnRLaW5kKTtcclxuICAgICAgICBsb2FkQXR0cmlidXRlKFwiVEVYQ09PUkRfMFwiLCBWZXJ0ZXhCdWZmZXIuVVZLaW5kKTtcclxuICAgICAgICBsb2FkQXR0cmlidXRlKFwiVEVYQ09PUkRfMVwiLCBWZXJ0ZXhCdWZmZXIuVVYyS2luZCk7XHJcbiAgICAgICAgbG9hZEF0dHJpYnV0ZShcIlRFWENPT1JEXzJcIiwgVmVydGV4QnVmZmVyLlVWM0tpbmQpO1xyXG4gICAgICAgIGxvYWRBdHRyaWJ1dGUoXCJURVhDT09SRF8zXCIsIFZlcnRleEJ1ZmZlci5VVjRLaW5kKTtcclxuICAgICAgICBsb2FkQXR0cmlidXRlKFwiVEVYQ09PUkRfNFwiLCBWZXJ0ZXhCdWZmZXIuVVY1S2luZCk7XHJcbiAgICAgICAgbG9hZEF0dHJpYnV0ZShcIlRFWENPT1JEXzVcIiwgVmVydGV4QnVmZmVyLlVWNktpbmQpO1xyXG4gICAgICAgIGxvYWRBdHRyaWJ1dGUoXCJKT0lOVFNfMFwiLCBWZXJ0ZXhCdWZmZXIuTWF0cmljZXNJbmRpY2VzS2luZCk7XHJcbiAgICAgICAgbG9hZEF0dHJpYnV0ZShcIldFSUdIVFNfMFwiLCBWZXJ0ZXhCdWZmZXIuTWF0cmljZXNXZWlnaHRzS2luZCk7XHJcbiAgICAgICAgbG9hZEF0dHJpYnV0ZShcIkpPSU5UU18xXCIsIFZlcnRleEJ1ZmZlci5NYXRyaWNlc0luZGljZXNFeHRyYUtpbmQpO1xyXG4gICAgICAgIGxvYWRBdHRyaWJ1dGUoXCJXRUlHSFRTXzFcIiwgVmVydGV4QnVmZmVyLk1hdHJpY2VzV2VpZ2h0c0V4dHJhS2luZCk7XHJcbiAgICAgICAgbG9hZEF0dHJpYnV0ZShcIkNPTE9SXzBcIiwgVmVydGV4QnVmZmVyLkNvbG9yS2luZCwgKGFjY2Vzc29yKSA9PiB7XHJcbiAgICAgICAgICAgIGlmIChhY2Nlc3Nvci50eXBlID09PSBBY2Nlc3NvclR5cGUuVkVDNCkge1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbk1lc2guaGFzVmVydGV4QWxwaGEgPSB0cnVlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiBiYWJ5bG9uR2VvbWV0cnk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfY3JlYXRlTW9ycGhUYXJnZXRzKGNvbnRleHQ6IHN0cmluZywgbm9kZTogSU5vZGUsIG1lc2g6IElNZXNoLCBwcmltaXRpdmU6IElNZXNoUHJpbWl0aXZlLCBiYWJ5bG9uTWVzaDogTWVzaCk6IHZvaWQge1xyXG4gICAgICAgIGlmICghcHJpbWl0aXZlLnRhcmdldHMpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKG5vZGUuX251bU1vcnBoVGFyZ2V0cyA9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgbm9kZS5fbnVtTW9ycGhUYXJnZXRzID0gcHJpbWl0aXZlLnRhcmdldHMubGVuZ3RoO1xyXG4gICAgICAgIH0gZWxzZSBpZiAocHJpbWl0aXZlLnRhcmdldHMubGVuZ3RoICE9PSBub2RlLl9udW1Nb3JwaFRhcmdldHMpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBQcmltaXRpdmVzIGRvIG5vdCBoYXZlIHRoZSBzYW1lIG51bWJlciBvZiB0YXJnZXRzYCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCB0YXJnZXROYW1lcyA9IG1lc2guZXh0cmFzID8gbWVzaC5leHRyYXMudGFyZ2V0TmFtZXMgOiBudWxsO1xyXG5cclxuICAgICAgICB0aGlzLl9iYWJ5bG9uU2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9ICEhdGhpcy5fYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgYmFieWxvbk1lc2gubW9ycGhUYXJnZXRNYW5hZ2VyID0gbmV3IE1vcnBoVGFyZ2V0TWFuYWdlcih0aGlzLl9iYWJ5bG9uU2NlbmUpO1xyXG4gICAgICAgIGJhYnlsb25NZXNoLm1vcnBoVGFyZ2V0TWFuYWdlci5fcGFyZW50Q29udGFpbmVyID0gdGhpcy5fYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgdGhpcy5fYmFieWxvblNjZW5lLl9ibG9ja0VudGl0eUNvbGxlY3Rpb24gPSBmYWxzZTtcclxuXHJcbiAgICAgICAgYmFieWxvbk1lc2gubW9ycGhUYXJnZXRNYW5hZ2VyLmFyZVVwZGF0ZXNGcm96ZW4gPSB0cnVlO1xyXG5cclxuICAgICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgcHJpbWl0aXZlLnRhcmdldHMubGVuZ3RoOyBpbmRleCsrKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHdlaWdodCA9IG5vZGUud2VpZ2h0cyA/IG5vZGUud2VpZ2h0c1tpbmRleF0gOiBtZXNoLndlaWdodHMgPyBtZXNoLndlaWdodHNbaW5kZXhdIDogMDtcclxuICAgICAgICAgICAgY29uc3QgbmFtZSA9IHRhcmdldE5hbWVzID8gdGFyZ2V0TmFtZXNbaW5kZXhdIDogYG1vcnBoVGFyZ2V0JHtpbmRleH1gO1xyXG4gICAgICAgICAgICBiYWJ5bG9uTWVzaC5tb3JwaFRhcmdldE1hbmFnZXIuYWRkVGFyZ2V0KG5ldyBNb3JwaFRhcmdldChuYW1lLCB3ZWlnaHQsIGJhYnlsb25NZXNoLmdldFNjZW5lKCkpKTtcclxuICAgICAgICAgICAgLy8gVE9ETzogdGVsbCB0aGUgdGFyZ2V0IHdoZXRoZXIgaXQgaGFzIHBvc2l0aW9ucywgbm9ybWFscywgdGFuZ2VudHNcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZE1vcnBoVGFyZ2V0c0FzeW5jKGNvbnRleHQ6IHN0cmluZywgcHJpbWl0aXZlOiBJTWVzaFByaW1pdGl2ZSwgYmFieWxvbk1lc2g6IE1lc2gsIGJhYnlsb25HZW9tZXRyeTogR2VvbWV0cnkpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBpZiAoIXByaW1pdGl2ZS50YXJnZXRzKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuXHJcbiAgICAgICAgY29uc3QgbW9ycGhUYXJnZXRNYW5hZ2VyID0gYmFieWxvbk1lc2gubW9ycGhUYXJnZXRNYW5hZ2VyITtcclxuICAgICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgbW9ycGhUYXJnZXRNYW5hZ2VyLm51bVRhcmdldHM7IGluZGV4KyspIHtcclxuICAgICAgICAgICAgY29uc3QgYmFieWxvbk1vcnBoVGFyZ2V0ID0gbW9ycGhUYXJnZXRNYW5hZ2VyLmdldFRhcmdldChpbmRleCk7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2godGhpcy5fbG9hZE1vcnBoVGFyZ2V0VmVydGV4RGF0YUFzeW5jKGAke2NvbnRleHR9L3RhcmdldHMvJHtpbmRleH1gLCBiYWJ5bG9uR2VvbWV0cnksIHByaW1pdGl2ZS50YXJnZXRzW2luZGV4XSwgYmFieWxvbk1vcnBoVGFyZ2V0KSk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICBtb3JwaFRhcmdldE1hbmFnZXIuYXJlVXBkYXRlc0Zyb3plbiA9IGZhbHNlO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2xvYWRNb3JwaFRhcmdldFZlcnRleERhdGFBc3luYyhjb250ZXh0OiBzdHJpbmcsIGJhYnlsb25HZW9tZXRyeTogR2VvbWV0cnksIGF0dHJpYnV0ZXM6IHsgW25hbWU6IHN0cmluZ106IG51bWJlciB9LCBiYWJ5bG9uTW9ycGhUYXJnZXQ6IE1vcnBoVGFyZ2V0KTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBuZXcgQXJyYXk8UHJvbWlzZTxhbnk+PigpO1xyXG5cclxuICAgICAgICBjb25zdCBsb2FkQXR0cmlidXRlID0gKGF0dHJpYnV0ZTogc3RyaW5nLCBraW5kOiBzdHJpbmcsIHNldERhdGE6IChiYWJ5bG9uVmVydGV4QnVmZmVyOiBWZXJ0ZXhCdWZmZXIsIGRhdGE6IEZsb2F0MzJBcnJheSkgPT4gdm9pZCkgPT4ge1xyXG4gICAgICAgICAgICBpZiAoYXR0cmlidXRlc1thdHRyaWJ1dGVdID09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBjb25zdCBiYWJ5bG9uVmVydGV4QnVmZmVyID0gYmFieWxvbkdlb21ldHJ5LmdldFZlcnRleEJ1ZmZlcihraW5kKTtcclxuICAgICAgICAgICAgaWYgKCFiYWJ5bG9uVmVydGV4QnVmZmVyKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGFjY2Vzc29yID0gQXJyYXlJdGVtLkdldChgJHtjb250ZXh0fS8ke2F0dHJpYnV0ZX1gLCB0aGlzLl9nbHRmLmFjY2Vzc29ycywgYXR0cmlidXRlc1thdHRyaWJ1dGVdKTtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaChcclxuICAgICAgICAgICAgICAgIHRoaXMuX2xvYWRGbG9hdEFjY2Vzc29yQXN5bmMoYC9hY2Nlc3NvcnMvJHthY2Nlc3Nvci5pbmRleH1gLCBhY2Nlc3NvcikudGhlbigoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHNldERhdGEoYmFieWxvblZlcnRleEJ1ZmZlciwgZGF0YSk7XHJcbiAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGxvYWRBdHRyaWJ1dGUoXCJQT1NJVElPTlwiLCBWZXJ0ZXhCdWZmZXIuUG9zaXRpb25LaW5kLCAoYmFieWxvblZlcnRleEJ1ZmZlciwgZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICBjb25zdCBwb3NpdGlvbnMgPSBuZXcgRmxvYXQzMkFycmF5KGRhdGEubGVuZ3RoKTtcclxuICAgICAgICAgICAgYmFieWxvblZlcnRleEJ1ZmZlci5mb3JFYWNoKGRhdGEubGVuZ3RoLCAodmFsdWUsIGluZGV4KSA9PiB7XHJcbiAgICAgICAgICAgICAgICBwb3NpdGlvbnNbaW5kZXhdID0gZGF0YVtpbmRleF0gKyB2YWx1ZTtcclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICBiYWJ5bG9uTW9ycGhUYXJnZXQuc2V0UG9zaXRpb25zKHBvc2l0aW9ucyk7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIGxvYWRBdHRyaWJ1dGUoXCJOT1JNQUxcIiwgVmVydGV4QnVmZmVyLk5vcm1hbEtpbmQsIChiYWJ5bG9uVmVydGV4QnVmZmVyLCBkYXRhKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IG5vcm1hbHMgPSBuZXcgRmxvYXQzMkFycmF5KGRhdGEubGVuZ3RoKTtcclxuICAgICAgICAgICAgYmFieWxvblZlcnRleEJ1ZmZlci5mb3JFYWNoKG5vcm1hbHMubGVuZ3RoLCAodmFsdWUsIGluZGV4KSA9PiB7XHJcbiAgICAgICAgICAgICAgICBub3JtYWxzW2luZGV4XSA9IGRhdGFbaW5kZXhdICsgdmFsdWU7XHJcbiAgICAgICAgICAgIH0pO1xyXG5cclxuICAgICAgICAgICAgYmFieWxvbk1vcnBoVGFyZ2V0LnNldE5vcm1hbHMobm9ybWFscyk7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIGxvYWRBdHRyaWJ1dGUoXCJUQU5HRU5UXCIsIFZlcnRleEJ1ZmZlci5UYW5nZW50S2luZCwgKGJhYnlsb25WZXJ0ZXhCdWZmZXIsIGRhdGEpID0+IHtcclxuICAgICAgICAgICAgY29uc3QgdGFuZ2VudHMgPSBuZXcgRmxvYXQzMkFycmF5KChkYXRhLmxlbmd0aCAvIDMpICogNCk7XHJcbiAgICAgICAgICAgIGxldCBkYXRhSW5kZXggPSAwO1xyXG4gICAgICAgICAgICBiYWJ5bG9uVmVydGV4QnVmZmVyLmZvckVhY2goKGRhdGEubGVuZ3RoIC8gMykgKiA0LCAodmFsdWUsIGluZGV4KSA9PiB7XHJcbiAgICAgICAgICAgICAgICAvLyBUYW5nZW50IGRhdGEgZm9yIG1vcnBoIHRhcmdldHMgaXMgc3RvcmVkIGFzIHh5eiBkZWx0YS5cclxuICAgICAgICAgICAgICAgIC8vIFRoZSB2ZXJ0ZXhEYXRhLnRhbmdlbnQgaXMgc3RvcmVkIGFzIHh5encuXHJcbiAgICAgICAgICAgICAgICAvLyBTbyB3ZSBuZWVkIHRvIHNraXAgZXZlcnkgZm91cnRoIHZlcnRleERhdGEudGFuZ2VudC5cclxuICAgICAgICAgICAgICAgIGlmICgoaW5kZXggKyAxKSAlIDQgIT09IDApIHtcclxuICAgICAgICAgICAgICAgICAgICB0YW5nZW50c1tkYXRhSW5kZXhdID0gZGF0YVtkYXRhSW5kZXhdICsgdmFsdWU7XHJcbiAgICAgICAgICAgICAgICAgICAgZGF0YUluZGV4Kys7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICBiYWJ5bG9uTW9ycGhUYXJnZXQuc2V0VGFuZ2VudHModGFuZ2VudHMpO1xyXG4gICAgICAgIH0pO1xyXG5cclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge30pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIF9Mb2FkVHJhbnNmb3JtKG5vZGU6IElOb2RlLCBiYWJ5bG9uTm9kZTogVHJhbnNmb3JtTm9kZSk6IHZvaWQge1xyXG4gICAgICAgIC8vIElnbm9yZSB0aGUgVFJTIG9mIHNraW5uZWQgbm9kZXMuXHJcbiAgICAgICAgLy8gU2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9LaHJvbm9zR3JvdXAvZ2xURi90cmVlL21hc3Rlci9zcGVjaWZpY2F0aW9uLzIuMCNza2lucyAoc2Vjb25kIGltcGxlbWVudGF0aW9uIG5vdGUpXHJcbiAgICAgICAgaWYgKG5vZGUuc2tpbiAhPSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgbGV0IHBvc2l0aW9uID0gVmVjdG9yMy5aZXJvKCk7XHJcbiAgICAgICAgbGV0IHJvdGF0aW9uID0gUXVhdGVybmlvbi5JZGVudGl0eSgpO1xyXG4gICAgICAgIGxldCBzY2FsaW5nID0gVmVjdG9yMy5PbmUoKTtcclxuXHJcbiAgICAgICAgaWYgKG5vZGUubWF0cml4KSB7XHJcbiAgICAgICAgICAgIGNvbnN0IG1hdHJpeCA9IE1hdHJpeC5Gcm9tQXJyYXkobm9kZS5tYXRyaXgpO1xyXG4gICAgICAgICAgICBtYXRyaXguZGVjb21wb3NlKHNjYWxpbmcsIHJvdGF0aW9uLCBwb3NpdGlvbik7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgaWYgKG5vZGUudHJhbnNsYXRpb24pIHtcclxuICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gVmVjdG9yMy5Gcm9tQXJyYXkobm9kZS50cmFuc2xhdGlvbik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKG5vZGUucm90YXRpb24pIHtcclxuICAgICAgICAgICAgICAgIHJvdGF0aW9uID0gUXVhdGVybmlvbi5Gcm9tQXJyYXkobm9kZS5yb3RhdGlvbik7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgaWYgKG5vZGUuc2NhbGUpIHtcclxuICAgICAgICAgICAgICAgIHNjYWxpbmcgPSBWZWN0b3IzLkZyb21BcnJheShub2RlLnNjYWxlKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgYmFieWxvbk5vZGUucG9zaXRpb24gPSBwb3NpdGlvbjtcclxuICAgICAgICBiYWJ5bG9uTm9kZS5yb3RhdGlvblF1YXRlcm5pb24gPSByb3RhdGlvbjtcclxuICAgICAgICBiYWJ5bG9uTm9kZS5zY2FsaW5nID0gc2NhbGluZztcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9sb2FkU2tpbkFzeW5jKGNvbnRleHQ6IHN0cmluZywgbm9kZTogSU5vZGUsIHNraW46IElTa2luLCBhc3NpZ246IChiYWJ5bG9uU2tlbGV0b246IFNrZWxldG9uKSA9PiB2b2lkKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgY29uc3QgZXh0ZW5zaW9uUHJvbWlzZSA9IHRoaXMuX2V4dGVuc2lvbnNMb2FkU2tpbkFzeW5jKGNvbnRleHQsIG5vZGUsIHNraW4pO1xyXG4gICAgICAgIGlmIChleHRlbnNpb25Qcm9taXNlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBleHRlbnNpb25Qcm9taXNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKHNraW4uX2RhdGEpIHtcclxuICAgICAgICAgICAgYXNzaWduKHNraW4uX2RhdGEuYmFieWxvblNrZWxldG9uKTtcclxuICAgICAgICAgICAgcmV0dXJuIHNraW4uX2RhdGEucHJvbWlzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHNrZWxldG9uSWQgPSBgc2tlbGV0b24ke3NraW4uaW5kZXh9YDtcclxuICAgICAgICB0aGlzLl9iYWJ5bG9uU2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9ICEhdGhpcy5fYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgY29uc3QgYmFieWxvblNrZWxldG9uID0gbmV3IFNrZWxldG9uKHNraW4ubmFtZSB8fCBza2VsZXRvbklkLCBza2VsZXRvbklkLCB0aGlzLl9iYWJ5bG9uU2NlbmUpO1xyXG4gICAgICAgIGJhYnlsb25Ta2VsZXRvbi5fcGFyZW50Q29udGFpbmVyID0gdGhpcy5fYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgdGhpcy5fYmFieWxvblNjZW5lLl9ibG9ja0VudGl0eUNvbGxlY3Rpb24gPSBmYWxzZTtcclxuXHJcbiAgICAgICAgdGhpcy5fbG9hZEJvbmVzKGNvbnRleHQsIHNraW4sIGJhYnlsb25Ta2VsZXRvbik7XHJcbiAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuX2xvYWRTa2luSW52ZXJzZUJpbmRNYXRyaWNlc0RhdGFBc3luYyhjb250ZXh0LCBza2luKS50aGVuKChpbnZlcnNlQmluZE1hdHJpY2VzRGF0YSkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLl91cGRhdGVCb25lTWF0cmljZXMoYmFieWxvblNrZWxldG9uLCBpbnZlcnNlQmluZE1hdHJpY2VzRGF0YSk7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHNraW4uX2RhdGEgPSB7XHJcbiAgICAgICAgICAgIGJhYnlsb25Ta2VsZXRvbjogYmFieWxvblNrZWxldG9uLFxyXG4gICAgICAgICAgICBwcm9taXNlOiBwcm9taXNlLFxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIGFzc2lnbihiYWJ5bG9uU2tlbGV0b24pO1xyXG5cclxuICAgICAgICByZXR1cm4gcHJvbWlzZTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9sb2FkQm9uZXMoY29udGV4dDogc3RyaW5nLCBza2luOiBJU2tpbiwgYmFieWxvblNrZWxldG9uOiBTa2VsZXRvbik6IHZvaWQge1xyXG4gICAgICAgIGlmIChza2luLnNrZWxldG9uID09IHVuZGVmaW5lZCB8fCB0aGlzLl9wYXJlbnQuYWx3YXlzQ29tcHV0ZVNrZWxldG9uUm9vdE5vZGUpIHtcclxuICAgICAgICAgICAgY29uc3Qgcm9vdE5vZGUgPSB0aGlzLl9maW5kU2tlbGV0b25Sb290Tm9kZShgJHtjb250ZXh0fS9qb2ludHNgLCBza2luLmpvaW50cyk7XHJcbiAgICAgICAgICAgIGlmIChyb290Tm9kZSkge1xyXG4gICAgICAgICAgICAgICAgaWYgKHNraW4uc2tlbGV0b24gPT09IHVuZGVmaW5lZCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHNraW4uc2tlbGV0b24gPSByb290Tm9kZS5pbmRleDtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaXNQYXJlbnQgPSAoYTogSU5vZGUsIGI6IElOb2RlKTogYm9vbGVhbiA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZvciAoOyBiLnBhcmVudDsgYiA9IGIucGFyZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoYi5wYXJlbnQgPT09IGEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNrZWxldG9uTm9kZSA9IEFycmF5SXRlbS5HZXQoYCR7Y29udGV4dH0vc2tlbGV0b25gLCB0aGlzLl9nbHRmLm5vZGVzLCBza2luLnNrZWxldG9uKTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAoc2tlbGV0b25Ob2RlICE9PSByb290Tm9kZSAmJiAhaXNQYXJlbnQoc2tlbGV0b25Ob2RlLCByb290Tm9kZSkpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLldhcm4oYCR7Y29udGV4dH0vc2tlbGV0b246IE92ZXJyaWRpbmcgd2l0aCBuZWFyZXN0IGNvbW1vbiBhbmNlc3RvciBhcyBza2VsZXRvbiBub2RlIGlzIG5vdCBhIGNvbW1vbiByb290YCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNraW4uc2tlbGV0b24gPSByb290Tm9kZS5pbmRleDtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBMb2dnZXIuV2FybihgJHtjb250ZXh0fTogRmFpbGVkIHRvIGZpbmQgY29tbW9uIHJvb3RgKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgYmFieWxvbkJvbmVzOiB7IFtpbmRleDogbnVtYmVyXTogQm9uZSB9ID0ge307XHJcbiAgICAgICAgZm9yIChjb25zdCBpbmRleCBvZiBza2luLmpvaW50cykge1xyXG4gICAgICAgICAgICBjb25zdCBub2RlID0gQXJyYXlJdGVtLkdldChgJHtjb250ZXh0fS9qb2ludHMvJHtpbmRleH1gLCB0aGlzLl9nbHRmLm5vZGVzLCBpbmRleCk7XHJcbiAgICAgICAgICAgIHRoaXMuX2xvYWRCb25lKG5vZGUsIHNraW4sIGJhYnlsb25Ta2VsZXRvbiwgYmFieWxvbkJvbmVzKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfZmluZFNrZWxldG9uUm9vdE5vZGUoY29udGV4dDogc3RyaW5nLCBqb2ludHM6IEFycmF5PG51bWJlcj4pOiBOdWxsYWJsZTxJTm9kZT4ge1xyXG4gICAgICAgIGlmIChqb2ludHMubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgcGF0aHM6IHsgW2pvaW50OiBudW1iZXJdOiBBcnJheTxJTm9kZT4gfSA9IHt9O1xyXG4gICAgICAgIGZvciAoY29uc3QgaW5kZXggb2Ygam9pbnRzKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHBhdGggPSBuZXcgQXJyYXk8SU5vZGU+KCk7XHJcbiAgICAgICAgICAgIGxldCBub2RlID0gQXJyYXlJdGVtLkdldChgJHtjb250ZXh0fS8ke2luZGV4fWAsIHRoaXMuX2dsdGYubm9kZXMsIGluZGV4KTtcclxuICAgICAgICAgICAgd2hpbGUgKG5vZGUuaW5kZXggIT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICBwYXRoLnVuc2hpZnQobm9kZSk7XHJcbiAgICAgICAgICAgICAgICBub2RlID0gbm9kZS5wYXJlbnQhO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHBhdGhzW2luZGV4XSA9IHBhdGg7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgcm9vdE5vZGU6IE51bGxhYmxlPElOb2RlPiA9IG51bGw7XHJcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IDsgKytpKSB7XHJcbiAgICAgICAgICAgIGxldCBwYXRoID0gcGF0aHNbam9pbnRzWzBdXTtcclxuICAgICAgICAgICAgaWYgKGkgPj0gcGF0aC5sZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybiByb290Tm9kZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3Qgbm9kZSA9IHBhdGhbaV07XHJcbiAgICAgICAgICAgIGZvciAobGV0IGogPSAxOyBqIDwgam9pbnRzLmxlbmd0aDsgKytqKSB7XHJcbiAgICAgICAgICAgICAgICBwYXRoID0gcGF0aHNbam9pbnRzW2pdXTtcclxuICAgICAgICAgICAgICAgIGlmIChpID49IHBhdGgubGVuZ3RoIHx8IG5vZGUgIT09IHBhdGhbaV0pIHtcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcm9vdE5vZGU7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHJvb3ROb2RlID0gbm9kZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZEJvbmUobm9kZTogSU5vZGUsIHNraW46IElTa2luLCBiYWJ5bG9uU2tlbGV0b246IFNrZWxldG9uLCBiYWJ5bG9uQm9uZXM6IHsgW2luZGV4OiBudW1iZXJdOiBCb25lIH0pOiBCb25lIHtcclxuICAgICAgICBsZXQgYmFieWxvbkJvbmUgPSBiYWJ5bG9uQm9uZXNbbm9kZS5pbmRleF07XHJcbiAgICAgICAgaWYgKGJhYnlsb25Cb25lKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBiYWJ5bG9uQm9uZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCBwYXJlbnRCYWJ5bG9uQm9uZTogTnVsbGFibGU8Qm9uZT4gPSBudWxsO1xyXG4gICAgICAgIGlmIChub2RlLmluZGV4ICE9PSBza2luLnNrZWxldG9uKSB7XHJcbiAgICAgICAgICAgIGlmIChub2RlLnBhcmVudCAmJiBub2RlLnBhcmVudC5pbmRleCAhPT0gLTEpIHtcclxuICAgICAgICAgICAgICAgIHBhcmVudEJhYnlsb25Cb25lID0gdGhpcy5fbG9hZEJvbmUobm9kZS5wYXJlbnQsIHNraW4sIGJhYnlsb25Ta2VsZXRvbiwgYmFieWxvbkJvbmVzKTtcclxuICAgICAgICAgICAgfSBlbHNlIGlmIChza2luLnNrZWxldG9uICE9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgICAgIExvZ2dlci5XYXJuKGAvc2tpbnMvJHtza2luLmluZGV4fS9za2VsZXRvbjogU2tlbGV0b24gbm9kZSBpcyBub3QgYSBjb21tb24gcm9vdGApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBib25lSW5kZXggPSBza2luLmpvaW50cy5pbmRleE9mKG5vZGUuaW5kZXgpO1xyXG4gICAgICAgIGJhYnlsb25Cb25lID0gbmV3IEJvbmUobm9kZS5uYW1lIHx8IGBqb2ludCR7bm9kZS5pbmRleH1gLCBiYWJ5bG9uU2tlbGV0b24sIHBhcmVudEJhYnlsb25Cb25lLCB0aGlzLl9nZXROb2RlTWF0cml4KG5vZGUpLCBudWxsLCBudWxsLCBib25lSW5kZXgpO1xyXG4gICAgICAgIGJhYnlsb25Cb25lc1tub2RlLmluZGV4XSA9IGJhYnlsb25Cb25lO1xyXG5cclxuICAgICAgICAvLyBXYWl0IHVudGlsIHRoZSBzY2VuZSBpcyBsb2FkZWQgdG8gZW5zdXJlIHRoZSB0cmFuc2Zvcm0gbm9kZXMgYXJlIGxvYWRlZC5cclxuICAgICAgICB0aGlzLl9wb3N0U2NlbmVMb2FkQWN0aW9ucy5wdXNoKCgpID0+IHtcclxuICAgICAgICAgICAgLy8gTGluayB0aGUgQmFieWxvbiBib25lIHdpdGggdGhlIGNvcnJlc3BvbmRpbmcgQmFieWxvbiB0cmFuc2Zvcm0gbm9kZS5cclxuICAgICAgICAgICAgLy8gQSBnbFRGIGpvaW50IGlzIGEgcG9pbnRlciB0byBhIGdsVEYgbm9kZSBpbiB0aGUgZ2xURiBub2RlIGhpZXJhcmNoeSBzaW1pbGFyIHRvIFVuaXR5M0QuXHJcbiAgICAgICAgICAgIGJhYnlsb25Cb25lLmxpbmtUcmFuc2Zvcm1Ob2RlKG5vZGUuX2JhYnlsb25UcmFuc2Zvcm1Ob2RlISk7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHJldHVybiBiYWJ5bG9uQm9uZTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9sb2FkU2tpbkludmVyc2VCaW5kTWF0cmljZXNEYXRhQXN5bmMoY29udGV4dDogc3RyaW5nLCBza2luOiBJU2tpbik6IFByb21pc2U8TnVsbGFibGU8RmxvYXQzMkFycmF5Pj4ge1xyXG4gICAgICAgIGlmIChza2luLmludmVyc2VCaW5kTWF0cmljZXMgPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobnVsbCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBhY2Nlc3NvciA9IEFycmF5SXRlbS5HZXQoYCR7Y29udGV4dH0vaW52ZXJzZUJpbmRNYXRyaWNlc2AsIHRoaXMuX2dsdGYuYWNjZXNzb3JzLCBza2luLmludmVyc2VCaW5kTWF0cmljZXMpO1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9sb2FkRmxvYXRBY2Nlc3NvckFzeW5jKGAvYWNjZXNzb3JzLyR7YWNjZXNzb3IuaW5kZXh9YCwgYWNjZXNzb3IpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX3VwZGF0ZUJvbmVNYXRyaWNlcyhiYWJ5bG9uU2tlbGV0b246IFNrZWxldG9uLCBpbnZlcnNlQmluZE1hdHJpY2VzRGF0YTogTnVsbGFibGU8RmxvYXQzMkFycmF5Pik6IHZvaWQge1xyXG4gICAgICAgIGZvciAoY29uc3QgYmFieWxvbkJvbmUgb2YgYmFieWxvblNrZWxldG9uLmJvbmVzKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGJhc2VNYXRyaXggPSBNYXRyaXguSWRlbnRpdHkoKTtcclxuICAgICAgICAgICAgY29uc3QgYm9uZUluZGV4ID0gYmFieWxvbkJvbmUuX2luZGV4ITtcclxuICAgICAgICAgICAgaWYgKGludmVyc2VCaW5kTWF0cmljZXNEYXRhICYmIGJvbmVJbmRleCAhPT0gLTEpIHtcclxuICAgICAgICAgICAgICAgIE1hdHJpeC5Gcm9tQXJyYXlUb1JlZihpbnZlcnNlQmluZE1hdHJpY2VzRGF0YSwgYm9uZUluZGV4ICogMTYsIGJhc2VNYXRyaXgpO1xyXG4gICAgICAgICAgICAgICAgYmFzZU1hdHJpeC5pbnZlcnRUb1JlZihiYXNlTWF0cml4KTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgY29uc3QgYmFieWxvblBhcmVudEJvbmUgPSBiYWJ5bG9uQm9uZS5nZXRQYXJlbnQoKTtcclxuICAgICAgICAgICAgaWYgKGJhYnlsb25QYXJlbnRCb25lKSB7XHJcbiAgICAgICAgICAgICAgICBiYXNlTWF0cml4Lm11bHRpcGx5VG9SZWYoYmFieWxvblBhcmVudEJvbmUuZ2V0QWJzb2x1dGVJbnZlcnNlQmluZE1hdHJpeCgpLCBiYXNlTWF0cml4KTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgYmFieWxvbkJvbmUudXBkYXRlTWF0cml4KGJhc2VNYXRyaXgsIGZhbHNlLCBmYWxzZSk7XHJcbiAgICAgICAgICAgIGJhYnlsb25Cb25lLl91cGRhdGVBYnNvbHV0ZUJpbmRNYXRyaWNlcyh1bmRlZmluZWQsIGZhbHNlKTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfZ2V0Tm9kZU1hdHJpeChub2RlOiBJTm9kZSk6IE1hdHJpeCB7XHJcbiAgICAgICAgcmV0dXJuIG5vZGUubWF0cml4XHJcbiAgICAgICAgICAgID8gTWF0cml4LkZyb21BcnJheShub2RlLm1hdHJpeClcclxuICAgICAgICAgICAgOiBNYXRyaXguQ29tcG9zZShcclxuICAgICAgICAgICAgICAgICAgbm9kZS5zY2FsZSA/IFZlY3RvcjMuRnJvbUFycmF5KG5vZGUuc2NhbGUpIDogVmVjdG9yMy5PbmUoKSxcclxuICAgICAgICAgICAgICAgICAgbm9kZS5yb3RhdGlvbiA/IFF1YXRlcm5pb24uRnJvbUFycmF5KG5vZGUucm90YXRpb24pIDogUXVhdGVybmlvbi5JZGVudGl0eSgpLFxyXG4gICAgICAgICAgICAgICAgICBub2RlLnRyYW5zbGF0aW9uID8gVmVjdG9yMy5Gcm9tQXJyYXkobm9kZS50cmFuc2xhdGlvbikgOiBWZWN0b3IzLlplcm8oKVxyXG4gICAgICAgICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBMb2FkcyBhIGdsVEYgY2FtZXJhLlxyXG4gICAgICogQHBhcmFtIGNvbnRleHQgVGhlIGNvbnRleHQgd2hlbiBsb2FkaW5nIHRoZSBhc3NldFxyXG4gICAgICogQHBhcmFtIGNhbWVyYSBUaGUgZ2xURiBjYW1lcmEgcHJvcGVydHlcclxuICAgICAqIEBwYXJhbSBhc3NpZ24gQSBmdW5jdGlvbiBjYWxsZWQgc3luY2hyb25vdXNseSBhZnRlciBwYXJzaW5nIHRoZSBnbFRGIHByb3BlcnRpZXNcclxuICAgICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGxvYWRlZCBCYWJ5bG9uIGNhbWVyYSB3aGVuIHRoZSBsb2FkIGlzIGNvbXBsZXRlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkQ2FtZXJhQXN5bmMoY29udGV4dDogc3RyaW5nLCBjYW1lcmE6IElDYW1lcmEsIGFzc2lnbjogKGJhYnlsb25DYW1lcmE6IENhbWVyYSkgPT4gdm9pZCA9ICgpID0+IHt9KTogUHJvbWlzZTxDYW1lcmE+IHtcclxuICAgICAgICBjb25zdCBleHRlbnNpb25Qcm9taXNlID0gdGhpcy5fZXh0ZW5zaW9uc0xvYWRDYW1lcmFBc3luYyhjb250ZXh0LCBjYW1lcmEsIGFzc2lnbik7XHJcbiAgICAgICAgaWYgKGV4dGVuc2lvblByb21pc2UpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGV4dGVuc2lvblByb21pc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBwcm9taXNlcyA9IG5ldyBBcnJheTxQcm9taXNlPGFueT4+KCk7XHJcblxyXG4gICAgICAgIHRoaXMubG9nT3BlbihgJHtjb250ZXh0fSAke2NhbWVyYS5uYW1lIHx8IFwiXCJ9YCk7XHJcblxyXG4gICAgICAgIHRoaXMuX2JhYnlsb25TY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gISF0aGlzLl9hc3NldENvbnRhaW5lcjtcclxuICAgICAgICBjb25zdCBiYWJ5bG9uQ2FtZXJhID0gbmV3IEZyZWVDYW1lcmEoY2FtZXJhLm5hbWUgfHwgYGNhbWVyYSR7Y2FtZXJhLmluZGV4fWAsIFZlY3RvcjMuWmVybygpLCB0aGlzLl9iYWJ5bG9uU2NlbmUsIGZhbHNlKTtcclxuICAgICAgICBiYWJ5bG9uQ2FtZXJhLl9wYXJlbnRDb250YWluZXIgPSB0aGlzLl9hc3NldENvbnRhaW5lcjtcclxuICAgICAgICB0aGlzLl9iYWJ5bG9uU2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9IGZhbHNlO1xyXG4gICAgICAgIGJhYnlsb25DYW1lcmEuaWdub3JlUGFyZW50U2NhbGluZyA9IHRydWU7XHJcbiAgICAgICAgY2FtZXJhLl9iYWJ5bG9uQ2FtZXJhID0gYmFieWxvbkNhbWVyYTtcclxuXHJcbiAgICAgICAgYmFieWxvbkNhbWVyYS5yb3RhdGlvbiA9IG5ldyBWZWN0b3IzKDAsIE1hdGguUEksIDApO1xyXG5cclxuICAgICAgICBzd2l0Y2ggKGNhbWVyYS50eXBlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgQ2FtZXJhVHlwZS5QRVJTUEVDVElWRToge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgcGVyc3BlY3RpdmUgPSBjYW1lcmEucGVyc3BlY3RpdmU7XHJcbiAgICAgICAgICAgICAgICBpZiAoIXBlcnNwZWN0aXZlKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBDYW1lcmEgcGVyc3BlY3RpdmUgcHJvcGVydGllcyBhcmUgbWlzc2luZ2ApO1xyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGJhYnlsb25DYW1lcmEuZm92ID0gcGVyc3BlY3RpdmUueWZvdjtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25DYW1lcmEubWluWiA9IHBlcnNwZWN0aXZlLnpuZWFyO1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbkNhbWVyYS5tYXhaID0gcGVyc3BlY3RpdmUuemZhciB8fCAwO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2FzZSBDYW1lcmFUeXBlLk9SVEhPR1JBUEhJQzoge1xyXG4gICAgICAgICAgICAgICAgaWYgKCFjYW1lcmEub3J0aG9ncmFwaGljKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBDYW1lcmEgb3J0aG9ncmFwaGljIHByb3BlcnRpZXMgYXJlIG1pc3NpbmdgKTtcclxuICAgICAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uQ2FtZXJhLm1vZGUgPSBDYW1lcmEuT1JUSE9HUkFQSElDX0NBTUVSQTtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25DYW1lcmEub3J0aG9MZWZ0ID0gLWNhbWVyYS5vcnRob2dyYXBoaWMueG1hZztcclxuICAgICAgICAgICAgICAgIGJhYnlsb25DYW1lcmEub3J0aG9SaWdodCA9IGNhbWVyYS5vcnRob2dyYXBoaWMueG1hZztcclxuICAgICAgICAgICAgICAgIGJhYnlsb25DYW1lcmEub3J0aG9Cb3R0b20gPSAtY2FtZXJhLm9ydGhvZ3JhcGhpYy55bWFnO1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbkNhbWVyYS5vcnRob1RvcCA9IGNhbWVyYS5vcnRob2dyYXBoaWMueW1hZztcclxuICAgICAgICAgICAgICAgIGJhYnlsb25DYW1lcmEubWluWiA9IGNhbWVyYS5vcnRob2dyYXBoaWMuem5lYXI7XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uQ2FtZXJhLm1heFogPSBjYW1lcmEub3J0aG9ncmFwaGljLnpmYXI7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBkZWZhdWx0OiB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29udGV4dH06IEludmFsaWQgY2FtZXJhIHR5cGUgKCR7Y2FtZXJhLnR5cGV9KWApO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBHTFRGTG9hZGVyLkFkZFBvaW50ZXJNZXRhZGF0YShiYWJ5bG9uQ2FtZXJhLCBjb250ZXh0KTtcclxuICAgICAgICB0aGlzLl9wYXJlbnQub25DYW1lcmFMb2FkZWRPYnNlcnZhYmxlLm5vdGlmeU9ic2VydmVycyhiYWJ5bG9uQ2FtZXJhKTtcclxuICAgICAgICBhc3NpZ24oYmFieWxvbkNhbWVyYSk7XHJcblxyXG4gICAgICAgIHRoaXMubG9nQ2xvc2UoKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UuYWxsKHByb21pc2VzKS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgcmV0dXJuIGJhYnlsb25DYW1lcmE7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZEFuaW1hdGlvbnNBc3luYygpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBjb25zdCBhbmltYXRpb25zID0gdGhpcy5fZ2x0Zi5hbmltYXRpb25zO1xyXG4gICAgICAgIGlmICghYW5pbWF0aW9ucykge1xyXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBwcm9taXNlcyA9IG5ldyBBcnJheTxQcm9taXNlPHZvaWQ+PigpO1xyXG5cclxuICAgICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgYW5pbWF0aW9ucy5sZW5ndGg7IGluZGV4KyspIHtcclxuICAgICAgICAgICAgY29uc3QgYW5pbWF0aW9uID0gYW5pbWF0aW9uc1tpbmRleF07XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRBbmltYXRpb25Bc3luYyhgL2FuaW1hdGlvbnMvJHthbmltYXRpb24uaW5kZXh9YCwgYW5pbWF0aW9uKS50aGVuKChhbmltYXRpb25Hcm91cCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIC8vIERlbGV0ZSB0aGUgYW5pbWF0aW9uIGdyb3VwIGlmIGl0IGVuZGVkIHVwIG5vdCBoYXZpbmcgYW55IGFuaW1hdGlvbnMgaW4gaXQuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFuaW1hdGlvbkdyb3VwLnRhcmdldGVkQW5pbWF0aW9ucy5sZW5ndGggPT09IDApIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYW5pbWF0aW9uR3JvdXAuZGlzcG9zZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge30pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTG9hZHMgYSBnbFRGIGFuaW1hdGlvbi5cclxuICAgICAqIEBwYXJhbSBjb250ZXh0IFRoZSBjb250ZXh0IHdoZW4gbG9hZGluZyB0aGUgYXNzZXRcclxuICAgICAqIEBwYXJhbSBhbmltYXRpb24gVGhlIGdsVEYgYW5pbWF0aW9uIHByb3BlcnR5XHJcbiAgICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBsb2FkZWQgQmFieWxvbiBhbmltYXRpb24gZ3JvdXAgd2hlbiB0aGUgbG9hZCBpcyBjb21wbGV0ZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZEFuaW1hdGlvbkFzeW5jKGNvbnRleHQ6IHN0cmluZywgYW5pbWF0aW9uOiBJQW5pbWF0aW9uKTogUHJvbWlzZTxBbmltYXRpb25Hcm91cD4ge1xyXG4gICAgICAgIGNvbnN0IHByb21pc2UgPSB0aGlzLl9leHRlbnNpb25zTG9hZEFuaW1hdGlvbkFzeW5jKGNvbnRleHQsIGFuaW1hdGlvbik7XHJcbiAgICAgICAgaWYgKHByb21pc2UpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHByb21pc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLl9iYWJ5bG9uU2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9ICEhdGhpcy5fYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgY29uc3QgYmFieWxvbkFuaW1hdGlvbkdyb3VwID0gbmV3IEFuaW1hdGlvbkdyb3VwKGFuaW1hdGlvbi5uYW1lIHx8IGBhbmltYXRpb24ke2FuaW1hdGlvbi5pbmRleH1gLCB0aGlzLl9iYWJ5bG9uU2NlbmUpO1xyXG4gICAgICAgIGJhYnlsb25BbmltYXRpb25Hcm91cC5fcGFyZW50Q29udGFpbmVyID0gdGhpcy5fYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgdGhpcy5fYmFieWxvblNjZW5lLl9ibG9ja0VudGl0eUNvbGxlY3Rpb24gPSBmYWxzZTtcclxuICAgICAgICBhbmltYXRpb24uX2JhYnlsb25BbmltYXRpb25Hcm91cCA9IGJhYnlsb25BbmltYXRpb25Hcm91cDtcclxuXHJcbiAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBuZXcgQXJyYXk8UHJvbWlzZTxhbnk+PigpO1xyXG5cclxuICAgICAgICBBcnJheUl0ZW0uQXNzaWduKGFuaW1hdGlvbi5jaGFubmVscyk7XHJcbiAgICAgICAgQXJyYXlJdGVtLkFzc2lnbihhbmltYXRpb24uc2FtcGxlcnMpO1xyXG5cclxuICAgICAgICBmb3IgKGNvbnN0IGNoYW5uZWwgb2YgYW5pbWF0aW9uLmNoYW5uZWxzKSB7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2FkQW5pbWF0aW9uQ2hhbm5lbEFzeW5jKGAke2NvbnRleHR9L2NoYW5uZWxzLyR7Y2hhbm5lbC5pbmRleH1gLCBjb250ZXh0LCBhbmltYXRpb24sIGNoYW5uZWwsIChiYWJ5bG9uVGFyZ2V0LCBiYWJ5bG9uQW5pbWF0aW9uKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgYmFieWxvblRhcmdldC5hbmltYXRpb25zID0gYmFieWxvblRhcmdldC5hbmltYXRpb25zIHx8IFtdO1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25UYXJnZXQuYW5pbWF0aW9ucy5wdXNoKGJhYnlsb25BbmltYXRpb24pO1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25BbmltYXRpb25Hcm91cC5hZGRUYXJnZXRlZEFuaW1hdGlvbihiYWJ5bG9uQW5pbWF0aW9uLCBiYWJ5bG9uVGFyZ2V0KTtcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICBiYWJ5bG9uQW5pbWF0aW9uR3JvdXAubm9ybWFsaXplKDApO1xyXG4gICAgICAgICAgICByZXR1cm4gYmFieWxvbkFuaW1hdGlvbkdyb3VwO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGhpZGRlblxyXG4gICAgICogTG9hZHMgYSBnbFRGIGFuaW1hdGlvbiBjaGFubmVsLlxyXG4gICAgICogQHBhcmFtIGNvbnRleHQgVGhlIGNvbnRleHQgd2hlbiBsb2FkaW5nIHRoZSBhc3NldFxyXG4gICAgICogQHBhcmFtIGFuaW1hdGlvbkNvbnRleHQgVGhlIGNvbnRleHQgb2YgdGhlIGFuaW1hdGlvbiB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gYW5pbWF0aW9uIFRoZSBnbFRGIGFuaW1hdGlvbiBwcm9wZXJ0eVxyXG4gICAgICogQHBhcmFtIGNoYW5uZWwgVGhlIGdsVEYgYW5pbWF0aW9uIGNoYW5uZWwgcHJvcGVydHlcclxuICAgICAqIEBwYXJhbSBvbkxvYWQgQ2FsbGVkIGZvciBlYWNoIGFuaW1hdGlvbiBsb2FkZWRcclxuICAgICAqIEByZXR1cm5zIEEgdm9pZCBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgbG9hZCBpcyBjb21wbGV0ZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgX2xvYWRBbmltYXRpb25DaGFubmVsQXN5bmMoXHJcbiAgICAgICAgY29udGV4dDogc3RyaW5nLFxyXG4gICAgICAgIGFuaW1hdGlvbkNvbnRleHQ6IHN0cmluZyxcclxuICAgICAgICBhbmltYXRpb246IElBbmltYXRpb24sXHJcbiAgICAgICAgY2hhbm5lbDogSUFuaW1hdGlvbkNoYW5uZWwsXHJcbiAgICAgICAgb25Mb2FkOiAoYmFieWxvbkFuaW1hdGFibGU6IElBbmltYXRhYmxlLCBiYWJ5bG9uQW5pbWF0aW9uOiBBbmltYXRpb24pID0+IHZvaWRcclxuICAgICk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIGNvbnN0IHByb21pc2UgPSB0aGlzLl9leHRlbnNpb25zTG9hZEFuaW1hdGlvbkNoYW5uZWxBc3luYyhjb250ZXh0LCBhbmltYXRpb25Db250ZXh0LCBhbmltYXRpb24sIGNoYW5uZWwsIG9uTG9hZCk7XHJcbiAgICAgICAgaWYgKHByb21pc2UpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHByb21pc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoY2hhbm5lbC50YXJnZXQubm9kZSA9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgdGFyZ2V0Tm9kZSA9IEFycmF5SXRlbS5HZXQoYCR7Y29udGV4dH0vdGFyZ2V0L25vZGVgLCB0aGlzLl9nbHRmLm5vZGVzLCBjaGFubmVsLnRhcmdldC5ub2RlKTtcclxuXHJcbiAgICAgICAgLy8gSWdub3JlIGFuaW1hdGlvbnMgdGhhdCBoYXZlIG5vIGFuaW1hdGlvbiB0YXJnZXRzLlxyXG4gICAgICAgIGlmIChcclxuICAgICAgICAgICAgKGNoYW5uZWwudGFyZ2V0LnBhdGggPT09IEFuaW1hdGlvbkNoYW5uZWxUYXJnZXRQYXRoLldFSUdIVFMgJiYgIXRhcmdldE5vZGUuX251bU1vcnBoVGFyZ2V0cykgfHxcclxuICAgICAgICAgICAgKGNoYW5uZWwudGFyZ2V0LnBhdGggIT09IEFuaW1hdGlvbkNoYW5uZWxUYXJnZXRQYXRoLldFSUdIVFMgJiYgIXRhcmdldE5vZGUuX2JhYnlsb25UcmFuc2Zvcm1Ob2RlKVxyXG4gICAgICAgICkge1xyXG4gICAgICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgcHJvcGVydGllczogQXJyYXk8QW5pbWF0aW9uUHJvcGVydHlJbmZvPjtcclxuICAgICAgICBzd2l0Y2ggKGNoYW5uZWwudGFyZ2V0LnBhdGgpIHtcclxuICAgICAgICAgICAgY2FzZSBBbmltYXRpb25DaGFubmVsVGFyZ2V0UGF0aC5UUkFOU0xBVElPTjoge1xyXG4gICAgICAgICAgICAgICAgcHJvcGVydGllcyA9IG5vZGVBbmltYXRpb25EYXRhLnRyYW5zbGF0aW9uO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2FzZSBBbmltYXRpb25DaGFubmVsVGFyZ2V0UGF0aC5ST1RBVElPTjoge1xyXG4gICAgICAgICAgICAgICAgcHJvcGVydGllcyA9IG5vZGVBbmltYXRpb25EYXRhLnJvdGF0aW9uO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2FzZSBBbmltYXRpb25DaGFubmVsVGFyZ2V0UGF0aC5TQ0FMRToge1xyXG4gICAgICAgICAgICAgICAgcHJvcGVydGllcyA9IG5vZGVBbmltYXRpb25EYXRhLnNjYWxlO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2FzZSBBbmltYXRpb25DaGFubmVsVGFyZ2V0UGF0aC5XRUlHSFRTOiB7XHJcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzID0gbm9kZUFuaW1hdGlvbkRhdGEud2VpZ2h0cztcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGRlZmF1bHQ6IHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fS90YXJnZXQvcGF0aDogSW52YWxpZCB2YWx1ZSAoJHtjaGFubmVsLnRhcmdldC5wYXRofSlgKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgdGFyZ2V0SW5mbzogSUFuaW1hdGlvblRhcmdldEluZm8gPSB7XHJcbiAgICAgICAgICAgIHRhcmdldDogdGFyZ2V0Tm9kZSxcclxuICAgICAgICAgICAgcHJvcGVydGllczogcHJvcGVydGllcyxcclxuICAgICAgICB9O1xyXG5cclxuICAgICAgICByZXR1cm4gdGhpcy5fbG9hZEFuaW1hdGlvbkNoYW5uZWxGcm9tVGFyZ2V0SW5mb0FzeW5jKGNvbnRleHQsIGFuaW1hdGlvbkNvbnRleHQsIGFuaW1hdGlvbiwgY2hhbm5lbCwgdGFyZ2V0SW5mbywgb25Mb2FkKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBoaWRkZW5cclxuICAgICAqIExvYWRzIGEgZ2xURiBhbmltYXRpb24gY2hhbm5lbC5cclxuICAgICAqIEBwYXJhbSBjb250ZXh0IFRoZSBjb250ZXh0IHdoZW4gbG9hZGluZyB0aGUgYXNzZXRcclxuICAgICAqIEBwYXJhbSBhbmltYXRpb25Db250ZXh0IFRoZSBjb250ZXh0IG9mIHRoZSBhbmltYXRpb24gd2hlbiBsb2FkaW5nIHRoZSBhc3NldFxyXG4gICAgICogQHBhcmFtIGFuaW1hdGlvbiBUaGUgZ2xURiBhbmltYXRpb24gcHJvcGVydHlcclxuICAgICAqIEBwYXJhbSBjaGFubmVsIFRoZSBnbFRGIGFuaW1hdGlvbiBjaGFubmVsIHByb3BlcnR5XHJcbiAgICAgKiBAcGFyYW0gdGFyZ2V0SW5mbyBUaGUgZ2xURiB0YXJnZXQgYW5kIHByb3BlcnRpZXNcclxuICAgICAqIEBwYXJhbSBvbkxvYWQgQ2FsbGVkIGZvciBlYWNoIGFuaW1hdGlvbiBsb2FkZWRcclxuICAgICAqIEByZXR1cm5zIEEgdm9pZCBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgbG9hZCBpcyBjb21wbGV0ZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgX2xvYWRBbmltYXRpb25DaGFubmVsRnJvbVRhcmdldEluZm9Bc3luYyhcclxuICAgICAgICBjb250ZXh0OiBzdHJpbmcsXHJcbiAgICAgICAgYW5pbWF0aW9uQ29udGV4dDogc3RyaW5nLFxyXG4gICAgICAgIGFuaW1hdGlvbjogSUFuaW1hdGlvbixcclxuICAgICAgICBjaGFubmVsOiBJQW5pbWF0aW9uQ2hhbm5lbCxcclxuICAgICAgICB0YXJnZXRJbmZvOiBJQW5pbWF0aW9uVGFyZ2V0SW5mbyxcclxuICAgICAgICBvbkxvYWQ6IChiYWJ5bG9uQW5pbWF0YWJsZTogSUFuaW1hdGFibGUsIGJhYnlsb25BbmltYXRpb246IEFuaW1hdGlvbikgPT4gdm9pZFxyXG4gICAgKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgY29uc3QgZnBzID0gdGhpcy5wYXJlbnQudGFyZ2V0RnBzO1xyXG4gICAgICAgIGNvbnN0IGludmZwcyA9IDEgLyBmcHM7XHJcblxyXG4gICAgICAgIGNvbnN0IHNhbXBsZXIgPSBBcnJheUl0ZW0uR2V0KGAke2NvbnRleHR9L3NhbXBsZXJgLCBhbmltYXRpb24uc2FtcGxlcnMsIGNoYW5uZWwuc2FtcGxlcik7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xvYWRBbmltYXRpb25TYW1wbGVyQXN5bmMoYCR7YW5pbWF0aW9uQ29udGV4dH0vc2FtcGxlcnMvJHtjaGFubmVsLnNhbXBsZXJ9YCwgc2FtcGxlcikudGhlbigoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICBsZXQgbnVtQW5pbWF0aW9ucyA9IDA7XHJcblxyXG4gICAgICAgICAgICAvLyBFeHRyYWN0IHRoZSBjb3JyZXNwb25kaW5nIHZhbHVlcyBmcm9tIHRoZSByZWFkIHZhbHVlLlxyXG4gICAgICAgICAgICAvLyBHTFRGIHZhbHVlcyBtYXkgYmUgZGlzcGF0Y2hlZCB0byBzZXZlcmFsIEJhYnlsb24gcHJvcGVydGllcy5cclxuICAgICAgICAgICAgLy8gRm9yIGV4YW1wbGUsIGJhc2VDb2xvckZhY3RvciBbYHJgLCBgZ2AsIGBiYCwgYGFgXSBpcyBkaXNwYXRjaGVkIHRvXHJcbiAgICAgICAgICAgIC8vIC0gYWxiZWRvQ29sb3IgYXMgQ29sb3IzKGByYCwgYGdgLCBgYmApXHJcbiAgICAgICAgICAgIC8vIC0gYWxwaGEgYXMgYGFgXHJcbiAgICAgICAgICAgIGZvciAoY29uc3QgcHJvcGVydHkgb2YgdGFyZ2V0SW5mby5wcm9wZXJ0aWVzKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBzdHJpZGUgPSBwcm9wZXJ0eS5nZXRTdHJpZGUodGFyZ2V0SW5mby50YXJnZXQpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaW5wdXQgPSBkYXRhLmlucHV0O1xyXG4gICAgICAgICAgICAgICAgY29uc3Qgb3V0cHV0ID0gZGF0YS5vdXRwdXQ7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBrZXlzID0gbmV3IEFycmF5PElBbmltYXRpb25LZXk+KGlucHV0Lmxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICBsZXQgb3V0cHV0T2Zmc2V0ID0gMDtcclxuXHJcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKGRhdGEuaW50ZXJwb2xhdGlvbikge1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQW5pbWF0aW9uU2FtcGxlckludGVycG9sYXRpb24uU1RFUDoge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgaW5wdXQubGVuZ3RoOyBpbmRleCsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHByb3BlcnR5LmdldFZhbHVlKHRhcmdldEluZm8udGFyZ2V0LCBvdXRwdXQsIG91dHB1dE9mZnNldCwgMSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRwdXRPZmZzZXQgKz0gc3RyaWRlO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGtleXNbaW5kZXhdID0ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZyYW1lOiBpbnB1dFtpbmRleF0gKiBmcHMsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHZhbHVlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGludGVycG9sYXRpb246IEFuaW1hdGlvbktleUludGVycG9sYXRpb24uU1RFUCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQW5pbWF0aW9uU2FtcGxlckludGVycG9sYXRpb24uQ1VCSUNTUExJTkU6IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGlucHV0Lmxlbmd0aDsgaW5kZXgrKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5UYW5nZW50ID0gcHJvcGVydHkuZ2V0VmFsdWUodGFyZ2V0SW5mby50YXJnZXQsIG91dHB1dCwgb3V0cHV0T2Zmc2V0LCBpbnZmcHMpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0T2Zmc2V0ICs9IHN0cmlkZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gcHJvcGVydHkuZ2V0VmFsdWUodGFyZ2V0SW5mby50YXJnZXQsIG91dHB1dCwgb3V0cHV0T2Zmc2V0LCAxKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG91dHB1dE9mZnNldCArPSBzdHJpZGU7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvdXRUYW5nZW50ID0gcHJvcGVydHkuZ2V0VmFsdWUodGFyZ2V0SW5mby50YXJnZXQsIG91dHB1dCwgb3V0cHV0T2Zmc2V0LCBpbnZmcHMpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0T2Zmc2V0ICs9IHN0cmlkZTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlzW2luZGV4XSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcmFtZTogaW5wdXRbaW5kZXhdICogZnBzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGluVGFuZ2VudDogaW5UYW5nZW50LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvdXRUYW5nZW50OiBvdXRUYW5nZW50LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBbmltYXRpb25TYW1wbGVySW50ZXJwb2xhdGlvbi5MSU5FQVI6IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaW5kZXggPSAwOyBpbmRleCA8IGlucHV0Lmxlbmd0aDsgaW5kZXgrKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBwcm9wZXJ0eS5nZXRWYWx1ZSh0YXJnZXRJbmZvLnRhcmdldCwgb3V0cHV0LCBvdXRwdXRPZmZzZXQsIDEpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb3V0cHV0T2Zmc2V0ICs9IHN0cmlkZTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBrZXlzW2luZGV4XSA9IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmcmFtZTogaW5wdXRbaW5kZXhdICogZnBzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiB2YWx1ZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmIChvdXRwdXRPZmZzZXQgPiAwKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgbmFtZSA9IGAke2FuaW1hdGlvbi5uYW1lIHx8IGBhbmltYXRpb24ke2FuaW1hdGlvbi5pbmRleH1gfV9jaGFubmVsJHtjaGFubmVsLmluZGV4fV8ke251bUFuaW1hdGlvbnN9YDtcclxuICAgICAgICAgICAgICAgICAgICBwcm9wZXJ0eS5idWlsZEFuaW1hdGlvbnModGFyZ2V0SW5mby50YXJnZXQsIG5hbWUsIGZwcywga2V5cywgKGJhYnlsb25BbmltYXRhYmxlLCBiYWJ5bG9uQW5pbWF0aW9uKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICsrbnVtQW5pbWF0aW9ucztcclxuICAgICAgICAgICAgICAgICAgICAgICAgb25Mb2FkKGJhYnlsb25BbmltYXRhYmxlLCBiYWJ5bG9uQW5pbWF0aW9uKTtcclxuICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2xvYWRBbmltYXRpb25TYW1wbGVyQXN5bmMoY29udGV4dDogc3RyaW5nLCBzYW1wbGVyOiBJQW5pbWF0aW9uU2FtcGxlcik6IFByb21pc2U8X0lBbmltYXRpb25TYW1wbGVyRGF0YT4ge1xyXG4gICAgICAgIGlmIChzYW1wbGVyLl9kYXRhKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBzYW1wbGVyLl9kYXRhO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgaW50ZXJwb2xhdGlvbiA9IHNhbXBsZXIuaW50ZXJwb2xhdGlvbiB8fCBBbmltYXRpb25TYW1wbGVySW50ZXJwb2xhdGlvbi5MSU5FQVI7XHJcbiAgICAgICAgc3dpdGNoIChpbnRlcnBvbGF0aW9uKSB7XHJcbiAgICAgICAgICAgIGNhc2UgQW5pbWF0aW9uU2FtcGxlckludGVycG9sYXRpb24uU1RFUDpcclxuICAgICAgICAgICAgY2FzZSBBbmltYXRpb25TYW1wbGVySW50ZXJwb2xhdGlvbi5MSU5FQVI6XHJcbiAgICAgICAgICAgIGNhc2UgQW5pbWF0aW9uU2FtcGxlckludGVycG9sYXRpb24uQ1VCSUNTUExJTkU6IHtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGRlZmF1bHQ6IHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fS9pbnRlcnBvbGF0aW9uOiBJbnZhbGlkIHZhbHVlICgke3NhbXBsZXIuaW50ZXJwb2xhdGlvbn0pYCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGlucHV0QWNjZXNzb3IgPSBBcnJheUl0ZW0uR2V0KGAke2NvbnRleHR9L2lucHV0YCwgdGhpcy5fZ2x0Zi5hY2Nlc3NvcnMsIHNhbXBsZXIuaW5wdXQpO1xyXG4gICAgICAgIGNvbnN0IG91dHB1dEFjY2Vzc29yID0gQXJyYXlJdGVtLkdldChgJHtjb250ZXh0fS9vdXRwdXRgLCB0aGlzLl9nbHRmLmFjY2Vzc29ycywgc2FtcGxlci5vdXRwdXQpO1xyXG4gICAgICAgIHNhbXBsZXIuX2RhdGEgPSBQcm9taXNlLmFsbChbXHJcbiAgICAgICAgICAgIHRoaXMuX2xvYWRGbG9hdEFjY2Vzc29yQXN5bmMoYC9hY2Nlc3NvcnMvJHtpbnB1dEFjY2Vzc29yLmluZGV4fWAsIGlucHV0QWNjZXNzb3IpLFxyXG4gICAgICAgICAgICB0aGlzLl9sb2FkRmxvYXRBY2Nlc3NvckFzeW5jKGAvYWNjZXNzb3JzLyR7b3V0cHV0QWNjZXNzb3IuaW5kZXh9YCwgb3V0cHV0QWNjZXNzb3IpLFxyXG4gICAgICAgIF0pLnRoZW4oKFtpbnB1dERhdGEsIG91dHB1dERhdGFdKSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICBpbnB1dDogaW5wdXREYXRhLFxyXG4gICAgICAgICAgICAgICAgaW50ZXJwb2xhdGlvbjogaW50ZXJwb2xhdGlvbixcclxuICAgICAgICAgICAgICAgIG91dHB1dDogb3V0cHV0RGF0YSxcclxuICAgICAgICAgICAgfTtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHNhbXBsZXIuX2RhdGE7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBMb2FkcyBhIGdsVEYgYnVmZmVyLlxyXG4gICAgICogQHBhcmFtIGNvbnRleHQgVGhlIGNvbnRleHQgd2hlbiBsb2FkaW5nIHRoZSBhc3NldFxyXG4gICAgICogQHBhcmFtIGJ1ZmZlciBUaGUgZ2xURiBidWZmZXIgcHJvcGVydHlcclxuICAgICAqIEBwYXJhbSBieXRlT2Zmc2V0IFRoZSBieXRlIG9mZnNldCB0byB1c2VcclxuICAgICAqIEBwYXJhbSBieXRlTGVuZ3RoIFRoZSBieXRlIGxlbmd0aCB0byB1c2VcclxuICAgICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGxvYWRlZCBkYXRhIHdoZW4gdGhlIGxvYWQgaXMgY29tcGxldGVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRCdWZmZXJBc3luYyhjb250ZXh0OiBzdHJpbmcsIGJ1ZmZlcjogSUJ1ZmZlciwgYnl0ZU9mZnNldDogbnVtYmVyLCBieXRlTGVuZ3RoOiBudW1iZXIpOiBQcm9taXNlPEFycmF5QnVmZmVyVmlldz4ge1xyXG4gICAgICAgIGNvbnN0IGV4dGVuc2lvblByb21pc2UgPSB0aGlzLl9leHRlbnNpb25zTG9hZEJ1ZmZlckFzeW5jKGNvbnRleHQsIGJ1ZmZlciwgYnl0ZU9mZnNldCwgYnl0ZUxlbmd0aCk7XHJcbiAgICAgICAgaWYgKGV4dGVuc2lvblByb21pc2UpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGV4dGVuc2lvblByb21pc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoIWJ1ZmZlci5fZGF0YSkge1xyXG4gICAgICAgICAgICBpZiAoYnVmZmVyLnVyaSkge1xyXG4gICAgICAgICAgICAgICAgYnVmZmVyLl9kYXRhID0gdGhpcy5sb2FkVXJpQXN5bmMoYCR7Y29udGV4dH0vdXJpYCwgYnVmZmVyLCBidWZmZXIudXJpKTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5fYmluKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBVcmkgaXMgbWlzc2luZyBvciB0aGUgYmluYXJ5IGdsVEYgaXMgbWlzc2luZyBpdHMgYmluYXJ5IGNodW5rYCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgYnVmZmVyLl9kYXRhID0gdGhpcy5fYmluLnJlYWRBc3luYygwLCBidWZmZXIuYnl0ZUxlbmd0aCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBidWZmZXIuX2RhdGEudGhlbigoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICB0cnkge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBVaW50OEFycmF5KGRhdGEuYnVmZmVyLCBkYXRhLmJ5dGVPZmZzZXQgKyBieXRlT2Zmc2V0LCBieXRlTGVuZ3RoKTtcclxuICAgICAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiAke2UubWVzc2FnZX1gKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTG9hZHMgYSBnbFRGIGJ1ZmZlciB2aWV3LlxyXG4gICAgICogQHBhcmFtIGNvbnRleHQgVGhlIGNvbnRleHQgd2hlbiBsb2FkaW5nIHRoZSBhc3NldFxyXG4gICAgICogQHBhcmFtIGJ1ZmZlclZpZXcgVGhlIGdsVEYgYnVmZmVyIHZpZXcgcHJvcGVydHlcclxuICAgICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGxvYWRlZCBkYXRhIHdoZW4gdGhlIGxvYWQgaXMgY29tcGxldGVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRCdWZmZXJWaWV3QXN5bmMoY29udGV4dDogc3RyaW5nLCBidWZmZXJWaWV3OiBJQnVmZmVyVmlldyk6IFByb21pc2U8QXJyYXlCdWZmZXJWaWV3PiB7XHJcbiAgICAgICAgY29uc3QgZXh0ZW5zaW9uUHJvbWlzZSA9IHRoaXMuX2V4dGVuc2lvbnNMb2FkQnVmZmVyVmlld0FzeW5jKGNvbnRleHQsIGJ1ZmZlclZpZXcpO1xyXG4gICAgICAgIGlmIChleHRlbnNpb25Qcm9taXNlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBleHRlbnNpb25Qcm9taXNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGJ1ZmZlclZpZXcuX2RhdGEpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGJ1ZmZlclZpZXcuX2RhdGE7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBidWZmZXIgPSBBcnJheUl0ZW0uR2V0KGAke2NvbnRleHR9L2J1ZmZlcmAsIHRoaXMuX2dsdGYuYnVmZmVycywgYnVmZmVyVmlldy5idWZmZXIpO1xyXG4gICAgICAgIGJ1ZmZlclZpZXcuX2RhdGEgPSB0aGlzLmxvYWRCdWZmZXJBc3luYyhgL2J1ZmZlcnMvJHtidWZmZXIuaW5kZXh9YCwgYnVmZmVyLCBidWZmZXJWaWV3LmJ5dGVPZmZzZXQgfHwgMCwgYnVmZmVyVmlldy5ieXRlTGVuZ3RoKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIGJ1ZmZlclZpZXcuX2RhdGE7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZEFjY2Vzc29yQXN5bmMoY29udGV4dDogc3RyaW5nLCBhY2Nlc3NvcjogSUFjY2Vzc29yLCBjb25zdHJ1Y3RvcjogVHlwZWRBcnJheUNvbnN0cnVjdG9yKTogUHJvbWlzZTxBcnJheUJ1ZmZlclZpZXc+IHtcclxuICAgICAgICBpZiAoYWNjZXNzb3IuX2RhdGEpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGFjY2Vzc29yLl9kYXRhO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgbnVtQ29tcG9uZW50cyA9IEdMVEZMb2FkZXIuX0dldE51bUNvbXBvbmVudHMoY29udGV4dCwgYWNjZXNzb3IudHlwZSk7XHJcbiAgICAgICAgY29uc3QgYnl0ZVN0cmlkZSA9IG51bUNvbXBvbmVudHMgKiBWZXJ0ZXhCdWZmZXIuR2V0VHlwZUJ5dGVMZW5ndGgoYWNjZXNzb3IuY29tcG9uZW50VHlwZSk7XHJcbiAgICAgICAgY29uc3QgbGVuZ3RoID0gbnVtQ29tcG9uZW50cyAqIGFjY2Vzc29yLmNvdW50O1xyXG5cclxuICAgICAgICBpZiAoYWNjZXNzb3IuYnVmZmVyVmlldyA9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgYWNjZXNzb3IuX2RhdGEgPSBQcm9taXNlLnJlc29sdmUobmV3IGNvbnN0cnVjdG9yKGxlbmd0aCkpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlclZpZXcgPSBBcnJheUl0ZW0uR2V0KGAke2NvbnRleHR9L2J1ZmZlclZpZXdgLCB0aGlzLl9nbHRmLmJ1ZmZlclZpZXdzLCBhY2Nlc3Nvci5idWZmZXJWaWV3KTtcclxuICAgICAgICAgICAgYWNjZXNzb3IuX2RhdGEgPSB0aGlzLmxvYWRCdWZmZXJWaWV3QXN5bmMoYC9idWZmZXJWaWV3cy8ke2J1ZmZlclZpZXcuaW5kZXh9YCwgYnVmZmVyVmlldykudGhlbigoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKGFjY2Vzc29yLmNvbXBvbmVudFR5cGUgPT09IEFjY2Vzc29yQ29tcG9uZW50VHlwZS5GTE9BVCAmJiAhYWNjZXNzb3Iubm9ybWFsaXplZCAmJiAoIWJ1ZmZlclZpZXcuYnl0ZVN0cmlkZSB8fCBidWZmZXJWaWV3LmJ5dGVTdHJpZGUgPT09IGJ5dGVTdHJpZGUpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIEdMVEZMb2FkZXIuX0dldFR5cGVkQXJyYXkoY29udGV4dCwgYWNjZXNzb3IuY29tcG9uZW50VHlwZSwgZGF0YSwgYWNjZXNzb3IuYnl0ZU9mZnNldCwgbGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdHlwZWRBcnJheSA9IG5ldyBjb25zdHJ1Y3RvcihsZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgICAgIFZlcnRleEJ1ZmZlci5Gb3JFYWNoKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBkYXRhLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBhY2Nlc3Nvci5ieXRlT2Zmc2V0IHx8IDAsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJ1ZmZlclZpZXcuYnl0ZVN0cmlkZSB8fCBieXRlU3RyaWRlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBudW1Db21wb25lbnRzLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBhY2Nlc3Nvci5jb21wb25lbnRUeXBlLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICB0eXBlZEFycmF5Lmxlbmd0aCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgYWNjZXNzb3Iubm9ybWFsaXplZCB8fCBmYWxzZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgKHZhbHVlLCBpbmRleCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdHlwZWRBcnJheVtpbmRleF0gPSB2YWx1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIHR5cGVkQXJyYXk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKGFjY2Vzc29yLnNwYXJzZSkge1xyXG4gICAgICAgICAgICBjb25zdCBzcGFyc2UgPSBhY2Nlc3Nvci5zcGFyc2U7XHJcbiAgICAgICAgICAgIGFjY2Vzc29yLl9kYXRhID0gYWNjZXNzb3IuX2RhdGEudGhlbigoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdHlwZWRBcnJheSA9IGRhdGEgYXMgVHlwZWRBcnJheUxpa2U7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBpbmRpY2VzQnVmZmVyVmlldyA9IEFycmF5SXRlbS5HZXQoYCR7Y29udGV4dH0vc3BhcnNlL2luZGljZXMvYnVmZmVyVmlld2AsIHRoaXMuX2dsdGYuYnVmZmVyVmlld3MsIHNwYXJzZS5pbmRpY2VzLmJ1ZmZlclZpZXcpO1xyXG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWVzQnVmZmVyVmlldyA9IEFycmF5SXRlbS5HZXQoYCR7Y29udGV4dH0vc3BhcnNlL3ZhbHVlcy9idWZmZXJWaWV3YCwgdGhpcy5fZ2x0Zi5idWZmZXJWaWV3cywgc3BhcnNlLnZhbHVlcy5idWZmZXJWaWV3KTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBQcm9taXNlLmFsbChbXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkQnVmZmVyVmlld0FzeW5jKGAvYnVmZmVyVmlld3MvJHtpbmRpY2VzQnVmZmVyVmlldy5pbmRleH1gLCBpbmRpY2VzQnVmZmVyVmlldyksXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sb2FkQnVmZmVyVmlld0FzeW5jKGAvYnVmZmVyVmlld3MvJHt2YWx1ZXNCdWZmZXJWaWV3LmluZGV4fWAsIHZhbHVlc0J1ZmZlclZpZXcpLFxyXG4gICAgICAgICAgICAgICAgXSkudGhlbigoW2luZGljZXNEYXRhLCB2YWx1ZXNEYXRhXSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGljZXMgPSBHTFRGTG9hZGVyLl9HZXRUeXBlZEFycmF5KFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBgJHtjb250ZXh0fS9zcGFyc2UvaW5kaWNlc2AsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHNwYXJzZS5pbmRpY2VzLmNvbXBvbmVudFR5cGUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGluZGljZXNEYXRhLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBzcGFyc2UuaW5kaWNlcy5ieXRlT2Zmc2V0LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBzcGFyc2UuY291bnRcclxuICAgICAgICAgICAgICAgICAgICApIGFzIEluZGljZXNBcnJheTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3BhcnNlTGVuZ3RoID0gbnVtQ29tcG9uZW50cyAqIHNwYXJzZS5jb3VudDtcclxuICAgICAgICAgICAgICAgICAgICBsZXQgdmFsdWVzOiBUeXBlZEFycmF5TGlrZTtcclxuXHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGFjY2Vzc29yLmNvbXBvbmVudFR5cGUgPT09IEFjY2Vzc29yQ29tcG9uZW50VHlwZS5GTE9BVCAmJiAhYWNjZXNzb3Iubm9ybWFsaXplZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZXMgPSBHTFRGTG9hZGVyLl9HZXRUeXBlZEFycmF5KGAke2NvbnRleHR9L3NwYXJzZS92YWx1ZXNgLCBhY2Nlc3Nvci5jb21wb25lbnRUeXBlLCB2YWx1ZXNEYXRhLCBzcGFyc2UudmFsdWVzLmJ5dGVPZmZzZXQsIHNwYXJzZUxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3Qgc3BhcnNlRGF0YSA9IEdMVEZMb2FkZXIuX0dldFR5cGVkQXJyYXkoYCR7Y29udGV4dH0vc3BhcnNlL3ZhbHVlc2AsIGFjY2Vzc29yLmNvbXBvbmVudFR5cGUsIHZhbHVlc0RhdGEsIHNwYXJzZS52YWx1ZXMuYnl0ZU9mZnNldCwgc3BhcnNlTGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzID0gbmV3IGNvbnN0cnVjdG9yKHNwYXJzZUxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIFZlcnRleEJ1ZmZlci5Gb3JFYWNoKHNwYXJzZURhdGEsIDAsIGJ5dGVTdHJpZGUsIG51bUNvbXBvbmVudHMsIGFjY2Vzc29yLmNvbXBvbmVudFR5cGUsIHZhbHVlcy5sZW5ndGgsIGFjY2Vzc29yLm5vcm1hbGl6ZWQgfHwgZmFsc2UsICh2YWx1ZSwgaW5kZXgpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlc1tpbmRleF0gPSB2YWx1ZTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICBsZXQgdmFsdWVzSW5kZXggPSAwO1xyXG4gICAgICAgICAgICAgICAgICAgIGZvciAobGV0IGluZGljZXNJbmRleCA9IDA7IGluZGljZXNJbmRleCA8IGluZGljZXMubGVuZ3RoOyBpbmRpY2VzSW5kZXgrKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZXQgZGF0YUluZGV4ID0gaW5kaWNlc1tpbmRpY2VzSW5kZXhdICogbnVtQ29tcG9uZW50cztcclxuICAgICAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgY29tcG9uZW50SW5kZXggPSAwOyBjb21wb25lbnRJbmRleCA8IG51bUNvbXBvbmVudHM7IGNvbXBvbmVudEluZGV4KyspIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHR5cGVkQXJyYXlbZGF0YUluZGV4KytdID0gdmFsdWVzW3ZhbHVlc0luZGV4KytdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHlwZWRBcnJheTtcclxuICAgICAgICAgICAgICAgIH0pO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBhY2Nlc3Nvci5fZGF0YTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgX2xvYWRGbG9hdEFjY2Vzc29yQXN5bmMoY29udGV4dDogc3RyaW5nLCBhY2Nlc3NvcjogSUFjY2Vzc29yKTogUHJvbWlzZTxGbG9hdDMyQXJyYXk+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fbG9hZEFjY2Vzc29yQXN5bmMoY29udGV4dCwgYWNjZXNzb3IsIEZsb2F0MzJBcnJheSkgYXMgUHJvbWlzZTxGbG9hdDMyQXJyYXk+O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBfbG9hZEluZGljZXNBY2Nlc3NvckFzeW5jKGNvbnRleHQ6IHN0cmluZywgYWNjZXNzb3I6IElBY2Nlc3Nvcik6IFByb21pc2U8SW5kaWNlc0FycmF5PiB7XHJcbiAgICAgICAgaWYgKGFjY2Vzc29yLnR5cGUgIT09IEFjY2Vzc29yVHlwZS5TQ0FMQVIpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9L3R5cGU6IEludmFsaWQgdmFsdWUgJHthY2Nlc3Nvci50eXBlfWApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKFxyXG4gICAgICAgICAgICBhY2Nlc3Nvci5jb21wb25lbnRUeXBlICE9PSBBY2Nlc3NvckNvbXBvbmVudFR5cGUuVU5TSUdORURfQllURSAmJlxyXG4gICAgICAgICAgICBhY2Nlc3Nvci5jb21wb25lbnRUeXBlICE9PSBBY2Nlc3NvckNvbXBvbmVudFR5cGUuVU5TSUdORURfU0hPUlQgJiZcclxuICAgICAgICAgICAgYWNjZXNzb3IuY29tcG9uZW50VHlwZSAhPT0gQWNjZXNzb3JDb21wb25lbnRUeXBlLlVOU0lHTkVEX0lOVFxyXG4gICAgICAgICkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29udGV4dH0vY29tcG9uZW50VHlwZTogSW52YWxpZCB2YWx1ZSAke2FjY2Vzc29yLmNvbXBvbmVudFR5cGV9YCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoYWNjZXNzb3IuX2RhdGEpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGFjY2Vzc29yLl9kYXRhIGFzIFByb21pc2U8SW5kaWNlc0FycmF5PjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChhY2Nlc3Nvci5zcGFyc2UpIHtcclxuICAgICAgICAgICAgY29uc3QgY29uc3RydWN0b3IgPSBHTFRGTG9hZGVyLl9HZXRUeXBlZEFycmF5Q29uc3RydWN0b3IoYCR7Y29udGV4dH0vY29tcG9uZW50VHlwZWAsIGFjY2Vzc29yLmNvbXBvbmVudFR5cGUpO1xyXG4gICAgICAgICAgICBhY2Nlc3Nvci5fZGF0YSA9IHRoaXMuX2xvYWRBY2Nlc3NvckFzeW5jKGNvbnRleHQsIGFjY2Vzc29yLCBjb25zdHJ1Y3Rvcik7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgY29uc3QgYnVmZmVyVmlldyA9IEFycmF5SXRlbS5HZXQoYCR7Y29udGV4dH0vYnVmZmVyVmlld2AsIHRoaXMuX2dsdGYuYnVmZmVyVmlld3MsIGFjY2Vzc29yLmJ1ZmZlclZpZXcpO1xyXG4gICAgICAgICAgICBhY2Nlc3Nvci5fZGF0YSA9IHRoaXMubG9hZEJ1ZmZlclZpZXdBc3luYyhgL2J1ZmZlclZpZXdzLyR7YnVmZmVyVmlldy5pbmRleH1gLCBidWZmZXJWaWV3KS50aGVuKChkYXRhKSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gR0xURkxvYWRlci5fR2V0VHlwZWRBcnJheShjb250ZXh0LCBhY2Nlc3Nvci5jb21wb25lbnRUeXBlLCBkYXRhLCBhY2Nlc3Nvci5ieXRlT2Zmc2V0LCBhY2Nlc3Nvci5jb3VudCk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGFjY2Vzc29yLl9kYXRhIGFzIFByb21pc2U8SW5kaWNlc0FycmF5PjtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgX2xvYWRWZXJ0ZXhCdWZmZXJWaWV3QXN5bmMoYnVmZmVyVmlldzogSUJ1ZmZlclZpZXcpOiBQcm9taXNlPEJ1ZmZlcj4ge1xyXG4gICAgICAgIGlmIChidWZmZXJWaWV3Ll9iYWJ5bG9uQnVmZmVyKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBidWZmZXJWaWV3Ll9iYWJ5bG9uQnVmZmVyO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgZW5naW5lID0gdGhpcy5fYmFieWxvblNjZW5lLmdldEVuZ2luZSgpO1xyXG4gICAgICAgIGJ1ZmZlclZpZXcuX2JhYnlsb25CdWZmZXIgPSB0aGlzLmxvYWRCdWZmZXJWaWV3QXN5bmMoYC9idWZmZXJWaWV3cy8ke2J1ZmZlclZpZXcuaW5kZXh9YCwgYnVmZmVyVmlldykudGhlbigoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gbmV3IEJ1ZmZlcihlbmdpbmUsIGRhdGEsIGZhbHNlKTtcclxuICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgcmV0dXJuIGJ1ZmZlclZpZXcuX2JhYnlsb25CdWZmZXI7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIF9sb2FkVmVydGV4QWNjZXNzb3JBc3luYyhjb250ZXh0OiBzdHJpbmcsIGFjY2Vzc29yOiBJQWNjZXNzb3IsIGtpbmQ6IHN0cmluZyk6IFByb21pc2U8VmVydGV4QnVmZmVyPiB7XHJcbiAgICAgICAgaWYgKGFjY2Vzc29yLl9iYWJ5bG9uVmVydGV4QnVmZmVyPy5ba2luZF0pIHtcclxuICAgICAgICAgICAgcmV0dXJuIGFjY2Vzc29yLl9iYWJ5bG9uVmVydGV4QnVmZmVyW2tpbmRdO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgaWYgKCFhY2Nlc3Nvci5fYmFieWxvblZlcnRleEJ1ZmZlcikge1xyXG4gICAgICAgICAgICBhY2Nlc3Nvci5fYmFieWxvblZlcnRleEJ1ZmZlciA9IHt9O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgZW5naW5lID0gdGhpcy5fYmFieWxvblNjZW5lLmdldEVuZ2luZSgpO1xyXG5cclxuICAgICAgICBpZiAoYWNjZXNzb3Iuc3BhcnNlIHx8IGFjY2Vzc29yLmJ1ZmZlclZpZXcgPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIGFjY2Vzc29yLl9iYWJ5bG9uVmVydGV4QnVmZmVyW2tpbmRdID0gdGhpcy5fbG9hZEZsb2F0QWNjZXNzb3JBc3luYyhjb250ZXh0LCBhY2Nlc3NvcikudGhlbigoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWZXJ0ZXhCdWZmZXIoZW5naW5lLCBkYXRhLCBraW5kLCBmYWxzZSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGJ1ZmZlclZpZXcgPSBBcnJheUl0ZW0uR2V0KGAke2NvbnRleHR9L2J1ZmZlclZpZXdgLCB0aGlzLl9nbHRmLmJ1ZmZlclZpZXdzLCBhY2Nlc3Nvci5idWZmZXJWaWV3KTtcclxuICAgICAgICAgICAgYWNjZXNzb3IuX2JhYnlsb25WZXJ0ZXhCdWZmZXJba2luZF0gPSB0aGlzLl9sb2FkVmVydGV4QnVmZmVyVmlld0FzeW5jKGJ1ZmZlclZpZXcpLnRoZW4oKGJhYnlsb25CdWZmZXIpID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IG51bUNvbXBvbmVudHMgPSBHTFRGTG9hZGVyLl9HZXROdW1Db21wb25lbnRzKGNvbnRleHQsIGFjY2Vzc29yLnR5cGUpO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIG5ldyBWZXJ0ZXhCdWZmZXIoXHJcbiAgICAgICAgICAgICAgICAgICAgZW5naW5lLFxyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25CdWZmZXIsXHJcbiAgICAgICAgICAgICAgICAgICAga2luZCxcclxuICAgICAgICAgICAgICAgICAgICBmYWxzZSxcclxuICAgICAgICAgICAgICAgICAgICB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgICAgICAgICAgYnVmZmVyVmlldy5ieXRlU3RyaWRlLFxyXG4gICAgICAgICAgICAgICAgICAgIHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgICAgICAgICBhY2Nlc3Nvci5ieXRlT2Zmc2V0LFxyXG4gICAgICAgICAgICAgICAgICAgIG51bUNvbXBvbmVudHMsXHJcbiAgICAgICAgICAgICAgICAgICAgYWNjZXNzb3IuY29tcG9uZW50VHlwZSxcclxuICAgICAgICAgICAgICAgICAgICBhY2Nlc3Nvci5ub3JtYWxpemVkLFxyXG4gICAgICAgICAgICAgICAgICAgIHRydWUsXHJcbiAgICAgICAgICAgICAgICAgICAgdW5kZWZpbmVkLFxyXG4gICAgICAgICAgICAgICAgICAgIHRydWVcclxuICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGFjY2Vzc29yLl9iYWJ5bG9uVmVydGV4QnVmZmVyW2tpbmRdO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2xvYWRNYXRlcmlhbE1ldGFsbGljUm91Z2huZXNzUHJvcGVydGllc0FzeW5jKGNvbnRleHQ6IHN0cmluZywgcHJvcGVydGllczogSU1hdGVyaWFsUGJyTWV0YWxsaWNSb3VnaG5lc3MsIGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBpZiAoIShiYWJ5bG9uTWF0ZXJpYWwgaW5zdGFuY2VvZiBQQlJNYXRlcmlhbCkpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBNYXRlcmlhbCB0eXBlIG5vdCBzdXBwb3J0ZWRgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuXHJcbiAgICAgICAgaWYgKHByb3BlcnRpZXMpIHtcclxuICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMuYmFzZUNvbG9yRmFjdG9yKSB7XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuYWxiZWRvQ29sb3IgPSBDb2xvcjMuRnJvbUFycmF5KHByb3BlcnRpZXMuYmFzZUNvbG9yRmFjdG9yKTtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5hbHBoYSA9IHByb3BlcnRpZXMuYmFzZUNvbG9yRmFjdG9yWzNdO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLmFsYmVkb0NvbG9yID0gQ29sb3IzLldoaXRlKCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5tZXRhbGxpYyA9IHByb3BlcnRpZXMubWV0YWxsaWNGYWN0b3IgPT0gdW5kZWZpbmVkID8gMSA6IHByb3BlcnRpZXMubWV0YWxsaWNGYWN0b3I7XHJcbiAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5yb3VnaG5lc3MgPSBwcm9wZXJ0aWVzLnJvdWdobmVzc0ZhY3RvciA9PSB1bmRlZmluZWQgPyAxIDogcHJvcGVydGllcy5yb3VnaG5lc3NGYWN0b3I7XHJcblxyXG4gICAgICAgICAgICBpZiAocHJvcGVydGllcy5iYXNlQ29sb3JUZXh0dXJlKSB7XHJcbiAgICAgICAgICAgICAgICBwcm9taXNlcy5wdXNoKFxyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMubG9hZFRleHR1cmVJbmZvQXN5bmMoYCR7Y29udGV4dH0vYmFzZUNvbG9yVGV4dHVyZWAsIHByb3BlcnRpZXMuYmFzZUNvbG9yVGV4dHVyZSwgKHRleHR1cmUpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgdGV4dHVyZS5uYW1lID0gYCR7YmFieWxvbk1hdGVyaWFsLm5hbWV9IChCYXNlIENvbG9yKWA7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5hbGJlZG9UZXh0dXJlID0gdGV4dHVyZTtcclxuICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKHByb3BlcnRpZXMubWV0YWxsaWNSb3VnaG5lc3NUZXh0dXJlKSB7XHJcbiAgICAgICAgICAgICAgICBwcm9wZXJ0aWVzLm1ldGFsbGljUm91Z2huZXNzVGV4dHVyZS5ub25Db2xvckRhdGEgPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaChcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLmxvYWRUZXh0dXJlSW5mb0FzeW5jKGAke2NvbnRleHR9L21ldGFsbGljUm91Z2huZXNzVGV4dHVyZWAsIHByb3BlcnRpZXMubWV0YWxsaWNSb3VnaG5lc3NUZXh0dXJlLCAodGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0dXJlLm5hbWUgPSBgJHtiYWJ5bG9uTWF0ZXJpYWwubmFtZX0gKE1ldGFsbGljIFJvdWdobmVzcylgO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwubWV0YWxsaWNUZXh0dXJlID0gdGV4dHVyZTtcclxuICAgICAgICAgICAgICAgICAgICB9KVxyXG4gICAgICAgICAgICAgICAgKTtcclxuXHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwudXNlTWV0YWxsbmVzc0Zyb21NZXRhbGxpY1RleHR1cmVCbHVlID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC51c2VSb3VnaG5lc3NGcm9tTWV0YWxsaWNUZXh0dXJlR3JlZW4gPSB0cnVlO1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLnVzZVJvdWdobmVzc0Zyb21NZXRhbGxpY1RleHR1cmVBbHBoYSA9IGZhbHNlO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge30pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBfbG9hZE1hdGVyaWFsQXN5bmMoXHJcbiAgICAgICAgY29udGV4dDogc3RyaW5nLFxyXG4gICAgICAgIG1hdGVyaWFsOiBJTWF0ZXJpYWwsXHJcbiAgICAgICAgYmFieWxvbk1lc2g6IE51bGxhYmxlPE1lc2g+LFxyXG4gICAgICAgIGJhYnlsb25EcmF3TW9kZTogbnVtYmVyLFxyXG4gICAgICAgIGFzc2lnbjogKGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwpID0+IHZvaWQgPSAoKSA9PiB7fVxyXG4gICAgKTogUHJvbWlzZTxNYXRlcmlhbD4ge1xyXG4gICAgICAgIGNvbnN0IGV4dGVuc2lvblByb21pc2UgPSB0aGlzLl9leHRlbnNpb25zTG9hZE1hdGVyaWFsQXN5bmMoY29udGV4dCwgbWF0ZXJpYWwsIGJhYnlsb25NZXNoLCBiYWJ5bG9uRHJhd01vZGUsIGFzc2lnbik7XHJcbiAgICAgICAgaWYgKGV4dGVuc2lvblByb21pc2UpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGV4dGVuc2lvblByb21pc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBtYXRlcmlhbC5fZGF0YSA9IG1hdGVyaWFsLl9kYXRhIHx8IHt9O1xyXG4gICAgICAgIGxldCBiYWJ5bG9uRGF0YSA9IG1hdGVyaWFsLl9kYXRhW2JhYnlsb25EcmF3TW9kZV07XHJcbiAgICAgICAgaWYgKCFiYWJ5bG9uRGF0YSkge1xyXG4gICAgICAgICAgICB0aGlzLmxvZ09wZW4oYCR7Y29udGV4dH0gJHttYXRlcmlhbC5uYW1lIHx8IFwiXCJ9YCk7XHJcblxyXG4gICAgICAgICAgICBjb25zdCBiYWJ5bG9uTWF0ZXJpYWwgPSB0aGlzLmNyZWF0ZU1hdGVyaWFsKGNvbnRleHQsIG1hdGVyaWFsLCBiYWJ5bG9uRHJhd01vZGUpO1xyXG5cclxuICAgICAgICAgICAgYmFieWxvbkRhdGEgPSB7XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWw6IGJhYnlsb25NYXRlcmlhbCxcclxuICAgICAgICAgICAgICAgIGJhYnlsb25NZXNoZXM6IFtdLFxyXG4gICAgICAgICAgICAgICAgcHJvbWlzZTogdGhpcy5sb2FkTWF0ZXJpYWxQcm9wZXJ0aWVzQXN5bmMoY29udGV4dCwgbWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbCksXHJcbiAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICBtYXRlcmlhbC5fZGF0YVtiYWJ5bG9uRHJhd01vZGVdID0gYmFieWxvbkRhdGE7XHJcblxyXG4gICAgICAgICAgICBHTFRGTG9hZGVyLkFkZFBvaW50ZXJNZXRhZGF0YShiYWJ5bG9uTWF0ZXJpYWwsIGNvbnRleHQpO1xyXG4gICAgICAgICAgICB0aGlzLl9wYXJlbnQub25NYXRlcmlhbExvYWRlZE9ic2VydmFibGUubm90aWZ5T2JzZXJ2ZXJzKGJhYnlsb25NYXRlcmlhbCk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLmxvZ0Nsb3NlKCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoYmFieWxvbk1lc2gpIHtcclxuICAgICAgICAgICAgYmFieWxvbkRhdGEuYmFieWxvbk1lc2hlcy5wdXNoKGJhYnlsb25NZXNoKTtcclxuXHJcbiAgICAgICAgICAgIGJhYnlsb25NZXNoLm9uRGlzcG9zZU9ic2VydmFibGUuYWRkT25jZSgoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBpbmRleCA9IGJhYnlsb25EYXRhLmJhYnlsb25NZXNoZXMuaW5kZXhPZihiYWJ5bG9uTWVzaCk7XHJcbiAgICAgICAgICAgICAgICBpZiAoaW5kZXggIT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYmFieWxvbkRhdGEuYmFieWxvbk1lc2hlcy5zcGxpY2UoaW5kZXgsIDEpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGFzc2lnbihiYWJ5bG9uRGF0YS5iYWJ5bG9uTWF0ZXJpYWwpO1xyXG5cclxuICAgICAgICByZXR1cm4gYmFieWxvbkRhdGEucHJvbWlzZS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgcmV0dXJuIGJhYnlsb25EYXRhLmJhYnlsb25NYXRlcmlhbDtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9jcmVhdGVEZWZhdWx0TWF0ZXJpYWwobmFtZTogc3RyaW5nLCBiYWJ5bG9uRHJhd01vZGU6IG51bWJlcik6IE1hdGVyaWFsIHtcclxuICAgICAgICB0aGlzLl9iYWJ5bG9uU2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9ICEhdGhpcy5fYXNzZXRDb250YWluZXI7XHJcbiAgICAgICAgY29uc3QgYmFieWxvbk1hdGVyaWFsID0gbmV3IFBCUk1hdGVyaWFsKG5hbWUsIHRoaXMuX2JhYnlsb25TY2VuZSk7XHJcbiAgICAgICAgYmFieWxvbk1hdGVyaWFsLl9wYXJlbnRDb250YWluZXIgPSB0aGlzLl9hc3NldENvbnRhaW5lcjtcclxuICAgICAgICB0aGlzLl9iYWJ5bG9uU2NlbmUuX2Jsb2NrRW50aXR5Q29sbGVjdGlvbiA9IGZhbHNlO1xyXG4gICAgICAgIC8vIE1vdmVkIHRvIG1lc2ggc28gdXNlciBjYW4gY2hhbmdlIG1hdGVyaWFscyBvbiBnbHRmIG1lc2hlczogYmFieWxvbk1hdGVyaWFsLnNpZGVPcmllbnRhdGlvbiA9IHRoaXMuX2JhYnlsb25TY2VuZS51c2VSaWdodEhhbmRlZFN5c3RlbSA/IE1hdGVyaWFsLkNvdW50ZXJDbG9ja1dpc2VTaWRlT3JpZW50YXRpb24gOiBNYXRlcmlhbC5DbG9ja1dpc2VTaWRlT3JpZW50YXRpb247XHJcbiAgICAgICAgYmFieWxvbk1hdGVyaWFsLmZpbGxNb2RlID0gYmFieWxvbkRyYXdNb2RlO1xyXG4gICAgICAgIGJhYnlsb25NYXRlcmlhbC5lbmFibGVTcGVjdWxhckFudGlBbGlhc2luZyA9IHRydWU7XHJcbiAgICAgICAgYmFieWxvbk1hdGVyaWFsLnVzZVJhZGlhbmNlT3ZlckFscGhhID0gIXRoaXMuX3BhcmVudC50cmFuc3BhcmVuY3lBc0NvdmVyYWdlO1xyXG4gICAgICAgIGJhYnlsb25NYXRlcmlhbC51c2VTcGVjdWxhck92ZXJBbHBoYSA9ICF0aGlzLl9wYXJlbnQudHJhbnNwYXJlbmN5QXNDb3ZlcmFnZTtcclxuICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwudHJhbnNwYXJlbmN5TW9kZSA9IFBCUk1hdGVyaWFsLlBCUk1BVEVSSUFMX09QQVFVRTtcclxuICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwubWV0YWxsaWMgPSAxO1xyXG4gICAgICAgIGJhYnlsb25NYXRlcmlhbC5yb3VnaG5lc3MgPSAxO1xyXG4gICAgICAgIHJldHVybiBiYWJ5bG9uTWF0ZXJpYWw7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDcmVhdGVzIGEgQmFieWxvbiBtYXRlcmlhbCBmcm9tIGEgZ2xURiBtYXRlcmlhbC5cclxuICAgICAqIEBwYXJhbSBjb250ZXh0IFRoZSBjb250ZXh0IHdoZW4gbG9hZGluZyB0aGUgYXNzZXRcclxuICAgICAqIEBwYXJhbSBtYXRlcmlhbCBUaGUgZ2xURiBtYXRlcmlhbCBwcm9wZXJ0eVxyXG4gICAgICogQHBhcmFtIGJhYnlsb25EcmF3TW9kZSBUaGUgZHJhdyBtb2RlIGZvciB0aGUgQmFieWxvbiBtYXRlcmlhbFxyXG4gICAgICogQHJldHVybnMgVGhlIEJhYnlsb24gbWF0ZXJpYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIGNyZWF0ZU1hdGVyaWFsKGNvbnRleHQ6IHN0cmluZywgbWF0ZXJpYWw6IElNYXRlcmlhbCwgYmFieWxvbkRyYXdNb2RlOiBudW1iZXIpOiBNYXRlcmlhbCB7XHJcbiAgICAgICAgY29uc3QgZXh0ZW5zaW9uUHJvbWlzZSA9IHRoaXMuX2V4dGVuc2lvbnNDcmVhdGVNYXRlcmlhbChjb250ZXh0LCBtYXRlcmlhbCwgYmFieWxvbkRyYXdNb2RlKTtcclxuICAgICAgICBpZiAoZXh0ZW5zaW9uUHJvbWlzZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZXh0ZW5zaW9uUHJvbWlzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IG5hbWUgPSBtYXRlcmlhbC5uYW1lIHx8IGBtYXRlcmlhbCR7bWF0ZXJpYWwuaW5kZXh9YDtcclxuICAgICAgICBjb25zdCBiYWJ5bG9uTWF0ZXJpYWwgPSB0aGlzLl9jcmVhdGVEZWZhdWx0TWF0ZXJpYWwobmFtZSwgYmFieWxvbkRyYXdNb2RlKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIGJhYnlsb25NYXRlcmlhbDtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIExvYWRzIHByb3BlcnRpZXMgZnJvbSBhIGdsVEYgbWF0ZXJpYWwgaW50byBhIEJhYnlsb24gbWF0ZXJpYWwuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gbWF0ZXJpYWwgVGhlIGdsVEYgbWF0ZXJpYWwgcHJvcGVydHlcclxuICAgICAqIEBwYXJhbSBiYWJ5bG9uTWF0ZXJpYWwgVGhlIEJhYnlsb24gbWF0ZXJpYWxcclxuICAgICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGxvYWQgaXMgY29tcGxldGVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRNYXRlcmlhbFByb3BlcnRpZXNBc3luYyhjb250ZXh0OiBzdHJpbmcsIG1hdGVyaWFsOiBJTWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBjb25zdCBleHRlbnNpb25Qcm9taXNlID0gdGhpcy5fZXh0ZW5zaW9uc0xvYWRNYXRlcmlhbFByb3BlcnRpZXNBc3luYyhjb250ZXh0LCBtYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsKTtcclxuICAgICAgICBpZiAoZXh0ZW5zaW9uUHJvbWlzZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZXh0ZW5zaW9uUHJvbWlzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuXHJcbiAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLmxvYWRNYXRlcmlhbEJhc2VQcm9wZXJ0aWVzQXN5bmMoY29udGV4dCwgbWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbCkpO1xyXG5cclxuICAgICAgICBpZiAobWF0ZXJpYWwucGJyTWV0YWxsaWNSb3VnaG5lc3MpIHtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaCh0aGlzLl9sb2FkTWF0ZXJpYWxNZXRhbGxpY1JvdWdobmVzc1Byb3BlcnRpZXNBc3luYyhgJHtjb250ZXh0fS9wYnJNZXRhbGxpY1JvdWdobmVzc2AsIG1hdGVyaWFsLnBick1ldGFsbGljUm91Z2huZXNzLCBiYWJ5bG9uTWF0ZXJpYWwpKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMubG9hZE1hdGVyaWFsQWxwaGFQcm9wZXJ0aWVzKGNvbnRleHQsIG1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWwpO1xyXG5cclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge30pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTG9hZHMgdGhlIG5vcm1hbCwgb2NjbHVzaW9uLCBhbmQgZW1pc3NpdmUgcHJvcGVydGllcyBmcm9tIGEgZ2xURiBtYXRlcmlhbCBpbnRvIGEgQmFieWxvbiBtYXRlcmlhbC5cclxuICAgICAqIEBwYXJhbSBjb250ZXh0IFRoZSBjb250ZXh0IHdoZW4gbG9hZGluZyB0aGUgYXNzZXRcclxuICAgICAqIEBwYXJhbSBtYXRlcmlhbCBUaGUgZ2xURiBtYXRlcmlhbCBwcm9wZXJ0eVxyXG4gICAgICogQHBhcmFtIGJhYnlsb25NYXRlcmlhbCBUaGUgQmFieWxvbiBtYXRlcmlhbFxyXG4gICAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgbG9hZCBpcyBjb21wbGV0ZVxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZE1hdGVyaWFsQmFzZVByb3BlcnRpZXNBc3luYyhjb250ZXh0OiBzdHJpbmcsIG1hdGVyaWFsOiBJTWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICBpZiAoIShiYWJ5bG9uTWF0ZXJpYWwgaW5zdGFuY2VvZiBQQlJNYXRlcmlhbCkpIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBNYXRlcmlhbCB0eXBlIG5vdCBzdXBwb3J0ZWRgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IHByb21pc2VzID0gbmV3IEFycmF5PFByb21pc2U8YW55Pj4oKTtcclxuXHJcbiAgICAgICAgYmFieWxvbk1hdGVyaWFsLmVtaXNzaXZlQ29sb3IgPSBtYXRlcmlhbC5lbWlzc2l2ZUZhY3RvciA/IENvbG9yMy5Gcm9tQXJyYXkobWF0ZXJpYWwuZW1pc3NpdmVGYWN0b3IpIDogbmV3IENvbG9yMygwLCAwLCAwKTtcclxuICAgICAgICBpZiAobWF0ZXJpYWwuZG91YmxlU2lkZWQpIHtcclxuICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLmJhY2tGYWNlQ3VsbGluZyA9IGZhbHNlO1xyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwudHdvU2lkZWRMaWdodGluZyA9IHRydWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAobWF0ZXJpYWwubm9ybWFsVGV4dHVyZSkge1xyXG4gICAgICAgICAgICBtYXRlcmlhbC5ub3JtYWxUZXh0dXJlLm5vbkNvbG9yRGF0YSA9IHRydWU7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRUZXh0dXJlSW5mb0FzeW5jKGAke2NvbnRleHR9L25vcm1hbFRleHR1cmVgLCBtYXRlcmlhbC5ub3JtYWxUZXh0dXJlLCAodGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRleHR1cmUubmFtZSA9IGAke2JhYnlsb25NYXRlcmlhbC5uYW1lfSAoTm9ybWFsKWA7XHJcbiAgICAgICAgICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLmJ1bXBUZXh0dXJlID0gdGV4dHVyZTtcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuaW52ZXJ0Tm9ybWFsTWFwWCA9ICF0aGlzLl9iYWJ5bG9uU2NlbmUudXNlUmlnaHRIYW5kZWRTeXN0ZW07XHJcbiAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5pbnZlcnROb3JtYWxNYXBZID0gdGhpcy5fYmFieWxvblNjZW5lLnVzZVJpZ2h0SGFuZGVkU3lzdGVtO1xyXG4gICAgICAgICAgICBpZiAobWF0ZXJpYWwubm9ybWFsVGV4dHVyZS5zY2FsZSAhPSB1bmRlZmluZWQgJiYgYmFieWxvbk1hdGVyaWFsLmJ1bXBUZXh0dXJlKSB7XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuYnVtcFRleHR1cmUubGV2ZWwgPSBtYXRlcmlhbC5ub3JtYWxUZXh0dXJlLnNjYWxlO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuZm9yY2VJcnJhZGlhbmNlSW5GcmFnbWVudCA9IHRydWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAobWF0ZXJpYWwub2NjbHVzaW9uVGV4dHVyZSkge1xyXG4gICAgICAgICAgICBtYXRlcmlhbC5vY2NsdXNpb25UZXh0dXJlLm5vbkNvbG9yRGF0YSA9IHRydWU7XHJcbiAgICAgICAgICAgIHByb21pc2VzLnB1c2goXHJcbiAgICAgICAgICAgICAgICB0aGlzLmxvYWRUZXh0dXJlSW5mb0FzeW5jKGAke2NvbnRleHR9L29jY2x1c2lvblRleHR1cmVgLCBtYXRlcmlhbC5vY2NsdXNpb25UZXh0dXJlLCAodGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRleHR1cmUubmFtZSA9IGAke2JhYnlsb25NYXRlcmlhbC5uYW1lfSAoT2NjbHVzaW9uKWA7XHJcbiAgICAgICAgICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLmFtYmllbnRUZXh0dXJlID0gdGV4dHVyZTtcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwudXNlQW1iaWVudEluR3JheVNjYWxlID0gdHJ1ZTtcclxuICAgICAgICAgICAgaWYgKG1hdGVyaWFsLm9jY2x1c2lvblRleHR1cmUuc3RyZW5ndGggIT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuYW1iaWVudFRleHR1cmVTdHJlbmd0aCA9IG1hdGVyaWFsLm9jY2x1c2lvblRleHR1cmUuc3RyZW5ndGg7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChtYXRlcmlhbC5lbWlzc2l2ZVRleHR1cmUpIHtcclxuICAgICAgICAgICAgcHJvbWlzZXMucHVzaChcclxuICAgICAgICAgICAgICAgIHRoaXMubG9hZFRleHR1cmVJbmZvQXN5bmMoYCR7Y29udGV4dH0vZW1pc3NpdmVUZXh0dXJlYCwgbWF0ZXJpYWwuZW1pc3NpdmVUZXh0dXJlLCAodGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgIHRleHR1cmUubmFtZSA9IGAke2JhYnlsb25NYXRlcmlhbC5uYW1lfSAoRW1pc3NpdmUpYDtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuZW1pc3NpdmVUZXh0dXJlID0gdGV4dHVyZTtcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5hbGwocHJvbWlzZXMpLnRoZW4oKCkgPT4ge30pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTG9hZHMgdGhlIGFscGhhIHByb3BlcnRpZXMgZnJvbSBhIGdsVEYgbWF0ZXJpYWwgaW50byBhIEJhYnlsb24gbWF0ZXJpYWwuXHJcbiAgICAgKiBNdXN0IGJlIGNhbGxlZCBhZnRlciB0aGUgc2V0dGluZyB0aGUgYWxiZWRvIHRleHR1cmUgb2YgdGhlIEJhYnlsb24gbWF0ZXJpYWwgd2hlbiB0aGUgbWF0ZXJpYWwgaGFzIGFuIGFsYmVkbyB0ZXh0dXJlLlxyXG4gICAgICogQHBhcmFtIGNvbnRleHQgVGhlIGNvbnRleHQgd2hlbiBsb2FkaW5nIHRoZSBhc3NldFxyXG4gICAgICogQHBhcmFtIG1hdGVyaWFsIFRoZSBnbFRGIG1hdGVyaWFsIHByb3BlcnR5XHJcbiAgICAgKiBAcGFyYW0gYmFieWxvbk1hdGVyaWFsIFRoZSBCYWJ5bG9uIG1hdGVyaWFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkTWF0ZXJpYWxBbHBoYVByb3BlcnRpZXMoY29udGV4dDogc3RyaW5nLCBtYXRlcmlhbDogSU1hdGVyaWFsLCBiYWJ5bG9uTWF0ZXJpYWw6IE1hdGVyaWFsKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKCEoYmFieWxvbk1hdGVyaWFsIGluc3RhbmNlb2YgUEJSTWF0ZXJpYWwpKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fTogTWF0ZXJpYWwgdHlwZSBub3Qgc3VwcG9ydGVkYCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBhbHBoYU1vZGUgPSBtYXRlcmlhbC5hbHBoYU1vZGUgfHwgTWF0ZXJpYWxBbHBoYU1vZGUuT1BBUVVFO1xyXG4gICAgICAgIHN3aXRjaCAoYWxwaGFNb2RlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgTWF0ZXJpYWxBbHBoYU1vZGUuT1BBUVVFOiB7XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwudHJhbnNwYXJlbmN5TW9kZSA9IFBCUk1hdGVyaWFsLlBCUk1BVEVSSUFMX09QQVFVRTtcclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNhc2UgTWF0ZXJpYWxBbHBoYU1vZGUuTUFTSzoge1xyXG4gICAgICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsLnRyYW5zcGFyZW5jeU1vZGUgPSBQQlJNYXRlcmlhbC5QQlJNQVRFUklBTF9BTFBIQVRFU1Q7XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwuYWxwaGFDdXRPZmYgPSBtYXRlcmlhbC5hbHBoYUN1dG9mZiA9PSB1bmRlZmluZWQgPyAwLjUgOiBtYXRlcmlhbC5hbHBoYUN1dG9mZjtcclxuICAgICAgICAgICAgICAgIGlmIChiYWJ5bG9uTWF0ZXJpYWwuYWxiZWRvVGV4dHVyZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5hbGJlZG9UZXh0dXJlLmhhc0FscGhhID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGJyZWFrO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIGNhc2UgTWF0ZXJpYWxBbHBoYU1vZGUuQkxFTkQ6IHtcclxuICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC50cmFuc3BhcmVuY3lNb2RlID0gUEJSTWF0ZXJpYWwuUEJSTUFURVJJQUxfQUxQSEFCTEVORDtcclxuICAgICAgICAgICAgICAgIGlmIChiYWJ5bG9uTWF0ZXJpYWwuYWxiZWRvVGV4dHVyZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIGJhYnlsb25NYXRlcmlhbC5hbGJlZG9UZXh0dXJlLmhhc0FscGhhID0gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICBiYWJ5bG9uTWF0ZXJpYWwudXNlQWxwaGFGcm9tQWxiZWRvVGV4dHVyZSA9IHRydWU7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBkZWZhdWx0OiB7XHJcbiAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29udGV4dH0vYWxwaGFNb2RlOiBJbnZhbGlkIHZhbHVlICgke21hdGVyaWFsLmFscGhhTW9kZX0pYCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBMb2FkcyBhIGdsVEYgdGV4dHVyZSBpbmZvLlxyXG4gICAgICogQHBhcmFtIGNvbnRleHQgVGhlIGNvbnRleHQgd2hlbiBsb2FkaW5nIHRoZSBhc3NldFxyXG4gICAgICogQHBhcmFtIHRleHR1cmVJbmZvIFRoZSBnbFRGIHRleHR1cmUgaW5mbyBwcm9wZXJ0eVxyXG4gICAgICogQHBhcmFtIGFzc2lnbiBBIGZ1bmN0aW9uIGNhbGxlZCBzeW5jaHJvbm91c2x5IGFmdGVyIHBhcnNpbmcgdGhlIGdsVEYgcHJvcGVydGllc1xyXG4gICAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgbG9hZGVkIEJhYnlsb24gdGV4dHVyZSB3aGVuIHRoZSBsb2FkIGlzIGNvbXBsZXRlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkVGV4dHVyZUluZm9Bc3luYyhjb250ZXh0OiBzdHJpbmcsIHRleHR1cmVJbmZvOiBJVGV4dHVyZUluZm8sIGFzc2lnbjogKGJhYnlsb25UZXh0dXJlOiBCYXNlVGV4dHVyZSkgPT4gdm9pZCA9ICgpID0+IHt9KTogUHJvbWlzZTxCYXNlVGV4dHVyZT4ge1xyXG4gICAgICAgIGNvbnN0IGV4dGVuc2lvblByb21pc2UgPSB0aGlzLl9leHRlbnNpb25zTG9hZFRleHR1cmVJbmZvQXN5bmMoY29udGV4dCwgdGV4dHVyZUluZm8sIGFzc2lnbik7XHJcbiAgICAgICAgaWYgKGV4dGVuc2lvblByb21pc2UpIHtcclxuICAgICAgICAgICAgcmV0dXJuIGV4dGVuc2lvblByb21pc2U7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLmxvZ09wZW4oYCR7Y29udGV4dH1gKTtcclxuXHJcbiAgICAgICAgaWYgKHRleHR1cmVJbmZvLnRleENvb3JkISA+PSA2KSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fS90ZXhDb29yZDogSW52YWxpZCB2YWx1ZSAoJHt0ZXh0dXJlSW5mby50ZXhDb29yZH0pYCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCB0ZXh0dXJlID0gQXJyYXlJdGVtLkdldChgJHtjb250ZXh0fS9pbmRleGAsIHRoaXMuX2dsdGYudGV4dHVyZXMsIHRleHR1cmVJbmZvLmluZGV4KTtcclxuICAgICAgICB0ZXh0dXJlLl90ZXh0dXJlSW5mbyA9IHRleHR1cmVJbmZvO1xyXG5cclxuICAgICAgICBjb25zdCBwcm9taXNlID0gdGhpcy5fbG9hZFRleHR1cmVBc3luYyhgL3RleHR1cmVzLyR7dGV4dHVyZUluZm8uaW5kZXh9YCwgdGV4dHVyZSwgKGJhYnlsb25UZXh0dXJlKSA9PiB7XHJcbiAgICAgICAgICAgIGJhYnlsb25UZXh0dXJlLmNvb3JkaW5hdGVzSW5kZXggPSB0ZXh0dXJlSW5mby50ZXhDb29yZCB8fCAwO1xyXG4gICAgICAgICAgICBHTFRGTG9hZGVyLkFkZFBvaW50ZXJNZXRhZGF0YShiYWJ5bG9uVGV4dHVyZSwgY29udGV4dCk7XHJcbiAgICAgICAgICAgIHRoaXMuX3BhcmVudC5vblRleHR1cmVMb2FkZWRPYnNlcnZhYmxlLm5vdGlmeU9ic2VydmVycyhiYWJ5bG9uVGV4dHVyZSk7XHJcbiAgICAgICAgICAgIGFzc2lnbihiYWJ5bG9uVGV4dHVyZSk7XHJcbiAgICAgICAgfSk7XHJcblxyXG4gICAgICAgIHRoaXMubG9nQ2xvc2UoKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIHByb21pc2U7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIF9sb2FkVGV4dHVyZUFzeW5jKGNvbnRleHQ6IHN0cmluZywgdGV4dHVyZTogSVRleHR1cmUsIGFzc2lnbjogKGJhYnlsb25UZXh0dXJlOiBCYXNlVGV4dHVyZSkgPT4gdm9pZCA9ICgpID0+IHt9KTogUHJvbWlzZTxCYXNlVGV4dHVyZT4ge1xyXG4gICAgICAgIGNvbnN0IGV4dGVuc2lvblByb21pc2UgPSB0aGlzLl9leHRlbnNpb25zTG9hZFRleHR1cmVBc3luYyhjb250ZXh0LCB0ZXh0dXJlLCBhc3NpZ24pO1xyXG4gICAgICAgIGlmIChleHRlbnNpb25Qcm9taXNlKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBleHRlbnNpb25Qcm9taXNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5sb2dPcGVuKGAke2NvbnRleHR9ICR7dGV4dHVyZS5uYW1lIHx8IFwiXCJ9YCk7XHJcblxyXG4gICAgICAgIGNvbnN0IHNhbXBsZXIgPSB0ZXh0dXJlLnNhbXBsZXIgPT0gdW5kZWZpbmVkID8gR0xURkxvYWRlci5EZWZhdWx0U2FtcGxlciA6IEFycmF5SXRlbS5HZXQoYCR7Y29udGV4dH0vc2FtcGxlcmAsIHRoaXMuX2dsdGYuc2FtcGxlcnMsIHRleHR1cmUuc2FtcGxlcik7XHJcbiAgICAgICAgY29uc3QgaW1hZ2UgPSBBcnJheUl0ZW0uR2V0KGAke2NvbnRleHR9L3NvdXJjZWAsIHRoaXMuX2dsdGYuaW1hZ2VzLCB0ZXh0dXJlLnNvdXJjZSk7XHJcbiAgICAgICAgY29uc3QgcHJvbWlzZSA9IHRoaXMuX2NyZWF0ZVRleHR1cmVBc3luYyhjb250ZXh0LCBzYW1wbGVyLCBpbWFnZSwgYXNzaWduLCB1bmRlZmluZWQsICF0ZXh0dXJlLl90ZXh0dXJlSW5mby5ub25Db2xvckRhdGEpO1xyXG5cclxuICAgICAgICB0aGlzLmxvZ0Nsb3NlKCk7XHJcblxyXG4gICAgICAgIHJldHVybiBwcm9taXNlO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBfY3JlYXRlVGV4dHVyZUFzeW5jKFxyXG4gICAgICAgIGNvbnRleHQ6IHN0cmluZyxcclxuICAgICAgICBzYW1wbGVyOiBJU2FtcGxlcixcclxuICAgICAgICBpbWFnZTogSUltYWdlLFxyXG4gICAgICAgIGFzc2lnbjogKGJhYnlsb25UZXh0dXJlOiBCYXNlVGV4dHVyZSkgPT4gdm9pZCA9ICgpID0+IHt9LFxyXG4gICAgICAgIHRleHR1cmVMb2FkZXJPcHRpb25zPzogYW55LFxyXG4gICAgICAgIHVzZVNSR0JCdWZmZXI/OiBib29sZWFuXHJcbiAgICApOiBQcm9taXNlPEJhc2VUZXh0dXJlPiB7XHJcbiAgICAgICAgY29uc3Qgc2FtcGxlckRhdGEgPSB0aGlzLl9sb2FkU2FtcGxlcihgL3NhbXBsZXJzLyR7c2FtcGxlci5pbmRleH1gLCBzYW1wbGVyKTtcclxuXHJcbiAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBuZXcgQXJyYXk8UHJvbWlzZTxhbnk+PigpO1xyXG5cclxuICAgICAgICBjb25zdCBkZWZlcnJlZCA9IG5ldyBEZWZlcnJlZDx2b2lkPigpO1xyXG4gICAgICAgIHRoaXMuX2JhYnlsb25TY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gISF0aGlzLl9hc3NldENvbnRhaW5lcjtcclxuICAgICAgICBjb25zdCB0ZXh0dXJlQ3JlYXRpb25PcHRpb25zOiBJVGV4dHVyZUNyZWF0aW9uT3B0aW9ucyA9IHtcclxuICAgICAgICAgICAgbm9NaXBtYXA6IHNhbXBsZXJEYXRhLm5vTWlwTWFwcyxcclxuICAgICAgICAgICAgaW52ZXJ0WTogZmFsc2UsXHJcbiAgICAgICAgICAgIHNhbXBsaW5nTW9kZTogc2FtcGxlckRhdGEuc2FtcGxpbmdNb2RlLFxyXG4gICAgICAgICAgICBvbkxvYWQ6ICgpID0+IHtcclxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5fZGlzcG9zZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICBkZWZlcnJlZC5yZXNvbHZlKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIG9uRXJyb3I6IChtZXNzYWdlPzogc3RyaW5nLCBleGNlcHRpb24/OiBhbnkpID0+IHtcclxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5fZGlzcG9zZWQpIHtcclxuICAgICAgICAgICAgICAgICAgICBkZWZlcnJlZC5yZWplY3QobmV3IEVycm9yKGAke2NvbnRleHR9OiAke2V4Y2VwdGlvbiAmJiBleGNlcHRpb24ubWVzc2FnZSA/IGV4Y2VwdGlvbi5tZXNzYWdlIDogbWVzc2FnZSB8fCBcIkZhaWxlZCB0byBsb2FkIHRleHR1cmVcIn1gKSk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIG1pbWVUeXBlOiBpbWFnZS5taW1lVHlwZSxcclxuICAgICAgICAgICAgbG9hZGVyT3B0aW9uczogdGV4dHVyZUxvYWRlck9wdGlvbnMsXHJcbiAgICAgICAgICAgIHVzZVNSR0JCdWZmZXI6ICEhdXNlU1JHQkJ1ZmZlciAmJiB0aGlzLl9wYXJlbnQudXNlU1JHQkJ1ZmZlcnMsXHJcbiAgICAgICAgfTtcclxuICAgICAgICBjb25zdCBiYWJ5bG9uVGV4dHVyZSA9IG5ldyBUZXh0dXJlKG51bGwsIHRoaXMuX2JhYnlsb25TY2VuZSwgdGV4dHVyZUNyZWF0aW9uT3B0aW9ucyk7XHJcbiAgICAgICAgYmFieWxvblRleHR1cmUuX3BhcmVudENvbnRhaW5lciA9IHRoaXMuX2Fzc2V0Q29udGFpbmVyO1xyXG4gICAgICAgIHRoaXMuX2JhYnlsb25TY2VuZS5fYmxvY2tFbnRpdHlDb2xsZWN0aW9uID0gZmFsc2U7XHJcbiAgICAgICAgcHJvbWlzZXMucHVzaChkZWZlcnJlZC5wcm9taXNlKTtcclxuXHJcbiAgICAgICAgcHJvbWlzZXMucHVzaChcclxuICAgICAgICAgICAgdGhpcy5sb2FkSW1hZ2VBc3luYyhgL2ltYWdlcy8ke2ltYWdlLmluZGV4fWAsIGltYWdlKS50aGVuKChkYXRhKSA9PiB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBuYW1lID0gaW1hZ2UudXJpIHx8IGAke3RoaXMuX2ZpbGVOYW1lfSNpbWFnZSR7aW1hZ2UuaW5kZXh9YDtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGRhdGFVcmwgPSBgZGF0YToke3RoaXMuX3VuaXF1ZVJvb3RVcmx9JHtuYW1lfWA7XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uVGV4dHVyZS51cGRhdGVVUkwoZGF0YVVybCwgZGF0YSk7XHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKTtcclxuXHJcbiAgICAgICAgYmFieWxvblRleHR1cmUud3JhcFUgPSBzYW1wbGVyRGF0YS53cmFwVTtcclxuICAgICAgICBiYWJ5bG9uVGV4dHVyZS53cmFwViA9IHNhbXBsZXJEYXRhLndyYXBWO1xyXG4gICAgICAgIGFzc2lnbihiYWJ5bG9uVGV4dHVyZSk7XHJcblxyXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgIHJldHVybiBiYWJ5bG9uVGV4dHVyZTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9sb2FkU2FtcGxlcihjb250ZXh0OiBzdHJpbmcsIHNhbXBsZXI6IElTYW1wbGVyKTogX0lTYW1wbGVyRGF0YSB7XHJcbiAgICAgICAgaWYgKCFzYW1wbGVyLl9kYXRhKSB7XHJcbiAgICAgICAgICAgIHNhbXBsZXIuX2RhdGEgPSB7XHJcbiAgICAgICAgICAgICAgICBub01pcE1hcHM6IHNhbXBsZXIubWluRmlsdGVyID09PSBUZXh0dXJlTWluRmlsdGVyLk5FQVJFU1QgfHwgc2FtcGxlci5taW5GaWx0ZXIgPT09IFRleHR1cmVNaW5GaWx0ZXIuTElORUFSLFxyXG4gICAgICAgICAgICAgICAgc2FtcGxpbmdNb2RlOiBHTFRGTG9hZGVyLl9HZXRUZXh0dXJlU2FtcGxpbmdNb2RlKGNvbnRleHQsIHNhbXBsZXIpLFxyXG4gICAgICAgICAgICAgICAgd3JhcFU6IEdMVEZMb2FkZXIuX0dldFRleHR1cmVXcmFwTW9kZShgJHtjb250ZXh0fS93cmFwU2AsIHNhbXBsZXIud3JhcFMpLFxyXG4gICAgICAgICAgICAgICAgd3JhcFY6IEdMVEZMb2FkZXIuX0dldFRleHR1cmVXcmFwTW9kZShgJHtjb250ZXh0fS93cmFwVGAsIHNhbXBsZXIud3JhcFQpLFxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHNhbXBsZXIuX2RhdGE7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBMb2FkcyBhIGdsVEYgaW1hZ2UuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gaW1hZ2UgVGhlIGdsVEYgaW1hZ2UgcHJvcGVydHlcclxuICAgICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGxvYWRlZCBkYXRhIHdoZW4gdGhlIGxvYWQgaXMgY29tcGxldGVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRJbWFnZUFzeW5jKGNvbnRleHQ6IHN0cmluZywgaW1hZ2U6IElJbWFnZSk6IFByb21pc2U8QXJyYXlCdWZmZXJWaWV3PiB7XHJcbiAgICAgICAgaWYgKCFpbWFnZS5fZGF0YSkge1xyXG4gICAgICAgICAgICB0aGlzLmxvZ09wZW4oYCR7Y29udGV4dH0gJHtpbWFnZS5uYW1lIHx8IFwiXCJ9YCk7XHJcblxyXG4gICAgICAgICAgICBpZiAoaW1hZ2UudXJpKSB7XHJcbiAgICAgICAgICAgICAgICBpbWFnZS5fZGF0YSA9IHRoaXMubG9hZFVyaUFzeW5jKGAke2NvbnRleHR9L3VyaWAsIGltYWdlLCBpbWFnZS51cmkpO1xyXG4gICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgYnVmZmVyVmlldyA9IEFycmF5SXRlbS5HZXQoYCR7Y29udGV4dH0vYnVmZmVyVmlld2AsIHRoaXMuX2dsdGYuYnVmZmVyVmlld3MsIGltYWdlLmJ1ZmZlclZpZXcpO1xyXG4gICAgICAgICAgICAgICAgaW1hZ2UuX2RhdGEgPSB0aGlzLmxvYWRCdWZmZXJWaWV3QXN5bmMoYC9idWZmZXJWaWV3cy8ke2J1ZmZlclZpZXcuaW5kZXh9YCwgYnVmZmVyVmlldyk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHRoaXMubG9nQ2xvc2UoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBpbWFnZS5fZGF0YTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIExvYWRzIGEgZ2xURiB1cmkuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gcHJvcGVydHkgVGhlIGdsVEYgcHJvcGVydHkgYXNzb2NpYXRlZCB3aXRoIHRoZSB1cmlcclxuICAgICAqIEBwYXJhbSB1cmkgVGhlIGJhc2U2NCBvciByZWxhdGl2ZSB1cmlcclxuICAgICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGxvYWRlZCBkYXRhIHdoZW4gdGhlIGxvYWQgaXMgY29tcGxldGVcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRVcmlBc3luYyhjb250ZXh0OiBzdHJpbmcsIHByb3BlcnR5OiBJUHJvcGVydHksIHVyaTogc3RyaW5nKTogUHJvbWlzZTxBcnJheUJ1ZmZlclZpZXc+IHtcclxuICAgICAgICBjb25zdCBleHRlbnNpb25Qcm9taXNlID0gdGhpcy5fZXh0ZW5zaW9uc0xvYWRVcmlBc3luYyhjb250ZXh0LCBwcm9wZXJ0eSwgdXJpKTtcclxuICAgICAgICBpZiAoZXh0ZW5zaW9uUHJvbWlzZSkge1xyXG4gICAgICAgICAgICByZXR1cm4gZXh0ZW5zaW9uUHJvbWlzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghR0xURkxvYWRlci5fVmFsaWRhdGVVcmkodXJpKSkge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYCR7Y29udGV4dH06ICcke3VyaX0nIGlzIGludmFsaWRgKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChJc0Jhc2U2NERhdGFVcmwodXJpKSkge1xyXG4gICAgICAgICAgICBjb25zdCBkYXRhID0gbmV3IFVpbnQ4QXJyYXkoRGVjb2RlQmFzZTY0VXJsVG9CaW5hcnkodXJpKSk7XHJcbiAgICAgICAgICAgIHRoaXMubG9nKGAke2NvbnRleHR9OiBEZWNvZGVkICR7dXJpLnN1YnN0cigwLCA2NCl9Li4uICgke2RhdGEubGVuZ3RofSBieXRlcylgKTtcclxuICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShkYXRhKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMubG9nKGAke2NvbnRleHR9OiBMb2FkaW5nICR7dXJpfWApO1xyXG5cclxuICAgICAgICByZXR1cm4gdGhpcy5fcGFyZW50LnByZXByb2Nlc3NVcmxBc3luYyh0aGlzLl9yb290VXJsICsgdXJpKS50aGVuKCh1cmwpID0+IHtcclxuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX3BhcmVudC5fbG9hZEZpbGUoXHJcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fYmFieWxvblNjZW5lLFxyXG4gICAgICAgICAgICAgICAgICAgIHVybCxcclxuICAgICAgICAgICAgICAgICAgICAoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX2Rpc3Bvc2VkKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmxvZyhgJHtjb250ZXh0fTogTG9hZGVkICR7dXJpfSAoJHsoZGF0YSBhcyBBcnJheUJ1ZmZlcikuYnl0ZUxlbmd0aH0gYnl0ZXMpYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG5ldyBVaW50OEFycmF5KGRhdGEgYXMgQXJyYXlCdWZmZXIpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICAgICAgdHJ1ZSxcclxuICAgICAgICAgICAgICAgICAgICAocmVxdWVzdCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZWplY3QobmV3IExvYWRGaWxlRXJyb3IoYCR7Y29udGV4dH06IEZhaWxlZCB0byBsb2FkICcke3VyaX0nJHtyZXF1ZXN0ID8gXCI6IFwiICsgcmVxdWVzdC5zdGF0dXMgKyBcIiBcIiArIHJlcXVlc3Quc3RhdHVzVGV4dCA6IFwiXCJ9YCwgcmVxdWVzdCkpO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQWRkcyBhIEpTT04gcG9pbnRlciB0byB0aGUgX2ludGVybmFsTWV0YWRhdGEgb2YgdGhlIEJhYnlsb24gb2JqZWN0IGF0IGA8b2JqZWN0Pi5faW50ZXJuYWxNZXRhZGF0YS5nbHRmLnBvaW50ZXJzYC5cclxuICAgICAqIEBwYXJhbSBiYWJ5bG9uT2JqZWN0IHRoZSBCYWJ5bG9uIG9iamVjdCB3aXRoIF9pbnRlcm5hbE1ldGFkYXRhXHJcbiAgICAgKiBAcGFyYW0gcG9pbnRlciB0aGUgSlNPTiBwb2ludGVyXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgQWRkUG9pbnRlck1ldGFkYXRhKGJhYnlsb25PYmplY3Q6IElXaXRoTWV0YWRhdGEsIHBvaW50ZXI6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIGJhYnlsb25PYmplY3QubWV0YWRhdGEgPSBiYWJ5bG9uT2JqZWN0Lm1ldGFkYXRhIHx8IHt9O1xyXG4gICAgICAgIGNvbnN0IG1ldGFkYXRhID0gKGJhYnlsb25PYmplY3QuX2ludGVybmFsTWV0YWRhdGEgPSBiYWJ5bG9uT2JqZWN0Ll9pbnRlcm5hbE1ldGFkYXRhIHx8IHt9KTtcclxuICAgICAgICBjb25zdCBnbHRmID0gKG1ldGFkYXRhLmdsdGYgPSBtZXRhZGF0YS5nbHRmIHx8IHt9KTtcclxuICAgICAgICBjb25zdCBwb2ludGVycyA9IChnbHRmLnBvaW50ZXJzID0gZ2x0Zi5wb2ludGVycyB8fCBbXSk7XHJcbiAgICAgICAgcG9pbnRlcnMucHVzaChwb2ludGVyKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHN0YXRpYyBfR2V0VGV4dHVyZVdyYXBNb2RlKGNvbnRleHQ6IHN0cmluZywgbW9kZTogVGV4dHVyZVdyYXBNb2RlIHwgdW5kZWZpbmVkKTogbnVtYmVyIHtcclxuICAgICAgICAvLyBTZXQgZGVmYXVsdHMgaWYgdW5kZWZpbmVkXHJcbiAgICAgICAgbW9kZSA9IG1vZGUgPT0gdW5kZWZpbmVkID8gVGV4dHVyZVdyYXBNb2RlLlJFUEVBVCA6IG1vZGU7XHJcblxyXG4gICAgICAgIHN3aXRjaCAobW9kZSkge1xyXG4gICAgICAgICAgICBjYXNlIFRleHR1cmVXcmFwTW9kZS5DTEFNUF9UT19FREdFOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFRleHR1cmUuQ0xBTVBfQUREUkVTU01PREU7XHJcbiAgICAgICAgICAgIGNhc2UgVGV4dHVyZVdyYXBNb2RlLk1JUlJPUkVEX1JFUEVBVDpcclxuICAgICAgICAgICAgICAgIHJldHVybiBUZXh0dXJlLk1JUlJPUl9BRERSRVNTTU9ERTtcclxuICAgICAgICAgICAgY2FzZSBUZXh0dXJlV3JhcE1vZGUuUkVQRUFUOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFRleHR1cmUuV1JBUF9BRERSRVNTTU9ERTtcclxuICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgIExvZ2dlci5XYXJuKGAke2NvbnRleHR9OiBJbnZhbGlkIHZhbHVlICgke21vZGV9KWApO1xyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFRleHR1cmUuV1JBUF9BRERSRVNTTU9ERTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdGF0aWMgX0dldFRleHR1cmVTYW1wbGluZ01vZGUoY29udGV4dDogc3RyaW5nLCBzYW1wbGVyOiBJU2FtcGxlcik6IG51bWJlciB7XHJcbiAgICAgICAgLy8gU2V0IGRlZmF1bHRzIGlmIHVuZGVmaW5lZFxyXG4gICAgICAgIGNvbnN0IG1hZ0ZpbHRlciA9IHNhbXBsZXIubWFnRmlsdGVyID09IHVuZGVmaW5lZCA/IFRleHR1cmVNYWdGaWx0ZXIuTElORUFSIDogc2FtcGxlci5tYWdGaWx0ZXI7XHJcbiAgICAgICAgY29uc3QgbWluRmlsdGVyID0gc2FtcGxlci5taW5GaWx0ZXIgPT0gdW5kZWZpbmVkID8gVGV4dHVyZU1pbkZpbHRlci5MSU5FQVJfTUlQTUFQX0xJTkVBUiA6IHNhbXBsZXIubWluRmlsdGVyO1xyXG5cclxuICAgICAgICBpZiAobWFnRmlsdGVyID09PSBUZXh0dXJlTWFnRmlsdGVyLkxJTkVBUikge1xyXG4gICAgICAgICAgICBzd2l0Y2ggKG1pbkZpbHRlcikge1xyXG4gICAgICAgICAgICAgICAgY2FzZSBUZXh0dXJlTWluRmlsdGVyLk5FQVJFU1Q6XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFRleHR1cmUuTElORUFSX05FQVJFU1Q7XHJcbiAgICAgICAgICAgICAgICBjYXNlIFRleHR1cmVNaW5GaWx0ZXIuTElORUFSOlxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBUZXh0dXJlLkxJTkVBUl9MSU5FQVI7XHJcbiAgICAgICAgICAgICAgICBjYXNlIFRleHR1cmVNaW5GaWx0ZXIuTkVBUkVTVF9NSVBNQVBfTkVBUkVTVDpcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gVGV4dHVyZS5MSU5FQVJfTkVBUkVTVF9NSVBORUFSRVNUO1xyXG4gICAgICAgICAgICAgICAgY2FzZSBUZXh0dXJlTWluRmlsdGVyLkxJTkVBUl9NSVBNQVBfTkVBUkVTVDpcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gVGV4dHVyZS5MSU5FQVJfTElORUFSX01JUE5FQVJFU1Q7XHJcbiAgICAgICAgICAgICAgICBjYXNlIFRleHR1cmVNaW5GaWx0ZXIuTkVBUkVTVF9NSVBNQVBfTElORUFSOlxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBUZXh0dXJlLkxJTkVBUl9ORUFSRVNUX01JUExJTkVBUjtcclxuICAgICAgICAgICAgICAgIGNhc2UgVGV4dHVyZU1pbkZpbHRlci5MSU5FQVJfTUlQTUFQX0xJTkVBUjpcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gVGV4dHVyZS5MSU5FQVJfTElORUFSX01JUExJTkVBUjtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLldhcm4oYCR7Y29udGV4dH0vbWluRmlsdGVyOiBJbnZhbGlkIHZhbHVlICgke21pbkZpbHRlcn0pYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFRleHR1cmUuTElORUFSX0xJTkVBUl9NSVBMSU5FQVI7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBpZiAobWFnRmlsdGVyICE9PSBUZXh0dXJlTWFnRmlsdGVyLk5FQVJFU1QpIHtcclxuICAgICAgICAgICAgICAgIExvZ2dlci5XYXJuKGAke2NvbnRleHR9L21hZ0ZpbHRlcjogSW52YWxpZCB2YWx1ZSAoJHttYWdGaWx0ZXJ9KWApO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBzd2l0Y2ggKG1pbkZpbHRlcikge1xyXG4gICAgICAgICAgICAgICAgY2FzZSBUZXh0dXJlTWluRmlsdGVyLk5FQVJFU1Q6XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFRleHR1cmUuTkVBUkVTVF9ORUFSRVNUO1xyXG4gICAgICAgICAgICAgICAgY2FzZSBUZXh0dXJlTWluRmlsdGVyLkxJTkVBUjpcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gVGV4dHVyZS5ORUFSRVNUX0xJTkVBUjtcclxuICAgICAgICAgICAgICAgIGNhc2UgVGV4dHVyZU1pbkZpbHRlci5ORUFSRVNUX01JUE1BUF9ORUFSRVNUOlxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBUZXh0dXJlLk5FQVJFU1RfTkVBUkVTVF9NSVBORUFSRVNUO1xyXG4gICAgICAgICAgICAgICAgY2FzZSBUZXh0dXJlTWluRmlsdGVyLkxJTkVBUl9NSVBNQVBfTkVBUkVTVDpcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gVGV4dHVyZS5ORUFSRVNUX0xJTkVBUl9NSVBORUFSRVNUO1xyXG4gICAgICAgICAgICAgICAgY2FzZSBUZXh0dXJlTWluRmlsdGVyLk5FQVJFU1RfTUlQTUFQX0xJTkVBUjpcclxuICAgICAgICAgICAgICAgICAgICByZXR1cm4gVGV4dHVyZS5ORUFSRVNUX05FQVJFU1RfTUlQTElORUFSO1xyXG4gICAgICAgICAgICAgICAgY2FzZSBUZXh0dXJlTWluRmlsdGVyLkxJTkVBUl9NSVBNQVBfTElORUFSOlxyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBUZXh0dXJlLk5FQVJFU1RfTElORUFSX01JUExJTkVBUjtcclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgICAgICAgICAgTG9nZ2VyLldhcm4oYCR7Y29udGV4dH0vbWluRmlsdGVyOiBJbnZhbGlkIHZhbHVlICgke21pbkZpbHRlcn0pYCk7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFRleHR1cmUuTkVBUkVTVF9ORUFSRVNUX01JUE5FQVJFU1Q7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdGF0aWMgX0dldFR5cGVkQXJyYXlDb25zdHJ1Y3Rvcihjb250ZXh0OiBzdHJpbmcsIGNvbXBvbmVudFR5cGU6IEFjY2Vzc29yQ29tcG9uZW50VHlwZSk6IFR5cGVkQXJyYXlDb25zdHJ1Y3RvciB7XHJcbiAgICAgICAgc3dpdGNoIChjb21wb25lbnRUeXBlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgQWNjZXNzb3JDb21wb25lbnRUeXBlLkJZVEU6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gSW50OEFycmF5O1xyXG4gICAgICAgICAgICBjYXNlIEFjY2Vzc29yQ29tcG9uZW50VHlwZS5VTlNJR05FRF9CWVRFOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFVpbnQ4QXJyYXk7XHJcbiAgICAgICAgICAgIGNhc2UgQWNjZXNzb3JDb21wb25lbnRUeXBlLlNIT1JUOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIEludDE2QXJyYXk7XHJcbiAgICAgICAgICAgIGNhc2UgQWNjZXNzb3JDb21wb25lbnRUeXBlLlVOU0lHTkVEX1NIT1JUOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFVpbnQxNkFycmF5O1xyXG4gICAgICAgICAgICBjYXNlIEFjY2Vzc29yQ29tcG9uZW50VHlwZS5VTlNJR05FRF9JTlQ6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gVWludDMyQXJyYXk7XHJcbiAgICAgICAgICAgIGNhc2UgQWNjZXNzb3JDb21wb25lbnRUeXBlLkZMT0FUOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIEZsb2F0MzJBcnJheTtcclxuICAgICAgICAgICAgZGVmYXVsdDpcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fTogSW52YWxpZCBjb21wb25lbnQgdHlwZSAke2NvbXBvbmVudFR5cGV9YCk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIF9HZXRUeXBlZEFycmF5KFxyXG4gICAgICAgIGNvbnRleHQ6IHN0cmluZyxcclxuICAgICAgICBjb21wb25lbnRUeXBlOiBBY2Nlc3NvckNvbXBvbmVudFR5cGUsXHJcbiAgICAgICAgYnVmZmVyVmlldzogQXJyYXlCdWZmZXJWaWV3LFxyXG4gICAgICAgIGJ5dGVPZmZzZXQ6IG51bWJlciB8IHVuZGVmaW5lZCxcclxuICAgICAgICBsZW5ndGg6IG51bWJlclxyXG4gICAgKTogVHlwZWRBcnJheUxpa2Uge1xyXG4gICAgICAgIGNvbnN0IGJ1ZmZlciA9IGJ1ZmZlclZpZXcuYnVmZmVyO1xyXG4gICAgICAgIGJ5dGVPZmZzZXQgPSBidWZmZXJWaWV3LmJ5dGVPZmZzZXQgKyAoYnl0ZU9mZnNldCB8fCAwKTtcclxuXHJcbiAgICAgICAgY29uc3QgY29uc3RydWN0b3IgPSBHTFRGTG9hZGVyLl9HZXRUeXBlZEFycmF5Q29uc3RydWN0b3IoYCR7Y29udGV4dH0vY29tcG9uZW50VHlwZWAsIGNvbXBvbmVudFR5cGUpO1xyXG5cclxuICAgICAgICBjb25zdCBjb21wb25lbnRUeXBlTGVuZ3RoID0gVmVydGV4QnVmZmVyLkdldFR5cGVCeXRlTGVuZ3RoKGNvbXBvbmVudFR5cGUpO1xyXG4gICAgICAgIGlmIChieXRlT2Zmc2V0ICUgY29tcG9uZW50VHlwZUxlbmd0aCAhPT0gMCkge1xyXG4gICAgICAgICAgICAvLyBIQUNLOiBDb3B5IHRoZSBidWZmZXIgaWYgYnl0ZSBvZmZzZXQgaXMgbm90IGEgbXVsdGlwbGUgb2YgY29tcG9uZW50IHR5cGUgYnl0ZSBsZW5ndGguXHJcbiAgICAgICAgICAgIExvZ2dlci5XYXJuKGAke2NvbnRleHR9OiBDb3B5aW5nIGJ1ZmZlciBhcyBieXRlIG9mZnNldCAoJHtieXRlT2Zmc2V0fSkgaXMgbm90IGEgbXVsdGlwbGUgb2YgY29tcG9uZW50IHR5cGUgYnl0ZSBsZW5ndGggKCR7Y29tcG9uZW50VHlwZUxlbmd0aH0pYCk7XHJcbiAgICAgICAgICAgIHJldHVybiBuZXcgY29uc3RydWN0b3IoYnVmZmVyLnNsaWNlKGJ5dGVPZmZzZXQsIGJ5dGVPZmZzZXQgKyBsZW5ndGggKiBjb21wb25lbnRUeXBlTGVuZ3RoKSwgMCk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gbmV3IGNvbnN0cnVjdG9yKGJ1ZmZlciwgYnl0ZU9mZnNldCwgbGVuZ3RoKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHN0YXRpYyBfR2V0TnVtQ29tcG9uZW50cyhjb250ZXh0OiBzdHJpbmcsIHR5cGU6IHN0cmluZyk6IG51bWJlciB7XHJcbiAgICAgICAgc3dpdGNoICh0eXBlKSB7XHJcbiAgICAgICAgICAgIGNhc2UgXCJTQ0FMQVJcIjpcclxuICAgICAgICAgICAgICAgIHJldHVybiAxO1xyXG4gICAgICAgICAgICBjYXNlIFwiVkVDMlwiOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIDI7XHJcbiAgICAgICAgICAgIGNhc2UgXCJWRUMzXCI6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gMztcclxuICAgICAgICAgICAgY2FzZSBcIlZFQzRcIjpcclxuICAgICAgICAgICAgICAgIHJldHVybiA0O1xyXG4gICAgICAgICAgICBjYXNlIFwiTUFUMlwiOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIDQ7XHJcbiAgICAgICAgICAgIGNhc2UgXCJNQVQzXCI6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gOTtcclxuICAgICAgICAgICAgY2FzZSBcIk1BVDRcIjpcclxuICAgICAgICAgICAgICAgIHJldHVybiAxNjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihgJHtjb250ZXh0fTogSW52YWxpZCB0eXBlICgke3R5cGV9KWApO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIF9WYWxpZGF0ZVVyaSh1cmk6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiBUb29scy5Jc0Jhc2U2NCh1cmkpIHx8IHVyaS5pbmRleE9mKFwiLi5cIikgPT09IC0xO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgX0dldERyYXdNb2RlKGNvbnRleHQ6IHN0cmluZywgbW9kZTogbnVtYmVyIHwgdW5kZWZpbmVkKTogbnVtYmVyIHtcclxuICAgICAgICBpZiAobW9kZSA9PSB1bmRlZmluZWQpIHtcclxuICAgICAgICAgICAgbW9kZSA9IE1lc2hQcmltaXRpdmVNb2RlLlRSSUFOR0xFUztcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHN3aXRjaCAobW9kZSkge1xyXG4gICAgICAgICAgICBjYXNlIE1lc2hQcmltaXRpdmVNb2RlLlBPSU5UUzpcclxuICAgICAgICAgICAgICAgIHJldHVybiBNYXRlcmlhbC5Qb2ludExpc3REcmF3TW9kZTtcclxuICAgICAgICAgICAgY2FzZSBNZXNoUHJpbWl0aXZlTW9kZS5MSU5FUzpcclxuICAgICAgICAgICAgICAgIHJldHVybiBNYXRlcmlhbC5MaW5lTGlzdERyYXdNb2RlO1xyXG4gICAgICAgICAgICBjYXNlIE1lc2hQcmltaXRpdmVNb2RlLkxJTkVfTE9PUDpcclxuICAgICAgICAgICAgICAgIHJldHVybiBNYXRlcmlhbC5MaW5lTG9vcERyYXdNb2RlO1xyXG4gICAgICAgICAgICBjYXNlIE1lc2hQcmltaXRpdmVNb2RlLkxJTkVfU1RSSVA6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gTWF0ZXJpYWwuTGluZVN0cmlwRHJhd01vZGU7XHJcbiAgICAgICAgICAgIGNhc2UgTWVzaFByaW1pdGl2ZU1vZGUuVFJJQU5HTEVTOlxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIE1hdGVyaWFsLlRyaWFuZ2xlRmlsbE1vZGU7XHJcbiAgICAgICAgICAgIGNhc2UgTWVzaFByaW1pdGl2ZU1vZGUuVFJJQU5HTEVfU1RSSVA6XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gTWF0ZXJpYWwuVHJpYW5nbGVTdHJpcERyYXdNb2RlO1xyXG4gICAgICAgICAgICBjYXNlIE1lc2hQcmltaXRpdmVNb2RlLlRSSUFOR0xFX0ZBTjpcclxuICAgICAgICAgICAgICAgIHJldHVybiBNYXRlcmlhbC5UcmlhbmdsZUZhbkRyYXdNb2RlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGAke2NvbnRleHR9OiBJbnZhbGlkIG1lc2ggcHJpbWl0aXZlIG1vZGUgKCR7bW9kZX0pYCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfY29tcGlsZU1hdGVyaWFsc0FzeW5jKCk6IFByb21pc2U8dm9pZD4ge1xyXG4gICAgICAgIHRoaXMuX3BhcmVudC5fc3RhcnRQZXJmb3JtYW5jZUNvdW50ZXIoXCJDb21waWxlIG1hdGVyaWFsc1wiKTtcclxuXHJcbiAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBuZXcgQXJyYXk8UHJvbWlzZTxhbnk+PigpO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5fZ2x0Zi5tYXRlcmlhbHMpIHtcclxuICAgICAgICAgICAgZm9yIChjb25zdCBtYXRlcmlhbCBvZiB0aGlzLl9nbHRmLm1hdGVyaWFscykge1xyXG4gICAgICAgICAgICAgICAgaWYgKG1hdGVyaWFsLl9kYXRhKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBiYWJ5bG9uRHJhd01vZGUgaW4gbWF0ZXJpYWwuX2RhdGEpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYmFieWxvbkRhdGEgPSBtYXRlcmlhbC5fZGF0YVtiYWJ5bG9uRHJhd01vZGVdO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGJhYnlsb25NZXNoIG9mIGJhYnlsb25EYXRhLmJhYnlsb25NZXNoZXMpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIEVuc3VyZSBub25Vbmlmb3JtU2NhbGluZyBpcyBzZXQgaWYgbmVjZXNzYXJ5LlxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYmFieWxvbk1lc2guY29tcHV0ZVdvcmxkTWF0cml4KHRydWUpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGJhYnlsb25NYXRlcmlhbCA9IGJhYnlsb25EYXRhLmJhYnlsb25NYXRlcmlhbDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2goYmFieWxvbk1hdGVyaWFsLmZvcmNlQ29tcGlsYXRpb25Bc3luYyhiYWJ5bG9uTWVzaCkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvbWlzZXMucHVzaChiYWJ5bG9uTWF0ZXJpYWwuZm9yY2VDb21waWxhdGlvbkFzeW5jKGJhYnlsb25NZXNoLCB7IHVzZUluc3RhbmNlczogdHJ1ZSB9KSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5fcGFyZW50LnVzZUNsaXBQbGFuZSkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2goYmFieWxvbk1hdGVyaWFsLmZvcmNlQ29tcGlsYXRpb25Bc3luYyhiYWJ5bG9uTWVzaCwgeyBjbGlwUGxhbmU6IHRydWUgfSkpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHByb21pc2VzLnB1c2goYmFieWxvbk1hdGVyaWFsLmZvcmNlQ29tcGlsYXRpb25Bc3luYyhiYWJ5bG9uTWVzaCwgeyBjbGlwUGxhbmU6IHRydWUsIHVzZUluc3RhbmNlczogdHJ1ZSB9KSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuX3BhcmVudC5fZW5kUGVyZm9ybWFuY2VDb3VudGVyKFwiQ29tcGlsZSBtYXRlcmlhbHNcIik7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfY29tcGlsZVNoYWRvd0dlbmVyYXRvcnNBc3luYygpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICB0aGlzLl9wYXJlbnQuX3N0YXJ0UGVyZm9ybWFuY2VDb3VudGVyKFwiQ29tcGlsZSBzaGFkb3cgZ2VuZXJhdG9yc1wiKTtcclxuXHJcbiAgICAgICAgY29uc3QgcHJvbWlzZXMgPSBuZXcgQXJyYXk8UHJvbWlzZTxhbnk+PigpO1xyXG5cclxuICAgICAgICBjb25zdCBsaWdodHMgPSB0aGlzLl9iYWJ5bG9uU2NlbmUubGlnaHRzO1xyXG4gICAgICAgIGZvciAoY29uc3QgbGlnaHQgb2YgbGlnaHRzKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGdlbmVyYXRvciA9IGxpZ2h0LmdldFNoYWRvd0dlbmVyYXRvcigpO1xyXG4gICAgICAgICAgICBpZiAoZ2VuZXJhdG9yKSB7XHJcbiAgICAgICAgICAgICAgICBwcm9taXNlcy5wdXNoKGdlbmVyYXRvci5mb3JjZUNvbXBpbGF0aW9uQXN5bmMoKSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBQcm9taXNlLmFsbChwcm9taXNlcykudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgIHRoaXMuX3BhcmVudC5fZW5kUGVyZm9ybWFuY2VDb3VudGVyKFwiQ29tcGlsZSBzaGFkb3cgZ2VuZXJhdG9yc1wiKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9mb3JFYWNoRXh0ZW5zaW9ucyhhY3Rpb246IChleHRlbnNpb246IElHTFRGTG9hZGVyRXh0ZW5zaW9uKSA9PiB2b2lkKTogdm9pZCB7XHJcbiAgICAgICAgZm9yIChjb25zdCBleHRlbnNpb24gb2YgdGhpcy5fZXh0ZW5zaW9ucykge1xyXG4gICAgICAgICAgICBpZiAoZXh0ZW5zaW9uLmVuYWJsZWQpIHtcclxuICAgICAgICAgICAgICAgIGFjdGlvbihleHRlbnNpb24pO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2FwcGx5RXh0ZW5zaW9uczxUPihwcm9wZXJ0eTogSVByb3BlcnR5LCBmdW5jdGlvbk5hbWU6IHN0cmluZywgYWN0aW9uQXN5bmM6IChleHRlbnNpb246IElHTFRGTG9hZGVyRXh0ZW5zaW9uKSA9PiBOdWxsYWJsZTxUPiB8IHVuZGVmaW5lZCk6IE51bGxhYmxlPFQ+IHtcclxuICAgICAgICBmb3IgKGNvbnN0IGV4dGVuc2lvbiBvZiB0aGlzLl9leHRlbnNpb25zKSB7XHJcbiAgICAgICAgICAgIGlmIChleHRlbnNpb24uZW5hYmxlZCkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgaWQgPSBgJHtleHRlbnNpb24ubmFtZX0uJHtmdW5jdGlvbk5hbWV9YDtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGxvYWRlclByb3BlcnR5ID0gcHJvcGVydHkgYXMgSUxvYWRlclByb3BlcnR5O1xyXG4gICAgICAgICAgICAgICAgbG9hZGVyUHJvcGVydHkuX2FjdGl2ZUxvYWRlckV4dGVuc2lvbkZ1bmN0aW9ucyA9IGxvYWRlclByb3BlcnR5Ll9hY3RpdmVMb2FkZXJFeHRlbnNpb25GdW5jdGlvbnMgfHwge307XHJcbiAgICAgICAgICAgICAgICBjb25zdCBhY3RpdmVMb2FkZXJFeHRlbnNpb25GdW5jdGlvbnMgPSBsb2FkZXJQcm9wZXJ0eS5fYWN0aXZlTG9hZGVyRXh0ZW5zaW9uRnVuY3Rpb25zO1xyXG4gICAgICAgICAgICAgICAgaWYgKCFhY3RpdmVMb2FkZXJFeHRlbnNpb25GdW5jdGlvbnNbaWRdKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgYWN0aXZlTG9hZGVyRXh0ZW5zaW9uRnVuY3Rpb25zW2lkXSA9IHRydWU7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IGFjdGlvbkFzeW5jKGV4dGVuc2lvbik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyZXN1bHQpIHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9IGZpbmFsbHkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBkZWxldGUgYWN0aXZlTG9hZGVyRXh0ZW5zaW9uRnVuY3Rpb25zW2lkXTtcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2V4dGVuc2lvbnNPbkxvYWRpbmcoKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5fZm9yRWFjaEV4dGVuc2lvbnMoKGV4dGVuc2lvbikgPT4gZXh0ZW5zaW9uLm9uTG9hZGluZyAmJiBleHRlbnNpb24ub25Mb2FkaW5nKCkpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2V4dGVuc2lvbnNPblJlYWR5KCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuX2ZvckVhY2hFeHRlbnNpb25zKChleHRlbnNpb24pID0+IGV4dGVuc2lvbi5vblJlYWR5ICYmIGV4dGVuc2lvbi5vblJlYWR5KCkpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2V4dGVuc2lvbnNMb2FkU2NlbmVBc3luYyhjb250ZXh0OiBzdHJpbmcsIHNjZW5lOiBJU2NlbmUpOiBOdWxsYWJsZTxQcm9taXNlPHZvaWQ+PiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5RXh0ZW5zaW9ucyhzY2VuZSwgXCJsb2FkU2NlbmVcIiwgKGV4dGVuc2lvbikgPT4gZXh0ZW5zaW9uLmxvYWRTY2VuZUFzeW5jICYmIGV4dGVuc2lvbi5sb2FkU2NlbmVBc3luYyhjb250ZXh0LCBzY2VuZSkpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2V4dGVuc2lvbnNMb2FkTm9kZUFzeW5jKGNvbnRleHQ6IHN0cmluZywgbm9kZTogSU5vZGUsIGFzc2lnbjogKGJhYnlsb25UcmFuc2Zvcm1Ob2RlOiBUcmFuc2Zvcm1Ob2RlKSA9PiB2b2lkKTogTnVsbGFibGU8UHJvbWlzZTxUcmFuc2Zvcm1Ob2RlPj4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBseUV4dGVuc2lvbnMobm9kZSwgXCJsb2FkTm9kZVwiLCAoZXh0ZW5zaW9uKSA9PiBleHRlbnNpb24ubG9hZE5vZGVBc3luYyAmJiBleHRlbnNpb24ubG9hZE5vZGVBc3luYyhjb250ZXh0LCBub2RlLCBhc3NpZ24pKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9leHRlbnNpb25zTG9hZENhbWVyYUFzeW5jKGNvbnRleHQ6IHN0cmluZywgY2FtZXJhOiBJQ2FtZXJhLCBhc3NpZ246IChiYWJ5bG9uQ2FtZXJhOiBDYW1lcmEpID0+IHZvaWQpOiBOdWxsYWJsZTxQcm9taXNlPENhbWVyYT4+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlFeHRlbnNpb25zKGNhbWVyYSwgXCJsb2FkQ2FtZXJhXCIsIChleHRlbnNpb24pID0+IGV4dGVuc2lvbi5sb2FkQ2FtZXJhQXN5bmMgJiYgZXh0ZW5zaW9uLmxvYWRDYW1lcmFBc3luYyhjb250ZXh0LCBjYW1lcmEsIGFzc2lnbikpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2V4dGVuc2lvbnNMb2FkVmVydGV4RGF0YUFzeW5jKGNvbnRleHQ6IHN0cmluZywgcHJpbWl0aXZlOiBJTWVzaFByaW1pdGl2ZSwgYmFieWxvbk1lc2g6IE1lc2gpOiBOdWxsYWJsZTxQcm9taXNlPEdlb21ldHJ5Pj4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBseUV4dGVuc2lvbnMocHJpbWl0aXZlLCBcImxvYWRWZXJ0ZXhEYXRhXCIsIChleHRlbnNpb24pID0+IGV4dGVuc2lvbi5fbG9hZFZlcnRleERhdGFBc3luYyAmJiBleHRlbnNpb24uX2xvYWRWZXJ0ZXhEYXRhQXN5bmMoY29udGV4dCwgcHJpbWl0aXZlLCBiYWJ5bG9uTWVzaCkpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2V4dGVuc2lvbnNMb2FkTWVzaFByaW1pdGl2ZUFzeW5jKFxyXG4gICAgICAgIGNvbnRleHQ6IHN0cmluZyxcclxuICAgICAgICBuYW1lOiBzdHJpbmcsXHJcbiAgICAgICAgbm9kZTogSU5vZGUsXHJcbiAgICAgICAgbWVzaDogSU1lc2gsXHJcbiAgICAgICAgcHJpbWl0aXZlOiBJTWVzaFByaW1pdGl2ZSxcclxuICAgICAgICBhc3NpZ246IChiYWJ5bG9uTWVzaDogQWJzdHJhY3RNZXNoKSA9PiB2b2lkXHJcbiAgICApOiBOdWxsYWJsZTxQcm9taXNlPEFic3RyYWN0TWVzaD4+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlFeHRlbnNpb25zKFxyXG4gICAgICAgICAgICBwcmltaXRpdmUsXHJcbiAgICAgICAgICAgIFwibG9hZE1lc2hQcmltaXRpdmVcIixcclxuICAgICAgICAgICAgKGV4dGVuc2lvbikgPT4gZXh0ZW5zaW9uLl9sb2FkTWVzaFByaW1pdGl2ZUFzeW5jICYmIGV4dGVuc2lvbi5fbG9hZE1lc2hQcmltaXRpdmVBc3luYyhjb250ZXh0LCBuYW1lLCBub2RlLCBtZXNoLCBwcmltaXRpdmUsIGFzc2lnbilcclxuICAgICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2V4dGVuc2lvbnNMb2FkTWF0ZXJpYWxBc3luYyhcclxuICAgICAgICBjb250ZXh0OiBzdHJpbmcsXHJcbiAgICAgICAgbWF0ZXJpYWw6IElNYXRlcmlhbCxcclxuICAgICAgICBiYWJ5bG9uTWVzaDogTnVsbGFibGU8TWVzaD4sXHJcbiAgICAgICAgYmFieWxvbkRyYXdNb2RlOiBudW1iZXIsXHJcbiAgICAgICAgYXNzaWduOiAoYmFieWxvbk1hdGVyaWFsOiBNYXRlcmlhbCkgPT4gdm9pZFxyXG4gICAgKTogTnVsbGFibGU8UHJvbWlzZTxNYXRlcmlhbD4+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlFeHRlbnNpb25zKFxyXG4gICAgICAgICAgICBtYXRlcmlhbCxcclxuICAgICAgICAgICAgXCJsb2FkTWF0ZXJpYWxcIixcclxuICAgICAgICAgICAgKGV4dGVuc2lvbikgPT4gZXh0ZW5zaW9uLl9sb2FkTWF0ZXJpYWxBc3luYyAmJiBleHRlbnNpb24uX2xvYWRNYXRlcmlhbEFzeW5jKGNvbnRleHQsIG1hdGVyaWFsLCBiYWJ5bG9uTWVzaCwgYmFieWxvbkRyYXdNb2RlLCBhc3NpZ24pXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9leHRlbnNpb25zQ3JlYXRlTWF0ZXJpYWwoY29udGV4dDogc3RyaW5nLCBtYXRlcmlhbDogSU1hdGVyaWFsLCBiYWJ5bG9uRHJhd01vZGU6IG51bWJlcik6IE51bGxhYmxlPE1hdGVyaWFsPiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5RXh0ZW5zaW9ucyhtYXRlcmlhbCwgXCJjcmVhdGVNYXRlcmlhbFwiLCAoZXh0ZW5zaW9uKSA9PiBleHRlbnNpb24uY3JlYXRlTWF0ZXJpYWwgJiYgZXh0ZW5zaW9uLmNyZWF0ZU1hdGVyaWFsKGNvbnRleHQsIG1hdGVyaWFsLCBiYWJ5bG9uRHJhd01vZGUpKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9leHRlbnNpb25zTG9hZE1hdGVyaWFsUHJvcGVydGllc0FzeW5jKGNvbnRleHQ6IHN0cmluZywgbWF0ZXJpYWw6IElNYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsOiBNYXRlcmlhbCk6IE51bGxhYmxlPFByb21pc2U8dm9pZD4+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlFeHRlbnNpb25zKFxyXG4gICAgICAgICAgICBtYXRlcmlhbCxcclxuICAgICAgICAgICAgXCJsb2FkTWF0ZXJpYWxQcm9wZXJ0aWVzXCIsXHJcbiAgICAgICAgICAgIChleHRlbnNpb24pID0+IGV4dGVuc2lvbi5sb2FkTWF0ZXJpYWxQcm9wZXJ0aWVzQXN5bmMgJiYgZXh0ZW5zaW9uLmxvYWRNYXRlcmlhbFByb3BlcnRpZXNBc3luYyhjb250ZXh0LCBtYXRlcmlhbCwgYmFieWxvbk1hdGVyaWFsKVxyXG4gICAgICAgICk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfZXh0ZW5zaW9uc0xvYWRUZXh0dXJlSW5mb0FzeW5jKGNvbnRleHQ6IHN0cmluZywgdGV4dHVyZUluZm86IElUZXh0dXJlSW5mbywgYXNzaWduOiAoYmFieWxvblRleHR1cmU6IEJhc2VUZXh0dXJlKSA9PiB2b2lkKTogTnVsbGFibGU8UHJvbWlzZTxCYXNlVGV4dHVyZT4+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlFeHRlbnNpb25zKHRleHR1cmVJbmZvLCBcImxvYWRUZXh0dXJlSW5mb1wiLCAoZXh0ZW5zaW9uKSA9PiBleHRlbnNpb24ubG9hZFRleHR1cmVJbmZvQXN5bmMgJiYgZXh0ZW5zaW9uLmxvYWRUZXh0dXJlSW5mb0FzeW5jKGNvbnRleHQsIHRleHR1cmVJbmZvLCBhc3NpZ24pKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9leHRlbnNpb25zTG9hZFRleHR1cmVBc3luYyhjb250ZXh0OiBzdHJpbmcsIHRleHR1cmU6IElUZXh0dXJlLCBhc3NpZ246IChiYWJ5bG9uVGV4dHVyZTogQmFzZVRleHR1cmUpID0+IHZvaWQpOiBOdWxsYWJsZTxQcm9taXNlPEJhc2VUZXh0dXJlPj4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBseUV4dGVuc2lvbnModGV4dHVyZSwgXCJsb2FkVGV4dHVyZVwiLCAoZXh0ZW5zaW9uKSA9PiBleHRlbnNpb24uX2xvYWRUZXh0dXJlQXN5bmMgJiYgZXh0ZW5zaW9uLl9sb2FkVGV4dHVyZUFzeW5jKGNvbnRleHQsIHRleHR1cmUsIGFzc2lnbikpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2V4dGVuc2lvbnNMb2FkQW5pbWF0aW9uQXN5bmMoY29udGV4dDogc3RyaW5nLCBhbmltYXRpb246IElBbmltYXRpb24pOiBOdWxsYWJsZTxQcm9taXNlPEFuaW1hdGlvbkdyb3VwPj4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBseUV4dGVuc2lvbnMoYW5pbWF0aW9uLCBcImxvYWRBbmltYXRpb25cIiwgKGV4dGVuc2lvbikgPT4gZXh0ZW5zaW9uLmxvYWRBbmltYXRpb25Bc3luYyAmJiBleHRlbnNpb24ubG9hZEFuaW1hdGlvbkFzeW5jKGNvbnRleHQsIGFuaW1hdGlvbikpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2V4dGVuc2lvbnNMb2FkQW5pbWF0aW9uQ2hhbm5lbEFzeW5jKFxyXG4gICAgICAgIGNvbnRleHQ6IHN0cmluZyxcclxuICAgICAgICBhbmltYXRpb25Db250ZXh0OiBzdHJpbmcsXHJcbiAgICAgICAgYW5pbWF0aW9uOiBJQW5pbWF0aW9uLFxyXG4gICAgICAgIGNoYW5uZWw6IElBbmltYXRpb25DaGFubmVsLFxyXG4gICAgICAgIG9uTG9hZDogKGJhYnlsb25BbmltYXRhYmxlOiBJQW5pbWF0YWJsZSwgYmFieWxvbkFuaW1hdGlvbjogQW5pbWF0aW9uKSA9PiB2b2lkXHJcbiAgICApOiBOdWxsYWJsZTxQcm9taXNlPHZvaWQ+PiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5RXh0ZW5zaW9ucyhcclxuICAgICAgICAgICAgYW5pbWF0aW9uLFxyXG4gICAgICAgICAgICBcImxvYWRBbmltYXRpb25DaGFubmVsXCIsXHJcbiAgICAgICAgICAgIChleHRlbnNpb24pID0+IGV4dGVuc2lvbi5fbG9hZEFuaW1hdGlvbkNoYW5uZWxBc3luYyAmJiBleHRlbnNpb24uX2xvYWRBbmltYXRpb25DaGFubmVsQXN5bmMoY29udGV4dCwgYW5pbWF0aW9uQ29udGV4dCwgYW5pbWF0aW9uLCBjaGFubmVsLCBvbkxvYWQpXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9leHRlbnNpb25zTG9hZFNraW5Bc3luYyhjb250ZXh0OiBzdHJpbmcsIG5vZGU6IElOb2RlLCBza2luOiBJU2tpbik6IE51bGxhYmxlPFByb21pc2U8dm9pZD4+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fYXBwbHlFeHRlbnNpb25zKHNraW4sIFwibG9hZFNraW5cIiwgKGV4dGVuc2lvbikgPT4gZXh0ZW5zaW9uLl9sb2FkU2tpbkFzeW5jICYmIGV4dGVuc2lvbi5fbG9hZFNraW5Bc3luYyhjb250ZXh0LCBub2RlLCBza2luKSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfZXh0ZW5zaW9uc0xvYWRVcmlBc3luYyhjb250ZXh0OiBzdHJpbmcsIHByb3BlcnR5OiBJUHJvcGVydHksIHVyaTogc3RyaW5nKTogTnVsbGFibGU8UHJvbWlzZTxBcnJheUJ1ZmZlclZpZXc+PiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5RXh0ZW5zaW9ucyhwcm9wZXJ0eSwgXCJsb2FkVXJpXCIsIChleHRlbnNpb24pID0+IGV4dGVuc2lvbi5fbG9hZFVyaUFzeW5jICYmIGV4dGVuc2lvbi5fbG9hZFVyaUFzeW5jKGNvbnRleHQsIHByb3BlcnR5LCB1cmkpKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9leHRlbnNpb25zTG9hZEJ1ZmZlclZpZXdBc3luYyhjb250ZXh0OiBzdHJpbmcsIGJ1ZmZlclZpZXc6IElCdWZmZXJWaWV3KTogTnVsbGFibGU8UHJvbWlzZTxBcnJheUJ1ZmZlclZpZXc+PiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2FwcGx5RXh0ZW5zaW9ucyhidWZmZXJWaWV3LCBcImxvYWRCdWZmZXJWaWV3XCIsIChleHRlbnNpb24pID0+IGV4dGVuc2lvbi5sb2FkQnVmZmVyVmlld0FzeW5jICYmIGV4dGVuc2lvbi5sb2FkQnVmZmVyVmlld0FzeW5jKGNvbnRleHQsIGJ1ZmZlclZpZXcpKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9leHRlbnNpb25zTG9hZEJ1ZmZlckFzeW5jKGNvbnRleHQ6IHN0cmluZywgYnVmZmVyOiBJQnVmZmVyLCBieXRlT2Zmc2V0OiBudW1iZXIsIGJ5dGVMZW5ndGg6IG51bWJlcik6IE51bGxhYmxlPFByb21pc2U8QXJyYXlCdWZmZXJWaWV3Pj4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9hcHBseUV4dGVuc2lvbnMoYnVmZmVyLCBcImxvYWRCdWZmZXJcIiwgKGV4dGVuc2lvbikgPT4gZXh0ZW5zaW9uLmxvYWRCdWZmZXJBc3luYyAmJiBleHRlbnNpb24ubG9hZEJ1ZmZlckFzeW5jKGNvbnRleHQsIGJ1ZmZlciwgYnl0ZU9mZnNldCwgYnl0ZUxlbmd0aCkpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogSGVscGVyIG1ldGhvZCBjYWxsZWQgYnkgYSBsb2FkZXIgZXh0ZW5zaW9uIHRvIGxvYWQgYW4gZ2xURiBleHRlbnNpb24uXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gcHJvcGVydHkgVGhlIGdsVEYgcHJvcGVydHkgdG8gbG9hZCB0aGUgZXh0ZW5zaW9uIGZyb21cclxuICAgICAqIEBwYXJhbSBleHRlbnNpb25OYW1lIFRoZSBuYW1lIG9mIHRoZSBleHRlbnNpb24gdG8gbG9hZFxyXG4gICAgICogQHBhcmFtIGFjdGlvbkFzeW5jIFRoZSBhY3Rpb24gdG8gcnVuXHJcbiAgICAgKiBAcmV0dXJucyBUaGUgcHJvbWlzZSByZXR1cm5lZCBieSBhY3Rpb25Bc3luYyBvciBudWxsIGlmIHRoZSBleHRlbnNpb24gZG9lcyBub3QgZXhpc3RcclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBMb2FkRXh0ZW5zaW9uQXN5bmM8VEV4dGVuc2lvbiA9IGFueSwgVFJlc3VsdCA9IHZvaWQ+KFxyXG4gICAgICAgIGNvbnRleHQ6IHN0cmluZyxcclxuICAgICAgICBwcm9wZXJ0eTogSVByb3BlcnR5LFxyXG4gICAgICAgIGV4dGVuc2lvbk5hbWU6IHN0cmluZyxcclxuICAgICAgICBhY3Rpb25Bc3luYzogKGV4dGVuc2lvbkNvbnRleHQ6IHN0cmluZywgZXh0ZW5zaW9uOiBURXh0ZW5zaW9uKSA9PiBOdWxsYWJsZTxQcm9taXNlPFRSZXN1bHQ+PlxyXG4gICAgKTogTnVsbGFibGU8UHJvbWlzZTxUUmVzdWx0Pj4ge1xyXG4gICAgICAgIGlmICghcHJvcGVydHkuZXh0ZW5zaW9ucykge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGV4dGVuc2lvbnMgPSBwcm9wZXJ0eS5leHRlbnNpb25zO1xyXG5cclxuICAgICAgICBjb25zdCBleHRlbnNpb24gPSBleHRlbnNpb25zW2V4dGVuc2lvbk5hbWVdIGFzIFRFeHRlbnNpb247XHJcbiAgICAgICAgaWYgKCFleHRlbnNpb24pIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gYWN0aW9uQXN5bmMoYCR7Y29udGV4dH0vZXh0ZW5zaW9ucy8ke2V4dGVuc2lvbk5hbWV9YCwgZXh0ZW5zaW9uKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEhlbHBlciBtZXRob2QgY2FsbGVkIGJ5IGEgbG9hZGVyIGV4dGVuc2lvbiB0byBsb2FkIGEgZ2xURiBleHRyYS5cclxuICAgICAqIEBwYXJhbSBjb250ZXh0IFRoZSBjb250ZXh0IHdoZW4gbG9hZGluZyB0aGUgYXNzZXRcclxuICAgICAqIEBwYXJhbSBwcm9wZXJ0eSBUaGUgZ2xURiBwcm9wZXJ0eSB0byBsb2FkIHRoZSBleHRyYSBmcm9tXHJcbiAgICAgKiBAcGFyYW0gZXh0ZW5zaW9uTmFtZSBUaGUgbmFtZSBvZiB0aGUgZXh0ZW5zaW9uIHRvIGxvYWRcclxuICAgICAqIEBwYXJhbSBhY3Rpb25Bc3luYyBUaGUgYWN0aW9uIHRvIHJ1blxyXG4gICAgICogQHJldHVybnMgVGhlIHByb21pc2UgcmV0dXJuZWQgYnkgYWN0aW9uQXN5bmMgb3IgbnVsbCBpZiB0aGUgZXh0cmEgZG9lcyBub3QgZXhpc3RcclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBMb2FkRXh0cmFBc3luYzxURXh0cmEgPSBhbnksIFRSZXN1bHQgPSB2b2lkPihcclxuICAgICAgICBjb250ZXh0OiBzdHJpbmcsXHJcbiAgICAgICAgcHJvcGVydHk6IElQcm9wZXJ0eSxcclxuICAgICAgICBleHRlbnNpb25OYW1lOiBzdHJpbmcsXHJcbiAgICAgICAgYWN0aW9uQXN5bmM6IChleHRyYUNvbnRleHQ6IHN0cmluZywgZXh0cmE6IFRFeHRyYSkgPT4gTnVsbGFibGU8UHJvbWlzZTxUUmVzdWx0Pj5cclxuICAgICk6IE51bGxhYmxlPFByb21pc2U8VFJlc3VsdD4+IHtcclxuICAgICAgICBpZiAoIXByb3BlcnR5LmV4dHJhcykge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGV4dHJhcyA9IHByb3BlcnR5LmV4dHJhcztcclxuXHJcbiAgICAgICAgY29uc3QgZXh0cmEgPSBleHRyYXNbZXh0ZW5zaW9uTmFtZV0gYXMgVEV4dHJhO1xyXG4gICAgICAgIGlmICghZXh0cmEpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICByZXR1cm4gYWN0aW9uQXN5bmMoYCR7Y29udGV4dH0vZXh0cmFzLyR7ZXh0ZW5zaW9uTmFtZX1gLCBleHRyYSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDaGVja3MgZm9yIHByZXNlbmNlIG9mIGFuIGV4dGVuc2lvbi5cclxuICAgICAqIEBwYXJhbSBuYW1lIFRoZSBuYW1lIG9mIHRoZSBleHRlbnNpb24gdG8gY2hlY2tcclxuICAgICAqIEByZXR1cm5zIEEgYm9vbGVhbiBpbmRpY2F0aW5nIHRoZSBwcmVzZW5jZSBvZiB0aGUgZ2l2ZW4gZXh0ZW5zaW9uIG5hbWUgaW4gYGV4dGVuc2lvbnNVc2VkYFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgaXNFeHRlbnNpb25Vc2VkKG5hbWU6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiAhIXRoaXMuX2dsdGYuZXh0ZW5zaW9uc1VzZWQgJiYgdGhpcy5fZ2x0Zi5leHRlbnNpb25zVXNlZC5pbmRleE9mKG5hbWUpICE9PSAtMTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEluY3JlbWVudHMgdGhlIGluZGVudGF0aW9uIGxldmVsIGFuZCBsb2dzIGEgbWVzc2FnZS5cclxuICAgICAqIEBwYXJhbSBtZXNzYWdlIFRoZSBtZXNzYWdlIHRvIGxvZ1xyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9nT3BlbihtZXNzYWdlOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLl9wYXJlbnQuX2xvZ09wZW4obWVzc2FnZSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWNyZW1lbnRzIHRoZSBpbmRlbnRhdGlvbiBsZXZlbC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvZ0Nsb3NlKCk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuX3BhcmVudC5fbG9nQ2xvc2UoKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIExvZ3MgYSBtZXNzYWdlXHJcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSBUaGUgbWVzc2FnZSB0byBsb2dcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvZyhtZXNzYWdlOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLl9wYXJlbnQuX2xvZyhtZXNzYWdlKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFN0YXJ0cyBhIHBlcmZvcm1hbmNlIGNvdW50ZXIuXHJcbiAgICAgKiBAcGFyYW0gY291bnRlck5hbWUgVGhlIG5hbWUgb2YgdGhlIHBlcmZvcm1hbmNlIGNvdW50ZXJcclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXJ0UGVyZm9ybWFuY2VDb3VudGVyKGNvdW50ZXJOYW1lOiBzdHJpbmcpOiB2b2lkIHtcclxuICAgICAgICB0aGlzLl9wYXJlbnQuX3N0YXJ0UGVyZm9ybWFuY2VDb3VudGVyKGNvdW50ZXJOYW1lKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEVuZHMgYSBwZXJmb3JtYW5jZSBjb3VudGVyLlxyXG4gICAgICogQHBhcmFtIGNvdW50ZXJOYW1lIFRoZSBuYW1lIG9mIHRoZSBwZXJmb3JtYW5jZSBjb3VudGVyXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBlbmRQZXJmb3JtYW5jZUNvdW50ZXIoY291bnRlck5hbWU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuX3BhcmVudC5fZW5kUGVyZm9ybWFuY2VDb3VudGVyKGNvdW50ZXJOYW1lKTtcclxuICAgIH1cclxufVxyXG5cclxuR0xURkZpbGVMb2FkZXIuX0NyZWF0ZUdMVEYyTG9hZGVyID0gKHBhcmVudCkgPT4gbmV3IEdMVEZMb2FkZXIocGFyZW50KTtcclxuIiwiaW1wb3J0IHsgQW5pbWF0aW9uIH0gZnJvbSBcImNvcmUvQW5pbWF0aW9ucy9hbmltYXRpb25cIjtcclxuaW1wb3J0IHsgUXVhdGVybmlvbiwgVmVjdG9yMyB9IGZyb20gXCJjb3JlL01hdGhzL21hdGgudmVjdG9yXCI7XHJcbmltcG9ydCB0eXBlIHsgSU5vZGUgfSBmcm9tIFwiLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElBbmltYXRhYmxlIH0gZnJvbSBcImNvcmUvQW5pbWF0aW9ucy9hbmltYXRhYmxlLmludGVyZmFjZVwiO1xyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgdHlwZSBHZXRWYWx1ZUZuID0gKHRhcmdldDogYW55LCBzb3VyY2U6IEZsb2F0MzJBcnJheSwgb2Zmc2V0OiBudW1iZXIsIHNjYWxlOiBudW1iZXIpID0+IGFueTtcclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuZXhwb3J0IGZ1bmN0aW9uIGdldFZlY3RvcjMoX3RhcmdldDogYW55LCBzb3VyY2U6IEZsb2F0MzJBcnJheSwgb2Zmc2V0OiBudW1iZXIsIHNjYWxlOiBudW1iZXIpOiBWZWN0b3IzIHtcclxuICAgIHJldHVybiBWZWN0b3IzLkZyb21BcnJheShzb3VyY2UsIG9mZnNldCkuc2NhbGVJblBsYWNlKHNjYWxlKTtcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgZnVuY3Rpb24gZ2V0UXVhdGVybmlvbihfdGFyZ2V0OiBhbnksIHNvdXJjZTogRmxvYXQzMkFycmF5LCBvZmZzZXQ6IG51bWJlciwgc2NhbGU6IG51bWJlcik6IFF1YXRlcm5pb24ge1xyXG4gICAgcmV0dXJuIFF1YXRlcm5pb24uRnJvbUFycmF5KHNvdXJjZSwgb2Zmc2V0KS5zY2FsZUluUGxhY2Uoc2NhbGUpO1xyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBmdW5jdGlvbiBnZXRXZWlnaHRzKHRhcmdldDogSU5vZGUsIHNvdXJjZTogRmxvYXQzMkFycmF5LCBvZmZzZXQ6IG51bWJlciwgc2NhbGU6IG51bWJlcik6IEFycmF5PG51bWJlcj4ge1xyXG4gICAgY29uc3QgdmFsdWUgPSBuZXcgQXJyYXk8bnVtYmVyPih0YXJnZXQuX251bU1vcnBoVGFyZ2V0cyEpO1xyXG4gICAgZm9yIChsZXQgaSA9IDA7IGkgPCB2YWx1ZS5sZW5ndGg7IGkrKykge1xyXG4gICAgICAgIHZhbHVlW2ldID0gc291cmNlW29mZnNldCsrXSAqIHNjYWxlO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB2YWx1ZTtcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQW5pbWF0aW9uUHJvcGVydHlJbmZvIHtcclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBjb25zdHJ1Y3RvcihcclxuICAgICAgICBwdWJsaWMgcmVhZG9ubHkgdHlwZTogbnVtYmVyLFxyXG4gICAgICAgIHB1YmxpYyByZWFkb25seSBuYW1lOiBzdHJpbmcsXHJcbiAgICAgICAgcHVibGljIHJlYWRvbmx5IGdldFZhbHVlOiBHZXRWYWx1ZUZuLFxyXG4gICAgICAgIHB1YmxpYyByZWFkb25seSBnZXRTdHJpZGU6ICh0YXJnZXQ6IGFueSkgPT4gbnVtYmVyXHJcbiAgICApIHt9XHJcblxyXG4gICAgcHJvdGVjdGVkIF9idWlsZEFuaW1hdGlvbihuYW1lOiBzdHJpbmcsIGZwczogbnVtYmVyLCBrZXlzOiBhbnlbXSk6IEFuaW1hdGlvbiB7XHJcbiAgICAgICAgY29uc3QgYmFieWxvbkFuaW1hdGlvbiA9IG5ldyBBbmltYXRpb24obmFtZSwgdGhpcy5uYW1lLCBmcHMsIHRoaXMudHlwZSk7XHJcbiAgICAgICAgYmFieWxvbkFuaW1hdGlvbi5zZXRLZXlzKGtleXMpO1xyXG4gICAgICAgIHJldHVybiBiYWJ5bG9uQW5pbWF0aW9uO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBhYnN0cmFjdCBidWlsZEFuaW1hdGlvbnModGFyZ2V0OiBhbnksIG5hbWU6IHN0cmluZywgZnBzOiBudW1iZXIsIGtleXM6IGFueVtdLCBjYWxsYmFjazogKGJhYnlsb25BbmltYXRhYmxlOiBJQW5pbWF0YWJsZSwgYmFieWxvbkFuaW1hdGlvbjogQW5pbWF0aW9uKSA9PiB2b2lkKTogdm9pZDtcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgY2xhc3MgVHJhbnNmb3JtTm9kZUFuaW1hdGlvblByb3BlcnR5SW5mbyBleHRlbmRzIEFuaW1hdGlvblByb3BlcnR5SW5mbyB7XHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgYnVpbGRBbmltYXRpb25zKHRhcmdldDogSU5vZGUsIG5hbWU6IHN0cmluZywgZnBzOiBudW1iZXIsIGtleXM6IGFueVtdLCBjYWxsYmFjazogKGJhYnlsb25BbmltYXRhYmxlOiBJQW5pbWF0YWJsZSwgYmFieWxvbkFuaW1hdGlvbjogQW5pbWF0aW9uKSA9PiB2b2lkKTogdm9pZCB7XHJcbiAgICAgICAgY2FsbGJhY2sodGFyZ2V0Ll9iYWJ5bG9uVHJhbnNmb3JtTm9kZSEsIHRoaXMuX2J1aWxkQW5pbWF0aW9uKG5hbWUsIGZwcywga2V5cykpO1xyXG4gICAgfVxyXG59XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbmV4cG9ydCBjbGFzcyBXZWlnaHRBbmltYXRpb25Qcm9wZXJ0eUluZm8gZXh0ZW5kcyBBbmltYXRpb25Qcm9wZXJ0eUluZm8ge1xyXG4gICAgcHVibGljIGJ1aWxkQW5pbWF0aW9ucyh0YXJnZXQ6IElOb2RlLCBuYW1lOiBzdHJpbmcsIGZwczogbnVtYmVyLCBrZXlzOiBhbnlbXSwgY2FsbGJhY2s6IChiYWJ5bG9uQW5pbWF0YWJsZTogSUFuaW1hdGFibGUsIGJhYnlsb25BbmltYXRpb246IEFuaW1hdGlvbikgPT4gdm9pZCk6IHZvaWQge1xyXG4gICAgICAgIGlmICh0YXJnZXQuX251bU1vcnBoVGFyZ2V0cykge1xyXG4gICAgICAgICAgICBmb3IgKGxldCB0YXJnZXRJbmRleCA9IDA7IHRhcmdldEluZGV4IDwgdGFyZ2V0Ll9udW1Nb3JwaFRhcmdldHM7IHRhcmdldEluZGV4KyspIHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGJhYnlsb25BbmltYXRpb24gPSBuZXcgQW5pbWF0aW9uKGAke25hbWV9XyR7dGFyZ2V0SW5kZXh9YCwgdGhpcy5uYW1lLCBmcHMsIHRoaXMudHlwZSk7XHJcbiAgICAgICAgICAgICAgICBiYWJ5bG9uQW5pbWF0aW9uLnNldEtleXMoXHJcbiAgICAgICAgICAgICAgICAgICAga2V5cy5tYXAoKGtleSkgPT4gKHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZnJhbWU6IGtleS5mcmFtZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgaW5UYW5nZW50OiBrZXkuaW5UYW5nZW50ID8ga2V5LmluVGFuZ2VudFt0YXJnZXRJbmRleF0gOiB1bmRlZmluZWQsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlOiBrZXkudmFsdWVbdGFyZ2V0SW5kZXhdLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBvdXRUYW5nZW50OiBrZXkub3V0VGFuZ2VudCA/IGtleS5vdXRUYW5nZW50W3RhcmdldEluZGV4XSA6IHVuZGVmaW5lZCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgaW50ZXJwb2xhdGlvbjoga2V5LmludGVycG9sYXRpb24sXHJcbiAgICAgICAgICAgICAgICAgICAgfSkpXHJcbiAgICAgICAgICAgICAgICApO1xyXG5cclxuICAgICAgICAgICAgICAgIGlmICh0YXJnZXQuX3ByaW1pdGl2ZUJhYnlsb25NZXNoZXMpIHtcclxuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGJhYnlsb25NZXNoIG9mIHRhcmdldC5fcHJpbWl0aXZlQmFieWxvbk1lc2hlcykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoYmFieWxvbk1lc2gubW9ycGhUYXJnZXRNYW5hZ2VyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBtb3JwaFRhcmdldCA9IGJhYnlsb25NZXNoLm1vcnBoVGFyZ2V0TWFuYWdlci5nZXRUYXJnZXQodGFyZ2V0SW5kZXgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgYmFieWxvbkFuaW1hdGlvbkNsb25lID0gYmFieWxvbkFuaW1hdGlvbi5jbG9uZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbW9ycGhUYXJnZXQuYW5pbWF0aW9ucy5wdXNoKGJhYnlsb25BbmltYXRpb25DbG9uZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayhtb3JwaFRhcmdldCwgYmFieWxvbkFuaW1hdGlvbkNsb25lKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgY29uc3Qgbm9kZUFuaW1hdGlvbkRhdGEgPSB7XHJcbiAgICB0cmFuc2xhdGlvbjogW25ldyBUcmFuc2Zvcm1Ob2RlQW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX1ZFQ1RPUjMsIFwicG9zaXRpb25cIiwgZ2V0VmVjdG9yMywgKCkgPT4gMyldLFxyXG4gICAgcm90YXRpb246IFtuZXcgVHJhbnNmb3JtTm9kZUFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9RVUFURVJOSU9OLCBcInJvdGF0aW9uUXVhdGVybmlvblwiLCBnZXRRdWF0ZXJuaW9uLCAoKSA9PiA0KV0sXHJcbiAgICBzY2FsZTogW25ldyBUcmFuc2Zvcm1Ob2RlQW5pbWF0aW9uUHJvcGVydHlJbmZvKEFuaW1hdGlvbi5BTklNQVRJT05UWVBFX1ZFQ1RPUjMsIFwic2NhbGluZ1wiLCBnZXRWZWN0b3IzLCAoKSA9PiAzKV0sXHJcbiAgICB3ZWlnaHRzOiBbbmV3IFdlaWdodEFuaW1hdGlvblByb3BlcnR5SW5mbyhBbmltYXRpb24uQU5JTUFUSU9OVFlQRV9GTE9BVCwgXCJpbmZsdWVuY2VcIiwgZ2V0V2VpZ2h0cywgKHRhcmdldCkgPT4gdGFyZ2V0Ll9udW1Nb3JwaFRhcmdldHMhKV0sXHJcbn07XHJcbiIsImltcG9ydCB0eXBlIHsgTnVsbGFibGUgfSBmcm9tIFwiY29yZS90eXBlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IEFuaW1hdGlvbiB9IGZyb20gXCJjb3JlL0FuaW1hdGlvbnMvYW5pbWF0aW9uXCI7XHJcbmltcG9ydCB0eXBlIHsgQW5pbWF0aW9uR3JvdXAgfSBmcm9tIFwiY29yZS9BbmltYXRpb25zL2FuaW1hdGlvbkdyb3VwXCI7XHJcbmltcG9ydCB0eXBlIHsgTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvbWF0ZXJpYWxcIjtcclxuaW1wb3J0IHR5cGUgeyBDYW1lcmEgfSBmcm9tIFwiY29yZS9DYW1lcmFzL2NhbWVyYVwiO1xyXG5pbXBvcnQgdHlwZSB7IEdlb21ldHJ5IH0gZnJvbSBcImNvcmUvTWVzaGVzL2dlb21ldHJ5XCI7XHJcbmltcG9ydCB0eXBlIHsgVHJhbnNmb3JtTm9kZSB9IGZyb20gXCJjb3JlL01lc2hlcy90cmFuc2Zvcm1Ob2RlXCI7XHJcbmltcG9ydCB0eXBlIHsgQmFzZVRleHR1cmUgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvVGV4dHVyZXMvYmFzZVRleHR1cmVcIjtcclxuaW1wb3J0IHR5cGUgeyBNZXNoIH0gZnJvbSBcImNvcmUvTWVzaGVzL21lc2hcIjtcclxuaW1wb3J0IHR5cGUgeyBBYnN0cmFjdE1lc2ggfSBmcm9tIFwiY29yZS9NZXNoZXMvYWJzdHJhY3RNZXNoXCI7XHJcbmltcG9ydCB0eXBlIHsgSURpc3Bvc2FibGUgfSBmcm9tIFwiY29yZS9zY2VuZVwiO1xyXG5pbXBvcnQgdHlwZSB7XHJcbiAgICBJU2NlbmUsXHJcbiAgICBJTm9kZSxcclxuICAgIElNZXNoLFxyXG4gICAgSVNraW4sXHJcbiAgICBJQ2FtZXJhLFxyXG4gICAgSU1lc2hQcmltaXRpdmUsXHJcbiAgICBJTWF0ZXJpYWwsXHJcbiAgICBJVGV4dHVyZUluZm8sXHJcbiAgICBJQW5pbWF0aW9uLFxyXG4gICAgSVRleHR1cmUsXHJcbiAgICBJQnVmZmVyVmlldyxcclxuICAgIElCdWZmZXIsXHJcbiAgICBJQW5pbWF0aW9uQ2hhbm5lbCxcclxufSBmcm9tIFwiLi9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgdHlwZSB7IElHTFRGTG9hZGVyRXh0ZW5zaW9uIGFzIElHTFRGQmFzZUxvYWRlckV4dGVuc2lvbiB9IGZyb20gXCIuLi9nbFRGRmlsZUxvYWRlclwiO1xyXG5pbXBvcnQgdHlwZSB7IElQcm9wZXJ0eSB9IGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuaW1wb3J0IHR5cGUgeyBJQW5pbWF0YWJsZSB9IGZyb20gXCJjb3JlL0FuaW1hdGlvbnMvYW5pbWF0YWJsZS5pbnRlcmZhY2VcIjtcclxuXHJcbi8qKlxyXG4gKiBJbnRlcmZhY2UgZm9yIGEgZ2xURiBsb2FkZXIgZXh0ZW5zaW9uLlxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBJR0xURkxvYWRlckV4dGVuc2lvbiBleHRlbmRzIElHTFRGQmFzZUxvYWRlckV4dGVuc2lvbiwgSURpc3Bvc2FibGUge1xyXG4gICAgLyoqXHJcbiAgICAgKiBDYWxsZWQgYWZ0ZXIgdGhlIGxvYWRlciBzdGF0ZSBjaGFuZ2VzIHRvIExPQURJTkcuXHJcbiAgICAgKi9cclxuICAgIG9uTG9hZGluZz8oKTogdm9pZDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENhbGxlZCBhZnRlciB0aGUgbG9hZGVyIHN0YXRlIGNoYW5nZXMgdG8gUkVBRFkuXHJcbiAgICAgKi9cclxuICAgIG9uUmVhZHk/KCk6IHZvaWQ7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmUgdGhpcyBtZXRob2QgdG8gbW9kaWZ5IHRoZSBkZWZhdWx0IGJlaGF2aW9yIHdoZW4gbG9hZGluZyBzY2VuZXMuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gc2NlbmUgVGhlIGdsVEYgc2NlbmUgcHJvcGVydHlcclxuICAgICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGxvYWQgaXMgY29tcGxldGUgb3IgbnVsbCBpZiBub3QgaGFuZGxlZFxyXG4gICAgICovXHJcbiAgICBsb2FkU2NlbmVBc3luYz8oY29udGV4dDogc3RyaW5nLCBzY2VuZTogSVNjZW5lKTogTnVsbGFibGU8UHJvbWlzZTx2b2lkPj47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmUgdGhpcyBtZXRob2QgdG8gbW9kaWZ5IHRoZSBkZWZhdWx0IGJlaGF2aW9yIHdoZW4gbG9hZGluZyBub2Rlcy5cclxuICAgICAqIEBwYXJhbSBjb250ZXh0IFRoZSBjb250ZXh0IHdoZW4gbG9hZGluZyB0aGUgYXNzZXRcclxuICAgICAqIEBwYXJhbSBub2RlIFRoZSBnbFRGIG5vZGUgcHJvcGVydHlcclxuICAgICAqIEBwYXJhbSBhc3NpZ24gQSBmdW5jdGlvbiBjYWxsZWQgc3luY2hyb25vdXNseSBhZnRlciBwYXJzaW5nIHRoZSBnbFRGIHByb3BlcnRpZXNcclxuICAgICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGxvYWRlZCBCYWJ5bG9uIHRyYW5zZm9ybSBub2RlIHdoZW4gdGhlIGxvYWQgaXMgY29tcGxldGUgb3IgbnVsbCBpZiBub3QgaGFuZGxlZFxyXG4gICAgICovXHJcbiAgICBsb2FkTm9kZUFzeW5jPyhjb250ZXh0OiBzdHJpbmcsIG5vZGU6IElOb2RlLCBhc3NpZ246IChiYWJ5bG9uTWVzaDogVHJhbnNmb3JtTm9kZSkgPT4gdm9pZCk6IE51bGxhYmxlPFByb21pc2U8VHJhbnNmb3JtTm9kZT4+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lIHRoaXMgbWV0aG9kIHRvIG1vZGlmeSB0aGUgZGVmYXVsdCBiZWhhdmlvciB3aGVuIGxvYWRpbmcgY2FtZXJhcy5cclxuICAgICAqIEBwYXJhbSBjb250ZXh0IFRoZSBjb250ZXh0IHdoZW4gbG9hZGluZyB0aGUgYXNzZXRcclxuICAgICAqIEBwYXJhbSBjYW1lcmEgVGhlIGdsVEYgY2FtZXJhIHByb3BlcnR5XHJcbiAgICAgKiBAcGFyYW0gYXNzaWduIEEgZnVuY3Rpb24gY2FsbGVkIHN5bmNocm9ub3VzbHkgYWZ0ZXIgcGFyc2luZyB0aGUgZ2xURiBwcm9wZXJ0aWVzXHJcbiAgICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBsb2FkZWQgQmFieWxvbiBjYW1lcmEgd2hlbiB0aGUgbG9hZCBpcyBjb21wbGV0ZSBvciBudWxsIGlmIG5vdCBoYW5kbGVkXHJcbiAgICAgKi9cclxuICAgIGxvYWRDYW1lcmFBc3luYz8oY29udGV4dDogc3RyaW5nLCBjYW1lcmE6IElDYW1lcmEsIGFzc2lnbjogKGJhYnlsb25DYW1lcmE6IENhbWVyYSkgPT4gdm9pZCk6IE51bGxhYmxlPFByb21pc2U8Q2FtZXJhPj47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqIERlZmluZSB0aGlzIG1ldGhvZCB0byBtb2RpZnkgdGhlIGRlZmF1bHQgYmVoYXZpb3Igd2hlbiBsb2FkaW5nIHZlcnRleCBkYXRhIGZvciBtZXNoIHByaW1pdGl2ZXMuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gcHJpbWl0aXZlIFRoZSBnbFRGIG1lc2ggcHJpbWl0aXZlIHByb3BlcnR5XHJcbiAgICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBsb2FkZWQgZ2VvbWV0cnkgd2hlbiB0aGUgbG9hZCBpcyBjb21wbGV0ZSBvciBudWxsIGlmIG5vdCBoYW5kbGVkXHJcbiAgICAgKi9cclxuICAgIF9sb2FkVmVydGV4RGF0YUFzeW5jPyhjb250ZXh0OiBzdHJpbmcsIHByaW1pdGl2ZTogSU1lc2hQcmltaXRpdmUsIGJhYnlsb25NZXNoOiBNZXNoKTogTnVsbGFibGU8UHJvbWlzZTxHZW9tZXRyeT4+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKiBEZWZpbmUgdGhpcyBtZXRob2QgdG8gbW9kaWZ5IHRoZSBkZWZhdWx0IGJlaGF2aW9yIHdoZW4gbG9hZGluZyBkYXRhIGZvciBtZXNoIHByaW1pdGl2ZXMuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gbmFtZSBUaGUgbWVzaCBuYW1lIHdoZW4gbG9hZGluZyB0aGUgYXNzZXRcclxuICAgICAqIEBwYXJhbSBub2RlIFRoZSBnbFRGIG5vZGUgd2hlbiBsb2FkaW5nIHRoZSBhc3NldFxyXG4gICAgICogQHBhcmFtIG1lc2ggVGhlIGdsVEYgbWVzaCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gcHJpbWl0aXZlIFRoZSBnbFRGIG1lc2ggcHJpbWl0aXZlIHByb3BlcnR5XHJcbiAgICAgKiBAcGFyYW0gYXNzaWduIEEgZnVuY3Rpb24gY2FsbGVkIHN5bmNocm9ub3VzbHkgYWZ0ZXIgcGFyc2luZyB0aGUgZ2xURiBwcm9wZXJ0aWVzXHJcbiAgICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBsb2FkZWQgbWVzaCB3aGVuIHRoZSBsb2FkIGlzIGNvbXBsZXRlIG9yIG51bGwgaWYgbm90IGhhbmRsZWRcclxuICAgICAqL1xyXG4gICAgX2xvYWRNZXNoUHJpbWl0aXZlQXN5bmM/KFxyXG4gICAgICAgIGNvbnRleHQ6IHN0cmluZyxcclxuICAgICAgICBuYW1lOiBzdHJpbmcsXHJcbiAgICAgICAgbm9kZTogSU5vZGUsXHJcbiAgICAgICAgbWVzaDogSU1lc2gsXHJcbiAgICAgICAgcHJpbWl0aXZlOiBJTWVzaFByaW1pdGl2ZSxcclxuICAgICAgICBhc3NpZ246IChiYWJ5bG9uTWVzaDogQWJzdHJhY3RNZXNoKSA9PiB2b2lkXHJcbiAgICApOiBOdWxsYWJsZTxQcm9taXNlPEFic3RyYWN0TWVzaD4+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKiBEZWZpbmUgdGhpcyBtZXRob2QgdG8gbW9kaWZ5IHRoZSBkZWZhdWx0IGJlaGF2aW9yIHdoZW4gbG9hZGluZyBtYXRlcmlhbHMuIExvYWQgbWF0ZXJpYWwgY3JlYXRlcyB0aGUgbWF0ZXJpYWwgYW5kIHRoZW4gbG9hZHMgbWF0ZXJpYWwgcHJvcGVydGllcy5cclxuICAgICAqIEBwYXJhbSBjb250ZXh0IFRoZSBjb250ZXh0IHdoZW4gbG9hZGluZyB0aGUgYXNzZXRcclxuICAgICAqIEBwYXJhbSBtYXRlcmlhbCBUaGUgZ2xURiBtYXRlcmlhbCBwcm9wZXJ0eVxyXG4gICAgICogQHBhcmFtIGFzc2lnbiBBIGZ1bmN0aW9uIGNhbGxlZCBzeW5jaHJvbm91c2x5IGFmdGVyIHBhcnNpbmcgdGhlIGdsVEYgcHJvcGVydGllc1xyXG4gICAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgbG9hZGVkIEJhYnlsb24gbWF0ZXJpYWwgd2hlbiB0aGUgbG9hZCBpcyBjb21wbGV0ZSBvciBudWxsIGlmIG5vdCBoYW5kbGVkXHJcbiAgICAgKi9cclxuICAgIF9sb2FkTWF0ZXJpYWxBc3luYz8oXHJcbiAgICAgICAgY29udGV4dDogc3RyaW5nLFxyXG4gICAgICAgIG1hdGVyaWFsOiBJTWF0ZXJpYWwsXHJcbiAgICAgICAgYmFieWxvbk1lc2g6IE51bGxhYmxlPE1lc2g+LFxyXG4gICAgICAgIGJhYnlsb25EcmF3TW9kZTogbnVtYmVyLFxyXG4gICAgICAgIGFzc2lnbjogKGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwpID0+IHZvaWRcclxuICAgICk6IE51bGxhYmxlPFByb21pc2U8TWF0ZXJpYWw+PjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZSB0aGlzIG1ldGhvZCB0byBtb2RpZnkgdGhlIGRlZmF1bHQgYmVoYXZpb3Igd2hlbiBjcmVhdGluZyBtYXRlcmlhbHMuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gbWF0ZXJpYWwgVGhlIGdsVEYgbWF0ZXJpYWwgcHJvcGVydHlcclxuICAgICAqIEBwYXJhbSBiYWJ5bG9uRHJhd01vZGUgVGhlIGRyYXcgbW9kZSBmb3IgdGhlIEJhYnlsb24gbWF0ZXJpYWxcclxuICAgICAqIEByZXR1cm5zIFRoZSBCYWJ5bG9uIG1hdGVyaWFsIG9yIG51bGwgaWYgbm90IGhhbmRsZWRcclxuICAgICAqL1xyXG4gICAgY3JlYXRlTWF0ZXJpYWw/KGNvbnRleHQ6IHN0cmluZywgbWF0ZXJpYWw6IElNYXRlcmlhbCwgYmFieWxvbkRyYXdNb2RlOiBudW1iZXIpOiBOdWxsYWJsZTxNYXRlcmlhbD47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmUgdGhpcyBtZXRob2QgdG8gbW9kaWZ5IHRoZSBkZWZhdWx0IGJlaGF2aW9yIHdoZW4gbG9hZGluZyBtYXRlcmlhbCBwcm9wZXJ0aWVzLlxyXG4gICAgICogQHBhcmFtIGNvbnRleHQgVGhlIGNvbnRleHQgd2hlbiBsb2FkaW5nIHRoZSBhc3NldFxyXG4gICAgICogQHBhcmFtIG1hdGVyaWFsIFRoZSBnbFRGIG1hdGVyaWFsIHByb3BlcnR5XHJcbiAgICAgKiBAcGFyYW0gYmFieWxvbk1hdGVyaWFsIFRoZSBCYWJ5bG9uIG1hdGVyaWFsXHJcbiAgICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBsb2FkIGlzIGNvbXBsZXRlIG9yIG51bGwgaWYgbm90IGhhbmRsZWRcclxuICAgICAqL1xyXG4gICAgbG9hZE1hdGVyaWFsUHJvcGVydGllc0FzeW5jPyhjb250ZXh0OiBzdHJpbmcsIG1hdGVyaWFsOiBJTWF0ZXJpYWwsIGJhYnlsb25NYXRlcmlhbDogTWF0ZXJpYWwpOiBOdWxsYWJsZTxQcm9taXNlPHZvaWQ+PjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZSB0aGlzIG1ldGhvZCB0byBtb2RpZnkgdGhlIGRlZmF1bHQgYmVoYXZpb3Igd2hlbiBsb2FkaW5nIHRleHR1cmUgaW5mb3MuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gdGV4dHVyZUluZm8gVGhlIGdsVEYgdGV4dHVyZSBpbmZvIHByb3BlcnR5XHJcbiAgICAgKiBAcGFyYW0gYXNzaWduIEEgZnVuY3Rpb24gY2FsbGVkIHN5bmNocm9ub3VzbHkgYWZ0ZXIgcGFyc2luZyB0aGUgZ2xURiBwcm9wZXJ0aWVzXHJcbiAgICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBsb2FkZWQgQmFieWxvbiB0ZXh0dXJlIHdoZW4gdGhlIGxvYWQgaXMgY29tcGxldGUgb3IgbnVsbCBpZiBub3QgaGFuZGxlZFxyXG4gICAgICovXHJcbiAgICBsb2FkVGV4dHVyZUluZm9Bc3luYz8oY29udGV4dDogc3RyaW5nLCB0ZXh0dXJlSW5mbzogSVRleHR1cmVJbmZvLCBhc3NpZ246IChiYWJ5bG9uVGV4dHVyZTogQmFzZVRleHR1cmUpID0+IHZvaWQpOiBOdWxsYWJsZTxQcm9taXNlPEJhc2VUZXh0dXJlPj47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqIERlZmluZSB0aGlzIG1ldGhvZCB0byBtb2RpZnkgdGhlIGRlZmF1bHQgYmVoYXZpb3Igd2hlbiBsb2FkaW5nIHRleHR1cmVzLlxyXG4gICAgICogQHBhcmFtIGNvbnRleHQgVGhlIGNvbnRleHQgd2hlbiBsb2FkaW5nIHRoZSBhc3NldFxyXG4gICAgICogQHBhcmFtIHRleHR1cmUgVGhlIGdsVEYgdGV4dHVyZSBwcm9wZXJ0eVxyXG4gICAgICogQHBhcmFtIGFzc2lnbiBBIGZ1bmN0aW9uIGNhbGxlZCBzeW5jaHJvbm91c2x5IGFmdGVyIHBhcnNpbmcgdGhlIGdsVEYgcHJvcGVydGllc1xyXG4gICAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgbG9hZGVkIEJhYnlsb24gdGV4dHVyZSB3aGVuIHRoZSBsb2FkIGlzIGNvbXBsZXRlIG9yIG51bGwgaWYgbm90IGhhbmRsZWRcclxuICAgICAqL1xyXG4gICAgX2xvYWRUZXh0dXJlQXN5bmM/KGNvbnRleHQ6IHN0cmluZywgdGV4dHVyZTogSVRleHR1cmUsIGFzc2lnbjogKGJhYnlsb25UZXh0dXJlOiBCYXNlVGV4dHVyZSkgPT4gdm9pZCk6IE51bGxhYmxlPFByb21pc2U8QmFzZVRleHR1cmU+PjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZSB0aGlzIG1ldGhvZCB0byBtb2RpZnkgdGhlIGRlZmF1bHQgYmVoYXZpb3Igd2hlbiBsb2FkaW5nIGFuaW1hdGlvbnMuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gYW5pbWF0aW9uIFRoZSBnbFRGIGFuaW1hdGlvbiBwcm9wZXJ0eVxyXG4gICAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgbG9hZGVkIEJhYnlsb24gYW5pbWF0aW9uIGdyb3VwIHdoZW4gdGhlIGxvYWQgaXMgY29tcGxldGUgb3IgbnVsbCBpZiBub3QgaGFuZGxlZFxyXG4gICAgICovXHJcbiAgICBsb2FkQW5pbWF0aW9uQXN5bmM/KGNvbnRleHQ6IHN0cmluZywgYW5pbWF0aW9uOiBJQW5pbWF0aW9uKTogTnVsbGFibGU8UHJvbWlzZTxBbmltYXRpb25Hcm91cD4+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKiBEZWZpbmUgdGhpcyBtZXRob2QgdG8gbW9kaWZ5IHRoZSBkZWZhdWx0IGJlaHZhaW9yIHdoZW4gbG9hZGluZyBhbmltYXRpb24gY2hhbm5lbHMuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gYW5pbWF0aW9uQ29udGV4dCBUaGUgY29udGV4dCBvZiB0aGUgYW5pbWF0aW9uIHdoZW4gbG9hZGluZyB0aGUgYXNzZXRcclxuICAgICAqIEBwYXJhbSBhbmltYXRpb24gVGhlIGdsVEYgYW5pbWF0aW9uIHByb3BlcnR5XHJcbiAgICAgKiBAcGFyYW0gY2hhbm5lbCBUaGUgZ2xURiBhbmltYXRpb24gY2hhbm5lbCBwcm9wZXJ0eVxyXG4gICAgICogQHBhcmFtIG9uTG9hZCBDYWxsZWQgZm9yIGVhY2ggYW5pbWF0aW9uIGxvYWRlZFxyXG4gICAgICogQHJldHVybnMgQSB2b2lkIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBsb2FkIGlzIGNvbXBsZXRlIG9yIG51bGwgaWYgbm90IGhhbmRsZWRcclxuICAgICAqL1xyXG4gICAgX2xvYWRBbmltYXRpb25DaGFubmVsQXN5bmM/KFxyXG4gICAgICAgIGNvbnRleHQ6IHN0cmluZyxcclxuICAgICAgICBhbmltYXRpb25Db250ZXh0OiBzdHJpbmcsXHJcbiAgICAgICAgYW5pbWF0aW9uOiBJQW5pbWF0aW9uLFxyXG4gICAgICAgIGNoYW5uZWw6IElBbmltYXRpb25DaGFubmVsLFxyXG4gICAgICAgIG9uTG9hZDogKGJhYnlsb25BbmltYXRhYmxlOiBJQW5pbWF0YWJsZSwgYmFieWxvbkFuaW1hdGlvbjogQW5pbWF0aW9uKSA9PiB2b2lkXHJcbiAgICApOiBOdWxsYWJsZTxQcm9taXNlPHZvaWQ+PjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICogRGVmaW5lIHRoaXMgbWV0aG9kIHRvIG1vZGlmeSB0aGUgZGVmYXVsdCBiZWhhdmlvciB3aGVuIGxvYWRpbmcgc2tpbnMuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gbm9kZSBUaGUgZ2xURiBub2RlIHByb3BlcnR5XHJcbiAgICAgKiBAcGFyYW0gc2tpbiBUaGUgZ2xURiBza2luIHByb3BlcnR5XHJcbiAgICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aGVuIHRoZSBsb2FkIGlzIGNvbXBsZXRlIG9yIG51bGwgaWYgbm90IGhhbmRsZWRcclxuICAgICAqL1xyXG4gICAgX2xvYWRTa2luQXN5bmM/KGNvbnRleHQ6IHN0cmluZywgbm9kZTogSU5vZGUsIHNraW46IElTa2luKTogTnVsbGFibGU8UHJvbWlzZTx2b2lkPj47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqIERlZmluZSB0aGlzIG1ldGhvZCB0byBtb2RpZnkgdGhlIGRlZmF1bHQgYmVoYXZpb3Igd2hlbiBsb2FkaW5nIHVyaXMuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gcHJvcGVydHkgVGhlIGdsVEYgcHJvcGVydHkgYXNzb2NpYXRlZCB3aXRoIHRoZSB1cmlcclxuICAgICAqIEBwYXJhbSB1cmkgVGhlIHVyaSB0byBsb2FkXHJcbiAgICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBsb2FkZWQgZGF0YSB3aGVuIHRoZSBsb2FkIGlzIGNvbXBsZXRlIG9yIG51bGwgaWYgbm90IGhhbmRsZWRcclxuICAgICAqL1xyXG4gICAgX2xvYWRVcmlBc3luYz8oY29udGV4dDogc3RyaW5nLCBwcm9wZXJ0eTogSVByb3BlcnR5LCB1cmk6IHN0cmluZyk6IE51bGxhYmxlPFByb21pc2U8QXJyYXlCdWZmZXJWaWV3Pj47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmUgdGhpcyBtZXRob2QgdG8gbW9kaWZ5IHRoZSBkZWZhdWx0IGJlaGF2aW9yIHdoZW4gbG9hZGluZyBidWZmZXIgdmlld3MuXHJcbiAgICAgKiBAcGFyYW0gY29udGV4dCBUaGUgY29udGV4dCB3aGVuIGxvYWRpbmcgdGhlIGFzc2V0XHJcbiAgICAgKiBAcGFyYW0gYnVmZmVyVmlldyBUaGUgZ2xURiBidWZmZXIgdmlldyBwcm9wZXJ0eVxyXG4gICAgICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgbG9hZGVkIGRhdGEgd2hlbiB0aGUgbG9hZCBpcyBjb21wbGV0ZSBvciBudWxsIGlmIG5vdCBoYW5kbGVkXHJcbiAgICAgKi9cclxuICAgIGxvYWRCdWZmZXJWaWV3QXN5bmM/KGNvbnRleHQ6IHN0cmluZywgYnVmZmVyVmlldzogSUJ1ZmZlclZpZXcpOiBOdWxsYWJsZTxQcm9taXNlPEFycmF5QnVmZmVyVmlldz4+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lIHRoaXMgbWV0aG9kIHRvIG1vZGlmeSB0aGUgZGVmYXVsdCBiZWhhdmlvciB3aGVuIGxvYWRpbmcgYnVmZmVycy5cclxuICAgICAqIEBwYXJhbSBjb250ZXh0IFRoZSBjb250ZXh0IHdoZW4gbG9hZGluZyB0aGUgYXNzZXRcclxuICAgICAqIEBwYXJhbSBidWZmZXIgVGhlIGdsVEYgYnVmZmVyIHByb3BlcnR5XHJcbiAgICAgKiBAcGFyYW0gYnl0ZU9mZnNldCBUaGUgYnl0ZSBvZmZzZXQgdG8gbG9hZFxyXG4gICAgICogQHBhcmFtIGJ5dGVMZW5ndGggVGhlIGJ5dGUgbGVuZ3RoIHRvIGxvYWRcclxuICAgICAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGxvYWRlZCBkYXRhIHdoZW4gdGhlIGxvYWQgaXMgY29tcGxldGUgb3IgbnVsbCBpZiBub3QgaGFuZGxlZFxyXG4gICAgICovXHJcbiAgICBsb2FkQnVmZmVyQXN5bmM/KGNvbnRleHQ6IHN0cmluZywgYnVmZmVyOiBJQnVmZmVyLCBieXRlT2Zmc2V0OiBudW1iZXIsIGJ5dGVMZW5ndGg6IG51bWJlcik6IE51bGxhYmxlPFByb21pc2U8QXJyYXlCdWZmZXJWaWV3Pj47XHJcbn1cclxuIiwiaW1wb3J0IHR5cGUgeyBBbmltYXRpb25Hcm91cCB9IGZyb20gXCJjb3JlL0FuaW1hdGlvbnMvYW5pbWF0aW9uR3JvdXBcIjtcclxuaW1wb3J0IHR5cGUgeyBTa2VsZXRvbiB9IGZyb20gXCJjb3JlL0JvbmVzL3NrZWxldG9uXCI7XHJcbmltcG9ydCB0eXBlIHsgTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvbWF0ZXJpYWxcIjtcclxuaW1wb3J0IHR5cGUgeyBUcmFuc2Zvcm1Ob2RlIH0gZnJvbSBcImNvcmUvTWVzaGVzL3RyYW5zZm9ybU5vZGVcIjtcclxuaW1wb3J0IHR5cGUgeyBCdWZmZXIsIFZlcnRleEJ1ZmZlciB9IGZyb20gXCJjb3JlL0J1ZmZlcnMvYnVmZmVyXCI7XHJcbmltcG9ydCB0eXBlIHsgQWJzdHJhY3RNZXNoIH0gZnJvbSBcImNvcmUvTWVzaGVzL2Fic3RyYWN0TWVzaFwiO1xyXG5pbXBvcnQgdHlwZSB7IE1lc2ggfSBmcm9tIFwiY29yZS9NZXNoZXMvbWVzaFwiO1xyXG5pbXBvcnQgdHlwZSB7IENhbWVyYSB9IGZyb20gXCJjb3JlL0NhbWVyYXMvY2FtZXJhXCI7XHJcbmltcG9ydCB0eXBlIHsgTGlnaHQgfSBmcm9tIFwiY29yZS9MaWdodHMvbGlnaHRcIjtcclxuXHJcbmltcG9ydCB0eXBlICogYXMgR0xURjIgZnJvbSBcImJhYnlsb25qcy1nbHRmMmludGVyZmFjZVwiO1xyXG5cclxuLyoqXHJcbiAqIExvYWRlciBpbnRlcmZhY2Ugd2l0aCBhbiBpbmRleCBmaWVsZC5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUFycmF5SXRlbSB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBpbmRleCBvZiB0aGlzIGl0ZW0gaW4gdGhlIGFycmF5LlxyXG4gICAgICovXHJcbiAgICBpbmRleDogbnVtYmVyO1xyXG59XHJcblxyXG4vKipcclxuICogTG9hZGVyIGludGVyZmFjZSB3aXRoIGFkZGl0aW9uYWwgbWVtYmVycy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUFjY2Vzc29yIGV4dGVuZHMgR0xURjIuSUFjY2Vzc29yLCBJQXJyYXlJdGVtIHtcclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIF9kYXRhPzogUHJvbWlzZTxBcnJheUJ1ZmZlclZpZXc+O1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIF9iYWJ5bG9uVmVydGV4QnVmZmVyPzogeyBba2luZDogc3RyaW5nXTogUHJvbWlzZTxWZXJ0ZXhCdWZmZXI+IH07XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2FkZXIgaW50ZXJmYWNlIHdpdGggYWRkaXRpb25hbCBtZW1iZXJzLlxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBJQW5pbWF0aW9uQ2hhbm5lbCBleHRlbmRzIEdMVEYyLklBbmltYXRpb25DaGFubmVsLCBJQXJyYXlJdGVtIHt9XHJcblxyXG4vKiogQGludGVybmFsICovXHJcbi8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBAdHlwZXNjcmlwdC1lc2xpbnQvbmFtaW5nLWNvbnZlbnRpb25cclxuZXhwb3J0IGludGVyZmFjZSBfSUFuaW1hdGlvblNhbXBsZXJEYXRhIHtcclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIGlucHV0OiBGbG9hdDMyQXJyYXk7XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgaW50ZXJwb2xhdGlvbjogR0xURjIuQW5pbWF0aW9uU2FtcGxlckludGVycG9sYXRpb247XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgb3V0cHV0OiBGbG9hdDMyQXJyYXk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2FkZXIgaW50ZXJmYWNlIHdpdGggYWRkaXRpb25hbCBtZW1iZXJzLlxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBJQW5pbWF0aW9uU2FtcGxlciBleHRlbmRzIEdMVEYyLklBbmltYXRpb25TYW1wbGVyLCBJQXJyYXlJdGVtIHtcclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIF9kYXRhPzogUHJvbWlzZTxfSUFuaW1hdGlvblNhbXBsZXJEYXRhPjtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvYWRlciBpbnRlcmZhY2Ugd2l0aCBhZGRpdGlvbmFsIG1lbWJlcnMuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElBbmltYXRpb24gZXh0ZW5kcyBHTFRGMi5JQW5pbWF0aW9uLCBJQXJyYXlJdGVtIHtcclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIGNoYW5uZWxzOiBJQW5pbWF0aW9uQ2hhbm5lbFtdO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHNhbXBsZXJzOiBJQW5pbWF0aW9uU2FtcGxlcltdO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIF9iYWJ5bG9uQW5pbWF0aW9uR3JvdXA/OiBBbmltYXRpb25Hcm91cDtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvYWRlciBpbnRlcmZhY2Ugd2l0aCBhZGRpdGlvbmFsIG1lbWJlcnMuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElCdWZmZXIgZXh0ZW5kcyBHTFRGMi5JQnVmZmVyLCBJQXJyYXlJdGVtIHtcclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIF9kYXRhPzogUHJvbWlzZTxBcnJheUJ1ZmZlclZpZXc+O1xyXG59XHJcblxyXG4vKipcclxuICogTG9hZGVyIGludGVyZmFjZSB3aXRoIGFkZGl0aW9uYWwgbWVtYmVycy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUJ1ZmZlclZpZXcgZXh0ZW5kcyBHTFRGMi5JQnVmZmVyVmlldywgSUFycmF5SXRlbSB7XHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBfZGF0YT86IFByb21pc2U8QXJyYXlCdWZmZXJWaWV3PjtcclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBfYmFieWxvbkJ1ZmZlcj86IFByb21pc2U8QnVmZmVyPjtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvYWRlciBpbnRlcmZhY2Ugd2l0aCBhZGRpdGlvbmFsIG1lbWJlcnMuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElDYW1lcmEgZXh0ZW5kcyBHTFRGMi5JQ2FtZXJhLCBJQXJyYXlJdGVtIHtcclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIF9iYWJ5bG9uQ2FtZXJhPzogQ2FtZXJhO1xyXG59XHJcblxyXG4vKipcclxuICogTG9hZGVyIGludGVyZmFjZSB3aXRoIGFkZGl0aW9uYWwgbWVtYmVycy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUltYWdlIGV4dGVuZHMgR0xURjIuSUltYWdlLCBJQXJyYXlJdGVtIHtcclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIF9kYXRhPzogUHJvbWlzZTxBcnJheUJ1ZmZlclZpZXc+O1xyXG59XHJcblxyXG4vKipcclxuICogTG9hZGVyIGludGVyZmFjZSB3aXRoIGFkZGl0aW9uYWwgbWVtYmVycy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSU1hdGVyaWFsTm9ybWFsVGV4dHVyZUluZm8gZXh0ZW5kcyBHTFRGMi5JTWF0ZXJpYWxOb3JtYWxUZXh0dXJlSW5mbywgSVRleHR1cmVJbmZvIHt9XHJcblxyXG4vKipcclxuICogTG9hZGVyIGludGVyZmFjZSB3aXRoIGFkZGl0aW9uYWwgbWVtYmVycy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSU1hdGVyaWFsT2NjbHVzaW9uVGV4dHVyZUluZm8gZXh0ZW5kcyBHTFRGMi5JTWF0ZXJpYWxPY2NsdXNpb25UZXh0dXJlSW5mbywgSVRleHR1cmVJbmZvIHt9XHJcblxyXG4vKipcclxuICogTG9hZGVyIGludGVyZmFjZSB3aXRoIGFkZGl0aW9uYWwgbWVtYmVycy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSU1hdGVyaWFsUGJyTWV0YWxsaWNSb3VnaG5lc3MgZXh0ZW5kcyBHTFRGMi5JTWF0ZXJpYWxQYnJNZXRhbGxpY1JvdWdobmVzcyB7XHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBiYXNlQ29sb3JUZXh0dXJlPzogSVRleHR1cmVJbmZvO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIG1ldGFsbGljUm91Z2huZXNzVGV4dHVyZT86IElUZXh0dXJlSW5mbztcclxufVxyXG5cclxuLyoqXHJcbiAqIExvYWRlciBpbnRlcmZhY2Ugd2l0aCBhZGRpdGlvbmFsIG1lbWJlcnMuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElNYXRlcmlhbCBleHRlbmRzIEdMVEYyLklNYXRlcmlhbCwgSUFycmF5SXRlbSB7XHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwYnJNZXRhbGxpY1JvdWdobmVzcz86IElNYXRlcmlhbFBick1ldGFsbGljUm91Z2huZXNzO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIG5vcm1hbFRleHR1cmU/OiBJTWF0ZXJpYWxOb3JtYWxUZXh0dXJlSW5mbztcclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBvY2NsdXNpb25UZXh0dXJlPzogSU1hdGVyaWFsT2NjbHVzaW9uVGV4dHVyZUluZm87XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgZW1pc3NpdmVUZXh0dXJlPzogSVRleHR1cmVJbmZvO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIF9kYXRhPzoge1xyXG4gICAgICAgIFtiYWJ5bG9uRHJhd01vZGU6IG51bWJlcl06IHtcclxuICAgICAgICAgICAgYmFieWxvbk1hdGVyaWFsOiBNYXRlcmlhbDtcclxuICAgICAgICAgICAgYmFieWxvbk1lc2hlczogQWJzdHJhY3RNZXNoW107XHJcbiAgICAgICAgICAgIHByb21pc2U6IFByb21pc2U8dm9pZD47XHJcbiAgICAgICAgfTtcclxuICAgIH07XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2FkZXIgaW50ZXJmYWNlIHdpdGggYWRkaXRpb25hbCBtZW1iZXJzLlxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBJTWVzaCBleHRlbmRzIEdMVEYyLklNZXNoLCBJQXJyYXlJdGVtIHtcclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHByaW1pdGl2ZXM6IElNZXNoUHJpbWl0aXZlW107XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2FkZXIgaW50ZXJmYWNlIHdpdGggYWRkaXRpb25hbCBtZW1iZXJzLlxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBJTWVzaFByaW1pdGl2ZSBleHRlbmRzIEdMVEYyLklNZXNoUHJpbWl0aXZlLCBJQXJyYXlJdGVtIHtcclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIF9pbnN0YW5jZURhdGE/OiB7XHJcbiAgICAgICAgYmFieWxvblNvdXJjZU1lc2g6IE1lc2g7XHJcbiAgICAgICAgcHJvbWlzZTogUHJvbWlzZTxhbnk+O1xyXG4gICAgfTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvYWRlciBpbnRlcmZhY2Ugd2l0aCBhZGRpdGlvbmFsIG1lbWJlcnMuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElOb2RlIGV4dGVuZHMgR0xURjIuSU5vZGUsIElBcnJheUl0ZW0ge1xyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcGFyZW50PzogSU5vZGU7XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgX2JhYnlsb25UcmFuc2Zvcm1Ob2RlPzogVHJhbnNmb3JtTm9kZTtcclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBfYmFieWxvblRyYW5zZm9ybU5vZGVGb3JTa2luPzogVHJhbnNmb3JtTm9kZTtcclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBfcHJpbWl0aXZlQmFieWxvbk1lc2hlcz86IEFic3RyYWN0TWVzaFtdO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIF9udW1Nb3JwaFRhcmdldHM/OiBudW1iZXI7XHJcbn1cclxuXHJcbi8qKiBAaW50ZXJuYWwgKi9cclxuLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvblxyXG5leHBvcnQgaW50ZXJmYWNlIF9JU2FtcGxlckRhdGEge1xyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgbm9NaXBNYXBzOiBib29sZWFuO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHNhbXBsaW5nTW9kZTogbnVtYmVyO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHdyYXBVOiBudW1iZXI7XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgd3JhcFY6IG51bWJlcjtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvYWRlciBpbnRlcmZhY2Ugd2l0aCBhZGRpdGlvbmFsIG1lbWJlcnMuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElTYW1wbGVyIGV4dGVuZHMgR0xURjIuSVNhbXBsZXIsIElBcnJheUl0ZW0ge1xyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgX2RhdGE/OiBfSVNhbXBsZXJEYXRhO1xyXG59XHJcblxyXG4vKipcclxuICogTG9hZGVyIGludGVyZmFjZSB3aXRoIGFkZGl0aW9uYWwgbWVtYmVycy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSVNjZW5lIGV4dGVuZHMgR0xURjIuSVNjZW5lLCBJQXJyYXlJdGVtIHt9XHJcblxyXG4vKipcclxuICogTG9hZGVyIGludGVyZmFjZSB3aXRoIGFkZGl0aW9uYWwgbWVtYmVycy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSVNraW4gZXh0ZW5kcyBHTFRGMi5JU2tpbiwgSUFycmF5SXRlbSB7XHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBfZGF0YT86IHtcclxuICAgICAgICBiYWJ5bG9uU2tlbGV0b246IFNrZWxldG9uO1xyXG4gICAgICAgIHByb21pc2U6IFByb21pc2U8dm9pZD47XHJcbiAgICB9O1xyXG59XHJcblxyXG4vKipcclxuICogTG9hZGVyIGludGVyZmFjZSB3aXRoIGFkZGl0aW9uYWwgbWVtYmVycy5cclxuICovXHJcbmV4cG9ydCBpbnRlcmZhY2UgSVRleHR1cmUgZXh0ZW5kcyBHTFRGMi5JVGV4dHVyZSwgSUFycmF5SXRlbSB7XHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBfdGV4dHVyZUluZm86IElUZXh0dXJlSW5mbztcclxufVxyXG5cclxuLyoqXHJcbiAqIExvYWRlciBpbnRlcmZhY2Ugd2l0aCBhZGRpdGlvbmFsIG1lbWJlcnMuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElUZXh0dXJlSW5mbyBleHRlbmRzIEdMVEYyLklUZXh0dXJlSW5mbyB7XHJcbiAgICAvKiogZmFsc2Ugb3IgdW5kZWZpbmVkIGlmIHRoZSB0ZXh0dXJlIGhvbGRzIGNvbG9yIGRhdGEgKHRydWUgaWYgZGF0YSBhcmUgcm91Z2huZXNzLCBub3JtYWwsIC4uLikgKi9cclxuICAgIG5vbkNvbG9yRGF0YT86IGJvb2xlYW47XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2FkZXIgaW50ZXJmYWNlIHdpdGggYWRkaXRpb25hbCBtZW1iZXJzLlxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBJR0xURiBleHRlbmRzIEdMVEYyLklHTFRGIHtcclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIGFjY2Vzc29ycz86IElBY2Nlc3NvcltdO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIGFuaW1hdGlvbnM/OiBJQW5pbWF0aW9uW107XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgYnVmZmVycz86IElCdWZmZXJbXTtcclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBidWZmZXJWaWV3cz86IElCdWZmZXJWaWV3W107XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgY2FtZXJhcz86IElDYW1lcmFbXTtcclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBpbWFnZXM/OiBJSW1hZ2VbXTtcclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBtYXRlcmlhbHM/OiBJTWF0ZXJpYWxbXTtcclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBtZXNoZXM/OiBJTWVzaFtdO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIG5vZGVzPzogSU5vZGVbXTtcclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBzYW1wbGVycz86IElTYW1wbGVyW107XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgc2NlbmVzPzogSVNjZW5lW107XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgc2tpbnM/OiBJU2tpbltdO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHRleHR1cmVzPzogSVRleHR1cmVbXTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvYWRlciBpbnRlcmZhY2Ugd2l0aCBhZGRpdGlvbmFsIG1lbWJlcnMuXHJcbiAqL1xyXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXHJcbmV4cG9ydCBpbnRlcmZhY2UgSUtIUkxpZ2h0c1B1bmN0dWFsX0xpZ2h0IGV4dGVuZHMgR0xURjIuSUtIUkxpZ2h0c1B1bmN0dWFsX0xpZ2h0LCBJQXJyYXlJdGVtIHtcclxuICAgIC8qKiBAaGlkZGVuICovXHJcbiAgICBfYmFieWxvbkxpZ2h0PzogTGlnaHQ7XHJcbn1cclxuIiwiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWludGVybmFsLW1vZHVsZXMgKi9cclxuZXhwb3J0ICogZnJvbSBcIi4vZ2xURkxvYWRlclwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9nbFRGTG9hZGVyRXh0ZW5zaW9uXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL2dsVEZMb2FkZXJJbnRlcmZhY2VzXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL0V4dGVuc2lvbnMvaW5kZXhcIjtcclxuIiwiLyogZXNsaW50LWRpc2FibGUgQHR5cGVzY3JpcHQtZXNsaW50L25vLXVudXNlZC12YXJzICovXHJcbi8qIGVzbGludC1kaXNhYmxlIEB0eXBlc2NyaXB0LWVzbGludC9uYW1pbmctY29udmVudGlvbiAqL1xyXG5pbXBvcnQgdHlwZSAqIGFzIEdMVEYyIGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuaW1wb3J0IHR5cGUgeyBOdWxsYWJsZSB9IGZyb20gXCJjb3JlL3R5cGVzXCI7XHJcbmltcG9ydCB0eXBlIHsgT2JzZXJ2ZXIgfSBmcm9tIFwiY29yZS9NaXNjL29ic2VydmFibGVcIjtcclxuaW1wb3J0IHsgT2JzZXJ2YWJsZSB9IGZyb20gXCJjb3JlL01pc2Mvb2JzZXJ2YWJsZVwiO1xyXG5pbXBvcnQgeyBUb29scyB9IGZyb20gXCJjb3JlL01pc2MvdG9vbHNcIjtcclxuaW1wb3J0IHR5cGUgeyBDYW1lcmEgfSBmcm9tIFwiY29yZS9DYW1lcmFzL2NhbWVyYVwiO1xyXG5pbXBvcnQgdHlwZSB7IEJhc2VUZXh0dXJlIH0gZnJvbSBcImNvcmUvTWF0ZXJpYWxzL1RleHR1cmVzL2Jhc2VUZXh0dXJlXCI7XHJcbmltcG9ydCB0eXBlIHsgTWF0ZXJpYWwgfSBmcm9tIFwiY29yZS9NYXRlcmlhbHMvbWF0ZXJpYWxcIjtcclxuaW1wb3J0IHR5cGUgeyBBYnN0cmFjdE1lc2ggfSBmcm9tIFwiY29yZS9NZXNoZXMvYWJzdHJhY3RNZXNoXCI7XHJcbmltcG9ydCB0eXBlIHtcclxuICAgIElTY2VuZUxvYWRlclBsdWdpbkZhY3RvcnksXHJcbiAgICBJU2NlbmVMb2FkZXJQbHVnaW4sXHJcbiAgICBJU2NlbmVMb2FkZXJQbHVnaW5Bc3luYyxcclxuICAgIElTY2VuZUxvYWRlclByb2dyZXNzRXZlbnQsXHJcbiAgICBJU2NlbmVMb2FkZXJQbHVnaW5FeHRlbnNpb25zLFxyXG4gICAgSVNjZW5lTG9hZGVyQXN5bmNSZXN1bHQsXHJcbn0gZnJvbSBcImNvcmUvTG9hZGluZy9zY2VuZUxvYWRlclwiO1xyXG5pbXBvcnQgeyBTY2VuZUxvYWRlciB9IGZyb20gXCJjb3JlL0xvYWRpbmcvc2NlbmVMb2FkZXJcIjtcclxuaW1wb3J0IHsgQXNzZXRDb250YWluZXIgfSBmcm9tIFwiY29yZS9hc3NldENvbnRhaW5lclwiO1xyXG5pbXBvcnQgdHlwZSB7IFNjZW5lLCBJRGlzcG9zYWJsZSB9IGZyb20gXCJjb3JlL3NjZW5lXCI7XHJcbmltcG9ydCB0eXBlIHsgV2ViUmVxdWVzdCB9IGZyb20gXCJjb3JlL01pc2Mvd2ViUmVxdWVzdFwiO1xyXG5pbXBvcnQgdHlwZSB7IElGaWxlUmVxdWVzdCB9IGZyb20gXCJjb3JlL01pc2MvZmlsZVJlcXVlc3RcIjtcclxuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSBcImNvcmUvTWlzYy9sb2dnZXJcIjtcclxuaW1wb3J0IHR5cGUgeyBJRGF0YUJ1ZmZlciB9IGZyb20gXCJjb3JlL01pc2MvZGF0YVJlYWRlclwiO1xyXG5pbXBvcnQgeyBEYXRhUmVhZGVyIH0gZnJvbSBcImNvcmUvTWlzYy9kYXRhUmVhZGVyXCI7XHJcbmltcG9ydCB7IEdMVEZWYWxpZGF0aW9uIH0gZnJvbSBcIi4vZ2xURlZhbGlkYXRpb25cIjtcclxuaW1wb3J0IHR5cGUgeyBMb2FkRmlsZUVycm9yIH0gZnJvbSBcImNvcmUvTWlzYy9maWxlVG9vbHNcIjtcclxuaW1wb3J0IHsgRGVjb2RlQmFzZTY0VXJsVG9CaW5hcnkgfSBmcm9tIFwiY29yZS9NaXNjL2ZpbGVUb29sc1wiO1xyXG5pbXBvcnQgeyBSdW50aW1lRXJyb3IsIEVycm9yQ29kZXMgfSBmcm9tIFwiY29yZS9NaXNjL2Vycm9yXCI7XHJcbmltcG9ydCB0eXBlIHsgVHJhbnNmb3JtTm9kZSB9IGZyb20gXCJjb3JlL01lc2hlcy90cmFuc2Zvcm1Ob2RlXCI7XHJcbmltcG9ydCB0eXBlIHsgTW9ycGhUYXJnZXRNYW5hZ2VyIH0gZnJvbSBcImNvcmUvTW9ycGgvbW9ycGhUYXJnZXRNYW5hZ2VyXCI7XHJcblxyXG5pbnRlcmZhY2UgSUZpbGVSZXF1ZXN0SW5mbyBleHRlbmRzIElGaWxlUmVxdWVzdCB7XHJcbiAgICBfbGVuZ3RoQ29tcHV0YWJsZT86IGJvb2xlYW47XHJcbiAgICBfbG9hZGVkPzogbnVtYmVyO1xyXG4gICAgX3RvdGFsPzogbnVtYmVyO1xyXG59XHJcblxyXG5mdW5jdGlvbiByZWFkQXN5bmMoYXJyYXlCdWZmZXI6IEFycmF5QnVmZmVyLCBieXRlT2Zmc2V0OiBudW1iZXIsIGJ5dGVMZW5ndGg6IG51bWJlcik6IFByb21pc2U8VWludDhBcnJheT4ge1xyXG4gICAgdHJ5IHtcclxuICAgICAgICByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKG5ldyBVaW50OEFycmF5KGFycmF5QnVmZmVyLCBieXRlT2Zmc2V0LCBieXRlTGVuZ3RoKSk7XHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVqZWN0KGUpO1xyXG4gICAgfVxyXG59XHJcblxyXG5mdW5jdGlvbiByZWFkVmlld0FzeW5jKGFycmF5QnVmZmVyVmlldzogQXJyYXlCdWZmZXJWaWV3LCBieXRlT2Zmc2V0OiBudW1iZXIsIGJ5dGVMZW5ndGg6IG51bWJlcik6IFByb21pc2U8VWludDhBcnJheT4ge1xyXG4gICAgdHJ5IHtcclxuICAgICAgICBpZiAoKGFycmF5QnVmZmVyVmlldyBhcyBVaW50OEFycmF5KS5ieXRlT2Zmc2V0ICsgYnl0ZUxlbmd0aCA+IGFycmF5QnVmZmVyVmlldy5ieXRlTGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkFycmF5IGxlbmd0aCBvdXQgb2YgYm91bmRzLlwiKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUobmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXJWaWV3LmJ1ZmZlciwgKGFycmF5QnVmZmVyVmlldyBhcyBVaW50OEFycmF5KS5ieXRlT2Zmc2V0ICsgYnl0ZU9mZnNldCwgYnl0ZUxlbmd0aCkpO1xyXG4gICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlamVjdChlKTtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIE1vZGUgdGhhdCBkZXRlcm1pbmVzIHRoZSBjb29yZGluYXRlIHN5c3RlbSB0byB1c2UuXHJcbiAqL1xyXG5leHBvcnQgZW51bSBHTFRGTG9hZGVyQ29vcmRpbmF0ZVN5c3RlbU1vZGUge1xyXG4gICAgLyoqXHJcbiAgICAgKiBBdXRvbWF0aWNhbGx5IGNvbnZlcnQgdGhlIGdsVEYgcmlnaHQtaGFuZGVkIGRhdGEgdG8gdGhlIGFwcHJvcHJpYXRlIHN5c3RlbSBiYXNlZCBvbiB0aGUgY3VycmVudCBjb29yZGluYXRlIHN5c3RlbSBtb2RlIG9mIHRoZSBzY2VuZS5cclxuICAgICAqL1xyXG4gICAgQVVUTyxcclxuXHJcbiAgICAvKipcclxuICAgICAqIFNldHMgdGhlIHVzZVJpZ2h0SGFuZGVkU3lzdGVtIGZsYWcgb24gdGhlIHNjZW5lLlxyXG4gICAgICovXHJcbiAgICBGT1JDRV9SSUdIVF9IQU5ERUQsXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBNb2RlIHRoYXQgZGV0ZXJtaW5lcyB3aGF0IGFuaW1hdGlvbnMgd2lsbCBzdGFydC5cclxuICovXHJcbmV4cG9ydCBlbnVtIEdMVEZMb2FkZXJBbmltYXRpb25TdGFydE1vZGUge1xyXG4gICAgLyoqXHJcbiAgICAgKiBObyBhbmltYXRpb24gd2lsbCBzdGFydC5cclxuICAgICAqL1xyXG4gICAgTk9ORSxcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBmaXJzdCBhbmltYXRpb24gd2lsbCBzdGFydC5cclxuICAgICAqL1xyXG4gICAgRklSU1QsXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBBbGwgYW5pbWF0aW9ucyB3aWxsIHN0YXJ0LlxyXG4gICAgICovXHJcbiAgICBBTEwsXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBJbnRlcmZhY2UgdGhhdCBjb250YWlucyB0aGUgZGF0YSBmb3IgdGhlIGdsVEYgYXNzZXQuXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGTG9hZGVyRGF0YSB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBvYmplY3QgdGhhdCByZXByZXNlbnRzIHRoZSBnbFRGIEpTT04uXHJcbiAgICAgKi9cclxuICAgIGpzb246IE9iamVjdDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBCSU4gY2h1bmsgb2YgYSBiaW5hcnkgZ2xURi5cclxuICAgICAqL1xyXG4gICAgYmluOiBOdWxsYWJsZTxJRGF0YUJ1ZmZlcj47XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBJbnRlcmZhY2UgZm9yIGV4dGVuZGluZyB0aGUgbG9hZGVyLlxyXG4gKi9cclxuZXhwb3J0IGludGVyZmFjZSBJR0xURkxvYWRlckV4dGVuc2lvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBuYW1lIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICovXHJcbiAgICByZWFkb25seSBuYW1lOiBzdHJpbmc7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIHdoZXRoZXIgdGhpcyBleHRlbnNpb24gaXMgZW5hYmxlZC5cclxuICAgICAqL1xyXG4gICAgZW5hYmxlZDogYm9vbGVhbjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgdGhlIG9yZGVyIG9mIHRoaXMgZXh0ZW5zaW9uLlxyXG4gICAgICogVGhlIGxvYWRlciBzb3J0cyB0aGUgZXh0ZW5zaW9ucyB1c2luZyB0aGVzZSB2YWx1ZXMgd2hlbiBsb2FkaW5nLlxyXG4gICAgICovXHJcbiAgICBvcmRlcj86IG51bWJlcjtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvYWRlciBzdGF0ZS5cclxuICovXHJcbmV4cG9ydCBlbnVtIEdMVEZMb2FkZXJTdGF0ZSB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBhc3NldCBpcyBsb2FkaW5nLlxyXG4gICAgICovXHJcbiAgICBMT0FESU5HLFxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGFzc2V0IGlzIHJlYWR5IGZvciByZW5kZXJpbmcuXHJcbiAgICAgKi9cclxuICAgIFJFQURZLFxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGFzc2V0IGlzIGNvbXBsZXRlbHkgbG9hZGVkLlxyXG4gICAgICovXHJcbiAgICBDT01QTEVURSxcclxufVxyXG5cclxuLyoqIEBpbnRlcm5hbCAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGTG9hZGVyIGV4dGVuZHMgSURpc3Bvc2FibGUge1xyXG4gICAgaW1wb3J0TWVzaEFzeW5jOiAoXHJcbiAgICAgICAgbWVzaGVzTmFtZXM6IGFueSxcclxuICAgICAgICBzY2VuZTogU2NlbmUsXHJcbiAgICAgICAgY29udGFpbmVyOiBOdWxsYWJsZTxBc3NldENvbnRhaW5lcj4sXHJcbiAgICAgICAgZGF0YTogSUdMVEZMb2FkZXJEYXRhLFxyXG4gICAgICAgIHJvb3RVcmw6IHN0cmluZyxcclxuICAgICAgICBvblByb2dyZXNzPzogKGV2ZW50OiBJU2NlbmVMb2FkZXJQcm9ncmVzc0V2ZW50KSA9PiB2b2lkLFxyXG4gICAgICAgIGZpbGVOYW1lPzogc3RyaW5nXHJcbiAgICApID0+IFByb21pc2U8SVNjZW5lTG9hZGVyQXN5bmNSZXN1bHQ+O1xyXG4gICAgbG9hZEFzeW5jOiAoc2NlbmU6IFNjZW5lLCBkYXRhOiBJR0xURkxvYWRlckRhdGEsIHJvb3RVcmw6IHN0cmluZywgb25Qcm9ncmVzcz86IChldmVudDogSVNjZW5lTG9hZGVyUHJvZ3Jlc3NFdmVudCkgPT4gdm9pZCwgZmlsZU5hbWU/OiBzdHJpbmcpID0+IFByb21pc2U8dm9pZD47XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBGaWxlIGxvYWRlciBmb3IgbG9hZGluZyBnbFRGIGZpbGVzIGludG8gYSBzY2VuZS5cclxuICovXHJcbmV4cG9ydCBjbGFzcyBHTFRGRmlsZUxvYWRlciBpbXBsZW1lbnRzIElEaXNwb3NhYmxlLCBJU2NlbmVMb2FkZXJQbHVnaW5Bc3luYywgSVNjZW5lTG9hZGVyUGx1Z2luRmFjdG9yeSB7XHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgc3RhdGljIF9DcmVhdGVHTFRGMUxvYWRlcjogKHBhcmVudDogR0xURkZpbGVMb2FkZXIpID0+IElHTFRGTG9hZGVyO1xyXG5cclxuICAgIC8qKiBAaW50ZXJuYWwgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgX0NyZWF0ZUdMVEYyTG9hZGVyOiAocGFyZW50OiBHTFRGRmlsZUxvYWRlcikgPT4gSUdMVEZMb2FkZXI7XHJcblxyXG4gICAgLy8gLS0tLS0tLS0tLS0tLS1cclxuICAgIC8vIENvbW1vbiBvcHRpb25zXHJcbiAgICAvLyAtLS0tLS0tLS0tLS0tLVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmFpc2VkIHdoZW4gdGhlIGFzc2V0IGhhcyBiZWVuIHBhcnNlZFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgb25QYXJzZWRPYnNlcnZhYmxlID0gbmV3IE9ic2VydmFibGU8SUdMVEZMb2FkZXJEYXRhPigpO1xyXG5cclxuICAgIHByaXZhdGUgX29uUGFyc2VkT2JzZXJ2ZXI6IE51bGxhYmxlPE9ic2VydmVyPElHTFRGTG9hZGVyRGF0YT4+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogUmFpc2VkIHdoZW4gdGhlIGFzc2V0IGhhcyBiZWVuIHBhcnNlZFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2V0IG9uUGFyc2VkKGNhbGxiYWNrOiAobG9hZGVyRGF0YTogSUdMVEZMb2FkZXJEYXRhKSA9PiB2b2lkKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuX29uUGFyc2VkT2JzZXJ2ZXIpIHtcclxuICAgICAgICAgICAgdGhpcy5vblBhcnNlZE9ic2VydmFibGUucmVtb3ZlKHRoaXMuX29uUGFyc2VkT2JzZXJ2ZXIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLl9vblBhcnNlZE9ic2VydmVyID0gdGhpcy5vblBhcnNlZE9ic2VydmFibGUuYWRkKGNhbGxiYWNrKTtcclxuICAgIH1cclxuXHJcbiAgICAvLyAtLS0tLS0tLS0tXHJcbiAgICAvLyBWMSBvcHRpb25zXHJcbiAgICAvLyAtLS0tLS0tLS0tXHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBTZXQgdGhpcyBwcm9wZXJ0eSB0byBmYWxzZSB0byBkaXNhYmxlIGluY3JlbWVudGFsIGxvYWRpbmcgd2hpY2ggZGVsYXlzIHRoZSBsb2FkZXIgZnJvbSBjYWxsaW5nIHRoZSBzdWNjZXNzIGNhbGxiYWNrIHVudGlsIGFmdGVyIGxvYWRpbmcgdGhlIG1lc2hlcyBhbmQgc2hhZGVycy5cclxuICAgICAqIFRleHR1cmVzIGFsd2F5cyBsb2FkcyBhc3luY2hyb25vdXNseS4gRm9yIGV4YW1wbGUsIHRoZSBzdWNjZXNzIGNhbGxiYWNrIGNhbiBjb21wdXRlIHRoZSBib3VuZGluZyBpbmZvcm1hdGlvbiBvZiB0aGUgbG9hZGVkIG1lc2hlcyB3aGVuIGluY3JlbWVudGFsIGxvYWRpbmcgaXMgZGlzYWJsZWQuXHJcbiAgICAgKiBEZWZhdWx0cyB0byB0cnVlLlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgSW5jcmVtZW50YWxMb2FkaW5nID0gdHJ1ZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIFNldCB0aGlzIHByb3BlcnR5IHRvIHRydWUgaW4gb3JkZXIgdG8gd29yayB3aXRoIGhvbW9nZW5lb3VzIGNvb3JkaW5hdGVzLCBhdmFpbGFibGUgd2l0aCBzb21lIGNvbnZlcnRlcnMgYW5kIGV4cG9ydGVycy5cclxuICAgICAqIERlZmF1bHRzIHRvIGZhbHNlLiBTZWUgaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvSG9tb2dlbmVvdXNfY29vcmRpbmF0ZXMuXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIHN0YXRpYyBIb21vZ2VuZW91c0Nvb3JkaW5hdGVzID0gZmFsc2U7XHJcblxyXG4gICAgLy8gLS0tLS0tLS0tLVxyXG4gICAgLy8gVjIgb3B0aW9uc1xyXG4gICAgLy8gLS0tLS0tLS0tLVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGNvb3JkaW5hdGUgc3lzdGVtIG1vZGUuIERlZmF1bHRzIHRvIEFVVE8uXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjb29yZGluYXRlU3lzdGVtTW9kZSA9IEdMVEZMb2FkZXJDb29yZGluYXRlU3lzdGVtTW9kZS5BVVRPO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGFuaW1hdGlvbiBzdGFydCBtb2RlLiBEZWZhdWx0cyB0byBGSVJTVC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGFuaW1hdGlvblN0YXJ0TW9kZSA9IEdMVEZMb2FkZXJBbmltYXRpb25TdGFydE1vZGUuRklSU1Q7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGlmIHRoZSBsb2FkZXIgc2hvdWxkIGNvbXBpbGUgbWF0ZXJpYWxzIGJlZm9yZSByYWlzaW5nIHRoZSBzdWNjZXNzIGNhbGxiYWNrLiBEZWZhdWx0cyB0byBmYWxzZS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGNvbXBpbGVNYXRlcmlhbHMgPSBmYWxzZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgaWYgdGhlIGxvYWRlciBzaG91bGQgYWxzbyBjb21waWxlIG1hdGVyaWFscyB3aXRoIGNsaXAgcGxhbmVzLiBEZWZhdWx0cyB0byBmYWxzZS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHVzZUNsaXBQbGFuZSA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lcyBpZiB0aGUgbG9hZGVyIHNob3VsZCBjb21waWxlIHNoYWRvdyBnZW5lcmF0b3JzIGJlZm9yZSByYWlzaW5nIHRoZSBzdWNjZXNzIGNhbGxiYWNrLiBEZWZhdWx0cyB0byBmYWxzZS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGNvbXBpbGVTaGFkb3dHZW5lcmF0b3JzID0gZmFsc2U7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGlmIHRoZSBBbHBoYSBibGVuZGVkIG1hdGVyaWFscyBhcmUgb25seSBhcHBsaWVkIGFzIGNvdmVyYWdlLlxyXG4gICAgICogSWYgZmFsc2UsIChkZWZhdWx0KSBUaGUgbHVtaW5hbmNlIG9mIGVhY2ggcGl4ZWwgd2lsbCByZWR1Y2UgaXRzIG9wYWNpdHkgdG8gc2ltdWxhdGUgdGhlIGJlaGF2aW91ciBvZiBtb3N0IHBoeXNpY2FsIG1hdGVyaWFscy5cclxuICAgICAqIElmIHRydWUsIG5vIGV4dHJhIGVmZmVjdHMgYXJlIGFwcGxpZWQgdG8gdHJhbnNwYXJlbnQgcGl4ZWxzLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdHJhbnNwYXJlbmN5QXNDb3ZlcmFnZSA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRGVmaW5lcyBpZiB0aGUgbG9hZGVyIHNob3VsZCB1c2UgcmFuZ2UgcmVxdWVzdHMgd2hlbiBsb2FkIGJpbmFyeSBnbFRGIGZpbGVzIGZyb20gSFRUUC5cclxuICAgICAqIEVuYWJsaW5nIHdpbGwgZGlzYWJsZSBvZmZsaW5lIHN1cHBvcnQgYW5kIGdsVEYgdmFsaWRhdG9yLlxyXG4gICAgICogRGVmYXVsdHMgdG8gZmFsc2UuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyB1c2VSYW5nZVJlcXVlc3RzID0gZmFsc2U7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGlmIHRoZSBsb2FkZXIgc2hvdWxkIGNyZWF0ZSBpbnN0YW5jZXMgd2hlbiBtdWx0aXBsZSBnbFRGIG5vZGVzIHBvaW50IHRvIHRoZSBzYW1lIGdsVEYgbWVzaC4gRGVmYXVsdHMgdG8gdHJ1ZS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGNyZWF0ZUluc3RhbmNlcyA9IHRydWU7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGlmIHRoZSBsb2FkZXIgc2hvdWxkIGFsd2F5cyBjb21wdXRlIHRoZSBib3VuZGluZyBib3hlcyBvZiBtZXNoZXMgYW5kIG5vdCB1c2UgdGhlIG1pbi9tYXggdmFsdWVzIGZyb20gdGhlIHBvc2l0aW9uIGFjY2Vzc29yLiBEZWZhdWx0cyB0byBmYWxzZS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGFsd2F5c0NvbXB1dGVCb3VuZGluZ0JveCA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSWYgdHJ1ZSwgbG9hZCBhbGwgbWF0ZXJpYWxzIGRlZmluZWQgaW4gdGhlIGZpbGUsIGV2ZW4gaWYgbm90IHVzZWQgYnkgYW55IG1lc2guIERlZmF1bHRzIHRvIGZhbHNlLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZEFsbE1hdGVyaWFscyA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSWYgdHJ1ZSwgbG9hZCBvbmx5IHRoZSBtYXRlcmlhbHMgZGVmaW5lZCBpbiB0aGUgZmlsZS4gRGVmYXVsdHMgdG8gZmFsc2UuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkT25seU1hdGVyaWFscyA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogSWYgdHJ1ZSwgZG8gbm90IGxvYWQgYW55IG1hdGVyaWFscyBkZWZpbmVkIGluIHRoZSBmaWxlLiBEZWZhdWx0cyB0byBmYWxzZS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHNraXBNYXRlcmlhbHMgPSBmYWxzZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIElmIHRydWUsIGxvYWQgdGhlIGNvbG9yIChnYW1tYSBlbmNvZGVkKSB0ZXh0dXJlcyBpbnRvIHNSR0IgYnVmZmVycyAoaWYgc3VwcG9ydGVkIGJ5IHRoZSBHUFUpLCB3aGljaCB3aWxsIHlpZWxkIG1vcmUgYWNjdXJhdGUgcmVzdWx0cyB3aGVuIHNhbXBsaW5nIHRoZSB0ZXh0dXJlLiBEZWZhdWx0cyB0byB0cnVlLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdXNlU1JHQkJ1ZmZlcnMgPSB0cnVlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogV2hlbiBsb2FkaW5nIGdsVEYgYW5pbWF0aW9ucywgd2hpY2ggYXJlIGRlZmluZWQgaW4gc2Vjb25kcywgdGFyZ2V0IHRoZW0gdG8gdGhpcyBGUFMuIERlZmF1bHRzIHRvIDYwLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdGFyZ2V0RnBzID0gNjA7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGlmIHRoZSBsb2FkZXIgc2hvdWxkIGFsd2F5cyBjb21wdXRlIHRoZSBuZWFyZXN0IGNvbW1vbiBhbmNlc3RvciBvZiB0aGUgc2tlbGV0b24gam9pbnRzIGluc3RlYWQgb2YgdXNpbmcgYHNraW4uc2tlbGV0b25gLiBEZWZhdWx0cyB0byBmYWxzZS5cclxuICAgICAqIFNldCB0aGlzIHRvIHRydWUgaWYgbG9hZGluZyBhc3NldHMgd2l0aCBpbnZhbGlkIGBza2luLnNrZWxldG9uYCB2YWx1ZXMuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBhbHdheXNDb21wdXRlU2tlbGV0b25Sb290Tm9kZSA9IGZhbHNlO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogRnVuY3Rpb24gY2FsbGVkIGJlZm9yZSBsb2FkaW5nIGEgdXJsIHJlZmVyZW5jZWQgYnkgdGhlIGFzc2V0LlxyXG4gICAgICogQHBhcmFtIHVybFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcHJlcHJvY2Vzc1VybEFzeW5jID0gKHVybDogc3RyaW5nKSA9PiBQcm9taXNlLnJlc29sdmUodXJsKTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIE9ic2VydmFibGUgcmFpc2VkIHdoZW4gdGhlIGxvYWRlciBjcmVhdGVzIGEgbWVzaCBhZnRlciBwYXJzaW5nIHRoZSBnbFRGIHByb3BlcnRpZXMgb2YgdGhlIG1lc2guXHJcbiAgICAgKiBOb3RlIHRoYXQgdGhlIG9ic2VydmFibGUgaXMgcmFpc2VkIGFzIHNvb24gYXMgdGhlIG1lc2ggb2JqZWN0IGlzIGNyZWF0ZWQsIG1lYW5pbmcgc29tZSBkYXRhIG1heSBub3QgaGF2ZSBiZWVuIHNldHVwIHlldCBmb3IgdGhpcyBtZXNoICh2ZXJ0ZXggZGF0YSwgbW9ycGggdGFyZ2V0cywgbWF0ZXJpYWwsIC4uLilcclxuICAgICAqL1xyXG4gICAgcHVibGljIHJlYWRvbmx5IG9uTWVzaExvYWRlZE9ic2VydmFibGUgPSBuZXcgT2JzZXJ2YWJsZTxBYnN0cmFjdE1lc2g+KCk7XHJcblxyXG4gICAgcHJpdmF0ZSBfb25NZXNoTG9hZGVkT2JzZXJ2ZXI6IE51bGxhYmxlPE9ic2VydmVyPEFic3RyYWN0TWVzaD4+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2FsbGJhY2sgcmFpc2VkIHdoZW4gdGhlIGxvYWRlciBjcmVhdGVzIGEgbWVzaCBhZnRlciBwYXJzaW5nIHRoZSBnbFRGIHByb3BlcnRpZXMgb2YgdGhlIG1lc2guXHJcbiAgICAgKiBOb3RlIHRoYXQgdGhlIGNhbGxiYWNrIGlzIGNhbGxlZCBhcyBzb29uIGFzIHRoZSBtZXNoIG9iamVjdCBpcyBjcmVhdGVkLCBtZWFuaW5nIHNvbWUgZGF0YSBtYXkgbm90IGhhdmUgYmVlbiBzZXR1cCB5ZXQgZm9yIHRoaXMgbWVzaCAodmVydGV4IGRhdGEsIG1vcnBoIHRhcmdldHMsIG1hdGVyaWFsLCAuLi4pXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzZXQgb25NZXNoTG9hZGVkKGNhbGxiYWNrOiAobWVzaDogQWJzdHJhY3RNZXNoKSA9PiB2b2lkKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuX29uTWVzaExvYWRlZE9ic2VydmVyKSB7XHJcbiAgICAgICAgICAgIHRoaXMub25NZXNoTG9hZGVkT2JzZXJ2YWJsZS5yZW1vdmUodGhpcy5fb25NZXNoTG9hZGVkT2JzZXJ2ZXIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLl9vbk1lc2hMb2FkZWRPYnNlcnZlciA9IHRoaXMub25NZXNoTG9hZGVkT2JzZXJ2YWJsZS5hZGQoY2FsbGJhY2spO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2FsbGJhY2sgcmFpc2VkIHdoZW4gdGhlIGxvYWRlciBjcmVhdGVzIGEgc2tpbiBhZnRlciBwYXJzaW5nIHRoZSBnbFRGIHByb3BlcnRpZXMgb2YgdGhlIHNraW4gbm9kZS5cclxuICAgICAqIEBzZWUgaHR0cHM6Ly9kb2MuYmFieWxvbmpzLmNvbS9mZWF0dXJlcy9mZWF0dXJlc0RlZXBEaXZlL2ltcG9ydGVycy9nbFRGL2dsVEZTa2lubmluZyNpZ25vcmluZy10aGUtdHJhbnNmb3JtLW9mLXRoZS1za2lubmVkLW1lc2hcclxuICAgICAqIEBwYXJhbSBub2RlIC0gdGhlIHRyYW5zZm9ybSBub2RlIHRoYXQgY29ycmVzcG9uZHMgdG8gdGhlIG9yaWdpbmFsIGdsVEYgc2tpbiBub2RlIHVzZWQgZm9yIGFuaW1hdGlvbnNcclxuICAgICAqIEBwYXJhbSBza2lubmVkTm9kZSAtIHRoZSB0cmFuc2Zvcm0gbm9kZSB0aGF0IGlzIHRoZSBza2lubmVkIG1lc2ggaXRzZWxmIG9yIHRoZSBwYXJlbnQgb2YgdGhlIHNraW5uZWQgbWVzaGVzXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyByZWFkb25seSBvblNraW5Mb2FkZWRPYnNlcnZhYmxlID0gbmV3IE9ic2VydmFibGU8eyBub2RlOiBUcmFuc2Zvcm1Ob2RlOyBza2lubmVkTm9kZTogVHJhbnNmb3JtTm9kZSB9PigpO1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogT2JzZXJ2YWJsZSByYWlzZWQgd2hlbiB0aGUgbG9hZGVyIGNyZWF0ZXMgYSB0ZXh0dXJlIGFmdGVyIHBhcnNpbmcgdGhlIGdsVEYgcHJvcGVydGllcyBvZiB0aGUgdGV4dHVyZS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHJlYWRvbmx5IG9uVGV4dHVyZUxvYWRlZE9ic2VydmFibGUgPSBuZXcgT2JzZXJ2YWJsZTxCYXNlVGV4dHVyZT4oKTtcclxuXHJcbiAgICBwcml2YXRlIF9vblRleHR1cmVMb2FkZWRPYnNlcnZlcjogTnVsbGFibGU8T2JzZXJ2ZXI8QmFzZVRleHR1cmU+PjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENhbGxiYWNrIHJhaXNlZCB3aGVuIHRoZSBsb2FkZXIgY3JlYXRlcyBhIHRleHR1cmUgYWZ0ZXIgcGFyc2luZyB0aGUgZ2xURiBwcm9wZXJ0aWVzIG9mIHRoZSB0ZXh0dXJlLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2V0IG9uVGV4dHVyZUxvYWRlZChjYWxsYmFjazogKHRleHR1cmU6IEJhc2VUZXh0dXJlKSA9PiB2b2lkKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuX29uVGV4dHVyZUxvYWRlZE9ic2VydmVyKSB7XHJcbiAgICAgICAgICAgIHRoaXMub25UZXh0dXJlTG9hZGVkT2JzZXJ2YWJsZS5yZW1vdmUodGhpcy5fb25UZXh0dXJlTG9hZGVkT2JzZXJ2ZXIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLl9vblRleHR1cmVMb2FkZWRPYnNlcnZlciA9IHRoaXMub25UZXh0dXJlTG9hZGVkT2JzZXJ2YWJsZS5hZGQoY2FsbGJhY2spO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogT2JzZXJ2YWJsZSByYWlzZWQgd2hlbiB0aGUgbG9hZGVyIGNyZWF0ZXMgYSBtYXRlcmlhbCBhZnRlciBwYXJzaW5nIHRoZSBnbFRGIHByb3BlcnRpZXMgb2YgdGhlIG1hdGVyaWFsLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgb25NYXRlcmlhbExvYWRlZE9ic2VydmFibGUgPSBuZXcgT2JzZXJ2YWJsZTxNYXRlcmlhbD4oKTtcclxuXHJcbiAgICBwcml2YXRlIF9vbk1hdGVyaWFsTG9hZGVkT2JzZXJ2ZXI6IE51bGxhYmxlPE9ic2VydmVyPE1hdGVyaWFsPj47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDYWxsYmFjayByYWlzZWQgd2hlbiB0aGUgbG9hZGVyIGNyZWF0ZXMgYSBtYXRlcmlhbCBhZnRlciBwYXJzaW5nIHRoZSBnbFRGIHByb3BlcnRpZXMgb2YgdGhlIG1hdGVyaWFsLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2V0IG9uTWF0ZXJpYWxMb2FkZWQoY2FsbGJhY2s6IChtYXRlcmlhbDogTWF0ZXJpYWwpID0+IHZvaWQpIHtcclxuICAgICAgICBpZiAodGhpcy5fb25NYXRlcmlhbExvYWRlZE9ic2VydmVyKSB7XHJcbiAgICAgICAgICAgIHRoaXMub25NYXRlcmlhbExvYWRlZE9ic2VydmFibGUucmVtb3ZlKHRoaXMuX29uTWF0ZXJpYWxMb2FkZWRPYnNlcnZlcik7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuX29uTWF0ZXJpYWxMb2FkZWRPYnNlcnZlciA9IHRoaXMub25NYXRlcmlhbExvYWRlZE9ic2VydmFibGUuYWRkKGNhbGxiYWNrKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE9ic2VydmFibGUgcmFpc2VkIHdoZW4gdGhlIGxvYWRlciBjcmVhdGVzIGEgY2FtZXJhIGFmdGVyIHBhcnNpbmcgdGhlIGdsVEYgcHJvcGVydGllcyBvZiB0aGUgY2FtZXJhLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgb25DYW1lcmFMb2FkZWRPYnNlcnZhYmxlID0gbmV3IE9ic2VydmFibGU8Q2FtZXJhPigpO1xyXG5cclxuICAgIHByaXZhdGUgX29uQ2FtZXJhTG9hZGVkT2JzZXJ2ZXI6IE51bGxhYmxlPE9ic2VydmVyPENhbWVyYT4+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2FsbGJhY2sgcmFpc2VkIHdoZW4gdGhlIGxvYWRlciBjcmVhdGVzIGEgY2FtZXJhIGFmdGVyIHBhcnNpbmcgdGhlIGdsVEYgcHJvcGVydGllcyBvZiB0aGUgY2FtZXJhLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2V0IG9uQ2FtZXJhTG9hZGVkKGNhbGxiYWNrOiAoY2FtZXJhOiBDYW1lcmEpID0+IHZvaWQpIHtcclxuICAgICAgICBpZiAodGhpcy5fb25DYW1lcmFMb2FkZWRPYnNlcnZlcikge1xyXG4gICAgICAgICAgICB0aGlzLm9uQ2FtZXJhTG9hZGVkT2JzZXJ2YWJsZS5yZW1vdmUodGhpcy5fb25DYW1lcmFMb2FkZWRPYnNlcnZlcik7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuX29uQ2FtZXJhTG9hZGVkT2JzZXJ2ZXIgPSB0aGlzLm9uQ2FtZXJhTG9hZGVkT2JzZXJ2YWJsZS5hZGQoY2FsbGJhY2spO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogT2JzZXJ2YWJsZSByYWlzZWQgd2hlbiB0aGUgYXNzZXQgaXMgY29tcGxldGVseSBsb2FkZWQsIGltbWVkaWF0ZWx5IGJlZm9yZSB0aGUgbG9hZGVyIGlzIGRpc3Bvc2VkLlxyXG4gICAgICogRm9yIGFzc2V0cyB3aXRoIExPRHMsIHJhaXNlZCB3aGVuIGFsbCBvZiB0aGUgTE9EcyBhcmUgY29tcGxldGUuXHJcbiAgICAgKiBGb3IgYXNzZXRzIHdpdGhvdXQgTE9EcywgcmFpc2VkIHdoZW4gdGhlIG1vZGVsIGlzIGNvbXBsZXRlLCBpbW1lZGlhdGVseSBhZnRlciB0aGUgbG9hZGVyIHJlc29sdmVzIHRoZSByZXR1cm5lZCBwcm9taXNlLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgb25Db21wbGV0ZU9ic2VydmFibGUgPSBuZXcgT2JzZXJ2YWJsZTx2b2lkPigpO1xyXG5cclxuICAgIHByaXZhdGUgX29uQ29tcGxldGVPYnNlcnZlcjogTnVsbGFibGU8T2JzZXJ2ZXI8dm9pZD4+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2FsbGJhY2sgcmFpc2VkIHdoZW4gdGhlIGFzc2V0IGlzIGNvbXBsZXRlbHkgbG9hZGVkLCBpbW1lZGlhdGVseSBiZWZvcmUgdGhlIGxvYWRlciBpcyBkaXNwb3NlZC5cclxuICAgICAqIEZvciBhc3NldHMgd2l0aCBMT0RzLCByYWlzZWQgd2hlbiBhbGwgb2YgdGhlIExPRHMgYXJlIGNvbXBsZXRlLlxyXG4gICAgICogRm9yIGFzc2V0cyB3aXRob3V0IExPRHMsIHJhaXNlZCB3aGVuIHRoZSBtb2RlbCBpcyBjb21wbGV0ZSwgaW1tZWRpYXRlbHkgYWZ0ZXIgdGhlIGxvYWRlciByZXNvbHZlcyB0aGUgcmV0dXJuZWQgcHJvbWlzZS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHNldCBvbkNvbXBsZXRlKGNhbGxiYWNrOiAoKSA9PiB2b2lkKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuX29uQ29tcGxldGVPYnNlcnZlcikge1xyXG4gICAgICAgICAgICB0aGlzLm9uQ29tcGxldGVPYnNlcnZhYmxlLnJlbW92ZSh0aGlzLl9vbkNvbXBsZXRlT2JzZXJ2ZXIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLl9vbkNvbXBsZXRlT2JzZXJ2ZXIgPSB0aGlzLm9uQ29tcGxldGVPYnNlcnZhYmxlLmFkZChjYWxsYmFjayk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPYnNlcnZhYmxlIHJhaXNlZCB3aGVuIGFuIGVycm9yIG9jY3Vycy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHJlYWRvbmx5IG9uRXJyb3JPYnNlcnZhYmxlID0gbmV3IE9ic2VydmFibGU8YW55PigpO1xyXG5cclxuICAgIHByaXZhdGUgX29uRXJyb3JPYnNlcnZlcjogTnVsbGFibGU8T2JzZXJ2ZXI8YW55Pj47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBDYWxsYmFjayByYWlzZWQgd2hlbiBhbiBlcnJvciBvY2N1cnMuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzZXQgb25FcnJvcihjYWxsYmFjazogKHJlYXNvbjogYW55KSA9PiB2b2lkKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuX29uRXJyb3JPYnNlcnZlcikge1xyXG4gICAgICAgICAgICB0aGlzLm9uRXJyb3JPYnNlcnZhYmxlLnJlbW92ZSh0aGlzLl9vbkVycm9yT2JzZXJ2ZXIpO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLl9vbkVycm9yT2JzZXJ2ZXIgPSB0aGlzLm9uRXJyb3JPYnNlcnZhYmxlLmFkZChjYWxsYmFjayk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPYnNlcnZhYmxlIHJhaXNlZCBhZnRlciB0aGUgbG9hZGVyIGlzIGRpc3Bvc2VkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmVhZG9ubHkgb25EaXNwb3NlT2JzZXJ2YWJsZSA9IG5ldyBPYnNlcnZhYmxlPHZvaWQ+KCk7XHJcblxyXG4gICAgcHJpdmF0ZSBfb25EaXNwb3NlT2JzZXJ2ZXI6IE51bGxhYmxlPE9ic2VydmVyPHZvaWQ+PjtcclxuXHJcbiAgICAvKipcclxuICAgICAqIENhbGxiYWNrIHJhaXNlZCBhZnRlciB0aGUgbG9hZGVyIGlzIGRpc3Bvc2VkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2V0IG9uRGlzcG9zZShjYWxsYmFjazogKCkgPT4gdm9pZCkge1xyXG4gICAgICAgIGlmICh0aGlzLl9vbkRpc3Bvc2VPYnNlcnZlcikge1xyXG4gICAgICAgICAgICB0aGlzLm9uRGlzcG9zZU9ic2VydmFibGUucmVtb3ZlKHRoaXMuX29uRGlzcG9zZU9ic2VydmVyKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5fb25EaXNwb3NlT2JzZXJ2ZXIgPSB0aGlzLm9uRGlzcG9zZU9ic2VydmFibGUuYWRkKGNhbGxiYWNrKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIE9ic2VydmFibGUgcmFpc2VkIGFmdGVyIGEgbG9hZGVyIGV4dGVuc2lvbiBpcyBjcmVhdGVkLlxyXG4gICAgICogU2V0IGFkZGl0aW9uYWwgb3B0aW9ucyBmb3IgYSBsb2FkZXIgZXh0ZW5zaW9uIGluIHRoaXMgZXZlbnQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyByZWFkb25seSBvbkV4dGVuc2lvbkxvYWRlZE9ic2VydmFibGUgPSBuZXcgT2JzZXJ2YWJsZTxJR0xURkxvYWRlckV4dGVuc2lvbj4oKTtcclxuXHJcbiAgICBwcml2YXRlIF9vbkV4dGVuc2lvbkxvYWRlZE9ic2VydmVyOiBOdWxsYWJsZTxPYnNlcnZlcjxJR0xURkxvYWRlckV4dGVuc2lvbj4+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2FsbGJhY2sgcmFpc2VkIGFmdGVyIGEgbG9hZGVyIGV4dGVuc2lvbiBpcyBjcmVhdGVkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2V0IG9uRXh0ZW5zaW9uTG9hZGVkKGNhbGxiYWNrOiAoZXh0ZW5zaW9uOiBJR0xURkxvYWRlckV4dGVuc2lvbikgPT4gdm9pZCkge1xyXG4gICAgICAgIGlmICh0aGlzLl9vbkV4dGVuc2lvbkxvYWRlZE9ic2VydmVyKSB7XHJcbiAgICAgICAgICAgIHRoaXMub25FeHRlbnNpb25Mb2FkZWRPYnNlcnZhYmxlLnJlbW92ZSh0aGlzLl9vbkV4dGVuc2lvbkxvYWRlZE9ic2VydmVyKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5fb25FeHRlbnNpb25Mb2FkZWRPYnNlcnZlciA9IHRoaXMub25FeHRlbnNpb25Mb2FkZWRPYnNlcnZhYmxlLmFkZChjYWxsYmFjayk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGlmIHRoZSBsb2FkZXIgbG9nZ2luZyBpcyBlbmFibGVkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgZ2V0IGxvZ2dpbmdFbmFibGVkKCk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiB0aGlzLl9sb2dnaW5nRW5hYmxlZDtcclxuICAgIH1cclxuXHJcbiAgICBwdWJsaWMgc2V0IGxvZ2dpbmdFbmFibGVkKHZhbHVlOiBib29sZWFuKSB7XHJcbiAgICAgICAgaWYgKHRoaXMuX2xvZ2dpbmdFbmFibGVkID09PSB2YWx1ZSkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLl9sb2dnaW5nRW5hYmxlZCA9IHZhbHVlO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5fbG9nZ2luZ0VuYWJsZWQpIHtcclxuICAgICAgICAgICAgdGhpcy5fbG9nID0gdGhpcy5fbG9nRW5hYmxlZDtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLl9sb2cgPSB0aGlzLl9sb2dEaXNhYmxlZDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEZWZpbmVzIGlmIHRoZSBsb2FkZXIgc2hvdWxkIGNhcHR1cmUgcGVyZm9ybWFuY2UgY291bnRlcnMuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBnZXQgY2FwdHVyZVBlcmZvcm1hbmNlQ291bnRlcnMoKTogYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NhcHR1cmVQZXJmb3JtYW5jZUNvdW50ZXJzO1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBzZXQgY2FwdHVyZVBlcmZvcm1hbmNlQ291bnRlcnModmFsdWU6IGJvb2xlYW4pIHtcclxuICAgICAgICBpZiAodGhpcy5fY2FwdHVyZVBlcmZvcm1hbmNlQ291bnRlcnMgPT09IHZhbHVlKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuX2NhcHR1cmVQZXJmb3JtYW5jZUNvdW50ZXJzID0gdmFsdWU7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLl9jYXB0dXJlUGVyZm9ybWFuY2VDb3VudGVycykge1xyXG4gICAgICAgICAgICB0aGlzLl9zdGFydFBlcmZvcm1hbmNlQ291bnRlciA9IHRoaXMuX3N0YXJ0UGVyZm9ybWFuY2VDb3VudGVyRW5hYmxlZDtcclxuICAgICAgICAgICAgdGhpcy5fZW5kUGVyZm9ybWFuY2VDb3VudGVyID0gdGhpcy5fZW5kUGVyZm9ybWFuY2VDb3VudGVyRW5hYmxlZDtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICB0aGlzLl9zdGFydFBlcmZvcm1hbmNlQ291bnRlciA9IHRoaXMuX3N0YXJ0UGVyZm9ybWFuY2VDb3VudGVyRGlzYWJsZWQ7XHJcbiAgICAgICAgICAgIHRoaXMuX2VuZFBlcmZvcm1hbmNlQ291bnRlciA9IHRoaXMuX2VuZFBlcmZvcm1hbmNlQ291bnRlckRpc2FibGVkO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIERlZmluZXMgaWYgdGhlIGxvYWRlciBzaG91bGQgdmFsaWRhdGUgdGhlIGFzc2V0LlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdmFsaWRhdGUgPSBmYWxzZTtcclxuXHJcbiAgICAvKipcclxuICAgICAqIE9ic2VydmFibGUgcmFpc2VkIGFmdGVyIHZhbGlkYXRpb24gd2hlbiB2YWxpZGF0ZSBpcyBzZXQgdG8gdHJ1ZS4gVGhlIGV2ZW50IGRhdGEgaXMgdGhlIHJlc3VsdCBvZiB0aGUgdmFsaWRhdGlvbi5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHJlYWRvbmx5IG9uVmFsaWRhdGVkT2JzZXJ2YWJsZSA9IG5ldyBPYnNlcnZhYmxlPEdMVEYyLklHTFRGVmFsaWRhdGlvblJlc3VsdHM+KCk7XHJcblxyXG4gICAgcHJpdmF0ZSBfb25WYWxpZGF0ZWRPYnNlcnZlcjogTnVsbGFibGU8T2JzZXJ2ZXI8R0xURjIuSUdMVEZWYWxpZGF0aW9uUmVzdWx0cz4+O1xyXG5cclxuICAgIC8qKlxyXG4gICAgICogQ2FsbGJhY2sgcmFpc2VkIGFmdGVyIGEgbG9hZGVyIGV4dGVuc2lvbiBpcyBjcmVhdGVkLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc2V0IG9uVmFsaWRhdGVkKGNhbGxiYWNrOiAocmVzdWx0czogR0xURjIuSUdMVEZWYWxpZGF0aW9uUmVzdWx0cykgPT4gdm9pZCkge1xyXG4gICAgICAgIGlmICh0aGlzLl9vblZhbGlkYXRlZE9ic2VydmVyKSB7XHJcbiAgICAgICAgICAgIHRoaXMub25WYWxpZGF0ZWRPYnNlcnZhYmxlLnJlbW92ZSh0aGlzLl9vblZhbGlkYXRlZE9ic2VydmVyKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgdGhpcy5fb25WYWxpZGF0ZWRPYnNlcnZlciA9IHRoaXMub25WYWxpZGF0ZWRPYnNlcnZhYmxlLmFkZChjYWxsYmFjayk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9hZGVyOiBOdWxsYWJsZTxJR0xURkxvYWRlcj4gPSBudWxsO1xyXG4gICAgcHJpdmF0ZSBfc3RhdGU6IE51bGxhYmxlPEdMVEZMb2FkZXJTdGF0ZT4gPSBudWxsO1xyXG4gICAgcHJpdmF0ZSBfcHJvZ3Jlc3NDYWxsYmFjaz86IChldmVudDogSVNjZW5lTG9hZGVyUHJvZ3Jlc3NFdmVudCkgPT4gdm9pZDtcclxuICAgIHByaXZhdGUgX3JlcXVlc3RzID0gbmV3IEFycmF5PElGaWxlUmVxdWVzdEluZm8+KCk7XHJcblxyXG4gICAgcHJpdmF0ZSBzdGF0aWMgX01hZ2ljQmFzZTY0RW5jb2RlZCA9IFwiWjJ4VVJnXCI7IC8vIFwiZ2xURlwiIGJhc2U2NCBlbmNvZGVkICh3aXRob3V0IHRoZSBxdW90ZXMhKVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogTmFtZSBvZiB0aGUgbG9hZGVyIChcImdsdGZcIilcclxuICAgICAqL1xyXG4gICAgcHVibGljIG5hbWUgPSBcImdsdGZcIjtcclxuXHJcbiAgICAvKiogQGludGVybmFsICovXHJcbiAgICBwdWJsaWMgZXh0ZW5zaW9uczogSVNjZW5lTG9hZGVyUGx1Z2luRXh0ZW5zaW9ucyA9IHtcclxuICAgICAgICBcIi5nbHRmXCI6IHsgaXNCaW5hcnk6IGZhbHNlIH0sXHJcbiAgICAgICAgXCIuZ2xiXCI6IHsgaXNCaW5hcnk6IHRydWUgfSxcclxuICAgIH07XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBEaXNwb3NlcyB0aGUgbG9hZGVyLCByZWxlYXNlcyByZXNvdXJjZXMgZHVyaW5nIGxvYWQsIGFuZCBjYW5jZWxzIGFueSBvdXRzdGFuZGluZyByZXF1ZXN0cy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGRpc3Bvc2UoKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKHRoaXMuX2xvYWRlcikge1xyXG4gICAgICAgICAgICB0aGlzLl9sb2FkZXIuZGlzcG9zZSgpO1xyXG4gICAgICAgICAgICB0aGlzLl9sb2FkZXIgPSBudWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgZm9yIChjb25zdCByZXF1ZXN0IG9mIHRoaXMuX3JlcXVlc3RzKSB7XHJcbiAgICAgICAgICAgIHJlcXVlc3QuYWJvcnQoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuX3JlcXVlc3RzLmxlbmd0aCA9IDA7XHJcblxyXG4gICAgICAgIGRlbGV0ZSB0aGlzLl9wcm9ncmVzc0NhbGxiYWNrO1xyXG5cclxuICAgICAgICB0aGlzLnByZXByb2Nlc3NVcmxBc3luYyA9ICh1cmwpID0+IFByb21pc2UucmVzb2x2ZSh1cmwpO1xyXG5cclxuICAgICAgICB0aGlzLm9uTWVzaExvYWRlZE9ic2VydmFibGUuY2xlYXIoKTtcclxuICAgICAgICB0aGlzLm9uU2tpbkxvYWRlZE9ic2VydmFibGUuY2xlYXIoKTtcclxuICAgICAgICB0aGlzLm9uVGV4dHVyZUxvYWRlZE9ic2VydmFibGUuY2xlYXIoKTtcclxuICAgICAgICB0aGlzLm9uTWF0ZXJpYWxMb2FkZWRPYnNlcnZhYmxlLmNsZWFyKCk7XHJcbiAgICAgICAgdGhpcy5vbkNhbWVyYUxvYWRlZE9ic2VydmFibGUuY2xlYXIoKTtcclxuICAgICAgICB0aGlzLm9uQ29tcGxldGVPYnNlcnZhYmxlLmNsZWFyKCk7XHJcbiAgICAgICAgdGhpcy5vbkV4dGVuc2lvbkxvYWRlZE9ic2VydmFibGUuY2xlYXIoKTtcclxuXHJcbiAgICAgICAgdGhpcy5vbkRpc3Bvc2VPYnNlcnZhYmxlLm5vdGlmeU9ic2VydmVycyh1bmRlZmluZWQpO1xyXG4gICAgICAgIHRoaXMub25EaXNwb3NlT2JzZXJ2YWJsZS5jbGVhcigpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBsb2FkRmlsZShcclxuICAgICAgICBzY2VuZTogU2NlbmUsXHJcbiAgICAgICAgZmlsZU9yVXJsOiBGaWxlIHwgc3RyaW5nIHwgQXJyYXlCdWZmZXJWaWV3LFxyXG4gICAgICAgIHJvb3RVcmw6IHN0cmluZyxcclxuICAgICAgICBvblN1Y2Nlc3M6IChkYXRhOiBhbnksIHJlc3BvbnNlVVJMPzogc3RyaW5nKSA9PiB2b2lkLFxyXG4gICAgICAgIG9uUHJvZ3Jlc3M/OiAoZXY6IElTY2VuZUxvYWRlclByb2dyZXNzRXZlbnQpID0+IHZvaWQsXHJcbiAgICAgICAgdXNlQXJyYXlCdWZmZXI/OiBib29sZWFuLFxyXG4gICAgICAgIG9uRXJyb3I/OiAocmVxdWVzdD86IFdlYlJlcXVlc3QsIGV4Y2VwdGlvbj86IExvYWRGaWxlRXJyb3IpID0+IHZvaWQsXHJcbiAgICAgICAgbmFtZT86IHN0cmluZ1xyXG4gICAgKTogTnVsbGFibGU8SUZpbGVSZXF1ZXN0PiB7XHJcbiAgICAgICAgaWYgKEFycmF5QnVmZmVyLmlzVmlldyhmaWxlT3JVcmwpKSB7XHJcbiAgICAgICAgICAgIHRoaXMuX2xvYWRCaW5hcnkoc2NlbmUsIGZpbGVPclVybCBhcyBBcnJheUJ1ZmZlclZpZXcsIHJvb3RVcmwsIG9uU3VjY2Vzcywgb25FcnJvciwgbmFtZSk7XHJcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5fcHJvZ3Jlc3NDYWxsYmFjayA9IG9uUHJvZ3Jlc3M7XHJcblxyXG4gICAgICAgIGNvbnN0IGZpbGVOYW1lID0gKGZpbGVPclVybCBhcyBGaWxlKS5uYW1lIHx8IFRvb2xzLkdldEZpbGVuYW1lKGZpbGVPclVybCBhcyBzdHJpbmcpO1xyXG5cclxuICAgICAgICBpZiAodXNlQXJyYXlCdWZmZXIpIHtcclxuICAgICAgICAgICAgaWYgKHRoaXMudXNlUmFuZ2VSZXF1ZXN0cykge1xyXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMudmFsaWRhdGUpIHtcclxuICAgICAgICAgICAgICAgICAgICBMb2dnZXIuV2FybihcImdsVEYgdmFsaWRhdGlvbiBpcyBub3Qgc3VwcG9ydGVkIHdoZW4gcmFuZ2UgcmVxdWVzdHMgYXJlIGVuYWJsZWRcIik7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgY29uc3QgZmlsZVJlcXVlc3Q6IElGaWxlUmVxdWVzdCA9IHtcclxuICAgICAgICAgICAgICAgICAgICBhYm9ydDogKCkgPT4ge30sXHJcbiAgICAgICAgICAgICAgICAgICAgb25Db21wbGV0ZU9ic2VydmFibGU6IG5ldyBPYnNlcnZhYmxlPElGaWxlUmVxdWVzdD4oKSxcclxuICAgICAgICAgICAgICAgIH07XHJcblxyXG4gICAgICAgICAgICAgICAgY29uc3QgZGF0YUJ1ZmZlciA9IHtcclxuICAgICAgICAgICAgICAgICAgICByZWFkQXN5bmM6IChieXRlT2Zmc2V0OiBudW1iZXIsIGJ5dGVMZW5ndGg6IG51bWJlcikgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gbmV3IFByb21pc2U8QXJyYXlCdWZmZXJWaWV3PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9sb2FkRmlsZShcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzY2VuZSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWxlT3JVcmwgYXMgRmlsZSB8IHN0cmluZyxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKG5ldyBVaW50OEFycmF5KGRhdGEgYXMgQXJyYXlCdWZmZXIpKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRydWUsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKGVycm9yKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAod2ViUmVxdWVzdCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3ZWJSZXF1ZXN0LnNldFJlcXVlc3RIZWFkZXIoXCJSYW5nZVwiLCBgYnl0ZXM9JHtieXRlT2Zmc2V0fS0ke2J5dGVPZmZzZXQgKyBieXRlTGVuZ3RoIC0gMX1gKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgICAgIGJ5dGVMZW5ndGg6IDAsXHJcbiAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgIHRoaXMuX3VucGFja0JpbmFyeUFzeW5jKG5ldyBEYXRhUmVhZGVyKGRhdGFCdWZmZXIpKS50aGVuKFxyXG4gICAgICAgICAgICAgICAgICAgIChsb2FkZXJEYXRhKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpbGVSZXF1ZXN0Lm9uQ29tcGxldGVPYnNlcnZhYmxlLm5vdGlmeU9ic2VydmVycyhmaWxlUmVxdWVzdCk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uU3VjY2Vzcyhsb2FkZXJEYXRhKTtcclxuICAgICAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgICAgIG9uRXJyb3IgPyAoZXJyb3IpID0+IG9uRXJyb3IodW5kZWZpbmVkLCBlcnJvcikgOiB1bmRlZmluZWRcclxuICAgICAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIGZpbGVSZXF1ZXN0O1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbG9hZEZpbGUoXHJcbiAgICAgICAgICAgICAgICBzY2VuZSxcclxuICAgICAgICAgICAgICAgIGZpbGVPclVybCBhcyBGaWxlIHwgc3RyaW5nLFxyXG4gICAgICAgICAgICAgICAgKGRhdGEpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl92YWxpZGF0ZShzY2VuZSwgbmV3IFVpbnQ4QXJyYXkoZGF0YSBhcyBBcnJheUJ1ZmZlciksIHJvb3RVcmwsIGZpbGVOYW1lKTtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLl91bnBhY2tCaW5hcnlBc3luYyhcclxuICAgICAgICAgICAgICAgICAgICAgICAgbmV3IERhdGFSZWFkZXIoe1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVhZEFzeW5jOiAoYnl0ZU9mZnNldCwgYnl0ZUxlbmd0aCkgPT4gcmVhZEFzeW5jKGRhdGEgYXMgQXJyYXlCdWZmZXIsIGJ5dGVPZmZzZXQsIGJ5dGVMZW5ndGgpLFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnl0ZUxlbmd0aDogKGRhdGEgYXMgQXJyYXlCdWZmZXIpLmJ5dGVMZW5ndGgsXHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICAgICAgKS50aGVuKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAobG9hZGVyRGF0YSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgb25TdWNjZXNzKGxvYWRlckRhdGEpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICBvbkVycm9yID8gKGVycm9yKSA9PiBvbkVycm9yKHVuZGVmaW5lZCwgZXJyb3IpIDogdW5kZWZpbmVkXHJcbiAgICAgICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgICAgICB0cnVlLFxyXG4gICAgICAgICAgICAgICAgb25FcnJvclxyXG4gICAgICAgICAgICApO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIHRoaXMuX2xvYWRGaWxlKFxyXG4gICAgICAgICAgICBzY2VuZSxcclxuICAgICAgICAgICAgZmlsZU9yVXJsIGFzIEZpbGUgfCBzdHJpbmcsXHJcbiAgICAgICAgICAgIChkYXRhKSA9PiB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl92YWxpZGF0ZShzY2VuZSwgbmV3IFVpbnQ4QXJyYXkoZGF0YSBhcyBBcnJheUJ1ZmZlciksIHJvb3RVcmwsIGZpbGVOYW1lKTtcclxuICAgICAgICAgICAgICAgIG9uU3VjY2Vzcyh7IGpzb246IHRoaXMuX3BhcnNlSnNvbihkYXRhIGFzIHN0cmluZykgfSk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIHVzZUFycmF5QnVmZmVyLFxyXG4gICAgICAgICAgICBvbkVycm9yXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBfbG9hZEJpbmFyeShcclxuICAgICAgICBzY2VuZTogU2NlbmUsXHJcbiAgICAgICAgZGF0YTogQXJyYXlCdWZmZXJWaWV3LFxyXG4gICAgICAgIHJvb3RVcmw6IHN0cmluZyxcclxuICAgICAgICBvblN1Y2Nlc3M6IChkYXRhOiBhbnksIHJlc3BvbnNlVVJMPzogc3RyaW5nKSA9PiB2b2lkLFxyXG4gICAgICAgIG9uRXJyb3I/OiAocmVxdWVzdD86IFdlYlJlcXVlc3QsIGV4Y2VwdGlvbj86IExvYWRGaWxlRXJyb3IpID0+IHZvaWQsXHJcbiAgICAgICAgZmlsZU5hbWU/OiBzdHJpbmdcclxuICAgICk6IHZvaWQge1xyXG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlKHNjZW5lLCBkYXRhLCByb290VXJsLCBmaWxlTmFtZSk7XHJcbiAgICAgICAgdGhpcy5fdW5wYWNrQmluYXJ5QXN5bmMoXHJcbiAgICAgICAgICAgIG5ldyBEYXRhUmVhZGVyKHtcclxuICAgICAgICAgICAgICAgIHJlYWRBc3luYzogKGJ5dGVPZmZzZXQsIGJ5dGVMZW5ndGgpID0+IHJlYWRWaWV3QXN5bmMoZGF0YSwgYnl0ZU9mZnNldCwgYnl0ZUxlbmd0aCksXHJcbiAgICAgICAgICAgICAgICBieXRlTGVuZ3RoOiBkYXRhLmJ5dGVMZW5ndGgsXHJcbiAgICAgICAgICAgIH0pXHJcbiAgICAgICAgKS50aGVuKFxyXG4gICAgICAgICAgICAobG9hZGVyRGF0YSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgb25TdWNjZXNzKGxvYWRlckRhdGEpO1xyXG4gICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICBvbkVycm9yID8gKGVycm9yKSA9PiBvbkVycm9yKHVuZGVmaW5lZCwgZXJyb3IpIDogdW5kZWZpbmVkXHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgaW1wb3J0TWVzaEFzeW5jKFxyXG4gICAgICAgIG1lc2hlc05hbWVzOiBhbnksXHJcbiAgICAgICAgc2NlbmU6IFNjZW5lLFxyXG4gICAgICAgIGRhdGE6IGFueSxcclxuICAgICAgICByb290VXJsOiBzdHJpbmcsXHJcbiAgICAgICAgb25Qcm9ncmVzcz86IChldmVudDogSVNjZW5lTG9hZGVyUHJvZ3Jlc3NFdmVudCkgPT4gdm9pZCxcclxuICAgICAgICBmaWxlTmFtZT86IHN0cmluZ1xyXG4gICAgKTogUHJvbWlzZTxJU2NlbmVMb2FkZXJBc3luY1Jlc3VsdD4ge1xyXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5vblBhcnNlZE9ic2VydmFibGUubm90aWZ5T2JzZXJ2ZXJzKGRhdGEpO1xyXG4gICAgICAgICAgICB0aGlzLm9uUGFyc2VkT2JzZXJ2YWJsZS5jbGVhcigpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5fbG9nKGBMb2FkaW5nICR7ZmlsZU5hbWUgfHwgXCJcIn1gKTtcclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyID0gdGhpcy5fZ2V0TG9hZGVyKGRhdGEpO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbG9hZGVyLmltcG9ydE1lc2hBc3luYyhtZXNoZXNOYW1lcywgc2NlbmUsIG51bGwsIGRhdGEsIHJvb3RVcmwsIG9uUHJvZ3Jlc3MsIGZpbGVOYW1lKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgbG9hZEFzeW5jKHNjZW5lOiBTY2VuZSwgZGF0YTogYW55LCByb290VXJsOiBzdHJpbmcsIG9uUHJvZ3Jlc3M/OiAoZXZlbnQ6IElTY2VuZUxvYWRlclByb2dyZXNzRXZlbnQpID0+IHZvaWQsIGZpbGVOYW1lPzogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLm9uUGFyc2VkT2JzZXJ2YWJsZS5ub3RpZnlPYnNlcnZlcnMoZGF0YSk7XHJcbiAgICAgICAgICAgIHRoaXMub25QYXJzZWRPYnNlcnZhYmxlLmNsZWFyKCk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLl9sb2coYExvYWRpbmcgJHtmaWxlTmFtZSB8fCBcIlwifWApO1xyXG4gICAgICAgICAgICB0aGlzLl9sb2FkZXIgPSB0aGlzLl9nZXRMb2FkZXIoZGF0YSk7XHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9sb2FkZXIubG9hZEFzeW5jKHNjZW5lLCBkYXRhLCByb290VXJsLCBvblByb2dyZXNzLCBmaWxlTmFtZSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIGxvYWRBc3NldENvbnRhaW5lckFzeW5jKHNjZW5lOiBTY2VuZSwgZGF0YTogYW55LCByb290VXJsOiBzdHJpbmcsIG9uUHJvZ3Jlc3M/OiAoZXZlbnQ6IElTY2VuZUxvYWRlclByb2dyZXNzRXZlbnQpID0+IHZvaWQsIGZpbGVOYW1lPzogc3RyaW5nKTogUHJvbWlzZTxBc3NldENvbnRhaW5lcj4ge1xyXG4gICAgICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoKS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgdGhpcy5vblBhcnNlZE9ic2VydmFibGUubm90aWZ5T2JzZXJ2ZXJzKGRhdGEpO1xyXG4gICAgICAgICAgICB0aGlzLm9uUGFyc2VkT2JzZXJ2YWJsZS5jbGVhcigpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5fbG9nKGBMb2FkaW5nICR7ZmlsZU5hbWUgfHwgXCJcIn1gKTtcclxuICAgICAgICAgICAgdGhpcy5fbG9hZGVyID0gdGhpcy5fZ2V0TG9hZGVyKGRhdGEpO1xyXG5cclxuICAgICAgICAgICAgLy8gUHJlcGFyZSB0aGUgYXNzZXQgY29udGFpbmVyLlxyXG4gICAgICAgICAgICBjb25zdCBjb250YWluZXIgPSBuZXcgQXNzZXRDb250YWluZXIoc2NlbmUpO1xyXG5cclxuICAgICAgICAgICAgLy8gR2V0IG1hdGVyaWFscy90ZXh0dXJlcyB3aGVuIGxvYWRpbmcgdG8gYWRkIHRvIGNvbnRhaW5lclxyXG4gICAgICAgICAgICBjb25zdCBtYXRlcmlhbHM6IEFycmF5PE1hdGVyaWFsPiA9IFtdO1xyXG4gICAgICAgICAgICB0aGlzLm9uTWF0ZXJpYWxMb2FkZWRPYnNlcnZhYmxlLmFkZCgobWF0ZXJpYWwpID0+IHtcclxuICAgICAgICAgICAgICAgIG1hdGVyaWFscy5wdXNoKG1hdGVyaWFsKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIGNvbnN0IHRleHR1cmVzOiBBcnJheTxCYXNlVGV4dHVyZT4gPSBbXTtcclxuICAgICAgICAgICAgdGhpcy5vblRleHR1cmVMb2FkZWRPYnNlcnZhYmxlLmFkZCgodGV4dHVyZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgdGV4dHVyZXMucHVzaCh0ZXh0dXJlKTtcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgICAgIGNvbnN0IGNhbWVyYXM6IEFycmF5PENhbWVyYT4gPSBbXTtcclxuICAgICAgICAgICAgdGhpcy5vbkNhbWVyYUxvYWRlZE9ic2VydmFibGUuYWRkKChjYW1lcmEpID0+IHtcclxuICAgICAgICAgICAgICAgIGNhbWVyYXMucHVzaChjYW1lcmEpO1xyXG4gICAgICAgICAgICB9KTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IG1vcnBoVGFyZ2V0TWFuYWdlcnM6IEFycmF5PE1vcnBoVGFyZ2V0TWFuYWdlcj4gPSBbXTtcclxuICAgICAgICAgICAgdGhpcy5vbk1lc2hMb2FkZWRPYnNlcnZhYmxlLmFkZCgobWVzaCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKG1lc2gubW9ycGhUYXJnZXRNYW5hZ2VyKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgbW9ycGhUYXJnZXRNYW5hZ2Vycy5wdXNoKG1lc2gubW9ycGhUYXJnZXRNYW5hZ2VyKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfSk7XHJcblxyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fbG9hZGVyLmltcG9ydE1lc2hBc3luYyhudWxsLCBzY2VuZSwgY29udGFpbmVyLCBkYXRhLCByb290VXJsLCBvblByb2dyZXNzLCBmaWxlTmFtZSkudGhlbigocmVzdWx0KSA9PiB7XHJcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShjb250YWluZXIuZ2VvbWV0cmllcywgcmVzdWx0Lmdlb21ldHJpZXMpO1xyXG4gICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkoY29udGFpbmVyLm1lc2hlcywgcmVzdWx0Lm1lc2hlcyk7XHJcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShjb250YWluZXIucGFydGljbGVTeXN0ZW1zLCByZXN1bHQucGFydGljbGVTeXN0ZW1zKTtcclxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KGNvbnRhaW5lci5za2VsZXRvbnMsIHJlc3VsdC5za2VsZXRvbnMpO1xyXG4gICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkoY29udGFpbmVyLmFuaW1hdGlvbkdyb3VwcywgcmVzdWx0LmFuaW1hdGlvbkdyb3Vwcyk7XHJcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShjb250YWluZXIubWF0ZXJpYWxzLCBtYXRlcmlhbHMpO1xyXG4gICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnB1c2guYXBwbHkoY29udGFpbmVyLnRleHR1cmVzLCB0ZXh0dXJlcyk7XHJcbiAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUucHVzaC5hcHBseShjb250YWluZXIubGlnaHRzLCByZXN1bHQubGlnaHRzKTtcclxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KGNvbnRhaW5lci50cmFuc2Zvcm1Ob2RlcywgcmVzdWx0LnRyYW5zZm9ybU5vZGVzKTtcclxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KGNvbnRhaW5lci5jYW1lcmFzLCBjYW1lcmFzKTtcclxuICAgICAgICAgICAgICAgIEFycmF5LnByb3RvdHlwZS5wdXNoLmFwcGx5KGNvbnRhaW5lci5tb3JwaFRhcmdldE1hbmFnZXJzLCBtb3JwaFRhcmdldE1hbmFnZXJzKTtcclxuICAgICAgICAgICAgICAgIHJldHVybiBjb250YWluZXI7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBjYW5EaXJlY3RMb2FkKGRhdGE6IHN0cmluZyk6IGJvb2xlYW4ge1xyXG4gICAgICAgIHJldHVybiAoXHJcbiAgICAgICAgICAgIChkYXRhLmluZGV4T2YoXCJhc3NldFwiKSAhPT0gLTEgJiYgZGF0YS5pbmRleE9mKFwidmVyc2lvblwiKSAhPT0gLTEpIHx8XHJcbiAgICAgICAgICAgIGRhdGEuc3RhcnRzV2l0aChcImRhdGE6YmFzZTY0LFwiICsgR0xURkZpbGVMb2FkZXIuX01hZ2ljQmFzZTY0RW5jb2RlZCkgfHwgLy8gdGhpcyBpcyB0ZWNobmljYWxseSBpbmNvcnJlY3QsIGJ1dCB3aWxsIGNvbnRpbnVlIHRvIHN1cHBvcnQgZm9yIGJhY2tjb21wYXQuXHJcbiAgICAgICAgICAgIGRhdGEuc3RhcnRzV2l0aChcImRhdGE6O2Jhc2U2NCxcIiArIEdMVEZGaWxlTG9hZGVyLl9NYWdpY0Jhc2U2NEVuY29kZWQpIHx8XHJcbiAgICAgICAgICAgIGRhdGEuc3RhcnRzV2l0aChcImRhdGE6YXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtO2Jhc2U2NCxcIiArIEdMVEZGaWxlTG9hZGVyLl9NYWdpY0Jhc2U2NEVuY29kZWQpIHx8XHJcbiAgICAgICAgICAgIGRhdGEuc3RhcnRzV2l0aChcImRhdGE6bW9kZWwvZ2x0Zi1iaW5hcnk7YmFzZTY0LFwiICsgR0xURkZpbGVMb2FkZXIuX01hZ2ljQmFzZTY0RW5jb2RlZClcclxuICAgICAgICApO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogQGludGVybmFsXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBkaXJlY3RMb2FkKHNjZW5lOiBTY2VuZSwgZGF0YTogc3RyaW5nKTogUHJvbWlzZTxhbnk+IHtcclxuICAgICAgICBpZiAoXHJcbiAgICAgICAgICAgIGRhdGEuc3RhcnRzV2l0aChcImJhc2U2NCxcIiArIEdMVEZGaWxlTG9hZGVyLl9NYWdpY0Jhc2U2NEVuY29kZWQpIHx8IC8vIHRoaXMgaXMgdGVjaG5pY2FsbHkgaW5jb3JyZWN0LCBidXQgd2lsbCBjb250aW51ZSB0byBzdXBwb3J0IGZvciBiYWNrY29tcGF0LlxyXG4gICAgICAgICAgICBkYXRhLnN0YXJ0c1dpdGgoXCI7YmFzZTY0LFwiICsgR0xURkZpbGVMb2FkZXIuX01hZ2ljQmFzZTY0RW5jb2RlZCkgfHxcclxuICAgICAgICAgICAgZGF0YS5zdGFydHNXaXRoKFwiYXBwbGljYXRpb24vb2N0ZXQtc3RyZWFtO2Jhc2U2NCxcIiArIEdMVEZGaWxlTG9hZGVyLl9NYWdpY0Jhc2U2NEVuY29kZWQpIHx8XHJcbiAgICAgICAgICAgIGRhdGEuc3RhcnRzV2l0aChcIm1vZGVsL2dsdGYtYmluYXJ5O2Jhc2U2NCxcIiArIEdMVEZGaWxlTG9hZGVyLl9NYWdpY0Jhc2U2NEVuY29kZWQpXHJcbiAgICAgICAgKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGFycmF5QnVmZmVyID0gRGVjb2RlQmFzZTY0VXJsVG9CaW5hcnkoZGF0YSk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLl92YWxpZGF0ZShzY2VuZSwgbmV3IFVpbnQ4QXJyYXkoYXJyYXlCdWZmZXIpKTtcclxuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3VucGFja0JpbmFyeUFzeW5jKFxyXG4gICAgICAgICAgICAgICAgbmV3IERhdGFSZWFkZXIoe1xyXG4gICAgICAgICAgICAgICAgICAgIHJlYWRBc3luYzogKGJ5dGVPZmZzZXQsIGJ5dGVMZW5ndGgpID0+IHJlYWRBc3luYyhhcnJheUJ1ZmZlciwgYnl0ZU9mZnNldCwgYnl0ZUxlbmd0aCksXHJcbiAgICAgICAgICAgICAgICAgICAgYnl0ZUxlbmd0aDogYXJyYXlCdWZmZXIuYnl0ZUxlbmd0aCxcclxuICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICk7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLl92YWxpZGF0ZShzY2VuZSwgZGF0YSk7XHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh7IGpzb246IHRoaXMuX3BhcnNlSnNvbihkYXRhKSB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFRoZSBjYWxsYmFjayB0aGF0IGFsbG93cyBjdXN0b20gaGFuZGxpbmcgb2YgdGhlIHJvb3QgdXJsIGJhc2VkIG9uIHRoZSByZXNwb25zZSB1cmwuXHJcbiAgICAgKiBAcGFyYW0gcm9vdFVybCB0aGUgb3JpZ2luYWwgcm9vdCB1cmxcclxuICAgICAqIEBwYXJhbSByZXNwb25zZVVSTCB0aGUgcmVzcG9uc2UgdXJsIGlmIGF2YWlsYWJsZVxyXG4gICAgICogQHJldHVybnMgdGhlIG5ldyByb290IHVybFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgcmV3cml0ZVJvb3RVUkw/KHJvb3RVcmw6IHN0cmluZywgcmVzcG9uc2VVUkw/OiBzdHJpbmcpOiBzdHJpbmc7XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIGNyZWF0ZVBsdWdpbigpOiBJU2NlbmVMb2FkZXJQbHVnaW4gfCBJU2NlbmVMb2FkZXJQbHVnaW5Bc3luYyB7XHJcbiAgICAgICAgcmV0dXJuIG5ldyBHTFRGRmlsZUxvYWRlcigpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVGhlIGxvYWRlciBzdGF0ZSBvciBudWxsIGlmIHRoZSBsb2FkZXIgaXMgbm90IGFjdGl2ZS5cclxuICAgICAqL1xyXG4gICAgcHVibGljIGdldCBsb2FkZXJTdGF0ZSgpOiBOdWxsYWJsZTxHTFRGTG9hZGVyU3RhdGU+IHtcclxuICAgICAgICByZXR1cm4gdGhpcy5fc3RhdGU7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBPYnNlcnZhYmxlIHJhaXNlZCB3aGVuIHRoZSBsb2FkZXIgc3RhdGUgY2hhbmdlcy5cclxuICAgICAqL1xyXG4gICAgcHVibGljIG9uTG9hZGVyU3RhdGVDaGFuZ2VkT2JzZXJ2YWJsZSA9IG5ldyBPYnNlcnZhYmxlPE51bGxhYmxlPEdMVEZMb2FkZXJTdGF0ZT4+KCk7XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBSZXR1cm5zIGEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdoZW4gdGhlIGFzc2V0IGlzIGNvbXBsZXRlbHkgbG9hZGVkLlxyXG4gICAgICogQHJldHVybnMgYSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgYXNzZXQgaXMgY29tcGxldGVseSBsb2FkZWQuXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyB3aGVuQ29tcGxldGVBc3luYygpOiBQcm9taXNlPHZvaWQ+IHtcclxuICAgICAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLm9uQ29tcGxldGVPYnNlcnZhYmxlLmFkZE9uY2UoKCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICAgICAgdGhpcy5vbkVycm9yT2JzZXJ2YWJsZS5hZGRPbmNlKChyZWFzb24pID0+IHtcclxuICAgICAgICAgICAgICAgIHJlamVjdChyZWFzb24pO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgX3NldFN0YXRlKHN0YXRlOiBHTFRGTG9hZGVyU3RhdGUpOiB2b2lkIHtcclxuICAgICAgICBpZiAodGhpcy5fc3RhdGUgPT09IHN0YXRlKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuX3N0YXRlID0gc3RhdGU7XHJcbiAgICAgICAgdGhpcy5vbkxvYWRlclN0YXRlQ2hhbmdlZE9ic2VydmFibGUubm90aWZ5T2JzZXJ2ZXJzKHRoaXMuX3N0YXRlKTtcclxuICAgICAgICB0aGlzLl9sb2coR0xURkxvYWRlclN0YXRlW3RoaXMuX3N0YXRlXSk7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBAaW50ZXJuYWxcclxuICAgICAqL1xyXG4gICAgcHVibGljIF9sb2FkRmlsZShcclxuICAgICAgICBzY2VuZTogU2NlbmUsXHJcbiAgICAgICAgZmlsZU9yVXJsOiBGaWxlIHwgc3RyaW5nLFxyXG4gICAgICAgIG9uU3VjY2VzczogKGRhdGE6IHN0cmluZyB8IEFycmF5QnVmZmVyKSA9PiB2b2lkLFxyXG4gICAgICAgIHVzZUFycmF5QnVmZmVyPzogYm9vbGVhbixcclxuICAgICAgICBvbkVycm9yPzogKHJlcXVlc3Q/OiBXZWJSZXF1ZXN0KSA9PiB2b2lkLFxyXG4gICAgICAgIG9uT3BlbmVkPzogKHJlcXVlc3Q6IFdlYlJlcXVlc3QpID0+IHZvaWRcclxuICAgICk6IElGaWxlUmVxdWVzdCB7XHJcbiAgICAgICAgY29uc3QgcmVxdWVzdCA9IHNjZW5lLl9sb2FkRmlsZShcclxuICAgICAgICAgICAgZmlsZU9yVXJsLFxyXG4gICAgICAgICAgICBvblN1Y2Nlc3MsXHJcbiAgICAgICAgICAgIChldmVudCkgPT4ge1xyXG4gICAgICAgICAgICAgICAgdGhpcy5fb25Qcm9ncmVzcyhldmVudCwgcmVxdWVzdCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIHRydWUsXHJcbiAgICAgICAgICAgIHVzZUFycmF5QnVmZmVyLFxyXG4gICAgICAgICAgICBvbkVycm9yLFxyXG4gICAgICAgICAgICBvbk9wZW5lZFxyXG4gICAgICAgICkgYXMgSUZpbGVSZXF1ZXN0SW5mbztcclxuICAgICAgICByZXF1ZXN0Lm9uQ29tcGxldGVPYnNlcnZhYmxlLmFkZCgocmVxdWVzdCkgPT4ge1xyXG4gICAgICAgICAgICB0aGlzLl9yZXF1ZXN0cy5zcGxpY2UodGhpcy5fcmVxdWVzdHMuaW5kZXhPZihyZXF1ZXN0KSwgMSk7XHJcbiAgICAgICAgfSk7XHJcbiAgICAgICAgdGhpcy5fcmVxdWVzdHMucHVzaChyZXF1ZXN0KTtcclxuICAgICAgICByZXR1cm4gcmVxdWVzdDtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9vblByb2dyZXNzKGV2ZW50OiBQcm9ncmVzc0V2ZW50LCByZXF1ZXN0OiBJRmlsZVJlcXVlc3RJbmZvKTogdm9pZCB7XHJcbiAgICAgICAgaWYgKCF0aGlzLl9wcm9ncmVzc0NhbGxiYWNrKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJlcXVlc3QuX2xlbmd0aENvbXB1dGFibGUgPSBldmVudC5sZW5ndGhDb21wdXRhYmxlO1xyXG4gICAgICAgIHJlcXVlc3QuX2xvYWRlZCA9IGV2ZW50LmxvYWRlZDtcclxuICAgICAgICByZXF1ZXN0Ll90b3RhbCA9IGV2ZW50LnRvdGFsO1xyXG5cclxuICAgICAgICBsZXQgbGVuZ3RoQ29tcHV0YWJsZSA9IHRydWU7XHJcbiAgICAgICAgbGV0IGxvYWRlZCA9IDA7XHJcbiAgICAgICAgbGV0IHRvdGFsID0gMDtcclxuICAgICAgICBmb3IgKGNvbnN0IHJlcXVlc3Qgb2YgdGhpcy5fcmVxdWVzdHMpIHtcclxuICAgICAgICAgICAgaWYgKHJlcXVlc3QuX2xlbmd0aENvbXB1dGFibGUgPT09IHVuZGVmaW5lZCB8fCByZXF1ZXN0Ll9sb2FkZWQgPT09IHVuZGVmaW5lZCB8fCByZXF1ZXN0Ll90b3RhbCA9PT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGxlbmd0aENvbXB1dGFibGUgPSBsZW5ndGhDb21wdXRhYmxlICYmIHJlcXVlc3QuX2xlbmd0aENvbXB1dGFibGU7XHJcbiAgICAgICAgICAgIGxvYWRlZCArPSByZXF1ZXN0Ll9sb2FkZWQ7XHJcbiAgICAgICAgICAgIHRvdGFsICs9IHJlcXVlc3QuX3RvdGFsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgdGhpcy5fcHJvZ3Jlc3NDYWxsYmFjayh7XHJcbiAgICAgICAgICAgIGxlbmd0aENvbXB1dGFibGU6IGxlbmd0aENvbXB1dGFibGUsXHJcbiAgICAgICAgICAgIGxvYWRlZDogbG9hZGVkLFxyXG4gICAgICAgICAgICB0b3RhbDogbGVuZ3RoQ29tcHV0YWJsZSA/IHRvdGFsIDogMCxcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF92YWxpZGF0ZShzY2VuZTogU2NlbmUsIGRhdGE6IHN0cmluZyB8IEFycmF5QnVmZmVyVmlldywgcm9vdFVybCA9IFwiXCIsIGZpbGVOYW1lID0gXCJcIik6IHZvaWQge1xyXG4gICAgICAgIGlmICghdGhpcy52YWxpZGF0ZSkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICB0aGlzLl9zdGFydFBlcmZvcm1hbmNlQ291bnRlcihcIlZhbGlkYXRlIEpTT05cIik7XHJcbiAgICAgICAgR0xURlZhbGlkYXRpb24uVmFsaWRhdGVBc3luYyhkYXRhLCByb290VXJsLCBmaWxlTmFtZSwgKHVyaSkgPT4ge1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5wcmVwcm9jZXNzVXJsQXN5bmMocm9vdFVybCArIHVyaSkudGhlbigodXJsKSA9PiBzY2VuZS5fbG9hZEZpbGVBc3luYyh1cmwsIHVuZGVmaW5lZCwgdHJ1ZSwgdHJ1ZSkgYXMgUHJvbWlzZTxBcnJheUJ1ZmZlcj4pO1xyXG4gICAgICAgIH0pLnRoZW4oXHJcbiAgICAgICAgICAgIChyZXN1bHQpID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2VuZFBlcmZvcm1hbmNlQ291bnRlcihcIlZhbGlkYXRlIEpTT05cIik7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm9uVmFsaWRhdGVkT2JzZXJ2YWJsZS5ub3RpZnlPYnNlcnZlcnMocmVzdWx0KTtcclxuICAgICAgICAgICAgICAgIHRoaXMub25WYWxpZGF0ZWRPYnNlcnZhYmxlLmNsZWFyKCk7XHJcbiAgICAgICAgICAgIH0sXHJcbiAgICAgICAgICAgIChyZWFzb24pID0+IHtcclxuICAgICAgICAgICAgICAgIHRoaXMuX2VuZFBlcmZvcm1hbmNlQ291bnRlcihcIlZhbGlkYXRlIEpTT05cIik7XHJcbiAgICAgICAgICAgICAgICBUb29scy5XYXJuKGBGYWlsZWQgdG8gdmFsaWRhdGU6ICR7cmVhc29uLm1lc3NhZ2V9YCk7XHJcbiAgICAgICAgICAgICAgICB0aGlzLm9uVmFsaWRhdGVkT2JzZXJ2YWJsZS5jbGVhcigpO1xyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9nZXRMb2FkZXIobG9hZGVyRGF0YTogSUdMVEZMb2FkZXJEYXRhKTogSUdMVEZMb2FkZXIge1xyXG4gICAgICAgIGNvbnN0IGFzc2V0ID0gKDxhbnk+bG9hZGVyRGF0YS5qc29uKS5hc3NldCB8fCB7fTtcclxuXHJcbiAgICAgICAgdGhpcy5fbG9nKGBBc3NldCB2ZXJzaW9uOiAke2Fzc2V0LnZlcnNpb259YCk7XHJcbiAgICAgICAgYXNzZXQubWluVmVyc2lvbiAmJiB0aGlzLl9sb2coYEFzc2V0IG1pbmltdW0gdmVyc2lvbjogJHthc3NldC5taW5WZXJzaW9ufWApO1xyXG4gICAgICAgIGFzc2V0LmdlbmVyYXRvciAmJiB0aGlzLl9sb2coYEFzc2V0IGdlbmVyYXRvcjogJHthc3NldC5nZW5lcmF0b3J9YCk7XHJcblxyXG4gICAgICAgIGNvbnN0IHZlcnNpb24gPSBHTFRGRmlsZUxvYWRlci5fcGFyc2VWZXJzaW9uKGFzc2V0LnZlcnNpb24pO1xyXG4gICAgICAgIGlmICghdmVyc2lvbikge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJJbnZhbGlkIHZlcnNpb246IFwiICsgYXNzZXQudmVyc2lvbik7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBpZiAoYXNzZXQubWluVmVyc2lvbiAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IG1pblZlcnNpb24gPSBHTFRGRmlsZUxvYWRlci5fcGFyc2VWZXJzaW9uKGFzc2V0Lm1pblZlcnNpb24pO1xyXG4gICAgICAgICAgICBpZiAoIW1pblZlcnNpb24pIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcihcIkludmFsaWQgbWluaW11bSB2ZXJzaW9uOiBcIiArIGFzc2V0Lm1pblZlcnNpb24pO1xyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICBpZiAoR0xURkZpbGVMb2FkZXIuX2NvbXBhcmVWZXJzaW9uKG1pblZlcnNpb24sIHsgbWFqb3I6IDIsIG1pbm9yOiAwIH0pID4gMCkge1xyXG4gICAgICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiSW5jb21wYXRpYmxlIG1pbmltdW0gdmVyc2lvbjogXCIgKyBhc3NldC5taW5WZXJzaW9uKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgY3JlYXRlTG9hZGVyczogeyBba2V5OiBudW1iZXJdOiAocGFyZW50OiBHTFRGRmlsZUxvYWRlcikgPT4gSUdMVEZMb2FkZXIgfSA9IHtcclxuICAgICAgICAgICAgMTogR0xURkZpbGVMb2FkZXIuX0NyZWF0ZUdMVEYxTG9hZGVyLFxyXG4gICAgICAgICAgICAyOiBHTFRGRmlsZUxvYWRlci5fQ3JlYXRlR0xURjJMb2FkZXIsXHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgY29uc3QgY3JlYXRlTG9hZGVyID0gY3JlYXRlTG9hZGVyc1t2ZXJzaW9uLm1ham9yXTtcclxuICAgICAgICBpZiAoIWNyZWF0ZUxvYWRlcikge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbnN1cHBvcnRlZCB2ZXJzaW9uOiBcIiArIGFzc2V0LnZlcnNpb24pO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGNyZWF0ZUxvYWRlcih0aGlzKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9wYXJzZUpzb24oanNvbjogc3RyaW5nKTogT2JqZWN0IHtcclxuICAgICAgICB0aGlzLl9zdGFydFBlcmZvcm1hbmNlQ291bnRlcihcIlBhcnNlIEpTT05cIik7XHJcbiAgICAgICAgdGhpcy5fbG9nKGBKU09OIGxlbmd0aDogJHtqc29uLmxlbmd0aH1gKTtcclxuICAgICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGpzb24pO1xyXG4gICAgICAgIHRoaXMuX2VuZFBlcmZvcm1hbmNlQ291bnRlcihcIlBhcnNlIEpTT05cIik7XHJcbiAgICAgICAgcmV0dXJuIHBhcnNlZDtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF91bnBhY2tCaW5hcnlBc3luYyhkYXRhUmVhZGVyOiBEYXRhUmVhZGVyKTogUHJvbWlzZTxJR0xURkxvYWRlckRhdGE+IHtcclxuICAgICAgICB0aGlzLl9zdGFydFBlcmZvcm1hbmNlQ291bnRlcihcIlVucGFjayBCaW5hcnlcIik7XHJcblxyXG4gICAgICAgIC8vIFJlYWQgbWFnaWMgKyB2ZXJzaW9uICsgbGVuZ3RoICsganNvbiBsZW5ndGggKyBqc29uIGZvcm1hdFxyXG4gICAgICAgIHJldHVybiBkYXRhUmVhZGVyLmxvYWRBc3luYygyMCkudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IEJpbmFyeSA9IHtcclxuICAgICAgICAgICAgICAgIE1hZ2ljOiAweDQ2NTQ2YzY3LFxyXG4gICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgY29uc3QgbWFnaWMgPSBkYXRhUmVhZGVyLnJlYWRVaW50MzIoKTtcclxuICAgICAgICAgICAgaWYgKG1hZ2ljICE9PSBCaW5hcnkuTWFnaWMpIHtcclxuICAgICAgICAgICAgICAgIHRocm93IG5ldyBSdW50aW1lRXJyb3IoXCJVbmV4cGVjdGVkIG1hZ2ljOiBcIiArIG1hZ2ljLCBFcnJvckNvZGVzLkdMVEZMb2FkZXJVbmV4cGVjdGVkTWFnaWNFcnJvcik7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHZlcnNpb24gPSBkYXRhUmVhZGVyLnJlYWRVaW50MzIoKTtcclxuXHJcbiAgICAgICAgICAgIGlmICh0aGlzLmxvZ2dpbmdFbmFibGVkKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9sb2coYEJpbmFyeSB2ZXJzaW9uOiAke3ZlcnNpb259YCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIGNvbnN0IGxlbmd0aCA9IGRhdGFSZWFkZXIucmVhZFVpbnQzMigpO1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMudXNlUmFuZ2VSZXF1ZXN0cyAmJiBsZW5ndGggIT09IGRhdGFSZWFkZXIuYnVmZmVyLmJ5dGVMZW5ndGgpIHtcclxuICAgICAgICAgICAgICAgIExvZ2dlci5XYXJuKGBMZW5ndGggaW4gaGVhZGVyIGRvZXMgbm90IG1hdGNoIGFjdHVhbCBkYXRhIGxlbmd0aDogJHtsZW5ndGh9ICE9ICR7ZGF0YVJlYWRlci5idWZmZXIuYnl0ZUxlbmd0aH1gKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgbGV0IHVucGFja2VkOiBQcm9taXNlPElHTFRGTG9hZGVyRGF0YT47XHJcbiAgICAgICAgICAgIHN3aXRjaCAodmVyc2lvbikge1xyXG4gICAgICAgICAgICAgICAgY2FzZSAxOiB7XHJcbiAgICAgICAgICAgICAgICAgICAgdW5wYWNrZWQgPSB0aGlzLl91bnBhY2tCaW5hcnlWMUFzeW5jKGRhdGFSZWFkZXIsIGxlbmd0aCk7XHJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICBjYXNlIDI6IHtcclxuICAgICAgICAgICAgICAgICAgICB1bnBhY2tlZCA9IHRoaXMuX3VucGFja0JpbmFyeVYyQXN5bmMoZGF0YVJlYWRlciwgbGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6IHtcclxuICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbnN1cHBvcnRlZCB2ZXJzaW9uOiBcIiArIHZlcnNpb24pO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICB0aGlzLl9lbmRQZXJmb3JtYW5jZUNvdW50ZXIoXCJVbnBhY2sgQmluYXJ5XCIpO1xyXG5cclxuICAgICAgICAgICAgcmV0dXJuIHVucGFja2VkO1xyXG4gICAgICAgIH0pO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX3VucGFja0JpbmFyeVYxQXN5bmMoZGF0YVJlYWRlcjogRGF0YVJlYWRlciwgbGVuZ3RoOiBudW1iZXIpOiBQcm9taXNlPElHTFRGTG9hZGVyRGF0YT4ge1xyXG4gICAgICAgIGNvbnN0IENvbnRlbnRGb3JtYXQgPSB7XHJcbiAgICAgICAgICAgIEpTT046IDAsXHJcbiAgICAgICAgfTtcclxuXHJcbiAgICAgICAgY29uc3QgY29udGVudExlbmd0aCA9IGRhdGFSZWFkZXIucmVhZFVpbnQzMigpO1xyXG4gICAgICAgIGNvbnN0IGNvbnRlbnRGb3JtYXQgPSBkYXRhUmVhZGVyLnJlYWRVaW50MzIoKTtcclxuXHJcbiAgICAgICAgaWYgKGNvbnRlbnRGb3JtYXQgIT09IENvbnRlbnRGb3JtYXQuSlNPTikge1xyXG4gICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoYFVuZXhwZWN0ZWQgY29udGVudCBmb3JtYXQ6ICR7Y29udGVudEZvcm1hdH1gKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGJvZHlMZW5ndGggPSBsZW5ndGggLSBkYXRhUmVhZGVyLmJ5dGVPZmZzZXQ7XHJcblxyXG4gICAgICAgIGNvbnN0IGRhdGE6IElHTFRGTG9hZGVyRGF0YSA9IHsganNvbjogdGhpcy5fcGFyc2VKc29uKGRhdGFSZWFkZXIucmVhZFN0cmluZyhjb250ZW50TGVuZ3RoKSksIGJpbjogbnVsbCB9O1xyXG4gICAgICAgIGlmIChib2R5TGVuZ3RoICE9PSAwKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHN0YXJ0Qnl0ZU9mZnNldCA9IGRhdGFSZWFkZXIuYnl0ZU9mZnNldDtcclxuICAgICAgICAgICAgZGF0YS5iaW4gPSB7XHJcbiAgICAgICAgICAgICAgICByZWFkQXN5bmM6IChieXRlT2Zmc2V0LCBieXRlTGVuZ3RoKSA9PiBkYXRhUmVhZGVyLmJ1ZmZlci5yZWFkQXN5bmMoc3RhcnRCeXRlT2Zmc2V0ICsgYnl0ZU9mZnNldCwgYnl0ZUxlbmd0aCksXHJcbiAgICAgICAgICAgICAgICBieXRlTGVuZ3RoOiBib2R5TGVuZ3RoLFxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShkYXRhKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF91bnBhY2tCaW5hcnlWMkFzeW5jKGRhdGFSZWFkZXI6IERhdGFSZWFkZXIsIGxlbmd0aDogbnVtYmVyKTogUHJvbWlzZTxJR0xURkxvYWRlckRhdGE+IHtcclxuICAgICAgICBjb25zdCBDaHVua0Zvcm1hdCA9IHtcclxuICAgICAgICAgICAgSlNPTjogMHg0ZTRmNTM0YSxcclxuICAgICAgICAgICAgQklOOiAweDAwNGU0OTQyLFxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIC8vIFJlYWQgdGhlIEpTT04gY2h1bmsgaGVhZGVyLlxyXG4gICAgICAgIGNvbnN0IGNodW5rTGVuZ3RoID0gZGF0YVJlYWRlci5yZWFkVWludDMyKCk7XHJcbiAgICAgICAgY29uc3QgY2h1bmtGb3JtYXQgPSBkYXRhUmVhZGVyLnJlYWRVaW50MzIoKTtcclxuICAgICAgICBpZiAoY2h1bmtGb3JtYXQgIT09IENodW5rRm9ybWF0LkpTT04pIHtcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKFwiRmlyc3QgY2h1bmsgZm9ybWF0IGlzIG5vdCBKU09OXCIpO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgLy8gQmFpbCBpZiB0aGVyZSBhcmUgbm8gb3RoZXIgY2h1bmtzLlxyXG4gICAgICAgIGlmIChkYXRhUmVhZGVyLmJ5dGVPZmZzZXQgKyBjaHVua0xlbmd0aCA9PT0gbGVuZ3RoKSB7XHJcbiAgICAgICAgICAgIHJldHVybiBkYXRhUmVhZGVyLmxvYWRBc3luYyhjaHVua0xlbmd0aCkudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4geyBqc29uOiB0aGlzLl9wYXJzZUpzb24oZGF0YVJlYWRlci5yZWFkU3RyaW5nKGNodW5rTGVuZ3RoKSksIGJpbjogbnVsbCB9O1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFJlYWQgdGhlIEpTT04gY2h1bmsgYW5kIHRoZSBsZW5ndGggYW5kIHR5cGUgb2YgdGhlIG5leHQgY2h1bmsuXHJcbiAgICAgICAgcmV0dXJuIGRhdGFSZWFkZXIubG9hZEFzeW5jKGNodW5rTGVuZ3RoICsgOCkudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgIGNvbnN0IGRhdGE6IElHTFRGTG9hZGVyRGF0YSA9IHsganNvbjogdGhpcy5fcGFyc2VKc29uKGRhdGFSZWFkZXIucmVhZFN0cmluZyhjaHVua0xlbmd0aCkpLCBiaW46IG51bGwgfTtcclxuXHJcbiAgICAgICAgICAgIGNvbnN0IHJlYWRBc3luYyA9ICgpOiBQcm9taXNlPElHTFRGTG9hZGVyRGF0YT4gPT4ge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgY2h1bmtMZW5ndGggPSBkYXRhUmVhZGVyLnJlYWRVaW50MzIoKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGNodW5rRm9ybWF0ID0gZGF0YVJlYWRlci5yZWFkVWludDMyKCk7XHJcblxyXG4gICAgICAgICAgICAgICAgc3dpdGNoIChjaHVua0Zvcm1hdCkge1xyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQ2h1bmtGb3JtYXQuSlNPTjoge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmV4cGVjdGVkIEpTT04gY2h1bmtcIik7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQ2h1bmtGb3JtYXQuQklOOiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHN0YXJ0Qnl0ZU9mZnNldCA9IGRhdGFSZWFkZXIuYnl0ZU9mZnNldDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YS5iaW4gPSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWFkQXN5bmM6IChieXRlT2Zmc2V0LCBieXRlTGVuZ3RoKSA9PiBkYXRhUmVhZGVyLmJ1ZmZlci5yZWFkQXN5bmMoc3RhcnRCeXRlT2Zmc2V0ICsgYnl0ZU9mZnNldCwgYnl0ZUxlbmd0aCksXHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBieXRlTGVuZ3RoOiBjaHVua0xlbmd0aCxcclxuICAgICAgICAgICAgICAgICAgICAgICAgfTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgZGF0YVJlYWRlci5za2lwQnl0ZXMoY2h1bmtMZW5ndGgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDoge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBpZ25vcmUgdW5yZWNvZ25pemVkIGNodW5rRm9ybWF0XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGRhdGFSZWFkZXIuc2tpcEJ5dGVzKGNodW5rTGVuZ3RoKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgIGlmIChkYXRhUmVhZGVyLmJ5dGVPZmZzZXQgIT09IGxlbmd0aCkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBkYXRhUmVhZGVyLmxvYWRBc3luYyg4KS50aGVuKHJlYWRBc3luYyk7XHJcbiAgICAgICAgICAgICAgICB9XHJcblxyXG4gICAgICAgICAgICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShkYXRhKTtcclxuICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgIHJldHVybiByZWFkQXN5bmMoKTtcclxuICAgICAgICB9KTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHN0YXRpYyBfcGFyc2VWZXJzaW9uKHZlcnNpb246IHN0cmluZyk6IE51bGxhYmxlPHsgbWFqb3I6IG51bWJlcjsgbWlub3I6IG51bWJlciB9PiB7XHJcbiAgICAgICAgaWYgKHZlcnNpb24gPT09IFwiMS4wXCIgfHwgdmVyc2lvbiA9PT0gXCIxLjAuMVwiKSB7XHJcbiAgICAgICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgICAgICBtYWpvcjogMSxcclxuICAgICAgICAgICAgICAgIG1pbm9yOiAwLFxyXG4gICAgICAgICAgICB9O1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgY29uc3QgbWF0Y2ggPSAodmVyc2lvbiArIFwiXCIpLm1hdGNoKC9eKFxcZCspXFwuKFxcZCspLyk7XHJcbiAgICAgICAgaWYgKCFtYXRjaCkge1xyXG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHJldHVybiB7XHJcbiAgICAgICAgICAgIG1ham9yOiBwYXJzZUludChtYXRjaFsxXSksXHJcbiAgICAgICAgICAgIG1pbm9yOiBwYXJzZUludChtYXRjaFsyXSksXHJcbiAgICAgICAgfTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHN0YXRpYyBfY29tcGFyZVZlcnNpb24oYTogeyBtYWpvcjogbnVtYmVyOyBtaW5vcjogbnVtYmVyIH0sIGI6IHsgbWFqb3I6IG51bWJlcjsgbWlub3I6IG51bWJlciB9KTogbnVtYmVyIHtcclxuICAgICAgICBpZiAoYS5tYWpvciA+IGIubWFqb3IpIHtcclxuICAgICAgICAgICAgcmV0dXJuIDE7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChhLm1ham9yIDwgYi5tYWpvcikge1xyXG4gICAgICAgICAgICByZXR1cm4gLTE7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIGlmIChhLm1pbm9yID4gYi5taW5vcikge1xyXG4gICAgICAgICAgICByZXR1cm4gMTtcclxuICAgICAgICB9XHJcbiAgICAgICAgaWYgKGEubWlub3IgPCBiLm1pbm9yKSB7XHJcbiAgICAgICAgICAgIHJldHVybiAtMTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuIDA7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzdGF0aWMgcmVhZG9ubHkgX2xvZ1NwYWNlcyA9IFwiICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcIjtcclxuICAgIHByaXZhdGUgX2xvZ0luZGVudExldmVsID0gMDtcclxuICAgIHByaXZhdGUgX2xvZ2dpbmdFbmFibGVkID0gZmFsc2U7XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIF9sb2cgPSB0aGlzLl9sb2dEaXNhYmxlZDtcclxuXHJcbiAgICAvKipcclxuICAgICAqIEBpbnRlcm5hbFxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgX2xvZ09wZW4obWVzc2FnZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5fbG9nKG1lc3NhZ2UpO1xyXG4gICAgICAgIHRoaXMuX2xvZ0luZGVudExldmVsKys7XHJcbiAgICB9XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIF9sb2dDbG9zZSgpOiB2b2lkIHtcclxuICAgICAgICAtLXRoaXMuX2xvZ0luZGVudExldmVsO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgX2xvZ0VuYWJsZWQobWVzc2FnZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3Qgc3BhY2VzID0gR0xURkZpbGVMb2FkZXIuX2xvZ1NwYWNlcy5zdWJzdHIoMCwgdGhpcy5fbG9nSW5kZW50TGV2ZWwgKiAyKTtcclxuICAgICAgICBMb2dnZXIuTG9nKGAke3NwYWNlc30ke21lc3NhZ2V9YCk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBfbG9nRGlzYWJsZWQobWVzc2FnZTogc3RyaW5nKTogdm9pZCB7fVxyXG5cclxuICAgIHByaXZhdGUgX2NhcHR1cmVQZXJmb3JtYW5jZUNvdW50ZXJzID0gZmFsc2U7XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIF9zdGFydFBlcmZvcm1hbmNlQ291bnRlciA9IHRoaXMuX3N0YXJ0UGVyZm9ybWFuY2VDb3VudGVyRGlzYWJsZWQ7XHJcblxyXG4gICAgLyoqIEBpbnRlcm5hbCAqL1xyXG4gICAgcHVibGljIF9lbmRQZXJmb3JtYW5jZUNvdW50ZXIgPSB0aGlzLl9lbmRQZXJmb3JtYW5jZUNvdW50ZXJEaXNhYmxlZDtcclxuXHJcbiAgICBwcml2YXRlIF9zdGFydFBlcmZvcm1hbmNlQ291bnRlckVuYWJsZWQoY291bnRlck5hbWU6IHN0cmluZyk6IHZvaWQge1xyXG4gICAgICAgIFRvb2xzLlN0YXJ0UGVyZm9ybWFuY2VDb3VudGVyKGNvdW50ZXJOYW1lKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9zdGFydFBlcmZvcm1hbmNlQ291bnRlckRpc2FibGVkKGNvdW50ZXJOYW1lOiBzdHJpbmcpOiB2b2lkIHt9XHJcblxyXG4gICAgcHJpdmF0ZSBfZW5kUGVyZm9ybWFuY2VDb3VudGVyRW5hYmxlZChjb3VudGVyTmFtZTogc3RyaW5nKTogdm9pZCB7XHJcbiAgICAgICAgVG9vbHMuRW5kUGVyZm9ybWFuY2VDb3VudGVyKGNvdW50ZXJOYW1lKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIF9lbmRQZXJmb3JtYW5jZUNvdW50ZXJEaXNhYmxlZChjb3VudGVyTmFtZTogc3RyaW5nKTogdm9pZCB7fVxyXG59XHJcblxyXG5pZiAoU2NlbmVMb2FkZXIpIHtcclxuICAgIFNjZW5lTG9hZGVyLlJlZ2lzdGVyUGx1Z2luKG5ldyBHTFRGRmlsZUxvYWRlcigpKTtcclxufVxyXG4iLCJpbXBvcnQgdHlwZSAqIGFzIEdMVEYyIGZyb20gXCJiYWJ5bG9uanMtZ2x0ZjJpbnRlcmZhY2VcIjtcclxuaW1wb3J0IHsgVG9vbHMgfSBmcm9tIFwiY29yZS9NaXNjL3Rvb2xzXCI7XHJcblxyXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQHR5cGVzY3JpcHQtZXNsaW50L25hbWluZy1jb252ZW50aW9uXHJcbmRlY2xhcmUgbGV0IEdMVEZWYWxpZGF0b3I6IEdMVEYyLklHTFRGVmFsaWRhdG9yO1xyXG5cclxuLy8gV29ya2VyR2xvYmFsU2NvcGVcclxuZGVjbGFyZSBmdW5jdGlvbiBpbXBvcnRTY3JpcHRzKC4uLnVybHM6IHN0cmluZ1tdKTogdm9pZDtcclxuZGVjbGFyZSBmdW5jdGlvbiBwb3N0TWVzc2FnZShtZXNzYWdlOiBhbnksIHRyYW5zZmVyPzogYW55W10pOiB2b2lkO1xyXG5cclxuZnVuY3Rpb24gdmFsaWRhdGVBc3luYyhcclxuICAgIGRhdGE6IHN0cmluZyB8IEFycmF5QnVmZmVyLFxyXG4gICAgcm9vdFVybDogc3RyaW5nLFxyXG4gICAgZmlsZU5hbWU6IHN0cmluZyxcclxuICAgIGdldEV4dGVybmFsUmVzb3VyY2U6ICh1cmk6IHN0cmluZykgPT4gUHJvbWlzZTxBcnJheUJ1ZmZlcj5cclxuKTogUHJvbWlzZTxHTFRGMi5JR0xURlZhbGlkYXRpb25SZXN1bHRzPiB7XHJcbiAgICBjb25zdCBvcHRpb25zOiBHTFRGMi5JR0xURlZhbGlkYXRpb25PcHRpb25zID0ge1xyXG4gICAgICAgIGV4dGVybmFsUmVzb3VyY2VGdW5jdGlvbjogKHVyaSkgPT4gZ2V0RXh0ZXJuYWxSZXNvdXJjZSh1cmkpLnRoZW4oKHZhbHVlKSA9PiBuZXcgVWludDhBcnJheSh2YWx1ZSkpLFxyXG4gICAgfTtcclxuXHJcbiAgICBpZiAoZmlsZU5hbWUpIHtcclxuICAgICAgICBvcHRpb25zLnVyaSA9IHJvb3RVcmwgPT09IFwiZmlsZTpcIiA/IGZpbGVOYW1lIDogcm9vdFVybCArIGZpbGVOYW1lO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiBkYXRhIGluc3RhbmNlb2YgQXJyYXlCdWZmZXIgPyBHTFRGVmFsaWRhdG9yLnZhbGlkYXRlQnl0ZXMobmV3IFVpbnQ4QXJyYXkoZGF0YSksIG9wdGlvbnMpIDogR0xURlZhbGlkYXRvci52YWxpZGF0ZVN0cmluZyhkYXRhLCBvcHRpb25zKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFRoZSB3b3JrZXIgZnVuY3Rpb24gdGhhdCBnZXRzIGNvbnZlcnRlZCB0byBhIGJsb2IgdXJsIHRvIHBhc3MgaW50byBhIHdvcmtlci5cclxuICovXHJcbmZ1bmN0aW9uIHdvcmtlckZ1bmMoKTogdm9pZCB7XHJcbiAgICBjb25zdCBwZW5kaW5nRXh0ZXJuYWxSZXNvdXJjZXM6IEFycmF5PHsgcmVzb2x2ZTogKGRhdGE6IGFueSkgPT4gdm9pZDsgcmVqZWN0OiAocmVhc29uOiBhbnkpID0+IHZvaWQgfT4gPSBbXTtcclxuXHJcbiAgICBvbm1lc3NhZ2UgPSAobWVzc2FnZSkgPT4ge1xyXG4gICAgICAgIGNvbnN0IGRhdGEgPSBtZXNzYWdlLmRhdGE7XHJcbiAgICAgICAgc3dpdGNoIChkYXRhLmlkKSB7XHJcbiAgICAgICAgICAgIGNhc2UgXCJpbml0XCI6IHtcclxuICAgICAgICAgICAgICAgIGltcG9ydFNjcmlwdHMoZGF0YS51cmwpO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2FzZSBcInZhbGlkYXRlXCI6IHtcclxuICAgICAgICAgICAgICAgIHZhbGlkYXRlQXN5bmMoXHJcbiAgICAgICAgICAgICAgICAgICAgZGF0YS5kYXRhLFxyXG4gICAgICAgICAgICAgICAgICAgIGRhdGEucm9vdFVybCxcclxuICAgICAgICAgICAgICAgICAgICBkYXRhLmZpbGVOYW1lLFxyXG4gICAgICAgICAgICAgICAgICAgICh1cmkpID0+XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGluZGV4ID0gcGVuZGluZ0V4dGVybmFsUmVzb3VyY2VzLmxlbmd0aDtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHBlbmRpbmdFeHRlcm5hbFJlc291cmNlcy5wdXNoKHsgcmVzb2x2ZSwgcmVqZWN0IH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcG9zdE1lc3NhZ2UoeyBpZDogXCJnZXRFeHRlcm5hbFJlc291cmNlXCIsIGluZGV4OiBpbmRleCwgdXJpOiB1cmkgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH0pXHJcbiAgICAgICAgICAgICAgICApLnRoZW4oXHJcbiAgICAgICAgICAgICAgICAgICAgKHZhbHVlKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgaWQ6IFwidmFsaWRhdGUucmVzb2x2ZVwiLCB2YWx1ZTogdmFsdWUgfSk7XHJcbiAgICAgICAgICAgICAgICAgICAgfSxcclxuICAgICAgICAgICAgICAgICAgICAocmVhc29uKSA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc3RNZXNzYWdlKHsgaWQ6IFwidmFsaWRhdGUucmVqZWN0XCIsIHJlYXNvbjogcmVhc29uIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjYXNlIFwiZ2V0RXh0ZXJuYWxSZXNvdXJjZS5yZXNvbHZlXCI6IHtcclxuICAgICAgICAgICAgICAgIHBlbmRpbmdFeHRlcm5hbFJlc291cmNlc1tkYXRhLmluZGV4XS5yZXNvbHZlKGRhdGEudmFsdWUpO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgY2FzZSBcImdldEV4dGVybmFsUmVzb3VyY2UucmVqZWN0XCI6IHtcclxuICAgICAgICAgICAgICAgIHBlbmRpbmdFeHRlcm5hbFJlc291cmNlc1tkYXRhLmluZGV4XS5yZWplY3QoZGF0YS5yZWFzb24pO1xyXG4gICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcbiAgICB9O1xyXG59XHJcblxyXG4vKipcclxuICogQ29uZmlndXJhdGlvbiBmb3IgZ2xURiB2YWxpZGF0aW9uXHJcbiAqL1xyXG5leHBvcnQgaW50ZXJmYWNlIElHTFRGVmFsaWRhdGlvbkNvbmZpZ3VyYXRpb24ge1xyXG4gICAgLyoqXHJcbiAgICAgKiBUaGUgdXJsIG9mIHRoZSBnbFRGIHZhbGlkYXRvci5cclxuICAgICAqL1xyXG4gICAgdXJsOiBzdHJpbmc7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBnbFRGIHZhbGlkYXRpb25cclxuICovXHJcbmV4cG9ydCBjbGFzcyBHTFRGVmFsaWRhdGlvbiB7XHJcbiAgICAvKipcclxuICAgICAqIFRoZSBjb25maWd1cmF0aW9uLiBEZWZhdWx0cyB0byBgeyB1cmw6IFwiaHR0cHM6Ly9jZG4uYmFieWxvbmpzLmNvbS9nbHRmX3ZhbGlkYXRvci5qc1wiIH1gLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgc3RhdGljIENvbmZpZ3VyYXRpb246IElHTFRGVmFsaWRhdGlvbkNvbmZpZ3VyYXRpb24gPSB7XHJcbiAgICAgICAgdXJsOiBgJHtUb29scy5fRGVmYXVsdENkblVybH0vZ2x0Zl92YWxpZGF0b3IuanNgLFxyXG4gICAgfTtcclxuXHJcbiAgICBwcml2YXRlIHN0YXRpYyBfTG9hZFNjcmlwdFByb21pc2U6IFByb21pc2U8dm9pZD47XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBWYWxpZGF0ZSBhIGdsVEYgYXNzZXQgdXNpbmcgdGhlIGdsVEYtVmFsaWRhdG9yLlxyXG4gICAgICogQHBhcmFtIGRhdGEgVGhlIEpTT04gb2YgYSBnbFRGIG9yIHRoZSBhcnJheSBidWZmZXIgb2YgYSBiaW5hcnkgZ2xURlxyXG4gICAgICogQHBhcmFtIHJvb3RVcmwgVGhlIHJvb3QgdXJsIGZvciB0aGUgZ2xURlxyXG4gICAgICogQHBhcmFtIGZpbGVOYW1lIFRoZSBmaWxlIG5hbWUgZm9yIHRoZSBnbFRGXHJcbiAgICAgKiBAcGFyYW0gZ2V0RXh0ZXJuYWxSZXNvdXJjZSBUaGUgY2FsbGJhY2sgdG8gZ2V0IGV4dGVybmFsIHJlc291cmNlcyBmb3IgdGhlIGdsVEYgdmFsaWRhdG9yXHJcbiAgICAgKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBnbFRGIHZhbGlkYXRpb24gcmVzdWx0cyBvbmNlIGNvbXBsZXRlXHJcbiAgICAgKi9cclxuICAgIHB1YmxpYyBzdGF0aWMgVmFsaWRhdGVBc3luYyhcclxuICAgICAgICBkYXRhOiBzdHJpbmcgfCBBcnJheUJ1ZmZlclZpZXcsXHJcbiAgICAgICAgcm9vdFVybDogc3RyaW5nLFxyXG4gICAgICAgIGZpbGVOYW1lOiBzdHJpbmcsXHJcbiAgICAgICAgZ2V0RXh0ZXJuYWxSZXNvdXJjZTogKHVyaTogc3RyaW5nKSA9PiBQcm9taXNlPEFycmF5QnVmZmVyPlxyXG4gICAgKTogUHJvbWlzZTxHTFRGMi5JR0xURlZhbGlkYXRpb25SZXN1bHRzPiB7XHJcbiAgICAgICAgY29uc3QgZGF0YUNvcHkgPSBBcnJheUJ1ZmZlci5pc1ZpZXcoZGF0YSkgPyAoZGF0YSBhcyBVaW50OEFycmF5KS5zbGljZSgpLmJ1ZmZlciA6IChkYXRhIGFzIHN0cmluZyk7XHJcblxyXG4gICAgICAgIGlmICh0eXBlb2YgV29ya2VyID09PSBcImZ1bmN0aW9uXCIpIHtcclxuICAgICAgICAgICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHdvcmtlckNvbnRlbnQgPSBgJHt2YWxpZGF0ZUFzeW5jfSgke3dvcmtlckZ1bmN9KSgpYDtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHdvcmtlckJsb2JVcmwgPSBVUkwuY3JlYXRlT2JqZWN0VVJMKG5ldyBCbG9iKFt3b3JrZXJDb250ZW50XSwgeyB0eXBlOiBcImFwcGxpY2F0aW9uL2phdmFzY3JpcHRcIiB9KSk7XHJcbiAgICAgICAgICAgICAgICBjb25zdCB3b3JrZXIgPSBuZXcgV29ya2VyKHdvcmtlckJsb2JVcmwpO1xyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IG9uRXJyb3IgPSAoZXJyb3I6IEVycm9yRXZlbnQpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICB3b3JrZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImVycm9yXCIsIG9uRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgIHdvcmtlci5yZW1vdmVFdmVudExpc3RlbmVyKFwibWVzc2FnZVwiLCBvbk1lc3NhZ2UpO1xyXG4gICAgICAgICAgICAgICAgICAgIHJlamVjdChlcnJvcik7XHJcbiAgICAgICAgICAgICAgICB9O1xyXG5cclxuICAgICAgICAgICAgICAgIGNvbnN0IG9uTWVzc2FnZSA9IChtZXNzYWdlOiBNZXNzYWdlRXZlbnQpID0+IHtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBkYXRhID0gbWVzc2FnZS5kYXRhO1xyXG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAoZGF0YS5pZCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwiZ2V0RXh0ZXJuYWxSZXNvdXJjZVwiOiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBnZXRFeHRlcm5hbFJlc291cmNlKGRhdGEudXJpKS50aGVuKFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICh2YWx1ZSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZXIucG9zdE1lc3NhZ2UoeyBpZDogXCJnZXRFeHRlcm5hbFJlc291cmNlLnJlc29sdmVcIiwgaW5kZXg6IGRhdGEuaW5kZXgsIHZhbHVlOiB2YWx1ZSB9LCBbdmFsdWVdKTtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9LFxyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIChyZWFzb24pID0+IHtcclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2VyLnBvc3RNZXNzYWdlKHsgaWQ6IFwiZ2V0RXh0ZXJuYWxSZXNvdXJjZS5yZWplY3RcIiwgaW5kZXg6IGRhdGEuaW5kZXgsIHJlYXNvbjogcmVhc29uIH0pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcclxuICAgICAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIFwidmFsaWRhdGUucmVzb2x2ZVwiOiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImVycm9yXCIsIG9uRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2VyLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIG9uTWVzc2FnZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXNvbHZlKGRhdGEudmFsdWUpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2VyLnRlcm1pbmF0ZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBcInZhbGlkYXRlLnJlamVjdFwiOiB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB3b3JrZXIucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImVycm9yXCIsIG9uRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2VyLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIG9uTWVzc2FnZSk7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWplY3QoZGF0YS5yZWFzb24pO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgd29ya2VyLnRlcm1pbmF0ZSgpO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICAgICAgfTtcclxuXHJcbiAgICAgICAgICAgICAgICB3b3JrZXIuYWRkRXZlbnRMaXN0ZW5lcihcImVycm9yXCIsIG9uRXJyb3IpO1xyXG4gICAgICAgICAgICAgICAgd29ya2VyLmFkZEV2ZW50TGlzdGVuZXIoXCJtZXNzYWdlXCIsIG9uTWVzc2FnZSk7XHJcblxyXG4gICAgICAgICAgICAgICAgd29ya2VyLnBvc3RNZXNzYWdlKHsgaWQ6IFwiaW5pdFwiLCB1cmw6IFRvb2xzLkdldEJhYnlsb25TY3JpcHRVUkwodGhpcy5Db25maWd1cmF0aW9uLnVybCkgfSk7XHJcbiAgICAgICAgICAgICAgICB3b3JrZXIucG9zdE1lc3NhZ2UoeyBpZDogXCJ2YWxpZGF0ZVwiLCBkYXRhOiBkYXRhQ29weSwgcm9vdFVybDogcm9vdFVybCwgZmlsZU5hbWU6IGZpbGVOYW1lIH0pO1xyXG4gICAgICAgICAgICB9KTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBpZiAoIXRoaXMuX0xvYWRTY3JpcHRQcm9taXNlKSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLl9Mb2FkU2NyaXB0UHJvbWlzZSA9IFRvb2xzLkxvYWRCYWJ5bG9uU2NyaXB0QXN5bmModGhpcy5Db25maWd1cmF0aW9uLnVybCk7XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9Mb2FkU2NyaXB0UHJvbWlzZS50aGVuKCgpID0+IHtcclxuICAgICAgICAgICAgICAgIHJldHVybiB2YWxpZGF0ZUFzeW5jKGRhdGFDb3B5LCByb290VXJsLCBmaWxlTmFtZSwgZ2V0RXh0ZXJuYWxSZXNvdXJjZSk7XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvbm8taW50ZXJuYWwtbW9kdWxlcyAqL1xyXG5leHBvcnQgKiBmcm9tIFwiLi9nbFRGRmlsZUxvYWRlclwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9nbFRGVmFsaWRhdGlvblwiO1xyXG5pbXBvcnQgKiBhcyBHTFRGMSBmcm9tIFwiLi8xLjAvaW5kZXhcIjtcclxuaW1wb3J0ICogYXMgR0xURjIgZnJvbSBcIi4vMi4wL2luZGV4XCI7XHJcbmV4cG9ydCB7IEdMVEYxLCBHTFRGMiB9O1xyXG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvbm8taW50ZXJuYWwtbW9kdWxlcyAqL1xyXG5leHBvcnQgKiBmcm9tIFwiLi9nbFRGL2luZGV4XCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL09CSi9pbmRleFwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9TVEwvaW5kZXhcIjtcclxuIiwiaW1wb3J0ICogYXMgRmlsZUxvYWRlciBmcm9tIFwibG9hZGVycy9nbFRGL2dsVEZGaWxlTG9hZGVyXCI7XHJcbmltcG9ydCAqIGFzIFZhbGlkYXRpb24gZnJvbSBcImxvYWRlcnMvZ2xURi9nbFRGVmFsaWRhdGlvblwiO1xyXG5cclxuLyoqXHJcbiAqIFRoaXMgaXMgdGhlIGVudHJ5IHBvaW50IGZvciB0aGUgVU1EIG1vZHVsZS5cclxuICogVGhlIGVudHJ5IHBvaW50IGZvciBhIGZ1dHVyZSBFU00gcGFja2FnZSBzaG91bGQgYmUgaW5kZXgudHNcclxuICovXHJcbmNvbnN0IGdsb2JhbE9iamVjdCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdW5kZWZpbmVkO1xyXG5pZiAodHlwZW9mIGdsb2JhbE9iamVjdCAhPT0gXCJ1bmRlZmluZWRcIikge1xyXG4gICAgKDxhbnk+Z2xvYmFsT2JqZWN0KS5CQUJZTE9OID0gKDxhbnk+Z2xvYmFsT2JqZWN0KS5CQUJZTE9OIHx8IHt9O1xyXG4gICAgZm9yIChjb25zdCBrZXkgaW4gRmlsZUxvYWRlcikge1xyXG4gICAgICAgICg8YW55Pmdsb2JhbE9iamVjdCkuQkFCWUxPTltrZXldID0gKDxhbnk+RmlsZUxvYWRlcilba2V5XTtcclxuICAgIH1cclxuICAgIGZvciAoY29uc3Qga2V5IGluIFZhbGlkYXRpb24pIHtcclxuICAgICAgICAoPGFueT5nbG9iYWxPYmplY3QpLkJBQllMT05ba2V5XSA9ICg8YW55PlZhbGlkYXRpb24pW2tleV07XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCAqIGZyb20gXCJsb2FkZXJzL2dsVEYvZ2xURkZpbGVMb2FkZXJcIjtcclxuZXhwb3J0ICogZnJvbSBcImxvYWRlcnMvZ2xURi9nbFRGVmFsaWRhdGlvblwiO1xyXG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvbm8taW50ZXJuYWwtbW9kdWxlcyAqL1xyXG5pbXBvcnQgKiBhcyBHTFRGMSBmcm9tIFwibG9hZGVycy9nbFRGLzEuMC9pbmRleFwiO1xyXG5cclxuLyoqXHJcbiAqIFRoaXMgaXMgdGhlIGVudHJ5IHBvaW50IGZvciB0aGUgVU1EIG1vZHVsZS5cclxuICogVGhlIGVudHJ5IHBvaW50IGZvciBhIGZ1dHVyZSBFU00gcGFja2FnZSBzaG91bGQgYmUgaW5kZXgudHNcclxuICovXHJcbmNvbnN0IGdsb2JhbE9iamVjdCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdW5kZWZpbmVkO1xyXG5pZiAodHlwZW9mIGdsb2JhbE9iamVjdCAhPT0gXCJ1bmRlZmluZWRcIikge1xyXG4gICAgKDxhbnk+Z2xvYmFsT2JqZWN0KS5CQUJZTE9OID0gKDxhbnk+Z2xvYmFsT2JqZWN0KS5CQUJZTE9OIHx8IHt9O1xyXG4gICAgKDxhbnk+Z2xvYmFsT2JqZWN0KS5CQUJZTE9OLkdMVEYxID0gKDxhbnk+Z2xvYmFsT2JqZWN0KS5CQUJZTE9OLkdMVEYxIHx8IHt9O1xyXG4gICAgZm9yIChjb25zdCBrZXkgaW4gR0xURjEpIHtcclxuICAgICAgICAoPGFueT5nbG9iYWxPYmplY3QpLkJBQllMT04uR0xURjFba2V5XSA9ICg8YW55PkdMVEYxKVtrZXldO1xyXG4gICAgfVxyXG59XHJcblxyXG5leHBvcnQgeyBHTFRGMSB9O1xyXG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvbm8taW50ZXJuYWwtbW9kdWxlcyAqL1xyXG5pbXBvcnQgKiBhcyBFeHRlbnNpb25zIGZyb20gXCJsb2FkZXJzL2dsVEYvMi4wL0V4dGVuc2lvbnMvaW5kZXhcIjtcclxuaW1wb3J0ICogYXMgSW50ZXJmYWNlcyBmcm9tIFwibG9hZGVycy9nbFRGLzIuMC9nbFRGTG9hZGVySW50ZXJmYWNlc1wiO1xyXG5pbXBvcnQgKiBhcyBHTFRGMiBmcm9tIFwibG9hZGVycy9nbFRGLzIuMC9pbmRleFwiO1xyXG5cclxuLyoqXHJcbiAqIFRoaXMgaXMgdGhlIGVudHJ5IHBvaW50IGZvciB0aGUgVU1EIG1vZHVsZS5cclxuICogVGhlIGVudHJ5IHBvaW50IGZvciBhIGZ1dHVyZSBFU00gcGFja2FnZSBzaG91bGQgYmUgaW5kZXgudHNcclxuICovXHJcbmNvbnN0IGdsb2JhbE9iamVjdCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdW5kZWZpbmVkO1xyXG5pZiAodHlwZW9mIGdsb2JhbE9iamVjdCAhPT0gXCJ1bmRlZmluZWRcIikge1xyXG4gICAgKDxhbnk+Z2xvYmFsT2JqZWN0KS5CQUJZTE9OID0gKDxhbnk+Z2xvYmFsT2JqZWN0KS5CQUJZTE9OIHx8IHt9O1xyXG4gICAgY29uc3QgQkFCWUxPTiA9ICg8YW55Pmdsb2JhbE9iamVjdCkuQkFCWUxPTjtcclxuICAgIEJBQllMT04uR0xURjIgPSBCQUJZTE9OLkdMVEYyIHx8IHt9O1xyXG4gICAgQkFCWUxPTi5HTFRGMi5Mb2FkZXIgPSBCQUJZTE9OLkdMVEYyLkxvYWRlciB8fCB7fTtcclxuICAgIEJBQllMT04uR0xURjIuTG9hZGVyLkV4dGVuc2lvbnMgPSBCQUJZTE9OLkdMVEYyLkxvYWRlci5FeHRlbnNpb25zIHx8IHt9O1xyXG5cclxuICAgIGNvbnN0IGtleXMgPSBbXTtcclxuICAgIGZvciAoY29uc3Qga2V5IGluIEV4dGVuc2lvbnMpIHtcclxuICAgICAgICBCQUJZTE9OLkdMVEYyLkxvYWRlci5FeHRlbnNpb25zW2tleV0gPSAoPGFueT5FeHRlbnNpb25zKVtrZXldO1xyXG4gICAgICAgIGtleXMucHVzaChrZXkpO1xyXG4gICAgfVxyXG4gICAgZm9yIChjb25zdCBrZXkgaW4gSW50ZXJmYWNlcykge1xyXG4gICAgICAgIEJBQllMT04uR0xURjIuTG9hZGVyW2tleV0gPSAoPGFueT5JbnRlcmZhY2VzKVtrZXldO1xyXG4gICAgICAgIGtleXMucHVzaChrZXkpO1xyXG4gICAgfVxyXG5cclxuICAgIGZvciAoY29uc3Qga2V5IGluIEdMVEYyKSB7XHJcbiAgICAgICAgLy8gUHJldmVudCBSZWFzc2lnbm1lbnQuXHJcbiAgICAgICAgaWYgKGtleXMuaW5kZXhPZihrZXkpID4gLTEpIHtcclxuICAgICAgICAgICAgY29udGludWU7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBCQUJZTE9OLkdMVEYyW2tleV0gPSAoPGFueT5HTFRGMilba2V5XTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IHsgR0xURjIgfTtcclxuIiwiLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWludGVybmFsLW1vZHVsZXMgKi9cclxuaW1wb3J0ICogYXMgTG9hZGVycyBmcm9tIFwibG9hZGVycy9PQkovaW5kZXhcIjtcclxuXHJcbi8qKlxyXG4gKiBUaGlzIGlzIHRoZSBlbnRyeSBwb2ludCBmb3IgdGhlIFVNRCBtb2R1bGUuXHJcbiAqIFRoZSBlbnRyeSBwb2ludCBmb3IgYSBmdXR1cmUgRVNNIHBhY2thZ2Ugc2hvdWxkIGJlIGluZGV4LnRzXHJcbiAqL1xyXG5jb25zdCBnbG9iYWxPYmplY3QgPSB0eXBlb2YgZ2xvYmFsICE9PSBcInVuZGVmaW5lZFwiID8gZ2xvYmFsIDogdHlwZW9mIHdpbmRvdyAhPT0gXCJ1bmRlZmluZWRcIiA/IHdpbmRvdyA6IHVuZGVmaW5lZDtcclxuaWYgKHR5cGVvZiBnbG9iYWxPYmplY3QgIT09IFwidW5kZWZpbmVkXCIpIHtcclxuICAgIGZvciAoY29uc3Qga2V5IGluIExvYWRlcnMpIHtcclxuICAgICAgICBpZiAoISg8YW55Pmdsb2JhbE9iamVjdCkuQkFCWUxPTltrZXldKSB7XHJcbiAgICAgICAgICAgICg8YW55Pmdsb2JhbE9iamVjdCkuQkFCWUxPTltrZXldID0gKDxhbnk+TG9hZGVycylba2V5XTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcbn1cclxuXHJcbmV4cG9ydCAqIGZyb20gXCJsb2FkZXJzL09CSi9pbmRleFwiO1xyXG4iLCIvKiBlc2xpbnQtZGlzYWJsZSBpbXBvcnQvbm8taW50ZXJuYWwtbW9kdWxlcyAqL1xyXG5pbXBvcnQgKiBhcyBMb2FkZXJzIGZyb20gXCJsb2FkZXJzL1NUTC9pbmRleFwiO1xyXG5cclxuLyoqXHJcbiAqIFRoaXMgaXMgdGhlIGVudHJ5IHBvaW50IGZvciB0aGUgVU1EIG1vZHVsZS5cclxuICogVGhlIGVudHJ5IHBvaW50IGZvciBhIGZ1dHVyZSBFU00gcGFja2FnZSBzaG91bGQgYmUgaW5kZXgudHNcclxuICovXHJcbmNvbnN0IGdsb2JhbE9iamVjdCA9IHR5cGVvZiBnbG9iYWwgIT09IFwidW5kZWZpbmVkXCIgPyBnbG9iYWwgOiB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gd2luZG93IDogdW5kZWZpbmVkO1xyXG5pZiAodHlwZW9mIGdsb2JhbE9iamVjdCAhPT0gXCJ1bmRlZmluZWRcIikge1xyXG4gICAgZm9yIChjb25zdCBrZXkgaW4gTG9hZGVycykge1xyXG4gICAgICAgIGlmICghKDxhbnk+Z2xvYmFsT2JqZWN0KS5CQUJZTE9OW2tleV0pIHtcclxuICAgICAgICAgICAgKDxhbnk+Z2xvYmFsT2JqZWN0KS5CQUJZTE9OW2tleV0gPSAoPGFueT5Mb2FkZXJzKVtrZXldO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0ICogZnJvbSBcImxvYWRlcnMvU1RML2luZGV4XCI7XHJcbiIsIi8qIGVzbGludC1kaXNhYmxlIGltcG9ydC9leHBvcnQgKi9cclxuLyogZXNsaW50LWRpc2FibGUgaW1wb3J0L25vLWludGVybmFsLW1vZHVsZXMgKi9cclxuZXhwb3J0ICogZnJvbSBcImxvYWRlcnMvaW5kZXhcIjtcclxuZXhwb3J0ICogZnJvbSBcIi4vbGVnYWN5LWdsVEZcIjtcclxuZXhwb3J0ICogZnJvbSBcIi4vbGVnYWN5LWdsVEYxXCI7XHJcbmV4cG9ydCAqIGZyb20gXCIuL2xlZ2FjeS1nbFRGMlwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9sZWdhY3ktb2JqRmlsZUxvYWRlclwiO1xyXG5leHBvcnQgKiBmcm9tIFwiLi9sZWdhY3ktc3RsRmlsZUxvYWRlclwiO1xyXG4iLCJtb2R1bGUuZXhwb3J0cyA9IF9fV0VCUEFDS19FWFRFUk5BTF9NT0RVTEVfYmFieWxvbmpzX01pc2Nfb2JzZXJ2YWJsZV9fOyIsIi8qKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKipcbkNvcHlyaWdodCAoYykgTWljcm9zb2Z0IENvcnBvcmF0aW9uLlxuXG5QZXJtaXNzaW9uIHRvIHVzZSwgY29weSwgbW9kaWZ5LCBhbmQvb3IgZGlzdHJpYnV0ZSB0aGlzIHNvZnR3YXJlIGZvciBhbnlcbnB1cnBvc2Ugd2l0aCBvciB3aXRob3V0IGZlZSBpcyBoZXJlYnkgZ3JhbnRlZC5cblxuVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiBBTkQgVEhFIEFVVEhPUiBESVNDTEFJTVMgQUxMIFdBUlJBTlRJRVMgV0lUSFxuUkVHQVJEIFRPIFRISVMgU09GVFdBUkUgSU5DTFVESU5HIEFMTCBJTVBMSUVEIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXG5JTkRJUkVDVCwgT1IgQ09OU0VRVUVOVElBTCBEQU1BR0VTIE9SIEFOWSBEQU1BR0VTIFdIQVRTT0VWRVIgUkVTVUxUSU5HIEZST01cbkxPU1MgT0YgVVNFLCBEQVRBIE9SIFBST0ZJVFMsIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBORUdMSUdFTkNFIE9SXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXG5QRVJGT1JNQU5DRSBPRiBUSElTIFNPRlRXQVJFLlxuKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKiogKi9cbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlLCBTdXBwcmVzc2VkRXJyb3IsIFN5bWJvbCAqL1xuXG52YXIgZXh0ZW5kU3RhdGljcyA9IGZ1bmN0aW9uKGQsIGIpIHtcbiAgZXh0ZW5kU3RhdGljcyA9IE9iamVjdC5zZXRQcm90b3R5cGVPZiB8fFxuICAgICAgKHsgX19wcm90b19fOiBbXSB9IGluc3RhbmNlb2YgQXJyYXkgJiYgZnVuY3Rpb24gKGQsIGIpIHsgZC5fX3Byb3RvX18gPSBiOyB9KSB8fFxuICAgICAgZnVuY3Rpb24gKGQsIGIpIHsgZm9yICh2YXIgcCBpbiBiKSBpZiAoT2JqZWN0LnByb3RvdHlwZS5oYXNPd25Qcm9wZXJ0eS5jYWxsKGIsIHApKSBkW3BdID0gYltwXTsgfTtcbiAgcmV0dXJuIGV4dGVuZFN0YXRpY3MoZCwgYik7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gX19leHRlbmRzKGQsIGIpIHtcbiAgaWYgKHR5cGVvZiBiICE9PSBcImZ1bmN0aW9uXCIgJiYgYiAhPT0gbnVsbClcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDbGFzcyBleHRlbmRzIHZhbHVlIFwiICsgU3RyaW5nKGIpICsgXCIgaXMgbm90IGEgY29uc3RydWN0b3Igb3IgbnVsbFwiKTtcbiAgZXh0ZW5kU3RhdGljcyhkLCBiKTtcbiAgZnVuY3Rpb24gX18oKSB7IHRoaXMuY29uc3RydWN0b3IgPSBkOyB9XG4gIGQucHJvdG90eXBlID0gYiA9PT0gbnVsbCA/IE9iamVjdC5jcmVhdGUoYikgOiAoX18ucHJvdG90eXBlID0gYi5wcm90b3R5cGUsIG5ldyBfXygpKTtcbn1cblxuZXhwb3J0IHZhciBfX2Fzc2lnbiA9IGZ1bmN0aW9uKCkge1xuICBfX2Fzc2lnbiA9IE9iamVjdC5hc3NpZ24gfHwgZnVuY3Rpb24gX19hc3NpZ24odCkge1xuICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XG4gICAgICAgICAgcyA9IGFyZ3VtZW50c1tpXTtcbiAgICAgICAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkpIHRbcF0gPSBzW3BdO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHQ7XG4gIH1cbiAgcmV0dXJuIF9fYXNzaWduLmFwcGx5KHRoaXMsIGFyZ3VtZW50cyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfX3Jlc3QocywgZSkge1xuICB2YXIgdCA9IHt9O1xuICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkgJiYgZS5pbmRleE9mKHApIDwgMClcbiAgICAgIHRbcF0gPSBzW3BdO1xuICBpZiAocyAhPSBudWxsICYmIHR5cGVvZiBPYmplY3QuZ2V0T3duUHJvcGVydHlTeW1ib2xzID09PSBcImZ1bmN0aW9uXCIpXG4gICAgICBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgaWYgKGUuaW5kZXhPZihwW2ldKSA8IDAgJiYgT2JqZWN0LnByb3RvdHlwZS5wcm9wZXJ0eUlzRW51bWVyYWJsZS5jYWxsKHMsIHBbaV0pKVxuICAgICAgICAgICAgICB0W3BbaV1dID0gc1twW2ldXTtcbiAgICAgIH1cbiAgcmV0dXJuIHQ7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfX2RlY29yYXRlKGRlY29yYXRvcnMsIHRhcmdldCwga2V5LCBkZXNjKSB7XG4gIHZhciBjID0gYXJndW1lbnRzLmxlbmd0aCwgciA9IGMgPCAzID8gdGFyZ2V0IDogZGVzYyA9PT0gbnVsbCA/IGRlc2MgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwga2V5KSA6IGRlc2MsIGQ7XG4gIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5kZWNvcmF0ZSA9PT0gXCJmdW5jdGlvblwiKSByID0gUmVmbGVjdC5kZWNvcmF0ZShkZWNvcmF0b3JzLCB0YXJnZXQsIGtleSwgZGVzYyk7XG4gIGVsc2UgZm9yICh2YXIgaSA9IGRlY29yYXRvcnMubGVuZ3RoIC0gMTsgaSA+PSAwOyBpLS0pIGlmIChkID0gZGVjb3JhdG9yc1tpXSkgciA9IChjIDwgMyA/IGQocikgOiBjID4gMyA/IGQodGFyZ2V0LCBrZXksIHIpIDogZCh0YXJnZXQsIGtleSkpIHx8IHI7XG4gIHJldHVybiBjID4gMyAmJiByICYmIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGtleSwgciksIHI7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfX3BhcmFtKHBhcmFtSW5kZXgsIGRlY29yYXRvcikge1xuICByZXR1cm4gZnVuY3Rpb24gKHRhcmdldCwga2V5KSB7IGRlY29yYXRvcih0YXJnZXQsIGtleSwgcGFyYW1JbmRleCk7IH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9fZXNEZWNvcmF0ZShjdG9yLCBkZXNjcmlwdG9ySW4sIGRlY29yYXRvcnMsIGNvbnRleHRJbiwgaW5pdGlhbGl6ZXJzLCBleHRyYUluaXRpYWxpemVycykge1xuICBmdW5jdGlvbiBhY2NlcHQoZikgeyBpZiAoZiAhPT0gdm9pZCAwICYmIHR5cGVvZiBmICE9PSBcImZ1bmN0aW9uXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJGdW5jdGlvbiBleHBlY3RlZFwiKTsgcmV0dXJuIGY7IH1cbiAgdmFyIGtpbmQgPSBjb250ZXh0SW4ua2luZCwga2V5ID0ga2luZCA9PT0gXCJnZXR0ZXJcIiA/IFwiZ2V0XCIgOiBraW5kID09PSBcInNldHRlclwiID8gXCJzZXRcIiA6IFwidmFsdWVcIjtcbiAgdmFyIHRhcmdldCA9ICFkZXNjcmlwdG9ySW4gJiYgY3RvciA/IGNvbnRleHRJbltcInN0YXRpY1wiXSA/IGN0b3IgOiBjdG9yLnByb3RvdHlwZSA6IG51bGw7XG4gIHZhciBkZXNjcmlwdG9yID0gZGVzY3JpcHRvckluIHx8ICh0YXJnZXQgPyBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRhcmdldCwgY29udGV4dEluLm5hbWUpIDoge30pO1xuICB2YXIgXywgZG9uZSA9IGZhbHNlO1xuICBmb3IgKHZhciBpID0gZGVjb3JhdG9ycy5sZW5ndGggLSAxOyBpID49IDA7IGktLSkge1xuICAgICAgdmFyIGNvbnRleHQgPSB7fTtcbiAgICAgIGZvciAodmFyIHAgaW4gY29udGV4dEluKSBjb250ZXh0W3BdID0gcCA9PT0gXCJhY2Nlc3NcIiA/IHt9IDogY29udGV4dEluW3BdO1xuICAgICAgZm9yICh2YXIgcCBpbiBjb250ZXh0SW4uYWNjZXNzKSBjb250ZXh0LmFjY2Vzc1twXSA9IGNvbnRleHRJbi5hY2Nlc3NbcF07XG4gICAgICBjb250ZXh0LmFkZEluaXRpYWxpemVyID0gZnVuY3Rpb24gKGYpIHsgaWYgKGRvbmUpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgYWRkIGluaXRpYWxpemVycyBhZnRlciBkZWNvcmF0aW9uIGhhcyBjb21wbGV0ZWRcIik7IGV4dHJhSW5pdGlhbGl6ZXJzLnB1c2goYWNjZXB0KGYgfHwgbnVsbCkpOyB9O1xuICAgICAgdmFyIHJlc3VsdCA9ICgwLCBkZWNvcmF0b3JzW2ldKShraW5kID09PSBcImFjY2Vzc29yXCIgPyB7IGdldDogZGVzY3JpcHRvci5nZXQsIHNldDogZGVzY3JpcHRvci5zZXQgfSA6IGRlc2NyaXB0b3Jba2V5XSwgY29udGV4dCk7XG4gICAgICBpZiAoa2luZCA9PT0gXCJhY2Nlc3NvclwiKSB7XG4gICAgICAgICAgaWYgKHJlc3VsdCA9PT0gdm9pZCAwKSBjb250aW51ZTtcbiAgICAgICAgICBpZiAocmVzdWx0ID09PSBudWxsIHx8IHR5cGVvZiByZXN1bHQgIT09IFwib2JqZWN0XCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJPYmplY3QgZXhwZWN0ZWRcIik7XG4gICAgICAgICAgaWYgKF8gPSBhY2NlcHQocmVzdWx0LmdldCkpIGRlc2NyaXB0b3IuZ2V0ID0gXztcbiAgICAgICAgICBpZiAoXyA9IGFjY2VwdChyZXN1bHQuc2V0KSkgZGVzY3JpcHRvci5zZXQgPSBfO1xuICAgICAgICAgIGlmIChfID0gYWNjZXB0KHJlc3VsdC5pbml0KSkgaW5pdGlhbGl6ZXJzLnVuc2hpZnQoXyk7XG4gICAgICB9XG4gICAgICBlbHNlIGlmIChfID0gYWNjZXB0KHJlc3VsdCkpIHtcbiAgICAgICAgICBpZiAoa2luZCA9PT0gXCJmaWVsZFwiKSBpbml0aWFsaXplcnMudW5zaGlmdChfKTtcbiAgICAgICAgICBlbHNlIGRlc2NyaXB0b3Jba2V5XSA9IF87XG4gICAgICB9XG4gIH1cbiAgaWYgKHRhcmdldCkgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRhcmdldCwgY29udGV4dEluLm5hbWUsIGRlc2NyaXB0b3IpO1xuICBkb25lID0gdHJ1ZTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBfX3J1bkluaXRpYWxpemVycyh0aGlzQXJnLCBpbml0aWFsaXplcnMsIHZhbHVlKSB7XG4gIHZhciB1c2VWYWx1ZSA9IGFyZ3VtZW50cy5sZW5ndGggPiAyO1xuICBmb3IgKHZhciBpID0gMDsgaSA8IGluaXRpYWxpemVycy5sZW5ndGg7IGkrKykge1xuICAgICAgdmFsdWUgPSB1c2VWYWx1ZSA/IGluaXRpYWxpemVyc1tpXS5jYWxsKHRoaXNBcmcsIHZhbHVlKSA6IGluaXRpYWxpemVyc1tpXS5jYWxsKHRoaXNBcmcpO1xuICB9XG4gIHJldHVybiB1c2VWYWx1ZSA/IHZhbHVlIDogdm9pZCAwO1xufTtcblxuZXhwb3J0IGZ1bmN0aW9uIF9fcHJvcEtleSh4KSB7XG4gIHJldHVybiB0eXBlb2YgeCA9PT0gXCJzeW1ib2xcIiA/IHggOiBcIlwiLmNvbmNhdCh4KTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBfX3NldEZ1bmN0aW9uTmFtZShmLCBuYW1lLCBwcmVmaXgpIHtcbiAgaWYgKHR5cGVvZiBuYW1lID09PSBcInN5bWJvbFwiKSBuYW1lID0gbmFtZS5kZXNjcmlwdGlvbiA/IFwiW1wiLmNvbmNhdChuYW1lLmRlc2NyaXB0aW9uLCBcIl1cIikgOiBcIlwiO1xuICByZXR1cm4gT2JqZWN0LmRlZmluZVByb3BlcnR5KGYsIFwibmFtZVwiLCB7IGNvbmZpZ3VyYWJsZTogdHJ1ZSwgdmFsdWU6IHByZWZpeCA/IFwiXCIuY29uY2F0KHByZWZpeCwgXCIgXCIsIG5hbWUpIDogbmFtZSB9KTtcbn07XG5cbmV4cG9ydCBmdW5jdGlvbiBfX21ldGFkYXRhKG1ldGFkYXRhS2V5LCBtZXRhZGF0YVZhbHVlKSB7XG4gIGlmICh0eXBlb2YgUmVmbGVjdCA9PT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgUmVmbGVjdC5tZXRhZGF0YSA9PT0gXCJmdW5jdGlvblwiKSByZXR1cm4gUmVmbGVjdC5tZXRhZGF0YShtZXRhZGF0YUtleSwgbWV0YWRhdGFWYWx1ZSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfX2F3YWl0ZXIodGhpc0FyZywgX2FyZ3VtZW50cywgUCwgZ2VuZXJhdG9yKSB7XG4gIGZ1bmN0aW9uIGFkb3B0KHZhbHVlKSB7IHJldHVybiB2YWx1ZSBpbnN0YW5jZW9mIFAgPyB2YWx1ZSA6IG5ldyBQKGZ1bmN0aW9uIChyZXNvbHZlKSB7IHJlc29sdmUodmFsdWUpOyB9KTsgfVxuICByZXR1cm4gbmV3IChQIHx8IChQID0gUHJvbWlzZSkpKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcbiAgICAgIGZ1bmN0aW9uIGZ1bGZpbGxlZCh2YWx1ZSkgeyB0cnkgeyBzdGVwKGdlbmVyYXRvci5uZXh0KHZhbHVlKSk7IH0gY2F0Y2ggKGUpIHsgcmVqZWN0KGUpOyB9IH1cbiAgICAgIGZ1bmN0aW9uIHJlamVjdGVkKHZhbHVlKSB7IHRyeSB7IHN0ZXAoZ2VuZXJhdG9yW1widGhyb3dcIl0odmFsdWUpKTsgfSBjYXRjaCAoZSkgeyByZWplY3QoZSk7IH0gfVxuICAgICAgZnVuY3Rpb24gc3RlcChyZXN1bHQpIHsgcmVzdWx0LmRvbmUgPyByZXNvbHZlKHJlc3VsdC52YWx1ZSkgOiBhZG9wdChyZXN1bHQudmFsdWUpLnRoZW4oZnVsZmlsbGVkLCByZWplY3RlZCk7IH1cbiAgICAgIHN0ZXAoKGdlbmVyYXRvciA9IGdlbmVyYXRvci5hcHBseSh0aGlzQXJnLCBfYXJndW1lbnRzIHx8IFtdKSkubmV4dCgpKTtcbiAgfSk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfX2dlbmVyYXRvcih0aGlzQXJnLCBib2R5KSB7XG4gIHZhciBfID0geyBsYWJlbDogMCwgc2VudDogZnVuY3Rpb24oKSB7IGlmICh0WzBdICYgMSkgdGhyb3cgdFsxXTsgcmV0dXJuIHRbMV07IH0sIHRyeXM6IFtdLCBvcHM6IFtdIH0sIGYsIHksIHQsIGc7XG4gIHJldHVybiBnID0geyBuZXh0OiB2ZXJiKDApLCBcInRocm93XCI6IHZlcmIoMSksIFwicmV0dXJuXCI6IHZlcmIoMikgfSwgdHlwZW9mIFN5bWJvbCA9PT0gXCJmdW5jdGlvblwiICYmIChnW1N5bWJvbC5pdGVyYXRvcl0gPSBmdW5jdGlvbigpIHsgcmV0dXJuIHRoaXM7IH0pLCBnO1xuICBmdW5jdGlvbiB2ZXJiKG4pIHsgcmV0dXJuIGZ1bmN0aW9uICh2KSB7IHJldHVybiBzdGVwKFtuLCB2XSk7IH07IH1cbiAgZnVuY3Rpb24gc3RlcChvcCkge1xuICAgICAgaWYgKGYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJHZW5lcmF0b3IgaXMgYWxyZWFkeSBleGVjdXRpbmcuXCIpO1xuICAgICAgd2hpbGUgKGcgJiYgKGcgPSAwLCBvcFswXSAmJiAoXyA9IDApKSwgXykgdHJ5IHtcbiAgICAgICAgICBpZiAoZiA9IDEsIHkgJiYgKHQgPSBvcFswXSAmIDIgPyB5W1wicmV0dXJuXCJdIDogb3BbMF0gPyB5W1widGhyb3dcIl0gfHwgKCh0ID0geVtcInJldHVyblwiXSkgJiYgdC5jYWxsKHkpLCAwKSA6IHkubmV4dCkgJiYgISh0ID0gdC5jYWxsKHksIG9wWzFdKSkuZG9uZSkgcmV0dXJuIHQ7XG4gICAgICAgICAgaWYgKHkgPSAwLCB0KSBvcCA9IFtvcFswXSAmIDIsIHQudmFsdWVdO1xuICAgICAgICAgIHN3aXRjaCAob3BbMF0pIHtcbiAgICAgICAgICAgICAgY2FzZSAwOiBjYXNlIDE6IHQgPSBvcDsgYnJlYWs7XG4gICAgICAgICAgICAgIGNhc2UgNDogXy5sYWJlbCsrOyByZXR1cm4geyB2YWx1ZTogb3BbMV0sIGRvbmU6IGZhbHNlIH07XG4gICAgICAgICAgICAgIGNhc2UgNTogXy5sYWJlbCsrOyB5ID0gb3BbMV07IG9wID0gWzBdOyBjb250aW51ZTtcbiAgICAgICAgICAgICAgY2FzZSA3OiBvcCA9IF8ub3BzLnBvcCgpOyBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgICAgaWYgKCEodCA9IF8udHJ5cywgdCA9IHQubGVuZ3RoID4gMCAmJiB0W3QubGVuZ3RoIC0gMV0pICYmIChvcFswXSA9PT0gNiB8fCBvcFswXSA9PT0gMikpIHsgXyA9IDA7IGNvbnRpbnVlOyB9XG4gICAgICAgICAgICAgICAgICBpZiAob3BbMF0gPT09IDMgJiYgKCF0IHx8IChvcFsxXSA+IHRbMF0gJiYgb3BbMV0gPCB0WzNdKSkpIHsgXy5sYWJlbCA9IG9wWzFdOyBicmVhazsgfVxuICAgICAgICAgICAgICAgICAgaWYgKG9wWzBdID09PSA2ICYmIF8ubGFiZWwgPCB0WzFdKSB7IF8ubGFiZWwgPSB0WzFdOyB0ID0gb3A7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICBpZiAodCAmJiBfLmxhYmVsIDwgdFsyXSkgeyBfLmxhYmVsID0gdFsyXTsgXy5vcHMucHVzaChvcCk7IGJyZWFrOyB9XG4gICAgICAgICAgICAgICAgICBpZiAodFsyXSkgXy5vcHMucG9wKCk7XG4gICAgICAgICAgICAgICAgICBfLnRyeXMucG9wKCk7IGNvbnRpbnVlO1xuICAgICAgICAgIH1cbiAgICAgICAgICBvcCA9IGJvZHkuY2FsbCh0aGlzQXJnLCBfKTtcbiAgICAgIH0gY2F0Y2ggKGUpIHsgb3AgPSBbNiwgZV07IHkgPSAwOyB9IGZpbmFsbHkgeyBmID0gdCA9IDA7IH1cbiAgICAgIGlmIChvcFswXSAmIDUpIHRocm93IG9wWzFdOyByZXR1cm4geyB2YWx1ZTogb3BbMF0gPyBvcFsxXSA6IHZvaWQgMCwgZG9uZTogdHJ1ZSB9O1xuICB9XG59XG5cbmV4cG9ydCB2YXIgX19jcmVhdGVCaW5kaW5nID0gT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuICB2YXIgZGVzYyA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IobSwgayk7XG4gIGlmICghZGVzYyB8fCAoXCJnZXRcIiBpbiBkZXNjID8gIW0uX19lc01vZHVsZSA6IGRlc2Mud3JpdGFibGUgfHwgZGVzYy5jb25maWd1cmFibGUpKSB7XG4gICAgICBkZXNjID0geyBlbnVtZXJhYmxlOiB0cnVlLCBnZXQ6IGZ1bmN0aW9uKCkgeyByZXR1cm4gbVtrXTsgfSB9O1xuICB9XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBrMiwgZGVzYyk7XG59KSA6IChmdW5jdGlvbihvLCBtLCBrLCBrMikge1xuICBpZiAoazIgPT09IHVuZGVmaW5lZCkgazIgPSBrO1xuICBvW2syXSA9IG1ba107XG59KTtcblxuZXhwb3J0IGZ1bmN0aW9uIF9fZXhwb3J0U3RhcihtLCBvKSB7XG4gIGZvciAodmFyIHAgaW4gbSkgaWYgKHAgIT09IFwiZGVmYXVsdFwiICYmICFPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobywgcCkpIF9fY3JlYXRlQmluZGluZyhvLCBtLCBwKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9fdmFsdWVzKG8pIHtcbiAgdmFyIHMgPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgU3ltYm9sLml0ZXJhdG9yLCBtID0gcyAmJiBvW3NdLCBpID0gMDtcbiAgaWYgKG0pIHJldHVybiBtLmNhbGwobyk7XG4gIGlmIChvICYmIHR5cGVvZiBvLmxlbmd0aCA9PT0gXCJudW1iZXJcIikgcmV0dXJuIHtcbiAgICAgIG5leHQ6IGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICBpZiAobyAmJiBpID49IG8ubGVuZ3RoKSBvID0gdm9pZCAwO1xuICAgICAgICAgIHJldHVybiB7IHZhbHVlOiBvICYmIG9baSsrXSwgZG9uZTogIW8gfTtcbiAgICAgIH1cbiAgfTtcbiAgdGhyb3cgbmV3IFR5cGVFcnJvcihzID8gXCJPYmplY3QgaXMgbm90IGl0ZXJhYmxlLlwiIDogXCJTeW1ib2wuaXRlcmF0b3IgaXMgbm90IGRlZmluZWQuXCIpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX19yZWFkKG8sIG4pIHtcbiAgdmFyIG0gPSB0eXBlb2YgU3ltYm9sID09PSBcImZ1bmN0aW9uXCIgJiYgb1tTeW1ib2wuaXRlcmF0b3JdO1xuICBpZiAoIW0pIHJldHVybiBvO1xuICB2YXIgaSA9IG0uY2FsbChvKSwgciwgYXIgPSBbXSwgZTtcbiAgdHJ5IHtcbiAgICAgIHdoaWxlICgobiA9PT0gdm9pZCAwIHx8IG4tLSA+IDApICYmICEociA9IGkubmV4dCgpKS5kb25lKSBhci5wdXNoKHIudmFsdWUpO1xuICB9XG4gIGNhdGNoIChlcnJvcikgeyBlID0geyBlcnJvcjogZXJyb3IgfTsgfVxuICBmaW5hbGx5IHtcbiAgICAgIHRyeSB7XG4gICAgICAgICAgaWYgKHIgJiYgIXIuZG9uZSAmJiAobSA9IGlbXCJyZXR1cm5cIl0pKSBtLmNhbGwoaSk7XG4gICAgICB9XG4gICAgICBmaW5hbGx5IHsgaWYgKGUpIHRocm93IGUuZXJyb3I7IH1cbiAgfVxuICByZXR1cm4gYXI7XG59XG5cbi8qKiBAZGVwcmVjYXRlZCAqL1xuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkKCkge1xuICBmb3IgKHZhciBhciA9IFtdLCBpID0gMDsgaSA8IGFyZ3VtZW50cy5sZW5ndGg7IGkrKylcbiAgICAgIGFyID0gYXIuY29uY2F0KF9fcmVhZChhcmd1bWVudHNbaV0pKTtcbiAgcmV0dXJuIGFyO1xufVxuXG4vKiogQGRlcHJlY2F0ZWQgKi9cbmV4cG9ydCBmdW5jdGlvbiBfX3NwcmVhZEFycmF5cygpIHtcbiAgZm9yICh2YXIgcyA9IDAsIGkgPSAwLCBpbCA9IGFyZ3VtZW50cy5sZW5ndGg7IGkgPCBpbDsgaSsrKSBzICs9IGFyZ3VtZW50c1tpXS5sZW5ndGg7XG4gIGZvciAodmFyIHIgPSBBcnJheShzKSwgayA9IDAsIGkgPSAwOyBpIDwgaWw7IGkrKylcbiAgICAgIGZvciAodmFyIGEgPSBhcmd1bWVudHNbaV0sIGogPSAwLCBqbCA9IGEubGVuZ3RoOyBqIDwgamw7IGorKywgaysrKVxuICAgICAgICAgIHJba10gPSBhW2pdO1xuICByZXR1cm4gcjtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9fc3ByZWFkQXJyYXkodG8sIGZyb20sIHBhY2spIHtcbiAgaWYgKHBhY2sgfHwgYXJndW1lbnRzLmxlbmd0aCA9PT0gMikgZm9yICh2YXIgaSA9IDAsIGwgPSBmcm9tLmxlbmd0aCwgYXI7IGkgPCBsOyBpKyspIHtcbiAgICAgIGlmIChhciB8fCAhKGkgaW4gZnJvbSkpIHtcbiAgICAgICAgICBpZiAoIWFyKSBhciA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZyb20sIDAsIGkpO1xuICAgICAgICAgIGFyW2ldID0gZnJvbVtpXTtcbiAgICAgIH1cbiAgfVxuICByZXR1cm4gdG8uY29uY2F0KGFyIHx8IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGZyb20pKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9fYXdhaXQodikge1xuICByZXR1cm4gdGhpcyBpbnN0YW5jZW9mIF9fYXdhaXQgPyAodGhpcy52ID0gdiwgdGhpcykgOiBuZXcgX19hd2FpdCh2KTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9fYXN5bmNHZW5lcmF0b3IodGhpc0FyZywgX2FyZ3VtZW50cywgZ2VuZXJhdG9yKSB7XG4gIGlmICghU3ltYm9sLmFzeW5jSXRlcmF0b3IpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJTeW1ib2wuYXN5bmNJdGVyYXRvciBpcyBub3QgZGVmaW5lZC5cIik7XG4gIHZhciBnID0gZ2VuZXJhdG9yLmFwcGx5KHRoaXNBcmcsIF9hcmd1bWVudHMgfHwgW10pLCBpLCBxID0gW107XG4gIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLmFzeW5jSXRlcmF0b3JdID0gZnVuY3Rpb24gKCkgeyByZXR1cm4gdGhpczsgfSwgaTtcbiAgZnVuY3Rpb24gdmVyYihuKSB7IGlmIChnW25dKSBpW25dID0gZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChhLCBiKSB7IHEucHVzaChbbiwgdiwgYSwgYl0pID4gMSB8fCByZXN1bWUobiwgdik7IH0pOyB9OyB9XG4gIGZ1bmN0aW9uIHJlc3VtZShuLCB2KSB7IHRyeSB7IHN0ZXAoZ1tuXSh2KSk7IH0gY2F0Y2ggKGUpIHsgc2V0dGxlKHFbMF1bM10sIGUpOyB9IH1cbiAgZnVuY3Rpb24gc3RlcChyKSB7IHIudmFsdWUgaW5zdGFuY2VvZiBfX2F3YWl0ID8gUHJvbWlzZS5yZXNvbHZlKHIudmFsdWUudikudGhlbihmdWxmaWxsLCByZWplY3QpIDogc2V0dGxlKHFbMF1bMl0sIHIpOyB9XG4gIGZ1bmN0aW9uIGZ1bGZpbGwodmFsdWUpIHsgcmVzdW1lKFwibmV4dFwiLCB2YWx1ZSk7IH1cbiAgZnVuY3Rpb24gcmVqZWN0KHZhbHVlKSB7IHJlc3VtZShcInRocm93XCIsIHZhbHVlKTsgfVxuICBmdW5jdGlvbiBzZXR0bGUoZiwgdikgeyBpZiAoZih2KSwgcS5zaGlmdCgpLCBxLmxlbmd0aCkgcmVzdW1lKHFbMF1bMF0sIHFbMF1bMV0pOyB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jRGVsZWdhdG9yKG8pIHtcbiAgdmFyIGksIHA7XG4gIHJldHVybiBpID0ge30sIHZlcmIoXCJuZXh0XCIpLCB2ZXJiKFwidGhyb3dcIiwgZnVuY3Rpb24gKGUpIHsgdGhyb3cgZTsgfSksIHZlcmIoXCJyZXR1cm5cIiksIGlbU3ltYm9sLml0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGk7XG4gIGZ1bmN0aW9uIHZlcmIobiwgZikgeyBpW25dID0gb1tuXSA/IGZ1bmN0aW9uICh2KSB7IHJldHVybiAocCA9ICFwKSA/IHsgdmFsdWU6IF9fYXdhaXQob1tuXSh2KSksIGRvbmU6IGZhbHNlIH0gOiBmID8gZih2KSA6IHY7IH0gOiBmOyB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfX2FzeW5jVmFsdWVzKG8pIHtcbiAgaWYgKCFTeW1ib2wuYXN5bmNJdGVyYXRvcikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0l0ZXJhdG9yIGlzIG5vdCBkZWZpbmVkLlwiKTtcbiAgdmFyIG0gPSBvW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSwgaTtcbiAgcmV0dXJuIG0gPyBtLmNhbGwobykgOiAobyA9IHR5cGVvZiBfX3ZhbHVlcyA9PT0gXCJmdW5jdGlvblwiID8gX192YWx1ZXMobykgOiBvW1N5bWJvbC5pdGVyYXRvcl0oKSwgaSA9IHt9LCB2ZXJiKFwibmV4dFwiKSwgdmVyYihcInRocm93XCIpLCB2ZXJiKFwicmV0dXJuXCIpLCBpW1N5bWJvbC5hc3luY0l0ZXJhdG9yXSA9IGZ1bmN0aW9uICgpIHsgcmV0dXJuIHRoaXM7IH0sIGkpO1xuICBmdW5jdGlvbiB2ZXJiKG4pIHsgaVtuXSA9IG9bbl0gJiYgZnVuY3Rpb24gKHYpIHsgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHsgdiA9IG9bbl0odiksIHNldHRsZShyZXNvbHZlLCByZWplY3QsIHYuZG9uZSwgdi52YWx1ZSk7IH0pOyB9OyB9XG4gIGZ1bmN0aW9uIHNldHRsZShyZXNvbHZlLCByZWplY3QsIGQsIHYpIHsgUHJvbWlzZS5yZXNvbHZlKHYpLnRoZW4oZnVuY3Rpb24odikgeyByZXNvbHZlKHsgdmFsdWU6IHYsIGRvbmU6IGQgfSk7IH0sIHJlamVjdCk7IH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9fbWFrZVRlbXBsYXRlT2JqZWN0KGNvb2tlZCwgcmF3KSB7XG4gIGlmIChPYmplY3QuZGVmaW5lUHJvcGVydHkpIHsgT2JqZWN0LmRlZmluZVByb3BlcnR5KGNvb2tlZCwgXCJyYXdcIiwgeyB2YWx1ZTogcmF3IH0pOyB9IGVsc2UgeyBjb29rZWQucmF3ID0gcmF3OyB9XG4gIHJldHVybiBjb29rZWQ7XG59O1xuXG52YXIgX19zZXRNb2R1bGVEZWZhdWx0ID0gT2JqZWN0LmNyZWF0ZSA/IChmdW5jdGlvbihvLCB2KSB7XG4gIE9iamVjdC5kZWZpbmVQcm9wZXJ0eShvLCBcImRlZmF1bHRcIiwgeyBlbnVtZXJhYmxlOiB0cnVlLCB2YWx1ZTogdiB9KTtcbn0pIDogZnVuY3Rpb24obywgdikge1xuICBvW1wiZGVmYXVsdFwiXSA9IHY7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gX19pbXBvcnRTdGFyKG1vZCkge1xuICBpZiAobW9kICYmIG1vZC5fX2VzTW9kdWxlKSByZXR1cm4gbW9kO1xuICB2YXIgcmVzdWx0ID0ge307XG4gIGlmIChtb2QgIT0gbnVsbCkgZm9yICh2YXIgayBpbiBtb2QpIGlmIChrICE9PSBcImRlZmF1bHRcIiAmJiBPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwobW9kLCBrKSkgX19jcmVhdGVCaW5kaW5nKHJlc3VsdCwgbW9kLCBrKTtcbiAgX19zZXRNb2R1bGVEZWZhdWx0KHJlc3VsdCwgbW9kKTtcbiAgcmV0dXJuIHJlc3VsdDtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9faW1wb3J0RGVmYXVsdChtb2QpIHtcbiAgcmV0dXJuIChtb2QgJiYgbW9kLl9fZXNNb2R1bGUpID8gbW9kIDogeyBkZWZhdWx0OiBtb2QgfTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9fY2xhc3NQcml2YXRlRmllbGRHZXQocmVjZWl2ZXIsIHN0YXRlLCBraW5kLCBmKSB7XG4gIGlmIChraW5kID09PSBcImFcIiAmJiAhZikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlByaXZhdGUgYWNjZXNzb3Igd2FzIGRlZmluZWQgd2l0aG91dCBhIGdldHRlclwiKTtcbiAgaWYgKHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgIT09IHN0YXRlIHx8ICFmIDogIXN0YXRlLmhhcyhyZWNlaXZlcikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgcmVhZCBwcml2YXRlIG1lbWJlciBmcm9tIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gIHJldHVybiBraW5kID09PSBcIm1cIiA/IGYgOiBraW5kID09PSBcImFcIiA/IGYuY2FsbChyZWNlaXZlcikgOiBmID8gZi52YWx1ZSA6IHN0YXRlLmdldChyZWNlaXZlcik7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBfX2NsYXNzUHJpdmF0ZUZpZWxkU2V0KHJlY2VpdmVyLCBzdGF0ZSwgdmFsdWUsIGtpbmQsIGYpIHtcbiAgaWYgKGtpbmQgPT09IFwibVwiKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiUHJpdmF0ZSBtZXRob2QgaXMgbm90IHdyaXRhYmxlXCIpO1xuICBpZiAoa2luZCA9PT0gXCJhXCIgJiYgIWYpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJQcml2YXRlIGFjY2Vzc29yIHdhcyBkZWZpbmVkIHdpdGhvdXQgYSBzZXR0ZXJcIik7XG4gIGlmICh0eXBlb2Ygc3RhdGUgPT09IFwiZnVuY3Rpb25cIiA/IHJlY2VpdmVyICE9PSBzdGF0ZSB8fCAhZiA6ICFzdGF0ZS5oYXMocmVjZWl2ZXIpKSB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2Fubm90IHdyaXRlIHByaXZhdGUgbWVtYmVyIHRvIGFuIG9iamVjdCB3aG9zZSBjbGFzcyBkaWQgbm90IGRlY2xhcmUgaXRcIik7XG4gIHJldHVybiAoa2luZCA9PT0gXCJhXCIgPyBmLmNhbGwocmVjZWl2ZXIsIHZhbHVlKSA6IGYgPyBmLnZhbHVlID0gdmFsdWUgOiBzdGF0ZS5zZXQocmVjZWl2ZXIsIHZhbHVlKSksIHZhbHVlO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gX19jbGFzc1ByaXZhdGVGaWVsZEluKHN0YXRlLCByZWNlaXZlcikge1xuICBpZiAocmVjZWl2ZXIgPT09IG51bGwgfHwgKHR5cGVvZiByZWNlaXZlciAhPT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgcmVjZWl2ZXIgIT09IFwiZnVuY3Rpb25cIikpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5ub3QgdXNlICdpbicgb3BlcmF0b3Igb24gbm9uLW9iamVjdFwiKTtcbiAgcmV0dXJuIHR5cGVvZiBzdGF0ZSA9PT0gXCJmdW5jdGlvblwiID8gcmVjZWl2ZXIgPT09IHN0YXRlIDogc3RhdGUuaGFzKHJlY2VpdmVyKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIF9fYWRkRGlzcG9zYWJsZVJlc291cmNlKGVudiwgdmFsdWUsIGFzeW5jKSB7XG4gIGlmICh2YWx1ZSAhPT0gbnVsbCAmJiB2YWx1ZSAhPT0gdm9pZCAwKSB7XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gXCJvYmplY3RcIiAmJiB0eXBlb2YgdmFsdWUgIT09IFwiZnVuY3Rpb25cIikgdGhyb3cgbmV3IFR5cGVFcnJvcihcIk9iamVjdCBleHBlY3RlZC5cIik7XG4gICAgdmFyIGRpc3Bvc2U7XG4gICAgaWYgKGFzeW5jKSB7XG4gICAgICAgIGlmICghU3ltYm9sLmFzeW5jRGlzcG9zZSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5hc3luY0Rpc3Bvc2UgaXMgbm90IGRlZmluZWQuXCIpO1xuICAgICAgICBkaXNwb3NlID0gdmFsdWVbU3ltYm9sLmFzeW5jRGlzcG9zZV07XG4gICAgfVxuICAgIGlmIChkaXNwb3NlID09PSB2b2lkIDApIHtcbiAgICAgICAgaWYgKCFTeW1ib2wuZGlzcG9zZSkgdGhyb3cgbmV3IFR5cGVFcnJvcihcIlN5bWJvbC5kaXNwb3NlIGlzIG5vdCBkZWZpbmVkLlwiKTtcbiAgICAgICAgZGlzcG9zZSA9IHZhbHVlW1N5bWJvbC5kaXNwb3NlXTtcbiAgICB9XG4gICAgaWYgKHR5cGVvZiBkaXNwb3NlICE9PSBcImZ1bmN0aW9uXCIpIHRocm93IG5ldyBUeXBlRXJyb3IoXCJPYmplY3Qgbm90IGRpc3Bvc2FibGUuXCIpO1xuICAgIGVudi5zdGFjay5wdXNoKHsgdmFsdWU6IHZhbHVlLCBkaXNwb3NlOiBkaXNwb3NlLCBhc3luYzogYXN5bmMgfSk7XG4gIH1cbiAgZWxzZSBpZiAoYXN5bmMpIHtcbiAgICBlbnYuc3RhY2sucHVzaCh7IGFzeW5jOiB0cnVlIH0pO1xuICB9XG4gIHJldHVybiB2YWx1ZTtcbn1cblxudmFyIF9TdXBwcmVzc2VkRXJyb3IgPSB0eXBlb2YgU3VwcHJlc3NlZEVycm9yID09PSBcImZ1bmN0aW9uXCIgPyBTdXBwcmVzc2VkRXJyb3IgOiBmdW5jdGlvbiAoZXJyb3IsIHN1cHByZXNzZWQsIG1lc3NhZ2UpIHtcbiAgdmFyIGUgPSBuZXcgRXJyb3IobWVzc2FnZSk7XG4gIHJldHVybiBlLm5hbWUgPSBcIlN1cHByZXNzZWRFcnJvclwiLCBlLmVycm9yID0gZXJyb3IsIGUuc3VwcHJlc3NlZCA9IHN1cHByZXNzZWQsIGU7XG59O1xuXG5leHBvcnQgZnVuY3Rpb24gX19kaXNwb3NlUmVzb3VyY2VzKGVudikge1xuICBmdW5jdGlvbiBmYWlsKGUpIHtcbiAgICBlbnYuZXJyb3IgPSBlbnYuaGFzRXJyb3IgPyBuZXcgX1N1cHByZXNzZWRFcnJvcihlLCBlbnYuZXJyb3IsIFwiQW4gZXJyb3Igd2FzIHN1cHByZXNzZWQgZHVyaW5nIGRpc3Bvc2FsLlwiKSA6IGU7XG4gICAgZW52Lmhhc0Vycm9yID0gdHJ1ZTtcbiAgfVxuICBmdW5jdGlvbiBuZXh0KCkge1xuICAgIHdoaWxlIChlbnYuc3RhY2subGVuZ3RoKSB7XG4gICAgICB2YXIgcmVjID0gZW52LnN0YWNrLnBvcCgpO1xuICAgICAgdHJ5IHtcbiAgICAgICAgdmFyIHJlc3VsdCA9IHJlYy5kaXNwb3NlICYmIHJlYy5kaXNwb3NlLmNhbGwocmVjLnZhbHVlKTtcbiAgICAgICAgaWYgKHJlYy5hc3luYykgcmV0dXJuIFByb21pc2UucmVzb2x2ZShyZXN1bHQpLnRoZW4obmV4dCwgZnVuY3Rpb24oZSkgeyBmYWlsKGUpOyByZXR1cm4gbmV4dCgpOyB9KTtcbiAgICAgIH1cbiAgICAgIGNhdGNoIChlKSB7XG4gICAgICAgICAgZmFpbChlKTtcbiAgICAgIH1cbiAgICB9XG4gICAgaWYgKGVudi5oYXNFcnJvcikgdGhyb3cgZW52LmVycm9yO1xuICB9XG4gIHJldHVybiBuZXh0KCk7XG59XG5cbmV4cG9ydCBkZWZhdWx0IHtcbiAgX19leHRlbmRzLFxuICBfX2Fzc2lnbixcbiAgX19yZXN0LFxuICBfX2RlY29yYXRlLFxuICBfX3BhcmFtLFxuICBfX21ldGFkYXRhLFxuICBfX2F3YWl0ZXIsXG4gIF9fZ2VuZXJhdG9yLFxuICBfX2NyZWF0ZUJpbmRpbmcsXG4gIF9fZXhwb3J0U3RhcixcbiAgX192YWx1ZXMsXG4gIF9fcmVhZCxcbiAgX19zcHJlYWQsXG4gIF9fc3ByZWFkQXJyYXlzLFxuICBfX3NwcmVhZEFycmF5LFxuICBfX2F3YWl0LFxuICBfX2FzeW5jR2VuZXJhdG9yLFxuICBfX2FzeW5jRGVsZWdhdG9yLFxuICBfX2FzeW5jVmFsdWVzLFxuICBfX21ha2VUZW1wbGF0ZU9iamVjdCxcbiAgX19pbXBvcnRTdGFyLFxuICBfX2ltcG9ydERlZmF1bHQsXG4gIF9fY2xhc3NQcml2YXRlRmllbGRHZXQsXG4gIF9fY2xhc3NQcml2YXRlRmllbGRTZXQsXG4gIF9fY2xhc3NQcml2YXRlRmllbGRJbixcbiAgX19hZGREaXNwb3NhYmxlUmVzb3VyY2UsXG4gIF9fZGlzcG9zZVJlc291cmNlcyxcbn07XG4iLCIvLyBUaGUgbW9kdWxlIGNhY2hlXG52YXIgX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fID0ge307XG5cbi8vIFRoZSByZXF1aXJlIGZ1bmN0aW9uXG5mdW5jdGlvbiBfX3dlYnBhY2tfcmVxdWlyZV9fKG1vZHVsZUlkKSB7XG5cdC8vIENoZWNrIGlmIG1vZHVsZSBpcyBpbiBjYWNoZVxuXHR2YXIgY2FjaGVkTW9kdWxlID0gX193ZWJwYWNrX21vZHVsZV9jYWNoZV9fW21vZHVsZUlkXTtcblx0aWYgKGNhY2hlZE1vZHVsZSAhPT0gdW5kZWZpbmVkKSB7XG5cdFx0cmV0dXJuIGNhY2hlZE1vZHVsZS5leHBvcnRzO1xuXHR9XG5cdC8vIENyZWF0ZSBhIG5ldyBtb2R1bGUgKGFuZCBwdXQgaXQgaW50byB0aGUgY2FjaGUpXG5cdHZhciBtb2R1bGUgPSBfX3dlYnBhY2tfbW9kdWxlX2NhY2hlX19bbW9kdWxlSWRdID0ge1xuXHRcdC8vIG5vIG1vZHVsZS5pZCBuZWVkZWRcblx0XHQvLyBubyBtb2R1bGUubG9hZGVkIG5lZWRlZFxuXHRcdGV4cG9ydHM6IHt9XG5cdH07XG5cblx0Ly8gRXhlY3V0ZSB0aGUgbW9kdWxlIGZ1bmN0aW9uXG5cdF9fd2VicGFja19tb2R1bGVzX19bbW9kdWxlSWRdKG1vZHVsZSwgbW9kdWxlLmV4cG9ydHMsIF9fd2VicGFja19yZXF1aXJlX18pO1xuXG5cdC8vIFJldHVybiB0aGUgZXhwb3J0cyBvZiB0aGUgbW9kdWxlXG5cdHJldHVybiBtb2R1bGUuZXhwb3J0cztcbn1cblxuIiwiLy8gZ2V0RGVmYXVsdEV4cG9ydCBmdW5jdGlvbiBmb3IgY29tcGF0aWJpbGl0eSB3aXRoIG5vbi1oYXJtb255IG1vZHVsZXNcbl9fd2VicGFja19yZXF1aXJlX18ubiA9IChtb2R1bGUpID0+IHtcblx0dmFyIGdldHRlciA9IG1vZHVsZSAmJiBtb2R1bGUuX19lc01vZHVsZSA/XG5cdFx0KCkgPT4gKG1vZHVsZVsnZGVmYXVsdCddKSA6XG5cdFx0KCkgPT4gKG1vZHVsZSk7XG5cdF9fd2VicGFja19yZXF1aXJlX18uZChnZXR0ZXIsIHsgYTogZ2V0dGVyIH0pO1xuXHRyZXR1cm4gZ2V0dGVyO1xufTsiLCIvLyBkZWZpbmUgZ2V0dGVyIGZ1bmN0aW9ucyBmb3IgaGFybW9ueSBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLmQgPSAoZXhwb3J0cywgZGVmaW5pdGlvbikgPT4ge1xuXHRmb3IodmFyIGtleSBpbiBkZWZpbml0aW9uKSB7XG5cdFx0aWYoX193ZWJwYWNrX3JlcXVpcmVfXy5vKGRlZmluaXRpb24sIGtleSkgJiYgIV9fd2VicGFja19yZXF1aXJlX18ubyhleHBvcnRzLCBrZXkpKSB7XG5cdFx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywga2V5LCB7IGVudW1lcmFibGU6IHRydWUsIGdldDogZGVmaW5pdGlvbltrZXldIH0pO1xuXHRcdH1cblx0fVxufTsiLCJfX3dlYnBhY2tfcmVxdWlyZV9fLmcgPSAoZnVuY3Rpb24oKSB7XG5cdGlmICh0eXBlb2YgZ2xvYmFsVGhpcyA9PT0gJ29iamVjdCcpIHJldHVybiBnbG9iYWxUaGlzO1xuXHR0cnkge1xuXHRcdHJldHVybiB0aGlzIHx8IG5ldyBGdW5jdGlvbigncmV0dXJuIHRoaXMnKSgpO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0aWYgKHR5cGVvZiB3aW5kb3cgPT09ICdvYmplY3QnKSByZXR1cm4gd2luZG93O1xuXHR9XG59KSgpOyIsIl9fd2VicGFja19yZXF1aXJlX18ubyA9IChvYmosIHByb3ApID0+IChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwob2JqLCBwcm9wKSkiLCIvLyBkZWZpbmUgX19lc01vZHVsZSBvbiBleHBvcnRzXG5fX3dlYnBhY2tfcmVxdWlyZV9fLnIgPSAoZXhwb3J0cykgPT4ge1xuXHRpZih0eXBlb2YgU3ltYm9sICE9PSAndW5kZWZpbmVkJyAmJiBTeW1ib2wudG9TdHJpbmdUYWcpIHtcblx0XHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgU3ltYm9sLnRvU3RyaW5nVGFnLCB7IHZhbHVlOiAnTW9kdWxlJyB9KTtcblx0fVxuXHRPYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgJ19fZXNNb2R1bGUnLCB7IHZhbHVlOiB0cnVlIH0pO1xufTsiLCJpbXBvcnQgKiBhcyBsb2FkZXJzIGZyb20gXCJAbHRzL2xvYWRlcnMvbGVnYWN5L2xlZ2FjeVwiO1xyXG5leHBvcnQgeyBsb2FkZXJzIH07XHJcbmV4cG9ydCBkZWZhdWx0IGxvYWRlcnM7XHJcbiJdLCJuYW1lcyI6W10sInNvdXJjZVJvb3QiOiIifQ==