%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/tjamichg/portal.tjamich.gob.mx/adminit2018/assets/js/plugins/autonumeric/
Upload File :
Create Path :
Current File : /home/tjamichg/portal.tjamich.gob.mx/adminit2018/assets/js/plugins/autonumeric/autoNumeric.js

(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();
})(this, 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] = {
/******/ 			exports: {},
/******/ 			id: moduleId,
/******/ 			loaded: false
/******/ 		};

/******/ 		// Execute the module function
/******/ 		modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);

/******/ 		// Flag the module as loaded
/******/ 		module.loaded = 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;

/******/ 	// __webpack_public_path__
/******/ 	__webpack_require__.p = "";

/******/ 	// Load entry module and return exports
/******/ 	return __webpack_require__(0);
/******/ })
/************************************************************************/
/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

	__webpack_require__(8);
	module.exports = __webpack_require__(1);


/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {

	eval("/*** IMPORTS FROM imports-loader ***/\n(function() {\n\n'use strict';\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.0.2\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @date         2017-08-02 UTC 02:50\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @authors      Bob Knothe, Alexandre Bonneau\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @contributors Sokolov Yura and others, cf. AUTHORS\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @copyright    2009 Robert J. Knothe http://www.decorplanit.com/plugin/\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                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      *               Note : Some functions are borrowed from big.js\n                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      * @link         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/* global module */\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__(3);\n\nvar _AutoNumericHelper2 = _interopRequireDefault(_AutoNumericHelper);\n\nvar _AutoNumericEnum = __webpack_require__(2);\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 <input> one), and provides autoNumeric-specific variables and functions.\n */\nvar AutoNumeric = function () {\n    //TODO Use the better notation `export default class` when webpack and babel will allow it (cf. https://github.com/webpack/webpack/issues/706)\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        }\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\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<string>}\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<string>}\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<string>}\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<number>}\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<string>}\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(domElementOrAutoNumericObject);\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(domElementOrAutoNumericObject);\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<HTMLElement>}\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            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            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            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(_unformatOnSubmit) {\n                _this.settings.unformatOnSubmit = _unformatOnSubmit; //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\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. <input value='42'>), 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 = 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._onInputFunc = function (e) {\n                _this2._onInput(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._onFormSubmitFunc = function () {\n                _this2._onFormSubmit();\n            };\n            this._onKeydownGlobalFunc = function (e) {\n                _this2._onKeydownGlobal(e);\n            };\n            this._onKeyupGlobalFunc = function (e) {\n                _this2._onKeyupGlobal(e);\n            };\n            this._onDropFunc = function (e) {\n                _this2._onDrop(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('input', this._onInputFunc, 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\n            if (!_AutoNumericHelper2.default.isNull(this.parentForm)) {\n                this.parentForm.addEventListener('submit', this._onFormSubmitFunc, false);\n            }\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            //FIXME test this\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('input', this._onInputFunc, 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\n            document.removeEventListener('keydown', this._onKeydownGlobalFunc, false);\n            document.removeEventListener('keyup', this._onKeyupGlobalFunc, false);\n\n            if (!_AutoNumericHelper2.default.isNull(this.parentForm)) {\n                this.parentForm.removeEventListener('submit', this._onFormSubmitFunc, false);\n            }\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         * 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<object>} 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 _this3 = 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 (_this3.rawValue >= range.min && _this3.rawValue < range.max) {\n                        _this3._addCSSClass(range.class);\n                    } else {\n                        _this3._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(_this3.rawValue)) {\n                                _this3._addCSSClass(userObject.classes);\n                            } else {\n                                _this3._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(_this3.rawValue)) {\n                                    _this3._addCSSClass(userObject.classes[0]);\n                                    _this3._removeCSSClass(userObject.classes[1]);\n                                } else {\n                                    _this3._removeCSSClass(userObject.classes[0]);\n                                    _this3._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(_this3.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                                            _this3._addCSSClass(userClass);\n                                        } else {\n                                            _this3._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                                            _this3._addCSSClass(userClass);\n                                        } else {\n                                            _this3._removeCSSClass(userClass);\n                                        }\n                                    });\n                                } else if (_AutoNumericHelper2.default.isNull(callbackResult)) {\n                                    // Remove all the classes\n                                    userObject.classes.forEach(function (userClass) {\n                                        _this3._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(_this3);\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.', _this3.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         *\n         * @param {object} newOptions\n         * @returns {AutoNumeric}\n         */\n\n    }, {\n        key: 'update',\n        value: function update() {\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\n            for (var _len2 = arguments.length, newOptions = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {\n                newOptions[_key2] = arguments[_key2];\n            }\n\n            if (_AutoNumericHelper2.default.isUndefinedOrNullOrEmpty(newOptions) || newOptions.length === 0) {\n                optionsToUse = null;\n            } else if (newOptions.length >= 1) {\n                newOptions.forEach(function (optionObject) {\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                // This test is needed by the `showPositiveSign` option\n\n\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                        _AutoNumericHelper2.default.triggerEvent(AutoNumeric.events.minRangeExceeded, this.domElement);\n                    }\n\n                    if (!maxTest) {\n                        _AutoNumericHelper2.default.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            normalizedValue = normalizedValue.replace(this.settings.decimalCharacter, '.');\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                // 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                // 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         * @returns {AutoNumeric}\n         * @private\n         */\n\n    }, {\n        key: '_setElementValue',\n        value: function _setElementValue(newElementValue) {\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            // `oldElementValue` is the previous value that will be overwritten. This is used to decide if an event should be sent or not.\n            var oldElementValue = _AutoNumericHelper2.default.getElementValue(this.domElement);\n\n            if (newElementValue !== oldElementValue) {\n                // Only update the value if it's different from the current one\n                _AutoNumericHelper2.default.setElementValue(this.domElement, newElementValue);\n                _AutoNumericHelper2.default.triggerEvent(AutoNumeric.events.formatted, this.domElement, { oldValue: oldElementValue, newValue: newElementValue });\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         * Return `true` if the user is currently modifying the element value manually.\n         *\n         * @returns {boolean}\n         * @private\n         */\n\n    }, {\n        key: '_isUserManuallyEditingTheValue',\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         * 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');\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);\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) ? 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<HTMLElement|HTMLInputElement>|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 _this4 = 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 = _this4.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                    _this4.settings.createLocalList = false;\n                }\n\n                var newAutoNumericElement = new AutoNumeric(domElement, _AutoNumericHelper2.default.getElementValue(domElement), _this4.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                    _this4._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                    _this4.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\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('');\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 <form> element, instead of the <input> element itself\n\n        /**\n         * Return a reference to the parent <form> 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         * @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                this.parentForm = this._getParentForm();\n            }\n\n            return this.parentForm;\n        }\n\n        /**\n         * Return a reference to the parent <form> 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 `<body>` 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 <input> 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 <input> 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 <input> 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 <form> 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 <form> 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 <form> 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 `<input>` 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 `<input>` 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 `<input>` 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 `<input>` 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 `<input>` 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 `<input>` 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: <tag data-currency-symbol=\"functionName\"></tag>\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 unwanted non-number characters.\n         * This keeps the numbers, the negative sign as well as 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: '_setBrackets',\n\n\n        /**\n         * Analyze the `negativeBracketsTypeOnBlur` options and keep track of the first and last bracket characters to use.\n         * @private\n         */\n        value: function _setBrackets() {\n            if (!_AutoNumericHelper2.default.isNull(this.settings.negativeBracketsTypeOnBlur)) {\n                var _settings$negativeBra = this.settings.negativeBracketsTypeOnBlur.split(',');\n\n                var _settings$negativeBra2 = _slicedToArray(_settings$negativeBra, 2);\n\n                this.settings.firstBracket = _settings$negativeBra2[0];\n                this.settings.lastBracket = _settings$negativeBra2[1];\n            } else {\n                this.settings.firstBracket = '';\n                this.settings.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 return the given string by stripping the currency sign (currencySymbol), the grouping separators (digitalGroupSpacing) and by replacing the decimal character (decimalCharacter) by a dot.\n         * Lastly, it also put the negative sign back to its normal position if needed.\n         *\n         * @param {string} s\n         * @param {object} settings\n         * @returns {string|void|XML|*}\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\n         * @returns {string}\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.negativeSignCharacter !== '') {\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)) {\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('-', '');\n                value = value.replace('+', '');\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            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            //TODO `AutoNumericHelper.setElementValue` is called 3 times sequentially here, fix that\n            //TODO Create separate handlers for the focus and mouseenter events\n            var initialElementValue = _AutoNumericHelper2.default.getElementValue(this.domElement);\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                // We 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                if (this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.focus && this.rawValue < 0 && this.settings.negativeBracketsTypeOnBlur !== null && this.settings.negativeSignCharacter !== '') {\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                    _AutoNumericHelper2.default.setElementValue(this.domElement, this.constructor._removeBrackets(_AutoNumericHelper2.default.getElementValue(this.domElement), this.settings));\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                        _AutoNumericHelper2.default.setElementValue(this.domElement, 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                        _AutoNumericHelper2.default.setElementValue(this.domElement, 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                this.valueOnFocus = _AutoNumericHelper2.default.getElementValue(e.target);\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                if (isEmptyValue && orderedValue !== '' && this.settings.emptyInputBehavior === AutoNumeric.options.emptyInputBehavior.focus) {\n                    _AutoNumericHelper2.default.setElementValue(this.domElement, orderedValue);\n\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                    if (orderedValue === this.settings.currencySymbol && this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.suffix) {\n                        _AutoNumericHelper2.default.setElementSelection(e.target, 0);\n                    }\n                }\n            }\n\n            if (_AutoNumericHelper2.default.getElementValue(this.domElement) !== initialElementValue) {\n                _AutoNumericHelper2.default.triggerEvent(AutoNumeric.events.formatted, this.domElement, { oldValue: initialElementValue, newValue: _AutoNumericHelper2.default.getElementValue(this.domElement) });\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                _AutoNumericHelper2.default.setElementSelection(e.target, this._initialCaretPosition(_AutoNumericHelper2.default.getElementValue(this.domElement)));\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.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\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 its 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                        _AutoNumericHelper2.default.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 value has changed since the `focus` event\n            var targetValue = _AutoNumericHelper2.default.getElementValue(e.target);\n            if (this.eventKey === _AutoNumericEnum2.default.keyName.Enter && this.valueOnFocus !== targetValue) {\n                _AutoNumericHelper2.default.triggerEvent(AutoNumeric.events.native.change, e.target);\n                this.valueOnFocus = targetValue;\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                    _AutoNumericHelper2.default.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                return;\n            }\n\n            this.formatted = false; //TODO Is this line needed? (I mean, _formatValue always set it to `true`, and this overwrite that info)\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                    _AutoNumericHelper2.default.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            this.formatted = false; //TODO Is this line needed? (I mean, _formatValue always set it to `true`, and this overwrite that info)\n        }\n\n        /**\n         * Handler for 'input' events.\n         * Handling this event instead of `keypress` is needed in order to support android devices.\n         *\n         * @param {Event} e\n         */\n\n    }, {\n        key: '_onInput',\n        value: function _onInput(e) {\n            var value = _AutoNumericHelper2.default.getElementValue(this.domElement);\n\n            // Fix the caret position on keyup in the `_formatValue()` function\n            this.androidSelectionStart = null;\n\n            if (this.eventKey === _AutoNumericEnum2.default.keyName.AndroidDefault) {\n                var selection = _AutoNumericHelper2.default.getElementSelection(this.domElement);\n                // The keyCode is equal to the default Android Chrome one (which is always equal to `keyCode.AndroidDefault`)\n                if (value.length > this.lastVal.length || value.length >= this.lastVal.length - selection.length) {\n                    // Determine the keycode of the character that was entered, and overwrite the faulty `eventKeyCode` info with it\n                    this.eventKey = value.charCodeAt(selection.start);\n\n                    // Capture the actual character entered, and update the `eventKey` with it (instead of the Android default one)\n                    this.eventKey = value.charAt(selection.start);\n\n                    // Check if the given character should be inserted, and if so, do insert it into the current element value\n                    var isCharacterInsertionAllowed = this._processCharacterInsertion();\n\n                    if (isCharacterInsertionAllowed) {\n                        // Allowed character entered (number, decimal or plus/minus sign)\n                        this._formatValue(e);\n\n                        selection = _AutoNumericHelper2.default.getElementSelection(this.domElement); //TODO is this needed a second time?\n                        // Capture the new caret position. This is required because on keyup, `_updateAutoNumericHolderEventKeycode()` captures the old caret position\n                        //TODO Check if this is an Android bug or an autoNumeric one\n                        this.androidSelectionStart = selection.start;\n\n                        // Move the caret to the right if the `androidCharEntered` is the decimal character or if it's on the left of the caret position\n                        var decimalCharacterPosition = _AutoNumericHelper2.default.getElementValue(this.domElement).indexOf(this.settings.decimalCharacter);\n                        var hasDecimalCharacter = decimalCharacterPosition !== -1;\n                        if (this.eventKey === this.settings.decimalCharacter || hasDecimalCharacter && decimalCharacterPosition < this.androidSelectionStart) {\n                            this.androidSelectionStart += this.settings.decimalCharacter.length;\n                        }\n\n                        if (this.settings.currencySymbolPlacement === AutoNumeric.options.currencySymbolPlacement.prefix && this.settings.currencySymbol.length) {\n                            this.androidSelectionStart += this.settings.currencySymbol.length;\n                        }\n\n                        if (selection.length > value.length) {\n                            // Position the caret right now before the 'keyup' event in order to prevent the caret from jumping around\n                            this._setCaretPosition(this.androidSelectionStart);\n                        }\n\n                        this.lastVal = _AutoNumericHelper2.default.getElementValue(this.domElement);\n\n                        return;\n                    } else {\n                        // The entered character is not allowed ; overwrite the new invalid value with the previous valid one, and set back the caret/selection\n                        _AutoNumericHelper2.default.setElementValue(this.lastVal); //TODO Update the rawValue here too via _setValue()?\n                        _AutoNumericHelper2.default.setElementSelection(this.domElement, selection.start, selection.end);\n                        this.androidSelectionStart = selection.start;\n                    }\n\n                    e.preventDefault(); //TODO Check how that is affecting the normal trigger of the input event\n\n                    this.formatted = false;\n                } else {\n                    // Character deleted\n                    //XXX The change in length could also be the result of the `Delete` key, but there usually are no such key in the Android virtual keyboards\n                    this.eventKey = _AutoNumericEnum2.default.keyName.Backspace;\n                }\n            }\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 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 isOnAndroid = this.androidSelectionStart !== null;\n            var targetValue = _AutoNumericHelper2.default.getElementValue(e.target);\n            if (skip && !isOnAndroid || 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            // 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                _AutoNumericHelper2.default.triggerEvent(AutoNumeric.events.formatted, e.target, { oldValue: this.initialValueOnKeydown, newValue: targetValue }); //TODO Do I need to remove this since we now send this event on `set()`?\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         * 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            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            //TODO Create separate handlers for blur and mouseleave\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\n                var value = void 0;\n                var isRawValueNull = _AutoNumericHelper2.default.isNull(rawValueToFormat);\n                if (isRawValueNull || rawValueToFormat === '') {\n                    value = rawValueToFormat;\n                } else {\n                    value = String(rawValueToFormat);\n                }\n\n                if (rawValueToFormat !== '' && !isRawValueNull) {\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                    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                            _AutoNumericHelper2.default.triggerEvent(AutoNumeric.events.minRangeExceeded, this.domElement);\n                        }\n                        if (!maxTest) {\n                            _AutoNumericHelper2.default.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                if (groupedValue !== this.valueOnFocus) {\n                    _AutoNumericHelper2.default.triggerEvent(AutoNumeric.events.native.change, this.domElement);\n                    delete this.valueOnFocus;\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            //TODO Using ctrl+z after a paste should cancel it -> How would that affect other frameworks/component built with that feature in mind though?\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            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            // 0. Special case if the user has selected all the input text before pasting\n            var initialFormattedValue = _AutoNumericHelper2.default.getElementValue(e.target);\n            var selectionStart = e.target.selectionStart || 0;\n            var selectionEnd = e.target.selectionEnd || 0;\n            var selectionSize = selectionEnd - selectionStart;\n            var isAllInputTextSelected = false;\n\n            if (selectionSize === initialFormattedValue.length) {\n                isAllInputTextSelected = true;\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);\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                if (this.settings.onInvalidPaste === AutoNumeric.options.onInvalidPaste.error) {\n                    //TODO Should we send a warning instead of throwing an 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 initialUnformattedNumber = this.getNumericString();\n            var isInitialValueNegative = _AutoNumericHelper2.default.isNegativeStrict(initialUnformattedNumber);\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                initialUnformattedNumber = '-' + initialUnformattedNumber;\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                        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 {\n                        if (isAllInputTextSelected) {\n                            // Special case when all the input text is selected before pasting, which means we'll completely erase its content and paste only the clipboard content\n                            caretPositionOnInitialTextAfterPasting = result.length;\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(e.target).slice(selectionStart, selectionEnd);\n                            caretPositionOnInitialTextAfterPasting = indexSelectionEndInRawValue - selectionSize + _AutoNumericHelper2.default.countCharInText(this.settings.digitGroupSeparator, selectedText) + pastedText.length;\n                        }\n                    }\n\n                    // Modify the caret position for special cases, only if the whole input has not been selected\n                    if (!isAllInputTextSelected) {\n                        if (isPasteNegativeAndInitialValueIsPositive) {\n                            // If the pasted value has a '-' 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\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(e.target);\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(e.target, targetValue.length - this.settings.currencySymbol.length); // This puts the caret on the right of the last decimal place\n                            } else {\n                                _AutoNumericHelper2.default.setElementSelection(e.target, 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(e.target, 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                _AutoNumericHelper2.default.triggerEvent(AutoNumeric.events.native.input, e.target);\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            if (_AutoNumericHelper2.default.getElementValue(e.target) !== this.valueOnFocus) {\n                _AutoNumericHelper2.default.triggerEvent(AutoNumeric.events.native.change, e.target);\n            }\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 the user is using the 'Shift' key modifier, then we ignore the wheel event\n            // This special behavior is applied in order to avoid preventing the user to scroll the page if the inputs are covering the whole available space.\n            // If that's the case, then he can use the 'Shift' modifier key while using the mouse wheel in order to bypass the increment/decrement feature\n            // This is useful on small screen where some badly configured inputs could use all the available space.\n            if (!e.shiftKey && this.settings.modifyValueOnWheel) {\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\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        /**\n         * Handler for 'drop' event\n         *\n         * @param {DragEvent} e\n         */\n\n    }, {\n        key: '_onDrop',\n        value: function _onDrop(e) {\n            this.isDropEvent = true;\n            e.preventDefault();\n            var droppedText = e.dataTransfer.getData('text/plain');\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 <form> 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            if (this.settings.unformatOnSubmit) {\n                this._setElementValue(this.rawValue);\n            }\n\n            return true;\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 <input>.\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 <input> 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 <input> 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                currentValue = _AutoNumericHelper2.default.getElementValue(this.domElement);\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: <asp:TextBox runat=\"server\" id=\"someID\" text=\"1234.56\" data-an-default=\"1234.56\">\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 = void 0;\n\n                            if (this.settings.negativeBracketsTypeOnBlur !== null && this.settings.negativeSignCharacter !== '') {\n                                toStrip = this.constructor._removeBrackets(currentValue, this.settings);\n                            } else {\n                                toStrip = currentValue;\n                            }\n\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)) {\n                                this._setRawValue(this.settings.negativeSignCharacter + 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 {\n                if (this.settings.defaultValueOverride === null) {\n                    this.set(currentValue);\n                } else {\n                    if (this.settings.defaultValueOverride === currentValue) {\n                        this.set(currentValue);\n                    }\n                }\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         */\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('-', '');\n            minimumValueIntegerPart = minimumValueIntegerPart.replace('-', '');\n\n            this.settings.mIntPos = Math.max(maximumValueIntegerPart.length, 1);\n            this.settings.mIntNeg = Math.max(minimumValueIntegerPart.length, 1);\n        }\n        /**\n         * Sets the alternative decimal separator key.\n         */\n\n    }, {\n        key: '_setAlternativeDecimalSeparatorCharacter',\n        value: function _setAlternativeDecimalSeparatorCharacter() {\n            if (_AutoNumericHelper2.default.isNull(this.settings.decimalCharacterAlternative) && Number(this.settings.decimalPlaces) > 0) {\n                if (this.settings.decimalCharacter === '.' && this.settings.digitGroupSeparator !== ',') {\n                    this.settings.decimalCharacterAlternative = ',';\n                } else if (this.settings.decimalCharacter === ',' && this.settings.digitGroupSeparator !== '.') {\n                    this.settings.decimalCharacterAlternative = '.';\n                }\n            }\n        }\n\n        /**\n         * Caches regular expressions for _stripAllNonNumberCharacters\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                this.androidSelectionStart = null; // If `null`, then we are not on an Android device (the keyCode is not always equal to 229)\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            // Set the negative and positive signs, as needed\n            this.settings.negativeSignCharacter = this.settings.minimumValue < 0 ? '-' : '';\n            this.settings.positiveSignCharacter = this.settings.maximumValue >= 0 ? '+' : '';\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._setAlternativeDecimalSeparatorCharacter();\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._setBrackets();\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         * Convert the `value` parameter that can either be :\n         * - a real number,\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: '_preparePastedText',\n\n\n        /**\n         * Return the pasted text that will be used.\n         *\n         * @param {string} text\n         * @returns {string|void|XML|*}\n         */\n        value: function _preparePastedText(text) {\n            return this.constructor._stripAllNonNumberCharacters(text, this.settings, true, this.isFocused).replace(this.settings.decimalCharacter, '.');\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' and 'formatted' state.\n         *\n         * Note : Those two 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            this.formatted = 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.\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 && Number(left) === 0) {\n                stripZeros = false;\n            }\n\n            if (this.isTrailingNegative && _AutoNumericHelper2.default.isNegative(right) && !_AutoNumericHelper2.default.isNegative(left)) {\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._stripAllNonNumberCharacters(left, this.settings, stripZeros, this.isFocused);\n            right = AutoNumeric._stripAllNonNumberCharacters(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 && Number(left) === 0) {\n                stripZeros = false;\n            }\n\n            if (this.isTrailingNegative && _AutoNumericHelper2.default.isNegative(right) && !_AutoNumericHelper2.default.isNegative(left)) {\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._stripAllNonNumberCharacters(left, this.settings, stripZeros, this.isFocused);\n            right = AutoNumeric._stripAllNonNumberCharacters(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                _AutoNumericHelper2.default.setElementValue(this.domElement, roundedValueToShow);\n                this._setCaretPosition(position);\n\n                return true;\n            }\n\n            if (!minTest) {\n                _AutoNumericHelper2.default.triggerEvent(AutoNumeric.events.minRangeExceeded, this.domElement);\n            } else if (!maxTest) {\n                _AutoNumericHelper2.default.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            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._stripAllNonNumberCharacters(left.substr(oldParts[0].length), this.settings, true, this.isFocused);\n                if (!this._setValueParts(modifiedLeftPart, right, true)) {\n                    _AutoNumericHelper2.default.setElementValue(this.domElement, oldParts.join(''));\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            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\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) && 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 && _AutoNumericHelper2.default.contains(value, this.settings.negativeSignCharacter)) {\n                                left = left.substring(1);\n                            } else if (left !== '-' && (this.selection.start <= value.indexOf(this.settings.negativeSignCharacter) || !_AutoNumericHelper2.default.contains(value, this.settings.negativeSignCharacter))) {\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) && _AutoNumericHelper2.default.contains(value, this.settings.negativeSignCharacter)) {\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 !== '' && !_AutoNumericHelper2.default.contains(value, this.settings.negativeSignCharacter)) {\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))) {\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 this.settings.decimalPlacesShownOnFocus !== AutoNumeric.options.decimalPlacesShownOnFocus.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 || this.eventKey === '.' || this.eventKey === ',' || this.eventKey === _AutoNumericEnum2.default.keyName.NumpadDot) {\n                if (!this._isDecimalCharacterInsertionAllowed() || !this.settings.decimalCharacter) {\n                    return true;\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.negativeSignCharacter` is only set if the minimumValue or maximumValue is lower than zero, allowing negative numbers to be entered)\n            if ((this.eventKey === '-' || this.eventKey === '+') && this.settings.negativeSignCharacter === '-') {\n                if (left === '' && _AutoNumericHelper2.default.contains(right, this.settings.negativeSignCharacter)) {\n                    // The value is originally negative (with a trailing negative sign)\n                    right = right.replace(this.settings.negativeSignCharacter, '');\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`?\n                } else {\n                    // The value is originally positive\n                    left = this.settings.negativeSignCharacter + left;\n                }\n\n                this._setValueParts(left, right);\n\n                return true;\n            }\n\n            // If the user tries to insert a digit before the minus sign\n            var eventNumber = Number(this.eventKey);\n            if (eventNumber >= 0 && eventNumber <= 9) {\n                if (this.settings.negativeSignCharacter && left === '' && _AutoNumericHelper2.default.contains(right, this.settings.negativeSignCharacter)) {\n                    left = this.settings.negativeSignCharacter;\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 = this.settings.negativeSignCharacter + 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            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)) {\n                    negativeSign = '-';\n                    subParts = subParts.replace('-', '');\n                    left = left.replace('-', '');\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 === '-' && subParts.length > this.settings.mIntNeg && left.charAt(0) === '0') {\n                    left = left.slice(1);\n                }\n\n                left = negativeSign + left;\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 !== '') {\n                    leftAr.shift();\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('-');\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) {\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) ? 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 || value === elementValue && (this.eventKey === _AutoNumericEnum2.default.keyName.num0 || this.eventKey === _AutoNumericEnum2.default.keyName.numpad0)) {\n                this._setElementValue(value);\n                this._setCaretPosition(position);\n            }\n\n            if (this.androidSelectionStart !== null) {\n                // If an Android browser is detected, fix the caret position\n                // Unfortunately this does not fix all android browsers, only Android Chrome currently.\n                // This is due to the fact those provide different order of events and/or keycodes thrown (this is a real mess :|).\n                this._setCaretPosition(this.androidSelectionStart);\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 <input> 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.0.2';\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<object|string>} optionsArray\n         * @returns {{}}\n         */\n\n    }, {\n        key: 'mergeOptions',\n        value: function mergeOptions(optionsArray) {\n            var _this5 = 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, _this5._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: '_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 <form> 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 _this6 = 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 (_this6.test(input)) {\n                    autoNumericInputs.push(input);\n                }\n            });\n\n            return autoNumericInputs;\n        }\n\n        // Static methods\n        /**\n         * Test if the given domElement is already managed by AutoNumeric (if it has been initialized on the current page).\n         *\n         * @param {HTMLElement} domElement\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'test',\n        value: function test(domElement) {\n            return this._isInGlobalList(domElement);\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' || //TODO Make sure for the other options that 'false' and 'true' are correctly taken into account\n            options.allowDecimalPadding === AutoNumeric.options.allowDecimalPadding.floats) && (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 (!testPositiveInteger.test(options.digitalGroupSpacing)) {\n                _AutoNumericHelper2.default.throwError('The digital grouping for thousand separator option \\'digitalGroupSpacing\\' is invalid ; it should be a positive integer, [' + 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) || testNumericalCharacters.test(options.suffixText))) {\n                _AutoNumericHelper2.default.throwError('The additional suffix option \\'suffixText\\' is invalid ; it should not contains the negative sign \\'-\\' nor any numerical characters, [' + options.suffixText + '] 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.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.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.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<object|string|Array<string|object>>} options\n         * @returns {null|object}\n         * @private\n         */\n\n    }, {\n        key: '_generateOptionsObjectFromOptionsArray',\n        value: function _generateOptionsObjectFromOptionsArray(options) {\n            var _this7 = 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, _this7._getOptionObject(optionObject));\n                    });\n                } else if (options.length >= 1) {\n                    options.forEach(function (optionObject) {\n                        _extends(optionsResult, _this7._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            if (value < 0) {\n                settings.negativeSignCharacter = '-';\n            } else {\n                settings.negativeSignCharacter = '';\n            }\n\n            var regex = {};\n            this._cachesUsualRegularExpressions(settings, regex); // This is needed by `_stripAllNonNumberCharacters` 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                _AutoNumericHelper2.default.triggerEvent(AutoNumeric.events.formatted, document, 'Range test failed');\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            // 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 (_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            value = value.toString();\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)) {\n                settings.negativeSignCharacter = '-';\n            } else if (!_AutoNumericHelper2.default.isNull(settings.negativeBracketsTypeOnBlur)) {\n                var _settings$negativeBra3 = settings.negativeBracketsTypeOnBlur.split(',');\n\n                var _settings$negativeBra4 = _slicedToArray(_settings$negativeBra3, 2);\n\n                settings.firstBracket = _settings$negativeBra4[0];\n                settings.lastBracket = _settings$negativeBra4[1];\n\n                if (value.charAt(0) === settings.firstBracket && value.charAt(value.length - 1) === settings.lastBracket) {\n                    settings.negativeSignCharacter = '-';\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);\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} options\n         * @returns {*}\n         */\n\n    }, {\n        key: 'localize',\n        value: function localize(numericStringOrDomElement) {\n            var options = 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 (_AutoNumericHelper2.default.isNull(options)) {\n                options = AutoNumeric.defaultSettings;\n            }\n\n            value = this.unformat(value, options);\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 && options.leadingZero !== AutoNumeric.options.leadingZero.keep) {\n                value = '0';\n            }\n\n            var outputFormatToUse = void 0;\n            if (_AutoNumericHelper2.default.isNull(options)) {\n                outputFormatToUse = options.outputFormat;\n            } else {\n                outputFormatToUse = AutoNumeric.defaultSettings.outputFormat;\n            }\n\n            return this._toLocale(value, outputFormatToUse);\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         *\n         * @param {HTMLElement} domElement\n         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isManagedByAutoNumeric',\n        value: function isManagedByAutoNumeric(domElement) {\n            //FIXME test this\n            return this._isInGlobalList(domElement);\n        }\n\n        /**\n         * Return the AutoNumeric object that manages the given DOM element.\n         *\n         * @param {HTMLElement} domElement\n         * @returns {null|AutoNumeric}\n         */\n\n    }, {\n        key: 'getAutoNumericElement',\n        value: function getAutoNumericElement(domElement) {\n            //FIXME test this\n            if (!this.isManagedByAutoNumeric(domElement)) {\n                return null;\n            }\n\n            return this._getFromGlobalList(domElement);\n        }\n    }, {\n        key: '_stripAllNonNumberCharacters',\n        value: function _stripAllNonNumberCharacters(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            //TODO Refactor this with `convertToNumericString()` if possible?\n            s = String(s); // Typecast to to a string, in case that the initialValue is a number\n\n            if (settings.currencySymbol !== '') {\n                // Remove currency sign\n                s = s.replace(settings.currencySymbol, '');\n            }\n\n            if (settings.suffixText) {\n                // Remove suffix\n                s = s.replace(settings.suffixText, '');\n            }\n\n            //TODO Remove the positive sign too?\n\n            // First replace anything before digits\n            s = s.replace(settings.skipFirstAutoStrip, '$1$2');\n\n            // Then replace anything after digits\n            s = s.replace(settings.skipLastAutoStrip, '$1');\n\n            // Then remove any uninteresting characters\n            s = s.replace(settings.allowedAutoStrip, '');\n            if (settings.decimalCharacterAlternative) {\n                s = s.replace(settings.decimalCharacterAlternative, settings.decimalCharacter);\n            }\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 need\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 need\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            var result = void 0;\n            if (!_AutoNumericHelper2.default.isNull(settings.negativeBracketsTypeOnBlur)) {\n                result = '' + settings.firstBracket + value.replace(settings.negativeSignCharacter, '') + settings.lastBracket;\n            } else {\n                result = value;\n            }\n\n            return result;\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 = '-' + result;\n                }\n            } else {\n                result = value;\n            }\n\n            return result;\n        }\n    }, {\n        key: '_convertToNumericString',\n        value: function _convertToNumericString(s, settings) {\n            // Remove the currency symbol\n            s = s.replace(settings.currencySymbol, '');\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            // Remove the suffixText\n            if (settings.suffixText !== AutoNumeric.options.suffixText.none) {\n                s = s.replace(settings.suffixText, '');\n            }\n\n            // Move the trailing negative sign to the right position, if any\n            if (_AutoNumericHelper2.default.isNegative(s) && s.lastIndexOf('-') === s.length - 1) {\n                s = s.replace('-', '');\n                s = '-' + s;\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         * Converts the ISO numeric string to the locale decimal and minus sign placement.\n         * See the \"outputFormat\" option definition for more details.\n         *\n         * @param {string|null} value\n         * @param {string|null} locale\n         * @returns {*}\n         */\n\n    }, {\n        key: '_toLocale',\n        value: function _toLocale(value, locale) {\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            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 !== '-' && 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.\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 = _AutoNumericHelper2.default.isNegative(inputValue) || _AutoNumericHelper2.default.isNegativeWithBrackets(inputValue, settings.firstBracket, settings.lastBracket); // Test if the value is negative before removing the negative sign\n\n            inputValue = this._stripAllNonNumberCharacters(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('-', '');\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))) {\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\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                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\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            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            var allNumbersReg = '[0-9]';\n            var noAllNumbersReg = '[^0-9]';\n\n            // Test if there is a negative character in the string\n            var aNegReg = settings.negativeSignCharacter ? '([-\\\\' + settings.negativeSignCharacter + ']?)' : '(-?)';\n            regex.aNegRegAutoStrip = aNegReg;\n\n            var negativeSignRegPart = void 0;\n            if (settings.negativeSignCharacter) {\n                negativeSignRegPart = '\\\\' + settings.negativeSignCharacter;\n            } else {\n                negativeSignRegPart = '';\n            }\n\n            settings.skipFirstAutoStrip = new RegExp(aNegReg + '[^-' + negativeSignRegPart + '\\\\' + settings.decimalCharacter + allNumbersReg + '].*?(' + allNumbersReg + '|\\\\' + settings.decimalCharacter + allNumbersReg + ')');\n            settings.skipLastAutoStrip = new RegExp('(' + allNumbersReg + '\\\\' + settings.decimalCharacter + '?)[^\\\\' + settings.decimalCharacter + allNumbersReg + ']' + noAllNumbersReg + '*$');\n\n            var allowed = '-0123456789\\\\' + settings.decimalCharacter;\n            settings.allowedAutoStrip = new RegExp('[^' + allowed + ']', 'g');\n            settings.numRegAutoStrip = new RegExp(aNegReg + '(?:\\\\' + settings.decimalCharacter + '?(' + allNumbersReg + '+\\\\' + settings.decimalCharacter + allNumbersReg + '+)|(' + allNumbersReg + '*(?:\\\\' + settings.decimalCharacter + allNumbersReg + '*)?))');\n\n            // Using this regex version `^${regex.aNegRegAutoStrip}0*(\\\\d|$)` entirely clear the input on blur\n            settings.stripReg = new RegExp('^' + regex.aNegRegAutoStrip + '0*(' + allNumbersReg + ')');\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                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                noEventListeners: true,\n                onInvalidPaste: true,\n                outputFormat: true,\n                overrideMinMaxLimits: 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                wheelStep: true,\n\n                // Additional information that are added to the `settings` object :\n                //FIXME 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                mIntNeg: true,\n                mIntPos: true,\n                negativeSignCharacter: true,\n                numRegAutoStrip: true,\n                originalDecimalPlaces: true,\n                originalDecimalPlacesRawValue: true,\n                positiveSignCharacter: true,\n                skipFirstAutoStrip: true,\n                skipLastAutoStrip: 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: '_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 = 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 value \"' + value + '\" being \\'set\\' is not numeric 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 _this8 = 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 (_this8.isManagedByAutoNumeric(element)) {\n                                var anObject = void 0;\n                                switch (formatType) {\n                                    case 'unformatted':\n                                        anObject = _this8.getAutoNumericElement(element);\n                                        if (!_AutoNumericHelper2.default.isNull(anObject)) {\n                                            valueResult = _this8.unformat(element, anObject.getSettings());\n                                        }\n                                        break;\n                                    case 'localized':\n                                        anObject = _this8.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 = _this8.localize(element, currentSettings);\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 <form> element is passed (or any other 'parent' (or 'root') DOM element), then autoNumeric will initialize each child `<input>` 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<HTMLInputElement>}} arg1\n * @param {number|Array|object|null} initialValue\n * @param {object|Array|null} options\n * @returns {Array}\n */\n\n\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 <form> 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 from https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent for obsolete browsers (IE)\n * //TODO Make sure we call that at least once when loading the AutoNumeric library\n */\n(function () {\n    if (typeof 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\n/**\n * //XXX This is needed in order to get direct access to the `AutoNumeric` constructor without having to use `new AutoNumeric.default()` (cf. http://stackoverflow.com/a/36389244/2834898) : using `export var __useDefault = true;` does not work though.\n * //XXX The workaround (using `module.exports = AutoNumeric` instead of `export default class AutoNumeric {}`) comes from https://github.com/webpack/webpack/issues/706#issuecomment-167908576\n * //XXX And the explanation why Babel 6 changed the way Babel 5 worked : http://stackoverflow.com/a/33506169/2834898\n * //XXX Ideally, we should be able to just declare `export default class AutoNumeric {}` in the future, and remove the following `module.exports = AutoNumeric;` line\n *\n * @type {AutoNumeric}\n */\nmodule.exports = AutoNumeric;\n}.call(window));//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvQXV0b051bWVyaWMuanM/YjJlOSJdLCJuYW1lcyI6WyJBdXRvTnVtZXJpYyIsImFyZzEiLCJhcmcyIiwiYXJnMyIsIl9zZXRBcmd1bWVudHNWYWx1ZXMiLCJkb21FbGVtZW50IiwiaW5pdGlhbFZhbHVlIiwidXNlck9wdGlvbnMiLCJkZWZhdWx0UmF3VmFsdWUiLCJfc2V0U2V0dGluZ3MiLCJfY2hlY2tFbGVtZW50Iiwic2F2ZWRDYW5jZWxsYWJsZVZhbHVlIiwiaGlzdG9yeVRhYmxlIiwiaGlzdG9yeVRhYmxlSW5kZXgiLCJvbkdvaW5nUmVkbyIsInBhcmVudEZvcm0iLCJfZ2V0UGFyZW50Rm9ybSIsInJ1bk9uY2UiLCJzZXR0aW5ncyIsImZvcm1hdE9uUGFnZUxvYWQiLCJfZm9ybWF0RGVmYXVsdFZhbHVlT25QYWdlTG9hZCIsImlzSW5wdXRFbGVtZW50IiwiaXNDb250ZW50RWRpdGFibGUiLCJub0V2ZW50TGlzdGVuZXJzIiwiX2NyZWF0ZUV2ZW50TGlzdGVuZXJzIiwiX3NldFJlYWRPbmx5IiwiX3NhdmVJbml0aWFsVmFsdWVzIiwic2Vzc2lvblN0b3JhZ2VBdmFpbGFibGUiLCJjb25zdHJ1Y3RvciIsIl9zdG9yYWdlVGVzdCIsInN0b3JhZ2VOYW1lUHJlZml4IiwiX3NldFBlcnNpc3RlbnRTdG9yYWdlTmFtZSIsImlzRm9jdXNlZCIsImlzV2hlZWxFdmVudCIsImlzRHJvcEV2ZW50IiwiaXNFZGl0aW5nIiwiY3JlYXRlTG9jYWxMaXN0IiwiX2NyZWF0ZUxvY2FsTGlzdCIsIl9hZGRUb0dsb2JhbExpc3QiLCJnbG9iYWwiLCJzZXQiLCJuZXdWYWx1ZSIsIm9wdGlvbnMiLCJhdXRvTnVtZXJpY0xvY2FsTGlzdCIsImZvckVhY2giLCJhTk9iamVjdCIsInNldFVuZm9ybWF0dGVkIiwidmFsdWUiLCJnZXQiLCJjYWxsYmFjayIsInJlc3VsdCIsInB1c2giLCJfZXhlY3V0ZUNhbGxiYWNrIiwiZ2V0TnVtZXJpY1N0cmluZyIsImdldEZvcm1hdHRlZCIsImdldE51bWJlciIsImdldExvY2FsaXplZCIsInJlZm9ybWF0IiwidW5mb3JtYXQiLCJ1bmZvcm1hdExvY2FsaXplZCIsImZvcmNlZE91dHB1dEZvcm1hdCIsInVwZGF0ZSIsIm5ld09wdGlvbnMiLCJpc1ByaXN0aW5lIiwiY2hlY2tPbmx5UmF3VmFsdWUiLCJjbGVhciIsImZvcmNlQ2xlYXJBbGwiLCJyZW1vdmUiLCJ3aXBlIiwibnVrZSIsImhhcyIsImRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0Iiwibm9kZSIsImFkZE9iamVjdCIsIm90aGVyQXV0b051bWVyaWNPYmplY3QiLCJnZXRBdXRvTnVtZXJpY0VsZW1lbnQiLCJfaGFzTG9jYWxMaXN0Iiwib3RoZXJBTkxvY2FsTGlzdCIsIl9nZXRMb2NhbExpc3QiLCJzaXplIiwibWVyZ2VkTG9jYWxMaXN0cyIsIk1hcCIsIm1lcmdlTWFwcyIsIl9hZGRUb0xvY2FsTGlzdCIsIl9zZXRMb2NhbExpc3QiLCJyZW1vdmVPYmplY3QiLCJrZWVwQ3VycmVudEFOT2JqZWN0IiwiaW5pdGlhbENvbXBsZXRlTG9jYWxMaXN0IiwiZGVsZXRlIiwiZW1wdHkiLCJrZWVwRWFjaEFOT2JqZWN0SW5JdHNPd25MaXN0IiwiZWxlbWVudHMiLCJnZXRMaXN0IiwicmVzZXQiLCJyYXdWYWx1ZSIsImRlZmF1bHRTZXR0aW5ncyIsImFsbG93RGVjaW1hbFBhZGRpbmciLCJjYXJldFBvc2l0aW9uT25Gb2N1cyIsIl9kZWxldGVMb2NhbExpc3QiLCJjdXJyZW5jeVN5bWJvbCIsImN1cnJlbmN5U3ltYm9sUGxhY2VtZW50IiwiZGVjaW1hbENoYXJhY3RlciIsImRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSIsImRlY2ltYWxQbGFjZXMiLCJ3YXJuaW5nIiwic2hvd1dhcm5pbmdzIiwiZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIiwiZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyIiwiZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyIsImRlZmF1bHRWYWx1ZU92ZXJyaWRlIiwiZGlnaXRhbEdyb3VwU3BhY2luZyIsImRpZ2l0R3JvdXBTZXBhcmF0b3IiLCJkaXZpc29yV2hlblVuZm9jdXNlZCIsImVtcHR5SW5wdXRCZWhhdmlvciIsIm51bGwiLCJmYWlsT25Vbmtub3duT3B0aW9uIiwiaGlzdG9yeVNpemUiLCJpc0NhbmNlbGxhYmxlIiwibGVhZGluZ1plcm8iLCJtYXhpbXVtVmFsdWUiLCJtaW5pbXVtVmFsdWUiLCJtb2RpZnlWYWx1ZU9uV2hlZWwiLCJuZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciIsIm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Iiwibm9FdmVudHMiLCJhZGRFdmVudHMiLCJfcmVtb3ZlRXZlbnRMaXN0ZW5lcnMiLCJvbkludmFsaWRQYXN0ZSIsIm91dHB1dEZvcm1hdCIsIm92ZXJyaWRlTWluTWF4TGltaXRzIiwicmF3VmFsdWVEaXZpc29yIiwicmVhZE9ubHkiLCJyb3VuZGluZ01ldGhvZCIsInNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UiLCJzeW1ib2xXaGVuVW5mb2N1c2VkIiwic2VsZWN0TnVtYmVyT25seSIsInNlbGVjdE9uRm9jdXMiLCJzZXJpYWxpemVTcGFjZXMiLCJzaG93T25seU51bWJlcnNPbkZvY3VzIiwic2hvd1Bvc2l0aXZlU2lnbiIsInN0eWxlUnVsZXMiLCJzdWZmaXhUZXh0IiwidW5mb3JtYXRPbkhvdmVyIiwidW5mb3JtYXRPblN1Ym1pdCIsIndoZWVsU3RlcCIsImluaXRpYWxWYWx1ZUh0bWxBdHRyaWJ1dGUiLCJnZXRBdHRyaWJ1dGUiLCJpc051bGwiLCJfb25Gb2N1c0luRnVuYyIsIl9vbkZvY3VzSW4iLCJlIiwiX29uRm9jdXNJbkFuZE1vdXNlRW50ZXJGdW5jIiwiX29uRm9jdXNJbkFuZE1vdXNlRW50ZXIiLCJfb25Gb2N1c0Z1bmMiLCJfb25Gb2N1cyIsIl9vbktleWRvd25GdW5jIiwiX29uS2V5ZG93biIsIl9vbktleXByZXNzRnVuYyIsIl9vbktleXByZXNzIiwiX29uSW5wdXRGdW5jIiwiX29uSW5wdXQiLCJfb25LZXl1cEZ1bmMiLCJfb25LZXl1cCIsIl9vbkZvY3VzT3V0QW5kTW91c2VMZWF2ZUZ1bmMiLCJfb25Gb2N1c091dEFuZE1vdXNlTGVhdmUiLCJfb25QYXN0ZUZ1bmMiLCJfb25QYXN0ZSIsIl9vbldoZWVsRnVuYyIsIl9vbldoZWVsIiwiX29uRm9ybVN1Ym1pdEZ1bmMiLCJfb25Gb3JtU3VibWl0IiwiX29uS2V5ZG93bkdsb2JhbEZ1bmMiLCJfb25LZXlkb3duR2xvYmFsIiwiX29uS2V5dXBHbG9iYWxGdW5jIiwiX29uS2V5dXBHbG9iYWwiLCJfb25Ecm9wRnVuYyIsIl9vbkRyb3AiLCJhZGRFdmVudExpc3RlbmVyIiwiX2RvZXNHbG9iYWxMaXN0RXhpc3RzIiwiZG9jdW1lbnQiLCJyZW1vdmVFdmVudExpc3RlbmVyIiwiaXNFbXB0eUhpc3RvcnlUYWJsZSIsImxlbmd0aCIsIl9oaXN0b3J5VGFibGVDdXJyZW50VmFsdWVVc2VkIiwiYWRkTmV3SGlzdG9yeVN0YXRlIiwibmV4dEhpc3RvcnlTdGF0ZUluZGV4IiwiYXJyYXlUcmltIiwic2VsZWN0aW9uIiwiZ2V0RWxlbWVudFNlbGVjdGlvbiIsInNlbGVjdGlvblN0YXJ0Iiwic3RhcnQiLCJzZWxlY3Rpb25FbmQiLCJlbmQiLCJfaGlzdG9yeVRhYmxlRm9yZ2V0IiwidW5kbyIsImNoZWNrIiwidW5kb0luZm8iLCJzZXRFbGVtZW50U2VsZWN0aW9uIiwiX2hpc3RvcnlUYWJsZVVuZG9PclJlZG8iLCJudW1iZXJPZkVudHJpZXNUb0ZvcmdldCIsInNoaWZ0ZWRBd2F5IiwiaSIsInNoaWZ0IiwiaW5kZXhUb1VzZSIsImlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSIsInBvc2l0aXZlIiwiX2FkZENTU0NsYXNzIiwiX3JlbW92ZUNTU0NsYXNzIiwibmVnYXRpdmUiLCJyYW5nZXMiLCJyYW5nZSIsIm1pbiIsIm1heCIsImNsYXNzIiwidXNlckRlZmluZWQiLCJpc0Z1bmN0aW9uIiwidXNlck9iamVjdCIsImlzU3RyaW5nIiwiY2xhc3NlcyIsImlzQXJyYXkiLCJjYWxsYmFja1Jlc3VsdCIsInVzZXJDbGFzcyIsImluZGV4IiwiaXNJbkFycmF5IiwiaXNJbnQiLCJ0aHJvd0Vycm9yIiwiY3NzQ2xhc3NOYW1lIiwiY2xhc3NMaXN0IiwiYWRkIiwib3JpZ2luYWxTZXR0aW5ncyIsImNsb25lT2JqZWN0IiwibnVtZXJpY1N0cmluZyIsIm9wdGlvbnNUb1VzZSIsIm9wdGlvbk9iamVjdCIsImVycm9yIiwic2F2ZUNoYW5nZVRvSGlzdG9yeSIsImlzVW5kZWZpbmVkIiwiX3NldEVsZW1lbnRBbmRSYXdWYWx1ZSIsIl9zYXZlVmFsdWVUb1BlcnNpc3RlbnRTdG9yYWdlIiwiX3RvTnVtZXJpY1ZhbHVlIiwiaXNOYU4iLCJOdW1iZXIiLCJzZXRWYWx1ZSIsInplcm8iLCJfY2hlY2tJZkluUmFuZ2VXaXRoT3ZlcnJpZGVPcHRpb24iLCJtaW5UZXN0IiwibWF4VGVzdCIsImlzWmVybyIsImlzWmVyb09ySGFzTm9WYWx1ZSIsImZvcmNlZFJhd1ZhbHVlIiwiX3JvdW5kUmF3VmFsdWUiLCJfdHJpbUxlYWRpbmdBbmRUcmFpbGluZ1plcm9zIiwicmVwbGFjZSIsIl9nZXRSYXdWYWx1ZVRvRm9ybWF0IiwiX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uRm9jdXMiLCJ0b1N0cmluZyIsIl9yb3VuZEZvcm1hdHRlZFZhbHVlU2hvd25PbkJsdXIiLCJfbW9kaWZ5TmVnYXRpdmVTaWduQW5kRGVjaW1hbENoYXJhY3RlckZvckZvcm1hdHRlZFZhbHVlIiwiX2FkZEdyb3VwU2VwYXJhdG9ycyIsInRyaWdnZXJFdmVudCIsImV2ZW50cyIsIm1pblJhbmdlRXhjZWVkZWQiLCJtYXhSYW5nZUV4Y2VlZGVkIiwiX3JlbW92ZVZhbHVlRnJvbVBlcnNpc3RlbnRTdG9yYWdlIiwiYWx3YXlzIiwic3RyaXBwZWRWYWx1ZSIsIl9yZW1vdmVCcmFja2V0cyIsIm5vcm1hbGl6ZWRWYWx1ZSIsIl9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnMiLCJpc051bWJlciIsIl9pc1VzZXJNYW51YWxseUVkaXRpbmdUaGVWYWx1ZSIsIl9wYXJzZVN0eWxlUnVsZXMiLCJfaGlzdG9yeVRhYmxlQWRkIiwibmV3RWxlbWVudFZhbHVlIiwib2xkRWxlbWVudFZhbHVlIiwiZ2V0RWxlbWVudFZhbHVlIiwic2V0RWxlbWVudFZhbHVlIiwiZm9ybWF0dGVkIiwib2xkVmFsdWUiLCJpc0Jvb2xlYW4iLCJfc2V0RWxlbWVudFZhbHVlIiwiX3NldFJhd1ZhbHVlIiwicmF3VmFsdWVGb3JUaGVFbGVtZW50VmFsdWUiLCJ0cmltUGFkZGVkWmVyb3NGcm9tRGVjaW1hbFBsYWNlcyIsIl90b0xvY2FsZSIsImlzRW1wdHlTdHJpbmciLCJrZWVwIiwib3V0cHV0Rm9ybWF0VG9Vc2UiLCJzZWxlY3ROdW1iZXIiLCJfZGVmYXVsdFNlbGVjdEFsbCIsInVuZm9ybWF0dGVkVmFsdWUiLCJ2YWx1ZUxlbiIsImN1cnJlbmN5U3ltYm9sU2l6ZSIsIm5lZ0xlbiIsImlzTmVnYXRpdmUiLCJzdWZmaXhUZXh0TGVuIiwic3VmZml4IiwibGVmdCIsInByZWZpeCIsInJpZ2h0IiwiaXNQb3NpdGl2ZSIsIm5vbmUiLCJlbGVtZW50VmFsdWUiLCJpbmRleE9mIiwiZGVjaW1hbENvdW50IiwicGFyZW50Tm9kZSIsIm90aGVyQW5FbGVtZW50IiwiZG9tRWxlbWVudFRvRGV0YWNoIiwiX3JlbW92ZUZyb21Mb2NhbExpc3QiLCJyZUZvcm1hdCIsInZhbHVlT3JFbGVtZW50Iiwib3B0aW9uT3ZlcnJpZGUiLCJfZm9ybWF0T3JVbmZvcm1hdE90aGVyIiwic3RyaW5nT3JFbGVtZW50IiwiaXNGb3JtYXR0aW5nIiwidmFsdWVPclN0cmluZ09yRWxlbWVudCIsInNldHRpbmdzVG9Vc2UiLCJfY2xvbmVBbmRNZXJnZVNldHRpbmdzIiwiaXNFbGVtZW50IiwiZm9ybWF0IiwiZG9tRWxlbWVudE9yQXJyYXlPclN0cmluZyIsImF0dGFjaGVkIiwicmV0dXJuQVNpbmdsZUF1dG9OdW1lcmljT2JqZWN0IiwiZG9tRWxlbWVudHNBcnJheSIsInF1ZXJ5U2VsZWN0b3JBbGwiLCJjdXJyZW50TG9jYWxMaXN0IiwiYXV0b051bWVyaWNPYmplY3RzQXJyYXkiLCJvcmlnaW5hbENyZWF0ZUxvY2FsTGlzdFNldHRpbmciLCJuZXdBdXRvTnVtZXJpY0VsZW1lbnQiLCJ0ZW1wb3JhcnlGb3JjZWRPcHRpb25zIiwiZm9jdXMiLCJfcmVtb3ZlRnJvbUdsb2JhbExpc3QiLCJyZW1vdmVDaGlsZCIsImZvcmNlU2VhcmNoIiwidGFnTmFtZSIsInRvTG93ZXJDYXNlIiwiX3NlcmlhbGl6ZU51bWVyaWNTdHJpbmciLCJmb3JtIiwiX3NlcmlhbGl6ZUZvcm1hdHRlZCIsIl9zZXJpYWxpemVMb2NhbGl6ZWQiLCJfc2VyaWFsaXplTnVtZXJpY1N0cmluZ0FycmF5IiwiX3NlcmlhbGl6ZUZvcm1hdHRlZEFycmF5IiwiX3NlcmlhbGl6ZUxvY2FsaXplZEFycmF5IiwiSlNPTiIsInN0cmluZ2lmeSIsImZvcm1BcnJheU51bWVyaWNTdHJpbmciLCJmb3JtQXJyYXlGb3JtYXR0ZWQiLCJmb3JtQXJyYXlMb2NhbGl6ZWQiLCJpbnB1dHMiLCJfZ2V0Q2hpbGRBTklucHV0RWxlbWVudCIsImlucHV0IiwiZm9ybVVuZm9ybWF0Iiwic3VibWl0IiwiZm9ybVJlZm9ybWF0IiwiZm9ybU51bWVyaWNTdHJpbmciLCJmb3JtRm9ybWF0dGVkIiwiZm9ybVVuZm9ybWF0TG9jYWxpemVkIiwiZm9ybUxvY2FsaXplZCIsImZvcm1Kc29uTnVtZXJpY1N0cmluZyIsImZvcm1Kc29uRm9ybWF0dGVkIiwiZm9ybUpzb25Mb2NhbGl6ZWQiLCJsb2NhbExpc3QiLCJhdXRvTnVtZXJpY09iamVjdCIsIm5ld1NldHRpbmdzIiwicHJlZGVmaW5lZE9wdGlvbiIsIl9tZXJnZVNldHRpbmdzIiwiX3VwZGF0ZVByZWRlZmluZWRPcHRpb25zIiwiZ2V0UHJlZGVmaW5lZE9wdGlvbnMiLCJGcmVuY2giLCJOb3J0aEFtZXJpY2FuIiwiQnJpdGlzaCIsIlN3aXNzIiwiSmFwYW5lc2UiLCJTcGFuaXNoIiwiQ2hpbmVzZSIsIkJyYXppbGlhbiIsImtleSIsImhhc093blByb3BlcnR5IiwiaHRtbEF0dHJpYnV0ZSIsImNhbWVsaXplIiwiaXNUcmFpbGluZ05lZ2F0aXZlIiwic3BsaXQiLCJmaXJzdEJyYWNrZXQiLCJsYXN0QnJhY2tldCIsInMiLCJuZWdhdGl2ZVNpZ25DaGFyYWN0ZXIiLCJtYXRjaCIsImlzVmFsdWVOZWdhdGl2ZSIsInRvdGFsTGVuZ3RoIiwidmFsdWVTaXplIiwiaW50ZWdlclNpemUiLCJoYXNEZWNpbWFsQ2hhciIsIm9mZnNldERlY2ltYWxDaGFyIiwiY29udGFpbnMiLCJkZWNpbWFsTGVmdCIsImRlY2ltYWxSaWdodCIsInNpZ25Ub1VzZSIsInBvc2l0aXZlU2lnbkNoYXJhY3RlciIsInBvc2l0aXZlTmVnYXRpdmVTaWduU2l6ZSIsImNhcmV0UG9zaXRpb24iLCJvcmlnaW5hbERpZ2l0R3JvdXBTZXBhcmF0b3IiLCJvcmlnaW5hbEN1cnJlbmN5U3ltYm9sIiwib3JpZ2luYWxTdWZmaXhUZXh0IiwibmFtZSIsInJhd1ZhbHVlU3RvcmFnZU5hbWUiLCJkZWNvZGVVUklDb21wb25lbnQiLCJpZCIsInNlc3Npb25TdG9yYWdlIiwic2V0SXRlbSIsImNvb2tpZSIsImdldEl0ZW0iLCJfcmVhZENvb2tpZSIsInJlbW92ZUl0ZW0iLCJkYXRlIiwiRGF0ZSIsInNldFRpbWUiLCJnZXRUaW1lIiwiZXhwaXJlcyIsInRvVVRDU3RyaW5nIiwiaW5pdGlhbEVsZW1lbnRWYWx1ZSIsInR5cGUiLCJhbHRLZXkiLCJfdW5mb3JtYXRBbHRIb3ZlcmVkIiwiaG92ZXJlZFdpdGhBbHQiLCJfcmVmb3JtYXRBbHRIb3ZlcmVkIiwicmF3VmFsdWVUb0Zvcm1hdCIsInJvdW5kZWRWYWx1ZSIsIm9ubHlOdW1iZXJzIiwiZm9ybWF0dGVkVmFsdWUiLCJ2YWx1ZU9uRm9jdXMiLCJ0YXJnZXQiLCJsYXN0VmFsIiwiaXNFbXB0eVZhbHVlIiwiX2lzRWxlbWVudFZhbHVlRW1wdHlPck9ubHlUaGVOZWdhdGl2ZVNpZ24iLCJvcmRlcmVkVmFsdWUiLCJfb3JkZXJWYWx1ZUN1cnJlbmN5U3ltYm9sQW5kU3VmZml4VGV4dCIsIl9zYXZlQ2FuY2VsbGFibGVWYWx1ZSIsInNlbGVjdCIsIl9pbml0aWFsQ2FyZXRQb3NpdGlvbiIsImdldEhvdmVyZWRFbGVtZW50IiwiX3VwZGF0ZUV2ZW50S2V5SW5mbyIsImluaXRpYWxWYWx1ZU9uS2V5ZG93biIsInByb2Nlc3NlZCIsImV2ZW50S2V5Iiwia2V5TmFtZSIsIkVzYyIsInByZXZlbnREZWZhdWx0IiwibmF0aXZlIiwidGFyZ2V0VmFsdWUiLCJFbnRlciIsImNoYW5nZSIsIl91cGRhdGVJbnRlcm5hbFByb3BlcnRpZXMiLCJfcHJvY2Vzc05vblByaW50YWJsZUtleXNBbmRTaG9ydGN1dHMiLCJCYWNrc3BhY2UiLCJEZWxldGUiLCJfcHJvY2Vzc0NoYXJhY3RlckRlbGV0aW9uIiwiX2Zvcm1hdFZhbHVlIiwidGhyb3dJbnB1dCIsIkluc2VydCIsImlzQ2hhcmFjdGVySW5zZXJ0aW9uQWxsb3dlZCIsIl9wcm9jZXNzQ2hhcmFjdGVySW5zZXJ0aW9uIiwicG9zaXRpb24iLCJhbmRyb2lkU2VsZWN0aW9uU3RhcnQiLCJBbmRyb2lkRGVmYXVsdCIsImNoYXJDb2RlQXQiLCJjaGFyQXQiLCJkZWNpbWFsQ2hhcmFjdGVyUG9zaXRpb24iLCJoYXNEZWNpbWFsQ2hhcmFjdGVyIiwiX3NldENhcmV0UG9zaXRpb24iLCJaIiwieiIsImN0cmxLZXkiLCJzaGlmdEtleSIsIl9oaXN0b3J5VGFibGVSZWRvIiwiX2hpc3RvcnlUYWJsZVVuZG8iLCJBbHQiLCJza2lwIiwidmFsdWVQYXJ0c0JlZm9yZVBhc3RlIiwiaXNPbkFuZHJvaWQiLCJUYWIiLCJpc1Jhd1ZhbHVlTnVsbCIsIlN0cmluZyIsIl9tb2RpZnlOZWdhdGl2ZVNpZ25BbmREZWNpbWFsQ2hhcmFjdGVyRm9yUmF3VmFsdWUiLCJfcm91bmRWYWx1ZSIsImdyb3VwZWRWYWx1ZSIsIm5ldmVyIiwiZmxvYXRzIiwiX29uQmx1ciIsInJhd1Bhc3RlZFRleHQiLCJ3aW5kb3ciLCJjbGlwYm9hcmREYXRhIiwiZ2V0RGF0YSIsImluaXRpYWxGb3JtYXR0ZWRWYWx1ZSIsInNlbGVjdGlvblNpemUiLCJpc0FsbElucHV0VGV4dFNlbGVjdGVkIiwiaXNQYXN0ZU5lZ2F0aXZlIiwiaXNOZWdhdGl2ZVN0cmljdCIsInNsaWNlIiwidW50cmFuc2xhdGVkUGFzdGVkVGV4dCIsIl9wcmVwYXJlUGFzdGVkVGV4dCIsInBhc3RlZFRleHQiLCJhcmFiaWNUb0xhdGluTnVtYmVycyIsImNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nIiwiaW5pdGlhbFVuZm9ybWF0dGVkTnVtYmVyIiwiaXNJbml0aWFsVmFsdWVOZWdhdGl2ZSIsImlzUGFzdGVOZWdhdGl2ZUFuZEluaXRpYWxWYWx1ZUlzUG9zaXRpdmUiLCJsZWZ0UGFydENvbnRhaW5lZEFEb3QiLCJsZWZ0UGFydCIsInJpZ2h0UGFydCIsInRydW5jYXRlIiwibGVmdEZvcm1hdHRlZFBhcnQiLCJyaWdodEZvcm1hdHRlZFBhcnQiLCJzZXRSYXdOZWdhdGl2ZVNpZ24iLCJjb252ZXJ0Q2hhcmFjdGVyQ291bnRUb0luZGV4UG9zaXRpb24iLCJjb3VudE51bWJlckNoYXJhY3RlcnNPblRoZUNhcmV0TGVmdFNpZGUiLCJtaW5QYXJzZSIsInBhcnNlU3RyIiwibWF4UGFyc2UiLCJsYXN0R29vZEtub3duUmVzdWx0IiwicGFzdGVkVGV4dEluZGV4IiwibW9kaWZpZWRMZWZ0UGFydCIsIl9jaGVja0lmSW5SYW5nZSIsImxhc3RHb29kS25vd25SZXN1bHRJbmRleCIsImxhc3RHb29kS25vd25SZXN1bHRTaXplIiwicmVwbGFjZUNoYXJBdCIsImlnbm9yZSIsImNsYW1wIiwibGVmdEZvcm1hdHRlZFBhcnQyIiwicmlnaHRGb3JtYXR0ZWRQYXJ0MiIsImluZGV4V2hlcmVQYXN0ZWRUZXh0SGFzQmVlbkluc2VydGVkIiwiaW5kZXhTZWxlY3Rpb25FbmRJblJhd1ZhbHVlIiwic2VsZWN0ZWRUZXh0IiwiY291bnRDaGFySW5UZXh0IiwidmFsdWVIYXNCZWVuU2V0IiwidmFsdWVIYXNCZWVuQ2xhbXBlZCIsImNsYW1wZWRWYWx1ZSIsImNsYW1wVG9SYW5nZUxpbWl0cyIsImNhcmV0UG9zaXRpb25JbkZvcm1hdHRlZE51bWJlciIsImZpbmRDYXJldFBvc2l0aW9uSW5Gb3JtYXR0ZWROdW1iZXIiLCJjdXJyZW50VW5mb3JtYXR0ZWRWYWx1ZSIsImlzV2hlZWxVcEV2ZW50IiwiaXNXaGVlbERvd25FdmVudCIsInN0ZXAiLCJhZGRBbmRSb3VuZFRvTmVhcmVzdEF1dG8iLCJzdWJ0cmFjdEFuZFJvdW5kVG9OZWFyZXN0QXV0byIsIl9zZXRTZWxlY3Rpb24iLCJkcm9wcGVkVGV4dCIsImRhdGFUcmFuc2ZlciIsImNsZWFuZWRWYWx1ZSIsInVuZm9ybWF0T3RoZXIiLCJjaGFyYWN0ZXIiLCJob3ZlcmVkRWxlbWVudCIsImlzTWFuYWdlZEJ5QXV0b051bWVyaWMiLCJhbkVsZW1lbnQiLCJhbGxvd2VkVGFnTGlzdCIsImN1cnJlbnRFbGVtZW50VGFnIiwiX2lzRWxlbWVudFRhZ1N1cHBvcnRlZCIsIl9pc0lucHV0RWxlbWVudCIsIl9pc0lucHV0VHlwZVN1cHBvcnRlZCIsImhhc0F0dHJpYnV0ZSIsImZvcmNlZEluaXRpYWxWYWx1ZSIsImN1cnJlbnRWYWx1ZSIsInVuTG9jYWxpemVkQ3VycmVudFZhbHVlIiwiSW5maW5pdHkiLCJfZ2V0VmFsdWVGcm9tUGVyc2lzdGVudFN0b3JhZ2UiLCJ0b1N0cmlwIiwibWF4aW11bVZhbHVlSW50ZWdlclBhcnQiLCJtaW5pbXVtVmFsdWVJbnRlZ2VyUGFydCIsIm1JbnRQb3MiLCJNYXRoIiwibUludE5lZyIsIl9jb252ZXJ0T2xkT3B0aW9uc1RvTmV3T25lcyIsImRlY2ltYWxQbGFjZXNSYXdWYWx1ZUluT3B0aW9ucyIsIm9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIiwiZGVjaW1hbFBsYWNlc0luT3B0aW9ucyIsIm9yaWdpbmFsRGVjaW1hbFBsYWNlcyIsIl9jYWxjdWxhdGVEZWNpbWFsUGxhY2VzT25VcGRhdGUiLCJnZXREZWZhdWx0Q29uZmlnIiwiZGF0YXNldCIsImNhcmV0Rml4IiwiX3RyYW5zZm9ybU9wdGlvbnNWYWx1ZXNUb0RlZmF1bHRUeXBlcyIsIl9ydW5DYWxsYmFja3NGb3VuZEluVGhlU2V0dGluZ3NPYmplY3QiLCJfY29ycmVjdE5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50T3B0aW9uIiwiX2NvcnJlY3RDYXJldFBvc2l0aW9uT25Gb2N1c0FuZFNlbGVjdE9uRm9jdXNPcHRpb25zIiwiX2NhbGN1bGF0ZURlY2ltYWxQbGFjZXNPbkluaXQiLCJfY2FsY3VsYXRlVk1pbkFuZFZNYXhJbnRlZ2VyU2l6ZXMiLCJfc2V0QWx0ZXJuYXRpdmVEZWNpbWFsU2VwYXJhdG9yQ2hhcmFjdGVyIiwiX3NldFRyYWlsaW5nTmVnYXRpdmVTaWduSW5mbyIsInJlZ2V4IiwiX2NhY2hlc1VzdWFsUmVndWxhckV4cHJlc3Npb25zIiwiX3NldEJyYWNrZXRzIiwiaXNFbXB0eU9iaiIsInZhbGlkYXRlIiwiX2tlZXBBbk9yaWdpbmFsU2V0dGluZ3NDb3B5IiwidGV4dCIsInN1YnN0cmluZyIsIl9nZXRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uIiwic3RyaXBaZXJvcyIsIkh5cGhlbiIsImRlbnkiLCJudW0wIiwibnVtcGFkMCIsIm0iLCJSZWdFeHAiLCJhTmVnUmVnQXV0b1N0cmlwIiwiaXNQYXN0ZSIsIl9ub3JtYWxpemVQYXJ0cyIsIm5vcm1hbGl6ZWRMZWZ0Iiwibm9ybWFsaXplZFJpZ2h0Iiwibm9ybWFsaXplZE5ld1ZhbHVlIiwicm91bmRlZFJhd1ZhbHVlIiwiX3RydW5jYXRlRGVjaW1hbFBsYWNlcyIsInRlc3RWYWx1ZSIsInZhbHVlVG9TZXRPbkVtcHR5Iiwicm91bmRlZFZhbHVlVG9TaG93IiwiY3VycmVuY3lTeW1ib2xMZW4iLCJoYXNOZWciLCJfZ2V0U2lnblBvc2l0aW9uIiwic2lnblBvc2l0aW9uIiwiY3VycmVuY3lTeW1ib2xQb3NpdGlvbiIsIm9sZFBhcnRzIiwic3Vic3RyIiwiX3NldFZhbHVlUGFydHMiLCJqb2luIiwibWV0YUtleSIsIl9jaGVja1Bhc3RlIiwiX3Nob3VsZFNraXBFdmVudEtleSIsImEiLCJjIiwidiIsIngiLCJfZXhwYW5kU2VsZWN0aW9uT25TaWduIiwiTGVmdEFycm93IiwiUmlnaHRBcnJvdyIsIl9kaXJlY3Rpb25LZXlzIiwiX2dldFVuZm9ybWF0dGVkTGVmdEFuZFJpZ2h0UGFydEFyb3VuZFRoZVNlbGVjdGlvbiIsIl9wcm9jZXNzQ2hhcmFjdGVyRGVsZXRpb25JZlRyYWlsaW5nTmVnYXRpdmVTaWduIiwiTnVtcGFkRG90IiwiX2lzRGVjaW1hbENoYXJhY3Rlckluc2VydGlvbkFsbG93ZWQiLCJldmVudE51bWJlciIsInN1YlBhcnRzIiwibmVnYXRpdmVTaWduIiwibGVmdEFyIiwic2lnblBhcnRzIiwiZXNjYXBlQ2hyIiwiZXNjYXBlZFBhcnRzIiwibWluaVBhcnRzIiwibGVmdFJlZyIsIm5ld0xlZnQiLCJpc0FyZzFFbGVtZW50IiwiaXNBcmcxU3RyaW5nIiwiaXNBcmcyT2JqZWN0IiwiaXNPYmplY3QiLCJpc0FyZzJBcnJheSIsIkFycmF5IiwiaXNBcmcyTnVtYmVyIiwiaXNOdW1iZXJPckFyYWJpYyIsImlzQXJnMlByZURlZmluZWRPcHRpb25OYW1lIiwiX2lzUHJlRGVmaW5lZE9wdGlvblZhbGlkIiwiaXNBcmcyTnVsbCIsImlzQXJnMkVtcHR5U3RyaW5nIiwiaXNBcmczT2JqZWN0IiwiaXNBcmczQXJyYXkiLCJpc0FyZzNOdWxsIiwiaXNBcmczUHJlRGVmaW5lZE9wdGlvbk5hbWUiLCJfZ2V0T3B0aW9uT2JqZWN0IiwibWVyZ2VPcHRpb25zIiwicXVlcnlTZWxlY3RvciIsIm9wdGlvbnNBcnJheSIsIm1lcmdlZE9wdGlvbnMiLCJvcHRpb25PYmplY3RPclByZWRlZmluZWRPcHRpb25TdHJpbmciLCJwcmVEZWZpbmVkT3B0aW9uTmFtZSIsInByZWRlZmluZWRPcHRpb25zIiwib3B0aW9uT2JqZWN0T3JQcmVkZWZpbmVkTmFtZSIsImZvcm1Ob2RlIiwiaW5wdXRMaXN0IiwiZ2V0RWxlbWVudHNCeVRhZ05hbWUiLCJhdXRvTnVtZXJpY0lucHV0cyIsImlucHV0RWxlbWVudHMiLCJwcm90b3R5cGUiLCJjYWxsIiwidGVzdCIsIl9pc0luR2xvYmFsTGlzdCIsIndlYWtNYXBOYW1lIiwiV2Vha01hcCIsImF1dG9OdW1lcmljR2xvYmFsTGlzdE5hbWUiLCJfY3JlYXRlV2Vha01hcCIsIl9jcmVhdGVHbG9iYWxMaXN0IiwiX2dldEZyb21HbG9iYWxMaXN0IiwiZ2V0U2V0dGluZ3MiLCJzaG91bGRFeHRlbmREZWZhdWx0T3B0aW9ucyIsIm9yaWdpbmFsT3B0aW9ucyIsImlzT3JpZ2luYWxPcHRpb25Bbk9iamVjdCIsImlzVHJ1ZU9yRmFsc2VTdHJpbmciLCJ0ZXN0UG9zaXRpdmVJbnRlZ2VyIiwidGVzdE51bWVyaWNhbENoYXJhY3RlcnMiLCJ0ZXN0RmxvYXRPckludGVnZXJBbmRQb3NzaWJsZU5lZ2F0aXZlU2lnbiIsInRlc3RQb3NpdGl2ZUZsb2F0T3JJbnRlZ2VyIiwiZG9Ob0ZvcmNlQ2FyZXRQb3NpdGlvbiIsImNvbW1hIiwiZG90Iiwibm9ybWFsU3BhY2UiLCJ0aGluU3BhY2UiLCJuYXJyb3dOb0JyZWFrU3BhY2UiLCJub0JyZWFrU3BhY2UiLCJub1NlcGFyYXRvciIsImFwb3N0cm9waGUiLCJhcmFiaWNUaG91c2FuZHNTZXBhcmF0b3IiLCJkb3RBYm92ZSIsIm1pZGRsZURvdCIsImFyYWJpY0RlY2ltYWxTZXBhcmF0b3IiLCJkZWNpbWFsU2VwYXJhdG9yS2V5U3ltYm9sIiwiY2VpbGluZyIsImZsb29yIiwicGFyc2VGbG9hdCIsIl92YWxpZGF0ZURlY2ltYWxQbGFjZXNSYXdWYWx1ZSIsImhhbGZVcFN5bW1ldHJpYyIsImhhbGZVcEFzeW1tZXRyaWMiLCJoYWxmRG93blN5bW1ldHJpYyIsImhhbGZEb3duQXN5bW1ldHJpYyIsImhhbGZFdmVuQmFua2Vyc1JvdW5kaW5nIiwidXBSb3VuZEF3YXlGcm9tWmVybyIsImRvd25Sb3VuZFRvd2FyZFplcm8iLCJ0b0NlaWxpbmdUb3dhcmRQb3NpdGl2ZUluZmluaXR5IiwidG9GbG9vclRvd2FyZE5lZ2F0aXZlSW5maW5pdHkiLCJ0b05lYXJlc3QwNSIsInRvTmVhcmVzdDA1QWx0IiwidXBUb05leHQwNSIsImRvd25Ub05leHQwNSIsInBhcmVudGhlc2VzIiwiYnJhY2tldHMiLCJjaGV2cm9ucyIsImN1cmx5QnJhY2VzIiwiYW5nbGVCcmFja2V0cyIsImphcGFuZXNlUXVvdGF0aW9uTWFya3MiLCJoYWxmQnJhY2tldHMiLCJ3aGl0ZVNxdWFyZUJyYWNrZXRzIiwicXVvdGF0aW9uTWFya3MiLCJndWlsbGVtZXRzIiwicHJlc3MiLCJhbGxvdyIsInN0cmluZyIsIm51bWJlciIsIm5lZ2F0aXZlRG90IiwibmVnYXRpdmVDb21tYSIsImRvdE5lZ2F0aXZlIiwiY29tbWFOZWdhdGl2ZSIsInBsdXMiLCJwZXJjZW50IiwicnVsZSIsImlzVmFsaWQiLCJvcHRpb25zUmVzdWx0IiwibnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCIsIl9nZW5lcmF0ZU9wdGlvbnNPYmplY3RGcm9tT3B0aW9uc0FycmF5IiwidmFsdWVTdHJpbmciLCJpc051bWJlclN0cmljdCIsIl9jb252ZXJ0VG9OdW1lcmljU3RyaW5nIiwidW53YW50ZWRDaGFyYWN0ZXJzIiwiTmFOIiwibG9jYWxpemVkVmFsdWUiLCJsb2NhbGl6ZSIsInNraXBGaXJzdEF1dG9TdHJpcCIsInNraXBMYXN0QXV0b1N0cmlwIiwiYWxsb3dlZEF1dG9TdHJpcCIsIm51bVJlZ0F1dG9TdHJpcCIsImludGVnZXJQYXJ0IiwiZGVjaW1hbFBhcnQiLCJtb2RpZmllZEludGVnZXJQYXJ0Iiwic3RyaXBSZWciLCJfYWRkQnJhY2tldHMiLCJyZWFycmFuZ2VTaWduc0FuZFZhbHVlT3JkZXIiLCJfbWVyZ2VDdXJyZW5jeVNpZ25OZWdhdGl2ZVBvc2l0aXZlU2lnbkFuZFZhbHVlIiwibGFzdEluZGV4T2YiLCJjb252ZXJ0VG9OdW1iZXIiLCJ0ZW1wIiwibG9jYWxlIiwic2lnbk9uRW1wdHkiLCJpbnB1dFZhbHVlIiwiY3VycmVudFJhd1ZhbHVlIiwiaXNOZWdhdGl2ZVdpdGhCcmFja2V0cyIsImRpZ2l0YWxHcm91cCIsInR3byIsInR3b1NjYWxlZCIsImZvdXIiLCJ0aHJlZSIsImRlY2ltYWxQbGFjZXNUb1JvdW5kVG8iLCJfdG9nZ2xlTmVnYXRpdmVCcmFja2V0Iiwicm91bmRlZElucHV0VmFsdWUiLCJkZWNpbWFsUGxhY2VzTmVlZGVkIiwiX3JvdW5kQ2xvc2VUbzA1IiwiX3ByZXBhcmVWYWx1ZUZvclJvdW5kaW5nIiwicHJlcGFyZWRWYWx1ZSIsImlucHV0VmFsdWVIYXNOb0RvdCIsImhhc0RlY2ltYWxzIiwidGVtcG9yYXJ5RGVjaW1hbFBsYWNlc092ZXJyaWRlIiwiZGVjaW1hbFBvc2l0aW9uVG9Vc2UiLCJjaGVja0RlY2ltYWxQbGFjZXMiLCJpbnB1dFZhbHVlUm91bmRlZCIsInplcm9zIiwiX3RydW5jYXRlWmVyb3MiLCJyb3VuZGVkU3RyTGVuZ3RoIiwibGFzdERpZ2l0IiwiaW5wdXRWYWx1ZUFycmF5Iiwib2RkIiwiX3Nob3VsZFJvdW5kVXAiLCJyb3VuZCIsImNlaWwiLCJtb2RpZmllZERlY2ltYWxQYXJ0IiwidmFsUGFyc2UiLCJ0ZXN0TWluTWF4IiwibmFtZUVRIiwiY2EiLCJtb2QiLCJkb05vdFNlbGVjdCIsInVzZURlZmF1bHQiLCJhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIiwiY3VycmVudFNldHRpbmdzIiwiYWxsTnVtYmVyc1JlZyIsIm5vQWxsTnVtYmVyc1JlZyIsImFOZWdSZWciLCJuZWdhdGl2ZVNpZ25SZWdQYXJ0IiwiYWxsb3dlZCIsIm9sZE9wdGlvbnNDb252ZXJ0ZXIiLCJhU2VwIiwiblNlcCIsImRHcm91cCIsImFEZWMiLCJhbHREZWMiLCJhU2lnbiIsInBTaWduIiwicE5lZyIsImFTdWZmaXgiLCJvTGltaXRzIiwidk1heCIsInZNaW4iLCJtRGVjIiwiZURlYyIsInNjYWxlRGVjaW1hbCIsImFTdG9yIiwibVJvdW5kIiwiYVBhZCIsIm5CcmFja2V0Iiwid0VtcHR5IiwibFplcm8iLCJhRm9ybSIsInNOdW1iZXIiLCJhbkRlZmF1bHQiLCJ1blNldE9uU3VibWl0Iiwib3V0cHV0VHlwZSIsImRlYnVnIiwib3B0aW9uIiwicGFyc2VkTWluVmFsdWUiLCJwYXJzZWRNYXhWYWx1ZSIsInBhcnNlZFZhbHVlIiwiZXZlbnRLZXlOYW1lIiwiaXNGbktleXMiLCJfYWxsRm5LZXlzIiwiaXNPU0tleXMiLCJPU0xlZnQiLCJPU1JpZ2h0IiwiaXNDb250ZXh0TWVudSIsIkNvbnRleHRNZW51IiwiaXNTb21lTm9uUHJpbnRhYmxlS2V5cyIsIl9zb21lTm9uUHJpbnRhYmxlS2V5cyIsImlzT3RoZXJOb25QcmludGFibGVLZXlzIiwiTnVtTG9jayIsIlNjcm9sbExvY2siLCJDb21tYW5kIiwiaXNVbnJlY29nbml6YWJsZUtleXMiLCJVbmlkZW50aWZpZWQiLCJpbnRvQW5BcnJheSIsImZvcm1hdFR5cGUiLCJzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIiLCJub2RlTmFtZSIsImVsZW1lbnQiLCJkaXNhYmxlZCIsInNlbGVjdGVkIiwiZW5jb2RlVVJJQ29tcG9uZW50IiwiY2hlY2tlZCIsInZhbHVlUmVzdWx0IiwiYW5PYmplY3QiLCJmaW5hbFJlc3VsdCIsIl9zZXJpYWxpemUiLCJtdWx0aXBsZSIsInJvb3RFbGVtZW50IiwiZXhjbHVkZSIsImZpbHRlck91dCIsImlzSW5pdGlhbFZhbHVlQXJyYXkiLCJpc0luaXRpYWxWYWx1ZUFycmF5QW5kTm90RW1wdHkiLCJzZWNvbmRBcmd1bWVudElzSW5pdGlhbFZhbHVlQXJyYXkiLCJzZWNvbmRBcmd1bWVudElzT3B0aW9uQXJyYXkiLCJ0eXBlT2ZGaXJzdEFycmF5RWxlbWVudCIsImlzT3B0aW9uc0FycmF5QW5kTm90RW1wdHkiLCJ0aGlyZEFyZ3VtZW50SXNPcHRpb25BcnJheSIsImlzSW5pdGlhbFZhbHVlTnVtYmVyIiwiaW5pdGlhbFZhbHVlQXJyYXlTaXplIiwiQ3VzdG9tRXZlbnQiLCJldmVudCIsInBhcmFtcyIsImJ1YmJsZXMiLCJjYW5jZWxhYmxlIiwiZGV0YWlsIiwiZXZ0IiwiY3JlYXRlRXZlbnQiLCJpbml0Q3VzdG9tRXZlbnQiLCJFdmVudCIsIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7Ozs7O3FqQkFBQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBNkNBOztBQUVBOzs7QUFDQTs7OztBQUNBOzs7Ozs7Ozs7O0FBRUE7Ozs7O0lBS01BLFc7QUFDRjtBQUNBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF1Q0EsMkJBQW1EO0FBQUEsWUFBdkNDLElBQXVDLHVFQUFoQyxJQUFnQzs7QUFBQTs7QUFBQSxZQUExQkMsSUFBMEIsdUVBQW5CLElBQW1CO0FBQUEsWUFBYkMsSUFBYSx1RUFBTixJQUFNOztBQUFBOztBQUMvQztBQUNBO0FBQ0E7QUFIK0Msb0NBSUdILFlBQVlJLG1CQUFaLENBQWdDSCxJQUFoQyxFQUFzQ0MsSUFBdEMsRUFBNENDLElBQTVDLENBSkg7QUFBQSxZQUl2Q0UsVUFKdUMseUJBSXZDQSxVQUp1QztBQUFBLFlBSTNCQyxZQUoyQix5QkFJM0JBLFlBSjJCO0FBQUEsWUFJYkMsV0FKYSx5QkFJYkEsV0FKYTs7QUFNL0M7OztBQUNBLGFBQUtGLFVBQUwsR0FBa0JBLFVBQWxCOztBQUVBO0FBQ0EsYUFBS0csZUFBTCxHQUF1QixFQUF2QixDQVYrQyxDQVVwQjtBQUMzQixhQUFLQyxZQUFMLENBQWtCRixXQUFsQixFQUErQixLQUEvQjtBQUNBO0FBQ0E7QUFDQSxhQUFLRyxhQUFMOztBQUVBO0FBQ0E7QUFDQSxhQUFLQyxxQkFBTCxHQUE2QixJQUE3Qjs7QUFFQTtBQUNBLGFBQUtDLFlBQUwsR0FBb0IsRUFBcEIsQ0FyQitDLENBcUJ2QjtBQUN4QixhQUFLQyxpQkFBTCxHQUF5QixDQUFDLENBQTFCLENBdEIrQyxDQXNCbEI7QUFDN0IsYUFBS0MsV0FBTCxHQUFtQixLQUFuQixDQXZCK0MsQ0F1QnJCOztBQUUxQjtBQUNBLGFBQUtDLFVBQUwsR0FBa0IsS0FBS0MsY0FBTCxFQUFsQjs7QUFFQTtBQUNBLFlBQUksQ0FBQyxLQUFLQyxPQUFOLElBQWlCLEtBQUtDLFFBQUwsQ0FBY0MsZ0JBQW5DLEVBQXFEO0FBQ2pEO0FBQ0EsaUJBQUtDLDZCQUFMLENBQW1DZCxZQUFuQztBQUNIOztBQUVELGFBQUtXLE9BQUwsR0FBZSxJQUFmOztBQUVBO0FBQ0EsWUFBSSxLQUFLSSxjQUFMLElBQXVCLEtBQUtDLGlCQUFoQyxFQUFtRDtBQUMvQyxnQkFBSSxDQUFDLEtBQUtKLFFBQUwsQ0FBY0ssZ0JBQW5CLEVBQXFDO0FBQ2pDO0FBQ0EscUJBQUtDLHFCQUFMO0FBQ0g7O0FBRUQsaUJBQUtDLFlBQUw7QUFDSDs7QUFFRDtBQUNBLGFBQUtDLGtCQUFMLENBQXdCcEIsWUFBeEI7O0FBRUE7QUFDQSxhQUFLcUIsdUJBQUwsR0FBK0IsS0FBS0MsV0FBTCxDQUFpQkMsWUFBakIsRUFBL0I7QUFDQSxhQUFLQyxpQkFBTCxHQUF5QixPQUF6QixDQW5EK0MsQ0FtRGI7QUFDbEMsYUFBS0MseUJBQUw7O0FBRUE7QUFDQTtBQUNBO0FBQ0EsYUFBS0MsU0FBTCxHQUFpQixLQUFqQjtBQUNBO0FBQ0EsYUFBS0MsWUFBTCxHQUFvQixLQUFwQjtBQUNBO0FBQ0EsYUFBS0MsV0FBTCxHQUFtQixLQUFuQjtBQUNBO0FBQ0EsYUFBS0MsU0FBTCxHQUFpQixLQUFqQjs7QUFFQSxZQUFJLEtBQUtqQixRQUFMLENBQWNrQixlQUFsQixFQUFtQztBQUMvQjtBQUNBLGlCQUFLQyxnQkFBTDtBQUNIOztBQUVEO0FBQ0EsYUFBS1QsV0FBTCxDQUFpQlUsZ0JBQWpCLENBQWtDLElBQWxDOztBQUVBO0FBQ0E7QUFDQTtBQUNBLGFBQUtDLE1BQUwsR0FBYztBQUNWOzs7Ozs7QUFNQUMsaUJBQUssYUFBQ0MsUUFBRCxFQUE4QjtBQUFBLG9CQUFuQkMsT0FBbUIsdUVBQVQsSUFBUzs7QUFDL0Isc0JBQUtDLG9CQUFMLENBQTBCQyxPQUExQixDQUFrQyxvQkFBWTtBQUMxQ0MsNkJBQVNMLEdBQVQsQ0FBYUMsUUFBYixFQUF1QkMsT0FBdkI7QUFDSCxpQkFGRDtBQUdILGFBWFM7O0FBYVY7Ozs7Ozs7QUFPQUksNEJBQWdCLHdCQUFDQyxLQUFELEVBQTJCO0FBQUEsb0JBQW5CTCxPQUFtQix1RUFBVCxJQUFTOztBQUN2QyxzQkFBS0Msb0JBQUwsQ0FBMEJDLE9BQTFCLENBQWtDLG9CQUFZO0FBQzFDQyw2QkFBU0MsY0FBVCxDQUF3QkMsS0FBeEIsRUFBK0JMLE9BQS9CO0FBQ0gsaUJBRkQ7QUFHSCxhQXhCUzs7QUEwQlY7Ozs7Ozs7QUFPQU0saUJBQUssZUFBcUI7QUFBQSxvQkFBcEJDLFFBQW9CLHVFQUFULElBQVM7O0FBQ3RCLG9CQUFNQyxTQUFTLEVBQWY7QUFDQSxzQkFBS1Asb0JBQUwsQ0FBMEJDLE9BQTFCLENBQWtDLG9CQUFZO0FBQzFDTSwyQkFBT0MsSUFBUCxDQUFZTixTQUFTRyxHQUFULEVBQVo7QUFDSCxpQkFGRDtBQUdBLHNCQUFLSSxnQkFBTCxDQUFzQkYsTUFBdEIsRUFBOEJELFFBQTlCOztBQUVBLHVCQUFPQyxNQUFQO0FBQ0gsYUF6Q1M7O0FBMkNWOzs7Ozs7QUFNQUcsOEJBQWtCLDRCQUFxQjtBQUFBLG9CQUFwQkosUUFBb0IsdUVBQVQsSUFBUzs7QUFDbkMsb0JBQU1DLFNBQVMsRUFBZjtBQUNBLHNCQUFLUCxvQkFBTCxDQUEwQkMsT0FBMUIsQ0FBa0Msb0JBQVk7QUFDMUNNLDJCQUFPQyxJQUFQLENBQVlOLFNBQVNRLGdCQUFULEVBQVo7QUFDSCxpQkFGRDtBQUdBLHNCQUFLRCxnQkFBTCxDQUFzQkYsTUFBdEIsRUFBOEJELFFBQTlCOztBQUVBLHVCQUFPQyxNQUFQO0FBQ0gsYUF6RFM7O0FBMkRWOzs7Ozs7QUFNQUksMEJBQWMsd0JBQXFCO0FBQUEsb0JBQXBCTCxRQUFvQix1RUFBVCxJQUFTOztBQUMvQixvQkFBTUMsU0FBUyxFQUFmO0FBQ0Esc0JBQUtQLG9CQUFMLENBQTBCQyxPQUExQixDQUFrQyxvQkFBWTtBQUMxQ00sMkJBQU9DLElBQVAsQ0FBWU4sU0FBU1MsWUFBVCxFQUFaO0FBQ0gsaUJBRkQ7QUFHQSxzQkFBS0YsZ0JBQUwsQ0FBc0JGLE1BQXRCLEVBQThCRCxRQUE5Qjs7QUFFQSx1QkFBT0MsTUFBUDtBQUNILGFBekVTOztBQTJFVjs7Ozs7O0FBTUFLLHVCQUFXLHFCQUFxQjtBQUFBLG9CQUFwQk4sUUFBb0IsdUVBQVQsSUFBUzs7QUFDNUIsb0JBQU1DLFNBQVMsRUFBZjtBQUNBLHNCQUFLUCxvQkFBTCxDQUEwQkMsT0FBMUIsQ0FBa0Msb0JBQVk7QUFDMUNNLDJCQUFPQyxJQUFQLENBQVlOLFNBQVNVLFNBQVQsRUFBWjtBQUNILGlCQUZEO0FBR0Esc0JBQUtILGdCQUFMLENBQXNCRixNQUF0QixFQUE4QkQsUUFBOUI7O0FBRUEsdUJBQU9DLE1BQVA7QUFDSCxhQXpGUzs7QUEyRlY7Ozs7OztBQU1BTSwwQkFBYyx3QkFBcUI7QUFBQSxvQkFBcEJQLFFBQW9CLHVFQUFULElBQVM7O0FBQy9CLG9CQUFNQyxTQUFTLEVBQWY7QUFDQSxzQkFBS1Asb0JBQUwsQ0FBMEJDLE9BQTFCLENBQWtDLG9CQUFZO0FBQzFDTSwyQkFBT0MsSUFBUCxDQUFZTixTQUFTVyxZQUFULEVBQVo7QUFDSCxpQkFGRDtBQUdBLHNCQUFLSixnQkFBTCxDQUFzQkYsTUFBdEIsRUFBOEJELFFBQTlCOztBQUVBLHVCQUFPQyxNQUFQO0FBQ0gsYUF6R1M7O0FBMkdWOzs7QUFHQU8sc0JBQVUsb0JBQU07QUFDWixzQkFBS2Qsb0JBQUwsQ0FBMEJDLE9BQTFCLENBQWtDLG9CQUFZO0FBQzFDQyw2QkFBU1ksUUFBVDtBQUNILGlCQUZEO0FBR0gsYUFsSFM7O0FBb0hWOzs7QUFHQUMsc0JBQVUsb0JBQU07QUFDWixzQkFBS2Ysb0JBQUwsQ0FBMEJDLE9BQTFCLENBQWtDLG9CQUFZO0FBQzFDQyw2QkFBU2EsUUFBVDtBQUNILGlCQUZEO0FBR0gsYUEzSFM7O0FBNkhWOzs7OztBQUtBQywrQkFBbUIsNkJBQStCO0FBQUEsb0JBQTlCQyxrQkFBOEIsdUVBQVQsSUFBUzs7QUFDOUMsc0JBQUtqQixvQkFBTCxDQUEwQkMsT0FBMUIsQ0FBa0Msb0JBQVk7QUFDMUNDLDZCQUFTYyxpQkFBVCxDQUEyQkMsa0JBQTNCO0FBQ0gsaUJBRkQ7QUFHSCxhQXRJUzs7QUF3SVY7Ozs7O0FBS0FDLG9CQUFRLGtCQUFtQjtBQUFBLGtEQUFmQyxVQUFlO0FBQWZBLDhCQUFlO0FBQUE7O0FBQ3ZCLHNCQUFLbkIsb0JBQUwsQ0FBMEJDLE9BQTFCLENBQWtDLG9CQUFZO0FBQzFDQyw2QkFBU2dCLE1BQVQsaUJBQW1CQyxVQUFuQjtBQUNILGlCQUZEO0FBR0gsYUFqSlM7O0FBbUpWOzs7Ozs7O0FBT0FDLHdCQUFZLHNCQUE4QjtBQUFBLG9CQUE3QkMsaUJBQTZCLHVFQUFULElBQVM7O0FBQ3RDLG9CQUFJRCxhQUFhLElBQWpCO0FBQ0Esc0JBQUtwQixvQkFBTCxDQUEwQkMsT0FBMUIsQ0FBa0Msb0JBQVk7QUFDMUMsd0JBQUltQixjQUFjLENBQUNsQixTQUFTa0IsVUFBVCxDQUFvQkMsaUJBQXBCLENBQW5CLEVBQTJEO0FBQ3ZERCxxQ0FBYSxLQUFiO0FBQ0g7QUFDSixpQkFKRDs7QUFNQSx1QkFBT0EsVUFBUDtBQUNILGFBbktTOztBQXFLVjs7Ozs7QUFLQUUsbUJBQU8saUJBQTJCO0FBQUEsb0JBQTFCQyxhQUEwQix1RUFBVixLQUFVOztBQUM5QixzQkFBS3ZCLG9CQUFMLENBQTBCQyxPQUExQixDQUFrQyxvQkFBWTtBQUMxQ0MsNkJBQVNvQixLQUFULENBQWVDLGFBQWY7QUFDSCxpQkFGRDtBQUdILGFBOUtTOztBQWdMVjs7O0FBR0FDLG9CQUFRLGtCQUFNO0FBQ1Ysc0JBQUt4QixvQkFBTCxDQUEwQkMsT0FBMUIsQ0FBa0Msb0JBQVk7QUFDMUNDLDZCQUFTc0IsTUFBVDtBQUNILGlCQUZEO0FBR0gsYUF2TFM7O0FBeUxWOzs7QUFHQUMsa0JBQU0sZ0JBQU07QUFDUixzQkFBS3pCLG9CQUFMLENBQTBCQyxPQUExQixDQUFrQyxvQkFBWTtBQUMxQ0MsNkJBQVN1QixJQUFUO0FBQ0gsaUJBRkQ7QUFHSCxhQWhNUzs7QUFrTVY7OztBQUdBQyxrQkFBTSxnQkFBTTtBQUNSLHNCQUFLMUIsb0JBQUwsQ0FBMEJDLE9BQTFCLENBQWtDLG9CQUFZO0FBQzFDQyw2QkFBU3dCLElBQVQ7QUFDSCxpQkFGRDtBQUdILGFBek1TOztBQTJNVjs7Ozs7O0FBTUFDLGlCQUFLLDRDQUFpQztBQUNsQyxvQkFBSXBCLGVBQUo7QUFDQSxvQkFBSXFCLHlDQUF5Q3ZFLFdBQTdDLEVBQTBEO0FBQ3REa0QsNkJBQVMsTUFBS1Asb0JBQUwsQ0FBMEIyQixHQUExQixDQUE4QkMsOEJBQThCQyxJQUE5QixFQUE5QixDQUFUO0FBQ0gsaUJBRkQsTUFFTztBQUNIdEIsNkJBQVMsTUFBS1Asb0JBQUwsQ0FBMEIyQixHQUExQixDQUE4QkMsNkJBQTlCLENBQVQ7QUFDSDs7QUFFRCx1QkFBT3JCLE1BQVA7QUFDSCxhQTFOUzs7QUE0TlY7Ozs7OztBQU1BdUIsdUJBQVcsa0RBQWlDO0FBQ3hDO0FBQ0Esb0JBQUlwRSxtQkFBSjtBQUNBLG9CQUFJcUUsK0JBQUo7QUFDQSxvQkFBSUgseUNBQXlDdkUsV0FBN0MsRUFBMEQ7QUFDdERLLGlDQUFha0UsOEJBQThCQyxJQUE5QixFQUFiO0FBQ0FFLDZDQUF5QkgsNkJBQXpCO0FBQ0gsaUJBSEQsTUFHTztBQUNIbEUsaUNBQWFrRSw2QkFBYjtBQUNBRyw2Q0FBeUIxRSxZQUFZMkUscUJBQVosQ0FBa0NKLDZCQUFsQyxDQUF6QjtBQUNIOztBQUVEO0FBQ0Esb0JBQUksQ0FBQyxNQUFLSyxhQUFMLEVBQUwsRUFBMkI7QUFDdkIsMEJBQUt2QyxnQkFBTDtBQUNIOztBQUVEO0FBQ0Esb0JBQUl3QyxtQkFBbUJILHVCQUF1QkksYUFBdkIsRUFBdkI7QUFDQSxvQkFBSUQsaUJBQWlCRSxJQUFqQixLQUEwQixDQUE5QixFQUFpQztBQUM3QjtBQUNBTCwyQ0FBdUJyQyxnQkFBdkI7QUFDQXdDLHVDQUFtQkgsdUJBQXVCSSxhQUF2QixFQUFuQixDQUg2QixDQUc4QjtBQUM5RDs7QUFFRCxvQkFBSUUseUJBQUo7QUFDQSxvQkFBSUgsNEJBQTRCSSxHQUFoQyxFQUFxQztBQUNqQztBQUNBRCx1Q0FBbUIsNEJBQWtCRSxTQUFsQixDQUE0QixNQUFLSixhQUFMLEVBQTVCLEVBQWtERCxnQkFBbEQsQ0FBbkI7QUFDSCxpQkFIRCxNQUdPO0FBQ0g7QUFDQTtBQUNBLDBCQUFLTSxlQUFMLENBQXFCOUUsVUFBckIsRUFBaUNxRSxzQkFBakM7QUFDQU0sdUNBQW1CLE1BQUtGLGFBQUwsRUFBbkI7QUFDSDs7QUFFRDtBQUNBRSxpQ0FBaUJwQyxPQUFqQixDQUF5QixvQkFBWTtBQUNqQ0MsNkJBQVN1QyxhQUFULENBQXVCSixnQkFBdkI7QUFDSCxpQkFGRDtBQUdILGFBMVFTOztBQTRRVjs7Ozs7Ozs7Ozs7QUFXQUssMEJBQWMsc0JBQUNkLDZCQUFELEVBQWdFO0FBQUEsb0JBQWhDZSxtQkFBZ0MsdUVBQVYsS0FBVTs7QUFDMUU7QUFDQSxvQkFBSWpGLG1CQUFKO0FBQ0Esb0JBQUlxRSwrQkFBSjtBQUNBLG9CQUFJSCx5Q0FBeUN2RSxXQUE3QyxFQUEwRDtBQUN0REssaUNBQWFrRSw4QkFBOEJDLElBQTlCLEVBQWI7QUFDQUUsNkNBQXlCSCw2QkFBekI7QUFDSCxpQkFIRCxNQUdPO0FBQ0hsRSxpQ0FBYWtFLDZCQUFiO0FBQ0FHLDZDQUF5QjFFLFlBQVkyRSxxQkFBWixDQUFrQ0osNkJBQWxDLENBQXpCO0FBQ0g7O0FBRUQ7QUFDQSxvQkFBTWdCLDJCQUEyQixNQUFLNUMsb0JBQXRDO0FBQ0Esc0JBQUtBLG9CQUFMLENBQTBCNkMsTUFBMUIsQ0FBaUNuRixVQUFqQzs7QUFFQTtBQUNBa0YseUNBQXlCM0MsT0FBekIsQ0FBaUMsb0JBQVk7QUFDekNDLDZCQUFTdUMsYUFBVCxDQUF1QixNQUFLekMsb0JBQTVCO0FBQ0gsaUJBRkQ7O0FBSUEsb0JBQUksQ0FBQzJDLG1CQUFELElBQXdCakYsZUFBZSxNQUFLbUUsSUFBTCxFQUEzQyxFQUF3RDtBQUNwRDtBQUNBO0FBQ0FFLDJDQUF1QlUsYUFBdkIsQ0FBcUMsSUFBSUgsR0FBSixFQUFyQztBQUNILGlCQUpELE1BSU87QUFDSDtBQUNBO0FBQ0FQLDJDQUF1QnJDLGdCQUF2QjtBQUNIO0FBQ0osYUFyVFM7O0FBdVRWOzs7Ozs7QUFNQW9ELG1CQUFPLGlCQUEwQztBQUFBLG9CQUF6Q0MsNEJBQXlDLHVFQUFWLEtBQVU7O0FBQzdDLG9CQUFNSCwyQkFBMkIsTUFBSzVDLG9CQUF0Qzs7QUFFQTtBQUNBNEMseUNBQXlCM0MsT0FBekIsQ0FBaUMsb0JBQVk7QUFDekMsd0JBQUk4Qyw0QkFBSixFQUFrQztBQUM5QjdDLGlDQUFTUixnQkFBVDtBQUNILHFCQUZELE1BRU87QUFDSFEsaUNBQVN1QyxhQUFULENBQXVCLElBQUlILEdBQUosRUFBdkI7QUFDSDtBQUNKLGlCQU5EO0FBT0gsYUF4VVM7O0FBMFVWOzs7OztBQUtBVSxzQkFBVSxvQkFBTTtBQUNaLG9CQUFNekMsU0FBUyxFQUFmO0FBQ0Esc0JBQUtQLG9CQUFMLENBQTBCQyxPQUExQixDQUFrQyxvQkFBWTtBQUMxQ00sMkJBQU9DLElBQVAsQ0FBWU4sU0FBUzJCLElBQVQsRUFBWjtBQUNILGlCQUZEOztBQUlBLHVCQUFPdEIsTUFBUDtBQUNILGFBdFZTOztBQXdWVjs7OztBQUlBMEMscUJBQVM7QUFBQSx1QkFBTSxNQUFLakQsb0JBQVg7QUFBQSxhQTVWQzs7QUE4VlY7Ozs7QUFJQW9DLGtCQUFNO0FBQUEsdUJBQU0sTUFBS3BDLG9CQUFMLENBQTBCb0MsSUFBaEM7QUFBQTtBQWxXSSxTQUFkOztBQXFXQTtBQUNBOzs7O0FBSUEsYUFBS3JDLE9BQUwsR0FBZTtBQUNYOzs7OztBQUtBbUQsbUJBQStCLGlCQUFNO0FBQ2pDO0FBQ0Esc0JBQUszRSxRQUFMLEdBQWdCLEVBQUU0RSxVQUFXLE1BQUt0RixlQUFsQixFQUFoQixDQUZpQyxDQUVvQjtBQUNyRCxzQkFBS3FELE1BQUwsQ0FBWTdELFlBQVkrRixlQUF4Qjs7QUFFQTtBQUNILGFBWlU7QUFhWEMsaUNBQStCLG1EQUF1QjtBQUNsRCxzQkFBS25DLE1BQUwsQ0FBWSxFQUFFbUMseUNBQUYsRUFBWjs7QUFFQTtBQUNILGFBakJVO0FBa0JYQyxrQ0FBK0IscURBQXdCO0FBQUU7QUFDckQsc0JBQUsvRSxRQUFMLENBQWMrRSxvQkFBZCxHQUFxQ0EscUJBQXJDOztBQUVBO0FBQ0gsYUF0QlU7QUF1Qlg3RCw2QkFBK0IsNENBQW1CO0FBQzlDLHNCQUFLbEIsUUFBTCxDQUFja0IsZUFBZCxHQUFnQ0EsaUJBQWhDOztBQUVBO0FBQ0Esb0JBQUksTUFBS2xCLFFBQUwsQ0FBY2tCLGVBQWxCLEVBQW1DO0FBQy9CLHdCQUFJLENBQUMsTUFBS3dDLGFBQUwsRUFBTCxFQUEyQjtBQUN2Qiw4QkFBS3ZDLGdCQUFMO0FBQ0g7QUFDSixpQkFKRCxNQUlPO0FBQ0gsMEJBQUs2RCxnQkFBTDtBQUNIOztBQUVEO0FBQ0gsYUFwQ1U7QUFxQ1hDLDRCQUErQix5Q0FBa0I7QUFDN0Msc0JBQUt0QyxNQUFMLENBQVksRUFBRXNDLCtCQUFGLEVBQVo7O0FBRUE7QUFDSCxhQXpDVTtBQTBDWEMscUNBQStCLDJEQUEyQjtBQUN0RCxzQkFBS3ZDLE1BQUwsQ0FBWSxFQUFFdUMsaURBQUYsRUFBWjs7QUFFQTtBQUNILGFBOUNVO0FBK0NYQyw4QkFBK0IsNkNBQW9CO0FBQy9DLHNCQUFLeEMsTUFBTCxDQUFZLEVBQUV3QyxtQ0FBRixFQUFaOztBQUVBO0FBQ0gsYUFuRFU7QUFvRFhDLHlDQUErQixtRUFBK0I7QUFDMUQsc0JBQUtwRixRQUFMLENBQWNvRiwyQkFBZCxHQUE0Q0EsNEJBQTVDOztBQUVBO0FBQ0gsYUF4RFU7QUF5RFg7Ozs7OztBQU1BQywyQkFBK0IsdUNBQWlCO0FBQzVDLDRDQUFrQkMsT0FBbEIsQ0FBMEIsMFJBQTFCLEVBQXNULE1BQUt0RixRQUFMLENBQWN1RixZQUFwVTtBQUNBLHNCQUFLNUMsTUFBTCxDQUFZLEVBQUUwQyw2QkFBRixFQUFaOztBQUVBO0FBQ0gsYUFwRVU7QUFxRVhHLG1DQUErQix1REFBeUI7QUFBRTtBQUN0RCxzQkFBSzdDLE1BQUwsQ0FBWSxFQUFFNkMsNkNBQUYsRUFBWjs7QUFFQTtBQUNILGFBekVVO0FBMEVYQyxzQ0FBK0IsNkRBQTRCO0FBQ3ZELHNCQUFLOUMsTUFBTCxDQUFZLEVBQUU4QyxtREFBRixFQUFaOztBQUVBO0FBQ0gsYUE5RVU7QUErRVhDLHVDQUErQiwrREFBNkI7QUFDeEQsc0JBQUsvQyxNQUFMLENBQVksRUFBRStDLHFEQUFGLEVBQVo7O0FBRUE7QUFDSCxhQW5GVTtBQW9GWEMsa0NBQStCLHFEQUF3QjtBQUNuRCxzQkFBS2hELE1BQUwsQ0FBWSxFQUFFZ0QsMkNBQUYsRUFBWjs7QUFFQTtBQUNILGFBeEZVO0FBeUZYQyxpQ0FBK0IsbURBQXVCO0FBQ2xELHNCQUFLakQsTUFBTCxDQUFZLEVBQUVpRCx5Q0FBRixFQUFaOztBQUVBO0FBQ0gsYUE3RlU7QUE4RlhDLGlDQUErQixtREFBdUI7QUFDbEQsc0JBQUtsRCxNQUFMLENBQVksRUFBRWtELHlDQUFGLEVBQVo7O0FBRUE7QUFDSCxhQWxHVTtBQW1HWEMsa0NBQStCLHFEQUF3QjtBQUNuRCxzQkFBS25ELE1BQUwsQ0FBWSxFQUFFbUQsMkNBQUYsRUFBWjs7QUFFQTtBQUNILGFBdkdVO0FBd0dYQyxnQ0FBK0IsaURBQXNCO0FBQ2pELG9CQUFJLE1BQUtuQixRQUFMLEtBQWtCLElBQWxCLElBQTBCbUIsd0JBQXVCakgsWUFBWTBDLE9BQVosQ0FBb0J1RSxrQkFBcEIsQ0FBdUNDLElBQTVGLEVBQWtHO0FBQzlGO0FBQ0E7QUFDQTtBQUNBLGdEQUFrQlYsT0FBbEIsdUdBQWdJUyxtQkFBaEksZ01BQW1WLE1BQUsvRixRQUFMLENBQWN1RixZQUFqVztBQUNBLDBCQUFLWCxRQUFMLEdBQWdCLEVBQWhCO0FBQ0g7O0FBRUQsc0JBQUtqQyxNQUFMLENBQVksRUFBRW9ELHVDQUFGLEVBQVo7O0FBRUE7QUFDSCxhQXBIVTtBQXFIWEUsaUNBQStCLG1EQUF1QjtBQUNsRCxzQkFBS2pHLFFBQUwsQ0FBY2lHLG1CQUFkLEdBQW9DQSxvQkFBcEMsQ0FEa0QsQ0FDTzs7QUFFekQ7QUFDSCxhQXpIVTtBQTBIWGhHLDhCQUErQiw2Q0FBb0I7QUFDL0Msc0JBQUtELFFBQUwsQ0FBY0MsZ0JBQWQsR0FBaUNBLGlCQUFqQyxDQUQrQyxDQUNJOztBQUVuRDtBQUNILGFBOUhVO0FBK0hYaUcseUJBQStCLG1DQUFlO0FBQzFDLHNCQUFLbEcsUUFBTCxDQUFja0csV0FBZCxHQUE0QkEsWUFBNUI7O0FBRUE7QUFDSCxhQW5JVTtBQW9JWEMsMkJBQStCLHVDQUFpQjtBQUM1QyxzQkFBS25HLFFBQUwsQ0FBY21HLGFBQWQsR0FBOEJBLGNBQTlCLENBRDRDLENBQ0M7O0FBRTdDO0FBQ0gsYUF4SVU7QUF5SVhDLHlCQUErQixtQ0FBZTtBQUMxQyxzQkFBS3pELE1BQUwsQ0FBWSxFQUFFeUQseUJBQUYsRUFBWjs7QUFFQTtBQUNILGFBN0lVO0FBOElYQywwQkFBK0IscUNBQWdCO0FBQzNDLHNCQUFLMUQsTUFBTCxDQUFZLEVBQUUwRCwyQkFBRixFQUFaOztBQUVBO0FBQ0gsYUFsSlU7QUFtSlhDLDBCQUErQixxQ0FBZ0I7QUFDM0Msc0JBQUszRCxNQUFMLENBQVksRUFBRTJELDJCQUFGLEVBQVo7O0FBRUE7QUFDSCxhQXZKVTtBQXdKWEMsZ0NBQStCLGlEQUFzQjtBQUNqRCxzQkFBS3ZHLFFBQUwsQ0FBY3VHLGtCQUFkLEdBQW1DQSxtQkFBbkMsQ0FEaUQsQ0FDTTs7QUFFdkQ7QUFDSCxhQTVKVTtBQTZKWEMsd0NBQStCLGlFQUE4QjtBQUN6RCxzQkFBSzdELE1BQUwsQ0FBWSxFQUFFNkQsdURBQUYsRUFBWjs7QUFFQTtBQUNILGFBaktVO0FBa0tYQywyQ0FBK0IsdUVBQWlDO0FBQzVELHNCQUFLOUQsTUFBTCxDQUFZLEVBQUU4RCw2REFBRixFQUFaOztBQUVBO0FBQ0gsYUF0S1U7QUF1S1hwRyw4QkFBK0IsNkNBQW9CO0FBQUU7QUFDakQsb0JBQUlBLHNCQUFxQnZCLFlBQVkwQyxPQUFaLENBQW9CbkIsZ0JBQXBCLENBQXFDcUcsUUFBMUQsSUFBc0UsTUFBSzFHLFFBQUwsQ0FBY0ssZ0JBQWQsS0FBbUN2QixZQUFZMEMsT0FBWixDQUFvQm5CLGdCQUFwQixDQUFxQ3NHLFNBQWxKLEVBQTZKO0FBQ3pKO0FBQ0EsMEJBQUtDLHFCQUFMO0FBQ0g7O0FBRUQsc0JBQUtqRSxNQUFMLENBQVksRUFBRXRDLG1DQUFGLEVBQVo7O0FBRUE7QUFDSCxhQWhMVTtBQWlMWHdHLDRCQUErQix5Q0FBa0I7QUFDN0Msc0JBQUs3RyxRQUFMLENBQWM2RyxjQUFkLEdBQStCQSxlQUEvQixDQUQ2QyxDQUNFOztBQUUvQztBQUNILGFBckxVO0FBc0xYQywwQkFBK0IscUNBQWdCO0FBQzNDLHNCQUFLOUcsUUFBTCxDQUFjOEcsWUFBZCxHQUE2QkEsYUFBN0I7O0FBRUE7QUFDSCxhQTFMVTtBQTJMWEMsa0NBQStCLHFEQUF3QjtBQUNuRCxzQkFBS3BFLE1BQUwsQ0FBWSxFQUFFb0UsMkNBQUYsRUFBWjs7QUFFQTtBQUNILGFBL0xVO0FBZ01YQyw2QkFBK0IsMkNBQW1CO0FBQzlDLHNCQUFLckUsTUFBTCxDQUFZLEVBQUVxRSxpQ0FBRixFQUFaOztBQUVBO0FBQ0gsYUFwTVU7QUFxTVhDLHNCQUErQiw2QkFBWTtBQUFFO0FBQ3pDLHNCQUFLakgsUUFBTCxDQUFjaUgsUUFBZCxHQUF5QkEsU0FBekI7QUFDQSxzQkFBSzFHLFlBQUw7O0FBRUE7QUFDSCxhQTFNVTtBQTJNWDJHLDRCQUErQix5Q0FBa0I7QUFDN0Msc0JBQUt2RSxNQUFMLENBQVksRUFBRXVFLCtCQUFGLEVBQVo7O0FBRUE7QUFDSCxhQS9NVTtBQWdOWEMsdUNBQStCLCtEQUE2QjtBQUN4RCxzQkFBS3hFLE1BQUwsQ0FBWSxFQUFFd0UscURBQUYsRUFBWjs7QUFFQTtBQUNILGFBcE5VO0FBcU5YQyxpQ0FBK0IsbURBQXVCO0FBQ2xELHNCQUFLekUsTUFBTCxDQUFZLEVBQUV5RSx5Q0FBRixFQUFaOztBQUVBO0FBQ0gsYUF6TlU7QUEwTlhDLDhCQUErQiw2Q0FBb0I7QUFDL0Msc0JBQUtySCxRQUFMLENBQWNxSCxnQkFBZCxHQUFpQ0EsaUJBQWpDLENBRCtDLENBQ0k7O0FBRW5EO0FBQ0gsYUE5TlU7QUErTlhDLDJCQUErQix1Q0FBaUI7QUFDNUMsc0JBQUt0SCxRQUFMLENBQWNzSCxhQUFkLEdBQThCQSxjQUE5QixDQUQ0QyxDQUNDOztBQUU3QztBQUNILGFBbk9VO0FBb09YQyw2QkFBK0IsMkNBQW1CO0FBQzlDLHNCQUFLdkgsUUFBTCxDQUFjdUgsZUFBZCxHQUFnQ0EsZ0JBQWhDLENBRDhDLENBQ0c7O0FBRWpEO0FBQ0gsYUF4T1U7QUF5T1hDLG9DQUErQix5REFBMEI7QUFDckQsc0JBQUs3RSxNQUFMLENBQVksRUFBRTZFLCtDQUFGLEVBQVo7O0FBRUE7QUFDSCxhQTdPVTtBQThPWEMsOEJBQStCLDZDQUFvQjtBQUMvQyxzQkFBSzlFLE1BQUwsQ0FBWSxFQUFFOEUsbUNBQUYsRUFBWjs7QUFFQTtBQUNILGFBbFBVO0FBbVBYbEMsMEJBQStCLHFDQUFnQjtBQUMzQyxzQkFBS3ZGLFFBQUwsQ0FBY3VGLFlBQWQsR0FBNkJBLGFBQTdCLENBRDJDLENBQ0E7O0FBRTNDO0FBQ0gsYUF2UFU7QUF3UFhtQyx3QkFBK0IsaUNBQWM7QUFDekMsc0JBQUsvRSxNQUFMLENBQVksRUFBRStFLHVCQUFGLEVBQVo7O0FBRUE7QUFDSCxhQTVQVTtBQTZQWEMsd0JBQStCLGlDQUFjO0FBQ3pDLHNCQUFLaEYsTUFBTCxDQUFZLEVBQUVnRix1QkFBRixFQUFaOztBQUVBO0FBQ0gsYUFqUVU7QUFrUVhDLDZCQUErQiwyQ0FBbUI7QUFDOUMsc0JBQUs1SCxRQUFMLENBQWM0SCxlQUFkLEdBQWdDQSxnQkFBaEMsQ0FEOEMsQ0FDRzs7QUFFakQ7QUFDSCxhQXRRVTtBQXVRWEMsOEJBQStCLDZDQUFvQjtBQUMvQyxzQkFBSzdILFFBQUwsQ0FBYzZILGdCQUFkLEdBQWlDQSxpQkFBakMsQ0FEK0MsQ0FDSTs7QUFFbkQ7QUFDSCxhQTNRVTtBQTRRWEMsdUJBQStCLCtCQUFhO0FBQ3hDLHNCQUFLOUgsUUFBTCxDQUFjOEgsU0FBZCxHQUEwQkEsVUFBMUIsQ0FEd0MsQ0FDSDs7QUFFckM7QUFDSDtBQWhSVSxTQUFmO0FBa1JIOztBQUVEOzs7Ozs7Ozs7OztBQTZOQTs7Ozs7Ozs7OzJDQVNtQjFJLFksRUFBYztBQUM3QjtBQUNBO0FBQ0EsaUJBQUsySSx5QkFBTCxHQUFpQyxLQUFLNUksVUFBTCxDQUFnQjZJLFlBQWhCLENBQTZCLE9BQTdCLENBQWpDO0FBQ0EsZ0JBQUksNEJBQWtCQyxNQUFsQixDQUF5QixLQUFLRix5QkFBOUIsQ0FBSixFQUE4RDtBQUMxRDtBQUNBLHFCQUFLQSx5QkFBTCxHQUFpQyxFQUFqQztBQUNIOztBQUVEO0FBQ0EsaUJBQUszSSxZQUFMLEdBQW9CQSxZQUFwQjtBQUNBLGdCQUFJLDRCQUFrQjZJLE1BQWxCLENBQXlCLEtBQUs3SSxZQUE5QixDQUFKLEVBQWlEO0FBQzdDO0FBQ0EscUJBQUtBLFlBQUwsR0FBb0IsRUFBcEI7QUFDSDtBQUNKOztBQUVEOzs7Ozs7O2dEQUl3QjtBQUFBOztBQUNwQjtBQUNBO0FBQ0EsaUJBQUs4SSxjQUFMLEdBQXNCLGFBQUs7QUFBRSx1QkFBS0MsVUFBTCxDQUFnQkMsQ0FBaEI7QUFBcUIsYUFBbEQ7QUFDQSxpQkFBS0MsMkJBQUwsR0FBbUMsYUFBSztBQUFFLHVCQUFLQyx1QkFBTCxDQUE2QkYsQ0FBN0I7QUFBa0MsYUFBNUU7QUFDQSxpQkFBS0csWUFBTCxHQUFvQixZQUFNO0FBQUUsdUJBQUtDLFFBQUw7QUFBa0IsYUFBOUM7QUFDQSxpQkFBS0MsY0FBTCxHQUFzQixhQUFLO0FBQUUsdUJBQUtDLFVBQUwsQ0FBZ0JOLENBQWhCO0FBQXFCLGFBQWxEO0FBQ0EsaUJBQUtPLGVBQUwsR0FBdUIsYUFBSztBQUFFLHVCQUFLQyxXQUFMLENBQWlCUixDQUFqQjtBQUFzQixhQUFwRDtBQUNBLGlCQUFLUyxZQUFMLEdBQW9CLGFBQUs7QUFBRSx1QkFBS0MsUUFBTCxDQUFjVixDQUFkO0FBQW1CLGFBQTlDO0FBQ0EsaUJBQUtXLFlBQUwsR0FBb0IsYUFBSztBQUFFLHVCQUFLQyxRQUFMLENBQWNaLENBQWQ7QUFBbUIsYUFBOUM7QUFDQSxpQkFBS2EsNEJBQUwsR0FBb0MsYUFBSztBQUFFLHVCQUFLQyx3QkFBTCxDQUE4QmQsQ0FBOUI7QUFBbUMsYUFBOUU7QUFDQSxpQkFBS2UsWUFBTCxHQUFvQixhQUFLO0FBQUUsdUJBQUtDLFFBQUwsQ0FBY2hCLENBQWQ7QUFBbUIsYUFBOUM7QUFDQSxpQkFBS2lCLFlBQUwsR0FBb0IsYUFBSztBQUFFLHVCQUFLQyxRQUFMLENBQWNsQixDQUFkO0FBQW1CLGFBQTlDO0FBQ0EsaUJBQUttQixpQkFBTCxHQUF5QixZQUFNO0FBQUUsdUJBQUtDLGFBQUw7QUFBdUIsYUFBeEQ7QUFDQSxpQkFBS0Msb0JBQUwsR0FBNEIsYUFBSztBQUFFLHVCQUFLQyxnQkFBTCxDQUFzQnRCLENBQXRCO0FBQTJCLGFBQTlEO0FBQ0EsaUJBQUt1QixrQkFBTCxHQUEwQixhQUFLO0FBQUUsdUJBQUtDLGNBQUwsQ0FBb0J4QixDQUFwQjtBQUF5QixhQUExRDtBQUNBLGlCQUFLeUIsV0FBTCxHQUFtQixhQUFLO0FBQUUsdUJBQUtDLE9BQUwsQ0FBYTFCLENBQWI7QUFBa0IsYUFBNUM7O0FBRUE7QUFDQSxpQkFBS2pKLFVBQUwsQ0FBZ0I0SyxnQkFBaEIsQ0FBaUMsU0FBakMsRUFBNEMsS0FBSzdCLGNBQWpELEVBQWlFLEtBQWpFO0FBQ0EsaUJBQUsvSSxVQUFMLENBQWdCNEssZ0JBQWhCLENBQWlDLE9BQWpDLEVBQTBDLEtBQUsxQiwyQkFBL0MsRUFBNEUsS0FBNUU7QUFDQSxpQkFBS2xKLFVBQUwsQ0FBZ0I0SyxnQkFBaEIsQ0FBaUMsT0FBakMsRUFBMEMsS0FBS3hCLFlBQS9DLEVBQTZELEtBQTdEO0FBQ0EsaUJBQUtwSixVQUFMLENBQWdCNEssZ0JBQWhCLENBQWlDLFlBQWpDLEVBQStDLEtBQUsxQiwyQkFBcEQsRUFBaUYsS0FBakY7QUFDQSxpQkFBS2xKLFVBQUwsQ0FBZ0I0SyxnQkFBaEIsQ0FBaUMsU0FBakMsRUFBNEMsS0FBS3RCLGNBQWpELEVBQWlFLEtBQWpFO0FBQ0EsaUJBQUt0SixVQUFMLENBQWdCNEssZ0JBQWhCLENBQWlDLFVBQWpDLEVBQTZDLEtBQUtwQixlQUFsRCxFQUFtRSxLQUFuRTtBQUNBLGlCQUFLeEosVUFBTCxDQUFnQjRLLGdCQUFoQixDQUFpQyxPQUFqQyxFQUEwQyxLQUFLbEIsWUFBL0MsRUFBNkQsS0FBN0Q7QUFDQSxpQkFBSzFKLFVBQUwsQ0FBZ0I0SyxnQkFBaEIsQ0FBaUMsT0FBakMsRUFBMEMsS0FBS2hCLFlBQS9DLEVBQTZELEtBQTdEO0FBQ0EsaUJBQUs1SixVQUFMLENBQWdCNEssZ0JBQWhCLENBQWlDLE1BQWpDLEVBQXlDLEtBQUtkLDRCQUE5QyxFQUE0RSxLQUE1RTtBQUNBLGlCQUFLOUosVUFBTCxDQUFnQjRLLGdCQUFoQixDQUFpQyxZQUFqQyxFQUErQyxLQUFLZCw0QkFBcEQsRUFBa0YsS0FBbEY7QUFDQSxpQkFBSzlKLFVBQUwsQ0FBZ0I0SyxnQkFBaEIsQ0FBaUMsT0FBakMsRUFBMEMsS0FBS1osWUFBL0MsRUFBNkQsS0FBN0Q7QUFDQSxpQkFBS2hLLFVBQUwsQ0FBZ0I0SyxnQkFBaEIsQ0FBaUMsT0FBakMsRUFBMEMsS0FBS1YsWUFBL0MsRUFBNkQsS0FBN0Q7QUFDQSxpQkFBS2xLLFVBQUwsQ0FBZ0I0SyxnQkFBaEIsQ0FBaUMsTUFBakMsRUFBeUMsS0FBS0YsV0FBOUMsRUFBMkQsS0FBM0Q7O0FBRUEsZ0JBQUksQ0FBQyw0QkFBa0I1QixNQUFsQixDQUF5QixLQUFLcEksVUFBOUIsQ0FBTCxFQUFnRDtBQUM1QyxxQkFBS0EsVUFBTCxDQUFnQmtLLGdCQUFoQixDQUFpQyxRQUFqQyxFQUEyQyxLQUFLUixpQkFBaEQsRUFBbUUsS0FBbkU7QUFDSDs7QUFFRDtBQUNBLGdCQUFJLENBQUN6SyxZQUFZa0wscUJBQVosRUFBTCxFQUEwQztBQUN0Q0MseUJBQVNGLGdCQUFULENBQTBCLFNBQTFCLEVBQXFDLEtBQUtOLG9CQUExQyxFQUFnRSxLQUFoRTtBQUNBUSx5QkFBU0YsZ0JBQVQsQ0FBMEIsT0FBMUIsRUFBbUMsS0FBS0osa0JBQXhDLEVBQTRELEtBQTVEO0FBQ0g7QUFDSjs7QUFFRDs7Ozs7OztnREFJd0I7QUFBRTtBQUN0QixpQkFBS3hLLFVBQUwsQ0FBZ0IrSyxtQkFBaEIsQ0FBb0MsU0FBcEMsRUFBK0MsS0FBS2hDLGNBQXBELEVBQW9FLEtBQXBFO0FBQ0EsaUJBQUsvSSxVQUFMLENBQWdCK0ssbUJBQWhCLENBQW9DLE9BQXBDLEVBQTZDLEtBQUs3QiwyQkFBbEQsRUFBK0UsS0FBL0U7QUFDQSxpQkFBS2xKLFVBQUwsQ0FBZ0IrSyxtQkFBaEIsQ0FBb0MsT0FBcEMsRUFBNkMsS0FBSzNCLFlBQWxELEVBQWdFLEtBQWhFO0FBQ0EsaUJBQUtwSixVQUFMLENBQWdCK0ssbUJBQWhCLENBQW9DLFlBQXBDLEVBQWtELEtBQUs3QiwyQkFBdkQsRUFBb0YsS0FBcEY7QUFDQSxpQkFBS2xKLFVBQUwsQ0FBZ0IrSyxtQkFBaEIsQ0FBb0MsTUFBcEMsRUFBNEMsS0FBS2pCLDRCQUFqRCxFQUErRSxLQUEvRTtBQUNBLGlCQUFLOUosVUFBTCxDQUFnQitLLG1CQUFoQixDQUFvQyxZQUFwQyxFQUFrRCxLQUFLakIsNEJBQXZELEVBQXFGLEtBQXJGO0FBQ0EsaUJBQUs5SixVQUFMLENBQWdCK0ssbUJBQWhCLENBQW9DLFNBQXBDLEVBQStDLEtBQUt6QixjQUFwRCxFQUFvRSxLQUFwRTtBQUNBLGlCQUFLdEosVUFBTCxDQUFnQitLLG1CQUFoQixDQUFvQyxVQUFwQyxFQUFnRCxLQUFLdkIsZUFBckQsRUFBc0UsS0FBdEU7QUFDQSxpQkFBS3hKLFVBQUwsQ0FBZ0IrSyxtQkFBaEIsQ0FBb0MsT0FBcEMsRUFBNkMsS0FBS3JCLFlBQWxELEVBQWdFLEtBQWhFO0FBQ0EsaUJBQUsxSixVQUFMLENBQWdCK0ssbUJBQWhCLENBQW9DLE9BQXBDLEVBQTZDLEtBQUtuQixZQUFsRCxFQUFnRSxLQUFoRTtBQUNBLGlCQUFLNUosVUFBTCxDQUFnQitLLG1CQUFoQixDQUFvQyxPQUFwQyxFQUE2QyxLQUFLZixZQUFsRCxFQUFnRSxLQUFoRTtBQUNBLGlCQUFLaEssVUFBTCxDQUFnQitLLG1CQUFoQixDQUFvQyxPQUFwQyxFQUE2QyxLQUFLYixZQUFsRCxFQUFnRSxLQUFoRTs7QUFFQVkscUJBQVNDLG1CQUFULENBQTZCLFNBQTdCLEVBQXdDLEtBQUtULG9CQUE3QyxFQUFtRSxLQUFuRTtBQUNBUSxxQkFBU0MsbUJBQVQsQ0FBNkIsT0FBN0IsRUFBc0MsS0FBS1Asa0JBQTNDLEVBQStELEtBQS9EOztBQUVBLGdCQUFJLENBQUMsNEJBQWtCMUIsTUFBbEIsQ0FBeUIsS0FBS3BJLFVBQTlCLENBQUwsRUFBZ0Q7QUFDNUMscUJBQUtBLFVBQUwsQ0FBZ0JxSyxtQkFBaEIsQ0FBb0MsUUFBcEMsRUFBOEMsS0FBS1gsaUJBQW5ELEVBQXNFLEtBQXRFO0FBQ0g7QUFDSjs7QUFFRDs7Ozs7Ozs7dUNBS2U7QUFDWCxnQkFBSSxLQUFLcEosY0FBTCxJQUF1QixLQUFLSCxRQUFMLENBQWNpSCxRQUF6QyxFQUFtRDtBQUMvQyxxQkFBSzlILFVBQUwsQ0FBZ0I4SCxRQUFoQixHQUEyQixJQUEzQjtBQUNIO0FBQ0o7O0FBRUQ7Ozs7Ozs7Ozs7OzsyQ0FTbUI7QUFDZjtBQUNBLGdCQUFNa0Qsc0JBQXNCLEtBQUt6SyxZQUFMLENBQWtCMEssTUFBbEIsS0FBNkIsQ0FBekQ7QUFDQTtBQUNBLGdCQUFJRCx1QkFBdUIsS0FBS3ZGLFFBQUwsS0FBa0IsS0FBS3lGLDZCQUFMLEVBQTdDLEVBQW1GO0FBQy9FO0FBQ0Esb0JBQUlDLHFCQUFxQixJQUF6QjtBQUNBLG9CQUFJLENBQUNILG1CQUFMLEVBQTBCO0FBQ3RCO0FBQ0Esd0JBQU1JLHdCQUF3QixLQUFLNUssaUJBQUwsR0FBeUIsQ0FBdkQ7QUFDQSx3QkFBSTRLLHdCQUF3QixLQUFLN0ssWUFBTCxDQUFrQjBLLE1BQTFDLElBQW9ELEtBQUt4RixRQUFMLEtBQWtCLEtBQUtsRixZQUFMLENBQWtCNksscUJBQWxCLEVBQXlDMUksS0FBbkgsRUFBMEg7QUFDdEg7QUFDQXlJLDZDQUFxQixLQUFyQjtBQUNILHFCQUhELE1BR087QUFDSDtBQUNBLG9EQUFrQkUsU0FBbEIsQ0FBNEIsS0FBSzlLLFlBQWpDLEVBQStDLEtBQUtDLGlCQUFMLEdBQXlCLENBQXhFO0FBQ0g7QUFDSjs7QUFFRDtBQUNBLHFCQUFLQSxpQkFBTDs7QUFFQTtBQUNBLG9CQUFJMkssa0JBQUosRUFBd0I7QUFDcEI7QUFDQSx3QkFBTUcsWUFBWSw0QkFBa0JDLG1CQUFsQixDQUFzQyxLQUFLdkwsVUFBM0MsQ0FBbEI7QUFDQSx5QkFBS3dMLGNBQUwsR0FBc0JGLFVBQVVHLEtBQWhDO0FBQ0EseUJBQUtDLFlBQUwsR0FBb0JKLFVBQVVLLEdBQTlCOztBQUVBO0FBQ0EseUJBQUtwTCxZQUFMLENBQWtCdUMsSUFBbEIsQ0FBdUI7QUFDbkI7QUFDQUosK0JBQU8sS0FBSytDLFFBRk87QUFHbkI7QUFDQTtBQUNBO0FBQ0E7QUFDQWdHLCtCQUFPLEtBQUtELGNBQUwsR0FBc0IsQ0FQVixFQU9hO0FBQ2hDRyw2QkFBTyxLQUFLRCxZQUFMLEdBQW9CO0FBUlIscUJBQXZCOztBQVdBO0FBQ0Esd0JBQUksS0FBS25MLFlBQUwsQ0FBa0IwSyxNQUFsQixHQUEyQixDQUEvQixFQUFrQztBQUM5Qiw2QkFBSzFLLFlBQUwsQ0FBa0IsS0FBS0MsaUJBQUwsR0FBeUIsQ0FBM0MsRUFBOENpTCxLQUE5QyxHQUFzRCxLQUFLRCxjQUEzRDtBQUNBLDZCQUFLakwsWUFBTCxDQUFrQixLQUFLQyxpQkFBTCxHQUF5QixDQUEzQyxFQUE4Q21MLEdBQTlDLEdBQW9ELEtBQUtELFlBQXpEO0FBQ0g7QUFDSjs7QUFFRDtBQUNBLG9CQUFJLEtBQUtuTCxZQUFMLENBQWtCMEssTUFBbEIsR0FBMkIsS0FBS3BLLFFBQUwsQ0FBY2tHLFdBQTdDLEVBQTBEO0FBQ3RELHlCQUFLNkUsbUJBQUw7QUFDSDtBQUNKO0FBQ0o7O0FBRUQ7Ozs7QUFJQTs7Ozs7Ozs7Ozs7Ozs7O0FBZUE7Ozs7Ozs7Ozs7a0RBT3FDO0FBQUEsZ0JBQWJDLElBQWEsdUVBQU4sSUFBTTs7QUFDakMsZ0JBQUlDLGNBQUo7QUFDQSxnQkFBSUQsSUFBSixFQUFVO0FBQ047QUFDQUMsd0JBQVEsS0FBS3RMLGlCQUFMLEdBQXlCLENBQWpDO0FBQ0Esb0JBQUlzTCxLQUFKLEVBQVc7QUFDUCx5QkFBS3RMLGlCQUFMO0FBQ0g7QUFDSixhQU5ELE1BTU87QUFDSDtBQUNBc0wsd0JBQVEsS0FBS3RMLGlCQUFMLEdBQXlCLENBQXpCLEdBQTZCLEtBQUtELFlBQUwsQ0FBa0IwSyxNQUF2RDtBQUNBLG9CQUFJYSxLQUFKLEVBQVc7QUFDUCx5QkFBS3RMLGlCQUFMO0FBQ0g7QUFDSjs7QUFFRCxnQkFBSXNMLEtBQUosRUFBVztBQUNQO0FBQ0Esb0JBQU1DLFdBQVcsS0FBS3hMLFlBQUwsQ0FBa0IsS0FBS0MsaUJBQXZCLENBQWpCO0FBQ0EscUJBQUsyQixHQUFMLENBQVM0SixTQUFTckosS0FBbEIsRUFBeUIsSUFBekIsRUFBK0IsS0FBL0IsRUFITyxDQUdnQzs7QUFFdkM7QUFDQSw0Q0FBa0JzSixtQkFBbEIsQ0FBc0MsS0FBS2hNLFVBQTNDLEVBQXVEK0wsU0FBU04sS0FBaEUsRUFBdUVNLFNBQVNKLEdBQWhGO0FBQ0g7QUFDSjs7QUFFRDs7Ozs7Ozs7OzRDQU1vQjtBQUNoQixpQkFBS00sdUJBQUwsQ0FBNkIsSUFBN0I7QUFDSDs7QUFFRDs7Ozs7Ozs7NENBS29CO0FBQ2hCLGlCQUFLQSx1QkFBTCxDQUE2QixLQUE3QjtBQUNIOztBQUVEOzs7O0FBSUE7Ozs7Ozs7Ozs7Ozs7OztBQWVBOzs7Ozs7Ozs7Ozs4Q0FRaUQ7QUFBQSxnQkFBN0JDLHVCQUE2Qix1RUFBSCxDQUFHOztBQUM3QyxnQkFBTUMsY0FBYyxFQUFwQjtBQUNBLGlCQUFLLElBQUlDLElBQUksQ0FBYixFQUFnQkEsSUFBSUYsdUJBQXBCLEVBQTZDRSxHQUE3QyxFQUFrRDtBQUM5Q0QsNEJBQVlySixJQUFaLENBQWlCLEtBQUt2QyxZQUFMLENBQWtCOEwsS0FBbEIsRUFBakI7QUFDQTtBQUNBLHFCQUFLN0wsaUJBQUw7QUFDQSxvQkFBSSxLQUFLQSxpQkFBTCxHQUF5QixDQUE3QixFQUFnQztBQUM1QjtBQUNBLHlCQUFLQSxpQkFBTCxHQUF5QixDQUF6QjtBQUNIO0FBQ0o7O0FBRUQsZ0JBQUkyTCxZQUFZbEIsTUFBWixLQUF1QixDQUEzQixFQUE4QjtBQUMxQix1QkFBT2tCLFlBQVksQ0FBWixDQUFQO0FBQ0g7O0FBRUQsbUJBQU9BLFdBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7O3dEQU1nQztBQUM1QixnQkFBSUcsYUFBYSxLQUFLOUwsaUJBQXRCO0FBQ0EsZ0JBQUk4TCxhQUFhLENBQWpCLEVBQW9CO0FBQ2hCQSw2QkFBYSxDQUFiO0FBQ0g7O0FBRUQsZ0JBQUl6SixlQUFKO0FBQ0EsZ0JBQUksNEJBQWtCMEosd0JBQWxCLENBQTJDLEtBQUtoTSxZQUFMLENBQWtCK0wsVUFBbEIsQ0FBM0MsQ0FBSixFQUErRTtBQUMzRXpKLHlCQUFTLEVBQVQ7QUFDSCxhQUZELE1BRU87QUFDSEEseUJBQVMsS0FBS3RDLFlBQUwsQ0FBa0IrTCxVQUFsQixFQUE4QjVKLEtBQXZDO0FBQ0g7O0FBRUQsbUJBQU9HLE1BQVA7QUFDSDs7QUFFRDs7Ozs7OzsyQ0FJbUI7QUFBQTs7QUFDZixnQkFBSSw0QkFBa0IwSix3QkFBbEIsQ0FBMkMsS0FBSzFMLFFBQUwsQ0FBYzBILFVBQXpELEtBQXdFLEtBQUs5QyxRQUFMLEtBQWtCLEVBQTlGLEVBQWtHO0FBQzlGO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBSSxDQUFDLDRCQUFrQjhHLHdCQUFsQixDQUEyQyxLQUFLMUwsUUFBTCxDQUFjMEgsVUFBZCxDQUF5QmlFLFFBQXBFLENBQUwsRUFBb0Y7QUFDaEYsb0JBQUksS0FBSy9HLFFBQUwsSUFBaUIsQ0FBckIsRUFBd0I7QUFDcEIseUJBQUtnSCxZQUFMLENBQWtCLEtBQUs1TCxRQUFMLENBQWMwSCxVQUFkLENBQXlCaUUsUUFBM0M7QUFDSCxpQkFGRCxNQUVPO0FBQ0gseUJBQUtFLGVBQUwsQ0FBcUIsS0FBSzdMLFFBQUwsQ0FBYzBILFVBQWQsQ0FBeUJpRSxRQUE5QztBQUNIO0FBQ0o7O0FBRUQ7QUFDQSxnQkFBSSxDQUFDLDRCQUFrQkQsd0JBQWxCLENBQTJDLEtBQUsxTCxRQUFMLENBQWMwSCxVQUFkLENBQXlCb0UsUUFBcEUsQ0FBTCxFQUFvRjtBQUNoRixvQkFBSSxLQUFLbEgsUUFBTCxHQUFnQixDQUFwQixFQUF1QjtBQUNuQix5QkFBS2dILFlBQUwsQ0FBa0IsS0FBSzVMLFFBQUwsQ0FBYzBILFVBQWQsQ0FBeUJvRSxRQUEzQztBQUNILGlCQUZELE1BRU87QUFDSCx5QkFBS0QsZUFBTCxDQUFxQixLQUFLN0wsUUFBTCxDQUFjMEgsVUFBZCxDQUF5Qm9FLFFBQTlDO0FBQ0g7QUFDSjs7QUFFRDtBQUNBLGdCQUFJLENBQUMsNEJBQWtCSix3QkFBbEIsQ0FBMkMsS0FBSzFMLFFBQUwsQ0FBYzBILFVBQWQsQ0FBeUJxRSxNQUFwRSxDQUFELElBQWdGLEtBQUsvTCxRQUFMLENBQWMwSCxVQUFkLENBQXlCcUUsTUFBekIsQ0FBZ0MzQixNQUFoQyxLQUEyQyxDQUEvSCxFQUFrSTtBQUM5SCxxQkFBS3BLLFFBQUwsQ0FBYzBILFVBQWQsQ0FBeUJxRSxNQUF6QixDQUFnQ3JLLE9BQWhDLENBQXdDLGlCQUFTO0FBQzdDLHdCQUFJLE9BQUtrRCxRQUFMLElBQWlCb0gsTUFBTUMsR0FBdkIsSUFBOEIsT0FBS3JILFFBQUwsR0FBZ0JvSCxNQUFNRSxHQUF4RCxFQUE2RDtBQUN6RCwrQkFBS04sWUFBTCxDQUFrQkksTUFBTUcsS0FBeEI7QUFDSCxxQkFGRCxNQUVPO0FBQ0gsK0JBQUtOLGVBQUwsQ0FBcUJHLE1BQU1HLEtBQTNCO0FBQ0g7QUFDSixpQkFORDtBQU9IOztBQUVEO0FBQ0E7QUFDQSxnQkFBSSxDQUFDLDRCQUFrQlQsd0JBQWxCLENBQTJDLEtBQUsxTCxRQUFMLENBQWMwSCxVQUFkLENBQXlCMEUsV0FBcEUsQ0FBRCxJQUFxRixLQUFLcE0sUUFBTCxDQUFjMEgsVUFBZCxDQUF5QjBFLFdBQXpCLENBQXFDaEMsTUFBckMsS0FBZ0QsQ0FBekksRUFBNEk7QUFDeEkscUJBQUtwSyxRQUFMLENBQWMwSCxVQUFkLENBQXlCMEUsV0FBekIsQ0FBcUMxSyxPQUFyQyxDQUE2QyxzQkFBYztBQUN2RCx3QkFBSSw0QkFBa0IySyxVQUFsQixDQUE2QkMsV0FBV3ZLLFFBQXhDLENBQUosRUFBdUQ7QUFDbkQ7QUFDQSw0QkFBSSw0QkFBa0J3SyxRQUFsQixDQUEyQkQsV0FBV0UsT0FBdEMsQ0FBSixFQUFvRDtBQUNoRDtBQUNBLGdDQUFJRixXQUFXdkssUUFBWCxDQUFvQixPQUFLNkMsUUFBekIsQ0FBSixFQUF3QztBQUNwQyx1Q0FBS2dILFlBQUwsQ0FBa0JVLFdBQVdFLE9BQTdCO0FBQ0gsNkJBRkQsTUFFTztBQUNILHVDQUFLWCxlQUFMLENBQXFCUyxXQUFXRSxPQUFoQztBQUNIO0FBQ0oseUJBUEQsTUFPTyxJQUFJLDRCQUFrQkMsT0FBbEIsQ0FBMEJILFdBQVdFLE9BQXJDLENBQUosRUFBbUQ7QUFDdEQsZ0NBQUlGLFdBQVdFLE9BQVgsQ0FBbUJwQyxNQUFuQixLQUE4QixDQUFsQyxFQUFxQztBQUNqQztBQUNBLG9DQUFJa0MsV0FBV3ZLLFFBQVgsQ0FBb0IsT0FBSzZDLFFBQXpCLENBQUosRUFBd0M7QUFDcEMsMkNBQUtnSCxZQUFMLENBQWtCVSxXQUFXRSxPQUFYLENBQW1CLENBQW5CLENBQWxCO0FBQ0EsMkNBQUtYLGVBQUwsQ0FBcUJTLFdBQVdFLE9BQVgsQ0FBbUIsQ0FBbkIsQ0FBckI7QUFDSCxpQ0FIRCxNQUdPO0FBQ0gsMkNBQUtYLGVBQUwsQ0FBcUJTLFdBQVdFLE9BQVgsQ0FBbUIsQ0FBbkIsQ0FBckI7QUFDQSwyQ0FBS1osWUFBTCxDQUFrQlUsV0FBV0UsT0FBWCxDQUFtQixDQUFuQixDQUFsQjtBQUNIO0FBQ0osNkJBVEQsTUFTTyxJQUFJRixXQUFXRSxPQUFYLENBQW1CcEMsTUFBbkIsR0FBNEIsQ0FBaEMsRUFBbUM7QUFDdEM7QUFDQSxvQ0FBTXNDLGlCQUFpQkosV0FBV3ZLLFFBQVgsQ0FBb0IsT0FBSzZDLFFBQXpCLENBQXZCO0FBQ0Esb0NBQUksNEJBQWtCNkgsT0FBbEIsQ0FBMEJDLGNBQTFCLENBQUosRUFBK0M7QUFDM0M7QUFDQUosK0NBQVdFLE9BQVgsQ0FBbUI5SyxPQUFuQixDQUEyQixVQUFDaUwsU0FBRCxFQUFZQyxLQUFaLEVBQXNCO0FBQzdDLDRDQUFJLDRCQUFrQkMsU0FBbEIsQ0FBNEJELEtBQTVCLEVBQW1DRixjQUFuQyxDQUFKLEVBQXdEO0FBQ3BELG1EQUFLZCxZQUFMLENBQWtCZSxTQUFsQjtBQUNILHlDQUZELE1BRU87QUFDSCxtREFBS2QsZUFBTCxDQUFxQmMsU0FBckI7QUFDSDtBQUNKLHFDQU5EO0FBT0gsaUNBVEQsTUFTTyxJQUFJLDRCQUFrQkcsS0FBbEIsQ0FBd0JKLGNBQXhCLENBQUosRUFBNkM7QUFDaEQ7QUFDQUosK0NBQVdFLE9BQVgsQ0FBbUI5SyxPQUFuQixDQUEyQixVQUFDaUwsU0FBRCxFQUFZQyxLQUFaLEVBQXNCO0FBQzdDLDRDQUFJQSxVQUFVRixjQUFkLEVBQThCO0FBQzFCLG1EQUFLZCxZQUFMLENBQWtCZSxTQUFsQjtBQUNILHlDQUZELE1BRU87QUFDSCxtREFBS2QsZUFBTCxDQUFxQmMsU0FBckI7QUFDSDtBQUNKLHFDQU5EO0FBT0gsaUNBVE0sTUFTQSxJQUFJLDRCQUFrQjFFLE1BQWxCLENBQXlCeUUsY0FBekIsQ0FBSixFQUE4QztBQUNqRDtBQUNBSiwrQ0FBV0UsT0FBWCxDQUFtQjlLLE9BQW5CLENBQTJCLHFCQUFhO0FBQ3BDLCtDQUFLbUssZUFBTCxDQUFxQmMsU0FBckI7QUFDSCxxQ0FGRDtBQUdILGlDQUxNLE1BS0E7QUFDSCxnRUFBa0JJLFVBQWxCLDJFQUFvR0wsY0FBcEcseUNBQW9HQSxjQUFwRztBQUNIO0FBQ0osNkJBN0JNLE1BNkJBO0FBQ0gsNERBQWtCSyxVQUFsQixDQUE2QixpRUFBN0I7QUFDSDtBQUNKLHlCQTFDTSxNQTBDQSxJQUFJLDRCQUFrQnJCLHdCQUFsQixDQUEyQ1ksV0FBV0UsT0FBdEQsQ0FBSixFQUFvRTtBQUN2RTtBQUNBRix1Q0FBV3ZLLFFBQVg7QUFDSCx5QkFITSxNQUdBO0FBQ0gsd0RBQWtCZ0wsVUFBbEIsQ0FBNkIsMEVBQTdCO0FBQ0g7QUFDSixxQkF6REQsTUF5RE87QUFDSCxvREFBa0J6SCxPQUFsQixpRUFBeUZ2RCxRQUF6Rix5Q0FBeUZBLFFBQXpGLGdCQUE0RyxPQUFLL0IsUUFBTCxDQUFjdUYsWUFBMUg7QUFDSDtBQUNKLGlCQTdERDtBQThESDtBQUNKOztBQUVEOzs7Ozs7Ozs7cUNBTWF5SCxZLEVBQWM7QUFDdkIsaUJBQUs3TixVQUFMLENBQWdCOE4sU0FBaEIsQ0FBMEJDLEdBQTFCLENBQThCRixZQUE5QjtBQUNIOztBQUVEOzs7Ozs7Ozs7d0NBTWdCQSxZLEVBQWM7QUFDMUIsaUJBQUs3TixVQUFMLENBQWdCOE4sU0FBaEIsQ0FBMEJoSyxNQUExQixDQUFpQytKLFlBQWpDO0FBQ0g7O0FBRUQ7O0FBRUE7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztpQ0FrQnNCO0FBQ2xCO0FBQ0EsZ0JBQU1HLG1CQUFtQiw0QkFBa0JDLFdBQWxCLENBQThCLEtBQUtwTixRQUFuQyxDQUF6QixDQUZrQixDQUVxRDs7QUFFdkU7QUFDQSxnQkFBTXFOLGdCQUFnQixLQUFLekksUUFBM0I7O0FBRUE7QUFDQSxnQkFBSTBJLGVBQWUsRUFBbkI7O0FBUmtCLCtDQUFaMUssVUFBWTtBQUFaQSwwQkFBWTtBQUFBOztBQVNsQixnQkFBSSw0QkFBa0I4SSx3QkFBbEIsQ0FBMkM5SSxVQUEzQyxLQUEwREEsV0FBV3dILE1BQVgsS0FBc0IsQ0FBcEYsRUFBdUY7QUFDbkZrRCwrQkFBZSxJQUFmO0FBQ0gsYUFGRCxNQUVPLElBQUkxSyxXQUFXd0gsTUFBWCxJQUFxQixDQUF6QixFQUE0QjtBQUMvQnhILDJCQUFXbEIsT0FBWCxDQUFtQix3QkFBZ0I7QUFDL0IsNkJBQWM0TCxZQUFkLEVBQTRCQyxZQUE1QjtBQUNILGlCQUZEO0FBR0g7O0FBRUQ7QUFDQSxnQkFBSTtBQUNBLHFCQUFLaE8sWUFBTCxDQUFrQitOLFlBQWxCLEVBQWdDLElBQWhDOztBQUVBO0FBQ0E7QUFDQSxxQkFBS2hNLEdBQUwsQ0FBUytMLGFBQVQ7QUFDSCxhQU5ELENBTUUsT0FBT0csS0FBUCxFQUFjO0FBQ1o7QUFDQSxxQkFBS2pPLFlBQUwsQ0FBa0I0TixnQkFBbEIsRUFBb0MsSUFBcEMsRUFGWSxDQUUrQjtBQUMzQyw0Q0FBa0JKLFVBQWxCLHlEQUFtRlMsS0FBbkY7O0FBRUEsdUJBQU8sSUFBUDtBQUNIOztBQUVELG1CQUFPLElBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7OztzQ0FVYztBQUNWLG1CQUFPLEtBQUt4TixRQUFaO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7NEJBZ0JJdUIsUSxFQUFzRDtBQUFBLGdCQUE1Q0MsT0FBNEMsdUVBQWxDLElBQWtDO0FBQUEsZ0JBQTVCaU0sbUJBQTRCLHVFQUFOLElBQU07O0FBQ3REO0FBQ0EsZ0JBQUksNEJBQWtCQyxXQUFsQixDQUE4Qm5NLFFBQTlCLENBQUosRUFBNkM7QUFDekMsNENBQWtCK0QsT0FBbEIsaUZBQXdHLEtBQUt0RixRQUFMLENBQWN1RixZQUF0SDtBQUNBLHVCQUFPLElBQVA7QUFDSDs7QUFFRDtBQUNBLGdCQUFJLENBQUMsNEJBQWtCMEMsTUFBbEIsQ0FBeUJ6RyxPQUF6QixDQUFMLEVBQXdDO0FBQ3BDLHFCQUFLakMsWUFBTCxDQUFrQmlDLE9BQWxCLEVBQTJCLElBQTNCLEVBRG9DLENBQ0Y7QUFDckM7O0FBRUQsZ0JBQUlELGFBQWEsSUFBYixJQUFxQixLQUFLdkIsUUFBTCxDQUFjK0Ysa0JBQWQsS0FBcUNqSCxZQUFZMEMsT0FBWixDQUFvQnVFLGtCQUFwQixDQUF1Q0MsSUFBckcsRUFBMkc7QUFDdkcsNENBQWtCVixPQUFsQiw2RkFBd0gsS0FBS3RGLFFBQUwsQ0FBYytGLGtCQUF0SSw0SEFBaVIsS0FBSy9GLFFBQUwsQ0FBY3VGLFlBQS9SO0FBQ0EsdUJBQU8sSUFBUDtBQUNIOztBQUVELGdCQUFJMUQsY0FBSjtBQUNBLGdCQUFJTixhQUFhLElBQWpCLEVBQXVCO0FBQ25CO0FBQ0E7QUFDQSxxQkFBS29NLHNCQUFMLENBQTRCLElBQTVCLEVBQWtDLElBQWxDLEVBQXdDRixtQkFBeEM7QUFDQSxxQkFBS0csNkJBQUw7O0FBRUEsdUJBQU8sSUFBUDtBQUNIOztBQUVEL0wsb0JBQVEsS0FBS25CLFdBQUwsQ0FBaUJtTixlQUFqQixDQUFpQ3RNLFFBQWpDLEVBQTJDLEtBQUt2QixRQUFoRCxDQUFSO0FBQ0EsZ0JBQUk4TixNQUFNQyxPQUFPbE0sS0FBUCxDQUFOLENBQUosRUFBMEI7QUFDdEI7QUFDQSw0Q0FBa0J5RCxPQUFsQiw0R0FBdUksS0FBS3RGLFFBQUwsQ0FBY3VGLFlBQXJKO0FBQ0EscUJBQUt5SSxRQUFMLENBQWMsRUFBZCxFQUFrQlAsbUJBQWxCOztBQUVBLHVCQUFPLElBQVA7QUFDSDs7QUFFRCxnQkFBSTVMLFVBQVUsRUFBVixJQUFnQixLQUFLN0IsUUFBTCxDQUFjK0Ysa0JBQWQsS0FBcUNqSCxZQUFZMEMsT0FBWixDQUFvQnVFLGtCQUFwQixDQUF1Q2tJLElBQWhHLEVBQXNHO0FBQ2xHO0FBQ0FwTSx3QkFBUSxDQUFSO0FBQ0g7O0FBRUQsZ0JBQUlBLFVBQVUsRUFBZCxFQUFrQjtBQUFBLDRDQUNhLEtBQUtuQixXQUFMLENBQWlCd04saUNBQWpCLENBQW1Eck0sS0FBbkQsRUFBMEQsS0FBSzdCLFFBQS9ELENBRGI7QUFBQTtBQUFBLG9CQUNQbU8sT0FETztBQUFBLG9CQUNFQyxPQURGO0FBRWQ7OztBQUNBLG9CQUFNQyxTQUFTLDRCQUFrQkMsa0JBQWxCLENBQXFDek0sS0FBckMsQ0FBZjtBQUNBLG9CQUFJd00sTUFBSixFQUFZO0FBQ1J4TSw0QkFBUSxHQUFSO0FBQ0g7O0FBRUQsb0JBQUlzTSxXQUFXQyxPQUFmLEVBQXdCO0FBQ3BCLHdCQUFJRyxpQkFBaUIsS0FBSzdOLFdBQUwsQ0FBaUI4TixjQUFqQixDQUFnQzNNLEtBQWhDLEVBQXVDLEtBQUs3QixRQUE1QyxDQUFyQjtBQUNBdU8scUNBQWlCLEtBQUtFLDRCQUFMLENBQWtDRixlQUFlRyxPQUFmLENBQXVCLEtBQUsxTyxRQUFMLENBQWNtRixnQkFBckMsRUFBdUQsR0FBdkQsQ0FBbEMsQ0FBakIsQ0FGb0IsQ0FFNkY7QUFDakh0RCw0QkFBUSxLQUFLOE0sb0JBQUwsQ0FBMEI5TSxLQUExQixDQUFSLENBSG9CLENBR3NCOztBQUUxQztBQUNBLHdCQUFJLEtBQUtmLFNBQVQsRUFBb0I7QUFDaEJlLGdDQUFRLEtBQUtuQixXQUFMLENBQWlCa08sZ0NBQWpCLENBQWtEL00sS0FBbEQsRUFBeUQsS0FBSzdCLFFBQTlELENBQVI7QUFDSCxxQkFGRCxNQUVPO0FBQ0gsNEJBQUksS0FBS0EsUUFBTCxDQUFjOEYsb0JBQWxCLEVBQXdDO0FBQ3BDakUsb0NBQVFBLFFBQVEsS0FBSzdCLFFBQUwsQ0FBYzhGLG9CQUE5QjtBQUNBakUsb0NBQVFBLE1BQU1nTixRQUFOLEVBQVI7QUFDSDs7QUFFRGhOLGdDQUFRLEtBQUtuQixXQUFMLENBQWlCb08sK0JBQWpCLENBQWlEak4sS0FBakQsRUFBd0QsS0FBSzdCLFFBQTdELENBQVI7QUFDSDs7QUFFRDZCLDRCQUFRLEtBQUtuQixXQUFMLENBQWlCcU8sdURBQWpCLENBQXlFbE4sS0FBekUsRUFBZ0YsS0FBSzdCLFFBQXJGLENBQVI7QUFDQTZCLDRCQUFRLEtBQUtuQixXQUFMLENBQWlCc08sbUJBQWpCLENBQXFDbk4sS0FBckMsRUFBNEMsS0FBSzdCLFFBQWpELEVBQTJELEtBQUtjLFNBQWhFLEVBQTJFLEtBQUs4RCxRQUFoRixFQUEwRjJKLGNBQTFGLENBQVI7QUFDQSx3QkFBSSxDQUFDLEtBQUt6TixTQUFOLElBQW1CLEtBQUtkLFFBQUwsQ0FBY29ILG1CQUFyQyxFQUEwRDtBQUN0RHZGLHFDQUFXQSxLQUFYLEdBQW1CLEtBQUs3QixRQUFMLENBQWNvSCxtQkFBakM7QUFDSDs7QUFFRCx3QkFBSSxLQUFLcEgsUUFBTCxDQUFjMEYseUJBQWQsSUFBMkMsS0FBSzFGLFFBQUwsQ0FBYzhGLG9CQUE3RCxFQUFtRjtBQUMvRSw2QkFBSzhILDZCQUFMO0FBQ0g7O0FBRUQseUJBQUtELHNCQUFMLENBQTRCOUwsS0FBNUIsRUFBbUMwTSxjQUFuQyxFQUFtRGQsbUJBQW5EOztBQUVBLDJCQUFPLElBQVA7QUFDSCxpQkE5QkQsTUE4Qk87QUFDSCx3QkFBSSxDQUFDVSxPQUFMLEVBQWM7QUFDVixvREFBa0JjLFlBQWxCLENBQStCblEsWUFBWW9RLE1BQVosQ0FBbUJDLGdCQUFsRCxFQUFvRSxLQUFLaFEsVUFBekU7QUFDSDs7QUFFRCx3QkFBSSxDQUFDaVAsT0FBTCxFQUFjO0FBQ1Ysb0RBQWtCYSxZQUFsQixDQUErQm5RLFlBQVlvUSxNQUFaLENBQW1CRSxnQkFBbEQsRUFBb0UsS0FBS2pRLFVBQXpFO0FBQ0g7O0FBRUQsZ0RBQWtCNE4sVUFBbEIsaUJBQTJDbEwsS0FBM0MsdURBQWtHLEtBQUs3QixRQUFMLENBQWNzRyxZQUFoSCw0QkFBbUosS0FBS3RHLFFBQUwsQ0FBY3FHLFlBQWpLOztBQUVBLHlCQUFLZ0osaUNBQUw7QUFDQSx5QkFBS3JCLFFBQUwsQ0FBYyxFQUFkLEVBQWtCUCxtQkFBbEIsRUFaRyxDQVlxQzs7QUFFeEMsMkJBQU8sSUFBUDtBQUNIO0FBQ0osYUF0REQsTUFzRE87QUFDSDtBQUNBLG9CQUFJekwsZUFBSjtBQUNBLG9CQUFJLEtBQUtoQyxRQUFMLENBQWMrRixrQkFBZCxLQUFxQ2pILFlBQVkwQyxPQUFaLENBQW9CdUUsa0JBQXBCLENBQXVDdUosTUFBaEYsRUFBd0Y7QUFDcEY7QUFDQXROLDZCQUFTLEtBQUtoQyxRQUFMLENBQWNpRixjQUF2QjtBQUNILGlCQUhELE1BR087QUFDSGpELDZCQUFTLEVBQVQ7QUFDSDs7QUFFRCxxQkFBSzJMLHNCQUFMLENBQTRCM0wsTUFBNUIsRUFBb0MsRUFBcEMsRUFBd0N5TCxtQkFBeEM7O0FBRUEsdUJBQU8sSUFBUDtBQUNIO0FBQ0o7O0FBRUQ7Ozs7Ozs7Ozs7Ozt1Q0FTZTVMLEssRUFBdUI7QUFBQSxnQkFBaEJMLE9BQWdCLHVFQUFOLElBQU07O0FBQ2xDO0FBQ0EsZ0JBQUlLLFVBQVUsSUFBVixJQUFrQiw0QkFBa0I2TCxXQUFsQixDQUE4QjdMLEtBQTlCLENBQXRCLEVBQTREO0FBQ3hELHVCQUFPLElBQVA7QUFDSDs7QUFFRDtBQUNBLGdCQUFJLENBQUMsNEJBQWtCb0csTUFBbEIsQ0FBeUJ6RyxPQUF6QixDQUFMLEVBQXdDO0FBQ3BDLHFCQUFLakMsWUFBTCxDQUFrQmlDLE9BQWxCLEVBQTJCLElBQTNCLEVBRG9DLENBQ0Y7QUFDckM7O0FBRUQsZ0JBQU0rTixnQkFBZ0IsS0FBSzdPLFdBQUwsQ0FBaUI4TyxlQUFqQixDQUFpQzNOLEtBQWpDLEVBQXdDLEtBQUs3QixRQUE3QyxDQUF0QjtBQUNBLGdCQUFJeVAsa0JBQWtCLEtBQUsvTyxXQUFMLENBQWlCZ1AsNEJBQWpCLENBQThDSCxhQUE5QyxFQUE2RCxLQUFLdlAsUUFBbEUsRUFBNEUsSUFBNUUsRUFBa0YsS0FBS2MsU0FBdkYsQ0FBdEI7QUFDQTJPLDhCQUFrQkEsZ0JBQWdCZixPQUFoQixDQUF3QixLQUFLMU8sUUFBTCxDQUFjbUYsZ0JBQXRDLEVBQXdELEdBQXhELENBQWxCO0FBQ0EsZ0JBQUksQ0FBQyw0QkFBa0J3SyxRQUFsQixDQUEyQkYsZUFBM0IsQ0FBTCxFQUFrRDtBQUM5Qyw0Q0FBa0IxQyxVQUFsQjtBQUNIOztBQWhCaUMseUNBa0JQLEtBQUtyTSxXQUFMLENBQWlCd04saUNBQWpCLENBQW1EdUIsZUFBbkQsRUFBb0UsS0FBS3pQLFFBQXpFLENBbEJPO0FBQUE7QUFBQSxnQkFrQjNCbU8sT0FsQjJCO0FBQUEsZ0JBa0JsQkMsT0FsQmtCOztBQW1CbEMsZ0JBQUlELFdBQVdDLE9BQWYsRUFBd0I7QUFDcEI7QUFDQSxxQkFBS0osUUFBTCxDQUFjbk0sS0FBZDtBQUNILGFBSEQsTUFHTztBQUNILDRDQUFrQmtMLFVBQWxCLDRDQUFzRSxLQUFLL00sUUFBTCxDQUFjc0csWUFBcEYsVUFBcUcsS0FBS3RHLFFBQUwsQ0FBY3FHLFlBQW5IO0FBQ0g7O0FBRUQsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7OztpQ0FRUzlFLFEsRUFBc0M7QUFBQSxnQkFBNUJrTSxtQkFBNEIsdUVBQU4sSUFBTTs7QUFDM0MsaUJBQUtFLHNCQUFMLENBQTRCcE0sUUFBNUIsRUFBc0NrTSxtQkFBdEM7O0FBRUEsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7O3FDQU9hN0ksUSxFQUFzQztBQUFBLGdCQUE1QjZJLG1CQUE0Qix1RUFBTixJQUFNOztBQUMvQztBQUNBLGdCQUFJLEtBQUs3SSxRQUFMLEtBQWtCQSxRQUF0QixFQUFnQztBQUFFO0FBQzlCO0FBQ0EscUJBQUtBLFFBQUwsR0FBZ0JBLFFBQWhCLENBRjRCLENBRUY7O0FBRTFCLG9CQUFLLENBQUMsNEJBQWtCcUQsTUFBbEIsQ0FBeUIsS0FBS2pJLFFBQUwsQ0FBY2dILGVBQXZDLENBQUQsSUFBNEQsS0FBS2hILFFBQUwsQ0FBY2dILGVBQWQsS0FBa0MsQ0FBL0YsSUFBcUc7QUFDckdwQyw2QkFBYSxFQURiLElBQ21CQSxhQUFhLElBRGhDLElBQ3dDO0FBQ3hDLHFCQUFLZ0wsOEJBQUwsRUFGSixFQUUyQztBQUFFO0FBQ3pDLHlCQUFLaEwsUUFBTCxJQUFpQixLQUFLNUUsUUFBTCxDQUFjZ0gsZUFBL0I7QUFDSDs7QUFFRDtBQUNBLHFCQUFLNkksZ0JBQUw7O0FBRUEsb0JBQUlwQyxtQkFBSixFQUF5QjtBQUNyQjtBQUNBLHlCQUFLcUMsZ0JBQUw7QUFDSDtBQUNKO0FBQ0o7O0FBRUQ7Ozs7Ozs7Ozs7O3lDQVFpQkMsZSxFQUFpQjtBQUM5QjtBQUNBO0FBQ0EsZ0JBQU1DLGtCQUFrQiw0QkFBa0JDLGVBQWxCLENBQWtDLEtBQUs5USxVQUF2QyxDQUF4Qjs7QUFFQSxnQkFBSTRRLG9CQUFvQkMsZUFBeEIsRUFBeUM7QUFDckM7QUFDQSw0Q0FBa0JFLGVBQWxCLENBQWtDLEtBQUsvUSxVQUF2QyxFQUFtRDRRLGVBQW5EO0FBQ0EsNENBQWtCZCxZQUFsQixDQUErQm5RLFlBQVlvUSxNQUFaLENBQW1CaUIsU0FBbEQsRUFBNkQsS0FBS2hSLFVBQWxFLEVBQThFLEVBQUVpUixVQUFVSixlQUFaLEVBQTZCek8sVUFBVXdPLGVBQXZDLEVBQTlFO0FBQ0g7O0FBRUQsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7K0NBWXVCQSxlLEVBQThEO0FBQUEsZ0JBQTdDbkwsUUFBNkMsdUVBQWxDLElBQWtDO0FBQUEsZ0JBQTVCNkksbUJBQTRCLHVFQUFOLElBQU07O0FBQ2pGLGdCQUFJLDRCQUFrQnhGLE1BQWxCLENBQXlCckQsUUFBekIsQ0FBSixFQUF3QztBQUNwQ0EsMkJBQVdtTCxlQUFYO0FBQ0gsYUFGRCxNQUVPLElBQUksNEJBQWtCTSxTQUFsQixDQUE0QnpMLFFBQTVCLENBQUosRUFBMkM7QUFDOUM2SSxzQ0FBc0I3SSxRQUF0QjtBQUNBQSwyQkFBV21MLGVBQVg7QUFDSDs7QUFFRDtBQUNBO0FBQ0EsaUJBQUtPLGdCQUFMLENBQXNCUCxlQUF0QjtBQUNBLGlCQUFLUSxZQUFMLENBQWtCM0wsUUFBbEIsRUFBNEI2SSxtQkFBNUI7O0FBRUEsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs2Q0FRcUI3SSxRLEVBQVU7QUFDM0IsZ0JBQUk0TCxtQ0FBSjtBQUNBLGdCQUFLLENBQUMsNEJBQWtCdkksTUFBbEIsQ0FBeUIsS0FBS2pJLFFBQUwsQ0FBY2dILGVBQXZDLENBQUQsSUFBNEQsS0FBS2hILFFBQUwsQ0FBY2dILGVBQWQsS0FBa0MsQ0FBL0YsSUFBcUc7QUFDckdwQyx5QkFBYSxFQURiLElBQ21CQSxhQUFhLElBRHBDLEVBQzBDO0FBQUU7QUFDeEM7QUFDQTRMLDZDQUE2QjVMLFdBQVcsS0FBSzVFLFFBQUwsQ0FBY2dILGVBQXREO0FBQ0gsYUFKRCxNQUlPO0FBQ0h3Siw2Q0FBNkI1TCxRQUE3QjtBQUNIOztBQUVELG1CQUFPNEwsMEJBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7O3lEQU1pQztBQUM3QjtBQUNBLG1CQUFRLEtBQUsxUCxTQUFMLElBQWtCLEtBQUtHLFNBQXhCLElBQXNDLEtBQUtELFdBQWxEO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7eUNBT2lCZ0IsTSxFQUFRRCxRLEVBQVU7QUFDL0IsZ0JBQUksQ0FBQyw0QkFBa0JrRyxNQUFsQixDQUF5QmxHLFFBQXpCLENBQUQsSUFBdUMsNEJBQWtCc0ssVUFBbEIsQ0FBNkJ0SyxRQUE3QixDQUEzQyxFQUFtRjtBQUMvRUEseUJBQVNDLE1BQVQsRUFBaUIsSUFBakI7QUFDSDtBQUNKOztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7OEJBZXFCO0FBQUEsZ0JBQWpCRCxRQUFpQix1RUFBTixJQUFNOztBQUNqQixtQkFBTyxLQUFLSSxnQkFBTCxDQUFzQkosUUFBdEIsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7OzJDQVVrQztBQUFBLGdCQUFqQkEsUUFBaUIsdUVBQU4sSUFBTTs7QUFDOUIsZ0JBQUlDLGVBQUo7QUFDQSxnQkFBSSw0QkFBa0JpRyxNQUFsQixDQUF5QixLQUFLckQsUUFBOUIsQ0FBSixFQUE2QztBQUN6QzVDLHlCQUFTLElBQVQ7QUFDSCxhQUZELE1BRU87QUFDSDtBQUNBO0FBQ0FBLHlCQUFTLDRCQUFrQnlPLGdDQUFsQixDQUFtRCxLQUFLN0wsUUFBeEQsQ0FBVDtBQUNIOztBQUVELGlCQUFLMUMsZ0JBQUwsQ0FBc0JGLE1BQXRCLEVBQThCRCxRQUE5Qjs7QUFFQSxtQkFBT0MsTUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7dUNBUzhCO0FBQUEsZ0JBQWpCRCxRQUFpQix1RUFBTixJQUFNOztBQUMxQixnQkFBSSxFQUFFLFdBQVcsS0FBSzVDLFVBQWhCLElBQThCLGlCQUFpQixLQUFLQSxVQUF0RCxDQUFKLEVBQXVFO0FBQ25FO0FBQ0EsNENBQWtCNE4sVUFBbEIsQ0FBNkIsc0RBQTdCO0FBQ0g7O0FBRUQsZ0JBQU0vSyxTQUFTLDRCQUFrQmlPLGVBQWxCLENBQWtDLEtBQUs5USxVQUF2QyxDQUFmO0FBQ0EsaUJBQUsrQyxnQkFBTCxDQUFzQkYsTUFBdEIsRUFBOEJELFFBQTlCOztBQUVBLG1CQUFPQyxNQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7Ozs7b0NBVTJCO0FBQUEsZ0JBQWpCRCxRQUFpQix1RUFBTixJQUFNOztBQUN2QixnQkFBSUMsZUFBSjtBQUNBLGdCQUFJLEtBQUs0QyxRQUFMLEtBQWtCLElBQXRCLEVBQTRCO0FBQ3hCNUMseUJBQVMsSUFBVDtBQUNILGFBRkQsTUFFTztBQUNIQSx5QkFBUyxLQUFLdEIsV0FBTCxDQUFpQmdRLFNBQWpCLENBQTJCLEtBQUt2TyxnQkFBTCxFQUEzQixFQUFvRCxRQUFwRCxDQUFUO0FBQ0g7O0FBRUQsaUJBQUtELGdCQUFMLENBQXNCRixNQUF0QixFQUE4QkQsUUFBOUI7O0FBRUEsbUJBQU9DLE1BQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7O3VDQWV5RDtBQUFBLGdCQUE1Q1Usa0JBQTRDLHVFQUF2QixJQUF1QjtBQUFBLGdCQUFqQlgsUUFBaUIsdUVBQU4sSUFBTTs7QUFDckQ7QUFDQSxnQkFBSSw0QkFBa0JzSyxVQUFsQixDQUE2QjNKLGtCQUE3QixLQUFvRCw0QkFBa0J1RixNQUFsQixDQUF5QmxHLFFBQXpCLENBQXhELEVBQTRGO0FBQ3hGQSwyQkFBV1csa0JBQVg7QUFDQUEscUNBQXFCLElBQXJCO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBSWIsY0FBSjtBQUNBLGdCQUFJLDRCQUFrQjhPLGFBQWxCLENBQWdDLEtBQUsvTCxRQUFyQyxDQUFKLEVBQW9EO0FBQ2hEL0Msd0JBQVEsRUFBUjtBQUNILGFBRkQsTUFFTztBQUNIO0FBQ0E7QUFDQUEsd0JBQVEsS0FBR2tNLE9BQU8sS0FBS25KLFFBQVosQ0FBWDtBQUNIOztBQUVELGdCQUFJL0MsVUFBVSxFQUFWLElBQWdCa00sT0FBT2xNLEtBQVAsTUFBa0IsQ0FBbEMsSUFBdUMsS0FBSzdCLFFBQUwsQ0FBY29HLFdBQWQsS0FBOEJ0SCxZQUFZMEMsT0FBWixDQUFvQjRFLFdBQXBCLENBQWdDd0ssSUFBekcsRUFBK0c7QUFDM0cvTyx3QkFBUSxHQUFSO0FBQ0g7O0FBRUQsZ0JBQUlnUCwwQkFBSjtBQUNBLGdCQUFJLDRCQUFrQjVJLE1BQWxCLENBQXlCdkYsa0JBQXpCLENBQUosRUFBa0Q7QUFDOUNtTyxvQ0FBb0IsS0FBSzdRLFFBQUwsQ0FBYzhHLFlBQWxDO0FBQ0gsYUFGRCxNQUVPO0FBQ0grSixvQ0FBb0JuTyxrQkFBcEI7QUFDSDs7QUFFRCxnQkFBTVYsU0FBUyxLQUFLdEIsV0FBTCxDQUFpQmdRLFNBQWpCLENBQTJCN08sS0FBM0IsRUFBa0NnUCxpQkFBbEMsQ0FBZjtBQUNBLGlCQUFLM08sZ0JBQUwsQ0FBc0JGLE1BQXRCLEVBQThCRCxRQUE5Qjs7QUFFQSxtQkFBT0MsTUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7OzttQ0FRVztBQUNQO0FBQ0EsaUJBQUtWLEdBQUwsQ0FBUyxLQUFLc0QsUUFBZDs7QUFFQSxtQkFBTyxJQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7OzttQ0FTVztBQUNQLGlCQUFLMEwsZ0JBQUwsQ0FBc0IsS0FBS25PLGdCQUFMLEVBQXRCOztBQUVBLG1CQUFPLElBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7OzRDQVM2QztBQUFBLGdCQUEzQk8sa0JBQTJCLHVFQUFOLElBQU07O0FBQ3pDLGlCQUFLNE4sZ0JBQUwsQ0FBc0IsS0FBS2hPLFlBQUwsQ0FBa0JJLGtCQUFsQixDQUF0Qjs7QUFFQSxtQkFBTyxJQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7O3FDQVFxQztBQUFBLGdCQUExQkksaUJBQTBCLHVFQUFOLElBQU07O0FBQ2pDLGdCQUFJZCxlQUFKO0FBQ0EsZ0JBQUljLGlCQUFKLEVBQXVCO0FBQ25CZCx5QkFBUyxLQUFLNUMsWUFBTCxLQUFzQixLQUFLK0MsZ0JBQUwsRUFBL0I7QUFDSCxhQUZELE1BRU87QUFDSEgseUJBQVMsS0FBSytGLHlCQUFMLEtBQW1DLEtBQUszRixZQUFMLEVBQTVDO0FBQ0g7O0FBRUQsbUJBQU9KLE1BQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7aUNBS1M7QUFDTCxnQkFBSSxLQUFLaEMsUUFBTCxDQUFjcUgsZ0JBQWxCLEVBQW9DO0FBQ2hDLHFCQUFLeUosWUFBTDtBQUNILGFBRkQsTUFFTztBQUNILHFCQUFLQyxpQkFBTDtBQUNIOztBQUVELG1CQUFPLElBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs0Q0FJb0I7QUFDaEIsd0NBQWtCNUYsbUJBQWxCLENBQXNDLEtBQUtoTSxVQUEzQyxFQUF1RCxDQUF2RCxFQUEwRCw0QkFBa0I4USxlQUFsQixDQUFrQyxLQUFLOVEsVUFBdkMsRUFBbURpTCxNQUE3RztBQUNIOztBQUVEOzs7Ozs7Ozt1Q0FLZTtBQUNYO0FBQ0EsZ0JBQU00RyxtQkFBbUIsNEJBQWtCZixlQUFsQixDQUFrQyxLQUFLOVEsVUFBdkMsQ0FBekI7QUFDQSxnQkFBTThSLFdBQVdELGlCQUFpQjVHLE1BQWxDO0FBQ0EsZ0JBQU04RyxxQkFBcUIsS0FBS2xSLFFBQUwsQ0FBY2lGLGNBQWQsQ0FBNkJtRixNQUF4RDtBQUNBLGdCQUFNbEYsMEJBQTBCLEtBQUtsRixRQUFMLENBQWNrRix1QkFBOUM7QUFDQSxnQkFBTWlNLFNBQVUsQ0FBQyw0QkFBa0JDLFVBQWxCLENBQTZCSixnQkFBN0IsQ0FBRixHQUFrRCxDQUFsRCxHQUFvRCxDQUFuRTtBQUNBLGdCQUFNSyxnQkFBZ0IsS0FBS3JSLFFBQUwsQ0FBYzJILFVBQWQsQ0FBeUJ5QyxNQUEvQzs7QUFFQSxnQkFBSVEsY0FBSjtBQUNBLGdCQUFJMUYsNEJBQTRCcEcsWUFBWTBDLE9BQVosQ0FBb0IwRCx1QkFBcEIsQ0FBNENvTSxNQUE1RSxFQUFvRjtBQUNoRjFHLHdCQUFRLENBQVI7QUFDSCxhQUZELE1BRU8sSUFBSSxLQUFLNUssUUFBTCxDQUFjeUcsNkJBQWQsS0FBZ0QzSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRDhLLElBQWxHLElBQ1BKLFdBQVcsQ0FESixJQUNTRCxxQkFBcUIsQ0FEbEMsRUFDcUM7QUFDeEN0Ryx3QkFBUXNHLHFCQUFxQixDQUE3QjtBQUNILGFBSE0sTUFHQTtBQUNIdEcsd0JBQVFzRyxrQkFBUjtBQUNIOztBQUVELGdCQUFJcEcsWUFBSjtBQUNBLGdCQUFJNUYsNEJBQTRCcEcsWUFBWTBDLE9BQVosQ0FBb0IwRCx1QkFBcEIsQ0FBNENzTSxNQUE1RSxFQUFvRjtBQUNoRjFHLHNCQUFNbUcsV0FBV0ksYUFBakI7QUFDSCxhQUZELE1BRU87QUFDSCx3QkFBUSxLQUFLclIsUUFBTCxDQUFjeUcsNkJBQXRCO0FBQ0kseUJBQUszSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRDhLLElBQXZEO0FBQ0l6Ryw4QkFBTW1HLFlBQVlJLGdCQUFnQkgsa0JBQTVCLENBQU47QUFDQTtBQUNKLHlCQUFLcFMsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0RnTCxLQUF2RDtBQUNJLDRCQUFJUCxxQkFBcUIsQ0FBekIsRUFBNEI7QUFDeEJwRyxrQ0FBTW1HLFlBQVlDLHFCQUFxQkMsTUFBckIsR0FBOEJFLGFBQTFDLENBQU47QUFDSCx5QkFGRCxNQUVPO0FBQ0h2RyxrQ0FBTW1HLFlBQVlDLHFCQUFxQkcsYUFBakMsQ0FBTjtBQUNIO0FBQ0Q7QUFDSjtBQUNJdkcsOEJBQU1tRyxZQUFZQyxxQkFBcUJHLGFBQWpDLENBQU47QUFaUjtBQWNIOztBQUVELHdDQUFrQmxHLG1CQUFsQixDQUFzQyxLQUFLaE0sVUFBM0MsRUFBdUR5TCxLQUF2RCxFQUE4REUsR0FBOUQ7O0FBRUEsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozt3Q0FLZ0I7QUFDWixnQkFBSUYsUUFBUSxDQUFaO0FBQ0EsZ0JBQU04RyxhQUFhLEtBQUs5TSxRQUFMLElBQWlCLENBQXBDOztBQUVBO0FBQ0EsZ0JBQUksS0FBSzVFLFFBQUwsQ0FBY2tGLHVCQUFkLEtBQTBDcEcsWUFBWTBDLE9BQVosQ0FBb0IwRCx1QkFBcEIsQ0FBNENzTSxNQUF0RixJQUNDLEtBQUt4UixRQUFMLENBQWNrRix1QkFBZCxLQUEwQ3BHLFlBQVkwQyxPQUFaLENBQW9CMEQsdUJBQXBCLENBQTRDb00sTUFBdEYsS0FDQSxLQUFLdFIsUUFBTCxDQUFjeUcsNkJBQWQsS0FBZ0QzSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRCtLLE1BQWxHLElBQ0QsS0FBS3hSLFFBQUwsQ0FBY3lHLDZCQUFkLEtBQWdEM0gsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0RrTCxJQUZqRyxDQURMLEVBRzhHO0FBQzFHLG9CQUFLLEtBQUszUixRQUFMLENBQWN5SCxnQkFBZCxJQUFrQ2lLLFVBQW5DLElBQW1EO0FBQ2xELGlCQUFDQSxVQUFELElBQWUsS0FBSzFSLFFBQUwsQ0FBY2tGLHVCQUFkLEtBQTBDcEcsWUFBWTBDLE9BQVosQ0FBb0IwRCx1QkFBcEIsQ0FBNENzTSxNQUFyRyxJQUErRyxLQUFLeFIsUUFBTCxDQUFjeUcsNkJBQWQsS0FBZ0QzSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRDhLLElBRHROLEVBQzZOO0FBQUU7QUFDM04zRyw0QkFBUUEsUUFBUSxDQUFoQjtBQUNIO0FBQ0o7O0FBRUQ7QUFDQSxnQkFBSSxLQUFLNUssUUFBTCxDQUFja0YsdUJBQWQsS0FBMENwRyxZQUFZMEMsT0FBWixDQUFvQjBELHVCQUFwQixDQUE0Q3NNLE1BQTFGLEVBQWtHO0FBQzlGNUcsd0JBQVFBLFFBQVEsS0FBSzVLLFFBQUwsQ0FBY2lGLGNBQWQsQ0FBNkJtRixNQUE3QztBQUNIOztBQUVEO0FBQ0EsZ0JBQU13SCxlQUFlLDRCQUFrQjNCLGVBQWxCLENBQWtDLEtBQUs5USxVQUF2QyxDQUFyQjtBQUNBLGdCQUFJMkwsTUFBTThHLGFBQWFDLE9BQWIsQ0FBcUIsS0FBSzdSLFFBQUwsQ0FBY21GLGdCQUFuQyxDQUFWO0FBQ0EsZ0JBQUkyRixRQUFRLENBQUMsQ0FBYixFQUFnQjtBQUNaO0FBQ0Esb0JBQUksS0FBSzlLLFFBQUwsQ0FBY2tGLHVCQUFkLEtBQTBDcEcsWUFBWTBDLE9BQVosQ0FBb0IwRCx1QkFBcEIsQ0FBNENvTSxNQUExRixFQUFrRztBQUM5RnhHLDBCQUFNOEcsYUFBYXhILE1BQWIsR0FBc0IsS0FBS3BLLFFBQUwsQ0FBY2lGLGNBQWQsQ0FBNkJtRixNQUF6RDtBQUNILGlCQUZELE1BRU87QUFDSFUsMEJBQU04RyxhQUFheEgsTUFBbkI7QUFDSDs7QUFFRDtBQUNBLG9CQUFJLENBQUNzSCxVQUFELEtBQ0MsS0FBSzFSLFFBQUwsQ0FBY3lHLDZCQUFkLEtBQWdEM0gsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q2SyxNQUFsRyxJQUNELEtBQUt0UixRQUFMLENBQWNrRix1QkFBZCxLQUEwQ3BHLFlBQVkwQyxPQUFaLENBQW9CMEQsdUJBQXBCLENBQTRDb00sTUFGdEYsQ0FBSixFQUVtRztBQUMvRnhHLDBCQUFNQSxNQUFNLENBQVo7QUFDSDs7QUFFRDtBQUNBQSxzQkFBTUEsTUFBTSxLQUFLOUssUUFBTCxDQUFjMkgsVUFBZCxDQUF5QnlDLE1BQXJDO0FBQ0g7O0FBRUQsd0NBQWtCZSxtQkFBbEIsQ0FBc0MsS0FBS2hNLFVBQTNDLEVBQXVEeUwsS0FBdkQsRUFBOERFLEdBQTlEOztBQUVBLG1CQUFPLElBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7O3dDQWVnQjtBQUNaLGdCQUFJRixRQUFRLDRCQUFrQnFGLGVBQWxCLENBQWtDLEtBQUs5USxVQUF2QyxFQUFtRDBTLE9BQW5ELENBQTJELEtBQUs3UixRQUFMLENBQWNtRixnQkFBekUsQ0FBWjtBQUNBLGdCQUFJMkYsWUFBSjs7QUFFQSxnQkFBSUYsVUFBVSxDQUFDLENBQWYsRUFBa0I7QUFDZDtBQUNBQSx3QkFBUSxDQUFSO0FBQ0FFLHNCQUFNLENBQU47QUFDSCxhQUpELE1BSU87QUFDSDtBQUNBRix3QkFBUUEsUUFBUSxDQUFoQixDQUZHLENBRWdCOztBQUVuQixvQkFBSWtILHFCQUFKO0FBQ0Esb0JBQUksS0FBS2hSLFNBQVQsRUFBb0I7QUFDaEJnUixtQ0FBZSxLQUFLOVIsUUFBTCxDQUFjMEYseUJBQTdCO0FBQ0gsaUJBRkQsTUFFTztBQUNIb00sbUNBQWUsS0FBSzlSLFFBQUwsQ0FBY3lGLHdCQUE3QjtBQUNIOztBQUVEcUYsc0JBQU1GLFFBQVFtRCxPQUFPK0QsWUFBUCxDQUFkO0FBQ0g7O0FBRUQsd0NBQWtCM0csbUJBQWxCLENBQXNDLEtBQUtoTSxVQUEzQyxFQUF1RHlMLEtBQXZELEVBQThERSxHQUE5RDs7QUFFQSxtQkFBTyxJQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7OytCQUtPO0FBQ0gsbUJBQU8sS0FBSzNMLFVBQVo7QUFDSDs7QUFFRDs7Ozs7Ozs7aUNBS1M7QUFDTCxtQkFBTyxLQUFLQSxVQUFMLENBQWdCNFMsVUFBdkI7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7aUNBUThCO0FBQUEsZ0JBQXZCQyxjQUF1Qix1RUFBTixJQUFNO0FBQUU7QUFDNUIsZ0JBQUlDLDJCQUFKO0FBQ0EsZ0JBQUksQ0FBQyw0QkFBa0JoSyxNQUFsQixDQUF5QitKLGNBQXpCLENBQUwsRUFBK0M7QUFDM0NDLHFDQUFxQkQsZUFBZTFPLElBQWYsRUFBckI7QUFDSCxhQUZELE1BRU87QUFDSDJPLHFDQUFxQixLQUFLOVMsVUFBMUI7QUFDSDs7QUFFRCxpQkFBSytTLG9CQUFMLENBQTBCRCxrQkFBMUIsRUFSMEIsQ0FRcUI7O0FBRS9DLG1CQUFPLElBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7OytCQVNPRCxjLEVBQWlDO0FBQUEsZ0JBQWpCRyxRQUFpQix1RUFBTixJQUFNO0FBQUU7QUFDdEMsaUJBQUtsTyxlQUFMLENBQXFCK04sZUFBZTFPLElBQWYsRUFBckIsRUFEb0MsQ0FDUztBQUM3QyxnQkFBSTZPLFFBQUosRUFBYztBQUNWSCwrQkFBZXJQLE1BQWYsQ0FBc0IsS0FBSzNDLFFBQTNCO0FBQ0g7O0FBRUQsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7b0NBU1lvUyxjLEVBQXVDO0FBQUEsZ0JBQXZCQyxjQUF1Qix1RUFBTixJQUFNO0FBQUU7QUFDakQsbUJBQU8sS0FBS0Msc0JBQUwsQ0FBNEIsSUFBNUIsRUFBa0NGLGNBQWxDLEVBQWtEQyxjQUFsRCxDQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7O3NDQVNjRSxlLEVBQXdDO0FBQUEsZ0JBQXZCRixjQUF1Qix1RUFBTixJQUFNO0FBQUU7QUFDcEQsbUJBQU8sS0FBS0Msc0JBQUwsQ0FBNEIsS0FBNUIsRUFBbUNDLGVBQW5DLEVBQW9ERixjQUFwRCxDQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7OzsrQ0FldUJHLFksRUFBY0Msc0IsRUFBK0M7QUFBQSxnQkFBdkJKLGNBQXVCLHVFQUFOLElBQU07QUFBRTtBQUNsRjtBQUNBLGdCQUFJSyxzQkFBSjtBQUNBLGdCQUFJLENBQUMsNEJBQWtCekssTUFBbEIsQ0FBeUJvSyxjQUF6QixDQUFMLEVBQStDO0FBQzNDSyxnQ0FBZ0IsS0FBS0Msc0JBQUwsQ0FBNEJOLGNBQTVCLENBQWhCO0FBQ0gsYUFGRCxNQUVPO0FBQ0hLLGdDQUFnQixLQUFLMVMsUUFBckI7QUFDSDs7QUFFRDtBQUNBLGdCQUFJZ0MsZUFBSjtBQUNBLGdCQUFJLDRCQUFrQjRRLFNBQWxCLENBQTRCSCxzQkFBNUIsQ0FBSixFQUF5RDtBQUNyRDtBQUNBLG9CQUFNYixlQUFlLDRCQUFrQjNCLGVBQWxCLENBQWtDd0Msc0JBQWxDLENBQXJCO0FBQ0Esb0JBQUlELFlBQUosRUFBa0I7QUFDZHhRLDZCQUFTbEQsWUFBWStULE1BQVosQ0FBbUJqQixZQUFuQixFQUFpQ2MsYUFBakMsQ0FBVDtBQUNILGlCQUZELE1BR0s7QUFDRDFRLDZCQUFTbEQsWUFBWTBELFFBQVosQ0FBcUJvUCxZQUFyQixFQUFtQ2MsYUFBbkMsQ0FBVDtBQUNIOztBQUVELDRDQUFrQnhDLGVBQWxCLENBQWtDdUMsc0JBQWxDLEVBQTBEelEsTUFBMUQsRUFWcUQsQ0FVYzs7QUFFbkUsdUJBQU8sSUFBUDtBQUNIOztBQUVEO0FBQ0EsZ0JBQUl3USxZQUFKLEVBQWtCO0FBQ2R4USx5QkFBU2xELFlBQVkrVCxNQUFaLENBQW1CSixzQkFBbkIsRUFBMkNDLGFBQTNDLENBQVQ7QUFDSCxhQUZELE1BR0s7QUFDRDFRLHlCQUFTbEQsWUFBWTBELFFBQVosQ0FBcUJpUSxzQkFBckIsRUFBNkNDLGFBQTdDLENBQVQ7QUFDSDs7QUFFRCxtQkFBTzFRLE1BQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7NkJBY0s4USx5QixFQUE0QztBQUFBOztBQUFBLGdCQUFqQkMsUUFBaUIsdUVBQU4sSUFBTTs7QUFDN0MsZ0JBQUlDLGlDQUFpQyxLQUFyQyxDQUQ2QyxDQUNEO0FBQzVDLGdCQUFJQyxtQkFBbUIsRUFBdkI7QUFDQSxnQkFBSSw0QkFBa0IxRyxRQUFsQixDQUEyQnVHLHlCQUEzQixDQUFKLEVBQTJEO0FBQ3ZERyxnRUFBd0JoSixTQUFTaUosZ0JBQVQsQ0FBMEJKLHlCQUExQixDQUF4QixHQUR1RCxDQUN3QjtBQUNsRixhQUZELE1BRU8sSUFBSSw0QkFBa0JGLFNBQWxCLENBQTRCRSx5QkFBNUIsQ0FBSixFQUE0RDtBQUMvREcsaUNBQWlCaFIsSUFBakIsQ0FBc0I2USx5QkFBdEI7QUFDQUUsaURBQWlDLElBQWpDLENBRitELENBRXhCO0FBQzFDLGFBSE0sTUFHQSxJQUFJLDRCQUFrQnZHLE9BQWxCLENBQTBCcUcseUJBQTFCLENBQUosRUFBMEQ7QUFDN0RHLG1DQUFtQkgseUJBQW5CO0FBQ0gsYUFGTSxNQUVBO0FBQ0gsNENBQWtCL0YsVUFBbEI7QUFDSDs7QUFFRCxnQkFBSWtHLGlCQUFpQjdJLE1BQWpCLEtBQTRCLENBQWhDLEVBQW1DO0FBQy9CLDRDQUFrQjlFLE9BQWxCLG9GQUE2RyxJQUE3Rzs7QUFFQSx1QkFBTyxFQUFQO0FBQ0g7O0FBRUQsZ0JBQU02TixtQkFBbUIsS0FBS3ZQLGFBQUwsRUFBekI7QUFDQSxnQkFBTXdQLDBCQUEwQixFQUFoQzs7QUFFQTtBQUNBSCw2QkFBaUJ2UixPQUFqQixDQUF5QixzQkFBYztBQUNuQztBQUNBLG9CQUFNMlIsaUNBQWlDLE9BQUtyVCxRQUFMLENBQWNrQixlQUFyRDtBQUNBLG9CQUFJNlIsUUFBSixFQUFjO0FBQ1Y7QUFDQSwyQkFBSy9TLFFBQUwsQ0FBY2tCLGVBQWQsR0FBZ0MsS0FBaEM7QUFDSDs7QUFFRCxvQkFBTW9TLHdCQUF5QixJQUFJeFUsV0FBSixDQUFnQkssVUFBaEIsRUFBNEIsNEJBQWtCOFEsZUFBbEIsQ0FBa0M5USxVQUFsQyxDQUE1QixFQUEyRSxPQUFLYSxRQUFoRixDQUEvQjs7QUFFQTtBQUNBO0FBQ0Esb0JBQUkrUyxRQUFKLEVBQWM7QUFDVjtBQUNBTywwQ0FBc0JwUCxhQUF0QixDQUFvQ2lQLGdCQUFwQzs7QUFFQTtBQUNBLDJCQUFLbFAsZUFBTCxDQUFxQjlFLFVBQXJCLEVBQWlDbVUscUJBQWpDLEVBTFUsQ0FLK0M7QUFDekQsMkJBQUt0VCxRQUFMLENBQWNrQixlQUFkLEdBQWdDbVMsOEJBQWhDO0FBQ0g7O0FBRURELHdDQUF3Qm5SLElBQXhCLENBQTZCcVIscUJBQTdCO0FBQ0gsYUF0QkQ7O0FBd0JBLGdCQUFJTiw4QkFBSixFQUFvQztBQUNoQztBQUNBLHVCQUFPSSx3QkFBd0IsQ0FBeEIsQ0FBUDtBQUNIOztBQUVEO0FBQ0EsbUJBQU9BLHVCQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7Z0NBTzZCO0FBQUEsZ0JBQXZCcFEsYUFBdUIsdUVBQVAsS0FBTzs7QUFDekIsZ0JBQUlBLGFBQUosRUFBbUI7QUFDZixvQkFBTXVRLHlCQUF5QjtBQUMzQnhOLHdDQUFvQmpILFlBQVkwQyxPQUFaLENBQW9CdUUsa0JBQXBCLENBQXVDeU47QUFEaEMsaUJBQS9CO0FBR0EscUJBQUtsUyxHQUFMLENBQVMsRUFBVCxFQUFhaVMsc0JBQWI7QUFDSCxhQUxELE1BS087QUFDSCxxQkFBS2pTLEdBQUwsQ0FBUyxFQUFUO0FBQ0g7O0FBRUQsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7O2lDQU9TO0FBQ0wsaUJBQUsrTixpQ0FBTDtBQUNBLGlCQUFLekkscUJBQUw7O0FBRUE7QUFDQSxpQkFBS3NMLG9CQUFMLENBQTBCLEtBQUsvUyxVQUEvQjtBQUNBO0FBQ0EsaUJBQUt1QixXQUFMLENBQWlCK1MscUJBQWpCLENBQXVDLElBQXZDO0FBQ0g7O0FBRUQ7Ozs7Ozs7OzsrQkFNTztBQUNILGlCQUFLbkQsZ0JBQUwsQ0FBc0IsRUFBdEI7QUFDQSxpQkFBS3JOLE1BQUw7QUFDSDs7QUFFRDs7Ozs7OytCQUdPO0FBQ0gsaUJBQUtBLE1BQUw7QUFDQTtBQUNBLGlCQUFLOUQsVUFBTCxDQUFnQjRTLFVBQWhCLENBQTJCMkIsV0FBM0IsQ0FBdUMsS0FBS3ZVLFVBQTVDO0FBQ0g7O0FBR0Q7O0FBRUE7Ozs7Ozs7Ozs7OzsrQkFTMEI7QUFBQSxnQkFBckJ3VSxXQUFxQix1RUFBUCxLQUFPOztBQUN0QixnQkFBSUEsZUFBZSw0QkFBa0JqSSx3QkFBbEIsQ0FBMkMsS0FBSzdMLFVBQWhELENBQW5CLEVBQWdGO0FBQzVFLHFCQUFLQSxVQUFMLEdBQWtCLEtBQUtDLGNBQUwsRUFBbEI7QUFDSDs7QUFFRCxtQkFBTyxLQUFLRCxVQUFaO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozt5Q0FNaUI7QUFDYixnQkFBSSxLQUFLVixVQUFMLENBQWdCeVUsT0FBaEIsQ0FBd0JDLFdBQXhCLE9BQTBDLE1BQTlDLEVBQXNEO0FBQ2xELHVCQUFPLElBQVA7QUFDSDs7QUFFRCxnQkFBSXZRLE9BQU8sS0FBS25FLFVBQWhCO0FBQ0EsZ0JBQUl5VSxnQkFBSjtBQUNBLGVBQUc7QUFDQ3RRLHVCQUFPQSxLQUFLeU8sVUFBWjtBQUNBLG9CQUFJLDRCQUFrQjlKLE1BQWxCLENBQXlCM0UsSUFBekIsQ0FBSixFQUFvQztBQUNoQztBQUNBLDJCQUFPLElBQVA7QUFDSDs7QUFFRCxvQkFBSUEsS0FBS3NRLE9BQVQsRUFBa0I7QUFDZEEsOEJBQVV0USxLQUFLc1EsT0FBTCxDQUFhQyxXQUFiLEVBQVY7QUFDSCxpQkFGRCxNQUVPO0FBQ0hELDhCQUFVLEVBQVY7QUFDSDs7QUFFRCxvQkFBSUEsWUFBWSxNQUFoQixFQUF3QjtBQUNwQjtBQUNBO0FBQ0g7QUFDSixhQWpCRCxRQWlCU0EsWUFBWSxNQWpCckI7O0FBbUJBLGdCQUFJQSxZQUFZLE1BQWhCLEVBQXdCO0FBQ3BCLHVCQUFPdFEsSUFBUDtBQUNILGFBRkQsTUFFTztBQUNILHVCQUFPLElBQVA7QUFDSDtBQUNKOztBQUVEOzs7Ozs7Ozs7NENBTW9CO0FBQ2hCLG1CQUFPLEtBQUs1QyxXQUFMLENBQWlCb1QsdUJBQWpCLENBQXlDLEtBQUtDLElBQUwsRUFBekMsRUFBc0QsS0FBSy9ULFFBQUwsQ0FBY3VILGVBQXBFLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7d0NBS2dCO0FBQ1osbUJBQU8sS0FBSzdHLFdBQUwsQ0FBaUJzVCxtQkFBakIsQ0FBcUMsS0FBS0QsSUFBTCxFQUFyQyxFQUFrRCxLQUFLL1QsUUFBTCxDQUFjdUgsZUFBaEUsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7O3dDQU95QztBQUFBLGdCQUEzQjdFLGtCQUEyQix1RUFBTixJQUFNOztBQUNyQyxnQkFBSW1PLDBCQUFKO0FBQ0EsZ0JBQUksNEJBQWtCNUksTUFBbEIsQ0FBeUJ2RixrQkFBekIsQ0FBSixFQUFrRDtBQUM5Q21PLG9DQUFvQixLQUFLN1EsUUFBTCxDQUFjOEcsWUFBbEM7QUFDSCxhQUZELE1BRU87QUFDSCtKLG9DQUFvQm5PLGtCQUFwQjtBQUNIOztBQUVELG1CQUFPLEtBQUtoQyxXQUFMLENBQWlCdVQsbUJBQWpCLENBQXFDLEtBQUtGLElBQUwsRUFBckMsRUFBa0QsS0FBSy9ULFFBQUwsQ0FBY3VILGVBQWhFLEVBQWlGc0osaUJBQWpGLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7O2lEQU15QjtBQUNyQixtQkFBTyxLQUFLblEsV0FBTCxDQUFpQndULDRCQUFqQixDQUE4QyxLQUFLSCxJQUFMLEVBQTlDLEVBQTJELEtBQUsvVCxRQUFMLENBQWN1SCxlQUF6RSxDQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs2Q0FNcUI7QUFDakIsbUJBQU8sS0FBSzdHLFdBQUwsQ0FBaUJ5VCx3QkFBakIsQ0FBMEMsS0FBS0osSUFBTCxFQUExQyxFQUF1RCxLQUFLL1QsUUFBTCxDQUFjdUgsZUFBckUsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7OzZDQU84QztBQUFBLGdCQUEzQjdFLGtCQUEyQix1RUFBTixJQUFNOztBQUMxQyxnQkFBSW1PLDBCQUFKO0FBQ0EsZ0JBQUksNEJBQWtCNUksTUFBbEIsQ0FBeUJ2RixrQkFBekIsQ0FBSixFQUFrRDtBQUM5Q21PLG9DQUFvQixLQUFLN1EsUUFBTCxDQUFjOEcsWUFBbEM7QUFDSCxhQUZELE1BRU87QUFDSCtKLG9DQUFvQm5PLGtCQUFwQjtBQUNIOztBQUVELG1CQUFPLEtBQUtoQyxXQUFMLENBQWlCMFQsd0JBQWpCLENBQTBDLEtBQUtMLElBQUwsRUFBMUMsRUFBdUQsS0FBSy9ULFFBQUwsQ0FBY3VILGVBQXJFLEVBQXNGc0osaUJBQXRGLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7O2dEQU13QjtBQUNwQixtQkFBT3dELEtBQUtDLFNBQUwsQ0FBZSxLQUFLQyxzQkFBTCxFQUFmLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7OzRDQU1vQjtBQUNoQixtQkFBT0YsS0FBS0MsU0FBTCxDQUFlLEtBQUtFLGtCQUFMLEVBQWYsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7OzRDQU82QztBQUFBLGdCQUEzQjlSLGtCQUEyQix1RUFBTixJQUFNOztBQUN6QyxtQkFBTzJSLEtBQUtDLFNBQUwsQ0FBZSxLQUFLRyxrQkFBTCxDQUF3Qi9SLGtCQUF4QixDQUFmLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7dUNBS2U7QUFBRTtBQUNiLGdCQUFNZ1MsU0FBUyxLQUFLaFUsV0FBTCxDQUFpQmlVLHVCQUFqQixDQUF5QyxLQUFLWixJQUFMLEVBQXpDLENBQWY7QUFDQVcsbUJBQU9oVCxPQUFQLENBQWUsaUJBQVM7QUFDcEI1Qyw0QkFBWTJFLHFCQUFaLENBQWtDbVIsS0FBbEMsRUFBeUNwUyxRQUF6QztBQUNILGFBRkQ7O0FBSUEsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7OztnREFLd0I7QUFBRTtBQUN0QixnQkFBTWtTLFNBQVMsS0FBS2hVLFdBQUwsQ0FBaUJpVSx1QkFBakIsQ0FBeUMsS0FBS1osSUFBTCxFQUF6QyxDQUFmO0FBQ0FXLG1CQUFPaFQsT0FBUCxDQUFlLGlCQUFTO0FBQ3BCNUMsNEJBQVkyRSxxQkFBWixDQUFrQ21SLEtBQWxDLEVBQXlDblMsaUJBQXpDO0FBQ0gsYUFGRDs7QUFJQSxtQkFBTyxJQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7O3VDQUtlO0FBQUU7QUFDYixnQkFBTWlTLFNBQVMsS0FBS2hVLFdBQUwsQ0FBaUJpVSx1QkFBakIsQ0FBeUMsS0FBS1osSUFBTCxFQUF6QyxDQUFmO0FBQ0FXLG1CQUFPaFQsT0FBUCxDQUFlLGlCQUFTO0FBQ3BCNUMsNEJBQVkyRSxxQkFBWixDQUFrQ21SLEtBQWxDLEVBQXlDclMsUUFBekM7QUFDSCxhQUZEOztBQUlBLG1CQUFPLElBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7a0RBUXlDO0FBQUEsZ0JBQWpCUixRQUFpQix1RUFBTixJQUFNO0FBQUU7QUFDdkMsZ0JBQUksNEJBQWtCa0csTUFBbEIsQ0FBeUJsRyxRQUF6QixDQUFKLEVBQXdDO0FBQ3BDLHFCQUFLOFMsWUFBTDtBQUNBLHFCQUFLZCxJQUFMLEdBQVllLE1BQVo7QUFDQSxxQkFBS0MsWUFBTDtBQUNILGFBSkQsTUFJTyxJQUFJLDRCQUFrQjFJLFVBQWxCLENBQTZCdEssUUFBN0IsQ0FBSixFQUE0QztBQUMvQ0EseUJBQVMsS0FBS2lULGlCQUFMLEVBQVQ7QUFDSCxhQUZNLE1BRUE7QUFDSCw0Q0FBa0JqSSxVQUFsQjtBQUNIOztBQUVELG1CQUFPLElBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7OENBUXFDO0FBQUEsZ0JBQWpCaEwsUUFBaUIsdUVBQU4sSUFBTTtBQUFFO0FBQ25DLGdCQUFJLDRCQUFrQmtHLE1BQWxCLENBQXlCbEcsUUFBekIsQ0FBSixFQUF3QztBQUNwQyxxQkFBS2dTLElBQUwsR0FBWWUsTUFBWjtBQUNILGFBRkQsTUFFTyxJQUFJLDRCQUFrQnpJLFVBQWxCLENBQTZCdEssUUFBN0IsQ0FBSixFQUE0QztBQUMvQ0EseUJBQVMsS0FBS2tULGFBQUwsRUFBVDtBQUNILGFBRk0sTUFFQTtBQUNILDRDQUFrQmxJLFVBQWxCO0FBQ0g7O0FBRUQsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7OENBU2dFO0FBQUEsZ0JBQTVDckssa0JBQTRDLHVFQUF2QixJQUF1QjtBQUFBLGdCQUFqQlgsUUFBaUIsdUVBQU4sSUFBTTtBQUFFO0FBQzlELGdCQUFJLDRCQUFrQmtHLE1BQWxCLENBQXlCbEcsUUFBekIsQ0FBSixFQUF3QztBQUNwQyxxQkFBS21ULHFCQUFMO0FBQ0EscUJBQUtuQixJQUFMLEdBQVllLE1BQVo7QUFDQSxxQkFBS0MsWUFBTDtBQUNILGFBSkQsTUFJTyxJQUFJLDRCQUFrQjFJLFVBQWxCLENBQTZCdEssUUFBN0IsQ0FBSixFQUE0QztBQUMvQ0EseUJBQVMsS0FBS29ULGFBQUwsQ0FBbUJ6UyxrQkFBbkIsQ0FBVDtBQUNILGFBRk0sTUFFQTtBQUNILDRDQUFrQnFLLFVBQWxCO0FBQ0g7O0FBRUQsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7O3FEQU82QmhMLFEsRUFBVTtBQUFFO0FBQ3JDLGdCQUFJLDRCQUFrQnNLLFVBQWxCLENBQTZCdEssUUFBN0IsQ0FBSixFQUE0QztBQUN4Q0EseUJBQVMsS0FBS3dTLHNCQUFMLEVBQVQ7QUFDSCxhQUZELE1BRU87QUFDSCw0Q0FBa0J4SCxVQUFsQjtBQUNIOztBQUVELG1CQUFPLElBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7OztpREFPeUJoTCxRLEVBQVU7QUFBRTtBQUNqQyxnQkFBSSw0QkFBa0JzSyxVQUFsQixDQUE2QnRLLFFBQTdCLENBQUosRUFBNEM7QUFDeENBLHlCQUFTLEtBQUt5UyxrQkFBTCxFQUFUO0FBQ0gsYUFGRCxNQUVPO0FBQ0gsNENBQWtCekgsVUFBbEI7QUFDSDs7QUFFRCxtQkFBTyxJQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7O2lEQVF5QmhMLFEsRUFBcUM7QUFBQSxnQkFBM0JXLGtCQUEyQix1RUFBTixJQUFNO0FBQUU7QUFDNUQsZ0JBQUksNEJBQWtCMkosVUFBbEIsQ0FBNkJ0SyxRQUE3QixDQUFKLEVBQTRDO0FBQ3hDQSx5QkFBUyxLQUFLMFMsa0JBQUwsQ0FBd0IvUixrQkFBeEIsQ0FBVDtBQUNILGFBRkQsTUFFTztBQUNILDRDQUFrQnFLLFVBQWxCO0FBQ0g7O0FBRUQsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7O29EQU80QmhMLFEsRUFBVTtBQUFFO0FBQ3BDLGdCQUFJLDRCQUFrQnNLLFVBQWxCLENBQTZCdEssUUFBN0IsQ0FBSixFQUE0QztBQUN4Q0EseUJBQVMsS0FBS3FULHFCQUFMLEVBQVQ7QUFDSCxhQUZELE1BRU87QUFDSCw0Q0FBa0JySSxVQUFsQjtBQUNIOztBQUVELG1CQUFPLElBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7OztnREFPd0JoTCxRLEVBQVU7QUFBRTtBQUNoQyxnQkFBSSw0QkFBa0JzSyxVQUFsQixDQUE2QnRLLFFBQTdCLENBQUosRUFBNEM7QUFDeENBLHlCQUFTLEtBQUtzVCxpQkFBTCxFQUFUO0FBQ0gsYUFGRCxNQUVPO0FBQ0gsNENBQWtCdEksVUFBbEI7QUFDSDs7QUFFRCxtQkFBTyxJQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7O2dEQVF3QmhMLFEsRUFBcUM7QUFBQSxnQkFBM0JXLGtCQUEyQix1RUFBTixJQUFNO0FBQUU7QUFDM0QsZ0JBQUksNEJBQWtCMkosVUFBbEIsQ0FBNkJ0SyxRQUE3QixDQUFKLEVBQTRDO0FBQ3hDQSx5QkFBUyxLQUFLdVQsaUJBQUwsQ0FBdUI1UyxrQkFBdkIsQ0FBVDtBQUNILGFBRkQsTUFFTztBQUNILDRDQUFrQnFLLFVBQWxCO0FBQ0g7O0FBRUQsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7OztBQWlLQTs7OzsyQ0FJbUI7QUFDZixpQkFBS3RMLG9CQUFMLEdBQTRCLElBQUlzQyxHQUFKLEVBQTVCO0FBQ0EsaUJBQUtFLGVBQUwsQ0FBcUIsS0FBSzlFLFVBQTFCO0FBQ0g7O0FBRUQ7Ozs7Ozs7MkNBSW1CO0FBQ2YsbUJBQU8sS0FBS3NDLG9CQUFaO0FBQ0g7O0FBRUQ7Ozs7Ozs7OztzQ0FNYzhULFMsRUFBVztBQUNyQixpQkFBSzlULG9CQUFMLEdBQTRCOFQsU0FBNUI7QUFDSDs7QUFFRDs7Ozs7Ozs7O3dDQU1nQjtBQUNaLG1CQUFPLEtBQUs5VCxvQkFBWjtBQUNIOztBQUVEOzs7Ozs7Ozs7d0NBTWdCO0FBQ1osbUJBQU8sS0FBS0Esb0JBQUwsWUFBcUNzQyxHQUFyQyxJQUE0QyxLQUFLdEMsb0JBQUwsQ0FBMEJvQyxJQUExQixLQUFtQyxDQUF0RjtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7d0NBU2dCMUUsVSxFQUFzQztBQUFBLGdCQUExQnFXLGlCQUEwQix1RUFBTixJQUFNOztBQUNsRCxnQkFBSSw0QkFBa0J2TixNQUFsQixDQUF5QnVOLGlCQUF6QixDQUFKLEVBQWlEO0FBQzdDQSxvQ0FBb0IsSUFBcEI7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQjlILFdBQWxCLENBQThCLEtBQUtqTSxvQkFBbkMsQ0FBTCxFQUErRDtBQUMzRCxxQkFBS0Esb0JBQUwsQ0FBMEJILEdBQTFCLENBQThCbkMsVUFBOUIsRUFBMENxVyxpQkFBMUMsRUFEMkQsQ0FDRztBQUNqRSxhQUZELE1BRU87QUFDSCw0Q0FBa0J6SSxVQUFsQiw4RUFBd0csS0FBS3RMLG9CQUE3RztBQUNIO0FBQ0o7O0FBRUQ7Ozs7Ozs7Ozs2Q0FNcUJ0QyxVLEVBQVk7QUFDN0IsZ0JBQUksQ0FBQyw0QkFBa0J1TyxXQUFsQixDQUE4QixLQUFLak0sb0JBQW5DLENBQUwsRUFBK0Q7QUFDM0QscUJBQUtBLG9CQUFMLENBQTBCNkMsTUFBMUIsQ0FBaUNuRixVQUFqQztBQUNILGFBRkQsTUFFTyxJQUFJLEtBQUthLFFBQUwsQ0FBY2tCLGVBQWxCLEVBQW1DO0FBQ3RDLDRDQUFrQjZMLFVBQWxCLGlGQUEyRyxLQUFLdEwsb0JBQWhIO0FBQ0g7QUFDSjs7QUFFRDs7Ozs7Ozs7Ozs7Ozt5Q0FVK0I7QUFBQSwrQ0FBYmdVLFdBQWE7QUFBYkEsMkJBQWE7QUFBQTs7QUFDM0IsdUNBQWMsS0FBS3pWLFFBQW5CLFNBQWdDeVYsV0FBaEM7QUFDSDs7QUFFRDs7Ozs7Ozs7OztpREFPdUM7QUFDbkMsZ0JBQU16VCxTQUFTLEVBQWY7O0FBRG1DLCtDQUFieVQsV0FBYTtBQUFiQSwyQkFBYTtBQUFBOztBQUVuQyx1Q0FBY3pULE1BQWQsRUFBc0IsS0FBS2hDLFFBQTNCLFNBQXdDeVYsV0FBeEM7O0FBRUEsbUJBQU96VCxNQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBc3VCQTtBQUNBOztBQUVBOzs7Ozs7OztpREFReUIwVCxnQixFQUF5QztBQUFBLGdCQUF2QnJELGNBQXVCLHVFQUFOLElBQU07O0FBQzlELGdCQUFJLENBQUMsNEJBQWtCcEssTUFBbEIsQ0FBeUJvSyxjQUF6QixDQUFMLEVBQStDO0FBQzNDLHFCQUFLc0QsY0FBTCxDQUFvQkQsZ0JBQXBCLEVBQXNDckQsY0FBdEM7QUFDQSxxQkFBSzFQLE1BQUwsQ0FBWSxLQUFLM0MsUUFBakI7QUFDSCxhQUhELE1BR087QUFDSCxxQkFBSzJDLE1BQUwsQ0FBWStTLGdCQUFaO0FBQ0g7O0FBRUQsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7O2lDQU84QjtBQUFBLGdCQUF2QnJELGNBQXVCLHVFQUFOLElBQU07O0FBQzFCLGlCQUFLdUQsd0JBQUwsQ0FBOEI5VyxZQUFZK1csb0JBQVosR0FBbUNDLE1BQWpFLEVBQXlFekQsY0FBekU7O0FBRUEsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7O3dDQU9xQztBQUFBLGdCQUF2QkEsY0FBdUIsdUVBQU4sSUFBTTs7QUFDakMsaUJBQUt1RCx3QkFBTCxDQUE4QjlXLFlBQVkrVyxvQkFBWixHQUFtQ0UsYUFBakUsRUFBZ0YxRCxjQUFoRjs7QUFFQSxtQkFBTyxJQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7a0NBTytCO0FBQUEsZ0JBQXZCQSxjQUF1Qix1RUFBTixJQUFNOztBQUMzQixpQkFBS3VELHdCQUFMLENBQThCOVcsWUFBWStXLG9CQUFaLEdBQW1DRyxPQUFqRSxFQUEwRTNELGNBQTFFOztBQUVBLG1CQUFPLElBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7OztnQ0FPNkI7QUFBQSxnQkFBdkJBLGNBQXVCLHVFQUFOLElBQU07O0FBQ3pCLGlCQUFLdUQsd0JBQUwsQ0FBOEI5VyxZQUFZK1csb0JBQVosR0FBbUNJLEtBQWpFLEVBQXdFNUQsY0FBeEU7O0FBRUEsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7O21DQU9nQztBQUFBLGdCQUF2QkEsY0FBdUIsdUVBQU4sSUFBTTs7QUFDNUIsaUJBQUt1RCx3QkFBTCxDQUE4QjlXLFlBQVkrVyxvQkFBWixHQUFtQ0ssUUFBakUsRUFBMkU3RCxjQUEzRTs7QUFFQSxtQkFBTyxJQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7a0NBTytCO0FBQUEsZ0JBQXZCQSxjQUF1Qix1RUFBTixJQUFNOztBQUMzQixpQkFBS3VELHdCQUFMLENBQThCOVcsWUFBWStXLG9CQUFaLEdBQW1DTSxPQUFqRSxFQUEwRTlELGNBQTFFOztBQUVBLG1CQUFPLElBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7OztrQ0FPK0I7QUFBQSxnQkFBdkJBLGNBQXVCLHVFQUFOLElBQU07O0FBQzNCLGlCQUFLdUQsd0JBQUwsQ0FBOEI5VyxZQUFZK1csb0JBQVosR0FBbUNPLE9BQWpFLEVBQTBFL0QsY0FBMUU7O0FBRUEsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7O29DQU9pQztBQUFBLGdCQUF2QkEsY0FBdUIsdUVBQU4sSUFBTTs7QUFDN0IsaUJBQUt1RCx3QkFBTCxDQUE4QjlXLFlBQVkrVyxvQkFBWixHQUFtQ1EsU0FBakUsRUFBNEVoRSxjQUE1RTs7QUFFQSxtQkFBTyxJQUFQO0FBQ0g7O0FBR0Q7QUFDQTs7Ozs7Ozs7O2dFQU13QztBQUFFO0FBQ3RDO0FBQ0EsaUJBQUssSUFBTWlFLEdBQVgsSUFBa0IsS0FBS3RXLFFBQXZCLEVBQWlDO0FBQzdCLG9CQUFJLEtBQUtBLFFBQUwsQ0FBY3VXLGNBQWQsQ0FBNkJELEdBQTdCLENBQUosRUFBdUM7QUFDbkMsd0JBQU16VSxRQUFRLEtBQUs3QixRQUFMLENBQWNzVyxHQUFkLENBQWQ7O0FBRUEsd0JBQUksT0FBT3pVLEtBQVAsS0FBaUIsVUFBckIsRUFBaUM7QUFDN0IsNkJBQUs3QixRQUFMLENBQWNzVyxHQUFkLElBQXFCelUsTUFBTSxJQUFOLEVBQVl5VSxHQUFaLENBQXJCO0FBQ0gscUJBRkQsTUFFTztBQUNIO0FBQ0EsNEJBQUlFLGdCQUFnQixLQUFLclgsVUFBTCxDQUFnQjZJLFlBQWhCLENBQTZCc08sR0FBN0IsQ0FBcEIsQ0FGRyxDQUVvRDtBQUN2REUsd0NBQWdCLDRCQUFrQkMsUUFBbEIsQ0FBMkJELGFBQTNCLENBQWhCO0FBQ0EsNEJBQUksT0FBTyxLQUFLeFcsUUFBTCxDQUFjd1csYUFBZCxDQUFQLEtBQXdDLFVBQTVDLEVBQXdEO0FBQ3BELGlDQUFLeFcsUUFBTCxDQUFjc1csR0FBZCxJQUFxQkUsY0FBYyxJQUFkLEVBQW9CRixHQUFwQixDQUFyQjtBQUNIO0FBQ0o7QUFDSjtBQUNKO0FBQ0o7O0FBRUQ7Ozs7Ozs7Ozt1REFNK0I7QUFDM0IsaUJBQUtJLGtCQUFMLEdBQTJCLEtBQUsxVyxRQUFMLENBQWNrRix1QkFBZCxLQUEwQ3BHLFlBQVkwQyxPQUFaLENBQW9CMEQsdUJBQXBCLENBQTRDc00sTUFBdEYsSUFBZ0csS0FBS3hSLFFBQUwsQ0FBY3lHLDZCQUFkLEtBQWdEM0gsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q2SyxNQUFuTSxJQUN6QixLQUFLdFIsUUFBTCxDQUFja0YsdUJBQWQsS0FBMENwRyxZQUFZMEMsT0FBWixDQUFvQjBELHVCQUFwQixDQUE0Q29NLE1BQXRGLEtBQ0EsS0FBS3RSLFFBQUwsQ0FBY3lHLDZCQUFkLEtBQWdEM0gsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q4SyxJQUFsRyxJQUEwRyxLQUFLdlIsUUFBTCxDQUFjeUcsNkJBQWQsS0FBZ0QzSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRGdMLEtBRDVNLENBREQ7QUFHSDs7QUFFRDs7Ozs7Ozs7Ozs7Ozs7O0FBa0pBOzs7O3VDQUllO0FBQ1gsZ0JBQUksQ0FBQyw0QkFBa0J4SixNQUFsQixDQUF5QixLQUFLakksUUFBTCxDQUFjd0csMEJBQXZDLENBQUwsRUFBeUU7QUFBQSw0Q0FDWCxLQUFLeEcsUUFBTCxDQUFjd0csMEJBQWQsQ0FBeUNtUSxLQUF6QyxDQUErQyxHQUEvQyxDQURXOztBQUFBOztBQUNwRSxxQkFBSzNXLFFBQUwsQ0FBYzRXLFlBRHNEO0FBQ3hDLHFCQUFLNVcsUUFBTCxDQUFjNlcsV0FEMEI7QUFFeEUsYUFGRCxNQUVPO0FBQ0gscUJBQUs3VyxRQUFMLENBQWM0VyxZQUFkLEdBQTZCLEVBQTdCO0FBQ0EscUJBQUs1VyxRQUFMLENBQWM2VyxXQUFkLEdBQTRCLEVBQTVCO0FBQ0g7QUFDSjs7QUFFRDs7Ozs7Ozs7Ozs7Ozs7O0FBb0ZBOzs7Ozs7MEVBTWtEQyxDLEVBQUc7QUFDakQsZ0JBQUksS0FBSzlXLFFBQUwsQ0FBY21GLGdCQUFkLEtBQW1DLEdBQXZDLEVBQTRDO0FBQ3hDMlIsb0JBQUlBLEVBQUVwSSxPQUFGLENBQVUsS0FBSzFPLFFBQUwsQ0FBY21GLGdCQUF4QixFQUEwQyxHQUExQyxDQUFKO0FBQ0g7O0FBRUQsZ0JBQUksS0FBS25GLFFBQUwsQ0FBYytXLHFCQUFkLEtBQXdDLEdBQXhDLElBQStDLEtBQUsvVyxRQUFMLENBQWMrVyxxQkFBZCxLQUF3QyxFQUEzRixFQUErRjtBQUMzRkQsb0JBQUlBLEVBQUVwSSxPQUFGLENBQVUsS0FBSzFPLFFBQUwsQ0FBYytXLHFCQUF4QixFQUErQyxHQUEvQyxDQUFKO0FBQ0g7O0FBRUQsZ0JBQUksQ0FBQ0QsRUFBRUUsS0FBRixDQUFRLElBQVIsQ0FBTCxFQUFvQjtBQUNoQjtBQUNBRixxQkFBSyxHQUFMO0FBQ0g7O0FBRUQsbUJBQU9BLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7O0FBNE5BOzs7Ozs7Ozs7Ozs7Ozs4Q0Fjc0JqVixLLEVBQU87QUFDekIsZ0JBQUksNEJBQWtCb0csTUFBbEIsQ0FBeUIsS0FBS2pJLFFBQUwsQ0FBYytFLG9CQUF2QyxDQUFKLEVBQWtFO0FBQzlELDRDQUFrQmdJLFVBQWxCLENBQTZCLG9HQUE3QjtBQUNIOztBQUVELGdCQUFNa0ssa0JBQWtCLEtBQUtyUyxRQUFMLEdBQWdCLENBQXhDO0FBQ0EsZ0JBQU0wSixxQkFBcUIsNEJBQWtCQSxrQkFBbEIsQ0FBcUN6TSxLQUFyQyxDQUEzQjtBQUNBLGdCQUFNcVYsY0FBY3JWLE1BQU11SSxNQUExQjs7QUFFQSxnQkFBSStNLFlBQVksQ0FBaEI7QUFDQSxnQkFBSUMsY0FBYyxDQUFsQjtBQUNBLGdCQUFJQyxpQkFBaUIsS0FBckI7QUFDQSxnQkFBSUMsb0JBQW9CLENBQXhCO0FBQ0EsZ0JBQUksS0FBS3RYLFFBQUwsQ0FBYytFLG9CQUFkLEtBQXVDakcsWUFBWTBDLE9BQVosQ0FBb0J1RCxvQkFBcEIsQ0FBeUM2RixLQUFwRixFQUEyRjtBQUN2Ri9JLHdCQUFRQSxNQUFNNk0sT0FBTixDQUFjLEdBQWQsRUFBbUIsRUFBbkIsQ0FBUjtBQUNBN00sd0JBQVFBLE1BQU02TSxPQUFOLENBQWMsR0FBZCxFQUFtQixFQUFuQixDQUFSO0FBQ0E3TSx3QkFBUUEsTUFBTTZNLE9BQU4sQ0FBYyxLQUFLMU8sUUFBTCxDQUFjaUYsY0FBNUIsRUFBNEMsRUFBNUMsQ0FBUjtBQUNBa1MsNEJBQVl0VixNQUFNdUksTUFBbEI7QUFDQWlOLGlDQUFpQiw0QkFBa0JFLFFBQWxCLENBQTJCMVYsS0FBM0IsRUFBa0MsS0FBSzdCLFFBQUwsQ0FBY21GLGdCQUFoRCxDQUFqQjs7QUFFQSxvQkFBSSxLQUFLbkYsUUFBTCxDQUFjK0Usb0JBQWQsS0FBdUNqRyxZQUFZMEMsT0FBWixDQUFvQnVELG9CQUFwQixDQUF5Q3lTLFdBQWhGLElBQ0EsS0FBS3hYLFFBQUwsQ0FBYytFLG9CQUFkLEtBQXVDakcsWUFBWTBDLE9BQVosQ0FBb0J1RCxvQkFBcEIsQ0FBeUMwUyxZQURwRixFQUNrRztBQUM5Rix3QkFBSUosY0FBSixFQUFvQjtBQUNoQkQsc0NBQWN2VixNQUFNZ1EsT0FBTixDQUFjLEtBQUs3UixRQUFMLENBQWNtRixnQkFBNUIsQ0FBZDtBQUNBbVMsNENBQW9CLEtBQUt0WCxRQUFMLENBQWNtRixnQkFBZCxDQUErQmlGLE1BQW5EO0FBQ0gscUJBSEQsTUFHTztBQUNIZ04sc0NBQWNELFNBQWQ7QUFDQUcsNENBQW9CLENBQXBCO0FBQ0g7QUFDSjtBQUNKOztBQUVELGdCQUFJSSxZQUFZLEVBQWhCO0FBQ0EsZ0JBQUlULGVBQUosRUFBcUI7QUFDakJTLDRCQUFZLEtBQUsxWCxRQUFMLENBQWMrVyxxQkFBMUI7QUFDSCxhQUZELE1BRU8sSUFBSSxLQUFLL1csUUFBTCxDQUFjeUgsZ0JBQWQsSUFBa0MsQ0FBQzZHLGtCQUF2QyxFQUEyRDtBQUM5RG9KLDRCQUFZLEtBQUsxWCxRQUFMLENBQWMyWCxxQkFBMUI7QUFDSDs7QUFFRCxnQkFBTUMsMkJBQTJCRixVQUFVdE4sTUFBM0M7QUFDQSxnQkFBTThHLHFCQUFxQixLQUFLbFIsUUFBTCxDQUFjaUYsY0FBZCxDQUE2Qm1GLE1BQXhEOztBQUVBO0FBQ0EsZ0JBQUl5TixzQkFBSjtBQUNBLGdCQUFJLEtBQUs3WCxRQUFMLENBQWNrRix1QkFBZCxLQUEwQ3BHLFlBQVkwQyxPQUFaLENBQW9CMEQsdUJBQXBCLENBQTRDc00sTUFBMUYsRUFBa0c7QUFDOUYsb0JBQUksS0FBS3hSLFFBQUwsQ0FBYytFLG9CQUFkLEtBQXVDakcsWUFBWTBDLE9BQVosQ0FBb0J1RCxvQkFBcEIsQ0FBeUM2RixLQUFwRixFQUEyRjtBQUN2Rix3QkFBSSxLQUFLNUssUUFBTCxDQUFjeUcsNkJBQWQsS0FBZ0QzSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRGtMLElBQWxHLEtBQ0NzRixtQkFBb0IsQ0FBQ0EsZUFBRCxJQUFvQixLQUFLalgsUUFBTCxDQUFjeUgsZ0JBQWxDLElBQXNELENBQUM2RyxrQkFENUUsQ0FBSixFQUNzRztBQUNsRyxnQ0FBUSxLQUFLdE8sUUFBTCxDQUFjeUcsNkJBQXRCO0FBQ0ksaUNBQUszSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRCtLLE1BQXZELENBREosQ0FDbUU7QUFDL0QsaUNBQUsxUyxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRDhLLElBQXZELENBRkosQ0FFbUU7QUFDL0QsaUNBQUt6UyxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRGdMLEtBQXZEO0FBQStEO0FBQzNEb0csZ0RBQWdCRCwyQkFBMkIxRyxrQkFBM0M7QUFDQTtBQUNKLGlDQUFLcFMsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q2SyxNQUF2RDtBQUErRDtBQUMzRHVHLGdEQUFnQjNHLGtCQUFoQjtBQUNBO0FBUlI7QUFVSCxxQkFaRCxNQVlPO0FBQWdFO0FBQ25FMkcsd0NBQWdCM0csa0JBQWhCO0FBQ0g7QUFDSixpQkFoQkQsTUFnQk8sSUFBSSxLQUFLbFIsUUFBTCxDQUFjK0Usb0JBQWQsS0FBdUNqRyxZQUFZMEMsT0FBWixDQUFvQnVELG9CQUFwQixDQUF5QytGLEdBQXBGLEVBQXlGO0FBQzVGLHdCQUFJLEtBQUs5SyxRQUFMLENBQWN5Ryw2QkFBZCxLQUFnRDNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEa0wsSUFBbEcsS0FDQ3NGLG1CQUFvQixDQUFDQSxlQUFELElBQW9CLEtBQUtqWCxRQUFMLENBQWN5SCxnQkFBbEMsSUFBc0QsQ0FBQzZHLGtCQUQ1RSxDQUFKLEVBQ3NHO0FBQ2xHLGdDQUFRLEtBQUt0TyxRQUFMLENBQWN5Ryw2QkFBdEI7QUFDSSxpQ0FBSzNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEK0ssTUFBdkQsQ0FESixDQUNtRTtBQUMvRCxpQ0FBSzFTLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEOEssSUFBdkQsQ0FGSixDQUVtRTtBQUMvRCxpQ0FBS3pTLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEZ0wsS0FBdkQ7QUFBK0Q7QUFDM0RvRyxnREFBZ0JYLFdBQWhCO0FBQ0E7QUFDSixpQ0FBS3BZLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtENkssTUFBdkQ7QUFBK0Q7QUFDM0R1RyxnREFBZ0IzRyxxQkFBcUJpRyxTQUFyQztBQUNBO0FBUlI7QUFVSCxxQkFaRCxNQVlPO0FBQWdFO0FBQ25FVSx3Q0FBZ0JYLFdBQWhCO0FBQ0g7QUFDSixpQkFoQk0sTUFnQkEsSUFBSSxLQUFLbFgsUUFBTCxDQUFjK0Usb0JBQWQsS0FBdUNqRyxZQUFZMEMsT0FBWixDQUFvQnVELG9CQUFwQixDQUF5Q3lTLFdBQXBGLEVBQWlHO0FBQ3BHLHdCQUFJLEtBQUt4WCxRQUFMLENBQWN5Ryw2QkFBZCxLQUFnRDNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEa0wsSUFBbEcsS0FDQ3NGLG1CQUFvQixDQUFDQSxlQUFELElBQW9CLEtBQUtqWCxRQUFMLENBQWN5SCxnQkFBbEMsSUFBc0QsQ0FBQzZHLGtCQUQ1RSxDQUFKLEVBQ3NHO0FBQ2xHLGdDQUFRLEtBQUt0TyxRQUFMLENBQWN5Ryw2QkFBdEI7QUFDSSxpQ0FBSzNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEK0ssTUFBdkQsQ0FESixDQUNtRTtBQUMvRCxpQ0FBSzFTLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEOEssSUFBdkQsQ0FGSixDQUVtRTtBQUMvRCxpQ0FBS3pTLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEZ0wsS0FBdkQ7QUFBK0Q7QUFDM0RvRyxnREFBZ0JELDJCQUEyQjFHLGtCQUEzQixHQUFnRGtHLFdBQWhFO0FBQ0E7QUFDSixpQ0FBS3RZLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtENkssTUFBdkQ7QUFBK0Q7QUFDM0R1RyxnREFBZ0IzRyxxQkFBcUJrRyxXQUFyQztBQUNBO0FBUlI7QUFVSCxxQkFaRCxNQVlPO0FBQWdFO0FBQ25FUyx3Q0FBZ0IzRyxxQkFBcUJrRyxXQUFyQztBQUNIO0FBQ0osaUJBaEJNLE1BZ0JBLElBQUksS0FBS3BYLFFBQUwsQ0FBYytFLG9CQUFkLEtBQXVDakcsWUFBWTBDLE9BQVosQ0FBb0J1RCxvQkFBcEIsQ0FBeUMwUyxZQUFwRixFQUFrRztBQUNyRyx3QkFBSSxLQUFLelgsUUFBTCxDQUFjeUcsNkJBQWQsS0FBZ0QzSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRGtMLElBQWxHLEtBQ0NzRixtQkFBb0IsQ0FBQ0EsZUFBRCxJQUFvQixLQUFLalgsUUFBTCxDQUFjeUgsZ0JBQWxDLElBQXNELENBQUM2RyxrQkFENUUsQ0FBSixFQUNzRztBQUNsRyxnQ0FBUSxLQUFLdE8sUUFBTCxDQUFjeUcsNkJBQXRCO0FBQ0ksaUNBQUszSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRCtLLE1BQXZELENBREosQ0FDbUU7QUFDL0QsaUNBQUsxUyxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRDhLLElBQXZELENBRkosQ0FFbUU7QUFDL0QsaUNBQUt6UyxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRGdMLEtBQXZEO0FBQStEO0FBQzNEb0csZ0RBQWdCRCwyQkFBMkIxRyxrQkFBM0IsR0FBZ0RrRyxXQUFoRCxHQUE4REUsaUJBQTlFO0FBQ0E7QUFDSixpQ0FBS3hZLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtENkssTUFBdkQ7QUFBK0Q7QUFDM0R1RyxnREFBZ0IzRyxxQkFBcUJrRyxXQUFyQixHQUFtQ0UsaUJBQW5EO0FBQ0E7QUFSUjtBQVVILHFCQVpELE1BWU87QUFBZ0U7QUFDbkVPLHdDQUFnQjNHLHFCQUFxQmtHLFdBQXJCLEdBQW1DRSxpQkFBbkQ7QUFDSDtBQUNKO0FBQ0osYUFsRUQsTUFrRU8sSUFBSSxLQUFLdFgsUUFBTCxDQUFja0YsdUJBQWQsS0FBMENwRyxZQUFZMEMsT0FBWixDQUFvQjBELHVCQUFwQixDQUE0Q29NLE1BQTFGLEVBQWtHO0FBQ3JHLG9CQUFJLEtBQUt0UixRQUFMLENBQWMrRSxvQkFBZCxLQUF1Q2pHLFlBQVkwQyxPQUFaLENBQW9CdUQsb0JBQXBCLENBQXlDNkYsS0FBcEYsRUFBMkY7QUFDdkYsd0JBQUksS0FBSzVLLFFBQUwsQ0FBY3lHLDZCQUFkLEtBQWdEM0gsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0RrTCxJQUFsRyxLQUNDc0YsbUJBQW9CLENBQUNBLGVBQUQsSUFBb0IsS0FBS2pYLFFBQUwsQ0FBY3lILGdCQUFsQyxJQUFzRCxDQUFDNkcsa0JBRDVFLENBQUosRUFDc0c7QUFDbEcsZ0NBQVEsS0FBS3RPLFFBQUwsQ0FBY3lHLDZCQUF0QjtBQUNJLGlDQUFLM0gsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q2SyxNQUF2RCxDQURKLENBQ21FO0FBQy9ELGlDQUFLeFMsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0RnTCxLQUF2RCxDQUZKLENBRW1FO0FBQy9ELGlDQUFLM1MsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q4SyxJQUF2RDtBQUErRDtBQUMzRHNHLGdEQUFnQixDQUFoQjtBQUNBO0FBQ0osaUNBQUsvWSxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRCtLLE1BQXZEO0FBQStEO0FBQzNEcUcsZ0RBQWdCRCx3QkFBaEI7QUFDQTtBQVJSO0FBVUgscUJBWkQsTUFZTztBQUFnRTtBQUNuRUMsd0NBQWdCLENBQWhCO0FBQ0g7QUFDSixpQkFoQkQsTUFnQk8sSUFBSSxLQUFLN1gsUUFBTCxDQUFjK0Usb0JBQWQsS0FBdUNqRyxZQUFZMEMsT0FBWixDQUFvQnVELG9CQUFwQixDQUF5QytGLEdBQXBGLEVBQXlGO0FBQzVGLHdCQUFJLEtBQUs5SyxRQUFMLENBQWN5Ryw2QkFBZCxLQUFnRDNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEa0wsSUFBbEcsS0FDQ3NGLG1CQUFvQixDQUFDQSxlQUFELElBQW9CLEtBQUtqWCxRQUFMLENBQWN5SCxnQkFBbEMsSUFBc0QsQ0FBQzZHLGtCQUQ1RSxDQUFKLEVBQ3NHO0FBQ2xHLGdDQUFRLEtBQUt0TyxRQUFMLENBQWN5Ryw2QkFBdEI7QUFDSSxpQ0FBSzNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtENkssTUFBdkQsQ0FESixDQUNtRTtBQUMvRCxpQ0FBS3hTLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEZ0wsS0FBdkQsQ0FGSixDQUVtRTtBQUMvRCxpQ0FBSzNTLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEOEssSUFBdkQ7QUFBK0Q7QUFDM0RzRyxnREFBZ0JWLFNBQWhCO0FBQ0E7QUFDSixpQ0FBS3JZLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEK0ssTUFBdkQ7QUFBK0Q7QUFDM0RxRyxnREFBZ0JELDJCQUEyQlQsU0FBM0M7QUFDQTtBQVJSO0FBVUgscUJBWkQsTUFZTztBQUFnRTtBQUNuRVUsd0NBQWdCVixTQUFoQjtBQUNIO0FBQ0osaUJBaEJNLE1BZ0JBLElBQUksS0FBS25YLFFBQUwsQ0FBYytFLG9CQUFkLEtBQXVDakcsWUFBWTBDLE9BQVosQ0FBb0J1RCxvQkFBcEIsQ0FBeUN5UyxXQUFwRixFQUFpRztBQUNwRyx3QkFBSSxLQUFLeFgsUUFBTCxDQUFjeUcsNkJBQWQsS0FBZ0QzSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRGtMLElBQWxHLEtBQ0NzRixtQkFBb0IsQ0FBQ0EsZUFBRCxJQUFvQixLQUFLalgsUUFBTCxDQUFjeUgsZ0JBQWxDLElBQXNELENBQUM2RyxrQkFENUUsQ0FBSixFQUNzRztBQUNsRyxnQ0FBUSxLQUFLdE8sUUFBTCxDQUFjeUcsNkJBQXRCO0FBQ0ksaUNBQUszSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRDZLLE1BQXZELENBREosQ0FDbUU7QUFDL0QsaUNBQUt4UyxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRGdMLEtBQXZELENBRkosQ0FFbUU7QUFDL0QsaUNBQUszUyxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRDhLLElBQXZEO0FBQStEO0FBQzNEc0csZ0RBQWdCVCxXQUFoQjtBQUNBO0FBQ0osaUNBQUt0WSxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRCtLLE1BQXZEO0FBQStEO0FBQzNEcUcsZ0RBQWdCRCwyQkFBMkJSLFdBQTNDO0FBQ0E7QUFSUjtBQVVILHFCQVpELE1BWU87QUFBZ0U7QUFDbkVTLHdDQUFnQlQsV0FBaEI7QUFDSDtBQUNKLGlCQWhCTSxNQWdCQSxJQUFJLEtBQUtwWCxRQUFMLENBQWMrRSxvQkFBZCxLQUF1Q2pHLFlBQVkwQyxPQUFaLENBQW9CdUQsb0JBQXBCLENBQXlDMFMsWUFBcEYsRUFBa0c7QUFDckcsd0JBQUksS0FBS3pYLFFBQUwsQ0FBY3lHLDZCQUFkLEtBQWdEM0gsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0RrTCxJQUFsRyxLQUNDc0YsbUJBQW9CLENBQUNBLGVBQUQsSUFBb0IsS0FBS2pYLFFBQUwsQ0FBY3lILGdCQUFsQyxJQUFzRCxDQUFDNkcsa0JBRDVFLENBQUosRUFDc0c7QUFDbEcsZ0NBQVEsS0FBS3RPLFFBQUwsQ0FBY3lHLDZCQUF0QjtBQUNJLGlDQUFLM0gsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q2SyxNQUF2RCxDQURKLENBQ21FO0FBQy9ELGlDQUFLeFMsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0RnTCxLQUF2RCxDQUZKLENBRW1FO0FBQy9ELGlDQUFLM1MsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q4SyxJQUF2RDtBQUErRDtBQUMzRHNHLGdEQUFnQlQsY0FBY0UsaUJBQTlCO0FBQ0E7QUFDSixpQ0FBS3hZLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEK0ssTUFBdkQ7QUFBK0Q7QUFDM0RxRyxnREFBZ0JELDJCQUEyQlIsV0FBM0IsR0FBeUNFLGlCQUF6RDtBQUNBO0FBUlI7QUFVSCxxQkFaRCxNQVlPO0FBQWdFO0FBQ25FTyx3Q0FBZ0JULGNBQWNFLGlCQUE5QjtBQUNIO0FBQ0o7QUFDSjs7QUFFRCxtQkFBT08sYUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7QUErVkE7Ozs7c0RBSThCO0FBQzFCLGlCQUFLQywyQkFBTCxHQUFtQyxLQUFLOVgsUUFBTCxDQUFjNkYsbUJBQWpEO0FBQ0EsaUJBQUtrUyxzQkFBTCxHQUFtQyxLQUFLL1gsUUFBTCxDQUFjaUYsY0FBakQ7QUFDQSxpQkFBSytTLGtCQUFMLEdBQW1DLEtBQUtoWSxRQUFMLENBQWMySCxVQUFqRDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7QUF5Q0E7Ozs7Ozs7cURBTzZCOUYsSyxFQUFPO0FBQ2hDO0FBQ0EsZ0JBQUlBLFVBQVUsRUFBVixJQUFnQkEsVUFBVSxJQUE5QixFQUFvQztBQUNoQyx1QkFBT0EsS0FBUDtBQUNIOztBQUVELGdCQUFJLEtBQUs3QixRQUFMLENBQWNvRyxXQUFkLEtBQThCdEgsWUFBWTBDLE9BQVosQ0FBb0I0RSxXQUFwQixDQUFnQ3dLLElBQWxFLEVBQXdFO0FBQ3BFLG9CQUFJN0MsT0FBT2xNLEtBQVAsTUFBa0IsQ0FBdEIsRUFBeUI7QUFDckI7QUFDQSwyQkFBTyxHQUFQO0FBQ0g7O0FBRUQ7QUFDQUEsd0JBQVFBLE1BQU02TSxPQUFOLENBQWMsZ0JBQWQsRUFBK0IsSUFBL0IsQ0FBUjtBQUNIOztBQUVEO0FBQ0E7QUFDQSxnQkFBSSw0QkFBa0I2SSxRQUFsQixDQUEyQjFWLEtBQTNCLEVBQWtDLEdBQWxDLENBQUosRUFBNEM7QUFDeENBLHdCQUFRQSxNQUFNNk0sT0FBTixDQUFjLGdCQUFkLEVBQWdDLElBQWhDLENBQVI7QUFDSDs7QUFFRDtBQUNBN00sb0JBQVFBLE1BQU02TSxPQUFOLENBQWMsS0FBZCxFQUFxQixFQUFyQixDQUFSOztBQUVBLG1CQUFPN00sS0FBUDtBQUNIOztBQUVEOzs7Ozs7O29EQUk0QjtBQUN4QixnQkFBSSxLQUFLN0IsUUFBTCxDQUFjbUgseUJBQWxCLEVBQTZDO0FBQ3pDLG9CQUFJLEtBQUtoSSxVQUFMLENBQWdCOFksSUFBaEIsS0FBeUIsRUFBekIsSUFBK0IsQ0FBQyw0QkFBa0J2SyxXQUFsQixDQUE4QixLQUFLdk8sVUFBTCxDQUFnQjhZLElBQTlDLENBQXBDLEVBQXlGO0FBQ3JGLHlCQUFLQyxtQkFBTCxRQUE4QixLQUFLdFgsaUJBQW5DLEdBQXVEdVgsbUJBQW1CLEtBQUtoWixVQUFMLENBQWdCOFksSUFBbkMsQ0FBdkQ7QUFDSCxpQkFGRCxNQUVPO0FBQ0gseUJBQUtDLG1CQUFMLFFBQThCLEtBQUt0WCxpQkFBbkMsR0FBdUQsS0FBS3pCLFVBQUwsQ0FBZ0JpWixFQUF2RTtBQUNIO0FBQ0o7QUFDSjs7QUFFRDs7Ozs7Ozt3REFJZ0M7QUFDNUIsZ0JBQUksS0FBS3BZLFFBQUwsQ0FBY21ILHlCQUFsQixFQUE2QztBQUN6QyxvQkFBSSxLQUFLMUcsdUJBQVQsRUFBa0M7QUFDOUI0WCxtQ0FBZUMsT0FBZixDQUF1QixLQUFLSixtQkFBNUIsRUFBaUQsS0FBS3RULFFBQXREO0FBQ0gsaUJBRkQsTUFFTztBQUNIO0FBQ0FxRiw2QkFBU3NPLE1BQVQsR0FBcUIsS0FBS0wsbUJBQTFCLFNBQWlELEtBQUt0VCxRQUF0RDtBQUNIO0FBQ0o7QUFDSjs7QUFFRDs7Ozs7Ozs7O3lEQU1pQztBQUM3QixnQkFBSSxLQUFLNUUsUUFBTCxDQUFjbUgseUJBQWxCLEVBQTZDO0FBQ3pDLG9CQUFJbkYsZUFBSjtBQUNBLG9CQUFJLEtBQUt2Qix1QkFBVCxFQUFrQztBQUM5QnVCLDZCQUFTcVcsZUFBZUcsT0FBZixDQUF1QixLQUFLTixtQkFBNUIsQ0FBVDtBQUNILGlCQUZELE1BRU87QUFDSGxXLDZCQUFTLEtBQUt5VyxXQUFMLENBQWlCLEtBQUtQLG1CQUF0QixDQUFUO0FBQ0g7O0FBRUQsdUJBQU9sVyxNQUFQO0FBQ0g7O0FBRUQsd0NBQWtCc0QsT0FBbEIsQ0FBMEIsMklBQTFCLEVBQXVLLEtBQUt0RixRQUFMLENBQWN1RixZQUFyTDs7QUFFQSxtQkFBTyxJQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7NERBSW9DO0FBQ2hDLGdCQUFJLEtBQUt2RixRQUFMLENBQWNtSCx5QkFBbEIsRUFBNkM7QUFDekMsb0JBQUksS0FBSzFHLHVCQUFULEVBQWtDO0FBQzlCNFgsbUNBQWVLLFVBQWYsQ0FBMEIsS0FBS1IsbUJBQS9CO0FBQ0gsaUJBRkQsTUFFTztBQUNILHdCQUFNUyxPQUFPLElBQUlDLElBQUosRUFBYjtBQUNBRCx5QkFBS0UsT0FBTCxDQUFhRixLQUFLRyxPQUFMLEtBQWlCLFFBQTlCLEVBRkcsQ0FFc0M7QUFDekMsd0JBQU1DLHlCQUF1QkosS0FBS0ssV0FBTCxFQUE3QjtBQUNBL08sNkJBQVNzTyxNQUFULEdBQXFCLEtBQUtMLG1CQUExQixlQUFxRGEsT0FBckQ7QUFDSDtBQUNKO0FBQ0o7O0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7O2dEQWN3QjNRLEMsRUFBRztBQUN2QixpQkFBS25ILFNBQUwsR0FBaUIsS0FBakIsQ0FEdUIsQ0FDQzs7QUFFeEI7QUFDQTtBQUNBLGdCQUFNZ1ksc0JBQXNCLDRCQUFrQmhKLGVBQWxCLENBQWtDLEtBQUs5USxVQUF2QyxDQUE1Qjs7QUFFQSxnQkFBSSxLQUFLYSxRQUFMLENBQWM0SCxlQUFkLElBQWlDUSxFQUFFOFEsSUFBRixLQUFXLFlBQTVDLElBQTREOVEsRUFBRStRLE1BQWxFLEVBQTBFO0FBQ3RFLHFCQUFLelksV0FBTCxDQUFpQjBZLG1CQUFqQixDQUFxQyxJQUFyQzs7QUFFQTtBQUNIOztBQUVELGdCQUFJaFIsRUFBRThRLElBQUYsS0FBVyxPQUFmLEVBQXdCO0FBQUU7QUFDdEI7QUFDQSxxQkFBS3BZLFNBQUwsR0FBaUIsSUFBakI7QUFDSDs7QUFFRCxnQkFBSXNILEVBQUU4USxJQUFGLEtBQVcsT0FBWCxJQUFzQixLQUFLbFosUUFBTCxDQUFjNEgsZUFBcEMsSUFBdUQsS0FBS3lSLGNBQWhFLEVBQWdGO0FBQzVFLHFCQUFLM1ksV0FBTCxDQUFpQjRZLG1CQUFqQixDQUFxQyxJQUFyQztBQUNIOztBQUVELGdCQUFJbFIsRUFBRThRLElBQUYsS0FBVyxPQUFYLElBQXNCOVEsRUFBRThRLElBQUYsS0FBVyxZQUFYLElBQTJCLENBQUMsS0FBS3BZLFNBQTNELEVBQXNFO0FBQ2xFLG9CQUFJLEtBQUtkLFFBQUwsQ0FBYytGLGtCQUFkLEtBQXFDakgsWUFBWTBDLE9BQVosQ0FBb0J1RSxrQkFBcEIsQ0FBdUN5TixLQUE1RSxJQUNBLEtBQUs1TyxRQUFMLEdBQWdCLENBRGhCLElBQ3FCLEtBQUs1RSxRQUFMLENBQWN3RywwQkFBZCxLQUE2QyxJQURsRSxJQUMwRSxLQUFLeEcsUUFBTCxDQUFjK1cscUJBQWQsS0FBd0MsRUFEdEgsRUFDMEg7QUFBRTtBQUN4SDtBQUNBLGdEQUFrQjdHLGVBQWxCLENBQWtDLEtBQUsvUSxVQUF2QyxFQUFtRCxLQUFLdUIsV0FBTCxDQUFpQjhPLGVBQWpCLENBQWlDLDRCQUFrQlMsZUFBbEIsQ0FBa0MsS0FBSzlRLFVBQXZDLENBQWpDLEVBQXFGLEtBQUthLFFBQTFGLENBQW5EO0FBQ0g7O0FBRUQ7QUFDQSxvQkFBTXVaLG1CQUFtQixLQUFLNUssb0JBQUwsQ0FBMEIsS0FBSy9KLFFBQS9CLENBQXpCOztBQUVBO0FBQ0Esb0JBQUkyVSxxQkFBcUIsRUFBekIsRUFBNkI7QUFDekI7QUFDQSx3QkFBSUMscUJBQUo7QUFDQSx3QkFBSSxLQUFLMVksU0FBVCxFQUFvQjtBQUNoQjBZLHVDQUFlLEtBQUs5WSxXQUFMLENBQWlCa08sZ0NBQWpCLENBQWtEMkssZ0JBQWxELEVBQW9FLEtBQUt2WixRQUF6RSxDQUFmO0FBQ0gscUJBRkQsTUFFTztBQUNId1osdUNBQWUsS0FBSzlZLFdBQUwsQ0FBaUJvTywrQkFBakIsQ0FBaUR5SyxnQkFBakQsRUFBbUUsS0FBS3ZaLFFBQXhFLENBQWY7QUFDSDs7QUFFRCx3QkFBSSxLQUFLQSxRQUFMLENBQWN3SCxzQkFBZCxLQUF5QzFJLFlBQVkwQyxPQUFaLENBQW9CZ0csc0JBQXBCLENBQTJDaVMsV0FBeEYsRUFBcUc7QUFDakc7QUFDQSw2QkFBS3paLFFBQUwsQ0FBYzZGLG1CQUFkLEdBQW9DLEVBQXBDO0FBQ0EsNkJBQUs3RixRQUFMLENBQWNpRixjQUFkLEdBQW9DLEVBQXBDO0FBQ0EsNkJBQUtqRixRQUFMLENBQWMySCxVQUFkLEdBQW9DLEVBQXBDO0FBQ0Esb0RBQWtCdUksZUFBbEIsQ0FBa0MsS0FBSy9RLFVBQXZDLEVBQW1EcWEsYUFBYTlLLE9BQWIsQ0FBcUIsR0FBckIsRUFBMEIsS0FBSzFPLFFBQUwsQ0FBY21GLGdCQUF4QyxDQUFuRDtBQUNILHFCQU5ELE1BTU87QUFDSCw0QkFBSXVVLHVCQUFKO0FBQ0EsNEJBQUksNEJBQWtCelIsTUFBbEIsQ0FBeUJ1UixZQUF6QixDQUFKLEVBQTRDO0FBQ3hDRSw2Q0FBaUIsRUFBakI7QUFDSCx5QkFGRCxNQUVPO0FBQ0hBLDZDQUFpQixLQUFLaFosV0FBTCxDQUFpQnNPLG1CQUFqQixDQUFxQ3dLLGFBQWE5SyxPQUFiLENBQXFCLEdBQXJCLEVBQTBCLEtBQUsxTyxRQUFMLENBQWNtRixnQkFBeEMsQ0FBckMsRUFBZ0csS0FBS25GLFFBQXJHLEVBQStHLEtBQUtjLFNBQXBILEVBQStIeVksZ0JBQS9ILENBQWpCO0FBQ0g7QUFDRCxvREFBa0JySixlQUFsQixDQUFrQyxLQUFLL1EsVUFBdkMsRUFBbUR1YSxjQUFuRDtBQUNIO0FBQ0o7O0FBRUQ7QUFDQSxxQkFBS0MsWUFBTCxHQUFvQiw0QkFBa0IxSixlQUFsQixDQUFrQzdILEVBQUV3UixNQUFwQyxDQUFwQjtBQUNBLHFCQUFLQyxPQUFMLEdBQWUsS0FBS0YsWUFBcEI7QUFDQSxvQkFBTUcsZUFBZSxLQUFLcFosV0FBTCxDQUFpQnFaLHlDQUFqQixDQUEyRCxLQUFLSixZQUFoRSxFQUE4RSxLQUFLM1osUUFBbkYsQ0FBckI7QUFDQSxvQkFBTWdhLGVBQWUsS0FBS3RaLFdBQUwsQ0FBaUJ1WixzQ0FBakIsQ0FBd0QsS0FBS04sWUFBN0QsRUFBMkUsS0FBSzNaLFFBQWhGLEVBQTBGLElBQTFGLENBQXJCLENBekNrRSxDQXlDb0Q7QUFDdEgsb0JBQUs4WixnQkFBZ0JFLGlCQUFpQixFQUFsQyxJQUF5QyxLQUFLaGEsUUFBTCxDQUFjK0Ysa0JBQWQsS0FBcUNqSCxZQUFZMEMsT0FBWixDQUFvQnVFLGtCQUFwQixDQUF1Q3lOLEtBQXpILEVBQWdJO0FBQzVILGdEQUFrQnRELGVBQWxCLENBQWtDLEtBQUsvUSxVQUF2QyxFQUFtRDZhLFlBQW5EOztBQUVBO0FBQ0Esd0JBQUlBLGlCQUFpQixLQUFLaGEsUUFBTCxDQUFjaUYsY0FBL0IsSUFBaUQsS0FBS2pGLFFBQUwsQ0FBY2tGLHVCQUFkLEtBQTBDcEcsWUFBWTBDLE9BQVosQ0FBb0IwRCx1QkFBcEIsQ0FBNENvTSxNQUEzSSxFQUFtSjtBQUMvSSxvREFBa0JuRyxtQkFBbEIsQ0FBc0MvQyxFQUFFd1IsTUFBeEMsRUFBZ0QsQ0FBaEQ7QUFDSDtBQUNKO0FBQ0o7O0FBRUQsZ0JBQUksNEJBQWtCM0osZUFBbEIsQ0FBa0MsS0FBSzlRLFVBQXZDLE1BQXVEOFosbUJBQTNELEVBQWdGO0FBQzVFLDRDQUFrQmhLLFlBQWxCLENBQStCblEsWUFBWW9RLE1BQVosQ0FBbUJpQixTQUFsRCxFQUE2RCxLQUFLaFIsVUFBbEUsRUFBOEUsRUFBRWlSLFVBQVU2SSxtQkFBWixFQUFpQzFYLFVBQVUsNEJBQWtCME8sZUFBbEIsQ0FBa0MsS0FBSzlRLFVBQXZDLENBQTNDLEVBQTlFO0FBQ0g7QUFDSjs7QUFFRDs7Ozs7Ozs7bUNBS1c7QUFDUCxnQkFBSSxLQUFLYSxRQUFMLENBQWNtRyxhQUFsQixFQUFpQztBQUM3QjtBQUNBLHFCQUFLK1QscUJBQUw7QUFDSDtBQUNKOztBQUVEOzs7Ozs7Ozs7O21DQU9XOVIsQyxFQUFHO0FBQ1YsZ0JBQUksS0FBS3BJLFFBQUwsQ0FBY3NILGFBQWxCLEVBQWlDO0FBQzdCO0FBQ0E7QUFDQSxxQkFBSzZTLE1BQUw7QUFDSCxhQUpELE1BSU87QUFDSDtBQUNBLDRDQUFrQmhQLG1CQUFsQixDQUFzQy9DLEVBQUV3UixNQUF4QyxFQUFnRCxLQUFLUSxxQkFBTCxDQUEyQiw0QkFBa0JuSyxlQUFsQixDQUFrQyxLQUFLOVEsVUFBdkMsQ0FBM0IsQ0FBaEQ7QUFDSDtBQUNKOztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7bUNBMENXaUosQyxFQUFHO0FBQ1YsaUJBQUtuSCxTQUFMLEdBQWlCLElBQWpCLENBRFUsQ0FDYTs7QUFFdkIsZ0JBQUksQ0FBQyxLQUFLSCxTQUFOLElBQW1CLEtBQUtkLFFBQUwsQ0FBYzRILGVBQWpDLElBQW9EUSxFQUFFK1EsTUFBdEQsSUFBZ0UsS0FBS2hhLFVBQUwsS0FBb0IsNEJBQWtCa2IsaUJBQWxCLEVBQXhGLEVBQStIO0FBQzNIO0FBQ0EscUJBQUszWixXQUFMLENBQWlCMFksbUJBQWpCLENBQXFDLElBQXJDOztBQUVBO0FBQ0g7O0FBRUQsaUJBQUtrQixtQkFBTCxDQUF5QmxTLENBQXpCO0FBQ0EsaUJBQUttUyxxQkFBTCxHQUE2Qiw0QkFBa0J0SyxlQUFsQixDQUFrQzdILEVBQUV3UixNQUFwQyxDQUE3QixDQVhVLENBV2dFOztBQUUxRSxnQkFBSSxLQUFLemEsVUFBTCxDQUFnQjhILFFBQXBCLEVBQThCO0FBQzFCLHFCQUFLdVQsU0FBTCxHQUFpQixJQUFqQjs7QUFFQTtBQUNIOztBQUVELGdCQUFJLEtBQUtDLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QkMsR0FBOUMsRUFBbUQ7QUFDL0M7QUFDQXZTLGtCQUFFd1MsY0FBRjs7QUFFQSxvQkFBSSxLQUFLNWEsUUFBTCxDQUFjbUcsYUFBbEIsRUFBaUM7QUFDN0I7QUFDQTtBQUNBLHdCQUFJLEtBQUt2QixRQUFMLEtBQWtCLEtBQUtuRixxQkFBM0IsRUFBa0Q7QUFDOUM7QUFDQSw2QkFBSzZCLEdBQUwsQ0FBUyxLQUFLN0IscUJBQWQ7QUFDQTtBQUNBLG9EQUFrQndQLFlBQWxCLENBQStCblEsWUFBWW9RLE1BQVosQ0FBbUIyTCxNQUFuQixDQUEwQmpHLEtBQXpELEVBQWdFeE0sRUFBRXdSLE1BQWxFO0FBQ0g7QUFDSjs7QUFFRDtBQUNBLHFCQUFLTyxNQUFMO0FBQ0E7QUFDSDs7QUFFRDtBQUNBLGdCQUFJVyxjQUFjLDRCQUFrQjdLLGVBQWxCLENBQWtDN0gsRUFBRXdSLE1BQXBDLENBQWxCO0FBQ0EsZ0JBQUksS0FBS2EsUUFBTCxLQUFrQiwwQkFBZ0JDLE9BQWhCLENBQXdCSyxLQUExQyxJQUFtRCxLQUFLcEIsWUFBTCxLQUFzQm1CLFdBQTdFLEVBQTBGO0FBQ3RGLDRDQUFrQjdMLFlBQWxCLENBQStCblEsWUFBWW9RLE1BQVosQ0FBbUIyTCxNQUFuQixDQUEwQkcsTUFBekQsRUFBaUU1UyxFQUFFd1IsTUFBbkU7QUFDQSxxQkFBS0QsWUFBTCxHQUFvQm1CLFdBQXBCOztBQUVBLG9CQUFJLEtBQUs5YSxRQUFMLENBQWNtRyxhQUFsQixFQUFpQztBQUM3QjtBQUNBLHlCQUFLK1QscUJBQUw7QUFDSDtBQUNKOztBQUVELGlCQUFLZSx5QkFBTCxDQUErQjdTLENBQS9COztBQUVBLGdCQUFJLEtBQUs4UyxvQ0FBTCxDQUEwQzlTLENBQTFDLENBQUosRUFBa0Q7QUFDOUMscUJBQUtvUyxTQUFMLEdBQWlCLElBQWpCOztBQUVBO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBSSxLQUFLQyxRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0JTLFNBQTFDLElBQXVELEtBQUtWLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QlUsTUFBckcsRUFBNkc7QUFDekcscUJBQUtDLHlCQUFMLEdBRHlHLENBQ3ZFO0FBQ2xDLHFCQUFLYixTQUFMLEdBQWlCLElBQWpCO0FBQ0EscUJBQUtjLFlBQUwsQ0FBa0JsVCxDQUFsQjs7QUFFQTtBQUNBMFMsOEJBQWMsNEJBQWtCN0ssZUFBbEIsQ0FBa0M3SCxFQUFFd1IsTUFBcEMsQ0FBZCxDQU55RyxDQU05QztBQUMzRCxvQkFBS2tCLGdCQUFnQixLQUFLakIsT0FBdEIsSUFBa0MsS0FBSzBCLFVBQTNDLEVBQXVEO0FBQ25EO0FBQ0EsZ0RBQWtCdE0sWUFBbEIsQ0FBK0JuUSxZQUFZb1EsTUFBWixDQUFtQjJMLE1BQW5CLENBQTBCakcsS0FBekQsRUFBZ0V4TSxFQUFFd1IsTUFBbEU7QUFDQXhSLHNCQUFFd1MsY0FBRixHQUhtRCxDQUcvQjtBQUN2Qjs7QUFFRCxxQkFBS2YsT0FBTCxHQUFlaUIsV0FBZjtBQUNBLHFCQUFLUyxVQUFMLEdBQWtCLElBQWxCOztBQUVBO0FBQ0g7O0FBRUQsaUJBQUtwTCxTQUFMLEdBQWlCLEtBQWpCLENBL0VVLENBK0VjO0FBQzNCOztBQUVEOzs7Ozs7Ozs7O29DQU9ZL0gsQyxFQUFHO0FBQ1gsZ0JBQUksS0FBS3FTLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QmMsTUFBOUMsRUFBc0Q7QUFDbEQ7QUFDSDs7QUFFRCxnQkFBTWhCLFlBQVksS0FBS0EsU0FBdkI7QUFDQSxpQkFBS1MseUJBQUwsQ0FBK0I3UyxDQUEvQjs7QUFFQSxnQkFBSSxLQUFLOFMsb0NBQUwsQ0FBMEM5UyxDQUExQyxDQUFKLEVBQWtEO0FBQzlDO0FBQ0g7O0FBRUQsZ0JBQUlvUyxTQUFKLEVBQWU7QUFDWHBTLGtCQUFFd1MsY0FBRjs7QUFFQTtBQUNIOztBQUVELGdCQUFNYSw4QkFBOEIsS0FBS0MsMEJBQUwsRUFBcEM7QUFDQSxnQkFBSUQsMkJBQUosRUFBaUM7QUFDN0IscUJBQUtILFlBQUwsQ0FBa0JsVCxDQUFsQjtBQUNBLG9CQUFNMFMsY0FBYyw0QkFBa0I3SyxlQUFsQixDQUFrQzdILEVBQUV3UixNQUFwQyxDQUFwQjtBQUNBLG9CQUFLa0IsZ0JBQWdCLEtBQUtqQixPQUF0QixJQUFrQyxLQUFLMEIsVUFBM0MsRUFBdUQ7QUFDbkQ7QUFDQSxnREFBa0J0TSxZQUFsQixDQUErQm5RLFlBQVlvUSxNQUFaLENBQW1CMkwsTUFBbkIsQ0FBMEJqRyxLQUF6RCxFQUFnRXhNLEVBQUV3UixNQUFsRTtBQUNBeFIsc0JBQUV3UyxjQUFGLEdBSG1ELENBRy9CO0FBQ3ZCLGlCQUpELE1BSU87QUFDSCx3QkFBSSxDQUFDLEtBQUtILFFBQUwsS0FBa0IsS0FBS3phLFFBQUwsQ0FBY21GLGdCQUFoQyxJQUFvRCxLQUFLc1YsUUFBTCxLQUFrQixLQUFLemEsUUFBTCxDQUFjb0YsMkJBQXJGLEtBQ0MsNEJBQWtCc0YsbUJBQWxCLENBQXNDdEMsRUFBRXdSLE1BQXhDLEVBQWdEaFAsS0FBaEQsS0FBMEQsNEJBQWtCRixtQkFBbEIsQ0FBc0N0QyxFQUFFd1IsTUFBeEMsRUFBZ0Q5TyxHQUQzRyxJQUVBLDRCQUFrQkosbUJBQWxCLENBQXNDdEMsRUFBRXdSLE1BQXhDLEVBQWdEaFAsS0FBaEQsS0FBMERrUSxZQUFZakosT0FBWixDQUFvQixLQUFLN1IsUUFBTCxDQUFjbUYsZ0JBQWxDLENBRjlELEVBRW1IO0FBQy9HLDRCQUFNd1csV0FBVyw0QkFBa0JqUixtQkFBbEIsQ0FBc0N0QyxFQUFFd1IsTUFBeEMsRUFBZ0RoUCxLQUFoRCxHQUF3RCxDQUF6RTtBQUNBLG9EQUFrQk8sbUJBQWxCLENBQXNDL0MsRUFBRXdSLE1BQXhDLEVBQWdEK0IsUUFBaEQ7QUFDSDs7QUFFRHZULHNCQUFFd1MsY0FBRjtBQUNIOztBQUVELHFCQUFLZixPQUFMLEdBQWUsNEJBQWtCNUosZUFBbEIsQ0FBa0M3SCxFQUFFd1IsTUFBcEMsQ0FBZjtBQUNBLHFCQUFLMkIsVUFBTCxHQUFrQixJQUFsQjs7QUFFQTtBQUNIOztBQUVEblQsY0FBRXdTLGNBQUY7O0FBRUEsaUJBQUt6SyxTQUFMLEdBQWlCLEtBQWpCLENBN0NXLENBNkNhO0FBQzNCOztBQUVEOzs7Ozs7Ozs7aUNBTVMvSCxDLEVBQUc7QUFDUixnQkFBTXZHLFFBQVEsNEJBQWtCb08sZUFBbEIsQ0FBa0MsS0FBSzlRLFVBQXZDLENBQWQ7O0FBRUE7QUFDQSxpQkFBS3ljLHFCQUFMLEdBQTZCLElBQTdCOztBQUVBLGdCQUFJLEtBQUtuQixRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0JtQixjQUE5QyxFQUE4RDtBQUMxRCxvQkFBSXBSLFlBQVksNEJBQWtCQyxtQkFBbEIsQ0FBc0MsS0FBS3ZMLFVBQTNDLENBQWhCO0FBQ0E7QUFDQSxvQkFBSTBDLE1BQU11SSxNQUFOLEdBQWUsS0FBS3lQLE9BQUwsQ0FBYXpQLE1BQTVCLElBQXNDdkksTUFBTXVJLE1BQU4sSUFBZ0IsS0FBS3lQLE9BQUwsQ0FBYXpQLE1BQWIsR0FBc0JLLFVBQVVMLE1BQTFGLEVBQWtHO0FBQzlGO0FBQ0EseUJBQUtxUSxRQUFMLEdBQWdCNVksTUFBTWlhLFVBQU4sQ0FBaUJyUixVQUFVRyxLQUEzQixDQUFoQjs7QUFFQTtBQUNBLHlCQUFLNlAsUUFBTCxHQUFnQjVZLE1BQU1rYSxNQUFOLENBQWF0UixVQUFVRyxLQUF2QixDQUFoQjs7QUFFQTtBQUNBLHdCQUFNNlEsOEJBQThCLEtBQUtDLDBCQUFMLEVBQXBDOztBQUVBLHdCQUFJRCwyQkFBSixFQUFpQztBQUM3QjtBQUNBLDZCQUFLSCxZQUFMLENBQWtCbFQsQ0FBbEI7O0FBRUFxQyxvQ0FBWSw0QkFBa0JDLG1CQUFsQixDQUFzQyxLQUFLdkwsVUFBM0MsQ0FBWixDQUo2QixDQUl1QztBQUNwRTtBQUNBO0FBQ0EsNkJBQUt5YyxxQkFBTCxHQUE2Qm5SLFVBQVVHLEtBQXZDOztBQUVBO0FBQ0EsNEJBQU1vUiwyQkFBMkIsNEJBQWtCL0wsZUFBbEIsQ0FBa0MsS0FBSzlRLFVBQXZDLEVBQW1EMFMsT0FBbkQsQ0FBMkQsS0FBSzdSLFFBQUwsQ0FBY21GLGdCQUF6RSxDQUFqQztBQUNBLDRCQUFNOFcsc0JBQXNCRCw2QkFBNkIsQ0FBQyxDQUExRDtBQUNBLDRCQUFJLEtBQUt2QixRQUFMLEtBQWtCLEtBQUt6YSxRQUFMLENBQWNtRixnQkFBaEMsSUFDQThXLHVCQUF1QkQsMkJBQTJCLEtBQUtKLHFCQUQzRCxFQUNrRjtBQUM5RSxpQ0FBS0EscUJBQUwsSUFBOEIsS0FBSzViLFFBQUwsQ0FBY21GLGdCQUFkLENBQStCaUYsTUFBN0Q7QUFDSDs7QUFFRCw0QkFBSSxLQUFLcEssUUFBTCxDQUFja0YsdUJBQWQsS0FBMENwRyxZQUFZMEMsT0FBWixDQUFvQjBELHVCQUFwQixDQUE0Q3NNLE1BQXRGLElBQWdHLEtBQUt4UixRQUFMLENBQWNpRixjQUFkLENBQTZCbUYsTUFBakksRUFBeUk7QUFDckksaUNBQUt3UixxQkFBTCxJQUE4QixLQUFLNWIsUUFBTCxDQUFjaUYsY0FBZCxDQUE2Qm1GLE1BQTNEO0FBQ0g7O0FBRUQsNEJBQUlLLFVBQVVMLE1BQVYsR0FBbUJ2SSxNQUFNdUksTUFBN0IsRUFBcUM7QUFDakM7QUFDQSxpQ0FBSzhSLGlCQUFMLENBQXVCLEtBQUtOLHFCQUE1QjtBQUNIOztBQUVELDZCQUFLL0IsT0FBTCxHQUFlLDRCQUFrQjVKLGVBQWxCLENBQWtDLEtBQUs5USxVQUF2QyxDQUFmOztBQUVBO0FBQ0gscUJBN0JELE1BNkJPO0FBQ0g7QUFDQSxvREFBa0IrUSxlQUFsQixDQUFrQyxLQUFLMkosT0FBdkMsRUFGRyxDQUU4QztBQUNqRCxvREFBa0IxTyxtQkFBbEIsQ0FBc0MsS0FBS2hNLFVBQTNDLEVBQXVEc0wsVUFBVUcsS0FBakUsRUFBd0VILFVBQVVLLEdBQWxGO0FBQ0EsNkJBQUs4USxxQkFBTCxHQUE2Qm5SLFVBQVVHLEtBQXZDO0FBQ0g7O0FBRUR4QyxzQkFBRXdTLGNBQUYsR0E5QzhGLENBOEMxRTs7QUFFcEIseUJBQUt6SyxTQUFMLEdBQWlCLEtBQWpCO0FBQ0gsaUJBakRELE1BaURPO0FBQ0g7QUFDQTtBQUNBLHlCQUFLc0ssUUFBTCxHQUFnQiwwQkFBZ0JDLE9BQWhCLENBQXdCUyxTQUF4QztBQUNIO0FBQ0o7QUFDSjs7QUFFRDs7Ozs7Ozs7O2lDQU1TL1MsQyxFQUFHO0FBQ1IsaUJBQUtuSCxTQUFMLEdBQWlCLEtBQWpCOztBQUVBLGdCQUFJLEtBQUtqQixRQUFMLENBQWNtRyxhQUFkLElBQStCLEtBQUtzVSxRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0JDLEdBQTdFLEVBQWtGO0FBQzlFO0FBQ0F2UyxrQkFBRXdTLGNBQUY7O0FBRUE7QUFDSDs7QUFFRDtBQUNBLGdCQUFJLEtBQUtILFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QnlCLENBQTFDLElBQStDLEtBQUsxQixRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0IwQixDQUE3RixFQUFnRztBQUM1RixvQkFBSWhVLEVBQUVpVSxPQUFGLElBQWFqVSxFQUFFa1UsUUFBbkIsRUFBNkI7QUFDekI7QUFDQWxVLHNCQUFFd1MsY0FBRjtBQUNBLHlCQUFLMkIsaUJBQUw7QUFDQSx5QkFBSzNjLFdBQUwsR0FBbUIsSUFBbkI7O0FBRUE7QUFDSCxpQkFQRCxNQU9PLElBQUl3SSxFQUFFaVUsT0FBRixJQUFhLENBQUNqVSxFQUFFa1UsUUFBcEIsRUFBOEI7QUFDakMsd0JBQUksS0FBSzFjLFdBQVQsRUFBc0I7QUFDbEI7QUFDQSw2QkFBS0EsV0FBTCxHQUFtQixLQUFuQjtBQUNILHFCQUhELE1BR087QUFDSHdJLDBCQUFFd1MsY0FBRjtBQUNBO0FBQ0EsNkJBQUs0QixpQkFBTDs7QUFFQTtBQUNIO0FBQ0o7QUFDSjs7QUFFRCxnQkFBSSxLQUFLNWMsV0FBTCxLQUFxQndJLEVBQUVpVSxPQUFGLElBQWFqVSxFQUFFa1UsUUFBcEMsQ0FBSixFQUFtRDtBQUMvQztBQUNBLHFCQUFLMWMsV0FBTCxHQUFtQixLQUFuQjtBQUNIOztBQUVEO0FBQ0EsZ0JBQUksS0FBSzZhLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QitCLEdBQTFDLElBQWlELEtBQUtwRCxjQUExRCxFQUEwRTtBQUN0RSxxQkFBSzNZLFdBQUwsQ0FBaUI0WSxtQkFBakIsQ0FBcUMsSUFBckM7O0FBRUE7QUFDSDs7QUFFRCxpQkFBSzJCLHlCQUFMLENBQStCN1MsQ0FBL0I7O0FBRUEsZ0JBQU1zVSxPQUFPLEtBQUt4QixvQ0FBTCxDQUEwQzlTLENBQTFDLENBQWI7QUFDQSxtQkFBTyxLQUFLdVUscUJBQVo7QUFDQSxnQkFBTUMsY0FBYyxLQUFLaEIscUJBQUwsS0FBK0IsSUFBbkQ7QUFDQSxnQkFBTWQsY0FBYyw0QkFBa0I3SyxlQUFsQixDQUFrQzdILEVBQUV3UixNQUFwQyxDQUFwQjtBQUNBLGdCQUFJOEMsUUFBUSxDQUFDRSxXQUFULElBQXdCOUIsZ0JBQWdCLEVBQTVDLEVBQWdEO0FBQzVDO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBSUEsZ0JBQWdCLEtBQUs5YSxRQUFMLENBQWNpRixjQUFsQyxFQUFrRDtBQUM5QyxvQkFBSSxLQUFLakYsUUFBTCxDQUFja0YsdUJBQWQsS0FBMENwRyxZQUFZMEMsT0FBWixDQUFvQjBELHVCQUFwQixDQUE0Q29NLE1BQTFGLEVBQWtHO0FBQzlGLGdEQUFrQm5HLG1CQUFsQixDQUFzQy9DLEVBQUV3UixNQUF4QyxFQUFnRCxDQUFoRDtBQUNILGlCQUZELE1BRU87QUFDSCxnREFBa0J6TyxtQkFBbEIsQ0FBc0MvQyxFQUFFd1IsTUFBeEMsRUFBZ0QsS0FBSzVaLFFBQUwsQ0FBY2lGLGNBQWQsQ0FBNkJtRixNQUE3RTtBQUNIO0FBQ0osYUFORCxNQU1PLElBQUksS0FBS3FRLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3Qm1DLEdBQTlDLEVBQW1EO0FBQ3RELDRDQUFrQjFSLG1CQUFsQixDQUFzQy9DLEVBQUV3UixNQUF4QyxFQUFnRCxDQUFoRCxFQUFtRGtCLFlBQVkxUSxNQUEvRDtBQUNIOztBQUVELGdCQUFLMFEsZ0JBQWdCLEtBQUs5YSxRQUFMLENBQWMySCxVQUEvQixJQUNDLEtBQUsvQyxRQUFMLEtBQWtCLEVBQWxCLElBQXdCLEtBQUs1RSxRQUFMLENBQWNpRixjQUFkLEtBQWlDLEVBQXpELElBQStELEtBQUtqRixRQUFMLENBQWMySCxVQUFkLEtBQTZCLEVBRGpHLEVBQ3NHO0FBQ2xHLDRDQUFrQndELG1CQUFsQixDQUFzQy9DLEVBQUV3UixNQUF4QyxFQUFnRCxDQUFoRDtBQUNIOztBQUVEO0FBQ0EsZ0JBQUksS0FBSzVaLFFBQUwsQ0FBYzBGLHlCQUFkLEtBQTRDLElBQWhELEVBQXNEO0FBQ2xELHFCQUFLa0ksNkJBQUw7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLEtBQUt1QyxTQUFWLEVBQXFCO0FBQUc7QUFDcEIscUJBQUttTCxZQUFMLENBQWtCbFQsQ0FBbEI7QUFDSDs7QUFFRDtBQUNBLGdCQUFJMFMsZ0JBQWdCLEtBQUtQLHFCQUF6QixFQUFnRDtBQUM1Qyw0Q0FBa0J0TCxZQUFsQixDQUErQm5RLFlBQVlvUSxNQUFaLENBQW1CaUIsU0FBbEQsRUFBNkQvSCxFQUFFd1IsTUFBL0QsRUFBdUUsRUFBRXhKLFVBQVUsS0FBS21LLHFCQUFqQixFQUF3Q2haLFVBQVV1WixXQUFsRCxFQUF2RSxFQUQ0QyxDQUM2RjtBQUM1STs7QUFFRDtBQUNBLGdCQUFJLEtBQUtwYixZQUFMLENBQWtCMEssTUFBbEIsR0FBMkIsQ0FBL0IsRUFBa0M7QUFDOUIsb0JBQU1LLFlBQVksNEJBQWtCQyxtQkFBbEIsQ0FBc0MsS0FBS3ZMLFVBQTNDLENBQWxCO0FBQ0EscUJBQUt3TCxjQUFMLEdBQXNCRixVQUFVRyxLQUFoQztBQUNBLHFCQUFLQyxZQUFMLEdBQW9CSixVQUFVSyxHQUE5QjtBQUNBLHFCQUFLcEwsWUFBTCxDQUFrQixLQUFLQyxpQkFBdkIsRUFBMENpTCxLQUExQyxHQUFrRCxLQUFLRCxjQUF2RDtBQUNBLHFCQUFLakwsWUFBTCxDQUFrQixLQUFLQyxpQkFBdkIsRUFBMENtTCxHQUExQyxHQUFnRCxLQUFLRCxZQUFyRDtBQUNIO0FBQ0o7O0FBRUQ7Ozs7Ozs7Ozs7Ozs7O2lEQVd5QnpDLEMsRUFBRztBQUN4QixpQkFBS25ILFNBQUwsR0FBaUIsS0FBakIsQ0FEd0IsQ0FDQTs7QUFFeEI7QUFDQTtBQUNBLGdCQUFJLEtBQUtqQixRQUFMLENBQWM0SCxlQUFkLElBQWlDUSxFQUFFOFEsSUFBRixLQUFXLFlBQTVDLElBQTRELEtBQUtHLGNBQXJFLEVBQXFGO0FBQ2pGLHFCQUFLM1ksV0FBTCxDQUFpQjRZLG1CQUFqQixDQUFxQyxJQUFyQzs7QUFFQTtBQUNIOztBQUVELGdCQUFLbFIsRUFBRThRLElBQUYsS0FBVyxZQUFYLElBQTJCLENBQUMsS0FBS3BZLFNBQWxDLElBQWdEc0gsRUFBRThRLElBQUYsS0FBVyxNQUEvRCxFQUF1RTtBQUNuRSxxQkFBS3RMLDZCQUFMO0FBQ0Esb0JBQUksS0FBSzVOLFFBQUwsQ0FBY3dILHNCQUFkLEtBQXlDMUksWUFBWTBDLE9BQVosQ0FBb0JnRyxzQkFBcEIsQ0FBMkNpUyxXQUF4RixFQUFxRztBQUNqRyx5QkFBS3paLFFBQUwsQ0FBYzZGLG1CQUFkLEdBQW9DLEtBQUtpUywyQkFBekM7QUFDQSx5QkFBSzlYLFFBQUwsQ0FBY2lGLGNBQWQsR0FBK0IsS0FBSzhTLHNCQUFwQztBQUNBLHlCQUFLL1gsUUFBTCxDQUFjMkgsVUFBZCxHQUEyQixLQUFLcVEsa0JBQWhDO0FBQ0g7O0FBRUQ7QUFDQSxvQkFBTXVCLG1CQUFtQixLQUFLNUssb0JBQUwsQ0FBMEIsS0FBSy9KLFFBQS9CLENBQXpCOztBQUVBLG9CQUFJL0MsY0FBSjtBQUNBLG9CQUFNaWIsaUJBQWlCLDRCQUFrQjdVLE1BQWxCLENBQXlCc1IsZ0JBQXpCLENBQXZCO0FBQ0Esb0JBQUl1RCxrQkFBa0J2RCxxQkFBcUIsRUFBM0MsRUFBK0M7QUFDM0MxWCw0QkFBUTBYLGdCQUFSO0FBQ0gsaUJBRkQsTUFFTztBQUNIMVgsNEJBQVFrYixPQUFPeEQsZ0JBQVAsQ0FBUjtBQUNIOztBQUVELG9CQUFJQSxxQkFBcUIsRUFBckIsSUFBMkIsQ0FBQ3VELGNBQWhDLEVBQWdEO0FBQUEsaURBQ2pCLEtBQUtwYyxXQUFMLENBQWlCd04saUNBQWpCLENBQW1EcUwsZ0JBQW5ELEVBQXFFLEtBQUt2WixRQUExRSxDQURpQjtBQUFBO0FBQUEsd0JBQ3JDbU8sT0FEcUM7QUFBQSx3QkFDNUJDLE9BRDRCOztBQUU1Qyx3QkFBSUQsV0FBV0MsT0FBWCxJQUFzQixDQUFDLEtBQUsxTixXQUFMLENBQWlCcVoseUNBQWpCLENBQTJEUixnQkFBM0QsRUFBNkUsS0FBS3ZaLFFBQWxGLENBQTNCLEVBQXdIO0FBQ3BINkIsZ0NBQVEsS0FBS21iLGlEQUFMLENBQXVEbmIsS0FBdkQsQ0FBUjs7QUFFQSw0QkFBSSxLQUFLN0IsUUFBTCxDQUFjOEYsb0JBQWQsSUFBc0MsQ0FBQyw0QkFBa0JtQyxNQUFsQixDQUF5QnBHLEtBQXpCLENBQTNDLEVBQTRFO0FBQ3hFQSxvQ0FBUUEsUUFBUSxLQUFLN0IsUUFBTCxDQUFjOEYsb0JBQTlCO0FBQ0FqRSxvQ0FBUUEsTUFBTWdOLFFBQU4sRUFBUjtBQUNIOztBQUVEaE4sZ0NBQVEsS0FBS25CLFdBQUwsQ0FBaUJvTywrQkFBakIsQ0FBaURqTixLQUFqRCxFQUF3RCxLQUFLN0IsUUFBN0QsQ0FBUjtBQUNBNkIsZ0NBQVEsS0FBS25CLFdBQUwsQ0FBaUJxTyx1REFBakIsQ0FBeUVsTixLQUF6RSxFQUFnRixLQUFLN0IsUUFBckYsQ0FBUjtBQUNILHFCQVZELE1BVU87QUFDSCw0QkFBSSxDQUFDbU8sT0FBTCxFQUFjO0FBQ1Ysd0RBQWtCYyxZQUFsQixDQUErQm5RLFlBQVlvUSxNQUFaLENBQW1CQyxnQkFBbEQsRUFBb0UsS0FBS2hRLFVBQXpFO0FBQ0g7QUFDRCw0QkFBSSxDQUFDaVAsT0FBTCxFQUFjO0FBQ1Ysd0RBQWtCYSxZQUFsQixDQUErQm5RLFlBQVlvUSxNQUFaLENBQW1CRSxnQkFBbEQsRUFBb0UsS0FBS2pRLFVBQXpFO0FBQ0g7QUFDSjtBQUNKLGlCQXBCRCxNQW9CTyxJQUFJb2EscUJBQXFCLEVBQXJCLElBQTJCLEtBQUt2WixRQUFMLENBQWMrRixrQkFBZCxLQUFxQ2pILFlBQVkwQyxPQUFaLENBQW9CdUUsa0JBQXBCLENBQXVDa0ksSUFBM0csRUFBaUg7QUFDcEgseUJBQUtzQyxZQUFMLENBQWtCLEdBQWxCO0FBQ0ExTyw0QkFBUSxLQUFLbkIsV0FBTCxDQUFpQnVjLFdBQWpCLENBQTZCLEdBQTdCLEVBQWtDLEtBQUtqZCxRQUF2QyxFQUFpRCxDQUFqRCxDQUFSO0FBQ0g7O0FBR0Qsb0JBQUlrZCxlQUFlLEtBQUt4YyxXQUFMLENBQWlCdVosc0NBQWpCLENBQXdEcFksS0FBeEQsRUFBK0QsS0FBSzdCLFFBQXBFLEVBQThFLEtBQTlFLENBQW5CO0FBQ0Esb0JBQUksRUFBRSxLQUFLVSxXQUFMLENBQWlCcVoseUNBQWpCLENBQTJEbFksS0FBM0QsRUFBa0UsS0FBSzdCLFFBQXZFLEtBQ0Q4YyxrQkFBa0IsS0FBSzljLFFBQUwsQ0FBYytGLGtCQUFkLEtBQXFDakgsWUFBWTBDLE9BQVosQ0FBb0J1RSxrQkFBcEIsQ0FBdUNDLElBRC9GLENBQUosRUFDMkc7QUFDdkdrWCxtQ0FBZSxLQUFLeGMsV0FBTCxDQUFpQnNPLG1CQUFqQixDQUFxQ25OLEtBQXJDLEVBQTRDLEtBQUs3QixRQUFqRCxFQUEyRCxLQUEzRCxFQUFrRXVaLGdCQUFsRSxDQUFmO0FBQ0g7O0FBRUQ7QUFDQSxvQkFBSTJELGlCQUFpQjNELGdCQUFqQixJQUNBQSxxQkFBcUIsRUFEckIsSUFDMkI7QUFDM0IscUJBQUt2WixRQUFMLENBQWM4RSxtQkFBZCxLQUFzQ2hHLFlBQVkwQyxPQUFaLENBQW9Cc0QsbUJBQXBCLENBQXdDcVksS0FGOUUsSUFHQSxLQUFLbmQsUUFBTCxDQUFjOEUsbUJBQWQsS0FBc0NoRyxZQUFZMEMsT0FBWixDQUFvQnNELG1CQUFwQixDQUF3Q3NZLE1BSGxGLEVBRzBGO0FBQ3RGLHdCQUFJLEtBQUtwZCxRQUFMLENBQWNvSCxtQkFBZCxJQUFxQ21TLHFCQUFxQixFQUExRCxJQUFnRUEscUJBQXFCLElBQXpGLEVBQStGO0FBQzNGMkQsNENBQWtCQSxZQUFsQixHQUFpQyxLQUFLbGQsUUFBTCxDQUFjb0gsbUJBQS9DO0FBQ0g7O0FBRUQseUJBQUtrSixnQkFBTCxDQUFzQjRNLFlBQXRCO0FBQ0g7O0FBRUQsb0JBQUlBLGlCQUFpQixLQUFLdkQsWUFBMUIsRUFBd0M7QUFDcEMsZ0RBQWtCMUssWUFBbEIsQ0FBK0JuUSxZQUFZb1EsTUFBWixDQUFtQjJMLE1BQW5CLENBQTBCRyxNQUF6RCxFQUFpRSxLQUFLN2IsVUFBdEU7QUFDQSwyQkFBTyxLQUFLd2EsWUFBWjtBQUNIOztBQUVELHFCQUFLMEQsT0FBTCxDQUFhalYsQ0FBYjtBQUNIO0FBQ0o7O0FBRUQ7Ozs7Ozs7O2lDQUtTQSxDLEVBQUc7QUFDUjtBQUNBO0FBQ0E7QUFDQUEsY0FBRXdTLGNBQUY7O0FBRUEsZ0JBQUkwQyxzQkFBSjtBQUNBLGdCQUFJQyxPQUFPQyxhQUFQLElBQXdCRCxPQUFPQyxhQUFQLENBQXFCQyxPQUFqRCxFQUEwRDtBQUN0RDtBQUNBSCxnQ0FBZ0JDLE9BQU9DLGFBQVAsQ0FBcUJDLE9BQXJCLENBQTZCLE1BQTdCLENBQWhCO0FBQ0gsYUFIRCxNQUdPLElBQUlyVixFQUFFb1YsYUFBRixJQUFtQnBWLEVBQUVvVixhQUFGLENBQWdCQyxPQUF2QyxFQUFnRDtBQUNuRDtBQUNBSCxnQ0FBZ0JsVixFQUFFb1YsYUFBRixDQUFnQkMsT0FBaEIsQ0FBd0IsWUFBeEIsQ0FBaEI7QUFDSCxhQUhNLE1BR0E7QUFDSCw0Q0FBa0IxUSxVQUFsQixDQUE2Qiw2RkFBN0I7QUFDSDs7QUFFRDtBQUNBLGdCQUFNMlEsd0JBQXdCLDRCQUFrQnpOLGVBQWxCLENBQWtDN0gsRUFBRXdSLE1BQXBDLENBQTlCO0FBQ0EsZ0JBQU1qUCxpQkFBaUJ2QyxFQUFFd1IsTUFBRixDQUFTalAsY0FBVCxJQUEyQixDQUFsRDtBQUNBLGdCQUFNRSxlQUFlekMsRUFBRXdSLE1BQUYsQ0FBUy9PLFlBQVQsSUFBeUIsQ0FBOUM7QUFDQSxnQkFBTThTLGdCQUFnQjlTLGVBQWVGLGNBQXJDO0FBQ0EsZ0JBQUlpVCx5QkFBeUIsS0FBN0I7O0FBRUEsZ0JBQUlELGtCQUFrQkQsc0JBQXNCdFQsTUFBNUMsRUFBb0Q7QUFDaER3VCx5Q0FBeUIsSUFBekI7QUFDSDs7QUFFRDtBQUNBLGdCQUFNQyxrQkFBa0IsNEJBQWtCQyxnQkFBbEIsQ0FBbUNSLGFBQW5DLENBQXhCO0FBQ0EsZ0JBQUlPLGVBQUosRUFBcUI7QUFDakI7QUFDQVAsZ0NBQWdCQSxjQUFjUyxLQUFkLENBQW9CLENBQXBCLEVBQXVCVCxjQUFjbFQsTUFBckMsQ0FBaEI7QUFDSDs7QUFFRDtBQUNBLGdCQUFNNFQseUJBQXlCLEtBQUtDLGtCQUFMLENBQXdCWCxhQUF4QixDQUEvQjs7QUFFQSxnQkFBSVksbUJBQUo7QUFDQSxnQkFBSUYsMkJBQTJCLEdBQS9CLEVBQW9DO0FBQ2hDO0FBQ0FFLDZCQUFhLEdBQWI7QUFDSCxhQUhELE1BR087QUFDSDtBQUNBO0FBQ0FBLDZCQUFhLDRCQUFrQkMsb0JBQWxCLENBQXVDSCxzQkFBdkMsRUFBK0QsS0FBL0QsRUFBc0UsS0FBdEUsRUFBNkUsS0FBN0UsQ0FBYjtBQUNIOztBQUVEO0FBQ0EsZ0JBQUlFLGVBQWUsR0FBZixLQUF1QixDQUFDLDRCQUFrQnZPLFFBQWxCLENBQTJCdU8sVUFBM0IsQ0FBRCxJQUEyQ0EsZUFBZSxFQUFqRixDQUFKLEVBQTBGO0FBQ3RGLG9CQUFJLEtBQUtsZSxRQUFMLENBQWM2RyxjQUFkLEtBQWlDL0gsWUFBWTBDLE9BQVosQ0FBb0JxRixjQUFwQixDQUFtQzJHLEtBQXhFLEVBQStFO0FBQzNFO0FBQ0EsZ0RBQWtCVCxVQUFsQix5QkFBa0R1USxhQUFsRDtBQUNIOztBQUVEO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBSWMsK0NBQUo7QUFDQSxnQkFBSUMsMkJBQTJCLEtBQUtsYyxnQkFBTCxFQUEvQjtBQUNBLGdCQUFJbWMseUJBQXlCLDRCQUFrQlIsZ0JBQWxCLENBQW1DTyx3QkFBbkMsQ0FBN0I7QUFDQSxnQkFBSUUsaURBQUo7QUFDQSxnQkFBSXZjLGVBQUo7O0FBRUE7QUFDQSxnQkFBSTZiLG1CQUFtQixDQUFDUyxzQkFBeEIsRUFBZ0Q7QUFDNUNELGlEQUErQkEsd0JBQS9CO0FBQ0FDLHlDQUF5QixJQUF6QjtBQUNBQywyREFBMkMsSUFBM0M7QUFDSCxhQUpELE1BS0s7QUFDREEsMkRBQTJDLEtBQTNDO0FBQ0g7O0FBRUQsZ0JBQUlDLHdCQUF3QixLQUE1QjtBQUNBLGdCQUFJQyxpQkFBSjtBQUNBLGdCQUFJQyxrQkFBSjtBQUNBLG9CQUFRLEtBQUsxZSxRQUFMLENBQWM2RyxjQUF0QjtBQUNJOzs7Ozs7Ozs7QUFTQTtBQUNBLHFCQUFLL0gsWUFBWTBDLE9BQVosQ0FBb0JxRixjQUFwQixDQUFtQzhYLFFBQXhDO0FBQ0EscUJBQUs3ZixZQUFZMEMsT0FBWixDQUFvQnFGLGNBQXBCLENBQW1DNkgsT0FBeEM7QUFDSSx3QkFBTWtRLG9CQUFvQmxCLHNCQUFzQkssS0FBdEIsQ0FBNEIsQ0FBNUIsRUFBK0JwVCxjQUEvQixDQUExQjtBQUNBLHdCQUFNa1UscUJBQXFCbkIsc0JBQXNCSyxLQUF0QixDQUE0QmxULFlBQTVCLEVBQTBDNlMsc0JBQXNCdFQsTUFBaEUsQ0FBM0I7O0FBRUEsd0JBQUlPLG1CQUFtQkUsWUFBdkIsRUFBcUM7QUFDakM7QUFDQTdJLGlDQUFTLEtBQUtpYyxrQkFBTCxDQUF3Qlcsb0JBQW9CQyxrQkFBNUMsQ0FBVDtBQUNILHFCQUhELE1BR087QUFDSDtBQUNBN2MsaUNBQVMsS0FBS2ljLGtCQUFMLENBQXdCUCxxQkFBeEIsQ0FBVDtBQUNIOztBQUVEO0FBQ0Esd0JBQUlZLHNCQUFKLEVBQTRCO0FBQ3hCdGMsaUNBQVMsNEJBQWtCOGMsa0JBQWxCLENBQXFDOWMsTUFBckMsQ0FBVDtBQUNIOztBQUVEO0FBQ0FvYyw2REFBeUMsNEJBQWtCVyxvQ0FBbEIsQ0FBdUQsNEJBQWtCQyx1Q0FBbEIsQ0FBMER0QixxQkFBMUQsRUFBaUYvUyxjQUFqRixFQUFpRyxLQUFLM0ssUUFBTCxDQUFjbUYsZ0JBQS9HLENBQXZELENBQXpDO0FBQ0Esd0JBQUlvWix3Q0FBSixFQUE4QztBQUMxQztBQUNBSDtBQUNBO0FBQ0g7O0FBRURLLCtCQUFXemMsT0FBTytiLEtBQVAsQ0FBYSxDQUFiLEVBQWdCSyxzQ0FBaEIsQ0FBWDtBQUNBTSxnQ0FBWTFjLE9BQU8rYixLQUFQLENBQWFLLHNDQUFiLEVBQXFEcGMsT0FBT29JLE1BQTVELENBQVo7QUFDQSx3QkFBSThULGVBQWUsR0FBbkIsRUFBd0I7QUFDcEIsNEJBQUksNEJBQWtCM0csUUFBbEIsQ0FBMkJrSCxRQUEzQixFQUFxQyxHQUFyQyxDQUFKLEVBQStDO0FBQzNDO0FBQ0E7QUFDQUQsb0RBQXdCLElBQXhCO0FBQ0FDLHVDQUFXQSxTQUFTL1AsT0FBVCxDQUFpQixHQUFqQixFQUFzQixFQUF0QixDQUFYO0FBQ0g7O0FBRURnUSxvQ0FBWUEsVUFBVWhRLE9BQVYsQ0FBa0IsR0FBbEIsRUFBdUIsRUFBdkIsQ0FBWjtBQUNIO0FBQ0Q7O0FBRUE7QUFDQTtBQUNBLHdCQUFNdVEsV0FBVyw0QkFBa0JDLFFBQWxCLENBQTJCLEtBQUtsZixRQUFMLENBQWNzRyxZQUF6QyxDQUFqQjtBQUNBLHdCQUFNNlksV0FBVyw0QkFBa0JELFFBQWxCLENBQTJCLEtBQUtsZixRQUFMLENBQWNxRyxZQUF6QyxDQUFqQjtBQUNBLHdCQUFJK1ksc0JBQXNCcGQsTUFBMUIsQ0EzQ0osQ0EyQ3NDO0FBQ2xDLHdCQUFJcWQsa0JBQWtCLENBQXRCO0FBQ0Esd0JBQUlDLG1CQUFtQmIsUUFBdkI7O0FBRUEsMkJBQU9ZLGtCQUFrQm5CLFdBQVc5VCxNQUFwQyxFQUE0QztBQUN4QztBQUNBa1YsNENBQW9CcEIsV0FBV21CLGVBQVgsQ0FBcEI7QUFDQXJkLGlDQUFTc2QsbUJBQW1CWixTQUE1Qjs7QUFFQTtBQUNBLDRCQUFJLENBQUMsS0FBS2hlLFdBQUwsQ0FBaUI2ZSxlQUFqQixDQUFpQ3ZkLE1BQWpDLEVBQXlDaWQsUUFBekMsRUFBbURFLFFBQW5ELENBQUwsRUFBbUU7QUFDL0Q7QUFDQTtBQUNIOztBQUVEO0FBQ0FDLDhDQUFzQnBkLE1BQXRCOztBQUVBO0FBQ0FxZDtBQUNIOztBQUVEO0FBQ0FqQiw4REFBMENpQixlQUExQzs7QUFFQTtBQUNBLHdCQUFJLEtBQUtyZixRQUFMLENBQWM2RyxjQUFkLEtBQWlDL0gsWUFBWTBDLE9BQVosQ0FBb0JxRixjQUFwQixDQUFtQzhYLFFBQXhFLEVBQWtGO0FBQzlFO0FBQ0EzYyxpQ0FBU29kLG1CQUFUOztBQUVBLDRCQUFJWixxQkFBSixFQUEyQjtBQUN2QjtBQUNBSjtBQUNIO0FBQ0Q7QUFDSDtBQUNEOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3QkFBSW9CLDJCQUEyQnBCLHNDQUEvQjtBQUNBLHdCQUFNcUIsMEJBQTBCTCxvQkFBb0JoVixNQUFwRDs7QUFFQSwyQkFBT2lWLGtCQUFrQm5CLFdBQVc5VCxNQUE3QixJQUF1Q29WLDJCQUEyQkMsdUJBQXpFLEVBQWtHO0FBQzlGLDRCQUFJTCxvQkFBb0JJLHdCQUFwQixNQUFrRCxHQUF0RCxFQUEyRDtBQUN2RDtBQUNBQTtBQUNBO0FBQ0g7O0FBRUQ7QUFDQXhkLGlDQUFTLDRCQUFrQjBkLGFBQWxCLENBQWdDTixtQkFBaEMsRUFBcURJLHdCQUFyRCxFQUErRXRCLFdBQVdtQixlQUFYLENBQS9FLENBQVQ7O0FBRUE7QUFDQSw0QkFBSSxDQUFDLEtBQUszZSxXQUFMLENBQWlCNmUsZUFBakIsQ0FBaUN2ZCxNQUFqQyxFQUF5Q2lkLFFBQXpDLEVBQW1ERSxRQUFuRCxDQUFMLEVBQW1FO0FBQy9EO0FBQ0E7QUFDSDs7QUFFRDtBQUNBQyw4Q0FBc0JwZCxNQUF0Qjs7QUFFQTtBQUNBcWQ7QUFDQUc7QUFDSDs7QUFFRDtBQUNBcEIsNkRBQXlDb0Isd0JBQXpDOztBQUVBLHdCQUFJaEIscUJBQUosRUFBMkI7QUFDdkI7QUFDQUo7QUFDSDs7QUFFRHBjLDZCQUFTb2QsbUJBQVQ7O0FBRUE7QUFDSjs7O0FBR0EscUJBQUt0Z0IsWUFBWTBDLE9BQVosQ0FBb0JxRixjQUFwQixDQUFtQzJHLEtBQXhDO0FBQ0EscUJBQUsxTyxZQUFZMEMsT0FBWixDQUFvQnFGLGNBQXBCLENBQW1DOFksTUFBeEM7QUFDQSxxQkFBSzdnQixZQUFZMEMsT0FBWixDQUFvQnFGLGNBQXBCLENBQW1DK1ksS0FBeEM7QUFDQTtBQUNJO0FBQ0Esd0JBQU1DLHFCQUFxQm5DLHNCQUFzQkssS0FBdEIsQ0FBNEIsQ0FBNUIsRUFBK0JwVCxjQUEvQixDQUEzQjtBQUNBLHdCQUFNbVYsc0JBQXNCcEMsc0JBQXNCSyxLQUF0QixDQUE0QmxULFlBQTVCLEVBQTBDNlMsc0JBQXNCdFQsTUFBaEUsQ0FBNUI7O0FBRUEsd0JBQUlPLG1CQUFtQkUsWUFBdkIsRUFBcUM7QUFDakM7QUFDQTdJLGlDQUFTLEtBQUtpYyxrQkFBTCxDQUF3QjRCLHFCQUFxQkMsbUJBQTdDLENBQVQ7QUFDSCxxQkFIRCxNQUdPO0FBQ0g7QUFDQTlkLGlDQUFTLEtBQUtpYyxrQkFBTCxDQUF3QlAscUJBQXhCLENBQVQ7QUFDSDs7QUFFRDtBQUNBLHdCQUFJWSxzQkFBSixFQUE0QjtBQUN4QnRjLGlDQUFTLDRCQUFrQjhjLGtCQUFsQixDQUFxQzljLE1BQXJDLENBQVQ7QUFDSDs7QUFFRDtBQUNBb2MsNkRBQXlDLDRCQUFrQlcsb0NBQWxCLENBQXVELDRCQUFrQkMsdUNBQWxCLENBQTBEdEIscUJBQTFELEVBQWlGL1MsY0FBakYsRUFBaUcsS0FBSzNLLFFBQUwsQ0FBY21GLGdCQUEvRyxDQUF2RCxDQUF6QztBQUNBLHdCQUFJb1osd0NBQUosRUFBOEM7QUFDMUM7QUFDQUg7QUFDQTtBQUNIOztBQUVESywrQkFBV3pjLE9BQU8rYixLQUFQLENBQWEsQ0FBYixFQUFnQkssc0NBQWhCLENBQVg7QUFDQU0sZ0NBQVkxYyxPQUFPK2IsS0FBUCxDQUFhSyxzQ0FBYixFQUFxRHBjLE9BQU9vSSxNQUE1RCxDQUFaO0FBQ0Esd0JBQUk4VCxlQUFlLEdBQW5CLEVBQXdCO0FBQ3BCO0FBQ0EsNEJBQUksNEJBQWtCM0csUUFBbEIsQ0FBMkJrSCxRQUEzQixFQUFxQyxHQUFyQyxDQUFKLEVBQStDO0FBQzNDO0FBQ0E7QUFDQUQsb0RBQXdCLElBQXhCO0FBQ0FDLHVDQUFXQSxTQUFTL1AsT0FBVCxDQUFpQixHQUFqQixFQUFzQixFQUF0QixDQUFYO0FBQ0g7QUFDRGdRLG9DQUFZQSxVQUFVaFEsT0FBVixDQUFrQixHQUFsQixFQUF1QixFQUF2QixDQUFaO0FBQ0g7QUFDRDs7QUFFQTtBQUNBMU0sa0NBQVl5YyxRQUFaLEdBQXVCUCxVQUF2QixHQUFvQ1EsU0FBcEM7O0FBRUE7QUFDQSx3QkFBSS9ULG1CQUFtQkUsWUFBdkIsRUFBcUM7QUFDakM7QUFDQSw0QkFBTWtWLHNDQUFzQyw0QkFBa0JoQixvQ0FBbEIsQ0FBdUQsNEJBQWtCQyx1Q0FBbEIsQ0FBMER0QixxQkFBMUQsRUFBaUYvUyxjQUFqRixFQUFpRyxLQUFLM0ssUUFBTCxDQUFjbUYsZ0JBQS9HLENBQXZELENBQTVDO0FBQ0FpWixpRUFBeUMyQixzQ0FBc0M3QixXQUFXOVQsTUFBMUYsQ0FIaUMsQ0FHaUU7QUFDckcscUJBSkQsTUFJTztBQUNILDRCQUFJd1Qsc0JBQUosRUFBNEI7QUFDeEI7QUFDQVEscUVBQXlDcGMsT0FBT29JLE1BQWhEO0FBQ0gseUJBSEQsTUFHTyxJQUFJc1UsY0FBYyxFQUFsQixFQUFzQjtBQUN6QjtBQUNBTixxRUFBeUMsNEJBQWtCVyxvQ0FBbEIsQ0FBdUQsNEJBQWtCQyx1Q0FBbEIsQ0FBMER0QixxQkFBMUQsRUFBaUYvUyxjQUFqRixFQUFpRyxLQUFLM0ssUUFBTCxDQUFjbUYsZ0JBQS9HLENBQXZELElBQTJMK1ksV0FBVzlULE1BQS9PO0FBQ0gseUJBSE0sTUFHQTtBQUNIO0FBQ0EsZ0NBQU00Viw4QkFBOEIsNEJBQWtCakIsb0NBQWxCLENBQXVELDRCQUFrQkMsdUNBQWxCLENBQTBEdEIscUJBQTFELEVBQWlGN1MsWUFBakYsRUFBK0YsS0FBSzdLLFFBQUwsQ0FBY21GLGdCQUE3RyxDQUF2RCxDQUFwQzs7QUFFQTtBQUNBLGdDQUFNOGEsZUFBZSw0QkFBa0JoUSxlQUFsQixDQUFrQzdILEVBQUV3UixNQUFwQyxFQUE0Q21FLEtBQTVDLENBQWtEcFQsY0FBbEQsRUFBa0VFLFlBQWxFLENBQXJCO0FBQ0F1VCxxRUFBeUM0Qiw4QkFBOEJyQyxhQUE5QixHQUE4Qyw0QkFBa0J1QyxlQUFsQixDQUFrQyxLQUFLbGdCLFFBQUwsQ0FBYzZGLG1CQUFoRCxFQUFxRW9hLFlBQXJFLENBQTlDLEdBQW1JL0IsV0FBVzlULE1BQXZMO0FBQ0g7QUFDSjs7QUFFRDtBQUNBLHdCQUFJLENBQUN3VCxzQkFBTCxFQUE2QjtBQUN6Qiw0QkFBSVcsd0NBQUosRUFBOEM7QUFDMUM7QUFDQUg7QUFDSDs7QUFFRCw0QkFBSUkscUJBQUosRUFBMkI7QUFDdkI7QUFDQUo7QUFDSDtBQUNKO0FBMU5UOztBQTZOQTtBQUNBLGdCQUFJLENBQUMsNEJBQWtCek8sUUFBbEIsQ0FBMkIzTixNQUEzQixDQUFELElBQXVDQSxXQUFXLEVBQXRELEVBQTBEO0FBQ3RELG9CQUFJLEtBQUtoQyxRQUFMLENBQWM2RyxjQUFkLEtBQWlDL0gsWUFBWTBDLE9BQVosQ0FBb0JxRixjQUFwQixDQUFtQzJHLEtBQXhFLEVBQStFO0FBQzNFLGdEQUFrQlQsVUFBbEIseUJBQWtEdVEsYUFBbEQsa0RBQTBHdGIsTUFBMUcsVUFEMkUsQ0FDNEM7QUFDdkg7QUFDSDtBQUNEO0FBQ0g7O0FBRUQ7QUFDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQXlCQSxnQkFBSW1lLGtCQUFrQixLQUF0QjtBQUNBLGdCQUFJQyxzQkFBc0IsS0FBMUI7QUFDQSxnQkFBSTtBQUNBLHFCQUFLOWUsR0FBTCxDQUFTVSxNQUFUO0FBQ0FtZSxrQ0FBa0IsSUFBbEI7QUFDSCxhQUhELENBR0UsT0FBTzNTLEtBQVAsRUFBYztBQUNaLG9CQUFJNlMscUJBQUo7QUFDQSx3QkFBUSxLQUFLcmdCLFFBQUwsQ0FBYzZHLGNBQXRCO0FBQ0kseUJBQUsvSCxZQUFZMEMsT0FBWixDQUFvQnFGLGNBQXBCLENBQW1DK1ksS0FBeEM7QUFDSVMsdUNBQWUsNEJBQWtCQyxrQkFBbEIsQ0FBcUN0ZSxNQUFyQyxFQUE2QyxLQUFLaEMsUUFBbEQsQ0FBZjtBQUNBLDRCQUFJO0FBQ0EsaUNBQUtzQixHQUFMLENBQVMrZSxZQUFUO0FBQ0gseUJBRkQsQ0FFRSxPQUFPN1MsS0FBUCxFQUFjO0FBQ1osd0RBQWtCVCxVQUFsQixxREFBOEVzVCxZQUE5RTtBQUNIOztBQUVERCw4Q0FBc0IsSUFBdEI7QUFDQUQsMENBQWtCLElBQWxCO0FBQ0FuZSxpQ0FBU3FlLFlBQVQsQ0FWSixDQVUyQjtBQUN2QjtBQUNKLHlCQUFLdmhCLFlBQVkwQyxPQUFaLENBQW9CcUYsY0FBcEIsQ0FBbUMyRyxLQUF4QztBQUNBLHlCQUFLMU8sWUFBWTBDLE9BQVosQ0FBb0JxRixjQUFwQixDQUFtQzhYLFFBQXhDO0FBQ0EseUJBQUs3ZixZQUFZMEMsT0FBWixDQUFvQnFGLGNBQXBCLENBQW1DNkgsT0FBeEM7QUFDSTtBQUNBLG9EQUFrQjNCLFVBQWxCLHlCQUFrRHVRLGFBQWxELGdDQUF3RnRiLE1BQXhGLDJDQUFtSSxLQUFLaEMsUUFBTCxDQUFjc0csWUFBakosdUJBQStLLEtBQUt0RyxRQUFMLENBQWNxRyxZQUE3TDtBQUNKO0FBQ0EseUJBQUt2SCxZQUFZMEMsT0FBWixDQUFvQnFGLGNBQXBCLENBQW1DOFksTUFBeEM7QUFDQTtBQUNBO0FBQ0E7QUFDSSwrQkF2QlIsQ0F1QmdCO0FBdkJoQjtBQXlCSDs7QUFFRDtBQUNBLGdCQUFNN0UsY0FBYyw0QkFBa0I3SyxlQUFsQixDQUFrQzdILEVBQUV3UixNQUFwQyxDQUFwQjtBQUNBLGdCQUFJMkcsdUNBQUo7QUFDQSxnQkFBSUosZUFBSixFQUFxQjtBQUNqQix3QkFBUSxLQUFLbmdCLFFBQUwsQ0FBYzZHLGNBQXRCO0FBQ0kseUJBQUsvSCxZQUFZMEMsT0FBWixDQUFvQnFGLGNBQXBCLENBQW1DK1ksS0FBeEM7QUFDSSw0QkFBSVEsbUJBQUosRUFBeUI7QUFDckIsZ0NBQUksS0FBS3BnQixRQUFMLENBQWNrRix1QkFBZCxLQUEwQ3BHLFlBQVkwQyxPQUFaLENBQW9CMEQsdUJBQXBCLENBQTRDb00sTUFBMUYsRUFBa0c7QUFDOUYsNERBQWtCbkcsbUJBQWxCLENBQXNDL0MsRUFBRXdSLE1BQXhDLEVBQWdEa0IsWUFBWTFRLE1BQVosR0FBcUIsS0FBS3BLLFFBQUwsQ0FBY2lGLGNBQWQsQ0FBNkJtRixNQUFsRyxFQUQ4RixDQUNhO0FBQzlHLDZCQUZELE1BRU87QUFDSCw0REFBa0JlLG1CQUFsQixDQUFzQy9DLEVBQUV3UixNQUF4QyxFQUFnRGtCLFlBQVkxUSxNQUE1RCxFQURHLENBQ2tFO0FBQ3hFOztBQUVEO0FBQ0gseUJBVlQsQ0FVVTtBQUNOO0FBQ0EseUJBQUt0TCxZQUFZMEMsT0FBWixDQUFvQnFGLGNBQXBCLENBQW1DMkcsS0FBeEM7QUFDQSx5QkFBSzFPLFlBQVkwQyxPQUFaLENBQW9CcUYsY0FBcEIsQ0FBbUM4WSxNQUF4QztBQUNBLHlCQUFLN2dCLFlBQVkwQyxPQUFaLENBQW9CcUYsY0FBcEIsQ0FBbUM4WCxRQUF4QztBQUNBLHlCQUFLN2YsWUFBWTBDLE9BQVosQ0FBb0JxRixjQUFwQixDQUFtQzZILE9BQXhDO0FBQ0E7QUFDSTtBQUNBNlIseURBQWlDLDRCQUFrQkMsa0NBQWxCLENBQXFEeGUsTUFBckQsRUFBNkRvYyxzQ0FBN0QsRUFBcUd0RCxXQUFyRyxFQUFrSCxLQUFLOWEsUUFBTCxDQUFjbUYsZ0JBQWhJLENBQWpDO0FBQ0Esb0RBQWtCZ0csbUJBQWxCLENBQXNDL0MsRUFBRXdSLE1BQXhDLEVBQWdEMkcsOEJBQWhEO0FBbkJSO0FBcUJIOztBQUVEO0FBQ0EsZ0JBQUlKLG1CQUFtQnpDLDBCQUEwQjVDLFdBQWpELEVBQThEO0FBQzFEO0FBQ0EsNENBQWtCN0wsWUFBbEIsQ0FBK0JuUSxZQUFZb1EsTUFBWixDQUFtQjJMLE1BQW5CLENBQTBCakcsS0FBekQsRUFBZ0V4TSxFQUFFd1IsTUFBbEU7QUFDSDtBQUNKOztBQUVEOzs7Ozs7Ozs7Z0NBTVF4UixDLEVBQUc7QUFDUDtBQUNBLGlCQUFLdEgsU0FBTCxHQUFpQixLQUFqQjtBQUNBO0FBQ0EsaUJBQUtHLFNBQUwsR0FBaUIsS0FBakI7O0FBRUEsZ0JBQUksNEJBQWtCZ1AsZUFBbEIsQ0FBa0M3SCxFQUFFd1IsTUFBcEMsTUFBZ0QsS0FBS0QsWUFBekQsRUFBdUU7QUFDbkUsNENBQWtCMUssWUFBbEIsQ0FBK0JuUSxZQUFZb1EsTUFBWixDQUFtQjJMLE1BQW5CLENBQTBCRyxNQUF6RCxFQUFpRTVTLEVBQUV3UixNQUFuRTtBQUNIO0FBQ0o7O0FBRUQ7Ozs7Ozs7O2lDQUtTeFIsQyxFQUFHO0FBQ1I7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBSSxDQUFDQSxFQUFFa1UsUUFBSCxJQUFlLEtBQUt0YyxRQUFMLENBQWN1RyxrQkFBakMsRUFBcUQ7QUFDakQscUJBQUt4RixZQUFMLEdBQW9CLElBQXBCLENBRGlELENBQ3ZCOztBQUUxQjtBQUNBLG9CQUFNNEosaUJBQWlCdkMsRUFBRXdSLE1BQUYsQ0FBU2pQLGNBQVQsSUFBMkIsQ0FBbEQ7QUFDQSxvQkFBTUUsZUFBZXpDLEVBQUV3UixNQUFGLENBQVMvTyxZQUFULElBQXlCLENBQTlDOztBQUVBO0FBQ0Esb0JBQU00ViwwQkFBMEIsS0FBSzdiLFFBQXJDOztBQUVBLG9CQUFJNUMsZUFBSjtBQUNBLG9CQUFJLDRCQUFrQjBKLHdCQUFsQixDQUEyQytVLHVCQUEzQyxDQUFKLEVBQXlFO0FBQ3JFO0FBQ0Esd0JBQUksS0FBS3pnQixRQUFMLENBQWNzRyxZQUFkLEdBQTZCLENBQTdCLElBQWtDLEtBQUt0RyxRQUFMLENBQWNxRyxZQUFkLEdBQTZCLENBQW5FLEVBQXNFO0FBQ2xFO0FBQ0EsNEJBQUksNEJBQWtCcWEsY0FBbEIsQ0FBaUN0WSxDQUFqQyxDQUFKLEVBQXlDO0FBQ3JDcEcscUNBQVMsS0FBS2hDLFFBQUwsQ0FBY3NHLFlBQXZCO0FBQ0gseUJBRkQsTUFFTyxJQUFJLDRCQUFrQnFhLGdCQUFsQixDQUFtQ3ZZLENBQW5DLENBQUosRUFBMkM7QUFDOUNwRyxxQ0FBUyxLQUFLaEMsUUFBTCxDQUFjcUcsWUFBdkI7QUFDSCx5QkFGTSxNQUVBO0FBQ0gsd0RBQWtCMEcsVUFBbEI7QUFDSDtBQUNKLHFCQVRELE1BU087QUFDSC9LLGlDQUFTLENBQVQ7QUFDSDtBQUNKLGlCQWRELE1BY087QUFDSEEsNkJBQVN5ZSx1QkFBVDtBQUNIOztBQUVEemUseUJBQVMsQ0FBQ0EsTUFBVixDQTdCaUQsQ0E2Qi9COztBQUVsQjtBQUNBO0FBQ0Esb0JBQUksNEJBQWtCMk4sUUFBbEIsQ0FBMkIsS0FBSzNQLFFBQUwsQ0FBYzhILFNBQXpDLENBQUosRUFBeUQ7QUFDckQsd0JBQU04WSxPQUFPLENBQUMsS0FBSzVnQixRQUFMLENBQWM4SCxTQUE1QixDQURxRCxDQUNkO0FBQ3ZDO0FBQ0E7QUFDQSx3QkFBSSw0QkFBa0I0WSxjQUFsQixDQUFpQ3RZLENBQWpDLENBQUosRUFBeUM7QUFBRTtBQUN2Q3BHLGtDQUFVNGUsSUFBVjtBQUNILHFCQUZELE1BRU8sSUFBSSw0QkFBa0JELGdCQUFsQixDQUFtQ3ZZLENBQW5DLENBQUosRUFBMkM7QUFBRTtBQUNoRHBHLGtDQUFVNGUsSUFBVjtBQUNIO0FBQ0osaUJBVEQsTUFTTztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0Esd0JBQUksNEJBQWtCRixjQUFsQixDQUFpQ3RZLENBQWpDLENBQUosRUFBeUM7QUFBRTtBQUN2Q3BHLGlDQUFTLDRCQUFrQjZlLHdCQUFsQixDQUEyQzdlLE1BQTNDLEVBQW1ELEtBQUtoQyxRQUFMLENBQWN3RixxQkFBakUsQ0FBVDtBQUNILHFCQUZELE1BRU8sSUFBSSw0QkFBa0JtYixnQkFBbEIsQ0FBbUN2WSxDQUFuQyxDQUFKLEVBQTJDO0FBQUU7QUFDaERwRyxpQ0FBUyw0QkFBa0I4ZSw2QkFBbEIsQ0FBZ0Q5ZSxNQUFoRCxFQUF3RCxLQUFLaEMsUUFBTCxDQUFjd0YscUJBQXRFLENBQVQ7QUFDSDtBQUNKOztBQUVEO0FBQ0E7QUFDQXhELHlCQUFTLDRCQUFrQnNlLGtCQUFsQixDQUFxQ3RlLE1BQXJDLEVBQTZDLEtBQUtoQyxRQUFsRCxDQUFUO0FBQ0Esb0JBQUlnQyxXQUFXLENBQUN5ZSx1QkFBaEIsRUFBeUM7QUFDckM7QUFDQSx5QkFBS25mLEdBQUwsQ0FBU1UsTUFBVDtBQUNIOztBQUVEO0FBQ0FvRyxrQkFBRXdTLGNBQUYsR0EvRGlELENBK0Q3Qjs7QUFFcEI7QUFDQTtBQUNBLHFCQUFLbUcsYUFBTCxDQUFtQnBXLGNBQW5CLEVBQW1DRSxZQUFuQzs7QUFFQSxxQkFBSzlKLFlBQUwsR0FBb0IsS0FBcEIsQ0FyRWlELENBcUV0QjtBQUM5QjtBQUNKOztBQUVEOzs7Ozs7OztnQ0FLUXFILEMsRUFBRztBQUNQLGlCQUFLcEgsV0FBTCxHQUFtQixJQUFuQjtBQUNBb0gsY0FBRXdTLGNBQUY7QUFDQSxnQkFBTW9HLGNBQWM1WSxFQUFFNlksWUFBRixDQUFleEQsT0FBZixDQUF1QixZQUF2QixDQUFwQjtBQUNBLGdCQUFNeUQsZUFBZSxLQUFLQyxhQUFMLENBQW1CSCxXQUFuQixDQUFyQjtBQUNBLGlCQUFLMWYsR0FBTCxDQUFTNGYsWUFBVDtBQUNBLGlCQUFLbGdCLFdBQUwsR0FBbUIsS0FBbkI7QUFDSDs7QUFFRDs7Ozs7Ozs7O3dDQU1nQjtBQUNaLGdCQUFJLEtBQUtoQixRQUFMLENBQWM2SCxnQkFBbEIsRUFBb0M7QUFDaEMscUJBQUt5SSxnQkFBTCxDQUFzQixLQUFLMUwsUUFBM0I7QUFDSDs7QUFFRCxtQkFBTyxJQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozt5Q0FNaUJ3RCxDLEVBQUc7QUFDaEI7QUFDQSxnQkFBSSw0QkFBa0JnWixTQUFsQixDQUE0QmhaLENBQTVCLE1BQW1DLDBCQUFnQnNTLE9BQWhCLENBQXdCK0IsR0FBL0QsRUFBb0U7QUFDaEUsb0JBQU00RSxpQkFBaUIsNEJBQWtCaEgsaUJBQWxCLEVBQXZCO0FBQ0Esb0JBQUl2YixZQUFZd2lCLHNCQUFaLENBQW1DRCxjQUFuQyxDQUFKLEVBQXdEO0FBQ3BELHdCQUFNRSxZQUFZemlCLFlBQVkyRSxxQkFBWixDQUFrQzRkLGNBQWxDLENBQWxCO0FBQ0EseUJBQUszZ0IsV0FBTCxDQUFpQjBZLG1CQUFqQixDQUFxQ21JLFNBQXJDO0FBQ0g7QUFDSjtBQUNKOztBQUVEOzs7Ozs7Ozs7dUNBTWVuWixDLEVBQUc7QUFDZCxnQkFBSSw0QkFBa0JnWixTQUFsQixDQUE0QmhaLENBQTVCLE1BQW1DLDBCQUFnQnNTLE9BQWhCLENBQXdCK0IsR0FBL0QsRUFBb0U7QUFDaEUsb0JBQU00RSxpQkFBaUIsNEJBQWtCaEgsaUJBQWxCLEVBQXZCO0FBQ0Esb0JBQUl2YixZQUFZd2lCLHNCQUFaLENBQW1DRCxjQUFuQyxDQUFKLEVBQXdEO0FBQ3BELHdCQUFNRSxZQUFZemlCLFlBQVkyRSxxQkFBWixDQUFrQzRkLGNBQWxDLENBQWxCO0FBQ0EseUJBQUszZ0IsV0FBTCxDQUFpQjRZLG1CQUFqQixDQUFxQ2lJLFNBQXJDO0FBQ0g7QUFDSjtBQUNKOztBQUVEOzs7Ozs7Ozs7O2lEQU95QjtBQUNyQixnQkFBSSxDQUFDLDRCQUFrQjNPLFNBQWxCLENBQTRCLEtBQUt6VCxVQUFqQyxDQUFMLEVBQW1EO0FBQy9DLDRDQUFrQjROLFVBQWxCLG9DQUE4RCxLQUFLNU4sVUFBbkU7QUFDSDs7QUFFRCxtQkFBTyw0QkFBa0IwTixTQUFsQixDQUE0QixLQUFLMU4sVUFBTCxDQUFnQnlVLE9BQWhCLENBQXdCQyxXQUF4QixFQUE1QixFQUFtRSxLQUFLMk4sY0FBeEUsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7MENBTWtCO0FBQ2QsbUJBQU8sS0FBS3JpQixVQUFMLENBQWdCeVUsT0FBaEIsQ0FBd0JDLFdBQXhCLE9BQTBDLE9BQWpEO0FBQ0g7O0FBRUQ7Ozs7Ozs7OztnREFNd0I7QUFDcEIsbUJBQVEsS0FBSzFVLFVBQUwsQ0FBZ0IrWixJQUFoQixLQUF5QixNQUF6QixJQUNBLEtBQUsvWixVQUFMLENBQWdCK1osSUFBaEIsS0FBeUIsUUFEekIsSUFFQSxLQUFLL1osVUFBTCxDQUFnQitaLElBQWhCLEtBQXlCLEtBRnpCLElBR0EsNEJBQWtCeE4sd0JBQWxCLENBQTJDLEtBQUt2TSxVQUFMLENBQWdCK1osSUFBM0QsQ0FIUjtBQUlIOztBQUVEOzs7Ozs7Ozs7Ozs7d0NBU2dCO0FBQ1osZ0JBQU11SSxvQkFBb0IsS0FBS3RpQixVQUFMLENBQWdCeVUsT0FBaEIsQ0FBd0JDLFdBQXhCLEVBQTFCOztBQUVBLGdCQUFJLENBQUMsS0FBSzZOLHNCQUFMLEVBQUwsRUFBb0M7QUFDaEMsNENBQWtCM1UsVUFBbEIsV0FBcUMwVSxpQkFBckM7QUFDSDs7QUFFRCxnQkFBSSxLQUFLRSxlQUFMLEVBQUosRUFBNEI7QUFDeEIsb0JBQUksQ0FBQyxLQUFLQyxxQkFBTCxFQUFMLEVBQW1DO0FBQy9CLGdEQUFrQjdVLFVBQWxCLHNCQUFnRCxLQUFLNU4sVUFBTCxDQUFnQitaLElBQWhFO0FBQ0g7O0FBRUQscUJBQUsvWSxjQUFMLEdBQXNCLElBQXRCO0FBQ0gsYUFORCxNQU1PO0FBQ0gscUJBQUtBLGNBQUwsR0FBc0IsS0FBdEI7QUFDQSxxQkFBS0MsaUJBQUwsR0FBeUIsS0FBS2pCLFVBQUwsQ0FBZ0IwaUIsWUFBaEIsQ0FBNkIsaUJBQTdCLEtBQW1ELEtBQUsxaUIsVUFBTCxDQUFnQjZJLFlBQWhCLENBQTZCLGlCQUE3QixNQUFvRCxNQUFoSTtBQUNIO0FBQ0o7O0FBRUQ7Ozs7Ozs7Ozt3REFNeUQ7QUFBQSxnQkFBM0I4WixrQkFBMkIsdUVBQU4sSUFBTTs7QUFDckQsZ0JBQUk5VCxXQUFXLElBQWY7QUFDQSxnQkFBSStULHFCQUFKO0FBQ0EsZ0JBQUksQ0FBQyw0QkFBa0I5WixNQUFsQixDQUF5QjZaLGtCQUF6QixDQUFMLEVBQW1EO0FBQy9DQywrQkFBZUQsa0JBQWY7QUFDSCxhQUZELE1BRU87QUFDSEMsK0JBQWUsNEJBQWtCOVIsZUFBbEIsQ0FBa0MsS0FBSzlRLFVBQXZDLENBQWY7QUFDSDs7QUFFRCxnQkFBSSxLQUFLZ0IsY0FBTCxJQUF1QixLQUFLQyxpQkFBaEMsRUFBbUQ7QUFDL0M7Ozs7Ozs7Ozs7OztBQVlBLG9CQUFNNGhCLDBCQUEwQixLQUFLdGhCLFdBQUwsQ0FBaUJtTixlQUFqQixDQUFpQ2tVLFlBQWpDLEVBQStDLEtBQUsvaEIsUUFBcEQsQ0FBaEMsQ0FiK0MsQ0FhZ0Q7QUFDL0Ysb0JBQUksQ0FBQyxLQUFLYixVQUFMLENBQWdCMGlCLFlBQWhCLENBQTZCLE9BQTdCLENBQUQsSUFBMEMsS0FBSzFpQixVQUFMLENBQWdCNkksWUFBaEIsQ0FBNkIsT0FBN0IsTUFBMEMsRUFBeEYsRUFBNEY7QUFDeEY7QUFDQSx3QkFBSSxDQUFDOEYsTUFBTUMsT0FBT2lVLHVCQUFQLENBQU4sQ0FBRCxJQUEyQ0MsYUFBYUQsdUJBQTVELEVBQXFGO0FBQ2pGLDZCQUFLMWdCLEdBQUwsQ0FBUzBnQix1QkFBVDtBQUNBaFUsbUNBQVcsS0FBWDtBQUNILHFCQUhELE1BR087QUFDSDtBQUNBLG9EQUFrQmpCLFVBQWxCLGlCQUEyQ2dWLFlBQTNDO0FBQ0g7QUFDSixpQkFURCxNQVNPO0FBQ0g7Ozs7OztBQU1BLHdCQUFLLEtBQUsvaEIsUUFBTCxDQUFjMkYsb0JBQWQsS0FBdUMsSUFBdkMsSUFBK0MsS0FBSzNGLFFBQUwsQ0FBYzJGLG9CQUFkLENBQW1Da0osUUFBbkMsT0FBa0RrVCxZQUFsRyxJQUNDLEtBQUsvaEIsUUFBTCxDQUFjMkYsb0JBQWQsS0FBdUMsSUFBdkMsSUFBK0NvYyxpQkFBaUIsRUFBaEUsSUFBc0VBLGlCQUFpQixLQUFLNWlCLFVBQUwsQ0FBZ0I2SSxZQUFoQixDQUE2QixPQUE3QixDQUR4RixJQUVDK1osaUJBQWlCLEVBQWpCLElBQXVCLEtBQUs1aUIsVUFBTCxDQUFnQjZJLFlBQWhCLENBQTZCLE1BQTdCLE1BQXlDLFFBQWhFLElBQTRFLENBQUMsNEJBQWtCMkgsUUFBbEIsQ0FBMkJxUyx1QkFBM0IsQ0FGbEYsRUFFd0k7QUFDcEksNEJBQUksS0FBS2hpQixRQUFMLENBQWNtSCx5QkFBZCxLQUE0QyxLQUFLbkgsUUFBTCxDQUFjMEYseUJBQWQsS0FBNEMsSUFBNUMsSUFBb0QsS0FBSzFGLFFBQUwsQ0FBYzhGLG9CQUE5RyxDQUFKLEVBQXlJO0FBQ3JJLGlDQUFLeUssWUFBTCxDQUFrQixLQUFLMlIsOEJBQUwsRUFBbEI7QUFDSDs7QUFFRDtBQUNBLDRCQUFJLENBQUMsS0FBS2xpQixRQUFMLENBQWNtSCx5QkFBbkIsRUFBOEM7QUFDMUMsZ0NBQUlnYixnQkFBSjs7QUFFQSxnQ0FBSSxLQUFLbmlCLFFBQUwsQ0FBY3dHLDBCQUFkLEtBQTZDLElBQTdDLElBQXFELEtBQUt4RyxRQUFMLENBQWMrVyxxQkFBZCxLQUF3QyxFQUFqRyxFQUFxRztBQUNqR29MLDBDQUFVLEtBQUt6aEIsV0FBTCxDQUFpQjhPLGVBQWpCLENBQWlDdVMsWUFBakMsRUFBK0MsS0FBSy9oQixRQUFwRCxDQUFWO0FBQ0gsNkJBRkQsTUFFTztBQUNIbWlCLDBDQUFVSixZQUFWO0FBQ0g7O0FBRUQsZ0NBQUksQ0FBQyxLQUFLL2hCLFFBQUwsQ0FBY3lHLDZCQUFkLEtBQWdEM0gsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q2SyxNQUFsRyxJQUNBLEtBQUt0UixRQUFMLENBQWN5Ryw2QkFBZCxLQUFnRDNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEK0ssTUFBbEcsSUFBNEcsS0FBS3hSLFFBQUwsQ0FBY2tGLHVCQUFkLEtBQTBDcEcsWUFBWTBDLE9BQVosQ0FBb0IwRCx1QkFBcEIsQ0FBNENvTSxNQURuTSxLQUVBLEtBQUt0UixRQUFMLENBQWMrVyxxQkFBZCxLQUF3QyxFQUZ4QyxJQUdBLDRCQUFrQjNGLFVBQWxCLENBQTZCMlEsWUFBN0IsQ0FISixFQUdnRDtBQUM1QyxxQ0FBS3hSLFlBQUwsQ0FBa0IsS0FBS3ZRLFFBQUwsQ0FBYytXLHFCQUFkLEdBQXNDLEtBQUtyVyxXQUFMLENBQWlCZ1AsNEJBQWpCLENBQThDeVMsT0FBOUMsRUFBdUQsS0FBS25pQixRQUE1RCxFQUFzRSxJQUF0RSxFQUE0RSxLQUFLYyxTQUFqRixDQUF4RDtBQUNILDZCQUxELE1BS087QUFDSCxxQ0FBS3lQLFlBQUwsQ0FBa0IsS0FBSzdQLFdBQUwsQ0FBaUJnUCw0QkFBakIsQ0FBOEN5UyxPQUE5QyxFQUF1RCxLQUFLbmlCLFFBQTVELEVBQXNFLElBQXRFLEVBQTRFLEtBQUtjLFNBQWpGLENBQWxCO0FBQ0g7QUFDSjs7QUFFRGtOLG1DQUFXLEtBQVg7QUFDSDtBQUNKOztBQUVELG9CQUFJK1QsaUJBQWlCLEVBQXJCLEVBQXlCO0FBQ3JCLDRCQUFRLEtBQUsvaEIsUUFBTCxDQUFjK0Ysa0JBQXRCO0FBQ0ksNkJBQUtqSCxZQUFZMEMsT0FBWixDQUFvQnVFLGtCQUFwQixDQUF1Q3lOLEtBQTVDO0FBQ0l4Rix1Q0FBVyxLQUFYO0FBQ0E7QUFDSjtBQUNBLDZCQUFLbFAsWUFBWTBDLE9BQVosQ0FBb0J1RSxrQkFBcEIsQ0FBdUN1SixNQUE1QztBQUNJLGlDQUFLZ0IsZ0JBQUwsQ0FBc0IsS0FBS3RRLFFBQUwsQ0FBY2lGLGNBQXBDO0FBQ0ErSSx1Q0FBVyxLQUFYO0FBQ0E7QUFDSiw2QkFBS2xQLFlBQVkwQyxPQUFaLENBQW9CdUUsa0JBQXBCLENBQXVDa0ksSUFBNUM7QUFDSSxpQ0FBSzNNLEdBQUwsQ0FBUyxHQUFUO0FBQ0EwTSx1Q0FBVyxLQUFYO0FBQ0E7QUFDSjtBQUNBO0FBZEo7QUFnQkgsaUJBakJELE1BaUJPLElBQUlBLFlBQVkrVCxpQkFBaUIsS0FBSzVpQixVQUFMLENBQWdCNkksWUFBaEIsQ0FBNkIsT0FBN0IsQ0FBakMsRUFBd0U7QUFDM0UseUJBQUsxRyxHQUFMLENBQVN5Z0IsWUFBVDtBQUNIO0FBQ0osYUFqRkQsTUFpRk87QUFDSCxvQkFBSSxLQUFLL2hCLFFBQUwsQ0FBYzJGLG9CQUFkLEtBQXVDLElBQTNDLEVBQWlEO0FBQzdDLHlCQUFLckUsR0FBTCxDQUFTeWdCLFlBQVQ7QUFDSCxpQkFGRCxNQUVPO0FBQ0gsd0JBQUksS0FBSy9oQixRQUFMLENBQWMyRixvQkFBZCxLQUF1Q29jLFlBQTNDLEVBQXlEO0FBQ3JELDZCQUFLemdCLEdBQUwsQ0FBU3lnQixZQUFUO0FBQ0g7QUFDSjtBQUNKO0FBQ0o7O0FBRUQ7Ozs7Ozs7Ozs7Ozs7OztBQTZNQTs7OzREQUdvQztBQUFBLHdDQUNBLEtBQUsvaEIsUUFBTCxDQUFjcUcsWUFBZCxDQUEyQndJLFFBQTNCLEdBQXNDOEgsS0FBdEMsQ0FBNEMsR0FBNUMsQ0FEQTtBQUFBO0FBQUEsZ0JBQzNCeUwsdUJBRDJCOztBQUFBLHVCQUVDLENBQUMsS0FBS3BpQixRQUFMLENBQWNzRyxZQUFmLElBQStCLEtBQUt0RyxRQUFMLENBQWNzRyxZQUFkLEtBQStCLENBQS9ELEdBQWtFLEVBQWxFLEdBQXFFLEtBQUt0RyxRQUFMLENBQWNzRyxZQUFkLENBQTJCdUksUUFBM0IsR0FBc0M4SCxLQUF0QyxDQUE0QyxHQUE1QyxDQUZyRTtBQUFBO0FBQUEsZ0JBRTNCMEwsdUJBRjJCOztBQUdoQ0Qsc0NBQTBCQSx3QkFBd0IxVCxPQUF4QixDQUFnQyxHQUFoQyxFQUFxQyxFQUFyQyxDQUExQjtBQUNBMlQsc0NBQTBCQSx3QkFBd0IzVCxPQUF4QixDQUFnQyxHQUFoQyxFQUFxQyxFQUFyQyxDQUExQjs7QUFFQSxpQkFBSzFPLFFBQUwsQ0FBY3NpQixPQUFkLEdBQXdCQyxLQUFLclcsR0FBTCxDQUFTa1csd0JBQXdCaFksTUFBakMsRUFBeUMsQ0FBekMsQ0FBeEI7QUFDQSxpQkFBS3BLLFFBQUwsQ0FBY3dpQixPQUFkLEdBQXdCRCxLQUFLclcsR0FBTCxDQUFTbVcsd0JBQXdCalksTUFBakMsRUFBeUMsQ0FBekMsQ0FBeEI7QUFDSDtBQUNEOzs7Ozs7bUVBRzJDO0FBQ3ZDLGdCQUFJLDRCQUFrQm5DLE1BQWxCLENBQXlCLEtBQUtqSSxRQUFMLENBQWNvRiwyQkFBdkMsS0FBdUUySSxPQUFPLEtBQUsvTixRQUFMLENBQWNxRixhQUFyQixJQUFzQyxDQUFqSCxFQUFvSDtBQUNoSCxvQkFBSSxLQUFLckYsUUFBTCxDQUFjbUYsZ0JBQWQsS0FBbUMsR0FBbkMsSUFBMEMsS0FBS25GLFFBQUwsQ0FBYzZGLG1CQUFkLEtBQXNDLEdBQXBGLEVBQXlGO0FBQ3JGLHlCQUFLN0YsUUFBTCxDQUFjb0YsMkJBQWQsR0FBNEMsR0FBNUM7QUFDSCxpQkFGRCxNQUVPLElBQUksS0FBS3BGLFFBQUwsQ0FBY21GLGdCQUFkLEtBQW1DLEdBQW5DLElBQTBDLEtBQUtuRixRQUFMLENBQWM2RixtQkFBZCxLQUFzQyxHQUFwRixFQUF5RjtBQUM1Rix5QkFBSzdGLFFBQUwsQ0FBY29GLDJCQUFkLEdBQTRDLEdBQTVDO0FBQ0g7QUFDSjtBQUNKOztBQUVEOzs7Ozs7Ozs7OztBQWdDQTs7O2dFQUd3QztBQUNwQyxpQkFBSyxJQUFNa1IsR0FBWCxJQUFrQixLQUFLdFcsUUFBdkIsRUFBaUM7QUFDN0Isb0JBQUksS0FBS0EsUUFBTCxDQUFjdVcsY0FBZCxDQUE2QkQsR0FBN0IsQ0FBSixFQUF1QztBQUNuQyx3QkFBTXpVLFFBQVEsS0FBSzdCLFFBQUwsQ0FBY3NXLEdBQWQsQ0FBZDs7QUFFQTtBQUNBLHdCQUFJelUsVUFBVSxNQUFWLElBQW9CQSxVQUFVLE9BQWxDLEVBQTJDO0FBQ3ZDLDZCQUFLN0IsUUFBTCxDQUFjc1csR0FBZCxJQUFxQnpVLFVBQVUsTUFBL0I7QUFDSDs7QUFFRDtBQUNBO0FBQ0Esd0JBQUksT0FBT0EsS0FBUCxLQUFpQixRQUFyQixFQUErQjtBQUMzQiw2QkFBSzdCLFFBQUwsQ0FBY3NXLEdBQWQsSUFBcUJ6VSxNQUFNZ04sUUFBTixFQUFyQjtBQUNIO0FBQ0o7QUFDSjtBQUNKOztBQUVEOzs7Ozs7Ozs7O0FBOEhBOzs7Ozs7Ozs7cUNBU2FyTixPLEVBQXlCO0FBQUEsZ0JBQWhCbUIsTUFBZ0IsdUVBQVAsS0FBTzs7QUFDbEM7QUFDQSxnQkFBSUEsVUFBVSxDQUFDLDRCQUFrQnNGLE1BQWxCLENBQXlCekcsT0FBekIsQ0FBZixFQUFrRDtBQUM5QyxxQkFBS2QsV0FBTCxDQUFpQitoQiwyQkFBakIsQ0FBNkNqaEIsT0FBN0M7QUFDSDs7QUFFRCxnQkFBSW1CLE1BQUosRUFBWTtBQUNSO0FBQ0E7QUFDQSxvQkFBTStmLGlDQUFpQywyQkFBMkJsaEIsT0FBbEU7QUFDQSxvQkFBSWtoQiw4QkFBSixFQUFvQztBQUNoQyx5QkFBSzFpQixRQUFMLENBQWMyaUIsNkJBQWQsR0FBOENuaEIsUUFBUWdFLHFCQUF0RDtBQUNIOztBQUVELG9CQUFNb2QseUJBQXlCLG1CQUFtQnBoQixPQUFsRDtBQUNBLG9CQUFJb2hCLHNCQUFKLEVBQTRCO0FBQ3hCLHlCQUFLNWlCLFFBQUwsQ0FBYzZpQixxQkFBZCxHQUFzQ3JoQixRQUFRNkQsYUFBOUM7QUFDSDs7QUFFRDtBQUNBLHFCQUFLM0UsV0FBTCxDQUFpQm9pQiwrQkFBakIsQ0FBaUR0aEIsT0FBakQsRUFBMEQsS0FBS3hCLFFBQS9EOztBQUVBO0FBQ0EscUJBQUsyVixjQUFMLENBQW9CblUsT0FBcEIsRUFqQlEsQ0FpQnNCO0FBQ2pDLGFBbEJELE1Ba0JPO0FBQ0g7QUFDQSxxQkFBS3hCLFFBQUwsR0FBZ0IsRUFBaEI7QUFDQTtBQUNBLHFCQUFLMlYsY0FBTCxDQUFvQixLQUFLalYsV0FBTCxDQUFpQnFpQixnQkFBakIsRUFBcEIsRUFBeUQsS0FBSzVqQixVQUFMLENBQWdCNmpCLE9BQXpFLEVBQWtGeGhCLE9BQWxGLEVBQTJGLEVBQUVvRCxVQUFXLEtBQUt0RixlQUFsQixFQUEzRjtBQUNBLHFCQUFLMmpCLFFBQUwsR0FBZ0IsS0FBaEI7QUFDQSxxQkFBSzFILFVBQUwsR0FBa0IsSUFBbEIsQ0FORyxDQU1xQjtBQUN4QixxQkFBS2lHLGNBQUwsR0FBc0IsMEJBQWdCQSxjQUF0QztBQUNBLHFCQUFLemhCLE9BQUwsR0FBZSxLQUFmO0FBQ0EscUJBQUtzWixjQUFMLEdBQXNCLEtBQXRCLENBVEcsQ0FTMEI7QUFDN0IscUJBQUt1QyxxQkFBTCxHQUE2QixJQUE3QixDQVZHLENBVWdDO0FBQ3RDOztBQUVEO0FBQ0EsaUJBQUtzSCxxQ0FBTDs7QUFFQTtBQUNBLGlCQUFLQyxxQ0FBTDs7QUFFQTtBQUNBLGlCQUFLemlCLFdBQUwsQ0FBaUIwaUIsMkNBQWpCLENBQTZELEtBQUtwakIsUUFBbEU7O0FBRUE7QUFDQTtBQUNBLGlCQUFLVSxXQUFMLENBQWlCMmlCLG1EQUFqQixDQUFxRSxLQUFLcmpCLFFBQTFFOztBQUVBO0FBQ0EsaUJBQUtBLFFBQUwsQ0FBYytXLHFCQUFkLEdBQXNDLEtBQUsvVyxRQUFMLENBQWNzRyxZQUFkLEdBQTZCLENBQTdCLEdBQWlDLEdBQWpDLEdBQXVDLEVBQTdFO0FBQ0EsaUJBQUt0RyxRQUFMLENBQWMyWCxxQkFBZCxHQUFzQyxLQUFLM1gsUUFBTCxDQUFjcUcsWUFBZCxJQUE4QixDQUE5QixHQUFrQyxHQUFsQyxHQUF3QyxFQUE5RTs7QUFFQTtBQUNBLGdCQUFJLENBQUMxRCxNQUFMLEVBQWE7QUFDVDtBQUNBLG9CQUFJLDRCQUFrQnNGLE1BQWxCLENBQXlCekcsT0FBekIsS0FBcUMsQ0FBQ0EsUUFBUTZELGFBQWxELEVBQWlFO0FBQzdELHlCQUFLckYsUUFBTCxDQUFjNmlCLHFCQUFkLEdBQXNDLElBQXRDO0FBQ0gsaUJBRkQsTUFFTztBQUNILHlCQUFLN2lCLFFBQUwsQ0FBYzZpQixxQkFBZCxHQUFzQ3JoQixRQUFRNkQsYUFBOUM7QUFDSDs7QUFFRDtBQUNBLHFCQUFLckYsUUFBTCxDQUFjMmlCLDZCQUFkLEdBQThDLEtBQUszaUIsUUFBTCxDQUFjd0YscUJBQTVEOztBQUVBO0FBQ0EscUJBQUs5RSxXQUFMLENBQWlCNGlCLDZCQUFqQixDQUErQyxLQUFLdGpCLFFBQXBEO0FBQ0g7O0FBRUQ7QUFDQSxpQkFBS3VqQixpQ0FBTDtBQUNBLGlCQUFLQyx3Q0FBTDtBQUNBLGlCQUFLQyw0QkFBTDtBQUNBLGlCQUFLQyxLQUFMLEdBQWEsRUFBYixDQTFFa0MsQ0EwRWpCO0FBQ2pCLGlCQUFLaGpCLFdBQUwsQ0FBaUJpakIsOEJBQWpCLENBQWdELEtBQUszakIsUUFBckQsRUFBK0QsS0FBSzBqQixLQUFwRTtBQUNBLGlCQUFLRSxZQUFMOztBQUVBO0FBQ0EsZ0JBQUksNEJBQWtCQyxVQUFsQixDQUE2QixLQUFLN2pCLFFBQWxDLENBQUosRUFBaUQ7QUFDN0MsNENBQWtCK00sVUFBbEIsQ0FBNkIsNEVBQTdCO0FBQ0g7O0FBRUQsaUJBQUtyTSxXQUFMLENBQWlCb2pCLFFBQWpCLENBQTBCLEtBQUs5akIsUUFBL0IsRUFBeUMsS0FBekMsRUFBZ0R3QixPQUFoRDs7QUFFQTtBQUNBLGlCQUFLdWlCLDJCQUFMO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWtDQTs7Ozs7OzJDQU1tQkMsSSxFQUFNO0FBQ3JCLG1CQUFPLEtBQUt0akIsV0FBTCxDQUFpQmdQLDRCQUFqQixDQUE4Q3NVLElBQTlDLEVBQW9ELEtBQUtoa0IsUUFBekQsRUFBbUUsSUFBbkUsRUFBeUUsS0FBS2MsU0FBOUUsRUFBeUY0TixPQUF6RixDQUFpRyxLQUFLMU8sUUFBTCxDQUFjbUYsZ0JBQS9HLEVBQWlJLEdBQWpJLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7OztBQWFBOzs7Ozs7Ozs7b0RBUzRCO0FBQ3hCLGlCQUFLc0YsU0FBTCxHQUFpQiw0QkFBa0JDLG1CQUFsQixDQUFzQyxLQUFLdkwsVUFBM0MsQ0FBakI7QUFDQSxpQkFBS3FiLFNBQUwsR0FBaUIsS0FBakI7QUFDQSxpQkFBS3JLLFNBQUwsR0FBaUIsS0FBakI7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7Ozs7Ozs7NENBY29CL0gsQyxFQUFHO0FBQ25CLGlCQUFLcVMsUUFBTCxHQUFnQiw0QkFBa0IyRyxTQUFsQixDQUE0QmhaLENBQTVCLENBQWhCO0FBQ0g7O0FBRUQ7Ozs7Ozs7OztnREFNd0I7QUFDcEIsaUJBQUszSSxxQkFBTCxHQUE2QixLQUFLbUYsUUFBbEM7QUFDSDs7QUFFRDs7Ozs7Ozs7OztzQ0FPY2dHLEssRUFBT0UsRyxFQUFLO0FBQ3RCO0FBQ0FGLG9CQUFRMlgsS0FBS3JXLEdBQUwsQ0FBU3RCLEtBQVQsRUFBZ0IsQ0FBaEIsQ0FBUjtBQUNBRSxrQkFBTXlYLEtBQUt0VyxHQUFMLENBQVNuQixHQUFULEVBQWMsNEJBQWtCbUYsZUFBbEIsQ0FBa0MsS0FBSzlRLFVBQXZDLEVBQW1EaUwsTUFBakUsQ0FBTjtBQUNBLGlCQUFLSyxTQUFMLEdBQWlCO0FBQ2JHLDRCQURhO0FBRWJFLHdCQUZhO0FBR2JWLHdCQUFRVSxNQUFNRjtBQUhELGFBQWpCOztBQU1BLHdDQUFrQk8sbUJBQWxCLENBQXNDLEtBQUtoTSxVQUEzQyxFQUF1RHlMLEtBQXZELEVBQThERSxHQUE5RDtBQUNIOztBQUVEOzs7Ozs7Ozs7MENBTWtCNlEsUSxFQUFVO0FBQ3hCLGlCQUFLb0YsYUFBTCxDQUFtQnBGLFFBQW5CLEVBQTZCQSxRQUE3QjtBQUNIOztBQUVEOzs7Ozs7Ozs7O2lFQU95QztBQUNyQyxnQkFBTTlaLFFBQVEsNEJBQWtCb08sZUFBbEIsQ0FBa0MsS0FBSzlRLFVBQXZDLENBQWQ7QUFDQSxnQkFBTW9TLE9BQU8xUCxNQUFNb2lCLFNBQU4sQ0FBZ0IsQ0FBaEIsRUFBbUIsS0FBS3haLFNBQUwsQ0FBZUcsS0FBbEMsQ0FBYjtBQUNBLGdCQUFNNkcsUUFBUTVQLE1BQU1vaUIsU0FBTixDQUFnQixLQUFLeFosU0FBTCxDQUFlSyxHQUEvQixFQUFvQ2pKLE1BQU11SSxNQUExQyxDQUFkOztBQUVBLG1CQUFPLENBQUNtSCxJQUFELEVBQU9FLEtBQVAsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7OzRFQU9vRDtBQUFBLHdDQUM1QixLQUFLeVMsc0NBQUwsRUFENEI7QUFBQTtBQUFBLGdCQUMzQzNTLElBRDJDO0FBQUEsZ0JBQ3JDRSxLQURxQzs7QUFFaEQsZ0JBQUlGLFNBQVMsRUFBVCxJQUFlRSxVQUFVLEVBQTdCLEVBQWlDO0FBQzdCLHVCQUFPLENBQUMsRUFBRCxFQUFLLEVBQUwsQ0FBUDtBQUNIOztBQUVEO0FBQ0EsZ0JBQUkwUyxhQUFhLElBQWpCO0FBQ0EsZ0JBQUksS0FBSzFKLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QjBKLE1BQTFDLElBQW9EclcsT0FBT3dELElBQVAsTUFBaUIsQ0FBekUsRUFBNEU7QUFDeEU0Uyw2QkFBYSxLQUFiO0FBQ0g7O0FBRUQsZ0JBQUksS0FBS3pOLGtCQUFMLElBQ0EsNEJBQWtCdEYsVUFBbEIsQ0FBNkJLLEtBQTdCLENBREEsSUFFQSxDQUFDLDRCQUFrQkwsVUFBbEIsQ0FBNkJHLElBQTdCLENBRkwsRUFFeUM7QUFDckM7QUFDQUEsdUJBQU8sTUFBTUEsSUFBYjtBQUNBRSx3QkFBUUEsTUFBTS9DLE9BQU4sQ0FBYyxLQUFLMU8sUUFBTCxDQUFjK1cscUJBQTVCLEVBQW1ELEVBQW5ELENBQVI7QUFDSDs7QUFFRHhGLG1CQUFPelMsWUFBWTRRLDRCQUFaLENBQXlDNkIsSUFBekMsRUFBK0MsS0FBS3ZSLFFBQXBELEVBQThEbWtCLFVBQTlELEVBQTBFLEtBQUtyakIsU0FBL0UsQ0FBUDtBQUNBMlEsb0JBQVEzUyxZQUFZNFEsNEJBQVosQ0FBeUMrQixLQUF6QyxFQUFnRCxLQUFLelIsUUFBckQsRUFBK0QsS0FBL0QsRUFBc0UsS0FBS2MsU0FBM0UsQ0FBUjs7QUFFQSxtQkFBTyxDQUFDeVEsSUFBRCxFQUFPRSxLQUFQLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7d0NBUWdCRixJLEVBQU1FLEssRUFBTztBQUN6QjtBQUNBO0FBQ0EsZ0JBQUkwUyxhQUFhLElBQWpCO0FBQ0EsZ0JBQUksS0FBSzFKLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QjBKLE1BQTFDLElBQW9EclcsT0FBT3dELElBQVAsTUFBaUIsQ0FBekUsRUFBNEU7QUFDeEU0Uyw2QkFBYSxLQUFiO0FBQ0g7O0FBRUQsZ0JBQUksS0FBS3pOLGtCQUFMLElBQ0EsNEJBQWtCdEYsVUFBbEIsQ0FBNkJLLEtBQTdCLENBREEsSUFFQSxDQUFDLDRCQUFrQkwsVUFBbEIsQ0FBNkJHLElBQTdCLENBRkwsRUFFeUM7QUFDckM7QUFDQUEsdUJBQU8sTUFBTUEsSUFBYjtBQUNBRSx3QkFBUUEsTUFBTS9DLE9BQU4sQ0FBYyxLQUFLMU8sUUFBTCxDQUFjK1cscUJBQTVCLEVBQW1ELEVBQW5ELENBQVI7QUFDSDs7QUFFRHhGLG1CQUFPelMsWUFBWTRRLDRCQUFaLENBQXlDNkIsSUFBekMsRUFBK0MsS0FBS3ZSLFFBQXBELEVBQThEbWtCLFVBQTlELEVBQTBFLEtBQUtyakIsU0FBL0UsQ0FBUDtBQUNBMlEsb0JBQVEzUyxZQUFZNFEsNEJBQVosQ0FBeUMrQixLQUF6QyxFQUFnRCxLQUFLelIsUUFBckQsRUFBK0QsS0FBL0QsRUFBc0UsS0FBS2MsU0FBM0UsQ0FBUjs7QUFFQTtBQUNBLGdCQUFJLEtBQUtkLFFBQUwsQ0FBY29HLFdBQWQsS0FBOEJ0SCxZQUFZMEMsT0FBWixDQUFvQjRFLFdBQXBCLENBQWdDaWUsSUFBOUQsS0FDQyxLQUFLNUosUUFBTCxLQUFrQiwwQkFBZ0JDLE9BQWhCLENBQXdCNEosSUFBMUMsSUFBa0QsS0FBSzdKLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QjZKLE9BRDdGLEtBRUF4VyxPQUFPd0QsSUFBUCxNQUFpQixDQUZqQjtBQUdBO0FBQ0EsYUFBQyw0QkFBa0JnRyxRQUFsQixDQUEyQmhHLElBQTNCLEVBQWlDLEtBQUt2UixRQUFMLENBQWNtRixnQkFBL0MsQ0FKRCxJQUlxRXNNLFVBQVUsRUFKbkYsRUFJdUY7QUFDbkZGLHVCQUFPQSxLQUFLMFMsU0FBTCxDQUFlLENBQWYsRUFBa0IxUyxLQUFLbkgsTUFBTCxHQUFjLENBQWhDLENBQVA7QUFDSDs7QUFFRDtBQUNBLGdCQUFJN0ksV0FBV2dRLE9BQU9FLEtBQXRCO0FBQ0EsZ0JBQUksS0FBS3pSLFFBQUwsQ0FBY21GLGdCQUFsQixFQUFvQztBQUNoQyxvQkFBTXFmLElBQUlqakIsU0FBU3lWLEtBQVQsQ0FBZSxJQUFJeU4sTUFBSixPQUFlLEtBQUtmLEtBQUwsQ0FBV2dCLGdCQUExQixVQUErQyxLQUFLMWtCLFFBQUwsQ0FBY21GLGdCQUE3RCxDQUFmLENBQVY7QUFDQSxvQkFBSXFmLENBQUosRUFBTztBQUNIalQsMkJBQU9BLEtBQUs3QyxPQUFMLENBQWE4VixFQUFFLENBQUYsQ0FBYixFQUFtQkEsRUFBRSxDQUFGLElBQU8sR0FBMUIsQ0FBUDtBQUNBampCLCtCQUFXZ1EsT0FBT0UsS0FBbEI7QUFDSDtBQUNKOztBQUVELG1CQUFPLENBQUNGLElBQUQsRUFBT0UsS0FBUCxFQUFjbFEsUUFBZCxDQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7Ozs7O3VDQVdlZ1EsSSxFQUFNRSxLLEVBQXdCO0FBQUEsZ0JBQWpCa1QsT0FBaUIsdUVBQVAsS0FBTzs7QUFBQSxtQ0FDcUIsS0FBS0MsZUFBTCxDQUFxQnJULElBQXJCLEVBQTJCRSxLQUEzQixDQURyQjtBQUFBO0FBQUEsZ0JBQ2xDb1QsY0FEa0M7QUFBQSxnQkFDbEJDLGVBRGtCO0FBQUEsZ0JBQ0RDLGtCQURDOztBQUFBLHdDQUVkam1CLFlBQVlvUCxpQ0FBWixDQUE4QzZXLGtCQUE5QyxFQUFrRSxLQUFLL2tCLFFBQXZFLENBRmM7QUFBQTtBQUFBLGdCQUVsQ21PLE9BRmtDO0FBQUEsZ0JBRXpCQyxPQUZ5Qjs7QUFJekMsZ0JBQUlELFdBQVdDLE9BQWYsRUFBd0I7QUFDcEI7QUFDQSxvQkFBTTRXLGtCQUFrQmxtQixZQUFZbW1CLHNCQUFaLENBQW1DRixrQkFBbkMsRUFBdUQsS0FBSy9rQixRQUE1RCxFQUFzRTJrQixPQUF0RSxFQUErRSxLQUFLM2tCLFFBQUwsQ0FBY3dGLHFCQUE3RixDQUF4QjtBQUNBLG9CQUFNMGYsWUFBWUYsZ0JBQWdCdFcsT0FBaEIsQ0FBd0IsS0FBSzFPLFFBQUwsQ0FBY21GLGdCQUF0QyxFQUF3RCxHQUF4RCxDQUFsQjs7QUFFQSxvQkFBSStmLGNBQWMsRUFBZCxJQUFvQkEsY0FBYyxLQUFLbGxCLFFBQUwsQ0FBYytXLHFCQUFwRCxFQUEyRTtBQUN2RSx3QkFBSW9PLDBCQUFKO0FBQ0EsNEJBQVEsS0FBS25sQixRQUFMLENBQWMrRixrQkFBdEI7QUFDSSw2QkFBS2pILFlBQVkwQyxPQUFaLENBQW9CdUUsa0JBQXBCLENBQXVDa0ksSUFBNUM7QUFDSWtYLGdEQUFvQixHQUFwQjtBQUNBO0FBQ0osNkJBQUtybUIsWUFBWTBDLE9BQVosQ0FBb0J1RSxrQkFBcEIsQ0FBdUNDLElBQTVDO0FBQ0ltZixnREFBb0IsSUFBcEI7QUFDQTtBQUNKO0FBQ0lBLGdEQUFvQixFQUFwQjtBQVJSOztBQVdBLHlCQUFLNVUsWUFBTCxDQUFrQjRVLGlCQUFsQjtBQUNILGlCQWRELE1BY087QUFDSCx5QkFBSzVVLFlBQUwsQ0FBa0IsS0FBSzlCLDRCQUFMLENBQWtDeVcsU0FBbEMsQ0FBbEI7QUFDSDs7QUFFRDtBQUNBLG9CQUFNRSxxQkFBcUJ0bUIsWUFBWW1tQixzQkFBWixDQUFtQ0Ysa0JBQW5DLEVBQXVELEtBQUsva0IsUUFBNUQsRUFBc0Uya0IsT0FBdEUsRUFBK0UsS0FBSzNrQixRQUFMLENBQWMwRix5QkFBN0YsQ0FBM0I7QUFDQSxvQkFBSWlXLFdBQVdrSixlQUFlemEsTUFBOUI7QUFDQSxvQkFBSXVSLFdBQVd5SixtQkFBbUJoYixNQUFsQyxFQUEwQztBQUN0Q3VSLCtCQUFXeUosbUJBQW1CaGIsTUFBOUI7QUFDSDs7QUFFRDtBQUNBLG9CQUFJdVIsYUFBYSxDQUFiLElBQWtCa0osbUJBQW1CLEdBQXJDLElBQTRDLEtBQUs3a0IsUUFBTCxDQUFjb0csV0FBZCxLQUE4QnRILFlBQVkwQyxPQUFaLENBQW9CNEUsV0FBcEIsQ0FBZ0NpZSxJQUE5RyxFQUFvSDtBQUNoSDtBQUNBLHdCQUFJUyxvQkFBb0IsRUFBcEIsSUFBMEJELG1CQUFtQixHQUFuQixJQUEwQkMsb0JBQW9CLEVBQTVFLEVBQWdGO0FBQzVFbkosbUNBQVcsQ0FBWDtBQUNILHFCQUZELE1BRU87QUFDSEEsbUNBQVcsQ0FBWDtBQUNIO0FBQ0o7O0FBRUQsNENBQWtCekwsZUFBbEIsQ0FBa0MsS0FBSy9RLFVBQXZDLEVBQW1EaW1CLGtCQUFuRDtBQUNBLHFCQUFLbEosaUJBQUwsQ0FBdUJQLFFBQXZCOztBQUVBLHVCQUFPLElBQVA7QUFDSDs7QUFFRCxnQkFBSSxDQUFDeE4sT0FBTCxFQUFjO0FBQ1YsNENBQWtCYyxZQUFsQixDQUErQm5RLFlBQVlvUSxNQUFaLENBQW1CQyxnQkFBbEQsRUFBb0UsS0FBS2hRLFVBQXpFO0FBQ0gsYUFGRCxNQUVPLElBQUksQ0FBQ2lQLE9BQUwsRUFBYztBQUNqQiw0Q0FBa0JhLFlBQWxCLENBQStCblEsWUFBWW9RLE1BQVosQ0FBbUJFLGdCQUFsRCxFQUFvRSxLQUFLalEsVUFBekU7QUFDSDs7QUFFRCxtQkFBTyxLQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7OzsyQ0FNbUI7QUFDZixnQkFBSTZDLGVBQUo7QUFDQSxnQkFBSSxLQUFLaEMsUUFBTCxDQUFjaUYsY0FBbEIsRUFBa0M7QUFDOUIsb0JBQU1vZ0Isb0JBQW9CLEtBQUtybEIsUUFBTCxDQUFjaUYsY0FBZCxDQUE2Qm1GLE1BQXZEO0FBQ0Esb0JBQU12SSxRQUFRLDRCQUFrQm9PLGVBQWxCLENBQWtDLEtBQUs5USxVQUF2QyxDQUFkO0FBQ0Esb0JBQUksS0FBS2EsUUFBTCxDQUFja0YsdUJBQWQsS0FBMENwRyxZQUFZMEMsT0FBWixDQUFvQjBELHVCQUFwQixDQUE0Q3NNLE1BQTFGLEVBQWtHO0FBQzlGLHdCQUFNOFQsU0FBUyxLQUFLdGxCLFFBQUwsQ0FBYytXLHFCQUFkLElBQXVDbFYsS0FBdkMsSUFBZ0RBLE1BQU1rYSxNQUFOLENBQWEsQ0FBYixNQUFvQixLQUFLL2IsUUFBTCxDQUFjK1cscUJBQWpHO0FBQ0Esd0JBQUl1TyxNQUFKLEVBQVk7QUFDUnRqQixpQ0FBUyxDQUFDLENBQUQsRUFBSXFqQixvQkFBb0IsQ0FBeEIsQ0FBVDtBQUNILHFCQUZELE1BRU87QUFDSHJqQixpQ0FBUyxDQUFDLENBQUQsRUFBSXFqQixpQkFBSixDQUFUO0FBQ0g7QUFDSixpQkFQRCxNQU9PO0FBQ0gsd0JBQU1wVSxXQUFXcFAsTUFBTXVJLE1BQXZCO0FBQ0FwSSw2QkFBUyxDQUFDaVAsV0FBV29VLGlCQUFaLEVBQStCcFUsUUFBL0IsQ0FBVDtBQUNIO0FBQ0osYUFkRCxNQWNPO0FBQ0hqUCx5QkFBUyxDQUFDLElBQUQsRUFBTyxDQUFDLENBQVIsQ0FBVDtBQUNIOztBQUVELG1CQUFPQSxNQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7O2lEQUt5QjtBQUFBLG9DQUMwQixLQUFLdWpCLGdCQUFMLEVBRDFCO0FBQUE7QUFBQSxnQkFDZEMsWUFEYztBQUFBLGdCQUNBQyxzQkFEQTs7QUFFckIsZ0JBQU1oYixZQUFZLEtBQUtBLFNBQXZCOztBQUVBO0FBQ0EsZ0JBQUlBLFVBQVVHLEtBQVYsR0FBa0I2YSxzQkFBbEIsSUFBNENoYixVQUFVSyxHQUFWLEdBQWdCMGEsWUFBaEUsRUFBOEU7QUFDMUU7QUFDQSxvQkFBSSxDQUFDL2EsVUFBVUcsS0FBVixHQUFrQjRhLFlBQWxCLElBQWtDL2EsVUFBVUssR0FBVixHQUFnQjJhLHNCQUFuRCxLQUNBLDRCQUFrQnhWLGVBQWxCLENBQWtDLEtBQUs5USxVQUF2QyxFQUFtRDhrQixTQUFuRCxDQUE2RDFCLEtBQUtyVyxHQUFMLENBQVN6QixVQUFVRyxLQUFuQixFQUEwQjRhLFlBQTFCLENBQTdELEVBQXNHakQsS0FBS3RXLEdBQUwsQ0FBU3hCLFVBQVVLLEdBQW5CLEVBQXdCMmEsc0JBQXhCLENBQXRHLEVBQ0t6TyxLQURMLENBQ1csT0FEWCxDQURKLEVBRXlCO0FBQ3JCLHdCQUFJdk0sVUFBVUcsS0FBVixHQUFrQjRhLFlBQXRCLEVBQW9DO0FBQ2hDLDZCQUFLekUsYUFBTCxDQUFtQnRXLFVBQVVHLEtBQTdCLEVBQW9DNGEsWUFBcEM7QUFDSCxxQkFGRCxNQUVPO0FBQ0gsNkJBQUt6RSxhQUFMLENBQW1CMEUsc0JBQW5CLEVBQTJDaGIsVUFBVUssR0FBckQ7QUFDSDtBQUNKLGlCQVJELE1BUU87QUFDSDtBQUNBLHlCQUFLaVcsYUFBTCxDQUFtQndCLEtBQUt0VyxHQUFMLENBQVN4QixVQUFVRyxLQUFuQixFQUEwQjRhLFlBQTFCLENBQW5CLEVBQTREakQsS0FBS3JXLEdBQUwsQ0FBU3pCLFVBQVVLLEdBQW5CLEVBQXdCMmEsc0JBQXhCLENBQTVEO0FBQ0g7QUFDSjtBQUNKOztBQUVEOzs7Ozs7c0NBR2M7QUFDVixnQkFBSSxDQUFDLDRCQUFrQi9YLFdBQWxCLENBQThCLEtBQUtpUCxxQkFBbkMsQ0FBTCxFQUFnRTtBQUM1RCxvQkFBTStJLFdBQVcsS0FBSy9JLHFCQUF0Qjs7QUFENEQsNkNBRXRDLEtBQUt1SCxzQ0FBTCxFQUZzQztBQUFBO0FBQUEsb0JBRXJEM1MsSUFGcUQ7QUFBQSxvQkFFL0NFLEtBRitDOztBQUk1RDs7O0FBQ0EsdUJBQU8sS0FBS2tMLHFCQUFaOztBQUVBLG9CQUFNMkMsbUJBQW1CL04sS0FBS29VLE1BQUwsQ0FBWSxDQUFaLEVBQWVELFNBQVMsQ0FBVCxFQUFZdGIsTUFBM0IsSUFBcUN0TCxZQUFZNFEsNEJBQVosQ0FBeUM2QixLQUFLb1UsTUFBTCxDQUFZRCxTQUFTLENBQVQsRUFBWXRiLE1BQXhCLENBQXpDLEVBQTBFLEtBQUtwSyxRQUEvRSxFQUF5RixJQUF6RixFQUErRixLQUFLYyxTQUFwRyxDQUE5RDtBQUNBLG9CQUFJLENBQUMsS0FBSzhrQixjQUFMLENBQW9CdEcsZ0JBQXBCLEVBQXNDN04sS0FBdEMsRUFBNkMsSUFBN0MsQ0FBTCxFQUF5RDtBQUNyRCxnREFBa0J2QixlQUFsQixDQUFrQyxLQUFLL1EsVUFBdkMsRUFBbUR1bUIsU0FBU0csSUFBVCxDQUFjLEVBQWQsQ0FBbkQ7QUFDQSx5QkFBSzNKLGlCQUFMLENBQXVCd0osU0FBUyxDQUFULEVBQVl0YixNQUFuQztBQUNIO0FBQ0o7QUFDSjs7QUFFRDs7Ozs7Ozs7Ozs7O0FBcUJBOzs7Ozs7Ozs2REFRcUNoQyxDLEVBQUc7QUFDcEM7QUFDQSxnQkFBSyxDQUFDQSxFQUFFaVUsT0FBRixJQUFhalUsRUFBRTBkLE9BQWhCLEtBQTRCMWQsRUFBRThRLElBQUYsS0FBVyxPQUF2QyxJQUFrRCxDQUFDLDRCQUFrQnhMLFdBQWxCLENBQThCLEtBQUtpUCxxQkFBbkMsQ0FBcEQsSUFBbUh2VSxFQUFFa1UsUUFBRixJQUFjLEtBQUs3QixRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0JjLE1BQS9LLEVBQXdMO0FBQ3BMO0FBQ0EscUJBQUt1SyxXQUFMOztBQUVBLHVCQUFPLEtBQVA7QUFDSDs7QUFFRDtBQUNBLGdCQUFJLEtBQUtybEIsV0FBTCxDQUFpQnNsQixtQkFBakIsQ0FBcUMsS0FBS3ZMLFFBQTFDLENBQUosRUFBeUQ7QUFDckQsdUJBQU8sSUFBUDtBQUNIOztBQUVEO0FBQ0EsZ0JBQUksQ0FBQ3JTLEVBQUVpVSxPQUFGLElBQWFqVSxFQUFFMGQsT0FBaEIsS0FBNEIsS0FBS3JMLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QnVMLENBQTFFLEVBQTZFO0FBQ3pFLG9CQUFJLEtBQUtqbUIsUUFBTCxDQUFjcUgsZ0JBQWxCLEVBQW9DO0FBQ2hDO0FBQ0FlLHNCQUFFd1MsY0FBRjtBQUNBO0FBQ0EseUJBQUs5SixZQUFMO0FBQ0g7O0FBRUQsdUJBQU8sSUFBUDtBQUNIOztBQUVEO0FBQ0EsZ0JBQUksQ0FBQzFJLEVBQUVpVSxPQUFGLElBQWFqVSxFQUFFMGQsT0FBaEIsTUFBNkIsS0FBS3JMLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QndMLENBQTFDLElBQStDLEtBQUt6TCxRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0J5TCxDQUF6RixJQUE4RixLQUFLMUwsUUFBTCxLQUFrQiwwQkFBZ0JDLE9BQWhCLENBQXdCMEwsQ0FBckssQ0FBSixFQUE2SztBQUN6SyxvQkFBSWhlLEVBQUU4USxJQUFGLEtBQVcsU0FBZixFQUEwQjtBQUN0Qix5QkFBS21OLHNCQUFMO0FBQ0g7O0FBRUQ7QUFDQSxvQkFBSSxLQUFLNUwsUUFBTCxLQUFrQiwwQkFBZ0JDLE9BQWhCLENBQXdCeUwsQ0FBMUMsSUFBK0MsS0FBSzFMLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QmMsTUFBN0YsRUFBcUc7QUFDakcsd0JBQUlwVCxFQUFFOFEsSUFBRixLQUFXLFNBQVgsSUFBd0I5USxFQUFFOFEsSUFBRixLQUFXLFVBQXZDLEVBQW1EO0FBQy9DLDRCQUFJLDRCQUFrQnhMLFdBQWxCLENBQThCLEtBQUtpUCxxQkFBbkMsQ0FBSixFQUErRDtBQUMzRCxpQ0FBS0EscUJBQUwsR0FBNkIsS0FBS3VILHNDQUFMLEVBQTdCO0FBQ0g7QUFDSixxQkFKRCxNQUlPO0FBQ0gsNkJBQUs2QixXQUFMO0FBQ0g7QUFDSjs7QUFFRCx1QkFBTzNkLEVBQUU4USxJQUFGLEtBQVcsU0FBWCxJQUF3QjlRLEVBQUU4USxJQUFGLEtBQVcsVUFBbkMsSUFBaUQsS0FBS3VCLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QndMLENBQWxHO0FBQ0g7O0FBRUQsZ0JBQUk5ZCxFQUFFaVUsT0FBRixJQUFhalUsRUFBRTBkLE9BQW5CLEVBQTRCO0FBQ3hCLG9CQUFJLEtBQUtyTCxRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0J5QixDQUExQyxJQUErQyxLQUFLMUIsUUFBTCxLQUFrQiwwQkFBZ0JDLE9BQWhCLENBQXdCMEIsQ0FBN0YsRUFBZ0c7QUFDNUYsMkJBQU8sS0FBUDtBQUNILGlCQUZELE1BRU87QUFDSCwyQkFBTyxJQUFQO0FBQ0g7QUFDSjs7QUFFRDtBQUNBO0FBQ0EsZ0JBQUksS0FBSzNCLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QjRMLFNBQTFDLElBQXVELEtBQUs3TCxRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0I2TCxVQUFyRyxFQUFpSDtBQUM3RyxvQkFBSW5lLEVBQUU4USxJQUFGLEtBQVcsU0FBWCxJQUF3QixDQUFDOVEsRUFBRWtVLFFBQS9CLEVBQXlDO0FBQ3JDLHdCQUFNemEsUUFBUSw0QkFBa0JvTyxlQUFsQixDQUFrQyxLQUFLOVEsVUFBdkMsQ0FBZDtBQUNBLHdCQUFJLEtBQUtzYixRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0I0TCxTQUExQyxLQUNDemtCLE1BQU1rYSxNQUFOLENBQWEsS0FBS3RSLFNBQUwsQ0FBZUcsS0FBZixHQUF1QixDQUFwQyxNQUEyQyxLQUFLNUssUUFBTCxDQUFjNkYsbUJBQXpELElBQ0RoRSxNQUFNa2EsTUFBTixDQUFhLEtBQUt0UixTQUFMLENBQWVHLEtBQWYsR0FBdUIsQ0FBcEMsTUFBMkMsS0FBSzVLLFFBQUwsQ0FBY21GLGdCQUZ6RCxDQUFKLEVBRWdGO0FBQzVFLDZCQUFLK1csaUJBQUwsQ0FBdUIsS0FBS3pSLFNBQUwsQ0FBZUcsS0FBZixHQUF1QixDQUE5QztBQUNILHFCQUpELE1BSU8sSUFBSSxLQUFLNlAsUUFBTCxLQUFrQiwwQkFBZ0JDLE9BQWhCLENBQXdCNkwsVUFBMUMsS0FDTjFrQixNQUFNa2EsTUFBTixDQUFhLEtBQUt0UixTQUFMLENBQWVHLEtBQWYsR0FBdUIsQ0FBcEMsTUFBMkMsS0FBSzVLLFFBQUwsQ0FBYzZGLG1CQUF6RCxJQUNEaEUsTUFBTWthLE1BQU4sQ0FBYSxLQUFLdFIsU0FBTCxDQUFlRyxLQUFmLEdBQXVCLENBQXBDLE1BQTJDLEtBQUs1SyxRQUFMLENBQWNtRixnQkFGbEQsQ0FBSixFQUV5RTtBQUM1RSw2QkFBSytXLGlCQUFMLENBQXVCLEtBQUt6UixTQUFMLENBQWVHLEtBQWYsR0FBdUIsQ0FBOUM7QUFDSDtBQUNKOztBQUVELHVCQUFPLElBQVA7QUFDSDs7QUFFRCxtQkFBTyw0QkFBa0JpQyxTQUFsQixDQUE0QixLQUFLNE4sUUFBakMsRUFBMkMsMEJBQWdCQyxPQUFoQixDQUF3QjhMLGNBQW5FLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7K0VBUStEO0FBQUE7QUFBQSxnQkFBZGpWLElBQWM7QUFBQSxnQkFBUkUsS0FBUTs7QUFDM0QsZ0JBQU01UCxRQUFRLDRCQUFrQm9PLGVBQWxCLENBQWtDLEtBQUs5USxVQUF2QyxDQUFkOztBQUVBLGdCQUFJLEtBQUthLFFBQUwsQ0FBY2tGLHVCQUFkLEtBQTBDcEcsWUFBWTBDLE9BQVosQ0FBb0IwRCx1QkFBcEIsQ0FBNENzTSxNQUF0RixJQUFnRyxLQUFLeFIsUUFBTCxDQUFjeUcsNkJBQWQsS0FBZ0QzSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRDZLLE1BQXRNLEVBQThNO0FBQzFNLG9CQUFJLEtBQUttSixRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0JTLFNBQTlDLEVBQXlEO0FBQ3JELHlCQUFLOEgsUUFBTCxHQUFpQixLQUFLeFksU0FBTCxDQUFlRyxLQUFmLElBQXdCL0ksTUFBTWdRLE9BQU4sQ0FBYyxLQUFLN1IsUUFBTCxDQUFjMkgsVUFBNUIsQ0FBeEIsSUFBbUUsS0FBSzNILFFBQUwsQ0FBYzJILFVBQWQsS0FBNkIsRUFBakg7QUFDQSx3QkFBSTlGLE1BQU1rYSxNQUFOLENBQWEsS0FBS3RSLFNBQUwsQ0FBZUcsS0FBZixHQUF1QixDQUFwQyxNQUEyQyxHQUEvQyxFQUFvRDtBQUNoRDJHLCtCQUFPQSxLQUFLMFMsU0FBTCxDQUFlLENBQWYsQ0FBUDtBQUNILHFCQUZELE1BRU8sSUFBSSxLQUFLeFosU0FBTCxDQUFlRyxLQUFmLElBQXdCL0ksTUFBTXVJLE1BQU4sR0FBZSxLQUFLcEssUUFBTCxDQUFjMkgsVUFBZCxDQUF5QnlDLE1BQXBFLEVBQTRFO0FBQy9FbUgsK0JBQU9BLEtBQUswUyxTQUFMLENBQWUsQ0FBZixFQUFrQjFTLEtBQUtuSCxNQUFMLEdBQWMsQ0FBaEMsQ0FBUDtBQUNIO0FBQ0osaUJBUEQsTUFPTztBQUNILHlCQUFLNlksUUFBTCxHQUFpQixLQUFLeFksU0FBTCxDQUFlRyxLQUFmLElBQXdCL0ksTUFBTWdRLE9BQU4sQ0FBYyxLQUFLN1IsUUFBTCxDQUFjMkgsVUFBNUIsQ0FBeEIsSUFBbUUsS0FBSzNILFFBQUwsQ0FBYzJILFVBQWQsS0FBNkIsRUFBakg7QUFDQSx3QkFBSSxLQUFLOEMsU0FBTCxDQUFlRyxLQUFmLElBQXdCL0ksTUFBTWdRLE9BQU4sQ0FBYyxLQUFLN1IsUUFBTCxDQUFjaUYsY0FBNUIsSUFBOEMsS0FBS2pGLFFBQUwsQ0FBY2lGLGNBQWQsQ0FBNkJtRixNQUF2RyxFQUErRztBQUMzR3FILGdDQUFRQSxNQUFNd1MsU0FBTixDQUFnQixDQUFoQixFQUFtQnhTLE1BQU1ySCxNQUF6QixDQUFSO0FBQ0g7QUFDRCx3QkFBSSw0QkFBa0JnSCxVQUFsQixDQUE2QkcsSUFBN0IsS0FBc0MxUCxNQUFNa2EsTUFBTixDQUFhLEtBQUt0UixTQUFMLENBQWVHLEtBQTVCLE1BQXVDLEdBQWpGLEVBQXNGO0FBQ2xGMkcsK0JBQU9BLEtBQUswUyxTQUFMLENBQWUsQ0FBZixDQUFQO0FBQ0g7QUFDSjtBQUNKOztBQUVELGdCQUFJLEtBQUtqa0IsUUFBTCxDQUFja0YsdUJBQWQsS0FBMENwRyxZQUFZMEMsT0FBWixDQUFvQjBELHVCQUFwQixDQUE0Q29NLE1BQTFGLEVBQWtHO0FBQzlGLHdCQUFRLEtBQUt0UixRQUFMLENBQWN5Ryw2QkFBdEI7QUFDSSx5QkFBSzNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEOEssSUFBdkQ7QUFDSSw2QkFBSzBSLFFBQUwsR0FBaUIsS0FBS3hZLFNBQUwsQ0FBZUcsS0FBZixJQUF3Qi9JLE1BQU1nUSxPQUFOLENBQWMsS0FBSzdSLFFBQUwsQ0FBYytXLHFCQUE1QixJQUFxRCxLQUFLL1csUUFBTCxDQUFjK1cscUJBQWQsQ0FBb0MzTSxNQUFsSTtBQUNBLDRCQUFJLEtBQUtxUSxRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0JTLFNBQTlDLEVBQXlEO0FBQ3JELGdDQUFJLEtBQUsxUSxTQUFMLENBQWVHLEtBQWYsS0FBMEIvSSxNQUFNZ1EsT0FBTixDQUFjLEtBQUs3UixRQUFMLENBQWMrVyxxQkFBNUIsSUFBcUQsS0FBSy9XLFFBQUwsQ0FBYytXLHFCQUFkLENBQW9DM00sTUFBbkgsSUFBOEgsNEJBQWtCbU4sUUFBbEIsQ0FBMkIxVixLQUEzQixFQUFrQyxLQUFLN0IsUUFBTCxDQUFjK1cscUJBQWhELENBQWxJLEVBQTBNO0FBQ3RNeEYsdUNBQU9BLEtBQUswUyxTQUFMLENBQWUsQ0FBZixDQUFQO0FBQ0gsNkJBRkQsTUFFTyxJQUFJMVMsU0FBUyxHQUFULEtBQWtCLEtBQUs5RyxTQUFMLENBQWVHLEtBQWYsSUFBd0IvSSxNQUFNZ1EsT0FBTixDQUFjLEtBQUs3UixRQUFMLENBQWMrVyxxQkFBNUIsQ0FBekIsSUFBZ0YsQ0FBQyw0QkFBa0JRLFFBQWxCLENBQTJCMVYsS0FBM0IsRUFBa0MsS0FBSzdCLFFBQUwsQ0FBYytXLHFCQUFoRCxDQUFsRyxDQUFKLEVBQStLO0FBQ2xMeEYsdUNBQU9BLEtBQUswUyxTQUFMLENBQWUsQ0FBZixFQUFrQjFTLEtBQUtuSCxNQUFMLEdBQWMsQ0FBaEMsQ0FBUDtBQUNIO0FBQ0oseUJBTkQsTUFNTztBQUNILGdDQUFJbUgsS0FBSyxDQUFMLE1BQVksR0FBaEIsRUFBcUI7QUFDakJFLHdDQUFRQSxNQUFNd1MsU0FBTixDQUFnQixDQUFoQixDQUFSO0FBQ0g7QUFDRCxnQ0FBSSxLQUFLeFosU0FBTCxDQUFlRyxLQUFmLEtBQXlCL0ksTUFBTWdRLE9BQU4sQ0FBYyxLQUFLN1IsUUFBTCxDQUFjK1cscUJBQTVCLENBQXpCLElBQStFLDRCQUFrQlEsUUFBbEIsQ0FBMkIxVixLQUEzQixFQUFrQyxLQUFLN0IsUUFBTCxDQUFjK1cscUJBQWhELENBQW5GLEVBQTJKO0FBQ3ZKeEYsdUNBQU9BLEtBQUswUyxTQUFMLENBQWUsQ0FBZixDQUFQO0FBQ0g7QUFDSjtBQUNEO0FBQ0oseUJBQUtubEIsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0RnTCxLQUF2RDtBQUNJLDZCQUFLd1IsUUFBTCxHQUFpQixLQUFLeFksU0FBTCxDQUFlRyxLQUFmLElBQXdCL0ksTUFBTWdRLE9BQU4sQ0FBYyxLQUFLN1IsUUFBTCxDQUFjK1cscUJBQTVCLElBQXFELEtBQUsvVyxRQUFMLENBQWMrVyxxQkFBZCxDQUFvQzNNLE1BQWxJO0FBQ0EsNEJBQUksS0FBS3FRLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QlMsU0FBOUMsRUFBeUQ7QUFDckQsZ0NBQUksS0FBSzFRLFNBQUwsQ0FBZUcsS0FBZixLQUEwQi9JLE1BQU1nUSxPQUFOLENBQWMsS0FBSzdSLFFBQUwsQ0FBYytXLHFCQUE1QixJQUFxRCxLQUFLL1csUUFBTCxDQUFjK1cscUJBQWQsQ0FBb0MzTSxNQUF2SCxFQUFnSTtBQUM1SG1ILHVDQUFPQSxLQUFLMFMsU0FBTCxDQUFlLENBQWYsQ0FBUDtBQUNILDZCQUZELE1BRU8sSUFBSTFTLFNBQVMsR0FBVCxJQUFnQixLQUFLOUcsU0FBTCxDQUFlRyxLQUFmLElBQXlCL0ksTUFBTWdRLE9BQU4sQ0FBYyxLQUFLN1IsUUFBTCxDQUFjK1cscUJBQTVCLElBQXFELEtBQUsvVyxRQUFMLENBQWNpRixjQUFkLENBQTZCbUYsTUFBL0gsRUFBd0k7QUFDM0ltSCx1Q0FBT0EsS0FBSzBTLFNBQUwsQ0FBZSxDQUFmLEVBQWtCMVMsS0FBS25ILE1BQUwsR0FBYyxDQUFoQyxDQUFQO0FBQ0gsNkJBRk0sTUFFQSxJQUFJbUgsU0FBUyxFQUFULElBQWUsQ0FBQyw0QkFBa0JnRyxRQUFsQixDQUEyQjFWLEtBQTNCLEVBQWtDLEtBQUs3QixRQUFMLENBQWMrVyxxQkFBaEQsQ0FBcEIsRUFBNEY7QUFDL0Z4Rix1Q0FBT0EsS0FBSzBTLFNBQUwsQ0FBZSxDQUFmLEVBQWtCMVMsS0FBS25ILE1BQUwsR0FBYyxDQUFoQyxDQUFQO0FBQ0g7QUFDSix5QkFSRCxNQVFPO0FBQ0gsaUNBQUs2WSxRQUFMLEdBQWlCLEtBQUt4WSxTQUFMLENBQWVHLEtBQWYsSUFBd0IvSSxNQUFNZ1EsT0FBTixDQUFjLEtBQUs3UixRQUFMLENBQWNpRixjQUE1QixDQUF4QixJQUF1RSxLQUFLakYsUUFBTCxDQUFjaUYsY0FBZCxLQUFpQyxFQUF6SDtBQUNBLGdDQUFJLEtBQUt3RixTQUFMLENBQWVHLEtBQWYsS0FBeUIvSSxNQUFNZ1EsT0FBTixDQUFjLEtBQUs3UixRQUFMLENBQWMrVyxxQkFBNUIsQ0FBN0IsRUFBaUY7QUFDN0V4Rix1Q0FBT0EsS0FBSzBTLFNBQUwsQ0FBZSxDQUFmLENBQVA7QUFDSDs7QUFFRHhTLG9DQUFRQSxNQUFNd1MsU0FBTixDQUFnQixDQUFoQixDQUFSO0FBQ0g7QUFDRDtBQXBDUjtBQXNDSDs7QUFFRCxtQkFBTyxDQUFDMVMsSUFBRCxFQUFPRSxLQUFQLENBQVA7QUFDSDs7QUFFRDs7Ozs7O29EQUc0QjtBQUN4QixnQkFBSUYsYUFBSjtBQUNBLGdCQUFJRSxjQUFKOztBQUVBLGdCQUFJLENBQUMsS0FBS2hILFNBQUwsQ0FBZUwsTUFBcEIsRUFBNEI7QUFBQSw0Q0FDUixLQUFLcWMsaURBQUwsRUFEUTs7QUFBQTs7QUFDdkJsVixvQkFEdUI7QUFDakJFLHFCQURpQjs7QUFFeEIsb0JBQUlGLFNBQVMsRUFBVCxJQUFlRSxVQUFVLEVBQTdCLEVBQWlDO0FBQzdCLHlCQUFLOEosVUFBTCxHQUFrQixLQUFsQjtBQUNIOztBQUVELG9CQUFJLEtBQUs3RSxrQkFBTCxJQUEyQiw0QkFBa0J0RixVQUFsQixDQUE2Qiw0QkFBa0JuQixlQUFsQixDQUFrQyxLQUFLOVEsVUFBdkMsQ0FBN0IsQ0FBL0IsRUFBaUg7QUFBQSxnREFDN0YsS0FBS3VuQiwrQ0FBTCxDQUFxRCxDQUFDblYsSUFBRCxFQUFPRSxLQUFQLENBQXJELENBRDZGOztBQUFBOztBQUM1R0Ysd0JBRDRHO0FBQ3RHRSx5QkFEc0c7QUFFaEgsaUJBRkQsTUFFTztBQUNILHdCQUFJLEtBQUtnSixRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0JTLFNBQTlDLEVBQXlEO0FBQ3JENUosK0JBQU9BLEtBQUswUyxTQUFMLENBQWUsQ0FBZixFQUFrQjFTLEtBQUtuSCxNQUFMLEdBQWMsQ0FBaEMsQ0FBUDtBQUNILHFCQUZELE1BRU87QUFDSHFILGdDQUFRQSxNQUFNd1MsU0FBTixDQUFnQixDQUFoQixFQUFtQnhTLE1BQU1ySCxNQUF6QixDQUFSO0FBQ0g7QUFDSjtBQUNKLGFBZkQsTUFlTztBQUNILHFCQUFLaWMsc0JBQUw7O0FBREcsNkNBRWEsS0FBS0ksaURBQUwsRUFGYjs7QUFBQTs7QUFFRmxWLG9CQUZFO0FBRUlFLHFCQUZKO0FBR047O0FBRUQsaUJBQUttVSxjQUFMLENBQW9CclUsSUFBcEIsRUFBMEJFLEtBQTFCO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7OERBT3NDO0FBQ2xDLG1CQUFPLEtBQUt6UixRQUFMLENBQWMwRix5QkFBZCxLQUE0QzVHLFlBQVkwQyxPQUFaLENBQW9Ca0UseUJBQXBCLENBQThDaU0sSUFBakc7QUFDSDs7QUFFRDs7Ozs7Ozs7OztxREFPNkI7QUFBQSx5Q0FDTCxLQUFLOFUsaURBQUwsRUFESztBQUFBO0FBQUEsZ0JBQ3BCbFYsSUFEb0I7QUFBQSxnQkFDZEUsS0FEYzs7QUFFekIsZ0JBQUksS0FBS2dKLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3Qm1CLGNBQTlDLEVBQThEO0FBQzFELHFCQUFLTixVQUFMLEdBQWtCLElBQWxCO0FBQ0g7O0FBRUQ7QUFDQTtBQUNBLGdCQUFJLEtBQUtkLFFBQUwsS0FBa0IsS0FBS3phLFFBQUwsQ0FBY21GLGdCQUFoQyxJQUNDLEtBQUtuRixRQUFMLENBQWNvRiwyQkFBZCxJQUE2QyxLQUFLcVYsUUFBTCxLQUFrQixLQUFLemEsUUFBTCxDQUFjb0YsMkJBRDlFLElBRUMsS0FBS3FWLFFBQUwsS0FBa0IsR0FBbEIsSUFBeUIsS0FBS0EsUUFBTCxLQUFrQixHQUEzQyxJQUFrRCxLQUFLQSxRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0JpTSxTQUZqRyxFQUU2RztBQUN6RyxvQkFBSSxDQUFDLEtBQUtDLG1DQUFMLEVBQUQsSUFBK0MsQ0FBQyxLQUFLNW1CLFFBQUwsQ0FBY21GLGdCQUFsRSxFQUFvRjtBQUNoRiwyQkFBTyxJQUFQO0FBQ0g7O0FBRUQ7QUFDQSxvQkFBSSxLQUFLbkYsUUFBTCxDQUFjK1cscUJBQWQsSUFBdUMsNEJBQWtCUSxRQUFsQixDQUEyQjlGLEtBQTNCLEVBQWtDLEtBQUt6UixRQUFMLENBQWMrVyxxQkFBaEQsQ0FBM0MsRUFBbUg7QUFDL0csMkJBQU8sSUFBUDtBQUNIOztBQUVEO0FBQ0Esb0JBQUksNEJBQWtCUSxRQUFsQixDQUEyQmhHLElBQTNCLEVBQWlDLEtBQUt2UixRQUFMLENBQWNtRixnQkFBL0MsQ0FBSixFQUFzRTtBQUNsRSwyQkFBTyxJQUFQO0FBQ0g7O0FBRUQsb0JBQUlzTSxNQUFNSSxPQUFOLENBQWMsS0FBSzdSLFFBQUwsQ0FBY21GLGdCQUE1QixJQUFnRCxDQUFwRCxFQUF1RDtBQUNuRCwyQkFBTyxJQUFQO0FBQ0g7O0FBRUQsb0JBQUlzTSxNQUFNSSxPQUFOLENBQWMsS0FBSzdSLFFBQUwsQ0FBY21GLGdCQUE1QixNQUFrRCxDQUF0RCxFQUF5RDtBQUNyRHNNLDRCQUFRQSxNQUFNa1UsTUFBTixDQUFhLENBQWIsQ0FBUjtBQUNIOztBQUVELHFCQUFLQyxjQUFMLENBQW9CclUsT0FBTyxLQUFLdlIsUUFBTCxDQUFjbUYsZ0JBQXpDLEVBQTJEc00sS0FBM0Q7O0FBRUEsdUJBQU8sSUFBUDtBQUNIOztBQUVEO0FBQ0EsZ0JBQUksQ0FBQyxLQUFLZ0osUUFBTCxLQUFrQixHQUFsQixJQUF5QixLQUFLQSxRQUFMLEtBQWtCLEdBQTVDLEtBQW9ELEtBQUt6YSxRQUFMLENBQWMrVyxxQkFBZCxLQUF3QyxHQUFoRyxFQUFxRztBQUNqRyxvQkFBSXhGLFNBQVMsRUFBVCxJQUFlLDRCQUFrQmdHLFFBQWxCLENBQTJCOUYsS0FBM0IsRUFBa0MsS0FBS3pSLFFBQUwsQ0FBYytXLHFCQUFoRCxDQUFuQixFQUEyRjtBQUN2RjtBQUNBdEYsNEJBQVFBLE1BQU0vQyxPQUFOLENBQWMsS0FBSzFPLFFBQUwsQ0FBYytXLHFCQUE1QixFQUFtRCxFQUFuRCxDQUFSO0FBQ0gsaUJBSEQsTUFHTyxJQUFJLDRCQUFrQjNGLFVBQWxCLENBQTZCRyxJQUE3QixDQUFKLEVBQXdDO0FBQzNDO0FBQ0E7QUFDQUEsMkJBQU9BLEtBQUs3QyxPQUFMLENBQWEsR0FBYixFQUFrQixFQUFsQixDQUFQLENBSDJDLENBR2I7QUFDakMsaUJBSk0sTUFJQTtBQUNIO0FBQ0E2QywyQkFBTyxLQUFLdlIsUUFBTCxDQUFjK1cscUJBQWQsR0FBc0N4RixJQUE3QztBQUNIOztBQUVELHFCQUFLcVUsY0FBTCxDQUFvQnJVLElBQXBCLEVBQTBCRSxLQUExQjs7QUFFQSx1QkFBTyxJQUFQO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBTW9WLGNBQWM5WSxPQUFPLEtBQUswTSxRQUFaLENBQXBCO0FBQ0EsZ0JBQUlvTSxlQUFlLENBQWYsSUFBb0JBLGVBQWUsQ0FBdkMsRUFBMEM7QUFDdEMsb0JBQUksS0FBSzdtQixRQUFMLENBQWMrVyxxQkFBZCxJQUF1Q3hGLFNBQVMsRUFBaEQsSUFBc0QsNEJBQWtCZ0csUUFBbEIsQ0FBMkI5RixLQUEzQixFQUFrQyxLQUFLelIsUUFBTCxDQUFjK1cscUJBQWhELENBQTFELEVBQWtJO0FBQzlIeEYsMkJBQU8sS0FBS3ZSLFFBQUwsQ0FBYytXLHFCQUFyQjtBQUNBdEYsNEJBQVFBLE1BQU13UyxTQUFOLENBQWdCLENBQWhCLEVBQW1CeFMsTUFBTXJILE1BQXpCLENBQVI7QUFDSDs7QUFFRCxvQkFBSSxLQUFLcEssUUFBTCxDQUFjcUcsWUFBZCxJQUE4QixDQUE5QixJQUFtQyxLQUFLckcsUUFBTCxDQUFjc0csWUFBZCxHQUE2QixLQUFLdEcsUUFBTCxDQUFjcUcsWUFBOUUsSUFBOEYsQ0FBQyw0QkFBa0JrUixRQUFsQixDQUEyQiw0QkFBa0J0SCxlQUFsQixDQUFrQyxLQUFLOVEsVUFBdkMsQ0FBM0IsRUFBK0UsS0FBS2EsUUFBTCxDQUFjK1cscUJBQTdGLENBQS9GLElBQXNOLEtBQUswRCxRQUFMLEtBQWtCLEdBQTVPLEVBQWlQO0FBQzdPbEosMkJBQU8sS0FBS3ZSLFFBQUwsQ0FBYytXLHFCQUFkLEdBQXNDeEYsSUFBN0M7QUFDSDs7QUFFRCxxQkFBS3FVLGNBQUwsQ0FBb0JyVSxPQUFPLEtBQUtrSixRQUFoQyxFQUEwQ2hKLEtBQTFDOztBQUVBLHVCQUFPLElBQVA7QUFDSDs7QUFFRDtBQUNBLGlCQUFLOEosVUFBTCxHQUFrQixLQUFsQjs7QUFFQSxtQkFBTyxLQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7OztxQ0FNYW5ULEMsRUFBRztBQUNaLGdCQUFNd0osZUFBZSw0QkFBa0IzQixlQUFsQixDQUFrQyxLQUFLOVEsVUFBdkMsQ0FBckI7O0FBRFkseUNBRUMsS0FBS3NuQixpREFBTCxFQUZEO0FBQUE7QUFBQSxnQkFFUGxWLElBRk87O0FBSVo7OztBQUNBLGdCQUFJLENBQUMsS0FBS3ZSLFFBQUwsQ0FBYzZGLG1CQUFkLEtBQXVDLEVBQXZDLElBQThDLEtBQUs3RixRQUFMLENBQWM2RixtQkFBZCxLQUFzQyxFQUF0QyxJQUE2QyxDQUFDLDRCQUFrQjBSLFFBQWxCLENBQTJCM0YsWUFBM0IsRUFBeUMsS0FBSzVSLFFBQUwsQ0FBYzZGLG1CQUF2RCxDQUE3RixNQUNDLEtBQUs3RixRQUFMLENBQWNpRixjQUFkLEtBQWlDLEVBQWpDLElBQXdDLEtBQUtqRixRQUFMLENBQWNpRixjQUFkLEtBQWlDLEVBQWpDLElBQXVDLENBQUMsNEJBQWtCc1MsUUFBbEIsQ0FBMkIzRixZQUEzQixFQUF5QyxLQUFLNVIsUUFBTCxDQUFjaUYsY0FBdkQsQ0FEakYsQ0FBSixFQUMrSjtBQUFBLDBDQUMxSTJNLGFBQWErRSxLQUFiLENBQW1CLEtBQUszVyxRQUFMLENBQWNtRixnQkFBakMsQ0FEMEk7QUFBQTtBQUFBLG9CQUN0SjJoQixRQURzSjs7QUFFM0osb0JBQUlDLGVBQWUsRUFBbkI7QUFDQSxvQkFBSSw0QkFBa0IzVixVQUFsQixDQUE2QjBWLFFBQTdCLENBQUosRUFBNEM7QUFDeENDLG1DQUFlLEdBQWY7QUFDQUQsK0JBQVdBLFNBQVNwWSxPQUFULENBQWlCLEdBQWpCLEVBQXNCLEVBQXRCLENBQVg7QUFDQTZDLDJCQUFPQSxLQUFLN0MsT0FBTCxDQUFhLEdBQWIsRUFBa0IsRUFBbEIsQ0FBUDtBQUNIOztBQUVEO0FBQ0Esb0JBQUlxWSxpQkFBaUIsRUFBakIsSUFBdUJELFNBQVMxYyxNQUFULEdBQWtCLEtBQUtwSyxRQUFMLENBQWNzaUIsT0FBdkQsSUFBa0UvUSxLQUFLd0ssTUFBTCxDQUFZLENBQVosTUFBbUIsR0FBekYsRUFBOEY7QUFDMUZ4SywyQkFBT0EsS0FBS3dNLEtBQUwsQ0FBVyxDQUFYLENBQVA7QUFDSDs7QUFFRDtBQUNBLG9CQUFJZ0osaUJBQWlCLEdBQWpCLElBQXdCRCxTQUFTMWMsTUFBVCxHQUFrQixLQUFLcEssUUFBTCxDQUFjd2lCLE9BQXhELElBQW1FalIsS0FBS3dLLE1BQUwsQ0FBWSxDQUFaLE1BQW1CLEdBQTFGLEVBQStGO0FBQzNGeEssMkJBQU9BLEtBQUt3TSxLQUFMLENBQVcsQ0FBWCxDQUFQO0FBQ0g7O0FBRUR4TSx1QkFBT3dWLGVBQWV4VixJQUF0QjtBQUNIOztBQUVELGdCQUFNMVAsUUFBUSxLQUFLbkIsV0FBTCxDQUFpQnNPLG1CQUFqQixDQUFxQzRDLFlBQXJDLEVBQW1ELEtBQUs1UixRQUF4RCxFQUFrRSxLQUFLYyxTQUF2RSxFQUFrRixLQUFLOEQsUUFBdkYsQ0FBZDtBQUNBLGdCQUFJK1csV0FBVzlaLE1BQU11SSxNQUFyQjtBQUNBLGdCQUFJdkksS0FBSixFQUFXO0FBQ1A7QUFDQSxvQkFBTW1sQixTQUFTelYsS0FBS29GLEtBQUwsQ0FBVyxFQUFYLENBQWY7O0FBRUE7QUFDQSxvQkFBSSxDQUFDLEtBQUszVyxRQUFMLENBQWN5Ryw2QkFBZCxLQUFnRDNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtENkssTUFBbEcsSUFDQSxLQUFLdFIsUUFBTCxDQUFjeUcsNkJBQWQsS0FBZ0QzSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRCtLLE1BQWxHLElBQTRHLEtBQUt4UixRQUFMLENBQWNrRix1QkFBZCxLQUEwQ3BHLFlBQVkwQyxPQUFaLENBQW9CMEQsdUJBQXBCLENBQTRDb00sTUFEbk0sS0FFQTBWLE9BQU8sQ0FBUCxNQUFjLEdBRmQsSUFFcUIsS0FBS2huQixRQUFMLENBQWMrVyxxQkFBZCxLQUF3QyxFQUZqRSxFQUVxRTtBQUNqRWlRLDJCQUFPeGIsS0FBUDs7QUFFQSx3QkFBSSxDQUFDLEtBQUtpUCxRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0JTLFNBQTFDLElBQXVELEtBQUtWLFFBQUwsS0FBa0IsMEJBQWdCQyxPQUFoQixDQUF3QlUsTUFBbEcsS0FDQSxLQUFLNkgsUUFEVCxFQUNtQjtBQUNmLDRCQUFLLEtBQUtqakIsUUFBTCxDQUFja0YsdUJBQWQsS0FBMENwRyxZQUFZMEMsT0FBWixDQUFvQjBELHVCQUFwQixDQUE0Q29NLE1BQXRGLElBQWdHLEtBQUt0UixRQUFMLENBQWN5Ryw2QkFBZCxLQUFnRDNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEOEssSUFBbk0sSUFDQyxLQUFLdlIsUUFBTCxDQUFja0YsdUJBQWQsS0FBMENwRyxZQUFZMEMsT0FBWixDQUFvQjBELHVCQUFwQixDQUE0Q3NNLE1BQXRGLElBQWdHLEtBQUt4UixRQUFMLENBQWN5Ryw2QkFBZCxLQUFnRDNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtENkssTUFEdk0sRUFDZ047QUFDNU0wVixtQ0FBTy9rQixJQUFQLENBQVksR0FBWjtBQUNBLGlDQUFLZ2hCLFFBQUwsR0FBZ0I3YSxFQUFFOFEsSUFBRixLQUFXLFNBQTNCO0FBQ0g7O0FBRUQsNEJBQUksS0FBS2xaLFFBQUwsQ0FBY2tGLHVCQUFkLEtBQTBDcEcsWUFBWTBDLE9BQVosQ0FBb0IwRCx1QkFBcEIsQ0FBNENvTSxNQUF0RixJQUFnRyxLQUFLdFIsUUFBTCxDQUFjeUcsNkJBQWQsS0FBZ0QzSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRGdMLEtBQXRNLEVBQTZNO0FBQ3pNLGdDQUFNd1YsWUFBWSxLQUFLam5CLFFBQUwsQ0FBY2lGLGNBQWQsQ0FBNkIwUixLQUE3QixDQUFtQyxFQUFuQyxDQUFsQjtBQUNBLGdDQUFNdVEsWUFBWSxDQUFDLElBQUQsRUFBTyxHQUFQLEVBQVksR0FBWixFQUFpQixHQUFqQixFQUFzQixHQUF0QixFQUEyQixHQUEzQixFQUFnQyxHQUFoQyxFQUFxQyxHQUFyQyxFQUEwQyxHQUExQyxFQUErQyxHQUEvQyxFQUFvRCxHQUFwRCxDQUFsQjtBQUNBLGdDQUFNQyxlQUFlLEVBQXJCO0FBQ0FGLHNDQUFVdmxCLE9BQVYsQ0FBa0IsVUFBQzZKLENBQUQsRUFBSTZiLFNBQUosRUFBa0I7QUFDaENBLDRDQUFZSCxVQUFVMWIsQ0FBVixDQUFaO0FBQ0Esb0NBQUksNEJBQWtCc0IsU0FBbEIsQ0FBNEJ1YSxTQUE1QixFQUF1Q0YsU0FBdkMsQ0FBSixFQUF1RDtBQUNuREMsaURBQWFsbEIsSUFBYixDQUFrQixPQUFPbWxCLFNBQXpCO0FBQ0gsaUNBRkQsTUFFTztBQUNIRCxpREFBYWxsQixJQUFiLENBQWtCbWxCLFNBQWxCO0FBQ0g7QUFDSiw2QkFQRDs7QUFTQSxnQ0FBSSxLQUFLM00sUUFBTCxLQUFrQiwwQkFBZ0JDLE9BQWhCLENBQXdCUyxTQUE5QyxFQUF5RDtBQUNyRGdNLDZDQUFhbGxCLElBQWIsQ0FBa0IsR0FBbEI7QUFDSDs7QUFFRDtBQUNBK2tCLG1DQUFPL2tCLElBQVAsQ0FBWWtsQixhQUFhdEIsSUFBYixDQUFrQixFQUFsQixDQUFaO0FBQ0EsaUNBQUs1QyxRQUFMLEdBQWdCN2EsRUFBRThRLElBQUYsS0FBVyxTQUEzQjtBQUNIO0FBQ0o7QUFDSjs7QUFFRCxxQkFBSyxJQUFJM04sSUFBSSxDQUFiLEVBQWdCQSxJQUFJeWIsT0FBTzVjLE1BQTNCLEVBQW1DbUIsR0FBbkMsRUFBd0M7QUFDcEMsd0JBQUksQ0FBQ3liLE9BQU96YixDQUFQLEVBQVV5TCxLQUFWLENBQWdCLEtBQWhCLENBQUwsRUFBNkI7QUFDekJnUSwrQkFBT3piLENBQVAsSUFBWSxPQUFPeWIsT0FBT3piLENBQVAsQ0FBbkI7QUFDSDtBQUNKOztBQUVELG9CQUFNOGIsVUFBVSxJQUFJNUMsTUFBSixDQUFXLFNBQVN1QyxPQUFPbkIsSUFBUCxDQUFZLEtBQVosQ0FBcEIsQ0FBaEI7O0FBRUE7QUFDQSxvQkFBTXlCLFVBQVV6bEIsTUFBTW1WLEtBQU4sQ0FBWXFRLE9BQVosQ0FBaEI7QUFDQSxvQkFBSUMsT0FBSixFQUFhO0FBQ1QzTCwrQkFBVzJMLFFBQVEsQ0FBUixFQUFXbGQsTUFBdEI7O0FBRUE7QUFDQSx3QkFBSSxLQUFLcEssUUFBTCxDQUFjeUgsZ0JBQWxCLEVBQW9DO0FBQ2hDLDRCQUFJa1UsYUFBYSxDQUFiLElBQWtCMkwsUUFBUTFTLEtBQVIsQ0FBY21ILE1BQWQsQ0FBcUIsQ0FBckIsTUFBNEIsS0FBSy9iLFFBQUwsQ0FBYzJYLHFCQUFoRSxFQUF1RjtBQUNuRmdFLHVDQUFZMkwsUUFBUTFTLEtBQVIsQ0FBYy9DLE9BQWQsQ0FBc0IsS0FBSzdSLFFBQUwsQ0FBY2lGLGNBQXBDLE1BQXdELENBQXpELEdBQThELEtBQUtqRixRQUFMLENBQWNpRixjQUFkLENBQTZCbUYsTUFBN0IsR0FBc0MsQ0FBcEcsR0FBd0csQ0FBbkg7QUFDSDs7QUFFRCw0QkFBSXVSLGFBQWEsQ0FBYixJQUFrQjJMLFFBQVExUyxLQUFSLENBQWNtSCxNQUFkLENBQXFCLEtBQUsvYixRQUFMLENBQWNpRixjQUFkLENBQTZCbUYsTUFBbEQsTUFBOEQsS0FBS3BLLFFBQUwsQ0FBYzJYLHFCQUFsRyxFQUF5SDtBQUNySGdFLHVDQUFXLEtBQUszYixRQUFMLENBQWNpRixjQUFkLENBQTZCbUYsTUFBN0IsR0FBc0MsQ0FBakQ7QUFDSDtBQUNKOztBQUVEO0FBQ0Esd0JBQUksQ0FBRXVSLGFBQWEsQ0FBYixJQUFrQjlaLE1BQU1rYSxNQUFOLENBQWEsQ0FBYixNQUFvQixLQUFLL2IsUUFBTCxDQUFjK1cscUJBQXJELElBQWdGNEUsYUFBYSxDQUFiLElBQWtCOVosTUFBTWthLE1BQU4sQ0FBYSxDQUFiLE1BQW9CLEtBQUsvYixRQUFMLENBQWMrVyxxQkFBckksS0FBZ0ssS0FBSy9XLFFBQUwsQ0FBY2lGLGNBQTlLLElBQWdNLEtBQUtqRixRQUFMLENBQWNrRix1QkFBZCxLQUEwQ3BHLFlBQVkwQyxPQUFaLENBQW9CMEQsdUJBQXBCLENBQTRDc00sTUFBMVIsRUFBa1M7QUFDOVI7QUFDQTtBQUNBbUssbUNBQVcsS0FBSzNiLFFBQUwsQ0FBY2lGLGNBQWQsQ0FBNkJtRixNQUE3QixJQUF1Qyw0QkFBa0IwVCxnQkFBbEIsQ0FBbUNqYyxLQUFuQyxJQUE0QyxDQUE1QyxHQUFnRCxDQUF2RixDQUFYO0FBQ0g7QUFDSixpQkFwQkQsTUFvQk87QUFDSCx3QkFBSSxLQUFLN0IsUUFBTCxDQUFjaUYsY0FBZCxJQUFnQyxLQUFLakYsUUFBTCxDQUFja0YsdUJBQWQsS0FBMENwRyxZQUFZMEMsT0FBWixDQUFvQjBELHVCQUFwQixDQUE0Q29NLE1BQTFILEVBQWtJO0FBQzlIO0FBQ0E7QUFDQXFLLG9DQUFZLEtBQUszYixRQUFMLENBQWNpRixjQUFkLENBQTZCbUYsTUFBekM7QUFDSDs7QUFFRCx3QkFBSSxLQUFLcEssUUFBTCxDQUFjMkgsVUFBbEIsRUFBOEI7QUFDMUI7QUFDQTtBQUNBZ1Usb0NBQVksS0FBSzNiLFFBQUwsQ0FBYzJILFVBQWQsQ0FBeUJ5QyxNQUFyQztBQUNIO0FBQ0o7QUFDSjs7QUFFRDtBQUNBLGdCQUFJdkksVUFBVStQLFlBQVYsSUFDQS9QLFVBQVUrUCxZQUFWLEtBQTJCLEtBQUs2SSxRQUFMLEtBQWtCLDBCQUFnQkMsT0FBaEIsQ0FBd0I0SixJQUExQyxJQUFrRCxLQUFLN0osUUFBTCxLQUFrQiwwQkFBZ0JDLE9BQWhCLENBQXdCNkosT0FBdkgsQ0FESixFQUNxSTtBQUNqSSxxQkFBS2pVLGdCQUFMLENBQXNCek8sS0FBdEI7QUFDQSxxQkFBS3FhLGlCQUFMLENBQXVCUCxRQUF2QjtBQUNIOztBQUVELGdCQUFJLEtBQUtDLHFCQUFMLEtBQStCLElBQW5DLEVBQXlDO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBLHFCQUFLTSxpQkFBTCxDQUF1QixLQUFLTixxQkFBNUI7QUFDSDs7QUFFRCxpQkFBS3pMLFNBQUwsR0FBaUIsSUFBakIsQ0FuSVksQ0FtSVc7QUFDMUI7O0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7a0NBNzNOaUI7QUFDYixtQkFBTyxPQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7NENBYTJCcFIsSSxFQUFNQyxJLEVBQU1DLEksRUFBTTtBQUN6QztBQUNBLGdCQUFJLDRCQUFrQmdKLE1BQWxCLENBQXlCbEosSUFBekIsQ0FBSixFQUFvQztBQUNoQyw0Q0FBa0JnTyxVQUFsQixDQUE2QixxRkFBN0I7QUFDSDs7QUFFRDtBQUNBO0FBQ0EsZ0JBQU13YSxnQkFBZ0IsNEJBQWtCM1UsU0FBbEIsQ0FBNEI3VCxJQUE1QixDQUF0QjtBQUNBLGdCQUFNeW9CLGVBQWUsNEJBQWtCamIsUUFBbEIsQ0FBMkJ4TixJQUEzQixDQUFyQjs7QUFFQSxnQkFBTTBvQixlQUFlLDRCQUFrQkMsUUFBbEIsQ0FBMkIxb0IsSUFBM0IsQ0FBckI7QUFDQSxnQkFBTTJvQixjQUFjQyxNQUFNbmIsT0FBTixDQUFjek4sSUFBZCxLQUF1QkEsS0FBS29MLE1BQUwsR0FBYyxDQUF6RDtBQUNBLGdCQUFNeWQsZUFBZSw0QkFBa0JDLGdCQUFsQixDQUFtQzlvQixJQUFuQyxLQUE0Q0EsU0FBUyxFQUExRTtBQUNBLGdCQUFNK29CLDZCQUE2QixLQUFLQyx3QkFBTCxDQUE4QmhwQixJQUE5QixDQUFuQztBQUNBLGdCQUFNaXBCLGFBQWEsNEJBQWtCaGdCLE1BQWxCLENBQXlCakosSUFBekIsQ0FBbkI7QUFDQSxnQkFBTWtwQixvQkFBb0IsNEJBQWtCdlgsYUFBbEIsQ0FBZ0MzUixJQUFoQyxDQUExQjs7QUFFQSxnQkFBTW1wQixlQUFlLDRCQUFrQlQsUUFBbEIsQ0FBMkJ6b0IsSUFBM0IsQ0FBckI7QUFDQSxnQkFBTW1wQixjQUFjUixNQUFNbmIsT0FBTixDQUFjeE4sSUFBZCxLQUF1QkEsS0FBS21MLE1BQUwsR0FBYyxDQUF6RDtBQUNBLGdCQUFNaWUsYUFBYSw0QkFBa0JwZ0IsTUFBbEIsQ0FBeUJoSixJQUF6QixDQUFuQjtBQUNBLGdCQUFNcXBCLDZCQUE2QixLQUFLTix3QkFBTCxDQUE4Qi9vQixJQUE5QixDQUFuQzs7QUFFQTtBQUNBLGdCQUFJRSxtQkFBSjtBQUNBLGdCQUFJRSxvQkFBSjtBQUNBLGdCQUFJRCxxQkFBSjs7QUFFQTtBQUNBLGdCQUFJbW9CLGlCQUFpQlUsVUFBakIsSUFBK0JJLFVBQW5DLEVBQStDO0FBQzNDO0FBQ0FscEIsNkJBQWFKLElBQWI7QUFDQUssK0JBQWUsSUFBZjtBQUNBQyw4QkFBYyxJQUFkO0FBQ0gsYUFMRCxNQUtPLElBQUlrb0IsaUJBQWlCTSxZQUFqQixJQUFpQ1EsVUFBckMsRUFBaUQ7QUFDcEQ7QUFDQTtBQUNBbHBCLDZCQUFhSixJQUFiO0FBQ0FLLCtCQUFlSixJQUFmO0FBQ0FLLDhCQUFjLElBQWQ7QUFDSCxhQU5NLE1BTUEsSUFBSWtvQixpQkFBaUJFLFlBQWpCLElBQWlDWSxVQUFyQyxFQUFpRDtBQUNwRDtBQUNBbHBCLDZCQUFhSixJQUFiO0FBQ0FLLCtCQUFlLElBQWY7QUFDQUMsOEJBQWNMLElBQWQ7QUFDSCxhQUxNLE1BS0EsSUFBSXVvQixpQkFBaUJRLDBCQUFqQixJQUErQ00sVUFBbkQsRUFBK0Q7QUFDbEU7QUFDQWxwQiw2QkFBYUosSUFBYjtBQUNBSywrQkFBZSxJQUFmO0FBQ0FDLDhCQUFjLEtBQUtrcEIsZ0JBQUwsQ0FBc0J2cEIsSUFBdEIsQ0FBZDtBQUNILGFBTE0sTUFLQSxJQUFJdW9CLGlCQUFpQkksV0FBakIsSUFBZ0NVLFVBQXBDLEVBQWdEO0FBQ25EO0FBQ0FscEIsNkJBQWFKLElBQWI7QUFDQUssK0JBQWUsSUFBZjtBQUNBQyw4QkFBYyxLQUFLbXBCLFlBQUwsQ0FBa0J4cEIsSUFBbEIsQ0FBZDtBQUNILGFBTE0sTUFLQSxJQUFJdW9CLGtCQUFrQlUsY0FBY0MsaUJBQWhDLEtBQXNEQyxZQUExRCxFQUF3RTtBQUMzRTtBQUNBaHBCLDZCQUFhSixJQUFiO0FBQ0FLLCtCQUFlLElBQWY7QUFDQUMsOEJBQWNKLElBQWQ7QUFDSCxhQUxNLE1BS0EsSUFBSXNvQixrQkFBa0JVLGNBQWNDLGlCQUFoQyxLQUFzREUsV0FBMUQsRUFBdUU7QUFDMUU7QUFDQWpwQiw2QkFBYUosSUFBYjtBQUNBSywrQkFBZSxJQUFmO0FBQ0FDLDhCQUFjLEtBQUttcEIsWUFBTCxDQUFrQnZwQixJQUFsQixDQUFkO0FBQ0gsYUFMTSxNQUtBLElBQUl1b0IsZ0JBQWdCUyxVQUFoQixJQUE4QkksVUFBbEMsRUFBOEM7QUFDakQ7QUFDQWxwQiw2QkFBYThLLFNBQVN3ZSxhQUFULENBQXVCMXBCLElBQXZCLENBQWI7QUFDQUssK0JBQWUsSUFBZjtBQUNBQyw4QkFBYyxJQUFkO0FBQ0gsYUFMTSxNQUtBLElBQUltb0IsZ0JBQWdCQyxZQUFoQixJQUFnQ1ksVUFBcEMsRUFBZ0Q7QUFDbkQ7QUFDQWxwQiw2QkFBYThLLFNBQVN3ZSxhQUFULENBQXVCMXBCLElBQXZCLENBQWI7QUFDQUssK0JBQWUsSUFBZjtBQUNBQyw4QkFBY0wsSUFBZDtBQUNILGFBTE0sTUFLQSxJQUFJd29CLGdCQUFnQk8sMEJBQWhCLElBQThDTSxVQUFsRCxFQUE4RDtBQUNqRTtBQUNBbHBCLDZCQUFhOEssU0FBU3dlLGFBQVQsQ0FBdUIxcEIsSUFBdkIsQ0FBYjtBQUNBSywrQkFBZSxJQUFmO0FBQ0FDLDhCQUFjLEtBQUtrcEIsZ0JBQUwsQ0FBc0J2cEIsSUFBdEIsQ0FBZDtBQUNILGFBTE0sTUFLQSxJQUFJd29CLGdCQUFnQkcsV0FBaEIsSUFBK0JVLFVBQW5DLEVBQStDO0FBQ2xEO0FBQ0FscEIsNkJBQWE4SyxTQUFTd2UsYUFBVCxDQUF1QjFwQixJQUF2QixDQUFiO0FBQ0FLLCtCQUFlLElBQWY7QUFDQUMsOEJBQWMsS0FBS21wQixZQUFMLENBQWtCeHBCLElBQWxCLENBQWQ7QUFDSCxhQUxNLE1BS0EsSUFBSXdvQixpQkFBaUJTLGNBQWNDLGlCQUEvQixLQUFxREMsWUFBekQsRUFBdUU7QUFDMUU7QUFDQWhwQiw2QkFBYThLLFNBQVN3ZSxhQUFULENBQXVCMXBCLElBQXZCLENBQWI7QUFDQUssK0JBQWUsSUFBZjtBQUNBQyw4QkFBY0osSUFBZDtBQUNILGFBTE0sTUFLQSxJQUFJdW9CLGlCQUFpQlMsY0FBY0MsaUJBQS9CLEtBQXFERSxXQUF6RCxFQUFzRTtBQUN6RTtBQUNBanBCLDZCQUFhOEssU0FBU3dlLGFBQVQsQ0FBdUIxcEIsSUFBdkIsQ0FBYjtBQUNBSywrQkFBZSxJQUFmO0FBQ0FDLDhCQUFjLEtBQUttcEIsWUFBTCxDQUFrQnZwQixJQUFsQixDQUFkO0FBQ0gsYUFMTSxNQUtBLElBQUl1b0IsZ0JBQWdCSyxZQUFoQixJQUFnQ1EsVUFBcEMsRUFBZ0Q7QUFDbkQ7QUFDQTtBQUNBO0FBQ0FscEIsNkJBQWE4SyxTQUFTd2UsYUFBVCxDQUF1QjFwQixJQUF2QixDQUFiO0FBQ0FLLCtCQUFlSixJQUFmO0FBQ0FLLDhCQUFjLElBQWQ7QUFDSCxhQVBNLE1BT0EsSUFBSW1vQixnQkFBZ0JLLFlBQWhCLElBQWdDTSxZQUFwQyxFQUFrRDtBQUNyRDtBQUNBO0FBQ0E7QUFDQWhwQiw2QkFBYThLLFNBQVN3ZSxhQUFULENBQXVCMXBCLElBQXZCLENBQWI7QUFDQUssK0JBQWVKLElBQWY7QUFDQUssOEJBQWNKLElBQWQ7QUFDSCxhQVBNLE1BT0EsSUFBSXVvQixnQkFBZ0JLLFlBQWhCLElBQWdDUywwQkFBcEMsRUFBZ0U7QUFDbkU7QUFDQTtBQUNBO0FBQ0FucEIsNkJBQWE4SyxTQUFTd2UsYUFBVCxDQUF1QjFwQixJQUF2QixDQUFiO0FBQ0FLLCtCQUFlSixJQUFmO0FBQ0FLLDhCQUFjLEtBQUtrcEIsZ0JBQUwsQ0FBc0J0cEIsSUFBdEIsQ0FBZDtBQUNILGFBUE0sTUFPQSxJQUFJc29CLGlCQUFpQk0sWUFBakIsSUFBaUNNLFlBQXJDLEVBQW1EO0FBQ3REO0FBQ0E7QUFDQTtBQUNBaHBCLDZCQUFhSixJQUFiO0FBQ0FLLCtCQUFlSixJQUFmO0FBQ0FLLDhCQUFjSixJQUFkO0FBQ0gsYUFQTSxNQU9BLElBQUlzb0IsaUJBQWlCTSxZQUFqQixJQUFpQ1MsMEJBQXJDLEVBQWlFO0FBQ3BFO0FBQ0E7QUFDQTtBQUNBbnBCLDZCQUFhSixJQUFiO0FBQ0FLLCtCQUFlSixJQUFmO0FBQ0FLLDhCQUFjLEtBQUtrcEIsZ0JBQUwsQ0FBc0J0cEIsSUFBdEIsQ0FBZDtBQUNILGFBUE0sTUFPQSxJQUFJc29CLGlCQUFpQk0sWUFBakIsSUFBaUNPLFdBQXJDLEVBQWtEO0FBQ3JEO0FBQ0E7QUFDQTtBQUNBanBCLDZCQUFhSixJQUFiO0FBQ0FLLCtCQUFlSixJQUFmO0FBQ0FLLDhCQUFjLEtBQUttcEIsWUFBTCxDQUFrQnZwQixJQUFsQixDQUFkO0FBQ0gsYUFQTSxNQU9BO0FBQ0gsNENBQWtCOE4sVUFBbEIsc0VBQStGaE8sSUFBL0YsY0FBMEdDLElBQTFHLGlCQUF3SEMsSUFBeEg7QUFDSDs7QUFFRCxnQkFBSSw0QkFBa0JnSixNQUFsQixDQUF5QjlJLFVBQXpCLENBQUosRUFBMEM7QUFDdEMsNENBQWtCNE4sVUFBbEIscUJBQThDaE8sSUFBOUM7QUFDSDs7QUFFRCxtQkFBTyxFQUFFSSxzQkFBRixFQUFjQywwQkFBZCxFQUE0QkMsd0JBQTVCLEVBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7cUNBUW9CcXBCLFksRUFBYztBQUFBOztBQUM5QjtBQUNBLGdCQUFNQyxnQkFBZ0IsRUFBdEI7QUFDQUQseUJBQWFobkIsT0FBYixDQUFxQixnREFBd0M7QUFDekQseUJBQWNpbkIsYUFBZCxFQUE2QixPQUFLSixnQkFBTCxDQUFzQkssb0NBQXRCLENBQTdCO0FBQ0gsYUFGRDs7QUFJQSxtQkFBT0QsYUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7O2lEQU9nQ0Usb0IsRUFBc0I7QUFDbEQsbUJBQU8vcEIsWUFBWWdxQixpQkFBWixDQUE4QnZTLGNBQTlCLENBQTZDc1Msb0JBQTdDLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozt5Q0FPd0JFLDRCLEVBQThCO0FBQ2xELGdCQUFJdm5CLGdCQUFKO0FBQ0EsZ0JBQUksNEJBQWtCK0ssUUFBbEIsQ0FBMkJ3Yyw0QkFBM0IsQ0FBSixFQUE4RDtBQUMxRHZuQiwwQkFBVTFDLFlBQVkrVyxvQkFBWixHQUFtQ2tULDRCQUFuQyxDQUFWO0FBQ0Esb0JBQUl2bkIsWUFBWSxLQUFLLENBQWpCLElBQXVCQSxZQUFZLElBQXZDLEVBQTZDO0FBQ3pDO0FBQ0EsZ0RBQWtCOEQsT0FBbEIsb0NBQTJEeWpCLDRCQUEzRCxxRkFBeUssSUFBeks7QUFDSDtBQUNKLGFBTkQsTUFNTztBQUFFO0FBQ0x2bkIsMEJBQVV1bkIsNEJBQVY7QUFDSDs7QUFFRCxtQkFBT3ZuQixPQUFQO0FBQ0g7Ozs0Q0FreUQwQitmLFMsRUFBVztBQUNsQ0Esc0JBQVVsSSxjQUFWLEdBQTJCLElBQTNCO0FBQ0FrSSxzQkFBVS9lLFFBQVY7QUFDSDs7QUFFRDs7Ozs7Ozs7OzRDQU0yQitlLFMsRUFBVztBQUNsQ0Esc0JBQVVsSSxjQUFWLEdBQTJCLEtBQTNCO0FBQ0FrSSxzQkFBVWhmLFFBQVY7QUFDSDs7QUFFRDs7Ozs7Ozs7OztnREFPK0J5bUIsUSxFQUFVO0FBQUE7O0FBQUU7QUFDdkMsZ0JBQU1DLFlBQVlELFNBQVNFLG9CQUFULENBQThCLE9BQTlCLENBQWxCOztBQUVBO0FBQ0EsZ0JBQU1DLG9CQUFvQixFQUExQjtBQUNBLGdCQUFNQyxnQkFBZ0J4QixNQUFNeUIsU0FBTixDQUFnQnRMLEtBQWhCLENBQXNCdUwsSUFBdEIsQ0FBMkJMLFNBQTNCLEVBQXNDLENBQXRDLENBQXRCO0FBQ0FHLDBCQUFjMW5CLE9BQWQsQ0FBc0IsaUJBQVM7QUFDM0Isb0JBQUksT0FBSzZuQixJQUFMLENBQVUzVSxLQUFWLENBQUosRUFBc0I7QUFDbEJ1VSxzQ0FBa0JsbkIsSUFBbEIsQ0FBdUIyUyxLQUF2QjtBQUNIO0FBQ0osYUFKRDs7QUFNQSxtQkFBT3VVLGlCQUFQO0FBQ0g7O0FBRUQ7QUFDQTs7Ozs7Ozs7OzZCQU1ZaHFCLFUsRUFBWTtBQUNwQixtQkFBTyxLQUFLcXFCLGVBQUwsQ0FBcUJycUIsVUFBckIsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7dUNBTXNCc3FCLFcsRUFBYTtBQUMvQmxNLG1CQUFPa00sV0FBUCxJQUFzQixJQUFJQyxPQUFKLEVBQXRCO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7NENBTzJCO0FBQ3ZCO0FBQ0EsaUJBQUtDLHlCQUFMLEdBQWlDLHVCQUFqQyxDQUZ1QixDQUVtQztBQUMxRDtBQUNBLGlCQUFLQyxjQUFMLENBQW9CLEtBQUtELHlCQUF6QjtBQUNIOztBQUVEOzs7Ozs7Ozs7Z0RBTStCO0FBQzNCLGdCQUFNelEsZUFBY3FFLE9BQU8sS0FBS29NLHlCQUFaLENBQWQsQ0FBTjtBQUNBLG1CQUFPelEsU0FBUyxXQUFULElBQ0FBLFNBQVMsUUFEaEI7QUFFSDs7QUFFRDs7Ozs7Ozs7O3lDQU13QjFELGlCLEVBQW1CO0FBQ3ZDLGdCQUFJLENBQUMsS0FBS3hMLHFCQUFMLEVBQUwsRUFBbUM7QUFDL0IscUJBQUs2ZixpQkFBTDtBQUNIOztBQUVELGdCQUFNMXFCLGFBQWFxVyxrQkFBa0JsUyxJQUFsQixFQUFuQjtBQUNBO0FBQ0E7QUFDQSxnQkFBSSxLQUFLa21CLGVBQUwsQ0FBcUJycUIsVUFBckIsQ0FBSixFQUFzQztBQUNsQyxvQkFBSSxLQUFLMnFCLGtCQUFMLENBQXdCM3FCLFVBQXhCLE1BQXdDLElBQTVDLEVBQWtEO0FBQzlDO0FBQ0E7QUFDSCxpQkFIRCxNQUdPO0FBQ0g7QUFDQSxnREFBa0JtRyxPQUFsQix1TEFBZ05rUSxrQkFBa0J1VSxXQUFsQixHQUFnQ3hrQixZQUFoUDtBQUNIO0FBQ0o7O0FBRURnWSxtQkFBTyxLQUFLb00seUJBQVosRUFBdUNyb0IsR0FBdkMsQ0FBMkNuQyxVQUEzQyxFQUF1RHFXLGlCQUF2RDtBQUNIOztBQUVEOzs7Ozs7Ozs7OENBTTZCQSxpQixFQUFtQjtBQUFFO0FBQzlDLGdCQUFJLEtBQUt4TCxxQkFBTCxFQUFKLEVBQWtDO0FBQzlCdVQsdUJBQU8sS0FBS29NLHlCQUFaLEVBQXVDcmxCLE1BQXZDLENBQThDa1Isa0JBQWtCbFMsSUFBbEIsRUFBOUM7QUFDSDtBQUNKOztBQUVEOzs7Ozs7Ozs7OzsyQ0FRMEJuRSxVLEVBQVk7QUFBRTtBQUNwQyxnQkFBSSxLQUFLNksscUJBQUwsRUFBSixFQUFrQztBQUM5Qix1QkFBT3VULE9BQU8sS0FBS29NLHlCQUFaLEVBQXVDN25CLEdBQXZDLENBQTJDM0MsVUFBM0MsQ0FBUDtBQUNIOztBQUVELG1CQUFPLElBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozt3Q0FPdUJBLFUsRUFBWTtBQUFFO0FBQ2pDLGdCQUFJLENBQUMsS0FBSzZLLHFCQUFMLEVBQUwsRUFBbUM7QUFDL0IsdUJBQU8sS0FBUDtBQUNIOztBQUVELG1CQUFPdVQsT0FBTyxLQUFLb00seUJBQVosRUFBdUN2bUIsR0FBdkMsQ0FBMkNqRSxVQUEzQyxDQUFQO0FBQ0g7OztpQ0E0SGVFLFcsRUFBd0U7QUFBQSxnQkFBM0QycUIsMEJBQTJELHVFQUE5QixJQUE4QjtBQUFBLGdCQUF4QkMsZUFBd0IsdUVBQU4sSUFBTTs7QUFDcEYsZ0JBQUksNEJBQWtCdmUsd0JBQWxCLENBQTJDck0sV0FBM0MsS0FBMkQsQ0FBQyw0QkFBa0Jxb0IsUUFBbEIsQ0FBMkJyb0IsV0FBM0IsQ0FBaEUsRUFBeUc7QUFDckcsNENBQWtCME4sVUFBbEIsa0VBQTRGMU4sV0FBNUY7QUFDSDs7QUFFRCxnQkFBTTZxQiwyQkFBMkIsNEJBQWtCeEMsUUFBbEIsQ0FBMkJ1QyxlQUEzQixDQUFqQztBQUNBLGdCQUFJLENBQUNDLHdCQUFELElBQTZCLENBQUMsNEJBQWtCamlCLE1BQWxCLENBQXlCZ2lCLGVBQXpCLENBQWxDLEVBQTZFO0FBQ3pFLDRDQUFrQmxkLFVBQWxCLDJHQUFxSTFOLFdBQXJJO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBSSxDQUFDLDRCQUFrQjRJLE1BQWxCLENBQXlCNUksV0FBekIsQ0FBTCxFQUE0QztBQUN4QyxxQkFBS29qQiwyQkFBTCxDQUFpQ3BqQixXQUFqQztBQUNIOztBQUVEO0FBQ0EsZ0JBQUltQyxnQkFBSjtBQUNBLGdCQUFJd29CLDBCQUFKLEVBQWdDO0FBQzVCeG9CLDBCQUFVLFNBQWMsRUFBZCxFQUFrQixLQUFLdWhCLGdCQUFMLEVBQWxCLEVBQTJDMWpCLFdBQTNDLENBQVY7QUFDSCxhQUZELE1BRU87QUFDSG1DLDBCQUFVbkMsV0FBVjtBQUNIOztBQUVEO0FBQ0EsZ0JBQUksQ0FBQyw0QkFBa0I4cUIsbUJBQWxCLENBQXNDM29CLFFBQVErRCxZQUE5QyxDQUFELElBQWdFLENBQUMsNEJBQWtCOEssU0FBbEIsQ0FBNEI3TyxRQUFRK0QsWUFBcEMsQ0FBckUsRUFBd0g7QUFDcEgsNENBQWtCd0gsVUFBbEIsaUdBQXFIdkwsUUFBUStELFlBQTdIO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBTTZrQixzQkFBc0IsVUFBNUI7QUFDQSxnQkFBTUMsMEJBQTBCLFFBQWhDO0FBQ0E7QUFDQSxnQkFBTUMsNENBQTRDLHdCQUFsRDtBQUNBLGdCQUFNQyw2QkFBNkIsc0JBQW5DOztBQUVBO0FBQ0EsZ0JBQUksQ0FBQyw0QkFBa0JKLG1CQUFsQixDQUFzQzNvQixRQUFRc0QsbUJBQTlDLENBQUQsSUFDQSxDQUFDLDRCQUFrQnVMLFNBQWxCLENBQTRCN08sUUFBUXNELG1CQUFwQyxDQURELElBRUF0RCxRQUFRc0QsbUJBQVIsS0FBZ0NoRyxZQUFZMEMsT0FBWixDQUFvQnNELG1CQUFwQixDQUF3Q3NZLE1BRjVFLEVBRW9GO0FBQ2hGLDRDQUFrQnJRLFVBQWxCLDRIQUF3SnZMLFFBQVFzRCxtQkFBaEs7QUFDSDs7QUFFRCxnQkFBSSxDQUFDdEQsUUFBUXNELG1CQUFSLEtBQWdDaEcsWUFBWTBDLE9BQVosQ0FBb0JzRCxtQkFBcEIsQ0FBd0NxWSxLQUF4RSxJQUNEM2IsUUFBUXNELG1CQUFSLEtBQWdDLE9BRC9CLElBQzBDO0FBQzNDdEQsb0JBQVFzRCxtQkFBUixLQUFnQ2hHLFlBQVkwQyxPQUFaLENBQW9Cc0QsbUJBQXBCLENBQXdDc1ksTUFGeEUsTUFHQzViLFFBQVE2RCxhQUFSLEtBQTBCdkcsWUFBWTBDLE9BQVosQ0FBb0I2RCxhQUFwQixDQUFrQ3NNLElBQTVELElBQ0RuUSxRQUFRaUUsd0JBQVIsS0FBcUMzRyxZQUFZMEMsT0FBWixDQUFvQmlFLHdCQUFwQixDQUE2Q2tNLElBRGpGLElBRURuUSxRQUFRa0UseUJBQVIsS0FBc0M1RyxZQUFZMEMsT0FBWixDQUFvQmtFLHlCQUFwQixDQUE4Q2lNLElBTHBGLENBQUosRUFLK0Y7QUFDM0YsNENBQWtCck0sT0FBbEIsMENBQStEOUQsUUFBUXNELG1CQUF2RSxpRUFBb0p0RCxRQUFRNkQsYUFBNUosVUFBOEs3RCxRQUFRaUUsd0JBQXRMLGFBQXNOakUsUUFBUWtFLHlCQUE5TixTQUE2UGxFLFFBQVErRCxZQUFyUTtBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCMEMsTUFBbEIsQ0FBeUJ6RyxRQUFRdUQsb0JBQWpDLENBQUQsSUFBMkQsQ0FBQyw0QkFBa0I4SCxTQUFsQixDQUE0QnJMLFFBQVF1RCxvQkFBcEMsRUFBMEQsQ0FDdEhqRyxZQUFZMEMsT0FBWixDQUFvQnVELG9CQUFwQixDQUF5QzZGLEtBRDZFLEVBRXRIOUwsWUFBWTBDLE9BQVosQ0FBb0J1RCxvQkFBcEIsQ0FBeUMrRixHQUY2RSxFQUd0SGhNLFlBQVkwQyxPQUFaLENBQW9CdUQsb0JBQXBCLENBQXlDeVMsV0FINkUsRUFJdEgxWSxZQUFZMEMsT0FBWixDQUFvQnVELG9CQUFwQixDQUF5QzBTLFlBSjZFLENBQTFELENBQWhFLEVBS0k7QUFDQSw0Q0FBa0IxSyxVQUFsQiwwSkFBNEt2TCxRQUFRdUQsb0JBQXBMO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBSXVJLHFCQUFKO0FBQ0EsZ0JBQUk0Yyx3QkFBSixFQUE4QjtBQUMxQjVjLCtCQUFlMmMsZUFBZjtBQUNILGFBRkQsTUFFTztBQUNIM2MsK0JBQWUsS0FBSytWLG1EQUFMLENBQXlEaGtCLFdBQXpELENBQWY7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQjRJLE1BQWxCLENBQXlCcUYsWUFBekIsQ0FBRCxJQUNFQSxhQUFhdkksb0JBQWIsS0FBc0NqRyxZQUFZMEMsT0FBWixDQUFvQnVELG9CQUFwQixDQUF5Q3lsQixzQkFBL0UsSUFDRmxkLGFBQWFoRyxhQUFiLEtBQStCeEksWUFBWTBDLE9BQVosQ0FBb0I4RixhQUFwQixDQUFrQzZTLE1BRnJFLEVBRStFO0FBQzNFLDRDQUFrQjdVLE9BQWxCLGtJQUFrSmdJLGFBQWF2SSxvQkFBL0osb0pBQStUdkQsUUFBUStELFlBQXZVO0FBQ0g7O0FBRUQsZ0JBQUksQ0FBQyw0QkFBa0JzSCxTQUFsQixDQUE0QnJMLFFBQVFxRSxtQkFBcEMsRUFBeUQsQ0FDMUQvRyxZQUFZMEMsT0FBWixDQUFvQnFFLG1CQUFwQixDQUF3QzRrQixLQURrQixFQUUxRDNyQixZQUFZMEMsT0FBWixDQUFvQnFFLG1CQUFwQixDQUF3QzZrQixHQUZrQixFQUcxRDVyQixZQUFZMEMsT0FBWixDQUFvQnFFLG1CQUFwQixDQUF3QzhrQixXQUhrQixFQUkxRDdyQixZQUFZMEMsT0FBWixDQUFvQnFFLG1CQUFwQixDQUF3QytrQixTQUprQixFQUsxRDlyQixZQUFZMEMsT0FBWixDQUFvQnFFLG1CQUFwQixDQUF3Q2dsQixrQkFMa0IsRUFNMUQvckIsWUFBWTBDLE9BQVosQ0FBb0JxRSxtQkFBcEIsQ0FBd0NpbEIsWUFOa0IsRUFPMURoc0IsWUFBWTBDLE9BQVosQ0FBb0JxRSxtQkFBcEIsQ0FBd0NrbEIsV0FQa0IsRUFRMURqc0IsWUFBWTBDLE9BQVosQ0FBb0JxRSxtQkFBcEIsQ0FBd0NtbEIsVUFSa0IsRUFTMURsc0IsWUFBWTBDLE9BQVosQ0FBb0JxRSxtQkFBcEIsQ0FBd0NvbEIsd0JBVGtCLEVBVTFEbnNCLFlBQVkwQyxPQUFaLENBQW9CcUUsbUJBQXBCLENBQXdDcWxCLFFBVmtCLENBQXpELENBQUwsRUFXSTtBQUNBLDRDQUFrQm5lLFVBQWxCLHNNQUFtTXZMLFFBQVFxRSxtQkFBM007QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQnNrQixtQkFBbEIsQ0FBc0Mzb0IsUUFBUWdHLHNCQUE5QyxDQUFELElBQTBFLENBQUMsNEJBQWtCNkksU0FBbEIsQ0FBNEI3TyxRQUFRZ0csc0JBQXBDLENBQS9FLEVBQTRJO0FBQ3hJLDRDQUFrQnVGLFVBQWxCLHFHQUF5SHZMLFFBQVFnRyxzQkFBakk7QUFDSDs7QUFFRCxnQkFBSSxDQUFDNGlCLG9CQUFvQmIsSUFBcEIsQ0FBeUIvbkIsUUFBUW9FLG1CQUFqQyxDQUFMLEVBQTREO0FBQ3hELDRDQUFrQm1ILFVBQWxCLGdJQUF3SnZMLFFBQVFvRSxtQkFBaEs7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQmlILFNBQWxCLENBQTRCckwsUUFBUTJELGdCQUFwQyxFQUFzRCxDQUN2RHJHLFlBQVkwQyxPQUFaLENBQW9CMkQsZ0JBQXBCLENBQXFDc2xCLEtBRGtCLEVBRXZEM3JCLFlBQVkwQyxPQUFaLENBQW9CMkQsZ0JBQXBCLENBQXFDdWxCLEdBRmtCLEVBR3ZENXJCLFlBQVkwQyxPQUFaLENBQW9CMkQsZ0JBQXBCLENBQXFDZ21CLFNBSGtCLEVBSXZEcnNCLFlBQVkwQyxPQUFaLENBQW9CMkQsZ0JBQXBCLENBQXFDaW1CLHNCQUprQixFQUt2RHRzQixZQUFZMEMsT0FBWixDQUFvQjJELGdCQUFwQixDQUFxQ2ttQix5QkFMa0IsQ0FBdEQsQ0FBTCxFQU1JO0FBQ0EsNENBQWtCdGUsVUFBbEIsK0lBQWdKdkwsUUFBUTJELGdCQUF4SjtBQUNIOztBQUVEO0FBQ0EsZ0JBQUkzRCxRQUFRMkQsZ0JBQVIsS0FBNkIzRCxRQUFRcUUsbUJBQXpDLEVBQThEO0FBQzFELDRDQUFrQmtILFVBQWxCLDhGQUFzSHZMLFFBQVEyRCxnQkFBOUgsOERBQXFNM0QsUUFBUXFFLG1CQUE3TTtBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCb0MsTUFBbEIsQ0FBeUJ6RyxRQUFRNEQsMkJBQWpDLENBQUQsSUFBa0UsQ0FBQyw0QkFBa0JtSCxRQUFsQixDQUEyQi9LLFFBQVE0RCwyQkFBbkMsQ0FBdkUsRUFBd0k7QUFDcEksNENBQWtCMkgsVUFBbEIsNEhBQW9KdkwsUUFBUTRELDJCQUE1SjtBQUNIOztBQUVELGdCQUFJNUQsUUFBUXlELGNBQVIsS0FBMkIsRUFBM0IsSUFBaUMsQ0FBQyw0QkFBa0JzSCxRQUFsQixDQUEyQi9LLFFBQVF5RCxjQUFuQyxDQUF0QyxFQUEwRjtBQUN0Riw0Q0FBa0I4SCxVQUFsQix5RkFBaUh2TCxRQUFReUQsY0FBekg7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQjRILFNBQWxCLENBQTRCckwsUUFBUTBELHVCQUFwQyxFQUE2RCxDQUM5RHBHLFlBQVkwQyxPQUFaLENBQW9CMEQsdUJBQXBCLENBQTRDc00sTUFEa0IsRUFFOUQxUyxZQUFZMEMsT0FBWixDQUFvQjBELHVCQUFwQixDQUE0Q29NLE1BRmtCLENBQTdELENBQUwsRUFHSTtBQUNBLDRDQUFrQnZFLFVBQWxCLGdKQUFvS3ZMLFFBQVEwRCx1QkFBNUs7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQjJILFNBQWxCLENBQTRCckwsUUFBUWlGLDZCQUFwQyxFQUFtRSxDQUNwRTNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEK0ssTUFEa0IsRUFFcEUxUyxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRDZLLE1BRmtCLEVBR3BFeFMsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q4SyxJQUhrQixFQUlwRXpTLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEZ0wsS0FKa0IsRUFLcEUzUyxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRGtMLElBTGtCLENBQW5FLENBQUwsRUFNSTtBQUNBLDRDQUFrQjVFLFVBQWxCLDZMQUEyTXZMLFFBQVFpRiw2QkFBbk47QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQjBqQixtQkFBbEIsQ0FBc0Mzb0IsUUFBUWlHLGdCQUE5QyxDQUFELElBQW9FLENBQUMsNEJBQWtCNEksU0FBbEIsQ0FBNEI3TyxRQUFRaUcsZ0JBQXBDLENBQXpFLEVBQWdJO0FBQzVILDRDQUFrQnNGLFVBQWxCLGtIQUFzSXZMLFFBQVFpRyxnQkFBOUk7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQjhFLFFBQWxCLENBQTJCL0ssUUFBUW1HLFVBQW5DLENBQUQsSUFBb0RuRyxRQUFRbUcsVUFBUixLQUF1QixFQUF2QixLQUE4Qiw0QkFBa0J5SixVQUFsQixDQUE2QjVQLFFBQVFtRyxVQUFyQyxLQUFvRDBpQix3QkFBd0JkLElBQXhCLENBQTZCL25CLFFBQVFtRyxVQUFyQyxDQUFsRixDQUF4RCxFQUE4TDtBQUMxTCw0Q0FBa0JvRixVQUFsQiw2SUFBbUt2TCxRQUFRbUcsVUFBM0s7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQk0sTUFBbEIsQ0FBeUJ6RyxRQUFRdUYsb0JBQWpDLENBQUQsSUFBMkQsQ0FBQyw0QkFBa0I4RixTQUFsQixDQUE0QnJMLFFBQVF1RixvQkFBcEMsRUFBMEQsQ0FDdEhqSSxZQUFZMEMsT0FBWixDQUFvQnVGLG9CQUFwQixDQUF5Q3VrQixPQUQ2RSxFQUV0SHhzQixZQUFZMEMsT0FBWixDQUFvQnVGLG9CQUFwQixDQUF5Q3drQixLQUY2RSxFQUd0SHpzQixZQUFZMEMsT0FBWixDQUFvQnVGLG9CQUFwQixDQUF5QzRZLE1BSDZFLENBQTFELENBQWhFLEVBSUk7QUFDQSw0Q0FBa0I1UyxVQUFsQiw0SUFBOEp2TCxRQUFRdUYsb0JBQXRLO0FBQ0g7O0FBRUQsZ0JBQUksQ0FBQyw0QkFBa0J3RixRQUFsQixDQUEyQi9LLFFBQVE2RSxZQUFuQyxDQUFELElBQXFELENBQUNpa0IsMENBQTBDZixJQUExQyxDQUErQy9uQixRQUFRNkUsWUFBdkQsQ0FBMUQsRUFBZ0k7QUFDNUgsNENBQWtCMEcsVUFBbEIsNElBQW9LdkwsUUFBUTZFLFlBQTVLO0FBQ0g7O0FBRUQsZ0JBQUksQ0FBQyw0QkFBa0JrRyxRQUFsQixDQUEyQi9LLFFBQVE4RSxZQUFuQyxDQUFELElBQXFELENBQUNna0IsMENBQTBDZixJQUExQyxDQUErQy9uQixRQUFROEUsWUFBdkQsQ0FBMUQsRUFBZ0k7QUFDNUgsNENBQWtCeUcsVUFBbEIsNElBQW9LdkwsUUFBUThFLFlBQTVLO0FBQ0g7O0FBRUQsZ0JBQUlrbEIsV0FBV2hxQixRQUFROEUsWUFBbkIsSUFBbUNrbEIsV0FBV2hxQixRQUFRNkUsWUFBbkIsQ0FBdkMsRUFBeUU7QUFDckUsNENBQWtCMEcsVUFBbEIsOEdBQXNJdkwsUUFBUThFLFlBQTlJLG1EQUFzTTlFLFFBQVE2RSxZQUE5TTtBQUNIOztBQUVELGdCQUFJLEVBQUcsNEJBQWtCeUcsS0FBbEIsQ0FBd0J0TCxRQUFRNkQsYUFBaEMsS0FBa0Q3RCxRQUFRNkQsYUFBUixJQUF5QixDQUE1RSxJQUFrRjtBQUNuRix3Q0FBa0JrSCxRQUFsQixDQUEyQi9LLFFBQVE2RCxhQUFuQyxLQUFxRCtrQixvQkFBb0JiLElBQXBCLENBQXlCL25CLFFBQVE2RCxhQUFqQyxDQUR0RCxDQUFKLENBQzRHO0FBRDVHLGNBRUU7QUFDRSxnREFBa0IwSCxVQUFsQiwyR0FBbUl2TCxRQUFRNkQsYUFBM0k7QUFDSDs7QUFFRCxnQkFBSSxFQUFFLDRCQUFrQjRDLE1BQWxCLENBQXlCekcsUUFBUWdFLHFCQUFqQyxLQUNELDRCQUFrQnNILEtBQWxCLENBQXdCdEwsUUFBUWdFLHFCQUFoQyxLQUEwRGhFLFFBQVFnRSxxQkFBUixJQUFpQyxDQUQxRixJQUNnRztBQUNqRyx3Q0FBa0IrRyxRQUFsQixDQUEyQi9LLFFBQVFnRSxxQkFBbkMsS0FBNkQ0a0Isb0JBQW9CYixJQUFwQixDQUF5Qi9uQixRQUFRZ0UscUJBQWpDLENBRjlELENBQUosQ0FFNEg7QUFGNUgsY0FHRTtBQUNFLGdEQUFrQnVILFVBQWxCLCtJQUF5S3ZMLFFBQVFnRSxxQkFBakw7QUFDSDs7QUFFRDtBQUNBLGlCQUFLaW1CLDhCQUFMLENBQW9DanFCLE9BQXBDOztBQUVBLGdCQUFJLENBQUMsNEJBQWtCeUcsTUFBbEIsQ0FBeUJ6RyxRQUFRa0UseUJBQWpDLENBQUQsSUFDQSxDQUFDMGtCLG9CQUFvQmIsSUFBcEIsQ0FBeUJ4TSxPQUFPdmIsUUFBUWtFLHlCQUFmLENBQXpCLENBREwsRUFDMEU7QUFDdEUsNENBQWtCcUgsVUFBbEIsMElBQW9LdkwsUUFBUWtFLHlCQUE1SztBQUNIOztBQUVEO0FBQ0EsZ0JBQUksQ0FBQyw0QkFBa0J1QyxNQUFsQixDQUF5QnpHLFFBQVFrRSx5QkFBakMsQ0FBRCxJQUFnRXFJLE9BQU92TSxRQUFRNkQsYUFBZixJQUFnQzBJLE9BQU92TSxRQUFRa0UseUJBQWYsQ0FBcEcsRUFBK0k7QUFDM0ksNENBQWtCSixPQUFsQixpRUFBc0Y5RCxRQUFRa0UseUJBQTlGLHdEQUF3S2xFLFFBQVE2RCxhQUFoTCxpSkFBMlU3RCxRQUFRK0QsWUFBblY7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQjBDLE1BQWxCLENBQXlCekcsUUFBUXNFLG9CQUFqQyxDQUFELElBQ0EsQ0FBQ3lrQiwyQkFBMkJoQixJQUEzQixDQUFnQy9uQixRQUFRc0Usb0JBQXhDLENBREQsSUFFQXRFLFFBQVFzRSxvQkFBUixLQUFpQyxDQUZqQyxJQUVzQ3RFLFFBQVFzRSxvQkFBUixLQUFpQyxHQUZ2RSxJQUdBdEUsUUFBUXNFLG9CQUFSLEtBQWlDLENBSGpDLElBR3NDdEUsUUFBUXNFLG9CQUFSLEtBQWlDLEdBSDNFLEVBR2dGO0FBQzVFLDRDQUFrQmlILFVBQWxCLHVJQUErSnZMLFFBQVFzRSxvQkFBdks7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQm1DLE1BQWxCLENBQXlCekcsUUFBUWlFLHdCQUFqQyxDQUFELElBQStELENBQUMya0Isb0JBQW9CYixJQUFwQixDQUF5Qi9uQixRQUFRaUUsd0JBQWpDLENBQXBFLEVBQWdJO0FBQzVILDRDQUFrQnNILFVBQWxCLCtJQUF5S3ZMLFFBQVFpRSx3QkFBakw7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQndDLE1BQWxCLENBQXlCekcsUUFBUTRGLG1CQUFqQyxDQUFELElBQTBELENBQUMsNEJBQWtCbUYsUUFBbEIsQ0FBMkIvSyxRQUFRNEYsbUJBQW5DLENBQS9ELEVBQXdIO0FBQ3BILDRDQUFrQjJGLFVBQWxCLDRHQUFvSXZMLFFBQVE0RixtQkFBNUk7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQitpQixtQkFBbEIsQ0FBc0Mzb0IsUUFBUTJGLHlCQUE5QyxDQUFELElBQTZFLENBQUMsNEJBQWtCa0osU0FBbEIsQ0FBNEI3TyxRQUFRMkYseUJBQXBDLENBQWxGLEVBQWtKO0FBQzlJLDRDQUFrQjRGLFVBQWxCLGdJQUFvSnZMLFFBQVEyRix5QkFBNUo7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQjBGLFNBQWxCLENBQTRCckwsUUFBUXFGLGNBQXBDLEVBQW9ELENBQ3JEL0gsWUFBWTBDLE9BQVosQ0FBb0JxRixjQUFwQixDQUFtQzJHLEtBRGtCLEVBRXJEMU8sWUFBWTBDLE9BQVosQ0FBb0JxRixjQUFwQixDQUFtQzhZLE1BRmtCLEVBR3JEN2dCLFlBQVkwQyxPQUFaLENBQW9CcUYsY0FBcEIsQ0FBbUMrWSxLQUhrQixFQUlyRDlnQixZQUFZMEMsT0FBWixDQUFvQnFGLGNBQXBCLENBQW1DOFgsUUFKa0IsRUFLckQ3ZixZQUFZMEMsT0FBWixDQUFvQnFGLGNBQXBCLENBQW1DNkgsT0FMa0IsQ0FBcEQsQ0FBTCxFQU1JO0FBQ0EsNENBQWtCM0IsVUFBbEIsd0tBQXNMdkwsUUFBUXFGLGNBQTlMO0FBQ0g7O0FBRUQsZ0JBQUksQ0FBQyw0QkFBa0JnRyxTQUFsQixDQUE0QnJMLFFBQVEwRixjQUFwQyxFQUFvRCxDQUNyRHBJLFlBQVkwQyxPQUFaLENBQW9CMEYsY0FBcEIsQ0FBbUN3a0IsZUFEa0IsRUFFckQ1c0IsWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQ3lrQixnQkFGa0IsRUFHckQ3c0IsWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQzBrQixpQkFIa0IsRUFJckQ5c0IsWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQzJrQixrQkFKa0IsRUFLckQvc0IsWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQzRrQix1QkFMa0IsRUFNckRodEIsWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQzZrQixtQkFOa0IsRUFPckRqdEIsWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQzhrQixtQkFQa0IsRUFRckRsdEIsWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQytrQiwrQkFSa0IsRUFTckRudEIsWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQ2dsQiw2QkFUa0IsRUFVckRwdEIsWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQ2lsQixXQVZrQixFQVdyRHJ0QixZQUFZMEMsT0FBWixDQUFvQjBGLGNBQXBCLENBQW1Da2xCLGNBWGtCLEVBWXJEdHRCLFlBQVkwQyxPQUFaLENBQW9CMEYsY0FBcEIsQ0FBbUNtbEIsVUFaa0IsRUFhckR2dEIsWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQ29sQixZQWJrQixDQUFwRCxDQUFMLEVBY0k7QUFDQSw0Q0FBa0J2ZixVQUFsQiwrTUFBNk12TCxRQUFRMEYsY0FBck47QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQmUsTUFBbEIsQ0FBeUJ6RyxRQUFRZ0YsMEJBQWpDLENBQUQsSUFBaUUsQ0FBQyw0QkFBa0JxRyxTQUFsQixDQUE0QnJMLFFBQVFnRiwwQkFBcEMsRUFBZ0UsQ0FDbEkxSCxZQUFZMEMsT0FBWixDQUFvQmdGLDBCQUFwQixDQUErQytsQixXQURtRixFQUVsSXp0QixZQUFZMEMsT0FBWixDQUFvQmdGLDBCQUFwQixDQUErQ2dtQixRQUZtRixFQUdsSTF0QixZQUFZMEMsT0FBWixDQUFvQmdGLDBCQUFwQixDQUErQ2ltQixRQUhtRixFQUlsSTN0QixZQUFZMEMsT0FBWixDQUFvQmdGLDBCQUFwQixDQUErQ2ttQixXQUptRixFQUtsSTV0QixZQUFZMEMsT0FBWixDQUFvQmdGLDBCQUFwQixDQUErQ21tQixhQUxtRixFQU1sSTd0QixZQUFZMEMsT0FBWixDQUFvQmdGLDBCQUFwQixDQUErQ29tQixzQkFObUYsRUFPbEk5dEIsWUFBWTBDLE9BQVosQ0FBb0JnRiwwQkFBcEIsQ0FBK0NxbUIsWUFQbUYsRUFRbEkvdEIsWUFBWTBDLE9BQVosQ0FBb0JnRiwwQkFBcEIsQ0FBK0NzbUIsbUJBUm1GLEVBU2xJaHVCLFlBQVkwQyxPQUFaLENBQW9CZ0YsMEJBQXBCLENBQStDdW1CLGNBVG1GLEVBVWxJanVCLFlBQVkwQyxPQUFaLENBQW9CZ0YsMEJBQXBCLENBQStDd21CLFVBVm1GLENBQWhFLENBQXRFLEVBV0k7QUFDQSw0Q0FBa0JqZ0IsVUFBbEIsbVFBQStNdkwsUUFBUWdGLDBCQUF2TjtBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCcUcsU0FBbEIsQ0FBNEJyTCxRQUFRdUUsa0JBQXBDLEVBQXdELENBQ3pEakgsWUFBWTBDLE9BQVosQ0FBb0J1RSxrQkFBcEIsQ0FBdUN5TixLQURrQixFQUV6RDFVLFlBQVkwQyxPQUFaLENBQW9CdUUsa0JBQXBCLENBQXVDa25CLEtBRmtCLEVBR3pEbnVCLFlBQVkwQyxPQUFaLENBQW9CdUUsa0JBQXBCLENBQXVDdUosTUFIa0IsRUFJekR4USxZQUFZMEMsT0FBWixDQUFvQnVFLGtCQUFwQixDQUF1Q2tJLElBSmtCLEVBS3pEblAsWUFBWTBDLE9BQVosQ0FBb0J1RSxrQkFBcEIsQ0FBdUNDLElBTGtCLENBQXhELENBQUwsRUFNSTtBQUNBLDRDQUFrQitHLFVBQWxCLDBKQUF3S3ZMLFFBQVF1RSxrQkFBaEw7QUFDSDs7QUFFRCxnQkFBSXZFLFFBQVF1RSxrQkFBUixLQUErQmpILFlBQVkwQyxPQUFaLENBQW9CdUUsa0JBQXBCLENBQXVDa0ksSUFBdEUsS0FDQ3pNLFFBQVE4RSxZQUFSLEdBQXVCLENBQXZCLElBQTRCOUUsUUFBUTZFLFlBQVIsR0FBdUIsQ0FEcEQsQ0FBSixFQUM0RDtBQUN4RCw0Q0FBa0IwRyxVQUFsQixxSkFBdUt2TCxRQUFROEUsWUFBL0ssVUFBZ005RSxRQUFRNkUsWUFBeE07QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQndHLFNBQWxCLENBQTRCckwsUUFBUTRFLFdBQXBDLEVBQWlELENBQ2xEdEgsWUFBWTBDLE9BQVosQ0FBb0I0RSxXQUFwQixDQUFnQzhtQixLQURrQixFQUVsRHB1QixZQUFZMEMsT0FBWixDQUFvQjRFLFdBQXBCLENBQWdDaWUsSUFGa0IsRUFHbER2bEIsWUFBWTBDLE9BQVosQ0FBb0I0RSxXQUFwQixDQUFnQ3dLLElBSGtCLENBQWpELENBQUwsRUFJSTtBQUNBLDRDQUFrQjdELFVBQWxCLDBIQUE0SXZMLFFBQVE0RSxXQUFwSjtBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCK2pCLG1CQUFsQixDQUFzQzNvQixRQUFRdkIsZ0JBQTlDLENBQUQsSUFBb0UsQ0FBQyw0QkFBa0JvUSxTQUFsQixDQUE0QjdPLFFBQVF2QixnQkFBcEMsQ0FBekUsRUFBZ0k7QUFDNUgsNENBQWtCOE0sVUFBbEIsd0hBQTRJdkwsUUFBUXZCLGdCQUFwSjtBQUNIOztBQUVELGdCQUFJLENBQUNtcUIsb0JBQW9CYixJQUFwQixDQUF5Qi9uQixRQUFRMEUsV0FBakMsQ0FBRCxJQUFrRDFFLFFBQVEwRSxXQUFSLEtBQXdCLENBQTlFLEVBQWlGO0FBQzdFLDRDQUFrQjZHLFVBQWxCLDZGQUFxSHZMLFFBQVEwRSxXQUE3SDtBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCaWtCLG1CQUFsQixDQUFzQzNvQixRQUFRNkYsZ0JBQTlDLENBQUQsSUFBb0UsQ0FBQyw0QkFBa0JnSixTQUFsQixDQUE0QjdPLFFBQVE2RixnQkFBcEMsQ0FBekUsRUFBZ0k7QUFDNUgsNENBQWtCMEYsVUFBbEIsa0hBQXNJdkwsUUFBUTZGLGdCQUE5STtBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCOGlCLG1CQUFsQixDQUFzQzNvQixRQUFROEYsYUFBOUMsQ0FBRCxJQUFpRSxDQUFDLDRCQUFrQitJLFNBQWxCLENBQTRCN08sUUFBUThGLGFBQXBDLENBQXRFLEVBQTBIO0FBQ3RILDRDQUFrQnlGLFVBQWxCLDRHQUFnSXZMLFFBQVE4RixhQUF4STtBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCVyxNQUFsQixDQUF5QnpHLFFBQVFtRSxvQkFBakMsQ0FBRCxJQUE0RG5FLFFBQVFtRSxvQkFBUixLQUFpQyxFQUFqQyxJQUF1QyxDQUFDMmtCLDBDQUEwQ2YsSUFBMUMsQ0FBK0MvbkIsUUFBUW1FLG9CQUF2RCxDQUF4RyxFQUF1TDtBQUNuTCw0Q0FBa0JvSCxVQUFsQix1SkFBK0t2TCxRQUFRbUUsb0JBQXZMO0FBQ0g7O0FBRUQsZ0JBQUksQ0FBQyw0QkFBa0J3a0IsbUJBQWxCLENBQXNDM29CLFFBQVFxRyxnQkFBOUMsQ0FBRCxJQUFvRSxDQUFDLDRCQUFrQndJLFNBQWxCLENBQTRCN08sUUFBUXFHLGdCQUFwQyxDQUF6RSxFQUFnSTtBQUM1SCw0Q0FBa0JrRixVQUFsQiwySEFBK0l2TCxRQUFRcUcsZ0JBQXZKO0FBQ0g7O0FBRUQsZ0JBQUksQ0FBQyw0QkFBa0JJLE1BQWxCLENBQXlCekcsUUFBUXNGLFlBQWpDLENBQUQsSUFBbUQsQ0FBQyw0QkFBa0IrRixTQUFsQixDQUE0QnJMLFFBQVFzRixZQUFwQyxFQUFrRCxDQUN0R2hJLFlBQVkwQyxPQUFaLENBQW9Cc0YsWUFBcEIsQ0FBaUNxbUIsTUFEcUUsRUFFdEdydUIsWUFBWTBDLE9BQVosQ0FBb0JzRixZQUFwQixDQUFpQ3NtQixNQUZxRSxFQUd0R3R1QixZQUFZMEMsT0FBWixDQUFvQnNGLFlBQXBCLENBQWlDNGpCLEdBSHFFLEVBSXRHNXJCLFlBQVkwQyxPQUFaLENBQW9Cc0YsWUFBcEIsQ0FBaUN1bUIsV0FKcUUsRUFLdEd2dUIsWUFBWTBDLE9BQVosQ0FBb0JzRixZQUFwQixDQUFpQzJqQixLQUxxRSxFQU10RzNyQixZQUFZMEMsT0FBWixDQUFvQnNGLFlBQXBCLENBQWlDd21CLGFBTnFFLEVBT3RHeHVCLFlBQVkwQyxPQUFaLENBQW9Cc0YsWUFBcEIsQ0FBaUN5bUIsV0FQcUUsRUFRdEd6dUIsWUFBWTBDLE9BQVosQ0FBb0JzRixZQUFwQixDQUFpQzBtQixhQVJxRSxDQUFsRCxDQUF4RCxFQVNJO0FBQ0EsNENBQWtCemdCLFVBQWxCLHVLQUErS3ZMLFFBQVFzRixZQUF2TDtBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCcWpCLG1CQUFsQixDQUFzQzNvQixRQUFRMkUsYUFBOUMsQ0FBRCxJQUFpRSxDQUFDLDRCQUFrQmtLLFNBQWxCLENBQTRCN08sUUFBUTJFLGFBQXBDLENBQXRFLEVBQTBIO0FBQ3RILDRDQUFrQjRHLFVBQWxCLGlIQUFxSXZMLFFBQVEyRSxhQUE3STtBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCZ2tCLG1CQUFsQixDQUFzQzNvQixRQUFRK0Usa0JBQTlDLENBQUQsSUFBc0UsQ0FBQyw0QkFBa0I4SixTQUFsQixDQUE0QjdPLFFBQVErRSxrQkFBcEMsQ0FBM0UsRUFBb0k7QUFDaEksNENBQWtCd0csVUFBbEIsb0lBQXdKdkwsUUFBUStFLGtCQUFoSztBQUNIOztBQUVELGdCQUFJLEVBQUUsNEJBQWtCZ0csUUFBbEIsQ0FBMkIvSyxRQUFRc0csU0FBbkMsS0FBaUQsNEJBQWtCNkgsUUFBbEIsQ0FBMkJuTyxRQUFRc0csU0FBbkMsQ0FBbkQsS0FDQ3RHLFFBQVFzRyxTQUFSLEtBQXNCLGFBQXRCLElBQXVDLENBQUN5aUIsMkJBQTJCaEIsSUFBM0IsQ0FBZ0MvbkIsUUFBUXNHLFNBQXhDLENBRHpDLElBRUFpRyxPQUFPdk0sUUFBUXNHLFNBQWYsTUFBOEIsQ0FGbEMsRUFFcUM7QUFDakM7QUFDQSw0Q0FBa0JpRixVQUFsQiwwTEFBZ052TCxRQUFRc0csU0FBeE47QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQitFLFNBQWxCLENBQTRCckwsUUFBUStGLGVBQXBDLEVBQXFELENBQ3REekksWUFBWTBDLE9BQVosQ0FBb0IrRixlQUFwQixDQUFvQ2ttQixJQURrQixFQUV0RDN1QixZQUFZMEMsT0FBWixDQUFvQitGLGVBQXBCLENBQW9DbW1CLE9BRmtCLENBQXJELENBQUwsRUFHSTtBQUNBLDRDQUFrQjNnQixVQUFsQixxSEFBeUl2TCxRQUFRK0YsZUFBako7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQjRpQixtQkFBbEIsQ0FBc0Mzb0IsUUFBUW5CLGdCQUE5QyxDQUFELElBQW9FLENBQUMsNEJBQWtCZ1EsU0FBbEIsQ0FBNEI3TyxRQUFRbkIsZ0JBQXBDLENBQXpFLEVBQWdJO0FBQzVILDRDQUFrQjBNLFVBQWxCLDRJQUFnS3ZMLFFBQVFuQixnQkFBeEs7QUFDSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQjRILE1BQWxCLENBQXlCekcsUUFBUWtHLFVBQWpDLENBQUQsSUFDQSxFQUFFLDRCQUFrQmdnQixRQUFsQixDQUEyQmxtQixRQUFRa0csVUFBbkMsTUFDQWxHLFFBQVFrRyxVQUFSLENBQW1CNk8sY0FBbkIsQ0FBa0MsVUFBbEMsS0FDRi9VLFFBQVFrRyxVQUFSLENBQW1CNk8sY0FBbkIsQ0FBa0MsVUFBbEMsQ0FERSxJQUVGL1UsUUFBUWtHLFVBQVIsQ0FBbUI2TyxjQUFuQixDQUFrQyxRQUFsQyxDQUZFLElBR0YvVSxRQUFRa0csVUFBUixDQUFtQjZPLGNBQW5CLENBQWtDLGFBQWxDLENBSkUsQ0FBRixDQURKLEVBS3lEO0FBQ3JELDRDQUFrQnhKLFVBQWxCLGlMQUFpTXZMLFFBQVFrRyxVQUF6TTtBQUNIOztBQUVEO0FBQ0EsZ0JBQUksQ0FBQyw0QkFBa0JPLE1BQWxCLENBQXlCekcsUUFBUWtHLFVBQWpDLENBQUQsSUFDQWxHLFFBQVFrRyxVQUFSLENBQW1CNk8sY0FBbkIsQ0FBa0MsYUFBbEMsQ0FEQSxJQUVBLENBQUMsNEJBQWtCdE8sTUFBbEIsQ0FBeUJ6RyxRQUFRa0csVUFBUixDQUFtQjBFLFdBQTVDLENBRkwsRUFFK0Q7QUFDM0Q1Syx3QkFBUWtHLFVBQVIsQ0FBbUIwRSxXQUFuQixDQUErQjFLLE9BQS9CLENBQXVDLGdCQUFRO0FBQzNDLHdCQUFJaXNCLEtBQUtwWCxjQUFMLENBQW9CLFVBQXBCLEtBQW1DLENBQUMsNEJBQWtCbEssVUFBbEIsQ0FBNkJzaEIsS0FBSzVyQixRQUFsQyxDQUF4QyxFQUFxRjtBQUNqRixvREFBa0JnTCxVQUFsQixxRkFBZ0g0Z0IsS0FBSzVyQixRQUFySDtBQUNIO0FBQ0osaUJBSkQ7QUFLSDs7QUFFRCxnQkFBSSxDQUFDLDRCQUFrQmtHLE1BQWxCLENBQXlCekcsUUFBUXdGLGVBQWpDLENBQUQsSUFDQSxDQUFDdWpCLDJCQUEyQmhCLElBQTNCLENBQWdDL25CLFFBQVF3RixlQUF4QyxDQURELElBRUF4RixRQUFRd0YsZUFBUixLQUE0QixDQUY1QixJQUVpQ3hGLFFBQVF3RixlQUFSLEtBQTRCLEdBRjdELElBR0F4RixRQUFRd0YsZUFBUixLQUE0QixDQUg1QixJQUdpQ3hGLFFBQVF3RixlQUFSLEtBQTRCLEdBSGpFLEVBR3NFO0FBQ2xFLDRDQUFrQitGLFVBQWxCLDRJQUFvS3ZMLFFBQVF3RixlQUE1SztBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCbWpCLG1CQUFsQixDQUFzQzNvQixRQUFReUYsUUFBOUMsQ0FBRCxJQUE0RCxDQUFDLDRCQUFrQm9KLFNBQWxCLENBQTRCN08sUUFBUXlGLFFBQXBDLENBQWpFLEVBQWdIO0FBQzVHLDRDQUFrQjhGLFVBQWxCLHVGQUEyR3ZMLFFBQVF5RixRQUFuSDtBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCa2pCLG1CQUFsQixDQUFzQzNvQixRQUFRb0csZUFBOUMsQ0FBRCxJQUFtRSxDQUFDLDRCQUFrQnlJLFNBQWxCLENBQTRCN08sUUFBUW9HLGVBQXBDLENBQXhFLEVBQThIO0FBQzFILDRDQUFrQm1GLFVBQWxCLDhGQUFrSHZMLFFBQVFvRyxlQUExSDtBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCdWlCLG1CQUFsQixDQUFzQzNvQixRQUFReUUsbUJBQTlDLENBQUQsSUFBdUUsQ0FBQyw0QkFBa0JvSyxTQUFsQixDQUE0QjdPLFFBQVF5RSxtQkFBcEMsQ0FBNUUsRUFBc0k7QUFDbEksNENBQWtCOEcsVUFBbEIsd0dBQTRIdkwsUUFBUXlFLG1CQUFwSTtBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCa2tCLG1CQUFsQixDQUFzQzNvQixRQUFRTixlQUE5QyxDQUFELElBQW1FLENBQUMsNEJBQWtCbVAsU0FBbEIsQ0FBNEI3TyxRQUFRTixlQUFwQyxDQUF4RSxFQUE4SDtBQUMxSCw0Q0FBa0I2TCxVQUFsQixvR0FBd0h2TCxRQUFRTixlQUFoSTtBQUNIO0FBQ0o7O0FBRUQ7Ozs7Ozs7Ozt1REFNc0NNLE8sRUFBUztBQUMzQztBQUNBLGdCQUFJLENBQUMsNEJBQWtCeUcsTUFBbEIsQ0FBeUJ6RyxRQUFRZ0UscUJBQWpDLENBQUwsRUFBOEQ7QUFDMUQsb0JBQUloRSxRQUFRZ0UscUJBQVIsR0FBZ0NoRSxRQUFRNkQsYUFBNUMsRUFBMkQ7QUFDdkQsZ0RBQWtCQyxPQUFsQiw4REFBcUY5RCxRQUFRZ0UscUJBQTdGLDZDQUEwSmhFLFFBQVE2RCxhQUFsSyxxTkFDNko3RCxRQUFRK0QsWUFEcks7QUFFSDs7QUFFRCxvQkFBSS9ELFFBQVFnRSxxQkFBUixHQUFnQ2hFLFFBQVFrRSx5QkFBNUMsRUFBdUU7QUFDbkUsZ0RBQWtCSixPQUFsQiw4REFBcUY5RCxRQUFRZ0UscUJBQTdGLGlEQUE4SmhFLFFBQVFrRSx5QkFBdEssaU9BQ3lLbEUsUUFBUStELFlBRGpMO0FBRUg7O0FBRUQsb0JBQUkvRCxRQUFRZ0UscUJBQVIsR0FBZ0NoRSxRQUFRaUUsd0JBQTVDLEVBQXNFO0FBQ2xFLGdEQUFrQkgsT0FBbEIsOERBQXFGOUQsUUFBUWdFLHFCQUE3Rix1REFBb0toRSxRQUFRaUUsd0JBQTVLLGdPQUN3S2pFLFFBQVErRCxZQURoTDtBQUVIO0FBQ0o7QUFDSjs7QUFFRDs7Ozs7Ozs7O3lDQU13Qi9ELE8sRUFBUztBQUM3QixnQkFBSW9zQixVQUFVLElBQWQ7QUFDQSxnQkFBSTtBQUNBLHFCQUFLOUosUUFBTCxDQUFjdGlCLE9BQWQsRUFBdUIsSUFBdkI7QUFDSCxhQUZELENBRUUsT0FBT2dNLEtBQVAsRUFBYztBQUNab2dCLDBCQUFVLEtBQVY7QUFDSDs7QUFFRCxtQkFBT0EsT0FBUDtBQUNIOztBQUVEOzs7Ozs7OzsyQ0FLMEI7QUFDdEIsbUJBQU85dUIsWUFBWStGLGVBQW5CO0FBQ0g7O0FBRUQ7Ozs7Ozs7OzsrQ0FNOEI7QUFDMUIsbUJBQU8vRixZQUFZZ3FCLGlCQUFuQjtBQUNIOztBQUVEOzs7Ozs7Ozs7OzsrREFROEN0bkIsTyxFQUFTO0FBQUE7O0FBQ25ELGdCQUFJcXNCLHNCQUFKO0FBQ0EsZ0JBQUksNEJBQWtCbmlCLHdCQUFsQixDQUEyQ2xLLE9BQTNDLEtBQXVEQSxRQUFRNEksTUFBUixLQUFtQixDQUE5RSxFQUFpRjtBQUM3RXlqQixnQ0FBZ0IsSUFBaEI7QUFDSCxhQUZELE1BRU87QUFDSEEsZ0NBQWdCLEVBQWhCO0FBQ0Esb0JBQUlyc0IsUUFBUTRJLE1BQVIsS0FBbUIsQ0FBbkIsSUFBd0J3ZCxNQUFNbmIsT0FBTixDQUFjakwsUUFBUSxDQUFSLENBQWQsQ0FBNUIsRUFBdUQ7QUFDbkRBLDRCQUFRLENBQVIsRUFBV0UsT0FBWCxDQUFtQix3QkFBZ0I7QUFDL0I7QUFDQSxpQ0FBY21zQixhQUFkLEVBQTZCLE9BQUt0RixnQkFBTCxDQUFzQmhiLFlBQXRCLENBQTdCO0FBQ0gscUJBSEQ7QUFJSCxpQkFMRCxNQUtPLElBQUkvTCxRQUFRNEksTUFBUixJQUFrQixDQUF0QixFQUF5QjtBQUM1QjVJLDRCQUFRRSxPQUFSLENBQWdCLHdCQUFnQjtBQUM1QixpQ0FBY21zQixhQUFkLEVBQTZCLE9BQUt0RixnQkFBTCxDQUFzQmhiLFlBQXRCLENBQTdCO0FBQ0gscUJBRkQ7QUFHSDtBQUNKOztBQUVELG1CQUFPc2dCLGFBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7OzsrQkFVY0MseUIsRUFBdUM7QUFDakQsZ0JBQUksNEJBQWtCcGdCLFdBQWxCLENBQThCb2dCLHlCQUE5QixLQUE0REEsOEJBQThCLElBQTlGLEVBQW9HO0FBQ2hHLHVCQUFPLElBQVA7QUFDSDs7QUFFRDtBQUNBLGdCQUFJanNCLGNBQUo7QUFDQSxnQkFBSSw0QkFBa0IrUSxTQUFsQixDQUE0QmtiLHlCQUE1QixDQUFKLEVBQTREO0FBQ3hEanNCLHdCQUFRLDRCQUFrQm9PLGVBQWxCLENBQWtDNmQseUJBQWxDLENBQVI7QUFDSCxhQUZELE1BRU87QUFDSGpzQix3QkFBUWlzQix5QkFBUjtBQUNIOztBQUVELGdCQUFJLENBQUMsNEJBQWtCdmhCLFFBQWxCLENBQTJCMUssS0FBM0IsQ0FBRCxJQUFzQyxDQUFDLDRCQUFrQjhOLFFBQWxCLENBQTJCOU4sS0FBM0IsQ0FBM0MsRUFBOEU7QUFDMUUsNENBQWtCa0wsVUFBbEIsaUJBQTJDbEwsS0FBM0M7QUFDSDs7QUFFRDs7QUFqQmlELCtDQUFUTCxPQUFTO0FBQVRBLHVCQUFTO0FBQUE7O0FBa0JqRCxnQkFBTThMLGVBQWUsS0FBS3lnQixzQ0FBTCxDQUE0Q3ZzQixPQUE1QyxDQUFyQjs7QUFFQTtBQUNBLGdCQUFNeEIsV0FBVyxTQUFjLEVBQWQsRUFBa0IsS0FBSytpQixnQkFBTCxFQUFsQixFQUEyQ3pWLFlBQTNDLENBQWpCO0FBQ0EsZ0JBQUl6TCxRQUFRLENBQVosRUFBZTtBQUNYN0IseUJBQVMrVyxxQkFBVCxHQUFpQyxHQUFqQztBQUNILGFBRkQsTUFFTztBQUNIL1cseUJBQVMrVyxxQkFBVCxHQUFpQyxFQUFqQztBQUNIOztBQUVELGdCQUFNMk0sUUFBUSxFQUFkO0FBQ0EsaUJBQUtDLDhCQUFMLENBQW9DM2pCLFFBQXBDLEVBQThDMGpCLEtBQTlDLEVBN0JpRCxDQTZCSzs7QUFFdEQ7QUFDQTtBQUNBLGdCQUFJc0ssY0FBYyxLQUFLbmdCLGVBQUwsQ0FBcUJoTSxLQUFyQixFQUE0QjdCLFFBQTVCLENBQWxCO0FBQ0EsZ0JBQUk4TixNQUFNQyxPQUFPaWdCLFdBQVAsQ0FBTixDQUFKLEVBQWdDO0FBQzVCLDRDQUFrQmpoQixVQUFsQixpQkFBMkNpaEIsV0FBM0M7QUFDSDs7QUFFRDs7QUF0Q2lELHdDQXVDdEIsS0FBSzlmLGlDQUFMLENBQXVDOGYsV0FBdkMsRUFBb0RodUIsUUFBcEQsQ0F2Q3NCO0FBQUE7QUFBQSxnQkF1QzFDbU8sT0F2QzBDO0FBQUEsZ0JBdUNqQ0MsT0F2Q2lDOztBQXdDakQsZ0JBQUksQ0FBQ0QsT0FBRCxJQUFZLENBQUNDLE9BQWpCLEVBQTBCO0FBQ3RCO0FBQ0EsNENBQWtCYSxZQUFsQixDQUErQm5RLFlBQVlvUSxNQUFaLENBQW1CaUIsU0FBbEQsRUFBNkRsRyxRQUE3RCxFQUF1RSxtQkFBdkU7QUFDQSw0Q0FBa0I4QyxVQUFsQixpQkFBMkNpaEIsV0FBM0MsdURBQXdHaHVCLFNBQVNzRyxZQUFqSCw0QkFBb0p0RyxTQUFTcUcsWUFBN0o7QUFDSDs7QUFFRDtBQUNBLGlCQUFLK2MsMkNBQUwsQ0FBaURwakIsUUFBakQ7QUFDQTtBQUNBLGlCQUFLc2pCLDZCQUFMLENBQW1DdGpCLFFBQW5DOztBQUVBO0FBQ0EsZ0JBQUssQ0FBQyw0QkFBa0IwTCx3QkFBbEIsQ0FBMkMxTCxTQUFTZ0gsZUFBcEQsQ0FBRCxJQUF5RWhILFNBQVNnSCxlQUFULEtBQTZCLENBQXZHLElBQTZHO0FBQzdHZ25CLDRCQUFnQixFQURoQixJQUNzQkEsZ0JBQWdCLElBRDFDLEVBQ2dEO0FBQUU7QUFDOUNBLCtCQUFlaHVCLFNBQVNnSCxlQUF4QjtBQUNIOztBQUVEO0FBQ0FnbkIsMEJBQWMsS0FBS3BmLGdDQUFMLENBQXNDb2YsV0FBdEMsRUFBbURodUIsUUFBbkQsQ0FBZDtBQUNBZ3VCLDBCQUFjLEtBQUtqZix1REFBTCxDQUE2RGlmLFdBQTdELEVBQTBFaHVCLFFBQTFFLENBQWQ7QUFDQWd1QiwwQkFBYyxLQUFLaGYsbUJBQUwsQ0FBeUJnZixXQUF6QixFQUFzQ2h1QixRQUF0QyxFQUFnRCxLQUFoRCxFQUF1RGd1QixXQUF2RCxDQUFkOztBQUVBLG1CQUFPQSxXQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7cUNBT29CN3VCLFUsRUFBNEI7QUFBQSxnQkFBaEJxQyxPQUFnQix1RUFBTixJQUFNO0FBQUU7QUFDOUMsZ0JBQU1rWSxpQkFBaUIsS0FBSzdHLE1BQUwsQ0FBWTFULFVBQVosRUFBd0JxQyxPQUF4QixDQUF2QjtBQUNBLHdDQUFrQjBPLGVBQWxCLENBQWtDL1EsVUFBbEMsRUFBOEN1YSxjQUE5Qzs7QUFFQSxtQkFBT0EsY0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7O2lDQVVnQm9VLHlCLEVBQXVDO0FBQ25ELGdCQUFJLDRCQUFrQkcsY0FBbEIsQ0FBaUNILHlCQUFqQyxDQUFKLEVBQWlFO0FBQzdEO0FBQ0EsdUJBQU9BLHlCQUFQO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBSWpzQixjQUFKO0FBQ0EsZ0JBQUksNEJBQWtCK1EsU0FBbEIsQ0FBNEJrYix5QkFBNUIsQ0FBSixFQUE0RDtBQUN4RGpzQix3QkFBUSw0QkFBa0JvTyxlQUFsQixDQUFrQzZkLHlCQUFsQyxDQUFSO0FBQ0gsYUFGRCxNQUVPO0FBQ0hqc0Isd0JBQVFpc0IseUJBQVI7QUFDSDs7QUFFRCxnQkFBSSw0QkFBa0JwZ0IsV0FBbEIsQ0FBOEI3TCxLQUE5QixLQUF3Q0EsVUFBVSxJQUF0RCxFQUE0RDtBQUN4RCx1QkFBTyxJQUFQO0FBQ0g7O0FBRUQsZ0JBQUksNEJBQWtCNEssT0FBbEIsQ0FBMEI1SyxLQUExQixLQUFvQyw0QkFBa0I2bEIsUUFBbEIsQ0FBMkI3bEIsS0FBM0IsQ0FBeEMsRUFBMkU7QUFDdkU7QUFDQSw0Q0FBa0JrTCxVQUFsQix1RkFBaUhsTCxLQUFqSDtBQUNIOztBQUVEOztBQXZCbUQsK0NBQVRMLE9BQVM7QUFBVEEsdUJBQVM7QUFBQTs7QUF3Qm5ELGdCQUFNOEwsZUFBZSxLQUFLeWdCLHNDQUFMLENBQTRDdnNCLE9BQTVDLENBQXJCOztBQUVBO0FBQ0EsZ0JBQU14QixXQUFXLFNBQWMsRUFBZCxFQUFrQixLQUFLK2lCLGdCQUFMLEVBQWxCLEVBQTJDelYsWUFBM0MsQ0FBakI7QUFDQXpMLG9CQUFRQSxNQUFNZ04sUUFBTixFQUFSOztBQUVBO0FBQ0EsZ0JBQUksNEJBQWtCdUMsVUFBbEIsQ0FBNkJ2UCxLQUE3QixDQUFKLEVBQXlDO0FBQ3JDN0IseUJBQVMrVyxxQkFBVCxHQUFpQyxHQUFqQztBQUNILGFBRkQsTUFFTyxJQUFJLENBQUMsNEJBQWtCOU8sTUFBbEIsQ0FBeUJqSSxTQUFTd0csMEJBQWxDLENBQUwsRUFBb0U7QUFBQSw2Q0FDdkJ4RyxTQUFTd0csMEJBQVQsQ0FBb0NtUSxLQUFwQyxDQUEwQyxHQUExQyxDQUR1Qjs7QUFBQTs7QUFDdEUzVyx5QkFBUzRXLFlBRDZEO0FBQy9DNVcseUJBQVM2VyxXQURzQzs7QUFFdkUsb0JBQUloVixNQUFNa2EsTUFBTixDQUFhLENBQWIsTUFBb0IvYixTQUFTNFcsWUFBN0IsSUFDQS9VLE1BQU1rYSxNQUFOLENBQWFsYSxNQUFNdUksTUFBTixHQUFlLENBQTVCLE1BQW1DcEssU0FBUzZXLFdBRGhELEVBQzZEO0FBQ3pEN1csNkJBQVMrVyxxQkFBVCxHQUFpQyxHQUFqQztBQUNBbFYsNEJBQVEsS0FBSzJOLGVBQUwsQ0FBcUIzTixLQUFyQixFQUE0QjdCLFFBQTVCLEVBQXNDLEtBQXRDLENBQVI7QUFDSDtBQUNKOztBQUVENkIsb0JBQVEsS0FBS3FzQix1QkFBTCxDQUE2QnJzQixLQUE3QixFQUFvQzdCLFFBQXBDLENBQVI7QUFDQSxnQkFBTW11QixxQkFBcUIsSUFBSTFKLE1BQUoscUJBQStCLElBQS9CLENBQTNCO0FBQ0EsZ0JBQUkwSixtQkFBbUI1RSxJQUFuQixDQUF3QjFuQixLQUF4QixDQUFKLEVBQW9DO0FBQ2hDLHVCQUFPdXNCLEdBQVA7QUFDSDs7QUFFRDtBQUNBLGlCQUFLaEwsMkNBQUwsQ0FBaURwakIsUUFBakQ7QUFDQTtBQUNBLGdCQUFJQSxTQUFTd0YscUJBQWIsRUFBb0M7QUFBRTtBQUNsQ3hGLHlCQUFTMmlCLDZCQUFULEdBQXlDM2lCLFNBQVN3RixxQkFBbEQ7QUFDSCxhQUZELE1BRU87QUFDSHhGLHlCQUFTMmlCLDZCQUFULEdBQXlDM2lCLFNBQVNxRixhQUFsRDtBQUNIOztBQUVELGlCQUFLaWUsNkJBQUwsQ0FBbUN0akIsUUFBbkM7O0FBRUE7QUFDQSxnQkFBSyxDQUFDLDRCQUFrQjBMLHdCQUFsQixDQUEyQzFMLFNBQVNnSCxlQUFwRCxDQUFELElBQXlFaEgsU0FBU2dILGVBQVQsS0FBNkIsQ0FBdkcsSUFBNkc7QUFDN0duRixzQkFBVSxFQURWLElBQ2dCQSxVQUFVLElBRDlCLEVBQ29DO0FBQUU7QUFDbENBLHlCQUFTN0IsU0FBU2dILGVBQWxCO0FBQ0g7O0FBRURuRixvQkFBUSxLQUFLMk0sY0FBTCxDQUFvQjNNLEtBQXBCLEVBQTJCN0IsUUFBM0IsQ0FBUjtBQUNBNkIsb0JBQVFBLE1BQU02TSxPQUFOLENBQWMxTyxTQUFTbUYsZ0JBQXZCLEVBQXlDLEdBQXpDLENBQVIsQ0FsRW1ELENBa0VJO0FBQ3ZEdEQsb0JBQVEsS0FBSzZPLFNBQUwsQ0FBZTdPLEtBQWYsRUFBc0I3QixTQUFTOEcsWUFBL0IsQ0FBUjs7QUFFQSxtQkFBT2pGLEtBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozt1Q0FPc0IxQyxVLEVBQTRCO0FBQUEsZ0JBQWhCcUMsT0FBZ0IsdUVBQU4sSUFBTTtBQUFFO0FBQ2hELGdCQUFNd1AsbUJBQW1CLEtBQUt4TyxRQUFMLENBQWNyRCxVQUFkLEVBQTBCcUMsT0FBMUIsQ0FBekI7QUFDQSx3Q0FBa0IwTyxlQUFsQixDQUFrQy9RLFVBQWxDLEVBQThDNlIsZ0JBQTlDOztBQUVBLG1CQUFPQSxnQkFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7O2lDQVVnQjhjLHlCLEVBQTJDO0FBQUEsZ0JBQWhCdHNCLE9BQWdCLHVFQUFOLElBQU07O0FBQ3ZELGdCQUFJSyxjQUFKO0FBQ0EsZ0JBQUksNEJBQWtCK1EsU0FBbEIsQ0FBNEJrYix5QkFBNUIsQ0FBSixFQUE0RDtBQUN4RGpzQix3QkFBUSw0QkFBa0JvTyxlQUFsQixDQUFrQzZkLHlCQUFsQyxDQUFSO0FBQ0gsYUFGRCxNQUVPO0FBQ0hqc0Isd0JBQVFpc0IseUJBQVI7QUFDSDs7QUFFRCxnQkFBSSw0QkFBa0I3bEIsTUFBbEIsQ0FBeUJ6RyxPQUF6QixDQUFKLEVBQXVDO0FBQ25DQSwwQkFBVTFDLFlBQVkrRixlQUF0QjtBQUNIOztBQUVEaEQsb0JBQVEsS0FBS1csUUFBTCxDQUFjWCxLQUFkLEVBQXFCTCxPQUFyQixDQUFSOztBQUVBO0FBQ0EsZ0JBQUl1TSxPQUFPbE0sS0FBUCxNQUFrQixDQUFsQixJQUF1QkwsUUFBUTRFLFdBQVIsS0FBd0J0SCxZQUFZMEMsT0FBWixDQUFvQjRFLFdBQXBCLENBQWdDd0ssSUFBbkYsRUFBeUY7QUFDckYvTyx3QkFBUSxHQUFSO0FBQ0g7O0FBRUQsZ0JBQUlnUCwwQkFBSjtBQUNBLGdCQUFJLDRCQUFrQjVJLE1BQWxCLENBQXlCekcsT0FBekIsQ0FBSixFQUF1QztBQUNuQ3FQLG9DQUFvQnJQLFFBQVFzRixZQUE1QjtBQUNILGFBRkQsTUFFTztBQUNIK0osb0NBQW9CL1IsWUFBWStGLGVBQVosQ0FBNEJpQyxZQUFoRDtBQUNIOztBQUVELG1CQUFPLEtBQUs0SixTQUFMLENBQWU3TyxLQUFmLEVBQXNCZ1AsaUJBQXRCLENBQVA7QUFDSDs7O3VDQUVxQjFSLFUsRUFBNEI7QUFBQSxnQkFBaEJxQyxPQUFnQix1RUFBTixJQUFNO0FBQUU7QUFDaEQsZ0JBQU02c0IsaUJBQWlCLEtBQUtDLFFBQUwsQ0FBY252QixVQUFkLEVBQTBCcUMsT0FBMUIsQ0FBdkI7QUFDQSx3Q0FBa0IwTyxlQUFsQixDQUFrQy9RLFVBQWxDLEVBQThDa3ZCLGNBQTlDOztBQUVBLG1CQUFPQSxjQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7OzsrQ0FNOEJsdkIsVSxFQUFZO0FBQUU7QUFDeEMsbUJBQU8sS0FBS3FxQixlQUFMLENBQXFCcnFCLFVBQXJCLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7OzhDQU02QkEsVSxFQUFZO0FBQUU7QUFDdkMsZ0JBQUksQ0FBQyxLQUFLbWlCLHNCQUFMLENBQTRCbmlCLFVBQTVCLENBQUwsRUFBOEM7QUFDMUMsdUJBQU8sSUFBUDtBQUNIOztBQUVELG1CQUFPLEtBQUsycUIsa0JBQUwsQ0FBd0IzcUIsVUFBeEIsQ0FBUDtBQUNIOzs7cURBbUxtQzJYLEMsRUFBRzlXLFEsRUFBVW1rQixVLEVBQVlyakIsUyxFQUFXO0FBQ3BFO0FBQ0E7QUFDQTtBQUNBZ1csZ0JBQUlpRyxPQUFPakcsQ0FBUCxDQUFKLENBSm9FLENBSXJEOztBQUVmLGdCQUFJOVcsU0FBU2lGLGNBQVQsS0FBNEIsRUFBaEMsRUFBb0M7QUFDaEM7QUFDQTZSLG9CQUFJQSxFQUFFcEksT0FBRixDQUFVMU8sU0FBU2lGLGNBQW5CLEVBQW1DLEVBQW5DLENBQUo7QUFDSDs7QUFFRCxnQkFBSWpGLFNBQVMySCxVQUFiLEVBQXlCO0FBQ3JCO0FBQ0FtUCxvQkFBSUEsRUFBRXBJLE9BQUYsQ0FBVTFPLFNBQVMySCxVQUFuQixFQUErQixFQUEvQixDQUFKO0FBQ0g7O0FBRUQ7O0FBRUE7QUFDQW1QLGdCQUFJQSxFQUFFcEksT0FBRixDQUFVMU8sU0FBU3V1QixrQkFBbkIsRUFBdUMsTUFBdkMsQ0FBSjs7QUFFQTtBQUNBelgsZ0JBQUlBLEVBQUVwSSxPQUFGLENBQVUxTyxTQUFTd3VCLGlCQUFuQixFQUFzQyxJQUF0QyxDQUFKOztBQUVBO0FBQ0ExWCxnQkFBSUEsRUFBRXBJLE9BQUYsQ0FBVTFPLFNBQVN5dUIsZ0JBQW5CLEVBQXFDLEVBQXJDLENBQUo7QUFDQSxnQkFBSXp1QixTQUFTb0YsMkJBQWIsRUFBMEM7QUFDdEMwUixvQkFBSUEsRUFBRXBJLE9BQUYsQ0FBVTFPLFNBQVNvRiwyQkFBbkIsRUFBZ0RwRixTQUFTbUYsZ0JBQXpELENBQUo7QUFDSDs7QUFFRDtBQUNBLGdCQUFNcWYsSUFBSTFOLEVBQUVFLEtBQUYsQ0FBUWhYLFNBQVMwdUIsZUFBakIsQ0FBVjtBQUNBNVgsZ0JBQUkwTixJQUFJLENBQUNBLEVBQUUsQ0FBRixDQUFELEVBQU9BLEVBQUUsQ0FBRixDQUFQLEVBQWFBLEVBQUUsQ0FBRixDQUFiLEVBQW1CcUIsSUFBbkIsQ0FBd0IsRUFBeEIsQ0FBSixHQUFrQyxFQUF0Qzs7QUFFQSxnQkFBSTdsQixTQUFTb0csV0FBVCxLQUF5QnRILFlBQVkwQyxPQUFaLENBQW9CNEUsV0FBcEIsQ0FBZ0M4bUIsS0FBekQsSUFBa0VsdEIsU0FBU29HLFdBQVQsS0FBeUJ0SCxZQUFZMEMsT0FBWixDQUFvQjRFLFdBQXBCLENBQWdDd0ssSUFBL0gsRUFBcUk7QUFDakksb0JBQUltVyxlQUFlLEVBQW5COztBQURpSSwrQkFFOUZqUSxFQUFFSCxLQUFGLENBQVEzVyxTQUFTbUYsZ0JBQWpCLENBRjhGO0FBQUE7QUFBQSxvQkFFMUh3cEIsV0FGMEg7QUFBQSxvQkFFN0dDLFdBRjZHOztBQUdqSSxvQkFBSUMsc0JBQXNCRixXQUExQjtBQUNBLG9CQUFJLDRCQUFrQnBYLFFBQWxCLENBQTJCc1gsbUJBQTNCLEVBQWdEN3VCLFNBQVMrVyxxQkFBekQsQ0FBSixFQUFxRjtBQUNqRmdRLG1DQUFlL21CLFNBQVMrVyxxQkFBeEI7QUFDQThYLDBDQUFzQkEsb0JBQW9CbmdCLE9BQXBCLENBQTRCMU8sU0FBUytXLHFCQUFyQyxFQUE0RCxFQUE1RCxDQUF0QjtBQUNIOztBQUVEO0FBQ0Esb0JBQUlnUSxpQkFBaUIsRUFBakIsSUFBdUI4SCxvQkFBb0J6a0IsTUFBcEIsR0FBNkJwSyxTQUFTc2lCLE9BQTdELElBQXdFdU0sb0JBQW9COVMsTUFBcEIsQ0FBMkIsQ0FBM0IsTUFBa0MsR0FBOUcsRUFBbUg7QUFDL0c4UywwQ0FBc0JBLG9CQUFvQjlRLEtBQXBCLENBQTBCLENBQTFCLENBQXRCO0FBQ0g7O0FBRUQ7QUFDQSxvQkFBSWdKLGlCQUFpQixFQUFqQixJQUF1QjhILG9CQUFvQnprQixNQUFwQixHQUE2QnBLLFNBQVN3aUIsT0FBN0QsSUFBd0VxTSxvQkFBb0I5UyxNQUFwQixDQUEyQixDQUEzQixNQUFrQyxHQUE5RyxFQUFtSDtBQUMvRzhTLDBDQUFzQkEsb0JBQW9COVEsS0FBcEIsQ0FBMEIsQ0FBMUIsQ0FBdEI7QUFDSDs7QUFFRGpILHlCQUFPaVEsWUFBUCxHQUFzQjhILG1CQUF0QixJQUE0Qyw0QkFBa0JuaEIsV0FBbEIsQ0FBOEJraEIsV0FBOUIsSUFBMkMsRUFBM0MsR0FBOEM1dUIsU0FBU21GLGdCQUFULEdBQTRCeXBCLFdBQXRIO0FBQ0g7O0FBRUQsZ0JBQUt6SyxjQUFjbmtCLFNBQVNvRyxXQUFULEtBQXlCdEgsWUFBWTBDLE9BQVosQ0FBb0I0RSxXQUFwQixDQUFnQ2llLElBQXhFLElBQ0MsQ0FBQ3ZqQixTQUFELElBQWNkLFNBQVNvRyxXQUFULEtBQXlCdEgsWUFBWTBDLE9BQVosQ0FBb0I0RSxXQUFwQixDQUFnQzhtQixLQUQ1RSxFQUNvRjtBQUNoRnBXLG9CQUFJQSxFQUFFcEksT0FBRixDQUFVMU8sU0FBUzh1QixRQUFuQixFQUE2QixNQUE3QixDQUFKO0FBQ0g7O0FBRUQsbUJBQU9oWSxDQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7OzsrQ0FTOEJqVixLLEVBQU83QixRLEVBQVVjLFMsRUFBVztBQUN0RDtBQUNBLGdCQUFJa0IsZUFBSjtBQUNBLGdCQUFJbEIsU0FBSixFQUFlO0FBQ1hrQix5QkFBUyxLQUFLd04sZUFBTCxDQUFxQjNOLEtBQXJCLEVBQTRCN0IsUUFBNUIsQ0FBVDtBQUNILGFBRkQsTUFFTztBQUNIZ0MseUJBQVMsS0FBSytzQixZQUFMLENBQWtCbHRCLEtBQWxCLEVBQXlCN0IsUUFBekIsQ0FBVDtBQUNIOztBQUVELG1CQUFPZ0MsTUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7OztxQ0FRb0JILEssRUFBTzdCLFEsRUFBVTtBQUNqQyxnQkFBSWdDLGVBQUo7QUFDQSxnQkFBSSxDQUFDLDRCQUFrQmlHLE1BQWxCLENBQXlCakksU0FBU3dHLDBCQUFsQyxDQUFMLEVBQW9FO0FBQ2hFeEUsOEJBQVloQyxTQUFTNFcsWUFBckIsR0FBb0MvVSxNQUFNNk0sT0FBTixDQUFjMU8sU0FBUytXLHFCQUF2QixFQUE4QyxFQUE5QyxDQUFwQyxHQUF3Ri9XLFNBQVM2VyxXQUFqRztBQUNILGFBRkQsTUFFTztBQUNIN1UseUJBQVNILEtBQVQ7QUFDSDs7QUFFRCxtQkFBT0csTUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7d0NBU3VCSCxLLEVBQU83QixRLEVBQThDO0FBQUEsZ0JBQXBDZ3ZCLDJCQUFvQyx1RUFBTixJQUFNOztBQUN4RSxnQkFBSWh0QixlQUFKO0FBQ0EsZ0JBQUksQ0FBQyw0QkFBa0JpRyxNQUFsQixDQUF5QmpJLFNBQVN3RywwQkFBbEMsQ0FBRCxJQUFrRTNFLE1BQU1rYSxNQUFOLENBQWEsQ0FBYixNQUFvQi9iLFNBQVM0VyxZQUFuRyxFQUFpSDtBQUM3RztBQUNBNVUseUJBQVNILE1BQU02TSxPQUFOLENBQWMxTyxTQUFTNFcsWUFBdkIsRUFBcUMsRUFBckMsQ0FBVDtBQUNBNVUseUJBQVNBLE9BQU8wTSxPQUFQLENBQWUxTyxTQUFTNlcsV0FBeEIsRUFBcUMsRUFBckMsQ0FBVDs7QUFFQTtBQUNBLG9CQUFJbVksMkJBQUosRUFBaUM7QUFDN0I7QUFDQWh0Qiw2QkFBU0EsT0FBTzBNLE9BQVAsQ0FBZTFPLFNBQVNpRixjQUF4QixFQUF3QyxFQUF4QyxDQUFUO0FBQ0FqRCw2QkFBUyxLQUFLaXRCLDhDQUFMLENBQW9EanRCLE1BQXBELEVBQTREaEMsUUFBNUQsRUFBc0UsSUFBdEUsRUFBNEUsS0FBNUUsQ0FBVCxDQUg2QixDQUdnRTtBQUNoRyxpQkFKRCxNQUlPO0FBQ0g7QUFDQWdDLDZCQUFTLE1BQU1BLE1BQWY7QUFDSDtBQUNKLGFBZEQsTUFjTztBQUNIQSx5QkFBU0gsS0FBVDtBQUNIOztBQUVELG1CQUFPRyxNQUFQO0FBQ0g7OztnREF5QjhCOFUsQyxFQUFHOVcsUSxFQUFVO0FBQ3hDO0FBQ0E4VyxnQkFBSUEsRUFBRXBJLE9BQUYsQ0FBVTFPLFNBQVNpRixjQUFuQixFQUFtQyxFQUFuQyxDQUFKOztBQUVBO0FBQ0E2UixnQkFBSUEsRUFBRXBJLE9BQUYsQ0FBVSxJQUFJK1YsTUFBSixPQUFlemtCLFNBQVM2RixtQkFBeEIsUUFBZ0QsR0FBaEQsQ0FBVixFQUFnRSxFQUFoRSxDQUFKOztBQUVBO0FBQ0EsZ0JBQUk3RixTQUFTbUYsZ0JBQVQsS0FBOEIsR0FBbEMsRUFBdUM7QUFDbkMyUixvQkFBSUEsRUFBRXBJLE9BQUYsQ0FBVTFPLFNBQVNtRixnQkFBbkIsRUFBcUMsR0FBckMsQ0FBSjtBQUNIOztBQUVEO0FBQ0EsZ0JBQUluRixTQUFTMkgsVUFBVCxLQUF3QjdJLFlBQVkwQyxPQUFaLENBQW9CbUcsVUFBcEIsQ0FBK0JnSyxJQUEzRCxFQUFpRTtBQUM3RG1GLG9CQUFJQSxFQUFFcEksT0FBRixDQUFVMU8sU0FBUzJILFVBQW5CLEVBQStCLEVBQS9CLENBQUo7QUFDSDs7QUFFRDtBQUNBLGdCQUFJLDRCQUFrQnlKLFVBQWxCLENBQTZCMEYsQ0FBN0IsS0FBbUNBLEVBQUVvWSxXQUFGLENBQWMsR0FBZCxNQUF1QnBZLEVBQUUxTSxNQUFGLEdBQVcsQ0FBekUsRUFBNEU7QUFDeEUwTSxvQkFBSUEsRUFBRXBJLE9BQUYsQ0FBVSxHQUFWLEVBQWUsRUFBZixDQUFKO0FBQ0FvSSxvQkFBSSxNQUFNQSxDQUFWO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBTXFZLGtCQUFrQm52QixTQUFTb0csV0FBVCxLQUF5QnRILFlBQVkwQyxPQUFaLENBQW9CNEUsV0FBcEIsQ0FBZ0N3SyxJQUFqRjtBQUNBLGdCQUFNd2UsT0FBTyw0QkFBa0JqUixvQkFBbEIsQ0FBdUNySCxDQUF2QyxFQUEwQ3FZLGVBQTFDLEVBQTJELEtBQTNELEVBQWtFLEtBQWxFLENBQWI7QUFDQSxnQkFBSSxDQUFDcmhCLE1BQU1zaEIsSUFBTixDQUFMLEVBQWtCO0FBQ2R0WSxvQkFBSXNZLEtBQUt2Z0IsUUFBTCxFQUFKO0FBQ0g7O0FBRUQsbUJBQU9pSSxDQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7O2tDQVFpQmpWLEssRUFBT3d0QixNLEVBQVE7QUFDNUIsZ0JBQUksNEJBQWtCcG5CLE1BQWxCLENBQXlCb25CLE1BQXpCLEtBQW9DQSxXQUFXdndCLFlBQVkwQyxPQUFaLENBQW9Cc0YsWUFBcEIsQ0FBaUNxbUIsTUFBcEYsRUFBNEY7QUFDeEYsdUJBQU90ckIsS0FBUDtBQUNIOztBQUVELGdCQUFJRyxlQUFKO0FBQ0Esb0JBQVFxdEIsTUFBUjtBQUNJLHFCQUFLdndCLFlBQVkwQyxPQUFaLENBQW9Cc0YsWUFBcEIsQ0FBaUNzbUIsTUFBdEM7QUFDSXByQiw2QkFBUytMLE9BQU9sTSxLQUFQLENBQVQ7QUFDQTtBQUNKLHFCQUFLL0MsWUFBWTBDLE9BQVosQ0FBb0JzRixZQUFwQixDQUFpQ3ltQixXQUF0QztBQUNJdnJCLDZCQUFTLDRCQUFrQm9QLFVBQWxCLENBQTZCdlAsS0FBN0IsSUFBc0NBLE1BQU02TSxPQUFOLENBQWMsR0FBZCxFQUFtQixFQUFuQixJQUF5QixHQUEvRCxHQUFxRTdNLEtBQTlFO0FBQ0E7QUFDSixxQkFBSy9DLFlBQVkwQyxPQUFaLENBQW9Cc0YsWUFBcEIsQ0FBaUMyakIsS0FBdEM7QUFDQSxxQkFBSzNyQixZQUFZMEMsT0FBWixDQUFvQnNGLFlBQXBCLENBQWlDd21CLGFBQXRDO0FBQ0l0ckIsNkJBQVNILE1BQU02TSxPQUFOLENBQWMsR0FBZCxFQUFtQixHQUFuQixDQUFUO0FBQ0E7QUFDSixxQkFBSzVQLFlBQVkwQyxPQUFaLENBQW9Cc0YsWUFBcEIsQ0FBaUMwbUIsYUFBdEM7QUFDSXhyQiw2QkFBU0gsTUFBTTZNLE9BQU4sQ0FBYyxHQUFkLEVBQW1CLEdBQW5CLENBQVQ7QUFDQTFNLDZCQUFTLDRCQUFrQm9QLFVBQWxCLENBQTZCcFAsTUFBN0IsSUFBdUNBLE9BQU8wTSxPQUFQLENBQWUsR0FBZixFQUFvQixFQUFwQixJQUEwQixHQUFqRSxHQUF1RTFNLE1BQWhGO0FBQ0E7QUFDSjtBQUNBLHFCQUFLbEQsWUFBWTBDLE9BQVosQ0FBb0JzRixZQUFwQixDQUFpQzRqQixHQUF0QztBQUNBLHFCQUFLNXJCLFlBQVkwQyxPQUFaLENBQW9Cc0YsWUFBcEIsQ0FBaUN1bUIsV0FBdEM7QUFDSXJyQiw2QkFBU0gsS0FBVDtBQUNBO0FBQ0o7QUFDSSxnREFBa0JrTCxVQUFsQiw4QkFBd0RzaUIsTUFBeEQ7QUFyQlI7O0FBd0JBLG1CQUFPcnRCLE1BQVA7QUFDSDs7O2dGQWdDOEQ4VSxDLEVBQUc5VyxRLEVBQVU7QUFDeEU7QUFDQSxnQkFBSUEsU0FBUytXLHFCQUFULEtBQW1DLEdBQW5DLElBQTBDL1csU0FBUytXLHFCQUFULEtBQW1DLEVBQWpGLEVBQXFGO0FBQ2pGRCxvQkFBSUEsRUFBRXBJLE9BQUYsQ0FBVSxHQUFWLEVBQWUxTyxTQUFTK1cscUJBQXhCLENBQUo7QUFDSDs7QUFFRCxnQkFBSS9XLFNBQVNtRixnQkFBVCxLQUE4QixHQUFsQyxFQUF1QztBQUNuQzJSLG9CQUFJQSxFQUFFcEksT0FBRixDQUFVLEdBQVYsRUFBZTFPLFNBQVNtRixnQkFBeEIsQ0FBSjtBQUNIOztBQUVELG1CQUFPMlIsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7OztrRUFRaURqVixLLEVBQU83QixRLEVBQVU7QUFDOUQsbUJBQU82QixVQUFVLEVBQVYsSUFBZ0JBLFVBQVU3QixTQUFTK1cscUJBQTFDO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7OzsrREFTOENsVixLLEVBQU83QixRLEVBQVVzdkIsVyxFQUFhO0FBQ3hFLGdCQUFJdHRCLGVBQUo7QUFDQSxnQkFBSWhDLFNBQVMrRixrQkFBVCxLQUFnQ2pILFlBQVkwQyxPQUFaLENBQW9CdUUsa0JBQXBCLENBQXVDdUosTUFBdkUsSUFBaUZnZ0IsV0FBckYsRUFBa0c7QUFDOUYsb0JBQUl0dkIsU0FBU3lHLDZCQUFULEtBQTJDM0gsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q4SyxJQUFqRyxFQUF1RztBQUNuR3ZQLDZCQUFTSCxRQUFRN0IsU0FBU2lGLGNBQWpCLEdBQWtDakYsU0FBUzJILFVBQXBEO0FBQ0gsaUJBRkQsTUFFTztBQUNIM0YsNkJBQVNoQyxTQUFTaUYsY0FBVCxHQUEwQnBELEtBQTFCLEdBQWtDN0IsU0FBUzJILFVBQXBEO0FBQ0g7QUFDSixhQU5ELE1BTU87QUFDSDNGLHlCQUFTSCxLQUFUO0FBQ0g7O0FBRUQsbUJBQU9HLE1BQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7Ozs0Q0FVMkJ1dEIsVSxFQUFZdnZCLFEsRUFBVWMsUyxFQUFXMHVCLGUsRUFBd0M7QUFBQSxnQkFBdkJqaEIsY0FBdUIsdUVBQU4sSUFBTTs7QUFDaEc7QUFDQTtBQUNBLGdCQUFNMEksa0JBQWtCLDRCQUFrQjdGLFVBQWxCLENBQTZCbWUsVUFBN0IsS0FBNEMsNEJBQWtCRSxzQkFBbEIsQ0FBeUNGLFVBQXpDLEVBQXFEdnZCLFNBQVM0VyxZQUE5RCxFQUE0RTVXLFNBQVM2VyxXQUFyRixDQUFwRSxDQUhnRyxDQUd1RTs7QUFFdkswWSx5QkFBYSxLQUFLN2YsNEJBQUwsQ0FBa0M2ZixVQUFsQyxFQUE4Q3Z2QixRQUE5QyxFQUF3RCxLQUF4RCxFQUErRGMsU0FBL0QsQ0FBYjs7QUFFQSxnQkFBSSxLQUFLaVoseUNBQUwsQ0FBK0N3VixVQUEvQyxFQUEyRHZ2QixRQUEzRCxDQUFKLEVBQTBFO0FBQ3RFLHVCQUFPLEtBQUtpYSxzQ0FBTCxDQUE0Q3NWLFVBQTVDLEVBQXdEdnZCLFFBQXhELEVBQWtFLElBQWxFLENBQVA7QUFDSDs7QUFFRCxnQkFBTXNPLHFCQUFxQiw0QkFBa0JBLGtCQUFsQixDQUFxQ2loQixVQUFyQyxDQUEzQjs7QUFFQTtBQUNBLGdCQUFJdFksZUFBSixFQUFxQjtBQUNqQnNZLDZCQUFhQSxXQUFXN2dCLE9BQVgsQ0FBbUIsR0FBbkIsRUFBd0IsRUFBeEIsQ0FBYjtBQUNIOztBQUVEMU8scUJBQVM0RixtQkFBVCxHQUErQjVGLFNBQVM0RixtQkFBVCxDQUE2QmlKLFFBQTdCLEVBQS9CO0FBQ0EsZ0JBQUk2Z0IscUJBQUo7QUFDQSxvQkFBUTF2QixTQUFTNEYsbUJBQWpCO0FBQ0kscUJBQUs5RyxZQUFZMEMsT0FBWixDQUFvQm9FLG1CQUFwQixDQUF3QytwQixHQUE3QztBQUNJRCxtQ0FBZSxzQkFBZjtBQUNBO0FBQ0oscUJBQUs1d0IsWUFBWTBDLE9BQVosQ0FBb0JvRSxtQkFBcEIsQ0FBd0NncUIsU0FBN0M7QUFDSUYsbUNBQWUsbURBQWY7QUFDQTtBQUNKLHFCQUFLNXdCLFlBQVkwQyxPQUFaLENBQW9Cb0UsbUJBQXBCLENBQXdDaXFCLElBQTdDO0FBQ0lILG1DQUFlLGtCQUFmO0FBQ0E7QUFDSixxQkFBSzV3QixZQUFZMEMsT0FBWixDQUFvQm9FLG1CQUFwQixDQUF3Q2txQixLQUE3QztBQUNBO0FBQ0lKLG1DQUFlLGtCQUFmO0FBWlI7O0FBZUE7O0FBbkNnRyxvQ0FvQy9ESCxXQUFXNVksS0FBWCxDQUFpQjNXLFNBQVNtRixnQkFBMUIsQ0FwQytEO0FBQUE7QUFBQSxnQkFvQzNGd3BCLFdBcEMyRjtBQUFBLGdCQW9DOUVDLFdBcEM4RTs7QUFxQ2hHLGdCQUFJNXVCLFNBQVNvRiwyQkFBVCxJQUF3Qyw0QkFBa0JzSSxXQUFsQixDQUE4QmtoQixXQUE5QixDQUE1QyxFQUF3RjtBQUFBLHlDQUN2RFcsV0FBVzVZLEtBQVgsQ0FBaUIzVyxTQUFTb0YsMkJBQTFCLENBRHVEOztBQUFBOztBQUNuRnVwQiwyQkFEbUY7QUFDdEVDLDJCQURzRTtBQUV2Rjs7QUFFRCxnQkFBSTV1QixTQUFTNkYsbUJBQVQsS0FBaUMsRUFBckMsRUFBeUM7QUFDckM7QUFDQSx1QkFBTzZwQixhQUFhbkcsSUFBYixDQUFrQm9GLFdBQWxCLENBQVAsRUFBdUM7QUFDbkNBLGtDQUFjQSxZQUFZamdCLE9BQVosQ0FBb0JnaEIsWUFBcEIsU0FBdUMxdkIsU0FBUzZGLG1CQUFoRCxRQUFkO0FBQ0g7QUFDSjs7QUFFRDtBQUNBLGdCQUFJa3FCLCtCQUFKO0FBQ0EsZ0JBQUlqdkIsU0FBSixFQUFlO0FBQ1hpdkIseUNBQXlCL3ZCLFNBQVMwRix5QkFBbEM7QUFDSCxhQUZELE1BRU87QUFDSHFxQix5Q0FBeUIvdkIsU0FBU3lGLHdCQUFsQztBQUNIOztBQUVELGdCQUFJc3FCLDJCQUEyQixDQUEzQixJQUFnQyxDQUFDLDRCQUFrQnJpQixXQUFsQixDQUE4QmtoQixXQUE5QixDQUFyQyxFQUFpRjtBQUM3RSxvQkFBSUEsWUFBWXhrQixNQUFaLEdBQXFCMmxCLHNCQUF6QixFQUFpRDtBQUM3QztBQUNBbkIsa0NBQWNBLFlBQVkzSyxTQUFaLENBQXNCLENBQXRCLEVBQXlCOEwsc0JBQXpCLENBQWQ7QUFDSDs7QUFFRDtBQUNBUixrQ0FBZ0JaLFdBQWhCLEdBQThCM3VCLFNBQVNtRixnQkFBdkMsR0FBMER5cEIsV0FBMUQ7QUFDSCxhQVJELE1BUU87QUFDSDtBQUNBVyw2QkFBYVosV0FBYjtBQUNIOztBQUVEO0FBQ0FZLHlCQUFhendCLFlBQVltd0IsOENBQVosQ0FBMkRNLFVBQTNELEVBQXVFdnZCLFFBQXZFLEVBQWlGaVgsZUFBakYsRUFBa0czSSxrQkFBbEcsQ0FBYixDQXRFZ0csQ0FzRW9DOztBQUVwSSxnQkFBSSw0QkFBa0JyRyxNQUFsQixDQUF5QnNHLGNBQXpCLENBQUosRUFBOEM7QUFDMUM7QUFDQUEsaUNBQWlCaWhCLGVBQWpCO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBSXh2QixTQUFTd0csMEJBQVQsS0FBd0MsSUFBeEMsS0FBaUQrSCxpQkFBaUIsQ0FBakIsSUFBc0IsNEJBQWtCdVAsZ0JBQWxCLENBQW1DeVIsVUFBbkMsQ0FBdkUsQ0FBSixFQUE0SDtBQUN4SEEsNkJBQWEsS0FBS1Msc0JBQUwsQ0FBNEJULFVBQTVCLEVBQXdDdnZCLFFBQXhDLEVBQWtEYyxTQUFsRCxDQUFiO0FBQ0g7O0FBRUQsZ0JBQUlrQixlQUFKO0FBQ0EsZ0JBQUloQyxTQUFTMkgsVUFBYixFQUF5QjtBQUNyQjNGLDhCQUFZdXRCLFVBQVosR0FBeUJ2dkIsU0FBUzJILFVBQWxDO0FBQ0gsYUFGRCxNQUVPO0FBQ0gzRix5QkFBU3V0QixVQUFUO0FBQ0g7O0FBRUQsbUJBQU92dEIsTUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7dUVBWXNEdXRCLFUsRUFBWXZ2QixRLEVBQVVpWCxlLEVBQWlCM0ksa0IsRUFBb0I7QUFDN0csZ0JBQUlvSixZQUFZLEVBQWhCO0FBQ0EsZ0JBQUlULGVBQUosRUFBcUI7QUFDakJTLDRCQUFZMVgsU0FBUytXLHFCQUFyQjtBQUNILGFBRkQsTUFFTyxJQUFJL1csU0FBU3lILGdCQUFULElBQTZCLENBQUM2RyxrQkFBbEMsRUFBc0Q7QUFDekRvSiw0QkFBWTFYLFNBQVMyWCxxQkFBckI7QUFDSDs7QUFFRCxnQkFBSTNWLGVBQUo7QUFDQSxnQkFBSWhDLFNBQVNrRix1QkFBVCxLQUFxQ3BHLFlBQVkwQyxPQUFaLENBQW9CMEQsdUJBQXBCLENBQTRDc00sTUFBckYsRUFBNkY7QUFDekYsb0JBQUl4UixTQUFTeUcsNkJBQVQsS0FBMkMzSCxZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRGtMLElBQTdGLEtBQ0NzRixtQkFBb0IsQ0FBQ0EsZUFBRCxJQUFvQmpYLFNBQVN5SCxnQkFBN0IsSUFBaUQsQ0FBQzZHLGtCQUR2RSxDQUFKLEVBQ2lHO0FBQzdGLDRCQUFRdE8sU0FBU3lHLDZCQUFqQjtBQUNJLDZCQUFLM0gsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0QrSyxNQUF2RDtBQUNBLDZCQUFLMVMsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q4SyxJQUF2RDtBQUNJdlAsMENBQVkwVixTQUFaLEdBQXdCMVgsU0FBU2lGLGNBQWpDLEdBQWtEc3FCLFVBQWxEO0FBQ0E7QUFDSiw2QkFBS3p3QixZQUFZMEMsT0FBWixDQUFvQmlGLDZCQUFwQixDQUFrRGdMLEtBQXZEO0FBQ0l6UCwwQ0FBWWhDLFNBQVNpRixjQUFyQixHQUFzQ3lTLFNBQXRDLEdBQWtENlgsVUFBbEQ7QUFDQTtBQUNKLDZCQUFLendCLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtENkssTUFBdkQ7QUFDSXRQLDBDQUFZaEMsU0FBU2lGLGNBQXJCLEdBQXNDc3FCLFVBQXRDLEdBQW1EN1gsU0FBbkQ7QUFDQTtBQVZSO0FBWUgsaUJBZEQsTUFjTztBQUNIMVYsNkJBQVNoQyxTQUFTaUYsY0FBVCxHQUEwQnNxQixVQUFuQztBQUNIO0FBQ0osYUFsQkQsTUFrQk8sSUFBSXZ2QixTQUFTa0YsdUJBQVQsS0FBcUNwRyxZQUFZMEMsT0FBWixDQUFvQjBELHVCQUFwQixDQUE0Q29NLE1BQXJGLEVBQTZGO0FBQ2hHLG9CQUFJdFIsU0FBU3lHLDZCQUFULEtBQTJDM0gsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0RrTCxJQUE3RixLQUNDc0YsbUJBQW9CLENBQUNBLGVBQUQsSUFBb0JqWCxTQUFTeUgsZ0JBQTdCLElBQWlELENBQUM2RyxrQkFEdkUsQ0FBSixFQUNpRztBQUM3Riw0QkFBUXRPLFNBQVN5Ryw2QkFBakI7QUFDSSw2QkFBSzNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtENkssTUFBdkQ7QUFDQSw2QkFBS3hTLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEZ0wsS0FBdkQ7QUFDSXpQLDBDQUFZdXRCLFVBQVosR0FBeUJ2dkIsU0FBU2lGLGNBQWxDLEdBQW1EeVMsU0FBbkQ7QUFDQTtBQUNKLDZCQUFLNVksWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q4SyxJQUF2RDtBQUNJdlAsMENBQVl1dEIsVUFBWixHQUF5QjdYLFNBQXpCLEdBQXFDMVgsU0FBU2lGLGNBQTlDO0FBQ0E7QUFDSiw2QkFBS25HLFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEK0ssTUFBdkQ7QUFDSXhQLDBDQUFZMFYsU0FBWixHQUF3QjZYLFVBQXhCLEdBQXFDdnZCLFNBQVNpRixjQUE5QztBQUNBO0FBVlI7QUFZSCxpQkFkRCxNQWNPO0FBQ0hqRCw2QkFBU3V0QixhQUFhdnZCLFNBQVNpRixjQUEvQjtBQUNIO0FBQ0o7O0FBRUQsbUJBQU9qRCxNQUFQO0FBQ0g7Ozt1Q0E0TXFCaXVCLGlCLEVBQW1CQyxtQixFQUFxQjtBQUMxRCxnQkFBSXhNLGNBQUo7QUFDQSxvQkFBUXdNLG1CQUFSO0FBQ0kscUJBQUssQ0FBTDtBQUNJO0FBQ0F4TSw0QkFBUSxzQkFBUjtBQUNBO0FBQ0oscUJBQUssQ0FBTDtBQUNJO0FBQ0FBLDRCQUFRLHdCQUFSO0FBQ0E7QUFDSjtBQUNJO0FBQ0FBLDRCQUFRLElBQUllLE1BQUosY0FBc0J5TCxtQkFBdEIsd0JBQVI7QUFYUjs7QUFjQTtBQUNBRCxnQ0FBb0JBLGtCQUFrQnZoQixPQUFsQixDQUEwQmdWLEtBQTFCLEVBQWlDLElBQWpDLENBQXBCO0FBQ0EsZ0JBQUl3TSx3QkFBd0IsQ0FBNUIsRUFBK0I7QUFDM0JELG9DQUFvQkEsa0JBQWtCdmhCLE9BQWxCLENBQTBCLEtBQTFCLEVBQWlDLEVBQWpDLENBQXBCO0FBQ0g7O0FBRUQsbUJBQU91aEIsaUJBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7dUNBUXNCcHVCLEssRUFBTzdCLFEsRUFBVTtBQUNuQyxtQkFBTyxLQUFLaWQsV0FBTCxDQUFpQnBiLEtBQWpCLEVBQXdCN0IsUUFBeEIsRUFBa0NBLFNBQVN3RixxQkFBM0MsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozt5REFRd0MzRCxLLEVBQU83QixRLEVBQVU7QUFDckQsbUJBQU8sS0FBS2lkLFdBQUwsQ0FBaUJwYixLQUFqQixFQUF3QjdCLFFBQXhCLEVBQWtDK04sT0FBTy9OLFNBQVMwRix5QkFBaEIsQ0FBbEMsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozt3REFRdUM3RCxLLEVBQU83QixRLEVBQVU7QUFDcEQsbUJBQU8sS0FBS2lkLFdBQUwsQ0FBaUJwYixLQUFqQixFQUF3QjdCLFFBQXhCLEVBQWtDK04sT0FBTy9OLFNBQVN5Rix3QkFBaEIsQ0FBbEMsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7OztvQ0FXbUI4cEIsVSxFQUFZdnZCLFEsRUFBVSt2QixzQixFQUF3QjtBQUM3RDtBQUNBLGdCQUFJLDRCQUFrQjluQixNQUFsQixDQUF5QnNuQixVQUF6QixDQUFKLEVBQTBDO0FBQ3RDO0FBQ0EsdUJBQU9BLFVBQVA7QUFDSDs7QUFFRDtBQUNBQSx5QkFBY0EsZUFBZSxFQUFoQixHQUFzQixHQUF0QixHQUE0QkEsV0FBVzFnQixRQUFYLEVBQXpDO0FBQ0EsZ0JBQUk3TyxTQUFTa0gsY0FBVCxLQUE0QnBJLFlBQVkwQyxPQUFaLENBQW9CMEYsY0FBcEIsQ0FBbUNpbEIsV0FBL0QsSUFDQW5zQixTQUFTa0gsY0FBVCxLQUE0QnBJLFlBQVkwQyxPQUFaLENBQW9CMEYsY0FBcEIsQ0FBbUNrbEIsY0FEL0QsSUFFQXBzQixTQUFTa0gsY0FBVCxLQUE0QnBJLFlBQVkwQyxPQUFaLENBQW9CMEYsY0FBcEIsQ0FBbUNtbEIsVUFGL0QsSUFHQXJzQixTQUFTa0gsY0FBVCxLQUE0QnBJLFlBQVkwQyxPQUFaLENBQW9CMEYsY0FBcEIsQ0FBbUNvbEIsWUFIbkUsRUFHaUY7QUFDN0UsdUJBQU8sS0FBSzZELGVBQUwsQ0FBcUJaLFVBQXJCLEVBQWlDdnZCLFFBQWpDLENBQVA7QUFDSDs7QUFkNEQsd0NBZ0J2QmxCLFlBQVlzeEIsd0JBQVosQ0FBcUNiLFVBQXJDLEVBQWlEdnZCLFFBQWpELENBaEJ1QjtBQUFBO0FBQUEsZ0JBZ0J0RCttQixZQWhCc0Q7QUFBQSxnQkFnQnhDc0osYUFoQndDOztBQWlCN0RkLHlCQUFhYyxhQUFiOztBQUVBLGdCQUFNclUsMkJBQTJCdVQsV0FBV0wsV0FBWCxDQUF1QixHQUF2QixDQUFqQztBQUNBLGdCQUFNb0IscUJBQXFCdFUsNkJBQTZCLENBQUMsQ0FBekQsQ0FwQjZELENBb0JEOztBQXBCQyxxQ0FxQnJDdVQsV0FBVzVZLEtBQVgsQ0FBaUIsR0FBakIsQ0FyQnFDO0FBQUE7QUFBQSxnQkFxQnBEaVksV0FyQm9ELDBCQXFCZDs7O0FBQy9DLGdCQUFNMkIsY0FBYzNCLGNBQWMsQ0FBbEM7O0FBRUE7QUFDQSxnQkFBSSxDQUFDMkIsV0FBRCxLQUNDdndCLFNBQVM4RSxtQkFBVCxLQUFpQ2hHLFlBQVkwQyxPQUFaLENBQW9Cc0QsbUJBQXBCLENBQXdDcVksS0FBekUsSUFDRG5kLFNBQVM4RSxtQkFBVCxLQUFpQ2hHLFlBQVkwQyxPQUFaLENBQW9Cc0QsbUJBQXBCLENBQXdDc1ksTUFGekUsQ0FBSixFQUVzRjtBQUNsRix1QkFBUXJQLE9BQU93aEIsVUFBUCxNQUF1QixDQUF4QixHQUE2QkEsVUFBN0IsUUFBNkN4SSxZQUE3QyxHQUE0RHdJLFVBQW5FO0FBQ0g7O0FBRUQ7QUFDQTtBQUNBLGdCQUFJaUIsdUNBQUo7QUFDQSxnQkFBSXh3QixTQUFTOEUsbUJBQVQsS0FBaUNoRyxZQUFZMEMsT0FBWixDQUFvQnNELG1CQUFwQixDQUF3Q3dLLE1BQXpFLElBQ0F0UCxTQUFTOEUsbUJBQVQsS0FBaUNoRyxZQUFZMEMsT0FBWixDQUFvQnNELG1CQUFwQixDQUF3Q3NZLE1BRDdFLEVBQ3FGO0FBQ2pGb1QsaURBQWlDVCxzQkFBakM7QUFDSCxhQUhELE1BR087QUFDSFMsaURBQWlDLENBQWpDO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBTUMsdUJBQXVCSCxxQkFBcUJmLFdBQVdubEIsTUFBWCxHQUFvQixDQUF6QyxHQUE2QzRSLHdCQUExRTtBQUNBO0FBQ0EsZ0JBQUkwVSxxQkFBc0JuQixXQUFXbmxCLE1BQVgsR0FBb0IsQ0FBckIsR0FBMEJxbUIsb0JBQW5EO0FBQ0EsZ0JBQUlFLG9CQUFvQixFQUF4Qjs7QUFFQTtBQUNBLGdCQUFJRCxzQkFBc0JYLHNCQUExQixFQUFrRDtBQUM5QztBQUNBWSxvQ0FBb0JwQixVQUFwQjtBQUNBLG9CQUFJbUIscUJBQXFCRiw4QkFBekIsRUFBeUQ7QUFDckQsd0JBQUlGLGtCQUFKLEVBQXdCO0FBQ3BCSyxpREFBdUJBLGlCQUF2QixHQUEyQzN3QixTQUFTbUYsZ0JBQXBEO0FBQ0g7O0FBRUQsd0JBQUl5ckIsUUFBUSxRQUFaLENBTHFELENBSy9CO0FBQ3RCLDJCQUFPRixxQkFBcUJGLDhCQUE1QixFQUE0RDtBQUN4REksZ0NBQVFBLE1BQU0zTSxTQUFOLENBQWdCLENBQWhCLEVBQW1CdU0saUNBQWlDRSxrQkFBcEQsQ0FBUjtBQUNBQyw2Q0FBcUJDLEtBQXJCO0FBQ0FGLDhDQUFzQkUsTUFBTXhtQixNQUE1QjtBQUNIO0FBQ0osaUJBWEQsTUFXTyxJQUFJc21CLHFCQUFxQkYsOEJBQXpCLEVBQXlEO0FBQzVERyx3Q0FBb0IsS0FBS0UsY0FBTCxDQUFvQkYsaUJBQXBCLEVBQXVDSCw4QkFBdkMsQ0FBcEI7QUFDSCxpQkFGTSxNQUVBLElBQUlFLHVCQUF1QixDQUF2QixJQUE0QkYsbUNBQW1DLENBQW5FLEVBQXNFO0FBQ3pFO0FBQ0FHLHdDQUFvQkEsa0JBQWtCamlCLE9BQWxCLENBQTBCLEtBQTFCLEVBQWlDLEVBQWpDLENBQXBCO0FBQ0g7O0FBRUQsdUJBQVFYLE9BQU80aUIsaUJBQVAsTUFBOEIsQ0FBL0IsR0FBb0NBLGlCQUFwQyxRQUEyRDVKLFlBQTNELEdBQTBFNEosaUJBQWpGO0FBQ0g7O0FBRUQ7QUFDQSxnQkFBSUcseUJBQUo7QUFDQSxnQkFBSVIsa0JBQUosRUFBd0I7QUFDcEJRLG1DQUFtQmYseUJBQXlCLENBQTVDO0FBQ0gsYUFGRCxNQUVPO0FBQ0hlLG1DQUFtQi9pQixPQUFPZ2lCLHNCQUFQLElBQWlDaGlCLE9BQU9pTyx3QkFBUCxDQUFwRDtBQUNIOztBQUVELGdCQUFNK1UsWUFBWWhqQixPQUFPd2hCLFdBQVd4VCxNQUFYLENBQWtCK1UsbUJBQW1CLENBQXJDLENBQVAsQ0FBbEI7QUFDQSxnQkFBSUUsa0JBQWtCekIsV0FBV3RMLFNBQVgsQ0FBcUIsQ0FBckIsRUFBd0I2TSxtQkFBbUIsQ0FBM0MsRUFBOENuYSxLQUE5QyxDQUFvRCxFQUFwRCxDQUF0QjtBQUNBLGdCQUFJc2EsWUFBSjtBQUNBLGdCQUFJMUIsV0FBV3hULE1BQVgsQ0FBa0IrVSxnQkFBbEIsTUFBd0MsR0FBNUMsRUFBaUQ7QUFDN0NHLHNCQUFNMUIsV0FBV3hULE1BQVgsQ0FBa0IrVSxtQkFBbUIsQ0FBckMsSUFBMEMsQ0FBaEQ7QUFDSCxhQUZELE1BRU87QUFDSEcsc0JBQU0xQixXQUFXeFQsTUFBWCxDQUFrQitVLGdCQUFsQixJQUFzQyxDQUE1QztBQUNIOztBQUVELGdCQUFJLEtBQUtJLGNBQUwsQ0FBb0JILFNBQXBCLEVBQStCL3dCLFFBQS9CLEVBQXlDK21CLFlBQXpDLEVBQXVEa0ssR0FBdkQsQ0FBSixFQUFpRTtBQUM3RDtBQUNBLHFCQUFLLElBQUkxbEIsSUFBS3lsQixnQkFBZ0I1bUIsTUFBaEIsR0FBeUIsQ0FBdkMsRUFBMkNtQixLQUFLLENBQWhELEVBQW1EQSxLQUFLLENBQXhELEVBQTJEO0FBQ3ZELHdCQUFJeWxCLGdCQUFnQnpsQixDQUFoQixNQUF1QixHQUEzQixFQUFnQztBQUM1QnlsQix3Q0FBZ0J6bEIsQ0FBaEIsSUFBcUIsQ0FBQ3lsQixnQkFBZ0J6bEIsQ0FBaEIsQ0FBRCxHQUFzQixDQUEzQztBQUNBLDRCQUFJeWxCLGdCQUFnQnpsQixDQUFoQixJQUFxQixFQUF6QixFQUE2QjtBQUN6QjtBQUNIOztBQUVELDRCQUFJQSxJQUFJLENBQVIsRUFBVztBQUNQeWxCLDRDQUFnQnpsQixDQUFoQixJQUFxQixHQUFyQjtBQUNIO0FBQ0o7QUFDSjtBQUNKOztBQUVEO0FBQ0F5bEIsOEJBQWtCQSxnQkFBZ0JqVCxLQUFoQixDQUFzQixDQUF0QixFQUF5QitTLG1CQUFtQixDQUE1QyxDQUFsQjs7QUFFQTtBQUNBSCxnQ0FBb0IsS0FBS0UsY0FBTCxDQUFvQkcsZ0JBQWdCbkwsSUFBaEIsQ0FBcUIsRUFBckIsQ0FBcEIsRUFBOEMySyw4QkFBOUMsQ0FBcEI7O0FBRUEsbUJBQVF6aUIsT0FBTzRpQixpQkFBUCxNQUE4QixDQUEvQixHQUFvQ0EsaUJBQXBDLFFBQTJENUosWUFBM0QsR0FBMEU0SixpQkFBakY7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7d0NBUXVCOXVCLEssRUFBTzdCLFEsRUFBVTtBQUNwQyxvQkFBUUEsU0FBU2tILGNBQWpCO0FBQ0kscUJBQUtwSSxZQUFZMEMsT0FBWixDQUFvQjBGLGNBQXBCLENBQW1DaWxCLFdBQXhDO0FBQ0EscUJBQUtydEIsWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQ2tsQixjQUF4QztBQUNJdnFCLDRCQUFRLENBQUMwZ0IsS0FBSzRPLEtBQUwsQ0FBV3R2QixRQUFRLEVBQW5CLElBQXlCLEVBQTFCLEVBQThCZ04sUUFBOUIsRUFBUjtBQUNBO0FBQ0oscUJBQUsvUCxZQUFZMEMsT0FBWixDQUFvQjBGLGNBQXBCLENBQW1DbWxCLFVBQXhDO0FBQ0l4cUIsNEJBQVEsQ0FBQzBnQixLQUFLNk8sSUFBTCxDQUFVdnZCLFFBQVEsRUFBbEIsSUFBd0IsRUFBekIsRUFBNkJnTixRQUE3QixFQUFSO0FBQ0E7QUFDSjtBQUNJaE4sNEJBQVEsQ0FBQzBnQixLQUFLZ0osS0FBTCxDQUFXMXBCLFFBQVEsRUFBbkIsSUFBeUIsRUFBMUIsRUFBOEJnTixRQUE5QixFQUFSO0FBVFI7O0FBWUEsZ0JBQUk3TSxlQUFKO0FBQ0EsZ0JBQUksQ0FBQyw0QkFBa0J1VixRQUFsQixDQUEyQjFWLEtBQTNCLEVBQWtDLEdBQWxDLENBQUwsRUFBNkM7QUFDekNHLHlCQUFTSCxRQUFRLEtBQWpCO0FBQ0gsYUFGRCxNQUVPLElBQUlBLE1BQU11SSxNQUFOLEdBQWV2SSxNQUFNZ1EsT0FBTixDQUFjLEdBQWQsQ0FBZixHQUFvQyxDQUF4QyxFQUEyQztBQUM5QzdQLHlCQUFTSCxRQUFRLEdBQWpCO0FBQ0gsYUFGTSxNQUVBO0FBQ0hHLHlCQUFTSCxLQUFUO0FBQ0g7O0FBRUQsbUJBQU9HLE1BQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7O2lEQVNnQ0gsSyxFQUFPN0IsUSxFQUFVO0FBQzdDO0FBQ0EsZ0JBQUkrbUIsZUFBZSxFQUFuQjtBQUNBLGdCQUFJLDRCQUFrQmpKLGdCQUFsQixDQUFtQ2pjLEtBQW5DLENBQUosRUFBK0M7QUFDM0NrbEIsK0JBQWUsR0FBZjs7QUFFQTtBQUNBbGxCLHdCQUFRQSxNQUFNNk0sT0FBTixDQUFjLEdBQWQsRUFBbUIsRUFBbkIsQ0FBUjtBQUNIOztBQUVEO0FBQ0EsZ0JBQUksQ0FBQzdNLE1BQU1tVixLQUFOLENBQVksS0FBWixDQUFMLEVBQXlCO0FBQ3JCblYsOEJBQVlBLEtBQVo7QUFDSDs7QUFFRDtBQUNBLGdCQUFJa00sT0FBT2xNLEtBQVAsTUFBa0IsQ0FBdEIsRUFBeUI7QUFDckJrbEIsK0JBQWUsRUFBZjtBQUNIOztBQUVEO0FBQ0EsZ0JBQUtoWixPQUFPbE0sS0FBUCxJQUFnQixDQUFoQixJQUFxQjdCLFNBQVNvRyxXQUFULEtBQXlCdEgsWUFBWTBDLE9BQVosQ0FBb0I0RSxXQUFwQixDQUFnQ3dLLElBQS9FLElBQ0MvTyxNQUFNdUksTUFBTixHQUFlLENBQWYsSUFBb0JwSyxTQUFTb0csV0FBVCxLQUF5QnRILFlBQVkwQyxPQUFaLENBQW9CNEUsV0FBcEIsQ0FBZ0M4bUIsS0FEbEYsRUFDMEY7QUFDdEZyckIsd0JBQVFBLE1BQU02TSxPQUFOLENBQWMsU0FBZCxFQUF5QixJQUF6QixDQUFSO0FBQ0g7O0FBRUQsbUJBQU8sQ0FBQ3FZLFlBQUQsRUFBZWxsQixLQUFmLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7Ozt1Q0FVc0JrdkIsUyxFQUFXL3dCLFEsRUFBVSttQixZLEVBQWNrSyxHLEVBQUs7QUFDMUQsbUJBQVFGLFlBQVksQ0FBWixJQUFpQi93QixTQUFTa0gsY0FBVCxLQUE0QnBJLFlBQVkwQyxPQUFaLENBQW9CMEYsY0FBcEIsQ0FBbUN3a0IsZUFBakYsSUFBeUk7QUFDM0lxRix3QkFBWSxDQUFaLElBQWlCL3dCLFNBQVNrSCxjQUFULEtBQTRCcEksWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQ3lrQixnQkFBaEYsSUFBb0c1RSxpQkFBaUIsRUFEbkgsSUFDeUk7QUFDM0lnSyx3QkFBWSxDQUFaLElBQWlCL3dCLFNBQVNrSCxjQUFULEtBQTRCcEksWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQ3lrQixnQkFBaEYsSUFBb0c1RSxpQkFBaUIsR0FGbkgsSUFFeUk7QUFDM0lnSyx3QkFBWSxDQUFaLElBQWlCL3dCLFNBQVNrSCxjQUFULEtBQTRCcEksWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQzBrQixpQkFIOUUsSUFHeUk7QUFDM0ltRix3QkFBWSxDQUFaLElBQWlCL3dCLFNBQVNrSCxjQUFULEtBQTRCcEksWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQzJrQixrQkFBaEYsSUFBc0c5RSxpQkFBaUIsRUFKckgsSUFJeUk7QUFDM0lnSyx3QkFBWSxDQUFaLElBQWlCL3dCLFNBQVNrSCxjQUFULEtBQTRCcEksWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQzJrQixrQkFBaEYsSUFBc0c5RSxpQkFBaUIsR0FMckgsSUFLeUk7QUFDM0lnSyx3QkFBWSxDQUFaLElBQWlCL3dCLFNBQVNrSCxjQUFULEtBQTRCcEksWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQzRrQix1QkFOOUUsSUFPRmlGLGNBQWMsQ0FBZCxJQUFtQi93QixTQUFTa0gsY0FBVCxLQUE0QnBJLFlBQVkwQyxPQUFaLENBQW9CMEYsY0FBcEIsQ0FBbUM0a0IsdUJBQWxGLElBQTZHbUYsUUFBUSxDQVBuSCxJQVFGRixZQUFZLENBQVosSUFBaUIvd0IsU0FBU2tILGNBQVQsS0FBNEJwSSxZQUFZMEMsT0FBWixDQUFvQjBGLGNBQXBCLENBQW1DK2tCLCtCQUFoRixJQUFtSGxGLGlCQUFpQixFQVJsSSxJQVNGZ0ssWUFBWSxDQUFaLElBQWlCL3dCLFNBQVNrSCxjQUFULEtBQTRCcEksWUFBWTBDLE9BQVosQ0FBb0IwRixjQUFwQixDQUFtQ2dsQiw2QkFBaEYsSUFBaUhuRixpQkFBaUIsR0FUaEksSUFVRmdLLFlBQVksQ0FBWixJQUFpQi93QixTQUFTa0gsY0FBVCxLQUE0QnBJLFlBQVkwQyxPQUFaLENBQW9CMEYsY0FBcEIsQ0FBbUM2a0IsbUJBVnJGLENBRDBELENBV3NGO0FBQ25KOztBQUVEOzs7Ozs7Ozs7Ozs7K0NBUzhCbHFCLEssRUFBTzdCLFEsRUFBVTJrQixPLEVBQVNvTCxzQixFQUF3QjtBQUM1RSxnQkFBSXBMLE9BQUosRUFBYTtBQUNUOWlCLHdCQUFRLEtBQUsrTSxnQ0FBTCxDQUFzQy9NLEtBQXRDLEVBQTZDN0IsUUFBN0MsQ0FBUjtBQUNIOztBQUgyRSwrQkFLekM2QixNQUFNOFUsS0FBTixDQUFZM1csU0FBU21GLGdCQUFyQixDQUx5QztBQUFBO0FBQUEsZ0JBS3JFd3BCLFdBTHFFO0FBQUEsZ0JBS3hEQyxXQUx3RDs7QUFPNUU7OztBQUNBLGdCQUFJQSxlQUFlQSxZQUFZeGtCLE1BQVosR0FBcUIybEIsc0JBQXhDLEVBQWdFO0FBQzVELG9CQUFJQSx5QkFBeUIsQ0FBN0IsRUFBZ0M7QUFDNUIsd0JBQU1zQixzQkFBc0J6QyxZQUFZM0ssU0FBWixDQUFzQixDQUF0QixFQUF5QjhMLHNCQUF6QixDQUE1QjtBQUNBbHVCLGlDQUFXOHNCLFdBQVgsR0FBeUIzdUIsU0FBU21GLGdCQUFsQyxHQUFxRGtzQixtQkFBckQ7QUFDSCxpQkFIRCxNQUdPO0FBQ0h4dkIsNEJBQVE4c0IsV0FBUjtBQUNIO0FBQ0o7O0FBRUQsbUJBQU85c0IsS0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7MERBU3lDQSxLLEVBQU83QixRLEVBQVU7QUFDdEQ2QixvQkFBUUEsTUFBTWdOLFFBQU4sRUFBUjtBQUNBaE4sb0JBQVFBLE1BQU02TSxPQUFOLENBQWMsR0FBZCxFQUFtQixHQUFuQixDQUFSO0FBQ0EsZ0JBQU11USxXQUFXLDRCQUFrQkMsUUFBbEIsQ0FBMkJsZixTQUFTc0csWUFBcEMsQ0FBakI7QUFDQSxnQkFBTTZZLFdBQVcsNEJBQWtCRCxRQUFsQixDQUEyQmxmLFNBQVNxRyxZQUFwQyxDQUFqQjtBQUNBLGdCQUFNaXJCLFdBQVcsNEJBQWtCcFMsUUFBbEIsQ0FBMkJyZCxLQUEzQixDQUFqQjs7QUFFQSxnQkFBSUcsZUFBSjtBQUNBLG9CQUFRaEMsU0FBUytHLG9CQUFqQjtBQUNJLHFCQUFLakksWUFBWTBDLE9BQVosQ0FBb0J1RixvQkFBcEIsQ0FBeUN3a0IsS0FBOUM7QUFDSXZwQiw2QkFBUyxDQUFDLDRCQUFrQnV2QixVQUFsQixDQUE2QnRTLFFBQTdCLEVBQXVDcVMsUUFBdkMsSUFBbUQsQ0FBQyxDQUFyRCxFQUF3RCxJQUF4RCxDQUFUO0FBQ0E7QUFDSixxQkFBS3h5QixZQUFZMEMsT0FBWixDQUFvQnVGLG9CQUFwQixDQUF5Q3VrQixPQUE5QztBQUNJdHBCLDZCQUFTLENBQUMsSUFBRCxFQUFPLDRCQUFrQnV2QixVQUFsQixDQUE2QnBTLFFBQTdCLEVBQXVDbVMsUUFBdkMsSUFBbUQsQ0FBMUQsQ0FBVDtBQUNBO0FBQ0oscUJBQUt4eUIsWUFBWTBDLE9BQVosQ0FBb0J1RixvQkFBcEIsQ0FBeUM0WSxNQUE5QztBQUNJM2QsNkJBQVMsQ0FBQyxJQUFELEVBQU8sSUFBUCxDQUFUO0FBQ0E7QUFDSjtBQUNJQSw2QkFBUyxDQUFDLDRCQUFrQnV2QixVQUFsQixDQUE2QnRTLFFBQTdCLEVBQXVDcVMsUUFBdkMsSUFBbUQsQ0FBQyxDQUFyRCxFQUF3RCw0QkFBa0JDLFVBQWxCLENBQTZCcFMsUUFBN0IsRUFBdUNtUyxRQUF2QyxJQUFtRCxDQUEzRyxDQUFUO0FBWFI7O0FBY0EsbUJBQU90dkIsTUFBUDtBQUNIOzs7b0NBbUJrQmlXLEksRUFBTTtBQUNyQixnQkFBTXVaLFNBQVN2WixPQUFPLEdBQXRCO0FBQ0EsZ0JBQU13WixLQUFLeG5CLFNBQVNzTyxNQUFULENBQWdCNUIsS0FBaEIsQ0FBc0IsR0FBdEIsQ0FBWDtBQUNBLGdCQUFJdVAsSUFBSSxFQUFSO0FBQ0EsaUJBQUssSUFBSTNhLElBQUksQ0FBYixFQUFnQkEsSUFBSWttQixHQUFHcm5CLE1BQXZCLEVBQStCbUIsS0FBSyxDQUFwQyxFQUF1QztBQUNuQzJhLG9CQUFJdUwsR0FBR2xtQixDQUFILENBQUo7QUFDQSx1QkFBTzJhLEVBQUVuSyxNQUFGLENBQVMsQ0FBVCxNQUFnQixHQUF2QixFQUE0QjtBQUN4Qm1LLHdCQUFJQSxFQUFFakMsU0FBRixDQUFZLENBQVosRUFBZWlDLEVBQUU5YixNQUFqQixDQUFKO0FBQ0g7QUFDRCxvQkFBSThiLEVBQUVyVSxPQUFGLENBQVUyZixNQUFWLE1BQXNCLENBQTFCLEVBQTZCO0FBQ3pCLDJCQUFPdEwsRUFBRWpDLFNBQUYsQ0FBWXVOLE9BQU9wbkIsTUFBbkIsRUFBMkI4YixFQUFFOWIsTUFBN0IsQ0FBUDtBQUNIO0FBQ0o7O0FBRUQsbUJBQU8sSUFBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7dUNBTXNCO0FBQ2xCLGdCQUFNc25CLE1BQU0sV0FBWjtBQUNBLGdCQUFJO0FBQ0FyWiwrQkFBZUMsT0FBZixDQUF1Qm9aLEdBQXZCLEVBQTRCQSxHQUE1QjtBQUNBclosK0JBQWVLLFVBQWYsQ0FBMEJnWixHQUExQjtBQUNBLHVCQUFPLElBQVA7QUFDSCxhQUpELENBSUUsT0FBT3RwQixDQUFQLEVBQVU7QUFDUix1QkFBTyxLQUFQO0FBQ0g7QUFDSjs7O29FQWs1Q2tEcEksUSxFQUFVO0FBQ3pEO0FBQ0E7QUFDQSxnQkFBSSxDQUFDLDRCQUFrQmlJLE1BQWxCLENBQXlCakksU0FBU3lHLDZCQUFsQyxDQUFMLEVBQXVFO0FBQ25FO0FBQ0g7O0FBRUQsZ0JBQUksQ0FBQyw0QkFBa0JpSCxXQUFsQixDQUE4QjFOLFFBQTlCLENBQUQsSUFDQSw0QkFBa0IwTCx3QkFBbEIsQ0FBMkMxTCxTQUFTeUcsNkJBQXBELENBREEsSUFFQSxDQUFDLDRCQUFrQmlGLHdCQUFsQixDQUEyQzFMLFNBQVNpRixjQUFwRCxDQUZMLEVBRTBFO0FBQ3RFLHdCQUFRakYsU0FBU2tGLHVCQUFqQjtBQUNJLHlCQUFLcEcsWUFBWTBDLE9BQVosQ0FBb0IwRCx1QkFBcEIsQ0FBNENvTSxNQUFqRDtBQUNJdFIsaUNBQVN5Ryw2QkFBVCxHQUF5QzNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEK0ssTUFBM0YsQ0FESixDQUN1RztBQUNuRztBQUNKLHlCQUFLMVMsWUFBWTBDLE9BQVosQ0FBb0IwRCx1QkFBcEIsQ0FBNENzTSxNQUFqRDtBQUNJeFIsaUNBQVN5Ryw2QkFBVCxHQUF5QzNILFlBQVkwQyxPQUFaLENBQW9CaUYsNkJBQXBCLENBQWtEOEssSUFBM0YsQ0FESixDQUNxRztBQUNqRztBQUNKO0FBQ0E7QUFSSjtBQVVILGFBYkQsTUFhTztBQUNIO0FBQ0F2Uix5QkFBU3lHLDZCQUFULEdBQXlDM0gsWUFBWTBDLE9BQVosQ0FBb0JpRiw2QkFBcEIsQ0FBa0Q4SyxJQUEzRjtBQUNIO0FBQ0o7O0FBRUQ7Ozs7Ozs7Ozs7Ozs0RUFTMkQvUCxPLEVBQVM7QUFDaEUsZ0JBQUksNEJBQWtCeUcsTUFBbEIsQ0FBeUJ6RyxPQUF6QixDQUFKLEVBQXVDO0FBQ25DLHVCQUFPLElBQVA7QUFDSDs7QUFFRDtBQUNBLGdCQUFJLENBQUMsNEJBQWtCa0ssd0JBQWxCLENBQTJDbEssUUFBUXVELG9CQUFuRCxDQUFELElBQTZFLDRCQUFrQjJHLHdCQUFsQixDQUEyQ2xLLFFBQVE4RixhQUFuRCxDQUFqRixFQUFvSjtBQUNoSjlGLHdCQUFROEYsYUFBUixHQUF3QnhJLFlBQVkwQyxPQUFaLENBQW9COEYsYUFBcEIsQ0FBa0NxcUIsV0FBMUQ7QUFDSDs7QUFFRDtBQUNBLGdCQUFJLDRCQUFrQmptQix3QkFBbEIsQ0FBMkNsSyxRQUFRdUQsb0JBQW5ELEtBQTRFLENBQUMsNEJBQWtCMkcsd0JBQWxCLENBQTJDbEssUUFBUThGLGFBQW5ELENBQTdFLElBQWtKOUYsUUFBUThGLGFBQVIsS0FBMEJ4SSxZQUFZMEMsT0FBWixDQUFvQjhGLGFBQXBCLENBQWtDNlMsTUFBbE4sRUFBME47QUFDdE4zWSx3QkFBUXVELG9CQUFSLEdBQStCakcsWUFBWTBDLE9BQVosQ0FBb0J1RCxvQkFBcEIsQ0FBeUN5bEIsc0JBQXhFO0FBQ0g7O0FBRUQsbUJBQU9ocEIsT0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O3NEQW1CcUN4QixRLEVBQVU7QUFDM0M7QUFDQSxpQkFBS3lyQiw4QkFBTCxDQUFvQ3pyQixRQUFwQzs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7QUFDQSxnQkFBSUEsU0FBUzBGLHlCQUFULEtBQXVDNUcsWUFBWTBDLE9BQVosQ0FBb0JrRSx5QkFBcEIsQ0FBOENrc0IsVUFBekYsRUFBc0c7QUFDbEc1eEIseUJBQVMwRix5QkFBVCxHQUFxQzFGLFNBQVNxRixhQUE5QztBQUNIOztBQUVELGdCQUFJckYsU0FBU3lGLHdCQUFULEtBQXNDM0csWUFBWTBDLE9BQVosQ0FBb0JpRSx3QkFBcEIsQ0FBNkNtc0IsVUFBdkYsRUFBb0c7QUFDaEc1eEIseUJBQVN5Rix3QkFBVCxHQUFvQ3pGLFNBQVNxRixhQUE3QztBQUNIOztBQUVELGdCQUFJckYsU0FBU3dGLHFCQUFULEtBQW1DMUcsWUFBWTBDLE9BQVosQ0FBb0JnRSxxQkFBcEIsQ0FBMENvc0IsVUFBakYsRUFBOEY7QUFDMUY1eEIseUJBQVN3RixxQkFBVCxHQUFpQ3hGLFNBQVNxRixhQUExQztBQUNIOztBQUVEO0FBQ0EsZ0JBQUl3c0Isa0NBQWtDLENBQXRDO0FBQ0EsZ0JBQUk3eEIsU0FBU2dILGVBQVQsSUFBNEJoSCxTQUFTZ0gsZUFBVCxLQUE2QmxJLFlBQVkwQyxPQUFaLENBQW9Cd0YsZUFBcEIsQ0FBb0MySyxJQUFqRyxFQUF1RztBQUNuR2tnQixrREFBa0M5VSxPQUFPL2MsU0FBU2dILGVBQWhCLEVBQWlDb0QsTUFBakMsR0FBMEMsQ0FBNUUsQ0FEbUcsQ0FDcEI7QUFDL0Usb0JBQUl5bkIsa0NBQWtDLENBQXRDLEVBQXlDO0FBQ3JDQSxzREFBa0MsQ0FBbEM7QUFDSDtBQUNKOztBQUVEN3hCLHFCQUFTd0YscUJBQVQsR0FBaUMrYyxLQUFLclcsR0FBTCxDQUM3QnFXLEtBQUtyVyxHQUFMLENBQVNsTSxTQUFTeUYsd0JBQWxCLEVBQTRDekYsU0FBUzBGLHlCQUFyRCxJQUFrRm1zQiwrQkFEckQsRUFFN0I5akIsT0FBTy9OLFNBQVMyaUIsNkJBQWhCLElBQWlEa1AsK0JBRnBCLENBQWpDO0FBSUg7O0FBRUQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O3dEQW9CdUM3eEIsUSxFQUFrQztBQUFBLGdCQUF4Qjh4QixlQUF3Qix1RUFBTixJQUFNOztBQUNyRTtBQUNBLGlCQUFLckcsOEJBQUwsQ0FBb0N6ckIsUUFBcEM7O0FBRUE7QUFDQSxnQkFBSSw0QkFBa0JpSSxNQUFsQixDQUF5QjZwQixlQUF6QixDQUFKLEVBQStDO0FBQzNDLDRDQUFrQi9rQixVQUFsQjtBQUNIOztBQUVELGdCQUFNNlYseUJBQXlCLG1CQUFtQjVpQixRQUFsRDtBQUNBLGdCQUFJLEVBQUU0aUIsMEJBQ0UsMkJBQTJCNWlCLFFBRDdCLElBRUUsK0JBQStCQSxRQUZqQyxJQUdFLDhCQUE4QkEsUUFIaEMsSUFJRSxxQkFBcUJBLFFBSnpCLENBQUosRUFJd0M7QUFDcEM7QUFDQTtBQUNIOztBQUVEO0FBQ0EsZ0JBQUk0aUIsc0JBQUosRUFBNEI7QUFDeEIsb0JBQUksRUFBRSwrQkFBK0I1aUIsUUFBakMsS0FDQUEsU0FBUzBGLHlCQUFULEtBQXVDNUcsWUFBWTBDLE9BQVosQ0FBb0JrRSx5QkFBcEIsQ0FBOENrc0IsVUFEekYsRUFDc0c7QUFDbEc1eEIsNkJBQVMwRix5QkFBVCxHQUFxQzFGLFNBQVNxRixhQUE5QztBQUNIOztBQUVELG9CQUFJLEVBQUUsOEJBQThCckYsUUFBaEMsS0FDQUEsU0FBU3lGLHdCQUFULEtBQXNDM0csWUFBWTBDLE9BQVosQ0FBb0JpRSx3QkFBcEIsQ0FBNkNtc0IsVUFEdkYsRUFDb0c7QUFDaEc1eEIsNkJBQVN5Rix3QkFBVCxHQUFvQ3pGLFNBQVNxRixhQUE3QztBQUNIOztBQUVELG9CQUFJLEVBQUUsMkJBQTJCckYsUUFBN0IsS0FDQUEsU0FBU3dGLHFCQUFULEtBQW1DMUcsWUFBWTBDLE9BQVosQ0FBb0JnRSxxQkFBcEIsQ0FBMENvc0IsVUFEakYsRUFDOEY7QUFDMUY1eEIsNkJBQVN3RixxQkFBVCxHQUFpQ3hGLFNBQVNxRixhQUExQztBQUNIO0FBQ0osYUFmRCxNQWVPO0FBQ0gsb0JBQUksNEJBQWtCcUksV0FBbEIsQ0FBOEIxTixTQUFTMEYseUJBQXZDLENBQUosRUFBdUU7QUFDbkUxRiw2QkFBUzBGLHlCQUFULEdBQXFDb3NCLGdCQUFnQnBzQix5QkFBckQ7QUFDSDs7QUFFRCxvQkFBSSw0QkFBa0JnSSxXQUFsQixDQUE4QjFOLFNBQVN5Rix3QkFBdkMsQ0FBSixFQUFzRTtBQUNsRXpGLDZCQUFTeUYsd0JBQVQsR0FBb0Nxc0IsZ0JBQWdCcnNCLHdCQUFwRDtBQUNIO0FBQ0o7O0FBRUQ7QUFDQSxnQkFBSW9zQixrQ0FBa0MsQ0FBdEM7QUFDQSxnQkFBSTd4QixTQUFTZ0gsZUFBVCxJQUE0QmhILFNBQVNnSCxlQUFULEtBQTZCbEksWUFBWTBDLE9BQVosQ0FBb0J3RixlQUFwQixDQUFvQzJLLElBQWpHLEVBQXVHO0FBQ25Ha2dCLGtEQUFrQzlVLE9BQU8vYyxTQUFTZ0gsZUFBaEIsRUFBaUNvRCxNQUFqQyxHQUEwQyxDQUE1RSxDQURtRyxDQUNwQjtBQUMvRSxvQkFBSXluQixrQ0FBa0MsQ0FBdEMsRUFBeUM7QUFDckNBLHNEQUFrQyxDQUFsQztBQUNIO0FBQ0o7O0FBRUQsZ0JBQUksQ0FBQzd4QixTQUFTcUYsYUFBVixJQUEyQixDQUFDckYsU0FBU3dGLHFCQUF6QyxFQUFnRTtBQUM1RHhGLHlCQUFTd0YscUJBQVQsR0FBaUMrYyxLQUFLclcsR0FBTCxDQUM3QnFXLEtBQUtyVyxHQUFMLENBQVNsTSxTQUFTeUYsd0JBQWxCLEVBQTRDekYsU0FBUzBGLHlCQUFyRCxJQUFrRm1zQiwrQkFEckQsRUFFN0I5akIsT0FBTytqQixnQkFBZ0JuUCw2QkFBdkIsSUFBd0RrUCwrQkFGM0IsQ0FBakM7QUFJSCxhQUxELE1BS087QUFDSDd4Qix5QkFBU3dGLHFCQUFULEdBQWlDK2MsS0FBS3JXLEdBQUwsQ0FDN0JxVyxLQUFLclcsR0FBTCxDQUFTbE0sU0FBU3lGLHdCQUFsQixFQUE0Q3pGLFNBQVMwRix5QkFBckQsSUFBa0Ztc0IsK0JBRHJELEVBRTdCOWpCLE9BQU8vTixTQUFTd0YscUJBQWhCLElBQXlDcXNCLCtCQUZaLENBQWpDO0FBSUg7QUFDSjs7O3VEQWlDcUM3eEIsUSxFQUFVMGpCLEssRUFBTztBQUNuRCxnQkFBTXFPLGdCQUFnQixPQUF0QjtBQUNBLGdCQUFNQyxrQkFBa0IsUUFBeEI7O0FBRUE7QUFDQSxnQkFBTUMsVUFBVWp5QixTQUFTK1cscUJBQVQsYUFBdUMvVyxTQUFTK1cscUJBQWhELFdBQTJFLE1BQTNGO0FBQ0EyTSxrQkFBTWdCLGdCQUFOLEdBQXlCdU4sT0FBekI7O0FBRUEsZ0JBQUlDLDRCQUFKO0FBQ0EsZ0JBQUlseUIsU0FBUytXLHFCQUFiLEVBQW9DO0FBQ2hDbWIsNkNBQTJCbHlCLFNBQVMrVyxxQkFBcEM7QUFDSCxhQUZELE1BRU87QUFDSG1iLHNDQUFzQixFQUF0QjtBQUNIOztBQUVEbHlCLHFCQUFTdXVCLGtCQUFULEdBQThCLElBQUk5SixNQUFKLENBQWN3TixPQUFkLFdBQTJCQyxtQkFBM0IsVUFBbURseUIsU0FBU21GLGdCQUE1RCxHQUErRTRzQixhQUEvRSxhQUFvR0EsYUFBcEcsV0FBdUgveEIsU0FBU21GLGdCQUFoSSxHQUFtSjRzQixhQUFuSixPQUE5QjtBQUNBL3hCLHFCQUFTd3VCLGlCQUFULEdBQTZCLElBQUkvSixNQUFKLE9BQWVzTixhQUFmLFVBQWlDL3hCLFNBQVNtRixnQkFBMUMsY0FBbUVuRixTQUFTbUYsZ0JBQTVFLEdBQStGNHNCLGFBQS9GLFNBQWdIQyxlQUFoSCxRQUE3Qjs7QUFFQSxnQkFBTUcsNEJBQTBCbnlCLFNBQVNtRixnQkFBekM7QUFDQW5GLHFCQUFTeXVCLGdCQUFULEdBQTRCLElBQUloSyxNQUFKLFFBQWdCME4sT0FBaEIsUUFBNEIsR0FBNUIsQ0FBNUI7QUFDQW55QixxQkFBUzB1QixlQUFULEdBQTJCLElBQUlqSyxNQUFKLENBQWN3TixPQUFkLGFBQTZCanlCLFNBQVNtRixnQkFBdEMsVUFBMkQ0c0IsYUFBM0QsV0FBOEUveEIsU0FBU21GLGdCQUF2RixHQUEwRzRzQixhQUExRyxZQUE4SEEsYUFBOUgsY0FBb0oveEIsU0FBU21GLGdCQUE3SixHQUFnTDRzQixhQUFoTCxXQUEzQjs7QUFFQTtBQUNBL3hCLHFCQUFTOHVCLFFBQVQsR0FBb0IsSUFBSXJLLE1BQUosT0FBZWYsTUFBTWdCLGdCQUFyQixXQUEyQ3FOLGFBQTNDLE9BQXBCO0FBQ0g7OztvREE2QmtDdndCLE8sRUFBUztBQUN4QztBQUNBLGdCQUFNNHdCLHNCQUFzQjtBQUN4QjtBQUNBQyxzQkFBb0MscUJBRlo7QUFHeEJDLHNCQUFvQyx3QkFIWjtBQUl4QkMsd0JBQW9DLHFCQUpaO0FBS3hCQyxzQkFBb0Msa0JBTFo7QUFNeEJDLHdCQUFvQyw2QkFOWjtBQU94QkMsdUJBQW9DLGdCQVBaO0FBUXhCQyx1QkFBb0MseUJBUlo7QUFTeEJDLHNCQUFvQywrQkFUWjtBQVV4QkMseUJBQW9DLFlBVlo7QUFXeEJDLHlCQUFvQyxzQkFYWjtBQVl4QkMsc0JBQW9DLGNBWlo7QUFheEJDLHNCQUFvQyxjQWJaO0FBY3hCQyxzQkFBb0MsdUJBZFo7QUFleEJDLHNCQUFvQywyQkFmWjtBQWdCeEJDLDhCQUFvQywwQkFoQlo7QUFpQnhCQyx1QkFBb0MsMkJBakJaO0FBa0J4QkMsd0JBQW9DLGdCQWxCWjtBQW1CeEJDLHNCQUFvQyxxQkFuQlo7QUFvQnhCQywwQkFBb0MsNEJBcEJaO0FBcUJ4QkMsd0JBQW9DLG9CQXJCWjtBQXNCeEJDLHVCQUFvQyxhQXRCWjtBQXVCeEJDLHVCQUFvQyxrQkF2Qlo7QUF3QnhCQyx5QkFBb0Msa0JBeEJaO0FBeUJ4QkMsMkJBQW9DLHNCQXpCWjtBQTBCeEJDLCtCQUFvQyxrQkExQlo7QUEyQnhCQyw0QkFBb0MsY0EzQlo7QUE0QnhCQyx1QkFBb0MsY0E1Qlo7O0FBOEJ4QjtBQUNBanZCLHFDQUFvQyxJQS9CWjtBQWdDeEJDLHNDQUFvQyxJQWhDWjtBQWlDeEI3RCxpQ0FBb0MsSUFqQ1o7QUFrQ3hCK0QsZ0NBQW9DLElBbENaO0FBbUN4QkMseUNBQW9DLElBbkNaO0FBb0N4QkMsa0NBQW9DLElBcENaO0FBcUN4QkMsNkNBQW9DLElBckNaO0FBc0N4QkMsK0JBQW9DLElBdENaO0FBdUN4QkcsdUNBQW9DLElBdkNaO0FBd0N4QkMsMENBQW9DLElBeENaO0FBeUN4QkMsMkNBQW9DLElBekNaO0FBMEN4QkMsc0NBQW9DLElBMUNaO0FBMkN4QkMscUNBQW9DLElBM0NaO0FBNEN4QkMscUNBQW9DLElBNUNaO0FBNkN4QkMsc0NBQW9DLElBN0NaO0FBOEN4QkMsb0NBQW9DLElBOUNaO0FBK0N4QkUscUNBQW9DLElBL0NaO0FBZ0R4QmhHLGtDQUFvQyxJQWhEWjtBQWlEeEJpRyw2QkFBb0MsSUFqRFo7QUFrRHhCQywrQkFBb0MsSUFsRFo7QUFtRHhCQyw2QkFBb0MsSUFuRFo7QUFvRHhCQyw4QkFBb0MsSUFwRFo7QUFxRHhCQyw4QkFBb0MsSUFyRFo7QUFzRHhCQyxvQ0FBb0MsSUF0RFo7QUF1RHhCQyw0Q0FBb0MsSUF2RFo7QUF3RHhCQywrQ0FBb0MsSUF4RFo7QUF5RHhCcEcsa0NBQW9DLElBekRaO0FBMER4QndHLGdDQUFvQyxJQTFEWjtBQTJEeEJDLDhCQUFvQyxJQTNEWjtBQTREeEJDLHNDQUFvQyxJQTVEWjtBQTZEeEJDLGlDQUFvQyxJQTdEWjtBQThEeEJDLDBCQUFvQyxJQTlEWjtBQStEeEJDLGdDQUFvQyxJQS9EWjtBQWdFeEJDLDJDQUFvQyxJQWhFWjtBQWlFeEJFLGtDQUFvQyxJQWpFWjtBQWtFeEJDLCtCQUFvQyxJQWxFWjtBQW1FeEJDLGlDQUFvQyxJQW5FWjtBQW9FeEJDLHdDQUFvQyxJQXBFWjtBQXFFeEJDLGtDQUFvQyxJQXJFWjtBQXNFeEJsQyw4QkFBb0MsSUF0RVo7QUF1RXhCbUMsNEJBQW9DLElBdkVaO0FBd0V4QkMsNEJBQW9DLElBeEVaO0FBeUV4QlAscUNBQW9DLElBekVaO0FBMEV4QlEsaUNBQW9DLElBMUVaO0FBMkV4QkMsa0NBQW9DLElBM0VaO0FBNEV4QkMsMkJBQW9DLElBNUVaOztBQThFeEI7QUFDQTtBQUNBMm1CLGtDQUFvQyxJQWhGWjtBQWlGeEJqTSx5QkFBb0MsSUFqRlo7QUFrRnhCRix5QkFBb0MsSUFsRlo7QUFtRnhCdkwsdUNBQW9DLElBbkZaO0FBb0Z4QjJYLGlDQUFvQyxJQXBGWjtBQXFGeEI3TCx1Q0FBb0MsSUFyRlo7QUFzRnhCRiwrQ0FBb0MsSUF0Rlo7QUF1RnhCaEwsdUNBQW9DLElBdkZaO0FBd0Z4QjRXLG9DQUFvQyxJQXhGWjtBQXlGeEJDLG1DQUFvQyxJQXpGWjtBQTBGeEJNLDBCQUFvQztBQTFGWixhQUE1Qjs7QUE2RkEsaUJBQUssSUFBTWtGLE1BQVgsSUFBcUJ4eUIsT0FBckIsRUFBOEI7QUFDMUIsb0JBQUlBLFFBQVErVSxjQUFSLENBQXVCeWQsTUFBdkIsQ0FBSixFQUFvQztBQUNoQyx3QkFBSTVCLG9CQUFvQjRCLE1BQXBCLE1BQWdDLElBQXBDLEVBQTBDO0FBQ3RDO0FBQ0E7QUFDSDs7QUFFRCx3QkFBSTVCLG9CQUFvQjdiLGNBQXBCLENBQW1DeWQsTUFBbkMsQ0FBSixFQUFnRDtBQUM1QztBQUNBLG9EQUFrQjF1QixPQUFsQixpREFBdUUwdUIsTUFBdkUseUJBQStGNUIsb0JBQW9CNEIsTUFBcEIsQ0FBL0YsbUZBQW9NLElBQXBNOztBQUVBO0FBQ0F4eUIsZ0NBQVE0d0Isb0JBQW9CNEIsTUFBcEIsQ0FBUixJQUF1Q3h5QixRQUFRd3lCLE1BQVIsQ0FBdkM7QUFDQSwrQkFBT3h5QixRQUFRd3lCLE1BQVIsQ0FBUDtBQUNILHFCQVBELE1BT08sSUFBSXh5QixRQUFReUUsbUJBQVosRUFBaUM7QUFDcEM7QUFDQSxvREFBa0I4RyxVQUFsQixvQkFBNkNpbkIsTUFBN0M7QUFDSDtBQUNKO0FBQ0o7O0FBRUQsZ0JBQUksVUFBVXh5QixPQUFkLEVBQXVCO0FBQ25CLDRDQUFrQjhELE9BQWxCLENBQTBCLHFMQUExQixFQUFpTixJQUFqTjtBQUNIO0FBQ0o7Ozt3Q0FpSHNCekQsSyxFQUFPN0IsUSxFQUFVO0FBQ3BDO0FBQ0EsZ0JBQUlnQyxlQUFKO0FBQ0EsZ0JBQUksNEJBQWtCMk4sUUFBbEIsQ0FBMkI1QixPQUFPbE0sS0FBUCxDQUEzQixDQUFKLEVBQStDO0FBQzNDO0FBQ0FHLHlCQUFTSCxLQUFUO0FBQ0gsYUFIRCxNQUdPO0FBQ0g7QUFDQTtBQUNBRyx5QkFBUyxLQUFLa3NCLHVCQUFMLENBQTZCcnNCLE1BQU1nTixRQUFOLEVBQTdCLEVBQStDN08sUUFBL0MsQ0FBVDs7QUFFQTtBQUNBLG9CQUFJLENBQUMsNEJBQWtCMlAsUUFBbEIsQ0FBMkI1QixPQUFPL0wsTUFBUCxDQUEzQixDQUFMLEVBQWlEO0FBQzdDLGdEQUFrQnNELE9BQWxCLGlCQUF3Q3pELEtBQXhDLGlGQUF5SDdCLFNBQVN1RixZQUFsSTtBQUNBdkQsNkJBQVNvc0IsR0FBVDtBQUNIO0FBQ0o7O0FBRUQsbUJBQU9wc0IsTUFBUDtBQUNIOzs7d0NBb0JzQkgsSyxFQUFPb3lCLGMsRUFBZ0JDLGMsRUFBZ0I7QUFDMUQsZ0JBQU1DLGNBQWMsNEJBQWtCalYsUUFBbEIsQ0FBMkJyZCxLQUEzQixDQUFwQjtBQUNBLG1CQUFPLDRCQUFrQjB2QixVQUFsQixDQUE2QjBDLGNBQTdCLEVBQTZDRSxXQUE3QyxJQUE0RCxDQUFDLENBQTdELElBQWtFLDRCQUFrQjVDLFVBQWxCLENBQTZCMkMsY0FBN0IsRUFBNkNDLFdBQTdDLElBQTRELENBQXJJO0FBQ0g7Ozs0Q0FvVTBCQyxZLEVBQWM7QUFDckMsZ0JBQU1DLFdBQVcsNEJBQWtCeG5CLFNBQWxCLENBQTRCdW5CLFlBQTVCLEVBQTBDLDBCQUFnQjFaLE9BQWhCLENBQXdCNFosVUFBbEUsQ0FBakI7QUFDQSxnQkFBTUMsV0FBV0gsaUJBQWlCLDBCQUFnQjFaLE9BQWhCLENBQXdCOFosTUFBekMsSUFBbURKLGlCQUFpQiwwQkFBZ0IxWixPQUFoQixDQUF3QitaLE9BQTdHO0FBQ0EsZ0JBQU1DLGdCQUFnQk4saUJBQWlCLDBCQUFnQjFaLE9BQWhCLENBQXdCaWEsV0FBL0Q7QUFDQSxnQkFBTUMseUJBQXlCLDRCQUFrQi9uQixTQUFsQixDQUE0QnVuQixZQUE1QixFQUEwQywwQkFBZ0IxWixPQUFoQixDQUF3Qm1hLHFCQUFsRSxDQUEvQjtBQUNBLGdCQUFNQywwQkFBMEJWLGlCQUFpQiwwQkFBZ0IxWixPQUFoQixDQUF3QnFhLE9BQXpDLElBQzVCWCxpQkFBaUIsMEJBQWdCMVosT0FBaEIsQ0FBd0JzYSxVQURiLElBRTVCWixpQkFBaUIsMEJBQWdCMVosT0FBaEIsQ0FBd0JjLE1BRmIsSUFHNUI0WSxpQkFBaUIsMEJBQWdCMVosT0FBaEIsQ0FBd0J1YSxPQUg3QztBQUlBLGdCQUFNQyx1QkFBdUJkLGlCQUFpQiwwQkFBZ0IxWixPQUFoQixDQUF3QnlhLFlBQXRFOztBQUVBLG1CQUFPZCxZQUFZRSxRQUFaLElBQXdCRyxhQUF4QixJQUF5Q0Usc0JBQXpDLElBQW1FTSxvQkFBbkUsSUFBMkZKLHVCQUFsRztBQUNIOzs7bUNBeWJpQi9nQixJLEVBQWtIO0FBQUEsZ0JBQTVHcWhCLFdBQTRHLHVFQUE5RixLQUE4RjtBQUFBLGdCQUF2RkMsVUFBdUYsdUVBQTFFLGFBQTBFOztBQUFBOztBQUFBLGdCQUEzREMsd0JBQTJELHVFQUFoQyxHQUFnQztBQUFBLGdCQUEzQjV5QixrQkFBMkIsdUVBQU4sSUFBTTs7QUFDaEksZ0JBQU1WLFNBQVMsRUFBZjs7QUFFQSxnQkFBSSxRQUFPK1IsSUFBUCx5Q0FBT0EsSUFBUCxPQUFnQixRQUFoQixJQUE0QkEsS0FBS3doQixRQUFMLENBQWMxaEIsV0FBZCxPQUFnQyxNQUFoRSxFQUF3RTtBQUNwRStULHNCQUFNeUIsU0FBTixDQUFnQnRMLEtBQWhCLENBQXNCdUwsSUFBdEIsQ0FBMkJ2VixLQUFLdFAsUUFBaEMsRUFBMEMvQyxPQUExQyxDQUFrRCxtQkFBVztBQUN6RCx3QkFBSTh6QixRQUFRdmQsSUFBUixJQUNBLENBQUN1ZCxRQUFRQyxRQURULElBRUEsQ0FBQyxNQUFELEVBQVMsT0FBVCxFQUFrQixRQUFsQixFQUE0QixRQUE1QixFQUFzQzVqQixPQUF0QyxDQUE4QzJqQixRQUFRdGMsSUFBdEQsTUFBZ0UsQ0FBQyxDQUZyRSxFQUV3RTtBQUNwRSw0QkFBSXNjLFFBQVF0YyxJQUFSLEtBQWlCLGlCQUFyQixFQUF3QztBQUNwQzBPLGtDQUFNeUIsU0FBTixDQUFnQnRMLEtBQWhCLENBQXNCdUwsSUFBdEIsQ0FBMkJrTSxRQUFRaDBCLE9BQW5DLEVBQTRDRSxPQUE1QyxDQUFvRCxrQkFBVTtBQUMxRCxvQ0FBSXN5QixPQUFPMEIsUUFBWCxFQUFxQjtBQUNqQjtBQUNBLHdDQUFJTixXQUFKLEVBQWlCO0FBQ2JwekIsK0NBQU9DLElBQVAsQ0FBWSxFQUFFZ1csTUFBTXVkLFFBQVF2ZCxJQUFoQixFQUFzQnBXLE9BQU9teUIsT0FBT255QixLQUFwQyxFQUFaO0FBQ0gscUNBRkQsTUFFTztBQUFFO0FBQ0xHLCtDQUFPQyxJQUFQLENBQWUwekIsbUJBQW1CSCxRQUFRdmQsSUFBM0IsQ0FBZixTQUFtRDBkLG1CQUFtQjNCLE9BQU9ueUIsS0FBMUIsQ0FBbkQ7QUFDSDtBQUNKO0FBQ0osNkJBVEQ7QUFVSCx5QkFYRCxNQVdPLElBQUksQ0FBQyxVQUFELEVBQWEsT0FBYixFQUFzQmdRLE9BQXRCLENBQThCMmpCLFFBQVF0YyxJQUF0QyxNQUFnRCxDQUFDLENBQWpELElBQXNEc2MsUUFBUUksT0FBbEUsRUFBMkU7QUFDOUUsZ0NBQUlDLG9CQUFKO0FBQ0EsZ0NBQUksT0FBS3ZVLHNCQUFMLENBQTRCa1UsT0FBNUIsQ0FBSixFQUEwQztBQUN0QyxvQ0FBSU0saUJBQUo7QUFDQSx3Q0FBUVQsVUFBUjtBQUNJLHlDQUFLLGFBQUw7QUFDSVMsbURBQVcsT0FBS3J5QixxQkFBTCxDQUEyQit4QixPQUEzQixDQUFYO0FBQ0EsNENBQUksQ0FBQyw0QkFBa0J2dEIsTUFBbEIsQ0FBeUI2dEIsUUFBekIsQ0FBTCxFQUF5QztBQUNyQ0QsMERBQWMsT0FBS3J6QixRQUFMLENBQWNnekIsT0FBZCxFQUF1Qk0sU0FBUy9MLFdBQVQsRUFBdkIsQ0FBZDtBQUNIO0FBQ0Q7QUFDSix5Q0FBSyxXQUFMO0FBQ0krTCxtREFBVyxPQUFLcnlCLHFCQUFMLENBQTJCK3hCLE9BQTNCLENBQVg7QUFDQSw0Q0FBSSxDQUFDLDRCQUFrQnZ0QixNQUFsQixDQUF5QjZ0QixRQUF6QixDQUFMLEVBQXlDO0FBQ3JDO0FBQ0EsZ0RBQU1oRSxrQkFBa0IsNEJBQWtCMWtCLFdBQWxCLENBQThCMG9CLFNBQVMvTCxXQUFULEVBQTlCLENBQXhCO0FBQ0EsZ0RBQUksQ0FBQyw0QkFBa0I5aEIsTUFBbEIsQ0FBeUJ2RixrQkFBekIsQ0FBTCxFQUFtRDtBQUMvQ292QixnRUFBZ0JockIsWUFBaEIsR0FBK0JwRSxrQkFBL0I7QUFDSDs7QUFFRG16QiwwREFBYyxPQUFLdkgsUUFBTCxDQUFja0gsT0FBZCxFQUF1QjFELGVBQXZCLENBQWQ7QUFDSDtBQUNEO0FBQ0oseUNBQUssV0FBTDtBQUNBO0FBQ0krRCxzREFBY0wsUUFBUTN6QixLQUF0QjtBQXJCUjtBQXVCSCw2QkF6QkQsTUF5Qk87QUFDSGcwQiw4Q0FBY0wsUUFBUTN6QixLQUF0QjtBQUNIOztBQUVELGdDQUFJLDRCQUFrQjZMLFdBQWxCLENBQThCbW9CLFdBQTlCLENBQUosRUFBZ0Q7QUFDNUMsNERBQWtCOW9CLFVBQWxCLENBQTZCLDZFQUE3QjtBQUNIOztBQUVELGdDQUFJcW9CLFdBQUosRUFBaUI7QUFDYnB6Qix1Q0FBT0MsSUFBUCxDQUFZLEVBQUVnVyxNQUFNdWQsUUFBUXZkLElBQWhCLEVBQXNCcFcsT0FBT2cwQixXQUE3QixFQUFaO0FBQ0gsNkJBRkQsTUFFTztBQUFFO0FBQ0w3ekIsdUNBQU9DLElBQVAsQ0FBZTB6QixtQkFBbUJILFFBQVF2ZCxJQUEzQixDQUFmLFNBQW1EMGQsbUJBQW1CRSxXQUFuQixDQUFuRDtBQUNIO0FBQ0o7QUFDSjtBQUNKLGlCQXpERDtBQTBESDs7QUFFRCxnQkFBSUUsb0JBQUo7O0FBRUEsZ0JBQUlYLFdBQUosRUFBaUI7QUFDYjtBQUNBO0FBQ0FXLDhCQUFjL3pCLE1BQWQ7QUFDSCxhQUpELE1BSU87QUFDSDtBQUNBK3pCLDhCQUFjL3pCLE9BQU82akIsSUFBUCxDQUFZLEdBQVosQ0FBZDs7QUFFQSxvQkFBSSxRQUFReVAsd0JBQVosRUFBc0M7QUFDbENTLGtDQUFjQSxZQUFZcm5CLE9BQVosQ0FBb0IsTUFBcEIsRUFBNEIsR0FBNUIsQ0FBZDtBQUNIO0FBQ0o7O0FBRUQsbUJBQU9xbkIsV0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7O2dEQU8rQmhpQixJLEVBQXNDO0FBQUEsZ0JBQWhDdWhCLHdCQUFnQyx1RUFBTCxHQUFLOztBQUNqRSxtQkFBTyxLQUFLVSxVQUFMLENBQWdCamlCLElBQWhCLEVBQXNCLEtBQXRCLEVBQTZCLGFBQTdCLEVBQTRDdWhCLHdCQUE1QyxDQUFQO0FBQ0g7O0FBRUQ7Ozs7Ozs7Ozs7NENBTzJCdmhCLEksRUFBc0M7QUFBQSxnQkFBaEN1aEIsd0JBQWdDLHVFQUFMLEdBQUs7O0FBQzdELG1CQUFPLEtBQUtVLFVBQUwsQ0FBZ0JqaUIsSUFBaEIsRUFBc0IsS0FBdEIsRUFBNkIsV0FBN0IsRUFBMEN1aEIsd0JBQTFDLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs7NENBUTJCdmhCLEksRUFBaUU7QUFBQSxnQkFBM0R1aEIsd0JBQTJELHVFQUFoQyxHQUFnQztBQUFBLGdCQUEzQjV5QixrQkFBMkIsdUVBQU4sSUFBTTs7QUFDeEYsbUJBQU8sS0FBS3N6QixVQUFMLENBQWdCamlCLElBQWhCLEVBQXNCLEtBQXRCLEVBQTZCLFdBQTdCLEVBQTBDdWhCLHdCQUExQyxFQUFvRTV5QixrQkFBcEUsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7O3FEQU9vQ3FSLEksRUFBc0M7QUFBQSxnQkFBaEN1aEIsd0JBQWdDLHVFQUFMLEdBQUs7O0FBQ3RFLG1CQUFPLEtBQUtVLFVBQUwsQ0FBZ0JqaUIsSUFBaEIsRUFBc0IsSUFBdEIsRUFBNEIsYUFBNUIsRUFBMkN1aEIsd0JBQTNDLENBQVA7QUFDSDs7QUFFRDs7Ozs7Ozs7OztpREFPZ0N2aEIsSSxFQUFzQztBQUFBLGdCQUFoQ3VoQix3QkFBZ0MsdUVBQUwsR0FBSzs7QUFDbEUsbUJBQU8sS0FBS1UsVUFBTCxDQUFnQmppQixJQUFoQixFQUFzQixJQUF0QixFQUE0QixXQUE1QixFQUF5Q3VoQix3QkFBekMsQ0FBUDtBQUNIOztBQUVEOzs7Ozs7Ozs7OztpREFRZ0N2aEIsSSxFQUFpRTtBQUFBLGdCQUEzRHVoQix3QkFBMkQsdUVBQWhDLEdBQWdDO0FBQUEsZ0JBQTNCNXlCLGtCQUEyQix1RUFBTixJQUFNOztBQUM3RixtQkFBTyxLQUFLc3pCLFVBQUwsQ0FBZ0JqaUIsSUFBaEIsRUFBc0IsSUFBdEIsRUFBNEIsV0FBNUIsRUFBeUN1aEIsd0JBQXpDLEVBQW1FNXlCLGtCQUFuRSxDQUFQO0FBQ0g7Ozs7OztBQUdMOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBMEJBNUQsWUFBWW0zQixRQUFaLEdBQXVCLFVBQUNsM0IsSUFBRCxFQUErQztBQUFBLFFBQXhDSyxZQUF3Qyx1RUFBekIsSUFBeUI7QUFBQSxRQUFuQm9DLE9BQW1CLHVFQUFULElBQVM7O0FBQ2xFLFFBQU1RLFNBQVMsRUFBZjs7QUFFQTtBQUNBLFFBQUksNEJBQWtCMGxCLFFBQWxCLENBQTJCdG9CLFlBQTNCLENBQUosRUFBOEM7QUFDMUM7QUFDQW9DLGtCQUFVcEMsWUFBVjtBQUNBQSx1QkFBZSxJQUFmO0FBQ0g7O0FBRUQsUUFBSSw0QkFBa0JtTixRQUFsQixDQUEyQnhOLElBQTNCLENBQUosRUFBc0M7QUFDbENBLDRDQUFZa0wsU0FBU2lKLGdCQUFULENBQTBCblUsSUFBMUIsQ0FBWixHQURrQyxDQUNZO0FBQ2pELEtBRkQsTUFFTyxJQUFJLDRCQUFrQjJvQixRQUFsQixDQUEyQjNvQixJQUEzQixDQUFKLEVBQXNDO0FBQ3pDLFlBQUksQ0FBQ0EsS0FBS3dYLGNBQUwsQ0FBb0IsYUFBcEIsQ0FBTCxFQUF5QztBQUNyQyx3Q0FBa0J4SixVQUFsQjtBQUNIOztBQUVEO0FBQ0EsWUFBTXRJLHdDQUFnQjFGLEtBQUttM0IsV0FBTCxDQUFpQmhqQixnQkFBakIsQ0FBa0MsT0FBbEMsQ0FBaEIsRUFBTjtBQUNBLFlBQUluVSxLQUFLd1gsY0FBTCxDQUFvQixTQUFwQixDQUFKLEVBQW9DO0FBQ2hDLGdCQUFJLENBQUNxUixNQUFNbmIsT0FBTixDQUFjMU4sS0FBS28zQixPQUFuQixDQUFMLEVBQWtDO0FBQzlCLDRDQUFrQnBwQixVQUFsQjtBQUNIOztBQUVEO0FBQ0FoTyxtQkFBTyw0QkFBa0JxM0IsU0FBbEIsQ0FBNEIzeEIsUUFBNUIsRUFBc0MxRixLQUFLbzNCLE9BQTNDLENBQVA7QUFDSCxTQVBELE1BT087QUFDSHAzQixtQkFBTzBGLFFBQVA7QUFDSDtBQUNKLEtBakJNLE1BaUJBLElBQUksQ0FBQyw0QkFBa0JnSSxPQUFsQixDQUEwQjFOLElBQTFCLENBQUwsRUFBc0M7QUFDekMsb0NBQWtCZ08sVUFBbEI7QUFDSDs7QUFFRCxRQUFJaE8sS0FBS3FMLE1BQUwsS0FBZ0IsQ0FBcEIsRUFBdUI7QUFDbkIsWUFBSTdFLGVBQWUsSUFBbkI7QUFDQSxZQUFJLENBQUMsNEJBQWtCMEMsTUFBbEIsQ0FBeUJ6RyxPQUF6QixDQUFELElBQXNDLDRCQUFrQjZPLFNBQWxCLENBQTRCN08sUUFBUStELFlBQXBDLENBQTFDLEVBQTZGO0FBQ3pGQSwyQkFBZS9ELFFBQVErRCxZQUF2QjtBQUNIOztBQUVELG9DQUFrQkQsT0FBbEIsb0ZBQTZHQyxZQUE3Rzs7QUFFQSxlQUFPLEVBQVA7QUFDSDs7QUFFRDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFFBQU04d0Isc0JBQXNCLDRCQUFrQjVwQixPQUFsQixDQUEwQnJOLFlBQTFCLENBQTVCO0FBQ0EsUUFBTWszQixpQ0FBaUNELHVCQUF1QmozQixhQUFhZ0wsTUFBYixJQUF1QixDQUFyRjtBQUNBLFFBQUltc0Isb0NBQW9DLEtBQXhDO0FBQ0EsUUFBSUMsOEJBQThCLEtBQWxDO0FBQ0E7QUFDQSxRQUFJRiw4QkFBSixFQUFvQztBQUNoQyxZQUFNRyxrQ0FBaUMxb0IsT0FBTzNPLGFBQWEsQ0FBYixDQUFQLENBQWpDLENBQU47QUFDQTtBQUNBbTNCLDRDQUFvQ0UsNEJBQTRCLFFBQTVCLElBQXdDLENBQUMzb0IsTUFBTUMsT0FBTzNPLGFBQWEsQ0FBYixDQUFQLENBQU4sQ0FBN0U7O0FBRUEsWUFBSSxDQUFDbTNCLGlDQUFMLEVBQXdDO0FBQ3BDO0FBQ0EsZ0JBQUlFLDRCQUE0QixRQUE1QixJQUF3QzNvQixNQUFNMm9CLHVCQUFOLENBQXhDLElBQTBFQSw0QkFBNEIsUUFBMUcsRUFBb0g7QUFDaEhELDhDQUE4QixJQUE5QjtBQUNIO0FBQ0o7QUFDSjs7QUFFRDtBQUNBLFFBQU1FLDRCQUE0Qiw0QkFBa0JqcUIsT0FBbEIsQ0FBMEJqTCxPQUExQixLQUFzQ0EsUUFBUTRJLE1BQVIsSUFBa0IsQ0FBMUY7QUFDQSxRQUFJdXNCLDZCQUE2QixLQUFqQztBQUNBLFFBQUlELHlCQUFKLEVBQStCO0FBQzNCLFlBQU1ELG1DQUFpQ2oxQixRQUFRLENBQVIsQ0FBakMsQ0FBTjtBQUNBLFlBQUlpMUIsNkJBQTRCLFFBQTVCLElBQXdDQSw2QkFBNEIsUUFBeEUsRUFBa0Y7QUFDOUU7QUFDQUUseUNBQTZCLElBQTdCO0FBQ0g7QUFDSjs7QUFFRDtBQUNBLFFBQUlycEIscUJBQUo7QUFDQSxRQUFJa3BCLDJCQUFKLEVBQWlDO0FBQzdCbHBCLHVCQUFleE8sWUFBWTBwQixZQUFaLENBQXlCcHBCLFlBQXpCLENBQWY7QUFDSCxLQUZELE1BRU8sSUFBSXUzQiwwQkFBSixFQUFnQztBQUNuQ3JwQix1QkFBZXhPLFlBQVkwcEIsWUFBWixDQUF5QmhuQixPQUF6QixDQUFmO0FBQ0gsS0FGTSxNQUVBO0FBQ0g4TCx1QkFBZTlMLE9BQWY7QUFDSDs7QUFHRDtBQUNBLFFBQU1vMUIsdUJBQXVCLDRCQUFrQmpuQixRQUFsQixDQUEyQnZRLFlBQTNCLENBQTdCO0FBQ0EsUUFBSXkzQiw4QkFBSjtBQUNBLFFBQUlOLGlDQUFKLEVBQXVDO0FBQ25DTSxnQ0FBd0J6M0IsYUFBYWdMLE1BQXJDO0FBQ0g7O0FBRUQ7QUFDQXJMLFNBQUsyQyxPQUFMLENBQWEsVUFBQ3ZDLFVBQUQsRUFBYXlOLEtBQWIsRUFBdUI7QUFDaEMsWUFBSWdxQixvQkFBSixFQUEwQjtBQUN0QjtBQUNBNTBCLG1CQUFPQyxJQUFQLENBQVksSUFBSW5ELFdBQUosQ0FBZ0JLLFVBQWhCLEVBQTRCQyxZQUE1QixFQUEwQ2tPLFlBQTFDLENBQVo7QUFDSCxTQUhELE1BR08sSUFBSWlwQixxQ0FBcUMzcEIsU0FBU2lxQixxQkFBbEQsRUFBeUU7QUFDNUU3MEIsbUJBQU9DLElBQVAsQ0FBWSxJQUFJbkQsV0FBSixDQUFnQkssVUFBaEIsRUFBNEJDLGFBQWF3TixLQUFiLENBQTVCLEVBQWlEVSxZQUFqRCxDQUFaO0FBQ0gsU0FGTSxNQUVBO0FBQ0h0TCxtQkFBT0MsSUFBUCxDQUFZLElBQUluRCxXQUFKLENBQWdCSyxVQUFoQixFQUE0QixJQUE1QixFQUFrQ21PLFlBQWxDLENBQVo7QUFDSDtBQUNKLEtBVEQ7O0FBV0EsV0FBT3RMLE1BQVA7QUFDSCxDQTlHRDs7QUFnSEE7Ozs7QUFJQSxDQUFDLFlBQVc7QUFDWixRQUFJLE9BQU91YixPQUFPdVosV0FBZCxLQUE4QixVQUFsQyxFQUE4QztBQUMxQyxlQUFPLEtBQVA7QUFDSDs7QUFFRCxhQUFTQSxXQUFULENBQXFCQyxLQUFyQixFQUE0QkMsTUFBNUIsRUFBb0M7QUFDaENBLGlCQUFTQSxVQUFVLEVBQUVDLFNBQVMsS0FBWCxFQUFrQkMsWUFBWSxLQUE5QixFQUFxQ0MsUUFBUSxLQUFLLENBQWxELEVBQW5CO0FBQ0EsWUFBTUMsTUFBTW50QixTQUFTb3RCLFdBQVQsQ0FBcUIsYUFBckIsQ0FBWjtBQUNBRCxZQUFJRSxlQUFKLENBQW9CUCxLQUFwQixFQUEyQkMsT0FBT0MsT0FBbEMsRUFBMkNELE9BQU9FLFVBQWxELEVBQThERixPQUFPRyxNQUFyRTtBQUNBLGVBQU9DLEdBQVA7QUFDSDs7QUFFRE4sZ0JBQVl6TixTQUFaLEdBQXdCOUwsT0FBT2dhLEtBQVAsQ0FBYWxPLFNBQXJDO0FBQ0E5TCxXQUFPdVosV0FBUCxHQUFxQkEsV0FBckI7QUFDQyxDQWREOztBQWlCQTs7Ozs7Ozs7QUFRQVUsT0FBT0MsT0FBUCxHQUFpQjM0QixXQUFqQixDIiwiZmlsZSI6IjEuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqICAgICAgICAgICAgICAgQXV0b051bWVyaWMuanNcbiAqXG4gKiBAdmVyc2lvbiAgICAgIDQuMC4yXG4gKiBAZGF0ZSAgICAgICAgIDIwMTctMDgtMDIgVVRDIDAyOjUwXG4gKlxuICogQGF1dGhvcnMgICAgICBCb2IgS25vdGhlLCBBbGV4YW5kcmUgQm9ubmVhdVxuICogQGNvbnRyaWJ1dG9ycyBTb2tvbG92IFl1cmEgYW5kIG90aGVycywgY2YuIEFVVEhPUlNcbiAqIEBjb3B5cmlnaHQgICAgMjAwOSBSb2JlcnQgSi4gS25vdGhlIGh0dHA6Ly93d3cuZGVjb3JwbGFuaXQuY29tL3BsdWdpbi9cbiAqIEBzaW5jZSAgICAgICAgMjAwOS0wOC0wOVxuICpcbiAqIEBzdW1tYXJ5ICAgICAgYXV0b051bWVyaWMgaXMgYSBzdGFuZGFsb25lIEphdmFzY3JpcHQgbGlicmFyeVxuICogICAgICAgICAgICAgICB0aGF0IHByb3ZpZGVzIGxpdmUgKmFzLXlvdS10eXBlKiBmb3JtYXR0aW5nIGZvclxuICogICAgICAgICAgICAgICBpbnRlcm5hdGlvbmFsIG51bWJlcnMgYW5kIGN1cnJlbmNpZXMuXG4gKlxuICogICAgICAgICAgICAgICBOb3RlIDogU29tZSBmdW5jdGlvbnMgYXJlIGJvcnJvd2VkIGZyb20gYmlnLmpzXG4gKiBAbGluayAgICAgICAgIGh0dHBzOi8vZ2l0aHViLmNvbS9NaWtlTWNsL2JpZy5qcy9cbiAqXG4gKiBQbGVhc2UgcmVwb3J0IGFueSBidWdzIHRvIGh0dHBzOi8vZ2l0aHViLmNvbS9hdXRvTnVtZXJpYy9hdXRvTnVtZXJpY1xuICpcbiAqIEBsaWNlbnNlICAgICAgUmVsZWFzZWQgdW5kZXIgdGhlIE1JVCBMaWNlbnNlXG4gKiBAbGluayAgICAgICAgIGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvbWl0LWxpY2Vuc2UucGhwXG4gKlxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb25cbiAqIG9idGFpbmluZyBhIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uXG4gKiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXRcbiAqIHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLFxuICogY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3ViIGxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gKiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGVcbiAqIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nXG4gKiBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlXG4gKiBpbmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELFxuICogRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTXG4gKiBPRiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORFxuICogTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFRcbiAqIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLFxuICogV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HXG4gKiBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SXG4gKiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG4gKi9cblxuLyogZ2xvYmFsIG1vZHVsZSAqL1xuXG4vL1RPRE8gUHJldmVudCBoYXZpbmcgdG8gZW50ZXIgcmVsYXRpdmUgcGF0aCBpbiB0aGUganMgZmlsZXMgKGllLiB1c2luZyBgLi9BdXRvTnVtZXJpY0hlbHBlcmAgaW5zdGVhZCBvZiBqdXN0IGBBdXRvTnVtZXJpY0hlbHBlcmApIChjZi4gaHR0cDovL21vZHVzY3JlYXRlLmNvbS9lczYtZXMyMDE1LWltcG9ydC1uby1yZWxhdGl2ZS1wYXRoLXdlYnBhY2svKVxuaW1wb3J0IEF1dG9OdW1lcmljSGVscGVyIGZyb20gJy4vQXV0b051bWVyaWNIZWxwZXInO1xuaW1wb3J0IEF1dG9OdW1lcmljRW51bSBmcm9tICcuL0F1dG9OdW1lcmljRW51bSc7XG5cbi8qKlxuICogQ2xhc3MgZGVjbGFyYXRpb24gZm9yIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QuXG4gKlxuICogQW4gQXV0b051bWVyaWMgZWxlbWVudCBpcyBhbiBvYmplY3Qgd3JhcHBlciB0aGF0IGtlZXBzIGEgcmVmZXJlbmNlIHRvIHRoZSBET00gZWxlbWVudCBpdCBtYW5hZ2VzICh1c3VhbGx5IGFuIDxpbnB1dD4gb25lKSwgYW5kIHByb3ZpZGVzIGF1dG9OdW1lcmljLXNwZWNpZmljIHZhcmlhYmxlcyBhbmQgZnVuY3Rpb25zLlxuICovXG5jbGFzcyBBdXRvTnVtZXJpYyB7XG4gICAgLy9UT0RPIFVzZSB0aGUgYmV0dGVyIG5vdGF0aW9uIGBleHBvcnQgZGVmYXVsdCBjbGFzc2Agd2hlbiB3ZWJwYWNrIGFuZCBiYWJlbCB3aWxsIGFsbG93IGl0IChjZi4gaHR0cHM6Ly9naXRodWIuY29tL3dlYnBhY2svd2VicGFjay9pc3N1ZXMvNzA2KVxuICAgIC8qKlxuICAgICAqIEluaXRpYWxpemUgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBvbnRvIHRoZSBnaXZlbiBET00gZWxlbWVudCwgYW5kIGF0dGFjaCB0aGUgc2V0dGluZ3MgYW5kIHJlbGF0ZWQgZXZlbnQgbGlzdGVuZXJzIHRvIGl0LlxuICAgICAqIFRoZSBvcHRpb25zIHBhc3NlZCBhcyBhIHBhcmFtZXRlciBpcyBhbiBvYmplY3QgdGhhdCBjb250YWlucyB0aGUgc2V0dGluZ3MgKGllLiB7ZGlnaXRHcm91cFNlcGFyYXRvcjogXCIuXCIsIGRlY2ltYWxDaGFyYWN0ZXI6IFwiLFwiLCBjdXJyZW5jeVN5bWJvbDogJ+KCrCAnfSlcbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQpOyAvLyBXaXRoIHRoZSBkZWZhdWx0IG9wdGlvbnNcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgeyBvcHRpb25zIH0pOyAvLyBXaXRoIG9uZSBvcHRpb24gb2JqZWN0XG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsICdldXJvUG9zJyk7IC8vIFdpdGggYSBuYW1lZCBwcmUtZGVmaW5lZCBzdHJpbmdcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgW3sgb3B0aW9uczEgfSwgJ2V1cm9Qb3MnLCB7IG9wdGlvbnMyIH1dKTsgLy8gV2l0aCBtdWx0aXBsZSBvcHRpb24gb2JqZWN0cyAodGhlIGxhdGVzdCBvcHRpb24gb3ZlcndyaXRpbmcgdGhlIHByZXZpb3VzIG9uZXMpXG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIG51bGwsIHsgb3B0aW9ucyB9KTsgLy8gV2l0aCBvbmUgb3B0aW9uIG9iamVjdCwgYW5kIGEgZmFpbGVkIGluaXRpYWwgdmFsdWVcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCkuZnJlbmNoKCk7IC8vIFdpdGggb25lIHByZS1kZWZpbmVkIGxhbmd1YWdlIG9iamVjdFxuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50KS5mcmVuY2goeyBvcHRpb25zIH0pOy8vIFdpdGggb25lIHByZS1kZWZpbmVkIGxhbmd1YWdlIG9iamVjdCBhbmQgYWRkaXRpb25hbCBvcHRpb25zIHRoYXQgd2lsbCBvdmVycmlkZSB0aGUgZGVmYXVsdHNcbiAgICAgKlxuICAgICAqIC8vIC4uLm9yIGluaXQgYW5kIHNldCB0aGUgdmFsdWUgaW4gb25lIGNhbGwgOlxuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAxMjM0NS43ODkpOyAvLyBXaXRoIHRoZSBkZWZhdWx0IG9wdGlvbnMsIGFuZCBhbiBpbml0aWFsIHZhbHVlXG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIDEyMzQ1Ljc4OSwgeyBvcHRpb25zIH0pO1xuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAnMTIzNDUuNzg5JywgeyBvcHRpb25zIH0pO1xuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAxMjM0NS43ODksICdldXJvUG9zJyk7XG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIDEyMzQ1Ljc4OSwgW3sgb3B0aW9uczEgfSwgJ2V1cm9Qb3MnLCB7IG9wdGlvbnMyIH1dKTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgMTIzNDUuNzg5KS5mcmVuY2goeyBvcHRpb25zIH0pO1xuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAxMjM0NS43ODksIHsgb3B0aW9ucyB9KS5mcmVuY2goeyBvcHRpb25zIH0pOyAvLyBOb3QgcmVhbGx5IGhlbHBmdWwsIGJ1dCBwb3NzaWJsZVxuICAgICAqXG4gICAgICogLy8gVGhlIEF1dG9OdW1lcmljIGNvbnN0cnVjdG9yIGNsYXNzIGNhbiBhbHNvIGFjY2VwdCBhIHN0cmluZyBhcyBhIGNzcyBzZWxlY3Rvci4gVW5kZXIgdGhlIGhvb2QgdGhpcyB1c2UgYFF1ZXJ5U2VsZWN0b3JgIGFuZCBsaW1pdCBpdHNlbGYgdG8gb25seSB0aGUgZmlyc3QgZWxlbWVudCBpdCBmaW5kcy5cbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnKTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCB7IG9wdGlvbnMgfSk7XG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgJ2V1cm9Qb3MnKTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCBbeyBvcHRpb25zMSB9LCAnZXVyb1BvcycsIHsgb3B0aW9uczIgfV0pO1xuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIDEyMzQ1Ljc4OSk7XG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgMTIzNDUuNzg5LCB7IG9wdGlvbnMgfSk7XG4gICAgICogYW5FbGVtZW50ID0gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgMTIzNDUuNzg5LCAnZXVyb1BvcycpO1xuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIDEyMzQ1Ljc4OSwgW3sgb3B0aW9uczEgfSwgJ2V1cm9Qb3MnLCB7IG9wdGlvbnMyIH1dKTtcbiAgICAgKiBhbkVsZW1lbnQgPSBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCBudWxsLCB7IG9wdGlvbnMgfSk7IC8vIFdpdGggYSBmYWlsZWQgaW5pdGlhbCB2YWx1ZVxuICAgICAqIGFuRWxlbWVudCA9IG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIDEyMzQ1Ljc4OSkuZnJlbmNoKHsgb3B0aW9ucyB9KTtcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fEFycmF5fG51bWJlcnxzdHJpbmd9IGFyZzFcbiAgICAgKiBAcGFyYW0ge29iamVjdHxBcnJheXxudW1iZXJ8c3RyaW5nfG51bGx9IGFyZzJcbiAgICAgKiBAcGFyYW0ge29iamVjdHxBcnJheXxudW1iZXJ8c3RyaW5nfG51bGx9IGFyZzNcbiAgICAgKiBAdGhyb3dzXG4gICAgICovXG4gICAgY29uc3RydWN0b3IoYXJnMSA9IG51bGwsIGFyZzIgPSBudWxsLCBhcmczID0gbnVsbCkge1xuICAgICAgICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxuICAgICAgICAvLyAtLS0tLS0tLS0tLS0tLSBJbml0aWFsaXphdGlvblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBhcmd1bWVudHNcbiAgICAgICAgY29uc3QgeyBkb21FbGVtZW50LCBpbml0aWFsVmFsdWUsIHVzZXJPcHRpb25zIH0gPSBBdXRvTnVtZXJpYy5fc2V0QXJndW1lbnRzVmFsdWVzKGFyZzEsIGFyZzIsIGFyZzMpO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIGVsZW1lbnRcbiAgICAgICAgdGhpcy5kb21FbGVtZW50ID0gZG9tRWxlbWVudDtcblxuICAgICAgICAvLyBHZW5lcmF0ZSB0aGUgc2V0dGluZ3NcbiAgICAgICAgdGhpcy5kZWZhdWx0UmF3VmFsdWUgPSAnJzsgLy8gVGhlIGRlZmF1bHQgcmF3IHZhbHVlIHRvIHNldCB3aGVuIGluaXRpYWxpemluZyBhbiBBdXRvTnVtZXJpYyBvYmplY3RcbiAgICAgICAgdGhpcy5fc2V0U2V0dGluZ3ModXNlck9wdGlvbnMsIGZhbHNlKTtcbiAgICAgICAgLy9UT0RPIElmIGBzdHlsZVJ1bGVzYCBpcyBub3QgbnVsbCwgYWRkIGJ5IGRlZmF1bHQgYSBjbGFzcyAnYXV0b051bWVyaWMnIHRoYXQgYWRkcyB0cmFuc2l0aW9uIHRvIGNvbG9yLCBiYWNrZ3JvdW5kLWNvbG9yLCBib3JkZXItY29sb3IgcHJvcGVydGllc1xuICAgICAgICAvLyBDaGVjayBpZiB0aGUgRE9NIGVsZW1lbnQgaXMgc3VwcG9ydGVkXG4gICAgICAgIHRoaXMuX2NoZWNrRWxlbWVudCgpO1xuXG4gICAgICAgIC8vIFN0b3JlIHRoZSBhZGRpdGlvbmFsIGF0dHJpYnV0ZXMgaW5zaWRlIHRoZSBBdXRvTnVtZXJpYyBvYmplY3RcbiAgICAgICAgLy8gTm90ZTogVGhpcyB2YXJpYWJsZSBpcyBuZWVkZWQgYW5kIG5vdCBhIGR1cGxpY2F0ZSBvZiBgaW5pdGlhbFZhbHVlT25LZXlkb3duYCBub3IgYHZhbHVlT25Gb2N1c2Agc2luY2UgaXQgc2VydmVzIGEgZGlmZmVyZW50IHB1cnBvc2UgYW5kIGhhcyBhIGRpZmZlcmVudCBsaWZlY3ljbGVcbiAgICAgICAgdGhpcy5zYXZlZENhbmNlbGxhYmxlVmFsdWUgPSBudWxsO1xuXG4gICAgICAgIC8vIEluaXRpYWxpemUgdGhlIHVuZG8vcmVkbyB2YXJpYWJsZXNcbiAgICAgICAgdGhpcy5oaXN0b3J5VGFibGUgPSBbXTsgLy8gS2VlcCB0cmFjayBvZiAqYWxsKiB2YWxpZCBzdGF0ZXMgb2YgdGhlIGVsZW1lbnQgdmFsdWVcbiAgICAgICAgdGhpcy5oaXN0b3J5VGFibGVJbmRleCA9IC0xOyAvLyBQb2ludGVyIHRvIHRoZSBjdXJyZW50IHVuZG8vcmVkbyBzdGF0ZS4gVGhpcyB3aWxsIGJlIHNldCB0byAnMCcgZHVyaW5nIGluaXRpYWxpemF0aW9uIHNpbmNlIGl0IGZpcnN0IGFkZHMgaXRzZWxmLlxuICAgICAgICB0aGlzLm9uR29pbmdSZWRvID0gZmFsc2U7IC8vIFZhcmlhYmxlIHRoYXQga2VlcHMgdHJhY2sgaWYgYSAncmVkbycgaXMgb25nb2luZyAoaW4gb3JkZXIgdG8gcHJldmVudCBhbiAndW5kbycgdG8gYmUgbGF1bmNoIHdoZW4gcmVsZWFzaW5nIHRoZSBzaGlmdCBrZXkgYmVmb3JlIHRoZSBjdHJsIGtleSBhZnRlciBhICdyZWRvJyBzaG9ydGN1dClcblxuICAgICAgICAvLyBJbml0aWFsaXplIHRoZSBwYXJlbnQgZm9ybSBlbGVtZW50LCBpZiBhbnlcbiAgICAgICAgdGhpcy5wYXJlbnRGb3JtID0gdGhpcy5fZ2V0UGFyZW50Rm9ybSgpO1xuXG4gICAgICAgIC8vIFNldCB0aGUgaW5pdGlhbCB2YWx1ZSBpZiBpdCBleGlzdHMgYW5kIGlmIHRoZSBgZm9ybWF0T25QYWdlTG9hZGAgb3B0aW9uIHdpbGwgYWxsb3cgaXRcbiAgICAgICAgaWYgKCF0aGlzLnJ1bk9uY2UgJiYgdGhpcy5zZXR0aW5ncy5mb3JtYXRPblBhZ2VMb2FkKSB7XG4gICAgICAgICAgICAvLyBGb3JtYXQgdGhlIGVsZW1lbnQgdmFsdWUgaWYgbmVlZGVkXG4gICAgICAgICAgICB0aGlzLl9mb3JtYXREZWZhdWx0VmFsdWVPblBhZ2VMb2FkKGluaXRpYWxWYWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLnJ1bk9uY2UgPSB0cnVlO1xuXG4gICAgICAgIC8vIEFkZCB0aGUgZXZlbnRzIGxpc3RlbmVycyBvbmx5IG9uIGlucHV0IGVsZW1lbnRzXG4gICAgICAgIGlmICh0aGlzLmlzSW5wdXRFbGVtZW50IHx8IHRoaXMuaXNDb250ZW50RWRpdGFibGUpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5zZXR0aW5ncy5ub0V2ZW50TGlzdGVuZXJzKSB7XG4gICAgICAgICAgICAgICAgLy9YWFggSGVyZSB3ZSBtYWtlIHN1cmUgdGhlIGdsb2JhbCBsaXN0IGlzIGNyZWF0ZWQgYWZ0ZXIgY3JlYXRpbmcgdGhlIGV2ZW50IGxpc3RlbmVycywgdG8gb25seSBjcmVhdGUgdGhlIGV2ZW50IGxpc3RlbmVycyBvbiBgZG9jdW1lbnRgIG9uY2VcbiAgICAgICAgICAgICAgICB0aGlzLl9jcmVhdGVFdmVudExpc3RlbmVycygpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9zZXRSZWFkT25seSgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2F2ZSB0aGUgaW5pdGlhbCB2YWx1ZXMgKGh0bWwgYXR0cmlidXRlICsgZWxlbWVudC52YWx1ZSkgZm9yIHRoZSBwcmlzdGluZSB0ZXN0XG4gICAgICAgIHRoaXMuX3NhdmVJbml0aWFsVmFsdWVzKGluaXRpYWxWYWx1ZSk7XG4gICAgICAgIFxuICAgICAgICAvLyBTZXR1cCB0aGUgZGF0YSBmb3IgdGhlIHBlcnNpc3RlbnQgc3RvcmFnZSBzb2x1dGlvbiAoaWUuIHNlc3Npb25TdG9yYWdlIG9yIGNvb2tpZXMpXG4gICAgICAgIHRoaXMuc2Vzc2lvblN0b3JhZ2VBdmFpbGFibGUgPSB0aGlzLmNvbnN0cnVjdG9yLl9zdG9yYWdlVGVzdCgpO1xuICAgICAgICB0aGlzLnN0b3JhZ2VOYW1lUHJlZml4ID0gJ0FVVE9fJzsgLy8gVGhlIHByZWZpeCBmb3IgdGhlIHJhdyB2YWx1ZSBzdG9yYWdlIG5hbWUgdmFyaWFibGUgY2FuIGJlIG1vZGlmaWVkIGhlcmVcbiAgICAgICAgdGhpcy5fc2V0UGVyc2lzdGVudFN0b3JhZ2VOYW1lKCk7XG5cbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgICAgICAgLy8gLS0tLS0tLS0tLS0tLS0gVHJhY2tpbmdcbiAgICAgICAgLy8gS2VlcCB0cmFjayBpZiB0aGUgZWxlbWVudCBpcyBjdXJyZW50bHkgZm9jdXNlZFxuICAgICAgICB0aGlzLmlzRm9jdXNlZCA9IGZhbHNlO1xuICAgICAgICAvLyBLZWVwIHRyYWNrIGlmIGEgbW91c2Ugd2hlZWwgZXZlbnQgaXMgY3VycmVudGx5IG9uZ29pbmdcbiAgICAgICAgdGhpcy5pc1doZWVsRXZlbnQgPSBmYWxzZTtcbiAgICAgICAgLy8gS2VlcCB0cmFjayBpZiBhIGRyb3AgZXZlbnQgaXMgY3VycmVudGx5IG9uZ29pbmdcbiAgICAgICAgdGhpcy5pc0Ryb3BFdmVudCA9IGZhbHNlO1xuICAgICAgICAvLyBLZWVwIHRyYWNrIGlmIHRoZSB1c2VyIGlzIGN1cnJlbnRseSBlZGl0aW5nIHRoZSBlbGVtZW50XG4gICAgICAgIHRoaXMuaXNFZGl0aW5nID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3JlYXRlTG9jYWxMaXN0KSB7XG4gICAgICAgICAgICAvLyBLZWVwIHRyYWNrIG9mIGV2ZXJ5IEF1dG9OdW1lcmljIGVsZW1lbnRzIHRoYXQgdGhpcyBvYmplY3QgaW5pdGlhbGl6ZWRcbiAgICAgICAgICAgIHRoaXMuX2NyZWF0ZUxvY2FsTGlzdCgpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gS2VlcCB0cmFjayBvZiBhbGwgQXV0b051bWVyaWMgZWxlbWVudHMgaW4gdGhlIGN1cnJlbnQgd2ViIHBhZ2VcbiAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fYWRkVG9HbG9iYWxMaXN0KHRoaXMpO1xuXG4gICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gICAgICAgIC8vIC0tLS0tLS0tLS0tLS0tIE1ldGhvZHNcbiAgICAgICAgLy8gQ3JlYXRlIHRoZSBnbG9iYWwgZnVuY3Rpb25zXG4gICAgICAgIHRoaXMuZ2xvYmFsID0ge1xuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBTZXQgdGhlIHNhbWUgZ2l2ZW4gZWxlbWVudCB2YWx1ZSBmb3IgZWFjaCBlbGVtZW50cyBpbiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0LCBhbmQgZm9ybWF0IHRob3NlIGVsZW1lbnRzIGltbWVkaWF0ZWx5XG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfSBuZXdWYWx1ZSBUaGUgdmFsdWUgbXVzdCBiZSBhIG51bWJlciBvciBhIG51bWVyaWMgc3RyaW5nXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9ucyBBIHNldHRpbmdzIG9iamVjdCB0aGF0IHdpbGwgb3ZlcnJpZGUgdGhlIGN1cnJlbnQgc2V0dGluZ3MuIE5vdGU6IHRoZSB1cGRhdGUgaXMgZG9uZSBvbmx5IGlmIHRoZSBgbmV3VmFsdWVgIGlzIGRlZmluZWQuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNldDogKG5ld1ZhbHVlLCBvcHRpb25zID0gbnVsbCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0LnNldChuZXdWYWx1ZSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFNldCB0aGUgdmFsdWUgZ2l2ZW4gdmFsdWUgZGlyZWN0bHkgYXMgdGhlIERPTSBlbGVtZW50IHZhbHVlLCB3aXRob3V0IGZvcm1hdHRpbmcgaXQgYmVmb3JlaGFuZC5cbiAgICAgICAgICAgICAqIFRoaXMgc2V0cyB0aGUgc2FtZSB1bmZvcm1hdHRlZCB2YWx1ZSBmb3IgZWFjaCBlbGVtZW50cyBpbiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0LlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ30gdmFsdWVcbiAgICAgICAgICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNldFVuZm9ybWF0dGVkOiAodmFsdWUsIG9wdGlvbnMgPSBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3Quc2V0VW5mb3JtYXR0ZWQodmFsdWUsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBUaGlzIGlzIGFuIGFsaWFzIG9mIHRoZSBgZ2V0TnVtZXJpY1N0cmluZygpYCBmdW5jdGlvbiwgYW5kIHNob3VsZCBub3QgYmUgdXNlZCBhbnltb3JlLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2sgSWYgYSBjYWxsYmFjayBpcyBwYXNzZWQsIHRoZW4gdGhlIHJlc3VsdCBpcyBwYXNzZWQgdG8gaXQgYXMgaXRzIGZpcnN0IGFyZ3VtZW50LCBhbmQgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBoYXMgaXRzIHNlY29uZFxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5PHN0cmluZz59XG4gICAgICAgICAgICAgKiBAZGVwcmVjYXRlZFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXQ6IChjYWxsYmFjayA9IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChhTk9iamVjdC5nZXQoKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fZXhlY3V0ZUNhbGxiYWNrKHJlc3VsdCwgY2FsbGJhY2spO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmV0dXJuIGFuIGFycmF5IG9mIHRoZSB1bmZvcm1hdHRlZCB2YWx1ZXMgKGFzIGEgc3RyaW5nKSBvZiBlYWNoIEF1dG9OdW1lcmljIGVsZW1lbnQgb2YgdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdFxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2sgSWYgYSBjYWxsYmFjayBpcyBwYXNzZWQsIHRoZW4gdGhlIHJlc3VsdCBpcyBwYXNzZWQgdG8gaXQgYXMgaXRzIGZpcnN0IGFyZ3VtZW50LCBhbmQgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBoYXMgaXRzIHNlY29uZFxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5PHN0cmluZz59XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldE51bWVyaWNTdHJpbmc6IChjYWxsYmFjayA9IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChhTk9iamVjdC5nZXROdW1lcmljU3RyaW5nKCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuX2V4ZWN1dGVDYWxsYmFjayhyZXN1bHQsIGNhbGxiYWNrKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFJldHVybiBhbiBhcnJheSBvZiB0aGUgY3VycmVudCBmb3JtYXR0ZWQgdmFsdWVzIChhcyBhIHN0cmluZykgb2YgZWFjaCBBdXRvTnVtZXJpYyBlbGVtZW50IG9mIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3RcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrIElmIGEgY2FsbGJhY2sgaXMgcGFzc2VkLCB0aGVuIHRoZSByZXN1bHQgaXMgcGFzc2VkIHRvIGl0IGFzIGl0cyBmaXJzdCBhcmd1bWVudCwgYW5kIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgaGFzIGl0cyBzZWNvbmRcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBcnJheTxzdHJpbmc+fVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBnZXRGb3JtYXR0ZWQ6IChjYWxsYmFjayA9IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChhTk9iamVjdC5nZXRGb3JtYXR0ZWQoKSk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgdGhpcy5fZXhlY3V0ZUNhbGxiYWNrKHJlc3VsdCwgY2FsbGJhY2spO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmV0dXJuIGFuIGFycmF5IG9mIHRoZSBlbGVtZW50IHVuZm9ybWF0dGVkIHZhbHVlcyAoYXMgYSByZWFsIEphdmFzY3JpcHQgbnVtYmVyKSwgZm9yIGVhY2ggZWxlbWVudCBvZiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXk8bnVtYmVyPn1cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0TnVtYmVyOiAoY2FsbGJhY2sgPSBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goYU5PYmplY3QuZ2V0TnVtYmVyKCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuX2V4ZWN1dGVDYWxsYmFjayhyZXN1bHQsIGNhbGxiYWNrKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFJldHVybnMgdGhlIHVuZm9ybWF0dGVkIHZhbHVlcyAoZm9sbG93aW5nIHRoZSBgb3V0cHV0Rm9ybWF0YCBzZXR0aW5nKSBvZiBlYWNoIGVsZW1lbnQgb2YgdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdCBpbnRvIGFuIGFycmF5XG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7QXJyYXk8c3RyaW5nPn1cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZ2V0TG9jYWxpemVkOiAoY2FsbGJhY2sgPSBudWxsKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gW107XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goYU5PYmplY3QuZ2V0TG9jYWxpemVkKCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIHRoaXMuX2V4ZWN1dGVDYWxsYmFjayhyZXN1bHQsIGNhbGxiYWNrKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEZvcmNlIGVhY2ggZWxlbWVudCBvZiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0IHRvIHJlZm9ybWF0IGl0cyB2YWx1ZVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICByZWZvcm1hdDogKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0LnJlZm9ybWF0KCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFJlbW92ZSB0aGUgZm9ybWF0dGluZyBhbmQga2VlcCBvbmx5IHRoZSByYXcgdW5mb3JtYXR0ZWQgdmFsdWUgKGFzIGEgbnVtZXJpY1N0cmluZykgaW4gZWFjaCBlbGVtZW50cyBvZiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHVuZm9ybWF0OiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QudW5mb3JtYXQoKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmVtb3ZlIHRoZSBmb3JtYXR0aW5nIGFuZCBrZWVwIG9ubHkgdGhlIGxvY2FsaXplZCB1bmZvcm1hdHRlZCB2YWx1ZSBpbiB0aGUgZWxlbWVudCwgd2l0aCB0aGUgb3B0aW9uIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IG91dHB1dEZvcm1hdCBpZiBuZWVkZWRcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge251bGx8c3RyaW5nfSBmb3JjZWRPdXRwdXRGb3JtYXQgSWYgc2V0IHRvIHNvbWV0aGluZyBkaWZmZXJlbnQgdGhhbiBgbnVsbGAsIHRoZW4gdGhpcyBpcyB1c2VkIGFzIGFuIG92ZXJyaWRpbmcgb3V0cHV0Rm9ybWF0IG9wdGlvblxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICB1bmZvcm1hdExvY2FsaXplZDogKGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGwpID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICBhTk9iamVjdC51bmZvcm1hdExvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBVcGRhdGVzIHRoZSBBdXRvTnVtZXJpYyBzZXR0aW5ncywgYW5kIGltbWVkaWF0ZWx5IGZvcm1hdCB0aGUgZWxlbWVudHMgYWNjb3JkaW5nbHksIGZvciBlYWNoIGVsZW1lbnRzIG9mIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3RcbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge29iamVjdH0gbmV3T3B0aW9ucyBUaGlzIGNhbiBiZSBlaXRoZXIgb25lIG9yIG1vcmUgb3B0aW9uIG9iamVjdHNcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdXBkYXRlOiAoLi4ubmV3T3B0aW9ucykgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0LnVwZGF0ZSguLi5uZXdPcHRpb25zKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmV0dXJuIGB0cnVlYCBpZiAqYWxsKiB0aGUgYXV0b051bWVyaWMtbWFuYWdlZCBlbGVtZW50cyBhcmUgcHJpc3RpbmUsIGlmIHRoZWlyIHJhdyB2YWx1ZSBoYXNuJ3QgY2hhbmdlZC5cbiAgICAgICAgICAgICAqIEJ5IGRlZmF1bHQsIHRoaXMgcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJhdyB1bmZvcm1hdHRlZCB2YWx1ZSBpcyBzdGlsbCB0aGUgc2FtZSBldmVuIGlmIHRoZSBmb3JtYXR0ZWQgb25lIGhhcyBjaGFuZ2VkIChkdWUgdG8gYSBjb25maWd1cmF0aW9uIHVwZGF0ZSBmb3IgaW5zdGFuY2UpLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gY2hlY2tPbmx5UmF3VmFsdWUgSWYgc2V0IHRvIGB0cnVlYCwgdGhlIHByaXN0aW5lIHZhbHVlIGlzIGRvbmUgb24gdGhlIHJhdyB1bmZvcm1hdHRlZCB2YWx1ZSwgbm90IHRoZSBmb3JtYXR0ZWQgb25lLiBJZiBzZXQgdG8gYGZhbHNlYCwgdGhpcyBhbHNvIGNoZWNrcyB0aGF0IHRoZSBmb3JtYXR0ZWQgdmFsdWUgaGFzbid0IGNoYW5nZWQuXG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgaXNQcmlzdGluZTogKGNoZWNrT25seVJhd1ZhbHVlID0gdHJ1ZSkgPT4ge1xuICAgICAgICAgICAgICAgIGxldCBpc1ByaXN0aW5lID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNQcmlzdGluZSAmJiAhYU5PYmplY3QuaXNQcmlzdGluZShjaGVja09ubHlSYXdWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzUHJpc3RpbmUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIGlzUHJpc3RpbmU7XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIEV4ZWN1dGUgdGhlIGBjbGVhcigpYCBtZXRob2Qgb24gZWFjaCBBdXRvTnVtZXJpYyBvYmplY3QgaW4gdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdFxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gZm9yY2VDbGVhckFsbFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBjbGVhcjogKGZvcmNlQ2xlYXJBbGwgPSBmYWxzZSkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0LmNsZWFyKGZvcmNlQ2xlYXJBbGwpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBFeGVjdXRlIHRoZSBgcmVtb3ZlKClgIG1ldGhvZCBvbiBlYWNoIEF1dG9OdW1lcmljIG9iamVjdCBpbiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHJlbW92ZTogKCkgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZm9yRWFjaChhTk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGFOT2JqZWN0LnJlbW92ZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBFeGVjdXRlIHRoZSBgd2lwZSgpYCBtZXRob2Qgb24gZWFjaCBBdXRvTnVtZXJpYyBvYmplY3QgaW4gdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICB3aXBlOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3Qud2lwZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBFeGVjdXRlIHRoZSBgbnVrZSgpYCBtZXRob2Qgb24gZWFjaCBBdXRvTnVtZXJpYyBvYmplY3QgaW4gdGhlIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBudWtlOiAoKSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QubnVrZSgpO1xuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBnaXZlbiBBdXRvTnVtZXJpYyBvYmplY3QgKG9yIERPTSBlbGVtZW50KSBpcyBpbiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fEF1dG9OdW1lcmljfSBkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdFxuICAgICAgICAgICAgICogQHJldHVybnMgeyp9XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGhhczogZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgICAgICAgICAgaWYgKGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0IGluc3RhbmNlb2YgQXV0b051bWVyaWMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5oYXMoZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3Qubm9kZSgpKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0Lmhhcyhkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogQWRkIGFuIGV4aXN0aW5nIEF1dG9OdW1lcmljIG9iamVjdCAob3IgRE9NIGVsZW1lbnQpIHRvIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QsIHVzaW5nIHRoZSBET00gZWxlbWVudCBhcyB0aGUga2V5LlxuICAgICAgICAgICAgICogVGhpcyBtYW5hZ2VzIHRoZSBjYXNlIHdoZXJlIGBhZGRPYmplY3RgIGlzIHVzZWQgb24gYW4gQXV0b051bWVyaWMgb2JqZWN0IHRoYXQgYWxyZWFkeSBoYXMgbXVsdGlwbGUgZWxlbWVudHMgaW4gaXRzIGxvY2FsIGxpc3QuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fEF1dG9OdW1lcmljfSBkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBhZGRPYmplY3Q6IGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAvLyBTdGFydCB3aXRoIHRoZSBzYW1lIGRhdGEsIHdoYXRldmVyIHRoZSB1c2VyIHBhc3NlZCBhcyBhcmd1bWVudHNcbiAgICAgICAgICAgICAgICBsZXQgZG9tRWxlbWVudDtcbiAgICAgICAgICAgICAgICBsZXQgb3RoZXJBdXRvTnVtZXJpY09iamVjdDtcbiAgICAgICAgICAgICAgICBpZiAoZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3QgaW5zdGFuY2VvZiBBdXRvTnVtZXJpYykge1xuICAgICAgICAgICAgICAgICAgICBkb21FbGVtZW50ID0gZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3Qubm9kZSgpO1xuICAgICAgICAgICAgICAgICAgICBvdGhlckF1dG9OdW1lcmljT2JqZWN0ID0gZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3Q7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZG9tRWxlbWVudCA9IGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0O1xuICAgICAgICAgICAgICAgICAgICBvdGhlckF1dG9OdW1lcmljT2JqZWN0ID0gQXV0b051bWVyaWMuZ2V0QXV0b051bWVyaWNFbGVtZW50KGRvbUVsZW1lbnRPckF1dG9OdW1lcmljT2JqZWN0KTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiB0aGUgY3VycmVudCBhdXRvTnVtZXJpYyBvYmplY3QgaGFzIGEgbG9jYWwgbGlzdFxuICAgICAgICAgICAgICAgIGlmICghdGhpcy5faGFzTG9jYWxMaXN0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fY3JlYXRlTG9jYWxMaXN0KCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIG90aGVyIGF1dG9OdW1lcmljIG9iamVjdCBoYXMgYSBsb2NhbCBsaXN0Li4uXG4gICAgICAgICAgICAgICAgbGV0IG90aGVyQU5Mb2NhbExpc3QgPSBvdGhlckF1dG9OdW1lcmljT2JqZWN0Ll9nZXRMb2NhbExpc3QoKTtcbiAgICAgICAgICAgICAgICBpZiAob3RoZXJBTkxvY2FsTGlzdC5zaXplID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFNwZWNpYWwgY2FzZSBpZiB0aGUgb3RoZXIgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBhbiBlbXB0eSBsb2NhbCBsaXN0LCB0aGVuIHBvcHVsYXRlIGl0c2VsZiB0byBpdFxuICAgICAgICAgICAgICAgICAgICBvdGhlckF1dG9OdW1lcmljT2JqZWN0Ll9jcmVhdGVMb2NhbExpc3QoKTtcbiAgICAgICAgICAgICAgICAgICAgb3RoZXJBTkxvY2FsTGlzdCA9IG90aGVyQXV0b051bWVyaWNPYmplY3QuX2dldExvY2FsTGlzdCgpOyAvLyBVcGRhdGUgdGhlIG90aGVyIGxvY2FsIGxpc3RcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgbWVyZ2VkTG9jYWxMaXN0cztcbiAgICAgICAgICAgICAgICBpZiAob3RoZXJBTkxvY2FsTGlzdCBpbnN0YW5jZW9mIE1hcCkge1xuICAgICAgICAgICAgICAgICAgICAvLyAuLi5JZiBpdCBkb2VzLCBtZXJnZSB0aGUgbG9jYWwgbGlzdHMgdG9nZXRoZXJcbiAgICAgICAgICAgICAgICAgICAgbWVyZ2VkTG9jYWxMaXN0cyA9IEF1dG9OdW1lcmljSGVscGVyLm1lcmdlTWFwcyh0aGlzLl9nZXRMb2NhbExpc3QoKSwgb3RoZXJBTkxvY2FsTGlzdCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gLi4uSWYgbm90LCBqdXN0IHNldCB0aGUgY3VycmVudCBsb2NhbCBsaXN0IG9udG8gdGhlIG90aGVyIEF1dG9OdW1lcmljIG9iamVjdFxuICAgICAgICAgICAgICAgICAgICAvLyBXZSBuZWVkIHRvIHNwZWNpZnkgdGhlIEF1dG9OdW1lcmljIG9iamVjdCwgb3RoZXJ3aXNlIHRoZSBgX2FkZFRvTG9jYWxMaXN0YCBmdW5jdGlvbiB3b3VsZCBub3QgY29ycmVjdGx5IGFkZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IHNpbmNlIHdlIHdvdWxkIG5vdCBoYXZlIGEgcmVmZXJlbmNlIHRvIGl0LCBidXQgYSByZWZlcmVuY2UgdG8gdGhlIGN1cnJlbnQgQXV0b051bWVyaWMgb2JqZWN0IG9uIHdoaWNoIGlzIGNhbGxlZCB0aGlzIG1ldGhvZC5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fYWRkVG9Mb2NhbExpc3QoZG9tRWxlbWVudCwgb3RoZXJBdXRvTnVtZXJpY09iamVjdCk7XG4gICAgICAgICAgICAgICAgICAgIG1lcmdlZExvY2FsTGlzdHMgPSB0aGlzLl9nZXRMb2NhbExpc3QoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHJlc3VsdGluZyBsaXN0LCBvbiBhbGwgdGhlIG9iamVjdHMgb2YgdGhhdCBsb2NhbCBsaXN0IChzbyB0aGF0IHdlIGNhbiBpbmRpZmZlcmVudGx5IHVzZSBgaW5pdCgpYCBvbiBhbnkgb2JqZWN0IGJlbG9uZ2luZyB0byB0aGF0IGxpc3QpXG4gICAgICAgICAgICAgICAgbWVyZ2VkTG9jYWxMaXN0cy5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QuX3NldExvY2FsTGlzdChtZXJnZWRMb2NhbExpc3RzKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmVtb3ZlIHRoZSBnaXZlbiBBdXRvTnVtZXJpYyBvYmplY3QgKG9yIERPTSBlbGVtZW50KSBmcm9tIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QsIHVzaW5nIHRoZSBET00gZWxlbWVudCBhcyB0aGUga2V5LlxuICAgICAgICAgICAgICogSWYgdGhpcyBmdW5jdGlvbiBhdHRlbXB0cyB0byByZW1vdmUgdGhlIGN1cnJlbnQgQXV0b051bWVyaWMgb2JqZWN0IGZyb20gdGhlIGxvY2FsIGxpc3QsIGEgd2FybmluZyBpcyBzaG93biwgYnV0IHRoZSBkZWxldGlvbiBpcyBzdGlsbCBkb25lLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIFNwZWNpYWwgY2FzZXMgOlxuICAgICAgICAgICAgICogLSBJZiB0aGUgY3VycmVudCBvYmplY3QgcmVtb3ZlcyBpdHNlbGYsIHRoZW4gaXQncyByZW1vdmVkIGZyb20gdGhlIHNoYXJlZCBsb2NhbCBsaXN0LCB0aGVuIGEgbmV3IGVtcHR5IGxvY2FsIGxpc3QgaXMgdXNlZC9jcmVhdGVkXG4gICAgICAgICAgICAgKiAtIElmIGFub3RoZXIgb2JqZWN0IHJlbW92ZSB0aGlzIG9iamVjdCwgdGhlbiBhIGxvY2FsIGxpc3Qgd2l0aCBvbmx5IHRoaXMgb2JqZWN0IGlzIHVzZWQvY3JlYXRlZFxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudHxBdXRvTnVtZXJpY30gZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3RcbiAgICAgICAgICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0ga2VlcEN1cnJlbnRBTk9iamVjdCBJZiBzZXQgdG8gYGZhbHNlYCwgdGhlbiB0aGUgZnVuY3Rpb24gd2lsbCBhbHNvIHJlbW92ZSB0aGUgY3VycmVudCBBdXRvTnVtZXJpYyBvYmplY3QgaWYgYXNrZWQsIG90aGVyd2lzZSBpdCB3aWxsIGlnbm9yZSBpdCBhbmQgcHJpbnQgYSB3YXJuaW5nIG1lc3NhZ2VcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgcmVtb3ZlT2JqZWN0OiAoZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3QsIGtlZXBDdXJyZW50QU5PYmplY3QgPSBmYWxzZSkgPT4ge1xuICAgICAgICAgICAgICAgIC8vIFN0YXJ0IHdpdGggdGhlIHNhbWUgZGF0YSwgd2hhdGV2ZXIgdGhlIHVzZXIgcGFzc2VkIGFzIGFyZ3VtZW50c1xuICAgICAgICAgICAgICAgIGxldCBkb21FbGVtZW50O1xuICAgICAgICAgICAgICAgIGxldCBvdGhlckF1dG9OdW1lcmljT2JqZWN0O1xuICAgICAgICAgICAgICAgIGlmIChkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdCBpbnN0YW5jZW9mIEF1dG9OdW1lcmljKSB7XG4gICAgICAgICAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdC5ub2RlKCk7XG4gICAgICAgICAgICAgICAgICAgIG90aGVyQXV0b051bWVyaWNPYmplY3QgPSBkb21FbGVtZW50T3JBdXRvTnVtZXJpY09iamVjdDtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBkb21FbGVtZW50ID0gZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3Q7XG4gICAgICAgICAgICAgICAgICAgIG90aGVyQXV0b051bWVyaWNPYmplY3QgPSBBdXRvTnVtZXJpYy5nZXRBdXRvTnVtZXJpY0VsZW1lbnQoZG9tRWxlbWVudE9yQXV0b051bWVyaWNPYmplY3QpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgb3RoZXIgb2JqZWN0IGZyb20gdGhlIGxvY2FsIGxpc3RcbiAgICAgICAgICAgICAgICBjb25zdCBpbml0aWFsQ29tcGxldGVMb2NhbExpc3QgPSB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0O1xuICAgICAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QuZGVsZXRlKGRvbUVsZW1lbnQpO1xuXG4gICAgICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBsb2NhbCBsaXN0IGZvciBhbGwgb2JqZWN0cyBpbiBpdFxuICAgICAgICAgICAgICAgIGluaXRpYWxDb21wbGV0ZUxvY2FsTGlzdC5mb3JFYWNoKGFOT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QuX3NldExvY2FsTGlzdCh0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0KTtcbiAgICAgICAgICAgICAgICB9KTtcblxuICAgICAgICAgICAgICAgIGlmICgha2VlcEN1cnJlbnRBTk9iamVjdCAmJiBkb21FbGVtZW50ID09PSB0aGlzLm5vZGUoKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIG9iamVjdCBpcyByZW1vdmVkIGJ5IGl0c2VsZlxuICAgICAgICAgICAgICAgICAgICAvLyBFbXB0eSB0aGUgb2JqZWN0IGxvY2FsIGxpc3RcbiAgICAgICAgICAgICAgICAgICAgb3RoZXJBdXRvTnVtZXJpY09iamVjdC5fc2V0TG9jYWxMaXN0KG5ldyBNYXApO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgb2JqZWN0IGlzIHJlbW92ZWQgYnkgYW5vdGhlciBvYmplY3RcbiAgICAgICAgICAgICAgICAgICAgLy8gU2V0IHRoZSBsb2NhbCBsaXN0IGZvciB0aGUgcmVtb3ZlZCBvYmplY3QsIHdpdGggb25seSB0aGlzIG9iamVjdCBpbiBpdFxuICAgICAgICAgICAgICAgICAgICBvdGhlckF1dG9OdW1lcmljT2JqZWN0Ll9jcmVhdGVMb2NhbExpc3QoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKipcbiAgICAgICAgICAgICAqIFJlbW92ZSBhbGwgZWxlbWVudHMgZnJvbSB0aGUgc2hhcmVkIGxpc3QsIGVmZmVjdGl2ZWx5IGVtcHR5aW5nIGl0LlxuICAgICAgICAgICAgICogVGhpcyBpcyB0aGUgZXF1aXZhbGVudCBvZiBjYWxsaW5nIGBkZXRhY2goKWAgb24gZWFjaCBvZiBpdHMgZWxlbWVudHMuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHBhcmFtIHtib29sZWFufSBrZWVwRWFjaEFOT2JqZWN0SW5JdHNPd25MaXN0IElmIHNldCB0byBgdHJ1ZWAsIHRoZW4gaW5zdGVhZCBvZiBjb21wbGV0ZWx5IGVtcHR5aW5nIHRoZSBsb2NhbCBsaXN0IG9mIGVhY2ggQXV0b051bWVyaWMgb2JqZWN0cywgZWFjaCBvbmUgb2YgdGhvc2Uga2VlcHMgaXRzZWxmIGluIGl0cyBvd24gbG9jYWwgbGlzdFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBlbXB0eTogKGtlZXBFYWNoQU5PYmplY3RJbkl0c093bkxpc3QgPSBmYWxzZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGluaXRpYWxDb21wbGV0ZUxvY2FsTGlzdCA9IHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3Q7XG5cbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGxvY2FsIGxpc3QgZm9yIGFsbCBvYmplY3RzIGluIGl0XG4gICAgICAgICAgICAgICAgaW5pdGlhbENvbXBsZXRlTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICBpZiAoa2VlcEVhY2hBTk9iamVjdEluSXRzT3duTGlzdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QuX2NyZWF0ZUxvY2FsTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgYU5PYmplY3QuX3NldExvY2FsTGlzdChuZXcgTWFwKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBSZXR1cm4gYW4gYXJyYXkgY29udGFpbmluZyBhbGwgdGhlIEF1dG9OdW1lcmljIERPTSBlbGVtZW50cyB0aGF0IGhhdmUgYmVlbiBpbml0aWFsaXplZCBieSBlYWNoIG90aGVyXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogQHJldHVybnMge0FycmF5PEhUTUxFbGVtZW50Pn1cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZWxlbWVudHM6ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCByZXN1bHQgPSBbXTtcbiAgICAgICAgICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LmZvckVhY2goYU5PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaChhTk9iamVjdC5ub2RlKCkpO1xuICAgICAgICAgICAgICAgIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmV0dXJuIHRoZSBgTWFwYCBvYmplY3QgZGlyZWN0bHlcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtNYXB9XG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGdldExpc3Q6ICgpID0+IHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QsXG5cbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmV0dXJuIHRoZSBudW1iZXIgb2YgZWxlbWVudCBpbiB0aGUgbG9jYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0XG4gICAgICAgICAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzaXplOiAoKSA9PiB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0LnNpemUsXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gQ3JlYXRlIHRoZSBmdW5jdGlvbnMgdGhhdCB3aWxsIGFsbG93IHRvIGNoYW5nZSBlYWNoIHNldHRpbmcgb25lIGJ5IG9uZVxuICAgICAgICAvKipcbiAgICAgICAgICogRm9yIGVhY2ggb3B0aW9ucywgd2UgZGVmaW5lIGlmIHdlIG5lZWQgdG8gcmVmb3JtYXQgdGhlIGVsZW1lbnQgY29udGVudCAoZG9lcyBjaGFuZ2luZyB0aGUgb3B0aW9ucyBzaG91bGQgY2hhbmdlIHRoZSB3YXkgaXRzIHZhbHVlIGlzIGRpc3BsYXllZD8pLlxuICAgICAgICAgKiBJZiB5ZXMsIHRoZW4gd2UgdXNlIHRoZSBgdXBkYXRlKClgIGZvciBmb3JjZSBhIHJlZm9ybWF0LCBvdGhlcndpc2UsIHdlIGp1c3QgdXBkYXRlIHRoZSBgc2V0dGluZ3NgIG9iamVjdC5cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMub3B0aW9ucyA9IHtcbiAgICAgICAgICAgIC8qKlxuICAgICAgICAgICAgICogUmVzZXQgYW55IG9wdGlvbnMgc2V0IHByZXZpb3VzbHksIGJ5IG92ZXJ3cml0aW5nIHRoZW0gd2l0aCB0aGUgZGVmYXVsdCBzZXR0aW5nc1xuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgcmVzZXQgICAgICAgICAgICAgICAgICAgICAgICA6ICgpID0+IHtcbiAgICAgICAgICAgICAgICAvL1RPRE8gQWRkIGEgYHNldHRpbmdzYCBwYXJhbWV0ZXIgc28gdGhhdCB0aGUgdXNlciBjYW4gcmVzZXQgdG8gYSBzcGVjaWZpYyBzZXQgb2Ygc2V0dGluZ3MuIFRoaXMgaXMgZGlmZmVyZW50IHRoYW4gdXBkYXRlIHNpbmNlIGl0IGRyb3BzIGFueSBub24tZGVmYXVsdCBzZXR0aW5ncyBiZWZvcmUgdXNpbmcgdGhvc2UgbmV3IHNldHRpbmdzLlxuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MgPSB7IHJhd1ZhbHVlIDogdGhpcy5kZWZhdWx0UmF3VmFsdWUgfTsgLy8gSGVyZSB3ZSBwYXNzIHRoZSBkZWZhdWx0IHJhd1ZhbHVlIGluIG9yZGVyIHRvIHByZXZlbnQgc2hvd2luZyBhIHdhcm5pbmcgdGhhdCB3ZSB0cnkgdG8gc2V0IGFuIGB1bmRlZmluZWRgIHZhbHVlXG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoQXV0b051bWVyaWMuZGVmYXVsdFNldHRpbmdzKTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGFsbG93RGVjaW1hbFBhZGRpbmcgICAgICAgICAgOiBhbGxvd0RlY2ltYWxQYWRkaW5nID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGFsbG93RGVjaW1hbFBhZGRpbmcgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Gb2N1cyAgICAgICAgIDogY2FyZXRQb3NpdGlvbk9uRm9jdXMgPT4geyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPSBjYXJldFBvc2l0aW9uT25Gb2N1cztcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNyZWF0ZUxvY2FsTGlzdCAgICAgICAgICAgICAgOiBjcmVhdGVMb2NhbExpc3QgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuY3JlYXRlTG9jYWxMaXN0ID0gY3JlYXRlTG9jYWxMaXN0O1xuXG4gICAgICAgICAgICAgICAgLy8gRGVsZXRlIHRoZSBsb2NhbCBsaXN0IHdoZW4gdGhpcyBpcyBzZXQgdG8gYGZhbHNlYCwgY3JlYXRlIGl0IGlmIHRoaXMgaXMgc2V0IHRvIGB0cnVlYCBhbmQgdGhlcmUgaXMgbm90IHByZS1leGlzdGluZyBsaXN0XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3JlYXRlTG9jYWxMaXN0KSB7XG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5faGFzTG9jYWxMaXN0KCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX2NyZWF0ZUxvY2FsTGlzdCgpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fZGVsZXRlTG9jYWxMaXN0KCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY3VycmVuY3lTeW1ib2wgICAgICAgICAgICAgICA6IGN1cnJlbmN5U3ltYm9sID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGN1cnJlbmN5U3ltYm9sIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgICAgICA6IGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50IH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVjaW1hbENoYXJhY3RlciAgICAgICAgICAgICA6IGRlY2ltYWxDaGFyYWN0ZXIgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgZGVjaW1hbENoYXJhY3RlciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSAgOiBkZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlID0gZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgLyoqXG4gICAgICAgICAgICAgKiBVcGRhdGUgdGhlIGRlY2ltYWwgcGxhY2VzIGdsb2JhbGx5LCB3aGljaCBtZWFucyB0aGlzIG92ZXJyaWRlIGFueSBwcmV2aW91c2x5IHNldCBudW1iZXIgb2YgZGVjaW1hbCBzaG93biBvbiBmb2N1cywgb24gYmx1ciwgb3IgaW4gdGhlIHJhdyB2YWx1ZS5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBAcGFyYW0ge2ludH0gZGVjaW1hbFBsYWNlc1xuICAgICAgICAgICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzICAgICAgICAgICAgICAgIDogZGVjaW1hbFBsYWNlcyA9PiB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZygnVXNpbmcgYG9wdGlvbnMuZGVjaW1hbFBsYWNlcygpYCBpbnN0ZWFkIG9mIGNhbGxpbmcgdGhlIHNwZWNpZmljIGBvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSgpYCwgYG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cygpYCBhbmQgYG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyKClgIG1ldGhvZHMgd2lsbCByZXNldCB0aG9zZSBvcHRpb25zLlxcblBsZWFzZSBjYWxsIHRoZSBzcGVjaWZpYyBtZXRob2RzIGlmIHlvdSBkbyBub3Qgd2FudCB0byByZXNldCB0aG9zZS4nLCB0aGlzLnNldHRpbmdzLnNob3dXYXJuaW5ncyk7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBkZWNpbWFsUGxhY2VzIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlICAgICAgICA6IGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9PiB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIgICAgIDogZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgICAgOiBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkZWZhdWx0VmFsdWVPdmVycmlkZSAgICAgICAgIDogZGVmYXVsdFZhbHVlT3ZlcnJpZGUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgZGVmYXVsdFZhbHVlT3ZlcnJpZGUgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkaWdpdGFsR3JvdXBTcGFjaW5nICAgICAgICAgIDogZGlnaXRhbEdyb3VwU3BhY2luZyA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBkaWdpdGFsR3JvdXBTcGFjaW5nIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZGlnaXRHcm91cFNlcGFyYXRvciAgICAgICAgICA6IGRpZ2l0R3JvdXBTZXBhcmF0b3IgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgZGlnaXRHcm91cFNlcGFyYXRvciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGRpdmlzb3JXaGVuVW5mb2N1c2VkICAgICAgICAgOiBkaXZpc29yV2hlblVuZm9jdXNlZCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBkaXZpc29yV2hlblVuZm9jdXNlZCB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGVtcHR5SW5wdXRCZWhhdmlvciAgICAgICAgICAgOiBlbXB0eUlucHV0QmVoYXZpb3IgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJhd1ZhbHVlID09PSBudWxsICYmIGVtcHR5SW5wdXRCZWhhdmlvciAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubnVsbCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2UgOiBpZiB0aGUgY3VycmVudCBgcmF3VmFsdWVgIGlzIGBudWxsYCBhbmQgdGhlIGBlbXB0eUlucHV0QmVoYXZpb3JgIGlzIGNoYW5nZWQgdG8gc29tZXRoaW5nIGVsc2UgdGhhbiBgJ251bGwnYCwgdGhlbiBpdCBtYWtlcyB0aGF0IGByYXdWYWx1ZWAgaW52YWxpZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gSGVyZSB3ZSBjYW4gZWl0aGVyIHByZXZlbnQgdGhlIG9wdGlvbiB1cGRhdGUgYW5kIHRocm93IGFuIGVycm9yLCBvciBzdGlsbCBhY2NlcHQgdGhlIG9wdGlvbiB1cGRhdGUgYW5kIHVwZGF0ZSB0aGUgdmFsdWUgZnJvbSBgbnVsbGAgdG8gYCcnYC5cbiAgICAgICAgICAgICAgICAgICAgLy8gV2UgY2Fubm90IGtlZXAgYHJhd1ZhbHVlYCB0byBgbnVsbGAgc2luY2UgaWYgYGVtcHR5SW5wdXRCZWhhdmlvcmAgaXMgbm90IHNldCB0byBgbnVsbGAsIGxvdHMgb2YgZnVuY3Rpb24gYXNzdW1lIGByYXdWYWx1ZWAgaXMgYSBzdHJpbmcuXG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFlvdSBhcmUgdHJ5aW5nIHRvIG1vZGlmeSB0aGUgXFxgZW1wdHlJbnB1dEJlaGF2aW9yXFxgIG9wdGlvbiB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gXFxgJ251bGwnXFxgICgke2VtcHR5SW5wdXRCZWhhdmlvcn0pLCBidXQgdGhlIGVsZW1lbnQgcmF3IHZhbHVlIGlzIGN1cnJlbnRseSBzZXQgdG8gXFxgbnVsbFxcYC4gVGhpcyB3b3VsZCByZXN1bHQgaW4gYW4gaW52YWxpZCBcXGByYXdWYWx1ZVxcYC4gSW4gb3JkZXIgdG8gZml4IHRoYXQsIHRoZSBlbGVtZW50IHZhbHVlIGhhcyBiZWVuIGNoYW5nZWQgdG8gdGhlIGVtcHR5IHN0cmluZyBcXGAnJ1xcYC5gLCB0aGlzLnNldHRpbmdzLnNob3dXYXJuaW5ncyk7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMucmF3VmFsdWUgPSAnJztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGVtcHR5SW5wdXRCZWhhdmlvciB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZhaWxPblVua25vd25PcHRpb24gICAgICAgICAgOiBmYWlsT25Vbmtub3duT3B0aW9uID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmZhaWxPblVua25vd25PcHRpb24gPSBmYWlsT25Vbmtub3duT3B0aW9uOyAvL0ZJWE1FIHRlc3QgdGhpc1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZm9ybWF0T25QYWdlTG9hZCAgICAgICAgICAgICA6IGZvcm1hdE9uUGFnZUxvYWQgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuZm9ybWF0T25QYWdlTG9hZCA9IGZvcm1hdE9uUGFnZUxvYWQ7IC8vRklYTUUgdGVzdCB0aGlzXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBoaXN0b3J5U2l6ZSAgICAgICAgICAgICAgICAgIDogaGlzdG9yeVNpemUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuaGlzdG9yeVNpemUgPSBoaXN0b3J5U2l6ZTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGlzQ2FuY2VsbGFibGUgICAgICAgICAgICAgICAgOiBpc0NhbmNlbGxhYmxlID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmlzQ2FuY2VsbGFibGUgPSBpc0NhbmNlbGxhYmxlOyAvL0ZJWE1FIHRlc3QgdGhpc1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbGVhZGluZ1plcm8gICAgICAgICAgICAgICAgICA6IGxlYWRpbmdaZXJvID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IGxlYWRpbmdaZXJvIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbWF4aW11bVZhbHVlICAgICAgICAgICAgICAgICA6IG1heGltdW1WYWx1ZSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBtYXhpbXVtVmFsdWUgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBtaW5pbXVtVmFsdWUgICAgICAgICAgICAgICAgIDogbWluaW11bVZhbHVlID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IG1pbmltdW1WYWx1ZSB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG1vZGlmeVZhbHVlT25XaGVlbCAgICAgICAgICAgOiBtb2RpZnlWYWx1ZU9uV2hlZWwgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MubW9kaWZ5VmFsdWVPbldoZWVsID0gbW9kaWZ5VmFsdWVPbldoZWVsOyAvL0ZJWE1FIHRlc3QgdGhpc1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIgICA6IG5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IG5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50IH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbm9FdmVudExpc3RlbmVycyAgICAgICAgICAgICA6IG5vRXZlbnRMaXN0ZW5lcnMgPT4geyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICAgICAgICAgIGlmIChub0V2ZW50TGlzdGVuZXJzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5vRXZlbnRMaXN0ZW5lcnMubm9FdmVudHMgJiYgdGhpcy5zZXR0aW5ncy5ub0V2ZW50TGlzdGVuZXJzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5vRXZlbnRMaXN0ZW5lcnMuYWRkRXZlbnRzKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgZXZlbnRzIG9uY2VcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IG5vRXZlbnRMaXN0ZW5lcnMgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBvbkludmFsaWRQYXN0ZSAgICAgICAgICAgICAgIDogb25JbnZhbGlkUGFzdGUgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Mub25JbnZhbGlkUGFzdGUgPSBvbkludmFsaWRQYXN0ZTsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdCAgICAgICAgICAgICAgICAgOiBvdXRwdXRGb3JtYXQgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Mub3V0cHV0Rm9ybWF0ID0gb3V0cHV0Rm9ybWF0O1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgb3ZlcnJpZGVNaW5NYXhMaW1pdHMgICAgICAgICA6IG92ZXJyaWRlTWluTWF4TGltaXRzID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IG92ZXJyaWRlTWluTWF4TGltaXRzIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcmF3VmFsdWVEaXZpc29yICAgICAgICAgICAgICA6IHJhd1ZhbHVlRGl2aXNvciA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyByYXdWYWx1ZURpdmlzb3IgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICByZWFkT25seSAgICAgICAgICAgICAgICAgICAgIDogcmVhZE9ubHkgPT4geyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MucmVhZE9ubHkgPSByZWFkT25seTtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRSZWFkT25seSgpO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgcm91bmRpbmdNZXRob2QgICAgICAgICAgICAgICA6IHJvdW5kaW5nTWV0aG9kID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IHJvdW5kaW5nTWV0aG9kIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSAgICA6IHNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHN5bWJvbFdoZW5VbmZvY3VzZWQgICAgICAgICAgOiBzeW1ib2xXaGVuVW5mb2N1c2VkID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IHN5bWJvbFdoZW5VbmZvY3VzZWQgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzZWxlY3ROdW1iZXJPbmx5ICAgICAgICAgICAgIDogc2VsZWN0TnVtYmVyT25seSA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5zZWxlY3ROdW1iZXJPbmx5ID0gc2VsZWN0TnVtYmVyT25seTsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNlbGVjdE9uRm9jdXMgICAgICAgICAgICAgICAgOiBzZWxlY3RPbkZvY3VzID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLnNlbGVjdE9uRm9jdXMgPSBzZWxlY3RPbkZvY3VzOyAvL0ZJWE1FIHRlc3QgdGhpc1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2VyaWFsaXplU3BhY2VzICAgICAgICAgICAgICA6IHNlcmlhbGl6ZVNwYWNlcyA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5zZXJpYWxpemVTcGFjZXMgPSBzZXJpYWxpemVTcGFjZXM7IC8vRklYTUUgdGVzdCB0aGlzXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBzaG93T25seU51bWJlcnNPbkZvY3VzICAgICAgIDogc2hvd09ubHlOdW1iZXJzT25Gb2N1cyA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy51cGRhdGUoeyBzaG93T25seU51bWJlcnNPbkZvY3VzIH0pO1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2hvd1Bvc2l0aXZlU2lnbiAgICAgICAgICAgICA6IHNob3dQb3NpdGl2ZVNpZ24gPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgc2hvd1Bvc2l0aXZlU2lnbiB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNob3dXYXJuaW5ncyAgICAgICAgICAgICAgICAgOiBzaG93V2FybmluZ3MgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Muc2hvd1dhcm5pbmdzID0gc2hvd1dhcm5pbmdzOyAvL0ZJWE1FIHRlc3QgdGhpc1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc3R5bGVSdWxlcyAgICAgICAgICAgICAgICAgICA6IHN0eWxlUnVsZXMgPT4ge1xuICAgICAgICAgICAgICAgIHRoaXMudXBkYXRlKHsgc3R5bGVSdWxlcyB9KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHN1ZmZpeFRleHQgICAgICAgICAgICAgICAgICAgOiBzdWZmaXhUZXh0ID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnVwZGF0ZSh7IHN1ZmZpeFRleHQgfSk7XG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB1bmZvcm1hdE9uSG92ZXIgICAgICAgICAgICAgIDogdW5mb3JtYXRPbkhvdmVyID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLnVuZm9ybWF0T25Ib3ZlciA9IHVuZm9ybWF0T25Ib3ZlcjsgLy9GSVhNRSB0ZXN0IHRoaXNcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHVuZm9ybWF0T25TdWJtaXQgICAgICAgICAgICAgOiB1bmZvcm1hdE9uU3VibWl0ID0+IHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLnVuZm9ybWF0T25TdWJtaXQgPSB1bmZvcm1hdE9uU3VibWl0OyAvL0ZJWE1FIHRlc3QgdGhpc1xuXG4gICAgICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgd2hlZWxTdGVwICAgICAgICAgICAgICAgICAgICA6IHdoZWVsU3RlcCA9PiB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy53aGVlbFN0ZXAgPSB3aGVlbFN0ZXA7IC8vRklYTUUgdGVzdCB0aGlzXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBhdXRvTnVtZXJpYyB2ZXJzaW9uIG51bWJlciAoZm9yIGRlYnVnZ2luZyBwdXJwb3NlKVxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgdmVyc2lvbigpIHtcbiAgICAgICAgcmV0dXJuICc0LjAuMic7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGFrZSB0aGUgcGFyYW1ldGVycyBnaXZlbiB0byB0aGUgQXV0b051bWVyaWMgb2JqZWN0LCBhbmQgb3V0cHV0IHRoZSB0aHJlZSB2YXJpYWJsZXMgdGhhdCBhcmUgbmVlZGVkIHRvIGZpbmlzaCBpbml0aWFsaXppbmcgaXQgOlxuICAgICAqIC0gZG9tRWxlbWVudCA6IFRoZSB0YXJnZXQgRE9NIGVsZW1lbnRcbiAgICAgKiAtIGluaXRpYWxWYWx1ZSA6IFRoZSBpbml0aWFsIHZhbHVlLCBvciBgbnVsbGAgaWYgbm9uZSBpcyBnaXZlblxuICAgICAqIC0gdXNlck9wdGlvbnMgOiBUaGUgb3B0aW9uIG9iamVjdFxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R8QXJyYXl8bnVtYmVyfHN0cmluZ30gYXJnMVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fEFycmF5fG51bWJlcnxzdHJpbmd8bnVsbH0gYXJnMlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fEFycmF5fG51bWJlcnxzdHJpbmd8bnVsbH0gYXJnM1xuICAgICAqIEByZXR1cm5zIHt7ZG9tRWxlbWVudDogKiwgaW5pdGlhbFZhbHVlOiAqLCB1c2VyT3B0aW9uczogKn19XG4gICAgICogQHRocm93c1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9zZXRBcmd1bWVudHNWYWx1ZXMoYXJnMSwgYXJnMiwgYXJnMykge1xuICAgICAgICAvLyBCYXNpYyBjaGVjayBvbiB0aGUgYXJndW1lbnQgY291bnRcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChhcmcxKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcignQXQgbGVhc3Qgb25lIHZhbGlkIHBhcmFtZXRlciBpcyBuZWVkZWQgaW4gb3JkZXIgdG8gaW5pdGlhbGl6ZSBhbiBBdXRvTnVtZXJpYyBvYmplY3QnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFByZXBhcmUgdGhlIGFyZ3VtZW50cyBpbiBvcmRlciB0byBjcmVhdGUgdGhlIEF1dG9OdW1lcmljIG9iamVjdCB3aXRoIHRoZSByaWdodCB2YWx1ZXNcbiAgICAgICAgLy8gVGVzdCB0aGUgYXJndW1lbnQgdHlwZXNcbiAgICAgICAgY29uc3QgaXNBcmcxRWxlbWVudCA9IEF1dG9OdW1lcmljSGVscGVyLmlzRWxlbWVudChhcmcxKTtcbiAgICAgICAgY29uc3QgaXNBcmcxU3RyaW5nID0gQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcoYXJnMSk7XG5cbiAgICAgICAgY29uc3QgaXNBcmcyT2JqZWN0ID0gQXV0b051bWVyaWNIZWxwZXIuaXNPYmplY3QoYXJnMik7XG4gICAgICAgIGNvbnN0IGlzQXJnMkFycmF5ID0gQXJyYXkuaXNBcnJheShhcmcyKSAmJiBhcmcyLmxlbmd0aCA+IDA7XG4gICAgICAgIGNvbnN0IGlzQXJnMk51bWJlciA9IEF1dG9OdW1lcmljSGVscGVyLmlzTnVtYmVyT3JBcmFiaWMoYXJnMikgfHwgYXJnMiA9PT0gJyc7XG4gICAgICAgIGNvbnN0IGlzQXJnMlByZURlZmluZWRPcHRpb25OYW1lID0gdGhpcy5faXNQcmVEZWZpbmVkT3B0aW9uVmFsaWQoYXJnMik7XG4gICAgICAgIGNvbnN0IGlzQXJnMk51bGwgPSBBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoYXJnMik7XG4gICAgICAgIGNvbnN0IGlzQXJnMkVtcHR5U3RyaW5nID0gQXV0b051bWVyaWNIZWxwZXIuaXNFbXB0eVN0cmluZyhhcmcyKTtcblxuICAgICAgICBjb25zdCBpc0FyZzNPYmplY3QgPSBBdXRvTnVtZXJpY0hlbHBlci5pc09iamVjdChhcmczKTtcbiAgICAgICAgY29uc3QgaXNBcmczQXJyYXkgPSBBcnJheS5pc0FycmF5KGFyZzMpICYmIGFyZzMubGVuZ3RoID4gMDtcbiAgICAgICAgY29uc3QgaXNBcmczTnVsbCA9IEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChhcmczKTtcbiAgICAgICAgY29uc3QgaXNBcmczUHJlRGVmaW5lZE9wdGlvbk5hbWUgPSB0aGlzLl9pc1ByZURlZmluZWRPcHRpb25WYWxpZChhcmczKTtcblxuICAgICAgICAvLyBHaXZlbiB0aGUgcGFyYW1ldGVycyBwYXNzZWQsIHNvcnQgdGhlIGRhdGEgYW5kIHJldHVybiBhIHN0YWJsZSBzdGF0ZSBiZWZvcmUgdGhlIGluaXRpYWxpemF0aW9uXG4gICAgICAgIGxldCBkb21FbGVtZW50O1xuICAgICAgICBsZXQgdXNlck9wdGlvbnM7XG4gICAgICAgIGxldCBpbml0aWFsVmFsdWU7XG5cbiAgICAgICAgLy9UT0RPIFNpbXBsaWZ5IHRob3NlIHRlc3RzIC0tPlxuICAgICAgICBpZiAoaXNBcmcxRWxlbWVudCAmJiBpc0FyZzJOdWxsICYmIGlzQXJnM051bGwpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50KTsgLy8gV2l0aCB0aGUgZGVmYXVsdCBvcHRpb25zXG4gICAgICAgICAgICBkb21FbGVtZW50ID0gYXJnMTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IG51bGw7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxRWxlbWVudCAmJiBpc0FyZzJOdW1iZXIgJiYgaXNBcmczTnVsbCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIDEyMzQ1Ljc4OSk7IC8vIFdpdGggdGhlIGRlZmF1bHQgb3B0aW9ucywgYW5kIGFuIGluaXRpYWwgdmFsdWVcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAnMTIzNDUuNzg5Jyk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gYXJnMTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGFyZzI7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IG51bGw7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxRWxlbWVudCAmJiBpc0FyZzJPYmplY3QgJiYgaXNBcmczTnVsbCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIHsgb3B0aW9ucyB9KTsgLy8gV2l0aCBvbmUgb3B0aW9uIG9iamVjdFxuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGFyZzE7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSBhcmcyO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMUVsZW1lbnQgJiYgaXNBcmcyUHJlRGVmaW5lZE9wdGlvbk5hbWUgJiYgaXNBcmczTnVsbCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsICdldXJvUG9zJyk7IC8vIFdpdGggb25lIHByZS1kZWZpbmVkIG9wdGlvbiBuYW1lXG4gICAgICAgICAgICBkb21FbGVtZW50ID0gYXJnMTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IHRoaXMuX2dldE9wdGlvbk9iamVjdChhcmcyKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFFbGVtZW50ICYmIGlzQXJnMkFycmF5ICYmIGlzQXJnM051bGwpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCBbeyBvcHRpb25zMSB9LCB7IG9wdGlvbnMyIH1dKTsgLy8gV2l0aCBtdWx0aXBsZSBvcHRpb24gb2JqZWN0cyAodGhlIGxhdGVzdCBvcHRpb24gb3ZlcndyaXRpbmcgdGhlIHByZXZpb3VzIG9uZXMpXG4gICAgICAgICAgICBkb21FbGVtZW50ID0gYXJnMTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IHRoaXMubWVyZ2VPcHRpb25zKGFyZzIpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMUVsZW1lbnQgJiYgKGlzQXJnMk51bGwgfHwgaXNBcmcyRW1wdHlTdHJpbmcpICYmIGlzQXJnM09iamVjdCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIG51bGwsIHsgb3B0aW9ucyB9KTsgLy8gV2l0aCBvbmUgb3B0aW9uIG9iamVjdFxuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGFyZzE7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSBhcmczO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMUVsZW1lbnQgJiYgKGlzQXJnMk51bGwgfHwgaXNBcmcyRW1wdHlTdHJpbmcpICYmIGlzQXJnM0FycmF5KSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgbnVsbCwgW3sgb3B0aW9uczEgfSwgeyBvcHRpb25zMiB9XSk7IC8vIFdpdGggbXVsdGlwbGUgb3B0aW9uIG9iamVjdHNcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBhcmcxO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gdGhpcy5tZXJnZU9wdGlvbnMoYXJnMyk7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIGlzQXJnMk51bGwgJiYgaXNBcmczTnVsbCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0Jyk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IG51bGw7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIGlzQXJnMk9iamVjdCAmJiBpc0FyZzNOdWxsKSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCB7IG9wdGlvbnMgfSk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IGFyZzI7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIGlzQXJnMlByZURlZmluZWRPcHRpb25OYW1lICYmIGlzQXJnM051bGwpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsICdldXJvUG9zJyk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IG51bGw7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IHRoaXMuX2dldE9wdGlvbk9iamVjdChhcmcyKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFTdHJpbmcgJiYgaXNBcmcyQXJyYXkgJiYgaXNBcmczTnVsbCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgW3sgb3B0aW9uczEgfSwgeyBvcHRpb25zMiB9XSk7IC8vIFdpdGggbXVsdGlwbGUgb3B0aW9uIG9iamVjdHNcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGFyZzEpO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gdGhpcy5tZXJnZU9wdGlvbnMoYXJnMik7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIChpc0FyZzJOdWxsIHx8IGlzQXJnMkVtcHR5U3RyaW5nKSAmJiBpc0FyZzNPYmplY3QpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIG51bGwsIHsgb3B0aW9ucyB9KTtcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGFyZzEpO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gbnVsbDtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gYXJnMztcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFTdHJpbmcgJiYgKGlzQXJnMk51bGwgfHwgaXNBcmcyRW1wdHlTdHJpbmcpICYmIGlzQXJnM0FycmF5KSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCBudWxsLCBbeyBvcHRpb25zMSB9LCB7IG9wdGlvbnMyIH1dKTsgLy8gV2l0aCBtdWx0aXBsZSBvcHRpb24gb2JqZWN0c1xuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGRvY3VtZW50LnF1ZXJ5U2VsZWN0b3IoYXJnMSk7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBudWxsO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSB0aGlzLm1lcmdlT3B0aW9ucyhhcmczKTtcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFTdHJpbmcgJiYgaXNBcmcyTnVtYmVyICYmIGlzQXJnM051bGwpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIDEyMzQ1Ljc4OSk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAnMTIzNDUuNzg5Jyk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAnJyk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGFyZzI7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IG51bGw7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIGlzQXJnMk51bWJlciAmJiBpc0FyZzNPYmplY3QpIHtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIDEyMzQ1Ljc4OSwgeyBvcHRpb25zIH0pO1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgJzEyMzQ1Ljc4OScsIHsgb3B0aW9ucyB9KTtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYygnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsICcnLCB7IG9wdGlvbnMgfSk7XG4gICAgICAgICAgICBkb21FbGVtZW50ID0gZG9jdW1lbnQucXVlcnlTZWxlY3RvcihhcmcxKTtcbiAgICAgICAgICAgIGluaXRpYWxWYWx1ZSA9IGFyZzI7XG4gICAgICAgICAgICB1c2VyT3B0aW9ucyA9IGFyZzM7XG4gICAgICAgIH0gZWxzZSBpZiAoaXNBcmcxU3RyaW5nICYmIGlzQXJnMk51bWJlciAmJiBpc0FyZzNQcmVEZWZpbmVkT3B0aW9uTmFtZSkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgMTIzNDUuNzg5LCAnZXVyb1BvcycpO1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKCcubXlDc3NDbGFzcyA+IGlucHV0JywgJzEyMzQ1Ljc4OScsICdldXJvUG9zJyk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoJy5teUNzc0NsYXNzID4gaW5wdXQnLCAnJywgJ2V1cm9Qb3MnKTtcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGFyZzEpO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gYXJnMjtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gdGhpcy5fZ2V0T3B0aW9uT2JqZWN0KGFyZzMpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMUVsZW1lbnQgJiYgaXNBcmcyTnVtYmVyICYmIGlzQXJnM09iamVjdCkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIDEyMzQ1Ljc4OSwgeyBvcHRpb25zIH0pO1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsICcxMjM0NS43ODknLCB7IG9wdGlvbnMgfSk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgJycsIHsgb3B0aW9ucyB9KTtcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBhcmcxO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gYXJnMjtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gYXJnMztcbiAgICAgICAgfSBlbHNlIGlmIChpc0FyZzFFbGVtZW50ICYmIGlzQXJnMk51bWJlciAmJiBpc0FyZzNQcmVEZWZpbmVkT3B0aW9uTmFtZSkge1xuICAgICAgICAgICAgLy8gbmV3IEF1dG9OdW1lcmljKGRvbUVsZW1lbnQsIDEyMzQ1Ljc4OSwgJ2V1cm9Qb3MnKTtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAnMTIzNDUuNzg5JywgJ2V1cm9Qb3MnKTtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAnJywgJ2V1cm9Qb3MnKTtcbiAgICAgICAgICAgIGRvbUVsZW1lbnQgPSBhcmcxO1xuICAgICAgICAgICAgaW5pdGlhbFZhbHVlID0gYXJnMjtcbiAgICAgICAgICAgIHVzZXJPcHRpb25zID0gdGhpcy5fZ2V0T3B0aW9uT2JqZWN0KGFyZzMpO1xuICAgICAgICB9IGVsc2UgaWYgKGlzQXJnMUVsZW1lbnQgJiYgaXNBcmcyTnVtYmVyICYmIGlzQXJnM0FycmF5KSB7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgMTIzNDUuNzg5LCBbeyBvcHRpb25zMSB9LCB7IG9wdGlvbnMyIH1dKTtcbiAgICAgICAgICAgIC8vIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCAnMTIzNDUuNzg5JywgW3sgb3B0aW9uczEgfSwgeyBvcHRpb25zMiB9XSk7XG4gICAgICAgICAgICAvLyBuZXcgQXV0b051bWVyaWMoZG9tRWxlbWVudCwgJycsIFt7IG9wdGlvbnMxIH0sIHsgb3B0aW9uczIgfV0pO1xuICAgICAgICAgICAgZG9tRWxlbWVudCA9IGFyZzE7XG4gICAgICAgICAgICBpbml0aWFsVmFsdWUgPSBhcmcyO1xuICAgICAgICAgICAgdXNlck9wdGlvbnMgPSB0aGlzLm1lcmdlT3B0aW9ucyhhcmczKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBwYXJhbWV0ZXJzIGdpdmVuIHRvIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgYXJlIG5vdCB2YWxpZCwgJyR7YXJnMX0nLCAnJHthcmcyfScgYW5kICcke2FyZzN9JyBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoZG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBzZWxlY3RvciAnJHthcmcxfScgZGlkIG5vdCBzZWxlY3QgYW55IHZhbGlkIERPTSBlbGVtZW50LiBQbGVhc2UgY2hlY2sgb24gd2hpY2ggZWxlbWVudCB5b3UgY2FsbGVkIEF1dG9OdW1lcmljLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHsgZG9tRWxlbWVudCwgaW5pdGlhbFZhbHVlLCB1c2VyT3B0aW9ucyB9O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1lcmdlIHRoZSBvcHRpb24gb2JqZWN0cyBmb3VuZCBpbiB0aGUgZ2l2ZW4gYXJyYXkgYG9wdGlvbnNBcnJheWAuXG4gICAgICogSWYgYSBgc3RyaW5nYCBpcyBmb3VuZCwgdGhlbiB3ZSB0cnkgdG8gZ2V0IHRoZSByZWxhdGVkIHByZS1kZWZpbmVkIG9wdGlvbiB1c2luZyB0aGF0IHN0cmluZyBhcyBpdHMgbmFtZS5cbiAgICAgKiBXaGVuIG1lcmdpbmcgdGhlIG9wdGlvbnMsIHRoZSBsYXRlc3Qgb3B0aW9uIG92ZXJ3cml0ZSBhbnkgcHJldmlvdXNseSBzZXQuIFRoaXMgYWxsb3dzIHRvIGZpbmUgdHVuZSBhIHByZS1kZWZpbmVkIG9wdGlvbiBmb3IgaW5zdGFuY2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5PG9iamVjdHxzdHJpbmc+fSBvcHRpb25zQXJyYXlcbiAgICAgKiBAcmV0dXJucyB7e319XG4gICAgICovXG4gICAgc3RhdGljIG1lcmdlT3B0aW9ucyhvcHRpb25zQXJyYXkpIHtcbiAgICAgICAgLy8gVGhpcyBhbGxvd3MgdGhlIHVzZXIgdG8gdXNlIG11bHRpcGxlIG9wdGlvbnMgKHN0cmluZ3Mgb3Igb2JqZWN0cykgaW4gYW4gYXJyYXksIGFuZCBvdmVyd3JpdGUgdGhlIHByZXZpb3VzIG9uZSB3aXRoIHRoZSBuZXh0IG9wdGlvbiBlbGVtZW50IDsgdGhpcyBpcyB1c2VmdWwgdG8gdHVuZSB0aGUgd2FudGVkIGZvcm1hdFxuICAgICAgICBjb25zdCBtZXJnZWRPcHRpb25zID0ge307XG4gICAgICAgIG9wdGlvbnNBcnJheS5mb3JFYWNoKG9wdGlvbk9iamVjdE9yUHJlZGVmaW5lZE9wdGlvblN0cmluZyA9PiB7XG4gICAgICAgICAgICBPYmplY3QuYXNzaWduKG1lcmdlZE9wdGlvbnMsIHRoaXMuX2dldE9wdGlvbk9iamVjdChvcHRpb25PYmplY3RPclByZWRlZmluZWRPcHRpb25TdHJpbmcpKTtcbiAgICAgICAgfSk7XG5cbiAgICAgICAgcmV0dXJuIG1lcmdlZE9wdGlvbnM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gcHJlLWRlZmluZWQgb3B0aW9uIG5hbWUgaXMgYW4gYXR0cmlidXRlIG9mIHRoZSBgQXV0b051bWVyaWMucHJlZGVmaW5lZE9wdGlvbnNgIG9iamVjdFxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHByZURlZmluZWRPcHRpb25OYW1lXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2lzUHJlRGVmaW5lZE9wdGlvblZhbGlkKHByZURlZmluZWRPcHRpb25OYW1lKSB7XG4gICAgICAgIHJldHVybiBBdXRvTnVtZXJpYy5wcmVkZWZpbmVkT3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShwcmVEZWZpbmVkT3B0aW9uTmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGFuIG9wdGlvbiBvYmplY3QgYmFzZWQgb24gdGhlIGdpdmVuIHBhcmFtZXRlci5cbiAgICAgKiBJZiBgb3B0aW9uT2JqZWN0T3JQcmVkZWZpbmVkTmFtZWAgaXMgYXMgc3RyaW5nLCB0aGVuIHdlIHJldHJpZXZlIHRoZSBwcmUtZGVmaW5lZCBvcHRpb24gb2JqZWN0LCBpZiBpdCdzIGFuIG9iamVjdCwgd2UgdXNlIGl0IGFzIGlzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R8c3RyaW5nfSBvcHRpb25PYmplY3RPclByZWRlZmluZWROYW1lXG4gICAgICogQHJldHVybnMge29iamVjdH1cbiAgICAgKi9cbiAgICBzdGF0aWMgX2dldE9wdGlvbk9iamVjdChvcHRpb25PYmplY3RPclByZWRlZmluZWROYW1lKSB7XG4gICAgICAgIGxldCBvcHRpb25zO1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9uT2JqZWN0T3JQcmVkZWZpbmVkTmFtZSkpIHtcbiAgICAgICAgICAgIG9wdGlvbnMgPSBBdXRvTnVtZXJpYy5nZXRQcmVkZWZpbmVkT3B0aW9ucygpW29wdGlvbk9iamVjdE9yUHJlZGVmaW5lZE5hbWVdO1xuICAgICAgICAgICAgaWYgKG9wdGlvbnMgPT09IHZvaWQoMCkgfHwgb3B0aW9ucyA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBnaXZlbiBwcmUtZGVmaW5lZCBuYW1lIGRvZXMgbm90IGV4aXN0LCB3YXJuIHRoYXQgc29tZXRoaW5nIGlzIHdyb25nLCBhbmQgY29udGludWUgdGhlIGV4ZWN1dGlvbiBvZiB0aGUgaW5pdGlhbGl6YXRpb25cbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBUaGUgZ2l2ZW4gcHJlLWRlZmluZWQgb3B0aW9uIFske29wdGlvbk9iamVjdE9yUHJlZGVmaW5lZE5hbWV9XSBpcyBub3QgcmVjb2duaXplZCBieSBhdXRvTnVtZXJpYy4gUGxlYXNlIGNoZWNrIHRoYXQgcHJlLWRlZmluZWQgb3B0aW9uIG5hbWUuYCwgdHJ1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7IC8vIEEgYHNldHRpbmdzYCBvYmplY3RcbiAgICAgICAgICAgIG9wdGlvbnMgPSBvcHRpb25PYmplY3RPclByZWRlZmluZWROYW1lO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG9wdGlvbnM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2F2ZSB0aGUgaW5pdGlhbCBlbGVtZW50IHZhbHVlcyBmb3IgbGF0ZXIgdXNlIGluIHRoZSBwcmlzdGluZSB0ZXN0LlxuICAgICAqIFRob3NlIHZhbHVlcyBhcmUgOlxuICAgICAqIC0gdGhlIGh0bWwgYXR0cmlidXRlIChpZS4gPGlucHV0IHZhbHVlPSc0Mic+KSwgYW5kXG4gICAgICogLSB0aGUgc2NyaXB0IGB2YWx1ZWAgKGllLiBgbGV0IGRvbUVsZW1lbnQudmFsdWVgKVxuICAgICAqXG4gICAgICogQHBhcmFtIHtudWxsfG51bWJlcnxzdHJpbmd9IGluaXRpYWxWYWx1ZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NhdmVJbml0aWFsVmFsdWVzKGluaXRpYWxWYWx1ZSkge1xuICAgICAgICAvLyBLZWVwIHRoZSB2ZXJ5IGZpcnN0IGluaXRpYWwgdmFsdWVzIChpbiB0aGUgaHRtbCBhdHRyaWJ1dGUgYW5kIHNldCBieSB0aGUgc2NyaXB0KS4gVGhpcyBpcyBuZWVkZWQgdG8gY2hlY2sgaWYgdGhlIGVsZW1lbnQgaXMgcHJpc3RpbmUuXG4gICAgICAgIC8vIFNhdmUgdGhlIGh0bWwgYXR0cmlidXRlICd2YWx1ZSdcbiAgICAgICAgdGhpcy5pbml0aWFsVmFsdWVIdG1sQXR0cmlidXRlID0gdGhpcy5kb21FbGVtZW50LmdldEF0dHJpYnV0ZSgndmFsdWUnKTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbCh0aGlzLmluaXRpYWxWYWx1ZUh0bWxBdHRyaWJ1dGUpKSB7XG4gICAgICAgICAgICAvLyBTZXQgdGhlIGRlZmF1bHQgZW1wdHkgdmFsdWUgYXR0cmlidXRlIGluc3RlYWQgb2YgYG51bGxgLCBzaW5jZSBpZiB0aGUgaW5pdGlhbCB2YWx1ZSBpcyBudWxsLCB0aGUgZW1wdHkgc3RyaW5nIGlzIHVzZWRcbiAgICAgICAgICAgIHRoaXMuaW5pdGlhbFZhbHVlSHRtbEF0dHJpYnV0ZSA9ICcnO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2F2ZSB0aGUgJ3NjcmlwdCcgdmFsdWVcbiAgICAgICAgdGhpcy5pbml0aWFsVmFsdWUgPSBpbml0aWFsVmFsdWU7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodGhpcy5pbml0aWFsVmFsdWUpKSB7XG4gICAgICAgICAgICAvLyBTYW1lIGFzIGFib3ZlXG4gICAgICAgICAgICB0aGlzLmluaXRpYWxWYWx1ZSA9ICcnO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYWxsIHRoZSBldmVudCBsaXN0ZW5lcnMgZm9yIHRoZSBnaXZlbiBET00gZWxlbWVudFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2NyZWF0ZUV2ZW50TGlzdGVuZXJzKCkge1xuICAgICAgICAvLyBDcmVhdGUgcmVmZXJlbmNlcyB0byB0aGUgZXZlbnQgaGFuZGxlciBmdW5jdGlvbnMsIHNvIHdlIGNhbiB0aGVuIGNsZWFubHkgcmVtb3ZlcyB0aG9zZSBsaXN0ZW5lcnMgaWYgbmVlZGVkXG4gICAgICAgIC8vIFRoYXQgd291bGQgbm90IGJlIHBvc3NpYmxlIGlmIHdlIHVzZWQgY2xvc3VyZXMgZGlyZWN0bHkgaW4gdGhlIGV2ZW50IGhhbmRsZXIgZGVjbGFyYXRpb25zXG4gICAgICAgIHRoaXMuX29uRm9jdXNJbkZ1bmMgPSBlID0+IHsgdGhpcy5fb25Gb2N1c0luKGUpOyB9O1xuICAgICAgICB0aGlzLl9vbkZvY3VzSW5BbmRNb3VzZUVudGVyRnVuYyA9IGUgPT4geyB0aGlzLl9vbkZvY3VzSW5BbmRNb3VzZUVudGVyKGUpOyB9O1xuICAgICAgICB0aGlzLl9vbkZvY3VzRnVuYyA9ICgpID0+IHsgdGhpcy5fb25Gb2N1cygpOyB9O1xuICAgICAgICB0aGlzLl9vbktleWRvd25GdW5jID0gZSA9PiB7IHRoaXMuX29uS2V5ZG93bihlKTsgfTtcbiAgICAgICAgdGhpcy5fb25LZXlwcmVzc0Z1bmMgPSBlID0+IHsgdGhpcy5fb25LZXlwcmVzcyhlKTsgfTtcbiAgICAgICAgdGhpcy5fb25JbnB1dEZ1bmMgPSBlID0+IHsgdGhpcy5fb25JbnB1dChlKTsgfTtcbiAgICAgICAgdGhpcy5fb25LZXl1cEZ1bmMgPSBlID0+IHsgdGhpcy5fb25LZXl1cChlKTsgfTtcbiAgICAgICAgdGhpcy5fb25Gb2N1c091dEFuZE1vdXNlTGVhdmVGdW5jID0gZSA9PiB7IHRoaXMuX29uRm9jdXNPdXRBbmRNb3VzZUxlYXZlKGUpOyB9O1xuICAgICAgICB0aGlzLl9vblBhc3RlRnVuYyA9IGUgPT4geyB0aGlzLl9vblBhc3RlKGUpOyB9O1xuICAgICAgICB0aGlzLl9vbldoZWVsRnVuYyA9IGUgPT4geyB0aGlzLl9vbldoZWVsKGUpOyB9O1xuICAgICAgICB0aGlzLl9vbkZvcm1TdWJtaXRGdW5jID0gKCkgPT4geyB0aGlzLl9vbkZvcm1TdWJtaXQoKTsgfTtcbiAgICAgICAgdGhpcy5fb25LZXlkb3duR2xvYmFsRnVuYyA9IGUgPT4geyB0aGlzLl9vbktleWRvd25HbG9iYWwoZSk7IH07XG4gICAgICAgIHRoaXMuX29uS2V5dXBHbG9iYWxGdW5jID0gZSA9PiB7IHRoaXMuX29uS2V5dXBHbG9iYWwoZSk7IH07XG4gICAgICAgIHRoaXMuX29uRHJvcEZ1bmMgPSBlID0+IHsgdGhpcy5fb25Ecm9wKGUpOyB9O1xuXG4gICAgICAgIC8vIEFkZCB0aGUgZXZlbnQgbGlzdGVuZXJzXG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdmb2N1c2luJywgdGhpcy5fb25Gb2N1c0luRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLl9vbkZvY3VzSW5BbmRNb3VzZUVudGVyRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLl9vbkZvY3VzRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VlbnRlcicsIHRoaXMuX29uRm9jdXNJbkFuZE1vdXNlRW50ZXJGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5fb25LZXlkb3duRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5cHJlc3MnLCB0aGlzLl9vbktleXByZXNzRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignaW5wdXQnLCB0aGlzLl9vbklucHV0RnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigna2V5dXAnLCB0aGlzLl9vbktleXVwRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignYmx1cicsIHRoaXMuX29uRm9jdXNPdXRBbmRNb3VzZUxlYXZlRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignbW91c2VsZWF2ZScsIHRoaXMuX29uRm9jdXNPdXRBbmRNb3VzZUxlYXZlRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcigncGFzdGUnLCB0aGlzLl9vblBhc3RlRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignd2hlZWwnLCB0aGlzLl9vbldoZWVsRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZHJvcCcsIHRoaXMuX29uRHJvcEZ1bmMsIGZhbHNlKTtcblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbCh0aGlzLnBhcmVudEZvcm0pKSB7XG4gICAgICAgICAgICB0aGlzLnBhcmVudEZvcm0uYWRkRXZlbnRMaXN0ZW5lcignc3VibWl0JywgdGhpcy5fb25Gb3JtU3VibWl0RnVuYywgZmFsc2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ3JlYXRlIG9uZSBnbG9iYWwgZXZlbnQgbGlzdGVuZXIgZm9yIHRoZSBrZXl1cCBldmVudCBvbiB0aGUgZG9jdW1lbnQgb2JqZWN0LCB3aGljaCB3aWxsIGJlIHNoYXJlZCBieSBhbGwgdGhlIGF1dG9OdW1lcmljIGVsZW1lbnRzXG4gICAgICAgIGlmICghQXV0b051bWVyaWMuX2RvZXNHbG9iYWxMaXN0RXhpc3RzKCkpIHtcbiAgICAgICAgICAgIGRvY3VtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLl9vbktleWRvd25HbG9iYWxGdW5jLCBmYWxzZSk7XG4gICAgICAgICAgICBkb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdrZXl1cCcsIHRoaXMuX29uS2V5dXBHbG9iYWxGdW5jLCBmYWxzZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgYWxsIHRoZSBhdXRvTnVtZXJpYy1yZWxhdGVkIGV2ZW50IGxpc3RlbmVycyBmb3IgdGhlIGdpdmVuIERPTSBlbGVtZW50XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfcmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdmb2N1c2luJywgdGhpcy5fb25Gb2N1c0luRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLl9vbkZvY3VzSW5BbmRNb3VzZUVudGVyRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignZm9jdXMnLCB0aGlzLl9vbkZvY3VzRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignbW91c2VlbnRlcicsIHRoaXMuX29uRm9jdXNJbkFuZE1vdXNlRW50ZXJGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdibHVyJywgdGhpcy5fb25Gb2N1c091dEFuZE1vdXNlTGVhdmVGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdtb3VzZWxlYXZlJywgdGhpcy5fb25Gb2N1c091dEFuZE1vdXNlTGVhdmVGdW5jLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5yZW1vdmVFdmVudExpc3RlbmVyKCdrZXlkb3duJywgdGhpcy5fb25LZXlkb3duRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5cHJlc3MnLCB0aGlzLl9vbktleXByZXNzRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignaW5wdXQnLCB0aGlzLl9vbklucHV0RnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigna2V5dXAnLCB0aGlzLl9vbktleXVwRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcigncGFzdGUnLCB0aGlzLl9vblBhc3RlRnVuYywgZmFsc2UpO1xuICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcignd2hlZWwnLCB0aGlzLl9vbldoZWVsRnVuYywgZmFsc2UpO1xuXG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleWRvd24nLCB0aGlzLl9vbktleWRvd25HbG9iYWxGdW5jLCBmYWxzZSk7XG4gICAgICAgIGRvY3VtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2tleXVwJywgdGhpcy5fb25LZXl1cEdsb2JhbEZ1bmMsIGZhbHNlKTtcblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbCh0aGlzLnBhcmVudEZvcm0pKSB7XG4gICAgICAgICAgICB0aGlzLnBhcmVudEZvcm0ucmVtb3ZlRXZlbnRMaXN0ZW5lcignc3VibWl0JywgdGhpcy5fb25Gb3JtU3VibWl0RnVuYywgZmFsc2UpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBlbGVtZW50IGF0dHJpYnV0ZSAncmVhZG9ubHknIGFjY29yZGluZyB0byB0aGUgY3VycmVudCBzZXR0aW5ncy5cbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NldFJlYWRPbmx5KCkge1xuICAgICAgICBpZiAodGhpcy5pc0lucHV0RWxlbWVudCAmJiB0aGlzLnNldHRpbmdzLnJlYWRPbmx5KSB7XG4gICAgICAgICAgICB0aGlzLmRvbUVsZW1lbnQucmVhZE9ubHkgPSB0cnVlO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2F2ZSB0aGUgY3VycmVudCByYXcgdmFsdWUgaW50byB0aGUgaGlzdG9yeSB0YWJsZSwgYWxvbmcgd2l0aCB0aGUgc2VsZWN0aW9uIGluZm9ybWF0aW9uLlxuICAgICAqXG4gICAgICogSWYgdGhlIHVzZXIgaGFzIGRvbmUgc29tZSB1bmRvcyBhbmQgdHJpZXMgdG8gZW50ZXI6XG4gICAgICogLSBhIG5ldyBhbmQgZGlmZmVyZW50IG51bWJlciB0aGFuIHRoZSAnbmV4dCcgc3RhdGUsIHRoaXMgZHJvcHMgdGhlIHJlc3Qgb2YgdGhlIGhpc3RvcnkgdGFibGVcbiAgICAgKiAtIHRoZSB2ZXJ5IHNhbWUgbnVtYmVyIHRoYXQgcmVzdWx0IGluIHRoZSBzYW1lIHJhd1ZhbHVlIHRoYW4gdGhlICduZXh0JyBzdGF0ZSwgd2Ugb25seSBtb3ZlIHRoZSBoaXN0b3J5IHRhYmxlIHBvaW50ZXIgdG8gdGhlIG5leHQgc3RhdGVcbiAgICAgKlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2hpc3RvcnlUYWJsZUFkZCgpIHtcbiAgICAgICAgLy9UT0RPIEFkZCBhIGB0aGlzLnNldHRpbmdzLnNhdmVTZWxlY3Rpb25zSW50b0hpc3RvcnlgIG9wdGlvbiB0byBwcmV2ZW50IHNhdmluZyB0aGUgc2VsZWN0aW9ucyAoaW4gb3JkZXIgdG8gZ2FpbiBwZXJmb3JtYW5jZSlcbiAgICAgICAgY29uc3QgaXNFbXB0eUhpc3RvcnlUYWJsZSA9IHRoaXMuaGlzdG9yeVRhYmxlLmxlbmd0aCA9PT0gMDtcbiAgICAgICAgLy8gT25seSBhZGQgYSBuZXcgdmFsdWUgaWYgaXQncyBkaWZmZXJlbnQgdGhhbiB0aGUgcHJldmlvdXMgb25lICh0byBwcmV2ZW50IGluZmluaXRlbHkgYWRkaW5nIHZhbHVlcyBvbiBtb3VzZW92ZXIgZm9yIGluc3RhbmNlKVxuICAgICAgICBpZiAoaXNFbXB0eUhpc3RvcnlUYWJsZSB8fCB0aGlzLnJhd1ZhbHVlICE9PSB0aGlzLl9oaXN0b3J5VGFibGVDdXJyZW50VmFsdWVVc2VkKCkpIHtcbiAgICAgICAgICAgIC8vIFRyaW0gdGhlIGhpc3RvcnkgdGFibGUgaWYgdGhlIHVzZXIgY2hhbmdlZCB0aGUgdmFsdWUgb2YgYW4gaW50ZXJtZWRpYXJ5IHN0YXRlXG4gICAgICAgICAgICBsZXQgYWRkTmV3SGlzdG9yeVN0YXRlID0gdHJ1ZTtcbiAgICAgICAgICAgIGlmICghaXNFbXB0eUhpc3RvcnlUYWJsZSkge1xuICAgICAgICAgICAgICAgIC8vIElmIHNvbWUgdW5kbyBoYXMgYmVlbiBkb25lIGFuZCB0aGUgdXNlciB0eXBlIHRoZSBleGFjdCBzYW1lIGRhdGEgdGhhbiB0aGUgbmV4dCBlbnRyeSBhZnRlciB0aGUgY3VycmVudCBoaXN0b3J5IHBvaW50ZXIsIGRvIG5vIGRyb3AgdGhlIHJlc3Qgb2YgdGhlICdyZWRvJyBsaXN0LCBhbmQganVzdCBhZHZhbmNlIHRoZSBoaXN0b3J5VGFibGVJbmRleFxuICAgICAgICAgICAgICAgIGNvbnN0IG5leHRIaXN0b3J5U3RhdGVJbmRleCA9IHRoaXMuaGlzdG9yeVRhYmxlSW5kZXggKyAxO1xuICAgICAgICAgICAgICAgIGlmIChuZXh0SGlzdG9yeVN0YXRlSW5kZXggPCB0aGlzLmhpc3RvcnlUYWJsZS5sZW5ndGggJiYgdGhpcy5yYXdWYWx1ZSA9PT0gdGhpcy5oaXN0b3J5VGFibGVbbmV4dEhpc3RvcnlTdGF0ZUluZGV4XS52YWx1ZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgY2hhcmFjdGVyIGlucHV0IHJlc3VsdCBpbiB0aGUgc2FtZSBzdGF0ZSB0aGFuIHRoZSBuZXh0IG9uZSwgZG8gbm90IHJlbW92ZSB0aGUgbmV4dCBoaXN0b3J5IHN0YXRlcyBub3IgYWRkIGEgbmV3IG9uZVxuICAgICAgICAgICAgICAgICAgICBhZGROZXdIaXN0b3J5U3RhdGUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBGaXJzdCByZW1vdmUgYW55dGhpbmcgdGhhdCBpcyBhZnRlciB0aGUgY3VycmVudCBpbmRleFxuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5hcnJheVRyaW0odGhpcy5oaXN0b3J5VGFibGUsIHRoaXMuaGlzdG9yeVRhYmxlSW5kZXggKyAxKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgaGlzdG9yeSBwb2ludGVyXG4gICAgICAgICAgICB0aGlzLmhpc3RvcnlUYWJsZUluZGV4Kys7XG5cbiAgICAgICAgICAgIC8vIEFkZCB0aGUgbmV3IGhpc3Rvcnkgc3RhdGUsIGlmIG5lZWRlZFxuICAgICAgICAgICAgaWYgKGFkZE5ld0hpc3RvcnlTdGF0ZSkge1xuICAgICAgICAgICAgICAgIC8vIFNhdmUgdGhlIHNlbGVjdGlvbiBpbmZvXG4gICAgICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFNlbGVjdGlvbih0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuc2VsZWN0aW9uU3RhcnQgPSBzZWxlY3Rpb24uc3RhcnQ7XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25FbmQgPSBzZWxlY3Rpb24uZW5kO1xuXG4gICAgICAgICAgICAgICAgLy8gVGhlbiBhZGQgdGhlIG5ldyByYXcgdmFsdWVcbiAgICAgICAgICAgICAgICB0aGlzLmhpc3RvcnlUYWJsZS5wdXNoKHtcbiAgICAgICAgICAgICAgICAgICAgLy8gU2F2ZSB0aGUgcmF3VmFsdWUgYW5kIHNlbGVjdGlvbiBzdGFydC9lbmRcbiAgICAgICAgICAgICAgICAgICAgdmFsdWU6IHRoaXMucmF3VmFsdWUsXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBzZWxlY3Rpb24gZm9yIHRoaXMgZWxlbWVudCBpcyB0ZW1wb3JhcnksIGFuZCB3aWxsIGJlIHVwZGF0ZWQgd2hlbiB0aGUgbmV4dCBoaXN0b3J5IHN0YXRlIHdpbGwgYmUgcmVjb3JkZWQuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoYXQgd2F5LCB3ZSBhcmUgYWx3YXlzIHN1cmUgd2Ugc2F2ZSB0aGUgbGFzdCBjYXJldCBvciBzZWxlY3Rpb24gcG9zaXRpb25zIGp1c3QgYmVmb3JlIHRoZSB2YWx1ZSBpcyBjaGFuZ2VkLiBPdGhlcndpc2Ugd2Ugd291bGQgb25seSBzYXZlIHRob3NlIHBvc2l0aW9ucyB3aGVuIHRoZSB2YWx1ZSBpcyBmaXJzdCBjaGFuZ2VkLCBhbmQgd291bGQgbm90IHRha2UgaW50byBhY2NvdW50IHRoYXQgdGhlIHVzZXIgY291bGQgbW92ZSB0aGUgY2FyZXQgYXJvdW5kIGFmdGVyd2FyZC5cbiAgICAgICAgICAgICAgICAgICAgLy8gRm9yIGluc3RhbmNlLCB0aGlzIGlzIG5lZWRlZCBpZiB0aGUgdXNlciBjaGFuZ2UgdGhlIGVsZW1lbnQgdmFsdWUsIGFuZCBpbW1lZGlhdGVseSB1bmRvIGl0IDsgaWYgaGUgdGhlbiBkb2VzIGEgcmVkbywgaGUnbGwgc2VlIHRoZSB2YWx1ZSBhbmQgdGhlIHJpZ2h0IHNlbGVjdGlvblxuICAgICAgICAgICAgICAgICAgICAvLyBUbyBzdW0gdXA7IFRoZSBzZWxlY3Rpb24gcG9zaXRpb24gYXJlIG5vdCBhbHdheXMgKzEgY2hhcmFjdGVyLCBzaW5jZSBpdCBjb3VsZCBhbHNvIGJlICcyJyBpZiBhIGdyb3VwIHNlcGFyYXRvciBpcyBhZGRlZCB3aGVuIGVudGVyaW5nIG9uZSBjaGFyYWN0ZXIuIFRoYXQncyB3aHkgdGhlIGN1cnJlbnQgaGlzdG9yeSBzdGF0ZSBjYXJldC9zZWxlY3Rpb24gcG9zaXRpb24gaXMgdXBkYXRlZCBvbiBlYWNoIGBrZXl1cGAgZXZlbnQuXG4gICAgICAgICAgICAgICAgICAgIHN0YXJ0OiB0aGlzLnNlbGVjdGlvblN0YXJ0ICsgMSwgLy8gSGVyZSB3ZSBhZGQgb25lIHNpbmNlIHRoZSB1c2VyIGFkZGVkIG9uZSBjaGFyYWN0ZXIgdG9vXG4gICAgICAgICAgICAgICAgICAgIGVuZCAgOiB0aGlzLnNlbGVjdGlvbkVuZCArIDEsXG4gICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHNlbGVjdGlvbiBpbiB0aGUgcHJldmlvdXMgZW50cnksIGluIG9yZGVyIHRvIGtlZXAgdHJhY2sgb2YgdGhlIHVwZGF0ZWQgY2FyZXQvc2VsZWN0aW9uIHBvc2l0aW9uc1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmhpc3RvcnlUYWJsZS5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlW3RoaXMuaGlzdG9yeVRhYmxlSW5kZXggLSAxXS5zdGFydCA9IHRoaXMuc2VsZWN0aW9uU3RhcnQ7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlW3RoaXMuaGlzdG9yeVRhYmxlSW5kZXggLSAxXS5lbmQgPSB0aGlzLnNlbGVjdGlvbkVuZDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIExpbWl0IHRoZSBoaXN0b3J5IHRhYmxlIHNpemUgYWNjb3JkaW5nIHRvIHRoZSBgaGlzdG9yeVNpemVgIG9wdGlvblxuICAgICAgICAgICAgaWYgKHRoaXMuaGlzdG9yeVRhYmxlLmxlbmd0aCA+IHRoaXMuc2V0dGluZ3MuaGlzdG9yeVNpemUpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9oaXN0b3J5VGFibGVGb3JnZXQoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlYnVnIGZ1bmN0aW9uIGZvciB0aGUgaGlzdG9yeSB0YWJsZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgLypcbiAgICBfZGVidWdIaXN0b3J5VGFibGUoKSB7XG4gICAgICAgIGxldCBpID0gMDtcbiAgICAgICAgbGV0IG1hcms7XG4gICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlLmZvckVhY2goaGlzdG9yeSA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy5oaXN0b3J5VGFibGVJbmRleCA9PT0gaSkge1xuICAgICAgICAgICAgICAgIG1hcmsgPSAnPiAnO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBtYXJrID0gJyc7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgJHttYXJrfSR7aSsrfTogJHtoaXN0b3J5LnZhbHVlfSAke2hpc3Rvcnkuc3RhcnR9fCR7aGlzdG9yeS5lbmR9IFtvbkdvaW5nUmVkbzogJHt0aGlzLm9uR29pbmdSZWRvfV1gKTsgLy9ERUJVR1xuICAgICAgICB9KTtcbiAgICB9XG4gICAgKi9cblxuICAgIC8qKlxuICAgICAqICdVbmRvJyBvciAnUmVkbycgdGhlIGxhc3QvbmV4dCB1c2VyIGVudHJ5IGluIHRoZSBoaXN0b3J5IHRhYmxlLlxuICAgICAqIFRoaXMgZG9lcyBub3QgbW9kaWZ5IHRoZSBoaXN0b3J5IHRhYmxlLCBvbmx5IHRoZSBwb2ludGVyIHRvIHRoZSBjdXJyZW50IHN0YXRlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtib29sZWFufSB1bmRvIElmIHNldCB0byBgdHJ1ZWAsIHRoZW4gdGhpcyBmdW5jdGlvbiBkb2VzIGFuICdVbmRvJywgb3RoZXJ3aXNlIGl0IGRvZXMgYSAnUmVkbydcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9oaXN0b3J5VGFibGVVbmRvT3JSZWRvKHVuZG8gPSB0cnVlKSB7XG4gICAgICAgIGxldCBjaGVjaztcbiAgICAgICAgaWYgKHVuZG8pIHtcbiAgICAgICAgICAgIC8vIE9ubHkgJ3VuZG8nIGlmIHRoZXJlIGFyZSBzb21lIGluZm8gdG8gdW5kb1xuICAgICAgICAgICAgY2hlY2sgPSB0aGlzLmhpc3RvcnlUYWJsZUluZGV4ID4gMDtcbiAgICAgICAgICAgIGlmIChjaGVjaykge1xuICAgICAgICAgICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlSW5kZXgtLTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE9ubHkgJ3JlZG8nIGlmIHRoZXJlIGFyZSBzb21lIGluZm8gdG8gcmVkbyBhdCB0aGUgZW5kIG9mIHRoZSBoaXN0b3J5IHRhYmxlXG4gICAgICAgICAgICBjaGVjayA9IHRoaXMuaGlzdG9yeVRhYmxlSW5kZXggKyAxIDwgdGhpcy5oaXN0b3J5VGFibGUubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKGNoZWNrKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5oaXN0b3J5VGFibGVJbmRleCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNoZWNrKSB7XG4gICAgICAgICAgICAvLyBTZXQgdGhlIHZhbHVlIGJhY2tcbiAgICAgICAgICAgIGNvbnN0IHVuZG9JbmZvID0gdGhpcy5oaXN0b3J5VGFibGVbdGhpcy5oaXN0b3J5VGFibGVJbmRleF07XG4gICAgICAgICAgICB0aGlzLnNldCh1bmRvSW5mby52YWx1ZSwgbnVsbCwgZmFsc2UpOyAvLyBuZXh0IG9yIHByZXZpb3VzIHJhdyB2YWx1ZVxuXG4gICAgICAgICAgICAvLyBTZXQgdGhlIHNlbGVjdGlvbiBiYWNrXG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50U2VsZWN0aW9uKHRoaXMuZG9tRWxlbWVudCwgdW5kb0luZm8uc3RhcnQsIHVuZG9JbmZvLmVuZCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAnVW5kbycgdGhlIGxhc3QgdXNlciBlbnRyeSBieSBnb2luZyBiYWNrIG9uZSBlbnRyeSBpbiB0aGUgaGlzdG9yeSB0YWJsZS5cbiAgICAgKiBUaGlzIGtlZXBzIHRoZSBmb2xsb3dpbmcgZW50cmllcyBpbiBvcmRlciB0byBhbGxvdyBmb3IgYSAncmVkbycuXG4gICAgICogVGhpcyBkb2VzIG5vdCBtb2RpZnkgdGhlIGhpc3RvcnkgdGFibGUsIG9ubHkgdGhlIHBvaW50ZXIgdG8gdGhlIGN1cnJlbnQgc3RhdGUuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfaGlzdG9yeVRhYmxlVW5kbygpIHtcbiAgICAgICAgdGhpcy5faGlzdG9yeVRhYmxlVW5kb09yUmVkbyh0cnVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiAnUmVkbycgdGhlIG5leHQgdXNlciBlbnRyeSBpbiB0aGUgaGlzdG9yeSB0YWJsZS5cbiAgICAgKiBUaGlzIGRvZXMgbm90IG1vZGlmeSB0aGUgaGlzdG9yeSB0YWJsZSwgb25seSB0aGUgcG9pbnRlciB0byB0aGUgY3VycmVudCBzdGF0ZS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9oaXN0b3J5VGFibGVSZWRvKCkge1xuICAgICAgICB0aGlzLl9oaXN0b3J5VGFibGVVbmRvT3JSZWRvKGZhbHNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXNldCB0aGUgaGlzdG9yeSB0YWJsZSB0byBpdHMgaW5pdGlhbCBzdGF0ZSwgYW5kIHNlbGVjdCB0aGUgdmFsdWUuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICAvKlxuICAgIHJlc2V0SGlzdG9yeVRhYmxlKCkgeyAvL0ZJWE1FIFRlc3QgdGhpc1xuICAgICAgICB0aGlzLnNldCh0aGlzLnJhd1ZhbHVlLCBudWxsLCBmYWxzZSk7XG4gICAgICAgIHRoaXMuc2VsZWN0KCk7XG4gICAgICAgIGNvbnN0IHNlbGVjdGlvbiA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRTZWxlY3Rpb24odGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgdGhpcy5oaXN0b3J5VGFibGVJbmRleCA9IDA7XG4gICAgICAgIHRoaXMuaGlzdG9yeVRhYmxlID0gW3tcbiAgICAgICAgICAgIC8vIFNhdmUgdGhlIHJhd1ZhbHVlIGFuZCBzZWxlY3Rpb24gc3RhcnQvZW5kXG4gICAgICAgICAgICB2YWx1ZTogdGhpcy5yYXdWYWx1ZSxcbiAgICAgICAgICAgIHN0YXJ0OiBzZWxlY3Rpb24uc3RhcnQsXG4gICAgICAgICAgICBlbmQgIDogc2VsZWN0aW9uLmVuZCxcbiAgICAgICAgfV07XG4gICAgfVxuICAgICovXG5cbiAgICAvKipcbiAgICAgKiBNYWtlIHRoZSBoaXN0b3J5IHRhYmxlIGZvcmdldCBpdHMgZmlyc3QgTiBlbGVtZW50cywgc2hpZnRpbmcgaXRzIGluZGV4ZXMgaW4gdGhlIHByb2Nlc3MuXG4gICAgICogYE5gIGJlaW5nIGdpdmVuIGFzIHRoZSBgbnVtYmVyT2ZFbnRyaWVzVG9Gb3JnZXRgIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBudW1iZXJPZkVudHJpZXNUb0ZvcmdldFxuICAgICAqIEByZXR1cm5zIHtvYmplY3R8QXJyYXk8b2JqZWN0Pn0gVGhlIGRpc2NhcmRlZCBvYmplY3RzLCBpbiBhbiBBcnJheS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9oaXN0b3J5VGFibGVGb3JnZXQobnVtYmVyT2ZFbnRyaWVzVG9Gb3JnZXQgPSAxKSB7XG4gICAgICAgIGNvbnN0IHNoaWZ0ZWRBd2F5ID0gW107XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbnVtYmVyT2ZFbnRyaWVzVG9Gb3JnZXQ7IGkrKykge1xuICAgICAgICAgICAgc2hpZnRlZEF3YXkucHVzaCh0aGlzLmhpc3RvcnlUYWJsZS5zaGlmdCgpKTtcbiAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgaGlzdG9yeSB0YWJsZSBpbmRleCBhY2NvcmRpbmdseVxuICAgICAgICAgICAgdGhpcy5oaXN0b3J5VGFibGVJbmRleC0tO1xuICAgICAgICAgICAgaWYgKHRoaXMuaGlzdG9yeVRhYmxlSW5kZXggPCAwKSB7XG4gICAgICAgICAgICAgICAgLy8gSW4gY2FzZSB0aGlzIGZ1bmN0aW9uIGlzIGNhbGxlZCBtb3JlIHRpbWVzIHRoYW4gdGhlcmUgaXMgc3RhdGVzIGluIHRoZSBoaXN0b3J5IHRhYmxlXG4gICAgICAgICAgICAgICAgdGhpcy5oaXN0b3J5VGFibGVJbmRleCA9IDA7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2hpZnRlZEF3YXkubGVuZ3RoID09PSAxKSB7XG4gICAgICAgICAgICByZXR1cm4gc2hpZnRlZEF3YXlbMF07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc2hpZnRlZEF3YXk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBjdXJyZW50bHkgdXNlZCB2YWx1ZSBmcm9tIHRoZSBoaXN0b3J5IHRhYmxlLlxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ3xudW1iZXJ9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfaGlzdG9yeVRhYmxlQ3VycmVudFZhbHVlVXNlZCgpIHtcbiAgICAgICAgbGV0IGluZGV4VG9Vc2UgPSB0aGlzLmhpc3RvcnlUYWJsZUluZGV4O1xuICAgICAgICBpZiAoaW5kZXhUb1VzZSA8IDApIHtcbiAgICAgICAgICAgIGluZGV4VG9Vc2UgPSAwO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh0aGlzLmhpc3RvcnlUYWJsZVtpbmRleFRvVXNlXSkpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9ICcnO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5oaXN0b3J5VGFibGVbaW5kZXhUb1VzZV0udmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFBhcnNlIHRoZSBgc3R5bGVSdWxlc2Agb3B0aW9uIGFuZCBydW4gdGhlIHRlc3QgZm9yIGVhY2ggZ2l2ZW4gcnVsZXMsIGVpdGhlciBwcmUtZGVmaW5lZCBvbmVzIGxpa2UgYHBvc2l0aXZlYCwgYG5lZ2F0aXZlYCBhbmQgYHJhbmdlc2AsIG9yIHVzZXIgZGVmaW5lZCBjYWxsYmFja3Mgd2l0aGluIHRoZSBgdXNlckRlZmluZWRgIGF0dHJpYnV0ZS5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9wYXJzZVN0eWxlUnVsZXMoKSB7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkodGhpcy5zZXR0aW5ncy5zdHlsZVJ1bGVzKSB8fCB0aGlzLnJhd1ZhbHVlID09PSAnJykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gJ3Bvc2l0aXZlJyBhdHRyaWJ1dGVcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkodGhpcy5zZXR0aW5ncy5zdHlsZVJ1bGVzLnBvc2l0aXZlKSkge1xuICAgICAgICAgICAgaWYgKHRoaXMucmF3VmFsdWUgPj0gMCkge1xuICAgICAgICAgICAgICAgIHRoaXMuX2FkZENTU0NsYXNzKHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy5wb3NpdGl2ZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHRoaXMuX3JlbW92ZUNTU0NsYXNzKHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy5wb3NpdGl2ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyAnbmVnYXRpdmUnIGF0dHJpYnV0ZVxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh0aGlzLnNldHRpbmdzLnN0eWxlUnVsZXMubmVnYXRpdmUpKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5yYXdWYWx1ZSA8IDApIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9hZGRDU1NDbGFzcyh0aGlzLnNldHRpbmdzLnN0eWxlUnVsZXMubmVnYXRpdmUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDU1NDbGFzcyh0aGlzLnNldHRpbmdzLnN0eWxlUnVsZXMubmVnYXRpdmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gJ3JhbmdlcycgYXR0cmlidXRlXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy5yYW5nZXMpICYmIHRoaXMuc2V0dGluZ3Muc3R5bGVSdWxlcy5yYW5nZXMubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICB0aGlzLnNldHRpbmdzLnN0eWxlUnVsZXMucmFuZ2VzLmZvckVhY2gocmFuZ2UgPT4ge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnJhd1ZhbHVlID49IHJhbmdlLm1pbiAmJiB0aGlzLnJhd1ZhbHVlIDwgcmFuZ2UubWF4KSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2FkZENTU0NsYXNzKHJhbmdlLmNsYXNzKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDU1NDbGFzcyhyYW5nZS5jbGFzcyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAndXNlckRlZmluZWQnIGF0dHJpYnV0ZVxuICAgICAgICAvL1RPRE8gQWxzbyBwYXNzIHRoZSBvbGQgcmF3IHZhbHVlIGFzIGEgcGFyYW1ldGVyLCBhbmQgbm90IG9ubHkgdGhlIG5ldyByYXcgdmFsdWVcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkodGhpcy5zZXR0aW5ncy5zdHlsZVJ1bGVzLnVzZXJEZWZpbmVkKSAmJiB0aGlzLnNldHRpbmdzLnN0eWxlUnVsZXMudXNlckRlZmluZWQubGVuZ3RoICE9PSAwKSB7XG4gICAgICAgICAgICB0aGlzLnNldHRpbmdzLnN0eWxlUnVsZXMudXNlckRlZmluZWQuZm9yRWFjaCh1c2VyT2JqZWN0ID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNGdW5jdGlvbih1c2VyT2JqZWN0LmNhbGxiYWNrKSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBUZXN0IGZvciB0aGUgdHlwZSBvZiB0aGUgYGNsYXNzZXNgIGF0dHJpYnV0ZSwgd2hpY2ggY2hhbmdlcyB0aGUgZnVuY3Rpb24gYmVoYXZpb3JcbiAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKHVzZXJPYmplY3QuY2xhc3NlcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmICdjbGFzc2VzJyBpcyBhIHN0cmluZywgc2V0IGl0IGlmIGB0cnVlYCwgcmVtb3ZlIGl0IGlmIGBmYWxzZWBcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1c2VyT2JqZWN0LmNhbGxiYWNrKHRoaXMucmF3VmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fYWRkQ1NTQ2xhc3ModXNlck9iamVjdC5jbGFzc2VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlQ1NTQ2xhc3ModXNlck9iamVjdC5jbGFzc2VzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0FycmF5KHVzZXJPYmplY3QuY2xhc3NlcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh1c2VyT2JqZWN0LmNsYXNzZXMubGVuZ3RoID09PSAyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgJ2NsYXNzZXMnIGlzIGFuIGFycmF5IHdpdGggb25seSAyIGVsZW1lbnRzLCBzZXQgdGhlIGZpcnN0IGNsYXNzIGlmIGB0cnVlYCwgdGhlIHNlY29uZCBpZiBgZmFsc2VgXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHVzZXJPYmplY3QuY2FsbGJhY2sodGhpcy5yYXdWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fYWRkQ1NTQ2xhc3ModXNlck9iamVjdC5jbGFzc2VzWzBdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlQ1NTQ2xhc3ModXNlck9iamVjdC5jbGFzc2VzWzFdKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDU1NDbGFzcyh1c2VyT2JqZWN0LmNsYXNzZXNbMF0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9hZGRDU1NDbGFzcyh1c2VyT2JqZWN0LmNsYXNzZXNbMV0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAodXNlck9iamVjdC5jbGFzc2VzLmxlbmd0aCA+IDIpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgY2FsbGJhY2sgcmV0dXJucyBhbiBhcnJheSBvZiBpbmRleGVzIHRvIHVzZSBvbiB0aGUgYGNsYXNzZXNgIGFycmF5XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgY2FsbGJhY2tSZXN1bHQgPSB1c2VyT2JqZWN0LmNhbGxiYWNrKHRoaXMucmF3VmFsdWUpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0FycmF5KGNhbGxiYWNrUmVzdWx0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiBtdWx0aXBsZSBpbmRleGVzIGFyZSByZXR1cm5lZFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VyT2JqZWN0LmNsYXNzZXMuZm9yRWFjaCgodXNlckNsYXNzLCBpbmRleCkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShpbmRleCwgY2FsbGJhY2tSZXN1bHQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fYWRkQ1NTQ2xhc3ModXNlckNsYXNzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlQ1NTQ2xhc3ModXNlckNsYXNzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0ludChjYWxsYmFja1Jlc3VsdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgb25seSBvbmUgaW5kZXggaXMgcmV0dXJuZWRcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdXNlck9iamVjdC5jbGFzc2VzLmZvckVhY2goKHVzZXJDbGFzcywgaW5kZXgpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpbmRleCA9PT0gY2FsbGJhY2tSZXN1bHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9hZGRDU1NDbGFzcyh1c2VyQ2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9yZW1vdmVDU1NDbGFzcyh1c2VyQ2xhc3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChjYWxsYmFja1Jlc3VsdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gUmVtb3ZlIGFsbCB0aGUgY2xhc3Nlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB1c2VyT2JqZWN0LmNsYXNzZXMuZm9yRWFjaCh1c2VyQ2xhc3MgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlQ1NTQ2xhc3ModXNlckNsYXNzKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGNhbGxiYWNrIHJlc3VsdCBpcyBub3QgYW4gYXJyYXkgbm9yIGEgdmFsaWQgYXJyYXkgaW5kZXgsICR7dHlwZW9mIGNhbGxiYWNrUmVzdWx0fSBnaXZlbi5gKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoJ1RoZSBjbGFzc2VzIGF0dHJpYnV0ZSBpcyBub3QgdmFsaWQgZm9yIHRoZSBgc3R5bGVSdWxlc2Agb3B0aW9uLicpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh1c2VyT2JqZWN0LmNsYXNzZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiAnY2xhc3NlcycgaXMgYHVuZGVmaW5lZGAgb3IgYG51bGxgLCB0aGVuIHRoZSBjYWxsYmFjayBpcyBjYWxsZWQgd2l0aCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IHBhc3NlZCBhcyBhIHBhcmFtZXRlclxuICAgICAgICAgICAgICAgICAgICAgICAgdXNlck9iamVjdC5jYWxsYmFjayh0aGlzKTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoJ1RoZSBjYWxsYmFjay9jbGFzc2VzIHN0cnVjdHVyZSBpcyBub3QgdmFsaWQgZm9yIHRoZSBgc3R5bGVSdWxlc2Agb3B0aW9uLicpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgVGhlIGdpdmVuIFxcYHN0eWxlUnVsZXNcXGAgY2FsbGJhY2sgaXMgbm90IGEgZnVuY3Rpb24sICR7dHlwZW9mIGNhbGxiYWNrfSBnaXZlbi5gLCB0aGlzLnNldHRpbmdzLnNob3dXYXJuaW5ncyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGQgdGhlIGdpdmVuIENTUyBjbGFzcyB0byB0aGUgRE9NIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY3NzQ2xhc3NOYW1lXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfYWRkQ1NTQ2xhc3MoY3NzQ2xhc3NOYW1lKSB7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5jbGFzc0xpc3QuYWRkKGNzc0NsYXNzTmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBnaXZlbiBDU1MgY2xhc3MgZnJvbSB0aGUgRE9NIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gY3NzQ2xhc3NOYW1lXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfcmVtb3ZlQ1NTQ2xhc3MoY3NzQ2xhc3NOYW1lKSB7XG4gICAgICAgIHRoaXMuZG9tRWxlbWVudC5jbGFzc0xpc3QucmVtb3ZlKGNzc0NsYXNzTmFtZSk7XG4gICAgfVxuXG4gICAgLy8gVGhpcyBhcmUgdGhlIHB1YmxpYyBmdW5jdGlvbiBhdmFpbGFibGUgb24gZWFjaCBhdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRcblxuICAgIC8qKlxuICAgICAqIE1ldGhvZCB0aGF0IHVwZGF0ZXMgdGhlIEF1dG9OdW1lcmljIHNldHRpbmdzLCBhbmQgaW1tZWRpYXRlbHkgZm9ybWF0IHRoZSBlbGVtZW50IGFjY29yZGluZ2x5LlxuICAgICAqIFRoZSBvcHRpb25zIHBhc3NlZCBhcyBwYXJhbWV0ZXIocykgaXMgZWl0aGVyIG9uZSBvciBtYW55IG9iamVjdHMgdGhhdCBlYWNoIGNvbnRhaW5zIHNvbWUgc2V0dGluZ3MsIGllLiA6XG4gICAgICoge1xuICAgICAqICAgICBkaWdpdEdyb3VwU2VwYXJhdG9yOiBcIi5cIixcbiAgICAgKiAgICAgZGVjaW1hbENoYXJhY3RlcjogXCIsXCIsXG4gICAgICogICAgIGN1cnJlbmN5U3ltYm9sOiAn4oKsICcsXG4gICAgICogfVxuICAgICAqIElmIG11bHRpcGxlIG9wdGlvbnMgYXJlIHBhc3NlZCwgdGhlIGxhdHRlciBvdmVyd3JpdGUgdGhlIHByZXZpb3VzIG9uZXMuXG4gICAgICpcbiAgICAgKiBOb3RlOiBJZiB0aGUgbmV3IHNldHRpbmdzIGFyZSBub3QgdmFsaWRhdGVkLCBvciB0aGUgY2FsbCB0byBgc2V0KClgIGZhaWxzLCB0aGVuIHRoZSBwcmV2aW91cyB2YWxpZCBzZXR0aW5ncyBhcmUgcmV2ZXJ0ZWQgYmFjayB0by5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlIGFuRWxlbWVudC51cGRhdGUoeyBvcHRpb25zIH0pIC8vIFVwZGF0ZXMgdGhlIHNldHRpbmdzXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnVwZGF0ZSh7IG9wdGlvbnMxIH0sIHsgb3B0aW9uczIgfSkgLy8gVXBkYXRlcyB0aGUgc2V0dGluZ3Mgd2l0aCBtdWx0aXBsZSBvcHRpb24gb2JqZWN0c1xuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG5ld09wdGlvbnNcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgdXBkYXRlKC4uLm5ld09wdGlvbnMpIHtcbiAgICAgICAgLy8gS2VlcCBhIGNvcHkgb2YgdGhlIG9yaWdpbmFsIHNldHRpbmdzIGJlZm9yZSBjaGFuZ2luZyB0aGVtLCBpbiBjYXNlIHRoZXkgZG8gbm90IHZhbGlkYXRlIGNvcnJlY3RseSwgc28gd2UgY2FuIHN3aXRjaCBiYWNrIHRvIHRoZW1cbiAgICAgICAgY29uc3Qgb3JpZ2luYWxTZXR0aW5ncyA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHRoaXMuc2V0dGluZ3MpOyAvL1RPRE8gQ2hlY2sgdGhhdCB0aGUgYHN0eWxlUnVsZXNgIG9wdGlvbiBpcyBjb3JyZWN0bHkgY2xvbmVkIChkdWUgdG8gZGVwdGggY2xvbmluZyBsaW1pdGF0aW9uKVxuXG4gICAgICAgIC8vIFN0b3JlIHRoZSBjdXJyZW50IHVuZm9ybWF0dGVkIGlucHV0IHZhbHVlXG4gICAgICAgIGNvbnN0IG51bWVyaWNTdHJpbmcgPSB0aGlzLnJhd1ZhbHVlO1xuXG4gICAgICAgIC8vIEdlbmVyYXRlIGEgc2luZ2xlIG9wdGlvbiBvYmplY3Qgd2l0aCB0aGUgc2V0dGluZ3MgZnJvbSB0aGUgbGF0dGVyIG92ZXJ3cml0aW5nIHRob3NlIGZyb20gdGhlIGZvcm1lclxuICAgICAgICBsZXQgb3B0aW9uc1RvVXNlID0ge307XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkobmV3T3B0aW9ucykgfHwgbmV3T3B0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIG9wdGlvbnNUb1VzZSA9IG51bGw7XG4gICAgICAgIH0gZWxzZSBpZiAobmV3T3B0aW9ucy5sZW5ndGggPj0gMSkge1xuICAgICAgICAgICAgbmV3T3B0aW9ucy5mb3JFYWNoKG9wdGlvbk9iamVjdCA9PiB7XG4gICAgICAgICAgICAgICAgT2JqZWN0LmFzc2lnbihvcHRpb25zVG9Vc2UsIG9wdGlvbk9iamVjdCk7XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFVwZGF0ZSB0aGUgc2V0dGluZ3NcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMuX3NldFNldHRpbmdzKG9wdGlvbnNUb1VzZSwgdHJ1ZSk7XG5cbiAgICAgICAgICAgIC8vIFJlZm9ybWF0IHRoZSBpbnB1dCB2YWx1ZSB3aXRoIHRoZSBuZXcgc2V0dGluZ3NcbiAgICAgICAgICAgIC8vIE5vdGU6IHdlIGFsd2F5cyBgc2V0YCwgZXZlbiB3aGVuIGBudW1lcmljU3RyaW5nYCBpcyB0aGUgZW1wdHkgc3RyaW5nICcnLCBzaW5jZSBgZW1wdHlJbnB1dEJlaGF2aW9yYCAoc2V0IHRvIGBhbHdheXNgIG9yIGB6ZXJvYCkgY2FuIGNoYW5nZSBob3cgdGhlIGVtcHR5IGlucHV0IGlzIGZvcm1hdHRlZFxuICAgICAgICAgICAgdGhpcy5zZXQobnVtZXJpY1N0cmluZyk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgc2V0dGluZ3MgdmFsaWRhdGlvbiBmYWlscywgdGhlbiB3ZSBzd2l0Y2ggYmFjayB0byB0aGUgcHJldmlvdXMgdmFsaWQgc2V0dGluZ3NcbiAgICAgICAgICAgIHRoaXMuX3NldFNldHRpbmdzKG9yaWdpbmFsU2V0dGluZ3MsIHRydWUpOyAvLyBgX3NldFNldHRpbmdzKClgIGlzIHVzZWQgaGVyZSBpbnN0ZWFkIG9mIGRpcmVjdGx5IGRvaW5nIGB0aGlzLnNldHRpbmdzID0gb3JpZ2luYWxTZXR0aW5ncztgIHNpbmNlIGxvdHMgb2Ygc2lkZSB2YXJpYWJsZXMgYXJlIGNhbGN1bGF0ZWQgZnJvbSB0aGUgc2V0dGluZ3MsIGFuZCB3ZSBuZWVkIHRvIGdldCB0aG9zZSBiYWNrIHRvIHRoZWlyIHByZXZpb3VzIHN0YXRlLiBOb3RlOiBgX3NldFNldHRpbmdzKClgIGlzIGNhbGxlZCBpbiB0aGUgJ3VwZGF0ZScgbW9kZSBpbiBvcmRlciB0byBjb3JyZWN0bHkgc2V0IGJhY2sgdGhlIGBvcmlnaW5hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZWAgdmFsdWUuXG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBVbmFibGUgdG8gdXBkYXRlIHRoZSBzZXR0aW5ncywgdGhvc2UgYXJlIGludmFsaWQ6IFske2Vycm9yfV1gKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIG9wdGlvbnMgb2JqZWN0IGNvbnRhaW5pbmcgYWxsIHRoZSBjdXJyZW50IGF1dG9OdW1lcmljIHNldHRpbmdzIGluIGVmZmVjdC5cbiAgICAgKiBZb3UgY2FuIHRoZW4gZGlyZWN0bHkgYWNjZXNzIGVhY2ggb3B0aW9uIGJ5IHVzaW5nIGl0cyBuYW1lIDogYGFuRWxlbWVudC5nZXRTZXR0aW5ncygpLm9wdGlvbk5hbWVBdXRvQ29tcGxldGVkYC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogYW5FbGVtZW50LmdldFNldHRpbmdzKClcbiAgICAgKiBhbkVsZW1lbnQuZ2V0U2V0dGluZ3MoKS5kZWNpbWFsQ2hhcmFjdGVyIC8vIFJldHVybiB0aGUgZGVjaW1hbENoYXJhY3RlciBzZXR0aW5nIGFzIGEgc3RyaW5nIC0gYW55IHZhbGlkIG9wdGlvbiBuYW1lIGNhbiBiZSB1c2VkXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7b2JqZWN0fVxuICAgICAqL1xuICAgIGdldFNldHRpbmdzKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5zZXR0aW5ncztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGdpdmVuIGVsZW1lbnQgdmFsdWUsIGFuZCBmb3JtYXQgaXQgaW1tZWRpYXRlbHkuXG4gICAgICogQWRkaXRpb25hbGx5LCB0aGlzIGBzZXQoKWAgbWV0aG9kIGNhbiBhY2NlcHQgb3B0aW9ucyB0aGF0IHdpbGwgYmUgbWVyZ2VkIGludG8gdGhlIGN1cnJlbnQgQXV0b051bWVyaWMgZWxlbWVudCwgdGFraW5nIHByZWNlZGVuY2Ugb3ZlciBhbnkgcHJldmlvdXMgc2V0dGluZ3MuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZSBhbkVsZW1lbnQuc2V0KCcxMjM0NS42NycpIC8vIEZvcm1hdHMgdGhlIHZhbHVlXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnNldCgxMjM0NS42NykgLy8gRm9ybWF0cyB0aGUgdmFsdWVcbiAgICAgKiBAZXhhbXBsZSBhbkVsZW1lbnQuc2V0KDEyMzQ1LjY3LCB7IGRlY2ltYWxDaGFyYWN0ZXIgOiAnLCcgfSkgLy8gVXBkYXRlIHRoZSBzZXR0aW5ncyBhbmQgZm9ybWF0cyB0aGUgdmFsdWUgaW4gb25lIGdvXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50Lm5vcnRoQW1lcmljYW4oKS5zZXQoJyQxMiwzNDUuNjcnKSAvLyBTZXQgYW4gYWxyZWFkeSBmb3JtYXR0ZWQgdmFsdWUgKHRoaXMgZG9lcyBub3QgX2V4YWN0bHlfIHJlc3BlY3QgdGhlIGN1cnJlbmN5IHN5bWJvbC9uZWdhdGl2ZSBwbGFjZW1lbnRzLCBidXQgb25seSByZW1vdmUgYWxsIG5vbi1udW1iZXJzIGNoYXJhY3RlcnMsIGFjY29yZGluZyB0byB0aGUgb25lcyBnaXZlbiBpbiB0aGUgc2V0dGluZ3MpXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnNldChudWxsKSAvLyBTZXQgdGhlIHJhd1ZhbHVlIGFuZCBlbGVtZW50IHZhbHVlIHRvIGBudWxsYFxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfG51bGx9IG5ld1ZhbHVlIFRoZSB2YWx1ZSBtdXN0IGJlIGEgbnVtYmVyLCBhIG51bWVyaWMgc3RyaW5nIG9yIGBudWxsYCAoaWYgYGVtcHR5SW5wdXRCZWhhdmlvcmAgaXMgc2V0IHRvIGAnbnVsbCdgKVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zIEEgc2V0dGluZ3Mgb2JqZWN0IHRoYXQgd2lsbCBvdmVycmlkZSB0aGUgY3VycmVudCBzZXR0aW5ncy4gTm90ZTogdGhlIHVwZGF0ZSBpcyBkb25lIG9ubHkgaWYgdGhlIGBuZXdWYWx1ZWAgaXMgZGVmaW5lZC5cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNhdmVDaGFuZ2VUb0hpc3RvcnkgSWYgc2V0IHRvIGB0cnVlYCwgdGhlbiB0aGUgY2hhbmdlIGlzIHJlY29yZGVkIGluIHRoZSBoaXN0b3J5IHRhYmxlXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqIEB0aHJvd3NcbiAgICAgKi9cbiAgICBzZXQobmV3VmFsdWUsIG9wdGlvbnMgPSBudWxsLCBzYXZlQ2hhbmdlVG9IaXN0b3J5ID0gdHJ1ZSkge1xuICAgICAgICAvL1RPRE8gQWRkIHRoZSBgc2F2ZVNldHRpbmdzYCBvcHRpb25zLiBJZiBgdHJ1ZWAsIHRoZW4gd2hlbiBgb3B0aW9uc2AgaXMgcGFzc2VkLCB0aGVuIGl0IG92ZXJ3cml0ZSB0aGUgY3VycmVudCBgdGhpcy5zZXR0aW5nc2AuIElmIGBmYWxzZWAgdGhlIGBvcHRpb25zYCBhcmUgb25seSB1c2VkIG9uY2UgYW5kIGB0aGlzLnNldHRpbmdzYCBpcyBub3QgbW9kaWZpZWRcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKG5ld1ZhbHVlKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgWW91IGFyZSB0cnlpbmcgdG8gc2V0IGFuICd1bmRlZmluZWQnIHZhbHVlIDsgYW4gZXJyb3IgY291bGQgaGF2ZSBvY2N1cnJlZC5gLCB0aGlzLnNldHRpbmdzLnNob3dXYXJuaW5ncyk7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRoZSBvcHRpb25zIHVwZGF0ZSBpcyBkb25lIG9ubHkgaWYgdGhlIGBuZXdWYWx1ZWAgaXMgbm90IGB1bmRlZmluZWRgXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMpKSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRTZXR0aW5ncyhvcHRpb25zLCB0cnVlKTsgLy8gV2UgZG8gbm90IGNhbGwgYHVwZGF0ZWAgaGVyZSBzaW5jZSB0aGlzIHdvdWxkIGNhbGwgYHNldGAgdG9vXG4gICAgICAgIH1cblxuICAgICAgICBpZiAobmV3VmFsdWUgPT09IG51bGwgJiYgdGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLm51bGwpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFlvdSBhcmUgdHJ5aW5nIHRvIHNldCB0aGUgXFxgbnVsbFxcYCB2YWx1ZSB3aGlsZSB0aGUgXFxgZW1wdHlJbnB1dEJlaGF2aW9yXFxgIG9wdGlvbiBpcyBzZXQgdG8gJHt0aGlzLnNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvcn0uIElmIHlvdSB3YW50IHRvIGJlIGFibGUgdG8gc2V0IHRoZSBcXGBudWxsXFxgIHZhbHVlLCB5b3UgbmVlZCB0byBjaGFuZ2UgdGhlICdlbXB0eUlucHV0QmVoYXZpb3InIG9wdGlvbiB0byBcXGAnbnVsbCdcXGAuYCwgdGhpcy5zZXR0aW5ncy5zaG93V2FybmluZ3MpO1xuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgdmFsdWU7XG4gICAgICAgIGlmIChuZXdWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgLy9UT0RPIE1lcmdlIHRoaXMgaW50byBhIGdsb2JhbCBgaWYgKG5ld1ZhbHVlID09PSBudWxsKSB7YCB0ZXN0LCB3aXRoIHRoZSB0ZXN0IGFib3ZlXG4gICAgICAgICAgICAvLyBIZXJlIHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5udWxsXG4gICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50QW5kUmF3VmFsdWUobnVsbCwgbnVsbCwgc2F2ZUNoYW5nZVRvSGlzdG9yeSk7XG4gICAgICAgICAgICB0aGlzLl9zYXZlVmFsdWVUb1BlcnNpc3RlbnRTdG9yYWdlKCk7XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG5cbiAgICAgICAgdmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl90b051bWVyaWNWYWx1ZShuZXdWYWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgIGlmIChpc05hTihOdW1iZXIodmFsdWUpKSkge1xuICAgICAgICAgICAgLy9UT0RPIERvIG5vdCBtb2RpZnkgdGhlIGVsZW1lbnQgdmFsdWUgaWYgdGhlIG5ld1ZhbHVlIHJlc3VsdHMgaW4gYE5hTmAuIE1ha2Ugc3VyZSB0aGUgc2V0dGluZ3MsIGlmIG1vZGlmaWVkLCBhcmUgcmV2ZXJ0IGJhY2sgdG9vLlxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgVGhlIHZhbHVlIHlvdSBhcmUgdHJ5aW5nIHRvIHNldCByZXN1bHRzIGluIFxcYE5hTlxcYC4gVGhlIGVsZW1lbnQgdmFsdWUgaXMgc2V0IHRvIHRoZSBlbXB0eSBzdHJpbmcgaW5zdGVhZC5gLCB0aGlzLnNldHRpbmdzLnNob3dXYXJuaW5ncyk7XG4gICAgICAgICAgICB0aGlzLnNldFZhbHVlKCcnLCBzYXZlQ2hhbmdlVG9IaXN0b3J5KTtcblxuICAgICAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGlmICh2YWx1ZSA9PT0gJycgJiYgdGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLnplcm8pIHtcbiAgICAgICAgICAgIC8vIEtlZXAgdGhlIHZhbHVlIHplcm8gaW5zaWRlIHRoZSBlbGVtZW50XG4gICAgICAgICAgICB2YWx1ZSA9IDA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUgIT09ICcnKSB7XG4gICAgICAgICAgICBjb25zdCBbbWluVGVzdCwgbWF4VGVzdF0gPSB0aGlzLmNvbnN0cnVjdG9yLl9jaGVja0lmSW5SYW5nZVdpdGhPdmVycmlkZU9wdGlvbih2YWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgICAgICAvLyBUaGlzIHRlc3QgaXMgbmVlZGVkIGJ5IHRoZSBgc2hvd1Bvc2l0aXZlU2lnbmAgb3B0aW9uXG4gICAgICAgICAgICBjb25zdCBpc1plcm8gPSBBdXRvTnVtZXJpY0hlbHBlci5pc1plcm9Pckhhc05vVmFsdWUodmFsdWUpO1xuICAgICAgICAgICAgaWYgKGlzWmVybykge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gJzAnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAobWluVGVzdCAmJiBtYXhUZXN0KSB7XG4gICAgICAgICAgICAgICAgbGV0IGZvcmNlZFJhd1ZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fcm91bmRSYXdWYWx1ZSh2YWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgZm9yY2VkUmF3VmFsdWUgPSB0aGlzLl90cmltTGVhZGluZ0FuZFRyYWlsaW5nWmVyb3MoZm9yY2VkUmF3VmFsdWUucmVwbGFjZSh0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIsICcuJykpOyAvLyBNb3ZlIHRoZSBgc2V0UmF3VmFsdWVgIGNhbGwgYWZ0ZXIgdGhlIGBzZXRFbGVtZW50VmFsdWVgIG9uZVxuICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5fZ2V0UmF3VmFsdWVUb0Zvcm1hdCh2YWx1ZSk7IC8vIE11bHRpcGx5IHRoZSByYXcgdmFsdWUgdG8gb2J0YWluIHRoZSBmb3JtYXR0ZWQgdmFsdWVcblxuICAgICAgICAgICAgICAgIC8vIFJvdW5kIHRoZSBnaXZlbiB2YWx1ZSBhY2NvcmRpbmcgdG8gdGhlIG9iamVjdCBzdGF0ZSAoZm9jdXNlZC91bmZvY3VzZWQpXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuaXNGb2N1c2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fcm91bmRGb3JtYXR0ZWRWYWx1ZVNob3duT25Gb2N1cyh2YWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuZGl2aXNvcldoZW5VbmZvY3VzZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdmFsdWUgLyB0aGlzLnNldHRpbmdzLmRpdmlzb3JXaGVuVW5mb2N1c2VkO1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9yb3VuZEZvcm1hdHRlZFZhbHVlU2hvd25PbkJsdXIodmFsdWUsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fbW9kaWZ5TmVnYXRpdmVTaWduQW5kRGVjaW1hbENoYXJhY3RlckZvckZvcm1hdHRlZFZhbHVlKHZhbHVlLCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX2FkZEdyb3VwU2VwYXJhdG9ycyh2YWx1ZSwgdGhpcy5zZXR0aW5ncywgdGhpcy5pc0ZvY3VzZWQsIHRoaXMucmF3VmFsdWUsIGZvcmNlZFJhd1ZhbHVlKTtcbiAgICAgICAgICAgICAgICBpZiAoIXRoaXMuaXNGb2N1c2VkICYmIHRoaXMuc2V0dGluZ3Muc3ltYm9sV2hlblVuZm9jdXNlZCkge1xuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IGAke3ZhbHVlfSR7dGhpcy5zZXR0aW5ncy5zeW1ib2xXaGVuVW5mb2N1c2VkfWA7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyB8fCB0aGlzLnNldHRpbmdzLmRpdmlzb3JXaGVuVW5mb2N1c2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NhdmVWYWx1ZVRvUGVyc2lzdGVudFN0b3JhZ2UoKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50QW5kUmF3VmFsdWUodmFsdWUsIGZvcmNlZFJhd1ZhbHVlLCBzYXZlQ2hhbmdlVG9IaXN0b3J5KTtcblxuICAgICAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoIW1pblRlc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5taW5SYW5nZUV4Y2VlZGVkLCB0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmICghbWF4VGVzdCkge1xuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLm1heFJhbmdlRXhjZWVkZWQsIHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHZhbHVlIFske3ZhbHVlfV0gYmVpbmcgc2V0IGZhbGxzIG91dHNpZGUgb2YgdGhlIG1pbmltdW1WYWx1ZSBbJHt0aGlzLnNldHRpbmdzLm1pbmltdW1WYWx1ZX1dIGFuZCBtYXhpbXVtVmFsdWUgWyR7dGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWV9XSByYW5nZSBzZXQgZm9yIHRoaXMgZWxlbWVudGApO1xuXG4gICAgICAgICAgICAgICAgdGhpcy5fcmVtb3ZlVmFsdWVGcm9tUGVyc2lzdGVudFN0b3JhZ2UoKTtcbiAgICAgICAgICAgICAgICB0aGlzLnNldFZhbHVlKCcnLCBzYXZlQ2hhbmdlVG9IaXN0b3J5KTsgLy9UT0RPIFNob3VsZG4ndCB3ZSBqdXN0IGRyb3AgdGhhdCBmYXVsdHkgbmV3VmFsdWUgYW5kIGtlZXAgdGhlIHByZXZpb3VzIG9uZT8gVGhpcyBpcyBiZWhpbmQgYSBgdGhyb3dFcnJvcigpYCBjYWxsIGFueXdheS4uXG5cbiAgICAgICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEhlcmUsIGB2YWx1ZWAgZXF1YWwgdGhlIGVtcHR5IHN0cmluZyBgJydgXG4gICAgICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5hbHdheXMpIHtcbiAgICAgICAgICAgICAgICAvLyBLZWVwIHRoZSBjdXJyZW5jeSBzeW1ib2wgYXMgcGVyIGVtcHR5SW5wdXRCZWhhdmlvclxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2w7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9ICcnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50QW5kUmF3VmFsdWUocmVzdWx0LCAnJywgc2F2ZUNoYW5nZVRvSGlzdG9yeSk7XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBnaXZlbiB2YWx1ZSBkaXJlY3RseSBhcyB0aGUgRE9NIGVsZW1lbnQgdmFsdWUsIHdpdGhvdXQgZm9ybWF0dGluZyBpdCBiZWZvcmVoYW5kLlxuICAgICAqIFlvdSBjYW4gYWxzbyBzZXQgdGhlIHZhbHVlIGFuZCB1cGRhdGUgdGhlIHNldHRpbmcgaW4gb25lIGdvICh0aGUgdmFsdWUgd2lsbCBhZ2FpbiBub3QgYmUgZm9ybWF0dGVkIGltbWVkaWF0ZWx5KS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ30gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uc1xuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKiBAdGhyb3dzXG4gICAgICovXG4gICAgc2V0VW5mb3JtYXR0ZWQodmFsdWUsIG9wdGlvbnMgPSBudWxsKSB7XG4gICAgICAgIC8vVE9ETyBTaG91bGQgd2UgdXNlIGBBdXRvTnVtZXJpYy51bmZvcm1hdCgpYCBoZXJlIGFuZCBzZXQgdGhlIHVuZm9ybWF0dGVkIHJlc3VsdCBpbiBjYXNlIGB2YWx1ZWAgaXMgZm9ybWF0dGVkP1xuICAgICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRoZSBvcHRpb25zIHVwZGF0ZSBpcyBkb25lIG9ubHkgaWYgdGhlIGB2YWx1ZWAgaXMgbm90IG51bGxcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucykpIHtcbiAgICAgICAgICAgIHRoaXMuX3NldFNldHRpbmdzKG9wdGlvbnMsIHRydWUpOyAvLyBXZSBkbyBub3QgY2FsbCBgdXBkYXRlYCBoZXJlIHNpbmNlIHRoaXMgd291bGQgY2FsbCBgc2V0YCB0b29cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHN0cmlwcGVkVmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9yZW1vdmVCcmFja2V0cyh2YWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgIGxldCBub3JtYWxpemVkVmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnMoc3RyaXBwZWRWYWx1ZSwgdGhpcy5zZXR0aW5ncywgdHJ1ZSwgdGhpcy5pc0ZvY3VzZWQpO1xuICAgICAgICBub3JtYWxpemVkVmFsdWUgPSBub3JtYWxpemVkVmFsdWUucmVwbGFjZSh0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIsICcuJyk7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIobm9ybWFsaXplZFZhbHVlKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHZhbHVlIGlzIG5vdCBhIHZhbGlkIG9uZSwgaXQncyBub3QgYSBudW1lcmljIHN0cmluZyBub3IgYSByZWNvZ25pemVkIGN1cnJlbmN5LmApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgW21pblRlc3QsIG1heFRlc3RdID0gdGhpcy5jb25zdHJ1Y3Rvci5fY2hlY2tJZkluUmFuZ2VXaXRoT3ZlcnJpZGVPcHRpb24obm9ybWFsaXplZFZhbHVlLCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgaWYgKG1pblRlc3QgJiYgbWF4VGVzdCkge1xuICAgICAgICAgICAgLy8gSWYgdGhlIGBub3JtYWxpemVkVmFsdWVgIGlzIGluIHRoZSByYW5nZVxuICAgICAgICAgICAgdGhpcy5zZXRWYWx1ZSh2YWx1ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdmFsdWUgaXMgb3V0IG9mIHRoZSByYW5nZSBsaW1pdHMgWyR7dGhpcy5zZXR0aW5ncy5taW5pbXVtVmFsdWV9LCAke3RoaXMuc2V0dGluZ3MubWF4aW11bVZhbHVlfV0uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGdpdmVuIHZhbHVlIGRpcmVjdGx5IGFzIHRoZSBET00gZWxlbWVudCB2YWx1ZSwgd2l0aG91dCBmb3JtYXR0aW5nIGl0IGJlZm9yZWhhbmQsIGFuZCB3aXRob3V0IGNoZWNraW5nIGl0cyB2YWxpZGl0eS5cbiAgICAgKiBUaGlzIGFsc28gdXBkYXRlcyB0aGUgYHJhd1ZhbHVlYCB3aXRoIHRoZSBnaXZlbiBgbmV3VmFsdWVgLCB3aXRob3V0IGNoZWNraW5nIGl0IHRvbyA7IGlmIGl0J3Mgbm90IGZvcm1hdHRlZCBsaWtlIGEgbnVtYmVyIHJlY29nbml6ZWQgYnkgSmF2YXNjcmlwdCwgdGhpcyAqd2lsbCogbGlrZWx5IG1ha2Ugb3RoZXIgQXV0b051bWVyaWMgbWV0aG9kcyBmYWlsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfG51bGx9IG5ld1ZhbHVlIFRoZSBuZXcgdmFsdWUgdG8gc2V0IG9uIHRoZSBlbGVtZW50XG4gICAgICogQHBhcmFtIHtib29sZWFufSBzYXZlQ2hhbmdlVG9IaXN0b3J5IElmIHNldCB0byBgdHJ1ZWAsIHRoZW4gdGhlIGNoYW5nZSBpcyByZWNvcmRlZCBpbiB0aGUgaGlzdG9yeSBhcnJheSwgb3RoZXJ3aXNlIGl0IGlzIG5vdFxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBzZXRWYWx1ZShuZXdWYWx1ZSwgc2F2ZUNoYW5nZVRvSGlzdG9yeSA9IHRydWUpIHtcbiAgICAgICAgdGhpcy5fc2V0RWxlbWVudEFuZFJhd1ZhbHVlKG5ld1ZhbHVlLCBzYXZlQ2hhbmdlVG9IaXN0b3J5KTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTYXZlIHRoZSByYXcgdmFsdWUgaW5zaWRlIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd8bnVsbH0gcmF3VmFsdWUgVGhlIG51bWVyaWMgdmFsdWUgYXMgdW5kZXJzdG9vZCBieSBKYXZhc2NyaXB0IGxpa2UgYSBgTnVtYmVyYFxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2F2ZUNoYW5nZVRvSGlzdG9yeSBJZiBzZXQgdG8gYHRydWVgLCB0aGVuIHRoZSBjaGFuZ2UgaXMgcmVjb3JkZWQgaW4gdGhlIGhpc3RvcnkgYXJyYXksIG90aGVyd2lzZSBpdCBpcyBub3RcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zZXRSYXdWYWx1ZShyYXdWYWx1ZSwgc2F2ZUNoYW5nZVRvSGlzdG9yeSA9IHRydWUpIHtcbiAgICAgICAgLy8gT25seSBzZXQgdGhlIHJhdyB2YWx1ZSBpZiB0aGUgZ2l2ZW4gdmFsdWUgaXMgZGlmZmVyZW50IHRoYW4gdGhlIGN1cnJlbnQgb25lXG4gICAgICAgIGlmICh0aGlzLnJhd1ZhbHVlICE9PSByYXdWYWx1ZSkgeyAvL1RPRE8gTWFuYWdlIHRoZSBjYXNlIHdoZXJlIG9uZSB2YWx1ZSBpcyBhIHN0cmluZyB3aGlsZSB0aGUgb3RoZXIgaXMgYSBudW1iZXI/XG4gICAgICAgICAgICAvLyBVcGRhdGUgdGhlIHJhdyB2YWx1ZVxuICAgICAgICAgICAgdGhpcy5yYXdWYWx1ZSA9IHJhd1ZhbHVlOyAvLyBCeSBkZWZhdWx0LCBpZiB0aGUgYHJhd1ZhbHVlYCBpcyBjaGFuZ2VkIHByb2dyYW1tYXRpY2FsbHlcblxuICAgICAgICAgICAgaWYgKCghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHRoaXMuc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yKSAmJiB0aGlzLnNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvciAhPT0gMCkgJiYgLy8gT25seSBkaXZpZGUgaWYgdGhlIGByYXdWYWx1ZURpdmlzb3JgIG9wdGlvbiBpcyBzZXRcbiAgICAgICAgICAgICAgICByYXdWYWx1ZSAhPT0gJycgJiYgcmF3VmFsdWUgIT09IG51bGwgJiYgLy8gRG8gbm90IG1vZGlmeSB0aGUgYHJhd1ZhbHVlYCBpZiBpdCdzIGFuIGVtcHR5IHN0cmluZyBvciBudWxsXG4gICAgICAgICAgICAgICAgdGhpcy5faXNVc2VyTWFudWFsbHlFZGl0aW5nVGhlVmFsdWUoKSkgeyAvLyBJZiB0aGUgdXNlciBpcyBtYW51YWxseSBjaGFuZ2luZyB0aGUgZWxlbWVudCB2YWx1ZVxuICAgICAgICAgICAgICAgIHRoaXMucmF3VmFsdWUgLz0gdGhpcy5zZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3I7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIENoYW5nZSB0aGUgZWxlbWVudCBzdHlsZSBvciB1c2UgdGhlIHJlbGV2YW50IGNhbGxiYWNrc1xuICAgICAgICAgICAgdGhpcy5fcGFyc2VTdHlsZVJ1bGVzKCk7XG5cbiAgICAgICAgICAgIGlmIChzYXZlQ2hhbmdlVG9IaXN0b3J5KSB7XG4gICAgICAgICAgICAgICAgLy8gU2F2ZSBpbiB0aGUgaGlzdG9yeSB0aGUgbGFzdCBrbm93biByYXcgdmFsdWUgYW5kIGZvcm1hdHRlZCByZXN1bHQgc2VsZWN0aW9uXG4gICAgICAgICAgICAgICAgdGhpcy5faGlzdG9yeVRhYmxlQWRkKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGdpdmVuIHZhbHVlIG9uIHRoZSBET00gZWxlbWVudCwgd2l0aG91dCBhZmZlY3RpbmcgdGhlIGByYXdWYWx1ZWAuXG4gICAgICogVGhpcyBzZW5kIGFuICdhdXRvTnVtZXJpYzpmb3JtYXR0ZWQnIGV2ZW50IGlmIHRoZSBuZXcgdmFsdWUgaXMgZGlmZmVyZW50IHRoYW4gdGhlIG9sZCBvbmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IG5ld0VsZW1lbnRWYWx1ZVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zZXRFbGVtZW50VmFsdWUobmV3RWxlbWVudFZhbHVlKSB7XG4gICAgICAgIC8vVE9ETyBVc2UgYW4gaW50ZXJuYWwgYXR0cmlidXRlIHRvIHRyYWNrIHRoZSBjdXJyZW50IHZhbHVlIG9mIHRoZSBlbGVtZW50IGBmb3JtYXR0ZWRWYWx1ZWAgKGxpa2UgaXRzIGNvdW50ZXJwYXJ0IGByYXdWYWx1ZWApLiBUaGlzIHdvdWxkIGFsbG93IHVzIHRvIGF2b2lkIGNhbGxpbmcgYGdldEVsZW1lbnRWYWx1ZWAgbWFueSB0aW1lc1xuICAgICAgICAvLyBgb2xkRWxlbWVudFZhbHVlYCBpcyB0aGUgcHJldmlvdXMgdmFsdWUgdGhhdCB3aWxsIGJlIG92ZXJ3cml0dGVuLiBUaGlzIGlzIHVzZWQgdG8gZGVjaWRlIGlmIGFuIGV2ZW50IHNob3VsZCBiZSBzZW50IG9yIG5vdC5cbiAgICAgICAgY29uc3Qgb2xkRWxlbWVudFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCk7XG5cbiAgICAgICAgaWYgKG5ld0VsZW1lbnRWYWx1ZSAhPT0gb2xkRWxlbWVudFZhbHVlKSB7XG4gICAgICAgICAgICAvLyBPbmx5IHVwZGF0ZSB0aGUgdmFsdWUgaWYgaXQncyBkaWZmZXJlbnQgZnJvbSB0aGUgY3VycmVudCBvbmVcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQsIG5ld0VsZW1lbnRWYWx1ZSk7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLmZvcm1hdHRlZCwgdGhpcy5kb21FbGVtZW50LCB7IG9sZFZhbHVlOiBvbGRFbGVtZW50VmFsdWUsIG5ld1ZhbHVlOiBuZXdFbGVtZW50VmFsdWUgfSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGdpdmVuIHZhbHVlIG9uIHRoZSBET00gZWxlbWVudCwgYW5kIHRoZSByYXcgdmFsdWUgb24gYHRoaXMucmF3VmFsdWVgLCBpZiBib3RoIGFyZSBnaXZlbi5cbiAgICAgKiBJZiBvbmx5IG9uZSB2YWx1ZSBpcyBnaXZlbiwgdGhlbiBib3RoIHRoZSBET00gZWxlbWVudCB2YWx1ZSBhbmQgdGhlIHJhdyB2YWx1ZSBhcmUgc2V0IHdpdGggdGhhdCB2YWx1ZS5cbiAgICAgKiBUaGUgdGhpcmQgYXJndW1lbnQgYHNhdmVDaGFuZ2VUb0hpc3RvcnlgIGRlZmluZXMgaWYgdGhlIGNoYW5nZSBzaG91bGQgYmUgcmVjb3JkZWQgaW4gdGhlIGhpc3RvcnkgYXJyYXkuXG4gICAgICogTm90ZTogaWYgdGhlIHNlY29uZCBhcmd1bWVudCBgcmF3VmFsdWVgIGlzIGEgYm9vbGVhbiwgd2UgY29uc2lkZXIgdGhhdCBpcyByZWFsbHkgaXMgdGhlIGBzYXZlQ2hhbmdlVG9IaXN0b3J5YCBhcmd1bWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ3xudWxsfSBuZXdFbGVtZW50VmFsdWVcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd8bnVsbHxib29sZWFufSByYXdWYWx1ZVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gc2F2ZUNoYW5nZVRvSGlzdG9yeVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zZXRFbGVtZW50QW5kUmF3VmFsdWUobmV3RWxlbWVudFZhbHVlLCByYXdWYWx1ZSA9IG51bGwsIHNhdmVDaGFuZ2VUb0hpc3RvcnkgPSB0cnVlKSB7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwocmF3VmFsdWUpKSB7XG4gICAgICAgICAgICByYXdWYWx1ZSA9IG5ld0VsZW1lbnRWYWx1ZTtcbiAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ocmF3VmFsdWUpKSB7XG4gICAgICAgICAgICBzYXZlQ2hhbmdlVG9IaXN0b3J5ID0gcmF3VmFsdWU7XG4gICAgICAgICAgICByYXdWYWx1ZSA9IG5ld0VsZW1lbnRWYWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vWFhYIFRoZSBvcmRlciBoZXJlIGlzIGltcG9ydGFudCA7IHRoZSB2YWx1ZSBzaG91bGQgZmlyc3QgYmUgc2V0IG9uIHRoZSBlbGVtZW50LCB0aGVuIGFuZCBvbmx5IHRoZW4gd2Ugc2hvdWxkIHVwZGF0ZSB0aGUgcmF3IHZhbHVlXG4gICAgICAgIC8vIEluIHRoZSBgc2V0KClgIGZ1bmN0aW9uLCB3ZSBtYWtlIHN1cmUgdG8gY2FsbCBgX3NldFJhd1ZhbHVlYCAqYWZ0ZXIqIGBzZXRFbGVtZW50VmFsdWVgIHNvIHRoYXQgaWYgYF9zZXRSYXdWYWx1ZWAgY2FsbHMgYSBjYWxsYmFjayB0aGF0IG1vZGlmeSB0aGUgYHJhd1ZhbHVlYCwgdGhlbiB0aGUgbmV3IHZhbHVlIGlzIHNldCBjb3JyZWN0bHkgKGFmdGVyIGBzZXRFbGVtZW50VmFsdWVgIGJyaWVmbHkgc2V0IGl0cyB2YWx1ZSBmaXJzdClcbiAgICAgICAgdGhpcy5fc2V0RWxlbWVudFZhbHVlKG5ld0VsZW1lbnRWYWx1ZSk7XG4gICAgICAgIHRoaXMuX3NldFJhd1ZhbHVlKHJhd1ZhbHVlLCBzYXZlQ2hhbmdlVG9IaXN0b3J5KTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIG11bHRpcGxpZWQgcmF3IHZhbHVlIHdpdGggdGhlIGByYXdWYWx1ZURpdmlzb3JgLlxuICAgICAqIFRoaXMgaXMgdXNlZCB0byBkaXNwbGF5IGRpZmZlcmVudCB2YWx1ZXMgYmV0d2VlbiB0aGUgcmF3IGFuZCBmb3JtYXR0ZWQgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfG51bGx9IHJhd1ZhbHVlIFRoZSBudW1lcmljIHZhbHVlIGFzIHVuZGVyc3Rvb2QgYnkgSmF2YXNjcmlwdCBsaWtlIGEgYE51bWJlcmBcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfHN0cmluZ3xudWxsfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2dldFJhd1ZhbHVlVG9Gb3JtYXQocmF3VmFsdWUpIHtcbiAgICAgICAgbGV0IHJhd1ZhbHVlRm9yVGhlRWxlbWVudFZhbHVlO1xuICAgICAgICBpZiAoKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodGhpcy5zZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IpICYmIHRoaXMuc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yICE9PSAwKSAmJiAvLyBPbmx5IG11bHRpcGx5IGlmIHRoZSBgcmF3VmFsdWVEaXZpc29yYCBvcHRpb24gaXMgc2V0XG4gICAgICAgICAgICByYXdWYWx1ZSAhPT0gJycgJiYgcmF3VmFsdWUgIT09IG51bGwpIHsgLy8gRG8gbm90IG1vZGlmeSB0aGUgYHJhd1ZhbHVlYCBpZiBpdCdzIGFuIGVtcHR5IHN0cmluZyBvciBudWxsXG4gICAgICAgICAgICAvLyAhdGhpcy5faXNVc2VyTWFudWFsbHlFZGl0aW5nVGhlVmFsdWUoKSkgeyAvLyBJZiB0aGUgdXNlciBpcyBOT1QgbWFudWFsbHkgY2hhbmdpbmcgdGhlIGVsZW1lbnQgdmFsdWUsIGJ1dCB0aGF0IGlzIGRvbmUgcHJvZ3JhbW1hdGljYWxseVxuICAgICAgICAgICAgcmF3VmFsdWVGb3JUaGVFbGVtZW50VmFsdWUgPSByYXdWYWx1ZSAqIHRoaXMuc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmF3VmFsdWVGb3JUaGVFbGVtZW50VmFsdWUgPSByYXdWYWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByYXdWYWx1ZUZvclRoZUVsZW1lbnRWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSB1c2VyIGlzIGN1cnJlbnRseSBtb2RpZnlpbmcgdGhlIGVsZW1lbnQgdmFsdWUgbWFudWFsbHkuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9pc1VzZXJNYW51YWxseUVkaXRpbmdUaGVWYWx1ZSgpIHtcbiAgICAgICAgLy8gcmV0dXJuICh0aGlzLmlzRm9jdXNlZCAmJiB0aGlzLmlzRWRpdGluZykgfHwgdGhpcy5pc1doZWVsRXZlbnQgfHwgdGhpcy5pc0Ryb3BFdmVudDtcbiAgICAgICAgcmV0dXJuICh0aGlzLmlzRm9jdXNlZCAmJiB0aGlzLmlzRWRpdGluZykgfHwgdGhpcy5pc0Ryb3BFdmVudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFeGVjdXRlIHRoZSBnaXZlbiBjYWxsYmFjayBmdW5jdGlvbiB1c2luZyB0aGUgZ2l2ZW4gcmVzdWx0IGFzIGl0cyBmaXJzdCBwYXJhbWV0ZXIsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGFzIGl0cyBzZWNvbmQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd8QXJyYXl8bnVsbH0gcmVzdWx0XG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZXhlY3V0ZUNhbGxiYWNrKHJlc3VsdCwgY2FsbGJhY2spIHtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoY2FsbGJhY2spICYmIEF1dG9OdW1lcmljSGVscGVyLmlzRnVuY3Rpb24oY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBjYWxsYmFjayhyZXN1bHQsIHRoaXMpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWxpYXMgb2YgdGhlIGBnZXROdW1lcmljU3RyaW5nKClgIGZ1bmN0aW9uLlxuICAgICAqIERldmVsb3BlcnMgc2hvdWxkIHVzZSBvbmUgb2YgdGhlIG1vcmUgZXhwbGljaXQgZnVuY3Rpb24gbmFtZXMgdG8gZ2V0IHdoYXQgdGhleSB3YW50IDpcbiAgICAgKiAtIGEgbnVtZXJpYyBzdHJpbmcgOiBgZ2V0TnVtZXJpY1N0cmluZygpYFxuICAgICAqIC0gYSBmb3JtYXR0ZWQgc3RyaW5nIDogYGdldEZvcm1hdHRlZCgpYFxuICAgICAqIC0gYSBudW1iZXIgOiBgZ2V0TnVtYmVyKClgLCBvclxuICAgICAqIC0gYSBsb2NhbGl6ZWQgbnVtZXJpYyBzdHJpbmcgOiBgZ2V0TG9jYWxpemVkKClgXG4gICAgICpcbiAgICAgKiBAdXNhZ2UgYW5FbGVtZW50LmdldCgpO1xuICAgICAqXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICpcbiAgICAgKiBAZGVwcmVjYXRlZFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH1cbiAgICAgKi9cbiAgICBnZXQoY2FsbGJhY2sgPSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmdldE51bWVyaWNTdHJpbmcoY2FsbGJhY2spO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgdW5mb3JtYXR0ZWQgdmFsdWUgYXMgYSBzdHJpbmcuXG4gICAgICogVGhpcyBjYW4gYWxzbyByZXR1cm4gYG51bGxgIGlmIGByYXdWYWx1ZWAgaXMgbnVsbC5cbiAgICAgKlxuICAgICAqIEB1c2FnZSBhbkVsZW1lbnQuZ2V0TnVtZXJpY1N0cmluZygpO1xuICAgICAqXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gICAgICovXG4gICAgZ2V0TnVtZXJpY1N0cmluZyhjYWxsYmFjayA9IG51bGwpIHtcbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbCh0aGlzLnJhd1ZhbHVlKSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEFsd2F5cyByZXR1cm4gYSBudW1lcmljIHN0cmluZ1xuICAgICAgICAgICAgLy8gVGhlIGZvbGxvd2luZyBzdGF0ZW1lbnQgZ2V0cyByaWQgb2YgdGhlIHRyYWlsaW5nIHplcm9zIGluIHRoZSBkZWNpbWFsIHBsYWNlcyBzaW5jZSB0aGUgY3VycmVudCBtZXRob2QgZG9lcyBub3QgcGFkIGRlY2ltYWxzXG4gICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0hlbHBlci50cmltUGFkZGVkWmVyb3NGcm9tRGVjaW1hbFBsYWNlcyh0aGlzLnJhd1ZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2V4ZWN1dGVDYWxsYmFjayhyZXN1bHQsIGNhbGxiYWNrKTtcblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgY3VycmVudCBmb3JtYXR0ZWQgdmFsdWUgb2YgdGhlIEF1dG9OdW1lcmljIGVsZW1lbnQgYXMgYSBzdHJpbmdcbiAgICAgKlxuICAgICAqIEB1c2FnZSBhbkVsZW1lbnQuZ2V0Rm9ybWF0dGVkKClcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2sgSWYgYSBjYWxsYmFjayBpcyBwYXNzZWQsIHRoZW4gdGhlIHJlc3VsdCBpcyBwYXNzZWQgdG8gaXQgYXMgaXRzIGZpcnN0IGFyZ3VtZW50LCBhbmQgdGhlIEF1dG9OdW1lcmljIG9iamVjdCBoYXMgaXRzIHNlY29uZFxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBnZXRGb3JtYXR0ZWQoY2FsbGJhY2sgPSBudWxsKSB7XG4gICAgICAgIGlmICghKCd2YWx1ZScgaW4gdGhpcy5kb21FbGVtZW50IHx8ICd0ZXh0Q29udGVudCcgaW4gdGhpcy5kb21FbGVtZW50KSkge1xuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIGAudmFsdWVgIG9yIGAudGV4dENvbnRlbnQnIGV4aXN0cyBiZWZvcmUgdHJ5aW5nIHRvIGFjY2VzcyB0aG9zZSBwcm9wZXJ0aWVzXG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKCdVbmFibGUgdG8gZ2V0IHRoZSBmb3JtYXR0ZWQgc3RyaW5nIGZyb20gdGhlIGVsZW1lbnQuJyk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgdGhpcy5fZXhlY3V0ZUNhbGxiYWNrKHJlc3VsdCwgY2FsbGJhY2spO1xuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBlbGVtZW50IHVuZm9ybWF0dGVkIHZhbHVlIGFzIGEgcmVhbCBKYXZhc2NyaXB0IG51bWJlci5cbiAgICAgKiBXYXJuaW5nOiBUaGlzIGNhbiBsZWFkIHRvIHByZWNpc2lvbiBwcm9ibGVtcyB3aXRoIGJpZyBudW1iZXJzIHRoYXQgc2hvdWxkIGJlIHN0b3JlZCBhcyBzdHJpbmdzLlxuICAgICAqXG4gICAgICogQHVzYWdlIGFuRWxlbWVudC5nZXROdW1iZXIoKVxuICAgICAqXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbnxudWxsfSBjYWxsYmFjayBJZiBhIGNhbGxiYWNrIGlzIHBhc3NlZCwgdGhlbiB0aGUgcmVzdWx0IGlzIHBhc3NlZCB0byBpdCBhcyBpdHMgZmlyc3QgYXJndW1lbnQsIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBpdHMgc2Vjb25kXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfG51bGx9XG4gICAgICovXG4gICAgZ2V0TnVtYmVyKGNhbGxiYWNrID0gbnVsbCkge1xuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAodGhpcy5yYXdWYWx1ZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmVzdWx0ID0gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuY29uc3RydWN0b3IuX3RvTG9jYWxlKHRoaXMuZ2V0TnVtZXJpY1N0cmluZygpLCAnbnVtYmVyJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9leGVjdXRlQ2FsbGJhY2socmVzdWx0LCBjYWxsYmFjayk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSB1bmZvcm1hdHRlZCB2YWx1ZSwgYnV0IGZvbGxvd2luZyB0aGUgYG91dHB1dEZvcm1hdGAgc2V0dGluZywgd2hpY2ggbWVhbnMgdGhlIG91dHB1dCBjYW4gZWl0aGVyIGJlIDpcbiAgICAgKiAtIGEgc3RyaW5nICh0aGF0IGNvdWxkIG9yIGNvdWxkIG5vdCByZXByZXNlbnQgYSBudW1iZXIgKGllLiBcIjEyMzQ1LDY3LVwiKSksIG9yXG4gICAgICogLSBhIHBsYWluIG51bWJlciAoaWYgdGhlIHNldHRpbmcgJ251bWJlcicgaXMgdXNlZCkuXG4gICAgICpcbiAgICAgKiBCeSBkZWZhdWx0IHRoZSByZXR1cm5lZCB2YWx1ZXMgYXJlIGFuIElTTyBudW1lcmljIHN0cmluZyBcIjEyMzQuNTZcIiBvciBcIi0xMjM0LjU2XCIgd2hlcmUgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGlzIGEgcGVyaW9kLlxuICAgICAqIENoZWNrIHRoZSBcIm91dHB1dEZvcm1hdFwiIG9wdGlvbiBkZWZpbml0aW9uIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBAdXNhZ2UgYW5FbGVtZW50LmdldExvY2FsaXplZCgpO1xuICAgICAqXG4gICAgICogQHBhcmFtIHtudWxsfHN0cmluZ3xmdW5jdGlvbn0gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gYG51bGxgLCB0aGVuIHRoaXMgaXMgdXNlZCBhcyBhbiBvdmVycmlkaW5nIG91dHB1dEZvcm1hdCBvcHRpb25cbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrIElmIGEgY2FsbGJhY2sgaXMgcGFzc2VkLCB0aGVuIHRoZSByZXN1bHQgaXMgcGFzc2VkIHRvIGl0IGFzIGl0cyBmaXJzdCBhcmd1bWVudCwgYW5kIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgaGFzIGl0cyBzZWNvbmRcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIGdldExvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsLCBjYWxsYmFjayA9IG51bGwpIHtcbiAgICAgICAgLy8gRmlyc3QsIGNoZWNrIGlmIG9ubHkgYSBjYWxsYmFjayBoYXMgYmVlbiBwYXNzZWQsIGFuZCBpZiBzbywgc2FuaXRpemUgdGhlIHBhcmFtZXRlcnNcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRnVuY3Rpb24oZm9yY2VkT3V0cHV0Rm9ybWF0KSAmJiBBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBjYWxsYmFjayA9IGZvcmNlZE91dHB1dEZvcm1hdDtcbiAgICAgICAgICAgIGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGVuIGdldCB0aGUgbG9jYWxpemVkIHZhbHVlXG4gICAgICAgIGxldCB2YWx1ZTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRW1wdHlTdHJpbmcodGhpcy5yYXdWYWx1ZSkpIHtcbiAgICAgICAgICAgIHZhbHVlID0gJyc7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBIZXJlIEkgdXNlIGB0aGlzLnJhd1ZhbHVlYCBpbnN0ZWFkIG9mIGB0aGlzLmdldE51bWVyaWNTdHJpbmcoKWAgc2luY2UgdGhlIGN1cnJlbnQgaW5wdXQgdmFsdWUgY291bGQgYmUgdW5mb3JtYXR0ZWQgd2l0aCBhIGxvY2FsaXphdGlvbiAoaWUuICcxMjM0NTY3LDg5LScpLlxuICAgICAgICAgICAgLy8gSSBhbHNvIGNvbnZlcnQgdGhlIHJhd1ZhbHVlIHRvIGEgbnVtYmVyLCB0aGVuIGJhY2sgdG8gYSBzdHJpbmcgaW4gb3JkZXIgdG8gZHJvcCB0aGUgZGVjaW1hbCBwYXJ0IGlmIHRoZSByYXdWYWx1ZSBpcyBhbiBpbnRlZ2VyLlxuICAgICAgICAgICAgdmFsdWUgPSAnJytOdW1iZXIodGhpcy5yYXdWYWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodmFsdWUgIT09ICcnICYmIE51bWJlcih2YWx1ZSkgPT09IDAgJiYgdGhpcy5zZXR0aW5ncy5sZWFkaW5nWmVybyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5rZWVwKSB7XG4gICAgICAgICAgICB2YWx1ZSA9ICcwJztcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBvdXRwdXRGb3JtYXRUb1VzZTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChmb3JjZWRPdXRwdXRGb3JtYXQpKSB7XG4gICAgICAgICAgICBvdXRwdXRGb3JtYXRUb1VzZSA9IHRoaXMuc2V0dGluZ3Mub3V0cHV0Rm9ybWF0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3V0cHV0Rm9ybWF0VG9Vc2UgPSBmb3JjZWRPdXRwdXRGb3JtYXQ7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCByZXN1bHQgPSB0aGlzLmNvbnN0cnVjdG9yLl90b0xvY2FsZSh2YWx1ZSwgb3V0cHV0Rm9ybWF0VG9Vc2UpO1xuICAgICAgICB0aGlzLl9leGVjdXRlQ2FsbGJhY2socmVzdWx0LCBjYWxsYmFjayk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JjZSB0aGUgZWxlbWVudCB0byByZWZvcm1hdCBpdHMgdmFsdWUgYWdhaW4gKGp1c3QgaW4gY2FzZSB0aGUgZm9ybWF0dGluZyBoYXMgYmVlbiBsb3N0KS5cbiAgICAgKiBUaGlzIGNhbiBiZSB1c2VkIHJpZ2h0IGFmdGVyIGEgZm9ybSBzdWJtaXNzaW9uIGZvciBpbnN0YW5jZSAoYWZ0ZXIgYSBwcmV2aW91cyBjYWxsIHRvIGB1bmZvcm1hdGApLlxuICAgICAqXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LnJlZm9ybWF0KClcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICByZWZvcm1hdCgpIHtcbiAgICAgICAgLy8gYHRoaXMucmF3VmFsdWVgIGlzIHVzZWQgaW5zdGVhZCBvZiBgdGhpcy5kb21FbGVtZW50LnZhbHVlYCBiZWNhdXNlIHdoZW4gdGhlIGNvbnRlbnQgaXMgYHVuZm9ybWF0TG9jYWxpemVkYCwgaXQgY2FuIGJlY29tZSBhIHN0cmluZyB0aGF0IGNhbm5vdCBiZSBjb252ZXJ0ZWQgdG8gYSBudW1iZXIgZWFzaWx5XG4gICAgICAgIHRoaXMuc2V0KHRoaXMucmF3VmFsdWUpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZSB0aGUgZm9ybWF0dGluZyBhbmQga2VlcCBvbmx5IHRoZSByYXcgdW5mb3JtYXR0ZWQgdmFsdWUgaW4gdGhlIGVsZW1lbnQgKGFzIGEgbnVtZXJpY1N0cmluZylcbiAgICAgKiBOb3RlOiB0aGlzIGlzIGxvb3NlbHkgYmFzZWQgb24gdGhlIHByZXZpb3VzICd1blNldCgpJyBmdW5jdGlvblxuICAgICAqXG4gICAgICogQnkgZGVmYXVsdCwgdmFsdWVzIGFyZSByZXR1cm5lZCBhcyBJU08gbnVtZXJpYyBzdHJpbmdzIChpZS4gXCIxMjM0LjU2XCIgb3IgXCItMTIzNC41NlwiKSwgd2hlcmUgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGlzIGEgcGVyaW9kLlxuICAgICAqIEBleGFtcGxlIGFuRWxlbWVudC51bmZvcm1hdCgpXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgdW5mb3JtYXQoKSB7XG4gICAgICAgIHRoaXMuX3NldEVsZW1lbnRWYWx1ZSh0aGlzLmdldE51bWVyaWNTdHJpbmcoKSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBmb3JtYXR0aW5nIGFuZCBrZWVwIG9ubHkgdGhlIGxvY2FsaXplZCB1bmZvcm1hdHRlZCB2YWx1ZSBpbiB0aGUgZWxlbWVudCwgd2l0aCB0aGUgb3B0aW9uIHRvIG92ZXJyaWRlIHRoZSBkZWZhdWx0IG91dHB1dEZvcm1hdCBpZiBuZWVkZWRcbiAgICAgKlxuICAgICAqIExvY2FsZSBmb3JtYXRzIGFyZSBzdXBwb3J0ZWQgXCIxMjM0LjU2LVwiIG9yIFwiMTIzNCw1NlwiIG9yIFwiLTEyMzQsNTYgb3IgXCIxMjM0LDU2LVwiLCBvciBldmVuIHBsYWluIG51bWJlcnMuXG4gICAgICogVGFrZSBhIGxvb2sgYXQgdGhlIGBvdXRwdXRGb3JtYXRgIG9wdGlvbiBkZWZpbml0aW9uIGluIHRoZSBkZWZhdWx0IHNldHRpbmdzIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bGx8c3RyaW5nfSBmb3JjZWRPdXRwdXRGb3JtYXQgSWYgc2V0IHRvIHNvbWV0aGluZyBkaWZmZXJlbnQgdGhhbiBgbnVsbGAsIHRoZW4gdGhpcyBpcyB1c2VkIGFzIGFuIG92ZXJyaWRpbmcgb3V0cHV0Rm9ybWF0IG9wdGlvblxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICB1bmZvcm1hdExvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3NldEVsZW1lbnRWYWx1ZSh0aGlzLmdldExvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQpKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBjdXJyZW50IHZhbHVlIGlzIHRoZSBzYW1lIGFzIHdoZW4gdGhlIGVsZW1lbnQgZ290IGluaXRpYWxpemVkLlxuICAgICAqIE5vdGU6IEJ5IGRlZmF1bHQsIHRoaXMgcmV0dXJucyBgdHJ1ZWAgaWYgdGhlIHJhdyB1bmZvcm1hdHRlZCB2YWx1ZSBpcyBzdGlsbCB0aGUgc2FtZSBldmVuIGlmIHRoZSBmb3JtYXR0ZWQgb25lIGhhcyBjaGFuZ2VkIChkdWUgdG8gYSBjb25maWd1cmF0aW9uIHVwZGF0ZSBmb3IgaW5zdGFuY2UpLlxuICAgICAqIEluIG9yZGVyIHRvIHRlc3QgaWYgdGhlIGZvcm1hdHRlZCB2YWx1ZSBpcyB0aGUgc2FtZSAod2hpY2ggbWVhbnMgbmVpdGhlciB0aGUgcmF3IHZhbHVlIG5vciB0aGUgc2V0dGluZ3MgaGF2ZSBiZWVuIGNoYW5nZWQpLCB0aGVuIHlvdSBtdXN0IHBhc3MgYGZhbHNlYCBhcyBpdHMgYXJndW1lbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGNoZWNrT25seVJhd1ZhbHVlIElmIHNldCB0byBgdHJ1ZWAsIHRoZSBwcmlzdGluZSB2YWx1ZSBpcyBkb25lIG9uIHRoZSByYXcgdW5mb3JtYXR0ZWQgdmFsdWUsIG5vdCB0aGUgZm9ybWF0dGVkIG9uZS4gIElmIHNldCB0byBgZmFsc2VgLCB0aGlzIGFsc28gY2hlY2tzIHRoYXQgdGhlIGZvcm1hdHRlZCB2YWx1ZSBoYXNuJ3QgY2hhbmdlZC5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBpc1ByaXN0aW5lKGNoZWNrT25seVJhd1ZhbHVlID0gdHJ1ZSkge1xuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoY2hlY2tPbmx5UmF3VmFsdWUpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuaW5pdGlhbFZhbHVlID09PSB0aGlzLmdldE51bWVyaWNTdHJpbmcoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuaW5pdGlhbFZhbHVlSHRtbEF0dHJpYnV0ZSA9PT0gdGhpcy5nZXRGb3JtYXR0ZWQoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VsZWN0IHRoZSBmb3JtYXR0ZWQgZWxlbWVudCBjb250ZW50LCBiYXNlZCBvbiB0aGUgYHNlbGVjdE51bWJlck9ubHlgIG9wdGlvblxuICAgICAqXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIHNlbGVjdCgpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc2VsZWN0TnVtYmVyT25seSkge1xuICAgICAgICAgICAgdGhpcy5zZWxlY3ROdW1iZXIoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRoaXMuX2RlZmF1bHRTZWxlY3RBbGwoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbGVjdCB0aGUgd2hvbGUgZWxlbWVudCBjb250ZW50IChpbmNsdWRpbmcgdGhlIGN1cnJlbmN5IHN5bWJvbCkuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZGVmYXVsdFNlbGVjdEFsbCgpIHtcbiAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbih0aGlzLmRvbUVsZW1lbnQsIDAsIEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpLmxlbmd0aCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VsZWN0IG9ubHkgdGhlIG51bWJlcnMgaW4gdGhlIGZvcm1hdHRlZCBlbGVtZW50IGNvbnRlbnQsIGxlYXZpbmcgb3V0IHRoZSBjdXJyZW5jeSBzeW1ib2wsIHdoYXRldmVyIHRoZSB2YWx1ZSBvZiB0aGUgYHNlbGVjdE51bWJlck9ubHlgIG9wdGlvblxuICAgICAqXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIHNlbGVjdE51bWJlcigpIHtcbiAgICAgICAgLy9UT0RPIE1ha2Ugc3VyZSB0aGUgc2VsZWN0aW9uIGlzIG9rIHdoZW4gc2hvd1Bvc2l0aXZlU2lnbiBpcyBzZXQgdG8gYHRydWVgIChzZWxlY3QgdGhlIG5lZ2F0aXZlIHNpZ24sIGJ1dCBub3QgdGhlIHBvc2l0aXZlIG9uZSlcbiAgICAgICAgY29uc3QgdW5mb3JtYXR0ZWRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICBjb25zdCB2YWx1ZUxlbiA9IHVuZm9ybWF0dGVkVmFsdWUubGVuZ3RoO1xuICAgICAgICBjb25zdCBjdXJyZW5jeVN5bWJvbFNpemUgPSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLmxlbmd0aDtcbiAgICAgICAgY29uc3QgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50O1xuICAgICAgICBjb25zdCBuZWdMZW4gPSAoIUF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUodW5mb3JtYXR0ZWRWYWx1ZSkpPzA6MTtcbiAgICAgICAgY29uc3Qgc3VmZml4VGV4dExlbiA9IHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dC5sZW5ndGg7XG5cbiAgICAgICAgbGV0IHN0YXJ0O1xuICAgICAgICBpZiAoY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4KSB7XG4gICAgICAgICAgICBzdGFydCA9IDA7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0ICYmXG4gICAgICAgICAgICBuZWdMZW4gPT09IDEgJiYgY3VycmVuY3lTeW1ib2xTaXplID4gMCkge1xuICAgICAgICAgICAgc3RhcnQgPSBjdXJyZW5jeVN5bWJvbFNpemUgKyAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc3RhcnQgPSBjdXJyZW5jeVN5bWJvbFNpemU7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgZW5kO1xuICAgICAgICBpZiAoY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4KSB7XG4gICAgICAgICAgICBlbmQgPSB2YWx1ZUxlbiAtIHN1ZmZpeFRleHRMZW47XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQpIHtcbiAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDpcbiAgICAgICAgICAgICAgICAgICAgZW5kID0gdmFsdWVMZW4gLSAoc3VmZml4VGV4dExlbiArIGN1cnJlbmN5U3ltYm9sU2l6ZSk7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKGN1cnJlbmN5U3ltYm9sU2l6ZSA+IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuZCA9IHZhbHVlTGVuIC0gKGN1cnJlbmN5U3ltYm9sU2l6ZSArIG5lZ0xlbiArIHN1ZmZpeFRleHRMZW4pO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZW5kID0gdmFsdWVMZW4gLSAoY3VycmVuY3lTeW1ib2xTaXplICsgc3VmZml4VGV4dExlbik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgICAgIGVuZCA9IHZhbHVlTGVuIC0gKGN1cnJlbmN5U3ltYm9sU2l6ZSArIHN1ZmZpeFRleHRMZW4pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbih0aGlzLmRvbUVsZW1lbnQsIHN0YXJ0LCBlbmQpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlbGVjdCBvbmx5IHRoZSBpbnRlZ2VyIHBhcnQgaW4gdGhlIGZvcm1hdHRlZCBlbGVtZW50IGNvbnRlbnQsIHdoYXRldmVyIHRoZSB2YWx1ZSBvZiBgc2VsZWN0TnVtYmVyT25seWBcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBzZWxlY3RJbnRlZ2VyKCkge1xuICAgICAgICBsZXQgc3RhcnQgPSAwO1xuICAgICAgICBjb25zdCBpc1Bvc2l0aXZlID0gdGhpcy5yYXdWYWx1ZSA+PSAwO1xuXG4gICAgICAgIC8vIE5lZ2F0aXZlIG9yIHBvc2l0aXZlIHNpZ24sIGlmIGFueVxuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXggfHxcbiAgICAgICAgICAgICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCAmJlxuICAgICAgICAgICAgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4IHx8XG4gICAgICAgICAgICB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Lm5vbmUpKSkge1xuICAgICAgICAgICAgaWYgKCh0aGlzLnNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24gJiYgaXNQb3NpdGl2ZSkgfHwgIC8vIFRoaXMgb25seSBleGNsdWRlIHRoZSBwb3NpdGl2ZSBzaWduIGZyb20gYmVpbmcgc2VsZWN0ZWRcbiAgICAgICAgICAgICAgICAoIWlzUG9zaXRpdmUgJiYgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXggJiYgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0KSkgeyAvLyBBbmQgdGhpcyBleGNsdWRlIHRoZSBuZWdhdGl2ZSBzaWduIGZyb20gYmVpbmcgc2VsZWN0ZWQgaW4gdGhpcyBzcGVjaWFsIGNhc2UgOiAnLeKCrCAxLjIzNCw1N3N1ZmZpeFRleHQnXG4gICAgICAgICAgICAgICAgc3RhcnQgPSBzdGFydCArIDE7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDdXJyZW5jeSBzeW1ib2xcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4KSB7XG4gICAgICAgICAgICBzdGFydCA9IHN0YXJ0ICsgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGg7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIHNlbGVjdGlvbiBlbmQgcG9zaXRpb25cbiAgICAgICAgY29uc3QgZWxlbWVudFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgIGxldCBlbmQgPSBlbGVtZW50VmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpO1xuICAgICAgICBpZiAoZW5kID09PSAtMSkge1xuICAgICAgICAgICAgLy8gTm8gZGVjaW1hbCBjaGFyYWN0ZXIgZm91bmRcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCkge1xuICAgICAgICAgICAgICAgIGVuZCA9IGVsZW1lbnRWYWx1ZS5sZW5ndGggLSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLmxlbmd0aDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgZW5kID0gZWxlbWVudFZhbHVlLmxlbmd0aDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVHJhaWxpbmcgbmVnYXRpdmUgc2lnblxuICAgICAgICAgICAgaWYgKCFpc1Bvc2l0aXZlICYmXG4gICAgICAgICAgICAgICAgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4IHx8XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgpKSB7XG4gICAgICAgICAgICAgICAgZW5kID0gZW5kIC0gMTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQXZvaWQgc2VsZWN0aW5nIHRoZSBzdWZmaXggdGVzdFxuICAgICAgICAgICAgZW5kID0gZW5kIC0gdGhpcy5zZXR0aW5ncy5zdWZmaXhUZXh0Lmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24odGhpcy5kb21FbGVtZW50LCBzdGFydCwgZW5kKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZWxlY3Qgb25seSB0aGUgZGVjaW1hbCBwYXJ0IGluIHRoZSBmb3JtYXR0ZWQgZWxlbWVudCBjb250ZW50LCB3aGF0ZXZlciB0aGUgdmFsdWUgb2YgYHNlbGVjdE51bWJlck9ubHlgXG4gICAgICogTXVsdGlwbGUgY2FzZXMgYXJlIHBvc3NpYmxlIDpcbiAgICAgKiArMS4yMzQsNTdzdWZmaXhUZXh0XG4gICAgICpcbiAgICAgKiDigqwgKzEuMjM0LDU3c3VmZml4VGV4dFxuICAgICAqICvigqwgMS4yMzQsNTdzdWZmaXhUZXh0XG4gICAgICog4oKsIDEuMjM0LDU3K3N1ZmZpeFRleHRcbiAgICAgKlxuICAgICAqIDEuMjM0LDU3KyDigqxzdWZmaXhUZXh0XG4gICAgICogMS4yMzQsNTcg4oKsK3N1ZmZpeFRleHRcbiAgICAgKiArMS4yMzQsNTcg4oKsc3VmZml4VGV4dFxuICAgICAqXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIHNlbGVjdERlY2ltYWwoKSB7XG4gICAgICAgIGxldCBzdGFydCA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpLmluZGV4T2YodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKTtcbiAgICAgICAgbGV0IGVuZDtcblxuICAgICAgICBpZiAoc3RhcnQgPT09IC0xKSB7XG4gICAgICAgICAgICAvLyBUaGUgZGVjaW1hbCBjaGFyYWN0ZXIgaGFzIG5vdCBiZWVuIGZvdW5kLCB3ZSBkZXNlbGVjdCBhbGxcbiAgICAgICAgICAgIHN0YXJ0ID0gMDtcbiAgICAgICAgICAgIGVuZCA9IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBBIGRlY2ltYWwgY2hhcmFjdGVyIGhhcyBiZWVuIGZvdW5kXG4gICAgICAgICAgICBzdGFydCA9IHN0YXJ0ICsgMTsgLy8gV2UgYWRkIDEgdG8gZXhjbHVkZSB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgZnJvbSB0aGUgc2VsZWN0aW9uXG5cbiAgICAgICAgICAgIGxldCBkZWNpbWFsQ291bnQ7XG4gICAgICAgICAgICBpZiAodGhpcy5pc0ZvY3VzZWQpIHtcbiAgICAgICAgICAgICAgICBkZWNpbWFsQ291bnQgPSB0aGlzLnNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXM7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGRlY2ltYWxDb3VudCA9IHRoaXMuc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBlbmQgPSBzdGFydCArIE51bWJlcihkZWNpbWFsQ291bnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbih0aGlzLmRvbUVsZW1lbnQsIHN0YXJ0LCBlbmQpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgRE9NIGVsZW1lbnQgcmVmZXJlbmNlIG9mIHRoZSBhdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fVxuICAgICAqL1xuICAgIG5vZGUoKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmRvbUVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBET00gZWxlbWVudCByZWZlcmVuY2Ugb2YgdGhlIHBhcmVudCBub2RlIG9mIHRoZSBhdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fE5vZGV9XG4gICAgICovXG4gICAgcGFyZW50KCkge1xuICAgICAgICByZXR1cm4gdGhpcy5kb21FbGVtZW50LnBhcmVudE5vZGU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRGV0YWNoIHRoZSBjdXJyZW50IEF1dG9OdW1lcmljIGVsZW1lbnQgZnJvbSB0aGUgc2hhcmVkIGxvY2FsICdpbml0JyBsaXN0LlxuICAgICAqIFRoaXMgbWVhbnMgYW55IGNoYW5nZXMgbWFkZSBvbiB0aGF0IGxvY2FsIHNoYXJlZCBsaXN0IHdpbGwgbm90IGJlIHRyYW5zbWl0dGVkIHRvIHRoYXQgZWxlbWVudCBhbnltb3JlLlxuICAgICAqIE5vdGUgOiBUaGUgdXNlciBjYW4gcHJvdmlkZSBhbm90aGVyIEF1dG9OdW1lcmljIGVsZW1lbnQsIGFuZCBkZXRhY2ggdGhpcyBvbmUgaW5zdGVhZCBvZiB0aGUgY3VycmVudCBvbmUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0F1dG9OdW1lcmljfSBvdGhlckFuRWxlbWVudFxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBkZXRhY2gob3RoZXJBbkVsZW1lbnQgPSBudWxsKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGxldCBkb21FbGVtZW50VG9EZXRhY2g7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG90aGVyQW5FbGVtZW50KSkge1xuICAgICAgICAgICAgZG9tRWxlbWVudFRvRGV0YWNoID0gb3RoZXJBbkVsZW1lbnQubm9kZSgpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZG9tRWxlbWVudFRvRGV0YWNoID0gdGhpcy5kb21FbGVtZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgdGhpcy5fcmVtb3ZlRnJvbUxvY2FsTGlzdChkb21FbGVtZW50VG9EZXRhY2gpOyAvL0ZJWE1FIFdoYXQgaGFwcGVucyBpZiB0aGUgc2VsZWN0ZWQgZG9tIGVsZW1lbnQgZG9lcyBub3QgZXhpc3QgaW4gdGhlIGxpc3Q/XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQXR0YWNoIHRoZSBnaXZlbiBBdXRvTnVtZXJpYyBlbGVtZW50IHRvIHRoZSBzaGFyZWQgbG9jYWwgJ2luaXQnIGxpc3QuXG4gICAgICogV2hlbiBkb2luZyB0aGF0LCBieSBkZWZhdWx0IHRoZSBET00gY29udGVudCBpcyBsZWZ0IHVudG91Y2hlZC5cbiAgICAgKiBUaGUgdXNlciBjYW4gZm9yY2UgYSByZWZvcm1hdCB3aXRoIHRoZSBuZXcgc2hhcmVkIGxpc3Qgb3B0aW9ucyBieSBwYXNzaW5nIGEgc2Vjb25kIGFyZ3VtZW50IHRvIGB0cnVlYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7QXV0b051bWVyaWN9IG90aGVyQW5FbGVtZW50XG4gICAgICogQHBhcmFtIHtib29sZWFufSByZUZvcm1hdFxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBhdHRhY2gob3RoZXJBbkVsZW1lbnQsIHJlRm9ybWF0ID0gdHJ1ZSkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICB0aGlzLl9hZGRUb0xvY2FsTGlzdChvdGhlckFuRWxlbWVudC5ub2RlKCkpOyAvL0ZJWE1FIFNob3VsZCB3ZSBtYWtlIHN1cmUgdGhlIGVsZW1lbnQgaXMgbm90IGFscmVhZHkgaW4gdGhlIGxpc3Q/XG4gICAgICAgIGlmIChyZUZvcm1hdCkge1xuICAgICAgICAgICAgb3RoZXJBbkVsZW1lbnQudXBkYXRlKHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRm9ybWF0IGFuZCByZXR1cm4gdGhlIGdpdmVuIHZhbHVlLCBvciBzZXQgdGhlIGZvcm1hdHRlZCB2YWx1ZSBpbnRvIHRoZSBnaXZlbiBET00gZWxlbWVudCBpZiBvbmUgaXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LlxuICAgICAqIEJ5IGRlZmF1bHQsIHRoaXMgdXNlIHRoZSBjdXJyZW50IGVsZW1lbnQgc2V0dGluZ3MuXG4gICAgICogVGhlIHVzZXIgY2FuIG92ZXJyaWRlIGFueSBvcHRpb24gb2YgaXRzIGNob29zaW5nIGJ5IHBhc3NpbmcgYW4gb3B0aW9uIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfEhUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IHZhbHVlT3JFbGVtZW50XG4gICAgICogQHBhcmFtIHtudWxsfG9iamVjdH0gb3B0aW9uT3ZlcnJpZGVcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gICAgICovXG4gICAgZm9ybWF0T3RoZXIodmFsdWVPckVsZW1lbnQsIG9wdGlvbk92ZXJyaWRlID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICByZXR1cm4gdGhpcy5fZm9ybWF0T3JVbmZvcm1hdE90aGVyKHRydWUsIHZhbHVlT3JFbGVtZW50LCBvcHRpb25PdmVycmlkZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW5mb3JtYXQgYW5kIHJldHVybiB0aGUgcmF3IG51bWVyaWMgc3RyaW5nIGNvcnJlc3BvbmRpbmcgdG8gdGhlIGdpdmVuIHZhbHVlLCBvciBkaXJlY3RseSBzZXQgdGhlIHVuZm9ybWF0dGVkIHZhbHVlIGludG8gdGhlIGdpdmVuIERPTSBlbGVtZW50IGlmIG9uZSBpcyBwYXNzZWQgYXMgYW4gYXJndW1lbnQuXG4gICAgICogQnkgZGVmYXVsdCwgdGhpcyB1c2UgdGhlIGN1cnJlbnQgZWxlbWVudCBzZXR0aW5ncy5cbiAgICAgKiBUaGUgdXNlciBjYW4gb3ZlcnJpZGUgYW55IG9wdGlvbiBvZiBpdHMgY2hvb3NpbmcgYnkgcGFzc2luZyBhbiBvcHRpb24gb2JqZWN0LlxuXG4gICAgICogQHBhcmFtIHtzdHJpbmd8SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudH0gc3RyaW5nT3JFbGVtZW50XG4gICAgICogQHBhcmFtIHtudWxsfG9iamVjdH0gb3B0aW9uT3ZlcnJpZGVcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gICAgICovXG4gICAgdW5mb3JtYXRPdGhlcihzdHJpbmdPckVsZW1lbnQsIG9wdGlvbk92ZXJyaWRlID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICByZXR1cm4gdGhpcy5fZm9ybWF0T3JVbmZvcm1hdE90aGVyKGZhbHNlLCBzdHJpbmdPckVsZW1lbnQsIG9wdGlvbk92ZXJyaWRlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXRob2QgdGhhdCBlaXRoZXIgZm9ybWF0IG9yIHVuZm9ybWF0IHRoZSB2YWx1ZSBvZiBhbm90aGVyIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiAtIEZvcm1hdCBhbmQgcmV0dXJuIHRoZSBnaXZlbiB2YWx1ZSwgb3Igc2V0IHRoZSBmb3JtYXR0ZWQgdmFsdWUgaW50byB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgaWYgb25lIGlzIHBhc3NlZCBhcyBhbiBhcmd1bWVudC5cbiAgICAgKiAtIFVuZm9ybWF0IGFuZCByZXR1cm4gdGhlIHJhdyBudW1lcmljIHN0cmluZyBjb3JyZXNwb25kaW5nIHRvIHRoZSBnaXZlbiB2YWx1ZSwgb3IgZGlyZWN0bHkgc2V0IHRoZSB1bmZvcm1hdHRlZCB2YWx1ZSBpbnRvIHRoZSBnaXZlbiBET00gZWxlbWVudCBpZiBvbmUgaXMgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LlxuICAgICAqXG4gICAgICogQnkgZGVmYXVsdCwgdGhpcyB1c2UgdGhlIGN1cnJlbnQgZWxlbWVudCBzZXR0aW5ncy5cbiAgICAgKiBUaGUgdXNlciBjYW4gb3ZlcnJpZGUgYW55IG9wdGlvbiBvZiBpdHMgY2hvb3NpbmcgYnkgcGFzc2luZyBhbiBvcHRpb24gb2JqZWN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtib29sZWFufSBpc0Zvcm1hdHRpbmcgSWYgc2V0IHRvIGB0cnVlYCwgdGhlbiB0aGUgbWV0aG9kIGZvcm1hdHMsIG90aGVyd2lzZSBpZiBzZXQgdG8gYGZhbHNlYCwgaXQgdW5mb3JtYXRzXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfEhUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IHZhbHVlT3JTdHJpbmdPckVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge251bGx8b2JqZWN0fSBvcHRpb25PdmVycmlkZVxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9mb3JtYXRPclVuZm9ybWF0T3RoZXIoaXNGb3JtYXR0aW5nLCB2YWx1ZU9yU3RyaW5nT3JFbGVtZW50LCBvcHRpb25PdmVycmlkZSA9IG51bGwpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgLy8gSWYgdGhlIHVzZXIgd2FudHMgdG8gb3ZlcnJpZGUgdGhlIGN1cnJlbnQgZWxlbWVudCBzZXR0aW5ncyB0ZW1wb3JhcmlseVxuICAgICAgICBsZXQgc2V0dGluZ3NUb1VzZTtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9uT3ZlcnJpZGUpKSB7XG4gICAgICAgICAgICBzZXR0aW5nc1RvVXNlID0gdGhpcy5fY2xvbmVBbmRNZXJnZVNldHRpbmdzKG9wdGlvbk92ZXJyaWRlKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNldHRpbmdzVG9Vc2UgPSB0aGlzLnNldHRpbmdzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gVGhlbiB0aGUgdW5mb3JtYXR0aW5nIGlzIGRvbmUuLi5cbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRWxlbWVudCh2YWx1ZU9yU3RyaW5nT3JFbGVtZW50KSkge1xuICAgICAgICAgICAgLy8gLi4uZWl0aGVyIGRpcmVjdGx5IG9uIHRoZSBET00gZWxlbWVudCB2YWx1ZVxuICAgICAgICAgICAgY29uc3QgZWxlbWVudFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHZhbHVlT3JTdHJpbmdPckVsZW1lbnQpO1xuICAgICAgICAgICAgaWYgKGlzRm9ybWF0dGluZykge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljLmZvcm1hdChlbGVtZW50VmFsdWUsIHNldHRpbmdzVG9Vc2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWMudW5mb3JtYXQoZWxlbWVudFZhbHVlLCBzZXR0aW5nc1RvVXNlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFZhbHVlKHZhbHVlT3JTdHJpbmdPckVsZW1lbnQsIHJlc3VsdCk7IC8vVE9ETyBVc2UgYHVuZm9ybWF0QW5kU2V0YCBhbmQgYGZvcm1hdEFuZFNldGBpbnN0ZWFkXG5cbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gLi4ub3Igb24gdGhlIGdpdmVuIHZhbHVlXG4gICAgICAgIGlmIChpc0Zvcm1hdHRpbmcpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljLmZvcm1hdCh2YWx1ZU9yU3RyaW5nT3JFbGVtZW50LCBzZXR0aW5nc1RvVXNlKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljLnVuZm9ybWF0KHZhbHVlT3JTdHJpbmdPckVsZW1lbnQsIHNldHRpbmdzVG9Vc2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVc2UgdGhlIGN1cnJlbnQgQXV0b051bWVyaWMgZWxlbWVudCBzZXR0aW5ncyB0byBpbml0aWFsaXplIHRoZSBET00gZWxlbWVudChzKSBnaXZlbiBhcyBhIHBhcmFtZXRlci5cbiAgICAgKiBEb2luZyBzbyB3aWxsICpsaW5rKiB0aGUgQXV0b051bWVyaWMgZWxlbWVudHMgdG9nZXRoZXIgc2luY2UgdGhleSB3aWxsIHNoYXJlIHRoZSBzYW1lIGxvY2FsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdC5cbiAgICAgKiAoY2YuIHByb3RvdHlwZSBwYXR0ZXJuIDogaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvUHJvdG90eXBlX3BhdHRlcm4pXG4gICAgICpcbiAgICAgKiBZb3UgY2FuIGBpbml0YCBlaXRoZXIgYSBzaW5nbGUgRE9NIGVsZW1lbnQgKGluIHRoYXQgY2FzZSBhbiBBdXRvTnVtZXJpYyBvYmplY3Qgd2lsbCBiZSByZXR1cm5lZCksIG9yIGFuIGFycmF5IG9mIERPTSBlbGVtZW50cyBvciBhIHN0cmluZyB0aGF0IHdpbGwgYmUgdXNlZCBhcyBhIENTUyBzZWxlY3Rvci4gSW4gdGhlIGxhdHRlciBjYXNlcywgYW4gYXJyYXkgb2YgQXV0b051bWVyaWMgb2JqZWN0cyB3aWxsIHRoZW4gYmUgcmV0dXJuZWQgKG9yIGFuIGVtcHR5IGFycmF5IGlmIG5vdGhpbmcgZ2V0cyBzZWxlY3RlZCBieSB0aGUgQ1NTIHNlbGVjdG9yKS5cbiAgICAgKlxuICAgICAqIFVzZSBjYXNlIDogT25jZSB5b3UgaGF2ZSBhbiBBdXRvTnVtZXJpYyBlbGVtZW50IGFscmVhZHkgc2V0dXAgY29ycmVjdGx5IHdpdGggdGhlIHJpZ2h0IG9wdGlvbnMsIHlvdSBjYW4gdXNlIGl0IGFzIG1hbnkgdGltZXMgeW91IHdhbnQgdG8gaW5pdGlhbGl6ZSBhcyBtYW55IG90aGVyIERPTSBlbGVtZW50cyBhcyBuZWVkZWQuXG4gICAgICogTm90ZSA6IHRoaXMgd29ya3Mgb25seSBvbiBlbGVtZW50cyB0aGF0IGNhbiBiZSBtYW5hZ2VkIGJ5IGF1dG9OdW1lcmljLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fEFycmF5PEhUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnQ+fHN0cmluZ30gZG9tRWxlbWVudE9yQXJyYXlPclN0cmluZ1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gYXR0YWNoZWQgSWYgc2V0IHRvIGBmYWxzZWAsIHRoZW4gdGhlIG5ld2x5IGdlbmVyYXRlZCBBdXRvTnVtZXJpYyBlbGVtZW50IHdpbGwgbm90IHNoYXJlIHRoZSBzYW1lIGxvY2FsIGVsZW1lbnQgbGlzdFxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY3xbQXV0b051bWVyaWNdfVxuICAgICAqL1xuICAgIGluaXQoZG9tRWxlbWVudE9yQXJyYXlPclN0cmluZywgYXR0YWNoZWQgPSB0cnVlKSB7XG4gICAgICAgIGxldCByZXR1cm5BU2luZ2xlQXV0b051bWVyaWNPYmplY3QgPSBmYWxzZTsgLy8gQnkgZGVmYXVsdCwgdGhpcyBmdW5jdGlvbiByZXR1cm5zIGFuIGFycmF5IG9mIEF1dG9OdW1lcmljIG9iamVjdHNcbiAgICAgICAgbGV0IGRvbUVsZW1lbnRzQXJyYXkgPSBbXTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKGRvbUVsZW1lbnRPckFycmF5T3JTdHJpbmcpKSB7XG4gICAgICAgICAgICBkb21FbGVtZW50c0FycmF5ID0gWy4uLiBkb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKGRvbUVsZW1lbnRPckFycmF5T3JTdHJpbmcpXTsgLy8gQ29udmVydCBhIE5vZGVMaXN0IHRvIGFuIEFycmF5XG4gICAgICAgIH0gZWxzZSBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNFbGVtZW50KGRvbUVsZW1lbnRPckFycmF5T3JTdHJpbmcpKSB7XG4gICAgICAgICAgICBkb21FbGVtZW50c0FycmF5LnB1c2goZG9tRWxlbWVudE9yQXJyYXlPclN0cmluZyk7XG4gICAgICAgICAgICByZXR1cm5BU2luZ2xlQXV0b051bWVyaWNPYmplY3QgPSB0cnVlOyAvLyBTcGVjaWFsIGNhc2Ugd2hlbiBvbmx5IG9uZSBET00gZWxlbWVudCBpcyBwYXNzZWQgYXMgYSBwYXJhbWV0ZXJcbiAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0FycmF5KGRvbUVsZW1lbnRPckFycmF5T3JTdHJpbmcpKSB7XG4gICAgICAgICAgICBkb21FbGVtZW50c0FycmF5ID0gZG9tRWxlbWVudE9yQXJyYXlPclN0cmluZztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBnaXZlbiBwYXJhbWV0ZXJzIHRvIHRoZSAnaW5pdCcgZnVuY3Rpb24gYXJlIGludmFsaWQuYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZG9tRWxlbWVudHNBcnJheS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYE5vIHZhbGlkIERPTSBlbGVtZW50cyB3ZXJlIGdpdmVuIGhlbmNlIG5vIEF1dG9OdW1lcmljIG9iamVjdCB3ZXJlIGluc3RhbnRpYXRlZC5gLCB0cnVlKTtcblxuICAgICAgICAgICAgcmV0dXJuIFtdO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY3VycmVudExvY2FsTGlzdCA9IHRoaXMuX2dldExvY2FsTGlzdCgpO1xuICAgICAgICBjb25zdCBhdXRvTnVtZXJpY09iamVjdHNBcnJheSA9IFtdO1xuXG4gICAgICAgIC8vIEluc3RhbnRpYXRlIChhbmQgbGluayBkZXBlbmRpbmcgb24gYGF0dGFjaGVkYCkgZWFjaCBBdXRvTnVtZXJpYyBvYmplY3RzXG4gICAgICAgIGRvbUVsZW1lbnRzQXJyYXkuZm9yRWFjaChkb21FbGVtZW50ID0+IHtcbiAgICAgICAgICAgIC8vIEluaXRpYWxpemUgdGhlIG5ldyBBdXRvTnVtZXJpYyBlbGVtZW50XG4gICAgICAgICAgICBjb25zdCBvcmlnaW5hbENyZWF0ZUxvY2FsTGlzdFNldHRpbmcgPSB0aGlzLnNldHRpbmdzLmNyZWF0ZUxvY2FsTGlzdDtcbiAgICAgICAgICAgIGlmIChhdHRhY2hlZCkge1xuICAgICAgICAgICAgICAgIC8vIFRlbXBvcmFyeSB2YXJpYWJsZSB0byBrbm93IGlmIHdlIHNob3VsZCBjcmVhdGUgdGhlIGxvY2FsIGxpc3QgZHVyaW5nIHRoZSBpbml0aWFsaXphdGlvbiAoc2luY2Ugd2UnbGwgcmVtb3ZlIGl0IGFmdGVyd2FyZHMpXG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5jcmVhdGVMb2NhbExpc3QgPSBmYWxzZTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgbmV3QXV0b051bWVyaWNFbGVtZW50ID0gIG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUoZG9tRWxlbWVudCksIHRoaXMuc2V0dGluZ3MpO1xuXG4gICAgICAgICAgICAvLyBTZXQgdGhlIGNvbW1vbiBzaGFyZWQgbG9jYWwgbGlzdCBpZiBuZWVkZWRcbiAgICAgICAgICAgIC8vIElmIHRoZSB1c2VyIHdhbnRzIHRvIGNyZWF0ZSBhIGRldGFjaGVkIG5ldyBBdXRvTnVtZXJpYyBlbGVtZW50LCB0aGVuIHNraXAgdGhlIGZvbGxvd2luZyBzdGVwIHRoYXQgYmluZCB0aGUgdHdvIGVsZW1lbnRzIHRvZ2V0aGVyIGJ5IGRlZmF1bHRcbiAgICAgICAgICAgIGlmIChhdHRhY2hlZCkge1xuICAgICAgICAgICAgICAgIC8vIDEpIFNldCB0aGUgbG9jYWwgbGlzdCByZWZlcmVuY2UgdG8gcG9pbnQgdG8gdGhlIGluaXRpYWxpemVyJ3Mgb25lXG4gICAgICAgICAgICAgICAgbmV3QXV0b051bWVyaWNFbGVtZW50Ll9zZXRMb2NhbExpc3QoY3VycmVudExvY2FsTGlzdCk7XG5cbiAgICAgICAgICAgICAgICAvLyAyKSBBZGQgdGhlIG5ldyBlbGVtZW50IHRvIHRoYXQgZXhpc3RpbmcgbGlzdFxuICAgICAgICAgICAgICAgIHRoaXMuX2FkZFRvTG9jYWxMaXN0KGRvbUVsZW1lbnQsIG5ld0F1dG9OdW1lcmljRWxlbWVudCk7IC8vIEhlcmUgd2UgdXNlIHRoZSAqbmV3KiBBdXRvTnVtZXJpYyBvYmplY3QgcmVmZXJlbmNlIHRvIGFkZCB0byB0aGUgbG9jYWwgbGlzdCwgc2luY2Ugd2UnbGwgbmVlZCB0aGUgcmVmZXJlbmNlIHRvIGB0aGlzYCBpbiB0aGUgbWV0aG9kcyB0byBwb2ludHMgdG8gdGhhdCBuZXcgQXV0b051bWVyaWMgb2JqZWN0LlxuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuY3JlYXRlTG9jYWxMaXN0ID0gb3JpZ2luYWxDcmVhdGVMb2NhbExpc3RTZXR0aW5nO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBhdXRvTnVtZXJpY09iamVjdHNBcnJheS5wdXNoKG5ld0F1dG9OdW1lcmljRWxlbWVudCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIGlmIChyZXR1cm5BU2luZ2xlQXV0b051bWVyaWNPYmplY3QpIHtcbiAgICAgICAgICAgIC8vIElmIGEgc2luZ2xlIERPTSBlbGVtZW50IHdhcyB1c2VkIGFzIHRoZSBwYXJhbWV0ZXIsIHRoZW4gd2UgcmV0dXJuIGFuIEF1dG9OdW1lcmljIG9iamVjdCBkaXJlY3RseVxuICAgICAgICAgICAgcmV0dXJuIGF1dG9OdW1lcmljT2JqZWN0c0FycmF5WzBdO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gLi4ub3RoZXJ3aXNlIHdlIHJldHVybiBhbiBBcnJheSBvZiBBdXRvTnVtZXJpYyBvYmplY3RzXG4gICAgICAgIHJldHVybiBhdXRvTnVtZXJpY09iamVjdHNBcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXNldCB0aGUgZWxlbWVudCB2YWx1ZSBlaXRoZXIgdG8gdGhlIGVtcHR5IHN0cmluZyAnJywgb3IgdGhlIGN1cnJlbmN5IHNpZ24sIGRlcGVuZGluZyBvbiB0aGUgYGVtcHR5SW5wdXRCZWhhdmlvcmAgb3B0aW9uIHZhbHVlLlxuICAgICAqIElmIHlvdSBzZXQgdGhlIGBmb3JjZUNsZWFyQWxsYCBhcmd1bWVudCB0byBgdHJ1ZWAsIHRoZW4gdGhlIGBlbXB0eUlucHV0QmVoYXZpb3JgIG9wdGlvbiBpcyBvdmVycmlkZGVuIGFuZCB0aGUgd2hvbGUgaW5wdXQgaXMgY2xlYXIsIGluY2x1ZGluZyBhbnkgY3VycmVuY3kgc2lnbi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gZm9yY2VDbGVhckFsbFxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBjbGVhcihmb3JjZUNsZWFyQWxsID0gZmFsc2UpIHtcbiAgICAgICAgaWYgKGZvcmNlQ2xlYXJBbGwpIHtcbiAgICAgICAgICAgIGNvbnN0IHRlbXBvcmFyeUZvcmNlZE9wdGlvbnMgPSB7XG4gICAgICAgICAgICAgICAgZW1wdHlJbnB1dEJlaGF2aW9yOiBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5mb2N1cyxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICB0aGlzLnNldCgnJywgdGVtcG9yYXJ5Rm9yY2VkT3B0aW9ucyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnNldCgnJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIGF1dG9OdW1lcmljIGRhdGEgYW5kIGV2ZW50IGxpc3RlbmVycyBmcm9tIHRoZSBlbGVtZW50LCBidXQga2VlcCB0aGUgZWxlbWVudCBjb250ZW50IGludGFjdC5cbiAgICAgKiBUaGlzIGFsc28gY2xlYXJzIHRoZSB2YWx1ZSBmcm9tIHNlc3Npb25TdG9yYWdlIChvciBjb29raWUsIGRlcGVuZGluZyBvbiBicm93c2VyIHN1cHBvcnRzKS5cbiAgICAgKiBOb3RlOiB0aGlzIGRvZXMgbm90IHJlbW92ZSB0aGUgZm9ybWF0dGluZy5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlIGFuRWxlbWVudC5yZW1vdmUoKVxuICAgICAqL1xuICAgIHJlbW92ZSgpIHtcbiAgICAgICAgdGhpcy5fcmVtb3ZlVmFsdWVGcm9tUGVyc2lzdGVudFN0b3JhZ2UoKTtcbiAgICAgICAgdGhpcy5fcmVtb3ZlRXZlbnRMaXN0ZW5lcnMoKTtcblxuICAgICAgICAvLyBBbHNvIHJlbW92ZSB0aGUgZWxlbWVudCBmcm9tIHRoZSBsb2NhbCBBdXRvTnVtZXJpYyBsaXN0XG4gICAgICAgIHRoaXMuX3JlbW92ZUZyb21Mb2NhbExpc3QodGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgLy8gQWxzbyByZW1vdmUgdGhlIGVsZW1lbnQgZnJvbSB0aGUgZ2xvYmFsIEF1dG9OdW1lcmljIGxpc3RcbiAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fcmVtb3ZlRnJvbUdsb2JhbExpc3QodGhpcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBhdXRvTnVtZXJpYyBkYXRhIGFuZCBldmVudCBsaXN0ZW5lcnMgZnJvbSB0aGUgZWxlbWVudCwgYW5kIHJlc2V0IGl0cyB2YWx1ZSB0byB0aGUgZW1wdHkgc3RyaW5nICcnLlxuICAgICAqIFRoaXMgYWxzbyBjbGVhcnMgdGhlIHZhbHVlIGZyb20gc2Vzc2lvblN0b3JhZ2UgKG9yIGNvb2tpZSwgZGVwZW5kaW5nIG9uIGJyb3dzZXIgc3VwcG9ydHMpLlxuICAgICAqXG4gICAgICogQGV4YW1wbGUgYW5FbGVtZW50LndpcGUoKVxuICAgICAqL1xuICAgIHdpcGUoKSB7XG4gICAgICAgIHRoaXMuX3NldEVsZW1lbnRWYWx1ZSgnJyk7XG4gICAgICAgIHRoaXMucmVtb3ZlKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBhdXRvTnVtZXJpYyBkYXRhIGFuZCBldmVudCBsaXN0ZW5lcnMgZnJvbSB0aGUgZWxlbWVudCwgYW5kIGRlbGV0ZSB0aGUgRE9NIGVsZW1lbnQgYWx0b2dldGhlclxuICAgICAqL1xuICAgIG51a2UoKSB7XG4gICAgICAgIHRoaXMucmVtb3ZlKCk7XG4gICAgICAgIC8vIFJlbW92ZSB0aGUgZWxlbWVudCBmcm9tIHRoZSBET01cbiAgICAgICAgdGhpcy5kb21FbGVtZW50LnBhcmVudE5vZGUucmVtb3ZlQ2hpbGQodGhpcy5kb21FbGVtZW50KTtcbiAgICB9XG5cblxuICAgIC8vIFNwZWNpYWwgZnVuY3Rpb25zIHRoYXQgcmVhbGx5IHdvcmsgb24gdGhlIHBhcmVudCA8Zm9ybT4gZWxlbWVudCwgaW5zdGVhZCBvZiB0aGUgPGlucHV0PiBlbGVtZW50IGl0c2VsZlxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGEgcmVmZXJlbmNlIHRvIHRoZSBwYXJlbnQgPGZvcm0+IGVsZW1lbnQgaWYgaXQgZXhpc3RzLCBvdGhlcndpc2UgcmV0dXJuIGBudWxsYC5cbiAgICAgKiBJZiB0aGUgcGFyZW50IGZvcm0gZWxlbWVudCBhcyBhbHJlYWR5IGJlZW4gZm91bmQsIHRoaXMgZGlyZWN0bHkgcmV0dXJuIGEgcmVmZXJlbmNlIHRvIGl0LlxuICAgICAqIEhvd2V2ZXIsIHlvdSBjYW4gZm9yY2UgQXV0b051bWVyaWMgdG8gc2VhcmNoIGFnYWluIGZvciBpdHMgcmVmZXJlbmNlIGJ5IHBhc3NpbmcgYHRydWVgIGFzIGEgcGFyYW1ldGVyIHRvIHRoaXMgbWV0aG9kLlxuICAgICAqIFRoaXMgbWV0aG9kIHVwZGF0ZXMgdGhlIGB0aGlzLnBhcmVudEZvcm1gIGF0dHJpYnV0ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gZm9yY2VTZWFyY2ggSWYgc2V0IHRvIGB0cnVlYCwgdGhlIHBhcmVudCBmb3JtIGlzIHNlYXJjaGVkIGFnYWluLCBldmVuIGlmIGB0aGlzLnBhcmVudEZvcm1gIGlzIGFscmVhZHkgc2V0LlxuICAgICAqIEByZXR1cm5zIHtIVE1MRm9ybUVsZW1lbnR8bnVsbH1cbiAgICAgKi9cbiAgICBmb3JtKGZvcmNlU2VhcmNoID0gZmFsc2UpIHtcbiAgICAgICAgaWYgKGZvcmNlU2VhcmNoIHx8IEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh0aGlzLnBhcmVudEZvcm0pKSB7XG4gICAgICAgICAgICB0aGlzLnBhcmVudEZvcm0gPSB0aGlzLl9nZXRQYXJlbnRGb3JtKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5wYXJlbnRGb3JtO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIHJlZmVyZW5jZSB0byB0aGUgcGFyZW50IDxmb3JtPiBlbGVtZW50IGlmIGl0IGV4aXN0cywgb3RoZXJ3aXNlIHJldHVybiBgbnVsbGAuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7SFRNTEZvcm1FbGVtZW50fG51bGx9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0UGFyZW50Rm9ybSgpIHtcbiAgICAgICAgaWYgKHRoaXMuZG9tRWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdib2R5Jykge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgbm9kZSA9IHRoaXMuZG9tRWxlbWVudDtcbiAgICAgICAgbGV0IHRhZ05hbWU7XG4gICAgICAgIGRvIHtcbiAgICAgICAgICAgIG5vZGUgPSBub2RlLnBhcmVudE5vZGU7XG4gICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG5vZGUpKSB7XG4gICAgICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlIHdoZW4gdXNpbmcgdGVtcGxhdGVzIHdpdGggZnJhbWV3b3JrcyBsaWtlIFZ1ZS5qcywgd2hlcmUgdGhlIGlucHV0IGVsZW1lbnQgY2FuIGJlICdkZXRhY2hlZCcgd2hlbiBpbml0aWFsaXppbmcgdGhlIERPTSBzdHJ1Y3R1cmVcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG5vZGUudGFnTmFtZSkge1xuICAgICAgICAgICAgICAgIHRhZ05hbWUgPSBub2RlLnRhZ05hbWUudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGFnTmFtZSA9ICcnO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGFnTmFtZSA9PT0gJ2JvZHknKSB7XG4gICAgICAgICAgICAgICAgLy8gR2V0IG91dCBvZiB0aGUgbG9vcCBpZiB3ZSBnZXQgdXAgdG8gdGhlIGA8Ym9keT5gIGVsZW1lbnRcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSB3aGlsZSAodGFnTmFtZSAhPT0gJ2Zvcm0nKTtcblxuICAgICAgICBpZiAodGFnTmFtZSA9PT0gJ2Zvcm0nKSB7XG4gICAgICAgICAgICByZXR1cm4gbm9kZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGEgc3RyaW5nIGluIHN0YW5kYXJkIFVSTC1lbmNvZGVkIG5vdGF0aW9uIHdpdGggdGhlIGZvcm0gaW5wdXQgdmFsdWVzIGJlaW5nIHVuZm9ybWF0dGVkLlxuICAgICAqIFRoaXMgc3RyaW5nIGNhbiBiZSB1c2VkIGFzIGEgcXVlcnkgZm9yIGluc3RhbmNlLlxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBmb3JtTnVtZXJpY1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IuX3NlcmlhbGl6ZU51bWVyaWNTdHJpbmcodGhpcy5mb3JtKCksIHRoaXMuc2V0dGluZ3Muc2VyaWFsaXplU3BhY2VzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBzdHJpbmcgaW4gc3RhbmRhcmQgVVJMLWVuY29kZWQgbm90YXRpb24gd2l0aCB0aGUgZm9ybSBpbnB1dCB2YWx1ZXMgYmVpbmcgZm9ybWF0dGVkLlxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBmb3JtRm9ybWF0dGVkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci5fc2VyaWFsaXplRm9ybWF0dGVkKHRoaXMuZm9ybSgpLCB0aGlzLnNldHRpbmdzLnNlcmlhbGl6ZVNwYWNlcyk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGEgc3RyaW5nIGluIHN0YW5kYXJkIFVSTC1lbmNvZGVkIG5vdGF0aW9uIHdpdGggdGhlIGZvcm0gaW5wdXQgdmFsdWVzLCB3aXRoIGxvY2FsaXplZCB2YWx1ZXMuXG4gICAgICogVGhlIGRlZmF1bHQgb3V0cHV0IGZvcm1hdCBjYW4gYmUgb3ZlcnJpZGRlbiBieSBwYXNzaW5nIHRoZSBvcHRpb24gYXMgYSBwYXJhbWV0ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bGx8c3RyaW5nfSBmb3JjZWRPdXRwdXRGb3JtYXQgSWYgc2V0IHRvIHNvbWV0aGluZyBkaWZmZXJlbnQgdGhhbiBgbnVsbGAsIHRoZW4gdGhpcyBpcyB1c2VkIGFzIGFuIG92ZXJyaWRpbmcgb3V0cHV0Rm9ybWF0IG9wdGlvblxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZm9ybUxvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsKSB7XG4gICAgICAgIGxldCBvdXRwdXRGb3JtYXRUb1VzZTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChmb3JjZWRPdXRwdXRGb3JtYXQpKSB7XG4gICAgICAgICAgICBvdXRwdXRGb3JtYXRUb1VzZSA9IHRoaXMuc2V0dGluZ3Mub3V0cHV0Rm9ybWF0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgb3V0cHV0Rm9ybWF0VG9Vc2UgPSBmb3JjZWRPdXRwdXRGb3JtYXQ7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci5fc2VyaWFsaXplTG9jYWxpemVkKHRoaXMuZm9ybSgpLCB0aGlzLnNldHRpbmdzLnNlcmlhbGl6ZVNwYWNlcywgb3V0cHV0Rm9ybWF0VG9Vc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhbiBhcnJheSBjb250YWluaW5nIGFuIG9iamVjdCBmb3IgZWFjaCBmb3JtIDxpbnB1dD4gZWxlbWVudC5cbiAgICAgKiBUaG9zZSBvYmplY3RzIGFyZSBvZiB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZSBgeyBuYW1lOiBmb28sIHZhbHVlOiAnNDInIH1gLCB3aGVyZSB0aGUgYG5hbWVgIGlzIHRoZSBET00gZWxlbWVudCBuYW1lLCBhbmQgdGhlIGB2YWx1ZWAgaXMgYW4gdW5mb3JtYXR0ZWQgbnVtZXJpYyBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9XG4gICAgICovXG4gICAgZm9ybUFycmF5TnVtZXJpY1N0cmluZygpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IuX3NlcmlhbGl6ZU51bWVyaWNTdHJpbmdBcnJheSh0aGlzLmZvcm0oKSwgdGhpcy5zZXR0aW5ncy5zZXJpYWxpemVTcGFjZXMpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhbiBhcnJheSBjb250YWluaW5nIGFuIG9iamVjdCBmb3IgZWFjaCBmb3JtIDxpbnB1dD4gZWxlbWVudC5cbiAgICAgKiBUaG9zZSBvYmplY3RzIGFyZSBvZiB0aGUgZm9sbG93aW5nIHN0cnVjdHVyZSBgeyBuYW1lOiBmb28sIHZhbHVlOiAnNDInIH1gLCB3aGVyZSB0aGUgYG5hbWVgIGlzIHRoZSBET00gZWxlbWVudCBuYW1lLCBhbmQgdGhlIGB2YWx1ZWAgaXMgdGhlIGZvcm1hdHRlZCBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9XG4gICAgICovXG4gICAgZm9ybUFycmF5Rm9ybWF0dGVkKCkge1xuICAgICAgICByZXR1cm4gdGhpcy5jb25zdHJ1Y3Rvci5fc2VyaWFsaXplRm9ybWF0dGVkQXJyYXkodGhpcy5mb3JtKCksIHRoaXMuc2V0dGluZ3Muc2VyaWFsaXplU3BhY2VzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYW4gYXJyYXkgY29udGFpbmluZyBhbiBvYmplY3QgZm9yIGVhY2ggZm9ybSA8aW5wdXQ+IGVsZW1lbnQuXG4gICAgICogVGhvc2Ugb2JqZWN0cyBhcmUgb2YgdGhlIGZvbGxvd2luZyBzdHJ1Y3R1cmUgYHsgbmFtZTogZm9vLCB2YWx1ZTogJzQyJyB9YCwgd2hlcmUgdGhlIGBuYW1lYCBpcyB0aGUgRE9NIGVsZW1lbnQgbmFtZSwgYW5kIHRoZSBgdmFsdWVgIGlzIHRoZSBsb2NhbGl6ZWQgbnVtZXJpYyBzdHJpbmcuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bGx8c3RyaW5nfSBmb3JjZWRPdXRwdXRGb3JtYXQgSWYgc2V0IHRvIHNvbWV0aGluZyBkaWZmZXJlbnQgdGhhbiBgbnVsbGAsIHRoZW4gdGhpcyBpcyB1c2VkIGFzIGFuIG92ZXJyaWRpbmcgb3V0cHV0Rm9ybWF0IG9wdGlvblxuICAgICAqIEByZXR1cm5zIHtBcnJheX1cbiAgICAgKi9cbiAgICBmb3JtQXJyYXlMb2NhbGl6ZWQoZm9yY2VkT3V0cHV0Rm9ybWF0ID0gbnVsbCkge1xuICAgICAgICBsZXQgb3V0cHV0Rm9ybWF0VG9Vc2U7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoZm9yY2VkT3V0cHV0Rm9ybWF0KSkge1xuICAgICAgICAgICAgb3V0cHV0Rm9ybWF0VG9Vc2UgPSB0aGlzLnNldHRpbmdzLm91dHB1dEZvcm1hdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdFRvVXNlID0gZm9yY2VkT3V0cHV0Rm9ybWF0O1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXMuY29uc3RydWN0b3IuX3NlcmlhbGl6ZUxvY2FsaXplZEFycmF5KHRoaXMuZm9ybSgpLCB0aGlzLnNldHRpbmdzLnNlcmlhbGl6ZVNwYWNlcywgb3V0cHV0Rm9ybWF0VG9Vc2UpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIEpTT04gc3RyaW5nIGNvbnRhaW5pbmcgYW4gb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgZm9ybSBpbnB1dCB2YWx1ZXMuXG4gICAgICogVGhpcyBpcyBiYXNlZCBvbiB0aGUgcmVzdWx0IG9mIHRoZSBgZm9ybUFycmF5TnVtZXJpY1N0cmluZygpYCBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgZm9ybUpzb25OdW1lcmljU3RyaW5nKCkge1xuICAgICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodGhpcy5mb3JtQXJyYXlOdW1lcmljU3RyaW5nKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIEpTT04gc3RyaW5nIGNvbnRhaW5pbmcgYW4gb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgZm9ybSBpbnB1dCB2YWx1ZXMuXG4gICAgICogVGhpcyBpcyBiYXNlZCBvbiB0aGUgcmVzdWx0IG9mIHRoZSBgZm9ybUFycmF5Rm9ybWF0dGVkKClgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBmb3JtSnNvbkZvcm1hdHRlZCgpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHRoaXMuZm9ybUFycmF5Rm9ybWF0dGVkKCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIEpTT04gc3RyaW5nIGNvbnRhaW5pbmcgYW4gb2JqZWN0IHJlcHJlc2VudGluZyB0aGUgZm9ybSBpbnB1dCB2YWx1ZXMuXG4gICAgICogVGhpcyBpcyBiYXNlZCBvbiB0aGUgcmVzdWx0IG9mIHRoZSBgZm9ybUFycmF5TG9jYWxpemVkKClgIGZ1bmN0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudWxsfHN0cmluZ30gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gYG51bGxgLCB0aGVuIHRoaXMgaXMgdXNlZCBhcyBhbiBvdmVycmlkaW5nIG91dHB1dEZvcm1hdCBvcHRpb25cbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIGZvcm1Kc29uTG9jYWxpemVkKGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHRoaXMuZm9ybUFycmF5TG9jYWxpemVkKGZvcmNlZE91dHB1dEZvcm1hdCkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVuZm9ybWF0IGFsbCB0aGUgYXV0b051bWVyaWMtbWFuYWdlZCBlbGVtZW50cyB0aGF0IGFyZSBhIGNoaWxkIG9mIHRoZSBwYXJlbnQgPGZvcm0+IGVsZW1lbnQgb2YgdGhpcyBET00gZWxlbWVudCwgdG8gbnVtZXJpYyBzdHJpbmdzXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgZm9ybVVuZm9ybWF0KCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBjb25zdCBpbnB1dHMgPSB0aGlzLmNvbnN0cnVjdG9yLl9nZXRDaGlsZEFOSW5wdXRFbGVtZW50KHRoaXMuZm9ybSgpKTtcbiAgICAgICAgaW5wdXRzLmZvckVhY2goaW5wdXQgPT4ge1xuICAgICAgICAgICAgQXV0b051bWVyaWMuZ2V0QXV0b051bWVyaWNFbGVtZW50KGlucHV0KS51bmZvcm1hdCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbmZvcm1hdCBhbGwgdGhlIGF1dG9OdW1lcmljLW1hbmFnZWQgZWxlbWVudHMgdGhhdCBhcmUgYSBjaGlsZCBvZiB0aGUgcGFyZW50IDxmb3JtPiBlbGVtZW50IG9mIHRoaXMgRE9NIGVsZW1lbnQsIHRvIGxvY2FsaXplZCBzdHJpbmdzXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgZm9ybVVuZm9ybWF0TG9jYWxpemVkKCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBjb25zdCBpbnB1dHMgPSB0aGlzLmNvbnN0cnVjdG9yLl9nZXRDaGlsZEFOSW5wdXRFbGVtZW50KHRoaXMuZm9ybSgpKTtcbiAgICAgICAgaW5wdXRzLmZvckVhY2goaW5wdXQgPT4ge1xuICAgICAgICAgICAgQXV0b051bWVyaWMuZ2V0QXV0b051bWVyaWNFbGVtZW50KGlucHV0KS51bmZvcm1hdExvY2FsaXplZCgpO1xuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZWZvcm1hdCBhbGwgdGhlIGF1dG9OdW1lcmljLW1hbmFnZWQgZWxlbWVudHMgdGhhdCBhcmUgYSBjaGlsZCBvZiB0aGUgcGFyZW50IDxmb3JtPiBlbGVtZW50IG9mIHRoaXMgRE9NIGVsZW1lbnRcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBmb3JtUmVmb3JtYXQoKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGNvbnN0IGlucHV0cyA9IHRoaXMuY29uc3RydWN0b3IuX2dldENoaWxkQU5JbnB1dEVsZW1lbnQodGhpcy5mb3JtKCkpO1xuICAgICAgICBpbnB1dHMuZm9yRWFjaChpbnB1dCA9PiB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5nZXRBdXRvTnVtZXJpY0VsZW1lbnQoaW5wdXQpLnJlZm9ybWF0KCk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvbnZlcnQgdGhlIGlucHV0IHZhbHVlcyB0byBudW1lcmljIHN0cmluZ3MsIHN1Ym1pdCB0aGUgZm9ybSwgdGhlbiByZWZvcm1hdCB0aG9zZSBiYWNrLlxuICAgICAqIFRoZSBmdW5jdGlvbiBjYW4gZWl0aGVyIHRha2UgYSBjYWxsYmFjaywgb3Igbm90LiBJZiBpdCBkb2Vzbid0LCB0aGUgZGVmYXVsdCBgZm9ybS5zdWJtaXQoKWAgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQuXG4gICAgICogT3RoZXJ3aXNlLCBpdCBydW5zIGBjYWxsYmFjayh2YWx1ZSlgIHdpdGggYHZhbHVlYCBiZWluZyBlcXVhbCB0byB0aGUgcmVzdWx0IG9mIGBmb3JtTnVtZXJpY1N0cmluZygpYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2tcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgZm9ybVN1Ym1pdE51bWVyaWNTdHJpbmcoY2FsbGJhY2sgPSBudWxsKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoY2FsbGJhY2spKSB7XG4gICAgICAgICAgICB0aGlzLmZvcm1VbmZvcm1hdCgpO1xuICAgICAgICAgICAgdGhpcy5mb3JtKCkuc3VibWl0KCk7XG4gICAgICAgICAgICB0aGlzLmZvcm1SZWZvcm1hdCgpO1xuICAgICAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRnVuY3Rpb24oY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0aGlzLmZvcm1OdW1lcmljU3RyaW5nKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGdpdmVuIGNhbGxiYWNrIGlzIG5vdCBhIGZ1bmN0aW9uLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU3VibWl0IHRoZSBmb3JtIHdpdGggdGhlIGN1cnJlbnQgZm9ybWF0dGVkIHZhbHVlcy5cbiAgICAgKiBUaGUgZnVuY3Rpb24gY2FuIGVpdGhlciB0YWtlIGEgY2FsbGJhY2ssIG9yIG5vdC4gSWYgaXQgZG9lc24ndCwgdGhlIGRlZmF1bHQgYGZvcm0uc3VibWl0KClgIGZ1bmN0aW9uIHdpbGwgYmUgY2FsbGVkLlxuICAgICAqIE90aGVyd2lzZSwgaXQgcnVucyBgY2FsbGJhY2sodmFsdWUpYCB3aXRoIGB2YWx1ZWAgYmVpbmcgZXF1YWwgdG8gdGhlIHJlc3VsdCBvZiBgZm9ybUZvcm1hdHRlZCgpYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb258bnVsbH0gY2FsbGJhY2tcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgZm9ybVN1Ym1pdEZvcm1hdHRlZChjYWxsYmFjayA9IG51bGwpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChjYWxsYmFjaykpIHtcbiAgICAgICAgICAgIHRoaXMuZm9ybSgpLnN1Ym1pdCgpO1xuICAgICAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRnVuY3Rpb24oY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0aGlzLmZvcm1Gb3JtYXR0ZWQoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gY2FsbGJhY2sgaXMgbm90IGEgZnVuY3Rpb24uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IHRoZSBpbnB1dCB2YWx1ZXMgdG8gbG9jYWxpemVkIHN0cmluZ3MsIHN1Ym1pdCB0aGUgZm9ybSwgdGhlbiByZWZvcm1hdCB0aG9zZSBiYWNrLlxuICAgICAqIFRoZSBmdW5jdGlvbiBjYW4gZWl0aGVyIHRha2UgYSBjYWxsYmFjaywgb3Igbm90LiBJZiBpdCBkb2Vzbid0LCB0aGUgZGVmYXVsdCBgZm9ybS5zdWJtaXQoKWAgZnVuY3Rpb24gd2lsbCBiZSBjYWxsZWQuXG4gICAgICogT3RoZXJ3aXNlLCBpdCBydW5zIGBjYWxsYmFjayh2YWx1ZSlgIHdpdGggYHZhbHVlYCBiZWluZyBlcXVhbCB0byB0aGUgcmVzdWx0IG9mIGBmb3JtTG9jYWxpemVkKClgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtudWxsfHN0cmluZ30gZm9yY2VkT3V0cHV0Rm9ybWF0IElmIHNldCB0byBzb21ldGhpbmcgZGlmZmVyZW50IHRoYW4gYG51bGxgLCB0aGVuIHRoaXMgaXMgdXNlZCBhcyBhbiBvdmVycmlkaW5nIG91dHB1dEZvcm1hdCBvcHRpb25cbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufG51bGx9IGNhbGxiYWNrXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1TdWJtaXRMb2NhbGl6ZWQoZm9yY2VkT3V0cHV0Rm9ybWF0ID0gbnVsbCwgY2FsbGJhY2sgPSBudWxsKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoY2FsbGJhY2spKSB7XG4gICAgICAgICAgICB0aGlzLmZvcm1VbmZvcm1hdExvY2FsaXplZCgpO1xuICAgICAgICAgICAgdGhpcy5mb3JtKCkuc3VibWl0KCk7XG4gICAgICAgICAgICB0aGlzLmZvcm1SZWZvcm1hdCgpO1xuICAgICAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRnVuY3Rpb24oY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0aGlzLmZvcm1Mb2NhbGl6ZWQoZm9yY2VkT3V0cHV0Rm9ybWF0KSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gY2FsbGJhY2sgaXMgbm90IGEgZnVuY3Rpb24uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhbiBhcnJheSBvZiBudW1lcmljIHN0cmluZ3MgZnJvbSB0aGUgYDxpbnB1dD5gIGVsZW1lbnRzLCBhbmQgcGFzcyBpdCB0byB0aGUgZ2l2ZW4gY2FsbGJhY2suXG4gICAgICogVW5kZXIgdGhlIGhvb2QsIHRoZSBhcnJheSBpcyBnZW5lcmF0ZWQgdmlhIGEgY2FsbCB0byBgZm9ybUFycmF5TnVtZXJpY1N0cmluZygpYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1TdWJtaXRBcnJheU51bWVyaWNTdHJpbmcoY2FsbGJhY2spIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRnVuY3Rpb24oY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0aGlzLmZvcm1BcnJheU51bWVyaWNTdHJpbmcoKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gY2FsbGJhY2sgaXMgbm90IGEgZnVuY3Rpb24uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhbiBhcnJheSBvZiB0aGUgY3VycmVudCBmb3JtYXR0ZWQgdmFsdWVzIGZyb20gdGhlIGA8aW5wdXQ+YCBlbGVtZW50cywgYW5kIHBhc3MgaXQgdG8gdGhlIGdpdmVuIGNhbGxiYWNrLlxuICAgICAqIFVuZGVyIHRoZSBob29kLCB0aGUgYXJyYXkgaXMgZ2VuZXJhdGVkIHZpYSBhIGNhbGwgdG8gYGZvcm1BcnJheUZvcm1hdHRlZCgpYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1TdWJtaXRBcnJheUZvcm1hdHRlZChjYWxsYmFjaykgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNGdW5jdGlvbihjYWxsYmFjaykpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrKHRoaXMuZm9ybUFycmF5Rm9ybWF0dGVkKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGdpdmVuIGNhbGxiYWNrIGlzIG5vdCBhIGZ1bmN0aW9uLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYW4gYXJyYXkgb2YgbG9jYWxpemVkIHN0cmluZ3MgZnJvbSB0aGUgYDxpbnB1dD5gIGVsZW1lbnRzLCBhbmQgcGFzcyBpdCB0byB0aGUgZ2l2ZW4gY2FsbGJhY2suXG4gICAgICogVW5kZXIgdGhlIGhvb2QsIHRoZSBhcnJheSBpcyBnZW5lcmF0ZWQgdmlhIGEgY2FsbCB0byBgZm9ybUFycmF5TG9jYWxpemVkKClgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAgICAgKiBAcGFyYW0ge251bGx8c3RyaW5nfSBmb3JjZWRPdXRwdXRGb3JtYXQgSWYgc2V0IHRvIHNvbWV0aGluZyBkaWZmZXJlbnQgdGhhbiBgbnVsbGAsIHRoZW4gdGhpcyBpcyB1c2VkIGFzIGFuIG92ZXJyaWRpbmcgb3V0cHV0Rm9ybWF0IG9wdGlvblxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBmb3JtU3VibWl0QXJyYXlMb2NhbGl6ZWQoY2FsbGJhY2ssIGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGwpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRnVuY3Rpb24oY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0aGlzLmZvcm1BcnJheUxvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBnaXZlbiBjYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgSlNPTiBzdHJpbmcgd2l0aCB0aGUgbnVtZXJpYyBzdHJpbmdzIHZhbHVlcyBmcm9tIHRoZSBgPGlucHV0PmAgZWxlbWVudHMsIGFuZCBwYXNzIGl0IHRvIHRoZSBnaXZlbiBjYWxsYmFjay5cbiAgICAgKiBVbmRlciB0aGUgaG9vZCwgdGhlIGFycmF5IGlzIGdlbmVyYXRlZCB2aWEgYSBjYWxsIHRvIGBmb3JtSnNvbk51bWVyaWNTdHJpbmcoKWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBmb3JtU3VibWl0SnNvbk51bWVyaWNTdHJpbmcoY2FsbGJhY2spIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRnVuY3Rpb24oY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0aGlzLmZvcm1Kc29uTnVtZXJpY1N0cmluZygpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBnaXZlbiBjYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGEgSlNPTiBzdHJpbmcgd2l0aCB0aGUgY3VycmVudCBmb3JtYXR0ZWQgdmFsdWVzIGZyb20gdGhlIGA8aW5wdXQ+YCBlbGVtZW50cywgYW5kIHBhc3MgaXQgdG8gdGhlIGdpdmVuIGNhbGxiYWNrLlxuICAgICAqIFVuZGVyIHRoZSBob29kLCB0aGUgYXJyYXkgaXMgZ2VuZXJhdGVkIHZpYSBhIGNhbGwgdG8gYGZvcm1Kc29uRm9ybWF0dGVkKClgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgZm9ybVN1Ym1pdEpzb25Gb3JtYXR0ZWQoY2FsbGJhY2spIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRnVuY3Rpb24oY2FsbGJhY2spKSB7XG4gICAgICAgICAgICBjYWxsYmFjayh0aGlzLmZvcm1Kc29uRm9ybWF0dGVkKCkpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGdpdmVuIGNhbGxiYWNrIGlzIG5vdCBhIGZ1bmN0aW9uLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYSBKU09OIHN0cmluZyB3aXRoIHRoZSBsb2NhbGl6ZWQgc3RyaW5ncyB2YWx1ZXMgZnJvbSB0aGUgYDxpbnB1dD5gIGVsZW1lbnRzLCBhbmQgcGFzcyBpdCB0byB0aGUgZ2l2ZW4gY2FsbGJhY2suXG4gICAgICogVW5kZXIgdGhlIGhvb2QsIHRoZSBhcnJheSBpcyBnZW5lcmF0ZWQgdmlhIGEgY2FsbCB0byBgZm9ybUpzb25Mb2NhbGl6ZWQoKWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICAgICAqIEBwYXJhbSB7bnVsbHxzdHJpbmd9IGZvcmNlZE91dHB1dEZvcm1hdCBJZiBzZXQgdG8gc29tZXRoaW5nIGRpZmZlcmVudCB0aGFuIGBudWxsYCwgdGhlbiB0aGlzIGlzIHVzZWQgYXMgYW4gb3ZlcnJpZGluZyBvdXRwdXRGb3JtYXQgb3B0aW9uXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGZvcm1TdWJtaXRKc29uTG9jYWxpemVkKGNhbGxiYWNrLCBmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0Z1bmN0aW9uKGNhbGxiYWNrKSkge1xuICAgICAgICAgICAgY2FsbGJhY2sodGhpcy5mb3JtSnNvbkxvY2FsaXplZChmb3JjZWRPdXRwdXRGb3JtYXQpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBnaXZlbiBjYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVuZm9ybWF0IHRoZSBnaXZlbiBBdXRvTnVtZXJpYyBlbGVtZW50LCBhbmQgdXBkYXRlIHRoZSBgaG92ZXJlZFdpdGhBbHRgIHZhcmlhYmxlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtBdXRvTnVtZXJpY30gYW5FbGVtZW50XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3VuZm9ybWF0QWx0SG92ZXJlZChhbkVsZW1lbnQpIHtcbiAgICAgICAgYW5FbGVtZW50LmhvdmVyZWRXaXRoQWx0ID0gdHJ1ZTtcbiAgICAgICAgYW5FbGVtZW50LnVuZm9ybWF0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVmb3JtYXQgdGhlIGdpdmVuIEF1dG9OdW1lcmljIGVsZW1lbnQsIGFuZCB1cGRhdGUgdGhlIGBob3ZlcmVkV2l0aEFsdGAgdmFyaWFibGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0F1dG9OdW1lcmljfSBhbkVsZW1lbnRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfcmVmb3JtYXRBbHRIb3ZlcmVkKGFuRWxlbWVudCkge1xuICAgICAgICBhbkVsZW1lbnQuaG92ZXJlZFdpdGhBbHQgPSBmYWxzZTtcbiAgICAgICAgYW5FbGVtZW50LnJlZm9ybWF0KCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGFuIGFycmF5IG9mIGF1dG9OdW1lcmljIGVsZW1lbnRzLCBjaGlsZCBvZiB0aGUgPGZvcm0+IGVsZW1lbnQgcGFzc2VkIGFzIGEgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZm9ybU5vZGVcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2dldENoaWxkQU5JbnB1dEVsZW1lbnQoZm9ybU5vZGUpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgY29uc3QgaW5wdXRMaXN0ID0gZm9ybU5vZGUuZ2V0RWxlbWVudHNCeVRhZ05hbWUoJ2lucHV0Jyk7XG5cbiAgICAgICAgLy8gTG9vcCB0aGlzIGxpc3QgYW5kIGtlZXAgb25seSB0aGUgaW5wdXRzIHRoYXQgYXJlIG1hbmFnZWQgYnkgQXV0b051bWVyaWNcbiAgICAgICAgY29uc3QgYXV0b051bWVyaWNJbnB1dHMgPSBbXTtcbiAgICAgICAgY29uc3QgaW5wdXRFbGVtZW50cyA9IEFycmF5LnByb3RvdHlwZS5zbGljZS5jYWxsKGlucHV0TGlzdCwgMCk7XG4gICAgICAgIGlucHV0RWxlbWVudHMuZm9yRWFjaChpbnB1dCA9PiB7XG4gICAgICAgICAgICBpZiAodGhpcy50ZXN0KGlucHV0KSkge1xuICAgICAgICAgICAgICAgIGF1dG9OdW1lcmljSW5wdXRzLnB1c2goaW5wdXQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcblxuICAgICAgICByZXR1cm4gYXV0b051bWVyaWNJbnB1dHM7XG4gICAgfVxuXG4gICAgLy8gU3RhdGljIG1ldGhvZHNcbiAgICAvKipcbiAgICAgKiBUZXN0IGlmIHRoZSBnaXZlbiBkb21FbGVtZW50IGlzIGFscmVhZHkgbWFuYWdlZCBieSBBdXRvTnVtZXJpYyAoaWYgaXQgaGFzIGJlZW4gaW5pdGlhbGl6ZWQgb24gdGhlIGN1cnJlbnQgcGFnZSkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBkb21FbGVtZW50XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIHRlc3QoZG9tRWxlbWVudCkge1xuICAgICAgICByZXR1cm4gdGhpcy5faXNJbkdsb2JhbExpc3QoZG9tRWxlbWVudCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgV2Vha01hcCB3aXRoIHRoZSBnaXZlbiBuYW1lLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHdlYWtNYXBOYW1lXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NyZWF0ZVdlYWtNYXAod2Vha01hcE5hbWUpIHtcbiAgICAgICAgd2luZG93W3dlYWtNYXBOYW1lXSA9IG5ldyBXZWFrTWFwKCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgbGlzdCBvZiBhbGwgdGhlIEF1dG9OdW1lcmljIGVsZW1lbnRzIHRoYXQgYXJlIGluaXRpYWxpemVkIG9uIHRoZSBjdXJyZW50IHBhZ2UuXG4gICAgICogVGhpcyBpcyBuZWVkZWQgaW4gb3JkZXIgdG8gZGV0ZXJtaW5lIGlmIGEgZ2l2ZW4gZG9tIGVsZW1lbnQgaXMgYWxyZWFkeSBtYW5hZ2VkIGJ5IGF1dG9OdW1lcmljLlxuICAgICAqIFRoaXMgdXNlcyBhIFdlYWtNYXAgaW4gb3JkZXIgdG8gbGltaXQgcG90ZW50aWFsIGdhcmJhZ2UgY29sbGVjdGlvbiBwcm9ibGVtcy5cbiAgICAgKiAoY2YuIG15IHRlc3RzIG9uIGh0dHA6Ly9jb2RlcGVuLmlvL0Fub3RoZXJMaW51eFVzZXIvcGVuL3BSUUdhTT9lZGl0b3JzPTEwMTEpXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NyZWF0ZUdsb2JhbExpc3QoKSB7XG4gICAgICAgIC8vIFRoZSBjaGVjayB0aGF0IHRoaXMgZ2xvYmFsIGxpc3QgZG9lcyBub3QgZXhpc3RzIGFscmVhZHkgaXMgZG9uZSBpbiB0aGUgYWRkIGFuZCByZW1vdmUgZnVuY3Rpb25zIGFscmVhZHlcbiAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0dsb2JhbExpc3ROYW1lID0gJ2F1dG9OdW1lcmljR2xvYmFsTGlzdCc7IC8vWFhYIFRoaXMgbG9va3Mgd2VpcmQgdG8gc2V0IGEgdmFyaWFibGUgb24gYHRoaXMuYCBpbiBhIHN0YXRpYyBtZXRob2QsIGJ1dCB0aGF0IHJlYWxseSBkZWNsYXJlIHRoYXQgdmFyaWFibGUgbGlrZSBhIHN0YXRpYyBwcm9wZXJ0eVxuICAgICAgICAvLyBOb3RlOiBJIHNob3VsZCBub3QgZ2V0IGFueSBtZW1vcnkgbGVha3MgZm9yIHJlZmVyZW5jaW5nIHRoZSBET00gZWxlbWVudCBpbiB0aGUgYHZhbHVlYCwgdGhpcyBET00gZWxlbWVudCBhbHNvIGJlaW5nIHRoZSBga2V5YCwgYWNjb3JkaW5nIHRvIHRoZSBzcGVjIDogaHR0cDovL3d3dy5lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzYuMC8jc2VjLXdlYWttYXAtb2JqZWN0c1xuICAgICAgICB0aGlzLl9jcmVhdGVXZWFrTWFwKHRoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2xvYmFsIEF1dG9OdW1lcmljIGVsZW1lbnQgbGlzdCBleGlzdHMuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfZG9lc0dsb2JhbExpc3RFeGlzdHMoKSB7XG4gICAgICAgIGNvbnN0IHR5cGUgPSB0eXBlb2Ygd2luZG93W3RoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZV07XG4gICAgICAgIHJldHVybiB0eXBlICE9PSAndW5kZWZpbmVkJyAmJlxuICAgICAgICAgICAgICAgdHlwZSA9PT0gJ29iamVjdCc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQWRkIHRoZSBnaXZlbiBvYmplY3QgdG8gdGhlIGdsb2JhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0F1dG9OdW1lcmljfSBhdXRvTnVtZXJpY09iamVjdFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9hZGRUb0dsb2JhbExpc3QoYXV0b051bWVyaWNPYmplY3QpIHtcbiAgICAgICAgaWYgKCF0aGlzLl9kb2VzR2xvYmFsTGlzdEV4aXN0cygpKSB7XG4gICAgICAgICAgICB0aGlzLl9jcmVhdGVHbG9iYWxMaXN0KCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkb21FbGVtZW50ID0gYXV0b051bWVyaWNPYmplY3Qubm9kZSgpO1xuICAgICAgICAvLyBUaGlzIGNoZWNrcyBpZiB0aGUgb2JqZWN0IGlzIG5vdCBhbHJlYWR5IGluIHRoZSBnbG9iYWwgbGlzdCBiZWZvcmUgYWRkaW5nIGl0LlxuICAgICAgICAvLyBUaGlzIGNvdWxkIGhhcHBlbiBpZiBhbiBBdXRvTnVtZXJpYyBlbGVtZW50IGlzIGluaXRpYWxpemVkLCB0aGVuIHRoZSBET00gZWxlbWVudCBpcyByZW1vdmVkIGRpcmVjdGx5IHZpYSBgcmVtb3ZlQ2hpbGRgIChoZW5jZSB0aGUgcmVmZXJlbmNlIGRvZXMgbm90IGdldCByZW1vdmVkIGZyb20gdGhlIGdsb2JhbCBsaXN0KSwgdGhlbiBpdCBnZXQgcmVjcmVhdGVkIGFuZCBpbml0aWFsaXplZCBhZ2FpblxuICAgICAgICBpZiAodGhpcy5faXNJbkdsb2JhbExpc3QoZG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLl9nZXRGcm9tR2xvYmFsTGlzdChkb21FbGVtZW50KSA9PT0gdGhpcykge1xuICAgICAgICAgICAgICAgIC8vIERvIG5vdCBhZGQgdGhpcyBBdXRvTnVtZXJpYyBvYmplY3QgYWdhaW4gc2luY2UgaXQncyBhbHJlYWR5IGluIHRoYXQgZ2xvYmFsIGxpc3RcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFByaW50IGEgd2FybmluZyB0byB3YXJuIHRoYXQgdGhlIGRvbUVsZW1lbnQgYWxyZWFkeSBoYXMgYSByZWZlcmVuY2UgaW4gdGhlIGdsb2JhbCBtYXAgKGJ1dCB3ZSBjYW5ub3QgZm9yIHN1cmUgc3RhcnRzIGRlbGV0aW5nIHRob3NlIG9sZCByZWZlcmVuY2VzIHNpbmNlIHRoZXkgY291bGQgc3RpbGwgYmUgdXNlZCBieSBhbm90aGVyIEF1dG9OdW1lcmljIG9iamVjdClcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBBIHJlZmVyZW5jZSB0byB0aGUgRE9NIGVsZW1lbnQgeW91IGp1c3QgaW5pdGlhbGl6ZWQgYWxyZWFkeSBleGlzdHMgaW4gdGhlIGdsb2JhbCBBdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuIFBsZWFzZSBtYWtlIHN1cmUgdG8gbm90IGluaXRpYWxpemUgdGhlIHNhbWUgRE9NIGVsZW1lbnQgbXVsdGlwbGUgdGltZXMuYCwgYXV0b051bWVyaWNPYmplY3QuZ2V0U2V0dGluZ3MoKS5zaG93V2FybmluZ3MpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgd2luZG93W3RoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZV0uc2V0KGRvbUVsZW1lbnQsIGF1dG9OdW1lcmljT2JqZWN0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIGdpdmVuIG9iamVjdCBmcm9tIHRoZSBnbG9iYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtBdXRvTnVtZXJpY30gYXV0b051bWVyaWNPYmplY3RcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfcmVtb3ZlRnJvbUdsb2JhbExpc3QoYXV0b051bWVyaWNPYmplY3QpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgaWYgKHRoaXMuX2RvZXNHbG9iYWxMaXN0RXhpc3RzKCkpIHtcbiAgICAgICAgICAgIHdpbmRvd1t0aGlzLmF1dG9OdW1lcmljR2xvYmFsTGlzdE5hbWVdLmRlbGV0ZShhdXRvTnVtZXJpY09iamVjdC5ub2RlKCkpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHRvIHRoZSBrZXkgYGRvbUVsZW1lbnRgIHBhc3NlZCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKiBUaGUgdmFsdWUgaXMgdGhlIEF1dG9OdW1lcmljIG9iamVjdCB0aGF0IG1hbmFnZXMgdGhlIERPTSBlbGVtZW50IGBkb21FbGVtZW50YC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudH0gZG9tRWxlbWVudFxuICAgICAqIEByZXR1cm5zIHtudWxsfEF1dG9OdW1lcmljfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9nZXRGcm9tR2xvYmFsTGlzdChkb21FbGVtZW50KSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmICh0aGlzLl9kb2VzR2xvYmFsTGlzdEV4aXN0cygpKSB7XG4gICAgICAgICAgICByZXR1cm4gd2luZG93W3RoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZV0uZ2V0KGRvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgaWYgdGhlIGdpdmVuIERPTSBlbGVtZW50IGlzIGluIHRoZSBnbG9iYWwgQXV0b051bWVyaWMgZWxlbWVudCBsaXN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBkb21FbGVtZW50XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2lzSW5HbG9iYWxMaXN0KGRvbUVsZW1lbnQpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgaWYgKCF0aGlzLl9kb2VzR2xvYmFsTGlzdEV4aXN0cygpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gd2luZG93W3RoaXMuYXV0b051bWVyaWNHbG9iYWxMaXN0TmFtZV0uaGFzKGRvbUVsZW1lbnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZSBhIGBNYXBgIHRoYXQgd2lsbCBzdG9yZXMgYWxsIHRoZSBhdXRvTnVtZXJpYyBlbGVtZW50cyB0aGF0IGFyZSBpbml0aWFsaXplZCBmcm9tIHRoaXMgY3VycmVudCBlbGVtZW50LlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2NyZWF0ZUxvY2FsTGlzdCgpIHtcbiAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdCA9IG5ldyBNYXAoKTtcbiAgICAgICAgdGhpcy5fYWRkVG9Mb2NhbExpc3QodGhpcy5kb21FbGVtZW50KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBJbiBzb21lIHJhcmUgY2FzZXMsIHlvdSBjb3VsZCB3YW50IHRvIGRlbGV0ZSB0aGUgbG9jYWwgbGlzdCBnZW5lcmF0ZWQgZHVyaW5nIHRoZSBlbGVtZW50IGluaXRpYWxpemF0aW9uIChpbiBvcmRlciB0byB1c2UgYW5vdGhlciBvbmUgaW5zdGVhZCBmb3IgaW5zdGFuY2UpLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2RlbGV0ZUxvY2FsTGlzdCgpIHtcbiAgICAgICAgZGVsZXRlIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0IHRoZSBsb2NhbCBsaXN0IHdpdGggdGhlIGdpdmVuIE1hcCBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge01hcH0gbG9jYWxMaXN0XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2V0TG9jYWxMaXN0KGxvY2FsTGlzdCkge1xuICAgICAgICB0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0ID0gbG9jYWxMaXN0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgbG9jYWwgbGlzdCBNYXAgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHJldHVybnMgeyp8TWFwfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2dldExvY2FsTGlzdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3Q7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGhhcyBhIGxvY2FsIGxpc3QgZGVmaW5lZCBhbHJlYWR5IGFuZCBoYXMgYXQgbGVhc3Qgb25lIGVsZW1lbnQgaW4gaXQgKGl0c2VsZiB1c3VhbGx5KS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2hhc0xvY2FsTGlzdCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3QgaW5zdGFuY2VvZiBNYXAgJiYgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5zaXplICE9PSAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFkZCB0aGUgZ2l2ZW4gb2JqZWN0IHRvIHRoZSBsb2NhbCBhdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuXG4gICAgICogTm90ZTogaW4gb3JkZXIgdG8ga2VlcCBhIGNvaGVyZW50IGxpc3QsIHdlIG9ubHkgYWRkIERPTSBlbGVtZW50cyBpbiBpdCwgbm90IHRoZSBhdXRvTnVtZXJpYyBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IGRvbUVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge0F1dG9OdW1lcmljfSBhdXRvTnVtZXJpY09iamVjdCBBIHJlZmVyZW5jZSB0byB0aGUgQXV0b051bWVyaWMgb2JqZWN0IHRoYXQgbWFuYWdlIHRoZSBnaXZlbiBET00gZWxlbWVudFxuICAgICAqIEB0aHJvd3NcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9hZGRUb0xvY2FsTGlzdChkb21FbGVtZW50LCBhdXRvTnVtZXJpY09iamVjdCA9IG51bGwpIHtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChhdXRvTnVtZXJpY09iamVjdCkpIHtcbiAgICAgICAgICAgIGF1dG9OdW1lcmljT2JqZWN0ID0gdGhpcztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQodGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdCkpIHtcbiAgICAgICAgICAgIHRoaXMuYXV0b051bWVyaWNMb2NhbExpc3Quc2V0KGRvbUVsZW1lbnQsIGF1dG9OdW1lcmljT2JqZWN0KTsgLy8gVXNlIHRoZSBET00gZWxlbWVudCBhcyBrZXksIGFuZCB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGFzIHRoZSB2YWx1ZVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGxvY2FsIGxpc3QgcHJvdmlkZWQgZG9lcyBub3QgZXhpc3RzIHdoZW4gdHJ5aW5nIHRvIGFkZCBhbiBlbGVtZW50LiBbJHt0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0fV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIGdpdmVuIG9iamVjdCBmcm9tIHRoZSBsb2NhbCBhdXRvTnVtZXJpYyBlbGVtZW50IGxpc3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IGRvbUVsZW1lbnRcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9yZW1vdmVGcm9tTG9jYWxMaXN0KGRvbUVsZW1lbnQpIHtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZCh0aGlzLmF1dG9OdW1lcmljTG9jYWxMaXN0KSkge1xuICAgICAgICAgICAgdGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdC5kZWxldGUoZG9tRWxlbWVudCk7XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5jcmVhdGVMb2NhbExpc3QpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBsb2NhbCBsaXN0IHByb3ZpZGVkIGRvZXMgbm90IGV4aXN0cyB3aGVuIHRyeWluZyB0byByZW1vdmUgYW4gZWxlbWVudC4gWyR7dGhpcy5hdXRvTnVtZXJpY0xvY2FsTGlzdH1dIGdpdmVuLmApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWVyZ2UgdGhlIGBuZXdTZXR0aW5nc2AgZ2l2ZW4gYXMgcGFyYW1ldGVycyBpbnRvIHRoZSBjdXJyZW50IGVsZW1lbnQgc2V0dGluZ3MuXG4gICAgICpcbiAgICAgKiBXQVJOSU5HOiBVc2luZyBgT2JqZWN0LmFzc2lnbigpYCBoZXJlIG1lYW5zIHRoZSBtZXJnZSBpcyBub3QgcmVjdXJzaXZlIGFuZCBvbmx5IG9uZSBkZXB0aCBpcyBtZXJnZWQuXG4gICAgICogY2YuIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzM5MTg4MTA4LzI4MzQ4OThcbiAgICAgKiBjZi4gdGVzdHMgb24gaHR0cDovL2NvZGVwZW4uaW8vQW5vdGhlckxpbnV4VXNlci9wZW4vS2FKT1JxP2VkaXRvcnM9MDAxMVxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG5ld1NldHRpbmdzXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfbWVyZ2VTZXR0aW5ncyguLi5uZXdTZXR0aW5ncykge1xuICAgICAgICBPYmplY3QuYXNzaWduKHRoaXMuc2V0dGluZ3MsIC4uLm5ld1NldHRpbmdzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBuZXcgb2JqZWN0IHdpdGggdGhlIGN1cnJlbnQgZWxlbWVudCBzZXR0aW5ncyBtZXJnZWQgd2l0aCB0aGUgbmV3IHNldHRpbmdzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG5ld1NldHRpbmdzXG4gICAgICogQHJldHVybnMge29iamVjdH1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9jbG9uZUFuZE1lcmdlU2V0dGluZ3MoLi4ubmV3U2V0dGluZ3MpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0ge307XG4gICAgICAgIE9iamVjdC5hc3NpZ24ocmVzdWx0LCB0aGlzLnNldHRpbmdzLCAuLi5uZXdTZXR0aW5ncyk7XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBWYWxpZGF0ZSB0aGUgZ2l2ZW4gb3B0aW9uIG9iamVjdC5cbiAgICAgKiBJZiB0aGUgb3B0aW9ucyBhcmUgdmFsaWQsIHRoaXMgZnVuY3Rpb24gcmV0dXJucyBub3RoaW5nLCBvdGhlcndpc2UgaWYgdGhlIG9wdGlvbnMgYXJlIGludmFsaWQsIHRoaXMgZnVuY3Rpb24gdGhyb3dzIGFuIGVycm9yLlxuICAgICAqXG4gICAgICogVGhpcyB0ZXN0cyBpZiB0aGUgb3B0aW9ucyBhcmUgbm90IGNvbmZsaWN0aW5nIGFuZCBhcmUgd2VsbCBmb3JtYXR0ZWQuXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyBsZW5pZW50IHNpbmNlIGl0IG9ubHkgdGVzdHMgdGhlIHNldHRpbmdzIHByb3BlcnRpZXMgOyBpdCBpZ25vcmVzIGFueSBvdGhlciBwcm9wZXJ0aWVzIHRoZSBvcHRpb25zIG9iamVjdCBjb3VsZCBoYXZlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSB1c2VyT3B0aW9uc1xuICAgICAqIEBwYXJhbSB7Qm9vbGVhbn0gc2hvdWxkRXh0ZW5kRGVmYXVsdE9wdGlvbnMgSWYgYHRydWVgLCB0aGVuIHRoaXMgZnVuY3Rpb24gd2lsbCBleHRlbmRzIHRoZSBgdXNlck9wdGlvbnNgIHBhc3NlZCBieSB0aGUgdXNlciwgd2l0aCB0aGUgZGVmYXVsdCBvcHRpb25zLlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fG51bGx9IG9yaWdpbmFsT3B0aW9ucyBUaGUgdXNlciBjYW4gcGFzcyB0aGUgb3JpZ2luYWwgb3B0aW9ucyAoYW5kIG5vdCB0aGUgb25lIHRoYXQgYXJlIGdlbmVyYXRlZCBmcm9tIHRoZSBkZWZhdWx0IHNldHRpbmdzIGFuZCB0aGUgdmFyaW91cyB1c2FiaWxpdHkgY29ycmVjdGlvbnMpLCBpbiBvcmRlciB0byBhZGQgY29tcGF0aWJpbGl0eSBhbmQgY29uZmxpY3RzIGNoZWNrcy5cbiAgICAgKiBAdGhyb3dzIEVycm9yIFRoaXMgdGhyb3dzIGlmIHRoZSBgdXNlck9wdGlvbnNgIGFyZSBub3QgdmFsaWRcbiAgICAgKi9cbiAgICBzdGF0aWMgdmFsaWRhdGUodXNlck9wdGlvbnMsIHNob3VsZEV4dGVuZERlZmF1bHRPcHRpb25zID0gdHJ1ZSwgb3JpZ2luYWxPcHRpb25zID0gbnVsbCkge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHVzZXJPcHRpb25zKSB8fCAhQXV0b051bWVyaWNIZWxwZXIuaXNPYmplY3QodXNlck9wdGlvbnMpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdXNlck9wdGlvbnMgYXJlIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSB2YWxpZCBvYmplY3QsIFske3VzZXJPcHRpb25zfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpc09yaWdpbmFsT3B0aW9uQW5PYmplY3QgPSBBdXRvTnVtZXJpY0hlbHBlci5pc09iamVjdChvcmlnaW5hbE9wdGlvbnMpO1xuICAgICAgICBpZiAoIWlzT3JpZ2luYWxPcHRpb25Bbk9iamVjdCAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9yaWdpbmFsT3B0aW9ucykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSAnb3JpZ2luYWxPcHRpb25zJyBwYXJhbWV0ZXIgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgYSB2YWxpZCBvcHRpb24gb2JqZWN0IG9yIFxcYG51bGxcXGAsIFske3VzZXJPcHRpb25zfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGUgdXNlciB1c2VkIG9sZCBvcHRpb25zLCB3ZSBjb252ZXJ0IHRoZW0gdG8gbmV3IG9uZXNcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwodXNlck9wdGlvbnMpKSB7XG4gICAgICAgICAgICB0aGlzLl9jb252ZXJ0T2xkT3B0aW9uc1RvTmV3T25lcyh1c2VyT3B0aW9ucyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGUgdXNlciBjYW4gY2hvb3NlIGlmIHRoZSBgdXNlck9wdGlvbnNgIGhhcyBhbHJlYWR5IGJlZW4gZXh0ZW5kZWQgd2l0aCB0aGUgZGVmYXVsdCBvcHRpb25zLCBvciBub3RcbiAgICAgICAgbGV0IG9wdGlvbnM7XG4gICAgICAgIGlmIChzaG91bGRFeHRlbmREZWZhdWx0T3B0aW9ucykge1xuICAgICAgICAgICAgb3B0aW9ucyA9IE9iamVjdC5hc3NpZ24oe30sIHRoaXMuZ2V0RGVmYXVsdENvbmZpZygpLCB1c2VyT3B0aW9ucyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvcHRpb25zID0gdXNlck9wdGlvbnM7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBGaXJzdCB0aGluZ3MgZmlyc3QsIHdlIHRlc3QgdGhhdCB0aGUgYHNob3dXYXJuaW5nc2Agb3B0aW9uIGlzIHZhbGlkXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLnNob3dXYXJuaW5ncykgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLnNob3dXYXJuaW5ncykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBkZWJ1ZyBvcHRpb24gJ3Nob3dXYXJuaW5ncycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMuc2hvd1dhcm5pbmdzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZWZpbmUgdGhlIHJlZ3VsYXIgZXhwcmVzc2lvbnMgbmVlZGVkIGZvciB0aGUgZm9sbG93aW5nIHRlc3RzXG4gICAgICAgIGNvbnN0IHRlc3RQb3NpdGl2ZUludGVnZXIgPSAvXlswLTldKyQvO1xuICAgICAgICBjb25zdCB0ZXN0TnVtZXJpY2FsQ2hhcmFjdGVycyA9IC9bMC05XSsvO1xuICAgICAgICAvLyBjb25zdCB0ZXN0RmxvYXRBbmRQb3NzaWJsZU5lZ2F0aXZlU2lnbiA9IC9eLT9bMC05XSsoXFwuP1swLTldKykkLztcbiAgICAgICAgY29uc3QgdGVzdEZsb2F0T3JJbnRlZ2VyQW5kUG9zc2libGVOZWdhdGl2ZVNpZ24gPSAvXi0/WzAtOV0rKFxcLj9bMC05XSspPyQvO1xuICAgICAgICBjb25zdCB0ZXN0UG9zaXRpdmVGbG9hdE9ySW50ZWdlciA9IC9eWzAtOV0rKFxcLj9bMC05XSspPyQvO1xuXG4gICAgICAgIC8vIFRoZW4gdGVzdHMgdGhlIG9wdGlvbnMgaW5kaXZpZHVhbGx5XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcpICYmXG4gICAgICAgICAgICAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZykgJiZcbiAgICAgICAgICAgIG9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nLmZsb2F0cykge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGRlY2ltYWwgcGFkZGluZyBvcHRpb24gJ2FsbG93RGVjaW1hbFBhZGRpbmcnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlIFxcYGZhbHNlXFxgLCBcXGB0cnVlXFxgIG9yIFxcYCdmbG9hdHMnXFxgLCBbJHtvcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmd9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICgob3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcubmV2ZXIgfHxcbiAgICAgICAgICAgIG9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZyA9PT0gJ2ZhbHNlJyB8fCAvL1RPRE8gTWFrZSBzdXJlIGZvciB0aGUgb3RoZXIgb3B0aW9ucyB0aGF0ICdmYWxzZScgYW5kICd0cnVlJyBhcmUgY29ycmVjdGx5IHRha2VuIGludG8gYWNjb3VudFxuICAgICAgICAgICAgb3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcuZmxvYXRzKSAmJlxuICAgICAgICAgICAgKG9wdGlvbnMuZGVjaW1hbFBsYWNlcyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzLm5vbmUgfHxcbiAgICAgICAgICAgIG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ci5ub25lIHx8XG4gICAgICAgICAgICBvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cy5ub25lKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgU2V0dGluZyAnYWxsb3dEZWNpbWFsUGFkZGluZycgdG8gWyR7b3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nfV0gd2lsbCBvdmVycmlkZSB0aGUgY3VycmVudCAnZGVjaW1hbFBsYWNlcyonIHNldHRpbmdzIFske29wdGlvbnMuZGVjaW1hbFBsYWNlc30sICR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXJ9IGFuZCAke29wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1c31dLmAsIG9wdGlvbnMuc2hvd1dhcm5pbmdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cywgW1xuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5zdGFydCxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZW5kLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5kZWNpbWFsTGVmdCxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZGVjaW1hbFJpZ2h0LFxuICAgICAgICBdKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGRpc3BsYXkgb24gZW1wdHkgc3RyaW5nIG9wdGlvbiAnY2FyZXRQb3NpdGlvbk9uRm9jdXMnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlIFxcYG51bGxcXGAsICdmb2N1cycsICdwcmVzcycsICdhbHdheXMnIG9yICd6ZXJvJywgWyR7b3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1c31dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU3BlY2lhbCBjYXNlIGhlcmUgZm9yIGBjYXJldFBvc2l0aW9uT25Gb2N1c2AgYW5kIGBzZWxlY3RPbkZvY3VzYCB3aGVyZSB3ZSBuZWVkIHRvIGNoZWNrIHRoZSBvcmlnaW5hbCBub24tdGVtcGVyZWQgdmVyc2lvbiBvZiB0aGUgb3B0aW9ucyBpbiBvcmRlciB0byBjaGVjayBmb3IgY29uZmxpY3RzLCBzaW5jZSB1c2luZyB0aGUgZGVmYXVsdCBzZXR0aW5ncyByZW1vdmUgdGhvc2UgYW5kIHdvdWxkIHByZXZlbnQgdXMgd2FybmluZyB0aGUgdXNlciB0aGF0IGhpcyBvcHRpb24gb2JqZWN0IGlzIG5vdCBjb3JyZWN0LlxuICAgICAgICBsZXQgb3B0aW9uc1RvVXNlO1xuICAgICAgICBpZiAoaXNPcmlnaW5hbE9wdGlvbkFuT2JqZWN0KSB7XG4gICAgICAgICAgICBvcHRpb25zVG9Vc2UgPSBvcmlnaW5hbE9wdGlvbnM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvcHRpb25zVG9Vc2UgPSB0aGlzLl9jb3JyZWN0Q2FyZXRQb3NpdGlvbk9uRm9jdXNBbmRTZWxlY3RPbkZvY3VzT3B0aW9ucyh1c2VyT3B0aW9ucyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zVG9Vc2UpICYmXG4gICAgICAgICAgICAoKG9wdGlvbnNUb1VzZS5jYXJldFBvc2l0aW9uT25Gb2N1cyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5kb05vRm9yY2VDYXJldFBvc2l0aW9uICYmXG4gICAgICAgICAgICBvcHRpb25zVG9Vc2Uuc2VsZWN0T25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5zZWxlY3RPbkZvY3VzLnNlbGVjdCkpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBUaGUgJ3NlbGVjdE9uRm9jdXMnIG9wdGlvbiBpcyBzZXQgdG8gJ3NlbGVjdCcsIHdoaWNoIGlzIGluIGNvbmZsaWN0IHdpdGggdGhlICdjYXJldFBvc2l0aW9uT25Gb2N1cycgd2hpY2ggaXMgc2V0IHRvICcke29wdGlvbnNUb1VzZS5jYXJldFBvc2l0aW9uT25Gb2N1c30nLiBBcyBhIHJlc3VsdCwgaWYgdGhpcyBoYXMgYmVlbiBjYWxsZWQgd2hlbiBpbnN0YW50aWF0aW5nIGFuIEF1dG9OdW1lcmljIG9iamVjdCwgdGhlICdzZWxlY3RPbkZvY3VzJyBvcHRpb24gaXMgZm9yY2VkIHRvICdkb05vdFNlbGVjdCcuYCwgb3B0aW9ucy5zaG93V2FybmluZ3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IuY29tbWEsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IuZG90LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLm5vcm1hbFNwYWNlLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLnRoaW5TcGFjZSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5uYXJyb3dOb0JyZWFrU3BhY2UsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3Iubm9CcmVha1NwYWNlLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLm5vU2VwYXJhdG9yLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmFwb3N0cm9waGUsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IuYXJhYmljVGhvdXNhbmRzU2VwYXJhdG9yLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmRvdEFib3ZlLFxuICAgICAgICBdKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHRob3VzYW5kIHNlcGFyYXRvciBjaGFyYWN0ZXIgb3B0aW9uICdkaWdpdEdyb3VwU2VwYXJhdG9yJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlICcsJywgJy4nLCAn2awnLCAny5knLCBcIidcIiwgJyAnLCAnXFx1MjAwOScsICdcXHUyMDJmJywgJ1xcdTAwYTAnIG9yIGVtcHR5ICgnJyksIFske29wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvcn1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1RydWVPckZhbHNlU3RyaW5nKG9wdGlvbnMuc2hvd09ubHlOdW1iZXJzT25Gb2N1cykgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLnNob3dPbmx5TnVtYmVyc09uRm9jdXMpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgJ3Nob3dPbmx5TnVtYmVyc09uRm9jdXMnIG9wdGlvbiBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGVpdGhlciAnZmFsc2UnIG9yICd0cnVlJywgWyR7b3B0aW9ucy5zaG93T25seU51bWJlcnNPbkZvY3VzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRlc3RQb3NpdGl2ZUludGVnZXIudGVzdChvcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZGlnaXRhbCBncm91cGluZyBmb3IgdGhvdXNhbmQgc2VwYXJhdG9yIG9wdGlvbiAnZGlnaXRhbEdyb3VwU3BhY2luZycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHBvc2l0aXZlIGludGVnZXIsIFske29wdGlvbnMuZGlnaXRhbEdyb3VwU3BhY2luZ31dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuY29tbWEsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuZG90LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLm1pZGRsZURvdCxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5hcmFiaWNEZWNpbWFsU2VwYXJhdG9yLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmRlY2ltYWxTZXBhcmF0b3JLZXlTeW1ib2wsXG4gICAgICAgIF0pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZGVjaW1hbCBzZXBhcmF0b3IgY2hhcmFjdGVyIG9wdGlvbiAnZGVjaW1hbENoYXJhY3RlcicgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSAnLicsICcsJywgJ8K3JywgJ+KOlicgb3IgJ9mrJywgWyR7b3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVja3MgaWYgdGhlIGRlY2ltYWwgYW5kIHRob3VzYW5kIGNoYXJhY3RlcnMgYXJlIHRoZSBzYW1lXG4gICAgICAgIGlmIChvcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIgPT09IG9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvcikge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgYXV0b051bWVyaWMgd2lsbCBub3QgZnVuY3Rpb24gcHJvcGVybHkgd2hlbiB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgJ2RlY2ltYWxDaGFyYWN0ZXInIFske29wdGlvbnMuZGVjaW1hbENoYXJhY3Rlcn1dIGFuZCB0aGUgdGhvdXNhbmQgc2VwYXJhdG9yICdkaWdpdEdyb3VwU2VwYXJhdG9yJyBbJHtvcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3J9XSBhcmUgdGhlIHNhbWUgY2hhcmFjdGVyLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc1N0cmluZyhvcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBhbHRlcm5hdGUgZGVjaW1hbCBzZXBhcmF0b3IgY2hhcmFjdGVyIG9wdGlvbiAnZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGEgc3RyaW5nLCBbJHtvcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZX1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKG9wdGlvbnMuY3VycmVuY3lTeW1ib2wgIT09ICcnICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc1N0cmluZyhvcHRpb25zLmN1cnJlbmN5U3ltYm9sKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGN1cnJlbmN5IHN5bWJvbCBvcHRpb24gJ2N1cnJlbmN5U3ltYm9sJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGEgc3RyaW5nLCBbJHtvcHRpb25zLmN1cnJlbmN5U3ltYm9sfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShvcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4LFxuICAgICAgICBdKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHBsYWNlbWVudCBvZiB0aGUgY3VycmVuY3kgc2lnbiBvcHRpb24gJ2N1cnJlbmN5U3ltYm9sUGxhY2VtZW50JyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGVpdGhlciBiZSAncCcgKHByZWZpeCkgb3IgJ3MnIChzdWZmaXgpLCBbJHtvcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50fV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShvcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeCxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodCxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBwbGFjZW1lbnQgb2YgdGhlIG5lZ2F0aXZlIHNpZ24gb3B0aW9uICduZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgJ3AnIChwcmVmaXgpLCAncycgKHN1ZmZpeCksICdsJyAobGVmdCksICdyJyAocmlnaHQpIG9yICdudWxsJywgWyR7b3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudH1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1RydWVPckZhbHNlU3RyaW5nKG9wdGlvbnMuc2hvd1Bvc2l0aXZlU2lnbikgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLnNob3dQb3NpdGl2ZVNpZ24pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgc2hvdyBwb3NpdGl2ZSBzaWduIG9wdGlvbiAnc2hvd1Bvc2l0aXZlU2lnbicgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMuc2hvd1Bvc2l0aXZlU2lnbn1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1N0cmluZyhvcHRpb25zLnN1ZmZpeFRleHQpIHx8IChvcHRpb25zLnN1ZmZpeFRleHQgIT09ICcnICYmIChBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKG9wdGlvbnMuc3VmZml4VGV4dCkgfHwgdGVzdE51bWVyaWNhbENoYXJhY3RlcnMudGVzdChvcHRpb25zLnN1ZmZpeFRleHQpKSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBhZGRpdGlvbmFsIHN1ZmZpeCBvcHRpb24gJ3N1ZmZpeFRleHQnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgbm90IGNvbnRhaW5zIHRoZSBuZWdhdGl2ZSBzaWduICctJyBub3IgYW55IG51bWVyaWNhbCBjaGFyYWN0ZXJzLCBbJHtvcHRpb25zLnN1ZmZpeFRleHR9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy5vdmVycmlkZU1pbk1heExpbWl0cywgW1xuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdmVycmlkZU1pbk1heExpbWl0cy5jZWlsaW5nLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdmVycmlkZU1pbk1heExpbWl0cy5mbG9vcixcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMuaWdub3JlLFxuICAgICAgICBdKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG92ZXJyaWRlIG1pbiAmIG1heCBsaW1pdHMgb3B0aW9uICdvdmVycmlkZU1pbk1heExpbWl0cycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgJ2NlaWxpbmcnLCAnZmxvb3InIG9yICdpZ25vcmUnLCBbJHtvcHRpb25zLm92ZXJyaWRlTWluTWF4TGltaXRzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKG9wdGlvbnMubWF4aW11bVZhbHVlKSB8fCAhdGVzdEZsb2F0T3JJbnRlZ2VyQW5kUG9zc2libGVOZWdhdGl2ZVNpZ24udGVzdChvcHRpb25zLm1heGltdW1WYWx1ZSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBtYXhpbXVtIHBvc3NpYmxlIHZhbHVlIG9wdGlvbiAnbWF4aW11bVZhbHVlJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGEgc3RyaW5nIHRoYXQgcmVwcmVzZW50cyBhIHBvc2l0aXZlIG9yIG5lZ2F0aXZlIG51bWJlciwgWyR7b3B0aW9ucy5tYXhpbXVtVmFsdWV9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5taW5pbXVtVmFsdWUpIHx8ICF0ZXN0RmxvYXRPckludGVnZXJBbmRQb3NzaWJsZU5lZ2F0aXZlU2lnbi50ZXN0KG9wdGlvbnMubWluaW11bVZhbHVlKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG1pbmltdW0gcG9zc2libGUgdmFsdWUgb3B0aW9uICdtaW5pbXVtVmFsdWUnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBzdHJpbmcgdGhhdCByZXByZXNlbnRzIGEgcG9zaXRpdmUgb3IgbmVnYXRpdmUgbnVtYmVyLCBbJHtvcHRpb25zLm1pbmltdW1WYWx1ZX1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcnNlRmxvYXQob3B0aW9ucy5taW5pbXVtVmFsdWUpID4gcGFyc2VGbG9hdChvcHRpb25zLm1heGltdW1WYWx1ZSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBtaW5pbXVtIHBvc3NpYmxlIHZhbHVlIG9wdGlvbiBpcyBncmVhdGVyIHRoYW4gdGhlIG1heGltdW0gcG9zc2libGUgdmFsdWUgb3B0aW9uIDsgJ21pbmltdW1WYWx1ZScgWyR7b3B0aW9ucy5taW5pbXVtVmFsdWV9XSBzaG91bGQgYmUgc21hbGxlciB0aGFuICdtYXhpbXVtVmFsdWUnIFske29wdGlvbnMubWF4aW11bVZhbHVlfV0uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoISgoQXV0b051bWVyaWNIZWxwZXIuaXNJbnQob3B0aW9ucy5kZWNpbWFsUGxhY2VzKSAmJiBvcHRpb25zLmRlY2ltYWxQbGFjZXMgPj0gMCkgfHwgLy8gSWYgaW50ZWdlciBvcHRpb25cbiAgICAgICAgICAgIChBdXRvTnVtZXJpY0hlbHBlci5pc1N0cmluZyhvcHRpb25zLmRlY2ltYWxQbGFjZXMpICYmIHRlc3RQb3NpdGl2ZUludGVnZXIudGVzdChvcHRpb25zLmRlY2ltYWxQbGFjZXMpKSkgLy8gSWYgc3RyaW5nIG9wdGlvblxuICAgICAgICApIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgb3B0aW9uICdkZWNpbWFsUGxhY2VzJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGEgcG9zaXRpdmUgaW50ZWdlciwgWyR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIShBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpIHx8XG4gICAgICAgICAgICAoQXV0b051bWVyaWNIZWxwZXIuaXNJbnQob3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpICYmIG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID49IDApIHx8IC8vIElmIGludGVnZXIgb3B0aW9uXG4gICAgICAgICAgICAoQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpICYmIHRlc3RQb3NpdGl2ZUludGVnZXIudGVzdChvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSkpKSAvLyBJZiBzdHJpbmcgb3B0aW9uXG4gICAgICAgICkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBmb3IgdGhlIHJhdyB2YWx1ZSBvcHRpb24gJ2RlY2ltYWxQbGFjZXNSYXdWYWx1ZScgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHBvc2l0aXZlIGludGVnZXIgb3IgXFxgbnVsbFxcYCwgWyR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWV9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENoZWNrcyBpZiB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIGZvciB0aGUgcmF3IHZhbHVlIGlzIGxvd2VyIHRoYW4gdGhlIGBkZWNpbWFsUGxhY2VzYCwgYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNgIGFuZC9vciBgZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyYCBvcHRpb25zXG4gICAgICAgIHRoaXMuX3ZhbGlkYXRlRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKG9wdGlvbnMpO1xuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cykgJiZcbiAgICAgICAgICAgICF0ZXN0UG9zaXRpdmVJbnRlZ2VyLnRlc3QoU3RyaW5nKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cykpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgbnVtYmVyIG9mIGV4cGFuZGVkIGRlY2ltYWwgcGxhY2VzIG9wdGlvbiAnZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cycgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHBvc2l0aXZlIGludGVnZXIgb3IgXFxgbnVsbFxcYCwgWyR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBDaGVja3MgaWYgdGhlIGV4dGVuZGVkIGRlY2ltYWwgcGxhY2VzIFwiZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1c1wiIGlzIGdyZWF0ZXIgdGhhbiB0aGUgZGVjaW1hbCBwbGFjZXMgbnVtYmVyIGBkZWNpbWFsUGxhY2VzYFxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMpICYmIE51bWJlcihvcHRpb25zLmRlY2ltYWxQbGFjZXMpID4gTnVtYmVyKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFRoZSBleHRlbmRlZCBkZWNpbWFsIHBsYWNlcyAnZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cycgWyR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzfV0gc2hvdWxkIGJlIGdyZWF0ZXIgdGhhbiB0aGUgJ2RlY2ltYWxQbGFjZXMnIFske29wdGlvbnMuZGVjaW1hbFBsYWNlc31dIHZhbHVlLiBDdXJyZW50bHksIHRoaXMgd2lsbCBsaW1pdCB0aGUgYWJpbGl0eSBvZiB5b3VyIHVzZXIgdG8gbWFudWFsbHkgY2hhbmdlIHNvbWUgb2YgdGhlIGRlY2ltYWwgcGxhY2VzLiBEbyB5b3UgcmVhbGx5IHdhbnQgdG8gZG8gdGhhdD9gLCBvcHRpb25zLnNob3dXYXJuaW5ncyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLmRpdmlzb3JXaGVuVW5mb2N1c2VkKSAmJlxuICAgICAgICAgICAgIXRlc3RQb3NpdGl2ZUZsb2F0T3JJbnRlZ2VyLnRlc3Qob3B0aW9ucy5kaXZpc29yV2hlblVuZm9jdXNlZCkgfHxcbiAgICAgICAgICAgIG9wdGlvbnMuZGl2aXNvcldoZW5VbmZvY3VzZWQgPT09IDAgfHwgb3B0aW9ucy5kaXZpc29yV2hlblVuZm9jdXNlZCA9PT0gJzAnIHx8XG4gICAgICAgICAgICBvcHRpb25zLmRpdmlzb3JXaGVuVW5mb2N1c2VkID09PSAxIHx8IG9wdGlvbnMuZGl2aXNvcldoZW5VbmZvY3VzZWQgPT09ICcxJykge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGRpdmlzb3Igb3B0aW9uICdkaXZpc29yV2hlblVuZm9jdXNlZCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHBvc2l0aXZlIG51bWJlciBoaWdoZXIgdGhhbiBvbmUsIHByZWZlcmFibHkgYW4gaW50ZWdlciwgWyR7b3B0aW9ucy5kaXZpc29yV2hlblVuZm9jdXNlZH1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIpICYmICF0ZXN0UG9zaXRpdmVJbnRlZ2VyLnRlc3Qob3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgbnVtYmVyIG9mIGRlY2ltYWxzIHNob3duIHdoZW4gdW5mb2N1c2VkIG9wdGlvbiAnZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGEgcG9zaXRpdmUgaW50ZWdlciBvciBcXGBudWxsXFxgLCBbJHtvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cn1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5zeW1ib2xXaGVuVW5mb2N1c2VkKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy5zeW1ib2xXaGVuVW5mb2N1c2VkKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHN5bWJvbCB0byBzaG93IHdoZW4gdW5mb2N1c2VkIG9wdGlvbiAnc3ltYm9sV2hlblVuZm9jdXNlZCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHN0cmluZywgWyR7b3B0aW9ucy5zeW1ib2xXaGVuVW5mb2N1c2VkfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy5zYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMuc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBzYXZlIHRvIHNlc3Npb24gc3RvcmFnZSBvcHRpb24gJ3NhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2UnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLnNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2V9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMub25JbnZhbGlkUGFzdGUsIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuZXJyb3IsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmlnbm9yZSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuY2xhbXAsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLnRydW5jYXRlLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5yZXBsYWNlLFxuICAgICAgICBdKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHBhc3RlIGJlaGF2aW9yIG9wdGlvbiAnb25JbnZhbGlkUGFzdGUnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlICdlcnJvcicsICdpZ25vcmUnLCAnY2xhbXAnLCAndHJ1bmNhdGUnIG9yICdyZXBsYWNlJyAoY2YuIGRvY3VtZW50YXRpb24pLCBbJHtvcHRpb25zLm9uSW52YWxpZFBhc3RlfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShvcHRpb25zLnJvdW5kaW5nTWV0aG9kLCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZVcFN5bW1ldHJpYyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZlVwQXN5bW1ldHJpYyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZkRvd25TeW1tZXRyaWMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZEb3duQXN5bW1ldHJpYyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZkV2ZW5CYW5rZXJzUm91bmRpbmcsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnVwUm91bmRBd2F5RnJvbVplcm8sXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmRvd25Sb3VuZFRvd2FyZFplcm8sXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnRvQ2VpbGluZ1Rvd2FyZFBvc2l0aXZlSW5maW5pdHksXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnRvRmxvb3JUb3dhcmROZWdhdGl2ZUluZmluaXR5LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC50b05lYXJlc3QwNSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QudG9OZWFyZXN0MDVBbHQsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnVwVG9OZXh0MDUsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmRvd25Ub05leHQwNSxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSByb3VuZGluZyBtZXRob2Qgb3B0aW9uICdyb3VuZGluZ01ldGhvZCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgJ1MnLCAnQScsICdzJywgJ2EnLCAnQicsICdVJywgJ0QnLCAnQycsICdGJywgJ04wNScsICdDSEYnLCAnVTA1JyBvciAnRDA1JyAoY2YuIGRvY3VtZW50YXRpb24pLCBbJHtvcHRpb25zLnJvdW5kaW5nTWV0aG9kfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIsIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIucGFyZW50aGVzZXMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLmJyYWNrZXRzLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5jaGV2cm9ucyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIuY3VybHlCcmFjZXMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLmFuZ2xlQnJhY2tldHMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLmphcGFuZXNlUXVvdGF0aW9uTWFya3MsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLmhhbGZCcmFja2V0cyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIud2hpdGVTcXVhcmVCcmFja2V0cyxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIucXVvdGF0aW9uTWFya3MsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyLmd1aWxsZW1ldHMsXG4gICAgICAgIF0pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgYnJhY2tldHMgZm9yIG5lZ2F0aXZlIHZhbHVlcyBvcHRpb24gJ25lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGVpdGhlciBiZSAnKCwpJywgJ1ssXScsICc8LD4nLCAneyx9JywgJ+OAiCzjgIknLCAn772iLO+9oycsICfiuKQs4rilJywgJ+Kfpizin6cnLCAn4oC5LOKAuicgb3IgJ8KrLMK7JywgWyR7b3B0aW9ucy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1cn1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc0luQXJyYXkob3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IsIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLmZvY3VzLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IucHJlc3MsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5hbHdheXMsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci56ZXJvLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubnVsbCxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBkaXNwbGF5IG9uIGVtcHR5IHN0cmluZyBvcHRpb24gJ2VtcHR5SW5wdXRCZWhhdmlvcicgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgJ2ZvY3VzJywgJ3ByZXNzJywgJ2Fsd2F5cycsICd6ZXJvJyBvciAnbnVsbCcsIFske29wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAob3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLnplcm8gJiZcbiAgICAgICAgICAgIChvcHRpb25zLm1pbmltdW1WYWx1ZSA+IDAgfHwgb3B0aW9ucy5tYXhpbXVtVmFsdWUgPCAwKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlICdlbXB0eUlucHV0QmVoYXZpb3InIG9wdGlvbiBpcyBzZXQgdG8gJ3plcm8nLCBidXQgdGhpcyB2YWx1ZSBpcyBvdXRzaWRlIG9mIHRoZSByYW5nZSBkZWZpbmVkIGJ5ICdtaW5pbXVtVmFsdWUnIGFuZCAnbWF4aW11bVZhbHVlJyBbJHtvcHRpb25zLm1pbmltdW1WYWx1ZX0sICR7b3B0aW9ucy5tYXhpbXVtVmFsdWV9XS5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMubGVhZGluZ1plcm8sIFtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8uYWxsb3csXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmRlbnksXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmtlZXAsXG4gICAgICAgIF0pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgbGVhZGluZyB6ZXJvIGJlaGF2aW9yIG9wdGlvbiAnbGVhZGluZ1plcm8nIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlICdhbGxvdycsICdkZW55JyBvciAna2VlcCcsIFske29wdGlvbnMubGVhZGluZ1plcm99XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLmZvcm1hdE9uUGFnZUxvYWQpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5mb3JtYXRPblBhZ2VMb2FkKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGZvcm1hdCBvbiBpbml0aWFsaXphdGlvbiBvcHRpb24gJ2Zvcm1hdE9uUGFnZUxvYWQnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLmZvcm1hdE9uUGFnZUxvYWR9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghdGVzdFBvc2l0aXZlSW50ZWdlci50ZXN0KG9wdGlvbnMuaGlzdG9yeVNpemUpIHx8IG9wdGlvbnMuaGlzdG9yeVNpemUgPT09IDApIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBoaXN0b3J5IHNpemUgb3B0aW9uICdoaXN0b3J5U2l6ZScgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBhIHBvc2l0aXZlIGludGVnZXIsIFske29wdGlvbnMuaGlzdG9yeVNpemV9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLnNlbGVjdE51bWJlck9ubHkpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5zZWxlY3ROdW1iZXJPbmx5KSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHNlbGVjdCBudW1iZXIgb25seSBvcHRpb24gJ3NlbGVjdE51bWJlck9ubHknIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLnNlbGVjdE51bWJlck9ubHl9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLnNlbGVjdE9uRm9jdXMpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5zZWxlY3RPbkZvY3VzKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHNlbGVjdCBvbiBmb2N1cyBvcHRpb24gJ3NlbGVjdE9uRm9jdXMnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLnNlbGVjdE9uRm9jdXN9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMuZGVmYXVsdFZhbHVlT3ZlcnJpZGUpICYmIChvcHRpb25zLmRlZmF1bHRWYWx1ZU92ZXJyaWRlICE9PSAnJyAmJiAhdGVzdEZsb2F0T3JJbnRlZ2VyQW5kUG9zc2libGVOZWdhdGl2ZVNpZ24udGVzdChvcHRpb25zLmRlZmF1bHRWYWx1ZU92ZXJyaWRlKSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSB1bmZvcm1hdHRlZCBkZWZhdWx0IHZhbHVlIG9wdGlvbiAnZGVmYXVsdFZhbHVlT3ZlcnJpZGUnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBzdHJpbmcgdGhhdCByZXByZXNlbnRzIGEgcG9zaXRpdmUgb3IgbmVnYXRpdmUgbnVtYmVyLCBbJHtvcHRpb25zLmRlZmF1bHRWYWx1ZU92ZXJyaWRlfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy51bmZvcm1hdE9uU3VibWl0KSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMudW5mb3JtYXRPblN1Ym1pdCkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSByZW1vdmUgZm9ybWF0dGluZyBvbiBzdWJtaXQgb3B0aW9uICd1bmZvcm1hdE9uU3VibWl0JyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGVpdGhlciAnZmFsc2UnIG9yICd0cnVlJywgWyR7b3B0aW9ucy51bmZvcm1hdE9uU3VibWl0fV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLm91dHB1dEZvcm1hdCkgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShvcHRpb25zLm91dHB1dEZvcm1hdCwgW1xuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQuc3RyaW5nLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQubnVtYmVyLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQuZG90LFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQubmVnYXRpdmVEb3QsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5jb21tYSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0Lm5lZ2F0aXZlQ29tbWEsXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5kb3ROZWdhdGl2ZSxcbiAgICAgICAgICAgIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0LmNvbW1hTmVnYXRpdmUsXG4gICAgICAgIF0pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgY3VzdG9tIGxvY2FsZSBmb3JtYXQgb3B0aW9uICdvdXRwdXRGb3JtYXQnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlIG51bGwsICdzdHJpbmcnLCAnbnVtYmVyJywgJy4nLCAnLS4nLCAnLCcsICctLCcsICcuLScgb3IgJywtJywgWyR7b3B0aW9ucy5vdXRwdXRGb3JtYXR9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLmlzQ2FuY2VsbGFibGUpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5pc0NhbmNlbGxhYmxlKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGNhbmNlbGxhYmxlIGJlaGF2aW9yIG9wdGlvbiAnaXNDYW5jZWxsYWJsZScgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMuaXNDYW5jZWxsYWJsZX1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1RydWVPckZhbHNlU3RyaW5nKG9wdGlvbnMubW9kaWZ5VmFsdWVPbldoZWVsKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNCb29sZWFuKG9wdGlvbnMubW9kaWZ5VmFsdWVPbldoZWVsKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIGluY3JlbWVudC9kZWNyZW1lbnQgb24gbW91c2Ugd2hlZWwgb3B0aW9uICdtb2RpZnlWYWx1ZU9uV2hlZWwnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLm1vZGlmeVZhbHVlT25XaGVlbH1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCEoQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcob3B0aW9ucy53aGVlbFN0ZXApIHx8IEF1dG9OdW1lcmljSGVscGVyLmlzTnVtYmVyKG9wdGlvbnMud2hlZWxTdGVwKSkgfHxcbiAgICAgICAgICAgIChvcHRpb25zLndoZWVsU3RlcCAhPT0gJ3Byb2dyZXNzaXZlJyAmJiAhdGVzdFBvc2l0aXZlRmxvYXRPckludGVnZXIudGVzdChvcHRpb25zLndoZWVsU3RlcCkpIHx8XG4gICAgICAgICAgICBOdW1iZXIob3B0aW9ucy53aGVlbFN0ZXApID09PSAwKSB7XG4gICAgICAgICAgICAvLyBBIHN0ZXAgZXF1YWwgdG8gJzAnIGlzIHJlamVjdGVkXG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgd2hlZWwgc3RlcCB2YWx1ZSBvcHRpb24gJ3doZWVsU3RlcCcgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBlaXRoZXIgYmUgdGhlIHN0cmluZyAncHJvZ3Jlc3NpdmUnLCBvciBhIG51bWJlciBvciBhIHN0cmluZyB0aGF0IHJlcHJlc2VudHMgYSBwb3NpdGl2ZSBudW1iZXIgKGV4Y2x1ZGluZyB6ZXJvKSwgWyR7b3B0aW9ucy53aGVlbFN0ZXB9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG9wdGlvbnMuc2VyaWFsaXplU3BhY2VzLCBbXG4gICAgICAgICAgICBBdXRvTnVtZXJpYy5vcHRpb25zLnNlcmlhbGl6ZVNwYWNlcy5wbHVzLFxuICAgICAgICAgICAgQXV0b051bWVyaWMub3B0aW9ucy5zZXJpYWxpemVTcGFjZXMucGVyY2VudCxcbiAgICAgICAgXSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBzcGFjZSByZXBsYWNlbWVudCBjaGFyYWN0ZXIgb3B0aW9uICdzZXJpYWxpemVTcGFjZXMnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgZWl0aGVyIGJlICcrJyBvciAnJTIwJywgWyR7b3B0aW9ucy5zZXJpYWxpemVTcGFjZXN9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNUcnVlT3JGYWxzZVN0cmluZyhvcHRpb25zLm5vRXZlbnRMaXN0ZW5lcnMpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5ub0V2ZW50TGlzdGVuZXJzKSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG9wdGlvbiAnbm9FdmVudExpc3RlbmVycycgdGhhdCBwcmV2ZW50IHRoZSBjcmVhdGlvbiBvZiBldmVudCBsaXN0ZW5lcnMgaXMgaW52YWxpZCA7IGl0IHNob3VsZCBiZSBlaXRoZXIgJ2ZhbHNlJyBvciAndHJ1ZScsIFske29wdGlvbnMubm9FdmVudExpc3RlbmVyc31dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bGwob3B0aW9ucy5zdHlsZVJ1bGVzKSAmJlxuICAgICAgICAgICAgIShBdXRvTnVtZXJpY0hlbHBlci5pc09iamVjdChvcHRpb25zLnN0eWxlUnVsZXMpICYmXG4gICAgICAgICAgICAoKG9wdGlvbnMuc3R5bGVSdWxlcy5oYXNPd25Qcm9wZXJ0eSgncG9zaXRpdmUnKSB8fFxuICAgICAgICAgICAgb3B0aW9ucy5zdHlsZVJ1bGVzLmhhc093blByb3BlcnR5KCduZWdhdGl2ZScpIHx8XG4gICAgICAgICAgICBvcHRpb25zLnN0eWxlUnVsZXMuaGFzT3duUHJvcGVydHkoJ3JhbmdlcycpIHx8XG4gICAgICAgICAgICBvcHRpb25zLnN0eWxlUnVsZXMuaGFzT3duUHJvcGVydHkoJ3VzZXJEZWZpbmVkJykpKSkpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBvcHRpb24gJ3N0eWxlUnVsZXMnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBjb3JyZWN0bHkgc3RydWN0dXJlZCBvYmplY3QsIHdpdGggb25lIG9yIG1vcmUgJ3Bvc2l0aXZlJywgJ25lZ2F0aXZlJywgJ3Jhbmdlcycgb3IgJ3VzZXJEZWZpbmVkJyBhdHRyaWJ1dGVzLCBbJHtvcHRpb25zLnN0eWxlUnVsZXN9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERlZXBlciB0ZXN0cyBvZiB0aGUgYHN0eWxlUnVsZXNgIG9iamVjdCA6IENoZWNrIHRoYXQgdGhlIGNhbGxiYWNrLCBpZiBkZWZpbmVkLCBpcyBhIGZ1bmN0aW9uXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMuc3R5bGVSdWxlcykgJiZcbiAgICAgICAgICAgIG9wdGlvbnMuc3R5bGVSdWxlcy5oYXNPd25Qcm9wZXJ0eSgndXNlckRlZmluZWQnKSAmJlxuICAgICAgICAgICAgIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLnN0eWxlUnVsZXMudXNlckRlZmluZWQpKSB7XG4gICAgICAgICAgICBvcHRpb25zLnN0eWxlUnVsZXMudXNlckRlZmluZWQuZm9yRWFjaChydWxlID0+IHtcbiAgICAgICAgICAgICAgICBpZiAocnVsZS5oYXNPd25Qcm9wZXJ0eSgnY2FsbGJhY2snKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNGdW5jdGlvbihydWxlLmNhbGxiYWNrKSkge1xuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgY2FsbGJhY2sgZGVmaW5lZCBpbiB0aGUgXFxgdXNlckRlZmluZWRcXGAgYXR0cmlidXRlIGlzIG5vdCBhIGZ1bmN0aW9uLCAke3R5cGVvZiBydWxlLmNhbGxiYWNrfSBnaXZlbi5gKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMucmF3VmFsdWVEaXZpc29yKSAmJlxuICAgICAgICAgICAgIXRlc3RQb3NpdGl2ZUZsb2F0T3JJbnRlZ2VyLnRlc3Qob3B0aW9ucy5yYXdWYWx1ZURpdmlzb3IpIHx8XG4gICAgICAgICAgICBvcHRpb25zLnJhd1ZhbHVlRGl2aXNvciA9PT0gMCB8fCBvcHRpb25zLnJhd1ZhbHVlRGl2aXNvciA9PT0gJzAnIHx8XG4gICAgICAgICAgICBvcHRpb25zLnJhd1ZhbHVlRGl2aXNvciA9PT0gMSB8fCBvcHRpb25zLnJhd1ZhbHVlRGl2aXNvciA9PT0gJzEnKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgcmF3IHZhbHVlIGRpdmlzb3Igb3B0aW9uICdyYXdWYWx1ZURpdmlzb3InIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgYSBwb3NpdGl2ZSBudW1iZXIgaGlnaGVyIHRoYW4gb25lLCBwcmVmZXJhYmx5IGFuIGludGVnZXIsIFske29wdGlvbnMucmF3VmFsdWVEaXZpc29yfV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy5yZWFkT25seSkgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLnJlYWRPbmx5KSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIG9wdGlvbiAncmVhZE9ubHknIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLnJlYWRPbmx5fV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy51bmZvcm1hdE9uSG92ZXIpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy51bmZvcm1hdE9uSG92ZXIpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgb3B0aW9uICd1bmZvcm1hdE9uSG92ZXInIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLnVuZm9ybWF0T25Ib3Zlcn1dIGdpdmVuLmApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1RydWVPckZhbHNlU3RyaW5nKG9wdGlvbnMuZmFpbE9uVW5rbm93bk9wdGlvbikgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLmZhaWxPblVua25vd25PcHRpb24pKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZGVidWcgb3B0aW9uICdmYWlsT25Vbmtub3duT3B0aW9uJyBpcyBpbnZhbGlkIDsgaXQgc2hvdWxkIGJlIGVpdGhlciAnZmFsc2UnIG9yICd0cnVlJywgWyR7b3B0aW9ucy5mYWlsT25Vbmtub3duT3B0aW9ufV0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVHJ1ZU9yRmFsc2VTdHJpbmcob3B0aW9ucy5jcmVhdGVMb2NhbExpc3QpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc0Jvb2xlYW4ob3B0aW9ucy5jcmVhdGVMb2NhbExpc3QpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZGVidWcgb3B0aW9uICdjcmVhdGVMb2NhbExpc3QnIGlzIGludmFsaWQgOyBpdCBzaG91bGQgYmUgZWl0aGVyICdmYWxzZScgb3IgJ3RydWUnLCBbJHtvcHRpb25zLmNyZWF0ZUxvY2FsTGlzdH1dIGdpdmVuLmApO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgdGhlIGBkZWNpbWFsUGxhY2VzKmAgb3B0aW9ucyBhbmQgb3V0cHV0IHRoZSByZWxldmFudCB3YXJuaW5ncyBpZiBzb21lIG9mIHRob3NlIHdpbGwgZ2V0IG92ZXJ3cml0dGVuIGR1cmluZyB0aGUgaW5pdGlhbGl6YXRpb24gb3Igc2V0dGluZ3MgdXBkYXRlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfdmFsaWRhdGVEZWNpbWFsUGxhY2VzUmF3VmFsdWUob3B0aW9ucykge1xuICAgICAgICAvLyBDaGVja3MgaWYgdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBmb3IgdGhlIHJhdyB2YWx1ZSBpcyBsb3dlciB0aGFuIHRoZSBgZGVjaW1hbFBsYWNlc2AsIGBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzYCBhbmQvb3IgYGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cmAgb3B0aW9uc1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSkpIHtcbiAgICAgICAgICAgIGlmIChvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA8IG9wdGlvbnMuZGVjaW1hbFBsYWNlcykge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8gc3RvcmUgaW4gdGhlIHJhdyB2YWx1ZSBbJHtvcHRpb25zLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZX1dIGlzIGxvd2VyIHRoYW4gdGhlIG9uZXMgdG8gZGlzcGxheSBbJHtvcHRpb25zLmRlY2ltYWxQbGFjZXN9XS4gVGhpcyB3aWxsIGxpa2VseSBjb25mdXNlIHlvdXIgdXNlcnMuXG5UbyBzb2x2ZSB0aGF0LCB5b3UnZCBuZWVkIHRvIGVpdGhlciBzZXQgXFxgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlXFxgIHRvIFxcYG51bGxcXGAsIG9yIHNldCBhIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBmb3IgdGhlIHJhdyB2YWx1ZSBlcXVhbCBvZiBiaWdnZXIgdGhhbiBcXGBkZWNpbWFsUGxhY2VzXFxgLmAsIG9wdGlvbnMuc2hvd1dhcm5pbmdzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDwgb3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzKSB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgVGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0byBzdG9yZSBpbiB0aGUgcmF3IHZhbHVlIFske29wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlfV0gaXMgbG93ZXIgdGhhbiB0aGUgb25lcyBzaG93biBvbiBmb2N1cyBbJHtvcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXN9XS4gVGhpcyB3aWxsIGxpa2VseSBjb25mdXNlIHlvdXIgdXNlcnMuXG5UbyBzb2x2ZSB0aGF0LCB5b3UnZCBuZWVkIHRvIGVpdGhlciBzZXQgXFxgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlXFxgIHRvIFxcYG51bGxcXGAsIG9yIHNldCBhIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBmb3IgdGhlIHJhdyB2YWx1ZSBlcXVhbCBvZiBiaWdnZXIgdGhhbiBcXGBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzXFxgLmAsIG9wdGlvbnMuc2hvd1dhcm5pbmdzKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKG9wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDwgb3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIpIHtcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBUaGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIHN0b3JlIGluIHRoZSByYXcgdmFsdWUgWyR7b3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWV9XSBpcyBsb3dlciB0aGFuIHRoZSBvbmVzIHNob3duIHdoZW4gdW5mb2N1c2VkIFske29wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyfV0uIFRoaXMgd2lsbCBsaWtlbHkgY29uZnVzZSB5b3VyIHVzZXJzLlxuVG8gc29sdmUgdGhhdCwgeW91J2QgbmVlZCB0byBlaXRoZXIgc2V0IFxcYGRlY2ltYWxQbGFjZXNSYXdWYWx1ZVxcYCB0byBcXGBudWxsXFxgLCBvciBzZXQgYSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgZm9yIHRoZSByYXcgdmFsdWUgZXF1YWwgb2YgYmlnZ2VyIHRoYW4gXFxgZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyXFxgLmAsIG9wdGlvbnMuc2hvd1dhcm5pbmdzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHNldHRpbmdzL29wdGlvbnMgYXJlIHZhbGlkLCBgZmFsc2VgIG90aGVyd2lzZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGFyZVNldHRpbmdzVmFsaWQob3B0aW9ucykge1xuICAgICAgICBsZXQgaXNWYWxpZCA9IHRydWU7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLnZhbGlkYXRlKG9wdGlvbnMsIHRydWUpO1xuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgaXNWYWxpZCA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGlzVmFsaWQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBkZWZhdWx0IGF1dG9OdW1lcmljIHNldHRpbmdzLlxuICAgICAqXG4gICAgICogQHJldHVybnMge29iamVjdH1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0RGVmYXVsdENvbmZpZygpIHtcbiAgICAgICAgcmV0dXJuIEF1dG9OdW1lcmljLmRlZmF1bHRTZXR0aW5ncztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYWxsIHRoZSBwcmVkZWZpbmVkIGxhbmd1YWdlIG9wdGlvbnMgaW4gb25lIG9iamVjdC5cbiAgICAgKiBZb3UgY2FuIGFsc28gYWNjZXNzIGEgc3BlY2lmaWMgbGFuZ3VhZ2Ugb2JqZWN0IGRpcmVjdGx5IGJ5IHVzaW5nIGBBdXRvTnVtZXJpYy5nZXRQcmVkZWZpbmVkT3B0aW9ucygpLkZyZW5jaGAgZm9yIGluc3RhbmNlLlxuICAgICAqXG4gICAgICogQHJldHVybnMge29iamVjdH1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0UHJlZGVmaW5lZE9wdGlvbnMoKSB7XG4gICAgICAgIHJldHVybiBBdXRvTnVtZXJpYy5wcmVkZWZpbmVkT3B0aW9ucztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbmFseXNlIHRoZSBnaXZlbiBhcnJheSBgb3B0aW9uc2AgYW5kIHJldHVybiBhIHNpbmdsZSAnbWVyZ2VkJyBvcHRpb24gb2JqZXQuXG4gICAgICogYG9wdGlvbnNgIGNhbiBiZSBgbnVsbGAsIG9yIGFuIGFycmF5IG9mIGFuIG9wdGlvbiBvYmplY3RzLCBvciBhbiBhcnJheSBjb250YWluaW5nIGFub3RoZXIgYXJyYXkgb2Ygb3B0aW9uIG9iamVjdHMgLyBzdHJpbmdzIChwcmUtZGVmaW5lZCBvcHRpb24gbmFtZXMpXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bGx8QXJyYXk8b2JqZWN0fHN0cmluZ3xBcnJheTxzdHJpbmd8b2JqZWN0Pj59IG9wdGlvbnNcbiAgICAgKiBAcmV0dXJucyB7bnVsbHxvYmplY3R9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2dlbmVyYXRlT3B0aW9uc09iamVjdEZyb21PcHRpb25zQXJyYXkob3B0aW9ucykge1xuICAgICAgICBsZXQgb3B0aW9uc1Jlc3VsdDtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShvcHRpb25zKSB8fCBvcHRpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICAgICAgb3B0aW9uc1Jlc3VsdCA9IG51bGw7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBvcHRpb25zUmVzdWx0ID0ge307XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5sZW5ndGggPT09IDEgJiYgQXJyYXkuaXNBcnJheShvcHRpb25zWzBdKSkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnNbMF0uZm9yRWFjaChvcHRpb25PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICAvLyBVc2luZyBgX2dldE9wdGlvbk9iamVjdCgpYCBhbGxvd3MgdXNpbmcgcHJlLWRlZmluZWQgbmFtZXMgaW4gdGhlIGBvcHRpb25zYCBhcnJheVxuICAgICAgICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKG9wdGlvbnNSZXN1bHQsIHRoaXMuX2dldE9wdGlvbk9iamVjdChvcHRpb25PYmplY3QpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAob3B0aW9ucy5sZW5ndGggPj0gMSkge1xuICAgICAgICAgICAgICAgIG9wdGlvbnMuZm9yRWFjaChvcHRpb25PYmplY3QgPT4ge1xuICAgICAgICAgICAgICAgICAgICBPYmplY3QuYXNzaWduKG9wdGlvbnNSZXN1bHQsIHRoaXMuX2dldE9wdGlvbk9iamVjdChvcHRpb25PYmplY3QpKTtcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBvcHRpb25zUmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvcm1hdCB0aGUgZ2l2ZW4gbnVtYmVyIChvciBudW1lcmljIHN0cmluZykgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucy4gVGhpcyByZXR1cm5zIHRoZSBmb3JtYXR0ZWQgdmFsdWUgYXMgYSBzdHJpbmcuXG4gICAgICogVGhpcyBjYW4gYWxzbyBmb3JtYXQgdGhlIGdpdmVuIERPTSBlbGVtZW50IHZhbHVlIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMgYW5kIHJldHVybnMgdGhlIGZvcm1hdHRlZCB2YWx1ZSBhcyBhIHN0cmluZy5cbiAgICAgKiBOb3RlIDogVGhpcyBmdW5jdGlvbiBkb2VzICpub3QqIHVwZGF0ZSB0aGF0IGVsZW1lbnQgdmFsdWUgd2l0aCB0aGUgbmV3bHkgZm9ybWF0dGVkIHZhbHVlLlxuICAgICAqIFRoaXMgYmFzaWNhbGx5IGFsbG93cyB0byBnZXQgdGhlIGZvcm1hdHRlZCB2YWx1ZSB3aXRob3V0IGZpcnN0IGhhdmluZyB0byBpbml0aWFsaXplIGFuIEF1dG9OdW1lcmljIG9iamVjdC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfHN0cmluZ3xIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBudW1lcmljU3RyaW5nT3JEb21FbGVtZW50IEEgbnVtYmVyLCBvciBhIHN0cmluZyB0aGF0IHJlcHJlc2VudCBhIGphdmFzY3JpcHQgbnVtYmVyLCBvciBhIERPTSBlbGVtZW50XG4gICAgICogQHBhcmFtIHtvYmplY3R8bnVsbH0gb3B0aW9ucyBNdWx0aXBsZSBvYmplY3RzIGNhbiBiZSBwYXNzZWQsIHRoZSBsYXR0ZXIgb3ZlcndyaXRpbmcgdGhlIHNldHRpbmdzIGZyb20gdGhlIGZvcm1lciBvbmVzXG4gICAgICogQHJldHVybnMge3N0cmluZ3xudWxsfVxuICAgICAqL1xuICAgIHN0YXRpYyBmb3JtYXQobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCwgLi4ub3B0aW9ucykge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCkgfHwgbnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZXRyaWV2ZSB0aGUgdmFsdWUgdG8gZm9ybWF0XG4gICAgICAgIGxldCB2YWx1ZTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRWxlbWVudChudW1lcmljU3RyaW5nT3JEb21FbGVtZW50KSkge1xuICAgICAgICAgICAgdmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZSA9IG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzU3RyaW5nKHZhbHVlKSAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIodmFsdWUpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdmFsdWUgXCIke3ZhbHVlfVwiIGJlaW5nIFwic2V0XCIgaXMgbm90IG51bWVyaWMgYW5kIHRoZXJlZm9yZSBjYW5ub3QgYmUgdXNlZCBhcHByb3ByaWF0ZWx5LmApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTWFuYWdlIG9wdGlvbnNcbiAgICAgICAgY29uc3Qgb3B0aW9uc1RvVXNlID0gdGhpcy5fZ2VuZXJhdGVPcHRpb25zT2JqZWN0RnJvbU9wdGlvbnNBcnJheShvcHRpb25zKTtcblxuICAgICAgICAvLyBJbml0aWF0ZSBhIHZlcnkgYmFzaWMgc2V0dGluZ3Mgb2JqZWN0XG4gICAgICAgIGNvbnN0IHNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5nZXREZWZhdWx0Q29uZmlnKCksIG9wdGlvbnNUb1VzZSk7XG4gICAgICAgIGlmICh2YWx1ZSA8IDApIHtcbiAgICAgICAgICAgIHNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciA9ICctJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciA9ICcnO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgcmVnZXggPSB7fTtcbiAgICAgICAgdGhpcy5fY2FjaGVzVXN1YWxSZWd1bGFyRXhwcmVzc2lvbnMoc2V0dGluZ3MsIHJlZ2V4KTsgLy8gVGhpcyBpcyBuZWVkZWQgYnkgYF9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnNgIHRoYXQgdXNlcyB0aG9zZSByZWdleFxuXG4gICAgICAgIC8vIENoZWNrIHRoZSB2YWxpZGl0eSBvZiB0aGUgYHZhbHVlYCBwYXJhbWV0ZXJcbiAgICAgICAgLy8gQ29udmVydCB0aGUgdmFsdWUgdG8gYSBudW1lcmljIHN0cmluZywgc3RyaXBwaW5nIHVubmVjZXNzYXJ5IGNoYXJhY3RlcnMgaW4gdGhlIHByb2Nlc3NcbiAgICAgICAgbGV0IHZhbHVlU3RyaW5nID0gdGhpcy5fdG9OdW1lcmljVmFsdWUodmFsdWUsIHNldHRpbmdzKTtcbiAgICAgICAgaWYgKGlzTmFOKE51bWJlcih2YWx1ZVN0cmluZykpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgdmFsdWUgWyR7dmFsdWVTdHJpbmd9XSB0aGF0IHlvdSBhcmUgdHJ5aW5nIHRvIGZvcm1hdCBpcyBub3QgYSByZWNvZ25pemVkIG51bWJlci5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEJhc2ljIHRlc3RzIHRvIGNoZWNrIGlmIHRoZSBnaXZlbiB2YWx1ZVN0cmluZyBpcyB2YWxpZFxuICAgICAgICBjb25zdCBbbWluVGVzdCwgbWF4VGVzdF0gPSB0aGlzLl9jaGVja0lmSW5SYW5nZVdpdGhPdmVycmlkZU9wdGlvbih2YWx1ZVN0cmluZywgc2V0dGluZ3MpO1xuICAgICAgICBpZiAoIW1pblRlc3QgfHwgIW1heFRlc3QpIHtcbiAgICAgICAgICAgIC8vIFRocm93IGEgY3VzdG9tIGV2ZW50XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLmZvcm1hdHRlZCwgZG9jdW1lbnQsICdSYW5nZSB0ZXN0IGZhaWxlZCcpO1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHZhbHVlIFske3ZhbHVlU3RyaW5nfV0gYmVpbmcgc2V0IGZhbGxzIG91dHNpZGUgb2YgdGhlIG1pbmltdW1WYWx1ZSBbJHtzZXR0aW5ncy5taW5pbXVtVmFsdWV9XSBhbmQgbWF4aW11bVZhbHVlIFske3NldHRpbmdzLm1heGltdW1WYWx1ZX1dIHJhbmdlIHNldCBmb3IgdGhpcyBlbGVtZW50YCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBHZW5lcmF0ZSB0aGUgYG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50YCBvcHRpb24gYXMgbmVlZGVkXG4gICAgICAgIHRoaXMuX2NvcnJlY3ROZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudE9wdGlvbihzZXR0aW5ncyk7XG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgbmVlZGVkIGRlY2ltYWwgcGxhY2VzXG4gICAgICAgIHRoaXMuX2NhbGN1bGF0ZURlY2ltYWxQbGFjZXNPbkluaXQoc2V0dGluZ3MpO1xuXG4gICAgICAgIC8vIE11bHRpcGx5IHRoZSByYXcgdmFsdWUgd2l0aCBgcmF3VmFsdWVEaXZpc29yYCBpZiBkZWZpbmVkXG4gICAgICAgIGlmICgoIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IpICYmIHNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvciAhPT0gMCkgJiYgLy8gT25seSBkaXZpZGUgaWYgdGhlIGByYXdWYWx1ZURpdmlzb3JgIG9wdGlvbiBpcyBzZXRcbiAgICAgICAgICAgIHZhbHVlU3RyaW5nICE9PSAnJyAmJiB2YWx1ZVN0cmluZyAhPT0gbnVsbCkgeyAvLyBEbyBub3QgbW9kaWZ5IHRoZSBgdmFsdWVTdHJpbmdgIGlmIGl0J3MgYW4gZW1wdHkgc3RyaW5nIG9yIG51bGxcbiAgICAgICAgICAgIHZhbHVlU3RyaW5nICo9IHNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvcjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEV2ZXJ5dGhpbmcgaXMgb2ssIHByb2NlZWQgdG8gcm91bmRpbmcsIGZvcm1hdHRpbmcgYW5kIGdyb3VwaW5nXG4gICAgICAgIHZhbHVlU3RyaW5nID0gdGhpcy5fcm91bmRGb3JtYXR0ZWRWYWx1ZVNob3duT25Gb2N1cyh2YWx1ZVN0cmluZywgc2V0dGluZ3MpO1xuICAgICAgICB2YWx1ZVN0cmluZyA9IHRoaXMuX21vZGlmeU5lZ2F0aXZlU2lnbkFuZERlY2ltYWxDaGFyYWN0ZXJGb3JGb3JtYXR0ZWRWYWx1ZSh2YWx1ZVN0cmluZywgc2V0dGluZ3MpO1xuICAgICAgICB2YWx1ZVN0cmluZyA9IHRoaXMuX2FkZEdyb3VwU2VwYXJhdG9ycyh2YWx1ZVN0cmluZywgc2V0dGluZ3MsIGZhbHNlLCB2YWx1ZVN0cmluZyk7XG5cbiAgICAgICAgcmV0dXJuIHZhbHVlU3RyaW5nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvcm1hdCB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgdmFsdWUsIGFuZCBzZXQgdGhlIHJlc3VsdGluZyB2YWx1ZSBiYWNrIGFzIHRoZSBlbGVtZW50IHZhbHVlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBkb21FbGVtZW50XG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gICAgICovXG4gICAgc3RhdGljIGZvcm1hdEFuZFNldChkb21FbGVtZW50LCBvcHRpb25zID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBjb25zdCBmb3JtYXR0ZWRWYWx1ZSA9IHRoaXMuZm9ybWF0KGRvbUVsZW1lbnQsIG9wdGlvbnMpO1xuICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50VmFsdWUoZG9tRWxlbWVudCwgZm9ybWF0dGVkVmFsdWUpO1xuXG4gICAgICAgIHJldHVybiBmb3JtYXR0ZWRWYWx1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbmZvcm1hdCB0aGUgZ2l2ZW4gZm9ybWF0dGVkIHN0cmluZyB3aXRoIHRoZSBnaXZlbiBvcHRpb25zLiBUaGlzIHJldHVybnMgYSBudW1lcmljIHN0cmluZy5cbiAgICAgKiBJdCBjYW4gYWxzbyB1bmZvcm1hdCB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgdmFsdWUgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucyBhbmQgcmV0dXJucyB0aGUgdW5mb3JtYXR0ZWQgbnVtZXJpYyBzdHJpbmcuXG4gICAgICogTm90ZTogVGhpcyBkb2VzICpub3QqIHVwZGF0ZSB0aGF0IGVsZW1lbnQgdmFsdWUuXG4gICAgICogVGhpcyBiYXNpY2FsbHkgYWxsb3dzIHRvIGdldCB0aGUgdW5mb3JtYXR0ZWQgdmFsdWUgd2l0aG91dCBmaXJzdCBoYXZpbmcgdG8gaW5pdGlhbGl6ZSBhbiBBdXRvTnVtZXJpYyBvYmplY3QuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ8SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudH0gbnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCBBIG51bWJlciwgb3IgYSBzdHJpbmcgdGhhdCByZXByZXNlbnQgYSBqYXZhc2NyaXB0IG51bWJlciwgb3IgYSBET00gZWxlbWVudFxuICAgICAqIEBwYXJhbSB7b2JqZWN0fG51bGx9IG9wdGlvbnMgTXVsdGlwbGUgb2JqZWN0cyBjYW4gYmUgcGFzc2VkLCB0aGUgbGF0dGVyIG92ZXJ3cml0aW5nIHRoZSBzZXR0aW5ncyBmcm9tIHRoZSBmb3JtZXIgb25lc1xuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVtYmVyfE5hTn1cbiAgICAgKi9cbiAgICBzdGF0aWMgdW5mb3JtYXQobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCwgLi4ub3B0aW9ucykge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXJTdHJpY3QobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIC8vIEdpdmluZyBhbiB1bmZvcm1hdHRlZCB2YWx1ZSBzaG91bGQgcmV0dXJuIHRoZSBzYW1lIHVuZm9ybWF0dGVkIHZhbHVlLCB3aGF0ZXZlciB0aGUgb3B0aW9ucyBwYXNzZWQgYXMgYSBwYXJhbWV0ZXJcbiAgICAgICAgICAgIHJldHVybiBudW1lcmljU3RyaW5nT3JEb21FbGVtZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmV0cmlldmUgdGhlIHZhbHVlIHRvIHVuZm9ybWF0XG4gICAgICAgIGxldCB2YWx1ZTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRWxlbWVudChudW1lcmljU3RyaW5nT3JEb21FbGVtZW50KSkge1xuICAgICAgICAgICAgdmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB2YWx1ZSA9IG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQodmFsdWUpIHx8IHZhbHVlID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0FycmF5KHZhbHVlKSB8fCBBdXRvTnVtZXJpY0hlbHBlci5pc09iamVjdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIC8vIENoZWNrIHRoZSB2YWxpZGl0eSBvZiB0aGUgYHZhbHVlYCBwYXJhbWV0ZXJcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYEEgbnVtYmVyIG9yIGEgc3RyaW5nIHJlcHJlc2VudGluZyBhIG51bWJlciBpcyBuZWVkZWQgdG8gYmUgYWJsZSB0byB1bmZvcm1hdCBpdCwgWyR7dmFsdWV9XSBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1hbmFnZSBvcHRpb25zXG4gICAgICAgIGNvbnN0IG9wdGlvbnNUb1VzZSA9IHRoaXMuX2dlbmVyYXRlT3B0aW9uc09iamVjdEZyb21PcHRpb25zQXJyYXkob3B0aW9ucyk7XG5cbiAgICAgICAgLy8gR2VuZXJhdGUgdGhlIHNldHRpbmdzXG4gICAgICAgIGNvbnN0IHNldHRpbmdzID0gT2JqZWN0LmFzc2lnbih7fSwgdGhpcy5nZXREZWZhdWx0Q29uZmlnKCksIG9wdGlvbnNUb1VzZSk7XG4gICAgICAgIHZhbHVlID0gdmFsdWUudG9TdHJpbmcoKTtcblxuICAgICAgICAvLyBUaGlzIGNoZWNrcyBpZiBhIG5lZ2F0aXZlIHNpZ24gaXMgYW55d2hlcmUgaW4gdGhlIGB2YWx1ZWAsIG5vdCBqdXN0IG9uIHRoZSB2ZXJ5IGZpcnN0IGNoYXJhY3RlciAoaWUuICcxMjM0NS42Ny0nKVxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciA9ICctJztcbiAgICAgICAgfSBlbHNlIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHNldHRpbmdzLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyKSkge1xuICAgICAgICAgICAgW3NldHRpbmdzLmZpcnN0QnJhY2tldCwgc2V0dGluZ3MubGFzdEJyYWNrZXRdID0gc2V0dGluZ3MubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIuc3BsaXQoJywnKTtcbiAgICAgICAgICAgIGlmICh2YWx1ZS5jaGFyQXQoMCkgPT09IHNldHRpbmdzLmZpcnN0QnJhY2tldCAmJlxuICAgICAgICAgICAgICAgIHZhbHVlLmNoYXJBdCh2YWx1ZS5sZW5ndGggLSAxKSA9PT0gc2V0dGluZ3MubGFzdEJyYWNrZXQpIHtcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgPSAnLSc7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSB0aGlzLl9yZW1vdmVCcmFja2V0cyh2YWx1ZSwgc2V0dGluZ3MsIGZhbHNlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhbHVlID0gdGhpcy5fY29udmVydFRvTnVtZXJpY1N0cmluZyh2YWx1ZSwgc2V0dGluZ3MpO1xuICAgICAgICBjb25zdCB1bndhbnRlZENoYXJhY3RlcnMgPSBuZXcgUmVnRXhwKGBbXistMDEyMzQ1Njc4OS5dYCwgJ2dpJyk7XG4gICAgICAgIGlmICh1bndhbnRlZENoYXJhY3RlcnMudGVzdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBOYU47XG4gICAgICAgIH1cblxuICAgICAgICAvLyBHZW5lcmF0ZSB0aGUgYG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50YCBvcHRpb24gYXMgbmVlZGVkXG4gICAgICAgIHRoaXMuX2NvcnJlY3ROZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudE9wdGlvbihzZXR0aW5ncyk7XG4gICAgICAgIC8vIENhbGN1bGF0ZSB0aGUgbmVlZGVkIGRlY2ltYWwgcGxhY2VzXG4gICAgICAgIGlmIChzZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpIHsgLy8gYG9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlYCBuZWVkcyB0byBiZSBkZWZpbmVkXG4gICAgICAgICAgICBzZXR0aW5ncy5vcmlnaW5hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IHNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNldHRpbmdzLm9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gc2V0dGluZ3MuZGVjaW1hbFBsYWNlcztcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX2NhbGN1bGF0ZURlY2ltYWxQbGFjZXNPbkluaXQoc2V0dGluZ3MpO1xuXG4gICAgICAgIC8vIERpdmlkZSB0aGUgcmF3IHZhbHVlIHdpdGggYHJhd1ZhbHVlRGl2aXNvcmAgaWYgZGVmaW5lZFxuICAgICAgICBpZiAoKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkoc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yKSAmJiBzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IgIT09IDApICYmIC8vIE9ubHkgZGl2aWRlIGlmIHRoZSBgcmF3VmFsdWVEaXZpc29yYCBvcHRpb24gaXMgc2V0XG4gICAgICAgICAgICB2YWx1ZSAhPT0gJycgJiYgdmFsdWUgIT09IG51bGwpIHsgLy8gRG8gbm90IG1vZGlmeSB0aGUgYHZhbHVlYCBpZiBpdCdzIGFuIGVtcHR5IHN0cmluZyBvciBudWxsXG4gICAgICAgICAgICB2YWx1ZSAvPSBzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3I7XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIHZhbHVlID0gdGhpcy5fcm91bmRSYXdWYWx1ZSh2YWx1ZSwgc2V0dGluZ3MpO1xuICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2Uoc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciwgJy4nKTsgLy8gSGVyZSB3ZSBuZWVkIHRvIGNvbnZlcnQgYmFjayB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgdG8gYSBwZXJpb2Qgc2luY2UgYF9yb3VuZFZhbHVlYCBhZGRzIGl0IGluIHNvbWUgY2FzZXNcbiAgICAgICAgdmFsdWUgPSB0aGlzLl90b0xvY2FsZSh2YWx1ZSwgc2V0dGluZ3Mub3V0cHV0Rm9ybWF0KTtcblxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW5mb3JtYXQgdGhlIGdpdmVuIERPTSBlbGVtZW50IHZhbHVlLCBhbmQgc2V0IHRoZSByZXN1bHRpbmcgdmFsdWUgYmFjayBhcyB0aGUgZWxlbWVudCB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudH0gZG9tRWxlbWVudFxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIHVuZm9ybWF0QW5kU2V0KGRvbUVsZW1lbnQsIG9wdGlvbnMgPSBudWxsKSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGNvbnN0IHVuZm9ybWF0dGVkVmFsdWUgPSB0aGlzLnVuZm9ybWF0KGRvbUVsZW1lbnQsIG9wdGlvbnMpO1xuICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50VmFsdWUoZG9tRWxlbWVudCwgdW5mb3JtYXR0ZWRWYWx1ZSk7XG5cbiAgICAgICAgcmV0dXJuIHVuZm9ybWF0dGVkVmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW5mb3JtYXQgYW5kIGxvY2FsaXplIHRoZSBnaXZlbiBmb3JtYXR0ZWQgc3RyaW5nIHdpdGggdGhlIGdpdmVuIG9wdGlvbnMuIFRoaXMgcmV0dXJucyBhIG51bWVyaWMgc3RyaW5nLlxuICAgICAqIEl0IGNhbiBhbHNvIHVuZm9ybWF0IGFuZCBsb2NhbGl6ZSB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgdmFsdWUgd2l0aCB0aGUgZ2l2ZW4gb3B0aW9ucyBhbmQgcmV0dXJucyB0aGUgdW5mb3JtYXR0ZWQgbnVtZXJpYyBzdHJpbmcuXG4gICAgICogTm90ZTogVGhpcyBkb2VzICpub3QqIHVwZGF0ZSB0aGF0IGVsZW1lbnQgdmFsdWUuXG4gICAgICogVGhpcyBiYXNpY2FsbHkgYWxsb3dzIHRvIGdldCB0aGUgbG9jYWxpemVkIHZhbHVlIHdpdGhvdXQgZmlyc3QgaGF2aW5nIHRvIGluaXRpYWxpemUgYW4gQXV0b051bWVyaWMgb2JqZWN0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd8bnVtYmVyfEhUTUxFbGVtZW50fEhUTUxJbnB1dEVsZW1lbnR9IG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uc1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBsb2NhbGl6ZShudW1lcmljU3RyaW5nT3JEb21FbGVtZW50LCBvcHRpb25zID0gbnVsbCkge1xuICAgICAgICBsZXQgdmFsdWU7XG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc0VsZW1lbnQobnVtZXJpY1N0cmluZ09yRG9tRWxlbWVudCkpIHtcbiAgICAgICAgICAgIHZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKG51bWVyaWNTdHJpbmdPckRvbUVsZW1lbnQpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdmFsdWUgPSBudW1lcmljU3RyaW5nT3JEb21FbGVtZW50O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zKSkge1xuICAgICAgICAgICAgb3B0aW9ucyA9IEF1dG9OdW1lcmljLmRlZmF1bHRTZXR0aW5ncztcbiAgICAgICAgfVxuXG4gICAgICAgIHZhbHVlID0gdGhpcy51bmZvcm1hdCh2YWx1ZSwgb3B0aW9ucyk7XG5cbiAgICAgICAgLy9YWFggVGhlIGZvbGxvd2luZyBjb2RlIGlzIHByZXR0eSBjbG9zZSB0byB0aGUgb25lIHlvdSBjYW4gZmluZCBpbiBgZ2V0TG9jYWxpemVkKClgLCBidXQgZGlmZmVyZW50IGVub3VnaCBzbyB3ZSB3b24ndCByZWZhY3RvciBpdC5cbiAgICAgICAgaWYgKE51bWJlcih2YWx1ZSkgPT09IDAgJiYgb3B0aW9ucy5sZWFkaW5nWmVybyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5rZWVwKSB7XG4gICAgICAgICAgICB2YWx1ZSA9ICcwJztcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBvdXRwdXRGb3JtYXRUb1VzZTtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zKSkge1xuICAgICAgICAgICAgb3V0cHV0Rm9ybWF0VG9Vc2UgPSBvcHRpb25zLm91dHB1dEZvcm1hdDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdFRvVXNlID0gQXV0b051bWVyaWMuZGVmYXVsdFNldHRpbmdzLm91dHB1dEZvcm1hdDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLl90b0xvY2FsZSh2YWx1ZSwgb3V0cHV0Rm9ybWF0VG9Vc2UpO1xuICAgIH1cblxuICAgIHN0YXRpYyBsb2NhbGl6ZUFuZFNldChkb21FbGVtZW50LCBvcHRpb25zID0gbnVsbCkgeyAvL0ZJWE1FIHRlc3QgdGhpc1xuICAgICAgICBjb25zdCBsb2NhbGl6ZWRWYWx1ZSA9IHRoaXMubG9jYWxpemUoZG9tRWxlbWVudCwgb3B0aW9ucyk7XG4gICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRWYWx1ZShkb21FbGVtZW50LCBsb2NhbGl6ZWRWYWx1ZSk7XG5cbiAgICAgICAgcmV0dXJuIGxvY2FsaXplZFZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGdpdmVuIERPTSBlbGVtZW50IGhhcyBhbiBBdXRvTnVtZXJpYyBvYmplY3QgdGhhdCBtYW5hZ2VzIGl0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudH0gZG9tRWxlbWVudFxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBpc01hbmFnZWRCeUF1dG9OdW1lcmljKGRvbUVsZW1lbnQpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgcmV0dXJuIHRoaXMuX2lzSW5HbG9iYWxMaXN0KGRvbUVsZW1lbnQpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgQXV0b051bWVyaWMgb2JqZWN0IHRoYXQgbWFuYWdlcyB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxFbGVtZW50fSBkb21FbGVtZW50XG4gICAgICogQHJldHVybnMge251bGx8QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgc3RhdGljIGdldEF1dG9OdW1lcmljRWxlbWVudChkb21FbGVtZW50KSB7IC8vRklYTUUgdGVzdCB0aGlzXG4gICAgICAgIGlmICghdGhpcy5pc01hbmFnZWRCeUF1dG9OdW1lcmljKGRvbUVsZW1lbnQpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLl9nZXRGcm9tR2xvYmFsTGlzdChkb21FbGVtZW50KTtcbiAgICB9XG5cblxuICAgIC8vIFByZS1kZWZpbmVkIG9wdGlvbnMgY2FuIGJlIGNhbGxlZCB0byB1cGRhdGUgdGhlIGN1cnJlbnQgZGVmYXVsdCBvcHRpb25zIHdpdGggdGhlaXIgc3BlY2lmaWNpdGllc1xuICAgIC8vWFhYIEEgYmV0dGVyIHdheSB3b3VsZCBiZSB0byBub3QgaW5pdGlhbGl6ZSBmaXJzdCwgYnV0IHRoYXQncyBub3QgcG9zc2libGUgc2luY2UgYG5ld2AgaXMgY2FsbGVkIGZpcnN0IGFuZCB3ZSBkbyBub3QgcGFzcyB0aGUgbGFuZ3VhZ2Ugb3B0aW9ucyAoaWUuIGBGcmVuY2hgKSB0byB0aGUgY29uc3RydWN0b3JcblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgQXV0b051bWVyaWMgb2JqZWN0IHdpdGggdGhlIHByZWRlZmluZWQgb3B0aW9ucywgYW5kIHBvc3NpYmx5IHNvbWUgb3B0aW9uIG92ZXJyaWRlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBwcmVkZWZpbmVkT3B0aW9uXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbk92ZXJyaWRlXG4gICAgICogQHByaXZhdGVcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgX3VwZGF0ZVByZWRlZmluZWRPcHRpb25zKHByZWRlZmluZWRPcHRpb24sIG9wdGlvbk92ZXJyaWRlID0gbnVsbCkge1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25PdmVycmlkZSkpIHtcbiAgICAgICAgICAgIHRoaXMuX21lcmdlU2V0dGluZ3MocHJlZGVmaW5lZE9wdGlvbiwgb3B0aW9uT3ZlcnJpZGUpO1xuICAgICAgICAgICAgdGhpcy51cGRhdGUodGhpcy5zZXR0aW5ncyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aGlzLnVwZGF0ZShwcmVkZWZpbmVkT3B0aW9uKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgc2V0dGluZ3MgdG8gdXNlIHRoZSBGcmVuY2ggcHJlLWRlZmluZWQgbGFuZ3VhZ2Ugb3B0aW9ucy5cbiAgICAgKiBUaG9zZSBwcmUtZGVmaW5lZCBvcHRpb25zIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHBhc3NpbmcgYW4gb3B0aW9uIG9iamVjdCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25PdmVycmlkZVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBmcmVuY2gob3B0aW9uT3ZlcnJpZGUgPSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVByZWRlZmluZWRPcHRpb25zKEF1dG9OdW1lcmljLmdldFByZWRlZmluZWRPcHRpb25zKCkuRnJlbmNoLCBvcHRpb25PdmVycmlkZSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBzZXR0aW5ncyB0byB1c2UgdGhlIE5vcnRoIEFtZXJpY2FuIHByZS1kZWZpbmVkIGxhbmd1YWdlIG9wdGlvbnMuXG4gICAgICogVGhvc2UgcHJlLWRlZmluZWQgb3B0aW9ucyBjYW4gYmUgb3ZlcnJpZGRlbiBieSBwYXNzaW5nIGFuIG9wdGlvbiBvYmplY3QgYXMgYSBwYXJhbWV0ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uT3ZlcnJpZGVcbiAgICAgKiBAcmV0dXJucyB7QXV0b051bWVyaWN9XG4gICAgICovXG4gICAgbm9ydGhBbWVyaWNhbihvcHRpb25PdmVycmlkZSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlUHJlZGVmaW5lZE9wdGlvbnMoQXV0b051bWVyaWMuZ2V0UHJlZGVmaW5lZE9wdGlvbnMoKS5Ob3J0aEFtZXJpY2FuLCBvcHRpb25PdmVycmlkZSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBzZXR0aW5ncyB0byB1c2UgdGhlIEJyaXRpc2ggcHJlLWRlZmluZWQgbGFuZ3VhZ2Ugb3B0aW9ucy5cbiAgICAgKiBUaG9zZSBwcmUtZGVmaW5lZCBvcHRpb25zIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHBhc3NpbmcgYW4gb3B0aW9uIG9iamVjdCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25PdmVycmlkZVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBicml0aXNoKG9wdGlvbk92ZXJyaWRlID0gbnVsbCkge1xuICAgICAgICB0aGlzLl91cGRhdGVQcmVkZWZpbmVkT3B0aW9ucyhBdXRvTnVtZXJpYy5nZXRQcmVkZWZpbmVkT3B0aW9ucygpLkJyaXRpc2gsIG9wdGlvbk92ZXJyaWRlKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIHNldHRpbmdzIHRvIHVzZSB0aGUgU3dpc3MgcHJlLWRlZmluZWQgbGFuZ3VhZ2Ugb3B0aW9ucy5cbiAgICAgKiBUaG9zZSBwcmUtZGVmaW5lZCBvcHRpb25zIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHBhc3NpbmcgYW4gb3B0aW9uIG9iamVjdCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25PdmVycmlkZVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBzd2lzcyhvcHRpb25PdmVycmlkZSA9IG51bGwpIHtcbiAgICAgICAgdGhpcy5fdXBkYXRlUHJlZGVmaW5lZE9wdGlvbnMoQXV0b051bWVyaWMuZ2V0UHJlZGVmaW5lZE9wdGlvbnMoKS5Td2lzcywgb3B0aW9uT3ZlcnJpZGUpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgc2V0dGluZ3MgdG8gdXNlIHRoZSBKYXBhbmVzZSBwcmUtZGVmaW5lZCBsYW5ndWFnZSBvcHRpb25zLlxuICAgICAqIFRob3NlIHByZS1kZWZpbmVkIG9wdGlvbnMgY2FuIGJlIG92ZXJyaWRkZW4gYnkgcGFzc2luZyBhbiBvcHRpb24gb2JqZWN0IGFzIGEgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbk92ZXJyaWRlXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGphcGFuZXNlKG9wdGlvbk92ZXJyaWRlID0gbnVsbCkge1xuICAgICAgICB0aGlzLl91cGRhdGVQcmVkZWZpbmVkT3B0aW9ucyhBdXRvTnVtZXJpYy5nZXRQcmVkZWZpbmVkT3B0aW9ucygpLkphcGFuZXNlLCBvcHRpb25PdmVycmlkZSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVXBkYXRlIHRoZSBzZXR0aW5ncyB0byB1c2UgdGhlIFNwYW5pc2ggcHJlLWRlZmluZWQgbGFuZ3VhZ2Ugb3B0aW9ucy5cbiAgICAgKiBUaG9zZSBwcmUtZGVmaW5lZCBvcHRpb25zIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHBhc3NpbmcgYW4gb3B0aW9uIG9iamVjdCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25PdmVycmlkZVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBzcGFuaXNoKG9wdGlvbk92ZXJyaWRlID0gbnVsbCkge1xuICAgICAgICB0aGlzLl91cGRhdGVQcmVkZWZpbmVkT3B0aW9ucyhBdXRvTnVtZXJpYy5nZXRQcmVkZWZpbmVkT3B0aW9ucygpLlNwYW5pc2gsIG9wdGlvbk92ZXJyaWRlKTtcblxuICAgICAgICByZXR1cm4gdGhpcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIHNldHRpbmdzIHRvIHVzZSB0aGUgQ2hpbmVzZSBwcmUtZGVmaW5lZCBsYW5ndWFnZSBvcHRpb25zLlxuICAgICAqIFRob3NlIHByZS1kZWZpbmVkIG9wdGlvbnMgY2FuIGJlIG92ZXJyaWRkZW4gYnkgcGFzc2luZyBhbiBvcHRpb24gb2JqZWN0IGFzIGEgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbk92ZXJyaWRlXG4gICAgICogQHJldHVybnMge0F1dG9OdW1lcmljfVxuICAgICAqL1xuICAgIGNoaW5lc2Uob3B0aW9uT3ZlcnJpZGUgPSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVByZWRlZmluZWRPcHRpb25zKEF1dG9OdW1lcmljLmdldFByZWRlZmluZWRPcHRpb25zKCkuQ2hpbmVzZSwgb3B0aW9uT3ZlcnJpZGUpO1xuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVwZGF0ZSB0aGUgc2V0dGluZ3MgdG8gdXNlIHRoZSBCcmF6aWxpYW4gcHJlLWRlZmluZWQgbGFuZ3VhZ2Ugb3B0aW9ucy5cbiAgICAgKiBUaG9zZSBwcmUtZGVmaW5lZCBvcHRpb25zIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHBhc3NpbmcgYW4gb3B0aW9uIG9iamVjdCBhcyBhIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25PdmVycmlkZVxuICAgICAqIEByZXR1cm5zIHtBdXRvTnVtZXJpY31cbiAgICAgKi9cbiAgICBicmF6aWxpYW4ob3B0aW9uT3ZlcnJpZGUgPSBudWxsKSB7XG4gICAgICAgIHRoaXMuX3VwZGF0ZVByZWRlZmluZWRPcHRpb25zKEF1dG9OdW1lcmljLmdldFByZWRlZmluZWRPcHRpb25zKCkuQnJhemlsaWFuLCBvcHRpb25PdmVycmlkZSk7XG5cbiAgICAgICAgcmV0dXJuIHRoaXM7XG4gICAgfVxuXG5cbiAgICAvLyBJbnRlcm5hbCBwcml2YXRlIGZ1bmN0aW9uc1xuICAgIC8qKlxuICAgICAqIFJ1biBhbnkgY2FsbGJhY2tzIGZvdW5kIGluIHRoZSBzZXR0aW5ncyBvYmplY3QgaW4gb3JkZXIgdG8gc2V0IHRoZSBzZXR0aW5ncyB2YWx1ZSBiYWNrLlxuICAgICAqIEFueSBwYXJhbWV0ZXIgY2FuIGhhdmUgYSBjYWxsYmFjayBkZWZpbmVkLlxuICAgICAqIFRoZSBjYWxsYmFjayB0YWtlcyB0aGUgY3VycmVudCBBdXRvTnVtZXJpYyBlbGVtZW50IGFzIHRoZSBmaXJzdCBhcmd1bWVudCwgYW5kIHRoZSBrZXkgbmFtZSBhcyB0aGUgc2Vjb25kLlxuICAgICAqIEBleGFtcGxlIGNhbGxiYWNrKHRoaXMsICdjdXJyZW5jeVN5bWJvbCcpXG4gICAgICovXG4gICAgX3J1bkNhbGxiYWNrc0ZvdW5kSW5UaGVTZXR0aW5nc09iamVjdCgpIHsgLy9GSVhNRSB0ZXN0IHRoaXNcbiAgICAgICAgLy8gTG9vcHMgdGhyb3VnaCB0aGUgdGhpcy5zZXR0aW5ncyBvYmplY3QgKG9wdGlvbiBhcnJheSkgdG8gZmluZCB0aGUgZm9sbG93aW5nXG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHRoaXMuc2V0dGluZ3MpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMuc2V0dGluZ3Nba2V5XTtcblxuICAgICAgICAgICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdmdW5jdGlvbicpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5nc1trZXldID0gdmFsdWUodGhpcywga2V5KTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBDYWxscyB0aGUgYXR0YWNoZWQgZnVuY3Rpb24gZnJvbSB0aGUgaHRtbDUgZGF0YS4gRm9yIGluc3RhbmNlOiA8dGFnIGRhdGEtY3VycmVuY3ktc3ltYm9sPVwiZnVuY3Rpb25OYW1lXCI+PC90YWc+XG4gICAgICAgICAgICAgICAgICAgIGxldCBodG1sQXR0cmlidXRlID0gdGhpcy5kb21FbGVtZW50LmdldEF0dHJpYnV0ZShrZXkpOyAvL1RPRE8gVXNlIGBkYXRhc2V0YCBpbnN0ZWFkIG9mIGBnZXRBdHRyaWJ1dGVgIHdoZW4gd2Ugd29uJ3QgbmVlZCB0byBzdXBwb3J0IG9ic29sZXRlIGJyb3dzZXJzXG4gICAgICAgICAgICAgICAgICAgIGh0bWxBdHRyaWJ1dGUgPSBBdXRvTnVtZXJpY0hlbHBlci5jYW1lbGl6ZShodG1sQXR0cmlidXRlKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB0aGlzLnNldHRpbmdzW2h0bWxBdHRyaWJ1dGVdID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzW2tleV0gPSBodG1sQXR0cmlidXRlKHRoaXMsIGtleSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBLZWVwIHRyYWNrIGlmIHRoZSBzZXR0aW5ncyBjb25maWd1cmF0aW9uIGxlYWRzIHRvIGEgdHJhaWxpbmcgbmVnYXRpdmUgc2lnbiAob25seSB3aGVuIHRoZSByYXcgdmFsdWUgaXMgbmVnYXRpdmUpLCBzbyB3ZSBkbyBub3QgaGF2ZSB0byB0ZXN0IHRoZSBzZXR0aW5ncyB2YWx1ZXMgZXZlcnkgdGltZSB3ZSBuZWVkIHRvIGtub3cgdGhhdC5cbiAgICAgKiBgaXNUcmFpbGluZ05lZ2F0aXZlYCBpcyBzZXQgdG8gYHRydWVgIGlmIHRoZSBzZXR0aW5ncyByZXN1bHQgaW4gYSB0cmFpbGluZyBuZWdhdGl2ZSBjaGFyYWN0ZXIsIGBmYWxzZWAgb3RoZXJ3aXNlLlxuICAgICAqIE5vdGU6IFRoaXMgcmV0dXJucyBgdHJ1ZWAgZXZlbiBpZiB0aGUgcmF3IHZhbHVlIGlzIHBvc2l0aXZlLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NldFRyYWlsaW5nTmVnYXRpdmVTaWduSW5mbygpIHtcbiAgICAgICAgdGhpcy5pc1RyYWlsaW5nTmVnYXRpdmUgPSAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXggJiYgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXgpIHx8XG4gICAgICAgICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCAmJlxuICAgICAgICAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0IHx8IHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTdHJpcCBhbGwgdW53YW50ZWQgbm9uLW51bWJlciBjaGFyYWN0ZXJzLlxuICAgICAqIFRoaXMga2VlcHMgdGhlIG51bWJlcnMsIHRoZSBuZWdhdGl2ZSBzaWduIGFzIHdlbGwgYXMgdGhlIGN1c3RvbSBkZWNpbWFsIGNoYXJhY3Rlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHBhcmFtIHtib29sZWFufSBzdHJpcFplcm9zIElmIHNldCB0byBgZmFsc2VgLCB0aGVuIHRoZSBsZWFkaW5nIHplcm8ocykgYXJlIG5vdCBzdHJpcHBlZCwgb3RoZXJ3aXNlIGlmIHNldCB0byBgdHJ1ZWAsIHRoZSBgbGVhZGluZ1plcm9gIG9wdGlvbiBpcyBmb2xsb3dlZFxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNGb2N1c2VkIElmIHRoZSBlbGVtZW50IGlzIGZvY3VzZWQsIHRoZW4gdGhpcyBpcyBgdHJ1ZWBcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfCp9XG4gICAgICovXG4gICAgc3RhdGljIF9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnMocywgc2V0dGluZ3MsIHN0cmlwWmVyb3MsIGlzRm9jdXNlZCkge1xuICAgICAgICAvL1hYWCBOb3RlOyB0aGlzIGZ1bmN0aW9uIGlzIHN0YXRpYyBzaW5jZSB3ZSBuZWVkIHRvIHBhc3MgYSBgc2V0dGluZ3NgIG9iamVjdCB3aGVuIGNhbGxpbmcgdGhlIHN0YXRpYyBgQXV0b051bWVyaWMuZm9ybWF0KClgIG1ldGhvZFxuICAgICAgICAvL1RPRE8gVGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgMTAgdGltZXMgKHNpYyEpIG9uIGVhY2gga2V5IGlucHV0LCBjb3VsZG4ndCB3ZSBsb3dlciB0aGF0IG51bWJlcj8gY2YuIGlzc3VlICMzMjVcbiAgICAgICAgLy9UT0RPIFJlZmFjdG9yIHRoaXMgd2l0aCBgY29udmVydFRvTnVtZXJpY1N0cmluZygpYCBpZiBwb3NzaWJsZT9cbiAgICAgICAgcyA9IFN0cmluZyhzKTsgLy8gVHlwZWNhc3QgdG8gdG8gYSBzdHJpbmcsIGluIGNhc2UgdGhhdCB0aGUgaW5pdGlhbFZhbHVlIGlzIGEgbnVtYmVyXG5cbiAgICAgICAgaWYgKHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sICE9PSAnJykge1xuICAgICAgICAgICAgLy8gUmVtb3ZlIGN1cnJlbmN5IHNpZ25cbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2Uoc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wsICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzZXR0aW5ncy5zdWZmaXhUZXh0KSB7XG4gICAgICAgICAgICAvLyBSZW1vdmUgc3VmZml4XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKHNldHRpbmdzLnN1ZmZpeFRleHQsICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vVE9ETyBSZW1vdmUgdGhlIHBvc2l0aXZlIHNpZ24gdG9vP1xuXG4gICAgICAgIC8vIEZpcnN0IHJlcGxhY2UgYW55dGhpbmcgYmVmb3JlIGRpZ2l0c1xuICAgICAgICBzID0gcy5yZXBsYWNlKHNldHRpbmdzLnNraXBGaXJzdEF1dG9TdHJpcCwgJyQxJDInKTtcblxuICAgICAgICAvLyBUaGVuIHJlcGxhY2UgYW55dGhpbmcgYWZ0ZXIgZGlnaXRzXG4gICAgICAgIHMgPSBzLnJlcGxhY2Uoc2V0dGluZ3Muc2tpcExhc3RBdXRvU3RyaXAsICckMScpO1xuXG4gICAgICAgIC8vIFRoZW4gcmVtb3ZlIGFueSB1bmludGVyZXN0aW5nIGNoYXJhY3RlcnNcbiAgICAgICAgcyA9IHMucmVwbGFjZShzZXR0aW5ncy5hbGxvd2VkQXV0b1N0cmlwLCAnJyk7XG4gICAgICAgIGlmIChzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUpIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2Uoc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlLCBzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEdldCBvbmx5IG51bWJlciBzdHJpbmdcbiAgICAgICAgY29uc3QgbSA9IHMubWF0Y2goc2V0dGluZ3MubnVtUmVnQXV0b1N0cmlwKTtcbiAgICAgICAgcyA9IG0gPyBbbVsxXSwgbVsyXSwgbVszXV0uam9pbignJykgOiAnJztcblxuICAgICAgICBpZiAoc2V0dGluZ3MubGVhZGluZ1plcm8gPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8uYWxsb3cgfHwgc2V0dGluZ3MubGVhZGluZ1plcm8gPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8ua2VlcCkge1xuICAgICAgICAgICAgbGV0IG5lZ2F0aXZlU2lnbiA9ICcnO1xuICAgICAgICAgICAgY29uc3QgW2ludGVnZXJQYXJ0LCBkZWNpbWFsUGFydF0gPSBzLnNwbGl0KHNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpO1xuICAgICAgICAgICAgbGV0IG1vZGlmaWVkSW50ZWdlclBhcnQgPSBpbnRlZ2VyUGFydDtcbiAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhtb2RpZmllZEludGVnZXJQYXJ0LCBzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICAgICAgbmVnYXRpdmVTaWduID0gc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyO1xuICAgICAgICAgICAgICAgIG1vZGlmaWVkSW50ZWdlclBhcnQgPSBtb2RpZmllZEludGVnZXJQYXJ0LnJlcGxhY2Uoc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLCAnJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0cmlwIGxlYWRpbmcgemVybyBvbiBwb3NpdGl2ZSB2YWx1ZSBpZiBuZWVkXG4gICAgICAgICAgICBpZiAobmVnYXRpdmVTaWduID09PSAnJyAmJiBtb2RpZmllZEludGVnZXJQYXJ0Lmxlbmd0aCA+IHNldHRpbmdzLm1JbnRQb3MgJiYgbW9kaWZpZWRJbnRlZ2VyUGFydC5jaGFyQXQoMCkgPT09ICcwJykge1xuICAgICAgICAgICAgICAgIG1vZGlmaWVkSW50ZWdlclBhcnQgPSBtb2RpZmllZEludGVnZXJQYXJ0LnNsaWNlKDEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBTdHJpcCBsZWFkaW5nIHplcm8gb24gbmVnYXRpdmUgdmFsdWUgaWYgbmVlZFxuICAgICAgICAgICAgaWYgKG5lZ2F0aXZlU2lnbiAhPT0gJycgJiYgbW9kaWZpZWRJbnRlZ2VyUGFydC5sZW5ndGggPiBzZXR0aW5ncy5tSW50TmVnICYmIG1vZGlmaWVkSW50ZWdlclBhcnQuY2hhckF0KDApID09PSAnMCcpIHtcbiAgICAgICAgICAgICAgICBtb2RpZmllZEludGVnZXJQYXJ0ID0gbW9kaWZpZWRJbnRlZ2VyUGFydC5zbGljZSgxKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcyA9IGAke25lZ2F0aXZlU2lnbn0ke21vZGlmaWVkSW50ZWdlclBhcnR9JHtBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZChkZWNpbWFsUGFydCk/Jyc6c2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciArIGRlY2ltYWxQYXJ0fWA7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKHN0cmlwWmVyb3MgJiYgc2V0dGluZ3MubGVhZGluZ1plcm8gPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8uZGVueSkgfHxcbiAgICAgICAgICAgICghaXNGb2N1c2VkICYmIHNldHRpbmdzLmxlYWRpbmdaZXJvID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmFsbG93KSkge1xuICAgICAgICAgICAgcyA9IHMucmVwbGFjZShzZXR0aW5ncy5zdHJpcFJlZywgJyQxJDInKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgb3IgcmVtb3ZlcyBicmFja2V0cyBvbiBuZWdhdGl2ZSB2YWx1ZXMsIGRlcGVuZGluZyBvbiB0aGUgZm9jdXMgc3RhdGUsIHdoaWNoIGlzIHBhc3NlZCBhcyBgaXNGb2N1c2VkYC5cbiAgICAgKiBUaGUgZm9jdXMgc3RhdGUgaXMgJ3N0b3JlZCcgaW4gdGhhdCBvYmplY3QgcHJvcGVydHkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzRm9jdXNlZFxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBfdG9nZ2xlTmVnYXRpdmVCcmFja2V0KHZhbHVlLCBzZXR0aW5ncywgaXNGb2N1c2VkKSB7XG4gICAgICAgIC8vWFhYIE5vdGU7IHRoaXMgZnVuY3Rpb24gaXMgc3RhdGljIHNpbmNlIHdlIG5lZWQgdG8gcGFzcyBhIGBzZXR0aW5nc2Agb2JqZWN0IHdoZW4gY2FsbGluZyB0aGUgc3RhdGljIGBBdXRvTnVtZXJpYy5mb3JtYXQoKWAgbWV0aG9kXG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIGlmIChpc0ZvY3VzZWQpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuX3JlbW92ZUJyYWNrZXRzKHZhbHVlLCBzZXR0aW5ncyk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSB0aGlzLl9hZGRCcmFja2V0cyh2YWx1ZSwgc2V0dGluZ3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBZGQgdGhlIGJyYWNrZXQgdHlwZXMgc3BlY2lmaWVkIGluIHRoZSBgc2V0dGluZ3NgIG9iamVjdCwgdG8gdGhlIGdpdmVuIHN0cmluZyBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfYWRkQnJhY2tldHModmFsdWUsIHNldHRpbmdzKSB7XG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHNldHRpbmdzLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyKSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gYCR7c2V0dGluZ3MuZmlyc3RCcmFja2V0fSR7dmFsdWUucmVwbGFjZShzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIsICcnKX0ke3NldHRpbmdzLmxhc3RCcmFja2V0fWA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlIHRoZSBicmFja2V0IHR5cGVzIHNwZWNpZmllZCBpbiB0aGUgYHNldHRpbmdzYCBvYmplY3QsIGZyb20gdGhlIGdpdmVuIHN0cmluZyBgdmFsdWVgLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHBhcmFtIHtib29sZWFufSByZWFycmFuZ2VTaWduc0FuZFZhbHVlT3JkZXIgSWYgc2V0IHRvIGB0cnVlYCwgdGhlbiBvbmx5IHRoZSBicmFja2V0cyBhcmUgcmVtb3ZlIGFuZCBhIG5lZ2F0aXZlIHNpZ24gaXMgYWRkZWQsIHdpdGhvdXQgcmVvcmRlcmluZyB0aGUgbmVnYXRpdmUgc2lnbiwgY3VycmVuY3kgc3ltYm9sIGFuZCB2YWx1ZSBhY2NvcmRpbmcgdG8gdGhlIHNldHRpbmdzLlxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3JlbW92ZUJyYWNrZXRzKHZhbHVlLCBzZXR0aW5ncywgcmVhcnJhbmdlU2lnbnNBbmRWYWx1ZU9yZGVyID0gdHJ1ZSkge1xuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChzZXR0aW5ncy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1cikgJiYgdmFsdWUuY2hhckF0KDApID09PSBzZXR0aW5ncy5maXJzdEJyYWNrZXQpIHtcbiAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgYnJhY2tldHMgaWYgdGhleSBhcmUgcHJlc2VudFxuICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUucmVwbGFjZShzZXR0aW5ncy5maXJzdEJyYWNrZXQsICcnKTtcbiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKHNldHRpbmdzLmxhc3RCcmFja2V0LCAnJyk7XG5cbiAgICAgICAgICAgIC8vIEFkZCBiYWNrIHRoZSBuZWdhdGl2ZSBzaWduIGF0IHRoZSByaWdodCBwbGFjZVxuICAgICAgICAgICAgaWYgKHJlYXJyYW5nZVNpZ25zQW5kVmFsdWVPcmRlcikge1xuICAgICAgICAgICAgICAgIC8vIEZpcnN0IHdlIG5lZWQgdG8gcmVtb3ZlIHRoZSBjdXJyZW5jeSBzeW1ib2wgZnJvbSB0aGUgdmFsdWUsIHNpbmNlIHdlIHdhbnQgdG8gYmUgYWJsZSB0byBhZGQgYmFjayB0aGUgbmVnYXRpdmUgc2lnbiBhdCB0aGUgcmlnaHQgcGxhY2UgKGluY2x1ZGluZyBiZXR3ZWVuIHRoZSB2YWx1ZSBhbmQgdGhlIGN1cnJlbmN5IHNpZ24pXG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gcmVzdWx0LnJlcGxhY2Uoc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wsICcnKTtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLl9tZXJnZUN1cnJlbmN5U2lnbk5lZ2F0aXZlUG9zaXRpdmVTaWduQW5kVmFsdWUocmVzdWx0LCBzZXR0aW5ncywgdHJ1ZSwgZmFsc2UpOyAvL1RPRE8gVGhpcyBhc3N1bWUgdGhlIHZhbHVlIGlzIG5lZ2F0aXZlIGFuZCBub24tZW1wdHkuIElzIHRoaXMgYWx3YXlzIHRoZSBjYXNlP1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBIZXJlIHdlIG9ubHkgd2FudCB0byBhZGQgdGhlIG5lZ2F0aXZlIHNpZ24gc2luY2Ugd2UgcmVtb3ZlZCB0aGUgYnJhY2tldHMsIHdpdGhvdXQgcmVvcmRlcmluZ1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9ICctJyArIHJlc3VsdDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBbmFseXplIHRoZSBgbmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXJgIG9wdGlvbnMgYW5kIGtlZXAgdHJhY2sgb2YgdGhlIGZpcnN0IGFuZCBsYXN0IGJyYWNrZXQgY2hhcmFjdGVycyB0byB1c2UuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2V0QnJhY2tldHMoKSB7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIpKSB7XG4gICAgICAgICAgICBbdGhpcy5zZXR0aW5ncy5maXJzdEJyYWNrZXQsIHRoaXMuc2V0dGluZ3MubGFzdEJyYWNrZXRdID0gdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ci5zcGxpdCgnLCcpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5maXJzdEJyYWNrZXQgPSAnJztcbiAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MubGFzdEJyYWNrZXQgPSAnJztcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhIG51bWJlciBhcyBhIG51bWVyaWMgc3RyaW5nIHRoYXQgY2FuIGJlIHR5cGVjYXN0IHRvIGEgTnVtYmVyIHRoYXQgSmF2YXNjcmlwdCB3aWxsIHVuZGVyc3RhbmQuXG4gICAgICpcbiAgICAgKiBUaGlzIGZ1bmN0aW9uIHJldHVybiB0aGUgZ2l2ZW4gc3RyaW5nIGJ5IHN0cmlwcGluZyB0aGUgY3VycmVuY3kgc2lnbiAoY3VycmVuY3lTeW1ib2wpLCB0aGUgZ3JvdXBpbmcgc2VwYXJhdG9ycyAoZGlnaXRhbEdyb3VwU3BhY2luZykgYW5kIGJ5IHJlcGxhY2luZyB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgKGRlY2ltYWxDaGFyYWN0ZXIpIGJ5IGEgZG90LlxuICAgICAqIExhc3RseSwgaXQgYWxzbyBwdXQgdGhlIG5lZ2F0aXZlIHNpZ24gYmFjayB0byBpdHMgbm9ybWFsIHBvc2l0aW9uIGlmIG5lZWRlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMge3N0cmluZ3x2b2lkfFhNTHwqfVxuICAgICAqL1xuICAgIHN0YXRpYyBfY29udmVydFRvTnVtZXJpY1N0cmluZyhzLCBzZXR0aW5ncykge1xuICAgICAgICAvLyBSZW1vdmUgdGhlIGN1cnJlbmN5IHN5bWJvbFxuICAgICAgICBzID0gcy5yZXBsYWNlKHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLCAnJyk7XG5cbiAgICAgICAgLy8gUmVtb3ZlIHRoZSBncm91cGluZyBzZXBhcmF0b3JzICh0aG91c2FuZHMgc2VwYXJhdG9ycyB1c3VhbGx5KVxuICAgICAgICBzID0gcy5yZXBsYWNlKG5ldyBSZWdFeHAoYFske3NldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3J9XWAsICdnJyksICcnKTtcblxuICAgICAgICAvLyBSZXBsYWNlIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBieSBhIGRvdFxuICAgICAgICBpZiAoc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciAhPT0gJy4nKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKHNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIsICcuJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBSZW1vdmUgdGhlIHN1ZmZpeFRleHRcbiAgICAgICAgaWYgKHNldHRpbmdzLnN1ZmZpeFRleHQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMuc3VmZml4VGV4dC5ub25lKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKHNldHRpbmdzLnN1ZmZpeFRleHQsICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1vdmUgdGhlIHRyYWlsaW5nIG5lZ2F0aXZlIHNpZ24gdG8gdGhlIHJpZ2h0IHBvc2l0aW9uLCBpZiBhbnlcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUocykgJiYgcy5sYXN0SW5kZXhPZignLScpID09PSBzLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2UoJy0nLCAnJyk7XG4gICAgICAgICAgICBzID0gJy0nICsgcztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIENvbnZlcnQgYXJhYmljIG51bWJlcnMgdG8gbGF0aW4gb25lcywgaWYgYW55XG4gICAgICAgIGNvbnN0IGNvbnZlcnRUb051bWJlciA9IHNldHRpbmdzLmxlYWRpbmdaZXJvICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmtlZXA7XG4gICAgICAgIGNvbnN0IHRlbXAgPSBBdXRvTnVtZXJpY0hlbHBlci5hcmFiaWNUb0xhdGluTnVtYmVycyhzLCBjb252ZXJ0VG9OdW1iZXIsIGZhbHNlLCBmYWxzZSk7XG4gICAgICAgIGlmICghaXNOYU4odGVtcCkpIHtcbiAgICAgICAgICAgIHMgPSB0ZW1wLnRvU3RyaW5nKCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0cyB0aGUgSVNPIG51bWVyaWMgc3RyaW5nIHRvIHRoZSBsb2NhbGUgZGVjaW1hbCBhbmQgbWludXMgc2lnbiBwbGFjZW1lbnQuXG4gICAgICogU2VlIHRoZSBcIm91dHB1dEZvcm1hdFwiIG9wdGlvbiBkZWZpbml0aW9uIGZvciBtb3JlIGRldGFpbHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudWxsfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IGxvY2FsZVxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBfdG9Mb2NhbGUodmFsdWUsIGxvY2FsZSkge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGxvY2FsZSkgfHwgbG9jYWxlID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5zdHJpbmcpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIHN3aXRjaCAobG9jYWxlKSB7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0Lm51bWJlcjpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBOdW1iZXIodmFsdWUpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5kb3ROZWdhdGl2ZTpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKHZhbHVlKSA/IHZhbHVlLnJlcGxhY2UoJy0nLCAnJykgKyAnLScgOiB2YWx1ZTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQuY29tbWE6XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0Lm5lZ2F0aXZlQ29tbWE6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUucmVwbGFjZSgnLicsICcsJyk7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0LmNvbW1hTmVnYXRpdmU6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUucmVwbGFjZSgnLicsICcsJyk7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZShyZXN1bHQpID8gcmVzdWx0LnJlcGxhY2UoJy0nLCAnJykgKyAnLScgOiByZXN1bHQ7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAvLyBUaGUgZGVmYXVsdCBjYXNlXG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3V0cHV0Rm9ybWF0LmRvdDpcbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vdXRwdXRGb3JtYXQubmVnYXRpdmVEb3Q6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gb3V0cHV0Rm9ybWF0IFske2xvY2FsZX1dIG9wdGlvbiBpcyBub3QgcmVjb2duaXplZC5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTW9kaWZ5IHRoZSBuZWdhdGl2ZSBzaWduIGFuZCB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgb2YgdGhlIGdpdmVuIHN0cmluZyB2YWx1ZSB0byBhbiBoeXBoZW4gKC0pIGFuZCBhIGRvdCAoLikgaW4gb3JkZXIgdG8gbWFrZSB0aGF0IHZhbHVlICd0eXBlY2FzdGFibGUnIHRvIGEgcmVhbCBudW1iZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc1xuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgX21vZGlmeU5lZ2F0aXZlU2lnbkFuZERlY2ltYWxDaGFyYWN0ZXJGb3JSYXdWYWx1ZShzKSB7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIgIT09ICcuJykge1xuICAgICAgICAgICAgcyA9IHMucmVwbGFjZSh0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIsICcuJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgIT09ICctJyAmJiB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciAhPT0gJycpIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2UodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIsICctJyk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXMubWF0Y2goL1xcZC8pKSB7XG4gICAgICAgICAgICAvLyBUaGUgZGVmYXVsdCB2YWx1ZSByZXR1cm5lZCBieSBgZ2V0YCBpcyBub3QgZm9ybWF0dGVkIHdpdGggZGVjaW1hbHNcbiAgICAgICAgICAgIHMgKz0gJzAnO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHM7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTW9kaWZ5IHRoZSBuZWdhdGl2ZSBzaWduIGFuZCB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgdG8gdXNlIHRob3NlIGRlZmluZWQgaW4gdGhlIHNldHRpbmdzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBfbW9kaWZ5TmVnYXRpdmVTaWduQW5kRGVjaW1hbENoYXJhY3RlckZvckZvcm1hdHRlZFZhbHVlKHMsIHNldHRpbmdzKSB7XG4gICAgICAgIC8vWFhYIE5vdGU7IHRoaXMgZnVuY3Rpb24gaXMgc3RhdGljIHNpbmNlIHdlIG5lZWQgdG8gcGFzcyBhIGBzZXR0aW5nc2Agb2JqZWN0IHdoZW4gY2FsbGluZyB0aGUgc3RhdGljIGBBdXRvTnVtZXJpYy5mb3JtYXQoKWAgbWV0aG9kXG4gICAgICAgIGlmIChzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgIT09ICctJyAmJiBzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgIT09ICcnKSB7XG4gICAgICAgICAgICBzID0gcy5yZXBsYWNlKCctJywgc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyICE9PSAnLicpIHtcbiAgICAgICAgICAgIHMgPSBzLnJlcGxhY2UoJy4nLCBzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGdpdmVuIHZhbHVlIGlzIGVtcHR5IG9yIGlzIGVxdWFsIHRvIHRoZSBuZWdhdGl2ZSBzaWduIGNoYXJhY3RlciBkZWZpbmVkIGluIHRoZSBnaXZlbiBzZXR0aW5ncy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9pc0VsZW1lbnRWYWx1ZUVtcHR5T3JPbmx5VGhlTmVnYXRpdmVTaWduKHZhbHVlLCBzZXR0aW5ncykge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09ICcnIHx8IHZhbHVlID09PSBzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXI7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSB2YWx1ZSB3aXRoIHRoZSBjdXJyZW5jeSBzeW1ib2wgYW5kIHRoZSBzdWZmaXggdGV4dCBvcmRlcmVkIGFjY29yZGluZyB0byB0aGUgZ2l2ZW4gc2V0dGluZ3MuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNpZ25PbkVtcHR5XG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX29yZGVyVmFsdWVDdXJyZW5jeVN5bWJvbEFuZFN1ZmZpeFRleHQodmFsdWUsIHNldHRpbmdzLCBzaWduT25FbXB0eSkge1xuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5hbHdheXMgfHwgc2lnbk9uRW1wdHkpIHtcbiAgICAgICAgICAgIGlmIChzZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0KSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUgKyBzZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCArIHNldHRpbmdzLnN1ZmZpeFRleHQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sICsgdmFsdWUgKyBzZXR0aW5ncy5zdWZmaXhUZXh0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1vZGlmeSB0aGUgaW5wdXQgdmFsdWUgYnkgYWRkaW5nIHRoZSBncm91cCBzZXBhcmF0b3JzLCBhcyBkZWZpbmVkIGluIHRoZSBzZXR0aW5ncy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBpbnB1dFZhbHVlIFRoZSBmb3JtYXR0ZWQgdmFsdWUgKGllLiB3aXRoIHRoZSBgZGVjaW1hbENoYXJhY3RlcmAgZGVmaW5lZCBpbiB0aGUgc2V0dGluZ3MsIG5vdCB0aGUgcmF3IHZhbHVlKVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNGb2N1c2VkXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfG51bGx9IGN1cnJlbnRSYXdWYWx1ZSBUaGUgb2JqZWN0IGN1cnJlbnQgcmF3IHZhbHVlIChgdGhpcy5yYXdWYWx1ZWApXG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfG51bGx9IGZvcmNlZFJhd1ZhbHVlIElmIHRoaXMgaXMgc2V0LCB0aGVuIHRoaXMgcmF3VmFsdWUgaXMgdXNlZCBpbnN0ZWFkIG9mIHRoZSBvbmUgcGFzc2VkIHRocm91Z2ggdGhlIGBzZXR0aW5nc2Agb2JqZWN0LiBUaGlzIGlzIHVzZWZ1bCBpcyBzb21lIHZlcnkgc3BlY2lmaWMgY2FzZXMgd2hlcmUgd2UgbmVlZCB0byBzZXQgdGhlIHJhdyB2YWx1ZSAqYWZ0ZXIqIHNldHRpbmdzIHRoZSBmb3JtYXR0ZWQgdmFsdWUsIHVzaW5nIHRoZSBgX2FkZEdyb3VwU2VwYXJhdG9ycygpYCBtZXRob2QuXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIF9hZGRHcm91cFNlcGFyYXRvcnMoaW5wdXRWYWx1ZSwgc2V0dGluZ3MsIGlzRm9jdXNlZCwgY3VycmVudFJhd1ZhbHVlLCBmb3JjZWRSYXdWYWx1ZSA9IG51bGwpIHtcbiAgICAgICAgLy9UT0RPIFRlc3QgaWYgYGlucHV0VmFsdWVgID09PSAnJywgYW5kIHJldHVybiAnJyBkaXJlY3RseSBpZiB0aGF0J3MgdGhlIGNhc2UsXG4gICAgICAgIC8vWFhYIE5vdGU7IHRoaXMgZnVuY3Rpb24gaXMgc3RhdGljIHNpbmNlIHdlIG5lZWQgdG8gcGFzcyBhIGBzZXR0aW5nc2Agb2JqZWN0IHdoZW4gY2FsbGluZyB0aGUgc3RhdGljIGBBdXRvTnVtZXJpYy5mb3JtYXQoKWAgbWV0aG9kXG4gICAgICAgIGNvbnN0IGlzVmFsdWVOZWdhdGl2ZSA9IEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUoaW5wdXRWYWx1ZSkgfHwgQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZVdpdGhCcmFja2V0cyhpbnB1dFZhbHVlLCBzZXR0aW5ncy5maXJzdEJyYWNrZXQsIHNldHRpbmdzLmxhc3RCcmFja2V0KTsgLy8gVGVzdCBpZiB0aGUgdmFsdWUgaXMgbmVnYXRpdmUgYmVmb3JlIHJlbW92aW5nIHRoZSBuZWdhdGl2ZSBzaWduXG5cbiAgICAgICAgaW5wdXRWYWx1ZSA9IHRoaXMuX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVycyhpbnB1dFZhbHVlLCBzZXR0aW5ncywgZmFsc2UsIGlzRm9jdXNlZCk7XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzRWxlbWVudFZhbHVlRW1wdHlPck9ubHlUaGVOZWdhdGl2ZVNpZ24oaW5wdXRWYWx1ZSwgc2V0dGluZ3MpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5fb3JkZXJWYWx1ZUN1cnJlbmN5U3ltYm9sQW5kU3VmZml4VGV4dChpbnB1dFZhbHVlLCBzZXR0aW5ncywgdHJ1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpc1plcm9Pckhhc05vVmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5pc1plcm9Pckhhc05vVmFsdWUoaW5wdXRWYWx1ZSk7XG5cbiAgICAgICAgLy8gVGVtcG9yYXJpbHkgcmVtb3ZlIHRoZSBuZWdhdGl2ZSBzaWduIGlmIHByZXNlbnRcbiAgICAgICAgaWYgKGlzVmFsdWVOZWdhdGl2ZSkge1xuICAgICAgICAgICAgaW5wdXRWYWx1ZSA9IGlucHV0VmFsdWUucmVwbGFjZSgnLScsICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHNldHRpbmdzLmRpZ2l0YWxHcm91cFNwYWNpbmcgPSBzZXR0aW5ncy5kaWdpdGFsR3JvdXBTcGFjaW5nLnRvU3RyaW5nKCk7XG4gICAgICAgIGxldCBkaWdpdGFsR3JvdXA7XG4gICAgICAgIHN3aXRjaCAoc2V0dGluZ3MuZGlnaXRhbEdyb3VwU3BhY2luZykge1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcudHdvOlxuICAgICAgICAgICAgICAgIGRpZ2l0YWxHcm91cCA9IC8oXFxkKSgoXFxkKShcXGR7Mn0/KSspJC87XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRhbEdyb3VwU3BhY2luZy50d29TY2FsZWQ6XG4gICAgICAgICAgICAgICAgZGlnaXRhbEdyb3VwID0gLyhcXGQpKCg/OlxcZHsyfSl7MCwyfVxcZHszfSg/Oig/OlxcZHsyfSl7Mn1cXGR7M30pKj8pJC87XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRhbEdyb3VwU3BhY2luZy5mb3VyOlxuICAgICAgICAgICAgICAgIGRpZ2l0YWxHcm91cCA9IC8oXFxkKSgoXFxkezR9PykrKSQvO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcudGhyZWU6XG4gICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICBkaWdpdGFsR3JvdXAgPSAvKFxcZCkoKFxcZHszfT8pKykkLztcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNwbGl0cyB0aGUgc3RyaW5nIGF0IHRoZSBkZWNpbWFsIHN0cmluZ1xuICAgICAgICBsZXQgW2ludGVnZXJQYXJ0LCBkZWNpbWFsUGFydF0gPSBpbnB1dFZhbHVlLnNwbGl0KHNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpO1xuICAgICAgICBpZiAoc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlICYmIEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKGRlY2ltYWxQYXJ0KSkge1xuICAgICAgICAgICAgW2ludGVnZXJQYXJ0LCBkZWNpbWFsUGFydF0gPSBpbnB1dFZhbHVlLnNwbGl0KHNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2V0dGluZ3MuZGlnaXRHcm91cFNlcGFyYXRvciAhPT0gJycpIHtcbiAgICAgICAgICAgIC8vIFJlLWluc2VydHMgdGhlIHRob3VzYW5kIHNlcGFyYXRvciB2aWEgYSByZWd1bGFyIGV4cHJlc3Npb25cbiAgICAgICAgICAgIHdoaWxlIChkaWdpdGFsR3JvdXAudGVzdChpbnRlZ2VyUGFydCkpIHtcbiAgICAgICAgICAgICAgICBpbnRlZ2VyUGFydCA9IGludGVnZXJQYXJ0LnJlcGxhY2UoZGlnaXRhbEdyb3VwLCBgJDEke3NldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3J9JDJgKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEZpbmQgb3V0IGhvdyBtYW55IGRlY2ltYWwgcGxhY2VzIHNob3VsZCBiZSBrZXB0LCBkZXBlbmRpbmcgb24gdGhlIG9iamVjdCBzdGF0ZSAoaXNGb2N1c2VkKVxuICAgICAgICBsZXQgZGVjaW1hbFBsYWNlc1RvUm91bmRUbztcbiAgICAgICAgaWYgKGlzRm9jdXNlZCkge1xuICAgICAgICAgICAgZGVjaW1hbFBsYWNlc1RvUm91bmRUbyA9IHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXM7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvID0gc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8gIT09IDAgJiYgIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKGRlY2ltYWxQYXJ0KSkge1xuICAgICAgICAgICAgaWYgKGRlY2ltYWxQYXJ0Lmxlbmd0aCA+IGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8pIHtcbiAgICAgICAgICAgICAgICAvLyBUcmltIHRoZSBleGNlc3NpdmUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzXG4gICAgICAgICAgICAgICAgZGVjaW1hbFBhcnQgPSBkZWNpbWFsUGFydC5zdWJzdHJpbmcoMCwgZGVjaW1hbFBsYWNlc1RvUm91bmRUbyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEpvaW5zIHRoZSB3aG9sZSBudW1iZXIgd2l0aCB0aGUgZGVjaW1hbCB2YWx1ZVxuICAgICAgICAgICAgaW5wdXRWYWx1ZSA9IGAke2ludGVnZXJQYXJ0fSR7c2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcn0ke2RlY2ltYWxQYXJ0fWA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBPdGhlcndpc2UgaWYgaXQncyBhbiBpbnRlZ2VyXG4gICAgICAgICAgICBpbnB1dFZhbHVlID0gaW50ZWdlclBhcnQ7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBBZGQgYmFjayB0aGUgbmVnYXRpdmUvcG9zaXRpdmUgc2lnbiBhbmQgdGhlIGN1cnJlbmN5IHN5bWJvbCwgYXQgdGhlIHJpZ2h0IHBvc2l0aW9uc1xuICAgICAgICBpbnB1dFZhbHVlID0gQXV0b051bWVyaWMuX21lcmdlQ3VycmVuY3lTaWduTmVnYXRpdmVQb3NpdGl2ZVNpZ25BbmRWYWx1ZShpbnB1dFZhbHVlLCBzZXR0aW5ncywgaXNWYWx1ZU5lZ2F0aXZlLCBpc1plcm9Pckhhc05vVmFsdWUpOyAvL1RPRE8gdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgYWdhaW4gaW4gYF90b2dnbGVOZWdhdGl2ZUJyYWNrZXRgIGlmIHRoZSBicmFja2V0cyBhcmUgcmVtb3ZlZDsgbGV0J3MgRFJZIHRoaXNcblxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGZvcmNlZFJhd1ZhbHVlKSkge1xuICAgICAgICAgICAgLy8gSWYgdGhlIHJhdyB2YWx1ZSBpcyBub3QgZm9yY2VkLCB1c2UgdGhlIGRlZmF1bHQgb25lIGZyb20gdGhlIHNldHRpbmdzIG9iamVjdFxuICAgICAgICAgICAgZm9yY2VkUmF3VmFsdWUgPSBjdXJyZW50UmF3VmFsdWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUb2dnbGUgdGhlIG5lZ2F0aXZlIHNpZ24gYW5kIGJyYWNrZXRzXG4gICAgICAgIGlmIChzZXR0aW5ncy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciAhPT0gbnVsbCAmJiAoZm9yY2VkUmF3VmFsdWUgPCAwIHx8IEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmVTdHJpY3QoaW5wdXRWYWx1ZSkpKSB7XG4gICAgICAgICAgICBpbnB1dFZhbHVlID0gdGhpcy5fdG9nZ2xlTmVnYXRpdmVCcmFja2V0KGlucHV0VmFsdWUsIHNldHRpbmdzLCBpc0ZvY3VzZWQpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKHNldHRpbmdzLnN1ZmZpeFRleHQpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGAke2lucHV0VmFsdWV9JHtzZXR0aW5ncy5zdWZmaXhUZXh0fWA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgPSBpbnB1dFZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYSBzZW1pLWZvcm1hdHRlZCBzdHJpbmcgd2hlcmUgdGhlIGlucHV0IHZhbHVlLCB0aGUgbmVnYXRpdmUgb3IgcG9zaXRpdmUgc2lnbiwgYW5kIHRoZSBjdXJyZW5jeSBzeW1ib2wgYXJlIHN0aXRjaGVkIHRvZ2V0aGVyIGF0IHRoZSByaWdodCBwb3NpdGlvbnMsIHVzaW5nIHRoZSBvcHRpb25zIHNldCBpbiB0aGUgYHNldHRpbmdzYCBvYmplY3QuXG4gICAgICogTm90ZSA6IHRoZSBgaW5wdXRWYWx1ZWAgaXMgdXN1YWxseSBub3QgYSBudW1lcmljIHN0cmluZyBzaW5jZSB0aGUgZ3JvdXBpbmcgc3ltYm9scyBhcmUgYWxyZWFkeSBhZGRlZCB0byBpdCBhdCB0aGlzIHBvaW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGlucHV0VmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzVmFsdWVOZWdhdGl2ZVxuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gaXNaZXJvT3JIYXNOb1ZhbHVlXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICogQHRocm93c1xuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9tZXJnZUN1cnJlbmN5U2lnbk5lZ2F0aXZlUG9zaXRpdmVTaWduQW5kVmFsdWUoaW5wdXRWYWx1ZSwgc2V0dGluZ3MsIGlzVmFsdWVOZWdhdGl2ZSwgaXNaZXJvT3JIYXNOb1ZhbHVlKSB7XG4gICAgICAgIGxldCBzaWduVG9Vc2UgPSAnJztcbiAgICAgICAgaWYgKGlzVmFsdWVOZWdhdGl2ZSkge1xuICAgICAgICAgICAgc2lnblRvVXNlID0gc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyO1xuICAgICAgICB9IGVsc2UgaWYgKHNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24gJiYgIWlzWmVyb09ySGFzTm9WYWx1ZSkge1xuICAgICAgICAgICAgc2lnblRvVXNlID0gc2V0dGluZ3MucG9zaXRpdmVTaWduQ2hhcmFjdGVyO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCkge1xuICAgICAgICAgICAgaWYgKHNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Lm5vbmUgJiZcbiAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24gJiYgIWlzWmVyb09ySGFzTm9WYWx1ZSkpKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChzZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGAke3NpZ25Ub1VzZX0ke3NldHRpbmdzLmN1cnJlbmN5U3ltYm9sfSR7aW5wdXRWYWx1ZX1gO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGAke3NldHRpbmdzLmN1cnJlbmN5U3ltYm9sfSR7c2lnblRvVXNlfSR7aW5wdXRWYWx1ZX1gO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXg6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBgJHtzZXR0aW5ncy5jdXJyZW5jeVN5bWJvbH0ke2lucHV0VmFsdWV9JHtzaWduVG9Vc2V9YDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgKyBpbnB1dFZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCkge1xuICAgICAgICAgICAgaWYgKHNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Lm5vbmUgJiZcbiAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24gJiYgIWlzWmVyb09ySGFzTm9WYWx1ZSkpKSB7XG4gICAgICAgICAgICAgICAgc3dpdGNoIChzZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4OlxuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBgJHtpbnB1dFZhbHVlfSR7c2V0dGluZ3MuY3VycmVuY3lTeW1ib2x9JHtzaWduVG9Vc2V9YDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGAke2lucHV0VmFsdWV9JHtzaWduVG9Vc2V9JHtzZXR0aW5ncy5jdXJyZW5jeVN5bWJvbH1gO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg6XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBgJHtzaWduVG9Vc2V9JHtpbnB1dFZhbHVlfSR7c2V0dGluZ3MuY3VycmVuY3lTeW1ib2x9YDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gaW5wdXRWYWx1ZSArIHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxjdWxhdGUgd2hlcmUgdG8gcHV0IHRoZSBjYXJldCBwb3NpdGlvbiBvbiBmb2N1cyBpZiB0aGUgZWxlbWVudCBjb250ZW50IGlzIG5vdCBzZWxlY3RlZC5cbiAgICAgKiBUaGlzIGNhbGN1bGF0aW9uIGlzIGFmZmVjdGVkIGJ5IHRoZSBgY2FyZXRQb3NpdGlvbk9uRm9jdXNgIG9wdGlvbiB3aGljaCBjYW4gYmUgZWl0aGVyIGBudWxsYCwgYCdzdGFydCdgLCBgJ2VuZCdgLCBgJ2RlY2ltYWxMZWZ0J2Agb3IgJ2RlY2ltYWxSaWdodCdgLCBhbmQgd2lsbCBkZWNpZGUgd2hlcmUgdG8gcHV0IHRoZSBjYXJldCAob24gdGhlIGxlZnQgb3IgcmlnaHQgb2YgdGhlIHZhbHVlIG9yIHRoZSBkZWNpbWFsIGNoYXJhY3RlciwgcmVzcGVjdGl2ZWx5KSA6XG4gICAgICogLSBgbnVsbGAgOiB0aGUgY2FyZXQgcG9zaXRpb24gaXMgbm90IGZvcmNlZFxuICAgICAqIC0gYCdzdGFydCdgIDogdGhlIGNhcmV0IGlzIHBvc2l0aW9uZWQgb24gdGhlIGxlZnQgaGFuZCBzaWRlIG9mIHRoZSB2YWx1ZVxuICAgICAqIC0gYCdlbmQnYCA6IHRoZSBjYXJldCBpcyBwb3NpdGlvbmVkIG9uIHRoZSByaWdodCBoYW5kIHNpZGUgb2YgdGhlIHZhbHVlXG4gICAgICogLSBgJ2RlY2ltYWxMZWZ0J2AgOiB0aGUgY2FyZXQgaXMgcG9zaXRpb25lZCBvbiB0aGUgbGVmdCBzaWRlIG9mIHRoZSBkZWNpbWFsIGNoYXJhY3RlclxuICAgICAqIC0gYCdkZWNpbWFsUmlnaHQnYCA6IHRoZSBjYXJldCBpcyBwb3NpdGlvbmVkIG9uIHRoZSByaWdodCBzaWRlIG9mIHRoZSBkZWNpbWFsIGNoYXJhY3RlclxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlIFRoZSBmb3JtYXR0ZWQgc3RyaW5nIHN0cmlwcGVkIG9mIHRoZSBjdXJyZW5jeSBzeW1ib2wgYW5kIG5lZ2F0aXZlL3Bvc2l0aXZlIHNpZ25cbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfVxuICAgICAqIEB0aHJvd3NcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9pbml0aWFsQ2FyZXRQb3NpdGlvbih2YWx1ZSkge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKCdgX2luaXRpYWxDYXJldFBvc2l0aW9uKClgIHNob3VsZCBuZXZlciBiZSBjYWxsZWQgd2hlbiB0aGUgYGNhcmV0UG9zaXRpb25PbkZvY3VzYCBvcHRpb24gaXMgYG51bGxgLicpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgaXNWYWx1ZU5lZ2F0aXZlID0gdGhpcy5yYXdWYWx1ZSA8IDA7XG4gICAgICAgIGNvbnN0IGlzWmVyb09ySGFzTm9WYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmlzWmVyb09ySGFzTm9WYWx1ZSh2YWx1ZSk7XG4gICAgICAgIGNvbnN0IHRvdGFsTGVuZ3RoID0gdmFsdWUubGVuZ3RoO1xuXG4gICAgICAgIGxldCB2YWx1ZVNpemUgPSAwO1xuICAgICAgICBsZXQgaW50ZWdlclNpemUgPSAwO1xuICAgICAgICBsZXQgaGFzRGVjaW1hbENoYXIgPSBmYWxzZTtcbiAgICAgICAgbGV0IG9mZnNldERlY2ltYWxDaGFyID0gMDtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuc3RhcnQpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWUucmVwbGFjZSgnLScsICcnKTtcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWUucmVwbGFjZSgnKycsICcnKTtcbiAgICAgICAgICAgIHZhbHVlID0gdmFsdWUucmVwbGFjZSh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLCAnJyk7XG4gICAgICAgICAgICB2YWx1ZVNpemUgPSB2YWx1ZS5sZW5ndGg7XG4gICAgICAgICAgICBoYXNEZWNpbWFsQ2hhciA9IEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKHZhbHVlLCB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jYXJldFBvc2l0aW9uT25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5kZWNpbWFsTGVmdCB8fFxuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZGVjaW1hbFJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKGhhc0RlY2ltYWxDaGFyKSB7XG4gICAgICAgICAgICAgICAgICAgIGludGVnZXJTaXplID0gdmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpO1xuICAgICAgICAgICAgICAgICAgICBvZmZzZXREZWNpbWFsQ2hhciA9IHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlci5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaW50ZWdlclNpemUgPSB2YWx1ZVNpemU7XG4gICAgICAgICAgICAgICAgICAgIG9mZnNldERlY2ltYWxDaGFyID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgc2lnblRvVXNlID0gJyc7XG4gICAgICAgIGlmIChpc1ZhbHVlTmVnYXRpdmUpIHtcbiAgICAgICAgICAgIHNpZ25Ub1VzZSA9IHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyO1xuICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSB7XG4gICAgICAgICAgICBzaWduVG9Vc2UgPSB0aGlzLnNldHRpbmdzLnBvc2l0aXZlU2lnbkNoYXJhY3RlcjtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgY29uc3QgcG9zaXRpdmVOZWdhdGl2ZVNpZ25TaXplID0gc2lnblRvVXNlLmxlbmd0aDtcbiAgICAgICAgY29uc3QgY3VycmVuY3lTeW1ib2xTaXplID0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGg7XG5cbiAgICAgICAgLy8gQ2FsY3VsYXRlIHRoZSBjYXJldCBwb3NpdGlvbiBiYXNlZCBvbiBgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnRgLCBgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnRgIGFuZCBgY2FyZXRQb3NpdGlvbk9uRm9jdXNgXG4gICAgICAgIGxldCBjYXJldFBvc2l0aW9uO1xuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLnN0YXJ0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OiAvLyAr4oKsfDEyLjM0XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDogICAvLyAr4oKsfDEyLjM0XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6ICAvLyDigqwrfDEyLjM0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IHBvc2l0aXZlTmVnYXRpdmVTaWduU2l6ZSArIGN1cnJlbmN5U3ltYm9sU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXg6IC8vIOKCrHwxMi4zNCtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gY3VycmVuY3lTeW1ib2xTaXplO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyDigqx8MTIuMzRcbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IGN1cnJlbmN5U3ltYm9sU2l6ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZW5kKSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OiAvLyAr4oKsMTIuMzR8XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDogICAvLyAr4oKsMTIuMzR8XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6ICAvLyDigqwrMTIuMzR8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IHRvdGFsTGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeDogLy8g4oKsMTIuMzR8K1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBjdXJyZW5jeVN5bWJvbFNpemUgKyB2YWx1ZVNpemU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIOKCrDEyLjM0fFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gdG90YWxMZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmRlY2ltYWxMZWZ0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OiAvLyAr4oKsMTJ8LjM0XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDogICAvLyAr4oKsMTJ8LjM0XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6ICAvLyDigqwrMTJ8LjM0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IHBvc2l0aXZlTmVnYXRpdmVTaWduU2l6ZSArIGN1cnJlbmN5U3ltYm9sU2l6ZSArIGludGVnZXJTaXplO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeDogLy8g4oKsMTJ8LjM0K1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBjdXJyZW5jeVN5bWJvbFNpemUgKyBpbnRlZ2VyU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8g4oKsMTJ8LjM0XG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBjdXJyZW5jeVN5bWJvbFNpemUgKyBpbnRlZ2VyU2l6ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuc2V0dGluZ3MuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMuZGVjaW1hbFJpZ2h0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OiAvLyAr4oKsMTIufDM0XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDogICAvLyAr4oKsMTIufDM0XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6ICAvLyDigqwrMTIufDM0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IHBvc2l0aXZlTmVnYXRpdmVTaWduU2l6ZSArIGN1cnJlbmN5U3ltYm9sU2l6ZSArIGludGVnZXJTaXplICsgb2Zmc2V0RGVjaW1hbENoYXI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4OiAvLyDigqwxMi58MzQrXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IGN1cnJlbmN5U3ltYm9sU2l6ZSArIGludGVnZXJTaXplICsgb2Zmc2V0RGVjaW1hbENoYXI7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIOKCrDEyLnwzNFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gY3VycmVuY3lTeW1ib2xTaXplICsgaW50ZWdlclNpemUgKyBvZmZzZXREZWNpbWFsQ2hhcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLnN0YXJ0KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubm9uZSAmJlxuICAgICAgICAgICAgICAgICAgICAoaXNWYWx1ZU5lZ2F0aXZlIHx8ICghaXNWYWx1ZU5lZ2F0aXZlICYmIHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbiAmJiAhaXNaZXJvT3JIYXNOb1ZhbHVlKSkpIHtcbiAgICAgICAgICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4OiAvLyB8MTIuMzTigqwrXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQ6ICAvLyB8MTIuMzTigqwrXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDogICAvLyB8MTIuMzQr4oKsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IDA7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4OiAvLyArfDEyLjM04oKsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IHBvc2l0aXZlTmVnYXRpdmVTaWduU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gfDEyLjM04oKsXG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSAwO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5jYXJldFBvc2l0aW9uT25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5lbmQpIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5ub25lICYmXG4gICAgICAgICAgICAgICAgICAgIChpc1ZhbHVlTmVnYXRpdmUgfHwgKCFpc1ZhbHVlTmVnYXRpdmUgJiYgdGhpcy5zZXR0aW5ncy5zaG93UG9zaXRpdmVTaWduICYmICFpc1plcm9Pckhhc05vVmFsdWUpKSkge1xuICAgICAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXg6IC8vIDEyLjM0fOKCrCtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodDogIC8vIDEyLjM0fOKCrCtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5sZWZ0OiAgIC8vIDEyLjM0fCvigqxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gdmFsdWVTaXplO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDogLy8gKzEyLjM0fOKCrFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBwb3NpdGl2ZU5lZ2F0aXZlU2lnblNpemUgKyB2YWx1ZVNpemU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDEyLjM0fOKCrFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gdmFsdWVTaXplO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5jYXJldFBvc2l0aW9uT25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jYXJldFBvc2l0aW9uT25Gb2N1cy5kZWNpbWFsTGVmdCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Lm5vbmUgJiZcbiAgICAgICAgICAgICAgICAgICAgKGlzVmFsdWVOZWdhdGl2ZSB8fCAoIWlzVmFsdWVOZWdhdGl2ZSAmJiB0aGlzLnNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24gJiYgIWlzWmVyb09ySGFzTm9WYWx1ZSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeDogLy8gMTJ8LjM04oKsK1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnJpZ2h0OiAgLy8gMTJ8LjM04oKsK1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQ6ICAgLy8gMTJ8LjM0K+KCrFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBpbnRlZ2VyU2l6ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg6IC8vICsxMnwuMzTigqxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gcG9zaXRpdmVOZWdhdGl2ZVNpZ25TaXplICsgaW50ZWdlclNpemU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2UgeyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIDEyfC4zNOKCrFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uID0gaW50ZWdlclNpemU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNldHRpbmdzLmNhcmV0UG9zaXRpb25PbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmRlY2ltYWxSaWdodCkge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Lm5vbmUgJiZcbiAgICAgICAgICAgICAgICAgICAgKGlzVmFsdWVOZWdhdGl2ZSB8fCAoIWlzVmFsdWVOZWdhdGl2ZSAmJiB0aGlzLnNldHRpbmdzLnNob3dQb3NpdGl2ZVNpZ24gJiYgIWlzWmVyb09ySGFzTm9WYWx1ZSkpKSB7XG4gICAgICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeDogLy8gMTIufDM04oKsK1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnJpZ2h0OiAgLy8gMTIufDM04oKsK1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQ6ICAgLy8gMTIufDM0K+KCrFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBpbnRlZ2VyU2l6ZSArIG9mZnNldERlY2ltYWxDaGFyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDogLy8gKzEyLnwzNOKCrFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb24gPSBwb3NpdGl2ZU5lZ2F0aXZlU2lnblNpemUgKyBpbnRlZ2VyU2l6ZSArIG9mZnNldERlY2ltYWxDaGFyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyAxMi58MzTigqxcbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbiA9IGludGVnZXJTaXplICsgb2Zmc2V0RGVjaW1hbENoYXI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGNhcmV0UG9zaXRpb247XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJ1bmNhdGUgdGhlIHRyYWlsaW5nIHplcm9lcyB0byB0aGUgZ2l2ZW4gbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcm91bmRlZElucHV0VmFsdWVcbiAgICAgKiBAcGFyYW0ge2ludH0gZGVjaW1hbFBsYWNlc05lZWRlZCBUaGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIGtlZXBcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqL1xuICAgIHN0YXRpYyBfdHJ1bmNhdGVaZXJvcyhyb3VuZGVkSW5wdXRWYWx1ZSwgZGVjaW1hbFBsYWNlc05lZWRlZCkge1xuICAgICAgICBsZXQgcmVnZXg7XG4gICAgICAgIHN3aXRjaCAoZGVjaW1hbFBsYWNlc05lZWRlZCkge1xuICAgICAgICAgICAgY2FzZSAwOlxuICAgICAgICAgICAgICAgIC8vIFByZXZlbnRzIHBhZGRpbmcgLSByZW1vdmVzIHRyYWlsaW5nIHplcm9zIHVudGlsIHRoZSBmaXJzdCBzaWduaWZpY2FudCBkaWdpdCBpcyBlbmNvdW50ZXJlZFxuICAgICAgICAgICAgICAgIHJlZ2V4ID0gLyhcXC4oPzpcXGQqWzEtOV0pPykwKiQvO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAxOlxuICAgICAgICAgICAgICAgIC8vIEFsbG93cyBwYWRkaW5nIHdoZW4gZGVjaW1hbFBsYWNlc05lZWRlZCBlcXVhbHMgb25lIC0gbGVhdmVzIG9uZSB6ZXJvIHRyYWlsaW5nIHRoZSBkZWNpbWFsIGNoYXJhY3RlclxuICAgICAgICAgICAgICAgIHJlZ2V4ID0gLyhcXC5cXGQoPzpcXGQqWzEtOV0pPykwKiQvO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgLy8gUmVtb3ZlcyBzdXBlcmZsdW91cyB6ZXJvcyBhZnRlciB0aGUgZGVjaW1hbFBsYWNlc05lZWRlZCBsZW5ndGhcbiAgICAgICAgICAgICAgICByZWdleCA9IG5ldyBSZWdFeHAoYChcXFxcLlxcXFxkeyR7ZGVjaW1hbFBsYWNlc05lZWRlZH19KD86XFxcXGQqWzEtOV0pPykwKmApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgdGhlcmUgYXJlIG5vIGRlY2ltYWwgcGxhY2VzLCB3ZSBkb24ndCBuZWVkIGEgZGVjaW1hbCBwb2ludCBhdCB0aGUgZW5kXG4gICAgICAgIHJvdW5kZWRJbnB1dFZhbHVlID0gcm91bmRlZElucHV0VmFsdWUucmVwbGFjZShyZWdleCwgJyQxJyk7XG4gICAgICAgIGlmIChkZWNpbWFsUGxhY2VzTmVlZGVkID09PSAwKSB7XG4gICAgICAgICAgICByb3VuZGVkSW5wdXRWYWx1ZSA9IHJvdW5kZWRJbnB1dFZhbHVlLnJlcGxhY2UoL1xcLiQvLCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcm91bmRlZElucHV0VmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUm91bmQgdGhlIGdpdmVuIGB2YWx1ZWAgd2l0aCB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHRvIGtlZXAgZm9yIHRoZSByYXcgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudWxsfSB2YWx1ZSBBbiB1bmZvcm1hdHRlZCBudW1lcmljIHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3JvdW5kUmF3VmFsdWUodmFsdWUsIHNldHRpbmdzKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9yb3VuZFZhbHVlKHZhbHVlLCBzZXR0aW5ncywgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSb3VuZCB0aGUgZ2l2ZW4gYHZhbHVlYCB3aXRoIHRoZSBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgdG8gc2hvdyBmb3IgdGhlIGVsZW1lbnQgaXMgZm9jdXNlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IHZhbHVlIEFuIHVuZm9ybWF0dGVkIG51bWVyaWMgdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfcm91bmRGb3JtYXR0ZWRWYWx1ZVNob3duT25Gb2N1cyh2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JvdW5kVmFsdWUodmFsdWUsIHNldHRpbmdzLCBOdW1iZXIoc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cykpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJvdW5kIHRoZSBnaXZlbiBgdmFsdWVgIHdpdGggdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0byBzaG93IGZvciB0aGUgZWxlbWVudCBpcyB1bmZvY3VzZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudWxsfSB2YWx1ZSBBbiB1bmZvcm1hdHRlZCBudW1lcmljIHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uQmx1cih2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3JvdW5kVmFsdWUodmFsdWUsIHNldHRpbmdzLCBOdW1iZXIoc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUm91bmQgdGhlIGlucHV0IHZhbHVlIHVzaW5nIHRoZSByb3VuZGluZyBtZXRob2QgZGVmaW5lZCBpbiB0aGUgc2V0dGluZ3MuXG4gICAgICogVGhpcyBmdW5jdGlvbiBhY2NlcHRzIG11bHRpcGxlIHJvdW5kaW5nIG1ldGhvZHMuIFNlZSB0aGUgZG9jdW1lbnRhdGlvbiBmb3IgbW9yZSBkZXRhaWxzIGFib3V0IHRob3NlLlxuICAgICAqXG4gICAgICogTm90ZSA6IFRoaXMgaXMgaGFuZGxlZCBhcyB0ZXh0IHNpbmNlIEphdmFTY3JpcHQgbWF0aCBmdW5jdGlvbnMgY2FuIHJldHVybiBpbmFjY3VyYXRlIHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IGlucHV0VmFsdWUgQW4gdW5mb3JtYXR0ZWQgbnVtZXJpYyB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEBwYXJhbSB7aW50fSBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIF9yb3VuZFZhbHVlKGlucHV0VmFsdWUsIHNldHRpbmdzLCBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvKSB7XG4gICAgICAgIC8vWFhYIE5vdGU7IHRoaXMgZnVuY3Rpb24gaXMgc3RhdGljIHNpbmNlIHdlIG5lZWQgdG8gcGFzcyBhIGBzZXR0aW5nc2Agb2JqZWN0IHdoZW4gY2FsbGluZyB0aGUgc3RhdGljIGBBdXRvTnVtZXJpYy5mb3JtYXQoKWAgbWV0aG9kXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bGwoaW5wdXRWYWx1ZSkpIHtcbiAgICAgICAgICAgIC8vIFByZXZlbnQgcm91bmRpbmcgYSBgbnVsbGAgdmFsdWVcbiAgICAgICAgICAgIHJldHVybiBpbnB1dFZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy9UT0RPIERpdmlkZSB0aGlzIGZ1bmN0aW9uIHRvIG1ha2UgaXQgZWFzaWVyIHRvIHVuZGVyc3RhbmRcbiAgICAgICAgaW5wdXRWYWx1ZSA9IChpbnB1dFZhbHVlID09PSAnJykgPyAnMCcgOiBpbnB1dFZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgIGlmIChzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC50b05lYXJlc3QwNSB8fFxuICAgICAgICAgICAgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QudG9OZWFyZXN0MDVBbHQgfHxcbiAgICAgICAgICAgIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnVwVG9OZXh0MDUgfHxcbiAgICAgICAgICAgIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmRvd25Ub05leHQwNSkge1xuICAgICAgICAgICAgcmV0dXJuIHRoaXMuX3JvdW5kQ2xvc2VUbzA1KGlucHV0VmFsdWUsIHNldHRpbmdzKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IFtuZWdhdGl2ZVNpZ24sIHByZXBhcmVkVmFsdWVdID0gQXV0b051bWVyaWMuX3ByZXBhcmVWYWx1ZUZvclJvdW5kaW5nKGlucHV0VmFsdWUsIHNldHRpbmdzKTtcbiAgICAgICAgaW5wdXRWYWx1ZSA9IHByZXBhcmVkVmFsdWU7XG5cbiAgICAgICAgY29uc3QgZGVjaW1hbENoYXJhY3RlclBvc2l0aW9uID0gaW5wdXRWYWx1ZS5sYXN0SW5kZXhPZignLicpO1xuICAgICAgICBjb25zdCBpbnB1dFZhbHVlSGFzTm9Eb3QgPSBkZWNpbWFsQ2hhcmFjdGVyUG9zaXRpb24gPT09IC0xOyAvLyBObyBkb3QgY2hhcmFjdGVyIGlzIGZvdW5kIGluIHRoZSBgaW5wdXRWYWx1ZWBcbiAgICAgICAgY29uc3QgWywgZGVjaW1hbFBhcnRdID0gaW5wdXRWYWx1ZS5zcGxpdCgnLicpOyAvLyBIZXJlIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBpcyBhbHdheXMgYSBwZXJpb2QgJy4nXG4gICAgICAgIGNvbnN0IGhhc0RlY2ltYWxzID0gZGVjaW1hbFBhcnQgPiAwO1xuXG4gICAgICAgIC8vIElmIG5vIGRlY2ltYWxzIGFyZSBkZXRlY3RlZFxuICAgICAgICBpZiAoIWhhc0RlY2ltYWxzICYmXG4gICAgICAgICAgICAoc2V0dGluZ3MuYWxsb3dEZWNpbWFsUGFkZGluZyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nLm5ldmVyIHx8XG4gICAgICAgICAgICBzZXR0aW5ncy5hbGxvd0RlY2ltYWxQYWRkaW5nID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcuZmxvYXRzKSkge1xuICAgICAgICAgICAgcmV0dXJuIChOdW1iZXIoaW5wdXRWYWx1ZSkgPT09IDApID8gaW5wdXRWYWx1ZSA6IGAke25lZ2F0aXZlU2lnbn0ke2lucHV0VmFsdWV9YDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEVsc2UgdGhlcmUgYXJlIHNvbWUgZGVjaW1hbCBwbGFjZXMgdGhhdCBtYXkgbmVlZCB0byBiZSByb3VuZGVkXG4gICAgICAgIC8vIFNldHMgdGhlIHRydW5jYXRlIHplcm8gbWV0aG9kXG4gICAgICAgIGxldCB0ZW1wb3JhcnlEZWNpbWFsUGxhY2VzT3ZlcnJpZGU7XG4gICAgICAgIGlmIChzZXR0aW5ncy5hbGxvd0RlY2ltYWxQYWRkaW5nID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcuYWx3YXlzIHx8XG4gICAgICAgICAgICBzZXR0aW5ncy5hbGxvd0RlY2ltYWxQYWRkaW5nID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcuZmxvYXRzKSB7XG4gICAgICAgICAgICB0ZW1wb3JhcnlEZWNpbWFsUGxhY2VzT3ZlcnJpZGUgPSBkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGVtcG9yYXJ5RGVjaW1hbFBsYWNlc092ZXJyaWRlID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIERlZmluZSB0aGUgZGVjaW1hbCBwb3NpdGlvbiB0byB1c2UgKHVzZSB0aGUgdmVyeSBsYXN0IHBvc2l0aW9uIGlmIHRoZXJlIGFyZSBubyBkb3QgaW4gdGhlIGluaXRpYWwgaW5wdXRWYWx1ZSlcbiAgICAgICAgY29uc3QgZGVjaW1hbFBvc2l0aW9uVG9Vc2UgPSBpbnB1dFZhbHVlSGFzTm9Eb3QgPyBpbnB1dFZhbHVlLmxlbmd0aCAtIDEgOiBkZWNpbWFsQ2hhcmFjdGVyUG9zaXRpb247XG4gICAgICAgIC8vIENoZWNrcyBkZWNpbWFsIHBsYWNlcyB0byBkZXRlcm1pbmUgaWYgcm91bmRpbmcgaXMgcmVxdWlyZWRcbiAgICAgICAgbGV0IGNoZWNrRGVjaW1hbFBsYWNlcyA9IChpbnB1dFZhbHVlLmxlbmd0aCAtIDEpIC0gZGVjaW1hbFBvc2l0aW9uVG9Vc2U7XG4gICAgICAgIGxldCBpbnB1dFZhbHVlUm91bmRlZCA9ICcnO1xuXG4gICAgICAgIC8vIENoZWNrIGlmIG5vIHJvdW5kaW5nIGlzIHJlcXVpcmVkXG4gICAgICAgIGlmIChjaGVja0RlY2ltYWxQbGFjZXMgPD0gZGVjaW1hbFBsYWNlc1RvUm91bmRUbykge1xuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgd2UgbmVlZCB0byBwYWQgd2l0aCB6ZXJvc1xuICAgICAgICAgICAgaW5wdXRWYWx1ZVJvdW5kZWQgPSBpbnB1dFZhbHVlO1xuICAgICAgICAgICAgaWYgKGNoZWNrRGVjaW1hbFBsYWNlcyA8IHRlbXBvcmFyeURlY2ltYWxQbGFjZXNPdmVycmlkZSkge1xuICAgICAgICAgICAgICAgIGlmIChpbnB1dFZhbHVlSGFzTm9Eb3QpIHtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZVJvdW5kZWQgPSBgJHtpbnB1dFZhbHVlUm91bmRlZH0ke3NldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJ9YDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBsZXQgemVyb3MgPSAnMDAwMDAwJzsgLy9UT0RPIENoYW5nZSB0aGF0IHN0cmluZyB3aXRoIGEgbG9uZ2VyIG9uZSB0byBwcmV2ZW50IGhhdmluZyB0byBsb29wIG51bWVyb3VzIHRpbWVzIGluIHRoZSBuZXh0IGB3aGlsZWAgc3RhdGVtZW50P1xuICAgICAgICAgICAgICAgIHdoaWxlIChjaGVja0RlY2ltYWxQbGFjZXMgPCB0ZW1wb3JhcnlEZWNpbWFsUGxhY2VzT3ZlcnJpZGUpIHtcbiAgICAgICAgICAgICAgICAgICAgemVyb3MgPSB6ZXJvcy5zdWJzdHJpbmcoMCwgdGVtcG9yYXJ5RGVjaW1hbFBsYWNlc092ZXJyaWRlIC0gY2hlY2tEZWNpbWFsUGxhY2VzKTtcbiAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZVJvdW5kZWQgKz0gemVyb3M7XG4gICAgICAgICAgICAgICAgICAgIGNoZWNrRGVjaW1hbFBsYWNlcyArPSB6ZXJvcy5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChjaGVja0RlY2ltYWxQbGFjZXMgPiB0ZW1wb3JhcnlEZWNpbWFsUGxhY2VzT3ZlcnJpZGUpIHtcbiAgICAgICAgICAgICAgICBpbnB1dFZhbHVlUm91bmRlZCA9IHRoaXMuX3RydW5jYXRlWmVyb3MoaW5wdXRWYWx1ZVJvdW5kZWQsIHRlbXBvcmFyeURlY2ltYWxQbGFjZXNPdmVycmlkZSk7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKGNoZWNrRGVjaW1hbFBsYWNlcyA9PT0gMCAmJiB0ZW1wb3JhcnlEZWNpbWFsUGxhY2VzT3ZlcnJpZGUgPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyBSZW1vdmUgYW55IHRyYWlsaW5nIGRvdCwgaWYgYW55XG4gICAgICAgICAgICAgICAgaW5wdXRWYWx1ZVJvdW5kZWQgPSBpbnB1dFZhbHVlUm91bmRlZC5yZXBsYWNlKC9cXC4kLywgJycpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gKE51bWJlcihpbnB1dFZhbHVlUm91bmRlZCkgPT09IDApID8gaW5wdXRWYWx1ZVJvdW5kZWQgOiBgJHtuZWdhdGl2ZVNpZ259JHtpbnB1dFZhbHVlUm91bmRlZH1gO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUm91bmRlZCBsZW5ndGggb2YgdGhlIHN0cmluZyBhZnRlciByb3VuZGluZ1xuICAgICAgICBsZXQgcm91bmRlZFN0ckxlbmd0aDtcbiAgICAgICAgaWYgKGlucHV0VmFsdWVIYXNOb0RvdCkge1xuICAgICAgICAgICAgcm91bmRlZFN0ckxlbmd0aCA9IGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8gLSAxO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcm91bmRlZFN0ckxlbmd0aCA9IE51bWJlcihkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvKSArIE51bWJlcihkZWNpbWFsQ2hhcmFjdGVyUG9zaXRpb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgbGFzdERpZ2l0ID0gTnVtYmVyKGlucHV0VmFsdWUuY2hhckF0KHJvdW5kZWRTdHJMZW5ndGggKyAxKSk7XG4gICAgICAgIGxldCBpbnB1dFZhbHVlQXJyYXkgPSBpbnB1dFZhbHVlLnN1YnN0cmluZygwLCByb3VuZGVkU3RyTGVuZ3RoICsgMSkuc3BsaXQoJycpO1xuICAgICAgICBsZXQgb2RkO1xuICAgICAgICBpZiAoaW5wdXRWYWx1ZS5jaGFyQXQocm91bmRlZFN0ckxlbmd0aCkgPT09ICcuJykge1xuICAgICAgICAgICAgb2RkID0gaW5wdXRWYWx1ZS5jaGFyQXQocm91bmRlZFN0ckxlbmd0aCAtIDEpICUgMjtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIG9kZCA9IGlucHV0VmFsdWUuY2hhckF0KHJvdW5kZWRTdHJMZW5ndGgpICUgMjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLl9zaG91bGRSb3VuZFVwKGxhc3REaWdpdCwgc2V0dGluZ3MsIG5lZ2F0aXZlU2lnbiwgb2RkKSkge1xuICAgICAgICAgICAgLy8gUm91bmQgdXAgdGhlIGxhc3QgZGlnaXQgaWYgcmVxdWlyZWQsIGFuZCBjb250aW51ZSB1bnRpbCBubyBtb3JlIDkncyBhcmUgZm91bmRcbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAoaW5wdXRWYWx1ZUFycmF5Lmxlbmd0aCAtIDEpOyBpID49IDA7IGkgLT0gMSkge1xuICAgICAgICAgICAgICAgIGlmIChpbnB1dFZhbHVlQXJyYXlbaV0gIT09ICcuJykge1xuICAgICAgICAgICAgICAgICAgICBpbnB1dFZhbHVlQXJyYXlbaV0gPSAraW5wdXRWYWx1ZUFycmF5W2ldICsgMTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlucHV0VmFsdWVBcnJheVtpXSA8IDEwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChpID4gMCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRWYWx1ZUFycmF5W2ldID0gJzAnO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVjb25zdHJ1Y3QgdGhlIHN0cmluZywgY29udmVydGluZyBhbnkgMTAncyB0byAwJ3NcbiAgICAgICAgaW5wdXRWYWx1ZUFycmF5ID0gaW5wdXRWYWx1ZUFycmF5LnNsaWNlKDAsIHJvdW5kZWRTdHJMZW5ndGggKyAxKTtcblxuICAgICAgICAvLyBSZXR1cm4gdGhlIHJvdW5kZWQgdmFsdWVcbiAgICAgICAgaW5wdXRWYWx1ZVJvdW5kZWQgPSB0aGlzLl90cnVuY2F0ZVplcm9zKGlucHV0VmFsdWVBcnJheS5qb2luKCcnKSwgdGVtcG9yYXJ5RGVjaW1hbFBsYWNlc092ZXJyaWRlKTtcblxuICAgICAgICByZXR1cm4gKE51bWJlcihpbnB1dFZhbHVlUm91bmRlZCkgPT09IDApID8gaW5wdXRWYWx1ZVJvdW5kZWQgOiBgJHtuZWdhdGl2ZVNpZ259JHtpbnB1dFZhbHVlUm91bmRlZH1gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJvdW5kIHRoZSBgdmFsdWVgIHdoZW4gdGhlIHJvdW5kaW5nIG1ldGhvZCBkZWFscyB3aXRoICcuMDUnXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9yb3VuZENsb3NlVG8wNSh2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgc3dpdGNoIChzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCkge1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnRvTmVhcmVzdDA1OlxuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLnRvTmVhcmVzdDA1QWx0OlxuICAgICAgICAgICAgICAgIHZhbHVlID0gKE1hdGgucm91bmQodmFsdWUgKiAyMCkgLyAyMCkudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC51cFRvTmV4dDA1OlxuICAgICAgICAgICAgICAgIHZhbHVlID0gKE1hdGguY2VpbCh2YWx1ZSAqIDIwKSAvIDIwKS50b1N0cmluZygpO1xuICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgZGVmYXVsdCA6XG4gICAgICAgICAgICAgICAgdmFsdWUgPSAoTWF0aC5mbG9vcih2YWx1ZSAqIDIwKSAvIDIwKS50b1N0cmluZygpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyh2YWx1ZSwgJy4nKSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUgKyAnLjAwJztcbiAgICAgICAgfSBlbHNlIGlmICh2YWx1ZS5sZW5ndGggLSB2YWx1ZS5pbmRleE9mKCcuJykgPCAzKSB7XG4gICAgICAgICAgICByZXN1bHQgPSB2YWx1ZSArICcwJztcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNb2RpZnkgdGhlIGdpdmVuIGB2YWx1ZWAgaW4gb3JkZXIgdG8gbWFrZSBpdCB1c2FibGUgZm9yIHRoZSByZXN0IG9mIHRoZSByb3VuZGluZyBmdW5jdGlvbi5cbiAgICAgKiBUaGlzIGNvbnZlcnQgdGhlIGB2YWx1ZWAgdG8gYSBwb3NpdGl2ZSBvbmUsIHRyaW0gYW55IGxlYWRpbmcgemVyb3MgYW5kIG1ha2Ugc3VyZSBpdCBkb2VzIG5vdCBzdGFydHMgd2l0aCBhIGxlYWRpbmcgZG90LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMge1tzdHJpbmcsIHN0cmluZ119XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3ByZXBhcmVWYWx1ZUZvclJvdW5kaW5nKHZhbHVlLCBzZXR0aW5ncykge1xuICAgICAgICAvLyBDaGVja3MgaWYgYGlucHV0VmFsdWVgIGlzIGEgbmVnYXRpdmUgdmFsdWVcbiAgICAgICAgbGV0IG5lZ2F0aXZlU2lnbiA9ICcnO1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZVN0cmljdCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIG5lZ2F0aXZlU2lnbiA9ICctJztcblxuICAgICAgICAgICAgLy8gUmVtb3ZlcyB0aGUgbmVnYXRpdmUgc2lnbiB0aGF0IHdpbGwgYmUgYWRkZWQgYmFjayBsYXRlciBpZiByZXF1aXJlZFxuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKCctJywgJycpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQXBwZW5kIGEgemVybyBpZiB0aGUgZmlyc3QgY2hhcmFjdGVyIGlzIG5vdCBhIGRpZ2l0ICh0aGVuIGl0IGlzIGxpa2VseSBhIGRvdClcbiAgICAgICAgaWYgKCF2YWx1ZS5tYXRjaCgvXlxcZC8pKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IGAwJHt2YWx1ZX1gO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGV0ZXJtaW5lcyBpZiB0aGUgdmFsdWUgaXMgZXF1YWwgdG8gemVyby4gSWYgaXQgaXMsIHJlbW92ZSB0aGUgbmVnYXRpdmUgc2lnblxuICAgICAgICBpZiAoTnVtYmVyKHZhbHVlKSA9PT0gMCkge1xuICAgICAgICAgICAgbmVnYXRpdmVTaWduID0gJyc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBUcmltcyBsZWFkaW5nIHplcm8ncyBhcyBuZWVkZWRcbiAgICAgICAgaWYgKChOdW1iZXIodmFsdWUpID4gMCAmJiBzZXR0aW5ncy5sZWFkaW5nWmVybyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5rZWVwKSB8fFxuICAgICAgICAgICAgKHZhbHVlLmxlbmd0aCA+IDAgJiYgc2V0dGluZ3MubGVhZGluZ1plcm8gPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8uYWxsb3cpKSB7XG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoL14wKihcXGQpLywgJyQxJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gW25lZ2F0aXZlU2lnbiwgdmFsdWVdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgYSByb3VuZCB1cCBzaG91bGQgYmUgZG9uZSBnaXZlbiB0aGUgbGFzdCBkaWdpdCwgdGhlIHNldHRpbmdzIGFuZCBvdGhlciBpbmZvcm1hdGlvbiBhYm91dCB0aGUgdmFsdWUuXG4gICAgICogXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IGxhc3REaWdpdFxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBzZXR0aW5nc1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuZWdhdGl2ZVNpZ25cbiAgICAgKiBAcGFyYW0ge251bWJlcn0gb2RkXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX3Nob3VsZFJvdW5kVXAobGFzdERpZ2l0LCBzZXR0aW5ncywgbmVnYXRpdmVTaWduLCBvZGQpIHtcbiAgICAgICAgcmV0dXJuIChsYXN0RGlnaXQgPiA0ICYmIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZVcFN5bW1ldHJpYykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfHwgLy8gUm91bmQgaGFsZiB1cCBzeW1tZXRyaWNcbiAgICAgICAgICAgIChsYXN0RGlnaXQgPiA0ICYmIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZVcEFzeW1tZXRyaWMgJiYgbmVnYXRpdmVTaWduID09PSAnJykgICAgICAgICAgICAgICAgfHwgLy8gUm91bmQgaGFsZiB1cCBhc3ltbWV0cmljIHBvc2l0aXZlIHZhbHVlc1xuICAgICAgICAgICAgKGxhc3REaWdpdCA+IDUgJiYgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZlVwQXN5bW1ldHJpYyAmJiBuZWdhdGl2ZVNpZ24gPT09ICctJykgICAgICAgICAgICAgICB8fCAvLyBSb3VuZCBoYWxmIHVwIGFzeW1tZXRyaWMgbmVnYXRpdmUgdmFsdWVzXG4gICAgICAgICAgICAobGFzdERpZ2l0ID4gNSAmJiBzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC5oYWxmRG93blN5bW1ldHJpYykgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHx8IC8vIFJvdW5kIGhhbGYgZG93biBzeW1tZXRyaWNcbiAgICAgICAgICAgIChsYXN0RGlnaXQgPiA1ICYmIHNldHRpbmdzLnJvdW5kaW5nTWV0aG9kID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnJvdW5kaW5nTWV0aG9kLmhhbGZEb3duQXN5bW1ldHJpYyAmJiBuZWdhdGl2ZVNpZ24gPT09ICcnKSAgICAgICAgICAgICAgfHwgLy8gUm91bmQgaGFsZiBkb3duIGFzeW1tZXRyaWMgcG9zaXRpdmUgdmFsdWVzXG4gICAgICAgICAgICAobGFzdERpZ2l0ID4gNCAmJiBzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC5oYWxmRG93bkFzeW1tZXRyaWMgJiYgbmVnYXRpdmVTaWduID09PSAnLScpICAgICAgICAgICAgIHx8IC8vIFJvdW5kIGhhbGYgZG93biBhc3ltbWV0cmljIG5lZ2F0aXZlIHZhbHVlc1xuICAgICAgICAgICAgKGxhc3REaWdpdCA+IDUgJiYgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZkV2ZW5CYW5rZXJzUm91bmRpbmcpICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB8fFxuICAgICAgICAgICAgKGxhc3REaWdpdCA9PT0gNSAmJiBzZXR0aW5ncy5yb3VuZGluZ01ldGhvZCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5yb3VuZGluZ01ldGhvZC5oYWxmRXZlbkJhbmtlcnNSb3VuZGluZyAmJiBvZGQgPT09IDEpICAgICAgICAgICAgICAgICB8fFxuICAgICAgICAgICAgKGxhc3REaWdpdCA+IDAgJiYgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QudG9DZWlsaW5nVG93YXJkUG9zaXRpdmVJbmZpbml0eSAmJiBuZWdhdGl2ZVNpZ24gPT09ICcnKSB8fFxuICAgICAgICAgICAgKGxhc3REaWdpdCA+IDAgJiYgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QudG9GbG9vclRvd2FyZE5lZ2F0aXZlSW5maW5pdHkgJiYgbmVnYXRpdmVTaWduID09PSAnLScpICB8fFxuICAgICAgICAgICAgKGxhc3REaWdpdCA+IDAgJiYgc2V0dGluZ3Mucm91bmRpbmdNZXRob2QgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QudXBSb3VuZEF3YXlGcm9tWmVybyk7ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBSb3VuZCB1cCBhd2F5IGZyb20gemVyb1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFRydW5jYXRlcyB0aGUgZGVjaW1hbCBwYXJ0IG9mIGEgbnVtYmVyIHRvIHRoZSBnaXZlbiBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgYGRlY2ltYWxQbGFjZXNUb1JvdW5kVG9gLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHBhcmFtIHtib29sZWFufSBpc1Bhc3RlXG4gICAgICogQHBhcmFtIHtpbnR9IGRlY2ltYWxQbGFjZXNUb1JvdW5kVG9cbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgX3RydW5jYXRlRGVjaW1hbFBsYWNlcyh2YWx1ZSwgc2V0dGluZ3MsIGlzUGFzdGUsIGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8pIHtcbiAgICAgICAgaWYgKGlzUGFzdGUpIHtcbiAgICAgICAgICAgIHZhbHVlID0gdGhpcy5fcm91bmRGb3JtYXR0ZWRWYWx1ZVNob3duT25Gb2N1cyh2YWx1ZSwgc2V0dGluZ3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgW2ludGVnZXJQYXJ0LCBkZWNpbWFsUGFydF0gPSB2YWx1ZS5zcGxpdChzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKTtcblxuICAgICAgICAvLyBUcnVuY2F0ZSB0aGUgZGVjaW1hbCBwYXJ0IHRvIHRoZSBzYXRpc2Z5aW5nIGxlbmd0aCBzaW5jZSB3ZSB3b3VsZCByb3VuZCBpdCBhbnl3YXlcbiAgICAgICAgaWYgKGRlY2ltYWxQYXJ0ICYmIGRlY2ltYWxQYXJ0Lmxlbmd0aCA+IGRlY2ltYWxQbGFjZXNUb1JvdW5kVG8pIHtcbiAgICAgICAgICAgIGlmIChkZWNpbWFsUGxhY2VzVG9Sb3VuZFRvID4gMCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IG1vZGlmaWVkRGVjaW1hbFBhcnQgPSBkZWNpbWFsUGFydC5zdWJzdHJpbmcoMCwgZGVjaW1hbFBsYWNlc1RvUm91bmRUbyk7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBgJHtpbnRlZ2VyUGFydH0ke3NldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJ9JHttb2RpZmllZERlY2ltYWxQYXJ0fWA7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gaW50ZWdlclBhcnQ7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ2hlY2sgdGhhdCB0aGUgbnVtYmVyIHNhdGlzZnkgdGhlIGZvcm1hdCBjb25kaXRpb25zXG4gICAgICogYW5kIGxheXMgYmV0d2VlbiBzZXR0aW5ncy5taW5pbXVtVmFsdWUgYW5kIHNldHRpbmdzLm1heGltdW1WYWx1ZVxuICAgICAqIGFuZCB0aGUgc3RyaW5nIGxlbmd0aCBkb2VzIG5vdCBleGNlZWQgdGhlIGRpZ2l0cyBpbiBzZXR0aW5ncy5taW5pbXVtVmFsdWUgYW5kIHNldHRpbmdzLm1heGltdW1WYWx1ZVxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIF9jaGVja0lmSW5SYW5nZVdpdGhPdmVycmlkZU9wdGlvbih2YWx1ZSwgc2V0dGluZ3MpIHtcbiAgICAgICAgdmFsdWUgPSB2YWx1ZS50b1N0cmluZygpO1xuICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoJywnLCAnLicpO1xuICAgICAgICBjb25zdCBtaW5QYXJzZSA9IEF1dG9OdW1lcmljSGVscGVyLnBhcnNlU3RyKHNldHRpbmdzLm1pbmltdW1WYWx1ZSk7XG4gICAgICAgIGNvbnN0IG1heFBhcnNlID0gQXV0b051bWVyaWNIZWxwZXIucGFyc2VTdHIoc2V0dGluZ3MubWF4aW11bVZhbHVlKTtcbiAgICAgICAgY29uc3QgdmFsUGFyc2UgPSBBdXRvTnVtZXJpY0hlbHBlci5wYXJzZVN0cih2YWx1ZSk7XG5cbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgc3dpdGNoIChzZXR0aW5ncy5vdmVycmlkZU1pbk1heExpbWl0cykge1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm92ZXJyaWRlTWluTWF4TGltaXRzLmZsb29yOlxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IFtBdXRvTnVtZXJpY0hlbHBlci50ZXN0TWluTWF4KG1pblBhcnNlLCB2YWxQYXJzZSkgPiAtMSwgdHJ1ZV07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMuY2VpbGluZzpcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBbdHJ1ZSwgQXV0b051bWVyaWNIZWxwZXIudGVzdE1pbk1heChtYXhQYXJzZSwgdmFsUGFyc2UpIDwgMV07XG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMuaWdub3JlOlxuICAgICAgICAgICAgICAgIHJlc3VsdCA9IFt0cnVlLCB0cnVlXTtcbiAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gW0F1dG9OdW1lcmljSGVscGVyLnRlc3RNaW5NYXgobWluUGFyc2UsIHZhbFBhcnNlKSA+IC0xLCBBdXRvTnVtZXJpY0hlbHBlci50ZXN0TWluTWF4KG1heFBhcnNlLCB2YWxQYXJzZSkgPCAxXTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogT3JpZ2luYWwgc2V0dGluZ3Mgc2F2ZWQgZm9yIHVzZSB3aGVuIHRoZSBgZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1c2AgYW5kIGBzaG93T25seU51bWJlcnNPbkZvY3VzYCBvcHRpb25zIGFyZSB1c2VkLlxuICAgICAqIFRob3NlIG9yaWdpbmFsIHNldHRpbmdzIGFyZSB1c2VkIGV4Y2x1c2l2ZWx5IGluIHRoZSBgZm9jdXNpbmAgYW5kIGBmb2N1c291dGAgZXZlbnQgaGFuZGxlcnMuXG4gICAgICovXG4gICAgX2tlZXBBbk9yaWdpbmFsU2V0dGluZ3NDb3B5KCkge1xuICAgICAgICB0aGlzLm9yaWdpbmFsRGlnaXRHcm91cFNlcGFyYXRvciA9IHRoaXMuc2V0dGluZ3MuZGlnaXRHcm91cFNlcGFyYXRvcjtcbiAgICAgICAgdGhpcy5vcmlnaW5hbEN1cnJlbmN5U3ltYm9sICAgICAgPSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sO1xuICAgICAgICB0aGlzLm9yaWdpbmFsU3VmZml4VGV4dCAgICAgICAgICA9IHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBPcmlnaW5hbCBzZXR0aW5ncyBzYXZlZCBmb3IgdXNlIHdoZW4gYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNgICYgYHNob3dPbmx5TnVtYmVyc09uRm9jdXNgIG9wdGlvbnMgYXJlIGJlaW5nIHVzZWQuXG4gICAgICogVGhpcyBpcyB0YWtlbiBmcm9tIFF1aXJrc21vZGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmFtZVxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBfcmVhZENvb2tpZShuYW1lKSB7XG4gICAgICAgIGNvbnN0IG5hbWVFUSA9IG5hbWUgKyAnPSc7XG4gICAgICAgIGNvbnN0IGNhID0gZG9jdW1lbnQuY29va2llLnNwbGl0KCc7Jyk7XG4gICAgICAgIGxldCBjID0gJyc7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2EubGVuZ3RoOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGMgPSBjYVtpXTtcbiAgICAgICAgICAgIHdoaWxlIChjLmNoYXJBdCgwKSA9PT0gJyAnKSB7XG4gICAgICAgICAgICAgICAgYyA9IGMuc3Vic3RyaW5nKDEsIGMubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmIChjLmluZGV4T2YobmFtZUVRKSA9PT0gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBjLnN1YnN0cmluZyhuYW1lRVEubGVuZ3RoLCBjLmxlbmd0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUZXN0IGlmIHNlc3Npb25TdG9yYWdlIGlzIHN1cHBvcnRlZC5cbiAgICAgKiBUaGlzIGlzIHRha2VuIGZyb20gTW9kZXJuaXpyLlxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIF9zdG9yYWdlVGVzdCgpIHtcbiAgICAgICAgY29uc3QgbW9kID0gJ21vZGVybml6cic7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICBzZXNzaW9uU3RvcmFnZS5zZXRJdGVtKG1vZCwgbW9kKTtcbiAgICAgICAgICAgIHNlc3Npb25TdG9yYWdlLnJlbW92ZUl0ZW0obW9kKTtcbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFueSB6ZXJvcyBpbiBleGNlc3MgaW4gdGhlIGZyb250IGFuZCBiYWNrIG9mIHRoZSBnaXZlbiBgdmFsdWVgLCBhY2NvcmRpbmcgdG8gdGhlIGBzZXR0aW5nc2AuXG4gICAgICogVGhpcyBhbHNvIG1hbmFnZXMgdGhlIGNhc2VzIHdoZXJlIHRoZSBkZWNpbWFsIHBvaW50IGlzIG9uIHRoZSBmYXIgbGVmdCBvciBmYXIgcmlnaHQgb2YgdGhlIGB2YWx1ZWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bGx9XG4gICAgICovXG4gICAgX3RyaW1MZWFkaW5nQW5kVHJhaWxpbmdaZXJvcyh2YWx1ZSkge1xuICAgICAgICAvLyBSZXR1cm4gdGhlIGVtcHR5IHN0cmluZyBpcyB0aGUgdmFsdWUgaXMgYWxyZWFkeSBlbXB0eS4gVGhpcyBwcmV2ZW50IGNvbnZlcnRpbmcgdGhhdCB2YWx1ZSB0byAnMCcuXG4gICAgICAgIGlmICh2YWx1ZSA9PT0gJycgfHwgdmFsdWUgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiB2YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmxlYWRpbmdaZXJvICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLmxlYWRpbmdaZXJvLmtlZXApIHtcbiAgICAgICAgICAgIGlmIChOdW1iZXIodmFsdWUpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgLy8gUmV0dXJuICcwJyBpZiB0aGUgdmFsdWUgaXMgemVyb1xuICAgICAgICAgICAgICAgIHJldHVybiAnMCc7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFRyaW0gdGhlIGxlYWRpbmcgemVyb3MsIHdoaWxlIGxlYXZpbmcgb25lIHplcm8gdG8gdGhlIGxlZnQgb2YgdGhlIGRlY2ltYWwgcG9pbnQgaWYgbmVlZGVkXG4gICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoL14oLSk/MCsoPz1cXGQpL2csJyQxJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvL1RPRE8gcmVtb3ZlIHRoaXMgZnJvbSB0aGF0IGZ1bmN0aW9uIGFuZCB1c2UgYHRyaW1QYWRkZWRaZXJvc0Zyb21EZWNpbWFsUGxhY2VzKClgIGluc3RlYWRcbiAgICAgICAgLy8gVHJpbSB0aGUgdHJhaWxpbmcgemVyb3MgYWZ0ZXIgdGhlIGxhc3QgZGVjaW1hbCBwbGFjZSBub3QgYmVpbmcgYSB6ZXJvIChpZS4gMS4yMzAwIC0+IDEuMjMpXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyh2YWx1ZSwgJy4nKSkge1xuICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKC8oXFwuWzAtOV0qPykwKyQvLCAnJDEnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlbW92ZSBhbnkgdHJhaWxpbmcgZGVjaW1hbCBwb2ludFxuICAgICAgICB2YWx1ZSA9IHZhbHVlLnJlcGxhY2UoL1xcLiQvLCAnJyk7XG5cbiAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIHRoZSBuYW1lIGZvciB0aGUgcGVyc2lzdGVudCBzdG9yZWQgZGF0YSB2YXJpYWJsZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NldFBlcnNpc3RlbnRTdG9yYWdlTmFtZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZG9tRWxlbWVudC5uYW1lICE9PSAnJyAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQodGhpcy5kb21FbGVtZW50Lm5hbWUpKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yYXdWYWx1ZVN0b3JhZ2VOYW1lID0gYCR7dGhpcy5zdG9yYWdlTmFtZVByZWZpeH0ke2RlY29kZVVSSUNvbXBvbmVudCh0aGlzLmRvbUVsZW1lbnQubmFtZSl9YDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5yYXdWYWx1ZVN0b3JhZ2VOYW1lID0gYCR7dGhpcy5zdG9yYWdlTmFtZVByZWZpeH0ke3RoaXMuZG9tRWxlbWVudC5pZH1gO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2F2ZSB0aGUgcmF3IFZhbHVlIGludG8gc2Vzc2lvblN0b3JhZ2Ugb3IgYSBjb29raWUgZGVwZW5kaW5nIG9uIHdoYXQgdGhlIGJyb3dzZXIgaXMgc3VwcG9ydGluZy5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zYXZlVmFsdWVUb1BlcnNpc3RlbnRTdG9yYWdlKCkge1xuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5zYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXNzaW9uU3RvcmFnZUF2YWlsYWJsZSkge1xuICAgICAgICAgICAgICAgIHNlc3Npb25TdG9yYWdlLnNldEl0ZW0odGhpcy5yYXdWYWx1ZVN0b3JhZ2VOYW1lLCB0aGlzLnJhd1ZhbHVlKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gVXNlIGNvb2tpZXMgZm9yIG9ic29sZXRlIGJyb3dzZXJzIHRoYXQgZG8gbm90IHN1cHBvcnQgc2Vzc2lvblN0b3JhZ2UgKGllLiBJRSA2ICYgNylcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5jb29raWUgPSBgJHt0aGlzLnJhd1ZhbHVlU3RvcmFnZU5hbWV9PSR7dGhpcy5yYXdWYWx1ZX07IGV4cGlyZXM9IDsgcGF0aD0vYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHJpZXZlIHRoZSByYXcgdmFsdWUgZnJvbSBzZXNzaW9uU3RvcmFnZSBvciB0aGUgY29va2llIGRlcGVuZGluZyBvbiB3aGF0IHRoZSBicm93c2VyIGlzIHN1cHBvcnRpbmcuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9nZXRWYWx1ZUZyb21QZXJzaXN0ZW50U3RvcmFnZSgpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSkge1xuICAgICAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgICAgIGlmICh0aGlzLnNlc3Npb25TdG9yYWdlQXZhaWxhYmxlKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gc2Vzc2lvblN0b3JhZ2UuZ2V0SXRlbSh0aGlzLnJhd1ZhbHVlU3RvcmFnZU5hbWUpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLl9yZWFkQ29va2llKHRoaXMucmF3VmFsdWVTdG9yYWdlTmFtZSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKCdgX2dldFZhbHVlRnJvbVBlcnNpc3RlbnRTdG9yYWdlKClgIGlzIGNhbGxlZCBidXQgYHNldHRpbmdzLnNhdmVWYWx1ZVRvU2Vzc2lvblN0b3JhZ2VgIGlzIGZhbHNlLiBUaGVyZSBtdXN0IGJlIGFuIGVycm9yIHRoYXQgbmVlZHMgZml4aW5nLicsIHRoaXMuc2V0dGluZ3Muc2hvd1dhcm5pbmdzKTtcblxuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIHJhdyB2YWx1ZSBkYXRhIGZyb20gc2Vzc2lvblN0b3JhZ2Ugb3IgdGhlIGNvb2tpZSBkZXBlbmRpbmcgb24gd2hhdCB0aGUgYnJvd3NlciBpcyBzdXBwb3J0aW5nLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3JlbW92ZVZhbHVlRnJvbVBlcnNpc3RlbnRTdG9yYWdlKCkge1xuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5zYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXNzaW9uU3RvcmFnZUF2YWlsYWJsZSkge1xuICAgICAgICAgICAgICAgIHNlc3Npb25TdG9yYWdlLnJlbW92ZUl0ZW0odGhpcy5yYXdWYWx1ZVN0b3JhZ2VOYW1lKTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZGF0ZSA9IG5ldyBEYXRlKCk7XG4gICAgICAgICAgICAgICAgZGF0ZS5zZXRUaW1lKGRhdGUuZ2V0VGltZSgpIC0gODY0MDAwMDApOyAvLyAtODY0MDAwMDAgPT09IC0xICogMjQgKiA2MCAqIDYwICogMTAwMFxuICAgICAgICAgICAgICAgIGNvbnN0IGV4cGlyZXMgPSBgOyBleHBpcmVzPSR7ZGF0ZS50b1VUQ1N0cmluZygpfWA7XG4gICAgICAgICAgICAgICAgZG9jdW1lbnQuY29va2llID0gYCR7dGhpcy5yYXdWYWx1ZVN0b3JhZ2VOYW1lfT0nJyA7JHtleHBpcmVzfTsgcGF0aD0vYDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yICdmb2N1c2luJyBhbmQgJ21vdXNlZW50ZXInIGV2ZW50c1xuICAgICAqIE9uIGZvY3VzaW4sIG11bHRpcGxlIHRoaW5ncyBoYXBwZW5zIDpcbiAgICAgKiAtIElmIGBBbHRgIGlzIHByZXNzZWQsIHVuZm9ybWF0XG4gICAgICogLSBSZW1vdmUgdGhlIHNlcGFyYXRvcnMgaWYgYHNob3dPbmx5TnVtYmVyc09uRm9jdXNgIGlzIHNldFxuICAgICAqIC0gRGVwZW5kaW5nIG9uIGBlbXB0eUlucHV0QmVoYXZpb3JgLCByZWZvcm1hdCB0aGUgZW1wdHkgZm9ybWF0dGVkIHZhbHVlXG4gICAgICogLSBEaXNwbGF5IHRoZSBjb3JyZWN0IG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyAob24gZm9jdXMvYmx1cilcbiAgICAgKiAtIFBsYWNlIHRoZSBjYXJldCBjb3JyZWN0bHkgaWYgdGhlIGVsZW1lbnQgaXMgZW1wdHlcbiAgICAgKlxuICAgICAqIE5vdGU6IE9uIGZvY3VzaW4sIHRoZSBgcmF3VmFsdWVgIGlzIG5ldmVyIGNoYW5nZWQuIE9ubHkgdGhlIGZvcm1hdHRlZCB2YWx1ZSBjYW4gYmUgbW9kaWZpZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfb25Gb2N1c0luQW5kTW91c2VFbnRlcihlKSB7XG4gICAgICAgIHRoaXMuaXNFZGl0aW5nID0gZmFsc2U7IC8vIEp1c3QgaW4gY2FzZSBubyBga2V5VXBgIGV2ZW50IGhhdmUgYmVlbiBzZW50IChpZiB0aGUgdXNlciBsb3N0IHRoZSBmb2N1cyB0byB0aGUgd2luZG93IHdoaWxlIHR5cGluZylcblxuICAgICAgICAvL1RPRE8gYEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRWYWx1ZWAgaXMgY2FsbGVkIDMgdGltZXMgc2VxdWVudGlhbGx5IGhlcmUsIGZpeCB0aGF0XG4gICAgICAgIC8vVE9ETyBDcmVhdGUgc2VwYXJhdGUgaGFuZGxlcnMgZm9yIHRoZSBmb2N1cyBhbmQgbW91c2VlbnRlciBldmVudHNcbiAgICAgICAgY29uc3QgaW5pdGlhbEVsZW1lbnRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICBcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MudW5mb3JtYXRPbkhvdmVyICYmIGUudHlwZSA9PT0gJ21vdXNlZW50ZXInICYmIGUuYWx0S2V5KSB7XG4gICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl91bmZvcm1hdEFsdEhvdmVyZWQodGhpcyk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChlLnR5cGUgPT09ICdmb2N1cycpIHsgLy9UT0RPIE1vdmUgdGhhdCBiYWNrIHRvIHRoZSAnZm9jdXMnIGV2ZW50IGhhbmRsZXIgd2hlbiB0aGUgc2VwYXJhdGlvbiBiZXR3ZWVuIHRoZSAnZm9jdXMnIGFuZCAnbW91c2VlbnRlcicgaGFuZGxlciB3aWxsIGJlIGRvbmVcbiAgICAgICAgICAgIC8vIFdlIGtlZXAgdHJhY2sgaWYgdGhlIGVsZW1lbnQgaXMgY3VycmVudGx5IGZvY3VzZWRcbiAgICAgICAgICAgIHRoaXMuaXNGb2N1c2VkID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChlLnR5cGUgPT09ICdmb2N1cycgJiYgdGhpcy5zZXR0aW5ncy51bmZvcm1hdE9uSG92ZXIgJiYgdGhpcy5ob3ZlcmVkV2l0aEFsdCkge1xuICAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fcmVmb3JtYXRBbHRIb3ZlcmVkKHRoaXMpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGUudHlwZSA9PT0gJ2ZvY3VzJyB8fCBlLnR5cGUgPT09ICdtb3VzZWVudGVyJyAmJiAhdGhpcy5pc0ZvY3VzZWQpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvciA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IuZm9jdXMgJiZcbiAgICAgICAgICAgICAgICB0aGlzLnJhd1ZhbHVlIDwgMCAmJiB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyICE9PSBudWxsICYmIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyICE9PSAnJykgeyAvL0ZJWE1FIHRoaXMgaXMgY2FsbGVkIGEgc2Vjb25kIHRpbWUgaW4gX2FkZEdyb3VwU2VwYXJhdG9ycyB0b28uIFByZXZlbnQgdGhpcywgaWYgcG9zc2libGUuXG4gICAgICAgICAgICAgICAgLy8gT25seSByZW1vdmUgdGhlIGJyYWNrZXRzIGlmIHRoZSB2YWx1ZSBpcyBuZWdhdGl2ZVxuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQsIHRoaXMuY29uc3RydWN0b3IuX3JlbW92ZUJyYWNrZXRzKEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpLCB0aGlzLnNldHRpbmdzKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFVzZSB0aGUgcmF3VmFsdWUsIG11bHRpcGxpZWQgYnkgYHJhd1ZhbHVlRGl2aXNvcmAgaWYgZGVmaW5lZFxuICAgICAgICAgICAgY29uc3QgcmF3VmFsdWVUb0Zvcm1hdCA9IHRoaXMuX2dldFJhd1ZhbHVlVG9Gb3JtYXQodGhpcy5yYXdWYWx1ZSk7XG5cbiAgICAgICAgICAgIC8vIE1vZGlmeSB0aGUgZWxlbWVudCB2YWx1ZSBhY2NvcmRpbmcgdG8gdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0byBzaG93IG9uIGZvY3VzIG9yIHRoZSBgc2hvd09ubHlOdW1iZXJzT25Gb2N1c2Agb3B0aW9uXG4gICAgICAgICAgICBpZiAocmF3VmFsdWVUb0Zvcm1hdCAhPT0gJycpIHtcbiAgICAgICAgICAgICAgICAvLyBSb3VuZCB0aGUgZ2l2ZW4gdmFsdWUgYWNjb3JkaW5nIHRvIHRoZSBvYmplY3Qgc3RhdGUgKGZvY3VzL3VuZm9jdXNlZClcbiAgICAgICAgICAgICAgICBsZXQgcm91bmRlZFZhbHVlO1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzRm9jdXNlZCkge1xuICAgICAgICAgICAgICAgICAgICByb3VuZGVkVmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9yb3VuZEZvcm1hdHRlZFZhbHVlU2hvd25PbkZvY3VzKHJhd1ZhbHVlVG9Gb3JtYXQsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJvdW5kZWRWYWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uQmx1cihyYXdWYWx1ZVRvRm9ybWF0LCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5zaG93T25seU51bWJlcnNPbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnNob3dPbmx5TnVtYmVyc09uRm9jdXMub25seU51bWJlcnMpIHtcbiAgICAgICAgICAgICAgICAgICAgLy9UT0RPIFVzZSBhIGB0aGlzLnNldHRpbmdzT3ZlcnJpZGVgIG9iamVjdCBpbnN0ZWFkIG9mIG1vZGlmeWluZyB0aGUgYHRoaXMuc2V0dGluZ3NgIG9iamVjdFxuICAgICAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3IgPSAnJztcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCAgICAgID0gJyc7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dCAgICAgICAgICA9ICcnO1xuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50LCByb3VuZGVkVmFsdWUucmVwbGFjZSgnLicsIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlcikpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGxldCBmb3JtYXR0ZWRWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChyb3VuZGVkVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBmb3JtYXR0ZWRWYWx1ZSA9ICcnO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgZm9ybWF0dGVkVmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9hZGRHcm91cFNlcGFyYXRvcnMocm91bmRlZFZhbHVlLnJlcGxhY2UoJy4nLCB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpLCB0aGlzLnNldHRpbmdzLCB0aGlzLmlzRm9jdXNlZCwgcmF3VmFsdWVUb0Zvcm1hdCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCwgZm9ybWF0dGVkVmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gSW4gb3JkZXIgdG8gc2VuZCBhICduYXRpdmUnIGNoYW5nZSBldmVudCB3aGVuIGJsdXJyaW5nIHRoZSBpbnB1dCwgd2UgbmVlZCB0byBmaXJzdCBzdG9yZSB0aGUgaW5pdGlhbCBpbnB1dCB2YWx1ZSBvbiBmb2N1cy5cbiAgICAgICAgICAgIHRoaXMudmFsdWVPbkZvY3VzID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKGUudGFyZ2V0KTtcbiAgICAgICAgICAgIHRoaXMubGFzdFZhbCA9IHRoaXMudmFsdWVPbkZvY3VzO1xuICAgICAgICAgICAgY29uc3QgaXNFbXB0eVZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5faXNFbGVtZW50VmFsdWVFbXB0eU9yT25seVRoZU5lZ2F0aXZlU2lnbih0aGlzLnZhbHVlT25Gb2N1cywgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgICAgICBjb25zdCBvcmRlcmVkVmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9vcmRlclZhbHVlQ3VycmVuY3lTeW1ib2xBbmRTdWZmaXhUZXh0KHRoaXMudmFsdWVPbkZvY3VzLCB0aGlzLnNldHRpbmdzLCB0cnVlKTsgLy8gVGhpcyBkaXNwbGF5cyB0aGUgY3VycmVuY3kgc2lnbiBvbiBob3ZlciBldmVuIGlmIHRoZSByYXdWYWx1ZSBpcyBlbXB0eVxuICAgICAgICAgICAgaWYgKChpc0VtcHR5VmFsdWUgJiYgb3JkZXJlZFZhbHVlICE9PSAnJykgJiYgdGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLmZvY3VzKSB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCwgb3JkZXJlZFZhbHVlKTtcblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZXJlIGlzIGEgY3VycmVuY3kgc3ltYm9sIGFuZCBpdHMgb24gdGhlIHJpZ2h0IGhhbmQgc2lkZSwgdGhlbiB3ZSBwbGFjZSB0aGUgY2FyZXQgYWNjb3JkaW5nbHkgb24gdGhlIGZhciBsZWZ0IHNpZGVcbiAgICAgICAgICAgICAgICBpZiAob3JkZXJlZFZhbHVlID09PSB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sICYmIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4KSB7XG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24oZS50YXJnZXQsIDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KSAhPT0gaW5pdGlhbEVsZW1lbnRWYWx1ZSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5mb3JtYXR0ZWQsIHRoaXMuZG9tRWxlbWVudCwgeyBvbGRWYWx1ZTogaW5pdGlhbEVsZW1lbnRWYWx1ZSwgbmV3VmFsdWU6IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpIH0pO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlciBmb3IgdGhlICdmb2N1cycgZXZlbnQuXG4gICAgICogV2UgdXBkYXRlIHRoZSBpbmZvIG9mIHRoZSBmb2N1c2VkIHN0YXRlIGluIHRoZSBgdGhpcy5pc0ZvY3VzZWRgIHZhcmlhYmxlIHdoZW4gdGhlIGVsZW1lbnQgZ2V0cyBmb2N1c2VkLlxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX29uRm9jdXMoKSB7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmlzQ2FuY2VsbGFibGUpIHtcbiAgICAgICAgICAgIC8vIFNhdmUgdGhlIGN1cnJlbnQgdW5mb3JtYXR0ZWQgdmFsdWUgZm9yIGxhdGVyIHVzZSBieSB0aGUgJ2NhbmNlbGxhYmxlJyBmZWF0dXJlXG4gICAgICAgICAgICB0aGlzLl9zYXZlQ2FuY2VsbGFibGVWYWx1ZSgpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlciBmb3IgdGhlICdmb2N1c2luJyBldmVudC5cbiAgICAgKiBUaGlzIGlzIGNhbGxlZCBiZWZvcmUgdGhlICdmb2N1cycgZXZlbnQsIGFuZCBpcyBuZWNlc3NhcnkgdG8gY2hhbmdlIHRoZSBzZWxlY3Rpb24gb24gZm9jdXMgdW5kZXIgRmlyZWZveCBmb3IgaW5zdGFuY2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfb25Gb2N1c0luKGUpIHtcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc2VsZWN0T25Gb2N1cykge1xuICAgICAgICAgICAgLy8gVGhlIHdob2xlIGlucHV0IGNvbnRlbnQgaXMgc2VsZWN0ZWQgb24gZm9jdXMgKGZvbGxvd2luZyB0aGUgYHNlbGVjdE9uRm9jdXNgIGFuZCBgc2VsZWN0TnVtYmVyT25seWAgb3B0aW9ucylcbiAgICAgICAgICAgIC8vWFhYIEZpcmVmb3ggPDQ3IGRvZXMgbm90IHJlc3BlY3QgdGhpcyBzZWxlY3Rpb24uLi5PaCB3ZWxsLlxuICAgICAgICAgICAgdGhpcy5zZWxlY3QoKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIE9yIHdlIGRlY2lkZSB3aGVyZSB0byBwdXQgdGhlIGNhcmV0IHVzaW5nIHRoZSBgY2FyZXRQb3NpdGlvbk9uRm9jdXNgIG9wdGlvblxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCwgdGhpcy5faW5pdGlhbENhcmV0UG9zaXRpb24oQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCkpKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yICdrZXlkb3duJyBldmVudHMuXG4gICAgICogVGhlIHVzZXIganVzdCBzdGFydGVkIHB1c2hpbmcgYW55IGtleSwgaGVuY2Ugb25lIGV2ZW50IGlzIHNlbnQuXG4gICAgICpcbiAgICAgKiBOb3RlIDpcbiAgICAgKiBCeSBkZWZhdWx0IGEgJ25vcm1hbCcgaW5wdXQgb3V0cHV0IHRob3NlIGV2ZW50cyBpbiB0aGUgcmlnaHQgb3JkZXIgd2hlbiBpbnB1dHRpbmcgYSBjaGFyYWN0ZXIga2V5IChpZS4gJ2EnKSA6XG4gICAgICogLSBrZXlkb3duXG4gICAgICogLSBrZXlwcmVzc1xuICAgICAqIC0gaW5wdXRcbiAgICAgKiAtIGtleXVwXG4gICAgICpcbiAgICAgKiAuLi53aGVuIGlucHV0dGluZyBhIG1vZGlmaWVyIGtleSAoaWUuICdjdHJsJykgOlxuICAgICAqIC0ga2V5ZG93blxuICAgICAqIC0ga2V5dXBcbiAgICAgKlxuICAgICAqIElmICdkZWxldGUnIG9yICdiYWNrc3BhY2UnIGlzIGVudGVyZWQsIHRoZSBmb2xsb3dpbmcgZXZlbnRzIGFyZSBzZW50IDpcbiAgICAgKiAtIGtleWRvd25cbiAgICAgKiAtIGlucHV0XG4gICAgICogLSBrZXl1cFxuICAgICAqXG4gICAgICogSWYgJ2VudGVyJyBpcyBlbnRlcmVkIGFuZCB0aGUgdmFsdWUgaGFzIG5vdCBjaGFuZ2VkLCB0aGUgZm9sbG93aW5nIGV2ZW50cyBhcmUgc2VudCA6XG4gICAgICogLSBrZXlkb3duXG4gICAgICogLSBrZXlwcmVzc1xuICAgICAqIC0ga2V5dXBcbiAgICAgKlxuICAgICAqIElmICdlbnRlcicgaXMgZW50ZXJlZCBhbmQgdGhlIHZhbHVlIGhhcyBiZWVuIGNoYW5nZWQsIHRoZSBmb2xsb3dpbmcgZXZlbnRzIGFyZSBzZW50IDpcbiAgICAgKiAtIGtleWRvd25cbiAgICAgKiAtIGtleXByZXNzXG4gICAgICogLSBjaGFuZ2VcbiAgICAgKiAtIGtleXVwXG4gICAgICpcbiAgICAgKiBXaGVuIGEgcGFzdGUgaXMgZG9uZSwgdGhlIGZvbGxvd2luZyBldmVudHMgYXJlIHNlbnQgOlxuICAgICAqIC0gaW5wdXQgKGlmIHBhc3RlIGlzIGRvbmUgd2l0aCB0aGUgbW91c2UpXG4gICAgICpcbiAgICAgKiAtIGtleWRvd24gKGlmIHBhc3RlIGlzIGRvbmUgd2l0aCBjdHJsK3YpXG4gICAgICogLSBrZXlkb3duXG4gICAgICogLSBpbnB1dFxuICAgICAqIC0ga2V5dXBcbiAgICAgKiAtIGtleXVwXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0tleWJvYXJkRXZlbnR9IGVcbiAgICAgKi9cbiAgICBfb25LZXlkb3duKGUpIHtcbiAgICAgICAgdGhpcy5pc0VkaXRpbmcgPSB0cnVlOyAvLyBLZWVwIHRyYWNrIGlmIHRoZSB1c2VyIGlzIGN1cnJlbnRseSBlZGl0aW5nIHRoZSBlbGVtZW50IG1hbnVhbGx5XG5cbiAgICAgICAgaWYgKCF0aGlzLmlzRm9jdXNlZCAmJiB0aGlzLnNldHRpbmdzLnVuZm9ybWF0T25Ib3ZlciAmJiBlLmFsdEtleSAmJiB0aGlzLmRvbUVsZW1lbnQgPT09IEF1dG9OdW1lcmljSGVscGVyLmdldEhvdmVyZWRFbGVtZW50KCkpIHtcbiAgICAgICAgICAgIC8vIEhlcmUgSSBwcmV2ZW50IGNhbGxpbmcgX3VuZm9ybWF0QWx0SG92ZXJlZCBpZiB0aGUgZWxlbWVudCBpcyBhbHJlYWR5IGZvY3VzZWQsIHNpbmNlIHRoZSBnbG9iYWwgJ2tleWRvd24nIGxpc3RlbmVyIHdpbGwgcGljayBpdCB1cCBhcyB3ZWxsXG4gICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl91bmZvcm1hdEFsdEhvdmVyZWQodGhpcyk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3VwZGF0ZUV2ZW50S2V5SW5mbyhlKTtcbiAgICAgICAgdGhpcy5pbml0aWFsVmFsdWVPbktleWRvd24gPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUoZS50YXJnZXQpOyAvLyBUaGlzIGlzIG5lZWRlZCBpbiBgb25LZXl1cCgpYCB0byBjaGVjayBpZiB0aGUgdmFsdWUgYXMgY2hhbmdlZCBkdXJpbmcgdGhlIGtleSBwcmVzc1xuXG4gICAgICAgIGlmICh0aGlzLmRvbUVsZW1lbnQucmVhZE9ubHkpIHtcbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc2VkID0gdHJ1ZTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkVzYykge1xuICAgICAgICAgICAgLy9YWFggVGhlIGRlZmF1bHQgJ0VzY2FwZScga2V5IGJlaGF2aW9yIGRpZmZlcnMgYmV0d2VlbiBGaXJlZm94IGFuZCBDaHJvbWUsIEZpcmVmb3ggYWxyZWFkeSBoYXZpbmcgYSBidWlsdC1pbiAnY2FuY2VsbGFibGUtbGlrZScgZmVhdHVyZS4gVGhpcyBpcyB3aHkgd2UgY2FsbCBgZS5wcmV2ZW50RGVmYXVsdCgpYCBoZXJlIGluc3RlYWQgb2YganVzdCB3aGVuIGBpc0NhbmNlbGxhYmxlYCBpcyBzZXQgdG8gYHRydWVgLiBUaGlzIGFsbG93IHVzIHRvIGtlZXAgdGhlIHNhbWUgYmVoYXZpb3IgYWNyb3NzIGJyb3dzZXJzLlxuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5pc0NhbmNlbGxhYmxlKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIHVzZXIgd2FudHMgdG8gY2FuY2VsIGl0cyBtb2RpZmljYXRpb25zIDpcbiAgICAgICAgICAgICAgICAvLyBXZSBzZXQgYmFjayB0aGUgc2F2ZWQgdmFsdWVcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5yYXdWYWx1ZSAhPT0gdGhpcy5zYXZlZENhbmNlbGxhYmxlVmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRG8gbm90IHNldCB0aGUgdmFsdWUgYWdhaW4gaWYgaXQgaGFzIG5vdCBjaGFuZ2VkXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0KHRoaXMuc2F2ZWRDYW5jZWxsYWJsZVZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgLy8gQW5kIHdlIG5lZWQgdG8gc2VuZCBhbiAnaW5wdXQnIGV2ZW50IHdoZW4gc2V0dGluZyBiYWNrIHRoZSBpbml0aWFsIHZhbHVlIGluIG9yZGVyIHRvIG1ha2Ugb3RoZXIgc2NyaXB0cyBhd2FyZSBvZiB0aGUgdmFsdWUgY2hhbmdlLi4uXG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubmF0aXZlLmlucHV0LCBlLnRhcmdldCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyAuLmFuZCBsYXN0bHkgd2UgdXBkYXRlIHRoZSBjYXJldCBzZWxlY3Rpb24sIGV2ZW4gaWYgdGhlIG9wdGlvbiBgaXNDYW5jZWxsYWJsZWAgaXMgZmFsc2VcbiAgICAgICAgICAgIHRoaXMuc2VsZWN0KCk7XG4gICAgICAgICAgICAvL1RPRE8gQWRkIGFuIG9wdGlvbiB0byBzZWxlY3QgZWl0aGVyIHRoZSBpbnRlZ2VyIG9yIGRlY2ltYWwgcGFydCB3aXRoIGBFc2NgXG4gICAgICAgIH1cblxuICAgICAgICAvLyBUaGUgXCJlbnRlclwiIGtleSB0aHJvd3MgYSBgY2hhbmdlYCBldmVudCBpZiB0aGUgdmFsdWUgaGFzIGNoYW5nZWQgc2luY2UgdGhlIGBmb2N1c2AgZXZlbnRcbiAgICAgICAgbGV0IHRhcmdldFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKGUudGFyZ2V0KTtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkVudGVyICYmIHRoaXMudmFsdWVPbkZvY3VzICE9PSB0YXJnZXRWYWx1ZSkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5uYXRpdmUuY2hhbmdlLCBlLnRhcmdldCk7XG4gICAgICAgICAgICB0aGlzLnZhbHVlT25Gb2N1cyA9IHRhcmdldFZhbHVlO1xuXG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5pc0NhbmNlbGxhYmxlKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgdGhlIHVzZXIgYWN0aXZhdGVkIHRoZSAnY2FuY2VsbGFibGUnIGZlYXR1cmUsIHdlIHNhdmUgdGhlIHZhbGlkYXRlZCB2YWx1ZSB3aGVuICdFbnRlcicgaXMgaGl0XG4gICAgICAgICAgICAgICAgdGhpcy5fc2F2ZUNhbmNlbGxhYmxlVmFsdWUoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuX3VwZGF0ZUludGVybmFsUHJvcGVydGllcyhlKTtcblxuICAgICAgICBpZiAodGhpcy5fcHJvY2Vzc05vblByaW50YWJsZUtleXNBbmRTaG9ydGN1dHMoZSkpIHtcbiAgICAgICAgICAgIHRoaXMucHJvY2Vzc2VkID0gdHJ1ZTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGtleSBpcyBhIGRlbGV0ZS9iYWNrc3BhY2Uga2V5XG4gICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5CYWNrc3BhY2UgfHwgdGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuRGVsZXRlKSB7XG4gICAgICAgICAgICB0aGlzLl9wcm9jZXNzQ2hhcmFjdGVyRGVsZXRpb24oKTsgLy8gQmVjYXVzZSBiYWNrc3BhY2UgYW5kIGRlbGV0ZSBvbmx5IHRyaWdnZXJzIGtleWRvd24gYW5kIGtleXVwIGV2ZW50cywgbm90IGtleXByZXNzXG4gICAgICAgICAgICB0aGlzLnByb2Nlc3NlZCA9IHRydWU7XG4gICAgICAgICAgICB0aGlzLl9mb3JtYXRWYWx1ZShlKTtcblxuICAgICAgICAgICAgLy8gSWYgYW5kIG9ubHkgaWYgdGhlIHJlc3VsdGluZyB2YWx1ZSBoYXMgY2hhbmdlZCBhZnRlciB0aGF0IGJhY2tzcGFjZS9kZWxldGUsIHRoZW4gd2UgaGF2ZSB0byBzZW5kIGFuICdpbnB1dCcgZXZlbnQgbGlrZSBicm93c2VycyBub3JtYWxseSBkby5cbiAgICAgICAgICAgIHRhcmdldFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKGUudGFyZ2V0KTsgLy8gVXBkYXRlIHRoZSB2YWx1ZSBzaW5jZSBpdCBjb3VsZCBoYXZlIGJlZW4gY2hhbmdlZCBkdXJpbmcgdGhlIGRlbGV0aW9uXG4gICAgICAgICAgICBpZiAoKHRhcmdldFZhbHVlICE9PSB0aGlzLmxhc3RWYWwpICYmIHRoaXMudGhyb3dJbnB1dCkge1xuICAgICAgICAgICAgICAgIC8vIFRocm93IGFuIGlucHV0IGV2ZW50IHdoZW4gYSBjaGFyYWN0ZXIgZGVsZXRpb24gaXMgZGV0ZWN0ZWRcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLm5hdGl2ZS5pbnB1dCwgZS50YXJnZXQpO1xuICAgICAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQoKTsgLy8gLi4uYW5kIGltbWVkaWF0ZWx5IHByZXZlbnQgdGhlIGJyb3dzZXIgdG8gZGVsZXRlIGEgc2Vjb25kIGNoYXJhY3RlclxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmxhc3RWYWwgPSB0YXJnZXRWYWx1ZTtcbiAgICAgICAgICAgIHRoaXMudGhyb3dJbnB1dCA9IHRydWU7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIHRoaXMuZm9ybWF0dGVkID0gZmFsc2U7IC8vVE9ETyBJcyB0aGlzIGxpbmUgbmVlZGVkPyAoSSBtZWFuLCBfZm9ybWF0VmFsdWUgYWx3YXlzIHNldCBpdCB0byBgdHJ1ZWAsIGFuZCB0aGlzIG92ZXJ3cml0ZSB0aGF0IGluZm8pXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlciBmb3IgJ2tleXByZXNzJyBldmVudHMuXG4gICAgICogVGhlIHVzZXIgaXMgc3RpbGwgcHJlc3NpbmcgdGhlIGtleSwgd2hpY2ggd2lsbCBvdXRwdXQgYSBjaGFyYWN0ZXIgKGllLiAnMicpIGNvbnRpbnVvdXNseSB1bnRpbCBpdCByZWxlYXNlcyB0aGUga2V5LlxuICAgICAqIE5vdGU6ICdrZXlwcmVzcycgZXZlbnRzIGFyZSBub3Qgc2VudCBmb3IgZGVsZXRlIGtleXMgbGlrZSBCYWNrc3BhY2UvRGVsZXRlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtLZXlib2FyZEV2ZW50fSBlXG4gICAgICovXG4gICAgX29uS2V5cHJlc3MoZSkge1xuICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuSW5zZXJ0KSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBwcm9jZXNzZWQgPSB0aGlzLnByb2Nlc3NlZDtcbiAgICAgICAgdGhpcy5fdXBkYXRlSW50ZXJuYWxQcm9wZXJ0aWVzKGUpO1xuXG4gICAgICAgIGlmICh0aGlzLl9wcm9jZXNzTm9uUHJpbnRhYmxlS2V5c0FuZFNob3J0Y3V0cyhlKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHByb2Nlc3NlZCkge1xuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBpc0NoYXJhY3Rlckluc2VydGlvbkFsbG93ZWQgPSB0aGlzLl9wcm9jZXNzQ2hhcmFjdGVySW5zZXJ0aW9uKCk7XG4gICAgICAgIGlmIChpc0NoYXJhY3Rlckluc2VydGlvbkFsbG93ZWQpIHtcbiAgICAgICAgICAgIHRoaXMuX2Zvcm1hdFZhbHVlKGUpO1xuICAgICAgICAgICAgY29uc3QgdGFyZ2V0VmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUoZS50YXJnZXQpO1xuICAgICAgICAgICAgaWYgKCh0YXJnZXRWYWx1ZSAhPT0gdGhpcy5sYXN0VmFsKSAmJiB0aGlzLnRocm93SW5wdXQpIHtcbiAgICAgICAgICAgICAgICAvLyBUaHJvd3MgaW5wdXQgZXZlbnQgb24gYWRkaW5nIGEgY2hhcmFjdGVyXG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5uYXRpdmUuaW5wdXQsIGUudGFyZ2V0KTtcbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7IC8vIC4uLmFuZCBpbW1lZGlhdGVseSBwcmV2ZW50IHRoZSBicm93c2VyIHRvIGFkZCBhIHNlY29uZCBjaGFyYWN0ZXJcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKCh0aGlzLmV2ZW50S2V5ID09PSB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIgfHwgdGhpcy5ldmVudEtleSA9PT0gdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUpICYmXG4gICAgICAgICAgICAgICAgICAgIChBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50U2VsZWN0aW9uKGUudGFyZ2V0KS5zdGFydCA9PT0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCkuZW5kKSAmJlxuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50U2VsZWN0aW9uKGUudGFyZ2V0KS5zdGFydCA9PT0gdGFyZ2V0VmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHBvc2l0aW9uID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCkuc3RhcnQgKyAxO1xuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50U2VsZWN0aW9uKGUudGFyZ2V0LCBwb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLmxhc3RWYWwgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUoZS50YXJnZXQpO1xuICAgICAgICAgICAgdGhpcy50aHJvd0lucHV0ID0gdHJ1ZTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuXG4gICAgICAgIHRoaXMuZm9ybWF0dGVkID0gZmFsc2U7IC8vVE9ETyBJcyB0aGlzIGxpbmUgbmVlZGVkPyAoSSBtZWFuLCBfZm9ybWF0VmFsdWUgYWx3YXlzIHNldCBpdCB0byBgdHJ1ZWAsIGFuZCB0aGlzIG92ZXJ3cml0ZSB0aGF0IGluZm8pXG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlciBmb3IgJ2lucHV0JyBldmVudHMuXG4gICAgICogSGFuZGxpbmcgdGhpcyBldmVudCBpbnN0ZWFkIG9mIGBrZXlwcmVzc2AgaXMgbmVlZGVkIGluIG9yZGVyIHRvIHN1cHBvcnQgYW5kcm9pZCBkZXZpY2VzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqL1xuICAgIF9vbklucHV0KGUpIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KTtcblxuICAgICAgICAvLyBGaXggdGhlIGNhcmV0IHBvc2l0aW9uIG9uIGtleXVwIGluIHRoZSBgX2Zvcm1hdFZhbHVlKClgIGZ1bmN0aW9uXG4gICAgICAgIHRoaXMuYW5kcm9pZFNlbGVjdGlvblN0YXJ0ID0gbnVsbDtcblxuICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQW5kcm9pZERlZmF1bHQpIHtcbiAgICAgICAgICAgIGxldCBzZWxlY3Rpb24gPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50U2VsZWN0aW9uKHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgICAgICAvLyBUaGUga2V5Q29kZSBpcyBlcXVhbCB0byB0aGUgZGVmYXVsdCBBbmRyb2lkIENocm9tZSBvbmUgKHdoaWNoIGlzIGFsd2F5cyBlcXVhbCB0byBga2V5Q29kZS5BbmRyb2lkRGVmYXVsdGApXG4gICAgICAgICAgICBpZiAodmFsdWUubGVuZ3RoID4gdGhpcy5sYXN0VmFsLmxlbmd0aCB8fCB2YWx1ZS5sZW5ndGggPj0gdGhpcy5sYXN0VmFsLmxlbmd0aCAtIHNlbGVjdGlvbi5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAvLyBEZXRlcm1pbmUgdGhlIGtleWNvZGUgb2YgdGhlIGNoYXJhY3RlciB0aGF0IHdhcyBlbnRlcmVkLCBhbmQgb3ZlcndyaXRlIHRoZSBmYXVsdHkgYGV2ZW50S2V5Q29kZWAgaW5mbyB3aXRoIGl0XG4gICAgICAgICAgICAgICAgdGhpcy5ldmVudEtleSA9IHZhbHVlLmNoYXJDb2RlQXQoc2VsZWN0aW9uLnN0YXJ0KTtcblxuICAgICAgICAgICAgICAgIC8vIENhcHR1cmUgdGhlIGFjdHVhbCBjaGFyYWN0ZXIgZW50ZXJlZCwgYW5kIHVwZGF0ZSB0aGUgYGV2ZW50S2V5YCB3aXRoIGl0IChpbnN0ZWFkIG9mIHRoZSBBbmRyb2lkIGRlZmF1bHQgb25lKVxuICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRLZXkgPSB2YWx1ZS5jaGFyQXQoc2VsZWN0aW9uLnN0YXJ0KTtcblxuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSBnaXZlbiBjaGFyYWN0ZXIgc2hvdWxkIGJlIGluc2VydGVkLCBhbmQgaWYgc28sIGRvIGluc2VydCBpdCBpbnRvIHRoZSBjdXJyZW50IGVsZW1lbnQgdmFsdWVcbiAgICAgICAgICAgICAgICBjb25zdCBpc0NoYXJhY3Rlckluc2VydGlvbkFsbG93ZWQgPSB0aGlzLl9wcm9jZXNzQ2hhcmFjdGVySW5zZXJ0aW9uKCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoaXNDaGFyYWN0ZXJJbnNlcnRpb25BbGxvd2VkKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIEFsbG93ZWQgY2hhcmFjdGVyIGVudGVyZWQgKG51bWJlciwgZGVjaW1hbCBvciBwbHVzL21pbnVzIHNpZ24pXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2Zvcm1hdFZhbHVlKGUpO1xuXG4gICAgICAgICAgICAgICAgICAgIHNlbGVjdGlvbiA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRTZWxlY3Rpb24odGhpcy5kb21FbGVtZW50KTsgLy9UT0RPIGlzIHRoaXMgbmVlZGVkIGEgc2Vjb25kIHRpbWU/XG4gICAgICAgICAgICAgICAgICAgIC8vIENhcHR1cmUgdGhlIG5ldyBjYXJldCBwb3NpdGlvbi4gVGhpcyBpcyByZXF1aXJlZCBiZWNhdXNlIG9uIGtleXVwLCBgX3VwZGF0ZUF1dG9OdW1lcmljSG9sZGVyRXZlbnRLZXljb2RlKClgIGNhcHR1cmVzIHRoZSBvbGQgY2FyZXQgcG9zaXRpb25cbiAgICAgICAgICAgICAgICAgICAgLy9UT0RPIENoZWNrIGlmIHRoaXMgaXMgYW4gQW5kcm9pZCBidWcgb3IgYW4gYXV0b051bWVyaWMgb25lXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYW5kcm9pZFNlbGVjdGlvblN0YXJ0ID0gc2VsZWN0aW9uLnN0YXJ0O1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIE1vdmUgdGhlIGNhcmV0IHRvIHRoZSByaWdodCBpZiB0aGUgYGFuZHJvaWRDaGFyRW50ZXJlZGAgaXMgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIG9yIGlmIGl0J3Mgb24gdGhlIGxlZnQgb2YgdGhlIGNhcmV0IHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGRlY2ltYWxDaGFyYWN0ZXJQb3NpdGlvbiA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpLmluZGV4T2YodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgaGFzRGVjaW1hbENoYXJhY3RlciA9IGRlY2ltYWxDaGFyYWN0ZXJQb3NpdGlvbiAhPT0gLTE7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgIGhhc0RlY2ltYWxDaGFyYWN0ZXIgJiYgZGVjaW1hbENoYXJhY3RlclBvc2l0aW9uIDwgdGhpcy5hbmRyb2lkU2VsZWN0aW9uU3RhcnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYW5kcm9pZFNlbGVjdGlvblN0YXJ0ICs9IHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlci5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXggJiYgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuYW5kcm9pZFNlbGVjdGlvblN0YXJ0ICs9IHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHNlbGVjdGlvbi5sZW5ndGggPiB2YWx1ZS5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFBvc2l0aW9uIHRoZSBjYXJldCByaWdodCBub3cgYmVmb3JlIHRoZSAna2V5dXAnIGV2ZW50IGluIG9yZGVyIHRvIHByZXZlbnQgdGhlIGNhcmV0IGZyb20ganVtcGluZyBhcm91bmRcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldENhcmV0UG9zaXRpb24odGhpcy5hbmRyb2lkU2VsZWN0aW9uU3RhcnQpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdGhpcy5sYXN0VmFsID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCk7XG5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBlbnRlcmVkIGNoYXJhY3RlciBpcyBub3QgYWxsb3dlZCA7IG92ZXJ3cml0ZSB0aGUgbmV3IGludmFsaWQgdmFsdWUgd2l0aCB0aGUgcHJldmlvdXMgdmFsaWQgb25lLCBhbmQgc2V0IGJhY2sgdGhlIGNhcmV0L3NlbGVjdGlvblxuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50VmFsdWUodGhpcy5sYXN0VmFsKTsgLy9UT0RPIFVwZGF0ZSB0aGUgcmF3VmFsdWUgaGVyZSB0b28gdmlhIF9zZXRWYWx1ZSgpP1xuICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50U2VsZWN0aW9uKHRoaXMuZG9tRWxlbWVudCwgc2VsZWN0aW9uLnN0YXJ0LCBzZWxlY3Rpb24uZW5kKTtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5hbmRyb2lkU2VsZWN0aW9uU3RhcnQgPSBzZWxlY3Rpb24uc3RhcnQ7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOyAvL1RPRE8gQ2hlY2sgaG93IHRoYXQgaXMgYWZmZWN0aW5nIHRoZSBub3JtYWwgdHJpZ2dlciBvZiB0aGUgaW5wdXQgZXZlbnRcblxuICAgICAgICAgICAgICAgIHRoaXMuZm9ybWF0dGVkID0gZmFsc2U7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIENoYXJhY3RlciBkZWxldGVkXG4gICAgICAgICAgICAgICAgLy9YWFggVGhlIGNoYW5nZSBpbiBsZW5ndGggY291bGQgYWxzbyBiZSB0aGUgcmVzdWx0IG9mIHRoZSBgRGVsZXRlYCBrZXksIGJ1dCB0aGVyZSB1c3VhbGx5IGFyZSBubyBzdWNoIGtleSBpbiB0aGUgQW5kcm9pZCB2aXJ0dWFsIGtleWJvYXJkc1xuICAgICAgICAgICAgICAgIHRoaXMuZXZlbnRLZXkgPSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5CYWNrc3BhY2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVyIGZvciAna2V5dXAnIGV2ZW50cy5cbiAgICAgKiBUaGUgdXNlciBqdXN0IHJlbGVhc2VkIGFueSBrZXksIGhlbmNlIG9uZSBldmVudCBpcyBzZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtLZXlib2FyZEV2ZW50fSBlXG4gICAgICovXG4gICAgX29uS2V5dXAoZSkge1xuICAgICAgICB0aGlzLmlzRWRpdGluZyA9IGZhbHNlO1xuXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmlzQ2FuY2VsbGFibGUgJiYgdGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuRXNjKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgdXNlciB3YW50cyB0byBjYW5jZWwgaXRzIG1vZGlmaWNhdGlvbnMsIHdlIGRyb3AgdGhlICdrZXl1cCcgZXZlbnQgZm9yIHRoZSBFc2Mga2V5XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE1hbmFnZSB0aGUgdW5kby9yZWRvIGV2ZW50c1xuICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuWiB8fCB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS56KSB7XG4gICAgICAgICAgICBpZiAoZS5jdHJsS2V5ICYmIGUuc2hpZnRLZXkpIHtcbiAgICAgICAgICAgICAgICAvLyBSZWRvXG4gICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgIHRoaXMuX2hpc3RvcnlUYWJsZVJlZG8oKTtcbiAgICAgICAgICAgICAgICB0aGlzLm9uR29pbmdSZWRvID0gdHJ1ZTtcblxuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoZS5jdHJsS2V5ICYmICFlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMub25Hb2luZ1JlZG8pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUHJldmVudCBhbiAndW5kbycgdG8gYmUgbGF1bmNoIHdoZW4gcmVsZWFzaW5nIHRoZSBzaGlmdCBrZXkgYmVmb3JlIHRoZSBjdHJsIGtleSBhZnRlciBhICdyZWRvJyBzaG9ydGN1dFxuICAgICAgICAgICAgICAgICAgICB0aGlzLm9uR29pbmdSZWRvID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgICAgICAgICAvLyBVbmRvXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX2hpc3RvcnlUYWJsZVVuZG8oKTtcblxuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMub25Hb2luZ1JlZG8gJiYgKGUuY3RybEtleSB8fCBlLnNoaWZ0S2V5KSkge1xuICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlIHdoZXJlIGlmIHRoZSB1c2VyIGhhcyBlbnRlcmVkIGBDb250cm9sK1NoaWZ0K3pgLCB0aGVuIHJlbGVhc2UgYHpgLCBrZWVwaW5nIGBDb250cm9sYCBvciBgU2hpZnRgIHByZXNzZWQsIHRoZW4gYHRoaXMub25Hb2luZ1JlZG9gIGlzIG5ldmVyIGNoYW5nZWQgYmFjayB0byBgZmFsc2VgIHdoZW4gdGhlIHVzZXIgcmVsZWFzZSBgQ29udHJvbGAgb3IgYFNoaWZ0YFxuICAgICAgICAgICAgdGhpcy5vbkdvaW5nUmVkbyA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTWFuYWdlIHRoZSByZWZvcm1hdCB3aGVuIGhvdmVyZWQgd2l0aCB0aGUgQWx0IGtleSBwcmVzc2VkXG4gICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5BbHQgJiYgdGhpcy5ob3ZlcmVkV2l0aEFsdCkge1xuICAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fcmVmb3JtYXRBbHRIb3ZlcmVkKHRoaXMpO1xuXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl91cGRhdGVJbnRlcm5hbFByb3BlcnRpZXMoZSk7XG5cbiAgICAgICAgY29uc3Qgc2tpcCA9IHRoaXMuX3Byb2Nlc3NOb25QcmludGFibGVLZXlzQW5kU2hvcnRjdXRzKGUpO1xuICAgICAgICBkZWxldGUgdGhpcy52YWx1ZVBhcnRzQmVmb3JlUGFzdGU7XG4gICAgICAgIGNvbnN0IGlzT25BbmRyb2lkID0gdGhpcy5hbmRyb2lkU2VsZWN0aW9uU3RhcnQgIT09IG51bGw7XG4gICAgICAgIGNvbnN0IHRhcmdldFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKGUudGFyZ2V0KTtcbiAgICAgICAgaWYgKHNraXAgJiYgIWlzT25BbmRyb2lkIHx8IHRhcmdldFZhbHVlID09PSAnJykge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkZWQgdG8gcHJvcGVybHkgcGxhY2UgdGhlIGNhcmV0IHdoZW4gb25seSB0aGUgY3VycmVuY3kgc2lnbiBpcyBwcmVzZW50XG4gICAgICAgIGlmICh0YXJnZXRWYWx1ZSA9PT0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCkge1xuICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4KSB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuc2V0RWxlbWVudFNlbGVjdGlvbihlLnRhcmdldCwgMCk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24oZS50YXJnZXQsIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5UYWIpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24oZS50YXJnZXQsIDAsIHRhcmdldFZhbHVlLmxlbmd0aCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoKHRhcmdldFZhbHVlID09PSB0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQpIHx8XG4gICAgICAgICAgICAodGhpcy5yYXdWYWx1ZSA9PT0gJycgJiYgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCAhPT0gJycgJiYgdGhpcy5zZXR0aW5ncy5zdWZmaXhUZXh0ICE9PSAnJykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24oZS50YXJnZXQsIDApO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gU2F2ZXMgdGhlIGV4dGVuZGVkIGRlY2ltYWwgdG8gcHJlc2VydmUgdGhlIGRhdGEgd2hlbiBuYXZpZ2F0aW5nIGF3YXkgZnJvbSB0aGUgcGFnZVxuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzICE9PSBudWxsKSB7XG4gICAgICAgICAgICB0aGlzLl9zYXZlVmFsdWVUb1BlcnNpc3RlbnRTdG9yYWdlKCk7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIXRoaXMuZm9ybWF0dGVkKSB7ICAvL1RPRE8gSXMgdGhpcyBsaW5lIG5lZWRlZD8gQ29uc2lkZXJpbmcgdGhhdCBvbktleWRvd24gYW5kIG9uS2V5cHJlc3MgYm90aCBmaW5pc2ggYnkgc2V0dGluZyBpdCB0byBmYWxzZS4uLlxuICAgICAgICAgICAgdGhpcy5fZm9ybWF0VmFsdWUoZSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiB0aGUgaW5wdXQgdmFsdWUgaGFzIGNoYW5nZWQgZHVyaW5nIHRoZSBrZXkgcHJlc3MgZXZlbnQgY2hhaW4sIGFuIGV2ZW50IGlzIHNlbnQgdG8gYWxlcnQgdGhhdCBhIGZvcm1hdHRpbmcgaGFzIGJlZW4gZG9uZSAoY2YuIElzc3VlICMxODcpXG4gICAgICAgIGlmICh0YXJnZXRWYWx1ZSAhPT0gdGhpcy5pbml0aWFsVmFsdWVPbktleWRvd24pIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMuZm9ybWF0dGVkLCBlLnRhcmdldCwgeyBvbGRWYWx1ZTogdGhpcy5pbml0aWFsVmFsdWVPbktleWRvd24sIG5ld1ZhbHVlOiB0YXJnZXRWYWx1ZSB9KTsgLy9UT0RPIERvIEkgbmVlZCB0byByZW1vdmUgdGhpcyBzaW5jZSB3ZSBub3cgc2VuZCB0aGlzIGV2ZW50IG9uIGBzZXQoKWA/XG4gICAgICAgIH1cblxuICAgICAgICAvLyBVcGRhdGUgdGhlIHNlbGVjdGlvbiBvZiB0aGUgY3VycmVudCBlbGVtZW50IG9mIHRoZSBoaXN0b3J5IHRhYmxlXG4gICAgICAgIGlmICh0aGlzLmhpc3RvcnlUYWJsZS5sZW5ndGggPiAxKSB7XG4gICAgICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50U2VsZWN0aW9uKHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgICAgICB0aGlzLnNlbGVjdGlvblN0YXJ0ID0gc2VsZWN0aW9uLnN0YXJ0O1xuICAgICAgICAgICAgdGhpcy5zZWxlY3Rpb25FbmQgPSBzZWxlY3Rpb24uZW5kO1xuICAgICAgICAgICAgdGhpcy5oaXN0b3J5VGFibGVbdGhpcy5oaXN0b3J5VGFibGVJbmRleF0uc3RhcnQgPSB0aGlzLnNlbGVjdGlvblN0YXJ0O1xuICAgICAgICAgICAgdGhpcy5oaXN0b3J5VGFibGVbdGhpcy5oaXN0b3J5VGFibGVJbmRleF0uZW5kID0gdGhpcy5zZWxlY3Rpb25FbmQ7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVyIGZvciAnZm9jdXNvdXQnIGV2ZW50c1xuICAgICAqIE9uIGZvY3Vzb3V0LCBtdWx0aXBsZSB0aGluZ3MgaGFwcGVucyA6XG4gICAgICogLSBUaGUgZWxlbWVudCB2YWx1ZSBpcyBmb3JtYXR0ZWQgYmFjayBpZiB0aGUgYEFsdGAga2V5IHdhcyBwcmVzc2VkLFxuICAgICAqIC0gVGhlIGVsZW1lbnQgdmFsdWUgaXMgZm9ybWF0dGVkIGJhY2sgaWYgYHNob3dPbmx5TnVtYmVyc09uRm9jdXNgIHdhcyBzZXQgdG8gb25seSBzaG93IG51bWJlcnMsXG4gICAgICogLSBUaGUgZWxlbWVudCB2YWx1ZSBpcyBtdWx0aXBsaWVkIGJ5IGByYXdWYWx1ZURpdmlzb3JgIG9uIGBibHVyYFxuICAgICAqXG4gICAgICogTm90ZTogT24gZm9jdXNvdXQsIHRoZSBgcmF3VmFsdWVgIGlzIG5ldmVyIGNoYW5nZWQuIE9ubHkgdGhlIGZvcm1hdHRlZCB2YWx1ZSBjYW4gYmUgbW9kaWZpZWQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0V2ZW50fSBlXG4gICAgICovXG4gICAgX29uRm9jdXNPdXRBbmRNb3VzZUxlYXZlKGUpIHtcbiAgICAgICAgdGhpcy5pc0VkaXRpbmcgPSBmYWxzZTsgLy8gSnVzdCBpbiBjYXNlIG5vIGBrZXlVcGAgZXZlbnQgaGF2ZSBiZWVuIHNlbnQgKGlmIHRoZSB1c2VyIGxvc3QgdGhlIGZvY3VzIHRvIHRoZSB3aW5kb3cgd2hpbGUgdHlwaW5nKVxuXG4gICAgICAgIC8vVE9ETyBDcmVhdGUgc2VwYXJhdGUgaGFuZGxlcnMgZm9yIGJsdXIgYW5kIG1vdXNlbGVhdmVcbiAgICAgICAgLy9GSVhNRSBEbyBub3QgY2FsbCBgc2V0KClgIGlmIHRoZSBjdXJyZW50IHJhdyB2YWx1ZSBpcyB0aGUgc2FtZSBhcyB0aGUgb25lIHdlIGFyZSB0cnlpbmcgdG8gc2V0IChjdXJyZW50bHksIG9uIGZvY3VzIG91dCwgYHNldCgpYCBpcyBhbHdheXMgY2FsbGVkLCBldmVuIGlmIHRoZSB2YWx1ZSBoYXMgbm90IGNoYW5nZWRcbiAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MudW5mb3JtYXRPbkhvdmVyICYmIGUudHlwZSA9PT0gJ21vdXNlbGVhdmUnICYmIHRoaXMuaG92ZXJlZFdpdGhBbHQpIHtcbiAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IuX3JlZm9ybWF0QWx0SG92ZXJlZCh0aGlzKTtcblxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKChlLnR5cGUgPT09ICdtb3VzZWxlYXZlJyAmJiAhdGhpcy5pc0ZvY3VzZWQpIHx8IGUudHlwZSA9PT0gJ2JsdXInKSB7XG4gICAgICAgICAgICB0aGlzLl9zYXZlVmFsdWVUb1BlcnNpc3RlbnRTdG9yYWdlKCk7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5zaG93T25seU51bWJlcnNPbkZvY3VzID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLnNob3dPbmx5TnVtYmVyc09uRm9jdXMub25seU51bWJlcnMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3IgPSB0aGlzLm9yaWdpbmFsRGlnaXRHcm91cFNlcGFyYXRvcjtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sID0gdGhpcy5vcmlnaW5hbEN1cnJlbmN5U3ltYm9sO1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dCA9IHRoaXMub3JpZ2luYWxTdWZmaXhUZXh0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBVc2UgdGhlIHJhd1ZhbHVlLCBtdWx0aXBsaWVkIGJ5IGByYXdWYWx1ZURpdmlzb3JgIGlmIGRlZmluZWRcbiAgICAgICAgICAgIGNvbnN0IHJhd1ZhbHVlVG9Gb3JtYXQgPSB0aGlzLl9nZXRSYXdWYWx1ZVRvRm9ybWF0KHRoaXMucmF3VmFsdWUpO1xuXG4gICAgICAgICAgICBsZXQgdmFsdWU7XG4gICAgICAgICAgICBjb25zdCBpc1Jhd1ZhbHVlTnVsbCA9IEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChyYXdWYWx1ZVRvRm9ybWF0KTtcbiAgICAgICAgICAgIGlmIChpc1Jhd1ZhbHVlTnVsbCB8fCByYXdWYWx1ZVRvRm9ybWF0ID09PSAnJykge1xuICAgICAgICAgICAgICAgIHZhbHVlID0gcmF3VmFsdWVUb0Zvcm1hdDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdmFsdWUgPSBTdHJpbmcocmF3VmFsdWVUb0Zvcm1hdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChyYXdWYWx1ZVRvRm9ybWF0ICE9PSAnJyAmJiAhaXNSYXdWYWx1ZU51bGwpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBbbWluVGVzdCwgbWF4VGVzdF0gPSB0aGlzLmNvbnN0cnVjdG9yLl9jaGVja0lmSW5SYW5nZVdpdGhPdmVycmlkZU9wdGlvbihyYXdWYWx1ZVRvRm9ybWF0LCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgICAgICAgICBpZiAobWluVGVzdCAmJiBtYXhUZXN0ICYmICF0aGlzLmNvbnN0cnVjdG9yLl9pc0VsZW1lbnRWYWx1ZUVtcHR5T3JPbmx5VGhlTmVnYXRpdmVTaWduKHJhd1ZhbHVlVG9Gb3JtYXQsIHRoaXMuc2V0dGluZ3MpKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5fbW9kaWZ5TmVnYXRpdmVTaWduQW5kRGVjaW1hbENoYXJhY3RlckZvclJhd1ZhbHVlKHZhbHVlKTtcblxuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5kaXZpc29yV2hlblVuZm9jdXNlZCAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKHZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWUgPSB2YWx1ZSAvIHRoaXMuc2V0dGluZ3MuZGl2aXNvcldoZW5VbmZvY3VzZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHZhbHVlLnRvU3RyaW5nKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICB2YWx1ZSA9IHRoaXMuY29uc3RydWN0b3IuX3JvdW5kRm9ybWF0dGVkVmFsdWVTaG93bk9uQmx1cih2YWx1ZSwgdGhpcy5zZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fbW9kaWZ5TmVnYXRpdmVTaWduQW5kRGVjaW1hbENoYXJhY3RlckZvckZvcm1hdHRlZFZhbHVlKHZhbHVlLCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICBpZiAoIW1pblRlc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubWluUmFuZ2VFeGNlZWRlZCwgdGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBpZiAoIW1heFRlc3QpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubWF4UmFuZ2VFeGNlZWRlZCwgdGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSBpZiAocmF3VmFsdWVUb0Zvcm1hdCA9PT0gJycgJiYgdGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLnplcm8pIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRSYXdWYWx1ZSgnMCcpO1xuICAgICAgICAgICAgICAgIHZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fcm91bmRWYWx1ZSgnMCcsIHRoaXMuc2V0dGluZ3MsIDApO1xuICAgICAgICAgICAgfVxuXG5cbiAgICAgICAgICAgIGxldCBncm91cGVkVmFsdWUgPSB0aGlzLmNvbnN0cnVjdG9yLl9vcmRlclZhbHVlQ3VycmVuY3lTeW1ib2xBbmRTdWZmaXhUZXh0KHZhbHVlLCB0aGlzLnNldHRpbmdzLCBmYWxzZSk7XG4gICAgICAgICAgICBpZiAoISh0aGlzLmNvbnN0cnVjdG9yLl9pc0VsZW1lbnRWYWx1ZUVtcHR5T3JPbmx5VGhlTmVnYXRpdmVTaWduKHZhbHVlLCB0aGlzLnNldHRpbmdzKSB8fFxuICAgICAgICAgICAgICAgIChpc1Jhd1ZhbHVlTnVsbCAmJiB0aGlzLnNldHRpbmdzLmVtcHR5SW5wdXRCZWhhdmlvciA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubnVsbCkpKSB7XG4gICAgICAgICAgICAgICAgZ3JvdXBlZFZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fYWRkR3JvdXBTZXBhcmF0b3JzKHZhbHVlLCB0aGlzLnNldHRpbmdzLCBmYWxzZSwgcmF3VmFsdWVUb0Zvcm1hdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFRlc3RpbmcgZm9yIGBhbGxvd0RlY2ltYWxQYWRkaW5nLm5ldmVyYCBvciBgYWxsb3dEZWNpbWFsUGFkZGluZy5mbG9hdHNgIGlzIG5lZWRlZCB0byBtYWtlIHN1cmUgd2UgZG8gbm90IGtlZXAgYSB0cmFpbGluZyBkZWNpbWFsQ2hhcmFjdGVyIChsaWtlICc1MDAuJykgaW4gdGhlIGVsZW1lbnQsIHNpbmNlIHRoZSByYXcgdmFsdWUgd291bGQgc3RpbGwgYmUgYSBjb3JyZWN0bHkgZm9ybWF0dGVkIGludGVnZXIgKCc1MDAnKVxuICAgICAgICAgICAgaWYgKGdyb3VwZWRWYWx1ZSAhPT0gcmF3VmFsdWVUb0Zvcm1hdCB8fFxuICAgICAgICAgICAgICAgIHJhd1ZhbHVlVG9Gb3JtYXQgPT09ICcnIHx8IC8vIFRoaXMgbWFrZSBzdXJlIHdlIGdldCByaWQgb24gYW55IGN1cnJlbmN5IHN5bWJvbCBvciBzdWZmaXggdGhhdCBtaWdodCBoYXZlIGJlZW4gYWRkZWQgb24gZm9jdXNcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmFsbG93RGVjaW1hbFBhZGRpbmcgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZy5uZXZlciB8fFxuICAgICAgICAgICAgICAgIHRoaXMuc2V0dGluZ3MuYWxsb3dEZWNpbWFsUGFkZGluZyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nLmZsb2F0cykge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLnN5bWJvbFdoZW5VbmZvY3VzZWQgJiYgcmF3VmFsdWVUb0Zvcm1hdCAhPT0gJycgJiYgcmF3VmFsdWVUb0Zvcm1hdCAhPT0gbnVsbCkge1xuICAgICAgICAgICAgICAgICAgICBncm91cGVkVmFsdWUgPSBgJHtncm91cGVkVmFsdWV9JHt0aGlzLnNldHRpbmdzLnN5bWJvbFdoZW5VbmZvY3VzZWR9YDtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50VmFsdWUoZ3JvdXBlZFZhbHVlKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGdyb3VwZWRWYWx1ZSAhPT0gdGhpcy52YWx1ZU9uRm9jdXMpIHtcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLm5hdGl2ZS5jaGFuZ2UsIHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgZGVsZXRlIHRoaXMudmFsdWVPbkZvY3VzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICB0aGlzLl9vbkJsdXIoZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVyIGZvciAncGFzdGUnIGV2ZW50XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0V2ZW50fENsaXBib2FyZEV2ZW50fSBlXG4gICAgICovXG4gICAgX29uUGFzdGUoZSkge1xuICAgICAgICAvL1RPRE8gVXNpbmcgY3RybCt6IGFmdGVyIGEgcGFzdGUgc2hvdWxkIGNhbmNlbCBpdCAtPiBIb3cgd291bGQgdGhhdCBhZmZlY3Qgb3RoZXIgZnJhbWV3b3Jrcy9jb21wb25lbnQgYnVpbHQgd2l0aCB0aGF0IGZlYXR1cmUgaW4gbWluZCB0aG91Z2g/XG4gICAgICAgIC8vRklYTUUgV2hlbiBwYXN0aW5nICcwMDAnIG9uIGEgdGhvdXNhbmQgZ3JvdXAgc2VsZWN0aW9uLCB0aGUgd2hvbGUgc2VsZWN0aW9uIGdldHMgZGVsZXRlZCwgYW5kIG9ubHkgb25lICcwJyBpcyBwYXN0ZWQgKGNmLiBpc3N1ZSAjMzAyKVxuICAgICAgICAvLyBUaGUgZXZlbnQgaXMgcHJldmVudGVkIGJ5IGRlZmF1bHQsIHNpbmNlIG90aGVyd2lzZSB0aGUgdXNlciB3b3VsZCBiZSBhYmxlIHRvIHBhc3RlIGludmFsaWQgY2hhcmFjdGVycyBpbnRvIHRoZSBpbnB1dFxuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICAgICAgbGV0IHJhd1Bhc3RlZFRleHQ7XG4gICAgICAgIGlmICh3aW5kb3cuY2xpcGJvYXJkRGF0YSAmJiB3aW5kb3cuY2xpcGJvYXJkRGF0YS5nZXREYXRhKSB7XG4gICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2UgZm9yIHRoZSBvYnNvbGV0ZSBhbmQgbm9uLXN0YW5kYXJkIElFIGJyb3dzZXJzIDEwIGFuZCAxMVxuICAgICAgICAgICAgcmF3UGFzdGVkVGV4dCA9IHdpbmRvdy5jbGlwYm9hcmREYXRhLmdldERhdGEoJ1RleHQnKTtcbiAgICAgICAgfSBlbHNlIGlmIChlLmNsaXBib2FyZERhdGEgJiYgZS5jbGlwYm9hcmREYXRhLmdldERhdGEpIHtcbiAgICAgICAgICAgIC8vIE5vcm1hbCBjYXNlIHdpdGggbW9kZXJuIGJyb3dzZXJzXG4gICAgICAgICAgICByYXdQYXN0ZWRUZXh0ID0gZS5jbGlwYm9hcmREYXRhLmdldERhdGEoJ3RleHQvcGxhaW4nKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoJ1VuYWJsZSB0byByZXRyaWV2ZSB0aGUgcGFzdGVkIHZhbHVlLiBQbGVhc2UgdXNlIGEgbW9kZXJuIGJyb3dzZXIgKGllLiBGaXJlZm94IG9yIENocm9taXVtKS4nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDAuIFNwZWNpYWwgY2FzZSBpZiB0aGUgdXNlciBoYXMgc2VsZWN0ZWQgYWxsIHRoZSBpbnB1dCB0ZXh0IGJlZm9yZSBwYXN0aW5nXG4gICAgICAgIGNvbnN0IGluaXRpYWxGb3JtYXR0ZWRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZShlLnRhcmdldCk7XG4gICAgICAgIGNvbnN0IHNlbGVjdGlvblN0YXJ0ID0gZS50YXJnZXQuc2VsZWN0aW9uU3RhcnQgfHwgMDtcbiAgICAgICAgY29uc3Qgc2VsZWN0aW9uRW5kID0gZS50YXJnZXQuc2VsZWN0aW9uRW5kIHx8IDA7XG4gICAgICAgIGNvbnN0IHNlbGVjdGlvblNpemUgPSBzZWxlY3Rpb25FbmQgLSBzZWxlY3Rpb25TdGFydDtcbiAgICAgICAgbGV0IGlzQWxsSW5wdXRUZXh0U2VsZWN0ZWQgPSBmYWxzZTtcblxuICAgICAgICBpZiAoc2VsZWN0aW9uU2l6ZSA9PT0gaW5pdGlhbEZvcm1hdHRlZFZhbHVlLmxlbmd0aCkge1xuICAgICAgICAgICAgaXNBbGxJbnB1dFRleHRTZWxlY3RlZCA9IHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyAxLiBDaGVjayBpZiB0aGUgcGFzdGUgaGFzIGEgbmVnYXRpdmUgc2lnbiAob25seSBpZiBpdCdzIHRoZSBmaXJzdCBjaGFyYWN0ZXIpLCBhbmQgc3RvcmUgdGhhdCBpbmZvcm1hdGlvbiBmb3IgbGF0ZXIgdXNlXG4gICAgICAgIGNvbnN0IGlzUGFzdGVOZWdhdGl2ZSA9IEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmVTdHJpY3QocmF3UGFzdGVkVGV4dCk7XG4gICAgICAgIGlmIChpc1Bhc3RlTmVnYXRpdmUpIHtcbiAgICAgICAgICAgIC8vIDFhLiBSZW1vdmUgdGhlIG5lZ2F0aXZlIHNpZ24gZnJvbSB0aGUgcGFzdGVkIHRleHRcbiAgICAgICAgICAgIHJhd1Bhc3RlZFRleHQgPSByYXdQYXN0ZWRUZXh0LnNsaWNlKDEsIHJhd1Bhc3RlZFRleHQubGVuZ3RoKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDIuIFN0cmlwIGFsbCB0aG91c2FuZCBzZXBhcmF0b3JzLCBicmFja2V0cyBhbmQgY3VycmVuY3kgc2lnbiwgYW5kIGNvbnZlcnQgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIHRvIGEgZG90XG4gICAgICAgIGNvbnN0IHVudHJhbnNsYXRlZFBhc3RlZFRleHQgPSB0aGlzLl9wcmVwYXJlUGFzdGVkVGV4dChyYXdQYXN0ZWRUZXh0KTtcblxuICAgICAgICBsZXQgcGFzdGVkVGV4dDtcbiAgICAgICAgaWYgKHVudHJhbnNsYXRlZFBhc3RlZFRleHQgPT09ICcuJykge1xuICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlIDogSWYgdGhlIHVzZXIgdHJpZXMgdG8gcGFzdGUgYSBzaW5nbGUgZGVjaW1hbCBjaGFyYWN0ZXIgKHRoYXQgaGFzIGJlZW4gdHJhbnNsYXRlZCB0byAnLicgYWxyZWFkeSlcbiAgICAgICAgICAgIHBhc3RlZFRleHQgPSAnLic7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBOb3JtYWwgY2FzZVxuICAgICAgICAgICAgLy8gQWxsb3cgcGFzdGluZyBhcmFiaWMgbnVtYmVyc1xuICAgICAgICAgICAgcGFzdGVkVGV4dCA9IEF1dG9OdW1lcmljSGVscGVyLmFyYWJpY1RvTGF0aW5OdW1iZXJzKHVudHJhbnNsYXRlZFBhc3RlZFRleHQsIGZhbHNlLCBmYWxzZSwgZmFsc2UpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gMy4gVGVzdCBpZiB0aGUgcGFzdGUgaXMgdmFsaWQgKG9ubHkgaGFzIG51bWJlcnMgYW5kIGV2ZW50dWFsbHkgYSBkZWNpbWFsIGNoYXJhY3RlcikuIElmIGl0J3Mgbm90IHZhbGlkLCBzdG9wIGhlcmUuXG4gICAgICAgIGlmIChwYXN0ZWRUZXh0ICE9PSAnLicgJiYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcihwYXN0ZWRUZXh0KSB8fCBwYXN0ZWRUZXh0ID09PSAnJykpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm9uSW52YWxpZFBhc3RlID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgLy9UT0RPIFNob3VsZCB3ZSBzZW5kIGEgd2FybmluZyBpbnN0ZWFkIG9mIHRocm93aW5nIGFuIGVycm9yP1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBwYXN0ZWQgdmFsdWUgJyR7cmF3UGFzdGVkVGV4dH0nIGlzIG5vdCBhIHZhbGlkIHBhc3RlIGNvbnRlbnQuYCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDQuIENhbGN1bGF0ZSB0aGUgcGFzdGUgcmVzdWx0XG4gICAgICAgIGxldCBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZztcbiAgICAgICAgbGV0IGluaXRpYWxVbmZvcm1hdHRlZE51bWJlciA9IHRoaXMuZ2V0TnVtZXJpY1N0cmluZygpO1xuICAgICAgICBsZXQgaXNJbml0aWFsVmFsdWVOZWdhdGl2ZSA9IEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmVTdHJpY3QoaW5pdGlhbFVuZm9ybWF0dGVkTnVtYmVyKTtcbiAgICAgICAgbGV0IGlzUGFzdGVOZWdhdGl2ZUFuZEluaXRpYWxWYWx1ZUlzUG9zaXRpdmU7XG4gICAgICAgIGxldCByZXN1bHQ7XG5cbiAgICAgICAgLy8gSWYgdGhlIHBhc3RlZCBjb250ZW50IGlzIG5lZ2F0aXZlLCB0aGVuIHRoZSByZXN1bHQgd2lsbCBiZSBuZWdhdGl2ZSB0b29cbiAgICAgICAgaWYgKGlzUGFzdGVOZWdhdGl2ZSAmJiAhaXNJbml0aWFsVmFsdWVOZWdhdGl2ZSkge1xuICAgICAgICAgICAgaW5pdGlhbFVuZm9ybWF0dGVkTnVtYmVyID0gYC0ke2luaXRpYWxVbmZvcm1hdHRlZE51bWJlcn1gO1xuICAgICAgICAgICAgaXNJbml0aWFsVmFsdWVOZWdhdGl2ZSA9IHRydWU7XG4gICAgICAgICAgICBpc1Bhc3RlTmVnYXRpdmVBbmRJbml0aWFsVmFsdWVJc1Bvc2l0aXZlID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGlzUGFzdGVOZWdhdGl2ZUFuZEluaXRpYWxWYWx1ZUlzUG9zaXRpdmUgPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBsZWZ0UGFydENvbnRhaW5lZEFEb3QgPSBmYWxzZTtcbiAgICAgICAgbGV0IGxlZnRQYXJ0O1xuICAgICAgICBsZXQgcmlnaHRQYXJ0O1xuICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3Mub25JbnZhbGlkUGFzdGUpIHtcbiAgICAgICAgICAgIC8qIDRhLiBUcnVuY2F0ZSBwYXN0ZSBiZWhhdmlvcjpcbiAgICAgICAgICAgICAqIEluc2VydCBhcyBtYW55IG51bWJlcnMgYXMgcG9zc2libGUgb24gdGhlIHJpZ2h0IGhhbmQgc2lkZSBvZiB0aGUgY2FyZXQgZnJvbSB0aGUgcGFzdGVkIHRleHQgY29udGVudCwgdW50aWwgdGhlIGlucHV0IHJlYWNoIGl0cyByYW5nZSBsaW1pdC5cbiAgICAgICAgICAgICAqIElmIHRoZXJlIGlzIG1vcmUgY2hhcmFjdGVycyBpbiB0aGUgY2xpcGJvYXJkIG9uY2UgYSBsaW1pdCBpcyByZWFjaGVkLCBkcm9wIHRoZSBleHRyYW5lb3VzIGNoYXJhY3RlcnMuXG4gICAgICAgICAgICAgKiBPdGhlcndpc2UgcGFzdGUgYWxsIHRoZSBudW1iZXJzIGluIHRoZSBjbGlwYm9hcmQuXG4gICAgICAgICAgICAgKiBXaGlsZSBkb2luZyBzbywgd2UgY2hlY2sgaWYgdGhlIHJlc3VsdCBpcyB3aXRoaW4gdGhlIG1pbmltdW0gYW5kIG1heGltdW0gdmFsdWVzIGFsbG93ZWQsIGFuZCBzdG9wIGFzIHNvb24gYXMgd2UgZW5jb3VudGVyIG9uZSBvZiB0aG9zZS5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiA0Yi4gUmVwbGFjZSBwYXN0ZSBiZWhhdmlvcjpcbiAgICAgICAgICAgICAqIElkZW0gdGhhbiB0aGUgJ3RydW5jYXRlJyBwYXN0ZSBiZWhhdmlvciwgZXhjZXB0IHRoYXQgd2hlbiBhIHJhbmdlIGxpbWl0IGlzIGhpdCwgd2UgdHJ5IHRvIHJlcGxhY2UgdGhlIHN1YnNlcXVlbnQgaW5pdGlhbCBudW1iZXJzIHdpdGggdGhlIHBhc3RlZCBvbmVzLCB1bnRpbCB3ZSBoaXQgdGhlIHJhbmdlIGxpbWl0IGEgc2Vjb25kIChhbmQgbGFzdCkgdGltZSwgb3Igd2UgcnVuIG91dCBvZiBudW1iZXJzIHRvIHBhc3RlXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIC8qIGVzbGludCBuby1jYXNlLWRlY2xhcmF0aW9uczogMCAqL1xuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLnRydW5jYXRlOlxuICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLnJlcGxhY2U6XG4gICAgICAgICAgICAgICAgY29uc3QgbGVmdEZvcm1hdHRlZFBhcnQgPSBpbml0aWFsRm9ybWF0dGVkVmFsdWUuc2xpY2UoMCwgc2VsZWN0aW9uU3RhcnQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJpZ2h0Rm9ybWF0dGVkUGFydCA9IGluaXRpYWxGb3JtYXR0ZWRWYWx1ZS5zbGljZShzZWxlY3Rpb25FbmQsIGluaXRpYWxGb3JtYXR0ZWRWYWx1ZS5sZW5ndGgpO1xuXG4gICAgICAgICAgICAgICAgaWYgKHNlbGVjdGlvblN0YXJ0ICE9PSBzZWxlY3Rpb25FbmQpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gYS4gSWYgdGhlcmUgaXMgYSBzZWxlY3Rpb24sIHJlbW92ZSB0aGUgc2VsZWN0ZWQgcGFydCwgYW5kIHJldHVybiB0aGUgbGVmdCBhbmQgcmlnaHQgcGFydFxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLl9wcmVwYXJlUGFzdGVkVGV4dChsZWZ0Rm9ybWF0dGVkUGFydCArIHJpZ2h0Rm9ybWF0dGVkUGFydCk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gYi4gRWxzZSBpZiB0aGlzIGlzIG9ubHkgb25lIGNhcmV0IChhbmQgdGhlcmVmb3JlIG5vIHNlbGVjdGlvbiksIHRoZW4gcmV0dXJuIHRoZSBsZWZ0IGFuZCByaWdodCBwYXJ0XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuX3ByZXBhcmVQYXN0ZWRUZXh0KGluaXRpYWxGb3JtYXR0ZWRWYWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQWRkIGJhY2sgdGhlIG5lZ2F0aXZlIHNpZ24gaWYgbmVlZGVkXG4gICAgICAgICAgICAgICAgaWYgKGlzSW5pdGlhbFZhbHVlTmVnYXRpdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIuc2V0UmF3TmVnYXRpdmVTaWduKHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQnVpbGQgdGhlIHVuZm9ybWF0dGVkIHJlc3VsdCBzdHJpbmdcbiAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZyA9IEF1dG9OdW1lcmljSGVscGVyLmNvbnZlcnRDaGFyYWN0ZXJDb3VudFRvSW5kZXhQb3NpdGlvbihBdXRvTnVtZXJpY0hlbHBlci5jb3VudE51bWJlckNoYXJhY3RlcnNPblRoZUNhcmV0TGVmdFNpZGUoaW5pdGlhbEZvcm1hdHRlZFZhbHVlLCBzZWxlY3Rpb25TdGFydCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSk7XG4gICAgICAgICAgICAgICAgaWYgKGlzUGFzdGVOZWdhdGl2ZUFuZEluaXRpYWxWYWx1ZUlzUG9zaXRpdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGluaXRpYWwgcGFzdGUgaXMgbmVnYXRpdmUgYW5kIHRoZSBpbml0aWFsIHZhbHVlIGlzIG5vdCwgdGhlbiBJIG11c3Qgb2Zmc2V0IHRoZSBjYXJldCBwb3NpdGlvbiBieSBvbmUgcGxhY2UgdG8gdGhlIHJpZ2h0IHRvIHRha2UgdGhlIGFkZGl0aW9uYWwgaHlwaGVuIGludG8gYWNjb3VudFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZysrO1xuICAgICAgICAgICAgICAgICAgICAvL1RPRE8gUXVpZCBpZiB0aGUgbmVnYXRpdmUgc2lnbiBpcyBub3Qgb24gdGhlIGxlZnQgKG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50IGFuZCBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCk/XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGVmdFBhcnQgPSByZXN1bHQuc2xpY2UoMCwgY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3RpbmcpO1xuICAgICAgICAgICAgICAgIHJpZ2h0UGFydCA9IHJlc3VsdC5zbGljZShjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZywgcmVzdWx0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgaWYgKHBhc3RlZFRleHQgPT09ICcuJykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMobGVmdFBhcnQsICcuJykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIEkgcmVtb3ZlIGEgZG90IGhlcmUsIHRoZW4gSSBuZWVkIHRvIHVwZGF0ZSB0aGUgY2FyZXQgcG9zaXRpb24gKGRlY3JlbWVudCBpdCBieSAxKSB3aGVuIHBvc2l0aW9uaW5nIGl0XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUbyBkbyBzbywgd2Uga2VlcCB0aGF0IGluZm8gaW4gb3JkZXIgdG8gbW9kaWZ5IHRoZSBjYXJldCBwb3NpdGlvbiBsYXRlclxuICAgICAgICAgICAgICAgICAgICAgICAgbGVmdFBhcnRDb250YWluZWRBRG90ID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnRQYXJ0ID0gbGVmdFBhcnQucmVwbGFjZSgnLicsICcnKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBcbiAgICAgICAgICAgICAgICAgICAgcmlnaHRQYXJ0ID0gcmlnaHRQYXJ0LnJlcGxhY2UoJy4nLCAnJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIC0tIEhlcmUsIHdlIGFyZSBnb29kIHRvIGdvIHRvIGNvbnRpbnVlIG9uIHRoZSBzYW1lIGJhc2lzXG5cbiAgICAgICAgICAgICAgICAvLyBjLiBBZGQgbnVtYmVycyBvbmUgYnkgb25lIGF0IHRoZSBjYXJldCBwb3NpdGlvbiwgd2hpbGUgdGVzdGluZyBpZiB0aGUgcmVzdWx0IGlzIHZhbGlkIGFuZCB3aXRoaW4gdGhlIHJhbmdlIG9mIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIHZhbHVlXG4gICAgICAgICAgICAgICAgLy8gICAgQ29udGludWUgdW50aWwgeW91IGVpdGhlciBydW4gb3V0IG9mIG51bWJlcnMgdG8gcGFzdGUsIG9yIHRoYXQgeW91IGdldCBvdXQgb2YgdGhlIHJhbmdlIGxpbWl0c1xuICAgICAgICAgICAgICAgIGNvbnN0IG1pblBhcnNlID0gQXV0b051bWVyaWNIZWxwZXIucGFyc2VTdHIodGhpcy5zZXR0aW5ncy5taW5pbXVtVmFsdWUpO1xuICAgICAgICAgICAgICAgIGNvbnN0IG1heFBhcnNlID0gQXV0b051bWVyaWNIZWxwZXIucGFyc2VTdHIodGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWUpO1xuICAgICAgICAgICAgICAgIGxldCBsYXN0R29vZEtub3duUmVzdWx0ID0gcmVzdWx0OyAvLyBUaGlzIGlzIHNldCBhcyB0aGUgZGVmYXVsdCwgaW4gY2FzZSB3ZSBkbyBub3QgYWRkIGV2ZW4gb25lIG51bWJlclxuICAgICAgICAgICAgICAgIGxldCBwYXN0ZWRUZXh0SW5kZXggPSAwO1xuICAgICAgICAgICAgICAgIGxldCBtb2RpZmllZExlZnRQYXJ0ID0gbGVmdFBhcnQ7XG5cbiAgICAgICAgICAgICAgICB3aGlsZSAocGFzdGVkVGV4dEluZGV4IDwgcGFzdGVkVGV4dC5sZW5ndGgpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gTW9kaWZ5IHRoZSByZXN1bHQgd2l0aCBhbm90aGVyIHBhc3RlZCBjaGFyYWN0ZXJcbiAgICAgICAgICAgICAgICAgICAgbW9kaWZpZWRMZWZ0UGFydCArPSBwYXN0ZWRUZXh0W3Bhc3RlZFRleHRJbmRleF07XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IG1vZGlmaWVkTGVmdFBhcnQgKyByaWdodFBhcnQ7XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgdGhlIHJhbmdlIGxpbWl0c1xuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuY29uc3RydWN0b3IuX2NoZWNrSWZJblJhbmdlKHJlc3VsdCwgbWluUGFyc2UsIG1heFBhcnNlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVGhlIHJlc3VsdCBpcyBvdXQgb2YgdGhlIHJhbmdlIGxpbWl0cywgc3RvcCB0aGUgbG9vcCBoZXJlXG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFNhdmUgdGhlIGxhc3QgZ29vZCBrbm93biByZXN1bHRcbiAgICAgICAgICAgICAgICAgICAgbGFzdEdvb2RLbm93blJlc3VsdCA9IHJlc3VsdDtcblxuICAgICAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGxvY2FsIHZhcmlhYmxlcyBmb3IgdGhlIG5leHQgbG9vcFxuICAgICAgICAgICAgICAgICAgICBwYXN0ZWRUZXh0SW5kZXgrKztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGxhc3QgY2FyZXQgcG9zaXRpb24gd2hlcmUgdG8gaW5zZXJ0IGEgbmV3IG51bWJlclxuICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nICs9IHBhc3RlZFRleHRJbmRleDtcblxuICAgICAgICAgICAgICAgIC8vWFhYIEhlcmUgd2UgaGF2ZSB0aGUgcmVzdWx0IGZvciB0aGUgYHRydW5jYXRlYCBvcHRpb25cbiAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5vbkludmFsaWRQYXN0ZSA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS50cnVuY2F0ZSkge1xuICAgICAgICAgICAgICAgICAgICAvL1RPRE8gSWYgdGhlIHVzZXIgYXMgZGVmaW5lZCBhIHRydW5jYXRlIGNhbGxiYWNrIGFuZCB0aGVyZSBhcmUgc3RpbGwgc29tZSBudW1iZXJzICh0aGF0IHdpbGwgYmUgZHJvcHBlZCksIHRoZW4gY2FsbCB0aGlzIGNhbGxiYWNrIHdpdGggdGhlIGluaXRpYWwgcGFzdGUgYXMgd2VsbCBhcyB0aGUgcmVtYWluaW5nIG51bWJlcnNcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gbGFzdEdvb2RLbm93blJlc3VsdDtcblxuICAgICAgICAgICAgICAgICAgICBpZiAobGVmdFBhcnRDb250YWluZWRBRG90KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGRvdCBoYXMgYmVlbiByZW1vdmVkIGZvciB0aGUgcGFydCBvbiB0aGUgbGVmdCBvZiB0aGUgY2FyZXQsIHdlIGRlY3JlbWVudCB0aGUgY2FyZXQgaW5kZXggcG9zaXRpb25cbiAgICAgICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nLS07XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vWFhYIC4uLmVsc2Ugd2UgbmVlZCB0byBjb250aW51ZSBtb2RpZnlpbmcgdGhlIHJlc3VsdCBmb3IgdGhlICdyZXBsYWNlJyBvcHRpb25cblxuICAgICAgICAgICAgICAgIC8vIGQuIFVudGlsIHRoZXJlIGFyZSBudW1iZXJzIHRvIHBhc3RlLCByZXBsYWNlIHRoZSBpbml0aWFsIG51bWJlcnMgb25lIGJ5IG9uZSwgYW5kIHN0aWxsIGRvIHRoZSByYW5nZSB0ZXN0LlxuICAgICAgICAgICAgICAgIC8vICAgIFN0b3Agd2hlbiB5b3UgaGF2ZSBubyBtb3JlIG51bWJlcnMgdG8gcGFzdGUsIG9yIGlmIHlvdSBhcmUgb3V0IG9mIHRoZSByYW5nZSBsaW1pdHMuXG4gICAgICAgICAgICAgICAgLy8gICAgSWYgeW91IGRvIGdldCB0byB0aGUgcmFuZ2UgbGltaXRzLCB1c2UgdGhlIHByZXZpb3VzIGtub3duIGdvb2QgdmFsdWUgd2l0aGluIHRob3NlIGxpbWl0cy5cbiAgICAgICAgICAgICAgICAvLyAgICBOb3RlOiBUaGUgbnVtYmVycyBhcmUgcmVwbGFjZWQgb25lIGJ5IG9uZSwgaW4gdGhlIGludGVnZXIgdGhlbiBkZWNpbWFsIHBhcnQsIHdoaWxlIGlnbm9yaW5nIHRoZSBkZWNpbWFsIGNoYXJhY3RlclxuICAgICAgICAgICAgICAgIC8vVE9ETyBXaGF0IHNob3VsZCBoYXBwZW4gaWYgdGhlIHVzZXIgdHJ5IHRvIHBhc3RlIGEgZGVjaW1hbCBudW1iZXI/IFNob3VsZCB3ZSBvdmVycmlkZSB0aGUgY3VycmVudCBpbml0aWFsIGRlY2ltYWwgY2hhcmFjdGVyIGluIGZhdm9yIG9mIHRoaXMgbmV3IG9uZT8gSWYgd2UgZG8sIHRoZW4gd2UgaGF2ZSB0byByZWNhbGN1bGF0ZSB0aGUgdk1pbi92TWF4IGZyb20gdGhlIHN0YXJ0IGluIG9yZGVyIHRvIHRha2UgaW50byBhY2NvdW50IHRoaXMgbmV3IGRlY2ltYWwgY2hhcmFjdGVyIHBvc2l0aW9uLi5cbiAgICAgICAgICAgICAgICBsZXQgbGFzdEdvb2RLbm93blJlc3VsdEluZGV4ID0gY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3Rpbmc7XG4gICAgICAgICAgICAgICAgY29uc3QgbGFzdEdvb2RLbm93blJlc3VsdFNpemUgPSBsYXN0R29vZEtub3duUmVzdWx0Lmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIHdoaWxlIChwYXN0ZWRUZXh0SW5kZXggPCBwYXN0ZWRUZXh0Lmxlbmd0aCAmJiBsYXN0R29vZEtub3duUmVzdWx0SW5kZXggPCBsYXN0R29vZEtub3duUmVzdWx0U2l6ZSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAobGFzdEdvb2RLbm93blJlc3VsdFtsYXN0R29vZEtub3duUmVzdWx0SW5kZXhdID09PSAnLicpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFdlIHNraXAgdGhlIGRlY2ltYWwgY2hhcmFjdGVyICdyZXBsYWNlbWVudCcuIFRoYXQgd2F5LCB3ZSBkbyBub3QgY2hhbmdlIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBwb3NpdGlvbiByZWdhcmRpbmcgdGhlIHJlbWFpbmluZyBudW1iZXJzLlxuICAgICAgICAgICAgICAgICAgICAgICAgbGFzdEdvb2RLbm93blJlc3VsdEluZGV4Kys7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoaXMgcmVwbGFjZSBvbmUgY2hhcmFjdGVyIGF0IGEgdGltZVxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0hlbHBlci5yZXBsYWNlQ2hhckF0KGxhc3RHb29kS25vd25SZXN1bHQsIGxhc3RHb29kS25vd25SZXN1bHRJbmRleCwgcGFzdGVkVGV4dFtwYXN0ZWRUZXh0SW5kZXhdKTtcblxuICAgICAgICAgICAgICAgICAgICAvLyBDaGVjayB0aGUgcmFuZ2UgbGltaXRzXG4gICAgICAgICAgICAgICAgICAgIGlmICghdGhpcy5jb25zdHJ1Y3Rvci5fY2hlY2tJZkluUmFuZ2UocmVzdWx0LCBtaW5QYXJzZSwgbWF4UGFyc2UpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGUgcmVzdWx0IGlzIG91dCBvZiB0aGUgcmFuZ2UgbGltaXRzLCBzdG9wIHRoZSBsb29wIGhlcmVcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gU2F2ZSB0aGUgbGFzdCBnb29kIGtub3duIHJlc3VsdFxuICAgICAgICAgICAgICAgICAgICBsYXN0R29vZEtub3duUmVzdWx0ID0gcmVzdWx0O1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFVwZGF0ZSB0aGUgbG9jYWwgdmFyaWFibGVzIGZvciB0aGUgbmV4dCBsb29wXG4gICAgICAgICAgICAgICAgICAgIHBhc3RlZFRleHRJbmRleCsrO1xuICAgICAgICAgICAgICAgICAgICBsYXN0R29vZEtub3duUmVzdWx0SW5kZXgrKztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBVcGRhdGUgdGhlIGxhc3QgY2FyZXQgcG9zaXRpb24gd2hlcmUgdG8gaW5zZXJ0IGEgbmV3IG51bWJlclxuICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nID0gbGFzdEdvb2RLbm93blJlc3VsdEluZGV4O1xuXG4gICAgICAgICAgICAgICAgaWYgKGxlZnRQYXJ0Q29udGFpbmVkQURvdCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBhIGRvdCBoYXMgYmVlbiByZW1vdmVkIGZvciB0aGUgcGFydCBvbiB0aGUgbGVmdCBvZiB0aGUgY2FyZXQsIHdlIGRlY3JlbWVudCB0aGUgY2FyZXQgaW5kZXggcG9zaXRpb25cbiAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3RpbmctLTtcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICByZXN1bHQgPSBsYXN0R29vZEtub3duUmVzdWx0O1xuXG4gICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAvKiA0Yy4gTm9ybWFsIHBhc3RlIGJlaGF2aW9yOlxuICAgICAgICAgICAgICogSW5zZXJ0IHRoZSBwYXN0ZWQgbnVtYmVyIGluc2lkZSB0aGUgY3VycmVudCB1bmZvcm1hdHRlZCB0ZXh0LCBhdCB0aGUgcmlnaHQgY2FyZXQgcG9zaXRpb24gb3Igc2VsZWN0aW9uXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5lcnJvcjpcbiAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5pZ25vcmU6XG4gICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuY2xhbXA6XG4gICAgICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgICAgIC8vIDEuIEdlbmVyYXRlIHRoZSB1bmZvcm1hdHRlZCByZXN1bHRcbiAgICAgICAgICAgICAgICBjb25zdCBsZWZ0Rm9ybWF0dGVkUGFydDIgPSBpbml0aWFsRm9ybWF0dGVkVmFsdWUuc2xpY2UoMCwgc2VsZWN0aW9uU3RhcnQpO1xuICAgICAgICAgICAgICAgIGNvbnN0IHJpZ2h0Rm9ybWF0dGVkUGFydDIgPSBpbml0aWFsRm9ybWF0dGVkVmFsdWUuc2xpY2Uoc2VsZWN0aW9uRW5kLCBpbml0aWFsRm9ybWF0dGVkVmFsdWUubGVuZ3RoKTtcblxuICAgICAgICAgICAgICAgIGlmIChzZWxlY3Rpb25TdGFydCAhPT0gc2VsZWN0aW9uRW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIGEuIElmIHRoZXJlIGlzIGEgc2VsZWN0aW9uLCByZW1vdmUgdGhlIHNlbGVjdGVkIHBhcnQsIGFuZCByZXR1cm4gdGhlIGxlZnQgYW5kIHJpZ2h0IHBhcnRcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gdGhpcy5fcHJlcGFyZVBhc3RlZFRleHQobGVmdEZvcm1hdHRlZFBhcnQyICsgcmlnaHRGb3JtYXR0ZWRQYXJ0Mik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gYi4gRWxzZSBpZiB0aGlzIGlzIG9ubHkgb25lIGNhcmV0IChhbmQgdGhlcmVmb3JlIG5vIHNlbGVjdGlvbiksIHRoZW4gcmV0dXJuIHRoZSBsZWZ0IGFuZCByaWdodCBwYXJ0XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuX3ByZXBhcmVQYXN0ZWRUZXh0KGluaXRpYWxGb3JtYXR0ZWRWYWx1ZSk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQWRkIGJhY2sgdGhlIG5lZ2F0aXZlIHNpZ24gaWYgbmVlZGVkXG4gICAgICAgICAgICAgICAgaWYgKGlzSW5pdGlhbFZhbHVlTmVnYXRpdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNIZWxwZXIuc2V0UmF3TmVnYXRpdmVTaWduKHJlc3VsdCk7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gQnVpbGQgdGhlIHVuZm9ybWF0dGVkIHJlc3VsdCBzdHJpbmdcbiAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZyA9IEF1dG9OdW1lcmljSGVscGVyLmNvbnZlcnRDaGFyYWN0ZXJDb3VudFRvSW5kZXhQb3NpdGlvbihBdXRvTnVtZXJpY0hlbHBlci5jb3VudE51bWJlckNoYXJhY3RlcnNPblRoZUNhcmV0TGVmdFNpZGUoaW5pdGlhbEZvcm1hdHRlZFZhbHVlLCBzZWxlY3Rpb25TdGFydCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSk7XG4gICAgICAgICAgICAgICAgaWYgKGlzUGFzdGVOZWdhdGl2ZUFuZEluaXRpYWxWYWx1ZUlzUG9zaXRpdmUpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGluaXRpYWwgcGFzdGUgaXMgbmVnYXRpdmUgYW5kIHRoZSBpbml0aWFsIHZhbHVlIGlzIG5vdCwgdGhlbiBJIG11c3Qgb2Zmc2V0IHRoZSBjYXJldCBwb3NpdGlvbiBieSBvbmUgcGxhY2UgdG8gdGhlIHJpZ2h0IHRvIHRha2UgdGhlIGFkZGl0aW9uYWwgaHlwaGVuIGludG8gYWNjb3VudFxuICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZysrO1xuICAgICAgICAgICAgICAgICAgICAvL1RPRE8gUXVpZCBpZiB0aGUgbmVnYXRpdmUgc2lnbiBpcyBub3Qgb24gdGhlIGxlZnQgKG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50IGFuZCBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCk/XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgbGVmdFBhcnQgPSByZXN1bHQuc2xpY2UoMCwgY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3RpbmcpO1xuICAgICAgICAgICAgICAgIHJpZ2h0UGFydCA9IHJlc3VsdC5zbGljZShjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZywgcmVzdWx0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgaWYgKHBhc3RlZFRleHQgPT09ICcuJykge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgdXNlciBvbmx5IHBhc3RlIGEgc2luZ2xlIGRlY2ltYWwgY2hhcmFjdGVyLCB0aGVuIHdlIHJlbW92ZSB0aGUgcHJldmlvdXNseSBleGlzdGluZyBvbmUgKGlmIGFueSlcbiAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKGxlZnRQYXJ0LCAnLicpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiBJIHJlbW92ZSBhIGRvdCBoZXJlLCB0aGVuIEkgbmVlZCB0byB1cGRhdGUgdGhlIGNhcmV0IHBvc2l0aW9uIChkZWNyZW1lbnQgaXQgYnkgMSkgd2hlbiBwb3NpdGlvbmluZyBpdFxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gVG8gZG8gc28sIHdlIGtlZXAgdGhhdCBpbmZvIGluIG9yZGVyIHRvIG1vZGlmeSB0aGUgY2FyZXQgcG9zaXRpb24gbGF0ZXJcbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnRQYXJ0Q29udGFpbmVkQURvdCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0UGFydCA9IGxlZnRQYXJ0LnJlcGxhY2UoJy4nLCAnJyk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgcmlnaHRQYXJ0ID0gcmlnaHRQYXJ0LnJlcGxhY2UoJy4nLCAnJyk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIC8vIC0tIEhlcmUsIHdlIGFyZSBnb29kIHRvIGdvIHRvIGNvbnRpbnVlIG9uIHRoZSBzYW1lIGJhc2lzXG5cbiAgICAgICAgICAgICAgICAvLyBHZW5lcmF0ZSB0aGUgdW5mb3JtYXR0ZWQgcmVzdWx0XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gYCR7bGVmdFBhcnR9JHtwYXN0ZWRUZXh0fSR7cmlnaHRQYXJ0fWA7XG5cbiAgICAgICAgICAgICAgICAvLyAyLiBDYWxjdWxhdGUgdGhlIGNhcmV0IHBvc2l0aW9uIGluIHRoZSB1bmZvcm1hdHRlZCB2YWx1ZSwgZm9yIGxhdGVyIHVzZVxuICAgICAgICAgICAgICAgIGlmIChzZWxlY3Rpb25TdGFydCA9PT0gc2VsZWN0aW9uRW5kKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZXJlIGlzIG5vIHNlbGVjdGlvbiwgdGhlbiB0aGUgY2FyZXQgcG9zaXRpb24gaXMgc2V0IGFmdGVyIHRoZSBwYXN0ZWQgdGV4dFxuICAgICAgICAgICAgICAgICAgICBjb25zdCBpbmRleFdoZXJlUGFzdGVkVGV4dEhhc0JlZW5JbnNlcnRlZCA9IEF1dG9OdW1lcmljSGVscGVyLmNvbnZlcnRDaGFyYWN0ZXJDb3VudFRvSW5kZXhQb3NpdGlvbihBdXRvTnVtZXJpY0hlbHBlci5jb3VudE51bWJlckNoYXJhY3RlcnNPblRoZUNhcmV0TGVmdFNpZGUoaW5pdGlhbEZvcm1hdHRlZFZhbHVlLCBzZWxlY3Rpb25TdGFydCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSk7XG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkluaXRpYWxUZXh0QWZ0ZXJQYXN0aW5nID0gaW5kZXhXaGVyZVBhc3RlZFRleHRIYXNCZWVuSW5zZXJ0ZWQgKyBwYXN0ZWRUZXh0Lmxlbmd0aDsgLy8gSSBtdXN0IG5vdCBjb3VudCB0aGUgY2hhcmFjdGVycyB0aGF0IGhhdmUgYmVlbiByZW1vdmVkIGZyb20gdGhlIHBhc3RlZCB0ZXh0IChpZS4gJy4nKVxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc0FsbElucHV0VGV4dFNlbGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBTcGVjaWFsIGNhc2Ugd2hlbiBhbGwgdGhlIGlucHV0IHRleHQgaXMgc2VsZWN0ZWQgYmVmb3JlIHBhc3RpbmcsIHdoaWNoIG1lYW5zIHdlJ2xsIGNvbXBsZXRlbHkgZXJhc2UgaXRzIGNvbnRlbnQgYW5kIHBhc3RlIG9ubHkgdGhlIGNsaXBib2FyZCBjb250ZW50XG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZyA9IHJlc3VsdC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAocmlnaHRQYXJ0ID09PSAnJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIHVzZXIgc2VsZWN0ZWQgZnJvbSB0aGUgY2FyZXQgcG9zaXRpb24gdG8gdGhlIGVuZCBvZiB0aGUgaW5wdXQgKG9uIHRoZSBmYXIgcmlnaHQpXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZyA9IEF1dG9OdW1lcmljSGVscGVyLmNvbnZlcnRDaGFyYWN0ZXJDb3VudFRvSW5kZXhQb3NpdGlvbihBdXRvTnVtZXJpY0hlbHBlci5jb3VudE51bWJlckNoYXJhY3RlcnNPblRoZUNhcmV0TGVmdFNpZGUoaW5pdGlhbEZvcm1hdHRlZFZhbHVlLCBzZWxlY3Rpb25TdGFydCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSkgKyBwYXN0ZWRUZXh0Lmxlbmd0aDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIE5vcm1hbCBjYXNlXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBpbmRleFNlbGVjdGlvbkVuZEluUmF3VmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5jb252ZXJ0Q2hhcmFjdGVyQ291bnRUb0luZGV4UG9zaXRpb24oQXV0b051bWVyaWNIZWxwZXIuY291bnROdW1iZXJDaGFyYWN0ZXJzT25UaGVDYXJldExlZnRTaWRlKGluaXRpYWxGb3JtYXR0ZWRWYWx1ZSwgc2VsZWN0aW9uRW5kLCB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpKTtcblxuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSGVyZSBJIG11c3Qgbm90IGNvdW50IHRoZSBjaGFyYWN0ZXJzIHRoYXQgaGF2ZSBiZWVuIHJlbW92ZWQgZnJvbSB0aGUgcGFzdGVkIHRleHQgKGllLiAnLicpLCBvciB0aGUgdGhvdXNhbmQgc2VwYXJhdG9ycyBpbiB0aGUgaW5pdGlhbCBzZWxlY3RlZCB0ZXh0XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBzZWxlY3RlZFRleHQgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUoZS50YXJnZXQpLnNsaWNlKHNlbGVjdGlvblN0YXJ0LCBzZWxlY3Rpb25FbmQpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY2FyZXRQb3NpdGlvbk9uSW5pdGlhbFRleHRBZnRlclBhc3RpbmcgPSBpbmRleFNlbGVjdGlvbkVuZEluUmF3VmFsdWUgLSBzZWxlY3Rpb25TaXplICsgQXV0b051bWVyaWNIZWxwZXIuY291bnRDaGFySW5UZXh0KHRoaXMuc2V0dGluZ3MuZGlnaXRHcm91cFNlcGFyYXRvciwgc2VsZWN0ZWRUZXh0KSArIHBhc3RlZFRleHQubGVuZ3RoO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgLy8gTW9kaWZ5IHRoZSBjYXJldCBwb3NpdGlvbiBmb3Igc3BlY2lhbCBjYXNlcywgb25seSBpZiB0aGUgd2hvbGUgaW5wdXQgaGFzIG5vdCBiZWVuIHNlbGVjdGVkXG4gICAgICAgICAgICAgICAgaWYgKCFpc0FsbElucHV0VGV4dFNlbGVjdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1Bhc3RlTmVnYXRpdmVBbmRJbml0aWFsVmFsdWVJc1Bvc2l0aXZlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgcGFzdGVkIHZhbHVlIGhhcyBhICctJyBzaWduLCBidXQgdGhlIGluaXRpYWwgdmFsdWUgZG9lcyBub3QsIG9mZnNldCB0aGUgaW5kZXggYnkgb25lXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZysrO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKGxlZnRQYXJ0Q29udGFpbmVkQURvdCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgLy8gSWYgYSBkb3QgaGFzIGJlZW4gcmVtb3ZlZCBmb3IgdGhlIHBhcnQgb24gdGhlIGxlZnQgb2YgdGhlIGNhcmV0LCB3ZSBkZWNyZW1lbnQgdGhlIGNhcmV0IGluZGV4IHBvc2l0aW9uXG4gICAgICAgICAgICAgICAgICAgICAgICBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZy0tO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gNS4gQ2hlY2sgaWYgdGhlIHJlc3VsdCBpcyBhIHZhbGlkIG51bWJlciwgaWYgbm90LCBkcm9wIHRoZSBwYXN0ZSBhbmQgZG8gbm90aGluZy5cbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcihyZXN1bHQpIHx8IHJlc3VsdCA9PT0gJycpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm9uSW52YWxpZFBhc3RlID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmVycm9yKSB7XG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHBhc3RlZCB2YWx1ZSAnJHtyYXdQYXN0ZWRUZXh0fScgd291bGQgcmVzdWx0IGludG8gYW4gaW52YWxpZCBjb250ZW50ICcke3Jlc3VsdH0nLmApOyAvL1RPRE8gU2hvdWxkIHdlIHNlbmQgYSB3YXJuaW5nIGluc3RlYWQgb2YgdGhyb3dpbmcgYW4gZXJyb3I/XG4gICAgICAgICAgICAgICAgLy9UT0RPIFRoaXMgaXMgbm90IERSWSA7IHJlZmFjdG9yIHdpdGggYWJvdmVcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIDYuIElmIGl0J3MgYSB2YWxpZCBudW1iZXIsIGNoZWNrIGlmIGl0IGZhbGxzIGluc2lkZSB0aGUgbWluaW11bSBhbmQgbWF4aW11bSB2YWx1ZS4gSWYgdGhpcyBmYWlscywgbW9kaWZ5IHRoZSB2YWx1ZSBmb2xsb3dpbmcgdGhpcyBwcm9jZWR1cmUgOlxuICAgICAgICAvKlxuICAgICAgICAgKiBJZiAnZXJyb3InICh0aGlzIGlzIHRoZSBkZWZhdWx0KSA6XG4gICAgICAgICAqICAgICAgLSBOb3JtYWwgcGFzdGUgYmVoYXZpb3IuXG4gICAgICAgICAqICAgICAgLSBUcnkgdG8gc2V0IHRoZSBuZXcgdmFsdWUsIGlmIGl0IGZhaWxzLCB0aGVuIHRocm93IGFuIGVycm9yIGluIHRoZSBjb25zb2xlLlxuICAgICAgICAgKiAgICAgIC0gRG8gbm90IGNoYW5nZSB0aGUgaW5wdXQgdmFsdWUsIGRvIG5vdCBjaGFuZ2UgdGhlIGN1cnJlbnQgc2VsZWN0aW9uLlxuICAgICAgICAgKiBJZiAnaWdub3JlJyA6XG4gICAgICAgICAqICAgICAgLSBOb3JtYWwgcGFzdGUgYmVoYXZpb3IuXG4gICAgICAgICAqICAgICAgLSBUcnkgdG8gc2V0IHRoZSBuZXcgdmFsdWUsIGlmIGl0IGZhaWxzLCBkbyBub3RoaW5nIG1vcmUuXG4gICAgICAgICAqICAgICAgLSBEbyBub3QgY2hhbmdlIHRoZSBpbnB1dCB2YWx1ZSwgZG8gbm90IGNoYW5nZSB0aGUgY3VycmVudCBzZWxlY3Rpb24uXG4gICAgICAgICAqIElmICdjbGFtcCcgOlxuICAgICAgICAgKiAgICAgIC0gTm9ybWFsIHBhc3RlIGJlaGF2aW9yLlxuICAgICAgICAgKiAgICAgIC0gVHJ5IHRvIHNldCB0aGUgbmV3IHZhbHVlLCBpZiBpdCBmYWlscywgc2V0IHRoZSB2YWx1ZSB0byB0aGUgbWluaW11bSBvciBtYXhpbXVtIGxpbWl0LCB3aGljaGV2ZXIgaXMgY2xvc2VzdCB0byB0aGVcbiAgICAgICAgICogICAgICAgIHBhc3RlIHJlc3VsdC5cbiAgICAgICAgICogICAgICAtIENoYW5nZSB0aGUgY2FyZXQgcG9zaXRpb24gdG8gYmUgcG9zaXRpb25lZCBvbiB0aGUgbGVmdCBoYW5kIHNpZGUgb2YgdGhlIGRlY2ltYWwgY2hhcmFjdGVyLlxuICAgICAgICAgKiBJZiAndHJ1bmNhdGUnIDpcbiAgICAgICAgICogICAgICAtIFRydW5jYXRlIHBhc3RlIGJlaGF2aW9yLlxuICAgICAgICAgKiAgICAgIC0gVHJ5IHRvIHNldCB0aGUgbmV3IHZhbHVlLCB1bnRpbCBpdCBmYWlscyAoaWYgdGhlIHJlc3VsdCBpcyBvdXQgb2YgdGhlIG1pbiBhbmQgbWF4IHZhbHVlIGxpbWl0cykuXG4gICAgICAgICAqICAgICAgLSBEcm9wIHRoZSByZW1haW5pbmcgbm9uLXBhc3RlZCBudW1iZXJzLCBhbmQga2VlcCB0aGUgbGFzdCBrbm93biBub24tZmFpbGluZyByZXN1bHQuXG4gICAgICAgICAqICAgICAgLSBDaGFuZ2UgdGhlIGNhcmV0IHBvc2l0aW9uIHRvIGJlIHBvc2l0aW9uZWQgYWZ0ZXIgdGhlIGxhc3QgcGFzdGVkIGNoYXJhY3Rlci5cbiAgICAgICAgICogSWYgJ3JlcGxhY2UnIDpcbiAgICAgICAgICogICAgICAtIFJlcGxhY2UgcGFzdGUgYmVoYXZpb3IuXG4gICAgICAgICAqICAgICAgLSBUcnkgdG8gc2V0IHRoZSBuZXcgdmFsdWUsIHVudGlsIGl0IGZhaWxzIChpZiB0aGUgcmVzdWx0IGlzIG91dCBvZiB0aGUgbWluIGFuZCBtYXggdmFsdWUgbGltaXRzKS5cbiAgICAgICAgICogICAgIC0gVGhlbiB0cnkgdG8gcmVwbGFjZSBhcyBtYW55IG51bWJlcnMgYXMgcG9zc2libGUgd2l0aCB0aGUgcGFzdGVkIG9uZXMuIE9uY2UgaXQgZmFpbHMsIGtlZXAgdGhlIGxhc3Qga25vd24gbm9uLWZhaWxpbmcgcmVzdWx0LlxuICAgICAgICAgKiAgICAgIC0gQ2hhbmdlIHRoZSBjYXJldCBwb3NpdGlvbiB0byBiZSBwb3NpdGlvbmVkIGFmdGVyIHRoZSBsYXN0IHBhc3RlZCBjaGFyYWN0ZXIuXG4gICAgICAgICAqL1xuICAgICAgICBsZXQgdmFsdWVIYXNCZWVuU2V0ID0gZmFsc2U7XG4gICAgICAgIGxldCB2YWx1ZUhhc0JlZW5DbGFtcGVkID0gZmFsc2U7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgICB0aGlzLnNldChyZXN1bHQpO1xuICAgICAgICAgICAgdmFsdWVIYXNCZWVuU2V0ID0gdHJ1ZTtcbiAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgIGxldCBjbGFtcGVkVmFsdWU7XG4gICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3Mub25JbnZhbGlkUGFzdGUpIHtcbiAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUuY2xhbXA6XG4gICAgICAgICAgICAgICAgICAgIGNsYW1wZWRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmNsYW1wVG9SYW5nZUxpbWl0cyhyZXN1bHQsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXQoY2xhbXBlZFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYEZhdGFsIGVycm9yOiBVbmFibGUgdG8gc2V0IHRoZSBjbGFtcGVkIHZhbHVlICcke2NsYW1wZWRWYWx1ZX0nLmApO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgdmFsdWVIYXNCZWVuQ2xhbXBlZCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlSGFzQmVlblNldCA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IGNsYW1wZWRWYWx1ZTsgLy8gVGhpcyBpcyB1c2VkIG9ubHkgZm9yIHNldHRpbmcgdGhlIGNhcmV0IHBvc2l0aW9uIGxhdGVyXG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5lcnJvcjpcbiAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMub25JbnZhbGlkUGFzdGUudHJ1bmNhdGU6XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLnJlcGxhY2U6XG4gICAgICAgICAgICAgICAgICAgIC8vIFRocm93IGFuIGVycm9yIG1lc3NhZ2VcbiAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHBhc3RlZCB2YWx1ZSAnJHtyYXdQYXN0ZWRUZXh0fScgcmVzdWx0cyBpbiBhIHZhbHVlICcke3Jlc3VsdH0nIHRoYXQgaXMgb3V0c2lkZSBvZiB0aGUgbWluaW11bSBbJHt0aGlzLnNldHRpbmdzLm1pbmltdW1WYWx1ZX1dIGFuZCBtYXhpbXVtIFske3RoaXMuc2V0dGluZ3MubWF4aW11bVZhbHVlfV0gdmFsdWUgcmFuZ2UuYCk7XG4gICAgICAgICAgICAgICAgLy8gZmFsbHMgdGhyb3VnaFxuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5pZ25vcmU6XG4gICAgICAgICAgICAgICAgLy8gRG8gbm90aGluZ1xuICAgICAgICAgICAgICAgIC8vIGZhbGxzIHRocm91Z2hcbiAgICAgICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuOyAvLyAuLi5hbmQgbm90aGluZyBlbHNlIHNob3VsZCBiZSBjaGFuZ2VkXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyA3LiBUaGVuIGxhc3RseSwgc2V0IHRoZSBjYXJldCBwb3NpdGlvbiBhdCB0aGUgcmlnaHQgbG9naWNhbCBwbGFjZVxuICAgICAgICBjb25zdCB0YXJnZXRWYWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZShlLnRhcmdldCk7XG4gICAgICAgIGxldCBjYXJldFBvc2l0aW9uSW5Gb3JtYXR0ZWROdW1iZXI7XG4gICAgICAgIGlmICh2YWx1ZUhhc0JlZW5TZXQpIHtcbiAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5vbkludmFsaWRQYXN0ZSkge1xuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5jbGFtcDpcbiAgICAgICAgICAgICAgICAgICAgaWYgKHZhbHVlSGFzQmVlbkNsYW1wZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24oZS50YXJnZXQsIHRhcmdldFZhbHVlLmxlbmd0aCAtIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoKTsgLy8gVGhpcyBwdXRzIHRoZSBjYXJldCBvbiB0aGUgcmlnaHQgb2YgdGhlIGxhc3QgZGVjaW1hbCBwbGFjZVxuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5zZXRFbGVtZW50U2VsZWN0aW9uKGUudGFyZ2V0LCB0YXJnZXRWYWx1ZS5sZW5ndGgpOyAvLyAuLmFuZCB0aGlzIG9uIHRoZSBmYXIgcmlnaHRcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIH0gLy8gZWxzZSBpZiB0aGUgdmFsdWUgaGFzIG5vdCBiZWVuIGNsYW1wZWQsIHRoZSBkZWZhdWx0IGJlaGF2aW9yIGlzIHVzZWQuLi5cbiAgICAgICAgICAgICAgICAvLyBmYWxscyB0aHJvdWdoXG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLmVycm9yOlxuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5pZ25vcmU6XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm9uSW52YWxpZFBhc3RlLnRydW5jYXRlOlxuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5yZXBsYWNlOlxuICAgICAgICAgICAgICAgIGRlZmF1bHQgOlxuICAgICAgICAgICAgICAgICAgICAvLyBXaGVuZXZlciBvbmUgb3IgbXVsdGlwbGUgY2hhcmFjdGVycyBhcmUgcGFzdGVkLCB0aGlzIG1lYW5zIHdlIGhhdmUgdG8gbWFuYWdlIHRoZSBwb3RlbnRpYWwgdGhvdXNhbmQgc2VwYXJhdG9ycyB0aGF0IGNvdWxkIGJlIGFkZGVkIGJ5IHRoZSBmb3JtYXR0aW5nXG4gICAgICAgICAgICAgICAgICAgIGNhcmV0UG9zaXRpb25JbkZvcm1hdHRlZE51bWJlciA9IEF1dG9OdW1lcmljSGVscGVyLmZpbmRDYXJldFBvc2l0aW9uSW5Gb3JtYXR0ZWROdW1iZXIocmVzdWx0LCBjYXJldFBvc2l0aW9uT25Jbml0aWFsVGV4dEFmdGVyUGFzdGluZywgdGFyZ2V0VmFsdWUsIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcik7XG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24oZS50YXJnZXQsIGNhcmV0UG9zaXRpb25JbkZvcm1hdHRlZE51bWJlcik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyA4LiBXZSBtYWtlIHN1cmUgd2Ugc2VuZCBhbiBpbnB1dCBldmVudCBvbmx5IGlmIHRoZSByZXN1bHQgaXMgZGlmZmVyZW50IHRoYW4gdGhlIGluaXRpYWwgdmFsdWUgYmVmb3JlIHRoZSBwYXN0ZVxuICAgICAgICBpZiAodmFsdWVIYXNCZWVuU2V0ICYmIGluaXRpYWxGb3JtYXR0ZWRWYWx1ZSAhPT0gdGFyZ2V0VmFsdWUpIHtcbiAgICAgICAgICAgIC8vIE9uIGEgJ25vcm1hbCcgbm9uLWF1dG9OdW1lcmljIGlucHV0LCBhbiBgaW5wdXRgIGV2ZW50IGlzIHNlbnQgd2hlbiBhIHBhc3RlIGlzIGRvbmUuIFdlIG1pbWljIHRoYXQuXG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLm5hdGl2ZS5pbnB1dCwgZS50YXJnZXQpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2hlbiBmb2N1c2luZyBvdXQgb2YgdGhlIGlucHV0LCB3ZSBjaGVjayBpZiB0aGUgdmFsdWUgaGFzIGNoYW5nZWQsIGFuZCBpZiBpdCBoYXMsIHRoZW4gd2Ugc2VuZCBhIGBjaGFuZ2VgIGV2ZW50IChzaW5jZSB0aGUgbmF0aXZlIG9uZSB3b3VsZCBoYXZlIGJlZW4gcHJldmVudGVkIGJ5IGBlLnByZXZlbnREZWZhdWx0KClgIGNhbGxlZCBpbiB0aGUgb3RoZXIgZXZlbnQgbGlzdGVuZXJzKS5cbiAgICAgKiBXZSBhbHNvIHVwZGF0ZSB0aGUgaW5mbyBvZiB0aGUgZm9jdXNlZCBzdGF0ZSBpbiB0aGUgYHRoaXMuaXNGb2N1c2VkYCB2YXJpYWJsZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7RXZlbnR9IGVcbiAgICAgKi9cbiAgICBfb25CbHVyKGUpIHtcbiAgICAgICAgLy8gS2VlcCB0cmFjayBpZiB0aGUgZWxlbWVudCBpcyBjdXJyZW50bHkgZm9jdXNlZFxuICAgICAgICB0aGlzLmlzRm9jdXNlZCA9IGZhbHNlO1xuICAgICAgICAvLyBLZWVwIHRyYWNrIGlmIHRoZSB1c2VyIGlzIGN1cnJlbnRseSBlZGl0aW5nIHRoZSBlbGVtZW50XG4gICAgICAgIHRoaXMuaXNFZGl0aW5nID0gZmFsc2U7XG5cbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZShlLnRhcmdldCkgIT09IHRoaXMudmFsdWVPbkZvY3VzKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50cmlnZ2VyRXZlbnQoQXV0b051bWVyaWMuZXZlbnRzLm5hdGl2ZS5jaGFuZ2UsIGUudGFyZ2V0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yICd3aGVlbCcgZXZlbnRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7V2hlZWxFdmVudH0gZVxuICAgICAqL1xuICAgIF9vbldoZWVsKGUpIHtcbiAgICAgICAgLy8gSWYgdGhlIHVzZXIgaXMgdXNpbmcgdGhlICdTaGlmdCcga2V5IG1vZGlmaWVyLCB0aGVuIHdlIGlnbm9yZSB0aGUgd2hlZWwgZXZlbnRcbiAgICAgICAgLy8gVGhpcyBzcGVjaWFsIGJlaGF2aW9yIGlzIGFwcGxpZWQgaW4gb3JkZXIgdG8gYXZvaWQgcHJldmVudGluZyB0aGUgdXNlciB0byBzY3JvbGwgdGhlIHBhZ2UgaWYgdGhlIGlucHV0cyBhcmUgY292ZXJpbmcgdGhlIHdob2xlIGF2YWlsYWJsZSBzcGFjZS5cbiAgICAgICAgLy8gSWYgdGhhdCdzIHRoZSBjYXNlLCB0aGVuIGhlIGNhbiB1c2UgdGhlICdTaGlmdCcgbW9kaWZpZXIga2V5IHdoaWxlIHVzaW5nIHRoZSBtb3VzZSB3aGVlbCBpbiBvcmRlciB0byBieXBhc3MgdGhlIGluY3JlbWVudC9kZWNyZW1lbnQgZmVhdHVyZVxuICAgICAgICAvLyBUaGlzIGlzIHVzZWZ1bCBvbiBzbWFsbCBzY3JlZW4gd2hlcmUgc29tZSBiYWRseSBjb25maWd1cmVkIGlucHV0cyBjb3VsZCB1c2UgYWxsIHRoZSBhdmFpbGFibGUgc3BhY2UuXG4gICAgICAgIGlmICghZS5zaGlmdEtleSAmJiB0aGlzLnNldHRpbmdzLm1vZGlmeVZhbHVlT25XaGVlbCkge1xuICAgICAgICAgICAgdGhpcy5pc1doZWVsRXZlbnQgPSB0cnVlOyAvLyBLZWVwIHRoZSBpbmZvIHRoYXQgd2UgYXJlIGN1cnJlbnRseSBtYW5hZ2luZyBhIG1vdXNlIHdoZWVsIGV2ZW50XG5cbiAgICAgICAgICAgIC8vIDApIEZpcnN0LCBzYXZlIHRoZSBjYXJldCBwb3NpdGlvbiBzbyB3ZSBjYW4gc2V0IGl0IGJhY2sgb25jZSB0aGUgdmFsdWUgaGFzIGJlZW4gY2hhbmdlZFxuICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uU3RhcnQgPSBlLnRhcmdldC5zZWxlY3Rpb25TdGFydCB8fCAwO1xuICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uRW5kID0gZS50YXJnZXQuc2VsZWN0aW9uRW5kIHx8IDA7XG5cbiAgICAgICAgICAgIC8vIDEpIEdldCB0aGUgdW5mb3JtYXR0ZWQgdmFsdWVcbiAgICAgICAgICAgIGNvbnN0IGN1cnJlbnRVbmZvcm1hdHRlZFZhbHVlID0gdGhpcy5yYXdWYWx1ZTtcblxuICAgICAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkoY3VycmVudFVuZm9ybWF0dGVkVmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgLy8gSWYgYnkgZGVmYXVsdCB0aGUgaW5wdXQgaXMgZW1wdHksIHN0YXJ0IGF0ICcwJ1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm1pbmltdW1WYWx1ZSA+IDAgfHwgdGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWUgPCAwKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIG9yIGlmICcwJyBpcyBub3QgYmV0d2VlbiBtaW4gYW5kIG1heCB2YWx1ZSwgJ21pbmltdW1WYWx1ZScgaWYgdGhlIHVzZXIgZG9lcyBhIHdoZWVsdXAsICdtYXhpbXVtVmFsdWUnIGlmIHRoZSB1c2VyIGRvZXMgYSB3aGVlbGRvd25cbiAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzV2hlZWxVcEV2ZW50KGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLnNldHRpbmdzLm1pbmltdW1WYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1doZWVsRG93bkV2ZW50KGUpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSB0aGlzLnNldHRpbmdzLm1heGltdW1WYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBldmVudCBpcyBub3QgYSAnd2hlZWwnIGV2ZW50LmApO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IGN1cnJlbnRVbmZvcm1hdHRlZFZhbHVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXN1bHQgPSArcmVzdWx0OyAvLyBUeXBlY2FzdCB0byBhIG51bWJlciBuZWVkZWQgZm9yIHRoZSBmb2xsb3dpbmcgYWRkaXRpb24vc3VidHJhY3Rpb25cblxuICAgICAgICAgICAgLy8gMikgSW5jcmVtZW50L0RlY3JlbWVudCB0aGUgdmFsdWVcbiAgICAgICAgICAgIC8vIEJ1dCBmaXJzdCwgY2hvb3NlIHRoZSBpbmNyZW1lbnQvZGVjcmVtZW50IG1ldGhvZCA7IGZpeGVkIG9yIHByb2dyZXNzaXZlXG4gICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIodGhpcy5zZXR0aW5ncy53aGVlbFN0ZXApKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc3RlcCA9ICt0aGlzLnNldHRpbmdzLndoZWVsU3RlcDsgLy8gVHlwZWNhc3QgdG8gYSBudW1iZXIgbmVlZGVkIGZvciB0aGUgZm9sbG93aW5nIGFkZGl0aW9uL3N1YnRyYWN0aW9uXG4gICAgICAgICAgICAgICAgLy8gRml4ZWQgbWV0aG9kXG4gICAgICAgICAgICAgICAgLy8gVGhpcyBpcyB0aGUgc2ltcGxlc3QgbWV0aG9kLCB3aGVyZSBhIGZpeGVkIG9mZnNldCBpbiBhZGRlZC9zdWJ0cmFjdGVkIGZyb20gdGhlIGN1cnJlbnQgdmFsdWVcbiAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNXaGVlbFVwRXZlbnQoZSkpIHsgLy8gSW5jcmVtZW50XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCArPSBzdGVwO1xuICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNXaGVlbERvd25FdmVudChlKSkgeyAvLyBEZWNyZW1lbnRcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0IC09IHN0ZXA7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBQcm9ncmVzc2l2ZSBtZXRob2RcbiAgICAgICAgICAgICAgICAvLyBGb3IgdGhpcyBtZXRob2QsIHdlIGNhbGN1bGF0ZSBhbiBvZmZzZXQgdGhhdCBpcyBpbiByZWxhdGlvbiB0byB0aGUgc2l6ZSBvZiB0aGUgY3VycmVudCBudW1iZXIgKHVzaW5nIG9ubHkgdGhlIGludGVnZXIgcGFydCBzaXplKS5cbiAgICAgICAgICAgICAgICAvLyBUaGUgYmlnZ2VyIHRoZSBudW1iZXIsIHRoZSBiaWdnZXIgdGhlIG9mZnNldCAodXN1YWxseSB0aGUgbnVtYmVyIGNvdW50IGluIHRoZSBpbnRlZ2VyIHBhcnQgbWludXMgMywgZXhjZXB0IGZvciBzbWFsbCBudW1iZXJzIHdoZXJlIGEgZGlmZmVyZW50IGJlaGF2aW9yIGlzIGJldHRlciBmb3IgdGhlIHVzZXIgZXhwZXJpZW5jZSkuXG4gICAgICAgICAgICAgICAgLy9UT0RPIEtub3duIGxpbWl0YXRpb24gOiBUaGUgcHJvZ3Jlc3NpdmUgbWV0aG9kIGRvZXMgbm90IHBsYXkgd2VsbCB3aXRoIG51bWJlcnMgYmV0d2VlbiAwIGFuZCAxIHdoZXJlIHRvIG1vZGlmeSB0aGUgZGVjaW1hbCBwbGFjZXMgdGhlIHJhd1ZhbHVlIGZpcnN0IGhhcyB0byBnbyBmcm9tICcxJyB0byAnMCdcbiAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNXaGVlbFVwRXZlbnQoZSkpIHsgLy8gSW5jcmVtZW50XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljSGVscGVyLmFkZEFuZFJvdW5kVG9OZWFyZXN0QXV0byhyZXN1bHQsIHRoaXMuc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzV2hlZWxEb3duRXZlbnQoZSkpIHsgLy8gRGVjcmVtZW50XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljSGVscGVyLnN1YnRyYWN0QW5kUm91bmRUb05lYXJlc3RBdXRvKHJlc3VsdCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gMykgU2V0IHRoZSBuZXcgdmFsdWUgc28gaXQgZ2V0cyBmb3JtYXR0ZWRcbiAgICAgICAgICAgIC8vIEZpcnN0IGNsYW1wIHRoZSByZXN1bHQgaWYgbmVlZGVkXG4gICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0hlbHBlci5jbGFtcFRvUmFuZ2VMaW1pdHMocmVzdWx0LCB0aGlzLnNldHRpbmdzKTtcbiAgICAgICAgICAgIGlmIChyZXN1bHQgIT09ICtjdXJyZW50VW5mb3JtYXR0ZWRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIC8vIE9ubHkgJ3NldCcgdGhlIHZhbHVlIGlmIGl0IGhhcyBjaGFuZ2VkLiBGb3IgaW5zdGFuY2UgJ3NldCcgc2hvdWxkIG5vdCBoYXBwZW4gaWYgdGhlIHVzZXIgaGl0cyBhIGxpbWl0IGFuZCBjb250aW51ZSB0byB0cnkgdG8gZ28gcGFzdCBpdCBzaW5jZSB3ZSBjbGFtcCB0aGUgdmFsdWUuXG4gICAgICAgICAgICAgICAgdGhpcy5zZXQocmVzdWx0KTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy9YWFggRG8gbm90IHByZXZlbnQgaWYgdGhlIHZhbHVlIGlzIG5vdCBtb2RpZmllZD8gRnJvbSBhIFVYIHBvaW50IG9mIHZpZXcsIHByZXZlbnRpbmcgdGhlIHdoZWVsIGV2ZW50IHdoZW4gdGhlIHVzZXIgdXNlIGl0IG9uIHRvcCBvZiBhbiBhdXRvTnVtZXJpYyBlbGVtZW50IHNob3VsZCBhbHdheXMgYmUgZG9uZSwgZXZlbiBpZiB0aGUgdmFsdWUgZG9lcyBub3QgY2hhbmdlLiBQZXJoYXBzIHRoYXQgY291bGQgYWZmZWN0IG90aGVyIHNjcmlwdHMgcmVseWluZyBvbiB0aGlzIGV2ZW50IHRvIGJlIHNlbnQgdGhvdWdoLlxuICAgICAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpOyAvLyBXZSBwcmV2ZW50IHRoZSBwYWdlIHRvIHNjcm9sbCB3aGlsZSB3ZSBpbmNyZW1lbnQvZGVjcmVtZW50IHRoZSB2YWx1ZVxuXG4gICAgICAgICAgICAvLyA0KSBGaW5hbGx5LCB3ZSBzZXQgYmFjayB0aGUgY2FyZXQgcG9zaXRpb24vc2VsZWN0aW9uXG4gICAgICAgICAgICAvLyBUaGVyZSBpcyBubyBuZWVkIHRvIHRha2UgaW50byBhY2NvdW50IHRoZSBmYWN0IHRoYXQgdGhlIG51bWJlciBjb3VudCBjb3VsZCBiZSBkaWZmZXJlbnQgYXQgdGhlIGVuZCBvZiB0aGUgd2hlZWwgZXZlbnQgOyBpdCB3b3VsZCBiZSB0b28gY29tcGxleCBhbmQgbW9zdCBvZiB0aGUgdGltZSB1bnJlbGlhYmxlXG4gICAgICAgICAgICB0aGlzLl9zZXRTZWxlY3Rpb24oc2VsZWN0aW9uU3RhcnQsIHNlbGVjdGlvbkVuZCk7XG5cbiAgICAgICAgICAgIHRoaXMuaXNXaGVlbEV2ZW50ID0gZmFsc2U7IC8vIFNldCBiYWNrIHRoZSBtb3VzZSB3aGVlbCBpbmRpY2F0b3IgdG8gaXRzIGRlZmF1bHRcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhhbmRsZXIgZm9yICdkcm9wJyBldmVudFxuICAgICAqXG4gICAgICogQHBhcmFtIHtEcmFnRXZlbnR9IGVcbiAgICAgKi9cbiAgICBfb25Ecm9wKGUpIHtcbiAgICAgICAgdGhpcy5pc0Ryb3BFdmVudCA9IHRydWU7XG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgY29uc3QgZHJvcHBlZFRleHQgPSBlLmRhdGFUcmFuc2Zlci5nZXREYXRhKCd0ZXh0L3BsYWluJyk7XG4gICAgICAgIGNvbnN0IGNsZWFuZWRWYWx1ZSA9IHRoaXMudW5mb3JtYXRPdGhlcihkcm9wcGVkVGV4dCk7XG4gICAgICAgIHRoaXMuc2V0KGNsZWFuZWRWYWx1ZSk7XG4gICAgICAgIHRoaXMuaXNEcm9wRXZlbnQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIYW5kbGVyIGZvciAnc3VibWl0JyBldmVudHMgaGFwcGVuaW5nIG9uIHRoZSBwYXJlbnQgPGZvcm0+IGVsZW1lbnQuXG4gICAgICogSWYgYHVuZm9ybWF0T25TdWJtaXRgIGlzIHNldCB0byBgdHJ1ZWAsIHRoZSBlbGVtZW50IHZhbHVlIGlzIGZpcnN0IHVuZm9ybWF0dGVkIGJlZm9yZSB0aGUgZm9ybSBpcyBzdWJtaXR0ZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBfb25Gb3JtU3VibWl0KCkge1xuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy51bmZvcm1hdE9uU3VibWl0KSB7XG4gICAgICAgICAgICB0aGlzLl9zZXRFbGVtZW50VmFsdWUodGhpcy5yYXdWYWx1ZSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBMaXN0ZW4gZm9yIHRoZSBgYWx0YCBrZXkga2V5ZG93biBldmVudCBnbG9iYWxseSwgYW5kIGlmIHRoZSBldmVudCBpcyBjYXVnaHQsIHVuZm9ybWF0IHRoZSBBdXRvTnVtZXJpYyBlbGVtZW50IHRoYXQgaXMgaG92ZXJlZCBieSB0aGUgbW91c2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0tleWJvYXJkRXZlbnR9IGVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9vbktleWRvd25HbG9iYWwoZSkge1xuICAgICAgICAvL1RPRE8gRmluZCBhIHdheSB0byBrZWVwIHRoZSBjYXJldCBwb3NpdGlvbiBiZXR3ZWVuIHRoZSBhbHQga2V5dXAva2V5ZG93biBzdGF0ZXNcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmNoYXJhY3RlcihlKSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQWx0KSB7XG4gICAgICAgICAgICBjb25zdCBob3ZlcmVkRWxlbWVudCA9IEF1dG9OdW1lcmljSGVscGVyLmdldEhvdmVyZWRFbGVtZW50KCk7XG4gICAgICAgICAgICBpZiAoQXV0b051bWVyaWMuaXNNYW5hZ2VkQnlBdXRvTnVtZXJpYyhob3ZlcmVkRWxlbWVudCkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBhbkVsZW1lbnQgPSBBdXRvTnVtZXJpYy5nZXRBdXRvTnVtZXJpY0VsZW1lbnQoaG92ZXJlZEVsZW1lbnQpO1xuICAgICAgICAgICAgICAgIHRoaXMuY29uc3RydWN0b3IuX3VuZm9ybWF0QWx0SG92ZXJlZChhbkVsZW1lbnQpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTGlzdGVuIGZvciB0aGUgYGFsdGAga2V5IGtleXVwIGV2ZW50IGdsb2JhbGx5LCBhbmQgaWYgdGhlIGV2ZW50IGlzIGNhdWdodCwgcmVmb3JtYXQgdGhlIEF1dG9OdW1lcmljIGVsZW1lbnQgdGhhdCBpcyBob3ZlcmVkIGJ5IHRoZSBtb3VzZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7S2V5Ym9hcmRFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX29uS2V5dXBHbG9iYWwoZSkge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuY2hhcmFjdGVyKGUpID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5BbHQpIHtcbiAgICAgICAgICAgIGNvbnN0IGhvdmVyZWRFbGVtZW50ID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0SG92ZXJlZEVsZW1lbnQoKTtcbiAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpYy5pc01hbmFnZWRCeUF1dG9OdW1lcmljKGhvdmVyZWRFbGVtZW50KSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGFuRWxlbWVudCA9IEF1dG9OdW1lcmljLmdldEF1dG9OdW1lcmljRWxlbWVudChob3ZlcmVkRWxlbWVudCk7XG4gICAgICAgICAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fcmVmb3JtYXRBbHRIb3ZlcmVkKGFuRWxlbWVudCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBET00gZWxlbWVudCBpcyBzdXBwb3J0ZWQgYnkgYXV0b051bWVyaWMuXG4gICAgICogQSBzdXBwb3J0ZWQgZWxlbWVudCBpcyBhbiBlbGVtZW50IHdoaXRlbGlzdGVkIGluIHRoZSBgYWxsb3dlZFRhZ0xpc3RgLlxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfaXNFbGVtZW50VGFnU3VwcG9ydGVkKCkge1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzRWxlbWVudCh0aGlzLmRvbUVsZW1lbnQpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgRE9NIGVsZW1lbnQgaXMgbm90IHZhbGlkLCAke3RoaXMuZG9tRWxlbWVudH0gZ2l2ZW4uYCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KHRoaXMuZG9tRWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCksIHRoaXMuYWxsb3dlZFRhZ0xpc3QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaW4gdGhlIERPTSBlbGVtZW50IGlzIGFuIDxpbnB1dD4uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9pc0lucHV0RWxlbWVudCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuZG9tRWxlbWVudC50YWdOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdpbnB1dCc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgaW5wdXQgdHlwZSBpcyBzdXBwb3J0ZWQgYnkgQXV0b051bWVyaWNcbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEB0aHJvd3NcbiAgICAgKi9cbiAgICBfaXNJbnB1dFR5cGVTdXBwb3J0ZWQoKSB7XG4gICAgICAgIHJldHVybiAodGhpcy5kb21FbGVtZW50LnR5cGUgPT09ICd0ZXh0JyB8fFxuICAgICAgICAgICAgICAgIHRoaXMuZG9tRWxlbWVudC50eXBlID09PSAnaGlkZGVuJyB8fFxuICAgICAgICAgICAgICAgIHRoaXMuZG9tRWxlbWVudC50eXBlID09PSAndGVsJyB8fFxuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh0aGlzLmRvbUVsZW1lbnQudHlwZSkpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENoZWNrIGlmIHRoZSBET00gZWxlbWVudCBpcyBzdXBwb3J0ZWQgYnkgYXV0b051bWVyaWMuXG4gICAgICogQSBzdXBwb3J0ZWQgZWxlbWVudCBpcyBlaXRoZXIgYW4gPGlucHV0PiBlbGVtZW50IHdpdGggdGhlIHJpZ2h0ICd0eXBlJyBhdHRyaWJ1dGUsIG9yIGEgdGFnIHdoaXRlbGlzdGVkIGluIHRoZSBgYWxsb3dlZFRhZ0xpc3RgLlxuICAgICAqIElmIHRoZSBjaGVjayBmYWlscywgdGhpcyBtZXRob2QgdGhyb3dzLlxuICAgICAqIFRoaXMgZnVuY3Rpb24gYWxzbyBzZXQgdGhlIGluZm8gYHRoaXMuaXNJbnB1dEVsZW1lbnRgIHdoaWNoIGtlZXAgdHJhY2tzIGlmIHRoZSBET00gZWxlbWVudCBpcyBhbiA8aW5wdXQ+IG9yIG5vdCwgYW5kIHRoZSBgdGhpcy5pc0NvbnRlbnRFZGl0YWJsZWAgaWYgdGhlIGVsZW1lbnQgaGFzIHRoZSBgY29udGVudGVkaXRhYmxlYCBhdHRyaWJ1dGUgc2V0IHRvIGB0cnVlYC5cbiAgICAgKlxuICAgICAqIEB0aHJvd3NcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9jaGVja0VsZW1lbnQoKSB7XG4gICAgICAgIGNvbnN0IGN1cnJlbnRFbGVtZW50VGFnID0gdGhpcy5kb21FbGVtZW50LnRhZ05hbWUudG9Mb3dlckNhc2UoKTtcblxuICAgICAgICBpZiAoIXRoaXMuX2lzRWxlbWVudFRhZ1N1cHBvcnRlZCgpKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgPCR7Y3VycmVudEVsZW1lbnRUYWd9PiB0YWcgaXMgbm90IHN1cHBvcnRlZCBieSBhdXRvTnVtZXJpY2ApO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuX2lzSW5wdXRFbGVtZW50KCkpIHtcbiAgICAgICAgICAgIGlmICghdGhpcy5faXNJbnB1dFR5cGVTdXBwb3J0ZWQoKSkge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBpbnB1dCB0eXBlIFwiJHt0aGlzLmRvbUVsZW1lbnQudHlwZX1cIiBpcyBub3Qgc3VwcG9ydGVkIGJ5IGF1dG9OdW1lcmljYCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuaXNJbnB1dEVsZW1lbnQgPSB0cnVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5pc0lucHV0RWxlbWVudCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy5pc0NvbnRlbnRFZGl0YWJsZSA9IHRoaXMuZG9tRWxlbWVudC5oYXNBdHRyaWJ1dGUoJ2NvbnRlbnRlZGl0YWJsZScpICYmIHRoaXMuZG9tRWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2NvbnRlbnRlZGl0YWJsZScpID09PSAndHJ1ZSc7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JtYXRzIHRoZSBkZWZhdWx0IHZhbHVlIG9uIHBhZ2UgbG9hZC5cbiAgICAgKiBUaGlzIGlzIGNhbGxlZCBvbmx5IGlmIHRoZSBgZm9ybWF0T25QYWdlTG9hZGAgb3B0aW9uIGlzIHNldCB0byBgdHJ1ZWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd8bnVsbH0gZm9yY2VkSW5pdGlhbFZhbHVlIFRoZSB2YWx1ZSB0aGF0IHNob3VsZCBiZSB1c2VkIGZvciBpbml0aWFsaXphdGlvbiwgaW4gcGxhY2Ugb24gdGhlIGV2ZW50dWFsIGh0bWwgb25lXG4gICAgICovXG4gICAgX2Zvcm1hdERlZmF1bHRWYWx1ZU9uUGFnZUxvYWQoZm9yY2VkSW5pdGlhbFZhbHVlID0gbnVsbCkge1xuICAgICAgICBsZXQgc2V0VmFsdWUgPSB0cnVlO1xuICAgICAgICBsZXQgY3VycmVudFZhbHVlO1xuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChmb3JjZWRJbml0aWFsVmFsdWUpKSB7XG4gICAgICAgICAgICBjdXJyZW50VmFsdWUgPSBmb3JjZWRJbml0aWFsVmFsdWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBjdXJyZW50VmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmlzSW5wdXRFbGVtZW50IHx8IHRoaXMuaXNDb250ZW50RWRpdGFibGUpIHtcbiAgICAgICAgICAgIC8qXG4gICAgICAgICAgICAgKiBJZiB0aGUgaW5wdXQgdmFsdWUgaGFzIGJlZW4gc2V0IGJ5IHRoZSBkZXYsIGJ1dCBub3QgZGlyZWN0bHkgYXMgYW4gYXR0cmlidXRlIGluIHRoZSBodG1sLCB0aGVuIGl0IHRha2VzXG4gICAgICAgICAgICAgKiBwcmVjZWRlbmNlIGFuZCBzaG91bGQgZ2V0IGZvcm1hdHRlZCBkdXJpbmcgdGhlIGluaXRpYWxpemF0aW9uIChpZiB0aGlzIGlucHV0IHZhbHVlIGlzIGEgdmFsaWQgbnVtYmVyIGFuZCB0aGF0IHRoZVxuICAgICAgICAgICAgICogZGV2ZWxvcGVyIHdhbnRzIGl0IGZvcm1hdHRlZCBvbiBpbml0IChjZi4gdGhlIGBzZXR0aW5ncy5mb3JtYXRPblBhZ2VMb2FkYCBvcHRpb24pKS5cbiAgICAgICAgICAgICAqIE5vdGU7IHRoaXMgaXMgdHJ1ZSB3aGF0ZXZlciB0aGUgZGV2ZWxvcGVyIGhhcyBzZXQgZm9yIGBkYXRhLWRlZmF1bHQtdmFsdWUtb3ZlcnJpZGVgIGluIHRoZSBodG1sIChhc3AubmV0IHVzZXJzKS5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBJbiBvdGhlciB3b3JkcyA6IGlmIGBkZWZhdWx0VmFsdWVPdmVycmlkZWAgaXMgbm90IG51bGwsIGl0IG1lYW5zIHRoZSBkZXZlbG9wZXIgaXMgdHJ5aW5nIHRvIHByZXZlbnQgcG9zdGJhY2sgcHJvYmxlbXMuXG4gICAgICAgICAgICAgKiBCdXQgaWYgYGlucHV0LnZhbHVlYCBpcyBzZXQgdG8gYSBudW1iZXIsIGFuZCB0aGUgaHRtbCBgdmFsdWVgIGF0dHJpYnV0ZSBpcyBub3Qgc2V0LCB0aGVuIGl0IG1lYW5zIHRoZSBkZXYgaGFzXG4gICAgICAgICAgICAgKiBjaGFuZ2VkIHRoZSBpbnB1dCB2YWx1ZSwgYW5kIHRoZW4gaXQgbWVhbnMgd2Ugc2hvdWxkIG5vdCBvdmVyd3JpdGUgaGlzIG93biBkZWNpc2lvbiB0byBkbyBzby5cbiAgICAgICAgICAgICAqIEhlbmNlLCBpZiBgZGVmYXVsdFZhbHVlT3ZlcnJpZGVgIGlzIG5vdCBudWxsLCBidXQgYGlucHV0LnZhbHVlYCBpcyBhIG51bWJlciBhbmQgYHRoaXMuZG9tRWxlbWVudC5oYXNBdHRyaWJ1dGUoJ3ZhbHVlJylgXG4gICAgICAgICAgICAgKiBpcyBmYWxzZSwgd2Ugc2hvdWxkIGlnbm9yZSBgZGVmYXVsdFZhbHVlT3ZlcnJpZGVgIGFsdG9nZXRoZXIuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGNvbnN0IHVuTG9jYWxpemVkQ3VycmVudFZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fdG9OdW1lcmljVmFsdWUoY3VycmVudFZhbHVlLCB0aGlzLnNldHRpbmdzKTsgLy8gVGhpcyBhbGxvd3MgdG8gdXNlIGEgbG9jYWxpemVkIHZhbHVlIG9uIHN0YXJ0dXBcbiAgICAgICAgICAgIGlmICghdGhpcy5kb21FbGVtZW50Lmhhc0F0dHJpYnV0ZSgndmFsdWUnKSB8fCB0aGlzLmRvbUVsZW1lbnQuZ2V0QXR0cmlidXRlKCd2YWx1ZScpID09PSAnJykge1xuICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSBgdmFsdWVgIGlzIHZhbGlkIG9yIG5vdFxuICAgICAgICAgICAgICAgIGlmICghaXNOYU4oTnVtYmVyKHVuTG9jYWxpemVkQ3VycmVudFZhbHVlKSkgJiYgSW5maW5pdHkgIT09IHVuTG9jYWxpemVkQ3VycmVudFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc2V0KHVuTG9jYWxpemVkQ3VycmVudFZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgc2V0VmFsdWUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiBub3QsIGluZm9ybSB0aGUgZGV2ZWxvcGVyIHRoYXQgbm90aGluZyB1c2FibGUgaGFzIGJlZW4gcHJvdmlkZWRcbiAgICAgICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudGhyb3dFcnJvcihgVGhlIHZhbHVlIFske2N1cnJlbnRWYWx1ZX1dIHVzZWQgaW4gdGhlIGlucHV0IGlzIG5vdCBhIHZhbGlkIHZhbHVlIGF1dG9OdW1lcmljIGNhbiB3b3JrIHdpdGguYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvKiBDaGVja3MgZm9yIDpcbiAgICAgICAgICAgICAgICAgKiAtIHBhZ2UgcmVsb2FkIGZyb20gYmFjayBidXR0b24sIGFuZFxuICAgICAgICAgICAgICAgICAqIC0gQVNQLm5ldCBmb3JtIHBvc3QgYmFja1xuICAgICAgICAgICAgICAgICAqICAgICAgVGhlIGZvbGxvd2luZyBIVE1MIGRhdGEgYXR0cmlidXRlIGlzIFJFUVVJUkVEIChkYXRhLWFuLWRlZmF1bHQ9XCJzYW1lIHZhbHVlIGFzIHRoZSB2YWx1ZSBhdHRyaWJ1dGVcIilcbiAgICAgICAgICAgICAgICAgKiAgICAgIGV4YW1wbGU6IDxhc3A6VGV4dEJveCBydW5hdD1cInNlcnZlclwiIGlkPVwic29tZUlEXCIgdGV4dD1cIjEyMzQuNTZcIiBkYXRhLWFuLWRlZmF1bHQ9XCIxMjM0LjU2XCI+XG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgaWYgKCh0aGlzLnNldHRpbmdzLmRlZmF1bHRWYWx1ZU92ZXJyaWRlICE9PSBudWxsICYmIHRoaXMuc2V0dGluZ3MuZGVmYXVsdFZhbHVlT3ZlcnJpZGUudG9TdHJpbmcoKSAhPT0gY3VycmVudFZhbHVlKSB8fFxuICAgICAgICAgICAgICAgICAgICAodGhpcy5zZXR0aW5ncy5kZWZhdWx0VmFsdWVPdmVycmlkZSA9PT0gbnVsbCAmJiBjdXJyZW50VmFsdWUgIT09ICcnICYmIGN1cnJlbnRWYWx1ZSAhPT0gdGhpcy5kb21FbGVtZW50LmdldEF0dHJpYnV0ZSgndmFsdWUnKSkgfHxcbiAgICAgICAgICAgICAgICAgICAgKGN1cnJlbnRWYWx1ZSAhPT0gJycgJiYgdGhpcy5kb21FbGVtZW50LmdldEF0dHJpYnV0ZSgndHlwZScpID09PSAnaGlkZGVuJyAmJiAhQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIodW5Mb2NhbGl6ZWRDdXJyZW50VmFsdWUpKSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5zYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlICYmICh0aGlzLnNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgIT09IG51bGwgfHwgdGhpcy5zZXR0aW5ncy5kaXZpc29yV2hlblVuZm9jdXNlZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFJhd1ZhbHVlKHRoaXMuX2dldFZhbHVlRnJvbVBlcnNpc3RlbnRTdG9yYWdlKCkpO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgdGhlIGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgdmFsdWUgc2hvdWxkIE5PVCBiZSBzYXZlZCBpbiBzZXNzaW9uU3RvcmFnZVxuICAgICAgICAgICAgICAgICAgICBpZiAoIXRoaXMuc2V0dGluZ3Muc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgbGV0IHRvU3RyaXA7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlQnJhY2tldHNUeXBlT25CbHVyICE9PSBudWxsICYmIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyICE9PSAnJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvU3RyaXAgPSB0aGlzLmNvbnN0cnVjdG9yLl9yZW1vdmVCcmFja2V0cyhjdXJyZW50VmFsdWUsIHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b1N0cmlwID0gY3VycmVudFZhbHVlO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQuc3VmZml4IHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgIT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4ICYmIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4KSkgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciAhPT0gJycgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKGN1cnJlbnRWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRSYXdWYWx1ZSh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciArIHRoaXMuY29uc3RydWN0b3IuX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVycyh0b1N0cmlwLCB0aGlzLnNldHRpbmdzLCB0cnVlLCB0aGlzLmlzRm9jdXNlZCkpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLl9zZXRSYXdWYWx1ZSh0aGlzLmNvbnN0cnVjdG9yLl9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnModG9TdHJpcCwgdGhpcy5zZXR0aW5ncywgdHJ1ZSwgdGhpcy5pc0ZvY3VzZWQpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIHNldFZhbHVlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoY3VycmVudFZhbHVlID09PSAnJykge1xuICAgICAgICAgICAgICAgIHN3aXRjaCAodGhpcy5zZXR0aW5ncy5lbXB0eUlucHV0QmVoYXZpb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5mb2N1czpcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFZhbHVlID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgLy9UT0RPIFdoYXQgYWJvdXQgdGhlIGBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5wcmVzc2AgdmFsdWU/XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IuYWx3YXlzOlxuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0RWxlbWVudFZhbHVlKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VmFsdWUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuZW1wdHlJbnB1dEJlaGF2aW9yLnplcm86XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnNldCgnMCcpO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2V0VmFsdWUgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICAgICAgLy9cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9IGVsc2UgaWYgKHNldFZhbHVlICYmIGN1cnJlbnRWYWx1ZSA9PT0gdGhpcy5kb21FbGVtZW50LmdldEF0dHJpYnV0ZSgndmFsdWUnKSkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0KGN1cnJlbnRWYWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5kZWZhdWx0VmFsdWVPdmVycmlkZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgICAgIHRoaXMuc2V0KGN1cnJlbnRWYWx1ZSk7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmRlZmF1bHRWYWx1ZU92ZXJyaWRlID09PSBjdXJyZW50VmFsdWUpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXQoY3VycmVudFZhbHVlKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbmhhbmNlIHRoZSB1c2VyIGV4cGVyaWVuY2UgYnkgbW9kaWZ5aW5nIHRoZSBkZWZhdWx0IGBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudGAgb3B0aW9uIGRlcGVuZGluZyBvbiBgY3VycmVuY3lTeW1ib2xgIGFuZCBgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnRgLlxuICAgICAqXG4gICAgICogSWYgdGhlIHVzZXIgaGFzIG5vdCBzZXQgdGhlIHBsYWNlbWVudCBvZiB0aGUgbmVnYXRpdmUgc2lnbiAoYG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50YCksIGJ1dCBoYXMgc2V0IGEgY3VycmVuY3kgc3ltYm9sIChgY3VycmVuY3lTeW1ib2xgKSxcbiAgICAgKiB0aGVuIHdlIG1vZGlmeSB0aGUgZGVmYXVsdCB2YWx1ZSBvZiBgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnRgIGluIG9yZGVyIHRvIGtlZXAgdGhlIHJlc3VsdGluZyBvdXRwdXQgbG9naWNhbCBieSBkZWZhdWx0IDpcbiAgICAgKiAtIFwiJC0xLDIzNC41NlwiIGluc3RlYWQgb2YgXCItJDEsMjM0LjU2XCIgKHtjdXJyZW5jeVN5bWJvbDogXCIkXCIsIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBcInJcIn0pXG4gICAgICogLSBcIi0xLDIzNC41NiRcIiBpbnN0ZWFkIG9mIFwiMSwyMzQuNTYtJFwiICh7Y3VycmVuY3lTeW1ib2w6IFwiJFwiLCBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudDogXCJzXCIsIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBcInBcIn0pXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NvcnJlY3ROZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudE9wdGlvbihzZXR0aW5ncykge1xuICAgICAgICAvL1hYWCBOb3RlOyB0aGlzIGZ1bmN0aW9uIGlzIHN0YXRpYyBzaW5jZSB3ZSBuZWVkIHRvIHBhc3MgYSBgc2V0dGluZ3NgIG9iamVjdCB3aGVuIGNhbGxpbmcgdGhlIHN0YXRpYyBgQXV0b051bWVyaWMuZm9ybWF0KClgIG1ldGhvZFxuICAgICAgICAvLyBJZiBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCBpcyBhbHJlYWR5IHNldCwgd2UgZG8gbm90IG92ZXJ3cml0ZSBpdFxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChzZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCkpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWQoc2V0dGluZ3MpICYmXG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkoc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQpICYmXG4gICAgICAgICAgICAhQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHNldHRpbmdzLmN1cnJlbmN5U3ltYm9sKSkge1xuICAgICAgICAgICAgc3dpdGNoIChzZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCkge1xuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXg6XG4gICAgICAgICAgICAgICAgICAgIHNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg7IC8vIERlZmF1bHQgLTEsMjM0LjU2IOKCrFxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlIEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQucHJlZml4OlxuICAgICAgICAgICAgICAgICAgICBzZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDsgLy8gRGVmYXVsdCAtJDEsMjM0LjU2XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQgOlxuICAgICAgICAgICAgICAgIC8vXG4gICAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBTZXRzIHRoZSBkZWZhdWx0IHZhbHVlIGlmIGBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudGAgaXMgYG51bGxgXG4gICAgICAgICAgICBzZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQubGVmdDtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvcnJlY3QgdGhlIGBjYXJldFBvc2l0aW9uT25Gb2N1c2AgYW5kIGBzZWxlY3RPbkZvY3VzYCBvcHRpb25zLCBzaW5jZSBzZXR0aW5nIGJvdGggbGVhZHMgdG8gYSBjb25mbGljdC5cbiAgICAgKiBUaGlzIG1ldGhvZCBkaXJlY3RseSBtb2RpZmllcyB0aGUgYG9wdGlvbnNgIG9iamVjdCBwYXNzZWQgYXMgYSBwYXJhbWV0ZXIsIHRoZW4gcmV0dXJucyBpdC5cbiAgICAgKiBJdCByZXR1cm5zIGBudWxsYCBpZiB0aGUgZ2l2ZW4gb3B0aW9uIGlzIGBudWxsYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvcHRpb25zIFRoZSBvcHRpb25zIHBhc3NlZCBhcyBhbiBhcmd1bWVudCBieSB0aGUgdXNlclxuICAgICAqIEByZXR1cm5zIHtvYmplY3R8bnVsbH1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfY29ycmVjdENhcmV0UG9zaXRpb25PbkZvY3VzQW5kU2VsZWN0T25Gb2N1c09wdGlvbnMob3B0aW9ucykge1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIElmIHRoZSB1c2VyIGhhcyBzZXQgdGhlIGBjYXJldFBvc2l0aW9uT25Gb2N1c2Agb3B0aW9uLCBkbyBub3Qgc2V0IGBzZWxlY3RPbkZvY3VzYCB0byBgdHJ1ZWAgYnkgZGVmYXVsdFxuICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShvcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzKSAmJiBBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkob3B0aW9ucy5zZWxlY3RPbkZvY3VzKSkge1xuICAgICAgICAgICAgb3B0aW9ucy5zZWxlY3RPbkZvY3VzID0gQXV0b051bWVyaWMub3B0aW9ucy5zZWxlY3RPbkZvY3VzLmRvTm90U2VsZWN0O1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgdGhlIHVzZXIgaGFzIHNldCB0aGUgYHNlbGVjdE9uRm9jdXNgIG9wdGlvbiB0byBgdHJ1ZWAsIHNldCBgY2FyZXRQb3NpdGlvbk9uRm9jdXNgIHRvIGBkb05vRm9yY2VDYXJldFBvc2l0aW9uYFxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KG9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMpICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkob3B0aW9ucy5zZWxlY3RPbkZvY3VzKSAmJiBvcHRpb25zLnNlbGVjdE9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuc2VsZWN0T25Gb2N1cy5zZWxlY3QpIHtcbiAgICAgICAgICAgIG9wdGlvbnMuY2FyZXRQb3NpdGlvbk9uRm9jdXMgPSBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmRvTm9Gb3JjZUNhcmV0UG9zaXRpb247XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gb3B0aW9ucztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYWxjdWxhdGUgdGhlIG51bWJlciBkZSBkZWNpbWFsIHBsYWNlcyB0byBiZSB1c2VkIGJ5IHRoZSBBdXRvTnVtZXJpYyBvYmplY3QsIGZvciBlYWNoIG9mIGl0cyBzdGF0ZSwgYW5kIGZvciBpdHMgZm9ybWF0dGVkIGFuZCByYXcgdmFsdWUuXG4gICAgICogQnkgZGVmYXVsdCwgdGhlIGByYXdWYWx1ZWAgcHJlY2lzaW9uIGlzIHRoZSBzYW1lIGFzIHRoZSBmb3JtYXR0ZWQgdmFsdWUgb25lLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2QgaXMgY2FsbGVkIGR1cmluZyB0aGUgQXV0b051bWVyaWMgb2JqZWN0IGluaXRpYWxpemF0aW9uLiBUaGlzIGFzc3VtZXMgc29tZSBpbnRlcm5hbCB2YXJpYWJsZSBzdGF0ZS5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kcyBzZXQgdGhlIGZvbGxvd2luZyBvcHRpb25zIGFjY29yZGluZ2x5IHRvIHRoZWlyIG93biB2YWx1ZSBhbmQgdGhlIG1hbmRhdG9yeSBgZGVjaW1hbFBsYWNlc2Agb3B0aW9uOlxuICAgICAqIC0gZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlICAgICAobnVsbGFibGUpXG4gICAgICogLSBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIgIChudWxsYWJsZSlcbiAgICAgKiAtIGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgKG51bGxhYmxlKVxuICAgICAqXG4gICAgICogTm90ZTogdGhlIGBkZWNpbWFsUGxhY2VzYCBvcHRpb24gaXMgb25seSB1c2VkIGhlcmUgYW5kIG9ubHkgc2VydmUgdG8gZGVmaW5lIHRob3NlIHRocmVlIHByZXZpb3VzIG9wdGlvbnMgdmFsdWUuXG4gICAgICogQXV0b051bWVyaWMgd2lsbCB0aGVuICpvbmx5KiB1c2UgYGRlY2ltYWxQbGFjZXNSYXdWYWx1ZWAsIGBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXJgIGFuZCBgZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1c2AgZnJvbSB0aGVyZS5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kcyBkaXJlY3RseSBtb2RpZmllcyB0aGUgYHNldHRpbmdzYCBvYmplY3QgcGFzc2VkIGFzIGEgcGFyYW1ldGVyLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzIFRoaXMgaXMgYW4gb2JqZWN0IHdpdGggdGhlIG5ldyBzZXR0aW5ncyB0byB1c2UuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NhbGN1bGF0ZURlY2ltYWxQbGFjZXNPbkluaXQoc2V0dGluZ3MpIHtcbiAgICAgICAgLy8gQ2hlY2sgdGhlIGBkZWNpbWFsUGxhY2VzKmAgb3B0aW9ucyBhbmQgb3V0cHV0IGFueSB3YXJuaW5ncyBhcyBuZWVkZWQsIGJlZm9yZSBtb2RpZnlpbmcgdGhvc2Ugb3B0aW9uc1xuICAgICAgICB0aGlzLl92YWxpZGF0ZURlY2ltYWxQbGFjZXNSYXdWYWx1ZShzZXR0aW5ncyk7XG5cbiAgICAgICAgLy8gSW5pdGlhbGl6YXRpb24gcGhhc2VcbiAgICAgICAgLy9YWFggVGhpcyBhc3N1bWVzIGF0IHRoaXMgc3RhZ2UsIGBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzYCBhcyBiZWVuIHNldCBmcm9tIHRoZSBkZWZhdWx0IG9wdGlvbnNcblxuICAgICAgICAvLyBPdmVyd3JpdGUgdGhlIGBkZWNpbWFsUGxhY2VzKmAgdmFsdWVzIGlmIHRoZSBgZGVjaW1hbFBsYWNlcypgIG9wdGlvbnMgYXJlIG5vdCBzZXQgaW4gdGhlIGBzZXR0aW5nc2BcbiAgICAgICAgLy8gU2V0cyBgZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyYCAocHJldmlvdXNseSBrbm93biBhcyBgc2NhbGVEZWNpbWFsUGxhY2VzYClcbiAgICAgICAgaWYgKHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cy51c2VEZWZhdWx0KSAge1xuICAgICAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyA9IHNldHRpbmdzLmRlY2ltYWxQbGFjZXM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ci51c2VEZWZhdWx0KSAge1xuICAgICAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyID0gc2V0dGluZ3MuZGVjaW1hbFBsYWNlcztcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlLnVzZURlZmF1bHQpICB7XG4gICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUgPSBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIHRoZSBhZGRpdGlvbmFsIGRlY2ltYWwgcGxhY2VzIHRvIHRoZSByYXcgdmFsdWVcbiAgICAgICAgbGV0IGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUgPSAwO1xuICAgICAgICBpZiAoc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yICYmIHNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvciAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5yYXdWYWx1ZURpdmlzb3Iubm9uZSkge1xuICAgICAgICAgICAgYWRkaXRpb25hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IFN0cmluZyhzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IpLmxlbmd0aCAtIDE7IC8vIGllLiBEaXZpZGluZyBieSAnMTAwJyBhZGRzIDIgZGVjaW1hbCBwbGFjZXMgdG8gdGhlIG5lZWRlZCBwcmVjaXNpb25cbiAgICAgICAgICAgIGlmIChhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDwgMCkge1xuICAgICAgICAgICAgICAgIGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gTWF0aC5tYXgoXG4gICAgICAgICAgICBNYXRoLm1heChzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIsIHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMpICsgYWRkaXRpb25hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSxcbiAgICAgICAgICAgIE51bWJlcihzZXR0aW5ncy5vcmlnaW5hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSkgKyBhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVjYWxjdWxhdGUgdGhlIG51bWJlciBkZSBkZWNpbWFsIHBsYWNlcyB0byBiZSB1c2VkIGJ5IHRoZSBBdXRvTnVtZXJpYyBvYmplY3QsIGZvciBlYWNoIG9mIGl0cyBzdGF0ZSwgYW5kIGZvciBpdHMgZm9ybWF0dGVkIGFuZCByYXcgdmFsdWUuXG4gICAgICogQnkgZGVmYXVsdCwgdGhlIGByYXdWYWx1ZWAgcHJlY2lzaW9uIGlzIHRoZSBzYW1lIGFzIHRoZSBmb3JtYXR0ZWQgdmFsdWUgb25lLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2QgaXMgY2xvc2UgdG8gdGhlIG9uZSBjYWxsZWQgZHVyaW5nIGluaXRpYWxpemF0aW9uLCBgX2NhbGN1bGF0ZURlY2ltYWxQbGFjZXNPbkluaXQoKWAsIGJ1dCB3aXRoIHNsaWdodCBkaWZmZXJlbmNlIHNvIHRoYXQgdGhlIGBkZWNpbWFsUGxhY2VzKmAgb3B0aW9ucyBhcmUgY29ycmVjdGx5IHVwZGF0ZWQgYXMgbmVlZGVkLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2RzIHNldCB0aGUgZm9sbG93aW5nIG9wdGlvbnMgYWNjb3JkaW5nbHkgdG8gdGhlaXIgb3duIHZhbHVlIGFuZCB0aGUgbWFuZGF0b3J5IGBkZWNpbWFsUGxhY2VzYCBvcHRpb246XG4gICAgICogLSBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgICAgIChudWxsYWJsZSlcbiAgICAgKiAtIGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciAgKG51bGxhYmxlKVxuICAgICAqIC0gZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyAobnVsbGFibGUpXG4gICAgICpcbiAgICAgKiBOb3RlOiB0aGUgYGRlY2ltYWxQbGFjZXNgIG9wdGlvbiBpcyBvbmx5IHVzZWQgaGVyZSBhbmQgb25seSBzZXJ2ZSB0byBkZWZpbmUgdGhvc2UgdGhyZWUgcHJldmlvdXMgb3B0aW9ucyB2YWx1ZS5cbiAgICAgKiBBdXRvTnVtZXJpYyB3aWxsIHRoZW4gKm9ubHkqIHVzZSBgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlYCwgYGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cmAgYW5kIGBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzYCBmcm9tIHRoZXJlLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2RzIGRpcmVjdGx5IG1vZGlmaWVzIHRoZSBgc2V0dGluZ3NgIG9iamVjdCBwYXNzZWQgYXMgYSBwYXJhbWV0ZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3MgVGhpcyBpcyBhbiBvYmplY3Qgd2l0aCB0aGUgbmV3IHNldHRpbmdzIHRvIHVzZS5cbiAgICAgKiBAcGFyYW0ge29iamVjdH0gY3VycmVudFNldHRpbmdzIFRoaXMgaXMgdGhlIGN1cnJlbnQgc2V0dGluZ3MgKGB0aGlzLnNldHRpbmdzYCkgdXNlZCBieSB0aGUgZWxlbWVudC5cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfY2FsY3VsYXRlRGVjaW1hbFBsYWNlc09uVXBkYXRlKHNldHRpbmdzLCBjdXJyZW50U2V0dGluZ3MgPSBudWxsKSB7XG4gICAgICAgIC8vIENoZWNrIHRoZSBgZGVjaW1hbFBsYWNlcypgIG9wdGlvbnMgYW5kIG91dHB1dCBhbnkgd2FybmluZ3MgYXMgbmVlZGVkLCBiZWZvcmUgbW9kaWZ5aW5nIHRob3NlIG9wdGlvbnNcbiAgICAgICAgdGhpcy5fdmFsaWRhdGVEZWNpbWFsUGxhY2VzUmF3VmFsdWUoc2V0dGluZ3MpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBwaGFzZVxuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGN1cnJlbnRTZXR0aW5ncykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFdoZW4gdXBkYXRpbmcgdGhlIHNldHRpbmdzLCB0aGUgcHJldmlvdXMgb25lcyBzaG91bGQgYmUgcGFzc2VkIGFzIGFuIGFyZ3VtZW50LmApO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgZGVjaW1hbFBsYWNlc0luT3B0aW9ucyA9ICdkZWNpbWFsUGxhY2VzJyBpbiBzZXR0aW5ncztcbiAgICAgICAgaWYgKCEoZGVjaW1hbFBsYWNlc0luT3B0aW9ucyB8fFxuICAgICAgICAgICAgICAgICdkZWNpbWFsUGxhY2VzUmF3VmFsdWUnIGluIHNldHRpbmdzIHx8XG4gICAgICAgICAgICAgICAgJ2RlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMnIGluIHNldHRpbmdzIHx8XG4gICAgICAgICAgICAgICAgJ2RlY2ltYWxQbGFjZXNTaG93bk9uQmx1cicgaW4gc2V0dGluZ3MgfHxcbiAgICAgICAgICAgICAgICAncmF3VmFsdWVEaXZpc29yJyBpbiBzZXR0aW5ncykpIHtcbiAgICAgICAgICAgIC8vIERvIE5vdGhpbmcgaWYgbm8gZGVjaW1hbCBwbGFjZXMtcmVsYXRlZCBvcHRpb25zIGFyZSBtb2RpZmllZFxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gT3ZlcndyaXRlIHRoZSBgZGVjaW1hbFBsYWNlcypgIHZhbHVlcyBpZiB0aGUgYGRlY2ltYWxQbGFjZXMqYCBvcHRpb25zIGFyZSBub3Qgc2V0IGluIHRoZSBgc2V0dGluZ3NgXG4gICAgICAgIGlmIChkZWNpbWFsUGxhY2VzSW5PcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAoISgnZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cycgaW4gc2V0dGluZ3MpIHx8XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzLnVzZURlZmF1bHQpICB7XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyA9IHNldHRpbmdzLmRlY2ltYWxQbGFjZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICghKCdkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXInIGluIHNldHRpbmdzKSB8fFxuICAgICAgICAgICAgICAgIHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIudXNlRGVmYXVsdCkgIHtcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIgPSBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAoISgnZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlJyBpbiBzZXR0aW5ncykgfHxcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlLnVzZURlZmF1bHQpICB7XG4gICAgICAgICAgICAgICAgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gc2V0dGluZ3MuZGVjaW1hbFBsYWNlcztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZChzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzKSkge1xuICAgICAgICAgICAgICAgIHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMgPSBjdXJyZW50U2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cikpIHtcbiAgICAgICAgICAgICAgICBzZXR0aW5ncy5kZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIgPSBjdXJyZW50U2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkIHRoZSBhZGRpdGlvbmFsIGRlY2ltYWwgcGxhY2VzIHRvIHRoZSByYXcgdmFsdWVcbiAgICAgICAgbGV0IGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUgPSAwO1xuICAgICAgICBpZiAoc2V0dGluZ3MucmF3VmFsdWVEaXZpc29yICYmIHNldHRpbmdzLnJhd1ZhbHVlRGl2aXNvciAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5yYXdWYWx1ZURpdmlzb3Iubm9uZSkge1xuICAgICAgICAgICAgYWRkaXRpb25hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IFN0cmluZyhzZXR0aW5ncy5yYXdWYWx1ZURpdmlzb3IpLmxlbmd0aCAtIDE7IC8vIGllLiBEaXZpZGluZyBieSAnMTAwJyBhZGRzIDIgZGVjaW1hbCBwbGFjZXMgdG8gdGhlIG5lZWRlZCBwcmVjaXNpb25cbiAgICAgICAgICAgIGlmIChhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDwgMCkge1xuICAgICAgICAgICAgICAgIGFkZGl0aW9uYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUgPSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCFzZXR0aW5ncy5kZWNpbWFsUGxhY2VzICYmICFzZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpIHtcbiAgICAgICAgICAgIHNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IE1hdGgubWF4KFxuICAgICAgICAgICAgICAgIE1hdGgubWF4KHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciwgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cykgKyBhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlLFxuICAgICAgICAgICAgICAgIE51bWJlcihjdXJyZW50U2V0dGluZ3Mub3JpZ2luYWxEZWNpbWFsUGxhY2VzUmF3VmFsdWUpICsgYWRkaXRpb25hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHNldHRpbmdzLmRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA9IE1hdGgubWF4KFxuICAgICAgICAgICAgICAgIE1hdGgubWF4KHNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciwgc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cykgKyBhZGRpdGlvbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlLFxuICAgICAgICAgICAgICAgIE51bWJlcihzZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUpICsgYWRkaXRpb25hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZVxuICAgICAgICAgICAgKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEFuYWx5emUgYW5kIHNhdmUgdGhlIG1pbmltdW1WYWx1ZSBhbmQgbWF4aW11bVZhbHVlIGludGVnZXIgc2l6ZSBmb3IgbGF0ZXIgdXNlc1xuICAgICAqL1xuICAgIF9jYWxjdWxhdGVWTWluQW5kVk1heEludGVnZXJTaXplcygpIHtcbiAgICAgICAgbGV0IFttYXhpbXVtVmFsdWVJbnRlZ2VyUGFydF0gPSB0aGlzLnNldHRpbmdzLm1heGltdW1WYWx1ZS50b1N0cmluZygpLnNwbGl0KCcuJyk7XG4gICAgICAgIGxldCBbbWluaW11bVZhbHVlSW50ZWdlclBhcnRdID0gKCF0aGlzLnNldHRpbmdzLm1pbmltdW1WYWx1ZSAmJiB0aGlzLnNldHRpbmdzLm1pbmltdW1WYWx1ZSAhPT0gMCk/W106dGhpcy5zZXR0aW5ncy5taW5pbXVtVmFsdWUudG9TdHJpbmcoKS5zcGxpdCgnLicpO1xuICAgICAgICBtYXhpbXVtVmFsdWVJbnRlZ2VyUGFydCA9IG1heGltdW1WYWx1ZUludGVnZXJQYXJ0LnJlcGxhY2UoJy0nLCAnJyk7XG4gICAgICAgIG1pbmltdW1WYWx1ZUludGVnZXJQYXJ0ID0gbWluaW11bVZhbHVlSW50ZWdlclBhcnQucmVwbGFjZSgnLScsICcnKTtcblxuICAgICAgICB0aGlzLnNldHRpbmdzLm1JbnRQb3MgPSBNYXRoLm1heChtYXhpbXVtVmFsdWVJbnRlZ2VyUGFydC5sZW5ndGgsIDEpO1xuICAgICAgICB0aGlzLnNldHRpbmdzLm1JbnROZWcgPSBNYXRoLm1heChtaW5pbXVtVmFsdWVJbnRlZ2VyUGFydC5sZW5ndGgsIDEpO1xuICAgIH1cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBhbHRlcm5hdGl2ZSBkZWNpbWFsIHNlcGFyYXRvciBrZXkuXG4gICAgICovXG4gICAgX3NldEFsdGVybmF0aXZlRGVjaW1hbFNlcGFyYXRvckNoYXJhY3RlcigpIHtcbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbCh0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSkgJiYgTnVtYmVyKHRoaXMuc2V0dGluZ3MuZGVjaW1hbFBsYWNlcykgPiAwKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyID09PSAnLicgJiYgdGhpcy5zZXR0aW5ncy5kaWdpdEdyb3VwU2VwYXJhdG9yICE9PSAnLCcpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSA9ICcsJztcbiAgICAgICAgICAgIH0gZWxzZSBpZiAodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyID09PSAnLCcgJiYgdGhpcy5zZXR0aW5ncy5kaWdpdEdyb3VwU2VwYXJhdG9yICE9PSAnLicpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSA9ICcuJztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENhY2hlcyByZWd1bGFyIGV4cHJlc3Npb25zIGZvciBfc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gcmVnZXhcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NhY2hlc1VzdWFsUmVndWxhckV4cHJlc3Npb25zKHNldHRpbmdzLCByZWdleCkge1xuICAgICAgICBjb25zdCBhbGxOdW1iZXJzUmVnID0gJ1swLTldJztcbiAgICAgICAgY29uc3Qgbm9BbGxOdW1iZXJzUmVnID0gJ1teMC05XSc7XG5cbiAgICAgICAgLy8gVGVzdCBpZiB0aGVyZSBpcyBhIG5lZ2F0aXZlIGNoYXJhY3RlciBpbiB0aGUgc3RyaW5nXG4gICAgICAgIGNvbnN0IGFOZWdSZWcgPSBzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXI/YChbLVxcXFwke3NldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlcn1dPylgOicoLT8pJztcbiAgICAgICAgcmVnZXguYU5lZ1JlZ0F1dG9TdHJpcCA9IGFOZWdSZWc7XG5cbiAgICAgICAgbGV0IG5lZ2F0aXZlU2lnblJlZ1BhcnQ7XG4gICAgICAgIGlmIChzZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgIG5lZ2F0aXZlU2lnblJlZ1BhcnQgPSBgXFxcXCR7c2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyfWA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuZWdhdGl2ZVNpZ25SZWdQYXJ0ID0gJyc7XG4gICAgICAgIH1cblxuICAgICAgICBzZXR0aW5ncy5za2lwRmlyc3RBdXRvU3RyaXAgPSBuZXcgUmVnRXhwKGAke2FOZWdSZWd9W14tJHtuZWdhdGl2ZVNpZ25SZWdQYXJ0fVxcXFwke3NldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXJ9JHthbGxOdW1iZXJzUmVnfV0uKj8oJHthbGxOdW1iZXJzUmVnfXxcXFxcJHtzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyfSR7YWxsTnVtYmVyc1JlZ30pYCk7XG4gICAgICAgIHNldHRpbmdzLnNraXBMYXN0QXV0b1N0cmlwID0gbmV3IFJlZ0V4cChgKCR7YWxsTnVtYmVyc1JlZ31cXFxcJHtzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyfT8pW15cXFxcJHtzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyfSR7YWxsTnVtYmVyc1JlZ31dJHtub0FsbE51bWJlcnNSZWd9KiRgKTtcblxuICAgICAgICBjb25zdCBhbGxvd2VkID0gYC0wMTIzNDU2Nzg5XFxcXCR7c2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcn1gO1xuICAgICAgICBzZXR0aW5ncy5hbGxvd2VkQXV0b1N0cmlwID0gbmV3IFJlZ0V4cChgW14ke2FsbG93ZWR9XWAsICdnJyk7XG4gICAgICAgIHNldHRpbmdzLm51bVJlZ0F1dG9TdHJpcCA9IG5ldyBSZWdFeHAoYCR7YU5lZ1JlZ30oPzpcXFxcJHtzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyfT8oJHthbGxOdW1iZXJzUmVnfStcXFxcJHtzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyfSR7YWxsTnVtYmVyc1JlZ30rKXwoJHthbGxOdW1iZXJzUmVnfSooPzpcXFxcJHtzZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyfSR7YWxsTnVtYmVyc1JlZ30qKT8pKWApO1xuXG4gICAgICAgIC8vIFVzaW5nIHRoaXMgcmVnZXggdmVyc2lvbiBgXiR7cmVnZXguYU5lZ1JlZ0F1dG9TdHJpcH0wKihcXFxcZHwkKWAgZW50aXJlbHkgY2xlYXIgdGhlIGlucHV0IG9uIGJsdXJcbiAgICAgICAgc2V0dGluZ3Muc3RyaXBSZWcgPSBuZXcgUmVnRXhwKGBeJHtyZWdleC5hTmVnUmVnQXV0b1N0cmlwfTAqKCR7YWxsTnVtYmVyc1JlZ30pYCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTW9kaWZ5IHRoZSB1c2VyIHNldHRpbmdzIHRvIG1ha2UgdGhlbSAnZXhwbG9pdGFibGUnIGxhdGVyLlxuICAgICAqL1xuICAgIF90cmFuc2Zvcm1PcHRpb25zVmFsdWVzVG9EZWZhdWx0VHlwZXMoKSB7XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHRoaXMuc2V0dGluZ3MpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB2YWx1ZSA9IHRoaXMuc2V0dGluZ3Nba2V5XTtcblxuICAgICAgICAgICAgICAgIC8vIENvbnZlcnQgdGhlIHN0cmluZ3MgJ3RydWUnIGFuZCAnZmFsc2UnIHRvIGJvb2xlYW5zXG4gICAgICAgICAgICAgICAgaWYgKHZhbHVlID09PSAndHJ1ZScgfHwgdmFsdWUgPT09ICdmYWxzZScpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5nc1trZXldID0gdmFsdWUgPT09ICd0cnVlJztcbiAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAvLyBDb252ZXJ0IG51bWJlcnMgaW4gb3B0aW9ucyB0byBzdHJpbmdzXG4gICAgICAgICAgICAgICAgLy9UT0RPIE9ubHkgdHJhbnNmb3JtIHRoZSB2YWx1ZXMgb2YgdHlwZSAnTnVtYmVyJyB0byAnU3RyaW5nJyBpZiBpdCdzIGEgY3VycmVuY3kgbnVtYmVyIChzbyB0aGF0IHdlIGNhbiBoYXZlIGJpZyBudW1iZXJzKS4gRG8gbm90IGNvbnZlcnQgb3RoZXIgbnVtYmVycyAoaWUuIGBoaXN0b3J5U2l6ZWApXG4gICAgICAgICAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5nc1trZXldID0gdmFsdWUudG9TdHJpbmcoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IHRoZSBvbGQgc2V0dGluZ3Mgb3B0aW9ucyBuYW1lIHRvIG5ldyBvbmVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IG9wdGlvbnNcbiAgICAgKi9cbiAgICBzdGF0aWMgX2NvbnZlcnRPbGRPcHRpb25zVG9OZXdPbmVzKG9wdGlvbnMpIHtcbiAgICAgICAgLy9UT0RPIERlbGV0ZSB0aGlzIGZ1bmN0aW9uIG9uY2UgdGhlIG9sZCBvcHRpb25zIGFyZSBub3QgdXNlZCBhbnltb3JlXG4gICAgICAgIGNvbnN0IG9sZE9wdGlvbnNDb252ZXJ0ZXIgPSB7XG4gICAgICAgICAgICAvLyBPbGQgb3B0aW9uIG5hbWVzLCB3aXRoIHRoZWlyIGNvcnJlc3BvbmRpbmcgbmV3IG5hbWVzXG4gICAgICAgICAgICBhU2VwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnZGlnaXRHcm91cFNlcGFyYXRvcicsXG4gICAgICAgICAgICBuU2VwICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnc2hvd09ubHlOdW1iZXJzT25Gb2N1cycsXG4gICAgICAgICAgICBkR3JvdXAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnZGlnaXRhbEdyb3VwU3BhY2luZycsXG4gICAgICAgICAgICBhRGVjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnZGVjaW1hbENoYXJhY3RlcicsXG4gICAgICAgICAgICBhbHREZWMgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlJyxcbiAgICAgICAgICAgIGFTaWduICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdjdXJyZW5jeVN5bWJvbCcsXG4gICAgICAgICAgICBwU2lnbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQnLFxuICAgICAgICAgICAgcE5lZyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ25lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50JyxcbiAgICAgICAgICAgIGFTdWZmaXggICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdzdWZmaXhUZXh0JyxcbiAgICAgICAgICAgIG9MaW1pdHMgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdvdmVycmlkZU1pbk1heExpbWl0cycsXG4gICAgICAgICAgICB2TWF4ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnbWF4aW11bVZhbHVlJyxcbiAgICAgICAgICAgIHZNaW4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdtaW5pbXVtVmFsdWUnLFxuICAgICAgICAgICAgbURlYyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2RlY2ltYWxQbGFjZXNPdmVycmlkZScsXG4gICAgICAgICAgICBlRGVjICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cycsXG4gICAgICAgICAgICBzY2FsZURlY2ltYWwgICAgICAgICAgICAgICAgICAgICAgOiAnZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyJyxcbiAgICAgICAgICAgIGFTdG9yICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdzYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlJyxcbiAgICAgICAgICAgIG1Sb3VuZCAgICAgICAgICAgICAgICAgICAgICAgICAgICA6ICdyb3VuZGluZ01ldGhvZCcsXG4gICAgICAgICAgICBhUGFkICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnYWxsb3dEZWNpbWFsUGFkZGluZycsXG4gICAgICAgICAgICBuQnJhY2tldCAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnbmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXInLFxuICAgICAgICAgICAgd0VtcHR5ICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2VtcHR5SW5wdXRCZWhhdmlvcicsXG4gICAgICAgICAgICBsWmVybyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiAnbGVhZGluZ1plcm8nLFxuICAgICAgICAgICAgYUZvcm0gICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2Zvcm1hdE9uUGFnZUxvYWQnLFxuICAgICAgICAgICAgc051bWJlciAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ3NlbGVjdE51bWJlck9ubHknLFxuICAgICAgICAgICAgYW5EZWZhdWx0ICAgICAgICAgICAgICAgICAgICAgICAgIDogJ2RlZmF1bHRWYWx1ZU92ZXJyaWRlJyxcbiAgICAgICAgICAgIHVuU2V0T25TdWJtaXQgICAgICAgICAgICAgICAgICAgICA6ICd1bmZvcm1hdE9uU3VibWl0JyxcbiAgICAgICAgICAgIG91dHB1dFR5cGUgICAgICAgICAgICAgICAgICAgICAgICA6ICdvdXRwdXRGb3JtYXQnLFxuICAgICAgICAgICAgZGVidWcgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogJ3Nob3dXYXJuaW5ncycsXG5cbiAgICAgICAgICAgIC8vIEN1cnJlbnQgb3B0aW9ucyA6XG4gICAgICAgICAgICBhbGxvd0RlY2ltYWxQYWRkaW5nICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgY2FyZXRQb3NpdGlvbk9uRm9jdXMgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGNyZWF0ZUxvY2FsTGlzdCAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBjdXJyZW5jeVN5bWJvbCAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGRlY2ltYWxDaGFyYWN0ZXIgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZGVjaW1hbFBsYWNlcyAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGRlZmF1bHRWYWx1ZU92ZXJyaWRlICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBkaWdpdGFsR3JvdXBTcGFjaW5nICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZGlnaXRHcm91cFNlcGFyYXRvciAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGRpdmlzb3JXaGVuVW5mb2N1c2VkICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBlbXB0eUlucHV0QmVoYXZpb3IgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgZmFpbE9uVW5rbm93bk9wdGlvbiAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGZvcm1hdE9uUGFnZUxvYWQgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBoaXN0b3J5U2l6ZSAgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgaXNDYW5jZWxsYWJsZSAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIGxlYWRpbmdaZXJvICAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBtYXhpbXVtVmFsdWUgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgbWluaW11bVZhbHVlICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG1vZGlmeVZhbHVlT25XaGVlbCAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBuZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG5vRXZlbnRMaXN0ZW5lcnMgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBvbkludmFsaWRQYXN0ZSAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgb3V0cHV0Rm9ybWF0ICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG92ZXJyaWRlTWluTWF4TGltaXRzICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICByYXdWYWx1ZURpdmlzb3IgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgcmVhZE9ubHkgICAgICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHJvdW5kaW5nTWV0aG9kICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBzYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgc2VsZWN0TnVtYmVyT25seSAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHNlbGVjdE9uRm9jdXMgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBzZXJpYWxpemVTcGFjZXMgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgc2hvd09ubHlOdW1iZXJzT25Gb2N1cyAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHNob3dQb3NpdGl2ZVNpZ24gICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBzaG93V2FybmluZ3MgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgc3R5bGVSdWxlcyAgICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHN1ZmZpeFRleHQgICAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBzeW1ib2xXaGVuVW5mb2N1c2VkICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgdW5mb3JtYXRPbkhvdmVyICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHVuZm9ybWF0T25TdWJtaXQgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICB3aGVlbFN0ZXAgICAgICAgICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuXG4gICAgICAgICAgICAvLyBBZGRpdGlvbmFsIGluZm9ybWF0aW9uIHRoYXQgYXJlIGFkZGVkIHRvIHRoZSBgc2V0dGluZ3NgIG9iamVjdCA6XG4gICAgICAgICAgICAvL0ZJWE1FIEZpbmQgYSB3YXkgdG8gZXhjbHVkZSB0aG9zZSBpbnRlcm5hbCBkYXRhIGZyb20gdGhlIHNldHRpbmdzIG9iamVjdCAoaWRlYWxseSBieSB1c2luZyBhbm90aGVyIG9iamVjdCwgb3IgYmV0dGVyIHlldCwgY2xhc3MgYXR0cmlidXRlcykgLS0+XG4gICAgICAgICAgICBhbGxvd2VkQXV0b1N0cmlwICAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgbUludE5lZyAgICAgICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG1JbnRQb3MgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBuZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgbnVtUmVnQXV0b1N0cmlwICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIG9yaWdpbmFsRGVjaW1hbFBsYWNlcyAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBvcmlnaW5hbERlY2ltYWxQbGFjZXNSYXdWYWx1ZSAgICAgOiB0cnVlLFxuICAgICAgICAgICAgcG9zaXRpdmVTaWduQ2hhcmFjdGVyICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgIHNraXBGaXJzdEF1dG9TdHJpcCAgICAgICAgICAgICAgICA6IHRydWUsXG4gICAgICAgICAgICBza2lwTGFzdEF1dG9TdHJpcCAgICAgICAgICAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgc3RyaXBSZWcgICAgICAgICAgICAgICAgICAgICAgICAgIDogdHJ1ZSxcbiAgICAgICAgfTtcblxuICAgICAgICBmb3IgKGNvbnN0IG9wdGlvbiBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBpZiAob3B0aW9ucy5oYXNPd25Qcm9wZXJ0eShvcHRpb24pKSB7XG4gICAgICAgICAgICAgICAgaWYgKG9sZE9wdGlvbnNDb252ZXJ0ZXJbb3B0aW9uXSA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB0aGUgb3B0aW9uIGlzIGEgJ25ldycgb3B0aW9uLCB3ZSBjb250aW51ZSBsb29waW5nXG4gICAgICAgICAgICAgICAgICAgIGNvbnRpbnVlO1xuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIGlmIChvbGRPcHRpb25zQ29udmVydGVyLmhhc093blByb3BlcnR5KG9wdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gRWxzZSB3ZSBoYXZlIGFuICdvbGQnIG9wdGlvbiBuYW1lXG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLndhcm5pbmcoYFlvdSBhcmUgdXNpbmcgdGhlIGRlcHJlY2F0ZWQgb3B0aW9uIG5hbWUgJyR7b3B0aW9ufScuIFBsZWFzZSB1c2UgJyR7b2xkT3B0aW9uc0NvbnZlcnRlcltvcHRpb25dfScgaW5zdGVhZCBmcm9tIG5vdyBvbi4gVGhlIG9sZCBvcHRpb24gbmFtZSB3aWxsIGJlIGRyb3BwZWQgdmVyeSBzb29u4oSiLmAsIHRydWUpO1xuXG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZW4gd2UgbW9kaWZ5IHRoZSBpbml0aWFsIG9wdGlvbiBvYmplY3QgdG8gdXNlIHRoZSBuZXcgb3B0aW9ucyBpbnN0ZWFkIG9mIHRoZSBvbGQgb25lc1xuICAgICAgICAgICAgICAgICAgICBvcHRpb25zW29sZE9wdGlvbnNDb252ZXJ0ZXJbb3B0aW9uXV0gPSBvcHRpb25zW29wdGlvbl07XG4gICAgICAgICAgICAgICAgICAgIGRlbGV0ZSBvcHRpb25zW29wdGlvbl07XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmIChvcHRpb25zLmZhaWxPblVua25vd25PcHRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gLi4ub3IgdGhlIG9wdGlvbiBuYW1lIGlzIHVua25vd24uIFRoaXMgbWVhbnMgdGhlcmUgaXMgYSBwcm9ibGVtIHdpdGggdGhlIG9wdGlvbnMgb2JqZWN0LCB0aGVyZWZvcmUgd2UgdGhyb3cgYW4gZXJyb3IuXG4gICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYE9wdGlvbiBuYW1lICcke29wdGlvbn0nIGlzIHVua25vd24uIFBsZWFzZSBmaXggdGhlIG9wdGlvbnMgcGFzc2VkIHRvIGF1dG9OdW1lcmljYCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKCdtRGVjJyBpbiBvcHRpb25zKSB7XG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKCdUaGUgb2xkIGBtRGVjYCBvcHRpb24gaGFzIGJlZW4gZGVwcmVjYXRlZCBpbiBmYXZvciBvZiBtb3JlIGFjY3VyYXRlIG9wdGlvbnMgOyBgZGVjaW1hbFBsYWNlc2AsIGBkZWNpbWFsUGxhY2VzUmF3VmFsdWVgLCBgZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1c2AgYW5kIGBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXJgLicsIHRydWUpO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQW5hbHlzZSB0aGUgc2V0dGluZ3Mvb3B0aW9ucyBwYXNzZWQgYnkgdGhlIHVzZXIsIHZhbGlkYXRlIGFuZCBjbGVhbiB0aGVtLCB0aGVuIHNldCB0aGVtIGludG8gYHRoaXMuc2V0dGluZ3NgLlxuICAgICAqIE5vdGU6IFRoaXMgc2V0cyB0aGUgc2V0dGluZ3MgdG8gYG51bGxgIGlmIHNvbWVob3cgdGhlIHNldHRpbmdzIG9iamV0IGlzIHVuZGVmaW5lZCBvciBlbXB0eVxuICAgICAqICAgICAgIElmIG9ubHkgYGRlY2ltYWxQbGFjZXNgIGlzIGRlZmluZWQgaW4gdGhlIG9wdGlvbiwgb3ZlcndyaXRlIHRoZSBvdGhlciBkZWNpbWFsUGxhY2VzKiBvcHRpb25zLCBvdGhlcndpc2UsIHVzZSB0aG9zZSBvcHRpb25zXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb3B0aW9uc1xuICAgICAqIEBwYXJhbSB7Ym9vbGVhbn0gdXBkYXRlIC0gSWYgc2V0IHRvIGB0cnVlYCwgdGhlbiB0aGUgc2V0dGluZ3MgYWxyZWFkeSBleGlzdHMgYW5kIHRoaXMgZnVuY3Rpb24gb25seSB1cGRhdGVzIHRoZW0gaW5zdGVhZCBvZiByZWNyZWF0aW5nIHRoZW0gZnJvbSBzY3JhdGNoXG4gICAgICogQHRocm93c1xuICAgICAqL1xuICAgIF9zZXRTZXR0aW5ncyhvcHRpb25zLCB1cGRhdGUgPSBmYWxzZSkge1xuICAgICAgICAvLyBJZiB0aGUgdXNlciB1c2VkIG9sZCBvcHRpb25zLCB3ZSBjb252ZXJ0IHRoZW0gdG8gbmV3IG9uZXNcbiAgICAgICAgaWYgKHVwZGF0ZSB8fCAhQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMpKSB7XG4gICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl9jb252ZXJ0T2xkT3B0aW9uc1RvTmV3T25lcyhvcHRpb25zKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh1cGRhdGUpIHtcbiAgICAgICAgICAgIC8vIFRoZSBzZXR0aW5ncyBhcmUgdXBkYXRlZFxuICAgICAgICAgICAgLy8gVXBkYXRlIHRoZSBvcmlnaW5hbCBkYXRhLCBpZiBpdCBoYXMgY2hhbmdlZFxuICAgICAgICAgICAgY29uc3QgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlSW5PcHRpb25zID0gJ2RlY2ltYWxQbGFjZXNSYXdWYWx1ZScgaW4gb3B0aW9ucztcbiAgICAgICAgICAgIGlmIChkZWNpbWFsUGxhY2VzUmF3VmFsdWVJbk9wdGlvbnMpIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLm9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gb3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbnN0IGRlY2ltYWxQbGFjZXNJbk9wdGlvbnMgPSAnZGVjaW1hbFBsYWNlcycgaW4gb3B0aW9ucztcbiAgICAgICAgICAgIGlmIChkZWNpbWFsUGxhY2VzSW5PcHRpb25zKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5vcmlnaW5hbERlY2ltYWxQbGFjZXMgPSBvcHRpb25zLmRlY2ltYWxQbGFjZXM7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFRoZW4gdXBkYXRlIGFsbCB0aGUgYGRlY2ltYWxQbGFjZXMqYCBvcHRpb25zXG4gICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl9jYWxjdWxhdGVEZWNpbWFsUGxhY2VzT25VcGRhdGUob3B0aW9ucywgdGhpcy5zZXR0aW5ncyk7XG5cbiAgICAgICAgICAgIC8vIEZpbmFsbHkgZ2VuZXJhdGUgdGhlIHVwZGF0ZWQgc2V0dGluZ3Mgb2JqZWN0IHRvIHVzZVxuICAgICAgICAgICAgdGhpcy5fbWVyZ2VTZXR0aW5ncyhvcHRpb25zKTsgLy9UT0RPIENoZWNrIHRoYXQgdGhlIGBzdHlsZVJ1bGVzYCBvcHRpb24gaXMgY29ycmVjdGx5IGNsb25lZCAoZHVlIHRvIGRlcHRoIGNsb25pbmcgbGltaXRhdGlvbilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIFRoZSBzZXR0aW5ncyBhcmUgZ2VuZXJhdGVkIGZvciB0aGUgZmlyc3QgdGltZVxuICAgICAgICAgICAgdGhpcy5zZXR0aW5ncyA9IHt9O1xuICAgICAgICAgICAgLy8gSWYgd2UgY291bGRuJ3QgZ3JhYiBhbnkgc2V0dGluZ3MsIGNyZWF0ZSB0aGVtIGZyb20gdGhlIGRlZmF1bHQgb25lcyBhbmQgY29tYmluZSB0aGVtIHdpdGggdGhlIG9wdGlvbnMgcGFzc2VkIGFzIGEgcGFyYW1ldGVyIGFzIHdlbGwgYXMgd2l0aCB0aGUgSFRNTDUgYGRhdGEtKmAgaW5mbyAodmlhIGB0aGlzLmRvbUVsZW1lbnQuZGF0YXNldGApLCBpZiBhbnkuXG4gICAgICAgICAgICB0aGlzLl9tZXJnZVNldHRpbmdzKHRoaXMuY29uc3RydWN0b3IuZ2V0RGVmYXVsdENvbmZpZygpLCB0aGlzLmRvbUVsZW1lbnQuZGF0YXNldCwgb3B0aW9ucywgeyByYXdWYWx1ZSA6IHRoaXMuZGVmYXVsdFJhd1ZhbHVlIH0pO1xuICAgICAgICAgICAgdGhpcy5jYXJldEZpeCA9IGZhbHNlO1xuICAgICAgICAgICAgdGhpcy50aHJvd0lucHV0ID0gdHJ1ZTsgLy8gVGhyb3cgaW5wdXQgZXZlbnRcbiAgICAgICAgICAgIHRoaXMuYWxsb3dlZFRhZ0xpc3QgPSBBdXRvTnVtZXJpY0VudW0uYWxsb3dlZFRhZ0xpc3Q7XG4gICAgICAgICAgICB0aGlzLnJ1bk9uY2UgPSBmYWxzZTtcbiAgICAgICAgICAgIHRoaXMuaG92ZXJlZFdpdGhBbHQgPSBmYWxzZTsgLy8gS2VlcCB0cmFja3MgaWYgdGhlIGN1cnJlbnQgQXV0b051bWVyaWMgZWxlbWVudCBpcyBob3ZlcmVkIGJ5IHRoZSBtb3VzZSBjdXJzb3Igd2hpbGUgYEFsdGAgaXMgcHJlc3NlZFxuICAgICAgICAgICAgdGhpcy5hbmRyb2lkU2VsZWN0aW9uU3RhcnQgPSBudWxsOyAvLyBJZiBgbnVsbGAsIHRoZW4gd2UgYXJlIG5vdCBvbiBhbiBBbmRyb2lkIGRldmljZSAodGhlIGtleUNvZGUgaXMgbm90IGFsd2F5cyBlcXVhbCB0byAyMjkpXG4gICAgICAgIH1cblxuICAgICAgICAvLyBNb2RpZnkgdGhlIHVzZXIgc2V0dGluZ3MgdG8gbWFrZSB0aGVtICdleHBsb2l0YWJsZSdcbiAgICAgICAgdGhpcy5fdHJhbnNmb3JtT3B0aW9uc1ZhbHVlc1RvRGVmYXVsdFR5cGVzKCk7XG5cbiAgICAgICAgLy8gSW1tZWRpYXRlbHkgcnVuIHRoZSBjYWxsYmFja3MgdGhhdCBjb3VsZCB1cGRhdGUgdGhlIHNldHRpbmdzIG9iamVjdFxuICAgICAgICB0aGlzLl9ydW5DYWxsYmFja3NGb3VuZEluVGhlU2V0dGluZ3NPYmplY3QoKTtcblxuICAgICAgICAvLyBJbXByb3ZlIHRoZSBgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnRgIG9wdGlvbiBpZiBuZWVkZWRcbiAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fY29ycmVjdE5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50T3B0aW9uKHRoaXMuc2V0dGluZ3MpO1xuXG4gICAgICAgIC8vIFNldCB0aGUgYGNhcmV0UG9zaXRpb25PbkZvY3VzYCBhbmQgYHNlbGVjdE9uRm9jdXNgIG9wdGlvbnMgc28gdGhhdCB0aGV5IGRvIG5vdCBjb25mbGljdCwgaWYgb25lIG9mIHRob3NlIGhhdmUgYmVlbiBzZXQgbWFudWFsbHkgYnkgdGhlIHVzZXIuXG4gICAgICAgIC8vIElmIG9yZGVyIHRvIGNoZWNrIHRoYXQsIHdlIHRha2UgYSBsb29rIGF0IHRoZSBvcmlnaW5hbCBvcHRpb25zIHRoZSB1c2VyIHBhc3NlZCBhcyBhbiBhcmd1bWVudCwgbm90IGB0aGlzLnNldHRpbmdzYCB0aGF0IGhhdmUgYmVlbiBtZXJnZWQgd2l0aCB0aGUgZGVmYXVsdCBzZXR0aW5ncy4gLy9UT0RPIENoZWNrIHRoZSB2YWxpZGl0eSBvZiB0aGF0IGNvbW1lbnRcbiAgICAgICAgdGhpcy5jb25zdHJ1Y3Rvci5fY29ycmVjdENhcmV0UG9zaXRpb25PbkZvY3VzQW5kU2VsZWN0T25Gb2N1c09wdGlvbnModGhpcy5zZXR0aW5ncyk7XG5cbiAgICAgICAgLy8gU2V0IHRoZSBuZWdhdGl2ZSBhbmQgcG9zaXRpdmUgc2lnbnMsIGFzIG5lZWRlZFxuICAgICAgICB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciA9IHRoaXMuc2V0dGluZ3MubWluaW11bVZhbHVlIDwgMCA/ICctJyA6ICcnO1xuICAgICAgICB0aGlzLnNldHRpbmdzLnBvc2l0aXZlU2lnbkNoYXJhY3RlciA9IHRoaXMuc2V0dGluZ3MubWF4aW11bVZhbHVlID49IDAgPyAnKycgOiAnJztcblxuICAgICAgICAvLyBDYWxjdWxhdGUgdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyAoZHVyaW5nIHRoZSBlbGVtZW50IGluaXRpYWxpemF0aW9uKVxuICAgICAgICBpZiAoIXVwZGF0ZSkge1xuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHRoZSBgb3JpZ2luYWxEZWNpbWFsUGxhY2VzYCBpbmZvIGlzIHNldFxuICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChvcHRpb25zKSB8fCAhb3B0aW9ucy5kZWNpbWFsUGxhY2VzKSB7XG4gICAgICAgICAgICAgICAgdGhpcy5zZXR0aW5ncy5vcmlnaW5hbERlY2ltYWxQbGFjZXMgPSBudWxsO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLnNldHRpbmdzLm9yaWdpbmFsRGVjaW1hbFBsYWNlcyA9IG9wdGlvbnMuZGVjaW1hbFBsYWNlcztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gU2F2ZSB0aGUgYG9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlYCBpbmZvXG4gICAgICAgICAgICB0aGlzLnNldHRpbmdzLm9yaWdpbmFsRGVjaW1hbFBsYWNlc1Jhd1ZhbHVlID0gdGhpcy5zZXR0aW5ncy5kZWNpbWFsUGxhY2VzUmF3VmFsdWU7XG5cbiAgICAgICAgICAgIC8vIFRoZW4gdXBkYXRlIGFsbCB0aGUgYGRlY2ltYWxQbGFjZXMqYCBvcHRpb25zXG4gICAgICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl9jYWxjdWxhdGVEZWNpbWFsUGxhY2VzT25Jbml0KHRoaXMuc2V0dGluZ3MpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gQWRkaXRpb25hbCBjaGFuZ2VzIHRvIHRoZSBzZXR0aW5ncyBvYmplY3RcbiAgICAgICAgdGhpcy5fY2FsY3VsYXRlVk1pbkFuZFZNYXhJbnRlZ2VyU2l6ZXMoKTtcbiAgICAgICAgdGhpcy5fc2V0QWx0ZXJuYXRpdmVEZWNpbWFsU2VwYXJhdG9yQ2hhcmFjdGVyKCk7XG4gICAgICAgIHRoaXMuX3NldFRyYWlsaW5nTmVnYXRpdmVTaWduSW5mbygpO1xuICAgICAgICB0aGlzLnJlZ2V4ID0ge307IC8vIENyZWF0ZSB0aGUgb2JqZWN0IHRoYXQgd2lsbCBzdG9yZSB0aGUgcmVndWxhciBleHByZXNzaW9uc1xuICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLl9jYWNoZXNVc3VhbFJlZ3VsYXJFeHByZXNzaW9ucyh0aGlzLnNldHRpbmdzLCB0aGlzLnJlZ2V4KTtcbiAgICAgICAgdGhpcy5fc2V0QnJhY2tldHMoKTtcblxuICAgICAgICAvLyBWYWxpZGF0ZSB0aGUgc2V0dGluZ3MuIEJvdGggdGVzdHMgdGhyb3dzIGlmIG5lY2Vzc2FyeS5cbiAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzRW1wdHlPYmoodGhpcy5zZXR0aW5ncykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoJ1VuYWJsZSB0byBzZXQgdGhlIHNldHRpbmdzLCB0aG9zZSBhcmUgaW52YWxpZCA7IGFuIGVtcHR5IG9iamVjdCB3YXMgZ2l2ZW4uJyk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmNvbnN0cnVjdG9yLnZhbGlkYXRlKHRoaXMuc2V0dGluZ3MsIGZhbHNlLCBvcHRpb25zKTtcblxuICAgICAgICAvLyBPcmlnaW5hbCBzZXR0aW5ncyBzYXZlZCBmb3IgdXNlIHdoZW4gZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cywgZGl2aXNvcldoZW5VbmZvY3VzZWQgJiBzaG93T25seU51bWJlcnNPbkZvY3VzIG9wdGlvbnMgYXJlIGJlaW5nIHVzZWRcbiAgICAgICAgdGhpcy5fa2VlcEFuT3JpZ2luYWxTZXR0aW5nc0NvcHkoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDb252ZXJ0IHRoZSBgdmFsdWVgIHBhcmFtZXRlciB0aGF0IGNhbiBlaXRoZXIgYmUgOlxuICAgICAqIC0gYSByZWFsIG51bWJlcixcbiAgICAgKiAtIGEgc3RyaW5nIHJlcHJlc2VudGluZyBhIHJlYWwgbnVtYmVyLCBvclxuICAgICAqIC0gYSBzdHJpbmcgcmVwcmVzZW50aW5nIGEgbG9jYWxpemVkIG51bWJlciAod2l0aCBzcGVjaWZpYyBncm91cCBzZXBhcmF0b3JzIGFuZCBkZWNpbWFsIGNoYXJhY3RlciksXG4gICAgICogLi4udG8gYSBzdHJpbmcgcmVwcmVzZW50aW5nIGEgcmVhbCAnamF2YXNjcmlwdCcgbnVtYmVyIChpZS4gJzEyMzQnIG9yICcxMjM0LjU2NycpLlxuICAgICAqXG4gICAgICogVGhpcyBmdW5jdGlvbiByZXR1cm5zIGBOYU5gIGlmIHN1Y2ggY29udmVyc2lvbiBmYWlscy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7aW50fGZsb2F0fHN0cmluZ30gdmFsdWVcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gc2V0dGluZ3NcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfE5hTn1cbiAgICAgKi9cbiAgICBzdGF0aWMgX3RvTnVtZXJpY1ZhbHVlKHZhbHVlLCBzZXR0aW5ncykge1xuICAgICAgICAvL1hYWCBOb3RlOyB0aGlzIGZ1bmN0aW9uIGlzIHN0YXRpYyBzaW5jZSB3ZSBuZWVkIHRvIHBhc3MgYSBgc2V0dGluZ3NgIG9iamVjdCB3aGVuIGNhbGxpbmcgdGhlIHN0YXRpYyBgQXV0b051bWVyaWMuZm9ybWF0KClgIG1ldGhvZFxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOdW1iZXIoTnVtYmVyKHZhbHVlKSkpIHtcbiAgICAgICAgICAgIC8vIFRoZSB2YWx1ZSBoYXMgZWl0aGVyIGFscmVhZHkgYmVlbiBzdHJpcHBlZCwgb3IgYSAncmVhbCcgamF2YXNjcmlwdCBudW1iZXIgaXMgcGFzc2VkIGFzIGEgcGFyYW1ldGVyXG4gICAgICAgICAgICByZXN1bHQgPSB2YWx1ZTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIC8vIEVsc2UgaWYgaXQncyBhIHN0cmluZyB0aGF0IGBOdW1iZXIoKWAgY2Fubm90IHR5cGVjYXN0LCB0aGVuIHdlIHRyeSB0byBjb252ZXJ0IHRoZSBsb2NhbGl6ZWQgbnVtZXJpYyBzdHJpbmcgdG8gYSBudW1lcmljIG9uZVxuICAgICAgICAgICAgLy8gQ29udmVydCB0aGUgdmFsdWUgdG8gYSBudW1lcmljIHN0cmluZywgc3RyaXBwaW5nIHVubmVjZXNzYXJ5IGNoYXJhY3RlcnMgaW4gdGhlIHByb2Nlc3NcbiAgICAgICAgICAgIHJlc3VsdCA9IHRoaXMuX2NvbnZlcnRUb051bWVyaWNTdHJpbmcodmFsdWUudG9TdHJpbmcoKSwgc2V0dGluZ3MpO1xuXG4gICAgICAgICAgICAvLyBJZiB0aGUgcmVzdWx0IGlzIHN0aWxsIG5vdCBhIG51bWVyaWMgc3RyaW5nLCB0aGVuIHdlIHRocm93IGEgd2FybmluZ1xuICAgICAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcihOdW1iZXIocmVzdWx0KSkpIHtcbiAgICAgICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci53YXJuaW5nKGBUaGUgdmFsdWUgXCIke3ZhbHVlfVwiIGJlaW5nICdzZXQnIGlzIG5vdCBudW1lcmljIGFuZCB0aGVyZWZvcmUgY2Fubm90IGJlIHVzZWQgYXBwcm9wcmlhdGVseS5gLCBzZXR0aW5ncy5zaG93V2FybmluZ3MpO1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IE5hTjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBwYXN0ZWQgdGV4dCB0aGF0IHdpbGwgYmUgdXNlZC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0XG4gICAgICogQHJldHVybnMge3N0cmluZ3x2b2lkfFhNTHwqfVxuICAgICAqL1xuICAgIF9wcmVwYXJlUGFzdGVkVGV4dCh0ZXh0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNvbnN0cnVjdG9yLl9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnModGV4dCwgdGhpcy5zZXR0aW5ncywgdHJ1ZSwgdGhpcy5pc0ZvY3VzZWQpLnJlcGxhY2UodGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyLCAnLicpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBUUlVFIGlmIHRoZSBnaXZlbiB2YWx1ZSAoYSBudW1iZXIgYXMgYSBzdHJpbmcpIGlzIHdpdGhpbiB0aGUgcmFuZ2Ugc2V0IGluIHRoZSBzZXR0aW5ncyBgbWluaW11bVZhbHVlYCBhbmQgYG1heGltdW1WYWx1ZWAsIEZBTFNFIG90aGVyd2lzZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBwYXJzZWRNaW5WYWx1ZSBQYXJzZWQgdmlhIHRoZSBgcGFyc2VTdHIoKWAgZnVuY3Rpb25cbiAgICAgKiBAcGFyYW0ge29iamVjdH0gcGFyc2VkTWF4VmFsdWUgUGFyc2VkIHZpYSB0aGUgYHBhcnNlU3RyKClgIGZ1bmN0aW9uXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIF9jaGVja0lmSW5SYW5nZSh2YWx1ZSwgcGFyc2VkTWluVmFsdWUsIHBhcnNlZE1heFZhbHVlKSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIucGFyc2VTdHIodmFsdWUpO1xuICAgICAgICByZXR1cm4gQXV0b051bWVyaWNIZWxwZXIudGVzdE1pbk1heChwYXJzZWRNaW5WYWx1ZSwgcGFyc2VkVmFsdWUpID4gLTEgJiYgQXV0b051bWVyaWNIZWxwZXIudGVzdE1pbk1heChwYXJzZWRNYXhWYWx1ZSwgcGFyc2VkVmFsdWUpIDwgMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIHNlbGVjdGlvbiB2YWx1ZXMgYXMgd2VsbCBhcyByZXNldHMgdGhlIGludGVybmFsIHN0YXRlIG9mIHRoZSBjdXJyZW50IEF1dG9OdW1lcmljIG9iamVjdC5cbiAgICAgKiBUaGlzIGtlZXBzIHRyYWNrcyBvZiB0aGUgY3VycmVudCBzZWxlY3Rpb24gYW5kIHJlc2V0cyB0aGUgJ3Byb2Nlc3NlZCcgYW5kICdmb3JtYXR0ZWQnIHN0YXRlLlxuICAgICAqXG4gICAgICogTm90ZSA6IFRob3NlIHR3byBjYW4gY2hhbmdlIGJldHdlZW4gdGhlIGtleWRvd24sIGtleXByZXNzIGFuZCBrZXl1cCBldmVudHMsIHRoYXQncyB3aHlcbiAgICAgKiAgICAgICAgdGhpcyBmdW5jdGlvbiBpcyBjYWxsZWQgb24gZWFjaCBldmVudCBoYW5kbGVyLlxuICAgICAqXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfdXBkYXRlSW50ZXJuYWxQcm9wZXJ0aWVzKCkge1xuICAgICAgICB0aGlzLnNlbGVjdGlvbiA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRTZWxlY3Rpb24odGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgdGhpcy5wcm9jZXNzZWQgPSBmYWxzZTtcbiAgICAgICAgdGhpcy5mb3JtYXR0ZWQgPSBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVcGRhdGUgdGhlIGBldmVudC5rZXlgIGF0dHJpYnV0ZSB0aGF0IHRyaWdnZXJlZCB0aGUgZ2l2ZW4gZXZlbnQuXG4gICAgICpcbiAgICAgKiBgZXZlbnQua2V5YCBkZXNjcmliZXM6XG4gICAgICogLSB0aGUga2V5IG5hbWUgKGlmIGEgbm9uLXByaW50YWJsZSBjaGFyYWN0ZXIpLFxuICAgICAqIC0gb3IgZGlyZWN0bHkgdGhlIGNoYXJhY3RlciB0aGF0IHJlc3VsdCBmcm9tIHRoZSBrZXkgcHJlc3MgdXNlZCB0byB0cmlnZ2VyIHRoZSBldmVudC5cbiAgICAgKlxuICAgICAqIEBsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9LZXlib2FyZEV2ZW50L2tleVxuICAgICAqIFRoZSBrZXkgbGlzdCBpcyBkZXNjcmliZWQgaGVyZTpcbiAgICAgKiBAbGluayBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvS2V5Ym9hcmRFdmVudC9rZXkvS2V5X1ZhbHVlc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtFdmVudHxLZXlib2FyZEV2ZW50fSBlXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfdXBkYXRlRXZlbnRLZXlJbmZvKGUpIHtcbiAgICAgICAgdGhpcy5ldmVudEtleSA9IEF1dG9OdW1lcmljSGVscGVyLmNoYXJhY3RlcihlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTYXZlIHRoZSB1bmZvcm1hdHRlZCBlbGVtZW50IHZhbHVlLlxuICAgICAqIFRoaXMgaXMgdXNlZCBpbiB0aGUgJ2NhbmNlbGxhYmxlJyBmZWF0dXJlIHdoZXJlIHRoZSBlbGVtZW50IHZhbHVlIGlzIHNhdmVkIG9uIGZvY3VzIGFuZCBpbnB1dCB2YWxpZGF0aW9uLCB0byBiZSB1c2VkIGlmIHRoZSB1c2VyIHdhbnRzIHRvIGNhbmNlbCBoaXMgbW9kaWZpY2F0aW9ucyBieSBoaXR0aW5nIHRoZSAnRXNjYXBlJyBrZXkuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zYXZlQ2FuY2VsbGFibGVWYWx1ZSgpIHtcbiAgICAgICAgdGhpcy5zYXZlZENhbmNlbGxhYmxlVmFsdWUgPSB0aGlzLnJhd1ZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgdGV4dCBzZWxlY3Rpb24gaW5zaWRlIHRoZSBpbnB1dCB3aXRoIHRoZSBnaXZlbiBzdGFydCBhbmQgZW5kIHBvc2l0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtpbnR9IHN0YXJ0XG4gICAgICogQHBhcmFtIHtpbnR9IGVuZFxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX3NldFNlbGVjdGlvbihzdGFydCwgZW5kKSB7XG4gICAgICAgIC8vVE9ETyB1c2UgdGhpcyBmdW5jdGlvbiB0byByZXBsYWNlIHRoZSBkaXJlY3QgY2FsbHMgdG8gYHNldEVsZW1lbnRTZWxlY3Rpb24oKWAsIHdoZXJldmVyIHBvc3NpYmxlXG4gICAgICAgIHN0YXJ0ID0gTWF0aC5tYXgoc3RhcnQsIDApO1xuICAgICAgICBlbmQgPSBNYXRoLm1pbihlbmQsIEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpLmxlbmd0aCk7XG4gICAgICAgIHRoaXMuc2VsZWN0aW9uID0ge1xuICAgICAgICAgICAgc3RhcnQsXG4gICAgICAgICAgICBlbmQsXG4gICAgICAgICAgICBsZW5ndGg6IGVuZCAtIHN0YXJ0LFxuICAgICAgICB9O1xuXG4gICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRTZWxlY3Rpb24odGhpcy5kb21FbGVtZW50LCBzdGFydCwgZW5kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGNhcmV0IHBvc2l0aW9uIGluc2lkZSB0aGUgaW5wdXQgYXQgdGhlIGdpdmVuIHBvc2l0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtpbnR9IHBvc2l0aW9uXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfc2V0Q2FyZXRQb3NpdGlvbihwb3NpdGlvbikge1xuICAgICAgICB0aGlzLl9zZXRTZWxlY3Rpb24ocG9zaXRpb24sIHBvc2l0aW9uKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYW4gYXJyYXkgY29udGFpbmluZyB0aGUgc3RyaW5nIHBhcnRzIGxvY2F0ZWQgb24gdGhlIGxlZnQgYW5kIHJpZ2h0IHNpZGUgb2YgdGhlIGNhcmV0IG9yIHNlbGVjdGlvbi5cbiAgICAgKiBUaG9zZSBwYXJ0cyBhcmUgbGVmdCAndW50b3VjaGVkJywgaWUuIGZvcm1hdHRlZCBieSBhdXRvTnVtZXJpYy5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIHtbc3RyaW5nLCBzdHJpbmddfSBUaGUgcGFydHMgb24gdGhlIGxlZnQgYW5kIHJpZ2h0IG9mIHRoZSBjYXJldCBvciBzZWxlY3Rpb25cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9nZXRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKCkge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICBjb25zdCBsZWZ0ID0gdmFsdWUuc3Vic3RyaW5nKDAsIHRoaXMuc2VsZWN0aW9uLnN0YXJ0KTtcbiAgICAgICAgY29uc3QgcmlnaHQgPSB2YWx1ZS5zdWJzdHJpbmcodGhpcy5zZWxlY3Rpb24uZW5kLCB2YWx1ZS5sZW5ndGgpO1xuXG4gICAgICAgIHJldHVybiBbbGVmdCwgcmlnaHRdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhbiBhcnJheSBjb250YWluaW5nIHRoZSBzdHJpbmcgcGFydHMgbG9jYXRlZCBvbiB0aGUgbGVmdCBhbmQgcmlnaHQgc2lkZSBvZiB0aGUgY2FyZXQgb3Igc2VsZWN0aW9uLlxuICAgICAqIFRob3NlIHBhcnRzIGFyZSB1bmZvcm1hdHRlZCAoc3RyaXBwZWQpIG9mIGFueSBub24tbnVtYmVycyBjaGFyYWN0ZXJzLlxuICAgICAqXG4gICAgICogQHJldHVybnMge1tzdHJpbmcsIHN0cmluZ119IFRoZSBwYXJ0cyBvbiB0aGUgbGVmdCBhbmQgcmlnaHQgb2YgdGhlIGNhcmV0IG9yIHNlbGVjdGlvbiwgdW5mb3JtYXR0ZWQuXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZ2V0VW5mb3JtYXR0ZWRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKCkge1xuICAgICAgICBsZXQgW2xlZnQsIHJpZ2h0XSA9IHRoaXMuX2dldExlZnRBbmRSaWdodFBhcnRBcm91bmRUaGVTZWxlY3Rpb24oKTtcbiAgICAgICAgaWYgKGxlZnQgPT09ICcnICYmIHJpZ2h0ID09PSAnJykge1xuICAgICAgICAgICAgcmV0dXJuIFsnJywgJyddO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgY2hhbmdpbmcgdGhlIHNpZ24gYW5kIGBsZWZ0YCBpcyBlcXVhbCB0byB0aGUgbnVtYmVyIHplcm8sIHByZXZlbnQgc3RyaXBwaW5nIHRoZSBsZWFkaW5nIHplcm8ocylcbiAgICAgICAgbGV0IHN0cmlwWmVyb3MgPSB0cnVlO1xuICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuSHlwaGVuICYmIE51bWJlcihsZWZ0KSA9PT0gMCkge1xuICAgICAgICAgICAgc3RyaXBaZXJvcyA9IGZhbHNlO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuaXNUcmFpbGluZ05lZ2F0aXZlICYmXG4gICAgICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKHJpZ2h0KSAmJlxuICAgICAgICAgICAgIUF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmUobGVmdCkpIHtcbiAgICAgICAgICAgIC8vIE9ubHkgc2V0IHRoZSBuZWdhdGl2ZSBzaWduIGlmIHRoZSB2YWx1ZSBpcyBuZWdhdGl2ZVxuICAgICAgICAgICAgbGVmdCA9ICctJyArIGxlZnQ7XG4gICAgICAgICAgICByaWdodCA9IHJpZ2h0LnJlcGxhY2UodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIsICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxlZnQgPSBBdXRvTnVtZXJpYy5fc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzKGxlZnQsIHRoaXMuc2V0dGluZ3MsIHN0cmlwWmVyb3MsIHRoaXMuaXNGb2N1c2VkKTtcbiAgICAgICAgcmlnaHQgPSBBdXRvTnVtZXJpYy5fc3RyaXBBbGxOb25OdW1iZXJDaGFyYWN0ZXJzKHJpZ2h0LCB0aGlzLnNldHRpbmdzLCBmYWxzZSwgdGhpcy5pc0ZvY3VzZWQpO1xuXG4gICAgICAgIHJldHVybiBbbGVmdCwgcmlnaHRdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN0cmlwIHBhcnRzIGZyb20gZXhjZXNzIGNoYXJhY3RlcnMgYW5kIGxlYWRpbmcgemVyb3MuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbGVmdFxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSByaWdodFxuICAgICAqIEByZXR1cm5zIHtbKiwqLCpdfVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX25vcm1hbGl6ZVBhcnRzKGxlZnQsIHJpZ2h0KSB7XG4gICAgICAgIC8vVE9ETyBSZWZhY3RvciB3aXRoIGBfZ2V0VW5mb3JtYXR0ZWRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uYCB3aGljaCBzaGFyZSBhIGxvdCBvZiBzaW1pbGFyIGNvZGVcbiAgICAgICAgLy8gSWYgY2hhbmdpbmcgdGhlIHNpZ24gYW5kIGxlZnQgaXMgZXF1YWwgdG8gdGhlIG51bWJlciB6ZXJvIC0gcHJldmVudHMgc3RyaXBwaW5nIHRoZSBsZWFkaW5nIHplcm9zXG4gICAgICAgIGxldCBzdHJpcFplcm9zID0gdHJ1ZTtcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkh5cGhlbiAmJiBOdW1iZXIobGVmdCkgPT09IDApIHtcbiAgICAgICAgICAgIHN0cmlwWmVyb3MgPSBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLmlzVHJhaWxpbmdOZWdhdGl2ZSAmJlxuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZShyaWdodCkgJiZcbiAgICAgICAgICAgICFBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKGxlZnQpKSB7XG4gICAgICAgICAgICAvLyBPbmx5IHNldCB0aGUgbmVnYXRpdmUgc2lnbiBpZiB0aGUgdmFsdWUgaXMgbmVnYXRpdmVcbiAgICAgICAgICAgIGxlZnQgPSAnLScgKyBsZWZ0O1xuICAgICAgICAgICAgcmlnaHQgPSByaWdodC5yZXBsYWNlKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICBsZWZ0ID0gQXV0b051bWVyaWMuX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVycyhsZWZ0LCB0aGlzLnNldHRpbmdzLCBzdHJpcFplcm9zLCB0aGlzLmlzRm9jdXNlZCk7XG4gICAgICAgIHJpZ2h0ID0gQXV0b051bWVyaWMuX3N0cmlwQWxsTm9uTnVtYmVyQ2hhcmFjdGVycyhyaWdodCwgdGhpcy5zZXR0aW5ncywgZmFsc2UsIHRoaXMuaXNGb2N1c2VkKTtcblxuICAgICAgICAvLyBQcmV2ZW50cyBtdWx0aXBsZSBsZWFkaW5nIHplcm9zIGZyb20gYmVpbmcgZW50ZXJlZFxuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5sZWFkaW5nWmVybyA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5sZWFkaW5nWmVyby5kZW55ICYmXG4gICAgICAgICAgICAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUubnVtMCB8fCB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5udW1wYWQwKSAmJlxuICAgICAgICAgICAgTnVtYmVyKGxlZnQpID09PSAwICYmXG4gICAgICAgICAgICAvLyBJZiBgcmlnaHRgIGlzIG5vdCBlbXB0eSBhbmQgdGhlIGZpcnN0IGNoYXJhY3RlciBpcyBub3QgYGRlY2ltYWxDaGFyYWN0ZXJgXG4gICAgICAgICAgICAhQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMobGVmdCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSAmJiByaWdodCAhPT0gJycpIHtcbiAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygwLCBsZWZ0Lmxlbmd0aCAtIDEpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSW5zZXJ0IHplcm8gdGhlcmUgaXMgYSBsZWFkaW5nIGRvdFxuICAgICAgICBsZXQgbmV3VmFsdWUgPSBsZWZ0ICsgcmlnaHQ7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IG0gPSBuZXdWYWx1ZS5tYXRjaChuZXcgUmVnRXhwKGBeJHt0aGlzLnJlZ2V4LmFOZWdSZWdBdXRvU3RyaXB9XFxcXCR7dGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyfWApKTtcbiAgICAgICAgICAgIGlmIChtKSB7XG4gICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQucmVwbGFjZShtWzFdLCBtWzFdICsgJzAnKTtcbiAgICAgICAgICAgICAgICBuZXdWYWx1ZSA9IGxlZnQgKyByaWdodDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBbbGVmdCwgcmlnaHQsIG5ld1ZhbHVlXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXQgdGhlIGZvcm1hdHRlZCBlbGVtZW50IHZhbHVlIGFzIHdlbGwgYXMgdGhlIGByYXdWYWx1ZWAuXG4gICAgICogVGhpcyByZXR1cm5zIGB0cnVlYCBpZiB0aGUgZWxlbWVudCBhbmQgcmF3IHZhbHVlIGhhdmUgYmVlbiBtb2RpZmllZCwgYGZhbHNlYCBvdGhlcndpc2UuXG4gICAgICogVGhpcyBtZXRob2QgYWxzbyBhZGp1c3QgdGhlIGNhcmV0IHBvc2l0aW9uIGFjY29yZGluZyB0byB0aGUgYGxlYWRpbmdaZXJvYCBvcHRpb24gYW5kIHRoZSBub3JtYWxpemVkIHZhbHVlLiAvL1RPRE8gV2hhdCBhYm91dCB0aGUgY3Vyc29yICpzZWxlY3Rpb24qP1xuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGxlZnRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcmlnaHRcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGlzUGFzdGVcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9zZXRWYWx1ZVBhcnRzKGxlZnQsIHJpZ2h0LCBpc1Bhc3RlID0gZmFsc2UpIHtcbiAgICAgICAgY29uc3QgW25vcm1hbGl6ZWRMZWZ0LCBub3JtYWxpemVkUmlnaHQsIG5vcm1hbGl6ZWROZXdWYWx1ZV0gPSB0aGlzLl9ub3JtYWxpemVQYXJ0cyhsZWZ0LCByaWdodCk7XG4gICAgICAgIGNvbnN0IFttaW5UZXN0LCBtYXhUZXN0XSA9IEF1dG9OdW1lcmljLl9jaGVja0lmSW5SYW5nZVdpdGhPdmVycmlkZU9wdGlvbihub3JtYWxpemVkTmV3VmFsdWUsIHRoaXMuc2V0dGluZ3MpO1xuXG4gICAgICAgIGlmIChtaW5UZXN0ICYmIG1heFRlc3QpIHtcbiAgICAgICAgICAgIC8vIEZpcnN0LCBzZXQgdGhlIHJhdyB2YWx1ZVxuICAgICAgICAgICAgY29uc3Qgcm91bmRlZFJhd1ZhbHVlID0gQXV0b051bWVyaWMuX3RydW5jYXRlRGVjaW1hbFBsYWNlcyhub3JtYWxpemVkTmV3VmFsdWUsIHRoaXMuc2V0dGluZ3MsIGlzUGFzdGUsIHRoaXMuc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKTtcbiAgICAgICAgICAgIGNvbnN0IHRlc3RWYWx1ZSA9IHJvdW5kZWRSYXdWYWx1ZS5yZXBsYWNlKHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciwgJy4nKTtcblxuICAgICAgICAgICAgaWYgKHRlc3RWYWx1ZSA9PT0gJycgfHwgdGVzdFZhbHVlID09PSB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlcikge1xuICAgICAgICAgICAgICAgIGxldCB2YWx1ZVRvU2V0T25FbXB0eTtcbiAgICAgICAgICAgICAgICBzd2l0Y2ggKHRoaXMuc2V0dGluZ3MuZW1wdHlJbnB1dEJlaGF2aW9yKSB7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IuemVybzpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlVG9TZXRPbkVtcHR5ID0gJzAnO1xuICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5lbXB0eUlucHV0QmVoYXZpb3IubnVsbDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlVG9TZXRPbkVtcHR5ID0gbnVsbDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICBkZWZhdWx0IDpcbiAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlVG9TZXRPbkVtcHR5ID0gJyc7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0UmF3VmFsdWUodmFsdWVUb1NldE9uRW1wdHkpO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRSYXdWYWx1ZSh0aGlzLl90cmltTGVhZGluZ0FuZFRyYWlsaW5nWmVyb3ModGVzdFZhbHVlKSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFRoZW4gc2V0IHRoZSBmb3JtYXR0ZWQgdmFsdWVcbiAgICAgICAgICAgIGNvbnN0IHJvdW5kZWRWYWx1ZVRvU2hvdyA9IEF1dG9OdW1lcmljLl90cnVuY2F0ZURlY2ltYWxQbGFjZXMobm9ybWFsaXplZE5ld1ZhbHVlLCB0aGlzLnNldHRpbmdzLCBpc1Bhc3RlLCB0aGlzLnNldHRpbmdzLmRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXMpO1xuICAgICAgICAgICAgbGV0IHBvc2l0aW9uID0gbm9ybWFsaXplZExlZnQubGVuZ3RoO1xuICAgICAgICAgICAgaWYgKHBvc2l0aW9uID4gcm91bmRlZFZhbHVlVG9TaG93Lmxlbmd0aCkge1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gcm91bmRlZFZhbHVlVG9TaG93Lmxlbmd0aDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gTWFrZSBzdXJlIHdoZW4gdGhlIHVzZXIgZW50ZXIgYSAnMCcgb24gdGhlIGZhciBsZWZ0IHdpdGggYSBsZWFkaW5nIHplcm8gb3B0aW9uIHNldCB0byAnZGVueScsIHRoYXQgdGhlIGNhcmV0IGRvZXMgbm90IG1vdmVzIHNpbmNlIHRoZSBpbnB1dCBpcyBkcm9wcGVkIChmaXggaXNzdWUgIzI4MylcbiAgICAgICAgICAgIGlmIChwb3NpdGlvbiA9PT0gMSAmJiBub3JtYWxpemVkTGVmdCA9PT0gJzAnICYmIHRoaXMuc2V0dGluZ3MubGVhZGluZ1plcm8gPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8uZGVueSkge1xuICAgICAgICAgICAgICAgIC8vIElmIHRoZSB1c2VyIGVudGVyIGAwYCwgdGhlbiB0aGUgY2FyZXQgaXMgcHV0IG9uIHRoZSByaWdodCBzaWRlIG9mIGl0IChGaXggaXNzdWUgIzI5OSlcbiAgICAgICAgICAgICAgICBpZiAobm9ybWFsaXplZFJpZ2h0ID09PSAnJyB8fCBub3JtYWxpemVkTGVmdCA9PT0gJzAnICYmIG5vcm1hbGl6ZWRSaWdodCAhPT0gJycpIHtcbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gPSAxO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHBvc2l0aW9uID0gMDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQsIHJvdW5kZWRWYWx1ZVRvU2hvdyk7XG4gICAgICAgICAgICB0aGlzLl9zZXRDYXJldFBvc2l0aW9uKHBvc2l0aW9uKTtcblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoIW1pblRlc3QpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRyaWdnZXJFdmVudChBdXRvTnVtZXJpYy5ldmVudHMubWluUmFuZ2VFeGNlZWRlZCwgdGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgfSBlbHNlIGlmICghbWF4VGVzdCkge1xuICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIudHJpZ2dlckV2ZW50KEF1dG9OdW1lcmljLmV2ZW50cy5tYXhSYW5nZUV4Y2VlZGVkLCB0aGlzLmRvbUVsZW1lbnQpO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEhlbHBlciBmdW5jdGlvbiBmb3IgYF9leHBhbmRTZWxlY3Rpb25PblNpZ24oKWAuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7QXJyYXl9IEFycmF5IGNvbnRhaW5pbmcgW3NpZ25Qb3NpdGlvbiwgY3VycmVuY3lTeW1ib2xQb3NpdGlvbl0gb2YgYSBmb3JtYXR0ZWQgdmFsdWVcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9nZXRTaWduUG9zaXRpb24oKSB7XG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sKSB7XG4gICAgICAgICAgICBjb25zdCBjdXJyZW5jeVN5bWJvbExlbiA9IHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoO1xuICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGhhc05lZyA9IHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyICYmIHZhbHVlICYmIHZhbHVlLmNoYXJBdCgwKSA9PT0gdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXI7XG4gICAgICAgICAgICAgICAgaWYgKGhhc05lZykge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBbMSwgY3VycmVuY3lTeW1ib2xMZW4gKyAxXTtcbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBbMCwgY3VycmVuY3lTeW1ib2xMZW5dO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWVMZW4gPSB2YWx1ZS5sZW5ndGg7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gW3ZhbHVlTGVuIC0gY3VycmVuY3lTeW1ib2xMZW4sIHZhbHVlTGVuXTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IFsxMDAwLCAtMV07XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEV4cGFuZHMgc2VsZWN0aW9uIHRvIGNvdmVyIHdob2xlIHNpZ25cbiAgICAgKiBQcmV2ZW50cyBwYXJ0aWFsIGRlbGV0aW9uL2NvcHlpbmcvb3ZlcndyaXRpbmcgb2YgYSBzaWduXG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfZXhwYW5kU2VsZWN0aW9uT25TaWduKCkge1xuICAgICAgICBjb25zdCBbc2lnblBvc2l0aW9uLCBjdXJyZW5jeVN5bWJvbFBvc2l0aW9uXSA9IHRoaXMuX2dldFNpZ25Qb3NpdGlvbigpO1xuICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSB0aGlzLnNlbGVjdGlvbjtcblxuICAgICAgICAvLyBJZiBzZWxlY3Rpb24gY2F0Y2hlcyBzb21ldGhpbmcgZXhjZXB0IHNpZ24gYW5kIGNhdGNoZXMgb25seSBzcGFjZSBmcm9tIHNpZ25cbiAgICAgICAgaWYgKHNlbGVjdGlvbi5zdGFydCA8IGN1cnJlbmN5U3ltYm9sUG9zaXRpb24gJiYgc2VsZWN0aW9uLmVuZCA+IHNpZ25Qb3NpdGlvbikge1xuICAgICAgICAgICAgLy8gVGhlbiBzZWxlY3Qgd2l0aG91dCBlbXB0eSBzcGFjZVxuICAgICAgICAgICAgaWYgKChzZWxlY3Rpb24uc3RhcnQgPCBzaWduUG9zaXRpb24gfHwgc2VsZWN0aW9uLmVuZCA+IGN1cnJlbmN5U3ltYm9sUG9zaXRpb24pICYmXG4gICAgICAgICAgICAgICAgQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCkuc3Vic3RyaW5nKE1hdGgubWF4KHNlbGVjdGlvbi5zdGFydCwgc2lnblBvc2l0aW9uKSwgTWF0aC5taW4oc2VsZWN0aW9uLmVuZCwgY3VycmVuY3lTeW1ib2xQb3NpdGlvbikpXG4gICAgICAgICAgICAgICAgICAgIC5tYXRjaCgvXlxccyokLykpIHtcbiAgICAgICAgICAgICAgICBpZiAoc2VsZWN0aW9uLnN0YXJ0IDwgc2lnblBvc2l0aW9uKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldFNlbGVjdGlvbihzZWxlY3Rpb24uc3RhcnQsIHNpZ25Qb3NpdGlvbik7XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0U2VsZWN0aW9uKGN1cnJlbmN5U3ltYm9sUG9zaXRpb24sIHNlbGVjdGlvbi5lbmQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgLy8gRWxzZSBzZWxlY3Qgd2l0aCB3aG9sZSBzaWduXG4gICAgICAgICAgICAgICAgdGhpcy5fc2V0U2VsZWN0aW9uKE1hdGgubWluKHNlbGVjdGlvbi5zdGFydCwgc2lnblBvc2l0aW9uKSwgTWF0aC5tYXgoc2VsZWN0aW9uLmVuZCwgY3VycmVuY3lTeW1ib2xQb3NpdGlvbikpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVHJ5IHRvIHN0cmlwIHBhc3RlZCB2YWx1ZSB0byBkaWdpdHNcbiAgICAgKi9cbiAgICBfY2hlY2tQYXN0ZSgpIHtcbiAgICAgICAgaWYgKCFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZCh0aGlzLnZhbHVlUGFydHNCZWZvcmVQYXN0ZSkpIHtcbiAgICAgICAgICAgIGNvbnN0IG9sZFBhcnRzID0gdGhpcy52YWx1ZVBhcnRzQmVmb3JlUGFzdGU7XG4gICAgICAgICAgICBjb25zdCBbbGVmdCwgcmlnaHRdID0gdGhpcy5fZ2V0TGVmdEFuZFJpZ2h0UGFydEFyb3VuZFRoZVNlbGVjdGlvbigpO1xuXG4gICAgICAgICAgICAvLyBUcnkgdG8gc3RyaXAgdGhlIHBhc3RlZCB2YWx1ZSBmaXJzdFxuICAgICAgICAgICAgZGVsZXRlIHRoaXMudmFsdWVQYXJ0c0JlZm9yZVBhc3RlO1xuXG4gICAgICAgICAgICBjb25zdCBtb2RpZmllZExlZnRQYXJ0ID0gbGVmdC5zdWJzdHIoMCwgb2xkUGFydHNbMF0ubGVuZ3RoKSArIEF1dG9OdW1lcmljLl9zdHJpcEFsbE5vbk51bWJlckNoYXJhY3RlcnMobGVmdC5zdWJzdHIob2xkUGFydHNbMF0ubGVuZ3RoKSwgdGhpcy5zZXR0aW5ncywgdHJ1ZSwgdGhpcy5pc0ZvY3VzZWQpO1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9zZXRWYWx1ZVBhcnRzKG1vZGlmaWVkTGVmdFBhcnQsIHJpZ2h0LCB0cnVlKSkge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnNldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQsIG9sZFBhcnRzLmpvaW4oJycpKTtcbiAgICAgICAgICAgICAgICB0aGlzLl9zZXRDYXJldFBvc2l0aW9uKG9sZFBhcnRzWzBdLmxlbmd0aCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBnaXZlbiBrZXkgc2hvdWxkIGJlIGlnbm9yZWQgb3Igbm90LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50S2V5TmFtZVxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIF9zaG91bGRTa2lwRXZlbnRLZXkoZXZlbnRLZXlOYW1lKSB7XG4gICAgICAgIGNvbnN0IGlzRm5LZXlzID0gQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KGV2ZW50S2V5TmFtZSwgQXV0b051bWVyaWNFbnVtLmtleU5hbWUuX2FsbEZuS2V5cyk7XG4gICAgICAgIGNvbnN0IGlzT1NLZXlzID0gZXZlbnRLZXlOYW1lID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5PU0xlZnQgfHwgZXZlbnRLZXlOYW1lID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5PU1JpZ2h0O1xuICAgICAgICBjb25zdCBpc0NvbnRleHRNZW51ID0gZXZlbnRLZXlOYW1lID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5Db250ZXh0TWVudTtcbiAgICAgICAgY29uc3QgaXNTb21lTm9uUHJpbnRhYmxlS2V5cyA9IEF1dG9OdW1lcmljSGVscGVyLmlzSW5BcnJheShldmVudEtleU5hbWUsIEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLl9zb21lTm9uUHJpbnRhYmxlS2V5cyk7XG4gICAgICAgIGNvbnN0IGlzT3RoZXJOb25QcmludGFibGVLZXlzID0gZXZlbnRLZXlOYW1lID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5OdW1Mb2NrIHx8XG4gICAgICAgICAgICBldmVudEtleU5hbWUgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLlNjcm9sbExvY2sgfHxcbiAgICAgICAgICAgIGV2ZW50S2V5TmFtZSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuSW5zZXJ0IHx8XG4gICAgICAgICAgICBldmVudEtleU5hbWUgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkNvbW1hbmQ7XG4gICAgICAgIGNvbnN0IGlzVW5yZWNvZ25pemFibGVLZXlzID0gZXZlbnRLZXlOYW1lID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5VbmlkZW50aWZpZWQ7XG5cbiAgICAgICAgcmV0dXJuIGlzRm5LZXlzIHx8IGlzT1NLZXlzIHx8IGlzQ29udGV4dE1lbnUgfHwgaXNTb21lTm9uUHJpbnRhYmxlS2V5cyB8fCBpc1VucmVjb2duaXphYmxlS2V5cyB8fCBpc090aGVyTm9uUHJpbnRhYmxlS2V5cztcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9jZXNzIGNvcHlpbmcsIGN1dHRpbmcgYW5kIHBhc3RpbmcsIGFzIHdlbGwgYXMgdW5kby9yZWRvaW5nIGFuZCBjdXJzb3IgbW92aW5nLlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgZnVydGhlciBwcm9jZXNzaW5nIHNob3VsZCBub3QgYmUgcGVyZm9ybWVkLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtLZXlib2FyZEV2ZW50fSBlXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfcHJvY2Vzc05vblByaW50YWJsZUtleXNBbmRTaG9ydGN1dHMoZSkge1xuICAgICAgICAvLyBDYXRjaCB0aGUgY3RybCB1cCBvbiBjdHJsLXZcbiAgICAgICAgaWYgKCgoZS5jdHJsS2V5IHx8IGUubWV0YUtleSkgJiYgZS50eXBlID09PSAna2V5dXAnICYmICFBdXRvTnVtZXJpY0hlbHBlci5pc1VuZGVmaW5lZCh0aGlzLnZhbHVlUGFydHNCZWZvcmVQYXN0ZSkpIHx8IChlLnNoaWZ0S2V5ICYmIHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkluc2VydCkpIHtcbiAgICAgICAgICAgIC8vVE9ETyBNb3ZlIHRoaXMgdGVzdCBpbnNpZGUgdGhlIGBvbktleXVwYCBoYW5kbGVyXG4gICAgICAgICAgICB0aGlzLl9jaGVja1Bhc3RlKCk7XG5cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNraXAgYWxsIGZ1bmN0aW9uIGtleXMgKEYxLUYxMiksIFdpbmRvd3Mga2V5cywgdGFiIGFuZCBvdGhlciBzcGVjaWFsIGtleXNcbiAgICAgICAgaWYgKHRoaXMuY29uc3RydWN0b3IuX3Nob3VsZFNraXBFdmVudEtleSh0aGlzLmV2ZW50S2V5KSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiBhIFwiU2VsZWN0IGFsbFwiIGtleWJvYXJkIHNob3J0Y3V0IGlzIGRldGVjdGVkIChjdHJsICsgYSlcbiAgICAgICAgaWYgKChlLmN0cmxLZXkgfHwgZS5tZXRhS2V5KSAmJiB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5hKSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5zZWxlY3ROdW1iZXJPbmx5KSB7XG4gICAgICAgICAgICAgICAgLy8gYHByZXZlbnREZWZhdWx0KClgIGlzIHVzZWQgaGVyZSB0byBwcmV2ZW50IHRoZSBicm93c2VyIHRvIGZpcnN0IHNlbGVjdCBhbGwgdGhlIGlucHV0IHRleHQgKGluY2x1ZGluZyB0aGUgY3VycmVuY3kgc2lnbiksIG90aGVyd2lzZSB3ZSB3b3VsZCBzZWUgdGhhdCB3aG9sZSBzZWxlY3Rpb24gZmlyc3QgaW4gYSBmbGFzaCwgdGhlbiB0aGUgc2VsZWN0aW9uIHdpdGggb25seSB0aGUgbnVtYmVyIHBhcnQgd2l0aG91dCB0aGUgY3VycmVuY3kgc2lnbi5cbiAgICAgICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgICAgICAgICAgLy9UT0RPIHJlcGxhY2UgYHNlbGVjdE51bWJlcmAgYnkgYHNlbGVjdGA/XG4gICAgICAgICAgICAgICAgdGhpcy5zZWxlY3ROdW1iZXIoKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiBhIFwiQ29weVwiLCBcIlBhc3RlXCIgb3IgXCJDdXRcIiBrZXlib2FyZCBzaG9ydGN1dCBpcyBkZXRlY3RlZCAocmVzcGVjdGl2ZWx5ICdjdHJsICsgYycsICdjdHJsICsgdicgb3IgJ2N0cmwgKyB4JylcbiAgICAgICAgaWYgKChlLmN0cmxLZXkgfHwgZS5tZXRhS2V5KSAmJiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuYyB8fCB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS52IHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLngpKSB7XG4gICAgICAgICAgICBpZiAoZS50eXBlID09PSAna2V5ZG93bicpIHtcbiAgICAgICAgICAgICAgICB0aGlzLl9leHBhbmRTZWxlY3Rpb25PblNpZ24oKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gVHJ5IHRvIHByZXZlbnQgd3JvbmcgcGFzdGVcbiAgICAgICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS52IHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkluc2VydCkge1xuICAgICAgICAgICAgICAgIGlmIChlLnR5cGUgPT09ICdrZXlkb3duJyB8fCBlLnR5cGUgPT09ICdrZXlwcmVzcycpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHRoaXMudmFsdWVQYXJ0c0JlZm9yZVBhc3RlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy52YWx1ZVBhcnRzQmVmb3JlUGFzdGUgPSB0aGlzLl9nZXRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKCk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICB0aGlzLl9jaGVja1Bhc3RlKCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gZS50eXBlID09PSAna2V5ZG93bicgfHwgZS50eXBlID09PSAna2V5cHJlc3MnIHx8IHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLmM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoZS5jdHJsS2V5IHx8IGUubWV0YUtleSkge1xuICAgICAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLlogfHwgdGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUueikge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBKdW1wIG92ZXIgdGhlIHRob3VzYW5kIHNlcGFyYXRvclxuICAgICAgICAvL1RPRE8gTW92ZSB0aGlzIHRlc3QgaW5zaWRlIHRoZSBgb25LZXlkb3duYCBoYW5kbGVyXG4gICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5MZWZ0QXJyb3cgfHwgdGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuUmlnaHRBcnJvdykge1xuICAgICAgICAgICAgaWYgKGUudHlwZSA9PT0gJ2tleWRvd24nICYmICFlLnNoaWZ0S2V5KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgdmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KTtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuTGVmdEFycm93ICYmXG4gICAgICAgICAgICAgICAgICAgICh2YWx1ZS5jaGFyQXQodGhpcy5zZWxlY3Rpb24uc3RhcnQgLSAyKSA9PT0gdGhpcy5zZXR0aW5ncy5kaWdpdEdyb3VwU2VwYXJhdG9yIHx8XG4gICAgICAgICAgICAgICAgICAgIHZhbHVlLmNoYXJBdCh0aGlzLnNlbGVjdGlvbi5zdGFydCAtIDIpID09PSB0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuX3NldENhcmV0UG9zaXRpb24odGhpcy5zZWxlY3Rpb24uc3RhcnQgLSAxKTtcbiAgICAgICAgICAgICAgICB9IGVsc2UgaWYgKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLlJpZ2h0QXJyb3cgJiZcbiAgICAgICAgICAgICAgICAgICAgKHZhbHVlLmNoYXJBdCh0aGlzLnNlbGVjdGlvbi5zdGFydCArIDEpID09PSB0aGlzLnNldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3IgfHxcbiAgICAgICAgICAgICAgICAgICAgdmFsdWUuY2hhckF0KHRoaXMuc2VsZWN0aW9uLnN0YXJ0ICsgMSkgPT09IHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5fc2V0Q2FyZXRQb3NpdGlvbih0aGlzLnNlbGVjdGlvbi5zdGFydCArIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KHRoaXMuZXZlbnRLZXksIEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLl9kaXJlY3Rpb25LZXlzKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBQcm9jZXNzIGRlbGV0aW9uIG9mIGNoYXJhY3RlcnMgd2hlbiB0aGUgbWludXMgc2lnbiBpcyB0byB0aGUgcmlnaHQgb2YgdGhlIG51bWVyaWMgY2hhcmFjdGVycy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBsZWZ0IFRoZSBwYXJ0IG9uIHRoZSBsZWZ0IG9mIHRoZSBjYXJldCBvciBzZWxlY3Rpb25cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcmlnaHQgVGhlIHBhcnQgb24gdGhlIHJpZ2h0IG9mIHRoZSBjYXJldCBvciBzZWxlY3Rpb25cbiAgICAgKiBAcmV0dXJucyB7W3N0cmluZywgc3RyaW5nXX1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIF9wcm9jZXNzQ2hhcmFjdGVyRGVsZXRpb25JZlRyYWlsaW5nTmVnYXRpdmVTaWduKFtsZWZ0LCByaWdodF0pIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KTtcblxuICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXggJiYgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXgpIHtcbiAgICAgICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5CYWNrc3BhY2UpIHtcbiAgICAgICAgICAgICAgICB0aGlzLmNhcmV0Rml4ID0gKHRoaXMuc2VsZWN0aW9uLnN0YXJ0ID49IHZhbHVlLmluZGV4T2YodGhpcy5zZXR0aW5ncy5zdWZmaXhUZXh0KSAmJiB0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQgIT09ICcnKTtcbiAgICAgICAgICAgICAgICBpZiAodmFsdWUuY2hhckF0KHRoaXMuc2VsZWN0aW9uLnN0YXJ0IC0gMSkgPT09ICctJykge1xuICAgICAgICAgICAgICAgICAgICBsZWZ0ID0gbGVmdC5zdWJzdHJpbmcoMSk7XG4gICAgICAgICAgICAgICAgfSBlbHNlIGlmICh0aGlzLnNlbGVjdGlvbi5zdGFydCA8PSB2YWx1ZS5sZW5ndGggLSB0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQubGVuZ3RoKSB7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygwLCBsZWZ0Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgdGhpcy5jYXJldEZpeCA9ICh0aGlzLnNlbGVjdGlvbi5zdGFydCA+PSB2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dCkgJiYgdGhpcy5zZXR0aW5ncy5zdWZmaXhUZXh0ICE9PSAnJyk7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2VsZWN0aW9uLnN0YXJ0ID49IHZhbHVlLmluZGV4T2YodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCkgKyB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLmxlbmd0aCkge1xuICAgICAgICAgICAgICAgICAgICByaWdodCA9IHJpZ2h0LnN1YnN0cmluZygxLCByaWdodC5sZW5ndGgpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZShsZWZ0KSAmJiB2YWx1ZS5jaGFyQXQodGhpcy5zZWxlY3Rpb24uc3RhcnQpID09PSAnLScpIHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCkge1xuICAgICAgICAgICAgc3dpdGNoICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50KSB7XG4gICAgICAgICAgICAgICAgY2FzZSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQ6XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2FyZXRGaXggPSAodGhpcy5zZWxlY3Rpb24uc3RhcnQgPj0gdmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikgKyB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3Rlci5sZW5ndGgpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQmFja3NwYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAodGhpcy5zZWxlY3Rpb24uc3RhcnQgPT09ICh2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSArIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLmxlbmd0aCkgJiYgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnModmFsdWUsIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobGVmdCAhPT0gJy0nICYmICgodGhpcy5zZWxlY3Rpb24uc3RhcnQgPD0gdmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikpIHx8ICFBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyh2YWx1ZSwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygwLCBsZWZ0Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxlZnRbMF0gPT09ICctJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2VsZWN0aW9uLnN0YXJ0ID09PSB2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSAmJiBBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyh2YWx1ZSwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodDpcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5jYXJldEZpeCA9ICh0aGlzLnNlbGVjdGlvbi5zdGFydCA+PSB2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSArIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyLmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5CYWNrc3BhY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGlvbi5zdGFydCA9PT0gKHZhbHVlLmluZGV4T2YodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpICsgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIubGVuZ3RoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygxKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSBpZiAobGVmdCAhPT0gJy0nICYmIHRoaXMuc2VsZWN0aW9uLnN0YXJ0IDw9ICh2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSAtIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygwLCBsZWZ0Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChsZWZ0ICE9PSAnJyAmJiAhQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnModmFsdWUsIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygwLCBsZWZ0Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYXJldEZpeCA9ICh0aGlzLnNlbGVjdGlvbi5zdGFydCA+PSB2YWx1ZS5pbmRleE9mKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wpICYmIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgIT09ICcnKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLnNlbGVjdGlvbi5zdGFydCA9PT0gdmFsdWUuaW5kZXhPZih0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZWZ0ID0gbGVmdC5zdWJzdHJpbmcoMSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQuc3Vic3RyaW5nKDEpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIFtsZWZ0LCByaWdodF07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUHJvY2VzcyB0aGUgZGVsZXRpb24gb2YgY2hhcmFjdGVycy5cbiAgICAgKi9cbiAgICBfcHJvY2Vzc0NoYXJhY3RlckRlbGV0aW9uKCkge1xuICAgICAgICBsZXQgbGVmdDtcbiAgICAgICAgbGV0IHJpZ2h0O1xuXG4gICAgICAgIGlmICghdGhpcy5zZWxlY3Rpb24ubGVuZ3RoKSB7XG4gICAgICAgICAgICBbbGVmdCwgcmlnaHRdID0gdGhpcy5fZ2V0VW5mb3JtYXR0ZWRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKCk7XG4gICAgICAgICAgICBpZiAobGVmdCA9PT0gJycgJiYgcmlnaHQgPT09ICcnKSB7XG4gICAgICAgICAgICAgICAgdGhpcy50aHJvd0lucHV0ID0gZmFsc2U7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmICh0aGlzLmlzVHJhaWxpbmdOZWdhdGl2ZSAmJiBBdXRvTnVtZXJpY0hlbHBlci5pc05lZ2F0aXZlKEF1dG9OdW1lcmljSGVscGVyLmdldEVsZW1lbnRWYWx1ZSh0aGlzLmRvbUVsZW1lbnQpKSkge1xuICAgICAgICAgICAgICAgIFtsZWZ0LCByaWdodF0gPSB0aGlzLl9wcm9jZXNzQ2hhcmFjdGVyRGVsZXRpb25JZlRyYWlsaW5nTmVnYXRpdmVTaWduKFtsZWZ0LCByaWdodF0pO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuQmFja3NwYWNlKSB7XG4gICAgICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnN1YnN0cmluZygwLCBsZWZ0Lmxlbmd0aCAtIDEpO1xuICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIHJpZ2h0ID0gcmlnaHQuc3Vic3RyaW5nKDEsIHJpZ2h0Lmxlbmd0aCk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgdGhpcy5fZXhwYW5kU2VsZWN0aW9uT25TaWduKCk7XG4gICAgICAgICAgICBbbGVmdCwgcmlnaHRdID0gdGhpcy5fZ2V0VW5mb3JtYXR0ZWRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLl9zZXRWYWx1ZVBhcnRzKGxlZnQsIHJpZ2h0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIGEgZGVjaW1hbCBjaGFyYWN0ZXIgaXMgYWxsb3dlZCB0byBiZSB0eXBlZC5cbiAgICAgKiBJZiB0aGUgbnVtYmVyIG9mIGRlY2ltYWwgcGxhY2VzIHNob3duIG9uIGZvY3VzIGlzIHplcm8sIHRoZW4gdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGlzIG5vdCBhbGxvd2VkLlxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICogQHByaXZhdGVcbiAgICAgKi9cbiAgICBfaXNEZWNpbWFsQ2hhcmFjdGVySW5zZXJ0aW9uQWxsb3dlZCgpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuc2V0dGluZ3MuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyAhPT0gQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzLm5vbmU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUga2V5IGlzIGFsbG93ZWQuXG4gICAgICogVGhpcyBmdW5jdGlvbiBkZWNpZGVzIGlmIHRoZSBrZXkgcHJlc3NlZCBzaG91bGQgYmUgZHJvcHBlZCBvciBhY2NlcHRlZCwgYW5kIG1vZGlmeSB0aGUgdmFsdWUgJ29uLXRoZS1mbHknIGFjY29yZGluZ2x5LlxuICAgICAqIC8vVE9ETyBUaGlzIHNob3VsZCB1c2UgYW5vdGhlciBmdW5jdGlvbiBpbiBvcmRlciB0byBzZXBhcmF0ZSB0aGUgdGVzdCBhbmQgdGhlIG1vZGlmaWNhdGlvblxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgX3Byb2Nlc3NDaGFyYWN0ZXJJbnNlcnRpb24oKSB7XG4gICAgICAgIGxldCBbbGVmdCwgcmlnaHRdID0gdGhpcy5fZ2V0VW5mb3JtYXR0ZWRMZWZ0QW5kUmlnaHRQYXJ0QXJvdW5kVGhlU2VsZWN0aW9uKCk7XG4gICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ICE9PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5BbmRyb2lkRGVmYXVsdCkge1xuICAgICAgICAgICAgdGhpcy50aHJvd0lucHV0ID0gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFN0YXJ0IHJ1bGVzIHdoZW4gdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGtleSBpcyBwcmVzc2VkIGFsd2F5cyB1c2UgbnVtZXJpYyBwYWQgZG90IHRvIGluc2VydCBkZWNpbWFsIHNlcGFyYXRvclxuICAgICAgICAvLyBEbyBub3QgYWxsb3cgZGVjaW1hbCBjaGFyYWN0ZXIgaWYgbm8gZGVjaW1hbCBwYXJ0IGFsbG93ZWRcbiAgICAgICAgaWYgKHRoaXMuZXZlbnRLZXkgPT09IHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciB8fFxuICAgICAgICAgICAgKHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlICYmIHRoaXMuZXZlbnRLZXkgPT09IHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlKSB8fFxuICAgICAgICAgICAgKHRoaXMuZXZlbnRLZXkgPT09ICcuJyB8fCB0aGlzLmV2ZW50S2V5ID09PSAnLCcgfHwgdGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuTnVtcGFkRG90KSkge1xuICAgICAgICAgICAgaWYgKCF0aGlzLl9pc0RlY2ltYWxDaGFyYWN0ZXJJbnNlcnRpb25BbGxvd2VkKCkgfHwgIXRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcikge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAvLyBEbyBub3QgYWxsb3cgZGVjaW1hbCBjaGFyYWN0ZXIgYmVmb3JlIG5lZ2F0aXZlU2lnbkNoYXJhY3RlciBjaGFyYWN0ZXJcbiAgICAgICAgICAgIGlmICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciAmJiBBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhyaWdodCwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIERvIG5vdCBhbGxvdyBhIGRlY2ltYWwgY2hhcmFjdGVyIGlmIGFub3RoZXIgZGVjaW1hbCBjaGFyYWN0ZXIgaXMgYWxyZWFkeSBwcmVzZW50XG4gICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMobGVmdCwgdGhpcy5zZXR0aW5ncy5kZWNpbWFsQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocmlnaHQuaW5kZXhPZih0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpID4gMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAocmlnaHQuaW5kZXhPZih0aGlzLnNldHRpbmdzLmRlY2ltYWxDaGFyYWN0ZXIpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgcmlnaHQgPSByaWdodC5zdWJzdHIoMSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlUGFydHMobGVmdCArIHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3RlciwgcmlnaHQpO1xuXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFByZXZlbnQgZW50ZXJpbmcgdGhlIG1pbnVzIHNpZ24gaWYgaXQncyBub3QgYWxsb3dlZCAoTm90ZTogYHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyYCBpcyBvbmx5IHNldCBpZiB0aGUgbWluaW11bVZhbHVlIG9yIG1heGltdW1WYWx1ZSBpcyBsb3dlciB0aGFuIHplcm8sIGFsbG93aW5nIG5lZ2F0aXZlIG51bWJlcnMgdG8gYmUgZW50ZXJlZClcbiAgICAgICAgaWYgKCh0aGlzLmV2ZW50S2V5ID09PSAnLScgfHwgdGhpcy5ldmVudEtleSA9PT0gJysnKSAmJiB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciA9PT0gJy0nKSB7XG4gICAgICAgICAgICBpZiAobGVmdCA9PT0gJycgJiYgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMocmlnaHQsIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgIC8vIFRoZSB2YWx1ZSBpcyBvcmlnaW5hbGx5IG5lZ2F0aXZlICh3aXRoIGEgdHJhaWxpbmcgbmVnYXRpdmUgc2lnbilcbiAgICAgICAgICAgICAgICByaWdodCA9IHJpZ2h0LnJlcGxhY2UodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIsICcnKTtcbiAgICAgICAgICAgIH0gZWxzZSBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZShsZWZ0KSkge1xuICAgICAgICAgICAgICAgIC8vIFRoZSB2YWx1ZSBpcyBvcmlnaW5hbGx5IG5lZ2F0aXZlICh3aXRoIGEgbGVhZGluZyBuZWdhdGl2ZSBzaWduKVxuICAgICAgICAgICAgICAgIC8vIFJlbW92ZSB0aGUgbmVnYXRpdmUgc2lnbiwgZWZmZWN0aXZlbHkgY29udmVydGluZyB0aGUgdmFsdWUgdG8gYSBwb3NpdGl2ZSBvbmVcbiAgICAgICAgICAgICAgICBsZWZ0ID0gbGVmdC5yZXBsYWNlKCctJywgJycpOyAvL1RPRE8gcmVwbGFjZSB3aXRoICcrJyBpZiBgc2hvd1Bvc2l0aXZlU2lnbmA/XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIC8vIFRoZSB2YWx1ZSBpcyBvcmlnaW5hbGx5IHBvc2l0aXZlXG4gICAgICAgICAgICAgICAgbGVmdCA9IHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyICsgbGVmdDtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgdGhpcy5fc2V0VmFsdWVQYXJ0cyhsZWZ0LCByaWdodCk7XG5cbiAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gSWYgdGhlIHVzZXIgdHJpZXMgdG8gaW5zZXJ0IGEgZGlnaXQgYmVmb3JlIHRoZSBtaW51cyBzaWduXG4gICAgICAgIGNvbnN0IGV2ZW50TnVtYmVyID0gTnVtYmVyKHRoaXMuZXZlbnRLZXkpO1xuICAgICAgICBpZiAoZXZlbnROdW1iZXIgPj0gMCAmJiBldmVudE51bWJlciA8PSA5KSB7XG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgJiYgbGVmdCA9PT0gJycgJiYgQXV0b051bWVyaWNIZWxwZXIuY29udGFpbnMocmlnaHQsIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSkge1xuICAgICAgICAgICAgICAgIGxlZnQgPSB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcjtcbiAgICAgICAgICAgICAgICByaWdodCA9IHJpZ2h0LnN1YnN0cmluZygxLCByaWdodC5sZW5ndGgpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBpZiAodGhpcy5zZXR0aW5ncy5tYXhpbXVtVmFsdWUgPD0gMCAmJiB0aGlzLnNldHRpbmdzLm1pbmltdW1WYWx1ZSA8IHRoaXMuc2V0dGluZ3MubWF4aW11bVZhbHVlICYmICFBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhBdXRvTnVtZXJpY0hlbHBlci5nZXRFbGVtZW50VmFsdWUodGhpcy5kb21FbGVtZW50KSwgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIpICYmIHRoaXMuZXZlbnRLZXkgIT09ICcwJykge1xuICAgICAgICAgICAgICAgIGxlZnQgPSB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlciArIGxlZnQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHRoaXMuX3NldFZhbHVlUGFydHMobGVmdCArIHRoaXMuZXZlbnRLZXksIHJpZ2h0KTtcblxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBQcmV2ZW50IGFueSBvdGhlciBjaGFyYWN0ZXJzXG4gICAgICAgIHRoaXMudGhyb3dJbnB1dCA9IGZhbHNlO1xuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb3JtYXR0aW5nIG9mIGp1c3QgcHJvY2Vzc2VkIHZhbHVlIHdoaWxlIGtlZXBpbmcgdGhlIGN1cnNvciBwb3NpdGlvblxuICAgICAqXG4gICAgICogQHBhcmFtIHtFdmVudH0gZVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgX2Zvcm1hdFZhbHVlKGUpIHtcbiAgICAgICAgY29uc3QgZWxlbWVudFZhbHVlID0gQXV0b051bWVyaWNIZWxwZXIuZ2V0RWxlbWVudFZhbHVlKHRoaXMuZG9tRWxlbWVudCk7XG4gICAgICAgIGxldCBbbGVmdF0gPSB0aGlzLl9nZXRVbmZvcm1hdHRlZExlZnRBbmRSaWdodFBhcnRBcm91bmRUaGVTZWxlY3Rpb24oKTtcblxuICAgICAgICAvLyBObyBncm91cGluZyBzZXBhcmF0b3IgYW5kIG5vIGN1cnJlbmN5IHNpZ25cbiAgICAgICAgaWYgKCh0aGlzLnNldHRpbmdzLmRpZ2l0R3JvdXBTZXBhcmF0b3IgID09PSAnJyB8fCAodGhpcy5zZXR0aW5ncy5kaWdpdEdyb3VwU2VwYXJhdG9yICE9PSAnJyAgJiYgIUF1dG9OdW1lcmljSGVscGVyLmNvbnRhaW5zKGVsZW1lbnRWYWx1ZSwgdGhpcy5zZXR0aW5ncy5kaWdpdEdyb3VwU2VwYXJhdG9yKSkpICYmXG4gICAgICAgICAgICAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCA9PT0gJycgfHwgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgIT09ICcnICYmICFBdXRvTnVtZXJpY0hlbHBlci5jb250YWlucyhlbGVtZW50VmFsdWUsIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wpKSkpIHtcbiAgICAgICAgICAgIGxldCBbc3ViUGFydHNdID0gZWxlbWVudFZhbHVlLnNwbGl0KHRoaXMuc2V0dGluZ3MuZGVjaW1hbENoYXJhY3Rlcik7XG4gICAgICAgICAgICBsZXQgbmVnYXRpdmVTaWduID0gJyc7XG4gICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNOZWdhdGl2ZShzdWJQYXJ0cykpIHtcbiAgICAgICAgICAgICAgICBuZWdhdGl2ZVNpZ24gPSAnLSc7XG4gICAgICAgICAgICAgICAgc3ViUGFydHMgPSBzdWJQYXJ0cy5yZXBsYWNlKCctJywgJycpO1xuICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnJlcGxhY2UoJy0nLCAnJyk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0cmlwIGxlYWRpbmcgemVybyBvbiBwb3NpdGl2ZSB2YWx1ZSBpZiBuZWVkZWRcbiAgICAgICAgICAgIGlmIChuZWdhdGl2ZVNpZ24gPT09ICcnICYmIHN1YlBhcnRzLmxlbmd0aCA+IHRoaXMuc2V0dGluZ3MubUludFBvcyAmJiBsZWZ0LmNoYXJBdCgwKSA9PT0gJzAnKSB7XG4gICAgICAgICAgICAgICAgbGVmdCA9IGxlZnQuc2xpY2UoMSk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIFN0cmlwIGxlYWRpbmcgemVybyBvbiBuZWdhdGl2ZSB2YWx1ZSBpZiBuZWVkZWRcbiAgICAgICAgICAgIGlmIChuZWdhdGl2ZVNpZ24gPT09ICctJyAmJiBzdWJQYXJ0cy5sZW5ndGggPiB0aGlzLnNldHRpbmdzLm1JbnROZWcgJiYgbGVmdC5jaGFyQXQoMCkgPT09ICcwJykge1xuICAgICAgICAgICAgICAgIGxlZnQgPSBsZWZ0LnNsaWNlKDEpO1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZWZ0ID0gbmVnYXRpdmVTaWduICsgbGVmdDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHZhbHVlID0gdGhpcy5jb25zdHJ1Y3Rvci5fYWRkR3JvdXBTZXBhcmF0b3JzKGVsZW1lbnRWYWx1ZSwgdGhpcy5zZXR0aW5ncywgdGhpcy5pc0ZvY3VzZWQsIHRoaXMucmF3VmFsdWUpO1xuICAgICAgICBsZXQgcG9zaXRpb24gPSB2YWx1ZS5sZW5ndGg7XG4gICAgICAgIGlmICh2YWx1ZSkge1xuICAgICAgICAgICAgLy8gUHJlcGFyZSByZWdleHAgd2hpY2ggc2VhcmNoZXMgZm9yIGN1cnNvciBwb3NpdGlvbiBmcm9tIHVuZm9ybWF0dGVkIGxlZnQgcGFydFxuICAgICAgICAgICAgY29uc3QgbGVmdEFyID0gbGVmdC5zcGxpdCgnJyk7XG5cbiAgICAgICAgICAgIC8vIEZpeGVzIGNhcmV0IHBvc2l0aW9uIHdpdGggdHJhaWxpbmcgbWludXMgc2lnblxuICAgICAgICAgICAgaWYgKCh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnN1ZmZpeCB8fFxuICAgICAgICAgICAgICAgICh0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ICE9PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeCAmJiB0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCkpICYmXG4gICAgICAgICAgICAgICAgbGVmdEFyWzBdID09PSAnLScgJiYgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVNpZ25DaGFyYWN0ZXIgIT09ICcnKSB7XG4gICAgICAgICAgICAgICAgbGVmdEFyLnNoaWZ0KCk7XG5cbiAgICAgICAgICAgICAgICBpZiAoKHRoaXMuZXZlbnRLZXkgPT09IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkJhY2tzcGFjZSB8fCB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5EZWxldGUpICYmXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuY2FyZXRGaXgpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnN1ZmZpeCAmJiB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID09PSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LmxlZnQpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXggJiYgdGhpcy5zZXR0aW5ncy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5zdWZmaXgpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBsZWZ0QXIucHVzaCgnLScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5jYXJldEZpeCA9IGUudHlwZSA9PT0gJ2tleWRvd24nO1xuICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQuc3VmZml4ICYmIHRoaXMuc2V0dGluZ3MubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPT09IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IHNpZ25QYXJ0cyA9IHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wuc3BsaXQoJycpO1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZXNjYXBlQ2hyID0gWydcXFxcJywgJ14nLCAnJCcsICcuJywgJ3wnLCAnPycsICcqJywgJysnLCAnKCcsICcpJywgJ1snXTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnN0IGVzY2FwZWRQYXJ0cyA9IFtdO1xuICAgICAgICAgICAgICAgICAgICAgICAgc2lnblBhcnRzLmZvckVhY2goKGksIG1pbmlQYXJ0cykgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG1pbmlQYXJ0cyA9IHNpZ25QYXJ0c1tpXTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNJbkFycmF5KG1pbmlQYXJ0cywgZXNjYXBlQ2hyKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBlc2NhcGVkUGFydHMucHVzaCgnXFxcXCcgKyBtaW5pUGFydHMpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVzY2FwZWRQYXJ0cy5wdXNoKG1pbmlQYXJ0cyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG5cbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5CYWNrc3BhY2UpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlc2NhcGVkUGFydHMucHVzaCgnLScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBQdXNoaW5nIHRoZSBlc2NhcGVkIHNpZ25cbiAgICAgICAgICAgICAgICAgICAgICAgIGxlZnRBci5wdXNoKGVzY2FwZWRQYXJ0cy5qb2luKCcnKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB0aGlzLmNhcmV0Rml4ID0gZS50eXBlID09PSAna2V5ZG93bic7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgbGVmdEFyLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFsZWZ0QXJbaV0ubWF0Y2goJ1xcXFxkJykpIHtcbiAgICAgICAgICAgICAgICAgICAgbGVmdEFyW2ldID0gJ1xcXFwnICsgbGVmdEFyW2ldO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgY29uc3QgbGVmdFJlZyA9IG5ldyBSZWdFeHAoJ14uKj8nICsgbGVmdEFyLmpvaW4oJy4qPycpKTtcblxuICAgICAgICAgICAgLy8gU2VhcmNoIGN1cnNvciBwb3NpdGlvbiBpbiBmb3JtYXR0ZWQgdmFsdWVcbiAgICAgICAgICAgIGNvbnN0IG5ld0xlZnQgPSB2YWx1ZS5tYXRjaChsZWZ0UmVnKTtcbiAgICAgICAgICAgIGlmIChuZXdMZWZ0KSB7XG4gICAgICAgICAgICAgICAgcG9zaXRpb24gPSBuZXdMZWZ0WzBdLmxlbmd0aDtcblxuICAgICAgICAgICAgICAgIC8vIElmIHRoZSBwb3NpdGl2ZSBzaWduIGlzIHNob3duLCBjYWxjdWxhdGUgdGhlIGNhcmV0IHBvc2l0aW9uIGFjY29yZGluZ2x5XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc2hvd1Bvc2l0aXZlU2lnbikge1xuICAgICAgICAgICAgICAgICAgICBpZiAocG9zaXRpb24gPT09IDAgJiYgbmV3TGVmdC5pbnB1dC5jaGFyQXQoMCkgPT09IHRoaXMuc2V0dGluZ3MucG9zaXRpdmVTaWduQ2hhcmFjdGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IChuZXdMZWZ0LmlucHV0LmluZGV4T2YodGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbCkgPT09IDEpID8gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGggKyAxIDogMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgIGlmIChwb3NpdGlvbiA9PT0gMCAmJiBuZXdMZWZ0LmlucHV0LmNoYXJBdCh0aGlzLnNldHRpbmdzLmN1cnJlbmN5U3ltYm9sLmxlbmd0aCkgPT09IHRoaXMuc2V0dGluZ3MucG9zaXRpdmVTaWduQ2hhcmFjdGVyKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoICsgMTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgIC8vIElmIHdlIGFyZSBqdXN0IGJlZm9yZSB0aGUgc2lnbiB3aGljaCBpcyBpbiBwcmVmaXggcG9zaXRpb25cbiAgICAgICAgICAgICAgICBpZiAoKChwb3NpdGlvbiA9PT0gMCAmJiB2YWx1ZS5jaGFyQXQoMCkgIT09IHRoaXMuc2V0dGluZ3MubmVnYXRpdmVTaWduQ2hhcmFjdGVyKSB8fCAocG9zaXRpb24gPT09IDEgJiYgdmFsdWUuY2hhckF0KDApID09PSB0aGlzLnNldHRpbmdzLm5lZ2F0aXZlU2lnbkNoYXJhY3RlcikpICYmIHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgJiYgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXgpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gUGxhY2UgY2FyZXQgYWZ0ZXIgcHJlZml4IHNpZ25cbiAgICAgICAgICAgICAgICAgICAgLy9UT0RPIFNob3VsZCB0aGUgdGVzdCBiZSAnaXNOZWdhdGl2ZScgaW5zdGVhZCBvZiAnaXNOZWdhdGl2ZVN0cmljdCcgaW4gb3JkZXIgdG8gc2VhcmNoIGZvciAnLScgZXZlcnl3aGVyZSBpbiB0aGUgc3RyaW5nP1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wubGVuZ3RoICsgKEF1dG9OdW1lcmljSGVscGVyLmlzTmVnYXRpdmVTdHJpY3QodmFsdWUpID8gMSA6IDApO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3MuY3VycmVuY3lTeW1ib2wgJiYgdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudCA9PT0gQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgpIHtcbiAgICAgICAgICAgICAgICAgICAgLy8gSWYgd2UgY291bGQgbm90IGZpbmQgYSBwbGFjZSBmb3IgY3Vyc29yIGFuZCBoYXZlIGEgc2lnbiBhcyBhIHN1ZmZpeFxuICAgICAgICAgICAgICAgICAgICAvLyBQbGFjZSBjYXJldCBiZWZvcmUgc3VmZml4IGN1cnJlbmN5IHNpZ25cbiAgICAgICAgICAgICAgICAgICAgcG9zaXRpb24gLT0gdGhpcy5zZXR0aW5ncy5jdXJyZW5jeVN5bWJvbC5sZW5ndGg7XG4gICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgaWYgKHRoaXMuc2V0dGluZ3Muc3VmZml4VGV4dCkge1xuICAgICAgICAgICAgICAgICAgICAvLyBJZiB3ZSBjb3VsZCBub3QgZmluZCBhIHBsYWNlIGZvciBjdXJzb3IgYW5kIGhhdmUgYSBzdWZmaXhcbiAgICAgICAgICAgICAgICAgICAgLy8gUGxhY2UgY2FyZXQgYmVmb3JlIHN1ZmZpeFxuICAgICAgICAgICAgICAgICAgICBwb3NpdGlvbiAtPSB0aGlzLnNldHRpbmdzLnN1ZmZpeFRleHQubGVuZ3RoO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIC8vIE9ubHkgdXBkYXRlIHRoZSB2YWx1ZSBpZiBpdCBoYXMgY2hhbmdlZC4gVGhpcyBwcmV2ZW50cyBtb2RpZnlpbmcgdGhlIHNlbGVjdGlvbiwgaWYgYW55LlxuICAgICAgICBpZiAodmFsdWUgIT09IGVsZW1lbnRWYWx1ZSB8fFxuICAgICAgICAgICAgdmFsdWUgPT09IGVsZW1lbnRWYWx1ZSAmJiAodGhpcy5ldmVudEtleSA9PT0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUubnVtMCB8fCB0aGlzLmV2ZW50S2V5ID09PSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5udW1wYWQwKSkge1xuICAgICAgICAgICAgdGhpcy5fc2V0RWxlbWVudFZhbHVlKHZhbHVlKTtcbiAgICAgICAgICAgIHRoaXMuX3NldENhcmV0UG9zaXRpb24ocG9zaXRpb24pO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMuYW5kcm9pZFNlbGVjdGlvblN0YXJ0ICE9PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBJZiBhbiBBbmRyb2lkIGJyb3dzZXIgaXMgZGV0ZWN0ZWQsIGZpeCB0aGUgY2FyZXQgcG9zaXRpb25cbiAgICAgICAgICAgIC8vIFVuZm9ydHVuYXRlbHkgdGhpcyBkb2VzIG5vdCBmaXggYWxsIGFuZHJvaWQgYnJvd3NlcnMsIG9ubHkgQW5kcm9pZCBDaHJvbWUgY3VycmVudGx5LlxuICAgICAgICAgICAgLy8gVGhpcyBpcyBkdWUgdG8gdGhlIGZhY3QgdGhvc2UgcHJvdmlkZSBkaWZmZXJlbnQgb3JkZXIgb2YgZXZlbnRzIGFuZC9vciBrZXljb2RlcyB0aHJvd24gKHRoaXMgaXMgYSByZWFsIG1lc3MgOnwpLlxuICAgICAgICAgICAgdGhpcy5fc2V0Q2FyZXRQb3NpdGlvbih0aGlzLmFuZHJvaWRTZWxlY3Rpb25TdGFydCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzLmZvcm1hdHRlZCA9IHRydWU7IC8vVE9ETyBSZW5hbWUgYHRoaXMuZm9ybWF0dGVkYCB0byBgdGhpcy5fZm9ybWF0RXhlY3V0ZWRgLCBzaW5jZSBpdCdzIHBvc3NpYmxlIHRoaXMgZnVuY3Rpb24gZG9lcyBub3QgbmVlZCB0byBmb3JtYXQgYW55dGhpbmcgKGluIHRoZSBjYXNlIHdoZXJlIHRoZSBrZXljb2RlIGlzIGRyb3BwZWQgZm9yIGluc3RhbmNlKVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlcmlhbGl6ZSB0aGUgZm9ybSBjaGlsZCA8aW5wdXQ+IGVsZW1lbnQgdmFsdWVzIHRvIGEgc3RyaW5nLCBvciBhbiBBcnJheS5cbiAgICAgKiBUaGUgb3V0cHV0IGZvcm1hdCBpcyBkZWZpbmVkIHdpdGggdGhlIGBmb3JtYXRUeXBlYCBhcmd1bWVudC5cbiAgICAgKiBUaGlzIGlzIGxvb3NlbHkgYmFzZWQgdXBvbiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS80MDcwNTk5My8yODM0ODk4LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRm9ybUVsZW1lbnR9IGZvcm1cbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGludG9BbkFycmF5IElmIGB0cnVlYCwgaW5zdGVhZCBvZiBnZW5lcmF0aW5nIGEgc3RyaW5nLCBpdCBnZW5lcmF0ZXMgYW4gQXJyYXkuXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGZvcm1hdFR5cGUgSWYgYCd1bmZvcm1hdHRlZCdgLCB0aGVuIHRoZSBBdXRvTnVtZXJpYyBlbGVtZW50cyB2YWx1ZXMgYXJlIHVuZm9ybWF0dGVkLCBpZiBgJ2xvY2FsaXplZCdgLCB0aGVuIHRoZSBBdXRvTnVtZXJpYyBlbGVtZW50cyB2YWx1ZXMgYXJlIGxvY2FsaXplZCwgYW5kIGlmIGAnZm9ybWF0dGVkJ2AsIHRoZW4gdGhlIEF1dG9OdW1lcmljIGVsZW1lbnRzIHZhbHVlcyBhcmUga2VwdCBmb3JtYXR0ZWQuIEluIGVpdGhlciB3YXksIHRoaXMgZnVuY3Rpb24gZG9lcyBub3QgbW9kaWZ5IHRoZSB2YWx1ZSBvZiBlYWNoIERPTSBlbGVtZW50LCBidXQgb25seSBhZmZlY3QgdGhlIHZhbHVlIHRoYXQgaXMgcmV0dXJuZWQgYnkgdGhhdCBzZXJpYWxpemUgZnVuY3Rpb24uXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlciBDYW4gZWl0aGVyIGJlIHRoZSAnKycgY2hhcmFjdGVyLCBvciB0aGUgJyUyMCcgc3RyaW5nLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IGZvcmNlZE91dHB1dEZvcm1hdCBJZiBzZXQsIHRoZW4gdGhpcyBpcyB0aGUgZm9ybWF0IHRoYXQgaXMgdXNlZCBmb3IgdGhlIGxvY2FsaXphdGlvbiwgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBgb3V0cHV0Rm9ybWF0YCBvcHRpb24uXG4gICAgICogQHJldHVybnMge3N0cmluZ3xBcnJheX1cbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2VyaWFsaXplKGZvcm0sIGludG9BbkFycmF5ID0gZmFsc2UsIGZvcm1hdFR5cGUgPSAndW5mb3JtYXR0ZWQnLCBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIgPSAnKycsIGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGwpIHtcbiAgICAgICAgY29uc3QgcmVzdWx0ID0gW107XG5cbiAgICAgICAgaWYgKHR5cGVvZiBmb3JtID09PSAnb2JqZWN0JyAmJiBmb3JtLm5vZGVOYW1lLnRvTG93ZXJDYXNlKCkgPT09ICdmb3JtJykge1xuICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZm9ybS5lbGVtZW50cykuZm9yRWFjaChlbGVtZW50ID0+IHtcbiAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC5uYW1lICYmXG4gICAgICAgICAgICAgICAgICAgICFlbGVtZW50LmRpc2FibGVkICYmXG4gICAgICAgICAgICAgICAgICAgIFsnZmlsZScsICdyZXNldCcsICdzdWJtaXQnLCAnYnV0dG9uJ10uaW5kZXhPZihlbGVtZW50LnR5cGUpID09PSAtMSkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZWxlbWVudC50eXBlID09PSAnc2VsZWN0LW11bHRpcGxlJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgQXJyYXkucHJvdG90eXBlLnNsaWNlLmNhbGwoZWxlbWVudC5vcHRpb25zKS5mb3JFYWNoKG9wdGlvbiA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKG9wdGlvbi5zZWxlY3RlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvL1RPRE8gU2hvdWxkIHdlIHVuZm9ybWF0L2Zvcm1hdC9sb2NhbGl6ZSB0aGUgc2VsZWN0aW9uIG9wdGlvbiAod2hpY2ggYmUgZGVmYXVsdCBzaG91bGQgYmUgcmVhZC1vbmx5KT9cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGludG9BbkFycmF5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaCh7IG5hbWU6IGVsZW1lbnQubmFtZSwgdmFsdWU6IG9wdGlvbi52YWx1ZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsgLy8gaW50byBhIHN0cmluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzdWx0LnB1c2goYCR7ZW5jb2RlVVJJQ29tcG9uZW50KGVsZW1lbnQubmFtZSl9PSR7ZW5jb2RlVVJJQ29tcG9uZW50KG9wdGlvbi52YWx1ZSl9YCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIGlmIChbJ2NoZWNrYm94JywgJ3JhZGlvJ10uaW5kZXhPZihlbGVtZW50LnR5cGUpID09PSAtMSB8fCBlbGVtZW50LmNoZWNrZWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGxldCB2YWx1ZVJlc3VsdDtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmICh0aGlzLmlzTWFuYWdlZEJ5QXV0b051bWVyaWMoZWxlbWVudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBsZXQgYW5PYmplY3Q7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgc3dpdGNoIChmb3JtYXRUeXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNhc2UgJ3VuZm9ybWF0dGVkJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuT2JqZWN0ID0gdGhpcy5nZXRBdXRvTnVtZXJpY0VsZW1lbnQoZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChhbk9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB2YWx1ZVJlc3VsdCA9IHRoaXMudW5mb3JtYXQoZWxlbWVudCwgYW5PYmplY3QuZ2V0U2V0dGluZ3MoKSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnbG9jYWxpemVkJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuT2JqZWN0ID0gdGhpcy5nZXRBdXRvTnVtZXJpY0VsZW1lbnQoZWxlbWVudCk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChhbk9iamVjdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAvLyBIZXJlIEkgbmVlZCB0byBjbG9uZSB0aGUgc2V0dGluZyBvYmplY3QsIG90aGVyd2lzZSBJIHdvdWxkIG1vZGlmeSBpdCB3aGVuIGNoYW5naW5nIHRoZSBgb3V0cHV0Rm9ybWF0YCBvcHRpb24gdmFsdWVcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBjdXJyZW50U2V0dGluZ3MgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChhbk9iamVjdC5nZXRTZXR0aW5ncygpKTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIUF1dG9OdW1lcmljSGVscGVyLmlzTnVsbChmb3JjZWRPdXRwdXRGb3JtYXQpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRTZXR0aW5ncy5vdXRwdXRGb3JtYXQgPSBmb3JjZWRPdXRwdXRGb3JtYXQ7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVSZXN1bHQgPSB0aGlzLmxvY2FsaXplKGVsZW1lbnQsIGN1cnJlbnRTZXR0aW5ncyk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2FzZSAnZm9ybWF0dGVkJzpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlUmVzdWx0ID0gZWxlbWVudC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHZhbHVlUmVzdWx0ID0gZWxlbWVudC52YWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKEF1dG9OdW1lcmljSGVscGVyLmlzVW5kZWZpbmVkKHZhbHVlUmVzdWx0KSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoJ1RoaXMgZXJyb3Igc2hvdWxkIG5ldmVyIGJlIGhpdC4gSWYgaXQgaGFzLCBzb21ldGhpbmcgcmVhbGx5IHdyb25nIGhhcHBlbmVkIScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoaW50b0FuQXJyYXkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXN1bHQucHVzaCh7IG5hbWU6IGVsZW1lbnQubmFtZSwgdmFsdWU6IHZhbHVlUmVzdWx0IH0pO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHsgLy8gaW50byBhIHN0cmluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdC5wdXNoKGAke2VuY29kZVVSSUNvbXBvbmVudChlbGVtZW50Lm5hbWUpfT0ke2VuY29kZVVSSUNvbXBvbmVudCh2YWx1ZVJlc3VsdCl9YCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGxldCBmaW5hbFJlc3VsdDtcblxuICAgICAgICBpZiAoaW50b0FuQXJyYXkpIHtcbiAgICAgICAgICAgIC8vIFJlc3VsdCBhcyBhbiBBcnJheVxuICAgICAgICAgICAgLy8gTm90ZTogYHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlcmAgZG9lcyBub3QgYWZmZWN0IHRoZSBhcnJheSByZXN1bHQgc2luY2Ugd2UgZG8gbm90IGNoYW5nZSB0aGUgc3BhY2UgY2hhcmFjdGVyIGZvciB0aGlzIG9uZVxuICAgICAgICAgICAgZmluYWxSZXN1bHQgPSByZXN1bHQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBSZXN1bHQgYXMgYSBzdHJpbmdcbiAgICAgICAgICAgIGZpbmFsUmVzdWx0ID0gcmVzdWx0LmpvaW4oJyYnKTtcblxuICAgICAgICAgICAgaWYgKCcrJyA9PT0gc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyKSB7XG4gICAgICAgICAgICAgICAgZmluYWxSZXN1bHQgPSBmaW5hbFJlc3VsdC5yZXBsYWNlKC8lMjAvZywgJysnKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBmaW5hbFJlc3VsdDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXJpYWxpemUgdGhlIGZvcm0gdmFsdWVzIHRvIGEgc3RyaW5nLCBvdXRwdXR0aW5nIG51bWVyaWMgc3RyaW5ncyBmb3IgZWFjaCBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnQgdmFsdWVzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRm9ybUVsZW1lbnR9IGZvcm1cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgX3NlcmlhbGl6ZU51bWVyaWNTdHJpbmcoZm9ybSwgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyID0gJysnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zZXJpYWxpemUoZm9ybSwgZmFsc2UsICd1bmZvcm1hdHRlZCcsIHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3Rlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2VyaWFsaXplIHRoZSBmb3JtIHZhbHVlcyB0byBhIHN0cmluZywgb3V0cHV0dGluZyB0aGUgZm9ybWF0dGVkIHZhbHVlIGFzIHN0cmluZ3MgZm9yIGVhY2ggQXV0b051bWVyaWMtbWFuYWdlZCBlbGVtZW50cy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fSBmb3JtXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlclxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd9XG4gICAgICovXG4gICAgc3RhdGljIF9zZXJpYWxpemVGb3JtYXR0ZWQoZm9ybSwgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyID0gJysnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zZXJpYWxpemUoZm9ybSwgZmFsc2UsICdmb3JtYXR0ZWQnLCBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNlcmlhbGl6ZSB0aGUgZm9ybSB2YWx1ZXMgdG8gYSBzdHJpbmcsIG91dHB1dHRpbmcgbG9jYWxpemVkIHN0cmluZ3MgZm9yIGVhY2ggQXV0b051bWVyaWMtbWFuYWdlZCBlbGVtZW50IHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fSBmb3JtXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IGZvcmNlZE91dHB1dEZvcm1hdCBJZiBzZXQsIHRoZW4gdGhpcyBpcyB0aGUgZm9ybWF0IHRoYXQgaXMgdXNlZCBmb3IgdGhlIGxvY2FsaXphdGlvbiwgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBgb3V0cHV0Rm9ybWF0YCBvcHRpb24uXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgX3NlcmlhbGl6ZUxvY2FsaXplZChmb3JtLCBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIgPSAnKycsIGZvcmNlZE91dHB1dEZvcm1hdCA9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlcmlhbGl6ZShmb3JtLCBmYWxzZSwgJ2xvY2FsaXplZCcsIHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlciwgZm9yY2VkT3V0cHV0Rm9ybWF0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZW5lcmF0ZSBhbiBBcnJheSB3aXRoIHRoZSBmb3JtIHZhbHVlcywgb3V0cHV0dGluZyBudW1lcmljIHN0cmluZ3MgZm9yIGVhY2ggQXV0b051bWVyaWMtbWFuYWdlZCBlbGVtZW50IHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fSBmb3JtXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlclxuICAgICAqIEByZXR1cm5zIHtBcnJheX1cbiAgICAgKi9cbiAgICBzdGF0aWMgX3NlcmlhbGl6ZU51bWVyaWNTdHJpbmdBcnJheShmb3JtLCBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIgPSAnKycpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuX3NlcmlhbGl6ZShmb3JtLCB0cnVlLCAndW5mb3JtYXR0ZWQnLCBzZXJpYWxpemVkU3BhY2VDaGFyYWN0ZXIpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEdlbmVyYXRlIGFuIEFycmF5IHdpdGggdGhlIGZvcm0gdmFsdWVzLCBvdXRwdXR0aW5nIHRoZSBmb3JtYXR0ZWQgdmFsdWUgYXMgc3RyaW5ncyBmb3IgZWFjaCBBdXRvTnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnRzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRm9ybUVsZW1lbnR9IGZvcm1cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyXG4gICAgICogQHJldHVybnMge0FycmF5fVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2VyaWFsaXplRm9ybWF0dGVkQXJyYXkoZm9ybSwgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyID0gJysnKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zZXJpYWxpemUoZm9ybSwgdHJ1ZSwgJ2Zvcm1hdHRlZCcsIHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3Rlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYW4gQXJyYXkgd2l0aCB0aGUgZm9ybSB2YWx1ZXMsIG91dHB1dHRpbmcgbG9jYWxpemVkIHN0cmluZ3MgZm9yIGVhY2ggQXV0b051bWVyaWMtbWFuYWdlZCBlbGVtZW50IHZhbHVlcy5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEZvcm1FbGVtZW50fSBmb3JtXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfG51bGx9IGZvcmNlZE91dHB1dEZvcm1hdCBJZiBzZXQsIHRoZW4gdGhpcyBpcyB0aGUgZm9ybWF0IHRoYXQgaXMgdXNlZCBmb3IgdGhlIGxvY2FsaXphdGlvbiwgaW5zdGVhZCBvZiB0aGUgZGVmYXVsdCBgb3V0cHV0Rm9ybWF0YCBvcHRpb24uXG4gICAgICogQHJldHVybnMge0FycmF5fVxuICAgICAqL1xuICAgIHN0YXRpYyBfc2VyaWFsaXplTG9jYWxpemVkQXJyYXkoZm9ybSwgc2VyaWFsaXplZFNwYWNlQ2hhcmFjdGVyID0gJysnLCBmb3JjZWRPdXRwdXRGb3JtYXQgPSBudWxsKSB7XG4gICAgICAgIHJldHVybiB0aGlzLl9zZXJpYWxpemUoZm9ybSwgdHJ1ZSwgJ2xvY2FsaXplZCcsIHNlcmlhbGl6ZWRTcGFjZUNoYXJhY3RlciwgZm9yY2VkT3V0cHV0Rm9ybWF0KTtcbiAgICB9XG59XG5cbi8qKlxuICogSW5pdGlhbGl6ZSBtdWx0aXBsZSBET00gZWxlbWVudHMgaW4gb25lIGNhbGwgKGFuZCBwb3NzaWJseSBwYXNzIG11bHRpcGxlIHZhbHVlcyB0aGF0IHdpbGwgYmUgbWFwcGVkIHRvIGVhY2ggRE9NIGVsZW1lbnQpLlxuICpcbiAqIEBleGFtcGxlXG4gKiAvLyBJbml0IG11bHRpcGxlIERPTSBlbGVtZW50cyBpbiBvbmUgY2FsbCAoYW5kIHBvc3NpYmx5IHBhc3MgbXVsdGlwbGUgdmFsdWVzIHRoYXQgd2lsbCBiZSBtYXBwZWQgdG8gZWFjaCBET00gZWxlbWVudClcbiAqIFthbkVsZW1lbnQxLCBhbkVsZW1lbnQyLCBhbkVsZW1lbnQzXSA9IEF1dG9OdW1lcmljLm11bHRpcGxlKFtkb21FbGVtZW50MSwgZG9tRWxlbWVudDIsIGRvbUVsZW1lbnQzXSwgeyBvcHRpb25zIH0pO1xuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDIsIGFuRWxlbWVudDNdID0gQXV0b051bWVyaWMubXVsdGlwbGUoW2RvbUVsZW1lbnQxLCBkb21FbGVtZW50MiwgZG9tRWxlbWVudDNdLCBbeyBvcHRpb25zIH0sICdldXJvUG9zJ10pO1xuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDIsIGFuRWxlbWVudDNdID0gQXV0b051bWVyaWMubXVsdGlwbGUoW2RvbUVsZW1lbnQxLCBkb21FbGVtZW50MiwgZG9tRWxlbWVudDNdLCAxMjM0NS43ODksIHsgb3B0aW9ucyB9KTtcbiAqIFthbkVsZW1lbnQxLCBhbkVsZW1lbnQyLCBhbkVsZW1lbnQzXSA9IEF1dG9OdW1lcmljLm11bHRpcGxlKFtkb21FbGVtZW50MSwgZG9tRWxlbWVudDIsIGRvbUVsZW1lbnQzXSwgMTIzNDUuNzg5LCBbeyBvcHRpb25zIH0sICdldXJvUG9zJ10pO1xuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDIsIGFuRWxlbWVudDNdID0gQXV0b051bWVyaWMubXVsdGlwbGUuZnJlbmNoKFtkb21FbGVtZW50MSwgZG9tRWxlbWVudDIsIGRvbUVsZW1lbnQzXSwgWzEyMzQ1Ljc4OSwgMjM0Ljc4LCBudWxsXSwgeyBvcHRpb25zIH0pO1xuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDIsIGFuRWxlbWVudDNdID0gQXV0b051bWVyaWMubXVsdGlwbGUuZnJlbmNoKFtkb21FbGVtZW50MSwgZG9tRWxlbWVudDIsIGRvbUVsZW1lbnQzXSwgWzEyMzQ1Ljc4OSwgMjM0Ljc4LCBudWxsXSwgW3sgb3B0aW9ucyB9LCAnZXVyb1BvcyddKTtcbiAqXG4gKiAvLyBTcGVjaWFsIGNhc2UsIGlmIGEgPGZvcm0+IGVsZW1lbnQgaXMgcGFzc2VkIChvciBhbnkgb3RoZXIgJ3BhcmVudCcgKG9yICdyb290JykgRE9NIGVsZW1lbnQpLCB0aGVuIGF1dG9OdW1lcmljIHdpbGwgaW5pdGlhbGl6ZSBlYWNoIGNoaWxkIGA8aW5wdXQ+YCBlbGVtZW50cyByZWN1cnNpdmVseSwgaWdub3JpbmcgdGhvc2UgcmVmZXJlbmNlZCBpbiB0aGUgYGV4Y2x1ZGVgIGF0dHJpYnV0ZVxuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDJdID0gQXV0b051bWVyaWMubXVsdGlwbGUoeyByb290RWxlbWVudDogZm9ybUVsZW1lbnQgfSwgeyBvcHRpb25zIH0pO1xuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDJdID0gQXV0b051bWVyaWMubXVsdGlwbGUoeyByb290RWxlbWVudDogZm9ybUVsZW1lbnQsIGV4Y2x1ZGUgOiBbaGlkZGVuRWxlbWVudCwgdG9rZW5FbGVtZW50XSB9LCB7IG9wdGlvbnMgfSk7XG4gKiBbYW5FbGVtZW50MSwgYW5FbGVtZW50Ml0gPSBBdXRvTnVtZXJpYy5tdWx0aXBsZSh7IHJvb3RFbGVtZW50OiBmb3JtRWxlbWVudCwgZXhjbHVkZSA6IFtoaWRkZW5FbGVtZW50LCB0b2tlbkVsZW1lbnRdIH0sIFsxMjM0NS43ODksIG51bGxdLCB7IG9wdGlvbnMgfSk7XG4gKlxuICogLy8gSWYgeW91IHdhbnQgdG8gc2VsZWN0IG11bHRpcGxlIGVsZW1lbnRzIHZpYSBhIGNzcyBzZWxlY3RvciwgdGhlbiB5b3UgbXVzdCB1c2UgdGhlIGBtdWx0aXBsZWAgZnVuY3Rpb24uIFVuZGVyIHRoZSBob29kIGBRdWVyeVNlbGVjdG9yQWxsYCBpcyB1c2VkLlxuICogW2FuRWxlbWVudDEsIGFuRWxlbWVudDJdID0gQXV0b051bWVyaWMubXVsdGlwbGUoJy5teUNzc0NsYXNzID4gaW5wdXQnLCB7IG9wdGlvbnMgfSk7IC8vIFRoaXMgYWx3YXlzIHJldHVybiBhbiBBcnJheSwgZXZlbiBpZiB0aGVyZSBpcyBvbmx5IG9uZSBlbGVtZW50IHNlbGVjdGVkXG4gKiBbYW5FbGVtZW50MSwgYW5FbGVtZW50Ml0gPSBBdXRvTnVtZXJpYy5tdWx0aXBsZSgnLm15Q3NzQ2xhc3MgPiBpbnB1dCcsIFtudWxsLCAxMjM0NS43ODldLCB7IG9wdGlvbnMgfSk7IC8vIElkZW0gYWJvdmUsIGJ1dCB3aXRoIHBhc3NpbmcgdGhlIGluaXRpYWwgdmFsdWVzIHRvb1xuICpcbiAqIEBwYXJhbSB7c3RyaW5nfEFycmF5fHsgcm9vdEVsZW1lbnQ6IEhUTUxFbGVtZW50IH18eyByb290RWxlbWVudDogSFRNTEVsZW1lbnQsIGV4Y2x1ZGU6IEFycmF5PEhUTUxJbnB1dEVsZW1lbnQ+fX0gYXJnMVxuICogQHBhcmFtIHtudW1iZXJ8QXJyYXl8b2JqZWN0fG51bGx9IGluaXRpYWxWYWx1ZVxuICogQHBhcmFtIHtvYmplY3R8QXJyYXl8bnVsbH0gb3B0aW9uc1xuICogQHJldHVybnMge0FycmF5fVxuICovXG5BdXRvTnVtZXJpYy5tdWx0aXBsZSA9IChhcmcxLCBpbml0aWFsVmFsdWUgPSBudWxsLCBvcHRpb25zID0gbnVsbCkgPT4ge1xuICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuXG4gICAgLy8gQW5hbHl6ZSB0aGUgYXJndW1lbnRzIGFuZCB0cmFuc2Zvcm0gdGhlbSB0byBtYWtlIHRoZW0gZXhwbG9pdGFibGVcbiAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNPYmplY3QoaW5pdGlhbFZhbHVlKSkge1xuICAgICAgICAvLyBJZiB0aGUgdXNlciBnYXZlIGFuIG9wdGlvbiBvYmplY3QgYXMgdGhlIHNlY29uZCBhcmd1bWVudCwgaW5zdGVhZCBvZiB0aGUgaW5pdGlhbCB2YWx1ZXNcbiAgICAgICAgb3B0aW9ucyA9IGluaXRpYWxWYWx1ZTtcbiAgICAgICAgaW5pdGlhbFZhbHVlID0gbnVsbDtcbiAgICB9XG5cbiAgICBpZiAoQXV0b051bWVyaWNIZWxwZXIuaXNTdHJpbmcoYXJnMSkpIHtcbiAgICAgICAgYXJnMSA9IFsuLi4gZG9jdW1lbnQucXVlcnlTZWxlY3RvckFsbChhcmcxKV07IC8vIENvbnZlcnQgYSBOb2RlTGlzdCB0byBhbiBBcnJheSAoY2YuIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzM3Mjk3MjkyLzI4MzQ4OTgpXG4gICAgfSBlbHNlIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc09iamVjdChhcmcxKSkge1xuICAgICAgICBpZiAoIWFyZzEuaGFzT3duUHJvcGVydHkoJ3Jvb3RFbGVtZW50JykpIHtcbiAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSBvYmplY3QgcGFzc2VkIHRvIHRoZSAnbXVsdGlwbGUnIGZ1bmN0aW9uIGlzIGludmFsaWQgOyBubyAncm9vdEVsZW1lbnQnIGF0dHJpYnV0ZSBmb3VuZC5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJldHJpZXZlIHRoZSBET00gZWxlbWVudCBsaXN0IGZyb20gdGhlIGdpdmVuIDxmb3JtPiBlbGVtZW50XG4gICAgICAgIGNvbnN0IGVsZW1lbnRzID0gWy4uLiBhcmcxLnJvb3RFbGVtZW50LnF1ZXJ5U2VsZWN0b3JBbGwoJ2lucHV0JyldO1xuICAgICAgICBpZiAoYXJnMS5oYXNPd25Qcm9wZXJ0eSgnZXhjbHVkZScpKSB7XG4gICAgICAgICAgICBpZiAoIUFycmF5LmlzQXJyYXkoYXJnMS5leGNsdWRlKSkge1xuICAgICAgICAgICAgICAgIEF1dG9OdW1lcmljSGVscGVyLnRocm93RXJyb3IoYFRoZSAnZXhjbHVkZScgYXJyYXkgcGFzc2VkIHRvIHRoZSAnbXVsdGlwbGUnIGZ1bmN0aW9uIGlzIGludmFsaWQuYCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIC8vIEZpbHRlciBvdXQgdGhlIGV4Y2x1ZGVkIGVsZW1lbnRzXG4gICAgICAgICAgICBhcmcxID0gQXV0b051bWVyaWNIZWxwZXIuZmlsdGVyT3V0KGVsZW1lbnRzLCBhcmcxLmV4Y2x1ZGUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgYXJnMSA9IGVsZW1lbnRzO1xuICAgICAgICB9XG4gICAgfSBlbHNlIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNBcnJheShhcmcxKSkge1xuICAgICAgICBBdXRvTnVtZXJpY0hlbHBlci50aHJvd0Vycm9yKGBUaGUgZ2l2ZW4gcGFyYW1ldGVycyB0byB0aGUgJ211bHRpcGxlJyBmdW5jdGlvbiBhcmUgaW52YWxpZC5gKTtcbiAgICB9XG5cbiAgICBpZiAoYXJnMS5sZW5ndGggPT09IDApIHtcbiAgICAgICAgbGV0IHNob3dXYXJuaW5ncyA9IHRydWU7XG4gICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKG9wdGlvbnMpICYmIEF1dG9OdW1lcmljSGVscGVyLmlzQm9vbGVhbihvcHRpb25zLnNob3dXYXJuaW5ncykpIHtcbiAgICAgICAgICAgIHNob3dXYXJuaW5ncyA9IG9wdGlvbnMuc2hvd1dhcm5pbmdzO1xuICAgICAgICB9XG5cbiAgICAgICAgQXV0b051bWVyaWNIZWxwZXIud2FybmluZyhgTm8gdmFsaWQgRE9NIGVsZW1lbnRzIHdlcmUgZ2l2ZW4gaGVuY2Ugbm8gQXV0b051bWVyaWMgb2JqZWN0IHdlcmUgaW5zdGFudGlhdGVkLmAsIHNob3dXYXJuaW5ncyk7XG5cbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cblxuICAgIC8vIEF0IHRoaXMgcG9pbnQsIHdlIGtub3cgYGFyZzFgIGlzIGFuIGFycmF5IG9mIERPTSBlbGVtZW50c1xuXG4gICAgLy8gVGhpcyBmdW5jdGlvbiBjYW4gYmUgaW5pdGlhbGl6ZWQgd2l0aCB0d28gdHlwZXMgb2YgYXJyYXksIG9uZSBmb3IgdGhlIGluaXRpYWwgdmFsdWVzLCBhbmQvb3Igb25lIGZvciB0aGUgb3B0aW9ucy5cbiAgICAvLyBTbyB3ZSBuZWVkIHRvIGZpbmQgb3V0IGlmIGFuIGFycmF5IGlzIGRldGVjdGVkIGlmIHRoZSB1c2VyIHBhc3NlZCBhbiBhcnJheSBvZiBpbml0aWFsIHZhbHVlcywgb3IgYW4gYXJyYXkgb2Ygb3B0aW9uc1xuICAgIC8vIFRoZXJlZm9yZSwgd2UgYW5hbHl6ZSB0aGUgY29udGVudCBvZiB0aGUgYXJyYXlzIGZvciB0aGUgc2Vjb25kIGFuZCB0aGlyZCBhcmd1bWVudHNcbiAgICAvLyAuLi5mb3IgdGhlIHNlY29uZCBwYXJhbWV0ZXIgOlxuICAgIGNvbnN0IGlzSW5pdGlhbFZhbHVlQXJyYXkgPSBBdXRvTnVtZXJpY0hlbHBlci5pc0FycmF5KGluaXRpYWxWYWx1ZSk7XG4gICAgY29uc3QgaXNJbml0aWFsVmFsdWVBcnJheUFuZE5vdEVtcHR5ID0gaXNJbml0aWFsVmFsdWVBcnJheSAmJiBpbml0aWFsVmFsdWUubGVuZ3RoID49IDE7XG4gICAgbGV0IHNlY29uZEFyZ3VtZW50SXNJbml0aWFsVmFsdWVBcnJheSA9IGZhbHNlO1xuICAgIGxldCBzZWNvbmRBcmd1bWVudElzT3B0aW9uQXJyYXkgPSBmYWxzZTtcbiAgICAvLyBBbnkgb2YgdGhlIGFycmF5cyBjYW4gYmUgZWl0aGVyIGFuIGFycmF5IG9mIGluaXRpYWwgdmFsdWVzLCBvciBhbiBhcnJheSBvZiBvcHRpb24gb2JqZWN0L3ByZS1kZWZpbmVkIG9wdGlvbiBuYW1lc1xuICAgIGlmIChpc0luaXRpYWxWYWx1ZUFycmF5QW5kTm90RW1wdHkpIHtcbiAgICAgICAgY29uc3QgdHlwZU9mRmlyc3RBcnJheUVsZW1lbnQgPSB0eXBlb2YgTnVtYmVyKGluaXRpYWxWYWx1ZVswXSk7XG4gICAgICAgIC8vIEZpcnN0IHdlIHRlc3QgdGhlIHNlY29uZCBhcmd1bWVudFxuICAgICAgICBzZWNvbmRBcmd1bWVudElzSW5pdGlhbFZhbHVlQXJyYXkgPSB0eXBlT2ZGaXJzdEFycmF5RWxlbWVudCA9PT0gJ251bWJlcicgJiYgIWlzTmFOKE51bWJlcihpbml0aWFsVmFsdWVbMF0pKTtcblxuICAgICAgICBpZiAoIXNlY29uZEFyZ3VtZW50SXNJbml0aWFsVmFsdWVBcnJheSkge1xuICAgICAgICAgICAgLy8gSWYgdGhlIHNlY29uZCBhcmd1bWVudCBpcyBhbiBhcnJheSwgYnV0IG5vdCBhbiBhcnJheSBvZiB2YWx1ZXMsIGNoZWNrIGlmIGl0J3MgaW5zdGVhZCBhbiBhcnJheSBvZiBvcHRpb25zL3ByZS1kZWZpbmVkIG9wdGlvbiBuYW1lc1xuICAgICAgICAgICAgaWYgKHR5cGVPZkZpcnN0QXJyYXlFbGVtZW50ID09PSAnc3RyaW5nJyB8fCBpc05hTih0eXBlT2ZGaXJzdEFycmF5RWxlbWVudCkgfHwgdHlwZU9mRmlyc3RBcnJheUVsZW1lbnQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAgICAgc2Vjb25kQXJndW1lbnRJc09wdGlvbkFycmF5ID0gdHJ1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIC4uLmZvciB0aGUgdGhpcmQgcGFyYW1ldGVyIDpcbiAgICBjb25zdCBpc09wdGlvbnNBcnJheUFuZE5vdEVtcHR5ID0gQXV0b051bWVyaWNIZWxwZXIuaXNBcnJheShvcHRpb25zKSAmJiBvcHRpb25zLmxlbmd0aCA+PSAxO1xuICAgIGxldCB0aGlyZEFyZ3VtZW50SXNPcHRpb25BcnJheSA9IGZhbHNlO1xuICAgIGlmIChpc09wdGlvbnNBcnJheUFuZE5vdEVtcHR5KSB7XG4gICAgICAgIGNvbnN0IHR5cGVPZkZpcnN0QXJyYXlFbGVtZW50ID0gdHlwZW9mIG9wdGlvbnNbMF07XG4gICAgICAgIGlmICh0eXBlT2ZGaXJzdEFycmF5RWxlbWVudCA9PT0gJ3N0cmluZycgfHwgdHlwZU9mRmlyc3RBcnJheUVsZW1lbnQgPT09ICdvYmplY3QnKSB7XG4gICAgICAgICAgICAvLyBJZiB0aGUgdGhpcmQgYXJndW1lbnQgaXMgYW4gYXJyYXkgb2Ygb3B0aW9ucy9wcmUtZGVmaW5lZCBvcHRpb24gbmFtZXNcbiAgICAgICAgICAgIHRoaXJkQXJndW1lbnRJc09wdGlvbkFycmF5ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8vIERlcGVuZGluZyBvZiBvdXIgZmluZGluZ3MsIHdlIGdlbmVyYXRlIHRoZSBvcHRpb25zIHZhcmlhYmxlIHRvIHVzZSBgb3B0aW9uc1RvVXNlYCwgZWl0aGVyIGRpcmVjdGx5LCBvciBtZXJnZWRcbiAgICBsZXQgb3B0aW9uc1RvVXNlO1xuICAgIGlmIChzZWNvbmRBcmd1bWVudElzT3B0aW9uQXJyYXkpIHtcbiAgICAgICAgb3B0aW9uc1RvVXNlID0gQXV0b051bWVyaWMubWVyZ2VPcHRpb25zKGluaXRpYWxWYWx1ZSk7XG4gICAgfSBlbHNlIGlmICh0aGlyZEFyZ3VtZW50SXNPcHRpb25BcnJheSkge1xuICAgICAgICBvcHRpb25zVG9Vc2UgPSBBdXRvTnVtZXJpYy5tZXJnZU9wdGlvbnMob3B0aW9ucyk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgb3B0aW9uc1RvVXNlID0gb3B0aW9ucztcbiAgICB9XG5cblxuICAgIC8vIEluaXRpYWxpemUgdGhlIGluaXRpYWwgdmFsdWVzXG4gICAgY29uc3QgaXNJbml0aWFsVmFsdWVOdW1iZXIgPSBBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcihpbml0aWFsVmFsdWUpO1xuICAgIGxldCBpbml0aWFsVmFsdWVBcnJheVNpemU7XG4gICAgaWYgKHNlY29uZEFyZ3VtZW50SXNJbml0aWFsVmFsdWVBcnJheSkge1xuICAgICAgICBpbml0aWFsVmFsdWVBcnJheVNpemUgPSBpbml0aWFsVmFsdWUubGVuZ3RoO1xuICAgIH1cblxuICAgIC8vIEluc3RhbnRpYXRlIGVhY2ggQXV0b051bWVyaWMgb2JqZWN0c1xuICAgIGFyZzEuZm9yRWFjaCgoZG9tRWxlbWVudCwgaW5kZXgpID0+IHtcbiAgICAgICAgaWYgKGlzSW5pdGlhbFZhbHVlTnVtYmVyKSB7XG4gICAgICAgICAgICAvLyBXZSBzZXQgdGhlIHNhbWUgdmFsdWUgZm9yIGVhY2ggZWxlbWVudHNcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCBpbml0aWFsVmFsdWUsIG9wdGlvbnNUb1VzZSkpO1xuICAgICAgICB9IGVsc2UgaWYgKHNlY29uZEFyZ3VtZW50SXNJbml0aWFsVmFsdWVBcnJheSAmJiBpbmRleCA8PSBpbml0aWFsVmFsdWVBcnJheVNpemUpIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCBpbml0aWFsVmFsdWVbaW5kZXhdLCBvcHRpb25zVG9Vc2UpKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlc3VsdC5wdXNoKG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCBudWxsLCBvcHRpb25zVG9Vc2UpKTtcbiAgICAgICAgfVxuICAgIH0pO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbi8qKlxuICogUG9seWZpbGwgZnJvbSBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvQ3VzdG9tRXZlbnQvQ3VzdG9tRXZlbnQgZm9yIG9ic29sZXRlIGJyb3dzZXJzIChJRSlcbiAqIC8vVE9ETyBNYWtlIHN1cmUgd2UgY2FsbCB0aGF0IGF0IGxlYXN0IG9uY2Ugd2hlbiBsb2FkaW5nIHRoZSBBdXRvTnVtZXJpYyBsaWJyYXJ5XG4gKi9cbihmdW5jdGlvbigpIHtcbmlmICh0eXBlb2Ygd2luZG93LkN1c3RvbUV2ZW50ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgcmV0dXJuIGZhbHNlO1xufVxuXG5mdW5jdGlvbiBDdXN0b21FdmVudChldmVudCwgcGFyYW1zKSB7XG4gICAgcGFyYW1zID0gcGFyYW1zIHx8IHsgYnViYmxlczogZmFsc2UsIGNhbmNlbGFibGU6IGZhbHNlLCBkZXRhaWw6IHZvaWQoMCkgfTtcbiAgICBjb25zdCBldnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnQ3VzdG9tRXZlbnQnKTtcbiAgICBldnQuaW5pdEN1c3RvbUV2ZW50KGV2ZW50LCBwYXJhbXMuYnViYmxlcywgcGFyYW1zLmNhbmNlbGFibGUsIHBhcmFtcy5kZXRhaWwpO1xuICAgIHJldHVybiBldnQ7XG59XG5cbkN1c3RvbUV2ZW50LnByb3RvdHlwZSA9IHdpbmRvdy5FdmVudC5wcm90b3R5cGU7XG53aW5kb3cuQ3VzdG9tRXZlbnQgPSBDdXN0b21FdmVudDtcbn0pKCk7XG5cblxuLyoqXG4gKiAvL1hYWCBUaGlzIGlzIG5lZWRlZCBpbiBvcmRlciB0byBnZXQgZGlyZWN0IGFjY2VzcyB0byB0aGUgYEF1dG9OdW1lcmljYCBjb25zdHJ1Y3RvciB3aXRob3V0IGhhdmluZyB0byB1c2UgYG5ldyBBdXRvTnVtZXJpYy5kZWZhdWx0KClgIChjZi4gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzYzODkyNDQvMjgzNDg5OCkgOiB1c2luZyBgZXhwb3J0IHZhciBfX3VzZURlZmF1bHQgPSB0cnVlO2AgZG9lcyBub3Qgd29yayB0aG91Z2guXG4gKiAvL1hYWCBUaGUgd29ya2Fyb3VuZCAodXNpbmcgYG1vZHVsZS5leHBvcnRzID0gQXV0b051bWVyaWNgIGluc3RlYWQgb2YgYGV4cG9ydCBkZWZhdWx0IGNsYXNzIEF1dG9OdW1lcmljIHt9YCkgY29tZXMgZnJvbSBodHRwczovL2dpdGh1Yi5jb20vd2VicGFjay93ZWJwYWNrL2lzc3Vlcy83MDYjaXNzdWVjb21tZW50LTE2NzkwODU3NlxuICogLy9YWFggQW5kIHRoZSBleHBsYW5hdGlvbiB3aHkgQmFiZWwgNiBjaGFuZ2VkIHRoZSB3YXkgQmFiZWwgNSB3b3JrZWQgOiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS8zMzUwNjE2OS8yODM0ODk4XG4gKiAvL1hYWCBJZGVhbGx5LCB3ZSBzaG91bGQgYmUgYWJsZSB0byBqdXN0IGRlY2xhcmUgYGV4cG9ydCBkZWZhdWx0IGNsYXNzIEF1dG9OdW1lcmljIHt9YCBpbiB0aGUgZnV0dXJlLCBhbmQgcmVtb3ZlIHRoZSBmb2xsb3dpbmcgYG1vZHVsZS5leHBvcnRzID0gQXV0b051bWVyaWM7YCBsaW5lXG4gKlxuICogQHR5cGUge0F1dG9OdW1lcmljfVxuICovXG5tb2R1bGUuZXhwb3J0cyA9IEF1dG9OdW1lcmljO1xuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL0F1dG9OdW1lcmljLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==");

/***/ },
/* 2 */
/***/ function(module, exports) {

	eval("/*** IMPORTS FROM imports-loader ***/\n(function() {\n\n'use strict';\n\nObject.defineProperty(exports, \"__esModule\", {\n    value: true\n});\n/**\n * Enumerations for autoNumeric.js\n * @author Alexandre Bonneau <alexandre.bonneau@linuxfr.eu>\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            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: '-',\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            182: 'MyComputer',\n            183: 'MyCalculator',\n            186: ';',\n            187: '=',\n            188: ',',\n            189: '-',\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            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;\n}.call(window));//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvQXV0b051bWVyaWNFbnVtLmpzP2M1N2MiXSwibmFtZXMiOlsiQXV0b051bWVyaWNFbnVtIiwiYWxsb3dlZFRhZ0xpc3QiLCJrZXlDb2RlIiwiQmFja3NwYWNlIiwiVGFiIiwiRW50ZXIiLCJTaGlmdCIsIkN0cmwiLCJBbHQiLCJQYXVzZSIsIkNhcHNMb2NrIiwiRXNjIiwiU3BhY2UiLCJQYWdlVXAiLCJQYWdlRG93biIsIkVuZCIsIkhvbWUiLCJMZWZ0QXJyb3ciLCJVcEFycm93IiwiUmlnaHRBcnJvdyIsIkRvd25BcnJvdyIsIkluc2VydCIsIkRlbGV0ZSIsIm51bTAiLCJudW0xIiwibnVtMiIsIm51bTMiLCJudW00IiwibnVtNSIsIm51bTYiLCJudW03IiwibnVtOCIsIm51bTkiLCJhIiwiYiIsImMiLCJkIiwiZSIsImYiLCJnIiwiaCIsImkiLCJqIiwiayIsImwiLCJtIiwibiIsIm8iLCJwIiwicSIsInIiLCJzIiwidCIsInUiLCJ2IiwidyIsIngiLCJ5IiwieiIsIk9TTGVmdCIsIk9TUmlnaHQiLCJDb250ZXh0TWVudSIsIm51bXBhZDAiLCJudW1wYWQxIiwibnVtcGFkMiIsIm51bXBhZDMiLCJudW1wYWQ0IiwibnVtcGFkNSIsIm51bXBhZDYiLCJudW1wYWQ3IiwibnVtcGFkOCIsIm51bXBhZDkiLCJNdWx0aXBseU51bXBhZCIsIlBsdXNOdW1wYWQiLCJNaW51c051bXBhZCIsIkRvdE51bXBhZCIsIlNsYXNoTnVtcGFkIiwiRjEiLCJGMiIsIkYzIiwiRjQiLCJGNSIsIkY2IiwiRjciLCJGOCIsIkY5IiwiRjEwIiwiRjExIiwiRjEyIiwiTnVtTG9jayIsIlNjcm9sbExvY2siLCJNeUNvbXB1dGVyIiwiTXlDYWxjdWxhdG9yIiwiU2VtaWNvbG9uIiwiRXF1YWwiLCJDb21tYSIsIkh5cGhlbiIsIkRvdCIsIlNsYXNoIiwiQmFja3F1b3RlIiwiTGVmdEJyYWNrZXQiLCJCYWNrc2xhc2giLCJSaWdodEJyYWNrZXQiLCJRdW90ZSIsIkNvbW1hbmQiLCJBbHRHcmFwaCIsIkFuZHJvaWREZWZhdWx0IiwiZnJvbUNoYXJDb2RlS2V5Q29kZSIsImtleU5hbWUiLCJVbmlkZW50aWZpZWQiLCJBbHRHciIsIkZuIiwiRm5Mb2NrIiwiSHlwZXIiLCJNZXRhIiwiU3VwZXIiLCJTeW1ib2wiLCJTeW1ib2xMb2NrIiwiQ2xlYXIiLCJDb3B5IiwiQ3JTZWwiLCJDdXQiLCJFcmFzZUVvZiIsIkV4U2VsIiwiUGFzdGUiLCJSZWRvIiwiVW5kbyIsIkFjY2VwdCIsIkFnYWluIiwiQXR0biIsIkNhbmNlbCIsIkV4ZWN1dGUiLCJGaW5kIiwiRmluaXNoIiwiSGVscCIsIlBsYXkiLCJQcm9wcyIsIlNlbGVjdCIsIlpvb21JbiIsIlpvb21PdXQiLCJCcmlnaHRuZXNzRG93biIsIkJyaWdodG5lc3NVcCIsIkVqZWN0IiwiTG9nT2ZmIiwiUG93ZXIiLCJQb3dlck9mZiIsIlByaW50U2NyZWVuIiwiSGliZXJuYXRlIiwiU3RhbmRieSIsIldha2VVcCIsIkNvbXBvc2UiLCJEZWFkIiwiUHJpbnQiLCJBIiwiQiIsIkMiLCJEIiwiRSIsIkYiLCJHIiwiSCIsIkkiLCJKIiwiSyIsIkwiLCJNIiwiTiIsIk8iLCJQIiwiUSIsIlIiLCJTIiwiVCIsIlUiLCJWIiwiVyIsIlgiLCJZIiwiWiIsIk1pbnVzIiwiUGx1cyIsIk51bXBhZERvdCIsIk51bXBhZERvdEFsdCIsIk51bXBhZE11bHRpcGx5IiwiTnVtcGFkUGx1cyIsIk51bXBhZE1pbnVzIiwiTnVtcGFkU2xhc2giLCJOdW1wYWREb3RPYnNvbGV0ZUJyb3dzZXJzIiwiTnVtcGFkTXVsdGlwbHlPYnNvbGV0ZUJyb3dzZXJzIiwiTnVtcGFkUGx1c09ic29sZXRlQnJvd3NlcnMiLCJOdW1wYWRNaW51c09ic29sZXRlQnJvd3NlcnMiLCJOdW1wYWRTbGFzaE9ic29sZXRlQnJvd3NlcnMiLCJfYWxsRm5LZXlzIiwiX3NvbWVOb25QcmludGFibGVLZXlzIiwiX2RpcmVjdGlvbktleXMiXSwibWFwcGluZ3MiOiI7Ozs7Ozs7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QXJELEVBQWdFLGFBQWhFLEVBQStFLGNBQS9FLEVBQStGLEtBQS9GLEVBQXNHLFNBQXRHLEVBQWlILFVBQWpILEVBQTZILE9BQTdILEVBQXNJLFVBQXRJLEVBQWtKLFFBQWxKLENBOU1wQjtBQStNSEMsNEJBQXVCLENBQUMsUUFBRCxFQUFXLFVBQVgsRUFBdUIsS0FBdkIsRUFBOEIsTUFBOUIsRUFBc0MsV0FBdEMsRUFBbUQsV0FBbkQsRUFBZ0UsWUFBaEUsRUFBOEUsU0FBOUU7QUEvTXBCLFNBQVA7QUFpTkg7QUE5ZW1CLENBQXhCOztrQkFpZmVsTSxlIiwiZmlsZSI6IjIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEVudW1lcmF0aW9ucyBmb3IgYXV0b051bWVyaWMuanNcbiAqIEBhdXRob3IgQWxleGFuZHJlIEJvbm5lYXUgPGFsZXhhbmRyZS5ib25uZWF1QGxpbnV4ZnIuZXU+XG4gKiBAY29weXJpZ2h0IMKpIDIwMTYgQWxleGFuZHJlIEJvbm5lYXVcbiAqXG4gKiBUaGUgTUlUIExpY2Vuc2UgKGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvbWl0LWxpY2Vuc2UucGhwKVxuICpcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uXG4gKiBvYnRhaW5pbmcgYSBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvblxuICogZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0XG4gKiByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSxcbiAqIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YiBsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlXG4gKiBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZ1xuICogY29uZGl0aW9uczpcbiAqXG4gKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZVxuICogaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gKlxuICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCxcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFU1xuICogT0YgTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkRcbiAqIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUXG4gKiBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSxcbiAqIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lOR1xuICogRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUlxuICogT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuICovXG5cbi8qKlxuICogT2JqZWN0IHRoYXQgc3RvcmUgdGhlIGhlbHBlciBlbnVtZXJhdGlvbnNcbiAqIEB0eXBlIHt7IGFsbG93ZWRUYWdMaXN0OiBbc3RyaW5nXSwga2V5Q29kZToge30sIGZyb21DaGFyQ29kZUtleUNvZGU6IFtzdHJpbmddLCBrZXlOYW1lOiB7fSB9fVxuICovXG5jb25zdCBBdXRvTnVtZXJpY0VudW0gPSB7XG4gICAgLyoqXG4gICAgICogTGlzdCBvZiBhbGxvd2VkIHRhZyBvbiB3aGljaCBhdXRvTnVtZXJpYyBjYW4gYmUgdXNlZC5cbiAgICAgKi9cbiAgICBnZXQgYWxsb3dlZFRhZ0xpc3QoKSB7XG4gICAgICAgIHJldHVybiBbXG4gICAgICAgICAgICAnYicsXG4gICAgICAgICAgICAnY2FwdGlvbicsXG4gICAgICAgICAgICAnY2l0ZScsXG4gICAgICAgICAgICAnY29kZScsXG4gICAgICAgICAgICAnY29uc3QnLFxuICAgICAgICAgICAgJ2RkJyxcbiAgICAgICAgICAgICdkZWwnLFxuICAgICAgICAgICAgJ2RpdicsXG4gICAgICAgICAgICAnZGZuJyxcbiAgICAgICAgICAgICdkdCcsXG4gICAgICAgICAgICAnZW0nLFxuICAgICAgICAgICAgJ2gxJyxcbiAgICAgICAgICAgICdoMicsXG4gICAgICAgICAgICAnaDMnLFxuICAgICAgICAgICAgJ2g0JyxcbiAgICAgICAgICAgICdoNScsXG4gICAgICAgICAgICAnaDYnLFxuICAgICAgICAgICAgJ2lucHV0JyxcbiAgICAgICAgICAgICdpbnMnLFxuICAgICAgICAgICAgJ2tkYicsXG4gICAgICAgICAgICAnbGFiZWwnLFxuICAgICAgICAgICAgJ2xpJyxcbiAgICAgICAgICAgICdvcHRpb24nLFxuICAgICAgICAgICAgJ291dHB1dCcsXG4gICAgICAgICAgICAncCcsXG4gICAgICAgICAgICAncScsXG4gICAgICAgICAgICAncycsXG4gICAgICAgICAgICAnc2FtcGxlJyxcbiAgICAgICAgICAgICdzcGFuJyxcbiAgICAgICAgICAgICdzdHJvbmcnLFxuICAgICAgICAgICAgJ3RkJyxcbiAgICAgICAgICAgICd0aCcsXG4gICAgICAgICAgICAndScsXG4gICAgICAgIF07XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFdyYXBwZXIgdmFyaWFibGUgdGhhdCBob2xkIG5hbWVkIGtleWJvYXJkIGtleXMgd2l0aCB0aGVpciByZXNwZWN0aXZlIGtleUNvZGUgYXMgc2VlbiBpbiBET00gZXZlbnRzLlxuICAgICAqIGNmLiBodHRwczovL2RldmVsb3Blci5tb3ppbGxhLm9yZy9lbi1VUy9kb2NzL1dlYi9BUEkvS2V5Ym9hcmRFdmVudC9rZXlDb2RlXG4gICAgICpcbiAgICAgKiBUaGlzIGRlcHJlY2F0ZWQgaW5mb3JtYXRpb24gaXMgdXNlZCBmb3Igb2Jzb2xldGUgYnJvd3NlcnMuXG4gICAgICogQGRlcHJlY2F0ZWRcbiAgICAgKi9cbiAgICBnZXQga2V5Q29kZSgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIEJhY2tzcGFjZSAgICAgOiA4LFxuICAgICAgICAgICAgVGFiICAgICAgICAgICA6IDksXG4gICAgICAgICAgICAvLyBObyAxMCwgMTFcbiAgICAgICAgICAgIC8vIDEyID09PSBOdW1wYWRFcXVhbCBvbiBXaW5kb3dzXG4gICAgICAgICAgICAvLyAxMiA9PT0gTnVtTG9jayBvbiBNYWNcbiAgICAgICAgICAgIEVudGVyICAgICAgICAgOiAxMyxcbiAgICAgICAgICAgIC8vIDE0IHJlc2VydmVkLCBidXQgbm90IHVzZWRcbiAgICAgICAgICAgIC8vIDE1IGRvZXMgbm90IGV4aXN0c1xuICAgICAgICAgICAgU2hpZnQgICAgICAgICA6IDE2LFxuICAgICAgICAgICAgQ3RybCAgICAgICAgICA6IDE3LFxuICAgICAgICAgICAgQWx0ICAgICAgICAgICA6IDE4LFxuICAgICAgICAgICAgUGF1c2UgICAgICAgICA6IDE5LFxuICAgICAgICAgICAgQ2Fwc0xvY2sgICAgICA6IDIwLFxuICAgICAgICAgICAgLy8gMjEsIDIyLCAyMywgMjQsIDI1IDogQXNpYXRpYyBrZXkgY29kZXNcbiAgICAgICAgICAgIC8vIDI2IGRvZXMgbm90IGV4aXN0c1xuICAgICAgICAgICAgRXNjICAgICAgICAgICA6IDI3LFxuICAgICAgICAgICAgLy8gMjgsIDI5LCAzMCwgMzEgOiBDb252ZXJ0LCBOb25Db252ZXJ0LCBBY2NlcHQgYW5kIE1vZGVDaGFuZ2Uga2V5c1xuICAgICAgICAgICAgU3BhY2UgICAgICAgICA6IDMyLFxuICAgICAgICAgICAgUGFnZVVwICAgICAgICA6IDMzLFxuICAgICAgICAgICAgUGFnZURvd24gICAgICA6IDM0LFxuICAgICAgICAgICAgRW5kICAgICAgICAgICA6IDM1LFxuICAgICAgICAgICAgSG9tZSAgICAgICAgICA6IDM2LFxuICAgICAgICAgICAgTGVmdEFycm93ICAgICA6IDM3LFxuICAgICAgICAgICAgVXBBcnJvdyAgICAgICA6IDM4LFxuICAgICAgICAgICAgUmlnaHRBcnJvdyAgICA6IDM5LFxuICAgICAgICAgICAgRG93bkFycm93ICAgICA6IDQwLFxuICAgICAgICAgICAgSW5zZXJ0ICAgICAgICA6IDQ1LFxuICAgICAgICAgICAgRGVsZXRlICAgICAgICA6IDQ2LFxuICAgICAgICAgICAgbnVtMCAgICAgICAgICA6IDQ4LFxuICAgICAgICAgICAgbnVtMSAgICAgICAgICA6IDQ5LFxuICAgICAgICAgICAgbnVtMiAgICAgICAgICA6IDUwLFxuICAgICAgICAgICAgbnVtMyAgICAgICAgICA6IDUxLFxuICAgICAgICAgICAgbnVtNCAgICAgICAgICA6IDUyLFxuICAgICAgICAgICAgbnVtNSAgICAgICAgICA6IDUzLFxuICAgICAgICAgICAgbnVtNiAgICAgICAgICA6IDU0LFxuICAgICAgICAgICAgbnVtNyAgICAgICAgICA6IDU1LFxuICAgICAgICAgICAgbnVtOCAgICAgICAgICA6IDU2LFxuICAgICAgICAgICAgbnVtOSAgICAgICAgICA6IDU3LFxuICAgICAgICAgICAgYSAgICAgICAgICAgICA6IDY1LFxuICAgICAgICAgICAgYiAgICAgICAgICAgICA6IDY2LFxuICAgICAgICAgICAgYyAgICAgICAgICAgICA6IDY3LFxuICAgICAgICAgICAgZCAgICAgICAgICAgICA6IDY4LFxuICAgICAgICAgICAgZSAgICAgICAgICAgICA6IDY5LFxuICAgICAgICAgICAgZiAgICAgICAgICAgICA6IDcwLFxuICAgICAgICAgICAgZyAgICAgICAgICAgICA6IDcxLFxuICAgICAgICAgICAgaCAgICAgICAgICAgICA6IDcyLFxuICAgICAgICAgICAgaSAgICAgICAgICAgICA6IDczLFxuICAgICAgICAgICAgaiAgICAgICAgICAgICA6IDc0LFxuICAgICAgICAgICAgayAgICAgICAgICAgICA6IDc1LFxuICAgICAgICAgICAgbCAgICAgICAgICAgICA6IDc2LFxuICAgICAgICAgICAgbSAgICAgICAgICAgICA6IDc3LFxuICAgICAgICAgICAgbiAgICAgICAgICAgICA6IDc4LFxuICAgICAgICAgICAgbyAgICAgICAgICAgICA6IDc5LFxuICAgICAgICAgICAgcCAgICAgICAgICAgICA6IDgwLFxuICAgICAgICAgICAgcSAgICAgICAgICAgICA6IDgxLFxuICAgICAgICAgICAgciAgICAgICAgICAgICA6IDgyLFxuICAgICAgICAgICAgcyAgICAgICAgICAgICA6IDgzLFxuICAgICAgICAgICAgdCAgICAgICAgICAgICA6IDg0LFxuICAgICAgICAgICAgdSAgICAgICAgICAgICA6IDg1LFxuICAgICAgICAgICAgdiAgICAgICAgICAgICA6IDg2LFxuICAgICAgICAgICAgdyAgICAgICAgICAgICA6IDg3LFxuICAgICAgICAgICAgeCAgICAgICAgICAgICA6IDg4LFxuICAgICAgICAgICAgeSAgICAgICAgICAgICA6IDg5LFxuICAgICAgICAgICAgeiAgICAgICAgICAgICA6IDkwLFxuICAgICAgICAgICAgT1NMZWZ0ICAgICAgICA6IDkxLFxuICAgICAgICAgICAgT1NSaWdodCAgICAgICA6IDkyLFxuICAgICAgICAgICAgQ29udGV4dE1lbnUgICA6IDkzLFxuICAgICAgICAgICAgbnVtcGFkMCAgICAgICA6IDk2LFxuICAgICAgICAgICAgbnVtcGFkMSAgICAgICA6IDk3LFxuICAgICAgICAgICAgbnVtcGFkMiAgICAgICA6IDk4LFxuICAgICAgICAgICAgbnVtcGFkMyAgICAgICA6IDk5LFxuICAgICAgICAgICAgbnVtcGFkNCAgICAgICA6IDEwMCxcbiAgICAgICAgICAgIG51bXBhZDUgICAgICAgOiAxMDEsXG4gICAgICAgICAgICBudW1wYWQ2ICAgICAgIDogMTAyLFxuICAgICAgICAgICAgbnVtcGFkNyAgICAgICA6IDEwMyxcbiAgICAgICAgICAgIG51bXBhZDggICAgICAgOiAxMDQsXG4gICAgICAgICAgICBudW1wYWQ5ICAgICAgIDogMTA1LFxuICAgICAgICAgICAgTXVsdGlwbHlOdW1wYWQ6IDEwNixcbiAgICAgICAgICAgIFBsdXNOdW1wYWQgICAgOiAxMDcsXG4gICAgICAgICAgICBNaW51c051bXBhZCAgIDogMTA5LFxuICAgICAgICAgICAgRG90TnVtcGFkICAgICA6IDExMCxcbiAgICAgICAgICAgIFNsYXNoTnVtcGFkICAgOiAxMTEsXG4gICAgICAgICAgICBGMSAgICAgICAgICAgIDogMTEyLFxuICAgICAgICAgICAgRjIgICAgICAgICAgICA6IDExMyxcbiAgICAgICAgICAgIEYzICAgICAgICAgICAgOiAxMTQsXG4gICAgICAgICAgICBGNCAgICAgICAgICAgIDogMTE1LFxuICAgICAgICAgICAgRjUgICAgICAgICAgICA6IDExNixcbiAgICAgICAgICAgIEY2ICAgICAgICAgICAgOiAxMTcsXG4gICAgICAgICAgICBGNyAgICAgICAgICAgIDogMTE4LFxuICAgICAgICAgICAgRjggICAgICAgICAgICA6IDExOSxcbiAgICAgICAgICAgIEY5ICAgICAgICAgICAgOiAxMjAsXG4gICAgICAgICAgICBGMTAgICAgICAgICAgIDogMTIxLFxuICAgICAgICAgICAgRjExICAgICAgICAgICA6IDEyMixcbiAgICAgICAgICAgIEYxMiAgICAgICAgICAgOiAxMjMsXG4gICAgICAgICAgICBOdW1Mb2NrICAgICAgIDogMTQ0LFxuICAgICAgICAgICAgU2Nyb2xsTG9jayAgICA6IDE0NSxcbiAgICAgICAgICAgIE15Q29tcHV0ZXIgICAgOiAxODIsXG4gICAgICAgICAgICBNeUNhbGN1bGF0b3IgIDogMTgzLFxuICAgICAgICAgICAgU2VtaWNvbG9uICAgICA6IDE4NixcbiAgICAgICAgICAgIEVxdWFsICAgICAgICAgOiAxODcsXG4gICAgICAgICAgICBDb21tYSAgICAgICAgIDogMTg4LFxuICAgICAgICAgICAgSHlwaGVuICAgICAgICA6IDE4OSxcbiAgICAgICAgICAgIERvdCAgICAgICAgICAgOiAxOTAsXG4gICAgICAgICAgICBTbGFzaCAgICAgICAgIDogMTkxLFxuICAgICAgICAgICAgQmFja3F1b3RlICAgICA6IDE5MixcbiAgICAgICAgICAgIExlZnRCcmFja2V0ICAgOiAyMTksXG4gICAgICAgICAgICBCYWNrc2xhc2ggICAgIDogMjIwLFxuICAgICAgICAgICAgUmlnaHRCcmFja2V0ICA6IDIyMSxcbiAgICAgICAgICAgIFF1b3RlICAgICAgICAgOiAyMjIsXG4gICAgICAgICAgICBDb21tYW5kICAgICAgIDogMjI0LFxuICAgICAgICAgICAgQWx0R3JhcGggICAgICA6IDIyNSxcbiAgICAgICAgICAgIEFuZHJvaWREZWZhdWx0OiAyMjksIC8vIEFuZHJvaWQgQ2hyb21lIHJldHVybnMgdGhlIHNhbWUga2V5Y29kZSBudW1iZXIgMjI5IGZvciBhbGwga2V5cyBwcmVzc2VkXG4gICAgICAgIH07XG4gICAgfSxcblxuICAgIC8qKlxuICAgICAqIFRoaXMgb2JqZWN0IGlzIHRoZSByZXZlcnNlIG9mIGBrZXlDb2RlYCwgYW5kIGlzIHVzZWQgdG8gdHJhbnNsYXRlIHRoZSBrZXkgY29kZSB0byBuYW1lZCBrZXlzIHdoZW4gbm8gdmFsaWQgY2hhcmFjdGVycyBjYW4gYmUgb2J0YWluZWQgYnkgYFN0cmluZy5mcm9tQ2hhckNvZGVgLlxuICAgICAqIFRoaXMgb2JqZWN0IGtleXMgY29ycmVzcG9uZCB0byB0aGUgYGV2ZW50LmtleUNvZGVgIG51bWJlciwgYW5kIHJldHVybnMgdGhlIGNvcnJlc3BvbmRpbmcga2V5IG5hbWUgKMOgIGxhIGV2ZW50LmtleSlcbiAgICAgKi9cbiAgICBnZXQgZnJvbUNoYXJDb2RlS2V5Q29kZSgpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgIDAgIDogJ0xhdW5jaENhbGN1bGF0b3InLFxuICAgICAgICAgICAgOCAgOiAnQmFja3NwYWNlJyxcbiAgICAgICAgICAgIDkgIDogJ1RhYicsXG4gICAgICAgICAgICAxMyA6ICdFbnRlcicsXG4gICAgICAgICAgICAxNiA6ICdTaGlmdCcsXG4gICAgICAgICAgICAxNyA6ICdDdHJsJyxcbiAgICAgICAgICAgIDE4IDogJ0FsdCcsXG4gICAgICAgICAgICAxOSA6ICdQYXVzZScsXG4gICAgICAgICAgICAyMCA6ICdDYXBzTG9jaycsXG4gICAgICAgICAgICAyNyA6ICdFc2NhcGUnLFxuICAgICAgICAgICAgMzIgOiAnICcsXG4gICAgICAgICAgICAzMyA6ICdQYWdlVXAnLFxuICAgICAgICAgICAgMzQgOiAnUGFnZURvd24nLFxuICAgICAgICAgICAgMzUgOiAnRW5kJyxcbiAgICAgICAgICAgIDM2IDogJ0hvbWUnLFxuICAgICAgICAgICAgMzcgOiAnQXJyb3dMZWZ0JyxcbiAgICAgICAgICAgIDM4IDogJ0Fycm93VXAnLFxuICAgICAgICAgICAgMzkgOiAnQXJyb3dSaWdodCcsXG4gICAgICAgICAgICA0MCA6ICdBcnJvd0Rvd24nLFxuICAgICAgICAgICAgNDUgOiAnSW5zZXJ0JyxcbiAgICAgICAgICAgIDQ2IDogJ0RlbGV0ZScsXG4gICAgICAgICAgICA0OCA6ICcwJyxcbiAgICAgICAgICAgIDQ5IDogJzEnLFxuICAgICAgICAgICAgNTAgOiAnMicsXG4gICAgICAgICAgICA1MSA6ICczJyxcbiAgICAgICAgICAgIDUyIDogJzQnLFxuICAgICAgICAgICAgNTMgOiAnNScsXG4gICAgICAgICAgICA1NCA6ICc2JyxcbiAgICAgICAgICAgIDU1IDogJzcnLFxuICAgICAgICAgICAgNTYgOiAnOCcsXG4gICAgICAgICAgICA1NyA6ICc5JyxcbiAgICAgICAgICAgIC8vIDY1OiAnYScsXG4gICAgICAgICAgICAvLyA2NjogJ2InLFxuICAgICAgICAgICAgLy8gNjc6ICdjJyxcbiAgICAgICAgICAgIC8vIDY4OiAnZCcsXG4gICAgICAgICAgICAvLyA2OTogJ2UnLFxuICAgICAgICAgICAgLy8gNzA6ICdmJyxcbiAgICAgICAgICAgIC8vIDcxOiAnZycsXG4gICAgICAgICAgICAvLyA3MjogJ2gnLFxuICAgICAgICAgICAgLy8gNzM6ICdpJyxcbiAgICAgICAgICAgIC8vIDc0OiAnaicsXG4gICAgICAgICAgICAvLyA3NTogJ2snLFxuICAgICAgICAgICAgLy8gNzY6ICdsJyxcbiAgICAgICAgICAgIC8vIDc3OiAnbScsXG4gICAgICAgICAgICAvLyA3ODogJ24nLFxuICAgICAgICAgICAgLy8gNzk6ICdvJyxcbiAgICAgICAgICAgIC8vIDgwOiAncCcsXG4gICAgICAgICAgICAvLyA4MTogJ3EnLFxuICAgICAgICAgICAgLy8gODI6ICdyJyxcbiAgICAgICAgICAgIC8vIDgzOiAncycsXG4gICAgICAgICAgICAvLyA4NDogJ3QnLFxuICAgICAgICAgICAgLy8gODU6ICd1JyxcbiAgICAgICAgICAgIC8vIDg2OiAndicsXG4gICAgICAgICAgICAvLyA4NzogJ3cnLFxuICAgICAgICAgICAgLy8gODg6ICd4JyxcbiAgICAgICAgICAgIC8vIDg5OiAneScsXG4gICAgICAgICAgICAvLyA5MDogJ3onLFxuICAgICAgICAgICAgOTEgOiAnT1MnLCAvLyBOb3RlOiBGaXJlZm94IGFuZCBDaHJvbWUgcmVwb3J0cyAnT1MnIGluc3RlYWQgb2YgJ09TTGVmdCdcbiAgICAgICAgICAgIDkyIDogJ09TUmlnaHQnLFxuICAgICAgICAgICAgOTMgOiAnQ29udGV4dE1lbnUnLFxuICAgICAgICAgICAgOTYgOiAnMCcsXG4gICAgICAgICAgICA5NyA6ICcxJyxcbiAgICAgICAgICAgIDk4IDogJzInLFxuICAgICAgICAgICAgOTkgOiAnMycsXG4gICAgICAgICAgICAxMDA6ICc0JyxcbiAgICAgICAgICAgIDEwMTogJzUnLFxuICAgICAgICAgICAgMTAyOiAnNicsXG4gICAgICAgICAgICAxMDM6ICc3JyxcbiAgICAgICAgICAgIDEwNDogJzgnLFxuICAgICAgICAgICAgMTA1OiAnOScsXG4gICAgICAgICAgICAxMDY6ICcqJyxcbiAgICAgICAgICAgIDEwNzogJysnLFxuICAgICAgICAgICAgMTA5OiAnLScsXG4gICAgICAgICAgICAxMTA6ICcuJyxcbiAgICAgICAgICAgIDExMTogJy8nLFxuICAgICAgICAgICAgMTEyOiAnRjEnLFxuICAgICAgICAgICAgMTEzOiAnRjInLFxuICAgICAgICAgICAgMTE0OiAnRjMnLFxuICAgICAgICAgICAgMTE1OiAnRjQnLFxuICAgICAgICAgICAgMTE2OiAnRjUnLFxuICAgICAgICAgICAgMTE3OiAnRjYnLFxuICAgICAgICAgICAgMTE4OiAnRjcnLFxuICAgICAgICAgICAgMTE5OiAnRjgnLFxuICAgICAgICAgICAgMTIwOiAnRjknLFxuICAgICAgICAgICAgMTIxOiAnRjEwJyxcbiAgICAgICAgICAgIDEyMjogJ0YxMScsXG4gICAgICAgICAgICAxMjM6ICdGMTInLFxuICAgICAgICAgICAgMTQ0OiAnTnVtTG9jaycsXG4gICAgICAgICAgICAxNDU6ICdTY3JvbGxMb2NrJyxcbiAgICAgICAgICAgIDE4MjogJ015Q29tcHV0ZXInLFxuICAgICAgICAgICAgMTgzOiAnTXlDYWxjdWxhdG9yJyxcbiAgICAgICAgICAgIDE4NjogJzsnLFxuICAgICAgICAgICAgMTg3OiAnPScsXG4gICAgICAgICAgICAxODg6ICcsJyxcbiAgICAgICAgICAgIDE4OTogJy0nLFxuICAgICAgICAgICAgMTkwOiAnLicsXG4gICAgICAgICAgICAxOTE6ICcvJyxcbiAgICAgICAgICAgIDE5MjogJ2AnLFxuICAgICAgICAgICAgMjE5OiAnWycsXG4gICAgICAgICAgICAyMjA6ICdcXFxcJyxcbiAgICAgICAgICAgIDIyMTogJ10nLFxuICAgICAgICAgICAgMjIyOiAnXFwnJyxcbiAgICAgICAgICAgIDIyNDogJ01ldGEnLFxuICAgICAgICAgICAgMjI1OiAnQWx0R3JhcGgnLFxuICAgICAgICB9O1xuICAgIH0sXG5cbiAgICAvKipcbiAgICAgKiBXcmFwcGVyIHZhcmlhYmxlIHRoYXQgaG9sZCBuYW1lZCBrZXlib2FyZCBrZXlzIHdpdGggdGhlaXIgcmVzcGVjdGl2ZSBrZXkgbmFtZSAoYXMgc2V0IGluIEtleWJvYXJkRXZlbnQua2V5KS5cbiAgICAgKiBUaG9zZSBuYW1lcyBhcmUgbGlzdGVkIGhlcmUgOlxuICAgICAqIEBsaW5rIGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9LZXlib2FyZEV2ZW50L2tleS9LZXlfVmFsdWVzXG4gICAgICovXG4gICAgZ2V0IGtleU5hbWUoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAvLyBTcGVjaWFsIHZhbHVlc1xuICAgICAgICAgICAgVW5pZGVudGlmaWVkICA6ICdVbmlkZW50aWZpZWQnLFxuICAgICAgICAgICAgQW5kcm9pZERlZmF1bHQ6ICdBbmRyb2lkRGVmYXVsdCcsXG5cbiAgICAgICAgICAgIC8vIE1vZGlmaWVyIGtleXNcbiAgICAgICAgICAgIEFsdCAgICAgICA6ICdBbHQnLFxuICAgICAgICAgICAgQWx0R3IgICAgIDogJ0FsdEdyYXBoJyxcbiAgICAgICAgICAgIENhcHNMb2NrICA6ICdDYXBzTG9jaycsIC8vIFVuZGVyIENocm9tZSwgZS5rZXkgaXMgZW1wdHkgZm9yIENhcHNMb2NrXG4gICAgICAgICAgICBDdHJsICAgICAgOiAnQ29udHJvbCcsXG4gICAgICAgICAgICBGbiAgICAgICAgOiAnRm4nLFxuICAgICAgICAgICAgRm5Mb2NrICAgIDogJ0ZuTG9jaycsXG4gICAgICAgICAgICBIeXBlciAgICAgOiAnSHlwZXInLCAvLyAnT1MnIHVuZGVyIEZpcmVmb3hcbiAgICAgICAgICAgIE1ldGEgICAgICA6ICdNZXRhJyxcbiAgICAgICAgICAgIE9TTGVmdCAgICA6ICdPUycsXG4gICAgICAgICAgICBPU1JpZ2h0ICAgOiAnT1MnLFxuICAgICAgICAgICAgQ29tbWFuZCAgIDogJ09TJyxcbiAgICAgICAgICAgIE51bUxvY2sgICA6ICdOdW1Mb2NrJyxcbiAgICAgICAgICAgIFNjcm9sbExvY2s6ICdTY3JvbGxMb2NrJyxcbiAgICAgICAgICAgIFNoaWZ0ICAgICA6ICdTaGlmdCcsXG4gICAgICAgICAgICBTdXBlciAgICAgOiAnU3VwZXInLCAvLyAnT1MnIHVuZGVyIEZpcmVmb3hcbiAgICAgICAgICAgIFN5bWJvbCAgICA6ICdTeW1ib2wnLFxuICAgICAgICAgICAgU3ltYm9sTG9jazogJ1N5bWJvbExvY2snLFxuXG4gICAgICAgICAgICAvLyBXaGl0ZXNwYWNlIGtleXNcbiAgICAgICAgICAgIEVudGVyOiAnRW50ZXInLFxuICAgICAgICAgICAgVGFiICA6ICdUYWInLFxuICAgICAgICAgICAgU3BhY2U6ICcgJywgLy8gJ1NwYWNlYmFyJyBmb3IgRmlyZWZveCA8MzcsIGFuZCBJRTlcblxuICAgICAgICAgICAgLy8gTmF2aWdhdGlvbiBrZXlzXG4gICAgICAgICAgICBMZWZ0QXJyb3cgOiAnQXJyb3dMZWZ0JywgLy8gJ0xlZnQnIGZvciBGaXJlZm94IDw9MzYsIGFuZCBJRTlcbiAgICAgICAgICAgIFVwQXJyb3cgICA6ICdBcnJvd1VwJywgLy8gJ1VwJyBmb3IgRmlyZWZveCA8PTM2LCBhbmQgSUU5XG4gICAgICAgICAgICBSaWdodEFycm93OiAnQXJyb3dSaWdodCcsIC8vICdSaWdodCcgZm9yIEZpcmVmb3ggPD0zNiwgYW5kIElFOVxuICAgICAgICAgICAgRG93bkFycm93IDogJ0Fycm93RG93bicsIC8vICdEb3duJyBmb3IgRmlyZWZveCA8PTM2LCBhbmQgSUU5XG4gICAgICAgICAgICBFbmQgICAgICAgOiAnRW5kJyxcbiAgICAgICAgICAgIEhvbWUgICAgICA6ICdIb21lJyxcbiAgICAgICAgICAgIFBhZ2VVcCAgICA6ICdQYWdlVXAnLFxuICAgICAgICAgICAgUGFnZURvd24gIDogJ1BhZ2VEb3duJyxcblxuICAgICAgICAgICAgLy8gRWRpdGluZyBrZXlzXG4gICAgICAgICAgICBCYWNrc3BhY2U6ICdCYWNrc3BhY2UnLFxuICAgICAgICAgICAgQ2xlYXIgICAgOiAnQ2xlYXInLFxuICAgICAgICAgICAgQ29weSAgICAgOiAnQ29weScsXG4gICAgICAgICAgICBDclNlbCAgICA6ICdDclNlbCcsIC8vICdDcnNlbCcgZm9yIEZpcmVmb3ggPD0zNiwgYW5kIElFOVxuICAgICAgICAgICAgQ3V0ICAgICAgOiAnQ3V0JyxcbiAgICAgICAgICAgIERlbGV0ZSAgIDogJ0RlbGV0ZScsIC8vICdEZWwnIGZvciBGaXJlZm94IDw9MzYsIGFuZCBJRTlcbiAgICAgICAgICAgIEVyYXNlRW9mIDogJ0VyYXNlRW9mJyxcbiAgICAgICAgICAgIEV4U2VsICAgIDogJ0V4U2VsJywgLy8gJ0V4c2VsJyBmb3IgRmlyZWZveCA8PTM2LCBhbmQgSUU5XG4gICAgICAgICAgICBJbnNlcnQgICA6ICdJbnNlcnQnLFxuICAgICAgICAgICAgUGFzdGUgICAgOiAnUGFzdGUnLFxuICAgICAgICAgICAgUmVkbyAgICAgOiAnUmVkbycsXG4gICAgICAgICAgICBVbmRvICAgICA6ICdVbmRvJyxcblxuICAgICAgICAgICAgLy8gVUkga2V5c1xuICAgICAgICAgICAgQWNjZXB0ICAgICA6ICdBY2NlcHQnLFxuICAgICAgICAgICAgQWdhaW4gICAgICA6ICdBZ2FpbicsXG4gICAgICAgICAgICBBdHRuICAgICAgIDogJ0F0dG4nLCAvLyAnVW5pZGVudGlmaWVkJyBmb3IgRmlyZWZveCwgQ2hyb21lLCBhbmQgSUU5ICgnS2FuYU1vZGUnIHdoZW4gdXNpbmcgdGhlIEphcGFuZXNlIGtleWJvYXJkIGxheW91dClcbiAgICAgICAgICAgIENhbmNlbCAgICAgOiAnQ2FuY2VsJyxcbiAgICAgICAgICAgIENvbnRleHRNZW51OiAnQ29udGV4dE1lbnUnLCAvLyAnQXBwcycgZm9yIEZpcmVmb3ggPD0zNiwgYW5kIElFOVxuICAgICAgICAgICAgRXNjICAgICAgICA6ICdFc2NhcGUnLCAvLyAnRXNjJyBmb3IgRmlyZWZveCA8PTM2LCBhbmQgSUU5XG4gICAgICAgICAgICBFeGVjdXRlICAgIDogJ0V4ZWN1dGUnLFxuICAgICAgICAgICAgRmluZCAgICAgICA6ICdGaW5kJyxcbiAgICAgICAgICAgIEZpbmlzaCAgICAgOiAnRmluaXNoJywgLy8gJ1VuaWRlbnRpZmllZCcgZm9yIEZpcmVmb3gsIENocm9tZSwgYW5kIElFOSAoJ0thdGFrYW5hJyB3aGVuIHVzaW5nIHRoZSBKYXBhbmVzZSBrZXlib2FyZCBsYXlvdXQpXG4gICAgICAgICAgICBIZWxwICAgICAgIDogJ0hlbHAnLFxuICAgICAgICAgICAgUGF1c2UgICAgICA6ICdQYXVzZScsXG4gICAgICAgICAgICBQbGF5ICAgICAgIDogJ1BsYXknLFxuICAgICAgICAgICAgUHJvcHMgICAgICA6ICdQcm9wcycsXG4gICAgICAgICAgICBTZWxlY3QgICAgIDogJ1NlbGVjdCcsXG4gICAgICAgICAgICBab29tSW4gICAgIDogJ1pvb21JbicsXG4gICAgICAgICAgICBab29tT3V0ICAgIDogJ1pvb21PdXQnLFxuXG4gICAgICAgICAgICAvLyBEZXZpY2Uga2V5c1xuICAgICAgICAgICAgQnJpZ2h0bmVzc0Rvd246ICdCcmlnaHRuZXNzRG93bicsXG4gICAgICAgICAgICBCcmlnaHRuZXNzVXAgIDogJ0JyaWdodG5lc3NVcCcsXG4gICAgICAgICAgICBFamVjdCAgICAgICAgIDogJ0VqZWN0JyxcbiAgICAgICAgICAgIExvZ09mZiAgICAgICAgOiAnTG9nT2ZmJyxcbiAgICAgICAgICAgIFBvd2VyICAgICAgICAgOiAnUG93ZXInLFxuICAgICAgICAgICAgUG93ZXJPZmYgICAgICA6ICdQb3dlck9mZicsXG4gICAgICAgICAgICBQcmludFNjcmVlbiAgIDogJ1ByaW50U2NyZWVuJyxcbiAgICAgICAgICAgIEhpYmVybmF0ZSAgICAgOiAnSGliZXJuYXRlJywgLy8gJ1VuaWRlbnRpZmllZCcgZm9yIEZpcmVmb3ggPD0zN1xuICAgICAgICAgICAgU3RhbmRieSAgICAgICA6ICdTdGFuZGJ5JywgLy8gJ1VuaWRlbnRpZmllZCcgZm9yIEZpcmVmb3ggPD0zNiwgYW5kIElFOVxuICAgICAgICAgICAgV2FrZVVwICAgICAgICA6ICdXYWtlVXAnLFxuXG4gICAgICAgICAgICAvLyBJTUUgYW5kIGNvbXBvc2l0aW9uIGtleXNcbiAgICAgICAgICAgIENvbXBvc2U6ICdDb21wb3NlJyxcbiAgICAgICAgICAgIERlYWQgICA6ICdEZWFkJyxcblxuICAgICAgICAgICAgLy8gRnVuY3Rpb24ga2V5c1xuICAgICAgICAgICAgRjEgOiAnRjEnLFxuICAgICAgICAgICAgRjIgOiAnRjInLFxuICAgICAgICAgICAgRjMgOiAnRjMnLFxuICAgICAgICAgICAgRjQgOiAnRjQnLFxuICAgICAgICAgICAgRjUgOiAnRjUnLFxuICAgICAgICAgICAgRjYgOiAnRjYnLFxuICAgICAgICAgICAgRjcgOiAnRjcnLFxuICAgICAgICAgICAgRjggOiAnRjgnLFxuICAgICAgICAgICAgRjkgOiAnRjknLFxuICAgICAgICAgICAgRjEwOiAnRjEwJyxcbiAgICAgICAgICAgIEYxMTogJ0YxMScsXG4gICAgICAgICAgICBGMTI6ICdGMTInLFxuXG4gICAgICAgICAgICAvLyBEb2N1bWVudCBrZXlzXG4gICAgICAgICAgICBQcmludDogJ1ByaW50JyxcblxuICAgICAgICAgICAgLy8gJ05vcm1hbCcga2V5c1xuICAgICAgICAgICAgbnVtMCAgICAgICAgOiAnMCcsXG4gICAgICAgICAgICBudW0xICAgICAgICA6ICcxJyxcbiAgICAgICAgICAgIG51bTIgICAgICAgIDogJzInLFxuICAgICAgICAgICAgbnVtMyAgICAgICAgOiAnMycsXG4gICAgICAgICAgICBudW00ICAgICAgICA6ICc0JyxcbiAgICAgICAgICAgIG51bTUgICAgICAgIDogJzUnLFxuICAgICAgICAgICAgbnVtNiAgICAgICAgOiAnNicsXG4gICAgICAgICAgICBudW03ICAgICAgICA6ICc3JyxcbiAgICAgICAgICAgIG51bTggICAgICAgIDogJzgnLFxuICAgICAgICAgICAgbnVtOSAgICAgICAgOiAnOScsXG4gICAgICAgICAgICBhICAgICAgICAgICA6ICdhJyxcbiAgICAgICAgICAgIGIgICAgICAgICAgIDogJ2InLFxuICAgICAgICAgICAgYyAgICAgICAgICAgOiAnYycsXG4gICAgICAgICAgICBkICAgICAgICAgICA6ICdkJyxcbiAgICAgICAgICAgIGUgICAgICAgICAgIDogJ2UnLFxuICAgICAgICAgICAgZiAgICAgICAgICAgOiAnZicsXG4gICAgICAgICAgICBnICAgICAgICAgICA6ICdnJyxcbiAgICAgICAgICAgIGggICAgICAgICAgIDogJ2gnLFxuICAgICAgICAgICAgaSAgICAgICAgICAgOiAnaScsXG4gICAgICAgICAgICBqICAgICAgICAgICA6ICdqJyxcbiAgICAgICAgICAgIGsgICAgICAgICAgIDogJ2snLFxuICAgICAgICAgICAgbCAgICAgICAgICAgOiAnbCcsXG4gICAgICAgICAgICBtICAgICAgICAgICA6ICdtJyxcbiAgICAgICAgICAgIG4gICAgICAgICAgIDogJ24nLFxuICAgICAgICAgICAgbyAgICAgICAgICAgOiAnbycsXG4gICAgICAgICAgICBwICAgICAgICAgICA6ICdwJyxcbiAgICAgICAgICAgIHEgICAgICAgICAgIDogJ3EnLFxuICAgICAgICAgICAgciAgICAgICAgICAgOiAncicsXG4gICAgICAgICAgICBzICAgICAgICAgICA6ICdzJyxcbiAgICAgICAgICAgIHQgICAgICAgICAgIDogJ3QnLFxuICAgICAgICAgICAgdSAgICAgICAgICAgOiAndScsXG4gICAgICAgICAgICB2ICAgICAgICAgICA6ICd2JyxcbiAgICAgICAgICAgIHcgICAgICAgICAgIDogJ3cnLFxuICAgICAgICAgICAgeCAgICAgICAgICAgOiAneCcsXG4gICAgICAgICAgICB5ICAgICAgICAgICA6ICd5JyxcbiAgICAgICAgICAgIHogICAgICAgICAgIDogJ3onLFxuICAgICAgICAgICAgQSAgICAgICAgICAgOiAnQScsXG4gICAgICAgICAgICBCICAgICAgICAgICA6ICdCJyxcbiAgICAgICAgICAgIEMgICAgICAgICAgIDogJ0MnLFxuICAgICAgICAgICAgRCAgICAgICAgICAgOiAnRCcsXG4gICAgICAgICAgICBFICAgICAgICAgICA6ICdFJyxcbiAgICAgICAgICAgIEYgICAgICAgICAgIDogJ0YnLFxuICAgICAgICAgICAgRyAgICAgICAgICAgOiAnRycsXG4gICAgICAgICAgICBIICAgICAgICAgICA6ICdIJyxcbiAgICAgICAgICAgIEkgICAgICAgICAgIDogJ0knLFxuICAgICAgICAgICAgSiAgICAgICAgICAgOiAnSicsXG4gICAgICAgICAgICBLICAgICAgICAgICA6ICdLJyxcbiAgICAgICAgICAgIEwgICAgICAgICAgIDogJ0wnLFxuICAgICAgICAgICAgTSAgICAgICAgICAgOiAnTScsXG4gICAgICAgICAgICBOICAgICAgICAgICA6ICdOJyxcbiAgICAgICAgICAgIE8gICAgICAgICAgIDogJ08nLFxuICAgICAgICAgICAgUCAgICAgICAgICAgOiAnUCcsXG4gICAgICAgICAgICBRICAgICAgICAgICA6ICdRJyxcbiAgICAgICAgICAgIFIgICAgICAgICAgIDogJ1InLFxuICAgICAgICAgICAgUyAgICAgICAgICAgOiAnUycsXG4gICAgICAgICAgICBUICAgICAgICAgICA6ICdUJyxcbiAgICAgICAgICAgIFUgICAgICAgICAgIDogJ1UnLFxuICAgICAgICAgICAgViAgICAgICAgICAgOiAnVicsXG4gICAgICAgICAgICBXICAgICAgICAgICA6ICdXJyxcbiAgICAgICAgICAgIFggICAgICAgICAgIDogJ1gnLFxuICAgICAgICAgICAgWSAgICAgICAgICAgOiAnWScsXG4gICAgICAgICAgICBaICAgICAgICAgICA6ICdaJyxcbiAgICAgICAgICAgIFNlbWljb2xvbiAgIDogJzsnLFxuICAgICAgICAgICAgRXF1YWwgICAgICAgOiAnPScsXG4gICAgICAgICAgICBDb21tYSAgICAgICA6ICcsJyxcbiAgICAgICAgICAgIEh5cGhlbiAgICAgIDogJy0nLFxuICAgICAgICAgICAgTWludXMgICAgICAgOiAnLScsXG4gICAgICAgICAgICBQbHVzICAgICAgICA6ICcrJyxcbiAgICAgICAgICAgIERvdCAgICAgICAgIDogJy4nLFxuICAgICAgICAgICAgU2xhc2ggICAgICAgOiAnLycsXG4gICAgICAgICAgICBCYWNrcXVvdGUgICA6ICdgJyxcbiAgICAgICAgICAgIExlZnRCcmFja2V0IDogJ1snLFxuICAgICAgICAgICAgUmlnaHRCcmFja2V0OiAnXScsXG4gICAgICAgICAgICBCYWNrc2xhc2ggICA6ICdcXFxcJyxcbiAgICAgICAgICAgIFF1b3RlICAgICAgIDogXCInXCIsXG5cbiAgICAgICAgICAgIC8vIE51bWVyaWMga2V5cGFkIGtleXNcbiAgICAgICAgICAgIG51bXBhZDAgICAgICAgICAgICAgICAgICAgICAgIDogJzAnLFxuICAgICAgICAgICAgbnVtcGFkMSAgICAgICAgICAgICAgICAgICAgICAgOiAnMScsXG4gICAgICAgICAgICBudW1wYWQyICAgICAgICAgICAgICAgICAgICAgICA6ICcyJyxcbiAgICAgICAgICAgIG51bXBhZDMgICAgICAgICAgICAgICAgICAgICAgIDogJzMnLFxuICAgICAgICAgICAgbnVtcGFkNCAgICAgICAgICAgICAgICAgICAgICAgOiAnNCcsXG4gICAgICAgICAgICBudW1wYWQ1ICAgICAgICAgICAgICAgICAgICAgICA6ICc1JyxcbiAgICAgICAgICAgIG51bXBhZDYgICAgICAgICAgICAgICAgICAgICAgIDogJzYnLFxuICAgICAgICAgICAgbnVtcGFkNyAgICAgICAgICAgICAgICAgICAgICAgOiAnNycsXG4gICAgICAgICAgICBudW1wYWQ4ICAgICAgICAgICAgICAgICAgICAgICA6ICc4JyxcbiAgICAgICAgICAgIG51bXBhZDkgICAgICAgICAgICAgICAgICAgICAgIDogJzknLFxuICAgICAgICAgICAgTnVtcGFkRG90ICAgICAgICAgICAgICAgICAgICAgOiAnLicsXG4gICAgICAgICAgICBOdW1wYWREb3RBbHQgICAgICAgICAgICAgICAgICA6ICcsJywgLy8gTW9kZXJuIGJyb3dzZXJzIGF1dG9tYXRpY2FsbHkgYWRhcHQgdGhlIGNoYXJhY3RlciBzZW50IGJ5IHRoaXMga2V5IHRvIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBvZiB0aGUgY3VycmVudCBsYW5ndWFnZVxuICAgICAgICAgICAgTnVtcGFkTXVsdGlwbHkgICAgICAgICAgICAgICAgOiAnKicsXG4gICAgICAgICAgICBOdW1wYWRQbHVzICAgICAgICAgICAgICAgICAgICA6ICcrJyxcbiAgICAgICAgICAgIE51bXBhZE1pbnVzICAgICAgICAgICAgICAgICAgIDogJy0nLFxuICAgICAgICAgICAgTnVtcGFkU2xhc2ggICAgICAgICAgICAgICAgICAgOiAnLycsXG4gICAgICAgICAgICBOdW1wYWREb3RPYnNvbGV0ZUJyb3dzZXJzICAgICA6ICdEZWNpbWFsJyxcbiAgICAgICAgICAgIE51bXBhZE11bHRpcGx5T2Jzb2xldGVCcm93c2VyczogJ011bHRpcGx5JyxcbiAgICAgICAgICAgIE51bXBhZFBsdXNPYnNvbGV0ZUJyb3dzZXJzICAgIDogJ0FkZCcsXG4gICAgICAgICAgICBOdW1wYWRNaW51c09ic29sZXRlQnJvd3NlcnMgICA6ICdTdWJ0cmFjdCcsXG4gICAgICAgICAgICBOdW1wYWRTbGFzaE9ic29sZXRlQnJvd3NlcnMgICA6ICdEaXZpZGUnLFxuXG4gICAgICAgICAgICAvLyBTcGVjaWFsIGFycmF5cyBmb3IgcXVpY2tlciB0ZXN0c1xuICAgICAgICAgICAgX2FsbEZuS2V5cyAgICAgICAgICAgOiBbJ0YxJywgJ0YyJywgJ0YzJywgJ0Y0JywgJ0Y1JywgJ0Y2JywgJ0Y3JywgJ0Y4JywgJ0Y5JywgJ0YxMCcsICdGMTEnLCAnRjEyJ10sXG4gICAgICAgICAgICBfc29tZU5vblByaW50YWJsZUtleXM6IFsnVGFiJywgJ0VudGVyJywgJ1NoaWZ0JywgJ1NoaWZ0TGVmdCcsICdTaGlmdFJpZ2h0JywgJ0NvbnRyb2wnLCAnQ29udHJvbExlZnQnLCAnQ29udHJvbFJpZ2h0JywgJ0FsdCcsICdBbHRMZWZ0JywgJ0FsdFJpZ2h0JywgJ1BhdXNlJywgJ0NhcHNMb2NrJywgJ0VzY2FwZSddLFxuICAgICAgICAgICAgX2RpcmVjdGlvbktleXMgICAgICAgOiBbJ1BhZ2VVcCcsICdQYWdlRG93bicsICdFbmQnLCAnSG9tZScsICdBcnJvd0Rvd24nLCAnQXJyb3dMZWZ0JywgJ0Fycm93UmlnaHQnLCAnQXJyb3dVcCddLFxuICAgICAgICB9O1xuICAgIH0sXG59O1xuXG5leHBvcnQgZGVmYXVsdCBBdXRvTnVtZXJpY0VudW07XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvQXV0b051bWVyaWNFbnVtLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==");

/***/ },
/* 3 */
/***/ function(module, exports, __webpack_require__) {

	eval("/*** IMPORTS FROM imports-loader ***/\n(function() {\n\n'use strict';\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 <alexandre.bonneau@linuxfr.eu>\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__(2);\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` 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            return obj instanceof Element;\n        }\n\n        /**\n         * Return `true` in the given DOM element is an <input>.\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 {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 checkEverywhere = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n            if (numberOrNumericString === '-') {\n                return true;\n            }\n\n            if (numberOrNumericString === '') {\n                return false;\n            }\n\n            //TODO Use the `negativeSignCharacter` from the settings here\n            if (AutoNumericHelper.isNumber(numberOrNumericString)) {\n                return numberOrNumericString < 0;\n            }\n\n            if (checkEverywhere) {\n                return this.contains(numberOrNumericString, '-');\n            }\n\n            return this.isNegativeStrict(numberOrNumericString);\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         * @returns {boolean}\n         */\n\n    }, {\n        key: 'isNegativeStrict',\n        value: function isNegativeStrict(numericString) {\n            //TODO Using the `negativeSignCharacter` from the settings here\n            return numericString.charAt(0) === '-';\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         *\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 <input> 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} element\n         * @param {object} detail\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            var event = void 0;\n            if (window.CustomEvent) {\n                event = new CustomEvent(eventName, { detail: detail, bubbles: false, cancelable: false }); // 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, true, true, { 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         * 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.<T>}\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    return AutoNumericHelper;\n}();\n\nexports.default = AutoNumericHelper;\n}.call(window));//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvQXV0b051bWVyaWNIZWxwZXIuanM/ODU0YyJdLCJuYW1lcyI6WyJBdXRvTnVtZXJpY0hlbHBlciIsInZhbHVlIiwic3RyIiwiU3RyaW5nIiwibG93ZXJjYXNlVmFsdWUiLCJ0b0xvd2VyQ2FzZSIsInJlZmVyZW5jZSIsIkFycmF5IiwiaXNBcnJheSIsIm9iaiIsInByb3AiLCJoYXNPd25Qcm9wZXJ0eSIsIm4iLCJpc05hTiIsInBhcnNlRmxvYXQiLCJpc0Zpbml0ZSIsImxhdGluQ29udmVydGVkTnVtYmVyIiwiYXJhYmljVG9MYXRpbk51bWJlcnMiLCJpc051bWJlciIsInBhcnNlSW50IiwiZnVuYyIsIm5lZWRsZSIsImlzU3RyaW5nIiwiaW5kZXhPZiIsImFycmF5IiwiaXNVbmRlZmluZWQiLCJhcnIiLCJPYmplY3QiLCJwcm90b3R5cGUiLCJ0b1N0cmluZyIsImNhbGwiLCJFcnJvciIsIkVsZW1lbnQiLCJkb21FbGVtZW50IiwiaXNFbGVtZW50IiwidGFnTmFtZSIsInNwbGl0IiwiZGVjaW1hbFBhcnQiLCJsZW5ndGgiLCJNYXRoIiwiYWJzIiwicmVzdWx0IiwibGFzdEluZGV4T2YiLCJldmVudCIsIndoaWNoIiwia2V5Q29kZSIsImtleSIsImlzU2VsZW5pdW1Cb3QiLCJrZXlDb2RlTnVtYmVyIiwiQW5kcm9pZERlZmF1bHQiLCJrZXlOYW1lIiwicG90ZW50aWFsUmVzdWx0IiwiZnJvbUNoYXJDb2RlS2V5Q29kZSIsImlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSIsImZyb21DaGFyQ29kZSIsImJyb3dzZXIiLCJOdW1wYWRQbHVzIiwiQ29udGV4dE1lbnUiLCJDclNlbCIsIk51bXBhZERvdCIsIm5hbWUiLCJ2ZXJzaW9uIiwiRG90IiwiRGVsZXRlIiwiTnVtcGFkU2xhc2giLCJEb3duQXJyb3ciLCJFc2MiLCJFeFNlbCIsIkxlZnRBcnJvdyIsIk9TTGVmdCIsIk51bXBhZE11bHRpcGx5IiwiUmlnaHRBcnJvdyIsIlNwYWNlIiwiTnVtcGFkTWludXMiLCJVcEFycm93IiwidWEiLCJuYXZpZ2F0b3IiLCJ1c2VyQWdlbnQiLCJ0ZW0iLCJNIiwibWF0Y2giLCJ0ZXN0IiwiZXhlYyIsInJlcGxhY2UiLCJhcHBOYW1lIiwiYXBwVmVyc2lvbiIsInNwbGljZSIsIndpbmRvdyIsIndlYmRyaXZlciIsIm51bWJlck9yTnVtZXJpY1N0cmluZyIsImNoZWNrRXZlcnl3aGVyZSIsImNvbnRhaW5zIiwiaXNOZWdhdGl2ZVN0cmljdCIsIm51bWVyaWNTdHJpbmciLCJjaGFyQXQiLCJ2YWx1ZVN0cmluZyIsImxlZnRCcmFja2V0IiwicmlnaHRCcmFja2V0Iiwic3RyaW5nIiwiaW5kZXgiLCJuZXdDaGFyYWN0ZXIiLCJzdWJzdHIiLCJzZXR0aW5ncyIsIm1heCIsIm1pbmltdW1WYWx1ZSIsIm1pbiIsIm1heGltdW1WYWx1ZSIsImZvcm1hdHRlZE51bWJlclN0cmluZyIsImNhcmV0UG9zaXRpb24iLCJkZWNpbWFsQ2hhcmFjdGVyIiwibnVtYmVyRG90T3JOZWdhdGl2ZVNpZ24iLCJSZWdFeHAiLCJudW1iZXJEb3RBbmROZWdhdGl2ZVNpZ25Db3VudCIsImkiLCJyYXdOdW1iZXJTdHJpbmciLCJjYXJldFBvc2l0aW9uSW5SYXdWYWx1ZSIsImZvcm1hdHRlZE51bWJlclN0cmluZ1NpemUiLCJyYXdOdW1iZXJTdHJpbmdTaXplIiwiZm9ybWF0dGVkTnVtYmVyU3RyaW5nSW5kZXgiLCJyYXdOdW1iZXJTdHJpbmdJbmRleCIsImNoYXJhY3RlciIsInRleHQiLCJjaGFyQ291bnRlciIsImNoYXJhY3RlckNvdW50IiwiZWxlbWVudCIsInBvc2l0aW9uIiwiaXNTZWxlY3Rpb25TdGFydFVuZGVmaW5lZCIsInNlbGVjdGlvblN0YXJ0IiwiZXJyb3IiLCJzZWxlY3Rpb24iLCJnZXRTZWxlY3Rpb24iLCJzZWxlY3Rpb25JbmZvIiwiZ2V0UmFuZ2VBdCIsInN0YXJ0Iiwic3RhcnRPZmZzZXQiLCJlbmQiLCJlbmRPZmZzZXQiLCJzZWxlY3Rpb25FbmQiLCJpc0lucHV0RWxlbWVudCIsInNldFNlbGVjdGlvblJhbmdlIiwiaXNOdWxsIiwiZmlyc3RDaGlsZCIsInJhbmdlIiwiZG9jdW1lbnQiLCJjcmVhdGVSYW5nZSIsInNldFN0YXJ0Iiwic2V0RW5kIiwicmVtb3ZlQWxsUmFuZ2VzIiwiYWRkUmFuZ2UiLCJtZXNzYWdlIiwic2hvd1dhcm5pbmciLCJjb25zb2xlIiwid2FybiIsIndoZWVsRXZlbnQiLCJkZWx0YVkiLCJ0aHJvd0Vycm9yIiwidHlwZSIsImRlY2ltYWxQbGFjZXMiLCJpbnRlZ2VyUGFydCIsInN0ZXBQbGFjZSIsInJvdW5kIiwiaXNBZGRpdGlvbiIsImRlY2ltYWxQbGFjZXNSYXdWYWx1ZSIsIk51bWJlciIsImZvcmNlRGVjaW1hbFBsYWNlcyIsImFic1ZhbHVlIiwicmF3VmFsdWVNaW5pbXVtT2Zmc2V0IiwicG93Iiwib2Zmc2V0IiwibWluaW11bU9mZnNldEZpcnN0RGVjaW1hbFBsYWNlSW5kZXgiLCJpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSIsInJvdW5kVG9OZWFyZXN0IiwibGVuZ3RoVmFsdWUiLCJkZWNpbWFsUGxhY2VzTGltaXQiLCJtb2RpZnlBbmRSb3VuZFRvTmVhcmVzdEF1dG8iLCJhcmFiaWNOdW1iZXJzIiwicmV0dXJuQU51bWJlciIsInBhcnNlRGVjaW1hbENoYXJhY3RlciIsInBhcnNlVGhvdXNhbmRTZXBhcmF0b3IiLCJkIiwiY2hhckNvZGVBdCIsInJlc3VsdEFzTnVtYmVyIiwiZXZlbnROYW1lIiwiZGV0YWlsIiwiQ3VzdG9tRXZlbnQiLCJidWJibGVzIiwiY2FuY2VsYWJsZSIsImNyZWF0ZUV2ZW50IiwiaW5pdEN1c3RvbUV2ZW50IiwiZGlzcGF0Y2hFdmVudCIsIngiLCJlIiwibkwiLCJqIiwic2xpY2UiLCJzIiwic2VhcmNoIiwiYyIsInkiLCJ4YyIsInljIiwiayIsImwiLCJ4TmVnIiwic3RyTGVuZ3RoIiwicmFuZG9tIiwidGV4dENvbnRlbnQiLCJzZXBhcmF0b3IiLCJyZW1vdmVEYXRhIiwic2tpcEZpcnN0V29yZCIsIndvcmRzIiwibWFwIiwid29yZCIsInRvVXBwZXJDYXNlIiwiam9pbiIsIm5vZGVUeXBlIiwiTm9kZSIsIkVMRU1FTlRfTk9ERSIsIkRPQ1VNRU5UX05PREUiLCJET0NVTUVOVF9GUkFHTUVOVF9OT0RFIiwiVEVYVF9OT0RFIiwibm9kZVZhbHVlIiwiZXhjbHVkZWRFbGVtZW50cyIsImZpbHRlciIsImlzSW5BcnJheSIsInRyaW1tZWREZWNpbWFsUGFydCIsImhvdmVyZWRFbGVtZW50cyIsInF1ZXJ5U2VsZWN0b3JBbGwiLCJhcnJMZW5ndGgiLCJTZXQiLCJjb25jYXQiLCJtYXBPYmplY3RzIiwiTWFwIiwicmVkdWNlIiwiYXMiLCJiIl0sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7Ozs7Ozs7cWpCQUFBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQTZCQTs7Ozs7Ozs7OztBQUVBOzs7O0lBSXFCQSxpQjs7Ozs7Ozs7QUFDakI7Ozs7Ozs7K0JBT2NDLEssRUFBTztBQUNqQixtQkFBT0EsVUFBVSxJQUFqQjtBQUNIOztBQUVEOzs7Ozs7Ozs7O29DQU9tQkEsSyxFQUFPO0FBQ3RCLG1CQUFPQSxVQUFVLEtBQUssQ0FBdEI7QUFDSDs7QUFFRDs7Ozs7Ozs7O2lEQU1nQ0EsSyxFQUFPO0FBQ25DLG1CQUFPQSxVQUFVLElBQVYsSUFBa0JBLFVBQVUsS0FBSyxDQUFqQyxJQUF1QyxPQUFPQSxLQUFyRDtBQUNIOztBQUVEOzs7Ozs7Ozs7aUNBTWdCQyxHLEVBQUs7QUFDakIsbUJBQVEsT0FBT0EsR0FBUCxLQUFlLFFBQWYsSUFBMkJBLGVBQWVDLE1BQWxEO0FBQ0g7QUFDRDs7Ozs7Ozs7OztzQ0FPcUJGLEssRUFBTztBQUN4QixtQkFBT0EsVUFBVSxFQUFqQjtBQUNIOztBQUVEOzs7Ozs7Ozs7O2tDQU9pQkEsSyxFQUFPO0FBQ3BCLG1CQUFPLE9BQU9BLEtBQVAsS0FBa0IsU0FBekI7QUFDSDs7QUFFRDs7Ozs7Ozs7Ozs0Q0FPMkJBLEssRUFBTztBQUM5QixnQkFBTUcsaUJBQWlCRCxPQUFPRixL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QU1nQztBQUFBLDhDQUFaQyxVQUFZO0FBQVpBLDBCQUFZO0FBQUE7O0FBQzVCLG1CQUFPLElBQUlDLEdBQUosQ0FBUUQsV0FBV0UsTUFBWCxDQUFrQixVQUFDQyxFQUFELEVBQUtDLENBQUw7QUFBQSx1QkFBV0QsR0FBR0osTUFBSCw4QkFBY0ssQ0FBZCxHQUFYO0FBQUEsYUFBbEIsRUFBZ0QsRUFBaEQsQ0FBUixDQUFQO0FBQ0g7Ozs7OztrQkEzMUNnQjNPLGlCIiwiZmlsZSI6IjMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEhlbHBlciBmdW5jdGlvbnMgZm9yIGF1dG9OdW1lcmljLmpzXG4gKiBAYXV0aG9yIEFsZXhhbmRyZSBCb25uZWF1IDxhbGV4YW5kcmUuYm9ubmVhdUBsaW51eGZyLmV1PlxuICogQGNvcHlyaWdodCDCqSAyMDE2IEFsZXhhbmRyZSBCb25uZWF1XG4gKlxuICogVGhlIE1JVCBMaWNlbnNlIChodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocClcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvblxuICogb2J0YWluaW5nIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb25cbiAqIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dFxuICogcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsXG4gKiBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWIgbGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZVxuICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmdcbiAqIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsXG4gKiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVNcbiAqIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EXG4gKiBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVFxuICogSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksXG4gKiBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1JcbiAqIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgQXV0b051bWVyaWNFbnVtIGZyb20gJy4vQXV0b051bWVyaWNFbnVtJztcblxuLyoqXG4gKiBTdGF0aWMgY2xhc3MgdGhhdCBob2xkcyBhbGwgdGhlIGhlbHBlciBmdW5jdGlvbnMgYXV0b051bWVyaWMgdXNlcy5cbiAqIE5vdGUgOiBub25lIG9mIHRoZSBmdW5jdGlvbnMgaW4gdGhlcmUgYXJlIGF3YXJlIG9mIGFueSBhdXRvTnVtZXJpYyBpbnRlcm5hbHMgKHdoaWNoIG1lYW5zIHRoZXJlIGFyZSBubyByZWZlcmVuY2VzIHRvIGF1dG9OdW1lcmljLXNwZWNpZmljIGluZm8gbGlrZSBvcHRpb25zIG5hbWVzIG9yIGRhdGEgc3RydWN0dXJlcykuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIEF1dG9OdW1lcmljSGVscGVyIHtcbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBgdmFsdWVgIGlzIG51bGxcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB0ZXN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybiBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgbnVsbCwgRkFMU0Ugb3RoZXJ3aXNlXG4gICAgICovXG4gICAgc3RhdGljIGlzTnVsbCh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IG51bGw7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgYHZhbHVlYCBpcyB1bmRlZmluZWRcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB0ZXN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybiBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgdW5kZWZpbmVkLCBGQUxTRSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBzdGF0aWMgaXNVbmRlZmluZWQodmFsdWUpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlID09PSB2b2lkKDApO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgdW5kZWZpbmVkLCBudWxsIG9yIGVtcHR5XG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eSh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHZvaWQoMCkgfHwgJycgPT09IHZhbHVlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGdpdmVuIHBhcmFtZXRlciBpcyBhIFN0cmluZ1xuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSBzdHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNTdHJpbmcoc3RyKSB7XG4gICAgICAgIHJldHVybiAodHlwZW9mIHN0ciA9PT0gJ3N0cmluZycgfHwgc3RyIGluc3RhbmNlb2YgU3RyaW5nKTtcbiAgICB9XG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgYHZhbHVlYCBpcyBhbiBlbXB0eSBzdHJpbmcgJydcbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byB0ZXN0XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybiBgdHJ1ZWAgaWYgdGhlIGB2YWx1ZWAgaXMgYW4gZW1wdHkgc3RyaW5nICcnLCBGQUxTRSBvdGhlcndpc2VcbiAgICAgKi9cbiAgICBzdGF0aWMgaXNFbXB0eVN0cmluZyh2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdmFsdWUgPT09ICcnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHBhcmFtZXRlciBpcyBhIGJvb2xlYW5cbiAgICAgKlxuICAgICAqIEBzdGF0aWNcbiAgICAgKiBAcGFyYW0geyp9IHZhbHVlXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzQm9vbGVhbih2YWx1ZSkge1xuICAgICAgICByZXR1cm4gdHlwZW9mKHZhbHVlKSA9PT0gJ2Jvb2xlYW4nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHBhcmFtZXRlciBpcyBhIHN0cmluZyAndHJ1ZScgb3IgJ2ZhbHNlJ1xuICAgICAqXG4gICAgICogVGhpcyBmdW5jdGlvbiBhY2NlcHRzIGFueSBjYXNlcyBmb3IgdGhvc2Ugc3RyaW5ncy5cbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdmFsdWVcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNUcnVlT3JGYWxzZVN0cmluZyh2YWx1ZSkge1xuICAgICAgICBjb25zdCBsb3dlcmNhc2VWYWx1ZSA9IFN0cmluZyh2YWx1ZSkudG9Mb3dlckNhc2UoKTtcbiAgICAgICAgcmV0dXJuIGxvd2VyY2FzZVZhbHVlID09PSAndHJ1ZScgfHwgbG93ZXJjYXNlVmFsdWUgPT09ICdmYWxzZSc7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGFuIG9iamVjdFxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSByZWZlcmVuY2VcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNPYmplY3QocmVmZXJlbmNlKSB7XG4gICAgICAgIHJldHVybiB0eXBlb2YgcmVmZXJlbmNlID09PSAnb2JqZWN0JyAmJiByZWZlcmVuY2UgIT09IG51bGwgJiYgIUFycmF5LmlzQXJyYXkocmVmZXJlbmNlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBnaXZlbiBvYmplY3QgaXMgZW1wdHlcbiAgICAgKiBjZi4gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy82Nzk5MTUvaG93LWRvLWktdGVzdC1mb3ItYW4tZW1wdHktamF2YXNjcmlwdC1vYmplY3QgYW5kIGh0dHA6Ly9qc3BlcmYuY29tL2VtcHR5LW9iamVjdC10ZXN0XG4gICAgICpcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gb2JqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzRW1wdHlPYmoob2JqKSB7XG4gICAgICAgIGZvciAoY29uc3QgcHJvcCBpbiBvYmopIHtcbiAgICAgICAgICAgIGlmIChvYmouaGFzT3duUHJvcGVydHkocHJvcCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgcmVhbCBudW1iZXIgKGFuZCBub3QgYSBudW1lcmljIHN0cmluZykuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IG5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNOdW1iZXJTdHJpY3Qobikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG4gPT09ICdudW1iZXInO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHBhcmFtZXRlciBpcyBhIG51bWJlciAob3IgYSBudW1iZXIgd3JpdHRlbiBhcyBhIHN0cmluZykuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IG5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNOdW1iZXIobikge1xuICAgICAgICByZXR1cm4gIXRoaXMuaXNBcnJheShuKSAmJiAhaXNOYU4ocGFyc2VGbG9hdChuKSkgJiYgaXNGaW5pdGUobik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgbnVtYmVyIChvciBhIG51bWJlciB3cml0dGVuIGFzIGEgc3RyaW5nKS5cbiAgICAgKiBUaGlzIHZlcnNpb24gYWxzbyBhY2NlcHRzIEFyYWJpYyBhbmQgUGVyc2lhbiBudW1iZXJzLlxuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSBuXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzTnVtYmVyT3JBcmFiaWMobikge1xuICAgICAgICBjb25zdCBsYXRpbkNvbnZlcnRlZE51bWJlciA9IHRoaXMuYXJhYmljVG9MYXRpbk51bWJlcnMobiwgZmFsc2UsIHRydWUsIHRydWUpO1xuICAgICAgICByZXR1cm4gdGhpcy5pc051bWJlcihsYXRpbkNvbnZlcnRlZE51bWJlcik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGFuIGludGVnZXIgKGFuZCBub3QgYSBmbG9hdCkuXG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IG5cbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNJbnQobikge1xuICAgICAgICByZXR1cm4gdHlwZW9mIG4gPT09ICdudW1iZXInICYmIHBhcnNlRmxvYXQobikgPT09IHBhcnNlSW50KG4sIDEwKSAmJiAhaXNOYU4obik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgZnVuY3Rpb24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBmdW5jXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzRnVuY3Rpb24oZnVuYykge1xuICAgICAgICByZXR1cm4gdHlwZW9mIGZ1bmMgPT09ICdmdW5jdGlvbic7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpcyB0aGUgc3RyaW5nIGBzdHJgIGNvbnRhaW5zIHRoZSBzdHJpbmcgYG5lZWRsZWBcbiAgICAgKiBOb3RlOiB0aGlzIGZ1bmN0aW9uIGRvZXMgbm90IGNvZXJjZSB0aGUgcGFyYW1ldGVycyB0eXBlc1xuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0clxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBuZWVkbGVcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgY29udGFpbnMoc3RyLCBuZWVkbGUpIHtcbiAgICAgICAgLy9UT0RPIFVzZSBgQXJyYXkucHJvdG90eXBlLmluY2x1ZGVzKClgIHdoZW4gYXZhaWxhYmxlIChjZi4gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvQXJyYXkvaW5jbHVkZXMpXG4gICAgICAgIGlmICghdGhpcy5pc1N0cmluZyhzdHIpIHx8ICF0aGlzLmlzU3RyaW5nKG5lZWRsZSkgfHwgc3RyID09PSAnJyB8fCBuZWVkbGUgPT09ICcnKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gc3RyLmluZGV4T2YobmVlZGxlKSAhPT0gLTE7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgYG5lZWRsZWAgaXMgaW4gdGhlIGFycmF5XG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IG5lZWRsZVxuICAgICAqIEBwYXJhbSB7QXJyYXl9IGFycmF5XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzSW5BcnJheShuZWVkbGUsIGFycmF5KSB7XG4gICAgICAgIGlmICghdGhpcy5pc0FycmF5KGFycmF5KSB8fCBhcnJheSA9PT0gW10gfHwgdGhpcy5pc1VuZGVmaW5lZChuZWVkbGUpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gYXJyYXkuaW5kZXhPZihuZWVkbGUpICE9PSAtMTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBwYXJhbWV0ZXIgaXMgYW4gQXJyYXlcbiAgICAgKiAvL1RPRE8gUmVwbGFjZSB0aGlzIGJ5IHRoZSBkZWZhdWx0IGBBcnJheS5pc0FycmF5KClgIGZ1bmN0aW9uP1xuICAgICAqXG4gICAgICogQHBhcmFtIHsqfSBhcnJcbiAgICAgKiBAdGhyb3dzIEVycm9yXG4gICAgICogQHJldHVybnMgeyp8Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNBcnJheShhcnIpIHtcbiAgICAgICAgaWYgKE9iamVjdC5wcm90b3R5cGUudG9TdHJpbmcuY2FsbChbXSkgPT09ICdbb2JqZWN0IEFycmF5XScpIHsgLy8gTWFrZSBzdXJlIGFuIGFycmF5IGhhcyBhIGNsYXNzIGF0dHJpYnV0ZSBvZiBbb2JqZWN0IEFycmF5XVxuICAgICAgICAgICAgLy8gVGVzdCBwYXNzZWQsIG5vdyBjaGVjayBpZiBpcyBhbiBBcnJheVxuICAgICAgICAgICAgcmV0dXJuIEFycmF5LmlzQXJyYXkoYXJyKSB8fCAodHlwZW9mIGFyciA9PT0gJ29iamVjdCcgJiYgT2JqZWN0LnByb3RvdHlwZS50b1N0cmluZy5jYWxsKGFycikgPT09ICdbb2JqZWN0IEFycmF5XScpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKCd0b1N0cmluZyBtZXNzYWdlIGNoYW5nZWQgZm9yIE9iamVjdCBBcnJheScpOyAvLyBWZXJpZnkgdGhhdCB0aGUgc3RyaW5nIHJldHVybmVkIGJ5IGB0b1N0cmluZ2AgZG9lcyBub3QgY2hhbmdlIGluIHRoZSBmdXR1cmUgKGNmLiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS84MzY1MjE1KVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgRE9NIGVsZW1lbnRcbiAgICAgKiBjZi4gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvNDc1NDEwNC8yODM0ODk4XG4gICAgICpcbiAgICAgKiBAcGFyYW0geyp9IG9ialxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBpc0VsZW1lbnQob2JqKSB7XG4gICAgICAgIC8vIHJldHVybiAhIShvYmogJiYgb2JqLm5vZGVOYW1lKTtcbiAgICAgICAgLy8gcmV0dXJuIG9iaiAmJiAnbm9kZVR5cGUnIGluIG9iajtcbiAgICAgICAgLy8gcmV0dXJuIG9iaiBpbnN0YW5jZW9mIEVsZW1lbnQgfHwgb2JqIGluc3RhbmNlb2YgSFRNTElucHV0RWxlbWVudCB8fCBvYmogaW5zdGFuY2VvZiBIVE1MRWxlbWVudDtcbiAgICAgICAgcmV0dXJuIG9iaiBpbnN0YW5jZW9mIEVsZW1lbnQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpbiB0aGUgZ2l2ZW4gRE9NIGVsZW1lbnQgaXMgYW4gPGlucHV0Pi5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7SFRNTEVsZW1lbnR8SFRNTElucHV0RWxlbWVudH0gZG9tRWxlbWVudFxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqIEBwcml2YXRlXG4gICAgICovXG4gICAgc3RhdGljIGlzSW5wdXRFbGVtZW50KGRvbUVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMuaXNFbGVtZW50KGRvbUVsZW1lbnQpICYmIGRvbUVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnaW5wdXQnO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHBhcmFtZXRlciBpcyBhIHN0cmluZyB0aGF0IHJlcHJlc2VudHMgYSBmbG9hdCBudW1iZXIsIGFuZCB0aGF0IG51bWJlciBoYXMgYSBkZWNpbWFsIHBhcnRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICAvLyBzdGF0aWMgaGFzRGVjaW1hbHMoc3RyKSB7XG4gICAgLy8gICAgIGNvbnN0IFssIGRlY2ltYWxQYXJ0XSA9IHN0ci5zcGxpdCgnLicpO1xuICAgIC8vICAgICByZXR1cm4gIWlzVW5kZWZpbmVkKGRlY2ltYWxQYXJ0KTtcbiAgICAvLyB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyBpZiB0aGUgcGFyYW1ldGVyIGlzIGEgc3RyaW5nIHRoYXQgcmVwcmVzZW50cyBhIGZsb2F0IG51bWJlciwgYW5kIHRoYXQgbnVtYmVyIGhhcyBhIGRlY2ltYWwgcGFydC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJcbiAgICAgKiBAcmV0dXJucyB7aW50fVxuICAgICAqL1xuICAgIHN0YXRpYyBkZWNpbWFsUGxhY2VzKHN0cikge1xuICAgICAgICBjb25zdCBbLCBkZWNpbWFsUGFydF0gPSBzdHIuc3BsaXQoJy4nKTtcbiAgICAgICAgaWYgKCF0aGlzLmlzVW5kZWZpbmVkKGRlY2ltYWxQYXJ0KSkge1xuICAgICAgICAgICAgcmV0dXJuIGRlY2ltYWxQYXJ0Lmxlbmd0aDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiAwO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IG5vbi16ZXJvIGRlY2ltYWwgcGxhY2UgaW4gdGhlIGdpdmVuIHZhbHVlLlxuICAgICAqIFRoZSBpbmRleCBzdGFydHMgYWZ0ZXIgdGhlIGRlY2ltYWwgcG9pbnQsIGlmIGFueSwgYW5kIGJlZ2lucyBhdCAnMScuXG4gICAgICogSWYgbm8gZGVjaW1hbCBwbGFjZXMgYXJlIGZvdW5kIGluIHRoZSB2YWx1ZSwgdGhpcyBmdW5jdGlvbiByZXR1cm5zIGAwYC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlXG4gICAgICogaW5kZXhGaXJzdE5vblplcm9EZWNpbWFsUGxhY2UoJzAuMDAnKSAtPiAwXG4gICAgICogaW5kZXhGaXJzdE5vblplcm9EZWNpbWFsUGxhY2UoJzEuMDAnKSAtPiAwXG4gICAgICogaW5kZXhGaXJzdE5vblplcm9EZWNpbWFsUGxhY2UoJzAuMTInKSAtPiAxXG4gICAgICogaW5kZXhGaXJzdE5vblplcm9EZWNpbWFsUGxhY2UoJzAuMTIzNCcpIC0+IDFcbiAgICAgKiBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSgnMC4wMTIzNCcpIC0+IDJcbiAgICAgKiBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSgnMC4wMDEyMzQnKSAtPiAzXG4gICAgICogaW5kZXhGaXJzdE5vblplcm9EZWNpbWFsUGxhY2UoJzAuMDAwMTIzNCcpIC0+IDRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICAgICAqIEByZXR1cm5zIHtOdW1iZXJ8bnVtYmVyfVxuICAgICAqL1xuICAgIHN0YXRpYyBpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSh2YWx1ZSkge1xuICAgICAgICBjb25zdCBbLCBkZWNpbWFsUGFydF0gPSBTdHJpbmcoTWF0aC5hYnModmFsdWUpKS5zcGxpdCgnLicpO1xuXG4gICAgICAgIGlmICh0aGlzLmlzVW5kZWZpbmVkKGRlY2ltYWxQYXJ0KSkge1xuICAgICAgICAgICAgcmV0dXJuIDA7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmVzdWx0ID0gZGVjaW1hbFBhcnQubGFzdEluZGV4T2YoJzAnKTtcbiAgICAgICAgaWYgKHJlc3VsdCA9PT0gLTEpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IDA7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXN1bHQgKz0gMjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBjb2RlIGZvciB0aGUga2V5IHVzZWQgdG8gZ2VuZXJhdGUgdGhlIGdpdmVuIGV2ZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtFdmVudH0gZXZlbnRcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfE51bWJlcn1cbiAgICAgKi9cbiAgICBzdGF0aWMga2V5Q29kZU51bWJlcihldmVudCkge1xuICAgICAgICAvLyBgZXZlbnQua2V5Q29kZWAgYW5kIGBldmVudC53aGljaGAgYXJlIGRlcHJlY2F0ZWQsIGBLZXlib2FyZEV2ZW50LmtleWAgKGh0dHBzOi8vZGV2ZWxvcGVyLm1vemlsbGEub3JnL2VuLVVTL2RvY3MvV2ViL0FQSS9LZXlib2FyZEV2ZW50L2tleSkgbXVzdCBiZSB1c2VkIG5vd1xuICAgICAgICAvLyBBbHNvLCBkbyBub3RlIHRoYXQgRmlyZWZveCBnZW5lcmF0ZSBhICdrZXlwcmVzcycgZXZlbnQgKGUua2V5Q29kZSA9PT0gMCkgZm9yIHRoZSBrZXlzIHRoYXQgZG8gbm90IHByaW50IGEgY2hhcmFjdGVyIChpZS4gJ0luc2VydCcsICdEZWxldGUnLCAnRm4nIGtleXMsICdQYWdlVXAnLCAnUGFnZURvd24nIGV0Yy4pLiAnU2hpZnQnIG9uIHRoZSBvdGhlciBoYW5kIGRvZXMgbm90IGdlbmVyYXRlIGEga2V5cHJlc3MgZXZlbnQuXG4gICAgICAgIHJldHVybiAodHlwZW9mIGV2ZW50LndoaWNoID09PSAndW5kZWZpbmVkJyk/ZXZlbnQua2V5Q29kZTpldmVudC53aGljaDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIGNoYXJhY3RlciBmcm9tIHRoZSBldmVudCBrZXkgY29kZS5cbiAgICAgKiBJZiB0aGUgS2V5Ym9hcmRFdmVudCBkb2VzIG5vdCByZXByZXNlbnQgYSBwcmludGFibGUgY2hhcmFjdGVyLCB0aGVuIHRoZSBrZXkgbmFtZSBpcyB1c2VkIChpZS4gJ01ldGEnLCAnU2hpZnQnLCAnRjEnLCBldGMuKVxuICAgICAqIEBleGFtcGxlIGNoYXJhY3Rlcig1MCkgPT4gJzInXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0tleWJvYXJkRXZlbnR9IGV2ZW50XG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgY2hhcmFjdGVyKGV2ZW50KSB7XG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIGlmIChldmVudC5rZXkgPT09ICdVbmlkZW50aWZpZWQnIHx8IGV2ZW50LmtleSA9PT0gdm9pZCgwKSB8fCB0aGlzLmlzU2VsZW5pdW1Cb3QoKSkge1xuICAgICAgICAgICAgLy9YWFggVGhlIHNlbGVuaXVtIGdlY2tvZHJpdmVyIGRvIG5vdCB1bmRlcnN0YW5kIGBldmVudC5rZXlgLCBoZW5jZSB3aGVuIHVzaW5nIGl0LCB3ZSBuZWVkIHRvIHJlbHkgb24gdGhlIG9sZCBkZXByZWNhdGVkIGBrZXlDb2RlYCBhdHRyaWJ1dGUsIGNmLiB1cHN0cmVhbSBpc3N1ZSBodHRwczovL2dpdGh1Yi5jb20vbW96aWxsYS9nZWNrb2RyaXZlci9pc3N1ZXMvNDQwXG4gICAgICAgICAgICAvLyBVc2UgdGhlIG9sZCBkZXByZWNhdGVkIGtleUNvZGUgcHJvcGVydHksIGlmIHRoZSBuZXcgYGtleWAgb25lIGlzIG5vdCBzdXBwb3J0ZWRcbiAgICAgICAgICAgIGNvbnN0IGtleUNvZGUgPSB0aGlzLmtleUNvZGVOdW1iZXIoZXZlbnQpO1xuICAgICAgICAgICAgaWYgKGtleUNvZGUgPT09IEF1dG9OdW1lcmljRW51bS5rZXlDb2RlLkFuZHJvaWREZWZhdWx0KSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkFuZHJvaWREZWZhdWx0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBjb25zdCBwb3RlbnRpYWxSZXN1bHQgPSBBdXRvTnVtZXJpY0VudW0uZnJvbUNoYXJDb2RlS2V5Q29kZVtrZXlDb2RlXTtcbiAgICAgICAgICAgIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNVbmRlZmluZWRPck51bGxPckVtcHR5KHBvdGVudGlhbFJlc3VsdCkpIHtcbiAgICAgICAgICAgICAgICAvLyBTaW5jZSBgU3RyaW5nLmZyb21DaGFyQ29kZWAgZG8gbm90IHJldHVybiBuYW1lZCBrZXlzIGZvciBzb21lIGtleXMgKCdFc2NhcGUnIGFuZCAnRW50ZXInIGZvciBpbnN0YW5jZSksIHdlIGNvbnZlcnQgdGhlIGNoYXJhY3RlcnMgdG8gdGhlIGtleSBuYW1lc1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHBvdGVudGlhbFJlc3VsdDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gU3RyaW5nLmZyb21DaGFyQ29kZShrZXlDb2RlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGxldCBicm93c2VyO1xuICAgICAgICAgICAgc3dpdGNoIChldmVudC5rZXkpIHtcbiAgICAgICAgICAgICAgICAvLyBNYW5hZ2VzIGFsbCB0aGUgc3BlY2lhbCBjYXNlcyBmb3Igb2Jzb2xldGUgYnJvd3NlcnMgdGhhdCByZXR1cm4gdGhlIG5vbi1zdGFuZGFyZCBuYW1lc1xuICAgICAgICAgICAgICAgIGNhc2UgJ0FkZCc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLk51bXBhZFBsdXM7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGNhc2UgJ0FwcHMnOlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5Db250ZXh0TWVudTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnQ3JzZWwnOlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5DclNlbDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnRGVjaW1hbCc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLk51bXBhZERvdDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnRGVsJzpcbiAgICAgICAgICAgICAgICAgICAgYnJvd3NlciA9IHRoaXMuYnJvd3NlcigpO1xuICAgICAgICAgICAgICAgICAgICBpZiAoKGJyb3dzZXIubmFtZSA9ICdmaXJlZm94JyAmJiBicm93c2VyLnZlcnNpb24gPD0gMzYpIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAoYnJvd3Nlci5uYW1lID0gJ2llJyAmJiBicm93c2VyLnZlcnNpb24gPD0gOSkpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIC8vIFNwZWNpYWwgd29ya2Fyb3VuZCBmb3IgdGhlIG9ic29sZXRlIGJyb3dzZXIgSUUxMSB3aGljaCBvdXRwdXQgYSAnRGVsZXRlJyBrZXkgd2hlbiB1c2luZyB0aGUgbnVtcGFkICdkb3QnIG9uZSEgVGhpcyBmaXhlcyBpc3N1ZSAjNDAxXG4gICAgICAgICAgICAgICAgICAgICAgICAvLyBUaGlzIHdvcmthcm91bmQgYnJlYWsgdGhlIHVzYWdlIG9mIHRoZSAnRGVsZXRlJyBrZXkgZm9yIEZpcmVmb3ggPD0zNiwgYW5kIElFOSwgc2luY2UgdGhvc2UgYnJvd3NlciBzZW5kICdEZWwnIGluc3RlYWQgb2YgJ0RlbGV0ZScsIHRoZXJlZm9yZSB3ZSBvbmx5IHVzZSBpdCBmb3IgdGhvc2Ugb2Jzb2xldGUgYnJvd3NlcnNcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkRvdDtcbiAgICAgICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkRlbGV0ZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdEaXZpZGUnOlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5OdW1wYWRTbGFzaDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnRG93bic6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkRvd25BcnJvdztcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnRXNjJzpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuRXNjO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdFeHNlbCc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLkV4U2VsO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdMZWZ0JzpcbiAgICAgICAgICAgICAgICAgICAgcmVzdWx0ID0gQXV0b051bWVyaWNFbnVtLmtleU5hbWUuTGVmdEFycm93O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdNZXRhJzpcbiAgICAgICAgICAgICAgICBjYXNlICdTdXBlcic6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLk9TTGVmdDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnTXVsdGlwbHknOlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5OdW1wYWRNdWx0aXBseTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAnUmlnaHQnOlxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBBdXRvTnVtZXJpY0VudW0ua2V5TmFtZS5SaWdodEFycm93O1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdTcGFjZWJhcic6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLlNwYWNlO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdTdWJ0cmFjdCc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLk51bXBhZE1pbnVzO1xuICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICBjYXNlICdVcCc6XG4gICAgICAgICAgICAgICAgICAgIHJlc3VsdCA9IEF1dG9OdW1lcmljRW51bS5rZXlOYW1lLlVwQXJyb3c7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIC8vIFRoZSBub3JtYWwgY2FzZVxuICAgICAgICAgICAgICAgICAgICByZXN1bHQgPSBldmVudC5rZXk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBhbiBvYmplY3QgY29udGFpbmluZyB0aGUgbmFtZSBhbmQgdmVyc2lvbiBvZiB0aGUgY3VycmVudCBicm93c2VyLlxuICAgICAqIEBleGFtcGxlIGBicm93c2VyVmVyc2lvbigpYCA9PiB7IG5hbWU6ICdGaXJlZm94JywgdmVyc2lvbjogJzQyJyB9XG4gICAgICogQmFzZWQgb24gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzgwODAwNTEvMjgzNDg5OFxuICAgICAqXG4gICAgICogQHJldHVybnMge3sgbmFtZTogc3RyaW5nLCB2ZXJzaW9uOiBzdHJpbmcgfX1cbiAgICAgKi9cbiAgICBzdGF0aWMgYnJvd3NlcigpIHtcbiAgICAgICAgY29uc3QgdWEgPSBuYXZpZ2F0b3IudXNlckFnZW50O1xuICAgICAgICBsZXQgdGVtO1xuICAgICAgICBsZXQgTSA9IHVhLm1hdGNoKC8ob3BlcmF8Y2hyb21lfHNhZmFyaXxmaXJlZm94fG1zaWV8dHJpZGVudCg/PVxcLykpXFwvP1xccyooXFxkKykvaSkgfHwgW107XG5cbiAgICAgICAgaWYgKC90cmlkZW50L2kudGVzdChNWzFdKSkge1xuICAgICAgICAgICAgdGVtID0gL1xcYnJ2WyA6XSsoXFxkKykvZy5leGVjKHVhKSB8fCBbXTtcbiAgICAgICAgICAgIHJldHVybiB7IG5hbWU6ICdpZScsIHZlcnNpb246ICh0ZW1bMV0gfHwgJycpIH07XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoTVsxXSA9PT0gJ0Nocm9tZScpIHtcbiAgICAgICAgICAgIHRlbSA9IHVhLm1hdGNoKC9cXGIoT1BSfEVkZ2UpXFwvKFxcZCspLyk7XG4gICAgICAgICAgICBpZiAodGVtICE9PSBudWxsKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIHsgbmFtZTogdGVtWzFdLnJlcGxhY2UoJ09QUicsICdvcGVyYScpLCB2ZXJzaW9uOiB0ZW1bMl0gfTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIE0gPSBNWzJdP1tNWzFdLCBNWzJdXTpbbmF2aWdhdG9yLmFwcE5hbWUsIG5hdmlnYXRvci5hcHBWZXJzaW9uLCAnLT8nXTtcbiAgICAgICAgaWYgKCh0ZW0gPSB1YS5tYXRjaCgvdmVyc2lvblxcLyhcXGQrKS9pKSkgIT09IG51bGwpIHtcbiAgICAgICAgICAgIE0uc3BsaWNlKDEsIDEsIHRlbVsxXSk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4geyBuYW1lOiBNWzBdLnRvTG93ZXJDYXNlKCksIHZlcnNpb246IE1bMV0gfTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDaGVjayBpZiB0aGUgYnJvd3NlciBpcyBjb250cm9sbGVkIGJ5IFNlbGVuaXVtLlxuICAgICAqIE5vdGU6IFRoaXMgb25seSB3b3JrcyB3aXRoaW4gdGhlIGdlY2tvZHJpdmVyLlxuICAgICAqIGNmLiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzMzMjI1OTQ3L2Nhbi1hLXdlYnNpdGUtZGV0ZWN0LXdoZW4teW91LWFyZS11c2luZy1zZWxlbml1bS13aXRoLWNocm9tZWRyaXZlclxuICAgICAqXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzU2VsZW5pdW1Cb3QoKSB7XG4gICAgICAgIC8vIG5vaW5zcGVjdGlvbiBKU1VucmVzb2x2ZWRWYXJpYWJsZVxuICAgICAgICByZXR1cm4gd2luZG93Lm5hdmlnYXRvci53ZWJkcml2ZXIgPT09IHRydWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gbnVtYmVyIGlzIG5lZ2F0aXZlLCBvciBpZiB0aGUgZ2l2ZW4gc3RyaW5nIGNvbnRhaW5zIGEgbmVnYXRpdmUgc2lnbiA6XG4gICAgICogLSBldmVyeXdoZXJlIGluIHRoZSBzdHJpbmcgKGJ5IGRlZmF1bHQpLCBvclxuICAgICAqIC0gb24gdGhlIGZpcnN0IGNoYXJhY3RlciBvbmx5IGlmIHRoZSBgY2hlY2tFdmVyeXdoZXJlYCBwYXJhbWV0ZXIgaXMgc2V0IHRvIGBmYWxzZWAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IG51bWJlck9yTnVtZXJpY1N0cmluZyBBIE51bWJlciwgb3IgYSBudW1iZXIgcmVwcmVzZW50ZWQgYnkgYSBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IGNoZWNrRXZlcnl3aGVyZSBJZiBUUlVFLCB0aGVuIHRoZSBuZWdhdGl2ZSBzaWduIGlzIHNlYXJjaCBldmVyeXdoZXJlIGluIHRoZSBudW1lcmljIHN0cmluZyAodGhpcyBpcyBuZWVkZWQgZm9yIGluc3RhbmNlIGlmIHRoZSBzdHJpbmcgaXMgJzEyMzQuNTYtJylcbiAgICAgKiBAcmV0dXJucyB7Ym9vbGVhbn1cbiAgICAgKi9cbiAgICBzdGF0aWMgaXNOZWdhdGl2ZShudW1iZXJPck51bWVyaWNTdHJpbmcsIGNoZWNrRXZlcnl3aGVyZSA9IHRydWUpIHtcbiAgICAgICAgaWYgKG51bWJlck9yTnVtZXJpY1N0cmluZyA9PT0gJy0nKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChudW1iZXJPck51bWVyaWNTdHJpbmcgPT09ICcnKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICAvL1RPRE8gVXNlIHRoZSBgbmVnYXRpdmVTaWduQ2hhcmFjdGVyYCBmcm9tIHRoZSBzZXR0aW5ncyBoZXJlXG4gICAgICAgIGlmIChBdXRvTnVtZXJpY0hlbHBlci5pc051bWJlcihudW1iZXJPck51bWVyaWNTdHJpbmcpKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVtYmVyT3JOdW1lcmljU3RyaW5nIDwgMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjaGVja0V2ZXJ5d2hlcmUpIHtcbiAgICAgICAgICAgIHJldHVybiB0aGlzLmNvbnRhaW5zKG51bWJlck9yTnVtZXJpY1N0cmluZywgJy0nKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLmlzTmVnYXRpdmVTdHJpY3QobnVtYmVyT3JOdW1lcmljU3RyaW5nKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gYHRydWVgIGlmIHRoZSBnaXZlbiBzdHJpbmcgY29udGFpbnMgYSBuZWdhdGl2ZSBzaWduIG9uIHRoZSBmaXJzdCBjaGFyYWN0ZXIgKG9uIHRoZSBmYXIgbGVmdCkuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZSBpc05lZ2F0aXZlU3RyaWN0KCcxMjM0LjU2JykgICAgID0+IGZhbHNlXG4gICAgICogQGV4YW1wbGUgaXNOZWdhdGl2ZVN0cmljdCgnMTIzNC41Ni0nKSAgICA9PiBmYWxzZVxuICAgICAqIEBleGFtcGxlIGlzTmVnYXRpdmVTdHJpY3QoJy0xMjM0LjU2JykgICAgPT4gdHJ1ZVxuICAgICAqIEBleGFtcGxlIGlzTmVnYXRpdmVTdHJpY3QoJy0xLDIzNC41NiDigqwnKSA9PiB0cnVlXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbnVtZXJpY1N0cmluZ1xuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBpc05lZ2F0aXZlU3RyaWN0KG51bWVyaWNTdHJpbmcpIHtcbiAgICAgICAgLy9UT0RPIFVzaW5nIHRoZSBgbmVnYXRpdmVTaWduQ2hhcmFjdGVyYCBmcm9tIHRoZSBzZXR0aW5ncyBoZXJlXG4gICAgICAgIHJldHVybiBudW1lcmljU3RyaW5nLmNoYXJBdCgwKSA9PT0gJy0nO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIHZlcnkgZmlyc3QgY2hhcmFjdGVyIGlzIHRoZSBvcGVuaW5nIGJyYWNrZXQsIGFuZCBpZiB0aGUgcmVzdCBvZiB0aGUgYHZhbHVlU3RyaW5nYCBhbHNvIGhhcyB0aGUgY2xvc2luZyBicmFja2V0LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHZhbHVlU3RyaW5nXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGxlZnRCcmFja2V0XG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHJpZ2h0QnJhY2tldFxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBpc05lZ2F0aXZlV2l0aEJyYWNrZXRzKHZhbHVlU3RyaW5nLCBsZWZ0QnJhY2tldCwgcmlnaHRCcmFja2V0KSB7XG4gICAgICAgIHJldHVybiB2YWx1ZVN0cmluZy5jaGFyQXQoMCkgPT09IGxlZnRCcmFja2V0ICYmIHRoaXMuY29udGFpbnModmFsdWVTdHJpbmcsIHJpZ2h0QnJhY2tldCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZm9ybWF0dGVkIG9yIHVuZm9ybWF0dGVkIG51bWVyaWMgc3RyaW5nIHJlcHJlc2VudCB0aGUgdmFsdWUgMCAoaWUuICcwLDAwIOKCrCcpLCBvciBpcyBlbXB0eSAoJyDigqwnKS5cbiAgICAgKiBUaGlzIHdvcmtzIHNpbmNlIHdlIHRlc3QgaWYgdGhlcmUgYXJlIGFueSBudW1iZXJzIGZyb20gMSB0byA5IGluIHRoZSBzdHJpbmcuIElmIHRoZXJlIGlzIG5vbmUsIHRoZW4gdGhlIG51bWJlciBpcyB6ZXJvIChvciB0aGUgc3RyaW5nIGlzIGVtcHR5KS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBudW1lcmljU3RyaW5nXG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzWmVyb09ySGFzTm9WYWx1ZShudW1lcmljU3RyaW5nKSB7XG4gICAgICAgIHJldHVybiAhKC9bMS05XS9nKS50ZXN0KG51bWVyaWNTdHJpbmcpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgbmVnYXRpdmUgdmVyc2lvbiBvZiB0aGUgdmFsdWUgKHJlcHJlc2VudGVkIGFzIGEgc3RyaW5nKSBnaXZlbiBhcyBhIHBhcmFtZXRlci5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSB2YWx1ZVxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRSYXdOZWdhdGl2ZVNpZ24odmFsdWUpIHtcbiAgICAgICAgaWYgKCF0aGlzLmlzTmVnYXRpdmVTdHJpY3QodmFsdWUpKSB7XG4gICAgICAgICAgICByZXR1cm4gYC0ke3ZhbHVlfWA7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdmFsdWU7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVwbGFjZSB0aGUgY2hhcmFjdGVyIGF0IHRoZSBwb3NpdGlvbiBgaW5kZXhgIGluIHRoZSBzdHJpbmcgYHN0cmluZ2AgYnkgdGhlIGNoYXJhY3RlcihzKSBgbmV3Q2hhcmFjdGVyYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBzdHJpbmdcbiAgICAgKiBAcGFyYW0ge2ludH0gaW5kZXhcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbmV3Q2hhcmFjdGVyXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgcmVwbGFjZUNoYXJBdChzdHJpbmcsIGluZGV4LCBuZXdDaGFyYWN0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGAke3N0cmluZy5zdWJzdHIoMCwgaW5kZXgpfSR7bmV3Q2hhcmFjdGVyfSR7c3RyaW5nLnN1YnN0cihpbmRleCArIG5ld0NoYXJhY3Rlci5sZW5ndGgpfWA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSB2YWx1ZSBjbGFtcGVkIHRvIHRoZSBuZWFyZXN0IG1pbmltdW0vbWF4aW11bSB2YWx1ZSwgYXMgZGVmaW5lZCBpbiB0aGUgc2V0dGluZ3MuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ3xudW1iZXJ9IHZhbHVlXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHNldHRpbmdzXG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBzdGF0aWMgY2xhbXBUb1JhbmdlTGltaXRzKHZhbHVlLCBzZXR0aW5ncykge1xuICAgICAgICAvL1hYWCBUaGlzIGZ1bmN0aW9uIGFsd2F5cyBhc3N1bWUgYHNldHRpbmdzLm1pbmltdW1WYWx1ZWAgaXMgbG93ZXIgdGhhbiBgc2V0dGluZ3MubWF4aW11bVZhbHVlYFxuICAgICAgICByZXR1cm4gTWF0aC5tYXgoc2V0dGluZ3MubWluaW11bVZhbHVlLCBNYXRoLm1pbihzZXR0aW5ncy5tYXhpbXVtVmFsdWUsIHZhbHVlKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBudW1iZXIgb2YgbnVtYmVyIG9yIGRvdCBjaGFyYWN0ZXJzIG9uIHRoZSBsZWZ0IHNpZGUgb2YgdGhlIGNhcmV0LCBpbiBhIGZvcm1hdHRlZCBudW1iZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZm9ybWF0dGVkTnVtYmVyU3RyaW5nXG4gICAgICogQHBhcmFtIHtpbnR9IGNhcmV0UG9zaXRpb24gVGhpcyBtdXN0IGJlIGEgcG9zaXRpdmUgaW50ZWdlclxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBkZWNpbWFsQ2hhcmFjdGVyXG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBzdGF0aWMgY291bnROdW1iZXJDaGFyYWN0ZXJzT25UaGVDYXJldExlZnRTaWRlKGZvcm1hdHRlZE51bWJlclN0cmluZywgY2FyZXRQb3NpdGlvbiwgZGVjaW1hbENoYXJhY3Rlcikge1xuICAgICAgICAvLyBIZXJlIHdlIGNvdW50IHRoZSBkb3QgYW5kIHJlcG9ydCBpdCBhcyBhIG51bWJlciBjaGFyYWN0ZXIgdG9vLCBzaW5jZSBpdCB3aWxsICdzdGF5JyBpbiB0aGUgSmF2YXNjcmlwdCBudW1iZXIgd2hlbiB1bmZvcm1hdHRlZFxuICAgICAgICBjb25zdCBudW1iZXJEb3RPck5lZ2F0aXZlU2lnbiA9IG5ldyBSZWdFeHAoYFswLTkke2RlY2ltYWxDaGFyYWN0ZXJ9LV1gKTsgLy8gTm8gbmVlZCB0byBlc2NhcGUgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGhlcmUsIHNpbmNlIGl0J3MgaW4gYFtdYFxuXG4gICAgICAgIGxldCBudW1iZXJEb3RBbmROZWdhdGl2ZVNpZ25Db3VudCA9IDA7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgY2FyZXRQb3NpdGlvbjsgaSsrKSB7XG4gICAgICAgICAgICAvLyBUZXN0IGlmIHRoZSBjaGFyYWN0ZXIgaXMgYSBudW1iZXIsIGEgZG90IG9yIGFuIGh5cGhlbi4gSWYgaXQgaXMsIGNvdW50IGl0LCBvdGhlcndpc2UgaWdub3JlIGl0XG4gICAgICAgICAgICBpZiAobnVtYmVyRG90T3JOZWdhdGl2ZVNpZ24udGVzdChmb3JtYXR0ZWROdW1iZXJTdHJpbmdbaV0pKSB7XG4gICAgICAgICAgICAgICAgbnVtYmVyRG90QW5kTmVnYXRpdmVTaWduQ291bnQrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBudW1iZXJEb3RBbmROZWdhdGl2ZVNpZ25Db3VudDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBXYWxrIHRoZSBgZm9ybWF0dGVkTnVtYmVyU3RyaW5nYCBmcm9tIGxlZnQgdG8gcmlnaHQsIG9uZSBjaGFyIGJ5IG9uZSwgY291bnRpbmcgdGhlIGBmb3JtYXR0ZWROdW1iZXJTdHJpbmdJbmRleGAuXG4gICAgICogSWYgdGhlIGNoYXIgaXMgaW4gdGhlIGByYXdOdW1iZXJTdHJpbmdgIChzdGFydGluZyBhdCBpbmRleCAwKSwgdGhlbiBgcmF3TnVtYmVyU3RyaW5nSW5kZXgrK2AsIGFuZCBjb250aW51ZSB1bnRpbFxuICAgICAqIHRoZXJlIGlzIG5vIG1vcmUgY2hhcmFjdGVycyBpbiBgcmF3TnVtYmVyU3RyaW5nYCkgb3IgdGhhdCBgcmF3TnVtYmVyU3RyaW5nSW5kZXggPT09IGNhcmV0UG9zaXRpb25JblJhd1ZhbHVlYC5cbiAgICAgKiBXaGVuIHlvdSBzdG9wLCB0aGUgYGZvcm1hdHRlZE51bWJlclN0cmluZ0luZGV4YCBpcyB0aGUgcG9zaXRpb24gd2hlcmUgdGhlIGNhcmV0IHNob3VsZCBiZSBzZXQuXG4gICAgICpcbiAgICAgKiBAZXhhbXBsZVxuICAgICAqIDEyMzQ1Njd8ODkuMDEgICA6IHBvc2l0aW9uIDcgKHJhd051bWJlclN0cmluZylcbiAgICAgKiAxMjMuNDU2Ljd8ODksMDEgOiBwb3NpdGlvbiA5IChmb3JtYXR0ZWROdW1iZXJTdHJpbmcpXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gcmF3TnVtYmVyU3RyaW5nXG4gICAgICogQHBhcmFtIHtpbnR9IGNhcmV0UG9zaXRpb25JblJhd1ZhbHVlXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IGZvcm1hdHRlZE51bWJlclN0cmluZ1xuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBkZWNpbWFsQ2hhcmFjdGVyXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIGZpbmRDYXJldFBvc2l0aW9uSW5Gb3JtYXR0ZWROdW1iZXIocmF3TnVtYmVyU3RyaW5nLCBjYXJldFBvc2l0aW9uSW5SYXdWYWx1ZSwgZm9ybWF0dGVkTnVtYmVyU3RyaW5nLCBkZWNpbWFsQ2hhcmFjdGVyKSB7XG4gICAgICAgIGNvbnN0IGZvcm1hdHRlZE51bWJlclN0cmluZ1NpemUgPSBmb3JtYXR0ZWROdW1iZXJTdHJpbmcubGVuZ3RoO1xuICAgICAgICBjb25zdCByYXdOdW1iZXJTdHJpbmdTaXplID0gcmF3TnVtYmVyU3RyaW5nLmxlbmd0aDtcblxuICAgICAgICBsZXQgZm9ybWF0dGVkTnVtYmVyU3RyaW5nSW5kZXg7XG4gICAgICAgIGxldCByYXdOdW1iZXJTdHJpbmdJbmRleCA9IDA7XG4gICAgICAgIGZvciAoZm9ybWF0dGVkTnVtYmVyU3RyaW5nSW5kZXggPSAwO1xuICAgICAgICAgICAgZm9ybWF0dGVkTnVtYmVyU3RyaW5nSW5kZXggPCBmb3JtYXR0ZWROdW1iZXJTdHJpbmdTaXplICYmXG4gICAgICAgICAgICByYXdOdW1iZXJTdHJpbmdJbmRleCA8IHJhd051bWJlclN0cmluZ1NpemUgJiZcbiAgICAgICAgICAgIHJhd051bWJlclN0cmluZ0luZGV4IDwgY2FyZXRQb3NpdGlvbkluUmF3VmFsdWU7XG4gICAgICAgICAgICBmb3JtYXR0ZWROdW1iZXJTdHJpbmdJbmRleCsrKSB7XG4gICAgICAgICAgICBpZiAocmF3TnVtYmVyU3RyaW5nW3Jhd051bWJlclN0cmluZ0luZGV4XSA9PT0gZm9ybWF0dGVkTnVtYmVyU3RyaW5nW2Zvcm1hdHRlZE51bWJlclN0cmluZ0luZGV4XSB8fFxuICAgICAgICAgICAgICAgIChyYXdOdW1iZXJTdHJpbmdbcmF3TnVtYmVyU3RyaW5nSW5kZXhdID09PSAnLicgJiYgZm9ybWF0dGVkTnVtYmVyU3RyaW5nW2Zvcm1hdHRlZE51bWJlclN0cmluZ0luZGV4XSA9PT0gZGVjaW1hbENoYXJhY3RlcikpIHtcbiAgICAgICAgICAgICAgICByYXdOdW1iZXJTdHJpbmdJbmRleCsrO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZvcm1hdHRlZE51bWJlclN0cmluZ0luZGV4O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENvdW50IHRoZSBudW1iZXIgb2Ygb2NjdXJyZW5jZSBvZiB0aGUgZ2l2ZW4gY2hhcmFjdGVyLCBpbiB0aGUgZ2l2ZW4gdGV4dC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBjaGFyYWN0ZXJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dFxuICAgICAqIEByZXR1cm5zIHtudW1iZXJ9XG4gICAgICovXG4gICAgc3RhdGljIGNvdW50Q2hhckluVGV4dChjaGFyYWN0ZXIsIHRleHQpIHtcbiAgICAgICAgbGV0IGNoYXJDb3VudGVyID0gMDtcbiAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCB0ZXh0Lmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBpZiAodGV4dFtpXSA9PT0gY2hhcmFjdGVyKSB7XG4gICAgICAgICAgICAgICAgY2hhckNvdW50ZXIrKztcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBjaGFyQ291bnRlcjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlIGluZGV4IHRoYXQgY2FuIGJlIHVzZWQgdG8gc2V0IHRoZSBjYXJldCBwb3NpdGlvbi5cbiAgICAgKiBUaGlzIHRha2VzIGludG8gYWNjb3VudCB0aGF0IHRoZSBwb3NpdGlvbiBpcyBzdGFydGluZyBhdCAnMCcsIG5vdCAxLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtpbnR9IGNoYXJhY3RlckNvdW50XG4gICAgICogQHJldHVybnMge251bWJlcn1cbiAgICAgKi9cbiAgICBzdGF0aWMgY29udmVydENoYXJhY3RlckNvdW50VG9JbmRleFBvc2l0aW9uKGNoYXJhY3RlckNvdW50KSB7XG4gICAgICAgIHJldHVybiBNYXRoLm1heChjaGFyYWN0ZXJDb3VudCwgY2hhcmFjdGVyQ291bnQgLSAxKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcm9zcyBicm93c2VyIHJvdXRpbmUgZm9yIGdldHRpbmcgc2VsZWN0ZWQgcmFuZ2UvY3Vyc29yIHBvc2l0aW9uLlxuICAgICAqIE5vdGU6IHRoaXMgYWxzbyB3b3JrcyB3aXRoIGVkZ2UgY2FzZXMgbGlrZSBjb250ZW50ZWRpdGFibGUtZW5hYmxlZCBlbGVtZW50cywgYW5kIGhpZGRlbiBpbnB1dHMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxJbnB1dEVsZW1lbnR8RXZlbnRUYXJnZXR9IGVsZW1lbnRcbiAgICAgKiBAcmV0dXJucyB7e319XG4gICAgICovXG4gICAgc3RhdGljIGdldEVsZW1lbnRTZWxlY3Rpb24oZWxlbWVudCkge1xuICAgICAgICBjb25zdCBwb3NpdGlvbiA9IHt9O1xuXG4gICAgICAgIGxldCBpc1NlbGVjdGlvblN0YXJ0VW5kZWZpbmVkO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaXNTZWxlY3Rpb25TdGFydFVuZGVmaW5lZCA9IHRoaXMuaXNVbmRlZmluZWQoZWxlbWVudC5zZWxlY3Rpb25TdGFydCk7XG4gICAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgICAgICBpc1NlbGVjdGlvblN0YXJ0VW5kZWZpbmVkID0gZmFsc2U7XG4gICAgICAgIH1cblxuICAgICAgICB0cnkge1xuICAgICAgICAgICAgaWYgKGlzU2VsZWN0aW9uU3RhcnRVbmRlZmluZWQpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBzZWxlY3Rpb24gPSB3aW5kb3cuZ2V0U2VsZWN0aW9uKCk7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uSW5mbyA9IHNlbGVjdGlvbi5nZXRSYW5nZUF0KDApO1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uLnN0YXJ0ID0gc2VsZWN0aW9uSW5mby5zdGFydE9mZnNldDtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbi5lbmQgPSBzZWxlY3Rpb25JbmZvLmVuZE9mZnNldDtcbiAgICAgICAgICAgICAgICBwb3NpdGlvbi5sZW5ndGggPSBwb3NpdGlvbi5lbmQgLSBwb3NpdGlvbi5zdGFydDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcG9zaXRpb24uc3RhcnQgPSBlbGVtZW50LnNlbGVjdGlvblN0YXJ0O1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uLmVuZCA9IGVsZW1lbnQuc2VsZWN0aW9uRW5kO1xuICAgICAgICAgICAgICAgIHBvc2l0aW9uLmxlbmd0aCA9IHBvc2l0aW9uLmVuZCAtIHBvc2l0aW9uLnN0YXJ0O1xuICAgICAgICAgICAgfVxuICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgLy8gTWFuYWdlcyB0aGUgY2FzZXMgd2hlcmUgOlxuICAgICAgICAgICAgLy8gLSB0aGUgJ2NvbnRlbnRlZGl0YWJsZScgZWxlbWVudHMgdGhhdCBoYXZlIG5vIHNlbGVjdGlvbnNcbiAgICAgICAgICAgIC8vIC0gdGhlIDxpbnB1dD4gZWxlbWVudCBpcyBvZiB0eXBlICdoaWRkZW4nXG4gICAgICAgICAgICBwb3NpdGlvbi5zdGFydCA9IDA7XG4gICAgICAgICAgICBwb3NpdGlvbi5lbmQgPSAwO1xuICAgICAgICAgICAgcG9zaXRpb24ubGVuZ3RoID0gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwb3NpdGlvbjtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcm9zcyBicm93c2VyIHJvdXRpbmUgZm9yIHNldHRpbmcgc2VsZWN0ZWQgcmFuZ2UvY3Vyc29yIHBvc2l0aW9uXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0hUTUxJbnB1dEVsZW1lbnR8RXZlbnRUYXJnZXR9IGVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge2ludH0gc3RhcnRcbiAgICAgKiBAcGFyYW0ge2ludHxudWxsfSBlbmRcbiAgICAgKi9cbiAgICBzdGF0aWMgc2V0RWxlbWVudFNlbGVjdGlvbihlbGVtZW50LCBzdGFydCwgZW5kID0gbnVsbCkge1xuICAgICAgICBpZiAodGhpcy5pc1VuZGVmaW5lZE9yTnVsbE9yRW1wdHkoZW5kKSkge1xuICAgICAgICAgICAgZW5kID0gc3RhcnQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAodGhpcy5pc0lucHV0RWxlbWVudChlbGVtZW50KSkge1xuICAgICAgICAgICAgZWxlbWVudC5zZXRTZWxlY3Rpb25SYW5nZShzdGFydCwgZW5kKTtcbiAgICAgICAgfSBlbHNlIGlmICghQXV0b051bWVyaWNIZWxwZXIuaXNOdWxsKGVsZW1lbnQuZmlyc3RDaGlsZCkpIHtcbiAgICAgICAgICAgIGNvbnN0IHJhbmdlID0gZG9jdW1lbnQuY3JlYXRlUmFuZ2UoKTtcbiAgICAgICAgICAgIHJhbmdlLnNldFN0YXJ0KGVsZW1lbnQuZmlyc3RDaGlsZCwgc3RhcnQpO1xuICAgICAgICAgICAgcmFuZ2Uuc2V0RW5kKGVsZW1lbnQuZmlyc3RDaGlsZCwgZW5kKTtcbiAgICAgICAgICAgIGNvbnN0IHNlbGVjdGlvbiA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICAgICAgICAgIHNlbGVjdGlvbi5yZW1vdmVBbGxSYW5nZXMoKTtcbiAgICAgICAgICAgIHNlbGVjdGlvbi5hZGRSYW5nZShyYW5nZSk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB0aGF0IHRocm93IGVycm9yIG1lc3NhZ2VzXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICAgICAqIEB0aHJvd3NcbiAgICAgKi9cbiAgICBzdGF0aWMgdGhyb3dFcnJvcihtZXNzYWdlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcihtZXNzYWdlKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB0aGF0IGRpc3BsYXkgYSB3YXJuaW5nIG1lc3NhZ2VzLCBhY2NvcmRpbmcgdG8gdGhlIGRlYnVnIGxldmVsLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNob3dXYXJuaW5nIElmIEZBTFNFLCB0aGVuIHRoZSB3YXJuaW5nIG1lc3NhZ2UgaXMgbm90IGRpc3BsYXllZFxuICAgICAqL1xuICAgIHN0YXRpYyB3YXJuaW5nKG1lc3NhZ2UsIHNob3dXYXJuaW5nID0gdHJ1ZSkge1xuICAgICAgICBpZiAoc2hvd1dhcm5pbmcpIHtcbiAgICAgICAgICAgIC8qIGVzbGludCBuby1jb25zb2xlOiAwICovXG4gICAgICAgICAgICBjb25zb2xlLndhcm4oYFdhcm5pbmc6ICR7bWVzc2FnZX1gKTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiBgdHJ1ZWAgaWYgdGhlIGdpdmVuIGV2ZW50IGlzIGEgd2hlZWx1cCBldmVudFxuICAgICAqXG4gICAgICogQHBhcmFtIHtXaGVlbEV2ZW50fSB3aGVlbEV2ZW50XG4gICAgICogQHJldHVybnMge2Jvb2xlYW59XG4gICAgICovXG4gICAgc3RhdGljIGlzV2hlZWxVcEV2ZW50KHdoZWVsRXZlbnQpIHtcbiAgICAgICAgaWYgKCF3aGVlbEV2ZW50LmRlbHRhWSkge1xuICAgICAgICAgICAgdGhpcy50aHJvd0Vycm9yKGBUaGUgZXZlbnQgcGFzc2VkIGFzIGEgcGFyYW1ldGVyIGlzIG5vdCBhIHZhbGlkIHdoZWVsIGV2ZW50LCAnJHt3aGVlbEV2ZW50LnR5cGV9JyBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB3aGVlbEV2ZW50LmRlbHRhWSA8IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGB0cnVlYCBpZiB0aGUgZ2l2ZW4gZXZlbnQgaXMgYSB3aGVlbGRvd24gZXZlbnRcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7V2hlZWxFdmVudH0gd2hlZWxFdmVudFxuICAgICAqIEByZXR1cm5zIHtib29sZWFufVxuICAgICAqL1xuICAgIHN0YXRpYyBpc1doZWVsRG93bkV2ZW50KHdoZWVsRXZlbnQpIHtcbiAgICAgICAgaWYgKCF3aGVlbEV2ZW50LmRlbHRhWSkge1xuICAgICAgICAgICAgdGhpcy50aHJvd0Vycm9yKGBUaGUgZXZlbnQgcGFzc2VkIGFzIGEgcGFyYW1ldGVyIGlzIG5vdCBhIHZhbGlkIHdoZWVsIGV2ZW50LCAnJHt3aGVlbEV2ZW50LnR5cGV9JyBnaXZlbi5gKTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB3aGVlbEV2ZW50LmRlbHRhWSA+IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSBnaXZlbiByYXcgdmFsdWUgdHJ1bmNhdGVkIGF0IHRoZSBnaXZlbiBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgYGRlY2ltYWxQbGFjZXNgLlxuICAgICAqIFRoaXMgZnVuY3Rpb24gZG9lcyBub3Qgcm91bmQgdGhlIHZhbHVlLlxuICAgICAqXG4gICAgICogQGV4YW1wbGVcbiAgICAgKiBmb3JjZURlY2ltYWxQbGFjZXMoMTIzLjQ1Njc4LCAwKSAtPiAnMTIzLjQ1Njc4J1xuICAgICAqIGZvcmNlRGVjaW1hbFBsYWNlcygxMjMuNDU2NzgsIDEpIC0+ICcxMjMuNCdcbiAgICAgKiBmb3JjZURlY2ltYWxQbGFjZXMoMTIzLjQ1Njc4LCAyKSAtPiAnMTIzLjQ1J1xuICAgICAqIGZvcmNlRGVjaW1hbFBsYWNlcygxMjMuNDU2NzgsIDMpIC0+ICcxMjMuNDU2J1xuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gICAgICogQHBhcmFtIHtpbnR9IGRlY2ltYWxQbGFjZXNcbiAgICAgKiBAcmV0dXJucyB7bnVtYmVyfHN0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgZm9yY2VEZWNpbWFsUGxhY2VzKHZhbHVlLCBkZWNpbWFsUGxhY2VzKSB7XG4gICAgICAgIC8vIFdlIGNvdWxkIG1ha2Ugc3VyZSBgZGVjaW1hbFBsYWNlc2AgaXMgYW4gaW50ZWdlciBhbmQgcG9zaXRpdmUsIGJ1dCB3ZSdsbCBsZWF2ZSB0aGF0IHRvIHRoZSBkZXYgY2FsbGluZyB0aGlzIGZ1bmN0aW9uLlxuICAgICAgICBjb25zdCBbaW50ZWdlclBhcnQsIGRlY2ltYWxQYXJ0XSA9IFN0cmluZyh2YWx1ZSkuc3BsaXQoJy4nKTtcbiAgICAgICAgaWYgKCFkZWNpbWFsUGFydCkge1xuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGAke2ludGVnZXJQYXJ0fS4ke2RlY2ltYWxQYXJ0LnN1YnN0cigwLCBkZWNpbWFsUGxhY2VzKX1gO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgJ25lYXJlc3Qgcm91bmRlZCcgdmFsdWUsIGFjY29yZGluZyB0byB0aGUgZ2l2ZW4gc3RlcCBzaXplLlxuICAgICAqIEBleGFtcGxlIHJvdW5kVG9OZWFyZXN0KDI2NDc4OSwgMTAwMDApKSA9PiAyNjAwMDBcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSB2YWx1ZVxuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBzdGVwUGxhY2VcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgcm91bmRUb05lYXJlc3QodmFsdWUsIHN0ZXBQbGFjZSA9IDEwMDApIHtcbiAgICAgICAgaWYgKDAgPT09IHZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gMDtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChzdGVwUGxhY2UgPT09IDApIHtcbiAgICAgICAgICAgIHRoaXMudGhyb3dFcnJvcignVGhlIGBzdGVwUGxhY2VgIHVzZWQgdG8gcm91bmQgaXMgZXF1YWwgdG8gYDBgLiBUaGlzIHZhbHVlIG11c3Qgbm90IGJlIGVxdWFsIHRvIHplcm8uJyk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gTWF0aC5yb3VuZCh2YWx1ZSAvIHN0ZXBQbGFjZSkgKiBzdGVwUGxhY2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIHRoZSAnbmVhcmVzdCByb3VuZGVkJyB2YWx1ZSBieSBhdXRvbWF0aWNhbGx5IGFkZGluZyBvciBzdWJ0cmFjdGluZyB0aGUgY2FsY3VsYXRlZCBvZmZzZXQgdG8gdGhlIGluaXRpYWwgdmFsdWUuXG4gICAgICogVGhpcyBpcyBkb25lIHdpdGhvdXQgaGF2aW5nIHRvIHBhc3MgYSBzdGVwIHRvIHRoaXMgZnVuY3Rpb24sIGFuZCBiYXNlZCBvbiB0aGUgc2l6ZSBvZiB0aGUgZ2l2ZW4gYHZhbHVlYC5cbiAgICAgKlxuICAgICAqIEBleGFtcGxlICAgICAgICAgICAgICAgICAgICBDYWxjdWxhdGVkIG9mZnNldFxuICAgICAqICAgICAgICAgICAxIC0+ICAgICAgICAgICAxICgxKVxuICAgICAqICAgICAgICAgIDE0IC0+ICAgICAgICAgIDEwICgxMClcbiAgICAgKiAgICAgICAgIDE0MyAtPiAgICAgICAgIDE0MCAoMTApXG4gICAgICogICAgICAgMS4yNzggLT4gICAgICAgMS4zMDAgKDEwMClcbiAgICAgKiAgICAgIDI4LjQ1NiAtPiAgICAgIDI4LjUwMCAoMTAwKVxuICAgICAqICAgICAyNzYuMzQ1IC0+ICAgICAyNzYuMDAwICgxLjAwMClcbiAgICAgKiAgIDQuNTM0LjA2MSAtPiAgIDQuNTMwLjAwMCAoMTAuMDAwKVxuICAgICAqICA2Ni43MjMuODQ0IC0+ICA2Ni43MDAuMDAwICgxMDAuMDAwKVxuICAgICAqIDI1Ny44MzMuNDExIC0+IDI1OC4wMDAuMDAwICgxLjAwMC4wMDApXG4gICAgICpcbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICAgICAgIEluaXRpYWwgICBBZGRlZCAgIE9mZnNldFxuICAgICAqIDIgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMS4xMiAgIC0+IDIuMDAgICAoMSlcbiAgICAgKiAzIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDEuMTIzICAtPiAyLjAwMCAgKDEpXG4gICAgICpcbiAgICAgKiBTcGVjaWFsIGNhc2Ugd2hlbiB0aGUgYHZhbHVlYCB0byByb3VuZCBpcyBiZXR3ZWVuIC0xIGFuZCAxLCBleGNsdWRlZCA6XG4gICAgICogQGV4YW1wbGVcbiAgICAgKiAgICAgTnVtYmVyIG9mICAgICAgICAgICAgIEluaXRpYWwgICBSZXN1bHQgIENhbGN1bGF0ZWRcbiAgICAgKiAgICAgZGVjaW1hbCBwbGFjZXMgICAgICAgIHZhbHVlICAgICAoYWRkKSAgIG9mZnNldFxuICAgICAqIDIgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4xMiAgIC0+IDAuMTMgICAgKDAuMDEpIDogTWF0aC5wb3coMTAsIC0yKVxuICAgICAqIDIgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4wMSAgIC0+IDAuMDIgICAgKDAuMDEpXG4gICAgICogMiBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjAwICAgLT4gMC4wMSAgICAoMC4wMSlcbiAgICAgKlxuICAgICAqIDMgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4xMjMgIC0+IDAuMTMzICAgKDAuMDEpICA6IE1hdGgucG93KDEwLCAtMilcbiAgICAgKiAzIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMDEyICAtPiAwLjAxMyAgICgwLjAwMSkgOiBNYXRoLnBvdygxMCwgLTMpXG4gICAgICogMyBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjAwMSAgLT4gMC4wMDEgICAoMC4wMDEpXG4gICAgICogMyBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjAwMCAgLT4gMC4wMDEgICAoMC4wMDEpXG4gICAgICpcbiAgICAgKiA0IGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuNDEyMyAtPiAwLjQyMDAgICgwLjAxKSAgIDogTWF0aC5wb3coMTAsIC0yKVxuICAgICAqIDQgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlIDogMC4wNDEyIC0+IDAuMDQyMCAgKDAuMDAxKSAgOiBNYXRoLnBvdygxMCwgLTMpXG4gICAgICogNCBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjAwNDEgLT4gMC4wMDQyICAoMC4wMDAxKSA6IE1hdGgucG93KDEwLCAtNClcbiAgICAgKiA0IGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMDAwNCAtPiAwLjAwMDUgICgwLjAwMDEpXG4gICAgICogNCBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjAwMDAgLT4gMC4wMDAxICAoMC4wMDAxKVxuICAgICAqXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IHZhbHVlXG4gICAgICogQHBhcmFtIHtib29sZWFufSBpc0FkZGl0aW9uXG4gICAgICogQHBhcmFtIHtpbnR9IGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSBUaGUgcHJlY2lzaW9uIG5lZWRlZCBieSB0aGUgYHJhd1ZhbHVlYFxuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyBtb2RpZnlBbmRSb3VuZFRvTmVhcmVzdEF1dG8odmFsdWUsIGlzQWRkaXRpb24sIGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSkge1xuICAgICAgICB2YWx1ZSA9IE51bWJlcih0aGlzLmZvcmNlRGVjaW1hbFBsYWNlcyh2YWx1ZSwgZGVjaW1hbFBsYWNlc1Jhd1ZhbHVlKSk7IC8vIE1ha2Ugc3VyZSB0aGF0ICcwLjEzMDAwMDAwMDAxJyBpcyBjb252ZXJ0ZWQgdG8gdGhlIG51bWJlciBvZiByYXdWYWx1ZSBkZWNpbWFsIHBsYWNlcyAnMC4xMydcblxuICAgICAgICBjb25zdCBhYnNWYWx1ZSA9IE1hdGguYWJzKHZhbHVlKTtcbiAgICAgICAgaWYgKGFic1ZhbHVlID49IDAgJiYgYWJzVmFsdWUgPCAxKSB7XG4gICAgICAgICAgICBjb25zdCByYXdWYWx1ZU1pbmltdW1PZmZzZXQgPSBNYXRoLnBvdygxMCwgLWRlY2ltYWxQbGFjZXNSYXdWYWx1ZSk7XG4gICAgICAgICAgICBpZiAodmFsdWUgPT09IDApIHtcbiAgICAgICAgICAgICAgICAvLyA0IGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMDAwMCAtPiAwLjAwMDEgKDAuMDAwMSlcbiAgICAgICAgICAgICAgICByZXR1cm4gKGlzQWRkaXRpb24pP3Jhd1ZhbHVlTWluaW11bU9mZnNldDotcmF3VmFsdWVNaW5pbXVtT2Zmc2V0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICBsZXQgb2Zmc2V0O1xuICAgICAgICAgICAgY29uc3QgbWluaW11bU9mZnNldEZpcnN0RGVjaW1hbFBsYWNlSW5kZXggPSBkZWNpbWFsUGxhY2VzUmF3VmFsdWU7XG4gICAgICAgICAgICAvLyBGaW5kIHdoZXJlIGlzIHRoZSBmaXJzdCBub24temVybyBkZWNpbWFsIHBsYWNlc1xuICAgICAgICAgICAgY29uc3QgaW5kZXhGaXJzdE5vblplcm9EZWNpbWFsUGxhY2UgPSB0aGlzLmluZGV4Rmlyc3ROb25aZXJvRGVjaW1hbFBsYWNlKHZhbHVlKTtcbiAgICAgICAgICAgIGlmIChpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSA+PSBtaW5pbXVtT2Zmc2V0Rmlyc3REZWNpbWFsUGxhY2VJbmRleCAtIDEpIHtcbiAgICAgICAgICAgICAgICAvKiA0IGRlY2ltYWxQbGFjZXNSYXdWYWx1ZSA6IDAuMDA0MSAtPiAwLjAwNDIgKDAuMDAwMSkgOiBNYXRoLnBvdygxMCwgLTQpXG4gICAgICAgICAgICAgICAgICogNCBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgOiAwLjAwMDQgLT4gMC4wMDA1ICgwLjAwMDEpXG4gICAgICAgICAgICAgICAgICovXG4gICAgICAgICAgICAgICAgb2Zmc2V0ID0gcmF3VmFsdWVNaW5pbXVtT2Zmc2V0O1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICBvZmZzZXQgPSBNYXRoLnBvdygxMCwgLShpbmRleEZpcnN0Tm9uWmVyb0RlY2ltYWxQbGFjZSArIDEpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgICAgIGlmIChpc0FkZGl0aW9uKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUgKyBvZmZzZXQ7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9IHZhbHVlIC0gb2Zmc2V0O1xuICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5yb3VuZFRvTmVhcmVzdChyZXN1bHQsIG9mZnNldCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBGb3IgdmFsdWVzID49IDFcbiAgICAgICAgICAgIHZhbHVlID0gcGFyc2VJbnQodmFsdWUsIDEwKTtcbiAgICAgICAgICAgIGNvbnN0IGxlbmd0aFZhbHVlID0gTWF0aC5hYnModmFsdWUpLnRvU3RyaW5nKCkubGVuZ3RoOyAvLyBgTWF0aC5hYnMoKWAgaXMgbmVlZGVkIGhlcmUgdG8gb21pdCB0aGUgbmVnYXRpdmUgc2lnbiAnLScgaW4gY2FzZSBvZiBhIG5lZ2F0aXZlIHZhbHVlXG5cbiAgICAgICAgICAgIGxldCBwb3c7XG4gICAgICAgICAgICBzd2l0Y2ggKGxlbmd0aFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgLy8gU3BlY2lhbCBjYXNlcyBmb3Igc21hbGwgbnVtYmVyc1xuICAgICAgICAgICAgICAgIGNhc2UgMTpcbiAgICAgICAgICAgICAgICAgICAgcG93ID0gMDtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSAyOlxuICAgICAgICAgICAgICAgIGNhc2UgMzpcbiAgICAgICAgICAgICAgICAgICAgcG93ID0gMTtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgY2FzZSA0OlxuICAgICAgICAgICAgICAgIGNhc2UgNTpcbiAgICAgICAgICAgICAgICAgICAgcG93ID0gMjtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgLy8gRGVmYXVsdCBiZWhhdmlvclxuICAgICAgICAgICAgICAgIGRlZmF1bHQ6XG4gICAgICAgICAgICAgICAgICAgIHBvdyA9IGxlbmd0aFZhbHVlIC0gMztcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IG9mZnNldCA9IE1hdGgucG93KDEwLCBwb3cpO1xuXG4gICAgICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICAgICAgaWYgKGlzQWRkaXRpb24pIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSB2YWx1ZSArIG9mZnNldDtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gdmFsdWUgLSBvZmZzZXQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGlmIChyZXN1bHQgPD0gMTAgJiYgcmVzdWx0ID49IC0xMCkge1xuICAgICAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiB0aGlzLnJvdW5kVG9OZWFyZXN0KHJlc3VsdCwgb2Zmc2V0KTtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgJ25lYXJlc3Qgcm91bmRlZCcgdmFsdWUgYXV0b21hdGljYWxseSBieSBhZGRpbmcgdGhlIGNhbGN1bGF0ZWQgb2Zmc2V0IHRvIHRoZSBpbml0aWFsIHZhbHVlLlxuICAgICAqIFRoaXMgd2lsbCBsaW1pdCB0aGUgcmVzdWx0IHRvIHRoZSBnaXZlbiBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgYGRlY2ltYWxQbGFjZXNMaW1pdGAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAgICAgKiBAcGFyYW0ge2ludH0gZGVjaW1hbFBsYWNlc0xpbWl0XG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIGFkZEFuZFJvdW5kVG9OZWFyZXN0QXV0byh2YWx1ZSwgZGVjaW1hbFBsYWNlc0xpbWl0KSB7XG4gICAgICAgIHJldHVybiB0aGlzLm1vZGlmeUFuZFJvdW5kVG9OZWFyZXN0QXV0byh2YWx1ZSwgdHJ1ZSwgZGVjaW1hbFBsYWNlc0xpbWl0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm4gdGhlICduZWFyZXN0IHJvdW5kZWQnIHZhbHVlIGF1dG9tYXRpY2FsbHkgYnkgc3VidHJhY3RpbmcgdGhlIGNhbGN1bGF0ZWQgb2Zmc2V0IHRvIHRoZSBpbml0aWFsIHZhbHVlLlxuICAgICAqIFRoaXMgd2lsbCBsaW1pdCB0aGUgcmVzdWx0IHRvIHRoZSBnaXZlbiBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgYGRlY2ltYWxQbGFjZXNMaW1pdGAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcn0gdmFsdWVcbiAgICAgKiBAcGFyYW0ge2ludH0gZGVjaW1hbFBsYWNlc0xpbWl0XG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIHN1YnRyYWN0QW5kUm91bmRUb05lYXJlc3RBdXRvKHZhbHVlLCBkZWNpbWFsUGxhY2VzTGltaXQpIHtcbiAgICAgICAgcmV0dXJuIHRoaXMubW9kaWZ5QW5kUm91bmRUb05lYXJlc3RBdXRvKHZhbHVlLCBmYWxzZSwgZGVjaW1hbFBsYWNlc0xpbWl0KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUYWtlIGFuIGFyYWJpYyBudW1iZXIgYXMgYSBzdHJpbmcgYW5kIHJldHVybiBhIGphdmFzY3JpcHQgbnVtYmVyLlxuICAgICAqIEJ5IGRlZmF1bHQsIHRoaXMgZnVuY3Rpb24gZG9lcyBub3QgdHJ5IHRvIGNvbnZlcnQgdGhlIGFyYWJpYyBkZWNpbWFsIGFuZCB0aG91c2FuZCBzZXBhcmF0b3IgY2hhcmFjdGVycy5cbiAgICAgKiBUaGlzIHJldHVybnMgYE5hTmAgaXMgdGhlIGNvbnZlcnNpb24gaXMgbm90IHBvc3NpYmxlLlxuICAgICAqIEJhc2VkIG9uIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzE3MDI1MzkyLzI4MzQ4OThcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBhcmFiaWNOdW1iZXJzXG4gICAgICogQHBhcmFtIHtib29sZWFufSByZXR1cm5BTnVtYmVyIElmIGB0cnVlYCwgcmV0dXJuIGEgTnVtYmVyLCBvdGhlcndpc2UgcmV0dXJuIGEgU3RyaW5nXG4gICAgICogQHBhcmFtIHtib29sZWFufSBwYXJzZURlY2ltYWxDaGFyYWN0ZXJcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHBhcnNlVGhvdXNhbmRTZXBhcmF0b3JcbiAgICAgKiBAcmV0dXJucyB7c3RyaW5nfG51bWJlcnxOYU59XG4gICAgICovXG4gICAgc3RhdGljIGFyYWJpY1RvTGF0aW5OdW1iZXJzKGFyYWJpY051bWJlcnMsIHJldHVybkFOdW1iZXIgPSB0cnVlLCBwYXJzZURlY2ltYWxDaGFyYWN0ZXIgPSBmYWxzZSwgcGFyc2VUaG91c2FuZFNlcGFyYXRvciA9IGZhbHNlKSB7XG4gICAgICAgIGlmICh0aGlzLmlzTnVsbChhcmFiaWNOdW1iZXJzKSkge1xuICAgICAgICAgICAgcmV0dXJuIGFyYWJpY051bWJlcnM7XG4gICAgICAgIH1cblxuICAgICAgICBsZXQgcmVzdWx0ID0gYXJhYmljTnVtYmVycy50b1N0cmluZygpO1xuICAgICAgICBpZiAocmVzdWx0ID09PSAnJykge1xuICAgICAgICAgICAgcmV0dXJuIGFyYWJpY051bWJlcnM7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmVzdWx0Lm1hdGNoKC9b2aDZodmi2aPZpNml2abZp9mo2anbtNu127ZdL2cpID09PSBudWxsKSB7XG4gICAgICAgICAgICAvLyBJZiBubyBBcmFiaWMvUGVyc2lhbiBudW1iZXJzIGFyZSBmb3VuZCwgcmV0dXJuIHRoZSBudW1lcmljIHN0cmluZyBvciBudW1iZXIgZGlyZWN0bHlcbiAgICAgICAgICAgIGlmIChyZXR1cm5BTnVtYmVyKSB7XG4gICAgICAgICAgICAgICAgcmVzdWx0ID0gTnVtYmVyKHJlc3VsdCk7XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocGFyc2VEZWNpbWFsQ2hhcmFjdGVyKSB7XG4gICAgICAgICAgICByZXN1bHQgPSByZXN1bHQucmVwbGFjZSgv2asvLCAnLicpOyAvLyBEZWNpbWFsIGNoYXJhY3RlclxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHBhcnNlVGhvdXNhbmRTZXBhcmF0b3IpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKC/ZrC9nLCAnJyk7IC8vIFRob3VzYW5kIHNlcGFyYXRvclxuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVwbGFjZSB0aGUgbnVtYmVycyBvbmx5XG4gICAgICAgIHJlc3VsdCA9IHJlc3VsdC5yZXBsYWNlKC9b2aDZodmi2aPZpNml2abZp9mo2aldL2csIGQgPT4gZC5jaGFyQ29kZUF0KDApIC0gMTYzMikgLy8gQXJhYmljIG51bWJlcnNcbiAgICAgICAgICAgIC5yZXBsYWNlKC9b27Dbsduy27PbtNu127bbt9u427ldL2csIGQgPT4gZC5jaGFyQ29kZUF0KDApIC0gMTc3Nik7IC8vIFBlcnNpYW4gbnVtYmVyc1xuXG4gICAgICAgIC8vIGBOYU5gIGhhcyBwcmVjZWRlbmNlIG92ZXIgdGhlIHN0cmluZyBgJ05hTidgXG4gICAgICAgIGNvbnN0IHJlc3VsdEFzTnVtYmVyID0gTnVtYmVyKHJlc3VsdCk7XG4gICAgICAgIGlmIChpc05hTihyZXN1bHRBc051bWJlcikpIHtcbiAgICAgICAgICAgIHJldHVybiByZXN1bHRBc051bWJlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChyZXR1cm5BTnVtYmVyKSB7XG4gICAgICAgICAgICByZXN1bHQgPSByZXN1bHRBc051bWJlcjtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlIGEgY3VzdG9tIGV2ZW50IGFuZCBpbW1lZGlhdGVseSBzZW50IGl0IGZyb20gdGhlIGdpdmVuIGVsZW1lbnQuXG4gICAgICogQnkgZGVmYXVsdCwgaWYgbm8gZWxlbWVudCBpcyBnaXZlbiwgdGhlIGV2ZW50IGlzIHRocm93biBmcm9tIGBkb2N1bWVudGAuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MRG9jdW1lbnR9IGVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge29iamVjdH0gZGV0YWlsXG4gICAgICovXG4gICAgc3RhdGljIHRyaWdnZXJFdmVudChldmVudE5hbWUsIGVsZW1lbnQgPSBkb2N1bWVudCwgZGV0YWlsID0gbnVsbCkge1xuICAgICAgICBsZXQgZXZlbnQ7XG4gICAgICAgIGlmICh3aW5kb3cuQ3VzdG9tRXZlbnQpIHtcbiAgICAgICAgICAgIGV2ZW50ID0gbmV3IEN1c3RvbUV2ZW50KGV2ZW50TmFtZSwgeyBkZXRhaWwsIGJ1YmJsZXM6IGZhbHNlLCBjYW5jZWxhYmxlOiBmYWxzZSB9KTsgLy8gVGhpcyBpcyBub3Qgc3VwcG9ydGVkIGJ5IGRlZmF1bHQgYnkgSUUgOyBXZSB1c2UgdGhlIHBvbHlmaWxsIGZvciBJRTkgYW5kIGxhdGVyLlxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXZlbnQgPSBkb2N1bWVudC5jcmVhdGVFdmVudCgnQ3VzdG9tRXZlbnQnKTtcbiAgICAgICAgICAgIGV2ZW50LmluaXRDdXN0b21FdmVudChldmVudE5hbWUsIHRydWUsIHRydWUsIHsgZGV0YWlsIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgZWxlbWVudC5kaXNwYXRjaEV2ZW50KGV2ZW50KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGdW5jdGlvbiB0byBwYXJzZSBtaW5pbXVtVmFsdWUsIG1heGltdW1WYWx1ZSAmIHRoZSBpbnB1dCB2YWx1ZSB0byBwcmVwYXJlIGZvciB0ZXN0aW5nIHRvIGRldGVybWluZSBpZiB0aGUgdmFsdWUgZmFsbHMgd2l0aGluIHRoZSBtaW4gLyBtYXggcmFuZ2UuXG4gICAgICogUmV0dXJuIGFuIG9iamVjdCBleGFtcGxlOiBtaW5pbXVtVmFsdWU6IFwiOTk5OTk5OTk5OTk5OTk5Ljk5XCIgcmV0dXJucyB0aGUgZm9sbG93aW5nIFwie3M6IC0xLCBlOiAxMiwgYzogQXJyYXlbMTVdfVwiLlxuICAgICAqXG4gICAgICogVGhpcyBmdW5jdGlvbiBpcyBhZGFwdGVkIGZyb20gQmlnLmpzIGh0dHBzOi8vZ2l0aHViLmNvbS9NaWtlTWNsL2JpZy5qcy8uIE1hbnkgdGhhbmtzIHRvIE1pa2UuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge251bWJlcnxzdHJpbmd9IG4gQSBudW1lcmljIHZhbHVlLlxuICAgICAqIEByZXR1cm5zIHt7fX1cbiAgICAgKi9cbiAgICBzdGF0aWMgcGFyc2VTdHIobikge1xuICAgICAgICBjb25zdCB4ID0ge307IC8vIEEgQmlnIG51bWJlciBpbnN0YW5jZS5cbiAgICAgICAgbGV0IGU7XG4gICAgICAgIGxldCBpO1xuICAgICAgICBsZXQgbkw7XG4gICAgICAgIGxldCBqO1xuXG4gICAgICAgIC8vIE1pbnVzIHplcm8/XG4gICAgICAgIGlmIChuID09PSAwICYmIDEgLyBuIDwgMCkge1xuICAgICAgICAgICAgbiA9ICctMCc7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZXRlcm1pbmUgc2lnbi4gMSBwb3NpdGl2ZSwgLTEgbmVnYXRpdmVcbiAgICAgICAgbiA9IG4udG9TdHJpbmcoKTtcbiAgICAgICAgaWYgKHRoaXMuaXNOZWdhdGl2ZVN0cmljdChuKSkge1xuICAgICAgICAgICAgbiA9IG4uc2xpY2UoMSk7XG4gICAgICAgICAgICB4LnMgPSAtMTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHgucyA9IDE7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBEZWNpbWFsIHBvaW50P1xuICAgICAgICBlID0gbi5pbmRleE9mKCcuJyk7XG4gICAgICAgIGlmIChlID4gLTEpIHtcbiAgICAgICAgICAgIG4gPSBuLnJlcGxhY2UoJy4nLCAnJyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBsZW5ndGggb2Ygc3RyaW5nIGlmIG5vIGRlY2ltYWwgY2hhcmFjdGVyXG4gICAgICAgIGlmIChlIDwgMCkge1xuICAgICAgICAgICAgLy8gSW50ZWdlclxuICAgICAgICAgICAgZSA9IG4ubGVuZ3RoO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gRGV0ZXJtaW5lIGxlYWRpbmcgemVyb3NcbiAgICAgICAgaSA9IChuLnNlYXJjaCgvWzEtOV0vaSkgPT09IC0xKSA/IG4ubGVuZ3RoIDogbi5zZWFyY2goL1sxLTldL2kpO1xuICAgICAgICBuTCA9IG4ubGVuZ3RoO1xuICAgICAgICBpZiAoaSA9PT0gbkwpIHtcbiAgICAgICAgICAgIC8vIFplcm9cbiAgICAgICAgICAgIHguZSA9IDA7XG4gICAgICAgICAgICB4LmMgPSBbMF07XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAvLyBEZXRlcm1pbmUgdHJhaWxpbmcgemVyb3NcbiAgICAgICAgICAgIGZvciAoaiA9IG5MIC0gMTsgbi5jaGFyQXQoaikgPT09ICcwJzsgaiAtPSAxKSB7XG4gICAgICAgICAgICAgICAgbkwgLT0gMTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIG5MIC09IDE7XG5cbiAgICAgICAgICAgIC8vIERlY2ltYWwgbG9jYXRpb25cbiAgICAgICAgICAgIHguZSA9IGUgLSBpIC0gMTtcbiAgICAgICAgICAgIHguYyA9IFtdO1xuXG4gICAgICAgICAgICAvLyBDb252ZXJ0IHN0cmluZyB0byBhcnJheSBvZiBkaWdpdHMgd2l0aG91dCBsZWFkaW5nL3RyYWlsaW5nIHplcm9zXG4gICAgICAgICAgICBmb3IgKGUgPSAwOyBpIDw9IG5MOyBpICs9IDEpIHtcbiAgICAgICAgICAgICAgICB4LmNbZV0gPSArbi5jaGFyQXQoaSk7XG4gICAgICAgICAgICAgICAgZSArPSAxO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIHg7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogRnVuY3Rpb24gdG8gdGVzdCBpZiB0aGUgaW5wdXQgdmFsdWUgZmFsbHMgd2l0aCB0aGUgTWluIC8gTWF4IHNldHRpbmdzLlxuICAgICAqIFRoaXMgdXNlcyB0aGUgcGFyc2VkIHN0cmluZ3MgZm9yIHRoZSBhYm92ZSBwYXJzZVN0ciBmdW5jdGlvbi5cbiAgICAgKlxuICAgICAqIFRoaXMgZnVuY3Rpb24gaXMgYWRhcHRlZCBmcm9tIEJpZy5qcyBodHRwczovL2dpdGh1Yi5jb20vTWlrZU1jbC9iaWcuanMvLiBNYW55IHRoYW5rcyB0byBNaWtlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtvYmplY3R9IHkgQmlnIG51bWJlciBpbnN0YW5jZVxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSB4IEJpZyBudW1iZXIgaW5zdGFuY2VcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgdGVzdE1pbk1heCh5LCB4KSB7XG4gICAgICAgIGNvbnN0IHhjID0geC5jO1xuICAgICAgICBjb25zdCB5YyA9IHkuYztcbiAgICAgICAgbGV0IGkgPSB4LnM7XG4gICAgICAgIGxldCBqID0geS5zO1xuICAgICAgICBsZXQgayA9IHguZTtcbiAgICAgICAgbGV0IGwgPSB5LmU7XG5cbiAgICAgICAgLy8gRWl0aGVyIHplcm8/XG4gICAgICAgIGlmICgheGNbMF0gfHwgIXljWzBdKSB7XG4gICAgICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICAgICAgaWYgKCF4Y1swXSkge1xuICAgICAgICAgICAgICAgIHJlc3VsdCA9ICF5Y1swXT8wOi1qO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICByZXN1bHQgPSBpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFNpZ25zIGRpZmZlcj9cbiAgICAgICAgaWYgKGkgIT09IGopIHtcbiAgICAgICAgICAgIHJldHVybiBpO1xuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHhOZWcgPSBpIDwgMDtcblxuICAgICAgICAvLyBDb21wYXJlIGV4cG9uZW50c1xuICAgICAgICBpZiAoayAhPT0gbCkge1xuICAgICAgICAgICAgcmV0dXJuIChrID4gbCBeIHhOZWcpPzE6LTE7XG4gICAgICAgIH1cbiAgICAgICAgaSA9IC0xO1xuICAgICAgICBrID0geGMubGVuZ3RoO1xuICAgICAgICBsID0geWMubGVuZ3RoO1xuICAgICAgICBqID0gKGsgPCBsKSA/IGsgOiBsO1xuXG4gICAgICAgIC8vIENvbXBhcmUgZGlnaXQgYnkgZGlnaXRcbiAgICAgICAgZm9yIChpICs9IDE7IGkgPCBqOyBpICs9IDEpIHtcbiAgICAgICAgICAgIGlmICh4Y1tpXSAhPT0geWNbaV0pIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKHhjW2ldID4geWNbaV0gXiB4TmVnKT8xOi0xO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gQ29tcGFyZSBsZW5ndGhzXG4gICAgICAgIGxldCByZXN1bHQ7XG4gICAgICAgIGlmIChrID09PSBsKSB7XG4gICAgICAgICAgICByZXN1bHQgPSAwO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gKGsgPiBsIF4geE5lZyk/MTotMTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiByZXN1bHQ7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogR2VuZXJhdGUgYSByYW5kb20gc3RyaW5nLlxuICAgICAqIGNmLiBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vYS84MDg0MjQ4LzI4MzQ4OThcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7TnVtYmVyfSBzdHJMZW5ndGggTGVuZ3RoIG9mIHRoZSBnZW5lcmF0ZWQgc3RyaW5nIChpbiBjaGFyYWN0ZXIgY291bnQpXG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgcmFuZG9tU3RyaW5nKHN0ckxlbmd0aCA9IDUpIHtcbiAgICAgICAgcmV0dXJuIE1hdGgucmFuZG9tKClcbiAgICAgICAgICAgIC50b1N0cmluZygzNilcbiAgICAgICAgICAgIC5zdWJzdHIoMiwgc3RyTGVuZ3RoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXRyaWV2ZSB0aGUgY3VycmVudCBlbGVtZW50IHZhbHVlLlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fEV2ZW50VGFyZ2V0fSBlbGVtZW50XG4gICAgICogQHJldHVybnMge251bWJlcnxzdHJpbmd8bnVsbH1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0RWxlbWVudFZhbHVlKGVsZW1lbnQpIHtcbiAgICAgICAgaWYgKGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnaW5wdXQnKSB7XG4gICAgICAgICAgICByZXR1cm4gZWxlbWVudC52YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzLnRleHQoZWxlbWVudCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTW9kaWZ5IHRoZSBlbGVtZW50IHZhbHVlIGRpcmVjdGx5LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtIVE1MRWxlbWVudHxIVE1MSW5wdXRFbGVtZW50fSBlbGVtZW50XG4gICAgICogQHBhcmFtIHtudW1iZXJ8c3RyaW5nfG51bGx9IHZhbHVlXG4gICAgICovXG4gICAgc3RhdGljIHNldEVsZW1lbnRWYWx1ZShlbGVtZW50LCB2YWx1ZSA9IG51bGwpIHtcbiAgICAgICAgaWYgKGVsZW1lbnQudGFnTmFtZS50b0xvd2VyQ2FzZSgpID09PSAnaW5wdXQnKSB7XG4gICAgICAgICAgICBlbGVtZW50LnZhbHVlID0gdmFsdWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlbGVtZW50LnRleHRDb250ZW50ID0gdmFsdWU7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUaGlzIGNsb25lIHRoZSBnaXZlbiBvYmplY3QsIGFuZCByZXR1cm4gaXQuXG4gICAgICogV0FSTklORzogVGhpcyBkb2VzIG5vdCBkbyBhIGRlZXAgY2xvbmluZy5cbiAgICAgKiBjZi4gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvSmF2YVNjcmlwdC9SZWZlcmVuY2UvR2xvYmFsX09iamVjdHMvT2JqZWN0L2Fzc2lnbiNFeGFtcGxlc1xuICAgICAqIC8vVE9ETyBBZGQgYSBgZGVlcGAgb3B0aW9uIHRvIGNsb25lIG9iamVjdCB3aXRoIG1vcmUgdGhhbiBvbmUgZGVwdGhcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7b2JqZWN0fSBvYmpcbiAgICAgKiBAcmV0dXJucyB7b2JqZWN0fVxuICAgICAqL1xuICAgIHN0YXRpYyBjbG9uZU9iamVjdChvYmopIHtcbiAgICAgICAgcmV0dXJuIE9iamVjdC5hc3NpZ24oe30sIG9iaik7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJuIGEgJ2NhbWVsaXplZCcgdmVyc2lvbiBvZiB0aGUgZ2l2ZW4gc3RyaW5nLlxuICAgICAqIEJ5IGRlZmF1bHQsIHRoaXMgYXNzdW1lIHRoYXQgOlxuICAgICAqIC0gdGhlIHNlcGFyYXRvcnMgYXJlIGh5cGhlbnMgJy0nLFxuICAgICAqIC0gdGhlICdkYXRhLScgc3RyaW5nIHNob3VsZCBiZSByZW1vdmVkLCBhbmRcbiAgICAgKiAtIHRoYXQgdGhlIHZlcnkgZmlyc3Qgd29yZCBzaG91bGQgbm90IGJlIGNhcGl0YWxpemVkLlxuICAgICAqXG4gICAgICogQGV4YW1wbGUgY2FtZWxpemUoJ2RhdGEtY3VycmVuY3ktc3ltYm9sJykgPT4gJ2N1cnJlbmN5U3ltYm9sJ1xuICAgICAqXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHN0ciBUZXh0IHRvIGNhbWVsaXplXG4gICAgICogQHBhcmFtIHtzdHJpbmd9IHNlcGFyYXRvciBDaGFyYWN0ZXIgdGhhdCBzZXBhcmF0ZSBlYWNoIHdvcmRcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHJlbW92ZURhdGEgSWYgc2V0IHRvIGB0cnVlYCwgcmVtb3ZlIHRoZSBgZGF0YS1gIHBhcnQgdGhhdCB5b3UgY2FuIGZpbmQgb24gc29tZSBodG1sIGF0dHJpYnV0ZXNcbiAgICAgKiBAcGFyYW0ge2Jvb2xlYW59IHNraXBGaXJzdFdvcmQgSWYgc2V0IHRvIGB0cnVlYCwgZG8gbm90IGNhcGl0YWxpemUgdGhlIHZlcnkgZmlyc3Qgd29yZFxuICAgICAqIEByZXR1cm5zIHtzdHJpbmd8bnVsbH1cbiAgICAgKi9cbiAgICBzdGF0aWMgY2FtZWxpemUoc3RyLCBzZXBhcmF0b3IgPSAnLScsIHJlbW92ZURhdGEgPSB0cnVlLCBza2lwRmlyc3RXb3JkID0gdHJ1ZSkge1xuICAgICAgICBpZiAodGhpcy5pc051bGwoc3RyKSkge1xuICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICBpZiAocmVtb3ZlRGF0YSkge1xuICAgICAgICAgICAgc3RyID0gc3RyLnJlcGxhY2UoL15kYXRhLS8sICcnKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIEN1dCB0aGUgc3RyaW5nIGludG8gd29yZHNcbiAgICAgICAgY29uc3Qgd29yZHMgPSBzdHIuc3BsaXQoc2VwYXJhdG9yKTtcblxuICAgICAgICAvLyBDYXBpdGFsaXplIGVhY2ggd29yZFxuICAgICAgICBsZXQgcmVzdWx0ID0gd29yZHMubWFwKHdvcmQgPT4gYCR7d29yZC5jaGFyQXQoMCkudG9VcHBlckNhc2UoKX0ke3dvcmQuc2xpY2UoMSl9YCk7XG5cbiAgICAgICAgLy8gVGhlbiBjb25jYXRlbmF0ZSB0aGVtIGJhY2tcbiAgICAgICAgcmVzdWx0ID0gcmVzdWx0LmpvaW4oJycpO1xuXG4gICAgICAgIGlmIChza2lwRmlyc3RXb3JkKSB7XG4gICAgICAgICAgICAvLyBTa2lwIHRoZSB2ZXJ5IGZpcnN0IGxldHRlclxuICAgICAgICAgICAgcmVzdWx0ID0gYCR7cmVzdWx0LmNoYXJBdCgwKS50b0xvd2VyQ2FzZSgpfSR7cmVzdWx0LnNsaWNlKDEpfWA7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgdGV4dCBjb21wb25lbnQgb2YgdGhlIGdpdmVuIERPTSBlbGVtZW50LlxuICAgICAqXG4gICAgICogQHBhcmFtIHtFbGVtZW50fSBkb21FbGVtZW50XG4gICAgICogQHJldHVybnMge3N0cmluZ31cbiAgICAgKi9cbiAgICBzdGF0aWMgdGV4dChkb21FbGVtZW50KSB7XG4gICAgICAgIGNvbnN0IG5vZGVUeXBlID0gZG9tRWxlbWVudC5ub2RlVHlwZTtcblxuICAgICAgICBsZXQgcmVzdWx0O1xuICAgICAgICAvLyBjZi4gaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL05vZGUvbm9kZVR5cGVcbiAgICAgICAgaWYgKG5vZGVUeXBlID09PSBOb2RlLkVMRU1FTlRfTk9ERSB8fFxuICAgICAgICAgICAgbm9kZVR5cGUgPT09IE5vZGUuRE9DVU1FTlRfTk9ERSB8fFxuICAgICAgICAgICAgbm9kZVR5cGUgPT09IE5vZGUuRE9DVU1FTlRfRlJBR01FTlRfTk9ERSkge1xuICAgICAgICAgICAgcmVzdWx0ID0gZG9tRWxlbWVudC50ZXh0Q29udGVudDtcbiAgICAgICAgfSBlbHNlIGlmIChub2RlVHlwZSA9PT0gTm9kZS5URVhUX05PREUpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGRvbUVsZW1lbnQubm9kZVZhbHVlO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gJyc7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldCB0aGUgdGV4dCBjb250ZW50IG9mIHRoZSBnaXZlbiBET00gZWxlbWVudC5cbiAgICAgKiBAcGFyYW0ge0VsZW1lbnR9IGRvbUVsZW1lbnRcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gdGV4dFxuICAgICAqL1xuICAgIHN0YXRpYyBzZXRUZXh0KGRvbUVsZW1lbnQsIHRleHQpIHtcbiAgICAgICAgY29uc3Qgbm9kZVR5cGUgPSBkb21FbGVtZW50Lm5vZGVUeXBlO1xuICAgICAgICBpZiAobm9kZVR5cGUgPT09IE5vZGUuRUxFTUVOVF9OT0RFIHx8XG4gICAgICAgICAgICBub2RlVHlwZSA9PT0gTm9kZS5ET0NVTUVOVF9OT0RFIHx8XG4gICAgICAgICAgICBub2RlVHlwZSA9PT0gTm9kZS5ET0NVTUVOVF9GUkFHTUVOVF9OT0RFKSB7XG4gICAgICAgICAgICBkb21FbGVtZW50LnRleHRDb250ZW50ID0gdGV4dDtcbiAgICAgICAgfVxuICAgICAgICAvL1RPRE8gRGlzcGxheSBhIHdhcm5pbmcgaWYgdGhhdCBmdW5jdGlvbiBkb2VzIG5vdCBkbyBhbnl0aGluZz9cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGaWx0ZXIgb3V0IHRoZSBnaXZlbiBgYXJyYCBhcnJheSB3aXRoIHRoZSBlbGVtZW50cyBmb3VuZCBpbiBgZXhjbHVkZWRFbGVtZW50c2AuXG4gICAgICogVGhpcyByZXR1cm5zIGEgbmV3IGFycmF5IGFuZCBkb2VzIG5vdCBtb2RpZnkgdGhlIHNvdXJjZS5cbiAgICAgKiBjZi4gdmVyaWZpY2F0aW9uIGhlcmUgOiBodHRwOi8vY29kZXBlbi5pby9Bbm90aGVyTGludXhVc2VyL3Blbi9YcHZyTWc/ZWRpdG9ycz0wMDEyXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBhcnJcbiAgICAgKiBAcGFyYW0ge0FycmF5fSBleGNsdWRlZEVsZW1lbnRzXG4gICAgICogQHJldHVybnMgeyp8QXJyYXkuPFQ+fVxuICAgICAqL1xuICAgIHN0YXRpYyBmaWx0ZXJPdXQoYXJyLCBleGNsdWRlZEVsZW1lbnRzKSB7XG4gICAgICAgIHJldHVybiBhcnIuZmlsdGVyKGVsZW1lbnQgPT4gIXRoaXMuaXNJbkFycmF5KGVsZW1lbnQsIGV4Y2x1ZGVkRWxlbWVudHMpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmUgdGhlIHRyYWlsaW5nIHplcm9zIGluIHRoZSBkZWNpbWFsIHBhcnQgb2YgYSBudW1iZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gbnVtZXJpY1N0cmluZ1xuICAgICAqIEByZXR1cm5zIHsqfVxuICAgICAqL1xuICAgIHN0YXRpYyB0cmltUGFkZGVkWmVyb3NGcm9tRGVjaW1hbFBsYWNlcyhudW1lcmljU3RyaW5nKSB7XG4gICAgICAgIG51bWVyaWNTdHJpbmcgPSBTdHJpbmcobnVtZXJpY1N0cmluZyk7XG4gICAgICAgIGlmIChudW1lcmljU3RyaW5nID09PSAnJykge1xuICAgICAgICAgICAgcmV0dXJuICcnO1xuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgW2ludGVnZXJQYXJ0LCBkZWNpbWFsUGFydF0gPSBudW1lcmljU3RyaW5nLnNwbGl0KCcuJyk7XG4gICAgICAgIGlmICh0aGlzLmlzVW5kZWZpbmVkT3JOdWxsT3JFbXB0eShkZWNpbWFsUGFydCkpIHtcbiAgICAgICAgICAgIHJldHVybiBpbnRlZ2VyUGFydDtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHRyaW1tZWREZWNpbWFsUGFydCA9IGRlY2ltYWxQYXJ0LnJlcGxhY2UoLzArJC9nLCAnJyk7XG5cbiAgICAgICAgbGV0IHJlc3VsdDtcbiAgICAgICAgaWYgKHRyaW1tZWREZWNpbWFsUGFydCA9PT0gJycpIHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGludGVnZXJQYXJ0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcmVzdWx0ID0gYCR7aW50ZWdlclBhcnR9LiR7dHJpbW1lZERlY2ltYWxQYXJ0fWA7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgdG9wLW1vc3QgaG92ZXJlZCBpdGVtIGJ5IHRoZSBtb3VzZSBjdXJzb3IuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyB7Kn1cbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0SG92ZXJlZEVsZW1lbnQoKSB7XG4gICAgICAgIGNvbnN0IGhvdmVyZWRFbGVtZW50cyA9IFsuLi5kb2N1bWVudC5xdWVyeVNlbGVjdG9yQWxsKCc6aG92ZXInKV07XG4gICAgICAgIHJldHVybiBob3ZlcmVkRWxlbWVudHNbaG92ZXJlZEVsZW1lbnRzLmxlbmd0aCAtIDFdO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybiB0aGUgZ2l2ZW4gYXJyYXkgdHJpbW1lZCB0byB0aGUgZ2l2ZW4gbGVuZ3RoLlxuICAgICAqIEBleGFtcGxlIGFycmF5VHJpbShbMSwgMiwgMywgNF0sIDIpIC0+IFsxLCAyXVxuICAgICAqXG4gICAgICogQHBhcmFtIHtBcnJheX0gYXJyYXlcbiAgICAgKiBAcGFyYW0ge051bWJlcn0gbGVuZ3RoXG4gICAgICogQHJldHVybnMgeyp9XG4gICAgICovXG4gICAgc3RhdGljIGFycmF5VHJpbShhcnJheSwgbGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IGFyckxlbmd0aCA9IGFycmF5Lmxlbmd0aDtcbiAgICAgICAgaWYgKGFyckxlbmd0aCA9PT0gMCB8fCBsZW5ndGggPiBhcnJMZW5ndGgpIHtcbiAgICAgICAgICAgIC8vIEFsc28gbWFuYWdlIHRoZSBjYXNlIHdoZXJlIGBsZW5ndGhgIGlzIGhpZ2hlciB0aGFuIHRoZSBjdXJyZW50IGxlbmd0aFxuICAgICAgICAgICAgcmV0dXJuIGFycmF5O1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGxlbmd0aCA8IDApIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuXG4gICAgICAgIGFycmF5Lmxlbmd0aCA9IHBhcnNlSW50KGxlbmd0aCwgMTApO1xuXG4gICAgICAgIHJldHVybiBhcnJheTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXJnZSBhbGwgdGhlIGdpdmVuIGFycmF5cyBieSBrZWVwaW5nIG9ubHkgdW5pcXVlIGVsZW1lbnRzLCBhbmQgcmV0dXJuIGFuIGFycmF5IHdpdGggZGUtZHVwbGljYXRlZCB2YWx1ZXMuXG4gICAgICogY2YuIGh0dHA6Ly9zdGFja292ZXJmbG93LmNvbS9hLzI3NjY0OTcxLzI4MzQ4OThcbiAgICAgKlxuICAgICAqIEBwYXJhbSB7Li4uYXJyYXl9IGFycmF5c1xuICAgICAqIEByZXR1cm5zIHtbKl19XG4gICAgICovXG4gICAgc3RhdGljIGFycmF5VW5pcXVlKC4uLmFycmF5cykgeyAvL0ZJWE1FIMOgIHRlc3RlclxuICAgICAgICByZXR1cm4gWy4uLm5ldyBTZXQoW10uY29uY2F0KC4uLmFycmF5cykpXTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBNZXJnZSBhbGwgdGhlIGdpdmVuIE1hcHMgYnkga2VlcGluZyBvbmx5IHVuaXF1ZSBlbGVtZW50cywgYW5kIHJldHVybiBhIG5ldyBNYXAgd2l0aCBkZS1kdXBsaWNhdGVkIGtleXMuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gey4uLk1hcH0gbWFwT2JqZWN0c1xuICAgICAqIEByZXR1cm5zIHtNYXB9XG4gICAgICovXG4gICAgc3RhdGljIG1lcmdlTWFwcyguLi5tYXBPYmplY3RzKSB7XG4gICAgICAgIHJldHVybiBuZXcgTWFwKG1hcE9iamVjdHMucmVkdWNlKChhcywgYikgPT4gYXMuY29uY2F0KFsuLi5iXSksIFtdKSk7XG4gICAgfVxufVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL0F1dG9OdW1lcmljSGVscGVyLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==");

/***/ },
/* 4 */
/***/ function(module, exports, __webpack_require__) {

	eval("/*** IMPORTS FROM imports-loader ***/\n(function() {\n\n'use strict';\n\nvar _AutoNumeric = __webpack_require__(1);\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\\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*` option 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             * Fon 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             */\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 : Given the option { divisorWhenUnfocused: 1000 } (or directly in the html `<input data-divisor-when-unfocused=\"1000\">`)\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            /* 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 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 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            /* Allow the user to increment or decrement the element value with the mouse wheel.\n             * The wheel behavior can by modified by the `wheelStep` option.\n             * This `wheelStep` options 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             * A special behavior is applied in order to avoid preventing the user to scroll the page if the inputs are covering the whole available space.\n             * You can use the 'Shift' modifier key while using the mouse wheel in order to temporarily disable the increment/decrement feature (useful on small screen where some badly configured inputs could use all the available space).\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 if the element should have event listeners activated on it.\n             * By default, those event listeners are only added to <input> 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            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            /* The `rawValueDivisor` divides the formatted value shown in the AutoNumeric element and store the result in `rawValue`.\n             * @example { rawValueDivisor: '100' } or <input data-raw-value-divisor=\"100\">\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 <input> element should be set as read only on initialization.\n             * When set to `true`, then the `readonly` html property is added to the <input> 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 focus out.\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                        }, 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 ctrl again\n             */\n            unformatOnHover: {\n                unformat: true,\n                doNotUnformat: false\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            /* 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 <alexandre.bonneau@linuxfr.eu>\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}.call(window));//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvQXV0b051bWVyaWNPcHRpb25zLmpzP2NlNWQiXSwibmFtZXMiOlsiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXQiLCJhbGxvd0RlY2ltYWxQYWRkaW5nIiwiYWx3YXlzIiwibmV2ZXIiLCJmbG9hdHMiLCJjYXJldFBvc2l0aW9uT25Gb2N1cyIsInN0YXJ0IiwiZW5kIiwiZGVjaW1hbExlZnQiLCJkZWNpbWFsUmlnaHQiLCJkb05vRm9yY2VDYXJldFBvc2l0aW9uIiwiY3JlYXRlTG9jYWxMaXN0IiwiY3JlYXRlTGlzdCIsImRvTm90Q3JlYXRlTGlzdCIsImN1cnJlbmN5U3ltYm9sIiwibm9uZSIsImN1cnJlbmN5U2lnbiIsImF1c3RyYWwiLCJhdXN0cmFsQ2VudGF2byIsImJhaHQiLCJjZWRpIiwiY2VudCIsImNvbG9uIiwiY3J1emVpcm8iLCJkb2xsYXIiLCJkb25nIiwiZHJhY2htYSIsImRyYW0iLCJldXJvcGVhbiIsImV1cm8iLCJmbG9yaW4iLCJmcmFuYyIsImd1YXJhbmkiLCJocnl2bmlhIiwia2lwIiwiYXR0IiwibGVwdG9uIiwibGlyYSIsImxpcmFPbGQiLCJsYXJpIiwibWFyayIsIm1pbGwiLCJuYWlyYSIsInBlc2V0YSIsInBlc28iLCJwZmVubmlnIiwicG91bmQiLCJyZWFsIiwicmllbCIsInJ1YmxlIiwicnVwZWUiLCJydXBlZU9sZCIsInNoZWtlbCIsInNoZWtlbEFsdCIsInRha2EiLCJ0ZW5nZSIsInRvZ3JvZyIsIndvbiIsInllbiIsImN1cnJlbmN5U3ltYm9sUGxhY2VtZW50IiwicHJlZml4Iiwic3VmZml4IiwiZGVjaW1hbENoYXJhY3RlciIsImNvbW1hIiwiZG90IiwibWlkZGxlRG90IiwiYXJhYmljRGVjaW1hbFNlcGFyYXRvciIsImRlY2ltYWxTZXBhcmF0b3JLZXlTeW1ib2wiLCJkZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmUiLCJkZWNpbWFsUGxhY2VzIiwib25lIiwidHdvIiwidGhyZWUiLCJmb3VyIiwiZml2ZSIsInNpeCIsImRlY2ltYWxQbGFjZXNSYXdWYWx1ZSIsInVzZURlZmF1bHQiLCJkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIiLCJkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzIiwiZGVmYXVsdFZhbHVlT3ZlcnJpZGUiLCJkb05vdE92ZXJyaWRlIiwiZGlnaXRhbEdyb3VwU3BhY2luZyIsInR3b1NjYWxlZCIsImRpZ2l0R3JvdXBTZXBhcmF0b3IiLCJub3JtYWxTcGFjZSIsInRoaW5TcGFjZSIsIm5hcnJvd05vQnJlYWtTcGFjZSIsIm5vQnJlYWtTcGFjZSIsIm5vU2VwYXJhdG9yIiwiYXBvc3Ryb3BoZSIsImFyYWJpY1Rob3VzYW5kc1NlcGFyYXRvciIsImRvdEFib3ZlIiwiZGl2aXNvcldoZW5VbmZvY3VzZWQiLCJwZXJjZW50YWdlIiwicGVybWlsbGUiLCJiYXNpc1BvaW50IiwiZW1wdHlJbnB1dEJlaGF2aW9yIiwibnVsbCIsImZvY3VzIiwicHJlc3MiLCJ6ZXJvIiwiZmFpbE9uVW5rbm93bk9wdGlvbiIsImZhaWwiLCJpZ25vcmUiLCJmb3JtYXRPblBhZ2VMb2FkIiwiZm9ybWF0IiwiZG9Ob3RGb3JtYXQiLCJoaXN0b3J5U2l6ZSIsInZlcnlTbWFsbCIsInNtYWxsIiwibWVkaXVtIiwibGFyZ2UiLCJ2ZXJ5TGFyZ2UiLCJpbnNhbmUiLCJOdW1iZXIiLCJNQVhfU0FGRV9JTlRFR0VSIiwiaXNDYW5jZWxsYWJsZSIsImNhbmNlbGxhYmxlIiwibm90Q2FuY2VsbGFibGUiLCJsZWFkaW5nWmVybyIsImFsbG93IiwiZGVueSIsImtlZXAiLCJtYXhpbXVtVmFsdWUiLCJ0ZW5UcmlsbGlvbnMiLCJ0ZW5UcmlsbGlvbnNOb0RlY2ltYWxzIiwib25lQmlsbGlvbiIsIm1pbmltdW1WYWx1ZSIsIm1vZGlmeVZhbHVlT25XaGVlbCIsIm1vZGlmeVZhbHVlIiwiZG9Ob3RoaW5nIiwibmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIiLCJwYXJlbnRoZXNlcyIsImJyYWNrZXRzIiwiY2hldnJvbnMiLCJjdXJseUJyYWNlcyIsImFuZ2xlQnJhY2tldHMiLCJqYXBhbmVzZVF1b3RhdGlvbk1hcmtzIiwiaGFsZkJyYWNrZXRzIiwid2hpdGVTcXVhcmVCcmFja2V0cyIsInF1b3RhdGlvbk1hcmtzIiwiZ3VpbGxlbWV0cyIsIm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50IiwibGVmdCIsInJpZ2h0Iiwibm9FdmVudExpc3RlbmVycyIsIm5vRXZlbnRzIiwiYWRkRXZlbnRzIiwib25JbnZhbGlkUGFzdGUiLCJlcnJvciIsImNsYW1wIiwidHJ1bmNhdGUiLCJyZXBsYWNlIiwib3V0cHV0Rm9ybWF0Iiwic3RyaW5nIiwibnVtYmVyIiwibmVnYXRpdmVEb3QiLCJuZWdhdGl2ZUNvbW1hIiwiZG90TmVnYXRpdmUiLCJjb21tYU5lZ2F0aXZlIiwib3ZlcnJpZGVNaW5NYXhMaW1pdHMiLCJjZWlsaW5nIiwiZmxvb3IiLCJyYXdWYWx1ZURpdmlzb3IiLCJyZWFkT25seSIsInJlYWRXcml0ZSIsInJvdW5kaW5nTWV0aG9kIiwiaGFsZlVwU3ltbWV0cmljIiwiaGFsZlVwQXN5bW1ldHJpYyIsImhhbGZEb3duU3ltbWV0cmljIiwiaGFsZkRvd25Bc3ltbWV0cmljIiwiaGFsZkV2ZW5CYW5rZXJzUm91bmRpbmciLCJ1cFJvdW5kQXdheUZyb21aZXJvIiwiZG93blJvdW5kVG93YXJkWmVybyIsInRvQ2VpbGluZ1Rvd2FyZFBvc2l0aXZlSW5maW5pdHkiLCJ0b0Zsb29yVG93YXJkTmVnYXRpdmVJbmZpbml0eSIsInRvTmVhcmVzdDA1IiwidG9OZWFyZXN0MDVBbHQiLCJ1cFRvTmV4dDA1IiwiZG93blRvTmV4dDA1Iiwic2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSIsInNhdmUiLCJkb05vdFNhdmUiLCJzZWxlY3ROdW1iZXJPbmx5Iiwic2VsZWN0TnVtYmVyc09ubHkiLCJzZWxlY3RBbGwiLCJzZWxlY3RPbkZvY3VzIiwic2VsZWN0IiwiZG9Ob3RTZWxlY3QiLCJzZXJpYWxpemVTcGFjZXMiLCJwbHVzIiwicGVyY2VudCIsInNob3dPbmx5TnVtYmVyc09uRm9jdXMiLCJvbmx5TnVtYmVycyIsInNob3dBbGwiLCJzaG93UG9zaXRpdmVTaWduIiwic2hvdyIsImhpZGUiLCJzaG93V2FybmluZ3MiLCJzdHlsZVJ1bGVzIiwicG9zaXRpdmVOZWdhdGl2ZSIsInBvc2l0aXZlIiwibmVnYXRpdmUiLCJyYW5nZTBUbzEwMFdpdGg0U3RlcHMiLCJyYW5nZXMiLCJtaW4iLCJtYXgiLCJjbGFzcyIsImV2ZW5PZGQiLCJ1c2VyRGVmaW5lZCIsImNhbGxiYWNrIiwicmF3VmFsdWUiLCJjbGFzc2VzIiwicmFuZ2VTbWFsbEFuZFplcm8iLCJzdWZmaXhUZXh0Iiwic3ltYm9sV2hlblVuZm9jdXNlZCIsInVuZm9ybWF0T25Ib3ZlciIsInVuZm9ybWF0IiwiZG9Ob3RVbmZvcm1hdCIsInVuZm9ybWF0T25TdWJtaXQiLCJrZWVwQ3VycmVudFZhbHVlIiwid2hlZWxTdGVwIiwicHJvZ3Jlc3NpdmUiXSwibWFwcGluZ3MiOiI7Ozs7O0FBNkJBOzs7Ozs7QUFFQTs7O0FBR0FBLE9BQU9DLGNBQVAsd0JBQW1DLFNBQW5DLEVBQThDO0FBQzFDQyxPQUQwQyxpQkFDcEM7QUFDRixlQUFPO0FBQ0g7Ozs7OztBQU1BQyxpQ0FBcUI7QUFDakJDLHdCQUFRLElBRFM7QUFFakJDLHVCQUFRLEtBRlM7QUFHakJDLHdCQUFRO0FBSFMsYUFQbEI7O0FBYUg7Ozs7Ozs7QUFPQUMsa0NBQXNCO0FBQ2xCQyx1QkFBd0IsT0FETjtBQUVsQkMscUJBQXdCLEtBRk47QUFHbEJDLDZCQUF3QixhQUhOO0FBSWxCQyw4QkFBd0IsY0FKTjtBQUtsQkMsd0NBQXdCO0FBTE4sYUFwQm5COztBQTRCSDs7O0FBR0FDLDZCQUFpQjtBQUNiQyw0QkFBaUIsSUFESjtBQUViQyxpQ0FBaUI7QUFGSixhQS9CZDs7QUFvQ0g7Ozs7QUFJQUMsNEJBQWdCO0FBQ1pDLHNCQUFnQixFQURKO0FBRVpDLDhCQUFnQixHQUZKO0FBR1pDLHlCQUFnQixHQUhKLEVBR1M7QUFDckJDLGdDQUFn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a0I7QUFGSixhQXJxQmY7O0FBMHFCSDs7Ozs7Ozs7QUFRQUMsdUJBQVc7QUFDUEMsNkJBQWE7QUFETjtBQWxyQlIsU0FBUDtBQXNyQkg7QUF4ckJ5QyxDQUE5QyxFLENBbENBIiwiZmlsZSI6IjQuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE9wdGlvbnMgZm9yIGF1dG9OdW1lcmljLmpzXG4gKiBAYXV0aG9yIEFsZXhhbmRyZSBCb25uZWF1IDxhbGV4YW5kcmUuYm9ubmVhdUBsaW51eGZyLmV1PlxuICogQGNvcHlyaWdodCDCqSAyMDE2IEFsZXhhbmRyZSBCb25uZWF1XG4gKlxuICogVGhlIE1JVCBMaWNlbnNlIChodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocClcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvblxuICogb2J0YWluaW5nIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb25cbiAqIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dFxuICogcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsXG4gKiBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWIgbGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZVxuICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmdcbiAqIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsXG4gKiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVNcbiAqIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EXG4gKiBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVFxuICogSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksXG4gKiBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1JcbiAqIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgQXV0b051bWVyaWMgZnJvbSAnLi9BdXRvTnVtZXJpYyc7XG5cbi8qKlxuICogT3B0aW9ucyB2YWx1ZXMgZW51bWVyYXRpb25cbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KEF1dG9OdW1lcmljLCAnb3B0aW9ucycsIHtcbiAgICBnZXQoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAvKiBEZWZpbmVzIGlmIHRoZSBkZWNpbWFsIHBsYWNlcyBzaG91bGQgYmUgcGFkZGVkIHdpdGggemVyb2VzXG4gICAgICAgICAgICAgKiBgdHJ1ZWAgICAgIDogYWx3YXlzIHBhZCBkZWNpbWFscyB3aXRoIHplcm9zIChpZS4gJzEyLjM0MDAnKVxuICAgICAgICAgICAgICogYGZhbHNlYCAgICA6IG5ldmVyIHBhZCB3aXRoIHplcm9zIChpZS4gJzEyLjM0JylcbiAgICAgICAgICAgICAqIGAnZmxvYXRzJ2AgOiBwYWQgd2l0aCB6ZXJvZXMgb25seSB3aGVuIHRoZXJlIGFyZSBkZWNpbWFscyAoaWUuICcxMicgYW5kICcxMi4zNDAwJylcbiAgICAgICAgICAgICAqIE5vdGU6IHNldHRpbmcgYWxsb3dEZWNpbWFsUGFkZGluZyB0byAnZmFsc2UnIHdpbGwgb3ZlcnJpZGUgdGhlICdkZWNpbWFsUGxhY2VzJyBzZXR0aW5nLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBhbGxvd0RlY2ltYWxQYWRkaW5nOiB7XG4gICAgICAgICAgICAgICAgYWx3YXlzOiB0cnVlLFxuICAgICAgICAgICAgICAgIG5ldmVyIDogZmFsc2UsXG4gICAgICAgICAgICAgICAgZmxvYXRzOiAnZmxvYXRzJyxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgd2hlcmUgc2hvdWxkIGJlIHBvc2l0aW9uZWQgdGhlIGNhcmV0IG9uIGZvY3VzXG4gICAgICAgICAgICAgKiBudWxsIDogRG8gbm90IGVuZm9yY2UgYW55IGNhcmV0IHBvc2l0aW9uaW5nIG9uIGZvY3VzICh0aGlzIGlzIG5lZWRlZCB3aGVuIHVzaW5nIGBzZWxlY3RPbkZvY3VzYClcbiAgICAgICAgICAgICAqIGAnc3RhcnQnYCA6IHB1dCB0aGUgY2FyZXQgb2YgdGhlIGZhciBsZWZ0IHNpZGUgb2YgdGhlIHZhbHVlIChleGNsdWRpbmcgdGhlIHBvc2l0aXZlL25lZ2F0aXZlIHNpZ24gYW5kIGN1cnJlbmN5IHN5bWJvbCwgaWYgYW55KVxuICAgICAgICAgICAgICogYCdlbmQnYCA6IHB1dCB0aGUgY2FyZXQgb2YgdGhlIGZhciByaWdodCBzaWRlIG9mIHRoZSB2YWx1ZSAoZXhjbHVkaW5nIHRoZSBwb3NpdGl2ZS9uZWdhdGl2ZSBzaWduIGFuZCBjdXJyZW5jeSBzeW1ib2wsIGlmIGFueSlcbiAgICAgICAgICAgICAqIGAnZGVjaW1hbExlZnQnYCA6IHB1dCB0aGUgY2FyZXQgb2YgdGhlIGxlZnQgb2YgdGhlIGRlY2ltYWwgY2hhcmFjdGVyIGlmIGFueVxuICAgICAgICAgICAgICogYCdkZWNpbWFsUmlnaHQnYCA6IHB1dCB0aGUgY2FyZXQgb2YgdGhlIHJpZ2h0IG9mIHRoZSBkZWNpbWFsIGNoYXJhY3RlciBpZiBhbnlcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgY2FyZXRQb3NpdGlvbk9uRm9jdXM6IHtcbiAgICAgICAgICAgICAgICBzdGFydCAgICAgICAgICAgICAgICAgOiAnc3RhcnQnLFxuICAgICAgICAgICAgICAgIGVuZCAgICAgICAgICAgICAgICAgICA6ICdlbmQnLFxuICAgICAgICAgICAgICAgIGRlY2ltYWxMZWZ0ICAgICAgICAgICA6ICdkZWNpbWFsTGVmdCcsXG4gICAgICAgICAgICAgICAgZGVjaW1hbFJpZ2h0ICAgICAgICAgIDogJ2RlY2ltYWxSaWdodCcsXG4gICAgICAgICAgICAgICAgZG9Ob0ZvcmNlQ2FyZXRQb3NpdGlvbjogbnVsbCxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgaWYgYSBsb2NhbCBsaXN0IG9mIEF1dG9OdW1lcmljIG9iamVjdHMgc2hvdWxkIGJlIGtlcHQgd2hlbiBpbml0aWFsaXppbmcgdGhpcyBvYmplY3QuXG4gICAgICAgICAgICAgKiBUaGlzIGxpc3QgaXMgdXNlZCBieSB0aGUgYGdsb2JhbC4qYCBmdW5jdGlvbnMuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGNyZWF0ZUxvY2FsTGlzdDoge1xuICAgICAgICAgICAgICAgIGNyZWF0ZUxpc3QgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBkb05vdENyZWF0ZUxpc3Q6IGZhbHNlLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyB0aGUgY3VycmVuY3kgc3ltYm9sIHN0cmluZy5cbiAgICAgICAgICAgICAqIEl0IGNhbiBiZSBhIHN0cmluZyBvZiBtb3JlIHRoYW4gb25lIGNoYXJhY3RlciAoYWxsb3dpbmcgZm9yIGluc3RhbmNlIHRvIHVzZSBhIHNwYWNlIG9uIGVpdGhlciBzaWRlIG9mIGl0LCBleGFtcGxlOiAnJCAnIG9yICcgJCcpXG4gICAgICAgICAgICAgKiBjZi4gaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ3VycmVuY3lfc3ltYm9sXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGN1cnJlbmN5U3ltYm9sOiB7XG4gICAgICAgICAgICAgICAgbm9uZSAgICAgICAgICA6ICcnLFxuICAgICAgICAgICAgICAgIGN1cnJlbmN5U2lnbiAgOiAnwqQnLFxuICAgICAgICAgICAgICAgIGF1c3RyYWwgICAgICAgOiAn4oKzJywgLy8gQVJBXG4gICAgICAgICAgICAgICAgYXVzdHJhbENlbnRhdm86ICfCoicsXG4gICAgICAgICAgICAgICAgYmFodCAgICAgICAgICA6ICfguL8nLCAvLyBUSEJcbiAgICAgICAgICAgICAgICBjZWRpICAgICAgICAgIDogJ+KCtScsIC8vIEdIU1xuICAgICAgICAgICAgICAgIGNlbnQgICAgICAgICAgOiAnwqInLFxuICAgICAgICAgICAgICAgIGNvbG9uICAgICAgICAgOiAn4oKhJywgLy8gQ1JDXG4gICAgICAgICAgICAgICAgY3J1emVpcm8gICAgICA6ICfigqInLCAvLyBCUkIgLSBOb3QgdXNlZCBhbnltb3JlIHNpbmNlIDE5OTNcbiAgICAgICAgICAgICAgICBkb2xsYXIgICAgICAgIDogJyQnLFxuICAgICAgICAgICAgICAgIGRvbmcgICAgICAgICAgOiAn4oKrJywgLy8gVk5EXG4gICAgICAgICAgICAgICAgZHJhY2htYSAgICAgICA6ICfigq8nLCAvLyBHUkQgKG9yICfOlM+Bz4cuJyBvciAnzpTPgS4nKVxuICAgICAgICAgICAgICAgIGRyYW0gICAgICAgICAgOiAn4oCL1o8nLCAvLyBBTURcbiAgICAgICAgICAgICAgICBldXJvcGVhbiAgICAgIDogJ+KCoCcsIC8vIFhFVSAob2xkIGN1cnJlbmN5IGJlZm9yZSB0aGUgRXVybylcbiAgICAgICAgICAgICAgICBldXJvICAgICAgICAgIDogJ+KCrCcsIC8vIEVVUlxuICAgICAgICAgICAgICAgIGZsb3JpbiAgICAgICAgOiAnxpInLFxuICAgICAgICAgICAgICAgIGZyYW5jICAgICAgICAgOiAn4oKjJywgLy8gRlJGXG4gICAgICAgICAgICAgICAgZ3VhcmFuaSAgICAgICA6ICfigrInLCAvLyBQWUdcbiAgICAgICAgICAgICAgICBocnl2bmlhICAgICAgIDogJ+KCtCcsIC8vINCz0YDQvVxuICAgICAgICAgICAgICAgIGtpcCAgICAgICAgICAgOiAn4oKtJywgLy8gTEFLXG4gICAgICAgICAgICAgICAgYXR0ICAgICAgICAgICA6ICfguq3gurHgupQnLCAvLyBjZW50cyBvZiB0aGUgS2lwXG4gICAgICAgICAgICAgICAgbGVwdG9uICAgICAgICA6ICfOmy4nLCAvLyBjZW50cyBvZiB0aGUgRHJhY2htYVxuICAgICAgICAgICAgICAgIGxpcmEgICAgICAgICAgOiAn4oK6JywgLy8gVFJZXG4gICAgICAgICAgICAgICAgbGlyYU9sZCAgICAgICA6ICfigqQnLFxuICAgICAgICAgICAgICAgIGxhcmkgICAgICAgICAgOiAn4oK+JywgLy8gR0VMXG4gICAgICAgICAgICAgICAgbWFyayAgICAgICAgICA6ICfihLMnLFxuICAgICAgICAgICAgICAgIG1pbGwgICAgICAgICAgOiAn4oKlJyxcbiAgICAgICAgICAgICAgICBuYWlyYSAgICAgICAgIDogJ+KCpicsIC8vIE5HTlxuICAgICAgICAgICAgICAgIHBlc2V0YSAgICAgICAgOiAn4oKnJyxcbiAgICAgICAgICAgICAgICBwZXNvICAgICAgICAgIDogJ+KCsScsIC8vIFBIUFxuICAgICAgICAgICAgICAgIHBmZW5uaWcgICAgICAgOiAn4oKwJywgLy8gY2VudHMgb2YgdGhlIE1hcmtcbiAgICAgICAgICAgICAgICBwb3VuZCAgICAgICAgIDogJ8KjJyxcbiAgICAgICAgICAgICAgICByZWFsICAgICAgICAgIDogJ1IkJywgLy8gQnJhemlsaWFuIHJlYWxcbiAgICAgICAgICAgICAgICByaWVsICAgICAgICAgIDogJ+GfmycsIC8vIEtIUlxuICAgICAgICAgICAgICAgIHJ1YmxlICAgICAgICAgOiAn4oK9JywgLy8gUlVCXG4gICAgICAgICAgICAgICAgcnVwZWUgICAgICAgICA6ICfigrknLCAvLyBJTlJcbiAgICAgICAgICAgICAgICBydXBlZU9sZCAgICAgIDogJ+KCqCcsXG4gICAgICAgICAgICAgICAgc2hla2VsICAgICAgICA6ICfigqonLFxuICAgICAgICAgICAgICAgIHNoZWtlbEFsdCAgICAgOiAn16nXtNeX4oCO4oCOJyxcbiAgICAgICAgICAgICAgICB0YWthICAgICAgICAgIDogJ+CnsycsIC8vIEJEVFxuICAgICAgICAgICAgICAgIHRlbmdlICAgICAgICAgOiAn4oK4JywgLy8gS1pUXG4gICAgICAgICAgICAgICAgdG9ncm9nICAgICAgICA6ICfigq4nLCAvLyBNTlRcbiAgICAgICAgICAgICAgICB3b24gICAgICAgICAgIDogJ+KCqScsXG4gICAgICAgICAgICAgICAgeWVuICAgICAgICAgICA6ICfCpScsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIHdoZXJlIHRoZSBjdXJyZW5jeSBzeW1ib2wgc2hvdWxkIGJlIHBsYWNlZCAoYmVmb3JlIG9mIGFmdGVyIHRoZSBudW1iZXJzKVxuICAgICAgICAgICAgICogZm9yIHByZWZpeCBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudDogXCJwXCIgKGRlZmF1bHQpXG4gICAgICAgICAgICAgKiBmb3Igc3VmZml4IGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50OiBcInNcIlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudDoge1xuICAgICAgICAgICAgICAgIHByZWZpeDogJ3AnLFxuICAgICAgICAgICAgICAgIHN1ZmZpeDogJ3MnLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyB3aGF0IGRlY2ltYWwgc2VwYXJhdG9yIGNoYXJhY3RlciBpcyB1c2VkXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGRlY2ltYWxDaGFyYWN0ZXI6IHtcbiAgICAgICAgICAgICAgICBjb21tYSAgICAgICAgICAgICAgICAgICAgOiAnLCcsXG4gICAgICAgICAgICAgICAgZG90ICAgICAgICAgICAgICAgICAgICAgIDogJy4nLFxuICAgICAgICAgICAgICAgIG1pZGRsZURvdCAgICAgICAgICAgICAgICA6ICfCtycsXG4gICAgICAgICAgICAgICAgYXJhYmljRGVjaW1hbFNlcGFyYXRvciAgIDogJ9mrJyxcbiAgICAgICAgICAgICAgICBkZWNpbWFsU2VwYXJhdG9yS2V5U3ltYm9sOiAn4o6WJyxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIEFsbG93IHRvIGRlY2xhcmUgYW4gYWx0ZXJuYXRpdmUgZGVjaW1hbCBzZXBhcmF0b3Igd2hpY2ggaXMgYXV0b21hdGljYWxseSByZXBsYWNlZCBieSBgZGVjaW1hbENoYXJhY3RlcmAgd2hlbiB0eXBlZC5cbiAgICAgICAgICAgICAqIFRoaXMgaXMgdXNlZCBieSBjb3VudHJpZXMgdGhhdCB1c2UgYSBjb21tYSBcIixcIiBhcyB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgYW5kIGhhdmUga2V5Ym9hcmRzXFxudW1lcmljIHBhZHMgdGhhdCBoYXZlXG4gICAgICAgICAgICAgKiBhIHBlcmlvZCAnZnVsbCBzdG9wJyBhcyB0aGUgZGVjaW1hbCBjaGFyYWN0ZXIgKEZyYW5jZSBvciBTcGFpbiBmb3IgaW5zdGFuY2UpLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmU6IHtcbiAgICAgICAgICAgICAgICBub25lIDogbnVsbCxcbiAgICAgICAgICAgICAgICBjb21tYTogJywnLFxuICAgICAgICAgICAgICAgIGRvdCAgOiAnLicsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIHRoZSBkZWZhdWx0IG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0byBzaG93IG9uIHRoZSBmb3JtYXR0ZWQgdmFsdWUsIGFuZCBrZWVwIGZvciB0aGUgcHJlY2lzaW9uLlxuICAgICAgICAgICAgICogSW5jaWRlbnRhbGx5LCBzaW5jZSB3ZSBuZWVkIHRvIGJlIGFibGUgdG8gc2hvdyB0aGF0IG1hbnkgZGVjaW1hbCBwbGFjZXMsIHRoaXMgYWxzbyBkZWZpbmVzIHRoZSByYXcgdmFsdWUgcHJlY2lzaW9uIGJ5IGRlZmF1bHQuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXM6IHtcbiAgICAgICAgICAgICAgICBub25lIDogMCxcbiAgICAgICAgICAgICAgICBvbmUgIDogMSxcbiAgICAgICAgICAgICAgICB0d28gIDogMixcbiAgICAgICAgICAgICAgICB0aHJlZTogMyxcbiAgICAgICAgICAgICAgICBmb3VyIDogNCxcbiAgICAgICAgICAgICAgICBmaXZlIDogNSxcbiAgICAgICAgICAgICAgICBzaXggIDogNixcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgaG93IG1hbnkgZGVjaW1hbCBwbGFjZXMgc2hvdWxkIGJlIGtlcHQgZm9yIHRoZSByYXcgdmFsdWUgKGllLiBUaGlzIGlzIHRoZSBwcmVjaXNpb24gZm9yIGZsb2F0IHZhbHVlcykuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogSWYgdGhpcyBvcHRpb24gaXMgc2V0IHRvIGBudWxsYCAod2hpY2ggaXMgdGhlIGRlZmF1bHQpLCB0aGVuIHRoZSB2YWx1ZSBvZiBgZGVjaW1hbFBsYWNlc2AgaXMgdXNlZCBmb3IgYGRlY2ltYWxQbGFjZXNSYXdWYWx1ZWAgYXMgd2VsbC5cbiAgICAgICAgICAgICAqIE5vdGU6IFNldHRpbmcgdGhpcyB0byBhIGxvd2VyIG51bWJlciBvZiBkZWNpbWFsIHBsYWNlcyB0aGFuIHRoZSBvbmUgdG8gYmUgc2hvd24gd2lsbCBsZWFkIHRvIGNvbmZ1c2lvbiBmb3IgdGhlIHVzZXJzLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzUmF3VmFsdWU6IHtcbiAgICAgICAgICAgICAgICB1c2VEZWZhdWx0OiBudWxsLFxuICAgICAgICAgICAgICAgIG5vbmUgICAgICA6IDAsXG4gICAgICAgICAgICAgICAgb25lICAgICAgIDogMSxcbiAgICAgICAgICAgICAgICB0d28gICAgICAgOiAyLFxuICAgICAgICAgICAgICAgIHRocmVlICAgICA6IDMsXG4gICAgICAgICAgICAgICAgZm91ciAgICAgIDogNCxcbiAgICAgICAgICAgICAgICBmaXZlICAgICAgOiA1LFxuICAgICAgICAgICAgICAgIHNpeCAgICAgICA6IDYsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIGhvdyBtYW55IGRlY2ltYWwgcGxhY2VzIHNob3VsZCBiZSB2aXNpYmxlIHdoZW4gdGhlIGVsZW1lbnQgaXMgdW5mb2N1c2VkLlxuICAgICAgICAgICAgICogSWYgdGhpcyBpcyBzZXQgdG8gYG51bGxgLCB0aGVuIHRoaXMgb3B0aW9uIGlzIGlnbm9yZWQsIGFuZCB0aGUgYGRlY2ltYWxQbGFjZXNgIG9wdGlvbiB2YWx1ZSB3aWxsIGJlIHVzZWQgaW5zdGVhZC5cbiAgICAgICAgICAgICAqIFRoaXMgbWVhbnMgdGhpcyBpcyBvcHRpb25hbCA7IGlmIG9taXR0ZWQgdGhlIGRlY2ltYWwgcGxhY2VzIHdpbGwgYmUgdGhlIHNhbWUgd2hlbiB0aGUgaW5wdXQgaGFzIHRoZSBmb2N1cy5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBUaGlzIG9wdGlvbiBjYW4gYmUgdXNlZCBpbiBjb25qb25jdGlvbiB3aXRoIHRoZSB0d28gb3RoZXIgYHNjYWxlKmAgb3B0aW9ucywgd2hpY2ggYWxsb3dzIHRvIGRpc3BsYXkgYSBkaWZmZXJlbnQgZm9ybWF0dGVkIHZhbHVlIHdoZW4gdGhlIGVsZW1lbnQgaXMgdW5mb2N1c2VkLCB3aGlsZSBhbm90aGVyIGZvcm1hdHRlZCB2YWx1ZSBpcyBzaG93biB3aGVuIGZvY3VzZWQuXG4gICAgICAgICAgICAgKiBGb3IgdGhvc2UgYHNjYWxlKmAgb3B0aW9uIHRvIGhhdmUgYW55IGVmZmVjdCwgYGRpdmlzb3JXaGVuVW5mb2N1c2VkYCBtdXN0IG5vdCBiZSBgbnVsbGAuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1cjoge1xuICAgICAgICAgICAgICAgIHVzZURlZmF1bHQ6IG51bGwsXG4gICAgICAgICAgICAgICAgbm9uZSAgICAgIDogMCxcbiAgICAgICAgICAgICAgICBvbmUgICAgICAgOiAxLFxuICAgICAgICAgICAgICAgIHR3byAgICAgICA6IDIsXG4gICAgICAgICAgICAgICAgdGhyZWUgICAgIDogMyxcbiAgICAgICAgICAgICAgICBmb3VyICAgICAgOiA0LFxuICAgICAgICAgICAgICAgIGZpdmUgICAgICA6IDUsXG4gICAgICAgICAgICAgICAgc2l4ICAgICAgIDogNixcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgaG93IG1hbnkgZGVjaW1hbCBwbGFjZXMgc2hvdWxkIGJlIHZpc2libGUgd2hlbiB0aGUgZWxlbWVudCBoYXMgdGhlIGZvY3VzLlxuICAgICAgICAgICAgICogSWYgdGhpcyBpcyBzZXQgdG8gYG51bGxgLCB0aGVuIHRoaXMgb3B0aW9uIGlzIGlnbm9yZWQsIGFuZCB0aGUgYGRlY2ltYWxQbGFjZXNgIG9wdGlvbiB2YWx1ZSB3aWxsIGJlIHVzZWQgaW5zdGVhZC5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBFeGFtcGxlOlxuICAgICAgICAgICAgICogRm9uIGluc3RhbmNlIGlmIGBkZWNpbWFsUGxhY2VzU2hvd25PbkZvY3VzYCBpcyBzZXQgdG8gYDVgIGFuZCB0aGUgZGVmYXVsdCBudW1iZXIgb2YgZGVjaW1hbCBwbGFjZXMgaXMgYDJgLCB0aGVuIG9uIGZvY3VzIGAxLDAwMC4xMjM0NWAgd2lsbCBiZSBzaG93biwgd2hpbGUgd2l0aG91dCBmb2N1cyBgMSwwMDAuMTJgIHdpbGwgYmUgc2V0IGJhY2suXG4gICAgICAgICAgICAgKiBOb3RlIDE6IHRoZSByZXN1bHRzIGRlcGVuZHMgb24gdGhlIHJvdW5kaW5nIG1ldGhvZCB1c2VkLlxuICAgICAgICAgICAgICogTm90ZSAyOiB0aGUgYGdldE51bWVyaWNTdHJpbmcoKWAgbWV0aG9kIHJldHVybnMgdGhlIGV4dGVuZGVkIGRlY2ltYWwgcGxhY2VzXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXM6IHtcbiAgICAgICAgICAgICAgICB1c2VEZWZhdWx0OiBudWxsLFxuICAgICAgICAgICAgICAgIG5vbmUgICAgICA6IDAsXG4gICAgICAgICAgICAgICAgb25lICAgICAgIDogMSxcbiAgICAgICAgICAgICAgICB0d28gICAgICAgOiAyLFxuICAgICAgICAgICAgICAgIHRocmVlICAgICA6IDMsXG4gICAgICAgICAgICAgICAgZm91ciAgICAgIDogNCxcbiAgICAgICAgICAgICAgICBmaXZlICAgICAgOiA1LFxuICAgICAgICAgICAgICAgIHNpeCAgICAgICA6IDYsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBIZWxwZXIgb3B0aW9uIGZvciBBU1AuTkVUIHBvc3RiYWNrXG4gICAgICAgICAgICAgKiBUaGlzIHNob3VsZCBiZSBzZXQgYXMgdGhlIHZhbHVlIG9mIHRoZSB1bmZvcm1hdHRlZCBkZWZhdWx0IHZhbHVlXG4gICAgICAgICAgICAgKiBleGFtcGxlczpcbiAgICAgICAgICAgICAqIG5vIGRlZmF1bHQgdmFsdWU9XCJcIiB7ZGVmYXVsdFZhbHVlT3ZlcnJpZGU6IFwiXCJ9XG4gICAgICAgICAgICAgKiB2YWx1ZT0xMjM0LjU2IHtkZWZhdWx0VmFsdWVPdmVycmlkZTogJzEyMzQuNTYnfVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBkZWZhdWx0VmFsdWVPdmVycmlkZToge1xuICAgICAgICAgICAgICAgIGRvTm90T3ZlcnJpZGU6IG51bGwsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIGhvdyBtYW55IG51bWJlcnMgc2hvdWxkIGJlIGdyb3VwZWQgdG9nZXRoZXIgKHVzdWFsbHkgZm9yIHRoZSB0aG91c2FuZCBzZXBhcmF0b3IpXG4gICAgICAgICAgICAgKiAtIFwiMlwiLCAgcmVzdWx0cyBpbiA5OSw5OSw5OSw5OTkgSW5kaWEncyBsYWtoc1xuICAgICAgICAgICAgICogLSBcIjJzXCIsIHJlc3VsdHMgaW4gOTksOTk5LDk5LDk5LDk5OSBJbmRpYSdzIGxha2hzIHNjYWxlZFxuICAgICAgICAgICAgICogLSBcIjNcIiwgIHJlc3VsdHMgaW4gOTk5LDk5OSw5OTkgKGRlZmF1bHQpXG4gICAgICAgICAgICAgKiAtIFwiNFwiLCAgcmVzdWx0cyBpbiA5OTk5LDk5OTksOTk5OSB1c2VkIGluIHNvbWUgQXNpYW4gY291bnRyaWVzXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGRpZ2l0YWxHcm91cFNwYWNpbmc6IHtcbiAgICAgICAgICAgICAgICB0d28gICAgICA6ICcyJyxcbiAgICAgICAgICAgICAgICB0d29TY2FsZWQ6ICcycycsXG4gICAgICAgICAgICAgICAgdGhyZWUgICAgOiAnMycsXG4gICAgICAgICAgICAgICAgZm91ciAgICAgOiAnNCcsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIHRoZSB0aG91c2FuZCBncm91cGluZyBzZXBhcmF0b3IgY2hhcmFjdGVyXG4gICAgICAgICAgICAgKiBFeGFtcGxlIDogSWYgYCcuJ2AgaXMgc2V0LCB0aGVuIHlvdSdsbCBnZXQgYCcxLjIzNC41NjcnYFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBkaWdpdEdyb3VwU2VwYXJhdG9yOiB7XG4gICAgICAgICAgICAgICAgY29tbWEgICAgICAgICAgICAgICAgICAgOiAnLCcsXG4gICAgICAgICAgICAgICAgZG90ICAgICAgICAgICAgICAgICAgICAgOiAnLicsXG4gICAgICAgICAgICAgICAgbm9ybWFsU3BhY2UgICAgICAgICAgICAgOiAnICcsXG4gICAgICAgICAgICAgICAgdGhpblNwYWNlICAgICAgICAgICAgICAgOiAnXFx1MjAwOScsXG4gICAgICAgICAgICAgICAgbmFycm93Tm9CcmVha1NwYWNlICAgICAgOiAnXFx1MjAyZicsXG4gICAgICAgICAgICAgICAgbm9CcmVha1NwYWNlICAgICAgICAgICAgOiAnXFx1MDBhMCcsXG4gICAgICAgICAgICAgICAgbm9TZXBhcmF0b3IgICAgICAgICAgICAgOiAnJyxcbiAgICAgICAgICAgICAgICBhcG9zdHJvcGhlICAgICAgICAgICAgICA6IGAnYCxcbiAgICAgICAgICAgICAgICBhcmFiaWNUaG91c2FuZHNTZXBhcmF0b3I6ICfZrCcsXG4gICAgICAgICAgICAgICAgZG90QWJvdmUgICAgICAgICAgICAgICAgOiAny5knLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogVGhlIGBkaXZpc29yV2hlblVuZm9jdXNlZGAgZGl2aWRlIHRoZSBlbGVtZW50IHZhbHVlIG9uIGZvY3VzLlxuICAgICAgICAgICAgICogT24gYmx1ciwgdGhlIGVsZW1lbnQgdmFsdWUgaXMgbXVsdGlwbGllZCBiYWNrLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIEV4YW1wbGUgOiBHaXZlbiB0aGUgb3B0aW9uIHsgZGl2aXNvcldoZW5VbmZvY3VzZWQ6IDEwMDAgfSAob3IgZGlyZWN0bHkgaW4gdGhlIGh0bWwgYDxpbnB1dCBkYXRhLWRpdmlzb3Itd2hlbi11bmZvY3VzZWQ9XCIxMDAwXCI+YClcbiAgICAgICAgICAgICAqIFRoZSBkaXZpc29yIHZhbHVlIGRvZXMgbm90IG5lZWQgdG8gYmUgYW4gaW50ZWdlciwgYnV0IHBsZWFzZSB1bmRlcnN0YW5kIHRoYXQgSmF2YXNjcmlwdCBoYXMgbGltaXRlZCBhY2N1cmFjeSBpbiBtYXRoIDsgdXNlIHdpdGggY2F1dGlvbi5cbiAgICAgICAgICAgICAqIE5vdGU6IFRoZSBgZ2V0TnVtZXJpY1N0cmluZ2AgbWV0aG9kIHJldHVybnMgdGhlIGZ1bGwgdmFsdWUsIGluY2x1ZGluZyB0aGUgJ2hpZGRlbicgZGVjaW1hbHMuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGRpdmlzb3JXaGVuVW5mb2N1c2VkOiB7XG4gICAgICAgICAgICAgICAgbm9uZSAgICAgIDogbnVsbCxcbiAgICAgICAgICAgICAgICBwZXJjZW50YWdlOiAxMDAsXG4gICAgICAgICAgICAgICAgcGVybWlsbGUgIDogMTAwMCxcbiAgICAgICAgICAgICAgICBiYXNpc1BvaW50OiAxMDAwMCxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgd2hhdCBzaG91bGQgYmUgZGlzcGxheWVkIGluIHRoZSBlbGVtZW50IGlmIHRoZSByYXcgdmFsdWUgaXMgYW4gZW1wdHkgc3RyaW5nICgnJykuXG4gICAgICAgICAgICAgKiAtICdmb2N1cycgIDogVGhlIGN1cnJlbmN5IHNpZ24gaXMgZGlzcGxheWVkIHdoZW4gdGhlIGlucHV0IHJlY2VpdmVzIGZvY3VzIChkZWZhdWx0KVxuICAgICAgICAgICAgICogLSAncHJlc3MnICA6IFRoZSBjdXJyZW5jeSBzaWduIGlzIGRpc3BsYXllZCB3aGVuZXZlciBhIGtleSBpcyBiZWluZyBwcmVzc2VkXG4gICAgICAgICAgICAgKiAtICdhbHdheXMnIDogVGhlIGN1cnJlbmN5IHNpZ24gaXMgYWx3YXlzIGRpc3BsYXllZFxuICAgICAgICAgICAgICogLSAnemVybycgICA6IEEgemVybyBpcyBkaXNwbGF5ZWQgKCdyb3VuZGVkJyB3aXRoIG9yIHdpdGhvdXQgYSBjdXJyZW5jeSBzaWduKSBpZiB0aGUgaW5wdXQgaGFzIG5vIHZhbHVlIG9uIGZvY3VzIG91dFxuICAgICAgICAgICAgICogLSAnbnVsbCcgICA6IFdoZW4gdGhlIGVsZW1lbnQgaXMgZW1wdHksIHRoZSBgcmF3VmFsdWVgIGFuZCB0aGUgZWxlbWVudCB2YWx1ZS90ZXh0IGlzIHNldCB0byBgbnVsbGAuIFRoaXMgYWxzbyBhbGxvd3MgdG8gc2V0IHRoZSB2YWx1ZSB0byBgbnVsbGAgdXNpbmcgYGFuRWxlbWVudC5zZXQobnVsbClgLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBlbXB0eUlucHV0QmVoYXZpb3I6IHtcbiAgICAgICAgICAgICAgICBudWxsICA6ICdudWxsJyxcbiAgICAgICAgICAgICAgICBmb2N1cyA6ICdmb2N1cycsXG4gICAgICAgICAgICAgICAgcHJlc3MgOiAncHJlc3MnLFxuICAgICAgICAgICAgICAgIGFsd2F5czogJ2Fsd2F5cycsXG4gICAgICAgICAgICAgICAgemVybyAgOiAnemVybycsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBUaGlzIG9wdGlvbiBpcyB0aGUgJ3N0cmljdCBtb2RlJyAoYWthICdkZWJ1ZycgbW9kZSksIHdoaWNoIGFsbG93cyBhdXRvTnVtZXJpYyB0byBzdHJpY3RseSBhbmFseXNlIHRoZSBvcHRpb25zIHBhc3NlZCwgYW5kIGZhaWxzIGlmIGFuIHVua25vd24gb3B0aW9ucyBpcyB1c2VkIGluIHRoZSBzZXR0aW5ncyBvYmplY3QuXG4gICAgICAgICAgICAgKiBZb3Ugc2hvdWxkIHNldCB0aGF0IHRvIGB0cnVlYCBpZiB5b3Ugd2FudCB0byBtYWtlIHN1cmUgeW91IGFyZSBvbmx5IHVzaW5nICdwdXJlJyBhdXRvTnVtZXJpYyBzZXR0aW5ncyBvYmplY3RzIGluIHlvdXIgY29kZS5cbiAgICAgICAgICAgICAqIElmIHlvdSBzZWUgdW5jYXVnaHQgZXJyb3JzIGluIHRoZSBjb25zb2xlIGFuZCB5b3VyIGNvZGUgc3RhcnRzIHRvIGZhaWwsIHRoaXMgbWVhbnMgc29tZWhvdyB0aG9zZSBvcHRpb25zIGdldHMgcG9sbHV0ZWQgYnkgYW5vdGhlciBwcm9ncmFtICh3aGljaCB1c3VhbGx5IGhhcHBlbnMgd2hlbiB1c2luZyBmcmFtZXdvcmtzKS5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgZmFpbE9uVW5rbm93bk9wdGlvbjoge1xuICAgICAgICAgICAgICAgIGZhaWwgIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBpZ25vcmU6IGZhbHNlLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGV0ZXJtaW5lIGlmIHRoZSBkZWZhdWx0IHZhbHVlIHdpbGwgYmUgZm9ybWF0dGVkIG9uIGluaXRpYWxpemF0aW9uLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBmb3JtYXRPblBhZ2VMb2FkOiB7XG4gICAgICAgICAgICAgICAgZm9ybWF0ICAgICA6IHRydWUsIC8vIGF1dG9tYXRpY2FsbHkgZm9ybWF0cyB0aGUgZGVmYXVsdCB2YWx1ZSBvbiBpbml0aWFsaXphdGlvblxuICAgICAgICAgICAgICAgIGRvTm90Rm9ybWF0OiBmYWxzZSwgLy8gd2lsbCBub3QgZm9ybWF0IHRoZSBkZWZhdWx0IHZhbHVlIG9uIGluaXRpYWxpemF0aW9uXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBTZXQgdGhlIHVuZG8vcmVkbyBoaXN0b3J5IHRhYmxlIHNpemUuXG4gICAgICAgICAgICAgKiBFYWNoIHJlY29yZCBrZWVwcyB0aGUgcmF3IHZhbHVlIGFzIHdlbGwgYW5kIHRoZSBsYXN0IGtub3duIGNhcmV0L3NlbGVjdGlvbiBwb3NpdGlvbnMuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIGhpc3RvcnlTaXplOiB7XG4gICAgICAgICAgICAgICAgdmVyeVNtYWxsOiA1LFxuICAgICAgICAgICAgICAgIHNtYWxsICAgIDogMTAsXG4gICAgICAgICAgICAgICAgbWVkaXVtICAgOiAyMCxcbiAgICAgICAgICAgICAgICBsYXJnZSAgICA6IDUwLFxuICAgICAgICAgICAgICAgIHZlcnlMYXJnZTogMTAwLFxuICAgICAgICAgICAgICAgIGluc2FuZSAgIDogTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBBbGxvdyB0aGUgdXNlciB0byAnY2FuY2VsJyBhbmQgdW5kbyB0aGUgY2hhbmdlcyBoZSBtYWRlIHRvIHRoZSBnaXZlbiBhdXRvbnVtZXJpYy1tYW5hZ2VkIGVsZW1lbnQsIGJ5IHByZXNzaW5nIHRoZSAnRXNjYXBlJyBrZXkuXG4gICAgICAgICAgICAgKiBXaGVuZXZlciB0aGUgdXNlciAndmFsaWRhdGUnIHRoZSBpbnB1dCAoZWl0aGVyIGJ5IGhpdHRpbmcgJ0VudGVyJywgb3IgYmx1cnJpbmcgdGhlIGVsZW1lbnQpLCB0aGUgbmV3IHZhbHVlIGlzIHNhdmVkIGZvciBzdWJzZXF1ZW50ICdjYW5jZWxsYXRpb24nLlxuICAgICAgICAgICAgICpcbiAgICAgICAgICAgICAqIFRoZSBwcm9jZXNzIDpcbiAgICAgICAgICAgICAqICAgLSBzYXZlIHRoZSBpbnB1dCB2YWx1ZSBvbiBmb2N1c1xuICAgICAgICAgICAgICogICAtIGlmIHRoZSB1c2VyIGNoYW5nZSB0aGUgaW5wdXQgdmFsdWUsIGFuZCBoaXQgYEVzY2FwZWAsIHRoZW4gdGhlIGluaXRpYWwgdmFsdWUgc2F2ZWQgb24gZm9jdXMgaXMgc2V0IGJhY2tcbiAgICAgICAgICAgICAqICAgLSBvbiB0aGUgb3RoZXIgaGFuZCBpZiB0aGUgdXNlciBlaXRoZXIgaGF2ZSB1c2VkIGBFbnRlcmAgdG8gdmFsaWRhdGUgKGBFbnRlcmAgdGhyb3dzIGEgY2hhbmdlIGV2ZW50KSBoaXMgZW50cmllcywgb3IgaWYgdGhlIGlucHV0IHZhbHVlIGhhcyBiZWVuIGNoYW5nZWQgYnkgYW5vdGhlciBzY3JpcHQgaW4gdGhlIG1lYW4gdGltZSwgdGhlbiB3ZSBzYXZlIHRoZSBuZXcgaW5wdXQgdmFsdWVcbiAgICAgICAgICAgICAqICAgLSBvbiBhIHN1Y2Nlc3NmdWwgJ2NhbmNlbCcsIHNlbGVjdCB0aGUgd2hvbGUgdmFsdWUgKHdoaWxlIHJlc3BlY3RpbmcgdGhlIGBzZWxlY3ROdW1iZXJPbmx5YCBvcHRpb24pXG4gICAgICAgICAgICAgKiAgIC0gYm9udXM7IGlmIHRoZSB2YWx1ZSBoYXMgbm90IGNoYW5nZWQsIGhpdHRpbmcgJ0VzYycganVzdCBzZWxlY3QgYWxsIHRoZSBpbnB1dCB2YWx1ZSAod2hpbGUgcmVzcGVjdGluZyB0aGUgYHNlbGVjdE51bWJlck9ubHlgIG9wdGlvbilcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgaXNDYW5jZWxsYWJsZToge1xuICAgICAgICAgICAgICAgIGNhbmNlbGxhYmxlICAgOiB0cnVlLFxuICAgICAgICAgICAgICAgIG5vdENhbmNlbGxhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIENvbnRyb2xzIHRoZSBsZWFkaW5nIHplcm8gYmVoYXZpb3JcbiAgICAgICAgICAgICAqIC0gJ2FsbG93JyA6IGFsbG93cyBsZWFkaW5nIHplcm9zIHRvIGJlIGVudGVyZWQuIFplcm9zIHdpbGwgYmUgdHJ1bmNhdGVkIHdoZW4gZW50ZXJpbmcgYWRkaXRpb25hbCBkaWdpdHMuIE9uIGZvY3Vzb3V0IHplcm9zIHdpbGwgYmUgZGVsZXRlZFxuICAgICAgICAgICAgICogLSAnZGVueScgIDogYWxsb3dzIG9ubHkgb25lIGxlYWRpbmcgemVybyBvbiB2YWx1ZXMgdGhhdCBhcmUgYmV0d2VlbiAxIGFuZCAtMVxuICAgICAgICAgICAgICogLSAna2VlcCcgIDogYWxsb3dzIGxlYWRpbmcgemVyb3MgdG8gYmUgZW50ZXJlZC4gb24gZm9jdXNvdXQgemVyb3Mgd2lsbCBiZSByZXRhaW5lZFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBsZWFkaW5nWmVybzoge1xuICAgICAgICAgICAgICAgIGFsbG93OiAnYWxsb3cnLFxuICAgICAgICAgICAgICAgIGRlbnkgOiAnZGVueScsXG4gICAgICAgICAgICAgICAga2VlcCA6ICdrZWVwJyxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgdGhlIG1heGltdW0gcG9zc2libGUgdmFsdWUgYSB1c2VyIGNhbiBlbnRlci5cbiAgICAgICAgICAgICAqIE5vdGVzOlxuICAgICAgICAgICAgICogLSB0aGlzIHZhbHVlIG11c3QgYSBzdHJpbmcgYW5kIHVzZSB0aGUgcGVyaW9kIGZvciB0aGUgZGVjaW1hbCBwb2ludFxuICAgICAgICAgICAgICogLSB0aGlzIHZhbHVlIG5lZWRzIHRvIGJlIGxhcmdlciB0aGFuIGBtaW5pbXVtVmFsdWVgXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1heGltdW1WYWx1ZToge1xuICAgICAgICAgICAgICAgIHRlblRyaWxsaW9ucyAgICAgICAgICA6ICc5OTk5OTk5OTk5OTk5Ljk5JywgLy8gOS45OTkuOTk5Ljk5OS45OTksOTkgfj0gMTAwMDAgYmlsbGlvbnNcbiAgICAgICAgICAgICAgICB0ZW5UcmlsbGlvbnNOb0RlY2ltYWxzOiAnOTk5OTk5OTk5OTk5OScsIC8vRklYTUUgVXBkYXRlIGFsbCB0aG9zZSBsaW1pdHMgdG8gdGhlICdyZWFsJyBudW1iZXJzXG4gICAgICAgICAgICAgICAgb25lQmlsbGlvbiAgICAgICAgICAgIDogJzk5OTk5OTk5OS45OScsXG4gICAgICAgICAgICAgICAgemVybyAgICAgICAgICAgICAgICAgIDogJzAnLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyB0aGUgbWluaW11bSBwb3NzaWJsZSB2YWx1ZSBhIHVzZXIgY2FuIGVudGVyLlxuICAgICAgICAgICAgICogTm90ZXM6XG4gICAgICAgICAgICAgKiAtIHRoaXMgdmFsdWUgbXVzdCBhIHN0cmluZyBhbmQgdXNlIHRoZSBwZXJpb2QgZm9yIHRoZSBkZWNpbWFsIHBvaW50XG4gICAgICAgICAgICAgKiAtIHRoaXMgdmFsdWUgbmVlZHMgdG8gYmUgc21hbGxlciB0aGFuIGBtYXhpbXVtVmFsdWVgXG4gICAgICAgICAgICAgKiAtIGlmIHRoaXMgaXMgc3VwZXJpb3IgdG8gMCwgdGhlbiB5b3UnbGwgZWZmZWN0aXZlbHkgcHJldmVudCB5b3VyIHVzZXIgdG8gZW50aXJlbHkgZGVsZXRlIHRoZSBjb250ZW50IG9mIHlvdXIgZWxlbWVudFxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBtaW5pbXVtVmFsdWU6IHtcbiAgICAgICAgICAgICAgICB0ZW5UcmlsbGlvbnMgICAgICAgICAgOiAnLTk5OTk5OTk5OTk5OTkuOTknLCAvLyAtOS45OTkuOTk5Ljk5OS45OTksOTkgfj0gMTAwMDAgYmlsbGlvbnNcbiAgICAgICAgICAgICAgICB0ZW5UcmlsbGlvbnNOb0RlY2ltYWxzOiAnLTk5OTk5OTk5OTk5OTknLFxuICAgICAgICAgICAgICAgIG9uZUJpbGxpb24gICAgICAgICAgICA6ICctOTk5OTk5OTk5Ljk5JyxcbiAgICAgICAgICAgICAgICB6ZXJvICAgICAgICAgICAgICAgICAgOiAnMCcsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBBbGxvdyB0aGUgdXNlciB0byBpbmNyZW1lbnQgb3IgZGVjcmVtZW50IHRoZSBlbGVtZW50IHZhbHVlIHdpdGggdGhlIG1vdXNlIHdoZWVsLlxuICAgICAgICAgICAgICogVGhlIHdoZWVsIGJlaGF2aW9yIGNhbiBieSBtb2RpZmllZCBieSB0aGUgYHdoZWVsU3RlcGAgb3B0aW9uLlxuICAgICAgICAgICAgICogVGhpcyBgd2hlZWxTdGVwYCBvcHRpb25zIGNhbiBiZSB1c2VkIGluIHR3byB3YXlzLCBlaXRoZXIgYnkgc2V0dGluZyA6XG4gICAgICAgICAgICAgKiAtIGEgJ2ZpeGVkJyBzdGVwIHZhbHVlIChgd2hlZWxTdGVwIDogMTAwMGApLCBvclxuICAgICAgICAgICAgICogLSB0aGUgJ3Byb2dyZXNzaXZlJyBzdHJpbmcgKGB3aGVlbFN0ZXAgOiAncHJvZ3Jlc3NpdmUnYCksIHdoaWNoIHdpbGwgdGhlbiBhY3RpdmF0ZSBhIHNwZWNpYWwgbW9kZSB3aGVyZSB0aGUgc3RlcCBpcyBhdXRvbWF0aWNhbGx5IGNhbGN1bGF0ZWQgYmFzZWQgb24gdGhlIGVsZW1lbnQgdmFsdWUgc2l6ZS5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBOb3RlIDpcbiAgICAgICAgICAgICAqIEEgc3BlY2lhbCBiZWhhdmlvciBpcyBhcHBsaWVkIGluIG9yZGVyIHRvIGF2b2lkIHByZXZlbnRpbmcgdGhlIHVzZXIgdG8gc2Nyb2xsIHRoZSBwYWdlIGlmIHRoZSBpbnB1dHMgYXJlIGNvdmVyaW5nIHRoZSB3aG9sZSBhdmFpbGFibGUgc3BhY2UuXG4gICAgICAgICAgICAgKiBZb3UgY2FuIHVzZSB0aGUgJ1NoaWZ0JyBtb2RpZmllciBrZXkgd2hpbGUgdXNpbmcgdGhlIG1vdXNlIHdoZWVsIGluIG9yZGVyIHRvIHRlbXBvcmFyaWx5IGRpc2FibGUgdGhlIGluY3JlbWVudC9kZWNyZW1lbnQgZmVhdHVyZSAodXNlZnVsIG9uIHNtYWxsIHNjcmVlbiB3aGVyZSBzb21lIGJhZGx5IGNvbmZpZ3VyZWQgaW5wdXRzIGNvdWxkIHVzZSBhbGwgdGhlIGF2YWlsYWJsZSBzcGFjZSkuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG1vZGlmeVZhbHVlT25XaGVlbDoge1xuICAgICAgICAgICAgICAgIG1vZGlmeVZhbHVlOiB0cnVlLFxuICAgICAgICAgICAgICAgIGRvTm90aGluZyAgOiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIEFkZHMgYnJhY2tldHMgb24gbmVnYXRpdmUgdmFsdWVzIChpZS4gdHJhbnNmb3JtcyAnLSQgOTk5Ljk5JyB0byAnKDk5OS45OSknKVxuICAgICAgICAgICAgICogVGhvc2UgYnJhY2tldHMgYXJlIHZpc2libGUgb25seSB3aGVuIHRoZSBmaWVsZCBkb2VzIE5PVCBoYXZlIHRoZSBmb2N1cy5cbiAgICAgICAgICAgICAqIFRoZSBsZWZ0IGFuZCByaWdodCBzeW1ib2xzIHNob3VsZCBiZSBlbmNsb3NlZCBpbiBxdW90ZXMgYW5kIHNlcGFyYXRlZCBieSBhIGNvbW1hLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBuZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1cjoge1xuICAgICAgICAgICAgICAgIHBhcmVudGhlc2VzICAgICAgICAgICA6ICcoLCknLFxuICAgICAgICAgICAgICAgIGJyYWNrZXRzICAgICAgICAgICAgICA6ICdbLF0nLFxuICAgICAgICAgICAgICAgIGNoZXZyb25zICAgICAgICAgICAgICA6ICc8LD4nLFxuICAgICAgICAgICAgICAgIGN1cmx5QnJhY2VzICAgICAgICAgICA6ICd7LH0nLFxuICAgICAgICAgICAgICAgIGFuZ2xlQnJhY2tldHMgICAgICAgICA6ICfjgIgs44CJJyxcbiAgICAgICAgICAgICAgICBqYXBhbmVzZVF1b3RhdGlvbk1hcmtzOiAn772iLO+9oycsXG4gICAgICAgICAgICAgICAgaGFsZkJyYWNrZXRzICAgICAgICAgIDogJ+K4pCziuKUnLFxuICAgICAgICAgICAgICAgIHdoaXRlU3F1YXJlQnJhY2tldHMgICA6ICfin6Ys4p+nJyxcbiAgICAgICAgICAgICAgICBxdW90YXRpb25NYXJrcyAgICAgICAgOiAn4oC5LOKAuicsXG4gICAgICAgICAgICAgICAgZ3VpbGxlbWV0cyAgICAgICAgICAgIDogJ8KrLMK7JyxcbiAgICAgICAgICAgICAgICBub25lICAgICAgICAgICAgICAgICAgOiBudWxsLCAvLyBUaGlzIGlzIHRoZSBkZWZhdWx0IHZhbHVlLCB3aGljaCBkZWFjdGl2YXRlIHRoaXMgZmVhdHVyZVxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogUGxhY2VtZW50IG9mIHRoZSBuZWdhdGl2ZS9wb3NpdGl2ZSBzaWduIHJlbGF0aXZlIHRvIHRoZSBgY3VycmVuY3lTeW1ib2xgIG9wdGlvbi5cbiAgICAgICAgICAgICAqXG4gICAgICAgICAgICAgKiBFeGFtcGxlOlxuICAgICAgICAgICAgICogLTEsMjM0LjU2ICA9PiBkZWZhdWx0IG5vIG9wdGlvbnMgcmVxdWlyZWRcbiAgICAgICAgICAgICAqIC0kMSwyMzQuNTYgPT4ge2N1cnJlbmN5U3ltYm9sOiBcIiRcIn0gb3Ige2N1cnJlbmN5U3ltYm9sOiBcIiRcIiwgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IFwibFwifVxuICAgICAgICAgICAgICogJC0xLDIzNC41NiA9PiB7Y3VycmVuY3lTeW1ib2w6IFwiJFwiLCBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogXCJyXCJ9IC8vIERlZmF1bHQgaWYgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgaXMgJ251bGwnIGFuZCBjdXJyZW5jeVN5bWJvbCBpcyBub3QgZW1wdHlcbiAgICAgICAgICAgICAqIC0xLDIzNC41NiQgPT4ge2N1cnJlbmN5U3ltYm9sOiBcIiRcIiwgY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQ6IFwic1wiLCBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogXCJwXCJ9IC8vIERlZmF1bHQgaWYgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgaXMgJ251bGwnIGFuZCBjdXJyZW5jeVN5bWJvbCBpcyBub3QgZW1wdHlcbiAgICAgICAgICAgICAqIDEsMjM0LjU2LSAgPT4ge25lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBcInNcIn1cbiAgICAgICAgICAgICAqICQxLDIzNC41Ni0gPT4ge2N1cnJlbmN5U3ltYm9sOiBcIiRcIiwgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IFwic1wifVxuICAgICAgICAgICAgICogMSwyMzQuNTYtJCA9PiB7Y3VycmVuY3lTeW1ib2w6IFwiJFwiLCBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudDogXCJzXCJ9XG4gICAgICAgICAgICAgKiAxLDIzNC41NiQtID0+IHtjdXJyZW5jeVN5bWJvbDogXCIkXCIsIGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50OiBcInNcIiwgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IFwiclwifVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDoge1xuICAgICAgICAgICAgICAgIHByZWZpeDogJ3AnLFxuICAgICAgICAgICAgICAgIHN1ZmZpeDogJ3MnLFxuICAgICAgICAgICAgICAgIGxlZnQgIDogJ2wnLFxuICAgICAgICAgICAgICAgIHJpZ2h0IDogJ3InLFxuICAgICAgICAgICAgICAgIG5vbmUgIDogbnVsbCxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgaWYgdGhlIGVsZW1lbnQgc2hvdWxkIGhhdmUgZXZlbnQgbGlzdGVuZXJzIGFjdGl2YXRlZCBvbiBpdC5cbiAgICAgICAgICAgICAqIEJ5IGRlZmF1bHQsIHRob3NlIGV2ZW50IGxpc3RlbmVycyBhcmUgb25seSBhZGRlZCB0byA8aW5wdXQ+IGVsZW1lbnRzIGFuZCBodG1sIGVsZW1lbnQgd2l0aCB0aGUgYGNvbnRlbnRlZGl0YWJsZWAgYXR0cmlidXRlIHNldCB0byBgdHJ1ZWAsIGJ1dCBub3Qgb24gdGhlIG90aGVyIGh0bWwgdGFncy5cbiAgICAgICAgICAgICAqIFRoaXMgYWxsb3dzIHRvIGluaXRpYWxpemUgZWxlbWVudHMgd2l0aG91dCBhbnkgZXZlbnQgbGlzdGVuZXJzLlxuICAgICAgICAgICAgICogV2FybmluZzogU2luY2UgQXV0b051bWVyaWMgd2lsbCBub3QgY2hlY2sgdGhlIGlucHV0IGNvbnRlbnQgYWZ0ZXIgaXRzIGluaXRpYWxpemF0aW9uLCB1c2luZyBzb21lIGF1dG9OdW1lcmljIG1ldGhvZHMgYWZ0ZXJ3YXJkcyAqd2lsbCogcHJvYmFibHkgbGVhZHMgdG8gZm9ybWF0dGluZyBwcm9ibGVtcy5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgbm9FdmVudExpc3RlbmVyczoge1xuICAgICAgICAgICAgICAgIG5vRXZlbnRzIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBhZGRFdmVudHM6IGZhbHNlLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogTWFuYWdlIGhvdyBhdXRvTnVtZXJpYyByZWFjdCB3aGVuIHRoZSB1c2VyIHRyaWVzIHRvIHBhc3RlIGFuIGludmFsaWQgbnVtYmVyLlxuICAgICAgICAgICAgICogLSAnZXJyb3InICAgIDogKFRoaXMgaXMgdGhlIGRlZmF1bHQgYmVoYXZpb3IpIFRoZSBpbnB1dCB2YWx1ZSBpcyBub3QgY2hhbmdlZCBhbmQgYW4gZXJyb3IgaXMgb3V0cHV0IGluIHRoZSBjb25zb2xlLlxuICAgICAgICAgICAgICogLSAnaWdub3JlJyAgIDogaWRlbSB0aGFuICdlcnJvcicsIGJ1dCBmYWlsIHNpbGVudGx5IHdpdGhvdXQgb3V0cHV0dGluZyBhbnkgZXJyb3Ivd2FybmluZyBpbiB0aGUgY29uc29sZS5cbiAgICAgICAgICAgICAqIC0gJ2NsYW1wJyAgICA6IGlmIHRoZSBwYXN0ZWQgdmFsdWUgaXMgZWl0aGVyIHRvbyBzbWFsbCBvciB0b28gYmlnIHJlZ2FyZGluZyB0aGUgbWluaW11bVZhbHVlIGFuZCBtYXhpbXVtVmFsdWUgcmFuZ2UsIHRoZW4gdGhlIHJlc3VsdCBpcyBjbGFtcGVkIHRvIHRob3NlIGxpbWl0cy5cbiAgICAgICAgICAgICAqIC0gJ3RydW5jYXRlJyA6IGF1dG9OdW1lcmljIHdpbGwgaW5zZXJ0IGFzIG1hbnkgcGFzdGVkIG51bWJlcnMgaXQgY2FuIGF0IHRoZSBpbml0aWFsIGNhcmV0L3NlbGVjdGlvbiwgdW50aWwgZXZlcnl0aGluZyBpcyBwYXN0ZWQsIG9yIHRoZSByYW5nZSBsaW1pdCBpcyBoaXQuXG4gICAgICAgICAgICAgKiAgICAgICAgICAgICAgICBUaGUgbm9uLXBhc3RlZCBudW1iZXJzIGFyZSBkcm9wcGVkIGFuZCB0aGVyZWZvcmUgbm90IHVzZWQgYXQgYWxsLlxuICAgICAgICAgICAgICogLSAncmVwbGFjZScgIDogYXV0b051bWVyaWMgd2lsbCBmaXJzdCBpbnNlcnQgYXMgbWFueSBwYXN0ZWQgbnVtYmVycyBpdCBjYW4gYXQgdGhlIGluaXRpYWwgY2FyZXQvc2VsZWN0aW9uLCB0aGVuIGlmIHRoZSByYW5nZSBsaW1pdCBpcyBoaXQsIGl0IHdpbGwgdHJ5XG4gICAgICAgICAgICAgKiAgICAgICAgICAgICAgICB0byByZXBsYWNlIG9uZSBieSBvbmUgdGhlIHJlbWFpbmluZyBpbml0aWFsIG51bWJlcnMgKG9uIHRoZSByaWdodCBzaWRlIG9mIHRoZSBjYXJldCkgd2l0aCB0aGUgcmVzdCBvZiB0aGUgcGFzdGVkIG51bWJlcnMuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogTm90ZSAxIDogQSBwYXN0ZSBjb250ZW50IHN0YXJ0aW5nIHdpdGggYSBuZWdhdGl2ZSBzaWduICctJyB3aWxsIGJlIGFjY2VwdGVkIGFueXdoZXJlIGluIHRoZSBpbnB1dCwgYW5kIHdpbGwgc2V0IHRoZSByZXN1bHRpbmcgdmFsdWUgYXMgYSBuZWdhdGl2ZSBudW1iZXJcbiAgICAgICAgICAgICAqIE5vdGUgMiA6IEEgcGFzdGUgY29udGVudCBzdGFydGluZyB3aXRoIGEgbnVtYmVyIHdpbGwgYmUgYWNjZXB0ZWQsIGV2ZW4gaWYgdGhlIHJlc3QgaXMgZ2liYmVyaXNoIChpZS4gJzEyM2Zvb2JhcjQ1NicpLlxuICAgICAgICAgICAgICogICAgICAgICAgT25seSB0aGUgZmlyc3QgbnVtYmVyIHdpbGwgYmUgdXNlZCAoaGVyZSAnMTIzJykuXG4gICAgICAgICAgICAgKiBOb3RlIDMgOiBUaGUgcGFzdGUgZXZlbnQgd29ya3Mgd2l0aCB0aGUgYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNgIG9wdGlvbiB0b28uXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIG9uSW52YWxpZFBhc3RlOiB7XG4gICAgICAgICAgICAgICAgZXJyb3IgICA6ICdlcnJvcicsXG4gICAgICAgICAgICAgICAgaWdub3JlICA6ICdpZ25vcmUnLFxuICAgICAgICAgICAgICAgIGNsYW1wICAgOiAnY2xhbXAnLFxuICAgICAgICAgICAgICAgIHRydW5jYXRlOiAndHJ1bmNhdGUnLFxuICAgICAgICAgICAgICAgIHJlcGxhY2UgOiAncmVwbGFjZScsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIGhvdyB0aGUgdmFsdWUgc2hvdWxkIGJlIGZvcm1hdHRlZCB3aGVuIHdhbnRpbmcgYSAnbG9jYWxpemVkJyB2ZXJzaW9uIG9mIGl0LlxuICAgICAgICAgICAgICogLSBudWxsIG9yICdzdHJpbmcnID0+ICdubm5uLm5uJyBvciAnLW5ubm4ubm4nIGFzIHRleHQgdHlwZS4gVGhpcyBpcyB0aGUgZGVmYXVsdCBiZWhhdmlvci5cbiAgICAgICAgICAgICAqIC0gJ251bWJlcicgICAgICAgICA9PiBubm5uLm5uIG9yIC1ubm5uLm5uIGFzIGEgTnVtYmVyIChXYXJuaW5nOiB0aGlzIHdvcmtzIG9ubHkgZm9yIGludGVnZXJzIGluZmVyaW9yIHRvIE51bWJlci5NQVhfU0FGRV9JTlRFR0VSKVxuICAgICAgICAgICAgICogLSAnLCcgb3IgJy0sJyAgICAgID0+ICdubm5uLG5uJyBvciAnLW5ubm4sbm4nXG4gICAgICAgICAgICAgKiAtICcuLScgICAgICAgICAgICAgPT4gJ25ubm4ubm4nIG9yICdubm5uLm5uLSdcbiAgICAgICAgICAgICAqIC0gJywtJyAgICAgICAgICAgICA9PiAnbm5ubixubicgb3IgJ25ubm4sbm4tJ1xuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBvdXRwdXRGb3JtYXQ6IHtcbiAgICAgICAgICAgICAgICBzdHJpbmcgICAgICAgOiAnc3RyaW5nJyxcbiAgICAgICAgICAgICAgICBudW1iZXIgICAgICAgOiAnbnVtYmVyJyxcbiAgICAgICAgICAgICAgICBkb3QgICAgICAgICAgOiAnLicsXG4gICAgICAgICAgICAgICAgbmVnYXRpdmVEb3QgIDogJy0uJyxcbiAgICAgICAgICAgICAgICBjb21tYSAgICAgICAgOiAnLCcsXG4gICAgICAgICAgICAgICAgbmVnYXRpdmVDb21tYTogJy0sJyxcbiAgICAgICAgICAgICAgICBkb3ROZWdhdGl2ZSAgOiAnLi0nLFxuICAgICAgICAgICAgICAgIGNvbW1hTmVnYXRpdmU6ICcsLScsXG4gICAgICAgICAgICAgICAgbm9uZSAgICAgICAgIDogbnVsbCxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIE92ZXJyaWRlIHRoZSBtaW5pbXVtIGFuZCBtYXhpbXVtIGxpbWl0c1xuICAgICAgICAgICAgICogb3ZlcnJpZGVNaW5NYXhMaW1pdHM6IFwiY2VpbGluZ1wiIGFkaGVyZXMgdG8gbWF4aW11bVZhbHVlIGFuZCBpZ25vcmVzIG1pbmltdW1WYWx1ZSBzZXR0aW5nc1xuICAgICAgICAgICAgICogb3ZlcnJpZGVNaW5NYXhMaW1pdHM6IFwiZmxvb3JcIiBhZGhlcmVzIHRvIG1pbmltdW1WYWx1ZSBhbmQgaWdub3JlcyBtYXhpbXVtVmFsdWUgc2V0dGluZ3NcbiAgICAgICAgICAgICAqIG92ZXJyaWRlTWluTWF4TGltaXRzOiBcImlnbm9yZVwiIGlnbm9yZXMgYm90aCBtaW5pbXVtVmFsdWUgJiBtYXhpbXVtVmFsdWVcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgb3ZlcnJpZGVNaW5NYXhMaW1pdHM6IHtcbiAgICAgICAgICAgICAgICBjZWlsaW5nICAgICAgOiAnY2VpbGluZycsXG4gICAgICAgICAgICAgICAgZmxvb3IgICAgICAgIDogJ2Zsb29yJyxcbiAgICAgICAgICAgICAgICBpZ25vcmUgICAgICAgOiAnaWdub3JlJyxcbiAgICAgICAgICAgICAgICBkb05vdE92ZXJyaWRlOiBudWxsLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogVGhlIGByYXdWYWx1ZURpdmlzb3JgIGRpdmlkZXMgdGhlIGZvcm1hdHRlZCB2YWx1ZSBzaG93biBpbiB0aGUgQXV0b051bWVyaWMgZWxlbWVudCBhbmQgc3RvcmUgdGhlIHJlc3VsdCBpbiBgcmF3VmFsdWVgLlxuICAgICAgICAgICAgICogQGV4YW1wbGUgeyByYXdWYWx1ZURpdmlzb3I6ICcxMDAnIH0gb3IgPGlucHV0IGRhdGEtcmF3LXZhbHVlLWRpdmlzb3I9XCIxMDBcIj5cbiAgICAgICAgICAgICAqIEdpdmVuIHRoZSBgMC4wMTIzNGAgcmF3IHZhbHVlLCB0aGUgZm9ybWF0dGVkIHZhbHVlIHdpbGwgYmUgZGlzcGxheWVkIGFzIGAnMS4yMzQnYC5cbiAgICAgICAgICAgICAqIFRoaXMgaXMgdXNlZnVsIHdoZW4gZGlzcGxheWluZyBwZXJjZW50YWdlIGZvciBpbnN0YW5jZSwgYW5kIGF2b2lkIHRoZSBuZWVkIHRvIGRpdmlkZS9tdWx0aXBseSBieSAxMDAgYmV0d2VlbiB0aGUgbnVtYmVyIHNob3duIGFuZCB0aGUgcmF3IHZhbHVlLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICByYXdWYWx1ZURpdmlzb3I6IHtcbiAgICAgICAgICAgICAgICBub25lICAgICAgOiBudWxsLFxuICAgICAgICAgICAgICAgIHBlcmNlbnRhZ2U6IDEwMCxcbiAgICAgICAgICAgICAgICBwZXJtaWxsZSAgOiAxMDAwLFxuICAgICAgICAgICAgICAgIGJhc2lzUG9pbnQ6IDEwMDAwLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyBpZiB0aGUgPGlucHV0PiBlbGVtZW50IHNob3VsZCBiZSBzZXQgYXMgcmVhZCBvbmx5IG9uIGluaXRpYWxpemF0aW9uLlxuICAgICAgICAgICAgICogV2hlbiBzZXQgdG8gYHRydWVgLCB0aGVuIHRoZSBgcmVhZG9ubHlgIGh0bWwgcHJvcGVydHkgaXMgYWRkZWQgdG8gdGhlIDxpbnB1dD4gZWxlbWVudCBvbiBpbml0aWFsaXphdGlvbi5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgcmVhZE9ubHk6IHtcbiAgICAgICAgICAgICAgICByZWFkT25seSA6IHRydWUsXG4gICAgICAgICAgICAgICAgcmVhZFdyaXRlOiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgdGhlIHJvdW5kaW5nIG1ldGhvZCB0byB1c2UuXG4gICAgICAgICAgICAgKiByb3VuZGluZ01ldGhvZDogXCJTXCIsIFJvdW5kLUhhbGYtVXAgU3ltbWV0cmljIChkZWZhdWx0KVxuICAgICAgICAgICAgICogcm91bmRpbmdNZXRob2Q6IFwiQVwiLCBSb3VuZC1IYWxmLVVwIEFzeW1tZXRyaWNcbiAgICAgICAgICAgICAqIHJvdW5kaW5nTWV0aG9kOiBcInNcIiwgUm91bmQtSGFsZi1Eb3duIFN5bW1ldHJpYyAobG93ZXIgY2FzZSBzKVxuICAgICAgICAgICAgICogcm91bmRpbmdNZXRob2Q6IFwiYVwiLCBSb3VuZC1IYWxmLURvd24gQXN5bW1ldHJpYyAobG93ZXIgY2FzZSBhKVxuICAgICAgICAgICAgICogcm91bmRpbmdNZXRob2Q6IFwiQlwiLCBSb3VuZC1IYWxmLUV2ZW4gXCJCYW5rZXJzIFJvdW5kaW5nXCJcbiAgICAgICAgICAgICAqIHJvdW5kaW5nTWV0aG9kOiBcIlVcIiwgUm91bmQgVXAgXCJSb3VuZC1Bd2F5LUZyb20tWmVyb1wiXG4gICAgICAgICAgICAgKiByb3VuZGluZ01ldGhvZDogXCJEXCIsIFJvdW5kIERvd24gXCJSb3VuZC1Ub3dhcmQtWmVyb1wiIC0gc2FtZSBhcyB0cnVuY2F0ZVxuICAgICAgICAgICAgICogcm91bmRpbmdNZXRob2Q6IFwiQ1wiLCBSb3VuZCB0byBDZWlsaW5nIFwiVG93YXJkIFBvc2l0aXZlIEluZmluaXR5XCJcbiAgICAgICAgICAgICAqIHJvdW5kaW5nTWV0aG9kOiBcIkZcIiwgUm91bmQgdG8gRmxvb3IgXCJUb3dhcmQgTmVnYXRpdmUgSW5maW5pdHlcIlxuICAgICAgICAgICAgICogcm91bmRpbmdNZXRob2Q6IFwiTjA1XCIgUm91bmRzIHRvIHRoZSBuZWFyZXN0IC4wNSA9PiBzYW1lIGFzIFwiQ0hGXCIgdXNlZCBpbiAxLjlYIGFuZCBzdGlsbCB2YWxpZFxuICAgICAgICAgICAgICogcm91bmRpbmdNZXRob2Q6IFwiVTA1XCIgUm91bmRzIHVwIHRvIG5leHQgLjA1XG4gICAgICAgICAgICAgKiByb3VuZGluZ01ldGhvZDogXCJEMDVcIiBSb3VuZHMgZG93biB0byBuZXh0IC4wNVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICByb3VuZGluZ01ldGhvZDoge1xuICAgICAgICAgICAgICAgIGhhbGZVcFN5bW1ldHJpYyAgICAgICAgICAgICAgICA6ICdTJyxcbiAgICAgICAgICAgICAgICBoYWxmVXBBc3ltbWV0cmljICAgICAgICAgICAgICAgOiAnQScsXG4gICAgICAgICAgICAgICAgaGFsZkRvd25TeW1tZXRyaWMgICAgICAgICAgICAgIDogJ3MnLFxuICAgICAgICAgICAgICAgIGhhbGZEb3duQXN5bW1ldHJpYyAgICAgICAgICAgICA6ICdhJyxcbiAgICAgICAgICAgICAgICBoYWxmRXZlbkJhbmtlcnNSb3VuZGluZyAgICAgICAgOiAnQicsXG4gICAgICAgICAgICAgICAgdXBSb3VuZEF3YXlGcm9tWmVybyAgICAgICAgICAgIDogJ1UnLFxuICAgICAgICAgICAgICAgIGRvd25Sb3VuZFRvd2FyZFplcm8gICAgICAgICAgICA6ICdEJyxcbiAgICAgICAgICAgICAgICB0b0NlaWxpbmdUb3dhcmRQb3NpdGl2ZUluZmluaXR5OiAnQycsXG4gICAgICAgICAgICAgICAgdG9GbG9vclRvd2FyZE5lZ2F0aXZlSW5maW5pdHkgIDogJ0YnLFxuICAgICAgICAgICAgICAgIHRvTmVhcmVzdDA1ICAgICAgICAgICAgICAgICAgICA6ICdOMDUnLFxuICAgICAgICAgICAgICAgIHRvTmVhcmVzdDA1QWx0ICAgICAgICAgICAgICAgICA6ICdDSEYnLFxuICAgICAgICAgICAgICAgIHVwVG9OZXh0MDUgICAgICAgICAgICAgICAgICAgICA6ICdVMDUnLFxuICAgICAgICAgICAgICAgIGRvd25Ub05leHQwNSAgICAgICAgICAgICAgICAgICA6ICdEMDUnLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogU2V0IHRvIGB0cnVlYCB0byBhbGxvdyB0aGUgYGRlY2ltYWxQbGFjZXNTaG93bk9uRm9jdXNgIHZhbHVlIHRvIGJlIHNhdmVkIHdpdGggc2Vzc2lvblN0b3JhZ2VcbiAgICAgICAgICAgICAqIElmIElFIDYgb3IgNyBpcyBkZXRlY3RlZCwgdGhlIHZhbHVlIHdpbGwgYmUgc2F2ZWQgYXMgYSBzZXNzaW9uIGNvb2tpZS5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZToge1xuICAgICAgICAgICAgICAgIHNhdmUgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBkb05vdFNhdmU6IGZhbHNlLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGV0ZXJtaW5lIGlmIHRoZSBzZWxlY3QgYWxsIGtleWJvYXJkIGNvbW1hbmQgd2lsbCBzZWxlY3QgdGhlIGNvbXBsZXRlIGlucHV0IHRleHQsIG9yIG9ubHkgdGhlIGlucHV0IG51bWVyaWMgdmFsdWVcbiAgICAgICAgICAgICAqIE5vdGUgOiBJZiB0aGUgY3VycmVuY3kgc3ltYm9sIGlzIGJldHdlZW4gdGhlIG51bWVyaWMgdmFsdWUgYW5kIHRoZSBuZWdhdGl2ZSBzaWduLCBvbmx5IHRoZSBudW1lcmljIHZhbHVlIHdpbGwgYmUgc2VsZWN0ZWRcbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2VsZWN0TnVtYmVyT25seToge1xuICAgICAgICAgICAgICAgIHNlbGVjdE51bWJlcnNPbmx5OiB0cnVlLFxuICAgICAgICAgICAgICAgIHNlbGVjdEFsbCAgICAgICAgOiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIERlZmluZXMgaWYgdGhlIGVsZW1lbnQgdmFsdWUgc2hvdWxkIGJlIHNlbGVjdGVkIG9uIGZvY3VzLlxuICAgICAgICAgICAgICogTm90ZTogVGhlIHNlbGVjdGlvbiBpcyBkb25lIHVzaW5nIHRoZSBgc2VsZWN0TnVtYmVyT25seWAgb3B0aW9uLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzZWxlY3RPbkZvY3VzOiB7XG4gICAgICAgICAgICAgICAgc2VsZWN0ICAgICA6IHRydWUsXG4gICAgICAgICAgICAgICAgZG9Ob3RTZWxlY3Q6IGZhbHNlLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyBob3cgdGhlIHNlcmlhbGl6ZSBmdW5jdGlvbnMgc2hvdWxkIHRyZWF0IHRoZSBzcGFjZXMuXG4gICAgICAgICAgICAgKiBUaG9zZSBzcGFjZXMgJyAnIGNhbiBlaXRoZXIgYmUgY29udmVydGVkIHRvIHRoZSBwbHVzIHNpZ24gJysnLCB3aGljaCBpcyB0aGUgZGVmYXVsdCwgb3IgdG8gJyUyMCcuXG4gICAgICAgICAgICAgKiBCb3RoIHZhbHVlcyBiZWluZyB2YWxpZCBwZXIgdGhlIHNwZWMgKGh0dHA6Ly93d3cudzMub3JnL0FkZHJlc3NpbmcvVVJML3VyaS1zcGVjLmh0bWwpLlxuICAgICAgICAgICAgICogQWxzbyBzZWUgdGhlIHN1bW1lZCB1cCBhbnN3ZXIgb24gaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzM5MzkyODcuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogdGw7ZHIgOiBTcGFjZXMgc2hvdWxkIGJlIGNvbnZlcnRlZCB0byAnJTIwJyBiZWZvcmUgdGhlICc/JyBzaWduLCB0aGVuIGNvbnZlcnRlZCB0byAnKycgYWZ0ZXIuXG4gICAgICAgICAgICAgKiBJbiBvdXIgY2FzZSBzaW5jZSB3ZSBzZXJpYWxpemUgdGhlIHF1ZXJ5LCB3ZSB1c2UgJysnIGFzIHRoZSBkZWZhdWx0IChidXQgYWxsb3cgdGhlIHVzZXIgdG8gZ2V0IGJhY2sgdGhlIG9sZCAqd3JvbmcqIGJlaGF2aW9yKS5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc2VyaWFsaXplU3BhY2VzOiB7XG4gICAgICAgICAgICAgICAgcGx1cyAgIDogJysnLFxuICAgICAgICAgICAgICAgIHBlcmNlbnQ6ICclMjAnLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyBpZiB0aGUgZWxlbWVudCB2YWx1ZSBzaG91bGQgYmUgY29udmVydGVkIHRvIHRoZSByYXcgdmFsdWUgb24gZm9jdXMgKGFuZCBiYWNrIHRvIHRoZSBmb3JtYXR0ZWQgb24gYmx1cikuXG4gICAgICAgICAgICAgKiBJZiBzZXQgdG8gYHRydWVgLCB0aGVuIGF1dG9OdW1lcmljIHJlbW92ZSB0aGUgdGhvdXNhbmQgc2VwYXJhdG9yLCBjdXJyZW5jeSBzeW1ib2wgYW5kIHN1ZmZpeCBvbiBmb2N1cy5cbiAgICAgICAgICAgICAqIEV4YW1wbGU6XG4gICAgICAgICAgICAgKiBJZiB0aGUgaW5wdXQgdmFsdWUgaXMgJyQgMSw5OTkuODggc3VmZml4Jywgb24gZm9jdXMgaXQgYmVjb21lcyAnMTk5OS44OCcgYW5kIGJhY2sgdG8gJyQgMSw5OTkuODggc3VmZml4JyBvbiBmb2N1cyBvdXQuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNob3dPbmx5TnVtYmVyc09uRm9jdXM6IHtcbiAgICAgICAgICAgICAgICBvbmx5TnVtYmVyczogdHJ1ZSxcbiAgICAgICAgICAgICAgICBzaG93QWxsICAgIDogZmFsc2UsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBBbGxvdyB0aGUgcG9zaXRpdmUgc2lnbiBzeW1ib2wgYCtgIHRvIGJlIGRpc3BsYXllZCBmb3IgcG9zaXRpdmUgbnVtYmVycy5cbiAgICAgICAgICAgICAqIEJ5IGRlZmF1bHQsIHRoaXMgcG9zaXRpdmUgc2lnbiBpcyBub3Qgc2hvd24uXG4gICAgICAgICAgICAgKiBUaGUgc2lnbiBwbGFjZW1lbnQgaXMgY29udHJvbGxlZCBieSB0aGUgJ25lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50JyBvcHRpb24sIG1pbWlja2luZyB0aGUgbmVnYXRpdmUgc2lnbiBwbGFjZW1lbnQgcnVsZXMuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHNob3dQb3NpdGl2ZVNpZ246IHtcbiAgICAgICAgICAgICAgICBzaG93OiB0cnVlLFxuICAgICAgICAgICAgICAgIGhpZGU6IGZhbHNlLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyBpZiB3YXJuaW5ncyBzaG91bGQgYmUgc2hvd24gaW4gdGhlIGNvbnNvbGVcbiAgICAgICAgICAgICAqIFRob3NlIHdhcm5pbmdzIGNhbiBiZSBpZ25vcmVkLCBidXQgYXJlIHVzdWFsbHkgcHJpbnRlZCB3aGVuIHNvbWV0aGluZyBjb3VsZCBiZSBpbXByb3ZlZCBieSB0aGUgdXNlciAoaWUuIG9wdGlvbiBjb25mbGljdHMpLlxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzaG93V2FybmluZ3M6IHtcbiAgICAgICAgICAgICAgICBzaG93OiB0cnVlLCAvLyBBbGwgd2FybmluZyBhcmUgc2hvd25cbiAgICAgICAgICAgICAgICBoaWRlOiBmYWxzZSwgLy8gTm8gd2FybmluZ3MgYXJlIHNob3duLCBvbmx5IHRoZSB0aHJvd24gZXJyb3JzXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBEZWZpbmVzIHRoZSBydWxlcyB0aGF0IGNhbGN1bGF0ZSB0aGUgQ1NTIGNsYXNzKGVzKSB0byBhcHBseSBvbiB0aGUgZWxlbWVudCwgYmFzZWQgb24gdGhlIHJhdyB1bmZvcm1hdHRlZCB2YWx1ZS5cbiAgICAgICAgICAgICAqIFRoaXMgY2FuIGFsc28gYmUgdXNlZCB0byBjYWxsIGNhbGxiYWNrcyB3aGVuZXZlciB0aGUgYHJhd1ZhbHVlYCBpcyB1cGRhdGVkLlxuICAgICAgICAgICAgICogSW1wb3J0YW50OiBhbGwgY2FsbGJhY2tzIG11c3QgcmV0dXJuIGBudWxsYCBpZiBubyByYW5nZXMvdXNlckRlZmluZWQgY2xhc3NlcyBhcmUgc2VsZWN0ZWRcbiAgICAgICAgICAgICAqIEBleGFtcGxlXG4gICAgICAgICAgICAgKiB7XG4gICAgICAgICAgICAgKiAgICAgcG9zaXRpdmUgICA6ICdhdXRvTnVtZXJpYy1wb3NpdGl2ZScsIC8vIE9yIGBudWxsYCB0byBub3QgdXNlIGl0XG4gICAgICAgICAgICAgKiAgICAgbmVnYXRpdmUgICA6ICdhdXRvTnVtZXJpYy1uZWdhdGl2ZScsXG4gICAgICAgICAgICAgKiAgICAgcmFuZ2VzICAgICA6IFtcbiAgICAgICAgICAgICAqICAgICAgICAgeyBtaW46IDAsIG1heDogMjUsIGNsYXNzOiAnYXV0b051bWVyaWMtcmVkJyB9LFxuICAgICAgICAgICAgICogICAgICAgICB7IG1pbjogMjUsIG1heDogNTAsIGNsYXNzOiAnYXV0b051bWVyaWMtb3JhbmdlJyB9LFxuICAgICAgICAgICAgICogICAgICAgICB7IG1pbjogNTAsIG1heDogNzUsIGNsYXNzOiAnYXV0b051bWVyaWMteWVsbG93JyB9LFxuICAgICAgICAgICAgICogICAgICAgICB7IG1pbjogNzUsIG1heDogTnVtYmVyLk1BWF9TQUZFX0lOVEVHRVIsIGNsYXNzOiAnYXV0b051bWVyaWMtZ3JlZW4nIH0sXG4gICAgICAgICAgICAgKiAgICAgXSxcbiAgICAgICAgICAgICAqICAgICB1c2VyRGVmaW5lZDogW1xuICAgICAgICAgICAgICogICAgICAgICAvLyBJZiAnY2xhc3NlcycgaXMgYSBzdHJpbmcsIHNldCBpdCBpZiBgdHJ1ZWAsIHJlbW92ZSBpdCBpZiBgZmFsc2VgXG4gICAgICAgICAgICAgKiAgICAgICAgIHsgY2FsbGJhY2s6IHJhd1ZhbHVlID0+IHsgcmV0dXJuIHRydWU7IH0sIGNsYXNzZXM6ICd0aGlzSXNUcnVlJyB9LFxuICAgICAgICAgICAgICogICAgICAgICAvLyBJZiAnY2xhc3NlcycgaXMgYW4gYXJyYXkgd2l0aCBvbmx5IDIgZWxlbWVudHMsIHNldCB0aGUgZmlyc3QgY2xhc3MgaWYgYHRydWVgLCB0aGUgc2Vjb25kIGlmIGBmYWxzZWBcbiAgICAgICAgICAgICAqICAgICAgICAgeyBjYWxsYmFjazogcmF3VmFsdWUgPT4gcmF3VmFsdWUgJSAyID09PSAwLCBjbGFzc2VzOiBbJ2F1dG9OdW1lcmljLWV2ZW4nLCAnYXV0b051bWVyaWMtb2RkJ10gfSxcbiAgICAgICAgICAgICAqICAgICAgICAgLy8gUmV0dXJuIG9ubHkgb25lIGluZGV4IHRvIHVzZSBvbiB0aGUgYGNsYXNzZXNgIGFycmF5IChoZXJlLCAnY2xhc3MzJylcbiAgICAgICAgICAgICAqICAgICAgICAgeyBjYWxsYmFjazogcmF3VmFsdWUgPT4geyByZXR1cm4gMjsgfSwgY2xhc3NlczogWydjbGFzczEnLCAnY2xhc3MyJywgJ2NsYXNzMyddIH0sXG4gICAgICAgICAgICAgKiAgICAgICAgIC8vIFJldHVybiBhbiBhcnJheSBvZiBpbmRleGVzIHRvIHVzZSBvbiB0aGUgYGNsYXNzZXNgIGFycmF5IChoZXJlLCAnY2xhc3MxJyBhbmQgJ2NsYXNzMycpXG4gICAgICAgICAgICAgKiAgICAgICAgIHsgY2FsbGJhY2s6IHJhd1ZhbHVlID0+IHsgcmV0dXJuIFswLCAyXTsgfSwgY2xhc3NlczogWydjbGFzczEnLCAnY2xhc3MyJywgJ2NsYXNzMyddIH0sXG4gICAgICAgICAgICAgKiAgICAgICAgIC8vIElmICdjbGFzc2VzJyBpcyBgdW5kZWZpbmVkYCBvciBgbnVsbGAsIHRoZW4gdGhlIGNhbGxiYWNrIGlzIGNhbGxlZCB3aXRoIHRoZSBBdXRvTnVtZXJpYyBvYmplY3QgcGFzc2VkIGFzIGEgcGFyYW1ldGVyXG4gICAgICAgICAgICAgKiAgICAgICAgIHsgY2FsbGJhY2s6IGFuRWxlbWVudCA9PiB7IHJldHVybiBhbkVsZW1lbnQuZ2V0Rm9ybWF0dGVkKCk7IH0gfSxcbiAgICAgICAgICAgICAqICAgICBdLFxuICAgICAgICAgICAgICogfVxuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzdHlsZVJ1bGVzOiB7XG4gICAgICAgICAgICAgICAgbm9uZSAgICAgICAgICAgICAgICAgOiBudWxsLFxuICAgICAgICAgICAgICAgIHBvc2l0aXZlTmVnYXRpdmUgICAgIDoge1xuICAgICAgICAgICAgICAgICAgICBwb3NpdGl2ZTogJ2F1dG9OdW1lcmljLXBvc2l0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgbmVnYXRpdmU6ICdhdXRvTnVtZXJpYy1uZWdhdGl2ZScsXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICByYW5nZTBUbzEwMFdpdGg0U3RlcHM6IHtcbiAgICAgICAgICAgICAgICAgICAgcmFuZ2VzOiBbXG4gICAgICAgICAgICAgICAgICAgICAgICB7IG1pbjogMCwgbWF4OiAyNSwgY2xhc3M6ICdhdXRvTnVtZXJpYy1yZWQnIH0sXG4gICAgICAgICAgICAgICAgICAgICAgICB7IG1pbjogMjUsIG1heDogNTAsIGNsYXNzOiAnYXV0b051bWVyaWMtb3JhbmdlJyB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgeyBtaW46IDUwLCBtYXg6IDc1LCBjbGFzczogJ2F1dG9OdW1lcmljLXllbGxvdycgfSxcbiAgICAgICAgICAgICAgICAgICAgICAgIHsgbWluOiA3NSwgbWF4OiAxMDAsIGNsYXNzOiAnYXV0b051bWVyaWMtZ3JlZW4nIH0sXG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBldmVuT2RkICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICAgICAgdXNlckRlZmluZWQ6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHsgY2FsbGJhY2s6IHJhd1ZhbHVlID0+IHJhd1ZhbHVlICUgMiA9PT0gMCwgY2xhc3NlczogWydhdXRvTnVtZXJpYy1ldmVuJywgJ2F1dG9OdW1lcmljLW9kZCddIH0sXG4gICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICByYW5nZVNtYWxsQW5kWmVybyAgICA6IHtcbiAgICAgICAgICAgICAgICAgICAgdXNlckRlZmluZWQ6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYWxsYmFjayAgOiByYXdWYWx1ZSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChyYXdWYWx1ZSA+PSAtMSAmJiByYXdWYWx1ZSA8IDApIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAwO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChOdW1iZXIocmF3VmFsdWUpID09PSAwKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gMTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAocmF3VmFsdWUgPiAwICYmIHJhd1ZhbHVlIDw9IDEpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybiAyO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7ICAvLyBJbiBjYXNlIHRoZSByYXdWYWx1ZSBpcyBvdXRzaWRlIHRob3NlIHJhbmdlc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0sIGNsYXNzZXM6IFtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2F1dG9OdW1lcmljLXNtYWxsLW5lZ2F0aXZlJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgJ2F1dG9OdW1lcmljLXplcm8nLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAnYXV0b051bWVyaWMtc21hbGwtcG9zaXRpdmUnLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICAvKiBBZGQgYSB0ZXh0IG9uIHRoZSByaWdodCBoYW5kIHNpZGUgb2YgdGhlIGVsZW1lbnQgdmFsdWUuXG4gICAgICAgICAgICAgKiBUaGlzIHN1ZmZpeCB0ZXh0IGNhbiBoYXZlIGFueSBjaGFyYWN0ZXJzIGluIGl0cyBzdHJpbmcsIGV4Y2VwdCBudW1lcmljIGNoYXJhY3RlcnMgYW5kIHRoZSBuZWdhdGl2ZS9wb3NpdGl2ZSBzaWduLlxuICAgICAgICAgICAgICogRXhhbXBsZTogJyBkb2xsYXJzJ1xuICAgICAgICAgICAgICovXG4gICAgICAgICAgICBzdWZmaXhUZXh0OiB7XG4gICAgICAgICAgICAgICAgbm9uZSAgICAgIDogJycsXG4gICAgICAgICAgICAgICAgcGVyY2VudGFnZTogJyUnLFxuICAgICAgICAgICAgICAgIHBlcm1pbGxlICA6ICfigLAnLFxuICAgICAgICAgICAgICAgIGJhc2lzUG9pbnQ6ICfigLEnLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogVGhlIHRocmVlIG9wdGlvbnMgKGRpdmlzb3JXaGVuVW5mb2N1c2VkLCBkZWNpbWFsUGxhY2VzU2hvd25PbkJsdXIgJiBzeW1ib2xXaGVuVW5mb2N1c2VkKSBoYW5kbGUgc2NhbGluZyBvZiB0aGUgaW5wdXQgd2hlbiB0aGUgaW5wdXQgZG9lcyBub3QgaGF2ZSBmb2N1c1xuICAgICAgICAgICAgICogUGxlYXNlIG5vdGUgdGhhdCB0aGUgbm9uLXNjYWxlZCB2YWx1ZSBpcyBoZWxkIGluIGRhdGEgYW5kIGl0IGlzIGFkdmlzZWQgdGhhdCB5b3UgdXNlIHRoZSBgc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZWAgb3B0aW9uIHRvIGVuc3VyZSByZXRhaW5pbmcgdGhlIHZhbHVlXG4gICAgICAgICAgICAgKiBbXCJkaXZpc29yXCIsIFwiZGVjaW1hbCBwbGFjZXNcIiwgXCJzeW1ib2xcIl1cbiAgICAgICAgICAgICAqIEV4YW1wbGU6IHdpdGggdGhlIGZvbGxvd2luZyBvcHRpb25zIHNldCB7ZGl2aXNvcldoZW5VbmZvY3VzZWQ6ICcxMDAwJywgZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyOiAnMScsIHN5bWJvbFdoZW5VbmZvY3VzZWQ6ICcgSyd9XG4gICAgICAgICAgICAgKiBFeGFtcGxlOiBmb2N1c2luIHZhbHVlIFwiMSwxMTEuMTFcIiBmb2N1c291dCB2YWx1ZSBcIjEuMSBLXCJcbiAgICAgICAgICAgICAqL1xuXG4gICAgICAgICAgICAvKiBUaGUgYHN5bWJvbFdoZW5VbmZvY3VzZWRgIG9wdGlvbiBpcyBhIHN5bWJvbCBwbGFjZWQgYXMgYSBzdWZmaXggd2hlbiBub3QgaW4gZm9jdXMuXG4gICAgICAgICAgICAgKiBUaGlzIGlzIG9wdGlvbmFsIHRvby5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgc3ltYm9sV2hlblVuZm9jdXNlZDoge1xuICAgICAgICAgICAgICAgIG5vbmUgICAgICA6IG51bGwsXG4gICAgICAgICAgICAgICAgcGVyY2VudGFnZTogJyUnLFxuICAgICAgICAgICAgICAgIHBlcm1pbGxlICA6ICfigLAnLFxuICAgICAgICAgICAgICAgIGJhc2lzUG9pbnQ6ICfigLEnLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogRGVmaW5lcyBpZiB0aGUgZWxlbWVudCB2YWx1ZSBzaG91bGQgYmUgdW5mb3JtYXR0ZWQgd2hlbiB0aGUgdXNlciBob3ZlciBoaXMgbW91c2Ugb3ZlciBpdCB3aGlsZSBob2xkaW5nIHRoZSBgQWx0YCBrZXkuXG4gICAgICAgICAgICAgKiBVbmZvcm1hdHRpbmcgdGhlcmUgbWVhbnMgdGhhdCB0aGlzIHJlbW92ZXMgYW55IG5vbi1udW1iZXIgY2hhcmFjdGVycyBhbmQgZGlzcGxheXMgdGhlICpyYXcqIHZhbHVlLCBhcyB1bmRlcnN0b29kIGJ5IEphdmFzY3JpcHQgKGllLiBgMTIuMzRgIGlzIGEgdmFsaWQgbnVtYmVyLCB3aGlsZSBgMTIsMzRgIGlzIG5vdCkuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogV2UgcmVmb3JtYXQgYmFjayBiZWZvcmUgYW55dGhpbmcgZWxzZSBpZiA6XG4gICAgICAgICAgICAgKiAtIHRoZSB1c2VyIGZvY3VzIG9uIHRoZSBlbGVtZW50IGJ5IHRhYmJpbmcgb3IgY2xpY2tpbmcgaW50byBpdCxcbiAgICAgICAgICAgICAqIC0gdGhlIHVzZXIgcmVsZWFzZXMgdGhlIGBBbHRgIGtleSwgYW5kXG4gICAgICAgICAgICAgKiAtIGlmIHdlIGRldGVjdCBhIG1vdXNlbGVhdmUgZXZlbnQuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogV2UgdW5mb3JtYXQgYWdhaW4gaWYgOlxuICAgICAgICAgICAgICogLSB3aGlsZSB0aGUgbW91c2UgaXMgb3ZlciB0aGUgZWxlbWVudCwgdGhlIHVzZXIgaGl0IGN0cmwgYWdhaW5cbiAgICAgICAgICAgICAqL1xuICAgICAgICAgICAgdW5mb3JtYXRPbkhvdmVyOiB7XG4gICAgICAgICAgICAgICAgdW5mb3JtYXQgICAgIDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBkb05vdFVuZm9ybWF0OiBmYWxzZSxcbiAgICAgICAgICAgIH0sXG5cbiAgICAgICAgICAgIC8qIFJlbW92ZXMgdGhlIGZvcm1hdHRpbmcgYW5kIHVzZSB0aGUgcmF3IHZhbHVlIGluIGVhY2ggYXV0b051bWVyaWMgZWxlbWVudHMgb2YgdGhlIHBhcmVudCBmb3JtIGVsZW1lbnQsIG9uIHRoZSBmb3JtIGBzdWJtaXRgIGV2ZW50LlxuICAgICAgICAgICAgICogVGhlIG91dHB1dCBmb3JtYXQgaXMgYSBudW1lcmljIHN0cmluZyAobm5ubi5ubiBvciAtbm5ubi5ubikuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHVuZm9ybWF0T25TdWJtaXQ6IHtcbiAgICAgICAgICAgICAgICB1bmZvcm1hdCAgICAgICAgOiB0cnVlLFxuICAgICAgICAgICAgICAgIGtlZXBDdXJyZW50VmFsdWU6IGZhbHNlLFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgLyogVGhhdCBvcHRpb24gaXMgbGlua2VkIHRvIHRoZSBgbW9kaWZ5VmFsdWVPbldoZWVsYCBvbmUgYW5kIHdpbGwgb25seSBiZSB1c2VkIGlmIHRoZSBsYXR0ZXIgaXMgc2V0IHRvIGB0cnVlYC5cbiAgICAgICAgICAgICAqIFRoaXMgb3B0aW9uIHdpbGwgbW9kaWZ5IHRoZSB3aGVlbCBiZWhhdmlvciBhbmQgY2FuIGJlIHVzZWQgaW4gdHdvIHdheXMsIGVpdGhlciBieSBzZXR0aW5nIDpcbiAgICAgICAgICAgICAqIC0gYSAnZml4ZWQnIHN0ZXAgdmFsdWUgKGEgcG9zaXRpdmUgZmxvYXQgb3IgaW50ZWdlciBudW1iZXIgYDEwMDBgKSwgb3JcbiAgICAgICAgICAgICAqIC0gdGhlIGAncHJvZ3Jlc3NpdmUnYCBzdHJpbmcuXG4gICAgICAgICAgICAgKlxuICAgICAgICAgICAgICogVGhlICdmaXhlZCcgbW9kZSBhbHdheXMgaW5jcmVtZW50L2RlY3JlbWVudCB0aGUgZWxlbWVudCB2YWx1ZSBieSB0aGF0IGFtb3VudCwgd2hpbGUgcmVzcGVjdGluZyB0aGUgYG1pbmltdW1WYWx1ZWAgYW5kIGBtYXhpbXVtVmFsdWVgIHNldHRpbmdzLlxuICAgICAgICAgICAgICogVGhlICdwcm9ncmVzc2l2ZScgbW9kZSB3aWxsIGluY3JlbWVudC9kZWNyZW1lbnQgdGhlIGVsZW1lbnQgdmFsdWUgYmFzZWQgb24gaXRzIGN1cnJlbnQgdmFsdWUuIFRoZSBiaWdnZXIgdGhlIG51bWJlciwgdGhlIGJpZ2dlciB0aGUgc3RlcCwgYW5kIHZpY2UgdmVyc2EuXG4gICAgICAgICAgICAgKi9cbiAgICAgICAgICAgIHdoZWVsU3RlcDoge1xuICAgICAgICAgICAgICAgIHByb2dyZXNzaXZlOiAncHJvZ3Jlc3NpdmUnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICB9LFxufSk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvQXV0b051bWVyaWNPcHRpb25zLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==");

/***/ },
/* 5 */
/***/ function(module, exports, __webpack_require__) {

	eval("/*** IMPORTS FROM imports-loader ***/\n(function() {\n\n'use strict';\n\nvar _AutoNumeric = __webpack_require__(1);\n\nvar _AutoNumeric2 = _interopRequireDefault(_AutoNumeric);\n\nvar _AutoNumericOptions = __webpack_require__(4);\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. `<input type=\"text\" data-currency-symbol=\" €\">`)\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 <alexandre.bonneau@linuxfr.eu>\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            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            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            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            wheelStep: _AutoNumeric2.default.options.wheelStep.progressive\n        };\n    }\n});\n}.call(window));//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvQXV0b051bWVyaWNEZWZhdWx0U2V0dGluZ3MuanM/ZTg2YiJdLCJuYW1lcyI6WyJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldCIsImFsbG93RGVjaW1hbFBhZGRpbmciLCJvcHRpb25zIiwiYWx3YXlzIiwiY2FyZXRQb3NpdGlvbk9uRm9jdXMiLCJkb05vRm9yY2VDYXJldFBvc2l0aW9uIiwiY3JlYXRlTG9jYWxMaXN0IiwiY3JlYXRlTGlzdCIsImN1cnJlbmN5U3ltYm9sIiwibm9uZSIsImN1cnJlbmN5U3ltYm9sUGxhY2VtZW50IiwicHJlZml4IiwiZGVjaW1hbENoYXJhY3RlciIsImRvdCIsImRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSIsImRlY2ltYWxQbGFjZXMiLCJ0d28iLCJkZWNpbWFsUGxhY2VzUmF3VmFsdWUiLCJ1c2VEZWZhdWx0IiwiZGVjaW1hbFBsYWNlc1Nob3duT25CbHVyIiwiZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyIsImRlZmF1bHRWYWx1ZU92ZXJyaWRlIiwiZG9Ob3RPdmVycmlkZSIsImRpZ2l0YWxHcm91cFNwYWNpbmciLCJ0aHJlZSIsImRpZ2l0R3JvdXBTZXBhcmF0b3IiLCJjb21tYSIsImRpdmlzb3JXaGVuVW5mb2N1c2VkIiwiZW1wdHlJbnB1dEJlaGF2aW9yIiwiZm9jdXMiLCJmYWlsT25Vbmtub3duT3B0aW9uIiwiaWdub3JlIiwiZm9ybWF0T25QYWdlTG9hZCIsImZvcm1hdCIsImhpc3RvcnlTaXplIiwibWVkaXVtIiwiaXNDYW5jZWxsYWJsZSIsImNhbmNlbGxhYmxlIiwibGVhZGluZ1plcm8iLCJkZW55IiwibWF4aW11bVZhbHVlIiwidGVuVHJpbGxpb25zIiwibWluaW11bVZhbHVlIiwibW9kaWZ5VmFsdWVPbldoZWVsIiwibW9kaWZ5VmFsdWUiLCJuZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciIsIm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Iiwibm9FdmVudExpc3RlbmVycyIsImFkZEV2ZW50cyIsIm9uSW52YWxpZFBhc3RlIiwiZXJyb3IiLCJvdXRwdXRGb3JtYXQiLCJvdmVycmlkZU1pbk1heExpbWl0cyIsInJhd1ZhbHVlRGl2aXNvciIsInJlYWRPbmx5IiwicmVhZFdyaXRlIiwicm91bmRpbmdNZXRob2QiLCJoYWxmVXBTeW1tZXRyaWMiLCJzYXZlVmFsdWVUb1Nlc3Npb25TdG9yYWdlIiwiZG9Ob3RTYXZlIiwic2VsZWN0TnVtYmVyT25seSIsInNlbGVjdE51bWJlcnNPbmx5Iiwic2VsZWN0T25Gb2N1cyIsInNlbGVjdCIsInNlcmlhbGl6ZVNwYWNlcyIsInBsdXMiLCJzaG93T25seU51bWJlcnNPbkZvY3VzIiwic2hvd0FsbCIsInNob3dQb3NpdGl2ZVNpZ24iLCJoaWRlIiwic2hvd1dhcm5pbmdzIiwic2hvdyIsInN0eWxlUnVsZXMiLCJzdWZmaXhUZXh0Iiwic3ltYm9sV2hlblVuZm9jdXNlZCIsInVuZm9ybWF0T25Ib3ZlciIsInVuZm9ybWF0IiwidW5mb3JtYXRPblN1Ym1pdCIsImtlZXBDdXJyZW50VmFsdWUiLCJ3aGVlbFN0ZXAiLCJwcm9ncmVzc2l2ZSJdLCJtYXBwaW5ncyI6Ijs7Ozs7QUE2QkE7Ozs7QUFDQTs7Ozs7O0FBRUE7O0FBRUE7Ozs7OztBQWxDQTs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUF3Q0FBLE9BQU9DLGNBQVAsd0JBQW1DLGlCQUFuQyxFQUFzRDtBQUNsREMsT0FEa0QsaUJBQzVDO0FBQ0YsZUFBTztBQUNIQyxpQ0FBK0Isc0JBQVlDLE9BQVosQ0FBb0JELG1CQUFwQixDQUF3Q0UsTUFEcEU7QUFFSEMsa0NBQStCLHNCQUFZRixPQUFaLENBQW9CRSxvQkFBcEIsQ0FBeUNDLHNCQUZyRTtBQUdIQyw2QkFBK0Isc0JBQVlKLE9BQVosQ0FBb0JJLGVBQXBCLENBQW9DQyxVQUhoRTtBQUlIQyw0QkFBK0Isc0JBQVlOLE9BQVosQ0FBb0JNLGNBQXBCLENBQW1DQyxJQUovRDtBQUtIQyxxQ0FBK0Isc0JBQVlSLE9B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QXVDSEMsb0NBQStCLHNCQUFZaEUsT0FBWixDQUFvQmdFLHNCQUFwQixDQUEyQ0MsT0F2Q3ZFO0FBd0NIQyw4QkFBK0Isc0JBQVlsRSxPQUFaLENBQW9Ca0UsZ0JBQXBCLENBQXFDQyxJQXhDakU7QUF5Q0hDLDBCQUErQixzQkFBWXBFLE9BQVosQ0FBb0JvRSxZQUFwQixDQUFpQ0MsSUF6QzdEO0FBMENIQyx3QkFBK0Isc0JBQVl0RSxPQUFaLENBQW9Cc0UsVUFBcEIsQ0FBK0IvRCxJQTFDM0Q7QUEyQ0hnRSx3QkFBK0Isc0JBQVl2RSxPQUFaLENBQW9CdUUsVUFBcEIsQ0FBK0JoRSxJQTNDM0Q7QUE0Q0hpRSxpQ0FBK0Isc0JBQVl4RSxPQUFaLENBQW9Cd0UsbUJBQXBCLENBQXdDakUsSUE1Q3BFO0FBNkNIa0UsNkJBQStCLHNCQUFZekUsT0FBWixDQUFvQnlFLGVBQXBCLENBQW9DQyxRQTdDaEU7QUE4Q0hDLDhCQUErQixzQkFBWTNFLE9BQVosQ0FBb0IyRSxnQkFBcEIsQ0FBcUNDLGdCQTlDakU7QUErQ0hDLHVCQUErQixzQkFBWTdFLE9BQVosQ0FBb0I2RSxTQUFwQixDQUE4QkM7QUEvQzFELFNBQVA7QUFpREg7QUFuRGlELENBQXRELEUiLCJmaWxlIjoiNS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogRGVmYXVsdCBzZXR0aW5ncyBmb3IgYXV0b051bWVyaWMuanNcbiAqIEBhdXRob3IgQWxleGFuZHJlIEJvbm5lYXUgPGFsZXhhbmRyZS5ib25uZWF1QGxpbnV4ZnIuZXU+XG4gKiBAY29weXJpZ2h0IMKpIDIwMTYgQWxleGFuZHJlIEJvbm5lYXVcbiAqXG4gKiBUaGUgTUlUIExpY2Vuc2UgKGh0dHA6Ly93d3cub3BlbnNvdXJjZS5vcmcvbGljZW5zZXMvbWl0LWxpY2Vuc2UucGhwKVxuICpcbiAqIFBlcm1pc3Npb24gaXMgaGVyZWJ5IGdyYW50ZWQsIGZyZWUgb2YgY2hhcmdlLCB0byBhbnkgcGVyc29uXG4gKiBvYnRhaW5pbmcgYSBjb3B5IG9mIHRoaXMgc29mdHdhcmUgYW5kIGFzc29jaWF0ZWQgZG9jdW1lbnRhdGlvblxuICogZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluIHRoZSBTb2Z0d2FyZSB3aXRob3V0XG4gKiByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvIHVzZSxcbiAqIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YiBsaWNlbnNlLCBhbmQvb3Igc2VsbFxuICogY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlXG4gKiBTb2Z0d2FyZSBpcyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZ1xuICogY29uZGl0aW9uczpcbiAqXG4gKiBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZVxuICogaW5jbHVkZWQgaW4gYWxsIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4gKlxuICogVEhFIFNPRlRXQVJFIElTIFBST1ZJREVEIFwiQVMgSVNcIiwgV0lUSE9VVCBXQVJSQU5UWSBPRiBBTlkgS0lORCxcbiAqIEVYUFJFU1MgT1IgSU1QTElFRCwgSU5DTFVESU5HIEJVVCBOT1QgTElNSVRFRCBUTyBUSEUgV0FSUkFOVElFU1xuICogT0YgTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTIEZPUiBBIFBBUlRJQ1VMQVIgUFVSUE9TRSBBTkRcbiAqIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1IgQ09QWVJJR0hUXG4gKiBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSxcbiAqIFdIRVRIRVIgSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lOR1xuICogRlJPTSwgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUlxuICogT1RIRVIgREVBTElOR1MgSU4gVEhFIFNPRlRXQVJFLlxuICovXG5cbmltcG9ydCBBdXRvTnVtZXJpYyBmcm9tICcuL0F1dG9OdW1lcmljJztcbmltcG9ydCBBdXRvTnVtZXJpY09wdGlvbnMgZnJvbSAnLi9BdXRvTnVtZXJpY09wdGlvbnMnO1xuXG4vKiBlc2xpbnQgbm8tdW51c2VkLXZhcnM6IDAgKi9cblxuLyoqXG4gKiBUaGUgZGVmYXVsdHMgb3B0aW9ucy5cbiAqIFRoZXNlIGNhbiBiZSBvdmVycmlkZGVuIGJ5IHRoZSBmb2xsb3dpbmcgbWV0aG9kczpcbiAqIC0gSFRNTDUgZGF0YSBhdHRyaWJ1dGVzIChpZS4gYDxpbnB1dCB0eXBlPVwidGV4dFwiIGRhdGEtY3VycmVuY3ktc3ltYm9sPVwiIOKCrFwiPmApXG4gKiAtIE9wdGlvbnMgcGFzc2VkIHRvIHRoZSBgdXBkYXRlYCBtZXRob2QgKGllLiBgYW5FbGVtZW50LnVwZGF0ZSh7IGN1cnJlbmN5U3ltYm9sOiAnIOKCrCcgfSk7YCksIG9yIHNpbXBseSBkdXJpbmcgdGhlIGluaXRpYWxpemF0aW9uIChpZS4gYG5ldyBBdXRvTnVtZXJpYyhkb21FbGVtZW50LCB7b3B0aW9uc30pO2ApXG4gKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShBdXRvTnVtZXJpYywgJ2RlZmF1bHRTZXR0aW5ncycsIHtcbiAgICBnZXQoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBhbGxvd0RlY2ltYWxQYWRkaW5nICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nLmFsd2F5cyxcbiAgICAgICAgICAgIGNhcmV0UG9zaXRpb25PbkZvY3VzICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmNhcmV0UG9zaXRpb25PbkZvY3VzLmRvTm9Gb3JjZUNhcmV0UG9zaXRpb24sXG4gICAgICAgICAgICBjcmVhdGVMb2NhbExpc3QgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jcmVhdGVMb2NhbExpc3QuY3JlYXRlTGlzdCxcbiAgICAgICAgICAgIGN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sLm5vbmUsXG4gICAgICAgICAgICBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXgsXG4gICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmRvdCxcbiAgICAgICAgICAgIGRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZS5ub25lLFxuICAgICAgICAgICAgZGVjaW1hbFBsYWNlcyAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlcy50d28sXG4gICAgICAgICAgICBkZWNpbWFsUGxhY2VzUmF3VmFsdWUgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsUGxhY2VzUmF3VmFsdWUudXNlRGVmYXVsdCxcbiAgICAgICAgICAgIGRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ciAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxQbGFjZXNTaG93bk9uQmx1ci51c2VEZWZhdWx0LFxuICAgICAgICAgICAgZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cyAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbFBsYWNlc1Nob3duT25Gb2N1cy51c2VEZWZhdWx0LFxuICAgICAgICAgICAgZGVmYXVsdFZhbHVlT3ZlcnJpZGUgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVmYXVsdFZhbHVlT3ZlcnJpZGUuZG9Ob3RPdmVycmlkZSxcbiAgICAgICAgICAgIGRpZ2l0YWxHcm91cFNwYWNpbmcgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0YWxHcm91cFNwYWNpbmcudGhyZWUsXG4gICAgICAgICAgICBkaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmNvbW1hLFxuICAgICAgICAgICAgZGl2aXNvcldoZW5VbmZvY3VzZWQgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGl2aXNvcldoZW5VbmZvY3VzZWQubm9uZSxcbiAgICAgICAgICAgIGVtcHR5SW5wdXRCZWhhdmlvciAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmVtcHR5SW5wdXRCZWhhdmlvci5mb2N1cyxcbiAgICAgICAgICAgIGZhaWxPblVua25vd25PcHRpb24gICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmZhaWxPblVua25vd25PcHRpb24uaWdub3JlLFxuICAgICAgICAgICAgZm9ybWF0T25QYWdlTG9hZCAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZm9ybWF0T25QYWdlTG9hZC5mb3JtYXQsXG4gICAgICAgICAgICBoaXN0b3J5U2l6ZSAgICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5oaXN0b3J5U2l6ZS5tZWRpdW0sXG4gICAgICAgICAgICBpc0NhbmNlbGxhYmxlICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5pc0NhbmNlbGxhYmxlLmNhbmNlbGxhYmxlLFxuICAgICAgICAgICAgbGVhZGluZ1plcm8gICAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubGVhZGluZ1plcm8uZGVueSxcbiAgICAgICAgICAgIG1heGltdW1WYWx1ZSAgICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm1heGltdW1WYWx1ZS50ZW5UcmlsbGlvbnMsXG4gICAgICAgICAgICBtaW5pbXVtVmFsdWUgICAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5taW5pbXVtVmFsdWUudGVuVHJpbGxpb25zLFxuICAgICAgICAgICAgbW9kaWZ5VmFsdWVPbldoZWVsICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubW9kaWZ5VmFsdWVPbldoZWVsLm1vZGlmeVZhbHVlLFxuICAgICAgICAgICAgbmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIubm9uZSxcbiAgICAgICAgICAgIG5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50OiBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50Lm5vbmUsXG4gICAgICAgICAgICBub0V2ZW50TGlzdGVuZXJzICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5ub0V2ZW50TGlzdGVuZXJzLmFkZEV2ZW50cyxcbiAgICAgICAgICAgIC8vVE9ETyBTaG91bGRuJ3Qgd2UgdXNlIGB0cnVuY2F0ZWAgYXMgdGhlIGRlZmF1bHQgdmFsdWU/XG4gICAgICAgICAgICBvbkludmFsaWRQYXN0ZSAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5vbkludmFsaWRQYXN0ZS5lcnJvcixcbiAgICAgICAgICAgIG91dHB1dEZvcm1hdCAgICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm91dHB1dEZvcm1hdC5ub25lLFxuICAgICAgICAgICAgb3ZlcnJpZGVNaW5NYXhMaW1pdHMgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMub3ZlcnJpZGVNaW5NYXhMaW1pdHMuZG9Ob3RPdmVycmlkZSxcbiAgICAgICAgICAgIHJhd1ZhbHVlRGl2aXNvciAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLnJhd1ZhbHVlRGl2aXNvci5ub25lLFxuICAgICAgICAgICAgcmVhZE9ubHkgICAgICAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMucmVhZE9ubHkucmVhZFdyaXRlLFxuICAgICAgICAgICAgcm91bmRpbmdNZXRob2QgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMucm91bmRpbmdNZXRob2QuaGFsZlVwU3ltbWV0cmljLFxuICAgICAgICAgICAgc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZSAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuc2F2ZVZhbHVlVG9TZXNzaW9uU3RvcmFnZS5kb05vdFNhdmUsXG4gICAgICAgICAgICBzZWxlY3ROdW1iZXJPbmx5ICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5zZWxlY3ROdW1iZXJPbmx5LnNlbGVjdE51bWJlcnNPbmx5LFxuICAgICAgICAgICAgc2VsZWN0T25Gb2N1cyAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuc2VsZWN0T25Gb2N1cy5zZWxlY3QsXG4gICAgICAgICAgICBzZXJpYWxpemVTcGFjZXMgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5zZXJpYWxpemVTcGFjZXMucGx1cyxcbiAgICAgICAgICAgIHNob3dPbmx5TnVtYmVyc09uRm9jdXMgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLnNob3dPbmx5TnVtYmVyc09uRm9jdXMuc2hvd0FsbCxcbiAgICAgICAgICAgIHNob3dQb3NpdGl2ZVNpZ24gICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLnNob3dQb3NpdGl2ZVNpZ24uaGlkZSxcbiAgICAgICAgICAgIHNob3dXYXJuaW5ncyAgICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLnNob3dXYXJuaW5ncy5zaG93LFxuICAgICAgICAgICAgc3R5bGVSdWxlcyAgICAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuc3R5bGVSdWxlcy5ub25lLFxuICAgICAgICAgICAgc3VmZml4VGV4dCAgICAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuc3VmZml4VGV4dC5ub25lLFxuICAgICAgICAgICAgc3ltYm9sV2hlblVuZm9jdXNlZCAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuc3ltYm9sV2hlblVuZm9jdXNlZC5ub25lLFxuICAgICAgICAgICAgdW5mb3JtYXRPbkhvdmVyICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMudW5mb3JtYXRPbkhvdmVyLnVuZm9ybWF0LFxuICAgICAgICAgICAgdW5mb3JtYXRPblN1Ym1pdCAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMudW5mb3JtYXRPblN1Ym1pdC5rZWVwQ3VycmVudFZhbHVlLFxuICAgICAgICAgICAgd2hlZWxTdGVwICAgICAgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMud2hlZWxTdGVwLnByb2dyZXNzaXZlLFxuICAgICAgICB9O1xuICAgIH0sXG59KTtcblxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL0F1dG9OdW1lcmljRGVmYXVsdFNldHRpbmdzLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==");

/***/ },
/* 6 */
/***/ function(module, exports, __webpack_require__) {

	eval("/*** IMPORTS FROM imports-loader ***/\n(function() {\n\n'use strict';\n\nvar _AutoNumeric = __webpack_require__(1);\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 {{formatted: string, minRangeExceeded: string, maxRangeExceeded: string, native: {input: string, change: string}}}\n */\nObject.defineProperty(_AutoNumeric2.default, 'events', {\n    get: function get() {\n        return {\n            formatted: 'autoNumeric:formatted',\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 <alexandre.bonneau@linuxfr.eu>\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}.call(window));//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvQXV0b051bWVyaWNFdmVudHMuanM/N2JkMyJdLCJuYW1lcyI6WyJPYmplY3QiLCJkZWZpbmVQcm9wZXJ0eSIsImdldCIsImZvcm1hdHRlZCIsIm1pblJhbmdlRXhjZWVkZWQiLCJtYXhSYW5nZUV4Y2VlZGVkIiwibmF0aXZlIiwiaW5wdXQiLCJjaGFuZ2UiXSwibWFwcGluZ3MiOiI7Ozs7O0FBNkJBOzs7Ozs7QUFFQTs7Ozs7QUFLQUEsT0FBT0MsY0FBUCx3QkFBbUMsUUFBbkMsRUFBNkM7QUFDekNDLE9BRHlDLGlCQUNuQztBQUNGLGVBQU87QUFDSEMsdUJBQWtCLHVCQURmO0FBRUhDLDhCQUFrQix5QkFGZjtBQUdIQyw4QkFBa0IseUJBSGY7QUFJSEMsb0JBQWtCO0FBQ2RDLHVCQUFRLE9BRE07QUFFZEMsd0JBQVE7QUFGTTtBQUpmLFNBQVA7QUFTSDtBQVh3QyxDQUE3QyxFLENBcENBIiwiZmlsZSI6IjYuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIE9wdGlvbnMgZm9yIGF1dG9OdW1lcmljLmpzXG4gKiBAYXV0aG9yIEFsZXhhbmRyZSBCb25uZWF1IDxhbGV4YW5kcmUuYm9ubmVhdUBsaW51eGZyLmV1PlxuICogQGNvcHlyaWdodCDCqSAyMDE3IEFsZXhhbmRyZSBCb25uZWF1XG4gKlxuICogVGhlIE1JVCBMaWNlbnNlIChodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocClcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvblxuICogb2J0YWluaW5nIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb25cbiAqIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dFxuICogcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsXG4gKiBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWIgbGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZVxuICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmdcbiAqIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsXG4gKiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVNcbiAqIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EXG4gKiBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVFxuICogSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksXG4gKiBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1JcbiAqIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgQXV0b051bWVyaWMgZnJvbSAnLi9BdXRvTnVtZXJpYyc7XG5cbi8qKlxuICogRXZlbnQgbGlzdCBtYW5hZ2VkIGJ5IEF1dG9OdW1lcmljXG4gKlxuICogQHR5cGUge3tmb3JtYXR0ZWQ6IHN0cmluZywgbWluUmFuZ2VFeGNlZWRlZDogc3RyaW5nLCBtYXhSYW5nZUV4Y2VlZGVkOiBzdHJpbmcsIG5hdGl2ZToge2lucHV0OiBzdHJpbmcsIGNoYW5nZTogc3RyaW5nfX19XG4gKi9cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShBdXRvTnVtZXJpYywgJ2V2ZW50cycsIHtcbiAgICBnZXQoKSB7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICBmb3JtYXR0ZWQgICAgICAgOiAnYXV0b051bWVyaWM6Zm9ybWF0dGVkJyxcbiAgICAgICAgICAgIG1pblJhbmdlRXhjZWVkZWQ6ICdhdXRvTnVtZXJpYzptaW5FeGNlZWRlZCcsXG4gICAgICAgICAgICBtYXhSYW5nZUV4Y2VlZGVkOiAnYXV0b051bWVyaWM6bWF4RXhjZWVkZWQnLFxuICAgICAgICAgICAgbmF0aXZlICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgIGlucHV0IDogJ2lucHV0JyxcbiAgICAgICAgICAgICAgICBjaGFuZ2U6ICdjaGFuZ2UnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICB9LFxufSk7XG5cblxuXG4vLyBXRUJQQUNLIEZPT1RFUiAvL1xuLy8gLi9zcmMvQXV0b051bWVyaWNFdmVudHMuanMiXSwic291cmNlUm9vdCI6IiJ9");

/***/ },
/* 7 */
/***/ function(module, exports, __webpack_require__) {

	eval("/*** IMPORTS FROM imports-loader ***/\n(function() {\n\n'use strict';\n\nvar _AutoNumeric = __webpack_require__(1);\n\nvar _AutoNumeric2 = _interopRequireDefault(_AutoNumeric);\n\nvar _AutoNumericHelper = __webpack_require__(3);\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 <alexandre.bonneau@linuxfr.eu>\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 it without affecting it\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\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            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}.call(window));//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvQXV0b051bWVyaWNQcmVkZWZpbmVkT3B0aW9ucy5qcz84ZWM5Il0sIm5hbWVzIjpbImV1cm8iLCJkaWdpdEdyb3VwU2VwYXJhdG9yIiwib3B0aW9ucyIsImRvdCIsImRlY2ltYWxDaGFyYWN0ZXIiLCJjb21tYSIsImRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSIsImN1cnJlbmN5U3ltYm9sIiwiY3VycmVuY3lTeW1ib2xQbGFjZW1lbnQiLCJzdWZmaXgiLCJuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCIsInByZWZpeCIsImRvbGxhciIsInJpZ2h0IiwiamFwYW5lc2UiLCJ5ZW4iLCJldXJvUG9zIiwiY2xvbmVPYmplY3QiLCJtaW5pbXVtVmFsdWUiLCJldXJvTmVnIiwibWF4aW11bVZhbHVlIiwiZXVyb1NwYWNlIiwibm9ybWFsU3BhY2UiLCJldXJvU3BhY2VQb3MiLCJldXJvU3BhY2VOZWciLCJwZXJjZW50YWdlRVUyZGVjIiwibm9uZSIsInN1ZmZpeFRleHQiLCJwZXJjZW50YWdlIiwid2hlZWxTdGVwIiwicmF3VmFsdWVEaXZpc29yIiwicGVyY2VudGFnZUVVMmRlY1BvcyIsInBlcmNlbnRhZ2VFVTJkZWNOZWciLCJwZXJjZW50YWdlRVUzZGVjIiwiZGVjaW1hbFBsYWNlcyIsInBlcmNlbnRhZ2VFVTNkZWNQb3MiLCJwZXJjZW50YWdlRVUzZGVjTmVnIiwiZG9sbGFyUG9zIiwiZG9sbGFyTmVnIiwiZG9sbGFyTmVnQnJhY2tldHMiLCJuZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciIsInBhcmVudGhlc2VzIiwicGVyY2VudGFnZVVTMmRlYyIsInBlcmNlbnRhZ2VVUzJkZWNQb3MiLCJwZXJjZW50YWdlVVMyZGVjTmVnIiwicGVyY2VudGFnZVVTM2RlYyIsInBlcmNlbnRhZ2VVUzNkZWNQb3MiLCJwZXJjZW50YWdlVVMzZGVjTmVnIiwiT2JqZWN0IiwiZGVmaW5lUHJvcGVydHkiLCJnZXQiLCJGcmVuY2giLCJTcGFuaXNoIiwiTm9ydGhBbWVyaWNhbiIsIkJyaXRpc2giLCJwb3VuZCIsIlN3aXNzIiwiYXBvc3Ryb3BoZSIsIkphcGFuZXNlIiwiQ2hpbmVzZSIsIkJyYXppbGlhbiIsInJlYWwiLCJkb3REZWNpbWFsQ2hhckNvbW1hU2VwYXJhdG9yIiwiY29tbWFEZWNpbWFsQ2hhckRvdFNlcGFyYXRvciIsImludGVnZXIiLCJpbnRlZ2VyUG9zIiwiemVybyIsImludGVnZXJOZWciLCJmbG9hdCIsImFsbG93RGVjaW1hbFBhZGRpbmciLCJuZXZlciIsImZsb2F0UG9zIiwidGVuVHJpbGxpb25zIiwiZmxvYXROZWciLCJudW1lcmljIiwibm9TZXBhcmF0b3IiLCJudW1lcmljUG9zIiwibnVtZXJpY05lZyJdLCJtYXBwaW5ncyI6Ijs7Ozs7QUE2QkE7Ozs7QUFDQTs7Ozs7O0FBOUJBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQWdDQSxJQUFNQSxPQUFPLEVBQUU7QUFDWEMseUJBQStCLHNCQUFZQyxPQUFaLENBQW9CRCxtQkFBcEIsQ0FBd0NFLEdBRDlELEVBQ21FO0FBQzVFQyxzQkFBK0Isc0JBQVlGLE9BQVosQ0FBb0JFLGdCQUFwQixDQUFxQ0MsS0FGM0Q7QUFHVEMsaUNBQStCLHNCQUFZSixPQUFaLENBQW9CSSwyQkFBcEIsQ0FBZ0RILEdBSHRFO0FBSVRJLG9CQUErQixjQUp0QjtBQUtUQyw2QkFBK0Isc0JBQVlOLE9BQVosQ0FBb0JNLHVCQUFwQixDQUE0Q0MsTUFMbEU7QUFNVEMsbUNBQStCLHNCQUFZUixPQUFaLENBQW9CUSw2QkFBcEIsQ0FBa0RDO0FBTnhFLENBQWI7O0FBU0EsSUFBTUMsU0FBUztBQUNYWCx5QkFBK0Isc0JBQVlDLE9BQVosQ0FBb0JELG1CQUFwQixDQUF3Q0ksS0FENUQ7QUFFWEQsc0JBQStCLHNCQUFZRixPQUFaLENBQW9CRSxnQkFBcEIsQ0FBcUNELEdBRnpEO0FBR1hJLG9CQUErQixzQkFBWUwsT0FBWixDQUFvQkssY0FBcEIsQ0FBbUNLLE1BSHZEO0FBSVhKLDZCQUEr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RjNCO0FBdUZIa0Qsd0JBQThCO0FBQzFCM0UscUNBQXFCLHNCQUFZQyxPQUFaLENBQW9CRCxtQkFBcEIsQ0FBd0MwRSxXQURuQztBQUUxQnZFLGtDQUFxQixzQkFBWUYsT0FBWixDQUFvQkUsZ0JBQXBCLENBQXFDRCxHQUZoQztBQUcxQkksZ0NBQXFCLHNCQUFZTCxPQUFaLENBQW9CSyxjQUFwQixDQUFtQ21CLElBSDlCO0FBSTFCUiw4QkFBcUIsc0JBQVloQixPQUFaLENBQW9CZ0IsWUFBcEIsQ0FBaUNnRCxJQUo1QjtBQUsxQjlDLDhCQUFxQixzQkFBWWxCLE9BQVosQ0FBb0JrQixZQUFwQixDQUFpQ29EO0FBTDVCLGFBdkYzQjtBQThGSEssd0JBQThCO0FBQzFCNUUscUNBQXFCLHNCQUFZQyxPQUFaLENBQW9CRCxtQkFBcEIsQ0FBd0MwRSxXQURuQztBQUUxQnZFLGtDQUFxQixzQkFBWUYsT0FBWixDQUFvQkUsZ0JBQXBCLENBQXFDRCxHQUZoQztBQUcxQkksZ0NBQXFCLHNCQUFZTCxPQUFaLENBQW9CSyxjQUFwQixDQUFtQ21CLElBSDlCO0FBSTFCUiw4QkFBcUIsc0JBQVloQixPQUFaLENBQW9CZ0IsWUFBcEIsQ0FBaUNzRCxZQUo1QjtBQUsxQnBELDhCQUFxQixzQkFBWWxCLE9BQVosQ0FBb0JrQixZQUFwQixDQUFpQzhDO0FBTDVCO0FBOUYzQixTQUFQO0FBc0dIO0FBeEdtRCxDQUF4RCxFIiwiZmlsZSI6IjcuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIFByZS1kZWZpbmVkIG9wdGlvbnMgZm9yIGF1dG9OdW1lcmljLmpzXG4gKiBAYXV0aG9yIEFsZXhhbmRyZSBCb25uZWF1IDxhbGV4YW5kcmUuYm9ubmVhdUBsaW51eGZyLmV1PlxuICogQGNvcHlyaWdodCDCqSAyMDE2IEFsZXhhbmRyZSBCb25uZWF1XG4gKlxuICogVGhlIE1JVCBMaWNlbnNlIChodHRwOi8vd3d3Lm9wZW5zb3VyY2Uub3JnL2xpY2Vuc2VzL21pdC1saWNlbnNlLnBocClcbiAqXG4gKiBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvblxuICogb2J0YWluaW5nIGEgY29weSBvZiB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb25cbiAqIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbCBpbiB0aGUgU29mdHdhcmUgd2l0aG91dFxuICogcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0cyB0byB1c2UsXG4gKiBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWIgbGljZW5zZSwgYW5kL29yIHNlbGxcbiAqIGNvcGllcyBvZiB0aGUgU29mdHdhcmUsIGFuZCB0byBwZXJtaXQgcGVyc29ucyB0byB3aG9tIHRoZVxuICogU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLCBzdWJqZWN0IHRvIHRoZSBmb2xsb3dpbmdcbiAqIGNvbmRpdGlvbnM6XG4gKlxuICogVGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UgYW5kIHRoaXMgcGVybWlzc2lvbiBub3RpY2Ugc2hhbGwgYmVcbiAqIGluY2x1ZGVkIGluIGFsbCBjb3BpZXMgb3Igc3Vic3RhbnRpYWwgcG9ydGlvbnMgb2YgdGhlIFNvZnR3YXJlLlxuICpcbiAqIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsXG4gKiBFWFBSRVNTIE9SIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVNcbiAqIE9GIE1FUkNIQU5UQUJJTElUWSwgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EXG4gKiBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRSBBVVRIT1JTIE9SIENPUFlSSUdIVFxuICogSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUiBMSUFCSUxJVFksXG4gKiBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkdcbiAqIEZST00sIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1JcbiAqIE9USEVSIERFQUxJTkdTIElOIFRIRSBTT0ZUV0FSRS5cbiAqL1xuXG5pbXBvcnQgQXV0b051bWVyaWMgZnJvbSAnLi9BdXRvTnVtZXJpYyc7XG5pbXBvcnQgQXV0b051bWVyaWNIZWxwZXIgZnJvbSAnLi9BdXRvTnVtZXJpY0hlbHBlcic7XG5cbmNvbnN0IGV1cm8gPSB7IC8vIEZyYW7Dp2Fpc1xuICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3IgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IuZG90LCAvLyBvciAnXFx1MjAyZidcbiAgICBkZWNpbWFsQ2hhcmFjdGVyICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmNvbW1hLFxuICAgIGRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZSAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXJBbHRlcm5hdGl2ZS5kb3QsXG4gICAgY3VycmVuY3lTeW1ib2wgICAgICAgICAgICAgICA6ICdcXHUyMDJm4oKsJyxcbiAgICBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgsXG4gICAgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4LFxufTtcblxuY29uc3QgZG9sbGFyID0ge1xuICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3IgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3IuY29tbWEsXG4gICAgZGVjaW1hbENoYXJhY3RlciAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5kb3QsXG4gICAgY3VycmVuY3lTeW1ib2wgICAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2wuZG9sbGFyLFxuICAgIGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCxcbiAgICBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodCxcbn07XG5cbmNvbnN0IGphcGFuZXNlID0geyAvLyDml6XmnKzoqp5cbiAgICBkaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmNvbW1hLFxuICAgIGRlY2ltYWxDaGFyYWN0ZXIgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuZG90LFxuICAgIGN1cnJlbmN5U3ltYm9sICAgICAgICAgICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sLnllbixcbiAgICBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXgsXG4gICAgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQsXG59O1xuXG5cbi8vIEhlcmUgd2UgbmVlZCB0byBjbG9uZSB0aGUgaW5pdGlhbCBvYmplY3RzIGluIG9yZGVyIHRvIGJlIGFibGUgdG8gZWRpdCBpdCB3aXRob3V0IGFmZmVjdGluZyBpdFxuY29uc3QgZXVyb1BvcyAgICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KGV1cm8pO1xuZXVyb1Bvcy5taW5pbXVtVmFsdWUgICAgICAgICAgICAgICAgICA9IDA7XG5jb25zdCBldXJvTmVnICAgICAgICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QoZXVybyk7XG5ldXJvTmVnLm1heGltdW1WYWx1ZSAgICAgICAgICAgICAgICAgID0gMDtcbmV1cm9OZWcubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQgPSBBdXRvTnVtZXJpYy5vcHRpb25zLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50LnByZWZpeDtcblxuY29uc3QgZXVyb1NwYWNlICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QoZXVybyk7XG5ldXJvU3BhY2UuZGlnaXRHcm91cFNlcGFyYXRvciAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3Iubm9ybWFsU3BhY2U7XG5jb25zdCBldXJvU3BhY2VQb3MgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChldXJvU3BhY2UpO1xuZXVyb1NwYWNlUG9zLm1pbmltdW1WYWx1ZSAgICAgICAgICAgICAgICAgID0gMDtcbmNvbnN0IGV1cm9TcGFjZU5lZyAgICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KGV1cm9TcGFjZSk7XG5ldXJvU3BhY2VOZWcubWF4aW11bVZhbHVlICAgICAgICAgICAgICAgICAgPSAwO1xuZXVyb1NwYWNlTmVnLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg7XG5cbmNvbnN0IHBlcmNlbnRhZ2VFVTJkZWMgICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChldXJvKTtcbnBlcmNlbnRhZ2VFVTJkZWMuY3VycmVuY3lTeW1ib2wgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sLm5vbmU7XG5wZXJjZW50YWdlRVUyZGVjLnN1ZmZpeFRleHQgICAgICAgICAgICAgICAgICAgICAgID0gYFxcdTIwMmYke0F1dG9OdW1lcmljLm9wdGlvbnMuc3VmZml4VGV4dC5wZXJjZW50YWdlfWA7XG5wZXJjZW50YWdlRVUyZGVjLndoZWVsU3RlcCAgICAgICAgICAgICAgICAgICAgICAgID0gMC4wMDAxOyAvLyBUaGlzIHRhcmdldHMgdGhlIGByYXdWYWx1ZWAsIG5vdCB0aGUgZm9ybWF0dGVkIG9uZVxucGVyY2VudGFnZUVVMmRlYy5yYXdWYWx1ZURpdmlzb3IgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljLm9wdGlvbnMucmF3VmFsdWVEaXZpc29yLnBlcmNlbnRhZ2U7XG5jb25zdCBwZXJjZW50YWdlRVUyZGVjUG9zICAgICAgICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QocGVyY2VudGFnZUVVMmRlYyk7XG5wZXJjZW50YWdlRVUyZGVjUG9zLm1pbmltdW1WYWx1ZSAgICAgICAgICAgICAgICAgID0gMDtcbmNvbnN0IHBlcmNlbnRhZ2VFVTJkZWNOZWcgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChwZXJjZW50YWdlRVUyZGVjKTtcbnBlcmNlbnRhZ2VFVTJkZWNOZWcubWF4aW11bVZhbHVlICAgICAgICAgICAgICAgICAgPSAwO1xucGVyY2VudGFnZUVVMmRlY05lZy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCA9IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4O1xuXG5jb25zdCBwZXJjZW50YWdlRVUzZGVjICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChwZXJjZW50YWdlRVUyZGVjKTtcbnBlcmNlbnRhZ2VFVTNkZWMuZGVjaW1hbFBsYWNlcyAgICA9IDM7XG5jb25zdCBwZXJjZW50YWdlRVUzZGVjUG9zICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChwZXJjZW50YWdlRVUyZGVjUG9zKTtcbnBlcmNlbnRhZ2VFVTNkZWNQb3MuZGVjaW1hbFBsYWNlcyA9IDM7XG5jb25zdCBwZXJjZW50YWdlRVUzZGVjTmVnICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChwZXJjZW50YWdlRVUyZGVjTmVnKTtcbnBlcmNlbnRhZ2VFVTNkZWNOZWcuZGVjaW1hbFBsYWNlcyA9IDM7XG5cbmNvbnN0IGRvbGxhclBvcyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QoZG9sbGFyKTtcbmRvbGxhclBvcy5taW5pbXVtVmFsdWUgICAgICAgICAgICAgICAgICAgICAgID0gMDtcbmNvbnN0IGRvbGxhck5lZyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWNIZWxwZXIuY2xvbmVPYmplY3QoZG9sbGFyKTtcbmRvbGxhck5lZy5tYXhpbXVtVmFsdWUgICAgICAgICAgICAgICAgICAgICAgID0gMDtcbmRvbGxhck5lZy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudCAgICAgID0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg7XG5jb25zdCBkb2xsYXJOZWdCcmFja2V0cyAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KGRvbGxhck5lZyk7XG5kb2xsYXJOZWdCcmFja2V0cy5uZWdhdGl2ZUJyYWNrZXRzVHlwZU9uQmx1ciA9IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVCcmFja2V0c1R5cGVPbkJsdXIucGFyZW50aGVzZXM7XG5cbmNvbnN0IHBlcmNlbnRhZ2VVUzJkZWMgICAgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChkb2xsYXIpO1xucGVyY2VudGFnZVVTMmRlYy5jdXJyZW5jeVN5bWJvbCAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2wubm9uZTtcbnBlcmNlbnRhZ2VVUzJkZWMuc3VmZml4VGV4dCAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpYy5vcHRpb25zLnN1ZmZpeFRleHQucGVyY2VudGFnZTtcbnBlcmNlbnRhZ2VVUzJkZWMud2hlZWxTdGVwICAgICAgICAgICAgICAgICAgICAgICAgPSAwLjAwMDE7XG5wZXJjZW50YWdlRVUyZGVjLnJhd1ZhbHVlRGl2aXNvciAgICAgICAgICAgICAgICAgID0gQXV0b051bWVyaWMub3B0aW9ucy5yYXdWYWx1ZURpdmlzb3IucGVyY2VudGFnZTtcbmNvbnN0IHBlcmNlbnRhZ2VVUzJkZWNQb3MgICAgICAgICAgICAgICAgICAgICAgICAgPSBBdXRvTnVtZXJpY0hlbHBlci5jbG9uZU9iamVjdChwZXJjZW50YWdlVVMyZGVjKTtcbnBlcmNlbnRhZ2VVUzJkZWNQb3MubWluaW11bVZhbHVlICAgICAgICAgICAgICAgICAgPSAwO1xuY29uc3QgcGVyY2VudGFnZVVTMmRlY05lZyAgICAgICAgICAgICAgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VVUzJkZWMpO1xucGVyY2VudGFnZVVTMmRlY05lZy5tYXhpbXVtVmFsdWUgICAgICAgICAgICAgICAgICA9IDA7XG5wZXJjZW50YWdlVVMyZGVjTmVnLm5lZ2F0aXZlUG9zaXRpdmVTaWduUGxhY2VtZW50ID0gQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5wcmVmaXg7XG5cbmNvbnN0IHBlcmNlbnRhZ2VVUzNkZWMgICAgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VVUzJkZWMpO1xucGVyY2VudGFnZVVTM2RlYy5kZWNpbWFsUGxhY2VzICAgID0gMztcbmNvbnN0IHBlcmNlbnRhZ2VVUzNkZWNQb3MgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VVUzJkZWNQb3MpO1xucGVyY2VudGFnZVVTM2RlY1Bvcy5kZWNpbWFsUGxhY2VzID0gMztcbmNvbnN0IHBlcmNlbnRhZ2VVUzNkZWNOZWcgICAgICAgICA9IEF1dG9OdW1lcmljSGVscGVyLmNsb25lT2JqZWN0KHBlcmNlbnRhZ2VVUzJkZWNOZWcpO1xucGVyY2VudGFnZVVTM2RlY05lZy5kZWNpbWFsUGxhY2VzID0gMztcblxuLyoqXG4gKiBQcmVkZWZpbmVkIG9wdGlvbnMgZm9yIHRoZSBtb3N0IGNvbW1vbiBsYW5ndWFnZXNcbiAqL1xuT2JqZWN0LmRlZmluZVByb3BlcnR5KEF1dG9OdW1lcmljLCAncHJlZGVmaW5lZE9wdGlvbnMnLCB7XG4gICAgZ2V0KCkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZXVybyxcbiAgICAgICAgICAgIGV1cm9Qb3MsXG4gICAgICAgICAgICBldXJvTmVnLFxuICAgICAgICAgICAgZXVyb1NwYWNlLFxuICAgICAgICAgICAgZXVyb1NwYWNlUG9zLFxuICAgICAgICAgICAgZXVyb1NwYWNlTmVnLFxuICAgICAgICAgICAgcGVyY2VudGFnZUVVMmRlYyxcbiAgICAgICAgICAgIHBlcmNlbnRhZ2VFVTJkZWNQb3MsXG4gICAgICAgICAgICBwZXJjZW50YWdlRVUyZGVjTmVnLFxuICAgICAgICAgICAgcGVyY2VudGFnZUVVM2RlYyxcbiAgICAgICAgICAgIHBlcmNlbnRhZ2VFVTNkZWNQb3MsXG4gICAgICAgICAgICBwZXJjZW50YWdlRVUzZGVjTmVnLFxuICAgICAgICAgICAgZG9sbGFyLFxuICAgICAgICAgICAgZG9sbGFyUG9zLFxuICAgICAgICAgICAgZG9sbGFyTmVnLFxuICAgICAgICAgICAgZG9sbGFyTmVnQnJhY2tldHMsXG4gICAgICAgICAgICBwZXJjZW50YWdlVVMyZGVjLFxuICAgICAgICAgICAgcGVyY2VudGFnZVVTMmRlY1BvcyxcbiAgICAgICAgICAgIHBlcmNlbnRhZ2VVUzJkZWNOZWcsXG4gICAgICAgICAgICBwZXJjZW50YWdlVVMzZGVjLFxuICAgICAgICAgICAgcGVyY2VudGFnZVVTM2RlY1BvcyxcbiAgICAgICAgICAgIHBlcmNlbnRhZ2VVUzNkZWNOZWcsXG4gICAgICAgICAgICBGcmVuY2ggICAgICAgICAgICAgICAgICAgICAgOiBldXJvLCAvLyBGcmFuw6dhaXNcbiAgICAgICAgICAgIFNwYW5pc2ggICAgICAgICAgICAgICAgICAgICA6IGV1cm8sIC8vIEVzcGHDsW9sXG4gICAgICAgICAgICBOb3J0aEFtZXJpY2FuICAgICAgICAgICAgICAgOiBkb2xsYXIsXG4gICAgICAgICAgICBCcml0aXNoICAgICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgZGlnaXRHcm91cFNlcGFyYXRvciAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5jb21tYSxcbiAgICAgICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmRvdCxcbiAgICAgICAgICAgICAgICBjdXJyZW5jeVN5bWJvbCAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC5wb3VuZCxcbiAgICAgICAgICAgICAgICBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5wcmVmaXgsXG4gICAgICAgICAgICAgICAgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucmlnaHQsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgU3dpc3MgICAgICAgICAgICAgICAgICAgICAgIDogeyAvLyBTdWlzc2VcbiAgICAgICAgICAgICAgICBkaWdpdEdyb3VwU2VwYXJhdG9yICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmFwb3N0cm9waGUsXG4gICAgICAgICAgICAgICAgZGVjaW1hbENoYXJhY3RlciAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5kb3QsXG4gICAgICAgICAgICAgICAgY3VycmVuY3lTeW1ib2wgICAgICAgICAgICAgICA6ICdcXHUyMDJmQ0hGJyxcbiAgICAgICAgICAgICAgICBjdXJyZW5jeVN5bWJvbFBsYWNlbWVudCAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbFBsYWNlbWVudC5zdWZmaXgsXG4gICAgICAgICAgICAgICAgbmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQ6IEF1dG9OdW1lcmljLm9wdGlvbnMubmVnYXRpdmVQb3NpdGl2ZVNpZ25QbGFjZW1lbnQucHJlZml4LFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIEphcGFuZXNlICAgICAgICAgICAgICAgICAgICA6IGphcGFuZXNlLCAvLyDml6XmnKzoqp5cbiAgICAgICAgICAgIENoaW5lc2UgICAgICAgICAgICAgICAgICAgICA6IGphcGFuZXNlLCAvLyDkuK3lm73oqp4gKENoaW5lc2UpXG4gICAgICAgICAgICBCcmF6aWxpYW4gICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgZGlnaXRHcm91cFNlcGFyYXRvciAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5kb3QsXG4gICAgICAgICAgICAgICAgZGVjaW1hbENoYXJhY3RlciAgICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5jb21tYSxcbiAgICAgICAgICAgICAgICBjdXJyZW5jeVN5bWJvbCAgICAgICAgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC5yZWFsLFxuICAgICAgICAgICAgICAgIGN1cnJlbmN5U3ltYm9sUGxhY2VtZW50ICAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sUGxhY2VtZW50LnByZWZpeCxcbiAgICAgICAgICAgICAgICBuZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudDogQXV0b051bWVyaWMub3B0aW9ucy5uZWdhdGl2ZVBvc2l0aXZlU2lnblBsYWNlbWVudC5yaWdodCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBkb3REZWNpbWFsQ2hhckNvbW1hU2VwYXJhdG9yOiB7XG4gICAgICAgICAgICAgICAgZGlnaXRHcm91cFNlcGFyYXRvcjogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmNvbW1hLFxuICAgICAgICAgICAgICAgIGRlY2ltYWxDaGFyYWN0ZXIgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5kb3QsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgY29tbWFEZWNpbWFsQ2hhckRvdFNlcGFyYXRvcjoge1xuICAgICAgICAgICAgICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3IgICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLmRvdCxcbiAgICAgICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyICAgICAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5jb21tYSxcbiAgICAgICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyQWx0ZXJuYXRpdmU6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3RlckFsdGVybmF0aXZlLmRvdCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpbnRlZ2VyICAgICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgZGVjaW1hbFBsYWNlczogMCxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBpbnRlZ2VyUG9zICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgbWluaW11bVZhbHVlIDogQXV0b051bWVyaWMub3B0aW9ucy5taW5pbXVtVmFsdWUuemVybyxcbiAgICAgICAgICAgICAgICBkZWNpbWFsUGxhY2VzOiAwLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGludGVnZXJOZWcgICAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICBtYXhpbXVtVmFsdWUgOiBBdXRvTnVtZXJpYy5vcHRpb25zLm1heGltdW1WYWx1ZS56ZXJvLFxuICAgICAgICAgICAgICAgIGRlY2ltYWxQbGFjZXM6IDAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZmxvYXQgICAgICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgIGFsbG93RGVjaW1hbFBhZGRpbmc6IEF1dG9OdW1lcmljLm9wdGlvbnMuYWxsb3dEZWNpbWFsUGFkZGluZy5uZXZlcixcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBmbG9hdFBvcyAgICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgYWxsb3dEZWNpbWFsUGFkZGluZzogQXV0b051bWVyaWMub3B0aW9ucy5hbGxvd0RlY2ltYWxQYWRkaW5nLm5ldmVyLFxuICAgICAgICAgICAgICAgIG1pbmltdW1WYWx1ZSAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubWluaW11bVZhbHVlLnplcm8sXG4gICAgICAgICAgICAgICAgbWF4aW11bVZhbHVlICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5tYXhpbXVtVmFsdWUudGVuVHJpbGxpb25zLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGZsb2F0TmVnICAgICAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICBhbGxvd0RlY2ltYWxQYWRkaW5nOiBBdXRvTnVtZXJpYy5vcHRpb25zLmFsbG93RGVjaW1hbFBhZGRpbmcubmV2ZXIsXG4gICAgICAgICAgICAgICAgbWluaW11bVZhbHVlICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5taW5pbXVtVmFsdWUudGVuVHJpbGxpb25zLFxuICAgICAgICAgICAgICAgIG1heGltdW1WYWx1ZSAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubWF4aW11bVZhbHVlLnplcm8sXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgbnVtZXJpYyAgICAgICAgICAgICAgICAgICAgIDoge1xuICAgICAgICAgICAgICAgIGRpZ2l0R3JvdXBTZXBhcmF0b3I6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGlnaXRHcm91cFNlcGFyYXRvci5ub1NlcGFyYXRvcixcbiAgICAgICAgICAgICAgICBkZWNpbWFsQ2hhcmFjdGVyICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRlY2ltYWxDaGFyYWN0ZXIuZG90LFxuICAgICAgICAgICAgICAgIGN1cnJlbmN5U3ltYm9sICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuY3VycmVuY3lTeW1ib2wubm9uZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBudW1lcmljUG9zICAgICAgICAgICAgICAgICAgOiB7XG4gICAgICAgICAgICAgICAgZGlnaXRHcm91cFNlcGFyYXRvcjogQXV0b051bWVyaWMub3B0aW9ucy5kaWdpdEdyb3VwU2VwYXJhdG9yLm5vU2VwYXJhdG9yLFxuICAgICAgICAgICAgICAgIGRlY2ltYWxDaGFyYWN0ZXIgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMuZGVjaW1hbENoYXJhY3Rlci5kb3QsXG4gICAgICAgICAgICAgICAgY3VycmVuY3lTeW1ib2wgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5jdXJyZW5jeVN5bWJvbC5ub25lLFxuICAgICAgICAgICAgICAgIG1pbmltdW1WYWx1ZSAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubWluaW11bVZhbHVlLnplcm8sXG4gICAgICAgICAgICAgICAgbWF4aW11bVZhbHVlICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5tYXhpbXVtVmFsdWUudGVuVHJpbGxpb25zLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIG51bWVyaWNOZWcgICAgICAgICAgICAgICAgICA6IHtcbiAgICAgICAgICAgICAgICBkaWdpdEdyb3VwU2VwYXJhdG9yOiBBdXRvTnVtZXJpYy5vcHRpb25zLmRpZ2l0R3JvdXBTZXBhcmF0b3Iubm9TZXBhcmF0b3IsXG4gICAgICAgICAgICAgICAgZGVjaW1hbENoYXJhY3RlciAgIDogQXV0b051bWVyaWMub3B0aW9ucy5kZWNpbWFsQ2hhcmFjdGVyLmRvdCxcbiAgICAgICAgICAgICAgICBjdXJyZW5jeVN5bWJvbCAgICAgOiBBdXRvTnVtZXJpYy5vcHRpb25zLmN1cnJlbmN5U3ltYm9sLm5vbmUsXG4gICAgICAgICAgICAgICAgbWluaW11bVZhbHVlICAgICAgIDogQXV0b051bWVyaWMub3B0aW9ucy5taW5pbXVtVmFsdWUudGVuVHJpbGxpb25zLFxuICAgICAgICAgICAgICAgIG1heGltdW1WYWx1ZSAgICAgICA6IEF1dG9OdW1lcmljLm9wdGlvbnMubWF4aW11bVZhbHVlLnplcm8sXG4gICAgICAgICAgICB9LFxuICAgICAgICB9O1xuICAgIH0sXG59KTtcblxuXG5cbi8vIFdFQlBBQ0sgRk9PVEVSIC8vXG4vLyAuL3NyYy9BdXRvTnVtZXJpY1ByZWRlZmluZWRPcHRpb25zLmpzIl0sInNvdXJjZVJvb3QiOiIifQ==");

/***/ },
/* 8 */
/***/ function(module, exports, __webpack_require__) {

	eval("/*** IMPORTS FROM imports-loader ***/\n(function() {\n\n'use strict';\n\nvar _AutoNumeric = __webpack_require__(1);\n\nvar _AutoNumeric2 = _interopRequireDefault(_AutoNumeric);\n\nvar _AutoNumericEvents = __webpack_require__(6);\n\nvar _AutoNumericEvents2 = _interopRequireDefault(_AutoNumericEvents);\n\nvar _AutoNumericOptions = __webpack_require__(4);\n\nvar _AutoNumericOptions2 = _interopRequireDefault(_AutoNumericOptions);\n\nvar _AutoNumericDefaultSettings = __webpack_require__(5);\n\nvar _AutoNumericDefaultSettings2 = _interopRequireDefault(_AutoNumericDefaultSettings);\n\nvar _AutoNumericPredefinedOptions = __webpack_require__(7);\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 * cf. workaround detailed here http://stackoverflow.com/a/33683495/2834898\n *\n * @type {AutoNumeric}\n */\nmodule.exports = _AutoNumeric2.default;\n//TODO Also export the AutoNumericEnum module\n/**\n * Babel + Webpack workaround for autoNumeric\n *\n * @author Alexandre Bonneau <alexandre.bonneau@linuxfr.eu>\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\n/* global module */\n}.call(window));//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly8vLi9zcmMvbWFpbi5qcz8zNDc5Il0sIm5hbWVzIjpbIm1vZHVsZSIsImV4cG9ydHMiXSwibWFwcGluZ3MiOiI7Ozs7O0FBZ0NBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUNBOzs7O0FBQ0E7Ozs7OztBQUVBOztBQUVBOzs7Ozs7QUFNQUEsT0FBT0MsT0FBUDtBQUNBO0FBL0NBOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUE4QkEsbUIiLCJmaWxlIjoiOC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQmFiZWwgKyBXZWJwYWNrIHdvcmthcm91bmQgZm9yIGF1dG9OdW1lcmljXG4gKlxuICogQGF1dGhvciBBbGV4YW5kcmUgQm9ubmVhdSA8YWxleGFuZHJlLmJvbm5lYXVAbGludXhmci5ldT5cbiAqIEBjb3B5cmlnaHQgwqkgMjAxNyBBbGV4YW5kcmUgQm9ubmVhdVxuICpcbiAqIFRoZSBNSVQgTGljZW5zZSAoaHR0cDovL3d3dy5vcGVuc291cmNlLm9yZy9saWNlbnNlcy9taXQtbGljZW5zZS5waHApXG4gKlxuICogUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb25cbiAqIG9idGFpbmluZyBhIGNvcHkgb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uXG4gKiBmaWxlcyAodGhlIFwiU29mdHdhcmVcIiksIHRvIGRlYWwgaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXRcbiAqIHJlc3RyaWN0aW9uLCBpbmNsdWRpbmcgd2l0aG91dCBsaW1pdGF0aW9uIHRoZSByaWdodHMgdG8gdXNlLFxuICogY29weSwgbW9kaWZ5LCBtZXJnZSwgcHVibGlzaCwgZGlzdHJpYnV0ZSwgc3ViIGxpY2Vuc2UsIGFuZC9vciBzZWxsXG4gKiBjb3BpZXMgb2YgdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGVcbiAqIFNvZnR3YXJlIGlzIGZ1cm5pc2hlZCB0byBkbyBzbywgc3ViamVjdCB0byB0aGUgZm9sbG93aW5nXG4gKiBjb25kaXRpb25zOlxuICpcbiAqIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlXG4gKiBpbmNsdWRlZCBpbiBhbGwgY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbiAqXG4gKiBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELFxuICogRVhQUkVTUyBPUiBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTXG4gKiBPRiBNRVJDSEFOVEFCSUxJVFksIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORFxuICogTk9OSU5GUklOR0VNRU5ULiBJTiBOTyBFVkVOVCBTSEFMTCBUSEUgQVVUSE9SUyBPUiBDT1BZUklHSFRcbiAqIEhPTERFUlMgQkUgTElBQkxFIEZPUiBBTlkgQ0xBSU0sIERBTUFHRVMgT1IgT1RIRVIgTElBQklMSVRZLFxuICogV0hFVEhFUiBJTiBBTiBBQ1RJT04gT0YgQ09OVFJBQ1QsIFRPUlQgT1IgT1RIRVJXSVNFLCBBUklTSU5HXG4gKiBGUk9NLCBPVVQgT0YgT1IgSU4gQ09OTkVDVElPTiBXSVRIIFRIRSBTT0ZUV0FSRSBPUiBUSEUgVVNFIE9SXG4gKiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG4gKi9cblxuLyogZ2xvYmFsIG1vZHVsZSAqL1xuXG5pbXBvcnQgQXV0b051bWVyaWMgZnJvbSAnLi9BdXRvTnVtZXJpYyc7XG5pbXBvcnQgQXV0b051bWVyaWNFdmVudHMgZnJvbSAnLi9BdXRvTnVtZXJpY0V2ZW50cyc7XG5pbXBvcnQgQXV0b051bWVyaWNPcHRpb25zIGZyb20gJy4vQXV0b051bWVyaWNPcHRpb25zJztcbmltcG9ydCBBdXRvTnVtZXJpY0RlZmF1bHRTZXR0aW5ncyBmcm9tICcuL0F1dG9OdW1lcmljRGVmYXVsdFNldHRpbmdzJztcbmltcG9ydCBBdXRvTnVtZXJpY1ByZWRlZmluZWRPcHRpb25zIGZyb20gJy4vQXV0b051bWVyaWNQcmVkZWZpbmVkT3B0aW9ucyc7XG5cbi8qIGVzbGludCBuby11bnVzZWQtdmFyczogMCAqL1xuXG4vKipcbiAqIFRoaXMgZmlsZSBzZXJ2ZSBhcyB0aGUgbWFpbiBlbnRyeSBwb2ludCB0byB0aGUgbGlicmFyeS5cbiAqIGNmLiB3b3JrYXJvdW5kIGRldGFpbGVkIGhlcmUgaHR0cDovL3N0YWNrb3ZlcmZsb3cuY29tL2EvMzM2ODM0OTUvMjgzNDg5OFxuICpcbiAqIEB0eXBlIHtBdXRvTnVtZXJpY31cbiAqL1xubW9kdWxlLmV4cG9ydHMgPSBBdXRvTnVtZXJpYztcbi8vVE9ETyBBbHNvIGV4cG9ydCB0aGUgQXV0b051bWVyaWNFbnVtIG1vZHVsZVxuXG5cblxuLy8gV0VCUEFDSyBGT09URVIgLy9cbi8vIC4vc3JjL21haW4uanMiXSwic291cmNlUm9vdCI6IiJ9");

/***/ }
/******/ ])
});
;

Zerion Mini Shell 1.0