(function webpackUniversalModuleDefinition(root, factory) { if(typeof exports === 'object' && typeof module === 'object') module.exports = factory(); else if(typeof define === 'function' && define.amd) define([], factory); else if(typeof exports === 'object') exports["AutoNumeric"] = factory(); else root["AutoNumeric"] = factory(); })(window, function() { return /******/ (function(modules) { // webpackBootstrap /******/ // The module cache /******/ var installedModules = {}; /******/ /******/ // The require function /******/ function __webpack_require__(moduleId) { /******/ /******/ // Check if module is in cache /******/ if(installedModules[moduleId]) { /******/ return installedModules[moduleId].exports; /******/ } /******/ // Create a new module (and put it into the cache) /******/ var module = installedModules[moduleId] = { /******/ i: moduleId, /******/ l: false, /******/ exports: {} /******/ }; /******/ /******/ // Execute the module function /******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); /******/ /******/ // Flag the module as loaded /******/ module.l = true; /******/ /******/ // Return the exports of the module /******/ return module.exports; /******/ } /******/ /******/ /******/ // expose the modules object (__webpack_modules__) /******/ __webpack_require__.m = modules; /******/ /******/ // expose the module cache /******/ __webpack_require__.c = installedModules; /******/ /******/ // define getter function for harmony exports /******/ __webpack_require__.d = function(exports, name, getter) { /******/ if(!__webpack_require__.o(exports, name)) { /******/ Object.defineProperty(exports, name, { /******/ configurable: false, /******/ enumerable: true, /******/ get: getter /******/ }); /******/ } /******/ }; /******/ /******/ // define __esModule on exports /******/ __webpack_require__.r = function(exports) { /******/ Object.defineProperty(exports, '__esModule', { value: true }); /******/ }; /******/ /******/ // getDefaultExport function for compatibility with non-harmony modules /******/ __webpack_require__.n = function(module) { /******/ var getter = module && module.__esModule ? /******/ function getDefault() { return module['default']; } : /******/ function getModuleExports() { return module; }; /******/ __webpack_require__.d(getter, 'a', getter); /******/ return getter; /******/ }; /******/ /******/ // Object.prototype.hasOwnProperty.call /******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; /******/ /******/ // __webpack_public_path__ /******/ __webpack_require__.p = ""; /******/ /******/ /******/ // Load entry module and return exports /******/ return __webpack_require__(__webpack_require__.s = "./src/main.js"); /******/ }) /************************************************************************/ /******/ ({ /***/ "./src/AutoNumeric.js": /*!****************************!*\ !*** ./src/AutoNumeric.js ***! \****************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n\nvar _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**\n * AutoNumeric.js\n *\n * @version 4.2.9\n * @date 2018-03-26 UTC 19:10\n *\n * @authors Bob Knothe, Alexandre Bonneau\n * @contributors Sokolov Yura and others, cf. AUTHORS\n * @copyright 2009 Robert J. Knothe\n * @since 2009-08-09\n *\n * @summary autoNumeric is a standalone Javascript library\n * that provides live *as-you-type* formatting for\n * international numbers and currencies.\n *\n * @link http://autonumeric.org\n *\n * Note : Some functions are borrowed from big.js\n * @see https://github.com/MikeMcl/big.js/\n *\n * Please report any bugs to https://github.com/autoNumeric/autoNumeric\n *\n * @license Released under the MIT License\n * @link http://www.opensource.org/licenses/mit-license.php\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sub license, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n//TODO Prevent having to enter relative path in the js files (ie. using `./AutoNumericHelper` instead of just `AutoNumericHelper`) (cf. http://moduscreate.com/es6-es2015-import-no-relative-path-webpack/)\n\n\nvar _AutoNumericHelper = __webpack_require__(/*! ./AutoNumericHelper */ \"./src/AutoNumericHelper.js\");\n\nvar _AutoNumericHelper2 = _interopRequireDefault(_AutoNumericHelper);\n\nvar _AutoNumericEnum = __webpack_require__(/*! ./AutoNumericEnum */ \"./src/AutoNumericEnum.js\");\n\nvar _AutoNumericEnum2 = _interopRequireDefault(_AutoNumericEnum);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n/**\n * Class declaration for the AutoNumeric object.\n *\n * An AutoNumeric element is an object wrapper that keeps a reference to the DOM element it manages (usually an one), and provides autoNumeric-specific variables and functions.\n */\nvar AutoNumeric = function () {\n /**\n * Initialize the AutoNumeric object onto the given DOM element, and attach the settings and related event listeners to it.\n * The options passed as a parameter is an object that contains the settings (ie. {digitGroupSeparator: \".\", decimalCharacter: \",\", currencySymbol: '€ '})\n *\n * @example\n * anElement = new AutoNumeric(domElement); // With the default options\n * anElement = new AutoNumeric(domElement, { options }); // With one option object\n * anElement = new AutoNumeric(domElement, 'euroPos'); // With a named pre-defined string\n * anElement = new AutoNumeric(domElement, [{ options1 }, 'euroPos', { options2 }]); // With multiple option objects (the latest option overwriting the previous ones)\n * anElement = new AutoNumeric(domElement, null, { options }); // With one option object, and a failed initial value\n * anElement = new AutoNumeric(domElement).french(); // With one pre-defined language object\n * anElement = new AutoNumeric(domElement).french({ options });// With one pre-defined language object and additional options that will override the defaults\n *\n * // ...or init and set the value in one call :\n * anElement = new AutoNumeric(domElement, 12345.789); // With the default options, and an initial value\n * anElement = new AutoNumeric(domElement, 12345.789, { options });\n * anElement = new AutoNumeric(domElement, '12345.789', { options });\n * anElement = new AutoNumeric(domElement, 12345.789, 'euroPos');\n * anElement = new AutoNumeric(domElement, 12345.789, [{ options1 }, 'euroPos', { options2 }]);\n * anElement = new AutoNumeric(domElement, 12345.789).french({ options });\n * anElement = new AutoNumeric(domElement, 12345.789, { options }).french({ options }); // Not really helpful, but possible\n *\n * // The AutoNumeric constructor class can also accept a string as a css selector. Under the hood this use `QuerySelector` and limit itself to only the first element it finds.\n * anElement = new AutoNumeric('.myCssClass > input');\n * anElement = new AutoNumeric('.myCssClass > input', { options });\n * anElement = new AutoNumeric('.myCssClass > input', 'euroPos');\n * anElement = new AutoNumeric('.myCssClass > input', [{ options1 }, 'euroPos', { options2 }]);\n * anElement = new AutoNumeric('.myCssClass > input', 12345.789);\n * anElement = new AutoNumeric('.myCssClass > input', 12345.789, { options });\n * anElement = new AutoNumeric('.myCssClass > input', 12345.789, 'euroPos');\n * anElement = new AutoNumeric('.myCssClass > input', 12345.789, [{ options1 }, 'euroPos', { options2 }]);\n * anElement = new AutoNumeric('.myCssClass > input', null, { options }); // With a failed initial value\n * anElement = new AutoNumeric('.myCssClass > input', 12345.789).french({ options });\n *\n * @param {object|Array|number|string} arg1\n * @param {object|Array|number|string|null} arg2\n * @param {object|Array|number|string|null} arg3\n * @throws\n */\n function AutoNumeric() {\n var arg1 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n var _this = this;\n\n var arg2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n var arg3 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n _classCallCheck(this, AutoNumeric);\n\n // --------------------------------------------------------\n // -------------- Initialization\n // Initialize the arguments\n var _AutoNumeric$_setArgu = AutoNumeric._setArgumentsValues(arg1, arg2, arg3),\n domElement = _AutoNumeric$_setArgu.domElement,\n initialValue = _AutoNumeric$_setArgu.initialValue,\n userOptions = _AutoNumeric$_setArgu.userOptions;\n\n // Initialize the element\n\n\n this.domElement = domElement;\n\n // Generate the settings\n this.defaultRawValue = ''; // The default raw value to set when initializing an AutoNumeric object\n this._setSettings(userOptions, false);\n //TODO If `styleRules` is not null, add by default a class 'autoNumeric' that adds transition to color, background-color, border-color properties\n // Check if the DOM element is supported\n this._checkElement();\n\n // Store the additional attributes inside the AutoNumeric object\n // Note: This variable is needed and not a duplicate of `initialValueOnKeydown` nor `valueOnFocus` since it serves a different purpose and has a different lifecycle\n this.savedCancellableValue = null;\n\n // Initialize the undo/redo variables\n this.historyTable = []; // Keep track of *all* valid states of the element value\n this.historyTableIndex = -1; // Pointer to the current undo/redo state. This will be set to '0' during initialization since it first adds itself.\n this.onGoingRedo = false; // Variable that keeps track if a 'redo' is ongoing (in order to prevent an 'undo' to be launch when releasing the shift key before the ctrl key after a 'redo' shortcut)\n\n // Initialize the parent form element, if any\n this.parentForm = this._getParentForm();\n\n // Set the initial value if it exists and if the `formatOnPageLoad` option will allow it\n if (!this.runOnce && this.settings.formatOnPageLoad) {\n // Format the element value if needed\n this._formatDefaultValueOnPageLoad(initialValue);\n } else {\n // Otherwise set the `rawValue` and the element value, but do not format the latter yet\n var valueToSet = void 0;\n if (_AutoNumericHelper2.default.isNull(initialValue)) {\n switch (this.settings.emptyInputBehavior) {\n case AutoNumeric.options.emptyInputBehavior.zero:\n valueToSet = '0';\n break;\n // In order to stay consistent when `formatOnPageLoad` is set to `true`, it's still impossible so set the `null` value as the initial value\n case AutoNumeric.options.emptyInputBehavior.null:\n default:\n valueToSet = '';\n }\n } else {\n valueToSet = initialValue;\n }\n\n this._setElementAndRawValue(valueToSet);\n }\n\n this.runOnce = true;\n\n // Add the events listeners only on input elements\n if (this.isInputElement || this.isContentEditable) {\n if (!this.settings.noEventListeners) {\n //XXX Here we make sure the global list is created after creating the event listeners, to only create the event listeners on `document` once\n this._createEventListeners();\n }\n\n this._setReadOnly();\n }\n\n // Save the initial values (html attribute + element.value) for the pristine test\n this._saveInitialValues(initialValue);\n\n // Setup the data for the persistent storage solution (ie. sessionStorage or cookies)\n this.sessionStorageAvailable = this.constructor._storageTest();\n this.storageNamePrefix = 'AUTO_'; // The prefix for the raw value storage name variable can be modified here\n this._setPersistentStorageName();\n\n // --------------------------------------------------------\n // -------------- Tracking\n // Keep track if the element is currently focused\n this.isFocused = false;\n // Keep track if a mouse wheel event is currently ongoing\n this.isWheelEvent = false;\n // Keep track if a drop event is currently ongoing\n this.isDropEvent = false;\n // Keep track if the user is currently editing the element\n this.isEditing = false;\n // Keep track of the rawValue (needed to define if a change event must be sent on blur or enter key)\n this.rawValueOnFocus = void 0;\n // Watch any external changes to the element value/textContent/nodeValue and `set()` the new value so that it gets formatted/saved in the history\n this.internalModification = false; // This is temporarily set to `true` only when the AutoNumeric object does update the element value\n this.attributeToWatch = this._getAttributeToWatch();\n this.getterSetter = Object.getOwnPropertyDescriptor(this.domElement.__proto__, this.attributeToWatch);\n this._addWatcher();\n\n if (this.settings.createLocalList) {\n // Keep track of every AutoNumeric elements that this object initialized\n this._createLocalList();\n }\n\n // Keep track of all AutoNumeric elements in the current web page\n this.constructor._addToGlobalList(this);\n\n // --------------------------------------------------------\n // -------------- Methods\n // Create the global functions\n this.global = {\n /**\n * Set the same given element value for each elements in the local AutoNumeric element list, and format those elements immediately\n *\n * @param {number|string} newValue The value must be a number or a numeric string\n * @param {object} options A settings object that will override the current settings. Note: the update is done only if the `newValue` is defined.\n */\n set: function set(newValue) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n _this.autoNumericLocalList.forEach(function (aNObject) {\n aNObject.set(newValue, options);\n });\n },\n\n /**\n * Set the value given value directly as the DOM element value, without formatting it beforehand.\n * This sets the same unformatted value for each elements in the local AutoNumeric element list.\n *\n * @param {number|string} value\n * @param {object} options\n */\n setUnformatted: function setUnformatted(value) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n _this.autoNumericLocalList.forEach(function (aNObject) {\n aNObject.setUnformatted(value, options);\n });\n },\n\n /**\n * This is an alias of the `getNumericString()` function, and should not be used anymore.\n *\n * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n * @returns {Array}\n * @deprecated\n */\n get: function get() {\n var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n var result = [];\n _this.autoNumericLocalList.forEach(function (aNObject) {\n result.push(aNObject.get());\n });\n _this._executeCallback(result, callback);\n\n return result;\n },\n\n /**\n * Return an array of the unformatted values (as a string) of each AutoNumeric element of the local AutoNumeric element list\n *\n * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n * @returns {Array}\n */\n getNumericString: function getNumericString() {\n var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n var result = [];\n _this.autoNumericLocalList.forEach(function (aNObject) {\n result.push(aNObject.getNumericString());\n });\n _this._executeCallback(result, callback);\n\n return result;\n },\n\n /**\n * Return an array of the current formatted values (as a string) of each AutoNumeric element of the local AutoNumeric element list\n *\n * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n * @returns {Array}\n */\n getFormatted: function getFormatted() {\n var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n var result = [];\n _this.autoNumericLocalList.forEach(function (aNObject) {\n result.push(aNObject.getFormatted());\n });\n _this._executeCallback(result, callback);\n\n return result;\n },\n\n /**\n * Return an array of the element unformatted values (as a real Javascript number), for each element of the local AutoNumeric element list\n *\n * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n * @returns {Array}\n */\n getNumber: function getNumber() {\n var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n var result = [];\n _this.autoNumericLocalList.forEach(function (aNObject) {\n result.push(aNObject.getNumber());\n });\n _this._executeCallback(result, callback);\n\n return result;\n },\n\n /**\n * Returns the unformatted values (following the `outputFormat` setting) of each element of the local AutoNumeric element list into an array\n *\n * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n * @returns {Array}\n */\n getLocalized: function getLocalized() {\n var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n var result = [];\n _this.autoNumericLocalList.forEach(function (aNObject) {\n result.push(aNObject.getLocalized());\n });\n _this._executeCallback(result, callback);\n\n return result;\n },\n\n /**\n * Force each element of the local AutoNumeric element list to reformat its value\n */\n reformat: function reformat() {\n _this.autoNumericLocalList.forEach(function (aNObject) {\n aNObject.reformat();\n });\n },\n\n /**\n * Remove the formatting and keep only the raw unformatted value (as a numericString) in each elements of the local AutoNumeric element list\n */\n unformat: function unformat() {\n _this.autoNumericLocalList.forEach(function (aNObject) {\n aNObject.unformat();\n });\n },\n\n /**\n * Remove the formatting and keep only the localized unformatted value in the element, with the option to override the default outputFormat if needed\n *\n * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n */\n unformatLocalized: function unformatLocalized() {\n var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n _this.autoNumericLocalList.forEach(function (aNObject) {\n aNObject.unformatLocalized(forcedOutputFormat);\n });\n },\n\n /**\n * Updates the AutoNumeric settings, and immediately format the elements accordingly, for each elements of the local AutoNumeric element list\n *\n * @param {object} newOptions This can be either one or more option objects\n */\n update: function update() {\n for (var _len = arguments.length, newOptions = Array(_len), _key = 0; _key < _len; _key++) {\n newOptions[_key] = arguments[_key];\n }\n\n _this.autoNumericLocalList.forEach(function (aNObject) {\n aNObject.update.apply(aNObject, newOptions);\n });\n },\n\n /**\n * Return `true` if *all* the autoNumeric-managed elements are pristine, if their raw value hasn't changed.\n * By default, this returns `true` if the raw unformatted value is still the same even if the formatted one has changed (due to a configuration update for instance).\n *\n * @param {boolean} checkOnlyRawValue If set to `true`, the pristine value is done on the raw unformatted value, not the formatted one. If set to `false`, this also checks that the formatted value hasn't changed.\n * @returns {boolean}\n */\n isPristine: function isPristine() {\n var checkOnlyRawValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n\n var isPristine = true;\n _this.autoNumericLocalList.forEach(function (aNObject) {\n if (isPristine && !aNObject.isPristine(checkOnlyRawValue)) {\n isPristine = false;\n }\n });\n\n return isPristine;\n },\n\n /**\n * Execute the `clear()` method on each AutoNumeric object in the local AutoNumeric element list\n *\n * @param {boolean} forceClearAll\n */\n clear: function clear() {\n var forceClearAll = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n\n _this.autoNumericLocalList.forEach(function (aNObject) {\n aNObject.clear(forceClearAll);\n });\n },\n\n /**\n * Execute the `remove()` method on each AutoNumeric object in the local AutoNumeric element list\n */\n remove: function remove() {\n _this.autoNumericLocalList.forEach(function (aNObject) {\n aNObject.remove();\n });\n },\n\n /**\n * Execute the `wipe()` method on each AutoNumeric object in the local AutoNumeric element list\n */\n wipe: function wipe() {\n _this.autoNumericLocalList.forEach(function (aNObject) {\n aNObject.wipe();\n });\n },\n\n /**\n * Execute the `nuke()` method on each AutoNumeric object in the local AutoNumeric element list\n */\n nuke: function nuke() {\n _this.autoNumericLocalList.forEach(function (aNObject) {\n aNObject.nuke();\n });\n },\n\n /**\n * Return `true` if the given AutoNumeric object (or DOM element) is in the local AutoNumeric element list\n *\n * @param {HTMLElement|HTMLInputElement|AutoNumeric} domElementOrAutoNumericObject\n * @returns {*}\n */\n has: function has(domElementOrAutoNumericObject) {\n var result = void 0;\n if (domElementOrAutoNumericObject instanceof AutoNumeric) {\n result = _this.autoNumericLocalList.has(domElementOrAutoNumericObject.node());\n } else {\n result = _this.autoNumericLocalList.has(domElementOrAutoNumericObject);\n }\n\n return result;\n },\n\n /**\n * Add an existing AutoNumeric object (or DOM element) to the local AutoNumeric element list, using the DOM element as the key.\n * This manages the case where `addObject` is used on an AutoNumeric object that already has multiple elements in its local list.\n *\n * @param {HTMLElement|HTMLInputElement|AutoNumeric} domElementOrAutoNumericObject\n */\n addObject: function addObject(domElementOrAutoNumericObject) {\n // Start with the same data, whatever the user passed as arguments\n var domElement = void 0;\n var otherAutoNumericObject = void 0;\n if (domElementOrAutoNumericObject instanceof AutoNumeric) {\n domElement = domElementOrAutoNumericObject.node();\n otherAutoNumericObject = domElementOrAutoNumericObject;\n } else {\n domElement = domElementOrAutoNumericObject;\n otherAutoNumericObject = AutoNumeric.getAutoNumericElement(domElement);\n }\n\n // Check if the current autoNumeric object has a local list\n if (!_this._hasLocalList()) {\n _this._createLocalList();\n }\n\n // Check if the other autoNumeric object has a local list...\n var otherANLocalList = otherAutoNumericObject._getLocalList();\n if (otherANLocalList.size === 0) {\n // Special case if the other AutoNumeric object has an empty local list, then populate itself to it\n otherAutoNumericObject._createLocalList();\n otherANLocalList = otherAutoNumericObject._getLocalList(); // Update the other local list\n }\n\n var mergedLocalLists = void 0;\n if (otherANLocalList instanceof Map) {\n // ...If it does, merge the local lists together\n mergedLocalLists = _AutoNumericHelper2.default.mergeMaps(_this._getLocalList(), otherANLocalList);\n } else {\n // ...If not, just set the current local list onto the other AutoNumeric object\n // We need to specify the AutoNumeric object, otherwise the `_addToLocalList` function would not correctly add the AutoNumeric object since we would not have a reference to it, but a reference to the current AutoNumeric object on which is called this method.\n _this._addToLocalList(domElement, otherAutoNumericObject);\n mergedLocalLists = _this._getLocalList();\n }\n\n // Update the resulting list, on all the objects of that local list (so that we can indifferently use `init()` on any object belonging to that list)\n mergedLocalLists.forEach(function (aNObject) {\n aNObject._setLocalList(mergedLocalLists);\n });\n },\n\n /**\n * Remove the given AutoNumeric object (or DOM element) from the local AutoNumeric element list, using the DOM element as the key.\n * If this function attempts to remove the current AutoNumeric object from the local list, a warning is shown, but the deletion is still done.\n *\n * Special cases :\n * - If the current object removes itself, then it's removed from the shared local list, then a new empty local list is used/created\n * - If another object remove this object, then a local list with only this object is used/created\n *\n * @param {HTMLElement|HTMLInputElement|AutoNumeric} domElementOrAutoNumericObject\n * @param {boolean} keepCurrentANObject If set to `false`, then the function will also remove the current AutoNumeric object if asked, otherwise it will ignore it and print a warning message\n */\n removeObject: function removeObject(domElementOrAutoNumericObject) {\n var keepCurrentANObject = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n // Start with the same data, whatever the user passed as arguments\n var domElement = void 0;\n var otherAutoNumericObject = void 0;\n if (domElementOrAutoNumericObject instanceof AutoNumeric) {\n domElement = domElementOrAutoNumericObject.node();\n otherAutoNumericObject = domElementOrAutoNumericObject;\n } else {\n domElement = domElementOrAutoNumericObject;\n otherAutoNumericObject = AutoNumeric.getAutoNumericElement(domElement);\n }\n\n // Remove the other object from the local list\n var initialCompleteLocalList = _this.autoNumericLocalList;\n _this.autoNumericLocalList.delete(domElement);\n\n // Update the local list for all objects in it\n initialCompleteLocalList.forEach(function (aNObject) {\n aNObject._setLocalList(_this.autoNumericLocalList);\n });\n\n if (!keepCurrentANObject && domElement === _this.node()) {\n // This object is removed by itself\n // Empty the object local list\n otherAutoNumericObject._setLocalList(new Map());\n } else {\n // This object is removed by another object\n // Set the local list for the removed object, with only this object in it\n otherAutoNumericObject._createLocalList();\n }\n },\n\n /**\n * Remove all elements from the shared list, effectively emptying it.\n * This is the equivalent of calling `detach()` on each of its elements.\n *\n * @param {boolean} keepEachANObjectInItsOwnList If set to `true`, then instead of completely emptying the local list of each AutoNumeric objects, each one of those keeps itself in its own local list\n */\n empty: function empty() {\n var keepEachANObjectInItsOwnList = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n\n var initialCompleteLocalList = _this.autoNumericLocalList;\n\n // Update the local list for all objects in it\n initialCompleteLocalList.forEach(function (aNObject) {\n if (keepEachANObjectInItsOwnList) {\n aNObject._createLocalList();\n } else {\n aNObject._setLocalList(new Map());\n }\n });\n },\n\n /**\n * Return an array containing all the AutoNumeric DOM elements that have been initialized by each other\n *\n * @returns {Array}\n */\n elements: function elements() {\n var result = [];\n _this.autoNumericLocalList.forEach(function (aNObject) {\n result.push(aNObject.node());\n });\n\n return result;\n },\n\n /**\n * Return the `Map` object directly\n * @returns {Map}\n */\n getList: function getList() {\n return _this.autoNumericLocalList;\n },\n\n /**\n * Return the number of element in the local AutoNumeric element list\n * @returns {number}\n */\n size: function size() {\n return _this.autoNumericLocalList.size;\n }\n };\n\n // Create the functions that will allow to change each setting one by one\n /**\n * For each options, we define if we need to reformat the element content (does changing the options should change the way its value is displayed?).\n * If yes, then we use the `update()` for force a reformat, otherwise, we just update the `settings` object.\n */\n this.options = {\n /**\n * Reset any options set previously, by overwriting them with the default settings\n *\n * @returns {AutoNumeric}\n */\n reset: function reset() {\n //TODO Add a `settings` parameter so that the user can reset to a specific set of settings. This is different than update since it drops any non-default settings before using those new settings.\n _this.settings = { rawValue: _this.defaultRawValue }; // Here we pass the default rawValue in order to prevent showing a warning that we try to set an `undefined` value\n _this.update(AutoNumeric.defaultSettings);\n\n return _this;\n },\n allowDecimalPadding: function allowDecimalPadding(_allowDecimalPadding) {\n _this.update({ allowDecimalPadding: _allowDecimalPadding });\n\n return _this;\n },\n caretPositionOnFocus: function caretPositionOnFocus(_caretPositionOnFocus) {\n //FIXME test this\n _this.settings.caretPositionOnFocus = _caretPositionOnFocus;\n\n return _this;\n },\n createLocalList: function createLocalList(_createLocalList2) {\n _this.settings.createLocalList = _createLocalList2;\n\n // Delete the local list when this is set to `false`, create it if this is set to `true` and there is not pre-existing list\n if (_this.settings.createLocalList) {\n if (!_this._hasLocalList()) {\n _this._createLocalList();\n }\n } else {\n _this._deleteLocalList();\n }\n\n return _this;\n },\n currencySymbol: function currencySymbol(_currencySymbol) {\n _this.update({ currencySymbol: _currencySymbol });\n\n return _this;\n },\n currencySymbolPlacement: function currencySymbolPlacement(_currencySymbolPlacement) {\n _this.update({ currencySymbolPlacement: _currencySymbolPlacement });\n\n return _this;\n },\n decimalCharacter: function decimalCharacter(_decimalCharacter) {\n _this.update({ decimalCharacter: _decimalCharacter });\n\n return _this;\n },\n decimalCharacterAlternative: function decimalCharacterAlternative(_decimalCharacterAlternative) {\n _this.settings.decimalCharacterAlternative = _decimalCharacterAlternative;\n\n return _this;\n },\n /**\n * Update the decimal places globally, which means this override any previously set number of decimal shown on focus, on blur, or in the raw value.\n *\n * @param {int} decimalPlaces\n * @returns {AutoNumeric}\n */\n decimalPlaces: function decimalPlaces(_decimalPlaces) {\n _AutoNumericHelper2.default.warning('Using `options.decimalPlaces()` instead of calling the specific `options.decimalPlacesRawValue()`, `options.decimalPlacesShownOnFocus()` and `options.decimalPlacesShownOnBlur()` methods will reset those options.\\nPlease call the specific methods if you do not want to reset those.', _this.settings.showWarnings);\n _this.update({ decimalPlaces: _decimalPlaces });\n\n return _this;\n },\n decimalPlacesRawValue: function decimalPlacesRawValue(_decimalPlacesRawValue) {\n //FIXME test this\n _this.update({ decimalPlacesRawValue: _decimalPlacesRawValue });\n\n return _this;\n },\n decimalPlacesShownOnBlur: function decimalPlacesShownOnBlur(_decimalPlacesShownOnBlur) {\n _this.update({ decimalPlacesShownOnBlur: _decimalPlacesShownOnBlur });\n\n return _this;\n },\n decimalPlacesShownOnFocus: function decimalPlacesShownOnFocus(_decimalPlacesShownOnFocus) {\n _this.update({ decimalPlacesShownOnFocus: _decimalPlacesShownOnFocus });\n\n return _this;\n },\n defaultValueOverride: function defaultValueOverride(_defaultValueOverride) {\n _this.update({ defaultValueOverride: _defaultValueOverride });\n\n return _this;\n },\n digitalGroupSpacing: function digitalGroupSpacing(_digitalGroupSpacing) {\n _this.update({ digitalGroupSpacing: _digitalGroupSpacing });\n\n return _this;\n },\n digitGroupSeparator: function digitGroupSeparator(_digitGroupSeparator) {\n _this.update({ digitGroupSeparator: _digitGroupSeparator });\n\n return _this;\n },\n divisorWhenUnfocused: function divisorWhenUnfocused(_divisorWhenUnfocused) {\n _this.update({ divisorWhenUnfocused: _divisorWhenUnfocused });\n\n return _this;\n },\n emptyInputBehavior: function emptyInputBehavior(_emptyInputBehavior) {\n if (_this.rawValue === null && _emptyInputBehavior !== AutoNumeric.options.emptyInputBehavior.null) {\n // Special case : if the current `rawValue` is `null` and the `emptyInputBehavior` is changed to something else than `'null'`, then it makes that `rawValue` invalid.\n // Here we can either prevent the option update and throw an error, or still accept the option update and update the value from `null` to `''`.\n // We cannot keep `rawValue` to `null` since if `emptyInputBehavior` is not set to `null`, lots of function assume `rawValue` is a string.\n _AutoNumericHelper2.default.warning('You are trying to modify the `emptyInputBehavior` option to something different than `\\'null\\'` (' + _emptyInputBehavior + '), but the element raw value is currently set to `null`. This would result in an invalid `rawValue`. In order to fix that, the element value has been changed to the empty string `\\'\\'`.', _this.settings.showWarnings);\n _this.rawValue = '';\n }\n\n _this.update({ emptyInputBehavior: _emptyInputBehavior });\n\n return _this;\n },\n eventBubbles: function eventBubbles(_eventBubbles) {\n _this.settings.eventBubbles = _eventBubbles;\n\n return _this;\n },\n eventIsCancelable: function eventIsCancelable(_eventIsCancelable) {\n _this.settings.eventIsCancelable = _eventIsCancelable;\n\n return _this;\n },\n failOnUnknownOption: function failOnUnknownOption(_failOnUnknownOption) {\n _this.settings.failOnUnknownOption = _failOnUnknownOption; //FIXME test this\n\n return _this;\n },\n formatOnPageLoad: function formatOnPageLoad(_formatOnPageLoad) {\n _this.settings.formatOnPageLoad = _formatOnPageLoad; //FIXME test this\n\n return _this;\n },\n historySize: function historySize(_historySize) {\n _this.settings.historySize = _historySize;\n\n return _this;\n },\n isCancellable: function isCancellable(_isCancellable) {\n _this.settings.isCancellable = _isCancellable; //FIXME test this\n\n return _this;\n },\n leadingZero: function leadingZero(_leadingZero) {\n _this.update({ leadingZero: _leadingZero });\n\n return _this;\n },\n maximumValue: function maximumValue(_maximumValue) {\n _this.update({ maximumValue: _maximumValue });\n\n return _this;\n },\n minimumValue: function minimumValue(_minimumValue) {\n _this.update({ minimumValue: _minimumValue });\n\n return _this;\n },\n modifyValueOnWheel: function modifyValueOnWheel(_modifyValueOnWheel) {\n _this.settings.modifyValueOnWheel = _modifyValueOnWheel; //FIXME test this\n\n return _this;\n },\n negativeBracketsTypeOnBlur: function negativeBracketsTypeOnBlur(_negativeBracketsTypeOnBlur) {\n _this.update({ negativeBracketsTypeOnBlur: _negativeBracketsTypeOnBlur });\n\n return _this;\n },\n negativePositiveSignPlacement: function negativePositiveSignPlacement(_negativePositiveSignPlacement) {\n _this.update({ negativePositiveSignPlacement: _negativePositiveSignPlacement });\n\n return _this;\n },\n negativeSignCharacter: function negativeSignCharacter(_negativeSignCharacter) {\n _this.update({ negativeSignCharacter: _negativeSignCharacter });\n\n return _this;\n },\n noEventListeners: function noEventListeners(_noEventListeners) {\n //FIXME test this\n if (_noEventListeners === AutoNumeric.options.noEventListeners.noEvents && _this.settings.noEventListeners === AutoNumeric.options.noEventListeners.addEvents) {\n // Remove the events once\n _this._removeEventListeners();\n }\n\n _this.update({ noEventListeners: _noEventListeners });\n\n return _this;\n },\n onInvalidPaste: function onInvalidPaste(_onInvalidPaste) {\n _this.settings.onInvalidPaste = _onInvalidPaste; //FIXME test this\n\n return _this;\n },\n outputFormat: function outputFormat(_outputFormat) {\n _this.settings.outputFormat = _outputFormat;\n\n return _this;\n },\n overrideMinMaxLimits: function overrideMinMaxLimits(_overrideMinMaxLimits) {\n _this.update({ overrideMinMaxLimits: _overrideMinMaxLimits });\n\n return _this;\n },\n positiveSignCharacter: function positiveSignCharacter(_positiveSignCharacter) {\n _this.update({ positiveSignCharacter: _positiveSignCharacter });\n\n return _this;\n },\n rawValueDivisor: function rawValueDivisor(_rawValueDivisor) {\n _this.update({ rawValueDivisor: _rawValueDivisor });\n\n return _this;\n },\n readOnly: function readOnly(_readOnly) {\n //FIXME test this\n _this.settings.readOnly = _readOnly;\n _this._setReadOnly();\n\n return _this;\n },\n roundingMethod: function roundingMethod(_roundingMethod) {\n _this.update({ roundingMethod: _roundingMethod });\n\n return _this;\n },\n saveValueToSessionStorage: function saveValueToSessionStorage(_saveValueToSessionStorage) {\n _this.update({ saveValueToSessionStorage: _saveValueToSessionStorage });\n\n return _this;\n },\n symbolWhenUnfocused: function symbolWhenUnfocused(_symbolWhenUnfocused) {\n _this.update({ symbolWhenUnfocused: _symbolWhenUnfocused });\n\n return _this;\n },\n selectNumberOnly: function selectNumberOnly(_selectNumberOnly) {\n _this.settings.selectNumberOnly = _selectNumberOnly; //FIXME test this\n\n return _this;\n },\n selectOnFocus: function selectOnFocus(_selectOnFocus) {\n _this.settings.selectOnFocus = _selectOnFocus; //FIXME test this\n\n return _this;\n },\n serializeSpaces: function serializeSpaces(_serializeSpaces) {\n _this.settings.serializeSpaces = _serializeSpaces; //FIXME test this\n\n return _this;\n },\n showOnlyNumbersOnFocus: function showOnlyNumbersOnFocus(_showOnlyNumbersOnFocus) {\n _this.update({ showOnlyNumbersOnFocus: _showOnlyNumbersOnFocus });\n\n return _this;\n },\n showPositiveSign: function showPositiveSign(_showPositiveSign) {\n _this.update({ showPositiveSign: _showPositiveSign });\n\n return _this;\n },\n showWarnings: function showWarnings(_showWarnings) {\n _this.settings.showWarnings = _showWarnings; //FIXME test this\n\n return _this;\n },\n styleRules: function styleRules(_styleRules) {\n _this.update({ styleRules: _styleRules });\n\n return _this;\n },\n suffixText: function suffixText(_suffixText) {\n _this.update({ suffixText: _suffixText });\n\n return _this;\n },\n unformatOnHover: function unformatOnHover(_unformatOnHover) {\n _this.settings.unformatOnHover = _unformatOnHover; //FIXME test this\n\n return _this;\n },\n unformatOnSubmit: function unformatOnSubmit(_unformatOnSubmit2) {\n _this.settings.unformatOnSubmit = _unformatOnSubmit2; //FIXME test this\n\n return _this;\n },\n valuesToStrings: function valuesToStrings(_valuesToStrings) {\n _this.update({ valuesToStrings: _valuesToStrings });\n\n return _this;\n },\n watchExternalChanges: function watchExternalChanges(_watchExternalChanges) {\n //FIXME test this\n _this.update({ watchExternalChanges: _watchExternalChanges });\n\n return _this;\n },\n wheelOn: function wheelOn(_wheelOn) {\n _this.settings.wheelOn = _wheelOn; //FIXME test this\n\n return _this;\n },\n wheelStep: function wheelStep(_wheelStep) {\n _this.settings.wheelStep = _wheelStep; //FIXME test this\n\n return _this;\n }\n };\n\n // Once the autoNumeric element has been initialized, broadcast that message with additional info.\n // Note: When using `AutoNumeric.multiple()`, one event is sent *per* element initialized\n this._triggerEvent(AutoNumeric.events.initialized, this.domElement, {\n newValue: _AutoNumericHelper2.default.getElementValue(this.domElement),\n newRawValue: this.rawValue,\n error: null,\n aNElement: this\n });\n }\n\n /**\n * Return the autoNumeric version number (for debugging purpose)\n *\n * @returns {string}\n */\n\n\n _createClass(AutoNumeric, [{\n key: '_saveInitialValues',\n\n\n /**\n * Save the initial element values for later use in the pristine test.\n * Those values are :\n * - the html attribute (ie. ), and\n * - the script `value` (ie. `let domElement.value`)\n *\n * @param {null|number|string} initialValue\n * @private\n */\n value: function _saveInitialValues(initialValue) {\n // Keep the very first initial values (in the html attribute and set by the script). This is needed to check if the element is pristine.\n // Save the html attribute 'value'\n this.initialValueHtmlAttribute = _AutoNumericHelper2.default.scientificToDecimal(this.domElement.getAttribute('value'));\n if (_AutoNumericHelper2.default.isNull(this.initialValueHtmlAttribute)) {\n // Set the default empty value attribute instead of `null`, since if the initial value is null, the empty string is used\n this.initialValueHtmlAttribute = '';\n }\n\n // Save the 'script' value\n this.initialValue = initialValue;\n if (_AutoNumericHelper2.default.isNull(this.initialValue)) {\n // Same as above\n this.initialValue = '';\n }\n }\n\n /**\n * Generate all the event listeners for the given DOM element\n * @private\n */\n\n }, {\n key: '_createEventListeners',\n value: function _createEventListeners() {\n var _this2 = this;\n\n // Create references to the event handler functions, so we can then cleanly removes those listeners if needed\n // That would not be possible if we used closures directly in the event handler declarations\n this._onFocusInFunc = function (e) {\n _this2._onFocusIn(e);\n };\n this._onFocusInAndMouseEnterFunc = function (e) {\n _this2._onFocusInAndMouseEnter(e);\n };\n this._onFocusFunc = function () {\n _this2._onFocus();\n };\n this._onKeydownFunc = function (e) {\n _this2._onKeydown(e);\n };\n this._onKeypressFunc = function (e) {\n _this2._onKeypress(e);\n };\n this._onKeyupFunc = function (e) {\n _this2._onKeyup(e);\n };\n this._onFocusOutAndMouseLeaveFunc = function (e) {\n _this2._onFocusOutAndMouseLeave(e);\n };\n this._onPasteFunc = function (e) {\n _this2._onPaste(e);\n };\n this._onWheelFunc = function (e) {\n _this2._onWheel(e);\n };\n this._onDropFunc = function (e) {\n _this2._onDrop(e);\n };\n this._onKeydownGlobalFunc = function (e) {\n _this2._onKeydownGlobal(e);\n };\n this._onKeyupGlobalFunc = function (e) {\n _this2._onKeyupGlobal(e);\n };\n\n // Add the event listeners\n this.domElement.addEventListener('focusin', this._onFocusInFunc, false);\n this.domElement.addEventListener('focus', this._onFocusInAndMouseEnterFunc, false);\n this.domElement.addEventListener('focus', this._onFocusFunc, false);\n this.domElement.addEventListener('mouseenter', this._onFocusInAndMouseEnterFunc, false);\n this.domElement.addEventListener('keydown', this._onKeydownFunc, false);\n this.domElement.addEventListener('keypress', this._onKeypressFunc, false);\n this.domElement.addEventListener('keyup', this._onKeyupFunc, false);\n this.domElement.addEventListener('blur', this._onFocusOutAndMouseLeaveFunc, false);\n this.domElement.addEventListener('mouseleave', this._onFocusOutAndMouseLeaveFunc, false);\n this.domElement.addEventListener('paste', this._onPasteFunc, false);\n this.domElement.addEventListener('wheel', this._onWheelFunc, false);\n this.domElement.addEventListener('drop', this._onDropFunc, false);\n this._setupFormListener();\n\n // Create one global event listener for the keyup event on the document object, which will be shared by all the autoNumeric elements\n if (!AutoNumeric._doesGlobalListExists()) {\n document.addEventListener('keydown', this._onKeydownGlobalFunc, false);\n document.addEventListener('keyup', this._onKeyupGlobalFunc, false);\n }\n }\n\n /**\n * Remove all the autoNumeric-related event listeners for the given DOM element\n * @private\n */\n\n }, {\n key: '_removeEventListeners',\n value: function _removeEventListeners() {\n this.domElement.removeEventListener('focusin', this._onFocusInFunc, false);\n this.domElement.removeEventListener('focus', this._onFocusInAndMouseEnterFunc, false);\n this.domElement.removeEventListener('focus', this._onFocusFunc, false);\n this.domElement.removeEventListener('mouseenter', this._onFocusInAndMouseEnterFunc, false);\n this.domElement.removeEventListener('blur', this._onFocusOutAndMouseLeaveFunc, false);\n this.domElement.removeEventListener('mouseleave', this._onFocusOutAndMouseLeaveFunc, false);\n this.domElement.removeEventListener('keydown', this._onKeydownFunc, false);\n this.domElement.removeEventListener('keypress', this._onKeypressFunc, false);\n this.domElement.removeEventListener('keyup', this._onKeyupFunc, false);\n this.domElement.removeEventListener('paste', this._onPasteFunc, false);\n this.domElement.removeEventListener('wheel', this._onWheelFunc, false);\n this.domElement.removeEventListener('drop', this._onDropFunc, false);\n this._removeFormListener();\n\n document.removeEventListener('keydown', this._onKeydownGlobalFunc, false);\n document.removeEventListener('keyup', this._onKeyupGlobalFunc, false);\n }\n\n /**\n * Mark the parent
so that other AutoNumeric object will not add more listeners.\n * Add a counter so that when removing the AutoNumeric object, we only remove the submit listener if that count is equal to 0.\n * Also keep a reference to the 'submit' event handler function to be able to remove that handler later if the `_removeFormListener()` function is called from another AutoNumeric object.\n *\n * @private\n */\n\n }, {\n key: '_setupFormListener',\n value: function _setupFormListener() {\n var _this3 = this;\n\n if (!_AutoNumericHelper2.default.isNull(this.parentForm)) {\n // Setup the handler function\n this._onFormSubmitFunc = function () {\n _this3._onFormSubmit();\n };\n\n // Check if the parent form already has the AutoNumeric mark\n if (this._hasParentFormCounter()) {\n this._incrementParentFormCounter();\n } else {\n // If not, add the counter\n this._initializeFormCounterToOne();\n // And add the submit event listener\n this.parentForm.addEventListener('submit', this._onFormSubmitFunc, false);\n // Also keep a reference to the handler function so that we can remove it later\n this._storeFormHandlerFunction();\n }\n }\n }\n\n /**\n * Remove the form 'submit' event listener, as well as the `dataset` info (`anCount` and `anFormHandler`) from the parent form, only when there are only one AutoNumeric child element left in that .\n * Otherwise decrement the `anCount`.\n *\n * @private\n */\n\n }, {\n key: '_removeFormListener',\n value: function _removeFormListener() {\n if (!_AutoNumericHelper2.default.isNull(this.parentForm)) {\n // Check the parent form counter value\n var anCount = this._getParentFormCounter();\n\n if (anCount === 1) {\n // If it's 1, remove the listener\n this.parentForm.removeEventListener('submit', this._getFormHandlerFunction(), false);\n // Also remove the dataset info\n this._removeFormDataSetInfo();\n } else if (anCount > 1) {\n // Otherwise if it's >1 decrement the counter\n this._decrementParentFormCounter();\n } else {\n // If it's <1, throw an error\n _AutoNumericHelper2.default.throwError('The AutoNumeric object count on the form is incoherent.');\n }\n }\n }\n\n /**\n * Return `true` if the parent form has the form counter attribute\n *\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_hasParentFormCounter',\n value: function _hasParentFormCounter() {\n return 'anCount' in this.parentForm.dataset;\n }\n\n /**\n * Return the count of AutoNumeric form children\n *\n * @returns {number}\n * @private\n */\n\n }, {\n key: '_getParentFormCounter',\n value: function _getParentFormCounter() {\n return Number(this.parentForm.dataset.anCount);\n }\n\n /**\n * Set the count of AutoNumeric form children to 1 for the given form element, or if none are passed, the current `this.parentForm` one.\n *\n * @param {HTMLFormElement|null} formElement\n * @private\n */\n\n }, {\n key: '_initializeFormCounterToOne',\n value: function _initializeFormCounterToOne() {\n var formElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n this._getFormElement(formElement).dataset.anCount = 1;\n }\n\n /**\n * Increment the AutoNumeric form children count for the given form element, or if none are passed, the current `this.parentForm` one.\n *\n * @param {HTMLFormElement|null} formElement\n * @private\n */\n\n }, {\n key: '_incrementParentFormCounter',\n value: function _incrementParentFormCounter() {\n var formElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n this._getFormElement(formElement).dataset.anCount++;\n }\n\n /**\n * Decrement the AutoNumeric form children count for the current `this.parentForm` form element.\n *\n * @private\n */\n\n }, {\n key: '_decrementParentFormCounter',\n value: function _decrementParentFormCounter() {\n this.parentForm.dataset.anCount--;\n }\n\n /**\n * Return `true` if the global form handler list exists on the `window` object.\n *\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_hasFormHandlerFunction',\n\n\n /**\n * Return `true` if the given form element, or if none are passed, the current `this.parentForm` one has a form handler name.\n *\n * @param {HTMLFormElement|null} formElement\n * @returns {boolean}\n * @private\n */\n value: function _hasFormHandlerFunction() {\n var formElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n return 'anFormHandler' in this._getFormElement(formElement).dataset;\n }\n\n /**\n * Return the given form element, or defaults to `this.parentForm` if no argument is passed.\n *\n * @param {HTMLFormElement|null} formElement\n * @returns {*}\n * @private\n */\n\n }, {\n key: '_getFormElement',\n value: function _getFormElement() {\n var formElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n var formElementToUse = void 0;\n if (!_AutoNumericHelper2.default.isNull(formElement)) {\n formElementToUse = formElement;\n } else {\n formElementToUse = this.parentForm;\n }\n\n return formElementToUse;\n }\n\n /**\n * Generate a form handler unique name and store it in the global form handler list.\n * This also save that name in the dataset of the given form element.\n *\n * @param {HTMLFormElement|null} formElement\n * @private\n */\n\n }, {\n key: '_storeFormHandlerFunction',\n value: function _storeFormHandlerFunction() {\n var formElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n // Create the weakMap if it does not exist\n if (!this.constructor._doesFormHandlerListExists()) {\n this.constructor._createFormHandlerList();\n }\n\n // Generate a unique name and save it in the form dataset\n var formHandlerName = _AutoNumericHelper2.default.randomString();\n this._getFormElement(formElement).dataset.anFormHandler = formHandlerName;\n\n // Add the form handler name and handle function reference to the WeakMap\n window.aNFormHandlerMap.set(formHandlerName, this._onFormSubmitFunc);\n }\n\n /**\n * Return the form handler key name from the parent form element, for the global form handler list.\n *\n * @returns {string|*}\n * @private\n */\n\n }, {\n key: '_getFormHandlerKey',\n value: function _getFormHandlerKey() {\n if (!this._hasFormHandlerFunction()) {\n _AutoNumericHelper2.default.throwError('Unable to retrieve the form handler name');\n }\n\n var formHandlerName = this.parentForm.dataset.anFormHandler;\n if (formHandlerName === '') {\n _AutoNumericHelper2.default.throwError('The form handler name is invalid');\n }\n\n return formHandlerName;\n }\n\n /**\n * Return the 'submit' event handler function used for the parent form.\n *\n * @returns {function}\n * @private\n */\n\n }, {\n key: '_getFormHandlerFunction',\n value: function _getFormHandlerFunction() {\n var formHandlerName = this._getFormHandlerKey();\n\n return window.aNFormHandlerMap.get(formHandlerName);\n }\n\n /**\n * Remove the dataset attributes `data-an-count` and `data-an-form-handler` from the parent form element.\n *\n * @private\n */\n\n }, {\n key: '_removeFormDataSetInfo',\n value: function _removeFormDataSetInfo() {\n // Just in case, set the counter to 0\n this._decrementParentFormCounter();\n // Remove the form handler function from the FormHandlerFunction Map\n window.aNFormHandlerMap.delete(this._getFormHandlerKey());\n // Lastly, remove the dataset attributes\n this.parentForm.removeAttribute('data-an-count');\n this.parentForm.removeAttribute('data-an-form-handler');\n }\n\n /**\n * Set the element attribute 'readonly' according to the current settings.\n *\n * @private\n */\n\n }, {\n key: '_setReadOnly',\n value: function _setReadOnly() {\n if (this.isInputElement && this.settings.readOnly) {\n this.domElement.readOnly = true;\n }\n }\n\n /**\n * Add a watcher so that any external change to the AutoNumeric-managed element would be detected.\n * As soon as such change is detected, AutoNumeric then tries to `set()` the value so that it gets formatted and stored in the history.\n * //XXX For now, this only works when watching the `value` attribute, not the `textContent` one\n * @private\n */\n\n }, {\n key: '_addWatcher',\n value: function _addWatcher() {\n var _this4 = this;\n\n // `getterSetter` can be undefined when a non-input element is used\n if (!_AutoNumericHelper2.default.isUndefined(this.getterSetter)) {\n var _getterSetter = this.getterSetter,\n setter = _getterSetter.set,\n getter = _getterSetter.get;\n\n Object.defineProperty(this.domElement, this.attributeToWatch, {\n configurable: true, // This is needed in some rare cases\n get: function get() {\n return getter.call(_this4.domElement);\n },\n set: function set(val) {\n setter.call(_this4.domElement, val);\n // Only `set()` the value if the modification comes from an external source\n if (_this4.settings.watchExternalChanges && !_this4.internalModification) {\n _this4.set(val);\n }\n }\n });\n }\n\n //FIXME The code above fails for the `textContent` attribute since `this.getterSetter` is undefined when using `getOwnPropertyDescriptor()`\n /* //XXX The code below *almost* work for the textContent, but breaks some unit tests\n this.valueWatched = this.domElement[this.attributeToWatch];\n Object.defineProperty(this.domElement, this.attributeToWatch, {\n configurable: true, // This is needed in some rare cases\n get : () => this.valueWatched,\n set : val => {\n this.valueWatched = val;\n // Only `set()` the value if the modification comes from an external source\n if (this.settings.watchExternalChanges && !this.internalModification) {\n this.set(val);\n }\n },\n });\n */\n }\n\n /**\n * Remove the watcher on the AutoNumeric-managed element\n * Note: This needs to be called when the AutoNumeric element is 'removed', otherwise the getter/setter stays on the DOM element and that can lead to problem if the user initialize another AutoNumeric object on it.\n * @private\n */\n\n }, {\n key: '_removeWatcher',\n value: function _removeWatcher() {\n var _this5 = this;\n\n // `getterSetter` can be undefined when a non-input element is used\n if (!_AutoNumericHelper2.default.isUndefined(this.getterSetter)) {\n var _getterSetter2 = this.getterSetter,\n setter = _getterSetter2.set,\n getter = _getterSetter2.get;\n\n Object.defineProperty(this.domElement, this.attributeToWatch, {\n configurable: true, // This is needed in some rare cases\n get: function get() {\n return getter.call(_this5.domElement);\n },\n set: function set(val) {\n setter.call(_this5.domElement, val);\n }\n });\n }\n\n //FIXME The code above fails for the `textContent` attribute since `this.getterSetter` is undefined when using `getOwnPropertyDescriptor()`\n /* //XXX The code below *almost* work for the textContent, but breaks some unit tests\n this.valueWatched = this.domElement[this.attributeToWatch];\n Object.defineProperty(this.domElement, this.attributeToWatch, {\n configurable: true, // This is needed in some rare cases\n get : () => this.valueWatched,\n set : val => {\n this.valueWatched = val;\n },\n });\n */\n }\n\n /**\n * Return the name of the object attribute that store the current formatted data in the DOM element.\n *\n * @returns {string}\n * @private\n */\n\n }, {\n key: '_getAttributeToWatch',\n value: function _getAttributeToWatch() {\n var attributeToWatch = void 0;\n if (this.isInputElement) {\n attributeToWatch = 'value';\n } else {\n var nodeType = this.domElement.nodeType;\n if (nodeType === Node.ELEMENT_NODE || nodeType === Node.DOCUMENT_NODE || nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n attributeToWatch = 'textContent';\n } else if (nodeType === Node.TEXT_NODE) {\n attributeToWatch = 'nodeValue';\n }\n }\n\n return attributeToWatch;\n }\n\n /**\n * Save the current raw value into the history table, along with the selection information.\n *\n * If the user has done some undos and tries to enter:\n * - a new and different number than the 'next' state, this drops the rest of the history table\n * - the very same number that result in the same rawValue than the 'next' state, we only move the history table pointer to the next state\n *\n * @private\n */\n\n }, {\n key: '_historyTableAdd',\n value: function _historyTableAdd() {\n //TODO Add a `this.settings.saveSelectionsIntoHistory` option to prevent saving the selections (in order to gain performance)\n var isEmptyHistoryTable = this.historyTable.length === 0;\n // Only add a new value if it's different than the previous one (to prevent infinitely adding values on mouseover for instance)\n if (isEmptyHistoryTable || this.rawValue !== this._historyTableCurrentValueUsed()) {\n // Trim the history table if the user changed the value of an intermediary state\n var addNewHistoryState = true;\n if (!isEmptyHistoryTable) {\n // If some undo has been done and the user type the exact same data than the next entry after the current history pointer, do no drop the rest of the 'redo' list, and just advance the historyTableIndex\n var nextHistoryStateIndex = this.historyTableIndex + 1;\n if (nextHistoryStateIndex < this.historyTable.length && this.rawValue === this.historyTable[nextHistoryStateIndex].value) {\n // If the character input result in the same state than the next one, do not remove the next history states nor add a new one\n addNewHistoryState = false;\n } else {\n // First remove anything that is after the current index\n _AutoNumericHelper2.default.arrayTrim(this.historyTable, this.historyTableIndex + 1);\n }\n }\n\n // Update the history pointer\n this.historyTableIndex++;\n\n // Add the new history state, if needed\n if (addNewHistoryState) {\n // Save the selection info\n var selection = _AutoNumericHelper2.default.getElementSelection(this.domElement);\n this.selectionStart = selection.start;\n this.selectionEnd = selection.end;\n\n // Then add the new raw value\n this.historyTable.push({\n // Save the rawValue and selection start/end\n value: this.rawValue,\n // The selection for this element is temporary, and will be updated when the next history state will be recorded.\n // That way, we are always sure we save the last caret or selection positions just before the value is changed. Otherwise we would only save those positions when the value is first changed, and would not take into account that the user could move the caret around afterward.\n // For instance, this is needed if the user change the element value, and immediately undo it ; if he then does a redo, he'll see the value and the right selection\n // To sum up; The selection position are not always +1 character, since it could also be '2' if a group separator is added when entering one character. That's why the current history state caret/selection position is updated on each `keyup` event.\n start: this.selectionStart + 1, // Here we add one since the user added one character too\n end: this.selectionEnd + 1\n });\n\n // Update the selection in the previous entry, in order to keep track of the updated caret/selection positions\n if (this.historyTable.length > 1) {\n this.historyTable[this.historyTableIndex - 1].start = this.selectionStart;\n this.historyTable[this.historyTableIndex - 1].end = this.selectionEnd;\n }\n }\n\n // Limit the history table size according to the `historySize` option\n if (this.historyTable.length > this.settings.historySize) {\n this._historyTableForget();\n }\n }\n }\n\n /**\n * Debug function for the history table\n * @private\n */\n /*\n _debugHistoryTable() {\n let i = 0;\n let mark;\n this.historyTable.forEach(history => {\n if (this.historyTableIndex === i) {\n mark = '> ';\n } else {\n mark = '';\n }\n console.log(`${mark}${i++}: ${history.value} ${history.start}|${history.end} [onGoingRedo: ${this.onGoingRedo}]`); //DEBUG\n });\n }\n */\n\n /**\n * 'Undo' or 'Redo' the last/next user entry in the history table.\n * This does not modify the history table, only the pointer to the current state.\n *\n * @param {boolean} undo If set to `true`, then this function does an 'Undo', otherwise it does a 'Redo'\n * @private\n */\n\n }, {\n key: '_historyTableUndoOrRedo',\n value: function _historyTableUndoOrRedo() {\n var undo = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n\n var check = void 0;\n if (undo) {\n // Only 'undo' if there are some info to undo\n check = this.historyTableIndex > 0;\n if (check) {\n this.historyTableIndex--;\n }\n } else {\n // Only 'redo' if there are some info to redo at the end of the history table\n check = this.historyTableIndex + 1 < this.historyTable.length;\n if (check) {\n this.historyTableIndex++;\n }\n }\n\n if (check) {\n // Set the value back\n var undoInfo = this.historyTable[this.historyTableIndex];\n this.set(undoInfo.value, null, false); // next or previous raw value\n\n // Set the selection back\n _AutoNumericHelper2.default.setElementSelection(this.domElement, undoInfo.start, undoInfo.end);\n }\n }\n\n /**\n * 'Undo' the last user entry by going back one entry in the history table.\n * This keeps the following entries in order to allow for a 'redo'.\n * This does not modify the history table, only the pointer to the current state.\n * @private\n */\n\n }, {\n key: '_historyTableUndo',\n value: function _historyTableUndo() {\n this._historyTableUndoOrRedo(true);\n }\n\n /**\n * 'Redo' the next user entry in the history table.\n * This does not modify the history table, only the pointer to the current state.\n * @private\n */\n\n }, {\n key: '_historyTableRedo',\n value: function _historyTableRedo() {\n this._historyTableUndoOrRedo(false);\n }\n\n /**\n * Reset the history table to its initial state, and select the value.\n * @private\n */\n /*\n resetHistoryTable() { //FIXME Test this\n this.set(this.rawValue, null, false);\n this.select();\n const selection = AutoNumericHelper.getElementSelection(this.domElement);\n this.historyTableIndex = 0;\n this.historyTable = [{\n // Save the rawValue and selection start/end\n value: this.rawValue,\n start: selection.start,\n end : selection.end,\n }];\n }\n */\n\n /**\n * Make the history table forget its first N elements, shifting its indexes in the process.\n * `N` being given as the `numberOfEntriesToForget` parameter.\n *\n * @param {Number} numberOfEntriesToForget\n * @returns {object|Array} The discarded objects, in an Array.\n * @private\n */\n\n }, {\n key: '_historyTableForget',\n value: function _historyTableForget() {\n var numberOfEntriesToForget = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;\n\n var shiftedAway = [];\n for (var i = 0; i < numberOfEntriesToForget; i++) {\n shiftedAway.push(this.historyTable.shift());\n // Update the history table index accordingly\n this.historyTableIndex--;\n if (this.historyTableIndex < 0) {\n // In case this function is called more times than there is states in the history table\n this.historyTableIndex = 0;\n }\n }\n\n if (shiftedAway.length === 1) {\n return shiftedAway[0];\n }\n\n return shiftedAway;\n }\n\n /**\n * Return the currently used value from the history table.\n *\n * @returns {string|number}\n * @private\n */\n\n }, {\n key: '_historyTableCurrentValueUsed',\n value: function _historyTableCurrentValueUsed() {\n var indexToUse = this.historyTableIndex;\n if (indexToUse < 0) {\n indexToUse = 0;\n }\n\n var result = void 0;\n if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.historyTable[indexToUse])) {\n result = '';\n } else {\n result = this.historyTable[indexToUse].value;\n }\n\n return result;\n }\n\n /**\n * Parse the `styleRules` option and run the test for each given rules, either pre-defined ones like `positive`, `negative` and `ranges`, or user defined callbacks within the `userDefined` attribute.\n * @private\n */\n\n }, {\n key: '_parseStyleRules',\n value: function _parseStyleRules() {\n var _this6 = this;\n\n if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.settings.styleRules) || this.rawValue === '') {\n return;\n }\n\n // 'positive' attribute\n if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.settings.styleRules.positive)) {\n if (this.rawValue >= 0) {\n this._addCSSClass(this.settings.styleRules.positive);\n } else {\n this._removeCSSClass(this.settings.styleRules.positive);\n }\n }\n\n // 'negative' attribute\n if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.settings.styleRules.negative)) {\n if (this.rawValue < 0) {\n this._addCSSClass(this.settings.styleRules.negative);\n } else {\n this._removeCSSClass(this.settings.styleRules.negative);\n }\n }\n\n // 'ranges' attribute\n if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.settings.styleRules.ranges) && this.settings.styleRules.ranges.length !== 0) {\n this.settings.styleRules.ranges.forEach(function (range) {\n if (_this6.rawValue >= range.min && _this6.rawValue < range.max) {\n _this6._addCSSClass(range.class);\n } else {\n _this6._removeCSSClass(range.class);\n }\n });\n }\n\n // 'userDefined' attribute\n //TODO Also pass the old raw value as a parameter, and not only the new raw value\n if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.settings.styleRules.userDefined) && this.settings.styleRules.userDefined.length !== 0) {\n this.settings.styleRules.userDefined.forEach(function (userObject) {\n if (_AutoNumericHelper2.default.isFunction(userObject.callback)) {\n // Test for the type of the `classes` attribute, which changes the function behavior\n if (_AutoNumericHelper2.default.isString(userObject.classes)) {\n // If 'classes' is a string, set it if `true`, remove it if `false`\n if (userObject.callback(_this6.rawValue)) {\n _this6._addCSSClass(userObject.classes);\n } else {\n _this6._removeCSSClass(userObject.classes);\n }\n } else if (_AutoNumericHelper2.default.isArray(userObject.classes)) {\n if (userObject.classes.length === 2) {\n // If 'classes' is an array with only 2 elements, set the first class if `true`, the second if `false`\n if (userObject.callback(_this6.rawValue)) {\n _this6._addCSSClass(userObject.classes[0]);\n _this6._removeCSSClass(userObject.classes[1]);\n } else {\n _this6._removeCSSClass(userObject.classes[0]);\n _this6._addCSSClass(userObject.classes[1]);\n }\n } else if (userObject.classes.length > 2) {\n // The callback returns an array of indexes to use on the `classes` array\n var callbackResult = userObject.callback(_this6.rawValue);\n if (_AutoNumericHelper2.default.isArray(callbackResult)) {\n // If multiple indexes are returned\n userObject.classes.forEach(function (userClass, index) {\n if (_AutoNumericHelper2.default.isInArray(index, callbackResult)) {\n _this6._addCSSClass(userClass);\n } else {\n _this6._removeCSSClass(userClass);\n }\n });\n } else if (_AutoNumericHelper2.default.isInt(callbackResult)) {\n // If only one index is returned\n userObject.classes.forEach(function (userClass, index) {\n if (index === callbackResult) {\n _this6._addCSSClass(userClass);\n } else {\n _this6._removeCSSClass(userClass);\n }\n });\n } else if (_AutoNumericHelper2.default.isNull(callbackResult)) {\n // Remove all the classes\n userObject.classes.forEach(function (userClass) {\n _this6._removeCSSClass(userClass);\n });\n } else {\n _AutoNumericHelper2.default.throwError('The callback result is not an array nor a valid array index, ' + (typeof callbackResult === 'undefined' ? 'undefined' : _typeof(callbackResult)) + ' given.');\n }\n } else {\n _AutoNumericHelper2.default.throwError('The classes attribute is not valid for the `styleRules` option.');\n }\n } else if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(userObject.classes)) {\n // If 'classes' is `undefined` or `null`, then the callback is called with the AutoNumeric object passed as a parameter\n userObject.callback(_this6);\n } else {\n _AutoNumericHelper2.default.throwError('The callback/classes structure is not valid for the `styleRules` option.');\n }\n } else {\n _AutoNumericHelper2.default.warning('The given `styleRules` callback is not a function, ' + (typeof callback === 'undefined' ? 'undefined' : _typeof(callback)) + ' given.', _this6.settings.showWarnings);\n }\n });\n }\n }\n\n /**\n * Add the given CSS class to the DOM element.\n *\n * @param {string} cssClassName\n * @private\n */\n\n }, {\n key: '_addCSSClass',\n value: function _addCSSClass(cssClassName) {\n this.domElement.classList.add(cssClassName);\n }\n\n /**\n * Remove the given CSS class from the DOM element.\n *\n * @param {string} cssClassName\n * @private\n */\n\n }, {\n key: '_removeCSSClass',\n value: function _removeCSSClass(cssClassName) {\n this.domElement.classList.remove(cssClassName);\n }\n\n // This are the public function available on each autoNumeric-managed element\n\n /**\n * Method that updates the AutoNumeric settings, and immediately format the element accordingly.\n * The options passed as parameter(s) is either one or many objects that each contains some settings, ie. :\n * {\n * digitGroupSeparator: \".\",\n * decimalCharacter: \",\",\n * currencySymbol: '€ ',\n * }\n * If multiple options are passed, the latter overwrite the previous ones.\n *\n * Note: If the new settings are not validated, or the call to `set()` fails, then the previous valid settings are reverted back to.\n *\n * @example anElement.update({ options }) // Updates the settings\n * @example anElement.update({ options1 }, { options2 }) // Updates the settings with multiple option objects\n * @example anElement.update([{ options1 }, { options2 }]) // Updates the settings with multiple option objects in a single array\n *\n * @param {object|string|array} newOptions\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'update',\n value: function update() {\n var _this7 = this;\n\n for (var _len2 = arguments.length, newOptions = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n newOptions[_key2] = arguments[_key2];\n }\n\n if (Array.isArray(newOptions) && Array.isArray(newOptions[0])) {\n // Allows to pass a single array of options\n newOptions = newOptions[0];\n }\n\n // Keep a copy of the original settings before changing them, in case they do not validate correctly, so we can switch back to them\n var originalSettings = _AutoNumericHelper2.default.cloneObject(this.settings); //TODO Check that the `styleRules` option is correctly cloned (due to depth cloning limitation)\n\n // Store the current unformatted input value\n var numericString = this.rawValue;\n\n // Generate a single option object with the settings from the latter overwriting those from the former\n var optionsToUse = {};\n if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(newOptions) || newOptions.length === 0) {\n optionsToUse = null;\n } else if (newOptions.length >= 1) {\n newOptions.forEach(function (optionObject) {\n if (_this7.constructor._isPreDefinedOptionValid(optionObject)) {\n // The option object is a predefined option name (ie. 'euro')\n optionObject = _this7.constructor._getOptionObject(optionObject);\n }\n\n _extends(optionsToUse, optionObject);\n });\n }\n\n // Update the settings\n try {\n this._setSettings(optionsToUse, true);\n\n // Reformat the input value with the new settings\n // Note: we always `set`, even when `numericString` is the empty string '', since `emptyInputBehavior` (set to `always` or `zero`) can change how the empty input is formatted\n this.set(numericString);\n } catch (error) {\n // If the settings validation fails, then we switch back to the previous valid settings\n this._setSettings(originalSettings, true); // `_setSettings()` is used here instead of directly doing `this.settings = originalSettings;` since lots of side variables are calculated from the settings, and we need to get those back to their previous state. Note: `_setSettings()` is called in the 'update' mode in order to correctly set back the `originalDecimalPlacesRawValue` value.\n _AutoNumericHelper2.default.throwError('Unable to update the settings, those are invalid: [' + error + ']');\n\n return this;\n }\n\n return this;\n }\n\n /**\n * Return the options object containing all the current autoNumeric settings in effect.\n * You can then directly access each option by using its name : `anElement.getSettings().optionNameAutoCompleted`.\n *\n * @example\n * anElement.getSettings()\n * anElement.getSettings().decimalCharacter // Return the decimalCharacter setting as a string - any valid option name can be used\n *\n * @returns {object}\n */\n\n }, {\n key: 'getSettings',\n value: function getSettings() {\n return this.settings;\n }\n\n /**\n * Set the given element value, and format it immediately.\n * Additionally, this `set()` method can accept options that will be merged into the current AutoNumeric element, taking precedence over any previous settings.\n *\n * @example anElement.set('12345.67') // Formats the value\n * @example anElement.set(12345.67) // Formats the value\n * @example anElement.set(12345.67, { decimalCharacter : ',' }) // Update the settings and formats the value in one go\n * @example anElement.northAmerican().set('$12,345.67') // Set an already formatted value (this does not _exactly_ respect the currency symbol/negative placements, but only remove all non-numbers characters, according to the ones given in the settings)\n * @example anElement.set(null) // Set the rawValue and element value to `null`\n *\n * @param {number|string|null} newValue The value must be a Number, a numeric string or `null` (if `emptyInputBehavior` is set to `'null'`)\n * @param {object} options A settings object that will override the current settings. Note: the update is done only if the `newValue` is defined.\n * @param {boolean} saveChangeToHistory If set to `true`, then the change is recorded in the history table\n * @returns {AutoNumeric}\n * @throws\n */\n\n }, {\n key: 'set',\n value: function set(newValue) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n var saveChangeToHistory = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n\n //TODO Add the `saveSettings` options. If `true`, then when `options` is passed, then it overwrite the current `this.settings`. If `false` the `options` are only used once and `this.settings` is not modified\n if (_AutoNumericHelper2.default.isUndefined(newValue)) {\n _AutoNumericHelper2.default.warning('You are trying to set an \\'undefined\\' value ; an error could have occurred.', this.settings.showWarnings);\n return this;\n }\n\n // The options update is done only if the `newValue` is not `undefined`\n if (!_AutoNumericHelper2.default.isNull(options)) {\n this._setSettings(options, true); // We do not call `update` here since this would call `set` too\n }\n\n if (newValue === null && this.settings.emptyInputBehavior !== AutoNumeric.options.emptyInputBehavior.null) {\n _AutoNumericHelper2.default.warning('You are trying to set the `null` value while the `emptyInputBehavior` option is set to ' + this.settings.emptyInputBehavior + '. If you want to be able to set the `null` value, you need to change the \\'emptyInputBehavior\\' option to `\\'null\\'`.', this.settings.showWarnings);\n return this;\n }\n\n var value = void 0;\n if (newValue === null) {\n //TODO Merge this into a global `if (newValue === null) {` test, with the test above\n // Here this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.null\n this._setElementAndRawValue(null, null, saveChangeToHistory);\n this._saveValueToPersistentStorage();\n\n return this;\n }\n\n value = this.constructor._toNumericValue(newValue, this.settings);\n if (isNaN(Number(value))) {\n //TODO Do not modify the element value if the newValue results in `NaN`. Make sure the settings, if modified, are revert back too.\n _AutoNumericHelper2.default.warning('The value you are trying to set results in `NaN`. The element value is set to the empty string instead.', this.settings.showWarnings);\n this.setValue('', saveChangeToHistory);\n\n return this;\n }\n\n if (value === '' && this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.zero) {\n // Keep the value zero inside the element\n value = 0;\n }\n\n if (value !== '') {\n var _constructor$_checkIf = this.constructor._checkIfInRangeWithOverrideOption(value, this.settings),\n _constructor$_checkIf2 = _slicedToArray(_constructor$_checkIf, 2),\n minTest = _constructor$_checkIf2[0],\n maxTest = _constructor$_checkIf2[1];\n\n // Modify the formatted value if the rawValue is found in the `valuesToStrings` option\n\n\n if (minTest && maxTest && this.settings.valuesToStrings && this._checkValuesToStrings(value)) {\n // Set the raw value normally, and the formatted value with the corresponding string\n this._setElementAndRawValue(this.settings.valuesToStrings[value], value, saveChangeToHistory);\n this._saveValueToPersistentStorage();\n\n return this;\n }\n\n // This test is needed by the `showPositiveSign` option\n var isZero = _AutoNumericHelper2.default.isZeroOrHasNoValue(value);\n if (isZero) {\n value = '0';\n }\n\n if (minTest && maxTest) {\n var forcedRawValue = this.constructor._roundRawValue(value, this.settings);\n forcedRawValue = this._trimLeadingAndTrailingZeros(forcedRawValue.replace(this.settings.decimalCharacter, '.')); // Move the `setRawValue` call after the `setElementValue` one\n value = this._getRawValueToFormat(value); // Multiply the raw value to obtain the formatted value\n\n // Round the given value according to the object state (focused/unfocused)\n if (this.isFocused) {\n value = this.constructor._roundFormattedValueShownOnFocus(value, this.settings);\n } else {\n if (this.settings.divisorWhenUnfocused) {\n value = value / this.settings.divisorWhenUnfocused;\n value = value.toString();\n }\n\n value = this.constructor._roundFormattedValueShownOnBlur(value, this.settings);\n }\n\n value = this.constructor._modifyNegativeSignAndDecimalCharacterForFormattedValue(value, this.settings);\n value = this.constructor._addGroupSeparators(value, this.settings, this.isFocused, this.rawValue, forcedRawValue);\n if (!this.isFocused && this.settings.symbolWhenUnfocused) {\n value = '' + value + this.settings.symbolWhenUnfocused;\n }\n\n if (this.settings.decimalPlacesShownOnFocus || this.settings.divisorWhenUnfocused) {\n this._saveValueToPersistentStorage();\n }\n\n this._setElementAndRawValue(value, forcedRawValue, saveChangeToHistory);\n\n return this;\n } else {\n if (!minTest) {\n this._triggerEvent(AutoNumeric.events.minRangeExceeded, this.domElement);\n }\n\n if (!maxTest) {\n this._triggerEvent(AutoNumeric.events.maxRangeExceeded, this.domElement);\n }\n\n _AutoNumericHelper2.default.throwError('The value [' + value + '] being set falls outside of the minimumValue [' + this.settings.minimumValue + '] and maximumValue [' + this.settings.maximumValue + '] range set for this element');\n\n this._removeValueFromPersistentStorage();\n this.setValue('', saveChangeToHistory); //TODO Shouldn't we just drop that faulty newValue and keep the previous one? This is behind a `throwError()` call anyway..\n\n return this;\n }\n } else {\n // Here, `value` equal the empty string `''`\n var result = void 0;\n if (this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.always) {\n // Keep the currency symbol as per emptyInputBehavior\n result = this.settings.currencySymbol;\n } else {\n result = '';\n }\n\n this._setElementAndRawValue(result, '', saveChangeToHistory);\n\n return this;\n }\n }\n\n /**\n * Set the given value directly as the DOM element value, without formatting it beforehand.\n * You can also set the value and update the setting in one go (the value will again not be formatted immediately).\n *\n * @param {number|string} value\n * @param {object} options\n * @returns {AutoNumeric}\n * @throws\n */\n\n }, {\n key: 'setUnformatted',\n value: function setUnformatted(value) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n //TODO Should we use `AutoNumeric.unformat()` here and set the unformatted result in case `value` is formatted?\n if (value === null || _AutoNumericHelper2.default.isUndefined(value)) {\n return this;\n }\n\n // The options update is done only if the `value` is not null\n if (!_AutoNumericHelper2.default.isNull(options)) {\n this._setSettings(options, true); // We do not call `update` here since this would call `set` too\n }\n\n var strippedValue = this.constructor._removeBrackets(value, this.settings);\n var normalizedValue = this.constructor._stripAllNonNumberCharacters(strippedValue, this.settings, true, this.isFocused);\n if (!_AutoNumericHelper2.default.isNumber(normalizedValue)) {\n _AutoNumericHelper2.default.throwError('The value is not a valid one, it\\'s not a numeric string nor a recognized currency.');\n }\n\n var _constructor$_checkIf3 = this.constructor._checkIfInRangeWithOverrideOption(normalizedValue, this.settings),\n _constructor$_checkIf4 = _slicedToArray(_constructor$_checkIf3, 2),\n minTest = _constructor$_checkIf4[0],\n maxTest = _constructor$_checkIf4[1];\n\n if (minTest && maxTest) {\n // If the `normalizedValue` is in the range\n this.setValue(value);\n } else {\n _AutoNumericHelper2.default.throwError('The value is out of the range limits [' + this.settings.minimumValue + ', ' + this.settings.maximumValue + '].');\n }\n\n return this;\n }\n\n /**\n * Set the given value directly as the DOM element value, without formatting it beforehand, and without checking its validity.\n * This also updates the `rawValue` with the given `newValue`, without checking it too ; if it's not formatted like a number recognized by Javascript, this *will* likely make other AutoNumeric methods fail.\n *\n * @param {string|number|null} newValue The new value to set on the element\n * @param {boolean} saveChangeToHistory If set to `true`, then the change is recorded in the history array, otherwise it is not\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'setValue',\n value: function setValue(newValue) {\n var saveChangeToHistory = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n this._setElementAndRawValue(newValue, saveChangeToHistory);\n\n return this;\n }\n\n /**\n * Save the raw value inside the AutoNumeric object.\n *\n * @param {number|string|null} rawValue The numeric value as understood by Javascript like a `Number`\n * @param {boolean} saveChangeToHistory If set to `true`, then the change is recorded in the history array, otherwise it is not\n * @private\n */\n\n }, {\n key: '_setRawValue',\n value: function _setRawValue(rawValue) {\n var saveChangeToHistory = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n // Only set the raw value if the given value is different than the current one\n if (this.rawValue !== rawValue) {\n //TODO Manage the case where one value is a string while the other is a number?\n var oldRawValue = this.rawValue;\n // Update the raw value\n this.rawValue = rawValue; // By default, if the `rawValue` is changed programmatically\n\n if (!_AutoNumericHelper2.default.isNull(this.settings.rawValueDivisor) && this.settings.rawValueDivisor !== 0 && // Only divide if the `rawValueDivisor` option is set\n rawValue !== '' && rawValue !== null && // Do not modify the `rawValue` if it's an empty string or null\n this._isUserManuallyEditingTheValue()) {\n // If the user is manually changing the element value\n this.rawValue /= this.settings.rawValueDivisor;\n }\n\n // Broadcast the `rawValueModified` event since the `rawValue` has been modified\n this._triggerEvent(AutoNumeric.events.rawValueModified, this.domElement, {\n oldRawValue: oldRawValue,\n newRawValue: this.rawValue,\n isPristine: this.isPristine(true),\n error: null,\n aNElement: this\n });\n\n // Change the element style or use the relevant callbacks\n this._parseStyleRules();\n\n if (saveChangeToHistory) {\n // Save in the history the last known raw value and formatted result selection\n this._historyTableAdd();\n }\n }\n }\n\n /**\n * Set the given value on the DOM element, without affecting the `rawValue`.\n * This send an 'autoNumeric:formatted' event if the new value is different than the old one.\n *\n * @param {number|string} newElementValue\n * @param {boolean} sendFormattedEvent If set to `true`, then the `AutoNumeric.events.formatted` event is sent if the value has changed\n * @returns {AutoNumeric}\n * @private\n */\n\n }, {\n key: '_setElementValue',\n value: function _setElementValue(newElementValue) {\n var sendFormattedEvent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n //TODO Use an internal attribute to track the current value of the element `formattedValue` (like its counterpart `rawValue`). This would allow us to avoid calling `getElementValue` many times\n var oldElementValue = _AutoNumericHelper2.default.getElementValue(this.domElement);\n\n // Only update the value if it's different from the current one\n if (newElementValue !== oldElementValue) {\n this.internalModification = true;\n _AutoNumericHelper2.default.setElementValue(this.domElement, newElementValue);\n this.internalModification = false;\n\n if (sendFormattedEvent) {\n this._triggerEvent(AutoNumeric.events.formatted, this.domElement, {\n oldValue: oldElementValue,\n newValue: newElementValue,\n oldRawValue: this.rawValue,\n newRawValue: this.rawValue,\n isPristine: this.isPristine(false),\n error: null,\n aNElement: this\n });\n }\n }\n\n return this;\n }\n\n /**\n * Set the given value on the DOM element, and the raw value on `this.rawValue`, if both are given.\n * If only one value is given, then both the DOM element value and the raw value are set with that value.\n * The third argument `saveChangeToHistory` defines if the change should be recorded in the history array.\n * Note: if the second argument `rawValue` is a boolean, we consider that is really is the `saveChangeToHistory` argument.\n *\n * @param {number|string|null} newElementValue\n * @param {number|string|null|boolean} rawValue\n * @param {boolean} saveChangeToHistory\n * @returns {AutoNumeric}\n * @private\n */\n\n }, {\n key: '_setElementAndRawValue',\n value: function _setElementAndRawValue(newElementValue) {\n var rawValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n var saveChangeToHistory = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n\n if (_AutoNumericHelper2.default.isNull(rawValue)) {\n rawValue = newElementValue;\n } else if (_AutoNumericHelper2.default.isBoolean(rawValue)) {\n saveChangeToHistory = rawValue;\n rawValue = newElementValue;\n }\n\n //XXX The order here is important ; the value should first be set on the element, then and only then we should update the raw value\n // In the `set()` function, we make sure to call `_setRawValue` *after* `setElementValue` so that if `_setRawValue` calls a callback that modify the `rawValue`, then the new value is set correctly (after `setElementValue` briefly set its value first)\n this._setElementValue(newElementValue);\n this._setRawValue(rawValue, saveChangeToHistory);\n\n return this;\n }\n\n /**\n * Return the multiplied raw value with the `rawValueDivisor`.\n * This is used to display different values between the raw and formatted values.\n *\n * @param {number|string|null} rawValue The numeric value as understood by Javascript like a `Number`\n * @returns {number|string|null}\n * @private\n */\n\n }, {\n key: '_getRawValueToFormat',\n value: function _getRawValueToFormat(rawValue) {\n var rawValueForTheElementValue = void 0;\n if (!_AutoNumericHelper2.default.isNull(this.settings.rawValueDivisor) && this.settings.rawValueDivisor !== 0 && // Only multiply if the `rawValueDivisor` option is set\n rawValue !== '' && rawValue !== null) {\n // Do not modify the `rawValue` if it's an empty string or null\n // !this._isUserManuallyEditingTheValue()) { // If the user is NOT manually changing the element value, but that is done programmatically\n rawValueForTheElementValue = rawValue * this.settings.rawValueDivisor;\n } else {\n rawValueForTheElementValue = rawValue;\n }\n\n return rawValueForTheElementValue;\n }\n\n /**\n * Check if the given value has a corresponding key in the `valuesToStrings` option object.\n *\n * @param {number|string} value\n * @returns {boolean} Returns `true` if such a key is found.\n * @private\n */\n\n }, {\n key: '_checkValuesToStrings',\n value: function _checkValuesToStrings(value) {\n return this.constructor._checkValuesToStringsArray(value, this.valuesToStringsKeys);\n }\n\n /**\n * Check if the given value has a corresponding key in the `stringsArray` array.\n *\n * @param {number|string} key\n * @param {array} stringsArray Array where the `key` is checked against its keys\n * @returns {boolean} Returns `true` if such a key is found.\n * @private\n */\n\n }, {\n key: '_isUserManuallyEditingTheValue',\n\n\n /**\n * Return `true` if the user is currently modifying the element value manually.\n *\n * @returns {boolean}\n * @private\n */\n value: function _isUserManuallyEditingTheValue() {\n // return (this.isFocused && this.isEditing) || this.isWheelEvent || this.isDropEvent;\n return this.isFocused && this.isEditing || this.isDropEvent;\n }\n\n /**\n * Execute the given callback function using the given result as its first parameter, and the AutoNumeric object as its second.\n *\n * @param {number|string|Array|null} result\n * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n * @private\n */\n\n }, {\n key: '_executeCallback',\n value: function _executeCallback(result, callback) {\n if (!_AutoNumericHelper2.default.isNull(callback) && _AutoNumericHelper2.default.isFunction(callback)) {\n callback(result, this);\n }\n }\n\n /**\n * Trigger the given event on the given element with the given detail.\n * This takes into account the `eventBubbles` and `eventIsCancelable` options.\n *\n * @param {string} eventName\n * @param {HTMLElement|HTMLDocument|EventTarget} element\n * @param {object} detail\n * @private\n */\n\n }, {\n key: '_triggerEvent',\n value: function _triggerEvent(eventName) {\n var element = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document;\n var detail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n _AutoNumericHelper2.default.triggerEvent(eventName, element, detail, this.settings.eventBubbles, this.settings.eventIsCancelable);\n }\n\n /**\n * Alias of the `getNumericString()` function.\n * Developers should use one of the more explicit function names to get what they want :\n * - a numeric string : `getNumericString()`\n * - a formatted string : `getFormatted()`\n * - a number : `getNumber()`, or\n * - a localized numeric string : `getLocalized()`\n *\n * @usage anElement.get();\n *\n * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n *\n * @deprecated\n * @returns {string|null}\n */\n\n }, {\n key: 'get',\n value: function get() {\n var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n return this.getNumericString(callback);\n }\n\n /**\n * Return the unformatted value as a string.\n * This can also return `null` if `rawValue` is null.\n *\n * @usage anElement.getNumericString();\n *\n * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n *\n * @returns {string|null}\n */\n\n }, {\n key: 'getNumericString',\n value: function getNumericString() {\n var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n var result = void 0;\n if (_AutoNumericHelper2.default.isNull(this.rawValue)) {\n result = null;\n } else {\n // Always return a numeric string\n // The following statement gets rid of the trailing zeros in the decimal places since the current method does not pad decimals\n result = _AutoNumericHelper2.default.trimPaddedZerosFromDecimalPlaces(this.rawValue);\n }\n\n this._executeCallback(result, callback);\n\n return result;\n }\n\n /**\n * Return the current formatted value of the AutoNumeric element as a string\n *\n * @usage anElement.getFormatted()\n *\n * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n *\n * @returns {string}\n */\n\n }, {\n key: 'getFormatted',\n value: function getFormatted() {\n var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n if (!('value' in this.domElement || 'textContent' in this.domElement)) {\n // Make sure `.value` or `.textContent' exists before trying to access those properties\n _AutoNumericHelper2.default.throwError('Unable to get the formatted string from the element.');\n }\n\n var result = _AutoNumericHelper2.default.getElementValue(this.domElement);\n this._executeCallback(result, callback);\n\n return result;\n }\n\n /**\n * Return the element unformatted value as a real Javascript number.\n * Warning: This can lead to precision problems with big numbers that should be stored as strings.\n *\n * @usage anElement.getNumber()\n *\n * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n *\n * @returns {number|null}\n */\n\n }, {\n key: 'getNumber',\n value: function getNumber() {\n var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n var result = void 0;\n if (this.rawValue === null) {\n result = null;\n } else {\n result = this.constructor._toLocale(this.getNumericString(), 'number', this.settings);\n }\n\n this._executeCallback(result, callback);\n\n return result;\n }\n\n /**\n * Returns the unformatted value, but following the `outputFormat` setting, which means the output can either be :\n * - a string (that could or could not represent a number (ie. \"12345,67-\")), or\n * - a plain number (if the setting 'number' is used).\n *\n * By default the returned values are an ISO numeric string \"1234.56\" or \"-1234.56\" where the decimal character is a period.\n * Check the \"outputFormat\" option definition for more details.\n *\n * @usage anElement.getLocalized();\n *\n * @param {null|string|function} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n * @param {function|null} callback If a callback is passed, then the result is passed to it as its first argument, and the AutoNumeric object has its second\n *\n * @returns {*}\n */\n\n }, {\n key: 'getLocalized',\n value: function getLocalized() {\n var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n // First, check if only a callback has been passed, and if so, sanitize the parameters\n if (_AutoNumericHelper2.default.isFunction(forcedOutputFormat) && _AutoNumericHelper2.default.isNull(callback)) {\n callback = forcedOutputFormat;\n forcedOutputFormat = null;\n }\n\n // Then get the localized value\n var value = void 0;\n if (_AutoNumericHelper2.default.isEmptyString(this.rawValue)) {\n value = '';\n } else {\n // Here I use `this.rawValue` instead of `this.getNumericString()` since the current input value could be unformatted with a localization (ie. '1234567,89-').\n // I also convert the rawValue to a number, then back to a string in order to drop the decimal part if the rawValue is an integer.\n value = '' + Number(this.rawValue);\n }\n\n if (value !== '' && Number(value) === 0 && this.settings.leadingZero !== AutoNumeric.options.leadingZero.keep) {\n value = '0';\n }\n\n var outputFormatToUse = void 0;\n if (_AutoNumericHelper2.default.isNull(forcedOutputFormat)) {\n outputFormatToUse = this.settings.outputFormat;\n } else {\n outputFormatToUse = forcedOutputFormat;\n }\n\n var result = this.constructor._toLocale(value, outputFormatToUse, this.settings);\n this._executeCallback(result, callback);\n\n return result;\n }\n\n /**\n * Force the element to reformat its value again (just in case the formatting has been lost).\n * This can be used right after a form submission for instance (after a previous call to `unformat`).\n *\n * @example anElement.reformat()\n *\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'reformat',\n value: function reformat() {\n // `this.rawValue` is used instead of `this.domElement.value` because when the content is `unformatLocalized`, it can become a string that cannot be converted to a number easily\n this.set(this.rawValue);\n\n return this;\n }\n\n /**\n * Remove the formatting and keep only the raw unformatted value in the element (as a numericString)\n * Note: this is loosely based on the previous 'unSet()' function\n *\n * By default, values are returned as ISO numeric strings (ie. \"1234.56\" or \"-1234.56\"), where the decimal character is a period.\n * @example anElement.unformat()\n *\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'unformat',\n value: function unformat() {\n this._setElementValue(this.getNumericString());\n\n return this;\n }\n\n /**\n * Remove the formatting and keep only the localized unformatted value in the element, with the option to override the default outputFormat if needed\n *\n * Locale formats are supported \"1234.56-\" or \"1234,56\" or \"-1234,56 or \"1234,56-\", or even plain numbers.\n * Take a look at the `outputFormat` option definition in the default settings for more details.\n *\n * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'unformatLocalized',\n value: function unformatLocalized() {\n var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n this._setElementValue(this.getLocalized(forcedOutputFormat));\n\n return this;\n }\n\n /**\n * Return `true` if the current value is the same as when the element got initialized.\n * Note: By default, this returns `true` if the raw unformatted value is still the same even if the formatted one has changed (due to a configuration update for instance).\n * In order to test if the formatted value is the same (which means neither the raw value nor the settings have been changed), then you must pass `false` as its argument.\n *\n * @param {boolean} checkOnlyRawValue If set to `true`, the pristine value is done on the raw unformatted value, not the formatted one. If set to `false`, this also checks that the formatted value hasn't changed.\n * @returns {boolean}\n */\n\n }, {\n key: 'isPristine',\n value: function isPristine() {\n var checkOnlyRawValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;\n\n var result = void 0;\n if (checkOnlyRawValue) {\n result = this.initialValue === this.getNumericString();\n } else {\n result = this.initialValueHtmlAttribute === this.getFormatted();\n }\n\n return result;\n }\n\n /**\n * Select the formatted element content, based on the `selectNumberOnly` option\n *\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'select',\n value: function select() {\n if (this.settings.selectNumberOnly) {\n this.selectNumber();\n } else {\n this._defaultSelectAll();\n }\n\n return this;\n }\n\n /**\n * Select the whole element content (including the currency symbol).\n * @private\n */\n\n }, {\n key: '_defaultSelectAll',\n value: function _defaultSelectAll() {\n _AutoNumericHelper2.default.setElementSelection(this.domElement, 0, _AutoNumericHelper2.default.getElementValue(this.domElement).length);\n }\n\n /**\n * Select only the numbers in the formatted element content, leaving out the currency symbol, whatever the value of the `selectNumberOnly` option\n *\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'selectNumber',\n value: function selectNumber() {\n //TODO Make sure the selection is ok when showPositiveSign is set to `true` (select the negative sign, but not the positive one)\n var unformattedValue = _AutoNumericHelper2.default.getElementValue(this.domElement);\n var valueLen = unformattedValue.length;\n var currencySymbolSize = this.settings.currencySymbol.length;\n var currencySymbolPlacement = this.settings.currencySymbolPlacement;\n var negLen = !_AutoNumericHelper2.default.isNegative(unformattedValue, this.settings.negativeSignCharacter) ? 0 : 1;\n var suffixTextLen = this.settings.suffixText.length;\n\n var start = void 0;\n if (currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n start = 0;\n } else if (this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.left && negLen === 1 && currencySymbolSize > 0) {\n start = currencySymbolSize + 1;\n } else {\n start = currencySymbolSize;\n }\n\n var end = void 0;\n if (currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix) {\n end = valueLen - suffixTextLen;\n } else {\n switch (this.settings.negativePositiveSignPlacement) {\n case AutoNumeric.options.negativePositiveSignPlacement.left:\n end = valueLen - (suffixTextLen + currencySymbolSize);\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.right:\n if (currencySymbolSize > 0) {\n end = valueLen - (currencySymbolSize + negLen + suffixTextLen);\n } else {\n end = valueLen - (currencySymbolSize + suffixTextLen);\n }\n break;\n default:\n end = valueLen - (currencySymbolSize + suffixTextLen);\n }\n }\n\n _AutoNumericHelper2.default.setElementSelection(this.domElement, start, end);\n\n return this;\n }\n\n /**\n * Select only the integer part in the formatted element content, whatever the value of `selectNumberOnly`\n *\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'selectInteger',\n value: function selectInteger() {\n var start = 0;\n var isPositive = this.rawValue >= 0;\n\n // Negative or positive sign, if any\n if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix || this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix && (this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.prefix || this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.none)) {\n if (this.settings.showPositiveSign && isPositive || // This only exclude the positive sign from being selected\n !isPositive && this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix && this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.left) {\n // And this exclude the negative sign from being selected in this special case : '-€ 1.234,57suffixText'\n start = start + 1;\n }\n }\n\n // Currency symbol\n if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix) {\n start = start + this.settings.currencySymbol.length;\n }\n\n // Calculate the selection end position\n var elementValue = _AutoNumericHelper2.default.getElementValue(this.domElement);\n var end = elementValue.indexOf(this.settings.decimalCharacter);\n if (end === -1) {\n // No decimal character found\n if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n end = elementValue.length - this.settings.currencySymbol.length;\n } else {\n end = elementValue.length;\n }\n\n // Trailing negative sign\n if (!isPositive && (this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.suffix || this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix)) {\n end = end - 1;\n }\n\n // Avoid selecting the suffix test\n end = end - this.settings.suffixText.length;\n }\n\n _AutoNumericHelper2.default.setElementSelection(this.domElement, start, end);\n\n return this;\n }\n\n /**\n * Select only the decimal part in the formatted element content, whatever the value of `selectNumberOnly`\n * Multiple cases are possible :\n * +1.234,57suffixText\n *\n * € +1.234,57suffixText\n * +€ 1.234,57suffixText\n * € 1.234,57+suffixText\n *\n * 1.234,57+ €suffixText\n * 1.234,57 €+suffixText\n * +1.234,57 €suffixText\n *\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'selectDecimal',\n value: function selectDecimal() {\n var start = _AutoNumericHelper2.default.getElementValue(this.domElement).indexOf(this.settings.decimalCharacter);\n var end = void 0;\n\n if (start === -1) {\n // The decimal character has not been found, we deselect all\n start = 0;\n end = 0;\n } else {\n // A decimal character has been found\n start = start + 1; // We add 1 to exclude the decimal character from the selection\n\n var decimalCount = void 0;\n if (this.isFocused) {\n decimalCount = this.settings.decimalPlacesShownOnFocus;\n } else {\n decimalCount = this.settings.decimalPlacesShownOnBlur;\n }\n\n end = start + Number(decimalCount);\n }\n\n _AutoNumericHelper2.default.setElementSelection(this.domElement, start, end);\n\n return this;\n }\n\n /**\n * Return the DOM element reference of the autoNumeric-managed element\n *\n * @returns {HTMLElement|HTMLInputElement}\n */\n\n }, {\n key: 'node',\n value: function node() {\n return this.domElement;\n }\n\n /**\n * Return the DOM element reference of the parent node of the autoNumeric-managed element\n *\n * @returns {HTMLElement|HTMLInputElement|Node}\n */\n\n }, {\n key: 'parent',\n value: function parent() {\n return this.domElement.parentNode;\n }\n\n /**\n * Detach the current AutoNumeric element from the shared local 'init' list.\n * This means any changes made on that local shared list will not be transmitted to that element anymore.\n * Note : The user can provide another AutoNumeric element, and detach this one instead of the current one.\n *\n * @param {AutoNumeric} otherAnElement\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'detach',\n value: function detach() {\n var otherAnElement = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n //FIXME test this\n var domElementToDetach = void 0;\n if (!_AutoNumericHelper2.default.isNull(otherAnElement)) {\n domElementToDetach = otherAnElement.node();\n } else {\n domElementToDetach = this.domElement;\n }\n\n this._removeFromLocalList(domElementToDetach); //FIXME What happens if the selected dom element does not exist in the list?\n\n return this;\n }\n\n /**\n * Attach the given AutoNumeric element to the shared local 'init' list.\n * When doing that, by default the DOM content is left untouched.\n * The user can force a reformat with the new shared list options by passing a second argument to `true`.\n *\n * @param {AutoNumeric} otherAnElement\n * @param {boolean} reFormat\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'attach',\n value: function attach(otherAnElement) {\n var reFormat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n //FIXME test this\n this._addToLocalList(otherAnElement.node()); //FIXME Should we make sure the element is not already in the list?\n if (reFormat) {\n otherAnElement.update(this.settings);\n }\n\n return this;\n }\n\n /**\n * Format and return the given value, or set the formatted value into the given DOM element if one is passed as an argument.\n * By default, this use the current element settings.\n * The user can override any option of its choosing by passing an option object.\n *\n * @param {number|HTMLElement|HTMLInputElement} valueOrElement\n * @param {null|object} optionOverride\n * @returns {string|null}\n */\n\n }, {\n key: 'formatOther',\n value: function formatOther(valueOrElement) {\n var optionOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n //FIXME test this\n return this._formatOrUnformatOther(true, valueOrElement, optionOverride);\n }\n\n /**\n * Unformat and return the raw numeric string corresponding to the given value, or directly set the unformatted value into the given DOM element if one is passed as an argument.\n * By default, this use the current element settings.\n * The user can override any option of its choosing by passing an option object.\n * @param {string|HTMLElement|HTMLInputElement} stringOrElement\n * @param {null|object} optionOverride\n * @returns {string|null}\n */\n\n }, {\n key: 'unformatOther',\n value: function unformatOther(stringOrElement) {\n var optionOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n //FIXME test this\n return this._formatOrUnformatOther(false, stringOrElement, optionOverride);\n }\n\n /**\n * Method that either format or unformat the value of another element.\n *\n * - Format and return the given value, or set the formatted value into the given DOM element if one is passed as an argument.\n * - Unformat and return the raw numeric string corresponding to the given value, or directly set the unformatted value into the given DOM element if one is passed as an argument.\n *\n * By default, this use the current element settings.\n * The user can override any option of its choosing by passing an option object.\n *\n * @param {boolean} isFormatting If set to `true`, then the method formats, otherwise if set to `false`, it unformats\n * @param {number|string|HTMLElement|HTMLInputElement} valueOrStringOrElement\n * @param {null|object} optionOverride\n * @returns {string|null}\n * @private\n */\n\n }, {\n key: '_formatOrUnformatOther',\n value: function _formatOrUnformatOther(isFormatting, valueOrStringOrElement) {\n var optionOverride = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n //FIXME test this\n // If the user wants to override the current element settings temporarily\n var settingsToUse = void 0;\n if (!_AutoNumericHelper2.default.isNull(optionOverride)) {\n settingsToUse = this._cloneAndMergeSettings(optionOverride);\n } else {\n settingsToUse = this.settings;\n }\n\n // Then the unformatting is done...\n var result = void 0;\n if (_AutoNumericHelper2.default.isElement(valueOrStringOrElement)) {\n // ...either directly on the DOM element value\n var elementValue = _AutoNumericHelper2.default.getElementValue(valueOrStringOrElement);\n if (isFormatting) {\n result = AutoNumeric.format(elementValue, settingsToUse);\n } else {\n result = AutoNumeric.unformat(elementValue, settingsToUse);\n }\n\n _AutoNumericHelper2.default.setElementValue(valueOrStringOrElement, result); //TODO Use `unformatAndSet` and `formatAndSet`instead\n\n return null;\n }\n\n // ...or on the given value\n if (isFormatting) {\n result = AutoNumeric.format(valueOrStringOrElement, settingsToUse);\n } else {\n result = AutoNumeric.unformat(valueOrStringOrElement, settingsToUse);\n }\n\n return result;\n }\n\n /**\n * Use the current AutoNumeric element settings to initialize the DOM element(s) given as a parameter.\n * Doing so will *link* the AutoNumeric elements together since they will share the same local AutoNumeric element list.\n * (cf. prototype pattern : https://en.wikipedia.org/wiki/Prototype_pattern)\n *\n * You can `init` either a single DOM element (in that case an AutoNumeric object will be returned), or an array of DOM elements or a string that will be used as a CSS selector. In the latter cases, an array of AutoNumeric objects will then be returned (or an empty array if nothing gets selected by the CSS selector).\n *\n * Use case : Once you have an AutoNumeric element already setup correctly with the right options, you can use it as many times you want to initialize as many other DOM elements as needed.\n * Note : this works only on elements that can be managed by autoNumeric.\n *\n * @param {HTMLElement|HTMLInputElement|Array|string} domElementOrArrayOrString\n * @param {boolean} attached If set to `false`, then the newly generated AutoNumeric element will not share the same local element list\n * @returns {AutoNumeric|[AutoNumeric]}\n */\n\n }, {\n key: 'init',\n value: function init(domElementOrArrayOrString) {\n var _this8 = this;\n\n var attached = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n var returnASingleAutoNumericObject = false; // By default, this function returns an array of AutoNumeric objects\n var domElementsArray = [];\n if (_AutoNumericHelper2.default.isString(domElementOrArrayOrString)) {\n domElementsArray = [].concat(_toConsumableArray(document.querySelectorAll(domElementOrArrayOrString))); // Convert a NodeList to an Array\n } else if (_AutoNumericHelper2.default.isElement(domElementOrArrayOrString)) {\n domElementsArray.push(domElementOrArrayOrString);\n returnASingleAutoNumericObject = true; // Special case when only one DOM element is passed as a parameter\n } else if (_AutoNumericHelper2.default.isArray(domElementOrArrayOrString)) {\n domElementsArray = domElementOrArrayOrString;\n } else {\n _AutoNumericHelper2.default.throwError('The given parameters to the \\'init\\' function are invalid.');\n }\n\n if (domElementsArray.length === 0) {\n _AutoNumericHelper2.default.warning('No valid DOM elements were given hence no AutoNumeric object were instantiated.', true);\n\n return [];\n }\n\n var currentLocalList = this._getLocalList();\n var autoNumericObjectsArray = [];\n\n // Instantiate (and link depending on `attached`) each AutoNumeric objects\n domElementsArray.forEach(function (domElement) {\n // Initialize the new AutoNumeric element\n var originalCreateLocalListSetting = _this8.settings.createLocalList;\n if (attached) {\n // Temporary variable to know if we should create the local list during the initialization (since we'll remove it afterwards)\n _this8.settings.createLocalList = false;\n }\n\n var newAutoNumericElement = new AutoNumeric(domElement, _AutoNumericHelper2.default.getElementValue(domElement), _this8.settings);\n\n // Set the common shared local list if needed\n // If the user wants to create a detached new AutoNumeric element, then skip the following step that bind the two elements together by default\n if (attached) {\n // 1) Set the local list reference to point to the initializer's one\n newAutoNumericElement._setLocalList(currentLocalList);\n\n // 2) Add the new element to that existing list\n _this8._addToLocalList(domElement, newAutoNumericElement); // Here we use the *new* AutoNumeric object reference to add to the local list, since we'll need the reference to `this` in the methods to points to that new AutoNumeric object.\n _this8.settings.createLocalList = originalCreateLocalListSetting;\n }\n\n autoNumericObjectsArray.push(newAutoNumericElement);\n });\n\n if (returnASingleAutoNumericObject) {\n // If a single DOM element was used as the parameter, then we return an AutoNumeric object directly\n return autoNumericObjectsArray[0];\n }\n\n // ...otherwise we return an Array of AutoNumeric objects\n return autoNumericObjectsArray;\n }\n\n /**\n * Reset the element value either to the empty string '', or the currency sign, depending on the `emptyInputBehavior` option value.\n * If you set the `forceClearAll` argument to `true`, then the `emptyInputBehavior` option is overridden and the whole input is clear, including any currency sign.\n *\n * @param {boolean} forceClearAll\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'clear',\n value: function clear() {\n var forceClearAll = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n\n if (forceClearAll) {\n var temporaryForcedOptions = {\n emptyInputBehavior: AutoNumeric.options.emptyInputBehavior.focus\n };\n this.set('', temporaryForcedOptions);\n } else {\n this.set('');\n }\n\n return this;\n }\n\n /**\n * Remove the autoNumeric data and event listeners from the element, but keep the element content intact.\n * This also clears the value from sessionStorage (or cookie, depending on browser supports).\n * Note: this does not remove the formatting.\n *\n * @example anElement.remove()\n */\n\n }, {\n key: 'remove',\n value: function remove() {\n this._removeValueFromPersistentStorage();\n this._removeEventListeners();\n this._removeWatcher();\n\n // Also remove the element from the local AutoNumeric list\n this._removeFromLocalList(this.domElement);\n // Also remove the element from the global AutoNumeric list\n this.constructor._removeFromGlobalList(this);\n }\n\n /**\n * Remove the autoNumeric data and event listeners from the element, and reset its value to the empty string ''.\n * This also clears the value from sessionStorage (or cookie, depending on browser supports).\n *\n * @example anElement.wipe()\n */\n\n }, {\n key: 'wipe',\n value: function wipe() {\n this._setElementValue('', false); // Do not send the 'AutoNumeric.events.formatted' event when wiping an AutoNumeric object\n this.remove();\n }\n\n /**\n * Remove the autoNumeric data and event listeners from the element, and delete the DOM element altogether\n */\n\n }, {\n key: 'nuke',\n value: function nuke() {\n this.remove();\n // Remove the element from the DOM\n this.domElement.parentNode.removeChild(this.domElement);\n }\n\n // Special functions that really work on the parent element, instead of the element itself\n\n /**\n * Return a reference to the parent element if it exists, otherwise return `null`.\n * If the parent form element as already been found, this directly return a reference to it.\n * However, you can force AutoNumeric to search again for its reference by passing `true` as a parameter to this method.\n * This method updates the `this.parentForm` attribute.\n *\n * In either case, whenever a new parent form is set for the current AutoNumeric element, we make sure to update the anCount and anFormHandler attributes on both the old form and the new one (for instance in case the user moved the input elements with `appendChild()` since AutoNumeric cannot not detect that).\n *\n * @param {boolean} forceSearch If set to `true`, the parent form is searched again, even if `this.parentForm` is already set.\n * @returns {HTMLFormElement|null}\n */\n\n }, {\n key: 'form',\n value: function form() {\n var forceSearch = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;\n\n if (forceSearch || _AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.parentForm)) {\n var newParentForm = this._getParentForm();\n if (!_AutoNumericHelper2.default.isNull(newParentForm) && newParentForm !== this.parentForm) {\n // If the current parent form exists and is different from the previous parent form\n\n // Search for all the AutoNumeric elements in the old parent form\n var oldANChildren = this._getFormAutoNumericChildren(this.parentForm);\n // Update the anCount with the correct number of AutoNumeric elements\n this.parentForm.dataset.anCount = oldANChildren.length;\n\n // Check if the new parent form already has a anFormHandler name\n if (this._hasFormHandlerFunction(newParentForm)) {\n this._incrementParentFormCounter(newParentForm); // Increment its counter\n } else {\n // Create one and set the anCount to 1\n this._storeFormHandlerFunction(newParentForm);\n this._initializeFormCounterToOne(newParentForm);\n }\n }\n\n this.parentForm = newParentForm;\n }\n\n return this.parentForm;\n }\n\n /**\n * Return an array of the AutoNumeric-managed elements for the given form element is passed, otherwise for the current `this.parentForm` element.\n *\n * @param {HTMLFormElement|null} formElement\n * @returns {Array.}\n * @private\n */\n\n }, {\n key: '_getFormAutoNumericChildren',\n value: function _getFormAutoNumericChildren(formElement) {\n var _this9 = this;\n\n // Search for all the child AutoNumeric elements in that parent form\n //XXX This only search for elements, not contenteditable non-input tag ones, for now\n var inputList = [].concat(_toConsumableArray(formElement.querySelectorAll('input')));\n\n return inputList.filter(function (input) {\n return _this9.constructor.isManagedByAutoNumeric(input);\n });\n }\n\n /**\n * Return a reference to the parent element if it exists, otherwise return `null`.\n *\n * @returns {HTMLFormElement|null}\n * @private\n */\n\n }, {\n key: '_getParentForm',\n value: function _getParentForm() {\n if (this.domElement.tagName.toLowerCase() === 'body') {\n return null;\n }\n\n var node = this.domElement;\n var tagName = void 0;\n do {\n node = node.parentNode;\n if (_AutoNumericHelper2.default.isNull(node)) {\n // Special case when using templates with frameworks like Vue.js, where the input element can be 'detached' when initializing the DOM structure\n return null;\n }\n\n if (node.tagName) {\n tagName = node.tagName.toLowerCase();\n } else {\n tagName = '';\n }\n\n if (tagName === 'body') {\n // Get out of the loop if we get up to the `` element\n break;\n }\n } while (tagName !== 'form');\n\n if (tagName === 'form') {\n return node;\n } else {\n return null;\n }\n }\n\n /**\n * Return a string in standard URL-encoded notation with the form input values being unformatted.\n * This string can be used as a query for instance.\n *\n * @returns {string}\n */\n\n }, {\n key: 'formNumericString',\n value: function formNumericString() {\n return this.constructor._serializeNumericString(this.form(), this.settings.serializeSpaces);\n }\n\n /**\n * Return a string in standard URL-encoded notation with the form input values being formatted.\n *\n * @returns {string}\n */\n\n }, {\n key: 'formFormatted',\n value: function formFormatted() {\n return this.constructor._serializeFormatted(this.form(), this.settings.serializeSpaces);\n }\n\n /**\n * Return a string in standard URL-encoded notation with the form input values, with localized values.\n * The default output format can be overridden by passing the option as a parameter.\n *\n * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n * @returns {string}\n */\n\n }, {\n key: 'formLocalized',\n value: function formLocalized() {\n var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n var outputFormatToUse = void 0;\n if (_AutoNumericHelper2.default.isNull(forcedOutputFormat)) {\n outputFormatToUse = this.settings.outputFormat;\n } else {\n outputFormatToUse = forcedOutputFormat;\n }\n\n return this.constructor._serializeLocalized(this.form(), this.settings.serializeSpaces, outputFormatToUse);\n }\n\n /**\n * Return an array containing an object for each form element.\n * Those objects are of the following structure `{ name: foo, value: '42' }`, where the `name` is the DOM element name, and the `value` is an unformatted numeric string.\n *\n * @returns {Array}\n */\n\n }, {\n key: 'formArrayNumericString',\n value: function formArrayNumericString() {\n return this.constructor._serializeNumericStringArray(this.form(), this.settings.serializeSpaces);\n }\n\n /**\n * Return an array containing an object for each form element.\n * Those objects are of the following structure `{ name: foo, value: '42' }`, where the `name` is the DOM element name, and the `value` is the formatted string.\n *\n * @returns {Array}\n */\n\n }, {\n key: 'formArrayFormatted',\n value: function formArrayFormatted() {\n return this.constructor._serializeFormattedArray(this.form(), this.settings.serializeSpaces);\n }\n\n /**\n * Return an array containing an object for each form element.\n * Those objects are of the following structure `{ name: foo, value: '42' }`, where the `name` is the DOM element name, and the `value` is the localized numeric string.\n *\n * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n * @returns {Array}\n */\n\n }, {\n key: 'formArrayLocalized',\n value: function formArrayLocalized() {\n var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n var outputFormatToUse = void 0;\n if (_AutoNumericHelper2.default.isNull(forcedOutputFormat)) {\n outputFormatToUse = this.settings.outputFormat;\n } else {\n outputFormatToUse = forcedOutputFormat;\n }\n\n return this.constructor._serializeLocalizedArray(this.form(), this.settings.serializeSpaces, outputFormatToUse);\n }\n\n /**\n * Return a JSON string containing an object representing the form input values.\n * This is based on the result of the `formArrayNumericString()` function.\n *\n * @returns {string}\n */\n\n }, {\n key: 'formJsonNumericString',\n value: function formJsonNumericString() {\n return JSON.stringify(this.formArrayNumericString());\n }\n\n /**\n * Return a JSON string containing an object representing the form input values.\n * This is based on the result of the `formArrayFormatted()` function.\n *\n * @returns {string}\n */\n\n }, {\n key: 'formJsonFormatted',\n value: function formJsonFormatted() {\n return JSON.stringify(this.formArrayFormatted());\n }\n\n /**\n * Return a JSON string containing an object representing the form input values.\n * This is based on the result of the `formArrayLocalized()` function.\n *\n * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n * @returns {string}\n */\n\n }, {\n key: 'formJsonLocalized',\n value: function formJsonLocalized() {\n var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n return JSON.stringify(this.formArrayLocalized(forcedOutputFormat));\n }\n\n /**\n * Unformat all the autoNumeric-managed elements that are a child of the parent element of this DOM element, to numeric strings\n *\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'formUnformat',\n value: function formUnformat() {\n //FIXME test this\n var inputs = this.constructor._getChildANInputElement(this.form());\n inputs.forEach(function (input) {\n AutoNumeric.getAutoNumericElement(input).unformat();\n });\n\n return this;\n }\n\n /**\n * Unformat all the autoNumeric-managed elements that are a child of the parent element of this DOM element, to localized strings\n *\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'formUnformatLocalized',\n value: function formUnformatLocalized() {\n //FIXME test this\n var inputs = this.constructor._getChildANInputElement(this.form());\n inputs.forEach(function (input) {\n AutoNumeric.getAutoNumericElement(input).unformatLocalized();\n });\n\n return this;\n }\n\n /**\n * Reformat all the autoNumeric-managed elements that are a child of the parent element of this DOM element\n *\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'formReformat',\n value: function formReformat() {\n //FIXME test this\n var inputs = this.constructor._getChildANInputElement(this.form());\n inputs.forEach(function (input) {\n AutoNumeric.getAutoNumericElement(input).reformat();\n });\n\n return this;\n }\n\n /**\n * Convert the input values to numeric strings, submit the form, then reformat those back.\n * The function can either take a callback, or not. If it doesn't, the default `form.submit()` function will be called.\n * Otherwise, it runs `callback(value)` with `value` being equal to the result of `formNumericString()`.\n *\n * @param {function|null} callback\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'formSubmitNumericString',\n value: function formSubmitNumericString() {\n var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n //FIXME test this\n if (_AutoNumericHelper2.default.isNull(callback)) {\n this.formUnformat();\n this.form().submit();\n this.formReformat();\n } else if (_AutoNumericHelper2.default.isFunction(callback)) {\n callback(this.formNumericString());\n } else {\n _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n }\n\n return this;\n }\n\n /**\n * Submit the form with the current formatted values.\n * The function can either take a callback, or not. If it doesn't, the default `form.submit()` function will be called.\n * Otherwise, it runs `callback(value)` with `value` being equal to the result of `formFormatted()`.\n *\n * @param {function|null} callback\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'formSubmitFormatted',\n value: function formSubmitFormatted() {\n var callback = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n //FIXME test this\n if (_AutoNumericHelper2.default.isNull(callback)) {\n this.form().submit();\n } else if (_AutoNumericHelper2.default.isFunction(callback)) {\n callback(this.formFormatted());\n } else {\n _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n }\n\n return this;\n }\n\n /**\n * Convert the input values to localized strings, submit the form, then reformat those back.\n * The function can either take a callback, or not. If it doesn't, the default `form.submit()` function will be called.\n * Otherwise, it runs `callback(value)` with `value` being equal to the result of `formLocalized()`.\n *\n * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n * @param {function|null} callback\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'formSubmitLocalized',\n value: function formSubmitLocalized() {\n var forcedOutputFormat = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n //FIXME test this\n if (_AutoNumericHelper2.default.isNull(callback)) {\n this.formUnformatLocalized();\n this.form().submit();\n this.formReformat();\n } else if (_AutoNumericHelper2.default.isFunction(callback)) {\n callback(this.formLocalized(forcedOutputFormat));\n } else {\n _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n }\n\n return this;\n }\n\n /**\n * Generate an array of numeric strings from the `` elements, and pass it to the given callback.\n * Under the hood, the array is generated via a call to `formArrayNumericString()`.\n *\n * @param {function} callback\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'formSubmitArrayNumericString',\n value: function formSubmitArrayNumericString(callback) {\n //FIXME test this\n if (_AutoNumericHelper2.default.isFunction(callback)) {\n callback(this.formArrayNumericString());\n } else {\n _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n }\n\n return this;\n }\n\n /**\n * Generate an array of the current formatted values from the `` elements, and pass it to the given callback.\n * Under the hood, the array is generated via a call to `formArrayFormatted()`.\n *\n * @param {function} callback\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'formSubmitArrayFormatted',\n value: function formSubmitArrayFormatted(callback) {\n //FIXME test this\n if (_AutoNumericHelper2.default.isFunction(callback)) {\n callback(this.formArrayFormatted());\n } else {\n _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n }\n\n return this;\n }\n\n /**\n * Generate an array of localized strings from the `` elements, and pass it to the given callback.\n * Under the hood, the array is generated via a call to `formArrayLocalized()`.\n *\n * @param {function} callback\n * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'formSubmitArrayLocalized',\n value: function formSubmitArrayLocalized(callback) {\n var forcedOutputFormat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n //FIXME test this\n if (_AutoNumericHelper2.default.isFunction(callback)) {\n callback(this.formArrayLocalized(forcedOutputFormat));\n } else {\n _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n }\n\n return this;\n }\n\n /**\n * Generate a JSON string with the numeric strings values from the `` elements, and pass it to the given callback.\n * Under the hood, the array is generated via a call to `formJsonNumericString()`.\n *\n * @param {function} callback\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'formSubmitJsonNumericString',\n value: function formSubmitJsonNumericString(callback) {\n //FIXME test this\n if (_AutoNumericHelper2.default.isFunction(callback)) {\n callback(this.formJsonNumericString());\n } else {\n _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n }\n\n return this;\n }\n\n /**\n * Generate a JSON string with the current formatted values from the `` elements, and pass it to the given callback.\n * Under the hood, the array is generated via a call to `formJsonFormatted()`.\n *\n * @param {function} callback\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'formSubmitJsonFormatted',\n value: function formSubmitJsonFormatted(callback) {\n //FIXME test this\n if (_AutoNumericHelper2.default.isFunction(callback)) {\n callback(this.formJsonFormatted());\n } else {\n _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n }\n\n return this;\n }\n\n /**\n * Generate a JSON string with the localized strings values from the `` elements, and pass it to the given callback.\n * Under the hood, the array is generated via a call to `formJsonLocalized()`.\n *\n * @param {function} callback\n * @param {null|string} forcedOutputFormat If set to something different than `null`, then this is used as an overriding outputFormat option\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'formSubmitJsonLocalized',\n value: function formSubmitJsonLocalized(callback) {\n var forcedOutputFormat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n //FIXME test this\n if (_AutoNumericHelper2.default.isFunction(callback)) {\n callback(this.formJsonLocalized(forcedOutputFormat));\n } else {\n _AutoNumericHelper2.default.throwError('The given callback is not a function.');\n }\n\n return this;\n }\n\n /**\n * Unformat the given AutoNumeric element, and update the `hoveredWithAlt` variable.\n *\n * @param {AutoNumeric} anElement\n * @private\n */\n\n }, {\n key: '_createLocalList',\n\n\n /**\n * Create a `Map` that will stores all the autoNumeric elements that are initialized from this current element.\n * @private\n */\n value: function _createLocalList() {\n this.autoNumericLocalList = new Map();\n this._addToLocalList(this.domElement);\n }\n\n /**\n * In some rare cases, you could want to delete the local list generated during the element initialization (in order to use another one instead for instance).\n * @private\n */\n\n }, {\n key: '_deleteLocalList',\n value: function _deleteLocalList() {\n delete this.autoNumericLocalList;\n }\n\n /**\n * Set the local list with the given Map object.\n *\n * @param {Map} localList\n * @private\n */\n\n }, {\n key: '_setLocalList',\n value: function _setLocalList(localList) {\n this.autoNumericLocalList = localList;\n }\n\n /**\n * Return the local list Map object.\n *\n * @returns {*|Map}\n * @private\n */\n\n }, {\n key: '_getLocalList',\n value: function _getLocalList() {\n return this.autoNumericLocalList;\n }\n\n /**\n * Return `true` if the AutoNumeric object has a local list defined already and has at least one element in it (itself usually).\n *\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_hasLocalList',\n value: function _hasLocalList() {\n return this.autoNumericLocalList instanceof Map && this.autoNumericLocalList.size !== 0;\n }\n\n /**\n * Add the given object to the local autoNumeric element list.\n * Note: in order to keep a coherent list, we only add DOM elements in it, not the autoNumeric object.\n *\n * @param {HTMLElement|HTMLInputElement} domElement\n * @param {AutoNumeric} autoNumericObject A reference to the AutoNumeric object that manage the given DOM element\n * @throws\n * @private\n */\n\n }, {\n key: '_addToLocalList',\n value: function _addToLocalList(domElement) {\n var autoNumericObject = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n if (_AutoNumericHelper2.default.isNull(autoNumericObject)) {\n autoNumericObject = this;\n }\n\n if (!_AutoNumericHelper2.default.isUndefined(this.autoNumericLocalList)) {\n this.autoNumericLocalList.set(domElement, autoNumericObject); // Use the DOM element as key, and the AutoNumeric object as the value\n } else {\n _AutoNumericHelper2.default.throwError('The local list provided does not exists when trying to add an element. [' + this.autoNumericLocalList + '] given.');\n }\n }\n\n /**\n * Remove the given object from the local autoNumeric element list.\n *\n * @param {HTMLElement|HTMLInputElement} domElement\n * @private\n */\n\n }, {\n key: '_removeFromLocalList',\n value: function _removeFromLocalList(domElement) {\n if (!_AutoNumericHelper2.default.isUndefined(this.autoNumericLocalList)) {\n this.autoNumericLocalList.delete(domElement);\n } else if (this.settings.createLocalList) {\n _AutoNumericHelper2.default.throwError('The local list provided does not exists when trying to remove an element. [' + this.autoNumericLocalList + '] given.');\n }\n }\n\n /**\n * Merge the `newSettings` given as parameters into the current element settings.\n *\n * WARNING: Using `Object.assign()` here means the merge is not recursive and only one depth is merged.\n * cf. http://stackoverflow.com/a/39188108/2834898\n * cf. tests on http://codepen.io/AnotherLinuxUser/pen/KaJORq?editors=0011\n *\n * @param {object} newSettings\n * @private\n */\n\n }, {\n key: '_mergeSettings',\n value: function _mergeSettings() {\n for (var _len3 = arguments.length, newSettings = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n newSettings[_key3] = arguments[_key3];\n }\n\n _extends.apply(undefined, [this.settings].concat(newSettings));\n }\n\n /**\n * Return a new object with the current element settings merged with the new settings.\n *\n * @param {object} newSettings\n * @returns {object}\n * @private\n */\n\n }, {\n key: '_cloneAndMergeSettings',\n value: function _cloneAndMergeSettings() {\n var result = {};\n\n for (var _len4 = arguments.length, newSettings = Array(_len4), _key4 = 0; _key4 < _len4; _key4++) {\n newSettings[_key4] = arguments[_key4];\n }\n\n _extends.apply(undefined, [result, this.settings].concat(newSettings));\n\n return result;\n }\n\n /**\n * Validate the given option object.\n * If the options are valid, this function returns nothing, otherwise if the options are invalid, this function throws an error.\n *\n * This tests if the options are not conflicting and are well formatted.\n * This function is lenient since it only tests the settings properties ; it ignores any other properties the options object could have.\n *\n * @param {*} userOptions\n * @param {Boolean} shouldExtendDefaultOptions If `true`, then this function will extends the `userOptions` passed by the user, with the default options.\n * @param {object|null} originalOptions The user can pass the original options (and not the one that are generated from the default settings and the various usability corrections), in order to add compatibility and conflicts checks.\n * @throws Error This throws if the `userOptions` are not valid\n */\n\n }, {\n key: '_updatePredefinedOptions',\n\n\n // Pre-defined options can be called to update the current default options with their specificities\n //XXX A better way would be to not initialize first, but that's not possible since `new` is called first and we do not pass the language options (ie. `French`) to the constructor\n\n /**\n * Update the AutoNumeric object with the predefined options, and possibly some option overrides.\n *\n * @param {object} predefinedOption\n * @param {object} optionOverride\n * @private\n * @returns {AutoNumeric}\n */\n value: function _updatePredefinedOptions(predefinedOption) {\n var optionOverride = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n if (!_AutoNumericHelper2.default.isNull(optionOverride)) {\n this._mergeSettings(predefinedOption, optionOverride);\n this.update(this.settings);\n } else {\n this.update(predefinedOption);\n }\n\n return this;\n }\n\n /**\n * Update the settings to use the French pre-defined language options.\n * Those pre-defined options can be overridden by passing an option object as a parameter.\n *\n * @param {object} optionOverride\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'french',\n value: function french() {\n var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().French, optionOverride);\n\n return this;\n }\n\n /**\n * Update the settings to use the North American pre-defined language options.\n * Those pre-defined options can be overridden by passing an option object as a parameter.\n *\n * @param {object} optionOverride\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'northAmerican',\n value: function northAmerican() {\n var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().NorthAmerican, optionOverride);\n\n return this;\n }\n\n /**\n * Update the settings to use the British pre-defined language options.\n * Those pre-defined options can be overridden by passing an option object as a parameter.\n *\n * @param {object} optionOverride\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'british',\n value: function british() {\n var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().British, optionOverride);\n\n return this;\n }\n\n /**\n * Update the settings to use the Swiss pre-defined language options.\n * Those pre-defined options can be overridden by passing an option object as a parameter.\n *\n * @param {object} optionOverride\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'swiss',\n value: function swiss() {\n var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().Swiss, optionOverride);\n\n return this;\n }\n\n /**\n * Update the settings to use the Japanese pre-defined language options.\n * Those pre-defined options can be overridden by passing an option object as a parameter.\n *\n * @param {object} optionOverride\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'japanese',\n value: function japanese() {\n var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().Japanese, optionOverride);\n\n return this;\n }\n\n /**\n * Update the settings to use the Spanish pre-defined language options.\n * Those pre-defined options can be overridden by passing an option object as a parameter.\n *\n * @param {object} optionOverride\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'spanish',\n value: function spanish() {\n var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().Spanish, optionOverride);\n\n return this;\n }\n\n /**\n * Update the settings to use the Chinese pre-defined language options.\n * Those pre-defined options can be overridden by passing an option object as a parameter.\n *\n * @param {object} optionOverride\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'chinese',\n value: function chinese() {\n var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().Chinese, optionOverride);\n\n return this;\n }\n\n /**\n * Update the settings to use the Brazilian pre-defined language options.\n * Those pre-defined options can be overridden by passing an option object as a parameter.\n *\n * @param {object} optionOverride\n * @returns {AutoNumeric}\n */\n\n }, {\n key: 'brazilian',\n value: function brazilian() {\n var optionOverride = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n this._updatePredefinedOptions(AutoNumeric.getPredefinedOptions().Brazilian, optionOverride);\n\n return this;\n }\n\n // Internal private functions\n /**\n * Run any callbacks found in the settings object in order to set the settings value back.\n * Any parameter can have a callback defined.\n * The callback takes the current AutoNumeric element as the first argument, and the key name as the second.\n * @example callback(this, 'currencySymbol')\n */\n\n }, {\n key: '_runCallbacksFoundInTheSettingsObject',\n value: function _runCallbacksFoundInTheSettingsObject() {\n //FIXME test this\n // Loops through the this.settings object (option array) to find the following\n for (var key in this.settings) {\n if (this.settings.hasOwnProperty(key)) {\n var value = this.settings[key];\n\n if (typeof value === 'function') {\n this.settings[key] = value(this, key);\n } else {\n // Calls the attached function from the html5 data. For instance: \n var htmlAttribute = this.domElement.getAttribute(key); //TODO Use `dataset` instead of `getAttribute` when we won't need to support obsolete browsers\n htmlAttribute = _AutoNumericHelper2.default.camelize(htmlAttribute);\n if (typeof this.settings[htmlAttribute] === 'function') {\n this.settings[key] = htmlAttribute(this, key);\n }\n }\n }\n }\n }\n\n /**\n * Keep track if the settings configuration leads to a trailing negative sign (only when the raw value is negative), so we do not have to test the settings values every time we need to know that.\n * `isTrailingNegative` is set to `true` if the settings result in a trailing negative character, `false` otherwise.\n * Note: This returns `true` even if the raw value is positive.\n * @private\n */\n\n }, {\n key: '_setTrailingNegativeSignInfo',\n value: function _setTrailingNegativeSignInfo() {\n this.isTrailingNegative = this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix && this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.suffix || this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix && (this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.left || this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.right);\n }\n\n /**\n * Strip all the unwanted non-number characters.\n * However it does not reorder the localized negative sign.\n *\n * @param {string} s\n * @param {object} settings\n * @param {boolean} stripZeros If set to `false`, then the leading zero(s) are not stripped, otherwise if set to `true`, the `leadingZero` option is followed\n * @param {boolean} isFocused If the element is focused, then this is `true`\n * @returns {string}\n * @private\n */\n\n }, {\n key: '_modifyNegativeSignAndDecimalCharacterForRawValue',\n\n\n /**\n * Modify the negative sign and the decimal character of the given string value to an hyphen (-) and a dot (.) in order to make that value 'typecastable' to a real number.\n *\n * @param {string} s The formatted value\n * @returns {string} The value with the 'normal' minus sign and decimal character\n */\n value: function _modifyNegativeSignAndDecimalCharacterForRawValue(s) {\n if (this.settings.decimalCharacter !== '.') {\n s = s.replace(this.settings.decimalCharacter, '.');\n }\n\n if (this.settings.negativeSignCharacter !== '-' && this.settings.isNegativeSignAllowed) {\n s = s.replace(this.settings.negativeSignCharacter, '-');\n }\n\n if (!s.match(/\\d/)) {\n // The default value returned by `get` is not formatted with decimals\n s += '0';\n }\n\n return s;\n }\n\n /**\n * Modify the negative sign and the decimal character to use those defined in the settings.\n *\n * @param {string} s\n * @param {object} settings\n * @returns {string}\n */\n\n }, {\n key: '_initialCaretPosition',\n\n\n /**\n * Calculate where to put the caret position on focus if the element content is not selected.\n * This calculation is affected by the `caretPositionOnFocus` option which can be either `null`, `'start'`, `'end'`, `'decimalLeft'` or 'decimalRight'`, and will decide where to put the caret (on the left or right of the value or the decimal character, respectively) :\n * - `null` : the caret position is not forced\n * - `'start'` : the caret is positioned on the left hand side of the value\n * - `'end'` : the caret is positioned on the right hand side of the value\n * - `'decimalLeft'` : the caret is positioned on the left side of the decimal character\n * - `'decimalRight'` : the caret is positioned on the right side of the decimal character\n *\n * @param {string} value The formatted string stripped of the currency symbol and negative/positive sign\n * @returns {number}\n * @throws\n * @private\n */\n value: function _initialCaretPosition(value) {\n if (_AutoNumericHelper2.default.isNull(this.settings.caretPositionOnFocus) && this.settings.selectOnFocus === AutoNumeric.options.selectOnFocus.doNotSelect) {\n _AutoNumericHelper2.default.throwError('`_initialCaretPosition()` should never be called when the `caretPositionOnFocus` option is `null`.');\n }\n\n var isValueNegative = this.rawValue < 0;\n var isZeroOrHasNoValue = _AutoNumericHelper2.default.isZeroOrHasNoValue(value);\n var totalLength = value.length;\n\n var valueSize = 0;\n var integerSize = 0;\n var hasDecimalChar = false;\n var offsetDecimalChar = 0;\n if (this.settings.caretPositionOnFocus !== AutoNumeric.options.caretPositionOnFocus.start) {\n value = value.replace(this.settings.negativeSignCharacter, '');\n value = value.replace(this.settings.positiveSignCharacter, '');\n value = value.replace(this.settings.currencySymbol, '');\n valueSize = value.length;\n hasDecimalChar = _AutoNumericHelper2.default.contains(value, this.settings.decimalCharacter);\n\n if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.decimalLeft || this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.decimalRight) {\n if (hasDecimalChar) {\n integerSize = value.indexOf(this.settings.decimalCharacter);\n offsetDecimalChar = this.settings.decimalCharacter.length;\n } else {\n integerSize = valueSize;\n offsetDecimalChar = 0;\n }\n }\n }\n\n var signToUse = '';\n if (isValueNegative) {\n signToUse = this.settings.negativeSignCharacter;\n } else if (this.settings.showPositiveSign && !isZeroOrHasNoValue) {\n signToUse = this.settings.positiveSignCharacter;\n }\n\n var positiveNegativeSignSize = signToUse.length;\n var currencySymbolSize = this.settings.currencySymbol.length;\n\n // Calculate the caret position based on `currencySymbolPlacement`, `negativePositiveSignPlacement` and `caretPositionOnFocus`\n var caretPosition = void 0;\n if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix) {\n if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.start) {\n if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n switch (this.settings.negativePositiveSignPlacement) {\n case AutoNumeric.options.negativePositiveSignPlacement.prefix: // +€|12.34\n case AutoNumeric.options.negativePositiveSignPlacement.left: // +€|12.34\n case AutoNumeric.options.negativePositiveSignPlacement.right:\n // €+|12.34\n caretPosition = positiveNegativeSignSize + currencySymbolSize;\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.suffix:\n // €|12.34+\n caretPosition = currencySymbolSize;\n break;\n }\n } else {\n // €|12.34\n caretPosition = currencySymbolSize;\n }\n } else if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.end) {\n if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n switch (this.settings.negativePositiveSignPlacement) {\n case AutoNumeric.options.negativePositiveSignPlacement.prefix: // +€12.34|\n case AutoNumeric.options.negativePositiveSignPlacement.left: // +€12.34|\n case AutoNumeric.options.negativePositiveSignPlacement.right:\n // €+12.34|\n caretPosition = totalLength;\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.suffix:\n // €12.34|+\n caretPosition = currencySymbolSize + valueSize;\n break;\n }\n } else {\n // €12.34|\n caretPosition = totalLength;\n }\n } else if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.decimalLeft) {\n if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n switch (this.settings.negativePositiveSignPlacement) {\n case AutoNumeric.options.negativePositiveSignPlacement.prefix: // +€12|.34\n case AutoNumeric.options.negativePositiveSignPlacement.left: // +€12|.34\n case AutoNumeric.options.negativePositiveSignPlacement.right:\n // €+12|.34\n caretPosition = positiveNegativeSignSize + currencySymbolSize + integerSize;\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.suffix:\n // €12|.34+\n caretPosition = currencySymbolSize + integerSize;\n break;\n }\n } else {\n // €12|.34\n caretPosition = currencySymbolSize + integerSize;\n }\n } else if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.decimalRight) {\n if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n switch (this.settings.negativePositiveSignPlacement) {\n case AutoNumeric.options.negativePositiveSignPlacement.prefix: // +€12.|34\n case AutoNumeric.options.negativePositiveSignPlacement.left: // +€12.|34\n case AutoNumeric.options.negativePositiveSignPlacement.right:\n // €+12.|34\n caretPosition = positiveNegativeSignSize + currencySymbolSize + integerSize + offsetDecimalChar;\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.suffix:\n // €12.|34+\n caretPosition = currencySymbolSize + integerSize + offsetDecimalChar;\n break;\n }\n } else {\n // €12.|34\n caretPosition = currencySymbolSize + integerSize + offsetDecimalChar;\n }\n }\n } else if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.start) {\n if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n switch (this.settings.negativePositiveSignPlacement) {\n case AutoNumeric.options.negativePositiveSignPlacement.suffix: // |12.34€+\n case AutoNumeric.options.negativePositiveSignPlacement.right: // |12.34€+\n case AutoNumeric.options.negativePositiveSignPlacement.left:\n // |12.34+€\n caretPosition = 0;\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.prefix:\n // +|12.34€\n caretPosition = positiveNegativeSignSize;\n break;\n }\n } else {\n // |12.34€\n caretPosition = 0;\n }\n } else if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.end) {\n if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n switch (this.settings.negativePositiveSignPlacement) {\n case AutoNumeric.options.negativePositiveSignPlacement.suffix: // 12.34|€+\n case AutoNumeric.options.negativePositiveSignPlacement.right: // 12.34|€+\n case AutoNumeric.options.negativePositiveSignPlacement.left:\n // 12.34|+€\n caretPosition = valueSize;\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.prefix:\n // +12.34|€\n caretPosition = positiveNegativeSignSize + valueSize;\n break;\n }\n } else {\n // 12.34|€\n caretPosition = valueSize;\n }\n } else if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.decimalLeft) {\n if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n switch (this.settings.negativePositiveSignPlacement) {\n case AutoNumeric.options.negativePositiveSignPlacement.suffix: // 12|.34€+\n case AutoNumeric.options.negativePositiveSignPlacement.right: // 12|.34€+\n case AutoNumeric.options.negativePositiveSignPlacement.left:\n // 12|.34+€\n caretPosition = integerSize;\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.prefix:\n // +12|.34€\n caretPosition = positiveNegativeSignSize + integerSize;\n break;\n }\n } else {\n // 12|.34€\n caretPosition = integerSize;\n }\n } else if (this.settings.caretPositionOnFocus === AutoNumeric.options.caretPositionOnFocus.decimalRight) {\n if (this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && this.settings.showPositiveSign && !isZeroOrHasNoValue)) {\n switch (this.settings.negativePositiveSignPlacement) {\n case AutoNumeric.options.negativePositiveSignPlacement.suffix: // 12.|34€+\n case AutoNumeric.options.negativePositiveSignPlacement.right: // 12.|34€+\n case AutoNumeric.options.negativePositiveSignPlacement.left:\n // 12.|34+€\n caretPosition = integerSize + offsetDecimalChar;\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.prefix:\n // +12.|34€\n caretPosition = positiveNegativeSignSize + integerSize + offsetDecimalChar;\n break;\n }\n } else {\n // 12.|34€\n caretPosition = integerSize + offsetDecimalChar;\n }\n }\n }\n\n return caretPosition;\n }\n\n /**\n * Truncate the trailing zeroes to the given number of decimal places\n *\n * @param {string} roundedInputValue\n * @param {int} decimalPlacesNeeded The number of decimal places to keep\n * @returns {string}\n */\n\n }, {\n key: '_keepAnOriginalSettingsCopy',\n\n\n /**\n * Original settings saved for use when the `decimalPlacesShownOnFocus` and `showOnlyNumbersOnFocus` options are used.\n * Those original settings are used exclusively in the `focusin` and `focusout` event handlers.\n */\n value: function _keepAnOriginalSettingsCopy() {\n this.originalDigitGroupSeparator = this.settings.digitGroupSeparator;\n this.originalCurrencySymbol = this.settings.currencySymbol;\n this.originalSuffixText = this.settings.suffixText;\n }\n\n /**\n * Original settings saved for use when `decimalPlacesShownOnFocus` & `showOnlyNumbersOnFocus` options are being used.\n * This is taken from Quirksmode.\n *\n * @param {string} name\n * @returns {*}\n */\n\n }, {\n key: '_trimLeadingAndTrailingZeros',\n\n\n /**\n * Removes any zeros in excess in the front and back of the given `value`, according to the `settings`.\n * This also manages the cases where the decimal point is on the far left or far right of the `value`.\n *\n * @param {string} value\n * @returns {string|null}\n */\n value: function _trimLeadingAndTrailingZeros(value) {\n // Return the empty string is the value is already empty. This prevent converting that value to '0'.\n if (value === '' || value === null) {\n return value;\n }\n\n if (this.settings.leadingZero !== AutoNumeric.options.leadingZero.keep) {\n if (Number(value) === 0) {\n // Return '0' if the value is zero\n return '0';\n }\n\n // Trim the leading zeros, while leaving one zero to the left of the decimal point if needed\n value = value.replace(/^(-)?0+(?=\\d)/g, '$1');\n }\n\n //TODO remove this from that function and use `trimPaddedZerosFromDecimalPlaces()` instead\n // Trim the trailing zeros after the last decimal place not being a zero (ie. 1.2300 -> 1.23)\n if (_AutoNumericHelper2.default.contains(value, '.')) {\n value = value.replace(/(\\.[0-9]*?)0+$/, '$1');\n }\n\n // Remove any trailing decimal point\n value = value.replace(/\\.$/, '');\n\n return value;\n }\n\n /**\n * Generate the name for the persistent stored data variable\n * @private\n */\n\n }, {\n key: '_setPersistentStorageName',\n value: function _setPersistentStorageName() {\n if (this.settings.saveValueToSessionStorage) {\n if (this.domElement.name !== '' && !_AutoNumericHelper2.default.isUndefined(this.domElement.name)) {\n this.rawValueStorageName = '' + this.storageNamePrefix + decodeURIComponent(this.domElement.name);\n } else {\n this.rawValueStorageName = '' + this.storageNamePrefix + this.domElement.id;\n }\n }\n }\n\n /**\n * Save the raw Value into sessionStorage or a cookie depending on what the browser is supporting.\n * @private\n */\n\n }, {\n key: '_saveValueToPersistentStorage',\n value: function _saveValueToPersistentStorage() {\n if (this.settings.saveValueToSessionStorage) {\n if (this.sessionStorageAvailable) {\n sessionStorage.setItem(this.rawValueStorageName, this.rawValue);\n } else {\n // Use cookies for obsolete browsers that do not support sessionStorage (ie. IE 6 & 7)\n document.cookie = this.rawValueStorageName + '=' + this.rawValue + '; expires= ; path=/';\n }\n }\n }\n\n /**\n * Retrieve the raw value from sessionStorage or the cookie depending on what the browser is supporting.\n *\n * @returns {*}\n * @private\n */\n\n }, {\n key: '_getValueFromPersistentStorage',\n value: function _getValueFromPersistentStorage() {\n if (this.settings.saveValueToSessionStorage) {\n var result = void 0;\n if (this.sessionStorageAvailable) {\n result = sessionStorage.getItem(this.rawValueStorageName);\n } else {\n result = this._readCookie(this.rawValueStorageName);\n }\n\n return result;\n }\n\n _AutoNumericHelper2.default.warning('`_getValueFromPersistentStorage()` is called but `settings.saveValueToSessionStorage` is false. There must be an error that needs fixing.', this.settings.showWarnings);\n\n return null;\n }\n\n /**\n * Remove the raw value data from sessionStorage or the cookie depending on what the browser is supporting.\n * @private\n */\n\n }, {\n key: '_removeValueFromPersistentStorage',\n value: function _removeValueFromPersistentStorage() {\n if (this.settings.saveValueToSessionStorage) {\n if (this.sessionStorageAvailable) {\n sessionStorage.removeItem(this.rawValueStorageName);\n } else {\n var date = new Date();\n date.setTime(date.getTime() - 86400000); // -86400000 === -1 * 24 * 60 * 60 * 1000\n var expires = '; expires=' + date.toUTCString();\n document.cookie = this.rawValueStorageName + '=\\'\\' ;' + expires + '; path=/';\n }\n }\n }\n\n /**\n * Handler for 'focusin' and 'mouseenter' events\n * On focusin, multiple things happens :\n * - If `Alt` is pressed, unformat\n * - Remove the separators if `showOnlyNumbersOnFocus` is set\n * - Depending on `emptyInputBehavior`, reformat the empty formatted value\n * - Display the correct number of decimal places (on focus/blur)\n * - Place the caret correctly if the element is empty\n *\n * Note: On focusin, the `rawValue` is never changed. Only the formatted value can be modified.\n *\n * @param {Event} e\n * @private\n */\n\n }, {\n key: '_onFocusInAndMouseEnter',\n value: function _onFocusInAndMouseEnter(e) {\n //TODO Create separate handlers for the focus and mouseenter events\n this.isEditing = false; // Just in case no `keyUp` event have been sent (ie. if the user lost the focus from the current window while typing)\n this.rawValueOnFocus = this.rawValue; // Keep track of the initial rawValue. This is needed to define if a change event must be dispatched later\n\n if (this.settings.unformatOnHover && e.type === 'mouseenter' && e.altKey) {\n this.constructor._unformatAltHovered(this);\n\n return;\n }\n\n if (e.type === 'focus') {\n //TODO Move that back to the 'focus' event handler when the separation between the 'focus' and 'mouseenter' handler will be done\n // Keep track if the element is currently focused\n this.isFocused = true;\n }\n\n if (e.type === 'focus' && this.settings.unformatOnHover && this.hoveredWithAlt) {\n this.constructor._reformatAltHovered(this);\n }\n\n if (e.type === 'focus' || e.type === 'mouseenter' && !this.isFocused) {\n var elementValueToSet = null; // Store the value we want to set on the element, and only call `_setElementValue()` once\n\n if (this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.focus && this.rawValue < 0 && this.settings.negativeBracketsTypeOnBlur !== null && this.settings.isNegativeSignAllowed) {\n //FIXME this is called a second time in _addGroupSeparators too. Prevent this, if possible.\n // Only remove the brackets if the value is negative\n elementValueToSet = this.constructor._removeBrackets(_AutoNumericHelper2.default.getElementValue(this.domElement), this.settings);\n //FIXME The element value is set here, why continue and set it again later in that same parent logic block?\n }\n\n // Use the `rawValue`, multiplied by `rawValueDivisor` if defined\n var rawValueToFormat = this._getRawValueToFormat(this.rawValue);\n\n // Modify the element value according to the number of decimal places to show on focus or the `showOnlyNumbersOnFocus` option\n if (rawValueToFormat !== '') {\n // Round the given value according to the object state (focus/unfocused)\n var roundedValue = void 0;\n if (this.isFocused) {\n roundedValue = this.constructor._roundFormattedValueShownOnFocus(rawValueToFormat, this.settings);\n } else {\n roundedValue = this.constructor._roundFormattedValueShownOnBlur(rawValueToFormat, this.settings);\n }\n\n if (this.settings.showOnlyNumbersOnFocus === AutoNumeric.options.showOnlyNumbersOnFocus.onlyNumbers) {\n //TODO Use a `this.settingsOverride` object instead of modifying the `this.settings` object\n this.settings.digitGroupSeparator = '';\n this.settings.currencySymbol = '';\n this.settings.suffixText = '';\n elementValueToSet = roundedValue.replace('.', this.settings.decimalCharacter);\n } else {\n var formattedValue = void 0;\n if (_AutoNumericHelper2.default.isNull(roundedValue)) {\n formattedValue = '';\n } else {\n formattedValue = this.constructor._addGroupSeparators(roundedValue.replace('.', this.settings.decimalCharacter), this.settings, this.isFocused, rawValueToFormat);\n }\n\n elementValueToSet = formattedValue;\n }\n }\n\n // In order to send a 'native' change event when blurring the input, we need to first store the initial input value on focus.\n if (_AutoNumericHelper2.default.isNull(elementValueToSet)) {\n this.valueOnFocus = '';\n } else {\n this.valueOnFocus = elementValueToSet;\n }\n\n this.lastVal = this.valueOnFocus;\n var isEmptyValue = this.constructor._isElementValueEmptyOrOnlyTheNegativeSign(this.valueOnFocus, this.settings);\n var orderedValue = this.constructor._orderValueCurrencySymbolAndSuffixText(this.valueOnFocus, this.settings, true); // This displays the currency sign on hover even if the rawValue is empty\n var orderedValueTest = isEmptyValue && orderedValue !== '' && this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.focus;\n if (orderedValueTest) {\n elementValueToSet = orderedValue;\n }\n\n if (!_AutoNumericHelper2.default.isNull(elementValueToSet)) {\n this._setElementValue(elementValueToSet);\n }\n\n if (orderedValueTest && orderedValue === this.settings.currencySymbol && this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n // If there is a currency symbol and its on the right hand side, then we place the caret accordingly on the far left side\n _AutoNumericHelper2.default.setElementSelection(e.target, 0);\n }\n }\n }\n\n /**\n * Handler for the 'focus' event.\n * We update the info of the focused state in the `this.isFocused` variable when the element gets focused.\n * @private\n */\n\n }, {\n key: '_onFocus',\n value: function _onFocus() {\n if (this.settings.isCancellable) {\n // Save the current unformatted value for later use by the 'cancellable' feature\n this._saveCancellableValue();\n }\n }\n\n /**\n * Handler for the 'focusin' event.\n * This is called before the 'focus' event, and is necessary to change the selection on focus under Firefox for instance.\n *\n * @param {Event} e\n * @private\n */\n\n }, {\n key: '_onFocusIn',\n value: function _onFocusIn(e) {\n if (this.settings.selectOnFocus) {\n // The whole input content is selected on focus (following the `selectOnFocus` and `selectNumberOnly` options)\n //XXX Firefox <47 does not respect this selection...Oh well.\n this.select();\n } else {\n // Or we decide where to put the caret using the `caretPositionOnFocus` option\n if (!_AutoNumericHelper2.default.isNull(this.settings.caretPositionOnFocus)) {\n _AutoNumericHelper2.default.setElementSelection(e.target, this._initialCaretPosition(_AutoNumericHelper2.default.getElementValue(this.domElement)));\n }\n }\n }\n\n /**\n * Handler for 'keydown' events.\n * The user just started pushing any key, hence one event is sent.\n *\n * Note :\n * By default a 'normal' input output those events in the right order when inputting a character key (ie. 'a') :\n * - keydown\n * - keypress\n * - input\n * - keyup\n *\n * ...when inputting a modifier key (ie. 'ctrl') :\n * - keydown\n * - keyup\n *\n * If 'delete' or 'backspace' is entered, the following events are sent :\n * - keydown\n * - input\n * - keyup\n *\n * If 'enter' is entered and the value has not changed, the following events are sent :\n * - keydown\n * - keypress\n * - keyup\n *\n * If 'enter' is entered and the value has been changed, the following events are sent :\n * - keydown\n * - keypress\n * - change\n * - keyup\n *\n * When a paste is done, the following events are sent :\n * - input (if paste is done with the mouse)\n *\n * - keydown (if paste is done with ctrl+v)\n * - keydown\n * - input\n * - keyup\n * - keyup\n *\n * @param {KeyboardEvent} e\n */\n\n }, {\n key: '_onKeydown',\n value: function _onKeydown(e) {\n this.formatted = false; // Keep track if the element has been formatted already. If that's the case, prevent further format calculations.\n this.isEditing = true; // Keep track if the user is currently editing the element manually\n\n if (!this.isFocused && this.settings.unformatOnHover && e.altKey && this.domElement === _AutoNumericHelper2.default.getHoveredElement()) {\n // Here I prevent calling _unformatAltHovered if the element is already focused, since the global 'keydown' listener will pick it up as well\n this.constructor._unformatAltHovered(this);\n\n return;\n }\n\n this._updateEventKeyInfo(e);\n this.initialValueOnKeydown = _AutoNumericHelper2.default.getElementValue(e.target); // This is needed in `onKeyup()` to check if the value as changed during the key press\n this.initialRawValueOnKeydown = this.rawValue;\n\n if (this.domElement.readOnly) {\n this.processed = true;\n\n return;\n }\n\n if (this.eventKey === _AutoNumericEnum2.default.keyName.Esc) {\n //XXX The default 'Escape' key behavior differs between Firefox and Chrome, Firefox already having a built-in 'cancellable-like' feature. This is why we call `e.preventDefault()` here instead of just when `isCancellable` is set to `true`. This allow us to keep the same behavior across browsers.\n e.preventDefault();\n\n if (this.settings.isCancellable) {\n // If the user wants to cancel his modifications:\n // We set back the saved value\n if (this.rawValue !== this.savedCancellableValue) {\n // Do not set the value again if it has not changed\n this.set(this.savedCancellableValue);\n // And we need to send an 'input' event when setting back the initial value in order to make other scripts aware of the value change...\n this._triggerEvent(AutoNumeric.events.native.input, e.target);\n }\n }\n\n // ..and lastly we update the caret selection, even if the option `isCancellable` is false\n this.select();\n //TODO Add an option to select either the integer or decimal part with `Esc`\n }\n\n // The \"enter\" key throws a `change` event if the raw value has changed since the `focus` event\n var targetValue = _AutoNumericHelper2.default.getElementValue(e.target);\n if (this.eventKey === _AutoNumericEnum2.default.keyName.Enter && this.rawValue !== this.rawValueOnFocus) {\n this._triggerEvent(AutoNumeric.events.native.change, e.target);\n this.valueOnFocus = targetValue;\n this.rawValueOnFocus = this.rawValue;\n\n if (this.settings.isCancellable) {\n // If the user activated the 'cancellable' feature, we save the validated value when 'Enter' is hit\n this._saveCancellableValue();\n }\n }\n\n this._updateInternalProperties(e);\n\n if (this._processNonPrintableKeysAndShortcuts(e)) {\n this.processed = true;\n\n return;\n }\n\n // Check if the key is a delete/backspace key\n if (this.eventKey === _AutoNumericEnum2.default.keyName.Backspace || this.eventKey === _AutoNumericEnum2.default.keyName.Delete) {\n this._processCharacterDeletion(); // Because backspace and delete only triggers keydown and keyup events, not keypress\n this.processed = true;\n this._formatValue(e);\n\n // If and only if the resulting value has changed after that backspace/delete, then we have to send an 'input' event like browsers normally do.\n targetValue = _AutoNumericHelper2.default.getElementValue(e.target); // Update the value since it could have been changed during the deletion\n if (targetValue !== this.lastVal && this.throwInput) {\n // Throw an input event when a character deletion is detected\n this._triggerEvent(AutoNumeric.events.native.input, e.target);\n e.preventDefault(); // ...and immediately prevent the browser to delete a second character\n }\n\n this.lastVal = targetValue;\n this.throwInput = true;\n }\n }\n\n /**\n * Handler for 'keypress' events.\n * The user is still pressing the key, which will output a character (ie. '2') continuously until it releases the key.\n * Note: 'keypress' events are not sent for delete keys like Backspace/Delete.\n *\n * @param {KeyboardEvent} e\n */\n\n }, {\n key: '_onKeypress',\n value: function _onKeypress(e) {\n if (this.eventKey === _AutoNumericEnum2.default.keyName.Insert) {\n return;\n }\n\n var processed = this.processed;\n this._updateInternalProperties(e);\n\n if (this._processNonPrintableKeysAndShortcuts(e)) {\n return;\n }\n\n if (processed) {\n e.preventDefault();\n\n return;\n }\n\n var isCharacterInsertionAllowed = this._processCharacterInsertion();\n if (isCharacterInsertionAllowed) {\n this._formatValue(e);\n var targetValue = _AutoNumericHelper2.default.getElementValue(e.target);\n if (targetValue !== this.lastVal && this.throwInput) {\n // Throws input event on adding a character\n this._triggerEvent(AutoNumeric.events.native.input, e.target);\n e.preventDefault(); // ...and immediately prevent the browser to add a second character\n } else {\n if ((this.eventKey === this.settings.decimalCharacter || this.eventKey === this.settings.decimalCharacterAlternative) && _AutoNumericHelper2.default.getElementSelection(e.target).start === _AutoNumericHelper2.default.getElementSelection(e.target).end && _AutoNumericHelper2.default.getElementSelection(e.target).start === targetValue.indexOf(this.settings.decimalCharacter)) {\n var position = _AutoNumericHelper2.default.getElementSelection(e.target).start + 1;\n _AutoNumericHelper2.default.setElementSelection(e.target, position);\n }\n\n e.preventDefault();\n }\n\n this.lastVal = _AutoNumericHelper2.default.getElementValue(e.target);\n this.throwInput = true;\n\n return;\n }\n\n e.preventDefault();\n }\n\n /**\n * Handler for 'keyup' events.\n * The user just released any key, hence one event is sent.\n *\n * @param {KeyboardEvent} e\n */\n\n }, {\n key: '_onKeyup',\n value: function _onKeyup(e) {\n this.isEditing = false;\n\n if (this.settings.isCancellable && this.eventKey === _AutoNumericEnum2.default.keyName.Esc) {\n // If the user wants to cancel its modifications, we drop the 'keyup' event for the Esc key\n e.preventDefault();\n\n return;\n }\n\n // Manage the undo/redo events\n if (this.eventKey === _AutoNumericEnum2.default.keyName.Z || this.eventKey === _AutoNumericEnum2.default.keyName.z) {\n if (e.ctrlKey && e.shiftKey) {\n // Redo\n e.preventDefault();\n this._historyTableRedo();\n this.onGoingRedo = true;\n\n return;\n } else if (e.ctrlKey && !e.shiftKey) {\n if (this.onGoingRedo) {\n // Prevent an 'undo' to be launch when releasing the shift key before the ctrl key after a 'redo' shortcut\n this.onGoingRedo = false;\n } else {\n e.preventDefault();\n // Undo\n this._historyTableUndo();\n\n return;\n }\n }\n }\n\n if (this.onGoingRedo && (e.ctrlKey || e.shiftKey)) {\n // Special case where if the user has entered `Control+Shift+z`, then release `z`, keeping `Control` or `Shift` pressed, then `this.onGoingRedo` is never changed back to `false` when the user release `Control` or `Shift`\n this.onGoingRedo = false;\n }\n\n // Manage the Cut event\n if ((e.ctrlKey || e.metaKey) && this.eventKey === _AutoNumericEnum2.default.keyName.x) {\n // Save the caret position at the start of the selection\n var caretPosition = _AutoNumericHelper2.default.getElementSelection(this.domElement).start;\n // Convert the remaining 'formatted' numbers in a Js number\n var cutNumber = this.constructor._toNumericValue(_AutoNumericHelper2.default.getElementValue(e.target), this.settings);\n // Try to set that value with `set()`\n this.set(cutNumber);\n // Set back the initial caret position\n this._setCaretPosition(caretPosition);\n }\n\n // Manage the reformat when hovered with the Alt key pressed\n if (this.eventKey === _AutoNumericEnum2.default.keyName.Alt && this.hoveredWithAlt) {\n this.constructor._reformatAltHovered(this);\n\n return;\n }\n\n this._updateInternalProperties(e);\n\n var skip = this._processNonPrintableKeysAndShortcuts(e);\n delete this.valuePartsBeforePaste;\n var targetValue = _AutoNumericHelper2.default.getElementValue(e.target);\n if (skip || targetValue === '') {\n return;\n }\n\n // Added to properly place the caret when only the currency sign is present\n if (targetValue === this.settings.currencySymbol) {\n if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n _AutoNumericHelper2.default.setElementSelection(e.target, 0);\n } else {\n _AutoNumericHelper2.default.setElementSelection(e.target, this.settings.currencySymbol.length);\n }\n } else if (this.eventKey === _AutoNumericEnum2.default.keyName.Tab) {\n _AutoNumericHelper2.default.setElementSelection(e.target, 0, targetValue.length);\n }\n\n if (targetValue === this.settings.suffixText || this.rawValue === '' && this.settings.currencySymbol !== '' && this.settings.suffixText !== '') {\n _AutoNumericHelper2.default.setElementSelection(e.target, 0);\n }\n\n // Saves the extended decimal to preserve the data when navigating away from the page\n if (this.settings.decimalPlacesShownOnFocus !== null) {\n this._saveValueToPersistentStorage();\n }\n\n if (!this.formatted) {\n //TODO Is this line needed? Considering that onKeydown and onKeypress both finish by setting it to false...\n this._formatValue(e);\n }\n\n // Force the `rawValue` update on Android Chrome\n this._saveRawValueForAndroid();\n\n // If the input value has changed during the key press event chain, an event is sent to alert that a formatting has been done (cf. Issue #187)\n if (targetValue !== this.initialValueOnKeydown) {\n this._triggerEvent(AutoNumeric.events.formatted, e.target, {\n oldValue: this.initialValueOnKeydown,\n newValue: targetValue,\n oldRawValue: this.initialRawValueOnKeydown,\n newRawValue: this.rawValue,\n isPristine: this.isPristine(false),\n error: null,\n aNElement: this\n });\n }\n\n // Update the selection of the current element of the history table\n if (this.historyTable.length > 1) {\n var selection = _AutoNumericHelper2.default.getElementSelection(this.domElement);\n this.selectionStart = selection.start;\n this.selectionEnd = selection.end;\n this.historyTable[this.historyTableIndex].start = this.selectionStart;\n this.historyTable[this.historyTableIndex].end = this.selectionEnd;\n }\n }\n\n /**\n * On Android Chrome, the `rawValue` is not updated when the user changes the input value.\n * This function updates the `rawValue` accordingly.\n * @private\n */\n\n }, {\n key: '_saveRawValueForAndroid',\n value: function _saveRawValueForAndroid() {\n if (this.eventKey === _AutoNumericEnum2.default.keyName.AndroidDefault) {\n var normalizedValue = this.constructor._stripAllNonNumberCharactersExceptCustomDecimalChar(this.getFormatted(), this.settings, true, this.isFocused);\n normalizedValue = this.constructor._convertToNumericString(normalizedValue, this.settings);\n\n this._setRawValue(normalizedValue);\n }\n }\n\n /**\n * Handler for 'focusout' events\n * On focusout, multiple things happens :\n * - The element value is formatted back if the `Alt` key was pressed,\n * - The element value is formatted back if `showOnlyNumbersOnFocus` was set to only show numbers,\n * - The element value is multiplied by `rawValueDivisor` on `blur`\n *\n * Note: On focusout, the `rawValue` is never changed. Only the formatted value can be modified.\n *\n * @param {Event} e\n */\n\n }, {\n key: '_onFocusOutAndMouseLeave',\n value: function _onFocusOutAndMouseLeave(e) {\n //TODO Create separate handlers for blur and mouseleave\n this.isEditing = false; // Just in case no `keyUp` event have been sent (if the user lost the focus to the window while typing)\n\n //FIXME Do not call `set()` if the current raw value is the same as the one we are trying to set (currently, on focus out, `set()` is always called, even if the value has not changed\n if (this.settings.unformatOnHover && e.type === 'mouseleave' && this.hoveredWithAlt) {\n this.constructor._reformatAltHovered(this);\n\n return;\n }\n\n if (e.type === 'mouseleave' && !this.isFocused || e.type === 'blur') {\n this._saveValueToPersistentStorage();\n if (this.settings.showOnlyNumbersOnFocus === AutoNumeric.options.showOnlyNumbersOnFocus.onlyNumbers) {\n this.settings.digitGroupSeparator = this.originalDigitGroupSeparator;\n this.settings.currencySymbol = this.originalCurrencySymbol;\n this.settings.suffixText = this.originalSuffixText;\n }\n\n // Use the rawValue, multiplied by `rawValueDivisor` if defined\n var rawValueToFormat = this._getRawValueToFormat(this.rawValue);\n var isRawValueNull = _AutoNumericHelper2.default.isNull(rawValueToFormat);\n\n var _constructor$_checkIf5 = this.constructor._checkIfInRangeWithOverrideOption(rawValueToFormat, this.settings),\n _constructor$_checkIf6 = _slicedToArray(_constructor$_checkIf5, 2),\n minTest = _constructor$_checkIf6[0],\n maxTest = _constructor$_checkIf6[1];\n\n // Directly set the formatted value if the `rawValue` is found in `valuesToStrings`\n\n\n var elementValueIsAlreadySet = false;\n if (rawValueToFormat !== '' && !isRawValueNull) {\n if (!minTest) {\n this._triggerEvent(AutoNumeric.events.minRangeExceeded, this.domElement);\n }\n\n if (!maxTest) {\n this._triggerEvent(AutoNumeric.events.maxRangeExceeded, this.domElement);\n }\n\n if (this.settings.valuesToStrings && this._checkValuesToStrings(rawValueToFormat)) {\n // Set the formatted value with the corresponding string\n this._setElementValue(this.settings.valuesToStrings[rawValueToFormat]);\n elementValueIsAlreadySet = true;\n }\n }\n\n // Only generate the formatted value if no `valuesToStrings` have been found\n if (!elementValueIsAlreadySet) {\n var value = void 0;\n if (isRawValueNull || rawValueToFormat === '') {\n value = rawValueToFormat;\n } else {\n value = String(rawValueToFormat);\n }\n\n if (rawValueToFormat !== '' && !isRawValueNull) {\n if (minTest && maxTest && !this.constructor._isElementValueEmptyOrOnlyTheNegativeSign(rawValueToFormat, this.settings)) {\n value = this._modifyNegativeSignAndDecimalCharacterForRawValue(value);\n\n if (this.settings.divisorWhenUnfocused && !_AutoNumericHelper2.default.isNull(value)) {\n value = value / this.settings.divisorWhenUnfocused;\n value = value.toString();\n }\n\n value = this.constructor._roundFormattedValueShownOnBlur(value, this.settings);\n value = this.constructor._modifyNegativeSignAndDecimalCharacterForFormattedValue(value, this.settings);\n } else {\n if (!minTest) {\n this._triggerEvent(AutoNumeric.events.minRangeExceeded, this.domElement);\n }\n\n if (!maxTest) {\n this._triggerEvent(AutoNumeric.events.maxRangeExceeded, this.domElement);\n }\n }\n } else if (rawValueToFormat === '' && this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.zero) {\n this._setRawValue('0');\n value = this.constructor._roundValue('0', this.settings, 0);\n }\n\n var groupedValue = this.constructor._orderValueCurrencySymbolAndSuffixText(value, this.settings, false);\n if (!(this.constructor._isElementValueEmptyOrOnlyTheNegativeSign(value, this.settings) || isRawValueNull && this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.null)) {\n groupedValue = this.constructor._addGroupSeparators(value, this.settings, false, rawValueToFormat);\n }\n\n // Testing for `allowDecimalPadding.never` or `allowDecimalPadding.floats` is needed to make sure we do not keep a trailing decimalCharacter (like '500.') in the element, since the raw value would still be a correctly formatted integer ('500')\n if (groupedValue !== rawValueToFormat || rawValueToFormat === '' || // This make sure we get rid on any currency symbol or suffix that might have been added on focus\n this.settings.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.never || this.settings.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.floats) {\n if (this.settings.symbolWhenUnfocused && rawValueToFormat !== '' && rawValueToFormat !== null) {\n groupedValue = '' + groupedValue + this.settings.symbolWhenUnfocused;\n }\n\n this._setElementValue(groupedValue);\n }\n }\n\n this._onBlur(e);\n }\n }\n\n /**\n * Handler for 'paste' event\n *\n * @param {Event|ClipboardEvent} e\n */\n\n }, {\n key: '_onPaste',\n value: function _onPaste(e) {\n //FIXME When pasting '000' on a thousand group selection, the whole selection gets deleted, and only one '0' is pasted (cf. issue #302)\n // The event is prevented by default, since otherwise the user would be able to paste invalid characters into the input\n e.preventDefault();\n\n if (this.settings.readOnly || this.domElement.readOnly || this.domElement.disabled) {\n // Do not allow pasting in a readonly element (fix issue #505)\n return;\n }\n\n var rawPastedText = void 0;\n if (window.clipboardData && window.clipboardData.getData) {\n // Special case for the obsolete and non-standard IE browsers 10 and 11\n rawPastedText = window.clipboardData.getData('Text');\n } else if (e.clipboardData && e.clipboardData.getData) {\n // Normal case with modern browsers\n rawPastedText = e.clipboardData.getData('text/plain');\n } else {\n _AutoNumericHelper2.default.throwError('Unable to retrieve the pasted value. Please use a modern browser (ie. Firefox or Chromium).');\n }\n\n // Fix for firefox paste handling on `contenteditable` elements where `e.target` is the the text node, not the element\n var eventTarget = void 0;\n if (!e.target.tagName) {\n eventTarget = e.explicitOriginalTarget;\n } else {\n eventTarget = e.target;\n }\n\n // 0. Special case if the user has selected all the input text before pasting\n var initialFormattedValue = _AutoNumericHelper2.default.getElementValue(eventTarget);\n var selectionStart = eventTarget.selectionStart || 0;\n var selectionEnd = eventTarget.selectionEnd || 0;\n var selectionSize = selectionEnd - selectionStart;\n\n if (selectionSize === initialFormattedValue.length) {\n // If all the element text is selected\n //TODO Refactor this with the tests below\n // Since the whole element content will be replaced, no need to complicate things and directly test for the validity of the pasted content, then set the `rawValue` and caret position (fix issue #482)\n // 1. Strip all thousand separators, brackets and currency sign, and convert the decimal character to a dot\n var _untranslatedPastedText = this._preparePastedText(rawPastedText);\n var pastedRawValue = _AutoNumericHelper2.default.arabicToLatinNumbers(_untranslatedPastedText, false, false, false); // Allow pasting arabic numbers\n\n // 2. Check that the paste is a valid number once it has been normalized to a raw value\n if (pastedRawValue === '.' || pastedRawValue === '' || pastedRawValue !== '.' && !_AutoNumericHelper2.default.isNumber(pastedRawValue)) {\n this.formatted = true; // This prevent the `keyup` event on the `v` key during a paste to try to format an empty value.\n // If the user tries to paste a single decimal character (that has been translated to '.' already) or the empty value, ignore the paste\n if (this.settings.onInvalidPaste === AutoNumeric.options.onInvalidPaste.error) {\n _AutoNumericHelper2.default.throwError('The pasted value \\'' + rawPastedText + '\\' is not a valid paste content.');\n }\n\n return;\n }\n\n // 3. Then try to set it as the new value. The `set()` method will run the additional tests (ie. limits) as needed.\n this.set(pastedRawValue);\n this.formatted = true;\n\n // 4. On a 'normal' non-autoNumeric input, an `input` event is sent when a paste is done. We mimic that.\n this._triggerEvent(AutoNumeric.events.native.input, eventTarget);\n\n // 5. Return since the job is done\n return;\n }\n\n // 1. Check if the paste has a negative sign (only if it's the first character), and store that information for later use\n var isPasteNegative = _AutoNumericHelper2.default.isNegativeStrict(rawPastedText, this.settings.negativeSignCharacter);\n if (isPasteNegative) {\n // 1a. Remove the negative sign from the pasted text\n rawPastedText = rawPastedText.slice(1, rawPastedText.length);\n }\n\n // 2. Strip all thousand separators, brackets and currency sign, and convert the decimal character to a dot\n var untranslatedPastedText = this._preparePastedText(rawPastedText);\n\n var pastedText = void 0;\n if (untranslatedPastedText === '.') {\n // Special case : If the user tries to paste a single decimal character (that has been translated to '.' already)\n pastedText = '.';\n } else {\n // Normal case\n // Allow pasting arabic numbers\n pastedText = _AutoNumericHelper2.default.arabicToLatinNumbers(untranslatedPastedText, false, false, false);\n }\n\n // 3. Test if the paste is valid (only has numbers and eventually a decimal character). If it's not valid, stop here.\n if (pastedText !== '.' && (!_AutoNumericHelper2.default.isNumber(pastedText) || pastedText === '')) {\n this.formatted = true; // This prevent the `keyup` event on the `v` key during a paste to try to format an empty value (fix issue #484)\n if (this.settings.onInvalidPaste === AutoNumeric.options.onInvalidPaste.error) {\n _AutoNumericHelper2.default.throwError('The pasted value \\'' + rawPastedText + '\\' is not a valid paste content.');\n }\n\n return;\n }\n\n // 4. Calculate the paste result\n var caretPositionOnInitialTextAfterPasting = void 0;\n var isInitialValueNegative = _AutoNumericHelper2.default.isNegativeStrict(this.getNumericString(), this.settings.negativeSignCharacter);\n var isPasteNegativeAndInitialValueIsPositive = void 0;\n var result = void 0;\n\n // If the pasted content is negative, then the result will be negative too\n if (isPasteNegative && !isInitialValueNegative) {\n isInitialValueNegative = true;\n isPasteNegativeAndInitialValueIsPositive = true;\n } else {\n isPasteNegativeAndInitialValueIsPositive = false;\n }\n\n var leftPartContainedADot = false;\n var leftPart = void 0;\n var rightPart = void 0;\n switch (this.settings.onInvalidPaste) {\n /* 4a. Truncate paste behavior:\n * Insert as many numbers as possible on the right hand side of the caret from the pasted text content, until the input reach its range limit.\n * If there is more characters in the clipboard once a limit is reached, drop the extraneous characters.\n * Otherwise paste all the numbers in the clipboard.\n * While doing so, we check if the result is within the minimum and maximum values allowed, and stop as soon as we encounter one of those.\n *\n * 4b. Replace paste behavior:\n * Idem than the 'truncate' paste behavior, except that when a range limit is hit, we try to replace the subsequent initial numbers with the pasted ones, until we hit the range limit a second (and last) time, or we run out of numbers to paste\n */\n /* eslint no-case-declarations: 0 */\n case AutoNumeric.options.onInvalidPaste.truncate:\n case AutoNumeric.options.onInvalidPaste.replace:\n var leftFormattedPart = initialFormattedValue.slice(0, selectionStart);\n var rightFormattedPart = initialFormattedValue.slice(selectionEnd, initialFormattedValue.length);\n\n if (selectionStart !== selectionEnd) {\n // a. If there is a selection, remove the selected part, and return the left and right part\n result = this._preparePastedText(leftFormattedPart + rightFormattedPart);\n } else {\n // b. Else if this is only one caret (and therefore no selection), then return the left and right part\n result = this._preparePastedText(initialFormattedValue);\n }\n\n // Add back the negative sign if needed\n if (isInitialValueNegative) {\n result = _AutoNumericHelper2.default.setRawNegativeSign(result);\n }\n\n // Build the unformatted result string\n caretPositionOnInitialTextAfterPasting = _AutoNumericHelper2.default.convertCharacterCountToIndexPosition(_AutoNumericHelper2.default.countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, this.settings.decimalCharacter));\n if (isPasteNegativeAndInitialValueIsPositive) {\n // If the initial paste is negative and the initial value is not, then I must offset the caret position by one place to the right to take the additional hyphen into account\n caretPositionOnInitialTextAfterPasting++;\n //TODO Quid if the negative sign is not on the left (negativePositiveSignPlacement and currencySymbolPlacement)?\n }\n\n leftPart = result.slice(0, caretPositionOnInitialTextAfterPasting);\n rightPart = result.slice(caretPositionOnInitialTextAfterPasting, result.length);\n if (pastedText === '.') {\n if (_AutoNumericHelper2.default.contains(leftPart, '.')) {\n // If I remove a dot here, then I need to update the caret position (decrement it by 1) when positioning it\n // To do so, we keep that info in order to modify the caret position later\n leftPartContainedADot = true;\n leftPart = leftPart.replace('.', '');\n }\n\n rightPart = rightPart.replace('.', '');\n }\n // -- Here, we are good to go to continue on the same basis\n\n // c. Add numbers one by one at the caret position, while testing if the result is valid and within the range of the minimum and maximum value\n // Continue until you either run out of numbers to paste, or that you get out of the range limits\n var minParse = _AutoNumericHelper2.default.parseStr(this.settings.minimumValue);\n var maxParse = _AutoNumericHelper2.default.parseStr(this.settings.maximumValue);\n var lastGoodKnownResult = result; // This is set as the default, in case we do not add even one number\n var pastedTextIndex = 0;\n var modifiedLeftPart = leftPart;\n\n while (pastedTextIndex < pastedText.length) {\n // Modify the result with another pasted character\n modifiedLeftPart += pastedText[pastedTextIndex];\n result = modifiedLeftPart + rightPart;\n\n // Check the range limits\n if (!this.constructor._checkIfInRange(result, minParse, maxParse)) {\n // The result is out of the range limits, stop the loop here\n break;\n }\n\n // Save the last good known result\n lastGoodKnownResult = result;\n\n // Update the local variables for the next loop\n pastedTextIndex++;\n }\n\n // Update the last caret position where to insert a new number\n caretPositionOnInitialTextAfterPasting += pastedTextIndex;\n\n //XXX Here we have the result for the `truncate` option\n if (this.settings.onInvalidPaste === AutoNumeric.options.onInvalidPaste.truncate) {\n //TODO If the user as defined a truncate callback and there are still some numbers (that will be dropped), then call this callback with the initial paste as well as the remaining numbers\n result = lastGoodKnownResult;\n\n if (leftPartContainedADot) {\n // If a dot has been removed for the part on the left of the caret, we decrement the caret index position\n caretPositionOnInitialTextAfterPasting--;\n }\n break;\n }\n //XXX ...else we need to continue modifying the result for the 'replace' option\n\n // d. Until there are numbers to paste, replace the initial numbers one by one, and still do the range test.\n // Stop when you have no more numbers to paste, or if you are out of the range limits.\n // If you do get to the range limits, use the previous known good value within those limits.\n // Note: The numbers are replaced one by one, in the integer then decimal part, while ignoring the decimal character\n //TODO What should happen if the user try to paste a decimal number? Should we override the current initial decimal character in favor of this new one? If we do, then we have to recalculate the vMin/vMax from the start in order to take into account this new decimal character position..\n var lastGoodKnownResultIndex = caretPositionOnInitialTextAfterPasting;\n var lastGoodKnownResultSize = lastGoodKnownResult.length;\n\n while (pastedTextIndex < pastedText.length && lastGoodKnownResultIndex < lastGoodKnownResultSize) {\n if (lastGoodKnownResult[lastGoodKnownResultIndex] === '.') {\n // We skip the decimal character 'replacement'. That way, we do not change the decimal character position regarding the remaining numbers.\n lastGoodKnownResultIndex++;\n continue;\n }\n\n // This replace one character at a time\n result = _AutoNumericHelper2.default.replaceCharAt(lastGoodKnownResult, lastGoodKnownResultIndex, pastedText[pastedTextIndex]);\n\n // Check the range limits\n if (!this.constructor._checkIfInRange(result, minParse, maxParse)) {\n // The result is out of the range limits, stop the loop here\n break;\n }\n\n // Save the last good known result\n lastGoodKnownResult = result;\n\n // Update the local variables for the next loop\n pastedTextIndex++;\n lastGoodKnownResultIndex++;\n }\n\n // Update the last caret position where to insert a new number\n caretPositionOnInitialTextAfterPasting = lastGoodKnownResultIndex;\n\n if (leftPartContainedADot) {\n // If a dot has been removed for the part on the left of the caret, we decrement the caret index position\n caretPositionOnInitialTextAfterPasting--;\n }\n\n result = lastGoodKnownResult;\n\n break;\n /* 4c. Normal paste behavior:\n * Insert the pasted number inside the current unformatted text, at the right caret position or selection\n */\n case AutoNumeric.options.onInvalidPaste.error:\n case AutoNumeric.options.onInvalidPaste.ignore:\n case AutoNumeric.options.onInvalidPaste.clamp:\n default:\n // 1. Generate the unformatted result\n var leftFormattedPart2 = initialFormattedValue.slice(0, selectionStart);\n var rightFormattedPart2 = initialFormattedValue.slice(selectionEnd, initialFormattedValue.length);\n\n if (selectionStart !== selectionEnd) {\n // a. If there is a selection, remove the selected part, and return the left and right part\n result = this._preparePastedText(leftFormattedPart2 + rightFormattedPart2);\n } else {\n // b. Else if this is only one caret (and therefore no selection), then return the left and right part\n result = this._preparePastedText(initialFormattedValue);\n }\n\n // Add back the negative sign if needed\n if (isInitialValueNegative) {\n result = _AutoNumericHelper2.default.setRawNegativeSign(result);\n }\n\n // Build the unformatted result string\n caretPositionOnInitialTextAfterPasting = _AutoNumericHelper2.default.convertCharacterCountToIndexPosition(_AutoNumericHelper2.default.countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, this.settings.decimalCharacter));\n if (isPasteNegativeAndInitialValueIsPositive) {\n // If the initial paste is negative and the initial value is not, then I must offset the caret position by one place to the right to take the additional hyphen into account\n caretPositionOnInitialTextAfterPasting++;\n //TODO Quid if the negative sign is not on the left (negativePositiveSignPlacement and currencySymbolPlacement)?\n }\n\n leftPart = result.slice(0, caretPositionOnInitialTextAfterPasting);\n rightPart = result.slice(caretPositionOnInitialTextAfterPasting, result.length);\n if (pastedText === '.') {\n // If the user only paste a single decimal character, then we remove the previously existing one (if any)\n if (_AutoNumericHelper2.default.contains(leftPart, '.')) {\n // If I remove a dot here, then I need to update the caret position (decrement it by 1) when positioning it\n // To do so, we keep that info in order to modify the caret position later\n leftPartContainedADot = true;\n leftPart = leftPart.replace('.', '');\n }\n\n rightPart = rightPart.replace('.', '');\n }\n // -- Here, we are good to go to continue on the same basis\n\n // Generate the unformatted result\n result = '' + leftPart + pastedText + rightPart;\n\n // 2. Calculate the caret position in the unformatted value, for later use\n if (selectionStart === selectionEnd) {\n // There is no selection, then the caret position is set after the pasted text\n var indexWherePastedTextHasBeenInserted = _AutoNumericHelper2.default.convertCharacterCountToIndexPosition(_AutoNumericHelper2.default.countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, this.settings.decimalCharacter));\n caretPositionOnInitialTextAfterPasting = indexWherePastedTextHasBeenInserted + pastedText.length; // I must not count the characters that have been removed from the pasted text (ie. '.')\n } else if (rightPart === '') {\n // If the user selected from the caret position to the end of the input (on the far right)\n caretPositionOnInitialTextAfterPasting = _AutoNumericHelper2.default.convertCharacterCountToIndexPosition(_AutoNumericHelper2.default.countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionStart, this.settings.decimalCharacter)) + pastedText.length;\n } else {\n // Normal case\n var indexSelectionEndInRawValue = _AutoNumericHelper2.default.convertCharacterCountToIndexPosition(_AutoNumericHelper2.default.countNumberCharactersOnTheCaretLeftSide(initialFormattedValue, selectionEnd, this.settings.decimalCharacter));\n\n // Here I must not count the characters that have been removed from the pasted text (ie. '.'), or the thousand separators in the initial selected text\n var selectedText = _AutoNumericHelper2.default.getElementValue(eventTarget).slice(selectionStart, selectionEnd);\n caretPositionOnInitialTextAfterPasting = indexSelectionEndInRawValue - selectionSize + _AutoNumericHelper2.default.countCharInText(this.settings.digitGroupSeparator, selectedText) + pastedText.length;\n }\n\n // Modify the caret position for special cases, only if the whole input has not been selected\n if (isPasteNegativeAndInitialValueIsPositive) {\n // If the pasted value has a negative sign ('-'), but the initial value does not, offset the index by one\n caretPositionOnInitialTextAfterPasting++;\n }\n\n if (leftPartContainedADot) {\n // If a dot has been removed for the part on the left of the caret, we decrement the caret index position\n caretPositionOnInitialTextAfterPasting--;\n }\n }\n\n // 5. Check if the result is a valid number, if not, drop the paste and do nothing.\n if (!_AutoNumericHelper2.default.isNumber(result) || result === '') {\n if (this.settings.onInvalidPaste === AutoNumeric.options.onInvalidPaste.error) {\n _AutoNumericHelper2.default.throwError('The pasted value \\'' + rawPastedText + '\\' would result into an invalid content \\'' + result + '\\'.'); //TODO Should we send a warning instead of throwing an error?\n //TODO This is not DRY ; refactor with above\n }\n return;\n }\n\n // 6. If it's a valid number, check if it falls inside the minimum and maximum value. If this fails, modify the value following this procedure :\n /*\n * If 'error' (this is the default) :\n * - Normal paste behavior.\n * - Try to set the new value, if it fails, then throw an error in the console.\n * - Do not change the input value, do not change the current selection.\n * If 'ignore' :\n * - Normal paste behavior.\n * - Try to set the new value, if it fails, do nothing more.\n * - Do not change the input value, do not change the current selection.\n * If 'clamp' :\n * - Normal paste behavior.\n * - Try to set the new value, if it fails, set the value to the minimum or maximum limit, whichever is closest to the\n * paste result.\n * - Change the caret position to be positioned on the left hand side of the decimal character.\n * If 'truncate' :\n * - Truncate paste behavior.\n * - Try to set the new value, until it fails (if the result is out of the min and max value limits).\n * - Drop the remaining non-pasted numbers, and keep the last known non-failing result.\n * - Change the caret position to be positioned after the last pasted character.\n * If 'replace' :\n * - Replace paste behavior.\n * - Try to set the new value, until it fails (if the result is out of the min and max value limits).\n * - Then try to replace as many numbers as possible with the pasted ones. Once it fails, keep the last known non-failing result.\n * - Change the caret position to be positioned after the last pasted character.\n */\n var valueHasBeenSet = false;\n var valueHasBeenClamped = false;\n try {\n this.set(result);\n valueHasBeenSet = true;\n } catch (error) {\n var clampedValue = void 0;\n switch (this.settings.onInvalidPaste) {\n case AutoNumeric.options.onInvalidPaste.clamp:\n clampedValue = _AutoNumericHelper2.default.clampToRangeLimits(result, this.settings);\n try {\n this.set(clampedValue);\n } catch (error) {\n _AutoNumericHelper2.default.throwError('Fatal error: Unable to set the clamped value \\'' + clampedValue + '\\'.');\n }\n\n valueHasBeenClamped = true;\n valueHasBeenSet = true;\n result = clampedValue; // This is used only for setting the caret position later\n break;\n case AutoNumeric.options.onInvalidPaste.error:\n case AutoNumeric.options.onInvalidPaste.truncate:\n case AutoNumeric.options.onInvalidPaste.replace:\n // Throw an error message\n _AutoNumericHelper2.default.throwError('The pasted value \\'' + rawPastedText + '\\' results in a value \\'' + result + '\\' that is outside of the minimum [' + this.settings.minimumValue + '] and maximum [' + this.settings.maximumValue + '] value range.');\n // falls through\n case AutoNumeric.options.onInvalidPaste.ignore:\n // Do nothing\n // falls through\n default:\n return; // ...and nothing else should be changed\n }\n }\n\n // 7. Then lastly, set the caret position at the right logical place\n var targetValue = _AutoNumericHelper2.default.getElementValue(eventTarget);\n var caretPositionInFormattedNumber = void 0;\n if (valueHasBeenSet) {\n switch (this.settings.onInvalidPaste) {\n case AutoNumeric.options.onInvalidPaste.clamp:\n if (valueHasBeenClamped) {\n if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n _AutoNumericHelper2.default.setElementSelection(eventTarget, targetValue.length - this.settings.currencySymbol.length); // This puts the caret on the right of the last decimal place\n } else {\n _AutoNumericHelper2.default.setElementSelection(eventTarget, targetValue.length); // ..and this on the far right\n }\n\n break;\n } // else if the value has not been clamped, the default behavior is used...\n // falls through\n case AutoNumeric.options.onInvalidPaste.error:\n case AutoNumeric.options.onInvalidPaste.ignore:\n case AutoNumeric.options.onInvalidPaste.truncate:\n case AutoNumeric.options.onInvalidPaste.replace:\n default:\n // Whenever one or multiple characters are pasted, this means we have to manage the potential thousand separators that could be added by the formatting\n caretPositionInFormattedNumber = _AutoNumericHelper2.default.findCaretPositionInFormattedNumber(result, caretPositionOnInitialTextAfterPasting, targetValue, this.settings.decimalCharacter);\n _AutoNumericHelper2.default.setElementSelection(eventTarget, caretPositionInFormattedNumber);\n }\n }\n\n // 8. We make sure we send an input event only if the result is different than the initial value before the paste\n if (valueHasBeenSet && initialFormattedValue !== targetValue) {\n // On a 'normal' non-autoNumeric input, an `input` event is sent when a paste is done. We mimic that.\n this._triggerEvent(AutoNumeric.events.native.input, eventTarget);\n }\n }\n\n /**\n * When focusing out of the input, we check if the value has changed, and if it has, then we send a `change` event (since the native one would have been prevented by `e.preventDefault()` called in the other event listeners).\n * We also update the info of the focused state in the `this.isFocused` variable.\n *\n * @param {Event} e\n */\n\n }, {\n key: '_onBlur',\n value: function _onBlur(e) {\n // Keep track if the element is currently focused\n this.isFocused = false;\n // Keep track if the user is currently editing the element\n this.isEditing = false;\n\n // Send a `change` event if the raw value has been changed since the last focus or 'enter' validation\n if (this.rawValue !== this.rawValueOnFocus) {\n this._triggerEvent(AutoNumeric.events.native.change, e.target);\n }\n\n this.rawValueOnFocus = void 0; // Reset the tracker\n }\n\n /**\n * Handler for 'wheel' event\n *\n * @param {WheelEvent} e\n */\n\n }, {\n key: '_onWheel',\n value: function _onWheel(e) {\n if (this.settings.readOnly || this.domElement.readOnly || this.domElement.disabled) {\n // Do not allow scrolling in a readonly element (fix issue #541)\n return;\n }\n\n if (this.settings.modifyValueOnWheel) {\n if (this.settings.wheelOn === AutoNumeric.options.wheelOn.focus) {\n if (this.isFocused) {\n if (!e.shiftKey) {\n this.wheelAction(e);\n }\n } else if (e.shiftKey) {\n this.wheelAction(e);\n }\n } else if (this.settings.wheelOn === AutoNumeric.options.wheelOn.hover) {\n if (!e.shiftKey) {\n this.wheelAction(e);\n } else {\n // Note: When not `defaultPrevented`, Shift + mouse wheel is reserved by the browsers for horizontal scrolling.\n // Hence, using the Shift key with the `wheelOn` 'hover' option will only scroll the page if we prevent the default behavior\n e.preventDefault(); // Do not scroll horizontally\n\n // Scroll vertically\n window.scrollBy(0, _AutoNumericHelper2.default.isNegativeStrict(String(e.deltaY)) ? -50 : 50); // `e.deltaY` is usually too small compared to how the page is scrolled. That's why we use a fixed offset.\n }\n } else {\n _AutoNumericHelper2.default.throwError('Unknown `wheelOn` option.');\n }\n }\n }\n\n /**\n * Increment or decrement the element value according to the `wheelStep` option chosen\n *\n * @param {WheelEvent} e The `wheel` event\n */\n\n }, {\n key: 'wheelAction',\n value: function wheelAction(e) {\n this.isWheelEvent = true; // Keep the info that we are currently managing a mouse wheel event\n\n // 0) First, save the caret position so we can set it back once the value has been changed\n var selectionStart = e.target.selectionStart || 0;\n var selectionEnd = e.target.selectionEnd || 0;\n\n // 1) Get the unformatted value\n var currentUnformattedValue = this.rawValue;\n\n var result = void 0;\n if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(currentUnformattedValue)) {\n // If by default the input is empty, start at '0'\n if (this.settings.minimumValue > 0 || this.settings.maximumValue < 0) {\n // or if '0' is not between min and max value, 'minimumValue' if the user does a wheelup, 'maximumValue' if the user does a wheeldown\n if (_AutoNumericHelper2.default.isWheelUpEvent(e)) {\n result = this.settings.minimumValue;\n } else if (_AutoNumericHelper2.default.isWheelDownEvent(e)) {\n result = this.settings.maximumValue;\n } else {\n _AutoNumericHelper2.default.throwError('The event is not a \\'wheel\\' event.');\n }\n } else {\n result = 0;\n }\n } else {\n result = currentUnformattedValue;\n }\n\n result = +result; // Typecast to a number needed for the following addition/subtraction\n\n // 2) Increment/Decrement the value\n // But first, choose the increment/decrement method ; fixed or progressive\n if (_AutoNumericHelper2.default.isNumber(this.settings.wheelStep)) {\n var step = +this.settings.wheelStep; // Typecast to a number needed for the following addition/subtraction\n // Fixed method\n // This is the simplest method, where a fixed offset in added/subtracted from the current value\n if (_AutoNumericHelper2.default.isWheelUpEvent(e)) {\n // Increment\n result += step;\n } else if (_AutoNumericHelper2.default.isWheelDownEvent(e)) {\n // Decrement\n result -= step;\n }\n } else {\n // Progressive method\n // For this method, we calculate an offset that is in relation to the size of the current number (using only the integer part size).\n // The bigger the number, the bigger the offset (usually the number count in the integer part minus 3, except for small numbers where a different behavior is better for the user experience).\n //TODO Known limitation : The progressive method does not play well with numbers between 0 and 1 where to modify the decimal places the rawValue first has to go from '1' to '0'\n if (_AutoNumericHelper2.default.isWheelUpEvent(e)) {\n // Increment\n result = _AutoNumericHelper2.default.addAndRoundToNearestAuto(result, this.settings.decimalPlacesRawValue);\n } else if (_AutoNumericHelper2.default.isWheelDownEvent(e)) {\n // Decrement\n result = _AutoNumericHelper2.default.subtractAndRoundToNearestAuto(result, this.settings.decimalPlacesRawValue);\n }\n }\n\n // 3) Set the new value so it gets formatted\n // First clamp the result if needed\n result = _AutoNumericHelper2.default.clampToRangeLimits(result, this.settings);\n if (result !== +currentUnformattedValue) {\n // Only 'set' the value if it has changed. For instance 'set' should not happen if the user hits a limit and continue to try to go past it since we clamp the value.\n this.set(result);\n\n // Since we changed the input value, we send a native `input` event\n this._triggerEvent(AutoNumeric.events.native.input, e.target);\n }\n\n //XXX Do not prevent if the value is not modified? From a UX point of view, preventing the wheel event when the user use it on top of an autoNumeric element should always be done, even if the value does not change. Perhaps that could affect other scripts relying on this event to be sent though.\n e.preventDefault(); // We prevent the page to scroll while we increment/decrement the value\n\n // 4) Finally, we set back the caret position/selection\n // There is no need to take into account the fact that the number count could be different at the end of the wheel event ; it would be too complex and most of the time unreliable\n this._setSelection(selectionStart, selectionEnd);\n\n this.isWheelEvent = false; // Set back the mouse wheel indicator to its default\n }\n\n /**\n * Handler for 'drop' event\n *\n * @param {DragEvent} e\n */\n\n }, {\n key: '_onDrop',\n value: function _onDrop(e) {\n // Note: by default browsers already prevent the drop on readOnly and disabled elements\n this.isDropEvent = true;\n e.preventDefault();\n var format = void 0;\n if (_AutoNumericHelper2.default.isIE11()) {\n format = 'text';\n } else {\n format = 'text/plain';\n }\n\n var droppedText = e.dataTransfer.getData(format);\n var cleanedValue = this.unformatOther(droppedText);\n this.set(cleanedValue);\n this.isDropEvent = false;\n }\n\n /**\n * Handler for 'submit' events happening on the parent element.\n * If `unformatOnSubmit` is set to `true`, the element value is first unformatted before the form is submitted.\n *\n * @returns {boolean}\n */\n\n }, {\n key: '_onFormSubmit',\n value: function _onFormSubmit() {\n var _this10 = this;\n\n // Search for all the AutoNumeric children of the form element and call the `_unformatOnSubmit()` function\n var inputElements = this._getFormAutoNumericChildren(this.parentForm);\n var aNElements = inputElements.map(function (aNElement) {\n return _this10.constructor.getAutoNumericElement(aNElement);\n });\n aNElements.forEach(function (aNElement) {\n return aNElement._unformatOnSubmit();\n });\n\n return true;\n }\n\n /**\n * Unformat the element value according to the `unformatOnSubmit` option\n *\n * @private\n */\n\n }, {\n key: '_unformatOnSubmit',\n value: function _unformatOnSubmit() {\n if (this.settings.unformatOnSubmit) {\n this._setElementValue(this.rawValue);\n }\n }\n\n /**\n * Listen for the `alt` key keydown event globally, and if the event is caught, unformat the AutoNumeric element that is hovered by the mouse.\n *\n * @param {KeyboardEvent} e\n * @private\n */\n\n }, {\n key: '_onKeydownGlobal',\n value: function _onKeydownGlobal(e) {\n //TODO Find a way to keep the caret position between the alt keyup/keydown states\n if (_AutoNumericHelper2.default.character(e) === _AutoNumericEnum2.default.keyName.Alt) {\n var hoveredElement = _AutoNumericHelper2.default.getHoveredElement();\n if (AutoNumeric.isManagedByAutoNumeric(hoveredElement)) {\n var anElement = AutoNumeric.getAutoNumericElement(hoveredElement);\n this.constructor._unformatAltHovered(anElement);\n }\n }\n }\n\n /**\n * Listen for the `alt` key keyup event globally, and if the event is caught, reformat the AutoNumeric element that is hovered by the mouse.\n *\n * @param {KeyboardEvent} e\n * @private\n */\n\n }, {\n key: '_onKeyupGlobal',\n value: function _onKeyupGlobal(e) {\n if (_AutoNumericHelper2.default.character(e) === _AutoNumericEnum2.default.keyName.Alt) {\n var hoveredElement = _AutoNumericHelper2.default.getHoveredElement();\n if (AutoNumeric.isManagedByAutoNumeric(hoveredElement)) {\n var anElement = AutoNumeric.getAutoNumericElement(hoveredElement);\n this.constructor._reformatAltHovered(anElement);\n }\n }\n }\n\n /**\n * Return `true` if the DOM element is supported by autoNumeric.\n * A supported element is an element whitelisted in the `allowedTagList`.\n *\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_isElementTagSupported',\n value: function _isElementTagSupported() {\n if (!_AutoNumericHelper2.default.isElement(this.domElement)) {\n _AutoNumericHelper2.default.throwError('The DOM element is not valid, ' + this.domElement + ' given.');\n }\n\n return _AutoNumericHelper2.default.isInArray(this.domElement.tagName.toLowerCase(), this.allowedTagList);\n }\n\n /**\n * Return `true` in the DOM element is an .\n *\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_isInputElement',\n value: function _isInputElement() {\n return this.domElement.tagName.toLowerCase() === 'input';\n }\n\n /**\n * Return `true` if the input type is supported by AutoNumeric\n *\n * @returns {boolean}\n * @throws\n */\n\n }, {\n key: '_isInputTypeSupported',\n value: function _isInputTypeSupported() {\n return this.domElement.type === 'text' || this.domElement.type === 'hidden' || this.domElement.type === 'tel' || _AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(this.domElement.type);\n }\n\n /**\n * Check if the DOM element is supported by autoNumeric.\n * A supported element is either an element with the right 'type' attribute, or a tag whitelisted in the `allowedTagList`.\n * If the check fails, this method throws.\n * This function also set the info `this.isInputElement` which keep tracks if the DOM element is an or not, and the `this.isContentEditable` if the element has the `contenteditable` attribute set to `true`.\n *\n * @throws\n * @private\n */\n\n }, {\n key: '_checkElement',\n value: function _checkElement() {\n var currentElementTag = this.domElement.tagName.toLowerCase();\n\n if (!this._isElementTagSupported()) {\n _AutoNumericHelper2.default.throwError('The <' + currentElementTag + '> tag is not supported by autoNumeric');\n }\n\n if (this._isInputElement()) {\n if (!this._isInputTypeSupported()) {\n _AutoNumericHelper2.default.throwError('The input type \"' + this.domElement.type + '\" is not supported by autoNumeric');\n }\n\n this.isInputElement = true;\n } else {\n this.isInputElement = false;\n this.isContentEditable = this.domElement.hasAttribute('contenteditable') && this.domElement.getAttribute('contenteditable') === 'true';\n }\n }\n\n /**\n * Formats the default value on page load.\n * This is called only if the `formatOnPageLoad` option is set to `true`.\n *\n * @param {number|string|null} forcedInitialValue The value that should be used for initialization, in place on the eventual html one\n */\n\n }, {\n key: '_formatDefaultValueOnPageLoad',\n value: function _formatDefaultValueOnPageLoad() {\n var forcedInitialValue = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;\n\n var setValue = true;\n var currentValue = void 0;\n if (!_AutoNumericHelper2.default.isNull(forcedInitialValue)) {\n currentValue = forcedInitialValue;\n } else {\n // Make sure the initial value does not have any superfluous whitespaces around it (Fix issue #479)\n currentValue = _AutoNumericHelper2.default.getElementValue(this.domElement).trim();\n // Correct the DOM attribute in case some whitespaces were present\n this.domElement.setAttribute('value', currentValue);\n }\n\n if (this.isInputElement || this.isContentEditable) {\n /*\n * If the input value has been set by the dev, but not directly as an attribute in the html, then it takes\n * precedence and should get formatted during the initialization (if this input value is a valid number and that the\n * developer wants it formatted on init (cf. the `settings.formatOnPageLoad` option)).\n * Note; this is true whatever the developer has set for `data-default-value-override` in the html (asp.net users).\n *\n * In other words : if `defaultValueOverride` is not null, it means the developer is trying to prevent postback problems.\n * But if `input.value` is set to a number, and the html `value` attribute is not set, then it means the dev has\n * changed the input value, and then it means we should not overwrite his own decision to do so.\n * Hence, if `defaultValueOverride` is not null, but `input.value` is a number and `this.domElement.hasAttribute('value')`\n * is false, we should ignore `defaultValueOverride` altogether.\n */\n var unLocalizedCurrentValue = this.constructor._toNumericValue(currentValue, this.settings); // This allows to use a localized value on startup\n if (!this.domElement.hasAttribute('value') || this.domElement.getAttribute('value') === '') {\n // Check if the `value` is valid or not\n if (!isNaN(Number(unLocalizedCurrentValue)) && Infinity !== unLocalizedCurrentValue) {\n this.set(unLocalizedCurrentValue);\n setValue = false;\n } else {\n // If not, inform the developer that nothing usable has been provided\n _AutoNumericHelper2.default.throwError('The value [' + currentValue + '] used in the input is not a valid value autoNumeric can work with.');\n }\n } else {\n /* Checks for :\n * - page reload from back button, and\n * - ASP.net form post back\n * The following HTML data attribute is REQUIRED (data-an-default=\"same value as the value attribute\")\n * example: \n */\n if (this.settings.defaultValueOverride !== null && this.settings.defaultValueOverride.toString() !== currentValue || this.settings.defaultValueOverride === null && currentValue !== '' && currentValue !== this.domElement.getAttribute('value') || currentValue !== '' && this.domElement.getAttribute('type') === 'hidden' && !_AutoNumericHelper2.default.isNumber(unLocalizedCurrentValue)) {\n if (this.settings.saveValueToSessionStorage && (this.settings.decimalPlacesShownOnFocus !== null || this.settings.divisorWhenUnfocused)) {\n this._setRawValue(this._getValueFromPersistentStorage());\n }\n\n // If the decimalPlacesShownOnFocus value should NOT be saved in sessionStorage\n if (!this.settings.saveValueToSessionStorage) {\n var toStrip = this.constructor._removeBrackets(currentValue, this.settings);\n if ((this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.suffix || this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.prefix && this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) && this.settings.negativeSignCharacter !== '' && _AutoNumericHelper2.default.isNegative(currentValue, this.settings.negativeSignCharacter)) {\n this._setRawValue('-' + this.constructor._stripAllNonNumberCharacters(toStrip, this.settings, true, this.isFocused));\n } else {\n this._setRawValue(this.constructor._stripAllNonNumberCharacters(toStrip, this.settings, true, this.isFocused));\n }\n }\n\n setValue = false;\n }\n }\n\n if (currentValue === '') {\n switch (this.settings.emptyInputBehavior) {\n case AutoNumeric.options.emptyInputBehavior.focus:\n setValue = false;\n break;\n //TODO What about the `AutoNumeric.options.emptyInputBehavior.press` value?\n case AutoNumeric.options.emptyInputBehavior.always:\n this._setElementValue(this.settings.currencySymbol);\n setValue = false;\n break;\n case AutoNumeric.options.emptyInputBehavior.zero:\n this.set('0');\n setValue = false;\n break;\n default:\n //\n }\n } else if (setValue && currentValue === this.domElement.getAttribute('value')) {\n this.set(currentValue);\n }\n } else if (this.settings.defaultValueOverride === null || this.settings.defaultValueOverride === currentValue) {\n this.set(currentValue);\n }\n }\n\n /**\n * Enhance the user experience by modifying the default `negativePositiveSignPlacement` option depending on `currencySymbol` and `currencySymbolPlacement`.\n *\n * If the user has not set the placement of the negative sign (`negativePositiveSignPlacement`), but has set a currency symbol (`currencySymbol`),\n * then we modify the default value of `negativePositiveSignPlacement` in order to keep the resulting output logical by default :\n * - \"$-1,234.56\" instead of \"-$1,234.56\" ({currencySymbol: \"$\", negativePositiveSignPlacement: \"r\"})\n * - \"-1,234.56$\" instead of \"1,234.56-$\" ({currencySymbol: \"$\", currencySymbolPlacement: \"s\", negativePositiveSignPlacement: \"p\"})\n *\n * @param {object} settings\n */\n\n }, {\n key: '_calculateVMinAndVMaxIntegerSizes',\n\n\n /**\n * Analyze and save the minimumValue and maximumValue integer size for later uses\n * @private\n */\n value: function _calculateVMinAndVMaxIntegerSizes() {\n var _settings$maximumValu = this.settings.maximumValue.toString().split('.'),\n _settings$maximumValu2 = _slicedToArray(_settings$maximumValu, 1),\n maximumValueIntegerPart = _settings$maximumValu2[0];\n\n var _ref = !this.settings.minimumValue && this.settings.minimumValue !== 0 ? [] : this.settings.minimumValue.toString().split('.'),\n _ref2 = _slicedToArray(_ref, 1),\n minimumValueIntegerPart = _ref2[0];\n\n maximumValueIntegerPart = maximumValueIntegerPart.replace(this.settings.negativeSignCharacter, '');\n minimumValueIntegerPart = minimumValueIntegerPart.replace(this.settings.negativeSignCharacter, '');\n\n this.settings.mIntPos = Math.max(maximumValueIntegerPart.length, 1);\n this.settings.mIntNeg = Math.max(minimumValueIntegerPart.length, 1);\n }\n\n /**\n * Calculate once what are the `valuesToStrings` option keys.\n * @private\n */\n\n }, {\n key: '_calculateValuesToStringsKeys',\n value: function _calculateValuesToStringsKeys() {\n if (this.settings.valuesToStrings) {\n this.valuesToStringsKeys = Object.keys(this.settings.valuesToStrings);\n } else {\n this.valuesToStringsKeys = [];\n }\n }\n\n /**\n * Caches regular expressions for _stripAllNonNumberCharactersExceptCustomDecimalChar\n *\n * @param {object} settings\n * @param {object} regex\n */\n\n }, {\n key: '_transformOptionsValuesToDefaultTypes',\n\n\n /**\n * Modify the user settings to make them 'exploitable' later.\n */\n value: function _transformOptionsValuesToDefaultTypes() {\n for (var key in this.settings) {\n if (this.settings.hasOwnProperty(key)) {\n var value = this.settings[key];\n\n // Convert the strings 'true' and 'false' to booleans\n if (value === 'true' || value === 'false') {\n this.settings[key] = value === 'true';\n }\n\n // Convert numbers in options to strings\n //TODO Only transform the values of type 'Number' to 'String' if it's a currency number (so that we can have big numbers). Do not convert other numbers (ie. `historySize`)\n if (typeof value === 'number') {\n this.settings[key] = value.toString();\n }\n }\n }\n }\n\n /**\n * Convert the old settings options name to new ones.\n *\n * @param {object} options\n */\n\n }, {\n key: '_setSettings',\n\n\n /**\n * Analyse the settings/options passed by the user, validate and clean them, then set them into `this.settings`.\n * Note: This sets the settings to `null` if somehow the settings objet is undefined or empty\n * If only `decimalPlaces` is defined in the option, overwrite the other decimalPlaces* options, otherwise, use those options\n *\n * @param {object} options\n * @param {boolean} update - If set to `true`, then the settings already exists and this function only updates them instead of recreating them from scratch\n * @throws\n */\n value: function _setSettings(options) {\n var update = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n\n // If the user used old options, we convert them to new ones\n if (update || !_AutoNumericHelper2.default.isNull(options)) {\n this.constructor._convertOldOptionsToNewOnes(options);\n }\n\n if (update) {\n // The settings are updated\n // Update the original data, if it has changed\n var decimalPlacesRawValueInOptions = 'decimalPlacesRawValue' in options;\n if (decimalPlacesRawValueInOptions) {\n this.settings.originalDecimalPlacesRawValue = options.decimalPlacesRawValue;\n }\n\n var decimalPlacesInOptions = 'decimalPlaces' in options;\n if (decimalPlacesInOptions) {\n this.settings.originalDecimalPlaces = options.decimalPlaces;\n }\n\n // Then update all the `decimalPlaces*` options\n this.constructor._calculateDecimalPlacesOnUpdate(options, this.settings);\n\n // Finally generate the updated settings object to use\n this._mergeSettings(options); //TODO Check that the `styleRules` option is correctly cloned (due to depth cloning limitation)\n } else {\n // The settings are generated for the first time\n this.settings = {};\n // If we couldn't grab any settings, create them from the default ones and combine them with the options passed as a parameter as well as with the HTML5 `data-*` info (via `this.domElement.dataset`), if any.\n this._mergeSettings(this.constructor.getDefaultConfig(), this.domElement.dataset, options, { rawValue: this.defaultRawValue });\n this.caretFix = false;\n this.throwInput = true; // Throw input event\n this.allowedTagList = _AutoNumericEnum2.default.allowedTagList;\n this.runOnce = false;\n this.hoveredWithAlt = false; // Keep tracks if the current AutoNumeric element is hovered by the mouse cursor while `Alt` is pressed\n }\n\n // Modify the user settings to make them 'exploitable'\n this._transformOptionsValuesToDefaultTypes();\n\n // Immediately run the callbacks that could update the settings object\n this._runCallbacksFoundInTheSettingsObject();\n\n // Improve the `negativePositiveSignPlacement` option if needed\n this.constructor._correctNegativePositiveSignPlacementOption(this.settings);\n\n // Set the `caretPositionOnFocus` and `selectOnFocus` options so that they do not conflict, if one of those have been set manually by the user.\n // If order to check that, we take a look at the original options the user passed as an argument, not `this.settings` that have been merged with the default settings. //TODO Check the validity of that comment\n this.constructor._correctCaretPositionOnFocusAndSelectOnFocusOptions(this.settings);\n\n // Define if the negative or positive signs are allowed\n this.constructor._setNegativePositiveSignPermissions(this.settings);\n\n // Calculate the number of decimal places (during the element initialization)\n if (!update) {\n // Make sure the `originalDecimalPlaces` info is set\n if (_AutoNumericHelper2.default.isNull(options) || !options.decimalPlaces) {\n this.settings.originalDecimalPlaces = null;\n } else {\n this.settings.originalDecimalPlaces = options.decimalPlaces;\n }\n\n // Save the `originalDecimalPlacesRawValue` info\n this.settings.originalDecimalPlacesRawValue = this.settings.decimalPlacesRawValue;\n\n // Then update all the `decimalPlaces*` options\n this.constructor._calculateDecimalPlacesOnInit(this.settings);\n }\n\n // Additional changes to the settings object\n this._calculateVMinAndVMaxIntegerSizes();\n this._setTrailingNegativeSignInfo();\n this.regex = {}; // Create the object that will store the regular expressions\n this.constructor._cachesUsualRegularExpressions(this.settings, this.regex);\n this.constructor._setBrackets(this.settings);\n this._calculateValuesToStringsKeys();\n\n // Validate the settings. Both tests throws if necessary.\n if (_AutoNumericHelper2.default.isEmptyObj(this.settings)) {\n _AutoNumericHelper2.default.throwError('Unable to set the settings, those are invalid ; an empty object was given.');\n }\n\n this.constructor.validate(this.settings, false, options);\n\n // Original settings saved for use when decimalPlacesShownOnFocus, divisorWhenUnfocused & showOnlyNumbersOnFocus options are being used\n this._keepAnOriginalSettingsCopy();\n }\n\n /**\n * Define if the negative or positive signs are allowed, and update the given settings object directly.\n *\n * @param {object} settings\n * @private\n */\n\n }, {\n key: '_preparePastedText',\n\n\n /**\n * Return the pasted text that will be used, by stripping most non-numeric characters\n *\n * @param {string} text\n * @returns {string}\n */\n value: function _preparePastedText(text) {\n return this.constructor._stripAllNonNumberCharacters(text, this.settings, true, this.isFocused);\n }\n\n /**\n * Return TRUE if the given value (a number as a string) is within the range set in the settings `minimumValue` and `maximumValue`, FALSE otherwise.\n *\n * @param {string} value\n * @param {object} parsedMinValue Parsed via the `parseStr()` function\n * @param {object} parsedMaxValue Parsed via the `parseStr()` function\n * @returns {boolean}\n */\n\n }, {\n key: '_updateInternalProperties',\n\n\n /**\n * Update the selection values as well as resets the internal state of the current AutoNumeric object.\n * This keeps tracks of the current selection and resets the 'processed' state.\n *\n * Note : This state can change between the keydown, keypress and keyup events, that's why\n * this function is called on each event handler.\n *\n * @private\n */\n value: function _updateInternalProperties() {\n this.selection = _AutoNumericHelper2.default.getElementSelection(this.domElement);\n this.processed = false;\n }\n\n /**\n * Update the `event.key` attribute that triggered the given event.\n *\n * `event.key` describes:\n * - the key name (if a non-printable character),\n * - or directly the character that result from the key press used to trigger the event.\n *\n * @link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key\n * The key list is described here:\n * @link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values\n *\n * @param {Event|KeyboardEvent} e\n * @private\n */\n\n }, {\n key: '_updateEventKeyInfo',\n value: function _updateEventKeyInfo(e) {\n this.eventKey = _AutoNumericHelper2.default.character(e);\n }\n\n /**\n * Save the unformatted element value.\n * This is used in the 'cancellable' feature where the element value is saved on focus and input validation, to be used if the user wants to cancel his modifications by hitting the 'Escape' key.\n *\n * @private\n */\n\n }, {\n key: '_saveCancellableValue',\n value: function _saveCancellableValue() {\n this.savedCancellableValue = this.rawValue;\n }\n\n /**\n * Set the text selection inside the input with the given start and end position.\n *\n * @param {int} start\n * @param {int} end\n * @private\n */\n\n }, {\n key: '_setSelection',\n value: function _setSelection(start, end) {\n //TODO use this function to replace the direct calls to `setElementSelection()`, wherever possible\n start = Math.max(start, 0);\n end = Math.min(end, _AutoNumericHelper2.default.getElementValue(this.domElement).length);\n this.selection = {\n start: start,\n end: end,\n length: end - start\n };\n\n _AutoNumericHelper2.default.setElementSelection(this.domElement, start, end);\n }\n\n /**\n * Set the caret position inside the input at the given position.\n *\n * @param {int} position\n * @private\n */\n\n }, {\n key: '_setCaretPosition',\n value: function _setCaretPosition(position) {\n this._setSelection(position, position);\n }\n\n /**\n * Return an array containing the string parts located on the left and right side of the caret or selection.\n * Those parts are left 'untouched', ie. formatted by autoNumeric.\n *\n * @returns {[string, string]} The parts on the left and right of the caret or selection\n * @private\n */\n\n }, {\n key: '_getLeftAndRightPartAroundTheSelection',\n value: function _getLeftAndRightPartAroundTheSelection() {\n var value = _AutoNumericHelper2.default.getElementValue(this.domElement);\n var left = value.substring(0, this.selection.start);\n var right = value.substring(this.selection.end, value.length);\n\n return [left, right];\n }\n\n /**\n * Return an array containing the string parts located on the left and right side of the caret or selection.\n * Those parts are unformatted (stripped) of any non-numbers characters, and any trailing negative character is put back on the left hand side of the number.\n *\n * @returns {[string, string]} The parts on the left and right of the caret or selection, unformatted.\n * @private\n */\n\n }, {\n key: '_getUnformattedLeftAndRightPartAroundTheSelection',\n value: function _getUnformattedLeftAndRightPartAroundTheSelection() {\n var _getLeftAndRightPartA = this._getLeftAndRightPartAroundTheSelection(),\n _getLeftAndRightPartA2 = _slicedToArray(_getLeftAndRightPartA, 2),\n left = _getLeftAndRightPartA2[0],\n right = _getLeftAndRightPartA2[1];\n\n if (left === '' && right === '') {\n return ['', ''];\n }\n\n // If changing the sign and `left` is equal to the number zero, prevent stripping the leading zero(s)\n var stripZeros = true;\n if ((this.eventKey === _AutoNumericEnum2.default.keyName.Hyphen || this.eventKey === _AutoNumericEnum2.default.keyName.Minus) && Number(left) === 0) {\n stripZeros = false;\n }\n\n //TODO DRY that with `_normalizeParts()` -->\n if (this.isTrailingNegative && (_AutoNumericHelper2.default.isNegative(right, this.settings.negativeSignCharacter) && // The caret is placed on the left of the negative sign\n !_AutoNumericHelper2.default.isNegative(left, this.settings.negativeSignCharacter) || right === '' && // ..or the caret is placed on the far right of the input (Fix issue #481)\n _AutoNumericHelper2.default.isNegative(left, this.settings.negativeSignCharacter, true))) {\n left = left.replace(this.settings.negativeSignCharacter, '');\n right = right.replace(this.settings.negativeSignCharacter, '');\n // This is done here because `_getUnformattedLeftAndRightPartAroundTheSelection()` is called multiple times during the same key event, and at one point the left/right value has been normalized already..\n left = left.replace('-', '');\n right = right.replace('-', '');\n\n // Then finally set back the normalized minus character at the right place\n left = '-' + left;\n }\n\n left = AutoNumeric._stripAllNonNumberCharactersExceptCustomDecimalChar(left, this.settings, stripZeros, this.isFocused);\n right = AutoNumeric._stripAllNonNumberCharactersExceptCustomDecimalChar(right, this.settings, false, this.isFocused);\n\n return [left, right];\n }\n\n /**\n * Strip parts from excess characters and leading zeros.\n *\n * @param {string} left\n * @param {string} right\n * @returns {[*,*,*]}\n * @private\n */\n\n }, {\n key: '_normalizeParts',\n value: function _normalizeParts(left, right) {\n //TODO Refactor with `_getUnformattedLeftAndRightPartAroundTheSelection` which share a lot of similar code\n // If changing the sign and left is equal to the number zero - prevents stripping the leading zeros\n var stripZeros = true;\n if ((this.eventKey === _AutoNumericEnum2.default.keyName.Hyphen || this.eventKey === _AutoNumericEnum2.default.keyName.Minus) && Number(left) === 0) {\n stripZeros = false;\n }\n\n if (this.isTrailingNegative && _AutoNumericHelper2.default.isNegative(right, this.settings.negativeSignCharacter) && !_AutoNumericHelper2.default.isNegative(left, this.settings.negativeSignCharacter)) {\n // Only set the negative sign if the value is negative\n left = '-' + left;\n right = right.replace(this.settings.negativeSignCharacter, '');\n }\n\n left = AutoNumeric._stripAllNonNumberCharactersExceptCustomDecimalChar(left, this.settings, stripZeros, this.isFocused);\n right = AutoNumeric._stripAllNonNumberCharactersExceptCustomDecimalChar(right, this.settings, false, this.isFocused);\n\n // Prevents multiple leading zeros from being entered\n if (this.settings.leadingZero === AutoNumeric.options.leadingZero.deny && (this.eventKey === _AutoNumericEnum2.default.keyName.num0 || this.eventKey === _AutoNumericEnum2.default.keyName.numpad0) && Number(left) === 0 &&\n // If `right` is not empty and the first character is not `decimalCharacter`\n !_AutoNumericHelper2.default.contains(left, this.settings.decimalCharacter) && right !== '') {\n left = left.substring(0, left.length - 1);\n }\n\n // Insert zero there is a leading dot\n var newValue = left + right;\n if (this.settings.decimalCharacter) {\n var m = newValue.match(new RegExp('^' + this.regex.aNegRegAutoStrip + '\\\\' + this.settings.decimalCharacter));\n if (m) {\n left = left.replace(m[1], m[1] + '0');\n newValue = left + right;\n }\n }\n\n return [left, right, newValue];\n }\n\n /**\n * Set the formatted element value as well as the `rawValue`.\n * This returns `true` if the element and raw value have been modified, `false` otherwise.\n * This method also adjust the caret position according to the `leadingZero` option and the normalized value. //TODO What about the cursor *selection*?\n *\n * @param {string} left\n * @param {string} right\n * @param {boolean} isPaste\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_setValueParts',\n value: function _setValueParts(left, right) {\n var isPaste = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n\n var _normalizeParts2 = this._normalizeParts(left, right),\n _normalizeParts3 = _slicedToArray(_normalizeParts2, 3),\n normalizedLeft = _normalizeParts3[0],\n normalizedRight = _normalizeParts3[1],\n normalizedNewValue = _normalizeParts3[2];\n\n var _AutoNumeric$_checkIf = AutoNumeric._checkIfInRangeWithOverrideOption(normalizedNewValue, this.settings),\n _AutoNumeric$_checkIf2 = _slicedToArray(_AutoNumeric$_checkIf, 2),\n minTest = _AutoNumeric$_checkIf2[0],\n maxTest = _AutoNumeric$_checkIf2[1];\n\n if (minTest && maxTest) {\n // First, set the raw value\n var roundedRawValue = AutoNumeric._truncateDecimalPlaces(normalizedNewValue, this.settings, isPaste, this.settings.decimalPlacesRawValue);\n var testValue = roundedRawValue.replace(this.settings.decimalCharacter, '.');\n\n if (testValue === '' || testValue === this.settings.negativeSignCharacter) {\n var valueToSetOnEmpty = void 0;\n switch (this.settings.emptyInputBehavior) {\n case AutoNumeric.options.emptyInputBehavior.zero:\n valueToSetOnEmpty = '0';\n break;\n case AutoNumeric.options.emptyInputBehavior.null:\n valueToSetOnEmpty = null;\n break;\n default:\n valueToSetOnEmpty = '';\n }\n\n this._setRawValue(valueToSetOnEmpty);\n } else {\n this._setRawValue(this._trimLeadingAndTrailingZeros(testValue));\n }\n\n // Then set the formatted value\n var roundedValueToShow = AutoNumeric._truncateDecimalPlaces(normalizedNewValue, this.settings, isPaste, this.settings.decimalPlacesShownOnFocus);\n var position = normalizedLeft.length;\n if (position > roundedValueToShow.length) {\n position = roundedValueToShow.length;\n }\n\n // Make sure when the user enter a '0' on the far left with a leading zero option set to 'deny', that the caret does not moves since the input is dropped (fix issue #283)\n if (position === 1 && normalizedLeft === '0' && this.settings.leadingZero === AutoNumeric.options.leadingZero.deny) {\n // If the user enter `0`, then the caret is put on the right side of it (Fix issue #299)\n if (normalizedRight === '' || normalizedLeft === '0' && normalizedRight !== '') {\n position = 1;\n } else {\n position = 0;\n }\n }\n\n this._setElementValue(roundedValueToShow, false);\n this._setCaretPosition(position);\n\n return true;\n }\n\n if (!minTest) {\n this._triggerEvent(AutoNumeric.events.minRangeExceeded, this.domElement);\n } else if (!maxTest) {\n this._triggerEvent(AutoNumeric.events.maxRangeExceeded, this.domElement);\n }\n\n return false;\n }\n\n /**\n * Helper function for `_expandSelectionOnSign()`.\n *\n * @returns {Array} Array containing [signPosition, currencySymbolPosition] of a formatted value\n * @private\n */\n\n }, {\n key: '_getSignPosition',\n value: function _getSignPosition() {\n var result = void 0;\n if (this.settings.currencySymbol) {\n var currencySymbolLen = this.settings.currencySymbol.length;\n var value = _AutoNumericHelper2.default.getElementValue(this.domElement);\n if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix) {\n var hasNeg = this.settings.negativeSignCharacter && value && value.charAt(0) === this.settings.negativeSignCharacter;\n if (hasNeg) {\n result = [1, currencySymbolLen + 1];\n } else {\n result = [0, currencySymbolLen];\n }\n } else {\n var valueLen = value.length;\n result = [valueLen - currencySymbolLen, valueLen];\n }\n } else {\n result = [1000, -1];\n }\n\n return result;\n }\n\n /**\n * Expands selection to cover whole sign\n * Prevents partial deletion/copying/overwriting of a sign\n * @private\n */\n\n }, {\n key: '_expandSelectionOnSign',\n value: function _expandSelectionOnSign() {\n var _getSignPosition2 = this._getSignPosition(),\n _getSignPosition3 = _slicedToArray(_getSignPosition2, 2),\n signPosition = _getSignPosition3[0],\n currencySymbolPosition = _getSignPosition3[1];\n\n var selection = this.selection;\n\n // If selection catches something except sign and catches only space from sign\n if (selection.start < currencySymbolPosition && selection.end > signPosition) {\n // Then select without empty space\n if ((selection.start < signPosition || selection.end > currencySymbolPosition) && _AutoNumericHelper2.default.getElementValue(this.domElement).substring(Math.max(selection.start, signPosition), Math.min(selection.end, currencySymbolPosition)).match(/^\\s*$/)) {\n if (selection.start < signPosition) {\n this._setSelection(selection.start, signPosition);\n } else {\n this._setSelection(currencySymbolPosition, selection.end);\n }\n } else {\n // Else select with whole sign\n this._setSelection(Math.min(selection.start, signPosition), Math.max(selection.end, currencySymbolPosition));\n }\n }\n }\n\n /**\n * Try to strip pasted value to digits\n */\n\n }, {\n key: '_checkPaste',\n value: function _checkPaste() {\n // Do not process anything if the value has already been formatted\n if (this.formatted) {\n return;\n }\n\n if (!_AutoNumericHelper2.default.isUndefined(this.valuePartsBeforePaste)) {\n var oldParts = this.valuePartsBeforePaste;\n\n var _getLeftAndRightPartA3 = this._getLeftAndRightPartAroundTheSelection(),\n _getLeftAndRightPartA4 = _slicedToArray(_getLeftAndRightPartA3, 2),\n left = _getLeftAndRightPartA4[0],\n right = _getLeftAndRightPartA4[1];\n\n // Try to strip the pasted value first\n\n\n delete this.valuePartsBeforePaste;\n\n var modifiedLeftPart = left.substr(0, oldParts[0].length) + AutoNumeric._stripAllNonNumberCharactersExceptCustomDecimalChar(left.substr(oldParts[0].length), this.settings, true, this.isFocused);\n if (!this._setValueParts(modifiedLeftPart, right, true)) {\n this._setElementValue(oldParts.join(''), false);\n this._setCaretPosition(oldParts[0].length);\n }\n }\n }\n\n /**\n * Return `true` if the given key should be ignored or not.\n *\n * @param {string} eventKeyName\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_processNonPrintableKeysAndShortcuts',\n\n\n /**\n * Process copying, cutting and pasting, as well as undo/redoing and cursor moving.\n * Return `true` if further processing should not be performed.\n *\n * @param {KeyboardEvent} e\n * @returns {boolean}\n * @private\n */\n value: function _processNonPrintableKeysAndShortcuts(e) {\n // Catch the ctrl up on ctrl-v\n if ((e.ctrlKey || e.metaKey) && e.type === 'keyup' && !_AutoNumericHelper2.default.isUndefined(this.valuePartsBeforePaste) || e.shiftKey && this.eventKey === _AutoNumericEnum2.default.keyName.Insert) {\n //TODO Move this test inside the `onKeyup` handler\n this._checkPaste();\n\n return false;\n }\n\n // Skip all function keys (F1-F12), Windows keys, tab and other special keys\n if (this.constructor._shouldSkipEventKey(this.eventKey)) {\n return true;\n }\n\n // If a \"Select all\" keyboard shortcut is detected (ctrl + a)\n if ((e.ctrlKey || e.metaKey) && this.eventKey === _AutoNumericEnum2.default.keyName.a) {\n if (this.settings.selectNumberOnly) {\n // `preventDefault()` is used here to prevent the browser to first select all the input text (including the currency sign), otherwise we would see that whole selection first in a flash, then the selection with only the number part without the currency sign.\n e.preventDefault();\n //TODO replace `selectNumber` by `select`?\n this.selectNumber();\n }\n\n return true;\n }\n\n // If a \"Copy\", \"Paste\" or \"Cut\" keyboard shortcut is detected (respectively 'ctrl + c', 'ctrl + v' or 'ctrl + x')\n if ((e.ctrlKey || e.metaKey) && (this.eventKey === _AutoNumericEnum2.default.keyName.c || this.eventKey === _AutoNumericEnum2.default.keyName.v || this.eventKey === _AutoNumericEnum2.default.keyName.x)) {\n if (e.type === 'keydown') {\n this._expandSelectionOnSign();\n }\n\n // Try to prevent wrong paste\n if (this.eventKey === _AutoNumericEnum2.default.keyName.v || this.eventKey === _AutoNumericEnum2.default.keyName.Insert) {\n if (e.type === 'keydown' || e.type === 'keypress') {\n if (_AutoNumericHelper2.default.isUndefined(this.valuePartsBeforePaste)) {\n this.valuePartsBeforePaste = this._getLeftAndRightPartAroundTheSelection();\n }\n } else {\n this._checkPaste();\n }\n }\n\n return e.type === 'keydown' || e.type === 'keypress' || this.eventKey === _AutoNumericEnum2.default.keyName.c;\n }\n\n // The undo shortcut\n if (e.ctrlKey || e.metaKey) {\n if (this.eventKey === _AutoNumericEnum2.default.keyName.Z || this.eventKey === _AutoNumericEnum2.default.keyName.z) {\n return false;\n } else {\n return true;\n }\n }\n\n // Jump over the thousand separator\n //TODO Move this test inside the `onKeydown` handler\n if (this.eventKey === _AutoNumericEnum2.default.keyName.LeftArrow || this.eventKey === _AutoNumericEnum2.default.keyName.RightArrow) {\n if (e.type === 'keydown' && !e.shiftKey) {\n var value = _AutoNumericHelper2.default.getElementValue(this.domElement);\n if (this.eventKey === _AutoNumericEnum2.default.keyName.LeftArrow && (value.charAt(this.selection.start - 2) === this.settings.digitGroupSeparator || value.charAt(this.selection.start - 2) === this.settings.decimalCharacter)) {\n this._setCaretPosition(this.selection.start - 1);\n } else if (this.eventKey === _AutoNumericEnum2.default.keyName.RightArrow && (value.charAt(this.selection.start + 1) === this.settings.digitGroupSeparator || value.charAt(this.selection.start + 1) === this.settings.decimalCharacter)) {\n this._setCaretPosition(this.selection.start + 1);\n }\n }\n\n return true;\n }\n\n return _AutoNumericHelper2.default.isInArray(this.eventKey, _AutoNumericEnum2.default.keyName._directionKeys);\n }\n\n /**\n * Process deletion of characters when the minus sign is to the right of the numeric characters.\n *\n * @param {string} left The part on the left of the caret or selection\n * @param {string} right The part on the right of the caret or selection\n * @returns {[string, string]}\n * @private\n */\n\n }, {\n key: '_processCharacterDeletionIfTrailingNegativeSign',\n value: function _processCharacterDeletionIfTrailingNegativeSign(_ref3) {\n var _ref4 = _slicedToArray(_ref3, 2),\n left = _ref4[0],\n right = _ref4[1];\n\n var value = _AutoNumericHelper2.default.getElementValue(this.domElement);\n var isValNegative = _AutoNumericHelper2.default.isNegative(value, this.settings.negativeSignCharacter);\n\n if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix && this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.suffix) {\n if (this.eventKey === _AutoNumericEnum2.default.keyName.Backspace) {\n this.caretFix = this.selection.start >= value.indexOf(this.settings.suffixText) && this.settings.suffixText !== '';\n if (value.charAt(this.selection.start - 1) === '-') {\n left = left.substring(1);\n } else if (this.selection.start <= value.length - this.settings.suffixText.length) {\n left = left.substring(0, left.length - 1);\n }\n } else {\n this.caretFix = this.selection.start >= value.indexOf(this.settings.suffixText) && this.settings.suffixText !== '';\n if (this.selection.start >= value.indexOf(this.settings.currencySymbol) + this.settings.currencySymbol.length) {\n right = right.substring(1, right.length);\n }\n if (_AutoNumericHelper2.default.isNegative(left, this.settings.negativeSignCharacter) && value.charAt(this.selection.start) === '-') {\n left = left.substring(1);\n }\n }\n }\n\n if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n switch (this.settings.negativePositiveSignPlacement) {\n case AutoNumeric.options.negativePositiveSignPlacement.left:\n this.caretFix = this.selection.start >= value.indexOf(this.settings.negativeSignCharacter) + this.settings.negativeSignCharacter.length;\n if (this.eventKey === _AutoNumericEnum2.default.keyName.Backspace) {\n if (this.selection.start === value.indexOf(this.settings.negativeSignCharacter) + this.settings.negativeSignCharacter.length && isValNegative) {\n left = left.substring(1);\n } else if (left !== '-' && (this.selection.start <= value.indexOf(this.settings.negativeSignCharacter) || !isValNegative)) {\n left = left.substring(0, left.length - 1);\n }\n } else {\n if (left[0] === '-') {\n right = right.substring(1);\n }\n if (this.selection.start === value.indexOf(this.settings.negativeSignCharacter) && isValNegative) {\n left = left.substring(1);\n }\n }\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.right:\n this.caretFix = this.selection.start >= value.indexOf(this.settings.negativeSignCharacter) + this.settings.negativeSignCharacter.length;\n if (this.eventKey === _AutoNumericEnum2.default.keyName.Backspace) {\n if (this.selection.start === value.indexOf(this.settings.negativeSignCharacter) + this.settings.negativeSignCharacter.length) {\n left = left.substring(1);\n } else if (left !== '-' && this.selection.start <= value.indexOf(this.settings.negativeSignCharacter) - this.settings.currencySymbol.length) {\n left = left.substring(0, left.length - 1);\n } else if (left !== '' && !isValNegative) {\n left = left.substring(0, left.length - 1);\n }\n } else {\n this.caretFix = this.selection.start >= value.indexOf(this.settings.currencySymbol) && this.settings.currencySymbol !== '';\n if (this.selection.start === value.indexOf(this.settings.negativeSignCharacter)) {\n left = left.substring(1);\n }\n\n right = right.substring(1);\n }\n break;\n }\n }\n\n return [left, right];\n }\n\n /**\n * Process the deletion of characters.\n */\n\n }, {\n key: '_processCharacterDeletion',\n value: function _processCharacterDeletion() {\n var left = void 0;\n var right = void 0;\n\n if (!this.selection.length) {\n var _getUnformattedLeftAn = this._getUnformattedLeftAndRightPartAroundTheSelection();\n\n var _getUnformattedLeftAn2 = _slicedToArray(_getUnformattedLeftAn, 2);\n\n left = _getUnformattedLeftAn2[0];\n right = _getUnformattedLeftAn2[1];\n\n if (left === '' && right === '') {\n this.throwInput = false;\n }\n\n if (this.isTrailingNegative && _AutoNumericHelper2.default.isNegative(_AutoNumericHelper2.default.getElementValue(this.domElement), this.settings.negativeSignCharacter)) {\n var _processCharacterDele = this._processCharacterDeletionIfTrailingNegativeSign([left, right]);\n\n var _processCharacterDele2 = _slicedToArray(_processCharacterDele, 2);\n\n left = _processCharacterDele2[0];\n right = _processCharacterDele2[1];\n } else {\n if (this.eventKey === _AutoNumericEnum2.default.keyName.Backspace) {\n left = left.substring(0, left.length - 1);\n } else {\n right = right.substring(1, right.length);\n }\n }\n } else {\n this._expandSelectionOnSign();\n\n var _getUnformattedLeftAn3 = this._getUnformattedLeftAndRightPartAroundTheSelection();\n\n var _getUnformattedLeftAn4 = _slicedToArray(_getUnformattedLeftAn3, 2);\n\n left = _getUnformattedLeftAn4[0];\n right = _getUnformattedLeftAn4[1];\n }\n\n this._setValueParts(left, right);\n }\n\n /**\n * Return `true` if a decimal character is allowed to be typed.\n * If the number of decimal places shown on focus is zero, then the decimal character is not allowed.\n *\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_isDecimalCharacterInsertionAllowed',\n value: function _isDecimalCharacterInsertionAllowed() {\n return String(this.settings.decimalPlacesShownOnFocus) !== String(AutoNumeric.options.decimalPlacesShownOnFocus.none) && String(this.settings.decimalPlaces) !== String(AutoNumeric.options.decimalPlaces.none);\n }\n\n /**\n * Return `true` if the key is allowed.\n * This function decides if the key pressed should be dropped or accepted, and modify the value 'on-the-fly' accordingly.\n * //TODO This should use another function in order to separate the test and the modification\n *\n * @returns {boolean}\n */\n\n }, {\n key: '_processCharacterInsertion',\n value: function _processCharacterInsertion() {\n var _getUnformattedLeftAn5 = this._getUnformattedLeftAndRightPartAroundTheSelection(),\n _getUnformattedLeftAn6 = _slicedToArray(_getUnformattedLeftAn5, 2),\n left = _getUnformattedLeftAn6[0],\n right = _getUnformattedLeftAn6[1];\n\n if (this.eventKey !== _AutoNumericEnum2.default.keyName.AndroidDefault) {\n this.throwInput = true;\n }\n\n // Start rules when the decimal character key is pressed always use numeric pad dot to insert decimal separator\n // Do not allow decimal character if no decimal part allowed\n if (this.eventKey === this.settings.decimalCharacter || this.settings.decimalCharacterAlternative && this.eventKey === this.settings.decimalCharacterAlternative) {\n if (!this._isDecimalCharacterInsertionAllowed() || !this.settings.decimalCharacter) {\n return false;\n }\n\n // Do not allow decimal character before negativeSignCharacter character\n if (this.settings.negativeSignCharacter && _AutoNumericHelper2.default.contains(right, this.settings.negativeSignCharacter)) {\n return true;\n }\n\n // Do not allow a decimal character if another decimal character is already present\n if (_AutoNumericHelper2.default.contains(left, this.settings.decimalCharacter)) {\n return true;\n }\n\n if (right.indexOf(this.settings.decimalCharacter) > 0) {\n return true;\n }\n\n if (right.indexOf(this.settings.decimalCharacter) === 0) {\n right = right.substr(1);\n }\n\n this._setValueParts(left + this.settings.decimalCharacter, right);\n\n return true;\n }\n\n // Prevent entering the minus sign if it's not allowed (Note: `this.settings.isNegativeSignAllowed` is only set to `true` if the minimumValue is lower than zero, allowing negative numbers to be entered)\n if ((this.eventKey === '-' || this.eventKey === '+') && this.settings.isNegativeSignAllowed) {\n // Here, the left and right parts have been normalized already, hence the minus sign usage\n if (left === '' && _AutoNumericHelper2.default.contains(right, '-')) {\n // The value is originally negative (with a trailing negative sign)\n right = right.replace('-', '');\n } else if (_AutoNumericHelper2.default.isNegative(left, '-')) {\n // The value is originally negative (with a leading negative sign)\n // Remove the negative sign, effectively converting the value to a positive one\n left = left.replace('-', ''); //TODO replace with '+' if `showPositiveSign` too?\n } else {\n // The value is originally positive, so we toggle the state to a negative one (unformatted, which means even with a trailing negative sign, we add the minus sign on the far left)\n left = '' + this.settings.negativeSignCharacter + left;\n }\n\n this._setValueParts(left, right);\n\n return true;\n }\n\n var eventNumber = Number(this.eventKey);\n if (eventNumber >= 0 && eventNumber <= 9) {\n // If the user tries to insert a digit\n if (this.settings.isNegativeSignAllowed && left === '' && _AutoNumericHelper2.default.contains(right, '-')) {\n // ...and that digit is before the minus sign\n left = '-';\n right = right.substring(1, right.length);\n }\n\n if (this.settings.maximumValue <= 0 && this.settings.minimumValue < this.settings.maximumValue && !_AutoNumericHelper2.default.contains(_AutoNumericHelper2.default.getElementValue(this.domElement), this.settings.negativeSignCharacter) && this.eventKey !== '0') {\n left = '-' + left;\n }\n\n this._setValueParts('' + left + this.eventKey, right);\n\n return true;\n }\n\n // Prevent any other characters\n this.throwInput = false;\n\n return false;\n }\n\n /**\n * Formatting of just processed value while keeping the cursor position\n *\n * @param {Event} e\n * @private\n */\n\n }, {\n key: '_formatValue',\n value: function _formatValue(e) {\n //TODO Break apart and simplify this really long function\n var elementValue = _AutoNumericHelper2.default.getElementValue(this.domElement);\n\n var _getUnformattedLeftAn7 = this._getUnformattedLeftAndRightPartAroundTheSelection(),\n _getUnformattedLeftAn8 = _slicedToArray(_getUnformattedLeftAn7, 1),\n left = _getUnformattedLeftAn8[0];\n\n // No grouping separator and no currency sign\n\n\n if ((this.settings.digitGroupSeparator === '' || this.settings.digitGroupSeparator !== '' && !_AutoNumericHelper2.default.contains(elementValue, this.settings.digitGroupSeparator)) && (this.settings.currencySymbol === '' || this.settings.currencySymbol !== '' && !_AutoNumericHelper2.default.contains(elementValue, this.settings.currencySymbol))) {\n var _elementValue$split = elementValue.split(this.settings.decimalCharacter),\n _elementValue$split2 = _slicedToArray(_elementValue$split, 1),\n subParts = _elementValue$split2[0];\n\n var negativeSign = '';\n if (_AutoNumericHelper2.default.isNegative(subParts, this.settings.negativeSignCharacter)) {\n negativeSign = this.settings.negativeSignCharacter;\n subParts = subParts.replace(this.settings.negativeSignCharacter, '');\n left = left.replace('-', ''); // Here we modify the unformatted value (with the 'normal' minus sign)\n }\n\n // Strip leading zero on positive value if needed\n if (negativeSign === '' && subParts.length > this.settings.mIntPos && left.charAt(0) === '0') {\n left = left.slice(1);\n }\n\n // Strip leading zero on negative value if needed\n if (negativeSign === this.settings.negativeSignCharacter && subParts.length > this.settings.mIntNeg && left.charAt(0) === '0') {\n left = left.slice(1);\n }\n\n if (!this.isTrailingNegative) {\n // Only add the minus sign if it's needed on that side of the numbers\n left = '' + negativeSign + left;\n }\n }\n\n var value = this.constructor._addGroupSeparators(elementValue, this.settings, this.isFocused, this.rawValue);\n var position = value.length;\n if (value) {\n // Prepare regexp which searches for cursor position from unformatted left part\n var leftAr = left.split('');\n\n // Fixes caret position with trailing minus sign\n if ((this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.suffix || this.settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.prefix && this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) && leftAr[0] === this.settings.negativeSignCharacter && !this.settings.isNegativeSignAllowed) {\n leftAr.shift(); // Remove the negative sign character\n\n if ((this.eventKey === _AutoNumericEnum2.default.keyName.Backspace || this.eventKey === _AutoNumericEnum2.default.keyName.Delete) && this.caretFix) {\n if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix && this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.left || this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix && this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.suffix) {\n leftAr.push(this.settings.negativeSignCharacter);\n this.caretFix = e.type === 'keydown';\n }\n\n if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix && this.settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.right) {\n var signParts = this.settings.currencySymbol.split('');\n var escapeChr = ['\\\\', '^', '$', '.', '|', '?', '*', '+', '(', ')', '['];\n var escapedParts = [];\n signParts.forEach(function (i, miniParts) {\n miniParts = signParts[i];\n if (_AutoNumericHelper2.default.isInArray(miniParts, escapeChr)) {\n escapedParts.push('\\\\' + miniParts);\n } else {\n escapedParts.push(miniParts);\n }\n });\n\n if (this.eventKey === _AutoNumericEnum2.default.keyName.Backspace && this.settings.negativeSignCharacter === '-') {\n escapedParts.push('-');\n }\n\n // Pushing the escaped sign\n leftAr.push(escapedParts.join(''));\n this.caretFix = e.type === 'keydown';\n }\n }\n }\n\n for (var i = 0; i < leftAr.length; i++) {\n if (!leftAr[i].match('\\\\d')) {\n leftAr[i] = '\\\\' + leftAr[i];\n }\n }\n\n var leftReg = new RegExp('^.*?' + leftAr.join('.*?'));\n\n // Search cursor position in formatted value\n var newLeft = value.match(leftReg);\n if (newLeft) {\n position = newLeft[0].length;\n\n // If the positive sign is shown, calculate the caret position accordingly\n if (this.settings.showPositiveSign) {\n if (position === 0 && newLeft.input.charAt(0) === this.settings.positiveSignCharacter) {\n position = newLeft.input.indexOf(this.settings.currencySymbol) === 1 ? this.settings.currencySymbol.length + 1 : 1;\n }\n\n if (position === 0 && newLeft.input.charAt(this.settings.currencySymbol.length) === this.settings.positiveSignCharacter) {\n position = this.settings.currencySymbol.length + 1;\n }\n }\n\n // If we are just before the sign which is in prefix position\n if ((position === 0 && value.charAt(0) !== this.settings.negativeSignCharacter || position === 1 && value.charAt(0) === this.settings.negativeSignCharacter) && this.settings.currencySymbol && this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix) {\n // Place caret after prefix sign\n //TODO Should the test be 'isNegative' instead of 'isNegativeStrict' in order to search for '-' everywhere in the string?\n position = this.settings.currencySymbol.length + (_AutoNumericHelper2.default.isNegativeStrict(value, this.settings.negativeSignCharacter) ? 1 : 0);\n }\n } else {\n if (this.settings.currencySymbol && this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n // If we could not find a place for cursor and have a sign as a suffix\n // Place caret before suffix currency sign\n position -= this.settings.currencySymbol.length;\n }\n\n if (this.settings.suffixText) {\n // If we could not find a place for cursor and have a suffix\n // Place caret before suffix\n position -= this.settings.suffixText.length;\n }\n }\n }\n\n // Only update the value if it has changed. This prevents modifying the selection, if any.\n if (value !== elementValue) {\n this._setElementValue(value, false);\n this._setCaretPosition(position);\n }\n\n this.formatted = true; //TODO Rename `this.formatted` to `this._formatExecuted`, since it's possible this function does not need to format anything (in the case where the keycode is dropped for instance)\n }\n\n /**\n * Serialize the form child element values to a string, or an Array.\n * The output format is defined with the `formatType` argument.\n * This is loosely based upon http://stackoverflow.com/a/40705993/2834898.\n *\n * @param {HTMLFormElement} form\n * @param {boolean} intoAnArray If `true`, instead of generating a string, it generates an Array.\n * @param {string} formatType If `'unformatted'`, then the AutoNumeric elements values are unformatted, if `'localized'`, then the AutoNumeric elements values are localized, and if `'formatted'`, then the AutoNumeric elements values are kept formatted. In either way, this function does not modify the value of each DOM element, but only affect the value that is returned by that serialize function.\n * @param {string} serializedSpaceCharacter Can either be the '+' character, or the '%20' string.\n * @param {string|null} forcedOutputFormat If set, then this is the format that is used for the localization, instead of the default `outputFormat` option.\n * @returns {string|Array}\n * @private\n */\n\n }], [{\n key: 'version',\n value: function version() {\n return '4.2.9';\n }\n\n /**\n * Take the parameters given to the AutoNumeric object, and output the three variables that are needed to finish initializing it :\n * - domElement : The target DOM element\n * - initialValue : The initial value, or `null` if none is given\n * - userOptions : The option object\n *\n * @param {object|Array|number|string} arg1\n * @param {object|Array|number|string|null} arg2\n * @param {object|Array|number|string|null} arg3\n * @returns {{domElement: *, initialValue: *, userOptions: *}}\n * @throws\n * @private\n */\n\n }, {\n key: '_setArgumentsValues',\n value: function _setArgumentsValues(arg1, arg2, arg3) {\n // Basic check on the argument count\n if (_AutoNumericHelper2.default.isNull(arg1)) {\n _AutoNumericHelper2.default.throwError('At least one valid parameter is needed in order to initialize an AutoNumeric object');\n }\n\n // Prepare the arguments in order to create the AutoNumeric object with the right values\n // Test the argument types\n var isArg1Element = _AutoNumericHelper2.default.isElement(arg1);\n var isArg1String = _AutoNumericHelper2.default.isString(arg1);\n\n var isArg2Object = _AutoNumericHelper2.default.isObject(arg2);\n var isArg2Array = Array.isArray(arg2) && arg2.length > 0;\n var isArg2Number = _AutoNumericHelper2.default.isNumberOrArabic(arg2) || arg2 === '';\n var isArg2PreDefinedOptionName = this._isPreDefinedOptionValid(arg2);\n var isArg2Null = _AutoNumericHelper2.default.isNull(arg2);\n var isArg2EmptyString = _AutoNumericHelper2.default.isEmptyString(arg2);\n\n var isArg3Object = _AutoNumericHelper2.default.isObject(arg3);\n var isArg3Array = Array.isArray(arg3) && arg3.length > 0;\n var isArg3Null = _AutoNumericHelper2.default.isNull(arg3);\n var isArg3PreDefinedOptionName = this._isPreDefinedOptionValid(arg3);\n\n // Given the parameters passed, sort the data and return a stable state before the initialization\n var domElement = void 0;\n var userOptions = void 0;\n var initialValue = void 0;\n\n //TODO Simplify those tests -->\n if (isArg1Element && isArg2Null && isArg3Null) {\n // new AutoNumeric(domElement); // With the default options\n domElement = arg1;\n initialValue = null;\n userOptions = null;\n } else if (isArg1Element && isArg2Number && isArg3Null) {\n // new AutoNumeric(domElement, 12345.789); // With the default options, and an initial value\n // new AutoNumeric(domElement, '12345.789');\n domElement = arg1;\n initialValue = arg2;\n userOptions = null;\n } else if (isArg1Element && isArg2Object && isArg3Null) {\n // new AutoNumeric(domElement, { options }); // With one option object\n domElement = arg1;\n initialValue = null;\n userOptions = arg2;\n } else if (isArg1Element && isArg2PreDefinedOptionName && isArg3Null) {\n // new AutoNumeric(domElement, 'euroPos'); // With one pre-defined option name\n domElement = arg1;\n initialValue = null;\n userOptions = this._getOptionObject(arg2);\n } else if (isArg1Element && isArg2Array && isArg3Null) {\n // new AutoNumeric(domElement, [{ options1 }, { options2 }]); // With multiple option objects (the latest option overwriting the previous ones)\n domElement = arg1;\n initialValue = null;\n userOptions = this.mergeOptions(arg2);\n } else if (isArg1Element && (isArg2Null || isArg2EmptyString) && isArg3Object) {\n // new AutoNumeric(domElement, null, { options }); // With one option object\n domElement = arg1;\n initialValue = null;\n userOptions = arg3;\n } else if (isArg1Element && (isArg2Null || isArg2EmptyString) && isArg3Array) {\n // new AutoNumeric(domElement, null, [{ options1 }, { options2 }]); // With multiple option objects\n domElement = arg1;\n initialValue = null;\n userOptions = this.mergeOptions(arg3);\n } else if (isArg1String && isArg2Null && isArg3Null) {\n // new AutoNumeric('.myCssClass > input');\n domElement = document.querySelector(arg1);\n initialValue = null;\n userOptions = null;\n } else if (isArg1String && isArg2Object && isArg3Null) {\n // new AutoNumeric('.myCssClass > input', { options });\n domElement = document.querySelector(arg1);\n initialValue = null;\n userOptions = arg2;\n } else if (isArg1String && isArg2PreDefinedOptionName && isArg3Null) {\n // new AutoNumeric('.myCssClass > input', 'euroPos');\n domElement = document.querySelector(arg1);\n initialValue = null;\n userOptions = this._getOptionObject(arg2);\n } else if (isArg1String && isArg2Array && isArg3Null) {\n // new AutoNumeric('.myCssClass > input', [{ options1 }, { options2 }]); // With multiple option objects\n domElement = document.querySelector(arg1);\n initialValue = null;\n userOptions = this.mergeOptions(arg2);\n } else if (isArg1String && (isArg2Null || isArg2EmptyString) && isArg3Object) {\n // new AutoNumeric('.myCssClass > input', null, { options });\n domElement = document.querySelector(arg1);\n initialValue = null;\n userOptions = arg3;\n } else if (isArg1String && (isArg2Null || isArg2EmptyString) && isArg3Array) {\n // new AutoNumeric('.myCssClass > input', null, [{ options1 }, { options2 }]); // With multiple option objects\n domElement = document.querySelector(arg1);\n initialValue = null;\n userOptions = this.mergeOptions(arg3);\n } else if (isArg1String && isArg2Number && isArg3Null) {\n // new AutoNumeric('.myCssClass > input', 12345.789);\n // new AutoNumeric('.myCssClass > input', '12345.789');\n // new AutoNumeric('.myCssClass > input', '');\n domElement = document.querySelector(arg1);\n initialValue = arg2;\n userOptions = null;\n } else if (isArg1String && isArg2Number && isArg3Object) {\n // new AutoNumeric('.myCssClass > input', 12345.789, { options });\n // new AutoNumeric('.myCssClass > input', '12345.789', { options });\n // new AutoNumeric('.myCssClass > input', '', { options });\n domElement = document.querySelector(arg1);\n initialValue = arg2;\n userOptions = arg3;\n } else if (isArg1String && isArg2Number && isArg3PreDefinedOptionName) {\n // new AutoNumeric('.myCssClass > input', 12345.789, 'euroPos');\n // new AutoNumeric('.myCssClass > input', '12345.789', 'euroPos');\n // new AutoNumeric('.myCssClass > input', '', 'euroPos');\n domElement = document.querySelector(arg1);\n initialValue = arg2;\n userOptions = this._getOptionObject(arg3);\n } else if (isArg1Element && isArg2Number && isArg3Object) {\n // new AutoNumeric(domElement, 12345.789, { options });\n // new AutoNumeric(domElement, '12345.789', { options });\n // new AutoNumeric(domElement, '', { options });\n domElement = arg1;\n initialValue = arg2;\n userOptions = arg3;\n } else if (isArg1Element && isArg2Number && isArg3PreDefinedOptionName) {\n // new AutoNumeric(domElement, 12345.789, 'euroPos');\n // new AutoNumeric(domElement, '12345.789', 'euroPos');\n // new AutoNumeric(domElement, '', 'euroPos');\n domElement = arg1;\n initialValue = arg2;\n userOptions = this._getOptionObject(arg3);\n } else if (isArg1Element && isArg2Number && isArg3Array) {\n // new AutoNumeric(domElement, 12345.789, [{ options1 }, { options2 }]);\n // new AutoNumeric(domElement, '12345.789', [{ options1 }, { options2 }]);\n // new AutoNumeric(domElement, '', [{ options1 }, { options2 }]);\n domElement = arg1;\n initialValue = arg2;\n userOptions = this.mergeOptions(arg3);\n } else {\n _AutoNumericHelper2.default.throwError('The parameters given to the AutoNumeric object are not valid, \\'' + arg1 + '\\', \\'' + arg2 + '\\' and \\'' + arg3 + '\\' given.');\n }\n\n if (_AutoNumericHelper2.default.isNull(domElement)) {\n _AutoNumericHelper2.default.throwError('The selector \\'' + arg1 + '\\' did not select any valid DOM element. Please check on which element you called AutoNumeric.');\n }\n\n return { domElement: domElement, initialValue: initialValue, userOptions: userOptions };\n }\n\n /**\n * Merge the option objects found in the given array `optionsArray`.\n * If a `string` is found, then we try to get the related pre-defined option using that string as its name.\n * When merging the options, the latest option overwrite any previously set. This allows to fine tune a pre-defined option for instance.\n *\n * @param {Array} optionsArray\n * @returns {{}}\n */\n\n }, {\n key: 'mergeOptions',\n value: function mergeOptions(optionsArray) {\n var _this11 = this;\n\n // This allows the user to use multiple options (strings or objects) in an array, and overwrite the previous one with the next option element ; this is useful to tune the wanted format\n var mergedOptions = {};\n optionsArray.forEach(function (optionObjectOrPredefinedOptionString) {\n _extends(mergedOptions, _this11._getOptionObject(optionObjectOrPredefinedOptionString));\n });\n\n return mergedOptions;\n }\n\n /**\n * Return `true` if the given pre-defined option name is an attribute of the `AutoNumeric.predefinedOptions` object\n *\n * @param {string} preDefinedOptionName\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_isPreDefinedOptionValid',\n value: function _isPreDefinedOptionValid(preDefinedOptionName) {\n return AutoNumeric.predefinedOptions.hasOwnProperty(preDefinedOptionName);\n }\n\n /**\n * Return an option object based on the given parameter.\n * If `optionObjectOrPredefinedName` is as string, then we retrieve the pre-defined option object, if it's an object, we use it as is.\n *\n * @param {object|string} optionObjectOrPredefinedName\n * @returns {object}\n */\n\n }, {\n key: '_getOptionObject',\n value: function _getOptionObject(optionObjectOrPredefinedName) {\n var options = void 0;\n if (_AutoNumericHelper2.default.isString(optionObjectOrPredefinedName)) {\n options = AutoNumeric.getPredefinedOptions()[optionObjectOrPredefinedName];\n if (options === void 0 || options === null) {\n // If the given pre-defined name does not exist, warn that something is wrong, and continue the execution of the initialization\n _AutoNumericHelper2.default.warning('The given pre-defined option [' + optionObjectOrPredefinedName + '] is not recognized by autoNumeric. Please check that pre-defined option name.', true);\n }\n } else {\n // A `settings` object\n options = optionObjectOrPredefinedName;\n }\n\n return options;\n }\n }, {\n key: '_doesFormHandlerListExists',\n value: function _doesFormHandlerListExists() {\n var type = _typeof(window.aNFormHandlerMap);\n\n return type !== 'undefined' && type === 'object';\n }\n\n /**\n * Create the global form handler list on the `window` object.\n *\n * @private\n */\n\n }, {\n key: '_createFormHandlerList',\n value: function _createFormHandlerList() {\n window.aNFormHandlerMap = new Map(); // I would have used a `WeakMap` here, but that does not allow using non-object for keys\n }\n }, {\n key: '_checkValuesToStringsArray',\n value: function _checkValuesToStringsArray(key, stringsArray) {\n return _AutoNumericHelper2.default.isInArray(String(key), stringsArray);\n }\n\n /**\n * Static helper for checking if the given `key` is found in the settings' `valuesToStrings` option object.\n *\n * @param {number|string} key\n * @param {object} settings\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_checkValuesToStringsSettings',\n value: function _checkValuesToStringsSettings(key, settings) {\n return this._checkValuesToStringsArray(key, Object.keys(settings.valuesToStrings));\n }\n\n /**\n * Static helper for checking if the given `value` is found in the settings' `valuesToStrings` option object.\n *\n * @param {number|string} value\n * @param {object} settings\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_checkStringsToValuesSettings',\n value: function _checkStringsToValuesSettings(value, settings) {\n return this._checkValuesToStringsArray(value, Object.values(settings.valuesToStrings));\n }\n }, {\n key: '_unformatAltHovered',\n value: function _unformatAltHovered(anElement) {\n anElement.hoveredWithAlt = true;\n anElement.unformat();\n }\n\n /**\n * Reformat the given AutoNumeric element, and update the `hoveredWithAlt` variable.\n *\n * @param {AutoNumeric} anElement\n * @private\n */\n\n }, {\n key: '_reformatAltHovered',\n value: function _reformatAltHovered(anElement) {\n anElement.hoveredWithAlt = false;\n anElement.reformat();\n }\n\n /**\n * Return an array of autoNumeric elements, child of the element passed as a parameter.\n *\n * @param {HTMLElement} formNode\n * @returns {Array}\n * @private\n */\n\n }, {\n key: '_getChildANInputElement',\n value: function _getChildANInputElement(formNode) {\n var _this12 = this;\n\n //FIXME test this\n var inputList = formNode.getElementsByTagName('input');\n\n // Loop this list and keep only the inputs that are managed by AutoNumeric\n var autoNumericInputs = [];\n var inputElements = Array.prototype.slice.call(inputList, 0);\n inputElements.forEach(function (input) {\n if (_this12.test(input)) {\n autoNumericInputs.push(input);\n }\n });\n\n return autoNumericInputs;\n }\n\n // Static methods\n /**\n * Test if the given DOM element, or the element selected by the given selector string is already managed by AutoNumeric (if it has been initialized on the current page).\n *\n * @param {HTMLElement|string} domElementOrSelector Accepts either directly a DOM element to test, or a string selector (that will return one and only one element, if any)\n * @returns {boolean}\n */\n\n }, {\n key: 'test',\n value: function test(domElementOrSelector) {\n return this._isInGlobalList(_AutoNumericHelper2.default.domElement(domElementOrSelector));\n }\n\n /**\n * Create a WeakMap with the given name.\n *\n * @param {string} weakMapName\n * @private\n */\n\n }, {\n key: '_createWeakMap',\n value: function _createWeakMap(weakMapName) {\n window[weakMapName] = new WeakMap();\n }\n\n /**\n * Create a list of all the AutoNumeric elements that are initialized on the current page.\n * This is needed in order to determine if a given dom element is already managed by autoNumeric.\n * This uses a WeakMap in order to limit potential garbage collection problems.\n * (cf. my tests on http://codepen.io/AnotherLinuxUser/pen/pRQGaM?editors=1011)\n * @private\n */\n\n }, {\n key: '_createGlobalList',\n value: function _createGlobalList() {\n // The check that this global list does not exists already is done in the add and remove functions already\n this.autoNumericGlobalListName = 'autoNumericGlobalList'; //XXX This looks weird to set a variable on `this.` in a static method, but that really declare that variable like a static property\n // Note: I should not get any memory leaks for referencing the DOM element in the `value`, this DOM element also being the `key`, according to the spec : http://www.ecma-international.org/ecma-262/6.0/#sec-weakmap-objects\n this._createWeakMap(this.autoNumericGlobalListName);\n }\n\n /**\n * Return `true` if the global AutoNumeric element list exists.\n *\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_doesGlobalListExists',\n value: function _doesGlobalListExists() {\n var type = _typeof(window[this.autoNumericGlobalListName]);\n return type !== 'undefined' && type === 'object';\n }\n\n /**\n * Add the given object to the global AutoNumeric element list.\n *\n * @param {AutoNumeric} autoNumericObject\n * @private\n */\n\n }, {\n key: '_addToGlobalList',\n value: function _addToGlobalList(autoNumericObject) {\n if (!this._doesGlobalListExists()) {\n this._createGlobalList();\n }\n\n var domElement = autoNumericObject.node();\n // This checks if the object is not already in the global list before adding it.\n // This could happen if an AutoNumeric element is initialized, then the DOM element is removed directly via `removeChild` (hence the reference does not get removed from the global list), then it get recreated and initialized again\n if (this._isInGlobalList(domElement)) {\n if (this._getFromGlobalList(domElement) === this) {\n // Do not add this AutoNumeric object again since it's already in that global list\n return;\n } else {\n // Print a warning to warn that the domElement already has a reference in the global map (but we cannot for sure starts deleting those old references since they could still be used by another AutoNumeric object)\n _AutoNumericHelper2.default.warning('A reference to the DOM element you just initialized already exists in the global AutoNumeric element list. Please make sure to not initialize the same DOM element multiple times.', autoNumericObject.getSettings().showWarnings);\n }\n }\n\n window[this.autoNumericGlobalListName].set(domElement, autoNumericObject);\n }\n\n /**\n * Remove the given object from the global AutoNumeric element list.\n *\n * @param {AutoNumeric} autoNumericObject\n * @private\n */\n\n }, {\n key: '_removeFromGlobalList',\n value: function _removeFromGlobalList(autoNumericObject) {\n //FIXME test this\n if (this._doesGlobalListExists()) {\n window[this.autoNumericGlobalListName].delete(autoNumericObject.node());\n }\n }\n\n /**\n * Return the value associated to the key `domElement` passed as a parameter.\n * The value is the AutoNumeric object that manages the DOM element `domElement`.\n *\n * @param {HTMLElement|HTMLInputElement} domElement\n * @returns {null|AutoNumeric}\n * @private\n */\n\n }, {\n key: '_getFromGlobalList',\n value: function _getFromGlobalList(domElement) {\n //FIXME test this\n if (this._doesGlobalListExists()) {\n return window[this.autoNumericGlobalListName].get(domElement);\n }\n\n return null;\n }\n\n /**\n * Check if the given DOM element is in the global AutoNumeric element list.\n *\n * @param {HTMLElement|HTMLInputElement} domElement\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_isInGlobalList',\n value: function _isInGlobalList(domElement) {\n //FIXME test this\n if (!this._doesGlobalListExists()) {\n return false;\n }\n\n return window[this.autoNumericGlobalListName].has(domElement);\n }\n }, {\n key: 'validate',\n value: function validate(userOptions) {\n var shouldExtendDefaultOptions = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n var originalOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(userOptions) || !_AutoNumericHelper2.default.isObject(userOptions)) {\n _AutoNumericHelper2.default.throwError('The userOptions are invalid ; it should be a valid object, [' + userOptions + '] given.');\n }\n\n var isOriginalOptionAnObject = _AutoNumericHelper2.default.isObject(originalOptions);\n if (!isOriginalOptionAnObject && !_AutoNumericHelper2.default.isNull(originalOptions)) {\n _AutoNumericHelper2.default.throwError('The \\'originalOptions\\' parameter is invalid ; it should either be a valid option object or `null`, [' + userOptions + '] given.');\n }\n\n // If the user used old options, we convert them to new ones\n if (!_AutoNumericHelper2.default.isNull(userOptions)) {\n this._convertOldOptionsToNewOnes(userOptions);\n }\n\n // The user can choose if the `userOptions` has already been extended with the default options, or not\n var options = void 0;\n if (shouldExtendDefaultOptions) {\n options = _extends({}, this.getDefaultConfig(), userOptions);\n } else {\n options = userOptions;\n }\n\n // First things first, we test that the `showWarnings` option is valid\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.showWarnings) && !_AutoNumericHelper2.default.isBoolean(options.showWarnings)) {\n _AutoNumericHelper2.default.throwError('The debug option \\'showWarnings\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.showWarnings + '] given.');\n }\n\n // Define the regular expressions needed for the following tests\n var testPositiveInteger = /^[0-9]+$/;\n var testNumericalCharacters = /[0-9]+/;\n // const testFloatAndPossibleNegativeSign = /^-?[0-9]+(\\.?[0-9]+)$/;\n var testFloatOrIntegerAndPossibleNegativeSign = /^-?[0-9]+(\\.?[0-9]+)?$/;\n var testPositiveFloatOrInteger = /^[0-9]+(\\.?[0-9]+)?$/;\n\n // Then tests the options individually\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.allowDecimalPadding) && !_AutoNumericHelper2.default.isBoolean(options.allowDecimalPadding) && options.allowDecimalPadding !== AutoNumeric.options.allowDecimalPadding.floats) {\n _AutoNumericHelper2.default.throwError('The decimal padding option \\'allowDecimalPadding\\' is invalid ; it should either be `false`, `true` or `\\'floats\\'`, [' + options.allowDecimalPadding + '] given.');\n }\n\n if ((options.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.never || options.allowDecimalPadding === 'false') && (options.decimalPlaces !== AutoNumeric.options.decimalPlaces.none || options.decimalPlacesShownOnBlur !== AutoNumeric.options.decimalPlacesShownOnBlur.none || options.decimalPlacesShownOnFocus !== AutoNumeric.options.decimalPlacesShownOnFocus.none)) {\n _AutoNumericHelper2.default.warning('Setting \\'allowDecimalPadding\\' to [' + options.allowDecimalPadding + '] will override the current \\'decimalPlaces*\\' settings [' + options.decimalPlaces + ', ' + options.decimalPlacesShownOnBlur + ' and ' + options.decimalPlacesShownOnFocus + '].', options.showWarnings);\n }\n\n if (!_AutoNumericHelper2.default.isNull(options.caretPositionOnFocus) && !_AutoNumericHelper2.default.isInArray(options.caretPositionOnFocus, [AutoNumeric.options.caretPositionOnFocus.start, AutoNumeric.options.caretPositionOnFocus.end, AutoNumeric.options.caretPositionOnFocus.decimalLeft, AutoNumeric.options.caretPositionOnFocus.decimalRight])) {\n _AutoNumericHelper2.default.throwError('The display on empty string option \\'caretPositionOnFocus\\' is invalid ; it should either be `null`, \\'focus\\', \\'press\\', \\'always\\' or \\'zero\\', [' + options.caretPositionOnFocus + '] given.');\n }\n\n // Special case here for `caretPositionOnFocus` and `selectOnFocus` where we need to check the original non-tempered version of the options in order to check for conflicts, since using the default settings remove those and would prevent us warning the user that his option object is not correct.\n var optionsToUse = void 0;\n if (isOriginalOptionAnObject) {\n optionsToUse = originalOptions;\n } else {\n optionsToUse = this._correctCaretPositionOnFocusAndSelectOnFocusOptions(userOptions);\n }\n\n if (!_AutoNumericHelper2.default.isNull(optionsToUse) && optionsToUse.caretPositionOnFocus !== AutoNumeric.options.caretPositionOnFocus.doNoForceCaretPosition && optionsToUse.selectOnFocus === AutoNumeric.options.selectOnFocus.select) {\n _AutoNumericHelper2.default.warning('The \\'selectOnFocus\\' option is set to \\'select\\', which is in conflict with the \\'caretPositionOnFocus\\' which is set to \\'' + optionsToUse.caretPositionOnFocus + '\\'. As a result, if this has been called when instantiating an AutoNumeric object, the \\'selectOnFocus\\' option is forced to \\'doNotSelect\\'.', options.showWarnings);\n }\n\n if (!_AutoNumericHelper2.default.isInArray(options.digitGroupSeparator, [AutoNumeric.options.digitGroupSeparator.comma, AutoNumeric.options.digitGroupSeparator.dot, AutoNumeric.options.digitGroupSeparator.normalSpace, AutoNumeric.options.digitGroupSeparator.thinSpace, AutoNumeric.options.digitGroupSeparator.narrowNoBreakSpace, AutoNumeric.options.digitGroupSeparator.noBreakSpace, AutoNumeric.options.digitGroupSeparator.noSeparator, AutoNumeric.options.digitGroupSeparator.apostrophe, AutoNumeric.options.digitGroupSeparator.arabicThousandsSeparator, AutoNumeric.options.digitGroupSeparator.dotAbove])) {\n _AutoNumericHelper2.default.throwError('The thousand separator character option \\'digitGroupSeparator\\' is invalid ; it should be \\',\\', \\'.\\', \\'\\u066C\\', \\'\\u02D9\\', \"\\'\", \\' \\', \\'\\u2009\\', \\'\\u202F\\', \\'\\xA0\\' or empty (\\'\\'), [' + options.digitGroupSeparator + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.showOnlyNumbersOnFocus) && !_AutoNumericHelper2.default.isBoolean(options.showOnlyNumbersOnFocus)) {\n _AutoNumericHelper2.default.throwError('The \\'showOnlyNumbersOnFocus\\' option is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.showOnlyNumbersOnFocus + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isInArray(options.digitalGroupSpacing, [AutoNumeric.options.digitalGroupSpacing.two, AutoNumeric.options.digitalGroupSpacing.twoScaled, AutoNumeric.options.digitalGroupSpacing.three, AutoNumeric.options.digitalGroupSpacing.four]) && !(options.digitalGroupSpacing >= 2 && options.digitalGroupSpacing <= 4)) {\n _AutoNumericHelper2.default.throwError('The grouping separator option for thousands \\'digitalGroupSpacing\\' is invalid ; it should be \\'2\\', \\'2s\\', \\'3\\', or \\'4\\', [' + options.digitalGroupSpacing + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isInArray(options.decimalCharacter, [AutoNumeric.options.decimalCharacter.comma, AutoNumeric.options.decimalCharacter.dot, AutoNumeric.options.decimalCharacter.middleDot, AutoNumeric.options.decimalCharacter.arabicDecimalSeparator, AutoNumeric.options.decimalCharacter.decimalSeparatorKeySymbol])) {\n _AutoNumericHelper2.default.throwError('The decimal separator character option \\'decimalCharacter\\' is invalid ; it should be \\'.\\', \\',\\', \\'\\xB7\\', \\'\\u2396\\' or \\'\\u066B\\', [' + options.decimalCharacter + '] given.');\n }\n\n // Checks if the decimal and thousand characters are the same\n if (options.decimalCharacter === options.digitGroupSeparator) {\n _AutoNumericHelper2.default.throwError('autoNumeric will not function properly when the decimal character \\'decimalCharacter\\' [' + options.decimalCharacter + '] and the thousand separator \\'digitGroupSeparator\\' [' + options.digitGroupSeparator + '] are the same character.');\n }\n\n if (!_AutoNumericHelper2.default.isNull(options.decimalCharacterAlternative) && !_AutoNumericHelper2.default.isString(options.decimalCharacterAlternative)) {\n _AutoNumericHelper2.default.throwError('The alternate decimal separator character option \\'decimalCharacterAlternative\\' is invalid ; it should be a string, [' + options.decimalCharacterAlternative + '] given.');\n }\n\n if (options.currencySymbol !== '' && !_AutoNumericHelper2.default.isString(options.currencySymbol)) {\n _AutoNumericHelper2.default.throwError('The currency symbol option \\'currencySymbol\\' is invalid ; it should be a string, [' + options.currencySymbol + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isInArray(options.currencySymbolPlacement, [AutoNumeric.options.currencySymbolPlacement.prefix, AutoNumeric.options.currencySymbolPlacement.suffix])) {\n _AutoNumericHelper2.default.throwError('The placement of the currency sign option \\'currencySymbolPlacement\\' is invalid ; it should either be \\'p\\' (prefix) or \\'s\\' (suffix), [' + options.currencySymbolPlacement + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isInArray(options.negativePositiveSignPlacement, [AutoNumeric.options.negativePositiveSignPlacement.prefix, AutoNumeric.options.negativePositiveSignPlacement.suffix, AutoNumeric.options.negativePositiveSignPlacement.left, AutoNumeric.options.negativePositiveSignPlacement.right, AutoNumeric.options.negativePositiveSignPlacement.none])) {\n _AutoNumericHelper2.default.throwError('The placement of the negative sign option \\'negativePositiveSignPlacement\\' is invalid ; it should either be \\'p\\' (prefix), \\'s\\' (suffix), \\'l\\' (left), \\'r\\' (right) or \\'null\\', [' + options.negativePositiveSignPlacement + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.showPositiveSign) && !_AutoNumericHelper2.default.isBoolean(options.showPositiveSign)) {\n _AutoNumericHelper2.default.throwError('The show positive sign option \\'showPositiveSign\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.showPositiveSign + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isString(options.suffixText) || options.suffixText !== '' && (_AutoNumericHelper2.default.isNegative(options.suffixText, options.negativeSignCharacter) || testNumericalCharacters.test(options.suffixText))) {\n _AutoNumericHelper2.default.throwError('The additional suffix option \\'suffixText\\' is invalid ; it should not contains the negative sign \\'' + this.settings.negativeSignCharacter + '\\' nor any numerical characters, [' + options.suffixText + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isString(options.negativeSignCharacter) || options.negativeSignCharacter.length !== 1 || _AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options.negativeSignCharacter) || testNumericalCharacters.test(options.negativeSignCharacter)) {\n _AutoNumericHelper2.default.throwError('The negative sign character option \\'negativeSignCharacter\\' is invalid ; it should be a single character, and cannot be any numerical characters, [' + options.negativeSignCharacter + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isString(options.positiveSignCharacter) || options.positiveSignCharacter.length !== 1 || _AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options.positiveSignCharacter) || testNumericalCharacters.test(options.positiveSignCharacter)) {\n _AutoNumericHelper2.default.throwError('The positive sign character option \\'positiveSignCharacter\\' is invalid ; it should be a single character, and cannot be any numerical characters, [' + options.positiveSignCharacter + '] given.\\nIf you want to hide the positive sign character, you need to set the `showPositiveSign` option to `true`.');\n }\n\n if (options.negativeSignCharacter === options.positiveSignCharacter) {\n _AutoNumericHelper2.default.throwError('The positive \\'positiveSignCharacter\\' and negative \\'negativeSignCharacter\\' sign characters cannot be identical ; [' + options.negativeSignCharacter + '] given.');\n }\n\n var _ref5 = _AutoNumericHelper2.default.isNull(options.negativeBracketsTypeOnBlur) ? ['', ''] : options.negativeBracketsTypeOnBlur.split(','),\n _ref6 = _slicedToArray(_ref5, 2),\n leftBracket = _ref6[0],\n rightBracket = _ref6[1];\n\n if (_AutoNumericHelper2.default.contains(options.digitGroupSeparator, options.negativeSignCharacter) || _AutoNumericHelper2.default.contains(options.decimalCharacter, options.negativeSignCharacter) || _AutoNumericHelper2.default.contains(options.decimalCharacterAlternative, options.negativeSignCharacter) || _AutoNumericHelper2.default.contains(leftBracket, options.negativeSignCharacter) || _AutoNumericHelper2.default.contains(rightBracket, options.negativeSignCharacter) || _AutoNumericHelper2.default.contains(options.suffixText, options.negativeSignCharacter)) {\n _AutoNumericHelper2.default.throwError('The negative sign character option \\'negativeSignCharacter\\' is invalid ; it should not be equal or a part of the digit separator, the decimal character, the decimal character alternative, the negative brackets or the suffix text, [' + options.negativeSignCharacter + '] given.');\n }\n\n if (_AutoNumericHelper2.default.contains(options.digitGroupSeparator, options.positiveSignCharacter) || _AutoNumericHelper2.default.contains(options.decimalCharacter, options.positiveSignCharacter) || _AutoNumericHelper2.default.contains(options.decimalCharacterAlternative, options.positiveSignCharacter) || _AutoNumericHelper2.default.contains(leftBracket, options.positiveSignCharacter) || _AutoNumericHelper2.default.contains(rightBracket, options.positiveSignCharacter) || _AutoNumericHelper2.default.contains(options.suffixText, options.positiveSignCharacter)) {\n _AutoNumericHelper2.default.throwError('The positive sign character option \\'positiveSignCharacter\\' is invalid ; it should not be equal or a part of the digit separator, the decimal character, the decimal character alternative, the negative brackets or the suffix text, [' + options.positiveSignCharacter + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isNull(options.overrideMinMaxLimits) && !_AutoNumericHelper2.default.isInArray(options.overrideMinMaxLimits, [AutoNumeric.options.overrideMinMaxLimits.ceiling, AutoNumeric.options.overrideMinMaxLimits.floor, AutoNumeric.options.overrideMinMaxLimits.ignore])) {\n _AutoNumericHelper2.default.throwError('The override min & max limits option \\'overrideMinMaxLimits\\' is invalid ; it should either be \\'ceiling\\', \\'floor\\' or \\'ignore\\', [' + options.overrideMinMaxLimits + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isString(options.maximumValue) || !testFloatOrIntegerAndPossibleNegativeSign.test(options.maximumValue)) {\n _AutoNumericHelper2.default.throwError('The maximum possible value option \\'maximumValue\\' is invalid ; it should be a string that represents a positive or negative number, [' + options.maximumValue + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isString(options.minimumValue) || !testFloatOrIntegerAndPossibleNegativeSign.test(options.minimumValue)) {\n _AutoNumericHelper2.default.throwError('The minimum possible value option \\'minimumValue\\' is invalid ; it should be a string that represents a positive or negative number, [' + options.minimumValue + '] given.');\n }\n\n if (parseFloat(options.minimumValue) > parseFloat(options.maximumValue)) {\n _AutoNumericHelper2.default.throwError('The minimum possible value option is greater than the maximum possible value option ; \\'minimumValue\\' [' + options.minimumValue + '] should be smaller than \\'maximumValue\\' [' + options.maximumValue + '].');\n }\n\n if (!(_AutoNumericHelper2.default.isInt(options.decimalPlaces) && options.decimalPlaces >= 0 || // If integer option\n _AutoNumericHelper2.default.isString(options.decimalPlaces) && testPositiveInteger.test(options.decimalPlaces)) // If string option\n ) {\n _AutoNumericHelper2.default.throwError('The number of decimal places option \\'decimalPlaces\\' is invalid ; it should be a positive integer, [' + options.decimalPlaces + '] given.');\n }\n\n if (!(_AutoNumericHelper2.default.isNull(options.decimalPlacesRawValue) || _AutoNumericHelper2.default.isInt(options.decimalPlacesRawValue) && options.decimalPlacesRawValue >= 0 || // If integer option\n _AutoNumericHelper2.default.isString(options.decimalPlacesRawValue) && testPositiveInteger.test(options.decimalPlacesRawValue)) // If string option\n ) {\n _AutoNumericHelper2.default.throwError('The number of decimal places for the raw value option \\'decimalPlacesRawValue\\' is invalid ; it should be a positive integer or `null`, [' + options.decimalPlacesRawValue + '] given.');\n }\n\n // Checks if the number of decimal places for the raw value is lower than the `decimalPlaces`, `decimalPlacesShownOnFocus` and/or `decimalPlacesShownOnBlur` options\n this._validateDecimalPlacesRawValue(options);\n\n if (!_AutoNumericHelper2.default.isNull(options.decimalPlacesShownOnFocus) && !testPositiveInteger.test(String(options.decimalPlacesShownOnFocus))) {\n _AutoNumericHelper2.default.throwError('The number of expanded decimal places option \\'decimalPlacesShownOnFocus\\' is invalid ; it should be a positive integer or `null`, [' + options.decimalPlacesShownOnFocus + '] given.');\n }\n\n // Checks if the extended decimal places \"decimalPlacesShownOnFocus\" is greater than the decimal places number `decimalPlaces`\n if (!_AutoNumericHelper2.default.isNull(options.decimalPlacesShownOnFocus) && Number(options.decimalPlaces) > Number(options.decimalPlacesShownOnFocus)) {\n _AutoNumericHelper2.default.warning('The extended decimal places \\'decimalPlacesShownOnFocus\\' [' + options.decimalPlacesShownOnFocus + '] should be greater than the \\'decimalPlaces\\' [' + options.decimalPlaces + '] value. Currently, this will limit the ability of your user to manually change some of the decimal places. Do you really want to do that?', options.showWarnings);\n }\n\n if (!_AutoNumericHelper2.default.isNull(options.divisorWhenUnfocused) && !testPositiveFloatOrInteger.test(options.divisorWhenUnfocused) || options.divisorWhenUnfocused === 0 || options.divisorWhenUnfocused === '0' || options.divisorWhenUnfocused === 1 || options.divisorWhenUnfocused === '1') {\n _AutoNumericHelper2.default.throwError('The divisor option \\'divisorWhenUnfocused\\' is invalid ; it should be a positive number higher than one, preferably an integer, [' + options.divisorWhenUnfocused + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isNull(options.decimalPlacesShownOnBlur) && !testPositiveInteger.test(options.decimalPlacesShownOnBlur)) {\n _AutoNumericHelper2.default.throwError('The number of decimals shown when unfocused option \\'decimalPlacesShownOnBlur\\' is invalid ; it should be a positive integer or `null`, [' + options.decimalPlacesShownOnBlur + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isNull(options.symbolWhenUnfocused) && !_AutoNumericHelper2.default.isString(options.symbolWhenUnfocused)) {\n _AutoNumericHelper2.default.throwError('The symbol to show when unfocused option \\'symbolWhenUnfocused\\' is invalid ; it should be a string, [' + options.symbolWhenUnfocused + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.saveValueToSessionStorage) && !_AutoNumericHelper2.default.isBoolean(options.saveValueToSessionStorage)) {\n _AutoNumericHelper2.default.throwError('The save to session storage option \\'saveValueToSessionStorage\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.saveValueToSessionStorage + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isInArray(options.onInvalidPaste, [AutoNumeric.options.onInvalidPaste.error, AutoNumeric.options.onInvalidPaste.ignore, AutoNumeric.options.onInvalidPaste.clamp, AutoNumeric.options.onInvalidPaste.truncate, AutoNumeric.options.onInvalidPaste.replace])) {\n _AutoNumericHelper2.default.throwError('The paste behavior option \\'onInvalidPaste\\' is invalid ; it should either be \\'error\\', \\'ignore\\', \\'clamp\\', \\'truncate\\' or \\'replace\\' (cf. documentation), [' + options.onInvalidPaste + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isInArray(options.roundingMethod, [AutoNumeric.options.roundingMethod.halfUpSymmetric, AutoNumeric.options.roundingMethod.halfUpAsymmetric, AutoNumeric.options.roundingMethod.halfDownSymmetric, AutoNumeric.options.roundingMethod.halfDownAsymmetric, AutoNumeric.options.roundingMethod.halfEvenBankersRounding, AutoNumeric.options.roundingMethod.upRoundAwayFromZero, AutoNumeric.options.roundingMethod.downRoundTowardZero, AutoNumeric.options.roundingMethod.toCeilingTowardPositiveInfinity, AutoNumeric.options.roundingMethod.toFloorTowardNegativeInfinity, AutoNumeric.options.roundingMethod.toNearest05, AutoNumeric.options.roundingMethod.toNearest05Alt, AutoNumeric.options.roundingMethod.upToNext05, AutoNumeric.options.roundingMethod.downToNext05])) {\n _AutoNumericHelper2.default.throwError('The rounding method option \\'roundingMethod\\' is invalid ; it should either be \\'S\\', \\'A\\', \\'s\\', \\'a\\', \\'B\\', \\'U\\', \\'D\\', \\'C\\', \\'F\\', \\'N05\\', \\'CHF\\', \\'U05\\' or \\'D05\\' (cf. documentation), [' + options.roundingMethod + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isNull(options.negativeBracketsTypeOnBlur) && !_AutoNumericHelper2.default.isInArray(options.negativeBracketsTypeOnBlur, [AutoNumeric.options.negativeBracketsTypeOnBlur.parentheses, AutoNumeric.options.negativeBracketsTypeOnBlur.brackets, AutoNumeric.options.negativeBracketsTypeOnBlur.chevrons, AutoNumeric.options.negativeBracketsTypeOnBlur.curlyBraces, AutoNumeric.options.negativeBracketsTypeOnBlur.angleBrackets, AutoNumeric.options.negativeBracketsTypeOnBlur.japaneseQuotationMarks, AutoNumeric.options.negativeBracketsTypeOnBlur.halfBrackets, AutoNumeric.options.negativeBracketsTypeOnBlur.whiteSquareBrackets, AutoNumeric.options.negativeBracketsTypeOnBlur.quotationMarks, AutoNumeric.options.negativeBracketsTypeOnBlur.guillemets])) {\n _AutoNumericHelper2.default.throwError('The brackets for negative values option \\'negativeBracketsTypeOnBlur\\' is invalid ; it should either be \\'(,)\\', \\'[,]\\', \\'<,>\\', \\'{,}\\', \\'\\u3008,\\u3009\\', \\'\\uFF62,\\uFF63\\', \\'\\u2E24,\\u2E25\\', \\'\\u27E6,\\u27E7\\', \\'\\u2039,\\u203A\\' or \\'\\xAB,\\xBB\\', [' + options.negativeBracketsTypeOnBlur + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isInArray(options.emptyInputBehavior, [AutoNumeric.options.emptyInputBehavior.focus, AutoNumeric.options.emptyInputBehavior.press, AutoNumeric.options.emptyInputBehavior.always, AutoNumeric.options.emptyInputBehavior.zero, AutoNumeric.options.emptyInputBehavior.null])) {\n _AutoNumericHelper2.default.throwError('The display on empty string option \\'emptyInputBehavior\\' is invalid ; it should either be \\'focus\\', \\'press\\', \\'always\\', \\'zero\\' or \\'null\\', [' + options.emptyInputBehavior + '] given.');\n }\n\n if (options.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.zero && (options.minimumValue > 0 || options.maximumValue < 0)) {\n _AutoNumericHelper2.default.throwError('The \\'emptyInputBehavior\\' option is set to \\'zero\\', but this value is outside of the range defined by \\'minimumValue\\' and \\'maximumValue\\' [' + options.minimumValue + ', ' + options.maximumValue + '].');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.eventBubbles) && !_AutoNumericHelper2.default.isBoolean(options.eventBubbles)) {\n _AutoNumericHelper2.default.throwError('The event bubbles option \\'eventBubbles\\' is invalid ; it should be either \\'true\\' or \\'false\\', [' + options.eventBubbles + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.eventIsCancelable) && !_AutoNumericHelper2.default.isBoolean(options.eventIsCancelable)) {\n _AutoNumericHelper2.default.throwError('The event is cancelable option \\'eventIsCancelable\\' is invalid ; it should be either \\'true\\' or \\'false\\', [' + options.eventIsCancelable + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isInArray(options.leadingZero, [AutoNumeric.options.leadingZero.allow, AutoNumeric.options.leadingZero.deny, AutoNumeric.options.leadingZero.keep])) {\n _AutoNumericHelper2.default.throwError('The leading zero behavior option \\'leadingZero\\' is invalid ; it should either be \\'allow\\', \\'deny\\' or \\'keep\\', [' + options.leadingZero + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.formatOnPageLoad) && !_AutoNumericHelper2.default.isBoolean(options.formatOnPageLoad)) {\n _AutoNumericHelper2.default.throwError('The format on initialization option \\'formatOnPageLoad\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.formatOnPageLoad + '] given.');\n }\n\n if (!testPositiveInteger.test(options.historySize) || options.historySize === 0) {\n _AutoNumericHelper2.default.throwError('The history size option \\'historySize\\' is invalid ; it should be a positive integer, [' + options.historySize + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.selectNumberOnly) && !_AutoNumericHelper2.default.isBoolean(options.selectNumberOnly)) {\n _AutoNumericHelper2.default.throwError('The select number only option \\'selectNumberOnly\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.selectNumberOnly + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.selectOnFocus) && !_AutoNumericHelper2.default.isBoolean(options.selectOnFocus)) {\n _AutoNumericHelper2.default.throwError('The select on focus option \\'selectOnFocus\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.selectOnFocus + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isNull(options.defaultValueOverride) && options.defaultValueOverride !== '' && !testFloatOrIntegerAndPossibleNegativeSign.test(options.defaultValueOverride)) {\n _AutoNumericHelper2.default.throwError('The unformatted default value option \\'defaultValueOverride\\' is invalid ; it should be a string that represents a positive or negative number, [' + options.defaultValueOverride + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.unformatOnSubmit) && !_AutoNumericHelper2.default.isBoolean(options.unformatOnSubmit)) {\n _AutoNumericHelper2.default.throwError('The remove formatting on submit option \\'unformatOnSubmit\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.unformatOnSubmit + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isNull(options.valuesToStrings) && !_AutoNumericHelper2.default.isObject(options.valuesToStrings)) {\n _AutoNumericHelper2.default.throwError('The option \\'valuesToStrings\\' is invalid ; it should be an object, ideally with \\'key -> value\\' entries, [' + options.valuesToStrings + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isNull(options.outputFormat) && !_AutoNumericHelper2.default.isInArray(options.outputFormat, [AutoNumeric.options.outputFormat.string, AutoNumeric.options.outputFormat.number, AutoNumeric.options.outputFormat.dot, AutoNumeric.options.outputFormat.negativeDot, AutoNumeric.options.outputFormat.comma, AutoNumeric.options.outputFormat.negativeComma, AutoNumeric.options.outputFormat.dotNegative, AutoNumeric.options.outputFormat.commaNegative])) {\n _AutoNumericHelper2.default.throwError('The custom locale format option \\'outputFormat\\' is invalid ; it should either be null, \\'string\\', \\'number\\', \\'.\\', \\'-.\\', \\',\\', \\'-,\\', \\'.-\\' or \\',-\\', [' + options.outputFormat + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.isCancellable) && !_AutoNumericHelper2.default.isBoolean(options.isCancellable)) {\n _AutoNumericHelper2.default.throwError('The cancellable behavior option \\'isCancellable\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.isCancellable + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.modifyValueOnWheel) && !_AutoNumericHelper2.default.isBoolean(options.modifyValueOnWheel)) {\n _AutoNumericHelper2.default.throwError('The increment/decrement on mouse wheel option \\'modifyValueOnWheel\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.modifyValueOnWheel + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.watchExternalChanges) && !_AutoNumericHelper2.default.isBoolean(options.watchExternalChanges)) {\n _AutoNumericHelper2.default.throwError('The option \\'watchExternalChanges\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.watchExternalChanges + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isInArray(options.wheelOn, [AutoNumeric.options.wheelOn.focus, AutoNumeric.options.wheelOn.hover])) {\n _AutoNumericHelper2.default.throwError('The wheel behavior option \\'wheelOn\\' is invalid ; it should either be \\'focus\\' or \\'hover\\', [' + options.wheelOn + '] given.');\n }\n\n if (!(_AutoNumericHelper2.default.isString(options.wheelStep) || _AutoNumericHelper2.default.isNumber(options.wheelStep)) || options.wheelStep !== 'progressive' && !testPositiveFloatOrInteger.test(options.wheelStep) || Number(options.wheelStep) === 0) {\n // A step equal to '0' is rejected\n _AutoNumericHelper2.default.throwError('The wheel step value option \\'wheelStep\\' is invalid ; it should either be the string \\'progressive\\', or a number or a string that represents a positive number (excluding zero), [' + options.wheelStep + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isInArray(options.serializeSpaces, [AutoNumeric.options.serializeSpaces.plus, AutoNumeric.options.serializeSpaces.percent])) {\n _AutoNumericHelper2.default.throwError('The space replacement character option \\'serializeSpaces\\' is invalid ; it should either be \\'+\\' or \\'%20\\', [' + options.serializeSpaces + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.noEventListeners) && !_AutoNumericHelper2.default.isBoolean(options.noEventListeners)) {\n _AutoNumericHelper2.default.throwError('The option \\'noEventListeners\\' that prevent the creation of event listeners is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.noEventListeners + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isNull(options.styleRules) && !(_AutoNumericHelper2.default.isObject(options.styleRules) && (options.styleRules.hasOwnProperty('positive') || options.styleRules.hasOwnProperty('negative') || options.styleRules.hasOwnProperty('ranges') || options.styleRules.hasOwnProperty('userDefined')))) {\n _AutoNumericHelper2.default.throwError('The option \\'styleRules\\' is invalid ; it should be a correctly structured object, with one or more \\'positive\\', \\'negative\\', \\'ranges\\' or \\'userDefined\\' attributes, [' + options.styleRules + '] given.');\n }\n\n // Deeper tests of the `styleRules` object : Check that the callback, if defined, is a function\n if (!_AutoNumericHelper2.default.isNull(options.styleRules) && options.styleRules.hasOwnProperty('userDefined') && !_AutoNumericHelper2.default.isNull(options.styleRules.userDefined)) {\n options.styleRules.userDefined.forEach(function (rule) {\n if (rule.hasOwnProperty('callback') && !_AutoNumericHelper2.default.isFunction(rule.callback)) {\n _AutoNumericHelper2.default.throwError('The callback defined in the `userDefined` attribute is not a function, ' + _typeof(rule.callback) + ' given.');\n }\n });\n }\n\n if (!_AutoNumericHelper2.default.isNull(options.rawValueDivisor) && !testPositiveFloatOrInteger.test(options.rawValueDivisor) || options.rawValueDivisor === 0 || options.rawValueDivisor === '0' || options.rawValueDivisor === 1 || options.rawValueDivisor === '1') {\n _AutoNumericHelper2.default.throwError('The raw value divisor option \\'rawValueDivisor\\' is invalid ; it should be a positive number higher than one, preferably an integer, [' + options.rawValueDivisor + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.readOnly) && !_AutoNumericHelper2.default.isBoolean(options.readOnly)) {\n _AutoNumericHelper2.default.throwError('The option \\'readOnly\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.readOnly + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.unformatOnHover) && !_AutoNumericHelper2.default.isBoolean(options.unformatOnHover)) {\n _AutoNumericHelper2.default.throwError('The option \\'unformatOnHover\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.unformatOnHover + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.failOnUnknownOption) && !_AutoNumericHelper2.default.isBoolean(options.failOnUnknownOption)) {\n _AutoNumericHelper2.default.throwError('The debug option \\'failOnUnknownOption\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.failOnUnknownOption + '] given.');\n }\n\n if (!_AutoNumericHelper2.default.isTrueOrFalseString(options.createLocalList) && !_AutoNumericHelper2.default.isBoolean(options.createLocalList)) {\n _AutoNumericHelper2.default.throwError('The debug option \\'createLocalList\\' is invalid ; it should be either \\'false\\' or \\'true\\', [' + options.createLocalList + '] given.');\n }\n }\n\n /**\n * Check the `decimalPlaces*` options and output the relevant warnings if some of those will get overwritten during the initialization or settings update.\n *\n * @param {object} options\n * @private\n */\n\n }, {\n key: '_validateDecimalPlacesRawValue',\n value: function _validateDecimalPlacesRawValue(options) {\n // Checks if the number of decimal places for the raw value is lower than the `decimalPlaces`, `decimalPlacesShownOnFocus` and/or `decimalPlacesShownOnBlur` options\n if (!_AutoNumericHelper2.default.isNull(options.decimalPlacesRawValue)) {\n if (options.decimalPlacesRawValue < options.decimalPlaces) {\n _AutoNumericHelper2.default.warning('The number of decimal places to store in the raw value [' + options.decimalPlacesRawValue + '] is lower than the ones to display [' + options.decimalPlaces + ']. This will likely confuse your users.\\nTo solve that, you\\'d need to either set `decimalPlacesRawValue` to `null`, or set a number of decimal places for the raw value equal of bigger than `decimalPlaces`.', options.showWarnings);\n }\n\n if (options.decimalPlacesRawValue < options.decimalPlacesShownOnFocus) {\n _AutoNumericHelper2.default.warning('The number of decimal places to store in the raw value [' + options.decimalPlacesRawValue + '] is lower than the ones shown on focus [' + options.decimalPlacesShownOnFocus + ']. This will likely confuse your users.\\nTo solve that, you\\'d need to either set `decimalPlacesRawValue` to `null`, or set a number of decimal places for the raw value equal of bigger than `decimalPlacesShownOnFocus`.', options.showWarnings);\n }\n\n if (options.decimalPlacesRawValue < options.decimalPlacesShownOnBlur) {\n _AutoNumericHelper2.default.warning('The number of decimal places to store in the raw value [' + options.decimalPlacesRawValue + '] is lower than the ones shown when unfocused [' + options.decimalPlacesShownOnBlur + ']. This will likely confuse your users.\\nTo solve that, you\\'d need to either set `decimalPlacesRawValue` to `null`, or set a number of decimal places for the raw value equal of bigger than `decimalPlacesShownOnBlur`.', options.showWarnings);\n }\n }\n }\n\n /**\n * Return `true` if the settings/options are valid, `false` otherwise.\n *\n * @param {object} options\n * @returns {boolean}\n */\n\n }, {\n key: 'areSettingsValid',\n value: function areSettingsValid(options) {\n var isValid = true;\n try {\n this.validate(options, true);\n } catch (error) {\n isValid = false;\n }\n\n return isValid;\n }\n\n /**\n * Return the default autoNumeric settings.\n *\n * @returns {object}\n */\n\n }, {\n key: 'getDefaultConfig',\n value: function getDefaultConfig() {\n return AutoNumeric.defaultSettings;\n }\n\n /**\n * Return all the predefined language options in one object.\n * You can also access a specific language object directly by using `AutoNumeric.getPredefinedOptions().French` for instance.\n *\n * @returns {object}\n */\n\n }, {\n key: 'getPredefinedOptions',\n value: function getPredefinedOptions() {\n return AutoNumeric.predefinedOptions;\n }\n\n /**\n * Analyse the given array `options` and return a single 'merged' option objet.\n * `options` can be `null`, or an array of an option objects, or an array containing another array of option objects / strings (pre-defined option names)\n *\n * @param {null|Array>} options\n * @returns {null|object}\n * @private\n */\n\n }, {\n key: '_generateOptionsObjectFromOptionsArray',\n value: function _generateOptionsObjectFromOptionsArray(options) {\n var _this13 = this;\n\n var optionsResult = void 0;\n if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options) || options.length === 0) {\n optionsResult = null;\n } else {\n optionsResult = {};\n if (options.length === 1 && Array.isArray(options[0])) {\n options[0].forEach(function (optionObject) {\n // Using `_getOptionObject()` allows using pre-defined names in the `options` array\n _extends(optionsResult, _this13._getOptionObject(optionObject));\n });\n } else if (options.length >= 1) {\n options.forEach(function (optionObject) {\n _extends(optionsResult, _this13._getOptionObject(optionObject));\n });\n }\n }\n\n return optionsResult;\n }\n\n /**\n * Format the given number (or numeric string) with the given options. This returns the formatted value as a string.\n * This can also format the given DOM element value with the given options and returns the formatted value as a string.\n * Note : This function does *not* update that element value with the newly formatted value.\n * This basically allows to get the formatted value without first having to initialize an AutoNumeric object.\n *\n * @param {number|string|HTMLElement|HTMLInputElement} numericStringOrDomElement A number, or a string that represent a javascript number, or a DOM element\n * @param {object|null} options Multiple objects can be passed, the latter overwriting the settings from the former ones\n * @returns {string|null}\n */\n\n }, {\n key: 'format',\n value: function format(numericStringOrDomElement) {\n if (_AutoNumericHelper2.default.isUndefined(numericStringOrDomElement) || numericStringOrDomElement === null) {\n return null;\n }\n\n // Retrieve the value to format\n var value = void 0;\n if (_AutoNumericHelper2.default.isElement(numericStringOrDomElement)) {\n value = _AutoNumericHelper2.default.getElementValue(numericStringOrDomElement);\n } else {\n value = numericStringOrDomElement;\n }\n\n if (!_AutoNumericHelper2.default.isString(value) && !_AutoNumericHelper2.default.isNumber(value)) {\n _AutoNumericHelper2.default.throwError('The value \"' + value + '\" being \"set\" is not numeric and therefore cannot be used appropriately.');\n }\n\n // Manage options\n\n for (var _len5 = arguments.length, options = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) {\n options[_key5 - 1] = arguments[_key5];\n }\n\n var optionsToUse = this._generateOptionsObjectFromOptionsArray(options);\n\n // Initiate a very basic settings object\n var settings = _extends({}, this.getDefaultConfig(), optionsToUse);\n settings.isNegativeSignAllowed = value < 0;\n settings.isPositiveSignAllowed = value >= 0;\n this._setBrackets(settings);\n\n var regex = {};\n this._cachesUsualRegularExpressions(settings, regex); // This is needed by `_stripAllNonNumberCharactersExceptCustomDecimalChar` that uses those regex\n\n // Check the validity of the `value` parameter\n // Convert the value to a numeric string, stripping unnecessary characters in the process\n var valueString = this._toNumericValue(value, settings);\n if (isNaN(Number(valueString))) {\n _AutoNumericHelper2.default.throwError('The value [' + valueString + '] that you are trying to format is not a recognized number.');\n }\n\n // Basic tests to check if the given valueString is valid\n\n var _checkIfInRangeWithOv = this._checkIfInRangeWithOverrideOption(valueString, settings),\n _checkIfInRangeWithOv2 = _slicedToArray(_checkIfInRangeWithOv, 2),\n minTest = _checkIfInRangeWithOv2[0],\n maxTest = _checkIfInRangeWithOv2[1];\n\n if (!minTest || !maxTest) {\n // Throw a custom event\n this._triggerEvent(AutoNumeric.events.formatted, document, {\n oldValue: null,\n newValue: null,\n oldRawValue: null,\n newRawValue: null,\n isPristine: null,\n error: 'Range test failed',\n aNElement: null\n });\n _AutoNumericHelper2.default.throwError('The value [' + valueString + '] being set falls outside of the minimumValue [' + settings.minimumValue + '] and maximumValue [' + settings.maximumValue + '] range set for this element');\n }\n\n // Directly format any `valuesToStrings` values, if found\n if (settings.valuesToStrings && this._checkValuesToStringsSettings(value, settings)) {\n return settings.valuesToStrings[value];\n }\n\n // Generate the `negativePositiveSignPlacement` option as needed\n this._correctNegativePositiveSignPlacementOption(settings);\n // Calculate the needed decimal places\n this._calculateDecimalPlacesOnInit(settings);\n\n // Multiply the raw value with `rawValueDivisor` if defined\n if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(settings.rawValueDivisor) && settings.rawValueDivisor !== 0 && // Only divide if the `rawValueDivisor` option is set\n valueString !== '' && valueString !== null) {\n // Do not modify the `valueString` if it's an empty string or null\n valueString *= settings.rawValueDivisor;\n }\n\n // Everything is ok, proceed to rounding, formatting and grouping\n valueString = this._roundFormattedValueShownOnFocus(valueString, settings);\n valueString = this._modifyNegativeSignAndDecimalCharacterForFormattedValue(valueString, settings);\n valueString = this._addGroupSeparators(valueString, settings, false, valueString);\n\n return valueString;\n }\n\n /**\n * Format the given DOM element value, and set the resulting value back as the element value.\n *\n * @param {HTMLElement|HTMLInputElement} domElement\n * @param {object} options\n * @returns {string|null}\n */\n\n }, {\n key: 'formatAndSet',\n value: function formatAndSet(domElement) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n //FIXME test this\n var formattedValue = this.format(domElement, options);\n _AutoNumericHelper2.default.setElementValue(domElement, formattedValue);\n\n return formattedValue;\n }\n\n /**\n * Unformat the given formatted string with the given options. This returns a numeric string.\n * It can also unformat the given DOM element value with the given options and returns the unformatted numeric string.\n * Note: This does *not* update that element value.\n * This basically allows to get the unformatted value without first having to initialize an AutoNumeric object.\n *\n * @param {string|number|HTMLElement|HTMLInputElement} numericStringOrDomElement A number, or a string that represent a javascript number, or a DOM element\n * @param {object|null} options Multiple objects can be passed, the latter overwriting the settings from the former ones\n * @returns {string|number|NaN}\n */\n\n }, {\n key: 'unformat',\n value: function unformat(numericStringOrDomElement) {\n if (_AutoNumericHelper2.default.isNumberStrict(numericStringOrDomElement)) {\n // Giving an unformatted value should return the same unformatted value, whatever the options passed as a parameter\n return numericStringOrDomElement;\n }\n\n // Retrieve the value to unformat\n var value = void 0;\n if (_AutoNumericHelper2.default.isElement(numericStringOrDomElement)) {\n value = _AutoNumericHelper2.default.getElementValue(numericStringOrDomElement);\n } else {\n value = numericStringOrDomElement;\n }\n\n if (value === '') {\n // This allows to be coherent when serializing forms with empty inputs. Fix issue #512.\n return '';\n }\n\n if (_AutoNumericHelper2.default.isUndefined(value) || value === null) {\n return null;\n }\n\n if (_AutoNumericHelper2.default.isArray(value) || _AutoNumericHelper2.default.isObject(value)) {\n // Check the validity of the `value` parameter\n _AutoNumericHelper2.default.throwError('A number or a string representing a number is needed to be able to unformat it, [' + value + '] given.');\n }\n\n // Manage options\n\n for (var _len6 = arguments.length, options = Array(_len6 > 1 ? _len6 - 1 : 0), _key6 = 1; _key6 < _len6; _key6++) {\n options[_key6 - 1] = arguments[_key6];\n }\n\n var optionsToUse = this._generateOptionsObjectFromOptionsArray(options);\n\n // Generate the settings\n var settings = _extends({}, this.getDefaultConfig(), optionsToUse);\n settings.isNegativeSignAllowed = false;\n settings.isPositiveSignAllowed = true;\n value = value.toString();\n\n // Directly unformat any `valuesToStrings` values, if found\n if (settings.valuesToStrings && this._checkStringsToValuesSettings(value, settings)) {\n return _AutoNumericHelper2.default.objectKeyLookup(settings.valuesToStrings, value);\n }\n\n // This checks if a negative sign is anywhere in the `value`, not just on the very first character (ie. '12345.67-')\n if (_AutoNumericHelper2.default.isNegative(value, settings.negativeSignCharacter)) {\n settings.isNegativeSignAllowed = true;\n settings.isPositiveSignAllowed = false;\n } else if (!_AutoNumericHelper2.default.isNull(settings.negativeBracketsTypeOnBlur)) {\n var _settings$negativeBra = settings.negativeBracketsTypeOnBlur.split(',');\n\n var _settings$negativeBra2 = _slicedToArray(_settings$negativeBra, 2);\n\n settings.firstBracket = _settings$negativeBra2[0];\n settings.lastBracket = _settings$negativeBra2[1];\n\n if (value.charAt(0) === settings.firstBracket && value.charAt(value.length - 1) === settings.lastBracket) {\n settings.isNegativeSignAllowed = true;\n settings.isPositiveSignAllowed = false;\n value = this._removeBrackets(value, settings, false);\n }\n }\n\n value = this._convertToNumericString(value, settings);\n var unwantedCharacters = new RegExp('[^+-0123456789.]', 'gi');\n if (unwantedCharacters.test(value)) {\n return NaN;\n }\n\n // Generate the `negativePositiveSignPlacement` option as needed\n this._correctNegativePositiveSignPlacementOption(settings);\n // Calculate the needed decimal places\n if (settings.decimalPlacesRawValue) {\n // `originalDecimalPlacesRawValue` needs to be defined\n settings.originalDecimalPlacesRawValue = settings.decimalPlacesRawValue;\n } else {\n settings.originalDecimalPlacesRawValue = settings.decimalPlaces;\n }\n\n this._calculateDecimalPlacesOnInit(settings);\n\n // Divide the raw value with `rawValueDivisor` if defined\n if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(settings.rawValueDivisor) && settings.rawValueDivisor !== 0 && // Only divide if the `rawValueDivisor` option is set\n value !== '' && value !== null) {\n // Do not modify the `value` if it's an empty string or null\n value /= settings.rawValueDivisor;\n }\n\n value = this._roundRawValue(value, settings);\n value = value.replace(settings.decimalCharacter, '.'); // Here we need to convert back the decimal character to a period since `_roundValue` adds it in some cases\n value = this._toLocale(value, settings.outputFormat, settings);\n\n return value;\n }\n\n /**\n * Unformat the given DOM element value, and set the resulting value back as the element value.\n *\n * @param {HTMLElement|HTMLInputElement} domElement\n * @param {object} options\n * @returns {*}\n */\n\n }, {\n key: 'unformatAndSet',\n value: function unformatAndSet(domElement) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n //FIXME test this\n var unformattedValue = this.unformat(domElement, options);\n _AutoNumericHelper2.default.setElementValue(domElement, unformattedValue);\n\n return unformattedValue;\n }\n\n /**\n * Unformat and localize the given formatted string with the given options. This returns a numeric string.\n * It can also unformat and localize the given DOM element value with the given options and returns the unformatted numeric string.\n * Note: This does *not* update that element value.\n * This basically allows to get the localized value without first having to initialize an AutoNumeric object.\n *\n * @param {string|number|HTMLElement|HTMLInputElement} numericStringOrDomElement\n * @param {object} settings\n * @returns {*}\n */\n\n }, {\n key: 'localize',\n value: function localize(numericStringOrDomElement) {\n var settings = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n var value = void 0;\n if (_AutoNumericHelper2.default.isElement(numericStringOrDomElement)) {\n value = _AutoNumericHelper2.default.getElementValue(numericStringOrDomElement);\n } else {\n value = numericStringOrDomElement;\n }\n\n if (value === '') {\n // This allows to be coherent when serializing forms with empty inputs. Fix issue #512.\n return '';\n }\n\n if (_AutoNumericHelper2.default.isNull(settings)) {\n settings = AutoNumeric.defaultSettings;\n }\n\n value = this.unformat(value, settings);\n\n //XXX The following code is pretty close to the one you can find in `getLocalized()`, but different enough so we won't refactor it.\n if (Number(value) === 0 && settings.leadingZero !== AutoNumeric.options.leadingZero.keep) {\n value = '0';\n }\n\n var outputFormatToUse = void 0;\n if (_AutoNumericHelper2.default.isNull(settings)) {\n outputFormatToUse = settings.outputFormat;\n } else {\n outputFormatToUse = AutoNumeric.defaultSettings.outputFormat;\n }\n\n return this._toLocale(value, outputFormatToUse, settings);\n }\n }, {\n key: 'localizeAndSet',\n value: function localizeAndSet(domElement) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n //FIXME test this\n var localizedValue = this.localize(domElement, options);\n _AutoNumericHelper2.default.setElementValue(domElement, localizedValue);\n\n return localizedValue;\n }\n\n /**\n * Return `true` if the given DOM element has an AutoNumeric object that manages it.\n * This function also accepts a selector string.\n *\n * @param {HTMLElement|string} domElementOrSelector Accepts either directly a DOM element to test, or a string selector (that will return one and only one element, if any)\n * @returns {boolean}\n */\n\n }, {\n key: 'isManagedByAutoNumeric',\n value: function isManagedByAutoNumeric(domElementOrSelector) {\n //FIXME test this\n return this._isInGlobalList(_AutoNumericHelper2.default.domElement(domElementOrSelector));\n }\n\n /**\n * Return the AutoNumeric object that manages the given DOM element.\n * This function also accepts a selector string.\n *\n * @param {HTMLElement|string} domElementOrSelector Accepts either directly a DOM element to test, or a string selector (that will return one and only one element, if any)\n * @returns {null|AutoNumeric}\n */\n\n }, {\n key: 'getAutoNumericElement',\n value: function getAutoNumericElement(domElementOrSelector) {\n var domElement = _AutoNumericHelper2.default.domElement(domElementOrSelector);\n\n if (!this.isManagedByAutoNumeric(domElement)) {\n return null;\n }\n\n return this._getFromGlobalList(domElement);\n }\n\n /**\n * Set the given element value, and format it immediately.\n * Return `null` if no AutoNumeric object is found, else, return the AutoNumeric object.\n *\n * @param {HTMLElement|string} domElementOrSelector Either a DOM element reference, or a selector string can be used\n * @param {number|string|null} newValue The value must be a Number, a numeric string or `null` (if `emptyInputBehavior` is set to `'null'`)\n * @param {object} options A settings object that will override the current settings. Note: the update is done only if the `newValue` is defined.\n * @param {boolean} saveChangeToHistory If set to `true`, then the change is recorded in the history table\n * @returns {AutoNumeric|null}\n */\n\n }, {\n key: 'set',\n value: function set(domElementOrSelector, newValue) {\n var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n var saveChangeToHistory = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;\n\n var domElement = _AutoNumericHelper2.default.domElement(domElementOrSelector);\n\n if (!this.isManagedByAutoNumeric(domElement)) {\n var showWarnings = void 0;\n if (!_AutoNumericHelper2.default.isNull(options) && options.hasOwnProperty('showWarnings')) {\n showWarnings = options.showWarnings;\n } else {\n showWarnings = true;\n }\n\n _AutoNumericHelper2.default.warning('Impossible to find an AutoNumeric object for the given DOM element or selector.', showWarnings);\n\n return null;\n }\n\n return this.getAutoNumericElement(domElement).set(newValue, options, saveChangeToHistory);\n }\n\n /**\n * Return the unformatted value as a string from the given DOM element or query selector.\n * This can also return `null` if `rawValue` is null.\n *\n * @param {HTMLElement|string} domElementOrSelector\n * @param {function|null} callback\n * @returns {string|null}\n */\n\n }, {\n key: 'getNumericString',\n value: function getNumericString(domElementOrSelector) {\n var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n return this._get(domElementOrSelector, AutoNumeric.getNumericString.name, callback);\n }\n\n /**\n * Return the current formatted value of the AutoNumeric element as a string, from the given DOM element or query selector.\n *\n * @param {HTMLElement|string} domElementOrSelector\n * @param {function|null} callback\n * @returns {string}\n */\n\n }, {\n key: 'getFormatted',\n value: function getFormatted(domElementOrSelector) {\n var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n return this._get(domElementOrSelector, AutoNumeric.getFormatted.name, callback);\n }\n\n /**\n * Return the element unformatted value as a real Javascript number, from the given DOM element or query selector.\n * Warning: This can lead to precision problems with big numbers that should be stored as strings.\n *\n * @param {HTMLElement|string} domElementOrSelector\n * @param {function|null} callback\n * @returns {number|null}\n */\n\n }, {\n key: 'getNumber',\n value: function getNumber(domElementOrSelector) {\n var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n return this._get(domElementOrSelector, AutoNumeric.getNumber.name, callback);\n }\n\n /**\n * DRY the code between the static `get*` functions\n *\n * @param {HTMLElement|string} domElementOrSelector\n * @param {string} getFunction The name of the non-static `get*` function as a string\n * @param {function|null} callback\n * @returns {*}\n * @private\n */\n\n }, {\n key: '_get',\n value: function _get(domElementOrSelector, getFunction) {\n var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n var domElement = _AutoNumericHelper2.default.domElement(domElementOrSelector);\n\n if (!this.isManagedByAutoNumeric(domElement)) {\n _AutoNumericHelper2.default.throwError('Impossible to find an AutoNumeric object for the given DOM element or selector.');\n }\n\n return this.getAutoNumericElement(domElement)[getFunction](callback);\n }\n\n /**\n * Returns the unformatted value following the `outputFormat` setting, from the given DOM element or query selector.\n * See the non-static `getLocalized()` method documentation for more details.\n *\n * @param {HTMLElement|string} domElementOrSelector\n * @param {null|string|function} forcedOutputFormat\n * @param {function|null} callback\n * @returns {*}\n */\n\n }, {\n key: 'getLocalized',\n value: function getLocalized(domElementOrSelector) {\n var forcedOutputFormat = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n var callback = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n var domElement = _AutoNumericHelper2.default.domElement(domElementOrSelector);\n\n if (!this.isManagedByAutoNumeric(domElement)) {\n _AutoNumericHelper2.default.throwError('Impossible to find an AutoNumeric object for the given DOM element or selector.');\n }\n\n return this.getAutoNumericElement(domElement).getLocalized(forcedOutputFormat, callback);\n }\n }, {\n key: '_stripAllNonNumberCharacters',\n value: function _stripAllNonNumberCharacters(s, settings, stripZeros, isFocused) {\n return this._stripAllNonNumberCharactersExceptCustomDecimalChar(s, settings, stripZeros, isFocused).replace(settings.decimalCharacter, '.');\n }\n\n /**\n * Strip all unwanted non-number characters except the custom decimal character.\n *\n * It converts the custom negative sign and removes the positive sign (custom or not).\n * This keeps :\n * - the numbers,\n * - the normal negative sign '-' if any,\n * - and the *custom* decimal character.\n *\n * @param {string} s\n * @param {object} settings\n * @param {boolean} stripZeros If set to `false`, then the leading zero(s) are not stripped, otherwise if set to `true`, the `leadingZero` option is followed\n * @param {boolean} isFocused If the element is focused, then this is `true`\n * @returns {string|*}\n */\n\n }, {\n key: '_stripAllNonNumberCharactersExceptCustomDecimalChar',\n value: function _stripAllNonNumberCharactersExceptCustomDecimalChar(s, settings, stripZeros, isFocused) {\n //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n //TODO This function is called 10 times (sic!) on each key input, couldn't we lower that number? cf. issue #325\n s = this._normalizeCurrencySuffixAndNegativeSignCharacters(s, settings);\n\n // Then remove all the characters that are not numbers, the normal negative sign '-', or the custom decimal character (note: this also remove any custom positive sign)\n s = s.replace(settings.allowedAutoStrip, '');\n\n // Get only number string\n var m = s.match(settings.numRegAutoStrip);\n s = m ? [m[1], m[2], m[3]].join('') : '';\n\n if (settings.leadingZero === AutoNumeric.options.leadingZero.allow || settings.leadingZero === AutoNumeric.options.leadingZero.keep) {\n var negativeSign = '';\n\n var _s$split = s.split(settings.decimalCharacter),\n _s$split2 = _slicedToArray(_s$split, 2),\n integerPart = _s$split2[0],\n decimalPart = _s$split2[1];\n\n var modifiedIntegerPart = integerPart;\n if (_AutoNumericHelper2.default.contains(modifiedIntegerPart, settings.negativeSignCharacter)) {\n negativeSign = settings.negativeSignCharacter;\n modifiedIntegerPart = modifiedIntegerPart.replace(settings.negativeSignCharacter, '');\n }\n\n // Strip leading zero on positive value if needed\n if (negativeSign === '' && modifiedIntegerPart.length > settings.mIntPos && modifiedIntegerPart.charAt(0) === '0') {\n modifiedIntegerPart = modifiedIntegerPart.slice(1);\n }\n\n // Strip leading zero on negative value if needed\n if (negativeSign !== '' && modifiedIntegerPart.length > settings.mIntNeg && modifiedIntegerPart.charAt(0) === '0') {\n modifiedIntegerPart = modifiedIntegerPart.slice(1);\n }\n\n s = '' + negativeSign + modifiedIntegerPart + (_AutoNumericHelper2.default.isUndefined(decimalPart) ? '' : settings.decimalCharacter + decimalPart);\n }\n\n if (stripZeros && settings.leadingZero === AutoNumeric.options.leadingZero.deny || !isFocused && settings.leadingZero === AutoNumeric.options.leadingZero.allow) {\n s = s.replace(settings.stripReg, '$1$2');\n }\n\n return s;\n }\n\n /**\n * Sets or removes brackets on negative values, depending on the focus state, which is passed as `isFocused`.\n * The focus state is 'stored' in that object property.\n *\n * @param {string} value\n * @param {object} settings\n * @param {boolean} isFocused\n * @returns {*}\n */\n\n }, {\n key: '_toggleNegativeBracket',\n value: function _toggleNegativeBracket(value, settings, isFocused) {\n //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n var result = void 0;\n if (isFocused) {\n result = this._removeBrackets(value, settings);\n } else {\n result = this._addBrackets(value, settings);\n }\n\n return result;\n }\n\n /**\n * Add the bracket types specified in the `settings` object, to the given string `value`.\n *\n * @param {string} value\n * @param {object} settings\n * @returns {string}\n * @private\n */\n\n }, {\n key: '_addBrackets',\n value: function _addBrackets(value, settings) {\n if (_AutoNumericHelper2.default.isNull(settings.negativeBracketsTypeOnBlur)) {\n return value;\n }\n\n return '' + settings.firstBracket + value.replace(settings.negativeSignCharacter, '') + settings.lastBracket;\n }\n\n /**\n * Remove the bracket types specified in the `settings` object, from the given string `value`.\n *\n * @param {string} value\n * @param {object} settings\n * @param {boolean} rearrangeSignsAndValueOrder If set to `true`, then only the brackets are remove and a negative sign is added, without reordering the negative sign, currency symbol and value according to the settings.\n * @returns {string}\n * @private\n */\n\n }, {\n key: '_removeBrackets',\n value: function _removeBrackets(value, settings) {\n var rearrangeSignsAndValueOrder = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n\n var result = void 0;\n if (!_AutoNumericHelper2.default.isNull(settings.negativeBracketsTypeOnBlur) && value.charAt(0) === settings.firstBracket) {\n // Remove the brackets if they are present\n result = value.replace(settings.firstBracket, '');\n result = result.replace(settings.lastBracket, '');\n\n // Add back the negative sign at the right place\n if (rearrangeSignsAndValueOrder) {\n // First we need to remove the currency symbol from the value, since we want to be able to add back the negative sign at the right place (including between the value and the currency sign)\n result = result.replace(settings.currencySymbol, '');\n result = this._mergeCurrencySignNegativePositiveSignAndValue(result, settings, true, false); //TODO This assume the value is negative and non-empty. Is this always the case?\n } else {\n // Here we only want to add the negative sign since we removed the brackets, without reordering\n result = '' + settings.negativeSignCharacter + result;\n }\n } else {\n result = value;\n }\n\n return result;\n }\n\n /**\n * Analyze the `negativeBracketsTypeOnBlur` options and keep track of the first and last bracket characters to use.\n *\n * @param {object} settings\n * @private\n */\n\n }, {\n key: '_setBrackets',\n value: function _setBrackets(settings) {\n if (_AutoNumericHelper2.default.isNull(settings.negativeBracketsTypeOnBlur)) {\n settings.firstBracket = '';\n settings.lastBracket = '';\n } else {\n // Use temporary variables to fix the MS Edge destructuring issue (see pull request #564)\n var _settings$negativeBra3 = settings.negativeBracketsTypeOnBlur.split(','),\n _settings$negativeBra4 = _slicedToArray(_settings$negativeBra3, 2),\n firstBracket = _settings$negativeBra4[0],\n lastBracket = _settings$negativeBra4[1];\n\n settings.firstBracket = firstBracket;\n settings.lastBracket = lastBracket;\n }\n }\n\n /**\n * Return a number as a numeric string that can be typecast to a Number that Javascript will understand.\n *\n * This function returns the given string by stripping:\n * - the currency sign (currencySymbol),\n * - the grouping separators (digitalGroupSpacing),\n * - the suffix text (suffixText),\n * - the positive sign (positiveSignCharacter),\n * - the brackets if any,\n * - by replacing the negative sign character with an hyphen,\n * - and by replacing the decimal character (decimalCharacter) by a dot.\n *\n * Lastly, it also put the negative sign back to its normal position if needed.\n * Bonus; it converts any arabic numbers found to the latin ones.\n *\n * @param {string} s\n * @param {object} settings\n * @returns {string|void|*}\n */\n\n }, {\n key: '_convertToNumericString',\n value: function _convertToNumericString(s, settings) {\n // Remove the custom brackets\n s = this._removeBrackets(s, settings, false);\n s = this._normalizeCurrencySuffixAndNegativeSignCharacters(s, settings);\n\n // Remove the grouping separators (thousands separators usually)\n s = s.replace(new RegExp('[' + settings.digitGroupSeparator + ']', 'g'), '');\n\n // Replace the decimal character by a dot\n if (settings.decimalCharacter !== '.') {\n s = s.replace(settings.decimalCharacter, '.');\n }\n\n // Move the trailing negative sign, if any, to the usual leftmost position\n if (_AutoNumericHelper2.default.isNegative(s) && s.lastIndexOf('-') === s.length - 1) {\n s = s.replace('-', '');\n s = '-' + s;\n }\n\n // Replace the custom positive sign\n if (settings.showPositiveSign) {\n s = s.replace(settings.positiveSignCharacter, '');\n }\n\n // Convert arabic numbers to latin ones, if any\n var convertToNumber = settings.leadingZero !== AutoNumeric.options.leadingZero.keep;\n var temp = _AutoNumericHelper2.default.arabicToLatinNumbers(s, convertToNumber, false, false);\n if (!isNaN(temp)) {\n s = temp.toString();\n }\n\n return s;\n }\n\n /**\n * Removes the currency symbol and the suffix text from the given string, and replace the custom negative sign with an hyphen.\n *\n * @param {string} s\n * @param {object} settings\n * @returns {string | *}\n * @private\n */\n\n }, {\n key: '_normalizeCurrencySuffixAndNegativeSignCharacters',\n value: function _normalizeCurrencySuffixAndNegativeSignCharacters(s, settings) {\n s = String(s); // Typecast to to a string, in case that the given value is a number\n\n // Remove the currency symbol\n if (settings.currencySymbol !== AutoNumeric.options.currencySymbol.none) {\n s = s.replace(settings.currencySymbol, '');\n }\n\n // Remove the suffixText\n if (settings.suffixText !== AutoNumeric.options.suffixText.none) {\n s = s.replace(settings.suffixText, '');\n }\n\n // Replace the custom negative sign with an hyphen\n if (settings.negativeSignCharacter !== AutoNumeric.options.negativeSignCharacter.hyphen) {\n s = s.replace(settings.negativeSignCharacter, '-');\n }\n\n return s;\n }\n\n /**\n * Converts the ISO numeric string to the locale decimal and minus sign placement.\n * See the \"outputFormat\" option definition for more details.\n * Note: If the `outputFormat` is set to a number, the custom `negativeSignCharacter` is ignored.\n *\n * @param {string|null} value The unformatted value\n * @param {string|null} locale\n * @param {object} settings\n * @returns {*}\n */\n\n }, {\n key: '_toLocale',\n value: function _toLocale(value, locale, settings) {\n if (_AutoNumericHelper2.default.isNull(locale) || locale === AutoNumeric.options.outputFormat.string) {\n return value;\n }\n\n var result = void 0;\n switch (locale) {\n case AutoNumeric.options.outputFormat.number:\n result = Number(value);\n break;\n case AutoNumeric.options.outputFormat.dotNegative:\n result = _AutoNumericHelper2.default.isNegative(value) ? value.replace('-', '') + '-' : value;\n break;\n case AutoNumeric.options.outputFormat.comma:\n case AutoNumeric.options.outputFormat.negativeComma:\n result = value.replace('.', ',');\n break;\n case AutoNumeric.options.outputFormat.commaNegative:\n result = value.replace('.', ',');\n result = _AutoNumericHelper2.default.isNegative(result) ? result.replace('-', '') + '-' : result;\n break;\n // The default case\n case AutoNumeric.options.outputFormat.dot:\n case AutoNumeric.options.outputFormat.negativeDot:\n result = value;\n break;\n default:\n _AutoNumericHelper2.default.throwError('The given outputFormat [' + locale + '] option is not recognized.');\n }\n\n if (locale !== AutoNumeric.options.outputFormat.number && settings.negativeSignCharacter !== '-') {\n // Modify the default minus sign with the custom one, if any\n result = result.replace('-', settings.negativeSignCharacter);\n }\n\n return result;\n }\n }, {\n key: '_modifyNegativeSignAndDecimalCharacterForFormattedValue',\n value: function _modifyNegativeSignAndDecimalCharacterForFormattedValue(s, settings) {\n //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n if (settings.negativeSignCharacter !== '-') {\n s = s.replace('-', settings.negativeSignCharacter);\n }\n\n if (settings.decimalCharacter !== '.') {\n s = s.replace('.', settings.decimalCharacter);\n }\n\n return s;\n }\n\n /**\n * Return `true` if the given value is empty or is equal to the negative sign character defined in the given settings.\n *\n * @param {string} value\n * @param {object} settings\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_isElementValueEmptyOrOnlyTheNegativeSign',\n value: function _isElementValueEmptyOrOnlyTheNegativeSign(value, settings) {\n return value === '' || value === settings.negativeSignCharacter;\n }\n\n /**\n * Return the value with the currency symbol and the suffix text ordered according to the given settings.\n *\n * @param {string} value\n * @param {object} settings\n * @param {boolean} signOnEmpty\n * @returns {*}\n * @private\n */\n\n }, {\n key: '_orderValueCurrencySymbolAndSuffixText',\n value: function _orderValueCurrencySymbolAndSuffixText(value, settings, signOnEmpty) {\n var result = void 0;\n if (settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.always || signOnEmpty) {\n if (settings.negativePositiveSignPlacement === AutoNumeric.options.negativePositiveSignPlacement.left) {\n result = value + settings.currencySymbol + settings.suffixText;\n } else {\n result = settings.currencySymbol + value + settings.suffixText;\n }\n } else {\n result = value;\n }\n\n return result;\n }\n\n /**\n * Modify the input value by adding the group separators, as defined in the settings, and the negative brackets if needed.\n *\n * @param {string} inputValue The formatted value (ie. with the `decimalCharacter` defined in the settings, not the raw value)\n * @param {object} settings\n * @param {boolean} isFocused\n * @param {number|string|null} currentRawValue The object current raw value (`this.rawValue`)\n * @param {number|string|null} forcedRawValue If this is set, then this rawValue is used instead of the one passed through the `settings` object. This is useful is some very specific cases where we need to set the raw value *after* settings the formatted value, using the `_addGroupSeparators()` method.\n * @returns {*}\n */\n\n }, {\n key: '_addGroupSeparators',\n value: function _addGroupSeparators(inputValue, settings, isFocused, currentRawValue) {\n var forcedRawValue = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;\n\n //TODO Test if `inputValue` === '', and return '' directly if that's the case,\n //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n var isValueNegative = void 0;\n if (!_AutoNumericHelper2.default.isNull(forcedRawValue)) {\n // Prefer directly testing if the raw value is negative in order for the test to be more performant than manipulating the formatted value\n isValueNegative = forcedRawValue < 0;\n } else {\n isValueNegative = _AutoNumericHelper2.default.isNegative(inputValue, settings.negativeSignCharacter) || _AutoNumericHelper2.default.isNegativeWithBrackets(inputValue, settings.firstBracket, settings.lastBracket); // Test if the value is negative before removing the negative sign\n }\n\n inputValue = this._stripAllNonNumberCharactersExceptCustomDecimalChar(inputValue, settings, false, isFocused);\n\n if (this._isElementValueEmptyOrOnlyTheNegativeSign(inputValue, settings)) {\n return this._orderValueCurrencySymbolAndSuffixText(inputValue, settings, true);\n }\n\n var isZeroOrHasNoValue = _AutoNumericHelper2.default.isZeroOrHasNoValue(inputValue);\n\n // Temporarily remove the negative sign if present\n if (isValueNegative) {\n inputValue = inputValue.replace('-', ''); // At this point the `inputValue` has been normalized with a 'normal' negative sign `'-'` //TODO Check that comment validity, since `_stripAllNonNumberCharactersExceptCustomDecimalChar` *does not* convert the negative sign\n }\n\n settings.digitalGroupSpacing = settings.digitalGroupSpacing.toString();\n var digitalGroup = void 0;\n switch (settings.digitalGroupSpacing) {\n case AutoNumeric.options.digitalGroupSpacing.two:\n digitalGroup = /(\\d)((\\d)(\\d{2}?)+)$/;\n break;\n case AutoNumeric.options.digitalGroupSpacing.twoScaled:\n digitalGroup = /(\\d)((?:\\d{2}){0,2}\\d{3}(?:(?:\\d{2}){2}\\d{3})*?)$/;\n break;\n case AutoNumeric.options.digitalGroupSpacing.four:\n digitalGroup = /(\\d)((\\d{4}?)+)$/;\n break;\n case AutoNumeric.options.digitalGroupSpacing.three:\n default:\n digitalGroup = /(\\d)((\\d{3}?)+)$/;\n }\n\n // Splits the string at the decimal string\n\n var _inputValue$split = inputValue.split(settings.decimalCharacter),\n _inputValue$split2 = _slicedToArray(_inputValue$split, 2),\n integerPart = _inputValue$split2[0],\n decimalPart = _inputValue$split2[1];\n\n if (settings.decimalCharacterAlternative && _AutoNumericHelper2.default.isUndefined(decimalPart)) {\n var _inputValue$split3 = inputValue.split(settings.decimalCharacterAlternative);\n\n var _inputValue$split4 = _slicedToArray(_inputValue$split3, 2);\n\n integerPart = _inputValue$split4[0];\n decimalPart = _inputValue$split4[1];\n }\n\n if (settings.digitGroupSeparator !== '') {\n // Re-inserts the thousand separator via a regular expression\n while (digitalGroup.test(integerPart)) {\n integerPart = integerPart.replace(digitalGroup, '$1' + settings.digitGroupSeparator + '$2');\n }\n }\n\n // Find out how many decimal places should be kept, depending on the object state (isFocused)\n var decimalPlacesToRoundTo = void 0;\n if (isFocused) {\n decimalPlacesToRoundTo = settings.decimalPlacesShownOnFocus;\n } else {\n decimalPlacesToRoundTo = settings.decimalPlacesShownOnBlur;\n }\n\n if (decimalPlacesToRoundTo !== 0 && !_AutoNumericHelper2.default.isUndefined(decimalPart)) {\n if (decimalPart.length > decimalPlacesToRoundTo) {\n // Trim the excessive number of decimal places\n decimalPart = decimalPart.substring(0, decimalPlacesToRoundTo);\n }\n\n // Joins the whole number with the decimal value\n inputValue = '' + integerPart + settings.decimalCharacter + decimalPart;\n } else {\n // Otherwise if it's an integer\n inputValue = integerPart;\n }\n\n // Add back the negative/positive sign and the currency symbol, at the right positions\n inputValue = AutoNumeric._mergeCurrencySignNegativePositiveSignAndValue(inputValue, settings, isValueNegative, isZeroOrHasNoValue); //TODO this function is called again in `_toggleNegativeBracket` if the brackets are removed; let's DRY this\n\n if (_AutoNumericHelper2.default.isNull(forcedRawValue)) {\n // If the raw value is not forced, use the default one from the settings object\n forcedRawValue = currentRawValue;\n }\n\n // Toggle the negative sign and brackets\n if (settings.negativeBracketsTypeOnBlur !== null && (forcedRawValue < 0 || _AutoNumericHelper2.default.isNegativeStrict(inputValue, settings.negativeSignCharacter))) {\n inputValue = this._toggleNegativeBracket(inputValue, settings, isFocused);\n }\n\n var result = void 0;\n if (settings.suffixText) {\n result = '' + inputValue + settings.suffixText;\n } else {\n result = inputValue;\n }\n\n return result;\n }\n\n /**\n * Return a semi-formatted string where the input value, the negative or positive sign, and the currency symbol are stitched together at the right positions, using the options set in the `settings` object.\n * Note : the `inputValue` is usually not a numeric string since the grouping symbols are already added to it at this point.\n *\n * @param {string} inputValue\n * @param {object} settings\n * @param {boolean} isValueNegative\n * @param {boolean} isZeroOrHasNoValue\n * @returns {*}\n * @throws\n * @private\n */\n\n }, {\n key: '_mergeCurrencySignNegativePositiveSignAndValue',\n value: function _mergeCurrencySignNegativePositiveSignAndValue(inputValue, settings, isValueNegative, isZeroOrHasNoValue) {\n var signToUse = '';\n if (isValueNegative) {\n signToUse = settings.negativeSignCharacter;\n } else if (settings.showPositiveSign && !isZeroOrHasNoValue) {\n signToUse = settings.positiveSignCharacter;\n }\n\n var result = void 0;\n if (settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix) {\n if (settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && settings.showPositiveSign && !isZeroOrHasNoValue)) {\n switch (settings.negativePositiveSignPlacement) {\n case AutoNumeric.options.negativePositiveSignPlacement.prefix:\n case AutoNumeric.options.negativePositiveSignPlacement.left:\n result = '' + signToUse + settings.currencySymbol + inputValue;\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.right:\n result = '' + settings.currencySymbol + signToUse + inputValue;\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.suffix:\n result = '' + settings.currencySymbol + inputValue + signToUse;\n break;\n }\n } else {\n result = settings.currencySymbol + inputValue;\n }\n } else if (settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n if (settings.negativePositiveSignPlacement !== AutoNumeric.options.negativePositiveSignPlacement.none && (isValueNegative || !isValueNegative && settings.showPositiveSign && !isZeroOrHasNoValue)) {\n switch (settings.negativePositiveSignPlacement) {\n case AutoNumeric.options.negativePositiveSignPlacement.suffix:\n case AutoNumeric.options.negativePositiveSignPlacement.right:\n result = '' + inputValue + settings.currencySymbol + signToUse;\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.left:\n result = '' + inputValue + signToUse + settings.currencySymbol;\n break;\n case AutoNumeric.options.negativePositiveSignPlacement.prefix:\n result = '' + signToUse + inputValue + settings.currencySymbol;\n break;\n }\n } else {\n result = inputValue + settings.currencySymbol;\n }\n }\n\n return result;\n }\n }, {\n key: '_truncateZeros',\n value: function _truncateZeros(roundedInputValue, decimalPlacesNeeded) {\n var regex = void 0;\n switch (decimalPlacesNeeded) {\n case 0:\n // Prevents padding - removes trailing zeros until the first significant digit is encountered\n regex = /(\\.(?:\\d*[1-9])?)0*$/;\n break;\n case 1:\n // Allows padding when decimalPlacesNeeded equals one - leaves one zero trailing the decimal character\n regex = /(\\.\\d(?:\\d*[1-9])?)0*$/;\n break;\n default:\n // Removes superfluous zeros after the decimalPlacesNeeded length\n regex = new RegExp('(\\\\.\\\\d{' + decimalPlacesNeeded + '}(?:\\\\d*[1-9])?)0*');\n }\n\n // If there are no decimal places, we don't need a decimal point at the end\n roundedInputValue = roundedInputValue.replace(regex, '$1');\n if (decimalPlacesNeeded === 0) {\n roundedInputValue = roundedInputValue.replace(/\\.$/, '');\n }\n\n return roundedInputValue;\n }\n\n /**\n * Round the given `value` with the number of decimal places to keep for the raw value.\n *\n * @param {string|null} value An unformatted numeric value\n * @param {object} settings\n * @returns {*}\n * @private\n */\n\n }, {\n key: '_roundRawValue',\n value: function _roundRawValue(value, settings) {\n return this._roundValue(value, settings, settings.decimalPlacesRawValue);\n }\n\n /**\n * Round the given `value` with the number of decimal places to show for the element is focused.\n *\n * @param {string|null} value An unformatted numeric value\n * @param {object} settings\n * @returns {*}\n * @private\n */\n\n }, {\n key: '_roundFormattedValueShownOnFocus',\n value: function _roundFormattedValueShownOnFocus(value, settings) {\n return this._roundValue(value, settings, Number(settings.decimalPlacesShownOnFocus));\n }\n\n /**\n * Round the given `value` with the number of decimal places to show for the element is unfocused.\n *\n * @param {string|null} value An unformatted numeric value\n * @param {object} settings\n * @returns {*}\n * @private\n */\n\n }, {\n key: '_roundFormattedValueShownOnBlur',\n value: function _roundFormattedValueShownOnBlur(value, settings) {\n return this._roundValue(value, settings, Number(settings.decimalPlacesShownOnBlur));\n }\n\n /**\n * Round the input value using the rounding method defined in the settings.\n * This function accepts multiple rounding methods. See the documentation for more details about those.\n *\n * Note : This is handled as text since JavaScript math functions can return inaccurate values.\n *\n * @param {string|null} inputValue An unformatted numeric value\n * @param {object} settings\n * @param {int} decimalPlacesToRoundTo\n * @returns {*}\n */\n\n }, {\n key: '_roundValue',\n value: function _roundValue(inputValue, settings, decimalPlacesToRoundTo) {\n //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n if (_AutoNumericHelper2.default.isNull(inputValue)) {\n // Prevent rounding a `null` value\n return inputValue;\n }\n\n //TODO Divide this function to make it easier to understand\n inputValue = inputValue === '' ? '0' : inputValue.toString();\n if (settings.roundingMethod === AutoNumeric.options.roundingMethod.toNearest05 || settings.roundingMethod === AutoNumeric.options.roundingMethod.toNearest05Alt || settings.roundingMethod === AutoNumeric.options.roundingMethod.upToNext05 || settings.roundingMethod === AutoNumeric.options.roundingMethod.downToNext05) {\n return this._roundCloseTo05(inputValue, settings);\n }\n\n var _AutoNumeric$_prepare = AutoNumeric._prepareValueForRounding(inputValue, settings),\n _AutoNumeric$_prepare2 = _slicedToArray(_AutoNumeric$_prepare, 2),\n negativeSign = _AutoNumeric$_prepare2[0],\n preparedValue = _AutoNumeric$_prepare2[1];\n\n inputValue = preparedValue;\n\n var decimalCharacterPosition = inputValue.lastIndexOf('.');\n var inputValueHasNoDot = decimalCharacterPosition === -1; // No dot character is found in the `inputValue`\n\n var _inputValue$split5 = inputValue.split('.'),\n _inputValue$split6 = _slicedToArray(_inputValue$split5, 2),\n decimalPart = _inputValue$split6[1]; // Here the decimal character is always a period '.'\n\n\n var hasDecimals = decimalPart > 0;\n\n // If no decimals are detected\n if (!hasDecimals && (settings.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.never || settings.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.floats)) {\n return Number(inputValue) === 0 ? inputValue : '' + negativeSign + inputValue;\n }\n\n // Else there are some decimal places that may need to be rounded\n // Sets the truncate zero method\n var temporaryDecimalPlacesOverride = void 0;\n if (settings.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.always || settings.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.floats) {\n temporaryDecimalPlacesOverride = decimalPlacesToRoundTo;\n } else {\n temporaryDecimalPlacesOverride = 0;\n }\n\n // Define the decimal position to use (use the very last position if there are no dot in the initial inputValue)\n var decimalPositionToUse = inputValueHasNoDot ? inputValue.length - 1 : decimalCharacterPosition;\n // Checks decimal places to determine if rounding is required\n var checkDecimalPlaces = inputValue.length - 1 - decimalPositionToUse;\n var inputValueRounded = '';\n\n // Check if no rounding is required\n if (checkDecimalPlaces <= decimalPlacesToRoundTo) {\n // Check if we need to pad with zeros\n inputValueRounded = inputValue;\n if (checkDecimalPlaces < temporaryDecimalPlacesOverride) {\n if (inputValueHasNoDot) {\n inputValueRounded = '' + inputValueRounded + settings.decimalCharacter;\n }\n\n var zeros = '000000'; //TODO Change that string with a longer one to prevent having to loop numerous times in the next `while` statement?\n while (checkDecimalPlaces < temporaryDecimalPlacesOverride) {\n zeros = zeros.substring(0, temporaryDecimalPlacesOverride - checkDecimalPlaces);\n inputValueRounded += zeros;\n checkDecimalPlaces += zeros.length;\n }\n } else if (checkDecimalPlaces > temporaryDecimalPlacesOverride) {\n inputValueRounded = this._truncateZeros(inputValueRounded, temporaryDecimalPlacesOverride);\n } else if (checkDecimalPlaces === 0 && temporaryDecimalPlacesOverride === 0) {\n // Remove any trailing dot, if any\n inputValueRounded = inputValueRounded.replace(/\\.$/, '');\n }\n\n return Number(inputValueRounded) === 0 ? inputValueRounded : '' + negativeSign + inputValueRounded;\n }\n\n // Rounded length of the string after rounding\n var roundedStrLength = void 0;\n if (inputValueHasNoDot) {\n roundedStrLength = decimalPlacesToRoundTo - 1;\n } else {\n roundedStrLength = Number(decimalPlacesToRoundTo) + Number(decimalCharacterPosition);\n }\n\n var lastDigit = Number(inputValue.charAt(roundedStrLength + 1));\n var inputValueArray = inputValue.substring(0, roundedStrLength + 1).split('');\n var odd = void 0;\n if (inputValue.charAt(roundedStrLength) === '.') {\n odd = inputValue.charAt(roundedStrLength - 1) % 2;\n } else {\n odd = inputValue.charAt(roundedStrLength) % 2;\n }\n\n if (this._shouldRoundUp(lastDigit, settings, negativeSign, odd)) {\n // Round up the last digit if required, and continue until no more 9's are found\n for (var i = inputValueArray.length - 1; i >= 0; i -= 1) {\n if (inputValueArray[i] !== '.') {\n inputValueArray[i] = +inputValueArray[i] + 1;\n if (inputValueArray[i] < 10) {\n break;\n }\n\n if (i > 0) {\n inputValueArray[i] = '0';\n }\n }\n }\n }\n\n // Reconstruct the string, converting any 10's to 0's\n inputValueArray = inputValueArray.slice(0, roundedStrLength + 1);\n\n // Return the rounded value\n inputValueRounded = this._truncateZeros(inputValueArray.join(''), temporaryDecimalPlacesOverride);\n\n return Number(inputValueRounded) === 0 ? inputValueRounded : '' + negativeSign + inputValueRounded;\n }\n\n /**\n * Round the `value` when the rounding method deals with '.05'\n *\n * @param {string} value\n * @param {object} settings\n * @returns {string}\n * @private\n */\n\n }, {\n key: '_roundCloseTo05',\n value: function _roundCloseTo05(value, settings) {\n switch (settings.roundingMethod) {\n case AutoNumeric.options.roundingMethod.toNearest05:\n case AutoNumeric.options.roundingMethod.toNearest05Alt:\n value = (Math.round(value * 20) / 20).toString();\n break;\n case AutoNumeric.options.roundingMethod.upToNext05:\n value = (Math.ceil(value * 20) / 20).toString();\n break;\n default:\n value = (Math.floor(value * 20) / 20).toString();\n }\n\n var result = void 0;\n if (!_AutoNumericHelper2.default.contains(value, '.')) {\n result = value + '.00';\n } else if (value.length - value.indexOf('.') < 3) {\n result = value + '0';\n } else {\n result = value;\n }\n\n return result;\n }\n\n /**\n * Modify the given `value` in order to make it usable for the rest of the rounding function.\n * This convert the `value` to a positive one, trim any leading zeros and make sure it does not starts with a leading dot.\n *\n * @param {string} value The unformatted value\n * @param {object} settings\n * @returns {[string, string]}\n * @private\n */\n\n }, {\n key: '_prepareValueForRounding',\n value: function _prepareValueForRounding(value, settings) {\n // Checks if `inputValue` is a negative value\n var negativeSign = '';\n if (_AutoNumericHelper2.default.isNegativeStrict(value, '-')) {\n // The value being unformatted, we check for the minus sign\n negativeSign = '-';\n\n // Removes the negative sign that will be added back later if required\n value = value.replace('-', '');\n }\n\n // Append a zero if the first character is not a digit (then it is likely a dot)\n if (!value.match(/^\\d/)) {\n value = '0' + value;\n }\n\n // Determines if the value is equal to zero. If it is, remove the negative sign\n if (Number(value) === 0) {\n negativeSign = '';\n }\n\n // Trims leading zero's as needed\n if (Number(value) > 0 && settings.leadingZero !== AutoNumeric.options.leadingZero.keep || value.length > 0 && settings.leadingZero === AutoNumeric.options.leadingZero.allow) {\n value = value.replace(/^0*(\\d)/, '$1');\n }\n\n return [negativeSign, value];\n }\n\n /**\n * Return `true` if a round up should be done given the last digit, the settings and other information about the value.\n *\n * @param {number} lastDigit\n * @param {object} settings\n * @param {string} negativeSign This variable comes from `_prepareValueForRounding()`, which return `'-'` if the initial value was negative\n * @param {number} odd\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: '_shouldRoundUp',\n value: function _shouldRoundUp(lastDigit, settings, negativeSign, odd) {\n return lastDigit > 4 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfUpSymmetric || // Round half up symmetric\n lastDigit > 4 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfUpAsymmetric && negativeSign === '' || // Round half up asymmetric positive values\n lastDigit > 5 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfUpAsymmetric && negativeSign === '-' || // Round half up asymmetric negative values\n lastDigit > 5 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfDownSymmetric || // Round half down symmetric\n lastDigit > 5 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfDownAsymmetric && negativeSign === '' || // Round half down asymmetric positive values\n lastDigit > 4 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfDownAsymmetric && negativeSign === '-' || // Round half down asymmetric negative values\n lastDigit > 5 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfEvenBankersRounding || lastDigit === 5 && settings.roundingMethod === AutoNumeric.options.roundingMethod.halfEvenBankersRounding && odd === 1 || lastDigit > 0 && settings.roundingMethod === AutoNumeric.options.roundingMethod.toCeilingTowardPositiveInfinity && negativeSign === '' || lastDigit > 0 && settings.roundingMethod === AutoNumeric.options.roundingMethod.toFloorTowardNegativeInfinity && negativeSign === '-' || lastDigit > 0 && settings.roundingMethod === AutoNumeric.options.roundingMethod.upRoundAwayFromZero; // Round up away from zero\n }\n\n /**\n * Truncates the decimal part of a number to the given number of decimal places `decimalPlacesToRoundTo`.\n *\n * @param {string} value\n * @param {object} settings\n * @param {boolean} isPaste\n * @param {int} decimalPlacesToRoundTo\n * @returns {*}\n */\n\n }, {\n key: '_truncateDecimalPlaces',\n value: function _truncateDecimalPlaces(value, settings, isPaste, decimalPlacesToRoundTo) {\n if (isPaste) {\n value = this._roundFormattedValueShownOnFocus(value, settings);\n }\n\n var _value$split = value.split(settings.decimalCharacter),\n _value$split2 = _slicedToArray(_value$split, 2),\n integerPart = _value$split2[0],\n decimalPart = _value$split2[1];\n\n // Truncate the decimal part to the satisfying length since we would round it anyway\n\n\n if (decimalPart && decimalPart.length > decimalPlacesToRoundTo) {\n if (decimalPlacesToRoundTo > 0) {\n var modifiedDecimalPart = decimalPart.substring(0, decimalPlacesToRoundTo);\n value = '' + integerPart + settings.decimalCharacter + modifiedDecimalPart;\n } else {\n value = integerPart;\n }\n }\n\n return value;\n }\n\n /**\n * Check that the number satisfy the format conditions\n * and lays between settings.minimumValue and settings.maximumValue\n * and the string length does not exceed the digits in settings.minimumValue and settings.maximumValue\n *\n * @param {string} value\n * @param {object} settings\n * @returns {*}\n */\n\n }, {\n key: '_checkIfInRangeWithOverrideOption',\n value: function _checkIfInRangeWithOverrideOption(value, settings) {\n if (_AutoNumericHelper2.default.isNull(value) && settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.null) {\n // When the `null` value is accepted as the `rawValue`, the limits are ignored\n return [true, true];\n }\n\n value = value.toString();\n value = value.replace(',', '.');\n var minParse = _AutoNumericHelper2.default.parseStr(settings.minimumValue);\n var maxParse = _AutoNumericHelper2.default.parseStr(settings.maximumValue);\n var valParse = _AutoNumericHelper2.default.parseStr(value);\n\n var result = void 0;\n switch (settings.overrideMinMaxLimits) {\n case AutoNumeric.options.overrideMinMaxLimits.floor:\n result = [_AutoNumericHelper2.default.testMinMax(minParse, valParse) > -1, true];\n break;\n case AutoNumeric.options.overrideMinMaxLimits.ceiling:\n result = [true, _AutoNumericHelper2.default.testMinMax(maxParse, valParse) < 1];\n break;\n case AutoNumeric.options.overrideMinMaxLimits.ignore:\n result = [true, true];\n break;\n default:\n result = [_AutoNumericHelper2.default.testMinMax(minParse, valParse) > -1, _AutoNumericHelper2.default.testMinMax(maxParse, valParse) < 1];\n }\n\n return result;\n }\n }, {\n key: '_readCookie',\n value: function _readCookie(name) {\n var nameEQ = name + '=';\n var ca = document.cookie.split(';');\n var c = '';\n for (var i = 0; i < ca.length; i += 1) {\n c = ca[i];\n while (c.charAt(0) === ' ') {\n c = c.substring(1, c.length);\n }\n if (c.indexOf(nameEQ) === 0) {\n return c.substring(nameEQ.length, c.length);\n }\n }\n\n return null;\n }\n\n /**\n * Test if sessionStorage is supported.\n * This is taken from Modernizr.\n *\n * @returns {boolean}\n */\n\n }, {\n key: '_storageTest',\n value: function _storageTest() {\n var mod = 'modernizr';\n try {\n sessionStorage.setItem(mod, mod);\n sessionStorage.removeItem(mod);\n return true;\n } catch (e) {\n return false;\n }\n }\n }, {\n key: '_correctNegativePositiveSignPlacementOption',\n value: function _correctNegativePositiveSignPlacementOption(settings) {\n //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n // If negativePositiveSignPlacement is already set, we do not overwrite it\n if (!_AutoNumericHelper2.default.isNull(settings.negativePositiveSignPlacement)) {\n return;\n }\n\n if (!_AutoNumericHelper2.default.isUndefined(settings) && _AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(settings.negativePositiveSignPlacement) && !_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(settings.currencySymbol)) {\n switch (settings.currencySymbolPlacement) {\n case AutoNumeric.options.currencySymbolPlacement.suffix:\n settings.negativePositiveSignPlacement = AutoNumeric.options.negativePositiveSignPlacement.prefix; // Default -1,234.56 €\n break;\n case AutoNumeric.options.currencySymbolPlacement.prefix:\n settings.negativePositiveSignPlacement = AutoNumeric.options.negativePositiveSignPlacement.left; // Default -$1,234.56\n break;\n default:\n //\n }\n } else {\n // Sets the default value if `negativePositiveSignPlacement` is `null`\n settings.negativePositiveSignPlacement = AutoNumeric.options.negativePositiveSignPlacement.left;\n }\n }\n\n /**\n * Correct the `caretPositionOnFocus` and `selectOnFocus` options, since setting both leads to a conflict.\n * This method directly modifies the `options` object passed as a parameter, then returns it.\n * It returns `null` if the given option is `null`.\n *\n * @param {object} options The options passed as an argument by the user\n * @returns {object|null}\n * @private\n */\n\n }, {\n key: '_correctCaretPositionOnFocusAndSelectOnFocusOptions',\n value: function _correctCaretPositionOnFocusAndSelectOnFocusOptions(options) {\n if (_AutoNumericHelper2.default.isNull(options)) {\n return null;\n }\n\n // If the user has set the `caretPositionOnFocus` option, do not set `selectOnFocus` to `true` by default\n if (!_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options.caretPositionOnFocus) && _AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options.selectOnFocus)) {\n options.selectOnFocus = AutoNumeric.options.selectOnFocus.doNotSelect;\n }\n\n // If the user has set the `selectOnFocus` option to `true`, set `caretPositionOnFocus` to `doNoForceCaretPosition`\n if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options.caretPositionOnFocus) && !_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(options.selectOnFocus) && options.selectOnFocus === AutoNumeric.options.selectOnFocus.select) {\n options.caretPositionOnFocus = AutoNumeric.options.caretPositionOnFocus.doNoForceCaretPosition;\n }\n\n return options;\n }\n\n /**\n * Calculate the number de decimal places to be used by the AutoNumeric object, for each of its state, and for its formatted and raw value.\n * By default, the `rawValue` precision is the same as the formatted value one.\n *\n * This method is called during the AutoNumeric object initialization. This assumes some internal variable state.\n *\n * This methods set the following options accordingly to their own value and the mandatory `decimalPlaces` option:\n * - decimalPlacesRawValue (nullable)\n * - decimalPlacesShownOnBlur (nullable)\n * - decimalPlacesShownOnFocus (nullable)\n *\n * Note: the `decimalPlaces` option is only used here and only serve to define those three previous options value.\n * AutoNumeric will then *only* use `decimalPlacesRawValue`, `decimalPlacesShownOnBlur` and `decimalPlacesShownOnFocus` from there.\n *\n * This methods directly modifies the `settings` object passed as a parameter.\n *\n * @param {object} settings This is an object with the new settings to use.\n * @private\n */\n\n }, {\n key: '_calculateDecimalPlacesOnInit',\n value: function _calculateDecimalPlacesOnInit(settings) {\n // Check the `decimalPlaces*` options and output any warnings as needed, before modifying those options\n this._validateDecimalPlacesRawValue(settings);\n\n // Initialization phase\n //XXX This assumes at this stage, `settings.decimalPlaces` as been set from the default options\n\n // Overwrite the `decimalPlaces*` values if the `decimalPlaces*` options are not set in the `settings`\n // Sets `decimalPlacesShownOnBlur` (previously known as `scaleDecimalPlaces`)\n if (settings.decimalPlacesShownOnFocus === AutoNumeric.options.decimalPlacesShownOnFocus.useDefault) {\n settings.decimalPlacesShownOnFocus = settings.decimalPlaces;\n }\n\n if (settings.decimalPlacesShownOnBlur === AutoNumeric.options.decimalPlacesShownOnBlur.useDefault) {\n settings.decimalPlacesShownOnBlur = settings.decimalPlaces;\n }\n\n if (settings.decimalPlacesRawValue === AutoNumeric.options.decimalPlacesRawValue.useDefault) {\n settings.decimalPlacesRawValue = settings.decimalPlaces;\n }\n\n // Add the additional decimal places to the raw value\n var additionalDecimalPlacesRawValue = 0;\n if (settings.rawValueDivisor && settings.rawValueDivisor !== AutoNumeric.options.rawValueDivisor.none) {\n additionalDecimalPlacesRawValue = String(settings.rawValueDivisor).length - 1; // ie. Dividing by '100' adds 2 decimal places to the needed precision\n if (additionalDecimalPlacesRawValue < 0) {\n additionalDecimalPlacesRawValue = 0;\n }\n }\n\n settings.decimalPlacesRawValue = Math.max(Math.max(settings.decimalPlacesShownOnBlur, settings.decimalPlacesShownOnFocus) + additionalDecimalPlacesRawValue, Number(settings.originalDecimalPlacesRawValue) + additionalDecimalPlacesRawValue);\n }\n\n /**\n * Recalculate the number de decimal places to be used by the AutoNumeric object, for each of its state, and for its formatted and raw value.\n * By default, the `rawValue` precision is the same as the formatted value one.\n *\n * This method is close to the one called during initialization, `_calculateDecimalPlacesOnInit()`, but with slight difference so that the `decimalPlaces*` options are correctly updated as needed.\n *\n * This methods set the following options accordingly to their own value and the mandatory `decimalPlaces` option:\n * - decimalPlacesRawValue (nullable)\n * - decimalPlacesShownOnBlur (nullable)\n * - decimalPlacesShownOnFocus (nullable)\n *\n * Note: the `decimalPlaces` option is only used here and only serve to define those three previous options value.\n * AutoNumeric will then *only* use `decimalPlacesRawValue`, `decimalPlacesShownOnBlur` and `decimalPlacesShownOnFocus` from there.\n *\n * This methods directly modifies the `settings` object passed as a parameter.\n *\n * @param {object} settings This is an object with the new settings to use.\n * @param {object} currentSettings This is the current settings (`this.settings`) used by the element.\n * @private\n */\n\n }, {\n key: '_calculateDecimalPlacesOnUpdate',\n value: function _calculateDecimalPlacesOnUpdate(settings) {\n var currentSettings = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n // Check the `decimalPlaces*` options and output any warnings as needed, before modifying those options\n this._validateDecimalPlacesRawValue(settings);\n\n // Update phase\n if (_AutoNumericHelper2.default.isNull(currentSettings)) {\n _AutoNumericHelper2.default.throwError('When updating the settings, the previous ones should be passed as an argument.');\n }\n\n var decimalPlacesInOptions = 'decimalPlaces' in settings;\n if (!(decimalPlacesInOptions || 'decimalPlacesRawValue' in settings || 'decimalPlacesShownOnFocus' in settings || 'decimalPlacesShownOnBlur' in settings || 'rawValueDivisor' in settings)) {\n // Do Nothing if no decimal places-related options are modified\n return;\n }\n\n // Overwrite the `decimalPlaces*` values if the `decimalPlaces*` options are not set in the `settings`\n if (decimalPlacesInOptions) {\n if (!('decimalPlacesShownOnFocus' in settings) || settings.decimalPlacesShownOnFocus === AutoNumeric.options.decimalPlacesShownOnFocus.useDefault) {\n settings.decimalPlacesShownOnFocus = settings.decimalPlaces;\n }\n\n if (!('decimalPlacesShownOnBlur' in settings) || settings.decimalPlacesShownOnBlur === AutoNumeric.options.decimalPlacesShownOnBlur.useDefault) {\n settings.decimalPlacesShownOnBlur = settings.decimalPlaces;\n }\n\n if (!('decimalPlacesRawValue' in settings) || settings.decimalPlacesRawValue === AutoNumeric.options.decimalPlacesRawValue.useDefault) {\n settings.decimalPlacesRawValue = settings.decimalPlaces;\n }\n } else {\n if (_AutoNumericHelper2.default.isUndefined(settings.decimalPlacesShownOnFocus)) {\n settings.decimalPlacesShownOnFocus = currentSettings.decimalPlacesShownOnFocus;\n }\n\n if (_AutoNumericHelper2.default.isUndefined(settings.decimalPlacesShownOnBlur)) {\n settings.decimalPlacesShownOnBlur = currentSettings.decimalPlacesShownOnBlur;\n }\n }\n\n // Add the additional decimal places to the raw value\n var additionalDecimalPlacesRawValue = 0;\n if (settings.rawValueDivisor && settings.rawValueDivisor !== AutoNumeric.options.rawValueDivisor.none) {\n additionalDecimalPlacesRawValue = String(settings.rawValueDivisor).length - 1; // ie. Dividing by '100' adds 2 decimal places to the needed precision\n if (additionalDecimalPlacesRawValue < 0) {\n additionalDecimalPlacesRawValue = 0;\n }\n }\n\n if (!settings.decimalPlaces && !settings.decimalPlacesRawValue) {\n settings.decimalPlacesRawValue = Math.max(Math.max(settings.decimalPlacesShownOnBlur, settings.decimalPlacesShownOnFocus) + additionalDecimalPlacesRawValue, Number(currentSettings.originalDecimalPlacesRawValue) + additionalDecimalPlacesRawValue);\n } else {\n settings.decimalPlacesRawValue = Math.max(Math.max(settings.decimalPlacesShownOnBlur, settings.decimalPlacesShownOnFocus) + additionalDecimalPlacesRawValue, Number(settings.decimalPlacesRawValue) + additionalDecimalPlacesRawValue);\n }\n }\n }, {\n key: '_cachesUsualRegularExpressions',\n value: function _cachesUsualRegularExpressions(settings, regex) {\n // Test if there is a negative character in the string\n var negativeSignReg = void 0;\n if (settings.negativeSignCharacter !== AutoNumeric.options.negativeSignCharacter.hyphen) {\n negativeSignReg = '([-\\\\' + settings.negativeSignCharacter + ']?)';\n } else {\n negativeSignReg = '(-?)';\n }\n\n regex.aNegRegAutoStrip = negativeSignReg;\n settings.allowedAutoStrip = new RegExp('[^-0123456789\\\\' + settings.decimalCharacter + ']', 'g');\n settings.numRegAutoStrip = new RegExp(negativeSignReg + '(?:\\\\' + settings.decimalCharacter + '?([0-9]+\\\\' + settings.decimalCharacter + '[0-9]+)|([0-9]*(?:\\\\' + settings.decimalCharacter + '[0-9]*)?))');\n\n // Using this regex version `^${regex.aNegRegAutoStrip}0*(\\\\d|$)` entirely clear the input on blur\n settings.stripReg = new RegExp('^' + regex.aNegRegAutoStrip + '0*([0-9])');\n }\n }, {\n key: '_convertOldOptionsToNewOnes',\n value: function _convertOldOptionsToNewOnes(options) {\n //TODO Delete this function once the old options are not used anymore\n var oldOptionsConverter = {\n // Old option names, with their corresponding new names\n aSep: 'digitGroupSeparator',\n nSep: 'showOnlyNumbersOnFocus',\n dGroup: 'digitalGroupSpacing',\n aDec: 'decimalCharacter',\n altDec: 'decimalCharacterAlternative',\n aSign: 'currencySymbol',\n pSign: 'currencySymbolPlacement',\n pNeg: 'negativePositiveSignPlacement',\n aSuffix: 'suffixText',\n oLimits: 'overrideMinMaxLimits',\n vMax: 'maximumValue',\n vMin: 'minimumValue',\n mDec: 'decimalPlacesOverride',\n eDec: 'decimalPlacesShownOnFocus',\n scaleDecimal: 'decimalPlacesShownOnBlur',\n aStor: 'saveValueToSessionStorage',\n mRound: 'roundingMethod',\n aPad: 'allowDecimalPadding',\n nBracket: 'negativeBracketsTypeOnBlur',\n wEmpty: 'emptyInputBehavior',\n lZero: 'leadingZero',\n aForm: 'formatOnPageLoad',\n sNumber: 'selectNumberOnly',\n anDefault: 'defaultValueOverride',\n unSetOnSubmit: 'unformatOnSubmit',\n outputType: 'outputFormat',\n debug: 'showWarnings',\n\n // Current options :\n allowDecimalPadding: true,\n caretPositionOnFocus: true,\n createLocalList: true,\n currencySymbol: true,\n currencySymbolPlacement: true,\n decimalCharacter: true,\n decimalCharacterAlternative: true,\n decimalPlaces: true,\n decimalPlacesRawValue: true,\n decimalPlacesShownOnBlur: true,\n decimalPlacesShownOnFocus: true,\n defaultValueOverride: true,\n digitalGroupSpacing: true,\n digitGroupSeparator: true,\n divisorWhenUnfocused: true,\n emptyInputBehavior: true,\n eventBubbles: true,\n eventIsCancelable: true,\n failOnUnknownOption: true,\n formatOnPageLoad: true,\n historySize: true,\n isCancellable: true,\n leadingZero: true,\n maximumValue: true,\n minimumValue: true,\n modifyValueOnWheel: true,\n negativeBracketsTypeOnBlur: true,\n negativePositiveSignPlacement: true,\n negativeSignCharacter: true,\n noEventListeners: true,\n onInvalidPaste: true,\n outputFormat: true,\n overrideMinMaxLimits: true,\n positiveSignCharacter: true,\n rawValueDivisor: true,\n readOnly: true,\n roundingMethod: true,\n saveValueToSessionStorage: true,\n selectNumberOnly: true,\n selectOnFocus: true,\n serializeSpaces: true,\n showOnlyNumbersOnFocus: true,\n showPositiveSign: true,\n showWarnings: true,\n styleRules: true,\n suffixText: true,\n symbolWhenUnfocused: true,\n unformatOnHover: true,\n unformatOnSubmit: true,\n valuesToStrings: true,\n watchExternalChanges: true,\n wheelOn: true,\n wheelStep: true,\n\n // Additional information that are added to the `settings` object :\n //TODO Find a way to exclude those internal data from the settings object (ideally by using another object, or better yet, class attributes) -->\n allowedAutoStrip: true,\n isNegativeSignAllowed: true,\n isPositiveSignAllowed: true,\n mIntNeg: true,\n mIntPos: true,\n numRegAutoStrip: true,\n originalDecimalPlaces: true,\n originalDecimalPlacesRawValue: true,\n stripReg: true\n };\n\n for (var option in options) {\n if (options.hasOwnProperty(option)) {\n if (oldOptionsConverter[option] === true) {\n // If the option is a 'new' option, we continue looping\n continue;\n }\n\n if (oldOptionsConverter.hasOwnProperty(option)) {\n // Else we have an 'old' option name\n _AutoNumericHelper2.default.warning('You are using the deprecated option name \\'' + option + '\\'. Please use \\'' + oldOptionsConverter[option] + '\\' instead from now on. The old option name will be dropped very soon\\u2122.', true);\n\n // Then we modify the initial option object to use the new options instead of the old ones\n options[oldOptionsConverter[option]] = options[option];\n delete options[option];\n } else if (options.failOnUnknownOption) {\n // ...or the option name is unknown. This means there is a problem with the options object, therefore we throw an error.\n _AutoNumericHelper2.default.throwError('Option name \\'' + option + '\\' is unknown. Please fix the options passed to autoNumeric');\n }\n }\n }\n\n if ('mDec' in options) {\n _AutoNumericHelper2.default.warning('The old `mDec` option has been deprecated in favor of more accurate options ; `decimalPlaces`, `decimalPlacesRawValue`, `decimalPlacesShownOnFocus` and `decimalPlacesShownOnBlur`.', true);\n }\n }\n }, {\n key: '_setNegativePositiveSignPermissions',\n value: function _setNegativePositiveSignPermissions(settings) {\n settings.isNegativeSignAllowed = settings.minimumValue < 0;\n settings.isPositiveSignAllowed = settings.maximumValue >= 0;\n }\n\n /**\n * Convert the `value` parameter that can either be :\n * - a real number,\n * - a number represented in the scientific notation (ie. -123.4567e-6)\n * - a string representing a real number, or\n * - a string representing a localized number (with specific group separators and decimal character),\n * ...to a string representing a real 'javascript' number (ie. '1234' or '1234.567').\n *\n * This function returns `NaN` if such conversion fails.\n *\n * @param {int|float|string} value\n * @param {object} settings\n * @returns {string|NaN}\n */\n\n }, {\n key: '_toNumericValue',\n value: function _toNumericValue(value, settings) {\n //XXX Note; this function is static since we need to pass a `settings` object when calling the static `AutoNumeric.format()` method\n var result = void 0;\n if (_AutoNumericHelper2.default.isNumber(Number(value))) {\n // The value has either already been stripped, or a 'real' javascript number is passed as a parameter\n result = _AutoNumericHelper2.default.scientificToDecimal(value);\n } else {\n // Else if it's a string that `Number()` cannot typecast, then we try to convert the localized numeric string to a numeric one\n // Convert the value to a numeric string, stripping unnecessary characters in the process\n result = this._convertToNumericString(value.toString(), settings);\n\n // If the result is still not a numeric string, then we throw a warning\n if (!_AutoNumericHelper2.default.isNumber(Number(result))) {\n _AutoNumericHelper2.default.warning('The given value \"' + value + '\" cannot be converted to a numeric one and therefore cannot be used appropriately.', settings.showWarnings);\n result = NaN;\n }\n }\n\n return result;\n }\n }, {\n key: '_checkIfInRange',\n value: function _checkIfInRange(value, parsedMinValue, parsedMaxValue) {\n var parsedValue = _AutoNumericHelper2.default.parseStr(value);\n return _AutoNumericHelper2.default.testMinMax(parsedMinValue, parsedValue) > -1 && _AutoNumericHelper2.default.testMinMax(parsedMaxValue, parsedValue) < 1;\n }\n }, {\n key: '_shouldSkipEventKey',\n value: function _shouldSkipEventKey(eventKeyName) {\n var isFnKeys = _AutoNumericHelper2.default.isInArray(eventKeyName, _AutoNumericEnum2.default.keyName._allFnKeys);\n var isOSKeys = eventKeyName === _AutoNumericEnum2.default.keyName.OSLeft || eventKeyName === _AutoNumericEnum2.default.keyName.OSRight;\n var isContextMenu = eventKeyName === _AutoNumericEnum2.default.keyName.ContextMenu;\n var isSomeNonPrintableKeys = _AutoNumericHelper2.default.isInArray(eventKeyName, _AutoNumericEnum2.default.keyName._someNonPrintableKeys);\n var isOtherNonPrintableKeys = eventKeyName === _AutoNumericEnum2.default.keyName.NumLock || eventKeyName === _AutoNumericEnum2.default.keyName.ScrollLock || eventKeyName === _AutoNumericEnum2.default.keyName.Insert || eventKeyName === _AutoNumericEnum2.default.keyName.Command;\n var isUnrecognizableKeys = eventKeyName === _AutoNumericEnum2.default.keyName.Unidentified;\n\n return isFnKeys || isOSKeys || isContextMenu || isSomeNonPrintableKeys || isUnrecognizableKeys || isOtherNonPrintableKeys;\n }\n }, {\n key: '_serialize',\n value: function _serialize(form) {\n var intoAnArray = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;\n var formatType = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 'unformatted';\n\n var _this14 = this;\n\n var serializedSpaceCharacter = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : '+';\n var forcedOutputFormat = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : null;\n\n var result = [];\n\n if ((typeof form === 'undefined' ? 'undefined' : _typeof(form)) === 'object' && form.nodeName.toLowerCase() === 'form') {\n Array.prototype.slice.call(form.elements).forEach(function (element) {\n if (element.name && !element.disabled && ['file', 'reset', 'submit', 'button'].indexOf(element.type) === -1) {\n if (element.type === 'select-multiple') {\n Array.prototype.slice.call(element.options).forEach(function (option) {\n if (option.selected) {\n //TODO Should we unformat/format/localize the selection option (which be default should be read-only)?\n if (intoAnArray) {\n result.push({ name: element.name, value: option.value });\n } else {\n // into a string\n result.push(encodeURIComponent(element.name) + '=' + encodeURIComponent(option.value));\n }\n }\n });\n } else if (['checkbox', 'radio'].indexOf(element.type) === -1 || element.checked) {\n var valueResult = void 0;\n if (_this14.isManagedByAutoNumeric(element)) {\n var anObject = void 0;\n switch (formatType) {\n case 'unformatted':\n anObject = _this14.getAutoNumericElement(element);\n if (!_AutoNumericHelper2.default.isNull(anObject)) {\n valueResult = _this14.unformat(element, anObject.getSettings());\n }\n\n break;\n case 'localized':\n anObject = _this14.getAutoNumericElement(element);\n if (!_AutoNumericHelper2.default.isNull(anObject)) {\n // Here I need to clone the setting object, otherwise I would modify it when changing the `outputFormat` option value\n var currentSettings = _AutoNumericHelper2.default.cloneObject(anObject.getSettings());\n if (!_AutoNumericHelper2.default.isNull(forcedOutputFormat)) {\n currentSettings.outputFormat = forcedOutputFormat;\n }\n\n valueResult = _this14.localize(element, currentSettings);\n }\n\n break;\n case 'formatted':\n default:\n valueResult = element.value;\n }\n } else {\n valueResult = element.value;\n }\n\n if (_AutoNumericHelper2.default.isUndefined(valueResult)) {\n _AutoNumericHelper2.default.throwError('This error should never be hit. If it has, something really wrong happened!');\n }\n\n if (intoAnArray) {\n result.push({ name: element.name, value: valueResult });\n } else {\n // into a string\n result.push(encodeURIComponent(element.name) + '=' + encodeURIComponent(valueResult));\n }\n }\n }\n });\n }\n\n var finalResult = void 0;\n\n if (intoAnArray) {\n // Result as an Array\n // Note: `serializedSpaceCharacter` does not affect the array result since we do not change the space character for this one\n finalResult = result;\n } else {\n // Result as a string\n finalResult = result.join('&');\n\n if ('+' === serializedSpaceCharacter) {\n finalResult = finalResult.replace(/%20/g, '+');\n }\n }\n\n return finalResult;\n }\n\n /**\n * Serialize the form values to a string, outputting numeric strings for each AutoNumeric-managed element values.\n *\n * @param {HTMLFormElement} form\n * @param {string} serializedSpaceCharacter\n * @returns {string}\n */\n\n }, {\n key: '_serializeNumericString',\n value: function _serializeNumericString(form) {\n var serializedSpaceCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '+';\n\n return this._serialize(form, false, 'unformatted', serializedSpaceCharacter);\n }\n\n /**\n * Serialize the form values to a string, outputting the formatted value as strings for each AutoNumeric-managed elements.\n *\n * @param {HTMLFormElement} form\n * @param {string} serializedSpaceCharacter\n * @returns {string}\n */\n\n }, {\n key: '_serializeFormatted',\n value: function _serializeFormatted(form) {\n var serializedSpaceCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '+';\n\n return this._serialize(form, false, 'formatted', serializedSpaceCharacter);\n }\n\n /**\n * Serialize the form values to a string, outputting localized strings for each AutoNumeric-managed element values.\n *\n * @param {HTMLFormElement} form\n * @param {string} serializedSpaceCharacter\n * @param {string|null} forcedOutputFormat If set, then this is the format that is used for the localization, instead of the default `outputFormat` option.\n * @returns {string}\n */\n\n }, {\n key: '_serializeLocalized',\n value: function _serializeLocalized(form) {\n var serializedSpaceCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '+';\n var forcedOutputFormat = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n return this._serialize(form, false, 'localized', serializedSpaceCharacter, forcedOutputFormat);\n }\n\n /**\n * Generate an Array with the form values, outputting numeric strings for each AutoNumeric-managed element values.\n *\n * @param {HTMLFormElement} form\n * @param {string} serializedSpaceCharacter\n * @returns {Array}\n */\n\n }, {\n key: '_serializeNumericStringArray',\n value: function _serializeNumericStringArray(form) {\n var serializedSpaceCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '+';\n\n return this._serialize(form, true, 'unformatted', serializedSpaceCharacter);\n }\n\n /**\n * Generate an Array with the form values, outputting the formatted value as strings for each AutoNumeric-managed elements.\n *\n * @param {HTMLFormElement} form\n * @param {string} serializedSpaceCharacter\n * @returns {Array}\n */\n\n }, {\n key: '_serializeFormattedArray',\n value: function _serializeFormattedArray(form) {\n var serializedSpaceCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '+';\n\n return this._serialize(form, true, 'formatted', serializedSpaceCharacter);\n }\n\n /**\n * Generate an Array with the form values, outputting localized strings for each AutoNumeric-managed element values.\n *\n * @param {HTMLFormElement} form\n * @param {string} serializedSpaceCharacter\n * @param {string|null} forcedOutputFormat If set, then this is the format that is used for the localization, instead of the default `outputFormat` option.\n * @returns {Array}\n */\n\n }, {\n key: '_serializeLocalizedArray',\n value: function _serializeLocalizedArray(form) {\n var serializedSpaceCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '+';\n var forcedOutputFormat = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n return this._serialize(form, true, 'localized', serializedSpaceCharacter, forcedOutputFormat);\n }\n }]);\n\n return AutoNumeric;\n}();\n\n/**\n * Initialize multiple DOM elements in one call (and possibly pass multiple values that will be mapped to each DOM element).\n *\n * @example\n * // Init multiple DOM elements in one call (and possibly pass multiple values that will be mapped to each DOM element)\n * [anElement1, anElement2, anElement3] = AutoNumeric.multiple([domElement1, domElement2, domElement3], { options });\n * [anElement1, anElement2, anElement3] = AutoNumeric.multiple([domElement1, domElement2, domElement3], [{ options }, 'euroPos']);\n * [anElement1, anElement2, anElement3] = AutoNumeric.multiple([domElement1, domElement2, domElement3], 12345.789, { options });\n * [anElement1, anElement2, anElement3] = AutoNumeric.multiple([domElement1, domElement2, domElement3], 12345.789, [{ options }, 'euroPos']);\n * [anElement1, anElement2, anElement3] = AutoNumeric.multiple.french([domElement1, domElement2, domElement3], [12345.789, 234.78, null], { options });\n * [anElement1, anElement2, anElement3] = AutoNumeric.multiple.french([domElement1, domElement2, domElement3], [12345.789, 234.78, null], [{ options }, 'euroPos']);\n *\n * // Special case, if a element is passed (or any other 'parent' (or 'root') DOM element), then autoNumeric will initialize each child `` elements recursively, ignoring those referenced in the `exclude` attribute\n * [anElement1, anElement2] = AutoNumeric.multiple({ rootElement: formElement }, { options });\n * [anElement1, anElement2] = AutoNumeric.multiple({ rootElement: formElement, exclude : [hiddenElement, tokenElement] }, { options });\n * [anElement1, anElement2] = AutoNumeric.multiple({ rootElement: formElement, exclude : [hiddenElement, tokenElement] }, [12345.789, null], { options });\n *\n * // If you want to select multiple elements via a css selector, then you must use the `multiple` function. Under the hood `QuerySelectorAll` is used.\n * [anElement1, anElement2] = AutoNumeric.multiple('.myCssClass > input', { options }); // This always return an Array, even if there is only one element selected\n * [anElement1, anElement2] = AutoNumeric.multiple('.myCssClass > input', [null, 12345.789], { options }); // Idem above, but with passing the initial values too\n *\n * @param {string|Array|{ rootElement: HTMLElement }|{ rootElement: HTMLElement, exclude: Array}} arg1\n * @param {number|Array|object|null} initialValue\n * @param {object|Array|null} options\n * @returns {Array}\n */\n\n\nexports.default = AutoNumeric;\nAutoNumeric.multiple = function (arg1) {\n var initialValue = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n var options = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n var result = [];\n\n // Analyze the arguments and transform them to make them exploitable\n if (_AutoNumericHelper2.default.isObject(initialValue)) {\n // If the user gave an option object as the second argument, instead of the initial values\n options = initialValue;\n initialValue = null;\n }\n\n if (_AutoNumericHelper2.default.isString(arg1)) {\n arg1 = [].concat(_toConsumableArray(document.querySelectorAll(arg1))); // Convert a NodeList to an Array (cf. http://stackoverflow.com/a/37297292/2834898)\n } else if (_AutoNumericHelper2.default.isObject(arg1)) {\n if (!arg1.hasOwnProperty('rootElement')) {\n _AutoNumericHelper2.default.throwError('The object passed to the \\'multiple\\' function is invalid ; no \\'rootElement\\' attribute found.');\n }\n\n // Retrieve the DOM element list from the given element\n var elements = [].concat(_toConsumableArray(arg1.rootElement.querySelectorAll('input')));\n if (arg1.hasOwnProperty('exclude')) {\n if (!Array.isArray(arg1.exclude)) {\n _AutoNumericHelper2.default.throwError('The \\'exclude\\' array passed to the \\'multiple\\' function is invalid.');\n }\n\n // Filter out the excluded elements\n arg1 = _AutoNumericHelper2.default.filterOut(elements, arg1.exclude);\n } else {\n arg1 = elements;\n }\n } else if (!_AutoNumericHelper2.default.isArray(arg1)) {\n _AutoNumericHelper2.default.throwError('The given parameters to the \\'multiple\\' function are invalid.');\n }\n\n if (arg1.length === 0) {\n var showWarnings = true;\n if (!_AutoNumericHelper2.default.isNull(options) && _AutoNumericHelper2.default.isBoolean(options.showWarnings)) {\n showWarnings = options.showWarnings;\n }\n\n _AutoNumericHelper2.default.warning('No valid DOM elements were given hence no AutoNumeric object were instantiated.', showWarnings);\n\n return [];\n }\n\n // At this point, we know `arg1` is an array of DOM elements\n\n // This function can be initialized with two types of array, one for the initial values, and/or one for the options.\n // So we need to find out if an array is detected if the user passed an array of initial values, or an array of options\n // Therefore, we analyze the content of the arrays for the second and third arguments\n // ...for the second parameter :\n var isInitialValueArray = _AutoNumericHelper2.default.isArray(initialValue);\n var isInitialValueArrayAndNotEmpty = isInitialValueArray && initialValue.length >= 1;\n var secondArgumentIsInitialValueArray = false;\n var secondArgumentIsOptionArray = false;\n // Any of the arrays can be either an array of initial values, or an array of option object/pre-defined option names\n if (isInitialValueArrayAndNotEmpty) {\n var typeOfFirstArrayElement = _typeof(Number(initialValue[0]));\n // First we test the second argument\n secondArgumentIsInitialValueArray = typeOfFirstArrayElement === 'number' && !isNaN(Number(initialValue[0]));\n\n if (!secondArgumentIsInitialValueArray) {\n // If the second argument is an array, but not an array of values, check if it's instead an array of options/pre-defined option names\n if (typeOfFirstArrayElement === 'string' || isNaN(typeOfFirstArrayElement) || typeOfFirstArrayElement === 'object') {\n secondArgumentIsOptionArray = true;\n }\n }\n }\n\n // ...for the third parameter :\n var isOptionsArrayAndNotEmpty = _AutoNumericHelper2.default.isArray(options) && options.length >= 1;\n var thirdArgumentIsOptionArray = false;\n if (isOptionsArrayAndNotEmpty) {\n var _typeOfFirstArrayElement = _typeof(options[0]);\n if (_typeOfFirstArrayElement === 'string' || _typeOfFirstArrayElement === 'object') {\n // If the third argument is an array of options/pre-defined option names\n thirdArgumentIsOptionArray = true;\n }\n }\n\n // Depending of our findings, we generate the options variable to use `optionsToUse`, either directly, or merged\n var optionsToUse = void 0;\n if (secondArgumentIsOptionArray) {\n optionsToUse = AutoNumeric.mergeOptions(initialValue);\n } else if (thirdArgumentIsOptionArray) {\n optionsToUse = AutoNumeric.mergeOptions(options);\n } else {\n optionsToUse = options;\n }\n\n // Initialize the initial values\n var isInitialValueNumber = _AutoNumericHelper2.default.isNumber(initialValue);\n var initialValueArraySize = void 0;\n if (secondArgumentIsInitialValueArray) {\n initialValueArraySize = initialValue.length;\n }\n\n // Instantiate each AutoNumeric objects\n arg1.forEach(function (domElement, index) {\n if (isInitialValueNumber) {\n // We set the same value for each elements\n result.push(new AutoNumeric(domElement, initialValue, optionsToUse));\n } else if (secondArgumentIsInitialValueArray && index <= initialValueArraySize) {\n result.push(new AutoNumeric(domElement, initialValue[index], optionsToUse));\n } else {\n result.push(new AutoNumeric(domElement, null, optionsToUse));\n }\n });\n\n return result;\n};\n\n/**\n * Polyfill for obsolete browsers like IE\n */\n(function () {\n // Polyfill for `CustomEvent` (cf. https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent)\n if (typeof window === 'undefined' || window.CustomEvent === 'function') {\n return false;\n }\n\n function CustomEvent(event, params) {\n params = params || { bubbles: false, cancelable: false, detail: void 0 };\n var evt = document.createEvent('CustomEvent');\n evt.initCustomEvent(event, params.bubbles, params.cancelable, params.detail);\n return evt;\n }\n\n CustomEvent.prototype = window.Event.prototype;\n window.CustomEvent = CustomEvent;\n\n // Polyfill for `Array.from()` (Fix issue #495)\n if (!Array.from) {\n Array.from = function (object) {\n return [].slice.call(object);\n };\n }\n})();\nmodule.exports = exports['default'];\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWMuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9BdXRvTnVtZXJpYy9zcmMvQXV0b051bWVyaWMuanM/ZTE0NyJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqICAgICAgICAgICAgICAgQXV0b051bWVyaWMuanNcbiAqXG4gKiBAdmVyc2lvbiAgICAgIDQuMi45XG4gKiBAZGF0ZSAgICAgICAgIDIwMTgtMDMtMjYgVVRDIDE5OjEwXG4gKlxuICogQGF1dGhvcnMgICAgICBCb2IgS25vdGhlLCBBbGV4YW5kcmUgQm9ubmVhdVxuICogQGNvbnRyaWJ1dG9ycyBTb2tvbG92IFl1cmEgYW5kIG90aGVycywgY2YuIEFVVEhPUlNcbiAqIEBjb3B5cmlnaHQgICAgMjAwOSBSb2JlcnQgSi4gS25vdGhlXG4gKiBAc2luY2UgICAgICAgIDIwMDktMDgtMDlcbiAqXG4gKiBAc3VtbWFyeSAgICAgIGF1dG9OdW1lcmljIGlzIGEgc3RhbmRhbG9uZSBKYXZhc2NyaXB0IGxpYnJhcnlcbiAqICAgICAgICAgICAgICAgdGhhdCBwcm92aWRlcyBsaXZlICphcy15b3UtdHlwZSogZm9ybWF0dGluZyBmb3JcbiAqICAgICAgICAgICAgICAgaW50ZXJuYXRpb25hbCBudW1iZXJzIGFuZCBjdXJyZW5jaWVzLlxuICpcbiAqIEBsaW5rICAgICAgICAgaHR0cDovL2F1dG9udW1lcmljLm9yZ1xuICpcbiAqICAgICAgICAgICAgICAgTm90ZSA6IFNvbWUgZnVuY3Rpb25zIGFyZSBib3Jyb3dlZCBmcm9tIGJpZy5qc1xuICogQHNlZSAgICAgICAgICBodHRwczovL2dpdGh1Yi5jb20vTWlrZU1jbC9iaWcuanMvXG4gKlxuICogUGxlYXNlIHJlcG9ydCBhbnkgYnVncyB0byBodHRwczovL2dpdGh1Yi5jb20vYXV0b051bWVyaWMvYXV0b051bWVyaWNcbiAqXG4gKiBAbGljZW5zZSAgICAgIFJlbGVhc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZVxuICogQGxpbmsgICAgICAgICBodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocFxuICpcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uXG4gKiBvYnRhaW5pbmcgYSBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvblxuICogZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0XG4gKiByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSxcbiAqIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YiBsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlXG4gKiBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZ1xuICogY29uZGl0aW9uczpcbiAqXG4gKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZVxuICogaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gKlxuICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCxcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFU1xuICogT0YgTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkRcbiAqIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUXG4gKiBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSxcbiAqIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lOR1xuICogRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUlxuICogT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuICovXG5cbi8vVE9ETyBQcmV2ZW50IGhhdmluZyB0byBlbnRlciByZWxhdGl2ZSBwYXRoIGluIHRoZSBqcyBmaWxlcyAoaWUuIHVzaW5nIGAuL0F1dG9OdW1lcmljSGVscGVyYCBpbnN0ZWFkIG9mIGp1c3QgYEF1dG9OdW1lcmljSGVscGVyYCkgKGNmLiBodHRwOi8vbW9kdXNjcmVhdGUuY29tL2VzNi1lczIwMTUtaW1wb3J0LW5vLXJlbGF0aXZlLXBhdGgtd2VicGFjay8pXG5pbXBvcnQgQXV0b051bWVyaWNIZWxwZXIgZnJvbSAnLi9BdXRvTnVtZXJpY0hlbHBlcic7XG5pbXBvcnQgQXV0b051bWVyaWNFbnVtIGZyb20gJy4vQXV0b051bWVyaWNFbnVtJztcblxuLyoqXG4gKiBDbGFzcyBkZWNsYXJhdGlvbiBmb3IgdGhlIEF1dG9OdW1lcmljIG9iamVjdC5cbiAqXG4gKiBBbiBBdXRvTnVtZXJpYyBlbGVtZW50IGlzIGFuIG9iamVjdCB3cmFwcGVyIHRoYXQga2VlcHMgYSByZWZlcmVuY2UgdG8gdGhlIERPTSBlbGVtZW50IGl0IG1hbmFnZXMgKHVzdWFsbHkgYW4gPGlucHV0PiBvbmUpLCBhbmQgcHJvdmlkZXMgYXV0b051bWVyaWMtc3BlY2lmaWMgdmFyaWFibGVzIGFuZCBmdW5jdGlvbnMuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEF1dG9OdW1lcmljIHtcbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXplIHRoZSBBdXRvTnVtZXJpYyBvYmplY3Qgb250byB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQsIGFuZCBhdHRhY2ggdGhlIHNldHRpbmdzIGFuZCByZWxhdGVkIGV2ZW50IGxpc3RlbmVycyB0byBpdC5cbiAgICAgKiBUaGUgb3B0aW9ucyBwYXNzZWQgYXMgYSBwYXJhbWV0ZXIgaXMgYW4gb2JqZWN0IHRoYXQgY29udGFpbnMgdGhlIHNldHRpbmdzIChpZS4ge2RpZ2l0R3JvdXBTZXBhcmF0b3I6IFwiLlwiLCBkZWNpbWFsQ2hhcmFjdGVyOiBcIixcIiwgY3VycmVuY3lTeW1ib2w6ICfigqwgJ30pXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50KTsgLy8gV2l0aCB0aGUgZGVmYXVsdCBvcHRpb25zXG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIHsgb3B0aW9ucyB9KTsgLy8gV2l0aCBvbmUgb3B0aW9uIG9iamVjdFxuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAnZXVyb1BvcycpOyAvLyBXaXRoIGEgbmFtZWQgcHJlLWRlZmluZWQgc3RyaW5nXG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIFt7IG9wdGlvbnMxIH0sICdldXJvUG9zJywgeyBvcHRpb25zMiB9XSk7IC8vIFdpdGggbXVsdGlwbGUgb3B0aW9uIG9iamVjdHMgKHRoZSBsYXRlc3Qgb3B0aW9uIG92ZXJ3cml0aW5nIHRoZSBwcmV2aW91cyBvbmVzKVxuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCBudWxsLCB7IG9wdGlvbnMgfSk7IC8vIFdpdGggb25lIG9wdGlvbiBvYmplY3QsIGFuZCBhIGZhaWxlZCBpbml0aWFsIHZhbHVlXG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQpLmZyZW5jaCgpOyAvLyBXaXRoIG9uZSBwcmUtZGVmaW5lZCBsYW5ndWFnZSBvYmplY3RcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCkuZnJlbmNoKHsgb3B0aW9ucyB9KTsvLyBXaXRoIG9uZSBwcmUtZGVmaW5lZCBsYW5ndWFnZSBvYmplY3QgYW5kIGFkZGl0aW9uYWwgb3B0aW9ucyB0aGF0IHdpbGwgb3ZlcnJpZGUgdGhlIGRlZmF1bHRzXG4gICAgICpcbiAgICAgKiAvLyAuLi5vciBpbml0IGFuZCBzZXQgdGhlIHZhbHVlIGluIG9uZSBjYWxsIDpcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgMTIzNDUuNzg5KTsgLy8gV2l0aCB0aGUgZGVmYXVsdCBvcHRpb25zLCBhbmQgYW4gaW5pdGlhbCB2YWx1ZVxuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAxMjM0NS43ODksIHsgb3B0aW9ucyB9KTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgJzEyMzQ1Ljc4OScsIHsgb3B0aW9ucyB9KTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgMTIzNDUuNzg5LCAnZXVyb1BvcycpO1xuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAxMjM0NS43ODksIFt7IG9wdGlvbnMxIH0sICdldXJvUG9zJywgeyBvcHRpb25zMiB9XSk7XG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIDEyMzQ1Ljc4OSkuZnJlbmNoKHsgb3B0aW9ucyB9KTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgMTIzNDUuNzg5LCB7IG9wdGlvbnMgfSkuZnJlbmNoKHsgb3B0aW9ucyB9KTsgLy8gTm90IHJlYWxseSBoZWxwZnVsLCBidXQgcG9zc2libGVcbiAgICAgKlxuICAgICAqIC8vIFRoZSBBdXRvTnVtZXJpYyBjb25zdHJ1Y3RvciBjbGFzcyBjYW4gYWxzbyBhY2NlcHQgYSBzdHJpbmcgYXMgYSBjc3Mgc2VsZWN0b3IuIFVuZGVyIHRoZSBob29kIHRoaXMgdXNlIGBRdWVyeVNlbGVjdG9yYCBhbmQgbGltaXQgaXRzZWxmIHRvIG9ubHkgdGhlIGZpcnN0IGVsZW1lbnQgaXQgZmluZHMuXG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0Jyk7XG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgeyBvcHRpb25zIH0pO1xuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsICdldXJvUG9zJyk7XG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgW3sgb3B0aW9uczEgfSwgJ2V1cm9Qb3MnLCB7IG9wdGlvbnMyIH1dKTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAxMjM0NS43ODkpO1xuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIDEyMzQ1Ljc4OSwgeyBvcHRpb25zIH0pO1xuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIDEyMzQ1Ljc4OSwgJ2V1cm9Qb3MnKTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAxMjM0NS43ODksIFt7IG9wdGlvbnMxIH0sICdldXJvUG9zJywgeyBvcHRpb25zMiB9XSk7XG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgbnVsbCwgeyBvcHRpb25zIH0pOyAvLyBXaXRoIGEgZmFpbGVkIGluaXRpYWwgdmFsdWVcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAxMjM0NS43ODkpLmZyZW5jaCh7IG9wdGlvbnMgfSk7XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdHxBcnJheXxudW1iZXJ8c3RyaW5nfSBhcmcxXG4gICAgICogQHBhcmFtIHtvYmplY3R8QXJyYXl8bnVtYmVyfHN0cmluZ3xudWxsfSBhcmcyXG4gICAgICogQHBhcmFtIHtvYmplY3R8QXJyYXl8bnVtYmVyfHN0cmluZ3xudWxsfSBhcmczXG4gICAgICogQHRocm93c1xuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGFyZzEgPSBudWxsLCBhcmcyID0gbnVsbCwgYXJnMyA9IG51bGwpIHtcbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0gSW5pdGlhbGl6YXRpb25cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgYXJndW1lbnRzXG4gICAgICAgIGNvbnN0IHsgZG9tRWxlbWVudCwgaW5pdGlhbFZhbHVlLCB1c2VyT3B0aW9ucyB9ID0gQXV0b051bWVyaWMuX3NldEFyZ3VtZW50c1ZhbHVlcyhhcmcxLCBhcmcyLCBhcmczKTtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBlbGVtZW50XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudCA9IGRvbUVsZW1lbnQ7XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgdGhlIHNldHRpbmdzXG4gICAgICAgIHRoaXMuZGVmYXVsdFJhd1ZhbHVlID0gJyc7IC8vIFRoZSBkZWZhdWx0IHJhdyB2YWx1ZSB0byBzZXQgd2hlbiBpbml0aWFsaXppbmcgYW4gQXV0b051bWVyaWMgb2JqZWN0XG4gICAgICAgIHRoaXMuX3NldFNldHRpbmdzKHVzZXJPcHRpb25zLCBmYWxzZSk7XG4gICAgICAgIC8vVE9ETyBJZiBgc3R5bGVSdWxlc2AgaXMgbm90IG51bGwsIGFkZCBieSBkZWZhdWx0IGEgY2xhc3MgJ2F1dG9OdW1lcmljJyB0aGF0IGFkZHMgdHJhbnNpdGlvbiB0byBjb2xvciwgYmFja2dyb3VuZC1jb2xvciwgYm9yZGVyLWNvbG9yIHByb3BlcnRpZXNcbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIERPTSBlbGVtZW50IGlzIHN1cHBvcnRlZFxuICAgICAgICB0aGlzLl9jaGVja0VsZW1lbnQoKTtcblxuICAgICAgICAvLyBTdG9yZSB0aGUgYWRkaXRpb25hbCBhdHRyaWJ1dGVzIGluc2lkZSB0aGUgQXV0b051bWVyaWMgb2JqZWN0XG4gICAgICAgIC8vIE5vdGU6IFRoaXMgdmFyaWFibGUgaXMgbmVlZGVkIGFuZCBub3QgYSBkdXBsaWNhdGUgb2YgYGluaXRpYWxWYWx1ZU9uS2V5ZG93bmAgbm9yIGB2YWx1ZU9uRm9jdXNgIHNpbmNlIGl0IHNlcnZlcyBhIGRpZmZlcmVudCBwdXJwb3NlIGFuZCBoYXMgYSBkaWZmZXJlbnQgbGlmZWN5Y2xlXG4gICAgICAgIHRoaXMuc2F2ZWRDYW5jZWxsYWJsZVZhbHVlID0gbnVsbDtcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSB1bmRvL3JlZG8gdmFyaWFibGVzXG4gICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlID0gW107IC8vIEtlZXAgdHJhY2sgb2YgKmFsbCogdmFsaWQgc3RhdGVzIG9mIHRoZSBlbGVtZW50IHZhbHVlXG4gICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlSW5kZXggPSAtMTsgLy8gUG9pbnRlciB0byB0aGUgY3VycmVudCB1bmRvL3JlZG8gc3RhdGUuIFRoaXMgd2lsbCBiZSBzZXQgdG8gJzAnIGR1cmluZyBpbml0aWFsaXphdGlvbiBzaW5jZSBpdCBmaXJzdCBhZGRzIGl0c2VsZi5cbiAgICAgICAgdGhpcy5vbkdvaW5nUmVkbyA9IGZhbHNlOyAvLyBWYXJpYWJsZSB0aGF0IGtlZXBzIHRyYWNrIGlmIGEgJ3JlZG8nIGlzIG9uZ29pbmcgKGluIG9yZGVyIHRvIHByZXZlbnQgYW4gJ3VuZG8nIHRvIGJlIGxhdW5jaCB3aGVuIHJlbGVhc2luZyB0aGUgc2hpZnQga2V5IGJlZm9yZSB0aGUgY3RybCBrZXkgYWZ0ZXIgYSAncmVkbycgc2hvcnRjdXQpXG5cbiAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgcGFyZW50IGZvcm0gZWxlbWVudCwgaWYgYW55XG4gICAgICAgIHRoaXMucGFyZW50Rm9ybSA9IHRoaXMuX2dldFBhcmVudEZvcm0oKTtcblxuICAgICAgICAvLyBTZXQgdGhlIGluaXRpYWwgdmFsdWUgaWYgaXQgZXhpc3RzIGFuZCBpZiB0aGUgYGZvcm1hdE9uUGFnZUxvYWRgIG9wdGlvbiB3aWxsIGFsbG93IGl0XG4gICAgICAgIGlmICghdGhpcy5ydW5PbmNlICYmIHRoaXMuc2V0dGluZ3MuZm9ybWF0T25QYWdlTG9hZCkge1xuICAgICAgICAgICAgLy8gRm9ybWF0IHRoZSBlbGVtZW50IHZhbHVlIGlmIG5lZWRlZFxuICAgICAgICAgICAgdGhpcy5fZm9ybWF0RGVmYXVsdFZhbHVlT25QYWdlTG9hZChpbml0aWFsVmFsdWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT3RoZXJ3aXNlIHNldCB0aGUgYHJhd1ZhbHVlYCBhbmQgdGhlIGVsZW1lbnQgdmFsdWUsIGJ1dCBkbyBub3QgZm9ybWF0IHRoZSBsYXR0ZXIgeWV0XG4gICAgICAgICAgICBsZXQgdmFsdWVUb1NldDtcbiAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoaW5pdGlhbFZhbHVlKSkge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci56ZXJvOlxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVUb1NldCA9ICcwJztcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAvLyBJbiBvcmRlciB0byBzdGF5IGNvbnNpc3RlbnQgd2hlbiBgZm9ybWF0T25QYWdlTG9hZGAgaXMgc2V0IHRvIGB0cnVlYCwgaXQncyBzdGlsbCBpbXBvc3NpYmxlIHNvIHNldCB0aGUgYG51bGxgIHZhbHVlIGFzIHRoZSBpbml0aWFsIHZhbHVlXG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubnVsbDpcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVRvU2V0ID0gJyc7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YWx1ZVRvU2V0ID0gaW5pdGlhbFZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50QW5kUmF3VmFsdWUodmFsdWVUb1NldCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJ1bk9uY2UgPSB0cnVlO1xuXG4gICAgICAgIC8vIEFkZCB0aGUgZXZlbnRzIGxpc3RlbmVycyBvbmx5IG9uIGlucHV0IGVsZW1lbnRzXG4gICAgICAgIGlmICh0aGlzLmlzSW5wdXRFbGVtZW50IHx8IHRoaXMuaXNDb250ZW50RWRpdGFibGUpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5zZXR0aW5ncy5ub0V2ZW50TGlzdGVuZXJzKSB7XG4gICAgICAgICAgICAgICAgLy9YWFggSGVyZSB3ZSBtYWtlIHN1cmUgdGhlIGdsb2JhbCBsaXN0IGlzIGNyZWF0ZWQgYWZ0ZXIgY3JlYXRpbmcgdGhlIGV2ZW50IGxpc3RlbmVycywgdG8gb25seSBjcmVhdGUgdGhlIGV2ZW50IGxpc3RlbmVycyBvbiBgZG9jdW1lbnRgIG9uY2VcbiAgICAgICAgICAgICAgICB0aGlzLl9jcmVhdGVFdmVudExpc3RlbmVycygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9zZXRSZWFkT25seSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2F2ZSB0aGUgaW5pdGlhbCB2YWx1ZXMgKGh0bWwgYXR0cmlidXRlICsgZWxlbWVudC52YWx1ZSkgZm9yIHRoZSBwcmlzdGluZSB0ZXN0XG4gICAgICAgIHRoaXMuX3NhdmVJbml0aWFsVmFsdWVzKGluaXRpYWxWYWx1ZSk7XG4gICAgICAgIFxuICAgICAgICAvLyBTZXR1cCB0aGUgZGF0YSBmb3IgdGhlIHBlcnNpc3RlbnQgc3RvcmFnZSBzb2x1dGlvbiAoaWUuIHNlc3Npb25TdG9yYWdlIG9yIGNvb2tpZXMpXG4gICAgICAgIHRoaXMuc2Vzc2lvblN0b3JhZ2VBdmFpbGFibGUgPSB0aGlzLmNvbnN0cnVjdG9yLl9zdG9yYWdlVGVzdCgpO1xuICAgICAgICB0aGlzLnN0b3JhZ2VOYW1lUHJlZml4ID0gJ0FVVE9fJzsgLy8gVGhlIHByZWZpeCBmb3IgdGhlIHJhdyB2YWx1ZSBzdG9yYWdlIG5hbWUgdmFyaWFibGUgY2FuIGJlIG1vZGlmaWVkIGhlcmVcbiAgICAgICAgdGhpcy5fc2V0UGVyc2lzdGVudFN0b3JhZ2VOYW1lKCk7XG5cbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0gVHJhY2tpbmdcbiAgICAgICAgLy8gS2VlcCB0cmFjayBpZiB0aGUgZWxlbWVudCBpcyBjdXJyZW50bHkgZm9jdXNlZFxuICAgICAgICB0aGlzLmlzRm9jdXNlZCA9IGZhbHNlO1xuICAgICAgICAvLyBLZWVwIHRyYWNrIGlmIGEgbW91c2Ugd2hlZWwgZXZlbnQgaXMgY3VycmVudGx5IG9uZ29pbmdcbiAgICAgICAgdGhpcy5pc1doZWVsRXZlbnQgPSBmYWxzZTtcbiAgICAgICAgLy8gS2VlcCB0cmFjayBpZiBhIGRyb3AgZXZlbnQgaXMgY3VycmVudGx5IG9uZ29pbmdcbiAgICAgICAgdGhpcy5pc0Ryb3BFdmVudCA9IGZhbHNlO1xuICAgICAgICAvLyBLZWVwIHRyYWNrIGlmIHRoZSB1c2VyIGlzIGN1cnJlbnRseSBlZGl0aW5nIHRoZSBlbGVtZW50XG4gICAgICAgIHRoaXMuaXNFZGl0aW5nID0gZmFsc2U7XG4gICAgICAgIC8vIEtlZXAgdHJhY2sgb2YgdGhlIHJhd1ZhbHVlIChuZWVkZWQgdG8gZGVmaW5lIGlmIGEgY2hhbmdlIGV2ZW50IG11c3QgYmUgc2VudCBvbiBibHVyIG9yIGVudGVyIGtleSlcbiAgICAgICAgdGhpcy5yYXdWYWx1ZU9uRm9jdXMgPSB2b2lkKDApO1xuICAgICAgICAvLyBXYXRjaCBhbnkgZXh0ZXJuYWwgY2hhbmdlcyB0byB0aGUgZWxlbWVudCB2YWx1ZS90ZXh0Q29udGVudC9ub2RlVmFsdWUgYW5kIGBzZXQoKWAgdGhlIG5ldyB2YWx1ZSBzbyB0aGF0IGl0IGdldHMgZm9ybWF0dGVkL3NhdmVkIGluIHRoZSBoaXN0b3J5XG4gICAgICAgIHRoaXMuaW50ZXJuYWxNb2RpZmljYXRpb24gPSBmYWxzZTsgLy8gVGhpcyBpcyB0ZW1wb3JhcmlseSBzZXQgdG8gYHRydWVgIG9ubHkgd2hlbiB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGRvZXMgdXBkYXRlIHRoZSBlbGVtZW50IHZhbHVlXG4gICAgICAgIHRoaXMuYXR0cmlidXRlVG9XYXRjaCA9IHRoaXMuX2dldEF0dHJpYnV0ZVRvV2F0Y2goKTtcbiAgICAgICAgdGhpcy5nZXR0ZXJTZXR0ZXIgPSBPYmplY3QuZ2V0T3duUHJvcGVydHlEZXNjcmlwdG9yKHRoaXMuZG9tRWxlbWVudC5fX3Byb3RvX18sIHRoaXMuYXR0cmlidXRlVG9XYXRjaCk7XG4gICAgICAgIHRoaXMuX2FkZFdhdGNoZXIoKTtcblxuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jcmVhdGVMb2NhbExpc3QpIHtcbiAgICAgICAgICAgIC8vIEtlZXAgdHJhY2sgb2YgZXZlcnkgQXV0b051bWVyaWMgZWxlbWVudHMgdGhhdCB0aGlzIG9iamVjdCBpbml0aWFsaXplZFxuICAgICAgICAgICAgdGhpcy5fY3JlYXRlTG9jYWxMaXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBLZWVwIHRyYWNrIG9mIGFsbCBBdXRvTnVtZXJpYyBlbGVtZW50cyBpbiB0aGUgY3VycmVudCB3ZWIgcGFnZVxuICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl9hZGRUb0dsb2JhbExpc3QodGhpcyk7XG5cbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0gTWV0aG9kc1xuICAgICAgICAvLyBDcmVhdGUgdGhlIGdsb2JhbCBmdW5jdGlvbnNcbiAgICAgICAgdGhpcy5nbG9iYWwgPSB7XG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNldCB0aGUgc2FtZSBnaXZlbiBlbGVtZW50IHZhbHVlIGZvciBlYWNoIGVsZW1lbnRzIGluIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QsIGFuZCBmb3JtYXQgdGhvc2UgZWxlbWVudHMgaW1tZWRpYXRlbHlcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IG5ld1ZhbHVlIFRoZSB2YWx1ZSBtdXN0IGJlIGEgbnVtYmVyIG9yIGEgbnVtZXJpYyBzdHJpbmdcbiAgICAgICAgICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zIEEgc2V0dGluZ3Mgb2JqZWN0IHRoYXQgd2lsbCBvdmVycmlkZSB0aGUgY3VycmVudCBzZXR0aW5ncy4gTm90ZTogdGhlIHVwZGF0ZSBpcyBkb25lIG9ubHkgaWYgdGhlIGBuZXdWYWx1ZWAgaXMgZGVmaW5lZC5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2V0OiAobmV3VmFsdWUsIG9wdGlvbnMgPSBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3Quc2V0KG5ld1ZhbHVlLCBvcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogU2V0IHRoZSB2YWx1ZSBnaXZlbiB2YWx1ZSBkaXJlY3RseSBhcyB0aGUgRE9NIGVsZW1lbnQgdmFsdWUsIHdpdGhvdXQgZm9ybWF0dGluZyBpdCBiZWZvcmVoYW5kLlxuICAgICAgICAgICAgICogVGhpcyBzZXRzIHRoZSBzYW1lIHVuZm9ybWF0dGVkIHZhbHVlIGZvciBlYWNoIGVsZW1lbnRzIGluIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfSB2YWx1ZVxuICAgICAgICAgICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2V0VW5mb3JtYXR0ZWQ6ICh2YWx1ZSwgb3B0aW9ucyA9IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhTk9iamVjdC5zZXRVbmZvcm1hdHRlZCh2YWx1ZSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFRoaXMgaXMgYW4gYWxpYXMgb2YgdGhlIGBnZXROdW1lcmljU3RyaW5nKClgIGZ1bmN0aW9uLCBhbmQgc2hvdWxkIG5vdCBiZSB1c2VkIGFueW1vcmUuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn1cbiAgICAgICAgICAgICAqIEBkZXByZWNhdGVkXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldDogKGNhbGxiYWNrID0gbnVsbCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGFOT2JqZWN0LmdldCgpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLl9leGVjdXRlQ2FsbGJhY2socmVzdWx0LCBjYWxsYmFjayk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBSZXR1cm4gYW4gYXJyYXkgb2YgdGhlIHVuZm9ybWF0dGVkIHZhbHVlcyAoYXMgYSBzdHJpbmcpIG9mIGVhY2ggQXV0b051bWVyaWMgZWxlbWVudCBvZiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn1cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0TnVtZXJpY1N0cmluZzogKGNhbGxiYWNrID0gbnVsbCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGFOT2JqZWN0LmdldE51bWVyaWNTdHJpbmcoKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fZXhlY3V0ZUNhbGxiYWNrKHJlc3VsdCwgY2FsbGJhY2spO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmV0dXJuIGFuIGFycmF5IG9mIHRoZSBjdXJyZW50IGZvcm1hdHRlZCB2YWx1ZXMgKGFzIGEgc3RyaW5nKSBvZiBlYWNoIEF1dG9OdW1lcmljIGVsZW1lbnQgb2YgdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdFxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2sgSWYgYSBjYWxsYmFjayBpcyBwYXNzZWQsIHRoZW4gdGhlIHJlc3VsdCBpcyBwYXNzZWQgdG8gaXQgYXMgaXRzIGZpcnN0IGFyZ3VtZW50LCBhbmQgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBoYXMgaXRzIHNlY29uZFxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5PHN0cmluZz59XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldEZvcm1hdHRlZDogKGNhbGxiYWNrID0gbnVsbCkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGFOT2JqZWN0LmdldEZvcm1hdHRlZCgpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICB0aGlzLl9leGVjdXRlQ2FsbGJhY2socmVzdWx0LCBjYWxsYmFjayk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBSZXR1cm4gYW4gYXJyYXkgb2YgdGhlIGVsZW1lbnQgdW5mb3JtYXR0ZWQgdmFsdWVzIChhcyBhIHJlYWwgSmF2YXNjcmlwdCBudW1iZXIpLCBmb3IgZWFjaCBlbGVtZW50IG9mIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3RcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrIElmIGEgY2FsbGJhY2sgaXMgcGFzc2VkLCB0aGVuIHRoZSByZXN1bHQgaXMgcGFzc2VkIHRvIGl0IGFzIGl0cyBmaXJzdCBhcmd1bWVudCwgYW5kIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgaGFzIGl0cyBzZWNvbmRcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheTxudW1iZXI+fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXROdW1iZXI6IChjYWxsYmFjayA9IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChhTk9iamVjdC5nZXROdW1iZXIoKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fZXhlY3V0ZUNhbGxiYWNrKHJlc3VsdCwgY2FsbGJhY2spO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmV0dXJucyB0aGUgdW5mb3JtYXR0ZWQgdmFsdWVzIChmb2xsb3dpbmcgdGhlIGBvdXRwdXRGb3JtYXRgIHNldHRpbmcpIG9mIGVhY2ggZWxlbWVudCBvZiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0IGludG8gYW4gYXJyYXlcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrIElmIGEgY2FsbGJhY2sgaXMgcGFzc2VkLCB0aGVuIHRoZSByZXN1bHQgaXMgcGFzc2VkIHRvIGl0IGFzIGl0cyBmaXJzdCBhcmd1bWVudCwgYW5kIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgaGFzIGl0cyBzZWNvbmRcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheTxzdHJpbmc+fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXRMb2NhbGl6ZWQ6IChjYWxsYmFjayA9IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChhTk9iamVjdC5nZXRMb2NhbGl6ZWQoKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fZXhlY3V0ZUNhbGxiYWNrKHJlc3VsdCwgY2FsbGJhY2spO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogRm9yY2UgZWFjaCBlbGVtZW50IG9mIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QgdG8gcmVmb3JtYXQgaXRzIHZhbHVlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHJlZm9ybWF0OiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QucmVmb3JtYXQoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmVtb3ZlIHRoZSBmb3JtYXR0aW5nIGFuZCBrZWVwIG9ubHkgdGhlIHJhdyB1bmZvcm1hdHRlZCB2YWx1ZSAoYXMgYSBudW1lcmljU3RyaW5nKSBpbiBlYWNoIGVsZW1lbnRzIG9mIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3RcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdW5mb3JtYXQ6ICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhTk9iamVjdC51bmZvcm1hdCgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBSZW1vdmUgdGhlIGZvcm1hdHRpbmcgYW5kIGtlZXAgb25seSB0aGUgbG9jYWxpemVkIHVuZm9ybWF0dGVkIHZhbHVlIGluIHRoZSBlbGVtZW50LCB3aXRoIHRoZSBvcHRpb24gdG8gb3ZlcnJpZGUgdGhlIGRlZmF1bHQgb3V0cHV0Rm9ybWF0IGlmIG5lZWRlZFxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7bnVsbHxzdHJpbmd9IGZvcmNlZE91dHB1dEZvcm1hdCBJZiBzZXQgdG8gc29tZXRoaW5nIGRpZmZlcmVudCB0aGFuIGBudWxsYCwgdGhlbiB0aGlzIGlzIHVzZWQgYXMgYW4gb3ZlcnJpZGluZyBvdXRwdXRGb3JtYXQgb3B0aW9uXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHVuZm9ybWF0TG9jYWxpemVkOiAoZm9yY2VkT3V0cHV0Rm9ybWF0ID0gbnVsbCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0LnVuZm9ybWF0TG9jYWxpemVkKGZvcmNlZE91dHB1dEZvcm1hdCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFVwZGF0ZXMgdGhlIEF1dG9OdW1lcmljIHNldHRpbmdzLCBhbmQgaW1tZWRpYXRlbHkgZm9ybWF0IHRoZSBlbGVtZW50cyBhY2NvcmRpbmdseSwgZm9yIGVhY2ggZWxlbWVudHMgb2YgdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdFxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7b2JqZWN0fSBuZXdPcHRpb25zIFRoaXMgY2FuIGJlIGVpdGhlciBvbmUgb3IgbW9yZSBvcHRpb24gb2JqZWN0c1xuICAgICAgICAgICAgICovXG4gICAgICAgICAgICB1cGRhdGU6ICguLi5uZXdPcHRpb25zKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QudXBkYXRlKC4uLm5ld09wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBSZXR1cm4gYHRydWVgIGlmICphbGwqIHRoZSBhdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRzIGFyZSBwcmlzdGluZSwgaWYgdGhlaXIgcmF3IHZhbHVlIGhhc24ndCBjaGFuZ2VkLlxuICAgICAgICAgICAgICogQnkgZGVmYXVsdCwgdGhpcyByZXR1cm5zIGB0cnVlYCBpZiB0aGUgcmF3IHVuZm9ybWF0dGVkIHZhbHVlIGlzIHN0aWxsIHRoZSBzYW1lIGV2ZW4gaWYgdGhlIGZvcm1hdHRlZCBvbmUgaGFzIGNoYW5nZWQgKGR1ZSB0byBhIGNvbmZpZ3VyYXRpb24gdXBkYXRlIGZvciBpbnN0YW5jZSkuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtib29sZWFufSBjaGVja09ubHlSYXdWYWx1ZSBJZiBzZXQgdG8gYHRydWVgLCB0aGUgcHJpc3RpbmUgdmFsdWUgaXMgZG9uZSBvbiB0aGUgcmF3IHVuZm9ybWF0dGVkIHZhbHVlLCBub3QgdGhlIGZvcm1hdHRlZCBvbmUuIElmIHNldCB0byBgZmFsc2VgLCB0aGlzIGFsc28gY2hlY2tzIHRoYXQgdGhlIGZvcm1hdHRlZCB2YWx1ZSBoYXNuJ3QgY2hhbmdlZC5cbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBpc1ByaXN0aW5lOiAoY2hlY2tPbmx5UmF3VmFsdWUgPSB0cnVlKSA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IGlzUHJpc3RpbmUgPSB0cnVlO1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1ByaXN0aW5lICYmICFhTk9iamVjdC5pc1ByaXN0aW5lKGNoZWNrT25seVJhd1ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaXNQcmlzdGluZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gaXNQcmlzdGluZTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogRXhlY3V0ZSB0aGUgYGNsZWFyKClgIG1ldGhvZCBvbiBlYWNoIEF1dG9OdW1lcmljIG9iamVjdCBpbiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtib29sZWFufSBmb3JjZUNsZWFyQWxsXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGNsZWFyOiAoZm9yY2VDbGVhckFsbCA9IGZhbHNlKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QuY2xlYXIoZm9yY2VDbGVhckFsbCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEV4ZWN1dGUgdGhlIGByZW1vdmUoKWAgbWV0aG9kIG9uIGVhY2ggQXV0b051bWVyaWMgb2JqZWN0IGluIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3RcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgcmVtb3ZlOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QucmVtb3ZlKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEV4ZWN1dGUgdGhlIGB3aXBlKClgIG1ldGhvZCBvbiBlYWNoIEF1dG9OdW1lcmljIG9iamVjdCBpbiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHdpcGU6ICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhTk9iamVjdC53aXBlKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEV4ZWN1dGUgdGhlIGBudWtlKClgIG1ldGhvZCBvbiBlYWNoIEF1dG9OdW1lcmljIG9iamVjdCBpbiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG51a2U6ICgpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhTk9iamVjdC5udWtlKCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGdpdmVuIEF1dG9OdW1lcmljIG9iamVjdCAob3IgRE9NIGVsZW1lbnQpIGlzIGluIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3RcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR8QXV0b051bWVyaWN9IGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0XG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgaGFzOiBkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgICAgICAgICBpZiAoZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3QgaW5zdGFuY2VvZiBBdXRvTnVtZXJpYykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0Lmhhcyhkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdC5ub2RlKCkpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuaGFzKGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBBZGQgYW4gZXhpc3RpbmcgQXV0b051bWVyaWMgb2JqZWN0IChvciBET00gZWxlbWVudCkgdG8gdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdCwgdXNpbmcgdGhlIERPTSBlbGVtZW50IGFzIHRoZSBrZXkuXG4gICAgICAgICAgICAgKiBUaGlzIG1hbmFnZXMgdGhlIGNhc2Ugd2hlcmUgYGFkZE9iamVjdGAgaXMgdXNlZCBvbiBhbiBBdXRvTnVtZXJpYyBvYmplY3QgdGhhdCBhbHJlYWR5IGhhcyBtdWx0aXBsZSBlbGVtZW50cyBpbiBpdHMgbG9jYWwgbGlzdC5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR8QXV0b051bWVyaWN9IGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGFkZE9iamVjdDogZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgIC8vIFN0YXJ0IHdpdGggdGhlIHNhbWUgZGF0YSwgd2hhdGV2ZXIgdGhlIHVzZXIgcGFzc2VkIGFzIGFyZ3VtZW50c1xuICAgICAgICAgICAgICAgIGxldCBkb21FbGVtZW50O1xuICAgICAgICAgICAgICAgIGxldCBvdGhlckF1dG9OdW1lcmljT2JqZWN0O1xuICAgICAgICAgICAgICAgIGlmIChkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdCBpbnN0YW5jZW9mIEF1dG9OdW1lcmljKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdC5ub2RlKCk7XG4gICAgICAgICAgICAgICAgICAgIG90aGVyQXV0b051bWVyaWNPYmplY3QgPSBkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkb21FbGVtZW50ID0gZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3Q7XG4gICAgICAgICAgICAgICAgICAgIG90aGVyQXV0b051bWVyaWNPYmplY3QgPSBBdXRvTnVtZXJpYy5nZXRBdXRvTnVtZXJpY0VsZW1lbnQoZG9tRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGN1cnJlbnQgYXV0b051bWVyaWMgb2JqZWN0IGhhcyBhIGxvY2FsIGxpc3RcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuX2hhc0xvY2FsTGlzdCgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZUxvY2FsTGlzdCgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSBvdGhlciBhdXRvTnVtZXJpYyBvYmplY3QgaGFzIGEgbG9jYWwgbGlzdC4uLlxuICAgICAgICAgICAgICAgIGxldCBvdGhlckFOTG9jYWxMaXN0ID0gb3RoZXJBdXRvTnVtZXJpY09iamVjdC5fZ2V0TG9jYWxMaXN0KCk7XG4gICAgICAgICAgICAgICAgaWYgKG90aGVyQU5Mb2NhbExpc3Quc2l6ZSA9PT0gMCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2UgaWYgdGhlIG90aGVyIEF1dG9OdW1lcmljIG9iamVjdCBoYXMgYW4gZW1wdHkgbG9jYWwgbGlzdCwgdGhlbiBwb3B1bGF0ZSBpdHNlbGYgdG8gaXRcbiAgICAgICAgICAgICAgICAgICAgb3RoZXJBdXRvTnVtZXJpY09iamVjdC5fY3JlYXRlTG9jYWxMaXN0KCk7XG4gICAgICAgICAgICAgICAgICAgIG90aGVyQU5Mb2NhbExpc3QgPSBvdGhlckF1dG9OdW1lcmljT2JqZWN0Ll9nZXRMb2NhbExpc3QoKTsgLy8gVXBkYXRlIHRoZSBvdGhlciBsb2NhbCBsaXN0XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGV0IG1lcmdlZExvY2FsTGlzdHM7XG4gICAgICAgICAgICAgICAgaWYgKG90aGVyQU5Mb2NhbExpc3QgaW5zdGFuY2VvZiBNYXApIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gLi4uSWYgaXQgZG9lcywgbWVyZ2UgdGhlIGxvY2FsIGxpc3RzIHRvZ2V0aGVyXG4gICAgICAgICAgICAgICAgICAgIG1lcmdlZExvY2FsTGlzdHMgPSBBdXRvTnVtZXJpY0hlbHBlci5tZXJnZU1hcHModGhpcy5fZ2V0TG9jYWxMaXN0KCksIG90aGVyQU5Mb2NhbExpc3QpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIC4uLklmIG5vdCwganVzdCBzZXQgdGhlIGN1cnJlbnQgbG9jYWwgbGlzdCBvbnRvIHRoZSBvdGhlciBBdXRvTnVtZXJpYyBvYmplY3RcbiAgICAgICAgICAgICAgICAgICAgLy8gV2UgbmVlZCB0byBzcGVjaWZ5IHRoZSBBdXRvTnVtZXJpYyBvYmplY3QsIG90aGVyd2lzZSB0aGUgYF9hZGRUb0xvY2FsTGlzdGAgZnVuY3Rpb24gd291bGQgbm90IGNvcnJlY3RseSBhZGQgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBzaW5jZSB3ZSB3b3VsZCBub3QgaGF2ZSBhIHJlZmVyZW5jZSB0byBpdCwgYnV0IGEgcmVmZXJlbmNlIHRvIHRoZSBjdXJyZW50IEF1dG9OdW1lcmljIG9iamVjdCBvbiB3aGljaCBpcyBjYWxsZWQgdGhpcyBtZXRob2QuXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2FkZFRvTG9jYWxMaXN0KGRvbUVsZW1lbnQsIG90aGVyQXV0b051bWVyaWNPYmplY3QpO1xuICAgICAgICAgICAgICAgICAgICBtZXJnZWRMb2NhbExpc3RzID0gdGhpcy5fZ2V0TG9jYWxMaXN0KCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSByZXN1bHRpbmcgbGlzdCwgb24gYWxsIHRoZSBvYmplY3RzIG9mIHRoYXQgbG9jYWwgbGlzdCAoc28gdGhhdCB3ZSBjYW4gaW5kaWZmZXJlbnRseSB1c2UgYGluaXQoKWAgb24gYW55IG9iamVjdCBiZWxvbmdpbmcgdG8gdGhhdCBsaXN0KVxuICAgICAgICAgICAgICAgIG1lcmdlZExvY2FsTGlzdHMuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0Ll9zZXRMb2NhbExpc3QobWVyZ2VkTG9jYWxMaXN0cyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFJlbW92ZSB0aGUgZ2l2ZW4gQXV0b051bWVyaWMgb2JqZWN0IChvciBET00gZWxlbWVudCkgZnJvbSB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0LCB1c2luZyB0aGUgRE9NIGVsZW1lbnQgYXMgdGhlIGtleS5cbiAgICAgICAgICAgICAqIElmIHRoaXMgZnVuY3Rpb24gYXR0ZW1wdHMgdG8gcmVtb3ZlIHRoZSBjdXJyZW50IEF1dG9OdW1lcmljIG9iamVjdCBmcm9tIHRoZSBsb2NhbCBsaXN0LCBhIHdhcm5pbmcgaXMgc2hvd24sIGJ1dCB0aGUgZGVsZXRpb24gaXMgc3RpbGwgZG9uZS5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBTcGVjaWFsIGNhc2VzIDpcbiAgICAgICAgICAgICAqIC0gSWYgdGhlIGN1cnJlbnQgb2JqZWN0IHJlbW92ZXMgaXRzZWxmLCB0aGVuIGl0J3MgcmVtb3ZlZCBmcm9tIHRoZSBzaGFyZWQgbG9jYWwgbGlzdCwgdGhlbiBhIG5ldyBlbXB0eSBsb2NhbCBsaXN0IGlzIHVzZWQvY3JlYXRlZFxuICAgICAgICAgICAgICogLSBJZiBhbm90aGVyIG9iamVjdCByZW1vdmUgdGhpcyBvYmplY3QsIHRoZW4gYSBsb2NhbCBsaXN0IHdpdGggb25seSB0aGlzIG9iamVjdCBpcyB1c2VkL2NyZWF0ZWRcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR8QXV0b051bWVyaWN9IGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0XG4gICAgICAgICAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGtlZXBDdXJyZW50QU5PYmplY3QgSWYgc2V0IHRvIGBmYWxzZWAsIHRoZW4gdGhlIGZ1bmN0aW9uIHdpbGwgYWxzbyByZW1vdmUgdGhlIGN1cnJlbnQgQXV0b051bWVyaWMgb2JqZWN0IGlmIGFza2VkLCBvdGhlcndpc2UgaXQgd2lsbCBpZ25vcmUgaXQgYW5kIHByaW50IGEgd2FybmluZyBtZXNzYWdlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHJlbW92ZU9iamVjdDogKGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0LCBrZWVwQ3VycmVudEFOT2JqZWN0ID0gZmFsc2UpID0+IHtcbiAgICAgICAgICAgICAgICAvLyBTdGFydCB3aXRoIHRoZSBzYW1lIGRhdGEsIHdoYXRldmVyIHRoZSB1c2VyIHBhc3NlZCBhcyBhcmd1bWVudHNcbiAgICAgICAgICAgICAgICBsZXQgZG9tRWxlbWVudDtcbiAgICAgICAgICAgICAgICBsZXQgb3RoZXJBdXRvTnVtZXJpY09iamVjdDtcbiAgICAgICAgICAgICAgICBpZiAoZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3QgaW5zdGFuY2VvZiBBdXRvTnVtZXJpYykge1xuICAgICAgICAgICAgICAgICAgICBkb21FbGVtZW50ID0gZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3Qubm9kZSgpO1xuICAgICAgICAgICAgICAgICAgICBvdGhlckF1dG9OdW1lcmljT2JqZWN0ID0gZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3Q7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tRWxlbWVudCA9IGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0O1xuICAgICAgICAgICAgICAgICAgICBvdGhlckF1dG9OdW1lcmljT2JqZWN0ID0gQXV0b051bWVyaWMuZ2V0QXV0b051bWVyaWNFbGVtZW50KGRvbUVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgb3RoZXIgb2JqZWN0IGZyb20gdGhlIGxvY2FsIGxpc3RcbiAgICAgICAgICAgICAgICBjb25zdCBpbml0aWFsQ29tcGxldGVMb2NhbExpc3QgPSB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0O1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZGVsZXRlKGRvbUVsZW1lbnQpO1xuXG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBsb2NhbCBsaXN0IGZvciBhbGwgb2JqZWN0cyBpbiBpdFxuICAgICAgICAgICAgICAgIGluaXRpYWxDb21wbGV0ZUxvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QuX3NldExvY2FsTGlzdCh0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0KTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmICgha2VlcEN1cnJlbnRBTk9iamVjdCAmJiBkb21FbGVtZW50ID09PSB0aGlzLm5vZGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIG9iamVjdCBpcyByZW1vdmVkIGJ5IGl0c2VsZlxuICAgICAgICAgICAgICAgICAgICAvLyBFbXB0eSB0aGUgb2JqZWN0IGxvY2FsIGxpc3RcbiAgICAgICAgICAgICAgICAgICAgb3RoZXJBdXRvTnVtZXJpY09iamVjdC5fc2V0TG9jYWxMaXN0KG5ldyBNYXApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgb2JqZWN0IGlzIHJlbW92ZWQgYnkgYW5vdGhlciBvYmplY3RcbiAgICAgICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBsb2NhbCBsaXN0IGZvciB0aGUgcmVtb3ZlZCBvYmplY3QsIHdpdGggb25seSB0aGlzIG9iamVjdCBpbiBpdFxuICAgICAgICAgICAgICAgICAgICBvdGhlckF1dG9OdW1lcmljT2JqZWN0Ll9jcmVhdGVMb2NhbExpc3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFJlbW92ZSBhbGwgZWxlbWVudHMgZnJvbSB0aGUgc2hhcmVkIGxpc3QsIGVmZmVjdGl2ZWx5IGVtcHR5aW5nIGl0LlxuICAgICAgICAgICAgICogVGhpcyBpcyB0aGUgZXF1aXZhbGVudCBvZiBjYWxsaW5nIGBkZXRhY2goKWAgb24gZWFjaCBvZiBpdHMgZWxlbWVudHMuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtib29sZWFufSBrZWVwRWFjaEFOT2JqZWN0SW5JdHNPd25MaXN0IElmIHNldCB0byBgdHJ1ZWAsIHRoZW4gaW5zdGVhZCBvZiBjb21wbGV0ZWx5IGVtcHR5aW5nIHRoZSBsb2NhbCBsaXN0IG9mIGVhY2ggQXV0b051bWVyaWMgb2JqZWN0cywgZWFjaCBvbmUgb2YgdGhvc2Uga2VlcHMgaXRzZWxmIGluIGl0cyBvd24gbG9jYWwgbGlzdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBlbXB0eTogKGtlZXBFYWNoQU5PYmplY3RJbkl0c093bkxpc3QgPSBmYWxzZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGluaXRpYWxDb21wbGV0ZUxvY2FsTGlzdCA9IHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3Q7XG5cbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGxvY2FsIGxpc3QgZm9yIGFsbCBvYmplY3RzIGluIGl0XG4gICAgICAgICAgICAgICAgaW5pdGlhbENvbXBsZXRlTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2VlcEVhY2hBTk9iamVjdEluSXRzT3duTGlzdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QuX2NyZWF0ZUxvY2FsTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QuX3NldExvY2FsTGlzdChuZXcgTWFwKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBSZXR1cm4gYW4gYXJyYXkgY29udGFpbmluZyBhbGwgdGhlIEF1dG9OdW1lcmljIERPTSBlbGVtZW50cyB0aGF0IGhhdmUgYmVlbiBpbml0aWFsaXplZCBieSBlYWNoIG90aGVyXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5PEhUTUxFbGVtZW50Pn1cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZWxlbWVudHM6ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChhTk9iamVjdC5ub2RlKCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmV0dXJuIHRoZSBgTWFwYCBvYmplY3QgZGlyZWN0bHlcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtNYXB9XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldExpc3Q6ICgpID0+IHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QsXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmV0dXJuIHRoZSBudW1iZXIgb2YgZWxlbWVudCBpbiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzaXplOiAoKSA9PiB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LnNpemUsXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gQ3JlYXRlIHRoZSBmdW5jdGlvbnMgdGhhdCB3aWxsIGFsbG93IHRvIGNoYW5nZSBlYWNoIHNldHRpbmcgb25lIGJ5IG9uZVxuICAgICAgICAvKipcbiAgICAgICAgICogRm9yIGVhY2ggb3B0aW9ucywgd2UgZGVmaW5lIGlmIHdlIG5lZWQgdG8gcmVmb3JtYXQgdGhlIGVsZW1lbnQgY29udGVudCAoZG9lcyBjaGFuZ2luZyB0aGUgb3B0aW9ucyBzaG91bGQgY2hhbmdlIHRoZSB3YXkgaXRzIHZhbHVlIGlzIGRpc3BsYXllZD8pLlxuICAgICAgICAgKiBJZiB5ZXMsIHRoZW4gd2UgdXNlIHRoZSBgdXBkYXRlKClgIGZvciBmb3JjZSBhIHJlZm9ybWF0LCBvdGhlcndpc2UsIHdlIGp1c3QgdXBkYXRlIHRoZSBgc2V0dGluZ3NgIG9iamVjdC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmVzZXQgYW55IG9wdGlvbnMgc2V0IHByZXZpb3VzbHksIGJ5IG92ZXJ3cml0aW5nIHRoZW0gd2l0aCB0aGUgZGVmYXVsdCBzZXR0aW5nc1xuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgcmVzZXQgICAgICAgICAgICAgICAgICAgICAgICA6ICgpID0+IHtcbiAgICAgICAgICAgICAgICAvL1RPRE8gQWRkIGEgYHNldHRpbmdzYCBwYXJhbWV0ZXIgc28gdGhhdCB0aGUgdXNlciBjYW4gcmVzZXQgdG8gYSBzcGVjaWZpYyBzZXQgb2Ygc2V0dGluZ3MuIFRoaXMgaXMgZGlmZmVyZW50IHRoYW4gdXBkYXRlIHNpbmNlIGl0IGRyb3BzIGFueSBub24tZGVmYXVsdCBzZXR0aW5ncyBiZWZvcmUgdXNpbmcgdGhvc2UgbmV3IHNldHRpbmdzLlxuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MgPSB7IHJhd1ZhbHVlIDogdGhpcy5kZWZhdWx0UmF3VmFsdWUgfTsgLy8gSGVyZSB3ZSBwYXNzIHRoZSBkZWZhdWx0IHJhd1ZhbHVlIGluIG9yZGVyIHRvIHByZXZlbnQgc2hvd2luZyBhIHdhcm5pbmcgdGhhdCB3ZSB0cnkgdG8gc2V0IGFuIGB1bmRlZmluZWRgIHZhbHVlXG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoQXV0b051bWVyaWMuZGVmYXVsdFNldHRpbmdzKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGFsbG93RGVjaW1hbFBhZGRpbmcgICAgICAgICAgOiBhbGxvd0RlY2ltYWxQYWRkaW5nID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGFsbG93RGVjaW1hbFBhZGRpbmcgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Gb2N1cyAgICAgICAgIDogY2FyZXRQb3NpdGlvbk9uRm9jdXMgPT4geyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPSBjYXJldFBvc2l0aW9uT25Gb2N1cztcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNyZWF0ZUxvY2FsTGlzdCAgICAgICAgICAgICAgOiBjcmVhdGVMb2NhbExpc3QgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuY3JlYXRlTG9jYWxMaXN0ID0gY3JlYXRlTG9jYWxMaXN0O1xuXG4gICAgICAgICAgICAgICAgLy8gRGVsZXRlIHRoZSBsb2NhbCBsaXN0IHdoZW4gdGhpcyBpcyBzZXQgdG8gYGZhbHNlYCwgY3JlYXRlIGl0IGlmIHRoaXMgaXMgc2V0IHRvIGB0cnVlYCBhbmQgdGhlcmUgaXMgbm90IHByZS1leGlzdGluZyBsaXN0XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3JlYXRlTG9jYWxMaXN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5faGFzTG9jYWxMaXN0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZUxvY2FsTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGVsZXRlTG9jYWxMaXN0KCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY3VycmVuY3lTeW1ib2wgICAgICAgICAgICAgICA6IGN1cnJlbmN5U3ltYm9sID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGN1cnJlbmN5U3ltYm9sIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgICAgICA6IGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50IH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVjaW1hbENoYXJhY3RlciAgICAgICAgICAgICA6IGRlY2ltYWxDaGFyYWN0ZXIgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgZGVjaW1hbENoYXJhY3RlciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSAgOiBkZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlID0gZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBVcGRhdGUgdGhlIGRlY2ltYWwgcGxhY2VzIGdsb2JhbGx5LCB3aGljaCBtZWFucyB0aGlzIG92ZXJyaWRlIGFueSBwcmV2aW91c2x5IHNldCBudW1iZXIgb2YgZGVjaW1hbCBzaG93biBvbiBmb2N1cywgb24gYmx1ciwgb3IgaW4gdGhlIHJhdyB2YWx1ZS5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge2ludH0gZGVjaW1hbFBsYWNlc1xuICAgICAgICAgICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzICAgICAgICAgICAgICAgIDogZGVjaW1hbFBsYWNlcyA9PiB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZygnVXNpbmcgYG9wdGlvbnMuZGVjaW1hbFBsYWNlcygpYCBpbnN0ZWFkIG9mIGNhbGxpbmcgdGhlIHNwZWNpZmljIGBvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSgpYCwgYG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cygpYCBhbmQgYG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyKClgIG1ldGhvZHMgd2lsbCByZXNldCB0aG9zZSBvcHRpb25zLlxcblBsZWFzZSBjYWxsIHRoZSBzcGVjaWZpYyBtZXRob2RzIGlmIHlvdSBkbyBub3Qgd2FudCB0byByZXNldCB0aG9zZS4nLCB0aGlzLnNldHRpbmdzLnNob3dXYXJuaW5ncyk7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBkZWNpbWFsUGxhY2VzIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlICAgICAgICA6IGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9PiB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIgICAgIDogZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgICAgOiBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZWZhdWx0VmFsdWVPdmVycmlkZSAgICAgICAgIDogZGVmYXVsdFZhbHVlT3ZlcnJpZGUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgZGVmYXVsdFZhbHVlT3ZlcnJpZGUgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkaWdpdGFsR3JvdXBTcGFjaW5nICAgICAgICAgIDogZGlnaXRhbEdyb3VwU3BhY2luZyA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBkaWdpdGFsR3JvdXBTcGFjaW5nIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGlnaXRHcm91cFNlcGFyYXRvciAgICAgICAgICA6IGRpZ2l0R3JvdXBTZXBhcmF0b3IgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgZGlnaXRHcm91cFNlcGFyYXRvciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRpdmlzb3JXaGVuVW5mb2N1c2VkICAgICAgICAgOiBkaXZpc29yV2hlblVuZm9jdXNlZCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBkaXZpc29yV2hlblVuZm9jdXNlZCB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVtcHR5SW5wdXRCZWhhdmlvciAgICAgICAgICAgOiBlbXB0eUlucHV0QmVoYXZpb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJhd1ZhbHVlID09PSBudWxsICYmIGVtcHR5SW5wdXRCZWhhdmlvciAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2UgOiBpZiB0aGUgY3VycmVudCBgcmF3VmFsdWVgIGlzIGBudWxsYCBhbmQgdGhlIGBlbXB0eUlucHV0QmVoYXZpb3JgIGlzIGNoYW5nZWQgdG8gc29tZXRoaW5nIGVsc2UgdGhhbiBgJ251bGwnYCwgdGhlbiBpdCBtYWtlcyB0aGF0IGByYXdWYWx1ZWAgaW52YWxpZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gSGVyZSB3ZSBjYW4gZWl0aGVyIHByZXZlbnQgdGhlIG9wdGlvbiB1cGRhdGUgYW5kIHRocm93IGFuIGVycm9yLCBvciBzdGlsbCBhY2NlcHQgdGhlIG9wdGlvbiB1cGRhdGUgYW5kIHVwZGF0ZSB0aGUgdmFsdWUgZnJvbSBgbnVsbGAgdG8gYCcnYC5cbiAgICAgICAgICAgICAgICAgICAgLy8gV2UgY2Fubm90IGtlZXAgYHJhd1ZhbHVlYCB0byBgbnVsbGAgc2luY2UgaWYgYGVtcHR5SW5wdXRCZWhhdmlvcmAgaXMgbm90IHNldCB0byBgbnVsbGAsIGxvdHMgb2YgZnVuY3Rpb24gYXNzdW1lIGByYXdWYWx1ZWAgaXMgYSBzdHJpbmcuXG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFlvdSBhcmUgdHJ5aW5nIHRvIG1vZGlmeSB0aGUgXFxgZW1wdHlJbnB1dEJlaGF2aW9yXFxgIG9wdGlvbiB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gXFxgJ251bGwnXFxgICgke2VtcHR5SW5wdXRCZWhhdmlvcn0pLCBidXQgdGhlIGVsZW1lbnQgcmF3IHZhbHVlIGlzIGN1cnJlbnRseSBzZXQgdG8gXFxgbnVsbFxcYC4gVGhpcyB3b3VsZCByZXN1bHQgaW4gYW4gaW52YWxpZCBcXGByYXdWYWx1ZVxcYC4gSW4gb3JkZXIgdG8gZml4IHRoYXQsIHRoZSBlbGVtZW50IHZhbHVlIGhhcyBiZWVuIGNoYW5nZWQgdG8gdGhlIGVtcHR5IHN0cmluZyBcXGAnJ1xcYC5gLCB0aGlzLnNldHRpbmdzLnNob3dXYXJuaW5ncyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmF3VmFsdWUgPSAnJztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGVtcHR5SW5wdXRCZWhhdmlvciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGV2ZW50QnViYmxlcyAgICAgICAgICAgICAgICAgOiBldmVudEJ1YmJsZXMgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuZXZlbnRCdWJibGVzID0gZXZlbnRCdWJibGVzO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZXZlbnRJc0NhbmNlbGFibGUgICAgICAgICAgICA6IGV2ZW50SXNDYW5jZWxhYmxlID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmV2ZW50SXNDYW5jZWxhYmxlID0gZXZlbnRJc0NhbmNlbGFibGU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmYWlsT25Vbmtub3duT3B0aW9uICAgICAgICAgIDogZmFpbE9uVW5rbm93bk9wdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5mYWlsT25Vbmtub3duT3B0aW9uID0gZmFpbE9uVW5rbm93bk9wdGlvbjsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZvcm1hdE9uUGFnZUxvYWQgICAgICAgICAgICAgOiBmb3JtYXRPblBhZ2VMb2FkID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmZvcm1hdE9uUGFnZUxvYWQgPSBmb3JtYXRPblBhZ2VMb2FkOyAvL0ZJWE1FIHRlc3QgdGhpc1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaGlzdG9yeVNpemUgICAgICAgICAgICAgICAgICA6IGhpc3RvcnlTaXplID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmhpc3RvcnlTaXplID0gaGlzdG9yeVNpemU7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpc0NhbmNlbGxhYmxlICAgICAgICAgICAgICAgIDogaXNDYW5jZWxsYWJsZSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5pc0NhbmNlbGxhYmxlID0gaXNDYW5jZWxsYWJsZTsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGxlYWRpbmdaZXJvICAgICAgICAgICAgICAgICAgOiBsZWFkaW5nWmVybyA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBsZWFkaW5nWmVybyB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG1heGltdW1WYWx1ZSAgICAgICAgICAgICAgICAgOiBtYXhpbXVtVmFsdWUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgbWF4aW11bVZhbHVlIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbWluaW11bVZhbHVlICAgICAgICAgICAgICAgICA6IG1pbmltdW1WYWx1ZSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBtaW5pbXVtVmFsdWUgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBtb2RpZnlWYWx1ZU9uV2hlZWwgICAgICAgICAgIDogbW9kaWZ5VmFsdWVPbldoZWVsID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLm1vZGlmeVZhbHVlT25XaGVlbCA9IG1vZGlmeVZhbHVlT25XaGVlbDsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyICAgOiBuZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBuZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG5lZ2F0aXZlU2lnbkNoYXJhY3RlciAgICAgICAgOiBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgbmVnYXRpdmVTaWduQ2hhcmFjdGVyIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbm9FdmVudExpc3RlbmVycyAgICAgICAgICAgICA6IG5vRXZlbnRMaXN0ZW5lcnMgPT4geyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICAgICAgICAgIGlmIChub0V2ZW50TGlzdGVuZXJzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5vRXZlbnRMaXN0ZW5lcnMubm9FdmVudHMgJiYgdGhpcy5zZXR0aW5ncy5ub0V2ZW50TGlzdGVuZXJzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5vRXZlbnRMaXN0ZW5lcnMuYWRkRXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgZXZlbnRzIG9uY2VcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IG5vRXZlbnRMaXN0ZW5lcnMgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbkludmFsaWRQYXN0ZSAgICAgICAgICAgICAgIDogb25JbnZhbGlkUGFzdGUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Mub25JbnZhbGlkUGFzdGUgPSBvbkludmFsaWRQYXN0ZTsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdCAgICAgICAgICAgICAgICAgOiBvdXRwdXRGb3JtYXQgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Mub3V0cHV0Rm9ybWF0ID0gb3V0cHV0Rm9ybWF0O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3ZlcnJpZGVNaW5NYXhMaW1pdHMgICAgICAgICA6IG92ZXJyaWRlTWluTWF4TGltaXRzID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IG92ZXJyaWRlTWluTWF4TGltaXRzIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcG9zaXRpdmVTaWduQ2hhcmFjdGVyICAgICAgICA6IHBvc2l0aXZlU2lnbkNoYXJhY3RlciA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBwb3NpdGl2ZVNpZ25DaGFyYWN0ZXIgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByYXdWYWx1ZURpdmlzb3IgICAgICAgICAgICAgIDogcmF3VmFsdWVEaXZpc29yID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IHJhd1ZhbHVlRGl2aXNvciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHJlYWRPbmx5ICAgICAgICAgICAgICAgICAgICAgOiByZWFkT25seSA9PiB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5yZWFkT25seSA9IHJlYWRPbmx5O1xuICAgICAgICAgICAgICAgIHRoaXMuX3NldFJlYWRPbmx5KCk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByb3VuZGluZ01ldGhvZCAgICAgICAgICAgICAgIDogcm91bmRpbmdNZXRob2QgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgcm91bmRpbmdNZXRob2QgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlICAgIDogc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBzYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3ltYm9sV2hlblVuZm9jdXNlZCAgICAgICAgICA6IHN5bWJvbFdoZW5VbmZvY3VzZWQgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgc3ltYm9sV2hlblVuZm9jdXNlZCB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNlbGVjdE51bWJlck9ubHkgICAgICAgICAgICAgOiBzZWxlY3ROdW1iZXJPbmx5ID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLnNlbGVjdE51bWJlck9ubHkgPSBzZWxlY3ROdW1iZXJPbmx5OyAvL0ZJWE1FIHRlc3QgdGhpc1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2VsZWN0T25Gb2N1cyAgICAgICAgICAgICAgICA6IHNlbGVjdE9uRm9jdXMgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Muc2VsZWN0T25Gb2N1cyA9IHNlbGVjdE9uRm9jdXM7IC8vRklYTUUgdGVzdCB0aGlzXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZXJpYWxpemVTcGFjZXMgICAgICAgICAgICAgIDogc2VyaWFsaXplU3BhY2VzID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLnNlcmlhbGl6ZVNwYWNlcyA9IHNlcmlhbGl6ZVNwYWNlczsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNob3dPbmx5TnVtYmVyc09uRm9jdXMgICAgICAgOiBzaG93T25seU51bWJlcnNPbkZvY3VzID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IHNob3dPbmx5TnVtYmVyc09uRm9jdXMgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzaG93UG9zaXRpdmVTaWduICAgICAgICAgICAgIDogc2hvd1Bvc2l0aXZlU2lnbiA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBzaG93UG9zaXRpdmVTaWduIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2hvd1dhcm5pbmdzICAgICAgICAgICAgICAgICA6IHNob3dXYXJuaW5ncyA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5zaG93V2FybmluZ3MgPSBzaG93V2FybmluZ3M7IC8vRklYTUUgdGVzdCB0aGlzXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzdHlsZVJ1bGVzICAgICAgICAgICAgICAgICAgIDogc3R5bGVSdWxlcyA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBzdHlsZVJ1bGVzIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3VmZml4VGV4dCAgICAgICAgICAgICAgICAgICA6IHN1ZmZpeFRleHQgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgc3VmZml4VGV4dCB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHVuZm9ybWF0T25Ib3ZlciAgICAgICAgICAgICAgOiB1bmZvcm1hdE9uSG92ZXIgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MudW5mb3JtYXRPbkhvdmVyID0gdW5mb3JtYXRPbkhvdmVyOyAvL0ZJWE1FIHRlc3QgdGhpc1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgdW5mb3JtYXRPblN1Ym1pdCAgICAgICAgICAgICA6IHVuZm9ybWF0T25TdWJtaXQgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MudW5mb3JtYXRPblN1Ym1pdCA9IHVuZm9ybWF0T25TdWJtaXQ7IC8vRklYTUUgdGVzdCB0aGlzXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB2YWx1ZXNUb1N0cmluZ3MgICAgICAgICAgICAgIDogdmFsdWVzVG9TdHJpbmdzID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IHZhbHVlc1RvU3RyaW5ncyB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHdhdGNoRXh0ZXJuYWxDaGFuZ2VzICAgICAgICAgOiB3YXRjaEV4dGVybmFsQ2hhbmdlcyA9PiB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyB3YXRjaEV4dGVybmFsQ2hhbmdlcyB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHdoZWVsT24gICAgICAgICAgICAgICAgICAgICAgOiB3aGVlbE9uID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLndoZWVsT24gPSB3aGVlbE9uOyAvL0ZJWE1FIHRlc3QgdGhpc1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgd2hlZWxTdGVwICAgICAgICAgICAgICAgICAgICA6IHdoZWVsU3RlcCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy53aGVlbFN0ZXAgPSB3aGVlbFN0ZXA7IC8vRklYTUUgdGVzdCB0aGlzXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gT25jZSB0aGUgYXV0b051bWVyaWMgZWxlbWVudCBoYXMgYmVlbiBpbml0aWFsaXplZCwgYnJvYWRjYXN0IHRoYXQgbWVzc2FnZSB3aXRoIGFkZGl0aW9uYWwgaW5mby5cbiAgICAgICAgLy8gTm90ZTogV2hlbiB1c2luZyBgQXV0b051bWVyaWMubXVsdGlwbGUoKWAsIG9uZSBldmVudCBpcyBzZW50ICpwZXIqIGVsZW1lbnQgaW5pdGlhbGl6ZWRcbiAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5pbml0aWFsaXplZCwgdGhpcy5kb21FbGVtZW50LCB7XG4gICAgICAgICAgICBuZXdWYWx1ZSAgIDogQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCksXG4gICAgICAgICAgICBuZXdSYXdWYWx1ZTogdGhpcy5yYXdWYWx1ZSxcbiAgICAgICAgICAgIGVycm9yICAgICAgOiBudWxsLFxuICAgICAgICAgICAgYU5FbGVtZW50ICA6IHRoaXMsXG4gICAgICAgIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgYXV0b051bWVyaWMgdmVyc2lvbiBudW1iZXIgKGZvciBkZWJ1Z2dpbmcgcHVycG9zZSlcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgc3RhdGljIHZlcnNpb24oKSB7XG4gICAgICAgIHJldHVybiAnNC4yLjknO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRha2UgdGhlIHBhcmFtZXRlcnMgZ2l2ZW4gdG8gdGhlIEF1dG9OdW1lcmljIG9iamVjdCwgYW5kIG91dHB1dCB0aGUgdGhyZWUgdmFyaWFibGVzIHRoYXQgYXJlIG5lZWRlZCB0byBmaW5pc2ggaW5pdGlhbGl6aW5nIGl0IDpcbiAgICAgKiAtIGRvbUVsZW1lbnQgOiBUaGUgdGFyZ2V0IERPTSBlbGVtZW50XG4gICAgICogLSBpbml0aWFsVmFsdWUgOiBUaGUgaW5pdGlhbCB2YWx1ZSwgb3IgYG51bGxgIGlmIG5vbmUgaXMgZ2l2ZW5cbiAgICAgKiAtIHVzZXJPcHRpb25zIDogVGhlIG9wdGlvbiBvYmplY3RcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fEFycmF5fG51bWJlcnxzdHJpbmd9IGFyZzFcbiAgICAgKiBAcGFyYW0ge29iamVjdHxBcnJheXxudW1iZXJ8c3RyaW5nfG51bGx9IGFyZzJcbiAgICAgKiBAcGFyYW0ge29iamVjdHxBcnJheXxudW1iZXJ8c3RyaW5nfG51bGx9IGFyZzNcbiAgICAgKiBAcmV0dXJucyB7e2RvbUVsZW1lbnQ6ICosIGluaXRpYWxWYWx1ZTogKiwgdXNlck9wdGlvbnM6ICp9fVxuICAgICAqIEB0aHJvd3NcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2V0QXJndW1lbnRzVmFsdWVzKGFyZzEsIGFyZzIsIGFyZzMpIHtcbiAgICAgICAgLy8gQmFzaWMgY2hlY2sgb24gdGhlIGFyZ3VtZW50IGNvdW50XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoYXJnMSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoJ0F0IGxlYXN0IG9uZSB2YWxpZCBwYXJhbWV0ZXIgaXMgbmVlZGVkIGluIG9yZGVyIHRvIGluaXRpYWxpemUgYW4gQXV0b051bWVyaWMgb2JqZWN0Jyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcmVwYXJlIHRoZSBhcmd1bWVudHMgaW4gb3JkZXIgdG8gY3JlYXRlIHRoZSBBdXRvTnVtZXJpYyBvYmplY3Qgd2l0aCB0aGUgcmlnaHQgdmFsdWVzXG4gICAgICAgIC8vIFRlc3QgdGhlIGFyZ3VtZW50IHR5cGVzXG4gICAgICAgIGNvbnN0IGlzQXJnMUVsZW1lbnQgPSBBdXRvTnVtZXJpY0hlbHBlci5pc0VsZW1lbnQoYXJnMSk7XG4gICAgICAgIGNvbnN0IGlzQXJnMVN0cmluZyA9IEF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKGFyZzEpO1xuXG4gICAgICAgIGNvbnN0IGlzQXJnMk9iamVjdCA9IEF1dG9OdW1lcmljSGVscGVyLmlzT2JqZWN0KGFyZzIpO1xuICAgICAgICBjb25zdCBpc0FyZzJBcnJheSA9IEFycmF5LmlzQXJyYXkoYXJnMikgJiYgYXJnMi5sZW5ndGggPiAwO1xuICAgICAgICBjb25zdCBpc0FyZzJOdW1iZXIgPSBBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlck9yQXJhYmljKGFyZzIpIHx8IGFyZzIgPT09ICcnO1xuICAgICAgICBjb25zdCBpc0FyZzJQcmVEZWZpbmVkT3B0aW9uTmFtZSA9IHRoaXMuX2lzUHJlRGVmaW5lZE9wdGlvblZhbGlkKGFyZzIpO1xuICAgICAgICBjb25zdCBpc0FyZzJOdWxsID0gQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGFyZzIpO1xuICAgICAgICBjb25zdCBpc0FyZzJFbXB0eVN0cmluZyA9IEF1dG9OdW1lcmljSGVscGVyLmlzRW1wdHlTdHJpbmcoYXJnMik7XG5cbiAgICAgICAgY29uc3QgaXNBcmczT2JqZWN0ID0gQXV0b051bWVyaWNIZWxwZXIuaXNPYmplY3QoYXJnMyk7XG4gICAgICAgIGNvbnN0IGlzQXJnM0FycmF5ID0gQXJyYXkuaXNBcnJheShhcmczKSAmJiBhcmczLmxlbmd0aCA+IDA7XG4gICAgICAgIGNvbnN0IGlzQXJnM051bGwgPSBBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoYXJnMyk7XG4gICAgICAgIGNvbnN0IGlzQXJnM1ByZURlZmluZWRPcHRpb25OYW1lID0gdGhpcy5faXNQcmVEZWZpbmVkT3B0aW9uVmFsaWQoYXJnMyk7XG5cbiAgICAgICAgLy8gR2l2ZW4gdGhlIHBhcmFtZXRlcnMgcGFzc2VkLCBzb3J0IHRoZSBkYXRhIGFuZCByZXR1cm4gYSBzdGFibGUgc3RhdGUgYmVmb3JlIHRoZSBpbml0aWFsaXphdGlvblxuICAgICAgICBsZXQgZG9tRWxlbWVudDtcbiAgICAgICAgbGV0IHVzZXJPcHRpb25zO1xuICAgICAgICBsZXQgaW5pdGlhbFZhbHVlO1xuXG4gICAgICAgIC8vVE9ETyBTaW1wbGlmeSB0aG9zZSB0ZXN0cyAtLT5cbiAgICAgICAgaWYgKGlzQXJnMUVsZW1lbnQgJiYgaXNBcmcyTnVsbCAmJiBpc0FyZzNOdWxsKSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCk7IC8vIFdpdGggdGhlIGRlZmF1bHQgb3B0aW9uc1xuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGFyZzE7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSBudWxsO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMUVsZW1lbnQgJiYgaXNBcmcyTnVtYmVyICYmIGlzQXJnM051bGwpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAxMjM0NS43ODkpOyAvLyBXaXRoIHRoZSBkZWZhdWx0IG9wdGlvbnMsIGFuZCBhbiBpbml0aWFsIHZhbHVlXG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgJzEyMzQ1Ljc4OScpO1xuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGFyZzE7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBhcmcyO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSBudWxsO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMUVsZW1lbnQgJiYgaXNBcmcyT2JqZWN0ICYmIGlzQXJnM051bGwpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCB7IG9wdGlvbnMgfSk7IC8vIFdpdGggb25lIG9wdGlvbiBvYmplY3RcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBhcmcxO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gYXJnMjtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFFbGVtZW50ICYmIGlzQXJnMlByZURlZmluZWRPcHRpb25OYW1lICYmIGlzQXJnM051bGwpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAnZXVyb1BvcycpOyAvLyBXaXRoIG9uZSBwcmUtZGVmaW5lZCBvcHRpb24gbmFtZVxuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGFyZzE7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSB0aGlzLl9nZXRPcHRpb25PYmplY3QoYXJnMik7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxRWxlbWVudCAmJiBpc0FyZzJBcnJheSAmJiBpc0FyZzNOdWxsKSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgW3sgb3B0aW9uczEgfSwgeyBvcHRpb25zMiB9XSk7IC8vIFdpdGggbXVsdGlwbGUgb3B0aW9uIG9iamVjdHMgKHRoZSBsYXRlc3Qgb3B0aW9uIG92ZXJ3cml0aW5nIHRoZSBwcmV2aW91cyBvbmVzKVxuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGFyZzE7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSB0aGlzLm1lcmdlT3B0aW9ucyhhcmcyKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFFbGVtZW50ICYmIChpc0FyZzJOdWxsIHx8IGlzQXJnMkVtcHR5U3RyaW5nKSAmJiBpc0FyZzNPYmplY3QpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCBudWxsLCB7IG9wdGlvbnMgfSk7IC8vIFdpdGggb25lIG9wdGlvbiBvYmplY3RcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBhcmcxO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gYXJnMztcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFFbGVtZW50ICYmIChpc0FyZzJOdWxsIHx8IGlzQXJnMkVtcHR5U3RyaW5nKSAmJiBpc0FyZzNBcnJheSkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIG51bGwsIFt7IG9wdGlvbnMxIH0sIHsgb3B0aW9uczIgfV0pOyAvLyBXaXRoIG11bHRpcGxlIG9wdGlvbiBvYmplY3RzXG4gICAgICAgICAgICBkb21FbGVtZW50ID0gYXJnMTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IHRoaXMubWVyZ2VPcHRpb25zKGFyZzMpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMVN0cmluZyAmJiBpc0FyZzJOdWxsICYmIGlzQXJnM051bGwpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcpO1xuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYXJnMSk7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSBudWxsO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMVN0cmluZyAmJiBpc0FyZzJPYmplY3QgJiYgaXNBcmczTnVsbCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgeyBvcHRpb25zIH0pO1xuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYXJnMSk7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSBhcmcyO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMVN0cmluZyAmJiBpc0FyZzJQcmVEZWZpbmVkT3B0aW9uTmFtZSAmJiBpc0FyZzNOdWxsKSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAnZXVyb1BvcycpO1xuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYXJnMSk7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSB0aGlzLl9nZXRPcHRpb25PYmplY3QoYXJnMik7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIGlzQXJnMkFycmF5ICYmIGlzQXJnM051bGwpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIFt7IG9wdGlvbnMxIH0sIHsgb3B0aW9uczIgfV0pOyAvLyBXaXRoIG11bHRpcGxlIG9wdGlvbiBvYmplY3RzXG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IHRoaXMubWVyZ2VPcHRpb25zKGFyZzIpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMVN0cmluZyAmJiAoaXNBcmcyTnVsbCB8fCBpc0FyZzJFbXB0eVN0cmluZykgJiYgaXNBcmczT2JqZWN0KSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCBudWxsLCB7IG9wdGlvbnMgfSk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IGFyZzM7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIChpc0FyZzJOdWxsIHx8IGlzQXJnMkVtcHR5U3RyaW5nKSAmJiBpc0FyZzNBcnJheSkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgbnVsbCwgW3sgb3B0aW9uczEgfSwgeyBvcHRpb25zMiB9XSk7IC8vIFdpdGggbXVsdGlwbGUgb3B0aW9uIG9iamVjdHNcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGFyZzEpO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gdGhpcy5tZXJnZU9wdGlvbnMoYXJnMyk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIGlzQXJnMk51bWJlciAmJiBpc0FyZzNOdWxsKSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAxMjM0NS43ODkpO1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgJzEyMzQ1Ljc4OScpO1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgJycpO1xuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYXJnMSk7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBhcmcyO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSBudWxsO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMVN0cmluZyAmJiBpc0FyZzJOdW1iZXIgJiYgaXNBcmczT2JqZWN0KSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAxMjM0NS43ODksIHsgb3B0aW9ucyB9KTtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsICcxMjM0NS43ODknLCB7IG9wdGlvbnMgfSk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAnJywgeyBvcHRpb25zIH0pO1xuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYXJnMSk7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBhcmcyO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSBhcmczO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMVN0cmluZyAmJiBpc0FyZzJOdW1iZXIgJiYgaXNBcmczUHJlRGVmaW5lZE9wdGlvbk5hbWUpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIDEyMzQ1Ljc4OSwgJ2V1cm9Qb3MnKTtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsICcxMjM0NS43ODknLCAnZXVyb1BvcycpO1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgJycsICdldXJvUG9zJyk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGFyZzI7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IHRoaXMuX2dldE9wdGlvbk9iamVjdChhcmczKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFFbGVtZW50ICYmIGlzQXJnMk51bWJlciAmJiBpc0FyZzNPYmplY3QpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAxMjM0NS43ODksIHsgb3B0aW9ucyB9KTtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAnMTIzNDUuNzg5JywgeyBvcHRpb25zIH0pO1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsICcnLCB7IG9wdGlvbnMgfSk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gYXJnMTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGFyZzI7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IGFyZzM7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxRWxlbWVudCAmJiBpc0FyZzJOdW1iZXIgJiYgaXNBcmczUHJlRGVmaW5lZE9wdGlvbk5hbWUpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAxMjM0NS43ODksICdldXJvUG9zJyk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgJzEyMzQ1Ljc4OScsICdldXJvUG9zJyk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgJycsICdldXJvUG9zJyk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gYXJnMTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGFyZzI7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IHRoaXMuX2dldE9wdGlvbk9iamVjdChhcmczKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFFbGVtZW50ICYmIGlzQXJnMk51bWJlciAmJiBpc0FyZzNBcnJheSkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIDEyMzQ1Ljc4OSwgW3sgb3B0aW9uczEgfSwgeyBvcHRpb25zMiB9XSk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgJzEyMzQ1Ljc4OScsIFt7IG9wdGlvbnMxIH0sIHsgb3B0aW9uczIgfV0pO1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsICcnLCBbeyBvcHRpb25zMSB9LCB7IG9wdGlvbnMyIH1dKTtcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBhcmcxO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gYXJnMjtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gdGhpcy5tZXJnZU9wdGlvbnMoYXJnMyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgcGFyYW1ldGVycyBnaXZlbiB0byB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGFyZSBub3QgdmFsaWQsICcke2FyZzF9JywgJyR7YXJnMn0nIGFuZCAnJHthcmczfScgZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGRvbUVsZW1lbnQpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgc2VsZWN0b3IgJyR7YXJnMX0nIGRpZCBub3Qgc2VsZWN0IGFueSB2YWxpZCBET00gZWxlbWVudC4gUGxlYXNlIGNoZWNrIG9uIHdoaWNoIGVsZW1lbnQgeW91IGNhbGxlZCBBdXRvTnVtZXJpYy5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IGRvbUVsZW1lbnQsIGluaXRpYWxWYWx1ZSwgdXNlck9wdGlvbnMgfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXJnZSB0aGUgb3B0aW9uIG9iamVjdHMgZm91bmQgaW4gdGhlIGdpdmVuIGFycmF5IGBvcHRpb25zQXJyYXlgLlxuICAgICAqIElmIGEgYHN0cmluZ2AgaXMgZm91bmQsIHRoZW4gd2UgdHJ5IHRvIGdldCB0aGUgcmVsYXRlZCBwcmUtZGVmaW5lZCBvcHRpb24gdXNpbmcgdGhhdCBzdHJpbmcgYXMgaXRzIG5hbWUuXG4gICAgICogV2hlbiBtZXJnaW5nIHRoZSBvcHRpb25zLCB0aGUgbGF0ZXN0IG9wdGlvbiBvdmVyd3JpdGUgYW55IHByZXZpb3VzbHkgc2V0LiBUaGlzIGFsbG93cyB0byBmaW5lIHR1bmUgYSBwcmUtZGVmaW5lZCBvcHRpb24gZm9yIGluc3RhbmNlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheTxvYmplY3R8c3RyaW5nPn0gb3B0aW9uc0FycmF5XG4gICAgICogQHJldHVybnMge3t9fVxuICAgICAqL1xuICAgIHN0YXRpYyBtZXJnZU9wdGlvbnMob3B0aW9uc0FycmF5KSB7XG4gICAgICAgIC8vIFRoaXMgYWxsb3dzIHRoZSB1c2VyIHRvIHVzZSBtdWx0aXBsZSBvcHRpb25zIChzdHJpbmdzIG9yIG9iamVjdHMpIGluIGFuIGFycmF5LCBhbmQgb3ZlcndyaXRlIHRoZSBwcmV2aW91cyBvbmUgd2l0aCB0aGUgbmV4dCBvcHRpb24gZWxlbWVudCA7IHRoaXMgaXMgdXNlZnVsIHRvIHR1bmUgdGhlIHdhbnRlZCBmb3JtYXRcbiAgICAgICAgY29uc3QgbWVyZ2VkT3B0aW9ucyA9IHt9O1xuICAgICAgICBvcHRpb25zQXJyYXkuZm9yRWFjaChvcHRpb25PYmplY3RPclByZWRlZmluZWRPcHRpb25TdHJpbmcgPT4ge1xuICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihtZXJnZWRPcHRpb25zLCB0aGlzLl9nZXRPcHRpb25PYmplY3Qob3B0aW9uT2JqZWN0T3JQcmVkZWZpbmVkT3B0aW9uU3RyaW5nKSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiBtZXJnZWRPcHRpb25zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGdpdmVuIHByZS1kZWZpbmVkIG9wdGlvbiBuYW1lIGlzIGFuIGF0dHJpYnV0ZSBvZiB0aGUgYEF1dG9OdW1lcmljLnByZWRlZmluZWRPcHRpb25zYCBvYmplY3RcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBwcmVEZWZpbmVkT3B0aW9uTmFtZVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9pc1ByZURlZmluZWRPcHRpb25WYWxpZChwcmVEZWZpbmVkT3B0aW9uTmFtZSkge1xuICAgICAgICByZXR1cm4gQXV0b051bWVyaWMucHJlZGVmaW5lZE9wdGlvbnMuaGFzT3duUHJvcGVydHkocHJlRGVmaW5lZE9wdGlvbk5hbWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhbiBvcHRpb24gb2JqZWN0IGJhc2VkIG9uIHRoZSBnaXZlbiBwYXJhbWV0ZXIuXG4gICAgICogSWYgYG9wdGlvbk9iamVjdE9yUHJlZGVmaW5lZE5hbWVgIGlzIGFzIHN0cmluZywgdGhlbiB3ZSByZXRyaWV2ZSB0aGUgcHJlLWRlZmluZWQgb3B0aW9uIG9iamVjdCwgaWYgaXQncyBhbiBvYmplY3QsIHdlIHVzZSBpdCBhcyBpcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fHN0cmluZ30gb3B0aW9uT2JqZWN0T3JQcmVkZWZpbmVkTmFtZVxuICAgICAqIEByZXR1cm5zIHtvYmplY3R9XG4gICAgICovXG4gICAgc3RhdGljIF9nZXRPcHRpb25PYmplY3Qob3B0aW9uT2JqZWN0T3JQcmVkZWZpbmVkTmFtZSkge1xuICAgICAgICBsZXQgb3B0aW9ucztcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKG9wdGlvbk9iamVjdE9yUHJlZGVmaW5lZE5hbWUpKSB7XG4gICAgICAgICAgICBvcHRpb25zID0gQXV0b051bWVyaWMuZ2V0UHJlZGVmaW5lZE9wdGlvbnMoKVtvcHRpb25PYmplY3RPclByZWRlZmluZWROYW1lXTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zID09PSB2b2lkKDApIHx8IG9wdGlvbnMgPT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgZ2l2ZW4gcHJlLWRlZmluZWQgbmFtZSBkb2VzIG5vdCBleGlzdCwgd2FybiB0aGF0IHNvbWV0aGluZyBpcyB3cm9uZywgYW5kIGNvbnRpbnVlIHRoZSBleGVjdXRpb24gb2YgdGhlIGluaXRpYWxpemF0aW9uXG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgVGhlIGdpdmVuIHByZS1kZWZpbmVkIG9wdGlvbiBbJHtvcHRpb25PYmplY3RPclByZWRlZmluZWROYW1lfV0gaXMgbm90IHJlY29nbml6ZWQgYnkgYXV0b051bWVyaWMuIFBsZWFzZSBjaGVjayB0aGF0IHByZS1kZWZpbmVkIG9wdGlvbiBuYW1lLmAsIHRydWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgeyAvLyBBIGBzZXR0aW5nc2Agb2JqZWN0XG4gICAgICAgICAgICBvcHRpb25zID0gb3B0aW9uT2JqZWN0T3JQcmVkZWZpbmVkTmFtZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvcHRpb25zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNhdmUgdGhlIGluaXRpYWwgZWxlbWVudCB2YWx1ZXMgZm9yIGxhdGVyIHVzZSBpbiB0aGUgcHJpc3RpbmUgdGVzdC5cbiAgICAgKiBUaG9zZSB2YWx1ZXMgYXJlIDpcbiAgICAgKiAtIHRoZSBodG1sIGF0dHJpYnV0ZSAoaWUuIDxpbnB1dCB2YWx1ZT0nNDInPiksIGFuZFxuICAgICAqIC0gdGhlIHNjcmlwdCBgdmFsdWVgIChpZS4gYGxldCBkb21FbGVtZW50LnZhbHVlYClcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVsbHxudW1iZXJ8c3RyaW5nfSBpbml0aWFsVmFsdWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zYXZlSW5pdGlhbFZhbHVlcyhpbml0aWFsVmFsdWUpIHtcbiAgICAgICAgLy8gS2VlcCB0aGUgdmVyeSBmaXJzdCBpbml0aWFsIHZhbHVlcyAoaW4gdGhlIGh0bWwgYXR0cmlidXRlIGFuZCBzZXQgYnkgdGhlIHNjcmlwdCkuIFRoaXMgaXMgbmVlZGVkIHRvIGNoZWNrIGlmIHRoZSBlbGVtZW50IGlzIHByaXN0aW5lLlxuICAgICAgICAvLyBTYXZlIHRoZSBodG1sIGF0dHJpYnV0ZSAndmFsdWUnXG4gICAgICAgIHRoaXMuaW5pdGlhbFZhbHVlSHRtbEF0dHJpYnV0ZSA9IEF1dG9OdW1lcmljSGVscGVyLnNjaWVudGlmaWNUb0RlY2ltYWwodGhpcy5kb21FbGVtZW50LmdldEF0dHJpYnV0ZSgndmFsdWUnKSk7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodGhpcy5pbml0aWFsVmFsdWVIdG1sQXR0cmlidXRlKSkge1xuICAgICAgICAgICAgLy8gU2V0IHRoZSBkZWZhdWx0IGVtcHR5IHZhbHVlIGF0dHJpYnV0ZSBpbnN0ZWFkIG9mIGBudWxsYCwgc2luY2UgaWYgdGhlIGluaXRpYWwgdmFsdWUgaXMgbnVsbCwgdGhlIGVtcHR5IHN0cmluZyBpcyB1c2VkXG4gICAgICAgICAgICB0aGlzLmluaXRpYWxWYWx1ZUh0bWxBdHRyaWJ1dGUgPSAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNhdmUgdGhlICdzY3JpcHQnIHZhbHVlXG4gICAgICAgIHRoaXMuaW5pdGlhbFZhbHVlID0gaW5pdGlhbFZhbHVlO1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHRoaXMuaW5pdGlhbFZhbHVlKSkge1xuICAgICAgICAgICAgLy8gU2FtZSBhcyBhYm92ZVxuICAgICAgICAgICAgdGhpcy5pbml0aWFsVmFsdWUgPSAnJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGFsbCB0aGUgZXZlbnQgbGlzdGVuZXJzIGZvciB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9jcmVhdGVFdmVudExpc3RlbmVycygpIHtcbiAgICAgICAgLy8gQ3JlYXRlIHJlZmVyZW5jZXMgdG8gdGhlIGV2ZW50IGhhbmRsZXIgZnVuY3Rpb25zLCBzbyB3ZSBjYW4gdGhlbiBjbGVhbmx5IHJlbW92ZXMgdGhvc2UgbGlzdGVuZXJzIGlmIG5lZWRlZFxuICAgICAgICAvLyBUaGF0IHdvdWxkIG5vdCBiZSBwb3NzaWJsZSBpZiB3ZSB1c2VkIGNsb3N1cmVzIGRpcmVjdGx5IGluIHRoZSBldmVudCBoYW5kbGVyIGRlY2xhcmF0aW9uc1xuICAgICAgICB0aGlzLl9vbkZvY3VzSW5GdW5jID0gZSA9PiB7IHRoaXMuX29uRm9jdXNJbihlKTsgfTtcbiAgICAgICAgdGhpcy5fb25Gb2N1c0luQW5kTW91c2VFbnRlckZ1bmMgPSBlID0+IHsgdGhpcy5fb25Gb2N1c0luQW5kTW91c2VFbnRlcihlKTsgfTtcbiAgICAgICAgdGhpcy5fb25Gb2N1c0Z1bmMgPSAoKSA9PiB7IHRoaXMuX29uRm9jdXMoKTsgfTtcbiAgICAgICAgdGhpcy5fb25LZXlkb3duRnVuYyA9IGUgPT4geyB0aGlzLl9vbktleWRvd24oZSk7IH07XG4gICAgICAgIHRoaXMuX29uS2V5cHJlc3NGdW5jID0gZSA9PiB7IHRoaXMuX29uS2V5cHJlc3MoZSk7IH07XG4gICAgICAgIHRoaXMuX29uS2V5dXBGdW5jID0gZSA9PiB7IHRoaXMuX29uS2V5dXAoZSk7IH07XG4gICAgICAgIHRoaXMuX29uRm9jdXNPdXRBbmRNb3VzZUxlYXZlRnVuYyA9IGUgPT4geyB0aGlzLl9vbkZvY3VzT3V0QW5kTW91c2VMZWF2ZShlKTsgfTtcbiAgICAgICAgdGhpcy5fb25QYXN0ZUZ1bmMgPSBlID0+IHsgdGhpcy5fb25QYXN0ZShlKTsgfTtcbiAgICAgICAgdGhpcy5fb25XaGVlbEZ1bmMgPSBlID0+IHsgdGhpcy5fb25XaGVlbChlKTsgfTtcbiAgICAgICAgdGhpcy5fb25Ecm9wRnVuYyA9IGUgPT4geyB0aGlzLl9vbkRyb3AoZSk7IH07XG4gICAgICAgIHRoaXMuX29uS2V5ZG93bkdsb2JhbEZ1bmMgPSBlID0+IHsgdGhpcy5fb25LZXlkb3duR2xvYmFsKGUpOyB9O1xuICAgICAgICB0aGlzLl9vbktleXVwR2xvYmFsRnVuYyA9IGUgPT4geyB0aGlzLl9vbktleXVwR2xvYmFsKGUpOyB9O1xuXG4gICAgICAgIC8vIEFkZCB0aGUgZXZlbnQgbGlzdGVuZXJzXG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdmb2N1c2luJywgdGhpcy5fb25Gb2N1c0luRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLl9vbkZvY3VzSW5BbmRNb3VzZUVudGVyRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLl9vbkZvY3VzRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VlbnRlcicsIHRoaXMuX29uRm9jdXNJbkFuZE1vdXNlRW50ZXJGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5fb25LZXlkb3duRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5cHJlc3MnLCB0aGlzLl9vbktleXByZXNzRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5dXAnLCB0aGlzLl9vbktleXVwRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignYmx1cicsIHRoaXMuX29uRm9jdXNPdXRBbmRNb3VzZUxlYXZlRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VsZWF2ZScsIHRoaXMuX29uRm9jdXNPdXRBbmRNb3VzZUxlYXZlRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncGFzdGUnLCB0aGlzLl9vblBhc3RlRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignd2hlZWwnLCB0aGlzLl9vbldoZWVsRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZHJvcCcsIHRoaXMuX29uRHJvcEZ1bmMsIGZhbHNlKTtcbiAgICAgICAgdGhpcy5fc2V0dXBGb3JtTGlzdGVuZXIoKTtcblxuICAgICAgICAvLyBDcmVhdGUgb25lIGdsb2JhbCBldmVudCBsaXN0ZW5lciBmb3IgdGhlIGtleXVwIGV2ZW50IG9uIHRoZSBkb2N1bWVudCBvYmplY3QsIHdoaWNoIHdpbGwgYmUgc2hhcmVkIGJ5IGFsbCB0aGUgYXV0b051bWVyaWMgZWxlbWVudHNcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpYy5fZG9lc0dsb2JhbExpc3RFeGlzdHMoKSkge1xuICAgICAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5ZG93bicsIHRoaXMuX29uS2V5ZG93bkdsb2JhbEZ1bmMsIGZhbHNlKTtcbiAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2tleXVwJywgdGhpcy5fb25LZXl1cEdsb2JhbEZ1bmMsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSBhbGwgdGhlIGF1dG9OdW1lcmljLXJlbGF0ZWQgZXZlbnQgbGlzdGVuZXJzIGZvciB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9yZW1vdmVFdmVudExpc3RlbmVycygpIHtcbiAgICAgICAgdGhpcy5kb21FbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2ZvY3VzaW4nLCB0aGlzLl9vbkZvY3VzSW5GdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuX29uRm9jdXNJbkFuZE1vdXNlRW50ZXJGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1cycsIHRoaXMuX29uRm9jdXNGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWVudGVyJywgdGhpcy5fb25Gb2N1c0luQW5kTW91c2VFbnRlckZ1bmMsIGZhbHNlKTtcbiAgICAgICAgdGhpcy5kb21FbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2JsdXInLCB0aGlzLl9vbkZvY3VzT3V0QW5kTW91c2VMZWF2ZUZ1bmMsIGZhbHNlKTtcbiAgICAgICAgdGhpcy5kb21FbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ21vdXNlbGVhdmUnLCB0aGlzLl9vbkZvY3VzT3V0QW5kTW91c2VMZWF2ZUZ1bmMsIGZhbHNlKTtcbiAgICAgICAgdGhpcy5kb21FbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLl9vbktleWRvd25GdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXlwcmVzcycsIHRoaXMuX29uS2V5cHJlc3NGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXl1cCcsIHRoaXMuX29uS2V5dXBGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdwYXN0ZScsIHRoaXMuX29uUGFzdGVGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCd3aGVlbCcsIHRoaXMuX29uV2hlZWxGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdkcm9wJywgdGhpcy5fb25Ecm9wRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLl9yZW1vdmVGb3JtTGlzdGVuZXIoKTtcblxuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5fb25LZXlkb3duR2xvYmFsRnVuYywgZmFsc2UpO1xuICAgICAgICBkb2N1bWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXl1cCcsIHRoaXMuX29uS2V5dXBHbG9iYWxGdW5jLCBmYWxzZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWFyayB0aGUgcGFyZW50IDxmb3JtPiBzbyB0aGF0IG90aGVyIEF1dG9OdW1lcmljIG9iamVjdCB3aWxsIG5vdCBhZGQgbW9yZSBsaXN0ZW5lcnMuXG4gICAgICogQWRkIGEgY291bnRlciBzbyB0aGF0IHdoZW4gcmVtb3ZpbmcgdGhlIEF1dG9OdW1lcmljIG9iamVjdCwgd2Ugb25seSByZW1vdmUgdGhlIHN1Ym1pdCBsaXN0ZW5lciBpZiB0aGF0IGNvdW50IGlzIGVxdWFsIHRvIDAuXG4gICAgICogQWxzbyBrZWVwIGEgcmVmZXJlbmNlIHRvIHRoZSAnc3VibWl0JyBldmVudCBoYW5kbGVyIGZ1bmN0aW9uIHRvIGJlIGFibGUgdG8gcmVtb3ZlIHRoYXQgaGFuZGxlciBsYXRlciBpZiB0aGUgYF9yZW1vdmVGb3JtTGlzdGVuZXIoKWAgZnVuY3Rpb24gaXMgY2FsbGVkIGZyb20gYW5vdGhlciBBdXRvTnVtZXJpYyBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zZXR1cEZvcm1MaXN0ZW5lcigpIHtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodGhpcy5wYXJlbnRGb3JtKSkge1xuICAgICAgICAgICAgLy8gU2V0dXAgdGhlIGhhbmRsZXIgZnVuY3Rpb25cbiAgICAgICAgICAgIHRoaXMuX29uRm9ybVN1Ym1pdEZ1bmMgPSAoKSA9PiB7IHRoaXMuX29uRm9ybVN1Ym1pdCgpOyB9O1xuXG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgcGFyZW50IGZvcm0gYWxyZWFkeSBoYXMgdGhlIEF1dG9OdW1lcmljIG1hcmtcbiAgICAgICAgICAgIGlmICh0aGlzLl9oYXNQYXJlbnRGb3JtQ291bnRlcigpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5faW5jcmVtZW50UGFyZW50Rm9ybUNvdW50ZXIoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgbm90LCBhZGQgdGhlIGNvdW50ZXJcbiAgICAgICAgICAgICAgICB0aGlzLl9pbml0aWFsaXplRm9ybUNvdW50ZXJUb09uZSgpO1xuICAgICAgICAgICAgICAgIC8vIEFuZCBhZGQgdGhlIHN1Ym1pdCBldmVudCBsaXN0ZW5lclxuICAgICAgICAgICAgICAgIHRoaXMucGFyZW50Rm9ybS5hZGRFdmVudExpc3RlbmVyKCdzdWJtaXQnLCB0aGlzLl9vbkZvcm1TdWJtaXRGdW5jLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgLy8gQWxzbyBrZWVwIGEgcmVmZXJlbmNlIHRvIHRoZSBoYW5kbGVyIGZ1bmN0aW9uIHNvIHRoYXQgd2UgY2FuIHJlbW92ZSBpdCBsYXRlclxuICAgICAgICAgICAgICAgIHRoaXMuX3N0b3JlRm9ybUhhbmRsZXJGdW5jdGlvbigpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBmb3JtICdzdWJtaXQnIGV2ZW50IGxpc3RlbmVyLCBhcyB3ZWxsIGFzIHRoZSBgZGF0YXNldGAgaW5mbyAoYGFuQ291bnRgIGFuZCBgYW5Gb3JtSGFuZGxlcmApIGZyb20gdGhlIHBhcmVudCBmb3JtLCBvbmx5IHdoZW4gdGhlcmUgYXJlIG9ubHkgb25lIEF1dG9OdW1lcmljIGNoaWxkIGVsZW1lbnQgbGVmdCBpbiB0aGF0IDxmb3JtPi5cbiAgICAgKiBPdGhlcndpc2UgZGVjcmVtZW50IHRoZSBgYW5Db3VudGAuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9yZW1vdmVGb3JtTGlzdGVuZXIoKSB7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHRoaXMucGFyZW50Rm9ybSkpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIHRoZSBwYXJlbnQgZm9ybSBjb3VudGVyIHZhbHVlXG4gICAgICAgICAgICBjb25zdCBhbkNvdW50ID0gdGhpcy5fZ2V0UGFyZW50Rm9ybUNvdW50ZXIoKTtcblxuICAgICAgICAgICAgaWYgKGFuQ291bnQgPT09IDEpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiBpdCdzIDEsIHJlbW92ZSB0aGUgbGlzdGVuZXJcbiAgICAgICAgICAgICAgICB0aGlzLnBhcmVudEZvcm0ucmVtb3ZlRXZlbnRMaXN0ZW5lcignc3VibWl0JywgdGhpcy5fZ2V0Rm9ybUhhbmRsZXJGdW5jdGlvbigpLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgLy8gQWxzbyByZW1vdmUgdGhlIGRhdGFzZXQgaW5mb1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZUZvcm1EYXRhU2V0SW5mbygpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChhbkNvdW50ID4gMSkge1xuICAgICAgICAgICAgICAgIC8vIE90aGVyd2lzZSBpZiBpdCdzID4xIGRlY3JlbWVudCB0aGUgY291bnRlclxuICAgICAgICAgICAgICAgIHRoaXMuX2RlY3JlbWVudFBhcmVudEZvcm1Db3VudGVyKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIElmIGl0J3MgPDEsIHRocm93IGFuIGVycm9yXG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIEF1dG9OdW1lcmljIG9iamVjdCBjb3VudCBvbiB0aGUgZm9ybSBpcyBpbmNvaGVyZW50LmApO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyZW50IGZvcm0gaGFzIHRoZSBmb3JtIGNvdW50ZXIgYXR0cmlidXRlXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9oYXNQYXJlbnRGb3JtQ291bnRlcigpIHtcbiAgICAgICAgcmV0dXJuICdhbkNvdW50JyBpbiB0aGlzLnBhcmVudEZvcm0uZGF0YXNldDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIGNvdW50IG9mIEF1dG9OdW1lcmljIGZvcm0gY2hpbGRyZW5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0UGFyZW50Rm9ybUNvdW50ZXIoKSB7XG4gICAgICAgIHJldHVybiBOdW1iZXIodGhpcy5wYXJlbnRGb3JtLmRhdGFzZXQuYW5Db3VudCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBjb3VudCBvZiBBdXRvTnVtZXJpYyBmb3JtIGNoaWxkcmVuIHRvIDEgZm9yIHRoZSBnaXZlbiBmb3JtIGVsZW1lbnQsIG9yIGlmIG5vbmUgYXJlIHBhc3NlZCwgdGhlIGN1cnJlbnQgYHRoaXMucGFyZW50Rm9ybWAgb25lLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRm9ybUVsZW1lbnR8bnVsbH0gZm9ybUVsZW1lbnRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9pbml0aWFsaXplRm9ybUNvdW50ZXJUb09uZShmb3JtRWxlbWVudCA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5fZ2V0Rm9ybUVsZW1lbnQoZm9ybUVsZW1lbnQpLmRhdGFzZXQuYW5Db3VudCA9IDE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSW5jcmVtZW50IHRoZSBBdXRvTnVtZXJpYyBmb3JtIGNoaWxkcmVuIGNvdW50IGZvciB0aGUgZ2l2ZW4gZm9ybSBlbGVtZW50LCBvciBpZiBub25lIGFyZSBwYXNzZWQsIHRoZSBjdXJyZW50IGB0aGlzLnBhcmVudEZvcm1gIG9uZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fG51bGx9IGZvcm1FbGVtZW50XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfaW5jcmVtZW50UGFyZW50Rm9ybUNvdW50ZXIoZm9ybUVsZW1lbnQgPSBudWxsKSB7XG4gICAgICAgIHRoaXMuX2dldEZvcm1FbGVtZW50KGZvcm1FbGVtZW50KS5kYXRhc2V0LmFuQ291bnQrKztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZWNyZW1lbnQgdGhlIEF1dG9OdW1lcmljIGZvcm0gY2hpbGRyZW4gY291bnQgZm9yIHRoZSBjdXJyZW50IGB0aGlzLnBhcmVudEZvcm1gIGZvcm0gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2RlY3JlbWVudFBhcmVudEZvcm1Db3VudGVyKCkge1xuICAgICAgICB0aGlzLnBhcmVudEZvcm0uZGF0YXNldC5hbkNvdW50LS07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2xvYmFsIGZvcm0gaGFuZGxlciBsaXN0IGV4aXN0cyBvbiB0aGUgYHdpbmRvd2Agb2JqZWN0LlxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2RvZXNGb3JtSGFuZGxlckxpc3RFeGlzdHMoKSB7XG4gICAgICAgIGNvbnN0IHR5cGUgPSB0eXBlb2Ygd2luZG93LmFORm9ybUhhbmRsZXJNYXA7XG5cbiAgICAgICAgcmV0dXJuIHR5cGUgIT09ICd1bmRlZmluZWQnICYmIHR5cGUgPT09ICdvYmplY3QnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSB0aGUgZ2xvYmFsIGZvcm0gaGFuZGxlciBsaXN0IG9uIHRoZSBgd2luZG93YCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfY3JlYXRlRm9ybUhhbmRsZXJMaXN0KCkge1xuICAgICAgICB3aW5kb3cuYU5Gb3JtSGFuZGxlck1hcCA9IG5ldyBNYXAoKTsgLy8gSSB3b3VsZCBoYXZlIHVzZWQgYSBgV2Vha01hcGAgaGVyZSwgYnV0IHRoYXQgZG9lcyBub3QgYWxsb3cgdXNpbmcgbm9uLW9iamVjdCBmb3Iga2V5c1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGdpdmVuIGZvcm0gZWxlbWVudCwgb3IgaWYgbm9uZSBhcmUgcGFzc2VkLCB0aGUgY3VycmVudCBgdGhpcy5wYXJlbnRGb3JtYCBvbmUgaGFzIGEgZm9ybSBoYW5kbGVyIG5hbWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxGb3JtRWxlbWVudHxudWxsfSBmb3JtRWxlbWVudFxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2hhc0Zvcm1IYW5kbGVyRnVuY3Rpb24oZm9ybUVsZW1lbnQgPSBudWxsKSB7XG4gICAgICAgIHJldHVybiAnYW5Gb3JtSGFuZGxlcicgaW4gdGhpcy5fZ2V0Rm9ybUVsZW1lbnQoZm9ybUVsZW1lbnQpLmRhdGFzZXQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBnaXZlbiBmb3JtIGVsZW1lbnQsIG9yIGRlZmF1bHRzIHRvIGB0aGlzLnBhcmVudEZvcm1gIGlmIG5vIGFyZ3VtZW50IGlzIHBhc3NlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fG51bGx9IGZvcm1FbGVtZW50XG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0Rm9ybUVsZW1lbnQoZm9ybUVsZW1lbnQgPSBudWxsKSB7XG4gICAgICAgIGxldCBmb3JtRWxlbWVudFRvVXNlO1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChmb3JtRWxlbWVudCkpIHtcbiAgICAgICAgICAgIGZvcm1FbGVtZW50VG9Vc2UgPSBmb3JtRWxlbWVudDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvcm1FbGVtZW50VG9Vc2UgPSB0aGlzLnBhcmVudEZvcm07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZm9ybUVsZW1lbnRUb1VzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIGZvcm0gaGFuZGxlciB1bmlxdWUgbmFtZSBhbmQgc3RvcmUgaXQgaW4gdGhlIGdsb2JhbCBmb3JtIGhhbmRsZXIgbGlzdC5cbiAgICAgKiBUaGlzIGFsc28gc2F2ZSB0aGF0IG5hbWUgaW4gdGhlIGRhdGFzZXQgb2YgdGhlIGdpdmVuIGZvcm0gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fG51bGx9IGZvcm1FbGVtZW50XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc3RvcmVGb3JtSGFuZGxlckZ1bmN0aW9uKGZvcm1FbGVtZW50ID0gbnVsbCkge1xuICAgICAgICAvLyBDcmVhdGUgdGhlIHdlYWtNYXAgaWYgaXQgZG9lcyBub3QgZXhpc3RcbiAgICAgICAgaWYgKCF0aGlzLmNvbnN0cnVjdG9yLl9kb2VzRm9ybUhhbmRsZXJMaXN0RXhpc3RzKCkpIHtcbiAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IuX2NyZWF0ZUZvcm1IYW5kbGVyTGlzdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgYSB1bmlxdWUgbmFtZSBhbmQgc2F2ZSBpdCBpbiB0aGUgZm9ybSBkYXRhc2V0XG4gICAgICAgIGNvbnN0IGZvcm1IYW5kbGVyTmFtZSA9IEF1dG9OdW1lcmljSGVscGVyLnJhbmRvbVN0cmluZygpO1xuICAgICAgICB0aGlzLl9nZXRGb3JtRWxlbWVudChmb3JtRWxlbWVudCkuZGF0YXNldC5hbkZvcm1IYW5kbGVyID0gZm9ybUhhbmRsZXJOYW1lO1xuXG4gICAgICAgIC8vIEFkZCB0aGUgZm9ybSBoYW5kbGVyIG5hbWUgYW5kIGhhbmRsZSBmdW5jdGlvbiByZWZlcmVuY2UgdG8gdGhlIFdlYWtNYXBcbiAgICAgICAgd2luZG93LmFORm9ybUhhbmRsZXJNYXAuc2V0KGZvcm1IYW5kbGVyTmFtZSwgdGhpcy5fb25Gb3JtU3VibWl0RnVuYyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBmb3JtIGhhbmRsZXIga2V5IG5hbWUgZnJvbSB0aGUgcGFyZW50IGZvcm0gZWxlbWVudCwgZm9yIHRoZSBnbG9iYWwgZm9ybSBoYW5kbGVyIGxpc3QuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfCp9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0Rm9ybUhhbmRsZXJLZXkoKSB7XG4gICAgICAgIGlmICghdGhpcy5faGFzRm9ybUhhbmRsZXJGdW5jdGlvbigpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBVbmFibGUgdG8gcmV0cmlldmUgdGhlIGZvcm0gaGFuZGxlciBuYW1lYCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBmb3JtSGFuZGxlck5hbWUgPSB0aGlzLnBhcmVudEZvcm0uZGF0YXNldC5hbkZvcm1IYW5kbGVyO1xuICAgICAgICBpZiAoZm9ybUhhbmRsZXJOYW1lID09PSAnJykge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGZvcm0gaGFuZGxlciBuYW1lIGlzIGludmFsaWRgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmb3JtSGFuZGxlck5hbWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSAnc3VibWl0JyBldmVudCBoYW5kbGVyIGZ1bmN0aW9uIHVzZWQgZm9yIHRoZSBwYXJlbnQgZm9ybS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtmdW5jdGlvbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9nZXRGb3JtSGFuZGxlckZ1bmN0aW9uKCkge1xuICAgICAgICBjb25zdCBmb3JtSGFuZGxlck5hbWUgPSB0aGlzLl9nZXRGb3JtSGFuZGxlcktleSgpO1xuXG4gICAgICAgIHJldHVybiB3aW5kb3cuYU5Gb3JtSGFuZGxlck1hcC5nZXQoZm9ybUhhbmRsZXJOYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIGRhdGFzZXQgYXR0cmlidXRlcyBgZGF0YS1hbi1jb3VudGAgYW5kIGBkYXRhLWFuLWZvcm0taGFuZGxlcmAgZnJvbSB0aGUgcGFyZW50IGZvcm0gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3JlbW92ZUZvcm1EYXRhU2V0SW5mbygpIHtcbiAgICAgICAgLy8gSnVzdCBpbiBjYXNlLCBzZXQgdGhlIGNvdW50ZXIgdG8gMFxuICAgICAgICB0aGlzLl9kZWNyZW1lbnRQYXJlbnRGb3JtQ291bnRlcigpO1xuICAgICAgICAvLyBSZW1vdmUgdGhlIGZvcm0gaGFuZGxlciBmdW5jdGlvbiBmcm9tIHRoZSBGb3JtSGFuZGxlckZ1bmN0aW9uIE1hcFxuICAgICAgICB3aW5kb3cuYU5Gb3JtSGFuZGxlck1hcC5kZWxldGUodGhpcy5fZ2V0Rm9ybUhhbmRsZXJLZXkoKSk7XG4gICAgICAgIC8vIExhc3RseSwgcmVtb3ZlIHRoZSBkYXRhc2V0IGF0dHJpYnV0ZXNcbiAgICAgICAgdGhpcy5wYXJlbnRGb3JtLnJlbW92ZUF0dHJpYnV0ZSgnZGF0YS1hbi1jb3VudCcpO1xuICAgICAgICB0aGlzLnBhcmVudEZvcm0ucmVtb3ZlQXR0cmlidXRlKCdkYXRhLWFuLWZvcm0taGFuZGxlcicpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZWxlbWVudCBhdHRyaWJ1dGUgJ3JlYWRvbmx5JyBhY2NvcmRpbmcgdG8gdGhlIGN1cnJlbnQgc2V0dGluZ3MuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zZXRSZWFkT25seSgpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNJbnB1dEVsZW1lbnQgJiYgdGhpcy5zZXR0aW5ncy5yZWFkT25seSkge1xuICAgICAgICAgICAgdGhpcy5kb21FbGVtZW50LnJlYWRPbmx5ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCBhIHdhdGNoZXIgc28gdGhhdCBhbnkgZXh0ZXJuYWwgY2hhbmdlIHRvIHRoZSBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnQgd291bGQgYmUgZGV0ZWN0ZWQuXG4gICAgICogQXMgc29vbiBhcyBzdWNoIGNoYW5nZSBpcyBkZXRlY3RlZCwgQXV0b051bWVyaWMgdGhlbiB0cmllcyB0byBgc2V0KClgIHRoZSB2YWx1ZSBzbyB0aGF0IGl0IGdldHMgZm9ybWF0dGVkIGFuZCBzdG9yZWQgaW4gdGhlIGhpc3RvcnkuXG4gICAgICogLy9YWFggRm9yIG5vdywgdGhpcyBvbmx5IHdvcmtzIHdoZW4gd2F0Y2hpbmcgdGhlIGB2YWx1ZWAgYXR0cmlidXRlLCBub3QgdGhlIGB0ZXh0Q29udGVudGAgb25lXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfYWRkV2F0Y2hlcigpIHtcbiAgICAgICAgLy8gYGdldHRlclNldHRlcmAgY2FuIGJlIHVuZGVmaW5lZCB3aGVuIGEgbm9uLWlucHV0IGVsZW1lbnQgaXMgdXNlZFxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHRoaXMuZ2V0dGVyU2V0dGVyKSkge1xuICAgICAgICAgICAgY29uc3QgeyBzZXQ6IHNldHRlciwgZ2V0OiBnZXR0ZXIgfSA9IHRoaXMuZ2V0dGVyU2V0dGVyO1xuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMuZG9tRWxlbWVudCwgdGhpcy5hdHRyaWJ1dGVUb1dhdGNoLCB7XG4gICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLCAvLyBUaGlzIGlzIG5lZWRlZCBpbiBzb21lIHJhcmUgY2FzZXNcbiAgICAgICAgICAgICAgICBnZXQgICAgICAgICA6ICgpID0+IGdldHRlci5jYWxsKHRoaXMuZG9tRWxlbWVudCksXG4gICAgICAgICAgICAgICAgc2V0ICAgICAgICAgOiB2YWwgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzZXR0ZXIuY2FsbCh0aGlzLmRvbUVsZW1lbnQsIHZhbCk7XG4gICAgICAgICAgICAgICAgICAgIC8vIE9ubHkgYHNldCgpYCB0aGUgdmFsdWUgaWYgdGhlIG1vZGlmaWNhdGlvbiBjb21lcyBmcm9tIGFuIGV4dGVybmFsIHNvdXJjZVxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy53YXRjaEV4dGVybmFsQ2hhbmdlcyAmJiAhdGhpcy5pbnRlcm5hbE1vZGlmaWNhdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXQodmFsKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vRklYTUUgVGhlIGNvZGUgYWJvdmUgZmFpbHMgZm9yIHRoZSBgdGV4dENvbnRlbnRgIGF0dHJpYnV0ZSBzaW5jZSBgdGhpcy5nZXR0ZXJTZXR0ZXJgIGlzIHVuZGVmaW5lZCB3aGVuIHVzaW5nIGBnZXRPd25Qcm9wZXJ0eURlc2NyaXB0b3IoKWBcbiAgICAgICAgLyogLy9YWFggVGhlIGNvZGUgYmVsb3cgKmFsbW9zdCogd29yayBmb3IgdGhlIHRleHRDb250ZW50LCBidXQgYnJlYWtzIHNvbWUgdW5pdCB0ZXN0c1xuICAgICAgICB0aGlzLnZhbHVlV2F0Y2hlZCA9IHRoaXMuZG9tRWxlbWVudFt0aGlzLmF0dHJpYnV0ZVRvV2F0Y2hdO1xuICAgICAgICBPYmplY3QuZGVmaW5lUHJvcGVydHkodGhpcy5kb21FbGVtZW50LCB0aGlzLmF0dHJpYnV0ZVRvV2F0Y2gsIHtcbiAgICAgICAgICAgIGNvbmZpZ3VyYWJsZTogdHJ1ZSwgLy8gVGhpcyBpcyBuZWVkZWQgaW4gc29tZSByYXJlIGNhc2VzXG4gICAgICAgICAgICBnZXQgICAgICAgICA6ICgpID0+IHRoaXMudmFsdWVXYXRjaGVkLFxuICAgICAgICAgICAgc2V0ICAgICAgICAgOiB2YWwgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudmFsdWVXYXRjaGVkID0gdmFsO1xuICAgICAgICAgICAgICAgIC8vIE9ubHkgYHNldCgpYCB0aGUgdmFsdWUgaWYgdGhlIG1vZGlmaWNhdGlvbiBjb21lcyBmcm9tIGFuIGV4dGVybmFsIHNvdXJjZVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLndhdGNoRXh0ZXJuYWxDaGFuZ2VzICYmICF0aGlzLmludGVybmFsTW9kaWZpY2F0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0KHZhbCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgICAgICovXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSB3YXRjaGVyIG9uIHRoZSBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRcbiAgICAgKiBOb3RlOiBUaGlzIG5lZWRzIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBBdXRvTnVtZXJpYyBlbGVtZW50IGlzICdyZW1vdmVkJywgb3RoZXJ3aXNlIHRoZSBnZXR0ZXIvc2V0dGVyIHN0YXlzIG9uIHRoZSBET00gZWxlbWVudCBhbmQgdGhhdCBjYW4gbGVhZCB0byBwcm9ibGVtIGlmIHRoZSB1c2VyIGluaXRpYWxpemUgYW5vdGhlciBBdXRvTnVtZXJpYyBvYmplY3Qgb24gaXQuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfcmVtb3ZlV2F0Y2hlcigpIHtcbiAgICAgICAgLy8gYGdldHRlclNldHRlcmAgY2FuIGJlIHVuZGVmaW5lZCB3aGVuIGEgbm9uLWlucHV0IGVsZW1lbnQgaXMgdXNlZFxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHRoaXMuZ2V0dGVyU2V0dGVyKSkge1xuICAgICAgICAgICAgY29uc3QgeyBzZXQ6IHNldHRlciwgZ2V0OiBnZXR0ZXIgfSA9IHRoaXMuZ2V0dGVyU2V0dGVyO1xuICAgICAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHRoaXMuZG9tRWxlbWVudCwgdGhpcy5hdHRyaWJ1dGVUb1dhdGNoLCB7XG4gICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLCAvLyBUaGlzIGlzIG5lZWRlZCBpbiBzb21lIHJhcmUgY2FzZXNcbiAgICAgICAgICAgICAgICBnZXQgICAgICAgICA6ICgpID0+IGdldHRlci5jYWxsKHRoaXMuZG9tRWxlbWVudCksXG4gICAgICAgICAgICAgICAgc2V0ICAgICAgICAgOiB2YWwgPT4ge1xuICAgICAgICAgICAgICAgICAgICBzZXR0ZXIuY2FsbCh0aGlzLmRvbUVsZW1lbnQsIHZhbCk7XG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9GSVhNRSBUaGUgY29kZSBhYm92ZSBmYWlscyBmb3IgdGhlIGB0ZXh0Q29udGVudGAgYXR0cmlidXRlIHNpbmNlIGB0aGlzLmdldHRlclNldHRlcmAgaXMgdW5kZWZpbmVkIHdoZW4gdXNpbmcgYGdldE93blByb3BlcnR5RGVzY3JpcHRvcigpYFxuICAgICAgICAvKiAvL1hYWCBUaGUgY29kZSBiZWxvdyAqYWxtb3N0KiB3b3JrIGZvciB0aGUgdGV4dENvbnRlbnQsIGJ1dCBicmVha3Mgc29tZSB1bml0IHRlc3RzXG4gICAgICAgIHRoaXMudmFsdWVXYXRjaGVkID0gdGhpcy5kb21FbGVtZW50W3RoaXMuYXR0cmlidXRlVG9XYXRjaF07XG4gICAgICAgIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0aGlzLmRvbUVsZW1lbnQsIHRoaXMuYXR0cmlidXRlVG9XYXRjaCwge1xuICAgICAgICAgICAgY29uZmlndXJhYmxlOiB0cnVlLCAvLyBUaGlzIGlzIG5lZWRlZCBpbiBzb21lIHJhcmUgY2FzZXNcbiAgICAgICAgICAgIGdldCAgICAgICAgIDogKCkgPT4gdGhpcy52YWx1ZVdhdGNoZWQsXG4gICAgICAgICAgICBzZXQgICAgICAgICA6IHZhbCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZVdhdGNoZWQgPSB2YWw7XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgKi9cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIG5hbWUgb2YgdGhlIG9iamVjdCBhdHRyaWJ1dGUgdGhhdCBzdG9yZSB0aGUgY3VycmVudCBmb3JtYXR0ZWQgZGF0YSBpbiB0aGUgRE9NIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2dldEF0dHJpYnV0ZVRvV2F0Y2goKSB7XG4gICAgICAgIGxldCBhdHRyaWJ1dGVUb1dhdGNoO1xuICAgICAgICBpZiAodGhpcy5pc0lucHV0RWxlbWVudCkge1xuICAgICAgICAgICAgYXR0cmlidXRlVG9XYXRjaCA9ICd2YWx1ZSc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBub2RlVHlwZSA9IHRoaXMuZG9tRWxlbWVudC5ub2RlVHlwZTtcbiAgICAgICAgICAgIGlmIChub2RlVHlwZSA9PT0gTm9kZS5FTEVNRU5UX05PREUgfHxcbiAgICAgICAgICAgICAgICBub2RlVHlwZSA9PT0gTm9kZS5ET0NVTUVOVF9OT0RFIHx8XG4gICAgICAgICAgICAgICAgbm9kZVR5cGUgPT09IE5vZGUuRE9DVU1FTlRfRlJBR01FTlRfTk9ERSkge1xuICAgICAgICAgICAgICAgIGF0dHJpYnV0ZVRvV2F0Y2ggPSAndGV4dENvbnRlbnQnO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHtcbiAgICAgICAgICAgICAgICBhdHRyaWJ1dGVUb1dhdGNoID0gJ25vZGVWYWx1ZSc7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYXR0cmlidXRlVG9XYXRjaDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTYXZlIHRoZSBjdXJyZW50IHJhdyB2YWx1ZSBpbnRvIHRoZSBoaXN0b3J5IHRhYmxlLCBhbG9uZyB3aXRoIHRoZSBzZWxlY3Rpb24gaW5mb3JtYXRpb24uXG4gICAgICpcbiAgICAgKiBJZiB0aGUgdXNlciBoYXMgZG9uZSBzb21lIHVuZG9zIGFuZCB0cmllcyB0byBlbnRlcjpcbiAgICAgKiAtIGEgbmV3IGFuZCBkaWZmZXJlbnQgbnVtYmVyIHRoYW4gdGhlICduZXh0JyBzdGF0ZSwgdGhpcyBkcm9wcyB0aGUgcmVzdCBvZiB0aGUgaGlzdG9yeSB0YWJsZVxuICAgICAqIC0gdGhlIHZlcnkgc2FtZSBudW1iZXIgdGhhdCByZXN1bHQgaW4gdGhlIHNhbWUgcmF3VmFsdWUgdGhhbiB0aGUgJ25leHQnIHN0YXRlLCB3ZSBvbmx5IG1vdmUgdGhlIGhpc3RvcnkgdGFibGUgcG9pbnRlciB0byB0aGUgbmV4dCBzdGF0ZVxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfaGlzdG9yeVRhYmxlQWRkKCkge1xuICAgICAgICAvL1RPRE8gQWRkIGEgYHRoaXMuc2V0dGluZ3Muc2F2ZVNlbGVjdGlvbnNJbnRvSGlzdG9yeWAgb3B0aW9uIHRvIHByZXZlbnQgc2F2aW5nIHRoZSBzZWxlY3Rpb25zIChpbiBvcmRlciB0byBnYWluIHBlcmZvcm1hbmNlKVxuICAgICAgICBjb25zdCBpc0VtcHR5SGlzdG9yeVRhYmxlID0gdGhpcy5oaXN0b3J5VGFibGUubGVuZ3RoID09PSAwO1xuICAgICAgICAvLyBPbmx5IGFkZCBhIG5ldyB2YWx1ZSBpZiBpdCdzIGRpZmZlcmVudCB0aGFuIHRoZSBwcmV2aW91cyBvbmUgKHRvIHByZXZlbnQgaW5maW5pdGVseSBhZGRpbmcgdmFsdWVzIG9uIG1vdXNlb3ZlciBmb3IgaW5zdGFuY2UpXG4gICAgICAgIGlmIChpc0VtcHR5SGlzdG9yeVRhYmxlIHx8IHRoaXMucmF3VmFsdWUgIT09IHRoaXMuX2hpc3RvcnlUYWJsZUN1cnJlbnRWYWx1ZVVzZWQoKSkge1xuICAgICAgICAgICAgLy8gVHJpbSB0aGUgaGlzdG9yeSB0YWJsZSBpZiB0aGUgdXNlciBjaGFuZ2VkIHRoZSB2YWx1ZSBvZiBhbiBpbnRlcm1lZGlhcnkgc3RhdGVcbiAgICAgICAgICAgIGxldCBhZGROZXdIaXN0b3J5U3RhdGUgPSB0cnVlO1xuICAgICAgICAgICAgaWYgKCFpc0VtcHR5SGlzdG9yeVRhYmxlKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgc29tZSB1bmRvIGhhcyBiZWVuIGRvbmUgYW5kIHRoZSB1c2VyIHR5cGUgdGhlIGV4YWN0IHNhbWUgZGF0YSB0aGFuIHRoZSBuZXh0IGVudHJ5IGFmdGVyIHRoZSBjdXJyZW50IGhpc3RvcnkgcG9pbnRlciwgZG8gbm8gZHJvcCB0aGUgcmVzdCBvZiB0aGUgJ3JlZG8nIGxpc3QsIGFuZCBqdXN0IGFkdmFuY2UgdGhlIGhpc3RvcnlUYWJsZUluZGV4XG4gICAgICAgICAgICAgICAgY29uc3QgbmV4dEhpc3RvcnlTdGF0ZUluZGV4ID0gdGhpcy5oaXN0b3J5VGFibGVJbmRleCArIDE7XG4gICAgICAgICAgICAgICAgaWYgKG5leHRIaXN0b3J5U3RhdGVJbmRleCA8IHRoaXMuaGlzdG9yeVRhYmxlLmxlbmd0aCAmJiB0aGlzLnJhd1ZhbHVlID09PSB0aGlzLmhpc3RvcnlUYWJsZVtuZXh0SGlzdG9yeVN0YXRlSW5kZXhdLnZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBjaGFyYWN0ZXIgaW5wdXQgcmVzdWx0IGluIHRoZSBzYW1lIHN0YXRlIHRoYW4gdGhlIG5leHQgb25lLCBkbyBub3QgcmVtb3ZlIHRoZSBuZXh0IGhpc3Rvcnkgc3RhdGVzIG5vciBhZGQgYSBuZXcgb25lXG4gICAgICAgICAgICAgICAgICAgIGFkZE5ld0hpc3RvcnlTdGF0ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEZpcnN0IHJlbW92ZSBhbnl0aGluZyB0aGF0IGlzIGFmdGVyIHRoZSBjdXJyZW50IGluZGV4XG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmFycmF5VHJpbSh0aGlzLmhpc3RvcnlUYWJsZSwgdGhpcy5oaXN0b3J5VGFibGVJbmRleCArIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBoaXN0b3J5IHBvaW50ZXJcbiAgICAgICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlSW5kZXgrKztcblxuICAgICAgICAgICAgLy8gQWRkIHRoZSBuZXcgaGlzdG9yeSBzdGF0ZSwgaWYgbmVlZGVkXG4gICAgICAgICAgICBpZiAoYWRkTmV3SGlzdG9yeVN0YXRlKSB7XG4gICAgICAgICAgICAgICAgLy8gU2F2ZSB0aGUgc2VsZWN0aW9uIGluZm9cbiAgICAgICAgICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50U2VsZWN0aW9uKHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25TdGFydCA9IHNlbGVjdGlvbi5zdGFydDtcbiAgICAgICAgICAgICAgICB0aGlzLnNlbGVjdGlvbkVuZCA9IHNlbGVjdGlvbi5lbmQ7XG5cbiAgICAgICAgICAgICAgICAvLyBUaGVuIGFkZCB0aGUgbmV3IHJhdyB2YWx1ZVxuICAgICAgICAgICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlLnB1c2goe1xuICAgICAgICAgICAgICAgICAgICAvLyBTYXZlIHRoZSByYXdWYWx1ZSBhbmQgc2VsZWN0aW9uIHN0YXJ0L2VuZFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZTogdGhpcy5yYXdWYWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlIHNlbGVjdGlvbiBmb3IgdGhpcyBlbGVtZW50IGlzIHRlbXBvcmFyeSwgYW5kIHdpbGwgYmUgdXBkYXRlZCB3aGVuIHRoZSBuZXh0IGhpc3Rvcnkgc3RhdGUgd2lsbCBiZSByZWNvcmRlZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhhdCB3YXksIHdlIGFyZSBhbHdheXMgc3VyZSB3ZSBzYXZlIHRoZSBsYXN0IGNhcmV0IG9yIHNlbGVjdGlvbiBwb3NpdGlvbnMganVzdCBiZWZvcmUgdGhlIHZhbHVlIGlzIGNoYW5nZWQuIE90aGVyd2lzZSB3ZSB3b3VsZCBvbmx5IHNhdmUgdGhvc2UgcG9zaXRpb25zIHdoZW4gdGhlIHZhbHVlIGlzIGZpcnN0IGNoYW5nZWQsIGFuZCB3b3VsZCBub3QgdGFrZSBpbnRvIGFjY291bnQgdGhhdCB0aGUgdXNlciBjb3VsZCBtb3ZlIHRoZSBjYXJldCBhcm91bmQgYWZ0ZXJ3YXJkLlxuICAgICAgICAgICAgICAgICAgICAvLyBGb3IgaW5zdGFuY2UsIHRoaXMgaXMgbmVlZGVkIGlmIHRoZSB1c2VyIGNoYW5nZSB0aGUgZWxlbWVudCB2YWx1ZSwgYW5kIGltbWVkaWF0ZWx5IHVuZG8gaXQgOyBpZiBoZSB0aGVuIGRvZXMgYSByZWRvLCBoZSdsbCBzZWUgdGhlIHZhbHVlIGFuZCB0aGUgcmlnaHQgc2VsZWN0aW9uXG4gICAgICAgICAgICAgICAgICAgIC8vIFRvIHN1bSB1cDsgVGhlIHNlbGVjdGlvbiBwb3NpdGlvbiBhcmUgbm90IGFsd2F5cyArMSBjaGFyYWN0ZXIsIHNpbmNlIGl0IGNvdWxkIGFsc28gYmUgJzInIGlmIGEgZ3JvdXAgc2VwYXJhdG9yIGlzIGFkZGVkIHdoZW4gZW50ZXJpbmcgb25lIGNoYXJhY3Rlci4gVGhhdCdzIHdoeSB0aGUgY3VycmVudCBoaXN0b3J5IHN0YXRlIGNhcmV0L3NlbGVjdGlvbiBwb3NpdGlvbiBpcyB1cGRhdGVkIG9uIGVhY2ggYGtleXVwYCBldmVudC5cbiAgICAgICAgICAgICAgICAgICAgc3RhcnQ6IHRoaXMuc2VsZWN0aW9uU3RhcnQgKyAxLCAvLyBIZXJlIHdlIGFkZCBvbmUgc2luY2UgdGhlIHVzZXIgYWRkZWQgb25lIGNoYXJhY3RlciB0b29cbiAgICAgICAgICAgICAgICAgICAgZW5kICA6IHRoaXMuc2VsZWN0aW9uRW5kICsgMSxcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgc2VsZWN0aW9uIGluIHRoZSBwcmV2aW91cyBlbnRyeSwgaW4gb3JkZXIgdG8ga2VlcCB0cmFjayBvZiB0aGUgdXBkYXRlZCBjYXJldC9zZWxlY3Rpb24gcG9zaXRpb25zXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaGlzdG9yeVRhYmxlLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oaXN0b3J5VGFibGVbdGhpcy5oaXN0b3J5VGFibGVJbmRleCAtIDFdLnN0YXJ0ID0gdGhpcy5zZWxlY3Rpb25TdGFydDtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5oaXN0b3J5VGFibGVbdGhpcy5oaXN0b3J5VGFibGVJbmRleCAtIDFdLmVuZCA9IHRoaXMuc2VsZWN0aW9uRW5kO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTGltaXQgdGhlIGhpc3RvcnkgdGFibGUgc2l6ZSBhY2NvcmRpbmcgdG8gdGhlIGBoaXN0b3J5U2l6ZWAgb3B0aW9uXG4gICAgICAgICAgICBpZiAodGhpcy5oaXN0b3J5VGFibGUubGVuZ3RoID4gdGhpcy5zZXR0aW5ncy5oaXN0b3J5U2l6ZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2hpc3RvcnlUYWJsZUZvcmdldCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVidWcgZnVuY3Rpb24gZm9yIHRoZSBoaXN0b3J5IHRhYmxlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICAvKlxuICAgIF9kZWJ1Z0hpc3RvcnlUYWJsZSgpIHtcbiAgICAgICAgbGV0IGkgPSAwO1xuICAgICAgICBsZXQgbWFyaztcbiAgICAgICAgdGhpcy5oaXN0b3J5VGFibGUuZm9yRWFjaChoaXN0b3J5ID0+IHtcbiAgICAgICAgICAgIGlmICh0aGlzLmhpc3RvcnlUYWJsZUluZGV4ID09PSBpKSB7XG4gICAgICAgICAgICAgICAgbWFyayA9ICc+ICc7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG1hcmsgPSAnJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGAke21hcmt9JHtpKyt9OiAke2hpc3RvcnkudmFsdWV9ICR7aGlzdG9yeS5zdGFydH18JHtoaXN0b3J5LmVuZH0gW29uR29pbmdSZWRvOiAke3RoaXMub25Hb2luZ1JlZG99XWApOyAvL0RFQlVHXG4gICAgICAgIH0pO1xuICAgIH1cbiAgICAqL1xuXG4gICAgLyoqXG4gICAgICogJ1VuZG8nIG9yICdSZWRvJyB0aGUgbGFzdC9uZXh0IHVzZXIgZW50cnkgaW4gdGhlIGhpc3RvcnkgdGFibGUuXG4gICAgICogVGhpcyBkb2VzIG5vdCBtb2RpZnkgdGhlIGhpc3RvcnkgdGFibGUsIG9ubHkgdGhlIHBvaW50ZXIgdG8gdGhlIGN1cnJlbnQgc3RhdGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHVuZG8gSWYgc2V0IHRvIGB0cnVlYCwgdGhlbiB0aGlzIGZ1bmN0aW9uIGRvZXMgYW4gJ1VuZG8nLCBvdGhlcndpc2UgaXQgZG9lcyBhICdSZWRvJ1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2hpc3RvcnlUYWJsZVVuZG9PclJlZG8odW5kbyA9IHRydWUpIHtcbiAgICAgICAgbGV0IGNoZWNrO1xuICAgICAgICBpZiAodW5kbykge1xuICAgICAgICAgICAgLy8gT25seSAndW5kbycgaWYgdGhlcmUgYXJlIHNvbWUgaW5mbyB0byB1bmRvXG4gICAgICAgICAgICBjaGVjayA9IHRoaXMuaGlzdG9yeVRhYmxlSW5kZXggPiAwO1xuICAgICAgICAgICAgaWYgKGNoZWNrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaXN0b3J5VGFibGVJbmRleC0tO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT25seSAncmVkbycgaWYgdGhlcmUgYXJlIHNvbWUgaW5mbyB0byByZWRvIGF0IHRoZSBlbmQgb2YgdGhlIGhpc3RvcnkgdGFibGVcbiAgICAgICAgICAgIGNoZWNrID0gdGhpcy5oaXN0b3J5VGFibGVJbmRleCArIDEgPCB0aGlzLmhpc3RvcnlUYWJsZS5sZW5ndGg7XG4gICAgICAgICAgICBpZiAoY2hlY2spIHtcbiAgICAgICAgICAgICAgICB0aGlzLmhpc3RvcnlUYWJsZUluZGV4Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2hlY2spIHtcbiAgICAgICAgICAgIC8vIFNldCB0aGUgdmFsdWUgYmFja1xuICAgICAgICAgICAgY29uc3QgdW5kb0luZm8gPSB0aGlzLmhpc3RvcnlUYWJsZVt0aGlzLmhpc3RvcnlUYWJsZUluZGV4XTtcbiAgICAgICAgICAgIHRoaXMuc2V0KHVuZG9JbmZvLnZhbHVlLCBudWxsLCBmYWxzZSk7IC8vIG5leHQgb3IgcHJldmlvdXMgcmF3IHZhbHVlXG5cbiAgICAgICAgICAgIC8vIFNldCB0aGUgc2VsZWN0aW9uIGJhY2tcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24odGhpcy5kb21FbGVtZW50LCB1bmRvSW5mby5zdGFydCwgdW5kb0luZm8uZW5kKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqICdVbmRvJyB0aGUgbGFzdCB1c2VyIGVudHJ5IGJ5IGdvaW5nIGJhY2sgb25lIGVudHJ5IGluIHRoZSBoaXN0b3J5IHRhYmxlLlxuICAgICAqIFRoaXMga2VlcHMgdGhlIGZvbGxvd2luZyBlbnRyaWVzIGluIG9yZGVyIHRvIGFsbG93IGZvciBhICdyZWRvJy5cbiAgICAgKiBUaGlzIGRvZXMgbm90IG1vZGlmeSB0aGUgaGlzdG9yeSB0YWJsZSwgb25seSB0aGUgcG9pbnRlciB0byB0aGUgY3VycmVudCBzdGF0ZS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9oaXN0b3J5VGFibGVVbmRvKCkge1xuICAgICAgICB0aGlzLl9oaXN0b3J5VGFibGVVbmRvT3JSZWRvKHRydWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqICdSZWRvJyB0aGUgbmV4dCB1c2VyIGVudHJ5IGluIHRoZSBoaXN0b3J5IHRhYmxlLlxuICAgICAqIFRoaXMgZG9lcyBub3QgbW9kaWZ5IHRoZSBoaXN0b3J5IHRhYmxlLCBvbmx5IHRoZSBwb2ludGVyIHRvIHRoZSBjdXJyZW50IHN0YXRlLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2hpc3RvcnlUYWJsZVJlZG8oKSB7XG4gICAgICAgIHRoaXMuX2hpc3RvcnlUYWJsZVVuZG9PclJlZG8oZmFsc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc2V0IHRoZSBoaXN0b3J5IHRhYmxlIHRvIGl0cyBpbml0aWFsIHN0YXRlLCBhbmQgc2VsZWN0IHRoZSB2YWx1ZS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIC8qXG4gICAgcmVzZXRIaXN0b3J5VGFibGUoKSB7IC8vRklYTUUgVGVzdCB0aGlzXG4gICAgICAgIHRoaXMuc2V0KHRoaXMucmF3VmFsdWUsIG51bGwsIGZhbHNlKTtcbiAgICAgICAgdGhpcy5zZWxlY3QoKTtcbiAgICAgICAgY29uc3Qgc2VsZWN0aW9uID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFNlbGVjdGlvbih0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICB0aGlzLmhpc3RvcnlUYWJsZUluZGV4ID0gMDtcbiAgICAgICAgdGhpcy5oaXN0b3J5VGFibGUgPSBbe1xuICAgICAgICAgICAgLy8gU2F2ZSB0aGUgcmF3VmFsdWUgYW5kIHNlbGVjdGlvbiBzdGFydC9lbmRcbiAgICAgICAgICAgIHZhbHVlOiB0aGlzLnJhd1ZhbHVlLFxuICAgICAgICAgICAgc3RhcnQ6IHNlbGVjdGlvbi5zdGFydCxcbiAgICAgICAgICAgIGVuZCAgOiBzZWxlY3Rpb24uZW5kLFxuICAgICAgICB9XTtcbiAgICB9XG4gICAgKi9cblxuICAgIC8qKlxuICAgICAqIE1ha2UgdGhlIGhpc3RvcnkgdGFibGUgZm9yZ2V0IGl0cyBmaXJzdCBOIGVsZW1lbnRzLCBzaGlmdGluZyBpdHMgaW5kZXhlcyBpbiB0aGUgcHJvY2Vzcy5cbiAgICAgKiBgTmAgYmVpbmcgZ2l2ZW4gYXMgdGhlIGBudW1iZXJPZkVudHJpZXNUb0ZvcmdldGAgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtOdW1iZXJ9IG51bWJlck9mRW50cmllc1RvRm9yZ2V0XG4gICAgICogQHJldHVybnMge29iamVjdHxBcnJheTxvYmplY3Q+fSBUaGUgZGlzY2FyZGVkIG9iamVjdHMsIGluIGFuIEFycmF5LlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2hpc3RvcnlUYWJsZUZvcmdldChudW1iZXJPZkVudHJpZXNUb0ZvcmdldCA9IDEpIHtcbiAgICAgICAgY29uc3Qgc2hpZnRlZEF3YXkgPSBbXTtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBudW1iZXJPZkVudHJpZXNUb0ZvcmdldDsgaSsrKSB7XG4gICAgICAgICAgICBzaGlmdGVkQXdheS5wdXNoKHRoaXMuaGlzdG9yeVRhYmxlLnNoaWZ0KCkpO1xuICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBoaXN0b3J5IHRhYmxlIGluZGV4IGFjY29yZGluZ2x5XG4gICAgICAgICAgICB0aGlzLmhpc3RvcnlUYWJsZUluZGV4LS07XG4gICAgICAgICAgICBpZiAodGhpcy5oaXN0b3J5VGFibGVJbmRleCA8IDApIHtcbiAgICAgICAgICAgICAgICAvLyBJbiBjYXNlIHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIG1vcmUgdGltZXMgdGhhbiB0aGVyZSBpcyBzdGF0ZXMgaW4gdGhlIGhpc3RvcnkgdGFibGVcbiAgICAgICAgICAgICAgICB0aGlzLmhpc3RvcnlUYWJsZUluZGV4ID0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzaGlmdGVkQXdheS5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgICAgIHJldHVybiBzaGlmdGVkQXdheVswXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzaGlmdGVkQXdheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIGN1cnJlbnRseSB1c2VkIHZhbHVlIGZyb20gdGhlIGhpc3RvcnkgdGFibGUuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bWJlcn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9oaXN0b3J5VGFibGVDdXJyZW50VmFsdWVVc2VkKCkge1xuICAgICAgICBsZXQgaW5kZXhUb1VzZSA9IHRoaXMuaGlzdG9yeVRhYmxlSW5kZXg7XG4gICAgICAgIGlmIChpbmRleFRvVXNlIDwgMCkge1xuICAgICAgICAgICAgaW5kZXhUb1VzZSA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHRoaXMuaGlzdG9yeVRhYmxlW2luZGV4VG9Vc2VdKSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gJyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSB0aGlzLmhpc3RvcnlUYWJsZVtpbmRleFRvVXNlXS52YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUGFyc2UgdGhlIGBzdHlsZVJ1bGVzYCBvcHRpb24gYW5kIHJ1biB0aGUgdGVzdCBmb3IgZWFjaCBnaXZlbiBydWxlcywgZWl0aGVyIHByZS1kZWZpbmVkIG9uZXMgbGlrZSBgcG9zaXRpdmVgLCBgbmVnYXRpdmVgIGFuZCBgcmFuZ2VzYCwgb3IgdXNlciBkZWZpbmVkIGNhbGxiYWNrcyB3aXRoaW4gdGhlIGB1c2VyRGVmaW5lZGAgYXR0cmlidXRlLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3BhcnNlU3R5bGVSdWxlcygpIHtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh0aGlzLnNldHRpbmdzLnN0eWxlUnVsZXMpIHx8IHRoaXMucmF3VmFsdWUgPT09ICcnKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyAncG9zaXRpdmUnIGF0dHJpYnV0ZVxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh0aGlzLnNldHRpbmdzLnN0eWxlUnVsZXMucG9zaXRpdmUpKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5yYXdWYWx1ZSA+PSAwKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fYWRkQ1NTQ2xhc3ModGhpcy5zZXR0aW5ncy5zdHlsZVJ1bGVzLnBvc2l0aXZlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlQ1NTQ2xhc3ModGhpcy5zZXR0aW5ncy5zdHlsZVJ1bGVzLnBvc2l0aXZlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vICduZWdhdGl2ZScgYXR0cmlidXRlXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy5uZWdhdGl2ZSkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnJhd1ZhbHVlIDwgMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2FkZENTU0NsYXNzKHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy5uZWdhdGl2ZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZUNTU0NsYXNzKHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy5uZWdhdGl2ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyAncmFuZ2VzJyBhdHRyaWJ1dGVcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkodGhpcy5zZXR0aW5ncy5zdHlsZVJ1bGVzLnJhbmdlcykgJiYgdGhpcy5zZXR0aW5ncy5zdHlsZVJ1bGVzLnJhbmdlcy5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy5yYW5nZXMuZm9yRWFjaChyYW5nZSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMucmF3VmFsdWUgPj0gcmFuZ2UubWluICYmIHRoaXMucmF3VmFsdWUgPCByYW5nZS5tYXgpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fYWRkQ1NTQ2xhc3MocmFuZ2UuY2xhc3MpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZUNTU0NsYXNzKHJhbmdlLmNsYXNzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vICd1c2VyRGVmaW5lZCcgYXR0cmlidXRlXG4gICAgICAgIC8vVE9ETyBBbHNvIHBhc3MgdGhlIG9sZCByYXcgdmFsdWUgYXMgYSBwYXJhbWV0ZXIsIGFuZCBub3Qgb25seSB0aGUgbmV3IHJhdyB2YWx1ZVxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh0aGlzLnNldHRpbmdzLnN0eWxlUnVsZXMudXNlckRlZmluZWQpICYmIHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy51c2VyRGVmaW5lZC5sZW5ndGggIT09IDApIHtcbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy51c2VyRGVmaW5lZC5mb3JFYWNoKHVzZXJPYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKHVzZXJPYmplY3QuY2FsbGJhY2spKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRlc3QgZm9yIHRoZSB0eXBlIG9mIHRoZSBgY2xhc3Nlc2AgYXR0cmlidXRlLCB3aGljaCBjaGFuZ2VzIHRoZSBmdW5jdGlvbiBiZWhhdmlvclxuICAgICAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcodXNlck9iamVjdC5jbGFzc2VzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgJ2NsYXNzZXMnIGlzIGEgc3RyaW5nLCBzZXQgaXQgaWYgYHRydWVgLCByZW1vdmUgaXQgaWYgYGZhbHNlYFxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVzZXJPYmplY3QuY2FsbGJhY2sodGhpcy5yYXdWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9hZGRDU1NDbGFzcyh1c2VyT2JqZWN0LmNsYXNzZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDU1NDbGFzcyh1c2VyT2JqZWN0LmNsYXNzZXMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzQXJyYXkodXNlck9iamVjdC5jbGFzc2VzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVzZXJPYmplY3QuY2xhc3Nlcy5sZW5ndGggPT09IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiAnY2xhc3NlcycgaXMgYW4gYXJyYXkgd2l0aCBvbmx5IDIgZWxlbWVudHMsIHNldCB0aGUgZmlyc3QgY2xhc3MgaWYgYHRydWVgLCB0aGUgc2Vjb25kIGlmIGBmYWxzZWBcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAodXNlck9iamVjdC5jYWxsYmFjayh0aGlzLnJhd1ZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9hZGRDU1NDbGFzcyh1c2VyT2JqZWN0LmNsYXNzZXNbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDU1NDbGFzcyh1c2VyT2JqZWN0LmNsYXNzZXNbMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZUNTU0NsYXNzKHVzZXJPYmplY3QuY2xhc3Nlc1swXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2FkZENTU0NsYXNzKHVzZXJPYmplY3QuY2xhc3Nlc1sxXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmICh1c2VyT2JqZWN0LmNsYXNzZXMubGVuZ3RoID4gMikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBjYWxsYmFjayByZXR1cm5zIGFuIGFycmF5IG9mIGluZGV4ZXMgdG8gdXNlIG9uIHRoZSBgY2xhc3Nlc2AgYXJyYXlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjYWxsYmFja1Jlc3VsdCA9IHVzZXJPYmplY3QuY2FsbGJhY2sodGhpcy5yYXdWYWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzQXJyYXkoY2FsbGJhY2tSZXN1bHQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIG11bHRpcGxlIGluZGV4ZXMgYXJlIHJldHVybmVkXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJPYmplY3QuY2xhc3Nlcy5mb3JFYWNoKCh1c2VyQ2xhc3MsIGluZGV4KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KGluZGV4LCBjYWxsYmFja1Jlc3VsdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9hZGRDU1NDbGFzcyh1c2VyQ2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDU1NDbGFzcyh1c2VyQ2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzSW50KGNhbGxiYWNrUmVzdWx0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiBvbmx5IG9uZSBpbmRleCBpcyByZXR1cm5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VyT2JqZWN0LmNsYXNzZXMuZm9yRWFjaCgodXNlckNsYXNzLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGluZGV4ID09PSBjYWxsYmFja1Jlc3VsdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2FkZENTU0NsYXNzKHVzZXJDbGFzcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZUNTU0NsYXNzKHVzZXJDbGFzcyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGNhbGxiYWNrUmVzdWx0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSZW1vdmUgYWxsIHRoZSBjbGFzc2VzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHVzZXJPYmplY3QuY2xhc3Nlcy5mb3JFYWNoKHVzZXJDbGFzcyA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDU1NDbGFzcyh1c2VyQ2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgY2FsbGJhY2sgcmVzdWx0IGlzIG5vdCBhbiBhcnJheSBub3IgYSB2YWxpZCBhcnJheSBpbmRleCwgJHt0eXBlb2YgY2FsbGJhY2tSZXN1bHR9IGdpdmVuLmApO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcignVGhlIGNsYXNzZXMgYXR0cmlidXRlIGlzIG5vdCB2YWxpZCBmb3IgdGhlIGBzdHlsZVJ1bGVzYCBvcHRpb24uJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHVzZXJPYmplY3QuY2xhc3NlcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmICdjbGFzc2VzJyBpcyBgdW5kZWZpbmVkYCBvciBgbnVsbGAsIHRoZW4gdGhlIGNhbGxiYWNrIGlzIGNhbGxlZCB3aXRoIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgcGFzc2VkIGFzIGEgcGFyYW1ldGVyXG4gICAgICAgICAgICAgICAgICAgICAgICB1c2VyT2JqZWN0LmNhbGxiYWNrKHRoaXMpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcignVGhlIGNhbGxiYWNrL2NsYXNzZXMgc3RydWN0dXJlIGlzIG5vdCB2YWxpZCBmb3IgdGhlIGBzdHlsZVJ1bGVzYCBvcHRpb24uJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBUaGUgZ2l2ZW4gXFxgc3R5bGVSdWxlc1xcYCBjYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvbiwgJHt0eXBlb2YgY2FsbGJhY2t9IGdpdmVuLmAsIHRoaXMuc2V0dGluZ3Muc2hvd1dhcm5pbmdzKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCB0aGUgZ2l2ZW4gQ1NTIGNsYXNzIHRvIHRoZSBET00gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjc3NDbGFzc05hbWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9hZGRDU1NDbGFzcyhjc3NDbGFzc05hbWUpIHtcbiAgICAgICAgdGhpcy5kb21FbGVtZW50LmNsYXNzTGlzdC5hZGQoY3NzQ2xhc3NOYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIGdpdmVuIENTUyBjbGFzcyBmcm9tIHRoZSBET00gZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjc3NDbGFzc05hbWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9yZW1vdmVDU1NDbGFzcyhjc3NDbGFzc05hbWUpIHtcbiAgICAgICAgdGhpcy5kb21FbGVtZW50LmNsYXNzTGlzdC5yZW1vdmUoY3NzQ2xhc3NOYW1lKTtcbiAgICB9XG5cbiAgICAvLyBUaGlzIGFyZSB0aGUgcHVibGljIGZ1bmN0aW9uIGF2YWlsYWJsZSBvbiBlYWNoIGF1dG9OdW1lcmljLW1hbmFnZWQgZWxlbWVudFxuXG4gICAgLyoqXG4gICAgICogTWV0aG9kIHRoYXQgdXBkYXRlcyB0aGUgQXV0b051bWVyaWMgc2V0dGluZ3MsIGFuZCBpbW1lZGlhdGVseSBmb3JtYXQgdGhlIGVsZW1lbnQgYWNjb3JkaW5nbHkuXG4gICAgICogVGhlIG9wdGlvbnMgcGFzc2VkIGFzIHBhcmFtZXRlcihzKSBpcyBlaXRoZXIgb25lIG9yIG1hbnkgb2JqZWN0cyB0aGF0IGVhY2ggY29udGFpbnMgc29tZSBzZXR0aW5ncywgaWUuIDpcbiAgICAgKiB7XG4gICAgICogICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3I6IFwiLlwiLFxuICAgICAqICAgICBkZWNpbWFsQ2hhcmFjdGVyOiBcIixcIixcbiAgICAgKiAgICAgY3VycmVuY3lTeW1ib2w6ICfigqwgJyxcbiAgICAgKiB9XG4gICAgICogSWYgbXVsdGlwbGUgb3B0aW9ucyBhcmUgcGFzc2VkLCB0aGUgbGF0dGVyIG92ZXJ3cml0ZSB0aGUgcHJldmlvdXMgb25lcy5cbiAgICAgKlxuICAgICAqIE5vdGU6IElmIHRoZSBuZXcgc2V0dGluZ3MgYXJlIG5vdCB2YWxpZGF0ZWQsIG9yIHRoZSBjYWxsIHRvIGBzZXQoKWAgZmFpbHMsIHRoZW4gdGhlIHByZXZpb3VzIHZhbGlkIHNldHRpbmdzIGFyZSByZXZlcnRlZCBiYWNrIHRvLlxuICAgICAqXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnVwZGF0ZSh7IG9wdGlvbnMgfSkgLy8gVXBkYXRlcyB0aGUgc2V0dGluZ3NcbiAgICAgKiBAZXhhbXBsZSBhbkVsZW1lbnQudXBkYXRlKHsgb3B0aW9uczEgfSwgeyBvcHRpb25zMiB9KSAvLyBVcGRhdGVzIHRoZSBzZXR0aW5ncyB3aXRoIG11bHRpcGxlIG9wdGlvbiBvYmplY3RzXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnVwZGF0ZShbeyBvcHRpb25zMSB9LCB7IG9wdGlvbnMyIH1dKSAvLyBVcGRhdGVzIHRoZSBzZXR0aW5ncyB3aXRoIG11bHRpcGxlIG9wdGlvbiBvYmplY3RzIGluIGEgc2luZ2xlIGFycmF5XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdHxzdHJpbmd8YXJyYXl9IG5ld09wdGlvbnNcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgdXBkYXRlKC4uLm5ld09wdGlvbnMpIHtcbiAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkobmV3T3B0aW9ucykgJiYgQXJyYXkuaXNBcnJheShuZXdPcHRpb25zWzBdKSkge1xuICAgICAgICAgICAgLy8gQWxsb3dzIHRvIHBhc3MgYSBzaW5nbGUgYXJyYXkgb2Ygb3B0aW9uc1xuICAgICAgICAgICAgbmV3T3B0aW9ucyA9IG5ld09wdGlvbnNbMF07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBLZWVwIGEgY29weSBvZiB0aGUgb3JpZ2luYWwgc2V0dGluZ3MgYmVmb3JlIGNoYW5naW5nIHRoZW0sIGluIGNhc2UgdGhleSBkbyBub3QgdmFsaWRhdGUgY29ycmVjdGx5LCBzbyB3ZSBjYW4gc3dpdGNoIGJhY2sgdG8gdGhlbVxuICAgICAgICBjb25zdCBvcmlnaW5hbFNldHRpbmdzID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QodGhpcy5zZXR0aW5ncyk7IC8vVE9ETyBDaGVjayB0aGF0IHRoZSBgc3R5bGVSdWxlc2Agb3B0aW9uIGlzIGNvcnJlY3RseSBjbG9uZWQgKGR1ZSB0byBkZXB0aCBjbG9uaW5nIGxpbWl0YXRpb24pXG5cbiAgICAgICAgLy8gU3RvcmUgdGhlIGN1cnJlbnQgdW5mb3JtYXR0ZWQgaW5wdXQgdmFsdWVcbiAgICAgICAgY29uc3QgbnVtZXJpY1N0cmluZyA9IHRoaXMucmF3VmFsdWU7XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgYSBzaW5nbGUgb3B0aW9uIG9iamVjdCB3aXRoIHRoZSBzZXR0aW5ncyBmcm9tIHRoZSBsYXR0ZXIgb3ZlcndyaXRpbmcgdGhvc2UgZnJvbSB0aGUgZm9ybWVyXG4gICAgICAgIGxldCBvcHRpb25zVG9Vc2UgPSB7fTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShuZXdPcHRpb25zKSB8fCBuZXdPcHRpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgb3B0aW9uc1RvVXNlID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIGlmIChuZXdPcHRpb25zLmxlbmd0aCA+PSAxKSB7XG4gICAgICAgICAgICBuZXdPcHRpb25zLmZvckVhY2gob3B0aW9uT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5jb25zdHJ1Y3Rvci5faXNQcmVEZWZpbmVkT3B0aW9uVmFsaWQob3B0aW9uT2JqZWN0KSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBUaGUgb3B0aW9uIG9iamVjdCBpcyBhIHByZWRlZmluZWQgb3B0aW9uIG5hbWUgKGllLiAnZXVybycpXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbk9iamVjdCA9IHRoaXMuY29uc3RydWN0b3IuX2dldE9wdGlvbk9iamVjdChvcHRpb25PYmplY3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24ob3B0aW9uc1RvVXNlLCBvcHRpb25PYmplY3QpO1xuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVcGRhdGUgdGhlIHNldHRpbmdzXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRTZXR0aW5ncyhvcHRpb25zVG9Vc2UsIHRydWUpO1xuXG4gICAgICAgICAgICAvLyBSZWZvcm1hdCB0aGUgaW5wdXQgdmFsdWUgd2l0aCB0aGUgbmV3IHNldHRpbmdzXG4gICAgICAgICAgICAvLyBOb3RlOiB3ZSBhbHdheXMgYHNldGAsIGV2ZW4gd2hlbiBgbnVtZXJpY1N0cmluZ2AgaXMgdGhlIGVtcHR5IHN0cmluZyAnJywgc2luY2UgYGVtcHR5SW5wdXRCZWhhdmlvcmAgKHNldCB0byBgYWx3YXlzYCBvciBgemVyb2ApIGNhbiBjaGFuZ2UgaG93IHRoZSBlbXB0eSBpbnB1dCBpcyBmb3JtYXR0ZWRcbiAgICAgICAgICAgIHRoaXMuc2V0KG51bWVyaWNTdHJpbmcpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgLy8gSWYgdGhlIHNldHRpbmdzIHZhbGlkYXRpb24gZmFpbHMsIHRoZW4gd2Ugc3dpdGNoIGJhY2sgdG8gdGhlIHByZXZpb3VzIHZhbGlkIHNldHRpbmdzXG4gICAgICAgICAgICB0aGlzLl9zZXRTZXR0aW5ncyhvcmlnaW5hbFNldHRpbmdzLCB0cnVlKTsgLy8gYF9zZXRTZXR0aW5ncygpYCBpcyB1c2VkIGhlcmUgaW5zdGVhZCBvZiBkaXJlY3RseSBkb2luZyBgdGhpcy5zZXR0aW5ncyA9IG9yaWdpbmFsU2V0dGluZ3M7YCBzaW5jZSBsb3RzIG9mIHNpZGUgdmFyaWFibGVzIGFyZSBjYWxjdWxhdGVkIGZyb20gdGhlIHNldHRpbmdzLCBhbmQgd2UgbmVlZCB0byBnZXQgdGhvc2UgYmFjayB0byB0aGVpciBwcmV2aW91cyBzdGF0ZS4gTm90ZTogYF9zZXRTZXR0aW5ncygpYCBpcyBjYWxsZWQgaW4gdGhlICd1cGRhdGUnIG1vZGUgaW4gb3JkZXIgdG8gY29ycmVjdGx5IHNldCBiYWNrIHRoZSBgb3JpZ2luYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWVgIHZhbHVlLlxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVW5hYmxlIHRvIHVwZGF0ZSB0aGUgc2V0dGluZ3MsIHRob3NlIGFyZSBpbnZhbGlkOiBbJHtlcnJvcn1dYCk7XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBvcHRpb25zIG9iamVjdCBjb250YWluaW5nIGFsbCB0aGUgY3VycmVudCBhdXRvTnVtZXJpYyBzZXR0aW5ncyBpbiBlZmZlY3QuXG4gICAgICogWW91IGNhbiB0aGVuIGRpcmVjdGx5IGFjY2VzcyBlYWNoIG9wdGlvbiBieSB1c2luZyBpdHMgbmFtZSA6IGBhbkVsZW1lbnQuZ2V0U2V0dGluZ3MoKS5vcHRpb25OYW1lQXV0b0NvbXBsZXRlZGAuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGFuRWxlbWVudC5nZXRTZXR0aW5ncygpXG4gICAgICogYW5FbGVtZW50LmdldFNldHRpbmdzKCkuZGVjaW1hbENoYXJhY3RlciAvLyBSZXR1cm4gdGhlIGRlY2ltYWxDaGFyYWN0ZXIgc2V0dGluZyBhcyBhIHN0cmluZyAtIGFueSB2YWxpZCBvcHRpb24gbmFtZSBjYW4gYmUgdXNlZFxuICAgICAqXG4gICAgICogQHJldHVybnMge29iamVjdH1cbiAgICAgKi9cbiAgICBnZXRTZXR0aW5ncygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2V0dGluZ3M7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBnaXZlbiBlbGVtZW50IHZhbHVlLCBhbmQgZm9ybWF0IGl0IGltbWVkaWF0ZWx5LlxuICAgICAqIEFkZGl0aW9uYWxseSwgdGhpcyBgc2V0KClgIG1ldGhvZCBjYW4gYWNjZXB0IG9wdGlvbnMgdGhhdCB3aWxsIGJlIG1lcmdlZCBpbnRvIHRoZSBjdXJyZW50IEF1dG9OdW1lcmljIGVsZW1lbnQsIHRha2luZyBwcmVjZWRlbmNlIG92ZXIgYW55IHByZXZpb3VzIHNldHRpbmdzLlxuICAgICAqXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnNldCgnMTIzNDUuNjcnKSAvLyBGb3JtYXRzIHRoZSB2YWx1ZVxuICAgICAqIEBleGFtcGxlIGFuRWxlbWVudC5zZXQoMTIzNDUuNjcpIC8vIEZvcm1hdHMgdGhlIHZhbHVlXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnNldCgxMjM0NS42NywgeyBkZWNpbWFsQ2hhcmFjdGVyIDogJywnIH0pIC8vIFVwZGF0ZSB0aGUgc2V0dGluZ3MgYW5kIGZvcm1hdHMgdGhlIHZhbHVlIGluIG9uZSBnb1xuICAgICAqIEBleGFtcGxlIGFuRWxlbWVudC5ub3J0aEFtZXJpY2FuKCkuc2V0KCckMTIsMzQ1LjY3JykgLy8gU2V0IGFuIGFscmVhZHkgZm9ybWF0dGVkIHZhbHVlICh0aGlzIGRvZXMgbm90IF9leGFjdGx5XyByZXNwZWN0IHRoZSBjdXJyZW5jeSBzeW1ib2wvbmVnYXRpdmUgcGxhY2VtZW50cywgYnV0IG9ubHkgcmVtb3ZlIGFsbCBub24tbnVtYmVycyBjaGFyYWN0ZXJzLCBhY2NvcmRpbmcgdG8gdGhlIG9uZXMgZ2l2ZW4gaW4gdGhlIHNldHRpbmdzKVxuICAgICAqIEBleGFtcGxlIGFuRWxlbWVudC5zZXQobnVsbCkgLy8gU2V0IHRoZSByYXdWYWx1ZSBhbmQgZWxlbWVudCB2YWx1ZSB0byBgbnVsbGBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ3xudWxsfSBuZXdWYWx1ZSBUaGUgdmFsdWUgbXVzdCBiZSBhIE51bWJlciwgYSBudW1lcmljIHN0cmluZyBvciBgbnVsbGAgKGlmIGBlbXB0eUlucHV0QmVoYXZpb3JgIGlzIHNldCB0byBgJ251bGwnYClcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyBBIHNldHRpbmdzIG9iamVjdCB0aGF0IHdpbGwgb3ZlcnJpZGUgdGhlIGN1cnJlbnQgc2V0dGluZ3MuIE5vdGU6IHRoZSB1cGRhdGUgaXMgZG9uZSBvbmx5IGlmIHRoZSBgbmV3VmFsdWVgIGlzIGRlZmluZWQuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBzYXZlQ2hhbmdlVG9IaXN0b3J5IElmIHNldCB0byBgdHJ1ZWAsIHRoZW4gdGhlIGNoYW5nZSBpcyByZWNvcmRlZCBpbiB0aGUgaGlzdG9yeSB0YWJsZVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKiBAdGhyb3dzXG4gICAgICovXG4gICAgc2V0KG5ld1ZhbHVlLCBvcHRpb25zID0gbnVsbCwgc2F2ZUNoYW5nZVRvSGlzdG9yeSA9IHRydWUpIHtcbiAgICAgICAgLy9UT0RPIEFkZCB0aGUgYHNhdmVTZXR0aW5nc2Agb3B0aW9ucy4gSWYgYHRydWVgLCB0aGVuIHdoZW4gYG9wdGlvbnNgIGlzIHBhc3NlZCwgdGhlbiBpdCBvdmVyd3JpdGUgdGhlIGN1cnJlbnQgYHRoaXMuc2V0dGluZ3NgLiBJZiBgZmFsc2VgIHRoZSBgb3B0aW9uc2AgYXJlIG9ubHkgdXNlZCBvbmNlIGFuZCBgdGhpcy5zZXR0aW5nc2AgaXMgbm90IG1vZGlmaWVkXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZChuZXdWYWx1ZSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFlvdSBhcmUgdHJ5aW5nIHRvIHNldCBhbiAndW5kZWZpbmVkJyB2YWx1ZSA7IGFuIGVycm9yIGNvdWxkIGhhdmUgb2NjdXJyZWQuYCwgdGhpcy5zZXR0aW5ncy5zaG93V2FybmluZ3MpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGUgb3B0aW9ucyB1cGRhdGUgaXMgZG9uZSBvbmx5IGlmIHRoZSBgbmV3VmFsdWVgIGlzIG5vdCBgdW5kZWZpbmVkYFxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zKSkge1xuICAgICAgICAgICAgdGhpcy5fc2V0U2V0dGluZ3Mob3B0aW9ucywgdHJ1ZSk7IC8vIFdlIGRvIG5vdCBjYWxsIGB1cGRhdGVgIGhlcmUgc2luY2UgdGhpcyB3b3VsZCBjYWxsIGBzZXRgIHRvb1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG5ld1ZhbHVlID09PSBudWxsICYmIHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5udWxsKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBZb3UgYXJlIHRyeWluZyB0byBzZXQgdGhlIFxcYG51bGxcXGAgdmFsdWUgd2hpbGUgdGhlIFxcYGVtcHR5SW5wdXRCZWhhdmlvclxcYCBvcHRpb24gaXMgc2V0IHRvICR7dGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3J9LiBJZiB5b3Ugd2FudCB0byBiZSBhYmxlIHRvIHNldCB0aGUgXFxgbnVsbFxcYCB2YWx1ZSwgeW91IG5lZWQgdG8gY2hhbmdlIHRoZSAnZW1wdHlJbnB1dEJlaGF2aW9yJyBvcHRpb24gdG8gXFxgJ251bGwnXFxgLmAsIHRoaXMuc2V0dGluZ3Muc2hvd1dhcm5pbmdzKTtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHZhbHVlO1xuICAgICAgICBpZiAobmV3VmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vVE9ETyBNZXJnZSB0aGlzIGludG8gYSBnbG9iYWwgYGlmIChuZXdWYWx1ZSA9PT0gbnVsbCkge2AgdGVzdCwgd2l0aCB0aGUgdGVzdCBhYm92ZVxuICAgICAgICAgICAgLy8gSGVyZSB0aGlzLnNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvciA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubnVsbFxuICAgICAgICAgICAgdGhpcy5fc2V0RWxlbWVudEFuZFJhd1ZhbHVlKG51bGwsIG51bGwsIHNhdmVDaGFuZ2VUb0hpc3RvcnkpO1xuICAgICAgICAgICAgdGhpcy5fc2F2ZVZhbHVlVG9QZXJzaXN0ZW50U3RvcmFnZSgpO1xuXG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fdG9OdW1lcmljVmFsdWUobmV3VmFsdWUsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICBpZiAoaXNOYU4oTnVtYmVyKHZhbHVlKSkpIHtcbiAgICAgICAgICAgIC8vVE9ETyBEbyBub3QgbW9kaWZ5IHRoZSBlbGVtZW50IHZhbHVlIGlmIHRoZSBuZXdWYWx1ZSByZXN1bHRzIGluIGBOYU5gLiBNYWtlIHN1cmUgdGhlIHNldHRpbmdzLCBpZiBtb2RpZmllZCwgYXJlIHJldmVydCBiYWNrIHRvby5cbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFRoZSB2YWx1ZSB5b3UgYXJlIHRyeWluZyB0byBzZXQgcmVzdWx0cyBpbiBcXGBOYU5cXGAuIFRoZSBlbGVtZW50IHZhbHVlIGlzIHNldCB0byB0aGUgZW1wdHkgc3RyaW5nIGluc3RlYWQuYCwgdGhpcy5zZXR0aW5ncy5zaG93V2FybmluZ3MpO1xuICAgICAgICAgICAgdGhpcy5zZXRWYWx1ZSgnJywgc2F2ZUNoYW5nZVRvSGlzdG9yeSk7XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBpZiAodmFsdWUgPT09ICcnICYmIHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci56ZXJvKSB7XG4gICAgICAgICAgICAvLyBLZWVwIHRoZSB2YWx1ZSB6ZXJvIGluc2lkZSB0aGUgZWxlbWVudFxuICAgICAgICAgICAgdmFsdWUgPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHZhbHVlICE9PSAnJykge1xuICAgICAgICAgICAgY29uc3QgW21pblRlc3QsIG1heFRlc3RdID0gdGhpcy5jb25zdHJ1Y3Rvci5fY2hlY2tJZkluUmFuZ2VXaXRoT3ZlcnJpZGVPcHRpb24odmFsdWUsIHRoaXMuc2V0dGluZ3MpO1xuXG4gICAgICAgICAgICAvLyBNb2RpZnkgdGhlIGZvcm1hdHRlZCB2YWx1ZSBpZiB0aGUgcmF3VmFsdWUgaXMgZm91bmQgaW4gdGhlIGB2YWx1ZXNUb1N0cmluZ3NgIG9wdGlvblxuICAgICAgICAgICAgaWYgKG1pblRlc3QgJiYgbWF4VGVzdCAmJiB0aGlzLnNldHRpbmdzLnZhbHVlc1RvU3RyaW5ncyAmJiB0aGlzLl9jaGVja1ZhbHVlc1RvU3RyaW5ncyh2YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAvLyBTZXQgdGhlIHJhdyB2YWx1ZSBub3JtYWxseSwgYW5kIHRoZSBmb3JtYXR0ZWQgdmFsdWUgd2l0aCB0aGUgY29ycmVzcG9uZGluZyBzdHJpbmdcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50QW5kUmF3VmFsdWUodGhpcy5zZXR0aW5ncy52YWx1ZXNUb1N0cmluZ3NbdmFsdWVdLCB2YWx1ZSwgc2F2ZUNoYW5nZVRvSGlzdG9yeSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2F2ZVZhbHVlVG9QZXJzaXN0ZW50U3RvcmFnZSgpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFRoaXMgdGVzdCBpcyBuZWVkZWQgYnkgdGhlIGBzaG93UG9zaXRpdmVTaWduYCBvcHRpb25cbiAgICAgICAgICAgIGNvbnN0IGlzWmVybyA9IEF1dG9OdW1lcmljSGVscGVyLmlzWmVyb09ySGFzTm9WYWx1ZSh2YWx1ZSk7XG4gICAgICAgICAgICBpZiAoaXNaZXJvKSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSAnMCc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChtaW5UZXN0ICYmIG1heFRlc3QpIHtcbiAgICAgICAgICAgICAgICBsZXQgZm9yY2VkUmF3VmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9yb3VuZFJhd1ZhbHVlKHZhbHVlLCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgICAgICAgICBmb3JjZWRSYXdWYWx1ZSA9IHRoaXMuX3RyaW1MZWFkaW5nQW5kVHJhaWxpbmdaZXJvcyhmb3JjZWRSYXdWYWx1ZS5yZXBsYWNlKHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciwgJy4nKSk7IC8vIE1vdmUgdGhlIGBzZXRSYXdWYWx1ZWAgY2FsbCBhZnRlciB0aGUgYHNldEVsZW1lbnRWYWx1ZWAgb25lXG4gICAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLl9nZXRSYXdWYWx1ZVRvRm9ybWF0KHZhbHVlKTsgLy8gTXVsdGlwbHkgdGhlIHJhdyB2YWx1ZSB0byBvYnRhaW4gdGhlIGZvcm1hdHRlZCB2YWx1ZVxuXG4gICAgICAgICAgICAgICAgLy8gUm91bmQgdGhlIGdpdmVuIHZhbHVlIGFjY29yZGluZyB0byB0aGUgb2JqZWN0IHN0YXRlIChmb2N1c2VkL3VuZm9jdXNlZClcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc0ZvY3VzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9yb3VuZEZvcm1hdHRlZFZhbHVlU2hvd25PbkZvY3VzKHZhbHVlLCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5kaXZpc29yV2hlblVuZm9jdXNlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZSAvIHRoaXMuc2V0dGluZ3MuZGl2aXNvcldoZW5VbmZvY3VzZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uQmx1cih2YWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9tb2RpZnlOZWdhdGl2ZVNpZ25BbmREZWNpbWFsQ2hhcmFjdGVyRm9yRm9ybWF0dGVkVmFsdWUodmFsdWUsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fYWRkR3JvdXBTZXBhcmF0b3JzKHZhbHVlLCB0aGlzLnNldHRpbmdzLCB0aGlzLmlzRm9jdXNlZCwgdGhpcy5yYXdWYWx1ZSwgZm9yY2VkUmF3VmFsdWUpO1xuICAgICAgICAgICAgICAgIGlmICghdGhpcy5pc0ZvY3VzZWQgJiYgdGhpcy5zZXR0aW5ncy5zeW1ib2xXaGVuVW5mb2N1c2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gYCR7dmFsdWV9JHt0aGlzLnNldHRpbmdzLnN5bWJvbFdoZW5VbmZvY3VzZWR9YDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzIHx8IHRoaXMuc2V0dGluZ3MuZGl2aXNvcldoZW5VbmZvY3VzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2F2ZVZhbHVlVG9QZXJzaXN0ZW50U3RvcmFnZSgpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuX3NldEVsZW1lbnRBbmRSYXdWYWx1ZSh2YWx1ZSwgZm9yY2VkUmF3VmFsdWUsIHNhdmVDaGFuZ2VUb0hpc3RvcnkpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICghbWluVGVzdCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLm1pblJhbmdlRXhjZWVkZWQsIHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKCFtYXhUZXN0KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubWF4UmFuZ2VFeGNlZWRlZCwgdGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdmFsdWUgWyR7dmFsdWV9XSBiZWluZyBzZXQgZmFsbHMgb3V0c2lkZSBvZiB0aGUgbWluaW11bVZhbHVlIFske3RoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlfV0gYW5kIG1heGltdW1WYWx1ZSBbJHt0aGlzLnNldHRpbmdzLm1heGltdW1WYWx1ZX1dIHJhbmdlIHNldCBmb3IgdGhpcyBlbGVtZW50YCk7XG5cbiAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVWYWx1ZUZyb21QZXJzaXN0ZW50U3RvcmFnZSgpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0VmFsdWUoJycsIHNhdmVDaGFuZ2VUb0hpc3RvcnkpOyAvL1RPRE8gU2hvdWxkbid0IHdlIGp1c3QgZHJvcCB0aGF0IGZhdWx0eSBuZXdWYWx1ZSBhbmQga2VlcCB0aGUgcHJldmlvdXMgb25lPyBUaGlzIGlzIGJlaGluZCBhIGB0aHJvd0Vycm9yKClgIGNhbGwgYW55d2F5Li5cblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gSGVyZSwgYHZhbHVlYCBlcXVhbCB0aGUgZW1wdHkgc3RyaW5nIGAnJ2BcbiAgICAgICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLmFsd2F5cykge1xuICAgICAgICAgICAgICAgIC8vIEtlZXAgdGhlIGN1cnJlbmN5IHN5bWJvbCBhcyBwZXIgZW1wdHlJbnB1dEJlaGF2aW9yXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gJyc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3NldEVsZW1lbnRBbmRSYXdWYWx1ZShyZXN1bHQsICcnLCBzYXZlQ2hhbmdlVG9IaXN0b3J5KTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGdpdmVuIHZhbHVlIGRpcmVjdGx5IGFzIHRoZSBET00gZWxlbWVudCB2YWx1ZSwgd2l0aG91dCBmb3JtYXR0aW5nIGl0IGJlZm9yZWhhbmQuXG4gICAgICogWW91IGNhbiBhbHNvIHNldCB0aGUgdmFsdWUgYW5kIHVwZGF0ZSB0aGUgc2V0dGluZyBpbiBvbmUgZ28gKHRoZSB2YWx1ZSB3aWxsIGFnYWluIG5vdCBiZSBmb3JtYXR0ZWQgaW1tZWRpYXRlbHkpLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqIEB0aHJvd3NcbiAgICAgKi9cbiAgICBzZXRVbmZvcm1hdHRlZCh2YWx1ZSwgb3B0aW9ucyA9IG51bGwpIHtcbiAgICAgICAgLy9UT0RPIFNob3VsZCB3ZSB1c2UgYEF1dG9OdW1lcmljLnVuZm9ybWF0KClgIGhlcmUgYW5kIHNldCB0aGUgdW5mb3JtYXR0ZWQgcmVzdWx0IGluIGNhc2UgYHZhbHVlYCBpcyBmb3JtYXR0ZWQ/XG4gICAgICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCBBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVGhlIG9wdGlvbnMgdXBkYXRlIGlzIGRvbmUgb25seSBpZiB0aGUgYHZhbHVlYCBpcyBub3QgbnVsbFxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zKSkge1xuICAgICAgICAgICAgdGhpcy5fc2V0U2V0dGluZ3Mob3B0aW9ucywgdHJ1ZSk7IC8vIFdlIGRvIG5vdCBjYWxsIGB1cGRhdGVgIGhlcmUgc2luY2UgdGhpcyB3b3VsZCBjYWxsIGBzZXRgIHRvb1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3Qgc3RyaXBwZWRWYWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX3JlbW92ZUJyYWNrZXRzKHZhbHVlLCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgY29uc3Qgbm9ybWFsaXplZFZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzKHN0cmlwcGVkVmFsdWUsIHRoaXMuc2V0dGluZ3MsIHRydWUsIHRoaXMuaXNGb2N1c2VkKTtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcihub3JtYWxpemVkVmFsdWUpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdmFsdWUgaXMgbm90IGEgdmFsaWQgb25lLCBpdCdzIG5vdCBhIG51bWVyaWMgc3RyaW5nIG5vciBhIHJlY29nbml6ZWQgY3VycmVuY3kuYCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBbbWluVGVzdCwgbWF4VGVzdF0gPSB0aGlzLmNvbnN0cnVjdG9yLl9jaGVja0lmSW5SYW5nZVdpdGhPdmVycmlkZU9wdGlvbihub3JtYWxpemVkVmFsdWUsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICBpZiAobWluVGVzdCAmJiBtYXhUZXN0KSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgYG5vcm1hbGl6ZWRWYWx1ZWAgaXMgaW4gdGhlIHJhbmdlXG4gICAgICAgICAgICB0aGlzLnNldFZhbHVlKHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSB2YWx1ZSBpcyBvdXQgb2YgdGhlIHJhbmdlIGxpbWl0cyBbJHt0aGlzLnNldHRpbmdzLm1pbmltdW1WYWx1ZX0sICR7dGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWV9XS5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZ2l2ZW4gdmFsdWUgZGlyZWN0bHkgYXMgdGhlIERPTSBlbGVtZW50IHZhbHVlLCB3aXRob3V0IGZvcm1hdHRpbmcgaXQgYmVmb3JlaGFuZCwgYW5kIHdpdGhvdXQgY2hlY2tpbmcgaXRzIHZhbGlkaXR5LlxuICAgICAqIFRoaXMgYWxzbyB1cGRhdGVzIHRoZSBgcmF3VmFsdWVgIHdpdGggdGhlIGdpdmVuIGBuZXdWYWx1ZWAsIHdpdGhvdXQgY2hlY2tpbmcgaXQgdG9vIDsgaWYgaXQncyBub3QgZm9ybWF0dGVkIGxpa2UgYSBudW1iZXIgcmVjb2duaXplZCBieSBKYXZhc2NyaXB0LCB0aGlzICp3aWxsKiBsaWtlbHkgbWFrZSBvdGhlciBBdXRvTnVtZXJpYyBtZXRob2RzIGZhaWwuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ8bnVsbH0gbmV3VmFsdWUgVGhlIG5ldyB2YWx1ZSB0byBzZXQgb24gdGhlIGVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNhdmVDaGFuZ2VUb0hpc3RvcnkgSWYgc2V0IHRvIGB0cnVlYCwgdGhlbiB0aGUgY2hhbmdlIGlzIHJlY29yZGVkIGluIHRoZSBoaXN0b3J5IGFycmF5LCBvdGhlcndpc2UgaXQgaXMgbm90XG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIHNldFZhbHVlKG5ld1ZhbHVlLCBzYXZlQ2hhbmdlVG9IaXN0b3J5ID0gdHJ1ZSkge1xuICAgICAgICB0aGlzLl9zZXRFbGVtZW50QW5kUmF3VmFsdWUobmV3VmFsdWUsIHNhdmVDaGFuZ2VUb0hpc3RvcnkpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNhdmUgdGhlIHJhdyB2YWx1ZSBpbnNpZGUgdGhlIEF1dG9OdW1lcmljIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ3xudWxsfSByYXdWYWx1ZSBUaGUgbnVtZXJpYyB2YWx1ZSBhcyB1bmRlcnN0b29kIGJ5IEphdmFzY3JpcHQgbGlrZSBhIGBOdW1iZXJgXG4gICAgICogQHBhcmFtIHtib29sZWFufSBzYXZlQ2hhbmdlVG9IaXN0b3J5IElmIHNldCB0byBgdHJ1ZWAsIHRoZW4gdGhlIGNoYW5nZSBpcyByZWNvcmRlZCBpbiB0aGUgaGlzdG9yeSBhcnJheSwgb3RoZXJ3aXNlIGl0IGlzIG5vdFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NldFJhd1ZhbHVlKHJhd1ZhbHVlLCBzYXZlQ2hhbmdlVG9IaXN0b3J5ID0gdHJ1ZSkge1xuICAgICAgICAvLyBPbmx5IHNldCB0aGUgcmF3IHZhbHVlIGlmIHRoZSBnaXZlbiB2YWx1ZSBpcyBkaWZmZXJlbnQgdGhhbiB0aGUgY3VycmVudCBvbmVcbiAgICAgICAgaWYgKHRoaXMucmF3VmFsdWUgIT09IHJhd1ZhbHVlKSB7IC8vVE9ETyBNYW5hZ2UgdGhlIGNhc2Ugd2hlcmUgb25lIHZhbHVlIGlzIGEgc3RyaW5nIHdoaWxlIHRoZSBvdGhlciBpcyBhIG51bWJlcj9cbiAgICAgICAgICAgIGNvbnN0IG9sZFJhd1ZhbHVlID0gdGhpcy5yYXdWYWx1ZTtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgcmF3IHZhbHVlXG4gICAgICAgICAgICB0aGlzLnJhd1ZhbHVlID0gcmF3VmFsdWU7IC8vIEJ5IGRlZmF1bHQsIGlmIHRoZSBgcmF3VmFsdWVgIGlzIGNoYW5nZWQgcHJvZ3JhbW1hdGljYWxseVxuXG4gICAgICAgICAgICBpZiAoKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodGhpcy5zZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IpICYmIHRoaXMuc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yICE9PSAwKSAmJiAvLyBPbmx5IGRpdmlkZSBpZiB0aGUgYHJhd1ZhbHVlRGl2aXNvcmAgb3B0aW9uIGlzIHNldFxuICAgICAgICAgICAgICAgIHJhd1ZhbHVlICE9PSAnJyAmJiByYXdWYWx1ZSAhPT0gbnVsbCAmJiAvLyBEbyBub3QgbW9kaWZ5IHRoZSBgcmF3VmFsdWVgIGlmIGl0J3MgYW4gZW1wdHkgc3RyaW5nIG9yIG51bGxcbiAgICAgICAgICAgICAgICB0aGlzLl9pc1VzZXJNYW51YWxseUVkaXRpbmdUaGVWYWx1ZSgpKSB7IC8vIElmIHRoZSB1c2VyIGlzIG1hbnVhbGx5IGNoYW5naW5nIHRoZSBlbGVtZW50IHZhbHVlXG4gICAgICAgICAgICAgICAgdGhpcy5yYXdWYWx1ZSAvPSB0aGlzLnNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvcjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQnJvYWRjYXN0IHRoZSBgcmF3VmFsdWVNb2RpZmllZGAgZXZlbnQgc2luY2UgdGhlIGByYXdWYWx1ZWAgaGFzIGJlZW4gbW9kaWZpZWRcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMucmF3VmFsdWVNb2RpZmllZCwgdGhpcy5kb21FbGVtZW50LCB7XG4gICAgICAgICAgICAgICAgb2xkUmF3VmFsdWUsXG4gICAgICAgICAgICAgICAgbmV3UmF3VmFsdWU6IHRoaXMucmF3VmFsdWUsXG4gICAgICAgICAgICAgICAgaXNQcmlzdGluZSA6IHRoaXMuaXNQcmlzdGluZSh0cnVlKSxcbiAgICAgICAgICAgICAgICBlcnJvciAgICAgIDogbnVsbCxcbiAgICAgICAgICAgICAgICBhTkVsZW1lbnQgIDogdGhpcyxcbiAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAvLyBDaGFuZ2UgdGhlIGVsZW1lbnQgc3R5bGUgb3IgdXNlIHRoZSByZWxldmFudCBjYWxsYmFja3NcbiAgICAgICAgICAgIHRoaXMuX3BhcnNlU3R5bGVSdWxlcygpO1xuXG4gICAgICAgICAgICBpZiAoc2F2ZUNoYW5nZVRvSGlzdG9yeSkge1xuICAgICAgICAgICAgICAgIC8vIFNhdmUgaW4gdGhlIGhpc3RvcnkgdGhlIGxhc3Qga25vd24gcmF3IHZhbHVlIGFuZCBmb3JtYXR0ZWQgcmVzdWx0IHNlbGVjdGlvblxuICAgICAgICAgICAgICAgIHRoaXMuX2hpc3RvcnlUYWJsZUFkZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBnaXZlbiB2YWx1ZSBvbiB0aGUgRE9NIGVsZW1lbnQsIHdpdGhvdXQgYWZmZWN0aW5nIHRoZSBgcmF3VmFsdWVgLlxuICAgICAqIFRoaXMgc2VuZCBhbiAnYXV0b051bWVyaWM6Zm9ybWF0dGVkJyBldmVudCBpZiB0aGUgbmV3IHZhbHVlIGlzIGRpZmZlcmVudCB0aGFuIHRoZSBvbGQgb25lLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfSBuZXdFbGVtZW50VmFsdWVcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNlbmRGb3JtYXR0ZWRFdmVudCBJZiBzZXQgdG8gYHRydWVgLCB0aGVuIHRoZSBgQXV0b051bWVyaWMuZXZlbnRzLmZvcm1hdHRlZGAgZXZlbnQgaXMgc2VudCBpZiB0aGUgdmFsdWUgaGFzIGNoYW5nZWRcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2V0RWxlbWVudFZhbHVlKG5ld0VsZW1lbnRWYWx1ZSwgc2VuZEZvcm1hdHRlZEV2ZW50ID0gdHJ1ZSkge1xuICAgICAgICAvL1RPRE8gVXNlIGFuIGludGVybmFsIGF0dHJpYnV0ZSB0byB0cmFjayB0aGUgY3VycmVudCB2YWx1ZSBvZiB0aGUgZWxlbWVudCBgZm9ybWF0dGVkVmFsdWVgIChsaWtlIGl0cyBjb3VudGVycGFydCBgcmF3VmFsdWVgKS4gVGhpcyB3b3VsZCBhbGxvdyB1cyB0byBhdm9pZCBjYWxsaW5nIGBnZXRFbGVtZW50VmFsdWVgIG1hbnkgdGltZXNcbiAgICAgICAgY29uc3Qgb2xkRWxlbWVudFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCk7XG5cbiAgICAgICAgLy8gT25seSB1cGRhdGUgdGhlIHZhbHVlIGlmIGl0J3MgZGlmZmVyZW50IGZyb20gdGhlIGN1cnJlbnQgb25lXG4gICAgICAgIGlmIChuZXdFbGVtZW50VmFsdWUgIT09IG9sZEVsZW1lbnRWYWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5pbnRlcm5hbE1vZGlmaWNhdGlvbiA9IHRydWU7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50LCBuZXdFbGVtZW50VmFsdWUpO1xuICAgICAgICAgICAgdGhpcy5pbnRlcm5hbE1vZGlmaWNhdGlvbiA9IGZhbHNlO1xuXG4gICAgICAgICAgICBpZiAoc2VuZEZvcm1hdHRlZEV2ZW50KSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5mb3JtYXR0ZWQsIHRoaXMuZG9tRWxlbWVudCwge1xuICAgICAgICAgICAgICAgICAgICBvbGRWYWx1ZSAgIDogb2xkRWxlbWVudFZhbHVlLFxuICAgICAgICAgICAgICAgICAgICBuZXdWYWx1ZSAgIDogbmV3RWxlbWVudFZhbHVlLFxuICAgICAgICAgICAgICAgICAgICBvbGRSYXdWYWx1ZTogdGhpcy5yYXdWYWx1ZSxcbiAgICAgICAgICAgICAgICAgICAgbmV3UmF3VmFsdWU6IHRoaXMucmF3VmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIGlzUHJpc3RpbmUgOiB0aGlzLmlzUHJpc3RpbmUoZmFsc2UpLFxuICAgICAgICAgICAgICAgICAgICBlcnJvciAgICAgIDogbnVsbCxcbiAgICAgICAgICAgICAgICAgICAgYU5FbGVtZW50ICA6IHRoaXMsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGdpdmVuIHZhbHVlIG9uIHRoZSBET00gZWxlbWVudCwgYW5kIHRoZSByYXcgdmFsdWUgb24gYHRoaXMucmF3VmFsdWVgLCBpZiBib3RoIGFyZSBnaXZlbi5cbiAgICAgKiBJZiBvbmx5IG9uZSB2YWx1ZSBpcyBnaXZlbiwgdGhlbiBib3RoIHRoZSBET00gZWxlbWVudCB2YWx1ZSBhbmQgdGhlIHJhdyB2YWx1ZSBhcmUgc2V0IHdpdGggdGhhdCB2YWx1ZS5cbiAgICAgKiBUaGUgdGhpcmQgYXJndW1lbnQgYHNhdmVDaGFuZ2VUb0hpc3RvcnlgIGRlZmluZXMgaWYgdGhlIGNoYW5nZSBzaG91bGQgYmUgcmVjb3JkZWQgaW4gdGhlIGhpc3RvcnkgYXJyYXkuXG4gICAgICogTm90ZTogaWYgdGhlIHNlY29uZCBhcmd1bWVudCBgcmF3VmFsdWVgIGlzIGEgYm9vbGVhbiwgd2UgY29uc2lkZXIgdGhhdCBpcyByZWFsbHkgaXMgdGhlIGBzYXZlQ2hhbmdlVG9IaXN0b3J5YCBhcmd1bWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ3xudWxsfSBuZXdFbGVtZW50VmFsdWVcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd8bnVsbHxib29sZWFufSByYXdWYWx1ZVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2F2ZUNoYW5nZVRvSGlzdG9yeVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zZXRFbGVtZW50QW5kUmF3VmFsdWUobmV3RWxlbWVudFZhbHVlLCByYXdWYWx1ZSA9IG51bGwsIHNhdmVDaGFuZ2VUb0hpc3RvcnkgPSB0cnVlKSB7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwocmF3VmFsdWUpKSB7XG4gICAgICAgICAgICByYXdWYWx1ZSA9IG5ld0VsZW1lbnRWYWx1ZTtcbiAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ocmF3VmFsdWUpKSB7XG4gICAgICAgICAgICBzYXZlQ2hhbmdlVG9IaXN0b3J5ID0gcmF3VmFsdWU7XG4gICAgICAgICAgICByYXdWYWx1ZSA9IG5ld0VsZW1lbnRWYWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vWFhYIFRoZSBvcmRlciBoZXJlIGlzIGltcG9ydGFudCA7IHRoZSB2YWx1ZSBzaG91bGQgZmlyc3QgYmUgc2V0IG9uIHRoZSBlbGVtZW50LCB0aGVuIGFuZCBvbmx5IHRoZW4gd2Ugc2hvdWxkIHVwZGF0ZSB0aGUgcmF3IHZhbHVlXG4gICAgICAgIC8vIEluIHRoZSBgc2V0KClgIGZ1bmN0aW9uLCB3ZSBtYWtlIHN1cmUgdG8gY2FsbCBgX3NldFJhd1ZhbHVlYCAqYWZ0ZXIqIGBzZXRFbGVtZW50VmFsdWVgIHNvIHRoYXQgaWYgYF9zZXRSYXdWYWx1ZWAgY2FsbHMgYSBjYWxsYmFjayB0aGF0IG1vZGlmeSB0aGUgYHJhd1ZhbHVlYCwgdGhlbiB0aGUgbmV3IHZhbHVlIGlzIHNldCBjb3JyZWN0bHkgKGFmdGVyIGBzZXRFbGVtZW50VmFsdWVgIGJyaWVmbHkgc2V0IGl0cyB2YWx1ZSBmaXJzdClcbiAgICAgICAgdGhpcy5fc2V0RWxlbWVudFZhbHVlKG5ld0VsZW1lbnRWYWx1ZSk7XG4gICAgICAgIHRoaXMuX3NldFJhd1ZhbHVlKHJhd1ZhbHVlLCBzYXZlQ2hhbmdlVG9IaXN0b3J5KTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIG11bHRpcGxpZWQgcmF3IHZhbHVlIHdpdGggdGhlIGByYXdWYWx1ZURpdmlzb3JgLlxuICAgICAqIFRoaXMgaXMgdXNlZCB0byBkaXNwbGF5IGRpZmZlcmVudCB2YWx1ZXMgYmV0d2VlbiB0aGUgcmF3IGFuZCBmb3JtYXR0ZWQgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfG51bGx9IHJhd1ZhbHVlIFRoZSBudW1lcmljIHZhbHVlIGFzIHVuZGVyc3Rvb2QgYnkgSmF2YXNjcmlwdCBsaWtlIGEgYE51bWJlcmBcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfHN0cmluZ3xudWxsfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2dldFJhd1ZhbHVlVG9Gb3JtYXQocmF3VmFsdWUpIHtcbiAgICAgICAgbGV0IHJhd1ZhbHVlRm9yVGhlRWxlbWVudFZhbHVlO1xuICAgICAgICBpZiAoKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodGhpcy5zZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IpICYmIHRoaXMuc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yICE9PSAwKSAmJiAvLyBPbmx5IG11bHRpcGx5IGlmIHRoZSBgcmF3VmFsdWVEaXZpc29yYCBvcHRpb24gaXMgc2V0XG4gICAgICAgICAgICByYXdWYWx1ZSAhPT0gJycgJiYgcmF3VmFsdWUgIT09IG51bGwpIHsgLy8gRG8gbm90IG1vZGlmeSB0aGUgYHJhd1ZhbHVlYCBpZiBpdCdzIGFuIGVtcHR5IHN0cmluZyBvciBudWxsXG4gICAgICAgICAgICAvLyAhdGhpcy5faXNVc2VyTWFudWFsbHlFZGl0aW5nVGhlVmFsdWUoKSkgeyAvLyBJZiB0aGUgdXNlciBpcyBOT1QgbWFudWFsbHkgY2hhbmdpbmcgdGhlIGVsZW1lbnQgdmFsdWUsIGJ1dCB0aGF0IGlzIGRvbmUgcHJvZ3JhbW1hdGljYWxseVxuICAgICAgICAgICAgcmF3VmFsdWVGb3JUaGVFbGVtZW50VmFsdWUgPSByYXdWYWx1ZSAqIHRoaXMuc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmF3VmFsdWVGb3JUaGVFbGVtZW50VmFsdWUgPSByYXdWYWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByYXdWYWx1ZUZvclRoZUVsZW1lbnRWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiB0aGUgZ2l2ZW4gdmFsdWUgaGFzIGEgY29ycmVzcG9uZGluZyBrZXkgaW4gdGhlIGB2YWx1ZXNUb1N0cmluZ3NgIG9wdGlvbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IHZhbHVlXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIHN1Y2ggYSBrZXkgaXMgZm91bmQuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfY2hlY2tWYWx1ZXNUb1N0cmluZ3ModmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IuX2NoZWNrVmFsdWVzVG9TdHJpbmdzQXJyYXkodmFsdWUsIHRoaXMudmFsdWVzVG9TdHJpbmdzS2V5cyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgdGhlIGdpdmVuIHZhbHVlIGhhcyBhIGNvcnJlc3BvbmRpbmcga2V5IGluIHRoZSBgc3RyaW5nc0FycmF5YCBhcnJheS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ30ga2V5XG4gICAgICogQHBhcmFtIHthcnJheX0gc3RyaW5nc0FycmF5IEFycmF5IHdoZXJlIHRoZSBga2V5YCBpcyBjaGVja2VkIGFnYWluc3QgaXRzIGtleXNcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgc3VjaCBhIGtleSBpcyBmb3VuZC5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfY2hlY2tWYWx1ZXNUb1N0cmluZ3NBcnJheShrZXksIHN0cmluZ3NBcnJheSkge1xuICAgICAgICByZXR1cm4gQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KFN0cmluZyhrZXkpLCBzdHJpbmdzQXJyYXkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0YXRpYyBoZWxwZXIgZm9yIGNoZWNraW5nIGlmIHRoZSBnaXZlbiBga2V5YCBpcyBmb3VuZCBpbiB0aGUgc2V0dGluZ3MnIGB2YWx1ZXNUb1N0cmluZ3NgIG9wdGlvbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IGtleVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9jaGVja1ZhbHVlc1RvU3RyaW5nc1NldHRpbmdzKGtleSwgc2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX2NoZWNrVmFsdWVzVG9TdHJpbmdzQXJyYXkoa2V5LCBPYmplY3Qua2V5cyhzZXR0aW5ncy52YWx1ZXNUb1N0cmluZ3MpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdGF0aWMgaGVscGVyIGZvciBjaGVja2luZyBpZiB0aGUgZ2l2ZW4gYHZhbHVlYCBpcyBmb3VuZCBpbiB0aGUgc2V0dGluZ3MnIGB2YWx1ZXNUb1N0cmluZ3NgIG9wdGlvbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NoZWNrU3RyaW5nc1RvVmFsdWVzU2V0dGluZ3ModmFsdWUsIHNldHRpbmdzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9jaGVja1ZhbHVlc1RvU3RyaW5nc0FycmF5KHZhbHVlLCBPYmplY3QudmFsdWVzKHNldHRpbmdzLnZhbHVlc1RvU3RyaW5ncykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHVzZXIgaXMgY3VycmVudGx5IG1vZGlmeWluZyB0aGUgZWxlbWVudCB2YWx1ZSBtYW51YWxseS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2lzVXNlck1hbnVhbGx5RWRpdGluZ1RoZVZhbHVlKCkge1xuICAgICAgICAvLyByZXR1cm4gKHRoaXMuaXNGb2N1c2VkICYmIHRoaXMuaXNFZGl0aW5nKSB8fCB0aGlzLmlzV2hlZWxFdmVudCB8fCB0aGlzLmlzRHJvcEV2ZW50O1xuICAgICAgICByZXR1cm4gKHRoaXMuaXNGb2N1c2VkICYmIHRoaXMuaXNFZGl0aW5nKSB8fCB0aGlzLmlzRHJvcEV2ZW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4ZWN1dGUgdGhlIGdpdmVuIGNhbGxiYWNrIGZ1bmN0aW9uIHVzaW5nIHRoZSBnaXZlbiByZXN1bHQgYXMgaXRzIGZpcnN0IHBhcmFtZXRlciwgYW5kIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgYXMgaXRzIHNlY29uZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ3xBcnJheXxudWxsfSByZXN1bHRcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrIElmIGEgY2FsbGJhY2sgaXMgcGFzc2VkLCB0aGVuIHRoZSByZXN1bHQgaXMgcGFzc2VkIHRvIGl0IGFzIGl0cyBmaXJzdCBhcmd1bWVudCwgYW5kIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgaGFzIGl0cyBzZWNvbmRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9leGVjdXRlQ2FsbGJhY2socmVzdWx0LCBjYWxsYmFjaykge1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChjYWxsYmFjaykgJiYgQXV0b051bWVyaWNIZWxwZXIuaXNGdW5jdGlvbihjYWxsYmFjaykpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKHJlc3VsdCwgdGhpcyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcmlnZ2VyIHRoZSBnaXZlbiBldmVudCBvbiB0aGUgZ2l2ZW4gZWxlbWVudCB3aXRoIHRoZSBnaXZlbiBkZXRhaWwuXG4gICAgICogVGhpcyB0YWtlcyBpbnRvIGFjY291bnQgdGhlIGBldmVudEJ1YmJsZXNgIGFuZCBgZXZlbnRJc0NhbmNlbGFibGVgIG9wdGlvbnMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MRG9jdW1lbnR8RXZlbnRUYXJnZXR9IGVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gZGV0YWlsXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfdHJpZ2dlckV2ZW50KGV2ZW50TmFtZSwgZWxlbWVudCA9IGRvY3VtZW50LCBkZXRhaWwgPSBudWxsKSB7XG4gICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRyaWdnZXJFdmVudChldmVudE5hbWUsIGVsZW1lbnQsIGRldGFpbCwgdGhpcy5zZXR0aW5ncy5ldmVudEJ1YmJsZXMsIHRoaXMuc2V0dGluZ3MuZXZlbnRJc0NhbmNlbGFibGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFsaWFzIG9mIHRoZSBgZ2V0TnVtZXJpY1N0cmluZygpYCBmdW5jdGlvbi5cbiAgICAgKiBEZXZlbG9wZXJzIHNob3VsZCB1c2Ugb25lIG9mIHRoZSBtb3JlIGV4cGxpY2l0IGZ1bmN0aW9uIG5hbWVzIHRvIGdldCB3aGF0IHRoZXkgd2FudCA6XG4gICAgICogLSBhIG51bWVyaWMgc3RyaW5nIDogYGdldE51bWVyaWNTdHJpbmcoKWBcbiAgICAgKiAtIGEgZm9ybWF0dGVkIHN0cmluZyA6IGBnZXRGb3JtYXR0ZWQoKWBcbiAgICAgKiAtIGEgbnVtYmVyIDogYGdldE51bWJlcigpYCwgb3JcbiAgICAgKiAtIGEgbG9jYWxpemVkIG51bWVyaWMgc3RyaW5nIDogYGdldExvY2FsaXplZCgpYFxuICAgICAqXG4gICAgICogQHVzYWdlIGFuRWxlbWVudC5nZXQoKTtcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2sgSWYgYSBjYWxsYmFjayBpcyBwYXNzZWQsIHRoZW4gdGhlIHJlc3VsdCBpcyBwYXNzZWQgdG8gaXQgYXMgaXRzIGZpcnN0IGFyZ3VtZW50LCBhbmQgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBoYXMgaXRzIHNlY29uZFxuICAgICAqXG4gICAgICogQGRlcHJlY2F0ZWRcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gICAgICovXG4gICAgZ2V0KGNhbGxiYWNrID0gbnVsbCkge1xuICAgICAgICByZXR1cm4gdGhpcy5nZXROdW1lcmljU3RyaW5nKGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIHVuZm9ybWF0dGVkIHZhbHVlIGFzIGEgc3RyaW5nLlxuICAgICAqIFRoaXMgY2FuIGFsc28gcmV0dXJuIGBudWxsYCBpZiBgcmF3VmFsdWVgIGlzIG51bGwuXG4gICAgICpcbiAgICAgKiBAdXNhZ2UgYW5FbGVtZW50LmdldE51bWVyaWNTdHJpbmcoKTtcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2sgSWYgYSBjYWxsYmFjayBpcyBwYXNzZWQsIHRoZW4gdGhlIHJlc3VsdCBpcyBwYXNzZWQgdG8gaXQgYXMgaXRzIGZpcnN0IGFyZ3VtZW50LCBhbmQgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBoYXMgaXRzIHNlY29uZFxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfVxuICAgICAqL1xuICAgIGdldE51bWVyaWNTdHJpbmcoY2FsbGJhY2sgPSBudWxsKSB7XG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodGhpcy5yYXdWYWx1ZSkpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBBbHdheXMgcmV0dXJuIGEgbnVtZXJpYyBzdHJpbmdcbiAgICAgICAgICAgIC8vIFRoZSBmb2xsb3dpbmcgc3RhdGVtZW50IGdldHMgcmlkIG9mIHRoZSB0cmFpbGluZyB6ZXJvcyBpbiB0aGUgZGVjaW1hbCBwbGFjZXMgc2luY2UgdGhlIGN1cnJlbnQgbWV0aG9kIGRvZXMgbm90IHBhZCBkZWNpbWFsc1xuICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIudHJpbVBhZGRlZFplcm9zRnJvbURlY2ltYWxQbGFjZXModGhpcy5yYXdWYWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9leGVjdXRlQ2FsbGJhY2socmVzdWx0LCBjYWxsYmFjayk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIGN1cnJlbnQgZm9ybWF0dGVkIHZhbHVlIG9mIHRoZSBBdXRvTnVtZXJpYyBlbGVtZW50IGFzIGEgc3RyaW5nXG4gICAgICpcbiAgICAgKiBAdXNhZ2UgYW5FbGVtZW50LmdldEZvcm1hdHRlZCgpXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrIElmIGEgY2FsbGJhY2sgaXMgcGFzc2VkLCB0aGVuIHRoZSByZXN1bHQgaXMgcGFzc2VkIHRvIGl0IGFzIGl0cyBmaXJzdCBhcmd1bWVudCwgYW5kIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgaGFzIGl0cyBzZWNvbmRcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZ2V0Rm9ybWF0dGVkKGNhbGxiYWNrID0gbnVsbCkge1xuICAgICAgICBpZiAoISgndmFsdWUnIGluIHRoaXMuZG9tRWxlbWVudCB8fCAndGV4dENvbnRlbnQnIGluIHRoaXMuZG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSBgLnZhbHVlYCBvciBgLnRleHRDb250ZW50JyBleGlzdHMgYmVmb3JlIHRyeWluZyB0byBhY2Nlc3MgdGhvc2UgcHJvcGVydGllc1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcignVW5hYmxlIHRvIGdldCB0aGUgZm9ybWF0dGVkIHN0cmluZyBmcm9tIHRoZSBlbGVtZW50LicpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgIHRoaXMuX2V4ZWN1dGVDYWxsYmFjayhyZXN1bHQsIGNhbGxiYWNrKTtcblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgZWxlbWVudCB1bmZvcm1hdHRlZCB2YWx1ZSBhcyBhIHJlYWwgSmF2YXNjcmlwdCBudW1iZXIuXG4gICAgICogV2FybmluZzogVGhpcyBjYW4gbGVhZCB0byBwcmVjaXNpb24gcHJvYmxlbXMgd2l0aCBiaWcgbnVtYmVycyB0aGF0IHNob3VsZCBiZSBzdG9yZWQgYXMgc3RyaW5ncy5cbiAgICAgKlxuICAgICAqIEB1c2FnZSBhbkVsZW1lbnQuZ2V0TnVtYmVyKClcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2sgSWYgYSBjYWxsYmFjayBpcyBwYXNzZWQsIHRoZW4gdGhlIHJlc3VsdCBpcyBwYXNzZWQgdG8gaXQgYXMgaXRzIGZpcnN0IGFyZ3VtZW50LCBhbmQgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBoYXMgaXRzIHNlY29uZFxuICAgICAqXG4gICAgICogQHJldHVybnMge251bWJlcnxudWxsfVxuICAgICAqL1xuICAgIGdldE51bWJlcihjYWxsYmFjayA9IG51bGwpIHtcbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKHRoaXMucmF3VmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSB0aGlzLmNvbnN0cnVjdG9yLl90b0xvY2FsZSh0aGlzLmdldE51bWVyaWNTdHJpbmcoKSwgJ251bWJlcicsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fZXhlY3V0ZUNhbGxiYWNrKHJlc3VsdCwgY2FsbGJhY2spO1xuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgdW5mb3JtYXR0ZWQgdmFsdWUsIGJ1dCBmb2xsb3dpbmcgdGhlIGBvdXRwdXRGb3JtYXRgIHNldHRpbmcsIHdoaWNoIG1lYW5zIHRoZSBvdXRwdXQgY2FuIGVpdGhlciBiZSA6XG4gICAgICogLSBhIHN0cmluZyAodGhhdCBjb3VsZCBvciBjb3VsZCBub3QgcmVwcmVzZW50IGEgbnVtYmVyIChpZS4gXCIxMjM0NSw2Ny1cIikpLCBvclxuICAgICAqIC0gYSBwbGFpbiBudW1iZXIgKGlmIHRoZSBzZXR0aW5nICdudW1iZXInIGlzIHVzZWQpLlxuICAgICAqXG4gICAgICogQnkgZGVmYXVsdCB0aGUgcmV0dXJuZWQgdmFsdWVzIGFyZSBhbiBJU08gbnVtZXJpYyBzdHJpbmcgXCIxMjM0LjU2XCIgb3IgXCItMTIzNC41NlwiIHdoZXJlIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBpcyBhIHBlcmlvZC5cbiAgICAgKiBDaGVjayB0aGUgXCJvdXRwdXRGb3JtYXRcIiBvcHRpb24gZGVmaW5pdGlvbiBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQHVzYWdlIGFuRWxlbWVudC5nZXRMb2NhbGl6ZWQoKTtcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVsbHxzdHJpbmd8ZnVuY3Rpb259IGZvcmNlZE91dHB1dEZvcm1hdCBJZiBzZXQgdG8gc29tZXRoaW5nIGRpZmZlcmVudCB0aGFuIGBudWxsYCwgdGhlbiB0aGlzIGlzIHVzZWQgYXMgYW4gb3ZlcnJpZGluZyBvdXRwdXRGb3JtYXQgb3B0aW9uXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBnZXRMb2NhbGl6ZWQoZm9yY2VkT3V0cHV0Rm9ybWF0ID0gbnVsbCwgY2FsbGJhY2sgPSBudWxsKSB7XG4gICAgICAgIC8vIEZpcnN0LCBjaGVjayBpZiBvbmx5IGEgY2FsbGJhY2sgaGFzIGJlZW4gcGFzc2VkLCBhbmQgaWYgc28sIHNhbml0aXplIHRoZSBwYXJhbWV0ZXJzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGZvcmNlZE91dHB1dEZvcm1hdCkgJiYgQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sgPSBmb3JjZWRPdXRwdXRGb3JtYXQ7XG4gICAgICAgICAgICBmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVGhlbiBnZXQgdGhlIGxvY2FsaXplZCB2YWx1ZVxuICAgICAgICBsZXQgdmFsdWU7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0VtcHR5U3RyaW5nKHRoaXMucmF3VmFsdWUpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9ICcnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gSGVyZSBJIHVzZSBgdGhpcy5yYXdWYWx1ZWAgaW5zdGVhZCBvZiBgdGhpcy5nZXROdW1lcmljU3RyaW5nKClgIHNpbmNlIHRoZSBjdXJyZW50IGlucHV0IHZhbHVlIGNvdWxkIGJlIHVuZm9ybWF0dGVkIHdpdGggYSBsb2NhbGl6YXRpb24gKGllLiAnMTIzNDU2Nyw4OS0nKS5cbiAgICAgICAgICAgIC8vIEkgYWxzbyBjb252ZXJ0IHRoZSByYXdWYWx1ZSB0byBhIG51bWJlciwgdGhlbiBiYWNrIHRvIGEgc3RyaW5nIGluIG9yZGVyIHRvIGRyb3AgdGhlIGRlY2ltYWwgcGFydCBpZiB0aGUgcmF3VmFsdWUgaXMgYW4gaW50ZWdlci5cbiAgICAgICAgICAgIHZhbHVlID0gJycrTnVtYmVyKHRoaXMucmF3VmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHZhbHVlICE9PSAnJyAmJiBOdW1iZXIodmFsdWUpID09PSAwICYmIHRoaXMuc2V0dGluZ3MubGVhZGluZ1plcm8gIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8ua2VlcCkge1xuICAgICAgICAgICAgdmFsdWUgPSAnMCc7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgb3V0cHV0Rm9ybWF0VG9Vc2U7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoZm9yY2VkT3V0cHV0Rm9ybWF0KSkge1xuICAgICAgICAgICAgb3V0cHV0Rm9ybWF0VG9Vc2UgPSB0aGlzLnNldHRpbmdzLm91dHB1dEZvcm1hdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdFRvVXNlID0gZm9yY2VkT3V0cHV0Rm9ybWF0O1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVzdWx0ID0gdGhpcy5jb25zdHJ1Y3Rvci5fdG9Mb2NhbGUodmFsdWUsIG91dHB1dEZvcm1hdFRvVXNlLCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgdGhpcy5fZXhlY3V0ZUNhbGxiYWNrKHJlc3VsdCwgY2FsbGJhY2spO1xuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRm9yY2UgdGhlIGVsZW1lbnQgdG8gcmVmb3JtYXQgaXRzIHZhbHVlIGFnYWluIChqdXN0IGluIGNhc2UgdGhlIGZvcm1hdHRpbmcgaGFzIGJlZW4gbG9zdCkuXG4gICAgICogVGhpcyBjYW4gYmUgdXNlZCByaWdodCBhZnRlciBhIGZvcm0gc3VibWlzc2lvbiBmb3IgaW5zdGFuY2UgKGFmdGVyIGEgcHJldmlvdXMgY2FsbCB0byBgdW5mb3JtYXRgKS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlIGFuRWxlbWVudC5yZWZvcm1hdCgpXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgcmVmb3JtYXQoKSB7XG4gICAgICAgIC8vIGB0aGlzLnJhd1ZhbHVlYCBpcyB1c2VkIGluc3RlYWQgb2YgYHRoaXMuZG9tRWxlbWVudC52YWx1ZWAgYmVjYXVzZSB3aGVuIHRoZSBjb250ZW50IGlzIGB1bmZvcm1hdExvY2FsaXplZGAsIGl0IGNhbiBiZWNvbWUgYSBzdHJpbmcgdGhhdCBjYW5ub3QgYmUgY29udmVydGVkIHRvIGEgbnVtYmVyIGVhc2lseVxuICAgICAgICB0aGlzLnNldCh0aGlzLnJhd1ZhbHVlKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIGZvcm1hdHRpbmcgYW5kIGtlZXAgb25seSB0aGUgcmF3IHVuZm9ybWF0dGVkIHZhbHVlIGluIHRoZSBlbGVtZW50IChhcyBhIG51bWVyaWNTdHJpbmcpXG4gICAgICogTm90ZTogdGhpcyBpcyBsb29zZWx5IGJhc2VkIG9uIHRoZSBwcmV2aW91cyAndW5TZXQoKScgZnVuY3Rpb25cbiAgICAgKlxuICAgICAqIEJ5IGRlZmF1bHQsIHZhbHVlcyBhcmUgcmV0dXJuZWQgYXMgSVNPIG51bWVyaWMgc3RyaW5ncyAoaWUuIFwiMTIzNC41NlwiIG9yIFwiLTEyMzQuNTZcIiksIHdoZXJlIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBpcyBhIHBlcmlvZC5cbiAgICAgKiBAZXhhbXBsZSBhbkVsZW1lbnQudW5mb3JtYXQoKVxuICAgICAqXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIHVuZm9ybWF0KCkge1xuICAgICAgICB0aGlzLl9zZXRFbGVtZW50VmFsdWUodGhpcy5nZXROdW1lcmljU3RyaW5nKCkpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSB0aGUgZm9ybWF0dGluZyBhbmQga2VlcCBvbmx5IHRoZSBsb2NhbGl6ZWQgdW5mb3JtYXR0ZWQgdmFsdWUgaW4gdGhlIGVsZW1lbnQsIHdpdGggdGhlIG9wdGlvbiB0byBvdmVycmlkZSB0aGUgZGVmYXVsdCBvdXRwdXRGb3JtYXQgaWYgbmVlZGVkXG4gICAgICpcbiAgICAgKiBMb2NhbGUgZm9ybWF0cyBhcmUgc3VwcG9ydGVkIFwiMTIzNC41Ni1cIiBvciBcIjEyMzQsNTZcIiBvciBcIi0xMjM0LDU2IG9yIFwiMTIzNCw1Ni1cIiwgb3IgZXZlbiBwbGFpbiBudW1iZXJzLlxuICAgICAqIFRha2UgYSBsb29rIGF0IHRoZSBgb3V0cHV0Rm9ybWF0YCBvcHRpb24gZGVmaW5pdGlvbiBpbiB0aGUgZGVmYXVsdCBzZXR0aW5ncyBmb3IgbW9yZSBkZXRhaWxzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudWxsfHN0cmluZ30gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gYG51bGxgLCB0aGVuIHRoaXMgaXMgdXNlZCBhcyBhbiBvdmVycmlkaW5nIG91dHB1dEZvcm1hdCBvcHRpb25cbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgdW5mb3JtYXRMb2NhbGl6ZWQoZm9yY2VkT3V0cHV0Rm9ybWF0ID0gbnVsbCkge1xuICAgICAgICB0aGlzLl9zZXRFbGVtZW50VmFsdWUodGhpcy5nZXRMb2NhbGl6ZWQoZm9yY2VkT3V0cHV0Rm9ybWF0KSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgY3VycmVudCB2YWx1ZSBpcyB0aGUgc2FtZSBhcyB3aGVuIHRoZSBlbGVtZW50IGdvdCBpbml0aWFsaXplZC5cbiAgICAgKiBOb3RlOiBCeSBkZWZhdWx0LCB0aGlzIHJldHVybnMgYHRydWVgIGlmIHRoZSByYXcgdW5mb3JtYXR0ZWQgdmFsdWUgaXMgc3RpbGwgdGhlIHNhbWUgZXZlbiBpZiB0aGUgZm9ybWF0dGVkIG9uZSBoYXMgY2hhbmdlZCAoZHVlIHRvIGEgY29uZmlndXJhdGlvbiB1cGRhdGUgZm9yIGluc3RhbmNlKS5cbiAgICAgKiBJbiBvcmRlciB0byB0ZXN0IGlmIHRoZSBmb3JtYXR0ZWQgdmFsdWUgaXMgdGhlIHNhbWUgKHdoaWNoIG1lYW5zIG5laXRoZXIgdGhlIHJhdyB2YWx1ZSBub3IgdGhlIHNldHRpbmdzIGhhdmUgYmVlbiBjaGFuZ2VkKSwgdGhlbiB5b3UgbXVzdCBwYXNzIGBmYWxzZWAgYXMgaXRzIGFyZ3VtZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtib29sZWFufSBjaGVja09ubHlSYXdWYWx1ZSBJZiBzZXQgdG8gYHRydWVgLCB0aGUgcHJpc3RpbmUgdmFsdWUgaXMgZG9uZSBvbiB0aGUgcmF3IHVuZm9ybWF0dGVkIHZhbHVlLCBub3QgdGhlIGZvcm1hdHRlZCBvbmUuICBJZiBzZXQgdG8gYGZhbHNlYCwgdGhpcyBhbHNvIGNoZWNrcyB0aGF0IHRoZSBmb3JtYXR0ZWQgdmFsdWUgaGFzbid0IGNoYW5nZWQuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgaXNQcmlzdGluZShjaGVja09ubHlSYXdWYWx1ZSA9IHRydWUpIHtcbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKGNoZWNrT25seVJhd1ZhbHVlKSB7XG4gICAgICAgICAgICByZXN1bHQgPSB0aGlzLmluaXRpYWxWYWx1ZSA9PT0gdGhpcy5nZXROdW1lcmljU3RyaW5nKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSB0aGlzLmluaXRpYWxWYWx1ZUh0bWxBdHRyaWJ1dGUgPT09IHRoaXMuZ2V0Rm9ybWF0dGVkKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbGVjdCB0aGUgZm9ybWF0dGVkIGVsZW1lbnQgY29udGVudCwgYmFzZWQgb24gdGhlIGBzZWxlY3ROdW1iZXJPbmx5YCBvcHRpb25cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBzZWxlY3QoKSB7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnNlbGVjdE51bWJlck9ubHkpIHtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0TnVtYmVyKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLl9kZWZhdWx0U2VsZWN0QWxsKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWxlY3QgdGhlIHdob2xlIGVsZW1lbnQgY29udGVudCAoaW5jbHVkaW5nIHRoZSBjdXJyZW5jeSBzeW1ib2wpLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2RlZmF1bHRTZWxlY3RBbGwoKSB7XG4gICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24odGhpcy5kb21FbGVtZW50LCAwLCBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KS5sZW5ndGgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbGVjdCBvbmx5IHRoZSBudW1iZXJzIGluIHRoZSBmb3JtYXR0ZWQgZWxlbWVudCBjb250ZW50LCBsZWF2aW5nIG91dCB0aGUgY3VycmVuY3kgc3ltYm9sLCB3aGF0ZXZlciB0aGUgdmFsdWUgb2YgdGhlIGBzZWxlY3ROdW1iZXJPbmx5YCBvcHRpb25cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBzZWxlY3ROdW1iZXIoKSB7XG4gICAgICAgIC8vVE9ETyBNYWtlIHN1cmUgdGhlIHNlbGVjdGlvbiBpcyBvayB3aGVuIHNob3dQb3NpdGl2ZVNpZ24gaXMgc2V0IHRvIGB0cnVlYCAoc2VsZWN0IHRoZSBuZWdhdGl2ZSBzaWduLCBidXQgbm90IHRoZSBwb3NpdGl2ZSBvbmUpXG4gICAgICAgIGNvbnN0IHVuZm9ybWF0dGVkVmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgY29uc3QgdmFsdWVMZW4gPSB1bmZvcm1hdHRlZFZhbHVlLmxlbmd0aDtcbiAgICAgICAgY29uc3QgY3VycmVuY3lTeW1ib2xTaXplID0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGg7XG4gICAgICAgIGNvbnN0IGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudDtcbiAgICAgICAgY29uc3QgbmVnTGVuID0gKCFBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKHVuZm9ybWF0dGVkVmFsdWUsIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSk/MDoxO1xuICAgICAgICBjb25zdCBzdWZmaXhUZXh0TGVuID0gdGhpcy5zZXR0aW5ncy5zdWZmaXhUZXh0Lmxlbmd0aDtcblxuICAgICAgICBsZXQgc3RhcnQ7XG4gICAgICAgIGlmIChjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgpIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gMDtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQgJiZcbiAgICAgICAgICAgIG5lZ0xlbiA9PT0gMSAmJiBjdXJyZW5jeVN5bWJvbFNpemUgPiAwKSB7XG4gICAgICAgICAgICBzdGFydCA9IGN1cnJlbmN5U3ltYm9sU2l6ZSArIDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzdGFydCA9IGN1cnJlbmN5U3ltYm9sU2l6ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBlbmQ7XG4gICAgICAgIGlmIChjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXgpIHtcbiAgICAgICAgICAgIGVuZCA9IHZhbHVlTGVuIC0gc3VmZml4VGV4dExlbjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkge1xuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0OlxuICAgICAgICAgICAgICAgICAgICBlbmQgPSB2YWx1ZUxlbiAtIChzdWZmaXhUZXh0TGVuICsgY3VycmVuY3lTeW1ib2xTaXplKTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnJpZ2h0OlxuICAgICAgICAgICAgICAgICAgICBpZiAoY3VycmVuY3lTeW1ib2xTaXplID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgZW5kID0gdmFsdWVMZW4gLSAoY3VycmVuY3lTeW1ib2xTaXplICsgbmVnTGVuICsgc3VmZml4VGV4dExlbik7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlbmQgPSB2YWx1ZUxlbiAtIChjdXJyZW5jeVN5bWJvbFNpemUgKyBzdWZmaXhUZXh0TGVuKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICAgICAgZW5kID0gdmFsdWVMZW4gLSAoY3VycmVuY3lTeW1ib2xTaXplICsgc3VmZml4VGV4dExlbik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50U2VsZWN0aW9uKHRoaXMuZG9tRWxlbWVudCwgc3RhcnQsIGVuZCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VsZWN0IG9ubHkgdGhlIGludGVnZXIgcGFydCBpbiB0aGUgZm9ybWF0dGVkIGVsZW1lbnQgY29udGVudCwgd2hhdGV2ZXIgdGhlIHZhbHVlIG9mIGBzZWxlY3ROdW1iZXJPbmx5YFxuICAgICAqXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIHNlbGVjdEludGVnZXIoKSB7XG4gICAgICAgIGxldCBzdGFydCA9IDA7XG4gICAgICAgIGNvbnN0IGlzUG9zaXRpdmUgPSB0aGlzLnJhd1ZhbHVlID49IDA7XG5cbiAgICAgICAgLy8gTmVnYXRpdmUgb3IgcG9zaXRpdmUgc2lnbiwgaWYgYW55XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCB8fFxuICAgICAgICAgICAgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4ICYmXG4gICAgICAgICAgICAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXggfHxcbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSkpKSB7XG4gICAgICAgICAgICBpZiAoKHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiBpc1Bvc2l0aXZlKSB8fCAgLy8gVGhpcyBvbmx5IGV4Y2x1ZGUgdGhlIHBvc2l0aXZlIHNpZ24gZnJvbSBiZWluZyBzZWxlY3RlZFxuICAgICAgICAgICAgICAgICghaXNQb3NpdGl2ZSAmJiB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCAmJiB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQpKSB7IC8vIEFuZCB0aGlzIGV4Y2x1ZGUgdGhlIG5lZ2F0aXZlIHNpZ24gZnJvbSBiZWluZyBzZWxlY3RlZCBpbiB0aGlzIHNwZWNpYWwgY2FzZSA6ICct4oKsIDEuMjM0LDU3c3VmZml4VGV4dCdcbiAgICAgICAgICAgICAgICBzdGFydCA9IHN0YXJ0ICsgMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEN1cnJlbmN5IHN5bWJvbFxuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXgpIHtcbiAgICAgICAgICAgIHN0YXJ0ID0gc3RhcnQgKyB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgc2VsZWN0aW9uIGVuZCBwb3NpdGlvblxuICAgICAgICBjb25zdCBlbGVtZW50VmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgbGV0IGVuZCA9IGVsZW1lbnRWYWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcik7XG4gICAgICAgIGlmIChlbmQgPT09IC0xKSB7XG4gICAgICAgICAgICAvLyBObyBkZWNpbWFsIGNoYXJhY3RlciBmb3VuZFxuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4KSB7XG4gICAgICAgICAgICAgICAgZW5kID0gZWxlbWVudFZhbHVlLmxlbmd0aCAtIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBlbmQgPSBlbGVtZW50VmFsdWUubGVuZ3RoO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBUcmFpbGluZyBuZWdhdGl2ZSBzaWduXG4gICAgICAgICAgICBpZiAoIWlzUG9zaXRpdmUgJiZcbiAgICAgICAgICAgICAgICAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXggfHxcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCkpIHtcbiAgICAgICAgICAgICAgICBlbmQgPSBlbmQgLSAxO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBBdm9pZCBzZWxlY3RpbmcgdGhlIHN1ZmZpeCB0ZXN0XG4gICAgICAgICAgICBlbmQgPSBlbmQgLSB0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbih0aGlzLmRvbUVsZW1lbnQsIHN0YXJ0LCBlbmQpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbGVjdCBvbmx5IHRoZSBkZWNpbWFsIHBhcnQgaW4gdGhlIGZvcm1hdHRlZCBlbGVtZW50IGNvbnRlbnQsIHdoYXRldmVyIHRoZSB2YWx1ZSBvZiBgc2VsZWN0TnVtYmVyT25seWBcbiAgICAgKiBNdWx0aXBsZSBjYXNlcyBhcmUgcG9zc2libGUgOlxuICAgICAqICsxLjIzNCw1N3N1ZmZpeFRleHRcbiAgICAgKlxuICAgICAqIOKCrCArMS4yMzQsNTdzdWZmaXhUZXh0XG4gICAgICogK+KCrCAxLjIzNCw1N3N1ZmZpeFRleHRcbiAgICAgKiDigqwgMS4yMzQsNTcrc3VmZml4VGV4dFxuICAgICAqXG4gICAgICogMS4yMzQsNTcrIOKCrHN1ZmZpeFRleHRcbiAgICAgKiAxLjIzNCw1NyDigqwrc3VmZml4VGV4dFxuICAgICAqICsxLjIzNCw1NyDigqxzdWZmaXhUZXh0XG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgc2VsZWN0RGVjaW1hbCgpIHtcbiAgICAgICAgbGV0IHN0YXJ0ID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCkuaW5kZXhPZih0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpO1xuICAgICAgICBsZXQgZW5kO1xuXG4gICAgICAgIGlmIChzdGFydCA9PT0gLTEpIHtcbiAgICAgICAgICAgIC8vIFRoZSBkZWNpbWFsIGNoYXJhY3RlciBoYXMgbm90IGJlZW4gZm91bmQsIHdlIGRlc2VsZWN0IGFsbFxuICAgICAgICAgICAgc3RhcnQgPSAwO1xuICAgICAgICAgICAgZW5kID0gMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEEgZGVjaW1hbCBjaGFyYWN0ZXIgaGFzIGJlZW4gZm91bmRcbiAgICAgICAgICAgIHN0YXJ0ID0gc3RhcnQgKyAxOyAvLyBXZSBhZGQgMSB0byBleGNsdWRlIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBmcm9tIHRoZSBzZWxlY3Rpb25cblxuICAgICAgICAgICAgbGV0IGRlY2ltYWxDb3VudDtcbiAgICAgICAgICAgIGlmICh0aGlzLmlzRm9jdXNlZCkge1xuICAgICAgICAgICAgICAgIGRlY2ltYWxDb3VudCA9IHRoaXMuc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZGVjaW1hbENvdW50ID0gdGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXI7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGVuZCA9IHN0YXJ0ICsgTnVtYmVyKGRlY2ltYWxDb3VudCk7XG4gICAgICAgIH1cblxuICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50U2VsZWN0aW9uKHRoaXMuZG9tRWxlbWVudCwgc3RhcnQsIGVuZCk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBET00gZWxlbWVudCByZWZlcmVuY2Ugb2YgdGhlIGF1dG9OdW1lcmljLW1hbmFnZWQgZWxlbWVudFxuICAgICAqXG4gICAgICogQHJldHVybnMge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9XG4gICAgICovXG4gICAgbm9kZSgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZG9tRWxlbWVudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIERPTSBlbGVtZW50IHJlZmVyZW5jZSBvZiB0aGUgcGFyZW50IG5vZGUgb2YgdGhlIGF1dG9OdW1lcmljLW1hbmFnZWQgZWxlbWVudFxuICAgICAqXG4gICAgICogQHJldHVybnMge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR8Tm9kZX1cbiAgICAgKi9cbiAgICBwYXJlbnQoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRvbUVsZW1lbnQucGFyZW50Tm9kZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEZXRhY2ggdGhlIGN1cnJlbnQgQXV0b051bWVyaWMgZWxlbWVudCBmcm9tIHRoZSBzaGFyZWQgbG9jYWwgJ2luaXQnIGxpc3QuXG4gICAgICogVGhpcyBtZWFucyBhbnkgY2hhbmdlcyBtYWRlIG9uIHRoYXQgbG9jYWwgc2hhcmVkIGxpc3Qgd2lsbCBub3QgYmUgdHJhbnNtaXR0ZWQgdG8gdGhhdCBlbGVtZW50IGFueW1vcmUuXG4gICAgICogTm90ZSA6IFRoZSB1c2VyIGNhbiBwcm92aWRlIGFub3RoZXIgQXV0b051bWVyaWMgZWxlbWVudCwgYW5kIGRldGFjaCB0aGlzIG9uZSBpbnN0ZWFkIG9mIHRoZSBjdXJyZW50IG9uZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QXV0b051bWVyaWN9IG90aGVyQW5FbGVtZW50XG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGRldGFjaChvdGhlckFuRWxlbWVudCA9IG51bGwpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgbGV0IGRvbUVsZW1lbnRUb0RldGFjaDtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3RoZXJBbkVsZW1lbnQpKSB7XG4gICAgICAgICAgICBkb21FbGVtZW50VG9EZXRhY2ggPSBvdGhlckFuRWxlbWVudC5ub2RlKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkb21FbGVtZW50VG9EZXRhY2ggPSB0aGlzLmRvbUVsZW1lbnQ7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9yZW1vdmVGcm9tTG9jYWxMaXN0KGRvbUVsZW1lbnRUb0RldGFjaCk7IC8vRklYTUUgV2hhdCBoYXBwZW5zIGlmIHRoZSBzZWxlY3RlZCBkb20gZWxlbWVudCBkb2VzIG5vdCBleGlzdCBpbiB0aGUgbGlzdD9cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBdHRhY2ggdGhlIGdpdmVuIEF1dG9OdW1lcmljIGVsZW1lbnQgdG8gdGhlIHNoYXJlZCBsb2NhbCAnaW5pdCcgbGlzdC5cbiAgICAgKiBXaGVuIGRvaW5nIHRoYXQsIGJ5IGRlZmF1bHQgdGhlIERPTSBjb250ZW50IGlzIGxlZnQgdW50b3VjaGVkLlxuICAgICAqIFRoZSB1c2VyIGNhbiBmb3JjZSBhIHJlZm9ybWF0IHdpdGggdGhlIG5ldyBzaGFyZWQgbGlzdCBvcHRpb25zIGJ5IHBhc3NpbmcgYSBzZWNvbmQgYXJndW1lbnQgdG8gYHRydWVgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtBdXRvTnVtZXJpY30gb3RoZXJBbkVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHJlRm9ybWF0XG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGF0dGFjaChvdGhlckFuRWxlbWVudCwgcmVGb3JtYXQgPSB0cnVlKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIHRoaXMuX2FkZFRvTG9jYWxMaXN0KG90aGVyQW5FbGVtZW50Lm5vZGUoKSk7IC8vRklYTUUgU2hvdWxkIHdlIG1ha2Ugc3VyZSB0aGUgZWxlbWVudCBpcyBub3QgYWxyZWFkeSBpbiB0aGUgbGlzdD9cbiAgICAgICAgaWYgKHJlRm9ybWF0KSB7XG4gICAgICAgICAgICBvdGhlckFuRWxlbWVudC51cGRhdGUodGhpcy5zZXR0aW5ncyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JtYXQgYW5kIHJldHVybiB0aGUgZ2l2ZW4gdmFsdWUsIG9yIHNldCB0aGUgZm9ybWF0dGVkIHZhbHVlIGludG8gdGhlIGdpdmVuIERPTSBlbGVtZW50IGlmIG9uZSBpcyBwYXNzZWQgYXMgYW4gYXJndW1lbnQuXG4gICAgICogQnkgZGVmYXVsdCwgdGhpcyB1c2UgdGhlIGN1cnJlbnQgZWxlbWVudCBzZXR0aW5ncy5cbiAgICAgKiBUaGUgdXNlciBjYW4gb3ZlcnJpZGUgYW55IG9wdGlvbiBvZiBpdHMgY2hvb3NpbmcgYnkgcGFzc2luZyBhbiBvcHRpb24gb2JqZWN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudH0gdmFsdWVPckVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge251bGx8b2JqZWN0fSBvcHRpb25PdmVycmlkZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH1cbiAgICAgKi9cbiAgICBmb3JtYXRPdGhlcih2YWx1ZU9yRWxlbWVudCwgb3B0aW9uT3ZlcnJpZGUgPSBudWxsKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIHJldHVybiB0aGlzLl9mb3JtYXRPclVuZm9ybWF0T3RoZXIodHJ1ZSwgdmFsdWVPckVsZW1lbnQsIG9wdGlvbk92ZXJyaWRlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbmZvcm1hdCBhbmQgcmV0dXJuIHRoZSByYXcgbnVtZXJpYyBzdHJpbmcgY29ycmVzcG9uZGluZyB0byB0aGUgZ2l2ZW4gdmFsdWUsIG9yIGRpcmVjdGx5IHNldCB0aGUgdW5mb3JtYXR0ZWQgdmFsdWUgaW50byB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgaWYgb25lIGlzIHBhc3NlZCBhcyBhbiBhcmd1bWVudC5cbiAgICAgKiBCeSBkZWZhdWx0LCB0aGlzIHVzZSB0aGUgY3VycmVudCBlbGVtZW50IHNldHRpbmdzLlxuICAgICAqIFRoZSB1c2VyIGNhbiBvdmVycmlkZSBhbnkgb3B0aW9uIG9mIGl0cyBjaG9vc2luZyBieSBwYXNzaW5nIGFuIG9wdGlvbiBvYmplY3QuXG5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBzdHJpbmdPckVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge251bGx8b2JqZWN0fSBvcHRpb25PdmVycmlkZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH1cbiAgICAgKi9cbiAgICB1bmZvcm1hdE90aGVyKHN0cmluZ09yRWxlbWVudCwgb3B0aW9uT3ZlcnJpZGUgPSBudWxsKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIHJldHVybiB0aGlzLl9mb3JtYXRPclVuZm9ybWF0T3RoZXIoZmFsc2UsIHN0cmluZ09yRWxlbWVudCwgb3B0aW9uT3ZlcnJpZGUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0aGF0IGVpdGhlciBmb3JtYXQgb3IgdW5mb3JtYXQgdGhlIHZhbHVlIG9mIGFub3RoZXIgZWxlbWVudC5cbiAgICAgKlxuICAgICAqIC0gRm9ybWF0IGFuZCByZXR1cm4gdGhlIGdpdmVuIHZhbHVlLCBvciBzZXQgdGhlIGZvcm1hdHRlZCB2YWx1ZSBpbnRvIHRoZSBnaXZlbiBET00gZWxlbWVudCBpZiBvbmUgaXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LlxuICAgICAqIC0gVW5mb3JtYXQgYW5kIHJldHVybiB0aGUgcmF3IG51bWVyaWMgc3RyaW5nIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGdpdmVuIHZhbHVlLCBvciBkaXJlY3RseSBzZXQgdGhlIHVuZm9ybWF0dGVkIHZhbHVlIGludG8gdGhlIGdpdmVuIERPTSBlbGVtZW50IGlmIG9uZSBpcyBwYXNzZWQgYXMgYW4gYXJndW1lbnQuXG4gICAgICpcbiAgICAgKiBCeSBkZWZhdWx0LCB0aGlzIHVzZSB0aGUgY3VycmVudCBlbGVtZW50IHNldHRpbmdzLlxuICAgICAqIFRoZSB1c2VyIGNhbiBvdmVycmlkZSBhbnkgb3B0aW9uIG9mIGl0cyBjaG9vc2luZyBieSBwYXNzaW5nIGFuIG9wdGlvbiBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzRm9ybWF0dGluZyBJZiBzZXQgdG8gYHRydWVgLCB0aGVuIHRoZSBtZXRob2QgZm9ybWF0cywgb3RoZXJ3aXNlIGlmIHNldCB0byBgZmFsc2VgLCBpdCB1bmZvcm1hdHNcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd8SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudH0gdmFsdWVPclN0cmluZ09yRWxlbWVudFxuICAgICAqIEBwYXJhbSB7bnVsbHxvYmplY3R9IG9wdGlvbk92ZXJyaWRlXG4gICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2Zvcm1hdE9yVW5mb3JtYXRPdGhlcihpc0Zvcm1hdHRpbmcsIHZhbHVlT3JTdHJpbmdPckVsZW1lbnQsIG9wdGlvbk92ZXJyaWRlID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICAvLyBJZiB0aGUgdXNlciB3YW50cyB0byBvdmVycmlkZSB0aGUgY3VycmVudCBlbGVtZW50IHNldHRpbmdzIHRlbXBvcmFyaWx5XG4gICAgICAgIGxldCBzZXR0aW5nc1RvVXNlO1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25PdmVycmlkZSkpIHtcbiAgICAgICAgICAgIHNldHRpbmdzVG9Vc2UgPSB0aGlzLl9jbG9uZUFuZE1lcmdlU2V0dGluZ3Mob3B0aW9uT3ZlcnJpZGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2V0dGluZ3NUb1VzZSA9IHRoaXMuc2V0dGluZ3M7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGVuIHRoZSB1bmZvcm1hdHRpbmcgaXMgZG9uZS4uLlxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNFbGVtZW50KHZhbHVlT3JTdHJpbmdPckVsZW1lbnQpKSB7XG4gICAgICAgICAgICAvLyAuLi5laXRoZXIgZGlyZWN0bHkgb24gdGhlIERPTSBlbGVtZW50IHZhbHVlXG4gICAgICAgICAgICBjb25zdCBlbGVtZW50VmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodmFsdWVPclN0cmluZ09yRWxlbWVudCk7XG4gICAgICAgICAgICBpZiAoaXNGb3JtYXR0aW5nKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWMuZm9ybWF0KGVsZW1lbnRWYWx1ZSwgc2V0dGluZ3NUb1VzZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpYy51bmZvcm1hdChlbGVtZW50VmFsdWUsIHNldHRpbmdzVG9Vc2UpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50VmFsdWUodmFsdWVPclN0cmluZ09yRWxlbWVudCwgcmVzdWx0KTsgLy9UT0RPIFVzZSBgdW5mb3JtYXRBbmRTZXRgIGFuZCBgZm9ybWF0QW5kU2V0YGluc3RlYWRcblxuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAuLi5vciBvbiB0aGUgZ2l2ZW4gdmFsdWVcbiAgICAgICAgaWYgKGlzRm9ybWF0dGluZykge1xuICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWMuZm9ybWF0KHZhbHVlT3JTdHJpbmdPckVsZW1lbnQsIHNldHRpbmdzVG9Vc2UpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWMudW5mb3JtYXQodmFsdWVPclN0cmluZ09yRWxlbWVudCwgc2V0dGluZ3NUb1VzZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVzZSB0aGUgY3VycmVudCBBdXRvTnVtZXJpYyBlbGVtZW50IHNldHRpbmdzIHRvIGluaXRpYWxpemUgdGhlIERPTSBlbGVtZW50KHMpIGdpdmVuIGFzIGEgcGFyYW1ldGVyLlxuICAgICAqIERvaW5nIHNvIHdpbGwgKmxpbmsqIHRoZSBBdXRvTnVtZXJpYyBlbGVtZW50cyB0b2dldGhlciBzaW5jZSB0aGV5IHdpbGwgc2hhcmUgdGhlIHNhbWUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0LlxuICAgICAqIChjZi4gcHJvdG90eXBlIHBhdHRlcm4gOiBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9Qcm90b3R5cGVfcGF0dGVybilcbiAgICAgKlxuICAgICAqIFlvdSBjYW4gYGluaXRgIGVpdGhlciBhIHNpbmdsZSBET00gZWxlbWVudCAoaW4gdGhhdCBjYXNlIGFuIEF1dG9OdW1lcmljIG9iamVjdCB3aWxsIGJlIHJldHVybmVkKSwgb3IgYW4gYXJyYXkgb2YgRE9NIGVsZW1lbnRzIG9yIGEgc3RyaW5nIHRoYXQgd2lsbCBiZSB1c2VkIGFzIGEgQ1NTIHNlbGVjdG9yLiBJbiB0aGUgbGF0dGVyIGNhc2VzLCBhbiBhcnJheSBvZiBBdXRvTnVtZXJpYyBvYmplY3RzIHdpbGwgdGhlbiBiZSByZXR1cm5lZCAob3IgYW4gZW1wdHkgYXJyYXkgaWYgbm90aGluZyBnZXRzIHNlbGVjdGVkIGJ5IHRoZSBDU1Mgc2VsZWN0b3IpLlxuICAgICAqXG4gICAgICogVXNlIGNhc2UgOiBPbmNlIHlvdSBoYXZlIGFuIEF1dG9OdW1lcmljIGVsZW1lbnQgYWxyZWFkeSBzZXR1cCBjb3JyZWN0bHkgd2l0aCB0aGUgcmlnaHQgb3B0aW9ucywgeW91IGNhbiB1c2UgaXQgYXMgbWFueSB0aW1lcyB5b3Ugd2FudCB0byBpbml0aWFsaXplIGFzIG1hbnkgb3RoZXIgRE9NIGVsZW1lbnRzIGFzIG5lZWRlZC5cbiAgICAgKiBOb3RlIDogdGhpcyB3b3JrcyBvbmx5IG9uIGVsZW1lbnRzIHRoYXQgY2FuIGJlIG1hbmFnZWQgYnkgYXV0b051bWVyaWMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR8QXJyYXk8SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudD58c3RyaW5nfSBkb21FbGVtZW50T3JBcnJheU9yU3RyaW5nXG4gICAgICogQHBhcmFtIHtib29sZWFufSBhdHRhY2hlZCBJZiBzZXQgdG8gYGZhbHNlYCwgdGhlbiB0aGUgbmV3bHkgZ2VuZXJhdGVkIEF1dG9OdW1lcmljIGVsZW1lbnQgd2lsbCBub3Qgc2hhcmUgdGhlIHNhbWUgbG9jYWwgZWxlbWVudCBsaXN0XG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfFtBdXRvTnVtZXJpY119XG4gICAgICovXG4gICAgaW5pdChkb21FbGVtZW50T3JBcnJheU9yU3RyaW5nLCBhdHRhY2hlZCA9IHRydWUpIHtcbiAgICAgICAgbGV0IHJldHVybkFTaW5nbGVBdXRvTnVtZXJpY09iamVjdCA9IGZhbHNlOyAvLyBCeSBkZWZhdWx0LCB0aGlzIGZ1bmN0aW9uIHJldHVybnMgYW4gYXJyYXkgb2YgQXV0b051bWVyaWMgb2JqZWN0c1xuICAgICAgICBsZXQgZG9tRWxlbWVudHNBcnJheSA9IFtdO1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcoZG9tRWxlbWVudE9yQXJyYXlPclN0cmluZykpIHtcbiAgICAgICAgICAgIGRvbUVsZW1lbnRzQXJyYXkgPSBbLi4uIGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoZG9tRWxlbWVudE9yQXJyYXlPclN0cmluZyldOyAvLyBDb252ZXJ0IGEgTm9kZUxpc3QgdG8gYW4gQXJyYXlcbiAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0VsZW1lbnQoZG9tRWxlbWVudE9yQXJyYXlPclN0cmluZykpIHtcbiAgICAgICAgICAgIGRvbUVsZW1lbnRzQXJyYXkucHVzaChkb21FbGVtZW50T3JBcnJheU9yU3RyaW5nKTtcbiAgICAgICAgICAgIHJldHVybkFTaW5nbGVBdXRvTnVtZXJpY09iamVjdCA9IHRydWU7IC8vIFNwZWNpYWwgY2FzZSB3aGVuIG9ubHkgb25lIERPTSBlbGVtZW50IGlzIHBhc3NlZCBhcyBhIHBhcmFtZXRlclxuICAgICAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzQXJyYXkoZG9tRWxlbWVudE9yQXJyYXlPclN0cmluZykpIHtcbiAgICAgICAgICAgIGRvbUVsZW1lbnRzQXJyYXkgPSBkb21FbGVtZW50T3JBcnJheU9yU3RyaW5nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGdpdmVuIHBhcmFtZXRlcnMgdG8gdGhlICdpbml0JyBmdW5jdGlvbiBhcmUgaW52YWxpZC5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkb21FbGVtZW50c0FycmF5Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgTm8gdmFsaWQgRE9NIGVsZW1lbnRzIHdlcmUgZ2l2ZW4gaGVuY2Ugbm8gQXV0b051bWVyaWMgb2JqZWN0IHdlcmUgaW5zdGFudGlhdGVkLmAsIHRydWUpO1xuXG4gICAgICAgICAgICByZXR1cm4gW107XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBjdXJyZW50TG9jYWxMaXN0ID0gdGhpcy5fZ2V0TG9jYWxMaXN0KCk7XG4gICAgICAgIGNvbnN0IGF1dG9OdW1lcmljT2JqZWN0c0FycmF5ID0gW107XG5cbiAgICAgICAgLy8gSW5zdGFudGlhdGUgKGFuZCBsaW5rIGRlcGVuZGluZyBvbiBgYXR0YWNoZWRgKSBlYWNoIEF1dG9OdW1lcmljIG9iamVjdHNcbiAgICAgICAgZG9tRWxlbWVudHNBcnJheS5mb3JFYWNoKGRvbUVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgLy8gSW5pdGlhbGl6ZSB0aGUgbmV3IEF1dG9OdW1lcmljIGVsZW1lbnRcbiAgICAgICAgICAgIGNvbnN0IG9yaWdpbmFsQ3JlYXRlTG9jYWxMaXN0U2V0dGluZyA9IHRoaXMuc2V0dGluZ3MuY3JlYXRlTG9jYWxMaXN0O1xuICAgICAgICAgICAgaWYgKGF0dGFjaGVkKSB7XG4gICAgICAgICAgICAgICAgLy8gVGVtcG9yYXJ5IHZhcmlhYmxlIHRvIGtub3cgaWYgd2Ugc2hvdWxkIGNyZWF0ZSB0aGUgbG9jYWwgbGlzdCBkdXJpbmcgdGhlIGluaXRpYWxpemF0aW9uIChzaW5jZSB3ZSdsbCByZW1vdmUgaXQgYWZ0ZXJ3YXJkcylcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmNyZWF0ZUxvY2FsTGlzdCA9IGZhbHNlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBuZXdBdXRvTnVtZXJpY0VsZW1lbnQgPSAgbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZShkb21FbGVtZW50KSwgdGhpcy5zZXR0aW5ncyk7XG5cbiAgICAgICAgICAgIC8vIFNldCB0aGUgY29tbW9uIHNoYXJlZCBsb2NhbCBsaXN0IGlmIG5lZWRlZFxuICAgICAgICAgICAgLy8gSWYgdGhlIHVzZXIgd2FudHMgdG8gY3JlYXRlIGEgZGV0YWNoZWQgbmV3IEF1dG9OdW1lcmljIGVsZW1lbnQsIHRoZW4gc2tpcCB0aGUgZm9sbG93aW5nIHN0ZXAgdGhhdCBiaW5kIHRoZSB0d28gZWxlbWVudHMgdG9nZXRoZXIgYnkgZGVmYXVsdFxuICAgICAgICAgICAgaWYgKGF0dGFjaGVkKSB7XG4gICAgICAgICAgICAgICAgLy8gMSkgU2V0IHRoZSBsb2NhbCBsaXN0IHJlZmVyZW5jZSB0byBwb2ludCB0byB0aGUgaW5pdGlhbGl6ZXIncyBvbmVcbiAgICAgICAgICAgICAgICBuZXdBdXRvTnVtZXJpY0VsZW1lbnQuX3NldExvY2FsTGlzdChjdXJyZW50TG9jYWxMaXN0KTtcblxuICAgICAgICAgICAgICAgIC8vIDIpIEFkZCB0aGUgbmV3IGVsZW1lbnQgdG8gdGhhdCBleGlzdGluZyBsaXN0XG4gICAgICAgICAgICAgICAgdGhpcy5fYWRkVG9Mb2NhbExpc3QoZG9tRWxlbWVudCwgbmV3QXV0b051bWVyaWNFbGVtZW50KTsgLy8gSGVyZSB3ZSB1c2UgdGhlICpuZXcqIEF1dG9OdW1lcmljIG9iamVjdCByZWZlcmVuY2UgdG8gYWRkIHRvIHRoZSBsb2NhbCBsaXN0LCBzaW5jZSB3ZSdsbCBuZWVkIHRoZSByZWZlcmVuY2UgdG8gYHRoaXNgIGluIHRoZSBtZXRob2RzIHRvIHBvaW50cyB0byB0aGF0IG5ldyBBdXRvTnVtZXJpYyBvYmplY3QuXG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5jcmVhdGVMb2NhbExpc3QgPSBvcmlnaW5hbENyZWF0ZUxvY2FsTGlzdFNldHRpbmc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGF1dG9OdW1lcmljT2JqZWN0c0FycmF5LnB1c2gobmV3QXV0b051bWVyaWNFbGVtZW50KTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgaWYgKHJldHVybkFTaW5nbGVBdXRvTnVtZXJpY09iamVjdCkge1xuICAgICAgICAgICAgLy8gSWYgYSBzaW5nbGUgRE9NIGVsZW1lbnQgd2FzIHVzZWQgYXMgdGhlIHBhcmFtZXRlciwgdGhlbiB3ZSByZXR1cm4gYW4gQXV0b051bWVyaWMgb2JqZWN0IGRpcmVjdGx5XG4gICAgICAgICAgICByZXR1cm4gYXV0b051bWVyaWNPYmplY3RzQXJyYXlbMF07XG4gICAgICAgIH1cblxuICAgICAgICAvLyAuLi5vdGhlcndpc2Ugd2UgcmV0dXJuIGFuIEFycmF5IG9mIEF1dG9OdW1lcmljIG9iamVjdHNcbiAgICAgICAgcmV0dXJuIGF1dG9OdW1lcmljT2JqZWN0c0FycmF5O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc2V0IHRoZSBlbGVtZW50IHZhbHVlIGVpdGhlciB0byB0aGUgZW1wdHkgc3RyaW5nICcnLCBvciB0aGUgY3VycmVuY3kgc2lnbiwgZGVwZW5kaW5nIG9uIHRoZSBgZW1wdHlJbnB1dEJlaGF2aW9yYCBvcHRpb24gdmFsdWUuXG4gICAgICogSWYgeW91IHNldCB0aGUgYGZvcmNlQ2xlYXJBbGxgIGFyZ3VtZW50IHRvIGB0cnVlYCwgdGhlbiB0aGUgYGVtcHR5SW5wdXRCZWhhdmlvcmAgb3B0aW9uIGlzIG92ZXJyaWRkZW4gYW5kIHRoZSB3aG9sZSBpbnB1dCBpcyBjbGVhciwgaW5jbHVkaW5nIGFueSBjdXJyZW5jeSBzaWduLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtib29sZWFufSBmb3JjZUNsZWFyQWxsXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGNsZWFyKGZvcmNlQ2xlYXJBbGwgPSBmYWxzZSkge1xuICAgICAgICBpZiAoZm9yY2VDbGVhckFsbCkge1xuICAgICAgICAgICAgY29uc3QgdGVtcG9yYXJ5Rm9yY2VkT3B0aW9ucyA9IHtcbiAgICAgICAgICAgICAgICBlbXB0eUlucHV0QmVoYXZpb3I6IEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLmZvY3VzLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHRoaXMuc2V0KCcnLCB0ZW1wb3JhcnlGb3JjZWRPcHRpb25zKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuc2V0KCcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSB0aGUgYXV0b051bWVyaWMgZGF0YSBhbmQgZXZlbnQgbGlzdGVuZXJzIGZyb20gdGhlIGVsZW1lbnQsIGJ1dCBrZWVwIHRoZSBlbGVtZW50IGNvbnRlbnQgaW50YWN0LlxuICAgICAqIFRoaXMgYWxzbyBjbGVhcnMgdGhlIHZhbHVlIGZyb20gc2Vzc2lvblN0b3JhZ2UgKG9yIGNvb2tpZSwgZGVwZW5kaW5nIG9uIGJyb3dzZXIgc3VwcG9ydHMpLlxuICAgICAqIE5vdGU6IHRoaXMgZG9lcyBub3QgcmVtb3ZlIHRoZSBmb3JtYXR0aW5nLlxuICAgICAqXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnJlbW92ZSgpXG4gICAgICovXG4gICAgcmVtb3ZlKCkge1xuICAgICAgICB0aGlzLl9yZW1vdmVWYWx1ZUZyb21QZXJzaXN0ZW50U3RvcmFnZSgpO1xuICAgICAgICB0aGlzLl9yZW1vdmVFdmVudExpc3RlbmVycygpO1xuICAgICAgICB0aGlzLl9yZW1vdmVXYXRjaGVyKCk7XG5cbiAgICAgICAgLy8gQWxzbyByZW1vdmUgdGhlIGVsZW1lbnQgZnJvbSB0aGUgbG9jYWwgQXV0b051bWVyaWMgbGlzdFxuICAgICAgICB0aGlzLl9yZW1vdmVGcm9tTG9jYWxMaXN0KHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgIC8vIEFsc28gcmVtb3ZlIHRoZSBlbGVtZW50IGZyb20gdGhlIGdsb2JhbCBBdXRvTnVtZXJpYyBsaXN0XG4gICAgICAgIHRoaXMuY29uc3RydWN0b3IuX3JlbW92ZUZyb21HbG9iYWxMaXN0KHRoaXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSB0aGUgYXV0b051bWVyaWMgZGF0YSBhbmQgZXZlbnQgbGlzdGVuZXJzIGZyb20gdGhlIGVsZW1lbnQsIGFuZCByZXNldCBpdHMgdmFsdWUgdG8gdGhlIGVtcHR5IHN0cmluZyAnJy5cbiAgICAgKiBUaGlzIGFsc28gY2xlYXJzIHRoZSB2YWx1ZSBmcm9tIHNlc3Npb25TdG9yYWdlIChvciBjb29raWUsIGRlcGVuZGluZyBvbiBicm93c2VyIHN1cHBvcnRzKS5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlIGFuRWxlbWVudC53aXBlKClcbiAgICAgKi9cbiAgICB3aXBlKCkge1xuICAgICAgICB0aGlzLl9zZXRFbGVtZW50VmFsdWUoJycsIGZhbHNlKTsgLy8gRG8gbm90IHNlbmQgdGhlICdBdXRvTnVtZXJpYy5ldmVudHMuZm9ybWF0dGVkJyBldmVudCB3aGVuIHdpcGluZyBhbiBBdXRvTnVtZXJpYyBvYmplY3RcbiAgICAgICAgdGhpcy5yZW1vdmUoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIGF1dG9OdW1lcmljIGRhdGEgYW5kIGV2ZW50IGxpc3RlbmVycyBmcm9tIHRoZSBlbGVtZW50LCBhbmQgZGVsZXRlIHRoZSBET00gZWxlbWVudCBhbHRvZ2V0aGVyXG4gICAgICovXG4gICAgbnVrZSgpIHtcbiAgICAgICAgdGhpcy5yZW1vdmUoKTtcbiAgICAgICAgLy8gUmVtb3ZlIHRoZSBlbGVtZW50IGZyb20gdGhlIERPTVxuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucGFyZW50Tm9kZS5yZW1vdmVDaGlsZCh0aGlzLmRvbUVsZW1lbnQpO1xuICAgIH1cblxuXG4gICAgLy8gU3BlY2lhbCBmdW5jdGlvbnMgdGhhdCByZWFsbHkgd29yayBvbiB0aGUgcGFyZW50IDxmb3JtPiBlbGVtZW50LCBpbnN0ZWFkIG9mIHRoZSA8aW5wdXQ+IGVsZW1lbnQgaXRzZWxmXG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSByZWZlcmVuY2UgdG8gdGhlIHBhcmVudCA8Zm9ybT4gZWxlbWVudCBpZiBpdCBleGlzdHMsIG90aGVyd2lzZSByZXR1cm4gYG51bGxgLlxuICAgICAqIElmIHRoZSBwYXJlbnQgZm9ybSBlbGVtZW50IGFzIGFscmVhZHkgYmVlbiBmb3VuZCwgdGhpcyBkaXJlY3RseSByZXR1cm4gYSByZWZlcmVuY2UgdG8gaXQuXG4gICAgICogSG93ZXZlciwgeW91IGNhbiBmb3JjZSBBdXRvTnVtZXJpYyB0byBzZWFyY2ggYWdhaW4gZm9yIGl0cyByZWZlcmVuY2UgYnkgcGFzc2luZyBgdHJ1ZWAgYXMgYSBwYXJhbWV0ZXIgdG8gdGhpcyBtZXRob2QuXG4gICAgICogVGhpcyBtZXRob2QgdXBkYXRlcyB0aGUgYHRoaXMucGFyZW50Rm9ybWAgYXR0cmlidXRlLlxuICAgICAqXG4gICAgICogSW4gZWl0aGVyIGNhc2UsIHdoZW5ldmVyIGEgbmV3IHBhcmVudCBmb3JtIGlzIHNldCBmb3IgdGhlIGN1cnJlbnQgQXV0b051bWVyaWMgZWxlbWVudCwgd2UgbWFrZSBzdXJlIHRvIHVwZGF0ZSB0aGUgYW5Db3VudCBhbmQgYW5Gb3JtSGFuZGxlciBhdHRyaWJ1dGVzIG9uIGJvdGggdGhlIG9sZCBmb3JtIGFuZCB0aGUgbmV3IG9uZSAoZm9yIGluc3RhbmNlIGluIGNhc2UgdGhlIHVzZXIgbW92ZWQgdGhlIGlucHV0IGVsZW1lbnRzIHdpdGggYGFwcGVuZENoaWxkKClgIHNpbmNlIEF1dG9OdW1lcmljIGNhbm5vdCBub3QgZGV0ZWN0IHRoYXQpLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtib29sZWFufSBmb3JjZVNlYXJjaCBJZiBzZXQgdG8gYHRydWVgLCB0aGUgcGFyZW50IGZvcm0gaXMgc2VhcmNoZWQgYWdhaW4sIGV2ZW4gaWYgYHRoaXMucGFyZW50Rm9ybWAgaXMgYWxyZWFkeSBzZXQuXG4gICAgICogQHJldHVybnMge0hUTUxGb3JtRWxlbWVudHxudWxsfVxuICAgICAqL1xuICAgIGZvcm0oZm9yY2VTZWFyY2ggPSBmYWxzZSkge1xuICAgICAgICBpZiAoZm9yY2VTZWFyY2ggfHwgQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHRoaXMucGFyZW50Rm9ybSkpIHtcbiAgICAgICAgICAgIGNvbnN0IG5ld1BhcmVudEZvcm0gPSB0aGlzLl9nZXRQYXJlbnRGb3JtKCk7XG4gICAgICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChuZXdQYXJlbnRGb3JtKSAmJiBuZXdQYXJlbnRGb3JtICE9PSB0aGlzLnBhcmVudEZvcm0pIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgY3VycmVudCBwYXJlbnQgZm9ybSBleGlzdHMgYW5kIGlzIGRpZmZlcmVudCBmcm9tIHRoZSBwcmV2aW91cyBwYXJlbnQgZm9ybVxuXG4gICAgICAgICAgICAgICAgLy8gU2VhcmNoIGZvciBhbGwgdGhlIEF1dG9OdW1lcmljIGVsZW1lbnRzIGluIHRoZSBvbGQgcGFyZW50IGZvcm1cbiAgICAgICAgICAgICAgICBjb25zdCBvbGRBTkNoaWxkcmVuID0gdGhpcy5fZ2V0Rm9ybUF1dG9OdW1lcmljQ2hpbGRyZW4odGhpcy5wYXJlbnRGb3JtKTtcbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGFuQ291bnQgd2l0aCB0aGUgY29ycmVjdCBudW1iZXIgb2YgQXV0b051bWVyaWMgZWxlbWVudHNcbiAgICAgICAgICAgICAgICB0aGlzLnBhcmVudEZvcm0uZGF0YXNldC5hbkNvdW50ID0gb2xkQU5DaGlsZHJlbi5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgbmV3IHBhcmVudCBmb3JtIGFscmVhZHkgaGFzIGEgYW5Gb3JtSGFuZGxlciBuYW1lXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuX2hhc0Zvcm1IYW5kbGVyRnVuY3Rpb24obmV3UGFyZW50Rm9ybSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5faW5jcmVtZW50UGFyZW50Rm9ybUNvdW50ZXIobmV3UGFyZW50Rm9ybSk7IC8vIEluY3JlbWVudCBpdHMgY291bnRlclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIENyZWF0ZSBvbmUgYW5kIHNldCB0aGUgYW5Db3VudCB0byAxXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3N0b3JlRm9ybUhhbmRsZXJGdW5jdGlvbihuZXdQYXJlbnRGb3JtKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5faW5pdGlhbGl6ZUZvcm1Db3VudGVyVG9PbmUobmV3UGFyZW50Rm9ybSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLnBhcmVudEZvcm0gPSBuZXdQYXJlbnRGb3JtO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMucGFyZW50Rm9ybTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYW4gYXJyYXkgb2YgdGhlIEF1dG9OdW1lcmljLW1hbmFnZWQgZWxlbWVudHMgZm9yIHRoZSBnaXZlbiBmb3JtIGVsZW1lbnQgaXMgcGFzc2VkLCBvdGhlcndpc2UgZm9yIHRoZSBjdXJyZW50IGB0aGlzLnBhcmVudEZvcm1gIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxGb3JtRWxlbWVudHxudWxsfSBmb3JtRWxlbWVudFxuICAgICAqIEByZXR1cm5zIHtBcnJheS48SFRNTElucHV0RWxlbWVudD59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0Rm9ybUF1dG9OdW1lcmljQ2hpbGRyZW4oZm9ybUVsZW1lbnQpIHtcbiAgICAgICAgLy8gU2VhcmNoIGZvciBhbGwgdGhlIGNoaWxkIEF1dG9OdW1lcmljIGVsZW1lbnRzIGluIHRoYXQgcGFyZW50IGZvcm1cbiAgICAgICAgLy9YWFggVGhpcyBvbmx5IHNlYXJjaCBmb3IgPGlucHV0PiBlbGVtZW50cywgbm90IGNvbnRlbnRlZGl0YWJsZSBub24taW5wdXQgdGFnIG9uZXMsIGZvciBub3dcbiAgICAgICAgY29uc3QgaW5wdXRMaXN0ID0gWy4uLiBmb3JtRWxlbWVudC5xdWVyeVNlbGVjdG9yQWxsKCdpbnB1dCcpXTtcblxuICAgICAgICByZXR1cm4gaW5wdXRMaXN0LmZpbHRlcihpbnB1dCA9PiB0aGlzLmNvbnN0cnVjdG9yLmlzTWFuYWdlZEJ5QXV0b051bWVyaWMoaW5wdXQpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSByZWZlcmVuY2UgdG8gdGhlIHBhcmVudCA8Zm9ybT4gZWxlbWVudCBpZiBpdCBleGlzdHMsIG90aGVyd2lzZSByZXR1cm4gYG51bGxgLlxuICAgICAqXG4gICAgICogQHJldHVybnMge0hUTUxGb3JtRWxlbWVudHxudWxsfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2dldFBhcmVudEZvcm0oKSB7XG4gICAgICAgIGlmICh0aGlzLmRvbUVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnYm9keScpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IG5vZGUgPSB0aGlzLmRvbUVsZW1lbnQ7XG4gICAgICAgIGxldCB0YWdOYW1lO1xuICAgICAgICBkbyB7XG4gICAgICAgICAgICBub2RlID0gbm9kZS5wYXJlbnROb2RlO1xuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChub2RlKSkge1xuICAgICAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSB3aGVuIHVzaW5nIHRlbXBsYXRlcyB3aXRoIGZyYW1ld29ya3MgbGlrZSBWdWUuanMsIHdoZXJlIHRoZSBpbnB1dCBlbGVtZW50IGNhbiBiZSAnZGV0YWNoZWQnIHdoZW4gaW5pdGlhbGl6aW5nIHRoZSBET00gc3RydWN0dXJlXG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChub2RlLnRhZ05hbWUpIHtcbiAgICAgICAgICAgICAgICB0YWdOYW1lID0gbm9kZS50YWdOYW1lLnRvTG93ZXJDYXNlKCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRhZ05hbWUgPSAnJztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHRhZ05hbWUgPT09ICdib2R5Jykge1xuICAgICAgICAgICAgICAgIC8vIEdldCBvdXQgb2YgdGhlIGxvb3AgaWYgd2UgZ2V0IHVwIHRvIHRoZSBgPGJvZHk+YCBlbGVtZW50XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gd2hpbGUgKHRhZ05hbWUgIT09ICdmb3JtJyk7XG5cbiAgICAgICAgaWYgKHRhZ05hbWUgPT09ICdmb3JtJykge1xuICAgICAgICAgICAgcmV0dXJuIG5vZGU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIHN0cmluZyBpbiBzdGFuZGFyZCBVUkwtZW5jb2RlZCBub3RhdGlvbiB3aXRoIHRoZSBmb3JtIGlucHV0IHZhbHVlcyBiZWluZyB1bmZvcm1hdHRlZC5cbiAgICAgKiBUaGlzIHN0cmluZyBjYW4gYmUgdXNlZCBhcyBhIHF1ZXJ5IGZvciBpbnN0YW5jZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZm9ybU51bWVyaWNTdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLl9zZXJpYWxpemVOdW1lcmljU3RyaW5nKHRoaXMuZm9ybSgpLCB0aGlzLnNldHRpbmdzLnNlcmlhbGl6ZVNwYWNlcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGEgc3RyaW5nIGluIHN0YW5kYXJkIFVSTC1lbmNvZGVkIG5vdGF0aW9uIHdpdGggdGhlIGZvcm0gaW5wdXQgdmFsdWVzIGJlaW5nIGZvcm1hdHRlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZm9ybUZvcm1hdHRlZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IuX3NlcmlhbGl6ZUZvcm1hdHRlZCh0aGlzLmZvcm0oKSwgdGhpcy5zZXR0aW5ncy5zZXJpYWxpemVTcGFjZXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIHN0cmluZyBpbiBzdGFuZGFyZCBVUkwtZW5jb2RlZCBub3RhdGlvbiB3aXRoIHRoZSBmb3JtIGlucHV0IHZhbHVlcywgd2l0aCBsb2NhbGl6ZWQgdmFsdWVzLlxuICAgICAqIFRoZSBkZWZhdWx0IG91dHB1dCBmb3JtYXQgY2FuIGJlIG92ZXJyaWRkZW4gYnkgcGFzc2luZyB0aGUgb3B0aW9uIGFzIGEgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudWxsfHN0cmluZ30gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gYG51bGxgLCB0aGVuIHRoaXMgaXMgdXNlZCBhcyBhbiBvdmVycmlkaW5nIG91dHB1dEZvcm1hdCBvcHRpb25cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIGZvcm1Mb2NhbGl6ZWQoZm9yY2VkT3V0cHV0Rm9ybWF0ID0gbnVsbCkge1xuICAgICAgICBsZXQgb3V0cHV0Rm9ybWF0VG9Vc2U7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoZm9yY2VkT3V0cHV0Rm9ybWF0KSkge1xuICAgICAgICAgICAgb3V0cHV0Rm9ybWF0VG9Vc2UgPSB0aGlzLnNldHRpbmdzLm91dHB1dEZvcm1hdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdFRvVXNlID0gZm9yY2VkT3V0cHV0Rm9ybWF0O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IuX3NlcmlhbGl6ZUxvY2FsaXplZCh0aGlzLmZvcm0oKSwgdGhpcy5zZXR0aW5ncy5zZXJpYWxpemVTcGFjZXMsIG91dHB1dEZvcm1hdFRvVXNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYW4gYXJyYXkgY29udGFpbmluZyBhbiBvYmplY3QgZm9yIGVhY2ggZm9ybSA8aW5wdXQ+IGVsZW1lbnQuXG4gICAgICogVGhvc2Ugb2JqZWN0cyBhcmUgb2YgdGhlIGZvbGxvd2luZyBzdHJ1Y3R1cmUgYHsgbmFtZTogZm9vLCB2YWx1ZTogJzQyJyB9YCwgd2hlcmUgdGhlIGBuYW1lYCBpcyB0aGUgRE9NIGVsZW1lbnQgbmFtZSwgYW5kIHRoZSBgdmFsdWVgIGlzIGFuIHVuZm9ybWF0dGVkIG51bWVyaWMgc3RyaW5nLlxuICAgICAqXG4gICAgICogQHJldHVybnMge0FycmF5fVxuICAgICAqL1xuICAgIGZvcm1BcnJheU51bWVyaWNTdHJpbmcoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLl9zZXJpYWxpemVOdW1lcmljU3RyaW5nQXJyYXkodGhpcy5mb3JtKCksIHRoaXMuc2V0dGluZ3Muc2VyaWFsaXplU3BhY2VzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYW4gYXJyYXkgY29udGFpbmluZyBhbiBvYmplY3QgZm9yIGVhY2ggZm9ybSA8aW5wdXQ+IGVsZW1lbnQuXG4gICAgICogVGhvc2Ugb2JqZWN0cyBhcmUgb2YgdGhlIGZvbGxvd2luZyBzdHJ1Y3R1cmUgYHsgbmFtZTogZm9vLCB2YWx1ZTogJzQyJyB9YCwgd2hlcmUgdGhlIGBuYW1lYCBpcyB0aGUgRE9NIGVsZW1lbnQgbmFtZSwgYW5kIHRoZSBgdmFsdWVgIGlzIHRoZSBmb3JtYXR0ZWQgc3RyaW5nLlxuICAgICAqXG4gICAgICogQHJldHVybnMge0FycmF5fVxuICAgICAqL1xuICAgIGZvcm1BcnJheUZvcm1hdHRlZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IuX3NlcmlhbGl6ZUZvcm1hdHRlZEFycmF5KHRoaXMuZm9ybSgpLCB0aGlzLnNldHRpbmdzLnNlcmlhbGl6ZVNwYWNlcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGFuIGFycmF5IGNvbnRhaW5pbmcgYW4gb2JqZWN0IGZvciBlYWNoIGZvcm0gPGlucHV0PiBlbGVtZW50LlxuICAgICAqIFRob3NlIG9iamVjdHMgYXJlIG9mIHRoZSBmb2xsb3dpbmcgc3RydWN0dXJlIGB7IG5hbWU6IGZvbywgdmFsdWU6ICc0MicgfWAsIHdoZXJlIHRoZSBgbmFtZWAgaXMgdGhlIERPTSBlbGVtZW50IG5hbWUsIGFuZCB0aGUgYHZhbHVlYCBpcyB0aGUgbG9jYWxpemVkIG51bWVyaWMgc3RyaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudWxsfHN0cmluZ30gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gYG51bGxgLCB0aGVuIHRoaXMgaXMgdXNlZCBhcyBhbiBvdmVycmlkaW5nIG91dHB1dEZvcm1hdCBvcHRpb25cbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9XG4gICAgICovXG4gICAgZm9ybUFycmF5TG9jYWxpemVkKGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGwpIHtcbiAgICAgICAgbGV0IG91dHB1dEZvcm1hdFRvVXNlO1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGZvcmNlZE91dHB1dEZvcm1hdCkpIHtcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdFRvVXNlID0gdGhpcy5zZXR0aW5ncy5vdXRwdXRGb3JtYXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvdXRwdXRGb3JtYXRUb1VzZSA9IGZvcmNlZE91dHB1dEZvcm1hdDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLl9zZXJpYWxpemVMb2NhbGl6ZWRBcnJheSh0aGlzLmZvcm0oKSwgdGhpcy5zZXR0aW5ncy5zZXJpYWxpemVTcGFjZXMsIG91dHB1dEZvcm1hdFRvVXNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBKU09OIHN0cmluZyBjb250YWluaW5nIGFuIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIGZvcm0gaW5wdXQgdmFsdWVzLlxuICAgICAqIFRoaXMgaXMgYmFzZWQgb24gdGhlIHJlc3VsdCBvZiB0aGUgYGZvcm1BcnJheU51bWVyaWNTdHJpbmcoKWAgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIGZvcm1Kc29uTnVtZXJpY1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHRoaXMuZm9ybUFycmF5TnVtZXJpY1N0cmluZygpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBKU09OIHN0cmluZyBjb250YWluaW5nIGFuIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIGZvcm0gaW5wdXQgdmFsdWVzLlxuICAgICAqIFRoaXMgaXMgYmFzZWQgb24gdGhlIHJlc3VsdCBvZiB0aGUgYGZvcm1BcnJheUZvcm1hdHRlZCgpYCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZm9ybUpzb25Gb3JtYXR0ZWQoKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh0aGlzLmZvcm1BcnJheUZvcm1hdHRlZCgpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBKU09OIHN0cmluZyBjb250YWluaW5nIGFuIG9iamVjdCByZXByZXNlbnRpbmcgdGhlIGZvcm0gaW5wdXQgdmFsdWVzLlxuICAgICAqIFRoaXMgaXMgYmFzZWQgb24gdGhlIHJlc3VsdCBvZiB0aGUgYGZvcm1BcnJheUxvY2FsaXplZCgpYCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVsbHxzdHJpbmd9IGZvcmNlZE91dHB1dEZvcm1hdCBJZiBzZXQgdG8gc29tZXRoaW5nIGRpZmZlcmVudCB0aGFuIGBudWxsYCwgdGhlbiB0aGlzIGlzIHVzZWQgYXMgYW4gb3ZlcnJpZGluZyBvdXRwdXRGb3JtYXQgb3B0aW9uXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBmb3JtSnNvbkxvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsKSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeSh0aGlzLmZvcm1BcnJheUxvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbmZvcm1hdCBhbGwgdGhlIGF1dG9OdW1lcmljLW1hbmFnZWQgZWxlbWVudHMgdGhhdCBhcmUgYSBjaGlsZCBvZiB0aGUgcGFyZW50IDxmb3JtPiBlbGVtZW50IG9mIHRoaXMgRE9NIGVsZW1lbnQsIHRvIG51bWVyaWMgc3RyaW5nc1xuICAgICAqXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1VbmZvcm1hdCgpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgY29uc3QgaW5wdXRzID0gdGhpcy5jb25zdHJ1Y3Rvci5fZ2V0Q2hpbGRBTklucHV0RWxlbWVudCh0aGlzLmZvcm0oKSk7XG4gICAgICAgIGlucHV0cy5mb3JFYWNoKGlucHV0ID0+IHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLmdldEF1dG9OdW1lcmljRWxlbWVudChpbnB1dCkudW5mb3JtYXQoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW5mb3JtYXQgYWxsIHRoZSBhdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRzIHRoYXQgYXJlIGEgY2hpbGQgb2YgdGhlIHBhcmVudCA8Zm9ybT4gZWxlbWVudCBvZiB0aGlzIERPTSBlbGVtZW50LCB0byBsb2NhbGl6ZWQgc3RyaW5nc1xuICAgICAqXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1VbmZvcm1hdExvY2FsaXplZCgpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgY29uc3QgaW5wdXRzID0gdGhpcy5jb25zdHJ1Y3Rvci5fZ2V0Q2hpbGRBTklucHV0RWxlbWVudCh0aGlzLmZvcm0oKSk7XG4gICAgICAgIGlucHV0cy5mb3JFYWNoKGlucHV0ID0+IHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLmdldEF1dG9OdW1lcmljRWxlbWVudChpbnB1dCkudW5mb3JtYXRMb2NhbGl6ZWQoKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVmb3JtYXQgYWxsIHRoZSBhdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRzIHRoYXQgYXJlIGEgY2hpbGQgb2YgdGhlIHBhcmVudCA8Zm9ybT4gZWxlbWVudCBvZiB0aGlzIERPTSBlbGVtZW50XG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgZm9ybVJlZm9ybWF0KCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBjb25zdCBpbnB1dHMgPSB0aGlzLmNvbnN0cnVjdG9yLl9nZXRDaGlsZEFOSW5wdXRFbGVtZW50KHRoaXMuZm9ybSgpKTtcbiAgICAgICAgaW5wdXRzLmZvckVhY2goaW5wdXQgPT4ge1xuICAgICAgICAgICAgQXV0b051bWVyaWMuZ2V0QXV0b051bWVyaWNFbGVtZW50KGlucHV0KS5yZWZvcm1hdCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IHRoZSBpbnB1dCB2YWx1ZXMgdG8gbnVtZXJpYyBzdHJpbmdzLCBzdWJtaXQgdGhlIGZvcm0sIHRoZW4gcmVmb3JtYXQgdGhvc2UgYmFjay5cbiAgICAgKiBUaGUgZnVuY3Rpb24gY2FuIGVpdGhlciB0YWtlIGEgY2FsbGJhY2ssIG9yIG5vdC4gSWYgaXQgZG9lc24ndCwgdGhlIGRlZmF1bHQgYGZvcm0uc3VibWl0KClgIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkLlxuICAgICAqIE90aGVyd2lzZSwgaXQgcnVucyBgY2FsbGJhY2sodmFsdWUpYCB3aXRoIGB2YWx1ZWAgYmVpbmcgZXF1YWwgdG8gdGhlIHJlc3VsdCBvZiBgZm9ybU51bWVyaWNTdHJpbmcoKWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1TdWJtaXROdW1lcmljU3RyaW5nKGNhbGxiYWNrID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgdGhpcy5mb3JtVW5mb3JtYXQoKTtcbiAgICAgICAgICAgIHRoaXMuZm9ybSgpLnN1Ym1pdCgpO1xuICAgICAgICAgICAgdGhpcy5mb3JtUmVmb3JtYXQoKTtcbiAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtTnVtZXJpY1N0cmluZygpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBnaXZlbiBjYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN1Ym1pdCB0aGUgZm9ybSB3aXRoIHRoZSBjdXJyZW50IGZvcm1hdHRlZCB2YWx1ZXMuXG4gICAgICogVGhlIGZ1bmN0aW9uIGNhbiBlaXRoZXIgdGFrZSBhIGNhbGxiYWNrLCBvciBub3QuIElmIGl0IGRvZXNuJ3QsIHRoZSBkZWZhdWx0IGBmb3JtLnN1Ym1pdCgpYCBmdW5jdGlvbiB3aWxsIGJlIGNhbGxlZC5cbiAgICAgKiBPdGhlcndpc2UsIGl0IHJ1bnMgYGNhbGxiYWNrKHZhbHVlKWAgd2l0aCBgdmFsdWVgIGJlaW5nIGVxdWFsIHRvIHRoZSByZXN1bHQgb2YgYGZvcm1Gb3JtYXR0ZWQoKWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1TdWJtaXRGb3JtYXR0ZWQoY2FsbGJhY2sgPSBudWxsKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoY2FsbGJhY2spKSB7XG4gICAgICAgICAgICB0aGlzLmZvcm0oKS5zdWJtaXQoKTtcbiAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtRm9ybWF0dGVkKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGdpdmVuIGNhbGxiYWNrIGlzIG5vdCBhIGZ1bmN0aW9uLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydCB0aGUgaW5wdXQgdmFsdWVzIHRvIGxvY2FsaXplZCBzdHJpbmdzLCBzdWJtaXQgdGhlIGZvcm0sIHRoZW4gcmVmb3JtYXQgdGhvc2UgYmFjay5cbiAgICAgKiBUaGUgZnVuY3Rpb24gY2FuIGVpdGhlciB0YWtlIGEgY2FsbGJhY2ssIG9yIG5vdC4gSWYgaXQgZG9lc24ndCwgdGhlIGRlZmF1bHQgYGZvcm0uc3VibWl0KClgIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkLlxuICAgICAqIE90aGVyd2lzZSwgaXQgcnVucyBgY2FsbGJhY2sodmFsdWUpYCB3aXRoIGB2YWx1ZWAgYmVpbmcgZXF1YWwgdG8gdGhlIHJlc3VsdCBvZiBgZm9ybUxvY2FsaXplZCgpYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVsbHxzdHJpbmd9IGZvcmNlZE91dHB1dEZvcm1hdCBJZiBzZXQgdG8gc29tZXRoaW5nIGRpZmZlcmVudCB0aGFuIGBudWxsYCwgdGhlbiB0aGlzIGlzIHVzZWQgYXMgYW4gb3ZlcnJpZGluZyBvdXRwdXRGb3JtYXQgb3B0aW9uXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFja1xuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBmb3JtU3VibWl0TG9jYWxpemVkKGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGwsIGNhbGxiYWNrID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgdGhpcy5mb3JtVW5mb3JtYXRMb2NhbGl6ZWQoKTtcbiAgICAgICAgICAgIHRoaXMuZm9ybSgpLnN1Ym1pdCgpO1xuICAgICAgICAgICAgdGhpcy5mb3JtUmVmb3JtYXQoKTtcbiAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtTG9jYWxpemVkKGZvcmNlZE91dHB1dEZvcm1hdCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGdpdmVuIGNhbGxiYWNrIGlzIG5vdCBhIGZ1bmN0aW9uLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYW4gYXJyYXkgb2YgbnVtZXJpYyBzdHJpbmdzIGZyb20gdGhlIGA8aW5wdXQ+YCBlbGVtZW50cywgYW5kIHBhc3MgaXQgdG8gdGhlIGdpdmVuIGNhbGxiYWNrLlxuICAgICAqIFVuZGVyIHRoZSBob29kLCB0aGUgYXJyYXkgaXMgZ2VuZXJhdGVkIHZpYSBhIGNhbGwgdG8gYGZvcm1BcnJheU51bWVyaWNTdHJpbmcoKWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBmb3JtU3VibWl0QXJyYXlOdW1lcmljU3RyaW5nKGNhbGxiYWNrKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtQXJyYXlOdW1lcmljU3RyaW5nKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGdpdmVuIGNhbGxiYWNrIGlzIG5vdCBhIGZ1bmN0aW9uLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYW4gYXJyYXkgb2YgdGhlIGN1cnJlbnQgZm9ybWF0dGVkIHZhbHVlcyBmcm9tIHRoZSBgPGlucHV0PmAgZWxlbWVudHMsIGFuZCBwYXNzIGl0IHRvIHRoZSBnaXZlbiBjYWxsYmFjay5cbiAgICAgKiBVbmRlciB0aGUgaG9vZCwgdGhlIGFycmF5IGlzIGdlbmVyYXRlZCB2aWEgYSBjYWxsIHRvIGBmb3JtQXJyYXlGb3JtYXR0ZWQoKWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBmb3JtU3VibWl0QXJyYXlGb3JtYXR0ZWQoY2FsbGJhY2spIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRnVuY3Rpb24oY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0aGlzLmZvcm1BcnJheUZvcm1hdHRlZCgpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBnaXZlbiBjYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGFuIGFycmF5IG9mIGxvY2FsaXplZCBzdHJpbmdzIGZyb20gdGhlIGA8aW5wdXQ+YCBlbGVtZW50cywgYW5kIHBhc3MgaXQgdG8gdGhlIGdpdmVuIGNhbGxiYWNrLlxuICAgICAqIFVuZGVyIHRoZSBob29kLCB0aGUgYXJyYXkgaXMgZ2VuZXJhdGVkIHZpYSBhIGNhbGwgdG8gYGZvcm1BcnJheUxvY2FsaXplZCgpYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICogQHBhcmFtIHtudWxsfHN0cmluZ30gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gYG51bGxgLCB0aGVuIHRoaXMgaXMgdXNlZCBhcyBhbiBvdmVycmlkaW5nIG91dHB1dEZvcm1hdCBvcHRpb25cbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgZm9ybVN1Ym1pdEFycmF5TG9jYWxpemVkKGNhbGxiYWNrLCBmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtQXJyYXlMb2NhbGl6ZWQoZm9yY2VkT3V0cHV0Rm9ybWF0KSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gY2FsbGJhY2sgaXMgbm90IGEgZnVuY3Rpb24uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIEpTT04gc3RyaW5nIHdpdGggdGhlIG51bWVyaWMgc3RyaW5ncyB2YWx1ZXMgZnJvbSB0aGUgYDxpbnB1dD5gIGVsZW1lbnRzLCBhbmQgcGFzcyBpdCB0byB0aGUgZ2l2ZW4gY2FsbGJhY2suXG4gICAgICogVW5kZXIgdGhlIGhvb2QsIHRoZSBhcnJheSBpcyBnZW5lcmF0ZWQgdmlhIGEgY2FsbCB0byBgZm9ybUpzb25OdW1lcmljU3RyaW5nKClgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgZm9ybVN1Ym1pdEpzb25OdW1lcmljU3RyaW5nKGNhbGxiYWNrKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtSnNvbk51bWVyaWNTdHJpbmcoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gY2FsbGJhY2sgaXMgbm90IGEgZnVuY3Rpb24uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhIEpTT04gc3RyaW5nIHdpdGggdGhlIGN1cnJlbnQgZm9ybWF0dGVkIHZhbHVlcyBmcm9tIHRoZSBgPGlucHV0PmAgZWxlbWVudHMsIGFuZCBwYXNzIGl0IHRvIHRoZSBnaXZlbiBjYWxsYmFjay5cbiAgICAgKiBVbmRlciB0aGUgaG9vZCwgdGhlIGFycmF5IGlzIGdlbmVyYXRlZCB2aWEgYSBjYWxsIHRvIGBmb3JtSnNvbkZvcm1hdHRlZCgpYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1TdWJtaXRKc29uRm9ybWF0dGVkKGNhbGxiYWNrKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtSnNvbkZvcm1hdHRlZCgpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBnaXZlbiBjYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgSlNPTiBzdHJpbmcgd2l0aCB0aGUgbG9jYWxpemVkIHN0cmluZ3MgdmFsdWVzIGZyb20gdGhlIGA8aW5wdXQ+YCBlbGVtZW50cywgYW5kIHBhc3MgaXQgdG8gdGhlIGdpdmVuIGNhbGxiYWNrLlxuICAgICAqIFVuZGVyIHRoZSBob29kLCB0aGUgYXJyYXkgaXMgZ2VuZXJhdGVkIHZpYSBhIGNhbGwgdG8gYGZvcm1Kc29uTG9jYWxpemVkKClgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAgICAgKiBAcGFyYW0ge251bGx8c3RyaW5nfSBmb3JjZWRPdXRwdXRGb3JtYXQgSWYgc2V0IHRvIHNvbWV0aGluZyBkaWZmZXJlbnQgdGhhbiBgbnVsbGAsIHRoZW4gdGhpcyBpcyB1c2VkIGFzIGFuIG92ZXJyaWRpbmcgb3V0cHV0Rm9ybWF0IG9wdGlvblxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBmb3JtU3VibWl0SnNvbkxvY2FsaXplZChjYWxsYmFjaywgZm9yY2VkT3V0cHV0Rm9ybWF0ID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNGdW5jdGlvbihjYWxsYmFjaykpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKHRoaXMuZm9ybUpzb25Mb2NhbGl6ZWQoZm9yY2VkT3V0cHV0Rm9ybWF0KSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gY2FsbGJhY2sgaXMgbm90IGEgZnVuY3Rpb24uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbmZvcm1hdCB0aGUgZ2l2ZW4gQXV0b051bWVyaWMgZWxlbWVudCwgYW5kIHVwZGF0ZSB0aGUgYGhvdmVyZWRXaXRoQWx0YCB2YXJpYWJsZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QXV0b051bWVyaWN9IGFuRWxlbWVudFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF91bmZvcm1hdEFsdEhvdmVyZWQoYW5FbGVtZW50KSB7XG4gICAgICAgIGFuRWxlbWVudC5ob3ZlcmVkV2l0aEFsdCA9IHRydWU7XG4gICAgICAgIGFuRWxlbWVudC51bmZvcm1hdCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlZm9ybWF0IHRoZSBnaXZlbiBBdXRvTnVtZXJpYyBlbGVtZW50LCBhbmQgdXBkYXRlIHRoZSBgaG92ZXJlZFdpdGhBbHRgIHZhcmlhYmxlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtBdXRvTnVtZXJpY30gYW5FbGVtZW50XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3JlZm9ybWF0QWx0SG92ZXJlZChhbkVsZW1lbnQpIHtcbiAgICAgICAgYW5FbGVtZW50LmhvdmVyZWRXaXRoQWx0ID0gZmFsc2U7XG4gICAgICAgIGFuRWxlbWVudC5yZWZvcm1hdCgpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhbiBhcnJheSBvZiBhdXRvTnVtZXJpYyBlbGVtZW50cywgY2hpbGQgb2YgdGhlIDxmb3JtPiBlbGVtZW50IHBhc3NlZCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR9IGZvcm1Ob2RlXG4gICAgICogQHJldHVybnMge0FycmF5fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9nZXRDaGlsZEFOSW5wdXRFbGVtZW50KGZvcm1Ob2RlKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGNvbnN0IGlucHV0TGlzdCA9IGZvcm1Ob2RlLmdldEVsZW1lbnRzQnlUYWdOYW1lKCdpbnB1dCcpO1xuXG4gICAgICAgIC8vIExvb3AgdGhpcyBsaXN0IGFuZCBrZWVwIG9ubHkgdGhlIGlucHV0cyB0aGF0IGFyZSBtYW5hZ2VkIGJ5IEF1dG9OdW1lcmljXG4gICAgICAgIGNvbnN0IGF1dG9OdW1lcmljSW5wdXRzID0gW107XG4gICAgICAgIGNvbnN0IGlucHV0RWxlbWVudHMgPSBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChpbnB1dExpc3QsIDApO1xuICAgICAgICBpbnB1dEVsZW1lbnRzLmZvckVhY2goaW5wdXQgPT4ge1xuICAgICAgICAgICAgaWYgKHRoaXMudGVzdChpbnB1dCkpIHtcbiAgICAgICAgICAgICAgICBhdXRvTnVtZXJpY0lucHV0cy5wdXNoKGlucHV0KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIGF1dG9OdW1lcmljSW5wdXRzO1xuICAgIH1cblxuICAgIC8vIFN0YXRpYyBtZXRob2RzXG4gICAgLyoqXG4gICAgICogVGVzdCBpZiB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQsIG9yIHRoZSBlbGVtZW50IHNlbGVjdGVkIGJ5IHRoZSBnaXZlbiBzZWxlY3RvciBzdHJpbmcgaXMgYWxyZWFkeSBtYW5hZ2VkIGJ5IEF1dG9OdW1lcmljIChpZiBpdCBoYXMgYmVlbiBpbml0aWFsaXplZCBvbiB0aGUgY3VycmVudCBwYWdlKS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8c3RyaW5nfSBkb21FbGVtZW50T3JTZWxlY3RvciBBY2NlcHRzIGVpdGhlciBkaXJlY3RseSBhIERPTSBlbGVtZW50IHRvIHRlc3QsIG9yIGEgc3RyaW5nIHNlbGVjdG9yICh0aGF0IHdpbGwgcmV0dXJuIG9uZSBhbmQgb25seSBvbmUgZWxlbWVudCwgaWYgYW55KVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyB0ZXN0KGRvbUVsZW1lbnRPclNlbGVjdG9yKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9pc0luR2xvYmFsTGlzdChBdXRvTnVtZXJpY0hlbHBlci5kb21FbGVtZW50KGRvbUVsZW1lbnRPclNlbGVjdG9yKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgV2Vha01hcCB3aXRoIHRoZSBnaXZlbiBuYW1lLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHdlYWtNYXBOYW1lXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NyZWF0ZVdlYWtNYXAod2Vha01hcE5hbWUpIHtcbiAgICAgICAgd2luZG93W3dlYWtNYXBOYW1lXSA9IG5ldyBXZWFrTWFwKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgbGlzdCBvZiBhbGwgdGhlIEF1dG9OdW1lcmljIGVsZW1lbnRzIHRoYXQgYXJlIGluaXRpYWxpemVkIG9uIHRoZSBjdXJyZW50IHBhZ2UuXG4gICAgICogVGhpcyBpcyBuZWVkZWQgaW4gb3JkZXIgdG8gZGV0ZXJtaW5lIGlmIGEgZ2l2ZW4gZG9tIGVsZW1lbnQgaXMgYWxyZWFkeSBtYW5hZ2VkIGJ5IGF1dG9OdW1lcmljLlxuICAgICAqIFRoaXMgdXNlcyBhIFdlYWtNYXAgaW4gb3JkZXIgdG8gbGltaXQgcG90ZW50aWFsIGdhcmJhZ2UgY29sbGVjdGlvbiBwcm9ibGVtcy5cbiAgICAgKiAoY2YuIG15IHRlc3RzIG9uIGh0dHA6Ly9jb2RlcGVuLmlvL0Fub3RoZXJMaW51eFVzZXIvcGVuL3BSUUdhTT9lZGl0b3JzPTEwMTEpXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NyZWF0ZUdsb2JhbExpc3QoKSB7XG4gICAgICAgIC8vIFRoZSBjaGVjayB0aGF0IHRoaXMgZ2xvYmFsIGxpc3QgZG9lcyBub3QgZXhpc3RzIGFscmVhZHkgaXMgZG9uZSBpbiB0aGUgYWRkIGFuZCByZW1vdmUgZnVuY3Rpb25zIGFscmVhZHlcbiAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0dsb2JhbExpc3ROYW1lID0gJ2F1dG9OdW1lcmljR2xvYmFsTGlzdCc7IC8vWFhYIFRoaXMgbG9va3Mgd2VpcmQgdG8gc2V0IGEgdmFyaWFibGUgb24gYHRoaXMuYCBpbiBhIHN0YXRpYyBtZXRob2QsIGJ1dCB0aGF0IHJlYWxseSBkZWNsYXJlIHRoYXQgdmFyaWFibGUgbGlrZSBhIHN0YXRpYyBwcm9wZXJ0eVxuICAgICAgICAvLyBOb3RlOiBJIHNob3VsZCBub3QgZ2V0IGFueSBtZW1vcnkgbGVha3MgZm9yIHJlZmVyZW5jaW5nIHRoZSBET00gZWxlbWVudCBpbiB0aGUgYHZhbHVlYCwgdGhpcyBET00gZWxlbWVudCBhbHNvIGJlaW5nIHRoZSBga2V5YCwgYWNjb3JkaW5nIHRvIHRoZSBzcGVjIDogaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLXdlYWttYXAtb2JqZWN0c1xuICAgICAgICB0aGlzLl9jcmVhdGVXZWFrTWFwKHRoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2xvYmFsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdCBleGlzdHMuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfZG9lc0dsb2JhbExpc3RFeGlzdHMoKSB7XG4gICAgICAgIGNvbnN0IHR5cGUgPSB0eXBlb2Ygd2luZG93W3RoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZV07XG4gICAgICAgIHJldHVybiB0eXBlICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgdHlwZSA9PT0gJ29iamVjdCc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkIHRoZSBnaXZlbiBvYmplY3QgdG8gdGhlIGdsb2JhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0F1dG9OdW1lcmljfSBhdXRvTnVtZXJpY09iamVjdFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9hZGRUb0dsb2JhbExpc3QoYXV0b051bWVyaWNPYmplY3QpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9kb2VzR2xvYmFsTGlzdEV4aXN0cygpKSB7XG4gICAgICAgICAgICB0aGlzLl9jcmVhdGVHbG9iYWxMaXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkb21FbGVtZW50ID0gYXV0b051bWVyaWNPYmplY3Qubm9kZSgpO1xuICAgICAgICAvLyBUaGlzIGNoZWNrcyBpZiB0aGUgb2JqZWN0IGlzIG5vdCBhbHJlYWR5IGluIHRoZSBnbG9iYWwgbGlzdCBiZWZvcmUgYWRkaW5nIGl0LlxuICAgICAgICAvLyBUaGlzIGNvdWxkIGhhcHBlbiBpZiBhbiBBdXRvTnVtZXJpYyBlbGVtZW50IGlzIGluaXRpYWxpemVkLCB0aGVuIHRoZSBET00gZWxlbWVudCBpcyByZW1vdmVkIGRpcmVjdGx5IHZpYSBgcmVtb3ZlQ2hpbGRgIChoZW5jZSB0aGUgcmVmZXJlbmNlIGRvZXMgbm90IGdldCByZW1vdmVkIGZyb20gdGhlIGdsb2JhbCBsaXN0KSwgdGhlbiBpdCBnZXQgcmVjcmVhdGVkIGFuZCBpbml0aWFsaXplZCBhZ2FpblxuICAgICAgICBpZiAodGhpcy5faXNJbkdsb2JhbExpc3QoZG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9nZXRGcm9tR2xvYmFsTGlzdChkb21FbGVtZW50KSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIC8vIERvIG5vdCBhZGQgdGhpcyBBdXRvTnVtZXJpYyBvYmplY3QgYWdhaW4gc2luY2UgaXQncyBhbHJlYWR5IGluIHRoYXQgZ2xvYmFsIGxpc3RcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFByaW50IGEgd2FybmluZyB0byB3YXJuIHRoYXQgdGhlIGRvbUVsZW1lbnQgYWxyZWFkeSBoYXMgYSByZWZlcmVuY2UgaW4gdGhlIGdsb2JhbCBtYXAgKGJ1dCB3ZSBjYW5ub3QgZm9yIHN1cmUgc3RhcnRzIGRlbGV0aW5nIHRob3NlIG9sZCByZWZlcmVuY2VzIHNpbmNlIHRoZXkgY291bGQgc3RpbGwgYmUgdXNlZCBieSBhbm90aGVyIEF1dG9OdW1lcmljIG9iamVjdClcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBBIHJlZmVyZW5jZSB0byB0aGUgRE9NIGVsZW1lbnQgeW91IGp1c3QgaW5pdGlhbGl6ZWQgYWxyZWFkeSBleGlzdHMgaW4gdGhlIGdsb2JhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuIFBsZWFzZSBtYWtlIHN1cmUgdG8gbm90IGluaXRpYWxpemUgdGhlIHNhbWUgRE9NIGVsZW1lbnQgbXVsdGlwbGUgdGltZXMuYCwgYXV0b051bWVyaWNPYmplY3QuZ2V0U2V0dGluZ3MoKS5zaG93V2FybmluZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgd2luZG93W3RoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZV0uc2V0KGRvbUVsZW1lbnQsIGF1dG9OdW1lcmljT2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIGdpdmVuIG9iamVjdCBmcm9tIHRoZSBnbG9iYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtBdXRvTnVtZXJpY30gYXV0b051bWVyaWNPYmplY3RcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfcmVtb3ZlRnJvbUdsb2JhbExpc3QoYXV0b051bWVyaWNPYmplY3QpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgaWYgKHRoaXMuX2RvZXNHbG9iYWxMaXN0RXhpc3RzKCkpIHtcbiAgICAgICAgICAgIHdpbmRvd1t0aGlzLmF1dG9OdW1lcmljR2xvYmFsTGlzdE5hbWVdLmRlbGV0ZShhdXRvTnVtZXJpY09iamVjdC5ub2RlKCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHRvIHRoZSBrZXkgYGRvbUVsZW1lbnRgIHBhc3NlZCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKiBUaGUgdmFsdWUgaXMgdGhlIEF1dG9OdW1lcmljIG9iamVjdCB0aGF0IG1hbmFnZXMgdGhlIERPTSBlbGVtZW50IGBkb21FbGVtZW50YC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudH0gZG9tRWxlbWVudFxuICAgICAqIEByZXR1cm5zIHtudWxsfEF1dG9OdW1lcmljfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9nZXRGcm9tR2xvYmFsTGlzdChkb21FbGVtZW50KSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmICh0aGlzLl9kb2VzR2xvYmFsTGlzdEV4aXN0cygpKSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93W3RoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZV0uZ2V0KGRvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgdGhlIGdpdmVuIERPTSBlbGVtZW50IGlzIGluIHRoZSBnbG9iYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBkb21FbGVtZW50XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2lzSW5HbG9iYWxMaXN0KGRvbUVsZW1lbnQpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgaWYgKCF0aGlzLl9kb2VzR2xvYmFsTGlzdEV4aXN0cygpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gd2luZG93W3RoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZV0uaGFzKGRvbUVsZW1lbnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIGBNYXBgIHRoYXQgd2lsbCBzdG9yZXMgYWxsIHRoZSBhdXRvTnVtZXJpYyBlbGVtZW50cyB0aGF0IGFyZSBpbml0aWFsaXplZCBmcm9tIHRoaXMgY3VycmVudCBlbGVtZW50LlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2NyZWF0ZUxvY2FsTGlzdCgpIHtcbiAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdCA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5fYWRkVG9Mb2NhbExpc3QodGhpcy5kb21FbGVtZW50KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbiBzb21lIHJhcmUgY2FzZXMsIHlvdSBjb3VsZCB3YW50IHRvIGRlbGV0ZSB0aGUgbG9jYWwgbGlzdCBnZW5lcmF0ZWQgZHVyaW5nIHRoZSBlbGVtZW50IGluaXRpYWxpemF0aW9uIChpbiBvcmRlciB0byB1c2UgYW5vdGhlciBvbmUgaW5zdGVhZCBmb3IgaW5zdGFuY2UpLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2RlbGV0ZUxvY2FsTGlzdCgpIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBsb2NhbCBsaXN0IHdpdGggdGhlIGdpdmVuIE1hcCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge01hcH0gbG9jYWxMaXN0XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2V0TG9jYWxMaXN0KGxvY2FsTGlzdCkge1xuICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0ID0gbG9jYWxMaXN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgbG9jYWwgbGlzdCBNYXAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHJldHVybnMgeyp8TWFwfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2dldExvY2FsTGlzdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBhIGxvY2FsIGxpc3QgZGVmaW5lZCBhbHJlYWR5IGFuZCBoYXMgYXQgbGVhc3Qgb25lIGVsZW1lbnQgaW4gaXQgKGl0c2VsZiB1c3VhbGx5KS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2hhc0xvY2FsTGlzdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QgaW5zdGFuY2VvZiBNYXAgJiYgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5zaXplICE9PSAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCB0aGUgZ2l2ZW4gb2JqZWN0IHRvIHRoZSBsb2NhbCBhdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuXG4gICAgICogTm90ZTogaW4gb3JkZXIgdG8ga2VlcCBhIGNvaGVyZW50IGxpc3QsIHdlIG9ubHkgYWRkIERPTSBlbGVtZW50cyBpbiBpdCwgbm90IHRoZSBhdXRvTnVtZXJpYyBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IGRvbUVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge0F1dG9OdW1lcmljfSBhdXRvTnVtZXJpY09iamVjdCBBIHJlZmVyZW5jZSB0byB0aGUgQXV0b051bWVyaWMgb2JqZWN0IHRoYXQgbWFuYWdlIHRoZSBnaXZlbiBET00gZWxlbWVudFxuICAgICAqIEB0aHJvd3NcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9hZGRUb0xvY2FsTGlzdChkb21FbGVtZW50LCBhdXRvTnVtZXJpY09iamVjdCA9IG51bGwpIHtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChhdXRvTnVtZXJpY09iamVjdCkpIHtcbiAgICAgICAgICAgIGF1dG9OdW1lcmljT2JqZWN0ID0gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQodGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdCkpIHtcbiAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3Quc2V0KGRvbUVsZW1lbnQsIGF1dG9OdW1lcmljT2JqZWN0KTsgLy8gVXNlIHRoZSBET00gZWxlbWVudCBhcyBrZXksIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGFzIHRoZSB2YWx1ZVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGxvY2FsIGxpc3QgcHJvdmlkZWQgZG9lcyBub3QgZXhpc3RzIHdoZW4gdHJ5aW5nIHRvIGFkZCBhbiBlbGVtZW50LiBbJHt0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0fV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIGdpdmVuIG9iamVjdCBmcm9tIHRoZSBsb2NhbCBhdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IGRvbUVsZW1lbnRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9yZW1vdmVGcm9tTG9jYWxMaXN0KGRvbUVsZW1lbnQpIHtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZCh0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0KSkge1xuICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5kZWxldGUoZG9tRWxlbWVudCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5jcmVhdGVMb2NhbExpc3QpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBsb2NhbCBsaXN0IHByb3ZpZGVkIGRvZXMgbm90IGV4aXN0cyB3aGVuIHRyeWluZyB0byByZW1vdmUgYW4gZWxlbWVudC4gWyR7dGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdH1dIGdpdmVuLmApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWVyZ2UgdGhlIGBuZXdTZXR0aW5nc2AgZ2l2ZW4gYXMgcGFyYW1ldGVycyBpbnRvIHRoZSBjdXJyZW50IGVsZW1lbnQgc2V0dGluZ3MuXG4gICAgICpcbiAgICAgKiBXQVJOSU5HOiBVc2luZyBgT2JqZWN0LmFzc2lnbigpYCBoZXJlIG1lYW5zIHRoZSBtZXJnZSBpcyBub3QgcmVjdXJzaXZlIGFuZCBvbmx5IG9uZSBkZXB0aCBpcyBtZXJnZWQuXG4gICAgICogY2YuIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzM5MTg4MTA4LzI4MzQ4OThcbiAgICAgKiBjZi4gdGVzdHMgb24gaHR0cDovL2NvZGVwZW4uaW8vQW5vdGhlckxpbnV4VXNlci9wZW4vS2FKT1JxP2VkaXRvcnM9MDAxMVxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG5ld1NldHRpbmdzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfbWVyZ2VTZXR0aW5ncyguLi5uZXdTZXR0aW5ncykge1xuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMuc2V0dGluZ3MsIC4uLm5ld1NldHRpbmdzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBuZXcgb2JqZWN0IHdpdGggdGhlIGN1cnJlbnQgZWxlbWVudCBzZXR0aW5ncyBtZXJnZWQgd2l0aCB0aGUgbmV3IHNldHRpbmdzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG5ld1NldHRpbmdzXG4gICAgICogQHJldHVybnMge29iamVjdH1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9jbG9uZUFuZE1lcmdlU2V0dGluZ3MoLi4ubmV3U2V0dGluZ3MpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0ge307XG4gICAgICAgIE9iamVjdC5hc3NpZ24ocmVzdWx0LCB0aGlzLnNldHRpbmdzLCAuLi5uZXdTZXR0aW5ncyk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBWYWxpZGF0ZSB0aGUgZ2l2ZW4gb3B0aW9uIG9iamVjdC5cbiAgICAgKiBJZiB0aGUgb3B0aW9ucyBhcmUgdmFsaWQsIHRoaXMgZnVuY3Rpb24gcmV0dXJucyBub3RoaW5nLCBvdGhlcndpc2UgaWYgdGhlIG9wdGlvbnMgYXJlIGludmFsaWQsIHRoaXMgZnVuY3Rpb24gdGhyb3dzIGFuIGVycm9yLlxuICAgICAqXG4gICAgICogVGhpcyB0ZXN0cyBpZiB0aGUgb3B0aW9ucyBhcmUgbm90IGNvbmZsaWN0aW5nIGFuZCBhcmUgd2VsbCBmb3JtYXR0ZWQuXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyBsZW5pZW50IHNpbmNlIGl0IG9ubHkgdGVzdHMgdGhlIHNldHRpbmdzIHByb3BlcnRpZXMgOyBpdCBpZ25vcmVzIGFueSBvdGhlciBwcm9wZXJ0aWVzIHRoZSBvcHRpb25zIG9iamVjdCBjb3VsZCBoYXZlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSB1c2VyT3B0aW9uc1xuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gc2hvdWxkRXh0ZW5kRGVmYXVsdE9wdGlvbnMgSWYgYHRydWVgLCB0aGVuIHRoaXMgZnVuY3Rpb24gd2lsbCBleHRlbmRzIHRoZSBgdXNlck9wdGlvbnNgIHBhc3NlZCBieSB0aGUgdXNlciwgd2l0aCB0aGUgZGVmYXVsdCBvcHRpb25zLlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fG51bGx9IG9yaWdpbmFsT3B0aW9ucyBUaGUgdXNlciBjYW4gcGFzcyB0aGUgb3JpZ2luYWwgb3B0aW9ucyAoYW5kIG5vdCB0aGUgb25lIHRoYXQgYXJlIGdlbmVyYXRlZCBmcm9tIHRoZSBkZWZhdWx0IHNldHRpbmdzIGFuZCB0aGUgdmFyaW91cyB1c2FiaWxpdHkgY29ycmVjdGlvbnMpLCBpbiBvcmRlciB0byBhZGQgY29tcGF0aWJpbGl0eSBhbmQgY29uZmxpY3RzIGNoZWNrcy5cbiAgICAgKiBAdGhyb3dzIEVycm9yIFRoaXMgdGhyb3dzIGlmIHRoZSBgdXNlck9wdGlvbnNgIGFyZSBub3QgdmFsaWRcbiAgICAgKi9cbiAgICBzdGF0aWMgdmFsaWRhdGUodXNlck9wdGlvbnMsIHNob3VsZEV4dGVuZERlZmF1bHRPcHRpb25zID0gdHJ1ZSwgb3JpZ2luYWxPcHRpb25zID0gbnVsbCkge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHVzZXJPcHRpb25zKSB8fCAhQXV0b051bWVyaWNIZWxwZXIuaXNPYmplY3QodXNlck9wdGlvbnMpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdXNlck9wdGlvbnMgYXJlIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSB2YWxpZCBvYmplY3QsIFske3VzZXJPcHRpb25zfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpc09yaWdpbmFsT3B0aW9uQW5PYmplY3QgPSBBdXRvTnVtZXJpY0hlbHBlci5pc09iamVjdChvcmlnaW5hbE9wdGlvbnMpO1xuICAgICAgICBpZiAoIWlzT3JpZ2luYWxPcHRpb25Bbk9iamVjdCAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9yaWdpbmFsT3B0aW9ucykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSAnb3JpZ2luYWxPcHRpb25zJyBwYXJhbWV0ZXIgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgYSB2YWxpZCBvcHRpb24gb2JqZWN0IG9yIFxcYG51bGxcXGAsIFske3VzZXJPcHRpb25zfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGUgdXNlciB1c2VkIG9sZCBvcHRpb25zLCB3ZSBjb252ZXJ0IHRoZW0gdG8gbmV3IG9uZXNcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodXNlck9wdGlvbnMpKSB7XG4gICAgICAgICAgICB0aGlzLl9jb252ZXJ0T2xkT3B0aW9uc1RvTmV3T25lcyh1c2VyT3B0aW9ucyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGUgdXNlciBjYW4gY2hvb3NlIGlmIHRoZSBgdXNlck9wdGlvbnNgIGhhcyBhbHJlYWR5IGJlZW4gZXh0ZW5kZWQgd2l0aCB0aGUgZGVmYXVsdCBvcHRpb25zLCBvciBub3RcbiAgICAgICAgbGV0IG9wdGlvbnM7XG4gICAgICAgIGlmIChzaG91bGRFeHRlbmREZWZhdWx0T3B0aW9ucykge1xuICAgICAgICAgICAgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuZ2V0RGVmYXVsdENvbmZpZygpLCB1c2VyT3B0aW9ucyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvcHRpb25zID0gdXNlck9wdGlvbnM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGaXJzdCB0aGluZ3MgZmlyc3QsIHdlIHRlc3QgdGhhdCB0aGUgYHNob3dXYXJuaW5nc2Agb3B0aW9uIGlzIHZhbGlkXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLnNob3dXYXJuaW5ncykgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLnNob3dXYXJuaW5ncykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBkZWJ1ZyBvcHRpb24gJ3Nob3dXYXJuaW5ncycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMuc2hvd1dhcm5pbmdzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZWZpbmUgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbnMgbmVlZGVkIGZvciB0aGUgZm9sbG93aW5nIHRlc3RzXG4gICAgICAgIGNvbnN0IHRlc3RQb3NpdGl2ZUludGVnZXIgPSAvXlswLTldKyQvO1xuICAgICAgICBjb25zdCB0ZXN0TnVtZXJpY2FsQ2hhcmFjdGVycyA9IC9bMC05XSsvO1xuICAgICAgICAvLyBjb25zdCB0ZXN0RmxvYXRBbmRQb3NzaWJsZU5lZ2F0aXZlU2lnbiA9IC9eLT9bMC05XSsoXFwuP1swLTldKykkLztcbiAgICAgICAgY29uc3QgdGVzdEZsb2F0T3JJbnRlZ2VyQW5kUG9zc2libGVOZWdhdGl2ZVNpZ24gPSAvXi0/WzAtOV0rKFxcLj9bMC05XSspPyQvO1xuICAgICAgICBjb25zdCB0ZXN0UG9zaXRpdmVGbG9hdE9ySW50ZWdlciA9IC9eWzAtOV0rKFxcLj9bMC05XSspPyQvO1xuXG4gICAgICAgIC8vIFRoZW4gdGVzdHMgdGhlIG9wdGlvbnMgaW5kaXZpZHVhbGx5XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcpICYmXG4gICAgICAgICAgICAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZykgJiZcbiAgICAgICAgICAgIG9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nLmZsb2F0cykge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGRlY2ltYWwgcGFkZGluZyBvcHRpb24gJ2FsbG93RGVjaW1hbFBhZGRpbmcnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlIFxcYGZhbHNlXFxgLCBcXGB0cnVlXFxgIG9yIFxcYCdmbG9hdHMnXFxgLCBbJHtvcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmd9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgob3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcubmV2ZXIgfHxcbiAgICAgICAgICAgIG9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZyA9PT0gJ2ZhbHNlJykgJiZcbiAgICAgICAgICAgIChvcHRpb25zLmRlY2ltYWxQbGFjZXMgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlcy5ub25lIHx8XG4gICAgICAgICAgICBvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIubm9uZSB8fFxuICAgICAgICAgICAgb3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMubm9uZSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFNldHRpbmcgJ2FsbG93RGVjaW1hbFBhZGRpbmcnIHRvIFske29wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZ31dIHdpbGwgb3ZlcnJpZGUgdGhlIGN1cnJlbnQgJ2RlY2ltYWxQbGFjZXMqJyBzZXR0aW5ncyBbJHtvcHRpb25zLmRlY2ltYWxQbGFjZXN9LCAke29wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyfSBhbmQgJHtvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXN9XS5gLCBvcHRpb25zLnNob3dXYXJuaW5ncyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMsIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuc3RhcnQsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmVuZCxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZGVjaW1hbExlZnQsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmRlY2ltYWxSaWdodCxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBkaXNwbGF5IG9uIGVtcHR5IHN0cmluZyBvcHRpb24gJ2NhcmV0UG9zaXRpb25PbkZvY3VzJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGVpdGhlciBiZSBcXGBudWxsXFxgLCAnZm9jdXMnLCAncHJlc3MnLCAnYWx3YXlzJyBvciAnemVybycsIFske29wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXN9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNwZWNpYWwgY2FzZSBoZXJlIGZvciBgY2FyZXRQb3NpdGlvbk9uRm9jdXNgIGFuZCBgc2VsZWN0T25Gb2N1c2Agd2hlcmUgd2UgbmVlZCB0byBjaGVjayB0aGUgb3JpZ2luYWwgbm9uLXRlbXBlcmVkIHZlcnNpb24gb2YgdGhlIG9wdGlvbnMgaW4gb3JkZXIgdG8gY2hlY2sgZm9yIGNvbmZsaWN0cywgc2luY2UgdXNpbmcgdGhlIGRlZmF1bHQgc2V0dGluZ3MgcmVtb3ZlIHRob3NlIGFuZCB3b3VsZCBwcmV2ZW50IHVzIHdhcm5pbmcgdGhlIHVzZXIgdGhhdCBoaXMgb3B0aW9uIG9iamVjdCBpcyBub3QgY29ycmVjdC5cbiAgICAgICAgbGV0IG9wdGlvbnNUb1VzZTtcbiAgICAgICAgaWYgKGlzT3JpZ2luYWxPcHRpb25Bbk9iamVjdCkge1xuICAgICAgICAgICAgb3B0aW9uc1RvVXNlID0gb3JpZ2luYWxPcHRpb25zO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3B0aW9uc1RvVXNlID0gdGhpcy5fY29ycmVjdENhcmV0UG9zaXRpb25PbkZvY3VzQW5kU2VsZWN0T25Gb2N1c09wdGlvbnModXNlck9wdGlvbnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9uc1RvVXNlKSAmJlxuICAgICAgICAgICAgKChvcHRpb25zVG9Vc2UuY2FyZXRQb3NpdGlvbk9uRm9jdXMgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZG9Ob0ZvcmNlQ2FyZXRQb3NpdGlvbiAmJlxuICAgICAgICAgICAgb3B0aW9uc1RvVXNlLnNlbGVjdE9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuc2VsZWN0T25Gb2N1cy5zZWxlY3QpKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgVGhlICdzZWxlY3RPbkZvY3VzJyBvcHRpb24gaXMgc2V0IHRvICdzZWxlY3QnLCB3aGljaCBpcyBpbiBjb25mbGljdCB3aXRoIHRoZSAnY2FyZXRQb3NpdGlvbk9uRm9jdXMnIHdoaWNoIGlzIHNldCB0byAnJHtvcHRpb25zVG9Vc2UuY2FyZXRQb3NpdGlvbk9uRm9jdXN9Jy4gQXMgYSByZXN1bHQsIGlmIHRoaXMgaGFzIGJlZW4gY2FsbGVkIHdoZW4gaW5zdGFudGlhdGluZyBhbiBBdXRvTnVtZXJpYyBvYmplY3QsIHRoZSAnc2VsZWN0T25Gb2N1cycgb3B0aW9uIGlzIGZvcmNlZCB0byAnZG9Ob3RTZWxlY3QnLmAsIG9wdGlvbnMuc2hvd1dhcm5pbmdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvciwgW1xuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmNvbW1hLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmRvdCxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5ub3JtYWxTcGFjZSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci50aGluU3BhY2UsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IubmFycm93Tm9CcmVha1NwYWNlLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLm5vQnJlYWtTcGFjZSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5ub1NlcGFyYXRvcixcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5hcG9zdHJvcGhlLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmFyYWJpY1Rob3VzYW5kc1NlcGFyYXRvcixcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5kb3RBYm92ZSxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSB0aG91c2FuZCBzZXBhcmF0b3IgY2hhcmFjdGVyIG9wdGlvbiAnZGlnaXRHcm91cFNlcGFyYXRvcicgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSAnLCcsICcuJywgJ9msJywgJ8uZJywgXCInXCIsICcgJywgJ1xcdTIwMDknLCAnXFx1MjAyZicsICdcXHUwMGEwJyBvciBlbXB0eSAoJycpLCBbJHtvcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3J9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLnNob3dPbmx5TnVtYmVyc09uRm9jdXMpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5zaG93T25seU51bWJlcnNPbkZvY3VzKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlICdzaG93T25seU51bWJlcnNPbkZvY3VzJyBvcHRpb24gaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMuc2hvd09ubHlOdW1iZXJzT25Gb2N1c31dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy5kaWdpdGFsR3JvdXBTcGFjaW5nLCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcudHdvLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdGFsR3JvdXBTcGFjaW5nLnR3b1NjYWxlZCxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRhbEdyb3VwU3BhY2luZy50aHJlZSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRhbEdyb3VwU3BhY2luZy5mb3VyLFxuICAgICAgICBdKSAmJiAhKG9wdGlvbnMuZGlnaXRhbEdyb3VwU3BhY2luZyA+PSAyICYmIG9wdGlvbnMuZGlnaXRhbEdyb3VwU3BhY2luZyA8PSA0KSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGdyb3VwaW5nIHNlcGFyYXRvciBvcHRpb24gZm9yIHRob3VzYW5kcyAnZGlnaXRhbEdyb3VwU3BhY2luZycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSAnMicsICcycycsICczJywgb3IgJzQnLCBbJHtvcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmd9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMuZGVjaW1hbENoYXJhY3RlciwgW1xuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmNvbW1hLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmRvdCxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5taWRkbGVEb3QsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuYXJhYmljRGVjaW1hbFNlcGFyYXRvcixcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5kZWNpbWFsU2VwYXJhdG9yS2V5U3ltYm9sLFxuICAgICAgICBdKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGRlY2ltYWwgc2VwYXJhdG9yIGNoYXJhY3RlciBvcHRpb24gJ2RlY2ltYWxDaGFyYWN0ZXInIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgJy4nLCAnLCcsICfCtycsICfijpYnIG9yICfZqycsIFske29wdGlvbnMuZGVjaW1hbENoYXJhY3Rlcn1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2tzIGlmIHRoZSBkZWNpbWFsIGFuZCB0aG91c2FuZCBjaGFyYWN0ZXJzIGFyZSB0aGUgc2FtZVxuICAgICAgICBpZiAob3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyID09PSBvcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYGF1dG9OdW1lcmljIHdpbGwgbm90IGZ1bmN0aW9uIHByb3Blcmx5IHdoZW4gdGhlIGRlY2ltYWwgY2hhcmFjdGVyICdkZWNpbWFsQ2hhcmFjdGVyJyBbJHtvcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXJ9XSBhbmQgdGhlIHRob3VzYW5kIHNlcGFyYXRvciAnZGlnaXRHcm91cFNlcGFyYXRvcicgWyR7b3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yfV0gYXJlIHRoZSBzYW1lIGNoYXJhY3Rlci5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgYWx0ZXJuYXRlIGRlY2ltYWwgc2VwYXJhdG9yIGNoYXJhY3RlciBvcHRpb24gJ2RlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZScgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHN0cmluZywgWyR7b3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmV9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChvcHRpb25zLmN1cnJlbmN5U3ltYm9sICE9PSAnJyAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5jdXJyZW5jeVN5bWJvbCkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBjdXJyZW5jeSBzeW1ib2wgb3B0aW9uICdjdXJyZW5jeVN5bWJvbCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHN0cmluZywgWyR7b3B0aW9ucy5jdXJyZW5jeVN5bWJvbH1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCwgW1xuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXgsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBwbGFjZW1lbnQgb2YgdGhlIGN1cnJlbmN5IHNpZ24gb3B0aW9uICdjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgJ3AnIChwcmVmaXgpIG9yICdzJyAoc3VmZml4KSwgWyR7b3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudH1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCwgW1xuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXgsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeCxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdCxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Lm5vbmUsXG4gICAgICAgIF0pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgcGxhY2VtZW50IG9mIHRoZSBuZWdhdGl2ZSBzaWduIG9wdGlvbiAnbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlICdwJyAocHJlZml4KSwgJ3MnIChzdWZmaXgpLCAnbCcgKGxlZnQpLCAncicgKHJpZ2h0KSBvciAnbnVsbCcsIFske29wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnR9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLnNob3dQb3NpdGl2ZVNpZ24pICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5zaG93UG9zaXRpdmVTaWduKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHNob3cgcG9zaXRpdmUgc2lnbiBvcHRpb24gJ3Nob3dQb3NpdGl2ZVNpZ24nIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLnNob3dQb3NpdGl2ZVNpZ259XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5zdWZmaXhUZXh0KSB8fCAob3B0aW9ucy5zdWZmaXhUZXh0ICE9PSAnJyAmJiAoQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZShvcHRpb25zLnN1ZmZpeFRleHQsIG9wdGlvbnMubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSB8fCB0ZXN0TnVtZXJpY2FsQ2hhcmFjdGVycy50ZXN0KG9wdGlvbnMuc3VmZml4VGV4dCkpKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGFkZGl0aW9uYWwgc3VmZml4IG9wdGlvbiAnc3VmZml4VGV4dCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBub3QgY29udGFpbnMgdGhlIG5lZ2F0aXZlIHNpZ24gJyR7dGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXJ9JyBub3IgYW55IG51bWVyaWNhbCBjaGFyYWN0ZXJzLCBbJHtvcHRpb25zLnN1ZmZpeFRleHR9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpIHx8XG4gICAgICAgICAgICBvcHRpb25zLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlci5sZW5ndGggIT09IDEgfHxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShvcHRpb25zLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikgfHxcbiAgICAgICAgICAgIHRlc3ROdW1lcmljYWxDaGFyYWN0ZXJzLnRlc3Qob3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgbmVnYXRpdmUgc2lnbiBjaGFyYWN0ZXIgb3B0aW9uICduZWdhdGl2ZVNpZ25DaGFyYWN0ZXInIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBzaW5nbGUgY2hhcmFjdGVyLCBhbmQgY2Fubm90IGJlIGFueSBudW1lcmljYWwgY2hhcmFjdGVycywgWyR7b3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXJ9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXIpIHx8XG4gICAgICAgICAgICBvcHRpb25zLnBvc2l0aXZlU2lnbkNoYXJhY3Rlci5sZW5ndGggIT09IDEgfHxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShvcHRpb25zLnBvc2l0aXZlU2lnbkNoYXJhY3RlcikgfHxcbiAgICAgICAgICAgIHRlc3ROdW1lcmljYWxDaGFyYWN0ZXJzLnRlc3Qob3B0aW9ucy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgcG9zaXRpdmUgc2lnbiBjaGFyYWN0ZXIgb3B0aW9uICdwb3NpdGl2ZVNpZ25DaGFyYWN0ZXInIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBzaW5nbGUgY2hhcmFjdGVyLCBhbmQgY2Fubm90IGJlIGFueSBudW1lcmljYWwgY2hhcmFjdGVycywgWyR7b3B0aW9ucy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXJ9XSBnaXZlbi5cXG5JZiB5b3Ugd2FudCB0byBoaWRlIHRoZSBwb3NpdGl2ZSBzaWduIGNoYXJhY3RlciwgeW91IG5lZWQgdG8gc2V0IHRoZSBcXGBzaG93UG9zaXRpdmVTaWduXFxgIG9wdGlvbiB0byBcXGB0cnVlXFxgLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdGlvbnMubmVnYXRpdmVTaWduQ2hhcmFjdGVyID09PSBvcHRpb25zLnBvc2l0aXZlU2lnbkNoYXJhY3Rlcikge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHBvc2l0aXZlICdwb3NpdGl2ZVNpZ25DaGFyYWN0ZXInIGFuZCBuZWdhdGl2ZSAnbmVnYXRpdmVTaWduQ2hhcmFjdGVyJyBzaWduIGNoYXJhY3RlcnMgY2Fubm90IGJlIGlkZW50aWNhbCA7IFske29wdGlvbnMubmVnYXRpdmVTaWduQ2hhcmFjdGVyfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBbbGVmdEJyYWNrZXQsIHJpZ2h0QnJhY2tldF0gPSBBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1cik/WycnLCAnJ106b3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5zcGxpdCgnLCcpO1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMob3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLCBvcHRpb25zLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikgfHxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKG9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlciwgb3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpIHx8XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhvcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSwgb3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpIHx8XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhsZWZ0QnJhY2tldCwgb3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpIHx8XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhyaWdodEJyYWNrZXQsIG9wdGlvbnMubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSB8fFxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMob3B0aW9ucy5zdWZmaXhUZXh0LCBvcHRpb25zLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBuZWdhdGl2ZSBzaWduIGNoYXJhY3RlciBvcHRpb24gJ25lZ2F0aXZlU2lnbkNoYXJhY3RlcicgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBub3QgYmUgZXF1YWwgb3IgYSBwYXJ0IG9mIHRoZSBkaWdpdCBzZXBhcmF0b3IsIHRoZSBkZWNpbWFsIGNoYXJhY3RlciwgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGFsdGVybmF0aXZlLCB0aGUgbmVnYXRpdmUgYnJhY2tldHMgb3IgdGhlIHN1ZmZpeCB0ZXh0LCBbJHtvcHRpb25zLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlcn1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKG9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvciwgb3B0aW9ucy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXIpIHx8XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhvcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIsIG9wdGlvbnMucG9zaXRpdmVTaWduQ2hhcmFjdGVyKSB8fFxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMob3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUsIG9wdGlvbnMucG9zaXRpdmVTaWduQ2hhcmFjdGVyKSB8fFxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMobGVmdEJyYWNrZXQsIG9wdGlvbnMucG9zaXRpdmVTaWduQ2hhcmFjdGVyKSB8fFxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMocmlnaHRCcmFja2V0LCBvcHRpb25zLnBvc2l0aXZlU2lnbkNoYXJhY3RlcikgfHxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKG9wdGlvbnMuc3VmZml4VGV4dCwgb3B0aW9ucy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgcG9zaXRpdmUgc2lnbiBjaGFyYWN0ZXIgb3B0aW9uICdwb3NpdGl2ZVNpZ25DaGFyYWN0ZXInIGlzIGludmFsaWQgOyBpdCBzaG91bGQgbm90IGJlIGVxdWFsIG9yIGEgcGFydCBvZiB0aGUgZGlnaXQgc2VwYXJhdG9yLCB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIsIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBhbHRlcm5hdGl2ZSwgdGhlIG5lZ2F0aXZlIGJyYWNrZXRzIG9yIHRoZSBzdWZmaXggdGV4dCwgWyR7b3B0aW9ucy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXJ9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy5vdmVycmlkZU1pbk1heExpbWl0cywgW1xuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdmVycmlkZU1pbk1heExpbWl0cy5jZWlsaW5nLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdmVycmlkZU1pbk1heExpbWl0cy5mbG9vcixcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMuaWdub3JlLFxuICAgICAgICBdKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG92ZXJyaWRlIG1pbiAmIG1heCBsaW1pdHMgb3B0aW9uICdvdmVycmlkZU1pbk1heExpbWl0cycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgJ2NlaWxpbmcnLCAnZmxvb3InIG9yICdpZ25vcmUnLCBbJHtvcHRpb25zLm92ZXJyaWRlTWluTWF4TGltaXRzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKG9wdGlvbnMubWF4aW11bVZhbHVlKSB8fCAhdGVzdEZsb2F0T3JJbnRlZ2VyQW5kUG9zc2libGVOZWdhdGl2ZVNpZ24udGVzdChvcHRpb25zLm1heGltdW1WYWx1ZSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBtYXhpbXVtIHBvc3NpYmxlIHZhbHVlIG9wdGlvbiAnbWF4aW11bVZhbHVlJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGEgc3RyaW5nIHRoYXQgcmVwcmVzZW50cyBhIHBvc2l0aXZlIG9yIG5lZ2F0aXZlIG51bWJlciwgWyR7b3B0aW9ucy5tYXhpbXVtVmFsdWV9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5taW5pbXVtVmFsdWUpIHx8ICF0ZXN0RmxvYXRPckludGVnZXJBbmRQb3NzaWJsZU5lZ2F0aXZlU2lnbi50ZXN0KG9wdGlvbnMubWluaW11bVZhbHVlKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG1pbmltdW0gcG9zc2libGUgdmFsdWUgb3B0aW9uICdtaW5pbXVtVmFsdWUnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBzdHJpbmcgdGhhdCByZXByZXNlbnRzIGEgcG9zaXRpdmUgb3IgbmVnYXRpdmUgbnVtYmVyLCBbJHtvcHRpb25zLm1pbmltdW1WYWx1ZX1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcnNlRmxvYXQob3B0aW9ucy5taW5pbXVtVmFsdWUpID4gcGFyc2VGbG9hdChvcHRpb25zLm1heGltdW1WYWx1ZSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBtaW5pbXVtIHBvc3NpYmxlIHZhbHVlIG9wdGlvbiBpcyBncmVhdGVyIHRoYW4gdGhlIG1heGltdW0gcG9zc2libGUgdmFsdWUgb3B0aW9uIDsgJ21pbmltdW1WYWx1ZScgWyR7b3B0aW9ucy5taW5pbXVtVmFsdWV9XSBzaG91bGQgYmUgc21hbGxlciB0aGFuICdtYXhpbXVtVmFsdWUnIFske29wdGlvbnMubWF4aW11bVZhbHVlfV0uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISgoQXV0b051bWVyaWNIZWxwZXIuaXNJbnQob3B0aW9ucy5kZWNpbWFsUGxhY2VzKSAmJiBvcHRpb25zLmRlY2ltYWxQbGFjZXMgPj0gMCkgfHwgLy8gSWYgaW50ZWdlciBvcHRpb25cbiAgICAgICAgICAgIChBdXRvTnVtZXJpY0hlbHBlci5pc1N0cmluZyhvcHRpb25zLmRlY2ltYWxQbGFjZXMpICYmIHRlc3RQb3NpdGl2ZUludGVnZXIudGVzdChvcHRpb25zLmRlY2ltYWxQbGFjZXMpKSkgLy8gSWYgc3RyaW5nIG9wdGlvblxuICAgICAgICApIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgb3B0aW9uICdkZWNpbWFsUGxhY2VzJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGEgcG9zaXRpdmUgaW50ZWdlciwgWyR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIShBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpIHx8XG4gICAgICAgICAgICAoQXV0b051bWVyaWNIZWxwZXIuaXNJbnQob3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpICYmIG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID49IDApIHx8IC8vIElmIGludGVnZXIgb3B0aW9uXG4gICAgICAgICAgICAoQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpICYmIHRlc3RQb3NpdGl2ZUludGVnZXIudGVzdChvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSkpKSAvLyBJZiBzdHJpbmcgb3B0aW9uXG4gICAgICAgICkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBmb3IgdGhlIHJhdyB2YWx1ZSBvcHRpb24gJ2RlY2ltYWxQbGFjZXNSYXdWYWx1ZScgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHBvc2l0aXZlIGludGVnZXIgb3IgXFxgbnVsbFxcYCwgWyR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWV9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrcyBpZiB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGZvciB0aGUgcmF3IHZhbHVlIGlzIGxvd2VyIHRoYW4gdGhlIGBkZWNpbWFsUGxhY2VzYCwgYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNgIGFuZC9vciBgZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyYCBvcHRpb25zXG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKG9wdGlvbnMpO1xuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cykgJiZcbiAgICAgICAgICAgICF0ZXN0UG9zaXRpdmVJbnRlZ2VyLnRlc3QoU3RyaW5nKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cykpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgbnVtYmVyIG9mIGV4cGFuZGVkIGRlY2ltYWwgcGxhY2VzIG9wdGlvbiAnZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHBvc2l0aXZlIGludGVnZXIgb3IgXFxgbnVsbFxcYCwgWyR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVja3MgaWYgdGhlIGV4dGVuZGVkIGRlY2ltYWwgcGxhY2VzIFwiZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1c1wiIGlzIGdyZWF0ZXIgdGhhbiB0aGUgZGVjaW1hbCBwbGFjZXMgbnVtYmVyIGBkZWNpbWFsUGxhY2VzYFxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMpICYmIE51bWJlcihvcHRpb25zLmRlY2ltYWxQbGFjZXMpID4gTnVtYmVyKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFRoZSBleHRlbmRlZCBkZWNpbWFsIHBsYWNlcyAnZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cycgWyR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzfV0gc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiB0aGUgJ2RlY2ltYWxQbGFjZXMnIFske29wdGlvbnMuZGVjaW1hbFBsYWNlc31dIHZhbHVlLiBDdXJyZW50bHksIHRoaXMgd2lsbCBsaW1pdCB0aGUgYWJpbGl0eSBvZiB5b3VyIHVzZXIgdG8gbWFudWFsbHkgY2hhbmdlIHNvbWUgb2YgdGhlIGRlY2ltYWwgcGxhY2VzLiBEbyB5b3UgcmVhbGx5IHdhbnQgdG8gZG8gdGhhdD9gLCBvcHRpb25zLnNob3dXYXJuaW5ncyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLmRpdmlzb3JXaGVuVW5mb2N1c2VkKSAmJlxuICAgICAgICAgICAgIXRlc3RQb3NpdGl2ZUZsb2F0T3JJbnRlZ2VyLnRlc3Qob3B0aW9ucy5kaXZpc29yV2hlblVuZm9jdXNlZCkgfHxcbiAgICAgICAgICAgIG9wdGlvbnMuZGl2aXNvcldoZW5VbmZvY3VzZWQgPT09IDAgfHwgb3B0aW9ucy5kaXZpc29yV2hlblVuZm9jdXNlZCA9PT0gJzAnIHx8XG4gICAgICAgICAgICBvcHRpb25zLmRpdmlzb3JXaGVuVW5mb2N1c2VkID09PSAxIHx8IG9wdGlvbnMuZGl2aXNvcldoZW5VbmZvY3VzZWQgPT09ICcxJykge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGRpdmlzb3Igb3B0aW9uICdkaXZpc29yV2hlblVuZm9jdXNlZCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHBvc2l0aXZlIG51bWJlciBoaWdoZXIgdGhhbiBvbmUsIHByZWZlcmFibHkgYW4gaW50ZWdlciwgWyR7b3B0aW9ucy5kaXZpc29yV2hlblVuZm9jdXNlZH1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIpICYmICF0ZXN0UG9zaXRpdmVJbnRlZ2VyLnRlc3Qob3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgbnVtYmVyIG9mIGRlY2ltYWxzIHNob3duIHdoZW4gdW5mb2N1c2VkIG9wdGlvbiAnZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGEgcG9zaXRpdmUgaW50ZWdlciBvciBcXGBudWxsXFxgLCBbJHtvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cn1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5zeW1ib2xXaGVuVW5mb2N1c2VkKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5zeW1ib2xXaGVuVW5mb2N1c2VkKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHN5bWJvbCB0byBzaG93IHdoZW4gdW5mb2N1c2VkIG9wdGlvbiAnc3ltYm9sV2hlblVuZm9jdXNlZCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHN0cmluZywgWyR7b3B0aW9ucy5zeW1ib2xXaGVuVW5mb2N1c2VkfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy5zYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMuc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBzYXZlIHRvIHNlc3Npb24gc3RvcmFnZSBvcHRpb24gJ3NhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLnNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2V9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMub25JbnZhbGlkUGFzdGUsIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuZXJyb3IsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmlnbm9yZSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuY2xhbXAsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLnRydW5jYXRlLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5yZXBsYWNlLFxuICAgICAgICBdKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHBhc3RlIGJlaGF2aW9yIG9wdGlvbiAnb25JbnZhbGlkUGFzdGUnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlICdlcnJvcicsICdpZ25vcmUnLCAnY2xhbXAnLCAndHJ1bmNhdGUnIG9yICdyZXBsYWNlJyAoY2YuIGRvY3VtZW50YXRpb24pLCBbJHtvcHRpb25zLm9uSW52YWxpZFBhc3RlfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShvcHRpb25zLnJvdW5kaW5nTWV0aG9kLCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZVcFN5bW1ldHJpYyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZlVwQXN5bW1ldHJpYyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZkRvd25TeW1tZXRyaWMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZEb3duQXN5bW1ldHJpYyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZkV2ZW5CYW5rZXJzUm91bmRpbmcsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnVwUm91bmRBd2F5RnJvbVplcm8sXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmRvd25Sb3VuZFRvd2FyZFplcm8sXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnRvQ2VpbGluZ1Rvd2FyZFBvc2l0aXZlSW5maW5pdHksXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnRvRmxvb3JUb3dhcmROZWdhdGl2ZUluZmluaXR5LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC50b05lYXJlc3QwNSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QudG9OZWFyZXN0MDVBbHQsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnVwVG9OZXh0MDUsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmRvd25Ub05leHQwNSxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSByb3VuZGluZyBtZXRob2Qgb3B0aW9uICdyb3VuZGluZ01ldGhvZCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgJ1MnLCAnQScsICdzJywgJ2EnLCAnQicsICdVJywgJ0QnLCAnQycsICdGJywgJ04wNScsICdDSEYnLCAnVTA1JyBvciAnRDA1JyAoY2YuIGRvY3VtZW50YXRpb24pLCBbJHtvcHRpb25zLnJvdW5kaW5nTWV0aG9kfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIsIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIucGFyZW50aGVzZXMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLmJyYWNrZXRzLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5jaGV2cm9ucyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIuY3VybHlCcmFjZXMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLmFuZ2xlQnJhY2tldHMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLmphcGFuZXNlUXVvdGF0aW9uTWFya3MsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLmhhbGZCcmFja2V0cyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIud2hpdGVTcXVhcmVCcmFja2V0cyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIucXVvdGF0aW9uTWFya3MsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLmd1aWxsZW1ldHMsXG4gICAgICAgIF0pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgYnJhY2tldHMgZm9yIG5lZ2F0aXZlIHZhbHVlcyBvcHRpb24gJ25lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGVpdGhlciBiZSAnKCwpJywgJ1ssXScsICc8LD4nLCAneyx9JywgJ+OAiCzjgIknLCAn772iLO+9oycsICfiuKQs4rilJywgJ+Kfpizin6cnLCAn4oC5LOKAuicgb3IgJ8KrLMK7JywgWyR7b3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1cn1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IsIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLmZvY3VzLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IucHJlc3MsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5hbHdheXMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci56ZXJvLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubnVsbCxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBkaXNwbGF5IG9uIGVtcHR5IHN0cmluZyBvcHRpb24gJ2VtcHR5SW5wdXRCZWhhdmlvcicgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgJ2ZvY3VzJywgJ3ByZXNzJywgJ2Fsd2F5cycsICd6ZXJvJyBvciAnbnVsbCcsIFske29wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLnplcm8gJiZcbiAgICAgICAgICAgIChvcHRpb25zLm1pbmltdW1WYWx1ZSA+IDAgfHwgb3B0aW9ucy5tYXhpbXVtVmFsdWUgPCAwKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlICdlbXB0eUlucHV0QmVoYXZpb3InIG9wdGlvbiBpcyBzZXQgdG8gJ3plcm8nLCBidXQgdGhpcyB2YWx1ZSBpcyBvdXRzaWRlIG9mIHRoZSByYW5nZSBkZWZpbmVkIGJ5ICdtaW5pbXVtVmFsdWUnIGFuZCAnbWF4aW11bVZhbHVlJyBbJHtvcHRpb25zLm1pbmltdW1WYWx1ZX0sICR7b3B0aW9ucy5tYXhpbXVtVmFsdWV9XS5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLmV2ZW50QnViYmxlcykgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLmV2ZW50QnViYmxlcykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBldmVudCBidWJibGVzIG9wdGlvbiAnZXZlbnRCdWJibGVzJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGVpdGhlciAndHJ1ZScgb3IgJ2ZhbHNlJywgWyR7b3B0aW9ucy5ldmVudEJ1YmJsZXN9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLmV2ZW50SXNDYW5jZWxhYmxlKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMuZXZlbnRJc0NhbmNlbGFibGUpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZXZlbnQgaXMgY2FuY2VsYWJsZSBvcHRpb24gJ2V2ZW50SXNDYW5jZWxhYmxlJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGVpdGhlciAndHJ1ZScgb3IgJ2ZhbHNlJywgWyR7b3B0aW9ucy5ldmVudElzQ2FuY2VsYWJsZX1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy5sZWFkaW5nWmVybywgW1xuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5hbGxvdyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8uZGVueSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8ua2VlcCxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBsZWFkaW5nIHplcm8gYmVoYXZpb3Igb3B0aW9uICdsZWFkaW5nWmVybycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgJ2FsbG93JywgJ2RlbnknIG9yICdrZWVwJywgWyR7b3B0aW9ucy5sZWFkaW5nWmVyb31dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1RydWVPckZhbHNlU3RyaW5nKG9wdGlvbnMuZm9ybWF0T25QYWdlTG9hZCkgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLmZvcm1hdE9uUGFnZUxvYWQpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZm9ybWF0IG9uIGluaXRpYWxpemF0aW9uIG9wdGlvbiAnZm9ybWF0T25QYWdlTG9hZCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMuZm9ybWF0T25QYWdlTG9hZH1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCF0ZXN0UG9zaXRpdmVJbnRlZ2VyLnRlc3Qob3B0aW9ucy5oaXN0b3J5U2l6ZSkgfHwgb3B0aW9ucy5oaXN0b3J5U2l6ZSA9PT0gMCkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGhpc3Rvcnkgc2l6ZSBvcHRpb24gJ2hpc3RvcnlTaXplJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGEgcG9zaXRpdmUgaW50ZWdlciwgWyR7b3B0aW9ucy5oaXN0b3J5U2l6ZX1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1RydWVPckZhbHNlU3RyaW5nKG9wdGlvbnMuc2VsZWN0TnVtYmVyT25seSkgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLnNlbGVjdE51bWJlck9ubHkpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgc2VsZWN0IG51bWJlciBvbmx5IG9wdGlvbiAnc2VsZWN0TnVtYmVyT25seScgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMuc2VsZWN0TnVtYmVyT25seX1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1RydWVPckZhbHNlU3RyaW5nKG9wdGlvbnMuc2VsZWN0T25Gb2N1cykgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLnNlbGVjdE9uRm9jdXMpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgc2VsZWN0IG9uIGZvY3VzIG9wdGlvbiAnc2VsZWN0T25Gb2N1cycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMuc2VsZWN0T25Gb2N1c31dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5kZWZhdWx0VmFsdWVPdmVycmlkZSkgJiYgKG9wdGlvbnMuZGVmYXVsdFZhbHVlT3ZlcnJpZGUgIT09ICcnICYmICF0ZXN0RmxvYXRPckludGVnZXJBbmRQb3NzaWJsZU5lZ2F0aXZlU2lnbi50ZXN0KG9wdGlvbnMuZGVmYXVsdFZhbHVlT3ZlcnJpZGUpKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHVuZm9ybWF0dGVkIGRlZmF1bHQgdmFsdWUgb3B0aW9uICdkZWZhdWx0VmFsdWVPdmVycmlkZScgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHN0cmluZyB0aGF0IHJlcHJlc2VudHMgYSBwb3NpdGl2ZSBvciBuZWdhdGl2ZSBudW1iZXIsIFske29wdGlvbnMuZGVmYXVsdFZhbHVlT3ZlcnJpZGV9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLnVuZm9ybWF0T25TdWJtaXQpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy51bmZvcm1hdE9uU3VibWl0KSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHJlbW92ZSBmb3JtYXR0aW5nIG9uIHN1Ym1pdCBvcHRpb24gJ3VuZm9ybWF0T25TdWJtaXQnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLnVuZm9ybWF0T25TdWJtaXR9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMudmFsdWVzVG9TdHJpbmdzKSAmJlxuICAgICAgICAgICAgIShBdXRvTnVtZXJpY0hlbHBlci5pc09iamVjdChvcHRpb25zLnZhbHVlc1RvU3RyaW5ncykpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgb3B0aW9uICd2YWx1ZXNUb1N0cmluZ3MnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYW4gb2JqZWN0LCBpZGVhbGx5IHdpdGggJ2tleSAtPiB2YWx1ZScgZW50cmllcywgWyR7b3B0aW9ucy52YWx1ZXNUb1N0cmluZ3N9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMub3V0cHV0Rm9ybWF0KSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMub3V0cHV0Rm9ybWF0LCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5zdHJpbmcsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5udW1iZXIsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5kb3QsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5uZWdhdGl2ZURvdCxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0LmNvbW1hLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQubmVnYXRpdmVDb21tYSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0LmRvdE5lZ2F0aXZlLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQuY29tbWFOZWdhdGl2ZSxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBjdXN0b20gbG9jYWxlIGZvcm1hdCBvcHRpb24gJ291dHB1dEZvcm1hdCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgbnVsbCwgJ3N0cmluZycsICdudW1iZXInLCAnLicsICctLicsICcsJywgJy0sJywgJy4tJyBvciAnLC0nLCBbJHtvcHRpb25zLm91dHB1dEZvcm1hdH1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1RydWVPckZhbHNlU3RyaW5nKG9wdGlvbnMuaXNDYW5jZWxsYWJsZSkgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLmlzQ2FuY2VsbGFibGUpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgY2FuY2VsbGFibGUgYmVoYXZpb3Igb3B0aW9uICdpc0NhbmNlbGxhYmxlJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGVpdGhlciAnZmFsc2UnIG9yICd0cnVlJywgWyR7b3B0aW9ucy5pc0NhbmNlbGxhYmxlfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy5tb2RpZnlWYWx1ZU9uV2hlZWwpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5tb2RpZnlWYWx1ZU9uV2hlZWwpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgaW5jcmVtZW50L2RlY3JlbWVudCBvbiBtb3VzZSB3aGVlbCBvcHRpb24gJ21vZGlmeVZhbHVlT25XaGVlbCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMubW9kaWZ5VmFsdWVPbldoZWVsfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy53YXRjaEV4dGVybmFsQ2hhbmdlcykgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLndhdGNoRXh0ZXJuYWxDaGFuZ2VzKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG9wdGlvbiAnd2F0Y2hFeHRlcm5hbENoYW5nZXMnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLndhdGNoRXh0ZXJuYWxDaGFuZ2VzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShvcHRpb25zLndoZWVsT24sIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMud2hlZWxPbi5mb2N1cyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMud2hlZWxPbi5ob3ZlcixcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSB3aGVlbCBiZWhhdmlvciBvcHRpb24gJ3doZWVsT24nIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlICdmb2N1cycgb3IgJ2hvdmVyJywgWyR7b3B0aW9ucy53aGVlbE9ufV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIShBdXRvTnVtZXJpY0hlbHBlci5pc1N0cmluZyhvcHRpb25zLndoZWVsU3RlcCkgfHwgQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIob3B0aW9ucy53aGVlbFN0ZXApKSB8fFxuICAgICAgICAgICAgKG9wdGlvbnMud2hlZWxTdGVwICE9PSAncHJvZ3Jlc3NpdmUnICYmICF0ZXN0UG9zaXRpdmVGbG9hdE9ySW50ZWdlci50ZXN0KG9wdGlvbnMud2hlZWxTdGVwKSkgfHxcbiAgICAgICAgICAgIE51bWJlcihvcHRpb25zLndoZWVsU3RlcCkgPT09IDApIHtcbiAgICAgICAgICAgIC8vIEEgc3RlcCBlcXVhbCB0byAnMCcgaXMgcmVqZWN0ZWRcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSB3aGVlbCBzdGVwIHZhbHVlIG9wdGlvbiAnd2hlZWxTdGVwJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGVpdGhlciBiZSB0aGUgc3RyaW5nICdwcm9ncmVzc2l2ZScsIG9yIGEgbnVtYmVyIG9yIGEgc3RyaW5nIHRoYXQgcmVwcmVzZW50cyBhIHBvc2l0aXZlIG51bWJlciAoZXhjbHVkaW5nIHplcm8pLCBbJHtvcHRpb25zLndoZWVsU3RlcH1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy5zZXJpYWxpemVTcGFjZXMsIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuc2VyaWFsaXplU3BhY2VzLnBsdXMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnNlcmlhbGl6ZVNwYWNlcy5wZXJjZW50LFxuICAgICAgICBdKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHNwYWNlIHJlcGxhY2VtZW50IGNoYXJhY3RlciBvcHRpb24gJ3NlcmlhbGl6ZVNwYWNlcycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgJysnIG9yICclMjAnLCBbJHtvcHRpb25zLnNlcmlhbGl6ZVNwYWNlc31dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1RydWVPckZhbHNlU3RyaW5nKG9wdGlvbnMubm9FdmVudExpc3RlbmVycykgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLm5vRXZlbnRMaXN0ZW5lcnMpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgb3B0aW9uICdub0V2ZW50TGlzdGVuZXJzJyB0aGF0IHByZXZlbnQgdGhlIGNyZWF0aW9uIG9mIGV2ZW50IGxpc3RlbmVycyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGVpdGhlciAnZmFsc2UnIG9yICd0cnVlJywgWyR7b3B0aW9ucy5ub0V2ZW50TGlzdGVuZXJzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLnN0eWxlUnVsZXMpICYmXG4gICAgICAgICAgICAhKEF1dG9OdW1lcmljSGVscGVyLmlzT2JqZWN0KG9wdGlvbnMuc3R5bGVSdWxlcykgJiZcbiAgICAgICAgICAgICgob3B0aW9ucy5zdHlsZVJ1bGVzLmhhc093blByb3BlcnR5KCdwb3NpdGl2ZScpIHx8XG4gICAgICAgICAgICBvcHRpb25zLnN0eWxlUnVsZXMuaGFzT3duUHJvcGVydHkoJ25lZ2F0aXZlJykgfHxcbiAgICAgICAgICAgIG9wdGlvbnMuc3R5bGVSdWxlcy5oYXNPd25Qcm9wZXJ0eSgncmFuZ2VzJykgfHxcbiAgICAgICAgICAgIG9wdGlvbnMuc3R5bGVSdWxlcy5oYXNPd25Qcm9wZXJ0eSgndXNlckRlZmluZWQnKSkpKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG9wdGlvbiAnc3R5bGVSdWxlcycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIGNvcnJlY3RseSBzdHJ1Y3R1cmVkIG9iamVjdCwgd2l0aCBvbmUgb3IgbW9yZSAncG9zaXRpdmUnLCAnbmVnYXRpdmUnLCAncmFuZ2VzJyBvciAndXNlckRlZmluZWQnIGF0dHJpYnV0ZXMsIFske29wdGlvbnMuc3R5bGVSdWxlc31dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVlcGVyIHRlc3RzIG9mIHRoZSBgc3R5bGVSdWxlc2Agb2JqZWN0IDogQ2hlY2sgdGhhdCB0aGUgY2FsbGJhY2ssIGlmIGRlZmluZWQsIGlzIGEgZnVuY3Rpb25cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5zdHlsZVJ1bGVzKSAmJlxuICAgICAgICAgICAgb3B0aW9ucy5zdHlsZVJ1bGVzLmhhc093blByb3BlcnR5KCd1c2VyRGVmaW5lZCcpICYmXG4gICAgICAgICAgICAhQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMuc3R5bGVSdWxlcy51c2VyRGVmaW5lZCkpIHtcbiAgICAgICAgICAgIG9wdGlvbnMuc3R5bGVSdWxlcy51c2VyRGVmaW5lZC5mb3JFYWNoKHJ1bGUgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChydWxlLmhhc093blByb3BlcnR5KCdjYWxsYmFjaycpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKHJ1bGUuY2FsbGJhY2spKSB7XG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBjYWxsYmFjayBkZWZpbmVkIGluIHRoZSBcXGB1c2VyRGVmaW5lZFxcYCBhdHRyaWJ1dGUgaXMgbm90IGEgZnVuY3Rpb24sICR7dHlwZW9mIHJ1bGUuY2FsbGJhY2t9IGdpdmVuLmApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5yYXdWYWx1ZURpdmlzb3IpICYmXG4gICAgICAgICAgICAhdGVzdFBvc2l0aXZlRmxvYXRPckludGVnZXIudGVzdChvcHRpb25zLnJhd1ZhbHVlRGl2aXNvcikgfHxcbiAgICAgICAgICAgIG9wdGlvbnMucmF3VmFsdWVEaXZpc29yID09PSAwIHx8IG9wdGlvbnMucmF3VmFsdWVEaXZpc29yID09PSAnMCcgfHxcbiAgICAgICAgICAgIG9wdGlvbnMucmF3VmFsdWVEaXZpc29yID09PSAxIHx8IG9wdGlvbnMucmF3VmFsdWVEaXZpc29yID09PSAnMScpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSByYXcgdmFsdWUgZGl2aXNvciBvcHRpb24gJ3Jhd1ZhbHVlRGl2aXNvcicgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHBvc2l0aXZlIG51bWJlciBoaWdoZXIgdGhhbiBvbmUsIHByZWZlcmFibHkgYW4gaW50ZWdlciwgWyR7b3B0aW9ucy5yYXdWYWx1ZURpdmlzb3J9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLnJlYWRPbmx5KSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMucmVhZE9ubHkpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgb3B0aW9uICdyZWFkT25seScgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMucmVhZE9ubHl9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLnVuZm9ybWF0T25Ib3ZlcikgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLnVuZm9ybWF0T25Ib3ZlcikpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBvcHRpb24gJ3VuZm9ybWF0T25Ib3ZlcicgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMudW5mb3JtYXRPbkhvdmVyfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy5mYWlsT25Vbmtub3duT3B0aW9uKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMuZmFpbE9uVW5rbm93bk9wdGlvbikpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBkZWJ1ZyBvcHRpb24gJ2ZhaWxPblVua25vd25PcHRpb24nIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLmZhaWxPblVua25vd25PcHRpb259XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLmNyZWF0ZUxvY2FsTGlzdCkgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLmNyZWF0ZUxvY2FsTGlzdCkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBkZWJ1ZyBvcHRpb24gJ2NyZWF0ZUxvY2FsTGlzdCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMuY3JlYXRlTG9jYWxMaXN0fV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayB0aGUgYGRlY2ltYWxQbGFjZXMqYCBvcHRpb25zIGFuZCBvdXRwdXQgdGhlIHJlbGV2YW50IHdhcm5pbmdzIGlmIHNvbWUgb2YgdGhvc2Ugd2lsbCBnZXQgb3ZlcndyaXR0ZW4gZHVyaW5nIHRoZSBpbml0aWFsaXphdGlvbiBvciBzZXR0aW5ncyB1cGRhdGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF92YWxpZGF0ZURlY2ltYWxQbGFjZXNSYXdWYWx1ZShvcHRpb25zKSB7XG4gICAgICAgIC8vIENoZWNrcyBpZiB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGZvciB0aGUgcmF3IHZhbHVlIGlzIGxvd2VyIHRoYW4gdGhlIGBkZWNpbWFsUGxhY2VzYCwgYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNgIGFuZC9vciBgZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyYCBvcHRpb25zXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKSkge1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDwgb3B0aW9ucy5kZWNpbWFsUGxhY2VzKSB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgVGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0byBzdG9yZSBpbiB0aGUgcmF3IHZhbHVlIFske29wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlfV0gaXMgbG93ZXIgdGhhbiB0aGUgb25lcyB0byBkaXNwbGF5IFske29wdGlvbnMuZGVjaW1hbFBsYWNlc31dLiBUaGlzIHdpbGwgbGlrZWx5IGNvbmZ1c2UgeW91ciB1c2Vycy5cblRvIHNvbHZlIHRoYXQsIHlvdSdkIG5lZWQgdG8gZWl0aGVyIHNldCBcXGBkZWNpbWFsUGxhY2VzUmF3VmFsdWVcXGAgdG8gXFxgbnVsbFxcYCwgb3Igc2V0IGEgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGZvciB0aGUgcmF3IHZhbHVlIGVxdWFsIG9mIGJpZ2dlciB0aGFuIFxcYGRlY2ltYWxQbGFjZXNcXGAuYCwgb3B0aW9ucy5zaG93V2FybmluZ3MpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUgPCBvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMpIHtcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBUaGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHN0b3JlIGluIHRoZSByYXcgdmFsdWUgWyR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWV9XSBpcyBsb3dlciB0aGFuIHRoZSBvbmVzIHNob3duIG9uIGZvY3VzIFske29wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1c31dLiBUaGlzIHdpbGwgbGlrZWx5IGNvbmZ1c2UgeW91ciB1c2Vycy5cblRvIHNvbHZlIHRoYXQsIHlvdSdkIG5lZWQgdG8gZWl0aGVyIHNldCBcXGBkZWNpbWFsUGxhY2VzUmF3VmFsdWVcXGAgdG8gXFxgbnVsbFxcYCwgb3Igc2V0IGEgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGZvciB0aGUgcmF3IHZhbHVlIGVxdWFsIG9mIGJpZ2dlciB0aGFuIFxcYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNcXGAuYCwgb3B0aW9ucy5zaG93V2FybmluZ3MpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAob3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUgPCBvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cikge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8gc3RvcmUgaW4gdGhlIHJhdyB2YWx1ZSBbJHtvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZX1dIGlzIGxvd2VyIHRoYW4gdGhlIG9uZXMgc2hvd24gd2hlbiB1bmZvY3VzZWQgWyR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXJ9XS4gVGhpcyB3aWxsIGxpa2VseSBjb25mdXNlIHlvdXIgdXNlcnMuXG5UbyBzb2x2ZSB0aGF0LCB5b3UnZCBuZWVkIHRvIGVpdGhlciBzZXQgXFxgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlXFxgIHRvIFxcYG51bGxcXGAsIG9yIHNldCBhIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBmb3IgdGhlIHJhdyB2YWx1ZSBlcXVhbCBvZiBiaWdnZXIgdGhhbiBcXGBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXJcXGAuYCwgb3B0aW9ucy5zaG93V2FybmluZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgc2V0dGluZ3Mvb3B0aW9ucyBhcmUgdmFsaWQsIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgYXJlU2V0dGluZ3NWYWxpZChvcHRpb25zKSB7XG4gICAgICAgIGxldCBpc1ZhbGlkID0gdHJ1ZTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMudmFsaWRhdGUob3B0aW9ucywgdHJ1ZSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBpc1ZhbGlkID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gaXNWYWxpZDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIGRlZmF1bHQgYXV0b051bWVyaWMgc2V0dGluZ3MuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7b2JqZWN0fVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXREZWZhdWx0Q29uZmlnKCkge1xuICAgICAgICByZXR1cm4gQXV0b051bWVyaWMuZGVmYXVsdFNldHRpbmdzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhbGwgdGhlIHByZWRlZmluZWQgbGFuZ3VhZ2Ugb3B0aW9ucyBpbiBvbmUgb2JqZWN0LlxuICAgICAqIFlvdSBjYW4gYWxzbyBhY2Nlc3MgYSBzcGVjaWZpYyBsYW5ndWFnZSBvYmplY3QgZGlyZWN0bHkgYnkgdXNpbmcgYEF1dG9OdW1lcmljLmdldFByZWRlZmluZWRPcHRpb25zKCkuRnJlbmNoYCBmb3IgaW5zdGFuY2UuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7b2JqZWN0fVxuICAgICAqL1xuICAgIHN0YXRpYyBnZXRQcmVkZWZpbmVkT3B0aW9ucygpIHtcbiAgICAgICAgcmV0dXJuIEF1dG9OdW1lcmljLnByZWRlZmluZWRPcHRpb25zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFuYWx5c2UgdGhlIGdpdmVuIGFycmF5IGBvcHRpb25zYCBhbmQgcmV0dXJuIGEgc2luZ2xlICdtZXJnZWQnIG9wdGlvbiBvYmpldC5cbiAgICAgKiBgb3B0aW9uc2AgY2FuIGJlIGBudWxsYCwgb3IgYW4gYXJyYXkgb2YgYW4gb3B0aW9uIG9iamVjdHMsIG9yIGFuIGFycmF5IGNvbnRhaW5pbmcgYW5vdGhlciBhcnJheSBvZiBvcHRpb24gb2JqZWN0cyAvIHN0cmluZ3MgKHByZS1kZWZpbmVkIG9wdGlvbiBuYW1lcylcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVsbHxBcnJheTxvYmplY3R8c3RyaW5nfEFycmF5PHN0cmluZ3xvYmplY3Q+Pn0gb3B0aW9uc1xuICAgICAqIEByZXR1cm5zIHtudWxsfG9iamVjdH1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfZ2VuZXJhdGVPcHRpb25zT2JqZWN0RnJvbU9wdGlvbnNBcnJheShvcHRpb25zKSB7XG4gICAgICAgIGxldCBvcHRpb25zUmVzdWx0O1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KG9wdGlvbnMpIHx8IG9wdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICBvcHRpb25zUmVzdWx0ID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9wdGlvbnNSZXN1bHQgPSB7fTtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmxlbmd0aCA9PT0gMSAmJiBBcnJheS5pc0FycmF5KG9wdGlvbnNbMF0pKSB7XG4gICAgICAgICAgICAgICAgb3B0aW9uc1swXS5mb3JFYWNoKG9wdGlvbk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFVzaW5nIGBfZ2V0T3B0aW9uT2JqZWN0KClgIGFsbG93cyB1c2luZyBwcmUtZGVmaW5lZCBuYW1lcyBpbiB0aGUgYG9wdGlvbnNgIGFycmF5XG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24ob3B0aW9uc1Jlc3VsdCwgdGhpcy5fZ2V0T3B0aW9uT2JqZWN0KG9wdGlvbk9iamVjdCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zLmxlbmd0aCA+PSAxKSB7XG4gICAgICAgICAgICAgICAgb3B0aW9ucy5mb3JFYWNoKG9wdGlvbk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIE9iamVjdC5hc3NpZ24ob3B0aW9uc1Jlc3VsdCwgdGhpcy5fZ2V0T3B0aW9uT2JqZWN0KG9wdGlvbk9iamVjdCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG9wdGlvbnNSZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRm9ybWF0IHRoZSBnaXZlbiBudW1iZXIgKG9yIG51bWVyaWMgc3RyaW5nKSB3aXRoIHRoZSBnaXZlbiBvcHRpb25zLiBUaGlzIHJldHVybnMgdGhlIGZvcm1hdHRlZCB2YWx1ZSBhcyBhIHN0cmluZy5cbiAgICAgKiBUaGlzIGNhbiBhbHNvIGZvcm1hdCB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgdmFsdWUgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucyBhbmQgcmV0dXJucyB0aGUgZm9ybWF0dGVkIHZhbHVlIGFzIGEgc3RyaW5nLlxuICAgICAqIE5vdGUgOiBUaGlzIGZ1bmN0aW9uIGRvZXMgKm5vdCogdXBkYXRlIHRoYXQgZWxlbWVudCB2YWx1ZSB3aXRoIHRoZSBuZXdseSBmb3JtYXR0ZWQgdmFsdWUuXG4gICAgICogVGhpcyBiYXNpY2FsbHkgYWxsb3dzIHRvIGdldCB0aGUgZm9ybWF0dGVkIHZhbHVlIHdpdGhvdXQgZmlyc3QgaGF2aW5nIHRvIGluaXRpYWxpemUgYW4gQXV0b051bWVyaWMgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfEhUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQgQSBudW1iZXIsIG9yIGEgc3RyaW5nIHRoYXQgcmVwcmVzZW50IGEgamF2YXNjcmlwdCBudW1iZXIsIG9yIGEgRE9NIGVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge29iamVjdHxudWxsfSBvcHRpb25zIE11bHRpcGxlIG9iamVjdHMgY2FuIGJlIHBhc3NlZCwgdGhlIGxhdHRlciBvdmVyd3JpdGluZyB0aGUgc2V0dGluZ3MgZnJvbSB0aGUgZm9ybWVyIG9uZXNcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gICAgICovXG4gICAgc3RhdGljIGZvcm1hdChudW1lcmljU3RyaW5nT3JEb21FbGVtZW50LCAuLi5vcHRpb25zKSB7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZChudW1lcmljU3RyaW5nT3JEb21FbGVtZW50KSB8fCBudW1lcmljU3RyaW5nT3JEb21FbGVtZW50ID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJldHJpZXZlIHRoZSB2YWx1ZSB0byBmb3JtYXRcbiAgICAgICAgbGV0IHZhbHVlO1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNFbGVtZW50KG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZShudW1lcmljU3RyaW5nT3JEb21FbGVtZW50KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHZhbHVlID0gbnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcodmFsdWUpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcih2YWx1ZSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSB2YWx1ZSBcIiR7dmFsdWV9XCIgYmVpbmcgXCJzZXRcIiBpcyBub3QgbnVtZXJpYyBhbmQgdGhlcmVmb3JlIGNhbm5vdCBiZSB1c2VkIGFwcHJvcHJpYXRlbHkuYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBNYW5hZ2Ugb3B0aW9uc1xuICAgICAgICBjb25zdCBvcHRpb25zVG9Vc2UgPSB0aGlzLl9nZW5lcmF0ZU9wdGlvbnNPYmplY3RGcm9tT3B0aW9uc0FycmF5KG9wdGlvbnMpO1xuXG4gICAgICAgIC8vIEluaXRpYXRlIGEgdmVyeSBiYXNpYyBzZXR0aW5ncyBvYmplY3RcbiAgICAgICAgY29uc3Qgc2V0dGluZ3MgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLmdldERlZmF1bHRDb25maWcoKSwgb3B0aW9uc1RvVXNlKTtcbiAgICAgICAgc2V0dGluZ3MuaXNOZWdhdGl2ZVNpZ25BbGxvd2VkID0gdmFsdWUgPCAwO1xuICAgICAgICBzZXR0aW5ncy5pc1Bvc2l0aXZlU2lnbkFsbG93ZWQgPSB2YWx1ZSA+PSAwO1xuICAgICAgICB0aGlzLl9zZXRCcmFja2V0cyhzZXR0aW5ncyk7XG5cbiAgICAgICAgY29uc3QgcmVnZXggPSB7fTtcbiAgICAgICAgdGhpcy5fY2FjaGVzVXN1YWxSZWd1bGFyRXhwcmVzc2lvbnMoc2V0dGluZ3MsIHJlZ2V4KTsgLy8gVGhpcyBpcyBuZWVkZWQgYnkgYF9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnNFeGNlcHRDdXN0b21EZWNpbWFsQ2hhcmAgdGhhdCB1c2VzIHRob3NlIHJlZ2V4XG5cbiAgICAgICAgLy8gQ2hlY2sgdGhlIHZhbGlkaXR5IG9mIHRoZSBgdmFsdWVgIHBhcmFtZXRlclxuICAgICAgICAvLyBDb252ZXJ0IHRoZSB2YWx1ZSB0byBhIG51bWVyaWMgc3RyaW5nLCBzdHJpcHBpbmcgdW5uZWNlc3NhcnkgY2hhcmFjdGVycyBpbiB0aGUgcHJvY2Vzc1xuICAgICAgICBsZXQgdmFsdWVTdHJpbmcgPSB0aGlzLl90b051bWVyaWNWYWx1ZSh2YWx1ZSwgc2V0dGluZ3MpO1xuICAgICAgICBpZiAoaXNOYU4oTnVtYmVyKHZhbHVlU3RyaW5nKSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSB2YWx1ZSBbJHt2YWx1ZVN0cmluZ31dIHRoYXQgeW91IGFyZSB0cnlpbmcgdG8gZm9ybWF0IGlzIG5vdCBhIHJlY29nbml6ZWQgbnVtYmVyLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQmFzaWMgdGVzdHMgdG8gY2hlY2sgaWYgdGhlIGdpdmVuIHZhbHVlU3RyaW5nIGlzIHZhbGlkXG4gICAgICAgIGNvbnN0IFttaW5UZXN0LCBtYXhUZXN0XSA9IHRoaXMuX2NoZWNrSWZJblJhbmdlV2l0aE92ZXJyaWRlT3B0aW9uKHZhbHVlU3RyaW5nLCBzZXR0aW5ncyk7XG4gICAgICAgIGlmICghbWluVGVzdCB8fCAhbWF4VGVzdCkge1xuICAgICAgICAgICAgLy8gVGhyb3cgYSBjdXN0b20gZXZlbnRcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMuZm9ybWF0dGVkLCBkb2N1bWVudCwge1xuICAgICAgICAgICAgICAgIG9sZFZhbHVlICAgOiBudWxsLFxuICAgICAgICAgICAgICAgIG5ld1ZhbHVlICAgOiBudWxsLFxuICAgICAgICAgICAgICAgIG9sZFJhd1ZhbHVlOiBudWxsLFxuICAgICAgICAgICAgICAgIG5ld1Jhd1ZhbHVlOiBudWxsLFxuICAgICAgICAgICAgICAgIGlzUHJpc3RpbmUgOiBudWxsLFxuICAgICAgICAgICAgICAgIGVycm9yICAgICAgOiAnUmFuZ2UgdGVzdCBmYWlsZWQnLFxuICAgICAgICAgICAgICAgIGFORWxlbWVudCAgOiBudWxsLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdmFsdWUgWyR7dmFsdWVTdHJpbmd9XSBiZWluZyBzZXQgZmFsbHMgb3V0c2lkZSBvZiB0aGUgbWluaW11bVZhbHVlIFske3NldHRpbmdzLm1pbmltdW1WYWx1ZX1dIGFuZCBtYXhpbXVtVmFsdWUgWyR7c2V0dGluZ3MubWF4aW11bVZhbHVlfV0gcmFuZ2Ugc2V0IGZvciB0aGlzIGVsZW1lbnRgKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERpcmVjdGx5IGZvcm1hdCBhbnkgYHZhbHVlc1RvU3RyaW5nc2AgdmFsdWVzLCBpZiBmb3VuZFxuICAgICAgICBpZiAoc2V0dGluZ3MudmFsdWVzVG9TdHJpbmdzICYmIHRoaXMuX2NoZWNrVmFsdWVzVG9TdHJpbmdzU2V0dGluZ3ModmFsdWUsIHNldHRpbmdzKSkge1xuICAgICAgICAgICAgcmV0dXJuIHNldHRpbmdzLnZhbHVlc1RvU3RyaW5nc1t2YWx1ZV07XG4gICAgICAgIH1cblxuICAgICAgICAvLyBHZW5lcmF0ZSB0aGUgYG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50YCBvcHRpb24gYXMgbmVlZGVkXG4gICAgICAgIHRoaXMuX2NvcnJlY3ROZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudE9wdGlvbihzZXR0aW5ncyk7XG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgbmVlZGVkIGRlY2ltYWwgcGxhY2VzXG4gICAgICAgIHRoaXMuX2NhbGN1bGF0ZURlY2ltYWxQbGFjZXNPbkluaXQoc2V0dGluZ3MpO1xuXG4gICAgICAgIC8vIE11bHRpcGx5IHRoZSByYXcgdmFsdWUgd2l0aCBgcmF3VmFsdWVEaXZpc29yYCBpZiBkZWZpbmVkXG4gICAgICAgIGlmICgoIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IpICYmIHNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvciAhPT0gMCkgJiYgLy8gT25seSBkaXZpZGUgaWYgdGhlIGByYXdWYWx1ZURpdmlzb3JgIG9wdGlvbiBpcyBzZXRcbiAgICAgICAgICAgIHZhbHVlU3RyaW5nICE9PSAnJyAmJiB2YWx1ZVN0cmluZyAhPT0gbnVsbCkgeyAvLyBEbyBub3QgbW9kaWZ5IHRoZSBgdmFsdWVTdHJpbmdgIGlmIGl0J3MgYW4gZW1wdHkgc3RyaW5nIG9yIG51bGxcbiAgICAgICAgICAgIHZhbHVlU3RyaW5nICo9IHNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEV2ZXJ5dGhpbmcgaXMgb2ssIHByb2NlZWQgdG8gcm91bmRpbmcsIGZvcm1hdHRpbmcgYW5kIGdyb3VwaW5nXG4gICAgICAgIHZhbHVlU3RyaW5nID0gdGhpcy5fcm91bmRGb3JtYXR0ZWRWYWx1ZVNob3duT25Gb2N1cyh2YWx1ZVN0cmluZywgc2V0dGluZ3MpO1xuICAgICAgICB2YWx1ZVN0cmluZyA9IHRoaXMuX21vZGlmeU5lZ2F0aXZlU2lnbkFuZERlY2ltYWxDaGFyYWN0ZXJGb3JGb3JtYXR0ZWRWYWx1ZSh2YWx1ZVN0cmluZywgc2V0dGluZ3MpO1xuICAgICAgICB2YWx1ZVN0cmluZyA9IHRoaXMuX2FkZEdyb3VwU2VwYXJhdG9ycyh2YWx1ZVN0cmluZywgc2V0dGluZ3MsIGZhbHNlLCB2YWx1ZVN0cmluZyk7XG5cbiAgICAgICAgcmV0dXJuIHZhbHVlU3RyaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvcm1hdCB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgdmFsdWUsIGFuZCBzZXQgdGhlIHJlc3VsdGluZyB2YWx1ZSBiYWNrIGFzIHRoZSBlbGVtZW50IHZhbHVlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBkb21FbGVtZW50XG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gICAgICovXG4gICAgc3RhdGljIGZvcm1hdEFuZFNldChkb21FbGVtZW50LCBvcHRpb25zID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBjb25zdCBmb3JtYXR0ZWRWYWx1ZSA9IHRoaXMuZm9ybWF0KGRvbUVsZW1lbnQsIG9wdGlvbnMpO1xuICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50VmFsdWUoZG9tRWxlbWVudCwgZm9ybWF0dGVkVmFsdWUpO1xuXG4gICAgICAgIHJldHVybiBmb3JtYXR0ZWRWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbmZvcm1hdCB0aGUgZ2l2ZW4gZm9ybWF0dGVkIHN0cmluZyB3aXRoIHRoZSBnaXZlbiBvcHRpb25zLiBUaGlzIHJldHVybnMgYSBudW1lcmljIHN0cmluZy5cbiAgICAgKiBJdCBjYW4gYWxzbyB1bmZvcm1hdCB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgdmFsdWUgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucyBhbmQgcmV0dXJucyB0aGUgdW5mb3JtYXR0ZWQgbnVtZXJpYyBzdHJpbmcuXG4gICAgICogTm90ZTogVGhpcyBkb2VzICpub3QqIHVwZGF0ZSB0aGF0IGVsZW1lbnQgdmFsdWUuXG4gICAgICogVGhpcyBiYXNpY2FsbHkgYWxsb3dzIHRvIGdldCB0aGUgdW5mb3JtYXR0ZWQgdmFsdWUgd2l0aG91dCBmaXJzdCBoYXZpbmcgdG8gaW5pdGlhbGl6ZSBhbiBBdXRvTnVtZXJpYyBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ8SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudH0gbnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCBBIG51bWJlciwgb3IgYSBzdHJpbmcgdGhhdCByZXByZXNlbnQgYSBqYXZhc2NyaXB0IG51bWJlciwgb3IgYSBET00gZWxlbWVudFxuICAgICAqIEBwYXJhbSB7b2JqZWN0fG51bGx9IG9wdGlvbnMgTXVsdGlwbGUgb2JqZWN0cyBjYW4gYmUgcGFzc2VkLCB0aGUgbGF0dGVyIG92ZXJ3cml0aW5nIHRoZSBzZXR0aW5ncyBmcm9tIHRoZSBmb3JtZXIgb25lc1xuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVtYmVyfE5hTn1cbiAgICAgKi9cbiAgICBzdGF0aWMgdW5mb3JtYXQobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCwgLi4ub3B0aW9ucykge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXJTdHJpY3QobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIC8vIEdpdmluZyBhbiB1bmZvcm1hdHRlZCB2YWx1ZSBzaG91bGQgcmV0dXJuIHRoZSBzYW1lIHVuZm9ybWF0dGVkIHZhbHVlLCB3aGF0ZXZlciB0aGUgb3B0aW9ucyBwYXNzZWQgYXMgYSBwYXJhbWV0ZXJcbiAgICAgICAgICAgIHJldHVybiBudW1lcmljU3RyaW5nT3JEb21FbGVtZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmV0cmlldmUgdGhlIHZhbHVlIHRvIHVuZm9ybWF0XG4gICAgICAgIGxldCB2YWx1ZTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRWxlbWVudChudW1lcmljU3RyaW5nT3JEb21FbGVtZW50KSkge1xuICAgICAgICAgICAgdmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZSA9IG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUgPT09ICcnKSB7XG4gICAgICAgICAgICAvLyBUaGlzIGFsbG93cyB0byBiZSBjb2hlcmVudCB3aGVuIHNlcmlhbGl6aW5nIGZvcm1zIHdpdGggZW1wdHkgaW5wdXRzLiBGaXggaXNzdWUgIzUxMi5cbiAgICAgICAgICAgIHJldHVybiAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZCh2YWx1ZSkgfHwgdmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzQXJyYXkodmFsdWUpIHx8IEF1dG9OdW1lcmljSGVscGVyLmlzT2JqZWN0KHZhbHVlKSkge1xuICAgICAgICAgICAgLy8gQ2hlY2sgdGhlIHZhbGlkaXR5IG9mIHRoZSBgdmFsdWVgIHBhcmFtZXRlclxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgQSBudW1iZXIgb3IgYSBzdHJpbmcgcmVwcmVzZW50aW5nIGEgbnVtYmVyIGlzIG5lZWRlZCB0byBiZSBhYmxlIHRvIHVuZm9ybWF0IGl0LCBbJHt2YWx1ZX1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTWFuYWdlIG9wdGlvbnNcbiAgICAgICAgY29uc3Qgb3B0aW9uc1RvVXNlID0gdGhpcy5fZ2VuZXJhdGVPcHRpb25zT2JqZWN0RnJvbU9wdGlvbnNBcnJheShvcHRpb25zKTtcblxuICAgICAgICAvLyBHZW5lcmF0ZSB0aGUgc2V0dGluZ3NcbiAgICAgICAgY29uc3Qgc2V0dGluZ3MgPSBPYmplY3QuYXNzaWduKHt9LCB0aGlzLmdldERlZmF1bHRDb25maWcoKSwgb3B0aW9uc1RvVXNlKTtcbiAgICAgICAgc2V0dGluZ3MuaXNOZWdhdGl2ZVNpZ25BbGxvd2VkID0gZmFsc2U7XG4gICAgICAgIHNldHRpbmdzLmlzUG9zaXRpdmVTaWduQWxsb3dlZCA9IHRydWU7XG4gICAgICAgIHZhbHVlID0gdmFsdWUudG9TdHJpbmcoKTtcblxuICAgICAgICAvLyBEaXJlY3RseSB1bmZvcm1hdCBhbnkgYHZhbHVlc1RvU3RyaW5nc2AgdmFsdWVzLCBpZiBmb3VuZFxuICAgICAgICBpZiAoc2V0dGluZ3MudmFsdWVzVG9TdHJpbmdzICYmIHRoaXMuX2NoZWNrU3RyaW5nc1RvVmFsdWVzU2V0dGluZ3ModmFsdWUsIHNldHRpbmdzKSkge1xuICAgICAgICAgICAgcmV0dXJuIEF1dG9OdW1lcmljSGVscGVyLm9iamVjdEtleUxvb2t1cChzZXR0aW5ncy52YWx1ZXNUb1N0cmluZ3MsIHZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRoaXMgY2hlY2tzIGlmIGEgbmVnYXRpdmUgc2lnbiBpcyBhbnl3aGVyZSBpbiB0aGUgYHZhbHVlYCwgbm90IGp1c3Qgb24gdGhlIHZlcnkgZmlyc3QgY2hhcmFjdGVyIChpZS4gJzEyMzQ1LjY3LScpXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKHZhbHVlLCBzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICBzZXR0aW5ncy5pc05lZ2F0aXZlU2lnbkFsbG93ZWQgPSB0cnVlO1xuICAgICAgICAgICAgc2V0dGluZ3MuaXNQb3NpdGl2ZVNpZ25BbGxvd2VkID0gZmFsc2U7XG4gICAgICAgIH0gZWxzZSBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChzZXR0aW5ncy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1cikpIHtcbiAgICAgICAgICAgIFtzZXR0aW5ncy5maXJzdEJyYWNrZXQsIHNldHRpbmdzLmxhc3RCcmFja2V0XSA9IHNldHRpbmdzLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLnNwbGl0KCcsJyk7XG4gICAgICAgICAgICBpZiAodmFsdWUuY2hhckF0KDApID09PSBzZXR0aW5ncy5maXJzdEJyYWNrZXQgJiZcbiAgICAgICAgICAgICAgICB2YWx1ZS5jaGFyQXQodmFsdWUubGVuZ3RoIC0gMSkgPT09IHNldHRpbmdzLmxhc3RCcmFja2V0KSB7XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MuaXNOZWdhdGl2ZVNpZ25BbGxvd2VkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5pc1Bvc2l0aXZlU2lnbkFsbG93ZWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuX3JlbW92ZUJyYWNrZXRzKHZhbHVlLCBzZXR0aW5ncywgZmFsc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdmFsdWUgPSB0aGlzLl9jb252ZXJ0VG9OdW1lcmljU3RyaW5nKHZhbHVlLCBzZXR0aW5ncyk7XG4gICAgICAgIGNvbnN0IHVud2FudGVkQ2hhcmFjdGVycyA9IG5ldyBSZWdFeHAoYFteKy0wMTIzNDU2Nzg5Ll1gLCAnZ2knKTtcbiAgICAgICAgaWYgKHVud2FudGVkQ2hhcmFjdGVycy50ZXN0KHZhbHVlKSkge1xuICAgICAgICAgICAgcmV0dXJuIE5hTjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEdlbmVyYXRlIHRoZSBgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnRgIG9wdGlvbiBhcyBuZWVkZWRcbiAgICAgICAgdGhpcy5fY29ycmVjdE5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50T3B0aW9uKHNldHRpbmdzKTtcbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBuZWVkZWQgZGVjaW1hbCBwbGFjZXNcbiAgICAgICAgaWYgKHNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSkgeyAvLyBgb3JpZ2luYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWVgIG5lZWRzIHRvIGJlIGRlZmluZWRcbiAgICAgICAgICAgIHNldHRpbmdzLm9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2V0dGluZ3Mub3JpZ2luYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUgPSBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fY2FsY3VsYXRlRGVjaW1hbFBsYWNlc09uSW5pdChzZXR0aW5ncyk7XG5cbiAgICAgICAgLy8gRGl2aWRlIHRoZSByYXcgdmFsdWUgd2l0aCBgcmF3VmFsdWVEaXZpc29yYCBpZiBkZWZpbmVkXG4gICAgICAgIGlmICgoIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IpICYmIHNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvciAhPT0gMCkgJiYgLy8gT25seSBkaXZpZGUgaWYgdGhlIGByYXdWYWx1ZURpdmlzb3JgIG9wdGlvbiBpcyBzZXRcbiAgICAgICAgICAgIHZhbHVlICE9PSAnJyAmJiB2YWx1ZSAhPT0gbnVsbCkgeyAvLyBEbyBub3QgbW9kaWZ5IHRoZSBgdmFsdWVgIGlmIGl0J3MgYW4gZW1wdHkgc3RyaW5nIG9yIG51bGxcbiAgICAgICAgICAgIHZhbHVlIC89IHNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbHVlID0gdGhpcy5fcm91bmRSYXdWYWx1ZSh2YWx1ZSwgc2V0dGluZ3MpO1xuICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2Uoc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciwgJy4nKTsgLy8gSGVyZSB3ZSBuZWVkIHRvIGNvbnZlcnQgYmFjayB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgdG8gYSBwZXJpb2Qgc2luY2UgYF9yb3VuZFZhbHVlYCBhZGRzIGl0IGluIHNvbWUgY2FzZXNcbiAgICAgICAgdmFsdWUgPSB0aGlzLl90b0xvY2FsZSh2YWx1ZSwgc2V0dGluZ3Mub3V0cHV0Rm9ybWF0LCBzZXR0aW5ncyk7XG5cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVuZm9ybWF0IHRoZSBnaXZlbiBET00gZWxlbWVudCB2YWx1ZSwgYW5kIHNldCB0aGUgcmVzdWx0aW5nIHZhbHVlIGJhY2sgYXMgdGhlIGVsZW1lbnQgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IGRvbUVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uc1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyB1bmZvcm1hdEFuZFNldChkb21FbGVtZW50LCBvcHRpb25zID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBjb25zdCB1bmZvcm1hdHRlZFZhbHVlID0gdGhpcy51bmZvcm1hdChkb21FbGVtZW50LCBvcHRpb25zKTtcbiAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFZhbHVlKGRvbUVsZW1lbnQsIHVuZm9ybWF0dGVkVmFsdWUpO1xuXG4gICAgICAgIHJldHVybiB1bmZvcm1hdHRlZFZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVuZm9ybWF0IGFuZCBsb2NhbGl6ZSB0aGUgZ2l2ZW4gZm9ybWF0dGVkIHN0cmluZyB3aXRoIHRoZSBnaXZlbiBvcHRpb25zLiBUaGlzIHJldHVybnMgYSBudW1lcmljIHN0cmluZy5cbiAgICAgKiBJdCBjYW4gYWxzbyB1bmZvcm1hdCBhbmQgbG9jYWxpemUgdGhlIGdpdmVuIERPTSBlbGVtZW50IHZhbHVlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMgYW5kIHJldHVybnMgdGhlIHVuZm9ybWF0dGVkIG51bWVyaWMgc3RyaW5nLlxuICAgICAqIE5vdGU6IFRoaXMgZG9lcyAqbm90KiB1cGRhdGUgdGhhdCBlbGVtZW50IHZhbHVlLlxuICAgICAqIFRoaXMgYmFzaWNhbGx5IGFsbG93cyB0byBnZXQgdGhlIGxvY2FsaXplZCB2YWx1ZSB3aXRob3V0IGZpcnN0IGhhdmluZyB0byBpbml0aWFsaXplIGFuIEF1dG9OdW1lcmljIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcnxIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBudW1lcmljU3RyaW5nT3JEb21FbGVtZW50XG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIGxvY2FsaXplKG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQsIHNldHRpbmdzID0gbnVsbCkge1xuICAgICAgICBsZXQgdmFsdWU7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0VsZW1lbnQobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIHZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFsdWUgPSBudW1lcmljU3RyaW5nT3JEb21FbGVtZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHZhbHVlID09PSAnJykge1xuICAgICAgICAgICAgLy8gVGhpcyBhbGxvd3MgdG8gYmUgY29oZXJlbnQgd2hlbiBzZXJpYWxpemluZyBmb3JtcyB3aXRoIGVtcHR5IGlucHV0cy4gRml4IGlzc3VlICM1MTIuXG4gICAgICAgICAgICByZXR1cm4gJyc7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHNldHRpbmdzKSkge1xuICAgICAgICAgICAgc2V0dGluZ3MgPSBBdXRvTnVtZXJpYy5kZWZhdWx0U2V0dGluZ3M7XG4gICAgICAgIH1cblxuICAgICAgICB2YWx1ZSA9IHRoaXMudW5mb3JtYXQodmFsdWUsIHNldHRpbmdzKTtcblxuICAgICAgICAvL1hYWCBUaGUgZm9sbG93aW5nIGNvZGUgaXMgcHJldHR5IGNsb3NlIHRvIHRoZSBvbmUgeW91IGNhbiBmaW5kIGluIGBnZXRMb2NhbGl6ZWQoKWAsIGJ1dCBkaWZmZXJlbnQgZW5vdWdoIHNvIHdlIHdvbid0IHJlZmFjdG9yIGl0LlxuICAgICAgICBpZiAoTnVtYmVyKHZhbHVlKSA9PT0gMCAmJiBzZXR0aW5ncy5sZWFkaW5nWmVybyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5rZWVwKSB7XG4gICAgICAgICAgICB2YWx1ZSA9ICcwJztcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBvdXRwdXRGb3JtYXRUb1VzZTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChzZXR0aW5ncykpIHtcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdFRvVXNlID0gc2V0dGluZ3Mub3V0cHV0Rm9ybWF0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3V0cHV0Rm9ybWF0VG9Vc2UgPSBBdXRvTnVtZXJpYy5kZWZhdWx0U2V0dGluZ3Mub3V0cHV0Rm9ybWF0O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX3RvTG9jYWxlKHZhbHVlLCBvdXRwdXRGb3JtYXRUb1VzZSwgc2V0dGluZ3MpO1xuICAgIH1cblxuICAgIHN0YXRpYyBsb2NhbGl6ZUFuZFNldChkb21FbGVtZW50LCBvcHRpb25zID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBjb25zdCBsb2NhbGl6ZWRWYWx1ZSA9IHRoaXMubG9jYWxpemUoZG9tRWxlbWVudCwgb3B0aW9ucyk7XG4gICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRWYWx1ZShkb21FbGVtZW50LCBsb2NhbGl6ZWRWYWx1ZSk7XG5cbiAgICAgICAgcmV0dXJuIGxvY2FsaXplZFZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGdpdmVuIERPTSBlbGVtZW50IGhhcyBhbiBBdXRvTnVtZXJpYyBvYmplY3QgdGhhdCBtYW5hZ2VzIGl0LlxuICAgICAqIFRoaXMgZnVuY3Rpb24gYWxzbyBhY2NlcHRzIGEgc2VsZWN0b3Igc3RyaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxzdHJpbmd9IGRvbUVsZW1lbnRPclNlbGVjdG9yIEFjY2VwdHMgZWl0aGVyIGRpcmVjdGx5IGEgRE9NIGVsZW1lbnQgdG8gdGVzdCwgb3IgYSBzdHJpbmcgc2VsZWN0b3IgKHRoYXQgd2lsbCByZXR1cm4gb25lIGFuZCBvbmx5IG9uZSBlbGVtZW50LCBpZiBhbnkpXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzTWFuYWdlZEJ5QXV0b051bWVyaWMoZG9tRWxlbWVudE9yU2VsZWN0b3IpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzSW5HbG9iYWxMaXN0KEF1dG9OdW1lcmljSGVscGVyLmRvbUVsZW1lbnQoZG9tRWxlbWVudE9yU2VsZWN0b3IpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIEF1dG9OdW1lcmljIG9iamVjdCB0aGF0IG1hbmFnZXMgdGhlIGdpdmVuIERPTSBlbGVtZW50LlxuICAgICAqIFRoaXMgZnVuY3Rpb24gYWxzbyBhY2NlcHRzIGEgc2VsZWN0b3Igc3RyaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxzdHJpbmd9IGRvbUVsZW1lbnRPclNlbGVjdG9yIEFjY2VwdHMgZWl0aGVyIGRpcmVjdGx5IGEgRE9NIGVsZW1lbnQgdG8gdGVzdCwgb3IgYSBzdHJpbmcgc2VsZWN0b3IgKHRoYXQgd2lsbCByZXR1cm4gb25lIGFuZCBvbmx5IG9uZSBlbGVtZW50LCBpZiBhbnkpXG4gICAgICogQHJldHVybnMge251bGx8QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgc3RhdGljIGdldEF1dG9OdW1lcmljRWxlbWVudChkb21FbGVtZW50T3JTZWxlY3Rvcikge1xuICAgICAgICBjb25zdCBkb21FbGVtZW50ID0gQXV0b051bWVyaWNIZWxwZXIuZG9tRWxlbWVudChkb21FbGVtZW50T3JTZWxlY3Rvcik7XG5cbiAgICAgICAgaWYgKCF0aGlzLmlzTWFuYWdlZEJ5QXV0b051bWVyaWMoZG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuX2dldEZyb21HbG9iYWxMaXN0KGRvbUVsZW1lbnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgZ2l2ZW4gZWxlbWVudCB2YWx1ZSwgYW5kIGZvcm1hdCBpdCBpbW1lZGlhdGVseS5cbiAgICAgKiBSZXR1cm4gYG51bGxgIGlmIG5vIEF1dG9OdW1lcmljIG9iamVjdCBpcyBmb3VuZCwgZWxzZSwgcmV0dXJuIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fHN0cmluZ30gZG9tRWxlbWVudE9yU2VsZWN0b3IgRWl0aGVyIGEgRE9NIGVsZW1lbnQgcmVmZXJlbmNlLCBvciBhIHNlbGVjdG9yIHN0cmluZyBjYW4gYmUgdXNlZFxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ3xudWxsfSBuZXdWYWx1ZSBUaGUgdmFsdWUgbXVzdCBiZSBhIE51bWJlciwgYSBudW1lcmljIHN0cmluZyBvciBgbnVsbGAgKGlmIGBlbXB0eUlucHV0QmVoYXZpb3JgIGlzIHNldCB0byBgJ251bGwnYClcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyBBIHNldHRpbmdzIG9iamVjdCB0aGF0IHdpbGwgb3ZlcnJpZGUgdGhlIGN1cnJlbnQgc2V0dGluZ3MuIE5vdGU6IHRoZSB1cGRhdGUgaXMgZG9uZSBvbmx5IGlmIHRoZSBgbmV3VmFsdWVgIGlzIGRlZmluZWQuXG4gICAgICogQHBhcmFtIHtib29sZWFufSBzYXZlQ2hhbmdlVG9IaXN0b3J5IElmIHNldCB0byBgdHJ1ZWAsIHRoZW4gdGhlIGNoYW5nZSBpcyByZWNvcmRlZCBpbiB0aGUgaGlzdG9yeSB0YWJsZVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY3xudWxsfVxuICAgICAqL1xuICAgIHN0YXRpYyBzZXQoZG9tRWxlbWVudE9yU2VsZWN0b3IsIG5ld1ZhbHVlLCBvcHRpb25zID0gbnVsbCwgc2F2ZUNoYW5nZVRvSGlzdG9yeSA9IHRydWUpIHtcbiAgICAgICAgY29uc3QgZG9tRWxlbWVudCA9IEF1dG9OdW1lcmljSGVscGVyLmRvbUVsZW1lbnQoZG9tRWxlbWVudE9yU2VsZWN0b3IpO1xuXG4gICAgICAgIGlmICghdGhpcy5pc01hbmFnZWRCeUF1dG9OdW1lcmljKGRvbUVsZW1lbnQpKSB7XG4gICAgICAgICAgICBsZXQgc2hvd1dhcm5pbmdzO1xuICAgICAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucykgJiYgb3B0aW9ucy5oYXNPd25Qcm9wZXJ0eSgnc2hvd1dhcm5pbmdzJykpIHtcbiAgICAgICAgICAgICAgICBzaG93V2FybmluZ3MgPSBvcHRpb25zLnNob3dXYXJuaW5ncztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgc2hvd1dhcm5pbmdzID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgSW1wb3NzaWJsZSB0byBmaW5kIGFuIEF1dG9OdW1lcmljIG9iamVjdCBmb3IgdGhlIGdpdmVuIERPTSBlbGVtZW50IG9yIHNlbGVjdG9yLmAsIHNob3dXYXJuaW5ncyk7XG5cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0QXV0b051bWVyaWNFbGVtZW50KGRvbUVsZW1lbnQpLnNldChuZXdWYWx1ZSwgb3B0aW9ucywgc2F2ZUNoYW5nZVRvSGlzdG9yeSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSB1bmZvcm1hdHRlZCB2YWx1ZSBhcyBhIHN0cmluZyBmcm9tIHRoZSBnaXZlbiBET00gZWxlbWVudCBvciBxdWVyeSBzZWxlY3Rvci5cbiAgICAgKiBUaGlzIGNhbiBhbHNvIHJldHVybiBgbnVsbGAgaWYgYHJhd1ZhbHVlYCBpcyBudWxsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxzdHJpbmd9IGRvbUVsZW1lbnRPclNlbGVjdG9yXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFja1xuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0TnVtZXJpY1N0cmluZyhkb21FbGVtZW50T3JTZWxlY3RvciwgY2FsbGJhY2sgPSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXQoZG9tRWxlbWVudE9yU2VsZWN0b3IsIEF1dG9OdW1lcmljLmdldE51bWVyaWNTdHJpbmcubmFtZSwgY2FsbGJhY2spO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgY3VycmVudCBmb3JtYXR0ZWQgdmFsdWUgb2YgdGhlIEF1dG9OdW1lcmljIGVsZW1lbnQgYXMgYSBzdHJpbmcsIGZyb20gdGhlIGdpdmVuIERPTSBlbGVtZW50IG9yIHF1ZXJ5IHNlbGVjdG9yLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxzdHJpbmd9IGRvbUVsZW1lbnRPclNlbGVjdG9yXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFja1xuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgc3RhdGljIGdldEZvcm1hdHRlZChkb21FbGVtZW50T3JTZWxlY3RvciwgY2FsbGJhY2sgPSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXQoZG9tRWxlbWVudE9yU2VsZWN0b3IsIEF1dG9OdW1lcmljLmdldEZvcm1hdHRlZC5uYW1lLCBjYWxsYmFjayk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBlbGVtZW50IHVuZm9ybWF0dGVkIHZhbHVlIGFzIGEgcmVhbCBKYXZhc2NyaXB0IG51bWJlciwgZnJvbSB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgb3IgcXVlcnkgc2VsZWN0b3IuXG4gICAgICogV2FybmluZzogVGhpcyBjYW4gbGVhZCB0byBwcmVjaXNpb24gcHJvYmxlbXMgd2l0aCBiaWcgbnVtYmVycyB0aGF0IHNob3VsZCBiZSBzdG9yZWQgYXMgc3RyaW5ncy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8c3RyaW5nfSBkb21FbGVtZW50T3JTZWxlY3RvclxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2tcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfG51bGx9XG4gICAgICovXG4gICAgc3RhdGljIGdldE51bWJlcihkb21FbGVtZW50T3JTZWxlY3RvciwgY2FsbGJhY2sgPSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9nZXQoZG9tRWxlbWVudE9yU2VsZWN0b3IsIEF1dG9OdW1lcmljLmdldE51bWJlci5uYW1lLCBjYWxsYmFjayk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRFJZIHRoZSBjb2RlIGJldHdlZW4gdGhlIHN0YXRpYyBgZ2V0KmAgZnVuY3Rpb25zXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fHN0cmluZ30gZG9tRWxlbWVudE9yU2VsZWN0b3JcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZ2V0RnVuY3Rpb24gVGhlIG5hbWUgb2YgdGhlIG5vbi1zdGF0aWMgYGdldCpgIGZ1bmN0aW9uIGFzIGEgc3RyaW5nXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFja1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9nZXQoZG9tRWxlbWVudE9yU2VsZWN0b3IsIGdldEZ1bmN0aW9uLCBjYWxsYmFjayA9IG51bGwpIHtcbiAgICAgICAgY29uc3QgZG9tRWxlbWVudCA9IEF1dG9OdW1lcmljSGVscGVyLmRvbUVsZW1lbnQoZG9tRWxlbWVudE9yU2VsZWN0b3IpO1xuXG4gICAgICAgIGlmICghdGhpcy5pc01hbmFnZWRCeUF1dG9OdW1lcmljKGRvbUVsZW1lbnQpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBJbXBvc3NpYmxlIHRvIGZpbmQgYW4gQXV0b051bWVyaWMgb2JqZWN0IGZvciB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgb3Igc2VsZWN0b3IuYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5nZXRBdXRvTnVtZXJpY0VsZW1lbnQoZG9tRWxlbWVudClbZ2V0RnVuY3Rpb25dKGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB1bmZvcm1hdHRlZCB2YWx1ZSBmb2xsb3dpbmcgdGhlIGBvdXRwdXRGb3JtYXRgIHNldHRpbmcsIGZyb20gdGhlIGdpdmVuIERPTSBlbGVtZW50IG9yIHF1ZXJ5IHNlbGVjdG9yLlxuICAgICAqIFNlZSB0aGUgbm9uLXN0YXRpYyBgZ2V0TG9jYWxpemVkKClgIG1ldGhvZCBkb2N1bWVudGF0aW9uIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fHN0cmluZ30gZG9tRWxlbWVudE9yU2VsZWN0b3JcbiAgICAgKiBAcGFyYW0ge251bGx8c3RyaW5nfGZ1bmN0aW9ufSBmb3JjZWRPdXRwdXRGb3JtYXRcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIGdldExvY2FsaXplZChkb21FbGVtZW50T3JTZWxlY3RvciwgZm9yY2VkT3V0cHV0Rm9ybWF0ID0gbnVsbCwgY2FsbGJhY2sgPSBudWxsKSB7XG4gICAgICAgIGNvbnN0IGRvbUVsZW1lbnQgPSBBdXRvTnVtZXJpY0hlbHBlci5kb21FbGVtZW50KGRvbUVsZW1lbnRPclNlbGVjdG9yKTtcblxuICAgICAgICBpZiAoIXRoaXMuaXNNYW5hZ2VkQnlBdXRvTnVtZXJpYyhkb21FbGVtZW50KSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgSW1wb3NzaWJsZSB0byBmaW5kIGFuIEF1dG9OdW1lcmljIG9iamVjdCBmb3IgdGhlIGdpdmVuIERPTSBlbGVtZW50IG9yIHNlbGVjdG9yLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuZ2V0QXV0b051bWVyaWNFbGVtZW50KGRvbUVsZW1lbnQpLmdldExvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQsIGNhbGxiYWNrKTtcbiAgICB9XG5cbiAgICAvLyBQcmUtZGVmaW5lZCBvcHRpb25zIGNhbiBiZSBjYWxsZWQgdG8gdXBkYXRlIHRoZSBjdXJyZW50IGRlZmF1bHQgb3B0aW9ucyB3aXRoIHRoZWlyIHNwZWNpZmljaXRpZXNcbiAgICAvL1hYWCBBIGJldHRlciB3YXkgd291bGQgYmUgdG8gbm90IGluaXRpYWxpemUgZmlyc3QsIGJ1dCB0aGF0J3Mgbm90IHBvc3NpYmxlIHNpbmNlIGBuZXdgIGlzIGNhbGxlZCBmaXJzdCBhbmQgd2UgZG8gbm90IHBhc3MgdGhlIGxhbmd1YWdlIG9wdGlvbnMgKGllLiBgRnJlbmNoYCkgdG8gdGhlIGNvbnN0cnVjdG9yXG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIEF1dG9OdW1lcmljIG9iamVjdCB3aXRoIHRoZSBwcmVkZWZpbmVkIG9wdGlvbnMsIGFuZCBwb3NzaWJseSBzb21lIG9wdGlvbiBvdmVycmlkZXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gcHJlZGVmaW5lZE9wdGlvblxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25PdmVycmlkZVxuICAgICAqIEBwcml2YXRlXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIF91cGRhdGVQcmVkZWZpbmVkT3B0aW9ucyhwcmVkZWZpbmVkT3B0aW9uLCBvcHRpb25PdmVycmlkZSA9IG51bGwpIHtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9uT3ZlcnJpZGUpKSB7XG4gICAgICAgICAgICB0aGlzLl9tZXJnZVNldHRpbmdzKHByZWRlZmluZWRPcHRpb24sIG9wdGlvbk92ZXJyaWRlKTtcbiAgICAgICAgICAgIHRoaXMudXBkYXRlKHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy51cGRhdGUocHJlZGVmaW5lZE9wdGlvbik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIHNldHRpbmdzIHRvIHVzZSB0aGUgRnJlbmNoIHByZS1kZWZpbmVkIGxhbmd1YWdlIG9wdGlvbnMuXG4gICAgICogVGhvc2UgcHJlLWRlZmluZWQgb3B0aW9ucyBjYW4gYmUgb3ZlcnJpZGRlbiBieSBwYXNzaW5nIGFuIG9wdGlvbiBvYmplY3QgYXMgYSBwYXJhbWV0ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uT3ZlcnJpZGVcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgZnJlbmNoKG9wdGlvbk92ZXJyaWRlID0gbnVsbCkge1xuICAgICAgICB0aGlzLl91cGRhdGVQcmVkZWZpbmVkT3B0aW9ucyhBdXRvTnVtZXJpYy5nZXRQcmVkZWZpbmVkT3B0aW9ucygpLkZyZW5jaCwgb3B0aW9uT3ZlcnJpZGUpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgc2V0dGluZ3MgdG8gdXNlIHRoZSBOb3J0aCBBbWVyaWNhbiBwcmUtZGVmaW5lZCBsYW5ndWFnZSBvcHRpb25zLlxuICAgICAqIFRob3NlIHByZS1kZWZpbmVkIG9wdGlvbnMgY2FuIGJlIG92ZXJyaWRkZW4gYnkgcGFzc2luZyBhbiBvcHRpb24gb2JqZWN0IGFzIGEgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbk92ZXJyaWRlXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIG5vcnRoQW1lcmljYW4ob3B0aW9uT3ZlcnJpZGUgPSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVByZWRlZmluZWRPcHRpb25zKEF1dG9OdW1lcmljLmdldFByZWRlZmluZWRPcHRpb25zKCkuTm9ydGhBbWVyaWNhbiwgb3B0aW9uT3ZlcnJpZGUpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgc2V0dGluZ3MgdG8gdXNlIHRoZSBCcml0aXNoIHByZS1kZWZpbmVkIGxhbmd1YWdlIG9wdGlvbnMuXG4gICAgICogVGhvc2UgcHJlLWRlZmluZWQgb3B0aW9ucyBjYW4gYmUgb3ZlcnJpZGRlbiBieSBwYXNzaW5nIGFuIG9wdGlvbiBvYmplY3QgYXMgYSBwYXJhbWV0ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uT3ZlcnJpZGVcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgYnJpdGlzaChvcHRpb25PdmVycmlkZSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlUHJlZGVmaW5lZE9wdGlvbnMoQXV0b051bWVyaWMuZ2V0UHJlZGVmaW5lZE9wdGlvbnMoKS5Ccml0aXNoLCBvcHRpb25PdmVycmlkZSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBzZXR0aW5ncyB0byB1c2UgdGhlIFN3aXNzIHByZS1kZWZpbmVkIGxhbmd1YWdlIG9wdGlvbnMuXG4gICAgICogVGhvc2UgcHJlLWRlZmluZWQgb3B0aW9ucyBjYW4gYmUgb3ZlcnJpZGRlbiBieSBwYXNzaW5nIGFuIG9wdGlvbiBvYmplY3QgYXMgYSBwYXJhbWV0ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uT3ZlcnJpZGVcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgc3dpc3Mob3B0aW9uT3ZlcnJpZGUgPSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVByZWRlZmluZWRPcHRpb25zKEF1dG9OdW1lcmljLmdldFByZWRlZmluZWRPcHRpb25zKCkuU3dpc3MsIG9wdGlvbk92ZXJyaWRlKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIHNldHRpbmdzIHRvIHVzZSB0aGUgSmFwYW5lc2UgcHJlLWRlZmluZWQgbGFuZ3VhZ2Ugb3B0aW9ucy5cbiAgICAgKiBUaG9zZSBwcmUtZGVmaW5lZCBvcHRpb25zIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHBhc3NpbmcgYW4gb3B0aW9uIG9iamVjdCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25PdmVycmlkZVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBqYXBhbmVzZShvcHRpb25PdmVycmlkZSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlUHJlZGVmaW5lZE9wdGlvbnMoQXV0b051bWVyaWMuZ2V0UHJlZGVmaW5lZE9wdGlvbnMoKS5KYXBhbmVzZSwgb3B0aW9uT3ZlcnJpZGUpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgc2V0dGluZ3MgdG8gdXNlIHRoZSBTcGFuaXNoIHByZS1kZWZpbmVkIGxhbmd1YWdlIG9wdGlvbnMuXG4gICAgICogVGhvc2UgcHJlLWRlZmluZWQgb3B0aW9ucyBjYW4gYmUgb3ZlcnJpZGRlbiBieSBwYXNzaW5nIGFuIG9wdGlvbiBvYmplY3QgYXMgYSBwYXJhbWV0ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uT3ZlcnJpZGVcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgc3BhbmlzaChvcHRpb25PdmVycmlkZSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlUHJlZGVmaW5lZE9wdGlvbnMoQXV0b051bWVyaWMuZ2V0UHJlZGVmaW5lZE9wdGlvbnMoKS5TcGFuaXNoLCBvcHRpb25PdmVycmlkZSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBzZXR0aW5ncyB0byB1c2UgdGhlIENoaW5lc2UgcHJlLWRlZmluZWQgbGFuZ3VhZ2Ugb3B0aW9ucy5cbiAgICAgKiBUaG9zZSBwcmUtZGVmaW5lZCBvcHRpb25zIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHBhc3NpbmcgYW4gb3B0aW9uIG9iamVjdCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25PdmVycmlkZVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBjaGluZXNlKG9wdGlvbk92ZXJyaWRlID0gbnVsbCkge1xuICAgICAgICB0aGlzLl91cGRhdGVQcmVkZWZpbmVkT3B0aW9ucyhBdXRvTnVtZXJpYy5nZXRQcmVkZWZpbmVkT3B0aW9ucygpLkNoaW5lc2UsIG9wdGlvbk92ZXJyaWRlKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIHNldHRpbmdzIHRvIHVzZSB0aGUgQnJhemlsaWFuIHByZS1kZWZpbmVkIGxhbmd1YWdlIG9wdGlvbnMuXG4gICAgICogVGhvc2UgcHJlLWRlZmluZWQgb3B0aW9ucyBjYW4gYmUgb3ZlcnJpZGRlbiBieSBwYXNzaW5nIGFuIG9wdGlvbiBvYmplY3QgYXMgYSBwYXJhbWV0ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uT3ZlcnJpZGVcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgYnJhemlsaWFuKG9wdGlvbk92ZXJyaWRlID0gbnVsbCkge1xuICAgICAgICB0aGlzLl91cGRhdGVQcmVkZWZpbmVkT3B0aW9ucyhBdXRvTnVtZXJpYy5nZXRQcmVkZWZpbmVkT3B0aW9ucygpLkJyYXppbGlhbiwgb3B0aW9uT3ZlcnJpZGUpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuXG4gICAgLy8gSW50ZXJuYWwgcHJpdmF0ZSBmdW5jdGlvbnNcbiAgICAvKipcbiAgICAgKiBSdW4gYW55IGNhbGxiYWNrcyBmb3VuZCBpbiB0aGUgc2V0dGluZ3Mgb2JqZWN0IGluIG9yZGVyIHRvIHNldCB0aGUgc2V0dGluZ3MgdmFsdWUgYmFjay5cbiAgICAgKiBBbnkgcGFyYW1ldGVyIGNhbiBoYXZlIGEgY2FsbGJhY2sgZGVmaW5lZC5cbiAgICAgKiBUaGUgY2FsbGJhY2sgdGFrZXMgdGhlIGN1cnJlbnQgQXV0b051bWVyaWMgZWxlbWVudCBhcyB0aGUgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUga2V5IG5hbWUgYXMgdGhlIHNlY29uZC5cbiAgICAgKiBAZXhhbXBsZSBjYWxsYmFjayh0aGlzLCAnY3VycmVuY3lTeW1ib2wnKVxuICAgICAqL1xuICAgIF9ydW5DYWxsYmFja3NGb3VuZEluVGhlU2V0dGluZ3NPYmplY3QoKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIC8vIExvb3BzIHRocm91Z2ggdGhlIHRoaXMuc2V0dGluZ3Mgb2JqZWN0IChvcHRpb24gYXJyYXkpIHRvIGZpbmQgdGhlIGZvbGxvd2luZ1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiB0aGlzLnNldHRpbmdzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnNldHRpbmdzW2tleV07XG5cbiAgICAgICAgICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Nba2V5XSA9IHZhbHVlKHRoaXMsIGtleSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gQ2FsbHMgdGhlIGF0dGFjaGVkIGZ1bmN0aW9uIGZyb20gdGhlIGh0bWw1IGRhdGEuIEZvciBpbnN0YW5jZTogPHRhZyBkYXRhLWN1cnJlbmN5LXN5bWJvbD1cImZ1bmN0aW9uTmFtZVwiPjwvdGFnPlxuICAgICAgICAgICAgICAgICAgICBsZXQgaHRtbEF0dHJpYnV0ZSA9IHRoaXMuZG9tRWxlbWVudC5nZXRBdHRyaWJ1dGUoa2V5KTsgLy9UT0RPIFVzZSBgZGF0YXNldGAgaW5zdGVhZCBvZiBgZ2V0QXR0cmlidXRlYCB3aGVuIHdlIHdvbid0IG5lZWQgdG8gc3VwcG9ydCBvYnNvbGV0ZSBicm93c2Vyc1xuICAgICAgICAgICAgICAgICAgICBodG1sQXR0cmlidXRlID0gQXV0b051bWVyaWNIZWxwZXIuY2FtZWxpemUoaHRtbEF0dHJpYnV0ZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdGhpcy5zZXR0aW5nc1todG1sQXR0cmlidXRlXSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5nc1trZXldID0gaHRtbEF0dHJpYnV0ZSh0aGlzLCBrZXkpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogS2VlcCB0cmFjayBpZiB0aGUgc2V0dGluZ3MgY29uZmlndXJhdGlvbiBsZWFkcyB0byBhIHRyYWlsaW5nIG5lZ2F0aXZlIHNpZ24gKG9ubHkgd2hlbiB0aGUgcmF3IHZhbHVlIGlzIG5lZ2F0aXZlKSwgc28gd2UgZG8gbm90IGhhdmUgdG8gdGVzdCB0aGUgc2V0dGluZ3MgdmFsdWVzIGV2ZXJ5IHRpbWUgd2UgbmVlZCB0byBrbm93IHRoYXQuXG4gICAgICogYGlzVHJhaWxpbmdOZWdhdGl2ZWAgaXMgc2V0IHRvIGB0cnVlYCBpZiB0aGUgc2V0dGluZ3MgcmVzdWx0IGluIGEgdHJhaWxpbmcgbmVnYXRpdmUgY2hhcmFjdGVyLCBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICAgKiBOb3RlOiBUaGlzIHJldHVybnMgYHRydWVgIGV2ZW4gaWYgdGhlIHJhdyB2YWx1ZSBpcyBwb3NpdGl2ZS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zZXRUcmFpbGluZ05lZ2F0aXZlU2lnbkluZm8oKSB7XG4gICAgICAgIHRoaXMuaXNUcmFpbGluZ05lZ2F0aXZlID0gKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4ICYmIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4KSB8fFxuICAgICAgICAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXggJiZcbiAgICAgICAgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdCB8fCB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnJpZ2h0KSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RyaXAgYWxsIHRoZSB1bndhbnRlZCBub24tbnVtYmVyIGNoYXJhY3RlcnMuXG4gICAgICogSG93ZXZlciBpdCBkb2VzIG5vdCByZW9yZGVyIHRoZSBsb2NhbGl6ZWQgbmVnYXRpdmUgc2lnbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHBhcmFtIHtib29sZWFufSBzdHJpcFplcm9zIElmIHNldCB0byBgZmFsc2VgLCB0aGVuIHRoZSBsZWFkaW5nIHplcm8ocykgYXJlIG5vdCBzdHJpcHBlZCwgb3RoZXJ3aXNlIGlmIHNldCB0byBgdHJ1ZWAsIHRoZSBgbGVhZGluZ1plcm9gIG9wdGlvbiBpcyBmb2xsb3dlZFxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNGb2N1c2VkIElmIHRoZSBlbGVtZW50IGlzIGZvY3VzZWQsIHRoZW4gdGhpcyBpcyBgdHJ1ZWBcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnMocywgc2V0dGluZ3MsIHN0cmlwWmVyb3MsIGlzRm9jdXNlZCkge1xuICAgICAgICByZXR1cm4gdGhpcy5fc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzRXhjZXB0Q3VzdG9tRGVjaW1hbENoYXIocywgc2V0dGluZ3MsIHN0cmlwWmVyb3MsIGlzRm9jdXNlZCkucmVwbGFjZShzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyLCAnLicpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0cmlwIGFsbCB1bndhbnRlZCBub24tbnVtYmVyIGNoYXJhY3RlcnMgZXhjZXB0IHRoZSBjdXN0b20gZGVjaW1hbCBjaGFyYWN0ZXIuXG4gICAgICpcbiAgICAgKiBJdCBjb252ZXJ0cyB0aGUgY3VzdG9tIG5lZ2F0aXZlIHNpZ24gYW5kIHJlbW92ZXMgdGhlIHBvc2l0aXZlIHNpZ24gKGN1c3RvbSBvciBub3QpLlxuICAgICAqIFRoaXMga2VlcHMgOlxuICAgICAqIC0gdGhlIG51bWJlcnMsXG4gICAgICogLSB0aGUgbm9ybWFsIG5lZ2F0aXZlIHNpZ24gJy0nIGlmIGFueSxcbiAgICAgKiAtIGFuZCB0aGUgKmN1c3RvbSogZGVjaW1hbCBjaGFyYWN0ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc1xuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc3RyaXBaZXJvcyBJZiBzZXQgdG8gYGZhbHNlYCwgdGhlbiB0aGUgbGVhZGluZyB6ZXJvKHMpIGFyZSBub3Qgc3RyaXBwZWQsIG90aGVyd2lzZSBpZiBzZXQgdG8gYHRydWVgLCB0aGUgYGxlYWRpbmdaZXJvYCBvcHRpb24gaXMgZm9sbG93ZWRcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzRm9jdXNlZCBJZiB0aGUgZWxlbWVudCBpcyBmb2N1c2VkLCB0aGVuIHRoaXMgaXMgYHRydWVgXG4gICAgICogQHJldHVybnMge3N0cmluZ3wqfVxuICAgICAqL1xuICAgIHN0YXRpYyBfc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzRXhjZXB0Q3VzdG9tRGVjaW1hbENoYXIocywgc2V0dGluZ3MsIHN0cmlwWmVyb3MsIGlzRm9jdXNlZCkge1xuICAgICAgICAvL1hYWCBOb3RlOyB0aGlzIGZ1bmN0aW9uIGlzIHN0YXRpYyBzaW5jZSB3ZSBuZWVkIHRvIHBhc3MgYSBgc2V0dGluZ3NgIG9iamVjdCB3aGVuIGNhbGxpbmcgdGhlIHN0YXRpYyBgQXV0b051bWVyaWMuZm9ybWF0KClgIG1ldGhvZFxuICAgICAgICAvL1RPRE8gVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgMTAgdGltZXMgKHNpYyEpIG9uIGVhY2gga2V5IGlucHV0LCBjb3VsZG4ndCB3ZSBsb3dlciB0aGF0IG51bWJlcj8gY2YuIGlzc3VlICMzMjVcbiAgICAgICAgcyA9IHRoaXMuX25vcm1hbGl6ZUN1cnJlbmN5U3VmZml4QW5kTmVnYXRpdmVTaWduQ2hhcmFjdGVycyhzLCBzZXR0aW5ncyk7XG5cbiAgICAgICAgLy8gVGhlbiByZW1vdmUgYWxsIHRoZSBjaGFyYWN0ZXJzIHRoYXQgYXJlIG5vdCBudW1iZXJzLCB0aGUgbm9ybWFsIG5lZ2F0aXZlIHNpZ24gJy0nLCBvciB0aGUgY3VzdG9tIGRlY2ltYWwgY2hhcmFjdGVyIChub3RlOiB0aGlzIGFsc28gcmVtb3ZlIGFueSBjdXN0b20gcG9zaXRpdmUgc2lnbilcbiAgICAgICAgcyA9IHMucmVwbGFjZShzZXR0aW5ncy5hbGxvd2VkQXV0b1N0cmlwLCAnJyk7XG5cbiAgICAgICAgLy8gR2V0IG9ubHkgbnVtYmVyIHN0cmluZ1xuICAgICAgICBjb25zdCBtID0gcy5tYXRjaChzZXR0aW5ncy5udW1SZWdBdXRvU3RyaXApO1xuICAgICAgICBzID0gbSA/IFttWzFdLCBtWzJdLCBtWzNdXS5qb2luKCcnKSA6ICcnO1xuXG4gICAgICAgIGlmIChzZXR0aW5ncy5sZWFkaW5nWmVybyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5hbGxvdyB8fCBzZXR0aW5ncy5sZWFkaW5nWmVybyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5rZWVwKSB7XG4gICAgICAgICAgICBsZXQgbmVnYXRpdmVTaWduID0gJyc7XG4gICAgICAgICAgICBjb25zdCBbaW50ZWdlclBhcnQsIGRlY2ltYWxQYXJ0XSA9IHMuc3BsaXQoc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcik7XG4gICAgICAgICAgICBsZXQgbW9kaWZpZWRJbnRlZ2VyUGFydCA9IGludGVnZXJQYXJ0O1xuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKG1vZGlmaWVkSW50ZWdlclBhcnQsIHNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikpIHtcbiAgICAgICAgICAgICAgICBuZWdhdGl2ZVNpZ24gPSBzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXI7XG4gICAgICAgICAgICAgICAgbW9kaWZpZWRJbnRlZ2VyUGFydCA9IG1vZGlmaWVkSW50ZWdlclBhcnQucmVwbGFjZShzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIsICcnKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU3RyaXAgbGVhZGluZyB6ZXJvIG9uIHBvc2l0aXZlIHZhbHVlIGlmIG5lZWRlZFxuICAgICAgICAgICAgaWYgKG5lZ2F0aXZlU2lnbiA9PT0gJycgJiYgbW9kaWZpZWRJbnRlZ2VyUGFydC5sZW5ndGggPiBzZXR0aW5ncy5tSW50UG9zICYmIG1vZGlmaWVkSW50ZWdlclBhcnQuY2hhckF0KDApID09PSAnMCcpIHtcbiAgICAgICAgICAgICAgICBtb2RpZmllZEludGVnZXJQYXJ0ID0gbW9kaWZpZWRJbnRlZ2VyUGFydC5zbGljZSgxKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU3RyaXAgbGVhZGluZyB6ZXJvIG9uIG5lZ2F0aXZlIHZhbHVlIGlmIG5lZWRlZFxuICAgICAgICAgICAgaWYgKG5lZ2F0aXZlU2lnbiAhPT0gJycgJiYgbW9kaWZpZWRJbnRlZ2VyUGFydC5sZW5ndGggPiBzZXR0aW5ncy5tSW50TmVnICYmIG1vZGlmaWVkSW50ZWdlclBhcnQuY2hhckF0KDApID09PSAnMCcpIHtcbiAgICAgICAgICAgICAgICBtb2RpZmllZEludGVnZXJQYXJ0ID0gbW9kaWZpZWRJbnRlZ2VyUGFydC5zbGljZSgxKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcyA9IGAke25lZ2F0aXZlU2lnbn0ke21vZGlmaWVkSW50ZWdlclBhcnR9JHtBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZChkZWNpbWFsUGFydCk/Jyc6c2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciArIGRlY2ltYWxQYXJ0fWA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKHN0cmlwWmVyb3MgJiYgc2V0dGluZ3MubGVhZGluZ1plcm8gPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8uZGVueSkgfHxcbiAgICAgICAgICAgICghaXNGb2N1c2VkICYmIHNldHRpbmdzLmxlYWRpbmdaZXJvID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmFsbG93KSkge1xuICAgICAgICAgICAgcyA9IHMucmVwbGFjZShzZXR0aW5ncy5zdHJpcFJlZywgJyQxJDInKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgb3IgcmVtb3ZlcyBicmFja2V0cyBvbiBuZWdhdGl2ZSB2YWx1ZXMsIGRlcGVuZGluZyBvbiB0aGUgZm9jdXMgc3RhdGUsIHdoaWNoIGlzIHBhc3NlZCBhcyBgaXNGb2N1c2VkYC5cbiAgICAgKiBUaGUgZm9jdXMgc3RhdGUgaXMgJ3N0b3JlZCcgaW4gdGhhdCBvYmplY3QgcHJvcGVydHkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzRm9jdXNlZFxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBfdG9nZ2xlTmVnYXRpdmVCcmFja2V0KHZhbHVlLCBzZXR0aW5ncywgaXNGb2N1c2VkKSB7XG4gICAgICAgIC8vWFhYIE5vdGU7IHRoaXMgZnVuY3Rpb24gaXMgc3RhdGljIHNpbmNlIHdlIG5lZWQgdG8gcGFzcyBhIGBzZXR0aW5nc2Agb2JqZWN0IHdoZW4gY2FsbGluZyB0aGUgc3RhdGljIGBBdXRvTnVtZXJpYy5mb3JtYXQoKWAgbWV0aG9kXG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIGlmIChpc0ZvY3VzZWQpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuX3JlbW92ZUJyYWNrZXRzKHZhbHVlLCBzZXR0aW5ncyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSB0aGlzLl9hZGRCcmFja2V0cyh2YWx1ZSwgc2V0dGluZ3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGQgdGhlIGJyYWNrZXQgdHlwZXMgc3BlY2lmaWVkIGluIHRoZSBgc2V0dGluZ3NgIG9iamVjdCwgdG8gdGhlIGdpdmVuIHN0cmluZyBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfYWRkQnJhY2tldHModmFsdWUsIHNldHRpbmdzKSB7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoc2V0dGluZ3MubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIpKSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYCR7c2V0dGluZ3MuZmlyc3RCcmFja2V0fSR7dmFsdWUucmVwbGFjZShzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIsICcnKX0ke3NldHRpbmdzLmxhc3RCcmFja2V0fWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBicmFja2V0IHR5cGVzIHNwZWNpZmllZCBpbiB0aGUgYHNldHRpbmdzYCBvYmplY3QsIGZyb20gdGhlIGdpdmVuIHN0cmluZyBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHBhcmFtIHtib29sZWFufSByZWFycmFuZ2VTaWduc0FuZFZhbHVlT3JkZXIgSWYgc2V0IHRvIGB0cnVlYCwgdGhlbiBvbmx5IHRoZSBicmFja2V0cyBhcmUgcmVtb3ZlIGFuZCBhIG5lZ2F0aXZlIHNpZ24gaXMgYWRkZWQsIHdpdGhvdXQgcmVvcmRlcmluZyB0aGUgbmVnYXRpdmUgc2lnbiwgY3VycmVuY3kgc3ltYm9sIGFuZCB2YWx1ZSBhY2NvcmRpbmcgdG8gdGhlIHNldHRpbmdzLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3JlbW92ZUJyYWNrZXRzKHZhbHVlLCBzZXR0aW5ncywgcmVhcnJhbmdlU2lnbnNBbmRWYWx1ZU9yZGVyID0gdHJ1ZSkge1xuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChzZXR0aW5ncy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1cikgJiYgdmFsdWUuY2hhckF0KDApID09PSBzZXR0aW5ncy5maXJzdEJyYWNrZXQpIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgYnJhY2tldHMgaWYgdGhleSBhcmUgcHJlc2VudFxuICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUucmVwbGFjZShzZXR0aW5ncy5maXJzdEJyYWNrZXQsICcnKTtcbiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKHNldHRpbmdzLmxhc3RCcmFja2V0LCAnJyk7XG5cbiAgICAgICAgICAgIC8vIEFkZCBiYWNrIHRoZSBuZWdhdGl2ZSBzaWduIGF0IHRoZSByaWdodCBwbGFjZVxuICAgICAgICAgICAgaWYgKHJlYXJyYW5nZVNpZ25zQW5kVmFsdWVPcmRlcikge1xuICAgICAgICAgICAgICAgIC8vIEZpcnN0IHdlIG5lZWQgdG8gcmVtb3ZlIHRoZSBjdXJyZW5jeSBzeW1ib2wgZnJvbSB0aGUgdmFsdWUsIHNpbmNlIHdlIHdhbnQgdG8gYmUgYWJsZSB0byBhZGQgYmFjayB0aGUgbmVnYXRpdmUgc2lnbiBhdCB0aGUgcmlnaHQgcGxhY2UgKGluY2x1ZGluZyBiZXR3ZWVuIHRoZSB2YWx1ZSBhbmQgdGhlIGN1cnJlbmN5IHNpZ24pXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnJlcGxhY2Uoc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wsICcnKTtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLl9tZXJnZUN1cnJlbmN5U2lnbk5lZ2F0aXZlUG9zaXRpdmVTaWduQW5kVmFsdWUocmVzdWx0LCBzZXR0aW5ncywgdHJ1ZSwgZmFsc2UpOyAvL1RPRE8gVGhpcyBhc3N1bWUgdGhlIHZhbHVlIGlzIG5lZ2F0aXZlIGFuZCBub24tZW1wdHkuIElzIHRoaXMgYWx3YXlzIHRoZSBjYXNlP1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBIZXJlIHdlIG9ubHkgd2FudCB0byBhZGQgdGhlIG5lZ2F0aXZlIHNpZ24gc2luY2Ugd2UgcmVtb3ZlZCB0aGUgYnJhY2tldHMsIHdpdGhvdXQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGAke3NldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlcn0ke3Jlc3VsdH1gO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFuYWx5emUgdGhlIGBuZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1cmAgb3B0aW9ucyBhbmQga2VlcCB0cmFjayBvZiB0aGUgZmlyc3QgYW5kIGxhc3QgYnJhY2tldCBjaGFyYWN0ZXJzIHRvIHVzZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9zZXRCcmFja2V0cyhzZXR0aW5ncykge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHNldHRpbmdzLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyKSkge1xuICAgICAgICAgICAgc2V0dGluZ3MuZmlyc3RCcmFja2V0ID0gJyc7XG4gICAgICAgICAgICBzZXR0aW5ncy5sYXN0QnJhY2tldCAgPSAnJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFVzZSB0ZW1wb3JhcnkgdmFyaWFibGVzIHRvIGZpeCB0aGUgTVMgRWRnZSBkZXN0cnVjdHVyaW5nIGlzc3VlIChzZWUgcHVsbCByZXF1ZXN0ICM1NjQpXG4gICAgICAgICAgICBjb25zdCBbZmlyc3RCcmFja2V0LCBsYXN0QnJhY2tldF0gPSBzZXR0aW5ncy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5zcGxpdCgnLCcpO1xuICAgICAgICAgICAgc2V0dGluZ3MuZmlyc3RCcmFja2V0ID0gZmlyc3RCcmFja2V0O1xuICAgICAgICAgICAgc2V0dGluZ3MubGFzdEJyYWNrZXQgPSBsYXN0QnJhY2tldDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIG51bWJlciBhcyBhIG51bWVyaWMgc3RyaW5nIHRoYXQgY2FuIGJlIHR5cGVjYXN0IHRvIGEgTnVtYmVyIHRoYXQgSmF2YXNjcmlwdCB3aWxsIHVuZGVyc3RhbmQuXG4gICAgICpcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIHJldHVybnMgdGhlIGdpdmVuIHN0cmluZyBieSBzdHJpcHBpbmc6XG4gICAgICogLSB0aGUgY3VycmVuY3kgc2lnbiAoY3VycmVuY3lTeW1ib2wpLFxuICAgICAqIC0gdGhlIGdyb3VwaW5nIHNlcGFyYXRvcnMgKGRpZ2l0YWxHcm91cFNwYWNpbmcpLFxuICAgICAqIC0gdGhlIHN1ZmZpeCB0ZXh0IChzdWZmaXhUZXh0KSxcbiAgICAgKiAtIHRoZSBwb3NpdGl2ZSBzaWduIChwb3NpdGl2ZVNpZ25DaGFyYWN0ZXIpLFxuICAgICAqIC0gdGhlIGJyYWNrZXRzIGlmIGFueSxcbiAgICAgKiAtIGJ5IHJlcGxhY2luZyB0aGUgbmVnYXRpdmUgc2lnbiBjaGFyYWN0ZXIgd2l0aCBhbiBoeXBoZW4sXG4gICAgICogLSBhbmQgYnkgcmVwbGFjaW5nIHRoZSBkZWNpbWFsIGNoYXJhY3RlciAoZGVjaW1hbENoYXJhY3RlcikgYnkgYSBkb3QuXG4gICAgICpcbiAgICAgKiBMYXN0bHksIGl0IGFsc28gcHV0IHRoZSBuZWdhdGl2ZSBzaWduIGJhY2sgdG8gaXRzIG5vcm1hbCBwb3NpdGlvbiBpZiBuZWVkZWQuXG4gICAgICogQm9udXM7IGl0IGNvbnZlcnRzIGFueSBhcmFiaWMgbnVtYmVycyBmb3VuZCB0byB0aGUgbGF0aW4gb25lcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMge3N0cmluZ3x2b2lkfCp9XG4gICAgICovXG4gICAgc3RhdGljIF9jb252ZXJ0VG9OdW1lcmljU3RyaW5nKHMsIHNldHRpbmdzKSB7XG4gICAgICAgIC8vIFJlbW92ZSB0aGUgY3VzdG9tIGJyYWNrZXRzXG4gICAgICAgIHMgPSB0aGlzLl9yZW1vdmVCcmFja2V0cyhzLCBzZXR0aW5ncywgZmFsc2UpO1xuICAgICAgICBzID0gdGhpcy5fbm9ybWFsaXplQ3VycmVuY3lTdWZmaXhBbmROZWdhdGl2ZVNpZ25DaGFyYWN0ZXJzKHMsIHNldHRpbmdzKTtcblxuICAgICAgICAvLyBSZW1vdmUgdGhlIGdyb3VwaW5nIHNlcGFyYXRvcnMgKHRob3VzYW5kcyBzZXBhcmF0b3JzIHVzdWFsbHkpXG4gICAgICAgIHMgPSBzLnJlcGxhY2UobmV3IFJlZ0V4cChgWyR7c2V0dGluZ3MuZGlnaXRHcm91cFNlcGFyYXRvcn1dYCwgJ2cnKSwgJycpO1xuXG4gICAgICAgIC8vIFJlcGxhY2UgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGJ5IGEgZG90XG4gICAgICAgIGlmIChzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyICE9PSAnLicpIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2Uoc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciwgJy4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1vdmUgdGhlIHRyYWlsaW5nIG5lZ2F0aXZlIHNpZ24sIGlmIGFueSwgdG8gdGhlIHVzdWFsIGxlZnRtb3N0IHBvc2l0aW9uXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKHMpICYmIHMubGFzdEluZGV4T2YoJy0nKSA9PT0gcy5sZW5ndGggLSAxKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKCctJywgJycpO1xuICAgICAgICAgICAgcyA9IGAtJHtzfWA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXBsYWNlIHRoZSBjdXN0b20gcG9zaXRpdmUgc2lnblxuICAgICAgICBpZiAoc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbikge1xuICAgICAgICAgICAgcyA9IHMucmVwbGFjZShzZXR0aW5ncy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXIsICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbnZlcnQgYXJhYmljIG51bWJlcnMgdG8gbGF0aW4gb25lcywgaWYgYW55XG4gICAgICAgIGNvbnN0IGNvbnZlcnRUb051bWJlciA9IHNldHRpbmdzLmxlYWRpbmdaZXJvICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmtlZXA7XG4gICAgICAgIGNvbnN0IHRlbXAgPSBBdXRvTnVtZXJpY0hlbHBlci5hcmFiaWNUb0xhdGluTnVtYmVycyhzLCBjb252ZXJ0VG9OdW1iZXIsIGZhbHNlLCBmYWxzZSk7XG4gICAgICAgIGlmICghaXNOYU4odGVtcCkpIHtcbiAgICAgICAgICAgIHMgPSB0ZW1wLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIHRoZSBjdXJyZW5jeSBzeW1ib2wgYW5kIHRoZSBzdWZmaXggdGV4dCBmcm9tIHRoZSBnaXZlbiBzdHJpbmcsIGFuZCByZXBsYWNlIHRoZSBjdXN0b20gbmVnYXRpdmUgc2lnbiB3aXRoIGFuIGh5cGhlbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMge3N0cmluZyB8ICp9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX25vcm1hbGl6ZUN1cnJlbmN5U3VmZml4QW5kTmVnYXRpdmVTaWduQ2hhcmFjdGVycyhzLCBzZXR0aW5ncykge1xuICAgICAgICBzID0gU3RyaW5nKHMpOyAvLyBUeXBlY2FzdCB0byB0byBhIHN0cmluZywgaW4gY2FzZSB0aGF0IHRoZSBnaXZlbiB2YWx1ZSBpcyBhIG51bWJlclxuXG4gICAgICAgIC8vIFJlbW92ZSB0aGUgY3VycmVuY3kgc3ltYm9sXG4gICAgICAgIGlmIChzZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC5ub25lKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZW1vdmUgdGhlIHN1ZmZpeFRleHRcbiAgICAgICAgaWYgKHNldHRpbmdzLnN1ZmZpeFRleHQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMuc3VmZml4VGV4dC5ub25lKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKHNldHRpbmdzLnN1ZmZpeFRleHQsICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlcGxhY2UgdGhlIGN1c3RvbSBuZWdhdGl2ZSBzaWduIHdpdGggYW4gaHlwaGVuXG4gICAgICAgIGlmIChzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVTaWduQ2hhcmFjdGVyLmh5cGhlbikge1xuICAgICAgICAgICAgcyA9IHMucmVwbGFjZShzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIsICctJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyB0aGUgSVNPIG51bWVyaWMgc3RyaW5nIHRvIHRoZSBsb2NhbGUgZGVjaW1hbCBhbmQgbWludXMgc2lnbiBwbGFjZW1lbnQuXG4gICAgICogU2VlIHRoZSBcIm91dHB1dEZvcm1hdFwiIG9wdGlvbiBkZWZpbml0aW9uIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICogTm90ZTogSWYgdGhlIGBvdXRwdXRGb3JtYXRgIGlzIHNldCB0byBhIG51bWJlciwgdGhlIGN1c3RvbSBgbmVnYXRpdmVTaWduQ2hhcmFjdGVyYCBpcyBpZ25vcmVkLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVsbH0gdmFsdWUgVGhlIHVuZm9ybWF0dGVkIHZhbHVlXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVsbH0gbG9jYWxlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIF90b0xvY2FsZSh2YWx1ZSwgbG9jYWxlLCBzZXR0aW5ncykge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGxvY2FsZSkgfHwgbG9jYWxlID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5zdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIHN3aXRjaCAobG9jYWxlKSB7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0Lm51bWJlcjpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBOdW1iZXIodmFsdWUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5kb3ROZWdhdGl2ZTpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKHZhbHVlKSA/IHZhbHVlLnJlcGxhY2UoJy0nLCAnJykgKyAnLScgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQuY29tbWE6XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0Lm5lZ2F0aXZlQ29tbWE6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUucmVwbGFjZSgnLicsICcsJyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0LmNvbW1hTmVnYXRpdmU6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUucmVwbGFjZSgnLicsICcsJyk7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZShyZXN1bHQpID8gcmVzdWx0LnJlcGxhY2UoJy0nLCAnJykgKyAnLScgOiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAvLyBUaGUgZGVmYXVsdCBjYXNlXG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0LmRvdDpcbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQubmVnYXRpdmVEb3Q6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gb3V0cHV0Rm9ybWF0IFske2xvY2FsZX1dIG9wdGlvbiBpcyBub3QgcmVjb2duaXplZC5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChsb2NhbGUgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0Lm51bWJlciAmJiBzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgIT09ICctJykge1xuICAgICAgICAgICAgLy8gTW9kaWZ5IHRoZSBkZWZhdWx0IG1pbnVzIHNpZ24gd2l0aCB0aGUgY3VzdG9tIG9uZSwgaWYgYW55XG4gICAgICAgICAgICByZXN1bHQgPSByZXN1bHQucmVwbGFjZSgnLScsIHNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1vZGlmeSB0aGUgbmVnYXRpdmUgc2lnbiBhbmQgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIG9mIHRoZSBnaXZlbiBzdHJpbmcgdmFsdWUgdG8gYW4gaHlwaGVuICgtKSBhbmQgYSBkb3QgKC4pIGluIG9yZGVyIHRvIG1ha2UgdGhhdCB2YWx1ZSAndHlwZWNhc3RhYmxlJyB0byBhIHJlYWwgbnVtYmVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHMgVGhlIGZvcm1hdHRlZCB2YWx1ZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9IFRoZSB2YWx1ZSB3aXRoIHRoZSAnbm9ybWFsJyBtaW51cyBzaWduIGFuZCBkZWNpbWFsIGNoYXJhY3RlclxuICAgICAqL1xuICAgIF9tb2RpZnlOZWdhdGl2ZVNpZ25BbmREZWNpbWFsQ2hhcmFjdGVyRm9yUmF3VmFsdWUocykge1xuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyICE9PSAnLicpIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2UodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyLCAnLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyICE9PSAnLScgJiYgdGhpcy5zZXR0aW5ncy5pc05lZ2F0aXZlU2lnbkFsbG93ZWQpIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2UodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIsICctJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXMubWF0Y2goL1xcZC8pKSB7XG4gICAgICAgICAgICAvLyBUaGUgZGVmYXVsdCB2YWx1ZSByZXR1cm5lZCBieSBgZ2V0YCBpcyBub3QgZm9ybWF0dGVkIHdpdGggZGVjaW1hbHNcbiAgICAgICAgICAgIHMgKz0gJzAnO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTW9kaWZ5IHRoZSBuZWdhdGl2ZSBzaWduIGFuZCB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgdG8gdXNlIHRob3NlIGRlZmluZWQgaW4gdGhlIHNldHRpbmdzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBfbW9kaWZ5TmVnYXRpdmVTaWduQW5kRGVjaW1hbENoYXJhY3RlckZvckZvcm1hdHRlZFZhbHVlKHMsIHNldHRpbmdzKSB7XG4gICAgICAgIC8vWFhYIE5vdGU7IHRoaXMgZnVuY3Rpb24gaXMgc3RhdGljIHNpbmNlIHdlIG5lZWQgdG8gcGFzcyBhIGBzZXR0aW5nc2Agb2JqZWN0IHdoZW4gY2FsbGluZyB0aGUgc3RhdGljIGBBdXRvTnVtZXJpYy5mb3JtYXQoKWAgbWV0aG9kXG4gICAgICAgIGlmIChzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgIT09ICctJykge1xuICAgICAgICAgICAgcyA9IHMucmVwbGFjZSgnLScsIHNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlcik7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciAhPT0gJy4nKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKCcuJywgc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBnaXZlbiB2YWx1ZSBpcyBlbXB0eSBvciBpcyBlcXVhbCB0byB0aGUgbmVnYXRpdmUgc2lnbiBjaGFyYWN0ZXIgZGVmaW5lZCBpbiB0aGUgZ2l2ZW4gc2V0dGluZ3MuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfaXNFbGVtZW50VmFsdWVFbXB0eU9yT25seVRoZU5lZ2F0aXZlU2lnbih2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSAnJyB8fCB2YWx1ZSA9PT0gc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgdmFsdWUgd2l0aCB0aGUgY3VycmVuY3kgc3ltYm9sIGFuZCB0aGUgc3VmZml4IHRleHQgb3JkZXJlZCBhY2NvcmRpbmcgdG8gdGhlIGdpdmVuIHNldHRpbmdzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHBhcmFtIHtib29sZWFufSBzaWduT25FbXB0eVxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9vcmRlclZhbHVlQ3VycmVuY3lTeW1ib2xBbmRTdWZmaXhUZXh0KHZhbHVlLCBzZXR0aW5ncywgc2lnbk9uRW1wdHkpIHtcbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKHNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvciA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IuYWx3YXlzIHx8IHNpZ25PbkVtcHR5KSB7XG4gICAgICAgICAgICBpZiAoc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdCkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlICsgc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgKyBzZXR0aW5ncy5zdWZmaXhUZXh0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBzZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCArIHZhbHVlICsgc2V0dGluZ3Muc3VmZml4VGV4dDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNb2RpZnkgdGhlIGlucHV0IHZhbHVlIGJ5IGFkZGluZyB0aGUgZ3JvdXAgc2VwYXJhdG9ycywgYXMgZGVmaW5lZCBpbiB0aGUgc2V0dGluZ3MsIGFuZCB0aGUgbmVnYXRpdmUgYnJhY2tldHMgaWYgbmVlZGVkLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGlucHV0VmFsdWUgVGhlIGZvcm1hdHRlZCB2YWx1ZSAoaWUuIHdpdGggdGhlIGBkZWNpbWFsQ2hhcmFjdGVyYCBkZWZpbmVkIGluIHRoZSBzZXR0aW5ncywgbm90IHRoZSByYXcgdmFsdWUpXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHBhcmFtIHtib29sZWFufSBpc0ZvY3VzZWRcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd8bnVsbH0gY3VycmVudFJhd1ZhbHVlIFRoZSBvYmplY3QgY3VycmVudCByYXcgdmFsdWUgKGB0aGlzLnJhd1ZhbHVlYClcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd8bnVsbH0gZm9yY2VkUmF3VmFsdWUgSWYgdGhpcyBpcyBzZXQsIHRoZW4gdGhpcyByYXdWYWx1ZSBpcyB1c2VkIGluc3RlYWQgb2YgdGhlIG9uZSBwYXNzZWQgdGhyb3VnaCB0aGUgYHNldHRpbmdzYCBvYmplY3QuIFRoaXMgaXMgdXNlZnVsIGlzIHNvbWUgdmVyeSBzcGVjaWZpYyBjYXNlcyB3aGVyZSB3ZSBuZWVkIHRvIHNldCB0aGUgcmF3IHZhbHVlICphZnRlciogc2V0dGluZ3MgdGhlIGZvcm1hdHRlZCB2YWx1ZSwgdXNpbmcgdGhlIGBfYWRkR3JvdXBTZXBhcmF0b3JzKClgIG1ldGhvZC5cbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgX2FkZEdyb3VwU2VwYXJhdG9ycyhpbnB1dFZhbHVlLCBzZXR0aW5ncywgaXNGb2N1c2VkLCBjdXJyZW50UmF3VmFsdWUsIGZvcmNlZFJhd1ZhbHVlID0gbnVsbCkge1xuICAgICAgICAvL1RPRE8gVGVzdCBpZiBgaW5wdXRWYWx1ZWAgPT09ICcnLCBhbmQgcmV0dXJuICcnIGRpcmVjdGx5IGlmIHRoYXQncyB0aGUgY2FzZSxcbiAgICAgICAgLy9YWFggTm90ZTsgdGhpcyBmdW5jdGlvbiBpcyBzdGF0aWMgc2luY2Ugd2UgbmVlZCB0byBwYXNzIGEgYHNldHRpbmdzYCBvYmplY3Qgd2hlbiBjYWxsaW5nIHRoZSBzdGF0aWMgYEF1dG9OdW1lcmljLmZvcm1hdCgpYCBtZXRob2RcbiAgICAgICAgbGV0IGlzVmFsdWVOZWdhdGl2ZTtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoZm9yY2VkUmF3VmFsdWUpKSB7XG4gICAgICAgICAgICAvLyBQcmVmZXIgZGlyZWN0bHkgdGVzdGluZyBpZiB0aGUgcmF3IHZhbHVlIGlzIG5lZ2F0aXZlIGluIG9yZGVyIGZvciB0aGUgdGVzdCB0byBiZSBtb3JlIHBlcmZvcm1hbnQgdGhhbiBtYW5pcHVsYXRpbmcgdGhlIGZvcm1hdHRlZCB2YWx1ZVxuICAgICAgICAgICAgaXNWYWx1ZU5lZ2F0aXZlID0gZm9yY2VkUmF3VmFsdWUgPCAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaXNWYWx1ZU5lZ2F0aXZlID0gQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZShpbnB1dFZhbHVlLCBzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpIHx8IEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmVXaXRoQnJhY2tldHMoaW5wdXRWYWx1ZSwgc2V0dGluZ3MuZmlyc3RCcmFja2V0LCBzZXR0aW5ncy5sYXN0QnJhY2tldCk7IC8vIFRlc3QgaWYgdGhlIHZhbHVlIGlzIG5lZ2F0aXZlIGJlZm9yZSByZW1vdmluZyB0aGUgbmVnYXRpdmUgc2lnblxuICAgICAgICB9XG5cbiAgICAgICAgaW5wdXRWYWx1ZSA9IHRoaXMuX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVyc0V4Y2VwdEN1c3RvbURlY2ltYWxDaGFyKGlucHV0VmFsdWUsIHNldHRpbmdzLCBmYWxzZSwgaXNGb2N1c2VkKTtcblxuICAgICAgICBpZiAodGhpcy5faXNFbGVtZW50VmFsdWVFbXB0eU9yT25seVRoZU5lZ2F0aXZlU2lnbihpbnB1dFZhbHVlLCBzZXR0aW5ncykpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLl9vcmRlclZhbHVlQ3VycmVuY3lTeW1ib2xBbmRTdWZmaXhUZXh0KGlucHV0VmFsdWUsIHNldHRpbmdzLCB0cnVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGlzWmVyb09ySGFzTm9WYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmlzWmVyb09ySGFzTm9WYWx1ZShpbnB1dFZhbHVlKTtcblxuICAgICAgICAvLyBUZW1wb3JhcmlseSByZW1vdmUgdGhlIG5lZ2F0aXZlIHNpZ24gaWYgcHJlc2VudFxuICAgICAgICBpZiAoaXNWYWx1ZU5lZ2F0aXZlKSB7XG4gICAgICAgICAgICBpbnB1dFZhbHVlID0gaW5wdXRWYWx1ZS5yZXBsYWNlKCctJywgJycpOyAvLyBBdCB0aGlzIHBvaW50IHRoZSBgaW5wdXRWYWx1ZWAgaGFzIGJlZW4gbm9ybWFsaXplZCB3aXRoIGEgJ25vcm1hbCcgbmVnYXRpdmUgc2lnbiBgJy0nYCAvL1RPRE8gQ2hlY2sgdGhhdCBjb21tZW50IHZhbGlkaXR5LCBzaW5jZSBgX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVyc0V4Y2VwdEN1c3RvbURlY2ltYWxDaGFyYCAqZG9lcyBub3QqIGNvbnZlcnQgdGhlIG5lZ2F0aXZlIHNpZ25cbiAgICAgICAgfVxuXG4gICAgICAgIHNldHRpbmdzLmRpZ2l0YWxHcm91cFNwYWNpbmcgPSBzZXR0aW5ncy5kaWdpdGFsR3JvdXBTcGFjaW5nLnRvU3RyaW5nKCk7XG4gICAgICAgIGxldCBkaWdpdGFsR3JvdXA7XG4gICAgICAgIHN3aXRjaCAoc2V0dGluZ3MuZGlnaXRhbEdyb3VwU3BhY2luZykge1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcudHdvOlxuICAgICAgICAgICAgICAgIGRpZ2l0YWxHcm91cCA9IC8oXFxkKSgoXFxkKShcXGR7Mn0/KSspJC87XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRhbEdyb3VwU3BhY2luZy50d29TY2FsZWQ6XG4gICAgICAgICAgICAgICAgZGlnaXRhbEdyb3VwID0gLyhcXGQpKCg/OlxcZHsyfSl7MCwyfVxcZHszfSg/Oig/OlxcZHsyfSl7Mn1cXGR7M30pKj8pJC87XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRhbEdyb3VwU3BhY2luZy5mb3VyOlxuICAgICAgICAgICAgICAgIGRpZ2l0YWxHcm91cCA9IC8oXFxkKSgoXFxkezR9PykrKSQvO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcudGhyZWU6XG4gICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICBkaWdpdGFsR3JvdXAgPSAvKFxcZCkoKFxcZHszfT8pKykkLztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNwbGl0cyB0aGUgc3RyaW5nIGF0IHRoZSBkZWNpbWFsIHN0cmluZ1xuICAgICAgICBsZXQgW2ludGVnZXJQYXJ0LCBkZWNpbWFsUGFydF0gPSBpbnB1dFZhbHVlLnNwbGl0KHNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpO1xuICAgICAgICBpZiAoc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlICYmIEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKGRlY2ltYWxQYXJ0KSkge1xuICAgICAgICAgICAgW2ludGVnZXJQYXJ0LCBkZWNpbWFsUGFydF0gPSBpbnB1dFZhbHVlLnNwbGl0KHNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2V0dGluZ3MuZGlnaXRHcm91cFNlcGFyYXRvciAhPT0gJycpIHtcbiAgICAgICAgICAgIC8vIFJlLWluc2VydHMgdGhlIHRob3VzYW5kIHNlcGFyYXRvciB2aWEgYSByZWd1bGFyIGV4cHJlc3Npb25cbiAgICAgICAgICAgIHdoaWxlIChkaWdpdGFsR3JvdXAudGVzdChpbnRlZ2VyUGFydCkpIHtcbiAgICAgICAgICAgICAgICBpbnRlZ2VyUGFydCA9IGludGVnZXJQYXJ0LnJlcGxhY2UoZGlnaXRhbEdyb3VwLCBgJDEke3NldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3J9JDJgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZpbmQgb3V0IGhvdyBtYW55IGRlY2ltYWwgcGxhY2VzIHNob3VsZCBiZSBrZXB0LCBkZXBlbmRpbmcgb24gdGhlIG9iamVjdCBzdGF0ZSAoaXNGb2N1c2VkKVxuICAgICAgICBsZXQgZGVjaW1hbFBsYWNlc1RvUm91bmRUbztcbiAgICAgICAgaWYgKGlzRm9jdXNlZCkge1xuICAgICAgICAgICAgZGVjaW1hbFBsYWNlc1RvUm91bmRUbyA9IHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvID0gc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8gIT09IDAgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKGRlY2ltYWxQYXJ0KSkge1xuICAgICAgICAgICAgaWYgKGRlY2ltYWxQYXJ0Lmxlbmd0aCA+IGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8pIHtcbiAgICAgICAgICAgICAgICAvLyBUcmltIHRoZSBleGNlc3NpdmUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzXG4gICAgICAgICAgICAgICAgZGVjaW1hbFBhcnQgPSBkZWNpbWFsUGFydC5zdWJzdHJpbmcoMCwgZGVjaW1hbFBsYWNlc1RvUm91bmRUbyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEpvaW5zIHRoZSB3aG9sZSBudW1iZXIgd2l0aCB0aGUgZGVjaW1hbCB2YWx1ZVxuICAgICAgICAgICAgaW5wdXRWYWx1ZSA9IGAke2ludGVnZXJQYXJ0fSR7c2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcn0ke2RlY2ltYWxQYXJ0fWA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UgaWYgaXQncyBhbiBpbnRlZ2VyXG4gICAgICAgICAgICBpbnB1dFZhbHVlID0gaW50ZWdlclBhcnQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgYmFjayB0aGUgbmVnYXRpdmUvcG9zaXRpdmUgc2lnbiBhbmQgdGhlIGN1cnJlbmN5IHN5bWJvbCwgYXQgdGhlIHJpZ2h0IHBvc2l0aW9uc1xuICAgICAgICBpbnB1dFZhbHVlID0gQXV0b051bWVyaWMuX21lcmdlQ3VycmVuY3lTaWduTmVnYXRpdmVQb3NpdGl2ZVNpZ25BbmRWYWx1ZShpbnB1dFZhbHVlLCBzZXR0aW5ncywgaXNWYWx1ZU5lZ2F0aXZlLCBpc1plcm9Pckhhc05vVmFsdWUpOyAvL1RPRE8gdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgYWdhaW4gaW4gYF90b2dnbGVOZWdhdGl2ZUJyYWNrZXRgIGlmIHRoZSBicmFja2V0cyBhcmUgcmVtb3ZlZDsgbGV0J3MgRFJZIHRoaXNcblxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGZvcmNlZFJhd1ZhbHVlKSkge1xuICAgICAgICAgICAgLy8gSWYgdGhlIHJhdyB2YWx1ZSBpcyBub3QgZm9yY2VkLCB1c2UgdGhlIGRlZmF1bHQgb25lIGZyb20gdGhlIHNldHRpbmdzIG9iamVjdFxuICAgICAgICAgICAgZm9yY2VkUmF3VmFsdWUgPSBjdXJyZW50UmF3VmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUb2dnbGUgdGhlIG5lZ2F0aXZlIHNpZ24gYW5kIGJyYWNrZXRzXG4gICAgICAgIGlmIChzZXR0aW5ncy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciAhPT0gbnVsbCAmJiAoZm9yY2VkUmF3VmFsdWUgPCAwIHx8IEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmVTdHJpY3QoaW5wdXRWYWx1ZSwgc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkpIHtcbiAgICAgICAgICAgIGlucHV0VmFsdWUgPSB0aGlzLl90b2dnbGVOZWdhdGl2ZUJyYWNrZXQoaW5wdXRWYWx1ZSwgc2V0dGluZ3MsIGlzRm9jdXNlZCk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoc2V0dGluZ3Muc3VmZml4VGV4dCkge1xuICAgICAgICAgICAgcmVzdWx0ID0gYCR7aW5wdXRWYWx1ZX0ke3NldHRpbmdzLnN1ZmZpeFRleHR9YDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGlucHV0VmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIHNlbWktZm9ybWF0dGVkIHN0cmluZyB3aGVyZSB0aGUgaW5wdXQgdmFsdWUsIHRoZSBuZWdhdGl2ZSBvciBwb3NpdGl2ZSBzaWduLCBhbmQgdGhlIGN1cnJlbmN5IHN5bWJvbCBhcmUgc3RpdGNoZWQgdG9nZXRoZXIgYXQgdGhlIHJpZ2h0IHBvc2l0aW9ucywgdXNpbmcgdGhlIG9wdGlvbnMgc2V0IGluIHRoZSBgc2V0dGluZ3NgIG9iamVjdC5cbiAgICAgKiBOb3RlIDogdGhlIGBpbnB1dFZhbHVlYCBpcyB1c3VhbGx5IG5vdCBhIG51bWVyaWMgc3RyaW5nIHNpbmNlIHRoZSBncm91cGluZyBzeW1ib2xzIGFyZSBhbHJlYWR5IGFkZGVkIHRvIGl0IGF0IHRoaXMgcG9pbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gaW5wdXRWYWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNWYWx1ZU5lZ2F0aXZlXG4gICAgICogQHBhcmFtIHtib29sZWFufSBpc1plcm9Pckhhc05vVmFsdWVcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKiBAdGhyb3dzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX21lcmdlQ3VycmVuY3lTaWduTmVnYXRpdmVQb3NpdGl2ZVNpZ25BbmRWYWx1ZShpbnB1dFZhbHVlLCBzZXR0aW5ncywgaXNWYWx1ZU5lZ2F0aXZlLCBpc1plcm9Pckhhc05vVmFsdWUpIHtcbiAgICAgICAgbGV0IHNpZ25Ub1VzZSA9ICcnO1xuICAgICAgICBpZiAoaXNWYWx1ZU5lZ2F0aXZlKSB7XG4gICAgICAgICAgICBzaWduVG9Vc2UgPSBzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXI7XG4gICAgICAgIH0gZWxzZSBpZiAoc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSB7XG4gICAgICAgICAgICBzaWduVG9Vc2UgPSBzZXR0aW5ncy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXI7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4KSB7XG4gICAgICAgICAgICBpZiAoc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgIChpc1ZhbHVlTmVnYXRpdmUgfHwgKCFpc1ZhbHVlTmVnYXRpdmUgJiYgc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gYCR7c2lnblRvVXNlfSR7c2V0dGluZ3MuY3VycmVuY3lTeW1ib2x9JHtpbnB1dFZhbHVlfWA7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnJpZ2h0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gYCR7c2V0dGluZ3MuY3VycmVuY3lTeW1ib2x9JHtzaWduVG9Vc2V9JHtpbnB1dFZhbHVlfWA7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGAke3NldHRpbmdzLmN1cnJlbmN5U3ltYm9sfSR7aW5wdXRWYWx1ZX0ke3NpZ25Ub1VzZX1gO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBzZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCArIGlucHV0VmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAoc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4KSB7XG4gICAgICAgICAgICBpZiAoc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgIChpc1ZhbHVlTmVnYXRpdmUgfHwgKCFpc1ZhbHVlTmVnYXRpdmUgJiYgc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXg6XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGAke2lucHV0VmFsdWV9JHtzZXR0aW5ncy5jdXJyZW5jeVN5bWJvbH0ke3NpZ25Ub1VzZX1gO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0OlxuICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gYCR7aW5wdXRWYWx1ZX0ke3NpZ25Ub1VzZX0ke3NldHRpbmdzLmN1cnJlbmN5U3ltYm9sfWA7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGAke3NpZ25Ub1VzZX0ke2lucHV0VmFsdWV9JHtzZXR0aW5ncy5jdXJyZW5jeVN5bWJvbH1gO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBpbnB1dFZhbHVlICsgc2V0dGluZ3MuY3VycmVuY3lTeW1ib2w7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZSB3aGVyZSB0byBwdXQgdGhlIGNhcmV0IHBvc2l0aW9uIG9uIGZvY3VzIGlmIHRoZSBlbGVtZW50IGNvbnRlbnQgaXMgbm90IHNlbGVjdGVkLlxuICAgICAqIFRoaXMgY2FsY3VsYXRpb24gaXMgYWZmZWN0ZWQgYnkgdGhlIGBjYXJldFBvc2l0aW9uT25Gb2N1c2Agb3B0aW9uIHdoaWNoIGNhbiBiZSBlaXRoZXIgYG51bGxgLCBgJ3N0YXJ0J2AsIGAnZW5kJ2AsIGAnZGVjaW1hbExlZnQnYCBvciAnZGVjaW1hbFJpZ2h0J2AsIGFuZCB3aWxsIGRlY2lkZSB3aGVyZSB0byBwdXQgdGhlIGNhcmV0IChvbiB0aGUgbGVmdCBvciByaWdodCBvZiB0aGUgdmFsdWUgb3IgdGhlIGRlY2ltYWwgY2hhcmFjdGVyLCByZXNwZWN0aXZlbHkpIDpcbiAgICAgKiAtIGBudWxsYCA6IHRoZSBjYXJldCBwb3NpdGlvbiBpcyBub3QgZm9yY2VkXG4gICAgICogLSBgJ3N0YXJ0J2AgOiB0aGUgY2FyZXQgaXMgcG9zaXRpb25lZCBvbiB0aGUgbGVmdCBoYW5kIHNpZGUgb2YgdGhlIHZhbHVlXG4gICAgICogLSBgJ2VuZCdgIDogdGhlIGNhcmV0IGlzIHBvc2l0aW9uZWQgb24gdGhlIHJpZ2h0IGhhbmQgc2lkZSBvZiB0aGUgdmFsdWVcbiAgICAgKiAtIGAnZGVjaW1hbExlZnQnYCA6IHRoZSBjYXJldCBpcyBwb3NpdGlvbmVkIG9uIHRoZSBsZWZ0IHNpZGUgb2YgdGhlIGRlY2ltYWwgY2hhcmFjdGVyXG4gICAgICogLSBgJ2RlY2ltYWxSaWdodCdgIDogdGhlIGNhcmV0IGlzIHBvc2l0aW9uZWQgb24gdGhlIHJpZ2h0IHNpZGUgb2YgdGhlIGRlY2ltYWwgY2hhcmFjdGVyXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgVGhlIGZvcm1hdHRlZCBzdHJpbmcgc3RyaXBwZWQgb2YgdGhlIGN1cnJlbmN5IHN5bWJvbCBhbmQgbmVnYXRpdmUvcG9zaXRpdmUgc2lnblxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICogQHRocm93c1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2luaXRpYWxDYXJldFBvc2l0aW9uKHZhbHVlKSB7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodGhpcy5zZXR0aW5ncy5jYXJldFBvc2l0aW9uT25Gb2N1cykgJiZcbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Muc2VsZWN0T25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5zZWxlY3RPbkZvY3VzLmRvTm90U2VsZWN0KSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKCdgX2luaXRpYWxDYXJldFBvc2l0aW9uKClgIHNob3VsZCBuZXZlciBiZSBjYWxsZWQgd2hlbiB0aGUgYGNhcmV0UG9zaXRpb25PbkZvY3VzYCBvcHRpb24gaXMgYG51bGxgLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaXNWYWx1ZU5lZ2F0aXZlID0gdGhpcy5yYXdWYWx1ZSA8IDA7XG4gICAgICAgIGNvbnN0IGlzWmVyb09ySGFzTm9WYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmlzWmVyb09ySGFzTm9WYWx1ZSh2YWx1ZSk7XG4gICAgICAgIGNvbnN0IHRvdGFsTGVuZ3RoID0gdmFsdWUubGVuZ3RoO1xuXG4gICAgICAgIGxldCB2YWx1ZVNpemUgPSAwO1xuICAgICAgICBsZXQgaW50ZWdlclNpemUgPSAwO1xuICAgICAgICBsZXQgaGFzRGVjaW1hbENoYXIgPSBmYWxzZTtcbiAgICAgICAgbGV0IG9mZnNldERlY2ltYWxDaGFyID0gMDtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuc3RhcnQpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWUucmVwbGFjZSh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciwgJycpO1xuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKHRoaXMuc2V0dGluZ3MucG9zaXRpdmVTaWduQ2hhcmFjdGVyLCAnJyk7XG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCwgJycpO1xuICAgICAgICAgICAgdmFsdWVTaXplID0gdmFsdWUubGVuZ3RoO1xuICAgICAgICAgICAgaGFzRGVjaW1hbENoYXIgPSBBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyh2YWx1ZSwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKTtcblxuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZGVjaW1hbExlZnQgfHxcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmRlY2ltYWxSaWdodCkge1xuICAgICAgICAgICAgICAgIGlmIChoYXNEZWNpbWFsQ2hhcikge1xuICAgICAgICAgICAgICAgICAgICBpbnRlZ2VyU2l6ZSA9IHZhbHVlLmluZGV4T2YodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKTtcbiAgICAgICAgICAgICAgICAgICAgb2Zmc2V0RGVjaW1hbENoYXIgPSB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIubGVuZ3RoO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGludGVnZXJTaXplID0gdmFsdWVTaXplO1xuICAgICAgICAgICAgICAgICAgICBvZmZzZXREZWNpbWFsQ2hhciA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHNpZ25Ub1VzZSA9ICcnO1xuICAgICAgICBpZiAoaXNWYWx1ZU5lZ2F0aXZlKSB7XG4gICAgICAgICAgICBzaWduVG9Vc2UgPSB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcjtcbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24gJiYgIWlzWmVyb09ySGFzTm9WYWx1ZSkge1xuICAgICAgICAgICAgc2lnblRvVXNlID0gdGhpcy5zZXR0aW5ncy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXI7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwb3NpdGl2ZU5lZ2F0aXZlU2lnblNpemUgPSBzaWduVG9Vc2UubGVuZ3RoO1xuICAgICAgICBjb25zdCBjdXJyZW5jeVN5bWJvbFNpemUgPSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLmxlbmd0aDtcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIGNhcmV0IHBvc2l0aW9uIGJhc2VkIG9uIGBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudGAsIGBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudGAgYW5kIGBjYXJldFBvc2l0aW9uT25Gb2N1c2BcbiAgICAgICAgbGV0IGNhcmV0UG9zaXRpb247XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuc3RhcnQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5ub25lICYmXG4gICAgICAgICAgICAgICAgICAgIChpc1ZhbHVlTmVnYXRpdmUgfHwgKCFpc1ZhbHVlTmVnYXRpdmUgJiYgdGhpcy5zZXR0aW5ncy5zaG93UG9zaXRpdmVTaWduICYmICFpc1plcm9Pckhhc05vVmFsdWUpKSkge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg6IC8vICvigqx8MTIuMzRcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0OiAgIC8vICvigqx8MTIuMzRcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodDogIC8vIOKCrCt8MTIuMzRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gcG9zaXRpdmVOZWdhdGl2ZVNpZ25TaXplICsgY3VycmVuY3lTeW1ib2xTaXplO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeDogLy8g4oKsfDEyLjM0K1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBjdXJyZW5jeVN5bWJvbFNpemU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIOKCrHwxMi4zNFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gY3VycmVuY3lTeW1ib2xTaXplO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5jYXJldFBvc2l0aW9uT25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5lbmQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5ub25lICYmXG4gICAgICAgICAgICAgICAgICAgIChpc1ZhbHVlTmVnYXRpdmUgfHwgKCFpc1ZhbHVlTmVnYXRpdmUgJiYgdGhpcy5zZXR0aW5ncy5zaG93UG9zaXRpdmVTaWduICYmICFpc1plcm9Pckhhc05vVmFsdWUpKSkge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg6IC8vICvigqwxMi4zNHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0OiAgIC8vICvigqwxMi4zNHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodDogIC8vIOKCrCsxMi4zNHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gdG90YWxMZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4OiAvLyDigqwxMi4zNHwrXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IGN1cnJlbmN5U3ltYm9sU2l6ZSArIHZhbHVlU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8g4oKsMTIuMzR8XG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSB0b3RhbExlbmd0aDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZGVjaW1hbExlZnQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5ub25lICYmXG4gICAgICAgICAgICAgICAgICAgIChpc1ZhbHVlTmVnYXRpdmUgfHwgKCFpc1ZhbHVlTmVnYXRpdmUgJiYgdGhpcy5zZXR0aW5ncy5zaG93UG9zaXRpdmVTaWduICYmICFpc1plcm9Pckhhc05vVmFsdWUpKSkge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg6IC8vICvigqwxMnwuMzRcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0OiAgIC8vICvigqwxMnwuMzRcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodDogIC8vIOKCrCsxMnwuMzRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gcG9zaXRpdmVOZWdhdGl2ZVNpZ25TaXplICsgY3VycmVuY3lTeW1ib2xTaXplICsgaW50ZWdlclNpemU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4OiAvLyDigqwxMnwuMzQrXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IGN1cnJlbmN5U3ltYm9sU2l6ZSArIGludGVnZXJTaXplO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyDigqwxMnwuMzRcbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IGN1cnJlbmN5U3ltYm9sU2l6ZSArIGludGVnZXJTaXplO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5jYXJldFBvc2l0aW9uT25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5kZWNpbWFsUmlnaHQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5ub25lICYmXG4gICAgICAgICAgICAgICAgICAgIChpc1ZhbHVlTmVnYXRpdmUgfHwgKCFpc1ZhbHVlTmVnYXRpdmUgJiYgdGhpcy5zZXR0aW5ncy5zaG93UG9zaXRpdmVTaWduICYmICFpc1plcm9Pckhhc05vVmFsdWUpKSkge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg6IC8vICvigqwxMi58MzRcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0OiAgIC8vICvigqwxMi58MzRcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodDogIC8vIOKCrCsxMi58MzRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gcG9zaXRpdmVOZWdhdGl2ZVNpZ25TaXplICsgY3VycmVuY3lTeW1ib2xTaXplICsgaW50ZWdlclNpemUgKyBvZmZzZXREZWNpbWFsQ2hhcjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXg6IC8vIOKCrDEyLnwzNCtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gY3VycmVuY3lTeW1ib2xTaXplICsgaW50ZWdlclNpemUgKyBvZmZzZXREZWNpbWFsQ2hhcjtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8g4oKsMTIufDM0XG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBjdXJyZW5jeVN5bWJvbFNpemUgKyBpbnRlZ2VyU2l6ZSArIG9mZnNldERlY2ltYWxDaGFyO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuc3RhcnQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5ub25lICYmXG4gICAgICAgICAgICAgICAgICAgIChpc1ZhbHVlTmVnYXRpdmUgfHwgKCFpc1ZhbHVlTmVnYXRpdmUgJiYgdGhpcy5zZXR0aW5ncy5zaG93UG9zaXRpdmVTaWduICYmICFpc1plcm9Pckhhc05vVmFsdWUpKSkge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXg6IC8vIHwxMi4zNOKCrCtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodDogIC8vIHwxMi4zNOKCrCtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0OiAgIC8vIHwxMi4zNCvigqxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gMDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg6IC8vICt8MTIuMzTigqxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gcG9zaXRpdmVOZWdhdGl2ZVNpZ25TaXplO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyB8MTIuMzTigqxcbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmVuZCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Lm5vbmUgJiZcbiAgICAgICAgICAgICAgICAgICAgKGlzVmFsdWVOZWdhdGl2ZSB8fCAoIWlzVmFsdWVOZWdhdGl2ZSAmJiB0aGlzLnNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24gJiYgIWlzWmVyb09ySGFzTm9WYWx1ZSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeDogLy8gMTIuMzR84oKsK1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnJpZ2h0OiAgLy8gMTIuMzR84oKsK1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQ6ICAgLy8gMTIuMzR8K+KCrFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSB2YWx1ZVNpemU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OiAvLyArMTIuMzR84oKsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IHBvc2l0aXZlTmVnYXRpdmVTaWduU2l6ZSArIHZhbHVlU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gMTIuMzR84oKsXG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSB2YWx1ZVNpemU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmRlY2ltYWxMZWZ0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4OiAvLyAxMnwuMzTigqwrXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6ICAvLyAxMnwuMzTigqwrXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDogICAvLyAxMnwuMzQr4oKsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IGludGVnZXJTaXplO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDogLy8gKzEyfC4zNOKCrFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBwb3NpdGl2ZU5lZ2F0aXZlU2lnblNpemUgKyBpbnRlZ2VyU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gMTJ8LjM04oKsXG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBpbnRlZ2VyU2l6ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZGVjaW1hbFJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4OiAvLyAxMi58MzTigqwrXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6ICAvLyAxMi58MzTigqwrXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDogICAvLyAxMi58MzQr4oKsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IGludGVnZXJTaXplICsgb2Zmc2V0RGVjaW1hbENoYXI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OiAvLyArMTIufDM04oKsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IHBvc2l0aXZlTmVnYXRpdmVTaWduU2l6ZSArIGludGVnZXJTaXplICsgb2Zmc2V0RGVjaW1hbENoYXI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDEyLnwzNOKCrFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gaW50ZWdlclNpemUgKyBvZmZzZXREZWNpbWFsQ2hhcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gY2FyZXRQb3NpdGlvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcnVuY2F0ZSB0aGUgdHJhaWxpbmcgemVyb2VzIHRvIHRoZSBnaXZlbiBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSByb3VuZGVkSW5wdXRWYWx1ZVxuICAgICAqIEBwYXJhbSB7aW50fSBkZWNpbWFsUGxhY2VzTmVlZGVkIFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8ga2VlcFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgc3RhdGljIF90cnVuY2F0ZVplcm9zKHJvdW5kZWRJbnB1dFZhbHVlLCBkZWNpbWFsUGxhY2VzTmVlZGVkKSB7XG4gICAgICAgIGxldCByZWdleDtcbiAgICAgICAgc3dpdGNoIChkZWNpbWFsUGxhY2VzTmVlZGVkKSB7XG4gICAgICAgICAgICBjYXNlIDA6XG4gICAgICAgICAgICAgICAgLy8gUHJldmVudHMgcGFkZGluZyAtIHJlbW92ZXMgdHJhaWxpbmcgemVyb3MgdW50aWwgdGhlIGZpcnN0IHNpZ25pZmljYW50IGRpZ2l0IGlzIGVuY291bnRlcmVkXG4gICAgICAgICAgICAgICAgcmVnZXggPSAvKFxcLig/OlxcZCpbMS05XSk/KTAqJC87XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIDE6XG4gICAgICAgICAgICAgICAgLy8gQWxsb3dzIHBhZGRpbmcgd2hlbiBkZWNpbWFsUGxhY2VzTmVlZGVkIGVxdWFscyBvbmUgLSBsZWF2ZXMgb25lIHplcm8gdHJhaWxpbmcgdGhlIGRlY2ltYWwgY2hhcmFjdGVyXG4gICAgICAgICAgICAgICAgcmVnZXggPSAvKFxcLlxcZCg/OlxcZCpbMS05XSk/KTAqJC87XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmVzIHN1cGVyZmx1b3VzIHplcm9zIGFmdGVyIHRoZSBkZWNpbWFsUGxhY2VzTmVlZGVkIGxlbmd0aFxuICAgICAgICAgICAgICAgIHJlZ2V4ID0gbmV3IFJlZ0V4cChgKFxcXFwuXFxcXGR7JHtkZWNpbWFsUGxhY2VzTmVlZGVkfX0oPzpcXFxcZCpbMS05XSk/KTAqYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGVyZSBhcmUgbm8gZGVjaW1hbCBwbGFjZXMsIHdlIGRvbid0IG5lZWQgYSBkZWNpbWFsIHBvaW50IGF0IHRoZSBlbmRcbiAgICAgICAgcm91bmRlZElucHV0VmFsdWUgPSByb3VuZGVkSW5wdXRWYWx1ZS5yZXBsYWNlKHJlZ2V4LCAnJDEnKTtcbiAgICAgICAgaWYgKGRlY2ltYWxQbGFjZXNOZWVkZWQgPT09IDApIHtcbiAgICAgICAgICAgIHJvdW5kZWRJbnB1dFZhbHVlID0gcm91bmRlZElucHV0VmFsdWUucmVwbGFjZSgvXFwuJC8sICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByb3VuZGVkSW5wdXRWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSb3VuZCB0aGUgZ2l2ZW4gYHZhbHVlYCB3aXRoIHRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8ga2VlcCBmb3IgdGhlIHJhdyB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IHZhbHVlIEFuIHVuZm9ybWF0dGVkIG51bWVyaWMgdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfcm91bmRSYXdWYWx1ZSh2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JvdW5kVmFsdWUodmFsdWUsIHNldHRpbmdzLCBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJvdW5kIHRoZSBnaXZlbiBgdmFsdWVgIHdpdGggdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0byBzaG93IGZvciB0aGUgZWxlbWVudCBpcyBmb2N1c2VkLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVsbH0gdmFsdWUgQW4gdW5mb3JtYXR0ZWQgbnVtZXJpYyB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9yb3VuZEZvcm1hdHRlZFZhbHVlU2hvd25PbkZvY3VzKHZhbHVlLCBzZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gdGhpcy5fcm91bmRWYWx1ZSh2YWx1ZSwgc2V0dGluZ3MsIE51bWJlcihzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUm91bmQgdGhlIGdpdmVuIGB2YWx1ZWAgd2l0aCB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHNob3cgZm9yIHRoZSBlbGVtZW50IGlzIHVuZm9jdXNlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IHZhbHVlIEFuIHVuZm9ybWF0dGVkIG51bWVyaWMgdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfcm91bmRGb3JtYXR0ZWRWYWx1ZVNob3duT25CbHVyKHZhbHVlLCBzZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gdGhpcy5fcm91bmRWYWx1ZSh2YWx1ZSwgc2V0dGluZ3MsIE51bWJlcihzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSb3VuZCB0aGUgaW5wdXQgdmFsdWUgdXNpbmcgdGhlIHJvdW5kaW5nIG1ldGhvZCBkZWZpbmVkIGluIHRoZSBzZXR0aW5ncy5cbiAgICAgKiBUaGlzIGZ1bmN0aW9uIGFjY2VwdHMgbXVsdGlwbGUgcm91bmRpbmcgbWV0aG9kcy4gU2VlIHRoZSBkb2N1bWVudGF0aW9uIGZvciBtb3JlIGRldGFpbHMgYWJvdXQgdGhvc2UuXG4gICAgICpcbiAgICAgKiBOb3RlIDogVGhpcyBpcyBoYW5kbGVkIGFzIHRleHQgc2luY2UgSmF2YVNjcmlwdCBtYXRoIGZ1bmN0aW9ucyBjYW4gcmV0dXJuIGluYWNjdXJhdGUgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVsbH0gaW5wdXRWYWx1ZSBBbiB1bmZvcm1hdHRlZCBudW1lcmljIHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHBhcmFtIHtpbnR9IGRlY2ltYWxQbGFjZXNUb1JvdW5kVG9cbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgX3JvdW5kVmFsdWUoaW5wdXRWYWx1ZSwgc2V0dGluZ3MsIGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8pIHtcbiAgICAgICAgLy9YWFggTm90ZTsgdGhpcyBmdW5jdGlvbiBpcyBzdGF0aWMgc2luY2Ugd2UgbmVlZCB0byBwYXNzIGEgYHNldHRpbmdzYCBvYmplY3Qgd2hlbiBjYWxsaW5nIHRoZSBzdGF0aWMgYEF1dG9OdW1lcmljLmZvcm1hdCgpYCBtZXRob2RcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChpbnB1dFZhbHVlKSkge1xuICAgICAgICAgICAgLy8gUHJldmVudCByb3VuZGluZyBhIGBudWxsYCB2YWx1ZVxuICAgICAgICAgICAgcmV0dXJuIGlucHV0VmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICAvL1RPRE8gRGl2aWRlIHRoaXMgZnVuY3Rpb24gdG8gbWFrZSBpdCBlYXNpZXIgdG8gdW5kZXJzdGFuZFxuICAgICAgICBpbnB1dFZhbHVlID0gKGlucHV0VmFsdWUgPT09ICcnKSA/ICcwJyA6IGlucHV0VmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgaWYgKHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnRvTmVhcmVzdDA1IHx8XG4gICAgICAgICAgICBzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC50b05lYXJlc3QwNUFsdCB8fFxuICAgICAgICAgICAgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QudXBUb05leHQwNSB8fFxuICAgICAgICAgICAgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuZG93blRvTmV4dDA1KSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fcm91bmRDbG9zZVRvMDUoaW5wdXRWYWx1ZSwgc2V0dGluZ3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgW25lZ2F0aXZlU2lnbiwgcHJlcGFyZWRWYWx1ZV0gPSBBdXRvTnVtZXJpYy5fcHJlcGFyZVZhbHVlRm9yUm91bmRpbmcoaW5wdXRWYWx1ZSwgc2V0dGluZ3MpO1xuICAgICAgICBpbnB1dFZhbHVlID0gcHJlcGFyZWRWYWx1ZTtcblxuICAgICAgICBjb25zdCBkZWNpbWFsQ2hhcmFjdGVyUG9zaXRpb24gPSBpbnB1dFZhbHVlLmxhc3RJbmRleE9mKCcuJyk7XG4gICAgICAgIGNvbnN0IGlucHV0VmFsdWVIYXNOb0RvdCA9IGRlY2ltYWxDaGFyYWN0ZXJQb3NpdGlvbiA9PT0gLTE7IC8vIE5vIGRvdCBjaGFyYWN0ZXIgaXMgZm91bmQgaW4gdGhlIGBpbnB1dFZhbHVlYFxuICAgICAgICBjb25zdCBbLCBkZWNpbWFsUGFydF0gPSBpbnB1dFZhbHVlLnNwbGl0KCcuJyk7IC8vIEhlcmUgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGlzIGFsd2F5cyBhIHBlcmlvZCAnLidcbiAgICAgICAgY29uc3QgaGFzRGVjaW1hbHMgPSBkZWNpbWFsUGFydCA+IDA7XG5cbiAgICAgICAgLy8gSWYgbm8gZGVjaW1hbHMgYXJlIGRldGVjdGVkXG4gICAgICAgIGlmICghaGFzRGVjaW1hbHMgJiZcbiAgICAgICAgICAgIChzZXR0aW5ncy5hbGxvd0RlY2ltYWxQYWRkaW5nID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcubmV2ZXIgfHxcbiAgICAgICAgICAgIHNldHRpbmdzLmFsbG93RGVjaW1hbFBhZGRpbmcgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZy5mbG9hdHMpKSB7XG4gICAgICAgICAgICByZXR1cm4gKE51bWJlcihpbnB1dFZhbHVlKSA9PT0gMCkgPyBpbnB1dFZhbHVlIDogYCR7bmVnYXRpdmVTaWdufSR7aW5wdXRWYWx1ZX1gO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRWxzZSB0aGVyZSBhcmUgc29tZSBkZWNpbWFsIHBsYWNlcyB0aGF0IG1heSBuZWVkIHRvIGJlIHJvdW5kZWRcbiAgICAgICAgLy8gU2V0cyB0aGUgdHJ1bmNhdGUgemVybyBtZXRob2RcbiAgICAgICAgbGV0IHRlbXBvcmFyeURlY2ltYWxQbGFjZXNPdmVycmlkZTtcbiAgICAgICAgaWYgKHNldHRpbmdzLmFsbG93RGVjaW1hbFBhZGRpbmcgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZy5hbHdheXMgfHxcbiAgICAgICAgICAgIHNldHRpbmdzLmFsbG93RGVjaW1hbFBhZGRpbmcgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZy5mbG9hdHMpIHtcbiAgICAgICAgICAgIHRlbXBvcmFyeURlY2ltYWxQbGFjZXNPdmVycmlkZSA9IGRlY2ltYWxQbGFjZXNUb1JvdW5kVG87XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0ZW1wb3JhcnlEZWNpbWFsUGxhY2VzT3ZlcnJpZGUgPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGVmaW5lIHRoZSBkZWNpbWFsIHBvc2l0aW9uIHRvIHVzZSAodXNlIHRoZSB2ZXJ5IGxhc3QgcG9zaXRpb24gaWYgdGhlcmUgYXJlIG5vIGRvdCBpbiB0aGUgaW5pdGlhbCBpbnB1dFZhbHVlKVxuICAgICAgICBjb25zdCBkZWNpbWFsUG9zaXRpb25Ub1VzZSA9IGlucHV0VmFsdWVIYXNOb0RvdCA/IGlucHV0VmFsdWUubGVuZ3RoIC0gMSA6IGRlY2ltYWxDaGFyYWN0ZXJQb3NpdGlvbjtcbiAgICAgICAgLy8gQ2hlY2tzIGRlY2ltYWwgcGxhY2VzIHRvIGRldGVybWluZSBpZiByb3VuZGluZyBpcyByZXF1aXJlZFxuICAgICAgICBsZXQgY2hlY2tEZWNpbWFsUGxhY2VzID0gKGlucHV0VmFsdWUubGVuZ3RoIC0gMSkgLSBkZWNpbWFsUG9zaXRpb25Ub1VzZTtcbiAgICAgICAgbGV0IGlucHV0VmFsdWVSb3VuZGVkID0gJyc7XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgbm8gcm91bmRpbmcgaXMgcmVxdWlyZWRcbiAgICAgICAgaWYgKGNoZWNrRGVjaW1hbFBsYWNlcyA8PSBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvKSB7XG4gICAgICAgICAgICAvLyBDaGVjayBpZiB3ZSBuZWVkIHRvIHBhZCB3aXRoIHplcm9zXG4gICAgICAgICAgICBpbnB1dFZhbHVlUm91bmRlZCA9IGlucHV0VmFsdWU7XG4gICAgICAgICAgICBpZiAoY2hlY2tEZWNpbWFsUGxhY2VzIDwgdGVtcG9yYXJ5RGVjaW1hbFBsYWNlc092ZXJyaWRlKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlucHV0VmFsdWVIYXNOb0RvdCkge1xuICAgICAgICAgICAgICAgICAgICBpbnB1dFZhbHVlUm91bmRlZCA9IGAke2lucHV0VmFsdWVSb3VuZGVkfSR7c2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcn1gO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxldCB6ZXJvcyA9ICcwMDAwMDAnOyAvL1RPRE8gQ2hhbmdlIHRoYXQgc3RyaW5nIHdpdGggYSBsb25nZXIgb25lIHRvIHByZXZlbnQgaGF2aW5nIHRvIGxvb3AgbnVtZXJvdXMgdGltZXMgaW4gdGhlIG5leHQgYHdoaWxlYCBzdGF0ZW1lbnQ/XG4gICAgICAgICAgICAgICAgd2hpbGUgKGNoZWNrRGVjaW1hbFBsYWNlcyA8IHRlbXBvcmFyeURlY2ltYWxQbGFjZXNPdmVycmlkZSkge1xuICAgICAgICAgICAgICAgICAgICB6ZXJvcyA9IHplcm9zLnN1YnN0cmluZygwLCB0ZW1wb3JhcnlEZWNpbWFsUGxhY2VzT3ZlcnJpZGUgLSBjaGVja0RlY2ltYWxQbGFjZXMpO1xuICAgICAgICAgICAgICAgICAgICBpbnB1dFZhbHVlUm91bmRlZCArPSB6ZXJvcztcbiAgICAgICAgICAgICAgICAgICAgY2hlY2tEZWNpbWFsUGxhY2VzICs9IHplcm9zLmxlbmd0aDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNoZWNrRGVjaW1hbFBsYWNlcyA+IHRlbXBvcmFyeURlY2ltYWxQbGFjZXNPdmVycmlkZSkge1xuICAgICAgICAgICAgICAgIGlucHV0VmFsdWVSb3VuZGVkID0gdGhpcy5fdHJ1bmNhdGVaZXJvcyhpbnB1dFZhbHVlUm91bmRlZCwgdGVtcG9yYXJ5RGVjaW1hbFBsYWNlc092ZXJyaWRlKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoY2hlY2tEZWNpbWFsUGxhY2VzID09PSAwICYmIHRlbXBvcmFyeURlY2ltYWxQbGFjZXNPdmVycmlkZSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIFJlbW92ZSBhbnkgdHJhaWxpbmcgZG90LCBpZiBhbnlcbiAgICAgICAgICAgICAgICBpbnB1dFZhbHVlUm91bmRlZCA9IGlucHV0VmFsdWVSb3VuZGVkLnJlcGxhY2UoL1xcLiQvLCAnJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiAoTnVtYmVyKGlucHV0VmFsdWVSb3VuZGVkKSA9PT0gMCkgPyBpbnB1dFZhbHVlUm91bmRlZCA6IGAke25lZ2F0aXZlU2lnbn0ke2lucHV0VmFsdWVSb3VuZGVkfWA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSb3VuZGVkIGxlbmd0aCBvZiB0aGUgc3RyaW5nIGFmdGVyIHJvdW5kaW5nXG4gICAgICAgIGxldCByb3VuZGVkU3RyTGVuZ3RoO1xuICAgICAgICBpZiAoaW5wdXRWYWx1ZUhhc05vRG90KSB7XG4gICAgICAgICAgICByb3VuZGVkU3RyTGVuZ3RoID0gZGVjaW1hbFBsYWNlc1RvUm91bmRUbyAtIDE7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByb3VuZGVkU3RyTGVuZ3RoID0gTnVtYmVyKGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8pICsgTnVtYmVyKGRlY2ltYWxDaGFyYWN0ZXJQb3NpdGlvbik7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBsYXN0RGlnaXQgPSBOdW1iZXIoaW5wdXRWYWx1ZS5jaGFyQXQocm91bmRlZFN0ckxlbmd0aCArIDEpKTtcbiAgICAgICAgbGV0IGlucHV0VmFsdWVBcnJheSA9IGlucHV0VmFsdWUuc3Vic3RyaW5nKDAsIHJvdW5kZWRTdHJMZW5ndGggKyAxKS5zcGxpdCgnJyk7XG4gICAgICAgIGxldCBvZGQ7XG4gICAgICAgIGlmIChpbnB1dFZhbHVlLmNoYXJBdChyb3VuZGVkU3RyTGVuZ3RoKSA9PT0gJy4nKSB7XG4gICAgICAgICAgICBvZGQgPSBpbnB1dFZhbHVlLmNoYXJBdChyb3VuZGVkU3RyTGVuZ3RoIC0gMSkgJSAyO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb2RkID0gaW5wdXRWYWx1ZS5jaGFyQXQocm91bmRlZFN0ckxlbmd0aCkgJSAyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX3Nob3VsZFJvdW5kVXAobGFzdERpZ2l0LCBzZXR0aW5ncywgbmVnYXRpdmVTaWduLCBvZGQpKSB7XG4gICAgICAgICAgICAvLyBSb3VuZCB1cCB0aGUgbGFzdCBkaWdpdCBpZiByZXF1aXJlZCwgYW5kIGNvbnRpbnVlIHVudGlsIG5vIG1vcmUgOSdzIGFyZSBmb3VuZFxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IChpbnB1dFZhbHVlQXJyYXkubGVuZ3RoIC0gMSk7IGkgPj0gMDsgaSAtPSAxKSB7XG4gICAgICAgICAgICAgICAgaWYgKGlucHV0VmFsdWVBcnJheVtpXSAhPT0gJy4nKSB7XG4gICAgICAgICAgICAgICAgICAgIGlucHV0VmFsdWVBcnJheVtpXSA9ICtpbnB1dFZhbHVlQXJyYXlbaV0gKyAxO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaW5wdXRWYWx1ZUFycmF5W2ldIDwgMTApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGkgPiAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpbnB1dFZhbHVlQXJyYXlbaV0gPSAnMCc7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZWNvbnN0cnVjdCB0aGUgc3RyaW5nLCBjb252ZXJ0aW5nIGFueSAxMCdzIHRvIDAnc1xuICAgICAgICBpbnB1dFZhbHVlQXJyYXkgPSBpbnB1dFZhbHVlQXJyYXkuc2xpY2UoMCwgcm91bmRlZFN0ckxlbmd0aCArIDEpO1xuXG4gICAgICAgIC8vIFJldHVybiB0aGUgcm91bmRlZCB2YWx1ZVxuICAgICAgICBpbnB1dFZhbHVlUm91bmRlZCA9IHRoaXMuX3RydW5jYXRlWmVyb3MoaW5wdXRWYWx1ZUFycmF5LmpvaW4oJycpLCB0ZW1wb3JhcnlEZWNpbWFsUGxhY2VzT3ZlcnJpZGUpO1xuXG4gICAgICAgIHJldHVybiAoTnVtYmVyKGlucHV0VmFsdWVSb3VuZGVkKSA9PT0gMCkgPyBpbnB1dFZhbHVlUm91bmRlZCA6IGAke25lZ2F0aXZlU2lnbn0ke2lucHV0VmFsdWVSb3VuZGVkfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUm91bmQgdGhlIGB2YWx1ZWAgd2hlbiB0aGUgcm91bmRpbmcgbWV0aG9kIGRlYWxzIHdpdGggJy4wNSdcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3JvdW5kQ2xvc2VUbzA1KHZhbHVlLCBzZXR0aW5ncykge1xuICAgICAgICBzd2l0Y2ggKHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kKSB7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QudG9OZWFyZXN0MDU6XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QudG9OZWFyZXN0MDVBbHQ6XG4gICAgICAgICAgICAgICAgdmFsdWUgPSAoTWF0aC5yb3VuZCh2YWx1ZSAqIDIwKSAvIDIwKS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnVwVG9OZXh0MDU6XG4gICAgICAgICAgICAgICAgdmFsdWUgPSAoTWF0aC5jZWlsKHZhbHVlICogMjApIC8gMjApLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IChNYXRoLmZsb29yKHZhbHVlICogMjApIC8gMjApLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKHZhbHVlLCAnLicpKSB7XG4gICAgICAgICAgICByZXN1bHQgPSB2YWx1ZSArICcuMDAnO1xuICAgICAgICB9IGVsc2UgaWYgKHZhbHVlLmxlbmd0aCAtIHZhbHVlLmluZGV4T2YoJy4nKSA8IDMpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlICsgJzAnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1vZGlmeSB0aGUgZ2l2ZW4gYHZhbHVlYCBpbiBvcmRlciB0byBtYWtlIGl0IHVzYWJsZSBmb3IgdGhlIHJlc3Qgb2YgdGhlIHJvdW5kaW5nIGZ1bmN0aW9uLlxuICAgICAqIFRoaXMgY29udmVydCB0aGUgYHZhbHVlYCB0byBhIHBvc2l0aXZlIG9uZSwgdHJpbSBhbnkgbGVhZGluZyB6ZXJvcyBhbmQgbWFrZSBzdXJlIGl0IGRvZXMgbm90IHN0YXJ0cyB3aXRoIGEgbGVhZGluZyBkb3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWUgVGhlIHVuZm9ybWF0dGVkIHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMge1tzdHJpbmcsIHN0cmluZ119XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3ByZXBhcmVWYWx1ZUZvclJvdW5kaW5nKHZhbHVlLCBzZXR0aW5ncykge1xuICAgICAgICAvLyBDaGVja3MgaWYgYGlucHV0VmFsdWVgIGlzIGEgbmVnYXRpdmUgdmFsdWVcbiAgICAgICAgbGV0IG5lZ2F0aXZlU2lnbiA9ICcnO1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZVN0cmljdCh2YWx1ZSwgJy0nKSkgeyAvLyBUaGUgdmFsdWUgYmVpbmcgdW5mb3JtYXR0ZWQsIHdlIGNoZWNrIGZvciB0aGUgbWludXMgc2lnblxuICAgICAgICAgICAgbmVnYXRpdmVTaWduID0gJy0nO1xuXG4gICAgICAgICAgICAvLyBSZW1vdmVzIHRoZSBuZWdhdGl2ZSBzaWduIHRoYXQgd2lsbCBiZSBhZGRlZCBiYWNrIGxhdGVyIGlmIHJlcXVpcmVkXG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoJy0nLCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBcHBlbmQgYSB6ZXJvIGlmIHRoZSBmaXJzdCBjaGFyYWN0ZXIgaXMgbm90IGEgZGlnaXQgKHRoZW4gaXQgaXMgbGlrZWx5IGEgZG90KVxuICAgICAgICBpZiAoIXZhbHVlLm1hdGNoKC9eXFxkLykpIHtcbiAgICAgICAgICAgIHZhbHVlID0gYDAke3ZhbHVlfWA7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZXRlcm1pbmVzIGlmIHRoZSB2YWx1ZSBpcyBlcXVhbCB0byB6ZXJvLiBJZiBpdCBpcywgcmVtb3ZlIHRoZSBuZWdhdGl2ZSBzaWduXG4gICAgICAgIGlmIChOdW1iZXIodmFsdWUpID09PSAwKSB7XG4gICAgICAgICAgICBuZWdhdGl2ZVNpZ24gPSAnJztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRyaW1zIGxlYWRpbmcgemVybydzIGFzIG5lZWRlZFxuICAgICAgICBpZiAoKE51bWJlcih2YWx1ZSkgPiAwICYmIHNldHRpbmdzLmxlYWRpbmdaZXJvICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmtlZXApIHx8XG4gICAgICAgICAgICAodmFsdWUubGVuZ3RoID4gMCAmJiBzZXR0aW5ncy5sZWFkaW5nWmVybyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5hbGxvdykpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWUucmVwbGFjZSgvXjAqKFxcZCkvLCAnJDEnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBbbmVnYXRpdmVTaWduLCB2YWx1ZV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiBhIHJvdW5kIHVwIHNob3VsZCBiZSBkb25lIGdpdmVuIHRoZSBsYXN0IGRpZ2l0LCB0aGUgc2V0dGluZ3MgYW5kIG90aGVyIGluZm9ybWF0aW9uIGFib3V0IHRoZSB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBsYXN0RGlnaXRcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmVnYXRpdmVTaWduIFRoaXMgdmFyaWFibGUgY29tZXMgZnJvbSBgX3ByZXBhcmVWYWx1ZUZvclJvdW5kaW5nKClgLCB3aGljaCByZXR1cm4gYCctJ2AgaWYgdGhlIGluaXRpYWwgdmFsdWUgd2FzIG5lZ2F0aXZlXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG9kZFxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9zaG91bGRSb3VuZFVwKGxhc3REaWdpdCwgc2V0dGluZ3MsIG5lZ2F0aXZlU2lnbiwgb2RkKSB7XG4gICAgICAgIHJldHVybiAobGFzdERpZ2l0ID4gNCAmJiBzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC5oYWxmVXBTeW1tZXRyaWMpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHx8IC8vIFJvdW5kIGhhbGYgdXAgc3ltbWV0cmljXG4gICAgICAgICAgICAobGFzdERpZ2l0ID4gNCAmJiBzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC5oYWxmVXBBc3ltbWV0cmljICYmIG5lZ2F0aXZlU2lnbiA9PT0gJycpICAgICAgICAgICAgICAgIHx8IC8vIFJvdW5kIGhhbGYgdXAgYXN5bW1ldHJpYyBwb3NpdGl2ZSB2YWx1ZXNcbiAgICAgICAgICAgIChsYXN0RGlnaXQgPiA1ICYmIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZVcEFzeW1tZXRyaWMgJiYgbmVnYXRpdmVTaWduID09PSAnLScpICAgICAgICAgICAgICAgfHwgLy8gUm91bmQgaGFsZiB1cCBhc3ltbWV0cmljIG5lZ2F0aXZlIHZhbHVlc1xuICAgICAgICAgICAgKGxhc3REaWdpdCA+IDUgJiYgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZkRvd25TeW1tZXRyaWMpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fCAvLyBSb3VuZCBoYWxmIGRvd24gc3ltbWV0cmljXG4gICAgICAgICAgICAobGFzdERpZ2l0ID4gNSAmJiBzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC5oYWxmRG93bkFzeW1tZXRyaWMgJiYgbmVnYXRpdmVTaWduID09PSAnJykgICAgICAgICAgICAgIHx8IC8vIFJvdW5kIGhhbGYgZG93biBhc3ltbWV0cmljIHBvc2l0aXZlIHZhbHVlc1xuICAgICAgICAgICAgKGxhc3REaWdpdCA+IDQgJiYgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZkRvd25Bc3ltbWV0cmljICYmIG5lZ2F0aXZlU2lnbiA9PT0gJy0nKSAgICAgICAgICAgICB8fCAvLyBSb3VuZCBoYWxmIGRvd24gYXN5bW1ldHJpYyBuZWdhdGl2ZSB2YWx1ZXNcbiAgICAgICAgICAgIChsYXN0RGlnaXQgPiA1ICYmIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZFdmVuQmFua2Vyc1JvdW5kaW5nKSAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfHxcbiAgICAgICAgICAgIChsYXN0RGlnaXQgPT09IDUgJiYgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZkV2ZW5CYW5rZXJzUm91bmRpbmcgJiYgb2RkID09PSAxKSAgICAgICAgICAgICAgICAgfHxcbiAgICAgICAgICAgIChsYXN0RGlnaXQgPiAwICYmIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnRvQ2VpbGluZ1Rvd2FyZFBvc2l0aXZlSW5maW5pdHkgJiYgbmVnYXRpdmVTaWduID09PSAnJykgfHxcbiAgICAgICAgICAgIChsYXN0RGlnaXQgPiAwICYmIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnRvRmxvb3JUb3dhcmROZWdhdGl2ZUluZmluaXR5ICYmIG5lZ2F0aXZlU2lnbiA9PT0gJy0nKSAgfHxcbiAgICAgICAgICAgIChsYXN0RGlnaXQgPiAwICYmIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnVwUm91bmRBd2F5RnJvbVplcm8pOyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUm91bmQgdXAgYXdheSBmcm9tIHplcm9cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUcnVuY2F0ZXMgdGhlIGRlY2ltYWwgcGFydCBvZiBhIG51bWJlciB0byB0aGUgZ2l2ZW4gbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNQYXN0ZVxuICAgICAqIEBwYXJhbSB7aW50fSBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIF90cnVuY2F0ZURlY2ltYWxQbGFjZXModmFsdWUsIHNldHRpbmdzLCBpc1Bhc3RlLCBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvKSB7XG4gICAgICAgIGlmIChpc1Bhc3RlKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHRoaXMuX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uRm9jdXModmFsdWUsIHNldHRpbmdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IFtpbnRlZ2VyUGFydCwgZGVjaW1hbFBhcnRdID0gdmFsdWUuc3BsaXQoc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcik7XG5cbiAgICAgICAgLy8gVHJ1bmNhdGUgdGhlIGRlY2ltYWwgcGFydCB0byB0aGUgc2F0aXNmeWluZyBsZW5ndGggc2luY2Ugd2Ugd291bGQgcm91bmQgaXQgYW55d2F5XG4gICAgICAgIGlmIChkZWNpbWFsUGFydCAmJiBkZWNpbWFsUGFydC5sZW5ndGggPiBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvKSB7XG4gICAgICAgICAgICBpZiAoZGVjaW1hbFBsYWNlc1RvUm91bmRUbyA+IDApIHtcbiAgICAgICAgICAgICAgICBjb25zdCBtb2RpZmllZERlY2ltYWxQYXJ0ID0gZGVjaW1hbFBhcnQuc3Vic3RyaW5nKDAsIGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8pO1xuICAgICAgICAgICAgICAgIHZhbHVlID0gYCR7aW50ZWdlclBhcnR9JHtzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyfSR7bW9kaWZpZWREZWNpbWFsUGFydH1gO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IGludGVnZXJQYXJ0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIHRoYXQgdGhlIG51bWJlciBzYXRpc2Z5IHRoZSBmb3JtYXQgY29uZGl0aW9uc1xuICAgICAqIGFuZCBsYXlzIGJldHdlZW4gc2V0dGluZ3MubWluaW11bVZhbHVlIGFuZCBzZXR0aW5ncy5tYXhpbXVtVmFsdWVcbiAgICAgKiBhbmQgdGhlIHN0cmluZyBsZW5ndGggZG9lcyBub3QgZXhjZWVkIHRoZSBkaWdpdHMgaW4gc2V0dGluZ3MubWluaW11bVZhbHVlIGFuZCBzZXR0aW5ncy5tYXhpbXVtVmFsdWVcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBfY2hlY2tJZkluUmFuZ2VXaXRoT3ZlcnJpZGVPcHRpb24odmFsdWUsIHNldHRpbmdzKSB7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodmFsdWUpICYmIHNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvciA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubnVsbCkge1xuICAgICAgICAgICAgLy8gV2hlbiB0aGUgYG51bGxgIHZhbHVlIGlzIGFjY2VwdGVkIGFzIHRoZSBgcmF3VmFsdWVgLCB0aGUgbGltaXRzIGFyZSBpZ25vcmVkXG4gICAgICAgICAgICByZXR1cm4gW3RydWUsIHRydWVdO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFsdWUgPSB2YWx1ZS50b1N0cmluZygpO1xuICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoJywnLCAnLicpO1xuICAgICAgICBjb25zdCBtaW5QYXJzZSA9IEF1dG9OdW1lcmljSGVscGVyLnBhcnNlU3RyKHNldHRpbmdzLm1pbmltdW1WYWx1ZSk7XG4gICAgICAgIGNvbnN0IG1heFBhcnNlID0gQXV0b051bWVyaWNIZWxwZXIucGFyc2VTdHIoc2V0dGluZ3MubWF4aW11bVZhbHVlKTtcbiAgICAgICAgY29uc3QgdmFsUGFyc2UgPSBBdXRvTnVtZXJpY0hlbHBlci5wYXJzZVN0cih2YWx1ZSk7XG5cbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgc3dpdGNoIChzZXR0aW5ncy5vdmVycmlkZU1pbk1heExpbWl0cykge1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm92ZXJyaWRlTWluTWF4TGltaXRzLmZsb29yOlxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IFtBdXRvTnVtZXJpY0hlbHBlci50ZXN0TWluTWF4KG1pblBhcnNlLCB2YWxQYXJzZSkgPiAtMSwgdHJ1ZV07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMuY2VpbGluZzpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBbdHJ1ZSwgQXV0b051bWVyaWNIZWxwZXIudGVzdE1pbk1heChtYXhQYXJzZSwgdmFsUGFyc2UpIDwgMV07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMuaWdub3JlOlxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IFt0cnVlLCB0cnVlXTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gW0F1dG9OdW1lcmljSGVscGVyLnRlc3RNaW5NYXgobWluUGFyc2UsIHZhbFBhcnNlKSA+IC0xLCBBdXRvTnVtZXJpY0hlbHBlci50ZXN0TWluTWF4KG1heFBhcnNlLCB2YWxQYXJzZSkgPCAxXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT3JpZ2luYWwgc2V0dGluZ3Mgc2F2ZWQgZm9yIHVzZSB3aGVuIHRoZSBgZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1c2AgYW5kIGBzaG93T25seU51bWJlcnNPbkZvY3VzYCBvcHRpb25zIGFyZSB1c2VkLlxuICAgICAqIFRob3NlIG9yaWdpbmFsIHNldHRpbmdzIGFyZSB1c2VkIGV4Y2x1c2l2ZWx5IGluIHRoZSBgZm9jdXNpbmAgYW5kIGBmb2N1c291dGAgZXZlbnQgaGFuZGxlcnMuXG4gICAgICovXG4gICAgX2tlZXBBbk9yaWdpbmFsU2V0dGluZ3NDb3B5KCkge1xuICAgICAgICB0aGlzLm9yaWdpbmFsRGlnaXRHcm91cFNlcGFyYXRvciA9IHRoaXMuc2V0dGluZ3MuZGlnaXRHcm91cFNlcGFyYXRvcjtcbiAgICAgICAgdGhpcy5vcmlnaW5hbEN1cnJlbmN5U3ltYm9sICAgICAgPSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sO1xuICAgICAgICB0aGlzLm9yaWdpbmFsU3VmZml4VGV4dCAgICAgICAgICA9IHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBPcmlnaW5hbCBzZXR0aW5ncyBzYXZlZCBmb3IgdXNlIHdoZW4gYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNgICYgYHNob3dPbmx5TnVtYmVyc09uRm9jdXNgIG9wdGlvbnMgYXJlIGJlaW5nIHVzZWQuXG4gICAgICogVGhpcyBpcyB0YWtlbiBmcm9tIFF1aXJrc21vZGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBfcmVhZENvb2tpZShuYW1lKSB7XG4gICAgICAgIGNvbnN0IG5hbWVFUSA9IG5hbWUgKyAnPSc7XG4gICAgICAgIGNvbnN0IGNhID0gZG9jdW1lbnQuY29va2llLnNwbGl0KCc7Jyk7XG4gICAgICAgIGxldCBjID0gJyc7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2EubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGMgPSBjYVtpXTtcbiAgICAgICAgICAgIHdoaWxlIChjLmNoYXJBdCgwKSA9PT0gJyAnKSB7XG4gICAgICAgICAgICAgICAgYyA9IGMuc3Vic3RyaW5nKDEsIGMubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjLmluZGV4T2YobmFtZUVRKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjLnN1YnN0cmluZyhuYW1lRVEubGVuZ3RoLCBjLmxlbmd0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUZXN0IGlmIHNlc3Npb25TdG9yYWdlIGlzIHN1cHBvcnRlZC5cbiAgICAgKiBUaGlzIGlzIHRha2VuIGZyb20gTW9kZXJuaXpyLlxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIF9zdG9yYWdlVGVzdCgpIHtcbiAgICAgICAgY29uc3QgbW9kID0gJ21vZGVybml6cic7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBzZXNzaW9uU3RvcmFnZS5zZXRJdGVtKG1vZCwgbW9kKTtcbiAgICAgICAgICAgIHNlc3Npb25TdG9yYWdlLnJlbW92ZUl0ZW0obW9kKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFueSB6ZXJvcyBpbiBleGNlc3MgaW4gdGhlIGZyb250IGFuZCBiYWNrIG9mIHRoZSBnaXZlbiBgdmFsdWVgLCBhY2NvcmRpbmcgdG8gdGhlIGBzZXR0aW5nc2AuXG4gICAgICogVGhpcyBhbHNvIG1hbmFnZXMgdGhlIGNhc2VzIHdoZXJlIHRoZSBkZWNpbWFsIHBvaW50IGlzIG9uIHRoZSBmYXIgbGVmdCBvciBmYXIgcmlnaHQgb2YgdGhlIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gICAgICovXG4gICAgX3RyaW1MZWFkaW5nQW5kVHJhaWxpbmdaZXJvcyh2YWx1ZSkge1xuICAgICAgICAvLyBSZXR1cm4gdGhlIGVtcHR5IHN0cmluZyBpcyB0aGUgdmFsdWUgaXMgYWxyZWFkeSBlbXB0eS4gVGhpcyBwcmV2ZW50IGNvbnZlcnRpbmcgdGhhdCB2YWx1ZSB0byAnMCcuXG4gICAgICAgIGlmICh2YWx1ZSA9PT0gJycgfHwgdmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmxlYWRpbmdaZXJvICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmtlZXApIHtcbiAgICAgICAgICAgIGlmIChOdW1iZXIodmFsdWUpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gUmV0dXJuICcwJyBpZiB0aGUgdmFsdWUgaXMgemVyb1xuICAgICAgICAgICAgICAgIHJldHVybiAnMCc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFRyaW0gdGhlIGxlYWRpbmcgemVyb3MsIHdoaWxlIGxlYXZpbmcgb25lIHplcm8gdG8gdGhlIGxlZnQgb2YgdGhlIGRlY2ltYWwgcG9pbnQgaWYgbmVlZGVkXG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoL14oLSk/MCsoPz1cXGQpL2csJyQxJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvL1RPRE8gcmVtb3ZlIHRoaXMgZnJvbSB0aGF0IGZ1bmN0aW9uIGFuZCB1c2UgYHRyaW1QYWRkZWRaZXJvc0Zyb21EZWNpbWFsUGxhY2VzKClgIGluc3RlYWRcbiAgICAgICAgLy8gVHJpbSB0aGUgdHJhaWxpbmcgemVyb3MgYWZ0ZXIgdGhlIGxhc3QgZGVjaW1hbCBwbGFjZSBub3QgYmVpbmcgYSB6ZXJvIChpZS4gMS4yMzAwIC0+IDEuMjMpXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyh2YWx1ZSwgJy4nKSkge1xuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKC8oXFwuWzAtOV0qPykwKyQvLCAnJDEnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlbW92ZSBhbnkgdHJhaWxpbmcgZGVjaW1hbCBwb2ludFxuICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoL1xcLiQvLCAnJyk7XG5cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIHRoZSBuYW1lIGZvciB0aGUgcGVyc2lzdGVudCBzdG9yZWQgZGF0YSB2YXJpYWJsZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NldFBlcnNpc3RlbnRTdG9yYWdlTmFtZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZG9tRWxlbWVudC5uYW1lICE9PSAnJyAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQodGhpcy5kb21FbGVtZW50Lm5hbWUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yYXdWYWx1ZVN0b3JhZ2VOYW1lID0gYCR7dGhpcy5zdG9yYWdlTmFtZVByZWZpeH0ke2RlY29kZVVSSUNvbXBvbmVudCh0aGlzLmRvbUVsZW1lbnQubmFtZSl9YDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yYXdWYWx1ZVN0b3JhZ2VOYW1lID0gYCR7dGhpcy5zdG9yYWdlTmFtZVByZWZpeH0ke3RoaXMuZG9tRWxlbWVudC5pZH1gO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2F2ZSB0aGUgcmF3IFZhbHVlIGludG8gc2Vzc2lvblN0b3JhZ2Ugb3IgYSBjb29raWUgZGVwZW5kaW5nIG9uIHdoYXQgdGhlIGJyb3dzZXIgaXMgc3VwcG9ydGluZy5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zYXZlVmFsdWVUb1BlcnNpc3RlbnRTdG9yYWdlKCkge1xuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5zYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXNzaW9uU3RvcmFnZUF2YWlsYWJsZSkge1xuICAgICAgICAgICAgICAgIHNlc3Npb25TdG9yYWdlLnNldEl0ZW0odGhpcy5yYXdWYWx1ZVN0b3JhZ2VOYW1lLCB0aGlzLnJhd1ZhbHVlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gVXNlIGNvb2tpZXMgZm9yIG9ic29sZXRlIGJyb3dzZXJzIHRoYXQgZG8gbm90IHN1cHBvcnQgc2Vzc2lvblN0b3JhZ2UgKGllLiBJRSA2ICYgNylcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5jb29raWUgPSBgJHt0aGlzLnJhd1ZhbHVlU3RvcmFnZU5hbWV9PSR7dGhpcy5yYXdWYWx1ZX07IGV4cGlyZXM9IDsgcGF0aD0vYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlIHRoZSByYXcgdmFsdWUgZnJvbSBzZXNzaW9uU3RvcmFnZSBvciB0aGUgY29va2llIGRlcGVuZGluZyBvbiB3aGF0IHRoZSBicm93c2VyIGlzIHN1cHBvcnRpbmcuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9nZXRWYWx1ZUZyb21QZXJzaXN0ZW50U3RvcmFnZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSkge1xuICAgICAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgICAgIGlmICh0aGlzLnNlc3Npb25TdG9yYWdlQXZhaWxhYmxlKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gc2Vzc2lvblN0b3JhZ2UuZ2V0SXRlbSh0aGlzLnJhd1ZhbHVlU3RvcmFnZU5hbWUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLl9yZWFkQ29va2llKHRoaXMucmF3VmFsdWVTdG9yYWdlTmFtZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKCdgX2dldFZhbHVlRnJvbVBlcnNpc3RlbnRTdG9yYWdlKClgIGlzIGNhbGxlZCBidXQgYHNldHRpbmdzLnNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2VgIGlzIGZhbHNlLiBUaGVyZSBtdXN0IGJlIGFuIGVycm9yIHRoYXQgbmVlZHMgZml4aW5nLicsIHRoaXMuc2V0dGluZ3Muc2hvd1dhcm5pbmdzKTtcblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIHJhdyB2YWx1ZSBkYXRhIGZyb20gc2Vzc2lvblN0b3JhZ2Ugb3IgdGhlIGNvb2tpZSBkZXBlbmRpbmcgb24gd2hhdCB0aGUgYnJvd3NlciBpcyBzdXBwb3J0aW5nLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3JlbW92ZVZhbHVlRnJvbVBlcnNpc3RlbnRTdG9yYWdlKCkge1xuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5zYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXNzaW9uU3RvcmFnZUF2YWlsYWJsZSkge1xuICAgICAgICAgICAgICAgIHNlc3Npb25TdG9yYWdlLnJlbW92ZUl0ZW0odGhpcy5yYXdWYWx1ZVN0b3JhZ2VOYW1lKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKCk7XG4gICAgICAgICAgICAgICAgZGF0ZS5zZXRUaW1lKGRhdGUuZ2V0VGltZSgpIC0gODY0MDAwMDApOyAvLyAtODY0MDAwMDAgPT09IC0xICogMjQgKiA2MCAqIDYwICogMTAwMFxuICAgICAgICAgICAgICAgIGNvbnN0IGV4cGlyZXMgPSBgOyBleHBpcmVzPSR7ZGF0ZS50b1VUQ1N0cmluZygpfWA7XG4gICAgICAgICAgICAgICAgZG9jdW1lbnQuY29va2llID0gYCR7dGhpcy5yYXdWYWx1ZVN0b3JhZ2VOYW1lfT0nJyA7JHtleHBpcmVzfTsgcGF0aD0vYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yICdmb2N1c2luJyBhbmQgJ21vdXNlZW50ZXInIGV2ZW50c1xuICAgICAqIE9uIGZvY3VzaW4sIG11bHRpcGxlIHRoaW5ncyBoYXBwZW5zIDpcbiAgICAgKiAtIElmIGBBbHRgIGlzIHByZXNzZWQsIHVuZm9ybWF0XG4gICAgICogLSBSZW1vdmUgdGhlIHNlcGFyYXRvcnMgaWYgYHNob3dPbmx5TnVtYmVyc09uRm9jdXNgIGlzIHNldFxuICAgICAqIC0gRGVwZW5kaW5nIG9uIGBlbXB0eUlucHV0QmVoYXZpb3JgLCByZWZvcm1hdCB0aGUgZW1wdHkgZm9ybWF0dGVkIHZhbHVlXG4gICAgICogLSBEaXNwbGF5IHRoZSBjb3JyZWN0IG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyAob24gZm9jdXMvYmx1cilcbiAgICAgKiAtIFBsYWNlIHRoZSBjYXJldCBjb3JyZWN0bHkgaWYgdGhlIGVsZW1lbnQgaXMgZW1wdHlcbiAgICAgKlxuICAgICAqIE5vdGU6IE9uIGZvY3VzaW4sIHRoZSBgcmF3VmFsdWVgIGlzIG5ldmVyIGNoYW5nZWQuIE9ubHkgdGhlIGZvcm1hdHRlZCB2YWx1ZSBjYW4gYmUgbW9kaWZpZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfb25Gb2N1c0luQW5kTW91c2VFbnRlcihlKSB7XG4gICAgICAgIC8vVE9ETyBDcmVhdGUgc2VwYXJhdGUgaGFuZGxlcnMgZm9yIHRoZSBmb2N1cyBhbmQgbW91c2VlbnRlciBldmVudHNcbiAgICAgICAgdGhpcy5pc0VkaXRpbmcgPSBmYWxzZTsgLy8gSnVzdCBpbiBjYXNlIG5vIGBrZXlVcGAgZXZlbnQgaGF2ZSBiZWVuIHNlbnQgKGllLiBpZiB0aGUgdXNlciBsb3N0IHRoZSBmb2N1cyBmcm9tIHRoZSBjdXJyZW50IHdpbmRvdyB3aGlsZSB0eXBpbmcpXG4gICAgICAgIHRoaXMucmF3VmFsdWVPbkZvY3VzID0gdGhpcy5yYXdWYWx1ZTsgLy8gS2VlcCB0cmFjayBvZiB0aGUgaW5pdGlhbCByYXdWYWx1ZS4gVGhpcyBpcyBuZWVkZWQgdG8gZGVmaW5lIGlmIGEgY2hhbmdlIGV2ZW50IG11c3QgYmUgZGlzcGF0Y2hlZCBsYXRlclxuXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnVuZm9ybWF0T25Ib3ZlciAmJiBlLnR5cGUgPT09ICdtb3VzZWVudGVyJyAmJiBlLmFsdEtleSkge1xuICAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fdW5mb3JtYXRBbHRIb3ZlcmVkKHRoaXMpO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZS50eXBlID09PSAnZm9jdXMnKSB7IC8vVE9ETyBNb3ZlIHRoYXQgYmFjayB0byB0aGUgJ2ZvY3VzJyBldmVudCBoYW5kbGVyIHdoZW4gdGhlIHNlcGFyYXRpb24gYmV0d2VlbiB0aGUgJ2ZvY3VzJyBhbmQgJ21vdXNlZW50ZXInIGhhbmRsZXIgd2lsbCBiZSBkb25lXG4gICAgICAgICAgICAvLyBLZWVwIHRyYWNrIGlmIHRoZSBlbGVtZW50IGlzIGN1cnJlbnRseSBmb2N1c2VkXG4gICAgICAgICAgICB0aGlzLmlzRm9jdXNlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZS50eXBlID09PSAnZm9jdXMnICYmIHRoaXMuc2V0dGluZ3MudW5mb3JtYXRPbkhvdmVyICYmIHRoaXMuaG92ZXJlZFdpdGhBbHQpIHtcbiAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IuX3JlZm9ybWF0QWx0SG92ZXJlZCh0aGlzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChlLnR5cGUgPT09ICdmb2N1cycgfHwgZS50eXBlID09PSAnbW91c2VlbnRlcicgJiYgIXRoaXMuaXNGb2N1c2VkKSB7XG4gICAgICAgICAgICBsZXQgZWxlbWVudFZhbHVlVG9TZXQgPSBudWxsOyAvLyBTdG9yZSB0aGUgdmFsdWUgd2Ugd2FudCB0byBzZXQgb24gdGhlIGVsZW1lbnQsIGFuZCBvbmx5IGNhbGwgYF9zZXRFbGVtZW50VmFsdWUoKWAgb25jZVxuXG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLmZvY3VzICYmXG4gICAgICAgICAgICAgICAgdGhpcy5yYXdWYWx1ZSA8IDAgJiYgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciAhPT0gbnVsbCAmJiB0aGlzLnNldHRpbmdzLmlzTmVnYXRpdmVTaWduQWxsb3dlZCkgeyAvL0ZJWE1FIHRoaXMgaXMgY2FsbGVkIGEgc2Vjb25kIHRpbWUgaW4gX2FkZEdyb3VwU2VwYXJhdG9ycyB0b28uIFByZXZlbnQgdGhpcywgaWYgcG9zc2libGUuXG4gICAgICAgICAgICAgICAgLy8gT25seSByZW1vdmUgdGhlIGJyYWNrZXRzIGlmIHRoZSB2YWx1ZSBpcyBuZWdhdGl2ZVxuICAgICAgICAgICAgICAgIGVsZW1lbnRWYWx1ZVRvU2V0ID0gdGhpcy5jb25zdHJ1Y3Rvci5fcmVtb3ZlQnJhY2tldHMoQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCksIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgIC8vRklYTUUgVGhlIGVsZW1lbnQgdmFsdWUgaXMgc2V0IGhlcmUsIHdoeSBjb250aW51ZSBhbmQgc2V0IGl0IGFnYWluIGxhdGVyIGluIHRoYXQgc2FtZSBwYXJlbnQgbG9naWMgYmxvY2s/XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFVzZSB0aGUgYHJhd1ZhbHVlYCwgbXVsdGlwbGllZCBieSBgcmF3VmFsdWVEaXZpc29yYCBpZiBkZWZpbmVkXG4gICAgICAgICAgICBjb25zdCByYXdWYWx1ZVRvRm9ybWF0ID0gdGhpcy5fZ2V0UmF3VmFsdWVUb0Zvcm1hdCh0aGlzLnJhd1ZhbHVlKTtcblxuICAgICAgICAgICAgLy8gTW9kaWZ5IHRoZSBlbGVtZW50IHZhbHVlIGFjY29yZGluZyB0byB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHNob3cgb24gZm9jdXMgb3IgdGhlIGBzaG93T25seU51bWJlcnNPbkZvY3VzYCBvcHRpb25cbiAgICAgICAgICAgIGlmIChyYXdWYWx1ZVRvRm9ybWF0ICE9PSAnJykge1xuICAgICAgICAgICAgICAgIC8vIFJvdW5kIHRoZSBnaXZlbiB2YWx1ZSBhY2NvcmRpbmcgdG8gdGhlIG9iamVjdCBzdGF0ZSAoZm9jdXMvdW5mb2N1c2VkKVxuICAgICAgICAgICAgICAgIGxldCByb3VuZGVkVmFsdWU7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNGb2N1c2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIHJvdW5kZWRWYWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uRm9jdXMocmF3VmFsdWVUb0Zvcm1hdCwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcm91bmRlZFZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fcm91bmRGb3JtYXR0ZWRWYWx1ZVNob3duT25CbHVyKHJhd1ZhbHVlVG9Gb3JtYXQsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnNob3dPbmx5TnVtYmVyc09uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuc2hvd09ubHlOdW1iZXJzT25Gb2N1cy5vbmx5TnVtYmVycykge1xuICAgICAgICAgICAgICAgICAgICAvL1RPRE8gVXNlIGEgYHRoaXMuc2V0dGluZ3NPdmVycmlkZWAgb2JqZWN0IGluc3RlYWQgb2YgbW9kaWZ5aW5nIHRoZSBgdGhpcy5zZXR0aW5nc2Agb2JqZWN0XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuZGlnaXRHcm91cFNlcGFyYXRvciA9ICcnO1xuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sICAgICAgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5zdWZmaXhUZXh0ICAgICAgICAgID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnRWYWx1ZVRvU2V0ID0gcm91bmRlZFZhbHVlLnJlcGxhY2UoJy4nLCB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBmb3JtYXR0ZWRWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChyb3VuZGVkVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXR0ZWRWYWx1ZSA9ICcnO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0dGVkVmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9hZGRHcm91cFNlcGFyYXRvcnMocm91bmRlZFZhbHVlLnJlcGxhY2UoJy4nLCB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpLCB0aGlzLnNldHRpbmdzLCB0aGlzLmlzRm9jdXNlZCwgcmF3VmFsdWVUb0Zvcm1hdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBlbGVtZW50VmFsdWVUb1NldCA9IGZvcm1hdHRlZFZhbHVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSW4gb3JkZXIgdG8gc2VuZCBhICduYXRpdmUnIGNoYW5nZSBldmVudCB3aGVuIGJsdXJyaW5nIHRoZSBpbnB1dCwgd2UgbmVlZCB0byBmaXJzdCBzdG9yZSB0aGUgaW5pdGlhbCBpbnB1dCB2YWx1ZSBvbiBmb2N1cy5cbiAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoZWxlbWVudFZhbHVlVG9TZXQpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZU9uRm9jdXMgPSAnJztcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy52YWx1ZU9uRm9jdXMgPSBlbGVtZW50VmFsdWVUb1NldDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5sYXN0VmFsID0gdGhpcy52YWx1ZU9uRm9jdXM7XG4gICAgICAgICAgICBjb25zdCBpc0VtcHR5VmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9pc0VsZW1lbnRWYWx1ZUVtcHR5T3JPbmx5VGhlTmVnYXRpdmVTaWduKHRoaXMudmFsdWVPbkZvY3VzLCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgICAgIGNvbnN0IG9yZGVyZWRWYWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX29yZGVyVmFsdWVDdXJyZW5jeVN5bWJvbEFuZFN1ZmZpeFRleHQodGhpcy52YWx1ZU9uRm9jdXMsIHRoaXMuc2V0dGluZ3MsIHRydWUpOyAvLyBUaGlzIGRpc3BsYXlzIHRoZSBjdXJyZW5jeSBzaWduIG9uIGhvdmVyIGV2ZW4gaWYgdGhlIHJhd1ZhbHVlIGlzIGVtcHR5XG4gICAgICAgICAgICBjb25zdCBvcmRlcmVkVmFsdWVUZXN0ID0gKGlzRW1wdHlWYWx1ZSAmJiBvcmRlcmVkVmFsdWUgIT09ICcnKSAmJiB0aGlzLnNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvciA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IuZm9jdXM7XG4gICAgICAgICAgICBpZiAob3JkZXJlZFZhbHVlVGVzdCkge1xuICAgICAgICAgICAgICAgIGVsZW1lbnRWYWx1ZVRvU2V0ID0gb3JkZXJlZFZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChlbGVtZW50VmFsdWVUb1NldCkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50VmFsdWUoZWxlbWVudFZhbHVlVG9TZXQpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAob3JkZXJlZFZhbHVlVGVzdCAmJiBvcmRlcmVkVmFsdWUgPT09IHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgJiYgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGVyZSBpcyBhIGN1cnJlbmN5IHN5bWJvbCBhbmQgaXRzIG9uIHRoZSByaWdodCBoYW5kIHNpZGUsIHRoZW4gd2UgcGxhY2UgdGhlIGNhcmV0IGFjY29yZGluZ2x5IG9uIHRoZSBmYXIgbGVmdCBzaWRlXG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCwgMCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVyIGZvciB0aGUgJ2ZvY3VzJyBldmVudC5cbiAgICAgKiBXZSB1cGRhdGUgdGhlIGluZm8gb2YgdGhlIGZvY3VzZWQgc3RhdGUgaW4gdGhlIGB0aGlzLmlzRm9jdXNlZGAgdmFyaWFibGUgd2hlbiB0aGUgZWxlbWVudCBnZXRzIGZvY3VzZWQuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfb25Gb2N1cygpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuaXNDYW5jZWxsYWJsZSkge1xuICAgICAgICAgICAgLy8gU2F2ZSB0aGUgY3VycmVudCB1bmZvcm1hdHRlZCB2YWx1ZSBmb3IgbGF0ZXIgdXNlIGJ5IHRoZSAnY2FuY2VsbGFibGUnIGZlYXR1cmVcbiAgICAgICAgICAgIHRoaXMuX3NhdmVDYW5jZWxsYWJsZVZhbHVlKCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVyIGZvciB0aGUgJ2ZvY3VzaW4nIGV2ZW50LlxuICAgICAqIFRoaXMgaXMgY2FsbGVkIGJlZm9yZSB0aGUgJ2ZvY3VzJyBldmVudCwgYW5kIGlzIG5lY2Vzc2FyeSB0byBjaGFuZ2UgdGhlIHNlbGVjdGlvbiBvbiBmb2N1cyB1bmRlciBGaXJlZm94IGZvciBpbnN0YW5jZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9vbkZvY3VzSW4oZSkge1xuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5zZWxlY3RPbkZvY3VzKSB7XG4gICAgICAgICAgICAvLyBUaGUgd2hvbGUgaW5wdXQgY29udGVudCBpcyBzZWxlY3RlZCBvbiBmb2N1cyAoZm9sbG93aW5nIHRoZSBgc2VsZWN0T25Gb2N1c2AgYW5kIGBzZWxlY3ROdW1iZXJPbmx5YCBvcHRpb25zKVxuICAgICAgICAgICAgLy9YWFggRmlyZWZveCA8NDcgZG9lcyBub3QgcmVzcGVjdCB0aGlzIHNlbGVjdGlvbi4uLk9oIHdlbGwuXG4gICAgICAgICAgICB0aGlzLnNlbGVjdCgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gT3Igd2UgZGVjaWRlIHdoZXJlIHRvIHB1dCB0aGUgY2FyZXQgdXNpbmcgdGhlIGBjYXJldFBvc2l0aW9uT25Gb2N1c2Agb3B0aW9uXG4gICAgICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbCh0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzKSkge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24oZS50YXJnZXQsIHRoaXMuX2luaXRpYWxDYXJldFBvc2l0aW9uKEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVyIGZvciAna2V5ZG93bicgZXZlbnRzLlxuICAgICAqIFRoZSB1c2VyIGp1c3Qgc3RhcnRlZCBwdXNoaW5nIGFueSBrZXksIGhlbmNlIG9uZSBldmVudCBpcyBzZW50LlxuICAgICAqXG4gICAgICogTm90ZSA6XG4gICAgICogQnkgZGVmYXVsdCBhICdub3JtYWwnIGlucHV0IG91dHB1dCB0aG9zZSBldmVudHMgaW4gdGhlIHJpZ2h0IG9yZGVyIHdoZW4gaW5wdXR0aW5nIGEgY2hhcmFjdGVyIGtleSAoaWUuICdhJykgOlxuICAgICAqIC0ga2V5ZG93blxuICAgICAqIC0ga2V5cHJlc3NcbiAgICAgKiAtIGlucHV0XG4gICAgICogLSBrZXl1cFxuICAgICAqXG4gICAgICogLi4ud2hlbiBpbnB1dHRpbmcgYSBtb2RpZmllciBrZXkgKGllLiAnY3RybCcpIDpcbiAgICAgKiAtIGtleWRvd25cbiAgICAgKiAtIGtleXVwXG4gICAgICpcbiAgICAgKiBJZiAnZGVsZXRlJyBvciAnYmFja3NwYWNlJyBpcyBlbnRlcmVkLCB0aGUgZm9sbG93aW5nIGV2ZW50cyBhcmUgc2VudCA6XG4gICAgICogLSBrZXlkb3duXG4gICAgICogLSBpbnB1dFxuICAgICAqIC0ga2V5dXBcbiAgICAgKlxuICAgICAqIElmICdlbnRlcicgaXMgZW50ZXJlZCBhbmQgdGhlIHZhbHVlIGhhcyBub3QgY2hhbmdlZCwgdGhlIGZvbGxvd2luZyBldmVudHMgYXJlIHNlbnQgOlxuICAgICAqIC0ga2V5ZG93blxuICAgICAqIC0ga2V5cHJlc3NcbiAgICAgKiAtIGtleXVwXG4gICAgICpcbiAgICAgKiBJZiAnZW50ZXInIGlzIGVudGVyZWQgYW5kIHRoZSB2YWx1ZSBoYXMgYmVlbiBjaGFuZ2VkLCB0aGUgZm9sbG93aW5nIGV2ZW50cyBhcmUgc2VudCA6XG4gICAgICogLSBrZXlkb3duXG4gICAgICogLSBrZXlwcmVzc1xuICAgICAqIC0gY2hhbmdlXG4gICAgICogLSBrZXl1cFxuICAgICAqXG4gICAgICogV2hlbiBhIHBhc3RlIGlzIGRvbmUsIHRoZSBmb2xsb3dpbmcgZXZlbnRzIGFyZSBzZW50IDpcbiAgICAgKiAtIGlucHV0IChpZiBwYXN0ZSBpcyBkb25lIHdpdGggdGhlIG1vdXNlKVxuICAgICAqXG4gICAgICogLSBrZXlkb3duIChpZiBwYXN0ZSBpcyBkb25lIHdpdGggY3RybCt2KVxuICAgICAqIC0ga2V5ZG93blxuICAgICAqIC0gaW5wdXRcbiAgICAgKiAtIGtleXVwXG4gICAgICogLSBrZXl1cFxuICAgICAqXG4gICAgICogQHBhcmFtIHtLZXlib2FyZEV2ZW50fSBlXG4gICAgICovXG4gICAgX29uS2V5ZG93bihlKSB7XG4gICAgICAgIHRoaXMuZm9ybWF0dGVkID0gZmFsc2U7IC8vIEtlZXAgdHJhY2sgaWYgdGhlIGVsZW1lbnQgaGFzIGJlZW4gZm9ybWF0dGVkIGFscmVhZHkuIElmIHRoYXQncyB0aGUgY2FzZSwgcHJldmVudCBmdXJ0aGVyIGZvcm1hdCBjYWxjdWxhdGlvbnMuXG4gICAgICAgIHRoaXMuaXNFZGl0aW5nID0gdHJ1ZTsgLy8gS2VlcCB0cmFjayBpZiB0aGUgdXNlciBpcyBjdXJyZW50bHkgZWRpdGluZyB0aGUgZWxlbWVudCBtYW51YWxseVxuXG4gICAgICAgIGlmICghdGhpcy5pc0ZvY3VzZWQgJiYgdGhpcy5zZXR0aW5ncy51bmZvcm1hdE9uSG92ZXIgJiYgZS5hbHRLZXkgJiYgdGhpcy5kb21FbGVtZW50ID09PSBBdXRvTnVtZXJpY0hlbHBlci5nZXRIb3ZlcmVkRWxlbWVudCgpKSB7XG4gICAgICAgICAgICAvLyBIZXJlIEkgcHJldmVudCBjYWxsaW5nIF91bmZvcm1hdEFsdEhvdmVyZWQgaWYgdGhlIGVsZW1lbnQgaXMgYWxyZWFkeSBmb2N1c2VkLCBzaW5jZSB0aGUgZ2xvYmFsICdrZXlkb3duJyBsaXN0ZW5lciB3aWxsIHBpY2sgaXQgdXAgYXMgd2VsbFxuICAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fdW5mb3JtYXRBbHRIb3ZlcmVkKHRoaXMpO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl91cGRhdGVFdmVudEtleUluZm8oZSk7XG4gICAgICAgIHRoaXMuaW5pdGlhbFZhbHVlT25LZXlkb3duID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKGUudGFyZ2V0KTsgLy8gVGhpcyBpcyBuZWVkZWQgaW4gYG9uS2V5dXAoKWAgdG8gY2hlY2sgaWYgdGhlIHZhbHVlIGFzIGNoYW5nZWQgZHVyaW5nIHRoZSBrZXkgcHJlc3NcbiAgICAgICAgdGhpcy5pbml0aWFsUmF3VmFsdWVPbktleWRvd24gPSB0aGlzLnJhd1ZhbHVlO1xuXG4gICAgICAgIGlmICh0aGlzLmRvbUVsZW1lbnQucmVhZE9ubHkpIHtcbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc2VkID0gdHJ1ZTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkVzYykge1xuICAgICAgICAgICAgLy9YWFggVGhlIGRlZmF1bHQgJ0VzY2FwZScga2V5IGJlaGF2aW9yIGRpZmZlcnMgYmV0d2VlbiBGaXJlZm94IGFuZCBDaHJvbWUsIEZpcmVmb3ggYWxyZWFkeSBoYXZpbmcgYSBidWlsdC1pbiAnY2FuY2VsbGFibGUtbGlrZScgZmVhdHVyZS4gVGhpcyBpcyB3aHkgd2UgY2FsbCBgZS5wcmV2ZW50RGVmYXVsdCgpYCBoZXJlIGluc3RlYWQgb2YganVzdCB3aGVuIGBpc0NhbmNlbGxhYmxlYCBpcyBzZXQgdG8gYHRydWVgLiBUaGlzIGFsbG93IHVzIHRvIGtlZXAgdGhlIHNhbWUgYmVoYXZpb3IgYWNyb3NzIGJyb3dzZXJzLlxuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5pc0NhbmNlbGxhYmxlKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIHVzZXIgd2FudHMgdG8gY2FuY2VsIGhpcyBtb2RpZmljYXRpb25zOlxuICAgICAgICAgICAgICAgIC8vIFdlIHNldCBiYWNrIHRoZSBzYXZlZCB2YWx1ZVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJhd1ZhbHVlICE9PSB0aGlzLnNhdmVkQ2FuY2VsbGFibGVWYWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBEbyBub3Qgc2V0IHRoZSB2YWx1ZSBhZ2FpbiBpZiBpdCBoYXMgbm90IGNoYW5nZWRcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXQodGhpcy5zYXZlZENhbmNlbGxhYmxlVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAvLyBBbmQgd2UgbmVlZCB0byBzZW5kIGFuICdpbnB1dCcgZXZlbnQgd2hlbiBzZXR0aW5nIGJhY2sgdGhlIGluaXRpYWwgdmFsdWUgaW4gb3JkZXIgdG8gbWFrZSBvdGhlciBzY3JpcHRzIGF3YXJlIG9mIHRoZSB2YWx1ZSBjaGFuZ2UuLi5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5uYXRpdmUuaW5wdXQsIGUudGFyZ2V0KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIC4uYW5kIGxhc3RseSB3ZSB1cGRhdGUgdGhlIGNhcmV0IHNlbGVjdGlvbiwgZXZlbiBpZiB0aGUgb3B0aW9uIGBpc0NhbmNlbGxhYmxlYCBpcyBmYWxzZVxuICAgICAgICAgICAgdGhpcy5zZWxlY3QoKTtcbiAgICAgICAgICAgIC8vVE9ETyBBZGQgYW4gb3B0aW9uIHRvIHNlbGVjdCBlaXRoZXIgdGhlIGludGVnZXIgb3IgZGVjaW1hbCBwYXJ0IHdpdGggYEVzY2BcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRoZSBcImVudGVyXCIga2V5IHRocm93cyBhIGBjaGFuZ2VgIGV2ZW50IGlmIHRoZSByYXcgdmFsdWUgaGFzIGNoYW5nZWQgc2luY2UgdGhlIGBmb2N1c2AgZXZlbnRcbiAgICAgICAgbGV0IHRhcmdldFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKGUudGFyZ2V0KTtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkVudGVyICYmIHRoaXMucmF3VmFsdWUgIT09IHRoaXMucmF3VmFsdWVPbkZvY3VzKSB7XG4gICAgICAgICAgICB0aGlzLl90cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLm5hdGl2ZS5jaGFuZ2UsIGUudGFyZ2V0KTtcbiAgICAgICAgICAgIHRoaXMudmFsdWVPbkZvY3VzID0gdGFyZ2V0VmFsdWU7XG4gICAgICAgICAgICB0aGlzLnJhd1ZhbHVlT25Gb2N1cyA9IHRoaXMucmF3VmFsdWU7XG5cbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmlzQ2FuY2VsbGFibGUpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgdXNlciBhY3RpdmF0ZWQgdGhlICdjYW5jZWxsYWJsZScgZmVhdHVyZSwgd2Ugc2F2ZSB0aGUgdmFsaWRhdGVkIHZhbHVlIHdoZW4gJ0VudGVyJyBpcyBoaXRcbiAgICAgICAgICAgICAgICB0aGlzLl9zYXZlQ2FuY2VsbGFibGVWYWx1ZSgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlSW50ZXJuYWxQcm9wZXJ0aWVzKGUpO1xuXG4gICAgICAgIGlmICh0aGlzLl9wcm9jZXNzTm9uUHJpbnRhYmxlS2V5c0FuZFNob3J0Y3V0cyhlKSkge1xuICAgICAgICAgICAgdGhpcy5wcm9jZXNzZWQgPSB0cnVlO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayBpZiB0aGUga2V5IGlzIGEgZGVsZXRlL2JhY2tzcGFjZSBrZXlcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkJhY2tzcGFjZSB8fCB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5EZWxldGUpIHtcbiAgICAgICAgICAgIHRoaXMuX3Byb2Nlc3NDaGFyYWN0ZXJEZWxldGlvbigpOyAvLyBCZWNhdXNlIGJhY2tzcGFjZSBhbmQgZGVsZXRlIG9ubHkgdHJpZ2dlcnMga2V5ZG93biBhbmQga2V5dXAgZXZlbnRzLCBub3Qga2V5cHJlc3NcbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc2VkID0gdHJ1ZTtcbiAgICAgICAgICAgIHRoaXMuX2Zvcm1hdFZhbHVlKGUpO1xuXG4gICAgICAgICAgICAvLyBJZiBhbmQgb25seSBpZiB0aGUgcmVzdWx0aW5nIHZhbHVlIGhhcyBjaGFuZ2VkIGFmdGVyIHRoYXQgYmFja3NwYWNlL2RlbGV0ZSwgdGhlbiB3ZSBoYXZlIHRvIHNlbmQgYW4gJ2lucHV0JyBldmVudCBsaWtlIGJyb3dzZXJzIG5vcm1hbGx5IGRvLlxuICAgICAgICAgICAgdGFyZ2V0VmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUoZS50YXJnZXQpOyAvLyBVcGRhdGUgdGhlIHZhbHVlIHNpbmNlIGl0IGNvdWxkIGhhdmUgYmVlbiBjaGFuZ2VkIGR1cmluZyB0aGUgZGVsZXRpb25cbiAgICAgICAgICAgIGlmICgodGFyZ2V0VmFsdWUgIT09IHRoaXMubGFzdFZhbCkgJiYgdGhpcy50aHJvd0lucHV0KSB7XG4gICAgICAgICAgICAgICAgLy8gVGhyb3cgYW4gaW5wdXQgZXZlbnQgd2hlbiBhIGNoYXJhY3RlciBkZWxldGlvbiBpcyBkZXRlY3RlZFxuICAgICAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubmF0aXZlLmlucHV0LCBlLnRhcmdldCk7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOyAvLyAuLi5hbmQgaW1tZWRpYXRlbHkgcHJldmVudCB0aGUgYnJvd3NlciB0byBkZWxldGUgYSBzZWNvbmQgY2hhcmFjdGVyXG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMubGFzdFZhbCA9IHRhcmdldFZhbHVlO1xuICAgICAgICAgICAgdGhpcy50aHJvd0lucHV0ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yICdrZXlwcmVzcycgZXZlbnRzLlxuICAgICAqIFRoZSB1c2VyIGlzIHN0aWxsIHByZXNzaW5nIHRoZSBrZXksIHdoaWNoIHdpbGwgb3V0cHV0IGEgY2hhcmFjdGVyIChpZS4gJzInKSBjb250aW51b3VzbHkgdW50aWwgaXQgcmVsZWFzZXMgdGhlIGtleS5cbiAgICAgKiBOb3RlOiAna2V5cHJlc3MnIGV2ZW50cyBhcmUgbm90IHNlbnQgZm9yIGRlbGV0ZSBrZXlzIGxpa2UgQmFja3NwYWNlL0RlbGV0ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7S2V5Ym9hcmRFdmVudH0gZVxuICAgICAqL1xuICAgIF9vbktleXByZXNzKGUpIHtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkluc2VydCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcHJvY2Vzc2VkID0gdGhpcy5wcm9jZXNzZWQ7XG4gICAgICAgIHRoaXMuX3VwZGF0ZUludGVybmFsUHJvcGVydGllcyhlKTtcblxuICAgICAgICBpZiAodGhpcy5fcHJvY2Vzc05vblByaW50YWJsZUtleXNBbmRTaG9ydGN1dHMoZSkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwcm9jZXNzZWQpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaXNDaGFyYWN0ZXJJbnNlcnRpb25BbGxvd2VkID0gdGhpcy5fcHJvY2Vzc0NoYXJhY3Rlckluc2VydGlvbigpO1xuICAgICAgICBpZiAoaXNDaGFyYWN0ZXJJbnNlcnRpb25BbGxvd2VkKSB7XG4gICAgICAgICAgICB0aGlzLl9mb3JtYXRWYWx1ZShlKTtcbiAgICAgICAgICAgIGNvbnN0IHRhcmdldFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKGUudGFyZ2V0KTtcbiAgICAgICAgICAgIGlmICgodGFyZ2V0VmFsdWUgIT09IHRoaXMubGFzdFZhbCkgJiYgdGhpcy50aHJvd0lucHV0KSB7XG4gICAgICAgICAgICAgICAgLy8gVGhyb3dzIGlucHV0IGV2ZW50IG9uIGFkZGluZyBhIGNoYXJhY3RlclxuICAgICAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubmF0aXZlLmlucHV0LCBlLnRhcmdldCk7XG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOyAvLyAuLi5hbmQgaW1tZWRpYXRlbHkgcHJldmVudCB0aGUgYnJvd3NlciB0byBhZGQgYSBzZWNvbmQgY2hhcmFjdGVyXG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICgodGhpcy5ldmVudEtleSA9PT0gdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyIHx8IHRoaXMuZXZlbnRLZXkgPT09IHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlKSAmJlxuICAgICAgICAgICAgICAgICAgICAoQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCkuc3RhcnQgPT09IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRTZWxlY3Rpb24oZS50YXJnZXQpLmVuZCkgJiZcbiAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCkuc3RhcnQgPT09IHRhcmdldFZhbHVlLmluZGV4T2YodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBwb3NpdGlvbiA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRTZWxlY3Rpb24oZS50YXJnZXQpLnN0YXJ0ICsgMTtcbiAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCwgcG9zaXRpb24pO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5sYXN0VmFsID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKGUudGFyZ2V0KTtcbiAgICAgICAgICAgIHRoaXMudGhyb3dJbnB1dCA9IHRydWU7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVyIGZvciAna2V5dXAnIGV2ZW50cy5cbiAgICAgKiBUaGUgdXNlciBqdXN0IHJlbGVhc2VkIGFueSBrZXksIGhlbmNlIG9uZSBldmVudCBpcyBzZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtLZXlib2FyZEV2ZW50fSBlXG4gICAgICovXG4gICAgX29uS2V5dXAoZSkge1xuICAgICAgICB0aGlzLmlzRWRpdGluZyA9IGZhbHNlO1xuXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmlzQ2FuY2VsbGFibGUgJiYgdGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuRXNjKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgdXNlciB3YW50cyB0byBjYW5jZWwgaXRzIG1vZGlmaWNhdGlvbnMsIHdlIGRyb3AgdGhlICdrZXl1cCcgZXZlbnQgZm9yIHRoZSBFc2Mga2V5XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1hbmFnZSB0aGUgdW5kby9yZWRvIGV2ZW50c1xuICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuWiB8fCB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS56KSB7XG4gICAgICAgICAgICBpZiAoZS5jdHJsS2V5ICYmIGUuc2hpZnRLZXkpIHtcbiAgICAgICAgICAgICAgICAvLyBSZWRvXG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX2hpc3RvcnlUYWJsZVJlZG8oKTtcbiAgICAgICAgICAgICAgICB0aGlzLm9uR29pbmdSZWRvID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZS5jdHJsS2V5ICYmICFlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub25Hb2luZ1JlZG8pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUHJldmVudCBhbiAndW5kbycgdG8gYmUgbGF1bmNoIHdoZW4gcmVsZWFzaW5nIHRoZSBzaGlmdCBrZXkgYmVmb3JlIHRoZSBjdHJsIGtleSBhZnRlciBhICdyZWRvJyBzaG9ydGN1dFxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uR29pbmdSZWRvID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAvLyBVbmRvXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2hpc3RvcnlUYWJsZVVuZG8oKTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMub25Hb2luZ1JlZG8gJiYgKGUuY3RybEtleSB8fCBlLnNoaWZ0S2V5KSkge1xuICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlIHdoZXJlIGlmIHRoZSB1c2VyIGhhcyBlbnRlcmVkIGBDb250cm9sK1NoaWZ0K3pgLCB0aGVuIHJlbGVhc2UgYHpgLCBrZWVwaW5nIGBDb250cm9sYCBvciBgU2hpZnRgIHByZXNzZWQsIHRoZW4gYHRoaXMub25Hb2luZ1JlZG9gIGlzIG5ldmVyIGNoYW5nZWQgYmFjayB0byBgZmFsc2VgIHdoZW4gdGhlIHVzZXIgcmVsZWFzZSBgQ29udHJvbGAgb3IgYFNoaWZ0YFxuICAgICAgICAgICAgdGhpcy5vbkdvaW5nUmVkbyA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTWFuYWdlIHRoZSBDdXQgZXZlbnRcbiAgICAgICAgaWYgKChlLmN0cmxLZXkgfHwgZS5tZXRhS2V5KSAmJiB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS54KSB7XG4gICAgICAgICAgICAvLyBTYXZlIHRoZSBjYXJldCBwb3NpdGlvbiBhdCB0aGUgc3RhcnQgb2YgdGhlIHNlbGVjdGlvblxuICAgICAgICAgICAgY29uc3QgY2FyZXRQb3NpdGlvbiA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRTZWxlY3Rpb24odGhpcy5kb21FbGVtZW50KS5zdGFydDtcbiAgICAgICAgICAgIC8vIENvbnZlcnQgdGhlIHJlbWFpbmluZyAnZm9ybWF0dGVkJyBudW1iZXJzIGluIGEgSnMgbnVtYmVyXG4gICAgICAgICAgICBjb25zdCBjdXROdW1iZXIgPSB0aGlzLmNvbnN0cnVjdG9yLl90b051bWVyaWNWYWx1ZShBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUoZS50YXJnZXQpLCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgICAgIC8vIFRyeSB0byBzZXQgdGhhdCB2YWx1ZSB3aXRoIGBzZXQoKWBcbiAgICAgICAgICAgIHRoaXMuc2V0KGN1dE51bWJlcik7XG4gICAgICAgICAgICAvLyBTZXQgYmFjayB0aGUgaW5pdGlhbCBjYXJldCBwb3NpdGlvblxuICAgICAgICAgICAgdGhpcy5fc2V0Q2FyZXRQb3NpdGlvbihjYXJldFBvc2l0aW9uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1hbmFnZSB0aGUgcmVmb3JtYXQgd2hlbiBob3ZlcmVkIHdpdGggdGhlIEFsdCBrZXkgcHJlc3NlZFxuICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQWx0ICYmIHRoaXMuaG92ZXJlZFdpdGhBbHQpIHtcbiAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IuX3JlZm9ybWF0QWx0SG92ZXJlZCh0aGlzKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fdXBkYXRlSW50ZXJuYWxQcm9wZXJ0aWVzKGUpO1xuXG4gICAgICAgIGNvbnN0IHNraXAgPSB0aGlzLl9wcm9jZXNzTm9uUHJpbnRhYmxlS2V5c0FuZFNob3J0Y3V0cyhlKTtcbiAgICAgICAgZGVsZXRlIHRoaXMudmFsdWVQYXJ0c0JlZm9yZVBhc3RlO1xuICAgICAgICBjb25zdCB0YXJnZXRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZShlLnRhcmdldCk7XG4gICAgICAgIGlmIChza2lwIHx8IHRhcmdldFZhbHVlID09PSAnJykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkZWQgdG8gcHJvcGVybHkgcGxhY2UgdGhlIGNhcmV0IHdoZW4gb25seSB0aGUgY3VycmVuY3kgc2lnbiBpcyBwcmVzZW50XG4gICAgICAgIGlmICh0YXJnZXRWYWx1ZSA9PT0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4KSB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCwgMCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24oZS50YXJnZXQsIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5UYWIpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24oZS50YXJnZXQsIDAsIHRhcmdldFZhbHVlLmxlbmd0aCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKHRhcmdldFZhbHVlID09PSB0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQpIHx8XG4gICAgICAgICAgICAodGhpcy5yYXdWYWx1ZSA9PT0gJycgJiYgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCAhPT0gJycgJiYgdGhpcy5zZXR0aW5ncy5zdWZmaXhUZXh0ICE9PSAnJykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24oZS50YXJnZXQsIDApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2F2ZXMgdGhlIGV4dGVuZGVkIGRlY2ltYWwgdG8gcHJlc2VydmUgdGhlIGRhdGEgd2hlbiBuYXZpZ2F0aW5nIGF3YXkgZnJvbSB0aGUgcGFnZVxuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzICE9PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLl9zYXZlVmFsdWVUb1BlcnNpc3RlbnRTdG9yYWdlKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuZm9ybWF0dGVkKSB7ICAvL1RPRE8gSXMgdGhpcyBsaW5lIG5lZWRlZD8gQ29uc2lkZXJpbmcgdGhhdCBvbktleWRvd24gYW5kIG9uS2V5cHJlc3MgYm90aCBmaW5pc2ggYnkgc2V0dGluZyBpdCB0byBmYWxzZS4uLlxuICAgICAgICAgICAgdGhpcy5fZm9ybWF0VmFsdWUoZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGb3JjZSB0aGUgYHJhd1ZhbHVlYCB1cGRhdGUgb24gQW5kcm9pZCBDaHJvbWVcbiAgICAgICAgdGhpcy5fc2F2ZVJhd1ZhbHVlRm9yQW5kcm9pZCgpO1xuXG4gICAgICAgIC8vIElmIHRoZSBpbnB1dCB2YWx1ZSBoYXMgY2hhbmdlZCBkdXJpbmcgdGhlIGtleSBwcmVzcyBldmVudCBjaGFpbiwgYW4gZXZlbnQgaXMgc2VudCB0byBhbGVydCB0aGF0IGEgZm9ybWF0dGluZyBoYXMgYmVlbiBkb25lIChjZi4gSXNzdWUgIzE4NylcbiAgICAgICAgaWYgKHRhcmdldFZhbHVlICE9PSB0aGlzLmluaXRpYWxWYWx1ZU9uS2V5ZG93bikge1xuICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5mb3JtYXR0ZWQsIGUudGFyZ2V0LCB7XG4gICAgICAgICAgICAgICAgb2xkVmFsdWUgICA6IHRoaXMuaW5pdGlhbFZhbHVlT25LZXlkb3duLFxuICAgICAgICAgICAgICAgIG5ld1ZhbHVlICAgOiB0YXJnZXRWYWx1ZSxcbiAgICAgICAgICAgICAgICBvbGRSYXdWYWx1ZTogdGhpcy5pbml0aWFsUmF3VmFsdWVPbktleWRvd24sXG4gICAgICAgICAgICAgICAgbmV3UmF3VmFsdWU6IHRoaXMucmF3VmFsdWUsXG4gICAgICAgICAgICAgICAgaXNQcmlzdGluZSA6IHRoaXMuaXNQcmlzdGluZShmYWxzZSksXG4gICAgICAgICAgICAgICAgZXJyb3IgICAgICA6IG51bGwsXG4gICAgICAgICAgICAgICAgYU5FbGVtZW50ICA6IHRoaXMsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgc2VsZWN0aW9uIG9mIHRoZSBjdXJyZW50IGVsZW1lbnQgb2YgdGhlIGhpc3RvcnkgdGFibGVcbiAgICAgICAgaWYgKHRoaXMuaGlzdG9yeVRhYmxlLmxlbmd0aCA+IDEpIHtcbiAgICAgICAgICAgIGNvbnN0IHNlbGVjdGlvbiA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRTZWxlY3Rpb24odGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0aW9uU3RhcnQgPSBzZWxlY3Rpb24uc3RhcnQ7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGlvbkVuZCA9IHNlbGVjdGlvbi5lbmQ7XG4gICAgICAgICAgICB0aGlzLmhpc3RvcnlUYWJsZVt0aGlzLmhpc3RvcnlUYWJsZUluZGV4XS5zdGFydCA9IHRoaXMuc2VsZWN0aW9uU3RhcnQ7XG4gICAgICAgICAgICB0aGlzLmhpc3RvcnlUYWJsZVt0aGlzLmhpc3RvcnlUYWJsZUluZGV4XS5lbmQgPSB0aGlzLnNlbGVjdGlvbkVuZDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE9uIEFuZHJvaWQgQ2hyb21lLCB0aGUgYHJhd1ZhbHVlYCBpcyBub3QgdXBkYXRlZCB3aGVuIHRoZSB1c2VyIGNoYW5nZXMgdGhlIGlucHV0IHZhbHVlLlxuICAgICAqIFRoaXMgZnVuY3Rpb24gdXBkYXRlcyB0aGUgYHJhd1ZhbHVlYCBhY2NvcmRpbmdseS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zYXZlUmF3VmFsdWVGb3JBbmRyb2lkKCkge1xuICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQW5kcm9pZERlZmF1bHQpIHtcbiAgICAgICAgICAgIGxldCBub3JtYWxpemVkVmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnNFeGNlcHRDdXN0b21EZWNpbWFsQ2hhcih0aGlzLmdldEZvcm1hdHRlZCgpLCB0aGlzLnNldHRpbmdzLCB0cnVlLCB0aGlzLmlzRm9jdXNlZCk7XG4gICAgICAgICAgICBub3JtYWxpemVkVmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9jb252ZXJ0VG9OdW1lcmljU3RyaW5nKG5vcm1hbGl6ZWRWYWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG5cbiAgICAgICAgICAgIHRoaXMuX3NldFJhd1ZhbHVlKG5vcm1hbGl6ZWRWYWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVyIGZvciAnZm9jdXNvdXQnIGV2ZW50c1xuICAgICAqIE9uIGZvY3Vzb3V0LCBtdWx0aXBsZSB0aGluZ3MgaGFwcGVucyA6XG4gICAgICogLSBUaGUgZWxlbWVudCB2YWx1ZSBpcyBmb3JtYXR0ZWQgYmFjayBpZiB0aGUgYEFsdGAga2V5IHdhcyBwcmVzc2VkLFxuICAgICAqIC0gVGhlIGVsZW1lbnQgdmFsdWUgaXMgZm9ybWF0dGVkIGJhY2sgaWYgYHNob3dPbmx5TnVtYmVyc09uRm9jdXNgIHdhcyBzZXQgdG8gb25seSBzaG93IG51bWJlcnMsXG4gICAgICogLSBUaGUgZWxlbWVudCB2YWx1ZSBpcyBtdWx0aXBsaWVkIGJ5IGByYXdWYWx1ZURpdmlzb3JgIG9uIGBibHVyYFxuICAgICAqXG4gICAgICogTm90ZTogT24gZm9jdXNvdXQsIHRoZSBgcmF3VmFsdWVgIGlzIG5ldmVyIGNoYW5nZWQuIE9ubHkgdGhlIGZvcm1hdHRlZCB2YWx1ZSBjYW4gYmUgbW9kaWZpZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICovXG4gICAgX29uRm9jdXNPdXRBbmRNb3VzZUxlYXZlKGUpIHtcbiAgICAgICAgLy9UT0RPIENyZWF0ZSBzZXBhcmF0ZSBoYW5kbGVycyBmb3IgYmx1ciBhbmQgbW91c2VsZWF2ZVxuICAgICAgICB0aGlzLmlzRWRpdGluZyA9IGZhbHNlOyAvLyBKdXN0IGluIGNhc2Ugbm8gYGtleVVwYCBldmVudCBoYXZlIGJlZW4gc2VudCAoaWYgdGhlIHVzZXIgbG9zdCB0aGUgZm9jdXMgdG8gdGhlIHdpbmRvdyB3aGlsZSB0eXBpbmcpXG5cbiAgICAgICAgLy9GSVhNRSBEbyBub3QgY2FsbCBgc2V0KClgIGlmIHRoZSBjdXJyZW50IHJhdyB2YWx1ZSBpcyB0aGUgc2FtZSBhcyB0aGUgb25lIHdlIGFyZSB0cnlpbmcgdG8gc2V0IChjdXJyZW50bHksIG9uIGZvY3VzIG91dCwgYHNldCgpYCBpcyBhbHdheXMgY2FsbGVkLCBldmVuIGlmIHRoZSB2YWx1ZSBoYXMgbm90IGNoYW5nZWRcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MudW5mb3JtYXRPbkhvdmVyICYmIGUudHlwZSA9PT0gJ21vdXNlbGVhdmUnICYmIHRoaXMuaG92ZXJlZFdpdGhBbHQpIHtcbiAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IuX3JlZm9ybWF0QWx0SG92ZXJlZCh0aGlzKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKChlLnR5cGUgPT09ICdtb3VzZWxlYXZlJyAmJiAhdGhpcy5pc0ZvY3VzZWQpIHx8IGUudHlwZSA9PT0gJ2JsdXInKSB7XG4gICAgICAgICAgICB0aGlzLl9zYXZlVmFsdWVUb1BlcnNpc3RlbnRTdG9yYWdlKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5zaG93T25seU51bWJlcnNPbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnNob3dPbmx5TnVtYmVyc09uRm9jdXMub25seU51bWJlcnMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3IgPSB0aGlzLm9yaWdpbmFsRGlnaXRHcm91cFNlcGFyYXRvcjtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sID0gdGhpcy5vcmlnaW5hbEN1cnJlbmN5U3ltYm9sO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dCA9IHRoaXMub3JpZ2luYWxTdWZmaXhUZXh0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBVc2UgdGhlIHJhd1ZhbHVlLCBtdWx0aXBsaWVkIGJ5IGByYXdWYWx1ZURpdmlzb3JgIGlmIGRlZmluZWRcbiAgICAgICAgICAgIGNvbnN0IHJhd1ZhbHVlVG9Gb3JtYXQgPSB0aGlzLl9nZXRSYXdWYWx1ZVRvRm9ybWF0KHRoaXMucmF3VmFsdWUpO1xuICAgICAgICAgICAgY29uc3QgaXNSYXdWYWx1ZU51bGwgPSBBdXRvTnVtZXJpY0hlbHBlci5pc051bGwocmF3VmFsdWVUb0Zvcm1hdCk7XG4gICAgICAgICAgICBjb25zdCBbbWluVGVzdCwgbWF4VGVzdF0gPSB0aGlzLmNvbnN0cnVjdG9yLl9jaGVja0lmSW5SYW5nZVdpdGhPdmVycmlkZU9wdGlvbihyYXdWYWx1ZVRvRm9ybWF0LCB0aGlzLnNldHRpbmdzKTtcblxuICAgICAgICAgICAgLy8gRGlyZWN0bHkgc2V0IHRoZSBmb3JtYXR0ZWQgdmFsdWUgaWYgdGhlIGByYXdWYWx1ZWAgaXMgZm91bmQgaW4gYHZhbHVlc1RvU3RyaW5nc2BcbiAgICAgICAgICAgIGxldCBlbGVtZW50VmFsdWVJc0FscmVhZHlTZXQgPSBmYWxzZTtcbiAgICAgICAgICAgIGlmIChyYXdWYWx1ZVRvRm9ybWF0ICE9PSAnJyAmJiAhaXNSYXdWYWx1ZU51bGwpIHtcbiAgICAgICAgICAgICAgICBpZiAoIW1pblRlc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5taW5SYW5nZUV4Y2VlZGVkLCB0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghbWF4VGVzdCkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLm1heFJhbmdlRXhjZWVkZWQsIHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MudmFsdWVzVG9TdHJpbmdzICYmIHRoaXMuX2NoZWNrVmFsdWVzVG9TdHJpbmdzKHJhd1ZhbHVlVG9Gb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFNldCB0aGUgZm9ybWF0dGVkIHZhbHVlIHdpdGggdGhlIGNvcnJlc3BvbmRpbmcgc3RyaW5nXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldEVsZW1lbnRWYWx1ZSh0aGlzLnNldHRpbmdzLnZhbHVlc1RvU3RyaW5nc1tyYXdWYWx1ZVRvRm9ybWF0XSk7XG4gICAgICAgICAgICAgICAgICAgIGVsZW1lbnRWYWx1ZUlzQWxyZWFkeVNldCA9IHRydWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBPbmx5IGdlbmVyYXRlIHRoZSBmb3JtYXR0ZWQgdmFsdWUgaWYgbm8gYHZhbHVlc1RvU3RyaW5nc2AgaGF2ZSBiZWVuIGZvdW5kXG4gICAgICAgICAgICBpZiAoIWVsZW1lbnRWYWx1ZUlzQWxyZWFkeVNldCkge1xuICAgICAgICAgICAgICAgIGxldCB2YWx1ZTtcbiAgICAgICAgICAgICAgICBpZiAoaXNSYXdWYWx1ZU51bGwgfHwgcmF3VmFsdWVUb0Zvcm1hdCA9PT0gJycpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSByYXdWYWx1ZVRvRm9ybWF0O1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gU3RyaW5nKHJhd1ZhbHVlVG9Gb3JtYXQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChyYXdWYWx1ZVRvRm9ybWF0ICE9PSAnJyAmJiAhaXNSYXdWYWx1ZU51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKG1pblRlc3QgJiYgbWF4VGVzdCAmJiAhdGhpcy5jb25zdHJ1Y3Rvci5faXNFbGVtZW50VmFsdWVFbXB0eU9yT25seVRoZU5lZ2F0aXZlU2lnbihyYXdWYWx1ZVRvRm9ybWF0LCB0aGlzLnNldHRpbmdzKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLl9tb2RpZnlOZWdhdGl2ZVNpZ25BbmREZWNpbWFsQ2hhcmFjdGVyRm9yUmF3VmFsdWUodmFsdWUpO1xuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5kaXZpc29yV2hlblVuZm9jdXNlZCAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUgLyB0aGlzLnNldHRpbmdzLmRpdmlzb3JXaGVuVW5mb2N1c2VkO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9yb3VuZEZvcm1hdHRlZFZhbHVlU2hvd25PbkJsdXIodmFsdWUsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9tb2RpZnlOZWdhdGl2ZVNpZ25BbmREZWNpbWFsQ2hhcmFjdGVyRm9yRm9ybWF0dGVkVmFsdWUodmFsdWUsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFtaW5UZXN0KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5taW5SYW5nZUV4Y2VlZGVkLCB0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoIW1heFRlc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl90cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLm1heFJhbmdlRXhjZWVkZWQsIHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHJhd1ZhbHVlVG9Gb3JtYXQgPT09ICcnICYmIHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci56ZXJvKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFJhd1ZhbHVlKCcwJyk7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fcm91bmRWYWx1ZSgnMCcsIHRoaXMuc2V0dGluZ3MsIDApO1xuICAgICAgICAgICAgICAgIH1cblxuXG4gICAgICAgICAgICAgICAgbGV0IGdyb3VwZWRWYWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX29yZGVyVmFsdWVDdXJyZW5jeVN5bWJvbEFuZFN1ZmZpeFRleHQodmFsdWUsIHRoaXMuc2V0dGluZ3MsIGZhbHNlKTtcbiAgICAgICAgICAgICAgICBpZiAoISh0aGlzLmNvbnN0cnVjdG9yLl9pc0VsZW1lbnRWYWx1ZUVtcHR5T3JPbmx5VGhlTmVnYXRpdmVTaWduKHZhbHVlLCB0aGlzLnNldHRpbmdzKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgKGlzUmF3VmFsdWVOdWxsICYmIHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5udWxsKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgZ3JvdXBlZFZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fYWRkR3JvdXBTZXBhcmF0b3JzKHZhbHVlLCB0aGlzLnNldHRpbmdzLCBmYWxzZSwgcmF3VmFsdWVUb0Zvcm1hdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gVGVzdGluZyBmb3IgYGFsbG93RGVjaW1hbFBhZGRpbmcubmV2ZXJgIG9yIGBhbGxvd0RlY2ltYWxQYWRkaW5nLmZsb2F0c2AgaXMgbmVlZGVkIHRvIG1ha2Ugc3VyZSB3ZSBkbyBub3Qga2VlcCBhIHRyYWlsaW5nIGRlY2ltYWxDaGFyYWN0ZXIgKGxpa2UgJzUwMC4nKSBpbiB0aGUgZWxlbWVudCwgc2luY2UgdGhlIHJhdyB2YWx1ZSB3b3VsZCBzdGlsbCBiZSBhIGNvcnJlY3RseSBmb3JtYXR0ZWQgaW50ZWdlciAoJzUwMCcpXG4gICAgICAgICAgICAgICAgaWYgKGdyb3VwZWRWYWx1ZSAhPT0gcmF3VmFsdWVUb0Zvcm1hdCB8fFxuICAgICAgICAgICAgICAgICAgICByYXdWYWx1ZVRvRm9ybWF0ID09PSAnJyB8fCAvLyBUaGlzIG1ha2Ugc3VyZSB3ZSBnZXQgcmlkIG9uIGFueSBjdXJyZW5jeSBzeW1ib2wgb3Igc3VmZml4IHRoYXQgbWlnaHQgaGF2ZSBiZWVuIGFkZGVkIG9uIGZvY3VzXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuYWxsb3dEZWNpbWFsUGFkZGluZyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nLm5ldmVyIHx8XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuYWxsb3dEZWNpbWFsUGFkZGluZyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nLmZsb2F0cykge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5zeW1ib2xXaGVuVW5mb2N1c2VkICYmIHJhd1ZhbHVlVG9Gb3JtYXQgIT09ICcnICYmIHJhd1ZhbHVlVG9Gb3JtYXQgIT09IG51bGwpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGdyb3VwZWRWYWx1ZSA9IGAke2dyb3VwZWRWYWx1ZX0ke3RoaXMuc2V0dGluZ3Muc3ltYm9sV2hlblVuZm9jdXNlZH1gO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0RWxlbWVudFZhbHVlKGdyb3VwZWRWYWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vbkJsdXIoZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVyIGZvciAncGFzdGUnIGV2ZW50XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0V2ZW50fENsaXBib2FyZEV2ZW50fSBlXG4gICAgICovXG4gICAgX29uUGFzdGUoZSkge1xuICAgICAgICAvL0ZJWE1FIFdoZW4gcGFzdGluZyAnMDAwJyBvbiBhIHRob3VzYW5kIGdyb3VwIHNlbGVjdGlvbiwgdGhlIHdob2xlIHNlbGVjdGlvbiBnZXRzIGRlbGV0ZWQsIGFuZCBvbmx5IG9uZSAnMCcgaXMgcGFzdGVkIChjZi4gaXNzdWUgIzMwMilcbiAgICAgICAgLy8gVGhlIGV2ZW50IGlzIHByZXZlbnRlZCBieSBkZWZhdWx0LCBzaW5jZSBvdGhlcndpc2UgdGhlIHVzZXIgd291bGQgYmUgYWJsZSB0byBwYXN0ZSBpbnZhbGlkIGNoYXJhY3RlcnMgaW50byB0aGUgaW5wdXRcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnJlYWRPbmx5IHx8IHRoaXMuZG9tRWxlbWVudC5yZWFkT25seSB8fCB0aGlzLmRvbUVsZW1lbnQuZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIC8vIERvIG5vdCBhbGxvdyBwYXN0aW5nIGluIGEgcmVhZG9ubHkgZWxlbWVudCAoZml4IGlzc3VlICM1MDUpXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmF3UGFzdGVkVGV4dDtcbiAgICAgICAgaWYgKHdpbmRvdy5jbGlwYm9hcmREYXRhICYmIHdpbmRvdy5jbGlwYm9hcmREYXRhLmdldERhdGEpIHtcbiAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSBmb3IgdGhlIG9ic29sZXRlIGFuZCBub24tc3RhbmRhcmQgSUUgYnJvd3NlcnMgMTAgYW5kIDExXG4gICAgICAgICAgICByYXdQYXN0ZWRUZXh0ID0gd2luZG93LmNsaXBib2FyZERhdGEuZ2V0RGF0YSgnVGV4dCcpO1xuICAgICAgICB9IGVsc2UgaWYgKGUuY2xpcGJvYXJkRGF0YSAmJiBlLmNsaXBib2FyZERhdGEuZ2V0RGF0YSkge1xuICAgICAgICAgICAgLy8gTm9ybWFsIGNhc2Ugd2l0aCBtb2Rlcm4gYnJvd3NlcnNcbiAgICAgICAgICAgIHJhd1Bhc3RlZFRleHQgPSBlLmNsaXBib2FyZERhdGEuZ2V0RGF0YSgndGV4dC9wbGFpbicpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcignVW5hYmxlIHRvIHJldHJpZXZlIHRoZSBwYXN0ZWQgdmFsdWUuIFBsZWFzZSB1c2UgYSBtb2Rlcm4gYnJvd3NlciAoaWUuIEZpcmVmb3ggb3IgQ2hyb21pdW0pLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRml4IGZvciBmaXJlZm94IHBhc3RlIGhhbmRsaW5nIG9uIGBjb250ZW50ZWRpdGFibGVgIGVsZW1lbnRzIHdoZXJlIGBlLnRhcmdldGAgaXMgdGhlIHRoZSB0ZXh0IG5vZGUsIG5vdCB0aGUgZWxlbWVudFxuICAgICAgICBsZXQgZXZlbnRUYXJnZXQ7XG4gICAgICAgIGlmICghZS50YXJnZXQudGFnTmFtZSkge1xuICAgICAgICAgICAgZXZlbnRUYXJnZXQgPSBlLmV4cGxpY2l0T3JpZ2luYWxUYXJnZXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBldmVudFRhcmdldCA9IGUudGFyZ2V0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gMC4gU3BlY2lhbCBjYXNlIGlmIHRoZSB1c2VyIGhhcyBzZWxlY3RlZCBhbGwgdGhlIGlucHV0IHRleHQgYmVmb3JlIHBhc3RpbmdcbiAgICAgICAgY29uc3QgaW5pdGlhbEZvcm1hdHRlZFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKGV2ZW50VGFyZ2V0KTtcbiAgICAgICAgY29uc3Qgc2VsZWN0aW9uU3RhcnQgPSBldmVudFRhcmdldC5zZWxlY3Rpb25TdGFydCB8fCAwO1xuICAgICAgICBjb25zdCBzZWxlY3Rpb25FbmQgPSBldmVudFRhcmdldC5zZWxlY3Rpb25FbmQgfHwgMDtcbiAgICAgICAgY29uc3Qgc2VsZWN0aW9uU2l6ZSA9IHNlbGVjdGlvbkVuZCAtIHNlbGVjdGlvblN0YXJ0O1xuXG4gICAgICAgIGlmIChzZWxlY3Rpb25TaXplID09PSBpbml0aWFsRm9ybWF0dGVkVmFsdWUubGVuZ3RoKSB7IC8vIElmIGFsbCB0aGUgZWxlbWVudCB0ZXh0IGlzIHNlbGVjdGVkXG4gICAgICAgICAgICAvL1RPRE8gUmVmYWN0b3IgdGhpcyB3aXRoIHRoZSB0ZXN0cyBiZWxvd1xuICAgICAgICAgICAgLy8gU2luY2UgdGhlIHdob2xlIGVsZW1lbnQgY29udGVudCB3aWxsIGJlIHJlcGxhY2VkLCBubyBuZWVkIHRvIGNvbXBsaWNhdGUgdGhpbmdzIGFuZCBkaXJlY3RseSB0ZXN0IGZvciB0aGUgdmFsaWRpdHkgb2YgdGhlIHBhc3RlZCBjb250ZW50LCB0aGVuIHNldCB0aGUgYHJhd1ZhbHVlYCBhbmQgY2FyZXQgcG9zaXRpb24gKGZpeCBpc3N1ZSAjNDgyKVxuICAgICAgICAgICAgLy8gMS4gU3RyaXAgYWxsIHRob3VzYW5kIHNlcGFyYXRvcnMsIGJyYWNrZXRzIGFuZCBjdXJyZW5jeSBzaWduLCBhbmQgY29udmVydCB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgdG8gYSBkb3RcbiAgICAgICAgICAgIGNvbnN0IHVudHJhbnNsYXRlZFBhc3RlZFRleHQgPSB0aGlzLl9wcmVwYXJlUGFzdGVkVGV4dChyYXdQYXN0ZWRUZXh0KTtcbiAgICAgICAgICAgIGNvbnN0IHBhc3RlZFJhd1ZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuYXJhYmljVG9MYXRpbk51bWJlcnModW50cmFuc2xhdGVkUGFzdGVkVGV4dCwgZmFsc2UsIGZhbHNlLCBmYWxzZSk7IC8vIEFsbG93IHBhc3RpbmcgYXJhYmljIG51bWJlcnNcblxuICAgICAgICAgICAgLy8gMi4gQ2hlY2sgdGhhdCB0aGUgcGFzdGUgaXMgYSB2YWxpZCBudW1iZXIgb25jZSBpdCBoYXMgYmVlbiBub3JtYWxpemVkIHRvIGEgcmF3IHZhbHVlXG4gICAgICAgICAgICBpZiAocGFzdGVkUmF3VmFsdWUgPT09ICcuJyB8fCBwYXN0ZWRSYXdWYWx1ZSA9PT0gJycgfHwgKHBhc3RlZFJhd1ZhbHVlICE9PSAnLicgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzTnVtYmVyKHBhc3RlZFJhd1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmZvcm1hdHRlZCA9IHRydWU7IC8vIFRoaXMgcHJldmVudCB0aGUgYGtleXVwYCBldmVudCBvbiB0aGUgYHZgIGtleSBkdXJpbmcgYSBwYXN0ZSB0byB0cnkgdG8gZm9ybWF0IGFuIGVtcHR5IHZhbHVlLlxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSB1c2VyIHRyaWVzIHRvIHBhc3RlIGEgc2luZ2xlIGRlY2ltYWwgY2hhcmFjdGVyICh0aGF0IGhhcyBiZWVuIHRyYW5zbGF0ZWQgdG8gJy4nIGFscmVhZHkpIG9yIHRoZSBlbXB0eSB2YWx1ZSwgaWdub3JlIHRoZSBwYXN0ZVxuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm9uSW52YWxpZFBhc3RlID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBwYXN0ZWQgdmFsdWUgJyR7cmF3UGFzdGVkVGV4dH0nIGlzIG5vdCBhIHZhbGlkIHBhc3RlIGNvbnRlbnQuYCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyAzLiBUaGVuIHRyeSB0byBzZXQgaXQgYXMgdGhlIG5ldyB2YWx1ZS4gVGhlIGBzZXQoKWAgbWV0aG9kIHdpbGwgcnVuIHRoZSBhZGRpdGlvbmFsIHRlc3RzIChpZS4gbGltaXRzKSBhcyBuZWVkZWQuXG4gICAgICAgICAgICB0aGlzLnNldChwYXN0ZWRSYXdWYWx1ZSk7XG4gICAgICAgICAgICB0aGlzLmZvcm1hdHRlZCA9IHRydWU7XG5cbiAgICAgICAgICAgIC8vIDQuIE9uIGEgJ25vcm1hbCcgbm9uLWF1dG9OdW1lcmljIGlucHV0LCBhbiBgaW5wdXRgIGV2ZW50IGlzIHNlbnQgd2hlbiBhIHBhc3RlIGlzIGRvbmUuIFdlIG1pbWljIHRoYXQuXG4gICAgICAgICAgICB0aGlzLl90cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLm5hdGl2ZS5pbnB1dCwgZXZlbnRUYXJnZXQpO1xuXG4gICAgICAgICAgICAvLyA1LiBSZXR1cm4gc2luY2UgdGhlIGpvYiBpcyBkb25lXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyAxLiBDaGVjayBpZiB0aGUgcGFzdGUgaGFzIGEgbmVnYXRpdmUgc2lnbiAob25seSBpZiBpdCdzIHRoZSBmaXJzdCBjaGFyYWN0ZXIpLCBhbmQgc3RvcmUgdGhhdCBpbmZvcm1hdGlvbiBmb3IgbGF0ZXIgdXNlXG4gICAgICAgIGNvbnN0IGlzUGFzdGVOZWdhdGl2ZSA9IEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmVTdHJpY3QocmF3UGFzdGVkVGV4dCwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpO1xuICAgICAgICBpZiAoaXNQYXN0ZU5lZ2F0aXZlKSB7XG4gICAgICAgICAgICAvLyAxYS4gUmVtb3ZlIHRoZSBuZWdhdGl2ZSBzaWduIGZyb20gdGhlIHBhc3RlZCB0ZXh0XG4gICAgICAgICAgICByYXdQYXN0ZWRUZXh0ID0gcmF3UGFzdGVkVGV4dC5zbGljZSgxLCByYXdQYXN0ZWRUZXh0Lmxlbmd0aCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAyLiBTdHJpcCBhbGwgdGhvdXNhbmQgc2VwYXJhdG9ycywgYnJhY2tldHMgYW5kIGN1cnJlbmN5IHNpZ24sIGFuZCBjb252ZXJ0IHRoZSBkZWNpbWFsIGNoYXJhY3RlciB0byBhIGRvdFxuICAgICAgICBjb25zdCB1bnRyYW5zbGF0ZWRQYXN0ZWRUZXh0ID0gdGhpcy5fcHJlcGFyZVBhc3RlZFRleHQocmF3UGFzdGVkVGV4dCk7XG5cbiAgICAgICAgbGV0IHBhc3RlZFRleHQ7XG4gICAgICAgIGlmICh1bnRyYW5zbGF0ZWRQYXN0ZWRUZXh0ID09PSAnLicpIHtcbiAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSA6IElmIHRoZSB1c2VyIHRyaWVzIHRvIHBhc3RlIGEgc2luZ2xlIGRlY2ltYWwgY2hhcmFjdGVyICh0aGF0IGhhcyBiZWVuIHRyYW5zbGF0ZWQgdG8gJy4nIGFscmVhZHkpXG4gICAgICAgICAgICBwYXN0ZWRUZXh0ID0gJy4nO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gTm9ybWFsIGNhc2VcbiAgICAgICAgICAgIC8vIEFsbG93IHBhc3RpbmcgYXJhYmljIG51bWJlcnNcbiAgICAgICAgICAgIHBhc3RlZFRleHQgPSBBdXRvTnVtZXJpY0hlbHBlci5hcmFiaWNUb0xhdGluTnVtYmVycyh1bnRyYW5zbGF0ZWRQYXN0ZWRUZXh0LCBmYWxzZSwgZmFsc2UsIGZhbHNlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDMuIFRlc3QgaWYgdGhlIHBhc3RlIGlzIHZhbGlkIChvbmx5IGhhcyBudW1iZXJzIGFuZCBldmVudHVhbGx5IGEgZGVjaW1hbCBjaGFyYWN0ZXIpLiBJZiBpdCdzIG5vdCB2YWxpZCwgc3RvcCBoZXJlLlxuICAgICAgICBpZiAocGFzdGVkVGV4dCAhPT0gJy4nICYmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIocGFzdGVkVGV4dCkgfHwgcGFzdGVkVGV4dCA9PT0gJycpKSB7XG4gICAgICAgICAgICB0aGlzLmZvcm1hdHRlZCA9IHRydWU7IC8vIFRoaXMgcHJldmVudCB0aGUgYGtleXVwYCBldmVudCBvbiB0aGUgYHZgIGtleSBkdXJpbmcgYSBwYXN0ZSB0byB0cnkgdG8gZm9ybWF0IGFuIGVtcHR5IHZhbHVlIChmaXggaXNzdWUgIzQ4NClcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm9uSW52YWxpZFBhc3RlID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHBhc3RlZCB2YWx1ZSAnJHtyYXdQYXN0ZWRUZXh0fScgaXMgbm90IGEgdmFsaWQgcGFzdGUgY29udGVudC5gKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gNC4gQ2FsY3VsYXRlIHRoZSBwYXN0ZSByZXN1bHRcbiAgICAgICAgbGV0IGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nO1xuICAgICAgICBsZXQgaXNJbml0aWFsVmFsdWVOZWdhdGl2ZSA9IEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmVTdHJpY3QodGhpcy5nZXROdW1lcmljU3RyaW5nKCksIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKTtcbiAgICAgICAgbGV0IGlzUGFzdGVOZWdhdGl2ZUFuZEluaXRpYWxWYWx1ZUlzUG9zaXRpdmU7XG4gICAgICAgIGxldCByZXN1bHQ7XG5cbiAgICAgICAgLy8gSWYgdGhlIHBhc3RlZCBjb250ZW50IGlzIG5lZ2F0aXZlLCB0aGVuIHRoZSByZXN1bHQgd2lsbCBiZSBuZWdhdGl2ZSB0b29cbiAgICAgICAgaWYgKGlzUGFzdGVOZWdhdGl2ZSAmJiAhaXNJbml0aWFsVmFsdWVOZWdhdGl2ZSkge1xuICAgICAgICAgICAgaXNJbml0aWFsVmFsdWVOZWdhdGl2ZSA9IHRydWU7XG4gICAgICAgICAgICBpc1Bhc3RlTmVnYXRpdmVBbmRJbml0aWFsVmFsdWVJc1Bvc2l0aXZlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlzUGFzdGVOZWdhdGl2ZUFuZEluaXRpYWxWYWx1ZUlzUG9zaXRpdmUgPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBsZWZ0UGFydENvbnRhaW5lZEFEb3QgPSBmYWxzZTtcbiAgICAgICAgbGV0IGxlZnRQYXJ0O1xuICAgICAgICBsZXQgcmlnaHRQYXJ0O1xuICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3Mub25JbnZhbGlkUGFzdGUpIHtcbiAgICAgICAgICAgIC8qIDRhLiBUcnVuY2F0ZSBwYXN0ZSBiZWhhdmlvcjpcbiAgICAgICAgICAgICAqIEluc2VydCBhcyBtYW55IG51bWJlcnMgYXMgcG9zc2libGUgb24gdGhlIHJpZ2h0IGhhbmQgc2lkZSBvZiB0aGUgY2FyZXQgZnJvbSB0aGUgcGFzdGVkIHRleHQgY29udGVudCwgdW50aWwgdGhlIGlucHV0IHJlYWNoIGl0cyByYW5nZSBsaW1pdC5cbiAgICAgICAgICAgICAqIElmIHRoZXJlIGlzIG1vcmUgY2hhcmFjdGVycyBpbiB0aGUgY2xpcGJvYXJkIG9uY2UgYSBsaW1pdCBpcyByZWFjaGVkLCBkcm9wIHRoZSBleHRyYW5lb3VzIGNoYXJhY3RlcnMuXG4gICAgICAgICAgICAgKiBPdGhlcndpc2UgcGFzdGUgYWxsIHRoZSBudW1iZXJzIGluIHRoZSBjbGlwYm9hcmQuXG4gICAgICAgICAgICAgKiBXaGlsZSBkb2luZyBzbywgd2UgY2hlY2sgaWYgdGhlIHJlc3VsdCBpcyB3aXRoaW4gdGhlIG1pbmltdW0gYW5kIG1heGltdW0gdmFsdWVzIGFsbG93ZWQsIGFuZCBzdG9wIGFzIHNvb24gYXMgd2UgZW5jb3VudGVyIG9uZSBvZiB0aG9zZS5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiA0Yi4gUmVwbGFjZSBwYXN0ZSBiZWhhdmlvcjpcbiAgICAgICAgICAgICAqIElkZW0gdGhhbiB0aGUgJ3RydW5jYXRlJyBwYXN0ZSBiZWhhdmlvciwgZXhjZXB0IHRoYXQgd2hlbiBhIHJhbmdlIGxpbWl0IGlzIGhpdCwgd2UgdHJ5IHRvIHJlcGxhY2UgdGhlIHN1YnNlcXVlbnQgaW5pdGlhbCBudW1iZXJzIHdpdGggdGhlIHBhc3RlZCBvbmVzLCB1bnRpbCB3ZSBoaXQgdGhlIHJhbmdlIGxpbWl0IGEgc2Vjb25kIChhbmQgbGFzdCkgdGltZSwgb3Igd2UgcnVuIG91dCBvZiBudW1iZXJzIHRvIHBhc3RlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIC8qIGVzbGludCBuby1jYXNlLWRlY2xhcmF0aW9uczogMCAqL1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLnRydW5jYXRlOlxuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLnJlcGxhY2U6XG4gICAgICAgICAgICAgICAgY29uc3QgbGVmdEZvcm1hdHRlZFBhcnQgPSBpbml0aWFsRm9ybWF0dGVkVmFsdWUuc2xpY2UoMCwgc2VsZWN0aW9uU3RhcnQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJpZ2h0Rm9ybWF0dGVkUGFydCA9IGluaXRpYWxGb3JtYXR0ZWRWYWx1ZS5zbGljZShzZWxlY3Rpb25FbmQsIGluaXRpYWxGb3JtYXR0ZWRWYWx1ZS5sZW5ndGgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHNlbGVjdGlvblN0YXJ0ICE9PSBzZWxlY3Rpb25FbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gYS4gSWYgdGhlcmUgaXMgYSBzZWxlY3Rpb24sIHJlbW92ZSB0aGUgc2VsZWN0ZWQgcGFydCwgYW5kIHJldHVybiB0aGUgbGVmdCBhbmQgcmlnaHQgcGFydFxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLl9wcmVwYXJlUGFzdGVkVGV4dChsZWZ0Rm9ybWF0dGVkUGFydCArIHJpZ2h0Rm9ybWF0dGVkUGFydCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gYi4gRWxzZSBpZiB0aGlzIGlzIG9ubHkgb25lIGNhcmV0IChhbmQgdGhlcmVmb3JlIG5vIHNlbGVjdGlvbiksIHRoZW4gcmV0dXJuIHRoZSBsZWZ0IGFuZCByaWdodCBwYXJ0XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuX3ByZXBhcmVQYXN0ZWRUZXh0KGluaXRpYWxGb3JtYXR0ZWRWYWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQWRkIGJhY2sgdGhlIG5lZ2F0aXZlIHNpZ24gaWYgbmVlZGVkXG4gICAgICAgICAgICAgICAgaWYgKGlzSW5pdGlhbFZhbHVlTmVnYXRpdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIuc2V0UmF3TmVnYXRpdmVTaWduKHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQnVpbGQgdGhlIHVuZm9ybWF0dGVkIHJlc3VsdCBzdHJpbmdcbiAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZyA9IEF1dG9OdW1lcmljSGVscGVyLmNvbnZlcnRDaGFyYWN0ZXJDb3VudFRvSW5kZXhQb3NpdGlvbihBdXRvTnVtZXJpY0hlbHBlci5jb3VudE51bWJlckNoYXJhY3RlcnNPblRoZUNhcmV0TGVmdFNpZGUoaW5pdGlhbEZvcm1hdHRlZFZhbHVlLCBzZWxlY3Rpb25TdGFydCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSk7XG4gICAgICAgICAgICAgICAgaWYgKGlzUGFzdGVOZWdhdGl2ZUFuZEluaXRpYWxWYWx1ZUlzUG9zaXRpdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGluaXRpYWwgcGFzdGUgaXMgbmVnYXRpdmUgYW5kIHRoZSBpbml0aWFsIHZhbHVlIGlzIG5vdCwgdGhlbiBJIG11c3Qgb2Zmc2V0IHRoZSBjYXJldCBwb3NpdGlvbiBieSBvbmUgcGxhY2UgdG8gdGhlIHJpZ2h0IHRvIHRha2UgdGhlIGFkZGl0aW9uYWwgaHlwaGVuIGludG8gYWNjb3VudFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZysrO1xuICAgICAgICAgICAgICAgICAgICAvL1RPRE8gUXVpZCBpZiB0aGUgbmVnYXRpdmUgc2lnbiBpcyBub3Qgb24gdGhlIGxlZnQgKG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50IGFuZCBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCk/XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGVmdFBhcnQgPSByZXN1bHQuc2xpY2UoMCwgY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3RpbmcpO1xuICAgICAgICAgICAgICAgIHJpZ2h0UGFydCA9IHJlc3VsdC5zbGljZShjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZywgcmVzdWx0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgaWYgKHBhc3RlZFRleHQgPT09ICcuJykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMobGVmdFBhcnQsICcuJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIEkgcmVtb3ZlIGEgZG90IGhlcmUsIHRoZW4gSSBuZWVkIHRvIHVwZGF0ZSB0aGUgY2FyZXQgcG9zaXRpb24gKGRlY3JlbWVudCBpdCBieSAxKSB3aGVuIHBvc2l0aW9uaW5nIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUbyBkbyBzbywgd2Uga2VlcCB0aGF0IGluZm8gaW4gb3JkZXIgdG8gbW9kaWZ5IHRoZSBjYXJldCBwb3NpdGlvbiBsYXRlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdFBhcnRDb250YWluZWRBRG90ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnRQYXJ0ID0gbGVmdFBhcnQucmVwbGFjZSgnLicsICcnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0UGFydCA9IHJpZ2h0UGFydC5yZXBsYWNlKCcuJywgJycpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvLyAtLSBIZXJlLCB3ZSBhcmUgZ29vZCB0byBnbyB0byBjb250aW51ZSBvbiB0aGUgc2FtZSBiYXNpc1xuXG4gICAgICAgICAgICAgICAgLy8gYy4gQWRkIG51bWJlcnMgb25lIGJ5IG9uZSBhdCB0aGUgY2FyZXQgcG9zaXRpb24sIHdoaWxlIHRlc3RpbmcgaWYgdGhlIHJlc3VsdCBpcyB2YWxpZCBhbmQgd2l0aGluIHRoZSByYW5nZSBvZiB0aGUgbWluaW11bSBhbmQgbWF4aW11bSB2YWx1ZVxuICAgICAgICAgICAgICAgIC8vICAgIENvbnRpbnVlIHVudGlsIHlvdSBlaXRoZXIgcnVuIG91dCBvZiBudW1iZXJzIHRvIHBhc3RlLCBvciB0aGF0IHlvdSBnZXQgb3V0IG9mIHRoZSByYW5nZSBsaW1pdHNcbiAgICAgICAgICAgICAgICBjb25zdCBtaW5QYXJzZSA9IEF1dG9OdW1lcmljSGVscGVyLnBhcnNlU3RyKHRoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlKTtcbiAgICAgICAgICAgICAgICBjb25zdCBtYXhQYXJzZSA9IEF1dG9OdW1lcmljSGVscGVyLnBhcnNlU3RyKHRoaXMuc2V0dGluZ3MubWF4aW11bVZhbHVlKTtcbiAgICAgICAgICAgICAgICBsZXQgbGFzdEdvb2RLbm93blJlc3VsdCA9IHJlc3VsdDsgLy8gVGhpcyBpcyBzZXQgYXMgdGhlIGRlZmF1bHQsIGluIGNhc2Ugd2UgZG8gbm90IGFkZCBldmVuIG9uZSBudW1iZXJcbiAgICAgICAgICAgICAgICBsZXQgcGFzdGVkVGV4dEluZGV4ID0gMDtcbiAgICAgICAgICAgICAgICBsZXQgbW9kaWZpZWRMZWZ0UGFydCA9IGxlZnRQYXJ0O1xuXG4gICAgICAgICAgICAgICAgd2hpbGUgKHBhc3RlZFRleHRJbmRleCA8IHBhc3RlZFRleHQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE1vZGlmeSB0aGUgcmVzdWx0IHdpdGggYW5vdGhlciBwYXN0ZWQgY2hhcmFjdGVyXG4gICAgICAgICAgICAgICAgICAgIG1vZGlmaWVkTGVmdFBhcnQgKz0gcGFzdGVkVGV4dFtwYXN0ZWRUZXh0SW5kZXhdO1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBtb2RpZmllZExlZnRQYXJ0ICsgcmlnaHRQYXJ0O1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIHRoZSByYW5nZSBsaW1pdHNcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmNvbnN0cnVjdG9yLl9jaGVja0lmSW5SYW5nZShyZXN1bHQsIG1pblBhcnNlLCBtYXhQYXJzZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSByZXN1bHQgaXMgb3V0IG9mIHRoZSByYW5nZSBsaW1pdHMsIHN0b3AgdGhlIGxvb3AgaGVyZVxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBTYXZlIHRoZSBsYXN0IGdvb2Qga25vd24gcmVzdWx0XG4gICAgICAgICAgICAgICAgICAgIGxhc3RHb29kS25vd25SZXN1bHQgPSByZXN1bHQ7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBsb2NhbCB2YXJpYWJsZXMgZm9yIHRoZSBuZXh0IGxvb3BcbiAgICAgICAgICAgICAgICAgICAgcGFzdGVkVGV4dEluZGV4Kys7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBsYXN0IGNhcmV0IHBvc2l0aW9uIHdoZXJlIHRvIGluc2VydCBhIG5ldyBudW1iZXJcbiAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZyArPSBwYXN0ZWRUZXh0SW5kZXg7XG5cbiAgICAgICAgICAgICAgICAvL1hYWCBIZXJlIHdlIGhhdmUgdGhlIHJlc3VsdCBmb3IgdGhlIGB0cnVuY2F0ZWAgb3B0aW9uXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Mub25JbnZhbGlkUGFzdGUgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUudHJ1bmNhdGUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy9UT0RPIElmIHRoZSB1c2VyIGFzIGRlZmluZWQgYSB0cnVuY2F0ZSBjYWxsYmFjayBhbmQgdGhlcmUgYXJlIHN0aWxsIHNvbWUgbnVtYmVycyAodGhhdCB3aWxsIGJlIGRyb3BwZWQpLCB0aGVuIGNhbGwgdGhpcyBjYWxsYmFjayB3aXRoIHRoZSBpbml0aWFsIHBhc3RlIGFzIHdlbGwgYXMgdGhlIHJlbWFpbmluZyBudW1iZXJzXG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGxhc3RHb29kS25vd25SZXN1bHQ7XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxlZnRQYXJ0Q29udGFpbmVkQURvdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBkb3QgaGFzIGJlZW4gcmVtb3ZlZCBmb3IgdGhlIHBhcnQgb24gdGhlIGxlZnQgb2YgdGhlIGNhcmV0LCB3ZSBkZWNyZW1lbnQgdGhlIGNhcmV0IGluZGV4IHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZy0tO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAvL1hYWCAuLi5lbHNlIHdlIG5lZWQgdG8gY29udGludWUgbW9kaWZ5aW5nIHRoZSByZXN1bHQgZm9yIHRoZSAncmVwbGFjZScgb3B0aW9uXG5cbiAgICAgICAgICAgICAgICAvLyBkLiBVbnRpbCB0aGVyZSBhcmUgbnVtYmVycyB0byBwYXN0ZSwgcmVwbGFjZSB0aGUgaW5pdGlhbCBudW1iZXJzIG9uZSBieSBvbmUsIGFuZCBzdGlsbCBkbyB0aGUgcmFuZ2UgdGVzdC5cbiAgICAgICAgICAgICAgICAvLyAgICBTdG9wIHdoZW4geW91IGhhdmUgbm8gbW9yZSBudW1iZXJzIHRvIHBhc3RlLCBvciBpZiB5b3UgYXJlIG91dCBvZiB0aGUgcmFuZ2UgbGltaXRzLlxuICAgICAgICAgICAgICAgIC8vICAgIElmIHlvdSBkbyBnZXQgdG8gdGhlIHJhbmdlIGxpbWl0cywgdXNlIHRoZSBwcmV2aW91cyBrbm93biBnb29kIHZhbHVlIHdpdGhpbiB0aG9zZSBsaW1pdHMuXG4gICAgICAgICAgICAgICAgLy8gICAgTm90ZTogVGhlIG51bWJlcnMgYXJlIHJlcGxhY2VkIG9uZSBieSBvbmUsIGluIHRoZSBpbnRlZ2VyIHRoZW4gZGVjaW1hbCBwYXJ0LCB3aGlsZSBpZ25vcmluZyB0aGUgZGVjaW1hbCBjaGFyYWN0ZXJcbiAgICAgICAgICAgICAgICAvL1RPRE8gV2hhdCBzaG91bGQgaGFwcGVuIGlmIHRoZSB1c2VyIHRyeSB0byBwYXN0ZSBhIGRlY2ltYWwgbnVtYmVyPyBTaG91bGQgd2Ugb3ZlcnJpZGUgdGhlIGN1cnJlbnQgaW5pdGlhbCBkZWNpbWFsIGNoYXJhY3RlciBpbiBmYXZvciBvZiB0aGlzIG5ldyBvbmU/IElmIHdlIGRvLCB0aGVuIHdlIGhhdmUgdG8gcmVjYWxjdWxhdGUgdGhlIHZNaW4vdk1heCBmcm9tIHRoZSBzdGFydCBpbiBvcmRlciB0byB0YWtlIGludG8gYWNjb3VudCB0aGlzIG5ldyBkZWNpbWFsIGNoYXJhY3RlciBwb3NpdGlvbi4uXG4gICAgICAgICAgICAgICAgbGV0IGxhc3RHb29kS25vd25SZXN1bHRJbmRleCA9IGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nO1xuICAgICAgICAgICAgICAgIGNvbnN0IGxhc3RHb29kS25vd25SZXN1bHRTaXplID0gbGFzdEdvb2RLbm93blJlc3VsdC5sZW5ndGg7XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAocGFzdGVkVGV4dEluZGV4IDwgcGFzdGVkVGV4dC5sZW5ndGggJiYgbGFzdEdvb2RLbm93blJlc3VsdEluZGV4IDwgbGFzdEdvb2RLbm93blJlc3VsdFNpemUpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGxhc3RHb29kS25vd25SZXN1bHRbbGFzdEdvb2RLbm93blJlc3VsdEluZGV4XSA9PT0gJy4nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBXZSBza2lwIHRoZSBkZWNpbWFsIGNoYXJhY3RlciAncmVwbGFjZW1lbnQnLiBUaGF0IHdheSwgd2UgZG8gbm90IGNoYW5nZSB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgcG9zaXRpb24gcmVnYXJkaW5nIHRoZSByZW1haW5pbmcgbnVtYmVycy5cbiAgICAgICAgICAgICAgICAgICAgICAgIGxhc3RHb29kS25vd25SZXN1bHRJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHJlcGxhY2Ugb25lIGNoYXJhY3RlciBhdCBhIHRpbWVcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIucmVwbGFjZUNoYXJBdChsYXN0R29vZEtub3duUmVzdWx0LCBsYXN0R29vZEtub3duUmVzdWx0SW5kZXgsIHBhc3RlZFRleHRbcGFzdGVkVGV4dEluZGV4XSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgdGhlIHJhbmdlIGxpbWl0c1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29uc3RydWN0b3IuX2NoZWNrSWZJblJhbmdlKHJlc3VsdCwgbWluUGFyc2UsIG1heFBhcnNlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIHJlc3VsdCBpcyBvdXQgb2YgdGhlIHJhbmdlIGxpbWl0cywgc3RvcCB0aGUgbG9vcCBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFNhdmUgdGhlIGxhc3QgZ29vZCBrbm93biByZXN1bHRcbiAgICAgICAgICAgICAgICAgICAgbGFzdEdvb2RLbm93blJlc3VsdCA9IHJlc3VsdDtcblxuICAgICAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGxvY2FsIHZhcmlhYmxlcyBmb3IgdGhlIG5leHQgbG9vcFxuICAgICAgICAgICAgICAgICAgICBwYXN0ZWRUZXh0SW5kZXgrKztcbiAgICAgICAgICAgICAgICAgICAgbGFzdEdvb2RLbm93blJlc3VsdEluZGV4Kys7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBsYXN0IGNhcmV0IHBvc2l0aW9uIHdoZXJlIHRvIGluc2VydCBhIG5ldyBudW1iZXJcbiAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZyA9IGxhc3RHb29kS25vd25SZXN1bHRJbmRleDtcblxuICAgICAgICAgICAgICAgIGlmIChsZWZ0UGFydENvbnRhaW5lZEFEb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBkb3QgaGFzIGJlZW4gcmVtb3ZlZCBmb3IgdGhlIHBhcnQgb24gdGhlIGxlZnQgb2YgdGhlIGNhcmV0LCB3ZSBkZWNyZW1lbnQgdGhlIGNhcmV0IGluZGV4IHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nLS07XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gbGFzdEdvb2RLbm93blJlc3VsdDtcblxuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgLyogNGMuIE5vcm1hbCBwYXN0ZSBiZWhhdmlvcjpcbiAgICAgICAgICAgICAqIEluc2VydCB0aGUgcGFzdGVkIG51bWJlciBpbnNpZGUgdGhlIGN1cnJlbnQgdW5mb3JtYXR0ZWQgdGV4dCwgYXQgdGhlIHJpZ2h0IGNhcmV0IHBvc2l0aW9uIG9yIHNlbGVjdGlvblxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuZXJyb3I6XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuaWdub3JlOlxuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmNsYW1wOlxuICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAvLyAxLiBHZW5lcmF0ZSB0aGUgdW5mb3JtYXR0ZWQgcmVzdWx0XG4gICAgICAgICAgICAgICAgY29uc3QgbGVmdEZvcm1hdHRlZFBhcnQyID0gaW5pdGlhbEZvcm1hdHRlZFZhbHVlLnNsaWNlKDAsIHNlbGVjdGlvblN0YXJ0KTtcbiAgICAgICAgICAgICAgICBjb25zdCByaWdodEZvcm1hdHRlZFBhcnQyID0gaW5pdGlhbEZvcm1hdHRlZFZhbHVlLnNsaWNlKHNlbGVjdGlvbkVuZCwgaW5pdGlhbEZvcm1hdHRlZFZhbHVlLmxlbmd0aCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoc2VsZWN0aW9uU3RhcnQgIT09IHNlbGVjdGlvbkVuZCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBhLiBJZiB0aGVyZSBpcyBhIHNlbGVjdGlvbiwgcmVtb3ZlIHRoZSBzZWxlY3RlZCBwYXJ0LCBhbmQgcmV0dXJuIHRoZSBsZWZ0IGFuZCByaWdodCBwYXJ0XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuX3ByZXBhcmVQYXN0ZWRUZXh0KGxlZnRGb3JtYXR0ZWRQYXJ0MiArIHJpZ2h0Rm9ybWF0dGVkUGFydDIpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGIuIEVsc2UgaWYgdGhpcyBpcyBvbmx5IG9uZSBjYXJldCAoYW5kIHRoZXJlZm9yZSBubyBzZWxlY3Rpb24pLCB0aGVuIHJldHVybiB0aGUgbGVmdCBhbmQgcmlnaHQgcGFydFxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLl9wcmVwYXJlUGFzdGVkVGV4dChpbml0aWFsRm9ybWF0dGVkVmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEFkZCBiYWNrIHRoZSBuZWdhdGl2ZSBzaWduIGlmIG5lZWRlZFxuICAgICAgICAgICAgICAgIGlmIChpc0luaXRpYWxWYWx1ZU5lZ2F0aXZlKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljSGVscGVyLnNldFJhd05lZ2F0aXZlU2lnbihyZXN1bHQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIEJ1aWxkIHRoZSB1bmZvcm1hdHRlZCByZXN1bHQgc3RyaW5nXG4gICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3RpbmcgPSBBdXRvTnVtZXJpY0hlbHBlci5jb252ZXJ0Q2hhcmFjdGVyQ291bnRUb0luZGV4UG9zaXRpb24oQXV0b051bWVyaWNIZWxwZXIuY291bnROdW1iZXJDaGFyYWN0ZXJzT25UaGVDYXJldExlZnRTaWRlKGluaXRpYWxGb3JtYXR0ZWRWYWx1ZSwgc2VsZWN0aW9uU3RhcnQsIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlcikpO1xuICAgICAgICAgICAgICAgIGlmIChpc1Bhc3RlTmVnYXRpdmVBbmRJbml0aWFsVmFsdWVJc1Bvc2l0aXZlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBpbml0aWFsIHBhc3RlIGlzIG5lZ2F0aXZlIGFuZCB0aGUgaW5pdGlhbCB2YWx1ZSBpcyBub3QsIHRoZW4gSSBtdXN0IG9mZnNldCB0aGUgY2FyZXQgcG9zaXRpb24gYnkgb25lIHBsYWNlIHRvIHRoZSByaWdodCB0byB0YWtlIHRoZSBhZGRpdGlvbmFsIGh5cGhlbiBpbnRvIGFjY291bnRcbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3RpbmcrKztcbiAgICAgICAgICAgICAgICAgICAgLy9UT0RPIFF1aWQgaWYgdGhlIG5lZ2F0aXZlIHNpZ24gaXMgbm90IG9uIHRoZSBsZWZ0IChuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCBhbmQgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQpP1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGxlZnRQYXJ0ID0gcmVzdWx0LnNsaWNlKDAsIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nKTtcbiAgICAgICAgICAgICAgICByaWdodFBhcnQgPSByZXN1bHQuc2xpY2UoY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3RpbmcsIHJlc3VsdC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIGlmIChwYXN0ZWRUZXh0ID09PSAnLicpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIHVzZXIgb25seSBwYXN0ZSBhIHNpbmdsZSBkZWNpbWFsIGNoYXJhY3RlciwgdGhlbiB3ZSByZW1vdmUgdGhlIHByZXZpb3VzbHkgZXhpc3Rpbmcgb25lIChpZiBhbnkpXG4gICAgICAgICAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhsZWZ0UGFydCwgJy4nKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgSSByZW1vdmUgYSBkb3QgaGVyZSwgdGhlbiBJIG5lZWQgdG8gdXBkYXRlIHRoZSBjYXJldCBwb3NpdGlvbiAoZGVjcmVtZW50IGl0IGJ5IDEpIHdoZW4gcG9zaXRpb25pbmcgaXRcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRvIGRvIHNvLCB3ZSBrZWVwIHRoYXQgaW5mbyBpbiBvcmRlciB0byBtb2RpZnkgdGhlIGNhcmV0IHBvc2l0aW9uIGxhdGVyXG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0UGFydENvbnRhaW5lZEFEb3QgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdFBhcnQgPSBsZWZ0UGFydC5yZXBsYWNlKCcuJywgJycpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgcmlnaHRQYXJ0ID0gcmlnaHRQYXJ0LnJlcGxhY2UoJy4nLCAnJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIC0tIEhlcmUsIHdlIGFyZSBnb29kIHRvIGdvIHRvIGNvbnRpbnVlIG9uIHRoZSBzYW1lIGJhc2lzXG5cbiAgICAgICAgICAgICAgICAvLyBHZW5lcmF0ZSB0aGUgdW5mb3JtYXR0ZWQgcmVzdWx0XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gYCR7bGVmdFBhcnR9JHtwYXN0ZWRUZXh0fSR7cmlnaHRQYXJ0fWA7XG5cbiAgICAgICAgICAgICAgICAvLyAyLiBDYWxjdWxhdGUgdGhlIGNhcmV0IHBvc2l0aW9uIGluIHRoZSB1bmZvcm1hdHRlZCB2YWx1ZSwgZm9yIGxhdGVyIHVzZVxuICAgICAgICAgICAgICAgIGlmIChzZWxlY3Rpb25TdGFydCA9PT0gc2VsZWN0aW9uRW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGlzIG5vIHNlbGVjdGlvbiwgdGhlbiB0aGUgY2FyZXQgcG9zaXRpb24gaXMgc2V0IGFmdGVyIHRoZSBwYXN0ZWQgdGV4dFxuICAgICAgICAgICAgICAgICAgICBjb25zdCBpbmRleFdoZXJlUGFzdGVkVGV4dEhhc0JlZW5JbnNlcnRlZCA9IEF1dG9OdW1lcmljSGVscGVyLmNvbnZlcnRDaGFyYWN0ZXJDb3VudFRvSW5kZXhQb3NpdGlvbihBdXRvTnVtZXJpY0hlbHBlci5jb3VudE51bWJlckNoYXJhY3RlcnNPblRoZUNhcmV0TGVmdFNpZGUoaW5pdGlhbEZvcm1hdHRlZFZhbHVlLCBzZWxlY3Rpb25TdGFydCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSk7XG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nID0gaW5kZXhXaGVyZVBhc3RlZFRleHRIYXNCZWVuSW5zZXJ0ZWQgKyBwYXN0ZWRUZXh0Lmxlbmd0aDsgLy8gSSBtdXN0IG5vdCBjb3VudCB0aGUgY2hhcmFjdGVycyB0aGF0IGhhdmUgYmVlbiByZW1vdmVkIGZyb20gdGhlIHBhc3RlZCB0ZXh0IChpZS4gJy4nKVxuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocmlnaHRQYXJ0ID09PSAnJykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgdXNlciBzZWxlY3RlZCBmcm9tIHRoZSBjYXJldCBwb3NpdGlvbiB0byB0aGUgZW5kIG9mIHRoZSBpbnB1dCAob24gdGhlIGZhciByaWdodClcbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3RpbmcgPSBBdXRvTnVtZXJpY0hlbHBlci5jb252ZXJ0Q2hhcmFjdGVyQ291bnRUb0luZGV4UG9zaXRpb24oQXV0b051bWVyaWNIZWxwZXIuY291bnROdW1iZXJDaGFyYWN0ZXJzT25UaGVDYXJldExlZnRTaWRlKGluaXRpYWxGb3JtYXR0ZWRWYWx1ZSwgc2VsZWN0aW9uU3RhcnQsIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlcikpICsgcGFzdGVkVGV4dC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTm9ybWFsIGNhc2VcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaW5kZXhTZWxlY3Rpb25FbmRJblJhd1ZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuY29udmVydENoYXJhY3RlckNvdW50VG9JbmRleFBvc2l0aW9uKEF1dG9OdW1lcmljSGVscGVyLmNvdW50TnVtYmVyQ2hhcmFjdGVyc09uVGhlQ2FyZXRMZWZ0U2lkZShpbml0aWFsRm9ybWF0dGVkVmFsdWUsIHNlbGVjdGlvbkVuZCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSGVyZSBJIG11c3Qgbm90IGNvdW50IHRoZSBjaGFyYWN0ZXJzIHRoYXQgaGF2ZSBiZWVuIHJlbW92ZWQgZnJvbSB0aGUgcGFzdGVkIHRleHQgKGllLiAnLicpLCBvciB0aGUgdGhvdXNhbmQgc2VwYXJhdG9ycyBpbiB0aGUgaW5pdGlhbCBzZWxlY3RlZCB0ZXh0XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGVkVGV4dCA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZShldmVudFRhcmdldCkuc2xpY2Uoc2VsZWN0aW9uU3RhcnQsIHNlbGVjdGlvbkVuZCk7XG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nID0gaW5kZXhTZWxlY3Rpb25FbmRJblJhd1ZhbHVlIC0gc2VsZWN0aW9uU2l6ZSArIEF1dG9OdW1lcmljSGVscGVyLmNvdW50Q2hhckluVGV4dCh0aGlzLnNldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3IsIHNlbGVjdGVkVGV4dCkgKyBwYXN0ZWRUZXh0Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBNb2RpZnkgdGhlIGNhcmV0IHBvc2l0aW9uIGZvciBzcGVjaWFsIGNhc2VzLCBvbmx5IGlmIHRoZSB3aG9sZSBpbnB1dCBoYXMgbm90IGJlZW4gc2VsZWN0ZWRcbiAgICAgICAgICAgICAgICBpZiAoaXNQYXN0ZU5lZ2F0aXZlQW5kSW5pdGlhbFZhbHVlSXNQb3NpdGl2ZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgcGFzdGVkIHZhbHVlIGhhcyBhIG5lZ2F0aXZlIHNpZ24gKCctJyksIGJ1dCB0aGUgaW5pdGlhbCB2YWx1ZSBkb2VzIG5vdCwgb2Zmc2V0IHRoZSBpbmRleCBieSBvbmVcbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3RpbmcrKztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAobGVmdFBhcnRDb250YWluZWRBRG90KSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIGEgZG90IGhhcyBiZWVuIHJlbW92ZWQgZm9yIHRoZSBwYXJ0IG9uIHRoZSBsZWZ0IG9mIHRoZSBjYXJldCwgd2UgZGVjcmVtZW50IHRoZSBjYXJldCBpbmRleCBwb3NpdGlvblxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZy0tO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDUuIENoZWNrIGlmIHRoZSByZXN1bHQgaXMgYSB2YWxpZCBudW1iZXIsIGlmIG5vdCwgZHJvcCB0aGUgcGFzdGUgYW5kIGRvIG5vdGhpbmcuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIocmVzdWx0KSB8fCByZXN1bHQgPT09ICcnKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5vbkludmFsaWRQYXN0ZSA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5lcnJvcikge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBwYXN0ZWQgdmFsdWUgJyR7cmF3UGFzdGVkVGV4dH0nIHdvdWxkIHJlc3VsdCBpbnRvIGFuIGludmFsaWQgY29udGVudCAnJHtyZXN1bHR9Jy5gKTsgLy9UT0RPIFNob3VsZCB3ZSBzZW5kIGEgd2FybmluZyBpbnN0ZWFkIG9mIHRocm93aW5nIGFuIGVycm9yP1xuICAgICAgICAgICAgICAgIC8vVE9ETyBUaGlzIGlzIG5vdCBEUlkgOyByZWZhY3RvciB3aXRoIGFib3ZlXG4gICAgICAgICAgICB9XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyA2LiBJZiBpdCdzIGEgdmFsaWQgbnVtYmVyLCBjaGVjayBpZiBpdCBmYWxscyBpbnNpZGUgdGhlIG1pbmltdW0gYW5kIG1heGltdW0gdmFsdWUuIElmIHRoaXMgZmFpbHMsIG1vZGlmeSB0aGUgdmFsdWUgZm9sbG93aW5nIHRoaXMgcHJvY2VkdXJlIDpcbiAgICAgICAgLypcbiAgICAgICAgICogSWYgJ2Vycm9yJyAodGhpcyBpcyB0aGUgZGVmYXVsdCkgOlxuICAgICAgICAgKiAgICAgIC0gTm9ybWFsIHBhc3RlIGJlaGF2aW9yLlxuICAgICAgICAgKiAgICAgIC0gVHJ5IHRvIHNldCB0aGUgbmV3IHZhbHVlLCBpZiBpdCBmYWlscywgdGhlbiB0aHJvdyBhbiBlcnJvciBpbiB0aGUgY29uc29sZS5cbiAgICAgICAgICogICAgICAtIERvIG5vdCBjaGFuZ2UgdGhlIGlucHV0IHZhbHVlLCBkbyBub3QgY2hhbmdlIHRoZSBjdXJyZW50IHNlbGVjdGlvbi5cbiAgICAgICAgICogSWYgJ2lnbm9yZScgOlxuICAgICAgICAgKiAgICAgIC0gTm9ybWFsIHBhc3RlIGJlaGF2aW9yLlxuICAgICAgICAgKiAgICAgIC0gVHJ5IHRvIHNldCB0aGUgbmV3IHZhbHVlLCBpZiBpdCBmYWlscywgZG8gbm90aGluZyBtb3JlLlxuICAgICAgICAgKiAgICAgIC0gRG8gbm90IGNoYW5nZSB0aGUgaW5wdXQgdmFsdWUsIGRvIG5vdCBjaGFuZ2UgdGhlIGN1cnJlbnQgc2VsZWN0aW9uLlxuICAgICAgICAgKiBJZiAnY2xhbXAnIDpcbiAgICAgICAgICogICAgICAtIE5vcm1hbCBwYXN0ZSBiZWhhdmlvci5cbiAgICAgICAgICogICAgICAtIFRyeSB0byBzZXQgdGhlIG5ldyB2YWx1ZSwgaWYgaXQgZmFpbHMsIHNldCB0aGUgdmFsdWUgdG8gdGhlIG1pbmltdW0gb3IgbWF4aW11bSBsaW1pdCwgd2hpY2hldmVyIGlzIGNsb3Nlc3QgdG8gdGhlXG4gICAgICAgICAqICAgICAgICBwYXN0ZSByZXN1bHQuXG4gICAgICAgICAqICAgICAgLSBDaGFuZ2UgdGhlIGNhcmV0IHBvc2l0aW9uIHRvIGJlIHBvc2l0aW9uZWQgb24gdGhlIGxlZnQgaGFuZCBzaWRlIG9mIHRoZSBkZWNpbWFsIGNoYXJhY3Rlci5cbiAgICAgICAgICogSWYgJ3RydW5jYXRlJyA6XG4gICAgICAgICAqICAgICAgLSBUcnVuY2F0ZSBwYXN0ZSBiZWhhdmlvci5cbiAgICAgICAgICogICAgICAtIFRyeSB0byBzZXQgdGhlIG5ldyB2YWx1ZSwgdW50aWwgaXQgZmFpbHMgKGlmIHRoZSByZXN1bHQgaXMgb3V0IG9mIHRoZSBtaW4gYW5kIG1heCB2YWx1ZSBsaW1pdHMpLlxuICAgICAgICAgKiAgICAgIC0gRHJvcCB0aGUgcmVtYWluaW5nIG5vbi1wYXN0ZWQgbnVtYmVycywgYW5kIGtlZXAgdGhlIGxhc3Qga25vd24gbm9uLWZhaWxpbmcgcmVzdWx0LlxuICAgICAgICAgKiAgICAgIC0gQ2hhbmdlIHRoZSBjYXJldCBwb3NpdGlvbiB0byBiZSBwb3NpdGlvbmVkIGFmdGVyIHRoZSBsYXN0IHBhc3RlZCBjaGFyYWN0ZXIuXG4gICAgICAgICAqIElmICdyZXBsYWNlJyA6XG4gICAgICAgICAqICAgICAgLSBSZXBsYWNlIHBhc3RlIGJlaGF2aW9yLlxuICAgICAgICAgKiAgICAgIC0gVHJ5IHRvIHNldCB0aGUgbmV3IHZhbHVlLCB1bnRpbCBpdCBmYWlscyAoaWYgdGhlIHJlc3VsdCBpcyBvdXQgb2YgdGhlIG1pbiBhbmQgbWF4IHZhbHVlIGxpbWl0cykuXG4gICAgICAgICAqICAgICAgLSBUaGVuIHRyeSB0byByZXBsYWNlIGFzIG1hbnkgbnVtYmVycyBhcyBwb3NzaWJsZSB3aXRoIHRoZSBwYXN0ZWQgb25lcy4gT25jZSBpdCBmYWlscywga2VlcCB0aGUgbGFzdCBrbm93biBub24tZmFpbGluZyByZXN1bHQuXG4gICAgICAgICAqICAgICAgLSBDaGFuZ2UgdGhlIGNhcmV0IHBvc2l0aW9uIHRvIGJlIHBvc2l0aW9uZWQgYWZ0ZXIgdGhlIGxhc3QgcGFzdGVkIGNoYXJhY3Rlci5cbiAgICAgICAgICovXG4gICAgICAgIGxldCB2YWx1ZUhhc0JlZW5TZXQgPSBmYWxzZTtcbiAgICAgICAgbGV0IHZhbHVlSGFzQmVlbkNsYW1wZWQgPSBmYWxzZTtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMuc2V0KHJlc3VsdCk7XG4gICAgICAgICAgICB2YWx1ZUhhc0JlZW5TZXQgPSB0cnVlO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgbGV0IGNsYW1wZWRWYWx1ZTtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5vbkludmFsaWRQYXN0ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5jbGFtcDpcbiAgICAgICAgICAgICAgICAgICAgY2xhbXBlZFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuY2xhbXBUb1JhbmdlTGltaXRzKHJlc3VsdCwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldChjbGFtcGVkVmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgRmF0YWwgZXJyb3I6IFVuYWJsZSB0byBzZXQgdGhlIGNsYW1wZWQgdmFsdWUgJyR7Y2xhbXBlZFZhbHVlfScuYCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YWx1ZUhhc0JlZW5DbGFtcGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVIYXNCZWVuU2V0ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gY2xhbXBlZFZhbHVlOyAvLyBUaGlzIGlzIHVzZWQgb25seSBmb3Igc2V0dGluZyB0aGUgY2FyZXQgcG9zaXRpb24gbGF0ZXJcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmVycm9yOlxuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS50cnVuY2F0ZTpcbiAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUucmVwbGFjZTpcbiAgICAgICAgICAgICAgICAgICAgLy8gVGhyb3cgYW4gZXJyb3IgbWVzc2FnZVxuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgcGFzdGVkIHZhbHVlICcke3Jhd1Bhc3RlZFRleHR9JyByZXN1bHRzIGluIGEgdmFsdWUgJyR7cmVzdWx0fScgdGhhdCBpcyBvdXRzaWRlIG9mIHRoZSBtaW5pbXVtIFske3RoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlfV0gYW5kIG1heGltdW0gWyR7dGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWV9XSB2YWx1ZSByYW5nZS5gKTtcbiAgICAgICAgICAgICAgICAvLyBmYWxscyB0aHJvdWdoXG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmlnbm9yZTpcbiAgICAgICAgICAgICAgICAvLyBEbyBub3RoaW5nXG4gICAgICAgICAgICAgICAgLy8gZmFsbHMgdGhyb3VnaFxuICAgICAgICAgICAgICAgIGRlZmF1bHQgOlxuICAgICAgICAgICAgICAgICAgICByZXR1cm47IC8vIC4uLmFuZCBub3RoaW5nIGVsc2Ugc2hvdWxkIGJlIGNoYW5nZWRcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDcuIFRoZW4gbGFzdGx5LCBzZXQgdGhlIGNhcmV0IHBvc2l0aW9uIGF0IHRoZSByaWdodCBsb2dpY2FsIHBsYWNlXG4gICAgICAgIGNvbnN0IHRhcmdldFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKGV2ZW50VGFyZ2V0KTtcbiAgICAgICAgbGV0IGNhcmV0UG9zaXRpb25JbkZvcm1hdHRlZE51bWJlcjtcbiAgICAgICAgaWYgKHZhbHVlSGFzQmVlblNldCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm9uSW52YWxpZFBhc3RlKSB7XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmNsYW1wOlxuICAgICAgICAgICAgICAgICAgICBpZiAodmFsdWVIYXNCZWVuQ2xhbXBlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbihldmVudFRhcmdldCwgdGFyZ2V0VmFsdWUubGVuZ3RoIC0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGgpOyAvLyBUaGlzIHB1dHMgdGhlIGNhcmV0IG9uIHRoZSByaWdodCBvZiB0aGUgbGFzdCBkZWNpbWFsIHBsYWNlXG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24oZXZlbnRUYXJnZXQsIHRhcmdldFZhbHVlLmxlbmd0aCk7IC8vIC4uYW5kIHRoaXMgb24gdGhlIGZhciByaWdodFxuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfSAvLyBlbHNlIGlmIHRoZSB2YWx1ZSBoYXMgbm90IGJlZW4gY2xhbXBlZCwgdGhlIGRlZmF1bHQgYmVoYXZpb3IgaXMgdXNlZC4uLlxuICAgICAgICAgICAgICAgIC8vIGZhbGxzIHRocm91Z2hcbiAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuZXJyb3I6XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmlnbm9yZTpcbiAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUudHJ1bmNhdGU6XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLnJlcGxhY2U6XG4gICAgICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgICAgIC8vIFdoZW5ldmVyIG9uZSBvciBtdWx0aXBsZSBjaGFyYWN0ZXJzIGFyZSBwYXN0ZWQsIHRoaXMgbWVhbnMgd2UgaGF2ZSB0byBtYW5hZ2UgdGhlIHBvdGVudGlhbCB0aG91c2FuZCBzZXBhcmF0b3JzIHRoYXQgY291bGQgYmUgYWRkZWQgYnkgdGhlIGZvcm1hdHRpbmdcbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbkluRm9ybWF0dGVkTnVtYmVyID0gQXV0b051bWVyaWNIZWxwZXIuZmluZENhcmV0UG9zaXRpb25JbkZvcm1hdHRlZE51bWJlcihyZXN1bHQsIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nLCB0YXJnZXRWYWx1ZSwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKTtcbiAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbihldmVudFRhcmdldCwgY2FyZXRQb3NpdGlvbkluRm9ybWF0dGVkTnVtYmVyKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDguIFdlIG1ha2Ugc3VyZSB3ZSBzZW5kIGFuIGlucHV0IGV2ZW50IG9ubHkgaWYgdGhlIHJlc3VsdCBpcyBkaWZmZXJlbnQgdGhhbiB0aGUgaW5pdGlhbCB2YWx1ZSBiZWZvcmUgdGhlIHBhc3RlXG4gICAgICAgIGlmICh2YWx1ZUhhc0JlZW5TZXQgJiYgaW5pdGlhbEZvcm1hdHRlZFZhbHVlICE9PSB0YXJnZXRWYWx1ZSkge1xuICAgICAgICAgICAgLy8gT24gYSAnbm9ybWFsJyBub24tYXV0b051bWVyaWMgaW5wdXQsIGFuIGBpbnB1dGAgZXZlbnQgaXMgc2VudCB3aGVuIGEgcGFzdGUgaXMgZG9uZS4gV2UgbWltaWMgdGhhdC5cbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubmF0aXZlLmlucHV0LCBldmVudFRhcmdldCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXaGVuIGZvY3VzaW5nIG91dCBvZiB0aGUgaW5wdXQsIHdlIGNoZWNrIGlmIHRoZSB2YWx1ZSBoYXMgY2hhbmdlZCwgYW5kIGlmIGl0IGhhcywgdGhlbiB3ZSBzZW5kIGEgYGNoYW5nZWAgZXZlbnQgKHNpbmNlIHRoZSBuYXRpdmUgb25lIHdvdWxkIGhhdmUgYmVlbiBwcmV2ZW50ZWQgYnkgYGUucHJldmVudERlZmF1bHQoKWAgY2FsbGVkIGluIHRoZSBvdGhlciBldmVudCBsaXN0ZW5lcnMpLlxuICAgICAqIFdlIGFsc28gdXBkYXRlIHRoZSBpbmZvIG9mIHRoZSBmb2N1c2VkIHN0YXRlIGluIHRoZSBgdGhpcy5pc0ZvY3VzZWRgIHZhcmlhYmxlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqL1xuICAgIF9vbkJsdXIoZSkge1xuICAgICAgICAvLyBLZWVwIHRyYWNrIGlmIHRoZSBlbGVtZW50IGlzIGN1cnJlbnRseSBmb2N1c2VkXG4gICAgICAgIHRoaXMuaXNGb2N1c2VkID0gZmFsc2U7XG4gICAgICAgIC8vIEtlZXAgdHJhY2sgaWYgdGhlIHVzZXIgaXMgY3VycmVudGx5IGVkaXRpbmcgdGhlIGVsZW1lbnRcbiAgICAgICAgdGhpcy5pc0VkaXRpbmcgPSBmYWxzZTtcblxuICAgICAgICAvLyBTZW5kIGEgYGNoYW5nZWAgZXZlbnQgaWYgdGhlIHJhdyB2YWx1ZSBoYXMgYmVlbiBjaGFuZ2VkIHNpbmNlIHRoZSBsYXN0IGZvY3VzIG9yICdlbnRlcicgdmFsaWRhdGlvblxuICAgICAgICBpZiAodGhpcy5yYXdWYWx1ZSAhPT0gdGhpcy5yYXdWYWx1ZU9uRm9jdXMpIHtcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubmF0aXZlLmNoYW5nZSwgZS50YXJnZXQpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5yYXdWYWx1ZU9uRm9jdXMgPSB2b2lkKDApOyAvLyBSZXNldCB0aGUgdHJhY2tlclxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yICd3aGVlbCcgZXZlbnRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7V2hlZWxFdmVudH0gZVxuICAgICAqL1xuICAgIF9vbldoZWVsKGUpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MucmVhZE9ubHkgfHwgdGhpcy5kb21FbGVtZW50LnJlYWRPbmx5IHx8IHRoaXMuZG9tRWxlbWVudC5kaXNhYmxlZCkge1xuICAgICAgICAgICAgLy8gRG8gbm90IGFsbG93IHNjcm9sbGluZyBpbiBhIHJlYWRvbmx5IGVsZW1lbnQgKGZpeCBpc3N1ZSAjNTQxKVxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubW9kaWZ5VmFsdWVPbldoZWVsKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy53aGVlbE9uID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLndoZWVsT24uZm9jdXMpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5pc0ZvY3VzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLndoZWVsQWN0aW9uKGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMud2hlZWxBY3Rpb24oZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNldHRpbmdzLndoZWVsT24gPT09IEF1dG9OdW1lcmljLm9wdGlvbnMud2hlZWxPbi5ob3Zlcikge1xuICAgICAgICAgICAgICAgIGlmICghZS5zaGlmdEtleSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLndoZWVsQWN0aW9uKGUpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIE5vdGU6IFdoZW4gbm90IGBkZWZhdWx0UHJldmVudGVkYCwgU2hpZnQgKyBtb3VzZSB3aGVlbCBpcyByZXNlcnZlZCBieSB0aGUgYnJvd3NlcnMgZm9yIGhvcml6b250YWwgc2Nyb2xsaW5nLlxuICAgICAgICAgICAgICAgICAgICAvLyBIZW5jZSwgdXNpbmcgdGhlIFNoaWZ0IGtleSB3aXRoIHRoZSBgd2hlZWxPbmAgJ2hvdmVyJyBvcHRpb24gd2lsbCBvbmx5IHNjcm9sbCB0aGUgcGFnZSBpZiB3ZSBwcmV2ZW50IHRoZSBkZWZhdWx0IGJlaGF2aW9yXG4gICAgICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTsgLy8gRG8gbm90IHNjcm9sbCBob3Jpem9udGFsbHlcblxuICAgICAgICAgICAgICAgICAgICAvLyBTY3JvbGwgdmVydGljYWxseVxuICAgICAgICAgICAgICAgICAgICB3aW5kb3cuc2Nyb2xsQnkoMCwgQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZVN0cmljdChTdHJpbmcoZS5kZWx0YVkpKT8tNTA6NTApOyAvLyBgZS5kZWx0YVlgIGlzIHVzdWFsbHkgdG9vIHNtYWxsIGNvbXBhcmVkIHRvIGhvdyB0aGUgcGFnZSBpcyBzY3JvbGxlZC4gVGhhdCdzIHdoeSB3ZSB1c2UgYSBmaXhlZCBvZmZzZXQuXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKCdVbmtub3duIGB3aGVlbE9uYCBvcHRpb24uJyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbmNyZW1lbnQgb3IgZGVjcmVtZW50IHRoZSBlbGVtZW50IHZhbHVlIGFjY29yZGluZyB0byB0aGUgYHdoZWVsU3RlcGAgb3B0aW9uIGNob3NlblxuICAgICAqXG4gICAgICogQHBhcmFtIHtXaGVlbEV2ZW50fSBlIFRoZSBgd2hlZWxgIGV2ZW50XG4gICAgICovXG4gICAgd2hlZWxBY3Rpb24oZSkge1xuICAgICAgICB0aGlzLmlzV2hlZWxFdmVudCA9IHRydWU7IC8vIEtlZXAgdGhlIGluZm8gdGhhdCB3ZSBhcmUgY3VycmVudGx5IG1hbmFnaW5nIGEgbW91c2Ugd2hlZWwgZXZlbnRcblxuICAgICAgICAvLyAwKSBGaXJzdCwgc2F2ZSB0aGUgY2FyZXQgcG9zaXRpb24gc28gd2UgY2FuIHNldCBpdCBiYWNrIG9uY2UgdGhlIHZhbHVlIGhhcyBiZWVuIGNoYW5nZWRcbiAgICAgICAgY29uc3Qgc2VsZWN0aW9uU3RhcnQgPSBlLnRhcmdldC5zZWxlY3Rpb25TdGFydCB8fCAwO1xuICAgICAgICBjb25zdCBzZWxlY3Rpb25FbmQgPSBlLnRhcmdldC5zZWxlY3Rpb25FbmQgfHwgMDtcblxuICAgICAgICAvLyAxKSBHZXQgdGhlIHVuZm9ybWF0dGVkIHZhbHVlXG4gICAgICAgIGNvbnN0IGN1cnJlbnRVbmZvcm1hdHRlZFZhbHVlID0gdGhpcy5yYXdWYWx1ZTtcblxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KGN1cnJlbnRVbmZvcm1hdHRlZFZhbHVlKSkge1xuICAgICAgICAgICAgLy8gSWYgYnkgZGVmYXVsdCB0aGUgaW5wdXQgaXMgZW1wdHksIHN0YXJ0IGF0ICcwJ1xuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlID4gMCB8fCB0aGlzLnNldHRpbmdzLm1heGltdW1WYWx1ZSA8IDApIHtcbiAgICAgICAgICAgICAgICAvLyBvciBpZiAnMCcgaXMgbm90IGJldHdlZW4gbWluIGFuZCBtYXggdmFsdWUsICdtaW5pbXVtVmFsdWUnIGlmIHRoZSB1c2VyIGRvZXMgYSB3aGVlbHVwLCAnbWF4aW11bVZhbHVlJyBpZiB0aGUgdXNlciBkb2VzIGEgd2hlZWxkb3duXG4gICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzV2hlZWxVcEV2ZW50KGUpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNXaGVlbERvd25FdmVudChlKSkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLnNldHRpbmdzLm1heGltdW1WYWx1ZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZXZlbnQgaXMgbm90IGEgJ3doZWVsJyBldmVudC5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSBjdXJyZW50VW5mb3JtYXR0ZWRWYWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJlc3VsdCA9ICtyZXN1bHQ7IC8vIFR5cGVjYXN0IHRvIGEgbnVtYmVyIG5lZWRlZCBmb3IgdGhlIGZvbGxvd2luZyBhZGRpdGlvbi9zdWJ0cmFjdGlvblxuXG4gICAgICAgIC8vIDIpIEluY3JlbWVudC9EZWNyZW1lbnQgdGhlIHZhbHVlXG4gICAgICAgIC8vIEJ1dCBmaXJzdCwgY2hvb3NlIHRoZSBpbmNyZW1lbnQvZGVjcmVtZW50IG1ldGhvZCA7IGZpeGVkIG9yIHByb2dyZXNzaXZlXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcih0aGlzLnNldHRpbmdzLndoZWVsU3RlcCkpIHtcbiAgICAgICAgICAgIGNvbnN0IHN0ZXAgPSArdGhpcy5zZXR0aW5ncy53aGVlbFN0ZXA7IC8vIFR5cGVjYXN0IHRvIGEgbnVtYmVyIG5lZWRlZCBmb3IgdGhlIGZvbGxvd2luZyBhZGRpdGlvbi9zdWJ0cmFjdGlvblxuICAgICAgICAgICAgLy8gRml4ZWQgbWV0aG9kXG4gICAgICAgICAgICAvLyBUaGlzIGlzIHRoZSBzaW1wbGVzdCBtZXRob2QsIHdoZXJlIGEgZml4ZWQgb2Zmc2V0IGluIGFkZGVkL3N1YnRyYWN0ZWQgZnJvbSB0aGUgY3VycmVudCB2YWx1ZVxuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzV2hlZWxVcEV2ZW50KGUpKSB7IC8vIEluY3JlbWVudFxuICAgICAgICAgICAgICAgIHJlc3VsdCArPSBzdGVwO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1doZWVsRG93bkV2ZW50KGUpKSB7IC8vIERlY3JlbWVudFxuICAgICAgICAgICAgICAgIHJlc3VsdCAtPSBzdGVwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gUHJvZ3Jlc3NpdmUgbWV0aG9kXG4gICAgICAgICAgICAvLyBGb3IgdGhpcyBtZXRob2QsIHdlIGNhbGN1bGF0ZSBhbiBvZmZzZXQgdGhhdCBpcyBpbiByZWxhdGlvbiB0byB0aGUgc2l6ZSBvZiB0aGUgY3VycmVudCBudW1iZXIgKHVzaW5nIG9ubHkgdGhlIGludGVnZXIgcGFydCBzaXplKS5cbiAgICAgICAgICAgIC8vIFRoZSBiaWdnZXIgdGhlIG51bWJlciwgdGhlIGJpZ2dlciB0aGUgb2Zmc2V0ICh1c3VhbGx5IHRoZSBudW1iZXIgY291bnQgaW4gdGhlIGludGVnZXIgcGFydCBtaW51cyAzLCBleGNlcHQgZm9yIHNtYWxsIG51bWJlcnMgd2hlcmUgYSBkaWZmZXJlbnQgYmVoYXZpb3IgaXMgYmV0dGVyIGZvciB0aGUgdXNlciBleHBlcmllbmNlKS5cbiAgICAgICAgICAgIC8vVE9ETyBLbm93biBsaW1pdGF0aW9uIDogVGhlIHByb2dyZXNzaXZlIG1ldGhvZCBkb2VzIG5vdCBwbGF5IHdlbGwgd2l0aCBudW1iZXJzIGJldHdlZW4gMCBhbmQgMSB3aGVyZSB0byBtb2RpZnkgdGhlIGRlY2ltYWwgcGxhY2VzIHRoZSByYXdWYWx1ZSBmaXJzdCBoYXMgdG8gZ28gZnJvbSAnMScgdG8gJzAnXG4gICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNXaGVlbFVwRXZlbnQoZSkpIHsgLy8gSW5jcmVtZW50XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIuYWRkQW5kUm91bmRUb05lYXJlc3RBdXRvKHJlc3VsdCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpO1xuICAgICAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1doZWVsRG93bkV2ZW50KGUpKSB7IC8vIERlY3JlbWVudFxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljSGVscGVyLnN1YnRyYWN0QW5kUm91bmRUb05lYXJlc3RBdXRvKHJlc3VsdCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gMykgU2V0IHRoZSBuZXcgdmFsdWUgc28gaXQgZ2V0cyBmb3JtYXR0ZWRcbiAgICAgICAgLy8gRmlyc3QgY2xhbXAgdGhlIHJlc3VsdCBpZiBuZWVkZWRcbiAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIuY2xhbXBUb1JhbmdlTGltaXRzKHJlc3VsdCwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgIGlmIChyZXN1bHQgIT09ICtjdXJyZW50VW5mb3JtYXR0ZWRWYWx1ZSkge1xuICAgICAgICAgICAgLy8gT25seSAnc2V0JyB0aGUgdmFsdWUgaWYgaXQgaGFzIGNoYW5nZWQuIEZvciBpbnN0YW5jZSAnc2V0JyBzaG91bGQgbm90IGhhcHBlbiBpZiB0aGUgdXNlciBoaXRzIGEgbGltaXQgYW5kIGNvbnRpbnVlIHRvIHRyeSB0byBnbyBwYXN0IGl0IHNpbmNlIHdlIGNsYW1wIHRoZSB2YWx1ZS5cbiAgICAgICAgICAgIHRoaXMuc2V0KHJlc3VsdCk7XG5cbiAgICAgICAgICAgIC8vIFNpbmNlIHdlIGNoYW5nZWQgdGhlIGlucHV0IHZhbHVlLCB3ZSBzZW5kIGEgbmF0aXZlIGBpbnB1dGAgZXZlbnRcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubmF0aXZlLmlucHV0LCBlLnRhcmdldCk7XG4gICAgICAgIH1cblxuICAgICAgICAvL1hYWCBEbyBub3QgcHJldmVudCBpZiB0aGUgdmFsdWUgaXMgbm90IG1vZGlmaWVkPyBGcm9tIGEgVVggcG9pbnQgb2YgdmlldywgcHJldmVudGluZyB0aGUgd2hlZWwgZXZlbnQgd2hlbiB0aGUgdXNlciB1c2UgaXQgb24gdG9wIG9mIGFuIGF1dG9OdW1lcmljIGVsZW1lbnQgc2hvdWxkIGFsd2F5cyBiZSBkb25lLCBldmVuIGlmIHRoZSB2YWx1ZSBkb2VzIG5vdCBjaGFuZ2UuIFBlcmhhcHMgdGhhdCBjb3VsZCBhZmZlY3Qgb3RoZXIgc2NyaXB0cyByZWx5aW5nIG9uIHRoaXMgZXZlbnQgdG8gYmUgc2VudCB0aG91Z2guXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTsgLy8gV2UgcHJldmVudCB0aGUgcGFnZSB0byBzY3JvbGwgd2hpbGUgd2UgaW5jcmVtZW50L2RlY3JlbWVudCB0aGUgdmFsdWVcblxuICAgICAgICAvLyA0KSBGaW5hbGx5LCB3ZSBzZXQgYmFjayB0aGUgY2FyZXQgcG9zaXRpb24vc2VsZWN0aW9uXG4gICAgICAgIC8vIFRoZXJlIGlzIG5vIG5lZWQgdG8gdGFrZSBpbnRvIGFjY291bnQgdGhlIGZhY3QgdGhhdCB0aGUgbnVtYmVyIGNvdW50IGNvdWxkIGJlIGRpZmZlcmVudCBhdCB0aGUgZW5kIG9mIHRoZSB3aGVlbCBldmVudCA7IGl0IHdvdWxkIGJlIHRvbyBjb21wbGV4IGFuZCBtb3N0IG9mIHRoZSB0aW1lIHVucmVsaWFibGVcbiAgICAgICAgdGhpcy5fc2V0U2VsZWN0aW9uKHNlbGVjdGlvblN0YXJ0LCBzZWxlY3Rpb25FbmQpO1xuXG4gICAgICAgIHRoaXMuaXNXaGVlbEV2ZW50ID0gZmFsc2U7IC8vIFNldCBiYWNrIHRoZSBtb3VzZSB3aGVlbCBpbmRpY2F0b3IgdG8gaXRzIGRlZmF1bHRcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVyIGZvciAnZHJvcCcgZXZlbnRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RHJhZ0V2ZW50fSBlXG4gICAgICovXG4gICAgX29uRHJvcChlKSB7XG4gICAgICAgIC8vIE5vdGU6IGJ5IGRlZmF1bHQgYnJvd3NlcnMgYWxyZWFkeSBwcmV2ZW50IHRoZSBkcm9wIG9uIHJlYWRPbmx5IGFuZCBkaXNhYmxlZCBlbGVtZW50c1xuICAgICAgICB0aGlzLmlzRHJvcEV2ZW50ID0gdHJ1ZTtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBsZXQgZm9ybWF0O1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNJRTExKCkpIHtcbiAgICAgICAgICAgIGZvcm1hdCA9ICd0ZXh0JztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZvcm1hdCA9ICd0ZXh0L3BsYWluJztcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGRyb3BwZWRUZXh0ID0gZS5kYXRhVHJhbnNmZXIuZ2V0RGF0YShmb3JtYXQpO1xuICAgICAgICBjb25zdCBjbGVhbmVkVmFsdWUgPSB0aGlzLnVuZm9ybWF0T3RoZXIoZHJvcHBlZFRleHQpO1xuICAgICAgICB0aGlzLnNldChjbGVhbmVkVmFsdWUpO1xuICAgICAgICB0aGlzLmlzRHJvcEV2ZW50ID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlciBmb3IgJ3N1Ym1pdCcgZXZlbnRzIGhhcHBlbmluZyBvbiB0aGUgcGFyZW50IDxmb3JtPiBlbGVtZW50LlxuICAgICAqIElmIGB1bmZvcm1hdE9uU3VibWl0YCBpcyBzZXQgdG8gYHRydWVgLCB0aGUgZWxlbWVudCB2YWx1ZSBpcyBmaXJzdCB1bmZvcm1hdHRlZCBiZWZvcmUgdGhlIGZvcm0gaXMgc3VibWl0dGVkLlxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgX29uRm9ybVN1Ym1pdCgpIHtcbiAgICAgICAgLy8gU2VhcmNoIGZvciBhbGwgdGhlIEF1dG9OdW1lcmljIGNoaWxkcmVuIG9mIHRoZSBmb3JtIGVsZW1lbnQgYW5kIGNhbGwgdGhlIGBfdW5mb3JtYXRPblN1Ym1pdCgpYCBmdW5jdGlvblxuICAgICAgICBjb25zdCBpbnB1dEVsZW1lbnRzID0gdGhpcy5fZ2V0Rm9ybUF1dG9OdW1lcmljQ2hpbGRyZW4odGhpcy5wYXJlbnRGb3JtKTtcbiAgICAgICAgY29uc3QgYU5FbGVtZW50cyA9IGlucHV0RWxlbWVudHMubWFwKGFORWxlbWVudCA9PiB0aGlzLmNvbnN0cnVjdG9yLmdldEF1dG9OdW1lcmljRWxlbWVudChhTkVsZW1lbnQpKTtcbiAgICAgICAgYU5FbGVtZW50cy5mb3JFYWNoKGFORWxlbWVudCA9PiBhTkVsZW1lbnQuX3VuZm9ybWF0T25TdWJtaXQoKSk7XG5cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW5mb3JtYXQgdGhlIGVsZW1lbnQgdmFsdWUgYWNjb3JkaW5nIHRvIHRoZSBgdW5mb3JtYXRPblN1Ym1pdGAgb3B0aW9uXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF91bmZvcm1hdE9uU3VibWl0KCkge1xuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy51bmZvcm1hdE9uU3VibWl0KSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50VmFsdWUodGhpcy5yYXdWYWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMaXN0ZW4gZm9yIHRoZSBgYWx0YCBrZXkga2V5ZG93biBldmVudCBnbG9iYWxseSwgYW5kIGlmIHRoZSBldmVudCBpcyBjYXVnaHQsIHVuZm9ybWF0IHRoZSBBdXRvTnVtZXJpYyBlbGVtZW50IHRoYXQgaXMgaG92ZXJlZCBieSB0aGUgbW91c2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0tleWJvYXJkRXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9vbktleWRvd25HbG9iYWwoZSkge1xuICAgICAgICAvL1RPRE8gRmluZCBhIHdheSB0byBrZWVwIHRoZSBjYXJldCBwb3NpdGlvbiBiZXR3ZWVuIHRoZSBhbHQga2V5dXAva2V5ZG93biBzdGF0ZXNcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmNoYXJhY3RlcihlKSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQWx0KSB7XG4gICAgICAgICAgICBjb25zdCBob3ZlcmVkRWxlbWVudCA9IEF1dG9OdW1lcmljSGVscGVyLmdldEhvdmVyZWRFbGVtZW50KCk7XG4gICAgICAgICAgICBpZiAoQXV0b051bWVyaWMuaXNNYW5hZ2VkQnlBdXRvTnVtZXJpYyhob3ZlcmVkRWxlbWVudCkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBhbkVsZW1lbnQgPSBBdXRvTnVtZXJpYy5nZXRBdXRvTnVtZXJpY0VsZW1lbnQoaG92ZXJlZEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IuX3VuZm9ybWF0QWx0SG92ZXJlZChhbkVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTGlzdGVuIGZvciB0aGUgYGFsdGAga2V5IGtleXVwIGV2ZW50IGdsb2JhbGx5LCBhbmQgaWYgdGhlIGV2ZW50IGlzIGNhdWdodCwgcmVmb3JtYXQgdGhlIEF1dG9OdW1lcmljIGVsZW1lbnQgdGhhdCBpcyBob3ZlcmVkIGJ5IHRoZSBtb3VzZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7S2V5Ym9hcmRFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX29uS2V5dXBHbG9iYWwoZSkge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuY2hhcmFjdGVyKGUpID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5BbHQpIHtcbiAgICAgICAgICAgIGNvbnN0IGhvdmVyZWRFbGVtZW50ID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0SG92ZXJlZEVsZW1lbnQoKTtcbiAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpYy5pc01hbmFnZWRCeUF1dG9OdW1lcmljKGhvdmVyZWRFbGVtZW50KSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFuRWxlbWVudCA9IEF1dG9OdW1lcmljLmdldEF1dG9OdW1lcmljRWxlbWVudChob3ZlcmVkRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fcmVmb3JtYXRBbHRIb3ZlcmVkKGFuRWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBET00gZWxlbWVudCBpcyBzdXBwb3J0ZWQgYnkgYXV0b051bWVyaWMuXG4gICAgICogQSBzdXBwb3J0ZWQgZWxlbWVudCBpcyBhbiBlbGVtZW50IHdoaXRlbGlzdGVkIGluIHRoZSBgYWxsb3dlZFRhZ0xpc3RgLlxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfaXNFbGVtZW50VGFnU3VwcG9ydGVkKCkge1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzRWxlbWVudCh0aGlzLmRvbUVsZW1lbnQpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgRE9NIGVsZW1lbnQgaXMgbm90IHZhbGlkLCAke3RoaXMuZG9tRWxlbWVudH0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KHRoaXMuZG9tRWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCksIHRoaXMuYWxsb3dlZFRhZ0xpc3QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaW4gdGhlIERPTSBlbGVtZW50IGlzIGFuIDxpbnB1dD4uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9pc0lucHV0RWxlbWVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZG9tRWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdpbnB1dCc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgaW5wdXQgdHlwZSBpcyBzdXBwb3J0ZWQgYnkgQXV0b051bWVyaWNcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEB0aHJvd3NcbiAgICAgKi9cbiAgICBfaXNJbnB1dFR5cGVTdXBwb3J0ZWQoKSB7XG4gICAgICAgIHJldHVybiAodGhpcy5kb21FbGVtZW50LnR5cGUgPT09ICd0ZXh0JyB8fFxuICAgICAgICAgICAgICAgIHRoaXMuZG9tRWxlbWVudC50eXBlID09PSAnaGlkZGVuJyB8fFxuICAgICAgICAgICAgICAgIHRoaXMuZG9tRWxlbWVudC50eXBlID09PSAndGVsJyB8fFxuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh0aGlzLmRvbUVsZW1lbnQudHlwZSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIHRoZSBET00gZWxlbWVudCBpcyBzdXBwb3J0ZWQgYnkgYXV0b051bWVyaWMuXG4gICAgICogQSBzdXBwb3J0ZWQgZWxlbWVudCBpcyBlaXRoZXIgYW4gPGlucHV0PiBlbGVtZW50IHdpdGggdGhlIHJpZ2h0ICd0eXBlJyBhdHRyaWJ1dGUsIG9yIGEgdGFnIHdoaXRlbGlzdGVkIGluIHRoZSBgYWxsb3dlZFRhZ0xpc3RgLlxuICAgICAqIElmIHRoZSBjaGVjayBmYWlscywgdGhpcyBtZXRob2QgdGhyb3dzLlxuICAgICAqIFRoaXMgZnVuY3Rpb24gYWxzbyBzZXQgdGhlIGluZm8gYHRoaXMuaXNJbnB1dEVsZW1lbnRgIHdoaWNoIGtlZXAgdHJhY2tzIGlmIHRoZSBET00gZWxlbWVudCBpcyBhbiA8aW5wdXQ+IG9yIG5vdCwgYW5kIHRoZSBgdGhpcy5pc0NvbnRlbnRFZGl0YWJsZWAgaWYgdGhlIGVsZW1lbnQgaGFzIHRoZSBgY29udGVudGVkaXRhYmxlYCBhdHRyaWJ1dGUgc2V0IHRvIGB0cnVlYC5cbiAgICAgKlxuICAgICAqIEB0aHJvd3NcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9jaGVja0VsZW1lbnQoKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRFbGVtZW50VGFnID0gdGhpcy5kb21FbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKTtcblxuICAgICAgICBpZiAoIXRoaXMuX2lzRWxlbWVudFRhZ1N1cHBvcnRlZCgpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgPCR7Y3VycmVudEVsZW1lbnRUYWd9PiB0YWcgaXMgbm90IHN1cHBvcnRlZCBieSBhdXRvTnVtZXJpY2ApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzSW5wdXRFbGVtZW50KCkpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5faXNJbnB1dFR5cGVTdXBwb3J0ZWQoKSkge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBpbnB1dCB0eXBlIFwiJHt0aGlzLmRvbUVsZW1lbnQudHlwZX1cIiBpcyBub3Qgc3VwcG9ydGVkIGJ5IGF1dG9OdW1lcmljYCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuaXNJbnB1dEVsZW1lbnQgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5pc0lucHV0RWxlbWVudCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5pc0NvbnRlbnRFZGl0YWJsZSA9IHRoaXMuZG9tRWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2NvbnRlbnRlZGl0YWJsZScpICYmIHRoaXMuZG9tRWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2NvbnRlbnRlZGl0YWJsZScpID09PSAndHJ1ZSc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JtYXRzIHRoZSBkZWZhdWx0IHZhbHVlIG9uIHBhZ2UgbG9hZC5cbiAgICAgKiBUaGlzIGlzIGNhbGxlZCBvbmx5IGlmIHRoZSBgZm9ybWF0T25QYWdlTG9hZGAgb3B0aW9uIGlzIHNldCB0byBgdHJ1ZWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd8bnVsbH0gZm9yY2VkSW5pdGlhbFZhbHVlIFRoZSB2YWx1ZSB0aGF0IHNob3VsZCBiZSB1c2VkIGZvciBpbml0aWFsaXphdGlvbiwgaW4gcGxhY2Ugb24gdGhlIGV2ZW50dWFsIGh0bWwgb25lXG4gICAgICovXG4gICAgX2Zvcm1hdERlZmF1bHRWYWx1ZU9uUGFnZUxvYWQoZm9yY2VkSW5pdGlhbFZhbHVlID0gbnVsbCkge1xuICAgICAgICBsZXQgc2V0VmFsdWUgPSB0cnVlO1xuICAgICAgICBsZXQgY3VycmVudFZhbHVlO1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChmb3JjZWRJbml0aWFsVmFsdWUpKSB7XG4gICAgICAgICAgICBjdXJyZW50VmFsdWUgPSBmb3JjZWRJbml0aWFsVmFsdWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgdGhlIGluaXRpYWwgdmFsdWUgZG9lcyBub3QgaGF2ZSBhbnkgc3VwZXJmbHVvdXMgd2hpdGVzcGFjZXMgYXJvdW5kIGl0IChGaXggaXNzdWUgIzQ3OSlcbiAgICAgICAgICAgIGN1cnJlbnRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpLnRyaW0oKTtcbiAgICAgICAgICAgIC8vIENvcnJlY3QgdGhlIERPTSBhdHRyaWJ1dGUgaW4gY2FzZSBzb21lIHdoaXRlc3BhY2VzIHdlcmUgcHJlc2VudFxuICAgICAgICAgICAgdGhpcy5kb21FbGVtZW50LnNldEF0dHJpYnV0ZSgndmFsdWUnLCBjdXJyZW50VmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuaXNJbnB1dEVsZW1lbnQgfHwgdGhpcy5pc0NvbnRlbnRFZGl0YWJsZSkge1xuICAgICAgICAgICAgLypcbiAgICAgICAgICAgICAqIElmIHRoZSBpbnB1dCB2YWx1ZSBoYXMgYmVlbiBzZXQgYnkgdGhlIGRldiwgYnV0IG5vdCBkaXJlY3RseSBhcyBhbiBhdHRyaWJ1dGUgaW4gdGhlIGh0bWwsIHRoZW4gaXQgdGFrZXNcbiAgICAgICAgICAgICAqIHByZWNlZGVuY2UgYW5kIHNob3VsZCBnZXQgZm9ybWF0dGVkIGR1cmluZyB0aGUgaW5pdGlhbGl6YXRpb24gKGlmIHRoaXMgaW5wdXQgdmFsdWUgaXMgYSB2YWxpZCBudW1iZXIgYW5kIHRoYXQgdGhlXG4gICAgICAgICAgICAgKiBkZXZlbG9wZXIgd2FudHMgaXQgZm9ybWF0dGVkIG9uIGluaXQgKGNmLiB0aGUgYHNldHRpbmdzLmZvcm1hdE9uUGFnZUxvYWRgIG9wdGlvbikpLlxuICAgICAgICAgICAgICogTm90ZTsgdGhpcyBpcyB0cnVlIHdoYXRldmVyIHRoZSBkZXZlbG9wZXIgaGFzIHNldCBmb3IgYGRhdGEtZGVmYXVsdC12YWx1ZS1vdmVycmlkZWAgaW4gdGhlIGh0bWwgKGFzcC5uZXQgdXNlcnMpLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEluIG90aGVyIHdvcmRzIDogaWYgYGRlZmF1bHRWYWx1ZU92ZXJyaWRlYCBpcyBub3QgbnVsbCwgaXQgbWVhbnMgdGhlIGRldmVsb3BlciBpcyB0cnlpbmcgdG8gcHJldmVudCBwb3N0YmFjayBwcm9ibGVtcy5cbiAgICAgICAgICAgICAqIEJ1dCBpZiBgaW5wdXQudmFsdWVgIGlzIHNldCB0byBhIG51bWJlciwgYW5kIHRoZSBodG1sIGB2YWx1ZWAgYXR0cmlidXRlIGlzIG5vdCBzZXQsIHRoZW4gaXQgbWVhbnMgdGhlIGRldiBoYXNcbiAgICAgICAgICAgICAqIGNoYW5nZWQgdGhlIGlucHV0IHZhbHVlLCBhbmQgdGhlbiBpdCBtZWFucyB3ZSBzaG91bGQgbm90IG92ZXJ3cml0ZSBoaXMgb3duIGRlY2lzaW9uIHRvIGRvIHNvLlxuICAgICAgICAgICAgICogSGVuY2UsIGlmIGBkZWZhdWx0VmFsdWVPdmVycmlkZWAgaXMgbm90IG51bGwsIGJ1dCBgaW5wdXQudmFsdWVgIGlzIGEgbnVtYmVyIGFuZCBgdGhpcy5kb21FbGVtZW50Lmhhc0F0dHJpYnV0ZSgndmFsdWUnKWBcbiAgICAgICAgICAgICAqIGlzIGZhbHNlLCB3ZSBzaG91bGQgaWdub3JlIGBkZWZhdWx0VmFsdWVPdmVycmlkZWAgYWx0b2dldGhlci5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgY29uc3QgdW5Mb2NhbGl6ZWRDdXJyZW50VmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl90b051bWVyaWNWYWx1ZShjdXJyZW50VmFsdWUsIHRoaXMuc2V0dGluZ3MpOyAvLyBUaGlzIGFsbG93cyB0byB1c2UgYSBsb2NhbGl6ZWQgdmFsdWUgb24gc3RhcnR1cFxuICAgICAgICAgICAgaWYgKCF0aGlzLmRvbUVsZW1lbnQuaGFzQXR0cmlidXRlKCd2YWx1ZScpIHx8IHRoaXMuZG9tRWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGB2YWx1ZWAgaXMgdmFsaWQgb3Igbm90XG4gICAgICAgICAgICAgICAgaWYgKCFpc05hTihOdW1iZXIodW5Mb2NhbGl6ZWRDdXJyZW50VmFsdWUpKSAmJiBJbmZpbml0eSAhPT0gdW5Mb2NhbGl6ZWRDdXJyZW50VmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXQodW5Mb2NhbGl6ZWRDdXJyZW50VmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIG5vdCwgaW5mb3JtIHRoZSBkZXZlbG9wZXIgdGhhdCBub3RoaW5nIHVzYWJsZSBoYXMgYmVlbiBwcm92aWRlZFxuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdmFsdWUgWyR7Y3VycmVudFZhbHVlfV0gdXNlZCBpbiB0aGUgaW5wdXQgaXMgbm90IGEgdmFsaWQgdmFsdWUgYXV0b051bWVyaWMgY2FuIHdvcmsgd2l0aC5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8qIENoZWNrcyBmb3IgOlxuICAgICAgICAgICAgICAgICAqIC0gcGFnZSByZWxvYWQgZnJvbSBiYWNrIGJ1dHRvbiwgYW5kXG4gICAgICAgICAgICAgICAgICogLSBBU1AubmV0IGZvcm0gcG9zdCBiYWNrXG4gICAgICAgICAgICAgICAgICogICAgICBUaGUgZm9sbG93aW5nIEhUTUwgZGF0YSBhdHRyaWJ1dGUgaXMgUkVRVUlSRUQgKGRhdGEtYW4tZGVmYXVsdD1cInNhbWUgdmFsdWUgYXMgdGhlIHZhbHVlIGF0dHJpYnV0ZVwiKVxuICAgICAgICAgICAgICAgICAqICAgICAgZXhhbXBsZTogPGFzcDpUZXh0Qm94IHJ1bmF0PVwic2VydmVyXCIgaWQ9XCJzb21lSURcIiB0ZXh0PVwiMTIzNC41NlwiIGRhdGEtYW4tZGVmYXVsdD1cIjEyMzQuNTZcIj5cbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBpZiAoKHRoaXMuc2V0dGluZ3MuZGVmYXVsdFZhbHVlT3ZlcnJpZGUgIT09IG51bGwgJiYgdGhpcy5zZXR0aW5ncy5kZWZhdWx0VmFsdWVPdmVycmlkZS50b1N0cmluZygpICE9PSBjdXJyZW50VmFsdWUpIHx8XG4gICAgICAgICAgICAgICAgICAgICh0aGlzLnNldHRpbmdzLmRlZmF1bHRWYWx1ZU92ZXJyaWRlID09PSBudWxsICYmIGN1cnJlbnRWYWx1ZSAhPT0gJycgJiYgY3VycmVudFZhbHVlICE9PSB0aGlzLmRvbUVsZW1lbnQuZ2V0QXR0cmlidXRlKCd2YWx1ZScpKSB8fFxuICAgICAgICAgICAgICAgICAgICAoY3VycmVudFZhbHVlICE9PSAnJyAmJiB0aGlzLmRvbUVsZW1lbnQuZ2V0QXR0cmlidXRlKCd0eXBlJykgPT09ICdoaWRkZW4nICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcih1bkxvY2FsaXplZEN1cnJlbnRWYWx1ZSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UgJiYgKHRoaXMuc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyAhPT0gbnVsbCB8fCB0aGlzLnNldHRpbmdzLmRpdmlzb3JXaGVuVW5mb2N1c2VkKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0UmF3VmFsdWUodGhpcy5fZ2V0VmFsdWVGcm9tUGVyc2lzdGVudFN0b3JhZ2UoKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyB2YWx1ZSBzaG91bGQgTk9UIGJlIHNhdmVkIGluIHNlc3Npb25TdG9yYWdlXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5zZXR0aW5ncy5zYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCB0b1N0cmlwID0gdGhpcy5jb25zdHJ1Y3Rvci5fcmVtb3ZlQnJhY2tldHMoY3VycmVudFZhbHVlLCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICgodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXggfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXggJiYgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgpKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyICE9PSAnJyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUoY3VycmVudFZhbHVlLCB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRSYXdWYWx1ZShgLSR7dGhpcy5jb25zdHJ1Y3Rvci5fc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzKHRvU3RyaXAsIHRoaXMuc2V0dGluZ3MsIHRydWUsIHRoaXMuaXNGb2N1c2VkKX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0UmF3VmFsdWUodGhpcy5jb25zdHJ1Y3Rvci5fc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzKHRvU3RyaXAsIHRoaXMuc2V0dGluZ3MsIHRydWUsIHRoaXMuaXNGb2N1c2VkKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGN1cnJlbnRWYWx1ZSA9PT0gJycpIHtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IuZm9jdXM6XG4gICAgICAgICAgICAgICAgICAgICAgICBzZXRWYWx1ZSA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIC8vVE9ETyBXaGF0IGFib3V0IHRoZSBgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IucHJlc3NgIHZhbHVlP1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLmFsd2F5czpcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldEVsZW1lbnRWYWx1ZSh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFZhbHVlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci56ZXJvOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXQoJzAnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFZhbHVlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChzZXRWYWx1ZSAmJiBjdXJyZW50VmFsdWUgPT09IHRoaXMuZG9tRWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3ZhbHVlJykpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldChjdXJyZW50VmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2V0dGluZ3MuZGVmYXVsdFZhbHVlT3ZlcnJpZGUgPT09IG51bGwgfHxcbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuZGVmYXVsdFZhbHVlT3ZlcnJpZGUgPT09IGN1cnJlbnRWYWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5zZXQoY3VycmVudFZhbHVlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEVuaGFuY2UgdGhlIHVzZXIgZXhwZXJpZW5jZSBieSBtb2RpZnlpbmcgdGhlIGRlZmF1bHQgYG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50YCBvcHRpb24gZGVwZW5kaW5nIG9uIGBjdXJyZW5jeVN5bWJvbGAgYW5kIGBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudGAuXG4gICAgICpcbiAgICAgKiBJZiB0aGUgdXNlciBoYXMgbm90IHNldCB0aGUgcGxhY2VtZW50IG9mIHRoZSBuZWdhdGl2ZSBzaWduIChgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnRgKSwgYnV0IGhhcyBzZXQgYSBjdXJyZW5jeSBzeW1ib2wgKGBjdXJyZW5jeVN5bWJvbGApLFxuICAgICAqIHRoZW4gd2UgbW9kaWZ5IHRoZSBkZWZhdWx0IHZhbHVlIG9mIGBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudGAgaW4gb3JkZXIgdG8ga2VlcCB0aGUgcmVzdWx0aW5nIG91dHB1dCBsb2dpY2FsIGJ5IGRlZmF1bHQgOlxuICAgICAqIC0gXCIkLTEsMjM0LjU2XCIgaW5zdGVhZCBvZiBcIi0kMSwyMzQuNTZcIiAoe2N1cnJlbmN5U3ltYm9sOiBcIiRcIiwgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IFwiclwifSlcbiAgICAgKiAtIFwiLTEsMjM0LjU2JFwiIGluc3RlYWQgb2YgXCIxLDIzNC41Ni0kXCIgKHtjdXJyZW5jeVN5bWJvbDogXCIkXCIsIGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50OiBcInNcIiwgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IFwicFwifSlcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqL1xuICAgIHN0YXRpYyBfY29ycmVjdE5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50T3B0aW9uKHNldHRpbmdzKSB7XG4gICAgICAgIC8vWFhYIE5vdGU7IHRoaXMgZnVuY3Rpb24gaXMgc3RhdGljIHNpbmNlIHdlIG5lZWQgdG8gcGFzcyBhIGBzZXR0aW5nc2Agb2JqZWN0IHdoZW4gY2FsbGluZyB0aGUgc3RhdGljIGBBdXRvTnVtZXJpYy5mb3JtYXQoKWAgbWV0aG9kXG4gICAgICAgIC8vIElmIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50IGlzIGFscmVhZHkgc2V0LCB3ZSBkbyBub3Qgb3ZlcndyaXRlIGl0XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZChzZXR0aW5ncykgJiZcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShzZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkgJiZcbiAgICAgICAgICAgICFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkoc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wpKSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeDpcbiAgICAgICAgICAgICAgICAgICAgc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDsgLy8gRGVmYXVsdCAtMSwyMzQuNTYg4oKsXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXg6XG4gICAgICAgICAgICAgICAgICAgIHNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0OyAvLyBEZWZhdWx0IC0kMSwyMzQuNTZcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFNldHMgdGhlIGRlZmF1bHQgdmFsdWUgaWYgYG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50YCBpcyBgbnVsbGBcbiAgICAgICAgICAgIHNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0O1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29ycmVjdCB0aGUgYGNhcmV0UG9zaXRpb25PbkZvY3VzYCBhbmQgYHNlbGVjdE9uRm9jdXNgIG9wdGlvbnMsIHNpbmNlIHNldHRpbmcgYm90aCBsZWFkcyB0byBhIGNvbmZsaWN0LlxuICAgICAqIFRoaXMgbWV0aG9kIGRpcmVjdGx5IG1vZGlmaWVzIHRoZSBgb3B0aW9uc2Agb2JqZWN0IHBhc3NlZCBhcyBhIHBhcmFtZXRlciwgdGhlbiByZXR1cm5zIGl0LlxuICAgICAqIEl0IHJldHVybnMgYG51bGxgIGlmIHRoZSBnaXZlbiBvcHRpb24gaXMgYG51bGxgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnMgVGhlIG9wdGlvbnMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50IGJ5IHRoZSB1c2VyXG4gICAgICogQHJldHVybnMge29iamVjdHxudWxsfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9jb3JyZWN0Q2FyZXRQb3NpdGlvbk9uRm9jdXNBbmRTZWxlY3RPbkZvY3VzT3B0aW9ucyhvcHRpb25zKSB7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucykpIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgdGhlIHVzZXIgaGFzIHNldCB0aGUgYGNhcmV0UG9zaXRpb25PbkZvY3VzYCBvcHRpb24sIGRvIG5vdCBzZXQgYHNlbGVjdE9uRm9jdXNgIHRvIGB0cnVlYCBieSBkZWZhdWx0XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KG9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMpICYmIEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShvcHRpb25zLnNlbGVjdE9uRm9jdXMpKSB7XG4gICAgICAgICAgICBvcHRpb25zLnNlbGVjdE9uRm9jdXMgPSBBdXRvTnVtZXJpYy5vcHRpb25zLnNlbGVjdE9uRm9jdXMuZG9Ob3RTZWxlY3Q7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGUgdXNlciBoYXMgc2V0IHRoZSBgc2VsZWN0T25Gb2N1c2Agb3B0aW9uIHRvIGB0cnVlYCwgc2V0IGBjYXJldFBvc2l0aW9uT25Gb2N1c2AgdG8gYGRvTm9Gb3JjZUNhcmV0UG9zaXRpb25gXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkob3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cykgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShvcHRpb25zLnNlbGVjdE9uRm9jdXMpICYmIG9wdGlvbnMuc2VsZWN0T25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5zZWxlY3RPbkZvY3VzLnNlbGVjdCkge1xuICAgICAgICAgICAgb3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cyA9IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZG9Ob0ZvcmNlQ2FyZXRQb3NpdGlvbjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvcHRpb25zO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhbGN1bGF0ZSB0aGUgbnVtYmVyIGRlIGRlY2ltYWwgcGxhY2VzIHRvIGJlIHVzZWQgYnkgdGhlIEF1dG9OdW1lcmljIG9iamVjdCwgZm9yIGVhY2ggb2YgaXRzIHN0YXRlLCBhbmQgZm9yIGl0cyBmb3JtYXR0ZWQgYW5kIHJhdyB2YWx1ZS5cbiAgICAgKiBCeSBkZWZhdWx0LCB0aGUgYHJhd1ZhbHVlYCBwcmVjaXNpb24gaXMgdGhlIHNhbWUgYXMgdGhlIGZvcm1hdHRlZCB2YWx1ZSBvbmUuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBjYWxsZWQgZHVyaW5nIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgaW5pdGlhbGl6YXRpb24uIFRoaXMgYXNzdW1lcyBzb21lIGludGVybmFsIHZhcmlhYmxlIHN0YXRlLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2RzIHNldCB0aGUgZm9sbG93aW5nIG9wdGlvbnMgYWNjb3JkaW5nbHkgdG8gdGhlaXIgb3duIHZhbHVlIGFuZCB0aGUgbWFuZGF0b3J5IGBkZWNpbWFsUGxhY2VzYCBvcHRpb246XG4gICAgICogLSBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgICAgIChudWxsYWJsZSlcbiAgICAgKiAtIGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciAgKG51bGxhYmxlKVxuICAgICAqIC0gZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyAobnVsbGFibGUpXG4gICAgICpcbiAgICAgKiBOb3RlOiB0aGUgYGRlY2ltYWxQbGFjZXNgIG9wdGlvbiBpcyBvbmx5IHVzZWQgaGVyZSBhbmQgb25seSBzZXJ2ZSB0byBkZWZpbmUgdGhvc2UgdGhyZWUgcHJldmlvdXMgb3B0aW9ucyB2YWx1ZS5cbiAgICAgKiBBdXRvTnVtZXJpYyB3aWxsIHRoZW4gKm9ubHkqIHVzZSBgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlYCwgYGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cmAgYW5kIGBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzYCBmcm9tIHRoZXJlLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2RzIGRpcmVjdGx5IG1vZGlmaWVzIHRoZSBgc2V0dGluZ3NgIG9iamVjdCBwYXNzZWQgYXMgYSBwYXJhbWV0ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgVGhpcyBpcyBhbiBvYmplY3Qgd2l0aCB0aGUgbmV3IHNldHRpbmdzIHRvIHVzZS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfY2FsY3VsYXRlRGVjaW1hbFBsYWNlc09uSW5pdChzZXR0aW5ncykge1xuICAgICAgICAvLyBDaGVjayB0aGUgYGRlY2ltYWxQbGFjZXMqYCBvcHRpb25zIGFuZCBvdXRwdXQgYW55IHdhcm5pbmdzIGFzIG5lZWRlZCwgYmVmb3JlIG1vZGlmeWluZyB0aG9zZSBvcHRpb25zXG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKHNldHRpbmdzKTtcblxuICAgICAgICAvLyBJbml0aWFsaXphdGlvbiBwaGFzZVxuICAgICAgICAvL1hYWCBUaGlzIGFzc3VtZXMgYXQgdGhpcyBzdGFnZSwgYHNldHRpbmdzLmRlY2ltYWxQbGFjZXNgIGFzIGJlZW4gc2V0IGZyb20gdGhlIGRlZmF1bHQgb3B0aW9uc1xuXG4gICAgICAgIC8vIE92ZXJ3cml0ZSB0aGUgYGRlY2ltYWxQbGFjZXMqYCB2YWx1ZXMgaWYgdGhlIGBkZWNpbWFsUGxhY2VzKmAgb3B0aW9ucyBhcmUgbm90IHNldCBpbiB0aGUgYHNldHRpbmdzYFxuICAgICAgICAvLyBTZXRzIGBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXJgIChwcmV2aW91c2x5IGtub3duIGFzIGBzY2FsZURlY2ltYWxQbGFjZXNgKVxuICAgICAgICBpZiAoc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzLnVzZURlZmF1bHQpICB7XG4gICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzID0gc2V0dGluZ3MuZGVjaW1hbFBsYWNlcztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyLnVzZURlZmF1bHQpICB7XG4gICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIgPSBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUudXNlRGVmYXVsdCkgIHtcbiAgICAgICAgICAgIHNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IHNldHRpbmdzLmRlY2ltYWxQbGFjZXM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgdGhlIGFkZGl0aW9uYWwgZGVjaW1hbCBwbGFjZXMgdG8gdGhlIHJhdyB2YWx1ZVxuICAgICAgICBsZXQgYWRkaXRpb25hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IDA7XG4gICAgICAgIGlmIChzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IgJiYgc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJhd1ZhbHVlRGl2aXNvci5ub25lKSB7XG4gICAgICAgICAgICBhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gU3RyaW5nKHNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvcikubGVuZ3RoIC0gMTsgLy8gaWUuIERpdmlkaW5nIGJ5ICcxMDAnIGFkZHMgMiBkZWNpbWFsIHBsYWNlcyB0byB0aGUgbmVlZGVkIHByZWNpc2lvblxuICAgICAgICAgICAgaWYgKGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUgPCAwKSB7XG4gICAgICAgICAgICAgICAgYWRkaXRpb25hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUgPSBNYXRoLm1heChcbiAgICAgICAgICAgIE1hdGgubWF4KHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciwgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cykgKyBhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlLFxuICAgICAgICAgICAgTnVtYmVyKHNldHRpbmdzLm9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKSArIGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWVcbiAgICAgICAgKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWNhbGN1bGF0ZSB0aGUgbnVtYmVyIGRlIGRlY2ltYWwgcGxhY2VzIHRvIGJlIHVzZWQgYnkgdGhlIEF1dG9OdW1lcmljIG9iamVjdCwgZm9yIGVhY2ggb2YgaXRzIHN0YXRlLCBhbmQgZm9yIGl0cyBmb3JtYXR0ZWQgYW5kIHJhdyB2YWx1ZS5cbiAgICAgKiBCeSBkZWZhdWx0LCB0aGUgYHJhd1ZhbHVlYCBwcmVjaXNpb24gaXMgdGhlIHNhbWUgYXMgdGhlIGZvcm1hdHRlZCB2YWx1ZSBvbmUuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGhvZCBpcyBjbG9zZSB0byB0aGUgb25lIGNhbGxlZCBkdXJpbmcgaW5pdGlhbGl6YXRpb24sIGBfY2FsY3VsYXRlRGVjaW1hbFBsYWNlc09uSW5pdCgpYCwgYnV0IHdpdGggc2xpZ2h0IGRpZmZlcmVuY2Ugc28gdGhhdCB0aGUgYGRlY2ltYWxQbGFjZXMqYCBvcHRpb25zIGFyZSBjb3JyZWN0bHkgdXBkYXRlZCBhcyBuZWVkZWQuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGhvZHMgc2V0IHRoZSBmb2xsb3dpbmcgb3B0aW9ucyBhY2NvcmRpbmdseSB0byB0aGVpciBvd24gdmFsdWUgYW5kIHRoZSBtYW5kYXRvcnkgYGRlY2ltYWxQbGFjZXNgIG9wdGlvbjpcbiAgICAgKiAtIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSAgICAgKG51bGxhYmxlKVxuICAgICAqIC0gZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyICAobnVsbGFibGUpXG4gICAgICogLSBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzIChudWxsYWJsZSlcbiAgICAgKlxuICAgICAqIE5vdGU6IHRoZSBgZGVjaW1hbFBsYWNlc2Agb3B0aW9uIGlzIG9ubHkgdXNlZCBoZXJlIGFuZCBvbmx5IHNlcnZlIHRvIGRlZmluZSB0aG9zZSB0aHJlZSBwcmV2aW91cyBvcHRpb25zIHZhbHVlLlxuICAgICAqIEF1dG9OdW1lcmljIHdpbGwgdGhlbiAqb25seSogdXNlIGBkZWNpbWFsUGxhY2VzUmF3VmFsdWVgLCBgZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyYCBhbmQgYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNgIGZyb20gdGhlcmUuXG4gICAgICpcbiAgICAgKiBUaGlzIG1ldGhvZHMgZGlyZWN0bHkgbW9kaWZpZXMgdGhlIGBzZXR0aW5nc2Agb2JqZWN0IHBhc3NlZCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5ncyBUaGlzIGlzIGFuIG9iamVjdCB3aXRoIHRoZSBuZXcgc2V0dGluZ3MgdG8gdXNlLlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBjdXJyZW50U2V0dGluZ3MgVGhpcyBpcyB0aGUgY3VycmVudCBzZXR0aW5ncyAoYHRoaXMuc2V0dGluZ3NgKSB1c2VkIGJ5IHRoZSBlbGVtZW50LlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9jYWxjdWxhdGVEZWNpbWFsUGxhY2VzT25VcGRhdGUoc2V0dGluZ3MsIGN1cnJlbnRTZXR0aW5ncyA9IG51bGwpIHtcbiAgICAgICAgLy8gQ2hlY2sgdGhlIGBkZWNpbWFsUGxhY2VzKmAgb3B0aW9ucyBhbmQgb3V0cHV0IGFueSB3YXJuaW5ncyBhcyBuZWVkZWQsIGJlZm9yZSBtb2RpZnlpbmcgdGhvc2Ugb3B0aW9uc1xuICAgICAgICB0aGlzLl92YWxpZGF0ZURlY2ltYWxQbGFjZXNSYXdWYWx1ZShzZXR0aW5ncyk7XG5cbiAgICAgICAgLy8gVXBkYXRlIHBoYXNlXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoY3VycmVudFNldHRpbmdzKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgV2hlbiB1cGRhdGluZyB0aGUgc2V0dGluZ3MsIHRoZSBwcmV2aW91cyBvbmVzIHNob3VsZCBiZSBwYXNzZWQgYXMgYW4gYXJndW1lbnQuYCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkZWNpbWFsUGxhY2VzSW5PcHRpb25zID0gJ2RlY2ltYWxQbGFjZXMnIGluIHNldHRpbmdzO1xuICAgICAgICBpZiAoIShkZWNpbWFsUGxhY2VzSW5PcHRpb25zIHx8XG4gICAgICAgICAgICAgICAgJ2RlY2ltYWxQbGFjZXNSYXdWYWx1ZScgaW4gc2V0dGluZ3MgfHxcbiAgICAgICAgICAgICAgICAnZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cycgaW4gc2V0dGluZ3MgfHxcbiAgICAgICAgICAgICAgICAnZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyJyBpbiBzZXR0aW5ncyB8fFxuICAgICAgICAgICAgICAgICdyYXdWYWx1ZURpdmlzb3InIGluIHNldHRpbmdzKSkge1xuICAgICAgICAgICAgLy8gRG8gTm90aGluZyBpZiBubyBkZWNpbWFsIHBsYWNlcy1yZWxhdGVkIG9wdGlvbnMgYXJlIG1vZGlmaWVkXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBPdmVyd3JpdGUgdGhlIGBkZWNpbWFsUGxhY2VzKmAgdmFsdWVzIGlmIHRoZSBgZGVjaW1hbFBsYWNlcypgIG9wdGlvbnMgYXJlIG5vdCBzZXQgaW4gdGhlIGBzZXR0aW5nc2BcbiAgICAgICAgaWYgKGRlY2ltYWxQbGFjZXNJbk9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmICghKCdkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzJyBpbiBzZXR0aW5ncykgfHxcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMudXNlRGVmYXVsdCkgIHtcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzID0gc2V0dGluZ3MuZGVjaW1hbFBsYWNlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCEoJ2RlY2ltYWxQbGFjZXNTaG93bk9uQmx1cicgaW4gc2V0dGluZ3MpIHx8XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ci51c2VEZWZhdWx0KSAge1xuICAgICAgICAgICAgICAgIHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciA9IHNldHRpbmdzLmRlY2ltYWxQbGFjZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKCdkZWNpbWFsUGxhY2VzUmF3VmFsdWUnIGluIHNldHRpbmdzKSB8fFxuICAgICAgICAgICAgICAgIHNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUudXNlRGVmYXVsdCkgIHtcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUgPSBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMpKSB7XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyA9IGN1cnJlbnRTZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQoc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyKSkge1xuICAgICAgICAgICAgICAgIHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciA9IGN1cnJlbnRTZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgdGhlIGFkZGl0aW9uYWwgZGVjaW1hbCBwbGFjZXMgdG8gdGhlIHJhdyB2YWx1ZVxuICAgICAgICBsZXQgYWRkaXRpb25hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IDA7XG4gICAgICAgIGlmIChzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IgJiYgc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJhd1ZhbHVlRGl2aXNvci5ub25lKSB7XG4gICAgICAgICAgICBhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gU3RyaW5nKHNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvcikubGVuZ3RoIC0gMTsgLy8gaWUuIERpdmlkaW5nIGJ5ICcxMDAnIGFkZHMgMiBkZWNpbWFsIHBsYWNlcyB0byB0aGUgbmVlZGVkIHByZWNpc2lvblxuICAgICAgICAgICAgaWYgKGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUgPCAwKSB7XG4gICAgICAgICAgICAgICAgYWRkaXRpb25hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXNldHRpbmdzLmRlY2ltYWxQbGFjZXMgJiYgIXNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSkge1xuICAgICAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gTWF0aC5tYXgoXG4gICAgICAgICAgICAgICAgTWF0aC5tYXgoc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyLCBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzKSArIGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUsXG4gICAgICAgICAgICAgICAgTnVtYmVyKGN1cnJlbnRTZXR0aW5ncy5vcmlnaW5hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSkgKyBhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlXG4gICAgICAgICAgICApO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gTWF0aC5tYXgoXG4gICAgICAgICAgICAgICAgTWF0aC5tYXgoc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyLCBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzKSArIGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUsXG4gICAgICAgICAgICAgICAgTnVtYmVyKHNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSkgKyBhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlXG4gICAgICAgICAgICApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQW5hbHl6ZSBhbmQgc2F2ZSB0aGUgbWluaW11bVZhbHVlIGFuZCBtYXhpbXVtVmFsdWUgaW50ZWdlciBzaXplIGZvciBsYXRlciB1c2VzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfY2FsY3VsYXRlVk1pbkFuZFZNYXhJbnRlZ2VyU2l6ZXMoKSB7XG4gICAgICAgIGxldCBbbWF4aW11bVZhbHVlSW50ZWdlclBhcnRdID0gdGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWUudG9TdHJpbmcoKS5zcGxpdCgnLicpO1xuICAgICAgICBsZXQgW21pbmltdW1WYWx1ZUludGVnZXJQYXJ0XSA9ICghdGhpcy5zZXR0aW5ncy5taW5pbXVtVmFsdWUgJiYgdGhpcy5zZXR0aW5ncy5taW5pbXVtVmFsdWUgIT09IDApP1tdOnRoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlLnRvU3RyaW5nKCkuc3BsaXQoJy4nKTtcbiAgICAgICAgbWF4aW11bVZhbHVlSW50ZWdlclBhcnQgPSBtYXhpbXVtVmFsdWVJbnRlZ2VyUGFydC5yZXBsYWNlKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLCAnJyk7XG4gICAgICAgIG1pbmltdW1WYWx1ZUludGVnZXJQYXJ0ID0gbWluaW11bVZhbHVlSW50ZWdlclBhcnQucmVwbGFjZSh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciwgJycpO1xuXG4gICAgICAgIHRoaXMuc2V0dGluZ3MubUludFBvcyA9IE1hdGgubWF4KG1heGltdW1WYWx1ZUludGVnZXJQYXJ0Lmxlbmd0aCwgMSk7XG4gICAgICAgIHRoaXMuc2V0dGluZ3MubUludE5lZyA9IE1hdGgubWF4KG1pbmltdW1WYWx1ZUludGVnZXJQYXJ0Lmxlbmd0aCwgMSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2FsY3VsYXRlIG9uY2Ugd2hhdCBhcmUgdGhlIGB2YWx1ZXNUb1N0cmluZ3NgIG9wdGlvbiBrZXlzLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2NhbGN1bGF0ZVZhbHVlc1RvU3RyaW5nc0tleXMoKSB7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnZhbHVlc1RvU3RyaW5ncykge1xuICAgICAgICAgICAgdGhpcy52YWx1ZXNUb1N0cmluZ3NLZXlzID0gT2JqZWN0LmtleXModGhpcy5zZXR0aW5ncy52YWx1ZXNUb1N0cmluZ3MpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy52YWx1ZXNUb1N0cmluZ3NLZXlzID0gW107XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWNoZXMgcmVndWxhciBleHByZXNzaW9ucyBmb3IgX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVyc0V4Y2VwdEN1c3RvbURlY2ltYWxDaGFyXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gcmVnZXhcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NhY2hlc1VzdWFsUmVndWxhckV4cHJlc3Npb25zKHNldHRpbmdzLCByZWdleCkge1xuICAgICAgICAvLyBUZXN0IGlmIHRoZXJlIGlzIGEgbmVnYXRpdmUgY2hhcmFjdGVyIGluIHRoZSBzdHJpbmdcbiAgICAgICAgbGV0IG5lZ2F0aXZlU2lnblJlZztcbiAgICAgICAgaWYgKHNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIuaHlwaGVuKSB7XG4gICAgICAgICAgICBuZWdhdGl2ZVNpZ25SZWcgPSBgKFstXFxcXCR7c2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyfV0/KWA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuZWdhdGl2ZVNpZ25SZWcgPSAnKC0/KSc7XG4gICAgICAgIH1cblxuICAgICAgICByZWdleC5hTmVnUmVnQXV0b1N0cmlwID0gbmVnYXRpdmVTaWduUmVnO1xuICAgICAgICBzZXR0aW5ncy5hbGxvd2VkQXV0b1N0cmlwID0gbmV3IFJlZ0V4cChgW14tMDEyMzQ1Njc4OVxcXFwke3NldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJ9XWAsICdnJyk7XG4gICAgICAgIHNldHRpbmdzLm51bVJlZ0F1dG9TdHJpcCA9IG5ldyBSZWdFeHAoYCR7bmVnYXRpdmVTaWduUmVnfSg/OlxcXFwke3NldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJ9PyhbMC05XStcXFxcJHtzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyfVswLTldKyl8KFswLTldKig/OlxcXFwke3NldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJ9WzAtOV0qKT8pKWApO1xuXG4gICAgICAgIC8vIFVzaW5nIHRoaXMgcmVnZXggdmVyc2lvbiBgXiR7cmVnZXguYU5lZ1JlZ0F1dG9TdHJpcH0wKihcXFxcZHwkKWAgZW50aXJlbHkgY2xlYXIgdGhlIGlucHV0IG9uIGJsdXJcbiAgICAgICAgc2V0dGluZ3Muc3RyaXBSZWcgPSBuZXcgUmVnRXhwKGBeJHtyZWdleC5hTmVnUmVnQXV0b1N0cmlwfTAqKFswLTldKWApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1vZGlmeSB0aGUgdXNlciBzZXR0aW5ncyB0byBtYWtlIHRoZW0gJ2V4cGxvaXRhYmxlJyBsYXRlci5cbiAgICAgKi9cbiAgICBfdHJhbnNmb3JtT3B0aW9uc1ZhbHVlc1RvRGVmYXVsdFR5cGVzKCkge1xuICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiB0aGlzLnNldHRpbmdzKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5oYXNPd25Qcm9wZXJ0eShrZXkpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLnNldHRpbmdzW2tleV07XG5cbiAgICAgICAgICAgICAgICAvLyBDb252ZXJ0IHRoZSBzdHJpbmdzICd0cnVlJyBhbmQgJ2ZhbHNlJyB0byBib29sZWFuc1xuICAgICAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gJ3RydWUnIHx8IHZhbHVlID09PSAnZmFsc2UnKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Nba2V5XSA9IHZhbHVlID09PSAndHJ1ZSc7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQ29udmVydCBudW1iZXJzIGluIG9wdGlvbnMgdG8gc3RyaW5nc1xuICAgICAgICAgICAgICAgIC8vVE9ETyBPbmx5IHRyYW5zZm9ybSB0aGUgdmFsdWVzIG9mIHR5cGUgJ051bWJlcicgdG8gJ1N0cmluZycgaWYgaXQncyBhIGN1cnJlbmN5IG51bWJlciAoc28gdGhhdCB3ZSBjYW4gaGF2ZSBiaWcgbnVtYmVycykuIERvIG5vdCBjb252ZXJ0IG90aGVyIG51bWJlcnMgKGllLiBgaGlzdG9yeVNpemVgKVxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Nba2V5XSA9IHZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydCB0aGUgb2xkIHNldHRpbmdzIG9wdGlvbnMgbmFtZSB0byBuZXcgb25lcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAgICovXG4gICAgc3RhdGljIF9jb252ZXJ0T2xkT3B0aW9uc1RvTmV3T25lcyhvcHRpb25zKSB7XG4gICAgICAgIC8vVE9ETyBEZWxldGUgdGhpcyBmdW5jdGlvbiBvbmNlIHRoZSBvbGQgb3B0aW9ucyBhcmUgbm90IHVzZWQgYW55bW9yZVxuICAgICAgICBjb25zdCBvbGRPcHRpb25zQ29udmVydGVyID0ge1xuICAgICAgICAgICAgLy8gT2xkIG9wdGlvbiBuYW1lcywgd2l0aCB0aGVpciBjb3JyZXNwb25kaW5nIG5ldyBuYW1lc1xuICAgICAgICAgICAgYVNlcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2RpZ2l0R3JvdXBTZXBhcmF0b3InLFxuICAgICAgICAgICAgblNlcCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ3Nob3dPbmx5TnVtYmVyc09uRm9jdXMnLFxuICAgICAgICAgICAgZEdyb3VwICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2RpZ2l0YWxHcm91cFNwYWNpbmcnLFxuICAgICAgICAgICAgYURlYyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2RlY2ltYWxDaGFyYWN0ZXInLFxuICAgICAgICAgICAgYWx0RGVjICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2RlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZScsXG4gICAgICAgICAgICBhU2lnbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnY3VycmVuY3lTeW1ib2wnLFxuICAgICAgICAgICAgcFNpZ24gICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2N1cnJlbmN5U3ltYm9sUGxhY2VtZW50JyxcbiAgICAgICAgICAgIHBOZWcgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICduZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCcsXG4gICAgICAgICAgICBhU3VmZml4ICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnc3VmZml4VGV4dCcsXG4gICAgICAgICAgICBvTGltaXRzICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnb3ZlcnJpZGVNaW5NYXhMaW1pdHMnLFxuICAgICAgICAgICAgdk1heCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ21heGltdW1WYWx1ZScsXG4gICAgICAgICAgICB2TWluICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnbWluaW11bVZhbHVlJyxcbiAgICAgICAgICAgIG1EZWMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdkZWNpbWFsUGxhY2VzT3ZlcnJpZGUnLFxuICAgICAgICAgICAgZURlYyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2RlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMnLFxuICAgICAgICAgICAgc2NhbGVEZWNpbWFsICAgICAgICAgICAgICAgICAgICAgIDogJ2RlY2ltYWxQbGFjZXNTaG93bk9uQmx1cicsXG4gICAgICAgICAgICBhU3RvciAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZScsXG4gICAgICAgICAgICBtUm91bmQgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAncm91bmRpbmdNZXRob2QnLFxuICAgICAgICAgICAgYVBhZCAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2FsbG93RGVjaW1hbFBhZGRpbmcnLFxuICAgICAgICAgICAgbkJyYWNrZXQgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ25lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyJyxcbiAgICAgICAgICAgIHdFbXB0eSAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdlbXB0eUlucHV0QmVoYXZpb3InLFxuICAgICAgICAgICAgbFplcm8gICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2xlYWRpbmdaZXJvJyxcbiAgICAgICAgICAgIGFGb3JtICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdmb3JtYXRPblBhZ2VMb2FkJyxcbiAgICAgICAgICAgIHNOdW1iZXIgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdzZWxlY3ROdW1iZXJPbmx5JyxcbiAgICAgICAgICAgIGFuRGVmYXVsdCAgICAgICAgICAgICAgICAgICAgICAgICA6ICdkZWZhdWx0VmFsdWVPdmVycmlkZScsXG4gICAgICAgICAgICB1blNldE9uU3VibWl0ICAgICAgICAgICAgICAgICAgICAgOiAndW5mb3JtYXRPblN1Ym1pdCcsXG4gICAgICAgICAgICBvdXRwdXRUeXBlICAgICAgICAgICAgICAgICAgICAgICAgOiAnb3V0cHV0Rm9ybWF0JyxcbiAgICAgICAgICAgIGRlYnVnICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdzaG93V2FybmluZ3MnLFxuXG4gICAgICAgICAgICAvLyBDdXJyZW50IG9wdGlvbnMgOlxuICAgICAgICAgICAgYWxsb3dEZWNpbWFsUGFkZGluZyAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkZvY3VzICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBjcmVhdGVMb2NhbExpc3QgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgY3VycmVuY3lTeW1ib2wgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXMgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBkZWZhdWx0VmFsdWVPdmVycmlkZSAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZGlnaXRhbEdyb3VwU3BhY2luZyAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3IgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBkaXZpc29yV2hlblVuZm9jdXNlZCAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZW1wdHlJbnB1dEJlaGF2aW9yICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGV2ZW50QnViYmxlcyAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBldmVudElzQ2FuY2VsYWJsZSAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZmFpbE9uVW5rbm93bk9wdGlvbiAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGZvcm1hdE9uUGFnZUxvYWQgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBoaXN0b3J5U2l6ZSAgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgaXNDYW5jZWxsYWJsZSAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGxlYWRpbmdaZXJvICAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBtYXhpbXVtVmFsdWUgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgbWluaW11bVZhbHVlICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG1vZGlmeVZhbHVlT25XaGVlbCAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBuZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG5lZ2F0aXZlU2lnbkNoYXJhY3RlciAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBub0V2ZW50TGlzdGVuZXJzICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgb25JbnZhbGlkUGFzdGUgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdCAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBvdmVycmlkZU1pbk1heExpbWl0cyAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgcG9zaXRpdmVTaWduQ2hhcmFjdGVyICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHJhd1ZhbHVlRGl2aXNvciAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICByZWFkT25seSAgICAgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgcm91bmRpbmdNZXRob2QgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBzZWxlY3ROdW1iZXJPbmx5ICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgc2VsZWN0T25Gb2N1cyAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHNlcmlhbGl6ZVNwYWNlcyAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBzaG93T25seU51bWJlcnNPbkZvY3VzICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgc2hvd1Bvc2l0aXZlU2lnbiAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHNob3dXYXJuaW5ncyAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBzdHlsZVJ1bGVzICAgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgc3VmZml4VGV4dCAgICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHN5bWJvbFdoZW5VbmZvY3VzZWQgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICB1bmZvcm1hdE9uSG92ZXIgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgdW5mb3JtYXRPblN1Ym1pdCAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHZhbHVlc1RvU3RyaW5ncyAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICB3YXRjaEV4dGVybmFsQ2hhbmdlcyAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgd2hlZWxPbiAgICAgICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHdoZWVsU3RlcCAgICAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG5cbiAgICAgICAgICAgIC8vIEFkZGl0aW9uYWwgaW5mb3JtYXRpb24gdGhhdCBhcmUgYWRkZWQgdG8gdGhlIGBzZXR0aW5nc2Agb2JqZWN0IDpcbiAgICAgICAgICAgIC8vVE9ETyBGaW5kIGEgd2F5IHRvIGV4Y2x1ZGUgdGhvc2UgaW50ZXJuYWwgZGF0YSBmcm9tIHRoZSBzZXR0aW5ncyBvYmplY3QgKGlkZWFsbHkgYnkgdXNpbmcgYW5vdGhlciBvYmplY3QsIG9yIGJldHRlciB5ZXQsIGNsYXNzIGF0dHJpYnV0ZXMpIC0tPlxuICAgICAgICAgICAgYWxsb3dlZEF1dG9TdHJpcCAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGlzTmVnYXRpdmVTaWduQWxsb3dlZCAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBpc1Bvc2l0aXZlU2lnbkFsbG93ZWQgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgbUludE5lZyAgICAgICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG1JbnRQb3MgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBudW1SZWdBdXRvU3RyaXAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgb3JpZ2luYWxEZWNpbWFsUGxhY2VzICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlICAgICA6IHRydWUsXG4gICAgICAgICAgICBzdHJpcFJlZyAgICAgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICB9O1xuXG4gICAgICAgIGZvciAoY29uc3Qgb3B0aW9uIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KG9wdGlvbikpIHtcbiAgICAgICAgICAgICAgICBpZiAob2xkT3B0aW9uc0NvbnZlcnRlcltvcHRpb25dID09PSB0cnVlKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIElmIHRoZSBvcHRpb24gaXMgYSAnbmV3JyBvcHRpb24sIHdlIGNvbnRpbnVlIGxvb3BpbmdcbiAgICAgICAgICAgICAgICAgICAgY29udGludWU7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKG9sZE9wdGlvbnNDb252ZXJ0ZXIuaGFzT3duUHJvcGVydHkob3B0aW9uKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBFbHNlIHdlIGhhdmUgYW4gJ29sZCcgb3B0aW9uIG5hbWVcbiAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgWW91IGFyZSB1c2luZyB0aGUgZGVwcmVjYXRlZCBvcHRpb24gbmFtZSAnJHtvcHRpb259Jy4gUGxlYXNlIHVzZSAnJHtvbGRPcHRpb25zQ29udmVydGVyW29wdGlvbl19JyBpbnN0ZWFkIGZyb20gbm93IG9uLiBUaGUgb2xkIG9wdGlvbiBuYW1lIHdpbGwgYmUgZHJvcHBlZCB2ZXJ5IHNvb27ihKIuYCwgdHJ1ZSk7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gVGhlbiB3ZSBtb2RpZnkgdGhlIGluaXRpYWwgb3B0aW9uIG9iamVjdCB0byB1c2UgdGhlIG5ldyBvcHRpb25zIGluc3RlYWQgb2YgdGhlIG9sZCBvbmVzXG4gICAgICAgICAgICAgICAgICAgIG9wdGlvbnNbb2xkT3B0aW9uc0NvbnZlcnRlcltvcHRpb25dXSA9IG9wdGlvbnNbb3B0aW9uXTtcbiAgICAgICAgICAgICAgICAgICAgZGVsZXRlIG9wdGlvbnNbb3B0aW9uXTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKG9wdGlvbnMuZmFpbE9uVW5rbm93bk9wdGlvbikge1xuICAgICAgICAgICAgICAgICAgICAvLyAuLi5vciB0aGUgb3B0aW9uIG5hbWUgaXMgdW5rbm93bi4gVGhpcyBtZWFucyB0aGVyZSBpcyBhIHByb2JsZW0gd2l0aCB0aGUgb3B0aW9ucyBvYmplY3QsIHRoZXJlZm9yZSB3ZSB0aHJvdyBhbiBlcnJvci5cbiAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgT3B0aW9uIG5hbWUgJyR7b3B0aW9ufScgaXMgdW5rbm93bi4gUGxlYXNlIGZpeCB0aGUgb3B0aW9ucyBwYXNzZWQgdG8gYXV0b051bWVyaWNgKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoJ21EZWMnIGluIG9wdGlvbnMpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoJ1RoZSBvbGQgYG1EZWNgIG9wdGlvbiBoYXMgYmVlbiBkZXByZWNhdGVkIGluIGZhdm9yIG9mIG1vcmUgYWNjdXJhdGUgb3B0aW9ucyA7IGBkZWNpbWFsUGxhY2VzYCwgYGRlY2ltYWxQbGFjZXNSYXdWYWx1ZWAsIGBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzYCBhbmQgYGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cmAuJywgdHJ1ZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbmFseXNlIHRoZSBzZXR0aW5ncy9vcHRpb25zIHBhc3NlZCBieSB0aGUgdXNlciwgdmFsaWRhdGUgYW5kIGNsZWFuIHRoZW0sIHRoZW4gc2V0IHRoZW0gaW50byBgdGhpcy5zZXR0aW5nc2AuXG4gICAgICogTm90ZTogVGhpcyBzZXRzIHRoZSBzZXR0aW5ncyB0byBgbnVsbGAgaWYgc29tZWhvdyB0aGUgc2V0dGluZ3Mgb2JqZXQgaXMgdW5kZWZpbmVkIG9yIGVtcHR5XG4gICAgICogICAgICAgSWYgb25seSBgZGVjaW1hbFBsYWNlc2AgaXMgZGVmaW5lZCBpbiB0aGUgb3B0aW9uLCBvdmVyd3JpdGUgdGhlIG90aGVyIGRlY2ltYWxQbGFjZXMqIG9wdGlvbnMsIG90aGVyd2lzZSwgdXNlIHRob3NlIG9wdGlvbnNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAgICogQHBhcmFtIHtib29sZWFufSB1cGRhdGUgLSBJZiBzZXQgdG8gYHRydWVgLCB0aGVuIHRoZSBzZXR0aW5ncyBhbHJlYWR5IGV4aXN0cyBhbmQgdGhpcyBmdW5jdGlvbiBvbmx5IHVwZGF0ZXMgdGhlbSBpbnN0ZWFkIG9mIHJlY3JlYXRpbmcgdGhlbSBmcm9tIHNjcmF0Y2hcbiAgICAgKiBAdGhyb3dzXG4gICAgICovXG4gICAgX3NldFNldHRpbmdzKG9wdGlvbnMsIHVwZGF0ZSA9IGZhbHNlKSB7XG4gICAgICAgIC8vIElmIHRoZSB1c2VyIHVzZWQgb2xkIG9wdGlvbnMsIHdlIGNvbnZlcnQgdGhlbSB0byBuZXcgb25lc1xuICAgICAgICBpZiAodXBkYXRlIHx8ICFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucykpIHtcbiAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IuX2NvbnZlcnRPbGRPcHRpb25zVG9OZXdPbmVzKG9wdGlvbnMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHVwZGF0ZSkge1xuICAgICAgICAgICAgLy8gVGhlIHNldHRpbmdzIGFyZSB1cGRhdGVkXG4gICAgICAgICAgICAvLyBVcGRhdGUgdGhlIG9yaWdpbmFsIGRhdGEsIGlmIGl0IGhhcyBjaGFuZ2VkXG4gICAgICAgICAgICBjb25zdCBkZWNpbWFsUGxhY2VzUmF3VmFsdWVJbk9wdGlvbnMgPSAnZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlJyBpbiBvcHRpb25zO1xuICAgICAgICAgICAgaWYgKGRlY2ltYWxQbGFjZXNSYXdWYWx1ZUluT3B0aW9ucykge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Mub3JpZ2luYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUgPSBvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgZGVjaW1hbFBsYWNlc0luT3B0aW9ucyA9ICdkZWNpbWFsUGxhY2VzJyBpbiBvcHRpb25zO1xuICAgICAgICAgICAgaWYgKGRlY2ltYWxQbGFjZXNJbk9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLm9yaWdpbmFsRGVjaW1hbFBsYWNlcyA9IG9wdGlvbnMuZGVjaW1hbFBsYWNlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVGhlbiB1cGRhdGUgYWxsIHRoZSBgZGVjaW1hbFBsYWNlcypgIG9wdGlvbnNcbiAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IuX2NhbGN1bGF0ZURlY2ltYWxQbGFjZXNPblVwZGF0ZShvcHRpb25zLCB0aGlzLnNldHRpbmdzKTtcblxuICAgICAgICAgICAgLy8gRmluYWxseSBnZW5lcmF0ZSB0aGUgdXBkYXRlZCBzZXR0aW5ncyBvYmplY3QgdG8gdXNlXG4gICAgICAgICAgICB0aGlzLl9tZXJnZVNldHRpbmdzKG9wdGlvbnMpOyAvL1RPRE8gQ2hlY2sgdGhhdCB0aGUgYHN0eWxlUnVsZXNgIG9wdGlvbiBpcyBjb3JyZWN0bHkgY2xvbmVkIChkdWUgdG8gZGVwdGggY2xvbmluZyBsaW1pdGF0aW9uKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgLy8gVGhlIHNldHRpbmdzIGFyZSBnZW5lcmF0ZWQgZm9yIHRoZSBmaXJzdCB0aW1lXG4gICAgICAgICAgICB0aGlzLnNldHRpbmdzID0ge307XG4gICAgICAgICAgICAvLyBJZiB3ZSBjb3VsZG4ndCBncmFiIGFueSBzZXR0aW5ncywgY3JlYXRlIHRoZW0gZnJvbSB0aGUgZGVmYXVsdCBvbmVzIGFuZCBjb21iaW5lIHRoZW0gd2l0aCB0aGUgb3B0aW9ucyBwYXNzZWQgYXMgYSBwYXJhbWV0ZXIgYXMgd2VsbCBhcyB3aXRoIHRoZSBIVE1MNSBgZGF0YS0qYCBpbmZvICh2aWEgYHRoaXMuZG9tRWxlbWVudC5kYXRhc2V0YCksIGlmIGFueS5cbiAgICAgICAgICAgIHRoaXMuX21lcmdlU2V0dGluZ3ModGhpcy5jb25zdHJ1Y3Rvci5nZXREZWZhdWx0Q29uZmlnKCksIHRoaXMuZG9tRWxlbWVudC5kYXRhc2V0LCBvcHRpb25zLCB7IHJhd1ZhbHVlIDogdGhpcy5kZWZhdWx0UmF3VmFsdWUgfSk7XG4gICAgICAgICAgICB0aGlzLmNhcmV0Rml4ID0gZmFsc2U7XG4gICAgICAgICAgICB0aGlzLnRocm93SW5wdXQgPSB0cnVlOyAvLyBUaHJvdyBpbnB1dCBldmVudFxuICAgICAgICAgICAgdGhpcy5hbGxvd2VkVGFnTGlzdCA9IEF1dG9OdW1lcmljRW51bS5hbGxvd2VkVGFnTGlzdDtcbiAgICAgICAgICAgIHRoaXMucnVuT25jZSA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5ob3ZlcmVkV2l0aEFsdCA9IGZhbHNlOyAvLyBLZWVwIHRyYWNrcyBpZiB0aGUgY3VycmVudCBBdXRvTnVtZXJpYyBlbGVtZW50IGlzIGhvdmVyZWQgYnkgdGhlIG1vdXNlIGN1cnNvciB3aGlsZSBgQWx0YCBpcyBwcmVzc2VkXG4gICAgICAgIH1cblxuICAgICAgICAvLyBNb2RpZnkgdGhlIHVzZXIgc2V0dGluZ3MgdG8gbWFrZSB0aGVtICdleHBsb2l0YWJsZSdcbiAgICAgICAgdGhpcy5fdHJhbnNmb3JtT3B0aW9uc1ZhbHVlc1RvRGVmYXVsdFR5cGVzKCk7XG5cbiAgICAgICAgLy8gSW1tZWRpYXRlbHkgcnVuIHRoZSBjYWxsYmFja3MgdGhhdCBjb3VsZCB1cGRhdGUgdGhlIHNldHRpbmdzIG9iamVjdFxuICAgICAgICB0aGlzLl9ydW5DYWxsYmFja3NGb3VuZEluVGhlU2V0dGluZ3NPYmplY3QoKTtcblxuICAgICAgICAvLyBJbXByb3ZlIHRoZSBgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnRgIG9wdGlvbiBpZiBuZWVkZWRcbiAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fY29ycmVjdE5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50T3B0aW9uKHRoaXMuc2V0dGluZ3MpO1xuXG4gICAgICAgIC8vIFNldCB0aGUgYGNhcmV0UG9zaXRpb25PbkZvY3VzYCBhbmQgYHNlbGVjdE9uRm9jdXNgIG9wdGlvbnMgc28gdGhhdCB0aGV5IGRvIG5vdCBjb25mbGljdCwgaWYgb25lIG9mIHRob3NlIGhhdmUgYmVlbiBzZXQgbWFudWFsbHkgYnkgdGhlIHVzZXIuXG4gICAgICAgIC8vIElmIG9yZGVyIHRvIGNoZWNrIHRoYXQsIHdlIHRha2UgYSBsb29rIGF0IHRoZSBvcmlnaW5hbCBvcHRpb25zIHRoZSB1c2VyIHBhc3NlZCBhcyBhbiBhcmd1bWVudCwgbm90IGB0aGlzLnNldHRpbmdzYCB0aGF0IGhhdmUgYmVlbiBtZXJnZWQgd2l0aCB0aGUgZGVmYXVsdCBzZXR0aW5ncy4gLy9UT0RPIENoZWNrIHRoZSB2YWxpZGl0eSBvZiB0aGF0IGNvbW1lbnRcbiAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fY29ycmVjdENhcmV0UG9zaXRpb25PbkZvY3VzQW5kU2VsZWN0T25Gb2N1c09wdGlvbnModGhpcy5zZXR0aW5ncyk7XG5cbiAgICAgICAgLy8gRGVmaW5lIGlmIHRoZSBuZWdhdGl2ZSBvciBwb3NpdGl2ZSBzaWducyBhcmUgYWxsb3dlZFxuICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl9zZXROZWdhdGl2ZVBvc2l0aXZlU2lnblBlcm1pc3Npb25zKHRoaXMuc2V0dGluZ3MpO1xuXG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIChkdXJpbmcgdGhlIGVsZW1lbnQgaW5pdGlhbGl6YXRpb24pXG4gICAgICAgIGlmICghdXBkYXRlKSB7XG4gICAgICAgICAgICAvLyBNYWtlIHN1cmUgdGhlIGBvcmlnaW5hbERlY2ltYWxQbGFjZXNgIGluZm8gaXMgc2V0XG4gICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMpIHx8ICFvcHRpb25zLmRlY2ltYWxQbGFjZXMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLm9yaWdpbmFsRGVjaW1hbFBsYWNlcyA9IG51bGw7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Mub3JpZ2luYWxEZWNpbWFsUGxhY2VzID0gb3B0aW9ucy5kZWNpbWFsUGxhY2VzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTYXZlIHRoZSBgb3JpZ2luYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWVgIGluZm9cbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Mub3JpZ2luYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUgPSB0aGlzLnNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZTtcblxuICAgICAgICAgICAgLy8gVGhlbiB1cGRhdGUgYWxsIHRoZSBgZGVjaW1hbFBsYWNlcypgIG9wdGlvbnNcbiAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IuX2NhbGN1bGF0ZURlY2ltYWxQbGFjZXNPbkluaXQodGhpcy5zZXR0aW5ncyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGRpdGlvbmFsIGNoYW5nZXMgdG8gdGhlIHNldHRpbmdzIG9iamVjdFxuICAgICAgICB0aGlzLl9jYWxjdWxhdGVWTWluQW5kVk1heEludGVnZXJTaXplcygpO1xuICAgICAgICB0aGlzLl9zZXRUcmFpbGluZ05lZ2F0aXZlU2lnbkluZm8oKTtcbiAgICAgICAgdGhpcy5yZWdleCA9IHt9OyAvLyBDcmVhdGUgdGhlIG9iamVjdCB0aGF0IHdpbGwgc3RvcmUgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbnNcbiAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fY2FjaGVzVXN1YWxSZWd1bGFyRXhwcmVzc2lvbnModGhpcy5zZXR0aW5ncywgdGhpcy5yZWdleCk7XG4gICAgICAgIHRoaXMuY29uc3RydWN0b3IuX3NldEJyYWNrZXRzKHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICB0aGlzLl9jYWxjdWxhdGVWYWx1ZXNUb1N0cmluZ3NLZXlzKCk7XG5cbiAgICAgICAgLy8gVmFsaWRhdGUgdGhlIHNldHRpbmdzLiBCb3RoIHRlc3RzIHRocm93cyBpZiBuZWNlc3NhcnkuXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0VtcHR5T2JqKHRoaXMuc2V0dGluZ3MpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKCdVbmFibGUgdG8gc2V0IHRoZSBzZXR0aW5ncywgdGhvc2UgYXJlIGludmFsaWQgOyBhbiBlbXB0eSBvYmplY3Qgd2FzIGdpdmVuLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci52YWxpZGF0ZSh0aGlzLnNldHRpbmdzLCBmYWxzZSwgb3B0aW9ucyk7XG5cbiAgICAgICAgLy8gT3JpZ2luYWwgc2V0dGluZ3Mgc2F2ZWQgZm9yIHVzZSB3aGVuIGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMsIGRpdmlzb3JXaGVuVW5mb2N1c2VkICYgc2hvd09ubHlOdW1iZXJzT25Gb2N1cyBvcHRpb25zIGFyZSBiZWluZyB1c2VkXG4gICAgICAgIHRoaXMuX2tlZXBBbk9yaWdpbmFsU2V0dGluZ3NDb3B5KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGVmaW5lIGlmIHRoZSBuZWdhdGl2ZSBvciBwb3NpdGl2ZSBzaWducyBhcmUgYWxsb3dlZCwgYW5kIHVwZGF0ZSB0aGUgZ2l2ZW4gc2V0dGluZ3Mgb2JqZWN0IGRpcmVjdGx5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3NldE5lZ2F0aXZlUG9zaXRpdmVTaWduUGVybWlzc2lvbnMoc2V0dGluZ3MpIHtcbiAgICAgICAgc2V0dGluZ3MuaXNOZWdhdGl2ZVNpZ25BbGxvd2VkID0gc2V0dGluZ3MubWluaW11bVZhbHVlIDwgMDtcbiAgICAgICAgc2V0dGluZ3MuaXNQb3NpdGl2ZVNpZ25BbGxvd2VkID0gc2V0dGluZ3MubWF4aW11bVZhbHVlID49IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ29udmVydCB0aGUgYHZhbHVlYCBwYXJhbWV0ZXIgdGhhdCBjYW4gZWl0aGVyIGJlIDpcbiAgICAgKiAtIGEgcmVhbCBudW1iZXIsXG4gICAgICogLSBhIG51bWJlciByZXByZXNlbnRlZCBpbiB0aGUgc2NpZW50aWZpYyBub3RhdGlvbiAoaWUuIC0xMjMuNDU2N2UtNilcbiAgICAgKiAtIGEgc3RyaW5nIHJlcHJlc2VudGluZyBhIHJlYWwgbnVtYmVyLCBvclxuICAgICAqIC0gYSBzdHJpbmcgcmVwcmVzZW50aW5nIGEgbG9jYWxpemVkIG51bWJlciAod2l0aCBzcGVjaWZpYyBncm91cCBzZXBhcmF0b3JzIGFuZCBkZWNpbWFsIGNoYXJhY3RlciksXG4gICAgICogLi4udG8gYSBzdHJpbmcgcmVwcmVzZW50aW5nIGEgcmVhbCAnamF2YXNjcmlwdCcgbnVtYmVyIChpZS4gJzEyMzQnIG9yICcxMjM0LjU2NycpLlxuICAgICAqXG4gICAgICogVGhpcyBmdW5jdGlvbiByZXR1cm5zIGBOYU5gIGlmIHN1Y2ggY29udmVyc2lvbiBmYWlscy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7aW50fGZsb2F0fHN0cmluZ30gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfE5hTn1cbiAgICAgKi9cbiAgICBzdGF0aWMgX3RvTnVtZXJpY1ZhbHVlKHZhbHVlLCBzZXR0aW5ncykge1xuICAgICAgICAvL1hYWCBOb3RlOyB0aGlzIGZ1bmN0aW9uIGlzIHN0YXRpYyBzaW5jZSB3ZSBuZWVkIHRvIHBhc3MgYSBgc2V0dGluZ3NgIG9iamVjdCB3aGVuIGNhbGxpbmcgdGhlIHN0YXRpYyBgQXV0b051bWVyaWMuZm9ybWF0KClgIG1ldGhvZFxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIoTnVtYmVyKHZhbHVlKSkpIHtcbiAgICAgICAgICAgIC8vIFRoZSB2YWx1ZSBoYXMgZWl0aGVyIGFscmVhZHkgYmVlbiBzdHJpcHBlZCwgb3IgYSAncmVhbCcgamF2YXNjcmlwdCBudW1iZXIgaXMgcGFzc2VkIGFzIGEgcGFyYW1ldGVyXG4gICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0hlbHBlci5zY2llbnRpZmljVG9EZWNpbWFsKHZhbHVlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEVsc2UgaWYgaXQncyBhIHN0cmluZyB0aGF0IGBOdW1iZXIoKWAgY2Fubm90IHR5cGVjYXN0LCB0aGVuIHdlIHRyeSB0byBjb252ZXJ0IHRoZSBsb2NhbGl6ZWQgbnVtZXJpYyBzdHJpbmcgdG8gYSBudW1lcmljIG9uZVxuICAgICAgICAgICAgLy8gQ29udmVydCB0aGUgdmFsdWUgdG8gYSBudW1lcmljIHN0cmluZywgc3RyaXBwaW5nIHVubmVjZXNzYXJ5IGNoYXJhY3RlcnMgaW4gdGhlIHByb2Nlc3NcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuX2NvbnZlcnRUb051bWVyaWNTdHJpbmcodmFsdWUudG9TdHJpbmcoKSwgc2V0dGluZ3MpO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGUgcmVzdWx0IGlzIHN0aWxsIG5vdCBhIG51bWVyaWMgc3RyaW5nLCB0aGVuIHdlIHRocm93IGEgd2FybmluZ1xuICAgICAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcihOdW1iZXIocmVzdWx0KSkpIHtcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBUaGUgZ2l2ZW4gdmFsdWUgXCIke3ZhbHVlfVwiIGNhbm5vdCBiZSBjb252ZXJ0ZWQgdG8gYSBudW1lcmljIG9uZSBhbmQgdGhlcmVmb3JlIGNhbm5vdCBiZSB1c2VkIGFwcHJvcHJpYXRlbHkuYCwgc2V0dGluZ3Muc2hvd1dhcm5pbmdzKTtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBOYU47XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgcGFzdGVkIHRleHQgdGhhdCB3aWxsIGJlIHVzZWQsIGJ5IHN0cmlwcGluZyBtb3N0IG5vbi1udW1lcmljIGNoYXJhY3RlcnNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0XG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBfcHJlcGFyZVBhc3RlZFRleHQodGV4dCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci5fc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzKHRleHQsIHRoaXMuc2V0dGluZ3MsIHRydWUsIHRoaXMuaXNGb2N1c2VkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gVFJVRSBpZiB0aGUgZ2l2ZW4gdmFsdWUgKGEgbnVtYmVyIGFzIGEgc3RyaW5nKSBpcyB3aXRoaW4gdGhlIHJhbmdlIHNldCBpbiB0aGUgc2V0dGluZ3MgYG1pbmltdW1WYWx1ZWAgYW5kIGBtYXhpbXVtVmFsdWVgLCBGQUxTRSBvdGhlcndpc2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gcGFyc2VkTWluVmFsdWUgUGFyc2VkIHZpYSB0aGUgYHBhcnNlU3RyKClgIGZ1bmN0aW9uXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHBhcnNlZE1heFZhbHVlIFBhcnNlZCB2aWEgdGhlIGBwYXJzZVN0cigpYCBmdW5jdGlvblxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBfY2hlY2tJZkluUmFuZ2UodmFsdWUsIHBhcnNlZE1pblZhbHVlLCBwYXJzZWRNYXhWYWx1ZSkge1xuICAgICAgICBjb25zdCBwYXJzZWRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLnBhcnNlU3RyKHZhbHVlKTtcbiAgICAgICAgcmV0dXJuIEF1dG9OdW1lcmljSGVscGVyLnRlc3RNaW5NYXgocGFyc2VkTWluVmFsdWUsIHBhcnNlZFZhbHVlKSA+IC0xICYmIEF1dG9OdW1lcmljSGVscGVyLnRlc3RNaW5NYXgocGFyc2VkTWF4VmFsdWUsIHBhcnNlZFZhbHVlKSA8IDE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBzZWxlY3Rpb24gdmFsdWVzIGFzIHdlbGwgYXMgcmVzZXRzIHRoZSBpbnRlcm5hbCBzdGF0ZSBvZiB0aGUgY3VycmVudCBBdXRvTnVtZXJpYyBvYmplY3QuXG4gICAgICogVGhpcyBrZWVwcyB0cmFja3Mgb2YgdGhlIGN1cnJlbnQgc2VsZWN0aW9uIGFuZCByZXNldHMgdGhlICdwcm9jZXNzZWQnIHN0YXRlLlxuICAgICAqXG4gICAgICogTm90ZSA6IFRoaXMgc3RhdGUgY2FuIGNoYW5nZSBiZXR3ZWVuIHRoZSBrZXlkb3duLCBrZXlwcmVzcyBhbmQga2V5dXAgZXZlbnRzLCB0aGF0J3Mgd2h5XG4gICAgICogICAgICAgIHRoaXMgZnVuY3Rpb24gaXMgY2FsbGVkIG9uIGVhY2ggZXZlbnQgaGFuZGxlci5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3VwZGF0ZUludGVybmFsUHJvcGVydGllcygpIHtcbiAgICAgICAgdGhpcy5zZWxlY3Rpb24gPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50U2VsZWN0aW9uKHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgIHRoaXMucHJvY2Vzc2VkID0gZmFsc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBgZXZlbnQua2V5YCBhdHRyaWJ1dGUgdGhhdCB0cmlnZ2VyZWQgdGhlIGdpdmVuIGV2ZW50LlxuICAgICAqXG4gICAgICogYGV2ZW50LmtleWAgZGVzY3JpYmVzOlxuICAgICAqIC0gdGhlIGtleSBuYW1lIChpZiBhIG5vbi1wcmludGFibGUgY2hhcmFjdGVyKSxcbiAgICAgKiAtIG9yIGRpcmVjdGx5IHRoZSBjaGFyYWN0ZXIgdGhhdCByZXN1bHQgZnJvbSB0aGUga2V5IHByZXNzIHVzZWQgdG8gdHJpZ2dlciB0aGUgZXZlbnQuXG4gICAgICpcbiAgICAgKiBAbGluayBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvS2V5Ym9hcmRFdmVudC9rZXlcbiAgICAgKiBUaGUga2V5IGxpc3QgaXMgZGVzY3JpYmVkIGhlcmU6XG4gICAgICogQGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0tleWJvYXJkRXZlbnQva2V5L0tleV9WYWx1ZXNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RXZlbnR8S2V5Ym9hcmRFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3VwZGF0ZUV2ZW50S2V5SW5mbyhlKSB7XG4gICAgICAgIHRoaXMuZXZlbnRLZXkgPSBBdXRvTnVtZXJpY0hlbHBlci5jaGFyYWN0ZXIoZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2F2ZSB0aGUgdW5mb3JtYXR0ZWQgZWxlbWVudCB2YWx1ZS5cbiAgICAgKiBUaGlzIGlzIHVzZWQgaW4gdGhlICdjYW5jZWxsYWJsZScgZmVhdHVyZSB3aGVyZSB0aGUgZWxlbWVudCB2YWx1ZSBpcyBzYXZlZCBvbiBmb2N1cyBhbmQgaW5wdXQgdmFsaWRhdGlvbiwgdG8gYmUgdXNlZCBpZiB0aGUgdXNlciB3YW50cyB0byBjYW5jZWwgaGlzIG1vZGlmaWNhdGlvbnMgYnkgaGl0dGluZyB0aGUgJ0VzY2FwZScga2V5LlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2F2ZUNhbmNlbGxhYmxlVmFsdWUoKSB7XG4gICAgICAgIHRoaXMuc2F2ZWRDYW5jZWxsYWJsZVZhbHVlID0gdGhpcy5yYXdWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIHRleHQgc2VsZWN0aW9uIGluc2lkZSB0aGUgaW5wdXQgd2l0aCB0aGUgZ2l2ZW4gc3RhcnQgYW5kIGVuZCBwb3NpdGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7aW50fSBzdGFydFxuICAgICAqIEBwYXJhbSB7aW50fSBlbmRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zZXRTZWxlY3Rpb24oc3RhcnQsIGVuZCkge1xuICAgICAgICAvL1RPRE8gdXNlIHRoaXMgZnVuY3Rpb24gdG8gcmVwbGFjZSB0aGUgZGlyZWN0IGNhbGxzIHRvIGBzZXRFbGVtZW50U2VsZWN0aW9uKClgLCB3aGVyZXZlciBwb3NzaWJsZVxuICAgICAgICBzdGFydCA9IE1hdGgubWF4KHN0YXJ0LCAwKTtcbiAgICAgICAgZW5kID0gTWF0aC5taW4oZW5kLCBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KS5sZW5ndGgpO1xuICAgICAgICB0aGlzLnNlbGVjdGlvbiA9IHtcbiAgICAgICAgICAgIHN0YXJ0LFxuICAgICAgICAgICAgZW5kLFxuICAgICAgICAgICAgbGVuZ3RoOiBlbmQgLSBzdGFydCxcbiAgICAgICAgfTtcblxuICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50U2VsZWN0aW9uKHRoaXMuZG9tRWxlbWVudCwgc3RhcnQsIGVuZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBjYXJldCBwb3NpdGlvbiBpbnNpZGUgdGhlIGlucHV0IGF0IHRoZSBnaXZlbiBwb3NpdGlvbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7aW50fSBwb3NpdGlvblxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NldENhcmV0UG9zaXRpb24ocG9zaXRpb24pIHtcbiAgICAgICAgdGhpcy5fc2V0U2VsZWN0aW9uKHBvc2l0aW9uLCBwb3NpdGlvbik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGFuIGFycmF5IGNvbnRhaW5pbmcgdGhlIHN0cmluZyBwYXJ0cyBsb2NhdGVkIG9uIHRoZSBsZWZ0IGFuZCByaWdodCBzaWRlIG9mIHRoZSBjYXJldCBvciBzZWxlY3Rpb24uXG4gICAgICogVGhvc2UgcGFydHMgYXJlIGxlZnQgJ3VudG91Y2hlZCcsIGllLiBmb3JtYXR0ZWQgYnkgYXV0b051bWVyaWMuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7W3N0cmluZywgc3RyaW5nXX0gVGhlIHBhcnRzIG9uIHRoZSBsZWZ0IGFuZCByaWdodCBvZiB0aGUgY2FyZXQgb3Igc2VsZWN0aW9uXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0TGVmdEFuZFJpZ2h0UGFydEFyb3VuZFRoZVNlbGVjdGlvbigpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgY29uc3QgbGVmdCA9IHZhbHVlLnN1YnN0cmluZygwLCB0aGlzLnNlbGVjdGlvbi5zdGFydCk7XG4gICAgICAgIGNvbnN0IHJpZ2h0ID0gdmFsdWUuc3Vic3RyaW5nKHRoaXMuc2VsZWN0aW9uLmVuZCwgdmFsdWUubGVuZ3RoKTtcblxuICAgICAgICByZXR1cm4gW2xlZnQsIHJpZ2h0XTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYW4gYXJyYXkgY29udGFpbmluZyB0aGUgc3RyaW5nIHBhcnRzIGxvY2F0ZWQgb24gdGhlIGxlZnQgYW5kIHJpZ2h0IHNpZGUgb2YgdGhlIGNhcmV0IG9yIHNlbGVjdGlvbi5cbiAgICAgKiBUaG9zZSBwYXJ0cyBhcmUgdW5mb3JtYXR0ZWQgKHN0cmlwcGVkKSBvZiBhbnkgbm9uLW51bWJlcnMgY2hhcmFjdGVycywgYW5kIGFueSB0cmFpbGluZyBuZWdhdGl2ZSBjaGFyYWN0ZXIgaXMgcHV0IGJhY2sgb24gdGhlIGxlZnQgaGFuZCBzaWRlIG9mIHRoZSBudW1iZXIuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7W3N0cmluZywgc3RyaW5nXX0gVGhlIHBhcnRzIG9uIHRoZSBsZWZ0IGFuZCByaWdodCBvZiB0aGUgY2FyZXQgb3Igc2VsZWN0aW9uLCB1bmZvcm1hdHRlZC5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9nZXRVbmZvcm1hdHRlZExlZnRBbmRSaWdodFBhcnRBcm91bmRUaGVTZWxlY3Rpb24oKSB7XG4gICAgICAgIGxldCBbbGVmdCwgcmlnaHRdID0gdGhpcy5fZ2V0TGVmdEFuZFJpZ2h0UGFydEFyb3VuZFRoZVNlbGVjdGlvbigpO1xuICAgICAgICBpZiAobGVmdCA9PT0gJycgJiYgcmlnaHQgPT09ICcnKSB7XG4gICAgICAgICAgICByZXR1cm4gWycnLCAnJ107XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiBjaGFuZ2luZyB0aGUgc2lnbiBhbmQgYGxlZnRgIGlzIGVxdWFsIHRvIHRoZSBudW1iZXIgemVybywgcHJldmVudCBzdHJpcHBpbmcgdGhlIGxlYWRpbmcgemVybyhzKVxuICAgICAgICBsZXQgc3RyaXBaZXJvcyA9IHRydWU7XG4gICAgICAgIGlmICgodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuSHlwaGVuIHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLk1pbnVzKSAmJiBOdW1iZXIobGVmdCkgPT09IDApIHtcbiAgICAgICAgICAgIHN0cmlwWmVyb3MgPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vVE9ETyBEUlkgdGhhdCB3aXRoIGBfbm9ybWFsaXplUGFydHMoKWAgLS0+XG4gICAgICAgIGlmICh0aGlzLmlzVHJhaWxpbmdOZWdhdGl2ZSAmJlxuICAgICAgICAgICAgKChBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKHJpZ2h0LCB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikgJiYgLy8gVGhlIGNhcmV0IGlzIHBsYWNlZCBvbiB0aGUgbGVmdCBvZiB0aGUgbmVnYXRpdmUgc2lnblxuICAgICAgICAgICAgIUF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUobGVmdCwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpKSB8fFxuICAgICAgICAgICAgKHJpZ2h0ID09PSAnJyAmJiAvLyAuLm9yIHRoZSBjYXJldCBpcyBwbGFjZWQgb24gdGhlIGZhciByaWdodCBvZiB0aGUgaW5wdXQgKEZpeCBpc3N1ZSAjNDgxKVxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZShsZWZ0LCB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciwgdHJ1ZSkpKSkge1xuICAgICAgICAgICAgbGVmdCA9IGxlZnQucmVwbGFjZSh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciwgJycpO1xuICAgICAgICAgICAgcmlnaHQgPSByaWdodC5yZXBsYWNlKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLCAnJyk7XG4gICAgICAgICAgICAvLyBUaGlzIGlzIGRvbmUgaGVyZSBiZWNhdXNlIGBfZ2V0VW5mb3JtYXR0ZWRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKClgIGlzIGNhbGxlZCBtdWx0aXBsZSB0aW1lcyBkdXJpbmcgdGhlIHNhbWUga2V5IGV2ZW50LCBhbmQgYXQgb25lIHBvaW50IHRoZSBsZWZ0L3JpZ2h0IHZhbHVlIGhhcyBiZWVuIG5vcm1hbGl6ZWQgYWxyZWFkeS4uXG4gICAgICAgICAgICBsZWZ0ID0gbGVmdC5yZXBsYWNlKCctJywgJycpO1xuICAgICAgICAgICAgcmlnaHQgPSByaWdodC5yZXBsYWNlKCctJywgJycpO1xuXG4gICAgICAgICAgICAvLyBUaGVuIGZpbmFsbHkgc2V0IGJhY2sgdGhlIG5vcm1hbGl6ZWQgbWludXMgY2hhcmFjdGVyIGF0IHRoZSByaWdodCBwbGFjZVxuICAgICAgICAgICAgbGVmdCA9IGAtJHtsZWZ0fWA7XG4gICAgICAgIH1cblxuICAgICAgICBsZWZ0ID0gQXV0b051bWVyaWMuX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVyc0V4Y2VwdEN1c3RvbURlY2ltYWxDaGFyKGxlZnQsIHRoaXMuc2V0dGluZ3MsIHN0cmlwWmVyb3MsIHRoaXMuaXNGb2N1c2VkKTtcbiAgICAgICAgcmlnaHQgPSBBdXRvTnVtZXJpYy5fc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzRXhjZXB0Q3VzdG9tRGVjaW1hbENoYXIocmlnaHQsIHRoaXMuc2V0dGluZ3MsIGZhbHNlLCB0aGlzLmlzRm9jdXNlZCk7XG5cbiAgICAgICAgcmV0dXJuIFtsZWZ0LCByaWdodF07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3RyaXAgcGFydHMgZnJvbSBleGNlc3MgY2hhcmFjdGVycyBhbmQgbGVhZGluZyB6ZXJvcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBsZWZ0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHJpZ2h0XG4gICAgICogQHJldHVybnMge1sqLCosKl19XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfbm9ybWFsaXplUGFydHMobGVmdCwgcmlnaHQpIHtcbiAgICAgICAgLy9UT0RPIFJlZmFjdG9yIHdpdGggYF9nZXRVbmZvcm1hdHRlZExlZnRBbmRSaWdodFBhcnRBcm91bmRUaGVTZWxlY3Rpb25gIHdoaWNoIHNoYXJlIGEgbG90IG9mIHNpbWlsYXIgY29kZVxuICAgICAgICAvLyBJZiBjaGFuZ2luZyB0aGUgc2lnbiBhbmQgbGVmdCBpcyBlcXVhbCB0byB0aGUgbnVtYmVyIHplcm8gLSBwcmV2ZW50cyBzdHJpcHBpbmcgdGhlIGxlYWRpbmcgemVyb3NcbiAgICAgICAgbGV0IHN0cmlwWmVyb3MgPSB0cnVlO1xuICAgICAgICBpZiAoKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkh5cGhlbiB8fCB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5NaW51cykgJiYgTnVtYmVyKGxlZnQpID09PSAwKSB7XG4gICAgICAgICAgICBzdHJpcFplcm9zID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5pc1RyYWlsaW5nTmVnYXRpdmUgJiZcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUocmlnaHQsIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSAmJlxuICAgICAgICAgICAgIUF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUobGVmdCwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICAvLyBPbmx5IHNldCB0aGUgbmVnYXRpdmUgc2lnbiBpZiB0aGUgdmFsdWUgaXMgbmVnYXRpdmVcbiAgICAgICAgICAgIGxlZnQgPSBgLSR7bGVmdH1gO1xuICAgICAgICAgICAgcmlnaHQgPSByaWdodC5yZXBsYWNlKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICBsZWZ0ID0gQXV0b051bWVyaWMuX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVyc0V4Y2VwdEN1c3RvbURlY2ltYWxDaGFyKGxlZnQsIHRoaXMuc2V0dGluZ3MsIHN0cmlwWmVyb3MsIHRoaXMuaXNGb2N1c2VkKTtcbiAgICAgICAgcmlnaHQgPSBBdXRvTnVtZXJpYy5fc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzRXhjZXB0Q3VzdG9tRGVjaW1hbENoYXIocmlnaHQsIHRoaXMuc2V0dGluZ3MsIGZhbHNlLCB0aGlzLmlzRm9jdXNlZCk7XG5cbiAgICAgICAgLy8gUHJldmVudHMgbXVsdGlwbGUgbGVhZGluZyB6ZXJvcyBmcm9tIGJlaW5nIGVudGVyZWRcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubGVhZGluZ1plcm8gPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8uZGVueSAmJlxuICAgICAgICAgICAgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLm51bTAgfHwgdGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUubnVtcGFkMCkgJiZcbiAgICAgICAgICAgIE51bWJlcihsZWZ0KSA9PT0gMCAmJlxuICAgICAgICAgICAgLy8gSWYgYHJpZ2h0YCBpcyBub3QgZW1wdHkgYW5kIHRoZSBmaXJzdCBjaGFyYWN0ZXIgaXMgbm90IGBkZWNpbWFsQ2hhcmFjdGVyYFxuICAgICAgICAgICAgIUF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKGxlZnQsIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlcikgJiYgcmlnaHQgIT09ICcnKSB7XG4gICAgICAgICAgICBsZWZ0ID0gbGVmdC5zdWJzdHJpbmcoMCwgbGVmdC5sZW5ndGggLSAxKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEluc2VydCB6ZXJvIHRoZXJlIGlzIGEgbGVhZGluZyBkb3RcbiAgICAgICAgbGV0IG5ld1ZhbHVlID0gbGVmdCArIHJpZ2h0O1xuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSB7XG4gICAgICAgICAgICBjb25zdCBtID0gbmV3VmFsdWUubWF0Y2gobmV3IFJlZ0V4cChgXiR7dGhpcy5yZWdleC5hTmVnUmVnQXV0b1N0cmlwfVxcXFwke3RoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcn1gKSk7XG4gICAgICAgICAgICBpZiAobSkge1xuICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnJlcGxhY2UobVsxXSwgbVsxXSArICcwJyk7XG4gICAgICAgICAgICAgICAgbmV3VmFsdWUgPSBsZWZ0ICsgcmlnaHQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW2xlZnQsIHJpZ2h0LCBuZXdWYWx1ZV07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBmb3JtYXR0ZWQgZWxlbWVudCB2YWx1ZSBhcyB3ZWxsIGFzIHRoZSBgcmF3VmFsdWVgLlxuICAgICAqIFRoaXMgcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIGVsZW1lbnQgYW5kIHJhdyB2YWx1ZSBoYXZlIGJlZW4gbW9kaWZpZWQsIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgICAqIFRoaXMgbWV0aG9kIGFsc28gYWRqdXN0IHRoZSBjYXJldCBwb3NpdGlvbiBhY2NvcmRpbmcgdG8gdGhlIGBsZWFkaW5nWmVyb2Agb3B0aW9uIGFuZCB0aGUgbm9ybWFsaXplZCB2YWx1ZS4gLy9UT0RPIFdoYXQgYWJvdXQgdGhlIGN1cnNvciAqc2VsZWN0aW9uKj9cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBsZWZ0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHJpZ2h0XG4gICAgICogQHBhcmFtIHtib29sZWFufSBpc1Bhc3RlXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2V0VmFsdWVQYXJ0cyhsZWZ0LCByaWdodCwgaXNQYXN0ZSA9IGZhbHNlKSB7XG4gICAgICAgIGNvbnN0IFtub3JtYWxpemVkTGVmdCwgbm9ybWFsaXplZFJpZ2h0LCBub3JtYWxpemVkTmV3VmFsdWVdID0gdGhpcy5fbm9ybWFsaXplUGFydHMobGVmdCwgcmlnaHQpO1xuICAgICAgICBjb25zdCBbbWluVGVzdCwgbWF4VGVzdF0gPSBBdXRvTnVtZXJpYy5fY2hlY2tJZkluUmFuZ2VXaXRoT3ZlcnJpZGVPcHRpb24obm9ybWFsaXplZE5ld1ZhbHVlLCB0aGlzLnNldHRpbmdzKTtcblxuICAgICAgICBpZiAobWluVGVzdCAmJiBtYXhUZXN0KSB7XG4gICAgICAgICAgICAvLyBGaXJzdCwgc2V0IHRoZSByYXcgdmFsdWVcbiAgICAgICAgICAgIGNvbnN0IHJvdW5kZWRSYXdWYWx1ZSA9IEF1dG9OdW1lcmljLl90cnVuY2F0ZURlY2ltYWxQbGFjZXMobm9ybWFsaXplZE5ld1ZhbHVlLCB0aGlzLnNldHRpbmdzLCBpc1Bhc3RlLCB0aGlzLnNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSk7XG4gICAgICAgICAgICBjb25zdCB0ZXN0VmFsdWUgPSByb3VuZGVkUmF3VmFsdWUucmVwbGFjZSh0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIsICcuJyk7XG5cbiAgICAgICAgICAgIGlmICh0ZXN0VmFsdWUgPT09ICcnIHx8IHRlc3RWYWx1ZSA9PT0gdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgICAgICBsZXQgdmFsdWVUb1NldE9uRW1wdHk7XG4gICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvcikge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLnplcm86XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVRvU2V0T25FbXB0eSA9ICcwJztcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLm51bGw6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVRvU2V0T25FbXB0eSA9IG51bGw7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVRvU2V0T25FbXB0eSA9ICcnO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHRoaXMuX3NldFJhd1ZhbHVlKHZhbHVlVG9TZXRPbkVtcHR5KTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0UmF3VmFsdWUodGhpcy5fdHJpbUxlYWRpbmdBbmRUcmFpbGluZ1plcm9zKHRlc3RWYWx1ZSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBUaGVuIHNldCB0aGUgZm9ybWF0dGVkIHZhbHVlXG4gICAgICAgICAgICBjb25zdCByb3VuZGVkVmFsdWVUb1Nob3cgPSBBdXRvTnVtZXJpYy5fdHJ1bmNhdGVEZWNpbWFsUGxhY2VzKG5vcm1hbGl6ZWROZXdWYWx1ZSwgdGhpcy5zZXR0aW5ncywgaXNQYXN0ZSwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzKTtcbiAgICAgICAgICAgIGxldCBwb3NpdGlvbiA9IG5vcm1hbGl6ZWRMZWZ0Lmxlbmd0aDtcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbiA+IHJvdW5kZWRWYWx1ZVRvU2hvdy5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHJvdW5kZWRWYWx1ZVRvU2hvdy5sZW5ndGg7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIE1ha2Ugc3VyZSB3aGVuIHRoZSB1c2VyIGVudGVyIGEgJzAnIG9uIHRoZSBmYXIgbGVmdCB3aXRoIGEgbGVhZGluZyB6ZXJvIG9wdGlvbiBzZXQgdG8gJ2RlbnknLCB0aGF0IHRoZSBjYXJldCBkb2VzIG5vdCBtb3ZlcyBzaW5jZSB0aGUgaW5wdXQgaXMgZHJvcHBlZCAoZml4IGlzc3VlICMyODMpXG4gICAgICAgICAgICBpZiAocG9zaXRpb24gPT09IDEgJiYgbm9ybWFsaXplZExlZnQgPT09ICcwJyAmJiB0aGlzLnNldHRpbmdzLmxlYWRpbmdaZXJvID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmRlbnkpIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGUgdXNlciBlbnRlciBgMGAsIHRoZW4gdGhlIGNhcmV0IGlzIHB1dCBvbiB0aGUgcmlnaHQgc2lkZSBvZiBpdCAoRml4IGlzc3VlICMyOTkpXG4gICAgICAgICAgICAgICAgaWYgKG5vcm1hbGl6ZWRSaWdodCA9PT0gJycgfHwgbm9ybWFsaXplZExlZnQgPT09ICcwJyAmJiBub3JtYWxpemVkUmlnaHQgIT09ICcnKSB7XG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gMTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IDA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50VmFsdWUocm91bmRlZFZhbHVlVG9TaG93LCBmYWxzZSk7XG4gICAgICAgICAgICB0aGlzLl9zZXRDYXJldFBvc2l0aW9uKHBvc2l0aW9uKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIW1pblRlc3QpIHtcbiAgICAgICAgICAgIHRoaXMuX3RyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubWluUmFuZ2VFeGNlZWRlZCwgdGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgfSBlbHNlIGlmICghbWF4VGVzdCkge1xuICAgICAgICAgICAgdGhpcy5fdHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5tYXhSYW5nZUV4Y2VlZGVkLCB0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhlbHBlciBmdW5jdGlvbiBmb3IgYF9leHBhbmRTZWxlY3Rpb25PblNpZ24oKWAuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IGNvbnRhaW5pbmcgW3NpZ25Qb3NpdGlvbiwgY3VycmVuY3lTeW1ib2xQb3NpdGlvbl0gb2YgYSBmb3JtYXR0ZWQgdmFsdWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9nZXRTaWduUG9zaXRpb24oKSB7XG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sKSB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW5jeVN5bWJvbExlbiA9IHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGhhc05lZyA9IHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyICYmIHZhbHVlICYmIHZhbHVlLmNoYXJBdCgwKSA9PT0gdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXI7XG4gICAgICAgICAgICAgICAgaWYgKGhhc05lZykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBbMSwgY3VycmVuY3lTeW1ib2xMZW4gKyAxXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBbMCwgY3VycmVuY3lTeW1ib2xMZW5dO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWVMZW4gPSB2YWx1ZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gW3ZhbHVlTGVuIC0gY3VycmVuY3lTeW1ib2xMZW4sIHZhbHVlTGVuXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IFsxMDAwLCAtMV07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4cGFuZHMgc2VsZWN0aW9uIHRvIGNvdmVyIHdob2xlIHNpZ25cbiAgICAgKiBQcmV2ZW50cyBwYXJ0aWFsIGRlbGV0aW9uL2NvcHlpbmcvb3ZlcndyaXRpbmcgb2YgYSBzaWduXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZXhwYW5kU2VsZWN0aW9uT25TaWduKCkge1xuICAgICAgICBjb25zdCBbc2lnblBvc2l0aW9uLCBjdXJyZW5jeVN5bWJvbFBvc2l0aW9uXSA9IHRoaXMuX2dldFNpZ25Qb3NpdGlvbigpO1xuICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSB0aGlzLnNlbGVjdGlvbjtcblxuICAgICAgICAvLyBJZiBzZWxlY3Rpb24gY2F0Y2hlcyBzb21ldGhpbmcgZXhjZXB0IHNpZ24gYW5kIGNhdGNoZXMgb25seSBzcGFjZSBmcm9tIHNpZ25cbiAgICAgICAgaWYgKHNlbGVjdGlvbi5zdGFydCA8IGN1cnJlbmN5U3ltYm9sUG9zaXRpb24gJiYgc2VsZWN0aW9uLmVuZCA+IHNpZ25Qb3NpdGlvbikge1xuICAgICAgICAgICAgLy8gVGhlbiBzZWxlY3Qgd2l0aG91dCBlbXB0eSBzcGFjZVxuICAgICAgICAgICAgaWYgKChzZWxlY3Rpb24uc3RhcnQgPCBzaWduUG9zaXRpb24gfHwgc2VsZWN0aW9uLmVuZCA+IGN1cnJlbmN5U3ltYm9sUG9zaXRpb24pICYmXG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCkuc3Vic3RyaW5nKE1hdGgubWF4KHNlbGVjdGlvbi5zdGFydCwgc2lnblBvc2l0aW9uKSwgTWF0aC5taW4oc2VsZWN0aW9uLmVuZCwgY3VycmVuY3lTeW1ib2xQb3NpdGlvbikpXG4gICAgICAgICAgICAgICAgICAgIC5tYXRjaCgvXlxccyokLykpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZWN0aW9uLnN0YXJ0IDwgc2lnblBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFNlbGVjdGlvbihzZWxlY3Rpb24uc3RhcnQsIHNpZ25Qb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0U2VsZWN0aW9uKGN1cnJlbmN5U3ltYm9sUG9zaXRpb24sIHNlbGVjdGlvbi5lbmQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gRWxzZSBzZWxlY3Qgd2l0aCB3aG9sZSBzaWduXG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0U2VsZWN0aW9uKE1hdGgubWluKHNlbGVjdGlvbi5zdGFydCwgc2lnblBvc2l0aW9uKSwgTWF0aC5tYXgoc2VsZWN0aW9uLmVuZCwgY3VycmVuY3lTeW1ib2xQb3NpdGlvbikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJ5IHRvIHN0cmlwIHBhc3RlZCB2YWx1ZSB0byBkaWdpdHNcbiAgICAgKi9cbiAgICBfY2hlY2tQYXN0ZSgpIHtcbiAgICAgICAgLy8gRG8gbm90IHByb2Nlc3MgYW55dGhpbmcgaWYgdGhlIHZhbHVlIGhhcyBhbHJlYWR5IGJlZW4gZm9ybWF0dGVkXG4gICAgICAgIGlmICh0aGlzLmZvcm1hdHRlZCkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZCh0aGlzLnZhbHVlUGFydHNCZWZvcmVQYXN0ZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IG9sZFBhcnRzID0gdGhpcy52YWx1ZVBhcnRzQmVmb3JlUGFzdGU7XG4gICAgICAgICAgICBjb25zdCBbbGVmdCwgcmlnaHRdID0gdGhpcy5fZ2V0TGVmdEFuZFJpZ2h0UGFydEFyb3VuZFRoZVNlbGVjdGlvbigpO1xuXG4gICAgICAgICAgICAvLyBUcnkgdG8gc3RyaXAgdGhlIHBhc3RlZCB2YWx1ZSBmaXJzdFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMudmFsdWVQYXJ0c0JlZm9yZVBhc3RlO1xuXG4gICAgICAgICAgICBjb25zdCBtb2RpZmllZExlZnRQYXJ0ID0gbGVmdC5zdWJzdHIoMCwgb2xkUGFydHNbMF0ubGVuZ3RoKSArIEF1dG9OdW1lcmljLl9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnNFeGNlcHRDdXN0b21EZWNpbWFsQ2hhcihsZWZ0LnN1YnN0cihvbGRQYXJ0c1swXS5sZW5ndGgpLCB0aGlzLnNldHRpbmdzLCB0cnVlLCB0aGlzLmlzRm9jdXNlZCk7XG4gICAgICAgICAgICBpZiAoIXRoaXMuX3NldFZhbHVlUGFydHMobW9kaWZpZWRMZWZ0UGFydCwgcmlnaHQsIHRydWUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0RWxlbWVudFZhbHVlKG9sZFBhcnRzLmpvaW4oJycpLCBmYWxzZSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0Q2FyZXRQb3NpdGlvbihvbGRQYXJ0c1swXS5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2l2ZW4ga2V5IHNob3VsZCBiZSBpZ25vcmVkIG9yIG5vdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBldmVudEtleU5hbWVcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2hvdWxkU2tpcEV2ZW50S2V5KGV2ZW50S2V5TmFtZSkge1xuICAgICAgICBjb25zdCBpc0ZuS2V5cyA9IEF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShldmVudEtleU5hbWUsIEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLl9hbGxGbktleXMpO1xuICAgICAgICBjb25zdCBpc09TS2V5cyA9IGV2ZW50S2V5TmFtZSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuT1NMZWZ0IHx8IGV2ZW50S2V5TmFtZSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuT1NSaWdodDtcbiAgICAgICAgY29uc3QgaXNDb250ZXh0TWVudSA9IGV2ZW50S2V5TmFtZSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQ29udGV4dE1lbnU7XG4gICAgICAgIGNvbnN0IGlzU29tZU5vblByaW50YWJsZUtleXMgPSBBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkoZXZlbnRLZXlOYW1lLCBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5fc29tZU5vblByaW50YWJsZUtleXMpO1xuICAgICAgICBjb25zdCBpc090aGVyTm9uUHJpbnRhYmxlS2V5cyA9IGV2ZW50S2V5TmFtZSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuTnVtTG9jayB8fFxuICAgICAgICAgICAgZXZlbnRLZXlOYW1lID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5TY3JvbGxMb2NrIHx8XG4gICAgICAgICAgICBldmVudEtleU5hbWUgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkluc2VydCB8fFxuICAgICAgICAgICAgZXZlbnRLZXlOYW1lID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5Db21tYW5kO1xuICAgICAgICBjb25zdCBpc1VucmVjb2duaXphYmxlS2V5cyA9IGV2ZW50S2V5TmFtZSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuVW5pZGVudGlmaWVkO1xuXG4gICAgICAgIHJldHVybiBpc0ZuS2V5cyB8fCBpc09TS2V5cyB8fCBpc0NvbnRleHRNZW51IHx8IGlzU29tZU5vblByaW50YWJsZUtleXMgfHwgaXNVbnJlY29nbml6YWJsZUtleXMgfHwgaXNPdGhlck5vblByaW50YWJsZUtleXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvY2VzcyBjb3B5aW5nLCBjdXR0aW5nIGFuZCBwYXN0aW5nLCBhcyB3ZWxsIGFzIHVuZG8vcmVkb2luZyBhbmQgY3Vyc29yIG1vdmluZy5cbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIGZ1cnRoZXIgcHJvY2Vzc2luZyBzaG91bGQgbm90IGJlIHBlcmZvcm1lZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7S2V5Ym9hcmRFdmVudH0gZVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3Byb2Nlc3NOb25QcmludGFibGVLZXlzQW5kU2hvcnRjdXRzKGUpIHtcbiAgICAgICAgLy8gQ2F0Y2ggdGhlIGN0cmwgdXAgb24gY3RybC12XG4gICAgICAgIGlmICgoKGUuY3RybEtleSB8fCBlLm1ldGFLZXkpICYmIGUudHlwZSA9PT0gJ2tleXVwJyAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQodGhpcy52YWx1ZVBhcnRzQmVmb3JlUGFzdGUpKSB8fCAoZS5zaGlmdEtleSAmJiB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5JbnNlcnQpKSB7XG4gICAgICAgICAgICAvL1RPRE8gTW92ZSB0aGlzIHRlc3QgaW5zaWRlIHRoZSBgb25LZXl1cGAgaGFuZGxlclxuICAgICAgICAgICAgdGhpcy5fY2hlY2tQYXN0ZSgpO1xuXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTa2lwIGFsbCBmdW5jdGlvbiBrZXlzIChGMS1GMTIpLCBXaW5kb3dzIGtleXMsIHRhYiBhbmQgb3RoZXIgc3BlY2lhbCBrZXlzXG4gICAgICAgIGlmICh0aGlzLmNvbnN0cnVjdG9yLl9zaG91bGRTa2lwRXZlbnRLZXkodGhpcy5ldmVudEtleSkpIHtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgYSBcIlNlbGVjdCBhbGxcIiBrZXlib2FyZCBzaG9ydGN1dCBpcyBkZXRlY3RlZCAoY3RybCArIGEpXG4gICAgICAgIGlmICgoZS5jdHJsS2V5IHx8IGUubWV0YUtleSkgJiYgdGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuYSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc2VsZWN0TnVtYmVyT25seSkge1xuICAgICAgICAgICAgICAgIC8vIGBwcmV2ZW50RGVmYXVsdCgpYCBpcyB1c2VkIGhlcmUgdG8gcHJldmVudCB0aGUgYnJvd3NlciB0byBmaXJzdCBzZWxlY3QgYWxsIHRoZSBpbnB1dCB0ZXh0IChpbmNsdWRpbmcgdGhlIGN1cnJlbmN5IHNpZ24pLCBvdGhlcndpc2Ugd2Ugd291bGQgc2VlIHRoYXQgd2hvbGUgc2VsZWN0aW9uIGZpcnN0IGluIGEgZmxhc2gsIHRoZW4gdGhlIHNlbGVjdGlvbiB3aXRoIG9ubHkgdGhlIG51bWJlciBwYXJ0IHdpdGhvdXQgdGhlIGN1cnJlbmN5IHNpZ24uXG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIC8vVE9ETyByZXBsYWNlIGBzZWxlY3ROdW1iZXJgIGJ5IGBzZWxlY3RgP1xuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0TnVtYmVyKCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgYSBcIkNvcHlcIiwgXCJQYXN0ZVwiIG9yIFwiQ3V0XCIga2V5Ym9hcmQgc2hvcnRjdXQgaXMgZGV0ZWN0ZWQgKHJlc3BlY3RpdmVseSAnY3RybCArIGMnLCAnY3RybCArIHYnIG9yICdjdHJsICsgeCcpXG4gICAgICAgIGlmICgoZS5jdHJsS2V5IHx8IGUubWV0YUtleSkgJiZcbiAgICAgICAgICAgICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5jIHx8XG4gICAgICAgICAgICAgdGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUudiB8fFxuICAgICAgICAgICAgIHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLngpKSB7XG4gICAgICAgICAgICBpZiAoZS50eXBlID09PSAna2V5ZG93bicpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9leHBhbmRTZWxlY3Rpb25PblNpZ24oKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVHJ5IHRvIHByZXZlbnQgd3JvbmcgcGFzdGVcbiAgICAgICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS52IHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkluc2VydCkge1xuICAgICAgICAgICAgICAgIGlmIChlLnR5cGUgPT09ICdrZXlkb3duJyB8fCBlLnR5cGUgPT09ICdrZXlwcmVzcycpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHRoaXMudmFsdWVQYXJ0c0JlZm9yZVBhc3RlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52YWx1ZVBhcnRzQmVmb3JlUGFzdGUgPSB0aGlzLl9nZXRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jaGVja1Bhc3RlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gZS50eXBlID09PSAna2V5ZG93bicgfHwgZS50eXBlID09PSAna2V5cHJlc3MnIHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLmM7XG4gICAgICAgIH1cblxuXG4gICAgICAgIC8vIFRoZSB1bmRvIHNob3J0Y3V0XG4gICAgICAgIGlmIChlLmN0cmxLZXkgfHwgZS5tZXRhS2V5KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuWiB8fCB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS56KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEp1bXAgb3ZlciB0aGUgdGhvdXNhbmQgc2VwYXJhdG9yXG4gICAgICAgIC8vVE9ETyBNb3ZlIHRoaXMgdGVzdCBpbnNpZGUgdGhlIGBvbktleWRvd25gIGhhbmRsZXJcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkxlZnRBcnJvdyB8fCB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5SaWdodEFycm93KSB7XG4gICAgICAgICAgICBpZiAoZS50eXBlID09PSAna2V5ZG93bicgJiYgIWUuc2hpZnRLZXkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5MZWZ0QXJyb3cgJiZcbiAgICAgICAgICAgICAgICAgICAgKHZhbHVlLmNoYXJBdCh0aGlzLnNlbGVjdGlvbi5zdGFydCAtIDIpID09PSB0aGlzLnNldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3IgfHxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUuY2hhckF0KHRoaXMuc2VsZWN0aW9uLnN0YXJ0IC0gMikgPT09IHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0Q2FyZXRQb3NpdGlvbih0aGlzLnNlbGVjdGlvbi5zdGFydCAtIDEpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuUmlnaHRBcnJvdyAmJlxuICAgICAgICAgICAgICAgICAgICAodmFsdWUuY2hhckF0KHRoaXMuc2VsZWN0aW9uLnN0YXJ0ICsgMSkgPT09IHRoaXMuc2V0dGluZ3MuZGlnaXRHcm91cFNlcGFyYXRvciB8fFxuICAgICAgICAgICAgICAgICAgICB2YWx1ZS5jaGFyQXQodGhpcy5zZWxlY3Rpb24uc3RhcnQgKyAxKSA9PT0gdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRDYXJldFBvc2l0aW9uKHRoaXMuc2VsZWN0aW9uLnN0YXJ0ICsgMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkodGhpcy5ldmVudEtleSwgQXV0b051bWVyaWNFbnVtLmtleU5hbWUuX2RpcmVjdGlvbktleXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFByb2Nlc3MgZGVsZXRpb24gb2YgY2hhcmFjdGVycyB3aGVuIHRoZSBtaW51cyBzaWduIGlzIHRvIHRoZSByaWdodCBvZiB0aGUgbnVtZXJpYyBjaGFyYWN0ZXJzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGxlZnQgVGhlIHBhcnQgb24gdGhlIGxlZnQgb2YgdGhlIGNhcmV0IG9yIHNlbGVjdGlvblxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSByaWdodCBUaGUgcGFydCBvbiB0aGUgcmlnaHQgb2YgdGhlIGNhcmV0IG9yIHNlbGVjdGlvblxuICAgICAqIEByZXR1cm5zIHtbc3RyaW5nLCBzdHJpbmddfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3Byb2Nlc3NDaGFyYWN0ZXJEZWxldGlvbklmVHJhaWxpbmdOZWdhdGl2ZVNpZ24oW2xlZnQsIHJpZ2h0XSkge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICBjb25zdCBpc1ZhbE5lZ2F0aXZlID0gQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZSh2YWx1ZSwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpO1xuXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCAmJiB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkJhY2tzcGFjZSkge1xuICAgICAgICAgICAgICAgIHRoaXMuY2FyZXRGaXggPSAodGhpcy5zZWxlY3Rpb24uc3RhcnQgPj0gdmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQpICYmIHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dCAhPT0gJycpO1xuICAgICAgICAgICAgICAgIGlmICh2YWx1ZS5jaGFyQXQodGhpcy5zZWxlY3Rpb24uc3RhcnQgLSAxKSA9PT0gJy0nKSB7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygxKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2VsZWN0aW9uLnN0YXJ0IDw9IHZhbHVlLmxlbmd0aCAtIHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQuc3Vic3RyaW5nKDAsIGxlZnQubGVuZ3RoIC0gMSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhcmV0Rml4ID0gKHRoaXMuc2VsZWN0aW9uLnN0YXJ0ID49IHZhbHVlLmluZGV4T2YodGhpcy5zZXR0aW5ncy5zdWZmaXhUZXh0KSAmJiB0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQgIT09ICcnKTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZWxlY3Rpb24uc3RhcnQgPj0gdmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sKSArIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQuc3Vic3RyaW5nKDEsIHJpZ2h0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKGxlZnQsIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSAmJiB2YWx1ZS5jaGFyQXQodGhpcy5zZWxlY3Rpb24uc3RhcnQpID09PSAnLScpIHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQ6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2FyZXRGaXggPSAodGhpcy5zZWxlY3Rpb24uc3RhcnQgPj0gdmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikgKyB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlci5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQmFja3NwYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZWxlY3Rpb24uc3RhcnQgPT09ICh2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSArIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLmxlbmd0aCkgJiYgaXNWYWxOZWdhdGl2ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobGVmdCAhPT0gJy0nICYmICgodGhpcy5zZWxlY3Rpb24uc3RhcnQgPD0gdmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikpIHx8ICFpc1ZhbE5lZ2F0aXZlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygwLCBsZWZ0Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxlZnRbMF0gPT09ICctJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2VsZWN0aW9uLnN0YXJ0ID09PSB2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSAmJiBpc1ZhbE5lZ2F0aXZlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodDpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jYXJldEZpeCA9ICh0aGlzLnNlbGVjdGlvbi5zdGFydCA+PSB2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSArIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5CYWNrc3BhY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGlvbi5zdGFydCA9PT0gKHZhbHVlLmluZGV4T2YodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpICsgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIubGVuZ3RoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobGVmdCAhPT0gJy0nICYmIHRoaXMuc2VsZWN0aW9uLnN0YXJ0IDw9ICh2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSAtIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygwLCBsZWZ0Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChsZWZ0ICE9PSAnJyAmJiAhaXNWYWxOZWdhdGl2ZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygwLCBsZWZ0Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYXJldEZpeCA9ICh0aGlzLnNlbGVjdGlvbi5zdGFydCA+PSB2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wpICYmIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgIT09ICcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGlvbi5zdGFydCA9PT0gdmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWZ0ID0gbGVmdC5zdWJzdHJpbmcoMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFtsZWZ0LCByaWdodF07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvY2VzcyB0aGUgZGVsZXRpb24gb2YgY2hhcmFjdGVycy5cbiAgICAgKi9cbiAgICBfcHJvY2Vzc0NoYXJhY3RlckRlbGV0aW9uKCkge1xuICAgICAgICBsZXQgbGVmdDtcbiAgICAgICAgbGV0IHJpZ2h0O1xuXG4gICAgICAgIGlmICghdGhpcy5zZWxlY3Rpb24ubGVuZ3RoKSB7XG4gICAgICAgICAgICBbbGVmdCwgcmlnaHRdID0gdGhpcy5fZ2V0VW5mb3JtYXR0ZWRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKCk7XG4gICAgICAgICAgICBpZiAobGVmdCA9PT0gJycgJiYgcmlnaHQgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50aHJvd0lucHV0ID0gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmlzVHJhaWxpbmdOZWdhdGl2ZSAmJiBBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpLCB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikpIHtcbiAgICAgICAgICAgICAgICBbbGVmdCwgcmlnaHRdID0gdGhpcy5fcHJvY2Vzc0NoYXJhY3RlckRlbGV0aW9uSWZUcmFpbGluZ05lZ2F0aXZlU2lnbihbbGVmdCwgcmlnaHRdKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkJhY2tzcGFjZSkge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0ID0gbGVmdC5zdWJzdHJpbmcoMCwgbGVmdC5sZW5ndGggLSAxKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByaWdodCA9IHJpZ2h0LnN1YnN0cmluZygxLCByaWdodC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2V4cGFuZFNlbGVjdGlvbk9uU2lnbigpO1xuICAgICAgICAgICAgW2xlZnQsIHJpZ2h0XSA9IHRoaXMuX2dldFVuZm9ybWF0dGVkTGVmdEFuZFJpZ2h0UGFydEFyb3VuZFRoZVNlbGVjdGlvbigpO1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fc2V0VmFsdWVQYXJ0cyhsZWZ0LCByaWdodCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiBhIGRlY2ltYWwgY2hhcmFjdGVyIGlzIGFsbG93ZWQgdG8gYmUgdHlwZWQuXG4gICAgICogSWYgdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBzaG93biBvbiBmb2N1cyBpcyB6ZXJvLCB0aGVuIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBpcyBub3QgYWxsb3dlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2lzRGVjaW1hbENoYXJhY3Rlckluc2VydGlvbkFsbG93ZWQoKSB7XG4gICAgICAgIHJldHVybiBTdHJpbmcodGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzKSAhPT0gU3RyaW5nKEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cy5ub25lKSAmJlxuICAgICAgICAgICAgU3RyaW5nKHRoaXMuc2V0dGluZ3MuZGVjaW1hbFBsYWNlcykgIT09IFN0cmluZyhBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXMubm9uZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUga2V5IGlzIGFsbG93ZWQuXG4gICAgICogVGhpcyBmdW5jdGlvbiBkZWNpZGVzIGlmIHRoZSBrZXkgcHJlc3NlZCBzaG91bGQgYmUgZHJvcHBlZCBvciBhY2NlcHRlZCwgYW5kIG1vZGlmeSB0aGUgdmFsdWUgJ29uLXRoZS1mbHknIGFjY29yZGluZ2x5LlxuICAgICAqIC8vVE9ETyBUaGlzIHNob3VsZCB1c2UgYW5vdGhlciBmdW5jdGlvbiBpbiBvcmRlciB0byBzZXBhcmF0ZSB0aGUgdGVzdCBhbmQgdGhlIG1vZGlmaWNhdGlvblxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgX3Byb2Nlc3NDaGFyYWN0ZXJJbnNlcnRpb24oKSB7XG4gICAgICAgIGxldCBbbGVmdCwgcmlnaHRdID0gdGhpcy5fZ2V0VW5mb3JtYXR0ZWRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKCk7XG4gICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ICE9PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5BbmRyb2lkRGVmYXVsdCkge1xuICAgICAgICAgICAgdGhpcy50aHJvd0lucHV0ID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFN0YXJ0IHJ1bGVzIHdoZW4gdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGtleSBpcyBwcmVzc2VkIGFsd2F5cyB1c2UgbnVtZXJpYyBwYWQgZG90IHRvIGluc2VydCBkZWNpbWFsIHNlcGFyYXRvclxuICAgICAgICAvLyBEbyBub3QgYWxsb3cgZGVjaW1hbCBjaGFyYWN0ZXIgaWYgbm8gZGVjaW1hbCBwYXJ0IGFsbG93ZWRcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciB8fFxuICAgICAgICAgICAgKHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlICYmIHRoaXMuZXZlbnRLZXkgPT09IHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlKSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9pc0RlY2ltYWxDaGFyYWN0ZXJJbnNlcnRpb25BbGxvd2VkKCkgfHwgIXRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcikge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gRG8gbm90IGFsbG93IGRlY2ltYWwgY2hhcmFjdGVyIGJlZm9yZSBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgY2hhcmFjdGVyXG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgJiYgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMocmlnaHQsIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEbyBub3QgYWxsb3cgYSBkZWNpbWFsIGNoYXJhY3RlciBpZiBhbm90aGVyIGRlY2ltYWwgY2hhcmFjdGVyIGlzIGFscmVhZHkgcHJlc2VudFxuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKGxlZnQsIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlcikpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHJpZ2h0LmluZGV4T2YodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSA+IDApIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHJpZ2h0LmluZGV4T2YodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQuc3Vic3RyKDEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZVBhcnRzKGxlZnQgKyB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIsIHJpZ2h0KTtcblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcmV2ZW50IGVudGVyaW5nIHRoZSBtaW51cyBzaWduIGlmIGl0J3Mgbm90IGFsbG93ZWQgKE5vdGU6IGB0aGlzLnNldHRpbmdzLmlzTmVnYXRpdmVTaWduQWxsb3dlZGAgaXMgb25seSBzZXQgdG8gYHRydWVgIGlmIHRoZSBtaW5pbXVtVmFsdWUgaXMgbG93ZXIgdGhhbiB6ZXJvLCBhbGxvd2luZyBuZWdhdGl2ZSBudW1iZXJzIHRvIGJlIGVudGVyZWQpXG4gICAgICAgIGlmICgodGhpcy5ldmVudEtleSA9PT0gJy0nIHx8IHRoaXMuZXZlbnRLZXkgPT09ICcrJykgJiYgdGhpcy5zZXR0aW5ncy5pc05lZ2F0aXZlU2lnbkFsbG93ZWQpIHtcbiAgICAgICAgICAgIC8vIEhlcmUsIHRoZSBsZWZ0IGFuZCByaWdodCBwYXJ0cyBoYXZlIGJlZW4gbm9ybWFsaXplZCBhbHJlYWR5LCBoZW5jZSB0aGUgbWludXMgc2lnbiB1c2FnZVxuICAgICAgICAgICAgaWYgKGxlZnQgPT09ICcnICYmIEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKHJpZ2h0LCAnLScpKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIHZhbHVlIGlzIG9yaWdpbmFsbHkgbmVnYXRpdmUgKHdpdGggYSB0cmFpbGluZyBuZWdhdGl2ZSBzaWduKVxuICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQucmVwbGFjZSgnLScsICcnKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZShsZWZ0LCAnLScpKSB7XG4gICAgICAgICAgICAgICAgLy8gVGhlIHZhbHVlIGlzIG9yaWdpbmFsbHkgbmVnYXRpdmUgKHdpdGggYSBsZWFkaW5nIG5lZ2F0aXZlIHNpZ24pXG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlIHRoZSBuZWdhdGl2ZSBzaWduLCBlZmZlY3RpdmVseSBjb252ZXJ0aW5nIHRoZSB2YWx1ZSB0byBhIHBvc2l0aXZlIG9uZVxuICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnJlcGxhY2UoJy0nLCAnJyk7IC8vVE9ETyByZXBsYWNlIHdpdGggJysnIGlmIGBzaG93UG9zaXRpdmVTaWduYCB0b28/XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFRoZSB2YWx1ZSBpcyBvcmlnaW5hbGx5IHBvc2l0aXZlLCBzbyB3ZSB0b2dnbGUgdGhlIHN0YXRlIHRvIGEgbmVnYXRpdmUgb25lICh1bmZvcm1hdHRlZCwgd2hpY2ggbWVhbnMgZXZlbiB3aXRoIGEgdHJhaWxpbmcgbmVnYXRpdmUgc2lnbiwgd2UgYWRkIHRoZSBtaW51cyBzaWduIG9uIHRoZSBmYXIgbGVmdClcbiAgICAgICAgICAgICAgICBsZWZ0ID0gYCR7dGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXJ9JHtsZWZ0fWA7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlUGFydHMobGVmdCwgcmlnaHQpO1xuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGV2ZW50TnVtYmVyID0gTnVtYmVyKHRoaXMuZXZlbnRLZXkpO1xuICAgICAgICBpZiAoZXZlbnROdW1iZXIgPj0gMCAmJiBldmVudE51bWJlciA8PSA5KSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgdXNlciB0cmllcyB0byBpbnNlcnQgYSBkaWdpdFxuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuaXNOZWdhdGl2ZVNpZ25BbGxvd2VkICYmIGxlZnQgPT09ICcnICYmIEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKHJpZ2h0LCAnLScpKSB7XG4gICAgICAgICAgICAgICAgLy8gLi4uYW5kIHRoYXQgZGlnaXQgaXMgYmVmb3JlIHRoZSBtaW51cyBzaWduXG4gICAgICAgICAgICAgICAgbGVmdCA9ICctJztcbiAgICAgICAgICAgICAgICByaWdodCA9IHJpZ2h0LnN1YnN0cmluZygxLCByaWdodC5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWUgPD0gMCAmJlxuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlIDwgdGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWUgJiZcbiAgICAgICAgICAgICAgICAhQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMoQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCksIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSAmJlxuICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRLZXkgIT09ICcwJykge1xuICAgICAgICAgICAgICAgIGxlZnQgPSBgLSR7bGVmdH1gO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9zZXRWYWx1ZVBhcnRzKGAke2xlZnR9JHt0aGlzLmV2ZW50S2V5fWAsIHJpZ2h0KTtcblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcmV2ZW50IGFueSBvdGhlciBjaGFyYWN0ZXJzXG4gICAgICAgIHRoaXMudGhyb3dJbnB1dCA9IGZhbHNlO1xuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JtYXR0aW5nIG9mIGp1c3QgcHJvY2Vzc2VkIHZhbHVlIHdoaWxlIGtlZXBpbmcgdGhlIGN1cnNvciBwb3NpdGlvblxuICAgICAqXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2Zvcm1hdFZhbHVlKGUpIHtcbiAgICAgICAgLy9UT0RPIEJyZWFrIGFwYXJ0IGFuZCBzaW1wbGlmeSB0aGlzIHJlYWxseSBsb25nIGZ1bmN0aW9uXG4gICAgICAgIGNvbnN0IGVsZW1lbnRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICBsZXQgW2xlZnRdID0gdGhpcy5fZ2V0VW5mb3JtYXR0ZWRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKCk7XG5cbiAgICAgICAgLy8gTm8gZ3JvdXBpbmcgc2VwYXJhdG9yIGFuZCBubyBjdXJyZW5jeSBzaWduXG4gICAgICAgIGlmICgodGhpcy5zZXR0aW5ncy5kaWdpdEdyb3VwU2VwYXJhdG9yICA9PT0gJycgfHwgKHRoaXMuc2V0dGluZ3MuZGlnaXRHcm91cFNlcGFyYXRvciAhPT0gJycgICYmICFBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhlbGVtZW50VmFsdWUsIHRoaXMuc2V0dGluZ3MuZGlnaXRHcm91cFNlcGFyYXRvcikpKSAmJlxuICAgICAgICAgICAgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgPT09ICcnIHx8ICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sICE9PSAnJyAmJiAhQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMoZWxlbWVudFZhbHVlLCB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sKSkpKSB7XG4gICAgICAgICAgICBsZXQgW3N1YlBhcnRzXSA9IGVsZW1lbnRWYWx1ZS5zcGxpdCh0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpO1xuICAgICAgICAgICAgbGV0IG5lZ2F0aXZlU2lnbiA9ICcnO1xuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUoc3ViUGFydHMsIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgIG5lZ2F0aXZlU2lnbiA9IHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyO1xuICAgICAgICAgICAgICAgIHN1YlBhcnRzID0gc3ViUGFydHMucmVwbGFjZSh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciwgJycpO1xuICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnJlcGxhY2UoJy0nLCAnJyk7IC8vIEhlcmUgd2UgbW9kaWZ5IHRoZSB1bmZvcm1hdHRlZCB2YWx1ZSAod2l0aCB0aGUgJ25vcm1hbCcgbWludXMgc2lnbilcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU3RyaXAgbGVhZGluZyB6ZXJvIG9uIHBvc2l0aXZlIHZhbHVlIGlmIG5lZWRlZFxuICAgICAgICAgICAgaWYgKG5lZ2F0aXZlU2lnbiA9PT0gJycgJiYgc3ViUGFydHMubGVuZ3RoID4gdGhpcy5zZXR0aW5ncy5tSW50UG9zICYmIGxlZnQuY2hhckF0KDApID09PSAnMCcpIHtcbiAgICAgICAgICAgICAgICBsZWZ0ID0gbGVmdC5zbGljZSgxKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU3RyaXAgbGVhZGluZyB6ZXJvIG9uIG5lZ2F0aXZlIHZhbHVlIGlmIG5lZWRlZFxuICAgICAgICAgICAgaWYgKG5lZ2F0aXZlU2lnbiA9PT0gdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgJiYgc3ViUGFydHMubGVuZ3RoID4gdGhpcy5zZXR0aW5ncy5tSW50TmVnICYmIGxlZnQuY2hhckF0KDApID09PSAnMCcpIHtcbiAgICAgICAgICAgICAgICBsZWZ0ID0gbGVmdC5zbGljZSgxKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCF0aGlzLmlzVHJhaWxpbmdOZWdhdGl2ZSkgeyAvLyBPbmx5IGFkZCB0aGUgbWludXMgc2lnbiBpZiBpdCdzIG5lZWRlZCBvbiB0aGF0IHNpZGUgb2YgdGhlIG51bWJlcnNcbiAgICAgICAgICAgICAgICBsZWZ0ID0gYCR7bmVnYXRpdmVTaWdufSR7bGVmdH1gO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgdmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9hZGRHcm91cFNlcGFyYXRvcnMoZWxlbWVudFZhbHVlLCB0aGlzLnNldHRpbmdzLCB0aGlzLmlzRm9jdXNlZCwgdGhpcy5yYXdWYWx1ZSk7XG4gICAgICAgIGxldCBwb3NpdGlvbiA9IHZhbHVlLmxlbmd0aDtcbiAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgICAvLyBQcmVwYXJlIHJlZ2V4cCB3aGljaCBzZWFyY2hlcyBmb3IgY3Vyc29yIHBvc2l0aW9uIGZyb20gdW5mb3JtYXR0ZWQgbGVmdCBwYXJ0XG4gICAgICAgICAgICBjb25zdCBsZWZ0QXIgPSBsZWZ0LnNwbGl0KCcnKTtcblxuICAgICAgICAgICAgLy8gRml4ZXMgY2FyZXQgcG9zaXRpb24gd2l0aCB0cmFpbGluZyBtaW51cyBzaWduXG4gICAgICAgICAgICBpZiAoKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4IHx8XG4gICAgICAgICAgICAgICAgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4ICYmIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4KSkgJiZcbiAgICAgICAgICAgICAgICBsZWZ0QXJbMF0gPT09IHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyICYmICF0aGlzLnNldHRpbmdzLmlzTmVnYXRpdmVTaWduQWxsb3dlZCkge1xuICAgICAgICAgICAgICAgIGxlZnRBci5zaGlmdCgpOyAvLyBSZW1vdmUgdGhlIG5lZ2F0aXZlIHNpZ24gY2hhcmFjdGVyXG5cbiAgICAgICAgICAgICAgICBpZiAoKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkJhY2tzcGFjZSB8fCB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5EZWxldGUpICYmXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2FyZXRGaXgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCAmJiB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXggJiYgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0QXIucHVzaCh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlcik7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhcmV0Rml4ID0gZS50eXBlID09PSAna2V5ZG93bic7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXggJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNpZ25QYXJ0cyA9IHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wuc3BsaXQoJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXNjYXBlQ2hyID0gWydcXFxcJywgJ14nLCAnJCcsICcuJywgJ3wnLCAnPycsICcqJywgJysnLCAnKCcsICcpJywgJ1snXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVzY2FwZWRQYXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2lnblBhcnRzLmZvckVhY2goKGksIG1pbmlQYXJ0cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbmlQYXJ0cyA9IHNpZ25QYXJ0c1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG1pbmlQYXJ0cywgZXNjYXBlQ2hyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlc2NhcGVkUGFydHMucHVzaCgnXFxcXCcgKyBtaW5pUGFydHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVzY2FwZWRQYXJ0cy5wdXNoKG1pbmlQYXJ0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5CYWNrc3BhY2UgJiYgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgPT09ICctJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVzY2FwZWRQYXJ0cy5wdXNoKCctJyk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFB1c2hpbmcgdGhlIGVzY2FwZWQgc2lnblxuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdEFyLnB1c2goZXNjYXBlZFBhcnRzLmpvaW4oJycpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuY2FyZXRGaXggPSBlLnR5cGUgPT09ICdrZXlkb3duJztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBsZWZ0QXIubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgICAgICBpZiAoIWxlZnRBcltpXS5tYXRjaCgnXFxcXGQnKSkge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0QXJbaV0gPSAnXFxcXCcgKyBsZWZ0QXJbaV07XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBsZWZ0UmVnID0gbmV3IFJlZ0V4cCgnXi4qPycgKyBsZWZ0QXIuam9pbignLio/JykpO1xuXG4gICAgICAgICAgICAvLyBTZWFyY2ggY3Vyc29yIHBvc2l0aW9uIGluIGZvcm1hdHRlZCB2YWx1ZVxuICAgICAgICAgICAgY29uc3QgbmV3TGVmdCA9IHZhbHVlLm1hdGNoKGxlZnRSZWcpO1xuICAgICAgICAgICAgaWYgKG5ld0xlZnQpIHtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IG5ld0xlZnRbMF0ubGVuZ3RoO1xuXG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIHBvc2l0aXZlIHNpZ24gaXMgc2hvd24sIGNhbGN1bGF0ZSB0aGUgY2FyZXQgcG9zaXRpb24gYWNjb3JkaW5nbHlcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5zaG93UG9zaXRpdmVTaWduKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChwb3NpdGlvbiA9PT0gMCAmJiBuZXdMZWZ0LmlucHV0LmNoYXJBdCgwKSA9PT0gdGhpcy5zZXR0aW5ncy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gKG5ld0xlZnQuaW5wdXQuaW5kZXhPZih0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sKSA9PT0gMSkgPyB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLmxlbmd0aCArIDEgOiAxO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHBvc2l0aW9uID09PSAwICYmIG5ld0xlZnQuaW5wdXQuY2hhckF0KHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoKSA9PT0gdGhpcy5zZXR0aW5ncy5wb3NpdGl2ZVNpZ25DaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGggKyAxO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gSWYgd2UgYXJlIGp1c3QgYmVmb3JlIHRoZSBzaWduIHdoaWNoIGlzIGluIHByZWZpeCBwb3NpdGlvblxuICAgICAgICAgICAgICAgIGlmICgoKHBvc2l0aW9uID09PSAwICYmIHZhbHVlLmNoYXJBdCgwKSAhPT0gdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpIHx8IChwb3NpdGlvbiA9PT0gMSAmJiB2YWx1ZS5jaGFyQXQoMCkgPT09IHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkgJiYgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCAmJiB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBQbGFjZSBjYXJldCBhZnRlciBwcmVmaXggc2lnblxuICAgICAgICAgICAgICAgICAgICAvL1RPRE8gU2hvdWxkIHRoZSB0ZXN0IGJlICdpc05lZ2F0aXZlJyBpbnN0ZWFkIG9mICdpc05lZ2F0aXZlU3RyaWN0JyBpbiBvcmRlciB0byBzZWFyY2ggZm9yICctJyBldmVyeXdoZXJlIGluIHRoZSBzdHJpbmc/XG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGggKyAoQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZVN0cmljdCh2YWx1ZSwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpID8gMSA6IDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgJiYgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgd2UgY291bGQgbm90IGZpbmQgYSBwbGFjZSBmb3IgY3Vyc29yIGFuZCBoYXZlIGEgc2lnbiBhcyBhIHN1ZmZpeFxuICAgICAgICAgICAgICAgICAgICAvLyBQbGFjZSBjYXJldCBiZWZvcmUgc3VmZml4IGN1cnJlbmN5IHNpZ25cbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gLT0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB3ZSBjb3VsZCBub3QgZmluZCBhIHBsYWNlIGZvciBjdXJzb3IgYW5kIGhhdmUgYSBzdWZmaXhcbiAgICAgICAgICAgICAgICAgICAgLy8gUGxhY2UgY2FyZXQgYmVmb3JlIHN1ZmZpeFxuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiAtPSB0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQubGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE9ubHkgdXBkYXRlIHRoZSB2YWx1ZSBpZiBpdCBoYXMgY2hhbmdlZC4gVGhpcyBwcmV2ZW50cyBtb2RpZnlpbmcgdGhlIHNlbGVjdGlvbiwgaWYgYW55LlxuICAgICAgICBpZiAodmFsdWUgIT09IGVsZW1lbnRWYWx1ZSkge1xuICAgICAgICAgICAgdGhpcy5fc2V0RWxlbWVudFZhbHVlKHZhbHVlLCBmYWxzZSk7XG4gICAgICAgICAgICB0aGlzLl9zZXRDYXJldFBvc2l0aW9uKHBvc2l0aW9uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZm9ybWF0dGVkID0gdHJ1ZTsgLy9UT0RPIFJlbmFtZSBgdGhpcy5mb3JtYXR0ZWRgIHRvIGB0aGlzLl9mb3JtYXRFeGVjdXRlZGAsIHNpbmNlIGl0J3MgcG9zc2libGUgdGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBuZWVkIHRvIGZvcm1hdCBhbnl0aGluZyAoaW4gdGhlIGNhc2Ugd2hlcmUgdGhlIGtleWNvZGUgaXMgZHJvcHBlZCBmb3IgaW5zdGFuY2UpXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VyaWFsaXplIHRoZSBmb3JtIGNoaWxkIDxpbnB1dD4gZWxlbWVudCB2YWx1ZXMgdG8gYSBzdHJpbmcsIG9yIGFuIEFycmF5LlxuICAgICAqIFRoZSBvdXRwdXQgZm9ybWF0IGlzIGRlZmluZWQgd2l0aCB0aGUgYGZvcm1hdFR5cGVgIGFyZ3VtZW50LlxuICAgICAqIFRoaXMgaXMgbG9vc2VseSBiYXNlZCB1cG9uIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzQwNzA1OTkzLzI4MzQ4OTguXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxGb3JtRWxlbWVudH0gZm9ybVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaW50b0FuQXJyYXkgSWYgYHRydWVgLCBpbnN0ZWFkIG9mIGdlbmVyYXRpbmcgYSBzdHJpbmcsIGl0IGdlbmVyYXRlcyBhbiBBcnJheS5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZm9ybWF0VHlwZSBJZiBgJ3VuZm9ybWF0dGVkJ2AsIHRoZW4gdGhlIEF1dG9OdW1lcmljIGVsZW1lbnRzIHZhbHVlcyBhcmUgdW5mb3JtYXR0ZWQsIGlmIGAnbG9jYWxpemVkJ2AsIHRoZW4gdGhlIEF1dG9OdW1lcmljIGVsZW1lbnRzIHZhbHVlcyBhcmUgbG9jYWxpemVkLCBhbmQgaWYgYCdmb3JtYXR0ZWQnYCwgdGhlbiB0aGUgQXV0b051bWVyaWMgZWxlbWVudHMgdmFsdWVzIGFyZSBrZXB0IGZvcm1hdHRlZC4gSW4gZWl0aGVyIHdheSwgdGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBtb2RpZnkgdGhlIHZhbHVlIG9mIGVhY2ggRE9NIGVsZW1lbnQsIGJ1dCBvbmx5IGFmZmVjdCB0aGUgdmFsdWUgdGhhdCBpcyByZXR1cm5lZCBieSB0aGF0IHNlcmlhbGl6ZSBmdW5jdGlvbi5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyIENhbiBlaXRoZXIgYmUgdGhlICcrJyBjaGFyYWN0ZXIsIG9yIHRoZSAnJTIwJyBzdHJpbmcuXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVsbH0gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCwgdGhlbiB0aGlzIGlzIHRoZSBmb3JtYXQgdGhhdCBpcyB1c2VkIGZvciB0aGUgbG9jYWxpemF0aW9uLCBpbnN0ZWFkIG9mIHRoZSBkZWZhdWx0IGBvdXRwdXRGb3JtYXRgIG9wdGlvbi5cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfEFycmF5fVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9zZXJpYWxpemUoZm9ybSwgaW50b0FuQXJyYXkgPSBmYWxzZSwgZm9ybWF0VHlwZSA9ICd1bmZvcm1hdHRlZCcsIHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlciA9ICcrJywgZm9yY2VkT3V0cHV0Rm9ybWF0ID0gbnVsbCkge1xuICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcblxuICAgICAgICBpZiAodHlwZW9mIGZvcm0gPT09ICdvYmplY3QnICYmIGZvcm0ubm9kZU5hbWUudG9Mb3dlckNhc2UoKSA9PT0gJ2Zvcm0nKSB7XG4gICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChmb3JtLmVsZW1lbnRzKS5mb3JFYWNoKGVsZW1lbnQgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlbGVtZW50Lm5hbWUgJiZcbiAgICAgICAgICAgICAgICAgICAgIWVsZW1lbnQuZGlzYWJsZWQgJiZcbiAgICAgICAgICAgICAgICAgICAgWydmaWxlJywgJ3Jlc2V0JywgJ3N1Ym1pdCcsICdidXR0b24nXS5pbmRleE9mKGVsZW1lbnQudHlwZSkgPT09IC0xKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChlbGVtZW50LnR5cGUgPT09ICdzZWxlY3QtbXVsdGlwbGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBBcnJheS5wcm90b3R5cGUuc2xpY2UuY2FsbChlbGVtZW50Lm9wdGlvbnMpLmZvckVhY2gob3B0aW9uID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAob3B0aW9uLnNlbGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vVE9ETyBTaG91bGQgd2UgdW5mb3JtYXQvZm9ybWF0L2xvY2FsaXplIHRoZSBzZWxlY3Rpb24gb3B0aW9uICh3aGljaCBiZSBkZWZhdWx0IHNob3VsZCBiZSByZWFkLW9ubHkpP1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW50b0FuQXJyYXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKHsgbmFtZTogZWxlbWVudC5uYW1lLCB2YWx1ZTogb3B0aW9uLnZhbHVlIH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgeyAvLyBpbnRvIGEgc3RyaW5nXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChgJHtlbmNvZGVVUklDb21wb25lbnQoZWxlbWVudC5uYW1lKX09JHtlbmNvZGVVUklDb21wb25lbnQob3B0aW9uLnZhbHVlKX1gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKFsnY2hlY2tib3gnLCAncmFkaW8nXS5pbmRleE9mKGVsZW1lbnQudHlwZSkgPT09IC0xIHx8IGVsZW1lbnQuY2hlY2tlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHZhbHVlUmVzdWx0O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNNYW5hZ2VkQnlBdXRvTnVtZXJpYyhlbGVtZW50KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxldCBhbk9iamVjdDtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKGZvcm1hdFR5cGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAndW5mb3JtYXR0ZWQnOlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYW5PYmplY3QgPSB0aGlzLmdldEF1dG9OdW1lcmljRWxlbWVudChlbGVtZW50KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGFuT2JqZWN0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlUmVzdWx0ID0gdGhpcy51bmZvcm1hdChlbGVtZW50LCBhbk9iamVjdC5nZXRTZXR0aW5ncygpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ2xvY2FsaXplZCc6XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhbk9iamVjdCA9IHRoaXMuZ2V0QXV0b051bWVyaWNFbGVtZW50KGVsZW1lbnQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoYW5PYmplY3QpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSGVyZSBJIG5lZWQgdG8gY2xvbmUgdGhlIHNldHRpbmcgb2JqZWN0LCBvdGhlcndpc2UgSSB3b3VsZCBtb2RpZnkgaXQgd2hlbiBjaGFuZ2luZyB0aGUgYG91dHB1dEZvcm1hdGAgb3B0aW9uIHZhbHVlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY3VycmVudFNldHRpbmdzID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QoYW5PYmplY3QuZ2V0U2V0dGluZ3MoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoZm9yY2VkT3V0cHV0Rm9ybWF0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjdXJyZW50U2V0dGluZ3Mub3V0cHV0Rm9ybWF0ID0gZm9yY2VkT3V0cHV0Rm9ybWF0O1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlUmVzdWx0ID0gdGhpcy5sb2NhbGl6ZShlbGVtZW50LCBjdXJyZW50U2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnZm9ybWF0dGVkJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlUmVzdWx0ID0gZWxlbWVudC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlUmVzdWx0ID0gZWxlbWVudC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHZhbHVlUmVzdWx0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoJ1RoaXMgZXJyb3Igc2hvdWxkIG5ldmVyIGJlIGhpdC4gSWYgaXQgaGFzLCBzb21ldGhpbmcgcmVhbGx5IHdyb25nIGhhcHBlbmVkIScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW50b0FuQXJyYXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaCh7IG5hbWU6IGVsZW1lbnQubmFtZSwgdmFsdWU6IHZhbHVlUmVzdWx0IH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsgLy8gaW50byBhIHN0cmluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGAke2VuY29kZVVSSUNvbXBvbmVudChlbGVtZW50Lm5hbWUpfT0ke2VuY29kZVVSSUNvbXBvbmVudCh2YWx1ZVJlc3VsdCl9YCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBmaW5hbFJlc3VsdDtcblxuICAgICAgICBpZiAoaW50b0FuQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIFJlc3VsdCBhcyBhbiBBcnJheVxuICAgICAgICAgICAgLy8gTm90ZTogYHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlcmAgZG9lcyBub3QgYWZmZWN0IHRoZSBhcnJheSByZXN1bHQgc2luY2Ugd2UgZG8gbm90IGNoYW5nZSB0aGUgc3BhY2UgY2hhcmFjdGVyIGZvciB0aGlzIG9uZVxuICAgICAgICAgICAgZmluYWxSZXN1bHQgPSByZXN1bHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBSZXN1bHQgYXMgYSBzdHJpbmdcbiAgICAgICAgICAgIGZpbmFsUmVzdWx0ID0gcmVzdWx0LmpvaW4oJyYnKTtcblxuICAgICAgICAgICAgaWYgKCcrJyA9PT0gc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyKSB7XG4gICAgICAgICAgICAgICAgZmluYWxSZXN1bHQgPSBmaW5hbFJlc3VsdC5yZXBsYWNlKC8lMjAvZywgJysnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmaW5hbFJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXJpYWxpemUgdGhlIGZvcm0gdmFsdWVzIHRvIGEgc3RyaW5nLCBvdXRwdXR0aW5nIG51bWVyaWMgc3RyaW5ncyBmb3IgZWFjaCBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnQgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRm9ybUVsZW1lbnR9IGZvcm1cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgX3NlcmlhbGl6ZU51bWVyaWNTdHJpbmcoZm9ybSwgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyID0gJysnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zZXJpYWxpemUoZm9ybSwgZmFsc2UsICd1bmZvcm1hdHRlZCcsIHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3Rlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VyaWFsaXplIHRoZSBmb3JtIHZhbHVlcyB0byBhIHN0cmluZywgb3V0cHV0dGluZyB0aGUgZm9ybWF0dGVkIHZhbHVlIGFzIHN0cmluZ3MgZm9yIGVhY2ggQXV0b051bWVyaWMtbWFuYWdlZCBlbGVtZW50cy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fSBmb3JtXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgc3RhdGljIF9zZXJpYWxpemVGb3JtYXR0ZWQoZm9ybSwgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyID0gJysnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zZXJpYWxpemUoZm9ybSwgZmFsc2UsICdmb3JtYXR0ZWQnLCBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlcmlhbGl6ZSB0aGUgZm9ybSB2YWx1ZXMgdG8gYSBzdHJpbmcsIG91dHB1dHRpbmcgbG9jYWxpemVkIHN0cmluZ3MgZm9yIGVhY2ggQXV0b051bWVyaWMtbWFuYWdlZCBlbGVtZW50IHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fSBmb3JtXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IGZvcmNlZE91dHB1dEZvcm1hdCBJZiBzZXQsIHRoZW4gdGhpcyBpcyB0aGUgZm9ybWF0IHRoYXQgaXMgdXNlZCBmb3IgdGhlIGxvY2FsaXphdGlvbiwgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBgb3V0cHV0Rm9ybWF0YCBvcHRpb24uXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgX3NlcmlhbGl6ZUxvY2FsaXplZChmb3JtLCBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIgPSAnKycsIGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlcmlhbGl6ZShmb3JtLCBmYWxzZSwgJ2xvY2FsaXplZCcsIHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlciwgZm9yY2VkT3V0cHV0Rm9ybWF0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhbiBBcnJheSB3aXRoIHRoZSBmb3JtIHZhbHVlcywgb3V0cHV0dGluZyBudW1lcmljIHN0cmluZ3MgZm9yIGVhY2ggQXV0b051bWVyaWMtbWFuYWdlZCBlbGVtZW50IHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fSBmb3JtXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlclxuICAgICAqIEByZXR1cm5zIHtBcnJheX1cbiAgICAgKi9cbiAgICBzdGF0aWMgX3NlcmlhbGl6ZU51bWVyaWNTdHJpbmdBcnJheShmb3JtLCBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIgPSAnKycpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlcmlhbGl6ZShmb3JtLCB0cnVlLCAndW5mb3JtYXR0ZWQnLCBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGFuIEFycmF5IHdpdGggdGhlIGZvcm0gdmFsdWVzLCBvdXRwdXR0aW5nIHRoZSBmb3JtYXR0ZWQgdmFsdWUgYXMgc3RyaW5ncyBmb3IgZWFjaCBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRm9ybUVsZW1lbnR9IGZvcm1cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyXG4gICAgICogQHJldHVybnMge0FycmF5fVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2VyaWFsaXplRm9ybWF0dGVkQXJyYXkoZm9ybSwgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyID0gJysnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zZXJpYWxpemUoZm9ybSwgdHJ1ZSwgJ2Zvcm1hdHRlZCcsIHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3Rlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYW4gQXJyYXkgd2l0aCB0aGUgZm9ybSB2YWx1ZXMsIG91dHB1dHRpbmcgbG9jYWxpemVkIHN0cmluZ3MgZm9yIGVhY2ggQXV0b051bWVyaWMtbWFuYWdlZCBlbGVtZW50IHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fSBmb3JtXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IGZvcmNlZE91dHB1dEZvcm1hdCBJZiBzZXQsIHRoZW4gdGhpcyBpcyB0aGUgZm9ybWF0IHRoYXQgaXMgdXNlZCBmb3IgdGhlIGxvY2FsaXphdGlvbiwgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBgb3V0cHV0Rm9ybWF0YCBvcHRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2VyaWFsaXplTG9jYWxpemVkQXJyYXkoZm9ybSwgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyID0gJysnLCBmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zZXJpYWxpemUoZm9ybSwgdHJ1ZSwgJ2xvY2FsaXplZCcsIHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlciwgZm9yY2VkT3V0cHV0Rm9ybWF0KTtcbiAgICB9XG59XG5cbi8qKlxuICogSW5pdGlhbGl6ZSBtdWx0aXBsZSBET00gZWxlbWVudHMgaW4gb25lIGNhbGwgKGFuZCBwb3NzaWJseSBwYXNzIG11bHRpcGxlIHZhbHVlcyB0aGF0IHdpbGwgYmUgbWFwcGVkIHRvIGVhY2ggRE9NIGVsZW1lbnQpLlxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBJbml0IG11bHRpcGxlIERPTSBlbGVtZW50cyBpbiBvbmUgY2FsbCAoYW5kIHBvc3NpYmx5IHBhc3MgbXVsdGlwbGUgdmFsdWVzIHRoYXQgd2lsbCBiZSBtYXBwZWQgdG8gZWFjaCBET00gZWxlbWVudClcbiAqIFthbkVsZW1lbnQxLCBhbkVsZW1lbnQyLCBhbkVsZW1lbnQzXSA9IEF1dG9OdW1lcmljLm11bHRpcGxlKFtkb21FbGVtZW50MSwgZG9tRWxlbWVudDIsIGRvbUVsZW1lbnQzXSwgeyBvcHRpb25zIH0pO1xuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDIsIGFuRWxlbWVudDNdID0gQXV0b051bWVyaWMubXVsdGlwbGUoW2RvbUVsZW1lbnQxLCBkb21FbGVtZW50MiwgZG9tRWxlbWVudDNdLCBbeyBvcHRpb25zIH0sICdldXJvUG9zJ10pO1xuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDIsIGFuRWxlbWVudDNdID0gQXV0b051bWVyaWMubXVsdGlwbGUoW2RvbUVsZW1lbnQxLCBkb21FbGVtZW50MiwgZG9tRWxlbWVudDNdLCAxMjM0NS43ODksIHsgb3B0aW9ucyB9KTtcbiAqIFthbkVsZW1lbnQxLCBhbkVsZW1lbnQyLCBhbkVsZW1lbnQzXSA9IEF1dG9OdW1lcmljLm11bHRpcGxlKFtkb21FbGVtZW50MSwgZG9tRWxlbWVudDIsIGRvbUVsZW1lbnQzXSwgMTIzNDUuNzg5LCBbeyBvcHRpb25zIH0sICdldXJvUG9zJ10pO1xuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDIsIGFuRWxlbWVudDNdID0gQXV0b051bWVyaWMubXVsdGlwbGUuZnJlbmNoKFtkb21FbGVtZW50MSwgZG9tRWxlbWVudDIsIGRvbUVsZW1lbnQzXSwgWzEyMzQ1Ljc4OSwgMjM0Ljc4LCBudWxsXSwgeyBvcHRpb25zIH0pO1xuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDIsIGFuRWxlbWVudDNdID0gQXV0b051bWVyaWMubXVsdGlwbGUuZnJlbmNoKFtkb21FbGVtZW50MSwgZG9tRWxlbWVudDIsIGRvbUVsZW1lbnQzXSwgWzEyMzQ1Ljc4OSwgMjM0Ljc4LCBudWxsXSwgW3sgb3B0aW9ucyB9LCAnZXVyb1BvcyddKTtcbiAqXG4gKiAvLyBTcGVjaWFsIGNhc2UsIGlmIGEgPGZvcm0+IGVsZW1lbnQgaXMgcGFzc2VkIChvciBhbnkgb3RoZXIgJ3BhcmVudCcgKG9yICdyb290JykgRE9NIGVsZW1lbnQpLCB0aGVuIGF1dG9OdW1lcmljIHdpbGwgaW5pdGlhbGl6ZSBlYWNoIGNoaWxkIGA8aW5wdXQ+YCBlbGVtZW50cyByZWN1cnNpdmVseSwgaWdub3JpbmcgdGhvc2UgcmVmZXJlbmNlZCBpbiB0aGUgYGV4Y2x1ZGVgIGF0dHJpYnV0ZVxuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDJdID0gQXV0b051bWVyaWMubXVsdGlwbGUoeyByb290RWxlbWVudDogZm9ybUVsZW1lbnQgfSwgeyBvcHRpb25zIH0pO1xuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDJdID0gQXV0b051bWVyaWMubXVsdGlwbGUoeyByb290RWxlbWVudDogZm9ybUVsZW1lbnQsIGV4Y2x1ZGUgOiBbaGlkZGVuRWxlbWVudCwgdG9rZW5FbGVtZW50XSB9LCB7IG9wdGlvbnMgfSk7XG4gKiBbYW5FbGVtZW50MSwgYW5FbGVtZW50Ml0gPSBBdXRvTnVtZXJpYy5tdWx0aXBsZSh7IHJvb3RFbGVtZW50OiBmb3JtRWxlbWVudCwgZXhjbHVkZSA6IFtoaWRkZW5FbGVtZW50LCB0b2tlbkVsZW1lbnRdIH0sIFsxMjM0NS43ODksIG51bGxdLCB7IG9wdGlvbnMgfSk7XG4gKlxuICogLy8gSWYgeW91IHdhbnQgdG8gc2VsZWN0IG11bHRpcGxlIGVsZW1lbnRzIHZpYSBhIGNzcyBzZWxlY3RvciwgdGhlbiB5b3UgbXVzdCB1c2UgdGhlIGBtdWx0aXBsZWAgZnVuY3Rpb24uIFVuZGVyIHRoZSBob29kIGBRdWVyeVNlbGVjdG9yQWxsYCBpcyB1c2VkLlxuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDJdID0gQXV0b051bWVyaWMubXVsdGlwbGUoJy5teUNzc0NsYXNzID4gaW5wdXQnLCB7IG9wdGlvbnMgfSk7IC8vIFRoaXMgYWx3YXlzIHJldHVybiBhbiBBcnJheSwgZXZlbiBpZiB0aGVyZSBpcyBvbmx5IG9uZSBlbGVtZW50IHNlbGVjdGVkXG4gKiBbYW5FbGVtZW50MSwgYW5FbGVtZW50Ml0gPSBBdXRvTnVtZXJpYy5tdWx0aXBsZSgnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIFtudWxsLCAxMjM0NS43ODldLCB7IG9wdGlvbnMgfSk7IC8vIElkZW0gYWJvdmUsIGJ1dCB3aXRoIHBhc3NpbmcgdGhlIGluaXRpYWwgdmFsdWVzIHRvb1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfEFycmF5fHsgcm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50IH18eyByb290RWxlbWVudDogSFRNTEVsZW1lbnQsIGV4Y2x1ZGU6IEFycmF5PEhUTUxJbnB1dEVsZW1lbnQ+fX0gYXJnMVxuICogQHBhcmFtIHtudW1iZXJ8QXJyYXl8b2JqZWN0fG51bGx9IGluaXRpYWxWYWx1ZVxuICogQHBhcmFtIHtvYmplY3R8QXJyYXl8bnVsbH0gb3B0aW9uc1xuICogQHJldHVybnMge0FycmF5fVxuICovXG5BdXRvTnVtZXJpYy5tdWx0aXBsZSA9IChhcmcxLCBpbml0aWFsVmFsdWUgPSBudWxsLCBvcHRpb25zID0gbnVsbCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuXG4gICAgLy8gQW5hbHl6ZSB0aGUgYXJndW1lbnRzIGFuZCB0cmFuc2Zvcm0gdGhlbSB0byBtYWtlIHRoZW0gZXhwbG9pdGFibGVcbiAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNPYmplY3QoaW5pdGlhbFZhbHVlKSkge1xuICAgICAgICAvLyBJZiB0aGUgdXNlciBnYXZlIGFuIG9wdGlvbiBvYmplY3QgYXMgdGhlIHNlY29uZCBhcmd1bWVudCwgaW5zdGVhZCBvZiB0aGUgaW5pdGlhbCB2YWx1ZXNcbiAgICAgICAgb3B0aW9ucyA9IGluaXRpYWxWYWx1ZTtcbiAgICAgICAgaW5pdGlhbFZhbHVlID0gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcoYXJnMSkpIHtcbiAgICAgICAgYXJnMSA9IFsuLi4gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChhcmcxKV07IC8vIENvbnZlcnQgYSBOb2RlTGlzdCB0byBhbiBBcnJheSAoY2YuIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzM3Mjk3MjkyLzI4MzQ4OTgpXG4gICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc09iamVjdChhcmcxKSkge1xuICAgICAgICBpZiAoIWFyZzEuaGFzT3duUHJvcGVydHkoJ3Jvb3RFbGVtZW50JykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBvYmplY3QgcGFzc2VkIHRvIHRoZSAnbXVsdGlwbGUnIGZ1bmN0aW9uIGlzIGludmFsaWQgOyBubyAncm9vdEVsZW1lbnQnIGF0dHJpYnV0ZSBmb3VuZC5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJldHJpZXZlIHRoZSBET00gZWxlbWVudCBsaXN0IGZyb20gdGhlIGdpdmVuIDxmb3JtPiBlbGVtZW50XG4gICAgICAgIGNvbnN0IGVsZW1lbnRzID0gWy4uLiBhcmcxLnJvb3RFbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ2lucHV0JyldO1xuICAgICAgICBpZiAoYXJnMS5oYXNPd25Qcm9wZXJ0eSgnZXhjbHVkZScpKSB7XG4gICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoYXJnMS5leGNsdWRlKSkge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSAnZXhjbHVkZScgYXJyYXkgcGFzc2VkIHRvIHRoZSAnbXVsdGlwbGUnIGZ1bmN0aW9uIGlzIGludmFsaWQuYCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEZpbHRlciBvdXQgdGhlIGV4Y2x1ZGVkIGVsZW1lbnRzXG4gICAgICAgICAgICBhcmcxID0gQXV0b051bWVyaWNIZWxwZXIuZmlsdGVyT3V0KGVsZW1lbnRzLCBhcmcxLmV4Y2x1ZGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYXJnMSA9IGVsZW1lbnRzO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNBcnJheShhcmcxKSkge1xuICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gcGFyYW1ldGVycyB0byB0aGUgJ211bHRpcGxlJyBmdW5jdGlvbiBhcmUgaW52YWxpZC5gKTtcbiAgICB9XG5cbiAgICBpZiAoYXJnMS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgbGV0IHNob3dXYXJuaW5ncyA9IHRydWU7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMpICYmIEF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLnNob3dXYXJuaW5ncykpIHtcbiAgICAgICAgICAgIHNob3dXYXJuaW5ncyA9IG9wdGlvbnMuc2hvd1dhcm5pbmdzO1xuICAgICAgICB9XG5cbiAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgTm8gdmFsaWQgRE9NIGVsZW1lbnRzIHdlcmUgZ2l2ZW4gaGVuY2Ugbm8gQXV0b051bWVyaWMgb2JqZWN0IHdlcmUgaW5zdGFudGlhdGVkLmAsIHNob3dXYXJuaW5ncyk7XG5cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIC8vIEF0IHRoaXMgcG9pbnQsIHdlIGtub3cgYGFyZzFgIGlzIGFuIGFycmF5IG9mIERPTSBlbGVtZW50c1xuXG4gICAgLy8gVGhpcyBmdW5jdGlvbiBjYW4gYmUgaW5pdGlhbGl6ZWQgd2l0aCB0d28gdHlwZXMgb2YgYXJyYXksIG9uZSBmb3IgdGhlIGluaXRpYWwgdmFsdWVzLCBhbmQvb3Igb25lIGZvciB0aGUgb3B0aW9ucy5cbiAgICAvLyBTbyB3ZSBuZWVkIHRvIGZpbmQgb3V0IGlmIGFuIGFycmF5IGlzIGRldGVjdGVkIGlmIHRoZSB1c2VyIHBhc3NlZCBhbiBhcnJheSBvZiBpbml0aWFsIHZhbHVlcywgb3IgYW4gYXJyYXkgb2Ygb3B0aW9uc1xuICAgIC8vIFRoZXJlZm9yZSwgd2UgYW5hbHl6ZSB0aGUgY29udGVudCBvZiB0aGUgYXJyYXlzIGZvciB0aGUgc2Vjb25kIGFuZCB0aGlyZCBhcmd1bWVudHNcbiAgICAvLyAuLi5mb3IgdGhlIHNlY29uZCBwYXJhbWV0ZXIgOlxuICAgIGNvbnN0IGlzSW5pdGlhbFZhbHVlQXJyYXkgPSBBdXRvTnVtZXJpY0hlbHBlci5pc0FycmF5KGluaXRpYWxWYWx1ZSk7XG4gICAgY29uc3QgaXNJbml0aWFsVmFsdWVBcnJheUFuZE5vdEVtcHR5ID0gaXNJbml0aWFsVmFsdWVBcnJheSAmJiBpbml0aWFsVmFsdWUubGVuZ3RoID49IDE7XG4gICAgbGV0IHNlY29uZEFyZ3VtZW50SXNJbml0aWFsVmFsdWVBcnJheSA9IGZhbHNlO1xuICAgIGxldCBzZWNvbmRBcmd1bWVudElzT3B0aW9uQXJyYXkgPSBmYWxzZTtcbiAgICAvLyBBbnkgb2YgdGhlIGFycmF5cyBjYW4gYmUgZWl0aGVyIGFuIGFycmF5IG9mIGluaXRpYWwgdmFsdWVzLCBvciBhbiBhcnJheSBvZiBvcHRpb24gb2JqZWN0L3ByZS1kZWZpbmVkIG9wdGlvbiBuYW1lc1xuICAgIGlmIChpc0luaXRpYWxWYWx1ZUFycmF5QW5kTm90RW1wdHkpIHtcbiAgICAgICAgY29uc3QgdHlwZU9mRmlyc3RBcnJheUVsZW1lbnQgPSB0eXBlb2YgTnVtYmVyKGluaXRpYWxWYWx1ZVswXSk7XG4gICAgICAgIC8vIEZpcnN0IHdlIHRlc3QgdGhlIHNlY29uZCBhcmd1bWVudFxuICAgICAgICBzZWNvbmRBcmd1bWVudElzSW5pdGlhbFZhbHVlQXJyYXkgPSB0eXBlT2ZGaXJzdEFycmF5RWxlbWVudCA9PT0gJ251bWJlcicgJiYgIWlzTmFOKE51bWJlcihpbml0aWFsVmFsdWVbMF0pKTtcblxuICAgICAgICBpZiAoIXNlY29uZEFyZ3VtZW50SXNJbml0aWFsVmFsdWVBcnJheSkge1xuICAgICAgICAgICAgLy8gSWYgdGhlIHNlY29uZCBhcmd1bWVudCBpcyBhbiBhcnJheSwgYnV0IG5vdCBhbiBhcnJheSBvZiB2YWx1ZXMsIGNoZWNrIGlmIGl0J3MgaW5zdGVhZCBhbiBhcnJheSBvZiBvcHRpb25zL3ByZS1kZWZpbmVkIG9wdGlvbiBuYW1lc1xuICAgICAgICAgICAgaWYgKHR5cGVPZkZpcnN0QXJyYXlFbGVtZW50ID09PSAnc3RyaW5nJyB8fCBpc05hTih0eXBlT2ZGaXJzdEFycmF5RWxlbWVudCkgfHwgdHlwZU9mRmlyc3RBcnJheUVsZW1lbnQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgc2Vjb25kQXJndW1lbnRJc09wdGlvbkFycmF5ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIC4uLmZvciB0aGUgdGhpcmQgcGFyYW1ldGVyIDpcbiAgICBjb25zdCBpc09wdGlvbnNBcnJheUFuZE5vdEVtcHR5ID0gQXV0b051bWVyaWNIZWxwZXIuaXNBcnJheShvcHRpb25zKSAmJiBvcHRpb25zLmxlbmd0aCA+PSAxO1xuICAgIGxldCB0aGlyZEFyZ3VtZW50SXNPcHRpb25BcnJheSA9IGZhbHNlO1xuICAgIGlmIChpc09wdGlvbnNBcnJheUFuZE5vdEVtcHR5KSB7XG4gICAgICAgIGNvbnN0IHR5cGVPZkZpcnN0QXJyYXlFbGVtZW50ID0gdHlwZW9mIG9wdGlvbnNbMF07XG4gICAgICAgIGlmICh0eXBlT2ZGaXJzdEFycmF5RWxlbWVudCA9PT0gJ3N0cmluZycgfHwgdHlwZU9mRmlyc3RBcnJheUVsZW1lbnQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgdGhpcmQgYXJndW1lbnQgaXMgYW4gYXJyYXkgb2Ygb3B0aW9ucy9wcmUtZGVmaW5lZCBvcHRpb24gbmFtZXNcbiAgICAgICAgICAgIHRoaXJkQXJndW1lbnRJc09wdGlvbkFycmF5ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIERlcGVuZGluZyBvZiBvdXIgZmluZGluZ3MsIHdlIGdlbmVyYXRlIHRoZSBvcHRpb25zIHZhcmlhYmxlIHRvIHVzZSBgb3B0aW9uc1RvVXNlYCwgZWl0aGVyIGRpcmVjdGx5LCBvciBtZXJnZWRcbiAgICBsZXQgb3B0aW9uc1RvVXNlO1xuICAgIGlmIChzZWNvbmRBcmd1bWVudElzT3B0aW9uQXJyYXkpIHtcbiAgICAgICAgb3B0aW9uc1RvVXNlID0gQXV0b051bWVyaWMubWVyZ2VPcHRpb25zKGluaXRpYWxWYWx1ZSk7XG4gICAgfSBlbHNlIGlmICh0aGlyZEFyZ3VtZW50SXNPcHRpb25BcnJheSkge1xuICAgICAgICBvcHRpb25zVG9Vc2UgPSBBdXRvTnVtZXJpYy5tZXJnZU9wdGlvbnMob3B0aW9ucyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3B0aW9uc1RvVXNlID0gb3B0aW9ucztcbiAgICB9XG5cblxuICAgIC8vIEluaXRpYWxpemUgdGhlIGluaXRpYWwgdmFsdWVzXG4gICAgY29uc3QgaXNJbml0aWFsVmFsdWVOdW1iZXIgPSBBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcihpbml0aWFsVmFsdWUpO1xuICAgIGxldCBpbml0aWFsVmFsdWVBcnJheVNpemU7XG4gICAgaWYgKHNlY29uZEFyZ3VtZW50SXNJbml0aWFsVmFsdWVBcnJheSkge1xuICAgICAgICBpbml0aWFsVmFsdWVBcnJheVNpemUgPSBpbml0aWFsVmFsdWUubGVuZ3RoO1xuICAgIH1cblxuICAgIC8vIEluc3RhbnRpYXRlIGVhY2ggQXV0b051bWVyaWMgb2JqZWN0c1xuICAgIGFyZzEuZm9yRWFjaCgoZG9tRWxlbWVudCwgaW5kZXgpID0+IHtcbiAgICAgICAgaWYgKGlzSW5pdGlhbFZhbHVlTnVtYmVyKSB7XG4gICAgICAgICAgICAvLyBXZSBzZXQgdGhlIHNhbWUgdmFsdWUgZm9yIGVhY2ggZWxlbWVudHNcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCBpbml0aWFsVmFsdWUsIG9wdGlvbnNUb1VzZSkpO1xuICAgICAgICB9IGVsc2UgaWYgKHNlY29uZEFyZ3VtZW50SXNJbml0aWFsVmFsdWVBcnJheSAmJiBpbmRleCA8PSBpbml0aWFsVmFsdWVBcnJheVNpemUpIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCBpbml0aWFsVmFsdWVbaW5kZXhdLCBvcHRpb25zVG9Vc2UpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCBudWxsLCBvcHRpb25zVG9Vc2UpKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbi8qKlxuICogUG9seWZpbGwgZm9yIG9ic29sZXRlIGJyb3dzZXJzIGxpa2UgSUVcbiAqL1xuKGZ1bmN0aW9uKCkge1xuLy8gUG9seWZpbGwgZm9yIGBDdXN0b21FdmVudGAgKGNmLiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvQ3VzdG9tRXZlbnQvQ3VzdG9tRXZlbnQpXG5pZiAodHlwZW9mIHdpbmRvdyA9PT0gJ3VuZGVmaW5lZCcgfHwgd2luZG93LkN1c3RvbUV2ZW50ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBDdXN0b21FdmVudChldmVudCwgcGFyYW1zKSB7XG4gICAgcGFyYW1zID0gcGFyYW1zIHx8IHsgYnViYmxlczogZmFsc2UsIGNhbmNlbGFibGU6IGZhbHNlLCBkZXRhaWw6IHZvaWQoMCkgfTtcbiAgICBjb25zdCBldnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnQ3VzdG9tRXZlbnQnKTtcbiAgICBldnQuaW5pdEN1c3RvbUV2ZW50KGV2ZW50LCBwYXJhbXMuYnViYmxlcywgcGFyYW1zLmNhbmNlbGFibGUsIHBhcmFtcy5kZXRhaWwpO1xuICAgIHJldHVybiBldnQ7XG59XG5cbkN1c3RvbUV2ZW50LnByb3RvdHlwZSA9IHdpbmRvdy5FdmVudC5wcm90b3R5cGU7XG53aW5kb3cuQ3VzdG9tRXZlbnQgPSBDdXN0b21FdmVudDtcblxuLy8gUG9seWZpbGwgZm9yIGBBcnJheS5mcm9tKClgIChGaXggaXNzdWUgIzQ5NSlcbmlmICghQXJyYXkuZnJvbSkge1xuICAgIEFycmF5LmZyb20gPSBvYmplY3QgPT4gW10uc2xpY2UuY2FsbChvYmplY3QpO1xufVxufSkoKTtcbiJdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7O0FBQUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBK0NBO0FBQ0E7QUFDQTtBQURBO0FBQ0E7OztBQUFBO0FBQ0E7Ozs7Ozs7OztBQUNBOzs7OztBQUtBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXVDQTtBQUFBO0FBQ0E7QUFEQTtBQUNBO0FBREE7QUFBQTtBQUNBO0FBREE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUhBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFLQTtBQUNBO0FBQ0E7QUFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVBBO0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQU1BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QUFNQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O0FBTUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQU1BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QUFNQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7OztBQUtBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7QUFLQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBV0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O0FBTUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7QUFJQTtBQUFBO0FBQUE7QUFDQTtBQUNBOzs7O0FBSUE7QUFBQTtBQUFBO0FBbFdBO0FBQ0E7QUFvV0E7QUFDQTs7OztBQUlBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBblRBO0FBQ0E7QUFxVEE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFKQTtBQU1BO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUE2TkE7Ozs7Ozs7OztBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7OztBQUlBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQXFCQTs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVRBO0FBV0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7O0FBY0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFMQTtBQU9BO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBVUE7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFSQTtBQUNBO0FBVUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUE7Ozs7Ozs7Ozs7Ozs7OztBQWVBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7O0FBSUE7Ozs7Ozs7Ozs7Ozs7OztBQWVBOzs7Ozs7Ozs7OztBQVFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7O0FBSUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW1CQTtBQUFBO0FBQ0E7QUFEQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQVVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFnQkE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBaEJBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFpQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFMQTtBQUNBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBUEE7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7O0FBWUE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FBb0NBOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUFVQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQVVBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFlQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBWkE7QUFjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFTQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFjQTtBQUFBO0FBQ0E7QUFEQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBREE7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7OztBQVdBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQWlLQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FBVUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBRkE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBODZCQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFRQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBR0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7O0FBaVNBOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQWtPQTs7Ozs7Ozs7Ozs7Ozs7QUFjQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFSQTtBQVVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFSQTtBQVVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFSQTtBQVVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFSQTtBQVVBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBUkE7QUFVQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBUkE7QUFVQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBUkE7QUFVQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBUkE7QUFVQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFvV0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBeUNBOzs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBY0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBMENBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBUEE7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7QUFXQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBWEE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQVlBO0FBQ0E7QUFDQTtBQURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBcE5BO0FBQ0E7QUFzTkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXZCQTtBQXlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBbkJBO0FBcUJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBSUE7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBWUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QUFNQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBZEE7QUFnQkE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7QUE2TUE7Ozs7QUFJQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBREE7QUFBQTtBQUFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQXVCQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQW1JQTs7Ozs7Ozs7O0FBU0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQThDQTs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQWFBOzs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBY0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFIQTtBQUNBO0FBS0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7OztBQVdBO0FBQUE7QUFDQTtBQURBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQURBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVJBO0FBQ0E7QUFVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUZBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFEQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFxQkE7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBcENBO0FBc0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFEQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFEQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQURBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUhBO0FBQUE7QUFBQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBREE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBRUE7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7O0FBcnBQQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7O0FBYUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQXdNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7OztBQSs2QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTs7O0FBZ2tDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBNEhBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBWUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXRLQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBdUtBO0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFEQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFGQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQWVBO0FBQ0E7QUFDQTtBQUNBO0FBWUE7QUFDQTtBQUNBO0FBQ0E7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUFVQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQWxCQTtBQUFBO0FBQUE7QUFDQTtBQWlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBckNBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFxQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFQQTtBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQVVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQTdCQTtBQUFBO0FBQUE7QUFDQTtBQTRCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBREE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUFVQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFFQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUFVQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQW1MQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFlQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFGQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQURBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFtQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQVVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBckJBO0FBQ0E7QUF1QkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQWdDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FBVUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVpBO0FBQ0E7QUFjQTtBQUNBO0FBMUNBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUEwQ0E7QUFBQTtBQUNBO0FBREE7QUFDQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7OztBQVlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBVkE7QUFZQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVZBO0FBWUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQTZNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBWEE7QUFDQTtBQWFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7OztBQVdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUNBO0FBZkE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQWdCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBckJBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFvQkE7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFUQTtBQUNBO0FBV0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7OztBQVVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFLQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFKQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBTUE7QUFDQTtBQUNBO0FBREE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7OztBQVNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBWEE7QUFDQTtBQWFBO0FBQ0E7OztBQW1CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFrOUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFSQTtBQVVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQW1CQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUlBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFvQkE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSUE7QUFDQTtBQUlBO0FBQ0E7OztBQWtDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBNkJBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUEvRkE7QUFDQTtBQWlHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7O0FBd0dBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFjQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFvQkE7QUFDQTtBQUNBO0FBQ0E7OztBQWdWQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFJQTtBQUNBO0FBQ0E7QUFDQTs7O0FBZ2NBO0FBQUE7QUFBQTtBQUNBO0FBREE7QUFDQTtBQURBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXZCQTtBQXlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7Ozs7OztBQUdBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBdm5SQTtBQWlwUkE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/AutoNumeric.js\n"); /***/ }), /***/ "./src/AutoNumericDefaultSettings.js": /*!*******************************************!*\ !*** ./src/AutoNumericDefaultSettings.js ***! \*******************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval("\n\nvar _AutoNumeric = __webpack_require__(/*! ./AutoNumeric */ \"./src/AutoNumeric.js\");\n\nvar _AutoNumeric2 = _interopRequireDefault(_AutoNumeric);\n\nvar _AutoNumericOptions = __webpack_require__(/*! ./AutoNumericOptions */ \"./src/AutoNumericOptions.js\");\n\nvar _AutoNumericOptions2 = _interopRequireDefault(_AutoNumericOptions);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/* eslint no-unused-vars: 0 */\n\n/**\n * The defaults options.\n * These can be overridden by the following methods:\n * - HTML5 data attributes (ie. ``)\n * - Options passed to the `update` method (ie. `anElement.update({ currencySymbol: ' €' });`), or simply during the initialization (ie. `new AutoNumeric(domElement, { options });`)\n */\n/**\n * Default settings for autoNumeric.js\n * @author Alexandre Bonneau \n * @copyright © 2016 Alexandre Bonneau\n *\n * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sub license, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\nObject.defineProperty(_AutoNumeric2.default, 'defaultSettings', {\n get: function get() {\n return {\n allowDecimalPadding: _AutoNumeric2.default.options.allowDecimalPadding.always,\n caretPositionOnFocus: _AutoNumeric2.default.options.caretPositionOnFocus.doNoForceCaretPosition,\n createLocalList: _AutoNumeric2.default.options.createLocalList.createList,\n currencySymbol: _AutoNumeric2.default.options.currencySymbol.none,\n currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.prefix,\n decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n decimalCharacterAlternative: _AutoNumeric2.default.options.decimalCharacterAlternative.none,\n decimalPlaces: _AutoNumeric2.default.options.decimalPlaces.two,\n decimalPlacesRawValue: _AutoNumeric2.default.options.decimalPlacesRawValue.useDefault,\n decimalPlacesShownOnBlur: _AutoNumeric2.default.options.decimalPlacesShownOnBlur.useDefault,\n decimalPlacesShownOnFocus: _AutoNumeric2.default.options.decimalPlacesShownOnFocus.useDefault,\n defaultValueOverride: _AutoNumeric2.default.options.defaultValueOverride.doNotOverride,\n digitalGroupSpacing: _AutoNumeric2.default.options.digitalGroupSpacing.three,\n digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.comma,\n divisorWhenUnfocused: _AutoNumeric2.default.options.divisorWhenUnfocused.none,\n emptyInputBehavior: _AutoNumeric2.default.options.emptyInputBehavior.focus,\n eventBubbles: _AutoNumeric2.default.options.eventBubbles.bubbles,\n eventIsCancelable: _AutoNumeric2.default.options.eventIsCancelable.isCancelable,\n failOnUnknownOption: _AutoNumeric2.default.options.failOnUnknownOption.ignore,\n formatOnPageLoad: _AutoNumeric2.default.options.formatOnPageLoad.format,\n historySize: _AutoNumeric2.default.options.historySize.medium,\n isCancellable: _AutoNumeric2.default.options.isCancellable.cancellable,\n leadingZero: _AutoNumeric2.default.options.leadingZero.deny,\n maximumValue: _AutoNumeric2.default.options.maximumValue.tenTrillions,\n minimumValue: _AutoNumeric2.default.options.minimumValue.tenTrillions,\n modifyValueOnWheel: _AutoNumeric2.default.options.modifyValueOnWheel.modifyValue,\n negativeBracketsTypeOnBlur: _AutoNumeric2.default.options.negativeBracketsTypeOnBlur.none,\n negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.none,\n negativeSignCharacter: _AutoNumeric2.default.options.negativeSignCharacter.hyphen,\n noEventListeners: _AutoNumeric2.default.options.noEventListeners.addEvents,\n //TODO Shouldn't we use `truncate` as the default value?\n onInvalidPaste: _AutoNumeric2.default.options.onInvalidPaste.error,\n outputFormat: _AutoNumeric2.default.options.outputFormat.none,\n overrideMinMaxLimits: _AutoNumeric2.default.options.overrideMinMaxLimits.doNotOverride,\n positiveSignCharacter: _AutoNumeric2.default.options.positiveSignCharacter.plus,\n rawValueDivisor: _AutoNumeric2.default.options.rawValueDivisor.none,\n readOnly: _AutoNumeric2.default.options.readOnly.readWrite,\n roundingMethod: _AutoNumeric2.default.options.roundingMethod.halfUpSymmetric,\n saveValueToSessionStorage: _AutoNumeric2.default.options.saveValueToSessionStorage.doNotSave,\n selectNumberOnly: _AutoNumeric2.default.options.selectNumberOnly.selectNumbersOnly,\n selectOnFocus: _AutoNumeric2.default.options.selectOnFocus.select,\n serializeSpaces: _AutoNumeric2.default.options.serializeSpaces.plus,\n showOnlyNumbersOnFocus: _AutoNumeric2.default.options.showOnlyNumbersOnFocus.showAll,\n showPositiveSign: _AutoNumeric2.default.options.showPositiveSign.hide,\n showWarnings: _AutoNumeric2.default.options.showWarnings.show,\n styleRules: _AutoNumeric2.default.options.styleRules.none,\n suffixText: _AutoNumeric2.default.options.suffixText.none,\n symbolWhenUnfocused: _AutoNumeric2.default.options.symbolWhenUnfocused.none,\n unformatOnHover: _AutoNumeric2.default.options.unformatOnHover.unformat,\n unformatOnSubmit: _AutoNumeric2.default.options.unformatOnSubmit.keepCurrentValue,\n valuesToStrings: _AutoNumeric2.default.options.valuesToStrings.none,\n watchExternalChanges: _AutoNumeric2.default.options.watchExternalChanges.doNotWatch,\n wheelOn: _AutoNumeric2.default.options.wheelOn.focus,\n wheelStep: _AutoNumeric2.default.options.wheelStep.progressive\n };\n }\n});\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWNEZWZhdWx0U2V0dGluZ3MuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9BdXRvTnVtZXJpYy9zcmMvQXV0b051bWVyaWNEZWZhdWx0U2V0dGluZ3MuanM/NTJkNiJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIERlZmF1bHQgc2V0dGluZ3MgZm9yIGF1dG9OdW1lcmljLmpzXG4gKiBAYXV0aG9yIEFsZXhhbmRyZSBCb25uZWF1IDxhbGV4YW5kcmUuYm9ubmVhdUBsaW51eGZyLmV1PlxuICogQGNvcHlyaWdodCDCqSAyMDE2IEFsZXhhbmRyZSBCb25uZWF1XG4gKlxuICogVGhlIE1JVCBMaWNlbnNlIChodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocClcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvblxuICogb2J0YWluaW5nIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb25cbiAqIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dFxuICogcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsXG4gKiBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWIgbGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZVxuICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmdcbiAqIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsXG4gKiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVNcbiAqIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EXG4gKiBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVFxuICogSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksXG4gKiBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1JcbiAqIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgQXV0b051bWVyaWMgZnJvbSAnLi9BdXRvTnVtZXJpYyc7XG5pbXBvcnQgQXV0b051bWVyaWNPcHRpb25zIGZyb20gJy4vQXV0b051bWVyaWNPcHRpb25zJztcblxuLyogZXNsaW50IG5vLXVudXNlZC12YXJzOiAwICovXG5cbi8qKlxuICogVGhlIGRlZmF1bHRzIG9wdGlvbnMuXG4gKiBUaGVzZSBjYW4gYmUgb3ZlcnJpZGRlbiBieSB0aGUgZm9sbG93aW5nIG1ldGhvZHM6XG4gKiAtIEhUTUw1IGRhdGEgYXR0cmlidXRlcyAoaWUuIGA8aW5wdXQgdHlwZT1cInRleHRcIiBkYXRhLWN1cnJlbmN5LXN5bWJvbD1cIiDigqxcIj5gKVxuICogLSBPcHRpb25zIHBhc3NlZCB0byB0aGUgYHVwZGF0ZWAgbWV0aG9kIChpZS4gYGFuRWxlbWVudC51cGRhdGUoeyBjdXJyZW5jeVN5bWJvbDogJyDigqwnIH0pO2ApLCBvciBzaW1wbHkgZHVyaW5nIHRoZSBpbml0aWFsaXphdGlvbiAoaWUuIGBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgeyBvcHRpb25zIH0pO2ApXG4gKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShBdXRvTnVtZXJpYywgJ2RlZmF1bHRTZXR0aW5ncycsIHtcbiAgICBnZXQoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBhbGxvd0RlY2ltYWxQYWRkaW5nICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nLmFsd2F5cyxcbiAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkZvY3VzICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmRvTm9Gb3JjZUNhcmV0UG9zaXRpb24sXG4gICAgICAgICAgICBjcmVhdGVMb2NhbExpc3QgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jcmVhdGVMb2NhbExpc3QuY3JlYXRlTGlzdCxcbiAgICAgICAgICAgIGN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sLm5vbmUsXG4gICAgICAgICAgICBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXgsXG4gICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmRvdCxcbiAgICAgICAgICAgIGRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZS5ub25lLFxuICAgICAgICAgICAgZGVjaW1hbFBsYWNlcyAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlcy50d28sXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUudXNlRGVmYXVsdCxcbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ci51c2VEZWZhdWx0LFxuICAgICAgICAgICAgZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cy51c2VEZWZhdWx0LFxuICAgICAgICAgICAgZGVmYXVsdFZhbHVlT3ZlcnJpZGUgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVmYXVsdFZhbHVlT3ZlcnJpZGUuZG9Ob3RPdmVycmlkZSxcbiAgICAgICAgICAgIGRpZ2l0YWxHcm91cFNwYWNpbmcgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcudGhyZWUsXG4gICAgICAgICAgICBkaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmNvbW1hLFxuICAgICAgICAgICAgZGl2aXNvcldoZW5VbmZvY3VzZWQgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGl2aXNvcldoZW5VbmZvY3VzZWQubm9uZSxcbiAgICAgICAgICAgIGVtcHR5SW5wdXRCZWhhdmlvciAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5mb2N1cyxcbiAgICAgICAgICAgIGV2ZW50QnViYmxlcyAgICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmV2ZW50QnViYmxlcy5idWJibGVzLFxuICAgICAgICAgICAgZXZlbnRJc0NhbmNlbGFibGUgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZXZlbnRJc0NhbmNlbGFibGUuaXNDYW5jZWxhYmxlLFxuICAgICAgICAgICAgZmFpbE9uVW5rbm93bk9wdGlvbiAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZmFpbE9uVW5rbm93bk9wdGlvbi5pZ25vcmUsXG4gICAgICAgICAgICBmb3JtYXRPblBhZ2VMb2FkICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5mb3JtYXRPblBhZ2VMb2FkLmZvcm1hdCxcbiAgICAgICAgICAgIGhpc3RvcnlTaXplICAgICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmhpc3RvcnlTaXplLm1lZGl1bSxcbiAgICAgICAgICAgIGlzQ2FuY2VsbGFibGUgICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmlzQ2FuY2VsbGFibGUuY2FuY2VsbGFibGUsXG4gICAgICAgICAgICBsZWFkaW5nWmVybyAgICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5kZW55LFxuICAgICAgICAgICAgbWF4aW11bVZhbHVlICAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubWF4aW11bVZhbHVlLnRlblRyaWxsaW9ucyxcbiAgICAgICAgICAgIG1pbmltdW1WYWx1ZSAgICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm1pbmltdW1WYWx1ZS50ZW5UcmlsbGlvbnMsXG4gICAgICAgICAgICBtb2RpZnlWYWx1ZU9uV2hlZWwgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5tb2RpZnlWYWx1ZU9uV2hlZWwubW9kaWZ5VmFsdWUsXG4gICAgICAgICAgICBuZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciAgIDogQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5ub25lLFxuICAgICAgICAgICAgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSxcbiAgICAgICAgICAgIG5lZ2F0aXZlU2lnbkNoYXJhY3RlciAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlci5oeXBoZW4sXG4gICAgICAgICAgICBub0V2ZW50TGlzdGVuZXJzICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5ub0V2ZW50TGlzdGVuZXJzLmFkZEV2ZW50cyxcbiAgICAgICAgICAgIC8vVE9ETyBTaG91bGRuJ3Qgd2UgdXNlIGB0cnVuY2F0ZWAgYXMgdGhlIGRlZmF1bHQgdmFsdWU/XG4gICAgICAgICAgICBvbkludmFsaWRQYXN0ZSAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5lcnJvcixcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdCAgICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5ub25lLFxuICAgICAgICAgICAgb3ZlcnJpZGVNaW5NYXhMaW1pdHMgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMuZG9Ob3RPdmVycmlkZSxcbiAgICAgICAgICAgIHBvc2l0aXZlU2lnbkNoYXJhY3RlciAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLnBvc2l0aXZlU2lnbkNoYXJhY3Rlci5wbHVzLFxuICAgICAgICAgICAgcmF3VmFsdWVEaXZpc29yICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMucmF3VmFsdWVEaXZpc29yLm5vbmUsXG4gICAgICAgICAgICByZWFkT25seSAgICAgICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5yZWFkT25seS5yZWFkV3JpdGUsXG4gICAgICAgICAgICByb3VuZGluZ01ldGhvZCAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC5oYWxmVXBTeW1tZXRyaWMsXG4gICAgICAgICAgICBzYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5zYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlLmRvTm90U2F2ZSxcbiAgICAgICAgICAgIHNlbGVjdE51bWJlck9ubHkgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLnNlbGVjdE51bWJlck9ubHkuc2VsZWN0TnVtYmVyc09ubHksXG4gICAgICAgICAgICBzZWxlY3RPbkZvY3VzICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5zZWxlY3RPbkZvY3VzLnNlbGVjdCxcbiAgICAgICAgICAgIHNlcmlhbGl6ZVNwYWNlcyAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLnNlcmlhbGl6ZVNwYWNlcy5wbHVzLFxuICAgICAgICAgICAgc2hvd09ubHlOdW1iZXJzT25Gb2N1cyAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuc2hvd09ubHlOdW1iZXJzT25Gb2N1cy5zaG93QWxsLFxuICAgICAgICAgICAgc2hvd1Bvc2l0aXZlU2lnbiAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuc2hvd1Bvc2l0aXZlU2lnbi5oaWRlLFxuICAgICAgICAgICAgc2hvd1dhcm5pbmdzICAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuc2hvd1dhcm5pbmdzLnNob3csXG4gICAgICAgICAgICBzdHlsZVJ1bGVzICAgICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5zdHlsZVJ1bGVzLm5vbmUsXG4gICAgICAgICAgICBzdWZmaXhUZXh0ICAgICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5zdWZmaXhUZXh0Lm5vbmUsXG4gICAgICAgICAgICBzeW1ib2xXaGVuVW5mb2N1c2VkICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5zeW1ib2xXaGVuVW5mb2N1c2VkLm5vbmUsXG4gICAgICAgICAgICB1bmZvcm1hdE9uSG92ZXIgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy51bmZvcm1hdE9uSG92ZXIudW5mb3JtYXQsXG4gICAgICAgICAgICB1bmZvcm1hdE9uU3VibWl0ICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy51bmZvcm1hdE9uU3VibWl0LmtlZXBDdXJyZW50VmFsdWUsXG4gICAgICAgICAgICB2YWx1ZXNUb1N0cmluZ3MgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy52YWx1ZXNUb1N0cmluZ3Mubm9uZSxcbiAgICAgICAgICAgIHdhdGNoRXh0ZXJuYWxDaGFuZ2VzICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLndhdGNoRXh0ZXJuYWxDaGFuZ2VzLmRvTm90V2F0Y2gsXG4gICAgICAgICAgICB3aGVlbE9uICAgICAgICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy53aGVlbE9uLmZvY3VzLFxuICAgICAgICAgICAgd2hlZWxTdGVwICAgICAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMud2hlZWxTdGVwLnByb2dyZXNzaXZlLFxuICAgICAgICB9O1xuICAgIH0sXG59KTtcblxuIl0sIm1hcHBpbmdzIjoiOztBQTZCQTtBQUNBOzs7QUFBQTtBQUNBOzs7OztBQUNBO0FBQ0E7QUFDQTs7Ozs7O0FBbENBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXdDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUF0REE7QUF3REE7QUExREEiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./src/AutoNumericDefaultSettings.js\n"); /***/ }), /***/ "./src/AutoNumericEnum.js": /*!********************************!*\ !*** ./src/AutoNumericEnum.js ***! \********************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n/**\n * Enumerations for autoNumeric.js\n * @author Alexandre Bonneau \n * @copyright © 2016 Alexandre Bonneau\n *\n * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sub license, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\n/**\n * Object that store the helper enumerations\n * @type {{ allowedTagList: [string], keyCode: {}, fromCharCodeKeyCode: [string], keyName: {} }}\n */\nvar AutoNumericEnum = {\n /**\n * List of allowed tag on which autoNumeric can be used.\n */\n get allowedTagList() {\n return ['b', 'caption', 'cite', 'code', 'const', 'dd', 'del', 'div', 'dfn', 'dt', 'em', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'input', 'ins', 'kdb', 'label', 'li', 'option', 'output', 'p', 'q', 's', 'sample', 'span', 'strong', 'td', 'th', 'u'];\n },\n\n /**\n * Wrapper variable that hold named keyboard keys with their respective keyCode as seen in DOM events.\n * cf. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode\n *\n * This deprecated information is used for obsolete browsers.\n * @deprecated\n */\n get keyCode() {\n return {\n Backspace: 8,\n Tab: 9,\n // No 10, 11\n // 12 === NumpadEqual on Windows\n // 12 === NumLock on Mac\n Enter: 13,\n // 14 reserved, but not used\n // 15 does not exists\n Shift: 16,\n Ctrl: 17,\n Alt: 18,\n Pause: 19,\n CapsLock: 20,\n // 21, 22, 23, 24, 25 : Asiatic key codes\n // 26 does not exists\n Esc: 27,\n // 28, 29, 30, 31 : Convert, NonConvert, Accept and ModeChange keys\n Space: 32,\n PageUp: 33,\n PageDown: 34,\n End: 35,\n Home: 36,\n LeftArrow: 37,\n UpArrow: 38,\n RightArrow: 39,\n DownArrow: 40,\n Insert: 45,\n Delete: 46,\n num0: 48,\n num1: 49,\n num2: 50,\n num3: 51,\n num4: 52,\n num5: 53,\n num6: 54,\n num7: 55,\n num8: 56,\n num9: 57,\n a: 65,\n b: 66,\n c: 67,\n d: 68,\n e: 69,\n f: 70,\n g: 71,\n h: 72,\n i: 73,\n j: 74,\n k: 75,\n l: 76,\n m: 77,\n n: 78,\n o: 79,\n p: 80,\n q: 81,\n r: 82,\n s: 83,\n t: 84,\n u: 85,\n v: 86,\n w: 87,\n x: 88,\n y: 89,\n z: 90,\n OSLeft: 91,\n OSRight: 92,\n ContextMenu: 93,\n numpad0: 96,\n numpad1: 97,\n numpad2: 98,\n numpad3: 99,\n numpad4: 100,\n numpad5: 101,\n numpad6: 102,\n numpad7: 103,\n numpad8: 104,\n numpad9: 105,\n MultiplyNumpad: 106,\n PlusNumpad: 107,\n MinusNumpad: 109,\n DotNumpad: 110,\n SlashNumpad: 111,\n F1: 112,\n F2: 113,\n F3: 114,\n F4: 115,\n F5: 116,\n F6: 117,\n F7: 118,\n F8: 119,\n F9: 120,\n F10: 121,\n F11: 122,\n F12: 123,\n NumLock: 144,\n ScrollLock: 145,\n HyphenFirefox: 173, // On the latest Linux and Windows OS, cf. https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode and https://bugzilla.mozilla.org/show_bug.cgi?id=787504 and https://stackoverflow.com/a/35473259/2834898\n MyComputer: 182,\n MyCalculator: 183,\n Semicolon: 186,\n Equal: 187,\n Comma: 188,\n Hyphen: 189,\n Dot: 190,\n Slash: 191,\n Backquote: 192,\n LeftBracket: 219,\n Backslash: 220,\n RightBracket: 221,\n Quote: 222,\n Command: 224,\n AltGraph: 225,\n AndroidDefault: 229 // Android Chrome returns the same keycode number 229 for all keys pressed\n };\n },\n\n /**\n * This object is the reverse of `keyCode`, and is used to translate the key code to named keys when no valid characters can be obtained by `String.fromCharCode`.\n * This object keys correspond to the `event.keyCode` number, and returns the corresponding key name (à la event.key)\n */\n get fromCharCodeKeyCode() {\n return {\n 0: 'LaunchCalculator',\n 8: 'Backspace',\n 9: 'Tab',\n 13: 'Enter',\n 16: 'Shift',\n 17: 'Ctrl',\n 18: 'Alt',\n 19: 'Pause',\n 20: 'CapsLock',\n 27: 'Escape',\n 32: ' ',\n 33: 'PageUp',\n 34: 'PageDown',\n 35: 'End',\n 36: 'Home',\n 37: 'ArrowLeft',\n 38: 'ArrowUp',\n 39: 'ArrowRight',\n 40: 'ArrowDown',\n 45: 'Insert',\n 46: 'Delete',\n 48: '0',\n 49: '1',\n 50: '2',\n 51: '3',\n 52: '4',\n 53: '5',\n 54: '6',\n 55: '7',\n 56: '8',\n 57: '9',\n // 65: 'a',\n // 66: 'b',\n // 67: 'c',\n // 68: 'd',\n // 69: 'e',\n // 70: 'f',\n // 71: 'g',\n // 72: 'h',\n // 73: 'i',\n // 74: 'j',\n // 75: 'k',\n // 76: 'l',\n // 77: 'm',\n // 78: 'n',\n // 79: 'o',\n // 80: 'p',\n // 81: 'q',\n // 82: 'r',\n // 83: 's',\n // 84: 't',\n // 85: 'u',\n // 86: 'v',\n // 87: 'w',\n // 88: 'x',\n // 89: 'y',\n // 90: 'z',\n 91: 'OS', // Note: Firefox and Chrome reports 'OS' instead of 'OSLeft'\n 92: 'OSRight',\n 93: 'ContextMenu',\n 96: '0',\n 97: '1',\n 98: '2',\n 99: '3',\n 100: '4',\n 101: '5',\n 102: '6',\n 103: '7',\n 104: '8',\n 105: '9',\n 106: '*',\n 107: '+',\n 109: '-', // The 'NumpadSubtract' code\n 110: '.',\n 111: '/',\n 112: 'F1',\n 113: 'F2',\n 114: 'F3',\n 115: 'F4',\n 116: 'F5',\n 117: 'F6',\n 118: 'F7',\n 119: 'F8',\n 120: 'F9',\n 121: 'F10',\n 122: 'F11',\n 123: 'F12',\n 144: 'NumLock',\n 145: 'ScrollLock',\n 173: '-', // The 'Minus' sign on Firefox. This is only needed when using the Selenium bot though.\n 182: 'MyComputer',\n 183: 'MyCalculator',\n 186: ';',\n 187: '=',\n 188: ',',\n 189: '-', // The 'Minus' sign on all other browsers\n 190: '.',\n 191: '/',\n 192: '`',\n 219: '[',\n 220: '\\\\',\n 221: ']',\n 222: '\\'',\n 224: 'Meta',\n 225: 'AltGraph'\n };\n },\n\n /**\n * Wrapper variable that hold named keyboard keys with their respective key name (as set in KeyboardEvent.key).\n * Those names are listed here :\n * @link https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values\n */\n get keyName() {\n return {\n // Special values\n Unidentified: 'Unidentified',\n AndroidDefault: 'AndroidDefault',\n\n // Modifier keys\n Alt: 'Alt',\n AltGr: 'AltGraph',\n CapsLock: 'CapsLock', // Under Chrome, e.key is empty for CapsLock\n Ctrl: 'Control',\n Fn: 'Fn',\n FnLock: 'FnLock',\n Hyper: 'Hyper', // 'OS' under Firefox\n Meta: 'Meta',\n OSLeft: 'OS',\n OSRight: 'OS',\n Command: 'OS',\n NumLock: 'NumLock',\n ScrollLock: 'ScrollLock',\n Shift: 'Shift',\n Super: 'Super', // 'OS' under Firefox\n Symbol: 'Symbol',\n SymbolLock: 'SymbolLock',\n\n // Whitespace keys\n Enter: 'Enter',\n Tab: 'Tab',\n Space: ' ', // 'Spacebar' for Firefox <37, and IE9\n\n // Navigation keys\n LeftArrow: 'ArrowLeft', // 'Left' for Firefox <=36, and IE9\n UpArrow: 'ArrowUp', // 'Up' for Firefox <=36, and IE9\n RightArrow: 'ArrowRight', // 'Right' for Firefox <=36, and IE9\n DownArrow: 'ArrowDown', // 'Down' for Firefox <=36, and IE9\n End: 'End',\n Home: 'Home',\n PageUp: 'PageUp',\n PageDown: 'PageDown',\n\n // Editing keys\n Backspace: 'Backspace',\n Clear: 'Clear',\n Copy: 'Copy',\n CrSel: 'CrSel', // 'Crsel' for Firefox <=36, and IE9\n Cut: 'Cut',\n Delete: 'Delete', // 'Del' for Firefox <=36, and IE9\n EraseEof: 'EraseEof',\n ExSel: 'ExSel', // 'Exsel' for Firefox <=36, and IE9\n Insert: 'Insert',\n Paste: 'Paste',\n Redo: 'Redo',\n Undo: 'Undo',\n\n // UI keys\n Accept: 'Accept',\n Again: 'Again',\n Attn: 'Attn', // 'Unidentified' for Firefox, Chrome, and IE9 ('KanaMode' when using the Japanese keyboard layout)\n Cancel: 'Cancel',\n ContextMenu: 'ContextMenu', // 'Apps' for Firefox <=36, and IE9\n Esc: 'Escape', // 'Esc' for Firefox <=36, and IE9\n Execute: 'Execute',\n Find: 'Find',\n Finish: 'Finish', // 'Unidentified' for Firefox, Chrome, and IE9 ('Katakana' when using the Japanese keyboard layout)\n Help: 'Help',\n Pause: 'Pause',\n Play: 'Play',\n Props: 'Props',\n Select: 'Select',\n ZoomIn: 'ZoomIn',\n ZoomOut: 'ZoomOut',\n\n // Device keys\n BrightnessDown: 'BrightnessDown',\n BrightnessUp: 'BrightnessUp',\n Eject: 'Eject',\n LogOff: 'LogOff',\n Power: 'Power',\n PowerOff: 'PowerOff',\n PrintScreen: 'PrintScreen',\n Hibernate: 'Hibernate', // 'Unidentified' for Firefox <=37\n Standby: 'Standby', // 'Unidentified' for Firefox <=36, and IE9\n WakeUp: 'WakeUp',\n\n // IME and composition keys\n Compose: 'Compose',\n Dead: 'Dead',\n\n // Function keys\n F1: 'F1',\n F2: 'F2',\n F3: 'F3',\n F4: 'F4',\n F5: 'F5',\n F6: 'F6',\n F7: 'F7',\n F8: 'F8',\n F9: 'F9',\n F10: 'F10',\n F11: 'F11',\n F12: 'F12',\n\n // Document keys\n Print: 'Print',\n\n // 'Normal' keys\n num0: '0',\n num1: '1',\n num2: '2',\n num3: '3',\n num4: '4',\n num5: '5',\n num6: '6',\n num7: '7',\n num8: '8',\n num9: '9',\n a: 'a',\n b: 'b',\n c: 'c',\n d: 'd',\n e: 'e',\n f: 'f',\n g: 'g',\n h: 'h',\n i: 'i',\n j: 'j',\n k: 'k',\n l: 'l',\n m: 'm',\n n: 'n',\n o: 'o',\n p: 'p',\n q: 'q',\n r: 'r',\n s: 's',\n t: 't',\n u: 'u',\n v: 'v',\n w: 'w',\n x: 'x',\n y: 'y',\n z: 'z',\n A: 'A',\n B: 'B',\n C: 'C',\n D: 'D',\n E: 'E',\n F: 'F',\n G: 'G',\n H: 'H',\n I: 'I',\n J: 'J',\n K: 'K',\n L: 'L',\n M: 'M',\n N: 'N',\n O: 'O',\n P: 'P',\n Q: 'Q',\n R: 'R',\n S: 'S',\n T: 'T',\n U: 'U',\n V: 'V',\n W: 'W',\n X: 'X',\n Y: 'Y',\n Z: 'Z',\n Semicolon: ';',\n Equal: '=',\n Comma: ',',\n Hyphen: '-',\n Minus: '-',\n Plus: '+',\n Dot: '.',\n Slash: '/',\n Backquote: '`',\n LeftBracket: '[',\n RightBracket: ']',\n Backslash: '\\\\',\n Quote: '\\'',\n\n // Numeric keypad keys\n numpad0: '0',\n numpad1: '1',\n numpad2: '2',\n numpad3: '3',\n numpad4: '4',\n numpad5: '5',\n numpad6: '6',\n numpad7: '7',\n numpad8: '8',\n numpad9: '9',\n NumpadDot: '.',\n NumpadDotAlt: ',', // Modern browsers automatically adapt the character sent by this key to the decimal character of the current language\n NumpadMultiply: '*',\n NumpadPlus: '+',\n NumpadMinus: '-',\n NumpadSubtract: '-',\n NumpadSlash: '/',\n NumpadDotObsoleteBrowsers: 'Decimal',\n NumpadMultiplyObsoleteBrowsers: 'Multiply',\n NumpadPlusObsoleteBrowsers: 'Add',\n NumpadMinusObsoleteBrowsers: 'Subtract',\n NumpadSlashObsoleteBrowsers: 'Divide',\n\n // Special arrays for quicker tests\n _allFnKeys: ['F1', 'F2', 'F3', 'F4', 'F5', 'F6', 'F7', 'F8', 'F9', 'F10', 'F11', 'F12'],\n _someNonPrintableKeys: ['Tab', 'Enter', 'Shift', 'ShiftLeft', 'ShiftRight', 'Control', 'ControlLeft', 'ControlRight', 'Alt', 'AltLeft', 'AltRight', 'Pause', 'CapsLock', 'Escape'],\n _directionKeys: ['PageUp', 'PageDown', 'End', 'Home', 'ArrowDown', 'ArrowLeft', 'ArrowRight', 'ArrowUp']\n };\n }\n};\n\nexports.default = AutoNumericEnum;\nmodule.exports = exports['default'];\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWNFbnVtLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vQXV0b051bWVyaWMvc3JjL0F1dG9OdW1lcmljRW51bS5qcz8xNTA2Il0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRW51bWVyYXRpb25zIGZvciBhdXRvTnVtZXJpYy5qc1xuICogQGF1dGhvciBBbGV4YW5kcmUgQm9ubmVhdSA8YWxleGFuZHJlLmJvbm5lYXVAbGludXhmci5ldT5cbiAqIEBjb3B5cmlnaHQgwqkgMjAxNiBBbGV4YW5kcmUgQm9ubmVhdVxuICpcbiAqIFRoZSBNSVQgTGljZW5zZSAoaHR0cDovL3d3dy5vcGVuc291cmNlLm9yZy9saWNlbnNlcy9taXQtbGljZW5zZS5waHApXG4gKlxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb25cbiAqIG9idGFpbmluZyBhIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uXG4gKiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXRcbiAqIHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLFxuICogY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3ViIGxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gKiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGVcbiAqIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nXG4gKiBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlXG4gKiBpbmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELFxuICogRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTXG4gKiBPRiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORFxuICogTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFRcbiAqIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLFxuICogV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HXG4gKiBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SXG4gKiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG4gKi9cblxuLyoqXG4gKiBPYmplY3QgdGhhdCBzdG9yZSB0aGUgaGVscGVyIGVudW1lcmF0aW9uc1xuICogQHR5cGUge3sgYWxsb3dlZFRhZ0xpc3Q6IFtzdHJpbmddLCBrZXlDb2RlOiB7fSwgZnJvbUNoYXJDb2RlS2V5Q29kZTogW3N0cmluZ10sIGtleU5hbWU6IHt9IH19XG4gKi9cbmNvbnN0IEF1dG9OdW1lcmljRW51bSA9IHtcbiAgICAvKipcbiAgICAgKiBMaXN0IG9mIGFsbG93ZWQgdGFnIG9uIHdoaWNoIGF1dG9OdW1lcmljIGNhbiBiZSB1c2VkLlxuICAgICAqL1xuICAgIGdldCBhbGxvd2VkVGFnTGlzdCgpIHtcbiAgICAgICAgcmV0dXJuIFtcbiAgICAgICAgICAgICdiJyxcbiAgICAgICAgICAgICdjYXB0aW9uJyxcbiAgICAgICAgICAgICdjaXRlJyxcbiAgICAgICAgICAgICdjb2RlJyxcbiAgICAgICAgICAgICdjb25zdCcsXG4gICAgICAgICAgICAnZGQnLFxuICAgICAgICAgICAgJ2RlbCcsXG4gICAgICAgICAgICAnZGl2JyxcbiAgICAgICAgICAgICdkZm4nLFxuICAgICAgICAgICAgJ2R0JyxcbiAgICAgICAgICAgICdlbScsXG4gICAgICAgICAgICAnaDEnLFxuICAgICAgICAgICAgJ2gyJyxcbiAgICAgICAgICAgICdoMycsXG4gICAgICAgICAgICAnaDQnLFxuICAgICAgICAgICAgJ2g1JyxcbiAgICAgICAgICAgICdoNicsXG4gICAgICAgICAgICAnaW5wdXQnLFxuICAgICAgICAgICAgJ2lucycsXG4gICAgICAgICAgICAna2RiJyxcbiAgICAgICAgICAgICdsYWJlbCcsXG4gICAgICAgICAgICAnbGknLFxuICAgICAgICAgICAgJ29wdGlvbicsXG4gICAgICAgICAgICAnb3V0cHV0JyxcbiAgICAgICAgICAgICdwJyxcbiAgICAgICAgICAgICdxJyxcbiAgICAgICAgICAgICdzJyxcbiAgICAgICAgICAgICdzYW1wbGUnLFxuICAgICAgICAgICAgJ3NwYW4nLFxuICAgICAgICAgICAgJ3N0cm9uZycsXG4gICAgICAgICAgICAndGQnLFxuICAgICAgICAgICAgJ3RoJyxcbiAgICAgICAgICAgICd1JyxcbiAgICAgICAgXTtcbiAgICB9LFxuXG4gICAgLyoqXG4gICAgICogV3JhcHBlciB2YXJpYWJsZSB0aGF0IGhvbGQgbmFtZWQga2V5Ym9hcmQga2V5cyB3aXRoIHRoZWlyIHJlc3BlY3RpdmUga2V5Q29kZSBhcyBzZWVuIGluIERPTSBldmVudHMuXG4gICAgICogY2YuIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9LZXlib2FyZEV2ZW50L2tleUNvZGVcbiAgICAgKlxuICAgICAqIFRoaXMgZGVwcmVjYXRlZCBpbmZvcm1hdGlvbiBpcyB1c2VkIGZvciBvYnNvbGV0ZSBicm93c2Vycy5cbiAgICAgKiBAZGVwcmVjYXRlZFxuICAgICAqL1xuICAgIGdldCBrZXlDb2RlKCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgQmFja3NwYWNlICAgICA6IDgsXG4gICAgICAgICAgICBUYWIgICAgICAgICAgIDogOSxcbiAgICAgICAgICAgIC8vIE5vIDEwLCAxMVxuICAgICAgICAgICAgLy8gMTIgPT09IE51bXBhZEVxdWFsIG9uIFdpbmRvd3NcbiAgICAgICAgICAgIC8vIDEyID09PSBOdW1Mb2NrIG9uIE1hY1xuICAgICAgICAgICAgRW50ZXIgICAgICAgICA6IDEzLFxuICAgICAgICAgICAgLy8gMTQgcmVzZXJ2ZWQsIGJ1dCBub3QgdXNlZFxuICAgICAgICAgICAgLy8gMTUgZG9lcyBub3QgZXhpc3RzXG4gICAgICAgICAgICBTaGlmdCAgICAgICAgIDogMTYsXG4gICAgICAgICAgICBDdHJsICAgICAgICAgIDogMTcsXG4gICAgICAgICAgICBBbHQgICAgICAgICAgIDogMTgsXG4gICAgICAgICAgICBQYXVzZSAgICAgICAgIDogMTksXG4gICAgICAgICAgICBDYXBzTG9jayAgICAgIDogMjAsXG4gICAgICAgICAgICAvLyAyMSwgMjIsIDIzLCAyNCwgMjUgOiBBc2lhdGljIGtleSBjb2Rlc1xuICAgICAgICAgICAgLy8gMjYgZG9lcyBub3QgZXhpc3RzXG4gICAgICAgICAgICBFc2MgICAgICAgICAgIDogMjcsXG4gICAgICAgICAgICAvLyAyOCwgMjksIDMwLCAzMSA6IENvbnZlcnQsIE5vbkNvbnZlcnQsIEFjY2VwdCBhbmQgTW9kZUNoYW5nZSBrZXlzXG4gICAgICAgICAgICBTcGFjZSAgICAgICAgIDogMzIsXG4gICAgICAgICAgICBQYWdlVXAgICAgICAgIDogMzMsXG4gICAgICAgICAgICBQYWdlRG93biAgICAgIDogMzQsXG4gICAgICAgICAgICBFbmQgICAgICAgICAgIDogMzUsXG4gICAgICAgICAgICBIb21lICAgICAgICAgIDogMzYsXG4gICAgICAgICAgICBMZWZ0QXJyb3cgICAgIDogMzcsXG4gICAgICAgICAgICBVcEFycm93ICAgICAgIDogMzgsXG4gICAgICAgICAgICBSaWdodEFycm93ICAgIDogMzksXG4gICAgICAgICAgICBEb3duQXJyb3cgICAgIDogNDAsXG4gICAgICAgICAgICBJbnNlcnQgICAgICAgIDogNDUsXG4gICAgICAgICAgICBEZWxldGUgICAgICAgIDogNDYsXG4gICAgICAgICAgICBudW0wICAgICAgICAgIDogNDgsXG4gICAgICAgICAgICBudW0xICAgICAgICAgIDogNDksXG4gICAgICAgICAgICBudW0yICAgICAgICAgIDogNTAsXG4gICAgICAgICAgICBudW0zICAgICAgICAgIDogNTEsXG4gICAgICAgICAgICBudW00ICAgICAgICAgIDogNTIsXG4gICAgICAgICAgICBudW01ICAgICAgICAgIDogNTMsXG4gICAgICAgICAgICBudW02ICAgICAgICAgIDogNTQsXG4gICAgICAgICAgICBudW03ICAgICAgICAgIDogNTUsXG4gICAgICAgICAgICBudW04ICAgICAgICAgIDogNTYsXG4gICAgICAgICAgICBudW05ICAgICAgICAgIDogNTcsXG4gICAgICAgICAgICBhICAgICAgICAgICAgIDogNjUsXG4gICAgICAgICAgICBiICAgICAgICAgICAgIDogNjYsXG4gICAgICAgICAgICBjICAgICAgICAgICAgIDogNjcsXG4gICAgICAgICAgICBkICAgICAgICAgICAgIDogNjgsXG4gICAgICAgICAgICBlICAgICAgICAgICAgIDogNjksXG4gICAgICAgICAgICBmICAgICAgICAgICAgIDogNzAsXG4gICAgICAgICAgICBnICAgICAgICAgICAgIDogNzEsXG4gICAgICAgICAgICBoICAgICAgICAgICAgIDogNzIsXG4gICAgICAgICAgICBpICAgICAgICAgICAgIDogNzMsXG4gICAgICAgICAgICBqICAgICAgICAgICAgIDogNzQsXG4gICAgICAgICAgICBrICAgICAgICAgICAgIDogNzUsXG4gICAgICAgICAgICBsICAgICAgICAgICAgIDogNzYsXG4gICAgICAgICAgICBtICAgICAgICAgICAgIDogNzcsXG4gICAgICAgICAgICBuICAgICAgICAgICAgIDogNzgsXG4gICAgICAgICAgICBvICAgICAgICAgICAgIDogNzksXG4gICAgICAgICAgICBwICAgICAgICAgICAgIDogODAsXG4gICAgICAgICAgICBxICAgICAgICAgICAgIDogODEsXG4gICAgICAgICAgICByICAgICAgICAgICAgIDogODIsXG4gICAgICAgICAgICBzICAgICAgICAgICAgIDogODMsXG4gICAgICAgICAgICB0ICAgICAgICAgICAgIDogODQsXG4gICAgICAgICAgICB1ICAgICAgICAgICAgIDogODUsXG4gICAgICAgICAgICB2ICAgICAgICAgICAgIDogODYsXG4gICAgICAgICAgICB3ICAgICAgICAgICAgIDogODcsXG4gICAgICAgICAgICB4ICAgICAgICAgICAgIDogODgsXG4gICAgICAgICAgICB5ICAgICAgICAgICAgIDogODksXG4gICAgICAgICAgICB6ICAgICAgICAgICAgIDogOTAsXG4gICAgICAgICAgICBPU0xlZnQgICAgICAgIDogOTEsXG4gICAgICAgICAgICBPU1JpZ2h0ICAgICAgIDogOTIsXG4gICAgICAgICAgICBDb250ZXh0TWVudSAgIDogOTMsXG4gICAgICAgICAgICBudW1wYWQwICAgICAgIDogOTYsXG4gICAgICAgICAgICBudW1wYWQxICAgICAgIDogOTcsXG4gICAgICAgICAgICBudW1wYWQyICAgICAgIDogOTgsXG4gICAgICAgICAgICBudW1wYWQzICAgICAgIDogOTksXG4gICAgICAgICAgICBudW1wYWQ0ICAgICAgIDogMTAwLFxuICAgICAgICAgICAgbnVtcGFkNSAgICAgICA6IDEwMSxcbiAgICAgICAgICAgIG51bXBhZDYgICAgICAgOiAxMDIsXG4gICAgICAgICAgICBudW1wYWQ3ICAgICAgIDogMTAzLFxuICAgICAgICAgICAgbnVtcGFkOCAgICAgICA6IDEwNCxcbiAgICAgICAgICAgIG51bXBhZDkgICAgICAgOiAxMDUsXG4gICAgICAgICAgICBNdWx0aXBseU51bXBhZDogMTA2LFxuICAgICAgICAgICAgUGx1c051bXBhZCAgICA6IDEwNyxcbiAgICAgICAgICAgIE1pbnVzTnVtcGFkICAgOiAxMDksXG4gICAgICAgICAgICBEb3ROdW1wYWQgICAgIDogMTEwLFxuICAgICAgICAgICAgU2xhc2hOdW1wYWQgICA6IDExMSxcbiAgICAgICAgICAgIEYxICAgICAgICAgICAgOiAxMTIsXG4gICAgICAgICAgICBGMiAgICAgICAgICAgIDogMTEzLFxuICAgICAgICAgICAgRjMgICAgICAgICAgICA6IDExNCxcbiAgICAgICAgICAgIEY0ICAgICAgICAgICAgOiAxMTUsXG4gICAgICAgICAgICBGNSAgICAgICAgICAgIDogMTE2LFxuICAgICAgICAgICAgRjYgICAgICAgICAgICA6IDExNyxcbiAgICAgICAgICAgIEY3ICAgICAgICAgICAgOiAxMTgsXG4gICAgICAgICAgICBGOCAgICAgICAgICAgIDogMTE5LFxuICAgICAgICAgICAgRjkgICAgICAgICAgICA6IDEyMCxcbiAgICAgICAgICAgIEYxMCAgICAgICAgICAgOiAxMjEsXG4gICAgICAgICAgICBGMTEgICAgICAgICAgIDogMTIyLFxuICAgICAgICAgICAgRjEyICAgICAgICAgICA6IDEyMyxcbiAgICAgICAgICAgIE51bUxvY2sgICAgICAgOiAxNDQsXG4gICAgICAgICAgICBTY3JvbGxMb2NrICAgIDogMTQ1LFxuICAgICAgICAgICAgSHlwaGVuRmlyZWZveCA6IDE3MywgLy8gT24gdGhlIGxhdGVzdCBMaW51eCBhbmQgV2luZG93cyBPUywgY2YuIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9LZXlib2FyZEV2ZW50L2tleUNvZGUgYW5kIGh0dHBzOi8vYnVnemlsbGEubW96aWxsYS5vcmcvc2hvd19idWcuY2dpP2lkPTc4NzUwNCBhbmQgaHR0cHM6Ly9zdGFja292ZXJmbG93LmNvbS9hLzM1NDczMjU5LzI4MzQ4OThcbiAgICAgICAgICAgIE15Q29tcHV0ZXIgICAgOiAxODIsXG4gICAgICAgICAgICBNeUNhbGN1bGF0b3IgIDogMTgzLFxuICAgICAgICAgICAgU2VtaWNvbG9uICAgICA6IDE4NixcbiAgICAgICAgICAgIEVxdWFsICAgICAgICAgOiAxODcsXG4gICAgICAgICAgICBDb21tYSAgICAgICAgIDogMTg4LFxuICAgICAgICAgICAgSHlwaGVuICAgICAgICA6IDE4OSxcbiAgICAgICAgICAgIERvdCAgICAgICAgICAgOiAxOTAsXG4gICAgICAgICAgICBTbGFzaCAgICAgICAgIDogMTkxLFxuICAgICAgICAgICAgQmFja3F1b3RlICAgICA6IDE5MixcbiAgICAgICAgICAgIExlZnRCcmFja2V0ICAgOiAyMTksXG4gICAgICAgICAgICBCYWNrc2xhc2ggICAgIDogMjIwLFxuICAgICAgICAgICAgUmlnaHRCcmFja2V0ICA6IDIyMSxcbiAgICAgICAgICAgIFF1b3RlICAgICAgICAgOiAyMjIsXG4gICAgICAgICAgICBDb21tYW5kICAgICAgIDogMjI0LFxuICAgICAgICAgICAgQWx0R3JhcGggICAgICA6IDIyNSxcbiAgICAgICAgICAgIEFuZHJvaWREZWZhdWx0OiAyMjksIC8vIEFuZHJvaWQgQ2hyb21lIHJldHVybnMgdGhlIHNhbWUga2V5Y29kZSBudW1iZXIgMjI5IGZvciBhbGwga2V5cyBwcmVzc2VkXG4gICAgICAgIH07XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFRoaXMgb2JqZWN0IGlzIHRoZSByZXZlcnNlIG9mIGBrZXlDb2RlYCwgYW5kIGlzIHVzZWQgdG8gdHJhbnNsYXRlIHRoZSBrZXkgY29kZSB0byBuYW1lZCBrZXlzIHdoZW4gbm8gdmFsaWQgY2hhcmFjdGVycyBjYW4gYmUgb2J0YWluZWQgYnkgYFN0cmluZy5mcm9tQ2hhckNvZGVgLlxuICAgICAqIFRoaXMgb2JqZWN0IGtleXMgY29ycmVzcG9uZCB0byB0aGUgYGV2ZW50LmtleUNvZGVgIG51bWJlciwgYW5kIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcga2V5IG5hbWUgKMOgIGxhIGV2ZW50LmtleSlcbiAgICAgKi9cbiAgICBnZXQgZnJvbUNoYXJDb2RlS2V5Q29kZSgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIDAgIDogJ0xhdW5jaENhbGN1bGF0b3InLFxuICAgICAgICAgICAgOCAgOiAnQmFja3NwYWNlJyxcbiAgICAgICAgICAgIDkgIDogJ1RhYicsXG4gICAgICAgICAgICAxMyA6ICdFbnRlcicsXG4gICAgICAgICAgICAxNiA6ICdTaGlmdCcsXG4gICAgICAgICAgICAxNyA6ICdDdHJsJyxcbiAgICAgICAgICAgIDE4IDogJ0FsdCcsXG4gICAgICAgICAgICAxOSA6ICdQYXVzZScsXG4gICAgICAgICAgICAyMCA6ICdDYXBzTG9jaycsXG4gICAgICAgICAgICAyNyA6ICdFc2NhcGUnLFxuICAgICAgICAgICAgMzIgOiAnICcsXG4gICAgICAgICAgICAzMyA6ICdQYWdlVXAnLFxuICAgICAgICAgICAgMzQgOiAnUGFnZURvd24nLFxuICAgICAgICAgICAgMzUgOiAnRW5kJyxcbiAgICAgICAgICAgIDM2IDogJ0hvbWUnLFxuICAgICAgICAgICAgMzcgOiAnQXJyb3dMZWZ0JyxcbiAgICAgICAgICAgIDM4IDogJ0Fycm93VXAnLFxuICAgICAgICAgICAgMzkgOiAnQXJyb3dSaWdodCcsXG4gICAgICAgICAgICA0MCA6ICdBcnJvd0Rvd24nLFxuICAgICAgICAgICAgNDUgOiAnSW5zZXJ0JyxcbiAgICAgICAgICAgIDQ2IDogJ0RlbGV0ZScsXG4gICAgICAgICAgICA0OCA6ICcwJyxcbiAgICAgICAgICAgIDQ5IDogJzEnLFxuICAgICAgICAgICAgNTAgOiAnMicsXG4gICAgICAgICAgICA1MSA6ICczJyxcbiAgICAgICAgICAgIDUyIDogJzQnLFxuICAgICAgICAgICAgNTMgOiAnNScsXG4gICAgICAgICAgICA1NCA6ICc2JyxcbiAgICAgICAgICAgIDU1IDogJzcnLFxuICAgICAgICAgICAgNTYgOiAnOCcsXG4gICAgICAgICAgICA1NyA6ICc5JyxcbiAgICAgICAgICAgIC8vIDY1OiAnYScsXG4gICAgICAgICAgICAvLyA2NjogJ2InLFxuICAgICAgICAgICAgLy8gNjc6ICdjJyxcbiAgICAgICAgICAgIC8vIDY4OiAnZCcsXG4gICAgICAgICAgICAvLyA2OTogJ2UnLFxuICAgICAgICAgICAgLy8gNzA6ICdmJyxcbiAgICAgICAgICAgIC8vIDcxOiAnZycsXG4gICAgICAgICAgICAvLyA3MjogJ2gnLFxuICAgICAgICAgICAgLy8gNzM6ICdpJyxcbiAgICAgICAgICAgIC8vIDc0OiAnaicsXG4gICAgICAgICAgICAvLyA3NTogJ2snLFxuICAgICAgICAgICAgLy8gNzY6ICdsJyxcbiAgICAgICAgICAgIC8vIDc3OiAnbScsXG4gICAgICAgICAgICAvLyA3ODogJ24nLFxuICAgICAgICAgICAgLy8gNzk6ICdvJyxcbiAgICAgICAgICAgIC8vIDgwOiAncCcsXG4gICAgICAgICAgICAvLyA4MTogJ3EnLFxuICAgICAgICAgICAgLy8gODI6ICdyJyxcbiAgICAgICAgICAgIC8vIDgzOiAncycsXG4gICAgICAgICAgICAvLyA4NDogJ3QnLFxuICAgICAgICAgICAgLy8gODU6ICd1JyxcbiAgICAgICAgICAgIC8vIDg2OiAndicsXG4gICAgICAgICAgICAvLyA4NzogJ3cnLFxuICAgICAgICAgICAgLy8gODg6ICd4JyxcbiAgICAgICAgICAgIC8vIDg5OiAneScsXG4gICAgICAgICAgICAvLyA5MDogJ3onLFxuICAgICAgICAgICAgOTEgOiAnT1MnLCAvLyBOb3RlOiBGaXJlZm94IGFuZCBDaHJvbWUgcmVwb3J0cyAnT1MnIGluc3RlYWQgb2YgJ09TTGVmdCdcbiAgICAgICAgICAgIDkyIDogJ09TUmlnaHQnLFxuICAgICAgICAgICAgOTMgOiAnQ29udGV4dE1lbnUnLFxuICAgICAgICAgICAgOTYgOiAnMCcsXG4gICAgICAgICAgICA5NyA6ICcxJyxcbiAgICAgICAgICAgIDk4IDogJzInLFxuICAgICAgICAgICAgOTkgOiAnMycsXG4gICAgICAgICAgICAxMDA6ICc0JyxcbiAgICAgICAgICAgIDEwMTogJzUnLFxuICAgICAgICAgICAgMTAyOiAnNicsXG4gICAgICAgICAgICAxMDM6ICc3JyxcbiAgICAgICAgICAgIDEwNDogJzgnLFxuICAgICAgICAgICAgMTA1OiAnOScsXG4gICAgICAgICAgICAxMDY6ICcqJyxcbiAgICAgICAgICAgIDEwNzogJysnLFxuICAgICAgICAgICAgMTA5OiAnLScsIC8vIFRoZSAnTnVtcGFkU3VidHJhY3QnIGNvZGVcbiAgICAgICAgICAgIDExMDogJy4nLFxuICAgICAgICAgICAgMTExOiAnLycsXG4gICAgICAgICAgICAxMTI6ICdGMScsXG4gICAgICAgICAgICAxMTM6ICdGMicsXG4gICAgICAgICAgICAxMTQ6ICdGMycsXG4gICAgICAgICAgICAxMTU6ICdGNCcsXG4gICAgICAgICAgICAxMTY6ICdGNScsXG4gICAgICAgICAgICAxMTc6ICdGNicsXG4gICAgICAgICAgICAxMTg6ICdGNycsXG4gICAgICAgICAgICAxMTk6ICdGOCcsXG4gICAgICAgICAgICAxMjA6ICdGOScsXG4gICAgICAgICAgICAxMjE6ICdGMTAnLFxuICAgICAgICAgICAgMTIyOiAnRjExJyxcbiAgICAgICAgICAgIDEyMzogJ0YxMicsXG4gICAgICAgICAgICAxNDQ6ICdOdW1Mb2NrJyxcbiAgICAgICAgICAgIDE0NTogJ1Njcm9sbExvY2snLFxuICAgICAgICAgICAgMTczOiAnLScsIC8vIFRoZSAnTWludXMnIHNpZ24gb24gRmlyZWZveC4gVGhpcyBpcyBvbmx5IG5lZWRlZCB3aGVuIHVzaW5nIHRoZSBTZWxlbml1bSBib3QgdGhvdWdoLlxuICAgICAgICAgICAgMTgyOiAnTXlDb21wdXRlcicsXG4gICAgICAgICAgICAxODM6ICdNeUNhbGN1bGF0b3InLFxuICAgICAgICAgICAgMTg2OiAnOycsXG4gICAgICAgICAgICAxODc6ICc9JyxcbiAgICAgICAgICAgIDE4ODogJywnLFxuICAgICAgICAgICAgMTg5OiAnLScsIC8vIFRoZSAnTWludXMnIHNpZ24gb24gYWxsIG90aGVyIGJyb3dzZXJzXG4gICAgICAgICAgICAxOTA6ICcuJyxcbiAgICAgICAgICAgIDE5MTogJy8nLFxuICAgICAgICAgICAgMTkyOiAnYCcsXG4gICAgICAgICAgICAyMTk6ICdbJyxcbiAgICAgICAgICAgIDIyMDogJ1xcXFwnLFxuICAgICAgICAgICAgMjIxOiAnXScsXG4gICAgICAgICAgICAyMjI6ICdcXCcnLFxuICAgICAgICAgICAgMjI0OiAnTWV0YScsXG4gICAgICAgICAgICAyMjU6ICdBbHRHcmFwaCcsXG4gICAgICAgIH07XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFdyYXBwZXIgdmFyaWFibGUgdGhhdCBob2xkIG5hbWVkIGtleWJvYXJkIGtleXMgd2l0aCB0aGVpciByZXNwZWN0aXZlIGtleSBuYW1lIChhcyBzZXQgaW4gS2V5Ym9hcmRFdmVudC5rZXkpLlxuICAgICAqIFRob3NlIG5hbWVzIGFyZSBsaXN0ZWQgaGVyZSA6XG4gICAgICogQGxpbmsgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0tleWJvYXJkRXZlbnQva2V5L0tleV9WYWx1ZXNcbiAgICAgKi9cbiAgICBnZXQga2V5TmFtZSgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC8vIFNwZWNpYWwgdmFsdWVzXG4gICAgICAgICAgICBVbmlkZW50aWZpZWQgIDogJ1VuaWRlbnRpZmllZCcsXG4gICAgICAgICAgICBBbmRyb2lkRGVmYXVsdDogJ0FuZHJvaWREZWZhdWx0JyxcblxuICAgICAgICAgICAgLy8gTW9kaWZpZXIga2V5c1xuICAgICAgICAgICAgQWx0ICAgICAgIDogJ0FsdCcsXG4gICAgICAgICAgICBBbHRHciAgICAgOiAnQWx0R3JhcGgnLFxuICAgICAgICAgICAgQ2Fwc0xvY2sgIDogJ0NhcHNMb2NrJywgLy8gVW5kZXIgQ2hyb21lLCBlLmtleSBpcyBlbXB0eSBmb3IgQ2Fwc0xvY2tcbiAgICAgICAgICAgIEN0cmwgICAgICA6ICdDb250cm9sJyxcbiAgICAgICAgICAgIEZuICAgICAgICA6ICdGbicsXG4gICAgICAgICAgICBGbkxvY2sgICAgOiAnRm5Mb2NrJyxcbiAgICAgICAgICAgIEh5cGVyICAgICA6ICdIeXBlcicsIC8vICdPUycgdW5kZXIgRmlyZWZveFxuICAgICAgICAgICAgTWV0YSAgICAgIDogJ01ldGEnLFxuICAgICAgICAgICAgT1NMZWZ0ICAgIDogJ09TJyxcbiAgICAgICAgICAgIE9TUmlnaHQgICA6ICdPUycsXG4gICAgICAgICAgICBDb21tYW5kICAgOiAnT1MnLFxuICAgICAgICAgICAgTnVtTG9jayAgIDogJ051bUxvY2snLFxuICAgICAgICAgICAgU2Nyb2xsTG9jazogJ1Njcm9sbExvY2snLFxuICAgICAgICAgICAgU2hpZnQgICAgIDogJ1NoaWZ0JyxcbiAgICAgICAgICAgIFN1cGVyICAgICA6ICdTdXBlcicsIC8vICdPUycgdW5kZXIgRmlyZWZveFxuICAgICAgICAgICAgU3ltYm9sICAgIDogJ1N5bWJvbCcsXG4gICAgICAgICAgICBTeW1ib2xMb2NrOiAnU3ltYm9sTG9jaycsXG5cbiAgICAgICAgICAgIC8vIFdoaXRlc3BhY2Uga2V5c1xuICAgICAgICAgICAgRW50ZXI6ICdFbnRlcicsXG4gICAgICAgICAgICBUYWIgIDogJ1RhYicsXG4gICAgICAgICAgICBTcGFjZTogJyAnLCAvLyAnU3BhY2ViYXInIGZvciBGaXJlZm94IDwzNywgYW5kIElFOVxuXG4gICAgICAgICAgICAvLyBOYXZpZ2F0aW9uIGtleXNcbiAgICAgICAgICAgIExlZnRBcnJvdyA6ICdBcnJvd0xlZnQnLCAvLyAnTGVmdCcgZm9yIEZpcmVmb3ggPD0zNiwgYW5kIElFOVxuICAgICAgICAgICAgVXBBcnJvdyAgIDogJ0Fycm93VXAnLCAvLyAnVXAnIGZvciBGaXJlZm94IDw9MzYsIGFuZCBJRTlcbiAgICAgICAgICAgIFJpZ2h0QXJyb3c6ICdBcnJvd1JpZ2h0JywgLy8gJ1JpZ2h0JyBmb3IgRmlyZWZveCA8PTM2LCBhbmQgSUU5XG4gICAgICAgICAgICBEb3duQXJyb3cgOiAnQXJyb3dEb3duJywgLy8gJ0Rvd24nIGZvciBGaXJlZm94IDw9MzYsIGFuZCBJRTlcbiAgICAgICAgICAgIEVuZCAgICAgICA6ICdFbmQnLFxuICAgICAgICAgICAgSG9tZSAgICAgIDogJ0hvbWUnLFxuICAgICAgICAgICAgUGFnZVVwICAgIDogJ1BhZ2VVcCcsXG4gICAgICAgICAgICBQYWdlRG93biAgOiAnUGFnZURvd24nLFxuXG4gICAgICAgICAgICAvLyBFZGl0aW5nIGtleXNcbiAgICAgICAgICAgIEJhY2tzcGFjZTogJ0JhY2tzcGFjZScsXG4gICAgICAgICAgICBDbGVhciAgICA6ICdDbGVhcicsXG4gICAgICAgICAgICBDb3B5ICAgICA6ICdDb3B5JyxcbiAgICAgICAgICAgIENyU2VsICAgIDogJ0NyU2VsJywgLy8gJ0Nyc2VsJyBmb3IgRmlyZWZveCA8PTM2LCBhbmQgSUU5XG4gICAgICAgICAgICBDdXQgICAgICA6ICdDdXQnLFxuICAgICAgICAgICAgRGVsZXRlICAgOiAnRGVsZXRlJywgLy8gJ0RlbCcgZm9yIEZpcmVmb3ggPD0zNiwgYW5kIElFOVxuICAgICAgICAgICAgRXJhc2VFb2YgOiAnRXJhc2VFb2YnLFxuICAgICAgICAgICAgRXhTZWwgICAgOiAnRXhTZWwnLCAvLyAnRXhzZWwnIGZvciBGaXJlZm94IDw9MzYsIGFuZCBJRTlcbiAgICAgICAgICAgIEluc2VydCAgIDogJ0luc2VydCcsXG4gICAgICAgICAgICBQYXN0ZSAgICA6ICdQYXN0ZScsXG4gICAgICAgICAgICBSZWRvICAgICA6ICdSZWRvJyxcbiAgICAgICAgICAgIFVuZG8gICAgIDogJ1VuZG8nLFxuXG4gICAgICAgICAgICAvLyBVSSBrZXlzXG4gICAgICAgICAgICBBY2NlcHQgICAgIDogJ0FjY2VwdCcsXG4gICAgICAgICAgICBBZ2FpbiAgICAgIDogJ0FnYWluJyxcbiAgICAgICAgICAgIEF0dG4gICAgICAgOiAnQXR0bicsIC8vICdVbmlkZW50aWZpZWQnIGZvciBGaXJlZm94LCBDaHJvbWUsIGFuZCBJRTkgKCdLYW5hTW9kZScgd2hlbiB1c2luZyB0aGUgSmFwYW5lc2Uga2V5Ym9hcmQgbGF5b3V0KVxuICAgICAgICAgICAgQ2FuY2VsICAgICA6ICdDYW5jZWwnLFxuICAgICAgICAgICAgQ29udGV4dE1lbnU6ICdDb250ZXh0TWVudScsIC8vICdBcHBzJyBmb3IgRmlyZWZveCA8PTM2LCBhbmQgSUU5XG4gICAgICAgICAgICBFc2MgICAgICAgIDogJ0VzY2FwZScsIC8vICdFc2MnIGZvciBGaXJlZm94IDw9MzYsIGFuZCBJRTlcbiAgICAgICAgICAgIEV4ZWN1dGUgICAgOiAnRXhlY3V0ZScsXG4gICAgICAgICAgICBGaW5kICAgICAgIDogJ0ZpbmQnLFxuICAgICAgICAgICAgRmluaXNoICAgICA6ICdGaW5pc2gnLCAvLyAnVW5pZGVudGlmaWVkJyBmb3IgRmlyZWZveCwgQ2hyb21lLCBhbmQgSUU5ICgnS2F0YWthbmEnIHdoZW4gdXNpbmcgdGhlIEphcGFuZXNlIGtleWJvYXJkIGxheW91dClcbiAgICAgICAgICAgIEhlbHAgICAgICAgOiAnSGVscCcsXG4gICAgICAgICAgICBQYXVzZSAgICAgIDogJ1BhdXNlJyxcbiAgICAgICAgICAgIFBsYXkgICAgICAgOiAnUGxheScsXG4gICAgICAgICAgICBQcm9wcyAgICAgIDogJ1Byb3BzJyxcbiAgICAgICAgICAgIFNlbGVjdCAgICAgOiAnU2VsZWN0JyxcbiAgICAgICAgICAgIFpvb21JbiAgICAgOiAnWm9vbUluJyxcbiAgICAgICAgICAgIFpvb21PdXQgICAgOiAnWm9vbU91dCcsXG5cbiAgICAgICAgICAgIC8vIERldmljZSBrZXlzXG4gICAgICAgICAgICBCcmlnaHRuZXNzRG93bjogJ0JyaWdodG5lc3NEb3duJyxcbiAgICAgICAgICAgIEJyaWdodG5lc3NVcCAgOiAnQnJpZ2h0bmVzc1VwJyxcbiAgICAgICAgICAgIEVqZWN0ICAgICAgICAgOiAnRWplY3QnLFxuICAgICAgICAgICAgTG9nT2ZmICAgICAgICA6ICdMb2dPZmYnLFxuICAgICAgICAgICAgUG93ZXIgICAgICAgICA6ICdQb3dlcicsXG4gICAgICAgICAgICBQb3dlck9mZiAgICAgIDogJ1Bvd2VyT2ZmJyxcbiAgICAgICAgICAgIFByaW50U2NyZWVuICAgOiAnUHJpbnRTY3JlZW4nLFxuICAgICAgICAgICAgSGliZXJuYXRlICAgICA6ICdIaWJlcm5hdGUnLCAvLyAnVW5pZGVudGlmaWVkJyBmb3IgRmlyZWZveCA8PTM3XG4gICAgICAgICAgICBTdGFuZGJ5ICAgICAgIDogJ1N0YW5kYnknLCAvLyAnVW5pZGVudGlmaWVkJyBmb3IgRmlyZWZveCA8PTM2LCBhbmQgSUU5XG4gICAgICAgICAgICBXYWtlVXAgICAgICAgIDogJ1dha2VVcCcsXG5cbiAgICAgICAgICAgIC8vIElNRSBhbmQgY29tcG9zaXRpb24ga2V5c1xuICAgICAgICAgICAgQ29tcG9zZTogJ0NvbXBvc2UnLFxuICAgICAgICAgICAgRGVhZCAgIDogJ0RlYWQnLFxuXG4gICAgICAgICAgICAvLyBGdW5jdGlvbiBrZXlzXG4gICAgICAgICAgICBGMSA6ICdGMScsXG4gICAgICAgICAgICBGMiA6ICdGMicsXG4gICAgICAgICAgICBGMyA6ICdGMycsXG4gICAgICAgICAgICBGNCA6ICdGNCcsXG4gICAgICAgICAgICBGNSA6ICdGNScsXG4gICAgICAgICAgICBGNiA6ICdGNicsXG4gICAgICAgICAgICBGNyA6ICdGNycsXG4gICAgICAgICAgICBGOCA6ICdGOCcsXG4gICAgICAgICAgICBGOSA6ICdGOScsXG4gICAgICAgICAgICBGMTA6ICdGMTAnLFxuICAgICAgICAgICAgRjExOiAnRjExJyxcbiAgICAgICAgICAgIEYxMjogJ0YxMicsXG5cbiAgICAgICAgICAgIC8vIERvY3VtZW50IGtleXNcbiAgICAgICAgICAgIFByaW50OiAnUHJpbnQnLFxuXG4gICAgICAgICAgICAvLyAnTm9ybWFsJyBrZXlzXG4gICAgICAgICAgICBudW0wICAgICAgICAgOiAnMCcsXG4gICAgICAgICAgICBudW0xICAgICAgICAgOiAnMScsXG4gICAgICAgICAgICBudW0yICAgICAgICAgOiAnMicsXG4gICAgICAgICAgICBudW0zICAgICAgICAgOiAnMycsXG4gICAgICAgICAgICBudW00ICAgICAgICAgOiAnNCcsXG4gICAgICAgICAgICBudW01ICAgICAgICAgOiAnNScsXG4gICAgICAgICAgICBudW02ICAgICAgICAgOiAnNicsXG4gICAgICAgICAgICBudW03ICAgICAgICAgOiAnNycsXG4gICAgICAgICAgICBudW04ICAgICAgICAgOiAnOCcsXG4gICAgICAgICAgICBudW05ICAgICAgICAgOiAnOScsXG4gICAgICAgICAgICBhICAgICAgICAgICAgOiAnYScsXG4gICAgICAgICAgICBiICAgICAgICAgICAgOiAnYicsXG4gICAgICAgICAgICBjICAgICAgICAgICAgOiAnYycsXG4gICAgICAgICAgICBkICAgICAgICAgICAgOiAnZCcsXG4gICAgICAgICAgICBlICAgICAgICAgICAgOiAnZScsXG4gICAgICAgICAgICBmICAgICAgICAgICAgOiAnZicsXG4gICAgICAgICAgICBnICAgICAgICAgICAgOiAnZycsXG4gICAgICAgICAgICBoICAgICAgICAgICAgOiAnaCcsXG4gICAgICAgICAgICBpICAgICAgICAgICAgOiAnaScsXG4gICAgICAgICAgICBqICAgICAgICAgICAgOiAnaicsXG4gICAgICAgICAgICBrICAgICAgICAgICAgOiAnaycsXG4gICAgICAgICAgICBsICAgICAgICAgICAgOiAnbCcsXG4gICAgICAgICAgICBtICAgICAgICAgICAgOiAnbScsXG4gICAgICAgICAgICBuICAgICAgICAgICAgOiAnbicsXG4gICAgICAgICAgICBvICAgICAgICAgICAgOiAnbycsXG4gICAgICAgICAgICBwICAgICAgICAgICAgOiAncCcsXG4gICAgICAgICAgICBxICAgICAgICAgICAgOiAncScsXG4gICAgICAgICAgICByICAgICAgICAgICAgOiAncicsXG4gICAgICAgICAgICBzICAgICAgICAgICAgOiAncycsXG4gICAgICAgICAgICB0ICAgICAgICAgICAgOiAndCcsXG4gICAgICAgICAgICB1ICAgICAgICAgICAgOiAndScsXG4gICAgICAgICAgICB2ICAgICAgICAgICAgOiAndicsXG4gICAgICAgICAgICB3ICAgICAgICAgICAgOiAndycsXG4gICAgICAgICAgICB4ICAgICAgICAgICAgOiAneCcsXG4gICAgICAgICAgICB5ICAgICAgICAgICAgOiAneScsXG4gICAgICAgICAgICB6ICAgICAgICAgICAgOiAneicsXG4gICAgICAgICAgICBBICAgICAgICAgICAgOiAnQScsXG4gICAgICAgICAgICBCICAgICAgICAgICAgOiAnQicsXG4gICAgICAgICAgICBDICAgICAgICAgICAgOiAnQycsXG4gICAgICAgICAgICBEICAgICAgICAgICAgOiAnRCcsXG4gICAgICAgICAgICBFICAgICAgICAgICAgOiAnRScsXG4gICAgICAgICAgICBGICAgICAgICAgICAgOiAnRicsXG4gICAgICAgICAgICBHICAgICAgICAgICAgOiAnRycsXG4gICAgICAgICAgICBIICAgICAgICAgICAgOiAnSCcsXG4gICAgICAgICAgICBJICAgICAgICAgICAgOiAnSScsXG4gICAgICAgICAgICBKICAgICAgICAgICAgOiAnSicsXG4gICAgICAgICAgICBLICAgICAgICAgICAgOiAnSycsXG4gICAgICAgICAgICBMICAgICAgICAgICAgOiAnTCcsXG4gICAgICAgICAgICBNICAgICAgICAgICAgOiAnTScsXG4gICAgICAgICAgICBOICAgICAgICAgICAgOiAnTicsXG4gICAgICAgICAgICBPICAgICAgICAgICAgOiAnTycsXG4gICAgICAgICAgICBQICAgICAgICAgICAgOiAnUCcsXG4gICAgICAgICAgICBRICAgICAgICAgICAgOiAnUScsXG4gICAgICAgICAgICBSICAgICAgICAgICAgOiAnUicsXG4gICAgICAgICAgICBTICAgICAgICAgICAgOiAnUycsXG4gICAgICAgICAgICBUICAgICAgICAgICAgOiAnVCcsXG4gICAgICAgICAgICBVICAgICAgICAgICAgOiAnVScsXG4gICAgICAgICAgICBWICAgICAgICAgICAgOiAnVicsXG4gICAgICAgICAgICBXICAgICAgICAgICAgOiAnVycsXG4gICAgICAgICAgICBYICAgICAgICAgICAgOiAnWCcsXG4gICAgICAgICAgICBZICAgICAgICAgICAgOiAnWScsXG4gICAgICAgICAgICBaICAgICAgICAgICAgOiAnWicsXG4gICAgICAgICAgICBTZW1pY29sb24gICAgOiAnOycsXG4gICAgICAgICAgICBFcXVhbCAgICAgICAgOiAnPScsXG4gICAgICAgICAgICBDb21tYSAgICAgICAgOiAnLCcsXG4gICAgICAgICAgICBIeXBoZW4gICAgICAgOiAnLScsXG4gICAgICAgICAgICBNaW51cyAgICAgICAgOiAnLScsXG4gICAgICAgICAgICBQbHVzICAgICAgICAgOiAnKycsXG4gICAgICAgICAgICBEb3QgICAgICAgICAgOiAnLicsXG4gICAgICAgICAgICBTbGFzaCAgICAgICAgOiAnLycsXG4gICAgICAgICAgICBCYWNrcXVvdGUgICAgOiAnYCcsXG4gICAgICAgICAgICBMZWZ0QnJhY2tldCAgOiAnWycsXG4gICAgICAgICAgICBSaWdodEJyYWNrZXQgOiAnXScsXG4gICAgICAgICAgICBCYWNrc2xhc2ggICAgOiAnXFxcXCcsXG4gICAgICAgICAgICBRdW90ZSAgICAgICAgOiAnXFwnJyxcblxuICAgICAgICAgICAgLy8gTnVtZXJpYyBrZXlwYWQga2V5c1xuICAgICAgICAgICAgbnVtcGFkMCAgICAgICAgICAgICAgICAgICAgICAgOiAnMCcsXG4gICAgICAgICAgICBudW1wYWQxICAgICAgICAgICAgICAgICAgICAgICA6ICcxJyxcbiAgICAgICAgICAgIG51bXBhZDIgICAgICAgICAgICAgICAgICAgICAgIDogJzInLFxuICAgICAgICAgICAgbnVtcGFkMyAgICAgICAgICAgICAgICAgICAgICAgOiAnMycsXG4gICAgICAgICAgICBudW1wYWQ0ICAgICAgICAgICAgICAgICAgICAgICA6ICc0JyxcbiAgICAgICAgICAgIG51bXBhZDUgICAgICAgICAgICAgICAgICAgICAgIDogJzUnLFxuICAgICAgICAgICAgbnVtcGFkNiAgICAgICAgICAgICAgICAgICAgICAgOiAnNicsXG4gICAgICAgICAgICBudW1wYWQ3ICAgICAgICAgICAgICAgICAgICAgICA6ICc3JyxcbiAgICAgICAgICAgIG51bXBhZDggICAgICAgICAgICAgICAgICAgICAgIDogJzgnLFxuICAgICAgICAgICAgbnVtcGFkOSAgICAgICAgICAgICAgICAgICAgICAgOiAnOScsXG4gICAgICAgICAgICBOdW1wYWREb3QgICAgICAgICAgICAgICAgICAgICA6ICcuJyxcbiAgICAgICAgICAgIE51bXBhZERvdEFsdCAgICAgICAgICAgICAgICAgIDogJywnLCAvLyBNb2Rlcm4gYnJvd3NlcnMgYXV0b21hdGljYWxseSBhZGFwdCB0aGUgY2hhcmFjdGVyIHNlbnQgYnkgdGhpcyBrZXkgdG8gdGhlIGRlY2ltYWwgY2hhcmFjdGVyIG9mIHRoZSBjdXJyZW50IGxhbmd1YWdlXG4gICAgICAgICAgICBOdW1wYWRNdWx0aXBseSAgICAgICAgICAgICAgICA6ICcqJyxcbiAgICAgICAgICAgIE51bXBhZFBsdXMgICAgICAgICAgICAgICAgICAgIDogJysnLFxuICAgICAgICAgICAgTnVtcGFkTWludXMgICAgICAgICAgICAgICAgICAgOiAnLScsXG4gICAgICAgICAgICBOdW1wYWRTdWJ0cmFjdCAgICAgICAgICAgICAgICA6ICctJyxcbiAgICAgICAgICAgIE51bXBhZFNsYXNoICAgICAgICAgICAgICAgICAgIDogJy8nLFxuICAgICAgICAgICAgTnVtcGFkRG90T2Jzb2xldGVCcm93c2VycyAgICAgOiAnRGVjaW1hbCcsXG4gICAgICAgICAgICBOdW1wYWRNdWx0aXBseU9ic29sZXRlQnJvd3NlcnM6ICdNdWx0aXBseScsXG4gICAgICAgICAgICBOdW1wYWRQbHVzT2Jzb2xldGVCcm93c2VycyAgICA6ICdBZGQnLFxuICAgICAgICAgICAgTnVtcGFkTWludXNPYnNvbGV0ZUJyb3dzZXJzICAgOiAnU3VidHJhY3QnLFxuICAgICAgICAgICAgTnVtcGFkU2xhc2hPYnNvbGV0ZUJyb3dzZXJzICAgOiAnRGl2aWRlJyxcblxuICAgICAgICAgICAgLy8gU3BlY2lhbCBhcnJheXMgZm9yIHF1aWNrZXIgdGVzdHNcbiAgICAgICAgICAgIF9hbGxGbktleXMgICAgICAgICAgIDogWydGMScsICdGMicsICdGMycsICdGNCcsICdGNScsICdGNicsICdGNycsICdGOCcsICdGOScsICdGMTAnLCAnRjExJywgJ0YxMiddLFxuICAgICAgICAgICAgX3NvbWVOb25QcmludGFibGVLZXlzOiBbJ1RhYicsICdFbnRlcicsICdTaGlmdCcsICdTaGlmdExlZnQnLCAnU2hpZnRSaWdodCcsICdDb250cm9sJywgJ0NvbnRyb2xMZWZ0JywgJ0NvbnRyb2xSaWdodCcsICdBbHQnLCAnQWx0TGVmdCcsICdBbHRSaWdodCcsICdQYXVzZScsICdDYXBzTG9jaycsICdFc2NhcGUnXSxcbiAgICAgICAgICAgIF9kaXJlY3Rpb25LZXlzICAgICAgIDogWydQYWdlVXAnLCAnUGFnZURvd24nLCAnRW5kJywgJ0hvbWUnLCAnQXJyb3dEb3duJywgJ0Fycm93TGVmdCcsICdBcnJvd1JpZ2h0JywgJ0Fycm93VXAnXSxcbiAgICAgICAgfTtcbiAgICB9LFxufTtcblxuZXhwb3J0IGRlZmF1bHQgQXV0b051bWVyaWNFbnVtO1xuIl0sIm1hcHBpbmdzIjoiOzs7OztBQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTZCQTs7OztBQUlBO0FBQ0E7OztBQUdBO0FBQ0E7QUFtQ0E7QUFDQTtBQUNBOzs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFqSEE7QUFtSEE7QUFDQTtBQUNBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQXpHQTtBQTJHQTtBQUNBO0FBQ0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBaE5BO0FBa05BO0FBamZBO0FBQ0E7QUFtZkE7QSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/AutoNumericEnum.js\n"); /***/ }), /***/ "./src/AutoNumericEvents.js": /*!**********************************!*\ !*** ./src/AutoNumericEvents.js ***! \**********************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval("\n\nvar _AutoNumeric = __webpack_require__(/*! ./AutoNumeric */ \"./src/AutoNumeric.js\");\n\nvar _AutoNumeric2 = _interopRequireDefault(_AutoNumeric);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Event list managed by AutoNumeric\n *\n * @type {{initialized: string, formatted: string, minRangeExceeded: string, maxRangeExceeded: string, native: {input: string, change: string}}}\n */\nObject.defineProperty(_AutoNumeric2.default, 'events', {\n get: function get() {\n return {\n initialized: 'autoNumeric:initialized',\n formatted: 'autoNumeric:formatted',\n rawValueModified: 'autoNumeric:rawValueModified',\n minRangeExceeded: 'autoNumeric:minExceeded',\n maxRangeExceeded: 'autoNumeric:maxExceeded',\n native: {\n input: 'input',\n change: 'change'\n }\n };\n }\n}); /**\n * Options for autoNumeric.js\n * @author Alexandre Bonneau \n * @copyright © 2017 Alexandre Bonneau\n *\n * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sub license, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWNFdmVudHMuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9BdXRvTnVtZXJpYy9zcmMvQXV0b051bWVyaWNFdmVudHMuanM/MmViNSJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE9wdGlvbnMgZm9yIGF1dG9OdW1lcmljLmpzXG4gKiBAYXV0aG9yIEFsZXhhbmRyZSBCb25uZWF1IDxhbGV4YW5kcmUuYm9ubmVhdUBsaW51eGZyLmV1PlxuICogQGNvcHlyaWdodCDCqSAyMDE3IEFsZXhhbmRyZSBCb25uZWF1XG4gKlxuICogVGhlIE1JVCBMaWNlbnNlIChodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocClcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvblxuICogb2J0YWluaW5nIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb25cbiAqIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dFxuICogcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsXG4gKiBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWIgbGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZVxuICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmdcbiAqIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsXG4gKiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVNcbiAqIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EXG4gKiBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVFxuICogSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksXG4gKiBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1JcbiAqIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgQXV0b051bWVyaWMgZnJvbSAnLi9BdXRvTnVtZXJpYyc7XG5cbi8qKlxuICogRXZlbnQgbGlzdCBtYW5hZ2VkIGJ5IEF1dG9OdW1lcmljXG4gKlxuICogQHR5cGUge3tpbml0aWFsaXplZDogc3RyaW5nLCBmb3JtYXR0ZWQ6IHN0cmluZywgbWluUmFuZ2VFeGNlZWRlZDogc3RyaW5nLCBtYXhSYW5nZUV4Y2VlZGVkOiBzdHJpbmcsIG5hdGl2ZToge2lucHV0OiBzdHJpbmcsIGNoYW5nZTogc3RyaW5nfX19XG4gKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShBdXRvTnVtZXJpYywgJ2V2ZW50cycsIHtcbiAgICBnZXQoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBpbml0aWFsaXplZCAgICAgOiAnYXV0b051bWVyaWM6aW5pdGlhbGl6ZWQnLFxuICAgICAgICAgICAgZm9ybWF0dGVkICAgICAgIDogJ2F1dG9OdW1lcmljOmZvcm1hdHRlZCcsXG4gICAgICAgICAgICByYXdWYWx1ZU1vZGlmaWVkOiAnYXV0b051bWVyaWM6cmF3VmFsdWVNb2RpZmllZCcsXG4gICAgICAgICAgICBtaW5SYW5nZUV4Y2VlZGVkOiAnYXV0b051bWVyaWM6bWluRXhjZWVkZWQnLFxuICAgICAgICAgICAgbWF4UmFuZ2VFeGNlZWRlZDogJ2F1dG9OdW1lcmljOm1heEV4Y2VlZGVkJyxcbiAgICAgICAgICAgIG5hdGl2ZSAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICBpbnB1dCA6ICdpbnB1dCcsXG4gICAgICAgICAgICAgICAgY2hhbmdlOiAnY2hhbmdlJyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgfSxcbn0pO1xuIl0sIm1hcHBpbmdzIjoiOztBQTZCQTtBQUNBOzs7OztBQUNBOzs7OztBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFGQTtBQU5BO0FBV0E7QUFiQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0EiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./src/AutoNumericEvents.js\n"); /***/ }), /***/ "./src/AutoNumericHelper.js": /*!**********************************!*\ !*** ./src/AutoNumericHelper.js ***! \**********************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };\n\nvar _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i[\"return\"]) _i[\"return\"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError(\"Invalid attempt to destructure non-iterable instance\"); } }; }();\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); /**\n * Helper functions for autoNumeric.js\n * @author Alexandre Bonneau \n * @copyright © 2016 Alexandre Bonneau\n *\n * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sub license, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\nvar _AutoNumericEnum = __webpack_require__(/*! ./AutoNumericEnum */ \"./src/AutoNumericEnum.js\");\n\nvar _AutoNumericEnum2 = _interopRequireDefault(_AutoNumericEnum);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\nfunction _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n/**\n * Static class that holds all the helper functions autoNumeric uses.\n * Note : none of the functions in there are aware of any autoNumeric internals (which means there are no references to autoNumeric-specific info like options names or data structures).\n */\nvar AutoNumericHelper = function () {\n function AutoNumericHelper() {\n _classCallCheck(this, AutoNumericHelper);\n }\n\n _createClass(AutoNumericHelper, null, [{\n key: 'isNull',\n\n /**\n * Return `true` if the `value` is null\n *\n * @static\n * @param {*} value The value to test\n * @returns {boolean} Return `true` if the `value` is null, FALSE otherwise\n */\n value: function isNull(value) {\n return value === null;\n }\n\n /**\n * Return `true` if the `value` is undefined\n *\n * @static\n * @param {*} value The value to test\n * @returns {boolean} Return `true` if the `value` is undefined, FALSE otherwise\n */\n\n }, {\n key: 'isUndefined',\n value: function isUndefined(value) {\n return value === void 0;\n }\n\n /**\n * Return `true` if the `value` is undefined, null or empty\n *\n * @param {*} value\n * @returns {boolean}\n */\n\n }, {\n key: 'isUndefinedOrNullOrEmpty',\n value: function isUndefinedOrNullOrEmpty(value) {\n return value === null || value === void 0 || '' === value;\n }\n\n /**\n * Return `true` if the given parameter is a String\n *\n * @param {*} str\n * @returns {boolean}\n */\n\n }, {\n key: 'isString',\n value: function isString(str) {\n return typeof str === 'string' || str instanceof String;\n }\n /**\n * Return `true` if the `value` is an empty string ''\n *\n * @static\n * @param {*} value The value to test\n * @returns {boolean} Return `true` if the `value` is an empty string '', FALSE otherwise\n */\n\n }, {\n key: 'isEmptyString',\n value: function isEmptyString(value) {\n return value === '';\n }\n\n /**\n * Return `true` if the parameter is a boolean\n *\n * @static\n * @param {*} value\n * @returns {boolean}\n */\n\n }, {\n key: 'isBoolean',\n value: function isBoolean(value) {\n return typeof value === 'boolean';\n }\n\n /**\n * Return `true` if the parameter is a string 'true' or 'false'\n *\n * This function accepts any cases for those strings.\n * @param {string} value\n * @returns {boolean}\n */\n\n }, {\n key: 'isTrueOrFalseString',\n value: function isTrueOrFalseString(value) {\n var lowercaseValue = String(value).toLowerCase();\n return lowercaseValue === 'true' || lowercaseValue === 'false';\n }\n\n /**\n * Return `true` if the parameter is an object\n *\n * @param {*} reference\n * @returns {boolean}\n */\n\n }, {\n key: 'isObject',\n value: function isObject(reference) {\n return (typeof reference === 'undefined' ? 'undefined' : _typeof(reference)) === 'object' && reference !== null && !Array.isArray(reference);\n }\n\n /**\n * Return `true` if the given object is empty\n * cf. http://stackoverflow.com/questions/679915/how-do-i-test-for-an-empty-javascript-object and http://jsperf.com/empty-object-test\n *\n * @param {object} obj\n * @returns {boolean}\n */\n\n }, {\n key: 'isEmptyObj',\n value: function isEmptyObj(obj) {\n for (var prop in obj) {\n if (obj.hasOwnProperty(prop)) {\n return false;\n }\n }\n return true;\n }\n\n /**\n * Return `true` if the parameter is a real number (and not a numeric string).\n *\n * @param {*} n\n * @returns {boolean}\n */\n\n }, {\n key: 'isNumberStrict',\n value: function isNumberStrict(n) {\n return typeof n === 'number';\n }\n\n /**\n * Return `true` if the parameter is a number (or a number written as a string).\n *\n * @param {*} n\n * @returns {boolean}\n */\n\n }, {\n key: 'isNumber',\n value: function isNumber(n) {\n return !this.isArray(n) && !isNaN(parseFloat(n)) && isFinite(n);\n }\n\n /**\n * Return `true` if the parameter is a number (or a number written as a string).\n * This version also accepts Arabic and Persian numbers.\n *\n * @param {*} n\n * @returns {boolean}\n */\n\n }, {\n key: 'isNumberOrArabic',\n value: function isNumberOrArabic(n) {\n var latinConvertedNumber = this.arabicToLatinNumbers(n, false, true, true);\n return this.isNumber(latinConvertedNumber);\n }\n\n /**\n * Return `true` if the parameter is an integer (and not a float).\n *\n * @param {*} n\n * @returns {boolean}\n */\n\n }, {\n key: 'isInt',\n value: function isInt(n) {\n return typeof n === 'number' && parseFloat(n) === parseInt(n, 10) && !isNaN(n);\n }\n\n /**\n * Return `true` if the parameter is a function.\n *\n * @param {function} func\n * @returns {boolean}\n */\n\n }, {\n key: 'isFunction',\n value: function isFunction(func) {\n return typeof func === 'function';\n }\n\n /**\n * Return `true` if the current browser is the obsolete Internet Explorer 11 (IE11) one\n * cf. https://stackoverflow.com/a/21825207/2834898\n *\n * @returns {boolean}\n */\n\n }, {\n key: 'isIE11',\n value: function isIE11() {\n // noinspection JSUnresolvedVariable\n return !!window.MSInputMethodContext && !!document.documentMode;\n }\n\n /**\n * Return `true` is the string `str` contains the string `needle`\n * Note: this function does not coerce the parameters types\n *\n * @param {string} str\n * @param {string} needle\n * @returns {boolean}\n */\n\n }, {\n key: 'contains',\n value: function contains(str, needle) {\n //TODO Use `Array.prototype.includes()` when available (cf. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes)\n if (!this.isString(str) || !this.isString(needle) || str === '' || needle === '') {\n return false;\n }\n\n return str.indexOf(needle) !== -1;\n }\n\n /**\n * Return `true` if the `needle` is in the array\n *\n * @param {*} needle\n * @param {Array} array\n * @returns {boolean}\n */\n\n }, {\n key: 'isInArray',\n value: function isInArray(needle, array) {\n if (!this.isArray(array) || array === [] || this.isUndefined(needle)) {\n return false;\n }\n\n return array.indexOf(needle) !== -1;\n }\n\n /**\n * Return `true` if the parameter is an Array\n * //TODO Replace this by the default `Array.isArray()` function?\n *\n * @param {*} arr\n * @throws Error\n * @returns {*|boolean}\n */\n\n }, {\n key: 'isArray',\n value: function isArray(arr) {\n if (Object.prototype.toString.call([]) === '[object Array]') {\n // Make sure an array has a class attribute of [object Array]\n // Test passed, now check if is an Array\n return Array.isArray(arr) || (typeof arr === 'undefined' ? 'undefined' : _typeof(arr)) === 'object' && Object.prototype.toString.call(arr) === '[object Array]';\n } else {\n throw new Error('toString message changed for Object Array'); // Verify that the string returned by `toString` does not change in the future (cf. http://stackoverflow.com/a/8365215)\n }\n }\n\n /**\n * Return `true` if the parameter is a DOM element\n * cf. http://stackoverflow.com/a/4754104/2834898\n *\n * @param {*} obj\n * @returns {boolean}\n */\n\n }, {\n key: 'isElement',\n value: function isElement(obj) {\n // return !!(obj && obj.nodeName);\n // return obj && 'nodeType' in obj;\n // return obj instanceof Element || obj instanceof HTMLInputElement || obj instanceof HTMLElement;\n if (typeof Element === 'undefined') {\n // This test is needed in environnements where the Element object does not exist (ie. in web workers)\n return false;\n }\n\n return obj instanceof Element;\n }\n\n /**\n * Return `true` in the given DOM element is an .\n *\n * @param {HTMLElement|HTMLInputElement} domElement\n * @returns {boolean}\n * @private\n */\n\n }, {\n key: 'isInputElement',\n value: function isInputElement(domElement) {\n return this.isElement(domElement) && domElement.tagName.toLowerCase() === 'input';\n }\n\n /**\n * Return `true` if the parameter is a string that represents a float number, and that number has a decimal part\n *\n * @param {string} str\n * @returns {boolean}\n */\n // static hasDecimals(str) {\n // const [, decimalPart] = str.split('.');\n // return !isUndefined(decimalPart);\n // }\n\n /**\n * Return the number of decimal places if the parameter is a string that represents a float number, and that number has a decimal part.\n *\n * @param {string} str\n * @returns {int}\n */\n\n }, {\n key: 'decimalPlaces',\n value: function decimalPlaces(str) {\n var _str$split = str.split('.'),\n _str$split2 = _slicedToArray(_str$split, 2),\n decimalPart = _str$split2[1];\n\n if (!this.isUndefined(decimalPart)) {\n return decimalPart.length;\n }\n\n return 0;\n }\n\n /**\n * Return the index of the first non-zero decimal place in the given value.\n * The index starts after the decimal point, if any, and begins at '1'.\n * If no decimal places are found in the value, this function returns `0`.\n *\n * @example\n * indexFirstNonZeroDecimalPlace('0.00') -> 0\n * indexFirstNonZeroDecimalPlace('1.00') -> 0\n * indexFirstNonZeroDecimalPlace('0.12') -> 1\n * indexFirstNonZeroDecimalPlace('0.1234') -> 1\n * indexFirstNonZeroDecimalPlace('0.01234') -> 2\n * indexFirstNonZeroDecimalPlace('0.001234') -> 3\n * indexFirstNonZeroDecimalPlace('0.0001234') -> 4\n *\n * @param {number} value\n * @returns {Number|number}\n */\n\n }, {\n key: 'indexFirstNonZeroDecimalPlace',\n value: function indexFirstNonZeroDecimalPlace(value) {\n var _String$split = String(Math.abs(value)).split('.'),\n _String$split2 = _slicedToArray(_String$split, 2),\n decimalPart = _String$split2[1];\n\n if (this.isUndefined(decimalPart)) {\n return 0;\n }\n\n var result = decimalPart.lastIndexOf('0');\n if (result === -1) {\n result = 0;\n } else {\n result += 2;\n }\n\n return result;\n }\n\n /**\n * Return the code for the key used to generate the given event.\n *\n * @param {Event} event\n * @returns {string|Number}\n */\n\n }, {\n key: 'keyCodeNumber',\n value: function keyCodeNumber(event) {\n // `event.keyCode` and `event.which` are deprecated, `KeyboardEvent.key` (https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key) must be used now\n // Also, do note that Firefox generate a 'keypress' event (e.keyCode === 0) for the keys that do not print a character (ie. 'Insert', 'Delete', 'Fn' keys, 'PageUp', 'PageDown' etc.). 'Shift' on the other hand does not generate a keypress event.\n return typeof event.which === 'undefined' ? event.keyCode : event.which;\n }\n\n /**\n * Return the character from the event key code.\n * If the KeyboardEvent does not represent a printable character, then the key name is used (ie. 'Meta', 'Shift', 'F1', etc.)\n * @example character(50) => '2'\n *\n * @param {KeyboardEvent} event\n * @returns {string}\n */\n\n }, {\n key: 'character',\n value: function character(event) {\n var result = void 0;\n if (event.key === 'Unidentified' || event.key === void 0 || this.isSeleniumBot()) {\n //XXX The selenium geckodriver do not understand `event.key`, hence when using it, we need to rely on the old deprecated `keyCode` attribute, cf. upstream issue https://github.com/mozilla/geckodriver/issues/440\n // Use the old deprecated keyCode property, if the new `key` one is not supported\n var keyCode = this.keyCodeNumber(event);\n if (keyCode === _AutoNumericEnum2.default.keyCode.AndroidDefault) {\n return _AutoNumericEnum2.default.keyName.AndroidDefault;\n }\n\n var potentialResult = _AutoNumericEnum2.default.fromCharCodeKeyCode[keyCode];\n if (!AutoNumericHelper.isUndefinedOrNullOrEmpty(potentialResult)) {\n // Since `String.fromCharCode` do not return named keys for some keys ('Escape' and 'Enter' for instance), we convert the characters to the key names\n result = potentialResult;\n } else {\n result = String.fromCharCode(keyCode);\n }\n } else {\n var browser = void 0;\n switch (event.key) {\n // Manages all the special cases for obsolete browsers that return the non-standard names\n case 'Add':\n result = _AutoNumericEnum2.default.keyName.NumpadPlus;\n break;\n case 'Apps':\n result = _AutoNumericEnum2.default.keyName.ContextMenu;\n break;\n case 'Crsel':\n result = _AutoNumericEnum2.default.keyName.CrSel;\n break;\n case 'Decimal':\n result = _AutoNumericEnum2.default.keyName.NumpadDot;\n break;\n case 'Del':\n browser = this.browser();\n if (browser.name === 'firefox' && browser.version <= 36 || browser.name === 'ie' && browser.version <= 9) {\n // Special workaround for the obsolete browser IE11 which output a 'Delete' key when using the numpad 'dot' one! This fixes issue #401\n // This workaround break the usage of the 'Delete' key for Firefox <=36, and IE9, since those browser send 'Del' instead of 'Delete', therefore we only use it for those obsolete browsers\n result = _AutoNumericEnum2.default.keyName.Dot;\n } else {\n result = _AutoNumericEnum2.default.keyName.Delete;\n }\n break;\n case 'Divide':\n result = _AutoNumericEnum2.default.keyName.NumpadSlash;\n break;\n case 'Down':\n result = _AutoNumericEnum2.default.keyName.DownArrow;\n break;\n case 'Esc':\n result = _AutoNumericEnum2.default.keyName.Esc;\n break;\n case 'Exsel':\n result = _AutoNumericEnum2.default.keyName.ExSel;\n break;\n case 'Left':\n result = _AutoNumericEnum2.default.keyName.LeftArrow;\n break;\n case 'Meta':\n case 'Super':\n result = _AutoNumericEnum2.default.keyName.OSLeft;\n break;\n case 'Multiply':\n result = _AutoNumericEnum2.default.keyName.NumpadMultiply;\n break;\n case 'Right':\n result = _AutoNumericEnum2.default.keyName.RightArrow;\n break;\n case 'Spacebar':\n result = _AutoNumericEnum2.default.keyName.Space;\n break;\n case 'Subtract':\n result = _AutoNumericEnum2.default.keyName.NumpadMinus;\n break;\n case 'Up':\n result = _AutoNumericEnum2.default.keyName.UpArrow;\n break;\n default:\n // The normal case\n result = event.key;\n }\n }\n\n return result;\n }\n\n /**\n * Return an object containing the name and version of the current browser.\n * @example `browserVersion()` => { name: 'Firefox', version: '42' }\n * Based on http://stackoverflow.com/a/38080051/2834898\n *\n * @returns {{ name: string, version: string }}\n */\n\n }, {\n key: 'browser',\n value: function browser() {\n var ua = navigator.userAgent;\n var tem = void 0;\n var M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\\/))\\/?\\s*(\\d+)/i) || [];\n\n if (/trident/i.test(M[1])) {\n tem = /\\brv[ :]+(\\d+)/g.exec(ua) || [];\n return { name: 'ie', version: tem[1] || '' };\n }\n\n if (M[1] === 'Chrome') {\n tem = ua.match(/\\b(OPR|Edge)\\/(\\d+)/);\n if (tem !== null) {\n return { name: tem[1].replace('OPR', 'opera'), version: tem[2] };\n }\n }\n\n M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];\n if ((tem = ua.match(/version\\/(\\d+)/i)) !== null) {\n M.splice(1, 1, tem[1]);\n }\n\n return { name: M[0].toLowerCase(), version: M[1] };\n }\n\n /**\n * Check if the browser is controlled by Selenium.\n * Note: This only works within the geckodriver.\n * cf. http://stackoverflow.com/questions/33225947/can-a-website-detect-when-you-are-using-selenium-with-chromedriver\n *\n * @returns {boolean}\n */\n\n }, {\n key: 'isSeleniumBot',\n value: function isSeleniumBot() {\n // noinspection JSUnresolvedVariable\n return window.navigator.webdriver === true;\n }\n\n /**\n * Return `true` if the given number is negative, or if the given string contains a negative sign :\n * - everywhere in the string (by default), or\n * - on the first character only if the `checkEverywhere` parameter is set to `false`.\n *\n * @param {number|string} numberOrNumericString A Number, or a number represented by a string\n * @param {string} negativeSignCharacter The single character that represent the negative sign\n * @param {boolean} checkEverywhere If TRUE, then the negative sign is search everywhere in the numeric string (this is needed for instance if the string is '1234.56-')\n * @returns {boolean}\n */\n\n }, {\n key: 'isNegative',\n value: function isNegative(numberOrNumericString) {\n var negativeSignCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '-';\n var checkEverywhere = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n\n if (numberOrNumericString === negativeSignCharacter) {\n return true;\n }\n\n if (numberOrNumericString === '') {\n return false;\n }\n\n if (AutoNumericHelper.isNumber(numberOrNumericString)) {\n return numberOrNumericString < 0;\n }\n\n if (checkEverywhere) {\n return this.contains(numberOrNumericString, negativeSignCharacter);\n }\n\n return this.isNegativeStrict(numberOrNumericString, negativeSignCharacter);\n }\n\n /**\n * Return `true` if the given string contains a negative sign on the first character (on the far left).\n *\n * @example isNegativeStrict('1234.56') => false\n * @example isNegativeStrict('1234.56-') => false\n * @example isNegativeStrict('-1234.56') => true\n * @example isNegativeStrict('-1,234.56 €') => true\n *\n * @param {string} numericString\n * @param {string} negativeSignCharacter The single character that represent the negative sign\n * @returns {boolean}\n */\n\n }, {\n key: 'isNegativeStrict',\n value: function isNegativeStrict(numericString) {\n var negativeSignCharacter = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '-';\n\n return numericString.charAt(0) === negativeSignCharacter;\n }\n\n /**\n * Return `true` if the very first character is the opening bracket, and if the rest of the `valueString` also has the closing bracket.\n *\n * @param {string} valueString\n * @param {string} leftBracket\n * @param {string} rightBracket\n * @returns {boolean}\n */\n\n }, {\n key: 'isNegativeWithBrackets',\n value: function isNegativeWithBrackets(valueString, leftBracket, rightBracket) {\n return valueString.charAt(0) === leftBracket && this.contains(valueString, rightBracket);\n }\n\n /**\n * Return `true` if the formatted or unformatted numeric string represent the value 0 (ie. '0,00 €'), or is empty (' €').\n * This works since we test if there are any numbers from 1 to 9 in the string. If there is none, then the number is zero (or the string is empty).\n *\n * @param {string} numericString\n * @returns {boolean}\n */\n\n }, {\n key: 'isZeroOrHasNoValue',\n value: function isZeroOrHasNoValue(numericString) {\n return !/[1-9]/g.test(numericString);\n }\n\n /**\n * Return the negative version of the value (represented as a string) given as a parameter.\n * The numeric string is a valid Javascript number when typecast to a `Number`.\n *\n * @param {string} value\n * @returns {*}\n */\n\n }, {\n key: 'setRawNegativeSign',\n value: function setRawNegativeSign(value) {\n if (!this.isNegativeStrict(value, '-')) {\n return '-' + value;\n }\n\n return value;\n }\n\n /**\n * Replace the character at the position `index` in the string `string` by the character(s) `newCharacter`.\n *\n * @param {string} string\n * @param {int} index\n * @param {string} newCharacter\n * @returns {string}\n */\n\n }, {\n key: 'replaceCharAt',\n value: function replaceCharAt(string, index, newCharacter) {\n return '' + string.substr(0, index) + newCharacter + string.substr(index + newCharacter.length);\n }\n\n /**\n * Return the value clamped to the nearest minimum/maximum value, as defined in the settings.\n *\n * @param {string|number} value\n * @param {object} settings\n * @returns {number}\n */\n\n }, {\n key: 'clampToRangeLimits',\n value: function clampToRangeLimits(value, settings) {\n //XXX This function always assume `settings.minimumValue` is lower than `settings.maximumValue`\n return Math.max(settings.minimumValue, Math.min(settings.maximumValue, value));\n }\n\n /**\n * Return the number of number or dot characters on the left side of the caret, in a formatted number.\n *\n * @param {string} formattedNumberString\n * @param {int} caretPosition This must be a positive integer\n * @param {string} decimalCharacter\n * @returns {number}\n */\n\n }, {\n key: 'countNumberCharactersOnTheCaretLeftSide',\n value: function countNumberCharactersOnTheCaretLeftSide(formattedNumberString, caretPosition, decimalCharacter) {\n // Here we count the dot and report it as a number character too, since it will 'stay' in the Javascript number when unformatted\n var numberDotOrNegativeSign = new RegExp('[0-9' + decimalCharacter + '-]'); // No need to escape the decimal character here, since it's in `[]`\n\n var numberDotAndNegativeSignCount = 0;\n for (var i = 0; i < caretPosition; i++) {\n // Test if the character is a number, a dot or an hyphen. If it is, count it, otherwise ignore it\n if (numberDotOrNegativeSign.test(formattedNumberString[i])) {\n numberDotAndNegativeSignCount++;\n }\n }\n\n return numberDotAndNegativeSignCount;\n }\n\n /**\n * Walk the `formattedNumberString` from left to right, one char by one, counting the `formattedNumberStringIndex`.\n * If the char is in the `rawNumberString` (starting at index 0), then `rawNumberStringIndex++`, and continue until\n * there is no more characters in `rawNumberString`) or that `rawNumberStringIndex === caretPositionInRawValue`.\n * When you stop, the `formattedNumberStringIndex` is the position where the caret should be set.\n *\n * @example\n * 1234567|89.01 : position 7 (rawNumberString)\n * 123.456.7|89,01 : position 9 (formattedNumberString)\n *\n * @param {string} rawNumberString\n * @param {int} caretPositionInRawValue\n * @param {string} formattedNumberString\n * @param {string} decimalCharacter\n * @returns {*}\n */\n\n }, {\n key: 'findCaretPositionInFormattedNumber',\n value: function findCaretPositionInFormattedNumber(rawNumberString, caretPositionInRawValue, formattedNumberString, decimalCharacter) {\n var formattedNumberStringSize = formattedNumberString.length;\n var rawNumberStringSize = rawNumberString.length;\n\n var formattedNumberStringIndex = void 0;\n var rawNumberStringIndex = 0;\n for (formattedNumberStringIndex = 0; formattedNumberStringIndex < formattedNumberStringSize && rawNumberStringIndex < rawNumberStringSize && rawNumberStringIndex < caretPositionInRawValue; formattedNumberStringIndex++) {\n if (rawNumberString[rawNumberStringIndex] === formattedNumberString[formattedNumberStringIndex] || rawNumberString[rawNumberStringIndex] === '.' && formattedNumberString[formattedNumberStringIndex] === decimalCharacter) {\n rawNumberStringIndex++;\n }\n }\n\n return formattedNumberStringIndex;\n }\n\n /**\n * Count the number of occurrence of the given character, in the given text.\n *\n * @param {string} character\n * @param {string} text\n * @returns {number}\n */\n\n }, {\n key: 'countCharInText',\n value: function countCharInText(character, text) {\n var charCounter = 0;\n for (var i = 0; i < text.length; i++) {\n if (text[i] === character) {\n charCounter++;\n }\n }\n\n return charCounter;\n }\n\n /**\n * Return the index that can be used to set the caret position.\n * This takes into account that the position is starting at '0', not 1.\n *\n * @param {int} characterCount\n * @returns {number}\n */\n\n }, {\n key: 'convertCharacterCountToIndexPosition',\n value: function convertCharacterCountToIndexPosition(characterCount) {\n return Math.max(characterCount, characterCount - 1);\n }\n\n /**\n * Cross browser routine for getting selected range/cursor position.\n * Note: this also works with edge cases like contenteditable-enabled elements, and hidden inputs.\n *\n * @param {HTMLInputElement|EventTarget} element\n * @returns {{}}\n */\n\n }, {\n key: 'getElementSelection',\n value: function getElementSelection(element) {\n var position = {};\n\n var isSelectionStartUndefined = void 0;\n try {\n isSelectionStartUndefined = this.isUndefined(element.selectionStart);\n } catch (error) {\n isSelectionStartUndefined = false;\n }\n\n try {\n if (isSelectionStartUndefined) {\n var selection = window.getSelection();\n var selectionInfo = selection.getRangeAt(0);\n position.start = selectionInfo.startOffset;\n position.end = selectionInfo.endOffset;\n position.length = position.end - position.start;\n } else {\n position.start = element.selectionStart;\n position.end = element.selectionEnd;\n position.length = position.end - position.start;\n }\n } catch (error) {\n // Manages the cases where :\n // - the 'contenteditable' elements that have no selections\n // - the element is of type 'hidden'\n position.start = 0;\n position.end = 0;\n position.length = 0;\n }\n\n return position;\n }\n\n /**\n * Cross browser routine for setting selected range/cursor position\n *\n * @param {HTMLInputElement|EventTarget} element\n * @param {int} start\n * @param {int|null} end\n */\n\n }, {\n key: 'setElementSelection',\n value: function setElementSelection(element, start) {\n var end = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n\n if (this.isUndefinedOrNullOrEmpty(end)) {\n end = start;\n }\n\n if (this.isInputElement(element)) {\n element.setSelectionRange(start, end);\n } else if (!AutoNumericHelper.isNull(element.firstChild)) {\n var range = document.createRange();\n range.setStart(element.firstChild, start);\n range.setEnd(element.firstChild, end);\n var selection = window.getSelection();\n selection.removeAllRanges();\n selection.addRange(range);\n }\n }\n\n /**\n * Function that throw error messages\n *\n * @param {string} message\n * @throws\n */\n\n }, {\n key: 'throwError',\n value: function throwError(message) {\n throw new Error(message);\n }\n\n /**\n * Function that display a warning messages, according to the debug level.\n *\n * @param {string} message\n * @param {boolean} showWarning If FALSE, then the warning message is not displayed\n */\n\n }, {\n key: 'warning',\n value: function warning(message) {\n var showWarning = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n if (showWarning) {\n /* eslint no-console: 0 */\n console.warn('Warning: ' + message);\n }\n }\n\n /**\n * Return `true` if the given event is a wheelup event\n *\n * @param {WheelEvent} wheelEvent\n * @returns {boolean}\n */\n\n }, {\n key: 'isWheelUpEvent',\n value: function isWheelUpEvent(wheelEvent) {\n if (!wheelEvent.deltaY) {\n this.throwError('The event passed as a parameter is not a valid wheel event, \\'' + wheelEvent.type + '\\' given.');\n }\n\n return wheelEvent.deltaY < 0;\n }\n\n /**\n * Return `true` if the given event is a wheeldown event\n *\n * @param {WheelEvent} wheelEvent\n * @returns {boolean}\n */\n\n }, {\n key: 'isWheelDownEvent',\n value: function isWheelDownEvent(wheelEvent) {\n if (!wheelEvent.deltaY) {\n this.throwError('The event passed as a parameter is not a valid wheel event, \\'' + wheelEvent.type + '\\' given.');\n }\n\n return wheelEvent.deltaY > 0;\n }\n\n /**\n * Return the given raw value truncated at the given number of decimal places `decimalPlaces`.\n * This function does not round the value.\n *\n * @example\n * forceDecimalPlaces(123.45678, 0) -> '123.45678'\n * forceDecimalPlaces(123.45678, 1) -> '123.4'\n * forceDecimalPlaces(123.45678, 2) -> '123.45'\n * forceDecimalPlaces(123.45678, 3) -> '123.456'\n *\n * @param {number} value\n * @param {int} decimalPlaces\n * @returns {number|string}\n */\n\n }, {\n key: 'forceDecimalPlaces',\n value: function forceDecimalPlaces(value, decimalPlaces) {\n // We could make sure `decimalPlaces` is an integer and positive, but we'll leave that to the dev calling this function.\n var _String$split3 = String(value).split('.'),\n _String$split4 = _slicedToArray(_String$split3, 2),\n integerPart = _String$split4[0],\n decimalPart = _String$split4[1];\n\n if (!decimalPart) {\n return value;\n }\n\n return integerPart + '.' + decimalPart.substr(0, decimalPlaces);\n }\n\n /**\n * Return the 'nearest rounded' value, according to the given step size.\n * @example roundToNearest(264789, 10000)) => 260000\n *\n * @param {number} value\n * @param {number} stepPlace\n * @returns {*}\n */\n\n }, {\n key: 'roundToNearest',\n value: function roundToNearest(value) {\n var stepPlace = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1000;\n\n if (0 === value) {\n return 0;\n }\n\n if (stepPlace === 0) {\n this.throwError('The `stepPlace` used to round is equal to `0`. This value must not be equal to zero.');\n }\n\n return Math.round(value / stepPlace) * stepPlace;\n }\n\n /**\n * Return the 'nearest rounded' value by automatically adding or subtracting the calculated offset to the initial value.\n * This is done without having to pass a step to this function, and based on the size of the given `value`.\n *\n * @example Calculated offset\n * 1 -> 1 (1)\n * 14 -> 10 (10)\n * 143 -> 140 (10)\n * 1.278 -> 1.300 (100)\n * 28.456 -> 28.500 (100)\n * 276.345 -> 276.000 (1.000)\n * 4.534.061 -> 4.530.000 (10.000)\n * 66.723.844 -> 66.700.000 (100.000)\n * 257.833.411 -> 258.000.000 (1.000.000)\n *\n * Initial Added Offset\n * 2 decimalPlacesRawValue : 1.12 -> 2.00 (1)\n * 3 decimalPlacesRawValue : 1.123 -> 2.000 (1)\n *\n * Special case when the `value` to round is between -1 and 1, excluded :\n * @example\n * Number of Initial Result Calculated\n * decimal places value (add) offset\n * 2 decimalPlacesRawValue : 0.12 -> 0.13 (0.01) : Math.pow(10, -2)\n * 2 decimalPlacesRawValue : 0.01 -> 0.02 (0.01)\n * 2 decimalPlacesRawValue : 0.00 -> 0.01 (0.01)\n *\n * 3 decimalPlacesRawValue : 0.123 -> 0.133 (0.01) : Math.pow(10, -2)\n * 3 decimalPlacesRawValue : 0.012 -> 0.013 (0.001) : Math.pow(10, -3)\n * 3 decimalPlacesRawValue : 0.001 -> 0.001 (0.001)\n * 3 decimalPlacesRawValue : 0.000 -> 0.001 (0.001)\n *\n * 4 decimalPlacesRawValue : 0.4123 -> 0.4200 (0.01) : Math.pow(10, -2)\n * 4 decimalPlacesRawValue : 0.0412 -> 0.0420 (0.001) : Math.pow(10, -3)\n * 4 decimalPlacesRawValue : 0.0041 -> 0.0042 (0.0001) : Math.pow(10, -4)\n * 4 decimalPlacesRawValue : 0.0004 -> 0.0005 (0.0001)\n * 4 decimalPlacesRawValue : 0.0000 -> 0.0001 (0.0001)\n *\n * @param {number} value\n * @param {boolean} isAddition\n * @param {int} decimalPlacesRawValue The precision needed by the `rawValue`\n * @returns {*}\n */\n\n }, {\n key: 'modifyAndRoundToNearestAuto',\n value: function modifyAndRoundToNearestAuto(value, isAddition, decimalPlacesRawValue) {\n value = Number(this.forceDecimalPlaces(value, decimalPlacesRawValue)); // Make sure that '0.13000000001' is converted to the number of rawValue decimal places '0.13'\n\n var absValue = Math.abs(value);\n if (absValue >= 0 && absValue < 1) {\n var rawValueMinimumOffset = Math.pow(10, -decimalPlacesRawValue);\n if (value === 0) {\n // 4 decimalPlacesRawValue : 0.0000 -> 0.0001 (0.0001)\n return isAddition ? rawValueMinimumOffset : -rawValueMinimumOffset;\n }\n\n var offset = void 0;\n var minimumOffsetFirstDecimalPlaceIndex = decimalPlacesRawValue;\n // Find where is the first non-zero decimal places\n var indexFirstNonZeroDecimalPlace = this.indexFirstNonZeroDecimalPlace(value);\n if (indexFirstNonZeroDecimalPlace >= minimumOffsetFirstDecimalPlaceIndex - 1) {\n /* 4 decimalPlacesRawValue : 0.0041 -> 0.0042 (0.0001) : Math.pow(10, -4)\n * 4 decimalPlacesRawValue : 0.0004 -> 0.0005 (0.0001)\n */\n offset = rawValueMinimumOffset;\n } else {\n offset = Math.pow(10, -(indexFirstNonZeroDecimalPlace + 1));\n }\n\n var result = void 0;\n if (isAddition) {\n result = value + offset;\n } else {\n result = value - offset;\n }\n\n return this.roundToNearest(result, offset);\n } else {\n // For values >= 1\n value = parseInt(value, 10);\n var lengthValue = Math.abs(value).toString().length; // `Math.abs()` is needed here to omit the negative sign '-' in case of a negative value\n\n var pow = void 0;\n switch (lengthValue) {\n // Special cases for small numbers\n case 1:\n pow = 0;\n break;\n case 2:\n case 3:\n pow = 1;\n break;\n case 4:\n case 5:\n pow = 2;\n break;\n // Default behavior\n default:\n pow = lengthValue - 3;\n }\n var _offset = Math.pow(10, pow);\n\n var _result = void 0;\n if (isAddition) {\n _result = value + _offset;\n } else {\n _result = value - _offset;\n }\n\n if (_result <= 10 && _result >= -10) {\n return _result;\n }\n\n return this.roundToNearest(_result, _offset);\n }\n }\n\n /**\n * Return the 'nearest rounded' value automatically by adding the calculated offset to the initial value.\n * This will limit the result to the given number of decimal places `decimalPlacesLimit`.\n *\n * @param {number} value\n * @param {int} decimalPlacesLimit\n * @returns {*}\n */\n\n }, {\n key: 'addAndRoundToNearestAuto',\n value: function addAndRoundToNearestAuto(value, decimalPlacesLimit) {\n return this.modifyAndRoundToNearestAuto(value, true, decimalPlacesLimit);\n }\n\n /**\n * Return the 'nearest rounded' value automatically by subtracting the calculated offset to the initial value.\n * This will limit the result to the given number of decimal places `decimalPlacesLimit`.\n *\n * @param {number} value\n * @param {int} decimalPlacesLimit\n * @returns {*}\n */\n\n }, {\n key: 'subtractAndRoundToNearestAuto',\n value: function subtractAndRoundToNearestAuto(value, decimalPlacesLimit) {\n return this.modifyAndRoundToNearestAuto(value, false, decimalPlacesLimit);\n }\n\n /**\n * Take an arabic number as a string and return a javascript number.\n * By default, this function does not try to convert the arabic decimal and thousand separator characters.\n * This returns `NaN` is the conversion is not possible.\n * Based on http://stackoverflow.com/a/17025392/2834898\n *\n * @param {string} arabicNumbers\n * @param {boolean} returnANumber If `true`, return a Number, otherwise return a String\n * @param {boolean} parseDecimalCharacter\n * @param {boolean} parseThousandSeparator\n * @returns {string|number|NaN}\n */\n\n }, {\n key: 'arabicToLatinNumbers',\n value: function arabicToLatinNumbers(arabicNumbers) {\n var returnANumber = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n var parseDecimalCharacter = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;\n var parseThousandSeparator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;\n\n if (this.isNull(arabicNumbers)) {\n return arabicNumbers;\n }\n\n var result = arabicNumbers.toString();\n if (result === '') {\n return arabicNumbers;\n }\n\n if (result.match(/[٠١٢٣٤٥٦٧٨٩۴۵۶]/g) === null) {\n // If no Arabic/Persian numbers are found, return the numeric string or number directly\n if (returnANumber) {\n result = Number(result);\n }\n\n return result;\n }\n\n if (parseDecimalCharacter) {\n result = result.replace(/٫/, '.'); // Decimal character\n }\n\n if (parseThousandSeparator) {\n result = result.replace(/٬/g, ''); // Thousand separator\n }\n\n // Replace the numbers only\n result = result.replace(/[٠١٢٣٤٥٦٧٨٩]/g, function (d) {\n return d.charCodeAt(0) - 1632;\n }) // Arabic numbers\n .replace(/[۰۱۲۳۴۵۶۷۸۹]/g, function (d) {\n return d.charCodeAt(0) - 1776;\n }); // Persian numbers\n\n // `NaN` has precedence over the string `'NaN'`\n var resultAsNumber = Number(result);\n if (isNaN(resultAsNumber)) {\n return resultAsNumber;\n }\n\n if (returnANumber) {\n result = resultAsNumber;\n }\n\n return result;\n }\n\n /**\n * Create a custom event and immediately sent it from the given element.\n * By default, if no element is given, the event is thrown from `document`.\n *\n * @param {string} eventName\n * @param {HTMLElement|HTMLDocument|EventTarget} element\n * @param {object} detail\n * @param {boolean} bubbles Set to `true` if the event must bubble up\n * @param {boolean} cancelable Set to `true` if the event must be cancelable\n */\n\n }, {\n key: 'triggerEvent',\n value: function triggerEvent(eventName) {\n var element = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document;\n var detail = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;\n var bubbles = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;\n var cancelable = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;\n\n var event = void 0;\n if (window.CustomEvent) {\n event = new CustomEvent(eventName, { detail: detail, bubbles: bubbles, cancelable: cancelable }); // This is not supported by default by IE ; We use the polyfill for IE9 and later.\n } else {\n event = document.createEvent('CustomEvent');\n event.initCustomEvent(eventName, bubbles, cancelable, { detail: detail });\n }\n\n element.dispatchEvent(event);\n }\n\n /**\n * Function to parse minimumValue, maximumValue & the input value to prepare for testing to determine if the value falls within the min / max range.\n * Return an object example: minimumValue: \"999999999999999.99\" returns the following \"{s: -1, e: 12, c: Array[15]}\".\n *\n * This function is adapted from Big.js https://github.com/MikeMcl/big.js/. Many thanks to Mike.\n *\n * @param {number|string} n A numeric value.\n * @returns {{}}\n */\n\n }, {\n key: 'parseStr',\n value: function parseStr(n) {\n var x = {}; // A Big number instance.\n var e = void 0;\n var i = void 0;\n var nL = void 0;\n var j = void 0;\n\n // Minus zero?\n if (n === 0 && 1 / n < 0) {\n n = '-0';\n }\n\n // Determine sign. 1 positive, -1 negative\n n = n.toString();\n if (this.isNegativeStrict(n, '-')) {\n n = n.slice(1);\n x.s = -1;\n } else {\n x.s = 1;\n }\n\n // Decimal point?\n e = n.indexOf('.');\n if (e > -1) {\n n = n.replace('.', '');\n }\n\n // Length of string if no decimal character\n if (e < 0) {\n // Integer\n e = n.length;\n }\n\n // Determine leading zeros\n i = n.search(/[1-9]/i) === -1 ? n.length : n.search(/[1-9]/i);\n nL = n.length;\n if (i === nL) {\n // Zero\n x.e = 0;\n x.c = [0];\n } else {\n // Determine trailing zeros\n for (j = nL - 1; n.charAt(j) === '0'; j -= 1) {\n nL -= 1;\n }\n nL -= 1;\n\n // Decimal location\n x.e = e - i - 1;\n x.c = [];\n\n // Convert string to array of digits without leading/trailing zeros\n for (e = 0; i <= nL; i += 1) {\n x.c[e] = +n.charAt(i);\n e += 1;\n }\n }\n\n return x;\n }\n\n /**\n * Function to test if the input value falls with the Min / Max settings.\n * This uses the parsed strings for the above parseStr function.\n *\n * This function is adapted from Big.js https://github.com/MikeMcl/big.js/. Many thanks to Mike.\n *\n * @param {object} y Big number instance\n * @param {object} x Big number instance\n * @returns {*}\n */\n\n }, {\n key: 'testMinMax',\n value: function testMinMax(y, x) {\n var xc = x.c;\n var yc = y.c;\n var i = x.s;\n var j = y.s;\n var k = x.e;\n var l = y.e;\n\n // Either zero?\n if (!xc[0] || !yc[0]) {\n var _result2 = void 0;\n if (!xc[0]) {\n _result2 = !yc[0] ? 0 : -j;\n } else {\n _result2 = i;\n }\n return _result2;\n }\n\n // Signs differ?\n if (i !== j) {\n return i;\n }\n var xNeg = i < 0;\n\n // Compare exponents\n if (k !== l) {\n return k > l ^ xNeg ? 1 : -1;\n }\n i = -1;\n k = xc.length;\n l = yc.length;\n j = k < l ? k : l;\n\n // Compare digit by digit\n for (i += 1; i < j; i += 1) {\n if (xc[i] !== yc[i]) {\n return xc[i] > yc[i] ^ xNeg ? 1 : -1;\n }\n }\n\n // Compare lengths\n var result = void 0;\n if (k === l) {\n result = 0;\n } else {\n result = k > l ^ xNeg ? 1 : -1;\n }\n\n return result;\n }\n\n /**\n * Generate a random string.\n * cf. http://stackoverflow.com/a/8084248/2834898\n *\n * @param {Number} strLength Length of the generated string (in character count)\n * @returns {string}\n */\n\n }, {\n key: 'randomString',\n value: function randomString() {\n var strLength = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 5;\n\n return Math.random().toString(36).substr(2, strLength);\n }\n\n /**\n * Return the DOM element when passed either a DOM element or a selector string.\n *\n * @param {HTMLElement|string} domElementOrSelector\n * @returns {HTMLElement}\n */\n\n }, {\n key: 'domElement',\n value: function domElement(domElementOrSelector) {\n var domElement = void 0;\n if (AutoNumericHelper.isString(domElementOrSelector)) {\n domElement = document.querySelector(domElementOrSelector);\n } else {\n domElement = domElementOrSelector;\n }\n\n return domElement;\n }\n\n /**\n * Retrieve the current element value.\n *\n * @param {HTMLElement|HTMLInputElement|EventTarget} element\n * @returns {number|string|null}\n */\n\n }, {\n key: 'getElementValue',\n value: function getElementValue(element) {\n if (element.tagName.toLowerCase() === 'input') {\n return element.value;\n }\n\n return this.text(element);\n }\n\n /**\n * Modify the element value directly.\n *\n * @param {HTMLElement|HTMLInputElement} element\n * @param {number|string|null} value\n */\n\n }, {\n key: 'setElementValue',\n value: function setElementValue(element) {\n var value = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;\n\n if (element.tagName.toLowerCase() === 'input') {\n element.value = value;\n } else {\n element.textContent = value;\n }\n }\n\n /**\n * This clone the given object, and return it.\n * WARNING: This does not do a deep cloning.\n * cf. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Examples\n * //TODO Add a `deep` option to clone object with more than one depth\n *\n * @param {object} obj\n * @returns {object}\n */\n\n }, {\n key: 'cloneObject',\n value: function cloneObject(obj) {\n return _extends({}, obj);\n }\n\n /**\n * Return a 'camelized' version of the given string.\n * By default, this assume that :\n * - the separators are hyphens '-',\n * - the 'data-' string should be removed, and\n * - that the very first word should not be capitalized.\n *\n * @example camelize('data-currency-symbol') => 'currencySymbol'\n *\n * @param {string} str Text to camelize\n * @param {string} separator Character that separate each word\n * @param {boolean} removeData If set to `true`, remove the `data-` part that you can find on some html attributes\n * @param {boolean} skipFirstWord If set to `true`, do not capitalize the very first word\n * @returns {string|null}\n */\n\n }, {\n key: 'camelize',\n value: function camelize(str) {\n var separator = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : '-';\n var removeData = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;\n var skipFirstWord = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : true;\n\n if (this.isNull(str)) {\n return null;\n }\n\n if (removeData) {\n str = str.replace(/^data-/, '');\n }\n\n // Cut the string into words\n var words = str.split(separator);\n\n // Capitalize each word\n var result = words.map(function (word) {\n return '' + word.charAt(0).toUpperCase() + word.slice(1);\n });\n\n // Then concatenate them back\n result = result.join('');\n\n if (skipFirstWord) {\n // Skip the very first letter\n result = '' + result.charAt(0).toLowerCase() + result.slice(1);\n }\n\n return result;\n }\n\n /**\n * Return the text component of the given DOM element.\n *\n * @param {Element} domElement\n * @returns {string}\n */\n\n }, {\n key: 'text',\n value: function text(domElement) {\n var nodeType = domElement.nodeType;\n\n var result = void 0;\n // cf. https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\n if (nodeType === Node.ELEMENT_NODE || nodeType === Node.DOCUMENT_NODE || nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n result = domElement.textContent;\n } else if (nodeType === Node.TEXT_NODE) {\n result = domElement.nodeValue;\n } else {\n result = '';\n }\n\n return result;\n }\n\n /**\n * Set the text content of the given DOM element.\n * @param {Element} domElement\n * @param {string} text\n */\n\n }, {\n key: 'setText',\n value: function setText(domElement, text) {\n var nodeType = domElement.nodeType;\n if (nodeType === Node.ELEMENT_NODE || nodeType === Node.DOCUMENT_NODE || nodeType === Node.DOCUMENT_FRAGMENT_NODE) {\n domElement.textContent = text;\n }\n //TODO Display a warning if that function does not do anything?\n }\n\n /**\n * Filter out the given `arr` array with the elements found in `excludedElements`.\n * This returns a new array and does not modify the source.\n * cf. verification here : http://codepen.io/AnotherLinuxUser/pen/XpvrMg?editors=0012\n *\n * @param {Array} arr\n * @param {Array} excludedElements\n * @returns {*|Array.}\n */\n\n }, {\n key: 'filterOut',\n value: function filterOut(arr, excludedElements) {\n var _this = this;\n\n return arr.filter(function (element) {\n return !_this.isInArray(element, excludedElements);\n });\n }\n\n /**\n * Remove the trailing zeros in the decimal part of a number.\n *\n * @param {string} numericString\n * @returns {*}\n */\n\n }, {\n key: 'trimPaddedZerosFromDecimalPlaces',\n value: function trimPaddedZerosFromDecimalPlaces(numericString) {\n numericString = String(numericString);\n if (numericString === '') {\n return '';\n }\n\n var _numericString$split = numericString.split('.'),\n _numericString$split2 = _slicedToArray(_numericString$split, 2),\n integerPart = _numericString$split2[0],\n decimalPart = _numericString$split2[1];\n\n if (this.isUndefinedOrNullOrEmpty(decimalPart)) {\n return integerPart;\n }\n\n var trimmedDecimalPart = decimalPart.replace(/0+$/g, '');\n\n var result = void 0;\n if (trimmedDecimalPart === '') {\n result = integerPart;\n } else {\n result = integerPart + '.' + trimmedDecimalPart;\n }\n\n return result;\n }\n\n /**\n * Return the top-most hovered item by the mouse cursor.\n *\n * @returns {*}\n */\n\n }, {\n key: 'getHoveredElement',\n value: function getHoveredElement() {\n var hoveredElements = [].concat(_toConsumableArray(document.querySelectorAll(':hover')));\n return hoveredElements[hoveredElements.length - 1];\n }\n\n /**\n * Return the given array trimmed to the given length.\n * @example arrayTrim([1, 2, 3, 4], 2) -> [1, 2]\n *\n * @param {Array} array\n * @param {Number} length\n * @returns {*}\n */\n\n }, {\n key: 'arrayTrim',\n value: function arrayTrim(array, length) {\n var arrLength = array.length;\n if (arrLength === 0 || length > arrLength) {\n // Also manage the case where `length` is higher than the current length\n return array;\n }\n\n if (length < 0) {\n return [];\n }\n\n array.length = parseInt(length, 10);\n\n return array;\n }\n\n /**\n * Merge all the given arrays by keeping only unique elements, and return an array with de-duplicated values.\n * cf. http://stackoverflow.com/a/27664971/2834898\n *\n * @param {...array} arrays\n * @returns {[*]}\n */\n\n }, {\n key: 'arrayUnique',\n value: function arrayUnique() {\n var _ref;\n\n //FIXME à tester\n return [].concat(_toConsumableArray(new Set((_ref = []).concat.apply(_ref, arguments))));\n }\n\n /**\n * Merge all the given Maps by keeping only unique elements, and return a new Map with de-duplicated keys.\n *\n * @param {...Map} mapObjects\n * @returns {Map}\n */\n\n }, {\n key: 'mergeMaps',\n value: function mergeMaps() {\n for (var _len = arguments.length, mapObjects = Array(_len), _key = 0; _key < _len; _key++) {\n mapObjects[_key] = arguments[_key];\n }\n\n return new Map(mapObjects.reduce(function (as, b) {\n return as.concat([].concat(_toConsumableArray(b)));\n }, []));\n }\n\n /**\n * Search the given `value` in the object `obj`, and return the very first key it finds\n *\n * @param {object} obj\n * @param {string|number} value\n * @returns {*|null}\n */\n\n }, {\n key: 'objectKeyLookup',\n value: function objectKeyLookup(obj, value) {\n var result = Object.entries(obj).find(function (array) {\n return array[1] === value;\n });\n var key = null;\n if (result !== void 0) {\n key = result[0];\n }\n\n return key;\n }\n\n /**\n * Insert the single character `char` in the string `str` at the given position `index`\n *\n * @param {string} str\n * @param {string} char\n * @param {int} index\n * @returns {string}\n */\n\n }, {\n key: 'insertAt',\n value: function insertAt(str, char, index) {\n str = String(str);\n\n if (index > str.length) {\n throw new Error('The given index is out of the string range.');\n }\n\n if (char.length !== 1) {\n throw new Error('The given string `char` should be only one character long.');\n }\n\n if (str === '' && index === 0) {\n return char;\n }\n\n return '' + str.slice(0, index) + char + str.slice(index);\n }\n\n /**\n * Convert the given scientific notation to the 'expanded' decimal notation\n *\n * @example scientificToDecimal('-123.4567e-6') returns '-0.0001234567'\n *\n * @param {number|string} val\n * @returns {number|string}\n */\n\n }, {\n key: 'scientificToDecimal',\n value: function scientificToDecimal(val) {\n // Check that the val is a Number\n var numericValue = Number(val);\n if (isNaN(numericValue)) {\n return NaN;\n }\n\n // Check if the number is in a scientific notation\n val = String(val);\n var isScientific = val.includes('e') || val.includes('E');\n\n if (!isScientific) {\n return val;\n }\n\n // Convert the scientific notation to a numeric string\n\n var _val$split = val.split(/e/i),\n _val$split2 = _slicedToArray(_val$split, 2),\n value = _val$split2[0],\n exponent = _val$split2[1];\n\n var isNegative = value < 0;\n if (isNegative) {\n value = value.replace('-', '');\n }\n\n var isNegativeExponent = +exponent < 0;\n if (isNegativeExponent) {\n exponent = exponent.replace('-', ''); // Remove the negative sign\n }\n\n var _value$split = value.split(/\\./),\n _value$split2 = _slicedToArray(_value$split, 2),\n int = _value$split2[0],\n float = _value$split2[1];\n\n var result = void 0;\n if (isNegativeExponent) {\n if (int.length > exponent) {\n // Place the decimal point at the int length count minus exponent\n result = this.insertAt(int, '.', int.length - exponent);\n } else {\n // If that decimal point is greater than the int length, pad with zeros (ie. Number('-123.4567e-6') --> -0.0001234567)\n result = '0.' + '0'.repeat(exponent - int.length) + int;\n }\n\n result = '' + result + (float ? float : '');\n } else {\n // Positive exponent\n if (float) {\n value = '' + int + float; // Remove the '.', if any\n if (exponent < float.length) {\n result = this.insertAt(value, '.', +exponent + int.length);\n } else {\n result = '' + value + '0'.repeat(exponent - float.length);\n }\n } else {\n value = value.replace('.', ''); // Single case where val is '1.e4'\n result = '' + value + '0'.repeat(Number(exponent));\n }\n }\n\n if (isNegative) {\n // Put back the negative sign, if any\n result = '-' + result;\n }\n\n return result;\n }\n }]);\n\n return AutoNumericHelper;\n}();\n\nexports.default = AutoNumericHelper;\nmodule.exports = exports['default'];\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWNIZWxwZXIuanMuanMiLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9BdXRvTnVtZXJpYy9zcmMvQXV0b051bWVyaWNIZWxwZXIuanM/ZTlhZiJdLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEhlbHBlciBmdW5jdGlvbnMgZm9yIGF1dG9OdW1lcmljLmpzXG4gKiBAYXV0aG9yIEFsZXhhbmRyZSBCb25uZWF1IDxhbGV4YW5kcmUuYm9ubmVhdUBsaW51eGZyLmV1PlxuICogQGNvcHlyaWdodCDCqSAyMDE2IEFsZXhhbmRyZSBCb25uZWF1XG4gKlxuICogVGhlIE1JVCBMaWNlbnNlIChodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocClcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvblxuICogb2J0YWluaW5nIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb25cbiAqIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dFxuICogcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsXG4gKiBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWIgbGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZVxuICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmdcbiAqIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsXG4gKiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVNcbiAqIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EXG4gKiBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVFxuICogSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksXG4gKiBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1JcbiAqIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgQXV0b051bWVyaWNFbnVtIGZyb20gJy4vQXV0b051bWVyaWNFbnVtJztcblxuLyoqXG4gKiBTdGF0aWMgY2xhc3MgdGhhdCBob2xkcyBhbGwgdGhlIGhlbHBlciBmdW5jdGlvbnMgYXV0b051bWVyaWMgdXNlcy5cbiAqIE5vdGUgOiBub25lIG9mIHRoZSBmdW5jdGlvbnMgaW4gdGhlcmUgYXJlIGF3YXJlIG9mIGFueSBhdXRvTnVtZXJpYyBpbnRlcm5hbHMgKHdoaWNoIG1lYW5zIHRoZXJlIGFyZSBubyByZWZlcmVuY2VzIHRvIGF1dG9OdW1lcmljLXNwZWNpZmljIGluZm8gbGlrZSBvcHRpb25zIG5hbWVzIG9yIGRhdGEgc3RydWN0dXJlcykuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEF1dG9OdW1lcmljSGVscGVyIHtcbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBgdmFsdWVgIGlzIG51bGxcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB0ZXN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybiBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgbnVsbCwgRkFMU0Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgc3RhdGljIGlzTnVsbCh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgYHZhbHVlYCBpcyB1bmRlZmluZWRcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB0ZXN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybiBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgdW5kZWZpbmVkLCBGQUxTRSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBzdGF0aWMgaXNVbmRlZmluZWQodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSB2b2lkKDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgdW5kZWZpbmVkLCBudWxsIG9yIGVtcHR5XG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHZvaWQoMCkgfHwgJycgPT09IHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGdpdmVuIHBhcmFtZXRlciBpcyBhIFN0cmluZ1xuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSBzdHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNTdHJpbmcoc3RyKSB7XG4gICAgICAgIHJldHVybiAodHlwZW9mIHN0ciA9PT0gJ3N0cmluZycgfHwgc3RyIGluc3RhbmNlb2YgU3RyaW5nKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgYHZhbHVlYCBpcyBhbiBlbXB0eSBzdHJpbmcgJydcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB0ZXN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybiBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgYW4gZW1wdHkgc3RyaW5nICcnLCBGQUxTRSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBzdGF0aWMgaXNFbXB0eVN0cmluZyh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09ICcnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHBhcmFtZXRlciBpcyBhIGJvb2xlYW5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzQm9vbGVhbih2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdHlwZW9mKHZhbHVlKSA9PT0gJ2Jvb2xlYW4nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHBhcmFtZXRlciBpcyBhIHN0cmluZyAndHJ1ZScgb3IgJ2ZhbHNlJ1xuICAgICAqXG4gICAgICogVGhpcyBmdW5jdGlvbiBhY2NlcHRzIGFueSBjYXNlcyBmb3IgdGhvc2Ugc3RyaW5ncy5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNUcnVlT3JGYWxzZVN0cmluZyh2YWx1ZSkge1xuICAgICAgICBjb25zdCBsb3dlcmNhc2VWYWx1ZSA9IFN0cmluZyh2YWx1ZSkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgcmV0dXJuIGxvd2VyY2FzZVZhbHVlID09PSAndHJ1ZScgfHwgbG93ZXJjYXNlVmFsdWUgPT09ICdmYWxzZSc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGFuIG9iamVjdFxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSByZWZlcmVuY2VcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNPYmplY3QocmVmZXJlbmNlKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgcmVmZXJlbmNlID09PSAnb2JqZWN0JyAmJiByZWZlcmVuY2UgIT09IG51bGwgJiYgIUFycmF5LmlzQXJyYXkocmVmZXJlbmNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBnaXZlbiBvYmplY3QgaXMgZW1wdHlcbiAgICAgKiBjZi4gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82Nzk5MTUvaG93LWRvLWktdGVzdC1mb3ItYW4tZW1wdHktamF2YXNjcmlwdC1vYmplY3QgYW5kIGh0dHA6Ly9qc3BlcmYuY29tL2VtcHR5LW9iamVjdC10ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb2JqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzRW1wdHlPYmoob2JqKSB7XG4gICAgICAgIGZvciAoY29uc3QgcHJvcCBpbiBvYmopIHtcbiAgICAgICAgICAgIGlmIChvYmouaGFzT3duUHJvcGVydHkocHJvcCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgcmVhbCBudW1iZXIgKGFuZCBub3QgYSBudW1lcmljIHN0cmluZykuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IG5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNOdW1iZXJTdHJpY3Qobikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG4gPT09ICdudW1iZXInO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHBhcmFtZXRlciBpcyBhIG51bWJlciAob3IgYSBudW1iZXIgd3JpdHRlbiBhcyBhIHN0cmluZykuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IG5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNOdW1iZXIobikge1xuICAgICAgICByZXR1cm4gIXRoaXMuaXNBcnJheShuKSAmJiAhaXNOYU4ocGFyc2VGbG9hdChuKSkgJiYgaXNGaW5pdGUobik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgbnVtYmVyIChvciBhIG51bWJlciB3cml0dGVuIGFzIGEgc3RyaW5nKS5cbiAgICAgKiBUaGlzIHZlcnNpb24gYWxzbyBhY2NlcHRzIEFyYWJpYyBhbmQgUGVyc2lhbiBudW1iZXJzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSBuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzTnVtYmVyT3JBcmFiaWMobikge1xuICAgICAgICBjb25zdCBsYXRpbkNvbnZlcnRlZE51bWJlciA9IHRoaXMuYXJhYmljVG9MYXRpbk51bWJlcnMobiwgZmFsc2UsIHRydWUsIHRydWUpO1xuICAgICAgICByZXR1cm4gdGhpcy5pc051bWJlcihsYXRpbkNvbnZlcnRlZE51bWJlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGFuIGludGVnZXIgKGFuZCBub3QgYSBmbG9hdCkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IG5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNJbnQobikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG4gPT09ICdudW1iZXInICYmIHBhcnNlRmxvYXQobikgPT09IHBhcnNlSW50KG4sIDEwKSAmJiAhaXNOYU4obik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBmdW5jXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzRnVuY3Rpb24oZnVuYykge1xuICAgICAgICByZXR1cm4gdHlwZW9mIGZ1bmMgPT09ICdmdW5jdGlvbic7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgY3VycmVudCBicm93c2VyIGlzIHRoZSBvYnNvbGV0ZSBJbnRlcm5ldCBFeHBsb3JlciAxMSAoSUUxMSkgb25lXG4gICAgICogY2YuIGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8yMTgyNTIwNy8yODM0ODk4XG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNJRTExKCkge1xuICAgICAgICAvLyBub2luc3BlY3Rpb24gSlNVbnJlc29sdmVkVmFyaWFibGVcbiAgICAgICAgcmV0dXJuICEhd2luZG93Lk1TSW5wdXRNZXRob2RDb250ZXh0ICYmICEhZG9jdW1lbnQuZG9jdW1lbnRNb2RlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaXMgdGhlIHN0cmluZyBgc3RyYCBjb250YWlucyB0aGUgc3RyaW5nIGBuZWVkbGVgXG4gICAgICogTm90ZTogdGhpcyBmdW5jdGlvbiBkb2VzIG5vdCBjb2VyY2UgdGhlIHBhcmFtZXRlcnMgdHlwZXNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmVlZGxlXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGNvbnRhaW5zKHN0ciwgbmVlZGxlKSB7XG4gICAgICAgIC8vVE9ETyBVc2UgYEFycmF5LnByb3RvdHlwZS5pbmNsdWRlcygpYCB3aGVuIGF2YWlsYWJsZSAoY2YuIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0phdmFTY3JpcHQvUmVmZXJlbmNlL0dsb2JhbF9PYmplY3RzL0FycmF5L2luY2x1ZGVzKVxuICAgICAgICBpZiAoIXRoaXMuaXNTdHJpbmcoc3RyKSB8fCAhdGhpcy5pc1N0cmluZyhuZWVkbGUpIHx8IHN0ciA9PT0gJycgfHwgbmVlZGxlID09PSAnJykge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHN0ci5pbmRleE9mKG5lZWRsZSkgIT09IC0xO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGBuZWVkbGVgIGlzIGluIHRoZSBhcnJheVxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSBuZWVkbGVcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJheVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBpc0luQXJyYXkobmVlZGxlLCBhcnJheSkge1xuICAgICAgICBpZiAoIXRoaXMuaXNBcnJheShhcnJheSkgfHwgYXJyYXkgPT09IFtdIHx8IHRoaXMuaXNVbmRlZmluZWQobmVlZGxlKSkge1xuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGFycmF5LmluZGV4T2YobmVlZGxlKSAhPT0gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGFuIEFycmF5XG4gICAgICogLy9UT0RPIFJlcGxhY2UgdGhpcyBieSB0aGUgZGVmYXVsdCBgQXJyYXkuaXNBcnJheSgpYCBmdW5jdGlvbj9cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Kn0gYXJyXG4gICAgICogQHRocm93cyBFcnJvclxuICAgICAqIEByZXR1cm5zIHsqfGJvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzQXJyYXkoYXJyKSB7XG4gICAgICAgIGlmIChPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoW10pID09PSAnW29iamVjdCBBcnJheV0nKSB7IC8vIE1ha2Ugc3VyZSBhbiBhcnJheSBoYXMgYSBjbGFzcyBhdHRyaWJ1dGUgb2YgW29iamVjdCBBcnJheV1cbiAgICAgICAgICAgIC8vIFRlc3QgcGFzc2VkLCBub3cgY2hlY2sgaWYgaXMgYW4gQXJyYXlcbiAgICAgICAgICAgIHJldHVybiBBcnJheS5pc0FycmF5KGFycikgfHwgKHR5cGVvZiBhcnIgPT09ICdvYmplY3QnICYmIE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChhcnIpID09PSAnW29iamVjdCBBcnJheV0nKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcigndG9TdHJpbmcgbWVzc2FnZSBjaGFuZ2VkIGZvciBPYmplY3QgQXJyYXknKTsgLy8gVmVyaWZ5IHRoYXQgdGhlIHN0cmluZyByZXR1cm5lZCBieSBgdG9TdHJpbmdgIGRvZXMgbm90IGNoYW5nZSBpbiB0aGUgZnV0dXJlIChjZi4gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvODM2NTIxNSlcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHBhcmFtZXRlciBpcyBhIERPTSBlbGVtZW50XG4gICAgICogY2YuIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzQ3NTQxMDQvMjgzNDg5OFxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSBvYmpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNFbGVtZW50KG9iaikge1xuICAgICAgICAvLyByZXR1cm4gISEob2JqICYmIG9iai5ub2RlTmFtZSk7XG4gICAgICAgIC8vIHJldHVybiBvYmogJiYgJ25vZGVUeXBlJyBpbiBvYmo7XG4gICAgICAgIC8vIHJldHVybiBvYmogaW5zdGFuY2VvZiBFbGVtZW50IHx8IG9iaiBpbnN0YW5jZW9mIEhUTUxJbnB1dEVsZW1lbnQgfHwgb2JqIGluc3RhbmNlb2YgSFRNTEVsZW1lbnQ7XG4gICAgICAgIGlmICh0eXBlb2YgRWxlbWVudCA9PT0gJ3VuZGVmaW5lZCcpIHtcbiAgICAgICAgICAgIC8vIFRoaXMgdGVzdCBpcyBuZWVkZWQgaW4gZW52aXJvbm5lbWVudHMgd2hlcmUgdGhlIEVsZW1lbnQgb2JqZWN0IGRvZXMgbm90IGV4aXN0IChpZS4gaW4gd2ViIHdvcmtlcnMpXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gb2JqIGluc3RhbmNlb2YgRWxlbWVudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGluIHRoZSBnaXZlbiBET00gZWxlbWVudCBpcyBhbiA8aW5wdXQ+LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBkb21FbGVtZW50XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgaXNJbnB1dEVsZW1lbnQoZG9tRWxlbWVudCkge1xuICAgICAgICByZXR1cm4gdGhpcy5pc0VsZW1lbnQoZG9tRWxlbWVudCkgJiYgZG9tRWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdpbnB1dCc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgc3RyaW5nIHRoYXQgcmVwcmVzZW50cyBhIGZsb2F0IG51bWJlciwgYW5kIHRoYXQgbnVtYmVyIGhhcyBhIGRlY2ltYWwgcGFydFxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIC8vIHN0YXRpYyBoYXNEZWNpbWFscyhzdHIpIHtcbiAgICAvLyAgICAgY29uc3QgWywgZGVjaW1hbFBhcnRdID0gc3RyLnNwbGl0KCcuJyk7XG4gICAgLy8gICAgIHJldHVybiAhaXNVbmRlZmluZWQoZGVjaW1hbFBhcnQpO1xuICAgIC8vIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGlmIHRoZSBwYXJhbWV0ZXIgaXMgYSBzdHJpbmcgdGhhdCByZXByZXNlbnRzIGEgZmxvYXQgbnVtYmVyLCBhbmQgdGhhdCBudW1iZXIgaGFzIGEgZGVjaW1hbCBwYXJ0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICAgICAqIEByZXR1cm5zIHtpbnR9XG4gICAgICovXG4gICAgc3RhdGljIGRlY2ltYWxQbGFjZXMoc3RyKSB7XG4gICAgICAgIGNvbnN0IFssIGRlY2ltYWxQYXJ0XSA9IHN0ci5zcGxpdCgnLicpO1xuICAgICAgICBpZiAoIXRoaXMuaXNVbmRlZmluZWQoZGVjaW1hbFBhcnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gZGVjaW1hbFBhcnQubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBpbmRleCBvZiB0aGUgZmlyc3Qgbm9uLXplcm8gZGVjaW1hbCBwbGFjZSBpbiB0aGUgZ2l2ZW4gdmFsdWUuXG4gICAgICogVGhlIGluZGV4IHN0YXJ0cyBhZnRlciB0aGUgZGVjaW1hbCBwb2ludCwgaWYgYW55LCBhbmQgYmVnaW5zIGF0ICcxJy5cbiAgICAgKiBJZiBubyBkZWNpbWFsIHBsYWNlcyBhcmUgZm91bmQgaW4gdGhlIHZhbHVlLCB0aGlzIGZ1bmN0aW9uIHJldHVybnMgYDBgLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSgnMC4wMCcpIC0+IDBcbiAgICAgKiBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSgnMS4wMCcpIC0+IDBcbiAgICAgKiBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSgnMC4xMicpIC0+IDFcbiAgICAgKiBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSgnMC4xMjM0JykgLT4gMVxuICAgICAqIGluZGV4Rmlyc3ROb25aZXJvRGVjaW1hbFBsYWNlKCcwLjAxMjM0JykgLT4gMlxuICAgICAqIGluZGV4Rmlyc3ROb25aZXJvRGVjaW1hbFBsYWNlKCcwLjAwMTIzNCcpIC0+IDNcbiAgICAgKiBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSgnMC4wMDAxMjM0JykgLT4gNFxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gICAgICogQHJldHVybnMge051bWJlcnxudW1iZXJ9XG4gICAgICovXG4gICAgc3RhdGljIGluZGV4Rmlyc3ROb25aZXJvRGVjaW1hbFBsYWNlKHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IFssIGRlY2ltYWxQYXJ0XSA9IFN0cmluZyhNYXRoLmFicyh2YWx1ZSkpLnNwbGl0KCcuJyk7XG5cbiAgICAgICAgaWYgKHRoaXMuaXNVbmRlZmluZWQoZGVjaW1hbFBhcnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXN1bHQgPSBkZWNpbWFsUGFydC5sYXN0SW5kZXhPZignMCcpO1xuICAgICAgICBpZiAocmVzdWx0ID09PSAtMSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gMDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCArPSAyO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIGNvZGUgZm9yIHRoZSBrZXkgdXNlZCB0byBnZW5lcmF0ZSB0aGUgZ2l2ZW4gZXZlbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBldmVudFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8TnVtYmVyfVxuICAgICAqL1xuICAgIHN0YXRpYyBrZXlDb2RlTnVtYmVyKGV2ZW50KSB7XG4gICAgICAgIC8vIGBldmVudC5rZXlDb2RlYCBhbmQgYGV2ZW50LndoaWNoYCBhcmUgZGVwcmVjYXRlZCwgYEtleWJvYXJkRXZlbnQua2V5YCAoaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0tleWJvYXJkRXZlbnQva2V5KSBtdXN0IGJlIHVzZWQgbm93XG4gICAgICAgIC8vIEFsc28sIGRvIG5vdGUgdGhhdCBGaXJlZm94IGdlbmVyYXRlIGEgJ2tleXByZXNzJyBldmVudCAoZS5rZXlDb2RlID09PSAwKSBmb3IgdGhlIGtleXMgdGhhdCBkbyBub3QgcHJpbnQgYSBjaGFyYWN0ZXIgKGllLiAnSW5zZXJ0JywgJ0RlbGV0ZScsICdGbicga2V5cywgJ1BhZ2VVcCcsICdQYWdlRG93bicgZXRjLikuICdTaGlmdCcgb24gdGhlIG90aGVyIGhhbmQgZG9lcyBub3QgZ2VuZXJhdGUgYSBrZXlwcmVzcyBldmVudC5cbiAgICAgICAgcmV0dXJuICh0eXBlb2YgZXZlbnQud2hpY2ggPT09ICd1bmRlZmluZWQnKT9ldmVudC5rZXlDb2RlOmV2ZW50LndoaWNoO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgY2hhcmFjdGVyIGZyb20gdGhlIGV2ZW50IGtleSBjb2RlLlxuICAgICAqIElmIHRoZSBLZXlib2FyZEV2ZW50IGRvZXMgbm90IHJlcHJlc2VudCBhIHByaW50YWJsZSBjaGFyYWN0ZXIsIHRoZW4gdGhlIGtleSBuYW1lIGlzIHVzZWQgKGllLiAnTWV0YScsICdTaGlmdCcsICdGMScsIGV0Yy4pXG4gICAgICogQGV4YW1wbGUgY2hhcmFjdGVyKDUwKSA9PiAnMidcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7S2V5Ym9hcmRFdmVudH0gZXZlbnRcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBjaGFyYWN0ZXIoZXZlbnQpIHtcbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKGV2ZW50LmtleSA9PT0gJ1VuaWRlbnRpZmllZCcgfHwgZXZlbnQua2V5ID09PSB2b2lkKDApIHx8IHRoaXMuaXNTZWxlbml1bUJvdCgpKSB7XG4gICAgICAgICAgICAvL1hYWCBUaGUgc2VsZW5pdW0gZ2Vja29kcml2ZXIgZG8gbm90IHVuZGVyc3RhbmQgYGV2ZW50LmtleWAsIGhlbmNlIHdoZW4gdXNpbmcgaXQsIHdlIG5lZWQgdG8gcmVseSBvbiB0aGUgb2xkIGRlcHJlY2F0ZWQgYGtleUNvZGVgIGF0dHJpYnV0ZSwgY2YuIHVwc3RyZWFtIGlzc3VlIGh0dHBzOi8vZ2l0aHViLmNvbS9tb3ppbGxhL2dlY2tvZHJpdmVyL2lzc3Vlcy80NDBcbiAgICAgICAgICAgIC8vIFVzZSB0aGUgb2xkIGRlcHJlY2F0ZWQga2V5Q29kZSBwcm9wZXJ0eSwgaWYgdGhlIG5ldyBga2V5YCBvbmUgaXMgbm90IHN1cHBvcnRlZFxuICAgICAgICAgICAgY29uc3Qga2V5Q29kZSA9IHRoaXMua2V5Q29kZU51bWJlcihldmVudCk7XG4gICAgICAgICAgICBpZiAoa2V5Q29kZSA9PT0gQXV0b051bWVyaWNFbnVtLmtleUNvZGUuQW5kcm9pZERlZmF1bHQpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQW5kcm9pZERlZmF1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IHBvdGVudGlhbFJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5mcm9tQ2hhckNvZGVLZXlDb2RlW2tleUNvZGVdO1xuICAgICAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkocG90ZW50aWFsUmVzdWx0KSkge1xuICAgICAgICAgICAgICAgIC8vIFNpbmNlIGBTdHJpbmcuZnJvbUNoYXJDb2RlYCBkbyBub3QgcmV0dXJuIG5hbWVkIGtleXMgZm9yIHNvbWUga2V5cyAoJ0VzY2FwZScgYW5kICdFbnRlcicgZm9yIGluc3RhbmNlKSwgd2UgY29udmVydCB0aGUgY2hhcmFjdGVycyB0byB0aGUga2V5IG5hbWVzXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gcG90ZW50aWFsUmVzdWx0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBTdHJpbmcuZnJvbUNoYXJDb2RlKGtleUNvZGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgbGV0IGJyb3dzZXI7XG4gICAgICAgICAgICBzd2l0Y2ggKGV2ZW50LmtleSkge1xuICAgICAgICAgICAgICAgIC8vIE1hbmFnZXMgYWxsIHRoZSBzcGVjaWFsIGNhc2VzIGZvciBvYnNvbGV0ZSBicm93c2VycyB0aGF0IHJldHVybiB0aGUgbm9uLXN0YW5kYXJkIG5hbWVzXG4gICAgICAgICAgICAgICAgY2FzZSAnQWRkJzpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuTnVtcGFkUGx1cztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnQXBwcyc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkNvbnRleHRNZW51O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdDcnNlbCc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkNyU2VsO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdEZWNpbWFsJzpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuTnVtcGFkRG90O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdEZWwnOlxuICAgICAgICAgICAgICAgICAgICBicm93c2VyID0gdGhpcy5icm93c2VyKCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICgoYnJvd3Nlci5uYW1lID09PSAnZmlyZWZveCcgJiYgYnJvd3Nlci52ZXJzaW9uIDw9IDM2KSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgKGJyb3dzZXIubmFtZSA9PT0gJ2llJyAmJiBicm93c2VyLnZlcnNpb24gPD0gOSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNwZWNpYWwgd29ya2Fyb3VuZCBmb3IgdGhlIG9ic29sZXRlIGJyb3dzZXIgSUUxMSB3aGljaCBvdXRwdXQgYSAnRGVsZXRlJyBrZXkgd2hlbiB1c2luZyB0aGUgbnVtcGFkICdkb3QnIG9uZSEgVGhpcyBmaXhlcyBpc3N1ZSAjNDAxXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHdvcmthcm91bmQgYnJlYWsgdGhlIHVzYWdlIG9mIHRoZSAnRGVsZXRlJyBrZXkgZm9yIEZpcmVmb3ggPD0zNiwgYW5kIElFOSwgc2luY2UgdGhvc2UgYnJvd3NlciBzZW5kICdEZWwnIGluc3RlYWQgb2YgJ0RlbGV0ZScsIHRoZXJlZm9yZSB3ZSBvbmx5IHVzZSBpdCBmb3IgdGhvc2Ugb2Jzb2xldGUgYnJvd3NlcnNcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkRvdDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkRlbGV0ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdEaXZpZGUnOlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5OdW1wYWRTbGFzaDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnRG93bic6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkRvd25BcnJvdztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnRXNjJzpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuRXNjO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdFeHNlbCc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkV4U2VsO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdMZWZ0JzpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuTGVmdEFycm93O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdNZXRhJzpcbiAgICAgICAgICAgICAgICBjYXNlICdTdXBlcic6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLk9TTGVmdDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnTXVsdGlwbHknOlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5OdW1wYWRNdWx0aXBseTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnUmlnaHQnOlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5SaWdodEFycm93O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdTcGFjZWJhcic6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLlNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdTdWJ0cmFjdCc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLk51bXBhZE1pbnVzO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdVcCc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLlVwQXJyb3c7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBub3JtYWwgY2FzZVxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBldmVudC5rZXk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgbmFtZSBhbmQgdmVyc2lvbiBvZiB0aGUgY3VycmVudCBicm93c2VyLlxuICAgICAqIEBleGFtcGxlIGBicm93c2VyVmVyc2lvbigpYCA9PiB7IG5hbWU6ICdGaXJlZm94JywgdmVyc2lvbjogJzQyJyB9XG4gICAgICogQmFzZWQgb24gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzgwODAwNTEvMjgzNDg5OFxuICAgICAqXG4gICAgICogQHJldHVybnMge3sgbmFtZTogc3RyaW5nLCB2ZXJzaW9uOiBzdHJpbmcgfX1cbiAgICAgKi9cbiAgICBzdGF0aWMgYnJvd3NlcigpIHtcbiAgICAgICAgY29uc3QgdWEgPSBuYXZpZ2F0b3IudXNlckFnZW50O1xuICAgICAgICBsZXQgdGVtO1xuICAgICAgICBsZXQgTSA9IHVhLm1hdGNoKC8ob3BlcmF8Y2hyb21lfHNhZmFyaXxmaXJlZm94fG1zaWV8dHJpZGVudCg/PVxcLykpXFwvP1xccyooXFxkKykvaSkgfHwgW107XG5cbiAgICAgICAgaWYgKC90cmlkZW50L2kudGVzdChNWzFdKSkge1xuICAgICAgICAgICAgdGVtID0gL1xcYnJ2WyA6XSsoXFxkKykvZy5leGVjKHVhKSB8fCBbXTtcbiAgICAgICAgICAgIHJldHVybiB7IG5hbWU6ICdpZScsIHZlcnNpb246ICh0ZW1bMV0gfHwgJycpIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoTVsxXSA9PT0gJ0Nocm9tZScpIHtcbiAgICAgICAgICAgIHRlbSA9IHVhLm1hdGNoKC9cXGIoT1BSfEVkZ2UpXFwvKFxcZCspLyk7XG4gICAgICAgICAgICBpZiAodGVtICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgbmFtZTogdGVtWzFdLnJlcGxhY2UoJ09QUicsICdvcGVyYScpLCB2ZXJzaW9uOiB0ZW1bMl0gfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIE0gPSBNWzJdP1tNWzFdLCBNWzJdXTpbbmF2aWdhdG9yLmFwcE5hbWUsIG5hdmlnYXRvci5hcHBWZXJzaW9uLCAnLT8nXTtcbiAgICAgICAgaWYgKCh0ZW0gPSB1YS5tYXRjaCgvdmVyc2lvblxcLyhcXGQrKS9pKSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIE0uc3BsaWNlKDEsIDEsIHRlbVsxXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4geyBuYW1lOiBNWzBdLnRvTG93ZXJDYXNlKCksIHZlcnNpb246IE1bMV0gfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiB0aGUgYnJvd3NlciBpcyBjb250cm9sbGVkIGJ5IFNlbGVuaXVtLlxuICAgICAqIE5vdGU6IFRoaXMgb25seSB3b3JrcyB3aXRoaW4gdGhlIGdlY2tvZHJpdmVyLlxuICAgICAqIGNmLiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzMzMjI1OTQ3L2Nhbi1hLXdlYnNpdGUtZGV0ZWN0LXdoZW4teW91LWFyZS11c2luZy1zZWxlbml1bS13aXRoLWNocm9tZWRyaXZlclxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzU2VsZW5pdW1Cb3QoKSB7XG4gICAgICAgIC8vIG5vaW5zcGVjdGlvbiBKU1VucmVzb2x2ZWRWYXJpYWJsZVxuICAgICAgICByZXR1cm4gd2luZG93Lm5hdmlnYXRvci53ZWJkcml2ZXIgPT09IHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gbnVtYmVyIGlzIG5lZ2F0aXZlLCBvciBpZiB0aGUgZ2l2ZW4gc3RyaW5nIGNvbnRhaW5zIGEgbmVnYXRpdmUgc2lnbiA6XG4gICAgICogLSBldmVyeXdoZXJlIGluIHRoZSBzdHJpbmcgKGJ5IGRlZmF1bHQpLCBvclxuICAgICAqIC0gb24gdGhlIGZpcnN0IGNoYXJhY3RlciBvbmx5IGlmIHRoZSBgY2hlY2tFdmVyeXdoZXJlYCBwYXJhbWV0ZXIgaXMgc2V0IHRvIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IG51bWJlck9yTnVtZXJpY1N0cmluZyBBIE51bWJlciwgb3IgYSBudW1iZXIgcmVwcmVzZW50ZWQgYnkgYSBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmVnYXRpdmVTaWduQ2hhcmFjdGVyIFRoZSBzaW5nbGUgY2hhcmFjdGVyIHRoYXQgcmVwcmVzZW50IHRoZSBuZWdhdGl2ZSBzaWduXG4gICAgICogQHBhcmFtIHtib29sZWFufSBjaGVja0V2ZXJ5d2hlcmUgSWYgVFJVRSwgdGhlbiB0aGUgbmVnYXRpdmUgc2lnbiBpcyBzZWFyY2ggZXZlcnl3aGVyZSBpbiB0aGUgbnVtZXJpYyBzdHJpbmcgKHRoaXMgaXMgbmVlZGVkIGZvciBpbnN0YW5jZSBpZiB0aGUgc3RyaW5nIGlzICcxMjM0LjU2LScpXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzTmVnYXRpdmUobnVtYmVyT3JOdW1lcmljU3RyaW5nLCBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgPSAnLScsIGNoZWNrRXZlcnl3aGVyZSA9IHRydWUpIHtcbiAgICAgICAgaWYgKG51bWJlck9yTnVtZXJpY1N0cmluZyA9PT0gbmVnYXRpdmVTaWduQ2hhcmFjdGVyKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChudW1iZXJPck51bWVyaWNTdHJpbmcgPT09ICcnKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIobnVtYmVyT3JOdW1lcmljU3RyaW5nKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bWJlck9yTnVtZXJpY1N0cmluZyA8IDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2hlY2tFdmVyeXdoZXJlKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5jb250YWlucyhudW1iZXJPck51bWVyaWNTdHJpbmcsIG5lZ2F0aXZlU2lnbkNoYXJhY3Rlcik7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5pc05lZ2F0aXZlU3RyaWN0KG51bWJlck9yTnVtZXJpY1N0cmluZywgbmVnYXRpdmVTaWduQ2hhcmFjdGVyKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBnaXZlbiBzdHJpbmcgY29udGFpbnMgYSBuZWdhdGl2ZSBzaWduIG9uIHRoZSBmaXJzdCBjaGFyYWN0ZXIgKG9uIHRoZSBmYXIgbGVmdCkuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZSBpc05lZ2F0aXZlU3RyaWN0KCcxMjM0LjU2JykgICAgID0+IGZhbHNlXG4gICAgICogQGV4YW1wbGUgaXNOZWdhdGl2ZVN0cmljdCgnMTIzNC41Ni0nKSAgICA9PiBmYWxzZVxuICAgICAqIEBleGFtcGxlIGlzTmVnYXRpdmVTdHJpY3QoJy0xMjM0LjU2JykgICAgPT4gdHJ1ZVxuICAgICAqIEBleGFtcGxlIGlzTmVnYXRpdmVTdHJpY3QoJy0xLDIzNC41NiDigqwnKSA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbnVtZXJpY1N0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgVGhlIHNpbmdsZSBjaGFyYWN0ZXIgdGhhdCByZXByZXNlbnQgdGhlIG5lZ2F0aXZlIHNpZ25cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNOZWdhdGl2ZVN0cmljdChudW1lcmljU3RyaW5nLCBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgPSAnLScpIHtcbiAgICAgICAgcmV0dXJuIG51bWVyaWNTdHJpbmcuY2hhckF0KDApID09PSBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgdmVyeSBmaXJzdCBjaGFyYWN0ZXIgaXMgdGhlIG9wZW5pbmcgYnJhY2tldCwgYW5kIGlmIHRoZSByZXN0IG9mIHRoZSBgdmFsdWVTdHJpbmdgIGFsc28gaGFzIHRoZSBjbG9zaW5nIGJyYWNrZXQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVTdHJpbmdcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGVmdEJyYWNrZXRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcmlnaHRCcmFja2V0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzTmVnYXRpdmVXaXRoQnJhY2tldHModmFsdWVTdHJpbmcsIGxlZnRCcmFja2V0LCByaWdodEJyYWNrZXQpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlU3RyaW5nLmNoYXJBdCgwKSA9PT0gbGVmdEJyYWNrZXQgJiYgdGhpcy5jb250YWlucyh2YWx1ZVN0cmluZywgcmlnaHRCcmFja2V0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBmb3JtYXR0ZWQgb3IgdW5mb3JtYXR0ZWQgbnVtZXJpYyBzdHJpbmcgcmVwcmVzZW50IHRoZSB2YWx1ZSAwIChpZS4gJzAsMDAg4oKsJyksIG9yIGlzIGVtcHR5ICgnIOKCrCcpLlxuICAgICAqIFRoaXMgd29ya3Mgc2luY2Ugd2UgdGVzdCBpZiB0aGVyZSBhcmUgYW55IG51bWJlcnMgZnJvbSAxIHRvIDkgaW4gdGhlIHN0cmluZy4gSWYgdGhlcmUgaXMgbm9uZSwgdGhlbiB0aGUgbnVtYmVyIGlzIHplcm8gKG9yIHRoZSBzdHJpbmcgaXMgZW1wdHkpLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG51bWVyaWNTdHJpbmdcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNaZXJvT3JIYXNOb1ZhbHVlKG51bWVyaWNTdHJpbmcpIHtcbiAgICAgICAgcmV0dXJuICEoL1sxLTldL2cpLnRlc3QobnVtZXJpY1N0cmluZyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBuZWdhdGl2ZSB2ZXJzaW9uIG9mIHRoZSB2YWx1ZSAocmVwcmVzZW50ZWQgYXMgYSBzdHJpbmcpIGdpdmVuIGFzIGEgcGFyYW1ldGVyLlxuICAgICAqIFRoZSBudW1lcmljIHN0cmluZyBpcyBhIHZhbGlkIEphdmFzY3JpcHQgbnVtYmVyIHdoZW4gdHlwZWNhc3QgdG8gYSBgTnVtYmVyYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRSYXdOZWdhdGl2ZVNpZ24odmFsdWUpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzTmVnYXRpdmVTdHJpY3QodmFsdWUsICctJykpIHtcbiAgICAgICAgICAgIHJldHVybiBgLSR7dmFsdWV9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXBsYWNlIHRoZSBjaGFyYWN0ZXIgYXQgdGhlIHBvc2l0aW9uIGBpbmRleGAgaW4gdGhlIHN0cmluZyBgc3RyaW5nYCBieSB0aGUgY2hhcmFjdGVyKHMpIGBuZXdDaGFyYWN0ZXJgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0cmluZ1xuICAgICAqIEBwYXJhbSB7aW50fSBpbmRleFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuZXdDaGFyYWN0ZXJcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyByZXBsYWNlQ2hhckF0KHN0cmluZywgaW5kZXgsIG5ld0NoYXJhY3Rlcikge1xuICAgICAgICByZXR1cm4gYCR7c3RyaW5nLnN1YnN0cigwLCBpbmRleCl9JHtuZXdDaGFyYWN0ZXJ9JHtzdHJpbmcuc3Vic3RyKGluZGV4ICsgbmV3Q2hhcmFjdGVyLmxlbmd0aCl9YDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIHZhbHVlIGNsYW1wZWQgdG8gdGhlIG5lYXJlc3QgbWluaW11bS9tYXhpbXVtIHZhbHVlLCBhcyBkZWZpbmVkIGluIHRoZSBzZXR0aW5ncy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bWJlcn0gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIHN0YXRpYyBjbGFtcFRvUmFuZ2VMaW1pdHModmFsdWUsIHNldHRpbmdzKSB7XG4gICAgICAgIC8vWFhYIFRoaXMgZnVuY3Rpb24gYWx3YXlzIGFzc3VtZSBgc2V0dGluZ3MubWluaW11bVZhbHVlYCBpcyBsb3dlciB0aGFuIGBzZXR0aW5ncy5tYXhpbXVtVmFsdWVgXG4gICAgICAgIHJldHVybiBNYXRoLm1heChzZXR0aW5ncy5taW5pbXVtVmFsdWUsIE1hdGgubWluKHNldHRpbmdzLm1heGltdW1WYWx1ZSwgdmFsdWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIG51bWJlciBvZiBudW1iZXIgb3IgZG90IGNoYXJhY3RlcnMgb24gdGhlIGxlZnQgc2lkZSBvZiB0aGUgY2FyZXQsIGluIGEgZm9ybWF0dGVkIG51bWJlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBmb3JtYXR0ZWROdW1iZXJTdHJpbmdcbiAgICAgKiBAcGFyYW0ge2ludH0gY2FyZXRQb3NpdGlvbiBUaGlzIG11c3QgYmUgYSBwb3NpdGl2ZSBpbnRlZ2VyXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGRlY2ltYWxDaGFyYWN0ZXJcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIHN0YXRpYyBjb3VudE51bWJlckNoYXJhY3RlcnNPblRoZUNhcmV0TGVmdFNpZGUoZm9ybWF0dGVkTnVtYmVyU3RyaW5nLCBjYXJldFBvc2l0aW9uLCBkZWNpbWFsQ2hhcmFjdGVyKSB7XG4gICAgICAgIC8vIEhlcmUgd2UgY291bnQgdGhlIGRvdCBhbmQgcmVwb3J0IGl0IGFzIGEgbnVtYmVyIGNoYXJhY3RlciB0b28sIHNpbmNlIGl0IHdpbGwgJ3N0YXknIGluIHRoZSBKYXZhc2NyaXB0IG51bWJlciB3aGVuIHVuZm9ybWF0dGVkXG4gICAgICAgIGNvbnN0IG51bWJlckRvdE9yTmVnYXRpdmVTaWduID0gbmV3IFJlZ0V4cChgWzAtOSR7ZGVjaW1hbENoYXJhY3Rlcn0tXWApOyAvLyBObyBuZWVkIHRvIGVzY2FwZSB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgaGVyZSwgc2luY2UgaXQncyBpbiBgW11gXG5cbiAgICAgICAgbGV0IG51bWJlckRvdEFuZE5lZ2F0aXZlU2lnbkNvdW50ID0gMDtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBjYXJldFBvc2l0aW9uOyBpKyspIHtcbiAgICAgICAgICAgIC8vIFRlc3QgaWYgdGhlIGNoYXJhY3RlciBpcyBhIG51bWJlciwgYSBkb3Qgb3IgYW4gaHlwaGVuLiBJZiBpdCBpcywgY291bnQgaXQsIG90aGVyd2lzZSBpZ25vcmUgaXRcbiAgICAgICAgICAgIGlmIChudW1iZXJEb3RPck5lZ2F0aXZlU2lnbi50ZXN0KGZvcm1hdHRlZE51bWJlclN0cmluZ1tpXSkpIHtcbiAgICAgICAgICAgICAgICBudW1iZXJEb3RBbmROZWdhdGl2ZVNpZ25Db3VudCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bWJlckRvdEFuZE5lZ2F0aXZlU2lnbkNvdW50O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFdhbGsgdGhlIGBmb3JtYXR0ZWROdW1iZXJTdHJpbmdgIGZyb20gbGVmdCB0byByaWdodCwgb25lIGNoYXIgYnkgb25lLCBjb3VudGluZyB0aGUgYGZvcm1hdHRlZE51bWJlclN0cmluZ0luZGV4YC5cbiAgICAgKiBJZiB0aGUgY2hhciBpcyBpbiB0aGUgYHJhd051bWJlclN0cmluZ2AgKHN0YXJ0aW5nIGF0IGluZGV4IDApLCB0aGVuIGByYXdOdW1iZXJTdHJpbmdJbmRleCsrYCwgYW5kIGNvbnRpbnVlIHVudGlsXG4gICAgICogdGhlcmUgaXMgbm8gbW9yZSBjaGFyYWN0ZXJzIGluIGByYXdOdW1iZXJTdHJpbmdgKSBvciB0aGF0IGByYXdOdW1iZXJTdHJpbmdJbmRleCA9PT0gY2FyZXRQb3NpdGlvbkluUmF3VmFsdWVgLlxuICAgICAqIFdoZW4geW91IHN0b3AsIHRoZSBgZm9ybWF0dGVkTnVtYmVyU3RyaW5nSW5kZXhgIGlzIHRoZSBwb3NpdGlvbiB3aGVyZSB0aGUgY2FyZXQgc2hvdWxkIGJlIHNldC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogMTIzNDU2N3w4OS4wMSAgIDogcG9zaXRpb24gNyAocmF3TnVtYmVyU3RyaW5nKVxuICAgICAqIDEyMy40NTYuN3w4OSwwMSA6IHBvc2l0aW9uIDkgKGZvcm1hdHRlZE51bWJlclN0cmluZylcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSByYXdOdW1iZXJTdHJpbmdcbiAgICAgKiBAcGFyYW0ge2ludH0gY2FyZXRQb3NpdGlvbkluUmF3VmFsdWVcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZm9ybWF0dGVkTnVtYmVyU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGRlY2ltYWxDaGFyYWN0ZXJcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgZmluZENhcmV0UG9zaXRpb25JbkZvcm1hdHRlZE51bWJlcihyYXdOdW1iZXJTdHJpbmcsIGNhcmV0UG9zaXRpb25JblJhd1ZhbHVlLCBmb3JtYXR0ZWROdW1iZXJTdHJpbmcsIGRlY2ltYWxDaGFyYWN0ZXIpIHtcbiAgICAgICAgY29uc3QgZm9ybWF0dGVkTnVtYmVyU3RyaW5nU2l6ZSA9IGZvcm1hdHRlZE51bWJlclN0cmluZy5sZW5ndGg7XG4gICAgICAgIGNvbnN0IHJhd051bWJlclN0cmluZ1NpemUgPSByYXdOdW1iZXJTdHJpbmcubGVuZ3RoO1xuXG4gICAgICAgIGxldCBmb3JtYXR0ZWROdW1iZXJTdHJpbmdJbmRleDtcbiAgICAgICAgbGV0IHJhd051bWJlclN0cmluZ0luZGV4ID0gMDtcbiAgICAgICAgZm9yIChmb3JtYXR0ZWROdW1iZXJTdHJpbmdJbmRleCA9IDA7XG4gICAgICAgICAgICBmb3JtYXR0ZWROdW1iZXJTdHJpbmdJbmRleCA8IGZvcm1hdHRlZE51bWJlclN0cmluZ1NpemUgJiZcbiAgICAgICAgICAgIHJhd051bWJlclN0cmluZ0luZGV4IDwgcmF3TnVtYmVyU3RyaW5nU2l6ZSAmJlxuICAgICAgICAgICAgcmF3TnVtYmVyU3RyaW5nSW5kZXggPCBjYXJldFBvc2l0aW9uSW5SYXdWYWx1ZTtcbiAgICAgICAgICAgIGZvcm1hdHRlZE51bWJlclN0cmluZ0luZGV4KyspIHtcbiAgICAgICAgICAgIGlmIChyYXdOdW1iZXJTdHJpbmdbcmF3TnVtYmVyU3RyaW5nSW5kZXhdID09PSBmb3JtYXR0ZWROdW1iZXJTdHJpbmdbZm9ybWF0dGVkTnVtYmVyU3RyaW5nSW5kZXhdIHx8XG4gICAgICAgICAgICAgICAgKHJhd051bWJlclN0cmluZ1tyYXdOdW1iZXJTdHJpbmdJbmRleF0gPT09ICcuJyAmJiBmb3JtYXR0ZWROdW1iZXJTdHJpbmdbZm9ybWF0dGVkTnVtYmVyU3RyaW5nSW5kZXhdID09PSBkZWNpbWFsQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgIHJhd051bWJlclN0cmluZ0luZGV4Kys7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZm9ybWF0dGVkTnVtYmVyU3RyaW5nSW5kZXg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ291bnQgdGhlIG51bWJlciBvZiBvY2N1cnJlbmNlIG9mIHRoZSBnaXZlbiBjaGFyYWN0ZXIsIGluIHRoZSBnaXZlbiB0ZXh0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGNoYXJhY3RlclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0XG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBzdGF0aWMgY291bnRDaGFySW5UZXh0KGNoYXJhY3RlciwgdGV4dCkge1xuICAgICAgICBsZXQgY2hhckNvdW50ZXIgPSAwO1xuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHRleHQubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgICAgIGlmICh0ZXh0W2ldID09PSBjaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgICAgICBjaGFyQ291bnRlcisrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNoYXJDb3VudGVyO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgaW5kZXggdGhhdCBjYW4gYmUgdXNlZCB0byBzZXQgdGhlIGNhcmV0IHBvc2l0aW9uLlxuICAgICAqIFRoaXMgdGFrZXMgaW50byBhY2NvdW50IHRoYXQgdGhlIHBvc2l0aW9uIGlzIHN0YXJ0aW5nIGF0ICcwJywgbm90IDEuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2ludH0gY2hhcmFjdGVyQ291bnRcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqL1xuICAgIHN0YXRpYyBjb252ZXJ0Q2hhcmFjdGVyQ291bnRUb0luZGV4UG9zaXRpb24oY2hhcmFjdGVyQ291bnQpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgubWF4KGNoYXJhY3RlckNvdW50LCBjaGFyYWN0ZXJDb3VudCAtIDEpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyb3NzIGJyb3dzZXIgcm91dGluZSBmb3IgZ2V0dGluZyBzZWxlY3RlZCByYW5nZS9jdXJzb3IgcG9zaXRpb24uXG4gICAgICogTm90ZTogdGhpcyBhbHNvIHdvcmtzIHdpdGggZWRnZSBjYXNlcyBsaWtlIGNvbnRlbnRlZGl0YWJsZS1lbmFibGVkIGVsZW1lbnRzLCBhbmQgaGlkZGVuIGlucHV0cy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTElucHV0RWxlbWVudHxFdmVudFRhcmdldH0gZWxlbWVudFxuICAgICAqIEByZXR1cm5zIHt7fX1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0RWxlbWVudFNlbGVjdGlvbihlbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IHBvc2l0aW9uID0ge307XG5cbiAgICAgICAgbGV0IGlzU2VsZWN0aW9uU3RhcnRVbmRlZmluZWQ7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpc1NlbGVjdGlvblN0YXJ0VW5kZWZpbmVkID0gdGhpcy5pc1VuZGVmaW5lZChlbGVtZW50LnNlbGVjdGlvblN0YXJ0KTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGlzU2VsZWN0aW9uU3RhcnRVbmRlZmluZWQgPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBpZiAoaXNTZWxlY3Rpb25TdGFydFVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHNlbGVjdGlvbiA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgICAgICAgICBjb25zdCBzZWxlY3Rpb25JbmZvID0gc2VsZWN0aW9uLmdldFJhbmdlQXQoMCk7XG4gICAgICAgICAgICAgICAgcG9zaXRpb24uc3RhcnQgPSBzZWxlY3Rpb25JbmZvLnN0YXJ0T2Zmc2V0O1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uLmVuZCA9IHNlbGVjdGlvbkluZm8uZW5kT2Zmc2V0O1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uLmxlbmd0aCA9IHBvc2l0aW9uLmVuZCAtIHBvc2l0aW9uLnN0YXJ0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbi5zdGFydCA9IGVsZW1lbnQuc2VsZWN0aW9uU3RhcnQ7XG4gICAgICAgICAgICAgICAgcG9zaXRpb24uZW5kID0gZWxlbWVudC5zZWxlY3Rpb25FbmQ7XG4gICAgICAgICAgICAgICAgcG9zaXRpb24ubGVuZ3RoID0gcG9zaXRpb24uZW5kIC0gcG9zaXRpb24uc3RhcnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAvLyBNYW5hZ2VzIHRoZSBjYXNlcyB3aGVyZSA6XG4gICAgICAgICAgICAvLyAtIHRoZSAnY29udGVudGVkaXRhYmxlJyBlbGVtZW50cyB0aGF0IGhhdmUgbm8gc2VsZWN0aW9uc1xuICAgICAgICAgICAgLy8gLSB0aGUgPGlucHV0PiBlbGVtZW50IGlzIG9mIHR5cGUgJ2hpZGRlbidcbiAgICAgICAgICAgIHBvc2l0aW9uLnN0YXJ0ID0gMDtcbiAgICAgICAgICAgIHBvc2l0aW9uLmVuZCA9IDA7XG4gICAgICAgICAgICBwb3NpdGlvbi5sZW5ndGggPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHBvc2l0aW9uO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyb3NzIGJyb3dzZXIgcm91dGluZSBmb3Igc2V0dGluZyBzZWxlY3RlZCByYW5nZS9jdXJzb3IgcG9zaXRpb25cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTElucHV0RWxlbWVudHxFdmVudFRhcmdldH0gZWxlbWVudFxuICAgICAqIEBwYXJhbSB7aW50fSBzdGFydFxuICAgICAqIEBwYXJhbSB7aW50fG51bGx9IGVuZFxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRFbGVtZW50U2VsZWN0aW9uKGVsZW1lbnQsIHN0YXJ0LCBlbmQgPSBudWxsKSB7XG4gICAgICAgIGlmICh0aGlzLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShlbmQpKSB7XG4gICAgICAgICAgICBlbmQgPSBzdGFydDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmlzSW5wdXRFbGVtZW50KGVsZW1lbnQpKSB7XG4gICAgICAgICAgICBlbGVtZW50LnNldFNlbGVjdGlvblJhbmdlKHN0YXJ0LCBlbmQpO1xuICAgICAgICB9IGVsc2UgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoZWxlbWVudC5maXJzdENoaWxkKSkge1xuICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSBkb2N1bWVudC5jcmVhdGVSYW5nZSgpO1xuICAgICAgICAgICAgcmFuZ2Uuc2V0U3RhcnQoZWxlbWVudC5maXJzdENoaWxkLCBzdGFydCk7XG4gICAgICAgICAgICByYW5nZS5zZXRFbmQoZWxlbWVudC5maXJzdENoaWxkLCBlbmQpO1xuICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgICAgICAgICAgc2VsZWN0aW9uLnJlbW92ZUFsbFJhbmdlcygpO1xuICAgICAgICAgICAgc2VsZWN0aW9uLmFkZFJhbmdlKHJhbmdlKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZ1bmN0aW9uIHRoYXQgdGhyb3cgZXJyb3IgbWVzc2FnZXNcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gICAgICogQHRocm93c1xuICAgICAqL1xuICAgIHN0YXRpYyB0aHJvd0Vycm9yKG1lc3NhZ2UpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKG1lc3NhZ2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZ1bmN0aW9uIHRoYXQgZGlzcGxheSBhIHdhcm5pbmcgbWVzc2FnZXMsIGFjY29yZGluZyB0byB0aGUgZGVidWcgbGV2ZWwuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2hvd1dhcm5pbmcgSWYgRkFMU0UsIHRoZW4gdGhlIHdhcm5pbmcgbWVzc2FnZSBpcyBub3QgZGlzcGxheWVkXG4gICAgICovXG4gICAgc3RhdGljIHdhcm5pbmcobWVzc2FnZSwgc2hvd1dhcm5pbmcgPSB0cnVlKSB7XG4gICAgICAgIGlmIChzaG93V2FybmluZykge1xuICAgICAgICAgICAgLyogZXNsaW50IG5vLWNvbnNvbGU6IDAgKi9cbiAgICAgICAgICAgIGNvbnNvbGUud2FybihgV2FybmluZzogJHttZXNzYWdlfWApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gZXZlbnQgaXMgYSB3aGVlbHVwIGV2ZW50XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge1doZWVsRXZlbnR9IHdoZWVsRXZlbnRcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNXaGVlbFVwRXZlbnQod2hlZWxFdmVudCkge1xuICAgICAgICBpZiAoIXdoZWVsRXZlbnQuZGVsdGFZKSB7XG4gICAgICAgICAgICB0aGlzLnRocm93RXJyb3IoYFRoZSBldmVudCBwYXNzZWQgYXMgYSBwYXJhbWV0ZXIgaXMgbm90IGEgdmFsaWQgd2hlZWwgZXZlbnQsICcke3doZWVsRXZlbnQudHlwZX0nIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHdoZWVsRXZlbnQuZGVsdGFZIDwgMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBnaXZlbiBldmVudCBpcyBhIHdoZWVsZG93biBldmVudFxuICAgICAqXG4gICAgICogQHBhcmFtIHtXaGVlbEV2ZW50fSB3aGVlbEV2ZW50XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzV2hlZWxEb3duRXZlbnQod2hlZWxFdmVudCkge1xuICAgICAgICBpZiAoIXdoZWVsRXZlbnQuZGVsdGFZKSB7XG4gICAgICAgICAgICB0aGlzLnRocm93RXJyb3IoYFRoZSBldmVudCBwYXNzZWQgYXMgYSBwYXJhbWV0ZXIgaXMgbm90IGEgdmFsaWQgd2hlZWwgZXZlbnQsICcke3doZWVsRXZlbnQudHlwZX0nIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHdoZWVsRXZlbnQuZGVsdGFZID4gMDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIGdpdmVuIHJhdyB2YWx1ZSB0cnVuY2F0ZWQgYXQgdGhlIGdpdmVuIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBgZGVjaW1hbFBsYWNlc2AuXG4gICAgICogVGhpcyBmdW5jdGlvbiBkb2VzIG5vdCByb3VuZCB0aGUgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIGZvcmNlRGVjaW1hbFBsYWNlcygxMjMuNDU2NzgsIDApIC0+ICcxMjMuNDU2NzgnXG4gICAgICogZm9yY2VEZWNpbWFsUGxhY2VzKDEyMy40NTY3OCwgMSkgLT4gJzEyMy40J1xuICAgICAqIGZvcmNlRGVjaW1hbFBsYWNlcygxMjMuNDU2NzgsIDIpIC0+ICcxMjMuNDUnXG4gICAgICogZm9yY2VEZWNpbWFsUGxhY2VzKDEyMy40NTY3OCwgMykgLT4gJzEyMy40NTYnXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAgICAgKiBAcGFyYW0ge2ludH0gZGVjaW1hbFBsYWNlc1xuICAgICAqIEByZXR1cm5zIHtudW1iZXJ8c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBmb3JjZURlY2ltYWxQbGFjZXModmFsdWUsIGRlY2ltYWxQbGFjZXMpIHtcbiAgICAgICAgLy8gV2UgY291bGQgbWFrZSBzdXJlIGBkZWNpbWFsUGxhY2VzYCBpcyBhbiBpbnRlZ2VyIGFuZCBwb3NpdGl2ZSwgYnV0IHdlJ2xsIGxlYXZlIHRoYXQgdG8gdGhlIGRldiBjYWxsaW5nIHRoaXMgZnVuY3Rpb24uXG4gICAgICAgIGNvbnN0IFtpbnRlZ2VyUGFydCwgZGVjaW1hbFBhcnRdID0gU3RyaW5nKHZhbHVlKS5zcGxpdCgnLicpO1xuICAgICAgICBpZiAoIWRlY2ltYWxQYXJ0KSB7XG4gICAgICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYCR7aW50ZWdlclBhcnR9LiR7ZGVjaW1hbFBhcnQuc3Vic3RyKDAsIGRlY2ltYWxQbGFjZXMpfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSAnbmVhcmVzdCByb3VuZGVkJyB2YWx1ZSwgYWNjb3JkaW5nIHRvIHRoZSBnaXZlbiBzdGVwIHNpemUuXG4gICAgICogQGV4YW1wbGUgcm91bmRUb05lYXJlc3QoMjY0Nzg5LCAxMDAwMCkpID0+IDI2MDAwMFxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHN0ZXBQbGFjZVxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyByb3VuZFRvTmVhcmVzdCh2YWx1ZSwgc3RlcFBsYWNlID0gMTAwMCkge1xuICAgICAgICBpZiAoMCA9PT0gdmFsdWUpIHtcbiAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN0ZXBQbGFjZSA9PT0gMCkge1xuICAgICAgICAgICAgdGhpcy50aHJvd0Vycm9yKCdUaGUgYHN0ZXBQbGFjZWAgdXNlZCB0byByb3VuZCBpcyBlcXVhbCB0byBgMGAuIFRoaXMgdmFsdWUgbXVzdCBub3QgYmUgZXF1YWwgdG8gemVyby4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBNYXRoLnJvdW5kKHZhbHVlIC8gc3RlcFBsYWNlKSAqIHN0ZXBQbGFjZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlICduZWFyZXN0IHJvdW5kZWQnIHZhbHVlIGJ5IGF1dG9tYXRpY2FsbHkgYWRkaW5nIG9yIHN1YnRyYWN0aW5nIHRoZSBjYWxjdWxhdGVkIG9mZnNldCB0byB0aGUgaW5pdGlhbCB2YWx1ZS5cbiAgICAgKiBUaGlzIGlzIGRvbmUgd2l0aG91dCBoYXZpbmcgdG8gcGFzcyBhIHN0ZXAgdG8gdGhpcyBmdW5jdGlvbiwgYW5kIGJhc2VkIG9uIHRoZSBzaXplIG9mIHRoZSBnaXZlbiBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQGV4YW1wbGUgICAgICAgICAgICAgICAgICAgIENhbGN1bGF0ZWQgb2Zmc2V0XG4gICAgICogICAgICAgICAgIDEgLT4gICAgICAgICAgIDEgKDEpXG4gICAgICogICAgICAgICAgMTQgLT4gICAgICAgICAgMTAgKDEwKVxuICAgICAqICAgICAgICAgMTQzIC0+ICAgICAgICAgMTQwICgxMClcbiAgICAgKiAgICAgICAxLjI3OCAtPiAgICAgICAxLjMwMCAoMTAwKVxuICAgICAqICAgICAgMjguNDU2IC0+ICAgICAgMjguNTAwICgxMDApXG4gICAgICogICAgIDI3Ni4zNDUgLT4gICAgIDI3Ni4wMDAgKDEuMDAwKVxuICAgICAqICAgNC41MzQuMDYxIC0+ICAgNC41MzAuMDAwICgxMC4wMDApXG4gICAgICogIDY2LjcyMy44NDQgLT4gIDY2LjcwMC4wMDAgKDEwMC4wMDApXG4gICAgICogMjU3LjgzMy40MTEgLT4gMjU4LjAwMC4wMDAgKDEuMDAwLjAwMClcbiAgICAgKlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgICAgICAgSW5pdGlhbCAgIEFkZGVkICAgT2Zmc2V0XG4gICAgICogMiBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAxLjEyICAgLT4gMi4wMCAgICgxKVxuICAgICAqIDMgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMS4xMjMgIC0+IDIuMDAwICAoMSlcbiAgICAgKlxuICAgICAqIFNwZWNpYWwgY2FzZSB3aGVuIHRoZSBgdmFsdWVgIHRvIHJvdW5kIGlzIGJldHdlZW4gLTEgYW5kIDEsIGV4Y2x1ZGVkIDpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqICAgICBOdW1iZXIgb2YgICAgICAgICAgICAgSW5pdGlhbCAgIFJlc3VsdCAgQ2FsY3VsYXRlZFxuICAgICAqICAgICBkZWNpbWFsIHBsYWNlcyAgICAgICAgdmFsdWUgICAgIChhZGQpICAgb2Zmc2V0XG4gICAgICogMiBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjEyICAgLT4gMC4xMyAgICAoMC4wMSkgOiBNYXRoLnBvdygxMCwgLTIpXG4gICAgICogMiBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjAxICAgLT4gMC4wMiAgICAoMC4wMSlcbiAgICAgKiAyIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMDAgICAtPiAwLjAxICAgICgwLjAxKVxuICAgICAqXG4gICAgICogMyBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjEyMyAgLT4gMC4xMzMgICAoMC4wMSkgIDogTWF0aC5wb3coMTAsIC0yKVxuICAgICAqIDMgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4wMTIgIC0+IDAuMDEzICAgKDAuMDAxKSA6IE1hdGgucG93KDEwLCAtMylcbiAgICAgKiAzIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMDAxICAtPiAwLjAwMSAgICgwLjAwMSlcbiAgICAgKiAzIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMDAwICAtPiAwLjAwMSAgICgwLjAwMSlcbiAgICAgKlxuICAgICAqIDQgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC40MTIzIC0+IDAuNDIwMCAgKDAuMDEpICAgOiBNYXRoLnBvdygxMCwgLTIpXG4gICAgICogNCBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjA0MTIgLT4gMC4wNDIwICAoMC4wMDEpICA6IE1hdGgucG93KDEwLCAtMylcbiAgICAgKiA0IGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMDA0MSAtPiAwLjAwNDIgICgwLjAwMDEpIDogTWF0aC5wb3coMTAsIC00KVxuICAgICAqIDQgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4wMDA0IC0+IDAuMDAwNSAgKDAuMDAwMSlcbiAgICAgKiA0IGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMDAwMCAtPiAwLjAwMDEgICgwLjAwMDEpXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzQWRkaXRpb25cbiAgICAgKiBAcGFyYW0ge2ludH0gZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIFRoZSBwcmVjaXNpb24gbmVlZGVkIGJ5IHRoZSBgcmF3VmFsdWVgXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIG1vZGlmeUFuZFJvdW5kVG9OZWFyZXN0QXV0byh2YWx1ZSwgaXNBZGRpdGlvbiwgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKSB7XG4gICAgICAgIHZhbHVlID0gTnVtYmVyKHRoaXMuZm9yY2VEZWNpbWFsUGxhY2VzKHZhbHVlLCBkZWNpbWFsUGxhY2VzUmF3VmFsdWUpKTsgLy8gTWFrZSBzdXJlIHRoYXQgJzAuMTMwMDAwMDAwMDEnIGlzIGNvbnZlcnRlZCB0byB0aGUgbnVtYmVyIG9mIHJhd1ZhbHVlIGRlY2ltYWwgcGxhY2VzICcwLjEzJ1xuXG4gICAgICAgIGNvbnN0IGFic1ZhbHVlID0gTWF0aC5hYnModmFsdWUpO1xuICAgICAgICBpZiAoYWJzVmFsdWUgPj0gMCAmJiBhYnNWYWx1ZSA8IDEpIHtcbiAgICAgICAgICAgIGNvbnN0IHJhd1ZhbHVlTWluaW11bU9mZnNldCA9IE1hdGgucG93KDEwLCAtZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKTtcbiAgICAgICAgICAgIGlmICh2YWx1ZSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIC8vIDQgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4wMDAwIC0+IDAuMDAwMSAoMC4wMDAxKVxuICAgICAgICAgICAgICAgIHJldHVybiAoaXNBZGRpdGlvbik/cmF3VmFsdWVNaW5pbXVtT2Zmc2V0Oi1yYXdWYWx1ZU1pbmltdW1PZmZzZXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBvZmZzZXQ7XG4gICAgICAgICAgICBjb25zdCBtaW5pbXVtT2Zmc2V0Rmlyc3REZWNpbWFsUGxhY2VJbmRleCA9IGRlY2ltYWxQbGFjZXNSYXdWYWx1ZTtcbiAgICAgICAgICAgIC8vIEZpbmQgd2hlcmUgaXMgdGhlIGZpcnN0IG5vbi16ZXJvIGRlY2ltYWwgcGxhY2VzXG4gICAgICAgICAgICBjb25zdCBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSA9IHRoaXMuaW5kZXhGaXJzdE5vblplcm9EZWNpbWFsUGxhY2UodmFsdWUpO1xuICAgICAgICAgICAgaWYgKGluZGV4Rmlyc3ROb25aZXJvRGVjaW1hbFBsYWNlID49IG1pbmltdW1PZmZzZXRGaXJzdERlY2ltYWxQbGFjZUluZGV4IC0gMSkge1xuICAgICAgICAgICAgICAgIC8qIDQgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4wMDQxIC0+IDAuMDA0MiAoMC4wMDAxKSA6IE1hdGgucG93KDEwLCAtNClcbiAgICAgICAgICAgICAgICAgKiA0IGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMDAwNCAtPiAwLjAwMDUgKDAuMDAwMSlcbiAgICAgICAgICAgICAgICAgKi9cbiAgICAgICAgICAgICAgICBvZmZzZXQgPSByYXdWYWx1ZU1pbmltdW1PZmZzZXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIG9mZnNldCA9IE1hdGgucG93KDEwLCAtKGluZGV4Rmlyc3ROb25aZXJvRGVjaW1hbFBsYWNlICsgMSkpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICAgICAgaWYgKGlzQWRkaXRpb24pIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB2YWx1ZSArIG9mZnNldDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUgLSBvZmZzZXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJvdW5kVG9OZWFyZXN0KHJlc3VsdCwgb2Zmc2V0KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEZvciB2YWx1ZXMgPj0gMVxuICAgICAgICAgICAgdmFsdWUgPSBwYXJzZUludCh2YWx1ZSwgMTApO1xuICAgICAgICAgICAgY29uc3QgbGVuZ3RoVmFsdWUgPSBNYXRoLmFicyh2YWx1ZSkudG9TdHJpbmcoKS5sZW5ndGg7IC8vIGBNYXRoLmFicygpYCBpcyBuZWVkZWQgaGVyZSB0byBvbWl0IHRoZSBuZWdhdGl2ZSBzaWduICctJyBpbiBjYXNlIG9mIGEgbmVnYXRpdmUgdmFsdWVcblxuICAgICAgICAgICAgbGV0IHBvdztcbiAgICAgICAgICAgIHN3aXRjaCAobGVuZ3RoVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2VzIGZvciBzbWFsbCBudW1iZXJzXG4gICAgICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgICAgICBwb3cgPSAwO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDI6XG4gICAgICAgICAgICAgICAgY2FzZSAzOlxuICAgICAgICAgICAgICAgICAgICBwb3cgPSAxO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIDQ6XG4gICAgICAgICAgICAgICAgY2FzZSA1OlxuICAgICAgICAgICAgICAgICAgICBwb3cgPSAyO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAvLyBEZWZhdWx0IGJlaGF2aW9yXG4gICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgcG93ID0gbGVuZ3RoVmFsdWUgLSAzO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3Qgb2Zmc2V0ID0gTWF0aC5wb3coMTAsIHBvdyk7XG5cbiAgICAgICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgICAgICBpZiAoaXNBZGRpdGlvbikge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlICsgb2Zmc2V0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB2YWx1ZSAtIG9mZnNldDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKHJlc3VsdCA8PSAxMCAmJiByZXN1bHQgPj0gLTEwKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRoaXMucm91bmRUb05lYXJlc3QocmVzdWx0LCBvZmZzZXQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSAnbmVhcmVzdCByb3VuZGVkJyB2YWx1ZSBhdXRvbWF0aWNhbGx5IGJ5IGFkZGluZyB0aGUgY2FsY3VsYXRlZCBvZmZzZXQgdG8gdGhlIGluaXRpYWwgdmFsdWUuXG4gICAgICogVGhpcyB3aWxsIGxpbWl0IHRoZSByZXN1bHQgdG8gdGhlIGdpdmVuIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBgZGVjaW1hbFBsYWNlc0xpbWl0YC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7aW50fSBkZWNpbWFsUGxhY2VzTGltaXRcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgYWRkQW5kUm91bmRUb05lYXJlc3RBdXRvKHZhbHVlLCBkZWNpbWFsUGxhY2VzTGltaXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubW9kaWZ5QW5kUm91bmRUb05lYXJlc3RBdXRvKHZhbHVlLCB0cnVlLCBkZWNpbWFsUGxhY2VzTGltaXQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgJ25lYXJlc3Qgcm91bmRlZCcgdmFsdWUgYXV0b21hdGljYWxseSBieSBzdWJ0cmFjdGluZyB0aGUgY2FsY3VsYXRlZCBvZmZzZXQgdG8gdGhlIGluaXRpYWwgdmFsdWUuXG4gICAgICogVGhpcyB3aWxsIGxpbWl0IHRoZSByZXN1bHQgdG8gdGhlIGdpdmVuIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBgZGVjaW1hbFBsYWNlc0xpbWl0YC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7aW50fSBkZWNpbWFsUGxhY2VzTGltaXRcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgc3VidHJhY3RBbmRSb3VuZFRvTmVhcmVzdEF1dG8odmFsdWUsIGRlY2ltYWxQbGFjZXNMaW1pdCkge1xuICAgICAgICByZXR1cm4gdGhpcy5tb2RpZnlBbmRSb3VuZFRvTmVhcmVzdEF1dG8odmFsdWUsIGZhbHNlLCBkZWNpbWFsUGxhY2VzTGltaXQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRha2UgYW4gYXJhYmljIG51bWJlciBhcyBhIHN0cmluZyBhbmQgcmV0dXJuIGEgamF2YXNjcmlwdCBudW1iZXIuXG4gICAgICogQnkgZGVmYXVsdCwgdGhpcyBmdW5jdGlvbiBkb2VzIG5vdCB0cnkgdG8gY29udmVydCB0aGUgYXJhYmljIGRlY2ltYWwgYW5kIHRob3VzYW5kIHNlcGFyYXRvciBjaGFyYWN0ZXJzLlxuICAgICAqIFRoaXMgcmV0dXJucyBgTmFOYCBpcyB0aGUgY29udmVyc2lvbiBpcyBub3QgcG9zc2libGUuXG4gICAgICogQmFzZWQgb24gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMTcwMjUzOTIvMjgzNDg5OFxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGFyYWJpY051bWJlcnNcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHJldHVybkFOdW1iZXIgSWYgYHRydWVgLCByZXR1cm4gYSBOdW1iZXIsIG90aGVyd2lzZSByZXR1cm4gYSBTdHJpbmdcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHBhcnNlRGVjaW1hbENoYXJhY3RlclxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gcGFyc2VUaG91c2FuZFNlcGFyYXRvclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVtYmVyfE5hTn1cbiAgICAgKi9cbiAgICBzdGF0aWMgYXJhYmljVG9MYXRpbk51bWJlcnMoYXJhYmljTnVtYmVycywgcmV0dXJuQU51bWJlciA9IHRydWUsIHBhcnNlRGVjaW1hbENoYXJhY3RlciA9IGZhbHNlLCBwYXJzZVRob3VzYW5kU2VwYXJhdG9yID0gZmFsc2UpIHtcbiAgICAgICAgaWYgKHRoaXMuaXNOdWxsKGFyYWJpY051bWJlcnMpKSB7XG4gICAgICAgICAgICByZXR1cm4gYXJhYmljTnVtYmVycztcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXN1bHQgPSBhcmFiaWNOdW1iZXJzLnRvU3RyaW5nKCk7XG4gICAgICAgIGlmIChyZXN1bHQgPT09ICcnKSB7XG4gICAgICAgICAgICByZXR1cm4gYXJhYmljTnVtYmVycztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXN1bHQubWF0Y2goL1vZoNmh2aLZo9mk2aXZptmn2ajZqdu027Xbtl0vZykgPT09IG51bGwpIHtcbiAgICAgICAgICAgIC8vIElmIG5vIEFyYWJpYy9QZXJzaWFuIG51bWJlcnMgYXJlIGZvdW5kLCByZXR1cm4gdGhlIG51bWVyaWMgc3RyaW5nIG9yIG51bWJlciBkaXJlY3RseVxuICAgICAgICAgICAgaWYgKHJldHVybkFOdW1iZXIpIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBOdW1iZXIocmVzdWx0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJzZURlY2ltYWxDaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKC/Zqy8sICcuJyk7IC8vIERlY2ltYWwgY2hhcmFjdGVyXG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyc2VUaG91c2FuZFNlcGFyYXRvcikge1xuICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnJlcGxhY2UoL9msL2csICcnKTsgLy8gVGhvdXNhbmQgc2VwYXJhdG9yXG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXBsYWNlIHRoZSBudW1iZXJzIG9ubHlcbiAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnJlcGxhY2UoL1vZoNmh2aLZo9mk2aXZptmn2ajZqV0vZywgZCA9PiBkLmNoYXJDb2RlQXQoMCkgLSAxNjMyKSAvLyBBcmFiaWMgbnVtYmVyc1xuICAgICAgICAgICAgLnJlcGxhY2UoL1vbsNux27Lbs9u027Xbttu327jbuV0vZywgZCA9PiBkLmNoYXJDb2RlQXQoMCkgLSAxNzc2KTsgLy8gUGVyc2lhbiBudW1iZXJzXG5cbiAgICAgICAgLy8gYE5hTmAgaGFzIHByZWNlZGVuY2Ugb3ZlciB0aGUgc3RyaW5nIGAnTmFOJ2BcbiAgICAgICAgY29uc3QgcmVzdWx0QXNOdW1iZXIgPSBOdW1iZXIocmVzdWx0KTtcbiAgICAgICAgaWYgKGlzTmFOKHJlc3VsdEFzTnVtYmVyKSkge1xuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdEFzTnVtYmVyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHJldHVybkFOdW1iZXIpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdEFzTnVtYmVyO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGUgYSBjdXN0b20gZXZlbnQgYW5kIGltbWVkaWF0ZWx5IHNlbnQgaXQgZnJvbSB0aGUgZ2l2ZW4gZWxlbWVudC5cbiAgICAgKiBCeSBkZWZhdWx0LCBpZiBubyBlbGVtZW50IGlzIGdpdmVuLCB0aGUgZXZlbnQgaXMgdGhyb3duIGZyb20gYGRvY3VtZW50YC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxEb2N1bWVudHxFdmVudFRhcmdldH0gZWxlbWVudFxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBkZXRhaWxcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGJ1YmJsZXMgU2V0IHRvIGB0cnVlYCBpZiB0aGUgZXZlbnQgbXVzdCBidWJibGUgdXBcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGNhbmNlbGFibGUgU2V0IHRvIGB0cnVlYCBpZiB0aGUgZXZlbnQgbXVzdCBiZSBjYW5jZWxhYmxlXG4gICAgICovXG4gICAgc3RhdGljIHRyaWdnZXJFdmVudChldmVudE5hbWUsIGVsZW1lbnQgPSBkb2N1bWVudCwgZGV0YWlsID0gbnVsbCwgYnViYmxlcyA9IHRydWUsIGNhbmNlbGFibGUgPSB0cnVlKSB7XG4gICAgICAgIGxldCBldmVudDtcbiAgICAgICAgaWYgKHdpbmRvdy5DdXN0b21FdmVudCkge1xuICAgICAgICAgICAgZXZlbnQgPSBuZXcgQ3VzdG9tRXZlbnQoZXZlbnROYW1lLCB7IGRldGFpbCwgYnViYmxlcyAsIGNhbmNlbGFibGUgfSk7IC8vIFRoaXMgaXMgbm90IHN1cHBvcnRlZCBieSBkZWZhdWx0IGJ5IElFIDsgV2UgdXNlIHRoZSBwb2x5ZmlsbCBmb3IgSUU5IGFuZCBsYXRlci5cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGV2ZW50ID0gZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ0N1c3RvbUV2ZW50Jyk7XG4gICAgICAgICAgICBldmVudC5pbml0Q3VzdG9tRXZlbnQoZXZlbnROYW1lLCBidWJibGVzLCBjYW5jZWxhYmxlLCB7IGRldGFpbCB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGVsZW1lbnQuZGlzcGF0Y2hFdmVudChldmVudCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRnVuY3Rpb24gdG8gcGFyc2UgbWluaW11bVZhbHVlLCBtYXhpbXVtVmFsdWUgJiB0aGUgaW5wdXQgdmFsdWUgdG8gcHJlcGFyZSBmb3IgdGVzdGluZyB0byBkZXRlcm1pbmUgaWYgdGhlIHZhbHVlIGZhbGxzIHdpdGhpbiB0aGUgbWluIC8gbWF4IHJhbmdlLlxuICAgICAqIFJldHVybiBhbiBvYmplY3QgZXhhbXBsZTogbWluaW11bVZhbHVlOiBcIjk5OTk5OTk5OTk5OTk5OS45OVwiIHJldHVybnMgdGhlIGZvbGxvd2luZyBcIntzOiAtMSwgZTogMTIsIGM6IEFycmF5WzE1XX1cIi5cbiAgICAgKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgYWRhcHRlZCBmcm9tIEJpZy5qcyBodHRwczovL2dpdGh1Yi5jb20vTWlrZU1jbC9iaWcuanMvLiBNYW55IHRoYW5rcyB0byBNaWtlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfSBuIEEgbnVtZXJpYyB2YWx1ZS5cbiAgICAgKiBAcmV0dXJucyB7e319XG4gICAgICovXG4gICAgc3RhdGljIHBhcnNlU3RyKG4pIHtcbiAgICAgICAgY29uc3QgeCA9IHt9OyAvLyBBIEJpZyBudW1iZXIgaW5zdGFuY2UuXG4gICAgICAgIGxldCBlO1xuICAgICAgICBsZXQgaTtcbiAgICAgICAgbGV0IG5MO1xuICAgICAgICBsZXQgajtcblxuICAgICAgICAvLyBNaW51cyB6ZXJvP1xuICAgICAgICBpZiAobiA9PT0gMCAmJiAxIC8gbiA8IDApIHtcbiAgICAgICAgICAgIG4gPSAnLTAnO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGV0ZXJtaW5lIHNpZ24uIDEgcG9zaXRpdmUsIC0xIG5lZ2F0aXZlXG4gICAgICAgIG4gPSBuLnRvU3RyaW5nKCk7XG4gICAgICAgIGlmICh0aGlzLmlzTmVnYXRpdmVTdHJpY3QobiwgJy0nKSkge1xuICAgICAgICAgICAgbiA9IG4uc2xpY2UoMSk7XG4gICAgICAgICAgICB4LnMgPSAtMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHgucyA9IDE7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZWNpbWFsIHBvaW50P1xuICAgICAgICBlID0gbi5pbmRleE9mKCcuJyk7XG4gICAgICAgIGlmIChlID4gLTEpIHtcbiAgICAgICAgICAgIG4gPSBuLnJlcGxhY2UoJy4nLCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBMZW5ndGggb2Ygc3RyaW5nIGlmIG5vIGRlY2ltYWwgY2hhcmFjdGVyXG4gICAgICAgIGlmIChlIDwgMCkge1xuICAgICAgICAgICAgLy8gSW50ZWdlclxuICAgICAgICAgICAgZSA9IG4ubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGV0ZXJtaW5lIGxlYWRpbmcgemVyb3NcbiAgICAgICAgaSA9IChuLnNlYXJjaCgvWzEtOV0vaSkgPT09IC0xKSA/IG4ubGVuZ3RoIDogbi5zZWFyY2goL1sxLTldL2kpO1xuICAgICAgICBuTCA9IG4ubGVuZ3RoO1xuICAgICAgICBpZiAoaSA9PT0gbkwpIHtcbiAgICAgICAgICAgIC8vIFplcm9cbiAgICAgICAgICAgIHguZSA9IDA7XG4gICAgICAgICAgICB4LmMgPSBbMF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBEZXRlcm1pbmUgdHJhaWxpbmcgemVyb3NcbiAgICAgICAgICAgIGZvciAoaiA9IG5MIC0gMTsgbi5jaGFyQXQoaikgPT09ICcwJzsgaiAtPSAxKSB7XG4gICAgICAgICAgICAgICAgbkwgLT0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5MIC09IDE7XG5cbiAgICAgICAgICAgIC8vIERlY2ltYWwgbG9jYXRpb25cbiAgICAgICAgICAgIHguZSA9IGUgLSBpIC0gMTtcbiAgICAgICAgICAgIHguYyA9IFtdO1xuXG4gICAgICAgICAgICAvLyBDb252ZXJ0IHN0cmluZyB0byBhcnJheSBvZiBkaWdpdHMgd2l0aG91dCBsZWFkaW5nL3RyYWlsaW5nIHplcm9zXG4gICAgICAgICAgICBmb3IgKGUgPSAwOyBpIDw9IG5MOyBpICs9IDEpIHtcbiAgICAgICAgICAgICAgICB4LmNbZV0gPSArbi5jaGFyQXQoaSk7XG4gICAgICAgICAgICAgICAgZSArPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRnVuY3Rpb24gdG8gdGVzdCBpZiB0aGUgaW5wdXQgdmFsdWUgZmFsbHMgd2l0aCB0aGUgTWluIC8gTWF4IHNldHRpbmdzLlxuICAgICAqIFRoaXMgdXNlcyB0aGUgcGFyc2VkIHN0cmluZ3MgZm9yIHRoZSBhYm92ZSBwYXJzZVN0ciBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgYWRhcHRlZCBmcm9tIEJpZy5qcyBodHRwczovL2dpdGh1Yi5jb20vTWlrZU1jbC9iaWcuanMvLiBNYW55IHRoYW5rcyB0byBNaWtlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHkgQmlnIG51bWJlciBpbnN0YW5jZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSB4IEJpZyBudW1iZXIgaW5zdGFuY2VcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgdGVzdE1pbk1heCh5LCB4KSB7XG4gICAgICAgIGNvbnN0IHhjID0geC5jO1xuICAgICAgICBjb25zdCB5YyA9IHkuYztcbiAgICAgICAgbGV0IGkgPSB4LnM7XG4gICAgICAgIGxldCBqID0geS5zO1xuICAgICAgICBsZXQgayA9IHguZTtcbiAgICAgICAgbGV0IGwgPSB5LmU7XG5cbiAgICAgICAgLy8gRWl0aGVyIHplcm8/XG4gICAgICAgIGlmICgheGNbMF0gfHwgIXljWzBdKSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICAgICAgaWYgKCF4Y1swXSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9ICF5Y1swXT8wOi1qO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNpZ25zIGRpZmZlcj9cbiAgICAgICAgaWYgKGkgIT09IGopIHtcbiAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHhOZWcgPSBpIDwgMDtcblxuICAgICAgICAvLyBDb21wYXJlIGV4cG9uZW50c1xuICAgICAgICBpZiAoayAhPT0gbCkge1xuICAgICAgICAgICAgcmV0dXJuIChrID4gbCBeIHhOZWcpPzE6LTE7XG4gICAgICAgIH1cbiAgICAgICAgaSA9IC0xO1xuICAgICAgICBrID0geGMubGVuZ3RoO1xuICAgICAgICBsID0geWMubGVuZ3RoO1xuICAgICAgICBqID0gKGsgPCBsKSA/IGsgOiBsO1xuXG4gICAgICAgIC8vIENvbXBhcmUgZGlnaXQgYnkgZGlnaXRcbiAgICAgICAgZm9yIChpICs9IDE7IGkgPCBqOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGlmICh4Y1tpXSAhPT0geWNbaV0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHhjW2ldID4geWNbaV0gXiB4TmVnKT8xOi0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29tcGFyZSBsZW5ndGhzXG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIGlmIChrID09PSBsKSB7XG4gICAgICAgICAgICByZXN1bHQgPSAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gKGsgPiBsIF4geE5lZyk/MTotMTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYSByYW5kb20gc3RyaW5nLlxuICAgICAqIGNmLiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS84MDg0MjQ4LzI4MzQ4OThcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBzdHJMZW5ndGggTGVuZ3RoIG9mIHRoZSBnZW5lcmF0ZWQgc3RyaW5nIChpbiBjaGFyYWN0ZXIgY291bnQpXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgcmFuZG9tU3RyaW5nKHN0ckxlbmd0aCA9IDUpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgucmFuZG9tKClcbiAgICAgICAgICAgIC50b1N0cmluZygzNilcbiAgICAgICAgICAgIC5zdWJzdHIoMiwgc3RyTGVuZ3RoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIERPTSBlbGVtZW50IHdoZW4gcGFzc2VkIGVpdGhlciBhIERPTSBlbGVtZW50IG9yIGEgc2VsZWN0b3Igc3RyaW5nLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxzdHJpbmd9IGRvbUVsZW1lbnRPclNlbGVjdG9yXG4gICAgICogQHJldHVybnMge0hUTUxFbGVtZW50fVxuICAgICAqL1xuICAgIHN0YXRpYyBkb21FbGVtZW50KGRvbUVsZW1lbnRPclNlbGVjdG9yKSB7XG4gICAgICAgIGxldCBkb21FbGVtZW50O1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcoZG9tRWxlbWVudE9yU2VsZWN0b3IpKSB7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3Rvcihkb21FbGVtZW50T3JTZWxlY3Rvcik7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9tRWxlbWVudE9yU2VsZWN0b3I7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gZG9tRWxlbWVudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZSB0aGUgY3VycmVudCBlbGVtZW50IHZhbHVlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fEV2ZW50VGFyZ2V0fSBlbGVtZW50XG4gICAgICogQHJldHVybnMge251bWJlcnxzdHJpbmd8bnVsbH1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0RWxlbWVudFZhbHVlKGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnaW5wdXQnKSB7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudC52YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnRleHQoZWxlbWVudCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTW9kaWZ5IHRoZSBlbGVtZW50IHZhbHVlIGRpcmVjdGx5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBlbGVtZW50XG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfG51bGx9IHZhbHVlXG4gICAgICovXG4gICAgc3RhdGljIHNldEVsZW1lbnRWYWx1ZShlbGVtZW50LCB2YWx1ZSA9IG51bGwpIHtcbiAgICAgICAgaWYgKGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnaW5wdXQnKSB7XG4gICAgICAgICAgICBlbGVtZW50LnZhbHVlID0gdmFsdWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbGVtZW50LnRleHRDb250ZW50ID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGNsb25lIHRoZSBnaXZlbiBvYmplY3QsIGFuZCByZXR1cm4gaXQuXG4gICAgICogV0FSTklORzogVGhpcyBkb2VzIG5vdCBkbyBhIGRlZXAgY2xvbmluZy5cbiAgICAgKiBjZi4gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvT2JqZWN0L2Fzc2lnbiNFeGFtcGxlc1xuICAgICAqIC8vVE9ETyBBZGQgYSBgZGVlcGAgb3B0aW9uIHRvIGNsb25lIG9iamVjdCB3aXRoIG1vcmUgdGhhbiBvbmUgZGVwdGhcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvYmpcbiAgICAgKiBAcmV0dXJucyB7b2JqZWN0fVxuICAgICAqL1xuICAgIHN0YXRpYyBjbG9uZU9iamVjdChvYmopIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIG9iaik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGEgJ2NhbWVsaXplZCcgdmVyc2lvbiBvZiB0aGUgZ2l2ZW4gc3RyaW5nLlxuICAgICAqIEJ5IGRlZmF1bHQsIHRoaXMgYXNzdW1lIHRoYXQgOlxuICAgICAqIC0gdGhlIHNlcGFyYXRvcnMgYXJlIGh5cGhlbnMgJy0nLFxuICAgICAqIC0gdGhlICdkYXRhLScgc3RyaW5nIHNob3VsZCBiZSByZW1vdmVkLCBhbmRcbiAgICAgKiAtIHRoYXQgdGhlIHZlcnkgZmlyc3Qgd29yZCBzaG91bGQgbm90IGJlIGNhcGl0YWxpemVkLlxuICAgICAqXG4gICAgICogQGV4YW1wbGUgY2FtZWxpemUoJ2RhdGEtY3VycmVuY3ktc3ltYm9sJykgPT4gJ2N1cnJlbmN5U3ltYm9sJ1xuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0ciBUZXh0IHRvIGNhbWVsaXplXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlcGFyYXRvciBDaGFyYWN0ZXIgdGhhdCBzZXBhcmF0ZSBlYWNoIHdvcmRcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHJlbW92ZURhdGEgSWYgc2V0IHRvIGB0cnVlYCwgcmVtb3ZlIHRoZSBgZGF0YS1gIHBhcnQgdGhhdCB5b3UgY2FuIGZpbmQgb24gc29tZSBodG1sIGF0dHJpYnV0ZXNcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNraXBGaXJzdFdvcmQgSWYgc2V0IHRvIGB0cnVlYCwgZG8gbm90IGNhcGl0YWxpemUgdGhlIHZlcnkgZmlyc3Qgd29yZFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH1cbiAgICAgKi9cbiAgICBzdGF0aWMgY2FtZWxpemUoc3RyLCBzZXBhcmF0b3IgPSAnLScsIHJlbW92ZURhdGEgPSB0cnVlLCBza2lwRmlyc3RXb3JkID0gdHJ1ZSkge1xuICAgICAgICBpZiAodGhpcy5pc051bGwoc3RyKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmVtb3ZlRGF0YSkge1xuICAgICAgICAgICAgc3RyID0gc3RyLnJlcGxhY2UoL15kYXRhLS8sICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEN1dCB0aGUgc3RyaW5nIGludG8gd29yZHNcbiAgICAgICAgY29uc3Qgd29yZHMgPSBzdHIuc3BsaXQoc2VwYXJhdG9yKTtcblxuICAgICAgICAvLyBDYXBpdGFsaXplIGVhY2ggd29yZFxuICAgICAgICBsZXQgcmVzdWx0ID0gd29yZHMubWFwKHdvcmQgPT4gYCR7d29yZC5jaGFyQXQoMCkudG9VcHBlckNhc2UoKX0ke3dvcmQuc2xpY2UoMSl9YCk7XG5cbiAgICAgICAgLy8gVGhlbiBjb25jYXRlbmF0ZSB0aGVtIGJhY2tcbiAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmpvaW4oJycpO1xuXG4gICAgICAgIGlmIChza2lwRmlyc3RXb3JkKSB7XG4gICAgICAgICAgICAvLyBTa2lwIHRoZSB2ZXJ5IGZpcnN0IGxldHRlclxuICAgICAgICAgICAgcmVzdWx0ID0gYCR7cmVzdWx0LmNoYXJBdCgwKS50b0xvd2VyQ2FzZSgpfSR7cmVzdWx0LnNsaWNlKDEpfWA7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgdGV4dCBjb21wb25lbnQgb2YgdGhlIGdpdmVuIERPTSBlbGVtZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtFbGVtZW50fSBkb21FbGVtZW50XG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgdGV4dChkb21FbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IG5vZGVUeXBlID0gZG9tRWxlbWVudC5ub2RlVHlwZTtcblxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICAvLyBjZi4gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL05vZGUvbm9kZVR5cGVcbiAgICAgICAgaWYgKG5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERSB8fFxuICAgICAgICAgICAgbm9kZVR5cGUgPT09IE5vZGUuRE9DVU1FTlRfTk9ERSB8fFxuICAgICAgICAgICAgbm9kZVR5cGUgPT09IE5vZGUuRE9DVU1FTlRfRlJBR01FTlRfTk9ERSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gZG9tRWxlbWVudC50ZXh0Q29udGVudDtcbiAgICAgICAgfSBlbHNlIGlmIChub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGRvbUVsZW1lbnQubm9kZVZhbHVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gJyc7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgdGV4dCBjb250ZW50IG9mIHRoZSBnaXZlbiBET00gZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge0VsZW1lbnR9IGRvbUVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dFxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRUZXh0KGRvbUVsZW1lbnQsIHRleHQpIHtcbiAgICAgICAgY29uc3Qgbm9kZVR5cGUgPSBkb21FbGVtZW50Lm5vZGVUeXBlO1xuICAgICAgICBpZiAobm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFIHx8XG4gICAgICAgICAgICBub2RlVHlwZSA9PT0gTm9kZS5ET0NVTUVOVF9OT0RFIHx8XG4gICAgICAgICAgICBub2RlVHlwZSA9PT0gTm9kZS5ET0NVTUVOVF9GUkFHTUVOVF9OT0RFKSB7XG4gICAgICAgICAgICBkb21FbGVtZW50LnRleHRDb250ZW50ID0gdGV4dDtcbiAgICAgICAgfVxuICAgICAgICAvL1RPRE8gRGlzcGxheSBhIHdhcm5pbmcgaWYgdGhhdCBmdW5jdGlvbiBkb2VzIG5vdCBkbyBhbnl0aGluZz9cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaWx0ZXIgb3V0IHRoZSBnaXZlbiBgYXJyYCBhcnJheSB3aXRoIHRoZSBlbGVtZW50cyBmb3VuZCBpbiBgZXhjbHVkZWRFbGVtZW50c2AuXG4gICAgICogVGhpcyByZXR1cm5zIGEgbmV3IGFycmF5IGFuZCBkb2VzIG5vdCBtb2RpZnkgdGhlIHNvdXJjZS5cbiAgICAgKiBjZi4gdmVyaWZpY2F0aW9uIGhlcmUgOiBodHRwOi8vY29kZXBlbi5pby9Bbm90aGVyTGludXhVc2VyL3Blbi9YcHZyTWc/ZWRpdG9ycz0wMDEyXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBleGNsdWRlZEVsZW1lbnRzXG4gICAgICogQHJldHVybnMgeyp8QXJyYXkuPFQ+fVxuICAgICAqL1xuICAgIHN0YXRpYyBmaWx0ZXJPdXQoYXJyLCBleGNsdWRlZEVsZW1lbnRzKSB7XG4gICAgICAgIHJldHVybiBhcnIuZmlsdGVyKGVsZW1lbnQgPT4gIXRoaXMuaXNJbkFycmF5KGVsZW1lbnQsIGV4Y2x1ZGVkRWxlbWVudHMpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIHRyYWlsaW5nIHplcm9zIGluIHRoZSBkZWNpbWFsIHBhcnQgb2YgYSBudW1iZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbnVtZXJpY1N0cmluZ1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyB0cmltUGFkZGVkWmVyb3NGcm9tRGVjaW1hbFBsYWNlcyhudW1lcmljU3RyaW5nKSB7XG4gICAgICAgIG51bWVyaWNTdHJpbmcgPSBTdHJpbmcobnVtZXJpY1N0cmluZyk7XG4gICAgICAgIGlmIChudW1lcmljU3RyaW5nID09PSAnJykge1xuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgW2ludGVnZXJQYXJ0LCBkZWNpbWFsUGFydF0gPSBudW1lcmljU3RyaW5nLnNwbGl0KCcuJyk7XG4gICAgICAgIGlmICh0aGlzLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShkZWNpbWFsUGFydCkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnRlZ2VyUGFydDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHRyaW1tZWREZWNpbWFsUGFydCA9IGRlY2ltYWxQYXJ0LnJlcGxhY2UoLzArJC9nLCAnJyk7XG5cbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKHRyaW1tZWREZWNpbWFsUGFydCA9PT0gJycpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGludGVnZXJQYXJ0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gYCR7aW50ZWdlclBhcnR9LiR7dHJpbW1lZERlY2ltYWxQYXJ0fWA7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgdG9wLW1vc3QgaG92ZXJlZCBpdGVtIGJ5IHRoZSBtb3VzZSBjdXJzb3IuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0SG92ZXJlZEVsZW1lbnQoKSB7XG4gICAgICAgIGNvbnN0IGhvdmVyZWRFbGVtZW50cyA9IFsuLi5kb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCc6aG92ZXInKV07XG4gICAgICAgIHJldHVybiBob3ZlcmVkRWxlbWVudHNbaG92ZXJlZEVsZW1lbnRzLmxlbmd0aCAtIDFdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgZ2l2ZW4gYXJyYXkgdHJpbW1lZCB0byB0aGUgZ2l2ZW4gbGVuZ3RoLlxuICAgICAqIEBleGFtcGxlIGFycmF5VHJpbShbMSwgMiwgMywgNF0sIDIpIC0+IFsxLCAyXVxuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXlcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbGVuZ3RoXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIGFycmF5VHJpbShhcnJheSwgbGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IGFyckxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcbiAgICAgICAgaWYgKGFyckxlbmd0aCA9PT0gMCB8fCBsZW5ndGggPiBhcnJMZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIEFsc28gbWFuYWdlIHRoZSBjYXNlIHdoZXJlIGBsZW5ndGhgIGlzIGhpZ2hlciB0aGFuIHRoZSBjdXJyZW50IGxlbmd0aFxuICAgICAgICAgICAgcmV0dXJuIGFycmF5O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxlbmd0aCA8IDApIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGFycmF5Lmxlbmd0aCA9IHBhcnNlSW50KGxlbmd0aCwgMTApO1xuXG4gICAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXJnZSBhbGwgdGhlIGdpdmVuIGFycmF5cyBieSBrZWVwaW5nIG9ubHkgdW5pcXVlIGVsZW1lbnRzLCBhbmQgcmV0dXJuIGFuIGFycmF5IHdpdGggZGUtZHVwbGljYXRlZCB2YWx1ZXMuXG4gICAgICogY2YuIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzI3NjY0OTcxLzI4MzQ4OThcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Li4uYXJyYXl9IGFycmF5c1xuICAgICAqIEByZXR1cm5zIHtbKl19XG4gICAgICovXG4gICAgc3RhdGljIGFycmF5VW5pcXVlKC4uLmFycmF5cykgeyAvL0ZJWE1FIMOgIHRlc3RlclxuICAgICAgICByZXR1cm4gWy4uLm5ldyBTZXQoW10uY29uY2F0KC4uLmFycmF5cykpXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXJnZSBhbGwgdGhlIGdpdmVuIE1hcHMgYnkga2VlcGluZyBvbmx5IHVuaXF1ZSBlbGVtZW50cywgYW5kIHJldHVybiBhIG5ldyBNYXAgd2l0aCBkZS1kdXBsaWNhdGVkIGtleXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gey4uLk1hcH0gbWFwT2JqZWN0c1xuICAgICAqIEByZXR1cm5zIHtNYXB9XG4gICAgICovXG4gICAgc3RhdGljIG1lcmdlTWFwcyguLi5tYXBPYmplY3RzKSB7XG4gICAgICAgIHJldHVybiBuZXcgTWFwKG1hcE9iamVjdHMucmVkdWNlKChhcywgYikgPT4gYXMuY29uY2F0KFsuLi5iXSksIFtdKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VhcmNoIHRoZSBnaXZlbiBgdmFsdWVgIGluIHRoZSBvYmplY3QgYG9iamAsIGFuZCByZXR1cm4gdGhlIHZlcnkgZmlyc3Qga2V5IGl0IGZpbmRzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb2JqXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfSB2YWx1ZVxuICAgICAqIEByZXR1cm5zIHsqfG51bGx9XG4gICAgICovXG4gICAgc3RhdGljIG9iamVjdEtleUxvb2t1cChvYmosIHZhbHVlKSB7XG4gICAgICAgIGNvbnN0IHJlc3VsdCA9IE9iamVjdC5lbnRyaWVzKG9iaikuZmluZChhcnJheSA9PiBhcnJheVsxXSA9PT0gdmFsdWUpO1xuICAgICAgICBsZXQga2V5ID0gbnVsbDtcbiAgICAgICAgaWYgKHJlc3VsdCAhPT0gdm9pZCgwKSkge1xuICAgICAgICAgICAga2V5ID0gcmVzdWx0WzBdO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGtleTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbnNlcnQgdGhlIHNpbmdsZSBjaGFyYWN0ZXIgYGNoYXJgIGluIHRoZSBzdHJpbmcgYHN0cmAgYXQgdGhlIGdpdmVuIHBvc2l0aW9uIGBpbmRleGBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY2hhclxuICAgICAqIEBwYXJhbSB7aW50fSBpbmRleFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgc3RhdGljIGluc2VydEF0KHN0ciwgY2hhciwgaW5kZXgpIHtcbiAgICAgICAgc3RyID0gU3RyaW5nKHN0cik7XG5cbiAgICAgICAgaWYgKGluZGV4ID4gc3RyLmxlbmd0aCkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBUaGUgZ2l2ZW4gaW5kZXggaXMgb3V0IG9mIHRoZSBzdHJpbmcgcmFuZ2UuYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoY2hhci5sZW5ndGggIT09IDEpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBFcnJvcignVGhlIGdpdmVuIHN0cmluZyBgY2hhcmAgc2hvdWxkIGJlIG9ubHkgb25lIGNoYXJhY3RlciBsb25nLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHN0ciA9PT0gJycgJiYgaW5kZXggPT09IDApIHtcbiAgICAgICAgICAgIHJldHVybiBjaGFyO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGAke3N0ci5zbGljZSgwLCBpbmRleCl9JHtjaGFyfSR7c3RyLnNsaWNlKGluZGV4KX1gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnQgdGhlIGdpdmVuIHNjaWVudGlmaWMgbm90YXRpb24gdG8gdGhlICdleHBhbmRlZCcgZGVjaW1hbCBub3RhdGlvblxuICAgICAqXG4gICAgICogQGV4YW1wbGUgc2NpZW50aWZpY1RvRGVjaW1hbCgnLTEyMy40NTY3ZS02JykgcmV0dXJucyAnLTAuMDAwMTIzNDU2NydcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ30gdmFsXG4gICAgICogQHJldHVybnMge251bWJlcnxzdHJpbmd9XG4gICAgICovXG4gICAgc3RhdGljIHNjaWVudGlmaWNUb0RlY2ltYWwodmFsKSB7XG4gICAgICAgIC8vIENoZWNrIHRoYXQgdGhlIHZhbCBpcyBhIE51bWJlclxuICAgICAgICBjb25zdCBudW1lcmljVmFsdWUgPSBOdW1iZXIodmFsKTtcbiAgICAgICAgaWYgKGlzTmFOKG51bWVyaWNWYWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVjayBpZiB0aGUgbnVtYmVyIGlzIGluIGEgc2NpZW50aWZpYyBub3RhdGlvblxuICAgICAgICB2YWwgICAgICAgICAgICAgICAgPSBTdHJpbmcodmFsKTtcbiAgICAgICAgY29uc3QgaXNTY2llbnRpZmljID0gdmFsLmluY2x1ZGVzKCdlJykgfHwgdmFsLmluY2x1ZGVzKCdFJyk7XG5cbiAgICAgICAgaWYgKCFpc1NjaWVudGlmaWMpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDb252ZXJ0IHRoZSBzY2llbnRpZmljIG5vdGF0aW9uIHRvIGEgbnVtZXJpYyBzdHJpbmdcbiAgICAgICAgbGV0IFt2YWx1ZSwgZXhwb25lbnRdID0gdmFsLnNwbGl0KC9lL2kpO1xuICAgICAgICBjb25zdCBpc05lZ2F0aXZlID0gdmFsdWUgPCAwO1xuICAgICAgICBpZiAoaXNOZWdhdGl2ZSkge1xuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKCctJywgJycpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaXNOZWdhdGl2ZUV4cG9uZW50ID0gK2V4cG9uZW50IDwgMDtcbiAgICAgICAgaWYgKGlzTmVnYXRpdmVFeHBvbmVudCkge1xuICAgICAgICAgICAgZXhwb25lbnQgPSBleHBvbmVudC5yZXBsYWNlKCctJywgJycpOyAvLyBSZW1vdmUgdGhlIG5lZ2F0aXZlIHNpZ25cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IFtpbnQsIGZsb2F0XSA9IHZhbHVlLnNwbGl0KC9cXC4vKTtcblxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoaXNOZWdhdGl2ZUV4cG9uZW50KSB7XG4gICAgICAgICAgICBpZiAoaW50Lmxlbmd0aCA+IGV4cG9uZW50KSB7XG4gICAgICAgICAgICAgICAgLy8gUGxhY2UgdGhlIGRlY2ltYWwgcG9pbnQgYXQgdGhlIGludCBsZW5ndGggY291bnQgbWludXMgZXhwb25lbnRcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLmluc2VydEF0KGludCwgJy4nLCBpbnQubGVuZ3RoIC0gZXhwb25lbnQpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBJZiB0aGF0IGRlY2ltYWwgcG9pbnQgaXMgZ3JlYXRlciB0aGFuIHRoZSBpbnQgbGVuZ3RoLCBwYWQgd2l0aCB6ZXJvcyAoaWUuIE51bWJlcignLTEyMy40NTY3ZS02JykgLS0+IC0wLjAwMDEyMzQ1NjcpXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gYDAuJHsnMCcucmVwZWF0KGV4cG9uZW50IC0gaW50Lmxlbmd0aCl9JHtpbnR9YDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmVzdWx0ID0gYCR7cmVzdWx0fSR7ZmxvYXQ/ZmxvYXQ6Jyd9YDtcbiAgICAgICAgfSBlbHNlIHsgLy8gUG9zaXRpdmUgZXhwb25lbnRcbiAgICAgICAgICAgIGlmIChmbG9hdCkge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gYCR7aW50fSR7ZmxvYXR9YDsgLy8gUmVtb3ZlIHRoZSAnLicsIGlmIGFueVxuICAgICAgICAgICAgICAgIGlmIChleHBvbmVudCA8IGZsb2F0Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLmluc2VydEF0KHZhbHVlLCAnLicsICtleHBvbmVudCArIGludC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGAke3ZhbHVlfSR7JzAnLnJlcGVhdChleHBvbmVudCAtIGZsb2F0Lmxlbmd0aCl9YDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUucmVwbGFjZSgnLicsICcnKTsgLy8gU2luZ2xlIGNhc2Ugd2hlcmUgdmFsIGlzICcxLmU0J1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGAke3ZhbHVlfSR7JzAnLnJlcGVhdChOdW1iZXIoZXhwb25lbnQpKX1gO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGlzTmVnYXRpdmUpIHtcbiAgICAgICAgICAgIC8vIFB1dCBiYWNrIHRoZSBuZWdhdGl2ZSBzaWduLCBpZiBhbnlcbiAgICAgICAgICAgIHJlc3VsdCA9IGAtJHtyZXN1bHR9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxufVxuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7QUFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUE2QkE7QUFDQTs7Ozs7Ozs7O0FBQ0E7Ozs7QUFJQTs7Ozs7Ozs7QUFDQTs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWlCQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBN0RBO0FBK0RBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7QUFVQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7OztBQVlBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFLQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFjQTtBQUNBO0FBREE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBMkNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFmQTtBQWlCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7QUFZQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FBVUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7Ozs7O0FBVUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQUFBO0FBR0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7O0FBTUE7QUFBQTtBQUNBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZUE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7OztBQUtBO0FBQ0E7QUFDQTtBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7O0FBU0E7QUFBQTtBQUNBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFMQTtBQUFBO0FBQUE7QUFBQTtBQUNBO0FBTUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7O0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7OztBQU9BO0FBQUE7QUFDQTtBQURBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7OztBQU1BO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQUNBO0FBQ0E7Ozs7Ozs7Ozs7QUFPQTtBQUNBO0FBQUE7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7Ozs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBaEJBO0FBQUE7QUFBQTtBQUFBO0FBQ0E7QUFnQkE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUExQkE7QUFBQTtBQUFBO0FBQUE7QUFDQTtBQTRCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFBQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7Ozs7OztBQWgvQ0E7QSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/AutoNumericHelper.js\n"); /***/ }), /***/ "./src/AutoNumericOptions.js": /*!***********************************!*\ !*** ./src/AutoNumericOptions.js ***! \***********************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval("\n\nvar _AutoNumeric = __webpack_require__(/*! ./AutoNumeric */ \"./src/AutoNumeric.js\");\n\nvar _AutoNumeric2 = _interopRequireDefault(_AutoNumeric);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Options values enumeration\n */\nObject.defineProperty(_AutoNumeric2.default, 'options', {\n get: function get() {\n return {\n /* Defines if the decimal places should be padded with zeroes\n * `true` : always pad decimals with zeros (ie. '12.3400')\n * `false` : never pad with zeros (ie. '12.34')\n * `'floats'` : pad with zeroes only when there are decimals (ie. '12' and '12.3400')\n * Note: setting allowDecimalPadding to 'false' will override the 'decimalPlaces' setting.\n */\n allowDecimalPadding: {\n always: true,\n never: false,\n floats: 'floats'\n },\n\n /* Defines where should be positioned the caret on focus\n * null : Do not enforce any caret positioning on focus (this is needed when using `selectOnFocus`)\n * `'start'` : put the caret of the far left side of the value (excluding the positive/negative sign and currency symbol, if any)\n * `'end'` : put the caret of the far right side of the value (excluding the positive/negative sign and currency symbol, if any)\n * `'decimalLeft'` : put the caret of the left of the decimal character if any\n * `'decimalRight'` : put the caret of the right of the decimal character if any\n */\n caretPositionOnFocus: {\n start: 'start',\n end: 'end',\n decimalLeft: 'decimalLeft',\n decimalRight: 'decimalRight',\n doNoForceCaretPosition: null\n },\n\n /* Defines if a local list of AutoNumeric objects should be kept when initializing this object.\n * This list is used by the `global.*` functions.\n */\n createLocalList: {\n createList: true,\n doNotCreateList: false\n },\n\n /* Defines the currency symbol string.\n * It can be a string of more than one character (allowing for instance to use a space on either side of it, example: '$ ' or ' $')\n * cf. https://en.wikipedia.org/wiki/Currency_symbol\n */\n currencySymbol: {\n none: '',\n currencySign: '¤',\n austral: '₳', // ARA\n australCentavo: '¢',\n baht: '฿', // THB\n cedi: '₵', // GHS\n cent: '¢',\n colon: '₡', // CRC\n cruzeiro: '₢', // BRB - Not used anymore since 1993\n dollar: '$',\n dong: '₫', // VND\n drachma: '₯', // GRD (or 'Δρχ.' or 'Δρ.')\n dram: '​֏', // AMD\n european: '₠', // XEU (old currency before the Euro)\n euro: '€', // EUR\n florin: 'ƒ',\n franc: '₣', // FRF\n guarani: '₲', // PYG\n hryvnia: '₴', // грн\n kip: '₭', // LAK\n att: 'ອັດ', // cents of the Kip\n lepton: 'Λ.', // cents of the Drachma\n lira: '₺', // TRY\n liraOld: '₤',\n lari: '₾', // GEL\n mark: 'ℳ',\n mill: '₥',\n naira: '₦', // NGN\n peseta: '₧',\n peso: '₱', // PHP\n pfennig: '₰', // cents of the Mark\n pound: '£',\n real: 'R$', // Brazilian real\n riel: '៛', // KHR\n ruble: '₽', // RUB\n rupee: '₹', // INR\n rupeeOld: '₨',\n shekel: '₪',\n shekelAlt: 'ש״ח‎‎',\n taka: '৳', // BDT\n tenge: '₸', // KZT\n togrog: '₮', // MNT\n won: '₩',\n yen: '¥'\n },\n\n /* Defines where the currency symbol should be placed (before of after the numbers)\n * for prefix currencySymbolPlacement: \"p\" (default)\n * for suffix currencySymbolPlacement: \"s\"\n */\n currencySymbolPlacement: {\n prefix: 'p',\n suffix: 's'\n },\n\n /* Defines what decimal separator character is used\n */\n decimalCharacter: {\n comma: ',',\n dot: '.',\n middleDot: '·',\n arabicDecimalSeparator: '٫',\n decimalSeparatorKeySymbol: '⎖'\n },\n\n /* Allow to declare an alternative decimal separator which is automatically replaced by `decimalCharacter` when typed.\n * This is used by countries that use a comma ',' as the decimal character and have keyboards with a numeric pads that have\n * a period 'full stop' as the decimal character (France or Spain for instance).\n */\n decimalCharacterAlternative: {\n none: null,\n comma: ',',\n dot: '.'\n },\n\n /* Defines the default number of decimal places to show on the formatted value, and keep for the precision.\n * Incidentally, since we need to be able to show that many decimal places, this also defines the raw value precision by default.\n */\n decimalPlaces: {\n none: 0,\n one: 1,\n two: 2,\n three: 3,\n four: 4,\n five: 5,\n six: 6\n },\n\n /* Defines how many decimal places should be kept for the raw value (ie. This is the precision for float values).\n *\n * If this option is set to `null` (which is the default), then the value of `decimalPlaces` is used for `decimalPlacesRawValue` as well.\n * Note: Setting this to a lower number of decimal places than the one to be shown will lead to confusion for the users.\n */\n decimalPlacesRawValue: {\n useDefault: null,\n none: 0,\n one: 1,\n two: 2,\n three: 3,\n four: 4,\n five: 5,\n six: 6\n },\n\n /* Defines how many decimal places should be visible when the element is unfocused.\n * If this is set to `null`, then this option is ignored, and the `decimalPlaces` option value will be used instead.\n * This means this is optional ; if omitted the decimal places will be the same when the input has the focus.\n *\n * This option can be used in conjonction with the two other `scale*` options, which allows to display a different formatted value when the element is unfocused, while another formatted value is shown when focused.\n * For those `scale*` options to have any effect, `divisorWhenUnfocused` must not be `null`.\n */\n decimalPlacesShownOnBlur: {\n useDefault: null,\n none: 0,\n one: 1,\n two: 2,\n three: 3,\n four: 4,\n five: 5,\n six: 6\n },\n\n /* Defines how many decimal places should be visible when the element has the focus.\n * If this is set to `null`, then this option is ignored, and the `decimalPlaces` option value will be used instead.\n *\n * Example:\n * For instance if `decimalPlacesShownOnFocus` is set to `5` and the default number of decimal places is `2`, then on focus `1,000.12345` will be shown, while without focus `1,000.12` will be set back.\n * Note 1: the results depends on the rounding method used.\n * Note 2: the `getNumericString()` method returns the extended decimal places\n */\n decimalPlacesShownOnFocus: {\n useDefault: null,\n none: 0,\n one: 1,\n two: 2,\n three: 3,\n four: 4,\n five: 5,\n six: 6\n },\n\n /* Helper option for ASP.NET postback\n * This should be set as the value of the unformatted default value\n * examples:\n * no default value=\"\" {defaultValueOverride: \"\"}\n * value=1234.56 {defaultValueOverride: '1234.56'}\n */\n defaultValueOverride: {\n doNotOverride: null\n },\n\n /* Defines how many numbers should be grouped together (usually for the thousand separator)\n * - \"2\", results in 99,99,99,999 India's lakhs\n * - \"2s\", results in 99,999,99,99,999 India's lakhs scaled\n * - \"3\", results in 999,999,999 (default)\n * - \"4\", results in 9999,9999,9999 used in some Asian countries\n * Note: This option does not accept other grouping choice.\n */\n digitalGroupSpacing: {\n two: '2',\n twoScaled: '2s',\n three: '3',\n four: '4'\n },\n\n /* Defines the thousand grouping separator character\n * Example : If `'.'` is set, then you'll get `'1.234.567'`\n */\n digitGroupSeparator: {\n comma: ',',\n dot: '.',\n normalSpace: ' ',\n thinSpace: '\\u2009',\n narrowNoBreakSpace: '\\u202F',\n noBreakSpace: '\\xA0',\n noSeparator: '',\n apostrophe: '\\'',\n arabicThousandsSeparator: '٬',\n dotAbove: '˙'\n },\n\n /* The `divisorWhenUnfocused` divide the element value on focus.\n * On blur, the element value is multiplied back.\n *\n * Example : Display percentages using { divisorWhenUnfocused: 100 } (or directly in the Html with ``)\n * The divisor value does not need to be an integer, but please understand that Javascript has limited accuracy in math ; use with caution.\n * Note: The `getNumericString` method returns the full value, including the 'hidden' decimals.\n */\n divisorWhenUnfocused: {\n none: null,\n percentage: 100,\n permille: 1000,\n basisPoint: 10000\n },\n\n /* Defines what should be displayed in the element if the raw value is an empty string ('').\n * - 'focus' : The currency sign is displayed when the input receives focus (default)\n * - 'press' : The currency sign is displayed whenever a key is being pressed\n * - 'always' : The currency sign is always displayed\n * - 'zero' : A zero is displayed ('rounded' with or without a currency sign) if the input has no value on focus out\n * - 'null' : When the element is empty, the `rawValue` and the element value/text is set to `null`. This also allows to set the value to `null` using `anElement.set(null)`.\n */\n emptyInputBehavior: {\n null: 'null',\n focus: 'focus',\n press: 'press',\n always: 'always',\n zero: 'zero'\n },\n\n /* Defines if the custom and native events triggered by AutoNumeric should bubble up or not.\n */\n eventBubbles: {\n bubbles: true,\n doesNotBubble: false\n },\n\n /* Defines if the custom and native events triggered by AutoNumeric should be cancelable.\n */\n eventIsCancelable: {\n isCancelable: true,\n isNotCancelable: false\n },\n\n /* This option is the 'strict mode' (aka 'debug' mode), which allows autoNumeric to strictly analyse the options passed, and fails if an unknown options is used in the settings object.\n * You should set that to `true` if you want to make sure you are only using 'pure' autoNumeric settings objects in your code.\n * If you see uncaught errors in the console and your code starts to fail, this means somehow those options gets polluted by another program (which usually happens when using frameworks).\n */\n failOnUnknownOption: {\n fail: true,\n ignore: false\n },\n\n /* Determine if the default value will be formatted on initialization.\n */\n formatOnPageLoad: {\n format: true, // automatically formats the default value on initialization\n doNotFormat: false // will not format the default value on initialization\n },\n\n /* Set the undo/redo history table size.\n * Each record keeps the raw value as well and the last known caret/selection positions.\n */\n historySize: {\n verySmall: 5,\n small: 10,\n medium: 20,\n large: 50,\n veryLarge: 100,\n insane: Number.MAX_SAFE_INTEGER\n },\n\n /* Allow the user to 'cancel' and undo the changes he made to the given autonumeric-managed element, by pressing the 'Escape' key.\n * Whenever the user 'validate' the input (either by hitting 'Enter', or blurring the element), the new value is saved for subsequent 'cancellation'.\n *\n * The process :\n * - save the input value on focus\n * - if the user change the input value, and hit `Escape`, then the initial value saved on focus is set back\n * - on the other hand if the user either have used `Enter` to validate (`Enter` throws a change event) his entries, or if the input value has been changed by another script in the mean time, then we save the new input value\n * - on a successful 'cancel', select the whole value (while respecting the `selectNumberOnly` option)\n * - bonus; if the value has not changed, hitting 'Esc' just select all the input value (while respecting the `selectNumberOnly` option)\n */\n isCancellable: {\n cancellable: true,\n notCancellable: false\n },\n\n /* Controls the leading zero behavior\n * - 'allow' : allows leading zeros to be entered. Zeros will be truncated when entering additional digits. On focusout zeros will be deleted\n * - 'deny' : allows only one leading zero on values that are between 1 and -1\n * - 'keep' : allows leading zeros to be entered. on focusout zeros will be retained\n */\n leadingZero: {\n allow: 'allow',\n deny: 'deny',\n keep: 'keep'\n },\n\n /* Defines the maximum possible value a user can enter.\n * Notes:\n * - this value must be a string and use the period for the decimal point\n * - this value needs to be larger than `minimumValue`\n */\n maximumValue: {\n tenTrillions: '9999999999999.99', // 9.999.999.999.999,99 ~= 10000 billions\n tenTrillionsNoDecimals: '9999999999999', //FIXME Update all those limits to the 'real' numbers\n oneBillion: '999999999.99',\n zero: '0'\n },\n\n /* Defines the minimum possible value a user can enter.\n * Notes:\n * - this value must be a string and use the period for the decimal point\n * - this value needs to be smaller than `maximumValue`\n * - if this is superior to 0, then you'll effectively prevent your user to entirely delete the content of your element\n */\n minimumValue: {\n tenTrillions: '-9999999999999.99', // -9.999.999.999.999,99 ~= 10000 billions\n tenTrillionsNoDecimals: '-9999999999999',\n oneBillion: '-999999999.99',\n zero: '0'\n },\n\n /* Allows the user to increment or decrement the element value with the mouse wheel.\n * The wheel behavior can be modified by the `wheelStep` option.\n * This `wheelStep` option can be used in two ways, either by setting:\n * - a 'fixed' step value (`wheelStep : 1000`), or\n * - the 'progressive' string (`wheelStep : 'progressive'`), which will then activate a special mode where the step is automatically calculated based on the element value size.\n *\n * Note :\n * You can activate/deactivate the wheel event for each `wheelOn` option value by using the 'Shift' modifier key while using the mouse wheel.\n */\n modifyValueOnWheel: {\n modifyValue: true,\n doNothing: false\n },\n\n /* Adds brackets on negative values (ie. transforms '-$ 999.99' to '($999.99)')\n * Those brackets are visible only when the field does NOT have the focus.\n * The left and right symbols should be enclosed in quotes and separated by a comma.\n */\n negativeBracketsTypeOnBlur: {\n parentheses: '(,)',\n brackets: '[,]',\n chevrons: '<,>',\n curlyBraces: '{,}',\n angleBrackets: '〈,〉',\n japaneseQuotationMarks: '「,」',\n halfBrackets: '⸤,⸥',\n whiteSquareBrackets: '⟦,⟧',\n quotationMarks: '‹,›',\n guillemets: '«,»',\n none: null // This is the default value, which deactivate this feature\n },\n\n /* Placement of the negative/positive sign relative to the `currencySymbol` option.\n *\n * Example:\n * -1,234.56 => default no options required\n * -$1,234.56 => {currencySymbol: \"$\"} or {currencySymbol: \"$\", negativePositiveSignPlacement: \"l\"}\n * $-1,234.56 => {currencySymbol: \"$\", negativePositiveSignPlacement: \"r\"} // Default if negativePositiveSignPlacement is 'null' and currencySymbol is not empty\n * -1,234.56$ => {currencySymbol: \"$\", currencySymbolPlacement: \"s\", negativePositiveSignPlacement: \"p\"} // Default if negativePositiveSignPlacement is 'null' and currencySymbol is not empty\n * 1,234.56- => {negativePositiveSignPlacement: \"s\"}\n * $1,234.56- => {currencySymbol: \"$\", negativePositiveSignPlacement: \"s\"}\n * 1,234.56-$ => {currencySymbol: \"$\", currencySymbolPlacement: \"s\"}\n * 1,234.56$- => {currencySymbol: \"$\", currencySymbolPlacement: \"s\", negativePositiveSignPlacement: \"r\"}\n */\n negativePositiveSignPlacement: {\n prefix: 'p',\n suffix: 's',\n left: 'l',\n right: 'r',\n none: null\n },\n\n /* Defines the negative sign symbol.\n * It can be a string of only one character.\n */\n negativeSignCharacter: {\n hyphen: '-',\n minus: '−',\n heavyMinus: '➖',\n fullWidthHyphen: '-',\n circledMinus: '⊖',\n squaredMinus: '⊟',\n triangleMinus: '⨺',\n plusMinus: '±',\n minusPlus: '∓',\n dotMinus: '∸',\n minusTilde: '≂',\n not: '¬'\n },\n\n /* Defines if the element should have event listeners activated on it.\n * By default, those event listeners are only added to elements and html element with the `contenteditable` attribute set to `true`, but not on the other html tags.\n * This allows to initialize elements without any event listeners.\n * Warning: Since AutoNumeric will not check the input content after its initialization, using some autoNumeric methods afterwards *will* probably leads to formatting problems.\n */\n noEventListeners: {\n noEvents: true,\n addEvents: false\n },\n\n /* Manage how autoNumeric react when the user tries to paste an invalid number.\n * - 'error' : (This is the default behavior) The input value is not changed and an error is output in the console.\n * - 'ignore' : idem than 'error', but fail silently without outputting any error/warning in the console.\n * - 'clamp' : if the pasted value is either too small or too big regarding the minimumValue and maximumValue range, then the result is clamped to those limits.\n * - 'truncate' : autoNumeric will insert as many pasted numbers it can at the initial caret/selection, until everything is pasted, or the range limit is hit.\n * The non-pasted numbers are dropped and therefore not used at all.\n * - 'replace' : autoNumeric will first insert as many pasted numbers it can at the initial caret/selection, then if the range limit is hit, it will try\n * to replace one by one the remaining initial numbers (on the right side of the caret) with the rest of the pasted numbers.\n *\n * Note 1 : A paste content starting with a negative sign '-' will be accepted anywhere in the input, and will set the resulting value as a negative number\n * Note 2 : A paste content starting with a number will be accepted, even if the rest is gibberish (ie. '123foobar456').\n * Only the first number will be used (here '123').\n * Note 3 : The paste event works with the `decimalPlacesShownOnFocus` option too.\n */\n onInvalidPaste: {\n error: 'error',\n ignore: 'ignore',\n clamp: 'clamp',\n truncate: 'truncate',\n replace: 'replace'\n },\n\n /* Defines how the value should be formatted when wanting a 'localized' version of it.\n * - null or 'string' => 'nnnn.nn' or '-nnnn.nn' as text type. This is the default behavior.\n * - 'number' => nnnn.nn or -nnnn.nn as a Number (Warning: this works only for integers inferior to Number.MAX_SAFE_INTEGER)\n * - ',' or '-,' => 'nnnn,nn' or '-nnnn,nn'\n * - '.-' => 'nnnn.nn' or 'nnnn.nn-'\n * - ',-' => 'nnnn,nn' or 'nnnn,nn-'\n *\n * Note: The hyphen '-' is translated to the custom negative sign defined in `negativeSignCharacter`\n */\n outputFormat: {\n string: 'string',\n number: 'number',\n dot: '.',\n negativeDot: '-.',\n comma: ',',\n negativeComma: '-,',\n dotNegative: '.-',\n commaNegative: ',-',\n none: null\n },\n\n /* Override the minimum and maximum limits\n * overrideMinMaxLimits: \"ceiling\" adheres to maximumValue and ignores minimumValue settings\n * overrideMinMaxLimits: \"floor\" adheres to minimumValue and ignores maximumValue settings\n * overrideMinMaxLimits: \"ignore\" ignores both minimumValue & maximumValue\n */\n overrideMinMaxLimits: {\n ceiling: 'ceiling',\n floor: 'floor',\n ignore: 'ignore',\n doNotOverride: null\n },\n\n /* Defines the positive sign symbol.\n * It can be a string of only one character.\n * This is shown only if `showPositiveSign` is set to `true`.\n */\n positiveSignCharacter: {\n plus: '+',\n fullWidthPlus: '+',\n heavyPlus: '➕',\n doublePlus: '⧺',\n triplePlus: '⧻',\n circledPlus: '⊕',\n squaredPlus: '⊞',\n trianglePlus: '⨹',\n plusMinus: '±',\n minusPlus: '∓',\n dotPlus: '∔',\n altHebrewPlus: '﬩',\n normalSpace: ' ',\n thinSpace: '\\u2009',\n narrowNoBreakSpace: '\\u202F',\n noBreakSpace: '\\xA0'\n },\n\n /* The `rawValueDivisor` divides the formatted value shown in the AutoNumeric element and store the result in `rawValue`.\n * @example { rawValueDivisor: '100' } or \n * Given the `0.01234` raw value, the formatted value will be displayed as `'1.234'`.\n * This is useful when displaying percentage for instance, and avoid the need to divide/multiply by 100 between the number shown and the raw value.\n */\n rawValueDivisor: {\n none: null,\n percentage: 100,\n permille: 1000,\n basisPoint: 10000\n },\n\n /* Defines if the element should be set as read only on initialization.\n * When set to `true`, then the `readonly` html property is added to the element on initialization.\n */\n readOnly: {\n readOnly: true,\n readWrite: false\n },\n\n /* Defines the rounding method to use.\n * roundingMethod: \"S\", Round-Half-Up Symmetric (default)\n * roundingMethod: \"A\", Round-Half-Up Asymmetric\n * roundingMethod: \"s\", Round-Half-Down Symmetric (lower case s)\n * roundingMethod: \"a\", Round-Half-Down Asymmetric (lower case a)\n * roundingMethod: \"B\", Round-Half-Even \"Bankers Rounding\"\n * roundingMethod: \"U\", Round Up \"Round-Away-From-Zero\"\n * roundingMethod: \"D\", Round Down \"Round-Toward-Zero\" - same as truncate\n * roundingMethod: \"C\", Round to Ceiling \"Toward Positive Infinity\"\n * roundingMethod: \"F\", Round to Floor \"Toward Negative Infinity\"\n * roundingMethod: \"N05\" Rounds to the nearest .05 => same as \"CHF\" used in 1.9X and still valid\n * roundingMethod: \"U05\" Rounds up to next .05\n * roundingMethod: \"D05\" Rounds down to next .05\n */\n roundingMethod: {\n halfUpSymmetric: 'S',\n halfUpAsymmetric: 'A',\n halfDownSymmetric: 's',\n halfDownAsymmetric: 'a',\n halfEvenBankersRounding: 'B',\n upRoundAwayFromZero: 'U',\n downRoundTowardZero: 'D',\n toCeilingTowardPositiveInfinity: 'C',\n toFloorTowardNegativeInfinity: 'F',\n toNearest05: 'N05',\n toNearest05Alt: 'CHF',\n upToNext05: 'U05',\n downToNext05: 'D05'\n },\n\n /* Set to `true` to allow the `decimalPlacesShownOnFocus` value to be saved with sessionStorage\n * If IE 6 or 7 is detected, the value will be saved as a session cookie.\n */\n saveValueToSessionStorage: {\n save: true,\n doNotSave: false\n },\n\n /* Determine if the select all keyboard command will select the complete input text, or only the input numeric value\n * Note : If the currency symbol is between the numeric value and the negative sign, only the numeric value will be selected\n */\n selectNumberOnly: {\n selectNumbersOnly: true,\n selectAll: false\n },\n\n /* Defines if the element value should be selected on focus.\n * Note: The selection is done using the `selectNumberOnly` option.\n */\n selectOnFocus: {\n select: true,\n doNotSelect: false\n },\n\n /* Defines how the serialize functions should treat the spaces.\n * Those spaces ' ' can either be converted to the plus sign '+', which is the default, or to '%20'.\n * Both values being valid per the spec (http://www.w3.org/Addressing/URL/uri-spec.html).\n * Also see the summed up answer on http://stackoverflow.com/a/33939287.\n *\n * tl;dr : Spaces should be converted to '%20' before the '?' sign, then converted to '+' after.\n * In our case since we serialize the query, we use '+' as the default (but allow the user to get back the old *wrong* behavior).\n */\n serializeSpaces: {\n plus: '+',\n percent: '%20'\n },\n\n /* Defines if the element value should be converted to the raw value on focus (and back to the formatted on blur).\n * If set to `true`, then autoNumeric remove the thousand separator, currency symbol and suffix on focus.\n * Example:\n * If the input value is '$ 1,999.88 suffix', on focus it becomes '1999.88' and back to '$ 1,999.88 suffix' on blur.\n */\n showOnlyNumbersOnFocus: {\n onlyNumbers: true,\n showAll: false\n },\n\n /* Allow the positive sign symbol `+` to be displayed for positive numbers.\n * By default, this positive sign is not shown.\n * The sign placement is controlled by the 'negativePositiveSignPlacement' option, mimicking the negative sign placement rules.\n */\n showPositiveSign: {\n show: true,\n hide: false\n },\n\n /* Defines if warnings should be shown in the console.\n * Those warnings can be ignored, but are usually printed when something could be improved by the user (ie. option conflicts).\n */\n showWarnings: {\n show: true, // All warning are shown\n hide: false // No warnings are shown, only the thrown errors\n },\n\n /* Defines the rules that calculate the CSS class(es) to apply on the element, based on the raw unformatted value.\n * This can also be used to call callbacks whenever the `rawValue` is updated.\n * Important: all callbacks must return `null` if no ranges/userDefined classes are selected\n * @example\n * {\n * positive : 'autoNumeric-positive', // Or `null` to not use it\n * negative : 'autoNumeric-negative',\n * ranges : [\n * { min: 0, max: 25, class: 'autoNumeric-red' },\n * { min: 25, max: 50, class: 'autoNumeric-orange' },\n * { min: 50, max: 75, class: 'autoNumeric-yellow' },\n * { min: 75, max: Number.MAX_SAFE_INTEGER, class: 'autoNumeric-green' },\n * ],\n * userDefined: [\n * // If 'classes' is a string, set it if `true`, remove it if `false`\n * { callback: rawValue => { return true; }, classes: 'thisIsTrue' },\n * // If 'classes' is an array with only 2 elements, set the first class if `true`, the second if `false`\n * { callback: rawValue => rawValue % 2 === 0, classes: ['autoNumeric-even', 'autoNumeric-odd'] },\n * // Return only one index to use on the `classes` array (here, 'class3')\n * { callback: rawValue => { return 2; }, classes: ['class1', 'class2', 'class3'] },\n * // Return an array of indexes to use on the `classes` array (here, 'class1' and 'class3')\n * { callback: rawValue => { return [0, 2]; }, classes: ['class1', 'class2', 'class3'] },\n * // If 'classes' is `undefined` or `null`, then the callback is called with the AutoNumeric object passed as a parameter\n * { callback: anElement => { return anElement.getFormatted(); } },\n * ],\n * }\n */\n styleRules: {\n none: null,\n positiveNegative: {\n positive: 'autoNumeric-positive',\n negative: 'autoNumeric-negative'\n },\n range0To100With4Steps: {\n ranges: [{ min: 0, max: 25, class: 'autoNumeric-red' }, { min: 25, max: 50, class: 'autoNumeric-orange' }, { min: 50, max: 75, class: 'autoNumeric-yellow' }, { min: 75, max: 100, class: 'autoNumeric-green' }]\n },\n evenOdd: {\n userDefined: [{ callback: function callback(rawValue) {\n return rawValue % 2 === 0;\n }, classes: ['autoNumeric-even', 'autoNumeric-odd'] }]\n },\n rangeSmallAndZero: {\n userDefined: [{\n callback: function callback(rawValue) {\n if (rawValue >= -1 && rawValue < 0) {\n return 0;\n }\n if (Number(rawValue) === 0) {\n return 1;\n }\n if (rawValue > 0 && rawValue <= 1) {\n return 2;\n }\n\n return null; // In case the rawValue is outside those ranges\n },\n classes: ['autoNumeric-small-negative', 'autoNumeric-zero', 'autoNumeric-small-positive']\n }]\n }\n },\n\n /* Add a text on the right hand side of the element value.\n * This suffix text can have any characters in its string, except numeric characters and the negative/positive sign.\n * Example: ' dollars'\n */\n suffixText: {\n none: '',\n percentage: '%',\n permille: '‰',\n basisPoint: '‱'\n },\n\n /* The three options (divisorWhenUnfocused, decimalPlacesShownOnBlur & symbolWhenUnfocused) handle scaling of the input when the input does not have focus\n * Please note that the non-scaled value is held in data and it is advised that you use the `saveValueToSessionStorage` option to ensure retaining the value\n * [\"divisor\", \"decimal places\", \"symbol\"]\n * Example: with the following options set {divisorWhenUnfocused: '1000', decimalPlacesShownOnBlur: '1', symbolWhenUnfocused: ' K'}\n * Example: focusin value \"1,111.11\" focusout value \"1.1 K\"\n */\n\n /* The `symbolWhenUnfocused` option is a symbol placed as a suffix when not in focus.\n * This is optional too.\n */\n symbolWhenUnfocused: {\n none: null,\n percentage: '%',\n permille: '‰',\n basisPoint: '‱'\n },\n\n /* Defines if the element value should be unformatted when the user hover his mouse over it while holding the `Alt` key.\n * Unformatting there means that this removes any non-number characters and displays the *raw* value, as understood by Javascript (ie. `12.34` is a valid number, while `12,34` is not).\n *\n * We reformat back before anything else if :\n * - the user focus on the element by tabbing or clicking into it,\n * - the user releases the `Alt` key, and\n * - if we detect a mouseleave event.\n *\n * We unformat again if :\n * - while the mouse is over the element, the user hit `Alt` again\n */\n unformatOnHover: {\n unformat: true,\n doNotUnformat: false //TODO Rename to `keepFormat`\n },\n\n /* Removes the formatting and use the raw value in each autoNumeric elements of the parent form element, on the form `submit` event.\n * The output format is a numeric string (nnnn.nn or -nnnn.nn).\n */\n unformatOnSubmit: {\n unformat: true,\n keepCurrentValue: false\n },\n\n /* Provides a way for automatically replacing the formatted value with a pre-defined string, when the raw value is equal to a specific value\n * Here you can specify as many 'conversion' as needed.\n */\n valuesToStrings: {\n none: null,\n zeroDash: {\n 0: '-'\n },\n oneAroundZero: {\n '-1': 'Min',\n 1: 'Max'\n }\n },\n\n /* Defines if the AutoNumeric element should watch external changes made without using `.set()`, but by using the basic `aNElement.node().value = 42` notation.\n * If set to `watch`, then AutoNumeric will format the new value using `.set()` internally.\n * Otherwise it will neither format it, nor save it in the history.\n */\n watchExternalChanges: {\n watch: true,\n doNotWatch: false\n },\n\n /* Defines when the wheel event will increment or decrement the element value.\n * When set to `'focus'`, the AutoNumeric-managed element needs to be focused for the wheel event to change the value.\n * When set to `'hover'`, using the wheel event while the mouse is hovering the element is sufficient (no focus needed).\n *\n * Note :\n * When `wheelOn` is set to `'focus'`, you can use the 'Shift' modifier key while using the mouse wheel in order to temporarily activate the increment/decrement feature even if the element is not focused.\n * When `wheelOn` is set to `'hover'`, you can use the 'Shift' modifier key while using the mouse wheel in order to temporarily disable the increment/decrement feature even if the element is not hovered.\n */\n wheelOn: {\n focus: 'focus',\n hover: 'hover'\n },\n\n /* That option is linked to the `modifyValueOnWheel` one and will only be used if the latter is set to `true`.\n * This option will modify the wheel behavior and can be used in two ways, either by setting :\n * - a 'fixed' step value (a positive float or integer number `1000`), or\n * - the `'progressive'` string.\n *\n * The 'fixed' mode always increment/decrement the element value by that amount, while respecting the `minimumValue` and `maximumValue` settings.\n * The 'progressive' mode will increment/decrement the element value based on its current value. The bigger the number, the bigger the step, and vice versa.\n */\n wheelStep: {\n progressive: 'progressive'\n }\n };\n }\n}); /**\n * Options for autoNumeric.js\n * @author Alexandre Bonneau \n * @copyright © 2016 Alexandre Bonneau\n *\n * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sub license, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWNPcHRpb25zLmpzLmpzIiwic291cmNlcyI6WyJ3ZWJwYWNrOi8vQXV0b051bWVyaWMvc3JjL0F1dG9OdW1lcmljT3B0aW9ucy5qcz9mMWI3Il0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogT3B0aW9ucyBmb3IgYXV0b051bWVyaWMuanNcbiAqIEBhdXRob3IgQWxleGFuZHJlIEJvbm5lYXUgPGFsZXhhbmRyZS5ib25uZWF1QGxpbnV4ZnIuZXU+XG4gKiBAY29weXJpZ2h0IMKpIDIwMTYgQWxleGFuZHJlIEJvbm5lYXVcbiAqXG4gKiBUaGUgTUlUIExpY2Vuc2UgKGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvbWl0LWxpY2Vuc2UucGhwKVxuICpcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uXG4gKiBvYnRhaW5pbmcgYSBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvblxuICogZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0XG4gKiByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSxcbiAqIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YiBsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlXG4gKiBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZ1xuICogY29uZGl0aW9uczpcbiAqXG4gKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZVxuICogaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gKlxuICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCxcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFU1xuICogT0YgTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkRcbiAqIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUXG4gKiBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSxcbiAqIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lOR1xuICogRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUlxuICogT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuICovXG5cbmltcG9ydCBBdXRvTnVtZXJpYyBmcm9tICcuL0F1dG9OdW1lcmljJztcblxuLyoqXG4gKiBPcHRpb25zIHZhbHVlcyBlbnVtZXJhdGlvblxuICovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoQXV0b051bWVyaWMsICdvcHRpb25zJywge1xuICAgIGdldCgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIC8qIERlZmluZXMgaWYgdGhlIGRlY2ltYWwgcGxhY2VzIHNob3VsZCBiZSBwYWRkZWQgd2l0aCB6ZXJvZXNcbiAgICAgICAgICAgICAqIGB0cnVlYCAgICAgOiBhbHdheXMgcGFkIGRlY2ltYWxzIHdpdGggemVyb3MgKGllLiAnMTIuMzQwMCcpXG4gICAgICAgICAgICAgKiBgZmFsc2VgICAgIDogbmV2ZXIgcGFkIHdpdGggemVyb3MgKGllLiAnMTIuMzQnKVxuICAgICAgICAgICAgICogYCdmbG9hdHMnYCA6IHBhZCB3aXRoIHplcm9lcyBvbmx5IHdoZW4gdGhlcmUgYXJlIGRlY2ltYWxzIChpZS4gJzEyJyBhbmQgJzEyLjM0MDAnKVxuICAgICAgICAgICAgICogTm90ZTogc2V0dGluZyBhbGxvd0RlY2ltYWxQYWRkaW5nIHRvICdmYWxzZScgd2lsbCBvdmVycmlkZSB0aGUgJ2RlY2ltYWxQbGFjZXMnIHNldHRpbmcuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGFsbG93RGVjaW1hbFBhZGRpbmc6IHtcbiAgICAgICAgICAgICAgICBhbHdheXM6IHRydWUsXG4gICAgICAgICAgICAgICAgbmV2ZXIgOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBmbG9hdHM6ICdmbG9hdHMnLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyB3aGVyZSBzaG91bGQgYmUgcG9zaXRpb25lZCB0aGUgY2FyZXQgb24gZm9jdXNcbiAgICAgICAgICAgICAqIG51bGwgOiBEbyBub3QgZW5mb3JjZSBhbnkgY2FyZXQgcG9zaXRpb25pbmcgb24gZm9jdXMgKHRoaXMgaXMgbmVlZGVkIHdoZW4gdXNpbmcgYHNlbGVjdE9uRm9jdXNgKVxuICAgICAgICAgICAgICogYCdzdGFydCdgIDogcHV0IHRoZSBjYXJldCBvZiB0aGUgZmFyIGxlZnQgc2lkZSBvZiB0aGUgdmFsdWUgKGV4Y2x1ZGluZyB0aGUgcG9zaXRpdmUvbmVnYXRpdmUgc2lnbiBhbmQgY3VycmVuY3kgc3ltYm9sLCBpZiBhbnkpXG4gICAgICAgICAgICAgKiBgJ2VuZCdgIDogcHV0IHRoZSBjYXJldCBvZiB0aGUgZmFyIHJpZ2h0IHNpZGUgb2YgdGhlIHZhbHVlIChleGNsdWRpbmcgdGhlIHBvc2l0aXZlL25lZ2F0aXZlIHNpZ24gYW5kIGN1cnJlbmN5IHN5bWJvbCwgaWYgYW55KVxuICAgICAgICAgICAgICogYCdkZWNpbWFsTGVmdCdgIDogcHV0IHRoZSBjYXJldCBvZiB0aGUgbGVmdCBvZiB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgaWYgYW55XG4gICAgICAgICAgICAgKiBgJ2RlY2ltYWxSaWdodCdgIDogcHV0IHRoZSBjYXJldCBvZiB0aGUgcmlnaHQgb2YgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGlmIGFueVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Gb2N1czoge1xuICAgICAgICAgICAgICAgIHN0YXJ0ICAgICAgICAgICAgICAgICA6ICdzdGFydCcsXG4gICAgICAgICAgICAgICAgZW5kICAgICAgICAgICAgICAgICAgIDogJ2VuZCcsXG4gICAgICAgICAgICAgICAgZGVjaW1hbExlZnQgICAgICAgICAgIDogJ2RlY2ltYWxMZWZ0JyxcbiAgICAgICAgICAgICAgICBkZWNpbWFsUmlnaHQgICAgICAgICAgOiAnZGVjaW1hbFJpZ2h0JyxcbiAgICAgICAgICAgICAgICBkb05vRm9yY2VDYXJldFBvc2l0aW9uOiBudWxsLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyBpZiBhIGxvY2FsIGxpc3Qgb2YgQXV0b051bWVyaWMgb2JqZWN0cyBzaG91bGQgYmUga2VwdCB3aGVuIGluaXRpYWxpemluZyB0aGlzIG9iamVjdC5cbiAgICAgICAgICAgICAqIFRoaXMgbGlzdCBpcyB1c2VkIGJ5IHRoZSBgZ2xvYmFsLipgIGZ1bmN0aW9ucy5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgY3JlYXRlTG9jYWxMaXN0OiB7XG4gICAgICAgICAgICAgICAgY3JlYXRlTGlzdCAgICAgOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRvTm90Q3JlYXRlTGlzdDogZmFsc2UsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIHRoZSBjdXJyZW5jeSBzeW1ib2wgc3RyaW5nLlxuICAgICAgICAgICAgICogSXQgY2FuIGJlIGEgc3RyaW5nIG9mIG1vcmUgdGhhbiBvbmUgY2hhcmFjdGVyIChhbGxvd2luZyBmb3IgaW5zdGFuY2UgdG8gdXNlIGEgc3BhY2Ugb24gZWl0aGVyIHNpZGUgb2YgaXQsIGV4YW1wbGU6ICckICcgb3IgJyAkJylcbiAgICAgICAgICAgICAqIGNmLiBodHRwczovL2VuLndpa2lwZWRpYS5vcmcvd2lraS9DdXJyZW5jeV9zeW1ib2xcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgY3VycmVuY3lTeW1ib2w6IHtcbiAgICAgICAgICAgICAgICBub25lICAgICAgICAgIDogJycsXG4gICAgICAgICAgICAgICAgY3VycmVuY3lTaWduICA6ICfCpCcsXG4gICAgICAgICAgICAgICAgYXVzdHJhbCAgICAgICA6ICfigrMnLCAvLyBBUkFcbiAgICAgICAgICAgICAgICBhdXN0cmFsQ2VudGF2bzogJ8KiJyxcbiAgICAgICAgICAgICAgICBiYWh0ICAgICAgICAgIDogJ+C4vycsIC8vIFRIQlxuICAgICAgICAgICAgICAgIGNlZGkgICAgICAgICAgOiAn4oK1JywgLy8gR0hTXG4gICAgICAgICAgICAgICAgY2VudCAgICAgICAgICA6ICfCoicsXG4gICAgICAgICAgICAgICAgY29sb24gICAgICAgICA6ICfigqEnLCAvLyBDUkNcbiAgICAgICAgICAgICAgICBjcnV6ZWlybyAgICAgIDogJ+KCoicsIC8vIEJSQiAtIE5vdCB1c2VkIGFueW1vcmUgc2luY2UgMTk5M1xuICAgICAgICAgICAgICAgIGRvbGxhciAgICAgICAgOiAnJCcsXG4gICAgICAgICAgICAgICAgZG9uZyAgICAgICAgICA6ICfigqsnLCAvLyBWTkRcbiAgICAgICAgICAgICAgICBkcmFjaG1hICAgICAgIDogJ+KCrycsIC8vIEdSRCAob3IgJ86Uz4HPhy4nIG9yICfOlM+BLicpXG4gICAgICAgICAgICAgICAgZHJhbSAgICAgICAgICA6ICfigIvWjycsIC8vIEFNRFxuICAgICAgICAgICAgICAgIGV1cm9wZWFuICAgICAgOiAn4oKgJywgLy8gWEVVIChvbGQgY3VycmVuY3kgYmVmb3JlIHRoZSBFdXJvKVxuICAgICAgICAgICAgICAgIGV1cm8gICAgICAgICAgOiAn4oKsJywgLy8gRVVSXG4gICAgICAgICAgICAgICAgZmxvcmluICAgICAgICA6ICfGkicsXG4gICAgICAgICAgICAgICAgZnJhbmMgICAgICAgICA6ICfigqMnLCAvLyBGUkZcbiAgICAgICAgICAgICAgICBndWFyYW5pICAgICAgIDogJ+KCsicsIC8vIFBZR1xuICAgICAgICAgICAgICAgIGhyeXZuaWEgICAgICAgOiAn4oK0JywgLy8g0LPRgNC9XG4gICAgICAgICAgICAgICAga2lwICAgICAgICAgICA6ICfigq0nLCAvLyBMQUtcbiAgICAgICAgICAgICAgICBhdHQgICAgICAgICAgIDogJ+C6reC6seC6lCcsIC8vIGNlbnRzIG9mIHRoZSBLaXBcbiAgICAgICAgICAgICAgICBsZXB0b24gICAgICAgIDogJ86bLicsIC8vIGNlbnRzIG9mIHRoZSBEcmFjaG1hXG4gICAgICAgICAgICAgICAgbGlyYSAgICAgICAgICA6ICfigronLCAvLyBUUllcbiAgICAgICAgICAgICAgICBsaXJhT2xkICAgICAgIDogJ+KCpCcsXG4gICAgICAgICAgICAgICAgbGFyaSAgICAgICAgICA6ICfigr4nLCAvLyBHRUxcbiAgICAgICAgICAgICAgICBtYXJrICAgICAgICAgIDogJ+KEsycsXG4gICAgICAgICAgICAgICAgbWlsbCAgICAgICAgICA6ICfigqUnLFxuICAgICAgICAgICAgICAgIG5haXJhICAgICAgICAgOiAn4oKmJywgLy8gTkdOXG4gICAgICAgICAgICAgICAgcGVzZXRhICAgICAgICA6ICfigqcnLFxuICAgICAgICAgICAgICAgIHBlc28gICAgICAgICAgOiAn4oKxJywgLy8gUEhQXG4gICAgICAgICAgICAgICAgcGZlbm5pZyAgICAgICA6ICfigrAnLCAvLyBjZW50cyBvZiB0aGUgTWFya1xuICAgICAgICAgICAgICAgIHBvdW5kICAgICAgICAgOiAnwqMnLFxuICAgICAgICAgICAgICAgIHJlYWwgICAgICAgICAgOiAnUiQnLCAvLyBCcmF6aWxpYW4gcmVhbFxuICAgICAgICAgICAgICAgIHJpZWwgICAgICAgICAgOiAn4Z+bJywgLy8gS0hSXG4gICAgICAgICAgICAgICAgcnVibGUgICAgICAgICA6ICfigr0nLCAvLyBSVUJcbiAgICAgICAgICAgICAgICBydXBlZSAgICAgICAgIDogJ+KCuScsIC8vIElOUlxuICAgICAgICAgICAgICAgIHJ1cGVlT2xkICAgICAgOiAn4oKoJyxcbiAgICAgICAgICAgICAgICBzaGVrZWwgICAgICAgIDogJ+KCqicsXG4gICAgICAgICAgICAgICAgc2hla2VsQWx0ICAgICA6ICfXqde015figI7igI4nLFxuICAgICAgICAgICAgICAgIHRha2EgICAgICAgICAgOiAn4KezJywgLy8gQkRUXG4gICAgICAgICAgICAgICAgdGVuZ2UgICAgICAgICA6ICfigrgnLCAvLyBLWlRcbiAgICAgICAgICAgICAgICB0b2dyb2cgICAgICAgIDogJ+KCricsIC8vIE1OVFxuICAgICAgICAgICAgICAgIHdvbiAgICAgICAgICAgOiAn4oKpJyxcbiAgICAgICAgICAgICAgICB5ZW4gICAgICAgICAgIDogJ8KlJyxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgd2hlcmUgdGhlIGN1cnJlbmN5IHN5bWJvbCBzaG91bGQgYmUgcGxhY2VkIChiZWZvcmUgb2YgYWZ0ZXIgdGhlIG51bWJlcnMpXG4gICAgICAgICAgICAgKiBmb3IgcHJlZml4IGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50OiBcInBcIiAoZGVmYXVsdClcbiAgICAgICAgICAgICAqIGZvciBzdWZmaXggY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQ6IFwic1wiXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50OiB7XG4gICAgICAgICAgICAgICAgcHJlZml4OiAncCcsXG4gICAgICAgICAgICAgICAgc3VmZml4OiAncycsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIHdoYXQgZGVjaW1hbCBzZXBhcmF0b3IgY2hhcmFjdGVyIGlzIHVzZWRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZGVjaW1hbENoYXJhY3Rlcjoge1xuICAgICAgICAgICAgICAgIGNvbW1hICAgICAgICAgICAgICAgICAgICA6ICcsJyxcbiAgICAgICAgICAgICAgICBkb3QgICAgICAgICAgICAgICAgICAgICAgOiAnLicsXG4gICAgICAgICAgICAgICAgbWlkZGxlRG90ICAgICAgICAgICAgICAgIDogJ8K3JyxcbiAgICAgICAgICAgICAgICBhcmFiaWNEZWNpbWFsU2VwYXJhdG9yICAgOiAn2asnLFxuICAgICAgICAgICAgICAgIGRlY2ltYWxTZXBhcmF0b3JLZXlTeW1ib2w6ICfijpYnLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogQWxsb3cgdG8gZGVjbGFyZSBhbiBhbHRlcm5hdGl2ZSBkZWNpbWFsIHNlcGFyYXRvciB3aGljaCBpcyBhdXRvbWF0aWNhbGx5IHJlcGxhY2VkIGJ5IGBkZWNpbWFsQ2hhcmFjdGVyYCB3aGVuIHR5cGVkLlxuICAgICAgICAgICAgICogVGhpcyBpcyB1c2VkIGJ5IGNvdW50cmllcyB0aGF0IHVzZSBhIGNvbW1hICcsJyBhcyB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgYW5kIGhhdmUga2V5Ym9hcmRzIHdpdGggYSBudW1lcmljIHBhZHMgdGhhdCBoYXZlXG4gICAgICAgICAgICAgKiBhIHBlcmlvZCAnZnVsbCBzdG9wJyBhcyB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgKEZyYW5jZSBvciBTcGFpbiBmb3IgaW5zdGFuY2UpLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmU6IHtcbiAgICAgICAgICAgICAgICBub25lIDogbnVsbCxcbiAgICAgICAgICAgICAgICBjb21tYTogJywnLFxuICAgICAgICAgICAgICAgIGRvdCAgOiAnLicsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIHRoZSBkZWZhdWx0IG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0byBzaG93IG9uIHRoZSBmb3JtYXR0ZWQgdmFsdWUsIGFuZCBrZWVwIGZvciB0aGUgcHJlY2lzaW9uLlxuICAgICAgICAgICAgICogSW5jaWRlbnRhbGx5LCBzaW5jZSB3ZSBuZWVkIHRvIGJlIGFibGUgdG8gc2hvdyB0aGF0IG1hbnkgZGVjaW1hbCBwbGFjZXMsIHRoaXMgYWxzbyBkZWZpbmVzIHRoZSByYXcgdmFsdWUgcHJlY2lzaW9uIGJ5IGRlZmF1bHQuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXM6IHtcbiAgICAgICAgICAgICAgICBub25lIDogMCxcbiAgICAgICAgICAgICAgICBvbmUgIDogMSxcbiAgICAgICAgICAgICAgICB0d28gIDogMixcbiAgICAgICAgICAgICAgICB0aHJlZTogMyxcbiAgICAgICAgICAgICAgICBmb3VyIDogNCxcbiAgICAgICAgICAgICAgICBmaXZlIDogNSxcbiAgICAgICAgICAgICAgICBzaXggIDogNixcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgaG93IG1hbnkgZGVjaW1hbCBwbGFjZXMgc2hvdWxkIGJlIGtlcHQgZm9yIHRoZSByYXcgdmFsdWUgKGllLiBUaGlzIGlzIHRoZSBwcmVjaXNpb24gZm9yIGZsb2F0IHZhbHVlcykuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogSWYgdGhpcyBvcHRpb24gaXMgc2V0IHRvIGBudWxsYCAod2hpY2ggaXMgdGhlIGRlZmF1bHQpLCB0aGVuIHRoZSB2YWx1ZSBvZiBgZGVjaW1hbFBsYWNlc2AgaXMgdXNlZCBmb3IgYGRlY2ltYWxQbGFjZXNSYXdWYWx1ZWAgYXMgd2VsbC5cbiAgICAgICAgICAgICAqIE5vdGU6IFNldHRpbmcgdGhpcyB0byBhIGxvd2VyIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0aGFuIHRoZSBvbmUgdG8gYmUgc2hvd24gd2lsbCBsZWFkIHRvIGNvbmZ1c2lvbiBmb3IgdGhlIHVzZXJzLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzUmF3VmFsdWU6IHtcbiAgICAgICAgICAgICAgICB1c2VEZWZhdWx0OiBudWxsLFxuICAgICAgICAgICAgICAgIG5vbmUgICAgICA6IDAsXG4gICAgICAgICAgICAgICAgb25lICAgICAgIDogMSxcbiAgICAgICAgICAgICAgICB0d28gICAgICAgOiAyLFxuICAgICAgICAgICAgICAgIHRocmVlICAgICA6IDMsXG4gICAgICAgICAgICAgICAgZm91ciAgICAgIDogNCxcbiAgICAgICAgICAgICAgICBmaXZlICAgICAgOiA1LFxuICAgICAgICAgICAgICAgIHNpeCAgICAgICA6IDYsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIGhvdyBtYW55IGRlY2ltYWwgcGxhY2VzIHNob3VsZCBiZSB2aXNpYmxlIHdoZW4gdGhlIGVsZW1lbnQgaXMgdW5mb2N1c2VkLlxuICAgICAgICAgICAgICogSWYgdGhpcyBpcyBzZXQgdG8gYG51bGxgLCB0aGVuIHRoaXMgb3B0aW9uIGlzIGlnbm9yZWQsIGFuZCB0aGUgYGRlY2ltYWxQbGFjZXNgIG9wdGlvbiB2YWx1ZSB3aWxsIGJlIHVzZWQgaW5zdGVhZC5cbiAgICAgICAgICAgICAqIFRoaXMgbWVhbnMgdGhpcyBpcyBvcHRpb25hbCA7IGlmIG9taXR0ZWQgdGhlIGRlY2ltYWwgcGxhY2VzIHdpbGwgYmUgdGhlIHNhbWUgd2hlbiB0aGUgaW5wdXQgaGFzIHRoZSBmb2N1cy5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBUaGlzIG9wdGlvbiBjYW4gYmUgdXNlZCBpbiBjb25qb25jdGlvbiB3aXRoIHRoZSB0d28gb3RoZXIgYHNjYWxlKmAgb3B0aW9ucywgd2hpY2ggYWxsb3dzIHRvIGRpc3BsYXkgYSBkaWZmZXJlbnQgZm9ybWF0dGVkIHZhbHVlIHdoZW4gdGhlIGVsZW1lbnQgaXMgdW5mb2N1c2VkLCB3aGlsZSBhbm90aGVyIGZvcm1hdHRlZCB2YWx1ZSBpcyBzaG93biB3aGVuIGZvY3VzZWQuXG4gICAgICAgICAgICAgKiBGb3IgdGhvc2UgYHNjYWxlKmAgb3B0aW9ucyB0byBoYXZlIGFueSBlZmZlY3QsIGBkaXZpc29yV2hlblVuZm9jdXNlZGAgbXVzdCBub3QgYmUgYG51bGxgLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXI6IHtcbiAgICAgICAgICAgICAgICB1c2VEZWZhdWx0OiBudWxsLFxuICAgICAgICAgICAgICAgIG5vbmUgICAgICA6IDAsXG4gICAgICAgICAgICAgICAgb25lICAgICAgIDogMSxcbiAgICAgICAgICAgICAgICB0d28gICAgICAgOiAyLFxuICAgICAgICAgICAgICAgIHRocmVlICAgICA6IDMsXG4gICAgICAgICAgICAgICAgZm91ciAgICAgIDogNCxcbiAgICAgICAgICAgICAgICBmaXZlICAgICAgOiA1LFxuICAgICAgICAgICAgICAgIHNpeCAgICAgICA6IDYsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIGhvdyBtYW55IGRlY2ltYWwgcGxhY2VzIHNob3VsZCBiZSB2aXNpYmxlIHdoZW4gdGhlIGVsZW1lbnQgaGFzIHRoZSBmb2N1cy5cbiAgICAgICAgICAgICAqIElmIHRoaXMgaXMgc2V0IHRvIGBudWxsYCwgdGhlbiB0aGlzIG9wdGlvbiBpcyBpZ25vcmVkLCBhbmQgdGhlIGBkZWNpbWFsUGxhY2VzYCBvcHRpb24gdmFsdWUgd2lsbCBiZSB1c2VkIGluc3RlYWQuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogRXhhbXBsZTpcbiAgICAgICAgICAgICAqIEZvciBpbnN0YW5jZSBpZiBgZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1c2AgaXMgc2V0IHRvIGA1YCBhbmQgdGhlIGRlZmF1bHQgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGlzIGAyYCwgdGhlbiBvbiBmb2N1cyBgMSwwMDAuMTIzNDVgIHdpbGwgYmUgc2hvd24sIHdoaWxlIHdpdGhvdXQgZm9jdXMgYDEsMDAwLjEyYCB3aWxsIGJlIHNldCBiYWNrLlxuICAgICAgICAgICAgICogTm90ZSAxOiB0aGUgcmVzdWx0cyBkZXBlbmRzIG9uIHRoZSByb3VuZGluZyBtZXRob2QgdXNlZC5cbiAgICAgICAgICAgICAqIE5vdGUgMjogdGhlIGBnZXROdW1lcmljU3RyaW5nKClgIG1ldGhvZCByZXR1cm5zIHRoZSBleHRlbmRlZCBkZWNpbWFsIHBsYWNlc1xuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzOiB7XG4gICAgICAgICAgICAgICAgdXNlRGVmYXVsdDogbnVsbCxcbiAgICAgICAgICAgICAgICBub25lICAgICAgOiAwLFxuICAgICAgICAgICAgICAgIG9uZSAgICAgICA6IDEsXG4gICAgICAgICAgICAgICAgdHdvICAgICAgIDogMixcbiAgICAgICAgICAgICAgICB0aHJlZSAgICAgOiAzLFxuICAgICAgICAgICAgICAgIGZvdXIgICAgICA6IDQsXG4gICAgICAgICAgICAgICAgZml2ZSAgICAgIDogNSxcbiAgICAgICAgICAgICAgICBzaXggICAgICAgOiA2LFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogSGVscGVyIG9wdGlvbiBmb3IgQVNQLk5FVCBwb3N0YmFja1xuICAgICAgICAgICAgICogVGhpcyBzaG91bGQgYmUgc2V0IGFzIHRoZSB2YWx1ZSBvZiB0aGUgdW5mb3JtYXR0ZWQgZGVmYXVsdCB2YWx1ZVxuICAgICAgICAgICAgICogZXhhbXBsZXM6XG4gICAgICAgICAgICAgKiBubyBkZWZhdWx0IHZhbHVlPVwiXCIge2RlZmF1bHRWYWx1ZU92ZXJyaWRlOiBcIlwifVxuICAgICAgICAgICAgICogdmFsdWU9MTIzNC41NiB7ZGVmYXVsdFZhbHVlT3ZlcnJpZGU6ICcxMjM0LjU2J31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZGVmYXVsdFZhbHVlT3ZlcnJpZGU6IHtcbiAgICAgICAgICAgICAgICBkb05vdE92ZXJyaWRlOiBudWxsLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyBob3cgbWFueSBudW1iZXJzIHNob3VsZCBiZSBncm91cGVkIHRvZ2V0aGVyICh1c3VhbGx5IGZvciB0aGUgdGhvdXNhbmQgc2VwYXJhdG9yKVxuICAgICAgICAgICAgICogLSBcIjJcIiwgIHJlc3VsdHMgaW4gOTksOTksOTksOTk5IEluZGlhJ3MgbGFraHNcbiAgICAgICAgICAgICAqIC0gXCIyc1wiLCByZXN1bHRzIGluIDk5LDk5OSw5OSw5OSw5OTkgSW5kaWEncyBsYWtocyBzY2FsZWRcbiAgICAgICAgICAgICAqIC0gXCIzXCIsICByZXN1bHRzIGluIDk5OSw5OTksOTk5IChkZWZhdWx0KVxuICAgICAgICAgICAgICogLSBcIjRcIiwgIHJlc3VsdHMgaW4gOTk5OSw5OTk5LDk5OTkgdXNlZCBpbiBzb21lIEFzaWFuIGNvdW50cmllc1xuICAgICAgICAgICAgICogTm90ZTogVGhpcyBvcHRpb24gZG9lcyBub3QgYWNjZXB0IG90aGVyIGdyb3VwaW5nIGNob2ljZS5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZGlnaXRhbEdyb3VwU3BhY2luZzoge1xuICAgICAgICAgICAgICAgIHR3byAgICAgIDogJzInLFxuICAgICAgICAgICAgICAgIHR3b1NjYWxlZDogJzJzJyxcbiAgICAgICAgICAgICAgICB0aHJlZSAgICA6ICczJyxcbiAgICAgICAgICAgICAgICBmb3VyICAgICA6ICc0JyxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgdGhlIHRob3VzYW5kIGdyb3VwaW5nIHNlcGFyYXRvciBjaGFyYWN0ZXJcbiAgICAgICAgICAgICAqIEV4YW1wbGUgOiBJZiBgJy4nYCBpcyBzZXQsIHRoZW4geW91J2xsIGdldCBgJzEuMjM0LjU2NydgXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3I6IHtcbiAgICAgICAgICAgICAgICBjb21tYSAgICAgICAgICAgICAgICAgICA6ICcsJyxcbiAgICAgICAgICAgICAgICBkb3QgICAgICAgICAgICAgICAgICAgICA6ICcuJyxcbiAgICAgICAgICAgICAgICBub3JtYWxTcGFjZSAgICAgICAgICAgICA6ICcgJyxcbiAgICAgICAgICAgICAgICB0aGluU3BhY2UgICAgICAgICAgICAgICA6ICdcXHUyMDA5JyxcbiAgICAgICAgICAgICAgICBuYXJyb3dOb0JyZWFrU3BhY2UgICAgICA6ICdcXHUyMDJmJyxcbiAgICAgICAgICAgICAgICBub0JyZWFrU3BhY2UgICAgICAgICAgICA6ICdcXHUwMGEwJyxcbiAgICAgICAgICAgICAgICBub1NlcGFyYXRvciAgICAgICAgICAgICA6ICcnLFxuICAgICAgICAgICAgICAgIGFwb3N0cm9waGUgICAgICAgICAgICAgIDogYCdgLFxuICAgICAgICAgICAgICAgIGFyYWJpY1Rob3VzYW5kc1NlcGFyYXRvcjogJ9msJyxcbiAgICAgICAgICAgICAgICBkb3RBYm92ZSAgICAgICAgICAgICAgICA6ICfLmScsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBUaGUgYGRpdmlzb3JXaGVuVW5mb2N1c2VkYCBkaXZpZGUgdGhlIGVsZW1lbnQgdmFsdWUgb24gZm9jdXMuXG4gICAgICAgICAgICAgKiBPbiBibHVyLCB0aGUgZWxlbWVudCB2YWx1ZSBpcyBtdWx0aXBsaWVkIGJhY2suXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogRXhhbXBsZSA6IERpc3BsYXkgcGVyY2VudGFnZXMgdXNpbmcgeyBkaXZpc29yV2hlblVuZm9jdXNlZDogMTAwIH0gKG9yIGRpcmVjdGx5IGluIHRoZSBIdG1sIHdpdGggYDxpbnB1dCBkYXRhLWRpdmlzb3Itd2hlbi11bmZvY3VzZWQ9XCIxMDBcIj5gKVxuICAgICAgICAgICAgICogVGhlIGRpdmlzb3IgdmFsdWUgZG9lcyBub3QgbmVlZCB0byBiZSBhbiBpbnRlZ2VyLCBidXQgcGxlYXNlIHVuZGVyc3RhbmQgdGhhdCBKYXZhc2NyaXB0IGhhcyBsaW1pdGVkIGFjY3VyYWN5IGluIG1hdGggOyB1c2Ugd2l0aCBjYXV0aW9uLlxuICAgICAgICAgICAgICogTm90ZTogVGhlIGBnZXROdW1lcmljU3RyaW5nYCBtZXRob2QgcmV0dXJucyB0aGUgZnVsbCB2YWx1ZSwgaW5jbHVkaW5nIHRoZSAnaGlkZGVuJyBkZWNpbWFscy5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZGl2aXNvcldoZW5VbmZvY3VzZWQ6IHtcbiAgICAgICAgICAgICAgICBub25lICAgICAgOiBudWxsLFxuICAgICAgICAgICAgICAgIHBlcmNlbnRhZ2U6IDEwMCxcbiAgICAgICAgICAgICAgICBwZXJtaWxsZSAgOiAxMDAwLFxuICAgICAgICAgICAgICAgIGJhc2lzUG9pbnQ6IDEwMDAwLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyB3aGF0IHNob3VsZCBiZSBkaXNwbGF5ZWQgaW4gdGhlIGVsZW1lbnQgaWYgdGhlIHJhdyB2YWx1ZSBpcyBhbiBlbXB0eSBzdHJpbmcgKCcnKS5cbiAgICAgICAgICAgICAqIC0gJ2ZvY3VzJyAgOiBUaGUgY3VycmVuY3kgc2lnbiBpcyBkaXNwbGF5ZWQgd2hlbiB0aGUgaW5wdXQgcmVjZWl2ZXMgZm9jdXMgKGRlZmF1bHQpXG4gICAgICAgICAgICAgKiAtICdwcmVzcycgIDogVGhlIGN1cnJlbmN5IHNpZ24gaXMgZGlzcGxheWVkIHdoZW5ldmVyIGEga2V5IGlzIGJlaW5nIHByZXNzZWRcbiAgICAgICAgICAgICAqIC0gJ2Fsd2F5cycgOiBUaGUgY3VycmVuY3kgc2lnbiBpcyBhbHdheXMgZGlzcGxheWVkXG4gICAgICAgICAgICAgKiAtICd6ZXJvJyAgIDogQSB6ZXJvIGlzIGRpc3BsYXllZCAoJ3JvdW5kZWQnIHdpdGggb3Igd2l0aG91dCBhIGN1cnJlbmN5IHNpZ24pIGlmIHRoZSBpbnB1dCBoYXMgbm8gdmFsdWUgb24gZm9jdXMgb3V0XG4gICAgICAgICAgICAgKiAtICdudWxsJyAgIDogV2hlbiB0aGUgZWxlbWVudCBpcyBlbXB0eSwgdGhlIGByYXdWYWx1ZWAgYW5kIHRoZSBlbGVtZW50IHZhbHVlL3RleHQgaXMgc2V0IHRvIGBudWxsYC4gVGhpcyBhbHNvIGFsbG93cyB0byBzZXQgdGhlIHZhbHVlIHRvIGBudWxsYCB1c2luZyBgYW5FbGVtZW50LnNldChudWxsKWAuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGVtcHR5SW5wdXRCZWhhdmlvcjoge1xuICAgICAgICAgICAgICAgIG51bGwgIDogJ251bGwnLFxuICAgICAgICAgICAgICAgIGZvY3VzIDogJ2ZvY3VzJyxcbiAgICAgICAgICAgICAgICBwcmVzcyA6ICdwcmVzcycsXG4gICAgICAgICAgICAgICAgYWx3YXlzOiAnYWx3YXlzJyxcbiAgICAgICAgICAgICAgICB6ZXJvICA6ICd6ZXJvJyxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgaWYgdGhlIGN1c3RvbSBhbmQgbmF0aXZlIGV2ZW50cyB0cmlnZ2VyZWQgYnkgQXV0b051bWVyaWMgc2hvdWxkIGJ1YmJsZSB1cCBvciBub3QuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGV2ZW50QnViYmxlczoge1xuICAgICAgICAgICAgICAgIGJ1YmJsZXM6IHRydWUsXG4gICAgICAgICAgICAgICAgZG9lc05vdEJ1YmJsZTogZmFsc2UsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIGlmIHRoZSBjdXN0b20gYW5kIG5hdGl2ZSBldmVudHMgdHJpZ2dlcmVkIGJ5IEF1dG9OdW1lcmljIHNob3VsZCBiZSBjYW5jZWxhYmxlLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBldmVudElzQ2FuY2VsYWJsZToge1xuICAgICAgICAgICAgICAgIGlzQ2FuY2VsYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBpc05vdENhbmNlbGFibGU6IGZhbHNlLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogVGhpcyBvcHRpb24gaXMgdGhlICdzdHJpY3QgbW9kZScgKGFrYSAnZGVidWcnIG1vZGUpLCB3aGljaCBhbGxvd3MgYXV0b051bWVyaWMgdG8gc3RyaWN0bHkgYW5hbHlzZSB0aGUgb3B0aW9ucyBwYXNzZWQsIGFuZCBmYWlscyBpZiBhbiB1bmtub3duIG9wdGlvbnMgaXMgdXNlZCBpbiB0aGUgc2V0dGluZ3Mgb2JqZWN0LlxuICAgICAgICAgICAgICogWW91IHNob3VsZCBzZXQgdGhhdCB0byBgdHJ1ZWAgaWYgeW91IHdhbnQgdG8gbWFrZSBzdXJlIHlvdSBhcmUgb25seSB1c2luZyAncHVyZScgYXV0b051bWVyaWMgc2V0dGluZ3Mgb2JqZWN0cyBpbiB5b3VyIGNvZGUuXG4gICAgICAgICAgICAgKiBJZiB5b3Ugc2VlIHVuY2F1Z2h0IGVycm9ycyBpbiB0aGUgY29uc29sZSBhbmQgeW91ciBjb2RlIHN0YXJ0cyB0byBmYWlsLCB0aGlzIG1lYW5zIHNvbWVob3cgdGhvc2Ugb3B0aW9ucyBnZXRzIHBvbGx1dGVkIGJ5IGFub3RoZXIgcHJvZ3JhbSAod2hpY2ggdXN1YWxseSBoYXBwZW5zIHdoZW4gdXNpbmcgZnJhbWV3b3JrcykuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGZhaWxPblVua25vd25PcHRpb246IHtcbiAgICAgICAgICAgICAgICBmYWlsICA6IHRydWUsXG4gICAgICAgICAgICAgICAgaWdub3JlOiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERldGVybWluZSBpZiB0aGUgZGVmYXVsdCB2YWx1ZSB3aWxsIGJlIGZvcm1hdHRlZCBvbiBpbml0aWFsaXphdGlvbi5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZm9ybWF0T25QYWdlTG9hZDoge1xuICAgICAgICAgICAgICAgIGZvcm1hdCAgICAgOiB0cnVlLCAvLyBhdXRvbWF0aWNhbGx5IGZvcm1hdHMgdGhlIGRlZmF1bHQgdmFsdWUgb24gaW5pdGlhbGl6YXRpb25cbiAgICAgICAgICAgICAgICBkb05vdEZvcm1hdDogZmFsc2UsIC8vIHdpbGwgbm90IGZvcm1hdCB0aGUgZGVmYXVsdCB2YWx1ZSBvbiBpbml0aWFsaXphdGlvblxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogU2V0IHRoZSB1bmRvL3JlZG8gaGlzdG9yeSB0YWJsZSBzaXplLlxuICAgICAgICAgICAgICogRWFjaCByZWNvcmQga2VlcHMgdGhlIHJhdyB2YWx1ZSBhcyB3ZWxsIGFuZCB0aGUgbGFzdCBrbm93biBjYXJldC9zZWxlY3Rpb24gcG9zaXRpb25zLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBoaXN0b3J5U2l6ZToge1xuICAgICAgICAgICAgICAgIHZlcnlTbWFsbDogNSxcbiAgICAgICAgICAgICAgICBzbWFsbCAgICA6IDEwLFxuICAgICAgICAgICAgICAgIG1lZGl1bSAgIDogMjAsXG4gICAgICAgICAgICAgICAgbGFyZ2UgICAgOiA1MCxcbiAgICAgICAgICAgICAgICB2ZXJ5TGFyZ2U6IDEwMCxcbiAgICAgICAgICAgICAgICBpbnNhbmUgICA6IE51bWJlci5NQVhfU0FGRV9JTlRFR0VSLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogQWxsb3cgdGhlIHVzZXIgdG8gJ2NhbmNlbCcgYW5kIHVuZG8gdGhlIGNoYW5nZXMgaGUgbWFkZSB0byB0aGUgZ2l2ZW4gYXV0b251bWVyaWMtbWFuYWdlZCBlbGVtZW50LCBieSBwcmVzc2luZyB0aGUgJ0VzY2FwZScga2V5LlxuICAgICAgICAgICAgICogV2hlbmV2ZXIgdGhlIHVzZXIgJ3ZhbGlkYXRlJyB0aGUgaW5wdXQgKGVpdGhlciBieSBoaXR0aW5nICdFbnRlcicsIG9yIGJsdXJyaW5nIHRoZSBlbGVtZW50KSwgdGhlIG5ldyB2YWx1ZSBpcyBzYXZlZCBmb3Igc3Vic2VxdWVudCAnY2FuY2VsbGF0aW9uJy5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBUaGUgcHJvY2VzcyA6XG4gICAgICAgICAgICAgKiAgIC0gc2F2ZSB0aGUgaW5wdXQgdmFsdWUgb24gZm9jdXNcbiAgICAgICAgICAgICAqICAgLSBpZiB0aGUgdXNlciBjaGFuZ2UgdGhlIGlucHV0IHZhbHVlLCBhbmQgaGl0IGBFc2NhcGVgLCB0aGVuIHRoZSBpbml0aWFsIHZhbHVlIHNhdmVkIG9uIGZvY3VzIGlzIHNldCBiYWNrXG4gICAgICAgICAgICAgKiAgIC0gb24gdGhlIG90aGVyIGhhbmQgaWYgdGhlIHVzZXIgZWl0aGVyIGhhdmUgdXNlZCBgRW50ZXJgIHRvIHZhbGlkYXRlIChgRW50ZXJgIHRocm93cyBhIGNoYW5nZSBldmVudCkgaGlzIGVudHJpZXMsIG9yIGlmIHRoZSBpbnB1dCB2YWx1ZSBoYXMgYmVlbiBjaGFuZ2VkIGJ5IGFub3RoZXIgc2NyaXB0IGluIHRoZSBtZWFuIHRpbWUsIHRoZW4gd2Ugc2F2ZSB0aGUgbmV3IGlucHV0IHZhbHVlXG4gICAgICAgICAgICAgKiAgIC0gb24gYSBzdWNjZXNzZnVsICdjYW5jZWwnLCBzZWxlY3QgdGhlIHdob2xlIHZhbHVlICh3aGlsZSByZXNwZWN0aW5nIHRoZSBgc2VsZWN0TnVtYmVyT25seWAgb3B0aW9uKVxuICAgICAgICAgICAgICogICAtIGJvbnVzOyBpZiB0aGUgdmFsdWUgaGFzIG5vdCBjaGFuZ2VkLCBoaXR0aW5nICdFc2MnIGp1c3Qgc2VsZWN0IGFsbCB0aGUgaW5wdXQgdmFsdWUgKHdoaWxlIHJlc3BlY3RpbmcgdGhlIGBzZWxlY3ROdW1iZXJPbmx5YCBvcHRpb24pXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGlzQ2FuY2VsbGFibGU6IHtcbiAgICAgICAgICAgICAgICBjYW5jZWxsYWJsZSAgIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBub3RDYW5jZWxsYWJsZTogZmFsc2UsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBDb250cm9scyB0aGUgbGVhZGluZyB6ZXJvIGJlaGF2aW9yXG4gICAgICAgICAgICAgKiAtICdhbGxvdycgOiBhbGxvd3MgbGVhZGluZyB6ZXJvcyB0byBiZSBlbnRlcmVkLiBaZXJvcyB3aWxsIGJlIHRydW5jYXRlZCB3aGVuIGVudGVyaW5nIGFkZGl0aW9uYWwgZGlnaXRzLiBPbiBmb2N1c291dCB6ZXJvcyB3aWxsIGJlIGRlbGV0ZWRcbiAgICAgICAgICAgICAqIC0gJ2RlbnknICA6IGFsbG93cyBvbmx5IG9uZSBsZWFkaW5nIHplcm8gb24gdmFsdWVzIHRoYXQgYXJlIGJldHdlZW4gMSBhbmQgLTFcbiAgICAgICAgICAgICAqIC0gJ2tlZXAnICA6IGFsbG93cyBsZWFkaW5nIHplcm9zIHRvIGJlIGVudGVyZWQuIG9uIGZvY3Vzb3V0IHplcm9zIHdpbGwgYmUgcmV0YWluZWRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbGVhZGluZ1plcm86IHtcbiAgICAgICAgICAgICAgICBhbGxvdzogJ2FsbG93JyxcbiAgICAgICAgICAgICAgICBkZW55IDogJ2RlbnknLFxuICAgICAgICAgICAgICAgIGtlZXAgOiAna2VlcCcsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIHRoZSBtYXhpbXVtIHBvc3NpYmxlIHZhbHVlIGEgdXNlciBjYW4gZW50ZXIuXG4gICAgICAgICAgICAgKiBOb3RlczpcbiAgICAgICAgICAgICAqIC0gdGhpcyB2YWx1ZSBtdXN0IGJlIGEgc3RyaW5nIGFuZCB1c2UgdGhlIHBlcmlvZCBmb3IgdGhlIGRlY2ltYWwgcG9pbnRcbiAgICAgICAgICAgICAqIC0gdGhpcyB2YWx1ZSBuZWVkcyB0byBiZSBsYXJnZXIgdGhhbiBgbWluaW11bVZhbHVlYFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtYXhpbXVtVmFsdWU6IHtcbiAgICAgICAgICAgICAgICB0ZW5UcmlsbGlvbnMgICAgICAgICAgOiAnOTk5OTk5OTk5OTk5OS45OScsIC8vIDkuOTk5Ljk5OS45OTkuOTk5LDk5IH49IDEwMDAwIGJpbGxpb25zXG4gICAgICAgICAgICAgICAgdGVuVHJpbGxpb25zTm9EZWNpbWFsczogJzk5OTk5OTk5OTk5OTknLCAvL0ZJWE1FIFVwZGF0ZSBhbGwgdGhvc2UgbGltaXRzIHRvIHRoZSAncmVhbCcgbnVtYmVyc1xuICAgICAgICAgICAgICAgIG9uZUJpbGxpb24gICAgICAgICAgICA6ICc5OTk5OTk5OTkuOTknLFxuICAgICAgICAgICAgICAgIHplcm8gICAgICAgICAgICAgICAgICA6ICcwJyxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgdGhlIG1pbmltdW0gcG9zc2libGUgdmFsdWUgYSB1c2VyIGNhbiBlbnRlci5cbiAgICAgICAgICAgICAqIE5vdGVzOlxuICAgICAgICAgICAgICogLSB0aGlzIHZhbHVlIG11c3QgYmUgYSBzdHJpbmcgYW5kIHVzZSB0aGUgcGVyaW9kIGZvciB0aGUgZGVjaW1hbCBwb2ludFxuICAgICAgICAgICAgICogLSB0aGlzIHZhbHVlIG5lZWRzIHRvIGJlIHNtYWxsZXIgdGhhbiBgbWF4aW11bVZhbHVlYFxuICAgICAgICAgICAgICogLSBpZiB0aGlzIGlzIHN1cGVyaW9yIHRvIDAsIHRoZW4geW91J2xsIGVmZmVjdGl2ZWx5IHByZXZlbnQgeW91ciB1c2VyIHRvIGVudGlyZWx5IGRlbGV0ZSB0aGUgY29udGVudCBvZiB5b3VyIGVsZW1lbnRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbWluaW11bVZhbHVlOiB7XG4gICAgICAgICAgICAgICAgdGVuVHJpbGxpb25zICAgICAgICAgIDogJy05OTk5OTk5OTk5OTk5Ljk5JywgLy8gLTkuOTk5Ljk5OS45OTkuOTk5LDk5IH49IDEwMDAwIGJpbGxpb25zXG4gICAgICAgICAgICAgICAgdGVuVHJpbGxpb25zTm9EZWNpbWFsczogJy05OTk5OTk5OTk5OTk5JyxcbiAgICAgICAgICAgICAgICBvbmVCaWxsaW9uICAgICAgICAgICAgOiAnLTk5OTk5OTk5OS45OScsXG4gICAgICAgICAgICAgICAgemVybyAgICAgICAgICAgICAgICAgIDogJzAnLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogQWxsb3dzIHRoZSB1c2VyIHRvIGluY3JlbWVudCBvciBkZWNyZW1lbnQgdGhlIGVsZW1lbnQgdmFsdWUgd2l0aCB0aGUgbW91c2Ugd2hlZWwuXG4gICAgICAgICAgICAgKiBUaGUgd2hlZWwgYmVoYXZpb3IgY2FuIGJlIG1vZGlmaWVkIGJ5IHRoZSBgd2hlZWxTdGVwYCBvcHRpb24uXG4gICAgICAgICAgICAgKiBUaGlzIGB3aGVlbFN0ZXBgIG9wdGlvbiBjYW4gYmUgdXNlZCBpbiB0d28gd2F5cywgZWl0aGVyIGJ5IHNldHRpbmc6XG4gICAgICAgICAgICAgKiAtIGEgJ2ZpeGVkJyBzdGVwIHZhbHVlIChgd2hlZWxTdGVwIDogMTAwMGApLCBvclxuICAgICAgICAgICAgICogLSB0aGUgJ3Byb2dyZXNzaXZlJyBzdHJpbmcgKGB3aGVlbFN0ZXAgOiAncHJvZ3Jlc3NpdmUnYCksIHdoaWNoIHdpbGwgdGhlbiBhY3RpdmF0ZSBhIHNwZWNpYWwgbW9kZSB3aGVyZSB0aGUgc3RlcCBpcyBhdXRvbWF0aWNhbGx5IGNhbGN1bGF0ZWQgYmFzZWQgb24gdGhlIGVsZW1lbnQgdmFsdWUgc2l6ZS5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBOb3RlIDpcbiAgICAgICAgICAgICAqIFlvdSBjYW4gYWN0aXZhdGUvZGVhY3RpdmF0ZSB0aGUgd2hlZWwgZXZlbnQgZm9yIGVhY2ggYHdoZWVsT25gIG9wdGlvbiB2YWx1ZSBieSB1c2luZyB0aGUgJ1NoaWZ0JyBtb2RpZmllciBrZXkgd2hpbGUgdXNpbmcgdGhlIG1vdXNlIHdoZWVsLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtb2RpZnlWYWx1ZU9uV2hlZWw6IHtcbiAgICAgICAgICAgICAgICBtb2RpZnlWYWx1ZTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBkb05vdGhpbmcgIDogZmFsc2UsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBBZGRzIGJyYWNrZXRzIG9uIG5lZ2F0aXZlIHZhbHVlcyAoaWUuIHRyYW5zZm9ybXMgJy0kIDk5OS45OScgdG8gJygkOTk5Ljk5KScpXG4gICAgICAgICAgICAgKiBUaG9zZSBicmFja2V0cyBhcmUgdmlzaWJsZSBvbmx5IHdoZW4gdGhlIGZpZWxkIGRvZXMgTk9UIGhhdmUgdGhlIGZvY3VzLlxuICAgICAgICAgICAgICogVGhlIGxlZnQgYW5kIHJpZ2h0IHN5bWJvbHMgc2hvdWxkIGJlIGVuY2xvc2VkIGluIHF1b3RlcyBhbmQgc2VwYXJhdGVkIGJ5IGEgY29tbWEuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyOiB7XG4gICAgICAgICAgICAgICAgcGFyZW50aGVzZXMgICAgICAgICAgIDogJygsKScsXG4gICAgICAgICAgICAgICAgYnJhY2tldHMgICAgICAgICAgICAgIDogJ1ssXScsXG4gICAgICAgICAgICAgICAgY2hldnJvbnMgICAgICAgICAgICAgIDogJzwsPicsXG4gICAgICAgICAgICAgICAgY3VybHlCcmFjZXMgICAgICAgICAgIDogJ3ssfScsXG4gICAgICAgICAgICAgICAgYW5nbGVCcmFja2V0cyAgICAgICAgIDogJ+OAiCzjgIknLFxuICAgICAgICAgICAgICAgIGphcGFuZXNlUXVvdGF0aW9uTWFya3M6ICfvvaIs772jJyxcbiAgICAgICAgICAgICAgICBoYWxmQnJhY2tldHMgICAgICAgICAgOiAn4rikLOK4pScsXG4gICAgICAgICAgICAgICAgd2hpdGVTcXVhcmVCcmFja2V0cyAgIDogJ+Kfpizin6cnLFxuICAgICAgICAgICAgICAgIHF1b3RhdGlvbk1hcmtzICAgICAgICA6ICfigLks4oC6JyxcbiAgICAgICAgICAgICAgICBndWlsbGVtZXRzICAgICAgICAgICAgOiAnwqsswrsnLFxuICAgICAgICAgICAgICAgIG5vbmUgICAgICAgICAgICAgICAgICA6IG51bGwsIC8vIFRoaXMgaXMgdGhlIGRlZmF1bHQgdmFsdWUsIHdoaWNoIGRlYWN0aXZhdGUgdGhpcyBmZWF0dXJlXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBQbGFjZW1lbnQgb2YgdGhlIG5lZ2F0aXZlL3Bvc2l0aXZlIHNpZ24gcmVsYXRpdmUgdG8gdGhlIGBjdXJyZW5jeVN5bWJvbGAgb3B0aW9uLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEV4YW1wbGU6XG4gICAgICAgICAgICAgKiAtMSwyMzQuNTYgID0+IGRlZmF1bHQgbm8gb3B0aW9ucyByZXF1aXJlZFxuICAgICAgICAgICAgICogLSQxLDIzNC41NiA9PiB7Y3VycmVuY3lTeW1ib2w6IFwiJFwifSBvciB7Y3VycmVuY3lTeW1ib2w6IFwiJFwiLCBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogXCJsXCJ9XG4gICAgICAgICAgICAgKiAkLTEsMjM0LjU2ID0+IHtjdXJyZW5jeVN5bWJvbDogXCIkXCIsIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBcInJcIn0gLy8gRGVmYXVsdCBpZiBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCBpcyAnbnVsbCcgYW5kIGN1cnJlbmN5U3ltYm9sIGlzIG5vdCBlbXB0eVxuICAgICAgICAgICAgICogLTEsMjM0LjU2JCA9PiB7Y3VycmVuY3lTeW1ib2w6IFwiJFwiLCBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudDogXCJzXCIsIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBcInBcIn0gLy8gRGVmYXVsdCBpZiBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCBpcyAnbnVsbCcgYW5kIGN1cnJlbmN5U3ltYm9sIGlzIG5vdCBlbXB0eVxuICAgICAgICAgICAgICogMSwyMzQuNTYtICA9PiB7bmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IFwic1wifVxuICAgICAgICAgICAgICogJDEsMjM0LjU2LSA9PiB7Y3VycmVuY3lTeW1ib2w6IFwiJFwiLCBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogXCJzXCJ9XG4gICAgICAgICAgICAgKiAxLDIzNC41Ni0kID0+IHtjdXJyZW5jeVN5bWJvbDogXCIkXCIsIGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50OiBcInNcIn1cbiAgICAgICAgICAgICAqIDEsMjM0LjU2JC0gPT4ge2N1cnJlbmN5U3ltYm9sOiBcIiRcIiwgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQ6IFwic1wiLCBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogXCJyXCJ9XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiB7XG4gICAgICAgICAgICAgICAgcHJlZml4OiAncCcsXG4gICAgICAgICAgICAgICAgc3VmZml4OiAncycsXG4gICAgICAgICAgICAgICAgbGVmdCAgOiAnbCcsXG4gICAgICAgICAgICAgICAgcmlnaHQgOiAncicsXG4gICAgICAgICAgICAgICAgbm9uZSAgOiBudWxsLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyB0aGUgbmVnYXRpdmUgc2lnbiBzeW1ib2wuXG4gICAgICAgICAgICAgKiBJdCBjYW4gYmUgYSBzdHJpbmcgb2Ygb25seSBvbmUgY2hhcmFjdGVyLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXI6IHtcbiAgICAgICAgICAgICAgICBoeXBoZW4gICAgICAgICA6ICctJyxcbiAgICAgICAgICAgICAgICBtaW51cyAgICAgICAgICA6ICfiiJInLFxuICAgICAgICAgICAgICAgIGhlYXZ5TWludXMgICAgIDogJ+KelicsXG4gICAgICAgICAgICAgICAgZnVsbFdpZHRoSHlwaGVuOiAn77yNJyxcbiAgICAgICAgICAgICAgICBjaXJjbGVkTWludXMgICA6ICfiipYnLFxuICAgICAgICAgICAgICAgIHNxdWFyZWRNaW51cyAgIDogJ+KKnycsXG4gICAgICAgICAgICAgICAgdHJpYW5nbGVNaW51cyAgOiAn4qi6JyxcbiAgICAgICAgICAgICAgICBwbHVzTWludXMgICAgICA6ICfCsScsXG4gICAgICAgICAgICAgICAgbWludXNQbHVzICAgICAgOiAn4oiTJyxcbiAgICAgICAgICAgICAgICBkb3RNaW51cyAgICAgICA6ICfiiLgnLFxuICAgICAgICAgICAgICAgIG1pbnVzVGlsZGUgICAgIDogJ+KJgicsXG4gICAgICAgICAgICAgICAgbm90ICAgICAgICAgICAgOiAnwqwnLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyBpZiB0aGUgZWxlbWVudCBzaG91bGQgaGF2ZSBldmVudCBsaXN0ZW5lcnMgYWN0aXZhdGVkIG9uIGl0LlxuICAgICAgICAgICAgICogQnkgZGVmYXVsdCwgdGhvc2UgZXZlbnQgbGlzdGVuZXJzIGFyZSBvbmx5IGFkZGVkIHRvIDxpbnB1dD4gZWxlbWVudHMgYW5kIGh0bWwgZWxlbWVudCB3aXRoIHRoZSBgY29udGVudGVkaXRhYmxlYCBhdHRyaWJ1dGUgc2V0IHRvIGB0cnVlYCwgYnV0IG5vdCBvbiB0aGUgb3RoZXIgaHRtbCB0YWdzLlxuICAgICAgICAgICAgICogVGhpcyBhbGxvd3MgdG8gaW5pdGlhbGl6ZSBlbGVtZW50cyB3aXRob3V0IGFueSBldmVudCBsaXN0ZW5lcnMuXG4gICAgICAgICAgICAgKiBXYXJuaW5nOiBTaW5jZSBBdXRvTnVtZXJpYyB3aWxsIG5vdCBjaGVjayB0aGUgaW5wdXQgY29udGVudCBhZnRlciBpdHMgaW5pdGlhbGl6YXRpb24sIHVzaW5nIHNvbWUgYXV0b051bWVyaWMgbWV0aG9kcyBhZnRlcndhcmRzICp3aWxsKiBwcm9iYWJseSBsZWFkcyB0byBmb3JtYXR0aW5nIHByb2JsZW1zLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBub0V2ZW50TGlzdGVuZXJzOiB7XG4gICAgICAgICAgICAgICAgbm9FdmVudHMgOiB0cnVlLFxuICAgICAgICAgICAgICAgIGFkZEV2ZW50czogZmFsc2UsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBNYW5hZ2UgaG93IGF1dG9OdW1lcmljIHJlYWN0IHdoZW4gdGhlIHVzZXIgdHJpZXMgdG8gcGFzdGUgYW4gaW52YWxpZCBudW1iZXIuXG4gICAgICAgICAgICAgKiAtICdlcnJvcicgICAgOiAoVGhpcyBpcyB0aGUgZGVmYXVsdCBiZWhhdmlvcikgVGhlIGlucHV0IHZhbHVlIGlzIG5vdCBjaGFuZ2VkIGFuZCBhbiBlcnJvciBpcyBvdXRwdXQgaW4gdGhlIGNvbnNvbGUuXG4gICAgICAgICAgICAgKiAtICdpZ25vcmUnICAgOiBpZGVtIHRoYW4gJ2Vycm9yJywgYnV0IGZhaWwgc2lsZW50bHkgd2l0aG91dCBvdXRwdXR0aW5nIGFueSBlcnJvci93YXJuaW5nIGluIHRoZSBjb25zb2xlLlxuICAgICAgICAgICAgICogLSAnY2xhbXAnICAgIDogaWYgdGhlIHBhc3RlZCB2YWx1ZSBpcyBlaXRoZXIgdG9vIHNtYWxsIG9yIHRvbyBiaWcgcmVnYXJkaW5nIHRoZSBtaW5pbXVtVmFsdWUgYW5kIG1heGltdW1WYWx1ZSByYW5nZSwgdGhlbiB0aGUgcmVzdWx0IGlzIGNsYW1wZWQgdG8gdGhvc2UgbGltaXRzLlxuICAgICAgICAgICAgICogLSAndHJ1bmNhdGUnIDogYXV0b051bWVyaWMgd2lsbCBpbnNlcnQgYXMgbWFueSBwYXN0ZWQgbnVtYmVycyBpdCBjYW4gYXQgdGhlIGluaXRpYWwgY2FyZXQvc2VsZWN0aW9uLCB1bnRpbCBldmVyeXRoaW5nIGlzIHBhc3RlZCwgb3IgdGhlIHJhbmdlIGxpbWl0IGlzIGhpdC5cbiAgICAgICAgICAgICAqICAgICAgICAgICAgICAgIFRoZSBub24tcGFzdGVkIG51bWJlcnMgYXJlIGRyb3BwZWQgYW5kIHRoZXJlZm9yZSBub3QgdXNlZCBhdCBhbGwuXG4gICAgICAgICAgICAgKiAtICdyZXBsYWNlJyAgOiBhdXRvTnVtZXJpYyB3aWxsIGZpcnN0IGluc2VydCBhcyBtYW55IHBhc3RlZCBudW1iZXJzIGl0IGNhbiBhdCB0aGUgaW5pdGlhbCBjYXJldC9zZWxlY3Rpb24sIHRoZW4gaWYgdGhlIHJhbmdlIGxpbWl0IGlzIGhpdCwgaXQgd2lsbCB0cnlcbiAgICAgICAgICAgICAqICAgICAgICAgICAgICAgIHRvIHJlcGxhY2Ugb25lIGJ5IG9uZSB0aGUgcmVtYWluaW5nIGluaXRpYWwgbnVtYmVycyAob24gdGhlIHJpZ2h0IHNpZGUgb2YgdGhlIGNhcmV0KSB3aXRoIHRoZSByZXN0IG9mIHRoZSBwYXN0ZWQgbnVtYmVycy5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBOb3RlIDEgOiBBIHBhc3RlIGNvbnRlbnQgc3RhcnRpbmcgd2l0aCBhIG5lZ2F0aXZlIHNpZ24gJy0nIHdpbGwgYmUgYWNjZXB0ZWQgYW55d2hlcmUgaW4gdGhlIGlucHV0LCBhbmQgd2lsbCBzZXQgdGhlIHJlc3VsdGluZyB2YWx1ZSBhcyBhIG5lZ2F0aXZlIG51bWJlclxuICAgICAgICAgICAgICogTm90ZSAyIDogQSBwYXN0ZSBjb250ZW50IHN0YXJ0aW5nIHdpdGggYSBudW1iZXIgd2lsbCBiZSBhY2NlcHRlZCwgZXZlbiBpZiB0aGUgcmVzdCBpcyBnaWJiZXJpc2ggKGllLiAnMTIzZm9vYmFyNDU2JykuXG4gICAgICAgICAgICAgKiAgICAgICAgICBPbmx5IHRoZSBmaXJzdCBudW1iZXIgd2lsbCBiZSB1c2VkIChoZXJlICcxMjMnKS5cbiAgICAgICAgICAgICAqIE5vdGUgMyA6IFRoZSBwYXN0ZSBldmVudCB3b3JrcyB3aXRoIHRoZSBgZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1c2Agb3B0aW9uIHRvby5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgb25JbnZhbGlkUGFzdGU6IHtcbiAgICAgICAgICAgICAgICBlcnJvciAgIDogJ2Vycm9yJyxcbiAgICAgICAgICAgICAgICBpZ25vcmUgIDogJ2lnbm9yZScsXG4gICAgICAgICAgICAgICAgY2xhbXAgICA6ICdjbGFtcCcsXG4gICAgICAgICAgICAgICAgdHJ1bmNhdGU6ICd0cnVuY2F0ZScsXG4gICAgICAgICAgICAgICAgcmVwbGFjZSA6ICdyZXBsYWNlJyxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgaG93IHRoZSB2YWx1ZSBzaG91bGQgYmUgZm9ybWF0dGVkIHdoZW4gd2FudGluZyBhICdsb2NhbGl6ZWQnIHZlcnNpb24gb2YgaXQuXG4gICAgICAgICAgICAgKiAtIG51bGwgb3IgJ3N0cmluZycgPT4gJ25ubm4ubm4nIG9yICctbm5ubi5ubicgYXMgdGV4dCB0eXBlLiBUaGlzIGlzIHRoZSBkZWZhdWx0IGJlaGF2aW9yLlxuICAgICAgICAgICAgICogLSAnbnVtYmVyJyAgICAgICAgID0+IG5ubm4ubm4gb3IgLW5ubm4ubm4gYXMgYSBOdW1iZXIgKFdhcm5pbmc6IHRoaXMgd29ya3Mgb25seSBmb3IgaW50ZWdlcnMgaW5mZXJpb3IgdG8gTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIpXG4gICAgICAgICAgICAgKiAtICcsJyBvciAnLSwnICAgICAgPT4gJ25ubm4sbm4nIG9yICctbm5ubixubidcbiAgICAgICAgICAgICAqIC0gJy4tJyAgICAgICAgICAgICA9PiAnbm5ubi5ubicgb3IgJ25ubm4ubm4tJ1xuICAgICAgICAgICAgICogLSAnLC0nICAgICAgICAgICAgID0+ICdubm5uLG5uJyBvciAnbm5ubixubi0nXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogTm90ZTogVGhlIGh5cGhlbiAnLScgaXMgdHJhbnNsYXRlZCB0byB0aGUgY3VzdG9tIG5lZ2F0aXZlIHNpZ24gZGVmaW5lZCBpbiBgbmVnYXRpdmVTaWduQ2hhcmFjdGVyYFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBvdXRwdXRGb3JtYXQ6IHtcbiAgICAgICAgICAgICAgICBzdHJpbmcgICAgICAgOiAnc3RyaW5nJyxcbiAgICAgICAgICAgICAgICBudW1iZXIgICAgICAgOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBkb3QgICAgICAgICAgOiAnLicsXG4gICAgICAgICAgICAgICAgbmVnYXRpdmVEb3QgIDogJy0uJyxcbiAgICAgICAgICAgICAgICBjb21tYSAgICAgICAgOiAnLCcsXG4gICAgICAgICAgICAgICAgbmVnYXRpdmVDb21tYTogJy0sJyxcbiAgICAgICAgICAgICAgICBkb3ROZWdhdGl2ZSAgOiAnLi0nLFxuICAgICAgICAgICAgICAgIGNvbW1hTmVnYXRpdmU6ICcsLScsXG4gICAgICAgICAgICAgICAgbm9uZSAgICAgICAgIDogbnVsbCxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIE92ZXJyaWRlIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIGxpbWl0c1xuICAgICAgICAgICAgICogb3ZlcnJpZGVNaW5NYXhMaW1pdHM6IFwiY2VpbGluZ1wiIGFkaGVyZXMgdG8gbWF4aW11bVZhbHVlIGFuZCBpZ25vcmVzIG1pbmltdW1WYWx1ZSBzZXR0aW5nc1xuICAgICAgICAgICAgICogb3ZlcnJpZGVNaW5NYXhMaW1pdHM6IFwiZmxvb3JcIiBhZGhlcmVzIHRvIG1pbmltdW1WYWx1ZSBhbmQgaWdub3JlcyBtYXhpbXVtVmFsdWUgc2V0dGluZ3NcbiAgICAgICAgICAgICAqIG92ZXJyaWRlTWluTWF4TGltaXRzOiBcImlnbm9yZVwiIGlnbm9yZXMgYm90aCBtaW5pbXVtVmFsdWUgJiBtYXhpbXVtVmFsdWVcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgb3ZlcnJpZGVNaW5NYXhMaW1pdHM6IHtcbiAgICAgICAgICAgICAgICBjZWlsaW5nICAgICAgOiAnY2VpbGluZycsXG4gICAgICAgICAgICAgICAgZmxvb3IgICAgICAgIDogJ2Zsb29yJyxcbiAgICAgICAgICAgICAgICBpZ25vcmUgICAgICAgOiAnaWdub3JlJyxcbiAgICAgICAgICAgICAgICBkb05vdE92ZXJyaWRlOiBudWxsLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyB0aGUgcG9zaXRpdmUgc2lnbiBzeW1ib2wuXG4gICAgICAgICAgICAgKiBJdCBjYW4gYmUgYSBzdHJpbmcgb2Ygb25seSBvbmUgY2hhcmFjdGVyLlxuICAgICAgICAgICAgICogVGhpcyBpcyBzaG93biBvbmx5IGlmIGBzaG93UG9zaXRpdmVTaWduYCBpcyBzZXQgdG8gYHRydWVgLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBwb3NpdGl2ZVNpZ25DaGFyYWN0ZXI6IHtcbiAgICAgICAgICAgICAgICBwbHVzICAgICAgICAgICAgICA6ICcrJyxcbiAgICAgICAgICAgICAgICBmdWxsV2lkdGhQbHVzICAgICA6ICfvvIsnLFxuICAgICAgICAgICAgICAgIGhlYXZ5UGx1cyAgICAgICAgIDogJ+KelScsXG4gICAgICAgICAgICAgICAgZG91YmxlUGx1cyAgICAgICAgOiAn4qe6JyxcbiAgICAgICAgICAgICAgICB0cmlwbGVQbHVzICAgICAgICA6ICfip7snLFxuICAgICAgICAgICAgICAgIGNpcmNsZWRQbHVzICAgICAgIDogJ+KKlScsXG4gICAgICAgICAgICAgICAgc3F1YXJlZFBsdXMgICAgICAgOiAn4oqeJyxcbiAgICAgICAgICAgICAgICB0cmlhbmdsZVBsdXMgICAgICA6ICfiqLknLFxuICAgICAgICAgICAgICAgIHBsdXNNaW51cyAgICAgICAgIDogJ8KxJyxcbiAgICAgICAgICAgICAgICBtaW51c1BsdXMgICAgICAgICA6ICfiiJMnLFxuICAgICAgICAgICAgICAgIGRvdFBsdXMgICAgICAgICAgIDogJ+KIlCcsXG4gICAgICAgICAgICAgICAgYWx0SGVicmV3UGx1cyAgICAgOiAn76ypJyxcbiAgICAgICAgICAgICAgICBub3JtYWxTcGFjZSAgICAgICA6ICcgJyxcbiAgICAgICAgICAgICAgICB0aGluU3BhY2UgICAgICAgICA6ICdcXHUyMDA5JyxcbiAgICAgICAgICAgICAgICBuYXJyb3dOb0JyZWFrU3BhY2U6ICdcXHUyMDJmJyxcbiAgICAgICAgICAgICAgICBub0JyZWFrU3BhY2UgICAgICA6ICdcXHUwMGEwJyxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIFRoZSBgcmF3VmFsdWVEaXZpc29yYCBkaXZpZGVzIHRoZSBmb3JtYXR0ZWQgdmFsdWUgc2hvd24gaW4gdGhlIEF1dG9OdW1lcmljIGVsZW1lbnQgYW5kIHN0b3JlIHRoZSByZXN1bHQgaW4gYHJhd1ZhbHVlYC5cbiAgICAgICAgICAgICAqIEBleGFtcGxlIHsgcmF3VmFsdWVEaXZpc29yOiAnMTAwJyB9IG9yIDxpbnB1dCBkYXRhLXJhdy12YWx1ZS1kaXZpc29yPVwiMTAwXCI+XG4gICAgICAgICAgICAgKiBHaXZlbiB0aGUgYDAuMDEyMzRgIHJhdyB2YWx1ZSwgdGhlIGZvcm1hdHRlZCB2YWx1ZSB3aWxsIGJlIGRpc3BsYXllZCBhcyBgJzEuMjM0J2AuXG4gICAgICAgICAgICAgKiBUaGlzIGlzIHVzZWZ1bCB3aGVuIGRpc3BsYXlpbmcgcGVyY2VudGFnZSBmb3IgaW5zdGFuY2UsIGFuZCBhdm9pZCB0aGUgbmVlZCB0byBkaXZpZGUvbXVsdGlwbHkgYnkgMTAwIGJldHdlZW4gdGhlIG51bWJlciBzaG93biBhbmQgdGhlIHJhdyB2YWx1ZS5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgcmF3VmFsdWVEaXZpc29yOiB7XG4gICAgICAgICAgICAgICAgbm9uZSAgICAgIDogbnVsbCxcbiAgICAgICAgICAgICAgICBwZXJjZW50YWdlOiAxMDAsXG4gICAgICAgICAgICAgICAgcGVybWlsbGUgIDogMTAwMCxcbiAgICAgICAgICAgICAgICBiYXNpc1BvaW50OiAxMDAwMCxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgaWYgdGhlIDxpbnB1dD4gZWxlbWVudCBzaG91bGQgYmUgc2V0IGFzIHJlYWQgb25seSBvbiBpbml0aWFsaXphdGlvbi5cbiAgICAgICAgICAgICAqIFdoZW4gc2V0IHRvIGB0cnVlYCwgdGhlbiB0aGUgYHJlYWRvbmx5YCBodG1sIHByb3BlcnR5IGlzIGFkZGVkIHRvIHRoZSA8aW5wdXQ+IGVsZW1lbnQgb24gaW5pdGlhbGl6YXRpb24uXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHJlYWRPbmx5OiB7XG4gICAgICAgICAgICAgICAgcmVhZE9ubHkgOiB0cnVlLFxuICAgICAgICAgICAgICAgIHJlYWRXcml0ZTogZmFsc2UsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIHRoZSByb3VuZGluZyBtZXRob2QgdG8gdXNlLlxuICAgICAgICAgICAgICogcm91bmRpbmdNZXRob2Q6IFwiU1wiLCBSb3VuZC1IYWxmLVVwIFN5bW1ldHJpYyAoZGVmYXVsdClcbiAgICAgICAgICAgICAqIHJvdW5kaW5nTWV0aG9kOiBcIkFcIiwgUm91bmQtSGFsZi1VcCBBc3ltbWV0cmljXG4gICAgICAgICAgICAgKiByb3VuZGluZ01ldGhvZDogXCJzXCIsIFJvdW5kLUhhbGYtRG93biBTeW1tZXRyaWMgKGxvd2VyIGNhc2UgcylcbiAgICAgICAgICAgICAqIHJvdW5kaW5nTWV0aG9kOiBcImFcIiwgUm91bmQtSGFsZi1Eb3duIEFzeW1tZXRyaWMgKGxvd2VyIGNhc2UgYSlcbiAgICAgICAgICAgICAqIHJvdW5kaW5nTWV0aG9kOiBcIkJcIiwgUm91bmQtSGFsZi1FdmVuIFwiQmFua2VycyBSb3VuZGluZ1wiXG4gICAgICAgICAgICAgKiByb3VuZGluZ01ldGhvZDogXCJVXCIsIFJvdW5kIFVwIFwiUm91bmQtQXdheS1Gcm9tLVplcm9cIlxuICAgICAgICAgICAgICogcm91bmRpbmdNZXRob2Q6IFwiRFwiLCBSb3VuZCBEb3duIFwiUm91bmQtVG93YXJkLVplcm9cIiAtIHNhbWUgYXMgdHJ1bmNhdGVcbiAgICAgICAgICAgICAqIHJvdW5kaW5nTWV0aG9kOiBcIkNcIiwgUm91bmQgdG8gQ2VpbGluZyBcIlRvd2FyZCBQb3NpdGl2ZSBJbmZpbml0eVwiXG4gICAgICAgICAgICAgKiByb3VuZGluZ01ldGhvZDogXCJGXCIsIFJvdW5kIHRvIEZsb29yIFwiVG93YXJkIE5lZ2F0aXZlIEluZmluaXR5XCJcbiAgICAgICAgICAgICAqIHJvdW5kaW5nTWV0aG9kOiBcIk4wNVwiIFJvdW5kcyB0byB0aGUgbmVhcmVzdCAuMDUgPT4gc2FtZSBhcyBcIkNIRlwiIHVzZWQgaW4gMS45WCBhbmQgc3RpbGwgdmFsaWRcbiAgICAgICAgICAgICAqIHJvdW5kaW5nTWV0aG9kOiBcIlUwNVwiIFJvdW5kcyB1cCB0byBuZXh0IC4wNVxuICAgICAgICAgICAgICogcm91bmRpbmdNZXRob2Q6IFwiRDA1XCIgUm91bmRzIGRvd24gdG8gbmV4dCAuMDVcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgcm91bmRpbmdNZXRob2Q6IHtcbiAgICAgICAgICAgICAgICBoYWxmVXBTeW1tZXRyaWMgICAgICAgICAgICAgICAgOiAnUycsXG4gICAgICAgICAgICAgICAgaGFsZlVwQXN5bW1ldHJpYyAgICAgICAgICAgICAgIDogJ0EnLFxuICAgICAgICAgICAgICAgIGhhbGZEb3duU3ltbWV0cmljICAgICAgICAgICAgICA6ICdzJyxcbiAgICAgICAgICAgICAgICBoYWxmRG93bkFzeW1tZXRyaWMgICAgICAgICAgICAgOiAnYScsXG4gICAgICAgICAgICAgICAgaGFsZkV2ZW5CYW5rZXJzUm91bmRpbmcgICAgICAgIDogJ0InLFxuICAgICAgICAgICAgICAgIHVwUm91bmRBd2F5RnJvbVplcm8gICAgICAgICAgICA6ICdVJyxcbiAgICAgICAgICAgICAgICBkb3duUm91bmRUb3dhcmRaZXJvICAgICAgICAgICAgOiAnRCcsXG4gICAgICAgICAgICAgICAgdG9DZWlsaW5nVG93YXJkUG9zaXRpdmVJbmZpbml0eTogJ0MnLFxuICAgICAgICAgICAgICAgIHRvRmxvb3JUb3dhcmROZWdhdGl2ZUluZmluaXR5ICA6ICdGJyxcbiAgICAgICAgICAgICAgICB0b05lYXJlc3QwNSAgICAgICAgICAgICAgICAgICAgOiAnTjA1JyxcbiAgICAgICAgICAgICAgICB0b05lYXJlc3QwNUFsdCAgICAgICAgICAgICAgICAgOiAnQ0hGJyxcbiAgICAgICAgICAgICAgICB1cFRvTmV4dDA1ICAgICAgICAgICAgICAgICAgICAgOiAnVTA1JyxcbiAgICAgICAgICAgICAgICBkb3duVG9OZXh0MDUgICAgICAgICAgICAgICAgICAgOiAnRDA1JyxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIFNldCB0byBgdHJ1ZWAgdG8gYWxsb3cgdGhlIGBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzYCB2YWx1ZSB0byBiZSBzYXZlZCB3aXRoIHNlc3Npb25TdG9yYWdlXG4gICAgICAgICAgICAgKiBJZiBJRSA2IG9yIDcgaXMgZGV0ZWN0ZWQsIHRoZSB2YWx1ZSB3aWxsIGJlIHNhdmVkIGFzIGEgc2Vzc2lvbiBjb29raWUuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2U6IHtcbiAgICAgICAgICAgICAgICBzYXZlICAgICA6IHRydWUsXG4gICAgICAgICAgICAgICAgZG9Ob3RTYXZlOiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERldGVybWluZSBpZiB0aGUgc2VsZWN0IGFsbCBrZXlib2FyZCBjb21tYW5kIHdpbGwgc2VsZWN0IHRoZSBjb21wbGV0ZSBpbnB1dCB0ZXh0LCBvciBvbmx5IHRoZSBpbnB1dCBudW1lcmljIHZhbHVlXG4gICAgICAgICAgICAgKiBOb3RlIDogSWYgdGhlIGN1cnJlbmN5IHN5bWJvbCBpcyBiZXR3ZWVuIHRoZSBudW1lcmljIHZhbHVlIGFuZCB0aGUgbmVnYXRpdmUgc2lnbiwgb25seSB0aGUgbnVtZXJpYyB2YWx1ZSB3aWxsIGJlIHNlbGVjdGVkXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNlbGVjdE51bWJlck9ubHk6IHtcbiAgICAgICAgICAgICAgICBzZWxlY3ROdW1iZXJzT25seTogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzZWxlY3RBbGwgICAgICAgIDogZmFsc2UsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIGlmIHRoZSBlbGVtZW50IHZhbHVlIHNob3VsZCBiZSBzZWxlY3RlZCBvbiBmb2N1cy5cbiAgICAgICAgICAgICAqIE5vdGU6IFRoZSBzZWxlY3Rpb24gaXMgZG9uZSB1c2luZyB0aGUgYHNlbGVjdE51bWJlck9ubHlgIG9wdGlvbi5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2VsZWN0T25Gb2N1czoge1xuICAgICAgICAgICAgICAgIHNlbGVjdCAgICAgOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRvTm90U2VsZWN0OiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgaG93IHRoZSBzZXJpYWxpemUgZnVuY3Rpb25zIHNob3VsZCB0cmVhdCB0aGUgc3BhY2VzLlxuICAgICAgICAgICAgICogVGhvc2Ugc3BhY2VzICcgJyBjYW4gZWl0aGVyIGJlIGNvbnZlcnRlZCB0byB0aGUgcGx1cyBzaWduICcrJywgd2hpY2ggaXMgdGhlIGRlZmF1bHQsIG9yIHRvICclMjAnLlxuICAgICAgICAgICAgICogQm90aCB2YWx1ZXMgYmVpbmcgdmFsaWQgcGVyIHRoZSBzcGVjIChodHRwOi8vd3d3LnczLm9yZy9BZGRyZXNzaW5nL1VSTC91cmktc3BlYy5odG1sKS5cbiAgICAgICAgICAgICAqIEFsc28gc2VlIHRoZSBzdW1tZWQgdXAgYW5zd2VyIG9uIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzMzOTM5Mjg3LlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIHRsO2RyIDogU3BhY2VzIHNob3VsZCBiZSBjb252ZXJ0ZWQgdG8gJyUyMCcgYmVmb3JlIHRoZSAnPycgc2lnbiwgdGhlbiBjb252ZXJ0ZWQgdG8gJysnIGFmdGVyLlxuICAgICAgICAgICAgICogSW4gb3VyIGNhc2Ugc2luY2Ugd2Ugc2VyaWFsaXplIHRoZSBxdWVyeSwgd2UgdXNlICcrJyBhcyB0aGUgZGVmYXVsdCAoYnV0IGFsbG93IHRoZSB1c2VyIHRvIGdldCBiYWNrIHRoZSBvbGQgKndyb25nKiBiZWhhdmlvcikuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNlcmlhbGl6ZVNwYWNlczoge1xuICAgICAgICAgICAgICAgIHBsdXMgICA6ICcrJyxcbiAgICAgICAgICAgICAgICBwZXJjZW50OiAnJTIwJyxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgaWYgdGhlIGVsZW1lbnQgdmFsdWUgc2hvdWxkIGJlIGNvbnZlcnRlZCB0byB0aGUgcmF3IHZhbHVlIG9uIGZvY3VzIChhbmQgYmFjayB0byB0aGUgZm9ybWF0dGVkIG9uIGJsdXIpLlxuICAgICAgICAgICAgICogSWYgc2V0IHRvIGB0cnVlYCwgdGhlbiBhdXRvTnVtZXJpYyByZW1vdmUgdGhlIHRob3VzYW5kIHNlcGFyYXRvciwgY3VycmVuY3kgc3ltYm9sIGFuZCBzdWZmaXggb24gZm9jdXMuXG4gICAgICAgICAgICAgKiBFeGFtcGxlOlxuICAgICAgICAgICAgICogSWYgdGhlIGlucHV0IHZhbHVlIGlzICckIDEsOTk5Ljg4IHN1ZmZpeCcsIG9uIGZvY3VzIGl0IGJlY29tZXMgJzE5OTkuODgnIGFuZCBiYWNrIHRvICckIDEsOTk5Ljg4IHN1ZmZpeCcgb24gYmx1ci5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2hvd09ubHlOdW1iZXJzT25Gb2N1czoge1xuICAgICAgICAgICAgICAgIG9ubHlOdW1iZXJzOiB0cnVlLFxuICAgICAgICAgICAgICAgIHNob3dBbGwgICAgOiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIEFsbG93IHRoZSBwb3NpdGl2ZSBzaWduIHN5bWJvbCBgK2AgdG8gYmUgZGlzcGxheWVkIGZvciBwb3NpdGl2ZSBudW1iZXJzLlxuICAgICAgICAgICAgICogQnkgZGVmYXVsdCwgdGhpcyBwb3NpdGl2ZSBzaWduIGlzIG5vdCBzaG93bi5cbiAgICAgICAgICAgICAqIFRoZSBzaWduIHBsYWNlbWVudCBpcyBjb250cm9sbGVkIGJ5IHRoZSAnbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQnIG9wdGlvbiwgbWltaWNraW5nIHRoZSBuZWdhdGl2ZSBzaWduIHBsYWNlbWVudCBydWxlcy5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2hvd1Bvc2l0aXZlU2lnbjoge1xuICAgICAgICAgICAgICAgIHNob3c6IHRydWUsXG4gICAgICAgICAgICAgICAgaGlkZTogZmFsc2UsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIGlmIHdhcm5pbmdzIHNob3VsZCBiZSBzaG93biBpbiB0aGUgY29uc29sZS5cbiAgICAgICAgICAgICAqIFRob3NlIHdhcm5pbmdzIGNhbiBiZSBpZ25vcmVkLCBidXQgYXJlIHVzdWFsbHkgcHJpbnRlZCB3aGVuIHNvbWV0aGluZyBjb3VsZCBiZSBpbXByb3ZlZCBieSB0aGUgdXNlciAoaWUuIG9wdGlvbiBjb25mbGljdHMpLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzaG93V2FybmluZ3M6IHtcbiAgICAgICAgICAgICAgICBzaG93OiB0cnVlLCAvLyBBbGwgd2FybmluZyBhcmUgc2hvd25cbiAgICAgICAgICAgICAgICBoaWRlOiBmYWxzZSwgLy8gTm8gd2FybmluZ3MgYXJlIHNob3duLCBvbmx5IHRoZSB0aHJvd24gZXJyb3JzXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIHRoZSBydWxlcyB0aGF0IGNhbGN1bGF0ZSB0aGUgQ1NTIGNsYXNzKGVzKSB0byBhcHBseSBvbiB0aGUgZWxlbWVudCwgYmFzZWQgb24gdGhlIHJhdyB1bmZvcm1hdHRlZCB2YWx1ZS5cbiAgICAgICAgICAgICAqIFRoaXMgY2FuIGFsc28gYmUgdXNlZCB0byBjYWxsIGNhbGxiYWNrcyB3aGVuZXZlciB0aGUgYHJhd1ZhbHVlYCBpcyB1cGRhdGVkLlxuICAgICAgICAgICAgICogSW1wb3J0YW50OiBhbGwgY2FsbGJhY2tzIG11c3QgcmV0dXJuIGBudWxsYCBpZiBubyByYW5nZXMvdXNlckRlZmluZWQgY2xhc3NlcyBhcmUgc2VsZWN0ZWRcbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKiB7XG4gICAgICAgICAgICAgKiAgICAgcG9zaXRpdmUgICA6ICdhdXRvTnVtZXJpYy1wb3NpdGl2ZScsIC8vIE9yIGBudWxsYCB0byBub3QgdXNlIGl0XG4gICAgICAgICAgICAgKiAgICAgbmVnYXRpdmUgICA6ICdhdXRvTnVtZXJpYy1uZWdhdGl2ZScsXG4gICAgICAgICAgICAgKiAgICAgcmFuZ2VzICAgICA6IFtcbiAgICAgICAgICAgICAqICAgICAgICAgeyBtaW46IDAsIG1heDogMjUsIGNsYXNzOiAnYXV0b051bWVyaWMtcmVkJyB9LFxuICAgICAgICAgICAgICogICAgICAgICB7IG1pbjogMjUsIG1heDogNTAsIGNsYXNzOiAnYXV0b051bWVyaWMtb3JhbmdlJyB9LFxuICAgICAgICAgICAgICogICAgICAgICB7IG1pbjogNTAsIG1heDogNzUsIGNsYXNzOiAnYXV0b051bWVyaWMteWVsbG93JyB9LFxuICAgICAgICAgICAgICogICAgICAgICB7IG1pbjogNzUsIG1heDogTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIsIGNsYXNzOiAnYXV0b051bWVyaWMtZ3JlZW4nIH0sXG4gICAgICAgICAgICAgKiAgICAgXSxcbiAgICAgICAgICAgICAqICAgICB1c2VyRGVmaW5lZDogW1xuICAgICAgICAgICAgICogICAgICAgICAvLyBJZiAnY2xhc3NlcycgaXMgYSBzdHJpbmcsIHNldCBpdCBpZiBgdHJ1ZWAsIHJlbW92ZSBpdCBpZiBgZmFsc2VgXG4gICAgICAgICAgICAgKiAgICAgICAgIHsgY2FsbGJhY2s6IHJhd1ZhbHVlID0+IHsgcmV0dXJuIHRydWU7IH0sIGNsYXNzZXM6ICd0aGlzSXNUcnVlJyB9LFxuICAgICAgICAgICAgICogICAgICAgICAvLyBJZiAnY2xhc3NlcycgaXMgYW4gYXJyYXkgd2l0aCBvbmx5IDIgZWxlbWVudHMsIHNldCB0aGUgZmlyc3QgY2xhc3MgaWYgYHRydWVgLCB0aGUgc2Vjb25kIGlmIGBmYWxzZWBcbiAgICAgICAgICAgICAqICAgICAgICAgeyBjYWxsYmFjazogcmF3VmFsdWUgPT4gcmF3VmFsdWUgJSAyID09PSAwLCBjbGFzc2VzOiBbJ2F1dG9OdW1lcmljLWV2ZW4nLCAnYXV0b051bWVyaWMtb2RkJ10gfSxcbiAgICAgICAgICAgICAqICAgICAgICAgLy8gUmV0dXJuIG9ubHkgb25lIGluZGV4IHRvIHVzZSBvbiB0aGUgYGNsYXNzZXNgIGFycmF5IChoZXJlLCAnY2xhc3MzJylcbiAgICAgICAgICAgICAqICAgICAgICAgeyBjYWxsYmFjazogcmF3VmFsdWUgPT4geyByZXR1cm4gMjsgfSwgY2xhc3NlczogWydjbGFzczEnLCAnY2xhc3MyJywgJ2NsYXNzMyddIH0sXG4gICAgICAgICAgICAgKiAgICAgICAgIC8vIFJldHVybiBhbiBhcnJheSBvZiBpbmRleGVzIHRvIHVzZSBvbiB0aGUgYGNsYXNzZXNgIGFycmF5IChoZXJlLCAnY2xhc3MxJyBhbmQgJ2NsYXNzMycpXG4gICAgICAgICAgICAgKiAgICAgICAgIHsgY2FsbGJhY2s6IHJhd1ZhbHVlID0+IHsgcmV0dXJuIFswLCAyXTsgfSwgY2xhc3NlczogWydjbGFzczEnLCAnY2xhc3MyJywgJ2NsYXNzMyddIH0sXG4gICAgICAgICAgICAgKiAgICAgICAgIC8vIElmICdjbGFzc2VzJyBpcyBgdW5kZWZpbmVkYCBvciBgbnVsbGAsIHRoZW4gdGhlIGNhbGxiYWNrIGlzIGNhbGxlZCB3aXRoIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgcGFzc2VkIGFzIGEgcGFyYW1ldGVyXG4gICAgICAgICAgICAgKiAgICAgICAgIHsgY2FsbGJhY2s6IGFuRWxlbWVudCA9PiB7IHJldHVybiBhbkVsZW1lbnQuZ2V0Rm9ybWF0dGVkKCk7IH0gfSxcbiAgICAgICAgICAgICAqICAgICBdLFxuICAgICAgICAgICAgICogfVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzdHlsZVJ1bGVzOiB7XG4gICAgICAgICAgICAgICAgbm9uZSAgICAgICAgICAgICAgICAgOiBudWxsLFxuICAgICAgICAgICAgICAgIHBvc2l0aXZlTmVnYXRpdmUgICAgIDoge1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGl2ZTogJ2F1dG9OdW1lcmljLXBvc2l0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgbmVnYXRpdmU6ICdhdXRvTnVtZXJpYy1uZWdhdGl2ZScsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICByYW5nZTBUbzEwMFdpdGg0U3RlcHM6IHtcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2VzOiBbXG4gICAgICAgICAgICAgICAgICAgICAgICB7IG1pbjogMCwgbWF4OiAyNSwgY2xhc3M6ICdhdXRvTnVtZXJpYy1yZWQnIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICB7IG1pbjogMjUsIG1heDogNTAsIGNsYXNzOiAnYXV0b051bWVyaWMtb3JhbmdlJyB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgeyBtaW46IDUwLCBtYXg6IDc1LCBjbGFzczogJ2F1dG9OdW1lcmljLXllbGxvdycgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHsgbWluOiA3NSwgbWF4OiAxMDAsIGNsYXNzOiAnYXV0b051bWVyaWMtZ3JlZW4nIH0sXG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBldmVuT2RkICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgICAgdXNlckRlZmluZWQ6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHsgY2FsbGJhY2s6IHJhd1ZhbHVlID0+IHJhd1ZhbHVlICUgMiA9PT0gMCwgY2xhc3NlczogWydhdXRvTnVtZXJpYy1ldmVuJywgJ2F1dG9OdW1lcmljLW9kZCddIH0sXG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICByYW5nZVNtYWxsQW5kWmVybyAgICA6IHtcbiAgICAgICAgICAgICAgICAgICAgdXNlckRlZmluZWQ6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayAgOiByYXdWYWx1ZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyYXdWYWx1ZSA+PSAtMSAmJiByYXdWYWx1ZSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChOdW1iZXIocmF3VmFsdWUpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmF3VmFsdWUgPiAwICYmIHJhd1ZhbHVlIDw9IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7ICAvLyBJbiBjYXNlIHRoZSByYXdWYWx1ZSBpcyBvdXRzaWRlIHRob3NlIHJhbmdlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2xhc3NlczogW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnYXV0b051bWVyaWMtc21hbGwtbmVnYXRpdmUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnYXV0b051bWVyaWMtemVybycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICdhdXRvTnVtZXJpYy1zbWFsbC1wb3NpdGl2ZScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIEFkZCBhIHRleHQgb24gdGhlIHJpZ2h0IGhhbmQgc2lkZSBvZiB0aGUgZWxlbWVudCB2YWx1ZS5cbiAgICAgICAgICAgICAqIFRoaXMgc3VmZml4IHRleHQgY2FuIGhhdmUgYW55IGNoYXJhY3RlcnMgaW4gaXRzIHN0cmluZywgZXhjZXB0IG51bWVyaWMgY2hhcmFjdGVycyBhbmQgdGhlIG5lZ2F0aXZlL3Bvc2l0aXZlIHNpZ24uXG4gICAgICAgICAgICAgKiBFeGFtcGxlOiAnIGRvbGxhcnMnXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHN1ZmZpeFRleHQ6IHtcbiAgICAgICAgICAgICAgICBub25lICAgICAgOiAnJyxcbiAgICAgICAgICAgICAgICBwZXJjZW50YWdlOiAnJScsXG4gICAgICAgICAgICAgICAgcGVybWlsbGUgIDogJ+KAsCcsXG4gICAgICAgICAgICAgICAgYmFzaXNQb2ludDogJ+KAsScsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBUaGUgdGhyZWUgb3B0aW9ucyAoZGl2aXNvcldoZW5VbmZvY3VzZWQsIGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciAmIHN5bWJvbFdoZW5VbmZvY3VzZWQpIGhhbmRsZSBzY2FsaW5nIG9mIHRoZSBpbnB1dCB3aGVuIHRoZSBpbnB1dCBkb2VzIG5vdCBoYXZlIGZvY3VzXG4gICAgICAgICAgICAgKiBQbGVhc2Ugbm90ZSB0aGF0IHRoZSBub24tc2NhbGVkIHZhbHVlIGlzIGhlbGQgaW4gZGF0YSBhbmQgaXQgaXMgYWR2aXNlZCB0aGF0IHlvdSB1c2UgdGhlIGBzYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlYCBvcHRpb24gdG8gZW5zdXJlIHJldGFpbmluZyB0aGUgdmFsdWVcbiAgICAgICAgICAgICAqIFtcImRpdmlzb3JcIiwgXCJkZWNpbWFsIHBsYWNlc1wiLCBcInN5bWJvbFwiXVxuICAgICAgICAgICAgICogRXhhbXBsZTogd2l0aCB0aGUgZm9sbG93aW5nIG9wdGlvbnMgc2V0IHtkaXZpc29yV2hlblVuZm9jdXNlZDogJzEwMDAnLCBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXI6ICcxJywgc3ltYm9sV2hlblVuZm9jdXNlZDogJyBLJ31cbiAgICAgICAgICAgICAqIEV4YW1wbGU6IGZvY3VzaW4gdmFsdWUgXCIxLDExMS4xMVwiIGZvY3Vzb3V0IHZhbHVlIFwiMS4xIEtcIlxuICAgICAgICAgICAgICovXG5cbiAgICAgICAgICAgIC8qIFRoZSBgc3ltYm9sV2hlblVuZm9jdXNlZGAgb3B0aW9uIGlzIGEgc3ltYm9sIHBsYWNlZCBhcyBhIHN1ZmZpeCB3aGVuIG5vdCBpbiBmb2N1cy5cbiAgICAgICAgICAgICAqIFRoaXMgaXMgb3B0aW9uYWwgdG9vLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzeW1ib2xXaGVuVW5mb2N1c2VkOiB7XG4gICAgICAgICAgICAgICAgbm9uZSAgICAgIDogbnVsbCxcbiAgICAgICAgICAgICAgICBwZXJjZW50YWdlOiAnJScsXG4gICAgICAgICAgICAgICAgcGVybWlsbGUgIDogJ+KAsCcsXG4gICAgICAgICAgICAgICAgYmFzaXNQb2ludDogJ+KAsScsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIGlmIHRoZSBlbGVtZW50IHZhbHVlIHNob3VsZCBiZSB1bmZvcm1hdHRlZCB3aGVuIHRoZSB1c2VyIGhvdmVyIGhpcyBtb3VzZSBvdmVyIGl0IHdoaWxlIGhvbGRpbmcgdGhlIGBBbHRgIGtleS5cbiAgICAgICAgICAgICAqIFVuZm9ybWF0dGluZyB0aGVyZSBtZWFucyB0aGF0IHRoaXMgcmVtb3ZlcyBhbnkgbm9uLW51bWJlciBjaGFyYWN0ZXJzIGFuZCBkaXNwbGF5cyB0aGUgKnJhdyogdmFsdWUsIGFzIHVuZGVyc3Rvb2QgYnkgSmF2YXNjcmlwdCAoaWUuIGAxMi4zNGAgaXMgYSB2YWxpZCBudW1iZXIsIHdoaWxlIGAxMiwzNGAgaXMgbm90KS5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBXZSByZWZvcm1hdCBiYWNrIGJlZm9yZSBhbnl0aGluZyBlbHNlIGlmIDpcbiAgICAgICAgICAgICAqIC0gdGhlIHVzZXIgZm9jdXMgb24gdGhlIGVsZW1lbnQgYnkgdGFiYmluZyBvciBjbGlja2luZyBpbnRvIGl0LFxuICAgICAgICAgICAgICogLSB0aGUgdXNlciByZWxlYXNlcyB0aGUgYEFsdGAga2V5LCBhbmRcbiAgICAgICAgICAgICAqIC0gaWYgd2UgZGV0ZWN0IGEgbW91c2VsZWF2ZSBldmVudC5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBXZSB1bmZvcm1hdCBhZ2FpbiBpZiA6XG4gICAgICAgICAgICAgKiAtIHdoaWxlIHRoZSBtb3VzZSBpcyBvdmVyIHRoZSBlbGVtZW50LCB0aGUgdXNlciBoaXQgYEFsdGAgYWdhaW5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdW5mb3JtYXRPbkhvdmVyOiB7XG4gICAgICAgICAgICAgICAgdW5mb3JtYXQgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBkb05vdFVuZm9ybWF0OiBmYWxzZSwgLy9UT0RPIFJlbmFtZSB0byBga2VlcEZvcm1hdGBcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIFJlbW92ZXMgdGhlIGZvcm1hdHRpbmcgYW5kIHVzZSB0aGUgcmF3IHZhbHVlIGluIGVhY2ggYXV0b051bWVyaWMgZWxlbWVudHMgb2YgdGhlIHBhcmVudCBmb3JtIGVsZW1lbnQsIG9uIHRoZSBmb3JtIGBzdWJtaXRgIGV2ZW50LlxuICAgICAgICAgICAgICogVGhlIG91dHB1dCBmb3JtYXQgaXMgYSBudW1lcmljIHN0cmluZyAobm5ubi5ubiBvciAtbm5ubi5ubikuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHVuZm9ybWF0T25TdWJtaXQ6IHtcbiAgICAgICAgICAgICAgICB1bmZvcm1hdCAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgICAgIGtlZXBDdXJyZW50VmFsdWU6IGZhbHNlLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogUHJvdmlkZXMgYSB3YXkgZm9yIGF1dG9tYXRpY2FsbHkgcmVwbGFjaW5nIHRoZSBmb3JtYXR0ZWQgdmFsdWUgd2l0aCBhIHByZS1kZWZpbmVkIHN0cmluZywgd2hlbiB0aGUgcmF3IHZhbHVlIGlzIGVxdWFsIHRvIGEgc3BlY2lmaWMgdmFsdWVcbiAgICAgICAgICAgICAqIEhlcmUgeW91IGNhbiBzcGVjaWZ5IGFzIG1hbnkgJ2NvbnZlcnNpb24nIGFzIG5lZWRlZC5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdmFsdWVzVG9TdHJpbmdzOiB7XG4gICAgICAgICAgICAgICAgbm9uZSAgICAgICAgIDogbnVsbCxcbiAgICAgICAgICAgICAgICB6ZXJvRGFzaCAgICAgOiB7XG4gICAgICAgICAgICAgICAgICAgIDA6ICctJyxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIG9uZUFyb3VuZFplcm86IHtcbiAgICAgICAgICAgICAgICAgICAgJy0xJzogJ01pbicsXG4gICAgICAgICAgICAgICAgICAgIDEgICA6ICdNYXgnLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIGlmIHRoZSBBdXRvTnVtZXJpYyBlbGVtZW50IHNob3VsZCB3YXRjaCBleHRlcm5hbCBjaGFuZ2VzIG1hZGUgd2l0aG91dCB1c2luZyBgLnNldCgpYCwgYnV0IGJ5IHVzaW5nIHRoZSBiYXNpYyBgYU5FbGVtZW50Lm5vZGUoKS52YWx1ZSA9IDQyYCBub3RhdGlvbi5cbiAgICAgICAgICAgICAqIElmIHNldCB0byBgd2F0Y2hgLCB0aGVuIEF1dG9OdW1lcmljIHdpbGwgZm9ybWF0IHRoZSBuZXcgdmFsdWUgdXNpbmcgYC5zZXQoKWAgaW50ZXJuYWxseS5cbiAgICAgICAgICAgICAqIE90aGVyd2lzZSBpdCB3aWxsIG5laXRoZXIgZm9ybWF0IGl0LCBub3Igc2F2ZSBpdCBpbiB0aGUgaGlzdG9yeS5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgd2F0Y2hFeHRlcm5hbENoYW5nZXM6IHtcbiAgICAgICAgICAgICAgICB3YXRjaCAgICAgOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRvTm90V2F0Y2g6IGZhbHNlLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyB3aGVuIHRoZSB3aGVlbCBldmVudCB3aWxsIGluY3JlbWVudCBvciBkZWNyZW1lbnQgdGhlIGVsZW1lbnQgdmFsdWUuXG4gICAgICAgICAgICAgKiBXaGVuIHNldCB0byBgJ2ZvY3VzJ2AsIHRoZSBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnQgbmVlZHMgdG8gYmUgZm9jdXNlZCBmb3IgdGhlIHdoZWVsIGV2ZW50IHRvIGNoYW5nZSB0aGUgdmFsdWUuXG4gICAgICAgICAgICAgKiBXaGVuIHNldCB0byBgJ2hvdmVyJ2AsIHVzaW5nIHRoZSB3aGVlbCBldmVudCB3aGlsZSB0aGUgbW91c2UgaXMgaG92ZXJpbmcgdGhlIGVsZW1lbnQgaXMgc3VmZmljaWVudCAobm8gZm9jdXMgbmVlZGVkKS5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBOb3RlIDpcbiAgICAgICAgICAgICAqIFdoZW4gYHdoZWVsT25gIGlzIHNldCB0byBgJ2ZvY3VzJ2AsIHlvdSBjYW4gdXNlIHRoZSAnU2hpZnQnIG1vZGlmaWVyIGtleSB3aGlsZSB1c2luZyB0aGUgbW91c2Ugd2hlZWwgaW4gb3JkZXIgdG8gdGVtcG9yYXJpbHkgYWN0aXZhdGUgdGhlIGluY3JlbWVudC9kZWNyZW1lbnQgZmVhdHVyZSBldmVuIGlmIHRoZSBlbGVtZW50IGlzIG5vdCBmb2N1c2VkLlxuICAgICAgICAgICAgICogV2hlbiBgd2hlZWxPbmAgaXMgc2V0IHRvIGAnaG92ZXInYCwgeW91IGNhbiB1c2UgdGhlICdTaGlmdCcgbW9kaWZpZXIga2V5IHdoaWxlIHVzaW5nIHRoZSBtb3VzZSB3aGVlbCBpbiBvcmRlciB0byB0ZW1wb3JhcmlseSBkaXNhYmxlIHRoZSBpbmNyZW1lbnQvZGVjcmVtZW50IGZlYXR1cmUgZXZlbiBpZiB0aGUgZWxlbWVudCBpcyBub3QgaG92ZXJlZC5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgd2hlZWxPbjoge1xuICAgICAgICAgICAgICAgIGZvY3VzOiAnZm9jdXMnLFxuICAgICAgICAgICAgICAgIGhvdmVyOiAnaG92ZXInLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogVGhhdCBvcHRpb24gaXMgbGlua2VkIHRvIHRoZSBgbW9kaWZ5VmFsdWVPbldoZWVsYCBvbmUgYW5kIHdpbGwgb25seSBiZSB1c2VkIGlmIHRoZSBsYXR0ZXIgaXMgc2V0IHRvIGB0cnVlYC5cbiAgICAgICAgICAgICAqIFRoaXMgb3B0aW9uIHdpbGwgbW9kaWZ5IHRoZSB3aGVlbCBiZWhhdmlvciBhbmQgY2FuIGJlIHVzZWQgaW4gdHdvIHdheXMsIGVpdGhlciBieSBzZXR0aW5nIDpcbiAgICAgICAgICAgICAqIC0gYSAnZml4ZWQnIHN0ZXAgdmFsdWUgKGEgcG9zaXRpdmUgZmxvYXQgb3IgaW50ZWdlciBudW1iZXIgYDEwMDBgKSwgb3JcbiAgICAgICAgICAgICAqIC0gdGhlIGAncHJvZ3Jlc3NpdmUnYCBzdHJpbmcuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogVGhlICdmaXhlZCcgbW9kZSBhbHdheXMgaW5jcmVtZW50L2RlY3JlbWVudCB0aGUgZWxlbWVudCB2YWx1ZSBieSB0aGF0IGFtb3VudCwgd2hpbGUgcmVzcGVjdGluZyB0aGUgYG1pbmltdW1WYWx1ZWAgYW5kIGBtYXhpbXVtVmFsdWVgIHNldHRpbmdzLlxuICAgICAgICAgICAgICogVGhlICdwcm9ncmVzc2l2ZScgbW9kZSB3aWxsIGluY3JlbWVudC9kZWNyZW1lbnQgdGhlIGVsZW1lbnQgdmFsdWUgYmFzZWQgb24gaXRzIGN1cnJlbnQgdmFsdWUuIFRoZSBiaWdnZXIgdGhlIG51bWJlciwgdGhlIGJpZ2dlciB0aGUgc3RlcCwgYW5kIHZpY2UgdmVyc2EuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHdoZWVsU3RlcDoge1xuICAgICAgICAgICAgICAgIHByb2dyZXNzaXZlOiAncHJvZ3Jlc3NpdmUnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICB9LFxufSk7XG4iXSwibWFwcGluZ3MiOiI7O0FBNkJBO0FBQ0E7Ozs7O0FBQ0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUhBO0FBQ0E7QUFLQTs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUxBO0FBQ0E7QUFPQTs7O0FBR0E7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBNUNBO0FBQ0E7QUE4Q0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTEE7QUFDQTtBQU9BOzs7O0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFIQTtBQUNBO0FBS0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFQQTtBQUNBO0FBU0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBUkE7QUFDQTtBQVVBOzs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBUkE7QUFDQTtBQVVBOzs7Ozs7OztBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQVJBO0FBQ0E7QUFVQTs7Ozs7O0FBTUE7QUFDQTtBQURBO0FBQ0E7QUFHQTs7Ozs7OztBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFKQTtBQUNBO0FBTUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFWQTtBQUNBO0FBWUE7Ozs7Ozs7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkE7QUFDQTtBQU1BOzs7Ozs7O0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTEE7QUFDQTtBQU9BOztBQUVBO0FBQ0E7QUFDQTtBQUZBO0FBQ0E7QUFJQTs7QUFFQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7O0FBRUE7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQU5BO0FBQ0E7QUFRQTs7Ozs7Ozs7OztBQVVBO0FBQ0E7QUFDQTtBQUZBO0FBQ0E7QUFJQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUhBO0FBQ0E7QUFLQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkE7QUFDQTtBQU1BOzs7Ozs7QUFNQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkE7QUFDQTtBQU1BOzs7Ozs7Ozs7QUFTQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFYQTtBQUNBO0FBYUE7Ozs7Ozs7Ozs7OztBQVlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUxBO0FBQ0E7QUFPQTs7O0FBR0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFaQTtBQUNBO0FBY0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7Ozs7Ozs7Ozs7OztBQWNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUxBO0FBQ0E7QUFPQTs7Ozs7Ozs7O0FBU0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFUQTtBQUNBO0FBV0E7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUpBO0FBQ0E7QUFNQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFoQkE7QUFDQTtBQWtCQTs7Ozs7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkE7QUFDQTtBQU1BOzs7QUFHQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7Ozs7Ozs7Ozs7Ozs7O0FBY0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQWJBO0FBQ0E7QUFlQTs7O0FBR0E7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7QUFHQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7OztBQUdBO0FBQ0E7QUFDQTtBQUZBO0FBQ0E7QUFJQTs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7Ozs7O0FBS0E7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7O0FBSUE7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7QUFHQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTJCQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBRkE7QUFJQTtBQUNBO0FBREE7QUFRQTtBQUNBO0FBQ0E7QUFBQTtBQUZBO0FBS0E7QUFDQTtBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFkQTtBQUZBO0FBbkJBO0FBQ0E7QUE0Q0E7Ozs7QUFJQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBSkE7QUFDQTtBQU1BOzs7Ozs7O0FBT0E7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFKQTtBQUNBO0FBTUE7Ozs7Ozs7Ozs7O0FBV0E7QUFDQTtBQUNBO0FBRkE7QUFDQTtBQUlBOzs7QUFHQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7OztBQUdBO0FBQ0E7QUFDQTtBQUNBO0FBREE7QUFHQTtBQUNBO0FBQ0E7QUFGQTtBQUxBO0FBQ0E7QUFVQTs7OztBQUlBO0FBQ0E7QUFDQTtBQUZBO0FBQ0E7QUFJQTs7Ozs7Ozs7QUFRQTtBQUNBO0FBQ0E7QUFGQTtBQUNBO0FBSUE7Ozs7Ozs7O0FBUUE7QUFDQTtBQURBO0FBaHhCQTtBQW94QkE7QUF0eEJBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/AutoNumericOptions.js\n"); /***/ }), /***/ "./src/AutoNumericPredefinedOptions.js": /*!*********************************************!*\ !*** ./src/AutoNumericPredefinedOptions.js ***! \*********************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval("\n\nvar _AutoNumeric = __webpack_require__(/*! ./AutoNumeric */ \"./src/AutoNumeric.js\");\n\nvar _AutoNumeric2 = _interopRequireDefault(_AutoNumeric);\n\nvar _AutoNumericHelper = __webpack_require__(/*! ./AutoNumericHelper */ \"./src/AutoNumericHelper.js\");\n\nvar _AutoNumericHelper2 = _interopRequireDefault(_AutoNumericHelper);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/**\n * Pre-defined options for autoNumeric.js\n * @author Alexandre Bonneau \n * @copyright © 2016 Alexandre Bonneau\n *\n * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sub license, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\nvar euro = { // Français\n digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.dot, // or '\\u202f'\n decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.comma,\n decimalCharacterAlternative: _AutoNumeric2.default.options.decimalCharacterAlternative.dot,\n currencySymbol: '\\u202F\\u20AC',\n currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.suffix,\n negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix\n};\n\nvar dollar = {\n digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.comma,\n decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n currencySymbol: _AutoNumeric2.default.options.currencySymbol.dollar,\n currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.prefix,\n negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.right\n};\n\nvar japanese = { // 日本語\n digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.comma,\n decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n currencySymbol: _AutoNumeric2.default.options.currencySymbol.yen,\n currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.prefix,\n negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.right\n};\n\n// Here we need to clone the initial objects in order to be able to edit the clones without affecting the originals\nvar euroPos = _AutoNumericHelper2.default.cloneObject(euro);\neuroPos.minimumValue = 0;\nvar euroNeg = _AutoNumericHelper2.default.cloneObject(euro);\neuroNeg.maximumValue = 0;\neuroNeg.negativePositiveSignPlacement = _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix;\n\nvar euroSpace = _AutoNumericHelper2.default.cloneObject(euro);\neuroSpace.digitGroupSeparator = _AutoNumeric2.default.options.digitGroupSeparator.normalSpace;\nvar euroSpacePos = _AutoNumericHelper2.default.cloneObject(euroSpace);\neuroSpacePos.minimumValue = 0;\nvar euroSpaceNeg = _AutoNumericHelper2.default.cloneObject(euroSpace);\neuroSpaceNeg.maximumValue = 0;\neuroSpaceNeg.negativePositiveSignPlacement = _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix;\n\nvar percentageEU2dec = _AutoNumericHelper2.default.cloneObject(euro);\npercentageEU2dec.currencySymbol = _AutoNumeric2.default.options.currencySymbol.none;\npercentageEU2dec.suffixText = '\\u202F' + _AutoNumeric2.default.options.suffixText.percentage;\npercentageEU2dec.wheelStep = 0.0001; // This targets the `rawValue`, not the formatted one\npercentageEU2dec.rawValueDivisor = _AutoNumeric2.default.options.rawValueDivisor.percentage;\nvar percentageEU2decPos = _AutoNumericHelper2.default.cloneObject(percentageEU2dec);\npercentageEU2decPos.minimumValue = 0;\nvar percentageEU2decNeg = _AutoNumericHelper2.default.cloneObject(percentageEU2dec);\npercentageEU2decNeg.maximumValue = 0;\npercentageEU2decNeg.negativePositiveSignPlacement = _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix;\n\nvar percentageEU3dec = _AutoNumericHelper2.default.cloneObject(percentageEU2dec);\npercentageEU3dec.decimalPlaces = 3;\nvar percentageEU3decPos = _AutoNumericHelper2.default.cloneObject(percentageEU2decPos);\npercentageEU3decPos.decimalPlaces = 3;\nvar percentageEU3decNeg = _AutoNumericHelper2.default.cloneObject(percentageEU2decNeg);\npercentageEU3decNeg.decimalPlaces = 3;\n\nvar dollarPos = _AutoNumericHelper2.default.cloneObject(dollar);\ndollarPos.minimumValue = 0;\nvar dollarNeg = _AutoNumericHelper2.default.cloneObject(dollar);\ndollarNeg.maximumValue = 0;\ndollarNeg.negativePositiveSignPlacement = _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix;\nvar dollarNegBrackets = _AutoNumericHelper2.default.cloneObject(dollarNeg);\ndollarNegBrackets.negativeBracketsTypeOnBlur = _AutoNumeric2.default.options.negativeBracketsTypeOnBlur.parentheses;\n\nvar percentageUS2dec = _AutoNumericHelper2.default.cloneObject(dollar);\npercentageUS2dec.currencySymbol = _AutoNumeric2.default.options.currencySymbol.none;\npercentageUS2dec.suffixText = _AutoNumeric2.default.options.suffixText.percentage;\npercentageUS2dec.wheelStep = 0.0001;\npercentageEU2dec.rawValueDivisor = _AutoNumeric2.default.options.rawValueDivisor.percentage;\nvar percentageUS2decPos = _AutoNumericHelper2.default.cloneObject(percentageUS2dec);\npercentageUS2decPos.minimumValue = 0;\nvar percentageUS2decNeg = _AutoNumericHelper2.default.cloneObject(percentageUS2dec);\npercentageUS2decNeg.maximumValue = 0;\npercentageUS2decNeg.negativePositiveSignPlacement = _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix;\n\nvar percentageUS3dec = _AutoNumericHelper2.default.cloneObject(percentageUS2dec);\npercentageUS3dec.decimalPlaces = 3;\nvar percentageUS3decPos = _AutoNumericHelper2.default.cloneObject(percentageUS2decPos);\npercentageUS3decPos.decimalPlaces = 3;\nvar percentageUS3decNeg = _AutoNumericHelper2.default.cloneObject(percentageUS2decNeg);\npercentageUS3decNeg.decimalPlaces = 3;\n\nvar turkish = _AutoNumericHelper2.default.cloneObject(euro);\nturkish.currencySymbol = _AutoNumeric2.default.options.currencySymbol.lira;\n\n/**\n * Predefined options for the most common languages\n */\nObject.defineProperty(_AutoNumeric2.default, 'predefinedOptions', {\n get: function get() {\n return {\n euro: euro,\n euroPos: euroPos,\n euroNeg: euroNeg,\n euroSpace: euroSpace,\n euroSpacePos: euroSpacePos,\n euroSpaceNeg: euroSpaceNeg,\n percentageEU2dec: percentageEU2dec,\n percentageEU2decPos: percentageEU2decPos,\n percentageEU2decNeg: percentageEU2decNeg,\n percentageEU3dec: percentageEU3dec,\n percentageEU3decPos: percentageEU3decPos,\n percentageEU3decNeg: percentageEU3decNeg,\n dollar: dollar,\n dollarPos: dollarPos,\n dollarNeg: dollarNeg,\n dollarNegBrackets: dollarNegBrackets,\n percentageUS2dec: percentageUS2dec,\n percentageUS2decPos: percentageUS2decPos,\n percentageUS2decNeg: percentageUS2decNeg,\n percentageUS3dec: percentageUS3dec,\n percentageUS3decPos: percentageUS3decPos,\n percentageUS3decNeg: percentageUS3decNeg,\n French: euro, // Français\n Spanish: euro, // Español\n NorthAmerican: dollar,\n British: {\n digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.comma,\n decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n currencySymbol: _AutoNumeric2.default.options.currencySymbol.pound,\n currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.prefix,\n negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.right\n },\n Swiss: { // Suisse\n digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.apostrophe,\n decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n currencySymbol: '\\u202FCHF',\n currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.suffix,\n negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.prefix\n },\n Japanese: japanese, // 日本語\n Chinese: japanese, // 中国語 (Chinese)\n Brazilian: {\n digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.dot,\n decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.comma,\n currencySymbol: _AutoNumeric2.default.options.currencySymbol.real,\n currencySymbolPlacement: _AutoNumeric2.default.options.currencySymbolPlacement.prefix,\n negativePositiveSignPlacement: _AutoNumeric2.default.options.negativePositiveSignPlacement.right\n },\n Turkish: turkish,\n dotDecimalCharCommaSeparator: {\n digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.comma,\n decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot\n },\n commaDecimalCharDotSeparator: {\n digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.dot,\n decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.comma,\n decimalCharacterAlternative: _AutoNumeric2.default.options.decimalCharacterAlternative.dot\n },\n integer: {\n decimalPlaces: 0\n },\n integerPos: {\n minimumValue: _AutoNumeric2.default.options.minimumValue.zero,\n decimalPlaces: 0\n },\n integerNeg: {\n maximumValue: _AutoNumeric2.default.options.maximumValue.zero,\n decimalPlaces: 0\n },\n float: {\n allowDecimalPadding: _AutoNumeric2.default.options.allowDecimalPadding.never\n },\n floatPos: {\n allowDecimalPadding: _AutoNumeric2.default.options.allowDecimalPadding.never,\n minimumValue: _AutoNumeric2.default.options.minimumValue.zero,\n maximumValue: _AutoNumeric2.default.options.maximumValue.tenTrillions\n },\n floatNeg: {\n allowDecimalPadding: _AutoNumeric2.default.options.allowDecimalPadding.never,\n minimumValue: _AutoNumeric2.default.options.minimumValue.tenTrillions,\n maximumValue: _AutoNumeric2.default.options.maximumValue.zero\n },\n numeric: {\n digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.noSeparator,\n decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n currencySymbol: _AutoNumeric2.default.options.currencySymbol.none\n },\n numericPos: {\n digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.noSeparator,\n decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n currencySymbol: _AutoNumeric2.default.options.currencySymbol.none,\n minimumValue: _AutoNumeric2.default.options.minimumValue.zero,\n maximumValue: _AutoNumeric2.default.options.maximumValue.tenTrillions\n },\n numericNeg: {\n digitGroupSeparator: _AutoNumeric2.default.options.digitGroupSeparator.noSeparator,\n decimalCharacter: _AutoNumeric2.default.options.decimalCharacter.dot,\n currencySymbol: _AutoNumeric2.default.options.currencySymbol.none,\n minimumValue: _AutoNumeric2.default.options.minimumValue.tenTrillions,\n maximumValue: _AutoNumeric2.default.options.maximumValue.zero\n }\n };\n }\n});\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvQXV0b051bWVyaWNQcmVkZWZpbmVkT3B0aW9ucy5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovL0F1dG9OdW1lcmljL3NyYy9BdXRvTnVtZXJpY1ByZWRlZmluZWRPcHRpb25zLmpzPzFlZTMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBQcmUtZGVmaW5lZCBvcHRpb25zIGZvciBhdXRvTnVtZXJpYy5qc1xuICogQGF1dGhvciBBbGV4YW5kcmUgQm9ubmVhdSA8YWxleGFuZHJlLmJvbm5lYXVAbGludXhmci5ldT5cbiAqIEBjb3B5cmlnaHQgwqkgMjAxNiBBbGV4YW5kcmUgQm9ubmVhdVxuICpcbiAqIFRoZSBNSVQgTGljZW5zZSAoaHR0cDovL3d3dy5vcGVuc291cmNlLm9yZy9saWNlbnNlcy9taXQtbGljZW5zZS5waHApXG4gKlxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb25cbiAqIG9idGFpbmluZyBhIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uXG4gKiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXRcbiAqIHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLFxuICogY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3ViIGxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gKiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGVcbiAqIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nXG4gKiBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlXG4gKiBpbmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELFxuICogRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTXG4gKiBPRiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORFxuICogTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFRcbiAqIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLFxuICogV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HXG4gKiBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SXG4gKiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG4gKi9cblxuaW1wb3J0IEF1dG9OdW1lcmljIGZyb20gJy4vQXV0b051bWVyaWMnO1xuaW1wb3J0IEF1dG9OdW1lcmljSGVscGVyIGZyb20gJy4vQXV0b051bWVyaWNIZWxwZXInO1xuXG5jb25zdCBldXJvID0geyAvLyBGcmFuw6dhaXNcbiAgICBkaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmRvdCwgLy8gb3IgJ1xcdTIwMmYnXG4gICAgZGVjaW1hbENoYXJhY3RlciAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5jb21tYSxcbiAgICBkZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUuZG90LFxuICAgIGN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgOiAnXFx1MjAyZuKCrCcsXG4gICAgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4LFxuICAgIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeCxcbn07XG5cbmNvbnN0IGRvbGxhciA9IHtcbiAgICBkaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmNvbW1hLFxuICAgIGRlY2ltYWxDaGFyYWN0ZXIgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuZG90LFxuICAgIGN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sLmRvbGxhcixcbiAgICBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXgsXG4gICAgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQsXG59O1xuXG5jb25zdCBqYXBhbmVzZSA9IHsgLy8g5pel5pys6KqeXG4gICAgZGlnaXRHcm91cFNlcGFyYXRvciAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5jb21tYSxcbiAgICBkZWNpbWFsQ2hhcmFjdGVyICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmRvdCxcbiAgICBjdXJyZW5jeVN5bWJvbCAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC55ZW4sXG4gICAgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4LFxuICAgIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnJpZ2h0LFxufTtcblxuXG4vLyBIZXJlIHdlIG5lZWQgdG8gY2xvbmUgdGhlIGluaXRpYWwgb2JqZWN0cyBpbiBvcmRlciB0byBiZSBhYmxlIHRvIGVkaXQgdGhlIGNsb25lcyB3aXRob3V0IGFmZmVjdGluZyB0aGUgb3JpZ2luYWxzXG5jb25zdCBldXJvUG9zICAgICAgICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QoZXVybyk7XG5ldXJvUG9zLm1pbmltdW1WYWx1ZSAgICAgICAgICAgICAgICAgID0gMDtcbmNvbnN0IGV1cm9OZWcgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChldXJvKTtcbmV1cm9OZWcubWF4aW11bVZhbHVlICAgICAgICAgICAgICAgICAgPSAwO1xuZXVyb05lZy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4O1xuXG5jb25zdCBldXJvU3BhY2UgICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChldXJvKTtcbmV1cm9TcGFjZS5kaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5ub3JtYWxTcGFjZTtcbmNvbnN0IGV1cm9TcGFjZVBvcyAgICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KGV1cm9TcGFjZSk7XG5ldXJvU3BhY2VQb3MubWluaW11bVZhbHVlICAgICAgICAgICAgICAgICAgPSAwO1xuY29uc3QgZXVyb1NwYWNlTmVnICAgICAgICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QoZXVyb1NwYWNlKTtcbmV1cm9TcGFjZU5lZy5tYXhpbXVtVmFsdWUgICAgICAgICAgICAgICAgICA9IDA7XG5ldXJvU3BhY2VOZWcubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDtcblxuY29uc3QgcGVyY2VudGFnZUVVMmRlYyAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KGV1cm8pO1xucGVyY2VudGFnZUVVMmRlYy5jdXJyZW5jeVN5bWJvbCAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2wubm9uZTtcbnBlcmNlbnRhZ2VFVTJkZWMuc3VmZml4VGV4dCAgICAgICAgICAgICAgICAgICAgICAgPSBgXFx1MjAyZiR7QXV0b051bWVyaWMub3B0aW9ucy5zdWZmaXhUZXh0LnBlcmNlbnRhZ2V9YDtcbnBlcmNlbnRhZ2VFVTJkZWMud2hlZWxTdGVwICAgICAgICAgICAgICAgICAgICAgICAgPSAwLjAwMDE7IC8vIFRoaXMgdGFyZ2V0cyB0aGUgYHJhd1ZhbHVlYCwgbm90IHRoZSBmb3JtYXR0ZWQgb25lXG5wZXJjZW50YWdlRVUyZGVjLnJhd1ZhbHVlRGl2aXNvciAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWMub3B0aW9ucy5yYXdWYWx1ZURpdmlzb3IucGVyY2VudGFnZTtcbmNvbnN0IHBlcmNlbnRhZ2VFVTJkZWNQb3MgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChwZXJjZW50YWdlRVUyZGVjKTtcbnBlcmNlbnRhZ2VFVTJkZWNQb3MubWluaW11bVZhbHVlICAgICAgICAgICAgICAgICAgPSAwO1xuY29uc3QgcGVyY2VudGFnZUVVMmRlY05lZyAgICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VFVTJkZWMpO1xucGVyY2VudGFnZUVVMmRlY05lZy5tYXhpbXVtVmFsdWUgICAgICAgICAgICAgICAgICA9IDA7XG5wZXJjZW50YWdlRVUyZGVjTmVnLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg7XG5cbmNvbnN0IHBlcmNlbnRhZ2VFVTNkZWMgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VFVTJkZWMpO1xucGVyY2VudGFnZUVVM2RlYy5kZWNpbWFsUGxhY2VzICAgID0gMztcbmNvbnN0IHBlcmNlbnRhZ2VFVTNkZWNQb3MgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VFVTJkZWNQb3MpO1xucGVyY2VudGFnZUVVM2RlY1Bvcy5kZWNpbWFsUGxhY2VzID0gMztcbmNvbnN0IHBlcmNlbnRhZ2VFVTNkZWNOZWcgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VFVTJkZWNOZWcpO1xucGVyY2VudGFnZUVVM2RlY05lZy5kZWNpbWFsUGxhY2VzID0gMztcblxuY29uc3QgZG9sbGFyUG9zICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChkb2xsYXIpO1xuZG9sbGFyUG9zLm1pbmltdW1WYWx1ZSAgICAgICAgICAgICAgICAgICAgICAgPSAwO1xuY29uc3QgZG9sbGFyTmVnICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChkb2xsYXIpO1xuZG9sbGFyTmVnLm1heGltdW1WYWx1ZSAgICAgICAgICAgICAgICAgICAgICAgPSAwO1xuZG9sbGFyTmVnLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ICAgICAgPSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDtcbmNvbnN0IGRvbGxhck5lZ0JyYWNrZXRzICAgICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QoZG9sbGFyTmVnKTtcbmRvbGxhck5lZ0JyYWNrZXRzLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyID0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5wYXJlbnRoZXNlcztcblxuY29uc3QgcGVyY2VudGFnZVVTMmRlYyAgICAgICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KGRvbGxhcik7XG5wZXJjZW50YWdlVVMyZGVjLmN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC5ub25lO1xucGVyY2VudGFnZVVTMmRlYy5zdWZmaXhUZXh0ICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljLm9wdGlvbnMuc3VmZml4VGV4dC5wZXJjZW50YWdlO1xucGVyY2VudGFnZVVTMmRlYy53aGVlbFN0ZXAgICAgICAgICAgICAgICAgICAgICAgICA9IDAuMDAwMTtcbnBlcmNlbnRhZ2VFVTJkZWMucmF3VmFsdWVEaXZpc29yICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpYy5vcHRpb25zLnJhd1ZhbHVlRGl2aXNvci5wZXJjZW50YWdlO1xuY29uc3QgcGVyY2VudGFnZVVTMmRlY1BvcyAgICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VVUzJkZWMpO1xucGVyY2VudGFnZVVTMmRlY1Bvcy5taW5pbXVtVmFsdWUgICAgICAgICAgICAgICAgICA9IDA7XG5jb25zdCBwZXJjZW50YWdlVVMyZGVjTmVnICAgICAgICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QocGVyY2VudGFnZVVTMmRlYyk7XG5wZXJjZW50YWdlVVMyZGVjTmVnLm1heGltdW1WYWx1ZSAgICAgICAgICAgICAgICAgID0gMDtcbnBlcmNlbnRhZ2VVUzJkZWNOZWcubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDtcblxuY29uc3QgcGVyY2VudGFnZVVTM2RlYyAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QocGVyY2VudGFnZVVTMmRlYyk7XG5wZXJjZW50YWdlVVMzZGVjLmRlY2ltYWxQbGFjZXMgICAgPSAzO1xuY29uc3QgcGVyY2VudGFnZVVTM2RlY1BvcyAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QocGVyY2VudGFnZVVTMmRlY1Bvcyk7XG5wZXJjZW50YWdlVVMzZGVjUG9zLmRlY2ltYWxQbGFjZXMgPSAzO1xuY29uc3QgcGVyY2VudGFnZVVTM2RlY05lZyAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QocGVyY2VudGFnZVVTMmRlY05lZyk7XG5wZXJjZW50YWdlVVMzZGVjTmVnLmRlY2ltYWxQbGFjZXMgPSAzO1xuXG5jb25zdCB0dXJraXNoID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QoZXVybyk7XG50dXJraXNoLmN1cnJlbmN5U3ltYm9sID0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC5saXJhO1xuXG4vKipcbiAqIFByZWRlZmluZWQgb3B0aW9ucyBmb3IgdGhlIG1vc3QgY29tbW9uIGxhbmd1YWdlc1xuICovXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoQXV0b051bWVyaWMsICdwcmVkZWZpbmVkT3B0aW9ucycsIHtcbiAgICBnZXQoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBldXJvLFxuICAgICAgICAgICAgZXVyb1BvcyxcbiAgICAgICAgICAgIGV1cm9OZWcsXG4gICAgICAgICAgICBldXJvU3BhY2UsXG4gICAgICAgICAgICBldXJvU3BhY2VQb3MsXG4gICAgICAgICAgICBldXJvU3BhY2VOZWcsXG4gICAgICAgICAgICBwZXJjZW50YWdlRVUyZGVjLFxuICAgICAgICAgICAgcGVyY2VudGFnZUVVMmRlY1BvcyxcbiAgICAgICAgICAgIHBlcmNlbnRhZ2VFVTJkZWNOZWcsXG4gICAgICAgICAgICBwZXJjZW50YWdlRVUzZGVjLFxuICAgICAgICAgICAgcGVyY2VudGFnZUVVM2RlY1BvcyxcbiAgICAgICAgICAgIHBlcmNlbnRhZ2VFVTNkZWNOZWcsXG4gICAgICAgICAgICBkb2xsYXIsXG4gICAgICAgICAgICBkb2xsYXJQb3MsXG4gICAgICAgICAgICBkb2xsYXJOZWcsXG4gICAgICAgICAgICBkb2xsYXJOZWdCcmFja2V0cyxcbiAgICAgICAgICAgIHBlcmNlbnRhZ2VVUzJkZWMsXG4gICAgICAgICAgICBwZXJjZW50YWdlVVMyZGVjUG9zLFxuICAgICAgICAgICAgcGVyY2VudGFnZVVTMmRlY05lZyxcbiAgICAgICAgICAgIHBlcmNlbnRhZ2VVUzNkZWMsXG4gICAgICAgICAgICBwZXJjZW50YWdlVVMzZGVjUG9zLFxuICAgICAgICAgICAgcGVyY2VudGFnZVVTM2RlY05lZyxcbiAgICAgICAgICAgIEZyZW5jaCAgICAgICAgICAgICAgICAgICAgICA6IGV1cm8sIC8vIEZyYW7Dp2Fpc1xuICAgICAgICAgICAgU3BhbmlzaCAgICAgICAgICAgICAgICAgICAgIDogZXVybywgLy8gRXNwYcOxb2xcbiAgICAgICAgICAgIE5vcnRoQW1lcmljYW4gICAgICAgICAgICAgICA6IGRvbGxhcixcbiAgICAgICAgICAgIEJyaXRpc2ggICAgICAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICBkaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmNvbW1hLFxuICAgICAgICAgICAgICAgIGRlY2ltYWxDaGFyYWN0ZXIgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuZG90LFxuICAgICAgICAgICAgICAgIGN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sLnBvdW5kLFxuICAgICAgICAgICAgICAgIGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCxcbiAgICAgICAgICAgICAgICBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBTd2lzcyAgICAgICAgICAgICAgICAgICAgICAgOiB7IC8vIFN1aXNzZVxuICAgICAgICAgICAgICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3IgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IuYXBvc3Ryb3BoZSxcbiAgICAgICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmRvdCxcbiAgICAgICAgICAgICAgICBjdXJyZW5jeVN5bWJvbCAgICAgICAgICAgICAgIDogJ1xcdTIwMmZDSEYnLFxuICAgICAgICAgICAgICAgIGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCxcbiAgICAgICAgICAgICAgICBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXgsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgSmFwYW5lc2UgICAgICAgICAgICAgICAgICAgIDogamFwYW5lc2UsIC8vIOaXpeacrOiqnlxuICAgICAgICAgICAgQ2hpbmVzZSAgICAgICAgICAgICAgICAgICAgIDogamFwYW5lc2UsIC8vIOS4reWbveiqniAoQ2hpbmVzZSlcbiAgICAgICAgICAgIEJyYXppbGlhbiAgICAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICBkaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmRvdCxcbiAgICAgICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmNvbW1hLFxuICAgICAgICAgICAgICAgIGN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sLnJlYWwsXG4gICAgICAgICAgICAgICAgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4LFxuICAgICAgICAgICAgICAgIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnJpZ2h0LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIFR1cmtpc2ggICAgICAgICAgICAgICAgICAgICA6IHR1cmtpc2gsXG4gICAgICAgICAgICBkb3REZWNpbWFsQ2hhckNvbW1hU2VwYXJhdG9yOiB7XG4gICAgICAgICAgICAgICAgZGlnaXRHcm91cFNlcGFyYXRvcjogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmNvbW1hLFxuICAgICAgICAgICAgICAgIGRlY2ltYWxDaGFyYWN0ZXIgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5kb3QsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29tbWFEZWNpbWFsQ2hhckRvdFNlcGFyYXRvcjoge1xuICAgICAgICAgICAgICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3IgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmRvdCxcbiAgICAgICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5jb21tYSxcbiAgICAgICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmU6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlLmRvdCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpbnRlZ2VyICAgICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgZGVjaW1hbFBsYWNlczogMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpbnRlZ2VyUG9zICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgbWluaW11bVZhbHVlIDogQXV0b051bWVyaWMub3B0aW9ucy5taW5pbXVtVmFsdWUuemVybyxcbiAgICAgICAgICAgICAgICBkZWNpbWFsUGxhY2VzOiAwLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGludGVnZXJOZWcgICAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICBtYXhpbXVtVmFsdWUgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm1heGltdW1WYWx1ZS56ZXJvLFxuICAgICAgICAgICAgICAgIGRlY2ltYWxQbGFjZXM6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZmxvYXQgICAgICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgIGFsbG93RGVjaW1hbFBhZGRpbmc6IEF1dG9OdW1lcmljLm9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZy5uZXZlcixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmbG9hdFBvcyAgICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgYWxsb3dEZWNpbWFsUGFkZGluZzogQXV0b051bWVyaWMub3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nLm5ldmVyLFxuICAgICAgICAgICAgICAgIG1pbmltdW1WYWx1ZSAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubWluaW11bVZhbHVlLnplcm8sXG4gICAgICAgICAgICAgICAgbWF4aW11bVZhbHVlICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5tYXhpbXVtVmFsdWUudGVuVHJpbGxpb25zLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZsb2F0TmVnICAgICAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICBhbGxvd0RlY2ltYWxQYWRkaW5nOiBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcubmV2ZXIsXG4gICAgICAgICAgICAgICAgbWluaW11bVZhbHVlICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5taW5pbXVtVmFsdWUudGVuVHJpbGxpb25zLFxuICAgICAgICAgICAgICAgIG1heGltdW1WYWx1ZSAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubWF4aW11bVZhbHVlLnplcm8sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbnVtZXJpYyAgICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3I6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5ub1NlcGFyYXRvcixcbiAgICAgICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuZG90LFxuICAgICAgICAgICAgICAgIGN1cnJlbmN5U3ltYm9sICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2wubm9uZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBudW1lcmljUG9zICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgZGlnaXRHcm91cFNlcGFyYXRvcjogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLm5vU2VwYXJhdG9yLFxuICAgICAgICAgICAgICAgIGRlY2ltYWxDaGFyYWN0ZXIgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5kb3QsXG4gICAgICAgICAgICAgICAgY3VycmVuY3lTeW1ib2wgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC5ub25lLFxuICAgICAgICAgICAgICAgIG1pbmltdW1WYWx1ZSAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubWluaW11bVZhbHVlLnplcm8sXG4gICAgICAgICAgICAgICAgbWF4aW11bVZhbHVlICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5tYXhpbXVtVmFsdWUudGVuVHJpbGxpb25zLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG51bWVyaWNOZWcgICAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICBkaWdpdEdyb3VwU2VwYXJhdG9yOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3Iubm9TZXBhcmF0b3IsXG4gICAgICAgICAgICAgICAgZGVjaW1hbENoYXJhY3RlciAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmRvdCxcbiAgICAgICAgICAgICAgICBjdXJyZW5jeVN5bWJvbCAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sLm5vbmUsXG4gICAgICAgICAgICAgICAgbWluaW11bVZhbHVlICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5taW5pbXVtVmFsdWUudGVuVHJpbGxpb25zLFxuICAgICAgICAgICAgICAgIG1heGltdW1WYWx1ZSAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubWF4aW11bVZhbHVlLnplcm8sXG4gICAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgIH0sXG59KTtcbiJdLCJtYXBwaW5ncyI6Ijs7QUE2QkE7QUFDQTs7O0FBQUE7QUFDQTs7Ozs7QUEvQkE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBZ0NBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTkE7QUFDQTtBQVFBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUxBO0FBQ0E7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFMQTtBQUNBO0FBUUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOzs7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUxBO0FBT0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTEE7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBTEE7QUFPQTtBQUNBO0FBQ0E7QUFDQTtBQUZBO0FBSUE7QUFDQTtBQUNBO0FBQ0E7QUFIQTtBQUtBO0FBQ0E7QUFEQTtBQUdBO0FBQ0E7QUFDQTtBQUZBO0FBSUE7QUFDQTtBQUNBO0FBRkE7QUFJQTtBQUNBO0FBREE7QUFHQTtBQUNBO0FBQ0E7QUFDQTtBQUhBO0FBS0E7QUFDQTtBQUNBO0FBQ0E7QUFIQTtBQUtBO0FBQ0E7QUFDQTtBQUNBO0FBSEE7QUFLQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFMQTtBQU9BO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUxBO0FBL0ZBO0FBdUdBO0FBekdBIiwic291cmNlUm9vdCI6IiJ9\n//# sourceURL=webpack-internal:///./src/AutoNumericPredefinedOptions.js\n"); /***/ }), /***/ "./src/main.js": /*!*********************!*\ !*** ./src/main.js ***! \*********************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; eval("\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\n\nvar _AutoNumeric = __webpack_require__(/*! ./AutoNumeric */ \"./src/AutoNumeric.js\");\n\nvar _AutoNumeric2 = _interopRequireDefault(_AutoNumeric);\n\nvar _AutoNumericEvents = __webpack_require__(/*! ./AutoNumericEvents */ \"./src/AutoNumericEvents.js\");\n\nvar _AutoNumericEvents2 = _interopRequireDefault(_AutoNumericEvents);\n\nvar _AutoNumericOptions = __webpack_require__(/*! ./AutoNumericOptions */ \"./src/AutoNumericOptions.js\");\n\nvar _AutoNumericOptions2 = _interopRequireDefault(_AutoNumericOptions);\n\nvar _AutoNumericDefaultSettings = __webpack_require__(/*! ./AutoNumericDefaultSettings */ \"./src/AutoNumericDefaultSettings.js\");\n\nvar _AutoNumericDefaultSettings2 = _interopRequireDefault(_AutoNumericDefaultSettings);\n\nvar _AutoNumericPredefinedOptions = __webpack_require__(/*! ./AutoNumericPredefinedOptions */ \"./src/AutoNumericPredefinedOptions.js\");\n\nvar _AutoNumericPredefinedOptions2 = _interopRequireDefault(_AutoNumericPredefinedOptions);\n\nfunction _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }\n\n/* eslint no-unused-vars: 0 */\n\n/**\n * This file serve as the main entry point to the library.\n *\n * @type {AutoNumeric}\n */\nexports.default = _AutoNumeric2.default; /**\n * Babel + Webpack workaround for autoNumeric\n *\n * @author Alexandre Bonneau \n * @copyright © 2017 Alexandre Bonneau\n *\n * The MIT License (http://www.opensource.org/licenses/mit-license.php)\n *\n * Permission is hereby granted, free of charge, to any person\n * obtaining a copy of this software and associated documentation\n * files (the \"Software\"), to deal in the Software without\n * restriction, including without limitation the rights to use,\n * copy, modify, merge, publish, distribute, sub license, and/or sell\n * copies of the Software, and to permit persons to whom the\n * Software is furnished to do so, subject to the following\n * conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\n * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\n * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\n * OTHER DEALINGS IN THE SOFTWARE.\n */\n\nmodule.exports = exports['default'];\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvbWFpbi5qcy5qcyIsInNvdXJjZXMiOlsid2VicGFjazovL0F1dG9OdW1lcmljL3NyYy9tYWluLmpzPzJlZTIiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBCYWJlbCArIFdlYnBhY2sgd29ya2Fyb3VuZCBmb3IgYXV0b051bWVyaWNcbiAqXG4gKiBAYXV0aG9yIEFsZXhhbmRyZSBCb25uZWF1IDxhbGV4YW5kcmUuYm9ubmVhdUBsaW51eGZyLmV1PlxuICogQGNvcHlyaWdodCDCqSAyMDE3IEFsZXhhbmRyZSBCb25uZWF1XG4gKlxuICogVGhlIE1JVCBMaWNlbnNlIChodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocClcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvblxuICogb2J0YWluaW5nIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb25cbiAqIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dFxuICogcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsXG4gKiBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWIgbGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZVxuICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmdcbiAqIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsXG4gKiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVNcbiAqIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EXG4gKiBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVFxuICogSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksXG4gKiBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1JcbiAqIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgQXV0b051bWVyaWMgZnJvbSAnLi9BdXRvTnVtZXJpYyc7XG5pbXBvcnQgQXV0b051bWVyaWNFdmVudHMgZnJvbSAnLi9BdXRvTnVtZXJpY0V2ZW50cyc7XG5pbXBvcnQgQXV0b051bWVyaWNPcHRpb25zIGZyb20gJy4vQXV0b051bWVyaWNPcHRpb25zJztcbmltcG9ydCBBdXRvTnVtZXJpY0RlZmF1bHRTZXR0aW5ncyBmcm9tICcuL0F1dG9OdW1lcmljRGVmYXVsdFNldHRpbmdzJztcbmltcG9ydCBBdXRvTnVtZXJpY1ByZWRlZmluZWRPcHRpb25zIGZyb20gJy4vQXV0b051bWVyaWNQcmVkZWZpbmVkT3B0aW9ucyc7XG5cbi8qIGVzbGludCBuby11bnVzZWQtdmFyczogMCAqL1xuXG4vKipcbiAqIFRoaXMgZmlsZSBzZXJ2ZSBhcyB0aGUgbWFpbiBlbnRyeSBwb2ludCB0byB0aGUgbGlicmFyeS5cbiAqXG4gKiBAdHlwZSB7QXV0b051bWVyaWN9XG4gKi9cbmV4cG9ydCBkZWZhdWx0IEF1dG9OdW1lcmljO1xuIl0sIm1hcHBpbmdzIjoiOzs7Ozs7QUE4QkE7QUFDQTs7O0FBQUE7QUFDQTs7O0FBQUE7QUFDQTs7O0FBQUE7QUFDQTs7O0FBQUE7QUFDQTs7Ozs7QUFDQTtBQUNBO0FBQ0E7Ozs7O0FBdENBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QSIsInNvdXJjZVJvb3QiOiIifQ==\n//# sourceURL=webpack-internal:///./src/main.js\n"); /***/ }) /******/ }); });