(self["webpackChunkramsey_plus_forms"] = self["webpackChunkramsey_plus_forms"] || []).push([[755],{ /***/ 181: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { /** * lodash (Custom Build) * Build: `lodash modularize exports="npm" -o ./` * Copyright jQuery Foundation and other contributors * Released under MIT license * Based on Underscore.js 1.8.3 * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors */ /** Used as the `TypeError` message for "Functions" methods. */ var FUNC_ERROR_TEXT = 'Expected a function'; /** Used as references for various `Number` constants. */ var NAN = 0 / 0; /** `Object#toString` result references. */ var symbolTag = '[object Symbol]'; /** Used to match leading and trailing whitespace. */ var reTrim = /^\s+|\s+$/g; /** Used to detect bad signed hexadecimal string values. */ var reIsBadHex = /^[-+]0x[0-9a-f]+$/i; /** Used to detect binary string values. */ var reIsBinary = /^0b[01]+$/i; /** Used to detect octal string values. */ var reIsOctal = /^0o[0-7]+$/i; /** Built-in method references without a dependency on `root`. */ var freeParseInt = parseInt; /** Detect free variable `global` from Node.js. */ var freeGlobal = typeof __webpack_require__.g == 'object' && __webpack_require__.g && __webpack_require__.g.Object === Object && __webpack_require__.g; /** Detect free variable `self`. */ var freeSelf = typeof self == 'object' && self && self.Object === Object && self; /** Used as a reference to the global object. */ var root = freeGlobal || freeSelf || Function('return this')(); /** Used for built-in method references. */ var objectProto = Object.prototype; /** * Used to resolve the * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring) * of values. */ var objectToString = objectProto.toString; /* Built-in method references for those with the same name as other `lodash` methods. */ var nativeMax = Math.max, nativeMin = Math.min; /** * Gets the timestamp of the number of milliseconds that have elapsed since * the Unix epoch (1 January 1970 00:00:00 UTC). * * @static * @memberOf _ * @since 2.4.0 * @category Date * @returns {number} Returns the timestamp. * @example * * _.defer(function(stamp) { * console.log(_.now() - stamp); * }, _.now()); * // => Logs the number of milliseconds it took for the deferred invocation. */ var now = function() { return root.Date.now(); }; /** * Creates a debounced function that delays invoking `func` until after `wait` * milliseconds have elapsed since the last time the debounced function was * invoked. The debounced function comes with a `cancel` method to cancel * delayed `func` invocations and a `flush` method to immediately invoke them. * Provide `options` to indicate whether `func` should be invoked on the * leading and/or trailing edge of the `wait` timeout. The `func` is invoked * with the last arguments provided to the debounced function. Subsequent * calls to the debounced function return the result of the last `func` * invocation. * * **Note:** If `leading` and `trailing` options are `true`, `func` is * invoked on the trailing edge of the timeout only if the debounced function * is invoked more than once during the `wait` timeout. * * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred * until to the next tick, similar to `setTimeout` with a timeout of `0`. * * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/) * for details over the differences between `_.debounce` and `_.throttle`. * * @static * @memberOf _ * @since 0.1.0 * @category Function * @param {Function} func The function to debounce. * @param {number} [wait=0] The number of milliseconds to delay. * @param {Object} [options={}] The options object. * @param {boolean} [options.leading=false] * Specify invoking on the leading edge of the timeout. * @param {number} [options.maxWait] * The maximum time `func` is allowed to be delayed before it's invoked. * @param {boolean} [options.trailing=true] * Specify invoking on the trailing edge of the timeout. * @returns {Function} Returns the new debounced function. * @example * * // Avoid costly calculations while the window size is in flux. * jQuery(window).on('resize', _.debounce(calculateLayout, 150)); * * // Invoke `sendMail` when clicked, debouncing subsequent calls. * jQuery(element).on('click', _.debounce(sendMail, 300, { * 'leading': true, * 'trailing': false * })); * * // Ensure `batchLog` is invoked once after 1 second of debounced calls. * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 }); * var source = new EventSource('/stream'); * jQuery(source).on('message', debounced); * * // Cancel the trailing debounced invocation. * jQuery(window).on('popstate', debounced.cancel); */ function debounce(func, wait, options) { var lastArgs, lastThis, maxWait, result, timerId, lastCallTime, lastInvokeTime = 0, leading = false, maxing = false, trailing = true; if (typeof func != 'function') { throw new TypeError(FUNC_ERROR_TEXT); } wait = toNumber(wait) || 0; if (isObject(options)) { leading = !!options.leading; maxing = 'maxWait' in options; maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait; trailing = 'trailing' in options ? !!options.trailing : trailing; } function invokeFunc(time) { var args = lastArgs, thisArg = lastThis; lastArgs = lastThis = undefined; lastInvokeTime = time; result = func.apply(thisArg, args); return result; } function leadingEdge(time) { // Reset any `maxWait` timer. lastInvokeTime = time; // Start the timer for the trailing edge. timerId = setTimeout(timerExpired, wait); // Invoke the leading edge. return leading ? invokeFunc(time) : result; } function remainingWait(time) { var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime, result = wait - timeSinceLastCall; return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result; } function shouldInvoke(time) { var timeSinceLastCall = time - lastCallTime, timeSinceLastInvoke = time - lastInvokeTime; // Either this is the first call, activity has stopped and we're at the // trailing edge, the system time has gone backwards and we're treating // it as the trailing edge, or we've hit the `maxWait` limit. return (lastCallTime === undefined || (timeSinceLastCall >= wait) || (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait)); } function timerExpired() { var time = now(); if (shouldInvoke(time)) { return trailingEdge(time); } // Restart the timer. timerId = setTimeout(timerExpired, remainingWait(time)); } function trailingEdge(time) { timerId = undefined; // Only invoke if we have `lastArgs` which means `func` has been // debounced at least once. if (trailing && lastArgs) { return invokeFunc(time); } lastArgs = lastThis = undefined; return result; } function cancel() { if (timerId !== undefined) { clearTimeout(timerId); } lastInvokeTime = 0; lastArgs = lastCallTime = lastThis = timerId = undefined; } function flush() { return timerId === undefined ? result : trailingEdge(now()); } function debounced() { var time = now(), isInvoking = shouldInvoke(time); lastArgs = arguments; lastThis = this; lastCallTime = time; if (isInvoking) { if (timerId === undefined) { return leadingEdge(lastCallTime); } if (maxing) { // Handle invocations in a tight loop. timerId = setTimeout(timerExpired, wait); return invokeFunc(lastCallTime); } } if (timerId === undefined) { timerId = setTimeout(timerExpired, wait); } return result; } debounced.cancel = cancel; debounced.flush = flush; return debounced; } /** * Checks if `value` is the * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types) * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) * * @static * @memberOf _ * @since 0.1.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is an object, else `false`. * @example * * _.isObject({}); * // => true * * _.isObject([1, 2, 3]); * // => true * * _.isObject(_.noop); * // => true * * _.isObject(null); * // => false */ function isObject(value) { var type = typeof value; return !!value && (type == 'object' || type == 'function'); } /** * Checks if `value` is object-like. A value is object-like if it's not `null` * and has a `typeof` result of "object". * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is object-like, else `false`. * @example * * _.isObjectLike({}); * // => true * * _.isObjectLike([1, 2, 3]); * // => true * * _.isObjectLike(_.noop); * // => false * * _.isObjectLike(null); * // => false */ function isObjectLike(value) { return !!value && typeof value == 'object'; } /** * Checks if `value` is classified as a `Symbol` primitive or object. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to check. * @returns {boolean} Returns `true` if `value` is a symbol, else `false`. * @example * * _.isSymbol(Symbol.iterator); * // => true * * _.isSymbol('abc'); * // => false */ function isSymbol(value) { return typeof value == 'symbol' || (isObjectLike(value) && objectToString.call(value) == symbolTag); } /** * Converts `value` to a number. * * @static * @memberOf _ * @since 4.0.0 * @category Lang * @param {*} value The value to process. * @returns {number} Returns the number. * @example * * _.toNumber(3.2); * // => 3.2 * * _.toNumber(Number.MIN_VALUE); * // => 5e-324 * * _.toNumber(Infinity); * // => Infinity * * _.toNumber('3.2'); * // => 3.2 */ function toNumber(value) { if (typeof value == 'number') { return value; } if (isSymbol(value)) { return NAN; } if (isObject(value)) { var other = typeof value.valueOf == 'function' ? value.valueOf() : value; value = isObject(other) ? (other + '') : other; } if (typeof value != 'string') { return value === 0 ? value : +value; } value = value.replace(reTrim, ''); var isBinary = reIsBinary.test(value); return (isBinary || reIsOctal.test(value)) ? freeParseInt(value.slice(2), isBinary ? 2 : 8) : (reIsBadHex.test(value) ? NAN : +value); } module.exports = debounce; /***/ }), /***/ 961: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; function checkDCE() { /* global __REACT_DEVTOOLS_GLOBAL_HOOK__ */ if ( typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ === 'undefined' || typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE !== 'function' ) { return; } if (false) // removed by dead control flow {} try { // Verify that the code above has been dead code eliminated (DCE'd). __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(checkDCE); } catch (err) { // DevTools shouldn't crash React, no matter what. // We should still report in case we break this code. console.error(err); } } if (true) { // DCE check should happen before ReactDOM bundle executes so that // DevTools can report bad minification during injection. checkDCE(); module.exports = __webpack_require__(6221); } else // removed by dead control flow {} /***/ }), /***/ 1942: /***/ ((__unused_webpack_module, exports) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); var geocodeByAddress = exports.geocodeByAddress = function geocodeByAddress(address) { var geocoder = new window.google.maps.Geocoder(); var OK = window.google.maps.GeocoderStatus.OK; return new Promise(function (resolve, reject) { geocoder.geocode({ address: address }, function (results, status) { if (status !== OK) { reject(status); } resolve(results); }); }); }; var getLatLng = exports.getLatLng = function getLatLng(result) { return new Promise(function (resolve, reject) { try { var latLng = { lat: result.geometry.location.lat(), lng: result.geometry.location.lng() }; resolve(latLng); } catch (e) { reject(e); } }); }; var geocodeByPlaceId = exports.geocodeByPlaceId = function geocodeByPlaceId(placeId) { var geocoder = new window.google.maps.Geocoder(); var OK = window.google.maps.GeocoderStatus.OK; return new Promise(function (resolve, reject) { geocoder.geocode({ placeId: placeId }, function (results, status) { if (status !== OK) { reject(status); } resolve(results); }); }); }; /***/ }), /***/ 3931: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; var __webpack_unused_export__; __webpack_unused_export__ = ({ value: true }); __webpack_unused_export__ = __webpack_unused_export__ = exports.IU = undefined; var _PlacesAutocomplete = __webpack_require__(7147); var _PlacesAutocomplete2 = _interopRequireDefault(_PlacesAutocomplete); var _utils = __webpack_require__(1942); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } exports.IU = _utils.geocodeByAddress; __webpack_unused_export__ = _utils.geocodeByPlaceId; __webpack_unused_export__ = _utils.getLatLng; exports.Ay = _PlacesAutocomplete2.default; /***/ }), /***/ 3946: /***/ ((__unused_webpack_module, exports) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); var compose = exports.compose = function compose() { for (var _len = arguments.length, fns = Array(_len), _key = 0; _key < _len; _key++) { fns[_key] = arguments[_key]; } return function () { for (var _len2 = arguments.length, args = Array(_len2), _key2 = 0; _key2 < _len2; _key2++) { args[_key2] = arguments[_key2]; } fns.forEach(function (fn) { return fn && fn.apply(undefined, args); }); }; }; var pick = exports.pick = function pick(obj) { for (var _len3 = arguments.length, props = Array(_len3 > 1 ? _len3 - 1 : 0), _key3 = 1; _key3 < _len3; _key3++) { props[_key3 - 1] = arguments[_key3]; } return props.reduce(function (newObj, prop) { if (obj && obj.hasOwnProperty(prop)) { newObj[prop] = obj[prop]; } return newObj; }, {}); }; /***/ }), /***/ 4164: /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* unused harmony export clsx */ function r(e){var t,f,n="";if("string"==typeof e||"number"==typeof e)n+=e;else if("object"==typeof e)if(Array.isArray(e)){var o=e.length;for(t=0;t { "use strict"; if (true) { module.exports = __webpack_require__(9698); } else // removed by dead control flow {} /***/ }), /***/ 6162: /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ A: () => (/* binding */ Select) /* harmony export */ }); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6540); /* harmony import */ var classnames__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6942); /* harmony import */ var classnames__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(classnames__WEBPACK_IMPORTED_MODULE_1__); /****************************************************************************** Copyright (c) Microsoft Corporation. Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ***************************************************************************** */ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */ var __assign = function() { __assign = Object.assign || function __assign(t) { for (var s, i = 1, n = arguments.length; i < n; i++) { s = arguments[i]; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p]; } return t; }; return __assign.apply(this, arguments); }; function __rest(s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; } typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) { var e = new Error(message); return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e; }; /** * * Demos: * * - [RDS Select](https://design.ramseysolutions.com/storybook/?path=/story/design-system-select--default) * * API: * * - [RDS Select API](https://design.ramseysolutions.com/components/select/?tab=technologies#react) */ var Select = (0,react__WEBPACK_IMPORTED_MODULE_0__.forwardRef)(function (_a, ref) { var _b; var children = _a.children, className = _a.className, _c = _a.invalid, invalid = _c === void 0 ? false : _c, _d = _a.size, size = _d === void 0 ? "md" : _d, rest = __rest(_a, ["children", "className", "invalid", "size"]); var selectClassNames = classnames__WEBPACK_IMPORTED_MODULE_1___default()("rds-Select", (_b = {}, _b["rds-Select--".concat(size)] = size !== "md", _b["is-invalid"] = invalid, _b), className); var conditionalAttributes = { "aria-invalid": invalid || undefined, }; return (react__WEBPACK_IMPORTED_MODULE_0__.createElement("select", __assign({ className: selectClassNames, ref: ref }, conditionalAttributes, rest), children)); }); Select.displayName = "Select"; //# sourceMappingURL=Select.esm.js.map /***/ }), /***/ 6540: /***/ ((module, __unused_webpack_exports, __webpack_require__) => { "use strict"; if (true) { module.exports = __webpack_require__(9869); } else // removed by dead control flow {} /***/ }), /***/ 7147: /***/ ((__unused_webpack_module, exports, __webpack_require__) => { "use strict"; Object.defineProperty(exports, "__esModule", ({ value: true })); var _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; }; var _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; }; }(); var _react = __webpack_require__(6540); var _react2 = _interopRequireDefault(_react); var _propTypes = __webpack_require__(5556); var _propTypes2 = _interopRequireDefault(_propTypes); var _lodash = __webpack_require__(181); var _lodash2 = _interopRequireDefault(_lodash); var _helpers = __webpack_require__(3946); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; } function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; } /* * Copyright (c) 2016-present, Ken Hibino. * Licensed under the MIT License (MIT). * See https://kenny-hibino.github.io/react-places-autocomplete */ // transform snake_case to camelCase var formattedSuggestion = function formattedSuggestion(structured_formatting) { return { mainText: structured_formatting.main_text, secondaryText: structured_formatting.secondary_text }; }; var PlacesAutocomplete = function (_React$Component) { _inherits(PlacesAutocomplete, _React$Component); function PlacesAutocomplete(props) { _classCallCheck(this, PlacesAutocomplete); var _this = _possibleConstructorReturn(this, (PlacesAutocomplete.__proto__ || Object.getPrototypeOf(PlacesAutocomplete)).call(this, props)); _this.init = function () { if (!window.google) { throw new Error('[react-places-autocomplete]: Google Maps JavaScript API library must be loaded. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library'); } if (!window.google.maps.places) { throw new Error('[react-places-autocomplete]: Google Maps Places library must be loaded. Please add `libraries=places` to the src URL. See: https://github.com/kenny-hibino/react-places-autocomplete#load-google-library'); } _this.autocompleteService = new window.google.maps.places.AutocompleteService(); _this.autocompleteOK = window.google.maps.places.PlacesServiceStatus.OK; _this.setState(function (state) { if (state.ready) { return null; } else { return { ready: true }; } }); }; _this.autocompleteCallback = function (predictions, status) { _this.setState({ loading: false }); if (status !== _this.autocompleteOK) { _this.props.onError(status, _this.clearSuggestions); return; } var highlightFirstSuggestion = _this.props.highlightFirstSuggestion; _this.setState({ suggestions: predictions.map(function (p, idx) { return { id: p.id, description: p.description, placeId: p.place_id, active: highlightFirstSuggestion && idx === 0 ? true : false, index: idx, formattedSuggestion: formattedSuggestion(p.structured_formatting), matchedSubstrings: p.matched_substrings, terms: p.terms, types: p.types }; }) }); }; _this.fetchPredictions = function () { var value = _this.props.value; if (value.length) { _this.setState({ loading: true }); _this.autocompleteService.getPlacePredictions(_extends({}, _this.props.searchOptions, { input: value }), _this.autocompleteCallback); } }; _this.clearSuggestions = function () { _this.setState({ suggestions: [] }); }; _this.clearActive = function () { _this.setState({ suggestions: _this.state.suggestions.map(function (suggestion) { return _extends({}, suggestion, { active: false }); }) }); }; _this.handleSelect = function (address, placeId, suggestion) { _this.clearSuggestions(); if (_this.props.onSelect) { _this.props.onSelect(address, placeId, suggestion); } else { _this.props.onChange(address); } }; _this.getActiveSuggestion = function () { return _this.state.suggestions.find(function (suggestion) { return suggestion.active; }); }; _this.selectActiveAtIndex = function (index) { var activeName = _this.state.suggestions.find(function (suggestion) { return suggestion.index === index; }).description; _this.setActiveAtIndex(index); _this.props.onChange(activeName); }; _this.selectUserInputValue = function () { _this.clearActive(); _this.props.onChange(_this.state.userInputValue); }; _this.handleEnterKey = function () { var activeSuggestion = _this.getActiveSuggestion(); if (activeSuggestion === undefined) { _this.handleSelect(_this.props.value, null, null); } else { _this.handleSelect(activeSuggestion.description, activeSuggestion.placeId, activeSuggestion); } }; _this.handleDownKey = function () { if (_this.state.suggestions.length === 0) { return; } var activeSuggestion = _this.getActiveSuggestion(); if (activeSuggestion === undefined) { _this.selectActiveAtIndex(0); } else if (activeSuggestion.index === _this.state.suggestions.length - 1) { _this.selectUserInputValue(); } else { _this.selectActiveAtIndex(activeSuggestion.index + 1); } }; _this.handleUpKey = function () { if (_this.state.suggestions.length === 0) { return; } var activeSuggestion = _this.getActiveSuggestion(); if (activeSuggestion === undefined) { _this.selectActiveAtIndex(_this.state.suggestions.length - 1); } else if (activeSuggestion.index === 0) { _this.selectUserInputValue(); } else { _this.selectActiveAtIndex(activeSuggestion.index - 1); } }; _this.handleInputKeyDown = function (event) { /* eslint-disable indent */ switch (event.key) { case 'Enter': event.preventDefault(); _this.handleEnterKey(); break; case 'ArrowDown': event.preventDefault(); // prevent the cursor from moving _this.handleDownKey(); break; case 'ArrowUp': event.preventDefault(); // prevent the cursor from moving _this.handleUpKey(); break; case 'Escape': _this.clearSuggestions(); break; } /* eslint-enable indent */ }; _this.setActiveAtIndex = function (index) { _this.setState({ suggestions: _this.state.suggestions.map(function (suggestion, idx) { if (idx === index) { return _extends({}, suggestion, { active: true }); } else { return _extends({}, suggestion, { active: false }); } }) }); }; _this.handleInputChange = function (event) { var value = event.target.value; _this.props.onChange(value); _this.setState({ userInputValue: value }); if (!value) { _this.clearSuggestions(); return; } if (_this.props.shouldFetchSuggestions) { _this.debouncedFetchPredictions(); } }; _this.handleInputOnBlur = function () { if (!_this.mousedownOnSuggestion) { _this.clearSuggestions(); } }; _this.getActiveSuggestionId = function () { var activeSuggestion = _this.getActiveSuggestion(); return activeSuggestion ? 'PlacesAutocomplete__suggestion-' + activeSuggestion.placeId : undefined; }; _this.getIsExpanded = function () { return _this.state.suggestions.length > 0; }; _this.getInputProps = function () { var options = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; if (options.hasOwnProperty('value')) { throw new Error('[react-places-autocomplete]: getInputProps does not accept `value`. Use `value` prop instead'); } if (options.hasOwnProperty('onChange')) { throw new Error('[react-places-autocomplete]: getInputProps does not accept `onChange`. Use `onChange` prop instead'); } var defaultInputProps = { type: 'text', autoComplete: 'off', role: 'combobox', 'aria-autocomplete': 'list', 'aria-expanded': _this.getIsExpanded(), 'aria-activedescendant': _this.getActiveSuggestionId(), disabled: !_this.state.ready }; return _extends({}, defaultInputProps, options, { onKeyDown: (0, _helpers.compose)(_this.handleInputKeyDown, options.onKeyDown), onBlur: (0, _helpers.compose)(_this.handleInputOnBlur, options.onBlur), value: _this.props.value, onChange: function onChange(event) { _this.handleInputChange(event); } }); }; _this.getSuggestionItemProps = function (suggestion) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; var handleSuggestionMouseEnter = _this.handleSuggestionMouseEnter.bind(_this, suggestion.index); var handleSuggestionClick = _this.handleSuggestionClick.bind(_this, suggestion); return _extends({}, options, { key: suggestion.id, id: _this.getActiveSuggestionId(), role: 'option', onMouseEnter: (0, _helpers.compose)(handleSuggestionMouseEnter, options.onMouseEnter), onMouseLeave: (0, _helpers.compose)(_this.handleSuggestionMouseLeave, options.onMouseLeave), onMouseDown: (0, _helpers.compose)(_this.handleSuggestionMouseDown, options.onMouseDown), onMouseUp: (0, _helpers.compose)(_this.handleSuggestionMouseUp, options.onMouseUp), onTouchStart: (0, _helpers.compose)(_this.handleSuggestionTouchStart, options.onTouchStart), onTouchEnd: (0, _helpers.compose)(_this.handleSuggestionMouseUp, options.onTouchEnd), onClick: (0, _helpers.compose)(handleSuggestionClick, options.onClick) }); }; _this.handleSuggestionMouseEnter = function (index) { _this.setActiveAtIndex(index); }; _this.handleSuggestionMouseLeave = function () { _this.mousedownOnSuggestion = false; _this.clearActive(); }; _this.handleSuggestionMouseDown = function (event) { event.preventDefault(); _this.mousedownOnSuggestion = true; }; _this.handleSuggestionTouchStart = function () { _this.mousedownOnSuggestion = true; }; _this.handleSuggestionMouseUp = function () { _this.mousedownOnSuggestion = false; }; _this.handleSuggestionClick = function (suggestion, event) { if (event && event.preventDefault) { event.preventDefault(); } var description = suggestion.description, placeId = suggestion.placeId; _this.handleSelect(description, placeId, suggestion); setTimeout(function () { _this.mousedownOnSuggestion = false; }); }; _this.state = { loading: false, suggestions: [], userInputValue: props.value, ready: !props.googleCallbackName }; _this.debouncedFetchPredictions = (0, _lodash2.default)(_this.fetchPredictions, props.debounce); return _this; } _createClass(PlacesAutocomplete, [{ key: 'componentDidMount', value: function componentDidMount() { var googleCallbackName = this.props.googleCallbackName; if (googleCallbackName) { var isPlacesLoaded = window.google && window.google.maps && window.google.maps.places; if (!isPlacesLoaded) { window[googleCallbackName] = this.init; } else { this.init(); } } else { this.init(); } } }, { key: 'componentWillUnmount', value: function componentWillUnmount() { var googleCallbackName = this.props.googleCallbackName; if (googleCallbackName && window[googleCallbackName]) { delete window[googleCallbackName]; } } }, { key: 'render', value: function render() { return this.props.children({ getInputProps: this.getInputProps, getSuggestionItemProps: this.getSuggestionItemProps, loading: this.state.loading, suggestions: this.state.suggestions }); } }]); return PlacesAutocomplete; }(_react2.default.Component); PlacesAutocomplete.propTypes = { onChange: _propTypes2.default.func.isRequired, value: _propTypes2.default.string.isRequired, children: _propTypes2.default.func.isRequired, onError: _propTypes2.default.func, onSelect: _propTypes2.default.func, searchOptions: _propTypes2.default.shape({ bounds: _propTypes2.default.object, componentRestrictions: _propTypes2.default.object, location: _propTypes2.default.object, offset: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]), radius: _propTypes2.default.oneOfType([_propTypes2.default.number, _propTypes2.default.string]), types: _propTypes2.default.array }), debounce: _propTypes2.default.number, highlightFirstSuggestion: _propTypes2.default.bool, shouldFetchSuggestions: _propTypes2.default.bool, googleCallbackName: _propTypes2.default.string }; PlacesAutocomplete.defaultProps = { /* eslint-disable no-unused-vars, no-console */ onError: function onError(status, _clearSuggestions) { return console.error('[react-places-autocomplete]: error happened when fetching data from Google Maps API.\nPlease check the docs here (https://developers.google.com/maps/documentation/javascript/places#place_details_responses)\nStatus: ', status); }, /* eslint-enable no-unused-vars, no-console */ searchOptions: {}, debounce: 200, highlightFirstSuggestion: false, shouldFetchSuggestions: true }; exports["default"] = PlacesAutocomplete; /***/ }), /***/ 8486: /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ nW: () => (/* binding */ useScript) /* harmony export */ }); /* unused harmony exports useBoolean, useClickAnyWhere, useCopyToClipboard, useCountdown, useCounter, useDarkMode, useDebounceCallback, useDebounceValue, useDocumentTitle, useEventCallback, useEventListener, useHover, useIntersectionObserver, useInterval, useIsClient, useIsMounted, useIsomorphicLayoutEffect, useLocalStorage, useMap, useMediaQuery, useOnClickOutside, useReadLocalStorage, useResizeObserver, useScreen, useScrollLock, useSessionStorage, useStep, useTernaryDarkMode, useTimeout, useToggle, useUnmount, useWindowSize */ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6540); /* harmony import */ var lodash_debounce__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(181); // src/useBoolean/useBoolean.ts function useBoolean(defaultValue = false) { if (typeof defaultValue !== "boolean") { throw new Error("defaultValue must be `true` or `false`"); } const [value, setValue] = useState(defaultValue); const setTrue = useCallback(() => { setValue(true); }, []); const setFalse = useCallback(() => { setValue(false); }, []); const toggle = useCallback(() => { setValue((x) => !x); }, []); return { value, setValue, setTrue, setFalse, toggle }; } var useIsomorphicLayoutEffect = typeof window !== "undefined" ? react__WEBPACK_IMPORTED_MODULE_0__.useLayoutEffect : react__WEBPACK_IMPORTED_MODULE_0__.useEffect; // src/useEventListener/useEventListener.ts function useEventListener(eventName, handler, element, options) { const savedHandler = useRef(handler); useIsomorphicLayoutEffect(() => { savedHandler.current = handler; }, [handler]); useEffect(() => { const targetElement = (element == null ? void 0 : element.current) ?? window; if (!(targetElement && targetElement.addEventListener)) return; const listener = (event) => { savedHandler.current(event); }; targetElement.addEventListener(eventName, listener, options); return () => { targetElement.removeEventListener(eventName, listener, options); }; }, [eventName, element, options]); } // src/useClickAnyWhere/useClickAnyWhere.ts function useClickAnyWhere(handler) { useEventListener("click", (event) => { handler(event); }); } function useCopyToClipboard() { const [copiedText, setCopiedText] = useState(null); const copy = useCallback(async (text) => { if (!(navigator == null ? void 0 : navigator.clipboard)) { console.warn("Clipboard not supported"); return false; } try { await navigator.clipboard.writeText(text); setCopiedText(text); return true; } catch (error) { console.warn("Copy failed", error); setCopiedText(null); return false; } }, []); return [copiedText, copy]; } function useCounter(initialValue) { const [count, setCount] = useState(initialValue ?? 0); const increment = useCallback(() => { setCount((x) => x + 1); }, []); const decrement = useCallback(() => { setCount((x) => x - 1); }, []); const reset = useCallback(() => { setCount(initialValue ?? 0); }, [initialValue]); return { count, increment, decrement, reset, setCount }; } function useInterval(callback, delay) { const savedCallback = useRef(callback); useIsomorphicLayoutEffect(() => { savedCallback.current = callback; }, [callback]); useEffect(() => { if (delay === null) { return; } const id = setInterval(() => { savedCallback.current(); }, delay); return () => { clearInterval(id); }; }, [delay]); } // src/useCountdown/useCountdown.ts function useCountdown({ countStart, countStop = 0, intervalMs = 1e3, isIncrement = false }) { const { count, increment, decrement, reset: resetCounter } = useCounter(countStart); const { value: isCountdownRunning, setTrue: startCountdown, setFalse: stopCountdown } = useBoolean(false); const resetCountdown = useCallback(() => { stopCountdown(); resetCounter(); }, [stopCountdown, resetCounter]); const countdownCallback = useCallback(() => { if (count === countStop) { stopCountdown(); return; } if (isIncrement) { increment(); } else { decrement(); } }, [count, countStop, decrement, increment, isIncrement, stopCountdown]); useInterval(countdownCallback, isCountdownRunning ? intervalMs : null); return [count, { startCountdown, stopCountdown, resetCountdown }]; } function useEventCallback(fn) { const ref = useRef(() => { throw new Error("Cannot call an event handler while rendering."); }); useIsomorphicLayoutEffect(() => { ref.current = fn; }, [fn]); return useCallback((...args) => { var _a; return (_a = ref.current) == null ? void 0 : _a.call(ref, ...args); }, [ref]); } // src/useLocalStorage/useLocalStorage.ts var IS_SERVER = typeof window === "undefined"; function useLocalStorage(key, initialValue, options = {}) { const { initializeWithValue = true } = options; const serializer = useCallback( (value) => { if (options.serializer) { return options.serializer(value); } return JSON.stringify(value); }, [options] ); const deserializer = useCallback( (value) => { if (options.deserializer) { return options.deserializer(value); } if (value === "undefined") { return void 0; } const defaultValue = initialValue instanceof Function ? initialValue() : initialValue; let parsed; try { parsed = JSON.parse(value); } catch (error) { console.error("Error parsing JSON:", error); return defaultValue; } return parsed; }, [options, initialValue] ); const readValue = useCallback(() => { const initialValueToUse = initialValue instanceof Function ? initialValue() : initialValue; if (IS_SERVER) { return initialValueToUse; } try { const raw = window.localStorage.getItem(key); return raw ? deserializer(raw) : initialValueToUse; } catch (error) { console.warn(`Error reading localStorage key \u201C${key}\u201D:`, error); return initialValueToUse; } }, [initialValue, key, deserializer]); const [storedValue, setStoredValue] = useState(() => { if (initializeWithValue) { return readValue(); } return initialValue instanceof Function ? initialValue() : initialValue; }); const setValue = useEventCallback((value) => { if (IS_SERVER) { console.warn( `Tried setting localStorage key \u201C${key}\u201D even though environment is not a client` ); } try { const newValue = value instanceof Function ? value(readValue()) : value; window.localStorage.setItem(key, serializer(newValue)); setStoredValue(newValue); window.dispatchEvent(new StorageEvent("local-storage", { key })); } catch (error) { console.warn(`Error setting localStorage key \u201C${key}\u201D:`, error); } }); const removeValue = useEventCallback(() => { if (IS_SERVER) { console.warn( `Tried removing localStorage key \u201C${key}\u201D even though environment is not a client` ); } const defaultValue = initialValue instanceof Function ? initialValue() : initialValue; window.localStorage.removeItem(key); setStoredValue(defaultValue); window.dispatchEvent(new StorageEvent("local-storage", { key })); }); useEffect(() => { setStoredValue(readValue()); }, [key]); const handleStorageChange = useCallback( (event) => { if (event.key && event.key !== key) { return; } setStoredValue(readValue()); }, [key, readValue] ); useEventListener("storage", handleStorageChange); useEventListener("local-storage", handleStorageChange); return [storedValue, setValue, removeValue]; } var IS_SERVER2 = typeof window === "undefined"; function useMediaQuery(query, { defaultValue = false, initializeWithValue = true } = {}) { const getMatches = (query2) => { if (IS_SERVER2) { return defaultValue; } return window.matchMedia(query2).matches; }; const [matches, setMatches] = useState(() => { if (initializeWithValue) { return getMatches(query); } return defaultValue; }); function handleChange() { setMatches(getMatches(query)); } useIsomorphicLayoutEffect(() => { const matchMedia = window.matchMedia(query); handleChange(); if (matchMedia.addListener) { matchMedia.addListener(handleChange); } else { matchMedia.addEventListener("change", handleChange); } return () => { if (matchMedia.removeListener) { matchMedia.removeListener(handleChange); } else { matchMedia.removeEventListener("change", handleChange); } }; }, [query]); return matches; } // src/useDarkMode/useDarkMode.ts var COLOR_SCHEME_QUERY = "(prefers-color-scheme: dark)"; var LOCAL_STORAGE_KEY = "usehooks-ts-dark-mode"; function useDarkMode(options = {}) { const { defaultValue, localStorageKey = LOCAL_STORAGE_KEY, initializeWithValue = true } = options; const isDarkOS = useMediaQuery(COLOR_SCHEME_QUERY, { initializeWithValue, defaultValue }); const [isDarkMode, setDarkMode] = useLocalStorage( localStorageKey, defaultValue ?? isDarkOS ?? false, { initializeWithValue } ); useIsomorphicLayoutEffect(() => { if (isDarkOS !== isDarkMode) { setDarkMode(isDarkOS); } }, [isDarkOS]); return { isDarkMode, toggle: () => { setDarkMode((prev) => !prev); }, enable: () => { setDarkMode(true); }, disable: () => { setDarkMode(false); }, set: (value) => { setDarkMode(value); } }; } function useUnmount(func) { const funcRef = useRef(func); funcRef.current = func; useEffect( () => () => { funcRef.current(); }, [] ); } // src/useDebounceCallback/useDebounceCallback.ts function useDebounceCallback(func, delay = 500, options) { const debouncedFunc = useRef(); useUnmount(() => { if (debouncedFunc.current) { debouncedFunc.current.cancel(); } }); const debounced = useMemo(() => { const debouncedFuncInstance = debounce(func, delay, options); const wrappedFunc = (...args) => { return debouncedFuncInstance(...args); }; wrappedFunc.cancel = () => { debouncedFuncInstance.cancel(); }; wrappedFunc.isPending = () => { return !!debouncedFunc.current; }; wrappedFunc.flush = () => { return debouncedFuncInstance.flush(); }; return wrappedFunc; }, [func, delay, options]); useEffect(() => { debouncedFunc.current = debounce(func, delay, options); }, [func, delay, options]); return debounced; } function useDebounceValue(initialValue, delay, options) { const eq = (options == null ? void 0 : options.equalityFn) ?? ((left, right) => left === right); const unwrappedInitialValue = initialValue instanceof Function ? initialValue() : initialValue; const [debouncedValue, setDebouncedValue] = useState(unwrappedInitialValue); const previousValueRef = useRef(unwrappedInitialValue); const updateDebouncedValue = useDebounceCallback( setDebouncedValue, delay, options ); if (!eq(previousValueRef.current, unwrappedInitialValue)) { updateDebouncedValue(unwrappedInitialValue); previousValueRef.current = unwrappedInitialValue; } return [debouncedValue, updateDebouncedValue]; } function useDocumentTitle(title, options = {}) { const { preserveTitleOnUnmount = true } = options; const defaultTitle = useRef(null); useIsomorphicLayoutEffect(() => { defaultTitle.current = window.document.title; }, []); useIsomorphicLayoutEffect(() => { window.document.title = title; }, [title]); useUnmount(() => { if (!preserveTitleOnUnmount && defaultTitle.current) { window.document.title = defaultTitle.current; } }); } function useHover(elementRef) { const [value, setValue] = useState(false); const handleMouseEnter = () => { setValue(true); }; const handleMouseLeave = () => { setValue(false); }; useEventListener("mouseenter", handleMouseEnter, elementRef); useEventListener("mouseleave", handleMouseLeave, elementRef); return value; } function useIntersectionObserver({ threshold = 0, root = null, rootMargin = "0%", freezeOnceVisible = false, initialIsIntersecting = false, onChange } = {}) { var _a; const [ref, setRef] = useState(null); const [state, setState] = useState(() => ({ isIntersecting: initialIsIntersecting, entry: void 0 })); const callbackRef = useRef(); callbackRef.current = onChange; const frozen = ((_a = state.entry) == null ? void 0 : _a.isIntersecting) && freezeOnceVisible; useEffect(() => { if (!ref) return; if (!("IntersectionObserver" in window)) return; if (frozen) return; let unobserve; const observer = new IntersectionObserver( (entries) => { const thresholds = Array.isArray(observer.thresholds) ? observer.thresholds : [observer.thresholds]; entries.forEach((entry) => { const isIntersecting = entry.isIntersecting && thresholds.some((threshold2) => entry.intersectionRatio >= threshold2); setState({ isIntersecting, entry }); if (callbackRef.current) { callbackRef.current(isIntersecting, entry); } if (isIntersecting && freezeOnceVisible && unobserve) { unobserve(); unobserve = void 0; } }); }, { threshold, root, rootMargin } ); observer.observe(ref); return () => { observer.disconnect(); }; }, [ ref, // eslint-disable-next-line react-hooks/exhaustive-deps JSON.stringify(threshold), root, rootMargin, frozen, freezeOnceVisible ]); const prevRef = useRef(null); useEffect(() => { var _a2; if (!ref && ((_a2 = state.entry) == null ? void 0 : _a2.target) && !freezeOnceVisible && !frozen && prevRef.current !== state.entry.target) { prevRef.current = state.entry.target; setState({ isIntersecting: initialIsIntersecting, entry: void 0 }); } }, [ref, state.entry, freezeOnceVisible, frozen, initialIsIntersecting]); const result = [ setRef, !!state.isIntersecting, state.entry ]; result.ref = result[0]; result.isIntersecting = result[1]; result.entry = result[2]; return result; } function useIsClient() { const [isClient, setClient] = useState(false); useEffect(() => { setClient(true); }, []); return isClient; } function useIsMounted() { const isMounted = useRef(false); useEffect(() => { isMounted.current = true; return () => { isMounted.current = false; }; }, []); return useCallback(() => isMounted.current, []); } function useMap(initialState = /* @__PURE__ */ new Map()) { const [map, setMap] = useState(new Map(initialState)); const actions = { set: useCallback((key, value) => { setMap((prev) => { const copy = new Map(prev); copy.set(key, value); return copy; }); }, []), setAll: useCallback((entries) => { setMap(() => new Map(entries)); }, []), remove: useCallback((key) => { setMap((prev) => { const copy = new Map(prev); copy.delete(key); return copy; }); }, []), reset: useCallback(() => { setMap(() => /* @__PURE__ */ new Map()); }, []) }; return [map, actions]; } // src/useOnClickOutside/useOnClickOutside.ts function useOnClickOutside(ref, handler, eventType = "mousedown", eventListenerOptions = {}) { useEventListener( eventType, (event) => { const target = event.target; if (!target || !target.isConnected) { return; } const isOutside = Array.isArray(ref) ? ref.filter((r) => Boolean(r.current)).every((r) => r.current && !r.current.contains(target)) : ref.current && !ref.current.contains(target); if (isOutside) { handler(event); } }, void 0, eventListenerOptions ); } var IS_SERVER3 = typeof window === "undefined"; function useReadLocalStorage(key, options = {}) { let { initializeWithValue = true } = options; if (IS_SERVER3) { initializeWithValue = false; } const deserializer = useCallback( (value) => { if (options.deserializer) { return options.deserializer(value); } if (value === "undefined") { return void 0; } let parsed; try { parsed = JSON.parse(value); } catch (error) { console.error("Error parsing JSON:", error); return null; } return parsed; }, [options] ); const readValue = useCallback(() => { if (IS_SERVER3) { return null; } try { const raw = window.localStorage.getItem(key); return raw ? deserializer(raw) : null; } catch (error) { console.warn(`Error reading localStorage key \u201C${key}\u201D:`, error); return null; } }, [key, deserializer]); const [storedValue, setStoredValue] = useState(() => { if (initializeWithValue) { return readValue(); } return void 0; }); useEffect(() => { setStoredValue(readValue()); }, [key]); const handleStorageChange = useCallback( (event) => { if (event.key && event.key !== key) { return; } setStoredValue(readValue()); }, [key, readValue] ); useEventListener("storage", handleStorageChange); useEventListener("local-storage", handleStorageChange); return storedValue; } var initialSize = { width: void 0, height: void 0 }; function useResizeObserver(options) { const { ref, box = "content-box" } = options; const [{ width, height }, setSize] = useState(initialSize); const isMounted = useIsMounted(); const previousSize = useRef({ ...initialSize }); const onResize = useRef(void 0); onResize.current = options.onResize; useEffect(() => { if (!ref.current) return; if (typeof window === "undefined" || !("ResizeObserver" in window)) return; const observer = new ResizeObserver(([entry]) => { const boxProp = box === "border-box" ? "borderBoxSize" : box === "device-pixel-content-box" ? "devicePixelContentBoxSize" : "contentBoxSize"; const newWidth = extractSize(entry, boxProp, "inlineSize"); const newHeight = extractSize(entry, boxProp, "blockSize"); const hasChanged = previousSize.current.width !== newWidth || previousSize.current.height !== newHeight; if (hasChanged) { const newSize = { width: newWidth, height: newHeight }; previousSize.current.width = newWidth; previousSize.current.height = newHeight; if (onResize.current) { onResize.current(newSize); } else { if (isMounted()) { setSize(newSize); } } } }); observer.observe(ref.current, { box }); return () => { observer.disconnect(); }; }, [box, ref, isMounted]); return { width, height }; } function extractSize(entry, box, sizeType) { if (!entry[box]) { if (box === "contentBoxSize") { return entry.contentRect[sizeType === "inlineSize" ? "width" : "height"]; } return void 0; } return Array.isArray(entry[box]) ? entry[box][0][sizeType] : ( // @ts-ignore Support Firefox's non-standard behavior entry[box][sizeType] ); } var IS_SERVER4 = typeof window === "undefined"; function useScreen(options = {}) { let { initializeWithValue = true } = options; if (IS_SERVER4) { initializeWithValue = false; } const readScreen = () => { if (IS_SERVER4) { return void 0; } return window.screen; }; const [screen, setScreen] = useState(() => { if (initializeWithValue) { return readScreen(); } return void 0; }); const debouncedSetScreen = useDebounceCallback( setScreen, options.debounceDelay ); function handleSize() { const newScreen = readScreen(); const setSize = options.debounceDelay ? debouncedSetScreen : setScreen; if (newScreen) { const { width, height, availHeight, availWidth, colorDepth, orientation, pixelDepth } = newScreen; setSize({ width, height, availHeight, availWidth, colorDepth, orientation, pixelDepth }); } } useEventListener("resize", handleSize); useIsomorphicLayoutEffect(() => { handleSize(); }, []); return screen; } var cachedScriptStatuses = /* @__PURE__ */ new Map(); function getScriptNode(src) { const node = document.querySelector( `script[src="${src}"]` ); const status = node == null ? void 0 : node.getAttribute("data-status"); return { node, status }; } function useScript(src, options) { const [status, setStatus] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(() => { if (!src || (options == null ? void 0 : options.shouldPreventLoad)) { return "idle"; } if (typeof window === "undefined") { return "loading"; } return cachedScriptStatuses.get(src) ?? "loading"; }); (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { if (!src || (options == null ? void 0 : options.shouldPreventLoad)) { return; } const cachedScriptStatus = cachedScriptStatuses.get(src); if (cachedScriptStatus === "ready" || cachedScriptStatus === "error") { setStatus(cachedScriptStatus); return; } const script = getScriptNode(src); let scriptNode = script.node; if (!scriptNode) { scriptNode = document.createElement("script"); scriptNode.src = src; scriptNode.async = true; if (options == null ? void 0 : options.id) { scriptNode.id = options.id; } scriptNode.setAttribute("data-status", "loading"); document.body.appendChild(scriptNode); const setAttributeFromEvent = (event) => { const scriptStatus = event.type === "load" ? "ready" : "error"; scriptNode == null ? void 0 : scriptNode.setAttribute("data-status", scriptStatus); }; scriptNode.addEventListener("load", setAttributeFromEvent); scriptNode.addEventListener("error", setAttributeFromEvent); } else { setStatus(script.status ?? cachedScriptStatus ?? "loading"); } const setStateFromEvent = (event) => { const newStatus = event.type === "load" ? "ready" : "error"; setStatus(newStatus); cachedScriptStatuses.set(src, newStatus); }; scriptNode.addEventListener("load", setStateFromEvent); scriptNode.addEventListener("error", setStateFromEvent); return () => { if (scriptNode) { scriptNode.removeEventListener("load", setStateFromEvent); scriptNode.removeEventListener("error", setStateFromEvent); } if (scriptNode && (options == null ? void 0 : options.removeOnUnmount)) { scriptNode.remove(); cachedScriptStatuses.delete(src); } }; }, [src, options == null ? void 0 : options.shouldPreventLoad, options == null ? void 0 : options.removeOnUnmount, options == null ? void 0 : options.id]); return status; } var IS_SERVER5 = typeof window === "undefined"; function useScrollLock(options = {}) { const { autoLock = true, lockTarget, widthReflow = true } = options; const [isLocked, setIsLocked] = useState(false); const target = useRef(null); const originalStyle = useRef(null); const lock = () => { if (target.current) { const { overflow, paddingRight } = target.current.style; originalStyle.current = { overflow, paddingRight }; if (widthReflow) { const offsetWidth = target.current === document.body ? window.innerWidth : target.current.offsetWidth; const currentPaddingRight = parseInt(window.getComputedStyle(target.current).paddingRight, 10) || 0; const scrollbarWidth = offsetWidth - target.current.scrollWidth; target.current.style.paddingRight = `${scrollbarWidth + currentPaddingRight}px`; } target.current.style.overflow = "hidden"; setIsLocked(true); } }; const unlock = () => { if (target.current && originalStyle.current) { target.current.style.overflow = originalStyle.current.overflow; if (widthReflow) { target.current.style.paddingRight = originalStyle.current.paddingRight; } } setIsLocked(false); }; useIsomorphicLayoutEffect(() => { if (IS_SERVER5) return; if (lockTarget) { target.current = typeof lockTarget === "string" ? document.querySelector(lockTarget) : lockTarget; } if (!target.current) { target.current = document.body; } if (autoLock) { lock(); } return () => { unlock(); }; }, [autoLock, lockTarget, widthReflow]); return { isLocked, lock, unlock }; } var IS_SERVER6 = typeof window === "undefined"; function useSessionStorage(key, initialValue, options = {}) { const { initializeWithValue = true } = options; const serializer = useCallback( (value) => { if (options.serializer) { return options.serializer(value); } return JSON.stringify(value); }, [options] ); const deserializer = useCallback( (value) => { if (options.deserializer) { return options.deserializer(value); } if (value === "undefined") { return void 0; } const defaultValue = initialValue instanceof Function ? initialValue() : initialValue; let parsed; try { parsed = JSON.parse(value); } catch (error) { console.error("Error parsing JSON:", error); return defaultValue; } return parsed; }, [options, initialValue] ); const readValue = useCallback(() => { const initialValueToUse = initialValue instanceof Function ? initialValue() : initialValue; if (IS_SERVER6) { return initialValueToUse; } try { const raw = window.sessionStorage.getItem(key); return raw ? deserializer(raw) : initialValueToUse; } catch (error) { console.warn(`Error reading sessionStorage key \u201C${key}\u201D:`, error); return initialValueToUse; } }, [initialValue, key, deserializer]); const [storedValue, setStoredValue] = useState(() => { if (initializeWithValue) { return readValue(); } return initialValue instanceof Function ? initialValue() : initialValue; }); const setValue = useEventCallback((value) => { if (IS_SERVER6) { console.warn( `Tried setting sessionStorage key \u201C${key}\u201D even though environment is not a client` ); } try { const newValue = value instanceof Function ? value(readValue()) : value; window.sessionStorage.setItem(key, serializer(newValue)); setStoredValue(newValue); window.dispatchEvent(new StorageEvent("session-storage", { key })); } catch (error) { console.warn(`Error setting sessionStorage key \u201C${key}\u201D:`, error); } }); const removeValue = useEventCallback(() => { if (IS_SERVER6) { console.warn( `Tried removing sessionStorage key \u201C${key}\u201D even though environment is not a client` ); } const defaultValue = initialValue instanceof Function ? initialValue() : initialValue; window.sessionStorage.removeItem(key); setStoredValue(defaultValue); window.dispatchEvent(new StorageEvent("session-storage", { key })); }); useEffect(() => { setStoredValue(readValue()); }, [key]); const handleStorageChange = useCallback( (event) => { if (event.key && event.key !== key) { return; } setStoredValue(readValue()); }, [key, readValue] ); useEventListener("storage", handleStorageChange); useEventListener("session-storage", handleStorageChange); return [storedValue, setValue, removeValue]; } function useStep(maxStep) { const [currentStep, setCurrentStep] = useState(1); const canGoToNextStep = currentStep + 1 <= maxStep; const canGoToPrevStep = currentStep - 1 > 0; const setStep = useCallback( (step) => { const newStep = step instanceof Function ? step(currentStep) : step; if (newStep >= 1 && newStep <= maxStep) { setCurrentStep(newStep); return; } throw new Error("Step not valid"); }, [maxStep, currentStep] ); const goToNextStep = useCallback(() => { if (canGoToNextStep) { setCurrentStep((step) => step + 1); } }, [canGoToNextStep]); const goToPrevStep = useCallback(() => { if (canGoToPrevStep) { setCurrentStep((step) => step - 1); } }, [canGoToPrevStep]); const reset = useCallback(() => { setCurrentStep(1); }, []); return [ currentStep, { goToNextStep, goToPrevStep, canGoToNextStep, canGoToPrevStep, setStep, reset } ]; } // src/useTernaryDarkMode/useTernaryDarkMode.ts var COLOR_SCHEME_QUERY2 = "(prefers-color-scheme: dark)"; var LOCAL_STORAGE_KEY2 = "usehooks-ts-ternary-dark-mode"; function useTernaryDarkMode({ defaultValue = "system", localStorageKey = LOCAL_STORAGE_KEY2, initializeWithValue = true } = {}) { const isDarkOS = useMediaQuery(COLOR_SCHEME_QUERY2, { initializeWithValue }); const [mode, setMode] = useLocalStorage(localStorageKey, defaultValue, { initializeWithValue }); const isDarkMode = mode === "dark" || mode === "system" && isDarkOS; const toggleTernaryDarkMode = () => { const modes = ["light", "system", "dark"]; setMode((prevMode) => { const nextIndex = (modes.indexOf(prevMode) + 1) % modes.length; return modes[nextIndex]; }); }; return { isDarkMode, ternaryDarkMode: mode, setTernaryDarkMode: setMode, toggleTernaryDarkMode }; } function useTimeout(callback, delay) { const savedCallback = useRef(callback); useIsomorphicLayoutEffect(() => { savedCallback.current = callback; }, [callback]); useEffect(() => { if (!delay && delay !== 0) { return; } const id = setTimeout(() => { savedCallback.current(); }, delay); return () => { clearTimeout(id); }; }, [delay]); } function useToggle(defaultValue) { const [value, setValue] = useState(!!defaultValue); const toggle = useCallback(() => { setValue((x) => !x); }, []); return [value, toggle, setValue]; } var IS_SERVER7 = typeof window === "undefined"; function useWindowSize(options = {}) { let { initializeWithValue = true } = options; if (IS_SERVER7) { initializeWithValue = false; } const [windowSize, setWindowSize] = useState(() => { if (initializeWithValue) { return { width: window.innerWidth, height: window.innerHeight }; } return { width: void 0, height: void 0 }; }); const debouncedSetWindowSize = useDebounceCallback( setWindowSize, options.debounceDelay ); function handleSize() { const setSize = options.debounceDelay ? debouncedSetWindowSize : setWindowSize; setSize({ width: window.innerWidth, height: window.innerHeight }); } useEventListener("resize", handleSize); useIsomorphicLayoutEffect(() => { handleSize(); }, []); return windowSize; } /***/ }), /***/ 9698: /***/ ((__unused_webpack_module, exports) => { "use strict"; /** * @license React * react-jsx-runtime.production.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ var REACT_ELEMENT_TYPE = Symbol.for("react.transitional.element"), REACT_FRAGMENT_TYPE = Symbol.for("react.fragment"); function jsxProd(type, config, maybeKey) { var key = null; void 0 !== maybeKey && (key = "" + maybeKey); void 0 !== config.key && (key = "" + config.key); if ("key" in config) { maybeKey = {}; for (var propName in config) "key" !== propName && (maybeKey[propName] = config[propName]); } else maybeKey = config; config = maybeKey.ref; return { $$typeof: REACT_ELEMENT_TYPE, type: type, key: key, ref: void 0 !== config ? config : null, props: maybeKey }; } exports.Fragment = REACT_FRAGMENT_TYPE; exports.jsx = jsxProd; exports.jsxs = jsxProd; /***/ }), /***/ 9785: /***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => { "use strict"; /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ mN: () => (/* binding */ useForm), /* harmony export */ xI: () => (/* binding */ Controller) /* harmony export */ }); /* unused harmony exports Form, FormProvider, Watch, appendErrors, createFormControl, get, set, useController, useFieldArray, useFormContext, useFormState, useWatch */ /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(6540); var isCheckBoxInput = (element) => element.type === 'checkbox'; var isDateObject = (value) => value instanceof Date; var isNullOrUndefined = (value) => value == null; const isObjectType = (value) => typeof value === 'object'; var isObject = (value) => !isNullOrUndefined(value) && !Array.isArray(value) && isObjectType(value) && !isDateObject(value); var getEventValue = (event) => isObject(event) && event.target ? isCheckBoxInput(event.target) ? event.target.checked : event.target.value : event; var getNodeParentName = (name) => name.substring(0, name.search(/\.\d+(\.|$)/)) || name; var isNameInFieldArray = (names, name) => names.has(getNodeParentName(name)); var isPlainObject = (tempObject) => { const prototypeCopy = tempObject.constructor && tempObject.constructor.prototype; return (isObject(prototypeCopy) && prototypeCopy.hasOwnProperty('isPrototypeOf')); }; var isWeb = typeof window !== 'undefined' && typeof window.HTMLElement !== 'undefined' && typeof document !== 'undefined'; function cloneObject(data) { let copy; const isArray = Array.isArray(data); const isFileListInstance = typeof FileList !== 'undefined' ? data instanceof FileList : false; if (data instanceof Date) { copy = new Date(data); } else if (!(isWeb && (data instanceof Blob || isFileListInstance)) && (isArray || isObject(data))) { copy = isArray ? [] : Object.create(Object.getPrototypeOf(data)); if (!isArray && !isPlainObject(data)) { copy = data; } else { for (const key in data) { if (data.hasOwnProperty(key)) { copy[key] = cloneObject(data[key]); } } } } else { return data; } return copy; } var isKey = (value) => /^\w*$/.test(value); var isUndefined = (val) => val === undefined; var compact = (value) => Array.isArray(value) ? value.filter(Boolean) : []; var stringToPath = (input) => compact(input.replace(/["|']|\]/g, '').split(/\.|\[/)); var get = (object, path, defaultValue) => { if (!path || !isObject(object)) { return defaultValue; } const result = (isKey(path) ? [path] : stringToPath(path)).reduce((result, key) => isNullOrUndefined(result) ? result : result[key], object); return isUndefined(result) || result === object ? isUndefined(object[path]) ? defaultValue : object[path] : result; }; var isBoolean = (value) => typeof value === 'boolean'; var set = (object, path, value) => { let index = -1; const tempPath = isKey(path) ? [path] : stringToPath(path); const length = tempPath.length; const lastIndex = length - 1; while (++index < length) { const key = tempPath[index]; let newValue = value; if (index !== lastIndex) { const objValue = object[key]; newValue = isObject(objValue) || Array.isArray(objValue) ? objValue : !isNaN(+tempPath[index + 1]) ? [] : {}; } if (key === '__proto__' || key === 'constructor' || key === 'prototype') { return; } object[key] = newValue; object = object[key]; } }; const EVENTS = { BLUR: 'blur', FOCUS_OUT: 'focusout', CHANGE: 'change', }; const VALIDATION_MODE = { onBlur: 'onBlur', onChange: 'onChange', onSubmit: 'onSubmit', onTouched: 'onTouched', all: 'all', }; const INPUT_VALIDATION_RULES = { max: 'max', min: 'min', maxLength: 'maxLength', minLength: 'minLength', pattern: 'pattern', required: 'required', validate: 'validate', }; const HookFormContext = react__WEBPACK_IMPORTED_MODULE_0__.createContext(null); HookFormContext.displayName = 'HookFormContext'; /** * This custom hook allows you to access the form context. useFormContext is intended to be used in deeply nested structures, where it would become inconvenient to pass the context as a prop. To be used with {@link FormProvider}. * * @remarks * [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi) * * @returns return all useForm methods * * @example * ```tsx * function App() { * const methods = useForm(); * const onSubmit = data => console.log(data); * * return ( * *
* * * *
* ); * } * * function NestedInput() { * const { register } = useFormContext(); // retrieve all hook methods * return ; * } * ``` */ const useFormContext = () => react__WEBPACK_IMPORTED_MODULE_0__.useContext(HookFormContext); /** * A provider component that propagates the `useForm` methods to all children components via [React Context](https://react.dev/reference/react/useContext) API. To be used with {@link useFormContext}. * * @remarks * [API](https://react-hook-form.com/docs/useformcontext) • [Demo](https://codesandbox.io/s/react-hook-form-v7-form-context-ytudi) * * @param props - all useForm methods * * @example * ```tsx * function App() { * const methods = useForm(); * const onSubmit = data => console.log(data); * * return ( * *
* * * *
* ); * } * * function NestedInput() { * const { register } = useFormContext(); // retrieve all hook methods * return ; * } * ``` */ const FormProvider = (props) => { const { children, ...data } = props; return (React.createElement(HookFormContext.Provider, { value: data }, children)); }; var getProxyFormState = (formState, control, localProxyFormState, isRoot = true) => { const result = { defaultValues: control._defaultValues, }; for (const key in formState) { Object.defineProperty(result, key, { get: () => { const _key = key; if (control._proxyFormState[_key] !== VALIDATION_MODE.all) { control._proxyFormState[_key] = !isRoot || VALIDATION_MODE.all; } localProxyFormState && (localProxyFormState[_key] = true); return formState[_key]; }, }); } return result; }; const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? react__WEBPACK_IMPORTED_MODULE_0__.useLayoutEffect : react__WEBPACK_IMPORTED_MODULE_0__.useEffect; /** * This custom hook allows you to subscribe to each form state, and isolate the re-render at the custom hook level. It has its scope in terms of form state subscription, so it would not affect other useFormState and useForm. Using this hook can reduce the re-render impact on large and complex form application. * * @remarks * [API](https://react-hook-form.com/docs/useformstate) • [Demo](https://codesandbox.io/s/useformstate-75xly) * * @param props - include options on specify fields to subscribe. {@link UseFormStateReturn} * * @example * ```tsx * function App() { * const { register, handleSubmit, control } = useForm({ * defaultValues: { * firstName: "firstName" * }}); * const { dirtyFields } = useFormState({ * control * }); * const onSubmit = (data) => console.log(data); * * return ( *
* * {dirtyFields.firstName &&

Field is dirty.

} * *
* ); * } * ``` */ function useFormState(props) { const methods = useFormContext(); const { control = methods.control, disabled, name, exact } = props || {}; const [formState, updateFormState] = react__WEBPACK_IMPORTED_MODULE_0__.useState(control._formState); const _localProxyFormState = react__WEBPACK_IMPORTED_MODULE_0__.useRef({ isDirty: false, isLoading: false, dirtyFields: false, touchedFields: false, validatingFields: false, isValidating: false, isValid: false, errors: false, }); useIsomorphicLayoutEffect(() => control._subscribe({ name, formState: _localProxyFormState.current, exact, callback: (formState) => { !disabled && updateFormState({ ...control._formState, ...formState, }); }, }), [name, disabled, exact]); react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => { _localProxyFormState.current.isValid && control._setValid(true); }, [control]); return react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => getProxyFormState(formState, control, _localProxyFormState.current, false), [formState, control]); } var isString = (value) => typeof value === 'string'; var generateWatchOutput = (names, _names, formValues, isGlobal, defaultValue) => { if (isString(names)) { isGlobal && _names.watch.add(names); return get(formValues, names, defaultValue); } if (Array.isArray(names)) { return names.map((fieldName) => (isGlobal && _names.watch.add(fieldName), get(formValues, fieldName))); } isGlobal && (_names.watchAll = true); return formValues; }; var isPrimitive = (value) => isNullOrUndefined(value) || !isObjectType(value); function deepEqual(object1, object2, _internal_visited = new WeakSet()) { if (isPrimitive(object1) || isPrimitive(object2)) { return Object.is(object1, object2); } if (isDateObject(object1) && isDateObject(object2)) { return object1.getTime() === object2.getTime(); } const keys1 = Object.keys(object1); const keys2 = Object.keys(object2); if (keys1.length !== keys2.length) { return false; } if (_internal_visited.has(object1) || _internal_visited.has(object2)) { return true; } _internal_visited.add(object1); _internal_visited.add(object2); for (const key of keys1) { const val1 = object1[key]; if (!keys2.includes(key)) { return false; } if (key !== 'ref') { const val2 = object2[key]; if ((isDateObject(val1) && isDateObject(val2)) || (isObject(val1) && isObject(val2)) || (Array.isArray(val1) && Array.isArray(val2)) ? !deepEqual(val1, val2, _internal_visited) : !Object.is(val1, val2)) { return false; } } } return true; } /** * Custom hook to subscribe to field change and isolate re-rendering at the component level. * * @remarks * * [API](https://react-hook-form.com/docs/usewatch) • [Demo](https://codesandbox.io/s/react-hook-form-v7-ts-usewatch-h9i5e) * * @example * ```tsx * const { control } = useForm(); * const values = useWatch({ * name: "fieldName" * control, * }) * ``` */ function useWatch(props) { const methods = useFormContext(); const { control = methods.control, name, defaultValue, disabled, exact, compute, } = props || {}; const _defaultValue = react__WEBPACK_IMPORTED_MODULE_0__.useRef(defaultValue); const _compute = react__WEBPACK_IMPORTED_MODULE_0__.useRef(compute); const _computeFormValues = react__WEBPACK_IMPORTED_MODULE_0__.useRef(undefined); const _prevControl = react__WEBPACK_IMPORTED_MODULE_0__.useRef(control); const _prevName = react__WEBPACK_IMPORTED_MODULE_0__.useRef(name); _compute.current = compute; const [value, updateValue] = react__WEBPACK_IMPORTED_MODULE_0__.useState(() => { const defaultValue = control._getWatch(name, _defaultValue.current); return _compute.current ? _compute.current(defaultValue) : defaultValue; }); const getCurrentOutput = react__WEBPACK_IMPORTED_MODULE_0__.useCallback((values) => { const formValues = generateWatchOutput(name, control._names, values || control._formValues, false, _defaultValue.current); return _compute.current ? _compute.current(formValues) : formValues; }, [control._formValues, control._names, name]); const refreshValue = react__WEBPACK_IMPORTED_MODULE_0__.useCallback((values) => { if (!disabled) { const formValues = generateWatchOutput(name, control._names, values || control._formValues, false, _defaultValue.current); if (_compute.current) { const computedFormValues = _compute.current(formValues); if (!deepEqual(computedFormValues, _computeFormValues.current)) { updateValue(computedFormValues); _computeFormValues.current = computedFormValues; } } else { updateValue(formValues); } } }, [control._formValues, control._names, disabled, name]); useIsomorphicLayoutEffect(() => { if (_prevControl.current !== control || !deepEqual(_prevName.current, name)) { _prevControl.current = control; _prevName.current = name; refreshValue(); } return control._subscribe({ name, formState: { values: true, }, exact, callback: (formState) => { refreshValue(formState.values); }, }); }, [control, exact, name, refreshValue]); react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => control._removeUnmounted()); // If name or control changed for this render, synchronously reflect the // latest value so callers (like useController) see the correct value // immediately on the same render. // Optimize: Check control reference first before expensive deepEqual const controlChanged = _prevControl.current !== control; const prevName = _prevName.current; // Cache the computed output to avoid duplicate calls within the same render // We include shouldReturnImmediate in deps to ensure proper recomputation const computedOutput = react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => { if (disabled) { return null; } const nameChanged = !controlChanged && !deepEqual(prevName, name); const shouldReturnImmediate = controlChanged || nameChanged; return shouldReturnImmediate ? getCurrentOutput() : null; }, [disabled, controlChanged, name, prevName, getCurrentOutput]); return computedOutput !== null ? computedOutput : value; } /** * Custom hook to work with controlled component, this function provide you with both form and field level state. Re-render is isolated at the hook level. * * @remarks * [API](https://react-hook-form.com/docs/usecontroller) • [Demo](https://codesandbox.io/s/usecontroller-0o8px) * * @param props - the path name to the form field value, and validation rules. * * @returns field properties, field and form state. {@link UseControllerReturn} * * @example * ```tsx * function Input(props) { * const { field, fieldState, formState } = useController(props); * return ( *
* *

{fieldState.isTouched && "Touched"}

*

{formState.isSubmitted ? "submitted" : ""}

*
* ); * } * ``` */ function useController(props) { const methods = useFormContext(); const { name, disabled, control = methods.control, shouldUnregister, defaultValue, } = props; const isArrayField = isNameInFieldArray(control._names.array, name); const defaultValueMemo = react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => get(control._formValues, name, get(control._defaultValues, name, defaultValue)), [control, name, defaultValue]); const value = useWatch({ control, name, defaultValue: defaultValueMemo, exact: true, }); const formState = useFormState({ control, name, exact: true, }); const _props = react__WEBPACK_IMPORTED_MODULE_0__.useRef(props); const _previousNameRef = react__WEBPACK_IMPORTED_MODULE_0__.useRef(undefined); const _registerProps = react__WEBPACK_IMPORTED_MODULE_0__.useRef(control.register(name, { ...props.rules, value, ...(isBoolean(props.disabled) ? { disabled: props.disabled } : {}), })); _props.current = props; const fieldState = react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => Object.defineProperties({}, { invalid: { enumerable: true, get: () => !!get(formState.errors, name), }, isDirty: { enumerable: true, get: () => !!get(formState.dirtyFields, name), }, isTouched: { enumerable: true, get: () => !!get(formState.touchedFields, name), }, isValidating: { enumerable: true, get: () => !!get(formState.validatingFields, name), }, error: { enumerable: true, get: () => get(formState.errors, name), }, }), [formState, name]); const onChange = react__WEBPACK_IMPORTED_MODULE_0__.useCallback((event) => _registerProps.current.onChange({ target: { value: getEventValue(event), name: name, }, type: EVENTS.CHANGE, }), [name]); const onBlur = react__WEBPACK_IMPORTED_MODULE_0__.useCallback(() => _registerProps.current.onBlur({ target: { value: get(control._formValues, name), name: name, }, type: EVENTS.BLUR, }), [name, control._formValues]); const ref = react__WEBPACK_IMPORTED_MODULE_0__.useCallback((elm) => { const field = get(control._fields, name); if (field && elm) { field._f.ref = { focus: () => elm.focus && elm.focus(), select: () => elm.select && elm.select(), setCustomValidity: (message) => elm.setCustomValidity(message), reportValidity: () => elm.reportValidity(), }; } }, [control._fields, name]); const field = react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => ({ name, value, ...(isBoolean(disabled) || formState.disabled ? { disabled: formState.disabled || disabled } : {}), onChange, onBlur, ref, }), [name, disabled, formState.disabled, onChange, onBlur, ref, value]); react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => { const _shouldUnregisterField = control._options.shouldUnregister || shouldUnregister; const previousName = _previousNameRef.current; if (previousName && previousName !== name && !isArrayField) { control.unregister(previousName); } control.register(name, { ..._props.current.rules, ...(isBoolean(_props.current.disabled) ? { disabled: _props.current.disabled } : {}), }); const updateMounted = (name, value) => { const field = get(control._fields, name); if (field && field._f) { field._f.mount = value; } }; updateMounted(name, true); if (_shouldUnregisterField) { const value = cloneObject(get(control._options.defaultValues, name, _props.current.defaultValue)); set(control._defaultValues, name, value); if (isUndefined(get(control._formValues, name))) { set(control._formValues, name, value); } } !isArrayField && control.register(name); _previousNameRef.current = name; return () => { (isArrayField ? _shouldUnregisterField && !control._state.action : _shouldUnregisterField) ? control.unregister(name) : updateMounted(name, false); }; }, [name, control, isArrayField, shouldUnregister]); react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => { control._setDisabledField({ disabled, name, }); }, [disabled, name, control]); return react__WEBPACK_IMPORTED_MODULE_0__.useMemo(() => ({ field, formState, fieldState, }), [field, formState, fieldState]); } /** * Component based on `useController` hook to work with controlled component. * * @remarks * [API](https://react-hook-form.com/docs/usecontroller/controller) • [Demo](https://codesandbox.io/s/react-hook-form-v6-controller-ts-jwyzw) • [Video](https://www.youtube.com/watch?v=N2UNk_UCVyA) * * @param props - the path name to the form field value, and validation rules. * * @returns provide field handler functions, field and form state. * * @example * ```tsx * function App() { * const { control } = useForm({ * defaultValues: { * test: "" * } * }); * * return ( *
* ( * <> * *

{formState.isSubmitted ? "submitted" : ""}

*

{fieldState.isTouched ? "touched" : ""}

* * )} * /> * * ); * } * ``` */ const Controller = (props) => props.render(useController(props)); const flatten = (obj) => { const output = {}; for (const key of Object.keys(obj)) { if (isObjectType(obj[key]) && obj[key] !== null) { const nested = flatten(obj[key]); for (const nestedKey of Object.keys(nested)) { output[`${key}.${nestedKey}`] = nested[nestedKey]; } } else { output[key] = obj[key]; } } return output; }; const POST_REQUEST = 'post'; /** * Form component to manage submission. * * @param props - to setup submission detail. {@link FormProps} * * @returns form component or headless render prop. * * @example * ```tsx * function App() { * const { control, formState: { errors } } = useForm(); * * return ( *
* *

{errors?.root?.server && 'Server error'}

* *
* ); * } * ``` */ function Form(props) { const methods = useFormContext(); const [mounted, setMounted] = React.useState(false); const { control = methods.control, onSubmit, children, action, method = POST_REQUEST, headers, encType, onError, render, onSuccess, validateStatus, ...rest } = props; const submit = async (event) => { let hasError = false; let type = ''; await control.handleSubmit(async (data) => { const formData = new FormData(); let formDataJson = ''; try { formDataJson = JSON.stringify(data); } catch (_a) { } const flattenFormValues = flatten(control._formValues); for (const key in flattenFormValues) { formData.append(key, flattenFormValues[key]); } if (onSubmit) { await onSubmit({ data, event, method, formData, formDataJson, }); } if (action) { try { const shouldStringifySubmissionData = [ headers && headers['Content-Type'], encType, ].some((value) => value && value.includes('json')); const response = await fetch(String(action), { method, headers: { ...headers, ...(encType && encType !== 'multipart/form-data' ? { 'Content-Type': encType } : {}), }, body: shouldStringifySubmissionData ? formDataJson : formData, }); if (response && (validateStatus ? !validateStatus(response.status) : response.status < 200 || response.status >= 300)) { hasError = true; onError && onError({ response }); type = String(response.status); } else { onSuccess && onSuccess({ response }); } } catch (error) { hasError = true; onError && onError({ error }); } } })(event); if (hasError && props.control) { props.control._subjects.state.next({ isSubmitSuccessful: false, }); props.control.setError('root.server', { type, }); } }; React.useEffect(() => { setMounted(true); }, []); return render ? (React.createElement(React.Fragment, null, render({ submit, }))) : (React.createElement("form", { noValidate: mounted, action: action, method: method, encType: encType, onSubmit: submit, ...rest }, children)); } var appendErrors = (name, validateAllFieldCriteria, errors, type, message) => validateAllFieldCriteria ? { ...errors[name], types: { ...(errors[name] && errors[name].types ? errors[name].types : {}), [type]: message || true, }, } : {}; var convertToArrayPayload = (value) => (Array.isArray(value) ? value : [value]); var createSubject = () => { let _observers = []; const next = (value) => { for (const observer of _observers) { observer.next && observer.next(value); } }; const subscribe = (observer) => { _observers.push(observer); return { unsubscribe: () => { _observers = _observers.filter((o) => o !== observer); }, }; }; const unsubscribe = () => { _observers = []; }; return { get observers() { return _observers; }, next, subscribe, unsubscribe, }; }; function extractFormValues(fieldsState, formValues) { const values = {}; for (const key in fieldsState) { if (fieldsState.hasOwnProperty(key)) { const fieldState = fieldsState[key]; const fieldValue = formValues[key]; if (fieldState && isObject(fieldState) && fieldValue) { const nestedFieldsState = extractFormValues(fieldState, fieldValue); if (isObject(nestedFieldsState)) { values[key] = nestedFieldsState; } } else if (fieldsState[key]) { values[key] = fieldValue; } } } return values; } var isEmptyObject = (value) => isObject(value) && !Object.keys(value).length; var isFileInput = (element) => element.type === 'file'; var isFunction = (value) => typeof value === 'function'; var isHTMLElement = (value) => { if (!isWeb) { return false; } const owner = value ? value.ownerDocument : 0; return (value instanceof (owner && owner.defaultView ? owner.defaultView.HTMLElement : HTMLElement)); }; var isMultipleSelect = (element) => element.type === `select-multiple`; var isRadioInput = (element) => element.type === 'radio'; var isRadioOrCheckbox = (ref) => isRadioInput(ref) || isCheckBoxInput(ref); var live = (ref) => isHTMLElement(ref) && ref.isConnected; function baseGet(object, updatePath) { const length = updatePath.slice(0, -1).length; let index = 0; while (index < length) { object = isUndefined(object) ? index++ : object[updatePath[index++]]; } return object; } function isEmptyArray(obj) { for (const key in obj) { if (obj.hasOwnProperty(key) && !isUndefined(obj[key])) { return false; } } return true; } function unset(object, path) { const paths = Array.isArray(path) ? path : isKey(path) ? [path] : stringToPath(path); const childObject = paths.length === 1 ? object : baseGet(object, paths); const index = paths.length - 1; const key = paths[index]; if (childObject) { delete childObject[key]; } if (index !== 0 && ((isObject(childObject) && isEmptyObject(childObject)) || (Array.isArray(childObject) && isEmptyArray(childObject)))) { unset(object, paths.slice(0, -1)); } return object; } var objectHasFunction = (data) => { for (const key in data) { if (isFunction(data[key])) { return true; } } return false; }; function isTraversable(value) { return Array.isArray(value) || (isObject(value) && !objectHasFunction(value)); } function markFieldsDirty(data, fields = {}) { for (const key in data) { const value = data[key]; if (isTraversable(value)) { fields[key] = Array.isArray(value) ? [] : {}; markFieldsDirty(value, fields[key]); } else if (!isUndefined(value)) { fields[key] = true; } } return fields; } function getDirtyFields(data, formValues, dirtyFieldsFromValues) { if (!dirtyFieldsFromValues) { dirtyFieldsFromValues = markFieldsDirty(formValues); } for (const key in data) { const value = data[key]; if (isTraversable(value)) { if (isUndefined(formValues) || isPrimitive(dirtyFieldsFromValues[key])) { dirtyFieldsFromValues[key] = markFieldsDirty(value, Array.isArray(value) ? [] : {}); } else { getDirtyFields(value, isNullOrUndefined(formValues) ? {} : formValues[key], dirtyFieldsFromValues[key]); } } else { const formValue = formValues[key]; dirtyFieldsFromValues[key] = !deepEqual(value, formValue); } } return dirtyFieldsFromValues; } const defaultResult = { value: false, isValid: false, }; const validResult = { value: true, isValid: true }; var getCheckboxValue = (options) => { if (Array.isArray(options)) { if (options.length > 1) { const values = options .filter((option) => option && option.checked && !option.disabled) .map((option) => option.value); return { value: values, isValid: !!values.length }; } return options[0].checked && !options[0].disabled ? // @ts-expect-error expected to work in the browser options[0].attributes && !isUndefined(options[0].attributes.value) ? isUndefined(options[0].value) || options[0].value === '' ? validResult : { value: options[0].value, isValid: true } : validResult : defaultResult; } return defaultResult; }; var getFieldValueAs = (value, { valueAsNumber, valueAsDate, setValueAs }) => isUndefined(value) ? value : valueAsNumber ? value === '' ? NaN : value ? +value : value : valueAsDate && isString(value) ? new Date(value) : setValueAs ? setValueAs(value) : value; const defaultReturn = { isValid: false, value: null, }; var getRadioValue = (options) => Array.isArray(options) ? options.reduce((previous, option) => option && option.checked && !option.disabled ? { isValid: true, value: option.value, } : previous, defaultReturn) : defaultReturn; function getFieldValue(_f) { const ref = _f.ref; if (isFileInput(ref)) { return ref.files; } if (isRadioInput(ref)) { return getRadioValue(_f.refs).value; } if (isMultipleSelect(ref)) { return [...ref.selectedOptions].map(({ value }) => value); } if (isCheckBoxInput(ref)) { return getCheckboxValue(_f.refs).value; } return getFieldValueAs(isUndefined(ref.value) ? _f.ref.value : ref.value, _f); } var getResolverOptions = (fieldsNames, _fields, criteriaMode, shouldUseNativeValidation) => { const fields = {}; for (const name of fieldsNames) { const field = get(_fields, name); field && set(fields, name, field._f); } return { criteriaMode, names: [...fieldsNames], fields, shouldUseNativeValidation, }; }; var isRegex = (value) => value instanceof RegExp; var getRuleValue = (rule) => isUndefined(rule) ? rule : isRegex(rule) ? rule.source : isObject(rule) ? isRegex(rule.value) ? rule.value.source : rule.value : rule; var getValidationModes = (mode) => ({ isOnSubmit: !mode || mode === VALIDATION_MODE.onSubmit, isOnBlur: mode === VALIDATION_MODE.onBlur, isOnChange: mode === VALIDATION_MODE.onChange, isOnAll: mode === VALIDATION_MODE.all, isOnTouch: mode === VALIDATION_MODE.onTouched, }); const ASYNC_FUNCTION = 'AsyncFunction'; var hasPromiseValidation = (fieldReference) => !!fieldReference && !!fieldReference.validate && !!((isFunction(fieldReference.validate) && fieldReference.validate.constructor.name === ASYNC_FUNCTION) || (isObject(fieldReference.validate) && Object.values(fieldReference.validate).find((validateFunction) => validateFunction.constructor.name === ASYNC_FUNCTION))); var hasValidation = (options) => options.mount && (options.required || options.min || options.max || options.maxLength || options.minLength || options.pattern || options.validate); var isWatched = (name, _names, isBlurEvent) => !isBlurEvent && (_names.watchAll || _names.watch.has(name) || [..._names.watch].some((watchName) => name.startsWith(watchName) && /^\.\w+/.test(name.slice(watchName.length)))); const iterateFieldsByAction = (fields, action, fieldsNames, abortEarly) => { for (const key of fieldsNames || Object.keys(fields)) { const field = get(fields, key); if (field) { const { _f, ...currentField } = field; if (_f) { if (_f.refs && _f.refs[0] && action(_f.refs[0], key) && !abortEarly) { return true; } else if (_f.ref && action(_f.ref, _f.name) && !abortEarly) { return true; } else { if (iterateFieldsByAction(currentField, action)) { break; } } } else if (isObject(currentField)) { if (iterateFieldsByAction(currentField, action)) { break; } } } } return; }; function schemaErrorLookup(errors, _fields, name) { const error = get(errors, name); if (error || isKey(name)) { return { error, name, }; } const names = name.split('.'); while (names.length) { const fieldName = names.join('.'); const field = get(_fields, fieldName); const foundError = get(errors, fieldName); if (field && !Array.isArray(field) && name !== fieldName) { return { name }; } if (foundError && foundError.type) { return { name: fieldName, error: foundError, }; } if (foundError && foundError.root && foundError.root.type) { return { name: `${fieldName}.root`, error: foundError.root, }; } names.pop(); } return { name, }; } var shouldRenderFormState = (formStateData, _proxyFormState, updateFormState, isRoot) => { updateFormState(formStateData); const { name, ...formState } = formStateData; return (isEmptyObject(formState) || Object.keys(formState).length >= Object.keys(_proxyFormState).length || Object.keys(formState).find((key) => _proxyFormState[key] === (!isRoot || VALIDATION_MODE.all))); }; var shouldSubscribeByName = (name, signalName, exact) => !name || !signalName || name === signalName || convertToArrayPayload(name).some((currentName) => currentName && (exact ? currentName === signalName : currentName.startsWith(signalName) || signalName.startsWith(currentName))); var skipValidation = (isBlurEvent, isTouched, isSubmitted, reValidateMode, mode) => { if (mode.isOnAll) { return false; } else if (!isSubmitted && mode.isOnTouch) { return !(isTouched || isBlurEvent); } else if (isSubmitted ? reValidateMode.isOnBlur : mode.isOnBlur) { return !isBlurEvent; } else if (isSubmitted ? reValidateMode.isOnChange : mode.isOnChange) { return isBlurEvent; } return true; }; var unsetEmptyArray = (ref, name) => !compact(get(ref, name)).length && unset(ref, name); var updateFieldArrayRootError = (errors, error, name) => { const fieldArrayErrors = convertToArrayPayload(get(errors, name)); set(fieldArrayErrors, 'root', error[name]); set(errors, name, fieldArrayErrors); return errors; }; function getValidateError(result, ref, type = 'validate') { if (isString(result) || (Array.isArray(result) && result.every(isString)) || (isBoolean(result) && !result)) { return { type, message: isString(result) ? result : '', ref, }; } } var getValueAndMessage = (validationData) => isObject(validationData) && !isRegex(validationData) ? validationData : { value: validationData, message: '', }; var validateField = async (field, disabledFieldNames, formValues, validateAllFieldCriteria, shouldUseNativeValidation, isFieldArray) => { const { ref, refs, required, maxLength, minLength, min, max, pattern, validate, name, valueAsNumber, mount, } = field._f; const inputValue = get(formValues, name); if (!mount || disabledFieldNames.has(name)) { return {}; } const inputRef = refs ? refs[0] : ref; const setCustomValidity = (message) => { if (shouldUseNativeValidation && inputRef.reportValidity) { inputRef.setCustomValidity(isBoolean(message) ? '' : message || ''); inputRef.reportValidity(); } }; const error = {}; const isRadio = isRadioInput(ref); const isCheckBox = isCheckBoxInput(ref); const isRadioOrCheckbox = isRadio || isCheckBox; const isEmpty = ((valueAsNumber || isFileInput(ref)) && isUndefined(ref.value) && isUndefined(inputValue)) || (isHTMLElement(ref) && ref.value === '') || inputValue === '' || (Array.isArray(inputValue) && !inputValue.length); const appendErrorsCurry = appendErrors.bind(null, name, validateAllFieldCriteria, error); const getMinMaxMessage = (exceedMax, maxLengthMessage, minLengthMessage, maxType = INPUT_VALIDATION_RULES.maxLength, minType = INPUT_VALIDATION_RULES.minLength) => { const message = exceedMax ? maxLengthMessage : minLengthMessage; error[name] = { type: exceedMax ? maxType : minType, message, ref, ...appendErrorsCurry(exceedMax ? maxType : minType, message), }; }; if (isFieldArray ? !Array.isArray(inputValue) || !inputValue.length : required && ((!isRadioOrCheckbox && (isEmpty || isNullOrUndefined(inputValue))) || (isBoolean(inputValue) && !inputValue) || (isCheckBox && !getCheckboxValue(refs).isValid) || (isRadio && !getRadioValue(refs).isValid))) { const { value, message } = isString(required) ? { value: !!required, message: required } : getValueAndMessage(required); if (value) { error[name] = { type: INPUT_VALIDATION_RULES.required, message, ref: inputRef, ...appendErrorsCurry(INPUT_VALIDATION_RULES.required, message), }; if (!validateAllFieldCriteria) { setCustomValidity(message); return error; } } } if (!isEmpty && (!isNullOrUndefined(min) || !isNullOrUndefined(max))) { let exceedMax; let exceedMin; const maxOutput = getValueAndMessage(max); const minOutput = getValueAndMessage(min); if (!isNullOrUndefined(inputValue) && !isNaN(inputValue)) { const valueNumber = ref.valueAsNumber || (inputValue ? +inputValue : inputValue); if (!isNullOrUndefined(maxOutput.value)) { exceedMax = valueNumber > maxOutput.value; } if (!isNullOrUndefined(minOutput.value)) { exceedMin = valueNumber < minOutput.value; } } else { const valueDate = ref.valueAsDate || new Date(inputValue); const convertTimeToDate = (time) => new Date(new Date().toDateString() + ' ' + time); const isTime = ref.type == 'time'; const isWeek = ref.type == 'week'; if (isString(maxOutput.value) && inputValue) { exceedMax = isTime ? convertTimeToDate(inputValue) > convertTimeToDate(maxOutput.value) : isWeek ? inputValue > maxOutput.value : valueDate > new Date(maxOutput.value); } if (isString(minOutput.value) && inputValue) { exceedMin = isTime ? convertTimeToDate(inputValue) < convertTimeToDate(minOutput.value) : isWeek ? inputValue < minOutput.value : valueDate < new Date(minOutput.value); } } if (exceedMax || exceedMin) { getMinMaxMessage(!!exceedMax, maxOutput.message, minOutput.message, INPUT_VALIDATION_RULES.max, INPUT_VALIDATION_RULES.min); if (!validateAllFieldCriteria) { setCustomValidity(error[name].message); return error; } } } if ((maxLength || minLength) && !isEmpty && (isString(inputValue) || (isFieldArray && Array.isArray(inputValue)))) { const maxLengthOutput = getValueAndMessage(maxLength); const minLengthOutput = getValueAndMessage(minLength); const exceedMax = !isNullOrUndefined(maxLengthOutput.value) && inputValue.length > +maxLengthOutput.value; const exceedMin = !isNullOrUndefined(minLengthOutput.value) && inputValue.length < +minLengthOutput.value; if (exceedMax || exceedMin) { getMinMaxMessage(exceedMax, maxLengthOutput.message, minLengthOutput.message); if (!validateAllFieldCriteria) { setCustomValidity(error[name].message); return error; } } } if (pattern && !isEmpty && isString(inputValue)) { const { value: patternValue, message } = getValueAndMessage(pattern); if (isRegex(patternValue) && !inputValue.match(patternValue)) { error[name] = { type: INPUT_VALIDATION_RULES.pattern, message, ref, ...appendErrorsCurry(INPUT_VALIDATION_RULES.pattern, message), }; if (!validateAllFieldCriteria) { setCustomValidity(message); return error; } } } if (validate) { if (isFunction(validate)) { const result = await validate(inputValue, formValues); const validateError = getValidateError(result, inputRef); if (validateError) { error[name] = { ...validateError, ...appendErrorsCurry(INPUT_VALIDATION_RULES.validate, validateError.message), }; if (!validateAllFieldCriteria) { setCustomValidity(validateError.message); return error; } } } else if (isObject(validate)) { let validationResult = {}; for (const key in validate) { if (!isEmptyObject(validationResult) && !validateAllFieldCriteria) { break; } const validateError = getValidateError(await validate[key](inputValue, formValues), inputRef, key); if (validateError) { validationResult = { ...validateError, ...appendErrorsCurry(key, validateError.message), }; setCustomValidity(validateError.message); if (validateAllFieldCriteria) { error[name] = validationResult; } } } if (!isEmptyObject(validationResult)) { error[name] = { ref: inputRef, ...validationResult, }; if (!validateAllFieldCriteria) { return error; } } } } setCustomValidity(true); return error; }; const defaultOptions = { mode: VALIDATION_MODE.onSubmit, reValidateMode: VALIDATION_MODE.onChange, shouldFocusError: true, }; function createFormControl(props = {}) { let _options = { ...defaultOptions, ...props, }; let _formState = { submitCount: 0, isDirty: false, isReady: false, isLoading: isFunction(_options.defaultValues), isValidating: false, isSubmitted: false, isSubmitting: false, isSubmitSuccessful: false, isValid: false, touchedFields: {}, dirtyFields: {}, validatingFields: {}, errors: _options.errors || {}, disabled: _options.disabled || false, }; let _fields = {}; let _defaultValues = isObject(_options.defaultValues) || isObject(_options.values) ? cloneObject(_options.defaultValues || _options.values) || {} : {}; let _formValues = _options.shouldUnregister ? {} : cloneObject(_defaultValues); let _state = { action: false, mount: false, watch: false, }; let _names = { mount: new Set(), disabled: new Set(), unMount: new Set(), array: new Set(), watch: new Set(), }; let delayErrorCallback; let timer = 0; const _proxyFormState = { isDirty: false, dirtyFields: false, validatingFields: false, touchedFields: false, isValidating: false, isValid: false, errors: false, }; let _proxySubscribeFormState = { ..._proxyFormState, }; const _subjects = { array: createSubject(), state: createSubject(), }; const shouldDisplayAllAssociatedErrors = _options.criteriaMode === VALIDATION_MODE.all; const debounce = (callback) => (wait) => { clearTimeout(timer); timer = setTimeout(callback, wait); }; const _setValid = async (shouldUpdateValid) => { if (!_options.disabled && (_proxyFormState.isValid || _proxySubscribeFormState.isValid || shouldUpdateValid)) { const isValid = _options.resolver ? isEmptyObject((await _runSchema()).errors) : await executeBuiltInValidation(_fields, true); if (isValid !== _formState.isValid) { _subjects.state.next({ isValid, }); } } }; const _updateIsValidating = (names, isValidating) => { if (!_options.disabled && (_proxyFormState.isValidating || _proxyFormState.validatingFields || _proxySubscribeFormState.isValidating || _proxySubscribeFormState.validatingFields)) { (names || Array.from(_names.mount)).forEach((name) => { if (name) { isValidating ? set(_formState.validatingFields, name, isValidating) : unset(_formState.validatingFields, name); } }); _subjects.state.next({ validatingFields: _formState.validatingFields, isValidating: !isEmptyObject(_formState.validatingFields), }); } }; const _setFieldArray = (name, values = [], method, args, shouldSetValues = true, shouldUpdateFieldsAndState = true) => { if (args && method && !_options.disabled) { _state.action = true; if (shouldUpdateFieldsAndState && Array.isArray(get(_fields, name))) { const fieldValues = method(get(_fields, name), args.argA, args.argB); shouldSetValues && set(_fields, name, fieldValues); } if (shouldUpdateFieldsAndState && Array.isArray(get(_formState.errors, name))) { const errors = method(get(_formState.errors, name), args.argA, args.argB); shouldSetValues && set(_formState.errors, name, errors); unsetEmptyArray(_formState.errors, name); } if ((_proxyFormState.touchedFields || _proxySubscribeFormState.touchedFields) && shouldUpdateFieldsAndState && Array.isArray(get(_formState.touchedFields, name))) { const touchedFields = method(get(_formState.touchedFields, name), args.argA, args.argB); shouldSetValues && set(_formState.touchedFields, name, touchedFields); } if (_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) { _formState.dirtyFields = getDirtyFields(_defaultValues, _formValues); } _subjects.state.next({ name, isDirty: _getDirty(name, values), dirtyFields: _formState.dirtyFields, errors: _formState.errors, isValid: _formState.isValid, }); } else { set(_formValues, name, values); } }; const updateErrors = (name, error) => { set(_formState.errors, name, error); _subjects.state.next({ errors: _formState.errors, }); }; const _setErrors = (errors) => { _formState.errors = errors; _subjects.state.next({ errors: _formState.errors, isValid: false, }); }; const updateValidAndValue = (name, shouldSkipSetValueAs, value, ref) => { const field = get(_fields, name); if (field) { const defaultValue = get(_formValues, name, isUndefined(value) ? get(_defaultValues, name) : value); isUndefined(defaultValue) || (ref && ref.defaultChecked) || shouldSkipSetValueAs ? set(_formValues, name, shouldSkipSetValueAs ? defaultValue : getFieldValue(field._f)) : setFieldValue(name, defaultValue); _state.mount && !_state.action && _setValid(); } }; const updateTouchAndDirty = (name, fieldValue, isBlurEvent, shouldDirty, shouldRender) => { let shouldUpdateField = false; let isPreviousDirty = false; const output = { name, }; if (!_options.disabled) { if (!isBlurEvent || shouldDirty) { if (_proxyFormState.isDirty || _proxySubscribeFormState.isDirty) { isPreviousDirty = _formState.isDirty; _formState.isDirty = output.isDirty = _getDirty(); shouldUpdateField = isPreviousDirty !== output.isDirty; } const isCurrentFieldPristine = deepEqual(get(_defaultValues, name), fieldValue); isPreviousDirty = !!get(_formState.dirtyFields, name); isCurrentFieldPristine ? unset(_formState.dirtyFields, name) : set(_formState.dirtyFields, name, true); output.dirtyFields = _formState.dirtyFields; shouldUpdateField = shouldUpdateField || ((_proxyFormState.dirtyFields || _proxySubscribeFormState.dirtyFields) && isPreviousDirty !== !isCurrentFieldPristine); } if (isBlurEvent) { const isPreviousFieldTouched = get(_formState.touchedFields, name); if (!isPreviousFieldTouched) { set(_formState.touchedFields, name, isBlurEvent); output.touchedFields = _formState.touchedFields; shouldUpdateField = shouldUpdateField || ((_proxyFormState.touchedFields || _proxySubscribeFormState.touchedFields) && isPreviousFieldTouched !== isBlurEvent); } } shouldUpdateField && shouldRender && _subjects.state.next(output); } return shouldUpdateField ? output : {}; }; const shouldRenderByError = (name, isValid, error, fieldState) => { const previousFieldError = get(_formState.errors, name); const shouldUpdateValid = (_proxyFormState.isValid || _proxySubscribeFormState.isValid) && isBoolean(isValid) && _formState.isValid !== isValid; if (_options.delayError && error) { delayErrorCallback = debounce(() => updateErrors(name, error)); delayErrorCallback(_options.delayError); } else { clearTimeout(timer); delayErrorCallback = null; error ? set(_formState.errors, name, error) : unset(_formState.errors, name); } if ((error ? !deepEqual(previousFieldError, error) : previousFieldError) || !isEmptyObject(fieldState) || shouldUpdateValid) { const updatedFormState = { ...fieldState, ...(shouldUpdateValid && isBoolean(isValid) ? { isValid } : {}), errors: _formState.errors, name, }; _formState = { ..._formState, ...updatedFormState, }; _subjects.state.next(updatedFormState); } }; const _runSchema = async (name) => { _updateIsValidating(name, true); const result = await _options.resolver(_formValues, _options.context, getResolverOptions(name || _names.mount, _fields, _options.criteriaMode, _options.shouldUseNativeValidation)); _updateIsValidating(name); return result; }; const executeSchemaAndUpdateState = async (names) => { const { errors } = await _runSchema(names); if (names) { for (const name of names) { const error = get(errors, name); error ? set(_formState.errors, name, error) : unset(_formState.errors, name); } } else { _formState.errors = errors; } return errors; }; const executeBuiltInValidation = async (fields, shouldOnlyCheckValid, context = { valid: true, }) => { for (const name in fields) { const field = fields[name]; if (field) { const { _f, ...fieldValue } = field; if (_f) { const isFieldArrayRoot = _names.array.has(_f.name); const isPromiseFunction = field._f && hasPromiseValidation(field._f); if (isPromiseFunction && _proxyFormState.validatingFields) { _updateIsValidating([_f.name], true); } const fieldError = await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation && !shouldOnlyCheckValid, isFieldArrayRoot); if (isPromiseFunction && _proxyFormState.validatingFields) { _updateIsValidating([_f.name]); } if (fieldError[_f.name]) { context.valid = false; if (shouldOnlyCheckValid) { break; } } !shouldOnlyCheckValid && (get(fieldError, _f.name) ? isFieldArrayRoot ? updateFieldArrayRootError(_formState.errors, fieldError, _f.name) : set(_formState.errors, _f.name, fieldError[_f.name]) : unset(_formState.errors, _f.name)); } !isEmptyObject(fieldValue) && (await executeBuiltInValidation(fieldValue, shouldOnlyCheckValid, context)); } } return context.valid; }; const _removeUnmounted = () => { for (const name of _names.unMount) { const field = get(_fields, name); field && (field._f.refs ? field._f.refs.every((ref) => !live(ref)) : !live(field._f.ref)) && unregister(name); } _names.unMount = new Set(); }; const _getDirty = (name, data) => !_options.disabled && (name && data && set(_formValues, name, data), !deepEqual(getValues(), _defaultValues)); const _getWatch = (names, defaultValue, isGlobal) => generateWatchOutput(names, _names, { ...(_state.mount ? _formValues : isUndefined(defaultValue) ? _defaultValues : isString(names) ? { [names]: defaultValue } : defaultValue), }, isGlobal, defaultValue); const _getFieldArray = (name) => compact(get(_state.mount ? _formValues : _defaultValues, name, _options.shouldUnregister ? get(_defaultValues, name, []) : [])); const setFieldValue = (name, value, options = {}) => { const field = get(_fields, name); let fieldValue = value; if (field) { const fieldReference = field._f; if (fieldReference) { !fieldReference.disabled && set(_formValues, name, getFieldValueAs(value, fieldReference)); fieldValue = isHTMLElement(fieldReference.ref) && isNullOrUndefined(value) ? '' : value; if (isMultipleSelect(fieldReference.ref)) { [...fieldReference.ref.options].forEach((optionRef) => (optionRef.selected = fieldValue.includes(optionRef.value))); } else if (fieldReference.refs) { if (isCheckBoxInput(fieldReference.ref)) { fieldReference.refs.forEach((checkboxRef) => { if (!checkboxRef.defaultChecked || !checkboxRef.disabled) { if (Array.isArray(fieldValue)) { checkboxRef.checked = !!fieldValue.find((data) => data === checkboxRef.value); } else { checkboxRef.checked = fieldValue === checkboxRef.value || !!fieldValue; } } }); } else { fieldReference.refs.forEach((radioRef) => (radioRef.checked = radioRef.value === fieldValue)); } } else if (isFileInput(fieldReference.ref)) { fieldReference.ref.value = ''; } else { fieldReference.ref.value = fieldValue; if (!fieldReference.ref.type) { _subjects.state.next({ name, values: cloneObject(_formValues), }); } } } } (options.shouldDirty || options.shouldTouch) && updateTouchAndDirty(name, fieldValue, options.shouldTouch, options.shouldDirty, true); options.shouldValidate && trigger(name); }; const setValues = (name, value, options) => { for (const fieldKey in value) { if (!value.hasOwnProperty(fieldKey)) { return; } const fieldValue = value[fieldKey]; const fieldName = name + '.' + fieldKey; const field = get(_fields, fieldName); (_names.array.has(name) || isObject(fieldValue) || (field && !field._f)) && !isDateObject(fieldValue) ? setValues(fieldName, fieldValue, options) : setFieldValue(fieldName, fieldValue, options); } }; const setValue = (name, value, options = {}) => { const field = get(_fields, name); const isFieldArray = _names.array.has(name); const cloneValue = cloneObject(value); set(_formValues, name, cloneValue); if (isFieldArray) { _subjects.array.next({ name, values: cloneObject(_formValues), }); if ((_proxyFormState.isDirty || _proxyFormState.dirtyFields || _proxySubscribeFormState.isDirty || _proxySubscribeFormState.dirtyFields) && options.shouldDirty) { _subjects.state.next({ name, dirtyFields: getDirtyFields(_defaultValues, _formValues), isDirty: _getDirty(name, cloneValue), }); } } else { field && !field._f && !isNullOrUndefined(cloneValue) ? setValues(name, cloneValue, options) : setFieldValue(name, cloneValue, options); } isWatched(name, _names) && _subjects.state.next({ ..._formState, name }); _subjects.state.next({ name: _state.mount ? name : undefined, values: cloneObject(_formValues), }); }; const onChange = async (event) => { _state.mount = true; const target = event.target; let name = target.name; let isFieldValueUpdated = true; const field = get(_fields, name); const _updateIsFieldValueUpdated = (fieldValue) => { isFieldValueUpdated = Number.isNaN(fieldValue) || (isDateObject(fieldValue) && isNaN(fieldValue.getTime())) || deepEqual(fieldValue, get(_formValues, name, fieldValue)); }; const validationModeBeforeSubmit = getValidationModes(_options.mode); const validationModeAfterSubmit = getValidationModes(_options.reValidateMode); if (field) { let error; let isValid; const fieldValue = target.type ? getFieldValue(field._f) : getEventValue(event); const isBlurEvent = event.type === EVENTS.BLUR || event.type === EVENTS.FOCUS_OUT; const shouldSkipValidation = (!hasValidation(field._f) && !_options.resolver && !get(_formState.errors, name) && !field._f.deps) || skipValidation(isBlurEvent, get(_formState.touchedFields, name), _formState.isSubmitted, validationModeAfterSubmit, validationModeBeforeSubmit); const watched = isWatched(name, _names, isBlurEvent); set(_formValues, name, fieldValue); if (isBlurEvent) { if (!target || !target.readOnly) { field._f.onBlur && field._f.onBlur(event); delayErrorCallback && delayErrorCallback(0); } } else if (field._f.onChange) { field._f.onChange(event); } const fieldState = updateTouchAndDirty(name, fieldValue, isBlurEvent); const shouldRender = !isEmptyObject(fieldState) || watched; !isBlurEvent && _subjects.state.next({ name, type: event.type, values: cloneObject(_formValues), }); if (shouldSkipValidation) { if (_proxyFormState.isValid || _proxySubscribeFormState.isValid) { if (_options.mode === 'onBlur') { if (isBlurEvent) { _setValid(); } } else if (!isBlurEvent) { _setValid(); } } return (shouldRender && _subjects.state.next({ name, ...(watched ? {} : fieldState) })); } !isBlurEvent && watched && _subjects.state.next({ ..._formState }); if (_options.resolver) { const { errors } = await _runSchema([name]); _updateIsFieldValueUpdated(fieldValue); if (isFieldValueUpdated) { const previousErrorLookupResult = schemaErrorLookup(_formState.errors, _fields, name); const errorLookupResult = schemaErrorLookup(errors, _fields, previousErrorLookupResult.name || name); error = errorLookupResult.error; name = errorLookupResult.name; isValid = isEmptyObject(errors); } } else { _updateIsValidating([name], true); error = (await validateField(field, _names.disabled, _formValues, shouldDisplayAllAssociatedErrors, _options.shouldUseNativeValidation))[name]; _updateIsValidating([name]); _updateIsFieldValueUpdated(fieldValue); if (isFieldValueUpdated) { if (error) { isValid = false; } else if (_proxyFormState.isValid || _proxySubscribeFormState.isValid) { isValid = await executeBuiltInValidation(_fields, true); } } } if (isFieldValueUpdated) { field._f.deps && (!Array.isArray(field._f.deps) || field._f.deps.length > 0) && trigger(field._f.deps); shouldRenderByError(name, isValid, error, fieldState); } } }; const _focusInput = (ref, key) => { if (get(_formState.errors, key) && ref.focus) { ref.focus(); return 1; } return; }; const trigger = async (name, options = {}) => { let isValid; let validationResult; const fieldNames = convertToArrayPayload(name); if (_options.resolver) { const errors = await executeSchemaAndUpdateState(isUndefined(name) ? name : fieldNames); isValid = isEmptyObject(errors); validationResult = name ? !fieldNames.some((name) => get(errors, name)) : isValid; } else if (name) { validationResult = (await Promise.all(fieldNames.map(async (fieldName) => { const field = get(_fields, fieldName); return await executeBuiltInValidation(field && field._f ? { [fieldName]: field } : field); }))).every(Boolean); !(!validationResult && !_formState.isValid) && _setValid(); } else { validationResult = isValid = await executeBuiltInValidation(_fields); } _subjects.state.next({ ...(!isString(name) || ((_proxyFormState.isValid || _proxySubscribeFormState.isValid) && isValid !== _formState.isValid) ? {} : { name }), ...(_options.resolver || !name ? { isValid } : {}), errors: _formState.errors, }); options.shouldFocus && !validationResult && iterateFieldsByAction(_fields, _focusInput, name ? fieldNames : _names.mount); return validationResult; }; const getValues = (fieldNames, config) => { let values = { ...(_state.mount ? _formValues : _defaultValues), }; if (config) { values = extractFormValues(config.dirtyFields ? _formState.dirtyFields : _formState.touchedFields, values); } return isUndefined(fieldNames) ? values : isString(fieldNames) ? get(values, fieldNames) : fieldNames.map((name) => get(values, name)); }; const getFieldState = (name, formState) => ({ invalid: !!get((formState || _formState).errors, name), isDirty: !!get((formState || _formState).dirtyFields, name), error: get((formState || _formState).errors, name), isValidating: !!get(_formState.validatingFields, name), isTouched: !!get((formState || _formState).touchedFields, name), }); const clearErrors = (name) => { name && convertToArrayPayload(name).forEach((inputName) => unset(_formState.errors, inputName)); _subjects.state.next({ errors: name ? _formState.errors : {}, }); }; const setError = (name, error, options) => { const ref = (get(_fields, name, { _f: {} })._f || {}).ref; const currentError = get(_formState.errors, name) || {}; // Don't override existing error messages elsewhere in the object tree. const { ref: currentRef, message, type, ...restOfErrorTree } = currentError; set(_formState.errors, name, { ...restOfErrorTree, ...error, ref, }); _subjects.state.next({ name, errors: _formState.errors, isValid: false, }); options && options.shouldFocus && ref && ref.focus && ref.focus(); }; const watch = (name, defaultValue) => isFunction(name) ? _subjects.state.subscribe({ next: (payload) => 'values' in payload && name(_getWatch(undefined, defaultValue), payload), }) : _getWatch(name, defaultValue, true); const _subscribe = (props) => _subjects.state.subscribe({ next: (formState) => { if (shouldSubscribeByName(props.name, formState.name, props.exact) && shouldRenderFormState(formState, props.formState || _proxyFormState, _setFormState, props.reRenderRoot)) { props.callback({ values: { ..._formValues }, ..._formState, ...formState, defaultValues: _defaultValues, }); } }, }).unsubscribe; const subscribe = (props) => { _state.mount = true; _proxySubscribeFormState = { ..._proxySubscribeFormState, ...props.formState, }; return _subscribe({ ...props, formState: _proxySubscribeFormState, }); }; const unregister = (name, options = {}) => { for (const fieldName of name ? convertToArrayPayload(name) : _names.mount) { _names.mount.delete(fieldName); _names.array.delete(fieldName); if (!options.keepValue) { unset(_fields, fieldName); unset(_formValues, fieldName); } !options.keepError && unset(_formState.errors, fieldName); !options.keepDirty && unset(_formState.dirtyFields, fieldName); !options.keepTouched && unset(_formState.touchedFields, fieldName); !options.keepIsValidating && unset(_formState.validatingFields, fieldName); !_options.shouldUnregister && !options.keepDefaultValue && unset(_defaultValues, fieldName); } _subjects.state.next({ values: cloneObject(_formValues), }); _subjects.state.next({ ..._formState, ...(!options.keepDirty ? {} : { isDirty: _getDirty() }), }); !options.keepIsValid && _setValid(); }; const _setDisabledField = ({ disabled, name, }) => { if ((isBoolean(disabled) && _state.mount) || !!disabled || _names.disabled.has(name)) { disabled ? _names.disabled.add(name) : _names.disabled.delete(name); } }; const register = (name, options = {}) => { let field = get(_fields, name); const disabledIsDefined = isBoolean(options.disabled) || isBoolean(_options.disabled); set(_fields, name, { ...(field || {}), _f: { ...(field && field._f ? field._f : { ref: { name } }), name, mount: true, ...options, }, }); _names.mount.add(name); if (field) { _setDisabledField({ disabled: isBoolean(options.disabled) ? options.disabled : _options.disabled, name, }); } else { updateValidAndValue(name, true, options.value); } return { ...(disabledIsDefined ? { disabled: options.disabled || _options.disabled } : {}), ...(_options.progressive ? { required: !!options.required, min: getRuleValue(options.min), max: getRuleValue(options.max), minLength: getRuleValue(options.minLength), maxLength: getRuleValue(options.maxLength), pattern: getRuleValue(options.pattern), } : {}), name, onChange, onBlur: onChange, ref: (ref) => { if (ref) { register(name, options); field = get(_fields, name); const fieldRef = isUndefined(ref.value) ? ref.querySelectorAll ? ref.querySelectorAll('input,select,textarea')[0] || ref : ref : ref; const radioOrCheckbox = isRadioOrCheckbox(fieldRef); const refs = field._f.refs || []; if (radioOrCheckbox ? refs.find((option) => option === fieldRef) : fieldRef === field._f.ref) { return; } set(_fields, name, { _f: { ...field._f, ...(radioOrCheckbox ? { refs: [ ...refs.filter(live), fieldRef, ...(Array.isArray(get(_defaultValues, name)) ? [{}] : []), ], ref: { type: fieldRef.type, name }, } : { ref: fieldRef }), }, }); updateValidAndValue(name, false, undefined, fieldRef); } else { field = get(_fields, name, {}); if (field._f) { field._f.mount = false; } (_options.shouldUnregister || options.shouldUnregister) && !(isNameInFieldArray(_names.array, name) && _state.action) && _names.unMount.add(name); } }, }; }; const _focusError = () => _options.shouldFocusError && iterateFieldsByAction(_fields, _focusInput, _names.mount); const _disableForm = (disabled) => { if (isBoolean(disabled)) { _subjects.state.next({ disabled }); iterateFieldsByAction(_fields, (ref, name) => { const currentField = get(_fields, name); if (currentField) { ref.disabled = currentField._f.disabled || disabled; if (Array.isArray(currentField._f.refs)) { currentField._f.refs.forEach((inputRef) => { inputRef.disabled = currentField._f.disabled || disabled; }); } } }, 0, false); } }; const handleSubmit = (onValid, onInvalid) => async (e) => { let onValidError = undefined; if (e) { e.preventDefault && e.preventDefault(); e.persist && e.persist(); } let fieldValues = cloneObject(_formValues); _subjects.state.next({ isSubmitting: true, }); if (_options.resolver) { const { errors, values } = await _runSchema(); _formState.errors = errors; fieldValues = cloneObject(values); } else { await executeBuiltInValidation(_fields); } if (_names.disabled.size) { for (const name of _names.disabled) { unset(fieldValues, name); } } unset(_formState.errors, 'root'); if (isEmptyObject(_formState.errors)) { _subjects.state.next({ errors: {}, }); try { await onValid(fieldValues, e); } catch (error) { onValidError = error; } } else { if (onInvalid) { await onInvalid({ ..._formState.errors }, e); } _focusError(); setTimeout(_focusError); } _subjects.state.next({ isSubmitted: true, isSubmitting: false, isSubmitSuccessful: isEmptyObject(_formState.errors) && !onValidError, submitCount: _formState.submitCount + 1, errors: _formState.errors, }); if (onValidError) { throw onValidError; } }; const resetField = (name, options = {}) => { if (get(_fields, name)) { if (isUndefined(options.defaultValue)) { setValue(name, cloneObject(get(_defaultValues, name))); } else { setValue(name, options.defaultValue); set(_defaultValues, name, cloneObject(options.defaultValue)); } if (!options.keepTouched) { unset(_formState.touchedFields, name); } if (!options.keepDirty) { unset(_formState.dirtyFields, name); _formState.isDirty = options.defaultValue ? _getDirty(name, cloneObject(get(_defaultValues, name))) : _getDirty(); } if (!options.keepError) { unset(_formState.errors, name); _proxyFormState.isValid && _setValid(); } _subjects.state.next({ ..._formState }); } }; const _reset = (formValues, keepStateOptions = {}) => { const updatedValues = formValues ? cloneObject(formValues) : _defaultValues; const cloneUpdatedValues = cloneObject(updatedValues); const isEmptyResetValues = isEmptyObject(formValues); const values = isEmptyResetValues ? _defaultValues : cloneUpdatedValues; if (!keepStateOptions.keepDefaultValues) { _defaultValues = updatedValues; } if (!keepStateOptions.keepValues) { if (keepStateOptions.keepDirtyValues) { const fieldsToCheck = new Set([ ..._names.mount, ...Object.keys(getDirtyFields(_defaultValues, _formValues)), ]); for (const fieldName of Array.from(fieldsToCheck)) { get(_formState.dirtyFields, fieldName) ? set(values, fieldName, get(_formValues, fieldName)) : setValue(fieldName, get(values, fieldName)); } } else { if (isWeb && isUndefined(formValues)) { for (const name of _names.mount) { const field = get(_fields, name); if (field && field._f) { const fieldReference = Array.isArray(field._f.refs) ? field._f.refs[0] : field._f.ref; if (isHTMLElement(fieldReference)) { const form = fieldReference.closest('form'); if (form) { form.reset(); break; } } } } } if (keepStateOptions.keepFieldsRef) { for (const fieldName of _names.mount) { setValue(fieldName, get(values, fieldName)); } } else { _fields = {}; } } _formValues = _options.shouldUnregister ? keepStateOptions.keepDefaultValues ? cloneObject(_defaultValues) : {} : cloneObject(values); _subjects.array.next({ values: { ...values }, }); _subjects.state.next({ values: { ...values }, }); } _names = { mount: keepStateOptions.keepDirtyValues ? _names.mount : new Set(), unMount: new Set(), array: new Set(), disabled: new Set(), watch: new Set(), watchAll: false, focus: '', }; _state.mount = !_proxyFormState.isValid || !!keepStateOptions.keepIsValid || !!keepStateOptions.keepDirtyValues || (!_options.shouldUnregister && !isEmptyObject(values)); _state.watch = !!_options.shouldUnregister; _subjects.state.next({ submitCount: keepStateOptions.keepSubmitCount ? _formState.submitCount : 0, isDirty: isEmptyResetValues ? false : keepStateOptions.keepDirty ? _formState.isDirty : !!(keepStateOptions.keepDefaultValues && !deepEqual(formValues, _defaultValues)), isSubmitted: keepStateOptions.keepIsSubmitted ? _formState.isSubmitted : false, dirtyFields: isEmptyResetValues ? {} : keepStateOptions.keepDirtyValues ? keepStateOptions.keepDefaultValues && _formValues ? getDirtyFields(_defaultValues, _formValues) : _formState.dirtyFields : keepStateOptions.keepDefaultValues && formValues ? getDirtyFields(_defaultValues, formValues) : keepStateOptions.keepDirty ? _formState.dirtyFields : {}, touchedFields: keepStateOptions.keepTouched ? _formState.touchedFields : {}, errors: keepStateOptions.keepErrors ? _formState.errors : {}, isSubmitSuccessful: keepStateOptions.keepIsSubmitSuccessful ? _formState.isSubmitSuccessful : false, isSubmitting: false, defaultValues: _defaultValues, }); }; const reset = (formValues, keepStateOptions) => _reset(isFunction(formValues) ? formValues(_formValues) : formValues, keepStateOptions); const setFocus = (name, options = {}) => { const field = get(_fields, name); const fieldReference = field && field._f; if (fieldReference) { const fieldRef = fieldReference.refs ? fieldReference.refs[0] : fieldReference.ref; if (fieldRef.focus) { fieldRef.focus(); options.shouldSelect && isFunction(fieldRef.select) && fieldRef.select(); } } }; const _setFormState = (updatedFormState) => { _formState = { ..._formState, ...updatedFormState, }; }; const _resetDefaultValues = () => isFunction(_options.defaultValues) && _options.defaultValues().then((values) => { reset(values, _options.resetOptions); _subjects.state.next({ isLoading: false, }); }); const methods = { control: { register, unregister, getFieldState, handleSubmit, setError, _subscribe, _runSchema, _focusError, _getWatch, _getDirty, _setValid, _setFieldArray, _setDisabledField, _setErrors, _getFieldArray, _reset, _resetDefaultValues, _removeUnmounted, _disableForm, _subjects, _proxyFormState, get _fields() { return _fields; }, get _formValues() { return _formValues; }, get _state() { return _state; }, set _state(value) { _state = value; }, get _defaultValues() { return _defaultValues; }, get _names() { return _names; }, set _names(value) { _names = value; }, get _formState() { return _formState; }, get _options() { return _options; }, set _options(value) { _options = { ..._options, ...value, }; }, }, subscribe, trigger, register, handleSubmit, watch, setValue, getValues, reset, resetField, clearErrors, unregister, setError, setFocus, getFieldState, }; return { ...methods, formControl: methods, }; } var generateId = () => { if (typeof crypto !== 'undefined' && crypto.randomUUID) { return crypto.randomUUID(); } const d = typeof performance === 'undefined' ? Date.now() : performance.now() * 1000; return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => { const r = (Math.random() * 16 + d) % 16 | 0; return (c == 'x' ? r : (r & 0x3) | 0x8).toString(16); }); }; var getFocusFieldName = (name, index, options = {}) => options.shouldFocus || isUndefined(options.shouldFocus) ? options.focusName || `${name}.${isUndefined(options.focusIndex) ? index : options.focusIndex}.` : ''; var appendAt = (data, value) => [ ...data, ...convertToArrayPayload(value), ]; var fillEmptyArray = (value) => Array.isArray(value) ? value.map(() => undefined) : undefined; function insert(data, index, value) { return [ ...data.slice(0, index), ...convertToArrayPayload(value), ...data.slice(index), ]; } var moveArrayAt = (data, from, to) => { if (!Array.isArray(data)) { return []; } if (isUndefined(data[to])) { data[to] = undefined; } data.splice(to, 0, data.splice(from, 1)[0]); return data; }; var prependAt = (data, value) => [ ...convertToArrayPayload(value), ...convertToArrayPayload(data), ]; function removeAtIndexes(data, indexes) { let i = 0; const temp = [...data]; for (const index of indexes) { temp.splice(index - i, 1); i++; } return compact(temp).length ? temp : []; } var removeArrayAt = (data, index) => isUndefined(index) ? [] : removeAtIndexes(data, convertToArrayPayload(index).sort((a, b) => a - b)); var swapArrayAt = (data, indexA, indexB) => { [data[indexA], data[indexB]] = [data[indexB], data[indexA]]; }; var updateAt = (fieldValues, index, value) => { fieldValues[index] = value; return fieldValues; }; /** * A custom hook that exposes convenient methods to perform operations with a list of dynamic inputs that need to be appended, updated, removed etc. • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn) • [Video](https://youtu.be/4MrbfGSFY2A) * * @remarks * [API](https://react-hook-form.com/docs/usefieldarray) • [Demo](https://codesandbox.io/s/react-hook-form-usefieldarray-ssugn) * * @param props - useFieldArray props * * @returns methods - functions to manipulate with the Field Arrays (dynamic inputs) {@link UseFieldArrayReturn} * * @example * ```tsx * function App() { * const { register, control, handleSubmit, reset, trigger, setError } = useForm({ * defaultValues: { * test: [] * } * }); * const { fields, append } = useFieldArray({ * control, * name: "test" * }); * * return ( *
console.log(data))}> * {fields.map((item, index) => ( * * ))} * * *
* ); * } * ``` */ function useFieldArray(props) { const methods = useFormContext(); const { control = methods.control, name, keyName = 'id', shouldUnregister, rules, } = props; const [fields, setFields] = React.useState(control._getFieldArray(name)); const ids = React.useRef(control._getFieldArray(name).map(generateId)); const _actioned = React.useRef(false); control._names.array.add(name); React.useMemo(() => rules && fields.length >= 0 && control.register(name, rules), [control, name, fields.length, rules]); useIsomorphicLayoutEffect(() => control._subjects.array.subscribe({ next: ({ values, name: fieldArrayName, }) => { if (fieldArrayName === name || !fieldArrayName) { const fieldValues = get(values, name); if (Array.isArray(fieldValues)) { setFields(fieldValues); ids.current = fieldValues.map(generateId); } } }, }).unsubscribe, [control, name]); const updateValues = React.useCallback((updatedFieldArrayValues) => { _actioned.current = true; control._setFieldArray(name, updatedFieldArrayValues); }, [control, name]); const append = (value, options) => { const appendValue = convertToArrayPayload(cloneObject(value)); const updatedFieldArrayValues = appendAt(control._getFieldArray(name), appendValue); control._names.focus = getFocusFieldName(name, updatedFieldArrayValues.length - 1, options); ids.current = appendAt(ids.current, appendValue.map(generateId)); updateValues(updatedFieldArrayValues); setFields(updatedFieldArrayValues); control._setFieldArray(name, updatedFieldArrayValues, appendAt, { argA: fillEmptyArray(value), }); }; const prepend = (value, options) => { const prependValue = convertToArrayPayload(cloneObject(value)); const updatedFieldArrayValues = prependAt(control._getFieldArray(name), prependValue); control._names.focus = getFocusFieldName(name, 0, options); ids.current = prependAt(ids.current, prependValue.map(generateId)); updateValues(updatedFieldArrayValues); setFields(updatedFieldArrayValues); control._setFieldArray(name, updatedFieldArrayValues, prependAt, { argA: fillEmptyArray(value), }); }; const remove = (index) => { const updatedFieldArrayValues = removeArrayAt(control._getFieldArray(name), index); ids.current = removeArrayAt(ids.current, index); updateValues(updatedFieldArrayValues); setFields(updatedFieldArrayValues); !Array.isArray(get(control._fields, name)) && set(control._fields, name, undefined); control._setFieldArray(name, updatedFieldArrayValues, removeArrayAt, { argA: index, }); }; const insert$1 = (index, value, options) => { const insertValue = convertToArrayPayload(cloneObject(value)); const updatedFieldArrayValues = insert(control._getFieldArray(name), index, insertValue); control._names.focus = getFocusFieldName(name, index, options); ids.current = insert(ids.current, index, insertValue.map(generateId)); updateValues(updatedFieldArrayValues); setFields(updatedFieldArrayValues); control._setFieldArray(name, updatedFieldArrayValues, insert, { argA: index, argB: fillEmptyArray(value), }); }; const swap = (indexA, indexB) => { const updatedFieldArrayValues = control._getFieldArray(name); swapArrayAt(updatedFieldArrayValues, indexA, indexB); swapArrayAt(ids.current, indexA, indexB); updateValues(updatedFieldArrayValues); setFields(updatedFieldArrayValues); control._setFieldArray(name, updatedFieldArrayValues, swapArrayAt, { argA: indexA, argB: indexB, }, false); }; const move = (from, to) => { const updatedFieldArrayValues = control._getFieldArray(name); moveArrayAt(updatedFieldArrayValues, from, to); moveArrayAt(ids.current, from, to); updateValues(updatedFieldArrayValues); setFields(updatedFieldArrayValues); control._setFieldArray(name, updatedFieldArrayValues, moveArrayAt, { argA: from, argB: to, }, false); }; const update = (index, value) => { const updateValue = cloneObject(value); const updatedFieldArrayValues = updateAt(control._getFieldArray(name), index, updateValue); ids.current = [...updatedFieldArrayValues].map((item, i) => !item || i === index ? generateId() : ids.current[i]); updateValues(updatedFieldArrayValues); setFields([...updatedFieldArrayValues]); control._setFieldArray(name, updatedFieldArrayValues, updateAt, { argA: index, argB: updateValue, }, true, false); }; const replace = (value) => { const updatedFieldArrayValues = convertToArrayPayload(cloneObject(value)); ids.current = updatedFieldArrayValues.map(generateId); updateValues([...updatedFieldArrayValues]); setFields([...updatedFieldArrayValues]); control._setFieldArray(name, [...updatedFieldArrayValues], (data) => data, {}, true, false); }; React.useEffect(() => { control._state.action = false; isWatched(name, control._names) && control._subjects.state.next({ ...control._formState, }); if (_actioned.current && (!getValidationModes(control._options.mode).isOnSubmit || control._formState.isSubmitted) && !getValidationModes(control._options.reValidateMode).isOnSubmit) { if (control._options.resolver) { control._runSchema([name]).then((result) => { const error = get(result.errors, name); const existingError = get(control._formState.errors, name); if (existingError ? (!error && existingError.type) || (error && (existingError.type !== error.type || existingError.message !== error.message)) : error && error.type) { error ? set(control._formState.errors, name, error) : unset(control._formState.errors, name); control._subjects.state.next({ errors: control._formState.errors, }); } }); } else { const field = get(control._fields, name); if (field && field._f && !(getValidationModes(control._options.reValidateMode).isOnSubmit && getValidationModes(control._options.mode).isOnSubmit)) { validateField(field, control._names.disabled, control._formValues, control._options.criteriaMode === VALIDATION_MODE.all, control._options.shouldUseNativeValidation, true).then((error) => !isEmptyObject(error) && control._subjects.state.next({ errors: updateFieldArrayRootError(control._formState.errors, error, name), })); } } } control._subjects.state.next({ name, values: cloneObject(control._formValues), }); control._names.focus && iterateFieldsByAction(control._fields, (ref, key) => { if (control._names.focus && key.startsWith(control._names.focus) && ref.focus) { ref.focus(); return 1; } return; }); control._names.focus = ''; control._setValid(); _actioned.current = false; }, [fields, name, control]); React.useEffect(() => { !get(control._formValues, name) && control._setFieldArray(name); return () => { const updateMounted = (name, value) => { const field = get(control._fields, name); if (field && field._f) { field._f.mount = value; } }; control._options.shouldUnregister || shouldUnregister ? control.unregister(name) : updateMounted(name, false); }; }, [name, control, keyName, shouldUnregister]); return { swap: React.useCallback(swap, [updateValues, name, control]), move: React.useCallback(move, [updateValues, name, control]), prepend: React.useCallback(prepend, [updateValues, name, control]), append: React.useCallback(append, [updateValues, name, control]), remove: React.useCallback(remove, [updateValues, name, control]), insert: React.useCallback(insert$1, [updateValues, name, control]), update: React.useCallback(update, [updateValues, name, control]), replace: React.useCallback(replace, [updateValues, name, control]), fields: React.useMemo(() => fields.map((field, index) => ({ ...field, [keyName]: ids.current[index] || generateId(), })), [fields, keyName]), }; } /** * Custom hook to manage the entire form. * * @remarks * [API](https://react-hook-form.com/docs/useform) • [Demo](https://codesandbox.io/s/react-hook-form-get-started-ts-5ksmm) • [Video](https://www.youtube.com/watch?v=RkXv4AXXC_4) * * @param props - form configuration and validation parameters. * * @returns methods - individual functions to manage the form state. {@link UseFormReturn} * * @example * ```tsx * function App() { * const { register, handleSubmit, watch, formState: { errors } } = useForm(); * const onSubmit = data => console.log(data); * * console.log(watch("example")); * * return ( *
* * * {errors.exampleRequired && This field is required} * *
* ); * } * ``` */ function useForm(props = {}) { const _formControl = react__WEBPACK_IMPORTED_MODULE_0__.useRef(undefined); const _values = react__WEBPACK_IMPORTED_MODULE_0__.useRef(undefined); const [formState, updateFormState] = react__WEBPACK_IMPORTED_MODULE_0__.useState({ isDirty: false, isValidating: false, isLoading: isFunction(props.defaultValues), isSubmitted: false, isSubmitting: false, isSubmitSuccessful: false, isValid: false, submitCount: 0, dirtyFields: {}, touchedFields: {}, validatingFields: {}, errors: props.errors || {}, disabled: props.disabled || false, isReady: false, defaultValues: isFunction(props.defaultValues) ? undefined : props.defaultValues, }); if (!_formControl.current) { if (props.formControl) { _formControl.current = { ...props.formControl, formState, }; if (props.defaultValues && !isFunction(props.defaultValues)) { props.formControl.reset(props.defaultValues, props.resetOptions); } } else { const { formControl, ...rest } = createFormControl(props); _formControl.current = { ...rest, formState, }; } } const control = _formControl.current.control; control._options = props; useIsomorphicLayoutEffect(() => { const sub = control._subscribe({ formState: control._proxyFormState, callback: () => updateFormState({ ...control._formState }), reRenderRoot: true, }); updateFormState((data) => ({ ...data, isReady: true, })); control._formState.isReady = true; return sub; }, [control]); react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => control._disableForm(props.disabled), [control, props.disabled]); react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => { if (props.mode) { control._options.mode = props.mode; } if (props.reValidateMode) { control._options.reValidateMode = props.reValidateMode; } }, [control, props.mode, props.reValidateMode]); react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => { if (props.errors) { control._setErrors(props.errors); control._focusError(); } }, [control, props.errors]); react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => { props.shouldUnregister && control._subjects.state.next({ values: control._getWatch(), }); }, [control, props.shouldUnregister]); react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => { if (control._proxyFormState.isDirty) { const isDirty = control._getDirty(); if (isDirty !== formState.isDirty) { control._subjects.state.next({ isDirty, }); } } }, [control, formState.isDirty]); react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => { var _a; if (props.values && !deepEqual(props.values, _values.current)) { control._reset(props.values, { keepFieldsRef: true, ...control._options.resetOptions, }); if (!((_a = control._options.resetOptions) === null || _a === void 0 ? void 0 : _a.keepIsValid)) { control._setValid(); } _values.current = props.values; updateFormState((state) => ({ ...state })); } else { control._resetDefaultValues(); } }, [control, props.values]); react__WEBPACK_IMPORTED_MODULE_0__.useEffect(() => { if (!control._state.mount) { control._setValid(); control._state.mount = true; } if (control._state.watch) { control._state.watch = false; control._subjects.state.next({ ...control._formState }); } control._removeUnmounted(); }); _formControl.current.formState = getProxyFormState(formState, control); return _formControl.current; } /** * Watch component that subscribes to form field changes and re-renders when watched fields update. * * @param control - The form control object from useForm * @param names - Array of field names to watch for changes * @param render - The function that receives watched values and returns ReactNode * @returns The result of calling render function with watched values * * @example * The `Watch` component only re-render when the values of `foo`, `bar`, and `baz.qux` change. * The types of `foo`, `bar`, and `baz.qux` are precisely inferred. * * ```tsx * const { control } = useForm(); * *
{foo}{bar}{baz_qux}
} * /> * ``` */ const Watch = ({ control, names, render, }) => render(useWatch({ control, name: names })); //# sourceMappingURL=index.esm.mjs.map /***/ }) }]); //# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiNzU1LmpzIiwibWFwcGluZ3MiOiI7Ozs7O0FBQUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQSx3QkFBd0IscUJBQU0sZ0JBQWdCLHFCQUFNLElBQUkscUJBQU0sc0JBQXNCLHFCQUFNOztBQUUxRjtBQUNBOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhLFFBQVE7QUFDckI7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsVUFBVTtBQUNyQixXQUFXLFFBQVE7QUFDbkIsV0FBVyxRQUFRLFdBQVc7QUFDOUIsV0FBVyxTQUFTO0FBQ3BCO0FBQ0EsV0FBVyxRQUFRO0FBQ25CO0FBQ0EsV0FBVyxTQUFTO0FBQ3BCO0FBQ0EsYUFBYSxVQUFVO0FBQ3ZCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLElBQUk7QUFDSjtBQUNBO0FBQ0EsK0NBQStDLGlCQUFpQjtBQUNoRTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsR0FBRztBQUNkLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0EsZ0JBQWdCO0FBQ2hCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxHQUFHO0FBQ2QsYUFBYSxTQUFTO0FBQ3RCO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFdBQVcsR0FBRztBQUNkLGFBQWEsU0FBUztBQUN0QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtB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O0FBQzlDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQSx3QkFBd0I7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsT0FBTztBQUNQOztBQUVBO0FBQ0E7O0FBRUE7QUFDQTs7QUFFQSx3QkFBd0I7QUFDeEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxPQUFPO0FBQ1A7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsVUFBVTtBQUNWO0FBQ0E7QUFDQSxRQUFRO0FBQ1I7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLE9BQU87QUFDUDtBQUNBLEdBQUc7O0FBRUg7QUFDQSxDQUFDOztBQUVEO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQSxH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Q0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQSxpQ0FBaUM7QUFDakM7QUFDQTtBQUNBO0FBQ0E7QUFDQSxJQUFJO0FBQ0o7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBLEtBQUs7QUFDTDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBLEdBQUc7QUFDSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw2Q0FBNkM7QUFDN0MsVUFBVSxnQ0FBZ0M7QUFDMUM7QUFDQTtBQUNBO0FBQ0EsR0FBRztBQUNIO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLEVBQUUsSUFBSTtBQUNOO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxHQUFHO0FBQ0g7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxx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QUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQSxZQUFZLHNHQUFzRztBQUNsSDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLGlCQUFpQjtBQUNqQyxnQkFBZ0I7QUFDaEI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0JBQWdCLCtCQUErQjtBQUMvQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFDQUFxQztBQUNyQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EseUJBQXlCO0FBQ3pCLHVCQUF1QjtBQUN2Qiw0QkFBNEI7QUFDNUIscUNBQXFDO0FBQ3JDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnRUFBZ0UsVUFBVSxJQUFJO0FBQzlFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxnQkFBZ0IsU0FBUztBQUN6QjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0Esd0JBQXdCLG9CQUFvQjtBQUM1QztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7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QkFBMEIsV0FBVztBQUNyQyxhQUFhO0FBQ2I7QUFDQSwwQkFBMEIsV0FBVztBQUNyQyxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsZ0NBQWdDO0FBQ2hDO0FBQ0E7QUFDQSxvQkFBb0I7QUFDcEIsd0VBQXdFO0FBQ3hFO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxTQUFTO0FBQ1Q7QUFDQTtBQUNBO0FBQ0E7QUFDQSx3Q0FBd0M7QUFDeEM7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2IsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7O0FBRUEsa0RBQWtEO0FBQ2xEO0FBQ0EsV0FBVyxLQUFLLEdBQUcsNkRBQTZEO0FBQ2hGOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTs7QUFFQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNGQUFzRjtBQUN0RjtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsNERBQTREO0FBQ3pFO0FBQ0E7QUFDQTtBQUNBLE1BQU07QUFDTixhQUFhLGlCQUFpQjtBQUM5QjtBQUNBO0FBQ0EsTUFBTTtBQUNOO0FBQ0E7QUFDQSx1QkFBdUIsd0NBQXdDO0FBQy9ELFVBQVU7QUFDVix3QkFBd0IsVUFBVSxvQkFBb0IsTUFBTSxlQUFlO0FBQzNFO0FBQ0Esd0NBQXdDLGVBQWUsbUJBQW1CLEVBQUU7QUFDNUU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxZQUFZLDRFQUE0RTtBQUN4RjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCLCtCQUErQjtBQUNoRDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVCxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHFGQUFxRjtBQUNyRjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxhQUFhO0FBQ2I7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQSxpQkFBaUI7QUFDakI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSx5QkFBeUI7QUFDekI7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYjtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsU0FBUztBQUNUO0FBQ0E7O0FBRUE7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHNFQUFzRTtBQUN0RTtBQUNBO0FBQ0E7QUFDQTtBQUNBLGFBQWEsNENBQTRDLFdBQVc7QUFDcEU7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1Qix1QkFBdUI7QUFDOUMscUNBQXFDLHdCQUF3QjtBQUM3RCxpQkFBaUIsaUNBQWlDLGdCQUFnQixHQUFHO0FBQ3JFLFVBQVU7QUFDVjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQkFBMkI7QUFDM0IseUJBQXlCLHlDQUFZO0FBQ3JDLG9CQUFvQix5Q0FBWTtBQUNoQyx5Q0FBeUMsMkNBQWM7QUFDdkQ7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBLHVCQUF1QjtBQUN2Qix5QkFBeUI7QUFDekIsNEJBQTRCO0FBQzVCLGtDQUFrQztBQUNsQztBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsS0FBSztBQUNMO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxvQkFBb0IsdUJBQXVCO0FBQzNDO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSw4Q0FBOEMsdUJBQXVCO0FBQ3JFO0FBQ0EsU0FBUztBQUNUO0FBQ0E7QUFDQTtBQUNBLFNBQVM7QUFDVDtBQUNBO0FBQ0EsS0FBSztBQUNMLElBQUksNENBQWU7QUFDbkIsSUFBSSw0Q0FBZTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsSUFBSSw0Q0FBZTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBLEtBQUs7QUFDTCxJQUFJLDRDQUFlO0FBQ25CO0FBQ0E7QUFDQTtBQUNBLGFBQWE7QUFDYixLQUFLO0FBQ0wsSUFBSSw0Q0FBZTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsaUJBQWlCO0FBQ2pCO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsSUFBSSw0Q0FBZTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsYUFBYTtBQUNiO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsMENBQTBDLFVBQVU7QUFDcEQ7QUFDQTtBQUNBO0FBQ0E7QUFDQSxLQUFLO0FBQ0wsSUFBSSw0Q0FBZTtBQUNuQjtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQSwyQ0FBMkMsdUJBQXVCO0FBQ2xFO0FBQ0E7QUFDQSxLQUFLO0FBQ0w7QUFDQTtBQUNBOztBQUVBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0E7QUFDQTtBQUNBO0FBQ0EsV0FBVyxVQUFVO0FBQ3JCO0FBQ0E7QUFDQSxjQUFjO0FBQ2QsWUFBWTtBQUNaLGFBQWEsK0JBQStCLEtBQUssS0FBSyxRQUFRO0FBQzlEO0FBQ0E7QUFDQTtBQUNBLGlCQUFpQix5QkFBeUIsdUJBQXVCLHNCQUFzQjs7QUFFb0Y7QUFDM0siLCJzb3VyY2VzIjpbIndlYnBhY2s6Ly9yYW1zZXktcGx1cy1mb3Jtcy8uL25vZGVfbW9kdWxlcy9sb2Rhc2guZGVib3VuY2UvaW5kZXguanMiLCJ3ZWJwYWNrOi8vcmFtc2V5LXBsdXMtZm9ybXMvLi9ub2RlX21vZHVsZXMvcmVhY3QtZG9tL2luZGV4LmpzIiwid2VicGFjazovL3JhbXNleS1wbHVzLWZvcm1zLy4vbm9kZV9tb2R1bGVzL3JlYWN0LXBsYWNlcy1hdXRvY29tcGxldGUvZGlzdC91dGlscy5qcyIsIndlYnBhY2s6Ly9yYW1zZXktcGx1cy1mb3Jtcy8uL25vZGVfbW9kdWxlcy9yZWFjdC1wbGFjZXMtYXV0b2NvbXBsZXRlL2Rpc3QvaW5kZXguanMiLCJ3ZWJwYWNrOi8vcmFtc2V5LXBsdXMtZm9ybXMvLi9ub2RlX21vZHVsZXMvcmVhY3QtcGxhY2VzLWF1dG9jb21wbGV0ZS9kaXN0L2hlbHBlcnMuanMiLCJ3ZWJwYWNrOi8vcmFtc2V5LXBsdXMtZm9ybXMvLi9ub2RlX21vZHVsZXMvY2xzeC9kaXN0L2Nsc3gubWpzIiwid2VicGFjazovL3JhbXNleS1wbHVzLWZvcm1zLy4vbm9kZV9tb2R1bGVzL3JlYWN0L2pzeC1ydW50aW1lLmpzIiwid2VicGFjazovL3JhbXNleS1wbHVzLWZvcm1zLy4vbm9kZV9tb2R1bGVzL0ByYW1zZXktZGVzaWduLXN5c3RlbS9zZWxlY3QvZGlzdC9TZWxlY3QuZXNtLmpzIiwid2VicGFjazovL3JhbXNleS1wbHVzLWZvcm1zLy4vbm9kZV9tb2R1bGVzL3JlYWN0L2luZGV4LmpzIiwid2VicGFjazovL3JhbXNleS1wbHVzLWZvcm1zLy4vbm9kZV9tb2R1bGVzL3JlYWN0LXBsYWNlcy1hdXRvY29tcGxldGUvZGlzdC9QbGFjZXNBdXRvY29tcGxldGUuanMiLCJ3ZWJwYWNrOi8vcmFtc2V5LXBsdXMtZm9ybXMvLi9ub2RlX21vZHVsZXMvdXNlaG9va3MtdHMvZGlzdC9pbmRleC5qcyIsIndlYnBhY2s6Ly9yYW1zZXktcGx1cy1mb3Jtcy8uL25vZGVfbW9kdWxlcy9yZWFjdC9janMvcmVhY3QtanN4LXJ1bnRpbWUucHJvZHVjdGlvbi5qcyIsIndlYnBhY2s6Ly9yYW1zZXktcGx1cy1mb3Jtcy8uL25vZGVfbW9kdWxlcy9yZWFjdC1ob29rLWZvcm0vZGlzdC9pbmRleC5lc20ubWpzIl0sInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogbG9kYXNoIChDdXN0b20gQnVpbGQpIDxodHRwczovL2xvZGFzaC5jb20vPlxuICogQnVpbGQ6IGBsb2Rhc2ggbW9kdWxhcml6ZSBleHBvcnRzPVwibnBtXCIgLW8gLi9gXG4gKiBDb3B5cmlnaHQgalF1ZXJ5IEZvdW5kYXRpb24gYW5kIG90aGVyIGNvbnRyaWJ1dG9ycyA8aHR0cHM6Ly9qcXVlcnkub3JnLz5cbiAqIFJlbGVhc2VkIHVuZGVyIE1JVCBsaWNlbnNlIDxodHRwczovL2xvZGFzaC5jb20vbGljZW5zZT5cbiAqIEJhc2VkIG9uIFVuZGVyc2NvcmUuanMgMS44LjMgPGh0dHA6Ly91bmRlcnNjb3JlanMub3JnL0xJQ0VOU0U+XG4gKiBDb3B5cmlnaHQgSmVyZW15IEFzaGtlbmFzLCBEb2N1bWVudENsb3VkIGFuZCBJbnZlc3RpZ2F0aXZlIFJlcG9ydGVycyAmIEVkaXRvcnNcbiAqL1xuXG4vKiogVXNlZCBhcyB0aGUgYFR5cGVFcnJvcmAgbWVzc2FnZSBmb3IgXCJGdW5jdGlvbnNcIiBtZXRob2RzLiAqL1xudmFyIEZVTkNfRVJST1JfVEVYVCA9ICdFeHBlY3RlZCBhIGZ1bmN0aW9uJztcblxuLyoqIFVzZWQgYXMgcmVmZXJlbmNlcyBmb3IgdmFyaW91cyBgTnVtYmVyYCBjb25zdGFudHMuICovXG52YXIgTkFOID0gMCAvIDA7XG5cbi8qKiBgT2JqZWN0I3RvU3RyaW5nYCByZXN1bHQgcmVmZXJlbmNlcy4gKi9cbnZhciBzeW1ib2xUYWcgPSAnW29iamVjdCBTeW1ib2xdJztcblxuLyoqIFVzZWQgdG8gbWF0Y2ggbGVhZGluZyBhbmQgdHJhaWxpbmcgd2hpdGVzcGFjZS4gKi9cbnZhciByZVRyaW0gPSAvXlxccyt8XFxzKyQvZztcblxuLyoqIFVzZWQgdG8gZGV0ZWN0IGJhZCBzaWduZWQgaGV4YWRlY2ltYWwgc3RyaW5nIHZhbHVlcy4gKi9cbnZhciByZUlzQmFkSGV4ID0gL15bLStdMHhbMC05YS1mXSskL2k7XG5cbi8qKiBVc2VkIHRvIGRldGVjdCBiaW5hcnkgc3RyaW5nIHZhbHVlcy4gKi9cbnZhciByZUlzQmluYXJ5ID0gL14wYlswMV0rJC9pO1xuXG4vKiogVXNlZCB0byBkZXRlY3Qgb2N0YWwgc3RyaW5nIHZhbHVlcy4gKi9cbnZhciByZUlzT2N0YWwgPSAvXjBvWzAtN10rJC9pO1xuXG4vKiogQnVpbHQtaW4gbWV0aG9kIHJlZmVyZW5jZXMgd2l0aG91dCBhIGRlcGVuZGVuY3kgb24gYHJvb3RgLiAqL1xudmFyIGZyZWVQYXJzZUludCA9IHBhcnNlSW50O1xuXG4vKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYGdsb2JhbGAgZnJvbSBOb2RlLmpzLiAqL1xudmFyIGZyZWVHbG9iYWwgPSB0eXBlb2YgZ2xvYmFsID09ICdvYmplY3QnICYmIGdsb2JhbCAmJiBnbG9iYWwuT2JqZWN0ID09PSBPYmplY3QgJiYgZ2xvYmFsO1xuXG4vKiogRGV0ZWN0IGZyZWUgdmFyaWFibGUgYHNlbGZgLiAqL1xudmFyIGZyZWVTZWxmID0gdHlwZW9mIHNlbGYgPT0gJ29iamVjdCcgJiYgc2VsZiAmJiBzZWxmLk9iamVjdCA9PT0gT2JqZWN0ICYmIHNlbGY7XG5cbi8qKiBVc2VkIGFzIGEgcmVmZXJlbmNlIHRvIHRoZSBnbG9iYWwgb2JqZWN0LiAqL1xudmFyIHJvb3QgPSBmcmVlR2xvYmFsIHx8IGZyZWVTZWxmIHx8IEZ1bmN0aW9uKCdyZXR1cm4gdGhpcycpKCk7XG5cbi8qKiBVc2VkIGZvciBidWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcy4gKi9cbnZhciBvYmplY3RQcm90byA9IE9iamVjdC5wcm90b3R5cGU7XG5cbi8qKlxuICogVXNlZCB0byByZXNvbHZlIHRoZVxuICogW2B0b1N0cmluZ1RhZ2BdKGh0dHA6Ly9lY21hLWludGVybmF0aW9uYWwub3JnL2VjbWEtMjYyLzcuMC8jc2VjLW9iamVjdC5wcm90b3R5cGUudG9zdHJpbmcpXG4gKiBvZiB2YWx1ZXMuXG4gKi9cbnZhciBvYmplY3RUb1N0cmluZyA9IG9iamVjdFByb3RvLnRvU3RyaW5nO1xuXG4vKiBCdWlsdC1pbiBtZXRob2QgcmVmZXJlbmNlcyBmb3IgdGhvc2Ugd2l0aCB0aGUgc2FtZSBuYW1lIGFzIG90aGVyIGBsb2Rhc2hgIG1ldGhvZHMuICovXG52YXIgbmF0aXZlTWF4ID0gTWF0aC5tYXgsXG4gICAgbmF0aXZlTWluID0gTWF0aC5taW47XG5cbi8qKlxuICogR2V0cyB0aGUgdGltZXN0YW1wIG9mIHRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRoYXQgaGF2ZSBlbGFwc2VkIHNpbmNlXG4gKiB0aGUgVW5peCBlcG9jaCAoMSBKYW51YXJ5IDE5NzAgMDA6MDA6MDAgVVRDKS5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDIuNC4wXG4gKiBAY2F0ZWdvcnkgRGF0ZVxuICogQHJldHVybnMge251bWJlcn0gUmV0dXJucyB0aGUgdGltZXN0YW1wLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmRlZmVyKGZ1bmN0aW9uKHN0YW1wKSB7XG4gKiAgIGNvbnNvbGUubG9nKF8ubm93KCkgLSBzdGFtcCk7XG4gKiB9LCBfLm5vdygpKTtcbiAqIC8vID0+IExvZ3MgdGhlIG51bWJlciBvZiBtaWxsaXNlY29uZHMgaXQgdG9vayBmb3IgdGhlIGRlZmVycmVkIGludm9jYXRpb24uXG4gKi9cbnZhciBub3cgPSBmdW5jdGlvbigpIHtcbiAgcmV0dXJuIHJvb3QuRGF0ZS5ub3coKTtcbn07XG5cbi8qKlxuICogQ3JlYXRlcyBhIGRlYm91bmNlZCBmdW5jdGlvbiB0aGF0IGRlbGF5cyBpbnZva2luZyBgZnVuY2AgdW50aWwgYWZ0ZXIgYHdhaXRgXG4gKiBtaWxsaXNlY29uZHMgaGF2ZSBlbGFwc2VkIHNpbmNlIHRoZSBsYXN0IHRpbWUgdGhlIGRlYm91bmNlZCBmdW5jdGlvbiB3YXNcbiAqIGludm9rZWQuIFRoZSBkZWJvdW5jZWQgZnVuY3Rpb24gY29tZXMgd2l0aCBhIGBjYW5jZWxgIG1ldGhvZCB0byBjYW5jZWxcbiAqIGRlbGF5ZWQgYGZ1bmNgIGludm9jYXRpb25zIGFuZCBhIGBmbHVzaGAgbWV0aG9kIHRvIGltbWVkaWF0ZWx5IGludm9rZSB0aGVtLlxuICogUHJvdmlkZSBgb3B0aW9uc2AgdG8gaW5kaWNhdGUgd2hldGhlciBgZnVuY2Agc2hvdWxkIGJlIGludm9rZWQgb24gdGhlXG4gKiBsZWFkaW5nIGFuZC9vciB0cmFpbGluZyBlZGdlIG9mIHRoZSBgd2FpdGAgdGltZW91dC4gVGhlIGBmdW5jYCBpcyBpbnZva2VkXG4gKiB3aXRoIHRoZSBsYXN0IGFyZ3VtZW50cyBwcm92aWRlZCB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uLiBTdWJzZXF1ZW50XG4gKiBjYWxscyB0byB0aGUgZGVib3VuY2VkIGZ1bmN0aW9uIHJldHVybiB0aGUgcmVzdWx0IG9mIHRoZSBsYXN0IGBmdW5jYFxuICogaW52b2NhdGlvbi5cbiAqXG4gKiAqKk5vdGU6KiogSWYgYGxlYWRpbmdgIGFuZCBgdHJhaWxpbmdgIG9wdGlvbnMgYXJlIGB0cnVlYCwgYGZ1bmNgIGlzXG4gKiBpbnZva2VkIG9uIHRoZSB0cmFpbGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0IG9ubHkgaWYgdGhlIGRlYm91bmNlZCBmdW5jdGlvblxuICogaXMgaW52b2tlZCBtb3JlIHRoYW4gb25jZSBkdXJpbmcgdGhlIGB3YWl0YCB0aW1lb3V0LlxuICpcbiAqIElmIGB3YWl0YCBpcyBgMGAgYW5kIGBsZWFkaW5nYCBpcyBgZmFsc2VgLCBgZnVuY2AgaW52b2NhdGlvbiBpcyBkZWZlcnJlZFxuICogdW50aWwgdG8gdGhlIG5leHQgdGljaywgc2ltaWxhciB0byBgc2V0VGltZW91dGAgd2l0aCBhIHRpbWVvdXQgb2YgYDBgLlxuICpcbiAqIFNlZSBbRGF2aWQgQ29yYmFjaG8ncyBhcnRpY2xlXShodHRwczovL2Nzcy10cmlja3MuY29tL2RlYm91bmNpbmctdGhyb3R0bGluZy1leHBsYWluZWQtZXhhbXBsZXMvKVxuICogZm9yIGRldGFpbHMgb3ZlciB0aGUgZGlmZmVyZW5jZXMgYmV0d2VlbiBgXy5kZWJvdW5jZWAgYW5kIGBfLnRocm90dGxlYC5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDAuMS4wXG4gKiBAY2F0ZWdvcnkgRnVuY3Rpb25cbiAqIEBwYXJhbSB7RnVuY3Rpb259IGZ1bmMgVGhlIGZ1bmN0aW9uIHRvIGRlYm91bmNlLlxuICogQHBhcmFtIHtudW1iZXJ9IFt3YWl0PTBdIFRoZSBudW1iZXIgb2YgbWlsbGlzZWNvbmRzIHRvIGRlbGF5LlxuICogQHBhcmFtIHtPYmplY3R9IFtvcHRpb25zPXt9XSBUaGUgb3B0aW9ucyBvYmplY3QuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLmxlYWRpbmc9ZmFsc2VdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgbGVhZGluZyBlZGdlIG9mIHRoZSB0aW1lb3V0LlxuICogQHBhcmFtIHtudW1iZXJ9IFtvcHRpb25zLm1heFdhaXRdXG4gKiAgVGhlIG1heGltdW0gdGltZSBgZnVuY2AgaXMgYWxsb3dlZCB0byBiZSBkZWxheWVkIGJlZm9yZSBpdCdzIGludm9rZWQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFtvcHRpb25zLnRyYWlsaW5nPXRydWVdXG4gKiAgU3BlY2lmeSBpbnZva2luZyBvbiB0aGUgdHJhaWxpbmcgZWRnZSBvZiB0aGUgdGltZW91dC5cbiAqIEByZXR1cm5zIHtGdW5jdGlvbn0gUmV0dXJucyB0aGUgbmV3IGRlYm91bmNlZCBmdW5jdGlvbi5cbiAqIEBleGFtcGxlXG4gKlxuICogLy8gQXZvaWQgY29zdGx5IGNhbGN1bGF0aW9ucyB3aGlsZSB0aGUgd2luZG93IHNpemUgaXMgaW4gZmx1eC5cbiAqIGpRdWVyeSh3aW5kb3cpLm9uKCdyZXNpemUnLCBfLmRlYm91bmNlKGNhbGN1bGF0ZUxheW91dCwgMTUwKSk7XG4gKlxuICogLy8gSW52b2tlIGBzZW5kTWFpbGAgd2hlbiBjbGlja2VkLCBkZWJvdW5jaW5nIHN1YnNlcXVlbnQgY2FsbHMuXG4gKiBqUXVlcnkoZWxlbWVudCkub24oJ2NsaWNrJywgXy5kZWJvdW5jZShzZW5kTWFpbCwgMzAwLCB7XG4gKiAgICdsZWFkaW5nJzogdHJ1ZSxcbiAqICAgJ3RyYWlsaW5nJzogZmFsc2VcbiAqIH0pKTtcbiAqXG4gKiAvLyBFbnN1cmUgYGJhdGNoTG9nYCBpcyBpbnZva2VkIG9uY2UgYWZ0ZXIgMSBzZWNvbmQgb2YgZGVib3VuY2VkIGNhbGxzLlxuICogdmFyIGRlYm91bmNlZCA9IF8uZGVib3VuY2UoYmF0Y2hMb2csIDI1MCwgeyAnbWF4V2FpdCc6IDEwMDAgfSk7XG4gKiB2YXIgc291cmNlID0gbmV3IEV2ZW50U291cmNlKCcvc3RyZWFtJyk7XG4gKiBqUXVlcnkoc291cmNlKS5vbignbWVzc2FnZScsIGRlYm91bmNlZCk7XG4gKlxuICogLy8gQ2FuY2VsIHRoZSB0cmFpbGluZyBkZWJvdW5jZWQgaW52b2NhdGlvbi5cbiAqIGpRdWVyeSh3aW5kb3cpLm9uKCdwb3BzdGF0ZScsIGRlYm91bmNlZC5jYW5jZWwpO1xuICovXG5mdW5jdGlvbiBkZWJvdW5jZShmdW5jLCB3YWl0LCBvcHRpb25zKSB7XG4gIHZhciBsYXN0QXJncyxcbiAgICAgIGxhc3RUaGlzLFxuICAgICAgbWF4V2FpdCxcbiAgICAgIHJlc3VsdCxcbiAgICAgIHRpbWVySWQsXG4gICAgICBsYXN0Q2FsbFRpbWUsXG4gICAgICBsYXN0SW52b2tlVGltZSA9IDAsXG4gICAgICBsZWFkaW5nID0gZmFsc2UsXG4gICAgICBtYXhpbmcgPSBmYWxzZSxcbiAgICAgIHRyYWlsaW5nID0gdHJ1ZTtcblxuICBpZiAodHlwZW9mIGZ1bmMgIT0gJ2Z1bmN0aW9uJykge1xuICAgIHRocm93IG5ldyBUeXBlRXJyb3IoRlVOQ19FUlJPUl9URVhUKTtcbiAgfVxuICB3YWl0ID0gdG9OdW1iZXIod2FpdCkgfHwgMDtcbiAgaWYgKGlzT2JqZWN0KG9wdGlvbnMpKSB7XG4gICAgbGVhZGluZyA9ICEhb3B0aW9ucy5sZWFkaW5nO1xuICAgIG1heGluZyA9ICdtYXhXYWl0JyBpbiBvcHRpb25zO1xuICAgIG1heFdhaXQgPSBtYXhpbmcgPyBuYXRpdmVNYXgodG9OdW1iZXIob3B0aW9ucy5tYXhXYWl0KSB8fCAwLCB3YWl0KSA6IG1heFdhaXQ7XG4gICAgdHJhaWxpbmcgPSAndHJhaWxpbmcnIGluIG9wdGlvbnMgPyAhIW9wdGlvbnMudHJhaWxpbmcgOiB0cmFpbGluZztcbiAgfVxuXG4gIGZ1bmN0aW9uIGludm9rZUZ1bmModGltZSkge1xuICAgIHZhciBhcmdzID0gbGFzdEFyZ3MsXG4gICAgICAgIHRoaXNBcmcgPSBsYXN0VGhpcztcblxuICAgIGxhc3RBcmdzID0gbGFzdFRoaXMgPSB1bmRlZmluZWQ7XG4gICAgbGFzdEludm9rZVRpbWUgPSB0aW1lO1xuICAgIHJlc3VsdCA9IGZ1bmMuYXBwbHkodGhpc0FyZywgYXJncyk7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGxlYWRpbmdFZGdlKHRpbWUpIHtcbiAgICAvLyBSZXNldCBhbnkgYG1heFdhaXRgIHRpbWVyLlxuICAgIGxhc3RJbnZva2VUaW1lID0gdGltZTtcbiAgICAvLyBTdGFydCB0aGUgdGltZXIgZm9yIHRoZSB0cmFpbGluZyBlZGdlLlxuICAgIHRpbWVySWQgPSBzZXRUaW1lb3V0KHRpbWVyRXhwaXJlZCwgd2FpdCk7XG4gICAgLy8gSW52b2tlIHRoZSBsZWFkaW5nIGVkZ2UuXG4gICAgcmV0dXJuIGxlYWRpbmcgPyBpbnZva2VGdW5jKHRpbWUpIDogcmVzdWx0O1xuICB9XG5cbiAgZnVuY3Rpb24gcmVtYWluaW5nV2FpdCh0aW1lKSB7XG4gICAgdmFyIHRpbWVTaW5jZUxhc3RDYWxsID0gdGltZSAtIGxhc3RDYWxsVGltZSxcbiAgICAgICAgdGltZVNpbmNlTGFzdEludm9rZSA9IHRpbWUgLSBsYXN0SW52b2tlVGltZSxcbiAgICAgICAgcmVzdWx0ID0gd2FpdCAtIHRpbWVTaW5jZUxhc3RDYWxsO1xuXG4gICAgcmV0dXJuIG1heGluZyA/IG5hdGl2ZU1pbihyZXN1bHQsIG1heFdhaXQgLSB0aW1lU2luY2VMYXN0SW52b2tlKSA6IHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIHNob3VsZEludm9rZSh0aW1lKSB7XG4gICAgdmFyIHRpbWVTaW5jZUxhc3RDYWxsID0gdGltZSAtIGxhc3RDYWxsVGltZSxcbiAgICAgICAgdGltZVNpbmNlTGFzdEludm9rZSA9IHRpbWUgLSBsYXN0SW52b2tlVGltZTtcblxuICAgIC8vIEVpdGhlciB0aGlzIGlzIHRoZSBmaXJzdCBjYWxsLCBhY3Rpdml0eSBoYXMgc3RvcHBlZCBhbmQgd2UncmUgYXQgdGhlXG4gICAgLy8gdHJhaWxpbmcgZWRnZSwgdGhlIHN5c3RlbSB0aW1lIGhhcyBnb25lIGJhY2t3YXJkcyBhbmQgd2UncmUgdHJlYXRpbmdcbiAgICAvLyBpdCBhcyB0aGUgdHJhaWxpbmcgZWRnZSwgb3Igd2UndmUgaGl0IHRoZSBgbWF4V2FpdGAgbGltaXQuXG4gICAgcmV0dXJuIChsYXN0Q2FsbFRpbWUgPT09IHVuZGVmaW5lZCB8fCAodGltZVNpbmNlTGFzdENhbGwgPj0gd2FpdCkgfHxcbiAgICAgICh0aW1lU2luY2VMYXN0Q2FsbCA8IDApIHx8IChtYXhpbmcgJiYgdGltZVNpbmNlTGFzdEludm9rZSA+PSBtYXhXYWl0KSk7XG4gIH1cblxuICBmdW5jdGlvbiB0aW1lckV4cGlyZWQoKSB7XG4gICAgdmFyIHRpbWUgPSBub3coKTtcbiAgICBpZiAoc2hvdWxkSW52b2tlKHRpbWUpKSB7XG4gICAgICByZXR1cm4gdHJhaWxpbmdFZGdlKHRpbWUpO1xuICAgIH1cbiAgICAvLyBSZXN0YXJ0IHRoZSB0aW1lci5cbiAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHJlbWFpbmluZ1dhaXQodGltZSkpO1xuICB9XG5cbiAgZnVuY3Rpb24gdHJhaWxpbmdFZGdlKHRpbWUpIHtcbiAgICB0aW1lcklkID0gdW5kZWZpbmVkO1xuXG4gICAgLy8gT25seSBpbnZva2UgaWYgd2UgaGF2ZSBgbGFzdEFyZ3NgIHdoaWNoIG1lYW5zIGBmdW5jYCBoYXMgYmVlblxuICAgIC8vIGRlYm91bmNlZCBhdCBsZWFzdCBvbmNlLlxuICAgIGlmICh0cmFpbGluZyAmJiBsYXN0QXJncykge1xuICAgICAgcmV0dXJuIGludm9rZUZ1bmModGltZSk7XG4gICAgfVxuICAgIGxhc3RBcmdzID0gbGFzdFRoaXMgPSB1bmRlZmluZWQ7XG4gICAgcmV0dXJuIHJlc3VsdDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGNhbmNlbCgpIHtcbiAgICBpZiAodGltZXJJZCAhPT0gdW5kZWZpbmVkKSB7XG4gICAgICBjbGVhclRpbWVvdXQodGltZXJJZCk7XG4gICAgfVxuICAgIGxhc3RJbnZva2VUaW1lID0gMDtcbiAgICBsYXN0QXJncyA9IGxhc3RDYWxsVGltZSA9IGxhc3RUaGlzID0gdGltZXJJZCA9IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGZ1bmN0aW9uIGZsdXNoKCkge1xuICAgIHJldHVybiB0aW1lcklkID09PSB1bmRlZmluZWQgPyByZXN1bHQgOiB0cmFpbGluZ0VkZ2Uobm93KCkpO1xuICB9XG5cbiAgZnVuY3Rpb24gZGVib3VuY2VkKCkge1xuICAgIHZhciB0aW1lID0gbm93KCksXG4gICAgICAgIGlzSW52b2tpbmcgPSBzaG91bGRJbnZva2UodGltZSk7XG5cbiAgICBsYXN0QXJncyA9IGFyZ3VtZW50cztcbiAgICBsYXN0VGhpcyA9IHRoaXM7XG4gICAgbGFzdENhbGxUaW1lID0gdGltZTtcblxuICAgIGlmIChpc0ludm9raW5nKSB7XG4gICAgICBpZiAodGltZXJJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVybiBsZWFkaW5nRWRnZShsYXN0Q2FsbFRpbWUpO1xuICAgICAgfVxuICAgICAgaWYgKG1heGluZykge1xuICAgICAgICAvLyBIYW5kbGUgaW52b2NhdGlvbnMgaW4gYSB0aWdodCBsb29wLlxuICAgICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgICAgICByZXR1cm4gaW52b2tlRnVuYyhsYXN0Q2FsbFRpbWUpO1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAodGltZXJJZCA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aW1lcklkID0gc2V0VGltZW91dCh0aW1lckV4cGlyZWQsIHdhaXQpO1xuICAgIH1cbiAgICByZXR1cm4gcmVzdWx0O1xuICB9XG4gIGRlYm91bmNlZC5jYW5jZWwgPSBjYW5jZWw7XG4gIGRlYm91bmNlZC5mbHVzaCA9IGZsdXNoO1xuICByZXR1cm4gZGVib3VuY2VkO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiBgdmFsdWVgIGlzIHRoZVxuICogW2xhbmd1YWdlIHR5cGVdKGh0dHA6Ly93d3cuZWNtYS1pbnRlcm5hdGlvbmFsLm9yZy9lY21hLTI2Mi83LjAvI3NlYy1lY21hc2NyaXB0LWxhbmd1YWdlLXR5cGVzKVxuICogb2YgYE9iamVjdGAuIChlLmcuIGFycmF5cywgZnVuY3Rpb25zLCBvYmplY3RzLCByZWdleGVzLCBgbmV3IE51bWJlcigwKWAsIGFuZCBgbmV3IFN0cmluZygnJylgKVxuICpcbiAqIEBzdGF0aWNcbiAqIEBtZW1iZXJPZiBfXG4gKiBAc2luY2UgMC4xLjBcbiAqIEBjYXRlZ29yeSBMYW5nXG4gKiBAcGFyYW0geyp9IHZhbHVlIFRoZSB2YWx1ZSB0byBjaGVjay5cbiAqIEByZXR1cm5zIHtib29sZWFufSBSZXR1cm5zIGB0cnVlYCBpZiBgdmFsdWVgIGlzIGFuIG9iamVjdCwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzT2JqZWN0KHt9KTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0KFsxLCAyLCAzXSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdChfLm5vb3ApO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNPYmplY3QobnVsbCk7XG4gKiAvLyA9PiBmYWxzZVxuICovXG5mdW5jdGlvbiBpc09iamVjdCh2YWx1ZSkge1xuICB2YXIgdHlwZSA9IHR5cGVvZiB2YWx1ZTtcbiAgcmV0dXJuICEhdmFsdWUgJiYgKHR5cGUgPT0gJ29iamVjdCcgfHwgdHlwZSA9PSAnZnVuY3Rpb24nKTtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgYHZhbHVlYCBpcyBvYmplY3QtbGlrZS4gQSB2YWx1ZSBpcyBvYmplY3QtbGlrZSBpZiBpdCdzIG5vdCBgbnVsbGBcbiAqIGFuZCBoYXMgYSBgdHlwZW9mYCByZXN1bHQgb2YgXCJvYmplY3RcIi5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMC4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gY2hlY2suXG4gKiBAcmV0dXJucyB7Ym9vbGVhbn0gUmV0dXJucyBgdHJ1ZWAgaWYgYHZhbHVlYCBpcyBvYmplY3QtbGlrZSwgZWxzZSBgZmFsc2VgLlxuICogQGV4YW1wbGVcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZSh7fSk7XG4gKiAvLyA9PiB0cnVlXG4gKlxuICogXy5pc09iamVjdExpa2UoWzEsIDIsIDNdKTtcbiAqIC8vID0+IHRydWVcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZShfLm5vb3ApO1xuICogLy8gPT4gZmFsc2VcbiAqXG4gKiBfLmlzT2JqZWN0TGlrZShudWxsKTtcbiAqIC8vID0+IGZhbHNlXG4gKi9cbmZ1bmN0aW9uIGlzT2JqZWN0TGlrZSh2YWx1ZSkge1xuICByZXR1cm4gISF2YWx1ZSAmJiB0eXBlb2YgdmFsdWUgPT0gJ29iamVjdCc7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIGB2YWx1ZWAgaXMgY2xhc3NpZmllZCBhcyBhIGBTeW1ib2xgIHByaW1pdGl2ZSBvciBvYmplY3QuXG4gKlxuICogQHN0YXRpY1xuICogQG1lbWJlck9mIF9cbiAqIEBzaW5jZSA0LjAuMFxuICogQGNhdGVnb3J5IExhbmdcbiAqIEBwYXJhbSB7Kn0gdmFsdWUgVGhlIHZhbHVlIHRvIGNoZWNrLlxuICogQHJldHVybnMge2Jvb2xlYW59IFJldHVybnMgYHRydWVgIGlmIGB2YWx1ZWAgaXMgYSBzeW1ib2wsIGVsc2UgYGZhbHNlYC5cbiAqIEBleGFtcGxlXG4gKlxuICogXy5pc1N5bWJvbChTeW1ib2wuaXRlcmF0b3IpO1xuICogLy8gPT4gdHJ1ZVxuICpcbiAqIF8uaXNTeW1ib2woJ2FiYycpO1xuICogLy8gPT4gZmFsc2VcbiAqL1xuZnVuY3Rpb24gaXNTeW1ib2wodmFsdWUpIHtcbiAgcmV0dXJuIHR5cGVvZiB2YWx1ZSA9PSAnc3ltYm9sJyB8fFxuICAgIChpc09iamVjdExpa2UodmFsdWUpICYmIG9iamVjdFRvU3RyaW5nLmNhbGwodmFsdWUpID09IHN5bWJvbFRhZyk7XG59XG5cbi8qKlxuICogQ29udmVydHMgYHZhbHVlYCB0byBhIG51bWJlci5cbiAqXG4gKiBAc3RhdGljXG4gKiBAbWVtYmVyT2YgX1xuICogQHNpbmNlIDQuMC4wXG4gKiBAY2F0ZWdvcnkgTGFuZ1xuICogQHBhcmFtIHsqfSB2YWx1ZSBUaGUgdmFsdWUgdG8gcHJvY2Vzcy5cbiAqIEByZXR1cm5zIHtudW1iZXJ9IFJldHVybnMgdGhlIG51bWJlci5cbiAqIEBleGFtcGxlXG4gKlxuICogXy50b051bWJlcigzLjIpO1xuICogLy8gPT4gMy4yXG4gKlxuICogXy50b051bWJlcihOdW1iZXIuTUlOX1ZBTFVFKTtcbiAqIC8vID0+IDVlLTMyNFxuICpcbiAqIF8udG9OdW1iZXIoSW5maW5pdHkpO1xuICogLy8gPT4gSW5maW5pdHlcbiAqXG4gKiBfLnRvTnVtYmVyKCczLjInKTtcbiAqIC8vID0+IDMuMlxuICovXG5mdW5jdGlvbiB0b051bWJlcih2YWx1ZSkge1xuICBpZiAodHlwZW9mIHZhbHVlID09ICdudW1iZXInKSB7XG4gICAgcmV0dXJuIHZhbHVlO1xuICB9XG4gIGlmIChpc1N5bWJvbCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gTkFOO1xuICB9XG4gIGlmIChpc09iamVjdCh2YWx1ZSkpIHtcbiAgICB2YXIgb3RoZXIgPSB0eXBlb2YgdmFsdWUudmFsdWVPZiA9PSAnZnVuY3Rpb24nID8gdmFsdWUudmFsdWVPZigpIDogdmFsdWU7XG4gICAgdmFsdWUgPSBpc09iamVjdChvdGhlcikgPyAob3RoZXIgKyAnJykgOiBvdGhlcjtcbiAgfVxuICBpZiAodHlwZW9mIHZhbHVlICE9ICdzdHJpbmcnKSB7XG4gICAgcmV0dXJuIHZhbHVlID09PSAwID8gdmFsdWUgOiArdmFsdWU7XG4gIH1cbiAgdmFsdWUgPSB2YWx1ZS5yZXBsYWNlKHJlVHJpbSwgJycpO1xuICB2YXIgaXNCaW5hcnkgPSByZUlzQmluYXJ5LnRlc3QodmFsdWUpO1xuICByZXR1cm4gKGlzQmluYXJ5IHx8IHJlSXNPY3RhbC50ZXN0KHZhbHVlKSlcbiAgICA/IGZyZWVQYXJzZUludCh2YWx1ZS5zbGljZSgyKSwgaXNCaW5hcnkgPyAyIDogOClcbiAgICA6IChyZUlzQmFkSGV4LnRlc3QodmFsdWUpID8gTkFOIDogK3ZhbHVlKTtcbn1cblxubW9kdWxlLmV4cG9ydHMgPSBkZWJvdW5jZTtcbiIsIid1c2Ugc3RyaWN0JztcblxuZnVuY3Rpb24gY2hlY2tEQ0UoKSB7XG4gIC8qIGdsb2JhbCBfX1JFQUNUX0RFVlRPT0xTX0dMT0JBTF9IT09LX18gKi9cbiAgaWYgKFxuICAgIHR5cGVvZiBfX1JFQUNUX0RFVlRPT0xTX0dMT0JBTF9IT09LX18gPT09ICd1bmRlZmluZWQnIHx8XG4gICAgdHlwZW9mIF9fUkVBQ1RfREVWVE9PTFNfR0xPQkFMX0hPT0tfXy5jaGVja0RDRSAhPT0gJ2Z1bmN0aW9uJ1xuICApIHtcbiAgICByZXR1cm47XG4gIH1cbiAgaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WICE9PSAncHJvZHVjdGlvbicpIHtcbiAgICAvLyBUaGlzIGJyYW5jaCBpcyB1bnJlYWNoYWJsZSBiZWNhdXNlIHRoaXMgZnVuY3Rpb24gaXMgb25seSBjYWxsZWRcbiAgICAvLyBpbiBwcm9kdWN0aW9uLCBidXQgdGhlIGNvbmRpdGlvbiBpcyB0cnVlIG9ubHkgaW4gZGV2ZWxvcG1lbnQuXG4gICAgLy8gVGhlcmVmb3JlIGlmIHRoZSBicmFuY2ggaXMgc3RpbGwgaGVyZSwgZGVhZCBjb2RlIGVsaW1pbmF0aW9uIHdhc24ndFxuICAgIC8vIHByb3Blcmx5IGFwcGxpZWQuXG4gICAgLy8gRG9uJ3QgY2hhbmdlIHRoZSBtZXNzYWdlLiBSZWFjdCBEZXZUb29scyByZWxpZXMgb24gaXQuIEFsc28gbWFrZSBzdXJlXG4gICAgLy8gdGhpcyBtZXNzYWdlIGRvZXNuJ3Qgb2NjdXIgZWxzZXdoZXJlIGluIHRoaXMgZnVuY3Rpb24sIG9yIGl0IHdpbGwgY2F1c2VcbiAgICAvLyBhIGZhbHNlIHBvc2l0aXZlLlxuICAgIHRocm93IG5ldyBFcnJvcignXl9eJyk7XG4gIH1cbiAgdHJ5IHtcbiAgICAvLyBWZXJpZnkgdGhhdCB0aGUgY29kZSBhYm92ZSBoYXMgYmVlbiBkZWFkIGNvZGUgZWxpbWluYXRlZCAoRENFJ2QpLlxuICAgIF9fUkVBQ1RfREVWVE9PTFNfR0xPQkFMX0hPT0tfXy5jaGVja0RDRShjaGVja0RDRSk7XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIC8vIERldlRvb2xzIHNob3VsZG4ndCBjcmFzaCBSZWFjdCwgbm8gbWF0dGVyIHdoYXQuXG4gICAgLy8gV2Ugc2hvdWxkIHN0aWxsIHJlcG9ydCBpbiBjYXNlIHdlIGJyZWFrIHRoaXMgY29kZS5cbiAgICBjb25zb2xlLmVycm9yKGVycik7XG4gIH1cbn1cblxuaWYgKHByb2Nlc3MuZW52Lk5PREVfRU5WID09PSAncHJvZHVjdGlvbicpIHtcbiAgLy8gRENFIGNoZWNrIHNob3VsZCBoYXBwZW4gYmVmb3JlIFJlYWN0RE9NIGJ1bmRsZSBleGVjdXRlcyBzbyB0aGF0XG4gIC8vIERldlRvb2xzIGNhbiByZXBvcnQgYmFkIG1pbmlmaWNhdGlvbiBkdXJpbmcgaW5qZWN0aW9uLlxuICBjaGVja0RDRSgpO1xuICBtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vY2pzL3JlYWN0LWRvbS5wcm9kdWN0aW9uLmpzJyk7XG59IGVsc2Uge1xuICBtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vY2pzL3JlYWN0LWRvbS5kZXZlbG9wbWVudC5qcycpO1xufVxuIiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG52YXIgZ2VvY29kZUJ5QWRkcmVzcyA9IGV4cG9ydHMuZ2VvY29kZUJ5QWRkcmVzcyA9IGZ1bmN0aW9uIGdlb2NvZGVCeUFkZHJlc3MoYWRkcmVzcykge1xuICB2YXIgZ2VvY29kZXIgPSBuZXcgd2luZG93Lmdvb2dsZS5tYXBzLkdlb2NvZGVyKCk7XG4gIHZhciBPSyA9IHdpbmRvdy5nb29nbGUubWFwcy5HZW9jb2RlclN0YXR1cy5PSztcblxuICByZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xuICAgIGdlb2NvZGVyLmdlb2NvZGUoeyBhZGRyZXNzOiBhZGRyZXNzIH0sIGZ1bmN0aW9uIChyZXN1bHRzLCBzdGF0dXMpIHtcbiAgICAgIGlmIChzdGF0dXMgIT09IE9LKSB7XG4gICAgICAgIHJlamVjdChzdGF0dXMpO1xuICAgICAgfVxuICAgICAgcmVzb2x2ZShyZXN1bHRzKTtcbiAgICB9KTtcbiAgfSk7XG59O1xuXG52YXIgZ2V0TGF0TG5nID0gZXhwb3J0cy5nZXRMYXRMbmcgPSBmdW5jdGlvbiBnZXRMYXRMbmcocmVzdWx0KSB7XG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgdHJ5IHtcbiAgICAgIHZhciBsYXRMbmcgPSB7XG4gICAgICAgIGxhdDogcmVzdWx0Lmdlb21ldHJ5LmxvY2F0aW9uLmxhdCgpLFxuICAgICAgICBsbmc6IHJlc3VsdC5nZW9tZXRyeS5sb2NhdGlvbi5sbmcoKVxuICAgICAgfTtcbiAgICAgIHJlc29sdmUobGF0TG5nKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICByZWplY3QoZSk7XG4gICAgfVxuICB9KTtcbn07XG5cbnZhciBnZW9jb2RlQnlQbGFjZUlkID0gZXhwb3J0cy5nZW9jb2RlQnlQbGFjZUlkID0gZnVuY3Rpb24gZ2VvY29kZUJ5UGxhY2VJZChwbGFjZUlkKSB7XG4gIHZhciBnZW9jb2RlciA9IG5ldyB3aW5kb3cuZ29vZ2xlLm1hcHMuR2VvY29kZXIoKTtcbiAgdmFyIE9LID0gd2luZG93Lmdvb2dsZS5tYXBzLkdlb2NvZGVyU3RhdHVzLk9LO1xuXG4gIHJldHVybiBuZXcgUHJvbWlzZShmdW5jdGlvbiAocmVzb2x2ZSwgcmVqZWN0KSB7XG4gICAgZ2VvY29kZXIuZ2VvY29kZSh7IHBsYWNlSWQ6IHBsYWNlSWQgfSwgZnVuY3Rpb24gKHJlc3VsdHMsIHN0YXR1cykge1xuICAgICAgaWYgKHN0YXR1cyAhPT0gT0spIHtcbiAgICAgICAgcmVqZWN0KHN0YXR1cyk7XG4gICAgICB9XG4gICAgICByZXNvbHZlKHJlc3VsdHMpO1xuICAgIH0pO1xuICB9KTtcbn07IiwiJ3VzZSBzdHJpY3QnO1xuXG5PYmplY3QuZGVmaW5lUHJvcGVydHkoZXhwb3J0cywgXCJfX2VzTW9kdWxlXCIsIHtcbiAgdmFsdWU6IHRydWVcbn0pO1xuZXhwb3J0cy5nZXRMYXRMbmcgPSBleHBvcnRzLmdlb2NvZGVCeVBsYWNlSWQgPSBleHBvcnRzLmdlb2NvZGVCeUFkZHJlc3MgPSB1bmRlZmluZWQ7XG5cbnZhciBfUGxhY2VzQXV0b2NvbXBsZXRlID0gcmVxdWlyZSgnLi9QbGFjZXNBdXRvY29tcGxldGUnKTtcblxudmFyIF9QbGFjZXNBdXRvY29tcGxldGUyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfUGxhY2VzQXV0b2NvbXBsZXRlKTtcblxudmFyIF91dGlscyA9IHJlcXVpcmUoJy4vdXRpbHMnKTtcblxuZnVuY3Rpb24gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChvYmopIHsgcmV0dXJuIG9iaiAmJiBvYmouX19lc01vZHVsZSA/IG9iaiA6IHsgZGVmYXVsdDogb2JqIH07IH1cblxuZXhwb3J0cy5nZW9jb2RlQnlBZGRyZXNzID0gX3V0aWxzLmdlb2NvZGVCeUFkZHJlc3M7XG5leHBvcnRzLmdlb2NvZGVCeVBsYWNlSWQgPSBfdXRpbHMuZ2VvY29kZUJ5UGxhY2VJZDtcbmV4cG9ydHMuZ2V0TGF0TG5nID0gX3V0aWxzLmdldExhdExuZztcbmV4cG9ydHMuZGVmYXVsdCA9IF9QbGFjZXNBdXRvY29tcGxldGUyLmRlZmF1bHQ7IiwiXCJ1c2Ugc3RyaWN0XCI7XG5cbk9iamVjdC5kZWZpbmVQcm9wZXJ0eShleHBvcnRzLCBcIl9fZXNNb2R1bGVcIiwge1xuICB2YWx1ZTogdHJ1ZVxufSk7XG52YXIgY29tcG9zZSA9IGV4cG9ydHMuY29tcG9zZSA9IGZ1bmN0aW9uIGNvbXBvc2UoKSB7XG4gIGZvciAodmFyIF9sZW4gPSBhcmd1bWVudHMubGVuZ3RoLCBmbnMgPSBBcnJheShfbGVuKSwgX2tleSA9IDA7IF9rZXkgPCBfbGVuOyBfa2V5KyspIHtcbiAgICBmbnNbX2tleV0gPSBhcmd1bWVudHNbX2tleV07XG4gIH1cblxuICByZXR1cm4gZnVuY3Rpb24gKCkge1xuICAgIGZvciAodmFyIF9sZW4yID0gYXJndW1lbnRzLmxlbmd0aCwgYXJncyA9IEFycmF5KF9sZW4yKSwgX2tleTIgPSAwOyBfa2V5MiA8IF9sZW4yOyBfa2V5MisrKSB7XG4gICAgICBhcmdzW19rZXkyXSA9IGFyZ3VtZW50c1tfa2V5Ml07XG4gICAgfVxuXG4gICAgZm5zLmZvckVhY2goZnVuY3Rpb24gKGZuKSB7XG4gICAgICByZXR1cm4gZm4gJiYgZm4uYXBwbHkodW5kZWZpbmVkLCBhcmdzKTtcbiAgICB9KTtcbiAgfTtcbn07XG5cbnZhciBwaWNrID0gZXhwb3J0cy5waWNrID0gZnVuY3Rpb24gcGljayhvYmopIHtcbiAgZm9yICh2YXIgX2xlbjMgPSBhcmd1bWVudHMubGVuZ3RoLCBwcm9wcyA9IEFycmF5KF9sZW4zID4gMSA/IF9sZW4zIC0gMSA6IDApLCBfa2V5MyA9IDE7IF9rZXkzIDwgX2xlbjM7IF9rZXkzKyspIHtcbiAgICBwcm9wc1tfa2V5MyAtIDFdID0gYXJndW1lbnRzW19rZXkzXTtcbiAgfVxuXG4gIHJldHVybiBwcm9wcy5yZWR1Y2UoZnVuY3Rpb24gKG5ld09iaiwgcHJvcCkge1xuICAgIGlmIChvYmogJiYgb2JqLmhhc093blByb3BlcnR5KHByb3ApKSB7XG4gICAgICBuZXdPYmpbcHJvcF0gPSBvYmpbcHJvcF07XG4gICAgfVxuICAgIHJldHVybiBuZXdPYmo7XG4gIH0sIHt9KTtcbn07IiwiZnVuY3Rpb24gcihlKXt2YXIgdCxmLG49XCJcIjtpZihcInN0cmluZ1wiPT10eXBlb2YgZXx8XCJudW1iZXJcIj09dHlwZW9mIGUpbis9ZTtlbHNlIGlmKFwib2JqZWN0XCI9PXR5cGVvZiBlKWlmKEFycmF5LmlzQXJyYXkoZSkpe3ZhciBvPWUubGVuZ3RoO2Zvcih0PTA7dDxvO3QrKyllW3RdJiYoZj1yKGVbdF0pKSYmKG4mJihuKz1cIiBcIiksbis9Zil9ZWxzZSBmb3IoZiBpbiBlKWVbZl0mJihuJiYobis9XCIgXCIpLG4rPWYpO3JldHVybiBufWV4cG9ydCBmdW5jdGlvbiBjbHN4KCl7Zm9yKHZhciBlLHQsZj0wLG49XCJcIixvPWFyZ3VtZW50cy5sZW5ndGg7ZjxvO2YrKykoZT1hcmd1bWVudHNbZl0pJiYodD1yKGUpKSYmKG4mJihuKz1cIiBcIiksbis9dCk7cmV0dXJuIG59ZXhwb3J0IGRlZmF1bHQgY2xzeDsiLCIndXNlIHN0cmljdCc7XG5cbmlmIChwcm9jZXNzLmVudi5OT0RFX0VOViA9PT0gJ3Byb2R1Y3Rpb24nKSB7XG4gIG1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9janMvcmVhY3QtanN4LXJ1bnRpbWUucHJvZHVjdGlvbi5qcycpO1xufSBlbHNlIHtcbiAgbW9kdWxlLmV4cG9ydHMgPSByZXF1aXJlKCcuL2Nqcy9yZWFjdC1qc3gtcnVudGltZS5kZXZlbG9wbWVudC5qcycpO1xufVxuIiwiaW1wb3J0IFJlYWN0LCB7IGZvcndhcmRSZWYgfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgY2xhc3NOYW1lcyBmcm9tICdjbGFzc25hbWVzJztcblxuLyoqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKlxyXG5Db3B5cmlnaHQgKGMpIE1pY3Jvc29mdCBDb3Jwb3JhdGlvbi5cclxuXHJcblBlcm1pc3Npb24gdG8gdXNlLCBjb3B5LCBtb2RpZnksIGFuZC9vciBkaXN0cmlidXRlIHRoaXMgc29mdHdhcmUgZm9yIGFueVxyXG5wdXJwb3NlIHdpdGggb3Igd2l0aG91dCBmZWUgaXMgaGVyZWJ5IGdyYW50ZWQuXHJcblxyXG5USEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiIEFORCBUSEUgQVVUSE9SIERJU0NMQUlNUyBBTEwgV0FSUkFOVElFUyBXSVRIXHJcblJFR0FSRCBUTyBUSElTIFNPRlRXQVJFIElOQ0xVRElORyBBTEwgSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWVxyXG5BTkQgRklUTkVTUy4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUiBCRSBMSUFCTEUgRk9SIEFOWSBTUEVDSUFMLCBESVJFQ1QsXHJcbklORElSRUNULCBPUiBDT05TRVFVRU5USUFMIERBTUFHRVMgT1IgQU5ZIERBTUFHRVMgV0hBVFNPRVZFUiBSRVNVTFRJTkcgRlJPTVxyXG5MT1NTIE9GIFVTRSwgREFUQSBPUiBQUk9GSVRTLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgTkVHTElHRU5DRSBPUlxyXG5PVEhFUiBUT1JUSU9VUyBBQ1RJT04sIEFSSVNJTkcgT1VUIE9GIE9SIElOIENPTk5FQ1RJT04gV0lUSCBUSEUgVVNFIE9SXHJcblBFUkZPUk1BTkNFIE9GIFRISVMgU09GVFdBUkUuXHJcbioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqKioqICovXHJcbi8qIGdsb2JhbCBSZWZsZWN0LCBQcm9taXNlLCBTdXBwcmVzc2VkRXJyb3IsIFN5bWJvbCwgSXRlcmF0b3IgKi9cclxuXHJcblxyXG52YXIgX19hc3NpZ24gPSBmdW5jdGlvbigpIHtcclxuICAgIF9fYXNzaWduID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiBfX2Fzc2lnbih0KSB7XHJcbiAgICAgICAgZm9yICh2YXIgcywgaSA9IDEsIG4gPSBhcmd1bWVudHMubGVuZ3RoOyBpIDwgbjsgaSsrKSB7XHJcbiAgICAgICAgICAgIHMgPSBhcmd1bWVudHNbaV07XHJcbiAgICAgICAgICAgIGZvciAodmFyIHAgaW4gcykgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzLCBwKSkgdFtwXSA9IHNbcF07XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHJldHVybiB0O1xyXG4gICAgfTtcclxuICAgIHJldHVybiBfX2Fzc2lnbi5hcHBseSh0aGlzLCBhcmd1bWVudHMpO1xyXG59O1xyXG5cclxuZnVuY3Rpb24gX19yZXN0KHMsIGUpIHtcclxuICAgIHZhciB0ID0ge307XHJcbiAgICBmb3IgKHZhciBwIGluIHMpIGlmIChPYmplY3QucHJvdG90eXBlLmhhc093blByb3BlcnR5LmNhbGwocywgcCkgJiYgZS5pbmRleE9mKHApIDwgMClcclxuICAgICAgICB0W3BdID0gc1twXTtcclxuICAgIGlmIChzICE9IG51bGwgJiYgdHlwZW9mIE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMgPT09IFwiZnVuY3Rpb25cIilcclxuICAgICAgICBmb3IgKHZhciBpID0gMCwgcCA9IE9iamVjdC5nZXRPd25Qcm9wZXJ0eVN5bWJvbHMocyk7IGkgPCBwLmxlbmd0aDsgaSsrKSB7XHJcbiAgICAgICAgICAgIGlmIChlLmluZGV4T2YocFtpXSkgPCAwICYmIE9iamVjdC5wcm90b3R5cGUucHJvcGVydHlJc0VudW1lcmFibGUuY2FsbChzLCBwW2ldKSlcclxuICAgICAgICAgICAgICAgIHRbcFtpXV0gPSBzW3BbaV1dO1xyXG4gICAgICAgIH1cclxuICAgIHJldHVybiB0O1xyXG59XHJcblxyXG50eXBlb2YgU3VwcHJlc3NlZEVycm9yID09PSBcImZ1bmN0aW9uXCIgPyBTdXBwcmVzc2VkRXJyb3IgOiBmdW5jdGlvbiAoZXJyb3IsIHN1cHByZXNzZWQsIG1lc3NhZ2UpIHtcclxuICAgIHZhciBlID0gbmV3IEVycm9yKG1lc3NhZ2UpO1xyXG4gICAgcmV0dXJuIGUubmFtZSA9IFwiU3VwcHJlc3NlZEVycm9yXCIsIGUuZXJyb3IgPSBlcnJvciwgZS5zdXBwcmVzc2VkID0gc3VwcHJlc3NlZCwgZTtcclxufTtcblxuLyoqXG4gKlxuICogRGVtb3M6XG4gKlxuICogLSBbUkRTIFNlbGVjdF0oaHR0cHM6Ly9kZXNpZ24ucmFtc2V5c29sdXRpb25zLmNvbS9zdG9yeWJvb2svP3BhdGg9L3N0b3J5L2Rlc2lnbi1zeXN0ZW0tc2VsZWN0LS1kZWZhdWx0KVxuICpcbiAqIEFQSTpcbiAqXG4gKiAtIFtSRFMgU2VsZWN0IEFQSV0oaHR0cHM6Ly9kZXNpZ24ucmFtc2V5c29sdXRpb25zLmNvbS9jb21wb25lbnRzL3NlbGVjdC8/dGFiPXRlY2hub2xvZ2llcyNyZWFjdClcbiAqL1xudmFyIFNlbGVjdCA9IGZvcndhcmRSZWYoZnVuY3Rpb24gKF9hLCByZWYpIHtcbiAgICB2YXIgX2I7XG4gICAgdmFyIGNoaWxkcmVuID0gX2EuY2hpbGRyZW4sIGNsYXNzTmFtZSA9IF9hLmNsYXNzTmFtZSwgX2MgPSBfYS5pbnZhbGlkLCBpbnZhbGlkID0gX2MgPT09IHZvaWQgMCA/IGZhbHNlIDogX2MsIF9kID0gX2Euc2l6ZSwgc2l6ZSA9IF9kID09PSB2b2lkIDAgPyBcIm1kXCIgOiBfZCwgcmVzdCA9IF9fcmVzdChfYSwgW1wiY2hpbGRyZW5cIiwgXCJjbGFzc05hbWVcIiwgXCJpbnZhbGlkXCIsIFwic2l6ZVwiXSk7XG4gICAgdmFyIHNlbGVjdENsYXNzTmFtZXMgPSBjbGFzc05hbWVzKFwicmRzLVNlbGVjdFwiLCAoX2IgPSB7fSxcbiAgICAgICAgX2JbXCJyZHMtU2VsZWN0LS1cIi5jb25jYXQoc2l6ZSldID0gc2l6ZSAhPT0gXCJtZFwiLFxuICAgICAgICBfYltcImlzLWludmFsaWRcIl0gPSBpbnZhbGlkLFxuICAgICAgICBfYiksIGNsYXNzTmFtZSk7XG4gICAgdmFyIGNvbmRpdGlvbmFsQXR0cmlidXRlcyA9IHtcbiAgICAgICAgXCJhcmlhLWludmFsaWRcIjogaW52YWxpZCB8fCB1bmRlZmluZWQsXG4gICAgfTtcbiAgICByZXR1cm4gKFJlYWN0LmNyZWF0ZUVsZW1lbnQoXCJzZWxlY3RcIiwgX19hc3NpZ24oeyBjbGFzc05hbWU6IHNlbGVjdENsYXNzTmFtZXMsIHJlZjogcmVmIH0sIGNvbmRpdGlvbmFsQXR0cmlidXRlcywgcmVzdCksIGNoaWxkcmVuKSk7XG59KTtcblNlbGVjdC5kaXNwbGF5TmFtZSA9IFwiU2VsZWN0XCI7XG5cbmV4cG9ydCB7IFNlbGVjdCBhcyBkZWZhdWx0IH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1TZWxlY3QuZXNtLmpzLm1hcFxuIiwiJ3VzZSBzdHJpY3QnO1xuXG5pZiAocHJvY2Vzcy5lbnYuTk9ERV9FTlYgPT09ICdwcm9kdWN0aW9uJykge1xuICBtb2R1bGUuZXhwb3J0cyA9IHJlcXVpcmUoJy4vY2pzL3JlYWN0LnByb2R1Y3Rpb24uanMnKTtcbn0gZWxzZSB7XG4gIG1vZHVsZS5leHBvcnRzID0gcmVxdWlyZSgnLi9janMvcmVhY3QuZGV2ZWxvcG1lbnQuanMnKTtcbn1cbiIsIid1c2Ugc3RyaWN0JztcblxuT2JqZWN0LmRlZmluZVByb3BlcnR5KGV4cG9ydHMsIFwiX19lc01vZHVsZVwiLCB7XG4gIHZhbHVlOiB0cnVlXG59KTtcblxudmFyIF9leHRlbmRzID0gT2JqZWN0LmFzc2lnbiB8fCBmdW5jdGlvbiAodGFyZ2V0KSB7IGZvciAodmFyIGkgPSAxOyBpIDwgYXJndW1lbnRzLmxlbmd0aDsgaSsrKSB7IHZhciBzb3VyY2UgPSBhcmd1bWVudHNbaV07IGZvciAodmFyIGtleSBpbiBzb3VyY2UpIHsgaWYgKE9iamVjdC5wcm90b3R5cGUuaGFzT3duUHJvcGVydHkuY2FsbChzb3VyY2UsIGtleSkpIHsgdGFyZ2V0W2tleV0gPSBzb3VyY2Vba2V5XTsgfSB9IH0gcmV0dXJuIHRhcmdldDsgfTtcblxudmFyIF9jcmVhdGVDbGFzcyA9IGZ1bmN0aW9uICgpIHsgZnVuY3Rpb24gZGVmaW5lUHJvcGVydGllcyh0YXJnZXQsIHByb3BzKSB7IGZvciAodmFyIGkgPSAwOyBpIDwgcHJvcHMubGVuZ3RoOyBpKyspIHsgdmFyIGRlc2NyaXB0b3IgPSBwcm9wc1tpXTsgZGVzY3JpcHRvci5lbnVtZXJhYmxlID0gZGVzY3JpcHRvci5lbnVtZXJhYmxlIHx8IGZhbHNlOyBkZXNjcmlwdG9yLmNvbmZpZ3VyYWJsZSA9IHRydWU7IGlmIChcInZhbHVlXCIgaW4gZGVzY3JpcHRvcikgZGVzY3JpcHRvci53cml0YWJsZSA9IHRydWU7IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh0YXJnZXQsIGRlc2NyaXB0b3Iua2V5LCBkZXNjcmlwdG9yKTsgfSB9IHJldHVybiBmdW5jdGlvbiAoQ29uc3RydWN0b3IsIHByb3RvUHJvcHMsIHN0YXRpY1Byb3BzKSB7IGlmIChwcm90b1Byb3BzKSBkZWZpbmVQcm9wZXJ0aWVzKENvbnN0cnVjdG9yLnByb3RvdHlwZSwgcHJvdG9Qcm9wcyk7IGlmIChzdGF0aWNQcm9wcykgZGVmaW5lUHJvcGVydGllcyhDb25zdHJ1Y3Rvciwgc3RhdGljUHJvcHMpOyByZXR1cm4gQ29uc3RydWN0b3I7IH07IH0oKTtcblxudmFyIF9yZWFjdCA9IHJlcXVpcmUoJ3JlYWN0Jyk7XG5cbnZhciBfcmVhY3QyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcmVhY3QpO1xuXG52YXIgX3Byb3BUeXBlcyA9IHJlcXVpcmUoJ3Byb3AtdHlwZXMnKTtcblxudmFyIF9wcm9wVHlwZXMyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfcHJvcFR5cGVzKTtcblxudmFyIF9sb2Rhc2ggPSByZXF1aXJlKCdsb2Rhc2guZGVib3VuY2UnKTtcblxudmFyIF9sb2Rhc2gyID0gX2ludGVyb3BSZXF1aXJlRGVmYXVsdChfbG9kYXNoKTtcblxudmFyIF9oZWxwZXJzID0gcmVxdWlyZSgnLi9oZWxwZXJzJyk7XG5cbmZ1bmN0aW9uIF9pbnRlcm9wUmVxdWlyZURlZmF1bHQob2JqKSB7IHJldHVybiBvYmogJiYgb2JqLl9fZXNNb2R1bGUgPyBvYmogOiB7IGRlZmF1bHQ6IG9iaiB9OyB9XG5cbmZ1bmN0aW9uIF9jbGFzc0NhbGxDaGVjayhpbnN0YW5jZSwgQ29uc3RydWN0b3IpIHsgaWYgKCEoaW5zdGFuY2UgaW5zdGFuY2VvZiBDb25zdHJ1Y3RvcikpIHsgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbm5vdCBjYWxsIGEgY2xhc3MgYXMgYSBmdW5jdGlvblwiKTsgfSB9XG5cbmZ1bmN0aW9uIF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHNlbGYsIGNhbGwpIHsgaWYgKCFzZWxmKSB7IHRocm93IG5ldyBSZWZlcmVuY2VFcnJvcihcInRoaXMgaGFzbid0IGJlZW4gaW5pdGlhbGlzZWQgLSBzdXBlcigpIGhhc24ndCBiZWVuIGNhbGxlZFwiKTsgfSByZXR1cm4gY2FsbCAmJiAodHlwZW9mIGNhbGwgPT09IFwib2JqZWN0XCIgfHwgdHlwZW9mIGNhbGwgPT09IFwiZnVuY3Rpb25cIikgPyBjYWxsIDogc2VsZjsgfVxuXG5mdW5jdGlvbiBfaW5oZXJpdHMoc3ViQ2xhc3MsIHN1cGVyQ2xhc3MpIHsgaWYgKHR5cGVvZiBzdXBlckNsYXNzICE9PSBcImZ1bmN0aW9uXCIgJiYgc3VwZXJDbGFzcyAhPT0gbnVsbCkgeyB0aHJvdyBuZXcgVHlwZUVycm9yKFwiU3VwZXIgZXhwcmVzc2lvbiBtdXN0IGVpdGhlciBiZSBudWxsIG9yIGEgZnVuY3Rpb24sIG5vdCBcIiArIHR5cGVvZiBzdXBlckNsYXNzKTsgfSBzdWJDbGFzcy5wcm90b3R5cGUgPSBPYmplY3QuY3JlYXRlKHN1cGVyQ2xhc3MgJiYgc3VwZXJDbGFzcy5wcm90b3R5cGUsIHsgY29uc3RydWN0b3I6IHsgdmFsdWU6IHN1YkNsYXNzLCBlbnVtZXJhYmxlOiBmYWxzZSwgd3JpdGFibGU6IHRydWUsIGNvbmZpZ3VyYWJsZTogdHJ1ZSB9IH0pOyBpZiAoc3VwZXJDbGFzcykgT2JqZWN0LnNldFByb3RvdHlwZU9mID8gT2JqZWN0LnNldFByb3RvdHlwZU9mKHN1YkNsYXNzLCBzdXBlckNsYXNzKSA6IHN1YkNsYXNzLl9fcHJvdG9fXyA9IHN1cGVyQ2xhc3M7IH0gLypcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogQ29weXJpZ2h0IChjKSAyMDE2LXByZXNlbnQsIEtlbiBIaWJpbm8uXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqIExpY2Vuc2VkIHVuZGVyIHRoZSBNSVQgTGljZW5zZSAoTUlUKS5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICogU2VlIGh0dHBzOi8va2VubnktaGliaW5vLmdpdGh1Yi5pby9yZWFjdC1wbGFjZXMtYXV0b2NvbXBsZXRlXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAqL1xuXG4vLyB0cmFuc2Zvcm0gc25ha2VfY2FzZSB0byBjYW1lbENhc2VcbnZhciBmb3JtYXR0ZWRTdWdnZXN0aW9uID0gZnVuY3Rpb24gZm9ybWF0dGVkU3VnZ2VzdGlvbihzdHJ1Y3R1cmVkX2Zvcm1hdHRpbmcpIHtcbiAgcmV0dXJuIHtcbiAgICBtYWluVGV4dDogc3RydWN0dXJlZF9mb3JtYXR0aW5nLm1haW5fdGV4dCxcbiAgICBzZWNvbmRhcnlUZXh0OiBzdHJ1Y3R1cmVkX2Zvcm1hdHRpbmcuc2Vjb25kYXJ5X3RleHRcbiAgfTtcbn07XG5cbnZhciBQbGFjZXNBdXRvY29tcGxldGUgPSBmdW5jdGlvbiAoX1JlYWN0JENvbXBvbmVudCkge1xuICBfaW5oZXJpdHMoUGxhY2VzQXV0b2NvbXBsZXRlLCBfUmVhY3QkQ29tcG9uZW50KTtcblxuICBmdW5jdGlvbiBQbGFjZXNBdXRvY29tcGxldGUocHJvcHMpIHtcbiAgICBfY2xhc3NDYWxsQ2hlY2sodGhpcywgUGxhY2VzQXV0b2NvbXBsZXRlKTtcblxuICAgIHZhciBfdGhpcyA9IF9wb3NzaWJsZUNvbnN0cnVjdG9yUmV0dXJuKHRoaXMsIChQbGFjZXNBdXRvY29tcGxldGUuX19wcm90b19fIHx8IE9iamVjdC5nZXRQcm90b3R5cGVPZihQbGFjZXNBdXRvY29tcGxldGUpKS5jYWxsKHRoaXMsIHByb3BzKSk7XG5cbiAgICBfdGhpcy5pbml0ID0gZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKCF3aW5kb3cuZ29vZ2xlKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignW3JlYWN0LXBsYWNlcy1hdXRvY29tcGxldGVdOiBHb29nbGUgTWFwcyBKYXZhU2NyaXB0IEFQSSBsaWJyYXJ5IG11c3QgYmUgbG9hZGVkLiBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9rZW5ueS1oaWJpbm8vcmVhY3QtcGxhY2VzLWF1dG9jb21wbGV0ZSNsb2FkLWdvb2dsZS1saWJyYXJ5Jyk7XG4gICAgICB9XG5cbiAgICAgIGlmICghd2luZG93Lmdvb2dsZS5tYXBzLnBsYWNlcykge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoJ1tyZWFjdC1wbGFjZXMtYXV0b2NvbXBsZXRlXTogR29vZ2xlIE1hcHMgUGxhY2VzIGxpYnJhcnkgbXVzdCBiZSBsb2FkZWQuIFBsZWFzZSBhZGQgYGxpYnJhcmllcz1wbGFjZXNgIHRvIHRoZSBzcmMgVVJMLiBTZWU6IGh0dHBzOi8vZ2l0aHViLmNvbS9rZW5ueS1oaWJpbm8vcmVhY3QtcGxhY2VzLWF1dG9jb21wbGV0ZSNsb2FkLWdvb2dsZS1saWJyYXJ5Jyk7XG4gICAgICB9XG5cbiAgICAgIF90aGlzLmF1dG9jb21wbGV0ZVNlcnZpY2UgPSBuZXcgd2luZG93Lmdvb2dsZS5tYXBzLnBsYWNlcy5BdXRvY29tcGxldGVTZXJ2aWNlKCk7XG4gICAgICBfdGhpcy5hdXRvY29tcGxldGVPSyA9IHdpbmRvdy5nb29nbGUubWFwcy5wbGFjZXMuUGxhY2VzU2VydmljZVN0YXR1cy5PSztcbiAgICAgIF90aGlzLnNldFN0YXRlKGZ1bmN0aW9uIChzdGF0ZSkge1xuICAgICAgICBpZiAoc3RhdGUucmVhZHkpIHtcbiAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4geyByZWFkeTogdHJ1ZSB9O1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgX3RoaXMuYXV0b2NvbXBsZXRlQ2FsbGJhY2sgPSBmdW5jdGlvbiAocHJlZGljdGlvbnMsIHN0YXR1cykge1xuICAgICAgX3RoaXMuc2V0U3RhdGUoeyBsb2FkaW5nOiBmYWxzZSB9KTtcbiAgICAgIGlmIChzdGF0dXMgIT09IF90aGlzLmF1dG9jb21wbGV0ZU9LKSB7XG4gICAgICAgIF90aGlzLnByb3BzLm9uRXJyb3Ioc3RhdHVzLCBfdGhpcy5jbGVhclN1Z2dlc3Rpb25zKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdmFyIGhpZ2hsaWdodEZpcnN0U3VnZ2VzdGlvbiA9IF90aGlzLnByb3BzLmhpZ2hsaWdodEZpcnN0U3VnZ2VzdGlvbjtcblxuICAgICAgX3RoaXMuc2V0U3RhdGUoe1xuICAgICAgICBzdWdnZXN0aW9uczogcHJlZGljdGlvbnMubWFwKGZ1bmN0aW9uIChwLCBpZHgpIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgaWQ6IHAuaWQsXG4gICAgICAgICAgICBkZXNjcmlwdGlvbjogcC5kZXNjcmlwdGlvbixcbiAgICAgICAgICAgIHBsYWNlSWQ6IHAucGxhY2VfaWQsXG4gICAgICAgICAgICBhY3RpdmU6IGhpZ2hsaWdodEZpcnN0U3VnZ2VzdGlvbiAmJiBpZHggPT09IDAgPyB0cnVlIDogZmFsc2UsXG4gICAgICAgICAgICBpbmRleDogaWR4LFxuICAgICAgICAgICAgZm9ybWF0dGVkU3VnZ2VzdGlvbjogZm9ybWF0dGVkU3VnZ2VzdGlvbihwLnN0cnVjdHVyZWRfZm9ybWF0dGluZyksXG4gICAgICAgICAgICBtYXRjaGVkU3Vic3RyaW5nczogcC5tYXRjaGVkX3N1YnN0cmluZ3MsXG4gICAgICAgICAgICB0ZXJtczogcC50ZXJtcyxcbiAgICAgICAgICAgIHR5cGVzOiBwLnR5cGVzXG4gICAgICAgICAgfTtcbiAgICAgICAgfSlcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfdGhpcy5mZXRjaFByZWRpY3Rpb25zID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIHZhbHVlID0gX3RoaXMucHJvcHMudmFsdWU7XG5cbiAgICAgIGlmICh2YWx1ZS5sZW5ndGgpIHtcbiAgICAgICAgX3RoaXMuc2V0U3RhdGUoeyBsb2FkaW5nOiB0cnVlIH0pO1xuICAgICAgICBfdGhpcy5hdXRvY29tcGxldGVTZXJ2aWNlLmdldFBsYWNlUHJlZGljdGlvbnMoX2V4dGVuZHMoe30sIF90aGlzLnByb3BzLnNlYXJjaE9wdGlvbnMsIHtcbiAgICAgICAgICBpbnB1dDogdmFsdWVcbiAgICAgICAgfSksIF90aGlzLmF1dG9jb21wbGV0ZUNhbGxiYWNrKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3RoaXMuY2xlYXJTdWdnZXN0aW9ucyA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIF90aGlzLnNldFN0YXRlKHsgc3VnZ2VzdGlvbnM6IFtdIH0pO1xuICAgIH07XG5cbiAgICBfdGhpcy5jbGVhckFjdGl2ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIF90aGlzLnNldFN0YXRlKHtcbiAgICAgICAgc3VnZ2VzdGlvbnM6IF90aGlzLnN0YXRlLnN1Z2dlc3Rpb25zLm1hcChmdW5jdGlvbiAoc3VnZ2VzdGlvbikge1xuICAgICAgICAgIHJldHVybiBfZXh0ZW5kcyh7fSwgc3VnZ2VzdGlvbiwge1xuICAgICAgICAgICAgYWN0aXZlOiBmYWxzZVxuICAgICAgICAgIH0pO1xuICAgICAgICB9KVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIF90aGlzLmhhbmRsZVNlbGVjdCA9IGZ1bmN0aW9uIChhZGRyZXNzLCBwbGFjZUlkLCBzdWdnZXN0aW9uKSB7XG4gICAgICBfdGhpcy5jbGVhclN1Z2dlc3Rpb25zKCk7XG4gICAgICBpZiAoX3RoaXMucHJvcHMub25TZWxlY3QpIHtcbiAgICAgICAgX3RoaXMucHJvcHMub25TZWxlY3QoYWRkcmVzcywgcGxhY2VJZCwgc3VnZ2VzdGlvbik7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBfdGhpcy5wcm9wcy5vbkNoYW5nZShhZGRyZXNzKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3RoaXMuZ2V0QWN0aXZlU3VnZ2VzdGlvbiA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIHJldHVybiBfdGhpcy5zdGF0ZS5zdWdnZXN0aW9ucy5maW5kKGZ1bmN0aW9uIChzdWdnZXN0aW9uKSB7XG4gICAgICAgIHJldHVybiBzdWdnZXN0aW9uLmFjdGl2ZTtcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfdGhpcy5zZWxlY3RBY3RpdmVBdEluZGV4ID0gZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgICB2YXIgYWN0aXZlTmFtZSA9IF90aGlzLnN0YXRlLnN1Z2dlc3Rpb25zLmZpbmQoZnVuY3Rpb24gKHN1Z2dlc3Rpb24pIHtcbiAgICAgICAgcmV0dXJuIHN1Z2dlc3Rpb24uaW5kZXggPT09IGluZGV4O1xuICAgICAgfSkuZGVzY3JpcHRpb247XG4gICAgICBfdGhpcy5zZXRBY3RpdmVBdEluZGV4KGluZGV4KTtcbiAgICAgIF90aGlzLnByb3BzLm9uQ2hhbmdlKGFjdGl2ZU5hbWUpO1xuICAgIH07XG5cbiAgICBfdGhpcy5zZWxlY3RVc2VySW5wdXRWYWx1ZSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIF90aGlzLmNsZWFyQWN0aXZlKCk7XG4gICAgICBfdGhpcy5wcm9wcy5vbkNoYW5nZShfdGhpcy5zdGF0ZS51c2VySW5wdXRWYWx1ZSk7XG4gICAgfTtcblxuICAgIF90aGlzLmhhbmRsZUVudGVyS2V5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgdmFyIGFjdGl2ZVN1Z2dlc3Rpb24gPSBfdGhpcy5nZXRBY3RpdmVTdWdnZXN0aW9uKCk7XG4gICAgICBpZiAoYWN0aXZlU3VnZ2VzdGlvbiA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIF90aGlzLmhhbmRsZVNlbGVjdChfdGhpcy5wcm9wcy52YWx1ZSwgbnVsbCwgbnVsbCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBfdGhpcy5oYW5kbGVTZWxlY3QoYWN0aXZlU3VnZ2VzdGlvbi5kZXNjcmlwdGlvbiwgYWN0aXZlU3VnZ2VzdGlvbi5wbGFjZUlkLCBhY3RpdmVTdWdnZXN0aW9uKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3RoaXMuaGFuZGxlRG93bktleSA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIGlmIChfdGhpcy5zdGF0ZS5zdWdnZXN0aW9ucy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICB2YXIgYWN0aXZlU3VnZ2VzdGlvbiA9IF90aGlzLmdldEFjdGl2ZVN1Z2dlc3Rpb24oKTtcbiAgICAgIGlmIChhY3RpdmVTdWdnZXN0aW9uID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgX3RoaXMuc2VsZWN0QWN0aXZlQXRJbmRleCgwKTtcbiAgICAgIH0gZWxzZSBpZiAoYWN0aXZlU3VnZ2VzdGlvbi5pbmRleCA9PT0gX3RoaXMuc3RhdGUuc3VnZ2VzdGlvbnMubGVuZ3RoIC0gMSkge1xuICAgICAgICBfdGhpcy5zZWxlY3RVc2VySW5wdXRWYWx1ZSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgX3RoaXMuc2VsZWN0QWN0aXZlQXRJbmRleChhY3RpdmVTdWdnZXN0aW9uLmluZGV4ICsgMSk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIF90aGlzLmhhbmRsZVVwS2V5ID0gZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKF90aGlzLnN0YXRlLnN1Z2dlc3Rpb25zLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIHZhciBhY3RpdmVTdWdnZXN0aW9uID0gX3RoaXMuZ2V0QWN0aXZlU3VnZ2VzdGlvbigpO1xuICAgICAgaWYgKGFjdGl2ZVN1Z2dlc3Rpb24gPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBfdGhpcy5zZWxlY3RBY3RpdmVBdEluZGV4KF90aGlzLnN0YXRlLnN1Z2dlc3Rpb25zLmxlbmd0aCAtIDEpO1xuICAgICAgfSBlbHNlIGlmIChhY3RpdmVTdWdnZXN0aW9uLmluZGV4ID09PSAwKSB7XG4gICAgICAgIF90aGlzLnNlbGVjdFVzZXJJbnB1dFZhbHVlKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBfdGhpcy5zZWxlY3RBY3RpdmVBdEluZGV4KGFjdGl2ZVN1Z2dlc3Rpb24uaW5kZXggLSAxKTtcbiAgICAgIH1cbiAgICB9O1xuXG4gICAgX3RoaXMuaGFuZGxlSW5wdXRLZXlEb3duID0gZnVuY3Rpb24gKGV2ZW50KSB7XG4gICAgICAvKiBlc2xpbnQtZGlzYWJsZSBpbmRlbnQgKi9cbiAgICAgIHN3aXRjaCAoZXZlbnQua2V5KSB7XG4gICAgICAgIGNhc2UgJ0VudGVyJzpcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgIF90aGlzLmhhbmRsZUVudGVyS2V5KCk7XG4gICAgICAgICAgYnJlYWs7XG4gICAgICAgIGNhc2UgJ0Fycm93RG93bic6XG4gICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy8gcHJldmVudCB0aGUgY3Vyc29yIGZyb20gbW92aW5nXG4gICAgICAgICAgX3RoaXMuaGFuZGxlRG93bktleSgpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdBcnJvd1VwJzpcbiAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOyAvLyBwcmV2ZW50IHRoZSBjdXJzb3IgZnJvbSBtb3ZpbmdcbiAgICAgICAgICBfdGhpcy5oYW5kbGVVcEtleSgpO1xuICAgICAgICAgIGJyZWFrO1xuICAgICAgICBjYXNlICdFc2NhcGUnOlxuICAgICAgICAgIF90aGlzLmNsZWFyU3VnZ2VzdGlvbnMoKTtcbiAgICAgICAgICBicmVhaztcbiAgICAgIH1cbiAgICAgIC8qIGVzbGludC1lbmFibGUgaW5kZW50ICovXG4gICAgfTtcblxuICAgIF90aGlzLnNldEFjdGl2ZUF0SW5kZXggPSBmdW5jdGlvbiAoaW5kZXgpIHtcbiAgICAgIF90aGlzLnNldFN0YXRlKHtcbiAgICAgICAgc3VnZ2VzdGlvbnM6IF90aGlzLnN0YXRlLnN1Z2dlc3Rpb25zLm1hcChmdW5jdGlvbiAoc3VnZ2VzdGlvbiwgaWR4KSB7XG4gICAgICAgICAgaWYgKGlkeCA9PT0gaW5kZXgpIHtcbiAgICAgICAgICAgIHJldHVybiBfZXh0ZW5kcyh7fSwgc3VnZ2VzdGlvbiwgeyBhY3RpdmU6IHRydWUgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiBfZXh0ZW5kcyh7fSwgc3VnZ2VzdGlvbiwgeyBhY3RpdmU6IGZhbHNlIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfSlcbiAgICAgIH0pO1xuICAgIH07XG5cbiAgICBfdGhpcy5oYW5kbGVJbnB1dENoYW5nZSA9IGZ1bmN0aW9uIChldmVudCkge1xuICAgICAgdmFyIHZhbHVlID0gZXZlbnQudGFyZ2V0LnZhbHVlO1xuXG4gICAgICBfdGhpcy5wcm9wcy5vbkNoYW5nZSh2YWx1ZSk7XG4gICAgICBfdGhpcy5zZXRTdGF0ZSh7IHVzZXJJbnB1dFZhbHVlOiB2YWx1ZSB9KTtcbiAgICAgIGlmICghdmFsdWUpIHtcbiAgICAgICAgX3RoaXMuY2xlYXJTdWdnZXN0aW9ucygpO1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBpZiAoX3RoaXMucHJvcHMuc2hvdWxkRmV0Y2hTdWdnZXN0aW9ucykge1xuICAgICAgICBfdGhpcy5kZWJvdW5jZWRGZXRjaFByZWRpY3Rpb25zKCk7XG4gICAgICB9XG4gICAgfTtcblxuICAgIF90aGlzLmhhbmRsZUlucHV0T25CbHVyID0gZnVuY3Rpb24gKCkge1xuICAgICAgaWYgKCFfdGhpcy5tb3VzZWRvd25PblN1Z2dlc3Rpb24pIHtcbiAgICAgICAgX3RoaXMuY2xlYXJTdWdnZXN0aW9ucygpO1xuICAgICAgfVxuICAgIH07XG5cbiAgICBfdGhpcy5nZXRBY3RpdmVTdWdnZXN0aW9uSWQgPSBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgYWN0aXZlU3VnZ2VzdGlvbiA9IF90aGlzLmdldEFjdGl2ZVN1Z2dlc3Rpb24oKTtcbiAgICAgIHJldHVybiBhY3RpdmVTdWdnZXN0aW9uID8gJ1BsYWNlc0F1dG9jb21wbGV0ZV9fc3VnZ2VzdGlvbi0nICsgYWN0aXZlU3VnZ2VzdGlvbi5wbGFjZUlkIDogdW5kZWZpbmVkO1xuICAgIH07XG5cbiAgICBfdGhpcy5nZXRJc0V4cGFuZGVkID0gZnVuY3Rpb24gKCkge1xuICAgICAgcmV0dXJuIF90aGlzLnN0YXRlLnN1Z2dlc3Rpb25zLmxlbmd0aCA+IDA7XG4gICAgfTtcblxuICAgIF90aGlzLmdldElucHV0UHJvcHMgPSBmdW5jdGlvbiAoKSB7XG4gICAgICB2YXIgb3B0aW9ucyA9IGFyZ3VtZW50cy5sZW5ndGggPiAwICYmIGFyZ3VtZW50c1swXSAhPT0gdW5kZWZpbmVkID8gYXJndW1lbnRzWzBdIDoge307XG5cbiAgICAgIGlmIChvcHRpb25zLmhhc093blByb3BlcnR5KCd2YWx1ZScpKSB7XG4gICAgICAgIHRocm93IG5ldyBFcnJvcignW3JlYWN0LXBsYWNlcy1hdXRvY29tcGxldGVdOiBnZXRJbnB1dFByb3BzIGRvZXMgbm90IGFjY2VwdCBgdmFsdWVgLiBVc2UgYHZhbHVlYCBwcm9wIGluc3RlYWQnKTtcbiAgICAgIH1cblxuICAgICAgaWYgKG9wdGlvbnMuaGFzT3duUHJvcGVydHkoJ29uQ2hhbmdlJykpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdbcmVhY3QtcGxhY2VzLWF1dG9jb21wbGV0ZV06IGdldElucHV0UHJvcHMgZG9lcyBub3QgYWNjZXB0IGBvbkNoYW5nZWAuIFVzZSBgb25DaGFuZ2VgIHByb3AgaW5zdGVhZCcpO1xuICAgICAgfVxuXG4gICAgICB2YXIgZGVmYXVsdElucHV0UHJvcHMgPSB7XG4gICAgICAgIHR5cGU6ICd0ZXh0JyxcbiAgICAgICAgYXV0b0NvbXBsZXRlOiAnb2ZmJyxcbiAgICAgICAgcm9sZTogJ2NvbWJvYm94JyxcbiAgICAgICAgJ2FyaWEtYXV0b2NvbXBsZXRlJzogJ2xpc3QnLFxuICAgICAgICAnYXJpYS1leHBhbmRlZCc6IF90aGlzLmdldElzRXhwYW5kZWQoKSxcbiAgICAgICAgJ2FyaWEtYWN0aXZlZGVzY2VuZGFudCc6IF90aGlzLmdldEFjdGl2ZVN1Z2dlc3Rpb25JZCgpLFxuICAgICAgICBkaXNhYmxlZDogIV90aGlzLnN0YXRlLnJlYWR5XG4gICAgICB9O1xuXG4gICAgICByZXR1cm4gX2V4dGVuZHMoe30sIGRlZmF1bHRJbnB1dFByb3BzLCBvcHRpb25zLCB7XG4gICAgICAgIG9uS2V5RG93bjogKDAsIF9oZWxwZXJzLmNvbXBvc2UpKF90aGlzLmhhbmRsZUlucHV0S2V5RG93biwgb3B0aW9ucy5vbktleURvd24pLFxuICAgICAgICBvbkJsdXI6ICgwLCBfaGVscGVycy5jb21wb3NlKShfdGhpcy5oYW5kbGVJbnB1dE9uQmx1ciwgb3B0aW9ucy5vbkJsdXIpLFxuICAgICAgICB2YWx1ZTogX3RoaXMucHJvcHMudmFsdWUsXG4gICAgICAgIG9uQ2hhbmdlOiBmdW5jdGlvbiBvbkNoYW5nZShldmVudCkge1xuICAgICAgICAgIF90aGlzLmhhbmRsZUlucHV0Q2hhbmdlKGV2ZW50KTtcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIF90aGlzLmdldFN1Z2dlc3Rpb25JdGVtUHJvcHMgPSBmdW5jdGlvbiAoc3VnZ2VzdGlvbikge1xuICAgICAgdmFyIG9wdGlvbnMgPSBhcmd1bWVudHMubGVuZ3RoID4gMSAmJiBhcmd1bWVudHNbMV0gIT09IHVuZGVmaW5lZCA/IGFyZ3VtZW50c1sxXSA6IHt9O1xuXG4gICAgICB2YXIgaGFuZGxlU3VnZ2VzdGlvbk1vdXNlRW50ZXIgPSBfdGhpcy5oYW5kbGVTdWdnZXN0aW9uTW91c2VFbnRlci5iaW5kKF90aGlzLCBzdWdnZXN0aW9uLmluZGV4KTtcbiAgICAgIHZhciBoYW5kbGVTdWdnZXN0aW9uQ2xpY2sgPSBfdGhpcy5oYW5kbGVTdWdnZXN0aW9uQ2xpY2suYmluZChfdGhpcywgc3VnZ2VzdGlvbik7XG5cbiAgICAgIHJldHVybiBfZXh0ZW5kcyh7fSwgb3B0aW9ucywge1xuICAgICAgICBrZXk6IHN1Z2dlc3Rpb24uaWQsXG4gICAgICAgIGlkOiBfdGhpcy5nZXRBY3RpdmVTdWdnZXN0aW9uSWQoKSxcbiAgICAgICAgcm9sZTogJ29wdGlvbicsXG4gICAgICAgIG9uTW91c2VFbnRlcjogKDAsIF9oZWxwZXJzLmNvbXBvc2UpKGhhbmRsZVN1Z2dlc3Rpb25Nb3VzZUVudGVyLCBvcHRpb25zLm9uTW91c2VFbnRlciksXG4gICAgICAgIG9uTW91c2VMZWF2ZTogKDAsIF9oZWxwZXJzLmNvbXBvc2UpKF90aGlzLmhhbmRsZVN1Z2dlc3Rpb25Nb3VzZUxlYXZlLCBvcHRpb25zLm9uTW91c2VMZWF2ZSksXG4gICAgICAgIG9uTW91c2VEb3duOiAoMCwgX2hlbHBlcnMuY29tcG9zZSkoX3RoaXMuaGFuZGxlU3VnZ2VzdGlvbk1vdXNlRG93biwgb3B0aW9ucy5vbk1vdXNlRG93biksXG4gICAgICAgIG9uTW91c2VVcDogKDAsIF9oZWxwZXJzLmNvbXBvc2UpKF90aGlzLmhhbmRsZVN1Z2dlc3Rpb25Nb3VzZVVwLCBvcHRpb25zLm9uTW91c2VVcCksXG4gICAgICAgIG9uVG91Y2hTdGFydDogKDAsIF9oZWxwZXJzLmNvbXBvc2UpKF90aGlzLmhhbmRsZVN1Z2dlc3Rpb25Ub3VjaFN0YXJ0LCBvcHRpb25zLm9uVG91Y2hTdGFydCksXG4gICAgICAgIG9uVG91Y2hFbmQ6ICgwLCBfaGVscGVycy5jb21wb3NlKShfdGhpcy5oYW5kbGVTdWdnZXN0aW9uTW91c2VVcCwgb3B0aW9ucy5vblRvdWNoRW5kKSxcbiAgICAgICAgb25DbGljazogKDAsIF9oZWxwZXJzLmNvbXBvc2UpKGhhbmRsZVN1Z2dlc3Rpb25DbGljaywgb3B0aW9ucy5vbkNsaWNrKVxuICAgICAgfSk7XG4gICAgfTtcblxuICAgIF90aGlzLmhhbmRsZVN1Z2dlc3Rpb25Nb3VzZUVudGVyID0gZnVuY3Rpb24gKGluZGV4KSB7XG4gICAgICBfdGhpcy5zZXRBY3RpdmVBdEluZGV4KGluZGV4KTtcbiAgICB9O1xuXG4gICAgX3RoaXMuaGFuZGxlU3VnZ2VzdGlvbk1vdXNlTGVhdmUgPSBmdW5jdGlvbiAoKSB7XG4gICAgICBfdGhpcy5tb3VzZWRvd25PblN1Z2dlc3Rpb24gPSBmYWxzZTtcbiAgICAgIF90aGlzLmNsZWFyQWN0aXZlKCk7XG4gICAgfTtcblxuICAgIF90aGlzLmhhbmRsZVN1Z2dlc3Rpb25Nb3VzZURvd24gPSBmdW5jdGlvbiAoZXZlbnQpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICBfdGhpcy5tb3VzZWRvd25PblN1Z2dlc3Rpb24gPSB0cnVlO1xuICAgIH07XG5cbiAgICBfdGhpcy5oYW5kbGVTdWdnZXN0aW9uVG91Y2hTdGFydCA9IGZ1bmN0aW9uICgpIHtcbiAgICAgIF90aGlzLm1vdXNlZG93bk9uU3VnZ2VzdGlvbiA9IHRydWU7XG4gICAgfTtcblxuICAgIF90aGlzLmhhbmRsZVN1Z2dlc3Rpb25Nb3VzZVVwID0gZnVuY3Rpb24gKCkge1xuICAgICAgX3RoaXMubW91c2Vkb3duT25TdWdnZXN0aW9uID0gZmFsc2U7XG4gICAgfTtcblxuICAgIF90aGlzLmhhbmRsZVN1Z2dlc3Rpb25DbGljayA9IGZ1bmN0aW9uIChzdWdnZXN0aW9uLCBldmVudCkge1xuICAgICAgaWYgKGV2ZW50ICYmIGV2ZW50LnByZXZlbnREZWZhdWx0KSB7XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICB9XG4gICAgICB2YXIgZGVzY3JpcHRpb24gPSBzdWdnZXN0aW9uLmRlc2NyaXB0aW9uLFxuICAgICAgICAgIHBsYWNlSWQgPSBzdWdnZXN0aW9uLnBsYWNlSWQ7XG5cbiAgICAgIF90aGlzLmhhbmRsZVNlbGVjdChkZXNjcmlwdGlvbiwgcGxhY2VJZCwgc3VnZ2VzdGlvbik7XG4gICAgICBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgX3RoaXMubW91c2Vkb3duT25TdWdnZXN0aW9uID0gZmFsc2U7XG4gICAgICB9KTtcbiAgICB9O1xuXG4gICAgX3RoaXMuc3RhdGUgPSB7XG4gICAgICBsb2FkaW5nOiBmYWxzZSxcbiAgICAgIHN1Z2dlc3Rpb25zOiBbXSxcbiAgICAgIHVzZXJJbnB1dFZhbHVlOiBwcm9wcy52YWx1ZSxcbiAgICAgIHJlYWR5OiAhcHJvcHMuZ29vZ2xlQ2FsbGJhY2tOYW1lXG4gICAgfTtcblxuICAgIF90aGlzLmRlYm91bmNlZEZldGNoUHJlZGljdGlvbnMgPSAoMCwgX2xvZGFzaDIuZGVmYXVsdCkoX3RoaXMuZmV0Y2hQcmVkaWN0aW9ucywgcHJvcHMuZGVib3VuY2UpO1xuICAgIHJldHVybiBfdGhpcztcbiAgfVxuXG4gIF9jcmVhdGVDbGFzcyhQbGFjZXNBdXRvY29tcGxldGUsIFt7XG4gICAga2V5OiAnY29tcG9uZW50RGlkTW91bnQnLFxuICAgIHZhbHVlOiBmdW5jdGlvbiBjb21wb25lbnREaWRNb3VudCgpIHtcbiAgICAgIHZhciBnb29nbGVDYWxsYmFja05hbWUgPSB0aGlzLnByb3BzLmdvb2dsZUNhbGxiYWNrTmFtZTtcblxuICAgICAgaWYgKGdvb2dsZUNhbGxiYWNrTmFtZSkge1xuICAgICAgICB2YXIgaXNQbGFjZXNMb2FkZWQgPSB3aW5kb3cuZ29vZ2xlICYmIHdpbmRvdy5nb29nbGUubWFwcyAmJiB3aW5kb3cuZ29vZ2xlLm1hcHMucGxhY2VzO1xuICAgICAgICBpZiAoIWlzUGxhY2VzTG9hZGVkKSB7XG4gICAgICAgICAgd2luZG93W2dvb2dsZUNhbGxiYWNrTmFtZV0gPSB0aGlzLmluaXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5pbml0KCk7XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRoaXMuaW5pdCgpO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ2NvbXBvbmVudFdpbGxVbm1vdW50JyxcbiAgICB2YWx1ZTogZnVuY3Rpb24gY29tcG9uZW50V2lsbFVubW91bnQoKSB7XG4gICAgICB2YXIgZ29vZ2xlQ2FsbGJhY2tOYW1lID0gdGhpcy5wcm9wcy5nb29nbGVDYWxsYmFja05hbWU7XG5cbiAgICAgIGlmIChnb29nbGVDYWxsYmFja05hbWUgJiYgd2luZG93W2dvb2dsZUNhbGxiYWNrTmFtZV0pIHtcbiAgICAgICAgZGVsZXRlIHdpbmRvd1tnb29nbGVDYWxsYmFja05hbWVdO1xuICAgICAgfVxuICAgIH1cbiAgfSwge1xuICAgIGtleTogJ3JlbmRlcicsXG4gICAgdmFsdWU6IGZ1bmN0aW9uIHJlbmRlcigpIHtcbiAgICAgIHJldHVybiB0aGlzLnByb3BzLmNoaWxkcmVuKHtcbiAgICAgICAgZ2V0SW5wdXRQcm9wczogdGhpcy5nZXRJbnB1dFByb3BzLFxuICAgICAgICBnZXRTdWdnZXN0aW9uSXRlbVByb3BzOiB0aGlzLmdldFN1Z2dlc3Rpb25JdGVtUHJvcHMsXG4gICAgICAgIGxvYWRpbmc6IHRoaXMuc3RhdGUubG9hZGluZyxcbiAgICAgICAgc3VnZ2VzdGlvbnM6IHRoaXMuc3RhdGUuc3VnZ2VzdGlvbnNcbiAgICAgIH0pO1xuICAgIH1cbiAgfV0pO1xuXG4gIHJldHVybiBQbGFjZXNBdXRvY29tcGxldGU7XG59KF9yZWFjdDIuZGVmYXVsdC5Db21wb25lbnQpO1xuXG5QbGFjZXNBdXRvY29tcGxldGUucHJvcFR5cGVzID0ge1xuICBvbkNoYW5nZTogX3Byb3BUeXBlczIuZGVmYXVsdC5mdW5jLmlzUmVxdWlyZWQsXG4gIHZhbHVlOiBfcHJvcFR5cGVzMi5kZWZhdWx0LnN0cmluZy5pc1JlcXVpcmVkLFxuICBjaGlsZHJlbjogX3Byb3BUeXBlczIuZGVmYXVsdC5mdW5jLmlzUmVxdWlyZWQsXG4gIG9uRXJyb3I6IF9wcm9wVHlwZXMyLmRlZmF1bHQuZnVuYyxcbiAgb25TZWxlY3Q6IF9wcm9wVHlwZXMyLmRlZmF1bHQuZnVuYyxcbiAgc2VhcmNoT3B0aW9uczogX3Byb3BUeXBlczIuZGVmYXVsdC5zaGFwZSh7XG4gICAgYm91bmRzOiBfcHJvcFR5cGVzMi5kZWZhdWx0Lm9iamVjdCxcbiAgICBjb21wb25lbnRSZXN0cmljdGlvbnM6IF9wcm9wVHlwZXMyLmRlZmF1bHQub2JqZWN0LFxuICAgIGxvY2F0aW9uOiBfcHJvcFR5cGVzMi5kZWZhdWx0Lm9iamVjdCxcbiAgICBvZmZzZXQ6IF9wcm9wVHlwZXMyLmRlZmF1bHQub25lT2ZUeXBlKFtfcHJvcFR5cGVzMi5kZWZhdWx0Lm51bWJlciwgX3Byb3BUeXBlczIuZGVmYXVsdC5zdHJpbmddKSxcbiAgICByYWRpdXM6IF9wcm9wVHlwZXMyLmRlZmF1bHQub25lT2ZUeXBlKFtfcHJvcFR5cGVzMi5kZWZhdWx0Lm51bWJlciwgX3Byb3BUeXBlczIuZGVmYXVsdC5zdHJpbmddKSxcbiAgICB0eXBlczogX3Byb3BUeXBlczIuZGVmYXVsdC5hcnJheVxuICB9KSxcbiAgZGVib3VuY2U6IF9wcm9wVHlwZXMyLmRlZmF1bHQubnVtYmVyLFxuICBoaWdobGlnaHRGaXJzdFN1Z2dlc3Rpb246IF9wcm9wVHlwZXMyLmRlZmF1bHQuYm9vbCxcbiAgc2hvdWxkRmV0Y2hTdWdnZXN0aW9uczogX3Byb3BUeXBlczIuZGVmYXVsdC5ib29sLFxuICBnb29nbGVDYWxsYmFja05hbWU6IF9wcm9wVHlwZXMyLmRlZmF1bHQuc3RyaW5nXG59O1xuXG5QbGFjZXNBdXRvY29tcGxldGUuZGVmYXVsdFByb3BzID0ge1xuICAvKiBlc2xpbnQtZGlzYWJsZSBuby11bnVzZWQtdmFycywgbm8tY29uc29sZSAqL1xuICBvbkVycm9yOiBmdW5jdGlvbiBvbkVycm9yKHN0YXR1cywgX2NsZWFyU3VnZ2VzdGlvbnMpIHtcbiAgICByZXR1cm4gY29uc29sZS5lcnJvcignW3JlYWN0LXBsYWNlcy1hdXRvY29tcGxldGVdOiBlcnJvciBoYXBwZW5lZCB3aGVuIGZldGNoaW5nIGRhdGEgZnJvbSBHb29nbGUgTWFwcyBBUEkuXFxuUGxlYXNlIGNoZWNrIHRoZSBkb2NzIGhlcmUgKGh0dHBzOi8vZGV2ZWxvcGVycy5nb29nbGUuY29tL21hcHMvZG9jdW1lbnRhdGlvbi9qYXZhc2NyaXB0L3BsYWNlcyNwbGFjZV9kZXRhaWxzX3Jlc3BvbnNlcylcXG5TdGF0dXM6ICcsIHN0YXR1cyk7XG4gIH0sXG4gIC8qIGVzbGludC1lbmFibGUgbm8tdW51c2VkLXZhcnMsIG5vLWNvbnNvbGUgKi9cbiAgc2VhcmNoT3B0aW9uczoge30sXG4gIGRlYm91bmNlOiAyMDAsXG4gIGhpZ2hsaWdodEZpcnN0U3VnZ2VzdGlvbjogZmFsc2UsXG4gIHNob3VsZEZldGNoU3VnZ2VzdGlvbnM6IHRydWVcbn07XG5cbmV4cG9ydHMuZGVmYXVsdCA9IFBsYWNlc0F1dG9jb21wbGV0ZTsiLCJpbXBvcnQgeyB1c2VTdGF0ZSwgdXNlQ2FsbGJhY2ssIHVzZUxheW91dEVmZmVjdCwgdXNlRWZmZWN0LCB1c2VSZWYsIHVzZU1lbW8gfSBmcm9tICdyZWFjdCc7XG5pbXBvcnQgZGVib3VuY2UgZnJvbSAnbG9kYXNoLmRlYm91bmNlJztcblxuLy8gc3JjL3VzZUJvb2xlYW4vdXNlQm9vbGVhbi50c1xuZnVuY3Rpb24gdXNlQm9vbGVhbihkZWZhdWx0VmFsdWUgPSBmYWxzZSkge1xuICBpZiAodHlwZW9mIGRlZmF1bHRWYWx1ZSAhPT0gXCJib29sZWFuXCIpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXCJkZWZhdWx0VmFsdWUgbXVzdCBiZSBgdHJ1ZWAgb3IgYGZhbHNlYFwiKTtcbiAgfVxuICBjb25zdCBbdmFsdWUsIHNldFZhbHVlXSA9IHVzZVN0YXRlKGRlZmF1bHRWYWx1ZSk7XG4gIGNvbnN0IHNldFRydWUgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgc2V0VmFsdWUodHJ1ZSk7XG4gIH0sIFtdKTtcbiAgY29uc3Qgc2V0RmFsc2UgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgc2V0VmFsdWUoZmFsc2UpO1xuICB9LCBbXSk7XG4gIGNvbnN0IHRvZ2dsZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICBzZXRWYWx1ZSgoeCkgPT4gIXgpO1xuICB9LCBbXSk7XG4gIHJldHVybiB7IHZhbHVlLCBzZXRWYWx1ZSwgc2V0VHJ1ZSwgc2V0RmFsc2UsIHRvZ2dsZSB9O1xufVxudmFyIHVzZUlzb21vcnBoaWNMYXlvdXRFZmZlY3QgPSB0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiID8gdXNlTGF5b3V0RWZmZWN0IDogdXNlRWZmZWN0O1xuXG4vLyBzcmMvdXNlRXZlbnRMaXN0ZW5lci91c2VFdmVudExpc3RlbmVyLnRzXG5mdW5jdGlvbiB1c2VFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgaGFuZGxlciwgZWxlbWVudCwgb3B0aW9ucykge1xuICBjb25zdCBzYXZlZEhhbmRsZXIgPSB1c2VSZWYoaGFuZGxlcik7XG4gIHVzZUlzb21vcnBoaWNMYXlvdXRFZmZlY3QoKCkgPT4ge1xuICAgIHNhdmVkSGFuZGxlci5jdXJyZW50ID0gaGFuZGxlcjtcbiAgfSwgW2hhbmRsZXJdKTtcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCB0YXJnZXRFbGVtZW50ID0gKGVsZW1lbnQgPT0gbnVsbCA/IHZvaWQgMCA6IGVsZW1lbnQuY3VycmVudCkgPz8gd2luZG93O1xuICAgIGlmICghKHRhcmdldEVsZW1lbnQgJiYgdGFyZ2V0RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKSlcbiAgICAgIHJldHVybjtcbiAgICBjb25zdCBsaXN0ZW5lciA9IChldmVudCkgPT4ge1xuICAgICAgc2F2ZWRIYW5kbGVyLmN1cnJlbnQoZXZlbnQpO1xuICAgIH07XG4gICAgdGFyZ2V0RWxlbWVudC5hZGRFdmVudExpc3RlbmVyKGV2ZW50TmFtZSwgbGlzdGVuZXIsIG9wdGlvbnMpO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICB0YXJnZXRFbGVtZW50LnJlbW92ZUV2ZW50TGlzdGVuZXIoZXZlbnROYW1lLCBsaXN0ZW5lciwgb3B0aW9ucyk7XG4gICAgfTtcbiAgfSwgW2V2ZW50TmFtZSwgZWxlbWVudCwgb3B0aW9uc10pO1xufVxuXG4vLyBzcmMvdXNlQ2xpY2tBbnlXaGVyZS91c2VDbGlja0FueVdoZXJlLnRzXG5mdW5jdGlvbiB1c2VDbGlja0FueVdoZXJlKGhhbmRsZXIpIHtcbiAgdXNlRXZlbnRMaXN0ZW5lcihcImNsaWNrXCIsIChldmVudCkgPT4ge1xuICAgIGhhbmRsZXIoZXZlbnQpO1xuICB9KTtcbn1cbmZ1bmN0aW9uIHVzZUNvcHlUb0NsaXBib2FyZCgpIHtcbiAgY29uc3QgW2NvcGllZFRleHQsIHNldENvcGllZFRleHRdID0gdXNlU3RhdGUobnVsbCk7XG4gIGNvbnN0IGNvcHkgPSB1c2VDYWxsYmFjayhhc3luYyAodGV4dCkgPT4ge1xuICAgIGlmICghKG5hdmlnYXRvciA9PSBudWxsID8gdm9pZCAwIDogbmF2aWdhdG9yLmNsaXBib2FyZCkpIHtcbiAgICAgIGNvbnNvbGUud2FybihcIkNsaXBib2FyZCBub3Qgc3VwcG9ydGVkXCIpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbiAgICB0cnkge1xuICAgICAgYXdhaXQgbmF2aWdhdG9yLmNsaXBib2FyZC53cml0ZVRleHQodGV4dCk7XG4gICAgICBzZXRDb3BpZWRUZXh0KHRleHQpO1xuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUud2FybihcIkNvcHkgZmFpbGVkXCIsIGVycm9yKTtcbiAgICAgIHNldENvcGllZFRleHQobnVsbCk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICB9LCBbXSk7XG4gIHJldHVybiBbY29waWVkVGV4dCwgY29weV07XG59XG5mdW5jdGlvbiB1c2VDb3VudGVyKGluaXRpYWxWYWx1ZSkge1xuICBjb25zdCBbY291bnQsIHNldENvdW50XSA9IHVzZVN0YXRlKGluaXRpYWxWYWx1ZSA/PyAwKTtcbiAgY29uc3QgaW5jcmVtZW50ID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIHNldENvdW50KCh4KSA9PiB4ICsgMSk7XG4gIH0sIFtdKTtcbiAgY29uc3QgZGVjcmVtZW50ID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIHNldENvdW50KCh4KSA9PiB4IC0gMSk7XG4gIH0sIFtdKTtcbiAgY29uc3QgcmVzZXQgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgc2V0Q291bnQoaW5pdGlhbFZhbHVlID8/IDApO1xuICB9LCBbaW5pdGlhbFZhbHVlXSk7XG4gIHJldHVybiB7XG4gICAgY291bnQsXG4gICAgaW5jcmVtZW50LFxuICAgIGRlY3JlbWVudCxcbiAgICByZXNldCxcbiAgICBzZXRDb3VudFxuICB9O1xufVxuZnVuY3Rpb24gdXNlSW50ZXJ2YWwoY2FsbGJhY2ssIGRlbGF5KSB7XG4gIGNvbnN0IHNhdmVkQ2FsbGJhY2sgPSB1c2VSZWYoY2FsbGJhY2spO1xuICB1c2VJc29tb3JwaGljTGF5b3V0RWZmZWN0KCgpID0+IHtcbiAgICBzYXZlZENhbGxiYWNrLmN1cnJlbnQgPSBjYWxsYmFjaztcbiAgfSwgW2NhbGxiYWNrXSk7XG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKGRlbGF5ID09PSBudWxsKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGlkID0gc2V0SW50ZXJ2YWwoKCkgPT4ge1xuICAgICAgc2F2ZWRDYWxsYmFjay5jdXJyZW50KCk7XG4gICAgfSwgZGVsYXkpO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBjbGVhckludGVydmFsKGlkKTtcbiAgICB9O1xuICB9LCBbZGVsYXldKTtcbn1cblxuLy8gc3JjL3VzZUNvdW50ZG93bi91c2VDb3VudGRvd24udHNcbmZ1bmN0aW9uIHVzZUNvdW50ZG93bih7XG4gIGNvdW50U3RhcnQsXG4gIGNvdW50U3RvcCA9IDAsXG4gIGludGVydmFsTXMgPSAxZTMsXG4gIGlzSW5jcmVtZW50ID0gZmFsc2Vcbn0pIHtcbiAgY29uc3Qge1xuICAgIGNvdW50LFxuICAgIGluY3JlbWVudCxcbiAgICBkZWNyZW1lbnQsXG4gICAgcmVzZXQ6IHJlc2V0Q291bnRlclxuICB9ID0gdXNlQ291bnRlcihjb3VudFN0YXJ0KTtcbiAgY29uc3Qge1xuICAgIHZhbHVlOiBpc0NvdW50ZG93blJ1bm5pbmcsXG4gICAgc2V0VHJ1ZTogc3RhcnRDb3VudGRvd24sXG4gICAgc2V0RmFsc2U6IHN0b3BDb3VudGRvd25cbiAgfSA9IHVzZUJvb2xlYW4oZmFsc2UpO1xuICBjb25zdCByZXNldENvdW50ZG93biA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICBzdG9wQ291bnRkb3duKCk7XG4gICAgcmVzZXRDb3VudGVyKCk7XG4gIH0sIFtzdG9wQ291bnRkb3duLCByZXNldENvdW50ZXJdKTtcbiAgY29uc3QgY291bnRkb3duQ2FsbGJhY2sgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgaWYgKGNvdW50ID09PSBjb3VudFN0b3ApIHtcbiAgICAgIHN0b3BDb3VudGRvd24oKTtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgaWYgKGlzSW5jcmVtZW50KSB7XG4gICAgICBpbmNyZW1lbnQoKTtcbiAgICB9IGVsc2Uge1xuICAgICAgZGVjcmVtZW50KCk7XG4gICAgfVxuICB9LCBbY291bnQsIGNvdW50U3RvcCwgZGVjcmVtZW50LCBpbmNyZW1lbnQsIGlzSW5jcmVtZW50LCBzdG9wQ291bnRkb3duXSk7XG4gIHVzZUludGVydmFsKGNvdW50ZG93bkNhbGxiYWNrLCBpc0NvdW50ZG93blJ1bm5pbmcgPyBpbnRlcnZhbE1zIDogbnVsbCk7XG4gIHJldHVybiBbY291bnQsIHsgc3RhcnRDb3VudGRvd24sIHN0b3BDb3VudGRvd24sIHJlc2V0Q291bnRkb3duIH1dO1xufVxuZnVuY3Rpb24gdXNlRXZlbnRDYWxsYmFjayhmbikge1xuICBjb25zdCByZWYgPSB1c2VSZWYoKCkgPT4ge1xuICAgIHRocm93IG5ldyBFcnJvcihcIkNhbm5vdCBjYWxsIGFuIGV2ZW50IGhhbmRsZXIgd2hpbGUgcmVuZGVyaW5nLlwiKTtcbiAgfSk7XG4gIHVzZUlzb21vcnBoaWNMYXlvdXRFZmZlY3QoKCkgPT4ge1xuICAgIHJlZi5jdXJyZW50ID0gZm47XG4gIH0sIFtmbl0pO1xuICByZXR1cm4gdXNlQ2FsbGJhY2soKC4uLmFyZ3MpID0+IHtcbiAgICB2YXIgX2E7XG4gICAgcmV0dXJuIChfYSA9IHJlZi5jdXJyZW50KSA9PSBudWxsID8gdm9pZCAwIDogX2EuY2FsbChyZWYsIC4uLmFyZ3MpO1xuICB9LCBbcmVmXSk7XG59XG5cbi8vIHNyYy91c2VMb2NhbFN0b3JhZ2UvdXNlTG9jYWxTdG9yYWdlLnRzXG52YXIgSVNfU0VSVkVSID0gdHlwZW9mIHdpbmRvdyA9PT0gXCJ1bmRlZmluZWRcIjtcbmZ1bmN0aW9uIHVzZUxvY2FsU3RvcmFnZShrZXksIGluaXRpYWxWYWx1ZSwgb3B0aW9ucyA9IHt9KSB7XG4gIGNvbnN0IHsgaW5pdGlhbGl6ZVdpdGhWYWx1ZSA9IHRydWUgfSA9IG9wdGlvbnM7XG4gIGNvbnN0IHNlcmlhbGl6ZXIgPSB1c2VDYWxsYmFjayhcbiAgICAodmFsdWUpID0+IHtcbiAgICAgIGlmIChvcHRpb25zLnNlcmlhbGl6ZXIpIHtcbiAgICAgICAgcmV0dXJuIG9wdGlvbnMuc2VyaWFsaXplcih2YWx1ZSk7XG4gICAgICB9XG4gICAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkodmFsdWUpO1xuICAgIH0sXG4gICAgW29wdGlvbnNdXG4gICk7XG4gIGNvbnN0IGRlc2VyaWFsaXplciA9IHVzZUNhbGxiYWNrKFxuICAgICh2YWx1ZSkgPT4ge1xuICAgICAgaWYgKG9wdGlvbnMuZGVzZXJpYWxpemVyKSB7XG4gICAgICAgIHJldHVybiBvcHRpb25zLmRlc2VyaWFsaXplcih2YWx1ZSk7XG4gICAgICB9XG4gICAgICBpZiAodmFsdWUgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgcmV0dXJuIHZvaWQgMDtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IGluaXRpYWxWYWx1ZSBpbnN0YW5jZW9mIEZ1bmN0aW9uID8gaW5pdGlhbFZhbHVlKCkgOiBpbml0aWFsVmFsdWU7XG4gICAgICBsZXQgcGFyc2VkO1xuICAgICAgdHJ5IHtcbiAgICAgICAgcGFyc2VkID0gSlNPTi5wYXJzZSh2YWx1ZSk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBjb25zb2xlLmVycm9yKFwiRXJyb3IgcGFyc2luZyBKU09OOlwiLCBlcnJvcik7XG4gICAgICAgIHJldHVybiBkZWZhdWx0VmFsdWU7XG4gICAgICB9XG4gICAgICByZXR1cm4gcGFyc2VkO1xuICAgIH0sXG4gICAgW29wdGlvbnMsIGluaXRpYWxWYWx1ZV1cbiAgKTtcbiAgY29uc3QgcmVhZFZhbHVlID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIGNvbnN0IGluaXRpYWxWYWx1ZVRvVXNlID0gaW5pdGlhbFZhbHVlIGluc3RhbmNlb2YgRnVuY3Rpb24gPyBpbml0aWFsVmFsdWUoKSA6IGluaXRpYWxWYWx1ZTtcbiAgICBpZiAoSVNfU0VSVkVSKSB7XG4gICAgICByZXR1cm4gaW5pdGlhbFZhbHVlVG9Vc2U7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBjb25zdCByYXcgPSB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0oa2V5KTtcbiAgICAgIHJldHVybiByYXcgPyBkZXNlcmlhbGl6ZXIocmF3KSA6IGluaXRpYWxWYWx1ZVRvVXNlO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLndhcm4oYEVycm9yIHJlYWRpbmcgbG9jYWxTdG9yYWdlIGtleSBcXHUyMDFDJHtrZXl9XFx1MjAxRDpgLCBlcnJvcik7XG4gICAgICByZXR1cm4gaW5pdGlhbFZhbHVlVG9Vc2U7XG4gICAgfVxuICB9LCBbaW5pdGlhbFZhbHVlLCBrZXksIGRlc2VyaWFsaXplcl0pO1xuICBjb25zdCBbc3RvcmVkVmFsdWUsIHNldFN0b3JlZFZhbHVlXSA9IHVzZVN0YXRlKCgpID0+IHtcbiAgICBpZiAoaW5pdGlhbGl6ZVdpdGhWYWx1ZSkge1xuICAgICAgcmV0dXJuIHJlYWRWYWx1ZSgpO1xuICAgIH1cbiAgICByZXR1cm4gaW5pdGlhbFZhbHVlIGluc3RhbmNlb2YgRnVuY3Rpb24gPyBpbml0aWFsVmFsdWUoKSA6IGluaXRpYWxWYWx1ZTtcbiAgfSk7XG4gIGNvbnN0IHNldFZhbHVlID0gdXNlRXZlbnRDYWxsYmFjaygodmFsdWUpID0+IHtcbiAgICBpZiAoSVNfU0VSVkVSKSB7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGBUcmllZCBzZXR0aW5nIGxvY2FsU3RvcmFnZSBrZXkgXFx1MjAxQyR7a2V5fVxcdTIwMUQgZXZlbiB0aG91Z2ggZW52aXJvbm1lbnQgaXMgbm90IGEgY2xpZW50YFxuICAgICAgKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG5ld1ZhbHVlID0gdmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbiA/IHZhbHVlKHJlYWRWYWx1ZSgpKSA6IHZhbHVlO1xuICAgICAgd2luZG93LmxvY2FsU3RvcmFnZS5zZXRJdGVtKGtleSwgc2VyaWFsaXplcihuZXdWYWx1ZSkpO1xuICAgICAgc2V0U3RvcmVkVmFsdWUobmV3VmFsdWUpO1xuICAgICAgd2luZG93LmRpc3BhdGNoRXZlbnQobmV3IFN0b3JhZ2VFdmVudChcImxvY2FsLXN0b3JhZ2VcIiwgeyBrZXkgfSkpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICBjb25zb2xlLndhcm4oYEVycm9yIHNldHRpbmcgbG9jYWxTdG9yYWdlIGtleSBcXHUyMDFDJHtrZXl9XFx1MjAxRDpgLCBlcnJvcik7XG4gICAgfVxuICB9KTtcbiAgY29uc3QgcmVtb3ZlVmFsdWUgPSB1c2VFdmVudENhbGxiYWNrKCgpID0+IHtcbiAgICBpZiAoSVNfU0VSVkVSKSB7XG4gICAgICBjb25zb2xlLndhcm4oXG4gICAgICAgIGBUcmllZCByZW1vdmluZyBsb2NhbFN0b3JhZ2Uga2V5IFxcdTIwMUMke2tleX1cXHUyMDFEIGV2ZW4gdGhvdWdoIGVudmlyb25tZW50IGlzIG5vdCBhIGNsaWVudGBcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IGluaXRpYWxWYWx1ZSBpbnN0YW5jZW9mIEZ1bmN0aW9uID8gaW5pdGlhbFZhbHVlKCkgOiBpbml0aWFsVmFsdWU7XG4gICAgd2luZG93LmxvY2FsU3RvcmFnZS5yZW1vdmVJdGVtKGtleSk7XG4gICAgc2V0U3RvcmVkVmFsdWUoZGVmYXVsdFZhbHVlKTtcbiAgICB3aW5kb3cuZGlzcGF0Y2hFdmVudChuZXcgU3RvcmFnZUV2ZW50KFwibG9jYWwtc3RvcmFnZVwiLCB7IGtleSB9KSk7XG4gIH0pO1xuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIHNldFN0b3JlZFZhbHVlKHJlYWRWYWx1ZSgpKTtcbiAgfSwgW2tleV0pO1xuICBjb25zdCBoYW5kbGVTdG9yYWdlQ2hhbmdlID0gdXNlQ2FsbGJhY2soXG4gICAgKGV2ZW50KSA9PiB7XG4gICAgICBpZiAoZXZlbnQua2V5ICYmIGV2ZW50LmtleSAhPT0ga2V5KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHNldFN0b3JlZFZhbHVlKHJlYWRWYWx1ZSgpKTtcbiAgICB9LFxuICAgIFtrZXksIHJlYWRWYWx1ZV1cbiAgKTtcbiAgdXNlRXZlbnRMaXN0ZW5lcihcInN0b3JhZ2VcIiwgaGFuZGxlU3RvcmFnZUNoYW5nZSk7XG4gIHVzZUV2ZW50TGlzdGVuZXIoXCJsb2NhbC1zdG9yYWdlXCIsIGhhbmRsZVN0b3JhZ2VDaGFuZ2UpO1xuICByZXR1cm4gW3N0b3JlZFZhbHVlLCBzZXRWYWx1ZSwgcmVtb3ZlVmFsdWVdO1xufVxudmFyIElTX1NFUlZFUjIgPSB0eXBlb2Ygd2luZG93ID09PSBcInVuZGVmaW5lZFwiO1xuZnVuY3Rpb24gdXNlTWVkaWFRdWVyeShxdWVyeSwge1xuICBkZWZhdWx0VmFsdWUgPSBmYWxzZSxcbiAgaW5pdGlhbGl6ZVdpdGhWYWx1ZSA9IHRydWVcbn0gPSB7fSkge1xuICBjb25zdCBnZXRNYXRjaGVzID0gKHF1ZXJ5MikgPT4ge1xuICAgIGlmIChJU19TRVJWRVIyKSB7XG4gICAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xuICAgIH1cbiAgICByZXR1cm4gd2luZG93Lm1hdGNoTWVkaWEocXVlcnkyKS5tYXRjaGVzO1xuICB9O1xuICBjb25zdCBbbWF0Y2hlcywgc2V0TWF0Y2hlc10gPSB1c2VTdGF0ZSgoKSA9PiB7XG4gICAgaWYgKGluaXRpYWxpemVXaXRoVmFsdWUpIHtcbiAgICAgIHJldHVybiBnZXRNYXRjaGVzKHF1ZXJ5KTtcbiAgICB9XG4gICAgcmV0dXJuIGRlZmF1bHRWYWx1ZTtcbiAgfSk7XG4gIGZ1bmN0aW9uIGhhbmRsZUNoYW5nZSgpIHtcbiAgICBzZXRNYXRjaGVzKGdldE1hdGNoZXMocXVlcnkpKTtcbiAgfVxuICB1c2VJc29tb3JwaGljTGF5b3V0RWZmZWN0KCgpID0+IHtcbiAgICBjb25zdCBtYXRjaE1lZGlhID0gd2luZG93Lm1hdGNoTWVkaWEocXVlcnkpO1xuICAgIGhhbmRsZUNoYW5nZSgpO1xuICAgIGlmIChtYXRjaE1lZGlhLmFkZExpc3RlbmVyKSB7XG4gICAgICBtYXRjaE1lZGlhLmFkZExpc3RlbmVyKGhhbmRsZUNoYW5nZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIG1hdGNoTWVkaWEuYWRkRXZlbnRMaXN0ZW5lcihcImNoYW5nZVwiLCBoYW5kbGVDaGFuZ2UpO1xuICAgIH1cbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgaWYgKG1hdGNoTWVkaWEucmVtb3ZlTGlzdGVuZXIpIHtcbiAgICAgICAgbWF0Y2hNZWRpYS5yZW1vdmVMaXN0ZW5lcihoYW5kbGVDaGFuZ2UpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgbWF0Y2hNZWRpYS5yZW1vdmVFdmVudExpc3RlbmVyKFwiY2hhbmdlXCIsIGhhbmRsZUNoYW5nZSk7XG4gICAgICB9XG4gICAgfTtcbiAgfSwgW3F1ZXJ5XSk7XG4gIHJldHVybiBtYXRjaGVzO1xufVxuXG4vLyBzcmMvdXNlRGFya01vZGUvdXNlRGFya01vZGUudHNcbnZhciBDT0xPUl9TQ0hFTUVfUVVFUlkgPSBcIihwcmVmZXJzLWNvbG9yLXNjaGVtZTogZGFyaylcIjtcbnZhciBMT0NBTF9TVE9SQUdFX0tFWSA9IFwidXNlaG9va3MtdHMtZGFyay1tb2RlXCI7XG5mdW5jdGlvbiB1c2VEYXJrTW9kZShvcHRpb25zID0ge30pIHtcbiAgY29uc3Qge1xuICAgIGRlZmF1bHRWYWx1ZSxcbiAgICBsb2NhbFN0b3JhZ2VLZXkgPSBMT0NBTF9TVE9SQUdFX0tFWSxcbiAgICBpbml0aWFsaXplV2l0aFZhbHVlID0gdHJ1ZVxuICB9ID0gb3B0aW9ucztcbiAgY29uc3QgaXNEYXJrT1MgPSB1c2VNZWRpYVF1ZXJ5KENPTE9SX1NDSEVNRV9RVUVSWSwge1xuICAgIGluaXRpYWxpemVXaXRoVmFsdWUsXG4gICAgZGVmYXVsdFZhbHVlXG4gIH0pO1xuICBjb25zdCBbaXNEYXJrTW9kZSwgc2V0RGFya01vZGVdID0gdXNlTG9jYWxTdG9yYWdlKFxuICAgIGxvY2FsU3RvcmFnZUtleSxcbiAgICBkZWZhdWx0VmFsdWUgPz8gaXNEYXJrT1MgPz8gZmFsc2UsXG4gICAgeyBpbml0aWFsaXplV2l0aFZhbHVlIH1cbiAgKTtcbiAgdXNlSXNvbW9ycGhpY0xheW91dEVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKGlzRGFya09TICE9PSBpc0RhcmtNb2RlKSB7XG4gICAgICBzZXREYXJrTW9kZShpc0RhcmtPUyk7XG4gICAgfVxuICB9LCBbaXNEYXJrT1NdKTtcbiAgcmV0dXJuIHtcbiAgICBpc0RhcmtNb2RlLFxuICAgIHRvZ2dsZTogKCkgPT4ge1xuICAgICAgc2V0RGFya01vZGUoKHByZXYpID0+ICFwcmV2KTtcbiAgICB9LFxuICAgIGVuYWJsZTogKCkgPT4ge1xuICAgICAgc2V0RGFya01vZGUodHJ1ZSk7XG4gICAgfSxcbiAgICBkaXNhYmxlOiAoKSA9PiB7XG4gICAgICBzZXREYXJrTW9kZShmYWxzZSk7XG4gICAgfSxcbiAgICBzZXQ6ICh2YWx1ZSkgPT4ge1xuICAgICAgc2V0RGFya01vZGUodmFsdWUpO1xuICAgIH1cbiAgfTtcbn1cbmZ1bmN0aW9uIHVzZVVubW91bnQoZnVuYykge1xuICBjb25zdCBmdW5jUmVmID0gdXNlUmVmKGZ1bmMpO1xuICBmdW5jUmVmLmN1cnJlbnQgPSBmdW5jO1xuICB1c2VFZmZlY3QoXG4gICAgKCkgPT4gKCkgPT4ge1xuICAgICAgZnVuY1JlZi5jdXJyZW50KCk7XG4gICAgfSxcbiAgICBbXVxuICApO1xufVxuXG4vLyBzcmMvdXNlRGVib3VuY2VDYWxsYmFjay91c2VEZWJvdW5jZUNhbGxiYWNrLnRzXG5mdW5jdGlvbiB1c2VEZWJvdW5jZUNhbGxiYWNrKGZ1bmMsIGRlbGF5ID0gNTAwLCBvcHRpb25zKSB7XG4gIGNvbnN0IGRlYm91bmNlZEZ1bmMgPSB1c2VSZWYoKTtcbiAgdXNlVW5tb3VudCgoKSA9PiB7XG4gICAgaWYgKGRlYm91bmNlZEZ1bmMuY3VycmVudCkge1xuICAgICAgZGVib3VuY2VkRnVuYy5jdXJyZW50LmNhbmNlbCgpO1xuICAgIH1cbiAgfSk7XG4gIGNvbnN0IGRlYm91bmNlZCA9IHVzZU1lbW8oKCkgPT4ge1xuICAgIGNvbnN0IGRlYm91bmNlZEZ1bmNJbnN0YW5jZSA9IGRlYm91bmNlKGZ1bmMsIGRlbGF5LCBvcHRpb25zKTtcbiAgICBjb25zdCB3cmFwcGVkRnVuYyA9ICguLi5hcmdzKSA9PiB7XG4gICAgICByZXR1cm4gZGVib3VuY2VkRnVuY0luc3RhbmNlKC4uLmFyZ3MpO1xuICAgIH07XG4gICAgd3JhcHBlZEZ1bmMuY2FuY2VsID0gKCkgPT4ge1xuICAgICAgZGVib3VuY2VkRnVuY0luc3RhbmNlLmNhbmNlbCgpO1xuICAgIH07XG4gICAgd3JhcHBlZEZ1bmMuaXNQZW5kaW5nID0gKCkgPT4ge1xuICAgICAgcmV0dXJuICEhZGVib3VuY2VkRnVuYy5jdXJyZW50O1xuICAgIH07XG4gICAgd3JhcHBlZEZ1bmMuZmx1c2ggPSAoKSA9PiB7XG4gICAgICByZXR1cm4gZGVib3VuY2VkRnVuY0luc3RhbmNlLmZsdXNoKCk7XG4gICAgfTtcbiAgICByZXR1cm4gd3JhcHBlZEZ1bmM7XG4gIH0sIFtmdW5jLCBkZWxheSwgb3B0aW9uc10pO1xuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGRlYm91bmNlZEZ1bmMuY3VycmVudCA9IGRlYm91bmNlKGZ1bmMsIGRlbGF5LCBvcHRpb25zKTtcbiAgfSwgW2Z1bmMsIGRlbGF5LCBvcHRpb25zXSk7XG4gIHJldHVybiBkZWJvdW5jZWQ7XG59XG5mdW5jdGlvbiB1c2VEZWJvdW5jZVZhbHVlKGluaXRpYWxWYWx1ZSwgZGVsYXksIG9wdGlvbnMpIHtcbiAgY29uc3QgZXEgPSAob3B0aW9ucyA9PSBudWxsID8gdm9pZCAwIDogb3B0aW9ucy5lcXVhbGl0eUZuKSA/PyAoKGxlZnQsIHJpZ2h0KSA9PiBsZWZ0ID09PSByaWdodCk7XG4gIGNvbnN0IHVud3JhcHBlZEluaXRpYWxWYWx1ZSA9IGluaXRpYWxWYWx1ZSBpbnN0YW5jZW9mIEZ1bmN0aW9uID8gaW5pdGlhbFZhbHVlKCkgOiBpbml0aWFsVmFsdWU7XG4gIGNvbnN0IFtkZWJvdW5jZWRWYWx1ZSwgc2V0RGVib3VuY2VkVmFsdWVdID0gdXNlU3RhdGUodW53cmFwcGVkSW5pdGlhbFZhbHVlKTtcbiAgY29uc3QgcHJldmlvdXNWYWx1ZVJlZiA9IHVzZVJlZih1bndyYXBwZWRJbml0aWFsVmFsdWUpO1xuICBjb25zdCB1cGRhdGVEZWJvdW5jZWRWYWx1ZSA9IHVzZURlYm91bmNlQ2FsbGJhY2soXG4gICAgc2V0RGVib3VuY2VkVmFsdWUsXG4gICAgZGVsYXksXG4gICAgb3B0aW9uc1xuICApO1xuICBpZiAoIWVxKHByZXZpb3VzVmFsdWVSZWYuY3VycmVudCwgdW53cmFwcGVkSW5pdGlhbFZhbHVlKSkge1xuICAgIHVwZGF0ZURlYm91bmNlZFZhbHVlKHVud3JhcHBlZEluaXRpYWxWYWx1ZSk7XG4gICAgcHJldmlvdXNWYWx1ZVJlZi5jdXJyZW50ID0gdW53cmFwcGVkSW5pdGlhbFZhbHVlO1xuICB9XG4gIHJldHVybiBbZGVib3VuY2VkVmFsdWUsIHVwZGF0ZURlYm91bmNlZFZhbHVlXTtcbn1cbmZ1bmN0aW9uIHVzZURvY3VtZW50VGl0bGUodGl0bGUsIG9wdGlvbnMgPSB7fSkge1xuICBjb25zdCB7IHByZXNlcnZlVGl0bGVPblVubW91bnQgPSB0cnVlIH0gPSBvcHRpb25zO1xuICBjb25zdCBkZWZhdWx0VGl0bGUgPSB1c2VSZWYobnVsbCk7XG4gIHVzZUlzb21vcnBoaWNMYXlvdXRFZmZlY3QoKCkgPT4ge1xuICAgIGRlZmF1bHRUaXRsZS5jdXJyZW50ID0gd2luZG93LmRvY3VtZW50LnRpdGxlO1xuICB9LCBbXSk7XG4gIHVzZUlzb21vcnBoaWNMYXlvdXRFZmZlY3QoKCkgPT4ge1xuICAgIHdpbmRvdy5kb2N1bWVudC50aXRsZSA9IHRpdGxlO1xuICB9LCBbdGl0bGVdKTtcbiAgdXNlVW5tb3VudCgoKSA9PiB7XG4gICAgaWYgKCFwcmVzZXJ2ZVRpdGxlT25Vbm1vdW50ICYmIGRlZmF1bHRUaXRsZS5jdXJyZW50KSB7XG4gICAgICB3aW5kb3cuZG9jdW1lbnQudGl0bGUgPSBkZWZhdWx0VGl0bGUuY3VycmVudDtcbiAgICB9XG4gIH0pO1xufVxuZnVuY3Rpb24gdXNlSG92ZXIoZWxlbWVudFJlZikge1xuICBjb25zdCBbdmFsdWUsIHNldFZhbHVlXSA9IHVzZVN0YXRlKGZhbHNlKTtcbiAgY29uc3QgaGFuZGxlTW91c2VFbnRlciA9ICgpID0+IHtcbiAgICBzZXRWYWx1ZSh0cnVlKTtcbiAgfTtcbiAgY29uc3QgaGFuZGxlTW91c2VMZWF2ZSA9ICgpID0+IHtcbiAgICBzZXRWYWx1ZShmYWxzZSk7XG4gIH07XG4gIHVzZUV2ZW50TGlzdGVuZXIoXCJtb3VzZWVudGVyXCIsIGhhbmRsZU1vdXNlRW50ZXIsIGVsZW1lbnRSZWYpO1xuICB1c2VFdmVudExpc3RlbmVyKFwibW91c2VsZWF2ZVwiLCBoYW5kbGVNb3VzZUxlYXZlLCBlbGVtZW50UmVmKTtcbiAgcmV0dXJuIHZhbHVlO1xufVxuZnVuY3Rpb24gdXNlSW50ZXJzZWN0aW9uT2JzZXJ2ZXIoe1xuICB0aHJlc2hvbGQgPSAwLFxuICByb290ID0gbnVsbCxcbiAgcm9vdE1hcmdpbiA9IFwiMCVcIixcbiAgZnJlZXplT25jZVZpc2libGUgPSBmYWxzZSxcbiAgaW5pdGlhbElzSW50ZXJzZWN0aW5nID0gZmFsc2UsXG4gIG9uQ2hhbmdlXG59ID0ge30pIHtcbiAgdmFyIF9hO1xuICBjb25zdCBbcmVmLCBzZXRSZWZdID0gdXNlU3RhdGUobnVsbCk7XG4gIGNvbnN0IFtzdGF0ZSwgc2V0U3RhdGVdID0gdXNlU3RhdGUoKCkgPT4gKHtcbiAgICBpc0ludGVyc2VjdGluZzogaW5pdGlhbElzSW50ZXJzZWN0aW5nLFxuICAgIGVudHJ5OiB2b2lkIDBcbiAgfSkpO1xuICBjb25zdCBjYWxsYmFja1JlZiA9IHVzZVJlZigpO1xuICBjYWxsYmFja1JlZi5jdXJyZW50ID0gb25DaGFuZ2U7XG4gIGNvbnN0IGZyb3plbiA9ICgoX2EgPSBzdGF0ZS5lbnRyeSkgPT0gbnVsbCA/IHZvaWQgMCA6IF9hLmlzSW50ZXJzZWN0aW5nKSAmJiBmcmVlemVPbmNlVmlzaWJsZTtcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBpZiAoIXJlZilcbiAgICAgIHJldHVybjtcbiAgICBpZiAoIShcIkludGVyc2VjdGlvbk9ic2VydmVyXCIgaW4gd2luZG93KSlcbiAgICAgIHJldHVybjtcbiAgICBpZiAoZnJvemVuKVxuICAgICAgcmV0dXJuO1xuICAgIGxldCB1bm9ic2VydmU7XG4gICAgY29uc3Qgb2JzZXJ2ZXIgPSBuZXcgSW50ZXJzZWN0aW9uT2JzZXJ2ZXIoXG4gICAgICAoZW50cmllcykgPT4ge1xuICAgICAgICBjb25zdCB0aHJlc2hvbGRzID0gQXJyYXkuaXNBcnJheShvYnNlcnZlci50aHJlc2hvbGRzKSA/IG9ic2VydmVyLnRocmVzaG9sZHMgOiBbb2JzZXJ2ZXIudGhyZXNob2xkc107XG4gICAgICAgIGVudHJpZXMuZm9yRWFjaCgoZW50cnkpID0+IHtcbiAgICAgICAgICBjb25zdCBpc0ludGVyc2VjdGluZyA9IGVudHJ5LmlzSW50ZXJzZWN0aW5nICYmIHRocmVzaG9sZHMuc29tZSgodGhyZXNob2xkMikgPT4gZW50cnkuaW50ZXJzZWN0aW9uUmF0aW8gPj0gdGhyZXNob2xkMik7XG4gICAgICAgICAgc2V0U3RhdGUoeyBpc0ludGVyc2VjdGluZywgZW50cnkgfSk7XG4gICAgICAgICAgaWYgKGNhbGxiYWNrUmVmLmN1cnJlbnQpIHtcbiAgICAgICAgICAgIGNhbGxiYWNrUmVmLmN1cnJlbnQoaXNJbnRlcnNlY3RpbmcsIGVudHJ5KTtcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGlzSW50ZXJzZWN0aW5nICYmIGZyZWV6ZU9uY2VWaXNpYmxlICYmIHVub2JzZXJ2ZSkge1xuICAgICAgICAgICAgdW5vYnNlcnZlKCk7XG4gICAgICAgICAgICB1bm9ic2VydmUgPSB2b2lkIDA7XG4gICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICAgIH0sXG4gICAgICB7IHRocmVzaG9sZCwgcm9vdCwgcm9vdE1hcmdpbiB9XG4gICAgKTtcbiAgICBvYnNlcnZlci5vYnNlcnZlKHJlZik7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIG9ic2VydmVyLmRpc2Nvbm5lY3QoKTtcbiAgICB9O1xuICB9LCBbXG4gICAgcmVmLFxuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSByZWFjdC1ob29rcy9leGhhdXN0aXZlLWRlcHNcbiAgICBKU09OLnN0cmluZ2lmeSh0aHJlc2hvbGQpLFxuICAgIHJvb3QsXG4gICAgcm9vdE1hcmdpbixcbiAgICBmcm96ZW4sXG4gICAgZnJlZXplT25jZVZpc2libGVcbiAgXSk7XG4gIGNvbnN0IHByZXZSZWYgPSB1c2VSZWYobnVsbCk7XG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgdmFyIF9hMjtcbiAgICBpZiAoIXJlZiAmJiAoKF9hMiA9IHN0YXRlLmVudHJ5KSA9PSBudWxsID8gdm9pZCAwIDogX2EyLnRhcmdldCkgJiYgIWZyZWV6ZU9uY2VWaXNpYmxlICYmICFmcm96ZW4gJiYgcHJldlJlZi5jdXJyZW50ICE9PSBzdGF0ZS5lbnRyeS50YXJnZXQpIHtcbiAgICAgIHByZXZSZWYuY3VycmVudCA9IHN0YXRlLmVudHJ5LnRhcmdldDtcbiAgICAgIHNldFN0YXRlKHsgaXNJbnRlcnNlY3Rpbmc6IGluaXRpYWxJc0ludGVyc2VjdGluZywgZW50cnk6IHZvaWQgMCB9KTtcbiAgICB9XG4gIH0sIFtyZWYsIHN0YXRlLmVudHJ5LCBmcmVlemVPbmNlVmlzaWJsZSwgZnJvemVuLCBpbml0aWFsSXNJbnRlcnNlY3RpbmddKTtcbiAgY29uc3QgcmVzdWx0ID0gW1xuICAgIHNldFJlZixcbiAgICAhIXN0YXRlLmlzSW50ZXJzZWN0aW5nLFxuICAgIHN0YXRlLmVudHJ5XG4gIF07XG4gIHJlc3VsdC5yZWYgPSByZXN1bHRbMF07XG4gIHJlc3VsdC5pc0ludGVyc2VjdGluZyA9IHJlc3VsdFsxXTtcbiAgcmVzdWx0LmVudHJ5ID0gcmVzdWx0WzJdO1xuICByZXR1cm4gcmVzdWx0O1xufVxuZnVuY3Rpb24gdXNlSXNDbGllbnQoKSB7XG4gIGNvbnN0IFtpc0NsaWVudCwgc2V0Q2xpZW50XSA9IHVzZVN0YXRlKGZhbHNlKTtcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBzZXRDbGllbnQodHJ1ZSk7XG4gIH0sIFtdKTtcbiAgcmV0dXJuIGlzQ2xpZW50O1xufVxuZnVuY3Rpb24gdXNlSXNNb3VudGVkKCkge1xuICBjb25zdCBpc01vdW50ZWQgPSB1c2VSZWYoZmFsc2UpO1xuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlzTW91bnRlZC5jdXJyZW50ID0gdHJ1ZTtcbiAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgaXNNb3VudGVkLmN1cnJlbnQgPSBmYWxzZTtcbiAgICB9O1xuICB9LCBbXSk7XG4gIHJldHVybiB1c2VDYWxsYmFjaygoKSA9PiBpc01vdW50ZWQuY3VycmVudCwgW10pO1xufVxuZnVuY3Rpb24gdXNlTWFwKGluaXRpYWxTdGF0ZSA9IC8qIEBfX1BVUkVfXyAqLyBuZXcgTWFwKCkpIHtcbiAgY29uc3QgW21hcCwgc2V0TWFwXSA9IHVzZVN0YXRlKG5ldyBNYXAoaW5pdGlhbFN0YXRlKSk7XG4gIGNvbnN0IGFjdGlvbnMgPSB7XG4gICAgc2V0OiB1c2VDYWxsYmFjaygoa2V5LCB2YWx1ZSkgPT4ge1xuICAgICAgc2V0TWFwKChwcmV2KSA9PiB7XG4gICAgICAgIGNvbnN0IGNvcHkgPSBuZXcgTWFwKHByZXYpO1xuICAgICAgICBjb3B5LnNldChrZXksIHZhbHVlKTtcbiAgICAgICAgcmV0dXJuIGNvcHk7XG4gICAgICB9KTtcbiAgICB9LCBbXSksXG4gICAgc2V0QWxsOiB1c2VDYWxsYmFjaygoZW50cmllcykgPT4ge1xuICAgICAgc2V0TWFwKCgpID0+IG5ldyBNYXAoZW50cmllcykpO1xuICAgIH0sIFtdKSxcbiAgICByZW1vdmU6IHVzZUNhbGxiYWNrKChrZXkpID0+IHtcbiAgICAgIHNldE1hcCgocHJldikgPT4ge1xuICAgICAgICBjb25zdCBjb3B5ID0gbmV3IE1hcChwcmV2KTtcbiAgICAgICAgY29weS5kZWxldGUoa2V5KTtcbiAgICAgICAgcmV0dXJuIGNvcHk7XG4gICAgICB9KTtcbiAgICB9LCBbXSksXG4gICAgcmVzZXQ6IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICAgIHNldE1hcCgoKSA9PiAvKiBAX19QVVJFX18gKi8gbmV3IE1hcCgpKTtcbiAgICB9LCBbXSlcbiAgfTtcbiAgcmV0dXJuIFttYXAsIGFjdGlvbnNdO1xufVxuXG4vLyBzcmMvdXNlT25DbGlja091dHNpZGUvdXNlT25DbGlja091dHNpZGUudHNcbmZ1bmN0aW9uIHVzZU9uQ2xpY2tPdXRzaWRlKHJlZiwgaGFuZGxlciwgZXZlbnRUeXBlID0gXCJtb3VzZWRvd25cIiwgZXZlbnRMaXN0ZW5lck9wdGlvbnMgPSB7fSkge1xuICB1c2VFdmVudExpc3RlbmVyKFxuICAgIGV2ZW50VHlwZSxcbiAgICAoZXZlbnQpID0+IHtcbiAgICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldDtcbiAgICAgIGlmICghdGFyZ2V0IHx8ICF0YXJnZXQuaXNDb25uZWN0ZWQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgY29uc3QgaXNPdXRzaWRlID0gQXJyYXkuaXNBcnJheShyZWYpID8gcmVmLmZpbHRlcigocikgPT4gQm9vbGVhbihyLmN1cnJlbnQpKS5ldmVyeSgocikgPT4gci5jdXJyZW50ICYmICFyLmN1cnJlbnQuY29udGFpbnModGFyZ2V0KSkgOiByZWYuY3VycmVudCAmJiAhcmVmLmN1cnJlbnQuY29udGFpbnModGFyZ2V0KTtcbiAgICAgIGlmIChpc091dHNpZGUpIHtcbiAgICAgICAgaGFuZGxlcihldmVudCk7XG4gICAgICB9XG4gICAgfSxcbiAgICB2b2lkIDAsXG4gICAgZXZlbnRMaXN0ZW5lck9wdGlvbnNcbiAgKTtcbn1cbnZhciBJU19TRVJWRVIzID0gdHlwZW9mIHdpbmRvdyA9PT0gXCJ1bmRlZmluZWRcIjtcbmZ1bmN0aW9uIHVzZVJlYWRMb2NhbFN0b3JhZ2Uoa2V5LCBvcHRpb25zID0ge30pIHtcbiAgbGV0IHsgaW5pdGlhbGl6ZVdpdGhWYWx1ZSA9IHRydWUgfSA9IG9wdGlvbnM7XG4gIGlmIChJU19TRVJWRVIzKSB7XG4gICAgaW5pdGlhbGl6ZVdpdGhWYWx1ZSA9IGZhbHNlO1xuICB9XG4gIGNvbnN0IGRlc2VyaWFsaXplciA9IHVzZUNhbGxiYWNrKFxuICAgICh2YWx1ZSkgPT4ge1xuICAgICAgaWYgKG9wdGlvbnMuZGVzZXJpYWxpemVyKSB7XG4gICAgICAgIHJldHVybiBvcHRpb25zLmRlc2VyaWFsaXplcih2YWx1ZSk7XG4gICAgICB9XG4gICAgICBpZiAodmFsdWUgPT09IFwidW5kZWZpbmVkXCIpIHtcbiAgICAgICAgcmV0dXJuIHZvaWQgMDtcbiAgICAgIH1cbiAgICAgIGxldCBwYXJzZWQ7XG4gICAgICB0cnkge1xuICAgICAgICBwYXJzZWQgPSBKU09OLnBhcnNlKHZhbHVlKTtcbiAgICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciBwYXJzaW5nIEpTT046XCIsIGVycm9yKTtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICB9XG4gICAgICByZXR1cm4gcGFyc2VkO1xuICAgIH0sXG4gICAgW29wdGlvbnNdXG4gICk7XG4gIGNvbnN0IHJlYWRWYWx1ZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICBpZiAoSVNfU0VSVkVSMykge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHRyeSB7XG4gICAgICBjb25zdCByYXcgPSB3aW5kb3cubG9jYWxTdG9yYWdlLmdldEl0ZW0oa2V5KTtcbiAgICAgIHJldHVybiByYXcgPyBkZXNlcmlhbGl6ZXIocmF3KSA6IG51bGw7XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnNvbGUud2FybihgRXJyb3IgcmVhZGluZyBsb2NhbFN0b3JhZ2Uga2V5IFxcdTIwMUMke2tleX1cXHUyMDFEOmAsIGVycm9yKTtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cbiAgfSwgW2tleSwgZGVzZXJpYWxpemVyXSk7XG4gIGNvbnN0IFtzdG9yZWRWYWx1ZSwgc2V0U3RvcmVkVmFsdWVdID0gdXNlU3RhdGUoKCkgPT4ge1xuICAgIGlmIChpbml0aWFsaXplV2l0aFZhbHVlKSB7XG4gICAgICByZXR1cm4gcmVhZFZhbHVlKCk7XG4gICAgfVxuICAgIHJldHVybiB2b2lkIDA7XG4gIH0pO1xuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIHNldFN0b3JlZFZhbHVlKHJlYWRWYWx1ZSgpKTtcbiAgfSwgW2tleV0pO1xuICBjb25zdCBoYW5kbGVTdG9yYWdlQ2hhbmdlID0gdXNlQ2FsbGJhY2soXG4gICAgKGV2ZW50KSA9PiB7XG4gICAgICBpZiAoZXZlbnQua2V5ICYmIGV2ZW50LmtleSAhPT0ga2V5KSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cbiAgICAgIHNldFN0b3JlZFZhbHVlKHJlYWRWYWx1ZSgpKTtcbiAgICB9LFxuICAgIFtrZXksIHJlYWRWYWx1ZV1cbiAgKTtcbiAgdXNlRXZlbnRMaXN0ZW5lcihcInN0b3JhZ2VcIiwgaGFuZGxlU3RvcmFnZUNoYW5nZSk7XG4gIHVzZUV2ZW50TGlzdGVuZXIoXCJsb2NhbC1zdG9yYWdlXCIsIGhhbmRsZVN0b3JhZ2VDaGFuZ2UpO1xuICByZXR1cm4gc3RvcmVkVmFsdWU7XG59XG52YXIgaW5pdGlhbFNpemUgPSB7XG4gIHdpZHRoOiB2b2lkIDAsXG4gIGhlaWdodDogdm9pZCAwXG59O1xuZnVuY3Rpb24gdXNlUmVzaXplT2JzZXJ2ZXIob3B0aW9ucykge1xuICBjb25zdCB7IHJlZiwgYm94ID0gXCJjb250ZW50LWJveFwiIH0gPSBvcHRpb25zO1xuICBjb25zdCBbeyB3aWR0aCwgaGVpZ2h0IH0sIHNldFNpemVdID0gdXNlU3RhdGUoaW5pdGlhbFNpemUpO1xuICBjb25zdCBpc01vdW50ZWQgPSB1c2VJc01vdW50ZWQoKTtcbiAgY29uc3QgcHJldmlvdXNTaXplID0gdXNlUmVmKHsgLi4uaW5pdGlhbFNpemUgfSk7XG4gIGNvbnN0IG9uUmVzaXplID0gdXNlUmVmKHZvaWQgMCk7XG4gIG9uUmVzaXplLmN1cnJlbnQgPSBvcHRpb25zLm9uUmVzaXplO1xuICB1c2VFZmZlY3QoKCkgPT4ge1xuICAgIGlmICghcmVmLmN1cnJlbnQpXG4gICAgICByZXR1cm47XG4gICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09IFwidW5kZWZpbmVkXCIgfHwgIShcIlJlc2l6ZU9ic2VydmVyXCIgaW4gd2luZG93KSlcbiAgICAgIHJldHVybjtcbiAgICBjb25zdCBvYnNlcnZlciA9IG5ldyBSZXNpemVPYnNlcnZlcigoW2VudHJ5XSkgPT4ge1xuICAgICAgY29uc3QgYm94UHJvcCA9IGJveCA9PT0gXCJib3JkZXItYm94XCIgPyBcImJvcmRlckJveFNpemVcIiA6IGJveCA9PT0gXCJkZXZpY2UtcGl4ZWwtY29udGVudC1ib3hcIiA/IFwiZGV2aWNlUGl4ZWxDb250ZW50Qm94U2l6ZVwiIDogXCJjb250ZW50Qm94U2l6ZVwiO1xuICAgICAgY29uc3QgbmV3V2lkdGggPSBleHRyYWN0U2l6ZShlbnRyeSwgYm94UHJvcCwgXCJpbmxpbmVTaXplXCIpO1xuICAgICAgY29uc3QgbmV3SGVpZ2h0ID0gZXh0cmFjdFNpemUoZW50cnksIGJveFByb3AsIFwiYmxvY2tTaXplXCIpO1xuICAgICAgY29uc3QgaGFzQ2hhbmdlZCA9IHByZXZpb3VzU2l6ZS5jdXJyZW50LndpZHRoICE9PSBuZXdXaWR0aCB8fCBwcmV2aW91c1NpemUuY3VycmVudC5oZWlnaHQgIT09IG5ld0hlaWdodDtcbiAgICAgIGlmIChoYXNDaGFuZ2VkKSB7XG4gICAgICAgIGNvbnN0IG5ld1NpemUgPSB7IHdpZHRoOiBuZXdXaWR0aCwgaGVpZ2h0OiBuZXdIZWlnaHQgfTtcbiAgICAgICAgcHJldmlvdXNTaXplLmN1cnJlbnQud2lkdGggPSBuZXdXaWR0aDtcbiAgICAgICAgcHJldmlvdXNTaXplLmN1cnJlbnQuaGVpZ2h0ID0gbmV3SGVpZ2h0O1xuICAgICAgICBpZiAob25SZXNpemUuY3VycmVudCkge1xuICAgICAgICAgIG9uUmVzaXplLmN1cnJlbnQobmV3U2l6ZSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKGlzTW91bnRlZCgpKSB7XG4gICAgICAgICAgICBzZXRTaXplKG5ld1NpemUpO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0pO1xuICAgIG9ic2VydmVyLm9ic2VydmUocmVmLmN1cnJlbnQsIHsgYm94IH0pO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBvYnNlcnZlci5kaXNjb25uZWN0KCk7XG4gICAgfTtcbiAgfSwgW2JveCwgcmVmLCBpc01vdW50ZWRdKTtcbiAgcmV0dXJuIHsgd2lkdGgsIGhlaWdodCB9O1xufVxuZnVuY3Rpb24gZXh0cmFjdFNpemUoZW50cnksIGJveCwgc2l6ZVR5cGUpIHtcbiAgaWYgKCFlbnRyeVtib3hdKSB7XG4gICAgaWYgKGJveCA9PT0gXCJjb250ZW50Qm94U2l6ZVwiKSB7XG4gICAgICByZXR1cm4gZW50cnkuY29udGVudFJlY3Rbc2l6ZVR5cGUgPT09IFwiaW5saW5lU2l6ZVwiID8gXCJ3aWR0aFwiIDogXCJoZWlnaHRcIl07XG4gICAgfVxuICAgIHJldHVybiB2b2lkIDA7XG4gIH1cbiAgcmV0dXJuIEFycmF5LmlzQXJyYXkoZW50cnlbYm94XSkgPyBlbnRyeVtib3hdWzBdW3NpemVUeXBlXSA6IChcbiAgICAvLyBAdHMtaWdub3JlIFN1cHBvcnQgRmlyZWZveCdzIG5vbi1zdGFuZGFyZCBiZWhhdmlvclxuICAgIGVudHJ5W2JveF1bc2l6ZVR5cGVdXG4gICk7XG59XG52YXIgSVNfU0VSVkVSNCA9IHR5cGVvZiB3aW5kb3cgPT09IFwidW5kZWZpbmVkXCI7XG5mdW5jdGlvbiB1c2VTY3JlZW4ob3B0aW9ucyA9IHt9KSB7XG4gIGxldCB7IGluaXRpYWxpemVXaXRoVmFsdWUgPSB0cnVlIH0gPSBvcHRpb25zO1xuICBpZiAoSVNfU0VSVkVSNCkge1xuICAgIGluaXRpYWxpemVXaXRoVmFsdWUgPSBmYWxzZTtcbiAgfVxuICBjb25zdCByZWFkU2NyZWVuID0gKCkgPT4ge1xuICAgIGlmIChJU19TRVJWRVI0KSB7XG4gICAgICByZXR1cm4gdm9pZCAwO1xuICAgIH1cbiAgICByZXR1cm4gd2luZG93LnNjcmVlbjtcbiAgfTtcbiAgY29uc3QgW3NjcmVlbiwgc2V0U2NyZWVuXSA9IHVzZVN0YXRlKCgpID0+IHtcbiAgICBpZiAoaW5pdGlhbGl6ZVdpdGhWYWx1ZSkge1xuICAgICAgcmV0dXJuIHJlYWRTY3JlZW4oKTtcbiAgICB9XG4gICAgcmV0dXJuIHZvaWQgMDtcbiAgfSk7XG4gIGNvbnN0IGRlYm91bmNlZFNldFNjcmVlbiA9IHVzZURlYm91bmNlQ2FsbGJhY2soXG4gICAgc2V0U2NyZWVuLFxuICAgIG9wdGlvbnMuZGVib3VuY2VEZWxheVxuICApO1xuICBmdW5jdGlvbiBoYW5kbGVTaXplKCkge1xuICAgIGNvbnN0IG5ld1NjcmVlbiA9IHJlYWRTY3JlZW4oKTtcbiAgICBjb25zdCBzZXRTaXplID0gb3B0aW9ucy5kZWJvdW5jZURlbGF5ID8gZGVib3VuY2VkU2V0U2NyZWVuIDogc2V0U2NyZWVuO1xuICAgIGlmIChuZXdTY3JlZW4pIHtcbiAgICAgIGNvbnN0IHtcbiAgICAgICAgd2lkdGgsXG4gICAgICAgIGhlaWdodCxcbiAgICAgICAgYXZhaWxIZWlnaHQsXG4gICAgICAgIGF2YWlsV2lkdGgsXG4gICAgICAgIGNvbG9yRGVwdGgsXG4gICAgICAgIG9yaWVudGF0aW9uLFxuICAgICAgICBwaXhlbERlcHRoXG4gICAgICB9ID0gbmV3U2NyZWVuO1xuICAgICAgc2V0U2l6ZSh7XG4gICAgICAgIHdpZHRoLFxuICAgICAgICBoZWlnaHQsXG4gICAgICAgIGF2YWlsSGVpZ2h0LFxuICAgICAgICBhdmFpbFdpZHRoLFxuICAgICAgICBjb2xvckRlcHRoLFxuICAgICAgICBvcmllbnRhdGlvbixcbiAgICAgICAgcGl4ZWxEZXB0aFxuICAgICAgfSk7XG4gICAgfVxuICB9XG4gIHVzZUV2ZW50TGlzdGVuZXIoXCJyZXNpemVcIiwgaGFuZGxlU2l6ZSk7XG4gIHVzZUlzb21vcnBoaWNMYXlvdXRFZmZlY3QoKCkgPT4ge1xuICAgIGhhbmRsZVNpemUoKTtcbiAgfSwgW10pO1xuICByZXR1cm4gc2NyZWVuO1xufVxudmFyIGNhY2hlZFNjcmlwdFN0YXR1c2VzID0gLyogQF9fUFVSRV9fICovIG5ldyBNYXAoKTtcbmZ1bmN0aW9uIGdldFNjcmlwdE5vZGUoc3JjKSB7XG4gIGNvbnN0IG5vZGUgPSBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKFxuICAgIGBzY3JpcHRbc3JjPVwiJHtzcmN9XCJdYFxuICApO1xuICBjb25zdCBzdGF0dXMgPSBub2RlID09IG51bGwgPyB2b2lkIDAgOiBub2RlLmdldEF0dHJpYnV0ZShcImRhdGEtc3RhdHVzXCIpO1xuICByZXR1cm4ge1xuICAgIG5vZGUsXG4gICAgc3RhdHVzXG4gIH07XG59XG5mdW5jdGlvbiB1c2VTY3JpcHQoc3JjLCBvcHRpb25zKSB7XG4gIGNvbnN0IFtzdGF0dXMsIHNldFN0YXR1c10gPSB1c2VTdGF0ZSgoKSA9PiB7XG4gICAgaWYgKCFzcmMgfHwgKG9wdGlvbnMgPT0gbnVsbCA/IHZvaWQgMCA6IG9wdGlvbnMuc2hvdWxkUHJldmVudExvYWQpKSB7XG4gICAgICByZXR1cm4gXCJpZGxlXCI7XG4gICAgfVxuICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICByZXR1cm4gXCJsb2FkaW5nXCI7XG4gICAgfVxuICAgIHJldHVybiBjYWNoZWRTY3JpcHRTdGF0dXNlcy5nZXQoc3JjKSA/PyBcImxvYWRpbmdcIjtcbiAgfSk7XG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKCFzcmMgfHwgKG9wdGlvbnMgPT0gbnVsbCA/IHZvaWQgMCA6IG9wdGlvbnMuc2hvdWxkUHJldmVudExvYWQpKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IGNhY2hlZFNjcmlwdFN0YXR1cyA9IGNhY2hlZFNjcmlwdFN0YXR1c2VzLmdldChzcmMpO1xuICAgIGlmIChjYWNoZWRTY3JpcHRTdGF0dXMgPT09IFwicmVhZHlcIiB8fCBjYWNoZWRTY3JpcHRTdGF0dXMgPT09IFwiZXJyb3JcIikge1xuICAgICAgc2V0U3RhdHVzKGNhY2hlZFNjcmlwdFN0YXR1cyk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIGNvbnN0IHNjcmlwdCA9IGdldFNjcmlwdE5vZGUoc3JjKTtcbiAgICBsZXQgc2NyaXB0Tm9kZSA9IHNjcmlwdC5ub2RlO1xuICAgIGlmICghc2NyaXB0Tm9kZSkge1xuICAgICAgc2NyaXB0Tm9kZSA9IGRvY3VtZW50LmNyZWF0ZUVsZW1lbnQoXCJzY3JpcHRcIik7XG4gICAgICBzY3JpcHROb2RlLnNyYyA9IHNyYztcbiAgICAgIHNjcmlwdE5vZGUuYXN5bmMgPSB0cnVlO1xuICAgICAgaWYgKG9wdGlvbnMgPT0gbnVsbCA/IHZvaWQgMCA6IG9wdGlvbnMuaWQpIHtcbiAgICAgICAgc2NyaXB0Tm9kZS5pZCA9IG9wdGlvbnMuaWQ7XG4gICAgICB9XG4gICAgICBzY3JpcHROb2RlLnNldEF0dHJpYnV0ZShcImRhdGEtc3RhdHVzXCIsIFwibG9hZGluZ1wiKTtcbiAgICAgIGRvY3VtZW50LmJvZHkuYXBwZW5kQ2hpbGQoc2NyaXB0Tm9kZSk7XG4gICAgICBjb25zdCBzZXRBdHRyaWJ1dGVGcm9tRXZlbnQgPSAoZXZlbnQpID0+IHtcbiAgICAgICAgY29uc3Qgc2NyaXB0U3RhdHVzID0gZXZlbnQudHlwZSA9PT0gXCJsb2FkXCIgPyBcInJlYWR5XCIgOiBcImVycm9yXCI7XG4gICAgICAgIHNjcmlwdE5vZGUgPT0gbnVsbCA/IHZvaWQgMCA6IHNjcmlwdE5vZGUuc2V0QXR0cmlidXRlKFwiZGF0YS1zdGF0dXNcIiwgc2NyaXB0U3RhdHVzKTtcbiAgICAgIH07XG4gICAgICBzY3JpcHROb2RlLmFkZEV2ZW50TGlzdGVuZXIoXCJsb2FkXCIsIHNldEF0dHJpYnV0ZUZyb21FdmVudCk7XG4gICAgICBzY3JpcHROb2RlLmFkZEV2ZW50TGlzdGVuZXIoXCJlcnJvclwiLCBzZXRBdHRyaWJ1dGVGcm9tRXZlbnQpO1xuICAgIH0gZWxzZSB7XG4gICAgICBzZXRTdGF0dXMoc2NyaXB0LnN0YXR1cyA/PyBjYWNoZWRTY3JpcHRTdGF0dXMgPz8gXCJsb2FkaW5nXCIpO1xuICAgIH1cbiAgICBjb25zdCBzZXRTdGF0ZUZyb21FdmVudCA9IChldmVudCkgPT4ge1xuICAgICAgY29uc3QgbmV3U3RhdHVzID0gZXZlbnQudHlwZSA9PT0gXCJsb2FkXCIgPyBcInJlYWR5XCIgOiBcImVycm9yXCI7XG4gICAgICBzZXRTdGF0dXMobmV3U3RhdHVzKTtcbiAgICAgIGNhY2hlZFNjcmlwdFN0YXR1c2VzLnNldChzcmMsIG5ld1N0YXR1cyk7XG4gICAgfTtcbiAgICBzY3JpcHROb2RlLmFkZEV2ZW50TGlzdGVuZXIoXCJsb2FkXCIsIHNldFN0YXRlRnJvbUV2ZW50KTtcbiAgICBzY3JpcHROb2RlLmFkZEV2ZW50TGlzdGVuZXIoXCJlcnJvclwiLCBzZXRTdGF0ZUZyb21FdmVudCk7XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIGlmIChzY3JpcHROb2RlKSB7XG4gICAgICAgIHNjcmlwdE5vZGUucmVtb3ZlRXZlbnRMaXN0ZW5lcihcImxvYWRcIiwgc2V0U3RhdGVGcm9tRXZlbnQpO1xuICAgICAgICBzY3JpcHROb2RlLnJlbW92ZUV2ZW50TGlzdGVuZXIoXCJlcnJvclwiLCBzZXRTdGF0ZUZyb21FdmVudCk7XG4gICAgICB9XG4gICAgICBpZiAoc2NyaXB0Tm9kZSAmJiAob3B0aW9ucyA9PSBudWxsID8gdm9pZCAwIDogb3B0aW9ucy5yZW1vdmVPblVubW91bnQpKSB7XG4gICAgICAgIHNjcmlwdE5vZGUucmVtb3ZlKCk7XG4gICAgICAgIGNhY2hlZFNjcmlwdFN0YXR1c2VzLmRlbGV0ZShzcmMpO1xuICAgICAgfVxuICAgIH07XG4gIH0sIFtzcmMsIG9wdGlvbnMgPT0gbnVsbCA/IHZvaWQgMCA6IG9wdGlvbnMuc2hvdWxkUHJldmVudExvYWQsIG9wdGlvbnMgPT0gbnVsbCA/IHZvaWQgMCA6IG9wdGlvbnMucmVtb3ZlT25Vbm1vdW50LCBvcHRpb25zID09IG51bGwgPyB2b2lkIDAgOiBvcHRpb25zLmlkXSk7XG4gIHJldHVybiBzdGF0dXM7XG59XG52YXIgSVNfU0VSVkVSNSA9IHR5cGVvZiB3aW5kb3cgPT09IFwidW5kZWZpbmVkXCI7XG5mdW5jdGlvbiB1c2VTY3JvbGxMb2NrKG9wdGlvbnMgPSB7fSkge1xuICBjb25zdCB7IGF1dG9Mb2NrID0gdHJ1ZSwgbG9ja1RhcmdldCwgd2lkdGhSZWZsb3cgPSB0cnVlIH0gPSBvcHRpb25zO1xuICBjb25zdCBbaXNMb2NrZWQsIHNldElzTG9ja2VkXSA9IHVzZVN0YXRlKGZhbHNlKTtcbiAgY29uc3QgdGFyZ2V0ID0gdXNlUmVmKG51bGwpO1xuICBjb25zdCBvcmlnaW5hbFN0eWxlID0gdXNlUmVmKG51bGwpO1xuICBjb25zdCBsb2NrID0gKCkgPT4ge1xuICAgIGlmICh0YXJnZXQuY3VycmVudCkge1xuICAgICAgY29uc3QgeyBvdmVyZmxvdywgcGFkZGluZ1JpZ2h0IH0gPSB0YXJnZXQuY3VycmVudC5zdHlsZTtcbiAgICAgIG9yaWdpbmFsU3R5bGUuY3VycmVudCA9IHsgb3ZlcmZsb3csIHBhZGRpbmdSaWdodCB9O1xuICAgICAgaWYgKHdpZHRoUmVmbG93KSB7XG4gICAgICAgIGNvbnN0IG9mZnNldFdpZHRoID0gdGFyZ2V0LmN1cnJlbnQgPT09IGRvY3VtZW50LmJvZHkgPyB3aW5kb3cuaW5uZXJXaWR0aCA6IHRhcmdldC5jdXJyZW50Lm9mZnNldFdpZHRoO1xuICAgICAgICBjb25zdCBjdXJyZW50UGFkZGluZ1JpZ2h0ID0gcGFyc2VJbnQod2luZG93LmdldENvbXB1dGVkU3R5bGUodGFyZ2V0LmN1cnJlbnQpLnBhZGRpbmdSaWdodCwgMTApIHx8IDA7XG4gICAgICAgIGNvbnN0IHNjcm9sbGJhcldpZHRoID0gb2Zmc2V0V2lkdGggLSB0YXJnZXQuY3VycmVudC5zY3JvbGxXaWR0aDtcbiAgICAgICAgdGFyZ2V0LmN1cnJlbnQuc3R5bGUucGFkZGluZ1JpZ2h0ID0gYCR7c2Nyb2xsYmFyV2lkdGggKyBjdXJyZW50UGFkZGluZ1JpZ2h0fXB4YDtcbiAgICAgIH1cbiAgICAgIHRhcmdldC5jdXJyZW50LnN0eWxlLm92ZXJmbG93ID0gXCJoaWRkZW5cIjtcbiAgICAgIHNldElzTG9ja2VkKHRydWUpO1xuICAgIH1cbiAgfTtcbiAgY29uc3QgdW5sb2NrID0gKCkgPT4ge1xuICAgIGlmICh0YXJnZXQuY3VycmVudCAmJiBvcmlnaW5hbFN0eWxlLmN1cnJlbnQpIHtcbiAgICAgIHRhcmdldC5jdXJyZW50LnN0eWxlLm92ZXJmbG93ID0gb3JpZ2luYWxTdHlsZS5jdXJyZW50Lm92ZXJmbG93O1xuICAgICAgaWYgKHdpZHRoUmVmbG93KSB7XG4gICAgICAgIHRhcmdldC5jdXJyZW50LnN0eWxlLnBhZGRpbmdSaWdodCA9IG9yaWdpbmFsU3R5bGUuY3VycmVudC5wYWRkaW5nUmlnaHQ7XG4gICAgICB9XG4gICAgfVxuICAgIHNldElzTG9ja2VkKGZhbHNlKTtcbiAgfTtcbiAgdXNlSXNvbW9ycGhpY0xheW91dEVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKElTX1NFUlZFUjUpXG4gICAgICByZXR1cm47XG4gICAgaWYgKGxvY2tUYXJnZXQpIHtcbiAgICAgIHRhcmdldC5jdXJyZW50ID0gdHlwZW9mIGxvY2tUYXJnZXQgPT09IFwic3RyaW5nXCIgPyBkb2N1bWVudC5xdWVyeVNlbGVjdG9yKGxvY2tUYXJnZXQpIDogbG9ja1RhcmdldDtcbiAgICB9XG4gICAgaWYgKCF0YXJnZXQuY3VycmVudCkge1xuICAgICAgdGFyZ2V0LmN1cnJlbnQgPSBkb2N1bWVudC5ib2R5O1xuICAgIH1cbiAgICBpZiAoYXV0b0xvY2spIHtcbiAgICAgIGxvY2soKTtcbiAgICB9XG4gICAgcmV0dXJuICgpID0+IHtcbiAgICAgIHVubG9jaygpO1xuICAgIH07XG4gIH0sIFthdXRvTG9jaywgbG9ja1RhcmdldCwgd2lkdGhSZWZsb3ddKTtcbiAgcmV0dXJuIHsgaXNMb2NrZWQsIGxvY2ssIHVubG9jayB9O1xufVxudmFyIElTX1NFUlZFUjYgPSB0eXBlb2Ygd2luZG93ID09PSBcInVuZGVmaW5lZFwiO1xuZnVuY3Rpb24gdXNlU2Vzc2lvblN0b3JhZ2Uoa2V5LCBpbml0aWFsVmFsdWUsIG9wdGlvbnMgPSB7fSkge1xuICBjb25zdCB7IGluaXRpYWxpemVXaXRoVmFsdWUgPSB0cnVlIH0gPSBvcHRpb25zO1xuICBjb25zdCBzZXJpYWxpemVyID0gdXNlQ2FsbGJhY2soXG4gICAgKHZhbHVlKSA9PiB7XG4gICAgICBpZiAob3B0aW9ucy5zZXJpYWxpemVyKSB7XG4gICAgICAgIHJldHVybiBvcHRpb25zLnNlcmlhbGl6ZXIodmFsdWUpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcbiAgICB9LFxuICAgIFtvcHRpb25zXVxuICApO1xuICBjb25zdCBkZXNlcmlhbGl6ZXIgPSB1c2VDYWxsYmFjayhcbiAgICAodmFsdWUpID0+IHtcbiAgICAgIGlmIChvcHRpb25zLmRlc2VyaWFsaXplcikge1xuICAgICAgICByZXR1cm4gb3B0aW9ucy5kZXNlcmlhbGl6ZXIodmFsdWUpO1xuICAgICAgfVxuICAgICAgaWYgKHZhbHVlID09PSBcInVuZGVmaW5lZFwiKSB7XG4gICAgICAgIHJldHVybiB2b2lkIDA7XG4gICAgICB9XG4gICAgICBjb25zdCBkZWZhdWx0VmFsdWUgPSBpbml0aWFsVmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbiA/IGluaXRpYWxWYWx1ZSgpIDogaW5pdGlhbFZhbHVlO1xuICAgICAgbGV0IHBhcnNlZDtcbiAgICAgIHRyeSB7XG4gICAgICAgIHBhcnNlZCA9IEpTT04ucGFyc2UodmFsdWUpO1xuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIkVycm9yIHBhcnNpbmcgSlNPTjpcIiwgZXJyb3IpO1xuICAgICAgICByZXR1cm4gZGVmYXVsdFZhbHVlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHBhcnNlZDtcbiAgICB9LFxuICAgIFtvcHRpb25zLCBpbml0aWFsVmFsdWVdXG4gICk7XG4gIGNvbnN0IHJlYWRWYWx1ZSA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICBjb25zdCBpbml0aWFsVmFsdWVUb1VzZSA9IGluaXRpYWxWYWx1ZSBpbnN0YW5jZW9mIEZ1bmN0aW9uID8gaW5pdGlhbFZhbHVlKCkgOiBpbml0aWFsVmFsdWU7XG4gICAgaWYgKElTX1NFUlZFUjYpIHtcbiAgICAgIHJldHVybiBpbml0aWFsVmFsdWVUb1VzZTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJhdyA9IHdpbmRvdy5zZXNzaW9uU3RvcmFnZS5nZXRJdGVtKGtleSk7XG4gICAgICByZXR1cm4gcmF3ID8gZGVzZXJpYWxpemVyKHJhdykgOiBpbml0aWFsVmFsdWVUb1VzZTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS53YXJuKGBFcnJvciByZWFkaW5nIHNlc3Npb25TdG9yYWdlIGtleSBcXHUyMDFDJHtrZXl9XFx1MjAxRDpgLCBlcnJvcik7XG4gICAgICByZXR1cm4gaW5pdGlhbFZhbHVlVG9Vc2U7XG4gICAgfVxuICB9LCBbaW5pdGlhbFZhbHVlLCBrZXksIGRlc2VyaWFsaXplcl0pO1xuICBjb25zdCBbc3RvcmVkVmFsdWUsIHNldFN0b3JlZFZhbHVlXSA9IHVzZVN0YXRlKCgpID0+IHtcbiAgICBpZiAoaW5pdGlhbGl6ZVdpdGhWYWx1ZSkge1xuICAgICAgcmV0dXJuIHJlYWRWYWx1ZSgpO1xuICAgIH1cbiAgICByZXR1cm4gaW5pdGlhbFZhbHVlIGluc3RhbmNlb2YgRnVuY3Rpb24gPyBpbml0aWFsVmFsdWUoKSA6IGluaXRpYWxWYWx1ZTtcbiAgfSk7XG4gIGNvbnN0IHNldFZhbHVlID0gdXNlRXZlbnRDYWxsYmFjaygodmFsdWUpID0+IHtcbiAgICBpZiAoSVNfU0VSVkVSNikge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgVHJpZWQgc2V0dGluZyBzZXNzaW9uU3RvcmFnZSBrZXkgXFx1MjAxQyR7a2V5fVxcdTIwMUQgZXZlbiB0aG91Z2ggZW52aXJvbm1lbnQgaXMgbm90IGEgY2xpZW50YFxuICAgICAgKTtcbiAgICB9XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IG5ld1ZhbHVlID0gdmFsdWUgaW5zdGFuY2VvZiBGdW5jdGlvbiA/IHZhbHVlKHJlYWRWYWx1ZSgpKSA6IHZhbHVlO1xuICAgICAgd2luZG93LnNlc3Npb25TdG9yYWdlLnNldEl0ZW0oa2V5LCBzZXJpYWxpemVyKG5ld1ZhbHVlKSk7XG4gICAgICBzZXRTdG9yZWRWYWx1ZShuZXdWYWx1ZSk7XG4gICAgICB3aW5kb3cuZGlzcGF0Y2hFdmVudChuZXcgU3RvcmFnZUV2ZW50KFwic2Vzc2lvbi1zdG9yYWdlXCIsIHsga2V5IH0pKTtcbiAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgY29uc29sZS53YXJuKGBFcnJvciBzZXR0aW5nIHNlc3Npb25TdG9yYWdlIGtleSBcXHUyMDFDJHtrZXl9XFx1MjAxRDpgLCBlcnJvcik7XG4gICAgfVxuICB9KTtcbiAgY29uc3QgcmVtb3ZlVmFsdWUgPSB1c2VFdmVudENhbGxiYWNrKCgpID0+IHtcbiAgICBpZiAoSVNfU0VSVkVSNikge1xuICAgICAgY29uc29sZS53YXJuKFxuICAgICAgICBgVHJpZWQgcmVtb3Zpbmcgc2Vzc2lvblN0b3JhZ2Uga2V5IFxcdTIwMUMke2tleX1cXHUyMDFEIGV2ZW4gdGhvdWdoIGVudmlyb25tZW50IGlzIG5vdCBhIGNsaWVudGBcbiAgICAgICk7XG4gICAgfVxuICAgIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IGluaXRpYWxWYWx1ZSBpbnN0YW5jZW9mIEZ1bmN0aW9uID8gaW5pdGlhbFZhbHVlKCkgOiBpbml0aWFsVmFsdWU7XG4gICAgd2luZG93LnNlc3Npb25TdG9yYWdlLnJlbW92ZUl0ZW0oa2V5KTtcbiAgICBzZXRTdG9yZWRWYWx1ZShkZWZhdWx0VmFsdWUpO1xuICAgIHdpbmRvdy5kaXNwYXRjaEV2ZW50KG5ldyBTdG9yYWdlRXZlbnQoXCJzZXNzaW9uLXN0b3JhZ2VcIiwgeyBrZXkgfSkpO1xuICB9KTtcbiAgdXNlRWZmZWN0KCgpID0+IHtcbiAgICBzZXRTdG9yZWRWYWx1ZShyZWFkVmFsdWUoKSk7XG4gIH0sIFtrZXldKTtcbiAgY29uc3QgaGFuZGxlU3RvcmFnZUNoYW5nZSA9IHVzZUNhbGxiYWNrKFxuICAgIChldmVudCkgPT4ge1xuICAgICAgaWYgKGV2ZW50LmtleSAmJiBldmVudC5rZXkgIT09IGtleSkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG4gICAgICBzZXRTdG9yZWRWYWx1ZShyZWFkVmFsdWUoKSk7XG4gICAgfSxcbiAgICBba2V5LCByZWFkVmFsdWVdXG4gICk7XG4gIHVzZUV2ZW50TGlzdGVuZXIoXCJzdG9yYWdlXCIsIGhhbmRsZVN0b3JhZ2VDaGFuZ2UpO1xuICB1c2VFdmVudExpc3RlbmVyKFwic2Vzc2lvbi1zdG9yYWdlXCIsIGhhbmRsZVN0b3JhZ2VDaGFuZ2UpO1xuICByZXR1cm4gW3N0b3JlZFZhbHVlLCBzZXRWYWx1ZSwgcmVtb3ZlVmFsdWVdO1xufVxuZnVuY3Rpb24gdXNlU3RlcChtYXhTdGVwKSB7XG4gIGNvbnN0IFtjdXJyZW50U3RlcCwgc2V0Q3VycmVudFN0ZXBdID0gdXNlU3RhdGUoMSk7XG4gIGNvbnN0IGNhbkdvVG9OZXh0U3RlcCA9IGN1cnJlbnRTdGVwICsgMSA8PSBtYXhTdGVwO1xuICBjb25zdCBjYW5Hb1RvUHJldlN0ZXAgPSBjdXJyZW50U3RlcCAtIDEgPiAwO1xuICBjb25zdCBzZXRTdGVwID0gdXNlQ2FsbGJhY2soXG4gICAgKHN0ZXApID0+IHtcbiAgICAgIGNvbnN0IG5ld1N0ZXAgPSBzdGVwIGluc3RhbmNlb2YgRnVuY3Rpb24gPyBzdGVwKGN1cnJlbnRTdGVwKSA6IHN0ZXA7XG4gICAgICBpZiAobmV3U3RlcCA+PSAxICYmIG5ld1N0ZXAgPD0gbWF4U3RlcCkge1xuICAgICAgICBzZXRDdXJyZW50U3RlcChuZXdTdGVwKTtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiU3RlcCBub3QgdmFsaWRcIik7XG4gICAgfSxcbiAgICBbbWF4U3RlcCwgY3VycmVudFN0ZXBdXG4gICk7XG4gIGNvbnN0IGdvVG9OZXh0U3RlcCA9IHVzZUNhbGxiYWNrKCgpID0+IHtcbiAgICBpZiAoY2FuR29Ub05leHRTdGVwKSB7XG4gICAgICBzZXRDdXJyZW50U3RlcCgoc3RlcCkgPT4gc3RlcCArIDEpO1xuICAgIH1cbiAgfSwgW2NhbkdvVG9OZXh0U3RlcF0pO1xuICBjb25zdCBnb1RvUHJldlN0ZXAgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgaWYgKGNhbkdvVG9QcmV2U3RlcCkge1xuICAgICAgc2V0Q3VycmVudFN0ZXAoKHN0ZXApID0+IHN0ZXAgLSAxKTtcbiAgICB9XG4gIH0sIFtjYW5Hb1RvUHJldlN0ZXBdKTtcbiAgY29uc3QgcmVzZXQgPSB1c2VDYWxsYmFjaygoKSA9PiB7XG4gICAgc2V0Q3VycmVudFN0ZXAoMSk7XG4gIH0sIFtdKTtcbiAgcmV0dXJuIFtcbiAgICBjdXJyZW50U3RlcCxcbiAgICB7XG4gICAgICBnb1RvTmV4dFN0ZXAsXG4gICAgICBnb1RvUHJldlN0ZXAsXG4gICAgICBjYW5Hb1RvTmV4dFN0ZXAsXG4gICAgICBjYW5Hb1RvUHJldlN0ZXAsXG4gICAgICBzZXRTdGVwLFxuICAgICAgcmVzZXRcbiAgICB9XG4gIF07XG59XG5cbi8vIHNyYy91c2VUZXJuYXJ5RGFya01vZGUvdXNlVGVybmFyeURhcmtNb2RlLnRzXG52YXIgQ09MT1JfU0NIRU1FX1FVRVJZMiA9IFwiKHByZWZlcnMtY29sb3Itc2NoZW1lOiBkYXJrKVwiO1xudmFyIExPQ0FMX1NUT1JBR0VfS0VZMiA9IFwidXNlaG9va3MtdHMtdGVybmFyeS1kYXJrLW1vZGVcIjtcbmZ1bmN0aW9uIHVzZVRlcm5hcnlEYXJrTW9kZSh7XG4gIGRlZmF1bHRWYWx1ZSA9IFwic3lzdGVtXCIsXG4gIGxvY2FsU3RvcmFnZUtleSA9IExPQ0FMX1NUT1JBR0VfS0VZMixcbiAgaW5pdGlhbGl6ZVdpdGhWYWx1ZSA9IHRydWVcbn0gPSB7fSkge1xuICBjb25zdCBpc0RhcmtPUyA9IHVzZU1lZGlhUXVlcnkoQ09MT1JfU0NIRU1FX1FVRVJZMiwgeyBpbml0aWFsaXplV2l0aFZhbHVlIH0pO1xuICBjb25zdCBbbW9kZSwgc2V0TW9kZV0gPSB1c2VMb2NhbFN0b3JhZ2UobG9jYWxTdG9yYWdlS2V5LCBkZWZhdWx0VmFsdWUsIHtcbiAgICBpbml0aWFsaXplV2l0aFZhbHVlXG4gIH0pO1xuICBjb25zdCBpc0RhcmtNb2RlID0gbW9kZSA9PT0gXCJkYXJrXCIgfHwgbW9kZSA9PT0gXCJzeXN0ZW1cIiAmJiBpc0RhcmtPUztcbiAgY29uc3QgdG9nZ2xlVGVybmFyeURhcmtNb2RlID0gKCkgPT4ge1xuICAgIGNvbnN0IG1vZGVzID0gW1wibGlnaHRcIiwgXCJzeXN0ZW1cIiwgXCJkYXJrXCJdO1xuICAgIHNldE1vZGUoKHByZXZNb2RlKSA9PiB7XG4gICAgICBjb25zdCBuZXh0SW5kZXggPSAobW9kZXMuaW5kZXhPZihwcmV2TW9kZSkgKyAxKSAlIG1vZGVzLmxlbmd0aDtcbiAgICAgIHJldHVybiBtb2Rlc1tuZXh0SW5kZXhdO1xuICAgIH0pO1xuICB9O1xuICByZXR1cm4ge1xuICAgIGlzRGFya01vZGUsXG4gICAgdGVybmFyeURhcmtNb2RlOiBtb2RlLFxuICAgIHNldFRlcm5hcnlEYXJrTW9kZTogc2V0TW9kZSxcbiAgICB0b2dnbGVUZXJuYXJ5RGFya01vZGVcbiAgfTtcbn1cbmZ1bmN0aW9uIHVzZVRpbWVvdXQoY2FsbGJhY2ssIGRlbGF5KSB7XG4gIGNvbnN0IHNhdmVkQ2FsbGJhY2sgPSB1c2VSZWYoY2FsbGJhY2spO1xuICB1c2VJc29tb3JwaGljTGF5b3V0RWZmZWN0KCgpID0+IHtcbiAgICBzYXZlZENhbGxiYWNrLmN1cnJlbnQgPSBjYWxsYmFjaztcbiAgfSwgW2NhbGxiYWNrXSk7XG4gIHVzZUVmZmVjdCgoKSA9PiB7XG4gICAgaWYgKCFkZWxheSAmJiBkZWxheSAhPT0gMCkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBjb25zdCBpZCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgc2F2ZWRDYWxsYmFjay5jdXJyZW50KCk7XG4gICAgfSwgZGVsYXkpO1xuICAgIHJldHVybiAoKSA9PiB7XG4gICAgICBjbGVhclRpbWVvdXQoaWQpO1xuICAgIH07XG4gIH0sIFtkZWxheV0pO1xufVxuZnVuY3Rpb24gdXNlVG9nZ2xlKGRlZmF1bHRWYWx1ZSkge1xuICBjb25zdCBbdmFsdWUsIHNldFZhbHVlXSA9IHVzZVN0YXRlKCEhZGVmYXVsdFZhbHVlKTtcbiAgY29uc3QgdG9nZ2xlID0gdXNlQ2FsbGJhY2soKCkgPT4ge1xuICAgIHNldFZhbHVlKCh4KSA9PiAheCk7XG4gIH0sIFtdKTtcbiAgcmV0dXJuIFt2YWx1ZSwgdG9nZ2xlLCBzZXRWYWx1ZV07XG59XG52YXIgSVNfU0VSVkVSNyA9IHR5cGVvZiB3aW5kb3cgPT09IFwidW5kZWZpbmVkXCI7XG5mdW5jdGlvbiB1c2VXaW5kb3dTaXplKG9wdGlvbnMgPSB7fSkge1xuICBsZXQgeyBpbml0aWFsaXplV2l0aFZhbHVlID0gdHJ1ZSB9ID0gb3B0aW9ucztcbiAgaWYgKElTX1NFUlZFUjcpIHtcbiAgICBpbml0aWFsaXplV2l0aFZhbHVlID0gZmFsc2U7XG4gIH1cbiAgY29uc3QgW3dpbmRvd1NpemUsIHNldFdpbmRvd1NpemVdID0gdXNlU3RhdGUoKCkgPT4ge1xuICAgIGlmIChpbml0aWFsaXplV2l0aFZhbHVlKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICB3aWR0aDogd2luZG93LmlubmVyV2lkdGgsXG4gICAgICAgIGhlaWdodDogd2luZG93LmlubmVySGVpZ2h0XG4gICAgICB9O1xuICAgIH1cbiAgICByZXR1cm4ge1xuICAgICAgd2lkdGg6IHZvaWQgMCxcbiAgICAgIGhlaWdodDogdm9pZCAwXG4gICAgfTtcbiAgfSk7XG4gIGNvbnN0IGRlYm91bmNlZFNldFdpbmRvd1NpemUgPSB1c2VEZWJvdW5jZUNhbGxiYWNrKFxuICAgIHNldFdpbmRvd1NpemUsXG4gICAgb3B0aW9ucy5kZWJvdW5jZURlbGF5XG4gICk7XG4gIGZ1bmN0aW9uIGhhbmRsZVNpemUoKSB7XG4gICAgY29uc3Qgc2V0U2l6ZSA9IG9wdGlvbnMuZGVib3VuY2VEZWxheSA/IGRlYm91bmNlZFNldFdpbmRvd1NpemUgOiBzZXRXaW5kb3dTaXplO1xuICAgIHNldFNpemUoe1xuICAgICAgd2lkdGg6IHdpbmRvdy5pbm5lcldpZHRoLFxuICAgICAgaGVpZ2h0OiB3aW5kb3cuaW5uZXJIZWlnaHRcbiAgICB9KTtcbiAgfVxuICB1c2VFdmVudExpc3RlbmVyKFwicmVzaXplXCIsIGhhbmRsZVNpemUpO1xuICB1c2VJc29tb3JwaGljTGF5b3V0RWZmZWN0KCgpID0+IHtcbiAgICBoYW5kbGVTaXplKCk7XG4gIH0sIFtdKTtcbiAgcmV0dXJuIHdpbmRvd1NpemU7XG59XG5cbmV4cG9ydCB7IHVzZUJvb2xlYW4sIHVzZUNsaWNrQW55V2hlcmUsIHVzZUNvcHlUb0NsaXBib2FyZCwgdXNlQ291bnRkb3duLCB1c2VDb3VudGVyLCB1c2VEYXJrTW9kZSwgdXNlRGVib3VuY2VDYWxsYmFjaywgdXNlRGVib3VuY2VWYWx1ZSwgdXNlRG9jdW1lbnRUaXRsZSwgdXNlRXZlbnRDYWxsYmFjaywgdXNlRXZlbnRMaXN0ZW5lciwgdXNlSG92ZXIsIHVzZUludGVyc2VjdGlvbk9ic2VydmVyLCB1c2VJbnRlcnZhbCwgdXNlSXNDbGllbnQsIHVzZUlzTW91bnRlZCwgdXNlSXNvbW9ycGhpY0xheW91dEVmZmVjdCwgdXNlTG9jYWxTdG9yYWdlLCB1c2VNYXAsIHVzZU1lZGlhUXVlcnksIHVzZU9uQ2xpY2tPdXRzaWRlLCB1c2VSZWFkTG9jYWxTdG9yYWdlLCB1c2VSZXNpemVPYnNlcnZlciwgdXNlU2NyZWVuLCB1c2VTY3JpcHQsIHVzZVNjcm9sbExvY2ssIHVzZVNlc3Npb25TdG9yYWdlLCB1c2VTdGVwLCB1c2VUZXJuYXJ5RGFya01vZGUsIHVzZVRpbWVvdXQsIHVzZVRvZ2dsZSwgdXNlVW5tb3VudCwgdXNlV2luZG93U2l6ZSB9O1xuIiwiLyoqXG4gKiBAbGljZW5zZSBSZWFjdFxuICogcmVhY3QtanN4LXJ1bnRpbWUucHJvZHVjdGlvbi5qc1xuICpcbiAqIENvcHlyaWdodCAoYykgTWV0YSBQbGF0Zm9ybXMsIEluYy4gYW5kIGFmZmlsaWF0ZXMuXG4gKlxuICogVGhpcyBzb3VyY2UgY29kZSBpcyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIGxpY2Vuc2UgZm91bmQgaW4gdGhlXG4gKiBMSUNFTlNFIGZpbGUgaW4gdGhlIHJvb3QgZGlyZWN0b3J5IG9mIHRoaXMgc291cmNlIHRyZWUuXG4gKi9cblxuXCJ1c2Ugc3RyaWN0XCI7XG52YXIgUkVBQ1RfRUxFTUVOVF9UWVBFID0gU3ltYm9sLmZvcihcInJlYWN0LnRyYW5zaXRpb25hbC5lbGVtZW50XCIpLFxuICBSRUFDVF9GUkFHTUVOVF9UWVBFID0gU3ltYm9sLmZvcihcInJlYWN0LmZyYWdtZW50XCIpO1xuZnVuY3Rpb24ganN4UHJvZCh0eXBlLCBjb25maWcsIG1heWJlS2V5KSB7XG4gIHZhciBrZXkgPSBudWxsO1xuICB2b2lkIDAgIT09IG1heWJlS2V5ICYmIChrZXkgPSBcIlwiICsgbWF5YmVLZXkpO1xuICB2b2lkIDAgIT09IGNvbmZpZy5rZXkgJiYgKGtleSA9IFwiXCIgKyBjb25maWcua2V5KTtcbiAgaWYgKFwia2V5XCIgaW4gY29uZmlnKSB7XG4gICAgbWF5YmVLZXkgPSB7fTtcbiAgICBmb3IgKHZhciBwcm9wTmFtZSBpbiBjb25maWcpXG4gICAgICBcImtleVwiICE9PSBwcm9wTmFtZSAmJiAobWF5YmVLZXlbcHJvcE5hbWVdID0gY29uZmlnW3Byb3BOYW1lXSk7XG4gIH0gZWxzZSBtYXliZUtleSA9IGNvbmZpZztcbiAgY29uZmlnID0gbWF5YmVLZXkucmVmO1xuICByZXR1cm4ge1xuICAgICQkdHlwZW9mOiBSRUFDVF9FTEVNRU5UX1RZUEUsXG4gICAgdHlwZTogdHlwZSxcbiAgICBrZXk6IGtleSxcbiAgICByZWY6IHZvaWQgMCAhPT0gY29uZmlnID8gY29uZmlnIDogbnVsbCxcbiAgICBwcm9wczogbWF5YmVLZXlcbiAgfTtcbn1cbmV4cG9ydHMuRnJhZ21lbnQgPSBSRUFDVF9GUkFHTUVOVF9UWVBFO1xuZXhwb3J0cy5qc3ggPSBqc3hQcm9kO1xuZXhwb3J0cy5qc3hzID0ganN4UHJvZDtcbiIsImltcG9ydCBSZWFjdCBmcm9tICdyZWFjdCc7XG5cbnZhciBpc0NoZWNrQm94SW5wdXQgPSAoZWxlbWVudCkgPT4gZWxlbWVudC50eXBlID09PSAnY2hlY2tib3gnO1xuXG52YXIgaXNEYXRlT2JqZWN0ID0gKHZhbHVlKSA9PiB2YWx1ZSBpbnN0YW5jZW9mIERhdGU7XG5cbnZhciBpc051bGxPclVuZGVmaW5lZCA9ICh2YWx1ZSkgPT4gdmFsdWUgPT0gbnVsbDtcblxuY29uc3QgaXNPYmplY3RUeXBlID0gKHZhbHVlKSA9PiB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnO1xudmFyIGlzT2JqZWN0ID0gKHZhbHVlKSA9PiAhaXNOdWxsT3JVbmRlZmluZWQodmFsdWUpICYmXG4gICAgIUFycmF5LmlzQXJyYXkodmFsdWUpICYmXG4gICAgaXNPYmplY3RUeXBlKHZhbHVlKSAmJlxuICAgICFpc0RhdGVPYmplY3QodmFsdWUpO1xuXG52YXIgZ2V0RXZlbnRWYWx1ZSA9IChldmVudCkgPT4gaXNPYmplY3QoZXZlbnQpICYmIGV2ZW50LnRhcmdldFxuICAgID8gaXNDaGVja0JveElucHV0KGV2ZW50LnRhcmdldClcbiAgICAgICAgPyBldmVudC50YXJnZXQuY2hlY2tlZFxuICAgICAgICA6IGV2ZW50LnRhcmdldC52YWx1ZVxuICAgIDogZXZlbnQ7XG5cbnZhciBnZXROb2RlUGFyZW50TmFtZSA9IChuYW1lKSA9PiBuYW1lLnN1YnN0cmluZygwLCBuYW1lLnNlYXJjaCgvXFwuXFxkKyhcXC58JCkvKSkgfHwgbmFtZTtcblxudmFyIGlzTmFtZUluRmllbGRBcnJheSA9IChuYW1lcywgbmFtZSkgPT4gbmFtZXMuaGFzKGdldE5vZGVQYXJlbnROYW1lKG5hbWUpKTtcblxudmFyIGlzUGxhaW5PYmplY3QgPSAodGVtcE9iamVjdCkgPT4ge1xuICAgIGNvbnN0IHByb3RvdHlwZUNvcHkgPSB0ZW1wT2JqZWN0LmNvbnN0cnVjdG9yICYmIHRlbXBPYmplY3QuY29uc3RydWN0b3IucHJvdG90eXBlO1xuICAgIHJldHVybiAoaXNPYmplY3QocHJvdG90eXBlQ29weSkgJiYgcHJvdG90eXBlQ29weS5oYXNPd25Qcm9wZXJ0eSgnaXNQcm90b3R5cGVPZicpKTtcbn07XG5cbnZhciBpc1dlYiA9IHR5cGVvZiB3aW5kb3cgIT09ICd1bmRlZmluZWQnICYmXG4gICAgdHlwZW9mIHdpbmRvdy5IVE1MRWxlbWVudCAhPT0gJ3VuZGVmaW5lZCcgJiZcbiAgICB0eXBlb2YgZG9jdW1lbnQgIT09ICd1bmRlZmluZWQnO1xuXG5mdW5jdGlvbiBjbG9uZU9iamVjdChkYXRhKSB7XG4gICAgbGV0IGNvcHk7XG4gICAgY29uc3QgaXNBcnJheSA9IEFycmF5LmlzQXJyYXkoZGF0YSk7XG4gICAgY29uc3QgaXNGaWxlTGlzdEluc3RhbmNlID0gdHlwZW9mIEZpbGVMaXN0ICE9PSAndW5kZWZpbmVkJyA/IGRhdGEgaW5zdGFuY2VvZiBGaWxlTGlzdCA6IGZhbHNlO1xuICAgIGlmIChkYXRhIGluc3RhbmNlb2YgRGF0ZSkge1xuICAgICAgICBjb3B5ID0gbmV3IERhdGUoZGF0YSk7XG4gICAgfVxuICAgIGVsc2UgaWYgKCEoaXNXZWIgJiYgKGRhdGEgaW5zdGFuY2VvZiBCbG9iIHx8IGlzRmlsZUxpc3RJbnN0YW5jZSkpICYmXG4gICAgICAgIChpc0FycmF5IHx8IGlzT2JqZWN0KGRhdGEpKSkge1xuICAgICAgICBjb3B5ID0gaXNBcnJheSA/IFtdIDogT2JqZWN0LmNyZWF0ZShPYmplY3QuZ2V0UHJvdG90eXBlT2YoZGF0YSkpO1xuICAgICAgICBpZiAoIWlzQXJyYXkgJiYgIWlzUGxhaW5PYmplY3QoZGF0YSkpIHtcbiAgICAgICAgICAgIGNvcHkgPSBkYXRhO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZm9yIChjb25zdCBrZXkgaW4gZGF0YSkge1xuICAgICAgICAgICAgICAgIGlmIChkYXRhLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgICAgICAgICAgY29weVtrZXldID0gY2xvbmVPYmplY3QoZGF0YVtrZXldKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgZWxzZSB7XG4gICAgICAgIHJldHVybiBkYXRhO1xuICAgIH1cbiAgICByZXR1cm4gY29weTtcbn1cblxudmFyIGlzS2V5ID0gKHZhbHVlKSA9PiAvXlxcdyokLy50ZXN0KHZhbHVlKTtcblxudmFyIGlzVW5kZWZpbmVkID0gKHZhbCkgPT4gdmFsID09PSB1bmRlZmluZWQ7XG5cbnZhciBjb21wYWN0ID0gKHZhbHVlKSA9PiBBcnJheS5pc0FycmF5KHZhbHVlKSA/IHZhbHVlLmZpbHRlcihCb29sZWFuKSA6IFtdO1xuXG52YXIgc3RyaW5nVG9QYXRoID0gKGlucHV0KSA9PiBjb21wYWN0KGlucHV0LnJlcGxhY2UoL1tcInwnXXxcXF0vZywgJycpLnNwbGl0KC9cXC58XFxbLykpO1xuXG52YXIgZ2V0ID0gKG9iamVjdCwgcGF0aCwgZGVmYXVsdFZhbHVlKSA9PiB7XG4gICAgaWYgKCFwYXRoIHx8ICFpc09iamVjdChvYmplY3QpKSB7XG4gICAgICAgIHJldHVybiBkZWZhdWx0VmFsdWU7XG4gICAgfVxuICAgIGNvbnN0IHJlc3VsdCA9IChpc0tleShwYXRoKSA/IFtwYXRoXSA6IHN0cmluZ1RvUGF0aChwYXRoKSkucmVkdWNlKChyZXN1bHQsIGtleSkgPT4gaXNOdWxsT3JVbmRlZmluZWQocmVzdWx0KSA/IHJlc3VsdCA6IHJlc3VsdFtrZXldLCBvYmplY3QpO1xuICAgIHJldHVybiBpc1VuZGVmaW5lZChyZXN1bHQpIHx8IHJlc3VsdCA9PT0gb2JqZWN0XG4gICAgICAgID8gaXNVbmRlZmluZWQob2JqZWN0W3BhdGhdKVxuICAgICAgICAgICAgPyBkZWZhdWx0VmFsdWVcbiAgICAgICAgICAgIDogb2JqZWN0W3BhdGhdXG4gICAgICAgIDogcmVzdWx0O1xufTtcblxudmFyIGlzQm9vbGVhbiA9ICh2YWx1ZSkgPT4gdHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbic7XG5cbnZhciBzZXQgPSAob2JqZWN0LCBwYXRoLCB2YWx1ZSkgPT4ge1xuICAgIGxldCBpbmRleCA9IC0xO1xuICAgIGNvbnN0IHRlbXBQYXRoID0gaXNLZXkocGF0aCkgPyBbcGF0aF0gOiBzdHJpbmdUb1BhdGgocGF0aCk7XG4gICAgY29uc3QgbGVuZ3RoID0gdGVtcFBhdGgubGVuZ3RoO1xuICAgIGNvbnN0IGxhc3RJbmRleCA9IGxlbmd0aCAtIDE7XG4gICAgd2hpbGUgKCsraW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgY29uc3Qga2V5ID0gdGVtcFBhdGhbaW5kZXhdO1xuICAgICAgICBsZXQgbmV3VmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgaWYgKGluZGV4ICE9PSBsYXN0SW5kZXgpIHtcbiAgICAgICAgICAgIGNvbnN0IG9ialZhbHVlID0gb2JqZWN0W2tleV07XG4gICAgICAgICAgICBuZXdWYWx1ZSA9XG4gICAgICAgICAgICAgICAgaXNPYmplY3Qob2JqVmFsdWUpIHx8IEFycmF5LmlzQXJyYXkob2JqVmFsdWUpXG4gICAgICAgICAgICAgICAgICAgID8gb2JqVmFsdWVcbiAgICAgICAgICAgICAgICAgICAgOiAhaXNOYU4oK3RlbXBQYXRoW2luZGV4ICsgMV0pXG4gICAgICAgICAgICAgICAgICAgICAgICA/IFtdXG4gICAgICAgICAgICAgICAgICAgICAgICA6IHt9O1xuICAgICAgICB9XG4gICAgICAgIGlmIChrZXkgPT09ICdfX3Byb3RvX18nIHx8IGtleSA9PT0gJ2NvbnN0cnVjdG9yJyB8fCBrZXkgPT09ICdwcm90b3R5cGUnKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgb2JqZWN0W2tleV0gPSBuZXdWYWx1ZTtcbiAgICAgICAgb2JqZWN0ID0gb2JqZWN0W2tleV07XG4gICAgfVxufTtcblxuY29uc3QgRVZFTlRTID0ge1xuICAgIEJMVVI6ICdibHVyJyxcbiAgICBGT0NVU19PVVQ6ICdmb2N1c291dCcsXG4gICAgQ0hBTkdFOiAnY2hhbmdlJyxcbn07XG5jb25zdCBWQUxJREFUSU9OX01PREUgPSB7XG4gICAgb25CbHVyOiAnb25CbHVyJyxcbiAgICBvbkNoYW5nZTogJ29uQ2hhbmdlJyxcbiAgICBvblN1Ym1pdDogJ29uU3VibWl0JyxcbiAgICBvblRvdWNoZWQ6ICdvblRvdWNoZWQnLFxuICAgIGFsbDogJ2FsbCcsXG59O1xuY29uc3QgSU5QVVRfVkFMSURBVElPTl9SVUxFUyA9IHtcbiAgICBtYXg6ICdtYXgnLFxuICAgIG1pbjogJ21pbicsXG4gICAgbWF4TGVuZ3RoOiAnbWF4TGVuZ3RoJyxcbiAgICBtaW5MZW5ndGg6ICdtaW5MZW5ndGgnLFxuICAgIHBhdHRlcm46ICdwYXR0ZXJuJyxcbiAgICByZXF1aXJlZDogJ3JlcXVpcmVkJyxcbiAgICB2YWxpZGF0ZTogJ3ZhbGlkYXRlJyxcbn07XG5cbmNvbnN0IEhvb2tGb3JtQ29udGV4dCA9IFJlYWN0LmNyZWF0ZUNvbnRleHQobnVsbCk7XG5Ib29rRm9ybUNvbnRleHQuZGlzcGxheU5hbWUgPSAnSG9va0Zvcm1Db250ZXh0Jztcbi8qKlxuICogVGhpcyBjdXN0b20gaG9vayBhbGxvd3MgeW91IHRvIGFjY2VzcyB0aGUgZm9ybSBjb250ZXh0LiB1c2VGb3JtQ29udGV4dCBpcyBpbnRlbmRlZCB0byBiZSB1c2VkIGluIGRlZXBseSBuZXN0ZWQgc3RydWN0dXJlcywgd2hlcmUgaXQgd291bGQgYmVjb21lIGluY29udmVuaWVudCB0byBwYXNzIHRoZSBjb250ZXh0IGFzIGEgcHJvcC4gVG8gYmUgdXNlZCB3aXRoIHtAbGluayBGb3JtUHJvdmlkZXJ9LlxuICpcbiAqIEByZW1hcmtzXG4gKiBbQVBJXShodHRwczovL3JlYWN0LWhvb2stZm9ybS5jb20vZG9jcy91c2Vmb3JtY29udGV4dCkg4oCiIFtEZW1vXShodHRwczovL2NvZGVzYW5kYm94LmlvL3MvcmVhY3QtaG9vay1mb3JtLXY3LWZvcm0tY29udGV4dC15dHVkaSlcbiAqXG4gKiBAcmV0dXJucyByZXR1cm4gYWxsIHVzZUZvcm0gbWV0aG9kc1xuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0c3hcbiAqIGZ1bmN0aW9uIEFwcCgpIHtcbiAqICAgY29uc3QgbWV0aG9kcyA9IHVzZUZvcm0oKTtcbiAqICAgY29uc3Qgb25TdWJtaXQgPSBkYXRhID0+IGNvbnNvbGUubG9nKGRhdGEpO1xuICpcbiAqICAgcmV0dXJuIChcbiAqICAgICA8Rm9ybVByb3ZpZGVyIHsuLi5tZXRob2RzfSA+XG4gKiAgICAgICA8Zm9ybSBvblN1Ym1pdD17bWV0aG9kcy5oYW5kbGVTdWJtaXQob25TdWJtaXQpfT5cbiAqICAgICAgICAgPE5lc3RlZElucHV0IC8+XG4gKiAgICAgICAgIDxpbnB1dCB0eXBlPVwic3VibWl0XCIgLz5cbiAqICAgICAgIDwvZm9ybT5cbiAqICAgICA8L0Zvcm1Qcm92aWRlcj5cbiAqICAgKTtcbiAqIH1cbiAqXG4gKiAgZnVuY3Rpb24gTmVzdGVkSW5wdXQoKSB7XG4gKiAgIGNvbnN0IHsgcmVnaXN0ZXIgfSA9IHVzZUZvcm1Db250ZXh0KCk7IC8vIHJldHJpZXZlIGFsbCBob29rIG1ldGhvZHNcbiAqICAgcmV0dXJuIDxpbnB1dCB7Li4ucmVnaXN0ZXIoXCJ0ZXN0XCIpfSAvPjtcbiAqIH1cbiAqIGBgYFxuICovXG5jb25zdCB1c2VGb3JtQ29udGV4dCA9ICgpID0+IFJlYWN0LnVzZUNvbnRleHQoSG9va0Zvcm1Db250ZXh0KTtcbi8qKlxuICogQSBwcm92aWRlciBjb21wb25lbnQgdGhhdCBwcm9wYWdhdGVzIHRoZSBgdXNlRm9ybWAgbWV0aG9kcyB0byBhbGwgY2hpbGRyZW4gY29tcG9uZW50cyB2aWEgW1JlYWN0IENvbnRleHRdKGh0dHBzOi8vcmVhY3QuZGV2L3JlZmVyZW5jZS9yZWFjdC91c2VDb250ZXh0KSBBUEkuIFRvIGJlIHVzZWQgd2l0aCB7QGxpbmsgdXNlRm9ybUNvbnRleHR9LlxuICpcbiAqIEByZW1hcmtzXG4gKiBbQVBJXShodHRwczovL3JlYWN0LWhvb2stZm9ybS5jb20vZG9jcy91c2Vmb3JtY29udGV4dCkg4oCiIFtEZW1vXShodHRwczovL2NvZGVzYW5kYm94LmlvL3MvcmVhY3QtaG9vay1mb3JtLXY3LWZvcm0tY29udGV4dC15dHVkaSlcbiAqXG4gKiBAcGFyYW0gcHJvcHMgLSBhbGwgdXNlRm9ybSBtZXRob2RzXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzeFxuICogZnVuY3Rpb24gQXBwKCkge1xuICogICBjb25zdCBtZXRob2RzID0gdXNlRm9ybSgpO1xuICogICBjb25zdCBvblN1Ym1pdCA9IGRhdGEgPT4gY29uc29sZS5sb2coZGF0YSk7XG4gKlxuICogICByZXR1cm4gKFxuICogICAgIDxGb3JtUHJvdmlkZXIgey4uLm1ldGhvZHN9ID5cbiAqICAgICAgIDxmb3JtIG9uU3VibWl0PXttZXRob2RzLmhhbmRsZVN1Ym1pdChvblN1Ym1pdCl9PlxuICogICAgICAgICA8TmVzdGVkSW5wdXQgLz5cbiAqICAgICAgICAgPGlucHV0IHR5cGU9XCJzdWJtaXRcIiAvPlxuICogICAgICAgPC9mb3JtPlxuICogICAgIDwvRm9ybVByb3ZpZGVyPlxuICogICApO1xuICogfVxuICpcbiAqICBmdW5jdGlvbiBOZXN0ZWRJbnB1dCgpIHtcbiAqICAgY29uc3QgeyByZWdpc3RlciB9ID0gdXNlRm9ybUNvbnRleHQoKTsgLy8gcmV0cmlldmUgYWxsIGhvb2sgbWV0aG9kc1xuICogICByZXR1cm4gPGlucHV0IHsuLi5yZWdpc3RlcihcInRlc3RcIil9IC8+O1xuICogfVxuICogYGBgXG4gKi9cbmNvbnN0IEZvcm1Qcm92aWRlciA9IChwcm9wcykgPT4ge1xuICAgIGNvbnN0IHsgY2hpbGRyZW4sIC4uLmRhdGEgfSA9IHByb3BzO1xuICAgIHJldHVybiAoUmVhY3QuY3JlYXRlRWxlbWVudChIb29rRm9ybUNvbnRleHQuUHJvdmlkZXIsIHsgdmFsdWU6IGRhdGEgfSwgY2hpbGRyZW4pKTtcbn07XG5cbnZhciBnZXRQcm94eUZvcm1TdGF0ZSA9IChmb3JtU3RhdGUsIGNvbnRyb2wsIGxvY2FsUHJveHlGb3JtU3RhdGUsIGlzUm9vdCA9IHRydWUpID0+IHtcbiAgICBjb25zdCByZXN1bHQgPSB7XG4gICAgICAgIGRlZmF1bHRWYWx1ZXM6IGNvbnRyb2wuX2RlZmF1bHRWYWx1ZXMsXG4gICAgfTtcbiAgICBmb3IgKGNvbnN0IGtleSBpbiBmb3JtU3RhdGUpIHtcbiAgICAgICAgT2JqZWN0LmRlZmluZVByb3BlcnR5KHJlc3VsdCwga2V5LCB7XG4gICAgICAgICAgICBnZXQ6ICgpID0+IHtcbiAgICAgICAgICAgICAgICBjb25zdCBfa2V5ID0ga2V5O1xuICAgICAgICAgICAgICAgIGlmIChjb250cm9sLl9wcm94eUZvcm1TdGF0ZVtfa2V5XSAhPT0gVkFMSURBVElPTl9NT0RFLmFsbCkge1xuICAgICAgICAgICAgICAgICAgICBjb250cm9sLl9wcm94eUZvcm1TdGF0ZVtfa2V5XSA9ICFpc1Jvb3QgfHwgVkFMSURBVElPTl9NT0RFLmFsbDtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgbG9jYWxQcm94eUZvcm1TdGF0ZSAmJiAobG9jYWxQcm94eUZvcm1TdGF0ZVtfa2V5XSA9IHRydWUpO1xuICAgICAgICAgICAgICAgIHJldHVybiBmb3JtU3RhdGVbX2tleV07XG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICB9XG4gICAgcmV0dXJuIHJlc3VsdDtcbn07XG5cbmNvbnN0IHVzZUlzb21vcnBoaWNMYXlvdXRFZmZlY3QgPSB0eXBlb2Ygd2luZG93ICE9PSAndW5kZWZpbmVkJyA/IFJlYWN0LnVzZUxheW91dEVmZmVjdCA6IFJlYWN0LnVzZUVmZmVjdDtcblxuLyoqXG4gKiBUaGlzIGN1c3RvbSBob29rIGFsbG93cyB5b3UgdG8gc3Vic2NyaWJlIHRvIGVhY2ggZm9ybSBzdGF0ZSwgYW5kIGlzb2xhdGUgdGhlIHJlLXJlbmRlciBhdCB0aGUgY3VzdG9tIGhvb2sgbGV2ZWwuIEl0IGhhcyBpdHMgc2NvcGUgaW4gdGVybXMgb2YgZm9ybSBzdGF0ZSBzdWJzY3JpcHRpb24sIHNvIGl0IHdvdWxkIG5vdCBhZmZlY3Qgb3RoZXIgdXNlRm9ybVN0YXRlIGFuZCB1c2VGb3JtLiBVc2luZyB0aGlzIGhvb2sgY2FuIHJlZHVjZSB0aGUgcmUtcmVuZGVyIGltcGFjdCBvbiBsYXJnZSBhbmQgY29tcGxleCBmb3JtIGFwcGxpY2F0aW9uLlxuICpcbiAqIEByZW1hcmtzXG4gKiBbQVBJXShodHRwczovL3JlYWN0LWhvb2stZm9ybS5jb20vZG9jcy91c2Vmb3Jtc3RhdGUpIOKAoiBbRGVtb10oaHR0cHM6Ly9jb2Rlc2FuZGJveC5pby9zL3VzZWZvcm1zdGF0ZS03NXhseSlcbiAqXG4gKiBAcGFyYW0gcHJvcHMgLSBpbmNsdWRlIG9wdGlvbnMgb24gc3BlY2lmeSBmaWVsZHMgdG8gc3Vic2NyaWJlLiB7QGxpbmsgVXNlRm9ybVN0YXRlUmV0dXJufVxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0c3hcbiAqIGZ1bmN0aW9uIEFwcCgpIHtcbiAqICAgY29uc3QgeyByZWdpc3RlciwgaGFuZGxlU3VibWl0LCBjb250cm9sIH0gPSB1c2VGb3JtKHtcbiAqICAgICBkZWZhdWx0VmFsdWVzOiB7XG4gKiAgICAgZmlyc3ROYW1lOiBcImZpcnN0TmFtZVwiXG4gKiAgIH19KTtcbiAqICAgY29uc3QgeyBkaXJ0eUZpZWxkcyB9ID0gdXNlRm9ybVN0YXRlKHtcbiAqICAgICBjb250cm9sXG4gKiAgIH0pO1xuICogICBjb25zdCBvblN1Ym1pdCA9IChkYXRhKSA9PiBjb25zb2xlLmxvZyhkYXRhKTtcbiAqXG4gKiAgIHJldHVybiAoXG4gKiAgICAgPGZvcm0gb25TdWJtaXQ9e2hhbmRsZVN1Ym1pdChvblN1Ym1pdCl9PlxuICogICAgICAgPGlucHV0IHsuLi5yZWdpc3RlcihcImZpcnN0TmFtZVwiKX0gcGxhY2Vob2xkZXI9XCJGaXJzdCBOYW1lXCIgLz5cbiAqICAgICAgIHtkaXJ0eUZpZWxkcy5maXJzdE5hbWUgJiYgPHA+RmllbGQgaXMgZGlydHkuPC9wPn1cbiAqICAgICAgIDxpbnB1dCB0eXBlPVwic3VibWl0XCIgLz5cbiAqICAgICA8L2Zvcm0+XG4gKiAgICk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuZnVuY3Rpb24gdXNlRm9ybVN0YXRlKHByb3BzKSB7XG4gICAgY29uc3QgbWV0aG9kcyA9IHVzZUZvcm1Db250ZXh0KCk7XG4gICAgY29uc3QgeyBjb250cm9sID0gbWV0aG9kcy5jb250cm9sLCBkaXNhYmxlZCwgbmFtZSwgZXhhY3QgfSA9IHByb3BzIHx8IHt9O1xuICAgIGNvbnN0IFtmb3JtU3RhdGUsIHVwZGF0ZUZvcm1TdGF0ZV0gPSBSZWFjdC51c2VTdGF0ZShjb250cm9sLl9mb3JtU3RhdGUpO1xuICAgIGNvbnN0IF9sb2NhbFByb3h5Rm9ybVN0YXRlID0gUmVhY3QudXNlUmVmKHtcbiAgICAgICAgaXNEaXJ0eTogZmFsc2UsXG4gICAgICAgIGlzTG9hZGluZzogZmFsc2UsXG4gICAgICAgIGRpcnR5RmllbGRzOiBmYWxzZSxcbiAgICAgICAgdG91Y2hlZEZpZWxkczogZmFsc2UsXG4gICAgICAgIHZhbGlkYXRpbmdGaWVsZHM6IGZhbHNlLFxuICAgICAgICBpc1ZhbGlkYXRpbmc6IGZhbHNlLFxuICAgICAgICBpc1ZhbGlkOiBmYWxzZSxcbiAgICAgICAgZXJyb3JzOiBmYWxzZSxcbiAgICB9KTtcbiAgICB1c2VJc29tb3JwaGljTGF5b3V0RWZmZWN0KCgpID0+IGNvbnRyb2wuX3N1YnNjcmliZSh7XG4gICAgICAgIG5hbWUsXG4gICAgICAgIGZvcm1TdGF0ZTogX2xvY2FsUHJveHlGb3JtU3RhdGUuY3VycmVudCxcbiAgICAgICAgZXhhY3QsXG4gICAgICAgIGNhbGxiYWNrOiAoZm9ybVN0YXRlKSA9PiB7XG4gICAgICAgICAgICAhZGlzYWJsZWQgJiZcbiAgICAgICAgICAgICAgICB1cGRhdGVGb3JtU3RhdGUoe1xuICAgICAgICAgICAgICAgICAgICAuLi5jb250cm9sLl9mb3JtU3RhdGUsXG4gICAgICAgICAgICAgICAgICAgIC4uLmZvcm1TdGF0ZSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgfSxcbiAgICB9KSwgW25hbWUsIGRpc2FibGVkLCBleGFjdF0pO1xuICAgIFJlYWN0LnVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIF9sb2NhbFByb3h5Rm9ybVN0YXRlLmN1cnJlbnQuaXNWYWxpZCAmJiBjb250cm9sLl9zZXRWYWxpZCh0cnVlKTtcbiAgICB9LCBbY29udHJvbF0pO1xuICAgIHJldHVybiBSZWFjdC51c2VNZW1vKCgpID0+IGdldFByb3h5Rm9ybVN0YXRlKGZvcm1TdGF0ZSwgY29udHJvbCwgX2xvY2FsUHJveHlGb3JtU3RhdGUuY3VycmVudCwgZmFsc2UpLCBbZm9ybVN0YXRlLCBjb250cm9sXSk7XG59XG5cbnZhciBpc1N0cmluZyA9ICh2YWx1ZSkgPT4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJztcblxudmFyIGdlbmVyYXRlV2F0Y2hPdXRwdXQgPSAobmFtZXMsIF9uYW1lcywgZm9ybVZhbHVlcywgaXNHbG9iYWwsIGRlZmF1bHRWYWx1ZSkgPT4ge1xuICAgIGlmIChpc1N0cmluZyhuYW1lcykpIHtcbiAgICAgICAgaXNHbG9iYWwgJiYgX25hbWVzLndhdGNoLmFkZChuYW1lcyk7XG4gICAgICAgIHJldHVybiBnZXQoZm9ybVZhbHVlcywgbmFtZXMsIGRlZmF1bHRWYWx1ZSk7XG4gICAgfVxuICAgIGlmIChBcnJheS5pc0FycmF5KG5hbWVzKSkge1xuICAgICAgICByZXR1cm4gbmFtZXMubWFwKChmaWVsZE5hbWUpID0+IChpc0dsb2JhbCAmJiBfbmFtZXMud2F0Y2guYWRkKGZpZWxkTmFtZSksXG4gICAgICAgICAgICBnZXQoZm9ybVZhbHVlcywgZmllbGROYW1lKSkpO1xuICAgIH1cbiAgICBpc0dsb2JhbCAmJiAoX25hbWVzLndhdGNoQWxsID0gdHJ1ZSk7XG4gICAgcmV0dXJuIGZvcm1WYWx1ZXM7XG59O1xuXG52YXIgaXNQcmltaXRpdmUgPSAodmFsdWUpID0+IGlzTnVsbE9yVW5kZWZpbmVkKHZhbHVlKSB8fCAhaXNPYmplY3RUeXBlKHZhbHVlKTtcblxuZnVuY3Rpb24gZGVlcEVxdWFsKG9iamVjdDEsIG9iamVjdDIsIF9pbnRlcm5hbF92aXNpdGVkID0gbmV3IFdlYWtTZXQoKSkge1xuICAgIGlmIChpc1ByaW1pdGl2ZShvYmplY3QxKSB8fCBpc1ByaW1pdGl2ZShvYmplY3QyKSkge1xuICAgICAgICByZXR1cm4gT2JqZWN0LmlzKG9iamVjdDEsIG9iamVjdDIpO1xuICAgIH1cbiAgICBpZiAoaXNEYXRlT2JqZWN0KG9iamVjdDEpICYmIGlzRGF0ZU9iamVjdChvYmplY3QyKSkge1xuICAgICAgICByZXR1cm4gb2JqZWN0MS5nZXRUaW1lKCkgPT09IG9iamVjdDIuZ2V0VGltZSgpO1xuICAgIH1cbiAgICBjb25zdCBrZXlzMSA9IE9iamVjdC5rZXlzKG9iamVjdDEpO1xuICAgIGNvbnN0IGtleXMyID0gT2JqZWN0LmtleXMob2JqZWN0Mik7XG4gICAgaWYgKGtleXMxLmxlbmd0aCAhPT0ga2V5czIubGVuZ3RoKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgaWYgKF9pbnRlcm5hbF92aXNpdGVkLmhhcyhvYmplY3QxKSB8fCBfaW50ZXJuYWxfdmlzaXRlZC5oYXMob2JqZWN0MikpIHtcbiAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgfVxuICAgIF9pbnRlcm5hbF92aXNpdGVkLmFkZChvYmplY3QxKTtcbiAgICBfaW50ZXJuYWxfdmlzaXRlZC5hZGQob2JqZWN0Mik7XG4gICAgZm9yIChjb25zdCBrZXkgb2Yga2V5czEpIHtcbiAgICAgICAgY29uc3QgdmFsMSA9IG9iamVjdDFba2V5XTtcbiAgICAgICAgaWYgKCFrZXlzMi5pbmNsdWRlcyhrZXkpKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGtleSAhPT0gJ3JlZicpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbDIgPSBvYmplY3QyW2tleV07XG4gICAgICAgICAgICBpZiAoKGlzRGF0ZU9iamVjdCh2YWwxKSAmJiBpc0RhdGVPYmplY3QodmFsMikpIHx8XG4gICAgICAgICAgICAgICAgKGlzT2JqZWN0KHZhbDEpICYmIGlzT2JqZWN0KHZhbDIpKSB8fFxuICAgICAgICAgICAgICAgIChBcnJheS5pc0FycmF5KHZhbDEpICYmIEFycmF5LmlzQXJyYXkodmFsMikpXG4gICAgICAgICAgICAgICAgPyAhZGVlcEVxdWFsKHZhbDEsIHZhbDIsIF9pbnRlcm5hbF92aXNpdGVkKVxuICAgICAgICAgICAgICAgIDogIU9iamVjdC5pcyh2YWwxLCB2YWwyKSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gdHJ1ZTtcbn1cblxuLyoqXG4gKiBDdXN0b20gaG9vayB0byBzdWJzY3JpYmUgdG8gZmllbGQgY2hhbmdlIGFuZCBpc29sYXRlIHJlLXJlbmRlcmluZyBhdCB0aGUgY29tcG9uZW50IGxldmVsLlxuICpcbiAqIEByZW1hcmtzXG4gKlxuICogW0FQSV0oaHR0cHM6Ly9yZWFjdC1ob29rLWZvcm0uY29tL2RvY3MvdXNld2F0Y2gpIOKAoiBbRGVtb10oaHR0cHM6Ly9jb2Rlc2FuZGJveC5pby9zL3JlYWN0LWhvb2stZm9ybS12Ny10cy11c2V3YXRjaC1oOWk1ZSlcbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHN4XG4gKiBjb25zdCB7IGNvbnRyb2wgfSA9IHVzZUZvcm0oKTtcbiAqIGNvbnN0IHZhbHVlcyA9IHVzZVdhdGNoKHtcbiAqICAgbmFtZTogXCJmaWVsZE5hbWVcIlxuICogICBjb250cm9sLFxuICogfSlcbiAqIGBgYFxuICovXG5mdW5jdGlvbiB1c2VXYXRjaChwcm9wcykge1xuICAgIGNvbnN0IG1ldGhvZHMgPSB1c2VGb3JtQ29udGV4dCgpO1xuICAgIGNvbnN0IHsgY29udHJvbCA9IG1ldGhvZHMuY29udHJvbCwgbmFtZSwgZGVmYXVsdFZhbHVlLCBkaXNhYmxlZCwgZXhhY3QsIGNvbXB1dGUsIH0gPSBwcm9wcyB8fCB7fTtcbiAgICBjb25zdCBfZGVmYXVsdFZhbHVlID0gUmVhY3QudXNlUmVmKGRlZmF1bHRWYWx1ZSk7XG4gICAgY29uc3QgX2NvbXB1dGUgPSBSZWFjdC51c2VSZWYoY29tcHV0ZSk7XG4gICAgY29uc3QgX2NvbXB1dGVGb3JtVmFsdWVzID0gUmVhY3QudXNlUmVmKHVuZGVmaW5lZCk7XG4gICAgY29uc3QgX3ByZXZDb250cm9sID0gUmVhY3QudXNlUmVmKGNvbnRyb2wpO1xuICAgIGNvbnN0IF9wcmV2TmFtZSA9IFJlYWN0LnVzZVJlZihuYW1lKTtcbiAgICBfY29tcHV0ZS5jdXJyZW50ID0gY29tcHV0ZTtcbiAgICBjb25zdCBbdmFsdWUsIHVwZGF0ZVZhbHVlXSA9IFJlYWN0LnVzZVN0YXRlKCgpID0+IHtcbiAgICAgICAgY29uc3QgZGVmYXVsdFZhbHVlID0gY29udHJvbC5fZ2V0V2F0Y2gobmFtZSwgX2RlZmF1bHRWYWx1ZS5jdXJyZW50KTtcbiAgICAgICAgcmV0dXJuIF9jb21wdXRlLmN1cnJlbnQgPyBfY29tcHV0ZS5jdXJyZW50KGRlZmF1bHRWYWx1ZSkgOiBkZWZhdWx0VmFsdWU7XG4gICAgfSk7XG4gICAgY29uc3QgZ2V0Q3VycmVudE91dHB1dCA9IFJlYWN0LnVzZUNhbGxiYWNrKCh2YWx1ZXMpID0+IHtcbiAgICAgICAgY29uc3QgZm9ybVZhbHVlcyA9IGdlbmVyYXRlV2F0Y2hPdXRwdXQobmFtZSwgY29udHJvbC5fbmFtZXMsIHZhbHVlcyB8fCBjb250cm9sLl9mb3JtVmFsdWVzLCBmYWxzZSwgX2RlZmF1bHRWYWx1ZS5jdXJyZW50KTtcbiAgICAgICAgcmV0dXJuIF9jb21wdXRlLmN1cnJlbnQgPyBfY29tcHV0ZS5jdXJyZW50KGZvcm1WYWx1ZXMpIDogZm9ybVZhbHVlcztcbiAgICB9LCBbY29udHJvbC5fZm9ybVZhbHVlcywgY29udHJvbC5fbmFtZXMsIG5hbWVdKTtcbiAgICBjb25zdCByZWZyZXNoVmFsdWUgPSBSZWFjdC51c2VDYWxsYmFjaygodmFsdWVzKSA9PiB7XG4gICAgICAgIGlmICghZGlzYWJsZWQpIHtcbiAgICAgICAgICAgIGNvbnN0IGZvcm1WYWx1ZXMgPSBnZW5lcmF0ZVdhdGNoT3V0cHV0KG5hbWUsIGNvbnRyb2wuX25hbWVzLCB2YWx1ZXMgfHwgY29udHJvbC5fZm9ybVZhbHVlcywgZmFsc2UsIF9kZWZhdWx0VmFsdWUuY3VycmVudCk7XG4gICAgICAgICAgICBpZiAoX2NvbXB1dGUuY3VycmVudCkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGNvbXB1dGVkRm9ybVZhbHVlcyA9IF9jb21wdXRlLmN1cnJlbnQoZm9ybVZhbHVlcyk7XG4gICAgICAgICAgICAgICAgaWYgKCFkZWVwRXF1YWwoY29tcHV0ZWRGb3JtVmFsdWVzLCBfY29tcHV0ZUZvcm1WYWx1ZXMuY3VycmVudCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdXBkYXRlVmFsdWUoY29tcHV0ZWRGb3JtVmFsdWVzKTtcbiAgICAgICAgICAgICAgICAgICAgX2NvbXB1dGVGb3JtVmFsdWVzLmN1cnJlbnQgPSBjb21wdXRlZEZvcm1WYWx1ZXM7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgdXBkYXRlVmFsdWUoZm9ybVZhbHVlcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9LCBbY29udHJvbC5fZm9ybVZhbHVlcywgY29udHJvbC5fbmFtZXMsIGRpc2FibGVkLCBuYW1lXSk7XG4gICAgdXNlSXNvbW9ycGhpY0xheW91dEVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGlmIChfcHJldkNvbnRyb2wuY3VycmVudCAhPT0gY29udHJvbCB8fFxuICAgICAgICAgICAgIWRlZXBFcXVhbChfcHJldk5hbWUuY3VycmVudCwgbmFtZSkpIHtcbiAgICAgICAgICAgIF9wcmV2Q29udHJvbC5jdXJyZW50ID0gY29udHJvbDtcbiAgICAgICAgICAgIF9wcmV2TmFtZS5jdXJyZW50ID0gbmFtZTtcbiAgICAgICAgICAgIHJlZnJlc2hWYWx1ZSgpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBjb250cm9sLl9zdWJzY3JpYmUoe1xuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIGZvcm1TdGF0ZToge1xuICAgICAgICAgICAgICAgIHZhbHVlczogdHJ1ZSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBleGFjdCxcbiAgICAgICAgICAgIGNhbGxiYWNrOiAoZm9ybVN0YXRlKSA9PiB7XG4gICAgICAgICAgICAgICAgcmVmcmVzaFZhbHVlKGZvcm1TdGF0ZS52YWx1ZXMpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfSk7XG4gICAgfSwgW2NvbnRyb2wsIGV4YWN0LCBuYW1lLCByZWZyZXNoVmFsdWVdKTtcbiAgICBSZWFjdC51c2VFZmZlY3QoKCkgPT4gY29udHJvbC5fcmVtb3ZlVW5tb3VudGVkKCkpO1xuICAgIC8vIElmIG5hbWUgb3IgY29udHJvbCBjaGFuZ2VkIGZvciB0aGlzIHJlbmRlciwgc3luY2hyb25vdXNseSByZWZsZWN0IHRoZVxuICAgIC8vIGxhdGVzdCB2YWx1ZSBzbyBjYWxsZXJzIChsaWtlIHVzZUNvbnRyb2xsZXIpIHNlZSB0aGUgY29ycmVjdCB2YWx1ZVxuICAgIC8vIGltbWVkaWF0ZWx5IG9uIHRoZSBzYW1lIHJlbmRlci5cbiAgICAvLyBPcHRpbWl6ZTogQ2hlY2sgY29udHJvbCByZWZlcmVuY2UgZmlyc3QgYmVmb3JlIGV4cGVuc2l2ZSBkZWVwRXF1YWxcbiAgICBjb25zdCBjb250cm9sQ2hhbmdlZCA9IF9wcmV2Q29udHJvbC5jdXJyZW50ICE9PSBjb250cm9sO1xuICAgIGNvbnN0IHByZXZOYW1lID0gX3ByZXZOYW1lLmN1cnJlbnQ7XG4gICAgLy8gQ2FjaGUgdGhlIGNvbXB1dGVkIG91dHB1dCB0byBhdm9pZCBkdXBsaWNhdGUgY2FsbHMgd2l0aGluIHRoZSBzYW1lIHJlbmRlclxuICAgIC8vIFdlIGluY2x1ZGUgc2hvdWxkUmV0dXJuSW1tZWRpYXRlIGluIGRlcHMgdG8gZW5zdXJlIHByb3BlciByZWNvbXB1dGF0aW9uXG4gICAgY29uc3QgY29tcHV0ZWRPdXRwdXQgPSBSZWFjdC51c2VNZW1vKCgpID0+IHtcbiAgICAgICAgaWYgKGRpc2FibGVkKSB7XG4gICAgICAgICAgICByZXR1cm4gbnVsbDtcbiAgICAgICAgfVxuICAgICAgICBjb25zdCBuYW1lQ2hhbmdlZCA9ICFjb250cm9sQ2hhbmdlZCAmJiAhZGVlcEVxdWFsKHByZXZOYW1lLCBuYW1lKTtcbiAgICAgICAgY29uc3Qgc2hvdWxkUmV0dXJuSW1tZWRpYXRlID0gY29udHJvbENoYW5nZWQgfHwgbmFtZUNoYW5nZWQ7XG4gICAgICAgIHJldHVybiBzaG91bGRSZXR1cm5JbW1lZGlhdGUgPyBnZXRDdXJyZW50T3V0cHV0KCkgOiBudWxsO1xuICAgIH0sIFtkaXNhYmxlZCwgY29udHJvbENoYW5nZWQsIG5hbWUsIHByZXZOYW1lLCBnZXRDdXJyZW50T3V0cHV0XSk7XG4gICAgcmV0dXJuIGNvbXB1dGVkT3V0cHV0ICE9PSBudWxsID8gY29tcHV0ZWRPdXRwdXQgOiB2YWx1ZTtcbn1cblxuLyoqXG4gKiBDdXN0b20gaG9vayB0byB3b3JrIHdpdGggY29udHJvbGxlZCBjb21wb25lbnQsIHRoaXMgZnVuY3Rpb24gcHJvdmlkZSB5b3Ugd2l0aCBib3RoIGZvcm0gYW5kIGZpZWxkIGxldmVsIHN0YXRlLiBSZS1yZW5kZXIgaXMgaXNvbGF0ZWQgYXQgdGhlIGhvb2sgbGV2ZWwuXG4gKlxuICogQHJlbWFya3NcbiAqIFtBUEldKGh0dHBzOi8vcmVhY3QtaG9vay1mb3JtLmNvbS9kb2NzL3VzZWNvbnRyb2xsZXIpIOKAoiBbRGVtb10oaHR0cHM6Ly9jb2Rlc2FuZGJveC5pby9zL3VzZWNvbnRyb2xsZXItMG84cHgpXG4gKlxuICogQHBhcmFtIHByb3BzIC0gdGhlIHBhdGggbmFtZSB0byB0aGUgZm9ybSBmaWVsZCB2YWx1ZSwgYW5kIHZhbGlkYXRpb24gcnVsZXMuXG4gKlxuICogQHJldHVybnMgZmllbGQgcHJvcGVydGllcywgZmllbGQgYW5kIGZvcm0gc3RhdGUuIHtAbGluayBVc2VDb250cm9sbGVyUmV0dXJufVxuICpcbiAqIEBleGFtcGxlXG4gKiBgYGB0c3hcbiAqIGZ1bmN0aW9uIElucHV0KHByb3BzKSB7XG4gKiAgIGNvbnN0IHsgZmllbGQsIGZpZWxkU3RhdGUsIGZvcm1TdGF0ZSB9ID0gdXNlQ29udHJvbGxlcihwcm9wcyk7XG4gKiAgIHJldHVybiAoXG4gKiAgICAgPGRpdj5cbiAqICAgICAgIDxpbnB1dCB7Li4uZmllbGR9IHBsYWNlaG9sZGVyPXtwcm9wcy5uYW1lfSAvPlxuICogICAgICAgPHA+e2ZpZWxkU3RhdGUuaXNUb3VjaGVkICYmIFwiVG91Y2hlZFwifTwvcD5cbiAqICAgICAgIDxwPntmb3JtU3RhdGUuaXNTdWJtaXR0ZWQgPyBcInN1Ym1pdHRlZFwiIDogXCJcIn08L3A+XG4gKiAgICAgPC9kaXY+XG4gKiAgICk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuZnVuY3Rpb24gdXNlQ29udHJvbGxlcihwcm9wcykge1xuICAgIGNvbnN0IG1ldGhvZHMgPSB1c2VGb3JtQ29udGV4dCgpO1xuICAgIGNvbnN0IHsgbmFtZSwgZGlzYWJsZWQsIGNvbnRyb2wgPSBtZXRob2RzLmNvbnRyb2wsIHNob3VsZFVucmVnaXN0ZXIsIGRlZmF1bHRWYWx1ZSwgfSA9IHByb3BzO1xuICAgIGNvbnN0IGlzQXJyYXlGaWVsZCA9IGlzTmFtZUluRmllbGRBcnJheShjb250cm9sLl9uYW1lcy5hcnJheSwgbmFtZSk7XG4gICAgY29uc3QgZGVmYXVsdFZhbHVlTWVtbyA9IFJlYWN0LnVzZU1lbW8oKCkgPT4gZ2V0KGNvbnRyb2wuX2Zvcm1WYWx1ZXMsIG5hbWUsIGdldChjb250cm9sLl9kZWZhdWx0VmFsdWVzLCBuYW1lLCBkZWZhdWx0VmFsdWUpKSwgW2NvbnRyb2wsIG5hbWUsIGRlZmF1bHRWYWx1ZV0pO1xuICAgIGNvbnN0IHZhbHVlID0gdXNlV2F0Y2goe1xuICAgICAgICBjb250cm9sLFxuICAgICAgICBuYW1lLFxuICAgICAgICBkZWZhdWx0VmFsdWU6IGRlZmF1bHRWYWx1ZU1lbW8sXG4gICAgICAgIGV4YWN0OiB0cnVlLFxuICAgIH0pO1xuICAgIGNvbnN0IGZvcm1TdGF0ZSA9IHVzZUZvcm1TdGF0ZSh7XG4gICAgICAgIGNvbnRyb2wsXG4gICAgICAgIG5hbWUsXG4gICAgICAgIGV4YWN0OiB0cnVlLFxuICAgIH0pO1xuICAgIGNvbnN0IF9wcm9wcyA9IFJlYWN0LnVzZVJlZihwcm9wcyk7XG4gICAgY29uc3QgX3ByZXZpb3VzTmFtZVJlZiA9IFJlYWN0LnVzZVJlZih1bmRlZmluZWQpO1xuICAgIGNvbnN0IF9yZWdpc3RlclByb3BzID0gUmVhY3QudXNlUmVmKGNvbnRyb2wucmVnaXN0ZXIobmFtZSwge1xuICAgICAgICAuLi5wcm9wcy5ydWxlcyxcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIC4uLihpc0Jvb2xlYW4ocHJvcHMuZGlzYWJsZWQpID8geyBkaXNhYmxlZDogcHJvcHMuZGlzYWJsZWQgfSA6IHt9KSxcbiAgICB9KSk7XG4gICAgX3Byb3BzLmN1cnJlbnQgPSBwcm9wcztcbiAgICBjb25zdCBmaWVsZFN0YXRlID0gUmVhY3QudXNlTWVtbygoKSA9PiBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh7fSwge1xuICAgICAgICBpbnZhbGlkOiB7XG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgZ2V0OiAoKSA9PiAhIWdldChmb3JtU3RhdGUuZXJyb3JzLCBuYW1lKSxcbiAgICAgICAgfSxcbiAgICAgICAgaXNEaXJ0eToge1xuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGdldDogKCkgPT4gISFnZXQoZm9ybVN0YXRlLmRpcnR5RmllbGRzLCBuYW1lKSxcbiAgICAgICAgfSxcbiAgICAgICAgaXNUb3VjaGVkOiB7XG4gICAgICAgICAgICBlbnVtZXJhYmxlOiB0cnVlLFxuICAgICAgICAgICAgZ2V0OiAoKSA9PiAhIWdldChmb3JtU3RhdGUudG91Y2hlZEZpZWxkcywgbmFtZSksXG4gICAgICAgIH0sXG4gICAgICAgIGlzVmFsaWRhdGluZzoge1xuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGdldDogKCkgPT4gISFnZXQoZm9ybVN0YXRlLnZhbGlkYXRpbmdGaWVsZHMsIG5hbWUpLFxuICAgICAgICB9LFxuICAgICAgICBlcnJvcjoge1xuICAgICAgICAgICAgZW51bWVyYWJsZTogdHJ1ZSxcbiAgICAgICAgICAgIGdldDogKCkgPT4gZ2V0KGZvcm1TdGF0ZS5lcnJvcnMsIG5hbWUpLFxuICAgICAgICB9LFxuICAgIH0pLCBbZm9ybVN0YXRlLCBuYW1lXSk7XG4gICAgY29uc3Qgb25DaGFuZ2UgPSBSZWFjdC51c2VDYWxsYmFjaygoZXZlbnQpID0+IF9yZWdpc3RlclByb3BzLmN1cnJlbnQub25DaGFuZ2Uoe1xuICAgICAgICB0YXJnZXQ6IHtcbiAgICAgICAgICAgIHZhbHVlOiBnZXRFdmVudFZhbHVlKGV2ZW50KSxcbiAgICAgICAgICAgIG5hbWU6IG5hbWUsXG4gICAgICAgIH0sXG4gICAgICAgIHR5cGU6IEVWRU5UUy5DSEFOR0UsXG4gICAgfSksIFtuYW1lXSk7XG4gICAgY29uc3Qgb25CbHVyID0gUmVhY3QudXNlQ2FsbGJhY2soKCkgPT4gX3JlZ2lzdGVyUHJvcHMuY3VycmVudC5vbkJsdXIoe1xuICAgICAgICB0YXJnZXQ6IHtcbiAgICAgICAgICAgIHZhbHVlOiBnZXQoY29udHJvbC5fZm9ybVZhbHVlcywgbmFtZSksXG4gICAgICAgICAgICBuYW1lOiBuYW1lLFxuICAgICAgICB9LFxuICAgICAgICB0eXBlOiBFVkVOVFMuQkxVUixcbiAgICB9KSwgW25hbWUsIGNvbnRyb2wuX2Zvcm1WYWx1ZXNdKTtcbiAgICBjb25zdCByZWYgPSBSZWFjdC51c2VDYWxsYmFjaygoZWxtKSA9PiB7XG4gICAgICAgIGNvbnN0IGZpZWxkID0gZ2V0KGNvbnRyb2wuX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgIGlmIChmaWVsZCAmJiBlbG0pIHtcbiAgICAgICAgICAgIGZpZWxkLl9mLnJlZiA9IHtcbiAgICAgICAgICAgICAgICBmb2N1czogKCkgPT4gZWxtLmZvY3VzICYmIGVsbS5mb2N1cygpLFxuICAgICAgICAgICAgICAgIHNlbGVjdDogKCkgPT4gZWxtLnNlbGVjdCAmJiBlbG0uc2VsZWN0KCksXG4gICAgICAgICAgICAgICAgc2V0Q3VzdG9tVmFsaWRpdHk6IChtZXNzYWdlKSA9PiBlbG0uc2V0Q3VzdG9tVmFsaWRpdHkobWVzc2FnZSksXG4gICAgICAgICAgICAgICAgcmVwb3J0VmFsaWRpdHk6ICgpID0+IGVsbS5yZXBvcnRWYWxpZGl0eSgpLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH0sIFtjb250cm9sLl9maWVsZHMsIG5hbWVdKTtcbiAgICBjb25zdCBmaWVsZCA9IFJlYWN0LnVzZU1lbW8oKCkgPT4gKHtcbiAgICAgICAgbmFtZSxcbiAgICAgICAgdmFsdWUsXG4gICAgICAgIC4uLihpc0Jvb2xlYW4oZGlzYWJsZWQpIHx8IGZvcm1TdGF0ZS5kaXNhYmxlZFxuICAgICAgICAgICAgPyB7IGRpc2FibGVkOiBmb3JtU3RhdGUuZGlzYWJsZWQgfHwgZGlzYWJsZWQgfVxuICAgICAgICAgICAgOiB7fSksXG4gICAgICAgIG9uQ2hhbmdlLFxuICAgICAgICBvbkJsdXIsXG4gICAgICAgIHJlZixcbiAgICB9KSwgW25hbWUsIGRpc2FibGVkLCBmb3JtU3RhdGUuZGlzYWJsZWQsIG9uQ2hhbmdlLCBvbkJsdXIsIHJlZiwgdmFsdWVdKTtcbiAgICBSZWFjdC51c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBjb25zdCBfc2hvdWxkVW5yZWdpc3RlckZpZWxkID0gY29udHJvbC5fb3B0aW9ucy5zaG91bGRVbnJlZ2lzdGVyIHx8IHNob3VsZFVucmVnaXN0ZXI7XG4gICAgICAgIGNvbnN0IHByZXZpb3VzTmFtZSA9IF9wcmV2aW91c05hbWVSZWYuY3VycmVudDtcbiAgICAgICAgaWYgKHByZXZpb3VzTmFtZSAmJiBwcmV2aW91c05hbWUgIT09IG5hbWUgJiYgIWlzQXJyYXlGaWVsZCkge1xuICAgICAgICAgICAgY29udHJvbC51bnJlZ2lzdGVyKHByZXZpb3VzTmFtZSk7XG4gICAgICAgIH1cbiAgICAgICAgY29udHJvbC5yZWdpc3RlcihuYW1lLCB7XG4gICAgICAgICAgICAuLi5fcHJvcHMuY3VycmVudC5ydWxlcyxcbiAgICAgICAgICAgIC4uLihpc0Jvb2xlYW4oX3Byb3BzLmN1cnJlbnQuZGlzYWJsZWQpXG4gICAgICAgICAgICAgICAgPyB7IGRpc2FibGVkOiBfcHJvcHMuY3VycmVudC5kaXNhYmxlZCB9XG4gICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgIH0pO1xuICAgICAgICBjb25zdCB1cGRhdGVNb3VudGVkID0gKG5hbWUsIHZhbHVlKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBmaWVsZCA9IGdldChjb250cm9sLl9maWVsZHMsIG5hbWUpO1xuICAgICAgICAgICAgaWYgKGZpZWxkICYmIGZpZWxkLl9mKSB7XG4gICAgICAgICAgICAgICAgZmllbGQuX2YubW91bnQgPSB2YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfTtcbiAgICAgICAgdXBkYXRlTW91bnRlZChuYW1lLCB0cnVlKTtcbiAgICAgICAgaWYgKF9zaG91bGRVbnJlZ2lzdGVyRmllbGQpIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlID0gY2xvbmVPYmplY3QoZ2V0KGNvbnRyb2wuX29wdGlvbnMuZGVmYXVsdFZhbHVlcywgbmFtZSwgX3Byb3BzLmN1cnJlbnQuZGVmYXVsdFZhbHVlKSk7XG4gICAgICAgICAgICBzZXQoY29udHJvbC5fZGVmYXVsdFZhbHVlcywgbmFtZSwgdmFsdWUpO1xuICAgICAgICAgICAgaWYgKGlzVW5kZWZpbmVkKGdldChjb250cm9sLl9mb3JtVmFsdWVzLCBuYW1lKSkpIHtcbiAgICAgICAgICAgICAgICBzZXQoY29udHJvbC5fZm9ybVZhbHVlcywgbmFtZSwgdmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgICFpc0FycmF5RmllbGQgJiYgY29udHJvbC5yZWdpc3RlcihuYW1lKTtcbiAgICAgICAgX3ByZXZpb3VzTmFtZVJlZi5jdXJyZW50ID0gbmFtZTtcbiAgICAgICAgcmV0dXJuICgpID0+IHtcbiAgICAgICAgICAgIChpc0FycmF5RmllbGRcbiAgICAgICAgICAgICAgICA/IF9zaG91bGRVbnJlZ2lzdGVyRmllbGQgJiYgIWNvbnRyb2wuX3N0YXRlLmFjdGlvblxuICAgICAgICAgICAgICAgIDogX3Nob3VsZFVucmVnaXN0ZXJGaWVsZClcbiAgICAgICAgICAgICAgICA/IGNvbnRyb2wudW5yZWdpc3RlcihuYW1lKVxuICAgICAgICAgICAgICAgIDogdXBkYXRlTW91bnRlZChuYW1lLCBmYWxzZSk7XG4gICAgICAgIH07XG4gICAgfSwgW25hbWUsIGNvbnRyb2wsIGlzQXJyYXlGaWVsZCwgc2hvdWxkVW5yZWdpc3Rlcl0pO1xuICAgIFJlYWN0LnVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGNvbnRyb2wuX3NldERpc2FibGVkRmllbGQoe1xuICAgICAgICAgICAgZGlzYWJsZWQsXG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICB9KTtcbiAgICB9LCBbZGlzYWJsZWQsIG5hbWUsIGNvbnRyb2xdKTtcbiAgICByZXR1cm4gUmVhY3QudXNlTWVtbygoKSA9PiAoe1xuICAgICAgICBmaWVsZCxcbiAgICAgICAgZm9ybVN0YXRlLFxuICAgICAgICBmaWVsZFN0YXRlLFxuICAgIH0pLCBbZmllbGQsIGZvcm1TdGF0ZSwgZmllbGRTdGF0ZV0pO1xufVxuXG4vKipcbiAqIENvbXBvbmVudCBiYXNlZCBvbiBgdXNlQ29udHJvbGxlcmAgaG9vayB0byB3b3JrIHdpdGggY29udHJvbGxlZCBjb21wb25lbnQuXG4gKlxuICogQHJlbWFya3NcbiAqIFtBUEldKGh0dHBzOi8vcmVhY3QtaG9vay1mb3JtLmNvbS9kb2NzL3VzZWNvbnRyb2xsZXIvY29udHJvbGxlcikg4oCiIFtEZW1vXShodHRwczovL2NvZGVzYW5kYm94LmlvL3MvcmVhY3QtaG9vay1mb3JtLXY2LWNvbnRyb2xsZXItdHMtand5encpIOKAoiBbVmlkZW9dKGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9TjJVTmtfVUNWeUEpXG4gKlxuICogQHBhcmFtIHByb3BzIC0gdGhlIHBhdGggbmFtZSB0byB0aGUgZm9ybSBmaWVsZCB2YWx1ZSwgYW5kIHZhbGlkYXRpb24gcnVsZXMuXG4gKlxuICogQHJldHVybnMgcHJvdmlkZSBmaWVsZCBoYW5kbGVyIGZ1bmN0aW9ucywgZmllbGQgYW5kIGZvcm0gc3RhdGUuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzeFxuICogZnVuY3Rpb24gQXBwKCkge1xuICogICBjb25zdCB7IGNvbnRyb2wgfSA9IHVzZUZvcm08Rm9ybVZhbHVlcz4oe1xuICogICAgIGRlZmF1bHRWYWx1ZXM6IHtcbiAqICAgICAgIHRlc3Q6IFwiXCJcbiAqICAgICB9XG4gKiAgIH0pO1xuICpcbiAqICAgcmV0dXJuIChcbiAqICAgICA8Zm9ybT5cbiAqICAgICAgIDxDb250cm9sbGVyXG4gKiAgICAgICAgIGNvbnRyb2w9e2NvbnRyb2x9XG4gKiAgICAgICAgIG5hbWU9XCJ0ZXN0XCJcbiAqICAgICAgICAgcmVuZGVyPXsoeyBmaWVsZDogeyBvbkNoYW5nZSwgb25CbHVyLCB2YWx1ZSwgcmVmIH0sIGZvcm1TdGF0ZSwgZmllbGRTdGF0ZSB9KSA9PiAoXG4gKiAgICAgICAgICAgPD5cbiAqICAgICAgICAgICAgIDxpbnB1dFxuICogICAgICAgICAgICAgICBvbkNoYW5nZT17b25DaGFuZ2V9IC8vIHNlbmQgdmFsdWUgdG8gaG9vayBmb3JtXG4gKiAgICAgICAgICAgICAgIG9uQmx1cj17b25CbHVyfSAvLyBub3RpZnkgd2hlbiBpbnB1dCBpcyB0b3VjaGVkXG4gKiAgICAgICAgICAgICAgIHZhbHVlPXt2YWx1ZX0gLy8gcmV0dXJuIHVwZGF0ZWQgdmFsdWVcbiAqICAgICAgICAgICAgICAgcmVmPXtyZWZ9IC8vIHNldCByZWYgZm9yIGZvY3VzIG1hbmFnZW1lbnRcbiAqICAgICAgICAgICAgIC8+XG4gKiAgICAgICAgICAgICA8cD57Zm9ybVN0YXRlLmlzU3VibWl0dGVkID8gXCJzdWJtaXR0ZWRcIiA6IFwiXCJ9PC9wPlxuICogICAgICAgICAgICAgPHA+e2ZpZWxkU3RhdGUuaXNUb3VjaGVkID8gXCJ0b3VjaGVkXCIgOiBcIlwifTwvcD5cbiAqICAgICAgICAgICA8Lz5cbiAqICAgICAgICAgKX1cbiAqICAgICAgIC8+XG4gKiAgICAgPC9mb3JtPlxuICogICApO1xuICogfVxuICogYGBgXG4gKi9cbmNvbnN0IENvbnRyb2xsZXIgPSAocHJvcHMpID0+IHByb3BzLnJlbmRlcih1c2VDb250cm9sbGVyKHByb3BzKSk7XG5cbmNvbnN0IGZsYXR0ZW4gPSAob2JqKSA9PiB7XG4gICAgY29uc3Qgb3V0cHV0ID0ge307XG4gICAgZm9yIChjb25zdCBrZXkgb2YgT2JqZWN0LmtleXMob2JqKSkge1xuICAgICAgICBpZiAoaXNPYmplY3RUeXBlKG9ialtrZXldKSAmJiBvYmpba2V5XSAhPT0gbnVsbCkge1xuICAgICAgICAgICAgY29uc3QgbmVzdGVkID0gZmxhdHRlbihvYmpba2V5XSk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IG5lc3RlZEtleSBvZiBPYmplY3Qua2V5cyhuZXN0ZWQpKSB7XG4gICAgICAgICAgICAgICAgb3V0cHV0W2Ake2tleX0uJHtuZXN0ZWRLZXl9YF0gPSBuZXN0ZWRbbmVzdGVkS2V5XTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIG91dHB1dFtrZXldID0gb2JqW2tleV07XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG91dHB1dDtcbn07XG5cbmNvbnN0IFBPU1RfUkVRVUVTVCA9ICdwb3N0Jztcbi8qKlxuICogRm9ybSBjb21wb25lbnQgdG8gbWFuYWdlIHN1Ym1pc3Npb24uXG4gKlxuICogQHBhcmFtIHByb3BzIC0gdG8gc2V0dXAgc3VibWlzc2lvbiBkZXRhaWwuIHtAbGluayBGb3JtUHJvcHN9XG4gKlxuICogQHJldHVybnMgZm9ybSBjb21wb25lbnQgb3IgaGVhZGxlc3MgcmVuZGVyIHByb3AuXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzeFxuICogZnVuY3Rpb24gQXBwKCkge1xuICogICBjb25zdCB7IGNvbnRyb2wsIGZvcm1TdGF0ZTogeyBlcnJvcnMgfSB9ID0gdXNlRm9ybSgpO1xuICpcbiAqICAgcmV0dXJuIChcbiAqICAgICA8Rm9ybSBhY3Rpb249XCIvYXBpXCIgY29udHJvbD17Y29udHJvbH0+XG4gKiAgICAgICA8aW5wdXQgey4uLnJlZ2lzdGVyKFwibmFtZVwiKX0gLz5cbiAqICAgICAgIDxwPntlcnJvcnM/LnJvb3Q/LnNlcnZlciAmJiAnU2VydmVyIGVycm9yJ308L3A+XG4gKiAgICAgICA8YnV0dG9uPlN1Ym1pdDwvYnV0dG9uPlxuICogICAgIDwvRm9ybT5cbiAqICAgKTtcbiAqIH1cbiAqIGBgYFxuICovXG5mdW5jdGlvbiBGb3JtKHByb3BzKSB7XG4gICAgY29uc3QgbWV0aG9kcyA9IHVzZUZvcm1Db250ZXh0KCk7XG4gICAgY29uc3QgW21vdW50ZWQsIHNldE1vdW50ZWRdID0gUmVhY3QudXNlU3RhdGUoZmFsc2UpO1xuICAgIGNvbnN0IHsgY29udHJvbCA9IG1ldGhvZHMuY29udHJvbCwgb25TdWJtaXQsIGNoaWxkcmVuLCBhY3Rpb24sIG1ldGhvZCA9IFBPU1RfUkVRVUVTVCwgaGVhZGVycywgZW5jVHlwZSwgb25FcnJvciwgcmVuZGVyLCBvblN1Y2Nlc3MsIHZhbGlkYXRlU3RhdHVzLCAuLi5yZXN0IH0gPSBwcm9wcztcbiAgICBjb25zdCBzdWJtaXQgPSBhc3luYyAoZXZlbnQpID0+IHtcbiAgICAgICAgbGV0IGhhc0Vycm9yID0gZmFsc2U7XG4gICAgICAgIGxldCB0eXBlID0gJyc7XG4gICAgICAgIGF3YWl0IGNvbnRyb2wuaGFuZGxlU3VibWl0KGFzeW5jIChkYXRhKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBmb3JtRGF0YSA9IG5ldyBGb3JtRGF0YSgpO1xuICAgICAgICAgICAgbGV0IGZvcm1EYXRhSnNvbiA9ICcnO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBmb3JtRGF0YUpzb24gPSBKU09OLnN0cmluZ2lmeShkYXRhKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChfYSkgeyB9XG4gICAgICAgICAgICBjb25zdCBmbGF0dGVuRm9ybVZhbHVlcyA9IGZsYXR0ZW4oY29udHJvbC5fZm9ybVZhbHVlcyk7XG4gICAgICAgICAgICBmb3IgKGNvbnN0IGtleSBpbiBmbGF0dGVuRm9ybVZhbHVlcykge1xuICAgICAgICAgICAgICAgIGZvcm1EYXRhLmFwcGVuZChrZXksIGZsYXR0ZW5Gb3JtVmFsdWVzW2tleV0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKG9uU3VibWl0KSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgb25TdWJtaXQoe1xuICAgICAgICAgICAgICAgICAgICBkYXRhLFxuICAgICAgICAgICAgICAgICAgICBldmVudCxcbiAgICAgICAgICAgICAgICAgICAgbWV0aG9kLFxuICAgICAgICAgICAgICAgICAgICBmb3JtRGF0YSxcbiAgICAgICAgICAgICAgICAgICAgZm9ybURhdGFKc29uLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGFjdGlvbikge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHNob3VsZFN0cmluZ2lmeVN1Ym1pc3Npb25EYXRhID0gW1xuICAgICAgICAgICAgICAgICAgICAgICAgaGVhZGVycyAmJiBoZWFkZXJzWydDb250ZW50LVR5cGUnXSxcbiAgICAgICAgICAgICAgICAgICAgICAgIGVuY1R5cGUsXG4gICAgICAgICAgICAgICAgICAgIF0uc29tZSgodmFsdWUpID0+IHZhbHVlICYmIHZhbHVlLmluY2x1ZGVzKCdqc29uJykpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCByZXNwb25zZSA9IGF3YWl0IGZldGNoKFN0cmluZyhhY3Rpb24pLCB7XG4gICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QsXG4gICAgICAgICAgICAgICAgICAgICAgICBoZWFkZXJzOiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLi4uaGVhZGVycyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi4oZW5jVHlwZSAmJiBlbmNUeXBlICE9PSAnbXVsdGlwYXJ0L2Zvcm0tZGF0YSdcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyB7ICdDb250ZW50LVR5cGUnOiBlbmNUeXBlIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgOiB7fSksXG4gICAgICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgYm9keTogc2hvdWxkU3RyaW5naWZ5U3VibWlzc2lvbkRhdGEgPyBmb3JtRGF0YUpzb24gOiBmb3JtRGF0YSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChyZXNwb25zZSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgKHZhbGlkYXRlU3RhdHVzXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPyAhdmFsaWRhdGVTdGF0dXMocmVzcG9uc2Uuc3RhdHVzKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogcmVzcG9uc2Uuc3RhdHVzIDwgMjAwIHx8IHJlc3BvbnNlLnN0YXR1cyA+PSAzMDApKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBoYXNFcnJvciA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgICAgICBvbkVycm9yICYmIG9uRXJyb3IoeyByZXNwb25zZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgICAgIHR5cGUgPSBTdHJpbmcocmVzcG9uc2Uuc3RhdHVzKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIG9uU3VjY2VzcyAmJiBvblN1Y2Nlc3MoeyByZXNwb25zZSB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgaGFzRXJyb3IgPSB0cnVlO1xuICAgICAgICAgICAgICAgICAgICBvbkVycm9yICYmIG9uRXJyb3IoeyBlcnJvciB9KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pKGV2ZW50KTtcbiAgICAgICAgaWYgKGhhc0Vycm9yICYmIHByb3BzLmNvbnRyb2wpIHtcbiAgICAgICAgICAgIHByb3BzLmNvbnRyb2wuX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgICAgIGlzU3VibWl0U3VjY2Vzc2Z1bDogZmFsc2UsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIHByb3BzLmNvbnRyb2wuc2V0RXJyb3IoJ3Jvb3Quc2VydmVyJywge1xuICAgICAgICAgICAgICAgIHR5cGUsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgc2V0TW91bnRlZCh0cnVlKTtcbiAgICB9LCBbXSk7XG4gICAgcmV0dXJuIHJlbmRlciA/IChSZWFjdC5jcmVhdGVFbGVtZW50KFJlYWN0LkZyYWdtZW50LCBudWxsLCByZW5kZXIoe1xuICAgICAgICBzdWJtaXQsXG4gICAgfSkpKSA6IChSZWFjdC5jcmVhdGVFbGVtZW50KFwiZm9ybVwiLCB7IG5vVmFsaWRhdGU6IG1vdW50ZWQsIGFjdGlvbjogYWN0aW9uLCBtZXRob2Q6IG1ldGhvZCwgZW5jVHlwZTogZW5jVHlwZSwgb25TdWJtaXQ6IHN1Ym1pdCwgLi4ucmVzdCB9LCBjaGlsZHJlbikpO1xufVxuXG52YXIgYXBwZW5kRXJyb3JzID0gKG5hbWUsIHZhbGlkYXRlQWxsRmllbGRDcml0ZXJpYSwgZXJyb3JzLCB0eXBlLCBtZXNzYWdlKSA9PiB2YWxpZGF0ZUFsbEZpZWxkQ3JpdGVyaWFcbiAgICA/IHtcbiAgICAgICAgLi4uZXJyb3JzW25hbWVdLFxuICAgICAgICB0eXBlczoge1xuICAgICAgICAgICAgLi4uKGVycm9yc1tuYW1lXSAmJiBlcnJvcnNbbmFtZV0udHlwZXMgPyBlcnJvcnNbbmFtZV0udHlwZXMgOiB7fSksXG4gICAgICAgICAgICBbdHlwZV06IG1lc3NhZ2UgfHwgdHJ1ZSxcbiAgICAgICAgfSxcbiAgICB9XG4gICAgOiB7fTtcblxudmFyIGNvbnZlcnRUb0FycmF5UGF5bG9hZCA9ICh2YWx1ZSkgPT4gKEFycmF5LmlzQXJyYXkodmFsdWUpID8gdmFsdWUgOiBbdmFsdWVdKTtcblxudmFyIGNyZWF0ZVN1YmplY3QgPSAoKSA9PiB7XG4gICAgbGV0IF9vYnNlcnZlcnMgPSBbXTtcbiAgICBjb25zdCBuZXh0ID0gKHZhbHVlKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3Qgb2JzZXJ2ZXIgb2YgX29ic2VydmVycykge1xuICAgICAgICAgICAgb2JzZXJ2ZXIubmV4dCAmJiBvYnNlcnZlci5uZXh0KHZhbHVlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3Qgc3Vic2NyaWJlID0gKG9ic2VydmVyKSA9PiB7XG4gICAgICAgIF9vYnNlcnZlcnMucHVzaChvYnNlcnZlcik7XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICB1bnN1YnNjcmliZTogKCkgPT4ge1xuICAgICAgICAgICAgICAgIF9vYnNlcnZlcnMgPSBfb2JzZXJ2ZXJzLmZpbHRlcigobykgPT4gbyAhPT0gb2JzZXJ2ZXIpO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIGNvbnN0IHVuc3Vic2NyaWJlID0gKCkgPT4ge1xuICAgICAgICBfb2JzZXJ2ZXJzID0gW107XG4gICAgfTtcbiAgICByZXR1cm4ge1xuICAgICAgICBnZXQgb2JzZXJ2ZXJzKCkge1xuICAgICAgICAgICAgcmV0dXJuIF9vYnNlcnZlcnM7XG4gICAgICAgIH0sXG4gICAgICAgIG5leHQsXG4gICAgICAgIHN1YnNjcmliZSxcbiAgICAgICAgdW5zdWJzY3JpYmUsXG4gICAgfTtcbn07XG5cbmZ1bmN0aW9uIGV4dHJhY3RGb3JtVmFsdWVzKGZpZWxkc1N0YXRlLCBmb3JtVmFsdWVzKSB7XG4gICAgY29uc3QgdmFsdWVzID0ge307XG4gICAgZm9yIChjb25zdCBrZXkgaW4gZmllbGRzU3RhdGUpIHtcbiAgICAgICAgaWYgKGZpZWxkc1N0YXRlLmhhc093blByb3BlcnR5KGtleSkpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkU3RhdGUgPSBmaWVsZHNTdGF0ZVtrZXldO1xuICAgICAgICAgICAgY29uc3QgZmllbGRWYWx1ZSA9IGZvcm1WYWx1ZXNba2V5XTtcbiAgICAgICAgICAgIGlmIChmaWVsZFN0YXRlICYmIGlzT2JqZWN0KGZpZWxkU3RhdGUpICYmIGZpZWxkVmFsdWUpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBuZXN0ZWRGaWVsZHNTdGF0ZSA9IGV4dHJhY3RGb3JtVmFsdWVzKGZpZWxkU3RhdGUsIGZpZWxkVmFsdWUpO1xuICAgICAgICAgICAgICAgIGlmIChpc09iamVjdChuZXN0ZWRGaWVsZHNTdGF0ZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVzW2tleV0gPSBuZXN0ZWRGaWVsZHNTdGF0ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChmaWVsZHNTdGF0ZVtrZXldKSB7XG4gICAgICAgICAgICAgICAgdmFsdWVzW2tleV0gPSBmaWVsZFZhbHVlO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIHJldHVybiB2YWx1ZXM7XG59XG5cbnZhciBpc0VtcHR5T2JqZWN0ID0gKHZhbHVlKSA9PiBpc09iamVjdCh2YWx1ZSkgJiYgIU9iamVjdC5rZXlzKHZhbHVlKS5sZW5ndGg7XG5cbnZhciBpc0ZpbGVJbnB1dCA9IChlbGVtZW50KSA9PiBlbGVtZW50LnR5cGUgPT09ICdmaWxlJztcblxudmFyIGlzRnVuY3Rpb24gPSAodmFsdWUpID0+IHR5cGVvZiB2YWx1ZSA9PT0gJ2Z1bmN0aW9uJztcblxudmFyIGlzSFRNTEVsZW1lbnQgPSAodmFsdWUpID0+IHtcbiAgICBpZiAoIWlzV2ViKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgY29uc3Qgb3duZXIgPSB2YWx1ZSA/IHZhbHVlLm93bmVyRG9jdW1lbnQgOiAwO1xuICAgIHJldHVybiAodmFsdWUgaW5zdGFuY2VvZlxuICAgICAgICAob3duZXIgJiYgb3duZXIuZGVmYXVsdFZpZXcgPyBvd25lci5kZWZhdWx0Vmlldy5IVE1MRWxlbWVudCA6IEhUTUxFbGVtZW50KSk7XG59O1xuXG52YXIgaXNNdWx0aXBsZVNlbGVjdCA9IChlbGVtZW50KSA9PiBlbGVtZW50LnR5cGUgPT09IGBzZWxlY3QtbXVsdGlwbGVgO1xuXG52YXIgaXNSYWRpb0lucHV0ID0gKGVsZW1lbnQpID0+IGVsZW1lbnQudHlwZSA9PT0gJ3JhZGlvJztcblxudmFyIGlzUmFkaW9PckNoZWNrYm94ID0gKHJlZikgPT4gaXNSYWRpb0lucHV0KHJlZikgfHwgaXNDaGVja0JveElucHV0KHJlZik7XG5cbnZhciBsaXZlID0gKHJlZikgPT4gaXNIVE1MRWxlbWVudChyZWYpICYmIHJlZi5pc0Nvbm5lY3RlZDtcblxuZnVuY3Rpb24gYmFzZUdldChvYmplY3QsIHVwZGF0ZVBhdGgpIHtcbiAgICBjb25zdCBsZW5ndGggPSB1cGRhdGVQYXRoLnNsaWNlKDAsIC0xKS5sZW5ndGg7XG4gICAgbGV0IGluZGV4ID0gMDtcbiAgICB3aGlsZSAoaW5kZXggPCBsZW5ndGgpIHtcbiAgICAgICAgb2JqZWN0ID0gaXNVbmRlZmluZWQob2JqZWN0KSA/IGluZGV4KysgOiBvYmplY3RbdXBkYXRlUGF0aFtpbmRleCsrXV07XG4gICAgfVxuICAgIHJldHVybiBvYmplY3Q7XG59XG5mdW5jdGlvbiBpc0VtcHR5QXJyYXkob2JqKSB7XG4gICAgZm9yIChjb25zdCBrZXkgaW4gb2JqKSB7XG4gICAgICAgIGlmIChvYmouaGFzT3duUHJvcGVydHkoa2V5KSAmJiAhaXNVbmRlZmluZWQob2JqW2tleV0pKSB7XG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIHRydWU7XG59XG5mdW5jdGlvbiB1bnNldChvYmplY3QsIHBhdGgpIHtcbiAgICBjb25zdCBwYXRocyA9IEFycmF5LmlzQXJyYXkocGF0aClcbiAgICAgICAgPyBwYXRoXG4gICAgICAgIDogaXNLZXkocGF0aClcbiAgICAgICAgICAgID8gW3BhdGhdXG4gICAgICAgICAgICA6IHN0cmluZ1RvUGF0aChwYXRoKTtcbiAgICBjb25zdCBjaGlsZE9iamVjdCA9IHBhdGhzLmxlbmd0aCA9PT0gMSA/IG9iamVjdCA6IGJhc2VHZXQob2JqZWN0LCBwYXRocyk7XG4gICAgY29uc3QgaW5kZXggPSBwYXRocy5sZW5ndGggLSAxO1xuICAgIGNvbnN0IGtleSA9IHBhdGhzW2luZGV4XTtcbiAgICBpZiAoY2hpbGRPYmplY3QpIHtcbiAgICAgICAgZGVsZXRlIGNoaWxkT2JqZWN0W2tleV07XG4gICAgfVxuICAgIGlmIChpbmRleCAhPT0gMCAmJlxuICAgICAgICAoKGlzT2JqZWN0KGNoaWxkT2JqZWN0KSAmJiBpc0VtcHR5T2JqZWN0KGNoaWxkT2JqZWN0KSkgfHxcbiAgICAgICAgICAgIChBcnJheS5pc0FycmF5KGNoaWxkT2JqZWN0KSAmJiBpc0VtcHR5QXJyYXkoY2hpbGRPYmplY3QpKSkpIHtcbiAgICAgICAgdW5zZXQob2JqZWN0LCBwYXRocy5zbGljZSgwLCAtMSkpO1xuICAgIH1cbiAgICByZXR1cm4gb2JqZWN0O1xufVxuXG52YXIgb2JqZWN0SGFzRnVuY3Rpb24gPSAoZGF0YSkgPT4ge1xuICAgIGZvciAoY29uc3Qga2V5IGluIGRhdGEpIHtcbiAgICAgICAgaWYgKGlzRnVuY3Rpb24oZGF0YVtrZXldKSkge1xuICAgICAgICAgICAgcmV0dXJuIHRydWU7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGZhbHNlO1xufTtcblxuZnVuY3Rpb24gaXNUcmF2ZXJzYWJsZSh2YWx1ZSkge1xuICAgIHJldHVybiBBcnJheS5pc0FycmF5KHZhbHVlKSB8fCAoaXNPYmplY3QodmFsdWUpICYmICFvYmplY3RIYXNGdW5jdGlvbih2YWx1ZSkpO1xufVxuZnVuY3Rpb24gbWFya0ZpZWxkc0RpcnR5KGRhdGEsIGZpZWxkcyA9IHt9KSB7XG4gICAgZm9yIChjb25zdCBrZXkgaW4gZGF0YSkge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGRhdGFba2V5XTtcbiAgICAgICAgaWYgKGlzVHJhdmVyc2FibGUodmFsdWUpKSB7XG4gICAgICAgICAgICBmaWVsZHNba2V5XSA9IEFycmF5LmlzQXJyYXkodmFsdWUpID8gW10gOiB7fTtcbiAgICAgICAgICAgIG1hcmtGaWVsZHNEaXJ0eSh2YWx1ZSwgZmllbGRzW2tleV0pO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKCFpc1VuZGVmaW5lZCh2YWx1ZSkpIHtcbiAgICAgICAgICAgIGZpZWxkc1trZXldID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gZmllbGRzO1xufVxuZnVuY3Rpb24gZ2V0RGlydHlGaWVsZHMoZGF0YSwgZm9ybVZhbHVlcywgZGlydHlGaWVsZHNGcm9tVmFsdWVzKSB7XG4gICAgaWYgKCFkaXJ0eUZpZWxkc0Zyb21WYWx1ZXMpIHtcbiAgICAgICAgZGlydHlGaWVsZHNGcm9tVmFsdWVzID0gbWFya0ZpZWxkc0RpcnR5KGZvcm1WYWx1ZXMpO1xuICAgIH1cbiAgICBmb3IgKGNvbnN0IGtleSBpbiBkYXRhKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gZGF0YVtrZXldO1xuICAgICAgICBpZiAoaXNUcmF2ZXJzYWJsZSh2YWx1ZSkpIHtcbiAgICAgICAgICAgIGlmIChpc1VuZGVmaW5lZChmb3JtVmFsdWVzKSB8fCBpc1ByaW1pdGl2ZShkaXJ0eUZpZWxkc0Zyb21WYWx1ZXNba2V5XSkpIHtcbiAgICAgICAgICAgICAgICBkaXJ0eUZpZWxkc0Zyb21WYWx1ZXNba2V5XSA9IG1hcmtGaWVsZHNEaXJ0eSh2YWx1ZSwgQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyBbXSA6IHt9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIGdldERpcnR5RmllbGRzKHZhbHVlLCBpc051bGxPclVuZGVmaW5lZChmb3JtVmFsdWVzKSA/IHt9IDogZm9ybVZhbHVlc1trZXldLCBkaXJ0eUZpZWxkc0Zyb21WYWx1ZXNba2V5XSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICBjb25zdCBmb3JtVmFsdWUgPSBmb3JtVmFsdWVzW2tleV07XG4gICAgICAgICAgICBkaXJ0eUZpZWxkc0Zyb21WYWx1ZXNba2V5XSA9ICFkZWVwRXF1YWwodmFsdWUsIGZvcm1WYWx1ZSk7XG4gICAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIGRpcnR5RmllbGRzRnJvbVZhbHVlcztcbn1cblxuY29uc3QgZGVmYXVsdFJlc3VsdCA9IHtcbiAgICB2YWx1ZTogZmFsc2UsXG4gICAgaXNWYWxpZDogZmFsc2UsXG59O1xuY29uc3QgdmFsaWRSZXN1bHQgPSB7IHZhbHVlOiB0cnVlLCBpc1ZhbGlkOiB0cnVlIH07XG52YXIgZ2V0Q2hlY2tib3hWYWx1ZSA9IChvcHRpb25zKSA9PiB7XG4gICAgaWYgKEFycmF5LmlzQXJyYXkob3B0aW9ucykpIHtcbiAgICAgICAgaWYgKG9wdGlvbnMubGVuZ3RoID4gMSkge1xuICAgICAgICAgICAgY29uc3QgdmFsdWVzID0gb3B0aW9uc1xuICAgICAgICAgICAgICAgIC5maWx0ZXIoKG9wdGlvbikgPT4gb3B0aW9uICYmIG9wdGlvbi5jaGVja2VkICYmICFvcHRpb24uZGlzYWJsZWQpXG4gICAgICAgICAgICAgICAgLm1hcCgob3B0aW9uKSA9PiBvcHRpb24udmFsdWUpO1xuICAgICAgICAgICAgcmV0dXJuIHsgdmFsdWU6IHZhbHVlcywgaXNWYWxpZDogISF2YWx1ZXMubGVuZ3RoIH07XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIG9wdGlvbnNbMF0uY2hlY2tlZCAmJiAhb3B0aW9uc1swXS5kaXNhYmxlZFxuICAgICAgICAgICAgPyAvLyBAdHMtZXhwZWN0LWVycm9yIGV4cGVjdGVkIHRvIHdvcmsgaW4gdGhlIGJyb3dzZXJcbiAgICAgICAgICAgICAgICBvcHRpb25zWzBdLmF0dHJpYnV0ZXMgJiYgIWlzVW5kZWZpbmVkKG9wdGlvbnNbMF0uYXR0cmlidXRlcy52YWx1ZSlcbiAgICAgICAgICAgICAgICAgICAgPyBpc1VuZGVmaW5lZChvcHRpb25zWzBdLnZhbHVlKSB8fCBvcHRpb25zWzBdLnZhbHVlID09PSAnJ1xuICAgICAgICAgICAgICAgICAgICAgICAgPyB2YWxpZFJlc3VsdFxuICAgICAgICAgICAgICAgICAgICAgICAgOiB7IHZhbHVlOiBvcHRpb25zWzBdLnZhbHVlLCBpc1ZhbGlkOiB0cnVlIH1cbiAgICAgICAgICAgICAgICAgICAgOiB2YWxpZFJlc3VsdFxuICAgICAgICAgICAgOiBkZWZhdWx0UmVzdWx0O1xuICAgIH1cbiAgICByZXR1cm4gZGVmYXVsdFJlc3VsdDtcbn07XG5cbnZhciBnZXRGaWVsZFZhbHVlQXMgPSAodmFsdWUsIHsgdmFsdWVBc051bWJlciwgdmFsdWVBc0RhdGUsIHNldFZhbHVlQXMgfSkgPT4gaXNVbmRlZmluZWQodmFsdWUpXG4gICAgPyB2YWx1ZVxuICAgIDogdmFsdWVBc051bWJlclxuICAgICAgICA/IHZhbHVlID09PSAnJ1xuICAgICAgICAgICAgPyBOYU5cbiAgICAgICAgICAgIDogdmFsdWVcbiAgICAgICAgICAgICAgICA/ICt2YWx1ZVxuICAgICAgICAgICAgICAgIDogdmFsdWVcbiAgICAgICAgOiB2YWx1ZUFzRGF0ZSAmJiBpc1N0cmluZyh2YWx1ZSlcbiAgICAgICAgICAgID8gbmV3IERhdGUodmFsdWUpXG4gICAgICAgICAgICA6IHNldFZhbHVlQXNcbiAgICAgICAgICAgICAgICA/IHNldFZhbHVlQXModmFsdWUpXG4gICAgICAgICAgICAgICAgOiB2YWx1ZTtcblxuY29uc3QgZGVmYXVsdFJldHVybiA9IHtcbiAgICBpc1ZhbGlkOiBmYWxzZSxcbiAgICB2YWx1ZTogbnVsbCxcbn07XG52YXIgZ2V0UmFkaW9WYWx1ZSA9IChvcHRpb25zKSA9PiBBcnJheS5pc0FycmF5KG9wdGlvbnMpXG4gICAgPyBvcHRpb25zLnJlZHVjZSgocHJldmlvdXMsIG9wdGlvbikgPT4gb3B0aW9uICYmIG9wdGlvbi5jaGVja2VkICYmICFvcHRpb24uZGlzYWJsZWRcbiAgICAgICAgPyB7XG4gICAgICAgICAgICBpc1ZhbGlkOiB0cnVlLFxuICAgICAgICAgICAgdmFsdWU6IG9wdGlvbi52YWx1ZSxcbiAgICAgICAgfVxuICAgICAgICA6IHByZXZpb3VzLCBkZWZhdWx0UmV0dXJuKVxuICAgIDogZGVmYXVsdFJldHVybjtcblxuZnVuY3Rpb24gZ2V0RmllbGRWYWx1ZShfZikge1xuICAgIGNvbnN0IHJlZiA9IF9mLnJlZjtcbiAgICBpZiAoaXNGaWxlSW5wdXQocmVmKSkge1xuICAgICAgICByZXR1cm4gcmVmLmZpbGVzO1xuICAgIH1cbiAgICBpZiAoaXNSYWRpb0lucHV0KHJlZikpIHtcbiAgICAgICAgcmV0dXJuIGdldFJhZGlvVmFsdWUoX2YucmVmcykudmFsdWU7XG4gICAgfVxuICAgIGlmIChpc011bHRpcGxlU2VsZWN0KHJlZikpIHtcbiAgICAgICAgcmV0dXJuIFsuLi5yZWYuc2VsZWN0ZWRPcHRpb25zXS5tYXAoKHsgdmFsdWUgfSkgPT4gdmFsdWUpO1xuICAgIH1cbiAgICBpZiAoaXNDaGVja0JveElucHV0KHJlZikpIHtcbiAgICAgICAgcmV0dXJuIGdldENoZWNrYm94VmFsdWUoX2YucmVmcykudmFsdWU7XG4gICAgfVxuICAgIHJldHVybiBnZXRGaWVsZFZhbHVlQXMoaXNVbmRlZmluZWQocmVmLnZhbHVlKSA/IF9mLnJlZi52YWx1ZSA6IHJlZi52YWx1ZSwgX2YpO1xufVxuXG52YXIgZ2V0UmVzb2x2ZXJPcHRpb25zID0gKGZpZWxkc05hbWVzLCBfZmllbGRzLCBjcml0ZXJpYU1vZGUsIHNob3VsZFVzZU5hdGl2ZVZhbGlkYXRpb24pID0+IHtcbiAgICBjb25zdCBmaWVsZHMgPSB7fTtcbiAgICBmb3IgKGNvbnN0IG5hbWUgb2YgZmllbGRzTmFtZXMpIHtcbiAgICAgICAgY29uc3QgZmllbGQgPSBnZXQoX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgIGZpZWxkICYmIHNldChmaWVsZHMsIG5hbWUsIGZpZWxkLl9mKTtcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgICAgY3JpdGVyaWFNb2RlLFxuICAgICAgICBuYW1lczogWy4uLmZpZWxkc05hbWVzXSxcbiAgICAgICAgZmllbGRzLFxuICAgICAgICBzaG91bGRVc2VOYXRpdmVWYWxpZGF0aW9uLFxuICAgIH07XG59O1xuXG52YXIgaXNSZWdleCA9ICh2YWx1ZSkgPT4gdmFsdWUgaW5zdGFuY2VvZiBSZWdFeHA7XG5cbnZhciBnZXRSdWxlVmFsdWUgPSAocnVsZSkgPT4gaXNVbmRlZmluZWQocnVsZSlcbiAgICA/IHJ1bGVcbiAgICA6IGlzUmVnZXgocnVsZSlcbiAgICAgICAgPyBydWxlLnNvdXJjZVxuICAgICAgICA6IGlzT2JqZWN0KHJ1bGUpXG4gICAgICAgICAgICA/IGlzUmVnZXgocnVsZS52YWx1ZSlcbiAgICAgICAgICAgICAgICA/IHJ1bGUudmFsdWUuc291cmNlXG4gICAgICAgICAgICAgICAgOiBydWxlLnZhbHVlXG4gICAgICAgICAgICA6IHJ1bGU7XG5cbnZhciBnZXRWYWxpZGF0aW9uTW9kZXMgPSAobW9kZSkgPT4gKHtcbiAgICBpc09uU3VibWl0OiAhbW9kZSB8fCBtb2RlID09PSBWQUxJREFUSU9OX01PREUub25TdWJtaXQsXG4gICAgaXNPbkJsdXI6IG1vZGUgPT09IFZBTElEQVRJT05fTU9ERS5vbkJsdXIsXG4gICAgaXNPbkNoYW5nZTogbW9kZSA9PT0gVkFMSURBVElPTl9NT0RFLm9uQ2hhbmdlLFxuICAgIGlzT25BbGw6IG1vZGUgPT09IFZBTElEQVRJT05fTU9ERS5hbGwsXG4gICAgaXNPblRvdWNoOiBtb2RlID09PSBWQUxJREFUSU9OX01PREUub25Ub3VjaGVkLFxufSk7XG5cbmNvbnN0IEFTWU5DX0ZVTkNUSU9OID0gJ0FzeW5jRnVuY3Rpb24nO1xudmFyIGhhc1Byb21pc2VWYWxpZGF0aW9uID0gKGZpZWxkUmVmZXJlbmNlKSA9PiAhIWZpZWxkUmVmZXJlbmNlICYmXG4gICAgISFmaWVsZFJlZmVyZW5jZS52YWxpZGF0ZSAmJlxuICAgICEhKChpc0Z1bmN0aW9uKGZpZWxkUmVmZXJlbmNlLnZhbGlkYXRlKSAmJlxuICAgICAgICBmaWVsZFJlZmVyZW5jZS52YWxpZGF0ZS5jb25zdHJ1Y3Rvci5uYW1lID09PSBBU1lOQ19GVU5DVElPTikgfHxcbiAgICAgICAgKGlzT2JqZWN0KGZpZWxkUmVmZXJlbmNlLnZhbGlkYXRlKSAmJlxuICAgICAgICAgICAgT2JqZWN0LnZhbHVlcyhmaWVsZFJlZmVyZW5jZS52YWxpZGF0ZSkuZmluZCgodmFsaWRhdGVGdW5jdGlvbikgPT4gdmFsaWRhdGVGdW5jdGlvbi5jb25zdHJ1Y3Rvci5uYW1lID09PSBBU1lOQ19GVU5DVElPTikpKTtcblxudmFyIGhhc1ZhbGlkYXRpb24gPSAob3B0aW9ucykgPT4gb3B0aW9ucy5tb3VudCAmJlxuICAgIChvcHRpb25zLnJlcXVpcmVkIHx8XG4gICAgICAgIG9wdGlvbnMubWluIHx8XG4gICAgICAgIG9wdGlvbnMubWF4IHx8XG4gICAgICAgIG9wdGlvbnMubWF4TGVuZ3RoIHx8XG4gICAgICAgIG9wdGlvbnMubWluTGVuZ3RoIHx8XG4gICAgICAgIG9wdGlvbnMucGF0dGVybiB8fFxuICAgICAgICBvcHRpb25zLnZhbGlkYXRlKTtcblxudmFyIGlzV2F0Y2hlZCA9IChuYW1lLCBfbmFtZXMsIGlzQmx1ckV2ZW50KSA9PiAhaXNCbHVyRXZlbnQgJiZcbiAgICAoX25hbWVzLndhdGNoQWxsIHx8XG4gICAgICAgIF9uYW1lcy53YXRjaC5oYXMobmFtZSkgfHxcbiAgICAgICAgWy4uLl9uYW1lcy53YXRjaF0uc29tZSgod2F0Y2hOYW1lKSA9PiBuYW1lLnN0YXJ0c1dpdGgod2F0Y2hOYW1lKSAmJlxuICAgICAgICAgICAgL15cXC5cXHcrLy50ZXN0KG5hbWUuc2xpY2Uod2F0Y2hOYW1lLmxlbmd0aCkpKSk7XG5cbmNvbnN0IGl0ZXJhdGVGaWVsZHNCeUFjdGlvbiA9IChmaWVsZHMsIGFjdGlvbiwgZmllbGRzTmFtZXMsIGFib3J0RWFybHkpID0+IHtcbiAgICBmb3IgKGNvbnN0IGtleSBvZiBmaWVsZHNOYW1lcyB8fCBPYmplY3Qua2V5cyhmaWVsZHMpKSB7XG4gICAgICAgIGNvbnN0IGZpZWxkID0gZ2V0KGZpZWxkcywga2V5KTtcbiAgICAgICAgaWYgKGZpZWxkKSB7XG4gICAgICAgICAgICBjb25zdCB7IF9mLCAuLi5jdXJyZW50RmllbGQgfSA9IGZpZWxkO1xuICAgICAgICAgICAgaWYgKF9mKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9mLnJlZnMgJiYgX2YucmVmc1swXSAmJiBhY3Rpb24oX2YucmVmc1swXSwga2V5KSAmJiAhYWJvcnRFYXJseSkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoX2YucmVmICYmIGFjdGlvbihfZi5yZWYsIF9mLm5hbWUpICYmICFhYm9ydEVhcmx5KSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGl0ZXJhdGVGaWVsZHNCeUFjdGlvbihjdXJyZW50RmllbGQsIGFjdGlvbikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSBpZiAoaXNPYmplY3QoY3VycmVudEZpZWxkKSkge1xuICAgICAgICAgICAgICAgIGlmIChpdGVyYXRlRmllbGRzQnlBY3Rpb24oY3VycmVudEZpZWxkLCBhY3Rpb24pKSB7XG4gICAgICAgICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICByZXR1cm47XG59O1xuXG5mdW5jdGlvbiBzY2hlbWFFcnJvckxvb2t1cChlcnJvcnMsIF9maWVsZHMsIG5hbWUpIHtcbiAgICBjb25zdCBlcnJvciA9IGdldChlcnJvcnMsIG5hbWUpO1xuICAgIGlmIChlcnJvciB8fCBpc0tleShuYW1lKSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZXJyb3IsXG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICB9O1xuICAgIH1cbiAgICBjb25zdCBuYW1lcyA9IG5hbWUuc3BsaXQoJy4nKTtcbiAgICB3aGlsZSAobmFtZXMubGVuZ3RoKSB7XG4gICAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IG5hbWVzLmpvaW4oJy4nKTtcbiAgICAgICAgY29uc3QgZmllbGQgPSBnZXQoX2ZpZWxkcywgZmllbGROYW1lKTtcbiAgICAgICAgY29uc3QgZm91bmRFcnJvciA9IGdldChlcnJvcnMsIGZpZWxkTmFtZSk7XG4gICAgICAgIGlmIChmaWVsZCAmJiAhQXJyYXkuaXNBcnJheShmaWVsZCkgJiYgbmFtZSAhPT0gZmllbGROYW1lKSB7XG4gICAgICAgICAgICByZXR1cm4geyBuYW1lIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvdW5kRXJyb3IgJiYgZm91bmRFcnJvci50eXBlKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG5hbWU6IGZpZWxkTmFtZSxcbiAgICAgICAgICAgICAgICBlcnJvcjogZm91bmRFcnJvcixcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGZvdW5kRXJyb3IgJiYgZm91bmRFcnJvci5yb290ICYmIGZvdW5kRXJyb3Iucm9vdC50eXBlKSB7XG4gICAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgICAgIG5hbWU6IGAke2ZpZWxkTmFtZX0ucm9vdGAsXG4gICAgICAgICAgICAgICAgZXJyb3I6IGZvdW5kRXJyb3Iucm9vdCxcbiAgICAgICAgICAgIH07XG4gICAgICAgIH1cbiAgICAgICAgbmFtZXMucG9wKCk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICAgIG5hbWUsXG4gICAgfTtcbn1cblxudmFyIHNob3VsZFJlbmRlckZvcm1TdGF0ZSA9IChmb3JtU3RhdGVEYXRhLCBfcHJveHlGb3JtU3RhdGUsIHVwZGF0ZUZvcm1TdGF0ZSwgaXNSb290KSA9PiB7XG4gICAgdXBkYXRlRm9ybVN0YXRlKGZvcm1TdGF0ZURhdGEpO1xuICAgIGNvbnN0IHsgbmFtZSwgLi4uZm9ybVN0YXRlIH0gPSBmb3JtU3RhdGVEYXRhO1xuICAgIHJldHVybiAoaXNFbXB0eU9iamVjdChmb3JtU3RhdGUpIHx8XG4gICAgICAgIE9iamVjdC5rZXlzKGZvcm1TdGF0ZSkubGVuZ3RoID49IE9iamVjdC5rZXlzKF9wcm94eUZvcm1TdGF0ZSkubGVuZ3RoIHx8XG4gICAgICAgIE9iamVjdC5rZXlzKGZvcm1TdGF0ZSkuZmluZCgoa2V5KSA9PiBfcHJveHlGb3JtU3RhdGVba2V5XSA9PT1cbiAgICAgICAgICAgICghaXNSb290IHx8IFZBTElEQVRJT05fTU9ERS5hbGwpKSk7XG59O1xuXG52YXIgc2hvdWxkU3Vic2NyaWJlQnlOYW1lID0gKG5hbWUsIHNpZ25hbE5hbWUsIGV4YWN0KSA9PiAhbmFtZSB8fFxuICAgICFzaWduYWxOYW1lIHx8XG4gICAgbmFtZSA9PT0gc2lnbmFsTmFtZSB8fFxuICAgIGNvbnZlcnRUb0FycmF5UGF5bG9hZChuYW1lKS5zb21lKChjdXJyZW50TmFtZSkgPT4gY3VycmVudE5hbWUgJiZcbiAgICAgICAgKGV4YWN0XG4gICAgICAgICAgICA/IGN1cnJlbnROYW1lID09PSBzaWduYWxOYW1lXG4gICAgICAgICAgICA6IGN1cnJlbnROYW1lLnN0YXJ0c1dpdGgoc2lnbmFsTmFtZSkgfHxcbiAgICAgICAgICAgICAgICBzaWduYWxOYW1lLnN0YXJ0c1dpdGgoY3VycmVudE5hbWUpKSk7XG5cbnZhciBza2lwVmFsaWRhdGlvbiA9IChpc0JsdXJFdmVudCwgaXNUb3VjaGVkLCBpc1N1Ym1pdHRlZCwgcmVWYWxpZGF0ZU1vZGUsIG1vZGUpID0+IHtcbiAgICBpZiAobW9kZS5pc09uQWxsKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG4gICAgZWxzZSBpZiAoIWlzU3VibWl0dGVkICYmIG1vZGUuaXNPblRvdWNoKSB7XG4gICAgICAgIHJldHVybiAhKGlzVG91Y2hlZCB8fCBpc0JsdXJFdmVudCk7XG4gICAgfVxuICAgIGVsc2UgaWYgKGlzU3VibWl0dGVkID8gcmVWYWxpZGF0ZU1vZGUuaXNPbkJsdXIgOiBtb2RlLmlzT25CbHVyKSB7XG4gICAgICAgIHJldHVybiAhaXNCbHVyRXZlbnQ7XG4gICAgfVxuICAgIGVsc2UgaWYgKGlzU3VibWl0dGVkID8gcmVWYWxpZGF0ZU1vZGUuaXNPbkNoYW5nZSA6IG1vZGUuaXNPbkNoYW5nZSkge1xuICAgICAgICByZXR1cm4gaXNCbHVyRXZlbnQ7XG4gICAgfVxuICAgIHJldHVybiB0cnVlO1xufTtcblxudmFyIHVuc2V0RW1wdHlBcnJheSA9IChyZWYsIG5hbWUpID0+ICFjb21wYWN0KGdldChyZWYsIG5hbWUpKS5sZW5ndGggJiYgdW5zZXQocmVmLCBuYW1lKTtcblxudmFyIHVwZGF0ZUZpZWxkQXJyYXlSb290RXJyb3IgPSAoZXJyb3JzLCBlcnJvciwgbmFtZSkgPT4ge1xuICAgIGNvbnN0IGZpZWxkQXJyYXlFcnJvcnMgPSBjb252ZXJ0VG9BcnJheVBheWxvYWQoZ2V0KGVycm9ycywgbmFtZSkpO1xuICAgIHNldChmaWVsZEFycmF5RXJyb3JzLCAncm9vdCcsIGVycm9yW25hbWVdKTtcbiAgICBzZXQoZXJyb3JzLCBuYW1lLCBmaWVsZEFycmF5RXJyb3JzKTtcbiAgICByZXR1cm4gZXJyb3JzO1xufTtcblxuZnVuY3Rpb24gZ2V0VmFsaWRhdGVFcnJvcihyZXN1bHQsIHJlZiwgdHlwZSA9ICd2YWxpZGF0ZScpIHtcbiAgICBpZiAoaXNTdHJpbmcocmVzdWx0KSB8fFxuICAgICAgICAoQXJyYXkuaXNBcnJheShyZXN1bHQpICYmIHJlc3VsdC5ldmVyeShpc1N0cmluZykpIHx8XG4gICAgICAgIChpc0Jvb2xlYW4ocmVzdWx0KSAmJiAhcmVzdWx0KSkge1xuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgdHlwZSxcbiAgICAgICAgICAgIG1lc3NhZ2U6IGlzU3RyaW5nKHJlc3VsdCkgPyByZXN1bHQgOiAnJyxcbiAgICAgICAgICAgIHJlZixcbiAgICAgICAgfTtcbiAgICB9XG59XG5cbnZhciBnZXRWYWx1ZUFuZE1lc3NhZ2UgPSAodmFsaWRhdGlvbkRhdGEpID0+IGlzT2JqZWN0KHZhbGlkYXRpb25EYXRhKSAmJiAhaXNSZWdleCh2YWxpZGF0aW9uRGF0YSlcbiAgICA/IHZhbGlkYXRpb25EYXRhXG4gICAgOiB7XG4gICAgICAgIHZhbHVlOiB2YWxpZGF0aW9uRGF0YSxcbiAgICAgICAgbWVzc2FnZTogJycsXG4gICAgfTtcblxudmFyIHZhbGlkYXRlRmllbGQgPSBhc3luYyAoZmllbGQsIGRpc2FibGVkRmllbGROYW1lcywgZm9ybVZhbHVlcywgdmFsaWRhdGVBbGxGaWVsZENyaXRlcmlhLCBzaG91bGRVc2VOYXRpdmVWYWxpZGF0aW9uLCBpc0ZpZWxkQXJyYXkpID0+IHtcbiAgICBjb25zdCB7IHJlZiwgcmVmcywgcmVxdWlyZWQsIG1heExlbmd0aCwgbWluTGVuZ3RoLCBtaW4sIG1heCwgcGF0dGVybiwgdmFsaWRhdGUsIG5hbWUsIHZhbHVlQXNOdW1iZXIsIG1vdW50LCB9ID0gZmllbGQuX2Y7XG4gICAgY29uc3QgaW5wdXRWYWx1ZSA9IGdldChmb3JtVmFsdWVzLCBuYW1lKTtcbiAgICBpZiAoIW1vdW50IHx8IGRpc2FibGVkRmllbGROYW1lcy5oYXMobmFtZSkpIHtcbiAgICAgICAgcmV0dXJuIHt9O1xuICAgIH1cbiAgICBjb25zdCBpbnB1dFJlZiA9IHJlZnMgPyByZWZzWzBdIDogcmVmO1xuICAgIGNvbnN0IHNldEN1c3RvbVZhbGlkaXR5ID0gKG1lc3NhZ2UpID0+IHtcbiAgICAgICAgaWYgKHNob3VsZFVzZU5hdGl2ZVZhbGlkYXRpb24gJiYgaW5wdXRSZWYucmVwb3J0VmFsaWRpdHkpIHtcbiAgICAgICAgICAgIGlucHV0UmVmLnNldEN1c3RvbVZhbGlkaXR5KGlzQm9vbGVhbihtZXNzYWdlKSA/ICcnIDogbWVzc2FnZSB8fCAnJyk7XG4gICAgICAgICAgICBpbnB1dFJlZi5yZXBvcnRWYWxpZGl0eSgpO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBjb25zdCBlcnJvciA9IHt9O1xuICAgIGNvbnN0IGlzUmFkaW8gPSBpc1JhZGlvSW5wdXQocmVmKTtcbiAgICBjb25zdCBpc0NoZWNrQm94ID0gaXNDaGVja0JveElucHV0KHJlZik7XG4gICAgY29uc3QgaXNSYWRpb09yQ2hlY2tib3ggPSBpc1JhZGlvIHx8IGlzQ2hlY2tCb3g7XG4gICAgY29uc3QgaXNFbXB0eSA9ICgodmFsdWVBc051bWJlciB8fCBpc0ZpbGVJbnB1dChyZWYpKSAmJlxuICAgICAgICBpc1VuZGVmaW5lZChyZWYudmFsdWUpICYmXG4gICAgICAgIGlzVW5kZWZpbmVkKGlucHV0VmFsdWUpKSB8fFxuICAgICAgICAoaXNIVE1MRWxlbWVudChyZWYpICYmIHJlZi52YWx1ZSA9PT0gJycpIHx8XG4gICAgICAgIGlucHV0VmFsdWUgPT09ICcnIHx8XG4gICAgICAgIChBcnJheS5pc0FycmF5KGlucHV0VmFsdWUpICYmICFpbnB1dFZhbHVlLmxlbmd0aCk7XG4gICAgY29uc3QgYXBwZW5kRXJyb3JzQ3VycnkgPSBhcHBlbmRFcnJvcnMuYmluZChudWxsLCBuYW1lLCB2YWxpZGF0ZUFsbEZpZWxkQ3JpdGVyaWEsIGVycm9yKTtcbiAgICBjb25zdCBnZXRNaW5NYXhNZXNzYWdlID0gKGV4Y2VlZE1heCwgbWF4TGVuZ3RoTWVzc2FnZSwgbWluTGVuZ3RoTWVzc2FnZSwgbWF4VHlwZSA9IElOUFVUX1ZBTElEQVRJT05fUlVMRVMubWF4TGVuZ3RoLCBtaW5UeXBlID0gSU5QVVRfVkFMSURBVElPTl9SVUxFUy5taW5MZW5ndGgpID0+IHtcbiAgICAgICAgY29uc3QgbWVzc2FnZSA9IGV4Y2VlZE1heCA/IG1heExlbmd0aE1lc3NhZ2UgOiBtaW5MZW5ndGhNZXNzYWdlO1xuICAgICAgICBlcnJvcltuYW1lXSA9IHtcbiAgICAgICAgICAgIHR5cGU6IGV4Y2VlZE1heCA/IG1heFR5cGUgOiBtaW5UeXBlLFxuICAgICAgICAgICAgbWVzc2FnZSxcbiAgICAgICAgICAgIHJlZixcbiAgICAgICAgICAgIC4uLmFwcGVuZEVycm9yc0N1cnJ5KGV4Y2VlZE1heCA/IG1heFR5cGUgOiBtaW5UeXBlLCBtZXNzYWdlKSxcbiAgICAgICAgfTtcbiAgICB9O1xuICAgIGlmIChpc0ZpZWxkQXJyYXlcbiAgICAgICAgPyAhQXJyYXkuaXNBcnJheShpbnB1dFZhbHVlKSB8fCAhaW5wdXRWYWx1ZS5sZW5ndGhcbiAgICAgICAgOiByZXF1aXJlZCAmJlxuICAgICAgICAgICAgKCghaXNSYWRpb09yQ2hlY2tib3ggJiYgKGlzRW1wdHkgfHwgaXNOdWxsT3JVbmRlZmluZWQoaW5wdXRWYWx1ZSkpKSB8fFxuICAgICAgICAgICAgICAgIChpc0Jvb2xlYW4oaW5wdXRWYWx1ZSkgJiYgIWlucHV0VmFsdWUpIHx8XG4gICAgICAgICAgICAgICAgKGlzQ2hlY2tCb3ggJiYgIWdldENoZWNrYm94VmFsdWUocmVmcykuaXNWYWxpZCkgfHxcbiAgICAgICAgICAgICAgICAoaXNSYWRpbyAmJiAhZ2V0UmFkaW9WYWx1ZShyZWZzKS5pc1ZhbGlkKSkpIHtcbiAgICAgICAgY29uc3QgeyB2YWx1ZSwgbWVzc2FnZSB9ID0gaXNTdHJpbmcocmVxdWlyZWQpXG4gICAgICAgICAgICA/IHsgdmFsdWU6ICEhcmVxdWlyZWQsIG1lc3NhZ2U6IHJlcXVpcmVkIH1cbiAgICAgICAgICAgIDogZ2V0VmFsdWVBbmRNZXNzYWdlKHJlcXVpcmVkKTtcbiAgICAgICAgaWYgKHZhbHVlKSB7XG4gICAgICAgICAgICBlcnJvcltuYW1lXSA9IHtcbiAgICAgICAgICAgICAgICB0eXBlOiBJTlBVVF9WQUxJREFUSU9OX1JVTEVTLnJlcXVpcmVkLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgcmVmOiBpbnB1dFJlZixcbiAgICAgICAgICAgICAgICAuLi5hcHBlbmRFcnJvcnNDdXJyeShJTlBVVF9WQUxJREFUSU9OX1JVTEVTLnJlcXVpcmVkLCBtZXNzYWdlKSxcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICBpZiAoIXZhbGlkYXRlQWxsRmllbGRDcml0ZXJpYSkge1xuICAgICAgICAgICAgICAgIHNldEN1c3RvbVZhbGlkaXR5KG1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgIHJldHVybiBlcnJvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoIWlzRW1wdHkgJiYgKCFpc051bGxPclVuZGVmaW5lZChtaW4pIHx8ICFpc051bGxPclVuZGVmaW5lZChtYXgpKSkge1xuICAgICAgICBsZXQgZXhjZWVkTWF4O1xuICAgICAgICBsZXQgZXhjZWVkTWluO1xuICAgICAgICBjb25zdCBtYXhPdXRwdXQgPSBnZXRWYWx1ZUFuZE1lc3NhZ2UobWF4KTtcbiAgICAgICAgY29uc3QgbWluT3V0cHV0ID0gZ2V0VmFsdWVBbmRNZXNzYWdlKG1pbik7XG4gICAgICAgIGlmICghaXNOdWxsT3JVbmRlZmluZWQoaW5wdXRWYWx1ZSkgJiYgIWlzTmFOKGlucHV0VmFsdWUpKSB7XG4gICAgICAgICAgICBjb25zdCB2YWx1ZU51bWJlciA9IHJlZi52YWx1ZUFzTnVtYmVyIHx8XG4gICAgICAgICAgICAgICAgKGlucHV0VmFsdWUgPyAraW5wdXRWYWx1ZSA6IGlucHV0VmFsdWUpO1xuICAgICAgICAgICAgaWYgKCFpc051bGxPclVuZGVmaW5lZChtYXhPdXRwdXQudmFsdWUpKSB7XG4gICAgICAgICAgICAgICAgZXhjZWVkTWF4ID0gdmFsdWVOdW1iZXIgPiBtYXhPdXRwdXQudmFsdWU7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWlzTnVsbE9yVW5kZWZpbmVkKG1pbk91dHB1dC52YWx1ZSkpIHtcbiAgICAgICAgICAgICAgICBleGNlZWRNaW4gPSB2YWx1ZU51bWJlciA8IG1pbk91dHB1dC52YWx1ZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHZhbHVlRGF0ZSA9IHJlZi52YWx1ZUFzRGF0ZSB8fCBuZXcgRGF0ZShpbnB1dFZhbHVlKTtcbiAgICAgICAgICAgIGNvbnN0IGNvbnZlcnRUaW1lVG9EYXRlID0gKHRpbWUpID0+IG5ldyBEYXRlKG5ldyBEYXRlKCkudG9EYXRlU3RyaW5nKCkgKyAnICcgKyB0aW1lKTtcbiAgICAgICAgICAgIGNvbnN0IGlzVGltZSA9IHJlZi50eXBlID09ICd0aW1lJztcbiAgICAgICAgICAgIGNvbnN0IGlzV2VlayA9IHJlZi50eXBlID09ICd3ZWVrJztcbiAgICAgICAgICAgIGlmIChpc1N0cmluZyhtYXhPdXRwdXQudmFsdWUpICYmIGlucHV0VmFsdWUpIHtcbiAgICAgICAgICAgICAgICBleGNlZWRNYXggPSBpc1RpbWVcbiAgICAgICAgICAgICAgICAgICAgPyBjb252ZXJ0VGltZVRvRGF0ZShpbnB1dFZhbHVlKSA+IGNvbnZlcnRUaW1lVG9EYXRlKG1heE91dHB1dC52YWx1ZSlcbiAgICAgICAgICAgICAgICAgICAgOiBpc1dlZWtcbiAgICAgICAgICAgICAgICAgICAgICAgID8gaW5wdXRWYWx1ZSA+IG1heE91dHB1dC52YWx1ZVxuICAgICAgICAgICAgICAgICAgICAgICAgOiB2YWx1ZURhdGUgPiBuZXcgRGF0ZShtYXhPdXRwdXQudmFsdWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzU3RyaW5nKG1pbk91dHB1dC52YWx1ZSkgJiYgaW5wdXRWYWx1ZSkge1xuICAgICAgICAgICAgICAgIGV4Y2VlZE1pbiA9IGlzVGltZVxuICAgICAgICAgICAgICAgICAgICA/IGNvbnZlcnRUaW1lVG9EYXRlKGlucHV0VmFsdWUpIDwgY29udmVydFRpbWVUb0RhdGUobWluT3V0cHV0LnZhbHVlKVxuICAgICAgICAgICAgICAgICAgICA6IGlzV2Vla1xuICAgICAgICAgICAgICAgICAgICAgICAgPyBpbnB1dFZhbHVlIDwgbWluT3V0cHV0LnZhbHVlXG4gICAgICAgICAgICAgICAgICAgICAgICA6IHZhbHVlRGF0ZSA8IG5ldyBEYXRlKG1pbk91dHB1dC52YWx1ZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgaWYgKGV4Y2VlZE1heCB8fCBleGNlZWRNaW4pIHtcbiAgICAgICAgICAgIGdldE1pbk1heE1lc3NhZ2UoISFleGNlZWRNYXgsIG1heE91dHB1dC5tZXNzYWdlLCBtaW5PdXRwdXQubWVzc2FnZSwgSU5QVVRfVkFMSURBVElPTl9SVUxFUy5tYXgsIElOUFVUX1ZBTElEQVRJT05fUlVMRVMubWluKTtcbiAgICAgICAgICAgIGlmICghdmFsaWRhdGVBbGxGaWVsZENyaXRlcmlhKSB7XG4gICAgICAgICAgICAgICAgc2V0Q3VzdG9tVmFsaWRpdHkoZXJyb3JbbmFtZV0ubWVzc2FnZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGVycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuICAgIGlmICgobWF4TGVuZ3RoIHx8IG1pbkxlbmd0aCkgJiZcbiAgICAgICAgIWlzRW1wdHkgJiZcbiAgICAgICAgKGlzU3RyaW5nKGlucHV0VmFsdWUpIHx8IChpc0ZpZWxkQXJyYXkgJiYgQXJyYXkuaXNBcnJheShpbnB1dFZhbHVlKSkpKSB7XG4gICAgICAgIGNvbnN0IG1heExlbmd0aE91dHB1dCA9IGdldFZhbHVlQW5kTWVzc2FnZShtYXhMZW5ndGgpO1xuICAgICAgICBjb25zdCBtaW5MZW5ndGhPdXRwdXQgPSBnZXRWYWx1ZUFuZE1lc3NhZ2UobWluTGVuZ3RoKTtcbiAgICAgICAgY29uc3QgZXhjZWVkTWF4ID0gIWlzTnVsbE9yVW5kZWZpbmVkKG1heExlbmd0aE91dHB1dC52YWx1ZSkgJiZcbiAgICAgICAgICAgIGlucHV0VmFsdWUubGVuZ3RoID4gK21heExlbmd0aE91dHB1dC52YWx1ZTtcbiAgICAgICAgY29uc3QgZXhjZWVkTWluID0gIWlzTnVsbE9yVW5kZWZpbmVkKG1pbkxlbmd0aE91dHB1dC52YWx1ZSkgJiZcbiAgICAgICAgICAgIGlucHV0VmFsdWUubGVuZ3RoIDwgK21pbkxlbmd0aE91dHB1dC52YWx1ZTtcbiAgICAgICAgaWYgKGV4Y2VlZE1heCB8fCBleGNlZWRNaW4pIHtcbiAgICAgICAgICAgIGdldE1pbk1heE1lc3NhZ2UoZXhjZWVkTWF4LCBtYXhMZW5ndGhPdXRwdXQubWVzc2FnZSwgbWluTGVuZ3RoT3V0cHV0Lm1lc3NhZ2UpO1xuICAgICAgICAgICAgaWYgKCF2YWxpZGF0ZUFsbEZpZWxkQ3JpdGVyaWEpIHtcbiAgICAgICAgICAgICAgICBzZXRDdXN0b21WYWxpZGl0eShlcnJvcltuYW1lXS5tZXNzYWdlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHBhdHRlcm4gJiYgIWlzRW1wdHkgJiYgaXNTdHJpbmcoaW5wdXRWYWx1ZSkpIHtcbiAgICAgICAgY29uc3QgeyB2YWx1ZTogcGF0dGVyblZhbHVlLCBtZXNzYWdlIH0gPSBnZXRWYWx1ZUFuZE1lc3NhZ2UocGF0dGVybik7XG4gICAgICAgIGlmIChpc1JlZ2V4KHBhdHRlcm5WYWx1ZSkgJiYgIWlucHV0VmFsdWUubWF0Y2gocGF0dGVyblZhbHVlKSkge1xuICAgICAgICAgICAgZXJyb3JbbmFtZV0gPSB7XG4gICAgICAgICAgICAgICAgdHlwZTogSU5QVVRfVkFMSURBVElPTl9SVUxFUy5wYXR0ZXJuLFxuICAgICAgICAgICAgICAgIG1lc3NhZ2UsXG4gICAgICAgICAgICAgICAgcmVmLFxuICAgICAgICAgICAgICAgIC4uLmFwcGVuZEVycm9yc0N1cnJ5KElOUFVUX1ZBTElEQVRJT05fUlVMRVMucGF0dGVybiwgbWVzc2FnZSksXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgaWYgKCF2YWxpZGF0ZUFsbEZpZWxkQ3JpdGVyaWEpIHtcbiAgICAgICAgICAgICAgICBzZXRDdXN0b21WYWxpZGl0eShtZXNzYWdlKTtcbiAgICAgICAgICAgICAgICByZXR1cm4gZXJyb3I7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKHZhbGlkYXRlKSB7XG4gICAgICAgIGlmIChpc0Z1bmN0aW9uKHZhbGlkYXRlKSkge1xuICAgICAgICAgICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgdmFsaWRhdGUoaW5wdXRWYWx1ZSwgZm9ybVZhbHVlcyk7XG4gICAgICAgICAgICBjb25zdCB2YWxpZGF0ZUVycm9yID0gZ2V0VmFsaWRhdGVFcnJvcihyZXN1bHQsIGlucHV0UmVmKTtcbiAgICAgICAgICAgIGlmICh2YWxpZGF0ZUVycm9yKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JbbmFtZV0gPSB7XG4gICAgICAgICAgICAgICAgICAgIC4uLnZhbGlkYXRlRXJyb3IsXG4gICAgICAgICAgICAgICAgICAgIC4uLmFwcGVuZEVycm9yc0N1cnJ5KElOUFVUX1ZBTElEQVRJT05fUlVMRVMudmFsaWRhdGUsIHZhbGlkYXRlRXJyb3IubWVzc2FnZSksXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgICAgICBpZiAoIXZhbGlkYXRlQWxsRmllbGRDcml0ZXJpYSkge1xuICAgICAgICAgICAgICAgICAgICBzZXRDdXN0b21WYWxpZGl0eSh2YWxpZGF0ZUVycm9yLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gZXJyb3I7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKGlzT2JqZWN0KHZhbGlkYXRlKSkge1xuICAgICAgICAgICAgbGV0IHZhbGlkYXRpb25SZXN1bHQgPSB7fTtcbiAgICAgICAgICAgIGZvciAoY29uc3Qga2V5IGluIHZhbGlkYXRlKSB7XG4gICAgICAgICAgICAgICAgaWYgKCFpc0VtcHR5T2JqZWN0KHZhbGlkYXRpb25SZXN1bHQpICYmICF2YWxpZGF0ZUFsbEZpZWxkQ3JpdGVyaWEpIHtcbiAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIGNvbnN0IHZhbGlkYXRlRXJyb3IgPSBnZXRWYWxpZGF0ZUVycm9yKGF3YWl0IHZhbGlkYXRlW2tleV0oaW5wdXRWYWx1ZSwgZm9ybVZhbHVlcyksIGlucHV0UmVmLCBrZXkpO1xuICAgICAgICAgICAgICAgIGlmICh2YWxpZGF0ZUVycm9yKSB7XG4gICAgICAgICAgICAgICAgICAgIHZhbGlkYXRpb25SZXN1bHQgPSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAuLi52YWxpZGF0ZUVycm9yLFxuICAgICAgICAgICAgICAgICAgICAgICAgLi4uYXBwZW5kRXJyb3JzQ3Vycnkoa2V5LCB2YWxpZGF0ZUVycm9yLm1lc3NhZ2UpLFxuICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICBzZXRDdXN0b21WYWxpZGl0eSh2YWxpZGF0ZUVycm9yLm1lc3NhZ2UpO1xuICAgICAgICAgICAgICAgICAgICBpZiAodmFsaWRhdGVBbGxGaWVsZENyaXRlcmlhKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvcltuYW1lXSA9IHZhbGlkYXRpb25SZXN1bHQ7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoIWlzRW1wdHlPYmplY3QodmFsaWRhdGlvblJlc3VsdCkpIHtcbiAgICAgICAgICAgICAgICBlcnJvcltuYW1lXSA9IHtcbiAgICAgICAgICAgICAgICAgICAgcmVmOiBpbnB1dFJlZixcbiAgICAgICAgICAgICAgICAgICAgLi4udmFsaWRhdGlvblJlc3VsdCxcbiAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgIGlmICghdmFsaWRhdGVBbGxGaWVsZENyaXRlcmlhKSB7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiBlcnJvcjtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG4gICAgc2V0Q3VzdG9tVmFsaWRpdHkodHJ1ZSk7XG4gICAgcmV0dXJuIGVycm9yO1xufTtcblxuY29uc3QgZGVmYXVsdE9wdGlvbnMgPSB7XG4gICAgbW9kZTogVkFMSURBVElPTl9NT0RFLm9uU3VibWl0LFxuICAgIHJlVmFsaWRhdGVNb2RlOiBWQUxJREFUSU9OX01PREUub25DaGFuZ2UsXG4gICAgc2hvdWxkRm9jdXNFcnJvcjogdHJ1ZSxcbn07XG5mdW5jdGlvbiBjcmVhdGVGb3JtQ29udHJvbChwcm9wcyA9IHt9KSB7XG4gICAgbGV0IF9vcHRpb25zID0ge1xuICAgICAgICAuLi5kZWZhdWx0T3B0aW9ucyxcbiAgICAgICAgLi4ucHJvcHMsXG4gICAgfTtcbiAgICBsZXQgX2Zvcm1TdGF0ZSA9IHtcbiAgICAgICAgc3VibWl0Q291bnQ6IDAsXG4gICAgICAgIGlzRGlydHk6IGZhbHNlLFxuICAgICAgICBpc1JlYWR5OiBmYWxzZSxcbiAgICAgICAgaXNMb2FkaW5nOiBpc0Z1bmN0aW9uKF9vcHRpb25zLmRlZmF1bHRWYWx1ZXMpLFxuICAgICAgICBpc1ZhbGlkYXRpbmc6IGZhbHNlLFxuICAgICAgICBpc1N1Ym1pdHRlZDogZmFsc2UsXG4gICAgICAgIGlzU3VibWl0dGluZzogZmFsc2UsXG4gICAgICAgIGlzU3VibWl0U3VjY2Vzc2Z1bDogZmFsc2UsXG4gICAgICAgIGlzVmFsaWQ6IGZhbHNlLFxuICAgICAgICB0b3VjaGVkRmllbGRzOiB7fSxcbiAgICAgICAgZGlydHlGaWVsZHM6IHt9LFxuICAgICAgICB2YWxpZGF0aW5nRmllbGRzOiB7fSxcbiAgICAgICAgZXJyb3JzOiBfb3B0aW9ucy5lcnJvcnMgfHwge30sXG4gICAgICAgIGRpc2FibGVkOiBfb3B0aW9ucy5kaXNhYmxlZCB8fCBmYWxzZSxcbiAgICB9O1xuICAgIGxldCBfZmllbGRzID0ge307XG4gICAgbGV0IF9kZWZhdWx0VmFsdWVzID0gaXNPYmplY3QoX29wdGlvbnMuZGVmYXVsdFZhbHVlcykgfHwgaXNPYmplY3QoX29wdGlvbnMudmFsdWVzKVxuICAgICAgICA/IGNsb25lT2JqZWN0KF9vcHRpb25zLmRlZmF1bHRWYWx1ZXMgfHwgX29wdGlvbnMudmFsdWVzKSB8fCB7fVxuICAgICAgICA6IHt9O1xuICAgIGxldCBfZm9ybVZhbHVlcyA9IF9vcHRpb25zLnNob3VsZFVucmVnaXN0ZXJcbiAgICAgICAgPyB7fVxuICAgICAgICA6IGNsb25lT2JqZWN0KF9kZWZhdWx0VmFsdWVzKTtcbiAgICBsZXQgX3N0YXRlID0ge1xuICAgICAgICBhY3Rpb246IGZhbHNlLFxuICAgICAgICBtb3VudDogZmFsc2UsXG4gICAgICAgIHdhdGNoOiBmYWxzZSxcbiAgICB9O1xuICAgIGxldCBfbmFtZXMgPSB7XG4gICAgICAgIG1vdW50OiBuZXcgU2V0KCksXG4gICAgICAgIGRpc2FibGVkOiBuZXcgU2V0KCksXG4gICAgICAgIHVuTW91bnQ6IG5ldyBTZXQoKSxcbiAgICAgICAgYXJyYXk6IG5ldyBTZXQoKSxcbiAgICAgICAgd2F0Y2g6IG5ldyBTZXQoKSxcbiAgICB9O1xuICAgIGxldCBkZWxheUVycm9yQ2FsbGJhY2s7XG4gICAgbGV0IHRpbWVyID0gMDtcbiAgICBjb25zdCBfcHJveHlGb3JtU3RhdGUgPSB7XG4gICAgICAgIGlzRGlydHk6IGZhbHNlLFxuICAgICAgICBkaXJ0eUZpZWxkczogZmFsc2UsXG4gICAgICAgIHZhbGlkYXRpbmdGaWVsZHM6IGZhbHNlLFxuICAgICAgICB0b3VjaGVkRmllbGRzOiBmYWxzZSxcbiAgICAgICAgaXNWYWxpZGF0aW5nOiBmYWxzZSxcbiAgICAgICAgaXNWYWxpZDogZmFsc2UsXG4gICAgICAgIGVycm9yczogZmFsc2UsXG4gICAgfTtcbiAgICBsZXQgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlID0ge1xuICAgICAgICAuLi5fcHJveHlGb3JtU3RhdGUsXG4gICAgfTtcbiAgICBjb25zdCBfc3ViamVjdHMgPSB7XG4gICAgICAgIGFycmF5OiBjcmVhdGVTdWJqZWN0KCksXG4gICAgICAgIHN0YXRlOiBjcmVhdGVTdWJqZWN0KCksXG4gICAgfTtcbiAgICBjb25zdCBzaG91bGREaXNwbGF5QWxsQXNzb2NpYXRlZEVycm9ycyA9IF9vcHRpb25zLmNyaXRlcmlhTW9kZSA9PT0gVkFMSURBVElPTl9NT0RFLmFsbDtcbiAgICBjb25zdCBkZWJvdW5jZSA9IChjYWxsYmFjaykgPT4gKHdhaXQpID0+IHtcbiAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgdGltZXIgPSBzZXRUaW1lb3V0KGNhbGxiYWNrLCB3YWl0KTtcbiAgICB9O1xuICAgIGNvbnN0IF9zZXRWYWxpZCA9IGFzeW5jIChzaG91bGRVcGRhdGVWYWxpZCkgPT4ge1xuICAgICAgICBpZiAoIV9vcHRpb25zLmRpc2FibGVkICYmXG4gICAgICAgICAgICAoX3Byb3h5Rm9ybVN0YXRlLmlzVmFsaWQgfHxcbiAgICAgICAgICAgICAgICBfcHJveHlTdWJzY3JpYmVGb3JtU3RhdGUuaXNWYWxpZCB8fFxuICAgICAgICAgICAgICAgIHNob3VsZFVwZGF0ZVZhbGlkKSkge1xuICAgICAgICAgICAgY29uc3QgaXNWYWxpZCA9IF9vcHRpb25zLnJlc29sdmVyXG4gICAgICAgICAgICAgICAgPyBpc0VtcHR5T2JqZWN0KChhd2FpdCBfcnVuU2NoZW1hKCkpLmVycm9ycylcbiAgICAgICAgICAgICAgICA6IGF3YWl0IGV4ZWN1dGVCdWlsdEluVmFsaWRhdGlvbihfZmllbGRzLCB0cnVlKTtcbiAgICAgICAgICAgIGlmIChpc1ZhbGlkICE9PSBfZm9ybVN0YXRlLmlzVmFsaWQpIHtcbiAgICAgICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICAgICAgICAgIGlzVmFsaWQsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IF91cGRhdGVJc1ZhbGlkYXRpbmcgPSAobmFtZXMsIGlzVmFsaWRhdGluZykgPT4ge1xuICAgICAgICBpZiAoIV9vcHRpb25zLmRpc2FibGVkICYmXG4gICAgICAgICAgICAoX3Byb3h5Rm9ybVN0YXRlLmlzVmFsaWRhdGluZyB8fFxuICAgICAgICAgICAgICAgIF9wcm94eUZvcm1TdGF0ZS52YWxpZGF0aW5nRmllbGRzIHx8XG4gICAgICAgICAgICAgICAgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlLmlzVmFsaWRhdGluZyB8fFxuICAgICAgICAgICAgICAgIF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZS52YWxpZGF0aW5nRmllbGRzKSkge1xuICAgICAgICAgICAgKG5hbWVzIHx8IEFycmF5LmZyb20oX25hbWVzLm1vdW50KSkuZm9yRWFjaCgobmFtZSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChuYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgIGlzVmFsaWRhdGluZ1xuICAgICAgICAgICAgICAgICAgICAgICAgPyBzZXQoX2Zvcm1TdGF0ZS52YWxpZGF0aW5nRmllbGRzLCBuYW1lLCBpc1ZhbGlkYXRpbmcpXG4gICAgICAgICAgICAgICAgICAgICAgICA6IHVuc2V0KF9mb3JtU3RhdGUudmFsaWRhdGluZ0ZpZWxkcywgbmFtZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICAgICAgdmFsaWRhdGluZ0ZpZWxkczogX2Zvcm1TdGF0ZS52YWxpZGF0aW5nRmllbGRzLFxuICAgICAgICAgICAgICAgIGlzVmFsaWRhdGluZzogIWlzRW1wdHlPYmplY3QoX2Zvcm1TdGF0ZS52YWxpZGF0aW5nRmllbGRzKSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG4gICAgfTtcbiAgICBjb25zdCBfc2V0RmllbGRBcnJheSA9IChuYW1lLCB2YWx1ZXMgPSBbXSwgbWV0aG9kLCBhcmdzLCBzaG91bGRTZXRWYWx1ZXMgPSB0cnVlLCBzaG91bGRVcGRhdGVGaWVsZHNBbmRTdGF0ZSA9IHRydWUpID0+IHtcbiAgICAgICAgaWYgKGFyZ3MgJiYgbWV0aG9kICYmICFfb3B0aW9ucy5kaXNhYmxlZCkge1xuICAgICAgICAgICAgX3N0YXRlLmFjdGlvbiA9IHRydWU7XG4gICAgICAgICAgICBpZiAoc2hvdWxkVXBkYXRlRmllbGRzQW5kU3RhdGUgJiYgQXJyYXkuaXNBcnJheShnZXQoX2ZpZWxkcywgbmFtZSkpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmllbGRWYWx1ZXMgPSBtZXRob2QoZ2V0KF9maWVsZHMsIG5hbWUpLCBhcmdzLmFyZ0EsIGFyZ3MuYXJnQik7XG4gICAgICAgICAgICAgICAgc2hvdWxkU2V0VmFsdWVzICYmIHNldChfZmllbGRzLCBuYW1lLCBmaWVsZFZhbHVlcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoc2hvdWxkVXBkYXRlRmllbGRzQW5kU3RhdGUgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KGdldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSkpKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXJyb3JzID0gbWV0aG9kKGdldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSksIGFyZ3MuYXJnQSwgYXJncy5hcmdCKTtcbiAgICAgICAgICAgICAgICBzaG91bGRTZXRWYWx1ZXMgJiYgc2V0KF9mb3JtU3RhdGUuZXJyb3JzLCBuYW1lLCBlcnJvcnMpO1xuICAgICAgICAgICAgICAgIHVuc2V0RW1wdHlBcnJheShfZm9ybVN0YXRlLmVycm9ycywgbmFtZSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoKF9wcm94eUZvcm1TdGF0ZS50b3VjaGVkRmllbGRzIHx8XG4gICAgICAgICAgICAgICAgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlLnRvdWNoZWRGaWVsZHMpICYmXG4gICAgICAgICAgICAgICAgc2hvdWxkVXBkYXRlRmllbGRzQW5kU3RhdGUgJiZcbiAgICAgICAgICAgICAgICBBcnJheS5pc0FycmF5KGdldChfZm9ybVN0YXRlLnRvdWNoZWRGaWVsZHMsIG5hbWUpKSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IHRvdWNoZWRGaWVsZHMgPSBtZXRob2QoZ2V0KF9mb3JtU3RhdGUudG91Y2hlZEZpZWxkcywgbmFtZSksIGFyZ3MuYXJnQSwgYXJncy5hcmdCKTtcbiAgICAgICAgICAgICAgICBzaG91bGRTZXRWYWx1ZXMgJiYgc2V0KF9mb3JtU3RhdGUudG91Y2hlZEZpZWxkcywgbmFtZSwgdG91Y2hlZEZpZWxkcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoX3Byb3h5Rm9ybVN0YXRlLmRpcnR5RmllbGRzIHx8IF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZS5kaXJ0eUZpZWxkcykge1xuICAgICAgICAgICAgICAgIF9mb3JtU3RhdGUuZGlydHlGaWVsZHMgPSBnZXREaXJ0eUZpZWxkcyhfZGVmYXVsdFZhbHVlcywgX2Zvcm1WYWx1ZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgaXNEaXJ0eTogX2dldERpcnR5KG5hbWUsIHZhbHVlcyksXG4gICAgICAgICAgICAgICAgZGlydHlGaWVsZHM6IF9mb3JtU3RhdGUuZGlydHlGaWVsZHMsXG4gICAgICAgICAgICAgICAgZXJyb3JzOiBfZm9ybVN0YXRlLmVycm9ycyxcbiAgICAgICAgICAgICAgICBpc1ZhbGlkOiBfZm9ybVN0YXRlLmlzVmFsaWQsXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHNldChfZm9ybVZhbHVlcywgbmFtZSwgdmFsdWVzKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3QgdXBkYXRlRXJyb3JzID0gKG5hbWUsIGVycm9yKSA9PiB7XG4gICAgICAgIHNldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSwgZXJyb3IpO1xuICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICBlcnJvcnM6IF9mb3JtU3RhdGUuZXJyb3JzLFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIGNvbnN0IF9zZXRFcnJvcnMgPSAoZXJyb3JzKSA9PiB7XG4gICAgICAgIF9mb3JtU3RhdGUuZXJyb3JzID0gZXJyb3JzO1xuICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICBlcnJvcnM6IF9mb3JtU3RhdGUuZXJyb3JzLFxuICAgICAgICAgICAgaXNWYWxpZDogZmFsc2UsXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgY29uc3QgdXBkYXRlVmFsaWRBbmRWYWx1ZSA9IChuYW1lLCBzaG91bGRTa2lwU2V0VmFsdWVBcywgdmFsdWUsIHJlZikgPT4ge1xuICAgICAgICBjb25zdCBmaWVsZCA9IGdldChfZmllbGRzLCBuYW1lKTtcbiAgICAgICAgaWYgKGZpZWxkKSB7XG4gICAgICAgICAgICBjb25zdCBkZWZhdWx0VmFsdWUgPSBnZXQoX2Zvcm1WYWx1ZXMsIG5hbWUsIGlzVW5kZWZpbmVkKHZhbHVlKSA/IGdldChfZGVmYXVsdFZhbHVlcywgbmFtZSkgOiB2YWx1ZSk7XG4gICAgICAgICAgICBpc1VuZGVmaW5lZChkZWZhdWx0VmFsdWUpIHx8XG4gICAgICAgICAgICAgICAgKHJlZiAmJiByZWYuZGVmYXVsdENoZWNrZWQpIHx8XG4gICAgICAgICAgICAgICAgc2hvdWxkU2tpcFNldFZhbHVlQXNcbiAgICAgICAgICAgICAgICA/IHNldChfZm9ybVZhbHVlcywgbmFtZSwgc2hvdWxkU2tpcFNldFZhbHVlQXMgPyBkZWZhdWx0VmFsdWUgOiBnZXRGaWVsZFZhbHVlKGZpZWxkLl9mKSlcbiAgICAgICAgICAgICAgICA6IHNldEZpZWxkVmFsdWUobmFtZSwgZGVmYXVsdFZhbHVlKTtcbiAgICAgICAgICAgIF9zdGF0ZS5tb3VudCAmJiAhX3N0YXRlLmFjdGlvbiAmJiBfc2V0VmFsaWQoKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3QgdXBkYXRlVG91Y2hBbmREaXJ0eSA9IChuYW1lLCBmaWVsZFZhbHVlLCBpc0JsdXJFdmVudCwgc2hvdWxkRGlydHksIHNob3VsZFJlbmRlcikgPT4ge1xuICAgICAgICBsZXQgc2hvdWxkVXBkYXRlRmllbGQgPSBmYWxzZTtcbiAgICAgICAgbGV0IGlzUHJldmlvdXNEaXJ0eSA9IGZhbHNlO1xuICAgICAgICBjb25zdCBvdXRwdXQgPSB7XG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICB9O1xuICAgICAgICBpZiAoIV9vcHRpb25zLmRpc2FibGVkKSB7XG4gICAgICAgICAgICBpZiAoIWlzQmx1ckV2ZW50IHx8IHNob3VsZERpcnR5KSB7XG4gICAgICAgICAgICAgICAgaWYgKF9wcm94eUZvcm1TdGF0ZS5pc0RpcnR5IHx8IF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZS5pc0RpcnR5KSB7XG4gICAgICAgICAgICAgICAgICAgIGlzUHJldmlvdXNEaXJ0eSA9IF9mb3JtU3RhdGUuaXNEaXJ0eTtcbiAgICAgICAgICAgICAgICAgICAgX2Zvcm1TdGF0ZS5pc0RpcnR5ID0gb3V0cHV0LmlzRGlydHkgPSBfZ2V0RGlydHkoKTtcbiAgICAgICAgICAgICAgICAgICAgc2hvdWxkVXBkYXRlRmllbGQgPSBpc1ByZXZpb3VzRGlydHkgIT09IG91dHB1dC5pc0RpcnR5O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBjb25zdCBpc0N1cnJlbnRGaWVsZFByaXN0aW5lID0gZGVlcEVxdWFsKGdldChfZGVmYXVsdFZhbHVlcywgbmFtZSksIGZpZWxkVmFsdWUpO1xuICAgICAgICAgICAgICAgIGlzUHJldmlvdXNEaXJ0eSA9ICEhZ2V0KF9mb3JtU3RhdGUuZGlydHlGaWVsZHMsIG5hbWUpO1xuICAgICAgICAgICAgICAgIGlzQ3VycmVudEZpZWxkUHJpc3RpbmVcbiAgICAgICAgICAgICAgICAgICAgPyB1bnNldChfZm9ybVN0YXRlLmRpcnR5RmllbGRzLCBuYW1lKVxuICAgICAgICAgICAgICAgICAgICA6IHNldChfZm9ybVN0YXRlLmRpcnR5RmllbGRzLCBuYW1lLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBvdXRwdXQuZGlydHlGaWVsZHMgPSBfZm9ybVN0YXRlLmRpcnR5RmllbGRzO1xuICAgICAgICAgICAgICAgIHNob3VsZFVwZGF0ZUZpZWxkID1cbiAgICAgICAgICAgICAgICAgICAgc2hvdWxkVXBkYXRlRmllbGQgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICgoX3Byb3h5Rm9ybVN0YXRlLmRpcnR5RmllbGRzIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlLmRpcnR5RmllbGRzKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzUHJldmlvdXNEaXJ0eSAhPT0gIWlzQ3VycmVudEZpZWxkUHJpc3RpbmUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKGlzQmx1ckV2ZW50KSB7XG4gICAgICAgICAgICAgICAgY29uc3QgaXNQcmV2aW91c0ZpZWxkVG91Y2hlZCA9IGdldChfZm9ybVN0YXRlLnRvdWNoZWRGaWVsZHMsIG5hbWUpO1xuICAgICAgICAgICAgICAgIGlmICghaXNQcmV2aW91c0ZpZWxkVG91Y2hlZCkge1xuICAgICAgICAgICAgICAgICAgICBzZXQoX2Zvcm1TdGF0ZS50b3VjaGVkRmllbGRzLCBuYW1lLCBpc0JsdXJFdmVudCk7XG4gICAgICAgICAgICAgICAgICAgIG91dHB1dC50b3VjaGVkRmllbGRzID0gX2Zvcm1TdGF0ZS50b3VjaGVkRmllbGRzO1xuICAgICAgICAgICAgICAgICAgICBzaG91bGRVcGRhdGVGaWVsZCA9XG4gICAgICAgICAgICAgICAgICAgICAgICBzaG91bGRVcGRhdGVGaWVsZCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICgoX3Byb3h5Rm9ybVN0YXRlLnRvdWNoZWRGaWVsZHMgfHxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlLnRvdWNoZWRGaWVsZHMpICYmXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlzUHJldmlvdXNGaWVsZFRvdWNoZWQgIT09IGlzQmx1ckV2ZW50KTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBzaG91bGRVcGRhdGVGaWVsZCAmJiBzaG91bGRSZW5kZXIgJiYgX3N1YmplY3RzLnN0YXRlLm5leHQob3V0cHV0KTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc2hvdWxkVXBkYXRlRmllbGQgPyBvdXRwdXQgOiB7fTtcbiAgICB9O1xuICAgIGNvbnN0IHNob3VsZFJlbmRlckJ5RXJyb3IgPSAobmFtZSwgaXNWYWxpZCwgZXJyb3IsIGZpZWxkU3RhdGUpID0+IHtcbiAgICAgICAgY29uc3QgcHJldmlvdXNGaWVsZEVycm9yID0gZ2V0KF9mb3JtU3RhdGUuZXJyb3JzLCBuYW1lKTtcbiAgICAgICAgY29uc3Qgc2hvdWxkVXBkYXRlVmFsaWQgPSAoX3Byb3h5Rm9ybVN0YXRlLmlzVmFsaWQgfHwgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlLmlzVmFsaWQpICYmXG4gICAgICAgICAgICBpc0Jvb2xlYW4oaXNWYWxpZCkgJiZcbiAgICAgICAgICAgIF9mb3JtU3RhdGUuaXNWYWxpZCAhPT0gaXNWYWxpZDtcbiAgICAgICAgaWYgKF9vcHRpb25zLmRlbGF5RXJyb3IgJiYgZXJyb3IpIHtcbiAgICAgICAgICAgIGRlbGF5RXJyb3JDYWxsYmFjayA9IGRlYm91bmNlKCgpID0+IHVwZGF0ZUVycm9ycyhuYW1lLCBlcnJvcikpO1xuICAgICAgICAgICAgZGVsYXlFcnJvckNhbGxiYWNrKF9vcHRpb25zLmRlbGF5RXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY2xlYXJUaW1lb3V0KHRpbWVyKTtcbiAgICAgICAgICAgIGRlbGF5RXJyb3JDYWxsYmFjayA9IG51bGw7XG4gICAgICAgICAgICBlcnJvclxuICAgICAgICAgICAgICAgID8gc2V0KF9mb3JtU3RhdGUuZXJyb3JzLCBuYW1lLCBlcnJvcilcbiAgICAgICAgICAgICAgICA6IHVuc2V0KF9mb3JtU3RhdGUuZXJyb3JzLCBuYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoKGVycm9yID8gIWRlZXBFcXVhbChwcmV2aW91c0ZpZWxkRXJyb3IsIGVycm9yKSA6IHByZXZpb3VzRmllbGRFcnJvcikgfHxcbiAgICAgICAgICAgICFpc0VtcHR5T2JqZWN0KGZpZWxkU3RhdGUpIHx8XG4gICAgICAgICAgICBzaG91bGRVcGRhdGVWYWxpZCkge1xuICAgICAgICAgICAgY29uc3QgdXBkYXRlZEZvcm1TdGF0ZSA9IHtcbiAgICAgICAgICAgICAgICAuLi5maWVsZFN0YXRlLFxuICAgICAgICAgICAgICAgIC4uLihzaG91bGRVcGRhdGVWYWxpZCAmJiBpc0Jvb2xlYW4oaXNWYWxpZCkgPyB7IGlzVmFsaWQgfSA6IHt9KSxcbiAgICAgICAgICAgICAgICBlcnJvcnM6IF9mb3JtU3RhdGUuZXJyb3JzLFxuICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgX2Zvcm1TdGF0ZSA9IHtcbiAgICAgICAgICAgICAgICAuLi5fZm9ybVN0YXRlLFxuICAgICAgICAgICAgICAgIC4uLnVwZGF0ZWRGb3JtU3RhdGUsXG4gICAgICAgICAgICB9O1xuICAgICAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQodXBkYXRlZEZvcm1TdGF0ZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IF9ydW5TY2hlbWEgPSBhc3luYyAobmFtZSkgPT4ge1xuICAgICAgICBfdXBkYXRlSXNWYWxpZGF0aW5nKG5hbWUsIHRydWUpO1xuICAgICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBfb3B0aW9ucy5yZXNvbHZlcihfZm9ybVZhbHVlcywgX29wdGlvbnMuY29udGV4dCwgZ2V0UmVzb2x2ZXJPcHRpb25zKG5hbWUgfHwgX25hbWVzLm1vdW50LCBfZmllbGRzLCBfb3B0aW9ucy5jcml0ZXJpYU1vZGUsIF9vcHRpb25zLnNob3VsZFVzZU5hdGl2ZVZhbGlkYXRpb24pKTtcbiAgICAgICAgX3VwZGF0ZUlzVmFsaWRhdGluZyhuYW1lKTtcbiAgICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9O1xuICAgIGNvbnN0IGV4ZWN1dGVTY2hlbWFBbmRVcGRhdGVTdGF0ZSA9IGFzeW5jIChuYW1lcykgPT4ge1xuICAgICAgICBjb25zdCB7IGVycm9ycyB9ID0gYXdhaXQgX3J1blNjaGVtYShuYW1lcyk7XG4gICAgICAgIGlmIChuYW1lcykge1xuICAgICAgICAgICAgZm9yIChjb25zdCBuYW1lIG9mIG5hbWVzKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBnZXQoZXJyb3JzLCBuYW1lKTtcbiAgICAgICAgICAgICAgICBlcnJvclxuICAgICAgICAgICAgICAgICAgICA/IHNldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSwgZXJyb3IpXG4gICAgICAgICAgICAgICAgICAgIDogdW5zZXQoX2Zvcm1TdGF0ZS5lcnJvcnMsIG5hbWUpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgX2Zvcm1TdGF0ZS5lcnJvcnMgPSBlcnJvcnM7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIGVycm9ycztcbiAgICB9O1xuICAgIGNvbnN0IGV4ZWN1dGVCdWlsdEluVmFsaWRhdGlvbiA9IGFzeW5jIChmaWVsZHMsIHNob3VsZE9ubHlDaGVja1ZhbGlkLCBjb250ZXh0ID0ge1xuICAgICAgICB2YWxpZDogdHJ1ZSxcbiAgICB9KSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBpbiBmaWVsZHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gZmllbGRzW25hbWVdO1xuICAgICAgICAgICAgaWYgKGZpZWxkKSB7XG4gICAgICAgICAgICAgICAgY29uc3QgeyBfZiwgLi4uZmllbGRWYWx1ZSB9ID0gZmllbGQ7XG4gICAgICAgICAgICAgICAgaWYgKF9mKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGlzRmllbGRBcnJheVJvb3QgPSBfbmFtZXMuYXJyYXkuaGFzKF9mLm5hbWUpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBpc1Byb21pc2VGdW5jdGlvbiA9IGZpZWxkLl9mICYmIGhhc1Byb21pc2VWYWxpZGF0aW9uKGZpZWxkLl9mKTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGlzUHJvbWlzZUZ1bmN0aW9uICYmIF9wcm94eUZvcm1TdGF0ZS52YWxpZGF0aW5nRmllbGRzKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfdXBkYXRlSXNWYWxpZGF0aW5nKFtfZi5uYW1lXSwgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZmllbGRFcnJvciA9IGF3YWl0IHZhbGlkYXRlRmllbGQoZmllbGQsIF9uYW1lcy5kaXNhYmxlZCwgX2Zvcm1WYWx1ZXMsIHNob3VsZERpc3BsYXlBbGxBc3NvY2lhdGVkRXJyb3JzLCBfb3B0aW9ucy5zaG91bGRVc2VOYXRpdmVWYWxpZGF0aW9uICYmICFzaG91bGRPbmx5Q2hlY2tWYWxpZCwgaXNGaWVsZEFycmF5Um9vdCk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChpc1Byb21pc2VGdW5jdGlvbiAmJiBfcHJveHlGb3JtU3RhdGUudmFsaWRhdGluZ0ZpZWxkcykge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3VwZGF0ZUlzVmFsaWRhdGluZyhbX2YubmFtZV0pO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIGlmIChmaWVsZEVycm9yW19mLm5hbWVdKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250ZXh0LnZhbGlkID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoc2hvdWxkT25seUNoZWNrVmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICAhc2hvdWxkT25seUNoZWNrVmFsaWQgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIChnZXQoZmllbGRFcnJvciwgX2YubmFtZSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IGlzRmllbGRBcnJheVJvb3RcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyB1cGRhdGVGaWVsZEFycmF5Um9vdEVycm9yKF9mb3JtU3RhdGUuZXJyb3JzLCBmaWVsZEVycm9yLCBfZi5uYW1lKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHNldChfZm9ybVN0YXRlLmVycm9ycywgX2YubmFtZSwgZmllbGRFcnJvcltfZi5uYW1lXSlcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHVuc2V0KF9mb3JtU3RhdGUuZXJyb3JzLCBfZi5uYW1lKSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICFpc0VtcHR5T2JqZWN0KGZpZWxkVmFsdWUpICYmXG4gICAgICAgICAgICAgICAgICAgIChhd2FpdCBleGVjdXRlQnVpbHRJblZhbGlkYXRpb24oZmllbGRWYWx1ZSwgc2hvdWxkT25seUNoZWNrVmFsaWQsIGNvbnRleHQpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gY29udGV4dC52YWxpZDtcbiAgICB9O1xuICAgIGNvbnN0IF9yZW1vdmVVbm1vdW50ZWQgPSAoKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBvZiBfbmFtZXMudW5Nb3VudCkge1xuICAgICAgICAgICAgY29uc3QgZmllbGQgPSBnZXQoX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgICAgICBmaWVsZCAmJlxuICAgICAgICAgICAgICAgIChmaWVsZC5fZi5yZWZzXG4gICAgICAgICAgICAgICAgICAgID8gZmllbGQuX2YucmVmcy5ldmVyeSgocmVmKSA9PiAhbGl2ZShyZWYpKVxuICAgICAgICAgICAgICAgICAgICA6ICFsaXZlKGZpZWxkLl9mLnJlZikpICYmXG4gICAgICAgICAgICAgICAgdW5yZWdpc3RlcihuYW1lKTtcbiAgICAgICAgfVxuICAgICAgICBfbmFtZXMudW5Nb3VudCA9IG5ldyBTZXQoKTtcbiAgICB9O1xuICAgIGNvbnN0IF9nZXREaXJ0eSA9IChuYW1lLCBkYXRhKSA9PiAhX29wdGlvbnMuZGlzYWJsZWQgJiZcbiAgICAgICAgKG5hbWUgJiYgZGF0YSAmJiBzZXQoX2Zvcm1WYWx1ZXMsIG5hbWUsIGRhdGEpLFxuICAgICAgICAgICAgIWRlZXBFcXVhbChnZXRWYWx1ZXMoKSwgX2RlZmF1bHRWYWx1ZXMpKTtcbiAgICBjb25zdCBfZ2V0V2F0Y2ggPSAobmFtZXMsIGRlZmF1bHRWYWx1ZSwgaXNHbG9iYWwpID0+IGdlbmVyYXRlV2F0Y2hPdXRwdXQobmFtZXMsIF9uYW1lcywge1xuICAgICAgICAuLi4oX3N0YXRlLm1vdW50XG4gICAgICAgICAgICA/IF9mb3JtVmFsdWVzXG4gICAgICAgICAgICA6IGlzVW5kZWZpbmVkKGRlZmF1bHRWYWx1ZSlcbiAgICAgICAgICAgICAgICA/IF9kZWZhdWx0VmFsdWVzXG4gICAgICAgICAgICAgICAgOiBpc1N0cmluZyhuYW1lcylcbiAgICAgICAgICAgICAgICAgICAgPyB7IFtuYW1lc106IGRlZmF1bHRWYWx1ZSB9XG4gICAgICAgICAgICAgICAgICAgIDogZGVmYXVsdFZhbHVlKSxcbiAgICB9LCBpc0dsb2JhbCwgZGVmYXVsdFZhbHVlKTtcbiAgICBjb25zdCBfZ2V0RmllbGRBcnJheSA9IChuYW1lKSA9PiBjb21wYWN0KGdldChfc3RhdGUubW91bnQgPyBfZm9ybVZhbHVlcyA6IF9kZWZhdWx0VmFsdWVzLCBuYW1lLCBfb3B0aW9ucy5zaG91bGRVbnJlZ2lzdGVyID8gZ2V0KF9kZWZhdWx0VmFsdWVzLCBuYW1lLCBbXSkgOiBbXSkpO1xuICAgIGNvbnN0IHNldEZpZWxkVmFsdWUgPSAobmFtZSwgdmFsdWUsIG9wdGlvbnMgPSB7fSkgPT4ge1xuICAgICAgICBjb25zdCBmaWVsZCA9IGdldChfZmllbGRzLCBuYW1lKTtcbiAgICAgICAgbGV0IGZpZWxkVmFsdWUgPSB2YWx1ZTtcbiAgICAgICAgaWYgKGZpZWxkKSB7XG4gICAgICAgICAgICBjb25zdCBmaWVsZFJlZmVyZW5jZSA9IGZpZWxkLl9mO1xuICAgICAgICAgICAgaWYgKGZpZWxkUmVmZXJlbmNlKSB7XG4gICAgICAgICAgICAgICAgIWZpZWxkUmVmZXJlbmNlLmRpc2FibGVkICYmXG4gICAgICAgICAgICAgICAgICAgIHNldChfZm9ybVZhbHVlcywgbmFtZSwgZ2V0RmllbGRWYWx1ZUFzKHZhbHVlLCBmaWVsZFJlZmVyZW5jZSkpO1xuICAgICAgICAgICAgICAgIGZpZWxkVmFsdWUgPVxuICAgICAgICAgICAgICAgICAgICBpc0hUTUxFbGVtZW50KGZpZWxkUmVmZXJlbmNlLnJlZikgJiYgaXNOdWxsT3JVbmRlZmluZWQodmFsdWUpXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICcnXG4gICAgICAgICAgICAgICAgICAgICAgICA6IHZhbHVlO1xuICAgICAgICAgICAgICAgIGlmIChpc011bHRpcGxlU2VsZWN0KGZpZWxkUmVmZXJlbmNlLnJlZikpIHtcbiAgICAgICAgICAgICAgICAgICAgWy4uLmZpZWxkUmVmZXJlbmNlLnJlZi5vcHRpb25zXS5mb3JFYWNoKChvcHRpb25SZWYpID0+IChvcHRpb25SZWYuc2VsZWN0ZWQgPSBmaWVsZFZhbHVlLmluY2x1ZGVzKG9wdGlvblJlZi52YWx1ZSkpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSBpZiAoZmllbGRSZWZlcmVuY2UucmVmcykge1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNDaGVja0JveElucHV0KGZpZWxkUmVmZXJlbmNlLnJlZikpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkUmVmZXJlbmNlLnJlZnMuZm9yRWFjaCgoY2hlY2tib3hSZWYpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoIWNoZWNrYm94UmVmLmRlZmF1bHRDaGVja2VkIHx8ICFjaGVja2JveFJlZi5kaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShmaWVsZFZhbHVlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY2hlY2tib3hSZWYuY2hlY2tlZCA9ICEhZmllbGRWYWx1ZS5maW5kKChkYXRhKSA9PiBkYXRhID09PSBjaGVja2JveFJlZi52YWx1ZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjaGVja2JveFJlZi5jaGVja2VkID1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBmaWVsZFZhbHVlID09PSBjaGVja2JveFJlZi52YWx1ZSB8fCAhIWZpZWxkVmFsdWU7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkUmVmZXJlbmNlLnJlZnMuZm9yRWFjaCgocmFkaW9SZWYpID0+IChyYWRpb1JlZi5jaGVja2VkID0gcmFkaW9SZWYudmFsdWUgPT09IGZpZWxkVmFsdWUpKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIGlmIChpc0ZpbGVJbnB1dChmaWVsZFJlZmVyZW5jZS5yZWYpKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpZWxkUmVmZXJlbmNlLnJlZi52YWx1ZSA9ICcnO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZmllbGRSZWZlcmVuY2UucmVmLnZhbHVlID0gZmllbGRWYWx1ZTtcbiAgICAgICAgICAgICAgICAgICAgaWYgKCFmaWVsZFJlZmVyZW5jZS5yZWYudHlwZSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdmFsdWVzOiBjbG9uZU9iamVjdChfZm9ybVZhbHVlcyksXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICAob3B0aW9ucy5zaG91bGREaXJ0eSB8fCBvcHRpb25zLnNob3VsZFRvdWNoKSAmJlxuICAgICAgICAgICAgdXBkYXRlVG91Y2hBbmREaXJ0eShuYW1lLCBmaWVsZFZhbHVlLCBvcHRpb25zLnNob3VsZFRvdWNoLCBvcHRpb25zLnNob3VsZERpcnR5LCB0cnVlKTtcbiAgICAgICAgb3B0aW9ucy5zaG91bGRWYWxpZGF0ZSAmJiB0cmlnZ2VyKG5hbWUpO1xuICAgIH07XG4gICAgY29uc3Qgc2V0VmFsdWVzID0gKG5hbWUsIHZhbHVlLCBvcHRpb25zKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgZmllbGRLZXkgaW4gdmFsdWUpIHtcbiAgICAgICAgICAgIGlmICghdmFsdWUuaGFzT3duUHJvcGVydHkoZmllbGRLZXkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgY29uc3QgZmllbGRWYWx1ZSA9IHZhbHVlW2ZpZWxkS2V5XTtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IG5hbWUgKyAnLicgKyBmaWVsZEtleTtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gZ2V0KF9maWVsZHMsIGZpZWxkTmFtZSk7XG4gICAgICAgICAgICAoX25hbWVzLmFycmF5LmhhcyhuYW1lKSB8fFxuICAgICAgICAgICAgICAgIGlzT2JqZWN0KGZpZWxkVmFsdWUpIHx8XG4gICAgICAgICAgICAgICAgKGZpZWxkICYmICFmaWVsZC5fZikpICYmXG4gICAgICAgICAgICAgICAgIWlzRGF0ZU9iamVjdChmaWVsZFZhbHVlKVxuICAgICAgICAgICAgICAgID8gc2V0VmFsdWVzKGZpZWxkTmFtZSwgZmllbGRWYWx1ZSwgb3B0aW9ucylcbiAgICAgICAgICAgICAgICA6IHNldEZpZWxkVmFsdWUoZmllbGROYW1lLCBmaWVsZFZhbHVlLCBvcHRpb25zKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3Qgc2V0VmFsdWUgPSAobmFtZSwgdmFsdWUsIG9wdGlvbnMgPSB7fSkgPT4ge1xuICAgICAgICBjb25zdCBmaWVsZCA9IGdldChfZmllbGRzLCBuYW1lKTtcbiAgICAgICAgY29uc3QgaXNGaWVsZEFycmF5ID0gX25hbWVzLmFycmF5LmhhcyhuYW1lKTtcbiAgICAgICAgY29uc3QgY2xvbmVWYWx1ZSA9IGNsb25lT2JqZWN0KHZhbHVlKTtcbiAgICAgICAgc2V0KF9mb3JtVmFsdWVzLCBuYW1lLCBjbG9uZVZhbHVlKTtcbiAgICAgICAgaWYgKGlzRmllbGRBcnJheSkge1xuICAgICAgICAgICAgX3N1YmplY3RzLmFycmF5Lm5leHQoe1xuICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgdmFsdWVzOiBjbG9uZU9iamVjdChfZm9ybVZhbHVlcyksXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIGlmICgoX3Byb3h5Rm9ybVN0YXRlLmlzRGlydHkgfHxcbiAgICAgICAgICAgICAgICBfcHJveHlGb3JtU3RhdGUuZGlydHlGaWVsZHMgfHxcbiAgICAgICAgICAgICAgICBfcHJveHlTdWJzY3JpYmVGb3JtU3RhdGUuaXNEaXJ0eSB8fFxuICAgICAgICAgICAgICAgIF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZS5kaXJ0eUZpZWxkcykgJiZcbiAgICAgICAgICAgICAgICBvcHRpb25zLnNob3VsZERpcnR5KSB7XG4gICAgICAgICAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgICAgICAgICBkaXJ0eUZpZWxkczogZ2V0RGlydHlGaWVsZHMoX2RlZmF1bHRWYWx1ZXMsIF9mb3JtVmFsdWVzKSxcbiAgICAgICAgICAgICAgICAgICAgaXNEaXJ0eTogX2dldERpcnR5KG5hbWUsIGNsb25lVmFsdWUpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgZmllbGQgJiYgIWZpZWxkLl9mICYmICFpc051bGxPclVuZGVmaW5lZChjbG9uZVZhbHVlKVxuICAgICAgICAgICAgICAgID8gc2V0VmFsdWVzKG5hbWUsIGNsb25lVmFsdWUsIG9wdGlvbnMpXG4gICAgICAgICAgICAgICAgOiBzZXRGaWVsZFZhbHVlKG5hbWUsIGNsb25lVmFsdWUsIG9wdGlvbnMpO1xuICAgICAgICB9XG4gICAgICAgIGlzV2F0Y2hlZChuYW1lLCBfbmFtZXMpICYmIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHsgLi4uX2Zvcm1TdGF0ZSwgbmFtZSB9KTtcbiAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgbmFtZTogX3N0YXRlLm1vdW50ID8gbmFtZSA6IHVuZGVmaW5lZCxcbiAgICAgICAgICAgIHZhbHVlczogY2xvbmVPYmplY3QoX2Zvcm1WYWx1ZXMpLFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIGNvbnN0IG9uQ2hhbmdlID0gYXN5bmMgKGV2ZW50KSA9PiB7XG4gICAgICAgIF9zdGF0ZS5tb3VudCA9IHRydWU7XG4gICAgICAgIGNvbnN0IHRhcmdldCA9IGV2ZW50LnRhcmdldDtcbiAgICAgICAgbGV0IG5hbWUgPSB0YXJnZXQubmFtZTtcbiAgICAgICAgbGV0IGlzRmllbGRWYWx1ZVVwZGF0ZWQgPSB0cnVlO1xuICAgICAgICBjb25zdCBmaWVsZCA9IGdldChfZmllbGRzLCBuYW1lKTtcbiAgICAgICAgY29uc3QgX3VwZGF0ZUlzRmllbGRWYWx1ZVVwZGF0ZWQgPSAoZmllbGRWYWx1ZSkgPT4ge1xuICAgICAgICAgICAgaXNGaWVsZFZhbHVlVXBkYXRlZCA9XG4gICAgICAgICAgICAgICAgTnVtYmVyLmlzTmFOKGZpZWxkVmFsdWUpIHx8XG4gICAgICAgICAgICAgICAgICAgIChpc0RhdGVPYmplY3QoZmllbGRWYWx1ZSkgJiYgaXNOYU4oZmllbGRWYWx1ZS5nZXRUaW1lKCkpKSB8fFxuICAgICAgICAgICAgICAgICAgICBkZWVwRXF1YWwoZmllbGRWYWx1ZSwgZ2V0KF9mb3JtVmFsdWVzLCBuYW1lLCBmaWVsZFZhbHVlKSk7XG4gICAgICAgIH07XG4gICAgICAgIGNvbnN0IHZhbGlkYXRpb25Nb2RlQmVmb3JlU3VibWl0ID0gZ2V0VmFsaWRhdGlvbk1vZGVzKF9vcHRpb25zLm1vZGUpO1xuICAgICAgICBjb25zdCB2YWxpZGF0aW9uTW9kZUFmdGVyU3VibWl0ID0gZ2V0VmFsaWRhdGlvbk1vZGVzKF9vcHRpb25zLnJlVmFsaWRhdGVNb2RlKTtcbiAgICAgICAgaWYgKGZpZWxkKSB7XG4gICAgICAgICAgICBsZXQgZXJyb3I7XG4gICAgICAgICAgICBsZXQgaXNWYWxpZDtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkVmFsdWUgPSB0YXJnZXQudHlwZVxuICAgICAgICAgICAgICAgID8gZ2V0RmllbGRWYWx1ZShmaWVsZC5fZilcbiAgICAgICAgICAgICAgICA6IGdldEV2ZW50VmFsdWUoZXZlbnQpO1xuICAgICAgICAgICAgY29uc3QgaXNCbHVyRXZlbnQgPSBldmVudC50eXBlID09PSBFVkVOVFMuQkxVUiB8fCBldmVudC50eXBlID09PSBFVkVOVFMuRk9DVVNfT1VUO1xuICAgICAgICAgICAgY29uc3Qgc2hvdWxkU2tpcFZhbGlkYXRpb24gPSAoIWhhc1ZhbGlkYXRpb24oZmllbGQuX2YpICYmXG4gICAgICAgICAgICAgICAgIV9vcHRpb25zLnJlc29sdmVyICYmXG4gICAgICAgICAgICAgICAgIWdldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSkgJiZcbiAgICAgICAgICAgICAgICAhZmllbGQuX2YuZGVwcykgfHxcbiAgICAgICAgICAgICAgICBza2lwVmFsaWRhdGlvbihpc0JsdXJFdmVudCwgZ2V0KF9mb3JtU3RhdGUudG91Y2hlZEZpZWxkcywgbmFtZSksIF9mb3JtU3RhdGUuaXNTdWJtaXR0ZWQsIHZhbGlkYXRpb25Nb2RlQWZ0ZXJTdWJtaXQsIHZhbGlkYXRpb25Nb2RlQmVmb3JlU3VibWl0KTtcbiAgICAgICAgICAgIGNvbnN0IHdhdGNoZWQgPSBpc1dhdGNoZWQobmFtZSwgX25hbWVzLCBpc0JsdXJFdmVudCk7XG4gICAgICAgICAgICBzZXQoX2Zvcm1WYWx1ZXMsIG5hbWUsIGZpZWxkVmFsdWUpO1xuICAgICAgICAgICAgaWYgKGlzQmx1ckV2ZW50KSB7XG4gICAgICAgICAgICAgICAgaWYgKCF0YXJnZXQgfHwgIXRhcmdldC5yZWFkT25seSkge1xuICAgICAgICAgICAgICAgICAgICBmaWVsZC5fZi5vbkJsdXIgJiYgZmllbGQuX2Yub25CbHVyKGV2ZW50KTtcbiAgICAgICAgICAgICAgICAgICAgZGVsYXlFcnJvckNhbGxiYWNrICYmIGRlbGF5RXJyb3JDYWxsYmFjaygwKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIGlmIChmaWVsZC5fZi5vbkNoYW5nZSkge1xuICAgICAgICAgICAgICAgIGZpZWxkLl9mLm9uQ2hhbmdlKGV2ZW50KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbnN0IGZpZWxkU3RhdGUgPSB1cGRhdGVUb3VjaEFuZERpcnR5KG5hbWUsIGZpZWxkVmFsdWUsIGlzQmx1ckV2ZW50KTtcbiAgICAgICAgICAgIGNvbnN0IHNob3VsZFJlbmRlciA9ICFpc0VtcHR5T2JqZWN0KGZpZWxkU3RhdGUpIHx8IHdhdGNoZWQ7XG4gICAgICAgICAgICAhaXNCbHVyRXZlbnQgJiZcbiAgICAgICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICAgICAgICAgIG5hbWUsXG4gICAgICAgICAgICAgICAgICAgIHR5cGU6IGV2ZW50LnR5cGUsXG4gICAgICAgICAgICAgICAgICAgIHZhbHVlczogY2xvbmVPYmplY3QoX2Zvcm1WYWx1ZXMpLFxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKHNob3VsZFNraXBWYWxpZGF0aW9uKSB7XG4gICAgICAgICAgICAgICAgaWYgKF9wcm94eUZvcm1TdGF0ZS5pc1ZhbGlkIHx8IF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZS5pc1ZhbGlkKSB7XG4gICAgICAgICAgICAgICAgICAgIGlmIChfb3B0aW9ucy5tb2RlID09PSAnb25CbHVyJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGlzQmx1ckV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgX3NldFZhbGlkKCk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgZWxzZSBpZiAoIWlzQmx1ckV2ZW50KSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBfc2V0VmFsaWQoKTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm4gKHNob3VsZFJlbmRlciAmJlxuICAgICAgICAgICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7IG5hbWUsIC4uLih3YXRjaGVkID8ge30gOiBmaWVsZFN0YXRlKSB9KSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAhaXNCbHVyRXZlbnQgJiYgd2F0Y2hlZCAmJiBfc3ViamVjdHMuc3RhdGUubmV4dCh7IC4uLl9mb3JtU3RhdGUgfSk7XG4gICAgICAgICAgICBpZiAoX29wdGlvbnMucmVzb2x2ZXIpIHtcbiAgICAgICAgICAgICAgICBjb25zdCB7IGVycm9ycyB9ID0gYXdhaXQgX3J1blNjaGVtYShbbmFtZV0pO1xuICAgICAgICAgICAgICAgIF91cGRhdGVJc0ZpZWxkVmFsdWVVcGRhdGVkKGZpZWxkVmFsdWUpO1xuICAgICAgICAgICAgICAgIGlmIChpc0ZpZWxkVmFsdWVVcGRhdGVkKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHByZXZpb3VzRXJyb3JMb29rdXBSZXN1bHQgPSBzY2hlbWFFcnJvckxvb2t1cChfZm9ybVN0YXRlLmVycm9ycywgX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGVycm9yTG9va3VwUmVzdWx0ID0gc2NoZW1hRXJyb3JMb29rdXAoZXJyb3JzLCBfZmllbGRzLCBwcmV2aW91c0Vycm9yTG9va3VwUmVzdWx0Lm5hbWUgfHwgbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIGVycm9yID0gZXJyb3JMb29rdXBSZXN1bHQuZXJyb3I7XG4gICAgICAgICAgICAgICAgICAgIG5hbWUgPSBlcnJvckxvb2t1cFJlc3VsdC5uYW1lO1xuICAgICAgICAgICAgICAgICAgICBpc1ZhbGlkID0gaXNFbXB0eU9iamVjdChlcnJvcnMpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgICAgIF91cGRhdGVJc1ZhbGlkYXRpbmcoW25hbWVdLCB0cnVlKTtcbiAgICAgICAgICAgICAgICBlcnJvciA9IChhd2FpdCB2YWxpZGF0ZUZpZWxkKGZpZWxkLCBfbmFtZXMuZGlzYWJsZWQsIF9mb3JtVmFsdWVzLCBzaG91bGREaXNwbGF5QWxsQXNzb2NpYXRlZEVycm9ycywgX29wdGlvbnMuc2hvdWxkVXNlTmF0aXZlVmFsaWRhdGlvbikpW25hbWVdO1xuICAgICAgICAgICAgICAgIF91cGRhdGVJc1ZhbGlkYXRpbmcoW25hbWVdKTtcbiAgICAgICAgICAgICAgICBfdXBkYXRlSXNGaWVsZFZhbHVlVXBkYXRlZChmaWVsZFZhbHVlKTtcbiAgICAgICAgICAgICAgICBpZiAoaXNGaWVsZFZhbHVlVXBkYXRlZCkge1xuICAgICAgICAgICAgICAgICAgICBpZiAoZXJyb3IpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzVmFsaWQgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBlbHNlIGlmIChfcHJveHlGb3JtU3RhdGUuaXNWYWxpZCB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgX3Byb3h5U3Vic2NyaWJlRm9ybVN0YXRlLmlzVmFsaWQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlzVmFsaWQgPSBhd2FpdCBleGVjdXRlQnVpbHRJblZhbGlkYXRpb24oX2ZpZWxkcywgdHJ1ZSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBpZiAoaXNGaWVsZFZhbHVlVXBkYXRlZCkge1xuICAgICAgICAgICAgICAgIGZpZWxkLl9mLmRlcHMgJiZcbiAgICAgICAgICAgICAgICAgICAgKCFBcnJheS5pc0FycmF5KGZpZWxkLl9mLmRlcHMpIHx8IGZpZWxkLl9mLmRlcHMubGVuZ3RoID4gMCkgJiZcbiAgICAgICAgICAgICAgICAgICAgdHJpZ2dlcihmaWVsZC5fZi5kZXBzKTtcbiAgICAgICAgICAgICAgICBzaG91bGRSZW5kZXJCeUVycm9yKG5hbWUsIGlzVmFsaWQsIGVycm9yLCBmaWVsZFN0YXRlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3QgX2ZvY3VzSW5wdXQgPSAocmVmLCBrZXkpID0+IHtcbiAgICAgICAgaWYgKGdldChfZm9ybVN0YXRlLmVycm9ycywga2V5KSAmJiByZWYuZm9jdXMpIHtcbiAgICAgICAgICAgIHJlZi5mb2N1cygpO1xuICAgICAgICAgICAgcmV0dXJuIDE7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH07XG4gICAgY29uc3QgdHJpZ2dlciA9IGFzeW5jIChuYW1lLCBvcHRpb25zID0ge30pID0+IHtcbiAgICAgICAgbGV0IGlzVmFsaWQ7XG4gICAgICAgIGxldCB2YWxpZGF0aW9uUmVzdWx0O1xuICAgICAgICBjb25zdCBmaWVsZE5hbWVzID0gY29udmVydFRvQXJyYXlQYXlsb2FkKG5hbWUpO1xuICAgICAgICBpZiAoX29wdGlvbnMucmVzb2x2ZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IGVycm9ycyA9IGF3YWl0IGV4ZWN1dGVTY2hlbWFBbmRVcGRhdGVTdGF0ZShpc1VuZGVmaW5lZChuYW1lKSA/IG5hbWUgOiBmaWVsZE5hbWVzKTtcbiAgICAgICAgICAgIGlzVmFsaWQgPSBpc0VtcHR5T2JqZWN0KGVycm9ycyk7XG4gICAgICAgICAgICB2YWxpZGF0aW9uUmVzdWx0ID0gbmFtZVxuICAgICAgICAgICAgICAgID8gIWZpZWxkTmFtZXMuc29tZSgobmFtZSkgPT4gZ2V0KGVycm9ycywgbmFtZSkpXG4gICAgICAgICAgICAgICAgOiBpc1ZhbGlkO1xuICAgICAgICB9XG4gICAgICAgIGVsc2UgaWYgKG5hbWUpIHtcbiAgICAgICAgICAgIHZhbGlkYXRpb25SZXN1bHQgPSAoYXdhaXQgUHJvbWlzZS5hbGwoZmllbGROYW1lcy5tYXAoYXN5bmMgKGZpZWxkTmFtZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gZ2V0KF9maWVsZHMsIGZpZWxkTmFtZSk7XG4gICAgICAgICAgICAgICAgcmV0dXJuIGF3YWl0IGV4ZWN1dGVCdWlsdEluVmFsaWRhdGlvbihmaWVsZCAmJiBmaWVsZC5fZiA/IHsgW2ZpZWxkTmFtZV06IGZpZWxkIH0gOiBmaWVsZCk7XG4gICAgICAgICAgICB9KSkpLmV2ZXJ5KEJvb2xlYW4pO1xuICAgICAgICAgICAgISghdmFsaWRhdGlvblJlc3VsdCAmJiAhX2Zvcm1TdGF0ZS5pc1ZhbGlkKSAmJiBfc2V0VmFsaWQoKTtcbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIHZhbGlkYXRpb25SZXN1bHQgPSBpc1ZhbGlkID0gYXdhaXQgZXhlY3V0ZUJ1aWx0SW5WYWxpZGF0aW9uKF9maWVsZHMpO1xuICAgICAgICB9XG4gICAgICAgIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgIC4uLighaXNTdHJpbmcobmFtZSkgfHxcbiAgICAgICAgICAgICAgICAoKF9wcm94eUZvcm1TdGF0ZS5pc1ZhbGlkIHx8IF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZS5pc1ZhbGlkKSAmJlxuICAgICAgICAgICAgICAgICAgICBpc1ZhbGlkICE9PSBfZm9ybVN0YXRlLmlzVmFsaWQpXG4gICAgICAgICAgICAgICAgPyB7fVxuICAgICAgICAgICAgICAgIDogeyBuYW1lIH0pLFxuICAgICAgICAgICAgLi4uKF9vcHRpb25zLnJlc29sdmVyIHx8ICFuYW1lID8geyBpc1ZhbGlkIH0gOiB7fSksXG4gICAgICAgICAgICBlcnJvcnM6IF9mb3JtU3RhdGUuZXJyb3JzLFxuICAgICAgICB9KTtcbiAgICAgICAgb3B0aW9ucy5zaG91bGRGb2N1cyAmJlxuICAgICAgICAgICAgIXZhbGlkYXRpb25SZXN1bHQgJiZcbiAgICAgICAgICAgIGl0ZXJhdGVGaWVsZHNCeUFjdGlvbihfZmllbGRzLCBfZm9jdXNJbnB1dCwgbmFtZSA/IGZpZWxkTmFtZXMgOiBfbmFtZXMubW91bnQpO1xuICAgICAgICByZXR1cm4gdmFsaWRhdGlvblJlc3VsdDtcbiAgICB9O1xuICAgIGNvbnN0IGdldFZhbHVlcyA9IChmaWVsZE5hbWVzLCBjb25maWcpID0+IHtcbiAgICAgICAgbGV0IHZhbHVlcyA9IHtcbiAgICAgICAgICAgIC4uLihfc3RhdGUubW91bnQgPyBfZm9ybVZhbHVlcyA6IF9kZWZhdWx0VmFsdWVzKSxcbiAgICAgICAgfTtcbiAgICAgICAgaWYgKGNvbmZpZykge1xuICAgICAgICAgICAgdmFsdWVzID0gZXh0cmFjdEZvcm1WYWx1ZXMoY29uZmlnLmRpcnR5RmllbGRzID8gX2Zvcm1TdGF0ZS5kaXJ0eUZpZWxkcyA6IF9mb3JtU3RhdGUudG91Y2hlZEZpZWxkcywgdmFsdWVzKTtcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXNVbmRlZmluZWQoZmllbGROYW1lcylcbiAgICAgICAgICAgID8gdmFsdWVzXG4gICAgICAgICAgICA6IGlzU3RyaW5nKGZpZWxkTmFtZXMpXG4gICAgICAgICAgICAgICAgPyBnZXQodmFsdWVzLCBmaWVsZE5hbWVzKVxuICAgICAgICAgICAgICAgIDogZmllbGROYW1lcy5tYXAoKG5hbWUpID0+IGdldCh2YWx1ZXMsIG5hbWUpKTtcbiAgICB9O1xuICAgIGNvbnN0IGdldEZpZWxkU3RhdGUgPSAobmFtZSwgZm9ybVN0YXRlKSA9PiAoe1xuICAgICAgICBpbnZhbGlkOiAhIWdldCgoZm9ybVN0YXRlIHx8IF9mb3JtU3RhdGUpLmVycm9ycywgbmFtZSksXG4gICAgICAgIGlzRGlydHk6ICEhZ2V0KChmb3JtU3RhdGUgfHwgX2Zvcm1TdGF0ZSkuZGlydHlGaWVsZHMsIG5hbWUpLFxuICAgICAgICBlcnJvcjogZ2V0KChmb3JtU3RhdGUgfHwgX2Zvcm1TdGF0ZSkuZXJyb3JzLCBuYW1lKSxcbiAgICAgICAgaXNWYWxpZGF0aW5nOiAhIWdldChfZm9ybVN0YXRlLnZhbGlkYXRpbmdGaWVsZHMsIG5hbWUpLFxuICAgICAgICBpc1RvdWNoZWQ6ICEhZ2V0KChmb3JtU3RhdGUgfHwgX2Zvcm1TdGF0ZSkudG91Y2hlZEZpZWxkcywgbmFtZSksXG4gICAgfSk7XG4gICAgY29uc3QgY2xlYXJFcnJvcnMgPSAobmFtZSkgPT4ge1xuICAgICAgICBuYW1lICYmXG4gICAgICAgICAgICBjb252ZXJ0VG9BcnJheVBheWxvYWQobmFtZSkuZm9yRWFjaCgoaW5wdXROYW1lKSA9PiB1bnNldChfZm9ybVN0YXRlLmVycm9ycywgaW5wdXROYW1lKSk7XG4gICAgICAgIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgIGVycm9yczogbmFtZSA/IF9mb3JtU3RhdGUuZXJyb3JzIDoge30sXG4gICAgICAgIH0pO1xuICAgIH07XG4gICAgY29uc3Qgc2V0RXJyb3IgPSAobmFtZSwgZXJyb3IsIG9wdGlvbnMpID0+IHtcbiAgICAgICAgY29uc3QgcmVmID0gKGdldChfZmllbGRzLCBuYW1lLCB7IF9mOiB7fSB9KS5fZiB8fCB7fSkucmVmO1xuICAgICAgICBjb25zdCBjdXJyZW50RXJyb3IgPSBnZXQoX2Zvcm1TdGF0ZS5lcnJvcnMsIG5hbWUpIHx8IHt9O1xuICAgICAgICAvLyBEb24ndCBvdmVycmlkZSBleGlzdGluZyBlcnJvciBtZXNzYWdlcyBlbHNld2hlcmUgaW4gdGhlIG9iamVjdCB0cmVlLlxuICAgICAgICBjb25zdCB7IHJlZjogY3VycmVudFJlZiwgbWVzc2FnZSwgdHlwZSwgLi4ucmVzdE9mRXJyb3JUcmVlIH0gPSBjdXJyZW50RXJyb3I7XG4gICAgICAgIHNldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSwge1xuICAgICAgICAgICAgLi4ucmVzdE9mRXJyb3JUcmVlLFxuICAgICAgICAgICAgLi4uZXJyb3IsXG4gICAgICAgICAgICByZWYsXG4gICAgICAgIH0pO1xuICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgZXJyb3JzOiBfZm9ybVN0YXRlLmVycm9ycyxcbiAgICAgICAgICAgIGlzVmFsaWQ6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICAgICAgb3B0aW9ucyAmJiBvcHRpb25zLnNob3VsZEZvY3VzICYmIHJlZiAmJiByZWYuZm9jdXMgJiYgcmVmLmZvY3VzKCk7XG4gICAgfTtcbiAgICBjb25zdCB3YXRjaCA9IChuYW1lLCBkZWZhdWx0VmFsdWUpID0+IGlzRnVuY3Rpb24obmFtZSlcbiAgICAgICAgPyBfc3ViamVjdHMuc3RhdGUuc3Vic2NyaWJlKHtcbiAgICAgICAgICAgIG5leHQ6IChwYXlsb2FkKSA9PiAndmFsdWVzJyBpbiBwYXlsb2FkICYmXG4gICAgICAgICAgICAgICAgbmFtZShfZ2V0V2F0Y2godW5kZWZpbmVkLCBkZWZhdWx0VmFsdWUpLCBwYXlsb2FkKSxcbiAgICAgICAgfSlcbiAgICAgICAgOiBfZ2V0V2F0Y2gobmFtZSwgZGVmYXVsdFZhbHVlLCB0cnVlKTtcbiAgICBjb25zdCBfc3Vic2NyaWJlID0gKHByb3BzKSA9PiBfc3ViamVjdHMuc3RhdGUuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKGZvcm1TdGF0ZSkgPT4ge1xuICAgICAgICAgICAgaWYgKHNob3VsZFN1YnNjcmliZUJ5TmFtZShwcm9wcy5uYW1lLCBmb3JtU3RhdGUubmFtZSwgcHJvcHMuZXhhY3QpICYmXG4gICAgICAgICAgICAgICAgc2hvdWxkUmVuZGVyRm9ybVN0YXRlKGZvcm1TdGF0ZSwgcHJvcHMuZm9ybVN0YXRlIHx8IF9wcm94eUZvcm1TdGF0ZSwgX3NldEZvcm1TdGF0ZSwgcHJvcHMucmVSZW5kZXJSb290KSkge1xuICAgICAgICAgICAgICAgIHByb3BzLmNhbGxiYWNrKHtcbiAgICAgICAgICAgICAgICAgICAgdmFsdWVzOiB7IC4uLl9mb3JtVmFsdWVzIH0sXG4gICAgICAgICAgICAgICAgICAgIC4uLl9mb3JtU3RhdGUsXG4gICAgICAgICAgICAgICAgICAgIC4uLmZvcm1TdGF0ZSxcbiAgICAgICAgICAgICAgICAgICAgZGVmYXVsdFZhbHVlczogX2RlZmF1bHRWYWx1ZXMsXG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0sXG4gICAgfSkudW5zdWJzY3JpYmU7XG4gICAgY29uc3Qgc3Vic2NyaWJlID0gKHByb3BzKSA9PiB7XG4gICAgICAgIF9zdGF0ZS5tb3VudCA9IHRydWU7XG4gICAgICAgIF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZSA9IHtcbiAgICAgICAgICAgIC4uLl9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZSxcbiAgICAgICAgICAgIC4uLnByb3BzLmZvcm1TdGF0ZSxcbiAgICAgICAgfTtcbiAgICAgICAgcmV0dXJuIF9zdWJzY3JpYmUoe1xuICAgICAgICAgICAgLi4ucHJvcHMsXG4gICAgICAgICAgICBmb3JtU3RhdGU6IF9wcm94eVN1YnNjcmliZUZvcm1TdGF0ZSxcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBjb25zdCB1bnJlZ2lzdGVyID0gKG5hbWUsIG9wdGlvbnMgPSB7fSkgPT4ge1xuICAgICAgICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBvZiBuYW1lID8gY29udmVydFRvQXJyYXlQYXlsb2FkKG5hbWUpIDogX25hbWVzLm1vdW50KSB7XG4gICAgICAgICAgICBfbmFtZXMubW91bnQuZGVsZXRlKGZpZWxkTmFtZSk7XG4gICAgICAgICAgICBfbmFtZXMuYXJyYXkuZGVsZXRlKGZpZWxkTmFtZSk7XG4gICAgICAgICAgICBpZiAoIW9wdGlvbnMua2VlcFZhbHVlKSB7XG4gICAgICAgICAgICAgICAgdW5zZXQoX2ZpZWxkcywgZmllbGROYW1lKTtcbiAgICAgICAgICAgICAgICB1bnNldChfZm9ybVZhbHVlcywgZmllbGROYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgICFvcHRpb25zLmtlZXBFcnJvciAmJiB1bnNldChfZm9ybVN0YXRlLmVycm9ycywgZmllbGROYW1lKTtcbiAgICAgICAgICAgICFvcHRpb25zLmtlZXBEaXJ0eSAmJiB1bnNldChfZm9ybVN0YXRlLmRpcnR5RmllbGRzLCBmaWVsZE5hbWUpO1xuICAgICAgICAgICAgIW9wdGlvbnMua2VlcFRvdWNoZWQgJiYgdW5zZXQoX2Zvcm1TdGF0ZS50b3VjaGVkRmllbGRzLCBmaWVsZE5hbWUpO1xuICAgICAgICAgICAgIW9wdGlvbnMua2VlcElzVmFsaWRhdGluZyAmJlxuICAgICAgICAgICAgICAgIHVuc2V0KF9mb3JtU3RhdGUudmFsaWRhdGluZ0ZpZWxkcywgZmllbGROYW1lKTtcbiAgICAgICAgICAgICFfb3B0aW9ucy5zaG91bGRVbnJlZ2lzdGVyICYmXG4gICAgICAgICAgICAgICAgIW9wdGlvbnMua2VlcERlZmF1bHRWYWx1ZSAmJlxuICAgICAgICAgICAgICAgIHVuc2V0KF9kZWZhdWx0VmFsdWVzLCBmaWVsZE5hbWUpO1xuICAgICAgICB9XG4gICAgICAgIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgIHZhbHVlczogY2xvbmVPYmplY3QoX2Zvcm1WYWx1ZXMpLFxuICAgICAgICB9KTtcbiAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgLi4uX2Zvcm1TdGF0ZSxcbiAgICAgICAgICAgIC4uLighb3B0aW9ucy5rZWVwRGlydHkgPyB7fSA6IHsgaXNEaXJ0eTogX2dldERpcnR5KCkgfSksXG4gICAgICAgIH0pO1xuICAgICAgICAhb3B0aW9ucy5rZWVwSXNWYWxpZCAmJiBfc2V0VmFsaWQoKTtcbiAgICB9O1xuICAgIGNvbnN0IF9zZXREaXNhYmxlZEZpZWxkID0gKHsgZGlzYWJsZWQsIG5hbWUsIH0pID0+IHtcbiAgICAgICAgaWYgKChpc0Jvb2xlYW4oZGlzYWJsZWQpICYmIF9zdGF0ZS5tb3VudCkgfHxcbiAgICAgICAgICAgICEhZGlzYWJsZWQgfHxcbiAgICAgICAgICAgIF9uYW1lcy5kaXNhYmxlZC5oYXMobmFtZSkpIHtcbiAgICAgICAgICAgIGRpc2FibGVkID8gX25hbWVzLmRpc2FibGVkLmFkZChuYW1lKSA6IF9uYW1lcy5kaXNhYmxlZC5kZWxldGUobmFtZSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IHJlZ2lzdGVyID0gKG5hbWUsIG9wdGlvbnMgPSB7fSkgPT4ge1xuICAgICAgICBsZXQgZmllbGQgPSBnZXQoX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgIGNvbnN0IGRpc2FibGVkSXNEZWZpbmVkID0gaXNCb29sZWFuKG9wdGlvbnMuZGlzYWJsZWQpIHx8IGlzQm9vbGVhbihfb3B0aW9ucy5kaXNhYmxlZCk7XG4gICAgICAgIHNldChfZmllbGRzLCBuYW1lLCB7XG4gICAgICAgICAgICAuLi4oZmllbGQgfHwge30pLFxuICAgICAgICAgICAgX2Y6IHtcbiAgICAgICAgICAgICAgICAuLi4oZmllbGQgJiYgZmllbGQuX2YgPyBmaWVsZC5fZiA6IHsgcmVmOiB7IG5hbWUgfSB9KSxcbiAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgICAgIG1vdW50OiB0cnVlLFxuICAgICAgICAgICAgICAgIC4uLm9wdGlvbnMsXG4gICAgICAgICAgICB9LFxuICAgICAgICB9KTtcbiAgICAgICAgX25hbWVzLm1vdW50LmFkZChuYW1lKTtcbiAgICAgICAgaWYgKGZpZWxkKSB7XG4gICAgICAgICAgICBfc2V0RGlzYWJsZWRGaWVsZCh7XG4gICAgICAgICAgICAgICAgZGlzYWJsZWQ6IGlzQm9vbGVhbihvcHRpb25zLmRpc2FibGVkKVxuICAgICAgICAgICAgICAgICAgICA/IG9wdGlvbnMuZGlzYWJsZWRcbiAgICAgICAgICAgICAgICAgICAgOiBfb3B0aW9ucy5kaXNhYmxlZCxcbiAgICAgICAgICAgICAgICBuYW1lLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cbiAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICB1cGRhdGVWYWxpZEFuZFZhbHVlKG5hbWUsIHRydWUsIG9wdGlvbnMudmFsdWUpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAuLi4oZGlzYWJsZWRJc0RlZmluZWRcbiAgICAgICAgICAgICAgICA/IHsgZGlzYWJsZWQ6IG9wdGlvbnMuZGlzYWJsZWQgfHwgX29wdGlvbnMuZGlzYWJsZWQgfVxuICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgLi4uKF9vcHRpb25zLnByb2dyZXNzaXZlXG4gICAgICAgICAgICAgICAgPyB7XG4gICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkOiAhIW9wdGlvbnMucmVxdWlyZWQsXG4gICAgICAgICAgICAgICAgICAgIG1pbjogZ2V0UnVsZVZhbHVlKG9wdGlvbnMubWluKSxcbiAgICAgICAgICAgICAgICAgICAgbWF4OiBnZXRSdWxlVmFsdWUob3B0aW9ucy5tYXgpLFxuICAgICAgICAgICAgICAgICAgICBtaW5MZW5ndGg6IGdldFJ1bGVWYWx1ZShvcHRpb25zLm1pbkxlbmd0aCksXG4gICAgICAgICAgICAgICAgICAgIG1heExlbmd0aDogZ2V0UnVsZVZhbHVlKG9wdGlvbnMubWF4TGVuZ3RoKSxcbiAgICAgICAgICAgICAgICAgICAgcGF0dGVybjogZ2V0UnVsZVZhbHVlKG9wdGlvbnMucGF0dGVybiksXG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIDoge30pLFxuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIG9uQ2hhbmdlLFxuICAgICAgICAgICAgb25CbHVyOiBvbkNoYW5nZSxcbiAgICAgICAgICAgIHJlZjogKHJlZikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChyZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVnaXN0ZXIobmFtZSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgICAgICAgIGZpZWxkID0gZ2V0KF9maWVsZHMsIG5hbWUpO1xuICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWVsZFJlZiA9IGlzVW5kZWZpbmVkKHJlZi52YWx1ZSlcbiAgICAgICAgICAgICAgICAgICAgICAgID8gcmVmLnF1ZXJ5U2VsZWN0b3JBbGxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA/IHJlZi5xdWVyeVNlbGVjdG9yQWxsKCdpbnB1dCxzZWxlY3QsdGV4dGFyZWEnKVswXSB8fCByZWZcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA6IHJlZlxuICAgICAgICAgICAgICAgICAgICAgICAgOiByZWY7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJhZGlvT3JDaGVja2JveCA9IGlzUmFkaW9PckNoZWNrYm94KGZpZWxkUmVmKTtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVmcyA9IGZpZWxkLl9mLnJlZnMgfHwgW107XG4gICAgICAgICAgICAgICAgICAgIGlmIChyYWRpb09yQ2hlY2tib3hcbiAgICAgICAgICAgICAgICAgICAgICAgID8gcmVmcy5maW5kKChvcHRpb24pID0+IG9wdGlvbiA9PT0gZmllbGRSZWYpXG4gICAgICAgICAgICAgICAgICAgICAgICA6IGZpZWxkUmVmID09PSBmaWVsZC5fZi5yZWYpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBzZXQoX2ZpZWxkcywgbmFtZSwge1xuICAgICAgICAgICAgICAgICAgICAgICAgX2Y6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi5maWVsZC5fZixcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAuLi4ocmFkaW9PckNoZWNrYm94XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgID8ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcmVmczogW1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLnJlZnMuZmlsdGVyKGxpdmUpLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkUmVmLFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4uLihBcnJheS5pc0FycmF5KGdldChfZGVmYXVsdFZhbHVlcywgbmFtZSkpID8gW3t9XSA6IFtdKSxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByZWY6IHsgdHlwZTogZmllbGRSZWYudHlwZSwgbmFtZSB9LFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogeyByZWY6IGZpZWxkUmVmIH0pLFxuICAgICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIHVwZGF0ZVZhbGlkQW5kVmFsdWUobmFtZSwgZmFsc2UsIHVuZGVmaW5lZCwgZmllbGRSZWYpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgZmllbGQgPSBnZXQoX2ZpZWxkcywgbmFtZSwge30pO1xuICAgICAgICAgICAgICAgICAgICBpZiAoZmllbGQuX2YpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGZpZWxkLl9mLm1vdW50ID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgKF9vcHRpb25zLnNob3VsZFVucmVnaXN0ZXIgfHwgb3B0aW9ucy5zaG91bGRVbnJlZ2lzdGVyKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgIShpc05hbWVJbkZpZWxkQXJyYXkoX25hbWVzLmFycmF5LCBuYW1lKSAmJiBfc3RhdGUuYWN0aW9uKSAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgX25hbWVzLnVuTW91bnQuYWRkKG5hbWUpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBjb25zdCBfZm9jdXNFcnJvciA9ICgpID0+IF9vcHRpb25zLnNob3VsZEZvY3VzRXJyb3IgJiZcbiAgICAgICAgaXRlcmF0ZUZpZWxkc0J5QWN0aW9uKF9maWVsZHMsIF9mb2N1c0lucHV0LCBfbmFtZXMubW91bnQpO1xuICAgIGNvbnN0IF9kaXNhYmxlRm9ybSA9IChkaXNhYmxlZCkgPT4ge1xuICAgICAgICBpZiAoaXNCb29sZWFuKGRpc2FibGVkKSkge1xuICAgICAgICAgICAgX3N1YmplY3RzLnN0YXRlLm5leHQoeyBkaXNhYmxlZCB9KTtcbiAgICAgICAgICAgIGl0ZXJhdGVGaWVsZHNCeUFjdGlvbihfZmllbGRzLCAocmVmLCBuYW1lKSA9PiB7XG4gICAgICAgICAgICAgICAgY29uc3QgY3VycmVudEZpZWxkID0gZ2V0KF9maWVsZHMsIG5hbWUpO1xuICAgICAgICAgICAgICAgIGlmIChjdXJyZW50RmllbGQpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVmLmRpc2FibGVkID0gY3VycmVudEZpZWxkLl9mLmRpc2FibGVkIHx8IGRpc2FibGVkO1xuICAgICAgICAgICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShjdXJyZW50RmllbGQuX2YucmVmcykpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIGN1cnJlbnRGaWVsZC5fZi5yZWZzLmZvckVhY2goKGlucHV0UmVmKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgaW5wdXRSZWYuZGlzYWJsZWQgPSBjdXJyZW50RmllbGQuX2YuZGlzYWJsZWQgfHwgZGlzYWJsZWQ7XG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0sIDAsIGZhbHNlKTtcbiAgICAgICAgfVxuICAgIH07XG4gICAgY29uc3QgaGFuZGxlU3VibWl0ID0gKG9uVmFsaWQsIG9uSW52YWxpZCkgPT4gYXN5bmMgKGUpID0+IHtcbiAgICAgICAgbGV0IG9uVmFsaWRFcnJvciA9IHVuZGVmaW5lZDtcbiAgICAgICAgaWYgKGUpIHtcbiAgICAgICAgICAgIGUucHJldmVudERlZmF1bHQgJiYgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgZS5wZXJzaXN0ICYmXG4gICAgICAgICAgICAgICAgZS5wZXJzaXN0KCk7XG4gICAgICAgIH1cbiAgICAgICAgbGV0IGZpZWxkVmFsdWVzID0gY2xvbmVPYmplY3QoX2Zvcm1WYWx1ZXMpO1xuICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICBpc1N1Ym1pdHRpbmc6IHRydWUsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAoX29wdGlvbnMucmVzb2x2ZXIpIHtcbiAgICAgICAgICAgIGNvbnN0IHsgZXJyb3JzLCB2YWx1ZXMgfSA9IGF3YWl0IF9ydW5TY2hlbWEoKTtcbiAgICAgICAgICAgIF9mb3JtU3RhdGUuZXJyb3JzID0gZXJyb3JzO1xuICAgICAgICAgICAgZmllbGRWYWx1ZXMgPSBjbG9uZU9iamVjdCh2YWx1ZXMpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgYXdhaXQgZXhlY3V0ZUJ1aWx0SW5WYWxpZGF0aW9uKF9maWVsZHMpO1xuICAgICAgICB9XG4gICAgICAgIGlmIChfbmFtZXMuZGlzYWJsZWQuc2l6ZSkge1xuICAgICAgICAgICAgZm9yIChjb25zdCBuYW1lIG9mIF9uYW1lcy5kaXNhYmxlZCkge1xuICAgICAgICAgICAgICAgIHVuc2V0KGZpZWxkVmFsdWVzLCBuYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICB1bnNldChfZm9ybVN0YXRlLmVycm9ycywgJ3Jvb3QnKTtcbiAgICAgICAgaWYgKGlzRW1wdHlPYmplY3QoX2Zvcm1TdGF0ZS5lcnJvcnMpKSB7XG4gICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICAgICAgZXJyb3JzOiB7fSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICBhd2FpdCBvblZhbGlkKGZpZWxkVmFsdWVzLCBlKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgICAgIG9uVmFsaWRFcnJvciA9IGVycm9yO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgaWYgKG9uSW52YWxpZCkge1xuICAgICAgICAgICAgICAgIGF3YWl0IG9uSW52YWxpZCh7IC4uLl9mb3JtU3RhdGUuZXJyb3JzIH0sIGUpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX2ZvY3VzRXJyb3IoKTtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoX2ZvY3VzRXJyb3IpO1xuICAgICAgICB9XG4gICAgICAgIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgIGlzU3VibWl0dGVkOiB0cnVlLFxuICAgICAgICAgICAgaXNTdWJtaXR0aW5nOiBmYWxzZSxcbiAgICAgICAgICAgIGlzU3VibWl0U3VjY2Vzc2Z1bDogaXNFbXB0eU9iamVjdChfZm9ybVN0YXRlLmVycm9ycykgJiYgIW9uVmFsaWRFcnJvcixcbiAgICAgICAgICAgIHN1Ym1pdENvdW50OiBfZm9ybVN0YXRlLnN1Ym1pdENvdW50ICsgMSxcbiAgICAgICAgICAgIGVycm9yczogX2Zvcm1TdGF0ZS5lcnJvcnMsXG4gICAgICAgIH0pO1xuICAgICAgICBpZiAob25WYWxpZEVycm9yKSB7XG4gICAgICAgICAgICB0aHJvdyBvblZhbGlkRXJyb3I7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IHJlc2V0RmllbGQgPSAobmFtZSwgb3B0aW9ucyA9IHt9KSA9PiB7XG4gICAgICAgIGlmIChnZXQoX2ZpZWxkcywgbmFtZSkpIHtcbiAgICAgICAgICAgIGlmIChpc1VuZGVmaW5lZChvcHRpb25zLmRlZmF1bHRWYWx1ZSkpIHtcbiAgICAgICAgICAgICAgICBzZXRWYWx1ZShuYW1lLCBjbG9uZU9iamVjdChnZXQoX2RlZmF1bHRWYWx1ZXMsIG5hbWUpKSk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBzZXRWYWx1ZShuYW1lLCBvcHRpb25zLmRlZmF1bHRWYWx1ZSk7XG4gICAgICAgICAgICAgICAgc2V0KF9kZWZhdWx0VmFsdWVzLCBuYW1lLCBjbG9uZU9iamVjdChvcHRpb25zLmRlZmF1bHRWYWx1ZSkpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgaWYgKCFvcHRpb25zLmtlZXBUb3VjaGVkKSB7XG4gICAgICAgICAgICAgICAgdW5zZXQoX2Zvcm1TdGF0ZS50b3VjaGVkRmllbGRzLCBuYW1lKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghb3B0aW9ucy5rZWVwRGlydHkpIHtcbiAgICAgICAgICAgICAgICB1bnNldChfZm9ybVN0YXRlLmRpcnR5RmllbGRzLCBuYW1lKTtcbiAgICAgICAgICAgICAgICBfZm9ybVN0YXRlLmlzRGlydHkgPSBvcHRpb25zLmRlZmF1bHRWYWx1ZVxuICAgICAgICAgICAgICAgICAgICA/IF9nZXREaXJ0eShuYW1lLCBjbG9uZU9iamVjdChnZXQoX2RlZmF1bHRWYWx1ZXMsIG5hbWUpKSlcbiAgICAgICAgICAgICAgICAgICAgOiBfZ2V0RGlydHkoKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGlmICghb3B0aW9ucy5rZWVwRXJyb3IpIHtcbiAgICAgICAgICAgICAgICB1bnNldChfZm9ybVN0YXRlLmVycm9ycywgbmFtZSk7XG4gICAgICAgICAgICAgICAgX3Byb3h5Rm9ybVN0YXRlLmlzVmFsaWQgJiYgX3NldFZhbGlkKCk7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7IC4uLl9mb3JtU3RhdGUgfSk7XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IF9yZXNldCA9IChmb3JtVmFsdWVzLCBrZWVwU3RhdGVPcHRpb25zID0ge30pID0+IHtcbiAgICAgICAgY29uc3QgdXBkYXRlZFZhbHVlcyA9IGZvcm1WYWx1ZXMgPyBjbG9uZU9iamVjdChmb3JtVmFsdWVzKSA6IF9kZWZhdWx0VmFsdWVzO1xuICAgICAgICBjb25zdCBjbG9uZVVwZGF0ZWRWYWx1ZXMgPSBjbG9uZU9iamVjdCh1cGRhdGVkVmFsdWVzKTtcbiAgICAgICAgY29uc3QgaXNFbXB0eVJlc2V0VmFsdWVzID0gaXNFbXB0eU9iamVjdChmb3JtVmFsdWVzKTtcbiAgICAgICAgY29uc3QgdmFsdWVzID0gaXNFbXB0eVJlc2V0VmFsdWVzID8gX2RlZmF1bHRWYWx1ZXMgOiBjbG9uZVVwZGF0ZWRWYWx1ZXM7XG4gICAgICAgIGlmICgha2VlcFN0YXRlT3B0aW9ucy5rZWVwRGVmYXVsdFZhbHVlcykge1xuICAgICAgICAgICAgX2RlZmF1bHRWYWx1ZXMgPSB1cGRhdGVkVmFsdWVzO1xuICAgICAgICB9XG4gICAgICAgIGlmICgha2VlcFN0YXRlT3B0aW9ucy5rZWVwVmFsdWVzKSB7XG4gICAgICAgICAgICBpZiAoa2VlcFN0YXRlT3B0aW9ucy5rZWVwRGlydHlWYWx1ZXMpIHtcbiAgICAgICAgICAgICAgICBjb25zdCBmaWVsZHNUb0NoZWNrID0gbmV3IFNldChbXG4gICAgICAgICAgICAgICAgICAgIC4uLl9uYW1lcy5tb3VudCxcbiAgICAgICAgICAgICAgICAgICAgLi4uT2JqZWN0LmtleXMoZ2V0RGlydHlGaWVsZHMoX2RlZmF1bHRWYWx1ZXMsIF9mb3JtVmFsdWVzKSksXG4gICAgICAgICAgICAgICAgXSk7XG4gICAgICAgICAgICAgICAgZm9yIChjb25zdCBmaWVsZE5hbWUgb2YgQXJyYXkuZnJvbShmaWVsZHNUb0NoZWNrKSkge1xuICAgICAgICAgICAgICAgICAgICBnZXQoX2Zvcm1TdGF0ZS5kaXJ0eUZpZWxkcywgZmllbGROYW1lKVxuICAgICAgICAgICAgICAgICAgICAgICAgPyBzZXQodmFsdWVzLCBmaWVsZE5hbWUsIGdldChfZm9ybVZhbHVlcywgZmllbGROYW1lKSlcbiAgICAgICAgICAgICAgICAgICAgICAgIDogc2V0VmFsdWUoZmllbGROYW1lLCBnZXQodmFsdWVzLCBmaWVsZE5hbWUpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgICAgICBpZiAoaXNXZWIgJiYgaXNVbmRlZmluZWQoZm9ybVZhbHVlcykpIHtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChjb25zdCBuYW1lIG9mIF9uYW1lcy5tb3VudCkge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgZmllbGQgPSBnZXQoX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBpZiAoZmllbGQgJiYgZmllbGQuX2YpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWVsZFJlZmVyZW5jZSA9IEFycmF5LmlzQXJyYXkoZmllbGQuX2YucmVmcylcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgPyBmaWVsZC5fZi5yZWZzWzBdXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogZmllbGQuX2YucmVmO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGlmIChpc0hUTUxFbGVtZW50KGZpZWxkUmVmZXJlbmNlKSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmb3JtID0gZmllbGRSZWZlcmVuY2UuY2xvc2VzdCgnZm9ybScpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBpZiAoZm9ybSkge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgZm9ybS5yZXNldCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgaWYgKGtlZXBTdGF0ZU9wdGlvbnMua2VlcEZpZWxkc1JlZikge1xuICAgICAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpZWxkTmFtZSBvZiBfbmFtZXMubW91bnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHNldFZhbHVlKGZpZWxkTmFtZSwgZ2V0KHZhbHVlcywgZmllbGROYW1lKSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgIF9maWVsZHMgPSB7fTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBfZm9ybVZhbHVlcyA9IF9vcHRpb25zLnNob3VsZFVucmVnaXN0ZXJcbiAgICAgICAgICAgICAgICA/IGtlZXBTdGF0ZU9wdGlvbnMua2VlcERlZmF1bHRWYWx1ZXNcbiAgICAgICAgICAgICAgICAgICAgPyBjbG9uZU9iamVjdChfZGVmYXVsdFZhbHVlcylcbiAgICAgICAgICAgICAgICAgICAgOiB7fVxuICAgICAgICAgICAgICAgIDogY2xvbmVPYmplY3QodmFsdWVzKTtcbiAgICAgICAgICAgIF9zdWJqZWN0cy5hcnJheS5uZXh0KHtcbiAgICAgICAgICAgICAgICB2YWx1ZXM6IHsgLi4udmFsdWVzIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgICAgICB2YWx1ZXM6IHsgLi4udmFsdWVzIH0sXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICBfbmFtZXMgPSB7XG4gICAgICAgICAgICBtb3VudDoga2VlcFN0YXRlT3B0aW9ucy5rZWVwRGlydHlWYWx1ZXMgPyBfbmFtZXMubW91bnQgOiBuZXcgU2V0KCksXG4gICAgICAgICAgICB1bk1vdW50OiBuZXcgU2V0KCksXG4gICAgICAgICAgICBhcnJheTogbmV3IFNldCgpLFxuICAgICAgICAgICAgZGlzYWJsZWQ6IG5ldyBTZXQoKSxcbiAgICAgICAgICAgIHdhdGNoOiBuZXcgU2V0KCksXG4gICAgICAgICAgICB3YXRjaEFsbDogZmFsc2UsXG4gICAgICAgICAgICBmb2N1czogJycsXG4gICAgICAgIH07XG4gICAgICAgIF9zdGF0ZS5tb3VudCA9XG4gICAgICAgICAgICAhX3Byb3h5Rm9ybVN0YXRlLmlzVmFsaWQgfHxcbiAgICAgICAgICAgICAgICAhIWtlZXBTdGF0ZU9wdGlvbnMua2VlcElzVmFsaWQgfHxcbiAgICAgICAgICAgICAgICAhIWtlZXBTdGF0ZU9wdGlvbnMua2VlcERpcnR5VmFsdWVzIHx8XG4gICAgICAgICAgICAgICAgKCFfb3B0aW9ucy5zaG91bGRVbnJlZ2lzdGVyICYmICFpc0VtcHR5T2JqZWN0KHZhbHVlcykpO1xuICAgICAgICBfc3RhdGUud2F0Y2ggPSAhIV9vcHRpb25zLnNob3VsZFVucmVnaXN0ZXI7XG4gICAgICAgIF9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgIHN1Ym1pdENvdW50OiBrZWVwU3RhdGVPcHRpb25zLmtlZXBTdWJtaXRDb3VudFxuICAgICAgICAgICAgICAgID8gX2Zvcm1TdGF0ZS5zdWJtaXRDb3VudFxuICAgICAgICAgICAgICAgIDogMCxcbiAgICAgICAgICAgIGlzRGlydHk6IGlzRW1wdHlSZXNldFZhbHVlc1xuICAgICAgICAgICAgICAgID8gZmFsc2VcbiAgICAgICAgICAgICAgICA6IGtlZXBTdGF0ZU9wdGlvbnMua2VlcERpcnR5XG4gICAgICAgICAgICAgICAgICAgID8gX2Zvcm1TdGF0ZS5pc0RpcnR5XG4gICAgICAgICAgICAgICAgICAgIDogISEoa2VlcFN0YXRlT3B0aW9ucy5rZWVwRGVmYXVsdFZhbHVlcyAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgIWRlZXBFcXVhbChmb3JtVmFsdWVzLCBfZGVmYXVsdFZhbHVlcykpLFxuICAgICAgICAgICAgaXNTdWJtaXR0ZWQ6IGtlZXBTdGF0ZU9wdGlvbnMua2VlcElzU3VibWl0dGVkXG4gICAgICAgICAgICAgICAgPyBfZm9ybVN0YXRlLmlzU3VibWl0dGVkXG4gICAgICAgICAgICAgICAgOiBmYWxzZSxcbiAgICAgICAgICAgIGRpcnR5RmllbGRzOiBpc0VtcHR5UmVzZXRWYWx1ZXNcbiAgICAgICAgICAgICAgICA/IHt9XG4gICAgICAgICAgICAgICAgOiBrZWVwU3RhdGVPcHRpb25zLmtlZXBEaXJ0eVZhbHVlc1xuICAgICAgICAgICAgICAgICAgICA/IGtlZXBTdGF0ZU9wdGlvbnMua2VlcERlZmF1bHRWYWx1ZXMgJiYgX2Zvcm1WYWx1ZXNcbiAgICAgICAgICAgICAgICAgICAgICAgID8gZ2V0RGlydHlGaWVsZHMoX2RlZmF1bHRWYWx1ZXMsIF9mb3JtVmFsdWVzKVxuICAgICAgICAgICAgICAgICAgICAgICAgOiBfZm9ybVN0YXRlLmRpcnR5RmllbGRzXG4gICAgICAgICAgICAgICAgICAgIDoga2VlcFN0YXRlT3B0aW9ucy5rZWVwRGVmYXVsdFZhbHVlcyAmJiBmb3JtVmFsdWVzXG4gICAgICAgICAgICAgICAgICAgICAgICA/IGdldERpcnR5RmllbGRzKF9kZWZhdWx0VmFsdWVzLCBmb3JtVmFsdWVzKVxuICAgICAgICAgICAgICAgICAgICAgICAgOiBrZWVwU3RhdGVPcHRpb25zLmtlZXBEaXJ0eVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gX2Zvcm1TdGF0ZS5kaXJ0eUZpZWxkc1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDoge30sXG4gICAgICAgICAgICB0b3VjaGVkRmllbGRzOiBrZWVwU3RhdGVPcHRpb25zLmtlZXBUb3VjaGVkXG4gICAgICAgICAgICAgICAgPyBfZm9ybVN0YXRlLnRvdWNoZWRGaWVsZHNcbiAgICAgICAgICAgICAgICA6IHt9LFxuICAgICAgICAgICAgZXJyb3JzOiBrZWVwU3RhdGVPcHRpb25zLmtlZXBFcnJvcnMgPyBfZm9ybVN0YXRlLmVycm9ycyA6IHt9LFxuICAgICAgICAgICAgaXNTdWJtaXRTdWNjZXNzZnVsOiBrZWVwU3RhdGVPcHRpb25zLmtlZXBJc1N1Ym1pdFN1Y2Nlc3NmdWxcbiAgICAgICAgICAgICAgICA/IF9mb3JtU3RhdGUuaXNTdWJtaXRTdWNjZXNzZnVsXG4gICAgICAgICAgICAgICAgOiBmYWxzZSxcbiAgICAgICAgICAgIGlzU3VibWl0dGluZzogZmFsc2UsXG4gICAgICAgICAgICBkZWZhdWx0VmFsdWVzOiBfZGVmYXVsdFZhbHVlcyxcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBjb25zdCByZXNldCA9IChmb3JtVmFsdWVzLCBrZWVwU3RhdGVPcHRpb25zKSA9PiBfcmVzZXQoaXNGdW5jdGlvbihmb3JtVmFsdWVzKVxuICAgICAgICA/IGZvcm1WYWx1ZXMoX2Zvcm1WYWx1ZXMpXG4gICAgICAgIDogZm9ybVZhbHVlcywga2VlcFN0YXRlT3B0aW9ucyk7XG4gICAgY29uc3Qgc2V0Rm9jdXMgPSAobmFtZSwgb3B0aW9ucyA9IHt9KSA9PiB7XG4gICAgICAgIGNvbnN0IGZpZWxkID0gZ2V0KF9maWVsZHMsIG5hbWUpO1xuICAgICAgICBjb25zdCBmaWVsZFJlZmVyZW5jZSA9IGZpZWxkICYmIGZpZWxkLl9mO1xuICAgICAgICBpZiAoZmllbGRSZWZlcmVuY2UpIHtcbiAgICAgICAgICAgIGNvbnN0IGZpZWxkUmVmID0gZmllbGRSZWZlcmVuY2UucmVmc1xuICAgICAgICAgICAgICAgID8gZmllbGRSZWZlcmVuY2UucmVmc1swXVxuICAgICAgICAgICAgICAgIDogZmllbGRSZWZlcmVuY2UucmVmO1xuICAgICAgICAgICAgaWYgKGZpZWxkUmVmLmZvY3VzKSB7XG4gICAgICAgICAgICAgICAgZmllbGRSZWYuZm9jdXMoKTtcbiAgICAgICAgICAgICAgICBvcHRpb25zLnNob3VsZFNlbGVjdCAmJlxuICAgICAgICAgICAgICAgICAgICBpc0Z1bmN0aW9uKGZpZWxkUmVmLnNlbGVjdCkgJiZcbiAgICAgICAgICAgICAgICAgICAgZmllbGRSZWYuc2VsZWN0KCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9O1xuICAgIGNvbnN0IF9zZXRGb3JtU3RhdGUgPSAodXBkYXRlZEZvcm1TdGF0ZSkgPT4ge1xuICAgICAgICBfZm9ybVN0YXRlID0ge1xuICAgICAgICAgICAgLi4uX2Zvcm1TdGF0ZSxcbiAgICAgICAgICAgIC4uLnVwZGF0ZWRGb3JtU3RhdGUsXG4gICAgICAgIH07XG4gICAgfTtcbiAgICBjb25zdCBfcmVzZXREZWZhdWx0VmFsdWVzID0gKCkgPT4gaXNGdW5jdGlvbihfb3B0aW9ucy5kZWZhdWx0VmFsdWVzKSAmJlxuICAgICAgICBfb3B0aW9ucy5kZWZhdWx0VmFsdWVzKCkudGhlbigodmFsdWVzKSA9PiB7XG4gICAgICAgICAgICByZXNldCh2YWx1ZXMsIF9vcHRpb25zLnJlc2V0T3B0aW9ucyk7XG4gICAgICAgICAgICBfc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICAgICAgaXNMb2FkaW5nOiBmYWxzZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9KTtcbiAgICBjb25zdCBtZXRob2RzID0ge1xuICAgICAgICBjb250cm9sOiB7XG4gICAgICAgICAgICByZWdpc3RlcixcbiAgICAgICAgICAgIHVucmVnaXN0ZXIsXG4gICAgICAgICAgICBnZXRGaWVsZFN0YXRlLFxuICAgICAgICAgICAgaGFuZGxlU3VibWl0LFxuICAgICAgICAgICAgc2V0RXJyb3IsXG4gICAgICAgICAgICBfc3Vic2NyaWJlLFxuICAgICAgICAgICAgX3J1blNjaGVtYSxcbiAgICAgICAgICAgIF9mb2N1c0Vycm9yLFxuICAgICAgICAgICAgX2dldFdhdGNoLFxuICAgICAgICAgICAgX2dldERpcnR5LFxuICAgICAgICAgICAgX3NldFZhbGlkLFxuICAgICAgICAgICAgX3NldEZpZWxkQXJyYXksXG4gICAgICAgICAgICBfc2V0RGlzYWJsZWRGaWVsZCxcbiAgICAgICAgICAgIF9zZXRFcnJvcnMsXG4gICAgICAgICAgICBfZ2V0RmllbGRBcnJheSxcbiAgICAgICAgICAgIF9yZXNldCxcbiAgICAgICAgICAgIF9yZXNldERlZmF1bHRWYWx1ZXMsXG4gICAgICAgICAgICBfcmVtb3ZlVW5tb3VudGVkLFxuICAgICAgICAgICAgX2Rpc2FibGVGb3JtLFxuICAgICAgICAgICAgX3N1YmplY3RzLFxuICAgICAgICAgICAgX3Byb3h5Rm9ybVN0YXRlLFxuICAgICAgICAgICAgZ2V0IF9maWVsZHMoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9maWVsZHM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0IF9mb3JtVmFsdWVzKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfZm9ybVZhbHVlcztcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXQgX3N0YXRlKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiBfc3RhdGU7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgc2V0IF9zdGF0ZSh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIF9zdGF0ZSA9IHZhbHVlO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGdldCBfZGVmYXVsdFZhbHVlcygpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX2RlZmF1bHRWYWx1ZXM7XG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgZ2V0IF9uYW1lcygpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX25hbWVzO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldCBfbmFtZXModmFsdWUpIHtcbiAgICAgICAgICAgICAgICBfbmFtZXMgPSB2YWx1ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXQgX2Zvcm1TdGF0ZSgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gX2Zvcm1TdGF0ZTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBnZXQgX29wdGlvbnMoKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIF9vcHRpb25zO1xuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNldCBfb3B0aW9ucyh2YWx1ZSkge1xuICAgICAgICAgICAgICAgIF9vcHRpb25zID0ge1xuICAgICAgICAgICAgICAgICAgICAuLi5fb3B0aW9ucyxcbiAgICAgICAgICAgICAgICAgICAgLi4udmFsdWUsXG4gICAgICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHN1YnNjcmliZSxcbiAgICAgICAgdHJpZ2dlcixcbiAgICAgICAgcmVnaXN0ZXIsXG4gICAgICAgIGhhbmRsZVN1Ym1pdCxcbiAgICAgICAgd2F0Y2gsXG4gICAgICAgIHNldFZhbHVlLFxuICAgICAgICBnZXRWYWx1ZXMsXG4gICAgICAgIHJlc2V0LFxuICAgICAgICByZXNldEZpZWxkLFxuICAgICAgICBjbGVhckVycm9ycyxcbiAgICAgICAgdW5yZWdpc3RlcixcbiAgICAgICAgc2V0RXJyb3IsXG4gICAgICAgIHNldEZvY3VzLFxuICAgICAgICBnZXRGaWVsZFN0YXRlLFxuICAgIH07XG4gICAgcmV0dXJuIHtcbiAgICAgICAgLi4ubWV0aG9kcyxcbiAgICAgICAgZm9ybUNvbnRyb2w6IG1ldGhvZHMsXG4gICAgfTtcbn1cblxudmFyIGdlbmVyYXRlSWQgPSAoKSA9PiB7XG4gICAgaWYgKHR5cGVvZiBjcnlwdG8gIT09ICd1bmRlZmluZWQnICYmIGNyeXB0by5yYW5kb21VVUlEKSB7XG4gICAgICAgIHJldHVybiBjcnlwdG8ucmFuZG9tVVVJRCgpO1xuICAgIH1cbiAgICBjb25zdCBkID0gdHlwZW9mIHBlcmZvcm1hbmNlID09PSAndW5kZWZpbmVkJyA/IERhdGUubm93KCkgOiBwZXJmb3JtYW5jZS5ub3coKSAqIDEwMDA7XG4gICAgcmV0dXJuICd4eHh4eHh4eC14eHh4LTR4eHgteXh4eC14eHh4eHh4eHh4eHgnLnJlcGxhY2UoL1t4eV0vZywgKGMpID0+IHtcbiAgICAgICAgY29uc3QgciA9IChNYXRoLnJhbmRvbSgpICogMTYgKyBkKSAlIDE2IHwgMDtcbiAgICAgICAgcmV0dXJuIChjID09ICd4JyA/IHIgOiAociAmIDB4MykgfCAweDgpLnRvU3RyaW5nKDE2KTtcbiAgICB9KTtcbn07XG5cbnZhciBnZXRGb2N1c0ZpZWxkTmFtZSA9IChuYW1lLCBpbmRleCwgb3B0aW9ucyA9IHt9KSA9PiBvcHRpb25zLnNob3VsZEZvY3VzIHx8IGlzVW5kZWZpbmVkKG9wdGlvbnMuc2hvdWxkRm9jdXMpXG4gICAgPyBvcHRpb25zLmZvY3VzTmFtZSB8fFxuICAgICAgICBgJHtuYW1lfS4ke2lzVW5kZWZpbmVkKG9wdGlvbnMuZm9jdXNJbmRleCkgPyBpbmRleCA6IG9wdGlvbnMuZm9jdXNJbmRleH0uYFxuICAgIDogJyc7XG5cbnZhciBhcHBlbmRBdCA9IChkYXRhLCB2YWx1ZSkgPT4gW1xuICAgIC4uLmRhdGEsXG4gICAgLi4uY29udmVydFRvQXJyYXlQYXlsb2FkKHZhbHVlKSxcbl07XG5cbnZhciBmaWxsRW1wdHlBcnJheSA9ICh2YWx1ZSkgPT4gQXJyYXkuaXNBcnJheSh2YWx1ZSkgPyB2YWx1ZS5tYXAoKCkgPT4gdW5kZWZpbmVkKSA6IHVuZGVmaW5lZDtcblxuZnVuY3Rpb24gaW5zZXJ0KGRhdGEsIGluZGV4LCB2YWx1ZSkge1xuICAgIHJldHVybiBbXG4gICAgICAgIC4uLmRhdGEuc2xpY2UoMCwgaW5kZXgpLFxuICAgICAgICAuLi5jb252ZXJ0VG9BcnJheVBheWxvYWQodmFsdWUpLFxuICAgICAgICAuLi5kYXRhLnNsaWNlKGluZGV4KSxcbiAgICBdO1xufVxuXG52YXIgbW92ZUFycmF5QXQgPSAoZGF0YSwgZnJvbSwgdG8pID0+IHtcbiAgICBpZiAoIUFycmF5LmlzQXJyYXkoZGF0YSkpIHtcbiAgICAgICAgcmV0dXJuIFtdO1xuICAgIH1cbiAgICBpZiAoaXNVbmRlZmluZWQoZGF0YVt0b10pKSB7XG4gICAgICAgIGRhdGFbdG9dID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICBkYXRhLnNwbGljZSh0bywgMCwgZGF0YS5zcGxpY2UoZnJvbSwgMSlbMF0pO1xuICAgIHJldHVybiBkYXRhO1xufTtcblxudmFyIHByZXBlbmRBdCA9IChkYXRhLCB2YWx1ZSkgPT4gW1xuICAgIC4uLmNvbnZlcnRUb0FycmF5UGF5bG9hZCh2YWx1ZSksXG4gICAgLi4uY29udmVydFRvQXJyYXlQYXlsb2FkKGRhdGEpLFxuXTtcblxuZnVuY3Rpb24gcmVtb3ZlQXRJbmRleGVzKGRhdGEsIGluZGV4ZXMpIHtcbiAgICBsZXQgaSA9IDA7XG4gICAgY29uc3QgdGVtcCA9IFsuLi5kYXRhXTtcbiAgICBmb3IgKGNvbnN0IGluZGV4IG9mIGluZGV4ZXMpIHtcbiAgICAgICAgdGVtcC5zcGxpY2UoaW5kZXggLSBpLCAxKTtcbiAgICAgICAgaSsrO1xuICAgIH1cbiAgICByZXR1cm4gY29tcGFjdCh0ZW1wKS5sZW5ndGggPyB0ZW1wIDogW107XG59XG52YXIgcmVtb3ZlQXJyYXlBdCA9IChkYXRhLCBpbmRleCkgPT4gaXNVbmRlZmluZWQoaW5kZXgpXG4gICAgPyBbXVxuICAgIDogcmVtb3ZlQXRJbmRleGVzKGRhdGEsIGNvbnZlcnRUb0FycmF5UGF5bG9hZChpbmRleCkuc29ydCgoYSwgYikgPT4gYSAtIGIpKTtcblxudmFyIHN3YXBBcnJheUF0ID0gKGRhdGEsIGluZGV4QSwgaW5kZXhCKSA9PiB7XG4gICAgW2RhdGFbaW5kZXhBXSwgZGF0YVtpbmRleEJdXSA9IFtkYXRhW2luZGV4Ql0sIGRhdGFbaW5kZXhBXV07XG59O1xuXG52YXIgdXBkYXRlQXQgPSAoZmllbGRWYWx1ZXMsIGluZGV4LCB2YWx1ZSkgPT4ge1xuICAgIGZpZWxkVmFsdWVzW2luZGV4XSA9IHZhbHVlO1xuICAgIHJldHVybiBmaWVsZFZhbHVlcztcbn07XG5cbi8qKlxuICogQSBjdXN0b20gaG9vayB0aGF0IGV4cG9zZXMgY29udmVuaWVudCBtZXRob2RzIHRvIHBlcmZvcm0gb3BlcmF0aW9ucyB3aXRoIGEgbGlzdCBvZiBkeW5hbWljIGlucHV0cyB0aGF0IG5lZWQgdG8gYmUgYXBwZW5kZWQsIHVwZGF0ZWQsIHJlbW92ZWQgZXRjLiDigKIgW0RlbW9dKGh0dHBzOi8vY29kZXNhbmRib3guaW8vcy9yZWFjdC1ob29rLWZvcm0tdXNlZmllbGRhcnJheS1zc3Vnbikg4oCiIFtWaWRlb10oaHR0cHM6Ly95b3V0dS5iZS80TXJiZkdTRlkyQSlcbiAqXG4gKiBAcmVtYXJrc1xuICogW0FQSV0oaHR0cHM6Ly9yZWFjdC1ob29rLWZvcm0uY29tL2RvY3MvdXNlZmllbGRhcnJheSkg4oCiIFtEZW1vXShodHRwczovL2NvZGVzYW5kYm94LmlvL3MvcmVhY3QtaG9vay1mb3JtLXVzZWZpZWxkYXJyYXktc3N1Z24pXG4gKlxuICogQHBhcmFtIHByb3BzIC0gdXNlRmllbGRBcnJheSBwcm9wc1xuICpcbiAqIEByZXR1cm5zIG1ldGhvZHMgLSBmdW5jdGlvbnMgdG8gbWFuaXB1bGF0ZSB3aXRoIHRoZSBGaWVsZCBBcnJheXMgKGR5bmFtaWMgaW5wdXRzKSB7QGxpbmsgVXNlRmllbGRBcnJheVJldHVybn1cbiAqXG4gKiBAZXhhbXBsZVxuICogYGBgdHN4XG4gKiBmdW5jdGlvbiBBcHAoKSB7XG4gKiAgIGNvbnN0IHsgcmVnaXN0ZXIsIGNvbnRyb2wsIGhhbmRsZVN1Ym1pdCwgcmVzZXQsIHRyaWdnZXIsIHNldEVycm9yIH0gPSB1c2VGb3JtKHtcbiAqICAgICBkZWZhdWx0VmFsdWVzOiB7XG4gKiAgICAgICB0ZXN0OiBbXVxuICogICAgIH1cbiAqICAgfSk7XG4gKiAgIGNvbnN0IHsgZmllbGRzLCBhcHBlbmQgfSA9IHVzZUZpZWxkQXJyYXkoe1xuICogICAgIGNvbnRyb2wsXG4gKiAgICAgbmFtZTogXCJ0ZXN0XCJcbiAqICAgfSk7XG4gKlxuICogICByZXR1cm4gKFxuICogICAgIDxmb3JtIG9uU3VibWl0PXtoYW5kbGVTdWJtaXQoZGF0YSA9PiBjb25zb2xlLmxvZyhkYXRhKSl9PlxuICogICAgICAge2ZpZWxkcy5tYXAoKGl0ZW0sIGluZGV4KSA9PiAoXG4gKiAgICAgICAgICA8aW5wdXQga2V5PXtpdGVtLmlkfSB7Li4ucmVnaXN0ZXIoYHRlc3QuJHtpbmRleH0uZmlyc3ROYW1lYCl9ICAvPlxuICogICAgICAgKSl9XG4gKiAgICAgICA8YnV0dG9uIHR5cGU9XCJidXR0b25cIiBvbkNsaWNrPXsoKSA9PiBhcHBlbmQoeyBmaXJzdE5hbWU6IFwiYmlsbFwiIH0pfT5cbiAqICAgICAgICAgYXBwZW5kXG4gKiAgICAgICA8L2J1dHRvbj5cbiAqICAgICAgIDxpbnB1dCB0eXBlPVwic3VibWl0XCIgLz5cbiAqICAgICA8L2Zvcm0+XG4gKiAgICk7XG4gKiB9XG4gKiBgYGBcbiAqL1xuZnVuY3Rpb24gdXNlRmllbGRBcnJheShwcm9wcykge1xuICAgIGNvbnN0IG1ldGhvZHMgPSB1c2VGb3JtQ29udGV4dCgpO1xuICAgIGNvbnN0IHsgY29udHJvbCA9IG1ldGhvZHMuY29udHJvbCwgbmFtZSwga2V5TmFtZSA9ICdpZCcsIHNob3VsZFVucmVnaXN0ZXIsIHJ1bGVzLCB9ID0gcHJvcHM7XG4gICAgY29uc3QgW2ZpZWxkcywgc2V0RmllbGRzXSA9IFJlYWN0LnVzZVN0YXRlKGNvbnRyb2wuX2dldEZpZWxkQXJyYXkobmFtZSkpO1xuICAgIGNvbnN0IGlkcyA9IFJlYWN0LnVzZVJlZihjb250cm9sLl9nZXRGaWVsZEFycmF5KG5hbWUpLm1hcChnZW5lcmF0ZUlkKSk7XG4gICAgY29uc3QgX2FjdGlvbmVkID0gUmVhY3QudXNlUmVmKGZhbHNlKTtcbiAgICBjb250cm9sLl9uYW1lcy5hcnJheS5hZGQobmFtZSk7XG4gICAgUmVhY3QudXNlTWVtbygoKSA9PiBydWxlcyAmJlxuICAgICAgICBmaWVsZHMubGVuZ3RoID49IDAgJiZcbiAgICAgICAgY29udHJvbC5yZWdpc3RlcihuYW1lLCBydWxlcyksIFtjb250cm9sLCBuYW1lLCBmaWVsZHMubGVuZ3RoLCBydWxlc10pO1xuICAgIHVzZUlzb21vcnBoaWNMYXlvdXRFZmZlY3QoKCkgPT4gY29udHJvbC5fc3ViamVjdHMuYXJyYXkuc3Vic2NyaWJlKHtcbiAgICAgICAgbmV4dDogKHsgdmFsdWVzLCBuYW1lOiBmaWVsZEFycmF5TmFtZSwgfSkgPT4ge1xuICAgICAgICAgICAgaWYgKGZpZWxkQXJyYXlOYW1lID09PSBuYW1lIHx8ICFmaWVsZEFycmF5TmFtZSkge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpZWxkVmFsdWVzID0gZ2V0KHZhbHVlcywgbmFtZSk7XG4gICAgICAgICAgICAgICAgaWYgKEFycmF5LmlzQXJyYXkoZmllbGRWYWx1ZXMpKSB7XG4gICAgICAgICAgICAgICAgICAgIHNldEZpZWxkcyhmaWVsZFZhbHVlcyk7XG4gICAgICAgICAgICAgICAgICAgIGlkcy5jdXJyZW50ID0gZmllbGRWYWx1ZXMubWFwKGdlbmVyYXRlSWQpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgfSxcbiAgICB9KS51bnN1YnNjcmliZSwgW2NvbnRyb2wsIG5hbWVdKTtcbiAgICBjb25zdCB1cGRhdGVWYWx1ZXMgPSBSZWFjdC51c2VDYWxsYmFjaygodXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXMpID0+IHtcbiAgICAgICAgX2FjdGlvbmVkLmN1cnJlbnQgPSB0cnVlO1xuICAgICAgICBjb250cm9sLl9zZXRGaWVsZEFycmF5KG5hbWUsIHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICB9LCBbY29udHJvbCwgbmFtZV0pO1xuICAgIGNvbnN0IGFwcGVuZCA9ICh2YWx1ZSwgb3B0aW9ucykgPT4ge1xuICAgICAgICBjb25zdCBhcHBlbmRWYWx1ZSA9IGNvbnZlcnRUb0FycmF5UGF5bG9hZChjbG9uZU9iamVjdCh2YWx1ZSkpO1xuICAgICAgICBjb25zdCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcyA9IGFwcGVuZEF0KGNvbnRyb2wuX2dldEZpZWxkQXJyYXkobmFtZSksIGFwcGVuZFZhbHVlKTtcbiAgICAgICAgY29udHJvbC5fbmFtZXMuZm9jdXMgPSBnZXRGb2N1c0ZpZWxkTmFtZShuYW1lLCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcy5sZW5ndGggLSAxLCBvcHRpb25zKTtcbiAgICAgICAgaWRzLmN1cnJlbnQgPSBhcHBlbmRBdChpZHMuY3VycmVudCwgYXBwZW5kVmFsdWUubWFwKGdlbmVyYXRlSWQpKTtcbiAgICAgICAgdXBkYXRlVmFsdWVzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgc2V0RmllbGRzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgY29udHJvbC5fc2V0RmllbGRBcnJheShuYW1lLCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcywgYXBwZW5kQXQsIHtcbiAgICAgICAgICAgIGFyZ0E6IGZpbGxFbXB0eUFycmF5KHZhbHVlKSxcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBjb25zdCBwcmVwZW5kID0gKHZhbHVlLCBvcHRpb25zKSA9PiB7XG4gICAgICAgIGNvbnN0IHByZXBlbmRWYWx1ZSA9IGNvbnZlcnRUb0FycmF5UGF5bG9hZChjbG9uZU9iamVjdCh2YWx1ZSkpO1xuICAgICAgICBjb25zdCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcyA9IHByZXBlbmRBdChjb250cm9sLl9nZXRGaWVsZEFycmF5KG5hbWUpLCBwcmVwZW5kVmFsdWUpO1xuICAgICAgICBjb250cm9sLl9uYW1lcy5mb2N1cyA9IGdldEZvY3VzRmllbGROYW1lKG5hbWUsIDAsIG9wdGlvbnMpO1xuICAgICAgICBpZHMuY3VycmVudCA9IHByZXBlbmRBdChpZHMuY3VycmVudCwgcHJlcGVuZFZhbHVlLm1hcChnZW5lcmF0ZUlkKSk7XG4gICAgICAgIHVwZGF0ZVZhbHVlcyh1cGRhdGVkRmllbGRBcnJheVZhbHVlcyk7XG4gICAgICAgIHNldEZpZWxkcyh1cGRhdGVkRmllbGRBcnJheVZhbHVlcyk7XG4gICAgICAgIGNvbnRyb2wuX3NldEZpZWxkQXJyYXkobmFtZSwgdXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXMsIHByZXBlbmRBdCwge1xuICAgICAgICAgICAgYXJnQTogZmlsbEVtcHR5QXJyYXkodmFsdWUpLFxuICAgICAgICB9KTtcbiAgICB9O1xuICAgIGNvbnN0IHJlbW92ZSA9IChpbmRleCkgPT4ge1xuICAgICAgICBjb25zdCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcyA9IHJlbW92ZUFycmF5QXQoY29udHJvbC5fZ2V0RmllbGRBcnJheShuYW1lKSwgaW5kZXgpO1xuICAgICAgICBpZHMuY3VycmVudCA9IHJlbW92ZUFycmF5QXQoaWRzLmN1cnJlbnQsIGluZGV4KTtcbiAgICAgICAgdXBkYXRlVmFsdWVzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgc2V0RmllbGRzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoZ2V0KGNvbnRyb2wuX2ZpZWxkcywgbmFtZSkpICYmXG4gICAgICAgICAgICBzZXQoY29udHJvbC5fZmllbGRzLCBuYW1lLCB1bmRlZmluZWQpO1xuICAgICAgICBjb250cm9sLl9zZXRGaWVsZEFycmF5KG5hbWUsIHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzLCByZW1vdmVBcnJheUF0LCB7XG4gICAgICAgICAgICBhcmdBOiBpbmRleCxcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBjb25zdCBpbnNlcnQkMSA9IChpbmRleCwgdmFsdWUsIG9wdGlvbnMpID0+IHtcbiAgICAgICAgY29uc3QgaW5zZXJ0VmFsdWUgPSBjb252ZXJ0VG9BcnJheVBheWxvYWQoY2xvbmVPYmplY3QodmFsdWUpKTtcbiAgICAgICAgY29uc3QgdXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXMgPSBpbnNlcnQoY29udHJvbC5fZ2V0RmllbGRBcnJheShuYW1lKSwgaW5kZXgsIGluc2VydFZhbHVlKTtcbiAgICAgICAgY29udHJvbC5fbmFtZXMuZm9jdXMgPSBnZXRGb2N1c0ZpZWxkTmFtZShuYW1lLCBpbmRleCwgb3B0aW9ucyk7XG4gICAgICAgIGlkcy5jdXJyZW50ID0gaW5zZXJ0KGlkcy5jdXJyZW50LCBpbmRleCwgaW5zZXJ0VmFsdWUubWFwKGdlbmVyYXRlSWQpKTtcbiAgICAgICAgdXBkYXRlVmFsdWVzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgc2V0RmllbGRzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgY29udHJvbC5fc2V0RmllbGRBcnJheShuYW1lLCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcywgaW5zZXJ0LCB7XG4gICAgICAgICAgICBhcmdBOiBpbmRleCxcbiAgICAgICAgICAgIGFyZ0I6IGZpbGxFbXB0eUFycmF5KHZhbHVlKSxcbiAgICAgICAgfSk7XG4gICAgfTtcbiAgICBjb25zdCBzd2FwID0gKGluZGV4QSwgaW5kZXhCKSA9PiB7XG4gICAgICAgIGNvbnN0IHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzID0gY29udHJvbC5fZ2V0RmllbGRBcnJheShuYW1lKTtcbiAgICAgICAgc3dhcEFycmF5QXQodXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXMsIGluZGV4QSwgaW5kZXhCKTtcbiAgICAgICAgc3dhcEFycmF5QXQoaWRzLmN1cnJlbnQsIGluZGV4QSwgaW5kZXhCKTtcbiAgICAgICAgdXBkYXRlVmFsdWVzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgc2V0RmllbGRzKHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzKTtcbiAgICAgICAgY29udHJvbC5fc2V0RmllbGRBcnJheShuYW1lLCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcywgc3dhcEFycmF5QXQsIHtcbiAgICAgICAgICAgIGFyZ0E6IGluZGV4QSxcbiAgICAgICAgICAgIGFyZ0I6IGluZGV4QixcbiAgICAgICAgfSwgZmFsc2UpO1xuICAgIH07XG4gICAgY29uc3QgbW92ZSA9IChmcm9tLCB0bykgPT4ge1xuICAgICAgICBjb25zdCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcyA9IGNvbnRyb2wuX2dldEZpZWxkQXJyYXkobmFtZSk7XG4gICAgICAgIG1vdmVBcnJheUF0KHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzLCBmcm9tLCB0byk7XG4gICAgICAgIG1vdmVBcnJheUF0KGlkcy5jdXJyZW50LCBmcm9tLCB0byk7XG4gICAgICAgIHVwZGF0ZVZhbHVlcyh1cGRhdGVkRmllbGRBcnJheVZhbHVlcyk7XG4gICAgICAgIHNldEZpZWxkcyh1cGRhdGVkRmllbGRBcnJheVZhbHVlcyk7XG4gICAgICAgIGNvbnRyb2wuX3NldEZpZWxkQXJyYXkobmFtZSwgdXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXMsIG1vdmVBcnJheUF0LCB7XG4gICAgICAgICAgICBhcmdBOiBmcm9tLFxuICAgICAgICAgICAgYXJnQjogdG8sXG4gICAgICAgIH0sIGZhbHNlKTtcbiAgICB9O1xuICAgIGNvbnN0IHVwZGF0ZSA9IChpbmRleCwgdmFsdWUpID0+IHtcbiAgICAgICAgY29uc3QgdXBkYXRlVmFsdWUgPSBjbG9uZU9iamVjdCh2YWx1ZSk7XG4gICAgICAgIGNvbnN0IHVwZGF0ZWRGaWVsZEFycmF5VmFsdWVzID0gdXBkYXRlQXQoY29udHJvbC5fZ2V0RmllbGRBcnJheShuYW1lKSwgaW5kZXgsIHVwZGF0ZVZhbHVlKTtcbiAgICAgICAgaWRzLmN1cnJlbnQgPSBbLi4udXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXNdLm1hcCgoaXRlbSwgaSkgPT4gIWl0ZW0gfHwgaSA9PT0gaW5kZXggPyBnZW5lcmF0ZUlkKCkgOiBpZHMuY3VycmVudFtpXSk7XG4gICAgICAgIHVwZGF0ZVZhbHVlcyh1cGRhdGVkRmllbGRBcnJheVZhbHVlcyk7XG4gICAgICAgIHNldEZpZWxkcyhbLi4udXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXNdKTtcbiAgICAgICAgY29udHJvbC5fc2V0RmllbGRBcnJheShuYW1lLCB1cGRhdGVkRmllbGRBcnJheVZhbHVlcywgdXBkYXRlQXQsIHtcbiAgICAgICAgICAgIGFyZ0E6IGluZGV4LFxuICAgICAgICAgICAgYXJnQjogdXBkYXRlVmFsdWUsXG4gICAgICAgIH0sIHRydWUsIGZhbHNlKTtcbiAgICB9O1xuICAgIGNvbnN0IHJlcGxhY2UgPSAodmFsdWUpID0+IHtcbiAgICAgICAgY29uc3QgdXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXMgPSBjb252ZXJ0VG9BcnJheVBheWxvYWQoY2xvbmVPYmplY3QodmFsdWUpKTtcbiAgICAgICAgaWRzLmN1cnJlbnQgPSB1cGRhdGVkRmllbGRBcnJheVZhbHVlcy5tYXAoZ2VuZXJhdGVJZCk7XG4gICAgICAgIHVwZGF0ZVZhbHVlcyhbLi4udXBkYXRlZEZpZWxkQXJyYXlWYWx1ZXNdKTtcbiAgICAgICAgc2V0RmllbGRzKFsuLi51cGRhdGVkRmllbGRBcnJheVZhbHVlc10pO1xuICAgICAgICBjb250cm9sLl9zZXRGaWVsZEFycmF5KG5hbWUsIFsuLi51cGRhdGVkRmllbGRBcnJheVZhbHVlc10sIChkYXRhKSA9PiBkYXRhLCB7fSwgdHJ1ZSwgZmFsc2UpO1xuICAgIH07XG4gICAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgY29udHJvbC5fc3RhdGUuYWN0aW9uID0gZmFsc2U7XG4gICAgICAgIGlzV2F0Y2hlZChuYW1lLCBjb250cm9sLl9uYW1lcykgJiZcbiAgICAgICAgICAgIGNvbnRyb2wuX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgICAgIC4uLmNvbnRyb2wuX2Zvcm1TdGF0ZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICBpZiAoX2FjdGlvbmVkLmN1cnJlbnQgJiZcbiAgICAgICAgICAgICghZ2V0VmFsaWRhdGlvbk1vZGVzKGNvbnRyb2wuX29wdGlvbnMubW9kZSkuaXNPblN1Ym1pdCB8fFxuICAgICAgICAgICAgICAgIGNvbnRyb2wuX2Zvcm1TdGF0ZS5pc1N1Ym1pdHRlZCkgJiZcbiAgICAgICAgICAgICFnZXRWYWxpZGF0aW9uTW9kZXMoY29udHJvbC5fb3B0aW9ucy5yZVZhbGlkYXRlTW9kZSkuaXNPblN1Ym1pdCkge1xuICAgICAgICAgICAgaWYgKGNvbnRyb2wuX29wdGlvbnMucmVzb2x2ZXIpIHtcbiAgICAgICAgICAgICAgICBjb250cm9sLl9ydW5TY2hlbWEoW25hbWVdKS50aGVuKChyZXN1bHQpID0+IHtcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgZXJyb3IgPSBnZXQocmVzdWx0LmVycm9ycywgbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGV4aXN0aW5nRXJyb3IgPSBnZXQoY29udHJvbC5fZm9ybVN0YXRlLmVycm9ycywgbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgIGlmIChleGlzdGluZ0Vycm9yXG4gICAgICAgICAgICAgICAgICAgICAgICA/ICghZXJyb3IgJiYgZXhpc3RpbmdFcnJvci50eXBlKSB8fFxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIChlcnJvciAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoZXhpc3RpbmdFcnJvci50eXBlICE9PSBlcnJvci50eXBlIHx8XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGlzdGluZ0Vycm9yLm1lc3NhZ2UgIT09IGVycm9yLm1lc3NhZ2UpKVxuICAgICAgICAgICAgICAgICAgICAgICAgOiBlcnJvciAmJiBlcnJvci50eXBlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBlcnJvclxuICAgICAgICAgICAgICAgICAgICAgICAgICAgID8gc2V0KGNvbnRyb2wuX2Zvcm1TdGF0ZS5lcnJvcnMsIG5hbWUsIGVycm9yKVxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIDogdW5zZXQoY29udHJvbC5fZm9ybVN0YXRlLmVycm9ycywgbmFtZSk7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb250cm9sLl9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICBlcnJvcnM6IGNvbnRyb2wuX2Zvcm1TdGF0ZS5lcnJvcnMsXG4gICAgICAgICAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZWxzZSB7XG4gICAgICAgICAgICAgICAgY29uc3QgZmllbGQgPSBnZXQoY29udHJvbC5fZmllbGRzLCBuYW1lKTtcbiAgICAgICAgICAgICAgICBpZiAoZmllbGQgJiZcbiAgICAgICAgICAgICAgICAgICAgZmllbGQuX2YgJiZcbiAgICAgICAgICAgICAgICAgICAgIShnZXRWYWxpZGF0aW9uTW9kZXMoY29udHJvbC5fb3B0aW9ucy5yZVZhbGlkYXRlTW9kZSkuaXNPblN1Ym1pdCAmJlxuICAgICAgICAgICAgICAgICAgICAgICAgZ2V0VmFsaWRhdGlvbk1vZGVzKGNvbnRyb2wuX29wdGlvbnMubW9kZSkuaXNPblN1Ym1pdCkpIHtcbiAgICAgICAgICAgICAgICAgICAgdmFsaWRhdGVGaWVsZChmaWVsZCwgY29udHJvbC5fbmFtZXMuZGlzYWJsZWQsIGNvbnRyb2wuX2Zvcm1WYWx1ZXMsIGNvbnRyb2wuX29wdGlvbnMuY3JpdGVyaWFNb2RlID09PSBWQUxJREFUSU9OX01PREUuYWxsLCBjb250cm9sLl9vcHRpb25zLnNob3VsZFVzZU5hdGl2ZVZhbGlkYXRpb24sIHRydWUpLnRoZW4oKGVycm9yKSA9PiAhaXNFbXB0eU9iamVjdChlcnJvcikgJiZcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnRyb2wuX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIGVycm9yczogdXBkYXRlRmllbGRBcnJheVJvb3RFcnJvcihjb250cm9sLl9mb3JtU3RhdGUuZXJyb3JzLCBlcnJvciwgbmFtZSksXG4gICAgICAgICAgICAgICAgICAgICAgICB9KSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIGNvbnRyb2wuX3N1YmplY3RzLnN0YXRlLm5leHQoe1xuICAgICAgICAgICAgbmFtZSxcbiAgICAgICAgICAgIHZhbHVlczogY2xvbmVPYmplY3QoY29udHJvbC5fZm9ybVZhbHVlcyksXG4gICAgICAgIH0pO1xuICAgICAgICBjb250cm9sLl9uYW1lcy5mb2N1cyAmJlxuICAgICAgICAgICAgaXRlcmF0ZUZpZWxkc0J5QWN0aW9uKGNvbnRyb2wuX2ZpZWxkcywgKHJlZiwga2V5KSA9PiB7XG4gICAgICAgICAgICAgICAgaWYgKGNvbnRyb2wuX25hbWVzLmZvY3VzICYmXG4gICAgICAgICAgICAgICAgICAgIGtleS5zdGFydHNXaXRoKGNvbnRyb2wuX25hbWVzLmZvY3VzKSAmJlxuICAgICAgICAgICAgICAgICAgICByZWYuZm9jdXMpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVmLmZvY3VzKCk7XG4gICAgICAgICAgICAgICAgICAgIHJldHVybiAxO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgY29udHJvbC5fbmFtZXMuZm9jdXMgPSAnJztcbiAgICAgICAgY29udHJvbC5fc2V0VmFsaWQoKTtcbiAgICAgICAgX2FjdGlvbmVkLmN1cnJlbnQgPSBmYWxzZTtcbiAgICB9LCBbZmllbGRzLCBuYW1lLCBjb250cm9sXSk7XG4gICAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgIWdldChjb250cm9sLl9mb3JtVmFsdWVzLCBuYW1lKSAmJiBjb250cm9sLl9zZXRGaWVsZEFycmF5KG5hbWUpO1xuICAgICAgICByZXR1cm4gKCkgPT4ge1xuICAgICAgICAgICAgY29uc3QgdXBkYXRlTW91bnRlZCA9IChuYW1lLCB2YWx1ZSkgPT4ge1xuICAgICAgICAgICAgICAgIGNvbnN0IGZpZWxkID0gZ2V0KGNvbnRyb2wuX2ZpZWxkcywgbmFtZSk7XG4gICAgICAgICAgICAgICAgaWYgKGZpZWxkICYmIGZpZWxkLl9mKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpZWxkLl9mLm1vdW50ID0gdmFsdWU7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGNvbnRyb2wuX29wdGlvbnMuc2hvdWxkVW5yZWdpc3RlciB8fCBzaG91bGRVbnJlZ2lzdGVyXG4gICAgICAgICAgICAgICAgPyBjb250cm9sLnVucmVnaXN0ZXIobmFtZSlcbiAgICAgICAgICAgICAgICA6IHVwZGF0ZU1vdW50ZWQobmFtZSwgZmFsc2UpO1xuICAgICAgICB9O1xuICAgIH0sIFtuYW1lLCBjb250cm9sLCBrZXlOYW1lLCBzaG91bGRVbnJlZ2lzdGVyXSk7XG4gICAgcmV0dXJuIHtcbiAgICAgICAgc3dhcDogUmVhY3QudXNlQ2FsbGJhY2soc3dhcCwgW3VwZGF0ZVZhbHVlcywgbmFtZSwgY29udHJvbF0pLFxuICAgICAgICBtb3ZlOiBSZWFjdC51c2VDYWxsYmFjayhtb3ZlLCBbdXBkYXRlVmFsdWVzLCBuYW1lLCBjb250cm9sXSksXG4gICAgICAgIHByZXBlbmQ6IFJlYWN0LnVzZUNhbGxiYWNrKHByZXBlbmQsIFt1cGRhdGVWYWx1ZXMsIG5hbWUsIGNvbnRyb2xdKSxcbiAgICAgICAgYXBwZW5kOiBSZWFjdC51c2VDYWxsYmFjayhhcHBlbmQsIFt1cGRhdGVWYWx1ZXMsIG5hbWUsIGNvbnRyb2xdKSxcbiAgICAgICAgcmVtb3ZlOiBSZWFjdC51c2VDYWxsYmFjayhyZW1vdmUsIFt1cGRhdGVWYWx1ZXMsIG5hbWUsIGNvbnRyb2xdKSxcbiAgICAgICAgaW5zZXJ0OiBSZWFjdC51c2VDYWxsYmFjayhpbnNlcnQkMSwgW3VwZGF0ZVZhbHVlcywgbmFtZSwgY29udHJvbF0pLFxuICAgICAgICB1cGRhdGU6IFJlYWN0LnVzZUNhbGxiYWNrKHVwZGF0ZSwgW3VwZGF0ZVZhbHVlcywgbmFtZSwgY29udHJvbF0pLFxuICAgICAgICByZXBsYWNlOiBSZWFjdC51c2VDYWxsYmFjayhyZXBsYWNlLCBbdXBkYXRlVmFsdWVzLCBuYW1lLCBjb250cm9sXSksXG4gICAgICAgIGZpZWxkczogUmVhY3QudXNlTWVtbygoKSA9PiBmaWVsZHMubWFwKChmaWVsZCwgaW5kZXgpID0+ICh7XG4gICAgICAgICAgICAuLi5maWVsZCxcbiAgICAgICAgICAgIFtrZXlOYW1lXTogaWRzLmN1cnJlbnRbaW5kZXhdIHx8IGdlbmVyYXRlSWQoKSxcbiAgICAgICAgfSkpLCBbZmllbGRzLCBrZXlOYW1lXSksXG4gICAgfTtcbn1cblxuLyoqXG4gKiBDdXN0b20gaG9vayB0byBtYW5hZ2UgdGhlIGVudGlyZSBmb3JtLlxuICpcbiAqIEByZW1hcmtzXG4gKiBbQVBJXShodHRwczovL3JlYWN0LWhvb2stZm9ybS5jb20vZG9jcy91c2Vmb3JtKSDigKIgW0RlbW9dKGh0dHBzOi8vY29kZXNhbmRib3guaW8vcy9yZWFjdC1ob29rLWZvcm0tZ2V0LXN0YXJ0ZWQtdHMtNWtzbW0pIOKAoiBbVmlkZW9dKGh0dHBzOi8vd3d3LnlvdXR1YmUuY29tL3dhdGNoP3Y9UmtYdjRBWFhDXzQpXG4gKlxuICogQHBhcmFtIHByb3BzIC0gZm9ybSBjb25maWd1cmF0aW9uIGFuZCB2YWxpZGF0aW9uIHBhcmFtZXRlcnMuXG4gKlxuICogQHJldHVybnMgbWV0aG9kcyAtIGluZGl2aWR1YWwgZnVuY3Rpb25zIHRvIG1hbmFnZSB0aGUgZm9ybSBzdGF0ZS4ge0BsaW5rIFVzZUZvcm1SZXR1cm59XG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHRzeFxuICogZnVuY3Rpb24gQXBwKCkge1xuICogICBjb25zdCB7IHJlZ2lzdGVyLCBoYW5kbGVTdWJtaXQsIHdhdGNoLCBmb3JtU3RhdGU6IHsgZXJyb3JzIH0gfSA9IHVzZUZvcm0oKTtcbiAqICAgY29uc3Qgb25TdWJtaXQgPSBkYXRhID0+IGNvbnNvbGUubG9nKGRhdGEpO1xuICpcbiAqICAgY29uc29sZS5sb2cod2F0Y2goXCJleGFtcGxlXCIpKTtcbiAqXG4gKiAgIHJldHVybiAoXG4gKiAgICAgPGZvcm0gb25TdWJtaXQ9e2hhbmRsZVN1Ym1pdChvblN1Ym1pdCl9PlxuICogICAgICAgPGlucHV0IGRlZmF1bHRWYWx1ZT1cInRlc3RcIiB7Li4ucmVnaXN0ZXIoXCJleGFtcGxlXCIpfSAvPlxuICogICAgICAgPGlucHV0IHsuLi5yZWdpc3RlcihcImV4YW1wbGVSZXF1aXJlZFwiLCB7IHJlcXVpcmVkOiB0cnVlIH0pfSAvPlxuICogICAgICAge2Vycm9ycy5leGFtcGxlUmVxdWlyZWQgJiYgPHNwYW4+VGhpcyBmaWVsZCBpcyByZXF1aXJlZDwvc3Bhbj59XG4gKiAgICAgICA8YnV0dG9uPlN1Ym1pdDwvYnV0dG9uPlxuICogICAgIDwvZm9ybT5cbiAqICAgKTtcbiAqIH1cbiAqIGBgYFxuICovXG5mdW5jdGlvbiB1c2VGb3JtKHByb3BzID0ge30pIHtcbiAgICBjb25zdCBfZm9ybUNvbnRyb2wgPSBSZWFjdC51c2VSZWYodW5kZWZpbmVkKTtcbiAgICBjb25zdCBfdmFsdWVzID0gUmVhY3QudXNlUmVmKHVuZGVmaW5lZCk7XG4gICAgY29uc3QgW2Zvcm1TdGF0ZSwgdXBkYXRlRm9ybVN0YXRlXSA9IFJlYWN0LnVzZVN0YXRlKHtcbiAgICAgICAgaXNEaXJ0eTogZmFsc2UsXG4gICAgICAgIGlzVmFsaWRhdGluZzogZmFsc2UsXG4gICAgICAgIGlzTG9hZGluZzogaXNGdW5jdGlvbihwcm9wcy5kZWZhdWx0VmFsdWVzKSxcbiAgICAgICAgaXNTdWJtaXR0ZWQ6IGZhbHNlLFxuICAgICAgICBpc1N1Ym1pdHRpbmc6IGZhbHNlLFxuICAgICAgICBpc1N1Ym1pdFN1Y2Nlc3NmdWw6IGZhbHNlLFxuICAgICAgICBpc1ZhbGlkOiBmYWxzZSxcbiAgICAgICAgc3VibWl0Q291bnQ6IDAsXG4gICAgICAgIGRpcnR5RmllbGRzOiB7fSxcbiAgICAgICAgdG91Y2hlZEZpZWxkczoge30sXG4gICAgICAgIHZhbGlkYXRpbmdGaWVsZHM6IHt9LFxuICAgICAgICBlcnJvcnM6IHByb3BzLmVycm9ycyB8fCB7fSxcbiAgICAgICAgZGlzYWJsZWQ6IHByb3BzLmRpc2FibGVkIHx8IGZhbHNlLFxuICAgICAgICBpc1JlYWR5OiBmYWxzZSxcbiAgICAgICAgZGVmYXVsdFZhbHVlczogaXNGdW5jdGlvbihwcm9wcy5kZWZhdWx0VmFsdWVzKVxuICAgICAgICAgICAgPyB1bmRlZmluZWRcbiAgICAgICAgICAgIDogcHJvcHMuZGVmYXVsdFZhbHVlcyxcbiAgICB9KTtcbiAgICBpZiAoIV9mb3JtQ29udHJvbC5jdXJyZW50KSB7XG4gICAgICAgIGlmIChwcm9wcy5mb3JtQ29udHJvbCkge1xuICAgICAgICAgICAgX2Zvcm1Db250cm9sLmN1cnJlbnQgPSB7XG4gICAgICAgICAgICAgICAgLi4ucHJvcHMuZm9ybUNvbnRyb2wsXG4gICAgICAgICAgICAgICAgZm9ybVN0YXRlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIGlmIChwcm9wcy5kZWZhdWx0VmFsdWVzICYmICFpc0Z1bmN0aW9uKHByb3BzLmRlZmF1bHRWYWx1ZXMpKSB7XG4gICAgICAgICAgICAgICAgcHJvcHMuZm9ybUNvbnRyb2wucmVzZXQocHJvcHMuZGVmYXVsdFZhbHVlcywgcHJvcHMucmVzZXRPcHRpb25zKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBlbHNlIHtcbiAgICAgICAgICAgIGNvbnN0IHsgZm9ybUNvbnRyb2wsIC4uLnJlc3QgfSA9IGNyZWF0ZUZvcm1Db250cm9sKHByb3BzKTtcbiAgICAgICAgICAgIF9mb3JtQ29udHJvbC5jdXJyZW50ID0ge1xuICAgICAgICAgICAgICAgIC4uLnJlc3QsXG4gICAgICAgICAgICAgICAgZm9ybVN0YXRlLFxuICAgICAgICAgICAgfTtcbiAgICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBjb250cm9sID0gX2Zvcm1Db250cm9sLmN1cnJlbnQuY29udHJvbDtcbiAgICBjb250cm9sLl9vcHRpb25zID0gcHJvcHM7XG4gICAgdXNlSXNvbW9ycGhpY0xheW91dEVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGNvbnN0IHN1YiA9IGNvbnRyb2wuX3N1YnNjcmliZSh7XG4gICAgICAgICAgICBmb3JtU3RhdGU6IGNvbnRyb2wuX3Byb3h5Rm9ybVN0YXRlLFxuICAgICAgICAgICAgY2FsbGJhY2s6ICgpID0+IHVwZGF0ZUZvcm1TdGF0ZSh7IC4uLmNvbnRyb2wuX2Zvcm1TdGF0ZSB9KSxcbiAgICAgICAgICAgIHJlUmVuZGVyUm9vdDogdHJ1ZSxcbiAgICAgICAgfSk7XG4gICAgICAgIHVwZGF0ZUZvcm1TdGF0ZSgoZGF0YSkgPT4gKHtcbiAgICAgICAgICAgIC4uLmRhdGEsXG4gICAgICAgICAgICBpc1JlYWR5OiB0cnVlLFxuICAgICAgICB9KSk7XG4gICAgICAgIGNvbnRyb2wuX2Zvcm1TdGF0ZS5pc1JlYWR5ID0gdHJ1ZTtcbiAgICAgICAgcmV0dXJuIHN1YjtcbiAgICB9LCBbY29udHJvbF0pO1xuICAgIFJlYWN0LnVzZUVmZmVjdCgoKSA9PiBjb250cm9sLl9kaXNhYmxlRm9ybShwcm9wcy5kaXNhYmxlZCksIFtjb250cm9sLCBwcm9wcy5kaXNhYmxlZF0pO1xuICAgIFJlYWN0LnVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIGlmIChwcm9wcy5tb2RlKSB7XG4gICAgICAgICAgICBjb250cm9sLl9vcHRpb25zLm1vZGUgPSBwcm9wcy5tb2RlO1xuICAgICAgICB9XG4gICAgICAgIGlmIChwcm9wcy5yZVZhbGlkYXRlTW9kZSkge1xuICAgICAgICAgICAgY29udHJvbC5fb3B0aW9ucy5yZVZhbGlkYXRlTW9kZSA9IHByb3BzLnJlVmFsaWRhdGVNb2RlO1xuICAgICAgICB9XG4gICAgfSwgW2NvbnRyb2wsIHByb3BzLm1vZGUsIHByb3BzLnJlVmFsaWRhdGVNb2RlXSk7XG4gICAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgaWYgKHByb3BzLmVycm9ycykge1xuICAgICAgICAgICAgY29udHJvbC5fc2V0RXJyb3JzKHByb3BzLmVycm9ycyk7XG4gICAgICAgICAgICBjb250cm9sLl9mb2N1c0Vycm9yKCk7XG4gICAgICAgIH1cbiAgICB9LCBbY29udHJvbCwgcHJvcHMuZXJyb3JzXSk7XG4gICAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgcHJvcHMuc2hvdWxkVW5yZWdpc3RlciAmJlxuICAgICAgICAgICAgY29udHJvbC5fc3ViamVjdHMuc3RhdGUubmV4dCh7XG4gICAgICAgICAgICAgICAgdmFsdWVzOiBjb250cm9sLl9nZXRXYXRjaCgpLFxuICAgICAgICAgICAgfSk7XG4gICAgfSwgW2NvbnRyb2wsIHByb3BzLnNob3VsZFVucmVnaXN0ZXJdKTtcbiAgICBSZWFjdC51c2VFZmZlY3QoKCkgPT4ge1xuICAgICAgICBpZiAoY29udHJvbC5fcHJveHlGb3JtU3RhdGUuaXNEaXJ0eSkge1xuICAgICAgICAgICAgY29uc3QgaXNEaXJ0eSA9IGNvbnRyb2wuX2dldERpcnR5KCk7XG4gICAgICAgICAgICBpZiAoaXNEaXJ0eSAhPT0gZm9ybVN0YXRlLmlzRGlydHkpIHtcbiAgICAgICAgICAgICAgICBjb250cm9sLl9zdWJqZWN0cy5zdGF0ZS5uZXh0KHtcbiAgICAgICAgICAgICAgICAgICAgaXNEaXJ0eSxcbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgIH0sIFtjb250cm9sLCBmb3JtU3RhdGUuaXNEaXJ0eV0pO1xuICAgIFJlYWN0LnVzZUVmZmVjdCgoKSA9PiB7XG4gICAgICAgIHZhciBfYTtcbiAgICAgICAgaWYgKHByb3BzLnZhbHVlcyAmJiAhZGVlcEVxdWFsKHByb3BzLnZhbHVlcywgX3ZhbHVlcy5jdXJyZW50KSkge1xuICAgICAgICAgICAgY29udHJvbC5fcmVzZXQocHJvcHMudmFsdWVzLCB7XG4gICAgICAgICAgICAgICAga2VlcEZpZWxkc1JlZjogdHJ1ZSxcbiAgICAgICAgICAgICAgICAuLi5jb250cm9sLl9vcHRpb25zLnJlc2V0T3B0aW9ucyxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgaWYgKCEoKF9hID0gY29udHJvbC5fb3B0aW9ucy5yZXNldE9wdGlvbnMpID09PSBudWxsIHx8IF9hID09PSB2b2lkIDAgPyB2b2lkIDAgOiBfYS5rZWVwSXNWYWxpZCkpIHtcbiAgICAgICAgICAgICAgICBjb250cm9sLl9zZXRWYWxpZCgpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgX3ZhbHVlcy5jdXJyZW50ID0gcHJvcHMudmFsdWVzO1xuICAgICAgICAgICAgdXBkYXRlRm9ybVN0YXRlKChzdGF0ZSkgPT4gKHsgLi4uc3RhdGUgfSkpO1xuICAgICAgICB9XG4gICAgICAgIGVsc2Uge1xuICAgICAgICAgICAgY29udHJvbC5fcmVzZXREZWZhdWx0VmFsdWVzKCk7XG4gICAgICAgIH1cbiAgICB9LCBbY29udHJvbCwgcHJvcHMudmFsdWVzXSk7XG4gICAgUmVhY3QudXNlRWZmZWN0KCgpID0+IHtcbiAgICAgICAgaWYgKCFjb250cm9sLl9zdGF0ZS5tb3VudCkge1xuICAgICAgICAgICAgY29udHJvbC5fc2V0VmFsaWQoKTtcbiAgICAgICAgICAgIGNvbnRyb2wuX3N0YXRlLm1vdW50ID0gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICBpZiAoY29udHJvbC5fc3RhdGUud2F0Y2gpIHtcbiAgICAgICAgICAgIGNvbnRyb2wuX3N0YXRlLndhdGNoID0gZmFsc2U7XG4gICAgICAgICAgICBjb250cm9sLl9zdWJqZWN0cy5zdGF0ZS5uZXh0KHsgLi4uY29udHJvbC5fZm9ybVN0YXRlIH0pO1xuICAgICAgICB9XG4gICAgICAgIGNvbnRyb2wuX3JlbW92ZVVubW91bnRlZCgpO1xuICAgIH0pO1xuICAgIF9mb3JtQ29udHJvbC5jdXJyZW50LmZvcm1TdGF0ZSA9IGdldFByb3h5Rm9ybVN0YXRlKGZvcm1TdGF0ZSwgY29udHJvbCk7XG4gICAgcmV0dXJuIF9mb3JtQ29udHJvbC5jdXJyZW50O1xufVxuXG4vKipcbiAqIFdhdGNoIGNvbXBvbmVudCB0aGF0IHN1YnNjcmliZXMgdG8gZm9ybSBmaWVsZCBjaGFuZ2VzIGFuZCByZS1yZW5kZXJzIHdoZW4gd2F0Y2hlZCBmaWVsZHMgdXBkYXRlLlxuICpcbiAqIEBwYXJhbSBjb250cm9sIC0gVGhlIGZvcm0gY29udHJvbCBvYmplY3QgZnJvbSB1c2VGb3JtXG4gKiBAcGFyYW0gbmFtZXMgLSBBcnJheSBvZiBmaWVsZCBuYW1lcyB0byB3YXRjaCBmb3IgY2hhbmdlc1xuICogQHBhcmFtIHJlbmRlciAtIFRoZSBmdW5jdGlvbiB0aGF0IHJlY2VpdmVzIHdhdGNoZWQgdmFsdWVzIGFuZCByZXR1cm5zIFJlYWN0Tm9kZVxuICogQHJldHVybnMgVGhlIHJlc3VsdCBvZiBjYWxsaW5nIHJlbmRlciBmdW5jdGlvbiB3aXRoIHdhdGNoZWQgdmFsdWVzXG4gKlxuICogQGV4YW1wbGVcbiAqIFRoZSBgV2F0Y2hgIGNvbXBvbmVudCBvbmx5IHJlLXJlbmRlciB3aGVuIHRoZSB2YWx1ZXMgb2YgYGZvb2AsIGBiYXJgLCBhbmQgYGJhei5xdXhgIGNoYW5nZS5cbiAqIFRoZSB0eXBlcyBvZiBgZm9vYCwgYGJhcmAsIGFuZCBgYmF6LnF1eGAgYXJlIHByZWNpc2VseSBpbmZlcnJlZC5cbiAqXG4gKiBgYGB0c3hcbiAqIGNvbnN0IHsgY29udHJvbCB9ID0gdXNlRm9ybSgpO1xuICpcbiAqIDxXYXRjaFxuICogICBjb250cm9sPXtjb250cm9sfVxuICogICBuYW1lcz17Wydmb28nLCAnYmFyJywgJ2Jhei5xdXgnXX1cbiAqICAgcmVuZGVyPXsoW2ZvbywgYmFyLCBiYXpfcXV4XSkgPT4gPGRpdj57Zm9vfXtiYXJ9e2Jhel9xdXh9PC9kaXY+fVxuICogLz5cbiAqIGBgYFxuICovXG5jb25zdCBXYXRjaCA9ICh7IGNvbnRyb2wsIG5hbWVzLCByZW5kZXIsIH0pID0+IHJlbmRlcih1c2VXYXRjaCh7IGNvbnRyb2wsIG5hbWU6IG5hbWVzIH0pKTtcblxuZXhwb3J0IHsgQ29udHJvbGxlciwgRm9ybSwgRm9ybVByb3ZpZGVyLCBXYXRjaCwgYXBwZW5kRXJyb3JzLCBjcmVhdGVGb3JtQ29udHJvbCwgZ2V0LCBzZXQsIHVzZUNvbnRyb2xsZXIsIHVzZUZpZWxkQXJyYXksIHVzZUZvcm0sIHVzZUZvcm1Db250ZXh0LCB1c2VGb3JtU3RhdGUsIHVzZVdhdGNoIH07XG4vLyMgc291cmNlTWFwcGluZ1VSTD1pbmRleC5lc20ubWpzLm1hcFxuIl0sIm5hbWVzIjpbXSwiaWdub3JlTGlzdCI6W10sInNvdXJjZVJvb3QiOiIifQ==